<script lang="ts" setup xmlns="http://www.w3.org/1999/html">
/**
 * 翻牌抽奖活动组件
 * 功能说明：
 * 1. 用户每周有10次翻牌机会，前7次为基础免费次数
 * 2. 第8-10次需要使用邀请码解锁（邀请好友使用自己的邀请码）
 * 3. 翻牌有中奖和不中奖两种结果，中奖可获得Token奖励
 * 4. 幸运值随着翻牌次数增加，每次增加12%
 * 5. 第9次中奖会触发翻倍提示，第10次奖励翻倍
 */
import type { CardFlipRecord, CardFlipStatusOutput, FlipCardOutput } from '@/api/cardFlip/types';
import { ElMessage, ElMessageBox } from 'element-plus';
import { onMounted, ref, watch } from 'vue';
import { flipCard, generateMyInviteCode, getWeeklyTaskStatus, useInviteCode } from '@/api/cardFlip';

// ============ Props ============
/** 接收外部传入的邀请码（通过 URL 参数传递） */
const props = defineProps<{
  externalInviteCode?: string;
}>();

// ============ 状态管理 ============
/** 任务数据：包含翻牌记录、次数统计、邀请码等信息 */
const taskData = ref<CardFlipStatusOutput | null>(null);

/** 操作加载状态：用于使用邀请码、生成邀请码等操作时显示loading */
const loading = ref(false);

/** 初始加载状态：用于页面首次加载时显示骨架屏，避免白屏闪烁 */
const initialLoading = ref(true);

/** 正在翻牌状态：标记是否有翻牌操作正在进行 */
const flipping = ref(false);

/** 邀请码输入对话框显示状态 */
const inviteCodeDialog = ref(false);

/** 用户输入的邀请码 */
const inputInviteCode = ref('');

/** 翻倍奖励提示对话框显示状态：第9次中奖时显示 */
const showDoubleRewardDialog = ref(false);

/** 最后一次翻牌结果：保存最近一次翻牌的返回数据 */
const lastFlipResult = ref<FlipCardOutput | null>(null);

/** 我的邀请码对话框显示状态 */
const showMyInviteCodeDialog = ref(false);

/** 翻牌动画状态集合：存储正在执行翻牌动画的卡片编号 */
const flippingCards = ref<Set<number>>(new Set());

/** 幸运值：范围0-100，每次翻牌增加12%，达到100%时触发满值动画 */
const luckyValue = ref(0);

// ============ 新增：初始动画状态 ============
/** 初始洗牌动画状态 */
const isShuffling = ref(false);

/** 洗牌动画阶段：'showing' | 'flipping' | 'stacking' | 'shuffling' | 'spreading' | 'done' */
const shuffleStage = ref<'showing' | 'flipping' | 'stacking' | 'shuffling' | 'spreading' | 'done'>('done');

/** 大奖卡片编号（用于展示阶段） */
const bigPrizeCards = ref<number[]>([]);

/** 当前翻牌的卡片（用于占位显示） */
const flippingCardNumber = ref<number | null>(null);

/** 卡片位置信息（用于动画计算） */
const cardPositions = ref<Map<number, DOMRect>>(new Map());

/** 克隆卡片DOM元素（用于翻牌动画） */
const clonedCardElement = ref<HTMLElement | null>(null);

/** 系统logo图片路径 */
const systemLogo = '/images/logo.png';

/** 洗牌交换序列（记录哪些卡片要交换位置） */
const shuffleSwaps = ref<Array<[number, number]>>([]);

// ============ 生命周期 ============
onMounted(async () => {
  // 页面加载时立即获取任务状态
  await fetchTaskStatus();

  // 如果是首次进入且还没翻过牌，播放洗牌动画
  if (taskData.value && taskData.value.totalFlips === 0) {
  }
  await playShuffleAnimation();
});

// ============ 监听外部邀请码 ============
/**
 * 监听外部传入的邀请码
 * 如果有邀请码，自动打开对话框并预填
 */
watch(
  () => props.externalInviteCode,
  (newCode) => {
    if (newCode && newCode.trim()) {
      // 延迟500ms，确保页面已经渲染完成
      setTimeout(() => {
        inputInviteCode.value = newCode.trim().toUpperCase();
        inviteCodeDialog.value = true;
        ElMessage.info({
          message: '🎁 检测到邀请码，已为您自动填充，请点击确认使用',
          duration: 3000,
        });
      }, 500);
    }
  },
  { immediate: true },
);

// ============ 新增：初始洗牌动画 ============
/**
 * 初始洗牌动画
 * 完整流程：
 * 1. 展示3张大奖卡片正面（神秘大奖）- 2.5秒
 * 2. 大奖卡片翻转到背面 - 0.8秒
 * 3. 卡片在网格内随机交换位置 - 3秒（多次交换）
 */
async function playShuffleAnimation() {
  if (isShuffling.value)
    return;

  isShuffling.value = true;

  // 获取未翻开的卡片编号列表
  const unflippedCards = taskData.value?.flipRecords
    ?.filter(record => !record.isFlipped)
    .map(record => record.flipNumber) || [];

  // 随机数量取min(3, 未翻开卡片数量)
  const randomCount = Math.min(3, unflippedCards.length);

  // 从未翻开的卡片中随机选择
  bigPrizeCards.value = generateRandomCards(randomCount, unflippedCards);

  // 阶段1：展示大奖卡片正面（2.5秒）
  shuffleStage.value = 'showing';
  await new Promise(resolve => setTimeout(resolve, 2500));

  // 阶段2：大奖卡片翻转（0.8秒）
  shuffleStage.value = 'flipping';
  await new Promise(resolve => setTimeout(resolve, 800));

  // 阶段3：生成随机交换序列并执行洗牌动画
  shuffleStage.value = 'shuffling';
  await performShuffleSwaps();

  // 完成
  shuffleStage.value = 'done';
  isShuffling.value = false;
  bigPrizeCards.value = [];
  shuffleSwaps.value = [];
}

/**
 * 生成随机卡片编号
 * @param count 需要随机选择的数量
 * @param availableCards 可选的卡片编号数组（未翻开的卡片）
 */
function generateRandomCards(count: number, availableCards: number[]): number[] {
  // 如果没有可用卡片或数量为0，返回空数组
  if (!availableCards.length || count === 0) {
    return [];
  }

  // 如果需要的数量大于等于可用卡片数量，直接返回所有可用卡片
  if (count >= availableCards.length) {
    return [...availableCards];
  }

  // 从可用卡片中随机选择指定数量
  const shuffled = [...availableCards].sort(() => Math.random() - 0.5);
  return shuffled.slice(0, count);
}

/**
 * 执行洗牌交换动画
 * 更快速、更多次的交换，让所有卡片都参与
 */
async function performShuffleSwaps() {
  const swapCount = 15; // 增加到15次交换，确保所有卡片都参与
  const swapDuration = 300; // 减少到300ms，速度更快
  const swapDelay = 50; // 减少间隔时间

  // 确保每张卡片至少参与一次交换
  const allCards = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  const shuffledPairs: Array<[number, number]> = [];

  // 先生成确保所有卡片都参与的交换序列
  for (let i = 0; i < allCards.length; i++) {
    const card1 = allCards[i];
    const card2 = allCards[(i + 1 + Math.floor(Math.random() * 5)) % allCards.length];
    if (card1 !== card2) {
      shuffledPairs.push([card1, card2]);
    }
  }

  // 再添加额外的随机交换
  for (let i = shuffledPairs.length; i < swapCount; i++) {
    const card1 = Math.floor(Math.random() * 10) + 1;
    let card2 = Math.floor(Math.random() * 10) + 1;
    while (card2 === card1) {
      card2 = Math.floor(Math.random() * 10) + 1;
    }
    shuffledPairs.push([card1, card2]);
  }

  // 执行交换动画
  for (const [card1, card2] of shuffledPairs) {
    shuffleSwaps.value.push([card1, card2]);

    // 获取两张卡片的DOM元素
    const element1 = document.querySelector(`[data-card-number="${card1}"]`) as HTMLElement;
    const element2 = document.querySelector(`[data-card-number="${card2}"]`) as HTMLElement;

    if (element1 && element2) {
      // 获取位置信息
      const rect1 = element1.getBoundingClientRect();
      const rect2 = element2.getBoundingClientRect();

      // 计算位移距离
      const deltaX = rect2.left - rect1.left;
      const deltaY = rect2.top - rect1.top;

      // 添加交换动画类
      element1.classList.add('swapping');
      element2.classList.add('swapping');

      // 应用位移
      element1.style.transform = `translate(${deltaX}px, ${deltaY}px) scale(1.05)`;
      element2.style.transform = `translate(${-deltaX}px, ${-deltaY}px) scale(1.05)`;

      // 等待动画完成
      await new Promise(resolve => setTimeout(resolve, swapDuration));

      // 重置transform
      element1.style.transform = '';
      element2.style.transform = '';

      // 移除动画类
      element1.classList.remove('swapping');
      element2.classList.remove('swapping');

      // 短暂延迟
      await new Promise(resolve => setTimeout(resolve, swapDelay));
    }
  }
}

// ============ 数据获取 ============
/**
 * 获取任务状态
 * 调用时机：
 * 1. 组件挂载时
 * 2. 翻牌成功后
 * 3. 使用邀请码成功后
 * 4. 生成邀请码成功后
 */
