<template>
  <view class="naming-detail">
    <!-- Starry Background -->
    <view class="starry-bg">
      <view v-for="star in stars" :key="star.id" class="star" :style="{
        top: star.top,
        left: star.left,
        width: star.size + 'px',
        height: star.size + 'px',
        animationDuration: star.duration + 's',
        animationDelay: star.delay + 's',
      }"></view>
      <view class="glow-top"></view>
      <view class="glow-bottom"></view>
    </view>

    <!-- Header -->
    <view class="detail-header">
      <view class="detail-header-back" @click="handleBack">
        <text class="back-icon">‹</text>
        <text class="back-text">返回</text>
      </view>
      <text class="detail-header-title">详解报告</text>
      <view class="detail-header-download" @click="handleDownloadPdf">
        <text class="detail-header-download-icon">↓</text>
        <text class="detail-header-download-text">下载PDF</text>
      </view>
    </view>

    <!-- Content -->
    <scroll-view scroll-y class="detail-content">
      <!-- 1. 总分卡片 -->
      <view class="score-card clickable" @click="openScoreDetail">
        <view class="score-corner score-corner-tl"></view>
        <view class="score-corner score-corner-tr"></view>
        <view class="score-corner score-corner-bl"></view>
        <view class="score-corner score-corner-br"></view>

        <view class="score-label">Total Score</view>
        <view class="score-value-wrap">
          <text class="score-value">{{ report.header.score }}</text>
          <view class="score-ring"></view>
        </view>

        <view class="score-stars">
          <text v-for="i in 5" :key="i" class="score-star" :class="{ active: i <= report.header.stars }">★</text>
        </view>

        <view class="score-divider"></view>

        <text class="score-name">{{ report.header.name }}</text>
        <text class="score-pinyin">{{ report.header.pinyin }}</text>
      </view>

      <!-- 2. 五行生克与八卦（放第一位） -->
      <view v-if="hasDetailWuxingBagua" class="section">
        <view class="section-title">
          <text class="section-icon">☰</text>
          <text class="section-text">五行生克与八卦</text>
        </view>
        <view class="wuge-card clickable" @click="openWuxingBaguaDetail">
          <text v-if="detailWuxingBaguaPreview[0]" class="info-card-title">{{ detailWuxingBaguaPreview[0] }}</text>
          <text v-if="detailWuxingBaguaPreview[1]" class="info-card-text">{{ detailWuxingBaguaPreview[1] }}</text>
          <text v-if="detailWuxingBaguaPreview[2]" class="info-card-text">{{ detailWuxingBaguaPreview[2] }}</text>
        </view>
      </view>

      <!-- 2a. 五行单字详解（用于“五行八卦”补全每个字） -->
      <view v-if="hasCharDetail" class="section">
        <view class="section-title">
          <text class="section-icon">字</text>
          <text class="section-text">五行单字详解</text>
        </view>
        <view class="info-card clickable" @click="openCharDetail">
          <text v-for="(it, idx) in charDetailPreview" :key="idx" class="info-card-text">{{ charDetailLine(it) }}</text>
          <text v-if="charDetailItems.length > 2" class="info-card-text muted">查看更多…</text>
        </view>
      </view>

      <!-- 2b. 八字与姓名五行（喜用 · 生克 · 补益） -->
      <view v-if="hasDetailBazi" class="section">
        <view class="section-title">
          <text class="section-icon">⚖</text>
          <text class="section-text">八字与姓名五行</text>
        </view>
        <view class="zodiac-card clickable" @click="openBaziNameFitDetail">
          <view class="zodiac-header">
            <view class="zodiac-info">
              <text v-if="detailBaziLines[0]" class="info-card-text">{{ detailBaziLines[0] }}</text>
              <text v-if="detailBaziLines[1]" class="info-card-text">{{ detailBaziLines[1] }}</text>
              <text v-if="detailBaziLines[2]" class="info-card-text">{{ detailBaziLines[2] }}</text>
            </view>
            <text
              v-if="detailBaziScoreText"
              class="zodiac-score"
            >{{ detailBaziScoreText }}</text>
          </view>
        </view>
      </view>

      <!-- 2c. 字义与生肖解析 -->
      <view
        v-if="report.meaningZodiac.meaning || report.meaningZodiac.judge || report.meaningZodiac.zodiac.value || report.meaningZodiac.zodiac.desc"
        class="section">
        <view class="section-title">
          <text class="section-icon">📖</text>
          <text class="section-text">字义与生肖解析</text>
        </view>

        <view class="meaning-card clickable" @click="openMeaningDetail">
          <view class="meaning-quote">❝</view>
          <text class="meaning-label">名字寓意</text>
          <text class="meaning-text">{{ report.meaningZodiac.meaning }}</text>
          <view class="meaning-judge">
            <text class="meaning-judge-label">判断：</text>
            <text class="meaning-judge-text">{{ report.meaningZodiac.judge }}</text>
          </view>
        </view>

        <view class="zodiac-card clickable" @click="openMeaningDetail">
          <view class="zodiac-header">
            <view class="zodiac-icon-wrap">
              <text class="zodiac-icon">{{ report.meaningZodiac.zodiac.icon }}</text>
            </view>
            <view class="zodiac-info">
              <text class="zodiac-label">{{ report.meaningZodiac.zodiac.label }}</text>
              <text class="zodiac-value">{{ report.meaningZodiac.zodiac.value }}</text>
            </view>
            <text class="zodiac-score">{{ report.meaningZodiac.zodiac.scoreText }}</text>
          </view>
          <text class="zodiac-desc">
            {{ report.meaningZodiac.zodiac.desc }}
          </text>
        </view>
      </view>

      <!-- 2d. 属相与名字合宜 -->
      <view v-if="hasDetailZodiacSign" class="section">
        <view class="section-title">
          <text class="section-icon">🐲</text>
          <text class="section-text">属相与名字</text>
        </view>
        <view class="zodiac-card clickable" @click="openZodiacSignDetail">
          <view class="zodiac-header">
            <view class="zodiac-icon-wrap">
              <text class="zodiac-icon">{{ detailZodiacIcon }}</text>
            </view>
            <view class="zodiac-info">
              <text class="zodiac-label">生肖</text>
              <text class="zodiac-value">{{ detailZodiacTitle }}</text>
              <text v-if="detailZodiacHarmony" class="zodiac-desc">{{ detailZodiacHarmony }}</text>
            </view>
          </view>
        </view>
      </view>

      <!-- 3. 家族与起名原理 -->
      <view v-if="report.family.cards.length" class="section">
        <view class="section-title">
          <text class="section-icon">👥</text>
          <text class="section-text">家族与起名原理</text>
        </view>

        <view v-for="(card, idx) in report.family.cards" :key="idx" class="info-card clickable"
          @click="openFamilyDetail">
          <text class="info-card-title">{{ card.title }}</text>
          <text class="info-card-text">{{ card.text }}</text>
        </view>
      </view>

      <!-- 4. 笔画数理分析 -->
      <view v-if="report.stroke.wuge.items.length || report.stroke.wuxing.items.length" class="section">
        <view class="section-title">
          <text class="section-icon">#</text>
          <text class="section-text">笔画数理分析</text>
        </view>

        <view class="wuge-card clickable" @click="openWugeDetail">
          <view class="wuge-header">
            <text class="wuge-label">三才五格配置</text>
            <text class="wuge-badge">{{ report.stroke.wuge.badge }}</text>
          </view>

          <view v-for="(it, idx) in report.stroke.wuge.items" :key="idx" class="wuge-item">
            <view class="wuge-item-header">
              <text class="wuge-item-name" :class="it.primary ? 'wuge-item-name-primary' : ''">{{ it.name }}</text>
              <text class="wuge-item-result" :class="it.primary ? 'wuge-item-result-primary' : ''">{{ it.result
              }}</text>
            </view>
            <view class="wuge-bar">
              <view class="wuge-bar-fill" :style="{ width: it.percent + '%', background: it.color }"></view>
            </view>
          </view>
        </view>

        <!-- 五行能量分布 -->
        <view v-if="report.stroke.wuxing.items.length" class="wuxing-card clickable" @click="openWuxingDetail">
          <text class="wuxing-title">{{ report.stroke.wuxing.title }}</text>
          <view class="wuxing-list">
            <view v-for="item in wuxingData" :key="item.label" class="wuxing-item">
              <text class="wuxing-label">{{ item.label }}</text>
              <view class="wuxing-bar">
                <view class="wuxing-bar-fill" :style="{ width: item.value + '%', background: item.color }"></view>
              </view>
              <text class="wuxing-value">{{ item.value }}%</text>
            </view>
          </view>
        </view>
      </view>

      <!-- 5. 三才配置深度解析 -->
      <view v-if="report.sancai.items.length || report.sancai.configText || report.sancai.badge" class="section">
        <view class="section-title">
          <text class="section-icon">⊞</text>
          <text class="section-text">三才配置深度解析</text>
        </view>

        <view class="sancai-card clickable" @click="openSancaiDetail">
          <view class="sancai-header">
            <view class="sancai-config">
              <text class="sancai-config-text">{{ report.sancai.configText }}</text>
              <text class="sancai-config-label">{{ report.sancai.configLabel }}</text>
            </view>
            <text class="sancai-badge">{{ report.sancai.badge }}</text>
          </view>

          <view v-for="(it, idx) in report.sancai.items" :key="idx" class="sancai-item">
            <text :class="it.primary ? 'sancai-item-label' : 'sancai-item-label-normal'">{{ it.label }}</text>
            <text class="sancai-item-text">{{ it.text }}</text>
          </view>
        </view>
      </view>

      <!-- 6. 潜在性格剖析 -->
      <view v-if="report.personality.strengths.items.length || report.personality.challenges.items.length"
        class="section">
        <view class="section-title">
          <text class="section-icon">👤</text>
          <text class="section-text">潜在性格剖析</text>
        </view>

        <view class="personality-grid">
          <view class="personality-card personality-card-strength clickable" @click="openPersonalityDetail('strength')">
            <text class="personality-title personality-title-gold">{{ report.personality.strengths.title }}</text>
            <view class="personality-list">
              <view v-for="(t, idx) in report.personality.strengths.items" :key="idx" class="personality-item">
                <view class="personality-dot personality-dot-gold"></view>
                <text class="personality-text">{{ t }}</text>
              </view>
            </view>
          </view>

          <view class="personality-card personality-card-challenge clickable"
            @click="openPersonalityDetail('challenge')">
            <text class="personality-title personality-title-red">{{ report.personality.challenges.title }}</text>
            <view class="personality-list">
              <view v-for="(t, idx) in report.personality.challenges.items" :key="idx" class="personality-item">
                <view class="personality-dot personality-dot-red"></view>
                <text class="personality-text">{{ t }}</text>
              </view>
            </view>
          </view>
        </view>
      </view>

      <!-- 7. 周易卦象 -->
      <view v-if="report.gua.name || report.gua.desc || report.gua.lines.length" class="section">
        <view class="section-title">
          <text class="section-icon">☯</text>
          <text class="section-text">周易卦象</text>
        </view>

        <view class="gua-card clickable" @click="openGuaDetail">
          <view class="gua-bg-text">{{ report.gua.bgText }}</view>
          <view class="gua-content">
            <view class="gua-symbol">
              <view v-for="(ln, idx) in report.gua.lines" :key="idx">
                <view v-if="ln === 'solid'" class="gua-line gua-line-solid"></view>
                <view v-else class="gua-line gua-line-broken">
                  <view class="gua-line-part"></view>
                  <view class="gua-line-part"></view>
                </view>
                <view v-if="idx === 2" class="gua-spacer"></view>
              </view>
            </view>
            <view class="gua-info">
              <view class="gua-header">
                <text class="gua-name">{{ report.gua.name }}</text>
                <text class="gua-badge">{{ report.gua.badge }}</text>
              </view>
              <text class="gua-desc">{{ report.gua.desc }}</text>
            </view>
          </view>
        </view>
      </view>

      <!-- 8. 开运锦囊 -->
      <view v-if="report.lucky.cards.length || report.lucky.health.value || report.lucky.health.note" class="section">
        <view class="section-title">
          <text class="section-icon">☀</text>
          <text class="section-text">开运锦囊</text>
        </view>

        <view class="lucky-grid">
          <view v-for="(c, idx) in report.lucky.cards" :key="idx" class="lucky-card clickable"
            @click="openLuckyDetail(c.key)">
            <view class="lucky-icon" :class="c.iconClass">{{ c.icon }}</view>
            <view class="lucky-info">
              <text class="lucky-label">{{ c.label }}</text>
              <text class="lucky-value">{{ c.value }}</text>
            </view>
          </view>
        </view>

        <view class="health-card clickable" @click="openHealthDetail">
          <view class="health-icon">❤</view>
          <view class="health-info">
            <view class="health-header">
              <text class="health-label">健康易感提示</text>
              <text class="health-note">{{ report.lucky.health.note }}</text>
            </view>
            <text class="health-value">{{ report.lucky.health.value }}</text>
          </view>
        </view>
      </view>

      <!-- 9. 六维格局 -->
      <SixDimensionRadar v-if="report.sixDimension.labels.length && report.sixDimension.values.length"
        :labels="report.sixDimension.labels" :values="report.sixDimension.values"
        :remark="report.sixDimension.remark" />

      <!-- 10. 人生运程模拟 -->
      <view v-if="report.fortune.labels.length || report.fortune.note" class="section">
        <view class="section-title">
          <text class="section-icon">📈</text>
          <text class="section-text">人生运程模拟</text>
        </view>

        <view class="fortune-card clickable" @click="openFortuneDetail">
          <view class="fortune-chart">
            <view class="fortune-line">
              <view class="fortune-point fortune-point-1"></view>
              <view class="fortune-point fortune-point-2"></view>
              <view class="fortune-point fortune-point-3"></view>
              <view class="fortune-point fortune-point-4"></view>
            </view>
            <view class="fortune-labels">
              <view v-for="(lb, idx) in report.fortune.labels" :key="idx" class="fortune-label-item"
                :class="lb.peak ? 'fortune-label-peak' : ''">
                <text class="fortune-label-text">{{ lb.text }}</text>
              </view>
            </view>
          </view>
          <text class="fortune-note">{{ report.fortune.note }}</text>
        </view>
      </view>

      <!-- 11. 情感与社交运势 -->
      <view v-if="report.emotion.title || report.emotion.desc || report.emotion.tags.length" class="section">
        <view class="section-title">
          <text class="section-icon">💕</text>
          <text class="section-text">情感与社交运势</text>
        </view>

        <view class="emotion-card clickable" @click="openEmotionDetail">
          <view class="emotion-header">
            <view class="emotion-icon-wrap">
              <text class="emotion-icon">💗</text>
            </view>
            <view class="emotion-info">
              <text class="emotion-title">{{ report.emotion.title }}</text>
              <text class="emotion-desc">{{ report.emotion.desc }}</text>
            </view>
          </view>
          <view class="emotion-divider"></view>
          <view class="emotion-tags-section">
            <text class="emotion-tags-title">{{ report.emotion.tagsTitle }}</text>
            <view class="emotion-tags">
              <text v-for="(t, idx) in report.emotion.tags" :key="idx" class="emotion-tag"
                :class="idx === 0 ? 'emotion-tag-primary' : ''">{{ t }}</text>
            </view>
          </view>
        </view>
      </view>

      <!-- 12. 日常生活开运指南 -->
      <view v-if="report.daily.cards.length || report.daily.avatar.items.length" class="section">
        <view class="section-title">
          <text class="section-icon">✨</text>
          <text class="section-text">日常生活开运指南</text>
        </view>

        <view class="daily-grid">
          <view v-for="(c, idx) in report.daily.cards" :key="idx" class="daily-card clickable" @click="openDailyDetail">
            <text class="daily-label">{{ c.title }}</text>
            <template v-if="c.type === 'time'">
              <view v-for="(t, i) in c.times" :key="i" class="daily-time-item">
                <text class="daily-time-icon">{{ t.icon }}</text>
                <text class="daily-time-text">{{ t.text }}</text>
              </view>
            </template>
            <template v-else>
              <view class="daily-items">
                <view v-for="(it, i) in c.items" :key="i" :class="it.class">{{ it.text }}</view>
              </view>
              <text class="daily-tip">{{ c.tip }}</text>
            </template>
          </view>
        </view>

        <!-- 开运头像风格推荐 -->
        <view class="avatar-card">
          <text class="avatar-label">{{ report.daily.avatar.label }}</text>
          <view class="avatar-list">
            <view v-for="(it, idx) in report.daily.avatar.items" :key="idx" :class="it.class">
              <text class="avatar-text">{{ it.text }}</text>
            </view>
          </view>
        </view>
      </view>

      <!-- 13. 诗词出处 -->
      <view v-if="report.poetry.text" class="section">
        <view class="section-title">
          <text class="section-icon">📜</text>
          <text class="section-text">诗词出处</text>
        </view>

        <view class="poetry-card">
          <view class="poetry-quote">❝</view>
          <text class="poetry-text">"{{ report.poetry.text }}"</text>
        </view>
      </view>

      <!-- Action Buttons -->
      <view class="action-buttons">
        <!-- <view class="action-btn action-btn-share">
          <text class="action-btn-text">生成海报</text>
        </view> -->
        <view class="action-btn action-btn-primary" @click="handleWealthAnalysis">
          <text class="action-btn-text">财运解析</text>
        </view>
        <!-- <view class="action-btn action-btn-download">
          <text class="action-btn-text">下载报告</text>
        </view> -->
      </view>

      <!-- Footer -->
      <view class="detail-footer">
        <text class="footer-text">壹梵 · 致力于东方美学与易经智慧的传承</text>
      </view>
    </scroll-view>

    <view v-if="showDetailModal" class="detail-modal-overlay" @click.stop="closeDetailModal">
      <view class="detail-modal" @click.stop="">
        <view class="detail-modal-head">
          <text class="detail-modal-title">{{ detailModalTitle }}</text>
          <view class="detail-modal-close" @click.stop="closeDetailModal"><text class="detail-modal-close-text">×</text>
          </view>
        </view>
        <scroll-view scroll-y class="detail-modal-body">
          <view class="detail-modal-content">
            <text v-for="(t, i) in detailModalLines" :key="i" class="detail-modal-text">{{ t }}</text>
          </view>
        </scroll-view>
      </view>
    </view>
  </view>
