<template>
    <view class="dw-page">
        <!-- 装饰背景 -->
        <view class="bg-decor bg-decor-a"></view>
        <view class="bg-decor bg-decor-b"></view>

        <!-- 顶部条 -->
        <view class="top">
            <view class="top-back" @click="handleBack">
                <view class="back-arrow"></view>
            </view>
            <view v-if="!isCropperActive" class="top-title">
                <text class="ellipsis">{{ title }}</text>
            </view>
            <view
                v-if="!pageLoading && !isCropperActive"
                class="top-meta"
                :style="{ paddingRight: menuButtonRightRpx + 'rpx' }"
            >
                <view class="top-progress">
                    <text class="cur">{{ activeIdx + 1 }}</text>
                    <text class="divider">/</text>
                    <text class="total">{{ paperList.length }}</text>
                </view>
                <view class="top-clock">
                    <image class="clock-icon" src="/static/image/svg/time.svg" mode="aspectFit" />
                    <text>{{ timeFilter }}</text>
                </view>
            </view>
        </view>

        <!-- 主体 -->
        <view v-if="!pageLoading" class="main">
            <view class="book-box">
                <Question
                    v-if="paperList.length && paperList[activeIdx]"
                    :key="`question-${activeIdx}-${paperList[activeIdx]?.id ?? ''}`"
                    :data="paperList[activeIdx]"
                    :idx="activeIdx + 1"
                    :total="paperList.length"
                    :resourceType="resourceType"
                    :reportFlag="reportFlag"
                    :subjectId="paperInfo.subjectId"
                    :recordId="params.recordId"
                    @submit="submitQuestion"
                    @cropper-visible-change="onCropperVisibleChange"
                />
            </view>

            <!-- 底部题号 + 操作 -->
            <view class="bottom-area" :style="bottomAreaStyle">
                <view class="bottom">
                    <view class="indicator-wrap">
                        <scroll-view class="indicator" scroll-x :show-scrollbar="false" enable-flex>
                            <view class="indicator-track">
                                <view
                                    v-for="(item, idx) in paperList"
                                    v-show="!item.unLook"
                                    :key="item.id || idx"
                                    :class="[
                                        'indicator-item',
                                        {
                                            active: activeIdx === idx,
                                            success: reportFlag && (item.correctResult || item.markFlag),
                                            error: reportFlag && !(item.correctResult || item.markFlag) && (item.submitAnswer || item.submitAnswerPic),
                                            empty: !reportFlag && !item.submitAnswer && !item.submitAnswerPic,
                                            answered: !reportFlag && (item.submitAnswer || item.submitAnswerPic),
                                        },
                                    ]"
                                    @click="switchQuestion(idx)"
                                >
                                    <text>{{ idx + 1 }}</text>
                                </view>
                            </view>
                        </scroll-view>
                    </view>

                    <view
                        v-if="!reportFlag"
                        :class="['btn-next', { disabled: submitLoading, submit: activeIdx >= paperList.length - 1 }]"
                        @click="handleNext"
                    >
                        <text>{{ activeIdx < paperList.length - 1 ? '下一题' : '提交' }}</text>
                        <view class="btn-arrow">
                            <svg viewBox="0 0 16 16" fill="none">
                                <path d="m6 4 4 4-4 4" stroke="#FFFFFF" stroke-width="2"
                                    stroke-linecap="round" stroke-linejoin="round" />
                            </svg>
                        </view>
                    </view>
                </view>
            </view>
        </view>

        <!-- 加载中 -->
        <view v-else class="loading-page">
            <Loading :text="reportFlag ? '正在加载报告中...' : '正在精选题目中...'" />
        </view>
    </view>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue';
