<script setup lang="ts">
import { ref, watch, onMounted, onUnmounted } from 'vue'
import DesignStage from '../../../components/DesignStage.vue'
import type Player from '../../../commons/player.ts'
import { $format_str, $is_local_mode } from '@/commons/utils.ts'
import { assetUrl, cssAssetUrl } from '@/commons/assets.ts'
import { playApplauseMusic, stopApplauseMusic } from '@/commons/music'

const props = defineProps<{
    rankList: Player[];
    horseBoosts: Record<string, number>;
}>();

const emit = defineEmits<{
    start: [];
    next: [];
    back: [];
}>();

const RANK_LIMIT = 10;
const designStage = ref<InstanceType<typeof DesignStage> | null>(null);
const gameStarted = ref(false);
const isGameRunning = ref(false);
const showResult = ref(false);

const imageUrls = {
    bg: cssAssetUrl('game3/bg2.webp'),
    logo: cssAssetUrl('game1/logo.png'),
    title: cssAssetUrl('game3/title2.webp'),
    username: cssAssetUrl('game4/username.svg'),
    defaultAvatar: assetUrl('game4/default-avator.svg'),
    resultBg: cssAssetUrl('game6/bg3.png'),
    resultTitle: cssAssetUrl('game6/title3.png'),
    podium: cssAssetUrl('game6/podium.png'),
    vip: cssAssetUrl('game6/vip.png'),
    avatar: cssAssetUrl('avatar-yellow.png'),
    avatarAnimation: cssAssetUrl('avatar-yellow_animation.png'),
    rankIcon: cssAssetUrl('game6/no4.png'),
    next: cssAssetUrl('game1/next.png'),
    back: cssAssetUrl('game1/back.png'),
};

// ========== 马匹帧配置（只用 ma1/ma2/ma3，不用 ma4） ==========
const HORSE_SIZE = 280;
const HORSE_START_X = -100;
const HORSE_END_X = 1920;
const HORSE_Y_OFFSET = 50;  // 马匹整体偏移

const horseFrameConfigs = [
    { type: 1, dir: 'game3/ma1', prefix: '1ma_', startIndex: 24, count: 12 },
    { type: 2, dir: 'game3/ma2', prefix: '2ma_', startIndex: 24, count: 12 },
    { type: 3, dir: 'game3/ma3', prefix: '3ma_', startIndex: 12, count: 14 },
];

const HORSE_TYPES = [1, 2, 3] as const;

const horseFrames: Record<number, string[]> = {};
const horseFrameCount: Record<number, number> = {};
for (const config of horseFrameConfigs) {
    horseFrames[config.type] = Array.from({ length: config.count }, (_, i) =>
        assetUrl(`${config.dir}/${config.prefix}${String(config.startIndex + i).padStart(5, '0')}.png`),
    );
    horseFrameCount[config.type] = config.count;
}

interface Horse {
    id: string;
    horseType: number;
    lane: number;
    frameIndex: number;
    frameTimer: number;
    x: number;          // 像素位置（用于渲染 translateX）
    xPercent: number;   // 进度百分比 0~100（对齐 game4 时间驱动模型）
    boost: number;      // 瞬时加速值，每帧衰减
    nickname: string;
    avatar: string;
    /** 稳定标识，优先 wechat_id 再 userid，用于匹配 WebSocket 数据 */
    playerKey: string;
}

const horses = ref<Horse[]>([]);
let horseIdCounter = 0;

// ========== 排名相关 ==========
const emptyPlayer = (index: number): Player => ({
    wechat_id: `empty-${index}`,
    nickname: '-',
    avatar: '',
    score: 0,
});

const list = ref<Player[]>(Array.from({ length: RANK_LIMIT }, (_, index) => emptyPlayer(index)));

const updateRankList = (rankList: Player[]) => {
    const next = Array.from({ length: RANK_LIMIT }, (_, index) => rankList[index] ?? emptyPlayer(index));
    list.value = next;
};

// ========== 瞬时加速脉冲（对齐 game4 detectScoreChanges） ==========
const transientBoosts = ref<Record<string, number>>({});
const prevScores: Record<string, number> = {};