</template>

<script setup lang="ts">
import { ref, computed } from "vue";
import SixDimensionRadar from "../SixDimensionRadar.vue";
import { getWealthAnalysisByReportId } from "@/api/cai-yun";
import pdfBgUrl from "../../utils/pdf/background.png";

const props = defineProps<{
  data: any | null;
}>();

const emit = defineEmits<{
  back: [];
  wealthAnalysis: [any];
}>();

type DetailBlock = { title: string; lines: string[] };

type PersonalNamingReport = {
  header: {
    score: number;
    stars: number;
    name: string;
    pinyin: string;
  };
  meaningZodiac: {
    meaning: string;
    judge: string;
    zodiac: {
      icon: string;
      label: string;
      value: string;
      scoreText: string;
      desc: string;
    };
  };
  family: {
    cards: Array<{ title: string; text: string }>;
  };
  stroke: {
    wuge: {
      badge: string;
      items: Array<{
        name: string;
        result: string;
        primary?: boolean;
        percent: number;
        color: string;
      }>;
    };
    wuxing: {
      title: string;
      items: Array<{ label: string; value: number; color: string }>;
    };
  };
  sancai: {
    configText: string;
    configLabel: string;
    badge: string;
    items: Array<{ label: string; text: string; primary?: boolean }>;
  };
  personality: {
    strengths: { title: string; items: string[] };
    challenges: { title: string; items: string[] };
  };
  gua: {
    bgText: string;
    name: string;
    badge: string;
    desc: string;
    lines: Array<'solid' | 'broken'>;
  };
  lucky: {
    cards: Array<{ key: 'color' | 'number' | 'industry' | 'constellation'; icon: string; iconClass: string; label: string; value: string }>;
    health: { note: string; value: string };
  };
  sixDimension: { labels: string[]; values: number[]; remark: string };
  fortune: { labels: Array<{ text: string; peak?: boolean }>; note: string };
  emotion: { title: string; desc: string; tagsTitle: string; tags: string[] };
  daily: {
    cards: Array<
      | { type: 'time'; title: string; times: Array<{ icon: string; text: string }> }
      | { type: 'wear'; title: string; items: Array<{ text: string; class: string }>; tip: string }
    >;
    avatar: { label: string; items: Array<{ text: string; class: string }> };
  };
  poetry: { text: string };
  /** 与测名详解同构：五行生克、八字与名、属相与名 */
  detailModules?: {
    bazi_name_fit?: any;
    wuxing_bagua?: any;
    zodiac_sign?: any;
    /** 单字五行/阴阳/卦象（用于“五行八卦”里展示每个字） */
    char_detail?: any;
  };
  details: {
    score: DetailBlock;
    meaning: DetailBlock;
    family: DetailBlock;
    wuge: DetailBlock;
    wuxing: DetailBlock;
    sancai: DetailBlock;
    personality_strength: DetailBlock;
    personality_challenge: DetailBlock;
    gua: DetailBlock;
    lucky: Record<'color' | 'number' | 'industry' | 'constellation', DetailBlock>;
    health: DetailBlock;
    fortune: DetailBlock;
    emotion: DetailBlock;
    daily: DetailBlock;
  };
};

