<template>
  <view class="action-bar" :style="{ paddingBottom: safeAreaBottom + 'px' }">
    <!-- 钻石消耗确认弹窗 -->
    <DiamondConfirmModal :visible="confirmModal.visible" :itemLabel="confirmModal.itemLabel"
      :itemCost="confirmModal.itemCost" @confirm="handleModalConfirm" @cancel="handleModalCancel" />
    <!-- 主容器 -->
    <view class="bar-container">
      <!-- 用户信息区域 -->
      <view class="user-info">
        <image :src="userInfo?.avatar_url || '/static/icon/avatar-default.png'" class="user-avatar" mode="aspectFill" />
        <view class="user-balance">
          <image src="/static/icon/crystal.png" class="balance-icon" mode="aspectFit" />
          <text class="balance-text">{{ userInfo?.crystal_balance || 0 }}</text>
        </view>
      </view>

      <view class="items-row">
        <view v-for="item in items" :key="item.type" class="action-item" :class="{ active: selectedItem === item.type }"
          @click="handleItemSelect(item)">
          <!-- 选中状态的背景 -->
          <image v-if="selectedItem === item.type" src="/static/rank/activity-support-icon/djbeij.jpg" class="item-bg"
            mode="aspectFill" />

          <!-- 图标区域：添加白色背景和阴影 -->
          <view class="icon-wrapper">
            <image :src="item.icon" class="item-icon" mode="aspectFill" lazy-load />
          </view>

          <!-- 名称区域 -->
          <view class="name-wrapper">
            <text class="item-name">{{ item.name || item.label }}</text>
          </view>

          <!-- 价格区域：钻石图标 + 数字 -->
          <view class="cost-wrapper">
            <image src="/static/icon/crystal.png" class="diamond-icon" mode="aspectFit" lazy-load />
            <text class="item-cost">{{ item.cost }}</text>
          </view>

          <!-- 选中状态显示"点击赠送" -->
          <view v-if="selectedItem === item.type" class="gift-text"
            @click="(e) => { e.stopPropagation(); handleDirectContribute(item) }">点击赠送</view>

          <!-- 每个道具独立的反馈动画 -->
          <view v-if="feedbackItem === item.type" class="feedback-layer">
            <view class="feedback-icon" :style="{ color: itemFeedbackColor(item.type) }">+1</view>
          </view>
        </view>
      </view>

      <!-- 数量选择器和确认按钮 -->
      <view class="quantity-control">
        <view class="quantity-selector">
          <view class="quantity-btn minus" @click.stop="decreaseQuantity">-</view>
          <input type="number" v-model="quantity" class="quantity-input" />
          <view class="quantity-btn plus" @click.stop="increaseQuantity">+</view>
        </view>
        <view class="confirm-btn" @click.stop="handleConfirmContribute">
          <text>确认赠送</text>
        </view>
      </view>
    </view>

    <!-- 重试按钮 (当有失败操作时显示) -->
    <view v-if="hasFailedActions" class="retry-banner" @click="retryFailedActions">
      <text class="retry-text">有操作失败，点击重试</text>
    </view>

    <!-- 自定义结果提示（替代系统 toast/modal，避免截断） -->
    <view v-show="resultToast.visible" class="result-toast" :class="{ 'result-toast--visible': resultToast.visible }">
      <text class="result-toast-icon">{{ resultToast.icon }}</text>
      <text class="result-toast-text">{{ resultToast.text }}</text>
    </view>
  </view>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue'
import { purchaseItem } from '@/utils/activity-config'
import DiamondConfirmModal from './DiamondConfirmModal.vue'

const props = defineProps({
  activityId: {
    type: String,
    required: true
  },
  actionItems: {
    type: Array,
    default: () => [
      { type: 'firework', label: '烟花', icon: '/static/rank/spark.png', cost: 1 },
      { type: 'megaphone', label: '喇叭', icon: '/static/icon/task.png', cost: 5 },
      { type: 'love', label: 'LOVE', icon: '/static/icon/castlove.png', cost: 10 }
    ]
  }
})

const emit = defineEmits(['contribute'])

// 动态响应父组件传入的道具配置
const items = computed(() => props.actionItems)

const safeAreaBottom = ref(0)
const feedbackItem = ref(null) // 当前触发反馈动画的道具 type
const selectedItem = ref(null) // 当前选中的道具
const quantity = ref(1) // 赠送数量
const isContributing = ref(false) // 正在贡献中，防止状态被清除

