<template>
  <view class="page">
    <view class="bg-decoration"></view>

    <!-- 自定义 tabBar (仅抖音小程序) -->
    <!-- #ifdef MP-TOUTIAO -->
    <customTabBarToutiao />
    <!-- #endif -->

    <!-- [NEW] 全新左右布局布局容器 -->
    <view class="shop-layout">
      
      <!-- 左侧边栏 - 极致轻盈设计 -->
      <view class="sidebar glass-effect">
        <scroll-view scroll-y class="sidebar-scroll">
          <view class="sidebar-list">
            <view 
              class="sidebar-item" 
              :class="{ active: selectedCategoryId === 0 }"
              @tap="onCategorySelect(0)"
            >
              <view class="indicator" v-if="selectedCategoryId === 0"></view>
              <text class="item-text">全部</text>
            </view>
            <view 
              v-for="cat in categories" 
              :key="cat.id" 
              class="sidebar-item" 
              :class="{ active: selectedCategoryId === cat.id }"
              @tap="onCategorySelect(cat.id)"
            >
              <view class="indicator" v-if="selectedCategoryId === cat.id"></view>
              <text class="item-text">{{ cat.name }}</text>
            </view>
          </view>
        </scroll-view>
      </view>

      <!-- 右侧主内容区域 -->
      <view class="main-content">
        <!-- 顶部搜索浮层 -->
        <view class="top-nav glass-effect">
          <view class="search-wrap">
            <view class="search-bar">
              <text class="search-icon">🔍</text>
              <input class="search-input" v-model="keyword" placeholder="搜好物" @confirm="onSearchConfirm" />
              <view class="filter-btn" @tap="togglePriceFilter">
                <text class="filter-icon">🔽</text>
              </view>
            </view>
            <!-- 频道切换 (商品/优惠券) -->
            <view class="tab-pill">
              <view
                class="tab-pill-item"
                v-for="tab in tabs" :key="tab.id"
                :class="{ active: currentTab === tab.id }"
                @tap="switchTab(tab.id)"
              >
                {{ tab.name }}
              </view>
            </view>
          </view>
        </view>

        <!-- 价格区间筛选面板 (独立浮层) -->
        <view class="price-filter-panel" :class="{ expanded: showPriceFilter }">
          <view class="filter-row">
            <view class="price-input-group">
              <input class="price-input" v-model="priceMin" type="digit" placeholder="最低价" />
              <text class="price-separator">-</text>
              <input class="price-input" v-model="priceMax" type="digit" placeholder="最高价" />
            </view>
            <view class="filter-actions">
              <view class="filter-btn-reset" @tap="resetPriceFilter">重置</view>
              <view class="filter-btn-confirm" @tap="applyPriceFilter">确定</view>
            </view>
          </view>
          <!-- 快捷价格区间 -->
          <view class="quick-price-ranges">
            <view
              v-for="range in priceRanges"
              :key="range.key"
              class="price-range-tag"
              :class="{ active: isRangeActive(range.key) }"
              @tap="selectQuickPrice(range)"
            >
              {{ range.label }}
            </view>
          </view>
        </view>

        <!-- 内容滚动容器 (带缩放动画) -->
        <scroll-view 
          scroll-y 
          class="content-scroll-area"
          @scrolltolower="handleScrollToLower"
        >
          <view 
            class="transition-container" 
            :class="{ switching: isSwitching }"
            @animationend="onAnimationEnd"
          >
            <!-- 商品 Grid (保持原有逻辑，优化视觉) -->
            <view v-if="currentTab === 'product'" class="products-grid">
              <view class="product-item" v-for="p in items" :key="p.id" @tap="onProductTap(p)">
                <view class="product-card">
                  <view class="thumb-wrap">
                    <image class="product-thumb" :src="p.image" mode="aspectFill" lazy-load="true" />
                    <view class="stock-tag" v-if="p.stock !== null && p.stock < 10 && p.stock > 0">仅剩{{p.stock}}</view>
                    <view class="stock-tag out" v-else-if="p.stock === 0">售罄</view>
                  </view>
                  <view class="product-info">
                    <text class="product-title">{{ p.title }}</text>
                    <view class="product-bottom">
                      <view class="price-row">
                        <text class="points-val">{{ p.points }}</text>
                        <text class="points-unit">积分</text>
                      </view>
                      <view class="redeem-btn-sm" v-if="p.stock > 0" @tap.stop="onRedeemTap(p)">+</view>
                    </view>
                  </view>
                </view>
              </view>
            </view>

            <!-- 优惠券视图 -->
            <view v-else-if="currentTab === 'coupon'" class="coupons-compact-list">
              <view class="coupon-compact-card" v-for="c in items" :key="c.id">
                <view class="c-val-box">
                  <text class="c-val">¥{{ (c.discount_value || 0) / 100 }}</text>
                </view>
                <view class="c-info-box">
                  <text class="c-title">{{ c.title }}</text>
                  <text class="c-price">{{ c.points }} 积分</text>
                </view>
                <view class="c-btn" @tap="onRedeemTap(c)">兑换</view>
              </view>
            </view>

            <!-- 道具卡视图 (后期开放) -->
            <view v-else-if="currentTab === 'item_card'" class="item-cards-list">
              <view class="empty-state" style="padding-top: 50rpx;">
                 <image class="empty-img" src="/static/empty.png" mode="widthFix" />
                 <text class="empty-text">暂未开放</text>
              </view>
            </view>

            <view v-if="!items.length && !loading" class="empty-mini">
              <image class="empty-mini-img" src="/static/empty.png" mode="widthFix" />
              <text>空空如也</text>
            </view>

            <view v-if="loading" class="mini-loading">
              <view class="pulse"></view>
            </view>
          </view>
        </scroll-view>
      </view>
    </view>
  </view>
