<template>
	<view class="page">
		<view class="status-bar" :style="{ height: navBarHeight + 'px' }"></view>

		<view class="page-head">
			<view>
				<text class="page-title">数据分析</text>
				<text class="page-subtitle">少抽趋势、节省金额和健康恢复进度</text>
			</view>
			<view class="head-chip" :class="statusChipClass">
				<text class="head-chip-arrow" :class="statusIconClass">{{ statusArrow }}</text>
				<text>{{ statusText }}</text>
			</view>
		</view>

		<!-- Tab 切换 -->
		<view class="segment-wrap">
			<view class="segment">
				<view
					v-for="tab in tabs"
					:key="tab.value"
					class="segment-item"
					:class="{ 'segment-active': currentTab === tab.value }"
					@tap="currentTab = tab.value"
				>
					{{ tab.label }}
				</view>
			</view>
		</view>

		<!-- 洞察卡片 -->
		<view class="insight-card">
			<view class="insight-icon" :class="insightIconClass">
				<text class="insight-glyph">{{ insightEmoji }}</text>
			</view>
			<view class="insight-content">
				<text class="insight-title">阶段洞察</text>
				<text class="insight-desc">{{ insightText }}</text>
			</view>
		</view>

		<!-- 吸烟趋势 -->
		<view class="card">
			<view class="card-header">
				<view>
					<text class="card-title">吸烟趋势</text>
					<text class="card-sub">{{ weeklyTrendRangeText }}</text>
				</view>
				<view class="card-link" @tap="goCalendarDetail">日历详情</view>
			</view>

			<!-- 日均数据 -->
			<view class="avg-row">
				<text class="avg-value">{{ weeklyAverageCount }}</text>
				<text class="avg-unit">支/天</text>
			</view>

			<!-- 日历格式趋势 -->
			<view v-if="weeklyTrendItems.length > 0" class="cal-grid">
				<view v-for="(item, index) in weeklyTrendItems" :key="index" class="cal-cell" :class="{ 'cal-cell-today': item.isHighlight }">
					<text class="cal-weekday">{{ item.weekday }}</text>
					<text class="cal-date">{{ item.date }}</text>
					<view class="cal-dot" :class="calDotClass(item.count)">
						<text class="cal-count">{{ item.count }}</text>
					</view>
				</view>
			</view>
			<view v-else class="empty-block">
				<view class="empty-visual empty-visual-trend">
					<text class="empty-visual-glyph">7</text>
				</view>
				<view class="empty-copy">
					<text class="empty-title">暂无趋势数据</text>
					<text class="empty-text">完成今天的记录后，这里会开始展示最近 7 天的波动节奏。</text>
				</view>
			</view>
		</view>

		<!-- 健康与储蓄 -->
		<view class="card">
			<view class="card-header">
				<text class="card-title">节省金额</text>
				<text class="card-sub">{{ moneySubtitle }}</text>
			</view>
			<view v-if="moneyAvailable" class="money-body">
				<view class="money-left">
					<text class="money-value">{{ savedMoneyText }}</text>
					<view class="progress-bar">
						<view class="progress-fill progress-fill-money" :style="{ width: moneyPercent + '%' }"></view>
					</view>
					<text class="money-target">目标 ¥{{ moneyTargetYuan }} ({{ moneyPercent }}%)</text>
				</view>
				<view class="ring" :style="moneyRingStyle">
					<view class="ring-inner">
						<text class="ring-value">{{ moneyRingText }}</text>
					</view>
				</view>
			</view>
			<view v-else class="empty-block empty-block-dashed">
				<view class="empty-visual empty-visual-money">
					<text class="empty-visual-glyph">¥</text>
				</view>
				<view class="empty-copy">
					<text class="empty-title">节省金额待解锁</text>
					<text class="empty-text">完善基础信息后，系统会自动换算每少抽一支烟省下的金额。</text>
				</view>
			</view>

			<view v-if="moneyAvailable" class="metric-chips">
				<view class="metric-chip metric-chip-warm">
					<text class="metric-label">预计</text>
					<text class="metric-val">{{ moneyExpectedTotal }}</text>
					<text class="metric-unit">支</text>
				</view>
				<view class="metric-chip metric-chip-cool">
					<text class="metric-label">实际</text>
					<text class="metric-val">{{ moneyActualTotal }}</text>
					<text class="metric-unit">支</text>
				</view>
			</view>
		</view>

		<!-- 健康恢复 -->
		<view class="card">
			<view class="card-header">
				<view class="card-title-row">
					<text class="card-title">健康恢复里程碑</text>
				</view>
				<view class="badge" :class="{ 'badge-muted': !healthAvailable }">{{ healthStatusText }}</view>
			</view>
			<view v-if="healthAvailable" class="health-overview">
				<view class="health-stat">
					<text class="health-stat-value">{{ smokeFreeText }}</text>
					<text class="health-stat-label">无烟时长</text>
				</view>
				<view class="ring" :style="healthRingStyle">
					<view class="ring-inner">
						<text class="ring-value">{{ lungRecoveryPercent }}%</text>
						<text class="ring-label">肺功能</text>
					</view>
				</view>
			</view>
			<view v-else class="empty-block empty-block-dashed">
				<view class="empty-visual empty-visual-health">
					<text class="empty-visual-glyph">肺</text>
				</view>
				<view class="empty-copy">
					<text class="empty-title">暂无健康数据</text>
					<text class="empty-text">完成一次记录后，这里会开始生成无烟时长和恢复节点。</text>
				</view>
			</view>
			<view v-if="healthItems.length > 0" class="health-list">
				<view v-for="(item, index) in healthItems" :key="index" class="health-item">
					<view class="health-item-top">
						<text class="health-item-name">{{ item.name }}</text>
						<text class="health-item-pct" :class="{ 'health-item-pct-done': item.percent >= 100 }">{{ item.percent }}%</text>
					</view>
					<view class="progress-bar">
						<view
							class="progress-fill"
							:class="item.percent >= 100 ? 'progress-fill-done' : 'progress-fill-pending'"
							:style="{ width: item.percent + '%' }"
						></view>
					</view>
				</view>
			</view>
		</view>

		<!-- 底部小卡片 -->
		<view class="mini-grid">
			<view class="mini-card">
				<text class="mini-label">连续记录</text>
				<view class="mini-value-row">
					<text class="mini-value">{{ streakDays }}</text>
					<text class="mini-unit">天</text>
				</view>
			</view>
			<view class="mini-card">
				<text class="mini-label">累计少抽</text>
				<view class="mini-value-row">
					<text class="mini-value">{{ reducedTotal }}</text>
					<text class="mini-unit">支</text>
				</view>
			</view>
		</view>

		<view class="bottom-safe"></view>
	</view>