async function fetchTaskStatus() {
  // 判断是否为首次加载（taskData为null表示首次加载）
  const isInitialLoad = taskData.value === null;

  // 首次加载使用initialLoading状态，显示骨架屏避免白屏
  // 后续刷新使用loading状态，提供用户操作反馈
  if (isInitialLoad) {
    initialLoading.value = true;
  }
  else {
    loading.value = true;
  }

  try {
    // 调用API获取本周任务状态
    const res = await getWeeklyTaskStatus();
    taskData.value = res.data;

    // 根据已翻牌次数更新幸运值显示
    updateLuckyValue();
  }
  catch (error: any) {
    ElMessage.error(error?.message || '获取任务状态失败');
  }
  finally {
    // 根据加载类型关闭对应的loading状态
    if (isInitialLoad) {
      initialLoading.value = false;
    }
    else {
      loading.value = false;
    }
  }
}

/**
 * 更新幸运值
 * 幸运值计算规则：每翻一次牌增加12%，最高100%
 * 达到100%时会触发特殊的满值动画效果
 */
function updateLuckyValue() {
  if (taskData.value) {
    const flips = taskData.value.totalFlips;
    // 每次翻牌增加12%幸运值，最大值限制为100
    luckyValue.value = Math.min(flips * 12, 100);
  }
}

// ============ 核心业务逻辑 ============
/**
 * 翻牌处理函数
 * 业务流程：
 * 1. 检查卡片是否可以翻（未翻过 且 有翻牌权限）
 * 2. 检查是否需要邀请码解锁（已翻7次以上需要邀请码）
 * 3. 调用后端接口执行翻牌
 * 4. 播放翻牌动画
 * 5. 刷新任务状态
 * 6. 显示中奖/未中奖结果
 * 7. 第9次中奖显示翻倍提示
 *
 * @param record 卡片记录对象
 */
async function handleFlipCard(record: CardFlipRecord) {
  console.log('record---', record);
  // 防止洗牌动画期间点击
  if (isShuffling.value) {
    return;
  }

  // 防抖：如果正在翻牌中，不响应点击
  if (flipping.value) {
    return;
  }

  // 检查卡片是否可以翻：未翻过的牌 且 后端允许翻牌
  const canFlip = !record.isFlipped && (taskData.value?.canFlip || false);

  if (canFlip) {
    // === 邀请码校验逻辑 ===
    // 当前已翻次数
    const currentFlips = taskData.value?.totalFlips || 0;

    // 如果已经翻了7次或以上，需要检查是否有剩余邀请次数
    if (currentFlips >= 7) {
      const remainingInviteFlips = taskData.value?.remainingInviteFlips || 0;

      // 如果没有剩余邀请次数，弹窗提示用户需要使用邀请码
      if (remainingInviteFlips === 0) {
        ElMessageBox.confirm(
          '🎁 需要先使用邀请码解锁更多翻牌机会哦~',
          '温馨提示',
          {
            confirmButtonText: '去使用',
            cancelButtonText: '取消',
            type: 'warning',
          },
        )
          .then(() => {
            // 用户点击确认，打开邀请码输入对话框
            inviteCodeDialog.value = true;
          })
          .catch(() => {});
        return;
      }
    }

    // === 开始翻牌流程（使用克隆DOM方式） ===
    // 标记为正在翻牌
    flipping.value = true;
    flippingCardNumber.value = record.flipNumber;

    try {
      // 1. 获取原卡片DOM元素
      const cardElement = document.querySelector(`[data-card-number="${record.flipNumber}"]`) as HTMLElement;
      if (!cardElement) {
        throw new Error('卡片元素未找到');
      }

      // 2. 克隆卡片DOM元素
      const clonedCard = cardElement.cloneNode(true) as HTMLElement;
      clonedCard.classList.add('cloned-flipping-card');

      // 移除可能影响显示的类（hover效果等）
      clonedCard.classList.remove('card-clickable');

      // 禁用鼠标事件，避免hover效果干扰
      clonedCard.style.pointerEvents = 'none';

      // 获取原卡片的位置信息
      const rect = cardElement.getBoundingClientRect();

      // 设置克隆卡片的初始位置（与原卡片重合）
      clonedCard.style.position = 'fixed';
      clonedCard.style.left = `${rect.left}px`;
      clonedCard.style.top = `${rect.top}px`;
      clonedCard.style.width = `${rect.width}px`;
      clonedCard.style.height = `${rect.height}px`;
      clonedCard.style.zIndex = '2000';
      clonedCard.style.transition = 'all 0.6s cubic-bezier(0.4, 0, 0.2, 1)';

      // 添加到body
      document.body.appendChild(clonedCard);
      clonedCardElement.value = clonedCard;

      // 3. 等待一帧，确保样式生效
      await new Promise(resolve => requestAnimationFrame(resolve));

      // 4. 移动克隆卡片到屏幕中心并放大（考虑边界限制）
      // 移动端使用更小的缩放比例
      const isMobile = window.innerWidth <= 768;
      const maxScale = isMobile ? 1.5 : 1.8;
      const scale = Math.min(maxScale, window.innerWidth / rect.width * (isMobile ? 0.5 : 0.6));
      const scaledWidth = rect.width * scale;
      const scaledHeight = rect.height * scale;

      // 计算中心位置，确保不溢出视口
      let centerX = window.innerWidth / 2;
      let centerY = window.innerHeight / 2;

      // 边界检查：确保卡片完全在视口内（移动端留更多边距）
      const margin = isMobile ? 30 : 20;
      const minX = scaledWidth / 2 + margin;
      const maxX = window.innerWidth - scaledWidth / 2 - margin;
      const minY = scaledHeight / 2 + margin;
      const maxY = window.innerHeight - scaledHeight / 2 - margin;

      centerX = Math.max(minX, Math.min(maxX, centerX));
      centerY = Math.max(minY, Math.min(maxY, centerY));

      clonedCard.style.left = `${centerX}px`;
      clonedCard.style.top = `${centerY}px`;
      clonedCard.style.transform = `translate(-50%, -50%) scale(${scale})`;

      // 等待移动动画完成
      await new Promise(resolve => setTimeout(resolve, 600));

      // 5. 调用后端接口执行翻牌操作
      const res = await flipCard({ flipNumber: record.flipNumber });
      lastFlipResult.value = res.data;

      // 6. 根据接口返回的结果，动态更新克隆卡片的card-back内容
      const cardBack = clonedCard.querySelector('.card-back') as HTMLElement;
      if (cardBack) {
        // 获取Vue scoped样式属性（用于保持样式一致性）
        const scopedAttr = Array.from(clonedCard.attributes).find(attr => attr.name.startsWith('data-v-'));
        const scopedAttrName = scopedAttr ? scopedAttr.name : '';

        // 辅助函数：为元素及其所有子元素添加scoped属性
        const addScopedAttr = (element: HTMLElement) => {
          if (scopedAttrName) {
            element.setAttribute(scopedAttrName, '');
            // 递归为所有子元素添加属性
            Array.from(element.children).forEach((child) => {
              addScopedAttr(child as HTMLElement);
            });
          }
        };

        // 清空原有内容（保留伪元素样式）
        cardBack.innerHTML = '';

        // 创建card-result容器
        const cardResult = document.createElement('div');
        cardResult.className = res.data.isWin ? 'card-result win' : 'card-result lose';

        if (res.data.isWin) {
          // 中奖情况：显示中奖样式
          cardResult.innerHTML = `
            <div class="win-glow"></div>
            <img src="${systemLogo}" class="result-watermark" alt="Logo">
            <div class="result-icon">🎉</div>
            <div class="result-text">中奖啦!</div>
            <div class="result-amount">${formatTokenDisplay(res.data.rewardAmount || 0)}</div>
            <div class="result-unit">Tokens</div>
          `;
        }
        else {
          // 未中奖情况：显示未中奖样式
          cardResult.innerHTML = `
            <img src="${systemLogo}" class="result-watermark" alt="Logo">
            <div class="result-icon">💫</div>
            <div class="result-text">未中奖</div>
            <div class="result-tip">继续加油!</div>
          `;
        }

        // 为新创建的元素添加scoped属性，确保样式正确应用
        addScopedAttr(cardResult);

        // 将card-result添加到card-back中
        cardBack.appendChild(cardResult);
      }

      // 7. 给克隆卡片添加翻转动画类
      const cardInner = clonedCard.querySelector('.card-inner') as HTMLElement;
      if (cardInner) {
        cardInner.style.transition = 'transform 0.8s ease-in-out';
        cardInner.style.transform = 'rotateY(180deg)';
      }

      // 等待翻转动画完成
      await new Promise(resolve => setTimeout(resolve, 800));

      // 8. 刷新任务状态
      await fetchTaskStatus();

      // 9. 卡片停留展示结果（2秒）
      await new Promise(resolve => setTimeout(resolve, 2000));

      // === 显示中奖结果 ===
      if (res.data.isWin) {
        showEnhancedWinAnimation();
        ElMessage.success({
          message: res.data.rewardDesc || '🎉 恭喜中奖！',
          duration: 3000,
          customClass: 'win-message',
        });

        if (res.data.showDoubleRewardTip) {
          setTimeout(() => {
            showDoubleRewardDialog.value = true;
          }, 500);
        }
      }
      else {
        ElMessage.info({
          message: '😢 很遗憾，未中奖',
          duration: 2000,
        });
      }

      // 10. 移除克隆卡片
      if (clonedCardElement.value) {
        // 添加淡出动画
        clonedCardElement.value.style.opacity = '0';
        await new Promise(resolve => setTimeout(resolve, 300));

        clonedCardElement.value.remove();
        clonedCardElement.value = null;
      }

      // 11. 清除占位状态，原卡片显示为已翻转
      flippingCardNumber.value = null;
    }
    catch (error: any) {
      // 清理克隆元素
      if (clonedCardElement.value) {
        clonedCardElement.value.remove();
        clonedCardElement.value = null;
      }
      flippingCardNumber.value = null;
    }
    finally {
      // 清理翻牌状态
      flipping.value = false;
      // 延迟移除动画状态，让动画自然结束
      setTimeout(() => {
        flippingCards.value.delete(record.flipNumber);
      }, 300);
    }
  }
}