</template>

<script setup>
import { onShow, onReachBottom } from '@dcloudio/uni-app'
import { ref, watch, onUnmounted } from 'vue'
import { getStoreItems, redeemProductByPoints, redeemCouponByPoints, redeemItemCardByPoints, getProductCategories } from '../../api/appUser'
import { vibrateShort } from '@/utils/vibrate.js'
// #ifdef MP-TOUTIAO
import customTabBarToutiao from '@/components/app-tab-bar-toutiao.vue'
// #endif

// 由于是 setup 语法，组件会自动注册，无需手动声明

const loading = ref(false)
const keyword = ref('')
const currentTab = ref('product')
const items = ref([])
const allItems = ref([])
const page = ref(1)
const pageSize = 20
const hasMore = ref(true)

// 分类相关
const categories = ref([])
const selectedCategoryId = ref(0)

// 标记是否已经初始化加载过数据
let hasInitialized = false

// 趣味加载文字数组
const loadingTexts = [
  '请稍等，正在努力加载中。。。',
  '精彩马上就来，请稍候片刻～',
  '正在搜寻更多好物，别急哦～',
  '加载中，好东西值得等待～',
  '正在为您准备惊喜，马上就好～',
  '小憩一下，精彩内容即将呈现～',
  '努力加载中，比心❤️～',
  '正在赶来，马上就到～',
  '稍安勿躁，美好值得等待～',
  '加载进度99%... 开个玩笑😄'
]
const loadingText = ref(loadingTexts[0])
const isSwitching = ref(false)
let loadingTextInterval = null

// 开始切换加载文字
function startLoadingTextRotation() {
  if (loadingTextInterval) return
  let index = 0
  loadingText.value = loadingTexts[index]
  loadingTextInterval = setInterval(() => {
    index = (index + 1) % loadingTexts.length
    loadingText.value = loadingTexts[index]
  }, 2000) // 每2秒切换一次
}

// 停止切换加载文字
function stopLoadingTextRotation() {
  if (loadingTextInterval) {
    clearInterval(loadingTextInterval)
    loadingTextInterval = null
  }
}

// 监听 loading 状态，自动启停文字轮播
watch(loading, (newVal) => {
  if (newVal) {
    startLoadingTextRotation()
  } else {
    stopLoadingTextRotation()
  }
})

// 价格筛选相关
const priceMin = ref('')
const priceMax = ref('')
const showPriceFilter = ref(false)
const priceRanges = [
  { key: 'all', label: '全部', min: null, max: null },
  { key: '0-100', label: '0-100', min: 0, max: 100 },
  { key: '100-500', label: '100-500', min: 100, max: 500 },
  { key: '500-1000', label: '500-1K', min: 500, max: 1000 },
  { key: '1000-5000', label: '1K-5K', min: 1000, max: 5000 },
  { key: '5000+', label: '5K+', min: 5000, max: null }
]
const activePriceRange = ref('all')