</template>

<script setup>
import { ref, computed, onMounted, watch } from 'vue'
import { onShareAppMessage, onShow } from '@dcloudio/uni-app'
import { useLogin } from '@/hooks/useLogin'
import * as api from '@/api'

const { waitForLogin } = useLogin()
const navBarHeight = ref(0)

const tabs = [
	{ label: '周', value: 'week' },
	{ label: '月', value: 'month' },
	{ label: '年', value: 'year' }
]

const currentTab = ref('week')
const statsData = ref(null)
const weeklyStatsData = ref(null)

const WEEKDAY_NAMES = ['日', '一', '二', '三', '四', '五', '六']

const changePercent = computed(() => {
	const value = statsData.value?.change_percent
	if (value === undefined || value === null) return null
	const num = Number(value)
	return Number.isNaN(num) ? null : num
})

const insightEmoji = computed(() => {
	if (changePercent.value === null) return '新'
	return changePercent.value <= 0 ? '稳' : '警'
})

const insightIconClass = computed(() => {
	if (changePercent.value === null) return 'insight-neutral'
	return changePercent.value <= 0 ? 'insight-good' : 'insight-warn'
})

const insightText = computed(() => {
	if (changePercent.value === null) {
		return '本阶段数据逐步稳定，建议保持记录，下一周期可获得趋势对比。'
	}
	const abs = Math.abs(changePercent.value)
	if (changePercent.value <= 0) {
		return `较上期下降 ${abs}%，趋势向好，继续保持节奏。`
	}
	return `较上期上升 ${abs}%，留意高峰时段，尝试延迟第一支。`
})

