<template>
  <div class="pc-layout">
    <div class="game-list-container">

      <div class="page-main-title" v-if="pageTitle">
        {{ pageTitle }}
      </div>

      <div class="lottery-header" v-if="gameData.length > 0">
        <div class="header-left-info">
          <div class="current-issue">
            <span class="label">{{ t('当前期') }}:</span>
            <span class="highlight">{{ nextIssue }}</span>
          </div>
          <div class="countdown-wrapper">
            <span class="label">{{ t('倒计时') }}:</span>
            <div class="digital-time">
              <span class="digit">{{ formattedCountdown.split(':')[0] }}</span>
              <span class="colon">:</span>
              <span class="digit">{{ formattedCountdown.split(':')[1] }}</span>
            </div>
          </div>
        </div>

        <div class="header-right-info">
          <div class="last-issue-info">
            <span class="label">{{ t('上一期') }}:</span>
            <span class="highlight">{{ issue }}</span>
          </div>
          <div class="last-open-codes" v-if="latestOpenCode.length > 0">
            <template v-if="isKuai3Dice({type: gameType, open_code: latestOpenCode.join(',')})">
              <div class="dice-wrapper">
                <span
                    class="dice-item mini-dice"
                    :class="['dice-' + num, (num == 1 || num == 4) ? 'dice-red' : '']"
                    v-for="(num, index) in latestOpenCode"
                    :key="'top-dice-'+index"
                >
                  <i class="dot" v-for="i in Number(num)" :key="i"></i>
                </span>
              </div>
            </template>
            <template v-else>
              <span class="code-ball mini" v-for="(code, idx) in latestOpenCode" :key="'top-code-'+idx" :style="getBallStyle(code, gameType)">
                {{ code }}
              </span>
            </template>
            <div class="other-codes" v-if="latestOpenCodeOther.length > 0">
              <span class="other-tag" v-for="(tag, idx) in latestOpenCodeOther" :key="'top-tag-'+idx">
                {{ tag }}
              </span>
            </div>
          </div>
          <el-button type="primary" plain size="small" @click="openHistoryDialog">{{ t('历史开奖') }}</el-button>
        </div>
      </div>

      <el-collapse v-model="mainActiveNames" class="dark-collapse" v-if="gameData.length > 0">
        <el-collapse-item v-for="(group, groupIndex) in gameData" :key="groupIndex" :name="group.gameplay">
          <template #title>
            <div class="group-header-content">
              <div class="header-left">
                <span class="group-title">{{ locale === 'zh' ? group.gameplay : (group.gameplay_en || group.gameplay) }}</span>
              </div>
            </div>
          </template>

          <div class="game-list">
            <div
                class="game-item"
                v-for="item in group.children"
                :key="item.id"
                :class="{ active: isSelected(item), 'is-disabled': !isKaipan }"
                @click="toggleBet(item)"
            >
              <span class="name">
                <template v-if="isDiceName(item)">
                  <div class="dice-wrapper">
                    <span
                        class="dice-item"
                        :class="['dice-' + num, (num == 1 || num == 4) ? 'dice-red' : '']"
                        v-for="(num, index) in item.name.split(',')"
                        :key="'dice-'+index"
                    >
                      <i class="dot" v-for="i in Number(num)" :key="i"></i>
                    </span>
                  </div>
                </template>
                <template v-else-if="[1, 3, 5].includes(Number(gameType)) && !isNaN(Number(item.name))">
                  <span class="code-ball" :style="getBetItemStyle(item.name, groupIndex)">
                    {{ item.name }}
                  </span>
                </template>
                <template v-else>
                  {{ locale === 'zh' ? item.name : (item.name_en || item.name) }}
                </template>
              </span>
              <span class="odds">{{ isKaipan ? item.odds : '--' }}</span>
            </div>
          </div>
        </el-collapse-item>
      </el-collapse>

      <div class="common-bottom"></div>
    </div>

    <div class="pc28-cart-container" :class="{ 'is-collapsed': !isCartExpanded }">

      <div class="cart-collapsed" v-if="!isCartExpanded" @click="isCartExpanded = true">
        <div class="custom-cart-icon">
          <el-icon class="icon-color" size="24"><ShoppingCart /></el-icon>
          <span class="custom-badge" v-if="selectedBets.length > 0">
            {{ selectedBets.length }}
          </span>
        </div>
        <div class="vertical-text">{{ t('彩票注单') }}</div>
      </div>

      <div class="cart-expanded" v-else>

        <div class="cart-header" @click="isCartExpanded = false">
          <div class="header-left">
            <el-icon class="pointer" size="20"><ArrowRight /></el-icon>
            <span class="header-badge" v-if="selectedBets.length > 0">{{ selectedBets.length }}</span>
            <span class="header-text">{{ t('彩票注单') }}</span>
          </div>
          <el-button link type="danger" @click.stop="clearAll" v-if="selectedBets.length > 0">
            {{ t('清空') }}
          </el-button>
        </div>

        <div v-if="selectedBets.length > 0" class="batch-stake-box">
          <span class="batch-label">{{ t('批量设置') }}</span>
          <div class="batch-input-wrapper">
            <el-input v-model="batchAmount" :placeholder="t('金额')" type="number" :disabled="!isKaipan" />
          </div>
          <el-button size="small" type="primary" @click.stop="applyBatchAmount" :disabled="!isKaipan">{{ t('确定') }}</el-button>
        </div>

        <div class="cart-body">
          <el-empty class="dark-empty" v-if="selectedBets.length === 0" :description="t('暂无彩票投注项')" />

          <div class="bet-list" v-else>
            <el-collapse v-model="cartActiveNames" class="cart-collapse">
              <el-collapse-item v-for="cartGroup in cartGroups" :key="cartGroup.id" :name="cartGroup.id">
                <template #title>
                  <div class="cart-group-title">
                    <span class="group-indicator"></span>
                    {{ locale === 'zh' ? cartGroup.name : cartGroup.name_en }}
                  </div>
                </template>

                <div class="bet-item" v-for="bet in cartGroup.selectedItems" :key="bet.id">
                  <div class="item-header">
                    <span class="team-names">
                      <template v-if="isDiceName(bet)">
                        <div class="dice-wrapper">
                          <span
                              class="dice-item"
                              :class="['dice-' + num, (num == 1 || num == 4) ? 'dice-red' : '']"
                              v-for="(num, index) in bet.name.split(',')"
                              :key="'dice-'+index"
                          >
                            <i class="dot" v-for="i in Number(num)" :key="i"></i>
                          </span>
                        </div>
                      </template>
                      <template v-else-if="[1, 3, 5].includes(Number(gameType)) && !isNaN(Number(bet.name))">
                        <span class="code-ball" :style="getBetItemStyle(bet.name, getBetGroupIndex(bet))">
                          {{ bet.name }}
                        </span>
                      </template>
                      <template v-else>
                        {{ locale === 'zh' ? bet.name : (bet.name_en || bet.name) }}
                      </template>
                    </span>
                    <span class="close-btn" @click.stop="removeBet(bet.id)" style="font-size: 16px;">×</span>
                  </div>

                  <div class="item-info">
                    <span class="type-name">{{ t('赔率') }}</span>
                    <span class="odds-val" :class="{'disabled-text': !isKaipan}">
                      {{ isKaipan ? Number(bet.odds).toFixed(2) : t('封盘') }}
                    </span>
                  </div>

                  <div class="limit-info" v-if="bet.mininum > 0 || bet.maxinum > 0">
                    <span>{{ t('限额') }}: {{ bet.mininum }} ~ {{ bet.maxinum }}</span>
                  </div>

                  <div class="stake-input-box">
                    <el-button class="stepper-btn" link @click="updateAmount(bet, -1)" :disabled="!isKaipan">-</el-button>
                    <el-input
                        v-model="bet.amount"
                        type="number"
                        class="stake-input"
                        :placeholder="t('本金')"
                        :disabled="!isKaipan"
                    />
                    <el-button class="stepper-btn" link @click="updateAmount(bet, 1)" :disabled="!isKaipan">+</el-button>
                  </div>

                  <div class="item-footer">
                    <div class="potential-win">
                      {{ t('预计可赢') }}: <span class="win-amount">{{ (Number(bet.amount || 0) * Number(bet.odds || 0)).toFixed(2) }}</span>
                    </div>
                  </div>
                </div>

              </el-collapse-item>
            </el-collapse>
          </div>
        </div>

        <div class="cart-footer" v-if="selectedBets.length > 0">
          <div class="total-odds-row">
            <span class="label">{{ t('总投注金额') }}</span>
            <span class="val">{{ totalAmount.toFixed(2) }}</span>
          </div>

          <el-button type="primary" class="w-full bet-action-btn" :disabled="!isKaipan || selectedBets.length === 0" @click="submit">
            {{ t('立即投注') }}
          </el-button>
        </div>

      </div>
    </div>

    <el-dialog v-model="isHistoryVisible" :title="t('历史开奖')" width="700px" custom-class="dark-theme-dialog" destroy-on-close top="5vh">
      <div style="width: 100%;height: 65vh;overflow-y: auto">
        <el-table :data="historyLottery" class="dark-table">
          <el-table-column prop="issue" :label="t('期数')" width="200">
            <template #default="scope">
              {{ t('第') }} {{ scope.row.issue }} {{ t('期') }}
            </template>
          </el-table-column>
          <el-table-column :label="t('开奖结果')">
            <template #default="scope">
              <div class="result-display">
                <div class="main-codes-row" v-if="scope.row.open_code">
                  <template v-if="isKuai3Dice(scope.row)">
                    <span
                        class="dice-item"
                        :class="['dice-' + num, (num == 1 || num == 4) ? 'dice-red' : '']"
                        v-for="(num, index) in String(scope.row.open_code).split(',')"
                        :key="'dice-'+index"
                    >
                      <i class="dot" v-for="i in Number(num)" :key="i"></i>
                    </span>
                  </template>
                  <template v-else>
                    <span class="code-ball" v-for="(code, idx) in String(scope.row.open_code).split(',')" :key="'code-'+idx" :style="getBallStyle(code, scope.row.type)">
                      {{ code }}
                    </span>
                  </template>
                </div>
                <div class="other-codes-row" v-if="scope.row.open_code_other">
                  <span class="other-tag" v-for="(tag, idx) in String(scope.row.open_code_other).split(',')" :key="'tag-'+idx">
                    {{ tag }}
                  </span>
                </div>
              </div>
            </template>
          </el-table-column>
        </el-table>
      </div>

      <div class="pagination-wrapper">
        <el-pagination
            v-model:current-page="historyPage"
            v-model:page-size="historyPageSize"
            :total="historyTotal"
            layout="total, prev, pager, next"
            @current-change="handleHistoryCurrentChange"
            background
        />
      </div>
    </el-dialog>

  </div>