/**
 * 增强的中奖动画
 * 更热烈、更隆重的效果：
 * 1. 更多彩纸（100个）
 * 2. 金色光芒效果
 * 3. 震动效果
 * 4. 声光效果
 */
function showEnhancedWinAnimation() {
  const container = document.querySelector('.card-flip-container');
  if (container) {
    // 定义彩色方案（增加金色系）
    const colors = ['#FFD700', '#FFA500', '#FF6B9D', '#f56c6c', '#409eff', '#67c23a', '#e6a23c', '#9c27b0', '#FF1493', '#00CED1'];

    // 创建100个纸屑元素（原来50个）
    for (let i = 0; i < 100; i++) {
      const confetti = document.createElement('div');
      confetti.className = 'confetti enhanced';

      // 设置初始位置（从顶部开始）
      confetti.style.position = 'absolute';
      confetti.style.top = '-10%';
      confetti.style.left = `${Math.random() * 100}%`;

      // 随机动画延迟，让纸屑不同时落下
      confetti.style.animationDelay = `${Math.random() * 0.5}s`;

      // 随机颜色
      confetti.style.background = colors[Math.floor(Math.random() * colors.length)];

      // 随机大小（8-20px，比原来更大）
      const size = 8 + Math.random() * 12;
      confetti.style.width = `${size}px`;
      confetti.style.height = `${size}px`;

      // 随机形状（圆形、方形、星形）
      const shapeRand = Math.random();
      if (shapeRand > 0.66) {
        confetti.style.borderRadius = '50%';
      }
      else if (shapeRand > 0.33) {
        confetti.style.borderRadius = '2px';
      }
      else {
        confetti.style.clipPath = 'polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%)';
      }

      // 随机透明度
      confetti.style.opacity = `${0.7 + Math.random() * 0.3}`;

      // 添加阴影效果
      confetti.style.boxShadow = '0 0 10px rgba(255, 215, 0, 0.8)';

      // 添加到容器
      container.appendChild(confetti);

      // 4秒后移除元素
      setTimeout(() => {
        confetti.remove();
      }, 4000);
    }

    // 添加金色光芒效果
    const flash = document.createElement('div');
    flash.className = 'win-flash';
    container.appendChild(flash);
    setTimeout(() => flash.remove(), 1000);

    // 移除震动效果（按用户要求）
    // container.classList.add('win-shake');
    // setTimeout(() => container.classList.remove('win-shake'), 500);
  }
}

/**
 * 显示中奖动画（保留原有函数以备用）
 * 创建50个彩色纸屑从顶部飘落的烟花效果
 * 纸屑随机颜色、大小、位置、延迟，3秒后自动移除
 */
function showWinAnimation() {
  const container = document.querySelector('.card-flip-container');
  if (container) {
    // 定义彩色方案
    const colors = ['#f56c6c', '#409eff', '#67c23a', '#e6a23c', '#9c27b0', '#FFD700', '#FF6B9D'];

    // 创建50个纸屑元素
    for (let i = 0; i < 50; i++) {
      const confetti = document.createElement('div');
      confetti.className = 'confetti';

      // 随机水平位置
      confetti.style.left = `${Math.random() * 100}%`;

      // 随机动画延迟，让纸屑不同时落下
      confetti.style.animationDelay = `${Math.random() * 0.5}s`;

      // 随机颜色
      confetti.style.background = colors[Math.floor(Math.random() * colors.length)];

      // 随机大小（6-16px）
      const size = 6 + Math.random() * 10;
      confetti.style.width = `${size}px`;
      confetti.style.height = `${size}px`;

      // 随机形状（圆形或方形）
      confetti.style.borderRadius = Math.random() > 0.5 ? '50%' : '2px';

      // 随机透明度
      confetti.style.opacity = `${0.7 + Math.random() * 0.3}`;

      // 添加到容器
      container.appendChild(confetti);

      // 3秒后移除元素，避免DOM堆积
      setTimeout(() => {
        confetti.remove();
      }, 3000);
    }
  }
}

// ============ 邀请码相关功能 ============
/**
 * 使用邀请码
 * 业务规则：
 * 1. 邀请码长度为8位
 * 2. 使用邀请码后可解锁最后3次翻牌机会（第8-10次）
 * 3. 使用他人邀请码后，自己的邀请码将失效
 * 4. 每个邀请码每周最多可被使用3次
 */
async function handleUseInviteCode() {
  // 验证输入是否为空
  if (!inputInviteCode.value.trim()) {
    ElMessage.warning('请输入邀请码');
    return;
  }

  loading.value = true;
  try {
    // 调用API使用邀请码，转换为大写统一格式
    await useInviteCode({ inviteCode: inputInviteCode.value.trim().toUpperCase() });

    // 成功提示
    ElMessage.success('🎊 邀请码使用成功！已解锁翻牌次数');

    // 关闭对话框并清空输入
    inviteCodeDialog.value = false;
    inputInviteCode.value = '';

    // 刷新任务状态，更新可翻次数
    await fetchTaskStatus();
  }
  catch (error: any) {
    // 错误提示已由API统一处理，这里注释掉避免重复提示
    // ElMessage.error(error?.message || '使用邀请码失败');
  }
  finally {
    loading.value = false;
  }
}

/**
 * 生成邀请码
 * 业务规则：
 * 1. 用户只能生成一次邀请码
 * 2. 如果已使用过他人的邀请码，则无法生成自己的邀请码
 * 3. 邀请码为8位随机字符串
 */
async function handleGenerateInviteCode() {
  loading.value = true;
  try {
    // 调用API生成邀请码
    await generateMyInviteCode();

    // 成功提示
    ElMessage.success('✨ 邀请码生成成功！');

    // 刷新任务状态，显示新生成的邀请码
    await fetchTaskStatus();
  }
  catch (error: any) {
    ElMessage.error(error?.message || '生成邀请码失败');
  }
  finally {
    loading.value = false;
  }
}

/**
 * 复制邀请码到剪贴板
 * 使用浏览器原生的 Clipboard API
 */
function copyInviteCode() {
  // 检查是否有邀请码
  if (!taskData.value?.myInviteCode) {
    ElMessage.warning('暂无邀请码');
    return;
  }

  // 使用 Clipboard API 复制到剪贴板
  navigator.clipboard.writeText(taskData.value.myInviteCode).then(() => {
    ElMessage.success('📋 邀请码已复制到剪贴板');
  }).catch(() => {
    ElMessage.error('复制失败，请手动复制');
  });
}

/**
 * 生成分享链接
 * 生成包含邀请码的完整 URL
 */
function generateShareLink(): string {
  const inviteCode = taskData.value?.myInviteCode;
  if (!inviteCode)
    return '';

  // const baseUrl = window.location.origin;
  const baseUrl = 'https://yxai.chat';
  const path = window.location.pathname;
  return `${baseUrl}${path}?inviteCode=${inviteCode}`;
}

/**
 * 生成分享文案
 * 类似小红书风格的分享内容
 */
function generateShareContent(): string {
  const shareLink = generateShareLink();

  return `
  🎁 【意心Ai】我来邀请你翻牌抽奖，分享我的限时邀请码~

填写我的邀请码，咱们双方各增加1次翻牌机会！最大可白嫖官方Claude4.5 220RMB额度 Token！💰

👉 点击链接立即参与我的专属邀请码链接：
${shareLink}

🍀 未注册用户，微信扫码登录，进入控制台👉每周邀请 即可立即参与！`;
}

/**
 * 复制分享链接和文案
 */
function copyShareContent() {
  if (!taskData.value?.myInviteCode) {
    ElMessage.warning('暂无邀请码');
    return;
  }

  const shareContent = generateShareContent();
  navigator.clipboard.writeText(shareContent).then(() => {
    ElMessage.success('🎉 分享内容已复制到剪贴板！快去分享给好友吧~');
  }).catch(() => {
    ElMessage.error('复制失败，请手动复制');
  });
}

// ============ 工具函数 ============
/**
 * 格式化 Token 显示（单位：万）
 * 例如：10000 → 1w，50000 → 5w
 *
 * @param tokens Token数量
 * @returns 格式化后的字符串
 */
function formatTokenDisplay(tokens: number): string {
  return `${(tokens / 10000).toFixed(0)}w`;
}

/**
 * 获取卡片样式类名
 * 根据卡片状态动态添加不同的CSS类
 *
 * @param record 卡片记录对象
 * @returns CSS类名数组
 */