const weeklyTrendRangeText = computed(() => {
	const start = weeklyStatsData.value?.start
	const end = weeklyStatsData.value?.end
	if (!start || !end) return '固定展示最近 7 天'
	return `${formatRangeText(start, end)} · 固定展示最近 7 天`
})

const statusText = computed(() => {
	if (changePercent.value === null) return '暂无对比'
	const sign = changePercent.value > 0 ? '+' : ''
	return `较上期 ${sign}${changePercent.value}%`
})

const statusChipClass = computed(() => {
	if (changePercent.value === null) return 'chip-neutral'
	return changePercent.value <= 0 ? 'chip-good' : 'chip-warn'
})

const statusArrow = computed(() => {
	if (changePercent.value === null) return '→'
	return changePercent.value <= 0 ? '↓' : '↑'
})

const statusIconClass = computed(() => {
	if (changePercent.value === null) return 'arrow-neutral'
	return changePercent.value <= 0 ? 'arrow-good' : 'arrow-warn'
})

const averageCount = computed(() => {
	const avg = statsData.value?.daily_average
	if (avg === undefined || avg === null) return 0
	return Number(avg) || 0
})

const weeklyAverageCount = computed(() => {
	const avg = weeklyStatsData.value?.daily_average
	if (avg === undefined || avg === null) return 0
	return Number(avg) || 0
})

const weeklyTrendItems = computed(() => {
	const trend = weeklyStatsData.value?.trend
	if (!trend || !Array.isArray(trend) || trend.length === 0) return []
	return trend.map((item, index) => {
		const count = Number(item.count) || 0
		const label = item.label || ''
		let weekday = ''
		let date = ''
		if (label.includes('-')) {
			const parts = label.split('-')
			const y = parseInt(parts[0], 10)
			const m = parseInt(parts[1], 10) - 1
			const d = parseInt(parts[2] || parts[1], 10)
			if (parts.length >= 3) {
				const dt = new Date(y, m, d)
				weekday = WEEKDAY_NAMES[dt.getDay()]
				date = String(d)
			} else {
				weekday = ''
				date = `${parseInt(parts[1], 10)}月`
			}
		} else {
			date = label
		}
		return { weekday, date, count, isHighlight: index === trend.length - 1 }
	})
})

function safeNumber(value) {
	if (value === undefined || value === null || value === '') return 0
	const num = Number(value)
	return Number.isNaN(num) ? 0 : num
}

function calDotClass(count) {
	if (count === 0) return 'cal-dot-zero'
	if (count <= 3) return 'cal-dot-low'
	if (count <= 8) return 'cal-dot-mid'
	return 'cal-dot-high'
}

const savedMoneyCent = computed(() => {
	const money = statsData.value?.money
	if (!money || !money.available) return 0
	return safeNumber(money.saved_cent)
})

const savedMoneyText = computed(() => {
	if (!moneyAvailable.value) return '--'
	return `¥${(savedMoneyCent.value / 100).toFixed(2)}`
})

const moneyAvailable = computed(() => !!statsData.value?.money?.available)

const moneyExpectedTotal = computed(() => {
	const money = statsData.value?.money
	if (!money || !money.available) return 0
	return safeNumber(money.expected_total)
})

