<template>
    <view class="ai-page">
        <!-- 顶部导航 -->
        <view class="ai-nav" :style="{ paddingTop: statusBarHeight + 'px' }">
            <view class="ai-nav__back" @tap="goBack">
                <u-icon name="arrow-left" size="36" color="#333" />
            </view>
            <text class="ai-nav__title">AI 智能预测</text>
            <view class="ai-nav__right" />
        </view>

        <scroll-view scroll-y class="ai-body" :style="{ height: bodyHeight + 'px' }">
            <view class="ai-body-inner">
                <!-- 彩种信息 -->
                <view class="ai-section ai-section--header">
                    <view class="ai-game-info">
                        <view class="ai-game-info__badge">AI</view>
                        <text class="ai-game-info__name">{{ gameName || '加载中...' }}</text>
                    </view>
                    <view class="ai-game-info__meta">
                        <text class="ai-game-info__tip">基于近{{ drawCount }}期历史数据深度分析 · {{ AI_DAILY_FREE_TEXT }}</text>
                        <view class="ai-quota">
                            <text class="ai-quota__label">今日剩余</text>
                            <text class="ai-quota__value">{{ freeRemain }}次</text>
                        </view>
                    </view>
                </view>

                <!-- 模块1: 历史开奖数据 -->
                <view class="ai-section" :class="{ 'ai-section--visible': modules.history.visible }">
                    <view class="ai-section__header">
                        <view class="ai-section__icon ai-section__icon--history">📊</view>
                        <text class="ai-section__title">历史开奖数据</text>
                        <view v-if="modules.history.loading" class="ai-section__loading">
                            <view class="ai-dot" />
                            <view class="ai-dot" />
                            <view class="ai-dot" />
                        </view>
                        <text v-else-if="modules.history.done" class="ai-section__done">✓</text>
                    </view>
                    <view v-if="modules.history.data" class="ai-section__body">
                        <view v-for="(draw, i) in displayedDraws" :key="i" class="history-row"
                            :style="{ animationDelay: i * 50 + 'ms' }">
                            <text class="history-row__issue">第{{ draw.issue }}期</text>
                            <view class="history-row__balls">
                                <text v-for="(n, j) in draw.numbers" :key="j" class="history-ball">{{ n }}</text>
                            </view>
                        </view>
                    </view>
                </view>

                <!-- 模块2: 热冷号分析 -->
                <view class="ai-section" :class="{ 'ai-section--visible': modules.hotCold.visible }">
                    <view class="ai-section__header">
                        <view class="ai-section__icon ai-section__icon--hot">🔥</view>
                        <text class="ai-section__title">热冷号分析</text>
                        <view v-if="modules.hotCold.loading" class="ai-section__loading">
                            <view class="ai-dot" />
                            <view class="ai-dot" />
                            <view class="ai-dot" />
                        </view>
                        <text v-else-if="modules.hotCold.done" class="ai-section__done">✓</text>
                    </view>
                    <view v-if="modules.hotCold.data" class="ai-section__body">
                        <view v-if="modules.hotCold.data.hot_numbers?.length" class="ai-nums-block">
                            <text class="ai-nums-block__label">🔴 热号（高频出现）</text>
                            <view class="ai-nums-row">
                                <text v-for="n in modules.hotCold.data.hot_numbers" :key="'h' + n"
                                    class="ai-ball ai-ball--hot">{{ formatNum(n) }}</text>
                            </view>
                        </view>
                        <view v-if="modules.hotCold.data.hot_analysis" class="ai-text-block">
                            <text class="ai-typewriter">{{ hotColdTyped.hotText }}</text>
                            <text v-if="hotColdTyping.hot" class="ai-cursor">|</text>
                        </view>
                        <view v-if="modules.hotCold.data.cold_numbers?.length" class="ai-nums-block">
                            <text class="ai-nums-block__label">🔵 冷号（低频出现）</text>
                            <view class="ai-nums-row">
                                <text v-for="n in modules.hotCold.data.cold_numbers" :key="'c' + n"
                                    class="ai-ball ai-ball--cold">{{ formatNum(n) }}</text>
                            </view>
                        </view>
                        <view v-if="modules.hotCold.data.cold_analysis" class="ai-text-block">
                            <text class="ai-typewriter">{{ hotColdTyped.coldText }}</text>
                            <text v-if="hotColdTyping.cold" class="ai-cursor">|</text>
                        </view>
                    </view>
                </view>

                <!-- 模块3: 趋势分析+推荐组合 -->
                <view class="ai-section" :class="{ 'ai-section--visible': modules.trend.visible }">
                    <view class="ai-section__header">
                        <view class="ai-section__icon ai-section__icon--trend">📈</view>
                        <text class="ai-section__title">趋势分析 & 推荐组合</text>
                        <view v-if="modules.trend.loading" class="ai-section__loading">
                            <view class="ai-dot" />
                            <view class="ai-dot" />
                            <view class="ai-dot" />
                        </view>
                        <text v-else-if="modules.trend.done" class="ai-section__done">✓</text>
                    </view>
                    <view v-if="modules.trend.data" class="ai-section__body">
                        <view v-if="modules.trend.data.trend_analysis" class="ai-text-block">
                            <text class="ai-nums-block__label">趋势分析</text>
                            <text class="ai-typewriter">{{ trendTyped.trendText }}</text>
                            <text v-if="trendTyping.trend" class="ai-cursor">|</text>
                        </view>
                        <view v-if="modules.trend.data.recommended_combinations?.length" class="ai-combo-block">
                            <text class="ai-nums-block__label">推荐组合</text>
                            <view v-for="(combo, ci) in modules.trend.data.recommended_combinations" :key="ci"
                                class="ai-combo">
                                <view class="ai-combo__head">
                                    <text class="ai-combo__idx">方案{{ ci + 1 }}</text>
                                    <text class="ai-combo__conf">信心 {{ combo.confidence }}%</text>
                                </view>
                                <view class="ai-combo__nums">
                                    <text v-for="n in combo.numbers" :key="n" class="ai-ball ai-ball--rec">{{
                                        formatNum(n)
                                    }}</text>
                                </view>
                                <text v-if="combo.reason" class="ai-combo__reason">{{ combo.reason }}</text>
                            </view>
                        </view>
                        <view v-if="modules.trend.data.disclaimer" class="ai-disclaimer">
                            <text>⚠️ {{ modules.trend.data.disclaimer }}</text>
                        </view>
                    </view>
                </view>

                <!-- 模块4: 统计数据 -->
                <view class="ai-section" :class="{ 'ai-section--visible': modules.stats.visible }">
                    <view class="ai-section__header">
                        <view class="ai-section__icon ai-section__icon--stats">📋</view>
                        <text class="ai-section__title">统计数据</text>
                        <view v-if="modules.stats.loading" class="ai-section__loading">
                            <view class="ai-dot" />
                            <view class="ai-dot" />
                            <view class="ai-dot" />
                        </view>
                        <text v-else-if="modules.stats.done" class="ai-section__done">✓</text>
                    </view>
                    <view v-if="modules.stats.data" class="ai-section__body">
                        <view class="ai-stat-grid">
                            <view v-if="modules.stats.data.odd_even_ratio" class="ai-stat-card">
                                <text class="ai-stat-card__label">奇偶比</text>
                                <text class="ai-stat-card__val">{{ modules.stats.data.odd_even_ratio }}</text>
                            </view>
                            <view v-if="modules.stats.data.big_small_ratio" class="ai-stat-card">
                                <text class="ai-stat-card__label">大小比</text>
                                <text class="ai-stat-card__val">{{ modules.stats.data.big_small_ratio }}</text>
                            </view>
                            <view v-if="modules.stats.data.sum_range" class="ai-stat-card">
                                <text class="ai-stat-card__label">和值范围</text>
                                <text class="ai-stat-card__val">{{ modules.stats.data.sum_range }}</text>
                            </view>
                        </view>
                        <view v-if="modules.stats.data.consecutive_analysis" class="ai-text-block">
                            <text class="ai-nums-block__label">连号分析</text>
                            <text class="ai-typewriter">{{ statsTyped.consecutiveText }}</text>
                            <text v-if="statsTyping.consecutive" class="ai-cursor">|</text>
                        </view>
                        <view v-if="modules.stats.data.span_analysis" class="ai-text-block">
                            <text class="ai-nums-block__label">跨度分析</text>
                            <text class="ai-typewriter">{{ statsTyped.spanText }}</text>
                            <text v-if="statsTyping.span" class="ai-cursor">|</text>
                        </view>
                        <view v-if="modules.stats.data.summary" class="ai-text-block">
                            <text class="ai-nums-block__label">总结</text>
                            <text class="ai-typewriter">{{ statsTyped.summaryText }}</text>
                            <text v-if="statsTyping.summary" class="ai-cursor">|</text>
                        </view>
                    </view>
                </view>

                <!-- 全部完成 -->
                <view v-if="allDone" class="ai-footer">
                    <text class="ai-footer__text">— 分析完毕 —</text>
                </view>

                <view style="height: 60rpx" />
            </view>
        </scroll-view>
    </view>