// 按索引分配颜色，不依赖后端 type 字符串
const FEEDBACK_COLORS = ['#FFD700', '#00CFFF', '#FF6B9D', '#A78BFA', '#34D399']

function itemFeedbackColor(type) {
  const idx = items.value.findIndex(i => i.type === type)
  return FEEDBACK_COLORS[idx >= 0 ? idx % FEEDBACK_COLORS.length : 0]
}
const pendingActions = ref([])
const hasFailedActions = ref(false)
const isOnline = ref(true)
const processingItems = new Set()  // 防止重复点击
const resultToast = ref({ visible: false, icon: '', text: '' })
let resultToastTimer = null

function showResultToast(icon, text) {
  if (resultToastTimer) clearTimeout(resultToastTimer)
  resultToast.value = { visible: true, icon, text }
  resultToastTimer = setTimeout(() => {
    resultToast.value.visible = false
  }, 3000)
}

// 自定义确认弹窗状态
const confirmModal = ref({ visible: false, itemLabel: '', itemCost: 0 })
let confirmResolve = null

function showConfirmModal(item) {
  confirmModal.value = { visible: true, itemLabel: item.label, itemCost: item.cost }
  return new Promise((resolve) => { confirmResolve = resolve })
}

function handleModalConfirm() {
  confirmModal.value.visible = false
  confirmResolve?.(true)
}

function handleModalCancel() {
  confirmModal.value.visible = false
  confirmResolve?.(false)
}

const userInfo = ref(null);

function loadUserInfo() {
  try {
    const userStr = uni.getStorageSync('user')
    if (userStr) {
      userInfo.value = typeof userStr === 'string' ? JSON.parse(userStr) : userStr
    }
  } catch (error) {
    console.error('加载用户信息失败:', error)
  }
}

// 网络状态监听
let networkListener = null
let syncDebounceTimer = null

function debouncedSync() {
  if (syncDebounceTimer) clearTimeout(syncDebounceTimer)
  if (resultToastTimer) clearTimeout(resultToastTimer)
  syncDebounceTimer = setTimeout(() => {
    syncDebounceTimer = null
    syncPendingActions()
  }, 1000)
}

onMounted(() => {
  // 获取安全区域信息
  const systemInfo = uni.getSystemInfoSync()
  safeAreaBottom.value = systemInfo.safeAreaInsets?.bottom || 0

  // 加载用户信息
  loadUserInfo()

  // 恢复离线队列
  loadPendingActions()

  // 监听网络状态
  networkListener = uni.onNetworkStatusChange((res) => {
    const wasOffline = !isOnline.value
    isOnline.value = res.isConnected

    // 如果从离线恢复到在线，自动同步（防抖避免网络抖动重复触发）
    if (wasOffline && isOnline.value && pendingActions.value.length > 0) {
      debouncedSync()
    }
  })

  // 检查当前网络状态
  uni.getNetworkType({
    success: (res) => {
      isOnline.value = res.networkType !== 'none'
    }
  })

  // 监听余额更新事件
  uni.$on('balanceUpdated', (data) => {
    if (userInfo.value) {
      userInfo.value.crystal_balance = data.crystal_balance
    }
  })
})

onUnmounted(() => {
  if (networkListener) uni.offNetworkStatusChange(networkListener)
  if (syncDebounceTimer) clearTimeout(syncDebounceTimer)
  if (resultToastTimer) clearTimeout(resultToastTimer)
  uni.$off('balanceUpdated')
})

// 存储键前缀
const STORAGE_PREFIX = 'topfans_'

// 加载离线队列
async function loadPendingActions() {
  try {
    // 先检查 key 是否存在
    const info = uni.getStorageInfoSync()
    const key = `${STORAGE_PREFIX}pending_actions_${props.activityId}`

    if (!info.keys.includes(key)) {
      return // key 不存在，直接返回
    }

    const cached = await uni.getStorage({
      key: `${STORAGE_PREFIX}pending_actions_${props.activityId}`
    })

    if (cached && cached[1]?.data && Array.isArray(cached[1].data)) {
      pendingActions.value = cached[1].data
      hasFailedActions.value = cached[1].data.length > 0

      // 如果在线，尝试同步
      if (isOnline.value && cached[1].data.length > 0) {
        syncPendingActions()
      }
    }
  } catch (error) {
    console.error('加载离线队列失败:', error)
  }
}