/** 获取玩家的稳定标识（优先 wechat_id，其次 userid，最后用 avatar 回退） */
const getPlayerKey = (player: Player, index = 0): string => {
    const key = player?.wechat_id || player?.userid || '';
    if (key && !key.startsWith('empty-')) return key;
    // 如果 WS 数据没有ID字段，用 avatar URL 作为唯一标识（每个用户头像各不相同）
    if (player?.nickname && player.nickname !== '-' && player.nickname !== '虚位以待' && player?.avatar) {
        return `avt:${player.avatar}`;
    }
    return `empty-${index}`;
};

/** 检测 rankList 中哪些玩家 score 增长了 → 触发瞬时加速脉冲 */
const detectScoreChanges = (players: Player[]) => {
    if (!players || players.length === 0) return;

    let hasNewBoost = false;
    const updated = { ...transientBoosts.value };

    players.forEach((p, index) => {
        const key = getPlayerKey(p, index);
        if (key.startsWith('empty-')) return;
        const newScore = Number(p.score ?? 0);
        if (isNaN(newScore)) return;
        const prev = prevScores[key] ?? 0;

        if (newScore > prev) {
            const current = updated[key] || 0;
            // boost 量与分数增量成正比，让领先者拉得更快，制造视觉差距
            const delta = newScore - prev;
            updated[key] = Math.min(current + BOOST_PULSE * Math.max(delta, 1), MAX_BOOST);
            hasNewBoost = true;
            console.log(`[game3 Rank1View] 🚀 ${p.nickname} score ${prev}→${newScore} (Δ${delta}), boost: ${updated[key].toFixed(1)}`);
        }

        prevScores[key] = newScore;
    });

    if (hasNewBoost) {
        transientBoosts.value = updated;
    }
};

watch(
    () => props.rankList,
    (rankList) => {
        // 本地模式：无 WS 数据时不覆盖本地模拟数据
        if ($is_local_mode() && (!rankList || rankList.length === 0)) return;
        console.log('[game3 Rank1View] websocket rankList 数据:', JSON.parse(JSON.stringify(rankList?.slice(0, 3))));
        updateRankList(rankList);
        // 检测积分增长 → 触发瞬时加速脉冲（对齐 game4）
        detectScoreChanges(rankList);
        // 游戏进行中，实时更新马匹玩家列表（处理加入/离开）
        if (isGameRunning.value) {
            updateHorses(rankList);
        }
    },
    { immediate: true, deep: true },
);

// 直接监听 list，确保游戏运行时任何 list 变化都触发马匹刷新
watch(
    list,
    (newList) => {
        const validCount = newList.filter(p => getPlayerKey(p).length > 0 && !getPlayerKey(p).startsWith('empty-')).length;
        console.log('[game3 Rank1View] list 变化, 有效玩家数:', validCount, 'isGameRunning:', isGameRunning.value);
        if (isGameRunning.value && validCount > 0) {
            updateHorses(newList);
        }
    },
    { deep: true },
);

watch(
    () => props.horseBoosts,
    (boosts) => {
        if (!boosts || Object.keys(boosts).length === 0) return;

        let hasNew = false;
        const updated = { ...transientBoosts.value };
        Object.entries(boosts).forEach(([id, val]) => {
            const score = Number(val ?? 0);
            if (score > 0) {
                const current = updated[id] || 0;
                updated[id] = Math.min(current + BOOST_PULSE, MAX_BOOST);
                hasNew = true;
            }
        });

        if (hasNew) {
            transientBoosts.value = updated;
            console.log('[game3 Rank1View] horseBoosts 触发加速:', JSON.parse(JSON.stringify(transientBoosts.value)));
        }
    },
    { deep: true },
);

// ========== 速度基准（对齐 game4 时间驱动模型） ==========
// 60s 游戏内，即使满加速也最多跑 ~75% 路程，确保马匹始终可见
const TOTAL_DISTANCE_PX = HORSE_END_X - HORSE_START_X;  // 2200px
const BASE_DURATION_SEC = 200;  // 基准时长 200s，即无加速时跑完全程需 200s
const BASE_SPEED_PX_PER_SEC = TOTAL_DISTANCE_PX / BASE_DURATION_SEC;  // 11.0px/s

// 瞬时加速脉冲机制（对齐 game4）
const BOOST_PULSE = 0.15;    // 每次 score 增长对应的额外速度倍率（从 0.3 下调，减缓加速累积）
const MAX_BOOST = 1.5;       // 最大加速倍率（从 3.0 下调，确保满速时 80s 才能跑完 2200px）
const BOOST_DECAY = 0.990;   // 每帧衰减系数（微微加快衰减，避免 boost 持续高位）