</template>

<script lang="ts" setup>
import { ref, reactive, computed, nextTick } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import {
    getLotteryAiHistory,
    getLotteryAiHotCold,
    getLotteryAiTrend,
    getLotteryAiStats
} from '@/api/lottery'
import { useUserStore } from '@/stores/user'
import { AI_DAILY_FREE_TEXT, getAiFreeRemain } from '@/config/ai'

const statusBarHeight = ref(0)
const bodyHeight = ref(600)
const gameCode = ref('')
const gameName = ref('')
const drawCount = ref(30)
const userStore = useUserStore()
const vipInfo = computed(() => userStore.userInfo?.vip_info || {})
const aiRemainOverride = ref<number | null>(null)
const freeRemain = computed(() => aiRemainOverride.value ?? getAiFreeRemain(vipInfo.value))
const syncAiRemain = (res: any) => {
    if (res?.remain_count !== undefined && res?.remain_count !== null) {
        aiRemainOverride.value = Number(res.remain_count)
    }
}

uni.getSystemInfo({
    success: (res) => {
        statusBarHeight.value = res.statusBarHeight || 0
        bodyHeight.value = res.windowHeight - (res.statusBarHeight || 0) - 44
    }
})

const goBack = () => uni.navigateBack()

const modules = reactive({
    history: { visible: false, loading: false, done: false, data: null as any },
    hotCold: { visible: false, loading: false, done: false, data: null as any },
    trend: { visible: false, loading: false, done: false, data: null as any },
    stats: { visible: false, loading: false, done: false, data: null as any },
})