function getCardClass(record: CardFlipRecord): string[] {
  const classes = ['card-item'];

  // 已翻牌的卡片
  if (record.isFlipped) {
    classes.push('card-flipped');
    if (record.isWin) {
      classes.push('card-win'); // 中奖样式
    }
    else {
      classes.push('card-lose'); // 未中奖样式
    }
  }

  // 正在翻牌动画中的卡片
  if (flippingCards.value.has(record.flipNumber)) {
    classes.push('card-flipping');
  }

  // 当前翻牌的卡片（占位状态）
  if (flippingCardNumber.value === record.flipNumber) {
    classes.push('card-placeholder');
  }

  // 可点击的卡片（未翻过的牌 且 有翻牌权限）
  if (!record.isFlipped && (taskData.value?.canFlip || false)) {
    classes.push('card-clickable');
  }
  // 锁定状态的卡片
  else if (!record.isFlipped) {
    classes.push('card-locked');
  }

  return classes;
}

// 删除 toggleInviteSection 函数，使用对话框代替
</script>

<template>
  <div v-loading="false" class="card-flip-container">
    <!-- 幸运值悬浮球 -->
    <div class="lucky-float-ball" :class="{ 'lucky-full': luckyValue >= 100 }">
      <div class="lucky-circle">
        <svg class="lucky-progress" viewBox="0 0 100 100">
          <defs>
            <linearGradient id="luckyGradient" x1="0%" y1="0%" x2="100%" y2="100%">
              <stop offset="0%" style="stop-color:#667eea;stop-opacity:1" />
              <stop offset="100%" style="stop-color:#764ba2;stop-opacity:1" />
            </linearGradient>
          </defs>
          <circle
            class="lucky-bg"
            cx="50"
            cy="50"
            r="40"
          />
          <circle
            class="lucky-bar"
            cx="50"
            cy="50"
            r="40"
            :stroke-dasharray="`${luckyValue * 2.51} 251`"
          />
        </svg>
        <div class="lucky-content">
          <div class="lucky-icon">
            {{ luckyValue >= 100 ? '🍀' : '✨' }}
          </div>
          <div class="lucky-text">
            {{ luckyValue }}%
          </div>
        </div>
      </div>
      <div class="lucky-label">
        <div class="lucky-main-text">
          <span class="fire-icon">🔥</span>幸运值{{ luckyValue }}%
        </div>
        <div class="lucky-sub-text">
          <span v-if="luckyValue < 100" class="lucky-highlight bounce">继续翻！后面奖励超高</span>
          <span v-else class="lucky-highlight full">幸运值满！奖励MAX</span>
        </div>
      </div>
    </div>

    <!-- 初始加载骨架屏 -->
    <div v-if="initialLoading" class="loading-skeleton">
      <div class="skeleton-compact-header" />
      <div class="skeleton-cards">
        <div v-for="i in 10" :key="i" class="skeleton-card" />
      </div>
    </div>

    <!-- 主内容 -->
    <template v-else>
      <!-- 紧凑顶部操作区（一行显示所有信息） -->
      <div class="compact-header">
        <div class="compact-stats">
          <span class="compact-stat-item">
            <span class="compact-label">翻牌</span>
            <span class="compact-value">{{ taskData?.totalFlips || 0 }}/10</span>
          </span>
          <span class="compact-stat-item">
            <span class="compact-label">邀请</span>
            <span class="compact-value">{{ taskData?.invitedCount || 0 }}人</span>
          </span>
        </div>

        <div v-if="taskData?.nextFlipTip" class="compact-tip">
          <span class="compact-tip-icon">💡</span>
          <span class="compact-tip-text">{{ taskData.nextFlipTip }}</span>
        </div>

        <div class="compact-actions">
          <el-button
            type="primary"
            size="small"
            icon="Gift"
            data-tour="my-invite-code-btn"
            @click="showMyInviteCodeDialog = true"
          >
            我的邀请码
          </el-button>
          <el-button
            type="warning"
            size="small"
            icon="Unlock"
            data-tour="use-invite-code-btn"
            @click="inviteCodeDialog = true"
          >
            使用邀请码
          </el-button>
        </div>
      </div>

      <!-- 翻牌区域 -->
      <div class="cards-section" :class="{ 'shuffle-mode': isShuffling }" data-tour="card-flip-area">
        <!-- 洗牌动画遮罩提示 -->
        <div v-if="isShuffling" class="shuffle-overlay">
          <div class="shuffle-tip">
            <span v-if="shuffleStage === 'showing'" class="shuffle-text">✨ 大奖卡片展示中... ✨</span>
            <span v-else-if="shuffleStage === 'flipping'" class="shuffle-text">🔄 卡片翻转中... 🔄</span>
            <span v-else-if="shuffleStage === 'shuffling'" class="shuffle-text">🎰 正在洗牌打乱... 🎰</span>
          </div>
        </div>

        <div class="cards-grid" :class="`shuffle-stage-${shuffleStage}`">
          <!-- 卡片包装器，始终占位 -->
          <div
            v-for="record in taskData?.flipRecords"
            :key="record.flipNumber"
            class="card-wrapper"
          >
            <div
              :data-card-number="record.flipNumber"
              :class="[
                ...getCardClass(record),
                {
                  'big-prize-card': shuffleStage === 'showing' && bigPrizeCards.includes(record.flipNumber),
                  'shuffle-card': shuffleStage === 'shuffling',
                  'card-placeholder': flippingCardNumber === record.flipNumber,
                },
              ]"
              @click="handleFlipCard(record)"
            >
              <div class="card-inner">
                <!-- 卡片背面（未翻开时显示，增加纹理） -->
                <div class="card-front">
                  <!-- 背景纹理层 -->
                  <div class="card-pattern" />

                  <div class="card-corner">
                    <span class="card-number">#{{ record.flipNumber }}</span>
                  </div>

                  <div class="card-content">
                    <!-- 使用系统logo替代表情图标 -->
                    <img :src="systemLogo" class="card-logo" alt="Logo">

                    <div class="card-mystery">
                      ?
                    </div>
                  </div>

                  <div class="card-type-badge">
                    {{ record.flipTypeDesc }}
                  </div>

                  <div class="card-shine" />
                </div>

                <!-- 卡片正面（翻开后显示结果，或洗牌时显示神秘大奖） -->
                <div class="card-back">
                  <!-- 洗牌动画中的神秘大奖展示 -->
                  <div v-if="shuffleStage === 'showing' && bigPrizeCards.includes(record.flipNumber)" class="card-result mystery-prize">
                    <div class="mystery-glow" />
                    <div class="mystery-stars">
                      ✨
                    </div>
                    <div class="mystery-icon">
                      🎁
                    </div>
                    <div class="mystery-text">
                      神秘大奖
                    </div>
                    <div class="mystery-hint">
                      敬请期待
                    </div>
                    <div class="mystery-sparkle">
                      ✨
                    </div>
                  </div>

                  <!-- 正常翻牌后的结果显示 -->
                  <template v-else>
                    <div v-if="record.isWin" class="card-result win">
                      <div class="win-glow" />

                      <!-- 系统logo水印 -->
                      <img :src="systemLogo" class="result-watermark" alt="Logo">

                      <div class="result-icon">
                        🎉
                      </div>
                      <div class="result-text">
                        中奖啦!
                      </div>
                      <div class="result-amount">
                        {{ formatTokenDisplay(record.rewardAmount || 0) }}
                      </div>
                      <div class="result-unit">
                        Tokens
                      </div>
                    </div>
                    <div v-else class="card-result lose">
                      <!-- 系统logo水印 -->
                      <img :src="systemLogo" class="result-watermark" alt="Logo">

                      <div class="result-icon">
                        💫
                      </div>
                      <div class="result-text">
                        未中奖
                      </div>
                      <div class="result-tip">
                        继续加油!
                      </div>
                    </div>
                  </template>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 使用邀请码对话框 -->
      <el-dialog
        v-model="inviteCodeDialog"
        title="🎁 使用邀请码"
        width="90%"
        :style="{ maxWidth: '400px' }"
        :close-on-click-modal="false"
        class="invite-dialog"
      >
        <div class="invite-dialog-content">
          <!-- 已填写过邀请码的提示 -->
          <div v-if="taskData?.isFilledInviteCode" class="already-filled-box">
            <span class="filled-icon">✅</span>
            <p class="filled-text">
              您已填写过邀请码，每人仅能填写一次他人邀请码
            </p>
          </div>

          <template v-else>
            <p class="dialog-tip">
              输入好友的邀请码，双方各增加1次翻牌机会！必定中奖，每次奖励最大额度翻倍！
            </p>
            <el-input
              v-model="inputInviteCode"
              placeholder="请输入8位邀请码"
              maxlength="8"
              clearable
              size="large"
              class="code-input"
            >
              <template #prefix>
                <span style="font-size: 20px;">🎫</span>
              </template>
            </el-input>
          </template>
        </div>
        <template #footer>
          <el-button @click="inviteCodeDialog = false">
            取消
          </el-button>
          <el-button
            v-if="!taskData?.isFilledInviteCode"
            type="primary"
            :loading="loading"
            @click="handleUseInviteCode"
          >
            确认使用
          </el-button>
        </template>
      </el-dialog>

      <!-- 我的邀请码对话框 -->
      <el-dialog
        v-model="showMyInviteCodeDialog"
        title="📮 我的邀请码"
        width="90%"
        :style="{ maxWidth: '400px' }"
        class="my-invite-dialog"
      >
        <div class="my-invite-dialog-content">
          <!-- 显示已有的邀请码 -->
          <div v-if="taskData?.myInviteCode" class="my-invite-code-display">
            <div class="code-box">
              <span class="code-text">{{ taskData.myInviteCode }}</span>
            </div>
            <div class="button-group">
              <el-button
                type="primary"
                icon="CopyDocument"
                @click="copyInviteCode"
              >
                复制邀请码
              </el-button>
              <el-button
                type="success"
                icon="Share"
                @click="copyShareContent"
              >
                复制分享链接
              </el-button>
            </div>
            <!-- 显示当前用户是否已填写过邀请码 -->
            <div v-if="taskData?.isFilledInviteCode" class="filled-status-info">
              <span class="status-icon">✅</span>
              <span class="status-text">您已填写过他人邀请码</span>
            </div>
            <div v-else class="unfilled-status-info">
              <span class="status-icon">💡</span>
              <span class="status-text">您还可以填写他人邀请码获得额外机会</span>
            </div>
            <p class="invite-tip">
              💌 分享给好友，好友填写您的邀请码后<br>
              <strong>双方各增加1次翻牌机会！</strong>
            </p>

            <div class="share-preview">
              <div class="share-preview-title">
                📱 分享预览
              </div>
              <div class="share-preview-content">
                {{ generateShareContent() }}
              </div>
            </div>
          </div>

          <!-- 生成邀请码 -->
          <div v-else class="generate-invite-box">
            <p class="generate-tip">
              您还没有邀请码，生成后分享给好友，<strong>双方各增加1次翻牌机会</strong>！
            </p>
            <el-button
              type="primary"
              size="large"
              :loading="loading"
              @click="handleGenerateInviteCode"
            >
              生成我的邀请码
            </el-button>
          </div>
        </div>
      </el-dialog>

      <!-- 翻倍奖励提示对话框 -->
      <el-dialog
        v-model="showDoubleRewardDialog"
        width="90%"
        :style="{ maxWidth: '400px' }"
        :show-close="false"
        class="double-reward-dialog"
      >
        <div class="double-reward-content">
          <div class="double-icon-container">
            <div class="double-icon">
              🎁
            </div>
            <div class="double-sparkle">
              ✨
            </div>
          </div>
          <h3 class="double-title">
            恭喜获得额外翻倍包!
          </h3>
          <p class="double-text">
            您已获得第9次奖励！<br>
            <span class="highlight">第10次翻牌将获得翻倍奖励！</span><br>
            赶快翻开最后一张牌吧！
          </p>
          <el-button type="primary" size="large" class="double-btn" @click="showDoubleRewardDialog = false">
            知道了，去翻牌 🚀
          </el-button>
        </div>
      </el-dialog>
    </template>
  </div>