const moneyActualTotal = computed(() => {
	const money = statsData.value?.money
	if (!money || !money.available) return 0
	return safeNumber(money.actual_total)
})

const moneySubtitle = computed(() => {
	if (!moneyAvailable.value) return '尚未解锁'
	return `预计 ${moneyExpectedTotal.value} 支`
})

const moneyTargetCent = computed(() => {
	const money = statsData.value?.money
	if (!money || !money.available) return 0
	const expectedTotal = safeNumber(money.expected_total)
	const packPriceCent = safeNumber(money.pack_price_cent)
	const cigsPerPack = safeNumber(money.cigs_per_pack)
	if (expectedTotal <= 0 || packPriceCent <= 0 || cigsPerPack <= 0) return 0
	return Math.round((expectedTotal / cigsPerPack) * packPriceCent)
})

const moneyPercent = computed(() => {
	const target = moneyTargetCent.value
	if (!moneyAvailable.value || target <= 0) return 0
	const percent = Math.round((savedMoneyCent.value / target) * 100)
	return Math.min(Math.max(percent, 0), 100)
})

const moneyTargetYuan = computed(() => {
	const target = moneyTargetCent.value
	if (target <= 0) return '0'
	return (target / 100).toFixed(0)
})

const moneyRingStyle = computed(() => {
	if (!moneyAvailable.value) {
		return { background: 'conic-gradient(#E2E8F0 0deg 360deg)' }
	}
	const angle = Math.round(moneyPercent.value * 3.6)
	return { background: `conic-gradient(#34C8A0 0deg ${angle}deg, #E8F8F3 ${angle}deg 360deg)` }
})

const moneyRingText = computed(() => {
	if (!moneyAvailable.value) return '--'
	return `${moneyPercent.value}%`
})

const healthStatusText = computed(() => {
	const health = statsData.value?.health
	if (!health || !health.available) return '暂无数据'
	const percent = Math.round(Number(health.lung_recovery_percent) || 0)
	if (percent >= 100) return '已达成'
	if (percent > 0) return `已恢复 ${percent}%`
	return '进行中'
})

const healthAvailable = computed(() => !!statsData.value?.health?.available)

const lungRecoveryPercent = computed(() => {
	const health = statsData.value?.health
	if (!health || !health.available) return 0
	const value = Number(health.lung_recovery_percent) || 0
	return Math.min(Math.max(Math.round(value), 0), 100)
})

const healthRingStyle = computed(() => {
	if (!healthAvailable.value) {
		return { background: 'conic-gradient(#E2E8F0 0deg 360deg)' }
	}
	const angle = Math.round(lungRecoveryPercent.value * 3.6)
	return { background: `conic-gradient(#34C8A0 0deg ${angle}deg, #E8F8F3 ${angle}deg 360deg)` }
})

const smokeFreeText = computed(() => {
	const health = statsData.value?.health
	if (!health || !health.available) return '0分钟'
	const total = Math.max(Number(health.smoke_free_minutes) || 0, 0)
	const days = Math.floor(total / 1440)
	const hours = Math.floor((total % 1440) / 60)
	const minutes = total % 60
	if (days > 0) return `${days}天${hours}小时`
	if (hours > 0) return `${hours}小时${minutes}分钟`
	return `${minutes}分钟`
})

const healthItems = computed(() => {
	const health = statsData.value?.health
	if (!health || !health.available || !health.milestones || health.milestones.length === 0) return []
	const minutes = health.smoke_free_minutes || 0
	return health.milestones.map(item => {
		if (item.reached) return { name: item.name, percent: 100 }
		const baseMinutes = item.minutes || 1
		const percent = Math.min(Math.round((minutes / baseMinutes) * 100), 100)
		return { name: item.name, percent }
	})
})

const streakDays = computed(() => statsData.value?.streak_days ?? 0)
const reducedTotal = computed(() => Math.max(moneyExpectedTotal.value - moneyActualTotal.value, 0))