// ========== 马匹动画循环 (RAF 驱动：时间驱动位移 + 帧动画) ==========
let horseRafId: number | undefined;
let horseLastTs = 0;
const HORSE_FRAME_TICK_MS = 48;

const startHorseLoop = () => {
    stopHorseLoop();
    horseLastTs = 0;
    let logCounter = 0;

    const tick = (ts: number) => {
        if (!isGameRunning.value) {
            horseRafId = requestAnimationFrame(tick);
            return;
        }
        if (!horseLastTs) horseLastTs = ts;
        const dt = Math.min(ts - horseLastTs, 200);
        horseLastTs = ts;

        if (horses.value.length === 0) {
            if (logCounter++ % 60 === 0) {
                console.log('[game3 Rank1View] RAF: horses 为空, gameStarted:', gameStarted.value, 'isGameRunning:', isGameRunning.value);
            }
            horseRafId = requestAnimationFrame(tick);
            return;
        }

        const newBoosts: Record<string, number> = {};

        for (const horse of horses.value) {
            if (horse.xPercent >= 100) continue;

            // 从 transientBoosts 读取实时加速值
            const boost = transientBoosts.value[horse.playerKey] || 0;
            horse.boost = boost;

            // 基础速度 + 加速 → 推进百分比
            const effectiveSpeed = BASE_SPEED_PX_PER_SEC * (1 + boost);
            const deltaPx = effectiveSpeed * (dt / 1000);
            horse.xPercent = Math.min(100, horse.xPercent + (deltaPx / TOTAL_DISTANCE_PX) * 100);

            // 像素位置 = 起始位置 + 百分比 * 总距离
            horse.x = HORSE_START_X + (horse.xPercent / 100) * TOTAL_DISTANCE_PX;

            // 帧动画
            const fc = horseFrameCount[horse.horseType] ?? 12;
            horse.frameTimer += dt;
            while (horse.frameTimer >= HORSE_FRAME_TICK_MS) {
                horse.frameTimer -= HORSE_FRAME_TICK_MS;
                horse.frameIndex = (horse.frameIndex + 1) % fc;
            }

            // 加速衰减
            const decayed = boost * Math.pow(BOOST_DECAY, dt / (1000 / 60));
            if (decayed > 0.001) {
                newBoosts[horse.playerKey] = decayed;
            }
        }

        transientBoosts.value = newBoosts;
        horseRafId = requestAnimationFrame(tick);
    };
    horseRafId = requestAnimationFrame(tick);
};

const stopHorseLoop = () => {
    if (horseRafId) {
        cancelAnimationFrame(horseRafId);
        horseRafId = undefined;
    }
};

// ========== 生成/更新马匹（对齐 game4 updateHorses 模式，保留已有马匹进度） ==========
const LANE_TOP_POSITIONS = [310, 510, 720];

const updateHorses = (players: Player[]) => {
    const validPlayers = players.filter(p => {
        const key = getPlayerKey(p);
        if (!key || key.startsWith('empty-')) return false;
        if (p.nickname === '-' || p.nickname === '虚位以待') return false;
        return true;
    });

    console.log('[game3 Rank1View] updateHorses: 输入', players.length, '条, 有效', validPlayers.length, '条',
        validPlayers.slice(0, 3).map(p => ({ key: getPlayerKey(p), name: p.nickname, score: p.score })));

    if (validPlayers.length === 0) {
        console.warn('[game3 Rank1View] updateHorses: 无有效玩家，horses 清空');
        horses.value = [];
        return;
    }

    // 保留已有马匹的 x/xPercent/boost，防止重新生成时位置跳变
    const existingMap = new Map(horses.value.map(h => [h.playerKey, h]));

    horses.value = validPlayers.map((player, index) => {
        const key = getPlayerKey(player, index);
        const existing = existingMap.get(key);
        return {
            id: existing?.id || `horse-${++horseIdCounter}`,
            horseType: HORSE_TYPES[index % HORSE_TYPES.length]!,
            lane: index % LANE_TOP_POSITIONS.length,
            frameIndex: existing?.frameIndex ?? Math.floor(Math.random() * (horseFrameCount[HORSE_TYPES[index % HORSE_TYPES.length]!] ?? 12)),
            frameTimer: existing?.frameTimer ?? 0,
            x: existing?.x ?? HORSE_START_X,
            xPercent: existing?.xPercent ?? 0,
            boost: existing?.boost ?? 0,
            nickname: player.nickname || '',
            avatar: player.avatar || '',
            playerKey: key,
        };
    });

    console.log('[game3 Rank1View] updateHorses: 生成', horses.value.length, '匹马');
};