const allDone = computed(() =>
    modules.history.done && modules.hotCold.done && modules.trend.done && modules.stats.done
)

// 历史数据逐行显示
const displayedDraws = ref<any[]>([])

// 打字机效果
const hotColdTyped = reactive({ hotText: '', coldText: '' })
const hotColdTyping = reactive({ hot: false, cold: false })
const trendTyped = reactive({ trendText: '' })
const trendTyping = reactive({ trend: false })
const statsTyped = reactive({ consecutiveText: '', spanText: '', summaryText: '' })
const statsTyping = reactive({ consecutive: false, span: false, summary: false })

function typeText(fullText: string, target: any, key: string, typingFlag: any, flagKey: string, speed = 20, step = 2): Promise<void> {
    return new Promise((resolve) => {
        if (!fullText) { resolve(); return }
        target[key] = ''
        typingFlag[flagKey] = true
        let i = 0
        const timer = setInterval(() => {
            if (i < fullText.length) {
                target[key] += fullText.slice(i, i + step)
                i += step
            } else {
                clearInterval(timer)
                typingFlag[flagKey] = false
                resolve()
            }
        }, speed)
    })
}

function formatNum(n: any) {
    const s = String(n)
    return s.length < 2 ? '0' + s : s
}

function delay(ms: number) {
    return new Promise(r => setTimeout(r, ms))
}

// 缓存相关
function getCacheKey(code: string) {
    return `ai_predict_${code}`
}

function loadCache(code: string): any | null {
    try {
        const raw = uni.getStorageSync(getCacheKey(code))
        if (!raw) return null
        const cached = JSON.parse(raw)
        // 检查缓存的最新期号是否与当前一致（进入页面后会通过接口获取最新期号对比）
        if (cached && cached.history?.recent_draws?.length) {
            return cached
        }
        return null
    } catch {
        return null
    }
}

function saveCache(code: string, data: any) {
    try {
        uni.setStorageSync(getCacheKey(code), JSON.stringify(data))
    } catch { /* ignore */ }
}