</template>

<style scoped lang="scss">
.card-flip-container {
  position: relative;
  padding: 16px;
  min-height: 400px;
  max-height: none;
  height: 100%;
  overflow-y: auto;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 16px;

  @media (max-width: 768px) {
    padding: 12px;
    border-radius: 12px;
  }

  /* 自定义滚动条 */
  &::-webkit-scrollbar {
    width: 6px;
  }

  &::-webkit-scrollbar-track {
    background: rgba(255, 255, 255, 0.1);
    border-radius: 3px;
  }

  &::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.3);
    border-radius: 3px;

    &:hover {
      background: rgba(255, 255, 255, 0.5);
    }
  }
}

/* 幸运值悬浮球 */
.lucky-float-ball {
  position: absolute;
  left: 50%;
  bottom: 16px;
  transform: translateX(-50%);
  z-index: 999;
  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;

  &:hover {
    transform: translateX(-50%) scale(1.05);
  }

  @media (max-width: 768px) {
    bottom: 12px;

    .lucky-circle {
      width: 70px;
      height: 70px;
    }

    .lucky-content .lucky-icon {
      font-size: 20px;
    }

    .lucky-content .lucky-text {
      font-size: 12px;
    }

    .lucky-label {
      margin-top: 4px;
    }
  }

  &.lucky-full {
    .lucky-circle {
      box-shadow: 0 0 20px rgba(255, 215, 0, 0.8), 0 0 40px rgba(255, 215, 0, 0.6);
      animation: lucky-celebration 2s ease-in-out infinite;
    }

    .lucky-content {
      animation: lucky-pulse 1.5s ease-in-out infinite;
    }
  }
}

.lucky-circle {
  position: relative;
  width: 80px;
  height: 80px;
  background: rgba(255, 255, 255, 0.95);
  border-radius: 50%;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2), 0 8px 32px rgba(102, 126, 234, 0.3);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.3s ease;
}

.lucky-progress {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);

  .lucky-bg {
    fill: none;
    stroke: rgba(102, 126, 234, 0.1);
    stroke-width: 6;
  }

  .lucky-bar {
    fill: none;
    stroke: url(#luckyGradient);
    stroke-width: 6;
    stroke-linecap: round;
    transition: stroke-dasharray 0.5s ease;
  }
}

.lucky-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;

  .lucky-icon {
    font-size: 24px;
    line-height: 1;
    filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2));
  }

  .lucky-text {
    font-size: 14px;
    font-weight: bold;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    line-height: 1;
  }
}

.lucky-label {
  text-align: center;
  margin-top: 6px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  width: max-content;
  min-width: 100px;
  max-width: 140px;
  margin-left: auto;
  margin-right: auto;

  .lucky-main-text {
    font-size: 14px;
    font-weight: bold;
    color: #fff;
    text-shadow: 0 2px 4px rgba(0, 0, 0, 0.4);
    letter-spacing: 1px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    white-space: nowrap;

    .fire-icon {
      font-size: 14px;
      animation: fireShake 0.5s ease-in-out infinite;
      display: inline-block;
    }
  }

  .lucky-sub-text {
    font-size: 11px;
    font-weight: 600;
    width: 100%;
    display: flex;
    justify-content: center;
  }

  .lucky-highlight {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 12px;
    font-size: 11px;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
    white-space: nowrap;
    text-align: center;

    &.bounce {
      background: linear-gradient(90deg, #ff6b6b 0%, #ffd93d 50%, #ff6b6b 100%);
      background-size: 200% 100%;
      color: #fff;
      box-shadow: 0 2px 10px rgba(255, 107, 107, 0.5);
      animation: gradientMove 2s linear infinite, bounceHint 1s ease-in-out infinite;
    }

    &.full {
      background: linear-gradient(135deg, #FFD700 0%, #ff6b9d 50%, #c06c84 100%);
      background-size: 200% 100%;
      color: #fff;
      box-shadow: 0 0 15px rgba(255, 215, 0, 0.8);
      animation: gradientMove 2s linear infinite, glowPulse 1.5s ease-in-out infinite;
    }
  }

  @media (max-width: 768px) {
    margin-top: 4px;
    gap: 3px;
    min-width: 80px;
    max-width: 120px;

    .lucky-main-text {
      font-size: 12px;

      .fire-icon {
        font-size: 12px;
      }
    }

    .lucky-highlight {
      font-size: 10px;
      padding: 2px 8px;
    }
  }
}

@keyframes fireShake {
  0%, 100% { transform: rotate(-5deg) scale(1); }
  50% { transform: rotate(5deg) scale(1.1); }
}

@keyframes bounceHint {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-3px); }
}

@keyframes gradientMove {
  0% { background-position: 0% 50%; }
  100% { background-position: 200% 50%; }
}

@keyframes glowPulse {
  0%, 100% { box-shadow: 0 0 10px rgba(255, 215, 0, 0.6); }
  50% { box-shadow: 0 0 20px rgba(255, 215, 0, 1), 0 0 30px rgba(255, 107, 157, 0.5); }
}

@keyframes lucky-celebration {
  0%, 100% {
    transform: scale(1) rotate(0deg);
  }
  25% {
    transform: scale(1.1) rotate(-5deg);
  }
  50% {
    transform: scale(1.15) rotate(0deg);
  }
  75% {
    transform: scale(1.1) rotate(5deg);
  }
}

@keyframes lucky-pulse {
  0%, 100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.1);
  }
}

/* 紧凑顶部操作区 */
.compact-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 14px;
  background: rgba(255, 255, 255, 0.95);
  border-radius: 12px;
  margin-bottom: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  animation: slideIn 0.5s ease;
  flex-wrap: wrap;

  @media (max-width: 768px) {
    padding: 8px 10px;
    gap: 8px;
    margin-bottom: 10px;
  }

  .compact-stats {
    display: flex;
    align-items: center;
    gap: 16px;
  }

  .compact-stat-item {
    display: flex;
    align-items: center;
    gap: 4px;
    white-space: nowrap;
  }

  .compact-label {
    font-size: 13px;
    color: #606266;
    font-weight: 500;
  }

  .compact-value {
    font-size: 15px;
    font-weight: bold;
    color: #303133;
  }

  .compact-tip {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
  }

  .compact-tip-icon {
    font-size: 16px;
    flex-shrink: 0;
  }

  .compact-tip-text {
    font-size: 13px;
    color: #606266;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .compact-actions {
    display: flex;
    gap: 8px;
    flex-shrink: 0;

    .el-button {
      font-weight: 500;
    }
  }

  @media (max-width: 768px) {
    .compact-tip {
      flex-basis: 100%;
      order: 3;
    }
  }
}