const normalizePersonalReport = (raw: any): PersonalNamingReport => {
  if (raw && raw.header && raw.meaningZodiac && raw.stroke && raw.details) {
    const legacy = raw as any;
    return {
      ...legacy,
      detailModules: {
        bazi_name_fit: legacy?.bazi_name_fit,
        wuxing_bagua: legacy?.wuxing_bagua,
        zodiac_sign: legacy?.zodiac_sign,
        char_detail: legacy?.char_detail,
      },
      family: {
        cards: Array.isArray(legacy?.family?.cards) ? legacy.family.cards : [],
      },
      stroke: {
        ...legacy?.stroke,
        wuge: {
          ...(legacy?.stroke?.wuge || {}),
          items: Array.isArray(legacy?.stroke?.wuge?.items) ? legacy.stroke.wuge.items : [],
        },
        wuxing: {
          ...(legacy?.stroke?.wuxing || {}),
          items: Array.isArray(legacy?.stroke?.wuxing?.items) ? legacy.stroke.wuxing.items : [],
        },
      },
      sancai: {
        ...(legacy?.sancai || {}),
        configText: String(legacy?.sancai?.configText || ''),
        configLabel: String(legacy?.sancai?.configLabel || '(天 - 人 - 地)'),
        badge: String(legacy?.sancai?.badge || ''),
        items: Array.isArray(legacy?.sancai?.items) ? legacy.sancai.items.filter(Boolean) : [],
      },
      personality: {
        strengths: {
          ...(legacy?.personality?.strengths || {}),
          items: Array.isArray(legacy?.personality?.strengths?.items) ? legacy.personality.strengths.items : [],
        },
        challenges: {
          ...(legacy?.personality?.challenges || {}),
          items: Array.isArray(legacy?.personality?.challenges?.items) ? legacy.personality.challenges.items : [],
        },
      },
      gua: {
        ...(legacy?.gua || {}),
        lines: Array.isArray(legacy?.gua?.lines) ? legacy.gua.lines : [],
      },
      lucky: {
        ...(legacy?.lucky || {}),
        cards: Array.isArray(legacy?.lucky?.cards) ? legacy.lucky.cards : [],
        health: legacy?.lucky?.health || { note: '', value: '' },
      },
      sixDimension: {
        ...(legacy?.sixDimension || {}),
        labels: Array.isArray(legacy?.sixDimension?.labels) ? legacy.sixDimension.labels : [],
        values: Array.isArray(legacy?.sixDimension?.values) ? legacy.sixDimension.values : [],
      },
      fortune: {
        ...(legacy?.fortune || {}),
        labels: Array.isArray(legacy?.fortune?.labels) ? legacy.fortune.labels : [],
      },
      emotion: {
        ...(legacy?.emotion || {}),
        tags: Array.isArray(legacy?.emotion?.tags) ? legacy.emotion.tags : [],
      },
      daily: {
        cards: Array.isArray(legacy?.daily?.cards) ? legacy.daily.cards : [],
        avatar: {
          label: String(legacy?.daily?.avatar?.label || ''),
          items: Array.isArray(legacy?.daily?.avatar?.items) ? legacy.daily.avatar.items : [],
        },
      },
    } as PersonalNamingReport;
  }

  const name = String(raw?.name || '');
  const pinyin = String(raw?.pinyin || '');
  const score = Number(raw?.total_score ?? raw?.score ?? 0);
  const stars = Number(raw?.star_rating ?? 0);
  const meaning = String(raw?.name_meaning ?? raw?.meaning ?? '');
  const poetrySource = String(raw?.poetry_source ?? raw?.source ?? '');

  const toLines = (v: any): string[] => {
    if (typeof v !== 'string') return [];
    const s = v.trim();
    if (!s) return [];
    return s.split(/\r?\n/).map((x) => x.trim()).filter(Boolean);
  };

  const zodiacAnalysis = String(raw?.zodiac_analysis ?? '');
  const wuxingAnalysis = String(raw?.wuxing_analysis ?? '');
  const sancaiAnalysis = String(raw?.sancai_analysis ?? '');
  const strokeAnalysis = String(raw?.stroke_analysis ?? '');

  const sixDim = raw?.six_dimension;
  const sixLabels = sixDim && typeof sixDim === 'object'
    ? Object.keys(sixDim)
    : [];
  const sixValues = sixDim && typeof sixDim === 'object'
    ? Object.values(sixDim).map((n: any) => Number(n) || 0)
    : [];

  const derivedStars = stars || (score ? Math.min(5, Math.max(1, Math.round(score / 20))) : 0);

  return {
    header: {
      score: Number.isFinite(score) ? score : 0,
      stars: Number.isFinite(derivedStars) ? derivedStars : 0,
      name,
      pinyin,
    },
    meaningZodiac: {
      meaning,
      judge: zodiacAnalysis,
      zodiac: {
        icon: '',
        label: '生肖适配度',
        value: '',
        scoreText: '',
        desc: zodiacAnalysis,
      },
    },
    family: {
      cards: [],
    },
    stroke: {
      wuge: {
        badge: '',
        items: [],
      },
      wuxing: {
        title: '五行能量分布',
        items: [],
      },
    },
    sancai: {
      configText: '',
      configLabel: '(天 - 人 - 地)',
      badge: '',
      items: sancaiAnalysis ? [{ label: '', text: sancaiAnalysis, primary: true }] : [],
    },
    personality: {
      strengths: { title: '', items: [] },
      challenges: { title: '', items: [] },
    },
    gua: {
      bgText: '',
      name: '',
      badge: '',
      desc: '',
      lines: [],
    },
    lucky: {
      cards: [],
      health: { note: '', value: '' },
    },
    sixDimension: {
      labels: sixLabels,
      values: sixValues,
      remark: '',
    },
    fortune: {
      labels: [],
      note: '',
    },
    emotion: {
      title: '',
      desc: '',
      tagsTitle: '',
      tags: [],
    },
    daily: {
      cards: [],
      avatar: { label: '', items: [] },
    },
    poetry: { text: poetrySource },
    detailModules: {
      bazi_name_fit: raw?.bazi_name_fit,
      wuxing_bagua: raw?.wuxing_bagua,
      zodiac_sign: raw?.zodiac_sign,
      char_detail: raw?.char_detail,
    },
    details: {
      score: {
        title: '总分详解',
        lines: [
          name ? `姓名：${name}` : '',
          pinyin ? `拼音：${pinyin}` : '',
          score ? `综合评分：${score}分` : '',
        ].filter(Boolean),
      },
      meaning: {
        title: '字义与生肖详解',
        lines: [
          meaning ? `名字寓意：${meaning}` : '',
          ...(raw?.zodiac_sign?.name_harmony
            ? [`属相与名字：${String(raw.zodiac_sign.name_harmony).trim()}`]
            : []),
          ...toLines(zodiacAnalysis),
        ].filter(Boolean),
      },
      family: {
        title: '家族与起名原理详解',
        lines: [],
      },
      wuge: {
        title: '三才五格配置详解',
        lines: toLines(strokeAnalysis),
      },
      wuxing: {
        title: '五行能量分布详解',
        lines: [
          ...toLines(wuxingAnalysis),
          ...(raw?.wuxing_bagua?.mutual_sketch ? [String(raw.wuxing_bagua.mutual_sketch).trim()] : []),
          ...(raw?.wuxing_bagua?.summary ? [String(raw.wuxing_bagua.summary).trim()] : []),
        ].filter(Boolean),
      },
      sancai: {
        title: '三才配置深度解析',
        lines: toLines(sancaiAnalysis),
      },
      personality_strength: {
        title: '优势性格详解',
        lines: [],
      },
      personality_challenge: {
        title: '潜在盲点详解',
        lines: [],
      },
      gua: {
        title: '周易卦象详解',
        lines: [],
      },
      lucky: {
        color: { title: '幸运色详解', lines: [] },
        number: { title: '幸运数详解', lines: [] },
        industry: { title: '建议行业详解', lines: [] },
        constellation: { title: '星座详解', lines: [] },
      },
      health: {
        title: '健康开运详解',
        lines: [],
      },
      fortune: {
        title: '人生运程模拟详解',
        lines: [],
      },
      emotion: {
        title: '情感与社交运势详解',
        lines: [],
      },
      daily: {
        title: '日常生活开运指南详解',
        lines: [],
      },
    },
  };
};

const rawData = computed(() => props.data);

const report = computed<PersonalNamingReport>(() => normalizePersonalReport(rawData.value));

const arr = (v: any) => (Array.isArray(v) ? v : []);
const toStr = (v: any) => String(v ?? "").trim();

const charDetailItems = computed(() => {
  const x = report.value.detailModules?.char_detail;
  const items = Array.isArray(x?.items) ? x.items : [];
  return items;
});
const hasCharDetail = computed(() => charDetailItems.value.length > 0);
const charDetailPreview = computed(() => charDetailItems.value.slice(0, 2));

function charDetailLine(it: any): string {
  const char = toStr(it?.char);
  const element = toStr(it?.element);
  const yinYang = toStr(it?.yin_yang_element) || toStr(it?.yin_yang);
  const trigram = [toStr(it?.bagua_trigram_symbol), toStr(it?.bagua_trigram)].filter(Boolean).join(' ');
  const parts = [char, element, yinYang, trigram ? `卦：${trigram}` : ''].filter(Boolean);
  return parts.join(' · ');
}

function flattenDetailNodes(nodes: any[]): string[] {
  const out: string[] = [];
  for (const n of nodes) {
    if (!n || typeof n !== "object") continue;
    if (n.type === "text" && toStr(n.text)) out.push(toStr(n.text));
    if (n.type === "list") {
      for (const item of arr(n.items)) {
        const s = toStr(item);
        if (s) out.push(`· ${s}`);
      }
    }
    if (n.type === "kv") {
      for (const item of arr(n.items)) {
        const lab = toStr(item?.label);
        const val = toStr(item?.value);
        if (lab || val) out.push(`${lab}：${val}`);
      }
    }
  }
  return out;
}

function linesFromCharDetail(x: any): string[] {
  if (!x || typeof x !== "object") return [];
  const lines: string[] = [];
  const items = Array.isArray((x as any).items) ? (x as any).items : [];
  for (const it of items) {
    const head = charDetailLine(it);
    if (head) lines.push(`【${head}】`);

    const note = toStr(it?.note);
    if (note) lines.push(note);

    const nodeLines = flattenDetailNodes(arr(it?.details?.nodes));
    nodeLines.forEach((l) => lines.push(l));

    const hexName = toStr(it?.hexagram_name);
    const hexCodeRaw = it?.hexagram_code;
    const hexCode = Number(hexCodeRaw);
    if (hexName || Number.isFinite(hexCode)) {
      lines.push(
        [
          '卦象：',
          hexName || '',
          Number.isFinite(hexCode) ? `（${hexCode}）` : '',
        ].join('')
      );
    }

    lines.push('');
  }
  while (lines.length && !lines[lines.length - 1].trim()) lines.pop();

  const summaryNodes = flattenDetailNodes(arr((x as any)?.details?.nodes));
  if (summaryNodes.length) {
    if (lines.length) lines.push('');
    summaryNodes.forEach((l) => lines.push(l));
  }
  return lines.filter((l) => l !== undefined && l !== null).map((l) => String(l));
}