function formatRangeText(start, end) {
	const startParts = start.split('-')
	const endParts = end.split('-')
	if (startParts.length < 3 || endParts.length < 3) return `${start} - ${end}`
	const startMonth = parseInt(startParts[1], 10)
	const startDay = parseInt(startParts[2], 10)
	const endMonth = parseInt(endParts[1], 10)
	const endDay = parseInt(endParts[2], 10)
	if (startMonth === endMonth) return `${startMonth}月${startDay}日-${endDay}日`
	return `${startMonth}月${startDay}日-${endMonth}月${endDay}日`
}

function setupNavBar() {
	const systemInfo = uni.getSystemInfoSync()
	const statusBarH = systemInfo.statusBarHeight || 0
	try {
		const menuBtn = uni.getMenuButtonBoundingClientRect()
		navBarHeight.value = menuBtn.bottom + (menuBtn.top - statusBarH)
	} catch (e) {
		navBarHeight.value = statusBarH + 44
	}
}

async function fetchStats() {
	try {
		await waitForLogin()
		const res = await api.getStats({ range: currentTab.value })
		statsData.value = res.data
	} catch (e) {
		console.error('fetchStats error:', e)
	}
}

async function fetchWeeklyStats() {
	try {
		await waitForLogin()
		const res = await api.getStats({ range: 'week' })
		weeklyStatsData.value = res.data
	} catch (e) {
		console.error('fetchWeeklyStats error:', e)
	}
}

function goCalendarDetail() {
	uni.navigateTo({ url: '/pages/stats-calendar/index' })
}

watch(currentTab, () => { fetchStats() })

onMounted(() => {
	setupNavBar()
	fetchStats()
	fetchWeeklyStats()
})

onShow(() => {
	fetchStats()
	fetchWeeklyStats()
})

onShareAppMessage(() => {
	return {
		title: '戒烟助手 - 我的戒烟数据分析',
		path: 'pages/index/index'
	}
})
</script>