// 从缓存直接还原所有模块（无动画）
function restoreFromCache(cached: any) {
    // 历史数据
    if (cached.history) {
        modules.history.data = cached.history
        gameName.value = cached.history.game_name || gameCode.value
        drawCount.value = cached.history.recent_draws?.length || 30
        displayedDraws.value = cached.history.recent_draws || []
        modules.history.visible = true
        modules.history.done = true
    }
    // 热冷号
    if (cached.hotCold) {
        modules.hotCold.data = cached.hotCold
        hotColdTyped.hotText = cached.hotCold.hot_analysis || ''
        hotColdTyped.coldText = cached.hotCold.cold_analysis || ''
        modules.hotCold.visible = true
        modules.hotCold.done = true
    }
    // 趋势
    if (cached.trend) {
        modules.trend.data = cached.trend
        trendTyped.trendText = cached.trend.trend_analysis || ''
        modules.trend.visible = true
        modules.trend.done = true
    }
    // 统计
    if (cached.stats) {
        modules.stats.data = cached.stats
        statsTyped.consecutiveText = cached.stats.consecutive_analysis || ''
        statsTyped.spanText = cached.stats.span_analysis || ''
        statsTyped.summaryText = cached.stats.summary || ''
        modules.stats.visible = true
        modules.stats.done = true
    }
}

async function showDrawsSequentially(draws: any[]) {
    displayedDraws.value = []
    for (let i = 0; i < Math.min(draws.length, 15); i++) {
        displayedDraws.value.push(draws[i])
        await delay(80)
    }
    if (draws.length > 15) {
        displayedDraws.value = draws
    }
}

async function startAnalysis() {
    if (!gameCode.value) return

    // 先检查缓存
    const cached = loadCache(gameCode.value)

    // 先请求历史数据获取最新期号
    modules.history.visible = true
    modules.history.loading = true
    let historyData: any = null
    try {
        historyData = await getLotteryAiHistory({ code: gameCode.value })
    } catch { /* ignore */ }

    // 有缓存且期号匹配 → 直接显示
    const latestIssue = historyData?.recent_draws?.[0]?.issue || ''
    const cachedIssue = cached?.history?.recent_draws?.[0]?.issue || ''

    if (cached && latestIssue && latestIssue === cachedIssue) {
        modules.history.loading = false
        restoreFromCache(cached)
        return
    }

    // 无缓存或期号不匹配 → 正常流式请求
    const cacheData: any = {}

    // 模块1: 历史数据
    if (historyData) {
        modules.history.data = historyData
        gameName.value = historyData.game_name || gameCode.value
        drawCount.value = historyData.recent_draws?.length || 30
        modules.history.loading = false
        modules.history.done = true
        cacheData.history = historyData
        await showDrawsSequentially(historyData.recent_draws || [])
    } else {
        modules.history.loading = false
        modules.history.done = true
    }

    await delay(300)

    // 模块2: 热冷号
    modules.hotCold.visible = true
    modules.hotCold.loading = true
    try {
        const data = await getLotteryAiHotCold({ code: gameCode.value })
        syncAiRemain(data)
        modules.hotCold.data = data
        modules.hotCold.loading = false
        modules.hotCold.done = true
        cacheData.hotCold = data
        await nextTick()
        await typeText(data.hot_analysis || '', hotColdTyped, 'hotText', hotColdTyping, 'hot')
        await delay(200)
        await typeText(data.cold_analysis || '', hotColdTyped, 'coldText', hotColdTyping, 'cold')
    } catch {
        modules.hotCold.loading = false
        modules.hotCold.done = true
    }

    await delay(300)

    // 模块3: 趋势
    modules.trend.visible = true
    modules.trend.loading = true
    try {
        const data = await getLotteryAiTrend({ code: gameCode.value })
        syncAiRemain(data)
        modules.trend.data = data
        modules.trend.loading = false
        modules.trend.done = true
        cacheData.trend = data
        await nextTick()
        await typeText(data.trend_analysis || '', trendTyped, 'trendText', trendTyping, 'trend')
    } catch {
        modules.trend.loading = false
        modules.trend.done = true
    }

    await delay(300)

    // 模块4: 统计
    modules.stats.visible = true
    modules.stats.loading = true
    try {
        const data = await getLotteryAiStats({ code: gameCode.value })
        syncAiRemain(data)
        modules.stats.data = data
        modules.stats.loading = false
        modules.stats.done = true
        cacheData.stats = data
        await nextTick()
        await typeText(data.consecutive_analysis || '', statsTyped, 'consecutiveText', statsTyping, 'consecutive')
        await delay(100)
        await typeText(data.span_analysis || '', statsTyped, 'spanText', statsTyping, 'span')
        await delay(100)
        await typeText(data.summary || '', statsTyped, 'summaryText', statsTyping, 'summary')
    } catch {
        modules.stats.loading = false
        modules.stats.done = true
    }

    // 全部完成后存入缓存
    if (cacheData.history) {
        saveCache(gameCode.value, cacheData)
    }
}