function linesFromBazi(b: any): string[] {
  if (!b || typeof b !== "object") return [];
  const lines: string[] = [];
  const xy = toStr(b.xiyongshen);
  const profile = toStr(b.name_wuxing_profile);
  const comp = toStr(b.complement_summary);
  if (xy) lines.push(`喜用神：${xy}`);
  if (profile) lines.push(`姓名五行：${profile}`);
  if (comp) lines.push(comp);
  const rawScore = b.fit_score;
  const n = Number(rawScore);
  if (rawScore !== undefined && rawScore !== null && rawScore !== "" && Number.isFinite(n)) {
    lines.push(`与八字契合度：${n}`);
  }
  return lines.filter(Boolean);
}

function linesFromWuxingBagua(x: any): string[] {
  if (!x || typeof x !== "object") return [];
  const lines: string[] = [];
  const w = toStr(x.wuxing_sketch);
  const bg = toStr(x.bagua_profile);
  const mut = toStr(x.mutual_sketch);
  const sum = toStr(x.summary);
  if (w) lines.push(`五行：${w}`);
  if (bg) lines.push(`八卦：${bg}`);
  if (mut) lines.push(`生克互助：${mut}`);
  if (sum) lines.push(sum);
  return lines.filter(Boolean);
}

function linesFromZodiac(z: any): string[] {
  if (!z || typeof z !== "object") return [];
  const lines: string[] = [];
  const animal = toStr(z.animal);
  const br = toStr(z.earthly_branch);
  if (animal || br) lines.push(`属相：${animal}${br ? `（${br}）` : ""}`);
  const trait = toStr(z.trait_summary);
  if (trait) lines.push(`生肖特性：${trait}`);
  const harm = toStr(z.name_harmony);
  if (harm) lines.push(`与名字：${harm}`);
  return lines.filter(Boolean);
}

const hasDetailBazi = computed(() => linesFromBazi(report.value.detailModules?.bazi_name_fit).length > 0);
const hasDetailWuxingBagua = computed(() => linesFromWuxingBagua(report.value.detailModules?.wuxing_bagua).length > 0);
const hasDetailZodiacSign = computed(() => linesFromZodiac(report.value.detailModules?.zodiac_sign).length > 0);

const detailBaziLines = computed(() => {
  const b = report.value.detailModules?.bazi_name_fit;
  const full = linesFromBazi(b);
  return full.slice(0, 3);
});

const detailBaziScoreText = computed(() => {
  const b = report.value.detailModules?.bazi_name_fit;
  if (!b) return "";
  const n = Number(b.fit_score);
  if (!Number.isFinite(n)) return "";
  return `${n}`;
});

const detailWuxingBaguaPreview = computed(() => linesFromWuxingBagua(report.value.detailModules?.wuxing_bagua).slice(0, 3));

const detailZodiacIcon = computed(() => {
  const z = report.value.detailModules?.zodiac_sign;
  const icon = toStr(z?.animal_icon);
  if (icon) return icon;
  const a = toStr(z?.animal);
  return a || "肖";
});

const detailZodiacTitle = computed(() => {
  const z = report.value.detailModules?.zodiac_sign;
  const animal = toStr(z?.animal);
  const br = toStr(z?.earthly_branch);
  if (animal && br) return `${animal} · ${br}`;
  return animal || br || "属相";
});

const detailZodiacHarmony = computed(() => toStr(report.value.detailModules?.zodiac_sign?.name_harmony));

// 星星数据
const stars = ref(
  Array.from({ length: 30 }).map((_, i) => ({
    id: i,
    top: `${Math.random() * 100}%`,
    left: `${Math.random() * 100}%`,
    size: Math.random() * 2 + 1,
    duration: Math.random() * 3 + 2,
    delay: Math.random() * 2,
  }))
);

// 五行数据
const wuxingData = computed(() => report.value.stroke.wuxing.items);

const handleBack = () => {
  emit("back");
};