<style scoped>
/* ── 页面 ── */
.page {
	min-height: 100vh;
	background: linear-gradient(180deg, #E6F7F2 0%, #F0FBF7 40%, #FAFFFE 100%);
	padding: 0 28rpx 0;
	box-sizing: border-box;
}

.status-bar {
	background: transparent;
}

.page-head {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 20rpx;
	margin: 10rpx 0 24rpx;
}

.page-title {
	display: block;
	font-size: 44rpx;
	font-weight: 800;
	line-height: 1.15;
	color: #0D3D2E;
}

.page-subtitle {
	display: block;
	margin-top: 8rpx;
	font-size: 23rpx;
	line-height: 1.5;
	color: #5D8F7C;
}

.head-chip {
	display: inline-flex;
	align-items: center;
	gap: 6rpx;
	flex-shrink: 0;
	padding: 10rpx 16rpx;
	border-radius: 999rpx;
	font-size: 21rpx;
	font-weight: 700;
	white-space: nowrap;
	border: 1.5rpx solid rgba(52, 200, 160, 0.12);
	background: rgba(255, 255, 255, 0.76);
}

.head-chip-arrow {
	font-size: 20rpx;
	font-weight: 800;
}

/* ── Tab 切换 ── */
.segment-wrap {
	position: relative;
	height: 112rpx;
	flex-shrink: 0;
	z-index: 20;
}

.segment {
	position: relative;
	z-index: 50;
	display: flex;
	background: rgba(255, 255, 255, 0.82);
	padding: 6rpx;
	border-radius: 22rpx;
	gap: 6rpx;
	border: 1.5rpx solid rgba(52, 200, 160, 0.14);
	box-shadow: 0 4rpx 16rpx rgba(52, 200, 160, 0.07);
	-webkit-backdrop-filter: blur(12px);
	backdrop-filter: blur(12px);
}

.segment::before {
	content: '';
	position: absolute;
	inset: -12rpx -8rpx -10rpx;
	border-radius: 34rpx;
	background: linear-gradient(180deg, rgba(230, 247, 242, 0.96) 0%, rgba(240, 251, 247, 0.88) 72%, rgba(240, 251, 247, 0) 100%);
	z-index: -1;
	pointer-events: none;
}

.segment-item {
	flex: 1;
	text-align: center;
	padding: 14rpx 0;
	font-size: 24rpx;
	font-weight: 600;
	color: #7aA898;
	border-radius: 16rpx;
}

.segment-active {
	background: #FFFFFF;
	color: #0D3D2E;
	box-shadow: 0 4rpx 12rpx rgba(52, 200, 160, 0.12);
}

/* ── 洞察卡片 ── */
.insight-card {
	display: flex;
	gap: 18rpx;
	align-items: flex-start;
	background: rgba(255, 255, 255, 0.88);
	border: 1.5rpx solid rgba(52, 200, 160, 0.14);
	border-radius: 24rpx;
	padding: 22rpx;
	margin-bottom: 20rpx;
	box-shadow: 0 4rpx 18rpx rgba(52, 200, 160, 0.07);
}

.insight-icon {
	width: 56rpx;
	height: 56rpx;
	border-radius: 16rpx;
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
}

.insight-good {
	background: rgba(52, 200, 160, 0.15);
	color: #1a8c62;
}

.insight-warn {
	background: rgba(251, 191, 36, 0.18);
	color: #B45309;
}

.insight-neutral {
	background: rgba(52, 200, 160, 0.08);
	color: #52806E;
}

.insight-glyph {
	font-size: 22rpx;
	font-weight: 700;
}

.insight-title {
	font-size: 24rpx;
	font-weight: 600;
	color: #0D3D2E;
	display: block;
	margin-bottom: 6rpx;
}

.insight-desc {
	font-size: 23rpx;
	color: #52806E;
	line-height: 1.6;
}

/* ── 通用卡片 ── */
.card {
	background: rgba(255, 255, 255, 0.88);
	border-radius: 24rpx;
	padding: 24rpx;
	margin-bottom: 20rpx;
	border: 1.5rpx solid rgba(52, 200, 160, 0.14);
	box-shadow: 0 4rpx 18rpx rgba(52, 200, 160, 0.07);
}

.card-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	margin-bottom: 16rpx;
}

.card-link {
	flex-shrink: 0;
	padding: 8rpx 16rpx;
	border-radius: 999rpx;
	background: rgba(52, 200, 160, 0.08);
	font-size: 22rpx;
	font-weight: 600;
	color: #1a8c62;
}

.card-title-row {
	display: flex;
	align-items: center;
	gap: 10rpx;
}

.card-title {
	font-size: 28rpx;
	font-weight: 600;
	color: #0D3D2E;
}

.card-sub {
	font-size: 21rpx;
	color: #7aA898;
	margin-top: 4rpx;
	display: block;
}

.chip-good {
	background: rgba(52, 200, 160, 0.12);
	color: #1a8c62;
}

.chip-warn {
	background: rgba(251, 191, 36, 0.14);
	color: #B45309;
}

.chip-neutral {
	background: rgba(52, 200, 160, 0.06);
	color: #7aA898;
}

.status-arrow {
	font-size: 18rpx;
	font-weight: 700;
}