</template>

<script setup>
import { ref, computed, watch, onMounted, onUnmounted } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import { getJisuGameList, submitJisuGameOrder, jisuGameLotteryStatus, jisuGameHistoryLottery } from '@/request/api';
import { ShoppingCart, ArrowRight } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import socket from '@/utils/websocket.js'

const { locale, t } = useI18n();
const route = useRoute();

const gameType = ref('');
const pageTitle = ref('');
const gameData = ref([]);
const selectedBets = ref([]);
const batchAmount = ref('');

const mainActiveNames = ref([]);

const isKaipan = ref(false);
const issue = ref('');
const nextIssue = ref('');
const countdown = ref(0);
const isHistoryVisible = ref(false);
let timer = null;

// 历史开奖相关变量
const historyLottery = ref([]);
const historyPage = ref(1);
const historyPageSize = ref(10);
const historyTotal = ref(0);

// 用于顶部显示的最新一期记录
const currentLatestRecord = ref(null);

const isCartExpanded = ref(true);
const cartActiveNames = ref([]);

const getCacheKey = () => `JISU_GAME_BETS_PC_TYPE_${gameType.value}`;

const cartGroups = computed(() => {
  const groups = [];
  gameData.value.forEach(main => {
    if (!main.children) return;
    const matches = selectedBets.value.filter(bet =>
        main.children.some(child => child.id === bet.id)
    );
    if (matches.length > 0) {
      groups.push({
        id: main.gameplay,
        name: main.gameplay,
        name_en: main.gameplay_en || main.gameplay,
        selectedItems: matches
      });
    }
  });
  return groups;
});