const handleDownloadPdf = async () => {
  if (typeof window === "undefined" || typeof document === "undefined") return;

  uni.showLoading({ title: "正在生成PDF..." });

  try {
    const raw = rawData.value || {};
    const name = String(report.value.header?.name || raw?.name || "").trim();
    const score = Number(report.value.header?.score ?? raw?.total_score ?? raw?.score ?? 0) || 0;
    const stars = Number(report.value.header?.stars ?? raw?.star_rating ?? 0) || 0;

    const escapeHtml = (s: string) =>
      s
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&#39;");

    const normalizeLines = (lines: any): string[] => {
      if (Array.isArray(lines)) return lines.map((x) => String(x ?? "").trim()).filter(Boolean);
      const single = String(lines ?? "").trim();
      return single ? [single] : [];
    };
    const uniqueLines = (lines: string[]) => {
      const seen = new Set<string>();
      const out: string[] = [];
      lines.forEach((line) => {
        const k = line.trim();
        if (!k || seen.has(k)) return;
        seen.add(k);
        out.push(k);
      });
      return out;
    };
    const noisyKeys = new Set(["details", "nodes", "type", "meta", "status", "code", "raw"]);
    const flattenAnyToLines = (val: any, depth = 0): string[] => {
      if (depth > 4 || val === null || val === undefined) return [];
      if (typeof val === "string" || typeof val === "number" || typeof val === "boolean") {
        const s = String(val).trim();
        return s ? [s] : [];
      }
      if (Array.isArray(val)) {
        return val.flatMap((it) => flattenAnyToLines(it, depth + 1));
      }
      if (typeof val === "object") {
        const out: string[] = [];
        Object.keys(val).forEach((k) => {
          if (noisyKeys.has(k)) return;
          const child = flattenAnyToLines((val as any)[k], depth + 1);
          if (!child.length) return;
          child.forEach((line) => out.push(`${k}：${line}`));
        });
        return out;
      }
      return [];
    };
    const mergeLines = (...groups: any[]) => uniqueLines(groups.flatMap((g) => normalizeLines(g)));
    const charDetailLines = mergeLines(
      linesFromCharDetail((raw as any)?.char_detail),
      linesFromCharDetail(report.value.detailModules?.char_detail),
      // 兼容老结构：没有 items 时仍尽量保留
      charDetailItems.value.map(charDetailLine),
      flattenDetailNodes(arr((raw as any)?.char_detail?.details?.nodes)),
      flattenAnyToLines((raw as any)?.char_detail),
      flattenAnyToLines(report.value.detailModules?.char_detail),
    );
    const rawLineMap: Record<string, string[]> = {
      "分数": mergeLines(flattenAnyToLines((raw as any)?.header)),
      "五行单字详解": charDetailLines,
      "五行生克与八卦": mergeLines(flattenAnyToLines((raw as any)?.wuxing_bagua), flattenAnyToLines(report.value.detailModules?.wuxing_bagua)),
      "八字与姓名五行": mergeLines(flattenAnyToLines((raw as any)?.bazi_name_fit), flattenAnyToLines(report.value.detailModules?.bazi_name_fit)),
      "字义与生肖": mergeLines(flattenAnyToLines((raw as any)?.meaning_zodiac), flattenAnyToLines((raw as any)?.meaning), flattenAnyToLines((raw as any)?.zodiac_sign)),
      "属相与名字": mergeLines(flattenAnyToLines((raw as any)?.zodiac_sign), flattenAnyToLines(report.value.detailModules?.zodiac_sign)),
      "三才五格": mergeLines(flattenAnyToLines((raw as any)?.sancai), flattenAnyToLines((raw as any)?.strokes_wuge_sancai)),
      "笔画数理": mergeLines(flattenAnyToLines((raw as any)?.stroke), flattenAnyToLines((raw as any)?.wuge)),
      "五行能量分布": mergeLines(flattenAnyToLines((raw as any)?.wuxing)),
      "周易卦象": mergeLines(flattenAnyToLines((raw as any)?.gua), flattenAnyToLines((raw as any)?.liuyao)),
      "幸运建议": mergeLines(flattenAnyToLines((raw as any)?.lucky_numbers), flattenAnyToLines((raw as any)?.lucky_colors), flattenAnyToLines((raw as any)?.lucky_tips)),
      "健康开运": mergeLines(flattenAnyToLines((raw as any)?.health)),
      "人生运程": mergeLines(flattenAnyToLines((raw as any)?.fortune), flattenAnyToLines((raw as any)?.lifespan)),
      "情感与社交": mergeLines(flattenAnyToLines((raw as any)?.emotion)),
      "日常开运指南": mergeLines(flattenAnyToLines((raw as any)?.daily)),
      "诗词出处": mergeLines(flattenAnyToLines((raw as any)?.poetry_source), flattenAnyToLines((raw as any)?.poetry)),
    };

    const moduleList: Array<{ title: string; lines: string[] }> = [];
    const push = (title: string, lines: string[]) => {
      const l = normalizeLines(lines);
      if (!l.length) return;
      moduleList.push({ title, lines: l });
    };

    // 主要模块（起名/改名详解）
    push("五行生克与八卦", (() => {
      const x = report.value.detailModules?.wuxing_bagua;
      const nodeLines = flattenDetailNodes(arr(x?.details?.nodes));
      return mergeLines(rawLineMap["五行生克与八卦"], nodeLines, linesFromWuxingBagua(x), flattenAnyToLines(x));
    })());
    push("五行单字详解", mergeLines(rawLineMap["五行单字详解"]));
    push("八字与姓名五行", (() => {
      const b = report.value.detailModules?.bazi_name_fit;
      const nodeLines = flattenDetailNodes(arr(b?.details?.nodes));
      return mergeLines(rawLineMap["八字与姓名五行"], nodeLines, linesFromBazi(b), flattenAnyToLines(b));
    })());
    push("字义与生肖", mergeLines(rawLineMap["字义与生肖"], report.value.details?.meaning?.lines || []));
    push("属相与名字", (() => {
      const z = report.value.detailModules?.zodiac_sign;
      const nodeLines = flattenDetailNodes(arr(z?.details?.nodes));
      return mergeLines(rawLineMap["属相与名字"], nodeLines, linesFromZodiac(z), flattenAnyToLines(z));
    })());
    push("三才五格", mergeLines(rawLineMap["三才五格"], report.value.details?.sancai?.lines || []));
    push("笔画数理", mergeLines(rawLineMap["笔画数理"], report.value.details?.wuge?.lines || []));
    push("五行能量分布", mergeLines(rawLineMap["五行能量分布"], report.value.details?.wuxing?.lines || []));
    push("周易卦象", mergeLines(rawLineMap["周易卦象"], report.value.details?.gua?.lines || []));
    push("幸运建议", mergeLines(rawLineMap["幸运建议"], [
      ...normalizeLines(report.value.details?.lucky?.color?.lines),
      ...normalizeLines(report.value.details?.lucky?.number?.lines),
      ...normalizeLines(report.value.details?.lucky?.industry?.lines),
      ...normalizeLines(report.value.details?.lucky?.constellation?.lines),
    ]));
    push("健康开运", mergeLines(rawLineMap["健康开运"], report.value.details?.health?.lines || []));
    push("人生运程", mergeLines(rawLineMap["人生运程"], report.value.details?.fortune?.lines || []));
    push("情感与社交", mergeLines(rawLineMap["情感与社交"], report.value.details?.emotion?.lines || []));
    push("日常开运指南", mergeLines(rawLineMap["日常开运指南"], report.value.details?.daily?.lines || []));
    push("诗词出处", mergeLines(rawLineMap["诗词出处"], normalizeLines([report.value.poetry?.text])));

    // 通用兜底：把接口新增但未纳入固定章节的字段补进 PDF，避免后端新增字段丢失
    const consumedRawKeys = new Set([
      "header",
      "char_detail",
      "wuxing_bagua",
      "bazi_name_fit",
      "meaning_zodiac",
      "meaning",
      "zodiac_sign",
      "sancai",
      "strokes_wuge_sancai",
      "stroke",
      "wuge",
      "wuxing",
      "gua",
      "liuyao",
      "lucky_numbers",
      "lucky_colors",
      "lucky_tips",
      "health",
      "fortune",
      "lifespan",
      "emotion",
      "daily",
      "poetry_source",
      "poetry",
      "details",
      "detailModules",
      "id",
      "report_id",
      "is_unlocked",
      "unlock_price",
      "locked",
      "lock",
      "price",
    ]);
    const rawKeyTitleMap: Record<string, string> = {
      lucky_numbers: "幸运数字",
      lucky_colors: "幸运颜色",
      career_plan: "事业规划",
      liuyao: "六爻分析",
    };
    Object.keys(raw || {}).forEach((k) => {
      if (consumedRawKeys.has(k)) return;
      const v = (raw as any)[k];
      const lines = mergeLines(
        v && typeof v === "object" ? flattenDetailNodes(arr((v as any)?.details?.nodes)) : [],
        flattenAnyToLines(v),
      );
      if (!lines.length) return;
      const title = rawKeyTitleMap[k] || (/^[a-z0-9_]+$/i.test(k) ? "" : k);
      push(title || "其他信息", lines);
    });

    // 兜底：若后端在根级还带了 detailModules 的 nodes，尽量补齐
    const extraKeys = ["bazi_name_fit", "wuxing_bagua", "zodiac_sign"];
    extraKeys.forEach((k) => {
      const v = (raw as any)?.[k];
      const lines = mergeLines(flattenDetailNodes(arr(v?.details?.nodes)), flattenAnyToLines(v));
      if (!lines.length) return;
      const titleMap: any = {
        bazi_name_fit: "八字与姓名五行（详）",
        wuxing_bagua: "五行生克与八卦（详）",
        zodiac_sign: "属相与名字（详）",
      };
      push(titleMap[k] || "补充", lines);
    });

    if (!moduleList.length) {
      uni.showToast({ title: "暂无可导出的报告内容", icon: "none" });
      return;
    }

    const [{ jsPDF }, html2canvasMod] = await Promise.all([import("jspdf"), import("html2canvas")]);
    const html2canvas = (html2canvasMod as any).default || (html2canvasMod as any);

    const PAGE_W = 794;
    const PAGE_H = 1123;
    const MAX_LINES = 46;
    const wrappedLineCost = (line: string) => {
      const text = String(line || "").trim();
      if (!text) return 1;
      return Math.max(1, Math.ceil(text.length / 30));
    };
    const splitByLines = (lines: string[], max: number) => {
      const res: string[][] = [];
      let bucket: string[] = [];
      let cost = 0;
      lines.forEach((line) => {
        const lc = wrappedLineCost(line);
        if (bucket.length && cost + lc > max) {
          res.push(bucket);
          bucket = [];
          cost = 0;
        }
        bucket.push(line);
        cost += lc;
      });
      if (bucket.length) res.push(bucket);
      return res.length ? res : [[]];
    };

    const styleId = "pdf-gen-mystic-style";
    let style = document.getElementById(styleId) as HTMLStyleElement | null;
    if (!style) {
      style = document.createElement("style");
      style.id = styleId;
      document.head.appendChild(style);
    }
    style.textContent = `
      .pdf-gen-page{position:absolute;width:${PAGE_W}px;height:${PAGE_H}px;background-size:cover;background-position:center;font-family:"Songti SC","SimSun","STSong","Noto Serif SC",serif;color:#f2e6d8;}
      .pdf-gen-panel{position:absolute;left:48px;right:48px;top:116px;bottom:92px;background:rgba(10,10,15,.62);border:1px solid rgba(212,175,55,.38);border-radius:16px;padding:30px 28px;box-sizing:border-box;overflow:hidden;}
      .pdf-cover-kicker{text-align:center;font-size:12px;letter-spacing:.28em;color:rgba(212,175,55,.72);margin-bottom:12px;}
      .pdf-cover-title{text-align:center;font-size:25px;letter-spacing:.16em;font-weight:700;color:rgba(212,175,55,.95);margin-bottom:22px;}
      .pdf-name{text-align:center;font-size:50px;font-weight:800;margin-bottom:14px;color:rgba(242,230,216,.98);text-shadow:0 0 18px rgba(212,175,55,.18);}
      .pdf-score-row{display:flex;align-items:center;justify-content:center;gap:16px;margin-top:8px;}
      .pdf-score{font-size:38px;font-weight:900;color:rgba(212,175,55,.98);}
      .pdf-cover-divider{width:210px;height:1px;margin:22px auto 18px;background:linear-gradient(90deg,rgba(212,175,55,0),rgba(212,175,55,.7),rgba(212,175,55,0));}
      .pdf-cover-seal{width:66px;height:66px;margin:26px auto 0;border-radius:50%;border:1px solid rgba(212,175,55,.34);box-shadow:inset 0 0 0 6px rgba(212,175,55,.05);display:flex;align-items:center;justify-content:center;color:rgba(212,175,55,.92);font-size:20px;}
      .pdf-stars{display:flex;gap:8px;font-size:16px;color:rgba(212,175,55,.95);letter-spacing:.08em;}
      .pdf-dir-title{font-size:20px;font-weight:800;letter-spacing:.14em;color:rgba(212,175,55,.95);margin-bottom:12px;}
      .pdf-dir-kicker{font-size:11px;letter-spacing:.24em;color:rgba(212,175,55,.68);margin-bottom:8px;}
      .pdf-dir-list{margin-top:6px;border-top:1px solid rgba(212,175,55,.14);}
      .pdf-dir-item{display:flex;align-items:center;border-bottom:1px solid rgba(255,255,255,.08);min-height:42px;padding:0 4px;box-sizing:border-box;gap:8px;}
      .pdf-dir-idx{width:68px;flex:0 0 68px;font-size:15px;color:rgba(212,175,55,.96);font-weight:800;}
      .pdf-dir-name{flex:1;font-size:16px;color:rgba(232,232,232,.96);font-weight:700;}
      .pdf-dir-dots{flex:1;border-bottom:1px dashed rgba(212,175,55,.34);height:0;transform:translateY(2px);}
      .pdf-dir-page{width:62px;flex:0 0 62px;text-align:right;font-size:13px;color:rgba(226,214,188,.92);font-weight:700;border:1px solid rgba(212,175,55,.22);border-radius:999px;padding:2px 8px;box-sizing:border-box;background:rgba(212,175,55,.06);}
      .pdf-chapter-bar{position:absolute;left:48px;right:48px;top:78px;height:48px;border-radius:12px;background:rgba(212,175,55,.08);border:1px solid rgba(212,175,55,.24);display:flex;align-items:center;padding:0 22px;box-sizing:border-box;}
      .pdf-chapter-no{font-size:16px;font-weight:900;color:rgba(212,175,55,.98);margin-right:14px;}
      .pdf-chapter-title{font-size:16px;font-weight:800;color:rgba(242,230,216,.98);}
      .pdf-flow-section{margin-bottom:10px;border-radius:10px;border:1px solid rgba(212,175,55,.16);background:rgba(11,16,38,.55);overflow:hidden;}
      .pdf-flow-head{height:38px;display:flex;align-items:center;gap:10px;padding:0 14px;border-bottom:1px solid rgba(212,175,55,.16);background:linear-gradient(90deg,rgba(212,175,55,.12),rgba(212,175,55,.03));}
      .pdf-flow-bullet{color:rgba(212,175,55,.96);font-size:15px;}
      .pdf-flow-title{color:rgba(245,236,218,.98);font-size:16px;font-weight:800;letter-spacing:.05em;}
      .pdf-flow-body{padding:10px 14px 12px;}
      .pdf-flow-line{font-size:15px;line-height:1.72;color:rgba(228,230,238,.95);margin-bottom:2px;white-space:pre-wrap;word-break:break-word;overflow-wrap:anywhere;}
      .pdf-page-footer{position:absolute;left:48px;right:48px;bottom:42px;height:24px;display:flex;align-items:center;justify-content:space-between;font-size:12px;color:rgba(210,210,210,.72);letter-spacing:.04em;}
      .pdf-footer-line{position:absolute;left:48px;right:48px;bottom:70px;height:1px;background:linear-gradient(90deg,rgba(212,175,55,0),rgba(212,175,55,.45),rgba(212,175,55,0));}
    `;

    const wrapper = document.createElement("div");
    wrapper.style.position = "fixed";
    wrapper.style.left = "-100000px";
    wrapper.style.top = "0";
    wrapper.style.zIndex = "-1";
    wrapper.style.width = "0";
    wrapper.style.height = "0";
    document.body.appendChild(wrapper);

    const pages: HTMLElement[] = [];
    const createPageEl = (idx: number) => {
      const el = document.createElement("div");
      el.className = "pdf-gen-page";
      el.style.left = `${idx * 2}px`;
      el.style.top = `${idx * 2}px`;
      (el.style as any).backgroundImage = `url(${pdfBgUrl})`;
      wrapper.appendChild(el);
      pages.push(el);
      return el;
    };

    const appendFooter = (el: HTMLElement, pageNo: number, label = "起名详解报告") => {
      const footer = document.createElement("div");
      footer.className = "pdf-page-footer";
      footer.innerHTML = `<div>${escapeHtml(label)}</div><div>第 ${pageNo} 页</div>`;
      const line = document.createElement("div");
      line.className = "pdf-footer-line";
      el.appendChild(line);
      el.appendChild(footer);
    };

    // 封面
    const coverEl = createPageEl(0);
    coverEl.innerHTML = `
      <div class="pdf-gen-panel">
        <div class="pdf-cover-kicker">玄 · 名 · 天 · 成</div>
        <div class="pdf-cover-title">起名详解报告</div>
        <div class="pdf-name">${escapeHtml(name || "未命名")}</div>
        <div style="text-align:center;color:rgba(226,226,226,0.92);font-size:14px;margin-bottom:18px;">易经数理 · 五行生克 · 三才五格</div>
        <div class="pdf-cover-divider"></div>
        <div class="pdf-score-row">
          <div class="pdf-score">${escapeHtml(String(score || ""))}</div>
          <div class="pdf-stars">${"★".repeat(Math.max(0, Math.min(5, stars)))}${"☆".repeat(Math.max(0, 5 - Math.max(0, Math.min(5, stars))))}</div>
        </div>
        <div class="pdf-cover-seal">名</div>
      </div>
    `;
    appendFooter(coverEl, 1, "起名详解报告 · 封面");

    // 目录
    const dirEl = createPageEl(1);

    // 分章分页：每章至少独占一页；超长章节自动续页
    type ChapterPage = { chapterNo: number; title: string; lines: string[]; continued?: boolean };
    const contentPages: ChapterPage[] = [];
    const dirItems: Array<{ no: number; title: string; start: number; end: number }> = [];
    let currentPageNo = 3;

    moduleList.forEach((m, idx) => {
      const chapterNo = idx + 1;
      const chunks = splitByLines(m.lines, MAX_LINES);
      const start = currentPageNo;
      chunks.forEach((chunk, cIdx) => {
        contentPages.push({
          chapterNo,
          title: m.title,
          lines: chunk,
          continued: cIdx > 0,
        });
        currentPageNo += 1;
      });
      const end = Math.max(start, currentPageNo - 1);
      dirItems.push({ no: chapterNo, title: m.title, start, end });
    });

    dirEl.innerHTML = `
      <div class="pdf-gen-panel">
        <div class="pdf-dir-kicker">卷 一 · 纲 目</div>
        <div class="pdf-dir-title">目录</div>
        <div class="pdf-dir-list">
          ${dirItems
            .map((it) => {
              const pageText = it.start === it.end ? `${it.start}` : `${it.start}-${it.end}`;
              return `<div class="pdf-dir-item">
                <div class="pdf-dir-idx">第${it.no}章</div>
                <div class="pdf-dir-name">${escapeHtml(it.title)}</div>
                <div class="pdf-dir-dots"></div>
                <div class="pdf-dir-page">${escapeHtml(pageText)}</div>
              </div>`;
            })
            .join("")}
        </div>
      </div>
    `;
    appendFooter(dirEl, 2, "起名详解报告 · 目录");

    // 正文页
    contentPages.forEach((section, i) => {
      const el = createPageEl(2 + i);
      const titleText = `第${section.chapterNo}章 ${section.title}${section.continued ? "（续）" : ""}`;
      const linesHtml = section.lines.map((ln) => `<div class="pdf-flow-line">${escapeHtml(ln || " ")}</div>`).join("");
      const sectionsHtml = `<div class="pdf-flow-section">
        <div class="pdf-flow-head">
          <div class="pdf-flow-bullet">✧</div>
          <div class="pdf-flow-title">${escapeHtml(titleText)}</div>
        </div>
        <div class="pdf-flow-body">${linesHtml}</div>
      </div>`;
      el.innerHTML = `
        <div class="pdf-chapter-bar">
          <div class="pdf-chapter-no">正文</div>
          <div class="pdf-chapter-title">${escapeHtml(titleText)}</div>
        </div>
        <div class="pdf-gen-panel" style="top:138px;">${sectionsHtml}</div>
      `;
      appendFooter(el, 3 + i);
    });

    const doc = new jsPDF({ unit: "pt", format: "a4" });
    const pageW = doc.internal.pageSize.getWidth();
    const pageH = doc.internal.pageSize.getHeight();
    // 提速关键：降低渲染倍率并使用 JPEG，通常可显著减少导出耗时
    const renderScale = Math.min(1.45, Math.max(1.15, Number((window as any)?.devicePixelRatio || 1)));
    const jpegQuality = 0.86;

    for (let i = 0; i < pages.length; i++) {
      const canvas = await html2canvas(pages[i], {
        scale: renderScale,
        useCORS: true,
        allowTaint: true,
        backgroundColor: "#0a0a0f",
        logging: false,
      });
      const img = canvas.toDataURL("image/jpeg", jpegQuality);
      if (i > 0) doc.addPage();
      doc.addImage(img, "JPEG", 0, 0, pageW, pageH, undefined, "FAST");
    }

    wrapper.remove();
    const safeName = name ? name.replace(/[\\/:*?\"<>|]/g, "_") : "起名详解";
    doc.save(`${safeName}-起名详解.pdf`);
    uni.showToast({ title: "PDF下载成功", icon: "success" });
  } catch (e) {
    console.error("生成PDF失败:", e);
    uni.showToast({ title: "PDF下载失败", icon: "none" });
  } finally {
    uni.hideLoading();
  }
};

const handleWealthAnalysis = async () => {
  
  const solutionId = Number(props.data?.id || 0);
  console.log('props.data===>>>', props.data);
  
  if (!solutionId) {
    uni.showToast({ title: '方案ID不存在', icon: 'none' });
    return;
  }

  try {
    uni.showLoading({ title: '加载中...' });
    

    
    const reportId = props.data?.report_id;
    
    if (!reportId) {
      uni.hideLoading();
      uni.showToast({ title: '报告ID不存在', icon: 'none' });
      return;
    }

    // 使用report_id获取财运解析数据
    const wealthData = await getWealthAnalysisByReportId(reportId);
    uni.hideLoading();
    
    uni.setStorageSync('wealth_analysis_report_id', reportId);
    emit('wealthAnalysis', { id: reportId, wealthData });
  } catch (error: any) {
    uni.hideLoading();
    uni.showToast({ title: error?.msg || error?.message || '加载失败，请重试', icon: 'none' });
  }
};

// 详情弹窗
const showDetailModal = ref(false);
const detailModalTitle = ref('');
const detailModalLines = ref<string[]>([]);

const openDetailModal = (title: string, lines: string[]) => {
  detailModalTitle.value = title;
  detailModalLines.value = lines;
  showDetailModal.value = true;
};

const closeDetailModal = () => {
  showDetailModal.value = false;
  detailModalTitle.value = '';
  detailModalLines.value = [];
};

// 各模块点击事件
const openScoreDetail = () => {
  const d = report.value.details.score;
  openDetailModal(d.title, d.lines);
};

const openMeaningDetail = () => {
  const d = report.value.details.meaning;
  openDetailModal(d.title, d.lines);
};

const openBaziNameFitDetail = () => {
  const b = report.value.detailModules?.bazi_name_fit;
  const nodes = flattenDetailNodes(arr(b?.details?.nodes));
  const lines = nodes.length ? nodes : linesFromBazi(b);
  openDetailModal("八字与姓名五行详解", lines);
};

const openWuxingBaguaDetail = () => {
  const x = report.value.detailModules?.wuxing_bagua;
  const nodes = flattenDetailNodes(arr(x?.details?.nodes));
  const charLines = charDetailItems.value.map(charDetailLine).filter(Boolean);
  const baguaLines = nodes.length ? nodes : linesFromWuxingBagua(x);
  const lines = [
    ...(charLines.length ? ['【五行单字详解 · 阴阳 · 卦象】', ...charLines, ''] : []),
    ...baguaLines,
  ];
  openDetailModal("五行生克与八卦详解", lines);
};

const openCharDetail = () => {
  const x = report.value.detailModules?.char_detail;
  const lines = linesFromCharDetail(x);
  openDetailModal("五行单字详解", lines.length ? lines : ['暂无数据']);
};

const openZodiacSignDetail = () => {
  const z = report.value.detailModules?.zodiac_sign;
  const nodes = flattenDetailNodes(arr(z?.details?.nodes));
  const lines = nodes.length ? nodes : linesFromZodiac(z);
  openDetailModal("属相与名字详解", lines);
};

const openFamilyDetail = () => {
  const d = report.value.details.family;
  openDetailModal(d.title, d.lines);
};

const openWugeDetail = () => {
  const d = report.value.details.wuge;
  openDetailModal(d.title, d.lines);
};

const openWuxingDetail = () => {
  const d = report.value.details.wuxing;
  openDetailModal(d.title, d.lines);
};

const openSancaiDetail = () => {
  const d = report.value.details.sancai;
  openDetailModal(d.title, d.lines);
};

const openPersonalityDetail = (type: 'strength' | 'challenge') => {
  const d = type === 'strength'
    ? report.value.details.personality_strength
    : report.value.details.personality_challenge;
  openDetailModal(d.title, d.lines);
};

const openGuaDetail = () => {
  const d = report.value.details.gua;
  openDetailModal(d.title, d.lines);
};

const openLuckyDetail = (type: string) => {
  const key = type as 'color' | 'number' | 'industry' | 'constellation';
  const d = report.value.details.lucky[key];
  if (d) openDetailModal(d.title, d.lines);
};

const openHealthDetail = () => {
  const d = report.value.details.health;
  openDetailModal(d.title, d.lines);
};

const openFortuneDetail = () => {
  const d = report.value.details.fortune;
  openDetailModal(d.title, d.lines);
};

const openEmotionDetail = () => {
  const d = report.value.details.emotion;
  openDetailModal(d.title, d.lines);
};

const openDailyDetail = () => {
  const d = report.value.details.daily;
  openDetailModal(d.title, d.lines);
};
</script>

<style scoped>
.naming-detail {
  min-height: 100vh;
  background: #0a0a0f;
  position: relative;
  color: #e2e2e2;
}

/* Starry Background */
.starry-bg {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
  background: linear-gradient(to bottom, #050508, #10101a, #1a1a2e);
}

.star {
  position: absolute;
  border-radius: 50%;
  background: #fff;
  opacity: 0.2;
  animation: twinkle ease-in-out infinite;
}

@keyframes twinkle {

  0%,
  100% {
    opacity: 0.1;
    transform: scale(1);
  }

  50% {
    opacity: 0.5;
    transform: scale(1.2);
  }
}

.glow-top {
  position: absolute;
  top: -10%;
  left: -10%;
  width: 50%;
  height: 50%;
  background: #2a3d5d;
  opacity: 0.2;
  filter: blur(100px);
  border-radius: 50%;
}

.glow-bottom {
  position: absolute;
  bottom: -10%;
  right: -10%;
  width: 50%;
  height: 50%;
  background: #9c2a2a;
  opacity: 0.1;
  filter: blur(100px);
  border-radius: 50%;
}

/* Header */
.detail-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 60rpx 32rpx 24rpx;
  background: rgba(10, 10, 15, 0.8);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

.detail-header-back {
  display: flex;
  align-items: center;
  color: #a0a0a0;
}

.back-icon {
  font-size: 24px;
  margin-right: 8rpx;
}

.back-text {
  font-size: 14px;
  letter-spacing: 0.1em;
}

.detail-header-title {
  font-size: 18px;
  font-weight: 700;
  color: #d4af37;
  letter-spacing: 0.3em;
}

.detail-header-download {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8rpx;
  padding: 10rpx 16rpx;
  border-radius: 999rpx;
  border: 1px solid rgba(212, 175, 55, 0.35);
  background: rgba(212, 175, 55, 0.10);
  color: rgba(255, 242, 210, 0.92);
  backdrop-filter: blur(8px);
}

.detail-header-download-icon {
  font-size: 18px;
  line-height: 1;
}

.detail-header-download-text {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
}

/* Content */
.detail-content {
  position: relative;
  z-index: 10;
  padding: 180rpx 32rpx 60rpx;
  height: 100vh;
  box-sizing: border-box;
}

/* Score Card */
.score-card {
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05));
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 8rpx;
  padding: 48rpx;
  text-align: center;
  position: relative;
  overflow: hidden;
  margin-bottom: 48rpx;
}

.score-corner {
  position: absolute;
  width: 12rpx;
  height: 12rpx;
  border-color: #d4af37;
  border-style: solid;
}

.score-corner-tl {
  top: 0;
  left: 0;
  border-width: 4rpx 0 0 4rpx;
}

.score-corner-tr {
  top: 0;
  right: 0;
  border-width: 4rpx 4rpx 0 0;
}

.score-corner-bl {
  bottom: 0;
  left: 0;
  border-width: 0 0 4rpx 4rpx;
}

.score-corner-br {
  bottom: 0;
  right: 0;
  border-width: 0 4rpx 4rpx 0;
}

.score-label {
  font-size: 10px;
  color: #d4af37;
  letter-spacing: 0.5em;
  text-transform: uppercase;
  opacity: 0.8;
  margin-bottom: 16rpx;
}

.score-value-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 280rpx;
  height: 280rpx;
  margin-bottom: 16rpx;
}