// 保存离线队列
async function savePendingActions() {
  try {
    await uni.setStorage({
      key: `${STORAGE_PREFIX}pending_actions_${props.activityId}`,
      data: pendingActions.value
    })
    hasFailedActions.value = pendingActions.value.length > 0
  } catch (error) {
    console.error('保存离线队列失败:', error)
  }
}

// 处理道具选择（第一次点击）
function handleItemSelect(item) {
  selectedItem.value = item.type
  quantity.value = 1
  isContributing.value = false
}

// 增加数量
function increaseQuantity() {
  quantity.value++
}

// 减少数量
function decreaseQuantity() {
  if (quantity.value > 1) {
    quantity.value--
  }
}

// 处理直接贡献（点击"点击赠送"，不需要确认）
async function handleDirectContribute(item) {
  // 防止同一道具重复点击
  if (processingItems.has(item.type) || isContributing.value) return
  processingItems.add(item.type)
  isContributing.value = true

  try {
    // 验证余额
    const hasBalance = await validateBalance(item.cost)
    if (!hasBalance) {
      showResultToast('', '余额不足')
      // 余额不足时直接返回，不调用API
      return
    }

    // 直接调用贡献API
    const success = await contributeItem(item)
    if (!success) {
      // 贡献失败时不显示额外提示，由 contributeItem 内部处理
      return
    }
  } finally {
    processingItems.delete(item.type)
    isContributing.value = false
  }
}

// 处理确认贡献（点击"确认赠送"）
async function handleConfirmContribute() {
  const item = items.value.find(i => i.type === selectedItem.value)
  if (!item || isContributing.value) return

  // 防止同一道具重复点击
  if (processingItems.has(item.type)) return
  processingItems.add(item.type)
  isContributing.value = true

  try {
    // 验证余额（乘以数量）
    const totalCost = item.cost * quantity.value
    const hasBalance = await validateBalance(totalCost)
    if (!hasBalance) {
      showResultToast('', '余额不足')
      return
    }

    // 弹出确认框
    const confirmed = await showConfirmModal({ ...item, cost: totalCost })
    if (!confirmed) {
      return
    }

    // 调用贡献API多次
    let successCount = 0
    let lastRemainingBalance = null
    let lastErrorMessage = ''
    for (let i = 0; i < quantity.value; i++) {
      const res = await contributeItem(item, true, true)
      console.log(`第${i+1}次调用返回值:`, res)
      if (res && res.success !== false) {
        successCount++
        lastRemainingBalance = res.remainingBalance
      } else {
        lastErrorMessage = res?.message || '活动不在进行中，无法购买'
      }
    }

    // 更新本地余额（使用最后一次成功的余额）
    if (lastRemainingBalance !== null) {
      await updateLocalBalanceFromResult(lastRemainingBalance)
    }

    // 显示自定义结果提示
    if (successCount === quantity.value) {
      showResultToast('✅', `贡献成功\n+${item.cost * successCount} 贡献值已到账`)
    } else if (successCount > 0) {
      showResultToast('⚠️', `部分成功 ${successCount}/${quantity.value}`)
    } else {
      showResultToast('❌', lastErrorMessage || '贡献失败')
    }
  } finally {
    processingItems.delete(item.type)
    isContributing.value = false
  }
}

// 验证用户余额（优先用缓存，避免重复读取存储）
async function validateBalance(cost) {
  try {
    if (!userInfo.value) {
      const userStr = uni.getStorageSync('user')
      if (userStr) {
        userInfo.value = typeof userStr === 'string' ? JSON.parse(userStr) : { ...userStr }
      }
    }
    const balance = Number(userInfo.value?.crystal_balance) || 0
    return balance >= cost
  } catch (error) {
    console.error('验证余额失败:', error)
    return false
  }
}