const formattedCountdown = computed(() => {
  if (countdown.value <= 0) return '00:00';
  const m = Math.floor(countdown.value / 60).toString().padStart(2, '0');
  const s = (countdown.value % 60).toString().padStart(2, '0');
  return `${m}:${s}`;
});

const latestOpenCode = computed(() => {
  if (currentLatestRecord.value && currentLatestRecord.value.open_code) {
    return String(currentLatestRecord.value.open_code).split(',');
  }
  return [];
});

const latestOpenCodeOther = computed(() => {
  if (currentLatestRecord.value && currentLatestRecord.value.open_code_other) {
    return String(currentLatestRecord.value.open_code_other).split(',');
  }
  return [];
});

const isSelected = (item) => {
  return selectedBets.value.some(bet => bet.id === item.id);
};

const isDiceName = (item) => {
  const tNum = Number(item.type || gameType.value);
  if ([6, 7].includes(tNum) && item.name) {
    return /^[1-6](,[1-6])*$/.test(item.name);
  }
  return false;
};

const isKuai3Dice = (row) => {
  const tNum = Number(row.type || gameType.value);
  if ([6, 7].includes(tNum) && row.open_code) {
    return String(row.open_code).split(',').length === 3;
  }
  return false;
};

const getBetGroupIndex = (bet) => {
  return gameData.value.findIndex(g => g.children && g.children.some(c => c.id === bet.id));
};

watch(cartGroups, (newGroups) => {
  newGroups.forEach(g => {
    if (!cartActiveNames.value.includes(g.id)) {
      cartActiveNames.value.push(g.id);
    }
  });
}, { deep: true, immediate: true });

function handleSocketMessage(e) {
  const res = e.detail;
  if (!res) return;

  if (res && res.message && String(res.message.type) === String(gameType.value)) {
    if (res.type === 'jisugame_kaipan') {
      isKaipan.value = true;
      fetchGameList();
      // 开盘时重置第一页拉取，以更新顶部最新开奖
      historyPage.value = 1;
      fetchHistoryLottery();
    } else if (res.type === 'jisugame_fengpan') {
      isKaipan.value = false;
    }
  }
}

onMounted(() => {
  if (route.query.type) {
    gameType.value = route.query.type;
  }

  if (route.query.title) {
    pageTitle.value = route.query.title;
  }

  const cached = localStorage.getItem(getCacheKey());
  if (cached) {
    try {
      selectedBets.value = JSON.parse(cached);
    } catch (e) {
      console.error('Failed to parse cached bets', e);
    }
  }

  fetchLotteryStatus();
  fetchGameList();

  // 初始化拉取一次用作顶部展示
  historyPage.value = 1;
  fetchHistoryLottery();

  socket.eventBus.addEventListener('onSocketMessage', handleSocketMessage);
});

onUnmounted(() => {
  if (timer) clearInterval(timer);

  socket.eventBus.removeEventListener('onSocketMessage', handleSocketMessage);
});

const fetchLotteryStatus = async () => {
  try {
    const res = await jisuGameLotteryStatus({ type: gameType.value });
    if (res?.data) {
      isKaipan.value = res.data.is_kaipan === 1;
    }
  } catch (error) {
    console.error('Failed to fetch lottery status:', error);
  }
};

const fetchGameList = async () => {
  try {
    const res = await getJisuGameList({ type: gameType.value });
    if (res?.data) {
      gameData.value = res.data.games || [];
      issue.value = res.data.issue || '';
      nextIssue.value = res.data.next_issue || '';
      countdown.value = res.data.countdown || 0;

      mainActiveNames.value = gameData.value.map(g => g.gameplay);

      startCountdown();
    }
  } catch (error) {
    console.error('Failed to fetch game list:', error);
  }
};