onLoad((opts: any) => {
    gameCode.value = opts?.code || ''
    gameName.value = opts?.name || ''
    if (userStore.isLogin && !userStore.userInfo?.id) {
        userStore.getUser().catch(() => { /* ignore */ })
    }
    startAnalysis()
})
</script>

<style lang="scss" scoped>
.ai-page {
    min-height: 100vh;
    background: linear-gradient(180deg, #f0f4ff 0%, #f8f9fc 100%);
}

.ai-nav {
    background: #fff;
    display: flex;
    align-items: center;
    height: 44px;
    padding: 0 24rpx;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);
    position: relative;

    &__back {
        width: 64rpx;
        height: 64rpx;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    &__title {
        flex: 1;
        text-align: center;
        font-size: 32rpx;
        font-weight: bold;
        color: #1a1a1a;
    }

    &__right {
        width: 64rpx;
    }
}

.ai-body {
    padding: 0;
}

.ai-body-inner {
    padding: 0 24rpx;
}

.ai-section {
    background: #fff;
    border-radius: 20rpx;
    margin-top: 24rpx;
    padding: 28rpx;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
    opacity: 0;
    transform: translateY(20rpx);
    transition: all 0.4s ease;

    &--visible {
        opacity: 1;
        transform: translateY(0);
    }

    &--header {
        opacity: 1;
        transform: none;
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        color: #fff;
    }

    &__header {
        display: flex;
        align-items: center;
        gap: 12rpx;
        margin-bottom: 20rpx;
    }

    &__icon {
        width: 48rpx;
        height: 48rpx;
        border-radius: 12rpx;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 24rpx;

        &--history {
            background: #e8f4fd;
        }

        &--hot {
            background: #fef0e7;
        }

        &--trend {
            background: #e8faf0;
        }

        &--stats {
            background: #f0e8fa;
        }
    }

    &__title {
        flex: 1;
        font-size: 30rpx;
        font-weight: bold;
        color: #1a1a1a;
    }

    &__loading {
        display: flex;
        gap: 8rpx;
        align-items: center;
    }

    &__done {
        color: #22c55e;
        font-size: 28rpx;
        font-weight: bold;
    }

    &__body {
        animation: fadeIn 0.3s ease;
    }
}

.ai-game-info {
    display: flex;
    align-items: center;
    gap: 16rpx;
    flex-wrap: wrap;

    &__badge {
        background: rgba(255, 255, 255, 0.25);
        color: #fff;
        font-size: 24rpx;
        font-weight: bold;
        padding: 4rpx 16rpx;
        border-radius: 8rpx;
    }

    &__name {
        font-size: 36rpx;
        font-weight: bold;
        color: #fff;
    }

    &__meta {
        width: 100%;
        display: flex;
        align-items: center;
        justify-content: space-between;
        flex-wrap: wrap;
        gap: 16rpx;
        margin-top: 10rpx;
    }

    &__tip {
        font-size: 24rpx;
        color: rgba(255, 255, 255, 0.8);
        flex: 1;
        min-width: 360rpx;
        line-height: 1.45;
    }
}

.ai-quota {
    display: flex;
    align-items: center;
    gap: 10rpx;
    padding: 8rpx 14rpx;
    border-radius: 999rpx;
    background: rgba(255, 255, 255, 0.18);
    border: 1px solid rgba(255, 255, 255, 0.28);
    white-space: nowrap;

    &__label {
        font-size: 22rpx;
        color: rgba(255, 255, 255, 0.76);
    }

    &__value {
        font-size: 24rpx;
        font-weight: 700;
        color: #fff;
    }
}

/* 历史行 */
.history-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12rpx 0;
    border-bottom: 1px solid #f5f5f5;
    animation: slideIn 0.3s ease both;

    &__issue {
        font-size: 24rpx;
        color: #666;
        flex-shrink: 0;
        white-space: nowrap;
        margin-right: auto;
    }

    &__date {
        font-size: 22rpx;
        color: #999;
        width: 200rpx;
        flex-shrink: 0;
    }

    &__balls {
        display: flex;
        flex-wrap: wrap;
        gap: 8rpx;
    }
}