// 贡献道具
async function contributeItem(item, isRetry = false, silent = false) {
  try {
    // 使用 activity-config.js 中的 purchaseItem 函数
    const result = await purchaseItem(props.activityId, item.type, 1)
    console.log(`[contributeItem] result:`, result, 'isRetry:', isRetry, 'silent:', silent)

    // 检查购买结果
    if (!result.success) {
      const msg = result.message || '活动不在进行中，无法购买'
      if (!silent) showResultToast('', msg)
      return { success: false, message: msg }
    }

    // 成功：触发反馈动画（重试时静默，不触发）
    if (!isRetry && !silent) {
      feedbackItem.value = item.type
      setTimeout(() => { feedbackItem.value = null }, 800)
    }

    // 更新本地用户余额：非重试时直接用服务端余额；重试时由 syncPendingActions 统一处理
    if (!isRetry && !silent) {
      await updateLocalBalanceFromResult(result.remainingBalance)
    }

    // 通知父组件更新进度（使用返回的当前进度）
    emit('contribute', item.type, result.currentProgress)

    // 如果是重试成功或静默模式，不单独弹 toast
    if (!isRetry && !silent) {
      showResultToast('✅', `贡献值 +${result.totalContribution}`)
    }

    // 重试时返回完整结果供 syncPendingActions 汇总；正常时返回 true
    return isRetry ? { contribution: result.totalContribution, remainingBalance: result.remainingBalance, success: true } : { success: true }
  } catch (error) {
    console.error('贡献失败:', error)

    // 如果不是重试操作，先乐观扣除本地余额再入队
    if (!isRetry && !silent) {
      deductLocalBalance(item.cost)
      const queued = addToPendingQueue(item)
      if (!queued) {
        // 队列已满，退还刚扣除的余额
        refundLocalBalance(item.cost)
        return { success: false, message: '网络异常，已加入队列' }
      }
      return { success: false, message: '网络异常，已加入队列' }
    }

    return { success: false, message: error.message || '贡献失败' }
  }
}

// 添加到离线队列（上限 10 个）
const QUEUE_LIMIT = 10

function addToPendingQueue(item) {
  if (pendingActions.value.length >= QUEUE_LIMIT) {
    showResultToast('⚠️', '离线队列已满\n请联网后再操作')
    return false
  }
  const action = {
    type: item.type,
    cost: item.cost,
    label: item.label,
    icon: item.icon,
    timestamp: Date.now(),
    retryCount: 0
  }
  pendingActions.value.push(action)
  savePendingActions()
  return true
}

// 乐观扣除本地余额（离线入队时使用）
function deductLocalBalance(cost) {
  try {
    const userStr = uni.getStorageSync('user')
    if (userStr) {
      // 确保正确解析用户对象
      let user
      if (typeof userStr === 'string') {
        user = JSON.parse(userStr)
      } else {
        user = { ...userStr }
      }

      // 扣除余额，确保不为负数
      user.crystal_balance = Math.max(0, (Number(user.crystal_balance) || 0) - cost)

      // 保存回存储
      uni.setStorageSync('user', JSON.stringify(user))
      userInfo.value = user
      uni.$emit('balanceUpdated', { crystal_balance: user.crystal_balance })
    }
  } catch (error) {
    console.error('扣除本地余额失败:', error)
  }
}

// 退还本地余额（同步彻底失败时使用）
function refundLocalBalance(cost) {
  try {
    const userStr = uni.getStorageSync('user')
    if (userStr) {
      // 确保正确解析用户对象
      let user
      if (typeof userStr === 'string') {
        user = JSON.parse(userStr)
      } else {
        user = { ...userStr }
      }

      // 退还余额
      user.crystal_balance = (Number(user.crystal_balance) || 0) + cost

      // 保存回存储
      uni.setStorageSync('user', JSON.stringify(user))
      userInfo.value = user
      uni.$emit('balanceUpdated', { crystal_balance: user.crystal_balance })
    }
  } catch (error) {
    console.error('退还本地余额失败:', error)
  }
}
async function updateLocalBalanceFromResult(newBalance) {
  try {
    const userStr = uni.getStorageSync('user')
    if (userStr) {
      // 确保正确解析用户对象
      let user
      if (typeof userStr === 'string') {
        user = JSON.parse(userStr)
      } else {
        // 如果已经是对象，创建一个新副本避免引用问题
        user = { ...userStr }
      }

      // 更新余额，确保是数字类型
      user.crystal_balance = Number(newBalance) || 0

      // 保存回存储，确保是字符串格式
      uni.setStorageSync('user', JSON.stringify(user))
      userInfo.value = user
      uni.$emit('balanceUpdated', { crystal_balance: user.crystal_balance })
    }
  } catch (error) {
    console.error('更新本地余额失败:', error)
  }
}