const fetchHistoryLottery = async () => {
  try {
    const res = await jisuGameHistoryLottery({
      type: gameType.value,
      page: historyPage.value,
      limit: historyPageSize.value
    });

    if (res?.data) {
      const resData = res.data.data || res.data;
      historyLottery.value = resData.list || [];
      historyTotal.value = resData.count || 0;

      // 如果请求的是第一页数据，将其第一条存为最新一期用作顶部展示
      if (historyPage.value === 1 && historyLottery.value.length > 0) {
        currentLatestRecord.value = historyLottery.value[0];
      }
    }
  } catch (error) {
    console.error('Failed to fetch history lottery:', error);
  }
};

// 打开历史开奖弹窗
const openHistoryDialog = () => {
  historyPage.value = 1;
  fetchHistoryLottery();
  isHistoryVisible.value = true;
};

// 切换页码
const handleHistoryCurrentChange = (val) => {
  historyPage.value = val;
  fetchHistoryLottery();
};

const startCountdown = () => {
  if (timer) clearInterval(timer);
  timer = setInterval(() => {
    if (countdown.value > 0) {
      countdown.value--;
    } else {
      clearInterval(timer);
    }
  }, 1000);
};

watch(selectedBets, (newVal) => {
  if (gameType.value) {
    localStorage.setItem(getCacheKey(), JSON.stringify(newVal));
  }
}, { deep: true });

const toggleBet = (item) => {
  if (!isKaipan.value) {
    ElMessage.warning(t('已封盘'));
    return;
  }

  const index = selectedBets.value.findIndex(bet => bet.id === item.id);
  if (index > -1) {
    selectedBets.value.splice(index, 1);
  } else {
    const defaultAmount = (item.mininum && item.mininum > 0) ? item.mininum : '';
    selectedBets.value.push({ ...item, amount: defaultAmount });
    isCartExpanded.value = true;
  }
};

const removeBet = (id) => {
  const index = selectedBets.value.findIndex(bet => bet.id === id);
  if (index > -1) {
    selectedBets.value.splice(index, 1);
  }
};

const clearAll = () => {
  selectedBets.value = [];
  batchAmount.value = '';
};

const applyBatchAmount = () => {
  if (!isKaipan.value) return;
  const amount = Number(batchAmount.value);
  if (amount > 0) {
    selectedBets.value.forEach(bet => {
      bet.amount = amount;
    });
  }
};

const updateAmount = (bet, step) => {
  if (!isKaipan.value) return;
  const current = Number(bet.amount) || 0;
  const next = current + step;
  if (next >= 0) {
    bet.amount = next;
  }
};

const totalAmount = computed(() => {
  return selectedBets.value.reduce((total, bet) => {
    return total + (Number(bet.amount) || 0);
  }, 0);
});

const submit = () => {
  if (!isKaipan.value || selectedBets.value.length === 0) return;

  const payload = {
    data: selectedBets.value.map(bet => ({
      id: bet.id,
      amount: Number(bet.amount) || 0
    }))
  };

  submitJisuGameOrder(payload).then(() => {
    clearAll();
  });
};

const getBallStyle = (code, type) => {
  const currentType = type || gameType.value;
  if ([1, 3, 5].includes(Number(currentType))) {
    const num = Number(code);
    const colors = [
      'linear-gradient(135deg, #F1C40F, #F39C12)',
      'linear-gradient(135deg, #3498DB, #2980B9)',
      'linear-gradient(135deg, #5D6D7E, #34495E)',
      'linear-gradient(135deg, #E67E22, #D35400)',
      'linear-gradient(135deg, #1ABC9C, #16A085)',
      'linear-gradient(135deg, #9B59B6, #8E44AD)',
      'linear-gradient(135deg, #BDC3C7, #95A5A6)',
      'linear-gradient(135deg, #E74C3C, #C0392B)',
      'linear-gradient(135deg, #A93226, #7B241C)',
      'linear-gradient(135deg, #2ECC71, #27AE60)'
    ];

    if (num >= 1 && num <= 10) {
      return {
        background: colors[num - 1],
        color: [1, 7].includes(num) ? '#141414' : '#ffffff'
      };
    }
  }
  return {};
};

const getBetItemStyle = (name, groupIndex) => {
  if (groupIndex === 0) {
    return {
      background: 'linear-gradient(135deg, #3498DB, #2980B9)',
      color: '#ffffff'
    };
  } else {
    return getBallStyle(name, gameType.value);
  }
};

</script>

<style scoped lang="scss">
/* ====== 左侧全局变量 ====== */
$primary-color: #f8b932;
$bg-main: #141414;
$bg-sidebar: #1e1e1e;
$border-color: #2a2a2a;
$text-main: #e0e0e0;
$text-gray: #7a7a7a;

/* ====== 右侧购物车新样式变量 ====== */
$cart-bg-sidebar: #1e1e1e;
$cart-bg-sidebar-hover: #2a2a2a;
$cart-bg-main: #141414;
$cart-border-color: rgba(255, 255, 255, 0.08);
$cart-text-primary: #e5e5e5;
$cart-text-secondary: #999;
$cart-main-color: #f8b932;

/* ====== 整体布局 ====== */
.pc-layout {
  display: flex;
  width: 100%;
  height: 100%;
  background-color: $bg-main;
  overflow: hidden;
}