/* 翻牌区域 */
.cards-section {
  margin-bottom: 16px;
  position: relative;

  &.shuffle-mode {
    pointer-events: none; // 洗牌期间禁止点击
  }
}

/* 洗牌动画遮罩 */
.shuffle-overlay {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 100;

  .shuffle-tip {
    background: rgba(0, 0, 0, 0.8);
    padding: 16px 32px;
    border-radius: 12px;
    backdrop-filter: blur(10px);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);

    @media (max-width: 768px) {
      padding: 12px 20px;
      border-radius: 8px;
    }
  }

  .shuffle-text {
    font-size: 18px;
    font-weight: bold;
    color: #fff;
    text-shadow: 0 2px 8px rgba(255, 215, 0, 0.6);
    animation: textPulse 1.5s ease-in-out infinite;
    white-space: nowrap;

    @media (max-width: 768px) {
      font-size: 14px;
    }

    @media (max-width: 480px) {
      font-size: 12px;
    }
  }
}

.cards-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
  max-width: 100%;

  @media (max-width: 768px) {
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
  }

  @media (max-width: 480px) {
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
  }

  // 洗牌阶段样式
  &.shuffle-stage-showing {
    .card-item:not(.big-prize-card) {
      opacity: 0.3;
      filter: grayscale(0.8);
    }
  }

  &.shuffle-stage-flipping {
    .big-prize-card .card-inner {
      animation: flipToBack 0.8s ease-in-out forwards;
    }
  }

  &.shuffle-stage-shuffling {
    .card-item {
      animation: shuffleInPlace 2s ease-in-out;
    }
  }
}

// 卡片包装器，简化为普通容器
.card-wrapper {
  width: 100%;
}

.card-item {
  position: relative;
  width: 100%;
  aspect-ratio: 2.5/3.5;
  perspective: 1000px;
  cursor: not-allowed;
  user-select: none;
  transition: all 0.3s ease;

  // 大奖卡片高亮样式
  &.big-prize-card {
    .card-inner {
      animation: bigPrizeGlow 1.5s ease-in-out infinite;
      box-shadow: 0 0 30px rgba(255, 215, 0, 0.8), 0 0 60px rgba(255, 215, 0, 0.5);
      transform: scale(1.1) translateY(-10px);
    }

    .card-front {
      transform: rotateY(180deg); // 大奖卡片展示正面（结果）
    }

    .card-back {
      transform: rotateY(0); // 翻转显示
    }
  }

  // 占位状态（翻牌时原卡片显示为半透明）
  &.card-placeholder {
    opacity: 0.3;
    pointer-events: none;
  }

  &.card-clickable {
    cursor: pointer;

    .card-front {
      animation: pulse 2s infinite;
    }

    &:not(.card-flipping):not(.card-flipped):not(.card-placeholder) {
      .card-inner {
        transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.3s ease, filter 0.3s ease;
      }

      &:hover .card-inner {
        transform: translateY(-8px) scale(1.05) rotateZ(2deg);
        box-shadow: 0 12px 28px rgba(102, 126, 234, 0.5), 0 4px 12px rgba(255, 215, 0, 0.3);
        filter: brightness(1.1);
      }

      &:active .card-inner {
        transform: translateY(-4px) scale(1.02);
        box-shadow: 0 6px 16px rgba(102, 126, 234, 0.4);
      }
    }
  }

  &.card-locked {
    opacity: 0.6;
  }

  &.card-flipping .card-inner {
    animation: flip 0.8s ease-in-out forwards;
  }

  &.card-flipped .card-inner {
    transform: rotateY(180deg);
  }
}

.card-inner {
  position: relative;
  width: 100%;
  height: 100%;
  transition: box-shadow 0.3s ease;
  transform-style: preserve-3d;
  border-radius: 10px;
}

.card-front,
.card-back {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  backface-visibility: hidden;
  border-radius: 10px;
  overflow: hidden;
}

.card-front {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);

  // 背景纹理层（更丰富的纹理效果）
  .card-pattern {
    position: absolute;
    inset: 0;
    background-image:
      repeating-linear-gradient(
          45deg,
          transparent,
          transparent 10px,
          rgba(255, 255, 255, 0.05) 10px,
          rgba(255, 255, 255, 0.05) 20px
      ),
      repeating-linear-gradient(
          -45deg,
          transparent,
          transparent 10px,
          rgba(255, 255, 255, 0.05) 10px,
          rgba(255, 255, 255, 0.05) 20px
      ),
      radial-gradient(circle at 20% 80%, rgba(255, 255, 255, 0.1), transparent 50%),
      radial-gradient(circle at 80% 20%, rgba(255, 255, 255, 0.08), transparent 50%);
    pointer-events: none;
    animation: patternShift 10s linear infinite;
  }

  .card-corner {
    position: absolute;
    top: 6px;
    left: 6px;
    z-index: 2;
  }

  .card-number {
    font-size: 10px;
    font-weight: bold;
    color: rgba(255, 255, 255, 0.9);
    background: rgba(0, 0, 0, 0.2);
    padding: 2px 6px;
    border-radius: 4px;

    @media (max-width: 768px) {
      font-size: 9px;
      padding: 2px 5px;
    }
  }

  .card-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    z-index: 1;

    @media (max-width: 768px) {
      gap: 6px;
    }
  }

  // 系统logo样式（优化为居中圆形，更丰富的效果）
  .card-logo {
    width: 56px;
    height: 56px;
    object-fit: cover;
    border-radius: 50%;
    border: 4px solid rgba(255, 255, 255, 1);
    box-shadow:
      0 4px 20px rgba(0, 0, 0, 0.5),
      0 0 30px rgba(255, 215, 0, 0.4),
      inset 0 2px 8px rgba(255, 255, 255, 0.3);
    animation: logoFloat 3s ease-in-out infinite;
    position: relative;
    z-index: 3;
    filter: brightness(1.1);

    @media (max-width: 768px) {
      width: 40px;
      height: 40px;
      border: 3px solid rgba(255, 255, 255, 1);
    }

    // 外层光晕效果
    &::before {
      content: '';
      position: absolute;
      inset: -10px;
      border-radius: 50%;
      background: radial-gradient(circle, rgba(255, 215, 0, 0.4), rgba(147, 112, 219, 0.2) 50%, transparent 70%);
      animation: logoHalo 2s ease-in-out infinite;
      z-index: -1;
    }

    // 内层光效
    &::after {
      content: '';
      position: absolute;
      inset: 0;
      border-radius: 50%;
      background: linear-gradient(135deg, rgba(255, 255, 255, 0.3) 0%, transparent 50%);
      pointer-events: none;
    }
  }

  .card-icon {
    font-size: 32px;
    filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2));
  }

  .card-mystery {
    font-size: 32px;
    font-weight: bold;
    color: #fff;
    text-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);

    @media (max-width: 768px) {
      font-size: 24px;
    }
  }

  .card-type-badge {
    position: absolute;
    bottom: 6px;
    font-size: 10px;
    color: rgba(255, 255, 255, 0.9);
    background: rgba(0, 0, 0, 0.2);
    padding: 2px 8px;
    border-radius: 10px;
    backdrop-filter: blur(4px);
    z-index: 2;

    @media (max-width: 768px) {
      font-size: 9px;
      padding: 2px 6px;
      bottom: 4px;
    }
  }

  .card-shine {
    position: absolute;
    top: 0;
    left: -100%;
    width: 100%;
    height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);
    animation: shine 3s infinite;
    pointer-events: none;
  }
}

.card-back {
  // 喜庆的渐变背景（红→金→橙）
  background:
    linear-gradient(135deg,
      rgba(255, 235, 238, 0.9) 0%,
      rgba(255, 250, 240, 0.9) 50%,
      rgba(255, 245, 235, 0.9) 100%
    );
  transform: rotateY(180deg);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
  display: flex;
  align-items: center;
  justify-content: center;

  // 喜庆纹理层（中国风波浪纹）
  &::before {
    content: '';
    position: absolute;
    inset: 0;
    background-image:
      repeating-radial-gradient(
          circle at 20% 30%,
          transparent 0,
          rgba(255, 107, 107, 0.03) 10px,
          transparent 20px
      ),
      repeating-radial-gradient(
          circle at 80% 70%,
          transparent 0,
          rgba(255, 193, 7, 0.03) 10px,
          transparent 20px
      );
    pointer-events: none;
  }

  // 装饰光效（金色和红色交替）
  &::after {
    content: '';
    position: absolute;
    inset: 0;
    background:
      radial-gradient(circle at 20% 20%, rgba(255, 215, 0, 0.08), transparent 50%),
      radial-gradient(circle at 80% 80%, rgba(255, 107, 107, 0.08), transparent 50%),
      radial-gradient(circle at 50% 50%, rgba(255, 152, 0, 0.05), transparent 60%);
    pointer-events: none;
  }
}