import { onLoad, onShow } from '@dcloudio/uni-app';
import {
    startExam,
    saveRecordAnswer,
    submitExam,
    getPaperRecordDetail,
} from '@/api/homework';
import { listMediaByRecordId } from '@/api/upload';
import { attachMediaAuditToPaperList } from '@/utils/mediaAudit';
import { getWxOpenid } from '@/utils/wxOpenid';
import {
    resource_type_homework,
    normalizeResourceType,
    isHomeworkExamResourceType,
} from '@/constants/doWork';
import Loading from '@/components/Loading/index.vue';
import Question from './components/Question.vue';

const pageLoading = ref(true);
const submitLoading = ref(false);
const menuButtonRightRpx = ref(0);
const isCropperActive = ref(false);
const windowWidthPx = ref(375);
const safeAreaPadding = ref({ top: 0, right: 0, bottom: 0, left: 0 });

const paperList = ref<any[]>([]);
const paperInfo = ref<any>({});
const activeIdx = ref(0);

const reportFlag = ref<0 | 1>(0);
const params = ref<any>({});

let timer: any = null;
const initialIdx = ref(0);

const resourceType = computed(() =>
    normalizeResourceType(params.value.resourceType || paperInfo.value.resourceType),
);

const normalizePaperList = (list: any, markUnLook = false) => {
    if (!Array.isArray(list)) return [];
    if (!markUnLook) return list;
    return list.map((item: any, idx: number) => ({
        ...item,
        unLook: idx > 0,
    }));
};