// ========== 预加载马匹帧 ==========
const preloadHorseFrames = () => {
    for (const frames of Object.values(horseFrames)) {
        for (const url of frames) {
            const img = new Image();
            img.src = url;
        }
    }
};

// ========== 游戏流程 ==========
const startIntro = async () => {
    console.log('[game3 Rank1View] startIntro 开始');
    showResult.value = false;
    gameStarted.value = false;
    isGameRunning.value = false;
    horses.value = [];
    horseIdCounter = 0;
    transientBoosts.value = {};
    Object.keys(prevScores).forEach(k => delete prevScores[k]);
    preloadHorseFrames();

    const countdownPromise = designStage.value?.startCountdown(3, 60);
    await new Promise((r) => setTimeout(r, 3500));

    console.log('[game3 Rank1View] 倒计时结束，马匹开始奔跑');
    gameStarted.value = true;
    isGameRunning.value = true;
    
    const validPlayers = list.value.filter(p => {
        const key = getPlayerKey(p);
        return key && !key.startsWith('empty-') && p.nickname !== '-' && p.nickname !== '虚位以待';
    });
    
    if (validPlayers.length > 0) {
        updateHorses(list.value);
    } else {
        const count = 8 + Math.floor(Math.random() * 3);
        const now = performance.now();
        const newHorses: Horse[] = [];
        
        for (let i = 0; i < count; i++) {
            const type = HORSE_TYPES[i % HORSE_TYPES.length]!;
            const lane = i % LANE_TOP_POSITIONS.length;
            const delayMs = i * 50 + Math.random() * 50;
            const durationMs = (60 + Math.random() * 40) * 1000;
            newHorses.push({
                id: `horse-${++horseIdCounter}`,
                horseType: type,
                lane,
                frameIndex: Math.floor(Math.random() * (horseFrameCount[type] ?? 12)),
                frameTimer: 0,
                x: HORSE_START_X,
                xPercent: 0,
                boost: 0,
                nickname: `马匹${i + 1}`,
                avatar: '',
                playerKey: `auto-${i}`,
            });
        }
        horses.value = newHorses;
        console.log('[game3 Rank1View] 生成', count, '匹默认马');
    }
    
    startHorseLoop();

    await countdownPromise;
    stopGame();
};

const stopGame = () => {
    isGameRunning.value = false;
    showResult.value = true;
    stopHorseLoop();
    playApplauseMusic();
    console.log('[game3 Rank1View] 游戏结束，显示结果页');
};

defineExpose({
    startIntro,
});

// ========== 头像样式 ==========
const horseAvatarStyle = (horse: Horse) => {
    if (horse.avatar) {
        return { backgroundImage: `url(${horse.avatar})`, backgroundSize: 'cover' };
    }
    return { backgroundImage: `url(${imageUrls.defaultAvatar})`, backgroundSize: 'cover' };
};

const renderAvatar = (item: any | null) => {
    if (item && item.avatar) {
        return `background: url("${String(item.avatar).replace(/"/g, '\\"')}") center / cover no-repeat;`
    }
    return `background: ${imageUrls.avatar} center / cover no-repeat;`
};