// 同步离线队列
async function syncPendingActions() {
  if (pendingActions.value.length === 0) {
    return
  }

  uni.showLoading({
    title: '同步中...',
    mask: true
  })

  const actions = [...pendingActions.value]
  const failedActions = []
  const CONCURRENCY = 3
  let totalContribution = 0
  let minRemainingBalance = Infinity  // 并发时取最小余额，避免覆盖问题

  try {
    // 分批并发执行，每批最多 CONCURRENCY 个
    for (let i = 0; i < actions.length; i += CONCURRENCY) {
      const batch = actions.slice(i, i + CONCURRENCY)
      const results = await Promise.all(batch.map(async (action) => {
        if (action.retryCount >= 3) {
          // 重试超限，退还之前乐观扣除的余额
          refundLocalBalance(action.cost)
          return { action, contribution: 0, remainingBalance: null, success: false }
        }
        action.retryCount = (action.retryCount || 0) + 1
        const item = { type: action.type, cost: action.cost, label: action.label, icon: action.icon }
        const res = await contributeItem(item, true)
        const success = res !== false && res !== null
        return {
          action,
          contribution: success ? res.contribution : 0,
          remainingBalance: success ? res.remainingBalance : null,
          success
        }
      }))
      results.forEach(({ action, contribution, remainingBalance, success }) => {
        if (success) {
          totalContribution += contribution
          if (remainingBalance !== null && remainingBalance < minRemainingBalance) {
            minRemainingBalance = remainingBalance
          }
        } else {
          failedActions.push(action)
        }
      })
    }
  } finally {
    uni.hideLoading()
    // 批次全部完成后，用最小余额做一次写入，避免并发覆盖
    if (minRemainingBalance !== Infinity) {
      await updateLocalBalanceFromResult(minRemainingBalance)
    }
  }

  // 更新队列
  pendingActions.value = failedActions
  savePendingActions()

  // 显示结果（自定义 toast，完全控制尺寸避免系统截断）
  const successCount = actions.length - failedActions.length
  if (successCount > 0 && failedActions.length === 0) {
    showResultToast('✅', `贡献成功\n+${totalContribution} 贡献值已到账`)
  } else if (successCount > 0 && failedActions.length > 0) {
    showResultToast('⚠️', `成功 ${successCount} 个，+${totalContribution} 贡献值\n失败 ${failedActions.length} 个，可点击重试`)
  } else {
    showResultToast('❌', '贡献失败\n钻石已退还')
  }
}

// 手动重试失败操作
function retryFailedActions() {
  syncPendingActions()
}

// 暴露方法供父组件调用
defineExpose({
  syncPendingActions,
  getPendingActionsCount: () => pendingActions.value.length
})
</script>

<style scoped>
/* 整体定位 */
.action-bar {
  width: 100%;
  min-height: 13rem;
  display: flex;
  justify-content: center;
}

/* 核心容器：模仿图中的粉色渐变长条 */
.bar-container {
  width: 100%;
  background-image: url('@/static/rank/activity-support-icon/beijingkuang.png');
  background-size: 105% 130%;
  background-position: center;
  border-radius: 40rpx 40rpx 0 0;
  padding: 20rpx 40rpx;
  display: flex;
  flex-direction: column;
  gap: 24rpx;
}

/* 用户信息区域 */
.user-info {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16rpx;
  padding-bottom: 16rpx;
  border-bottom: 1rpx solid rgba(255, 255, 255, 0.3);
}

.user-avatar {
  width: 80rpx;
  height: 80rpx;
  border-radius: 50%;
  border: 3rpx solid #fff;
}

.user-balance {
  display: flex;
  align-items: center;
  gap: 8rpx;
  /* background: rgba(0, 0, 0, 0.2); */
  padding: 8rpx 20rpx;
  background: linear-gradient(to bottom right,
			#F0E4B1 0%,
			#F08399 50%,
			#B94E73 100%);
	border-radius: 24rpx;
	box-shadow:
		0 4rpx 12rpx rgba(255, 143, 158, 0.2),
		inset 0 2rpx 4rpx rgba(255, 255, 255, 0.4);
  border-radius: 30rpx;
}

.balance-icon {
  width: 40rpx;
  height: 40rpx;
}

.balance-text {
  font-size: 28rpx;
  color: #fff;
  font-weight: bold;
}

/* 道具行容器 */
.items-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16rpx;
  padding: 16rpx 0;
}

.action-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  position: relative;
  cursor: pointer;
  padding: 16rpx;
  border-radius: 20rpx;
}

/* 选中状态 */
.action-item.active .icon-wrapper,
.action-item.active .name-wrapper,
.action-item.active .cost-wrapper {
  opacity: 0.6;
}

/* 选中背景 */
.item-bg {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
}

.gift-text {
  font-size: 22rpx;
  color: #fff;
  white-space: nowrap;
  text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.3);
  background: linear-gradient(to bottom right,
      #F0E4B1 0%,
      #F08399 50%,
      #B94E73 100%);
  border-radius: 24rpx;
  padding: 6rpx 16rpx;
  margin-top: 8rpx;
  box-shadow:
    0 4rpx 12rpx rgba(255, 143, 158, 0.2),
    inset 0 2rpx 4rpx rgba(255, 255, 255, 0.4);
  position: relative;
}