/* ====== 左侧：赛事及盘口区 ====== */
.game-list-container {
  flex: 1;
  padding: 20px;
  overflow-y: auto;

  /* 页面大标题样式 */
  .page-main-title {
    font-size: 22px;
    font-weight: bold;
    color: $primary-color;
    margin-bottom: 20px;
    display: flex;
    align-items: center;

    &::before {
      content: '';
      display: inline-block;
      width: 4px;
      height: 22px;
      background-color: $primary-color;
      margin-right: 12px;
      border-radius: 2px;
    }
  }

  /* 顶部开奖信息栏 */
  .lottery-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    background-color: $bg-sidebar;
    padding: 16px 20px;
    border-radius: 6px;
    border: 1px solid $border-color;
    margin-bottom: 20px;
    flex-wrap: wrap;
    gap: 16px;

    .header-left-info, .header-right-info {
      display: flex;
      align-items: center;
      gap: 24px;
      flex-wrap: wrap;
    }

    .label {
      font-size: 14px;
      color: $text-gray;
      margin-right: 8px;
    }

    .highlight {
      font-size: 16px;
      color: $text-main;
      font-weight: bold;
    }

    .digital-time {
      display: inline-flex;
      align-items: center;
      gap: 4px;

      .digit {
        background: #2a2a2a;
        color: $primary-color;
        padding: 4px 8px;
        border-radius: 4px;
        font-weight: bold;
        font-size: 16px;
        letter-spacing: 1px;
        border: 1px solid #333;
      }
      .colon {
        color: $primary-color;
        font-weight: bold;
        font-size: 16px;
        animation: blink 1s infinite;
      }
    }

    .last-open-codes {
      display: flex;
      align-items: center;
      gap: 6px;

      .code-ball {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 24px;
        height: 24px;
        background: #333; /* 默认深色底 */
        color: #fff;
        border-radius: 50%;
        font-weight: bold;
        font-size: 12px;
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
      }

      .other-codes {
        display: flex;
        gap: 4px;
        margin-left: 6px;

        .other-tag {
          background-color: rgba(255, 255, 255, 0.08);
          border: 1px solid rgba(255, 255, 255, 0.15);
          color: #e0e0e0;
          padding: 2px 6px;
          border-radius: 4px;
          font-size: 12px;
        }
      }
    }
  }

  @keyframes blink {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.3; }
  }

  /* 左侧折叠面板深色模式样式 */
  :deep(.dark-collapse) {
    border-top: none;
    border-bottom: none;

    .el-collapse-item {
      background: $bg-sidebar;
      border: 1px solid $border-color;
      border-radius: 6px;
      margin-bottom: 16px;
      overflow: hidden;
    }

    .el-collapse-item__header {
      background: $bg-sidebar;
      border-bottom: 1px solid $border-color;
      color: #fff;
      height: 48px;
      padding: 0 16px;

      &.is-active {
        border-bottom-color: $border-color;
      }
    }

    .el-collapse-item__wrap {
      background: transparent;
      border-bottom: none;
    }

    .el-collapse-item__content {
      padding-bottom: 0;
    }

    .group-header-content {
      display: flex;
      align-items: center;
      width: 100%;

      .header-left {
        display: flex;
        align-items: center;

        &::before {
          content: '';
          display: inline-block;
          width: 3px;
          height: 14px;
          background-color: $primary-color;
          margin-right: 10px;
          border-radius: 1.5px;
        }

        .group-title {
          font-size: 14px;
          font-weight: bold;
        }
      }
    }
  }

  .game-list {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    padding: 16px;
    background-color: rgba(0, 0, 0, 0.1);

    .game-item {
      flex: 1 1 calc(25% - 12px);
      min-width: 140px;
      background: $bg-main;
      border: 1px solid $border-color;
      border-radius: 4px;
      padding: 14px;
      display: flex;
      justify-content: space-between;
      align-items: center;
      cursor: pointer;
      transition: all 0.2s ease;

      &:hover:not(.is-disabled) {
        border-color: #555;
      }

      &.active {
        background-color: $primary-color;
        border-color: $primary-color;
        .name { color: #000; font-weight: bold; }
        .odds { color: #000; }
      }

      &.is-disabled {
        cursor: not-allowed;
        opacity: 0.5;
        background-color: rgba(255, 255, 255, 0.02);
      }

      .name {
        font-size: 14px;
        color: $text-main;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;

        .code-ball {
          display: inline-flex;
          align-items: center;
          justify-content: center;
          width: 28px;
          height: 28px;
          border-radius: 50%;
          font-weight: bold;
          font-size: 14px;
          box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
          background-color: #333;
          color: #fff;
        }
      }

      .odds {
        color: $primary-color;
        font-weight: bold;
        font-size: 15px;
      }
    }
  }
}

/* ====================================================
   右侧购物车
   ==================================================== */
.pc28-cart-container {
  height: 100%;
  background-color: $cart-bg-sidebar;
  border-left: 1px solid $cart-border-color;
  display: flex;
  flex-direction: column;
  transition: width 0.3s ease;
  position: relative;
  overflow: visible;

  &.is-collapsed { width: 50px !important; }
  &:not(.is-collapsed) { width: 320px !important; }
}

.cart-collapsed {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: 20px;
  cursor: pointer;
  transition: background 0.3s;
  &:hover { background-color: $cart-bg-sidebar-hover; }

  .custom-cart-icon {
    position: relative;
    margin-bottom: 20px;
    display: flex; justify-content: center; align-items: center;
    .icon-color { color: $cart-main-color; }
    .custom-badge {
      position: absolute; top: -6px; right: -10px;
      color: #fff; background-color: $cart-main-color; font-size: 12px;
      padding: 2px 5px; line-height: 1; border-radius: 10px; border: 2px solid $cart-bg-sidebar; font-weight: bold; transform: scale(0.9);
    }
  }
  .vertical-text { writing-mode: vertical-rl; letter-spacing: 4px; font-weight: bold; color: $cart-text-primary; }
}

.cart-expanded {
  display: flex;
  flex-direction: column;
  height: 100%;

  .cart-header {
    height: 50px; display: flex; justify-content: space-between; align-items: center; padding: 0 16px;
    border-bottom: 1px solid $cart-border-color; background-color: $cart-bg-sidebar; cursor: pointer; transition: background 0.2s;
    &:hover { background-color: $cart-bg-sidebar-hover; }
    .header-left {
      display: flex; align-items: center; gap: 8px; color: $cart-text-primary;
      .pointer { color: $cart-text-secondary; display: flex; align-items: center; transition: transform 0.2s; }
      .header-badge { color: #000; background-color: $cart-main-color; font-size: 12px; height: 18px; line-height: 18px; padding: 0 6px; border-radius: 9px; font-weight: bold; }
      .header-text { font-weight: bold; color: $cart-text-primary; font-size: 15px; }
    }
  }

  .batch-stake-box {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 12px;
    background-color: $cart-bg-sidebar;
    border-bottom: 1px solid $cart-border-color;

    .batch-label {
      font-size: 13px;
      color: $cart-text-primary;
      white-space: nowrap;
    }

    .batch-input-wrapper {
      flex: 1;
      margin: 0 10px;

      :deep(.el-input__wrapper) {
        background-color: #1a1a1a !important;
        box-shadow: 0 0 0 1px $cart-border-color inset !important;
        height: 28px;
        padding: 0;

        &.is-disabled {
          background-color: transparent !important;
        }
      }
      :deep(.el-input__inner) {
        color: $cart-text-primary !important;
        text-align: center;
        font-size: 13px;
      }
    }

    .el-button--primary {
      background-color: $cart-main-color;
      border-color: $cart-main-color;
      color: #000;
      font-weight: bold;
      &:hover { opacity: 0.9; }

      &.is-disabled {
        background-color: #555;
        border-color: #555;
        color: #999;
      }
    }
  }

  .cart-body {
    flex: 1; overflow-y: auto; padding: 12px; background-color: $cart-bg-main;

    :deep(.dark-empty .el-empty__description p) { color: $cart-text-secondary; }

    .cart-collapse {
      border-top: none;
      border-bottom: none;

      :deep(.el-collapse-item__header) {
        background-color: transparent;
        color: $cart-text-secondary;
        border-bottom: none;
        height: 36px;
        line-height: 36px;
      }

      :deep(.el-collapse-item__wrap) {
        background-color: transparent;
        border-bottom: none;
      }

      :deep(.el-collapse-item__content) {
        padding-bottom: 0;
      }

      .cart-group-title {
        display: flex;
        align-items: center;
        font-size: 13px;
        font-weight: bold;
        color: #bbb;
        width: 100%;

        .group-indicator {
          display: inline-block;
          width: 3px;
          height: 12px;
          background-color: $cart-main-color;
          margin-right: 8px;
          border-radius: 2px;
        }
      }
    }

    .bet-item {
      position: relative; background-color: $cart-bg-sidebar; border-radius: 8px; padding: 12px; margin-bottom: 12px; border: 1px solid $cart-border-color;
      transition: border-color 0.3s;
      &:hover { border-color: rgba(248, 185, 50, 0.3); }

      .item-header {
        display: flex; justify-content: space-between; margin-bottom: 8px;
        .team-names {
          font-weight: bold; font-size: 14px; color: $cart-text-primary;

          .code-ball {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 24px;
            height: 24px;
            border-radius: 50%;
            font-weight: bold;
            font-size: 12px;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
            background-color: #333;
            color: #fff;
          }
        }
        .close-btn { cursor: pointer; z-index: 11; position: relative; color: $cart-text-secondary; &:hover { color: #f56c6c; } }
      }

      .item-info {
        display: flex; justify-content: space-between; font-size: 13px; margin-bottom: 6px;
        .type-name { color: $cart-text-secondary; }
        .odds-val {
          font-weight: bold; color: $cart-main-color; font-size: 16px;
          &.disabled-text {
            color: #999;
            font-weight: normal;
          }
        }
      }

      .limit-info {
        display: flex; justify-content: space-between; font-size: 12px; color: #777; margin-bottom: 12px;
      }

      .stake-input-box {
        display: flex; align-items: center; border: 1px solid $cart-border-color; border-radius: 4px; height: 32px; overflow: hidden; background: #1a1a1a;
        .stepper-btn {
          height: 100%; width: 32px; border: none; background: #262626; color: $cart-text-primary; margin: 0; padding: 0; font-size: 16px; cursor: pointer;
          &:hover:not(:disabled) { color: $cart-main-color; }
          &:disabled { color: #555; cursor: not-allowed; }
        }
        :deep(.el-input__wrapper) { box-shadow: none !important; background: transparent !important; padding: 0; }
        :deep(.el-input__inner) { text-align: center; font-weight: bold; color: $cart-text-primary !important; font-family: monospace; }
        :deep(.el-input.is-disabled .el-input__inner) { color: #666 !important; }
      }

      .item-footer {
        margin-top: 10px; text-align: right; font-size: 12px; color: $cart-text-secondary;
        .potential-win .win-amount { color: #67c23a; font-weight: bold; margin-left: 4px; font-size: 14px; }
      }
    }

    /* 滚动条美化 */
    &::-webkit-scrollbar { width: 6px; }
    &::-webkit-scrollbar-track { background: transparent; }
    &::-webkit-scrollbar-thumb { background: #333; border-radius: 10px; }
    &::-webkit-scrollbar-thumb:hover { background: #555; }
  }

  .cart-footer {
    padding: 16px; border-top: 1px solid $cart-border-color; background: $cart-bg-sidebar;
    .total-odds-row {
      display: flex; justify-content: space-between; margin-bottom: 12px; font-size: 14px; color: $cart-text-primary;
      .label { font-weight: bold; }
      .val { color: $cart-main-color; font-weight: bold; font-size: 18px; }
    }
    .bet-action-btn {
      width: 100%; height: 44px; font-size: 16px; font-weight: bold; color: #000; background-color: $cart-main-color; border-color: $cart-main-color;
      &:hover:not(:disabled) { opacity: 0.9; }
      &:disabled {
        background-color: #555;
        border-color: #555;
        color: #999;
      }
    }
  }
}

/* 移除数字输入框滚轮原生箭头 */
:deep(.stake-input input::-webkit-outer-spin-button),
:deep(.stake-input input::-webkit-inner-spin-button),
:deep(.batch-input-wrapper input::-webkit-outer-spin-button),
:deep(.batch-input-wrapper input::-webkit-inner-spin-button) {
  -webkit-appearance: none;
  margin: 0;
}
:deep(.stake-input input[type="number"]),
:deep(.batch-input-wrapper input[type="number"]) {
  -moz-appearance: textfield;
}

/* ====================================================
   历史开奖弹窗样式扩展
   ==================================================== */
:deep(.dark-theme-dialog) {
  background-color: #1e1e1e;
  .el-dialog__title {
    color: #e0e0e0;
    font-weight: bold;
  }
  .el-dialog__header {
    border-bottom: 1px solid #2a2a2a;
    margin-right: 0;
  }
}

/* 开奖号码与其它结果的富文本排版样式 */
.result-display {
  display: block; /* 保证上下结构 */
  padding: 8px 0;

  .main-codes-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;

    .code-ball {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 28px;
      height: 28px;
      background: #333; /* 默认底色 */
      color: #fff;
      border-radius: 50%;
      font-weight: bold;
      font-size: 14px;
      box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
    }
  }

  .other-codes-row {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 8px; /* 通过外边距分隔到第二行 */

    .other-tag {
      background-color: rgba(255, 255, 255, 0.08);
      border: 1px solid rgba(255, 255, 255, 0.15);
      color: #e0e0e0;
      padding: 2px 8px;
      border-radius: 4px;
      font-size: 12px;
    }
  }
}

/* 弹窗底部分页样式定制 */
.pagination-wrapper {
  margin-top: 20px;
  display: flex;
  justify-content: flex-end;
  padding-right: 10px;

  :deep(.el-pagination.is-background .el-pager li:not(.is-active)) {
    background-color: #2a2a2a;
    color: #e0e0e0;
  }
  :deep(.el-pagination.is-background .el-pager li.is-active) {
    background-color: $primary-color;
    color: #000;
  }
  :deep(.el-pagination.is-background .btn-next),
  :deep(.el-pagination.is-background .btn-prev) {
    background-color: #2a2a2a;
    color: #e0e0e0;
  }
  :deep(.el-pagination__total) {
    color: #e0e0e0;
  }
}

/* 骰子相关样式 */
.dice-wrapper {
  display: inline-flex;
  gap: 4px;
  align-items: center;
}

.dice-item {
  width: 25px;
  height: 25px;
  background-color: #ffffff;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  display: grid;
  padding: 2px;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  box-shadow: inset 0 -2px 0 rgba(0,0,0,0.05), 0 1px 3px rgba(0,0,0,0.1);
  box-sizing: border-box;
  flex-shrink: 0;

  .dot {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background-color: #303133;
    justify-self: center;
    align-self: center;
  }

  &.dice-1 { .dot:nth-child(1) { grid-column: 2; grid-row: 2; width: 5px; height: 5px; } }
  &.dice-2 { .dot:nth-child(1) { grid-column: 1; grid-row: 1; } .dot:nth-child(2) { grid-column: 3; grid-row: 3; } }
  &.dice-3 { .dot:nth-child(1) { grid-column: 1; grid-row: 1; } .dot:nth-child(2) { grid-column: 2; grid-row: 2; } .dot:nth-child(3) { grid-column: 3; grid-row: 3; } }
  &.dice-4 {
    .dot:nth-child(1) { grid-column: 1; grid-row: 1; }
    .dot:nth-child(2) { grid-column: 3; grid-row: 1; }
    .dot:nth-child(3) { grid-column: 1; grid-row: 3; }
    .dot:nth-child(4) { grid-column: 3; grid-row: 3; }
  }
  &.dice-5 {
    .dot:nth-child(1) { grid-column: 1; grid-row: 1; }
    .dot:nth-child(2) { grid-column: 3; grid-row: 1; }
    .dot:nth-child(3) { grid-column: 2; grid-row: 2; }
    .dot:nth-child(4) { grid-column: 1; grid-row: 3; }
    .dot:nth-child(5) { grid-column: 3; grid-row: 3; }
  }
  &.dice-6 {
    .dot:nth-child(1) { grid-column: 1; grid-row: 1; }
    .dot:nth-child(2) { grid-column: 1; grid-row: 2; }
    .dot:nth-child(3) { grid-column: 1; grid-row: 3; }
    .dot:nth-child(4) { grid-column: 3; grid-row: 1; }
    .dot:nth-child(5) { grid-column: 3; grid-row: 2; }
    .dot:nth-child(6) { grid-column: 3; grid-row: 3; }
  }

  &.dice-red .dot {
    background-color: #f56c6c;
  }
}

:deep(.dark-table) {
  background-color: transparent !important;
  --el-table-border-color: #2a2a2a;
  --el-table-header-bg-color: #141414;
  --el-table-header-text-color: #999;
  --el-table-tr-bg-color: transparent;
  --el-table-row-hover-bg-color: #2a2a2a;

  th.el-table__cell {
    background-color: var(--el-table-header-bg-color) !important;
    border-bottom: 1px solid var(--el-table-border-color);
  }

  tr {
    background-color: transparent !important;
  }

  td.el-table__cell {
    border-bottom: 1px dashed var(--el-table-border-color);
    color: #e0e0e0;
  }

  .el-table__inner-wrapper::before {
    display: none;
  }
}

/* ====================================================
   响应式适配
   ==================================================== */
@media screen and (max-width: 1600px) {
  .pc28-cart-container:not(.is-collapsed) { width: 280px !important; }
  .pc28-cart-container .cart-expanded .cart-header { height: 44px; padding: 0 12px; }
  .pc28-cart-container .cart-expanded .cart-header .header-text { font-size: 14px; }
  .pc28-cart-container .cart-expanded .cart-body { padding: 10px; }
  .pc28-cart-container .cart-expanded .cart-body .bet-item { padding: 10px; margin-bottom: 10px; }
  .pc28-cart-container .cart-expanded .cart-body .bet-item .item-header .team-names { font-size: 13px; }
  .pc28-cart-container .cart-expanded .cart-body .bet-item .item-info .odds-val { font-size: 15px; }
  .pc28-cart-container .cart-expanded .cart-footer { padding: 12px; }
  .pc28-cart-container .cart-expanded .cart-footer .bet-action-btn { height: 40px; font-size: 15px; }
}

@media screen and (max-width: 1350px) {
  .pc28-cart-container:not(.is-collapsed) { width: 250px !important; }
  .pc28-cart-container .cart-expanded .cart-header .header-text { font-size: 13px; }
  .pc28-cart-container .cart-expanded .cart-body .bet-item .item-info .type-name { font-size: 12px; }
  .pc28-cart-container .cart-expanded .cart-body { padding: 8px; }
  .pc28-cart-container .cart-expanded .cart-body .bet-item { padding: 8px; }
  .pc28-cart-container .cart-expanded .cart-body .bet-item .item-header .team-names { font-size: 12px; }
  .pc28-cart-container .cart-expanded .cart-body .bet-item .item-info { font-size: 12px; }
  .pc28-cart-container .cart-expanded .cart-body .bet-item .item-info .odds-val { font-size: 14px; }
  .pc28-cart-container .cart-expanded .cart-body .bet-item .limit-info { font-size: 11px; margin-bottom: 8px; }
  .pc28-cart-container .cart-expanded .cart-body .bet-item .stake-input-box { height: 28px; }
  .pc28-cart-container .cart-expanded .cart-body .bet-item .item-footer { font-size: 11px; }
  .pc28-cart-container .cart-expanded .cart-body .bet-item .item-footer .potential-win .win-amount { font-size: 13px; }
  .pc28-cart-container .cart-expanded .cart-footer { padding: 10px; }
  .pc28-cart-container .cart-expanded .cart-footer .total-odds-row { font-size: 12px; margin-bottom: 8px; }
  .pc28-cart-container .cart-expanded .cart-footer .total-odds-row .val { font-size: 14px; }
  .pc28-cart-container .cart-expanded .cart-footer .bet-action-btn { height: 36px; font-size: 14px; }
  .pc28-cart-container .cart-expanded .cart-header { height: 40px; padding: 0 10px; }
}

@media screen and (max-width: 1200px) {
  .pc28-cart-container:not(.is-collapsed) { width: 230px !important; }
  .pc28-cart-container.is-collapsed { width: 46px !important; }
  .pc28-cart-container .cart-expanded .cart-body .bet-item .item-header .team-names { font-size: 11px; }
  .pc28-cart-container .cart-expanded .cart-header .header-text { font-size: 11px !important; }
  .pc28-cart-container .cart-expanded .cart-body .bet-item .item-info .type-name { font-size: 11px; }
  .pc28-cart-container .cart-expanded .cart-body .bet-item .limit-info { font-size: 11px !important; }
  .pc28-cart-container .cart-expanded .cart-body .bet-item .item-info .odds-val { font-size: 11px !important; }
  .pc28-cart-container .cart-expanded .cart-body .bet-item .item-footer .potential-win { font-size: 11px !important; }
  .pc28-cart-container .cart-expanded .cart-body .bet-item .item-footer .potential-win .win-amount { font-size: 11px !important; }
  .pc28-cart-container .cart-expanded .cart-body .bet-item .item-header { margin-bottom: 6px !important; }
  .pc28-cart-container .cart-expanded .cart-body .bet-item .item-info { margin-bottom: 5px !important; }
  .pc28-cart-container .cart-expanded .cart-body .bet-item .stake-input-box { height: 24px !important; }
  .pc28-cart-container .cart-expanded .cart-footer .total-odds-row { font-size: 11px; margin-bottom: 6px; }
  .pc28-cart-container .cart-expanded .cart-footer .total-odds-row .val { font-size: 12px; }
  .pc28-cart-container .cart-expanded .cart-footer .bet-action-btn { height: 32px; font-size: 14px; }
  .pc28-cart-container .cart-expanded .cart-header { height: 38px; }
  .pc28-cart-container .cart-expanded .cart-header .header-badge { font-size: 11px !important; height: 16px !important; line-height: 16px !important; }
}
</style>