onMounted(() => {
    preloadHorseFrames();
    if ($is_local_mode()) {
        // 本地模式：预填10个模拟玩家数据，由 startIntro 流程驱动赛马
        const mockAvatars = [
            'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Felix',
            'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Aneka',
            'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Salem',
            'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Midnight',
            'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Lucky',
            'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Bandit',
            'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Misty',
            'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Pepper',
            'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Oreo',
            'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Tiger',
        ];
        list.value = [
            { userid: 'local-1',  nickname: '疾风骑士',   avatar: mockAvatars[0], score: 45 },
            { userid: 'local-2',  nickname: '闪电侠',     avatar: mockAvatars[1], score: 38 },
            { userid: 'local-3',  nickname: '追风者',     avatar: mockAvatars[2], score: 30 },
            { userid: 'local-4',  nickname: '千里马',     avatar: mockAvatars[3], score: 22 },
            { userid: 'local-5',  nickname: '飞毛腿',     avatar: mockAvatars[4], score: 15 },
            { userid: 'local-6',  nickname: '烈焰驹',     avatar: mockAvatars[5], score: 52 },
            { userid: 'local-7',  nickname: '暴风战士',   avatar: mockAvatars[6], score: 41 },
            { userid: 'local-8',  nickname: '神行者',     avatar: mockAvatars[7], score: 35 },
            { userid: 'local-9',  nickname: '银鞍客',     avatar: mockAvatars[8], score: 28 },
            { userid: 'local-10', nickname: '踏雪无痕',   avatar: mockAvatars[9], score: 18 },
        ];
        // 每匹马不同的基础增速：领先者（高分）增速更高，自然拉开差距
        const growthRates: Record<string, number> = {};
        list.value.forEach((p, i) => {
            // 高分马增速 1.4~1.8x，低分马 0.6~1.0x，制造持久速度差异
            growthRates[p.userid!] = 0.4 + (i / (list.value.length - 1)) * 1.4;
        });
        // 跟随 isGameRunning 自动管理模拟分数组件
        let simInterval: ReturnType<typeof setInterval> | undefined;
        watch(isGameRunning, (running) => {
            if (simInterval) { clearInterval(simInterval); simInterval = undefined; }
            if (running) {
                simInterval = setInterval(() => {
                    if (!isGameRunning.value) { clearInterval(simInterval); simInterval = undefined; return; }
                    for (const p of list.value) {
                        if (typeof p.score === 'number' && p.score < 120 && p.userid) {
                            const rate = growthRates[p.userid] || 1.0;
                            const growth = Math.max(1, Math.floor((Math.random() * 3 + 1) * rate));
                            p.score += growth;
                        }
                    }
                    detectScoreChanges(list.value);
                }, 1500);
            }
        }, { immediate: true });
    }
});

onUnmounted(() => {
    stopGame();
    stopApplauseMusic();
});
</script>

<template>
    <DesignStage ref="designStage">
        <div class="screen-container" :class="{ paused: !gameStarted }">
            <!-- 背景层：无缝滚动 -->
            <div class="bg-track">
                <div class="bg-inner"></div>
                <div class="bg-inner"></div>
            </div>

            <!-- Logo & Title -->
            <div class="img-logo"></div>
            <div class="img-title"></div>

            <!-- 马匹 -->
            <template v-if="gameStarted && !showResult">
                <div
                    v-for="horse in horses"
                    :key="horse.id"
                    class="horse-wrapper"
                    :style="{
                        top: `${(LANE_TOP_POSITIONS[horse.lane] ?? 560) + HORSE_Y_OFFSET}px`,
                        transform: `translateX(${horse.x}px)`,
                    }"
                >
                    <div class="horse-sprite">
                        <img
                            v-for="(url, frameIdx) in horseFrames[horse.horseType]"
                            :key="frameIdx"
                            :src="url"
                            class="horse-frame"
                            :class="{ active: frameIdx === horse.frameIndex }"
                            alt=""
                        />
                    </div>
                    <div class="horse-shadow"></div>
                    <div class="horse-avatar" :style="horseAvatarStyle(horse)"></div>
                    <div class="horse-username">
                        <span class="username-text">{{ $format_str(horse.nickname, 8) }}</span>
                    </div>
                </div>
            </template>

            <!-- 结果页（参考 game6 Rank2View） -->
            <div v-if="showResult" class="result-overlay">
                <div class="result-bg"></div>
                <div class="result-logo"></div>
                <div class="result-title"></div>

                <div class="podium">
                    <div class="img-vip"></div>
                    <div class="rank-no1">
                        <div class="avatar" :style="`${renderAvatar(list[0])}`"></div>
                        <div class="nickname">{{ list[0]?.nickname }}</div>
                    </div>
                    <div class="rank-no2">
                        <div class="avatar" :style="`${renderAvatar(list[1])}`"></div>
                        <div class="nickname">{{ list[1]?.nickname }}</div>
                    </div>
                    <div class="rank-no3">
                        <div class="avatar" :style="`${renderAvatar(list[2])}`"></div>
                        <div class="nickname">{{ list[2]?.nickname }}</div>
                    </div>
                </div>

                <div class="rank-container">
                    <div v-for="(item, index) in list.slice(3)" :key="item.userid || item.wechat_id || `rank-${index}`">
                        <div class="no-icon">{{ index + 4 }}</div>
                        <div>
                            <div class="img-avatar-container">
                                <div class="img-avatar" :style="`${renderAvatar(list[index + 3])}`"></div>
                            </div>
                            <div class="txt-nickname">{{ item.nickname }}</div>
                        </div>
                    </div>
                </div>

                <div class="btn-next" @click="emit('next')"></div>
                <div class="btn-back" @click="emit('back')"></div>
            </div>
        </div>
    </DesignStage>