.score-value {
  font-size: 72px;
  font-weight: 700;
  background: linear-gradient(to bottom, #d4af37, #8a6e1e);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.score-ring {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: 1px dashed rgba(212, 175, 55, 0.2);
  border-radius: 50%;
  animation: rotate 10s linear infinite;
}

@keyframes rotate {
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
}

.score-stars {
  display: flex;
  justify-content: center;
  gap: 8rpx;
  margin-bottom: 24rpx;
}

.score-star {
  font-size: 14px;
  color: #5a5a5a;
}

.score-star.active {
  color: #d4af37;
}

.score-divider {
  height: 1px;
  background: linear-gradient(to right, transparent, rgba(212, 175, 55, 0.3), transparent);
  margin: 16rpx 0;
}

.score-name {
  display: block;
  font-size: 28px;
  font-weight: 700;
  color: #e2e2e2;
  letter-spacing: 0.2em;
  margin-top: 16rpx;
  margin-bottom: 8rpx;
}

.score-pinyin {
  display: block;
  font-size: 14px;
  color: #a0a0a0;
  font-style: italic;
}

/* Section */
.section {
  margin-bottom: 48rpx;
}

.section-title {
  display: flex;
  align-items: center;
  margin-bottom: 24rpx;
  padding-left: 8rpx;
}

.section-icon {
  font-size: 16px;
  color: #d4af37;
  margin-right: 12rpx;
}

.section-text {
  font-size: 16px;
  font-weight: 700;
  color: #e2e2e2;
  letter-spacing: 0.1em;
}

/* Meaning Card */
.meaning-card {
  background: #1a1a2e;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12rpx;
  padding: 32rpx;
  position: relative;
  overflow: hidden;
  margin-bottom: 20rpx;
}

.meaning-quote {
  position: absolute;
  top: 0;
  right: 16rpx;
  font-size: 48px;
  color: #d4af37;
  opacity: 0.1;
}

.meaning-label {
  display: block;
  font-size: 14px;
  font-weight: 700;
  color: #d4af37;
  margin-bottom: 16rpx;
}

.meaning-text {
  display: block;
  font-size: 14px;
  color: #a0a0a0;
  line-height: 1.8;
  margin-bottom: 16rpx;
}

.meaning-judge {
  display: flex;
  flex-wrap: wrap;
}

.meaning-judge-label {
  font-size: 14px;
  color: #d4af37;
}

.meaning-judge-text {
  font-size: 14px;
  color: #a0a0a0;
}

/* Zodiac Card */
.zodiac-card {
  background: linear-gradient(to right, #16213e, #1a1a2e);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12rpx;
  padding: 32rpx;
}

.zodiac-header {
  display: flex;
  align-items: center;
  margin-bottom: 20rpx;
}

.zodiac-icon-wrap {
  width: 80rpx;
  height: 80rpx;
  border-radius: 50%;
  background: rgba(212, 175, 55, 0.2);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-right: 20rpx;
}

.zodiac-icon {
  font-size: 24px;
}

.zodiac-info {
  flex: 1;
}

.zodiac-label {
  display: block;
  font-size: 12px;
  color: #a0a0a0;
  margin-bottom: 4rpx;
}

.zodiac-value {
  display: block;
  font-size: 16px;
  font-weight: 700;
  color: #e2e2e2;
}

.zodiac-score {
  font-size: 24px;
  font-weight: 700;
  color: #d4af37;
}

.zodiac-desc {
  font-size: 14px;
  color: #a0a0a0;
  line-height: 1.6;
}

/* Info Card */
.info-card {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12rpx;
  padding: 32rpx;
  margin-bottom: 16rpx;
}

.info-card-title {
  display: block;
  font-size: 14px;
  font-weight: 700;
  color: #d4af37;
  margin-bottom: 16rpx;
}

.info-card-text {
  display: block;
  font-size: 14px;
  color: #a0a0a0;
  line-height: 1.8;
}

/* Wuge Card */
.wuge-card {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 12rpx;
  padding: 32rpx;
  margin-bottom: 20rpx;
}

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

.wuge-label {
  font-size: 14px;
  color: #e2e2e2;
}

.wuge-badge {
  font-size: 12px;
  color: #d4af37;
  border: 1px solid #d4af37;
  padding: 4rpx 16rpx;
  border-radius: 4rpx;
}

.wuge-item {
  margin-bottom: 20rpx;
}

.wuge-item-header {
  display: flex;
  justify-content: space-between;
  margin-bottom: 8rpx;
}

.wuge-item-name {
  font-size: 12px;
  color: #a0a0a0;
}

.wuge-item-name-primary {
  color: #e2e2e2;
  font-weight: 700;
}

.wuge-item-result {
  font-size: 12px;
  color: #a0a0a0;
}

.wuge-item-result-primary {
  color: #d4af37;
}

.wuge-bar {
  height: 8rpx;
  background: rgba(255, 255, 255, 0.1);
  border-radius: 4rpx;
  overflow: hidden;
}

.wuge-bar-fill {
  height: 100%;
  border-radius: 4rpx;
  transition: width 1s ease-out;
}

/* Wuxing Card */
.wuxing-card {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 12rpx;
  padding: 32rpx;
}

.wuxing-title {
  display: block;
  font-size: 14px;
  font-weight: 700;
  color: #d4af37;
  margin-bottom: 20rpx;
  padding-left: 16rpx;
  border-left: 4rpx solid #d4af37;
}

.wuxing-list {
  display: flex;
  flex-direction: column;
  gap: 12rpx;
}

.wuxing-item {
  display: flex;
  align-items: center;
  gap: 16rpx;
}

.wuxing-label {
  width: 48rpx;
  font-size: 14px;
  color: #a0a0a0;
}

.wuxing-bar {
  flex: 1;
  height: 8rpx;
  background: rgba(255, 255, 255, 0.1);
  border-radius: 4rpx;
  overflow: hidden;
}

.wuxing-bar-fill {
  height: 100%;
  border-radius: 4rpx;
  transition: width 1.2s ease-out;
}

.wuxing-value {
  width: 60rpx;
  text-align: right;
  font-size: 14px;
  color: #e2e2e2;
  font-family: monospace;
}

/* Sancai Card */
.sancai-card {
  background: #1a1a2e;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12rpx;
  padding: 32rpx;
}

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

.sancai-config {
  display: flex;
  align-items: baseline;
  gap: 12rpx;
}

.sancai-config-text {
  font-size: 14px;
  font-weight: 700;
  color: #d4af37;
}

.sancai-config-label {
  font-size: 12px;
  color: #a0a0a0;
}

.sancai-badge {
  font-size: 12px;
  color: #e2e2e2;
  background: rgba(212, 175, 55, 0.2);
  border: 1px solid #d4af37;
  padding: 4rpx 16rpx;
  border-radius: 999rpx;
}

.sancai-item {
  margin-bottom: 16rpx;
}

.sancai-item-label {
  font-size: 14px;
  font-weight: 700;
  color: #d4af37;
}

.sancai-item-label-normal {
  font-size: 14px;
  font-weight: 700;
  color: #e2e2e2;
}

.sancai-item-text {
  font-size: 14px;
  color: #a0a0a0;
  line-height: 1.6;
}

/* Personality Grid */
.personality-grid {
  display: flex;
  gap: 16rpx;
}

.personality-card {
  flex: 1;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 12rpx;
  padding: 24rpx;
}

.personality-title {
  display: block;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin-bottom: 16rpx;
}

.personality-title-gold {
  color: #d4af37;
}

.personality-title-red {
  color: #9c2a2a;
}

.personality-list {
  display: flex;
  flex-direction: column;
  gap: 12rpx;
}

.personality-item {
  display: flex;
  align-items: center;
}

.personality-dot {
  width: 12rpx;
  height: 12rpx;
  border-radius: 50%;
  margin-right: 12rpx;
}

.personality-dot-gold {
  background: #d4af37;
}

.personality-dot-red {
  background: #9c2a2a;
}

.personality-text {
  font-size: 12px;
  color: #a0a0a0;
}

/* Gua Card */
.gua-card {
  background: linear-gradient(to right, #1a1a2e, #16213e);
  border: 1px solid rgba(212, 175, 55, 0.3);
  border-radius: 12rpx;
  padding: 32rpx;
  position: relative;
  overflow: hidden;
}

.gua-bg-text {
  position: absolute;
  right: -20rpx;
  top: -20rpx;
  font-size: 120px;
  color: rgba(255, 255, 255, 0.05);
  pointer-events: none;
}

.gua-content {
  display: flex;
  align-items: center;
  gap: 40rpx;
  position: relative;
  z-index: 1;
}

.gua-symbol {
  display: flex;
  flex-direction: column;
  gap: 8rpx;
  width: 120rpx;
}

.gua-line {
  height: 8rpx;
}

.gua-line-solid {
  background: #d4af37;
  box-shadow: 0 0 8px #d4af37;
}

.gua-line-broken {
  display: flex;
  justify-content: space-between;
}

.gua-line-part {
  width: 45%;
  height: 8rpx;
  background: rgba(212, 175, 55, 0.5);
}

.gua-spacer {
  height: 8rpx;
}

.gua-info {
  flex: 1;
}

.gua-header {
  display: flex;
  align-items: baseline;
  gap: 16rpx;
  margin-bottom: 16rpx;
}

.gua-name {
  font-size: 24px;
  font-weight: 700;
  color: #e2e2e2;
  letter-spacing: 0.1em;
}

.gua-badge {
  font-size: 12px;
  color: #9c2a2a;
  border: 1px solid #9c2a2a;
  padding: 4rpx 12rpx;
  border-radius: 4rpx;
}

.gua-desc {
  font-size: 14px;
  color: #a0a0a0;
  line-height: 1.6;
}

/* Lucky Grid */
.lucky-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 16rpx;
  margin-bottom: 16rpx;
}

.lucky-card {
  width: calc(50% - 8rpx);
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 12rpx;
  padding: 24rpx;
  display: flex;
  align-items: center;
  gap: 20rpx;
  box-sizing: border-box;
}

.lucky-icon {
  width: 80rpx;
  height: 80rpx;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.1);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
}

.lucky-icon-blue {
  color: #60a5fa;
}

.lucky-icon-pink {
  color: #f472b6;
}

.lucky-icon-green {
  color: #4ade80;
}

.lucky-icon-yellow {
  color: #facc15;
}

.lucky-info {
  flex: 1;
}

.lucky-label {
  display: block;
  font-size: 12px;
  color: #a0a0a0;
  margin-bottom: 4rpx;
}

.lucky-value {
  display: block;
  font-size: 14px;
  font-weight: 700;
  color: #e2e2e2;
}

/* Health Card */
.health-card {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 12rpx;
  padding: 24rpx;
  display: flex;
  align-items: center;
  gap: 20rpx;
}

.health-icon {
  width: 80rpx;
  height: 80rpx;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.1);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  color: #f87171;
}