.card-result {
  text-align: center;
  padding: 12px;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  position: relative;
  z-index: 1;

  @media (max-width: 768px) {
    padding: 8px;
  }

  // logo水印样式
  .result-watermark {
    position: absolute;
    width: 70%;
    height: 70%;
    object-fit: contain;
    opacity: 0.06;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    pointer-events: none;
    z-index: 0;
    filter: blur(1px);
  }

  &.win {
    position: relative;
    overflow: hidden;
    background: linear-gradient(135deg, #fff8e1 0%, #fff 50%, #fff8e1 100%);

    // 增强背景光效
    &::before {
      content: '';
      position: absolute;
      inset: 0;
      background: radial-gradient(circle at center, rgba(255, 215, 0, 0.15), transparent 70%);
      animation: winBackgroundPulse 2s ease-in-out infinite;
    }

    .win-glow {
      position: absolute;
      inset: 0;
      background: radial-gradient(circle, rgba(255, 215, 0, 0.4) 0%, rgba(255, 107, 157, 0.2) 50%, transparent 70%);
      animation: glow 1.5s infinite;
    }

    .result-icon {
      font-size: 48px;
      animation: bounce 0.6s ease, rotate 2s ease-in-out infinite;
      z-index: 1;
      filter: drop-shadow(0 4px 8px rgba(255, 215, 0, 0.5));
      margin-bottom: 4px;

      @media (max-width: 768px) {
        font-size: 36px;
      }
    }

    .result-text {
      font-size: 20px;
      font-weight: 900;
      background: linear-gradient(135deg, #f56c6c 0%, #ff8080 50%, #f56c6c 100%);
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
      margin: 6px 0;
      text-shadow: 0 2px 8px rgba(245, 108, 108, 0.4);
      z-index: 1;
      letter-spacing: 2px;
      position: relative;

      @media (max-width: 768px) {
        font-size: 16px;
        letter-spacing: 1px;
      }

      // 文字外发光
      &::after {
        content: attr(data-text);
        position: absolute;
        left: 0;
        top: 0;
        z-index: -1;
        color: rgba(245, 108, 108, 0.5);
        filter: blur(4px);
      }
    }

    .result-amount {
      font-size: 40px;
      font-weight: 900;
      background: linear-gradient(135deg, #f56c6c 0%, #e6a23c 50%, #FFD700 100%);
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
      margin: 10px 0;
      animation: scaleUp 0.5s ease, amountShine 3s ease-in-out infinite;
      z-index: 1;
      position: relative;
      filter: drop-shadow(0 3px 10px rgba(255, 215, 0, 0.6));

      @media (max-width: 768px) {
        font-size: 32px;
        margin: 8px 0;
      }

      // 金色光效边框
      &::before {
        content: attr(data-amount);
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        background: linear-gradient(135deg, rgba(255, 215, 0, 0.8), rgba(255, 107, 157, 0.6));
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        filter: blur(12px);
        z-index: -1;
      }
    }

    .result-unit {
      font-size: 16px;
      font-weight: 700;
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
      z-index: 1;
      letter-spacing: 3px;
      text-transform: uppercase;
      margin-top: 4px;

      @media (max-width: 768px) {
        font-size: 14px;
        letter-spacing: 2px;
      }
    }
  }

  &.lose {
    background: linear-gradient(135deg, #f5f7fa 0%, #e8eaf0 50%, #f5f7fa 100%);

    // 柔和的背景光效
    &::before {
      content: '';
      position: absolute;
      inset: 0;
      background: radial-gradient(circle at center, rgba(147, 112, 219, 0.08), transparent 70%);
    }

    .result-icon {
      font-size: 48px;
      opacity: 0.85;
      z-index: 1;
      margin-bottom: 6px;
      filter: drop-shadow(0 2px 6px rgba(147, 112, 219, 0.3));
      animation: gentleBounce 2s ease-in-out infinite;

      @media (max-width: 768px) {
        font-size: 36px;
      }
    }

    .result-text {
      font-size: 18px;
      font-weight: 700;
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
      margin: 8px 0;
      z-index: 1;
      letter-spacing: 1px;

      @media (max-width: 768px) {
        font-size: 15px;
      }
    }

    .result-tip {
      font-size: 14px;
      color: #909399;
      z-index: 1;
      margin-top: 6px;
      font-weight: 500;

      @media (max-width: 768px) {
        font-size: 12px;
      }
    }
  }

  // 神秘大奖样式
  &.mystery-prize {
    background: linear-gradient(135deg, #ff6b9d 0%, #c06c84 50%, #6c5b7b 100%);
    position: relative;
    overflow: hidden;

    .mystery-glow {
      position: absolute;
      inset: 0;
      background: radial-gradient(circle, rgba(255, 107, 157, 0.6) 0%, rgba(192, 108, 132, 0.4) 50%, transparent 70%);
      animation: mysteryGlow 2s ease-in-out infinite;
    }

    .mystery-icon {
      font-size: 56px;
      animation: bounce 1s ease infinite, rotate 3s ease-in-out infinite;
      z-index: 1;
      filter: drop-shadow(0 4px 12px rgba(255, 215, 0, 0.8));
      margin: 10px 0;

      @media (max-width: 768px) {
        font-size: 42px;
        margin: 8px 0;
      }
    }

    .mystery-text {
      font-size: 24px;
      font-weight: bold;
      color: #fff;
      text-shadow: 0 2px 8px rgba(0, 0, 0, 0.5), 0 0 20px rgba(255, 215, 0, 0.8);
      z-index: 1;
      letter-spacing: 4px;
      margin: 8px 0;

      @media (max-width: 768px) {
        font-size: 18px;
        letter-spacing: 2px;
      }
    }

    .mystery-hint {
      font-size: 14px;
      color: rgba(255, 255, 255, 0.9);
      z-index: 1;
      letter-spacing: 2px;
      margin-top: 6px;

      @media (max-width: 768px) {
        font-size: 12px;
        letter-spacing: 1px;
      }
    }

    .mystery-stars {
      position: absolute;
      top: 10px;
      left: 10px;
      font-size: 24px;
      animation: sparkle 2s ease-in-out infinite;
      z-index: 1;
    }

    .mystery-sparkle {
      position: absolute;
      bottom: 10px;
      right: 10px;
      font-size: 24px;
      animation: sparkle 2s ease-in-out infinite 1s;
      z-index: 1;
    }
  }
}

.card-lock {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.5);
  border-radius: 10px;
  backdrop-filter: blur(2px);
  pointer-events: none;

  .lock-icon {
    font-size: 24px;
  }
}

/* 对话框样式 */
.invite-dialog-content {
  padding: 8px 0;

  .dialog-tip {
    font-size: 14px;
    color: #606266;
    margin-bottom: 16px;
    text-align: center;
    line-height: 1.6;

    @media (max-width: 768px) {
      font-size: 13px;
      margin-bottom: 12px;
    }
  }

  .code-input {
    :deep(.el-input__inner) {
      text-align: center;
      letter-spacing: 2px;
      font-weight: bold;
      font-size: 16px;
    }
  }

  .already-filled-box {
    text-align: center;
    padding: 24px 16px;
    background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);
    border: 1px solid #bae6fd;
    border-radius: 12px;

    @media (max-width: 768px) {
      padding: 20px 12px;
    }

    .filled-icon {
      font-size: 48px;
      display: block;
      margin-bottom: 12px;

      @media (max-width: 768px) {
        font-size: 40px;
        margin-bottom: 10px;
      }
    }

    .filled-text {
      font-size: 15px;
      color: #0369a1;
      line-height: 1.6;
      margin: 0;
      font-weight: 500;

      @media (max-width: 768px) {
        font-size: 14px;
      }
    }
  }
}

/* 我的邀请码对话框样式 */
.my-invite-dialog-content {
  padding: 8px 0;

  .invite-disabled-box {
    text-align: center;
    padding: 20px;
    background: #fef0f0;
    border: 1px solid #fde2e2;
    border-radius: 8px;

    .disabled-icon {
      font-size: 48px;
      display: block;
      margin-bottom: 12px;
    }

    .disabled-text {
      font-size: 14px;
      color: #f56c6c;
      line-height: 1.6;
      margin: 0;
    }
  }

  .my-invite-code-display {
    text-align: center;

    .code-box {
      padding: 16px;
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      border-radius: 12px;
      margin-bottom: 16px;

      @media (max-width: 768px) {
        padding: 14px;
        margin-bottom: 12px;
      }

      .code-text {
        font-size: 28px;
        font-weight: bold;
        color: #fff;
        letter-spacing: 6px;
        text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);

        @media (max-width: 768px) {
          font-size: 24px;
          letter-spacing: 4px;
        }
      }
    }

    .button-group {
      display: flex;
      gap: 8px;
      margin-bottom: 12px;

      @media (max-width: 768px) {
        flex-direction: column;
        gap: 10px;
      }

      .el-button {
        flex: 1;

        @media (max-width: 768px) {
          width: 100%;
        }
      }
    }

    .invite-tip {
      font-size: 13px;
      color: #909399;
      line-height: 1.5;
      margin: 0 0 12px 0;

      @media (max-width: 768px) {
        font-size: 12px;
      }

      strong {
        color: #f56c6c;
        font-weight: 600;
      }
    }

    .filled-status-info,
    .unfilled-status-info {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 6px;
      padding: 8px 12px;
      border-radius: 8px;
      margin-bottom: 12px;
      font-size: 13px;
      font-weight: 500;
    }

    .filled-status-info {
      background: #f0fdf4;
      border: 1px solid #86efac;
      color: #166534;

      .status-icon {
        font-size: 16px;
      }
    }

    .unfilled-status-info {
      background: #fefce8;
      border: 1px solid #fde047;
      color: #854d0e;

      .status-icon {
        font-size: 16px;
      }
    }

    .share-preview {
      background: #f5f7fa;
      border: 1px solid #e4e7ed;
      border-radius: 8px;
      padding: 12px;
      text-align: left;

      @media (max-width: 768px) {
        padding: 10px;
      }

      .share-preview-title {
        font-size: 14px;
        font-weight: bold;
        color: #303133;
        margin-bottom: 8px;
        text-align: center;

        @media (max-width: 768px) {
          font-size: 13px;
        }
      }

      .share-preview-content {
        font-size: 13px;
        color: #606266;
        line-height: 1.6;
        white-space: pre-line;
        background: #fff;
        padding: 10px;
        border-radius: 4px;
        max-height: 200px;
        overflow-y: auto;

        @media (max-width: 768px) {
          font-size: 12px;
          padding: 8px;
          max-height: 150px;
        }

        /* 自定义滚动条 */
        &::-webkit-scrollbar {
          width: 4px;
        }

        &::-webkit-scrollbar-track {
          background: rgba(0, 0, 0, 0.05);
          border-radius: 2px;
        }

        &::-webkit-scrollbar-thumb {
          background: rgba(0, 0, 0, 0.2);
          border-radius: 2px;

          &:hover {
            background: rgba(0, 0, 0, 0.3);
          }
        }
      }
    }
  }

  .generate-invite-box {
    text-align: center;
    padding: 20px 0;

    .generate-tip {
      font-size: 14px;
      color: #606266;
      margin-bottom: 20px;
      line-height: 1.6;

      strong {
        color: #f56c6c;
        font-weight: 600;
      }
    }

    .el-button {
      width: 100%;
    }
  }
}

.double-reward-dialog {
  :deep(.el-dialog__body) {
    padding: 32px 24px;
  }
}

.double-reward-content {
  text-align: center;

  .double-icon-container {
    position: relative;
    display: inline-block;
    margin-bottom: 20px;

    @media (max-width: 768px) {
      margin-bottom: 16px;
    }

    .double-icon {
      font-size: 64px;
      animation: bounce 1s infinite;

      @media (max-width: 768px) {
        font-size: 52px;
      }
    }

    .double-sparkle {
      position: absolute;
      top: -10px;
      right: -10px;
      font-size: 32px;
      animation: spin 2s linear infinite;

      @media (max-width: 768px) {
        font-size: 26px;
      }
    }
  }

  .double-title {
    font-size: 20px;
    font-weight: bold;
    color: #303133;
    margin-bottom: 16px;

    @media (max-width: 768px) {
      font-size: 18px;
      margin-bottom: 12px;
    }
  }

  .double-text {
    font-size: 15px;
    line-height: 1.8;
    color: #606266;
    margin-bottom: 24px;

    @media (max-width: 768px) {
      font-size: 14px;
      margin-bottom: 20px;
    }

    .highlight {
      color: #f56c6c;
      font-weight: bold;
      font-size: 16px;

      @media (max-width: 768px) {
        font-size: 15px;
      }
    }
  }

  .double-btn {
    width: 100%;
    background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
    border: none;
    font-weight: bold;
  }
}

/* 烟花动画 */
.confetti {
  position: absolute;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  animation: confetti-fall 2s ease-out forwards;
  pointer-events: none;
  z-index: 1000;

  &.enhanced {
    animation: confetti-fall 3s ease-out forwards;
  }
}

/* 增强中奖动画效果 */
.win-flash {
  position: absolute;
  inset: 0;
  background: radial-gradient(circle, rgba(255, 215, 0, 0.6) 0%, transparent 70%);
  animation: flashEffect 1s ease-out;
  pointer-events: none;
  z-index: 999;
}

.win-shake {
  animation: shakeEffect 0.5s ease-out;
}

/* 动画定义 */
@keyframes flip {
  0% {
    transform: rotateY(0);
  }
  50% {
    transform: rotateY(90deg);
  }
  100% {
    transform: rotateY(180deg);
  }
}

// Logo浮动动画
@keyframes logoFloat {
  0%, 100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-5px);
  }
}