/* 数量选择器和确认按钮 */
.quantity-control {
  display: flex;
  align-items: center;
  /* justify-content: center; */
  gap: 24rpx;
  padding-top: 24rpx;
  border-top: 1rpx solid rgba(255, 255, 255, 0.3);
}

.quantity-selector {
  display: flex;
  align-items: center;
  gap: 16rpx;
  background: rgba(0, 0, 0, 0.2);
  border-radius: 40rpx;
  padding: 8rpx 16rpx;
}

.quantity-btn {
  width: 48rpx;
  height: 48rpx;
  border-radius: 50%;
  background: linear-gradient(to bottom right, #F0E4B1 0%, #F08399 50%, #B94E73 100%);
  color: #fff;
  font-size: 32rpx;
  font-weight: bold;
  display: flex;
  align-items: center;
  justify-content: center;
}

.quantity-input {
  width: 60rpx;
  text-align: center;
  font-size: 28rpx;
  color: #fff;
  background: transparent;
}

.confirm-btn {
  background-image: url('@/static/rank/activity-support-icon/beijingkuang.png');
  background-size: cover;
  background-position: center;
  border-radius: 40rpx;
  padding: 16rpx 40rpx;
  box-shadow: 0 4rpx 12rpx rgba(255, 143, 158, 0.3);
}

.confirm-btn text {
  font-size: 28rpx;
  color: #fff;
  font-weight: bold;
  text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.3);
}

/* 图标包装器 */
.icon-wrapper {
  width: 112rpx;
  height: 112rpx;
  display: flex;
  justify-content: center;
  align-items: center;
  margin-bottom: 8rpx;
  overflow: hidden;
}

.item-icon {
  width: 100%;
  height: 100%;
}

/* 名称包装器 */
.name-wrapper {
  margin-bottom: 4rpx;
}

.item-name {
  font-size: 22rpx;
  color: #fff;
  text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.3);
  text-align: center;
}

/* 价格包装器：横向排列钻石和数字 */
.cost-wrapper {
  display: flex;
  align-items: center;
  gap: 4rpx;
}

/* 钻石图标样式 */
.diamond-icon {
  width: 40rpx;
  height: 40rpx;
}

.item-cost {
  font-size: 24rpx;
  color: #fff;
  /* 橙色，接近图中 LISA 的颜色 */
  text-shadow:
    0 3rpx 6rpx rgba(0, 0, 0, 0.4),
    0 1rpx 3rpx rgba(0, 0, 0, 0.3);
  font-family: 'yt', sans-serif;
}

/* --- 以下保持原有逻辑样式 --- */

.feedback-layer {
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  pointer-events: none;
  z-index: 10;
}

.feedback-icon {
  font-size: 60rpx;
  color: #ff6b9d;
  font-weight: bold;
  animation: feedback-pop 1s ease-out;
}

.retry-banner {
  position: absolute;
  top: -80rpx;
  /* 调整位置以免遮挡渐变条 */
  left: 50%;
  transform: translateX(-50%);
  background: rgba(255, 107, 157, 0.9);
  padding: 10rpx 30rpx;
  border-radius: 30rpx;
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.2);
  cursor: pointer;
  white-space: nowrap;
}

.retry-text {
  font-size: 24rpx;
  color: #fff;
  font-weight: 500;
}

@keyframes feedback-pop {
  0% {
    opacity: 0;
    transform: scale(0.5) translateY(0);
  }

  50% {
    opacity: 1;
    transform: scale(1.2) translateY(-40rpx);
  }

  100% {
    opacity: 0;
    transform: scale(1) translateY(-80rpx);
  }
}

.result-toast {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 9999;
  background: rgba(0, 0, 0, 0.75);
  border-radius: 20rpx;
  padding: 40rpx 48rpx;
  min-width: 320rpx;
  max-width: 560rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16rpx;
  opacity: 0;
  transition: opacity 0.3s ease;
  pointer-events: none;
}

.result-toast--visible {
  opacity: 1;
  pointer-events: auto;
}

.result-toast-icon {
  font-size: 56rpx;
  line-height: 1;
}

.result-toast-text {
  font-size: 28rpx;
  color: #fff;
  text-align: center;
  line-height: 1.6;
  white-space: pre-line;
}
</style>