.health-info {
  flex: 1;
}

.health-header {
  display: flex;
  justify-content: space-between;
  margin-bottom: 4rpx;
}

.health-label {
  font-size: 12px;
  color: #a0a0a0;
}

.health-note {
  font-size: 12px;
  color: #5a5a5a;
}

.health-value {
  font-size: 14px;
  font-weight: 700;
  color: #e2e2e2;
}

/* Poetry Card */
.poetry-card {
  background: rgba(226, 226, 226, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 12rpx;
  padding: 40rpx;
  position: relative;
  overflow: hidden;
}

.poetry-quote {
  position: absolute;
  top: -16rpx;
  left: -16rpx;
  font-size: 80px;
  color: rgba(255, 255, 255, 0.05);
  transform: rotate(180deg);
}

.poetry-text {
  display: block;
  font-size: 16px;
  color: #e2e2e2;
  line-height: 2;
  font-style: italic;
  text-align: center;
  position: relative;
  z-index: 1;
}

/* Action Buttons */
.action-buttons {
  display: flex;
  gap: 16rpx;
  margin: 48rpx 0;
}

.action-btn {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12rpx;
  padding: 24rpx;
  border-radius: 12rpx;
}

.action-btn-share,
.action-btn-download {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.1);
  color: #a0a0a0;
}