// 闪光效果
@keyframes flashEffect {
  0% {
    opacity: 0;
  }
  50% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

// 震动效果
@keyframes shakeEffect {
  0%, 100% {
    transform: translateX(0);
  }
  10%, 30%, 50%, 70%, 90% {
    transform: translateX(-5px);
  }
  20%, 40%, 60%, 80% {
    transform: translateX(5px);
  }
}

@keyframes bounce {
  0%, 100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-10px);
  }
}

@keyframes pulse {
  0%, 100% {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
  }
  50% {
    box-shadow: 0 4px 20px rgba(255, 215, 0, 0.6);
  }
}

@keyframes shine {
  0% {
    left: -100%;
  }
  100% {
    left: 100%;
  }
}

@keyframes glow {
  0%, 100% {
    opacity: 0.5;
  }
  50% {
    opacity: 1;
  }
}

@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

@keyframes confetti-fall {
  0% {
    top: -10%;
    opacity: 1;
  }
  100% {
    top: 100%;
    opacity: 0;
    transform: translateX(20px) rotate(180deg);
  }
}

@keyframes slideIn {
  from {
    opacity: 0;
    transform: translateY(-10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes rotate {
  0%, 100% {
    transform: rotate(-5deg);
  }
  50% {
    transform: rotate(5deg);
  }
}

@keyframes scaleUp {
  0% {
    transform: scale(0.5);
    opacity: 0;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

// 洗牌动画（在网格内小幅度移动）
@keyframes shuffleInPlace {
  0%, 100% {
    transform: translate(0, 0) rotate(0deg);
  }
  20% {
    transform: translate(15px, -10px) rotate(8deg) scale(1.05);
  }
  40% {
    transform: translate(-12px, 8px) rotate(-6deg) scale(0.95);
  }
  60% {
    transform: translate(10px, 12px) rotate(5deg) scale(1.03);
  }
  80% {
    transform: translate(-8px, -8px) rotate(-4deg) scale(0.98);
  }
}

// 交换动画样式（加快速度）
.card-item.swapping {
  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  z-index: 10;
}

// 背景纹理移动动画
@keyframes patternShift {
  0% {
    background-position: 0 0, 0 0, 0 0, 0 0;
  }
  100% {
    background-position: 40px 40px, -40px -40px, 20px 20px, -20px -20px;
  }
}

// 柔和的弹跳动画（未中奖）
@keyframes gentleBounce {
  0%, 100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-5px);
  }
}

// 新增：大奖卡片光效
@keyframes bigPrizeGlow {
  0%, 100% {
    box-shadow: 0 0 30px rgba(255, 215, 0, 0.8), 0 0 60px rgba(255, 215, 0, 0.5);
  }
  50% {
    box-shadow: 0 0 40px rgba(255, 215, 0, 1), 0 0 80px rgba(255, 215, 0, 0.7), 0 0 100px rgba(255, 215, 0, 0.4);
  }
}

// 新增：Logo光晕动画
@keyframes logoHalo {
  0%, 100% {
    opacity: 0.5;
    transform: scale(1);
  }
  50% {
    opacity: 0.8;
    transform: scale(1.2);
  }
}

// 新增：文字脉冲
@keyframes textPulse {
  0%, 100% {
    opacity: 0.9;
    transform: scale(1);
  }
  50% {
    opacity: 1;
    transform: scale(1.05);
  }
}

// 新增：金额闪烁动画
@keyframes amountShine {
  0%, 100% {
    filter: brightness(1);
  }
  50% {
    filter: brightness(1.3);
  }
}

// 新增：中奖背景脉冲
@keyframes winBackgroundPulse {
  0%, 100% {
    opacity: 0.15;
  }
  50% {
    opacity: 0.25;
  }
}

// 大奖卡片翻转到背面
@keyframes flipToBack {
  0% {
    transform: rotateY(0);
  }
  100% {
    transform: rotateY(180deg);
  }
}

// 新增：神秘大奖光效
@keyframes mysteryGlow {
  0%, 100% {
    opacity: 0.6;
  }
  50% {
    opacity: 1;
  }
}

// 新增：星星闪烁效果
@keyframes sparkle {
  0%, 100% {
    opacity: 0.5;
    transform: scale(1) rotate(0deg);
  }
  50% {
    opacity: 1;
    transform: scale(1.2) rotate(180deg);
  }
}

/* 骨架屏样式 */
.loading-skeleton {
  padding: 16px 0;

  .skeleton-compact-header {
    height: 48px;
    background: linear-gradient(90deg, rgba(255, 255, 255, 0.1) 25%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.1) 75%);
    background-size: 200% 100%;
    border-radius: 12px;
    margin-bottom: 12px;
    animation: skeleton-loading 1.5s ease-in-out infinite;
  }

  .skeleton-cards {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 8px;

    @media (max-width: 768px) {
      grid-template-columns: repeat(5, 1fr);
      gap: 6px;
    }
  }

  .skeleton-card {
    aspect-ratio: 2.5/3.5;
    background: linear-gradient(90deg, rgba(255, 255, 255, 0.1) 25%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.1) 75%);
    background-size: 200% 100%;
    border-radius: 10px;
    animation: skeleton-loading 1.5s ease-in-out infinite;
  }
}

@keyframes skeleton-loading {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -200% 0;
  }
}
</style>