</template>

<style scoped>
.screen-container {
    width: 1920px;
    height: 1080px;
    position: relative;
    overflow: hidden;
}

.screen-container.paused .bg-track {
    animation-play-state: paused;
}

/* ========== 背景无缝滚动 ========== */
.bg-track {
    width: 3840px;
    height: 1080px;
    position: absolute;
    top: 0;
    left: 0;
    display: flex;
    animation: bg-scroll-left 30s linear infinite;
    z-index: 0;
}

.bg-inner {
    width: 1920px;
    height: 1080px;
    background: v-bind('imageUrls.bg') center / cover no-repeat;
    flex-shrink: 0;
}

@keyframes bg-scroll-left {
    0% {
        transform: translateX(0);
    }
    100% {
        transform: translateX(-1920px);
    }
}

.img-logo {
    background: v-bind('imageUrls.logo');
    background-size: cover;
    width: 428px;
    height: 77px;
    position: absolute;
    left: 37px;
    top: 82px;
    z-index: 20;
}

.img-title {
    background: v-bind('imageUrls.title') center / cover no-repeat;
    width: 544px;
    height: 208px;
    position: absolute;
    left: 679px;
    top: 52px;
    z-index: 20;
}

/* ========== 马匹 ========== */
.horse-wrapper {
    position: absolute;
    left: 0;
    width: 280px;
    height: 280px;
    z-index: 15;
}

.horse-sprite {
    position: relative;
    width: 280px;
    height: 280px;
}

.horse-frame {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    opacity: 0;
    pointer-events: none;
    z-index: 1;
}

.horse-frame.active {
    opacity: 1;
}

.horse-shadow {
    position: absolute;
    bottom: 20px;
    left: 50%;
    transform: translateX(-50%);
    width: 180px;
    height: 24px;
    background: radial-gradient(ellipse, rgba(0, 0, 0, 0.4) 0%, transparent 70%);
    border-radius: 50%;
    pointer-events: none;
    z-index: 0;
}

/* ========== 马背用户信息 ========== */
.horse-avatar {
    width: 50px;
    height: 50px;
    border-radius: 50%;
    position: absolute;
    top: 80px;
    left: 60px;
    border: 2px solid #FFCF44;
    z-index: 3;
}

.horse-username {
    background: v-bind('imageUrls.username');
    background-size: contain;
    background-repeat: no-repeat;
    width: 120px;
    height: 44px;
    padding-left: 12px;
    position: absolute;
    top: 105px;
    left: 60px;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 2;
}

.username-text {
    position: absolute;
    top: 2px;
    color: #000;
    font-size: 16px;
    font-weight: bold;
    max-width: 100px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    padding-left: 6px;
    box-sizing: border-box;
}

/* ========== 结果页（参考 game6 Rank2View） ========== */
.result-overlay {
    width: 1920px;
    height: 1080px;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 100;
}

.result-bg {
    width: 1920px;
    height: 1080px;
    background: v-bind('imageUrls.resultBg') center / cover no-repeat;
    position: absolute;
    top: 0;
    left: 0;
}

.result-logo {
    background: v-bind('imageUrls.logo');
    background-size: cover;
    width: 428px;
    height: 77px;
    position: absolute;
    left: 37px;
    top: 82px;
    z-index: 1;
}

.result-title {
    background: v-bind('imageUrls.resultTitle') center / cover no-repeat;
    width: 831px;
    height: 120px;
    position: absolute;
    left: 545px;
    top: 64px;
    z-index: 1;
}