.action-btn-primary {
  background: rgba(212, 175, 55, 0.1);
  border: 1px solid rgba(212, 175, 55, 0.5);
  color: #d4af37;
  box-shadow: 0 0 15px rgba(212, 175, 55, 0.15);
}

.action-btn-icon {
  font-size: 20px;
}

.action-btn-text {
  font-size: 12px;
  letter-spacing: 0.1em;
}

/* Fortune Card - 人生运程模拟 */
.fortune-card {
  background: #1a1a2e;
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 12rpx;
  padding: 32rpx;
  position: relative;
  overflow: hidden;
}

.fortune-chart {
  height: 200rpx;
  position: relative;
  margin-bottom: 24rpx;
}

.fortune-line {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 40rpx;
  background: linear-gradient(90deg,
      transparent 5%,
      rgba(212, 175, 55, 0.1) 15%,
      rgba(212, 175, 55, 0.3) 30%,
      rgba(212, 175, 55, 0.5) 35%,
      rgba(212, 175, 55, 0.3) 50%,
      rgba(212, 175, 55, 0.2) 70%,
      transparent 95%);
  clip-path: polygon(0% 80%, 25% 50%, 35% 15%, 50% 25%, 70% 35%, 100% 55%, 100% 100%, 0% 100%);
}

.fortune-point {
  position: absolute;
  width: 16rpx;
  height: 16rpx;
  background: #d4af37;
  border-radius: 50%;
}

.fortune-point-1 {
  left: 10%;
  top: 70%;
}

.fortune-point-2 {
  left: 35%;
  top: 15%;
}

.fortune-point-3 {
  left: 60%;
  top: 30%;
}

.fortune-point-4 {
  left: 90%;
  top: 50%;
}

.fortune-labels {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  justify-content: space-between;
}

.fortune-label-item {
  text-align: center;
}

.fortune-label-text {
  font-size: 12px;
  color: #a0a0a0;
}

.fortune-label-peak .fortune-label-text {
  color: #d4af37;
  font-weight: 700;
}

.fortune-note {
  display: block;
  font-size: 12px;
  color: #5a5a5a;
  text-align: center;
  padding-top: 16rpx;
  border-top: 1px solid rgba(255, 255, 255, 0.05);
}

/* Emotion Card - 情感与社交运势 */
.emotion-card {
  background: #1a1a2e;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12rpx;
  padding: 32rpx;
}

.emotion-header {
  display: flex;
  gap: 24rpx;
  margin-bottom: 24rpx;
}

.emotion-icon-wrap {
  width: 100rpx;
  height: 100rpx;
  border-radius: 50%;
  background: rgba(236, 72, 153, 0.1);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.emotion-icon {
  font-size: 32px;
}

.emotion-info {
  flex: 1;
}

.emotion-title {
  display: block;
  font-size: 14px;
  font-weight: 700;
  color: #e2e2e2;
  margin-bottom: 12rpx;
}

.emotion-desc {
  display: block;
  font-size: 12px;
  color: #a0a0a0;
  line-height: 1.6;
}

.emotion-divider {
  height: 1px;
  background: rgba(255, 255, 255, 0.05);
  margin: 24rpx 0;
}

.emotion-tags-title {
  display: block;
  font-size: 14px;
  font-weight: 700;
  color: #e2e2e2;
  margin-bottom: 16rpx;
}

.emotion-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 16rpx;
}

.emotion-tag {
  padding: 12rpx 20rpx;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 8rpx;
  font-size: 12px;
  color: #a0a0a0;
}

.emotion-tag-primary {
  color: #d4af37;
  border-color: rgba(212, 175, 55, 0.3);
}

/* Daily Grid - 日常生活开运指南 */
.daily-grid {
  display: flex;
  gap: 16rpx;
  margin-bottom: 16rpx;
}

.daily-card {
  flex: 1;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 12rpx;
  padding: 24rpx;
}

.daily-label {
  display: block;
  font-size: 12px;
  color: #a0a0a0;
  margin-bottom: 16rpx;
}

.daily-time-item {
  display: flex;
  align-items: center;
  gap: 12rpx;
  margin-bottom: 8rpx;
}

.daily-time-icon {
  font-size: 14px;
}

.daily-time-text {
  font-size: 14px;
  font-weight: 700;
  color: #e2e2e2;
}

.daily-items {
  display: flex;
  gap: 16rpx;
  margin-bottom: 12rpx;
}

.daily-item {
  width: 64rpx;
  height: 64rpx;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
}

.daily-item-red {
  background: rgba(127, 29, 29, 0.5);
  border: 1px solid rgba(239, 68, 68, 0.3);
  color: #fecaca;
}

.daily-item-yellow {
  background: rgba(113, 63, 18, 0.5);
  border: 1px solid rgba(234, 179, 8, 0.3);
  color: #fef08a;
}

.daily-tip {
  display: block;
  font-size: 10px;
  color: #5a5a5a;
}

/* Avatar Card - 开运头像风格推荐 */
.avatar-card {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 12rpx;
  padding: 24rpx;
}

.avatar-label {
  display: block;
  font-size: 12px;
  color: #a0a0a0;
  margin-bottom: 20rpx;
}

.avatar-list {
  display: flex;
  gap: 20rpx;
  overflow-x: auto;
}

.avatar-item {
  width: 120rpx;
  height: 120rpx;
  border-radius: 12rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.avatar-item-sunrise {
  background: linear-gradient(135deg, #fb923c, #ef4444);
}

.avatar-item-calligraphy {
  background: #2c2c2c;
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.avatar-item-festive {
  background: #fecaca;
}

.avatar-text {
  font-size: 10px;
  color: #fff;
}

.avatar-item-calligraphy .avatar-text {
  color: #a0a0a0;
}

.avatar-item-festive .avatar-text {
  color: #991b1b;
}

/* Footer */
.detail-footer {
  text-align: center;
  padding: 40rpx 0 80rpx;
}

.footer-text {
  font-size: 10px;
  color: #5a5a5a;
}

.clickable {
  transition: opacity 0.15s ease;
}

.clickable:active {
  opacity: 0.82;
}

.detail-modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 120;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 28rpx;
}

.detail-modal {
  width: 100%;
  max-width: 680rpx;
  background: rgba(10, 10, 15, 0.98);
  border: 1px solid rgba(212, 175, 55, 0.25);
  border-radius: 18rpx;
  overflow: hidden;
}

.detail-modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18rpx 18rpx;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.detail-modal-title {
  flex: 1;
  color: #d4af37;
  font-weight: 900;
  font-size: 28rpx;
  padding-right: 16rpx;
}

.detail-modal-close {
  width: 56rpx;
  height: 56rpx;
  border-radius: 999rpx;
  background: rgba(255, 255, 255, 0.06);
  display: flex;
  align-items: center;
  justify-content: center;
}

.detail-modal-close-text {
  color: #a0a0a0;
  font-size: 34rpx;
  line-height: 1;
}

.detail-modal-body {
  max-height: 70vh;
}

.detail-modal-content {
  padding: 18rpx;
}

.detail-modal-text {
  display: block;
  color: #a0a0a0;
  font-size: 24rpx;
  line-height: 1.8;
  margin-bottom: 12rpx;
}
</style>