const tabs = [
  { id: 'product', name: '商品' },
  { id: 'coupon', name: '优惠券' }
  // { id: 'item_card', name: '道具卡' } // 暂不开放
  // { id: 'item_card', name: '道具卡' } // 暂不开放
]

function cleanUrl(u) {
  const s = String(u || '').trim()
  const m = s.match(/https?:\/\/[^\s'"`]+/)
  if (m && m[0]) return m[0]
  return s.replace(/[`'\"]/g, '').trim()
}

function normalizeItems(list, kind) {
  if (!Array.isArray(list)) return []

  // 格式化积分显示 - 不四舍五入，保留两位小数
  const formatPoints = (value) => {
    if (value === undefined || value === null) return '0.00'
    const num = Number(value)
    if (isNaN(num)) return '0.00'

    // 价格字段单位是分，如 1250 = 12.50积分
    // 除以100得到显示值
    const finalValue = num / 100

    // 使用 Math.floor 避免四舍五入，保留两位小数
    return String(Math.floor(finalValue * 100) / 100).replace(/(\.\d)$/, '$10')
  }

  return list.map((i, idx) => ({
    id: i.id,
    kind: i.kind || kind,
    image: cleanUrl(i.main_image || i.image || ''),
    title: i.name || i.title || '',
    price: i.price || i.discount_value || 0,
    points: formatPoints(i.price || i.discount_value),
    stock: i.in_stock ? 99 : 0, // Simplified stock check if returned as bool
    discount_value: i.discount_value || 0,
    min_spend: i.min_spend || 0,
    description: i.description || ''
  })).filter(i => i.title)
}

function switchTab(id) {
  if (currentTab.value === id) return
  vibrateShort()
  currentTab.value = id
  triggerSwitching()
  items.value = []
  allItems.value = []
  page.value = 1
  hasMore.value = true
  loadItems()
}

function triggerSwitching() {
  isSwitching.value = true
}

function onAnimationEnd() {
  isSwitching.value = false
}

async function loadItems(append = false) {
  if (loading.value) return
  loading.value = true
  try {
    // 构建筛选参数
    const filters = {}
    if (keyword.value && keyword.value.trim()) {
      filters.keyword = keyword.value.trim()
    }
    if (priceMin.value !== '' && priceMin.value !== null) {
      filters.price_min = priceMin.value
    }
    if (priceMax.value !== '' && priceMax.value !== null) {
      filters.price_max = priceMax.value
    }
    // 添加分类筛选
    if (selectedCategoryId.value > 0) {
      filters.category_id = selectedCategoryId.value
    }
    
    const res = await getStoreItems(currentTab.value, page.value, pageSize, filters)
    const list = res.list || res || []
    const total = res.total || 0
    const newItems = normalizeItems(list, currentTab.value)

    if (append) {
      allItems.value = [...allItems.value, ...newItems]
    } else {
      allItems.value = newItems
    }

    // 直接使用服务端返回的数据（已经过筛选）
    items.value = allItems.value

    // 检查是否还有更多数据
    const totalPages = Math.ceil(total / pageSize)
    hasMore.value = page.value < totalPages
  } catch (e) {
    console.error(e)
    hasMore.value = false
  } finally {
    loading.value = false
  }
}

function applyFilters() {
  const k = String(keyword.value || '').trim().toLowerCase()
  const minPrice = priceMin.value !== '' ? parseFloat(priceMin.value) : null
  const maxPrice = priceMax.value !== '' ? parseFloat(priceMax.value) : null

  items.value = allItems.value.filter(item => {
    // 关键词筛选
    const title = String(item.title || '').toLowerCase()
    const matchKeyword = !k || title.includes(k)

    // 价格筛选
    const itemPrice = item.points || 0
    let matchPrice = true
    if (minPrice !== null) {
      matchPrice = matchPrice && itemPrice >= minPrice
    }
    if (maxPrice !== null) {
      matchPrice = matchPrice && itemPrice <= maxPrice
    }

    return matchKeyword && matchPrice
  })
}

function applyPriceFilter() {
  activePriceRange.value = 'custom'
  // 重新加载数据（服务端筛选）
  page.value = 1
  hasMore.value = true
  allItems.value = []
  loadItems()
  // 关闭筛选面板
  showPriceFilter.value = false
}

function resetPriceFilter() {
  priceMin.value = ''
  priceMax.value = ''
  activePriceRange.value = 'all'
  // 重新加载数据
  page.value = 1
  hasMore.value = true
  allItems.value = []
  loadItems()
  // 关闭筛选面板
  showPriceFilter.value = false
}

function selectQuickPrice(range) {
  vibrateShort()
  activePriceRange.value = range.key
  if (range.min !== null) {
    priceMin.value = range.min.toString()
  } else {
    priceMin.value = ''
  }
  if (range.max !== null) {
    priceMax.value = range.max.toString()
  } else {
    priceMax.value = ''
  }
  // 重新加载数据
  page.value = 1
  hasMore.value = true
  allItems.value = []
  loadItems()
  // 关闭筛选面板
  showPriceFilter.value = false
}

function isRangeActive(range) {
  return activePriceRange.value === range.key
}

// 切换价格筛选面板显示/隐藏
function togglePriceFilter() {
  vibrateShort()
  showPriceFilter.value = !showPriceFilter.value
}

function onSearchConfirm() {
  // 搜索时重新加载数据
  page.value = 1
  hasMore.value = true
  allItems.value = []
  loadItems()
}

function onProductTap(p) {
  if (p.kind === 'product') {
    uni.navigateTo({ url: `/pages-shop/shop/detail?id=${p.id}` })
  }
}

async function onRedeemTap(item) {
  // 检查商品库存
  if (item.kind === 'product' && item.stock === 0) {
    uni.showModal({
      title: '商品已售罄',
      content: '该商品库存不足，请联系客服处理',
      showCancel: false
    })
    return
  }
  const token = uni.getStorageSync('token')
  if (!token) {
    uni.showModal({
      title: '温馨提示',
      content: '兑换商品需要先登录哦',
      confirmText: '去登录',
      cancelText: '暂不登录',
      success: (res) => { if (res.confirm) uni.navigateTo({ url: '/pages/login/index' }) }
    })
    return
  }
  
  uni.showModal({
    title: '确认兑换',
    content: `是否消耗 ${item.points} 积分兑换 ${item.title}？`,
    success: async (res) => {
      if (res.confirm) {
        uni.showLoading({ title: '兑换中...' })
        try {
          const userId = uni.getStorageSync('user_id')
          if (!userId) throw new Error('用户ID不存在')
          
          if (item.kind === 'product') {
            await redeemProductByPoints(userId, item.id, 1)
          } else if (item.kind === 'coupon') {
            await redeemCouponByPoints(userId, item.id)
          } else if (item.kind === 'item_card') {
            await redeemItemCardByPoints(userId, item.id, 1)
          }
          
          uni.hideLoading()
          uni.showModal({
            title: '兑换成功',
            content: `您已成功兑换 ${item.title || item.name}`,
            showCancel: false,
            success: () => {
              loadItems()
            }
          })
        } catch (e) {
          uni.hideLoading()
          uni.showToast({ title: e.message || '兑换失败', icon: 'none' })
        }
      }
    }
  })
}

// 获取分类列表
async function fetchCategories() {
  try {
    const res = await getProductCategories()
    // 兼容可能存在的不同数据结构
    if (res && res.items) {
      categories.value = res.items
    } else if (Array.isArray(res)) {
      categories.value = res
    } else {
      categories.value = []
    }
  } catch (e) {
    console.error('获取分类失败:', e)
  }
}

// 选择分类
function onCategorySelect(id) {
  if (selectedCategoryId.value === id) return
  vibrateShort()
  selectedCategoryId.value = id
  triggerSwitching()
  page.value = 1
  hasMore.value = true
  items.value = []
  loadItems()
}

onShow(() => {
  // 只在首次加载时初始化数据，避免从详情页返回时重复加载
  if (!hasInitialized) {
    page.value = 1
    hasMore.value = true
    allItems.value = []
    loadItems()
    fetchCategories()
    hasInitialized = true
  }
})

onReachBottom(() => {
  // 触底加载更多（页面级，scroll-view 内不触发）
  handleScrollToLower()
})

// scroll-view 触底加载
function handleScrollToLower() {
  if (hasMore.value && !loading.value) {
    page.value++
    loadItems(true)
  }
}

watch(keyword, () => applyFilters())

// 组件卸载时清理定时器
onUnmounted(() => {
  stopLoadingTextRotation()
})

</script>

<style lang="scss" scoped>
.page {
  height: 100vh;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  padding-bottom: calc(120rpx + env(safe-area-inset-bottom));
  background-color: #f7f8fa;
  overflow: hidden;
}

.shop-layout {
  display: flex;
  flex: 1;
  min-height: 0;
  width: 100%;
}

.glass-effect {
  background: rgba(255, 255, 255, 0.7);
  backdrop-filter: blur(30rpx);
  -webkit-backdrop-filter: blur(30rpx);
}

/* 侧边栏 */
.sidebar {
  width: 160rpx;
  height: 100%;
  min-height: 0;
  overflow: hidden;
  border-right: 1rpx solid rgba(0, 0, 0, 0.05);
  z-index: 10;
}
.sidebar-scroll {
  height: 100%;
  min-height: 0;
}
.sidebar-list {
  padding: 40rpx 0 calc(140rpx + env(safe-area-inset-bottom));
}
.sidebar-item {
  height: 100rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
  
  .item-text {
    font-size: 26rpx;
    color: #666;
    transition: all 0.3s;
  }
  
  &.active {
    .item-text {
      color: $brand-primary;
      font-weight: 700;
      transform: scale(1.1);
    }
  }
}
.indicator {
  position: absolute;
  left: 0;
  width: 8rpx;
  height: 32rpx;
  background: $gradient-brand;
  border-radius: 0 4rpx 4rpx 0;
}

/* 主内容区 */
.main-content {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: #fff;
  position: relative;
  overflow: visible;
}

.top-nav {
  padding: 20rpx 24rpx;
  border-bottom: 1rpx solid rgba(0, 0, 0, 0.03);
  position: relative;
  z-index: 50;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(30rpx);
  -webkit-backdrop-filter: blur(30rpx);
  flex-shrink: 0;
}
.search-wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20rpx;
}
.search-bar {
  flex: 1;
  height: 64rpx;
  background: rgba(0, 0, 0, 0.04);
  border-radius: 32rpx;
  display: flex;
  align-items: center;
  padding: 0 24rpx;
}
.search-icon { font-size: 24rpx; opacity: 0.4; }
.search-input { flex: 1; margin-left: 12rpx; font-size: 24rpx; }

/* 筛选按钮 */
.filter-btn {
  margin-left: 12rpx;
  padding: 8rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}
.filter-icon {
  font-size: 20rpx;
  opacity: 0.5;
  transition: transform 0.3s;
}

/* 价格筛选面板 */
.price-filter-panel {
  position: absolute;
  top: 120rpx;
  left: 24rpx;
  right: 24rpx;
  padding: 20rpx;
  background: rgba(255, 255, 255, 0.98);
  border-radius: 20rpx;
  overflow: hidden;
  max-height: 0;
  opacity: 0;
  transition: all 0.3s ease-out;
  z-index: 100;
  box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.12);
  pointer-events: none;

  &.expanded {
    max-height: 500rpx;
    opacity: 1;
    pointer-events: auto;
  }
}

.filter-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16rpx;
  margin-bottom: 16rpx;
}

.price-input-group {
  flex: 1;
  display: flex;
  align-items: center;
  background: rgba(0, 0, 0, 0.03);
  border-radius: 12rpx;
  padding: 0 16rpx;
  height: 60rpx;
}

.price-input {
  flex: 1;
  height: 100%;
  font-size: 24rpx;
  text-align: center;
}

.price-separator {
  margin: 0 12rpx;
  color: #999;
  font-size: 24rpx;
}

.filter-actions {
  display: flex;
  gap: 12rpx;
}

.filter-btn-reset,
.filter-btn-confirm {
  padding: 12rpx 24rpx;
  border-radius: 12rpx;
  font-size: 24rpx;
  white-space: nowrap;
}

.filter-btn-reset {
  background: rgba(0, 0, 0, 0.05);
  color: #666;
}

.filter-btn-confirm {
  background: $gradient-brand;
  color: #fff;
}

/* 快捷价格区间 */
.quick-price-ranges {
  display: flex;
  flex-wrap: wrap;
  gap: 12rpx;
}

.price-range-tag {
  padding: 10rpx 20rpx;
  background: rgba(0, 0, 0, 0.04);
  border-radius: 20rpx;
  font-size: 22rpx;
  color: #666;
  transition: all 0.2s;

  &.active {
    background: $gradient-brand;
    color: #fff;
    transform: scale(1.05);
  }

  &:active {
    transform: scale(0.95);
  }
}

.tab-pill {
  display: flex;
  background: rgba(0, 0, 0, 0.03);
  padding: 4rpx;
  border-radius: 30rpx;
}
.tab-pill-item {
  padding: 8rpx 20rpx;
  font-size: 22rpx;
  color: #888;
  border-radius: 26rpx;
  &.active {
    background: #fff;
    color: #333;
    font-weight: 600;
    box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.05);
  }
}

.content-scroll-area {
  flex: 1;
  height: 0; /* 关键：在 flex 布局中需要设置为 0 才能正确计算高度 */
  background: #fcfcfc;
  overflow: hidden;
  position: relative;
  z-index: 1;
}

/* 缩放动画的核心部分 */
.transition-container {
  padding: 24rpx;
  min-height: 100%;
  &.switching {
    animation: zoomInOut 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  }
}

@keyframes zoomInOut {
  0% { transform: scale(1); opacity: 1; }
  45% { transform: scale(0.95); opacity: 0.7; }
  100% { transform: scale(1); opacity: 1; }
}

/* [NEW] 真正瀑布流布局 (Masonry) */
.products-grid {
  column-count: 2;
  column-gap: 20rpx;
  width: 100%;
}

.product-item {
  break-inside: avoid;
  margin-bottom: 20rpx;
  width: 100%;
}

.product-card {
  background: #fff;
  border-radius: 20rpx;
  overflow: hidden;
  box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.03);
  border: 1rpx solid rgba(0,0,0,0.02);
  transition: transform 0.2s;
  &:active {
    transform: scale(0.98);
  }
}

/* 创造高度落差感 */
.product-item:nth-child(2n) .thumb-wrap {
  padding-top: 120%; /* 偶数项更高，产生交错效果 */
}

.thumb-wrap {
  width: 100%;
  padding-top: 100%;
  position: relative;
  background: #fafafa;
  overflow: hidden;
}
.thumb-wrap .product-thumb {
  transition: opacity 0.3s;
}

/* 库存标签 */
.stock-tag {
  position: absolute;
  top: 8rpx;
  right: 8rpx;
  padding: 4rpx 12rpx;
  border-radius: 20rpx;
  font-size: 20rpx;
  color: #fff;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(4rpx);
  -webkit-backdrop-filter: blur(4rpx);
  z-index: 2;

  &.out {
    background: rgba(255, 59, 48, 0.9);
  }
}

.product-thumb { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
.product-info { padding: 16rpx; }
.product-title { 
  font-size: 24rpx; color: #333; line-height: 1.4; height: 2.8em; 
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.product-bottom { display: flex; align-items: center; justify-content: space-between; margin-top: 12rpx; }
.points-val { font-size: 28rpx; color: $brand-primary; font-weight: 700; }
.points-unit { font-size: 18rpx; color: $brand-primary; margin-left: 2rpx; }
.redeem-btn-sm {
  width: 44rpx; height: 44rpx; background: $gradient-brand; 
  color: #fff; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 28rpx;
}

/* 紧凑型优惠券列表 */
.coupons-compact-list { display: flex; flex-direction: column; gap: 20rpx; }
.coupon-compact-card {
  background: #fff; border-radius: 16rpx; padding: 24rpx;
  display: flex; align-items: center; border: 1rpx solid rgba(0,0,0,0.03);
}
.c-val-box { width: 100rpx; font-weight: 800; color: #FF6B6B; }
.c-info-box { flex: 1; }
.c-title { display: block; font-size: 24rpx; font-weight: 600; color: #333; }
.c-price { font-size: 20rpx; color: #999; }
.c-btn { background: #333; color: #fff; font-size: 22rpx; padding: 6rpx 20rpx; border-radius: 10rpx; }

.empty-mini {
  padding-top: 100rpx;
  text-align: center;
  color: #ccc;
  font-size: 24rpx;
}
.empty-mini-img {
  width: 160rpx;
  display: block;
  margin: 0 auto 10rpx;
}
.mini-loading { padding-top: 60rpx; display: flex; justify-content: center; }
.pulse { width: 40rpx; height: 40rpx; background: $brand-primary; border-radius: 50%; opacity: 0.3; animation: pulse 1s infinite; }
@keyframes pulse { from { transform: scale(1); opacity: 0.3; } to { transform: scale(2); opacity: 0; } }

.no-more {
  text-align: center;
  padding: 40rpx 0;
  color: $text-tertiary;
  opacity: 0.6;
}

</style>