.arrow-good { color: #1a8c62; }
.arrow-warn { color: #D97706; }
.arrow-neutral { color: #7aA898; }

/* ── 日均 ── */
.avg-row {
	display: flex;
	align-items: baseline;
	gap: 8rpx;
	margin-bottom: 20rpx;
}

.avg-value {
	font-size: 52rpx;
	font-weight: 700;
	color: #0D3D2E;
}

.avg-unit {
	font-size: 22rpx;
	color: #7aA898;
}

/* ── 日历格式趋势 ── */
.cal-grid {
	display: flex;
	gap: 0;
}

.cal-cell {
	flex: 1;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 8rpx;
	padding: 10rpx 0;
}

.cal-cell-today {
	position: relative;
}

.cal-cell-today::before {
	content: '';
	position: absolute;
	inset: 2rpx;
	border-radius: 16rpx;
	background: rgba(52, 200, 160, 0.06);
}

.cal-weekday {
	font-size: 20rpx;
	color: #7aA898;
	font-weight: 500;
	position: relative;
}

.cal-date {
	font-size: 26rpx;
	font-weight: 600;
	color: #0D3D2E;
	position: relative;
}

.cal-dot {
	width: 52rpx;
	height: 52rpx;
	border-radius: 14rpx;
	display: flex;
	align-items: center;
	justify-content: center;
	position: relative;
}

.cal-dot-zero {
	background: rgba(52, 200, 160, 0.06);
}

.cal-dot-low {
	background: rgba(52, 200, 160, 0.18);
}

.cal-dot-mid {
	background: rgba(251, 191, 36, 0.2);
}

.cal-dot-high {
	background: rgba(239, 68, 68, 0.15);
}

.cal-count {
	font-size: 22rpx;
	font-weight: 700;
	color: #0D3D2E;
}

.cal-dot-zero .cal-count {
	color: #9CC5B5;
}

.cal-dot-high .cal-count {
	color: #DC2626;
}

/* ── 空状态 ── */
.empty-block {
	padding: 28rpx 24rpx;
	border-radius: 20rpx;
	background: rgba(52, 200, 160, 0.05);
	display: flex;
	align-items: center;
	gap: 18rpx;
}

.empty-block-dashed {
	border: 2rpx dashed rgba(52, 200, 160, 0.2);
	background: transparent;
}

.empty-visual {
	width: 78rpx;
	height: 78rpx;
	border-radius: 24rpx;
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	box-shadow: inset 0 1rpx 0 rgba(255, 255, 255, 0.8);
}

.empty-visual-trend {
	background: linear-gradient(180deg, rgba(52, 200, 160, 0.16) 0%, rgba(52, 200, 160, 0.08) 100%);
}

.empty-visual-money {
	background: linear-gradient(180deg, rgba(251, 191, 36, 0.18) 0%, rgba(245, 158, 11, 0.08) 100%);
}

.empty-visual-health {
	background: linear-gradient(180deg, rgba(52, 200, 160, 0.18) 0%, rgba(59, 130, 246, 0.08) 100%);
}

.empty-visual-glyph {
	font-size: 28rpx;
	font-weight: 800;
	color: #0D3D2E;
}

.empty-copy {
	flex: 1;
	min-width: 0;
}

.empty-title {
	display: block;
	font-size: 24rpx;
	font-weight: 700;
	color: #0D3D2E;
	margin-bottom: 6rpx;
}

.empty-text {
	font-size: 24rpx;
	line-height: 1.6;
	color: #7aA898;
}

/* ── 节省金额 ── */
.money-body {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 20rpx;
}

.money-left {
	flex: 1;
}

.money-value {
	font-size: 42rpx;
	font-weight: 700;
	color: #0D3D2E;
	margin-bottom: 12rpx;
	display: block;
}

.money-target {
	font-size: 21rpx;
	color: #7aA898;
	margin-top: 8rpx;
	display: block;
}

.metric-chips {
	display: flex;
	gap: 12rpx;
	margin-top: 16rpx;
}

.metric-chip {
	flex: 1;
	display: flex;
	align-items: baseline;
	justify-content: center;
	gap: 6rpx;
	padding: 8rpx 12rpx;
	border-radius: 12rpx;
	font-weight: 600;
}

.metric-chip-warm {
	background: rgba(52, 200, 160, 0.08);
	color: #1a8c62;
}

.metric-chip-cool {
	background: rgba(59, 130, 246, 0.08);
	color: #2563EB;
}

.metric-label {
	font-size: 20rpx;
	opacity: 0.8;
}

.metric-val {
	font-size: 24rpx;
}

.metric-unit {
	font-size: 20rpx;
	opacity: 0.7;
}

/* ── 进度条 ── */
.progress-bar {
	height: 10rpx;
	background: rgba(52, 200, 160, 0.1);
	border-radius: 999rpx;
	overflow: hidden;
}

.progress-fill {
	height: 100%;
	border-radius: 999rpx;
}

.progress-fill-money {
	background: linear-gradient(90deg, #34C8A0, #3DD9AE);
}

.progress-fill-done {
	background: linear-gradient(90deg, #34C8A0, #3DD9AE);
}

.progress-fill-pending {
	background: rgba(52, 200, 160, 0.3);
}

/* ── 圆环 ── */
.ring {
	width: 110rpx;
	height: 110rpx;
	border-radius: 50%;
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
}

.ring-inner {
	width: 82rpx;
	height: 82rpx;
	border-radius: 50%;
	background: #FFFFFF;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 2rpx;
	box-shadow: 0 4rpx 12rpx rgba(52, 200, 160, 0.1);
}

.ring-value {
	font-size: 22rpx;
	font-weight: 700;
	color: #0D3D2E;
}

.ring-label {
	font-size: 16rpx;
	color: #7aA898;
}

/* ── 徽章 ── */
.badge {
	font-size: 20rpx;
	padding: 6rpx 14rpx;
	border-radius: 999rpx;
	background: rgba(52, 200, 160, 0.12);
	color: #1a8c62;
	font-weight: 600;
}

.badge-muted {
	background: rgba(52, 200, 160, 0.06);
	color: #7aA898;
}

/* ── 健康概览 ── */
.health-overview {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16rpx;
	margin-bottom: 20rpx;
}

.health-stat {
	flex: 1;
	background: rgba(52, 200, 160, 0.06);
	border-radius: 16rpx;
	padding: 18rpx;
	border: 1.5rpx solid rgba(52, 200, 160, 0.12);
}

.health-stat-value {
	display: block;
	font-size: 28rpx;
	font-weight: 700;
	color: #0D3D2E;
	margin-bottom: 4rpx;
}

.health-stat-label {
	font-size: 20rpx;
	color: #7aA898;
}

/* ── 健康列表 ── */
.health-list {
	display: flex;
	flex-direction: column;
	gap: 14rpx;
}

.health-item-top {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-bottom: 6rpx;
}

.health-item-name {
	font-size: 23rpx;
	color: #0D3D2E;
	font-weight: 500;
}

.health-item-pct {
	font-size: 21rpx;
	color: #7aA898;
	font-weight: 600;
}

.health-item-pct-done {
	color: #1a8c62;
}

/* ── 底部小卡片 ── */
.mini-grid {
	display: flex;
	gap: 16rpx;
	margin-bottom: 20rpx;
}

.mini-card {
	flex: 1;
	background: rgba(255, 255, 255, 0.88);
	border-radius: 20rpx;
	padding: 22rpx;
	border: 1.5rpx solid rgba(52, 200, 160, 0.14);
	box-shadow: 0 4rpx 18rpx rgba(52, 200, 160, 0.07);
}

.mini-label {
	font-size: 22rpx;
	color: #7aA898;
	margin-bottom: 8rpx;
	display: block;
}

.mini-value-row {
	display: flex;
	align-items: baseline;
	gap: 6rpx;
}

.mini-value {
	font-size: 40rpx;
	font-weight: 700;
	color: #0D3D2E;
}

.mini-unit {
	font-size: 21rpx;
	color: #7aA898;
}

.bottom-safe {
	height: calc(32rpx + env(safe-area-inset-bottom));
}
</style>