const normalizeAnswerPic = (value: any) => String(value || '')
    .split(',')
    .map((url) => String(url || '').replace(/[`]/g, '').replace(/http:\/\//gi, 'https://').trim())
    .filter(Boolean)
    .join(',');

const isUploadImageQuestion = (item: any) => {
    const typeText = [
        item?.titleChannelTypeName,
        item?.channelTypeName,
        item?.typeName,
        item?.titleTypeName,
    ].filter(Boolean).join(',');
    return /上传|拍照/.test(typeText);
};

const extractPicLinksFromAnswer = (answer: any) => {
    const raw = String(answer || '');
    if (!raw) return '';
    const links = raw.match(/https?:\/\/[^\s,]+/g) || [];
    return normalizeAnswerPic(links.join(','));
};

const getSubmitAnswerPic = (item: any) => {
    const answerPic = normalizeAnswerPic(item?.submitAnswerPic);
    if (answerPic) return answerPic;
    if (!isUploadImageQuestion(item)) return '';
    return extractPicLinksFromAnswer(item?.submitAnswer);
};

// 与 Web saveRecordAnswer 一致：接口 itemId 应传答卷记录题目 ID，而非题库题目 id
const getQuestionKey = (item: any) => item?.itemId || item?.jobStuTittleId || item?.id || '';

const normalizeCurrentMultiAnswer = () => {
    const cur = paperList.value[activeIdx.value];
    if (!cur || cur.titleChannelTypeName !== '多选题') return;
    const raw = String(cur.submitAnswer || '');
    cur.submitAnswer = raw
        .split(',')
        .flatMap((item) => item.split(''))
        .map((item) => item.trim())
        .filter(Boolean)
        .sort()
        .join(',');
};

const title = computed(() => {
    const name = paperInfo.value.paperName;
    if (name) {
        return name.replace(/-\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/, '');
    }
    return '作业';
});

const timeFilter = computed(() => {
    const cost = paperInfo.value.costTime || 0;
    const h = Math.floor(cost / 3600);
    const m = Math.floor((cost % 3600) / 60);
    const s = cost % 60;
    if (h > 0) return `${h}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;
    return `${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;
});

const rpxToPx = (rpx: number, windowWidth = windowWidthPx.value) =>
    Math.round((windowWidth / 750) * rpx);

const isIOSDevice = (sys: UniApp.GetSystemInfoResult) => {
    const platform = String(sys.platform || '').toLowerCase();
    const system = String(sys.system || '').toLowerCase();
    return platform === 'ios' || /ios|iphone|ipad/.test(system);
};

const pickValidInset = (values: number[]) => {
    const valid = values.filter((v) => Number.isFinite(v) && v > 0 && v < 120);
    return valid.length ? Math.max(...valid) : 0;
};

const syncSafeArea = () => {
    try {
        const sys = uni.getSystemInfoSync() as UniApp.GetSystemInfoResult & {
            safeAreaInsets?: { top?: number; right?: number; bottom?: number; left?: number };
        };
        let windowInfo: UniApp.GetWindowInfoResult & {
            safeAreaInsets?: { top?: number; right?: number; bottom?: number; left?: number };
        } = {} as any;
        try {
            windowInfo = (uni.getWindowInfo?.() || {}) as typeof windowInfo;
        } catch {
            // ignore
        }

        const windowWidth = windowInfo.windowWidth || sys.windowWidth || 375;
        const windowHeight = windowInfo.windowHeight || sys.windowHeight || 0;
        const screenWidth = windowInfo.screenWidth || sys.screenWidth || windowWidth;
        const screenHeight = windowInfo.screenHeight || sys.screenHeight || windowHeight;
        const sa = windowInfo.safeArea || sys.safeArea;
        const insets = windowInfo.safeAreaInsets || sys.safeAreaInsets;
        const isLandscape = windowWidth > windowHeight;
        const isIOS = isIOSDevice(sys);
        const shortEdge = Math.min(windowWidth, windowHeight);

        const bottomCandidates: number[] = [];
        const leftCandidates: number[] = [];
        const rightCandidates: number[] = [];

        if (insets) {
            if ((insets.bottom ?? 0) > 0) bottomCandidates.push(insets.bottom!);
            if ((insets.left ?? 0) > 0) leftCandidates.push(insets.left!);
            if ((insets.right ?? 0) > 0) rightCandidates.push(insets.right!);
        }

        if (sa) {
            if (windowHeight > 0) {
                bottomCandidates.push(windowHeight - sa.bottom);
                bottomCandidates.push(windowHeight - sa.height - (sa.top || 0));
            }
            if (screenHeight > 0) {
                bottomCandidates.push(screenHeight - sa.bottom);
            }
            if (isLandscape && shortEdge > 0 && sa.height > 0) {
                bottomCandidates.push(shortEdge - sa.height - (sa.top || 0));
            }
            if (sa.left > 0) leftCandidates.push(sa.left);
            if (windowWidth > 0 && sa.right > 0 && sa.right < windowWidth) {
                rightCandidates.push(windowWidth - sa.right);
            }
            if (screenWidth > 0 && sa.right > 0 && sa.right < screenWidth) {
                rightCandidates.push(screenWidth - sa.right);
            }
        }

        let bottom = pickValidInset(bottomCandidates);
        let left = pickValidInset(leftCandidates);
        let right = pickValidInset(rightCandidates);

        // 横屏强制页在部分 iOS 机型上 safeArea API 返回 0，使用 Home Indicator 经验值兜底
        if (bottom === 0 && isIOS) {
            bottom = isLandscape ? 21 : 34;
        }

        windowWidthPx.value = windowWidth;
        safeAreaPadding.value = { top: 0, left, right, bottom };
    } catch {
        // 保留默认值
    }
};

const bottomAreaStyle = computed(() => {
    const { left, right, bottom } = safeAreaPadding.value;
    const topPadding = rpxToPx(2);
    const bottomPadding = rpxToPx(8);
    const safeAreaHalf = bottom / 2;
    return {
        paddingTop: `${topPadding}px`,
        paddingLeft: `${rpxToPx(12) + left}px`,
        paddingRight: `${rpxToPx(12) + right}px`,
        paddingBottom: `${bottomPadding + safeAreaHalf}px`,
    };
});

onLoad((options: any) => {
    initialIdx.value = Number(options.idx) || 0;
    // 与 Web route.params.id 一致：带 id 时为查看报告
    if (options.id) {
        reportFlag.value = 1;
        params.value = {
            ...options,
            id: options.id,
            recordId: options.recordId || options.id,
            resourceType: normalizeResourceType(options.resourceType),
        };
    } else {
        reportFlag.value = Number(options.reportFlag || 0) as 0 | 1;
        params.value = {
            ...options,
            resourceType: normalizeResourceType(options.resourceType),
        };
        if (reportFlag.value === 1 && params.value.recordId && !params.value.id) {
            params.value.id = params.value.recordId;
        }
    }
    init();
});

const handleBack = () => {
    if (reportFlag.value) {
        uni.navigateBack();
        return;
    }
    uni.showModal({
        title: '提示',
        content: '是否确认退出，退出后不保留答题记录',
        confirmColor: '#4f46e5',
        success: (res) => {
            if (res.confirm) {
                clearTimer();
                uni.navigateBack();
            }
        },
    });
};

const switchQuestion = async (idx?: number) => {
    if (idx === activeIdx.value) {
        if (!reportFlag.value && isHomeworkExamResourceType(resourceType.value)) {
            await saveAnswer();
        }
        return;
    }
    if (idx !== undefined) {
        if (!reportFlag.value && isHomeworkExamResourceType(resourceType.value)) {
            normalizeCurrentMultiAnswer();
            await saveAnswer();
        }
        activeIdx.value = idx;
    } else if (activeIdx.value < paperList.value.length - 1) {
        if (!reportFlag.value && isHomeworkExamResourceType(resourceType.value)) {
            normalizeCurrentMultiAnswer();
            await saveAnswer();
        }
        activeIdx.value++;
    }
    if (!reportFlag.value && paperList.value[activeIdx.value]) {
        paperList.value[activeIdx.value].unLook = false;
    }
};

const handleNext = async () => {
    if (submitLoading.value) return;
    if (activeIdx.value < paperList.value.length - 1) {
        await switchQuestion();
    } else {
        if (paperList.value.some((i) => !i.submitAnswer && !i.submitAnswerPic)) {
            uni.showModal({
                title: '提示',
                content: '还有题目未作答，确定要提交答案吗？',
                confirmColor: '#4f46e5',
                success: (res) => {
                    if (res.confirm) submitTrain();
                },
            });
        } else {
            submitTrain();
        }
    }
};

const saveAnswer = async () => {
    const cur = paperList.value[activeIdx.value];
    if (!cur) return;
    try {
        await saveRecordAnswer({
            answer: cur.submitAnswer || '',
            answerPic: cur.submitAnswerPic || '',
            costTime: (paperInfo.value.costTime || 0) * 1000,
            itemId: cur.itemId,
            recordId: params.value.recordId,
        });
    } catch (err) {
        console.error('[doWork] save err', err);
    }
};

const submitQuestion = (answer: any) => {
    if (reportFlag.value) return;
    const idx = activeIdx.value;
    if (answer.submitAnswer !== undefined) {
        paperList.value[idx].submitAnswer = answer.submitAnswer;
    }
    if (answer.submitAnswerPic !== undefined) {
        paperList.value[idx].submitAnswerPic = answer.submitAnswerPic;
    }
    if (answer.toNext && activeIdx.value < paperList.value.length - 1) {
        setTimeout(() => switchQuestion(), 300);
    }
};

const onCropperVisibleChange = (visible: boolean) => {
    isCropperActive.value = !!visible;
};

const submitTrain = async () => {
    clearTimer();
    submitLoading.value = true;
    uni.showLoading({ title: '提交中...', mask: true });
    try {
        normalizeCurrentMultiAnswer();
        await saveAnswer();
        await submitExam({
            answerDtoList: paperList.value.map((item) => ({
                itemId: getQuestionKey(item),
                answer: item.submitAnswer || '',
                answerPic: getSubmitAnswerPic(item),
            })),
            costTime: (paperInfo.value.costTime || 0) * 1000,
            recordId: params.value.recordId,
        });
        uni.hideLoading();
        uni.showModal({
            title: '提示',
            content: '试卷提交成功请等待批改',
            showCancel: false,
            confirmText: '好的',
            confirmColor: '#4f46e5',
            success: () => uni.navigateBack(),
        });
    } catch (err: any) {
        uni.hideLoading();
        uni.showToast({ title: err?.message || '提交失败', icon: 'none' });
        startTimer();
    } finally {
        submitLoading.value = false;
    }
};

const startTimer = (init?: boolean) => {
    clearTimer();
    if (init) paperInfo.value.costTime = 0;
    timer = setInterval(() => {
        paperInfo.value.costTime = (paperInfo.value.costTime || 0) + 1;
    }, 1000);
};

const clearTimer = () => {
    if (timer) {
        clearInterval(timer);
        timer = null;
    }
};

const initReport = async () => {
    const recordId = params.value.recordId || params.value.id;
    const res = await getPaperRecordDetail({
        recordId,
        reportFlag: 1,
    });
    paperInfo.value = res.data;
    paperList.value = normalizePaperList(res.data?.titleVoList || res.data?.subjectTitleVoList);

    try {
        const auditRes = await listMediaByRecordId(recordId);
        const auditList = Array.isArray(auditRes.data) ? auditRes.data : [];
        attachMediaAuditToPaperList(paperList.value, auditList);
    } catch (err) {
        console.warn('[doWork] media audit query failed', err);
    }
};

const initNewTrain = async () => {
    if (resourceType.value !== resource_type_homework) {
        throw new Error('暂不支持该练习类型');
    }
    await getWxOpenid();
    const res: any = await startExam(params.value.recordId);
    paperInfo.value = res.data || res;
    if (paperInfo.value.costTime) {
        paperInfo.value.costTime = Math.floor(paperInfo.value.costTime / 1000);
    }
    paperList.value = normalizePaperList(
        paperInfo.value?.titleVoList || paperInfo.value?.subjectTitleVoList || [],
        true,
    );
};

const getMenuButtonInfo = () => {
    try {
        // #ifdef MP-WEIXIN
        const m = uni.getMenuButtonBoundingClientRect();
        const sys = uni.getSystemInfoSync();
        if (m && sys) {
            const rightPx = sys.windowWidth - m.right;
            const widthPx = m.width;
            const pxToRpx = 750 / sys.windowWidth;
            menuButtonRightRpx.value = Math.ceil((rightPx + widthPx) * pxToRpx) + 16;
        } else {
            menuButtonRightRpx.value = 120;
        }
        // #endif
        // #ifndef MP-WEIXIN
        menuButtonRightRpx.value = 0;
        // #endif
    } catch {
        menuButtonRightRpx.value = 120;
    }
};

const init = async () => {
    try {
        pageLoading.value = true;
        if (reportFlag.value) {
            await initReport();
        } else {
            await initNewTrain();
            startTimer();
        }
        const target = Math.min(initialIdx.value, paperList.value.length - 1);
        activeIdx.value = Math.max(0, target);
        if (!reportFlag.value && paperList.value[activeIdx.value]) {
            paperList.value[activeIdx.value].unLook = false;
        }
    } catch (err: any) {
        console.error('[doWork] init err', err);
        // 401 已由 request 拦截器统一跳转登录，避免 navigateBack 覆盖 reLaunch
        if (Number(err?.code) === 401) return;
        uni.showToast({ title: err?.message || '加载失败', icon: 'none' });
        setTimeout(() => uni.navigateBack(), 1500);
    } finally {
        pageLoading.value = false;
        // 横屏页初始化完成后重新同步，避免首次 getSystemInfo 拿到旋转前尺寸
        setTimeout(() => {
            syncSafeArea();
            getMenuButtonInfo();
        }, 50);
    }
};

onShow(() => {
    syncSafeArea();
    getMenuButtonInfo();
});

let resizeHandler: (() => void) | null = null;

onMounted(() => {
    syncSafeArea();
    getMenuButtonInfo();
    resizeHandler = () => {
        syncSafeArea();
        getMenuButtonInfo();
    };
    uni.onWindowResize(resizeHandler);
});

onUnmounted(() => {
    if (resizeHandler) {
        uni.offWindowResize(resizeHandler);
        resizeHandler = null;
    }
    clearTimer();
    isCropperActive.value = false;
    paperInfo.value = {};
    paperList.value = [];
    activeIdx.value = 0;
});
</script>

<style lang="scss" scoped>
.dw-page {
    height: 100vh;
    width: 100vw;
    overflow: hidden;
    box-sizing: border-box;
    position: relative;
    background: linear-gradient(160deg, #eef2ff 0%, #f5f7ff 40%, #f0fdf4 100%);
    display: flex;
    flex-direction: column;
}

/* 装饰背景 */
.bg-decor {
    position: absolute;
    border-radius: 50%;
    filter: blur(60rpx);
    pointer-events: none;
    z-index: 0;

    &-a {
        top: -80rpx;
        right: -80rpx;
        width: 280rpx;
        height: 280rpx;
        background: radial-gradient(circle, rgba(129, 140, 248, 0.35), transparent 70%);
    }

    &-b {
        bottom: -80rpx;
        left: -80rpx;
        width: 280rpx;
        height: 280rpx;
        background: radial-gradient(circle, rgba(34, 197, 94, 0.3), transparent 70%);
    }
}

/* 顶部条 */
.top {
    position: relative;
    z-index: 10;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 3rpx 12rpx 2rpx;
    gap: 8rpx;
}

.top-back {
    width: 34rpx;
    height: 34rpx;
    flex-shrink: 0;
    background: #ffffff;
    border-radius: 10rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow:
        0 4rpx 10rpx rgba(99, 102, 241, 0.18),
        inset 0 -3rpx 0 rgba(199, 210, 254, 0.6);

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

.back-arrow {
    width: 9rpx;
    height: 9rpx;
    border-left: 2rpx solid #4f46e5;
    border-bottom: 2rpx solid #4f46e5;
    transform: rotate(45deg);
    margin-left: 4rpx;
}

.top-title {
    flex: 1;
    min-width: 0;
    font-size: 17rpx;
    font-weight: 700;
    color: #312e81;
    text-align: center;

    text {
        max-width: 100%;
    }
}

.top-meta {
    display: flex;
    align-items: center;
    gap: 6rpx;
    flex-shrink: 0;
}

.top-progress {
    display: flex;
    align-items: baseline;
    gap: 2rpx;
    padding: 3rpx 10rpx;
    background: linear-gradient(180deg, #818cf8, #4f46e5);
    border-radius: 999rpx;
    color: #ffffff;
    box-shadow:
        0 4rpx 10rpx rgba(79, 70, 229, 0.3),
        inset 0 -3rpx 0 rgba(0, 0, 0, 0.12);

    .cur {
        font-size: 16rpx;
        font-weight: 800;
    }

    .divider {
        font-size: 11rpx;
        opacity: 0.6;
    }

    .total {
        font-size: 13rpx;
        opacity: 0.8;
    }
}

.top-clock {
    display: flex;
    align-items: center;
    gap: 4rpx;
    padding:  5rpx 10rpx;
    background: #ffffff;
    border-radius: 999rpx;
    box-shadow:
        0 4rpx 10rpx rgba(99, 102, 241, 0.15),
        inset 0 -3rpx 0 rgba(199, 210, 254, 0.5);

    .clock-icon {
        width: 17rpx;
        height: 17rpx;
        flex-shrink: 0;
    }

    text {
        font-size: 15rpx;
        font-weight: 700;
        color: #4f46e5;
        font-variant-numeric: tabular-nums;
        line-height: 20rpx;
        vertical-align: middle;
    }
}

/* 主体 */
.main {
    flex: 1;
    height: 0;
    position: relative;
    z-index: 1;
    padding: 0 8rpx;
    display: flex;
    flex-direction: column;
}

.book-box {
    flex: 1;
    overflow: hidden;
    position: relative;
    margin: 0 2rpx;
}

.bottom-area {
    flex-shrink: 0;
    box-sizing: border-box;
    background: linear-gradient(to bottom, transparent, rgba(245, 247, 255, 0.5));
}

.bottom {
    display: flex;
    align-items: center;
    gap: 8rpx;
    box-sizing: border-box;
}

.indicator-wrap {
    flex: 1;
    width: 0;
    height: 44rpx;
    padding: 0 8rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    background: rgba(255, 255, 255, 0.55);
    border-radius: 999rpx;
    backdrop-filter: blur(4rpx);
    -webkit-backdrop-filter: blur(4rpx);
    border: 1rpx solid rgba(199, 210, 254, 0.3);
}

.indicator {
    width: 100%;
    height: 44rpx;
    white-space: nowrap;
}

.indicator-track {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 100%;
    height: 44rpx;
    gap: 12rpx;
    padding: 0 6rpx;
    box-sizing: border-box;
}

.indicator-item {
    flex-shrink: 0;
    width: 26rpx;
    height: 26rpx;
    border-radius: 999rpx;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 200ms ease;
    position: relative;

    text {
        display: block;
        font-size: 13rpx;
        font-weight: 600;
        color: #6366f1;
        line-height: 26rpx;
        text-align: center;
        transition: color 200ms ease;
    }

    &.answered {
        background: linear-gradient(180deg, #c7d2fe, #818cf8);

        text {
            color: #ffffff;
        }
    }

    &.empty {
        background: #e2e8f0;

        text {
            color: #94a3b8;
        }
    }

    &.success {
        background: linear-gradient(180deg, #4ade80, #16a34a);

        text {
            color: #ffffff;
        }
    }

    &.error {
        background: linear-gradient(180deg, #f87171, #dc2626);

        text {
            color: #ffffff;
        }
    }

    &.active {
        z-index: 2;
        width: 30rpx;
        height: 30rpx;
        background: linear-gradient(180deg, #818cf8, #4f46e5);
        box-shadow:
            0 4rpx 10rpx rgba(79, 70, 229, 0.35),
            0 0 0 2rpx rgba(255, 255, 255, 0.9);

        text {
            color: #ffffff;
            font-size: 15rpx;
            font-weight: 800;
            line-height: 30rpx;
        }
    }
}

.btn-next {
    flex-shrink: 0;
    height: 32rpx;
    padding: 0 14rpx;
    border-radius: 999rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6rpx;
    background: linear-gradient(180deg, #4ade80, #16a34a);
    color: #ffffff;
    box-shadow:
        0 6rpx 14rpx rgba(22, 163, 74, 0.35),
        inset 0 -3rpx 0 rgba(0, 0, 0, 0.15);
    transition: all 150ms ease;

    text {
        font-size: 15rpx;
        font-weight: 700;
        letter-spacing: 2rpx;
    }

    .btn-arrow {
        width: 15rpx;
        height: 15rpx;

        svg {
            width: 100%;
            height: 100%;
        }
    }

    &.submit {
        background: linear-gradient(180deg, #818cf8, #4f46e5);
        box-shadow:
            0 6rpx 14rpx rgba(79, 70, 229, 0.4),
            inset 0 -3rpx 0 rgba(0, 0, 0, 0.15);
    }

    &.disabled {
        opacity: 0.6;
    }

    &:active {
        transform: translateY(2rpx);
    }
}

/* 加载 */
.loading-page {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    z-index: 1;
}
</style>