.history-ball {
    background: #eef2ff;
    color: #4f46e5;
    font-size: 22rpx;
    font-weight: bold;
    width: 48rpx;
    height: 48rpx;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* 号码块 */
.ai-nums-block {
    margin-bottom: 20rpx;

    &__label {
        font-size: 26rpx;
        font-weight: bold;
        color: #333;
        margin-bottom: 12rpx;
        display: block;
    }
}

.ai-nums-row {
    display: flex;
    flex-wrap: wrap;
    gap: 12rpx;
}

.ai-ball {
    width: 56rpx;
    height: 56rpx;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 24rpx;
    font-weight: bold;

    &--hot {
        background: linear-gradient(135deg, #ff6b6b, #ee5a24);
        color: #fff;
    }

    &--cold {
        background: linear-gradient(135deg, #74b9ff, #0984e3);
        color: #fff;
    }

    &--rec {
        background: linear-gradient(135deg, #a29bfe, #6c5ce7);
        color: #fff;
    }
}

/* 文字块 */
.ai-text-block {
    margin-bottom: 20rpx;
    padding: 16rpx 20rpx;
    background: #fafbfc;
    border-radius: 12rpx;
}

.ai-typewriter {
    font-size: 26rpx;
    color: #444;
    line-height: 1.7;
    word-break: break-all;
    white-space: pre-wrap;
}

.ai-cursor {
    color: #667eea;
    font-weight: bold;
    animation: blink 0.6s infinite;
}

/* 推荐组合 */
.ai-combo-block {
    margin-bottom: 20rpx;
}

.ai-combo {
    background: #fafbfc;
    border-radius: 12rpx;
    padding: 20rpx;
    margin-top: 12rpx;

    &__head {
        display: flex;
        justify-content: space-between;
        margin-bottom: 12rpx;
    }

    &__idx {
        font-size: 26rpx;
        font-weight: bold;
        color: #6c5ce7;
    }

    &__conf {
        font-size: 24rpx;
        color: #22c55e;
        font-weight: bold;
    }

    &__nums {
        display: flex;
        flex-wrap: wrap;
        gap: 12rpx;
    }

    &__reason {
        font-size: 24rpx;
        color: #666;
        margin-top: 12rpx;
        line-height: 1.5;
    }
}

/* 统计格子 */
.ai-stat-grid {
    display: flex;
    gap: 16rpx;
    margin-bottom: 20rpx;
}

.ai-stat-card {
    flex: 1;
    background: #f8f9fc;
    border-radius: 12rpx;
    padding: 16rpx;
    text-align: center;

    &__label {
        font-size: 22rpx;
        color: #999;
        display: block;
    }

    &__val {
        font-size: 30rpx;
        font-weight: bold;
        color: #333;
        margin-top: 4rpx;
        display: block;
    }
}

/* 免责声明 */
.ai-disclaimer {
    background: #fffbeb;
    border-radius: 12rpx;
    padding: 16rpx 20rpx;
    margin-top: 16rpx;

    text {
        font-size: 22rpx;
        color: #b45309;
        line-height: 1.6;
    }
}

/* 底部 */
.ai-footer {
    text-align: center;
    padding: 40rpx 0 20rpx;

    &__text {
        font-size: 24rpx;
        color: #ccc;
    }
}

/* loading dots */
.ai-dot {
    width: 12rpx;
    height: 12rpx;
    border-radius: 50%;
    background: #667eea;
    animation: dotPulse 1s infinite;

    &:nth-child(2) {
        animation-delay: 0.2s;
    }

    &:nth-child(3) {
        animation-delay: 0.4s;
    }
}

@keyframes dotPulse {

    0%,
    80%,
    100% {
        opacity: 0.3;
        transform: scale(0.8);
    }

    40% {
        opacity: 1;
        transform: scale(1.2);
    }
}

@keyframes fadeIn {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

@keyframes slideIn {
    from {
        opacity: 0;
        transform: translateX(-10rpx);
    }

    to {
        opacity: 1;
        transform: translateX(0);
    }
}

@keyframes blink {

    0%,
    100% {
        opacity: 1;
    }

    50% {
        opacity: 0;
    }
}
</style>