.podium {
    background: v-bind('imageUrls.podium') no-repeat center;
    width: 1920px;
    height: 740px;
    position: absolute;
    bottom: 0;
    left: 0;
    z-index: 1;

    .img-vip {
        width: 969px;
        height: 238px;
        position: absolute;
        left: 480px;
        top: -60px;
        background: v-bind('imageUrls.vip') center / cover no-repeat;
    }

    .rank-no1 {
        position: relative;

        .avatar {
            width: 160px;
            height: 160px;
            border-radius: 80px;
            position: absolute;
            left: 884px;
            top: -7px;
        }

        .nickname {
            width: 220px;
            height: 52px;
            background: linear-gradient(0deg, #FFBF5A 0%, #FFE47A 100%);
            border: 1px solid #FFF9DC;
            text-align: center;
            line-height: 46px;
            position: absolute;
            left: 850px;
            top: 136px;
            z-index: 1;
            border-radius: 26px;
            font-size: 30px;
            color: #4B1A14;
        }
    }

    .rank-no2 {
        position: relative;

        .avatar {
            width: 144px;
            height: 144px;
            border-radius: 72px;
            position: absolute;
            left: 488px;
            top: 27px;
        }

        .nickname {
            width: 220px;
            height: 52px;
            background: linear-gradient(0deg, #AEA6A7 0%, #EAE4DF 100%);
            border: 1px solid white;
            color: #383636;
            text-align: center;
            line-height: 52px;
            position: absolute;
            left: 447px;
            top: 160px;
            z-index: 1;
            border-radius: 23px;
            font-size: 30px;
        }
    }

    .rank-no3 {
        position: relative;

        .avatar {
            width: 144px;
            height: 144px;
            border-radius: 72px;
            position: absolute;
            left: 1297px;
            top: 26px;
        }

        .nickname {
            width: 220px;
            height: 52px;
            background: linear-gradient(0deg, #F3AE76 0%, #F9CDA3 100%);
            color: #6F3A0E;
            text-align: center;
            line-height: 46px;
            position: absolute;
            left: 1255px;
            top: 160px;
            z-index: 1;
            border-radius: 26px;
            font-size: 30px;
            border: 1px solid #FEFEFD;
        }
    }
}

.rank-container {
    display: flex;
    align-items: center;
    width: 1570px;
    height: 115px;
    position: absolute;
    bottom: 263px;
    left: 200px;
    z-index: 2;

    > div {
        flex: 1;
        display: grid;
        width: 100px;
        height: 100%;

        .no-icon {
            background: v-bind('imageUrls.rankIcon') no-repeat center;
            width: 42px;
            height: 47px;
            position: absolute;
            text-align: center;
            line-height: 42px;
            color: #CC7F36;
            font-weight: bold;
            top: 50px;
        }

        .img-avatar-container {
            position: relative;
            margin: 0 auto;
            margin-top: 10px;
            width: 72px;
            height: 72px;
            border-radius: 36px;
            transform: scale(1.6);
            top: 50px;
        }

        .img-avatar-container::before {
            content: "";
            position: absolute;
            inset: 0;
            border-radius: inherit;
            background: v-bind('imageUrls.avatarAnimation') center / cover no-repeat;
            animation: avatar-rotate 10s linear infinite;
        }

        .img-avatar {
            position: relative;
            top: 6px;
            z-index: 1;
            margin: 0 auto;
            width: 60px;
            height: 60px;
            border-radius: 30px;
            background: v-bind('imageUrls.avatar') center / cover no-repeat;
        }

        .txt-nickname {
            color: #F9EBCB;
            font-size: 22px;
            text-align: center;
            position: absolute;
            top: 170px;
            margin-left: 68px;
        }
    }
}

.btn-next {
    position: absolute;
    bottom: 50px;
    left: 620px;
    width: 316px;
    height: 105px;
    cursor: pointer;
    background: v-bind('imageUrls.next') center / cover no-repeat;
    z-index: 2;
}

.btn-back {
    position: absolute;
    bottom: 50px;
    left: 1020px;
    width: 316px;
    height: 105px;
    cursor: pointer;
    background: v-bind('imageUrls.back') center / cover no-repeat;
    z-index: 2;
}

@keyframes avatar-rotate {
    0% {
        transform: rotate(0deg);
    }
    100% {
        transform: rotate(360deg);
    }
}
</style>
