// ============================================
// 养生调理知识库 — Main App
// ============================================
const { useState, useEffect, useMemo, useRef } = React;
const API = "/api";

// ---- Icons (inline SVG, ink-line style) ----
const Icon = {
  body: () => (
    <svg viewBox="0 0 32 32">
      <circle cx="16" cy="7" r="3.2" />
      <path d="M11 17 Q16 12 21 17 L21 26 Q16 28 11 26 Z" />
      <path d="M8 19 L11 18 M24 19 L21 18" />
    </svg>
  ),
  bowl: () => (
    <svg viewBox="0 0 32 32">
      <path d="M5 16 Q5 24 16 26 Q27 24 27 16 Z" />
      <path d="M5 16 H27" />
      <path d="M11 12 Q13 8 16 10 Q19 12 21 9" />
      <circle cx="22" cy="7" r="1.6" />
    </svg>
  ),
  symptom: () => (
    <svg viewBox="0 0 32 32">
      <rect x="6" y="6" width="16" height="16" rx="1" />
      <path d="M10 11 H18 M10 15 H16 M10 19 H14" />
      <circle cx="23" cy="22" r="4" />
      <path d="M21.5 22 L22.5 23 L24.5 21" />
    </svg>
  ),
  people: () => (
    <svg viewBox="0 0 32 32">
      <rect x="5" y="8" width="22" height="16" rx="1.5" />
      <circle cx="10" cy="13" r="1.4" />
      <circle cx="10" cy="19" r="1.4" />
      <path d="M14 12 H23 M14 14 H21 M14 18 H23 M14 20 H21" />
    </svg>
  ),
  herb: () => (
    <svg viewBox="0 0 32 32">
      <path d="M9 6 H21 L23 9 V25 Q23 27 21 27 H11 Q9 27 9 25 Z" />
      <path d="M12 12 H20 M12 16 H18 M12 20 H17" />
      <circle cx="23" cy="9" r="2.4" />
      <path d="M22 11 L20 14" />
    </svg>
  ),
  search: () => (
    <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.6">
      <circle cx="7" cy="7" r="4.5" />
      <path d="M10.5 10.5 L14 14" />
    </svg>
  ),
  arrow: () => <span style={{display:"inline-block", transform:"translateY(-1px)"}}>→</span>,
  home: () => (
    <svg viewBox="0 0 32 32">
      <path d="M5 15 L16 5 L27 15 V27 H20 V21 H12 V27 H5 Z" strokeLinejoin="round"/>
    </svg>
  ),
  close: () => (
    <svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.8">
      <path d="M2 2 L14 14 M14 2 L2 14"/>
    </svg>
  ),
};

// ============= Search Overlay =============
function SearchOverlay({ open, onClose }) {
  const [q, setQ] = useState("");
  const [results, setResults] = useState([]);
  const [loading, setLoading] = useState(false);
  const timerRef = useRef(null);

  useEffect(() => {
    if (!open) { setQ(""); setResults([]); return; }
    document.getElementById("search-input-main")?.focus();
  }, [open]);

  const typeMap = { constitution:"体质", solar_term:"节气", recipe:"食疗", symptom:"症状" };

  const search = (val) => {
    setQ(val);
    clearTimeout(timerRef.current);
    if (!val.trim()) { setResults([]); return; }
    timerRef.current = setTimeout(async () => {
      setLoading(true);
      try {
        const data = await fetch(`${API}/search?q=${encodeURIComponent(val)}`).then(r => r.json());
        setResults(data.results || []);
      } finally { setLoading(false); }
    }, 280);
  };

  if (!open) return null;
  return (
    <div style={{position:"fixed",inset:0,zIndex:1000,display:"flex",flexDirection:"column",alignItems:"center",background:"rgba(31,26,18,.6)",backdropFilter:"blur(4px)"}}
      onClick={onClose}>
      <div style={{marginTop:80,width:"min(640px,90vw)",background:"var(--bg-card)",border:"1px solid var(--line)",boxShadow:"0 24px 60px rgba(0,0,0,.3)"}}
        onClick={e => e.stopPropagation()}>
        <div style={{display:"flex",alignItems:"center",gap:12,padding:"14px 20px",borderBottom:"1px solid var(--line-soft)"}}>
          <Icon.search />
          <input id="search-input-main" value={q} onChange={e => search(e.target.value)}
            placeholder="搜索体质、节气、症状、食疗…"
            style={{flex:1,border:"none",outline:"none",background:"none",fontFamily:"var(--sans)",fontSize:16,color:"var(--ink)"}}/>
          {loading && <span style={{fontSize:12,color:"var(--ink-mute)"}}>搜索中…</span>}
          <button onClick={onClose} style={{background:"none",border:"none",cursor:"pointer",fontSize:18,color:"var(--ink-3)"}}>✕</button>
        </div>
        {results.length > 0 && (
          <div style={{maxHeight:420,overflowY:"auto"}}>
            {results.map((r, i) => (
              <div key={i} style={{padding:"14px 20px",borderBottom:"1px solid var(--line-soft)",cursor:"pointer"}}
                onMouseEnter={e => e.currentTarget.style.background="var(--bg-soft)"}
                onMouseLeave={e => e.currentTarget.style.background=""}>
                <div style={{display:"flex",gap:8,alignItems:"center",marginBottom:4}}>
                  <span style={{fontSize:11,padding:"2px 8px",background:"rgba(184,146,84,.15)",color:"var(--gold)",letterSpacing:1}}>{typeMap[r.type]||r.type}</span>
                  <span style={{fontFamily:"var(--serif)",fontSize:15,color:"var(--ink)"}}>{r.title}</span>
                  {r.tag && <span style={{fontSize:11,color:"var(--ink-3)"}}>{r.tag}</span>}
                </div>
                <div style={{fontSize:12,color:"var(--ink-3)",lineHeight:1.6,overflow:"hidden",display:"-webkit-box",WebkitLineClamp:2,WebkitBoxOrient:"vertical"}}>
                  {typeof r.summary === "string" ? r.summary.replace(/[\[\]"]/g,"") : ""}
                </div>
              </div>
            ))}
          </div>
        )}
        {q && !loading && results.length === 0 && (
          <div style={{padding:"28px 20px",textAlign:"center",color:"var(--ink-3)",fontFamily:"var(--serif)"}}>未找到与「{q}」相关的内容</div>
        )}
        {!q && (
          <div style={{padding:"16px 20px",color:"var(--ink-3)",fontSize:13}}>
            试试搜索：<span style={{cursor:"pointer",color:"var(--jade)"}} onClick={()=>search("失眠")}>失眠</span>
            {" · "}<span style={{cursor:"pointer",color:"var(--jade)"}} onClick={()=>search("气虚")}>气虚</span>
            {" · "}<span style={{cursor:"pointer",color:"var(--jade)"}} onClick={()=>search("山药")}>山药</span>
          </div>
        )}
      </div>
    </div>
  );
}

// ============= Quiz Modal =============
function QuizModal({ open, onClose }) {
  const [mode, setMode] = React.useState(null);
  const [questions, setQuestions] = React.useState([]);
  const [step, setStep] = React.useState(0);
  const [answers, setAnswers] = React.useState({});
  const [result, setResult] = React.useState(null);
  const [loading, setLoading] = React.useState(false);

  React.useEffect(() => {
    if (!open) { setMode(null); setQuestions([]); return; }
    setStep(0); setAnswers({}); setResult(null);
  }, [open]);

  const startQuiz = (selectedMode) => {
    setMode(selectedMode);
    setLoading(true);
    fetch(`${API}/quiz/questions?mode=${selectedMode}`)
      .then(r => r.json())
      .then(data => { setQuestions(data); setLoading(false); });
  };

  const answer = (idx) => {
    const q = questions[step];
    const newAnswers = { ...answers, [q.id]: idx };
    setAnswers(newAnswers);
    if (step < questions.length - 1) { setStep(step + 1); }
    else { submitQuiz(newAnswers); }
  };

  const submitQuiz = async (ans) => {
    setLoading(true);
    try {
      const data = await fetch(`${API}/quiz/result`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ answers: ans }),
      }).then(r => r.json());
      setResult(data);
    } finally { setLoading(false); }
  };

  if (!open) return null;
  const q = questions[step];
  const progress = questions.length ? Math.round((step / questions.length) * 100) : 0;

  const modeOptions = [
    { id: "quick",    label: "快速测试", time: "约 10 题 · 2 分钟",  desc: "快速了解主要体质倾向，适合初次了解",   mark: "⚡" },
    { id: "standard", label: "标准测试", time: "约 30 题 · 5 分钟",  desc: "较全面的体质评估，适合大多数人",       mark: "◎", recommended: true },
  ];

  return (
    <div style={{position:"fixed",inset:0,zIndex:1000,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(31,26,18,.6)",backdropFilter:"blur(4px)"}}
      onClick={!result ? undefined : onClose}>
      <div style={{width:"min(560px,92vw)",background:"var(--bg-card)",border:"1px solid var(--line)",boxShadow:"0 24px 60px rgba(0,0,0,.3)",maxHeight:"90vh",overflowY:"auto"}}
        onClick={e => e.stopPropagation()}>

        <div style={{padding:"20px 28px",borderBottom:"1px solid var(--line)",display:"flex",justifyContent:"space-between",alignItems:"center"}}>
          <div>
            <div style={{fontSize:11,letterSpacing:4,color:"var(--vermillion)"}}>九型体质自测</div>
            <div style={{fontFamily:"var(--serif)",fontSize:18,letterSpacing:3,marginTop:4}}>
              {!mode ? "选择测试方式" : result ? "测评结果" : `第 ${step+1} 题 / 共 ${questions.length} 题`}
            </div>
          </div>
          <button onClick={onClose} style={{background:"none",border:"none",cursor:"pointer",fontSize:20,color:"var(--ink-3)"}}>x</button>
        </div>

        {mode && !result && (
          <div style={{height:3,background:"var(--line-soft)"}}>
            <div style={{height:"100%",width:progress+"%",background:"var(--jade)",transition:"width .3s"}}/>
          </div>
        )}

        {!mode && (
          <div style={{padding:"28px"}}>
            <div style={{fontFamily:"var(--serif)",fontSize:13,color:"var(--ink-3)",letterSpacing:1,marginBottom:24,textAlign:"center"}}>
              根据你的时间与需求，选择合适的测试方式
            </div>
            <div style={{display:"flex",flexDirection:"column",gap:12}}>
              {modeOptions.map(m => (
                <button key={m.id} onClick={() => startQuiz(m.id)}
                  style={{position:"relative",padding:"18px 22px",border:`1px solid ${m.recommended ? "var(--jade)" : "var(--line)"}`,background:m.recommended ? "rgba(44,74,59,.04)" : "var(--bg-soft)",textAlign:"left",cursor:"pointer",transition:"all .2s",borderRadius:2,width:"100%"}}
                  onMouseEnter={e=>{e.currentTarget.style.borderColor="var(--jade)";e.currentTarget.style.background="rgba(44,74,59,.06)";}}
                  onMouseLeave={e=>{e.currentTarget.style.borderColor=m.recommended?"var(--jade)":"var(--line)";e.currentTarget.style.background=m.recommended?"rgba(44,74,59,.04)":"var(--bg-soft)";}}>
                  {m.recommended && (
                    <span style={{position:"absolute",top:-1,right:16,padding:"2px 10px",background:"var(--jade)",color:"#fff",fontSize:11,letterSpacing:2,fontFamily:"var(--serif)"}}>推 荐</span>
                  )}
                  <div style={{display:"flex",alignItems:"center",gap:14}}>
                    <span style={{fontSize:22,width:28,textAlign:"center",color:"var(--jade)"}}>{m.mark}</span>
                    <div style={{flex:1}}>
                      <div style={{display:"flex",alignItems:"baseline",gap:10,marginBottom:4}}>
                        <span style={{fontFamily:"var(--serif)",fontSize:16,letterSpacing:2,color:"var(--ink)"}}>{m.label}</span>
                        <span style={{fontSize:12,color:"var(--jade)",letterSpacing:1}}>{m.time}</span>
                      </div>
                      <div style={{fontSize:13,color:"var(--ink-3)",letterSpacing:1}}>{m.desc}</div>
                    </div>
                    <span style={{color:"var(--jade)",fontSize:16,flexShrink:0}}>→</span>
                  </div>
                </button>
              ))}
            </div>
          </div>
        )}

        {mode && (
          <div style={{padding:"32px 28px"}}>
            {loading && (
              <div style={{textAlign:"center",padding:40,fontFamily:"var(--serif)",color:"var(--ink-3)"}}>
                {questions.length === 0 ? "题目加载中..." : "正在分析体质..."}
              </div>
            )}

            {!loading && !result && q && (
              <div>
                <div style={{fontFamily:"var(--serif)",fontSize:18,letterSpacing:2,lineHeight:1.7,marginBottom:28,color:"var(--ink)"}}>{q.question}</div>
                <div style={{display:"flex",flexDirection:"column",gap:10}}>
                  {q.options.map((opt, i) => (
                    <button key={i} onClick={() => answer(i)}
                      style={{padding:"14px 20px",border:"1px solid var(--line)",background:"var(--bg-soft)",textAlign:"left",cursor:"pointer",fontFamily:"var(--sans)",fontSize:14,color:"var(--ink-2)",letterSpacing:1,transition:"all .15s",borderRadius:2}}
                      onMouseEnter={e=>{e.currentTarget.style.borderColor="var(--jade)";e.currentTarget.style.background="rgba(44,74,59,.06)";}}
                      onMouseLeave={e=>{e.currentTarget.style.borderColor="var(--line)";e.currentTarget.style.background="var(--bg-soft)";}}>
                      <span style={{color:"var(--vermillion)",fontFamily:"var(--serif)",marginRight:10}}>{["甲","乙","丙","丁"][i]}</span>
                      {opt}
                    </button>
                  ))}
                </div>
                {step > 0 && (
                  <button onClick={() => setStep(step-1)}
                    style={{marginTop:20,background:"none",border:"none",cursor:"pointer",fontSize:13,color:"var(--ink-3)"}}>
                    &lt;- 上一题
                  </button>
                )}
              </div>
            )}

            {!loading && result && (
              <div>
                <div style={{textAlign:"center",marginBottom:28}}>
                  <div style={{fontFamily:"var(--serif)",fontSize:48,color:"var(--jade)",letterSpacing:6,marginBottom:8}}>{result.primary.name}</div>
                  <div style={{fontSize:12,letterSpacing:4,color:"var(--ink-3)"}}>{result.primary.en}</div>
                  <div style={{display:"inline-block",marginTop:12,padding:"4px 14px",border:"1px solid var(--jade-3,#6E8E78)",color:"var(--jade)",fontSize:12,letterSpacing:2,borderRadius:14}}>{result.primary.tag}</div>
                </div>
                <div style={{background:"var(--bg-soft)",padding:"16px 20px",borderLeft:"2px solid var(--jade)",marginBottom:20}}>
                  <div style={{fontSize:13,color:"var(--ink-2)",lineHeight:1.8}}><span style={{color:"var(--jade)",fontFamily:"var(--serif)",marginRight:8}}>主症</span>{result.primary.sign}</div>
                  <div style={{fontSize:13,color:"var(--ink-2)",lineHeight:1.8,marginTop:6}}><span style={{color:"var(--jade)",fontFamily:"var(--serif)",marginRight:8}}>舌脉</span>{result.primary.desc}</div>
                </div>
                <div style={{marginBottom:20}}>
                  <div style={{fontFamily:"var(--serif)",fontSize:14,letterSpacing:2,marginBottom:12,color:"var(--ink)"}}>调理建议</div>
                  {result.primary.advice.map((a, i) => (
                    <div key={i} style={{padding:"8px 0",borderBottom:"1px dashed var(--line-soft)",fontSize:13,color:"var(--ink-2)"}}>{a}</div>
                  ))}
                </div>
                <div style={{marginBottom:24}}>
                  <div style={{fontFamily:"var(--serif)",fontSize:14,letterSpacing:2,marginBottom:10,color:"var(--ink)"}}>常用本草</div>
                  <div style={{display:"flex",flexWrap:"wrap",gap:6}}>
                    {result.primary.herbs.map(h => (
                      <span key={h} style={{padding:"4px 10px",background:"rgba(184,146,84,.12)",border:"1px solid rgba(184,146,84,.3)",fontFamily:"var(--serif)",fontSize:13,letterSpacing:2}}>{h}</span>
                    ))}
                  </div>
                </div>
                {(() => {
                  const LINKS = {
                    '阳虚': [
                      { name: '古酒熏足', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=3eq3liyhi2d8tbj&shopAutoChoose=1&yz_from=qr' },
                      { name: '暖宫养护', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=35zzn561901pp7h&shopAutoChoose=1&yz_from=qr' },
                      { name: 'D脉养—肾', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=2x664ltsey6ulj6&shopAutoChoose=1&yz_from=qr' },
                      { name: '温宫脉养', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=2opxz3iwjd3fxkm&shopAutoChoose=1&yz_from=qr' },
                      { name: 'GSYY草本滴液', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=2xkxeczhiwx0dmb&shopAutoChoose=1&yz_from=qr' },
                      { name: 'NGQS草本滴液', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=273k5td2pz5250i&shopAutoChoose=1&yz_from=qr' },
                    ],
                    '阴虚': [
                      { name: '脾胃养护', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=2fsg4lesdgjrxc5&shopAutoChoose=1&yz_from=qr' },
                      { name: '腰肾养护', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=2og2chfmqylxp5a&shopAutoChoose=1&yz_from=qr' },
                      { name: 'JPYQ草本滴液', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=2oscr7s5et97xwl&shopAutoChoose=1&yz_from=qr' },
                      { name: 'SGLQ草本滴液', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=3exfepwdb1fy5gv&shopAutoChoose=1&yz_from=qr' },
                    ],
                    '气虚': [
                      { name: '脾胃养护', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=2fsg4lesdgjrxc5&shopAutoChoose=1&yz_from=qr' },
                      { name: '腰肾养护', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=2og2chfmqylxp5a&shopAutoChoose=1&yz_from=qr' },
                      { name: 'JPYQ草本滴液', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=2oscr7s5et97xwl&shopAutoChoose=1&yz_from=qr' },
                      { name: 'LCYH草本滴液', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=3njtziwq3ept9uy&shopAutoChoose=1&yz_from=qr' },
                    ],
                    '气郁': [
                      { name: '肝胆养护', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=2x4wekjgbbakd9w&shopAutoChoose=1&yz_from=qr' },
                      { name: '心肺养护', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=364vt1fpf2tq5ct&shopAutoChoose=1&yz_from=qr' },
                      { name: 'SGLQ草本滴液', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=3exfepwdb1fy5gv&shopAutoChoose=1&yz_from=qr' },
                    ],
                    '痰湿': [
                      { name: '古酒熏足', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=3eq3liyhi2d8tbj&shopAutoChoose=1&yz_from=qr' },
                      { name: '脾胃养护', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=2fsg4lesdgjrxc5&shopAutoChoose=1&yz_from=qr' },
                      { name: '温宫脉养', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=2opxz3iwjd3fxkm&shopAutoChoose=1&yz_from=qr' },
                      { name: 'NGQS草本滴液', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=273k5td2pz5250i&shopAutoChoose=1&yz_from=qr' },
                    ],
                    '湿热': [
                      { name: 'D脉养—宫', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=1yh5xghlxkzj16w&shopAutoChoose=1&yz_from=qr' },
                      { name: 'CWY草本滴液', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=36dh65k5yf6lpoo&shopAutoChoose=1&yz_from=qr' },
                      { name: 'FY草本滴液', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=3eq2jx0lr0zzxag&shopAutoChoose=1&yz_from=qr' },
                    ],
                    '血瘀': [
                      { name: '暖宫养护', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=35zzn561901pp7h&shopAutoChoose=1&yz_from=qr' },
                      { name: 'NGQS草本滴液', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=273k5td2pz5250i&shopAutoChoose=1&yz_from=qr' },
                    ],
                    '血虚': [
                      { name: '温宫脉养', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=2opxz3iwjd3fxkm&shopAutoChoose=1&yz_from=qr' },
                      { name: 'LCYH草本滴液', url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=3njtziwq3ept9uy&shopAutoChoose=1&yz_from=qr' },
                    ],
                  };
                  const name = (result.primary && result.primary.name) || '';
                  const key = Object.keys(LINKS).find(k => name.includes(k));
                  const products = key ? LINKS[key] : [];
                  if (!products.length) return null;
                  return (
                    <div style={{marginBottom:24}}>
                      <div style={{fontFamily:"var(--serif)",fontSize:14,letterSpacing:2,marginBottom:4,color:"var(--ink)"}}>
                        专属调理方案
                      </div>
                      <div style={{fontSize:12,color:"var(--ink-3)",letterSpacing:1,marginBottom:12}}>根据体质类型为您推荐古柗春特色调理服务</div>
                      <div style={{display:"flex",flexDirection:"column",gap:8}}>
                        {products.map((p, i) => (
                          <a key={i} href={p.url} target="_blank" rel="noopener noreferrer"
                            style={{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"12px 16px",border:"1px solid rgba(184,146,84,.35)",background:"rgba(184,146,84,.06)",textDecoration:"none",transition:"all .15s",borderRadius:2}}>
                            <div style={{display:"flex",alignItems:"center",gap:10}}>
                              <span style={{width:6,height:6,borderRadius:"50%",background:"var(--vermillion)",flexShrink:0,display:"inline-block"}}/>
                              <span style={{fontFamily:"var(--serif)",fontSize:14,letterSpacing:1,color:"var(--ink)"}}>{p.name}</span>
                            </div>
                            <span style={{fontSize:12,color:"var(--vermillion)",letterSpacing:1,flexShrink:0}}>立即购买 →</span>
                          </a>
                        ))}
                      </div>
                    </div>
                  );
                })()}
                <div style={{display:"flex",gap:10}}>
                  <button onClick={() => { setStep(0); setAnswers({}); setResult(null); setMode(null); setQuestions([]); }}
                    style={{flex:1,padding:"12px",border:"1px solid var(--line)",background:"var(--bg-soft)",cursor:"pointer",fontFamily:"var(--sans)",fontSize:13,letterSpacing:2}}>
                    重新测评
                  </button>
                  <button onClick={onClose}
                    style={{flex:1,padding:"12px",border:"none",background:"var(--jade)",color:"#fff",cursor:"pointer",fontFamily:"var(--sans)",fontSize:13,letterSpacing:2}}>
                    关闭
                  </button>
                </div>
              </div>
            )}
          </div>
        )}
      </div>
    </div>
  );
}

// ============= Top Nav =============

// ============= AI 体质分析弹窗 v2 =============
function AIAnalysisModal({ open, onClose }) {
  if (!open) return null;

  // steps: 0=信息 1=舌苔 2=面部 3=舌下脉 4=分析中 5=结果
  const [step, setStep] = React.useState(0);
  const [info, setInfo] = React.useState({ name:'', phone:'', gender:'女', birthday:'', height:'', weight:'' });
  const [tongueImg,    setTongueImg]    = React.useState(null);
  const [faceImg,      setFaceImg]      = React.useState(null);
  const [sublingualImg,setSublingualImg]= React.useState(null);
  const [result, setResult] = React.useState(null);
  const [recordId, setRecordId] = React.useState(null);
  const [shareMode, setShareMode] = React.useState(false);
  const [activeTab, setActiveTab] = React.useState(0);
  const [apiProducts, setApiProducts] = React.useState(null);
  const [error,  setError]  = React.useState('');

  const setField = function(k, v) { setInfo(function(prev){ var o={}; for(var x in prev) o[x]=prev[x]; o[k]=v; return o; }); };

  const compressImage = function(file) {
    return new Promise(function(resolve) {
      var reader = new FileReader();
      reader.onload = function(e) {
        var img = new Image();
        img.onload = function() {
          var canvas = document.createElement('canvas');
          var maxW = 800;
          var scale = Math.min(1, maxW / Math.max(img.width, img.height));
          canvas.width  = img.width  * scale;
          canvas.height = img.height * scale;
          canvas.getContext('2d').drawImage(img, 0, 0, canvas.width, canvas.height);
          resolve(canvas.toDataURL('image/jpeg', 0.82));
        };
        img.src = e.target.result;
      };
      reader.readAsDataURL(file);
    });
  };

  // 打开弹窗时从服务器加载产品数据
  React.useEffect(function() {
    if (!open) return;
    fetch('/api/products')
      .then(function(r){ return r.json(); })
      .then(function(data){ if (data.success) setApiProducts(data.data); })
      .catch(function(){}); // 失败时静默，使用本地兜底数据
  }, [open]);

  const handleAnalyze = async function() {
    setStep(4); setError('');
    try {
      var payload = {
        name: info.name, phone: info.phone, gender: info.gender,
        birthday: info.birthday, height: info.height, weight: info.weight,
        tongueImage: tongueImg, faceImage: faceImg, sublingualImage: sublingualImg
      };
      var resp = await fetch('/api/ai-analysis', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload)
      });
      var data = await resp.json();
      if (!data.success) throw new Error(data.error || '分析失败，请重试');
      setResult(data.analysis);
      setRecordId(data.recordId || null);
      setStep(5);
    } catch(e) {
      setError(e.message);
      setStep(3);
    }
  };

  const reset = function() {
    setStep(0);
    setInfo({ name:'', phone:'', gender:'女', birthday:'', height:'', weight:'' });
    setTongueImg(null); setFaceImg(null); setSublingualImg(null);
    setResult(null); setRecordId(null); setShareMode(false); setActiveTab(0); setApiProducts(null); setError('');
  };

  // ── 产品链接 ──────────────────────────────────────────────────
  var LINKS = {
    '阳虚': [
      { name: '古酒熏足',      url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=3eq3liyhi2d8tbj&shopAutoChoose=1&yz_from=qr' },
      { name: '暖宫养护',      url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=35zzn561901pp7h&shopAutoChoose=1&yz_from=qr' },
      { name: 'D脉养—肾',     url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=2x664ltsey6ulj6&shopAutoChoose=1&yz_from=qr' },
      { name: '温宫脉养',      url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=2opxz3iwjd3fxkm&shopAutoChoose=1&yz_from=qr' },
      { name: 'GSYY草本滴液',  url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=2xkxeczhiwx0dmb&shopAutoChoose=1&yz_from=qr' },
      { name: 'NGQS草本滴液',  url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=273k5td2pz5250i&shopAutoChoose=1&yz_from=qr' },
    ],
    '阴虚': [
      { name: '脾胃养护',      url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=2fsg4lesdgjrxc5&shopAutoChoose=1&yz_from=qr' },
      { name: '腰肾养护',      url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=2og2chfmqylxp5a&shopAutoChoose=1&yz_from=qr' },
      { name: 'JPYQ草本滴液',  url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=2oscr7s5et97xwl&shopAutoChoose=1&yz_from=qr' },
      { name: 'SGLQ草本滴液',  url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=3exfepwdb1fy5gv&shopAutoChoose=1&yz_from=qr' },
    ],
    '气虚': [
      { name: '脾胃养护',      url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=2fsg4lesdgjrxc5&shopAutoChoose=1&yz_from=qr' },
      { name: '腰肾养护',      url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=2og2chfmqylxp5a&shopAutoChoose=1&yz_from=qr' },
      { name: 'JPYQ草本滴液',  url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=2oscr7s5et97xwl&shopAutoChoose=1&yz_from=qr' },
      { name: 'LCYH草本滴液',  url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=3njtziwq3ept9uy&shopAutoChoose=1&yz_from=qr' },
    ],
    '气郁': [
      { name: '肝胆养护',      url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=2x4wekjgbbakd9w&shopAutoChoose=1&yz_from=qr' },
      { name: '心肺养护',      url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=364vt1fpf2tq5ct&shopAutoChoose=1&yz_from=qr' },
      { name: 'SGLQ草本滴液',  url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=3exfepwdb1fy5gv&shopAutoChoose=1&yz_from=qr' },
    ],
    '痰湿': [
      { name: '古酒熏足',      url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=3eq3liyhi2d8tbj&shopAutoChoose=1&yz_from=qr' },
      { name: '脾胃养护',      url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=2fsg4lesdgjrxc5&shopAutoChoose=1&yz_from=qr' },
      { name: '温宫脉养',      url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=2opxz3iwjd3fxkm&shopAutoChoose=1&yz_from=qr' },
      { name: 'NGQS草本滴液',  url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=273k5td2pz5250i&shopAutoChoose=1&yz_from=qr' },
    ],
    '湿热': [
      { name: 'D脉养—宫',     url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=1yh5xghlxkzj16w&shopAutoChoose=1&yz_from=qr' },
      { name: 'CWY草本滴液',  url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=36dh65k5yf6lpoo&shopAutoChoose=1&yz_from=qr' },
      { name: 'FY草本滴液',   url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=3eq2jx0lr0zzxag&shopAutoChoose=1&yz_from=qr' },
    ],
    '血瘀': [
      { name: '暖宫养护',      url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=35zzn561901pp7h&shopAutoChoose=1&yz_from=qr' },
      { name: 'NGQS草本滴液',  url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=273k5td2pz5250i&shopAutoChoose=1&yz_from=qr' },
    ],
    '血虚': [
      { name: '温宫脉养',      url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/service?kdtId=188888413&keyword=2opxz3iwjd3fxkm&shopAutoChoose=1&yz_from=qr' },
      { name: 'LCYH草本滴液',  url: 'https://mei6xdbxefhnhxonb.youzan.com/h5/goods/product?kdtId=188888413&keyword=3njtziwq3ept9uy&shopAutoChoose=1&yz_from=qr' },
    ],
    '平和': [],
  };

  // ── 样式常量 ──────────────────────────────────────────────────
  var inp = { width:'100%', padding:'10px 12px', border:'1px solid var(--line)', background:'var(--bg-soft)', fontFamily:'var(--sans)', fontSize:14, letterSpacing:1, boxSizing:'border-box', outline:'none', color:'var(--ink)', borderRadius:2 };
  var lbl = { display:'block', fontSize:12, letterSpacing:2, color:'var(--ink-3)', marginBottom:6, fontFamily:'var(--sans)' };

  // ── 拍照区组件 ────────────────────────────────────────────────
  // ── 实时相机组件（带人脸/舌苔引导线）─────────────────────────────────
  var CameraCapture = function(props) {
    var img = props.img, setImg = props.setImg, label = props.label, guideType = props.guideType || 'tongue';
    var videoRef = React.useRef(null);
    var canvasRef = React.useRef(null);
    var streamRef = React.useRef(null);
    var _co = React.useState(false); var camOpen = _co[0], setCamOpen = _co[1];
    var _ce = React.useState(false); var camError = _ce[0], setCamError = _ce[1];
    var _pv = React.useState(null);  var preview = _pv[0], setPreview = _pv[1];
    var _fu = React.useState(true);    var facingUser = _fu[0], setFacingUser = _fu[1];

    React.useEffect(function() {
      if (!camOpen || preview || camError) return;
      var dead = false;
      if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
        setCamError(true); return;
      }
      var fm = facingUser ? 'user' : 'environment';
      function applyStream(s) {
        if (dead) { s.getTracks().forEach(function(t){t.stop();}); return; }
        streamRef.current = s;
        if (videoRef.current) { videoRef.current.srcObject = s; }
      }
      // 三级容错：exact → ideal → 枚举设备索引
      navigator.mediaDevices.getUserMedia({ video: { facingMode: { exact: fm } } })
        .then(applyStream)
        .catch(function() {
          if (dead) return;
          navigator.mediaDevices.getUserMedia({ video: { facingMode: fm, width: { ideal: 1280 }, height: { ideal: 720 } } })
            .then(applyStream)
            .catch(function() {
              if (dead) return;
              // 枚举设备，按索引选前/后置
              navigator.mediaDevices.enumerateDevices().then(function(devs) {
                var cams = devs.filter(function(d){ return d.kind === 'videoinput'; });
                var idx = facingUser ? Math.max(0, cams.length - 1) : 0;
                var id = cams[idx] && cams[idx].deviceId;
                if (!id) { if (!dead) setCamError(true); return; }
                navigator.mediaDevices.getUserMedia({ video: { deviceId: { exact: id } } })
                  .then(applyStream).catch(function(){ if (!dead) setCamError(true); });
              }).catch(function(){ if (!dead) setCamError(true); });
            });
        });
      return function() {
        dead = true;
        if (streamRef.current) { streamRef.current.getTracks().forEach(function(t){t.stop();}); streamRef.current = null; }
      };
    }, [camOpen, preview, camError, facingUser]);

    function stopStream() {
      if (streamRef.current) { streamRef.current.getTracks().forEach(function(t){t.stop();}); streamRef.current = null; }
    }
    function doCapture() {
      var v = videoRef.current, c = canvasRef.current;
      if (!v || !c) return;
      c.width = v.videoWidth || 1280; c.height = v.videoHeight || 720;
      c.getContext('2d').drawImage(v, 0, 0);
      setPreview(c.toDataURL('image/jpeg', 0.85));
      stopStream();
    }
    function doConfirm() { setImg(preview); setPreview(null); setCamOpen(false); setCamError(false); }
    function doRetake()  { setPreview(null); setCamError(false); }
    function doClose()   { stopStream(); setCamOpen(false); setCamError(false); setPreview(null); }

    // 引导线覆盖层（viewBox 100x160，适配竖屏相机）
    var guideOverlay;
    if (guideType === 'face') {
      // 人脸轮廓：额头宽 → 脸颊 → 下巴尖
      guideOverlay = (
        <svg style={{position:'absolute',inset:0,width:'100%',height:'100%',pointerEvents:'none'}} viewBox="0 0 100 160" preserveAspectRatio="xMidYMid meet"><path d="M50,8 C64,8 77,15 84,27 C91,39 91,53 89,65 C87,77 83,89 76,99 C70,109 62,118 56,124 C53,127 51,130 50,130 C49,130 47,127 44,124 C38,118 30,109 24,99 C17,89 13,77 11,65 C9,53 9,39 16,27 C23,15 36,8 50,8" fill="none" stroke="rgba(255,255,255,0.52)" strokeWidth="0.85"/><circle cx="50" cy="8" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="62" cy="9" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="74" cy="14" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="82" cy="25" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="89" cy="37" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="91" cy="51" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="89" cy="65" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="86" cy="77" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="82" cy="90" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="76" cy="100" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="68" cy="110" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="60" cy="119" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="55" cy="125" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="51" cy="130" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="50" cy="130" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="49" cy="130" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="45" cy="125" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="40" cy="119" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="32" cy="110" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="24" cy="100" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="18" cy="90" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="14" cy="77" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="11" cy="65" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="9" cy="51" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="11" cy="37" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="18" cy="25" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="26" cy="14" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="38" cy="9" r="1.3" fill="rgba(175,175,175,0.72)"/><path d="M25,57 L33,51 L41,57 L33,63 Z" fill="none" stroke="rgba(255,255,255,0.45)" strokeWidth="0.7"/><circle cx="25" cy="57" r="0.95" fill="rgba(175,175,175,0.68)"/><circle cx="33" cy="51" r="0.95" fill="rgba(175,175,175,0.68)"/><circle cx="41" cy="57" r="0.95" fill="rgba(175,175,175,0.68)"/><circle cx="33" cy="63" r="0.95" fill="rgba(175,175,175,0.68)"/><path d="M59,57 L67,51 L75,57 L67,63 Z" fill="none" stroke="rgba(255,255,255,0.45)" strokeWidth="0.7"/><circle cx="59" cy="57" r="0.95" fill="rgba(175,175,175,0.68)"/><circle cx="67" cy="51" r="0.95" fill="rgba(175,175,175,0.68)"/><circle cx="75" cy="57" r="0.95" fill="rgba(175,175,175,0.68)"/><circle cx="67" cy="63" r="0.95" fill="rgba(175,175,175,0.68)"/><line x1="50" y1="74" x2="50" y2="86" stroke="rgba(255,255,255,0.38)" strokeWidth="0.65"/><line x1="44" y1="86" x2="56" y2="86" stroke="rgba(255,255,255,0.38)" strokeWidth="0.65"/><circle cx="50" cy="74" r="0.9" fill="rgba(175,175,175,0.62)"/><circle cx="50" cy="86" r="0.9" fill="rgba(175,175,175,0.62)"/><circle cx="44" cy="86" r="0.9" fill="rgba(175,175,175,0.62)"/><circle cx="56" cy="86" r="0.9" fill="rgba(175,175,175,0.62)"/><path d="M36,101 C42,98 50,97 58,98 C62,99 64,101" fill="none" stroke="rgba(255,255,255,0.38)" strokeWidth="0.7"/><circle cx="36" cy="101" r="0.9" fill="rgba(175,175,175,0.6)"/><circle cx="50" cy="97" r="0.9" fill="rgba(175,175,175,0.6)"/><circle cx="64" cy="101" r="0.9" fill="rgba(175,175,175,0.6)"/><text x="50" y="159" textAnchor="middle" fill="rgba(255,255,255,0.82)" fontSize="4.8" fontFamily="sans-serif" letterSpacing="0.5">面部对准轮廓，自然放松</text></svg>
      );
    } else if (guideType === 'sublingual') {
      guideOverlay = (
        <svg style={{position:'absolute',inset:0,width:'100%',height:'100%',pointerEvents:'none'}} viewBox="0 0 100 160" preserveAspectRatio="xMidYMid meet"><path d="M50,8 C64,8 77,15 84,27 C91,39 91,53 89,65 C87,77 83,89 76,99 C70,109 62,118 56,124 C53,127 51,130 50,130 C49,130 47,127 44,124 C38,118 30,109 24,99 C17,89 13,77 11,65 C9,53 9,39 16,27 C23,15 36,8 50,8" fill="none" stroke="rgba(255,255,255,0.52)" strokeWidth="0.85"/><circle cx="50" cy="8" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="62" cy="9" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="74" cy="14" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="82" cy="25" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="89" cy="37" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="91" cy="51" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="89" cy="65" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="86" cy="77" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="82" cy="90" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="76" cy="100" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="68" cy="110" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="60" cy="119" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="55" cy="125" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="51" cy="130" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="50" cy="130" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="49" cy="130" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="45" cy="125" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="40" cy="119" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="32" cy="110" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="24" cy="100" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="18" cy="90" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="14" cy="77" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="11" cy="65" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="9" cy="51" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="11" cy="37" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="18" cy="25" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="26" cy="14" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="38" cy="9" r="1.3" fill="rgba(175,175,175,0.72)"/><path d="M25,57 L33,51 L41,57 L33,63 Z" fill="none" stroke="rgba(255,255,255,0.45)" strokeWidth="0.7"/><circle cx="25" cy="57" r="0.95" fill="rgba(175,175,175,0.68)"/><circle cx="33" cy="51" r="0.95" fill="rgba(175,175,175,0.68)"/><circle cx="41" cy="57" r="0.95" fill="rgba(175,175,175,0.68)"/><circle cx="33" cy="63" r="0.95" fill="rgba(175,175,175,0.68)"/><path d="M59,57 L67,51 L75,57 L67,63 Z" fill="none" stroke="rgba(255,255,255,0.45)" strokeWidth="0.7"/><circle cx="59" cy="57" r="0.95" fill="rgba(175,175,175,0.68)"/><circle cx="67" cy="51" r="0.95" fill="rgba(175,175,175,0.68)"/><circle cx="75" cy="57" r="0.95" fill="rgba(175,175,175,0.68)"/><circle cx="67" cy="63" r="0.95" fill="rgba(175,175,175,0.68)"/><line x1="50" y1="74" x2="50" y2="86" stroke="rgba(255,255,255,0.38)" strokeWidth="0.65"/><line x1="44" y1="86" x2="56" y2="86" stroke="rgba(255,255,255,0.38)" strokeWidth="0.65"/><circle cx="50" cy="74" r="0.9" fill="rgba(175,175,175,0.62)"/><circle cx="50" cy="86" r="0.9" fill="rgba(175,175,175,0.62)"/><circle cx="44" cy="86" r="0.9" fill="rgba(175,175,175,0.62)"/><circle cx="56" cy="86" r="0.9" fill="rgba(175,175,175,0.62)"/><path d="M33,103 C38,100 44,98 50,97 C56,98 62,100 67,103" fill="none" stroke="#F5A623" strokeWidth="1.4"/><path d="M33,103 C30,110 29,120 31,129 C34,137 40,142 46,144 C48,145 50,145 52,145 C54,145 56,145 58,143 C64,140 70,135 71,129 C72,119 70,110 67,103" fill="none" stroke="#F5A623" strokeWidth="1.4"/><circle cx="33" cy="103" r="1.35" fill="#F5A623"/><circle cx="38" cy="100" r="1.35" fill="#F5A623"/><circle cx="44" cy="98" r="1.35" fill="#F5A623"/><circle cx="50" cy="97" r="1.35" fill="#F5A623"/><circle cx="56" cy="98" r="1.35" fill="#F5A623"/><circle cx="62" cy="100" r="1.35" fill="#F5A623"/><circle cx="67" cy="103" r="1.35" fill="#F5A623"/><circle cx="70" cy="110" r="1.35" fill="#F5A623"/><circle cx="71" cy="120" r="1.35" fill="#F5A623"/><circle cx="69" cy="129" r="1.35" fill="#F5A623"/><circle cx="65" cy="136" r="1.35" fill="#F5A623"/><circle cx="57" cy="141" r="1.35" fill="#F5A623"/><circle cx="50" cy="143" r="1.35" fill="#F5A623"/><circle cx="43" cy="141" r="1.35" fill="#F5A623"/><circle cx="35" cy="136" r="1.35" fill="#F5A623"/><circle cx="31" cy="129" r="1.35" fill="#F5A623"/><circle cx="29" cy="120" r="1.35" fill="#F5A623"/><circle cx="30" cy="110" r="1.35" fill="#F5A623"/><path d="M50,99 C47,109 53,120 50,139" fill="none" stroke="#F5A623" strokeWidth="0.8" strokeDasharray="1.8 1.8"/><text x="50" y="159" textAnchor="middle" fill="rgba(255,255,255,0.82)" fontSize="4.8" fontFamily="sans-serif" letterSpacing="0.5">翘舌至上颚，露出舌底脉络</text></svg>
      );
    } else {
      guideOverlay = (
        <svg style={{position:'absolute',inset:0,width:'100%',height:'100%',pointerEvents:'none'}} viewBox="0 0 100 160" preserveAspectRatio="xMidYMid meet"><path d="M50,8 C64,8 77,15 84,27 C91,39 91,53 89,65 C87,77 83,89 76,99 C70,109 62,118 56,124 C53,127 51,130 50,130 C49,130 47,127 44,124 C38,118 30,109 24,99 C17,89 13,77 11,65 C9,53 9,39 16,27 C23,15 36,8 50,8" fill="none" stroke="rgba(255,255,255,0.52)" strokeWidth="0.85"/><circle cx="50" cy="8" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="62" cy="9" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="74" cy="14" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="82" cy="25" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="89" cy="37" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="91" cy="51" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="89" cy="65" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="86" cy="77" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="82" cy="90" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="76" cy="100" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="68" cy="110" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="60" cy="119" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="55" cy="125" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="51" cy="130" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="50" cy="130" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="49" cy="130" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="45" cy="125" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="40" cy="119" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="32" cy="110" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="24" cy="100" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="18" cy="90" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="14" cy="77" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="11" cy="65" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="9" cy="51" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="11" cy="37" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="18" cy="25" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="26" cy="14" r="1.3" fill="rgba(175,175,175,0.72)"/><circle cx="38" cy="9" r="1.3" fill="rgba(175,175,175,0.72)"/><path d="M25,57 L33,51 L41,57 L33,63 Z" fill="none" stroke="rgba(255,255,255,0.45)" strokeWidth="0.7"/><circle cx="25" cy="57" r="0.95" fill="rgba(175,175,175,0.68)"/><circle cx="33" cy="51" r="0.95" fill="rgba(175,175,175,0.68)"/><circle cx="41" cy="57" r="0.95" fill="rgba(175,175,175,0.68)"/><circle cx="33" cy="63" r="0.95" fill="rgba(175,175,175,0.68)"/><path d="M59,57 L67,51 L75,57 L67,63 Z" fill="none" stroke="rgba(255,255,255,0.45)" strokeWidth="0.7"/><circle cx="59" cy="57" r="0.95" fill="rgba(175,175,175,0.68)"/><circle cx="67" cy="51" r="0.95" fill="rgba(175,175,175,0.68)"/><circle cx="75" cy="57" r="0.95" fill="rgba(175,175,175,0.68)"/><circle cx="67" cy="63" r="0.95" fill="rgba(175,175,175,0.68)"/><line x1="50" y1="74" x2="50" y2="86" stroke="rgba(255,255,255,0.38)" strokeWidth="0.65"/><line x1="44" y1="86" x2="56" y2="86" stroke="rgba(255,255,255,0.38)" strokeWidth="0.65"/><circle cx="50" cy="74" r="0.9" fill="rgba(175,175,175,0.62)"/><circle cx="50" cy="86" r="0.9" fill="rgba(175,175,175,0.62)"/><circle cx="44" cy="86" r="0.9" fill="rgba(175,175,175,0.62)"/><circle cx="56" cy="86" r="0.9" fill="rgba(175,175,175,0.62)"/><path d="M33,103 C38,100 44,98 50,97 C56,98 62,100 67,103" fill="none" stroke="#F5A623" strokeWidth="1.4"/><path d="M33,103 C30,111 29,122 30,133 C32,143 37,151 43,155 C46,157 48,157 50,157 C52,157 54,157 57,155 C63,151 68,143 70,133 C71,122 70,111 67,103" fill="none" stroke="#F5A623" strokeWidth="1.4"/><circle cx="33" cy="103" r="1.35" fill="#F5A623"/><circle cx="38" cy="100" r="1.35" fill="#F5A623"/><circle cx="44" cy="98" r="1.35" fill="#F5A623"/><circle cx="50" cy="97" r="1.35" fill="#F5A623"/><circle cx="56" cy="98" r="1.35" fill="#F5A623"/><circle cx="62" cy="100" r="1.35" fill="#F5A623"/><circle cx="67" cy="103" r="1.35" fill="#F5A623"/><circle cx="70" cy="111" r="1.35" fill="#F5A623"/><circle cx="71" cy="122" r="1.35" fill="#F5A623"/><circle cx="70" cy="133" r="1.35" fill="#F5A623"/><circle cx="67" cy="142" r="1.35" fill="#F5A623"/><circle cx="62" cy="150" r="1.35" fill="#F5A623"/><circle cx="57" cy="154" r="1.35" fill="#F5A623"/><circle cx="50" cy="156" r="1.35" fill="#F5A623"/><circle cx="43" cy="154" r="1.35" fill="#F5A623"/><circle cx="38" cy="150" r="1.35" fill="#F5A623"/><circle cx="33" cy="142" r="1.35" fill="#F5A623"/><circle cx="30" cy="133" r="1.35" fill="#F5A623"/><circle cx="29" cy="122" r="1.35" fill="#F5A623"/><circle cx="30" cy="111" r="1.35" fill="#F5A623"/><path d="M50,99 C47,111 53,124 50,150" fill="none" stroke="#F5A623" strokeWidth="0.8" strokeDasharray="1.8 1.8"/><text x="50" y="159" textAnchor="middle" fill="rgba(255,255,255,0.82)" fontSize="4.8" fontFamily="sans-serif" letterSpacing="0.5">伸出舌头，对准橙色轮廓框</text></svg>
      );
    }

    // 已有照片：显示预览 + 重拍
    if (img) {
      return (
        <div style={{marginBottom:20,position:'relative'}}>
          <img src={img} style={{width:'100%',maxHeight:260,objectFit:'cover',border:'1px solid var(--line)'}} />
          <button onClick={function(){setImg(null);}}
            style={{position:'absolute',top:8,right:8,background:'rgba(0,0,0,.6)',border:'none',color:'#fff',borderRadius:'50%',width:30,height:30,cursor:'pointer',fontSize:14}}>✕</button>
          <div style={{position:'absolute',bottom:0,left:0,right:0,background:'rgba(44,74,59,.85)',padding:'8px 14px'}}>
            <div style={{fontSize:11,color:'rgba(255,255,255,.9)',letterSpacing:1}}>✓ 照片已上传，点击右上角 ✕ 可重拍</div>
          </div>
        </div>
      );
    }

    // 全屏相机界面
    if (camOpen) {
      return (
        <div style={{position:'fixed',inset:0,zIndex:1010,background:'#000',display:'flex',flexDirection:'column'}}>
          <canvas ref={canvasRef} style={{display:'none'}} />
          <button onClick={doClose}
            style={{position:'absolute',top:16,left:16,zIndex:20,background:'rgba(0,0,0,.55)',border:'none',color:'#fff',borderRadius:'50%',width:40,height:40,cursor:'pointer',fontSize:20,display:'flex',alignItems:'center',justifyContent:'center'}}>✕</button>

          <div style={{position:'absolute',top:16,left:0,right:0,textAlign:'center',zIndex:20,pointerEvents:'none'}}>
            <span style={{background:'rgba(0,0,0,.45)',padding:'4px 18px',borderRadius:20,color:'rgba(255,255,255,.85)',fontSize:13,letterSpacing:2}}>{label}</span>
          </div>
          {preview ? (
            <div style={{flex:1,position:'relative'}}>
              <img src={preview} style={{width:'100%',height:'100%',objectFit:'cover'}} />
              <div style={{position:'absolute',bottom:0,left:0,right:0,padding:'28px 20px 48px',background:'linear-gradient(transparent,rgba(0,0,0,.75))',display:'flex',gap:14}}>
                <button onClick={doRetake}
                  style={{flex:1,padding:'14px 0',background:'rgba(255,255,255,.12)',border:'1px solid rgba(255,255,255,.4)',color:'#fff',borderRadius:4,fontSize:15,cursor:'pointer',letterSpacing:2,fontFamily:'inherit'}}>重拍</button>
                <button onClick={doConfirm}
                  style={{flex:1,padding:'14px 0',background:'var(--jade)',border:'none',color:'#fff',borderRadius:4,fontSize:15,cursor:'pointer',letterSpacing:2,fontFamily:'inherit'}}>使用此照片</button>
              </div>
            </div>
          ) : camError ? (
            <div style={{flex:1,display:'flex',flexDirection:'column',alignItems:'center',justifyContent:'center',padding:32,gap:20}}>
              <div style={{fontSize:40}}>📷</div>
              <div style={{color:'#fff',fontSize:15,textAlign:'center',lineHeight:2,letterSpacing:1}}>相机访问失败<br/><span style={{fontSize:12,opacity:.5,letterSpacing:0}}>请检查系统设置中的相机权限</span></div>
              <label style={{padding:'13px 32px',background:'var(--jade)',color:'#fff',borderRadius:4,cursor:'pointer',fontSize:14,letterSpacing:2}}>
                <input type="file" accept="image/*" capture="environment" style={{display:'none'}}
                  onChange={async function(e){ if(e.target.files[0]){ var d=await compressImage(e.target.files[0]); setImg(d); doClose(); } }} />
                从相册选取
              </label>
            </div>
          ) : (
            <div style={{flex:1,position:'relative',overflow:'hidden'}}>
              <video ref={videoRef} autoPlay playsInline muted style={{width:'100%',height:'100%',objectFit:'cover'}} />
              {guideOverlay}
              <div style={{position:'absolute',bottom:0,left:0,right:0,padding:'16px 20px 44px',background:'linear-gradient(transparent,rgba(0,0,0,.65))',display:'flex',alignItems:'center',gap:12}}>
                <div style={{width:52,display:'flex',flexDirection:'column',alignItems:'center',gap:3,cursor:'pointer'}}>
                  <div style={{color:'rgba(255,255,255,.65)',fontSize:22,lineHeight:1}}>&#9776;</div>
                  <div style={{color:'rgba(255,255,255,.6)',fontSize:10,letterSpacing:0.5}}>注意事项</div>
                </div>
                <button onClick={doCapture}
                  style={{flex:1,padding:'15px 0',background:'#4A90E2',border:'none',color:'#fff',borderRadius:28,fontSize:18,cursor:'pointer',letterSpacing:4,fontFamily:'inherit',fontWeight:500}}>拍照</button>
                <button onClick={function(){ setFacingUser(function(p){return !p;}); }}
                  style={{width:52,display:'flex',flexDirection:'column',alignItems:'center',gap:3,background:'none',border:'none',cursor:'pointer',padding:0}}>
                  <div style={{color:'rgba(255,255,255,.65)',fontSize:22,lineHeight:1}}>&#x21BA;</div>
                  <div style={{color:'rgba(255,255,255,.6)',fontSize:10,letterSpacing:0.5}}>切换镜头</div>
                </button>
              </div>
            </div>
          )}
        </div>
      );
    }

    // 触发按钮（黑色取景框预览）
    return (
      <div style={{marginBottom:20}} onClick={function(){setCamOpen(true); setCamError(false);}}>
        <div style={{position:'relative',background:'#111',borderRadius:4,overflow:'hidden',minHeight:190,display:'flex',alignItems:'center',justifyContent:'center',cursor:'pointer'}}>
          <svg style={{position:'absolute',inset:0,width:'100%',height:'100%'}} viewBox="0 0 340 190" preserveAspectRatio="none">
            {guideType !== 'face' && (
              <path d="M170,32 C180,32 212,44 222,66 C232,88 228,114 218,128 C208,142 190,150 170,152 C150,150 132,142 122,128 C112,114 108,88 118,66 C128,44 160,32 170,32 Z"
                fill="none" stroke="rgba(255,255,255,0.3)" strokeWidth="1.5" strokeDasharray="8 4"/>
            )}
            <path d="M8 44 L8 20 L32 20" fill="none" stroke="rgba(255,255,255,0.4)" strokeWidth="2" strokeLinecap="round"/>
            <path d="M332 44 L332 20 L308 20" fill="none" stroke="rgba(255,255,255,0.4)" strokeWidth="2" strokeLinecap="round"/>
            <path d="M8 146 L8 170 L32 170" fill="none" stroke="rgba(255,255,255,0.4)" strokeWidth="2" strokeLinecap="round"/>
            <path d="M332 146 L332 170 L308 170" fill="none" stroke="rgba(255,255,255,0.4)" strokeWidth="2" strokeLinecap="round"/>
          </svg>
          <div style={{position:'relative',zIndex:1,textAlign:'center'}}>
            <div style={{fontSize:34,marginBottom:10}}>📷</div>
            <div style={{color:'rgba(255,255,255,.9)',fontSize:13,letterSpacing:2,marginBottom:4}}>{label}</div>
            <div style={{color:'rgba(255,255,255,.45)',fontSize:11,letterSpacing:1}}>点击开始拍摄</div>
          </div>
        </div>
      </div>
    );
  };

  var photoBtn = function(img, setImg, label, hint) {
    var gt = label.indexOf('面部') >= 0 ? 'face' : (label.indexOf('舌底') >= 0 || label.indexOf('脉') >= 0) ? 'sublingual' : 'tongue';
    return React.createElement(CameraCapture, {img:img, setImg:setImg, label:label, guideType:gt});
  };

  // ── 雷达图 SVG ────────────────────────────────────────────────
  var RadarChart = function(props) {
    var data = props.data;
    var labels = ['平和质','气虚质','阳虚质','阴虚质','痰湿质','湿热质','血瘀质','气郁质','特禀质'];
    var N = labels.length;
    var cx = 110; var cy = 110; var R = 85;
    var points = labels.map(function(k, i) {
      var angle = (i / N) * Math.PI * 2 - Math.PI / 2;
      var val   = Math.min(100, Math.max(0, (data && data[k]) ? data[k] : 0));
      var r     = (val / 100) * R;
      return { x: cx + r * Math.cos(angle), y: cy + r * Math.sin(angle),
               lx: cx + (R + 18) * Math.cos(angle), ly: cy + (R + 18) * Math.sin(angle),
               val: val, label: k.replace('质','') };
    });
    var polyPts = points.map(function(p){ return p.x + ',' + p.y; }).join(' ');
    var gridLines = [25,50,75,100].map(function(pct) {
      var r2 = (pct / 100) * R;
      var gpts = labels.map(function(k, i) {
        var angle = (i / N) * Math.PI * 2 - Math.PI / 2;
        return (cx + r2 * Math.cos(angle)) + ',' + (cy + r2 * Math.sin(angle));
      }).join(' ');
      return <polygon key={pct} points={gpts} fill="none" stroke="var(--line)" strokeWidth="0.8" />;
    });
    var axes = labels.map(function(k, i) {
      var angle = (i / N) * Math.PI * 2 - Math.PI / 2;
      return <line key={k} x1={cx} y1={cy} x2={cx + R * Math.cos(angle)} y2={cy + R * Math.sin(angle)} stroke="var(--line)" strokeWidth="0.8" />;
    });
    return (
      <svg viewBox="0 0 220 220" style={{width:'100%', maxWidth:280, display:'block', margin:'0 auto'}}>
        {gridLines}{axes}
        <polygon points={polyPts} fill="rgba(71,115,88,.25)" stroke="var(--jade)" strokeWidth="2" />
        {points.map(function(p, i){
          var anchor = p.lx < cx - 5 ? 'end' : p.lx > cx + 5 ? 'start' : 'middle';
          return (
            <g key={i}>
              <circle cx={p.x} cy={p.y} r="3" fill="var(--jade)" />
              <text x={p.lx} y={p.ly} textAnchor={anchor} fontSize="9" fill="var(--ink-2)" dominantBaseline="central" fontFamily="var(--sans)">{p.label}</text>
            </g>
          );
        })}
      </svg>
    );
  };

  // ── 步骤条 ────────────────────────────────────────────────────
  var STEP_LABELS = ['基本信息','舌苔','面部','舌下脉'];
  var stepBar = step < 4 ? (
    <div style={{display:'flex', gap:4, marginBottom:24}}>
      {STEP_LABELS.map(function(s, i) {
        return (
          <div key={i} style={{flex:1, textAlign:'center'}}>
            <div style={{height:3, borderRadius:2, background: step >= i ? 'var(--jade)' : 'var(--line)', marginBottom:4}} />
            <div style={{fontSize:10, color: step >= i ? 'var(--jade)' : 'var(--ink-3)', letterSpacing:1}}>{s}</div>
          </div>
        );
      })}
    </div>
  ) : null;

  return (
    <div style={{position:'fixed', top:0, left:0, right:0, bottom:0, background:'rgba(31,26,18,.72)', zIndex:2000, display:'flex', alignItems:'flex-end', justifyContent:'center'}}
      onClick={function(e){ if(e.target===e.currentTarget) onClose(); }}>
      <div style={{background:'var(--bg)', width:'100%', maxWidth:540, maxHeight:'92vh', overflowY:'auto', padding:'24px 20px 52px', borderRadius:'16px 16px 0 0', position:'relative'}}>

        {/* Header */}
        <div style={{display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:20}}>
          <div>
            <div style={{fontFamily:'var(--serif)', fontSize:20, letterSpacing:3, color:'var(--ink)'}}>AI 体质分析</div>
            <div style={{fontSize:11, color:'var(--ink-3)', letterSpacing:2, marginTop:3}}>望诊 · 辨质 · 调理建议</div>
          </div>
          <button onClick={onClose} style={{background:'none', border:'none', cursor:'pointer', fontSize:20, color:'var(--ink-3)', padding:4}}>✕</button>
        </div>

        {stepBar}

        {/* ── Step 0: 基本信息 ── */}
        {step === 0 && (
          <div>
            <div style={{fontFamily:'var(--serif)', fontSize:15, letterSpacing:2, marginBottom:16, color:'var(--ink)'}}>填写基本信息</div>
            <div style={{display:'grid', gridTemplateColumns:'1fr 1fr', gap:12, marginBottom:12}}>
              <div><label style={lbl}>姓名</label>
                <input style={inp} value={info.name} onChange={function(e){setField('name',e.target.value);}} placeholder="请输入姓名" />
              </div>
              <div><label style={lbl}>联系电话</label>
                <input style={inp} type="tel" value={info.phone} onChange={function(e){setField('phone',e.target.value);}} placeholder="手机号码" />
              </div>
              <div><label style={lbl}>性别</label>
                <select style={inp} value={info.gender} onChange={function(e){setField('gender',e.target.value);}}>
                  <option>女</option><option>男</option>
                </select>
              </div>
              <div><label style={lbl}>公历生日</label>
                <input style={inp} type="text" value={info.birthday} onChange={function(e){setField('birthday',e.target.value);}} placeholder="如 1990-01-01" />
              </div>
              <div><label style={lbl}>身高 (cm)</label>
                <input style={inp} type="number" value={info.height} onChange={function(e){setField('height',e.target.value);}} placeholder="如 165" />
              </div>
              <div><label style={lbl}>体重 (kg)</label>
                <input style={inp} type="number" value={info.weight} onChange={function(e){setField('weight',e.target.value);}} placeholder="如 55" />
              </div>
            </div>
            <div style={{fontSize:12, color:'var(--ink-3)', letterSpacing:1, marginBottom:16, padding:'10px 12px', background:'rgba(184,146,84,.08)', borderLeft:'3px solid var(--gold)'}}>
              信息仅用于本次体质分析，不会公开分享
            </div>
            <button style={{width:'100%', padding:'13px', border:'none', background:'var(--jade)', color:'#fff', cursor:'pointer', fontFamily:'var(--sans)', fontSize:14, letterSpacing:3, borderRadius:2, marginTop:8}}
              onClick={function(){setStep(1);}}>下一步：拍摄舌苔</button>
          </div>
        )}



        {/* ── Step 1: 舌苔 ── */}
        {step === 1 && (
          <div>
            <div style={{fontFamily:'var(--serif)', fontSize:15, letterSpacing:2, marginBottom:16, color:'var(--ink)'}}>拍摄舌苔图</div>
            {photoBtn(tongueImg, setTongueImg, '拍摄舌面照片', '轻轻伸出舌头，在自然光或白光下拍摄清晰舌面，包含舌尖至舌根的完整区域。')}
            <div style={{display:'flex', gap:10}}>
              <button style={{width:'100%', padding:'12px', border:'1px solid var(--line)', background:'var(--bg-soft)', color:'var(--ink)', cursor:'pointer', fontFamily:'var(--sans)', fontSize:13, letterSpacing:2, borderRadius:2, marginTop:8}}
                onClick={function(){setStep(0);}}>上一步</button>
              <button style={{width:'100%', padding:'13px', border:'none', background:'var(--jade)', color:'#fff', cursor:'pointer', fontFamily:'var(--sans)', fontSize:14, letterSpacing:2, borderRadius:2, marginTop:8, flex:2}}
                onClick={function(){setStep(2);}}>
                {tongueImg ? '下一步：拍面部' : '跳过'}
              </button>
            </div>
          </div>
        )}

        {/* ── Step 2: 面部 ── */}
        {step === 2 && (
          <div>
            <div style={{fontFamily:'var(--serif)', fontSize:15, letterSpacing:2, marginBottom:16, color:'var(--ink)'}}>拍摄面部图</div>
            {photoBtn(faceImg, setFaceImg, '拍摄面部照片', '自然光下正面拍摄，面部放松，不需化妆，便于分析面色与气色。')}
            <div style={{display:'flex', gap:10}}>
              <button style={{width:'100%', padding:'12px', border:'1px solid var(--line)', background:'var(--bg-soft)', color:'var(--ink)', cursor:'pointer', fontFamily:'var(--sans)', fontSize:13, letterSpacing:2, borderRadius:2, marginTop:8}}
                onClick={function(){setStep(1);}}>上一步</button>
              <button style={{width:'100%', padding:'13px', border:'none', background:'var(--jade)', color:'#fff', cursor:'pointer', fontFamily:'var(--sans)', fontSize:14, letterSpacing:2, borderRadius:2, marginTop:8, flex:2}}
                onClick={function(){setStep(3);}}>
                {faceImg ? '下一步：拍舌下脉' : '跳过'}
              </button>
            </div>
          </div>
        )}

        {/* ── Step 3: 舌下脉 ── */}
        {step === 3 && (
          <div>
            <div style={{fontFamily:'var(--serif)', fontSize:15, letterSpacing:2, marginBottom:16, color:'var(--ink)'}}>拍摄舌下脉络</div>
            {photoBtn(sublingualImg, setSublingualImg, '拍摄舌底脉络', '将舌头翘起贴近上颚，在明亮光线下拍摄舌底正中两侧的脉络，用于判断气血瘀滞情况。')}
            {error && <div style={{color:'#c0392b', fontSize:13, marginBottom:8, letterSpacing:1}}>{error}</div>}
            {(!tongueImg && !faceImg && !sublingualImg) && (
              <div style={{color:'#c0392b', fontSize:12, marginBottom:8, letterSpacing:1}}>请至少上传一张照片</div>
            )}
            <div style={{display:'flex', gap:10}}>
              <button style={{width:'100%', padding:'12px', border:'1px solid var(--line)', background:'var(--bg-soft)', color:'var(--ink)', cursor:'pointer', fontFamily:'var(--sans)', fontSize:13, letterSpacing:2, borderRadius:2, marginTop:8}}
                onClick={function(){setStep(2);}}>上一步</button>
              <button
                style={{width:'100%', padding:'13px', border:'none', background:'var(--jade)', color:'#fff', cursor:'pointer', fontFamily:'var(--sans)', fontSize:14, letterSpacing:2, borderRadius:2, marginTop:8, flex:2, opacity:(tongueImg||faceImg||sublingualImg)?1:0.45}}
                onClick={function(){ if(tongueImg||faceImg||sublingualImg) handleAnalyze(); }}
                disabled={!tongueImg && !faceImg && !sublingualImg}>
                开始 AI 分析
              </button>
            </div>
          </div>
        )}

        {/* ── Step 4: 分析中 ── */}
        {step === 4 && (
          <div style={{textAlign:'center', padding:'40px 0 60px'}}>
            <div style={{fontFamily:'var(--serif)', fontSize:18, letterSpacing:3, color:'var(--ink)', marginBottom:16}}>AI 望诊中</div>
            <div style={{width:48, height:48, border:'3px solid var(--line)', borderTop:'3px solid var(--jade)', borderRadius:'50%', margin:'0 auto 24px', animation:'spin 1s linear infinite'}} />
            <div style={{fontSize:13, color:'var(--ink-3)', letterSpacing:2, lineHeight:2}}>
              正在分析舌象 · 面色 · 脉络<br/>结合九种体质辨识知识库<br/>生成个性化调理方案
            </div>
            <style>{'@keyframes spin { to { transform: rotate(360deg); } }'}</style>
          </div>
        )}

        {/* ── Step 5: 结果 (Tab 布局) ── */}
        {step === 5 && result && (
          <div>
            {/* ── Tab 导航 ── */}
            {(function(){
              var tabs = ['概览','五脏','体质','调养','保存','健康预测'];
              return (
                <div style={{display:'flex', borderBottom:'2px solid var(--line)', marginBottom:16, overflowX:'auto'}}>
                  {tabs.map(function(t, i){
                    var active = activeTab === i;
                    return (
                      <button key={i} onClick={function(){ setActiveTab(i); }}
                        style={{flex:'0 0 auto', padding:'10px 14px', border:'none', background:'none', cursor:'pointer',
                          fontFamily:'var(--sans)', fontSize:13, letterSpacing:2,
                          color: active ? 'var(--jade)' : 'var(--ink-3)',
                          borderBottom: active ? '2px solid var(--jade)' : '2px solid transparent',
                          marginBottom:'-2px', whiteSpace:'nowrap'}}>
                        {t}
                      </button>
                    );
                  })}
                </div>
              );
            })()}

            {/* ══ Tab 0: 概览 ══ */}
            {activeTab === 0 && (
              <div>
                {/* 主体质 */}
                <div style={{textAlign:'center', padding:'16px 0 20px', borderBottom:'1px solid var(--line)', marginBottom:20}}>
                  <div style={{fontSize:11, letterSpacing:4, color:'var(--ink-3)', marginBottom:8, fontFamily:'var(--sans)'}}>AI 体质分析结果</div>
                  <div style={{fontFamily:'var(--serif)', fontSize:32, letterSpacing:5, color:'var(--jade)', marginBottom:4}}>
                    {(result.primary && result.primary.name) || '未知'}
                  </div>
                  {result.primary && result.primary.en && (
                    <div style={{fontSize:12, color:'var(--ink-3)', letterSpacing:2, marginBottom:8}}>{result.primary.en}</div>
                  )}
                  {result.primary && result.primary.score ? (
                    <div style={{display:'inline-block', background:'rgba(184,146,84,.12)', padding:'4px 16px', borderRadius:20, fontSize:12, color:'var(--gold)', letterSpacing:2}}>
                      主体质匹配度 {result.primary.score}%
                    </div>
                  ) : null}
                  {result.secondary && result.secondary.name ? (
                    <div style={{fontSize:12, color:'var(--ink-3)', letterSpacing:2, marginTop:8}}>
                      兼夹：{result.secondary.name}{result.secondary.score ? (' ' + result.secondary.score + '%') : ''}
                    </div>
                  ) : null}
                  {result.primary && result.primary.description && (
                    <div style={{fontSize:13, color:'var(--ink-2)', letterSpacing:1, lineHeight:1.8, marginTop:12, textAlign:'left', padding:'10px 12px', background:'var(--bg-soft)', borderRadius:3}}>
                      {result.primary.description}
                    </div>
                  )}
                </div>

                {/* 雷达图 */}
                {result.constitutions && (
                  <div style={{marginBottom:20}}>
                    <div style={{fontFamily:'var(--serif)', fontSize:13, letterSpacing:2, marginBottom:12, color:'var(--ink)'}}>兼夹体质雷达图</div>
                    <RadarChart data={result.constitutions} />
                  </div>
                )}

                {/* 体质指数 BMI */}
                {(function(){
                  var h = parseFloat(info.height); var w = parseFloat(info.weight);
                  if (!h || !w) return null;
                  var bmi = w / ((h/100)*(h/100));
                  var bmiStr = bmi.toFixed(1);
                  var level, col, bg;
                  if (bmi < 18.5)    { level='偏瘦';   col='#5b9bd5'; bg='rgba(91,155,213,.1)'; }
                  else if (bmi < 24) { level='正常';   col='var(--jade)'; bg='rgba(71,115,88,.08)'; }
                  else if (bmi < 28) { level='超重';   col='#e6a23c'; bg='rgba(230,162,60,.1)'; }
                  else if (bmi < 32) { level='肥胖';   col='#e05c45'; bg='rgba(224,92,69,.1)'; }
                  else               { level='重度肥胖'; col='#c0392b'; bg='rgba(192,57,43,.1)'; }
                  return (
                    <div style={{padding:'14px', background:bg, border:'1px solid '+col+'44', borderRadius:4, marginBottom:4}}>
                      <div style={{fontFamily:'var(--serif)', fontSize:13, letterSpacing:2, marginBottom:10, color:'var(--ink)'}}>体质指数</div>
                      <div style={{display:'flex', alignItems:'center', gap:16}}>
                        <div style={{textAlign:'center', minWidth:60}}>
                          <div style={{fontFamily:'var(--serif)', fontSize:34, color:col}}>{bmiStr}</div>
                          <div style={{fontSize:11, color:'var(--ink-3)', letterSpacing:1}}>BMI</div>
                        </div>
                        <div style={{flex:1}}>
                          <div style={{display:'inline-block', padding:'3px 14px', background:col, color:'#fff', borderRadius:20, fontSize:12, letterSpacing:2, marginBottom:8}}>{level}</div>
                          <div style={{display:'flex', gap:3}}>
                            {[['偏瘦','#5b9bd5'],['正常','var(--jade)'],['超重','#e6a23c'],['肥胖','#e05c45'],['重度肥胖','#c0392b']].map(function(item,i){
                              return <div key={i} style={{flex:1, height:5, background:item[1], borderRadius:2, opacity:level===item[0]?1:0.25}} />;
                            })}
                          </div>
                        </div>
                      </div>
                    </div>
                  );
                })()}
              </div>
            )}

            {/* ══ Tab 1: 五脏 ══ */}
            {activeTab === 1 && (
              <div>
                {/* 五脏关注 */}
                {result.wuZang ? (
                  <div style={{marginBottom:20}}>
                    <div style={{fontFamily:'var(--serif)', fontSize:13, letterSpacing:2, marginBottom:12, color:'var(--ink)'}}>五脏关注</div>
                    <div style={{display:'grid', gridTemplateColumns:'1fr 1fr', gap:8, marginBottom:12}}>
                      {[['肝','liver','木'],['心','heart','火'],['脾','spleen','土'],['肺','lung','金'],['肾','kidney','水']].map(function(item){
                        var organ=item[0]; var key=item[1]; var elem=item[2];
                        var d = result.wuZang[key];
                        if (!d) return null;
                        var col = d.level==='偏弱' ? '#e05c45' : d.level==='偏旺' ? '#e6a23c' : 'var(--jade)';
                        return (
                          <div key={key} style={{padding:'10px 12px', background:'var(--bg-soft)', borderRadius:4, borderLeft:'3px solid '+col}}>
                            <div style={{display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:4}}>
                              <span style={{fontFamily:'var(--serif)', fontSize:15, color:'var(--ink)'}}>{organ}<span style={{fontSize:11, color:'var(--ink-3)'}}>({elem})</span></span>
                              <span style={{fontSize:11, padding:'1px 8px', background:col+'22', color:col, borderRadius:10, letterSpacing:1}}>{d.level}</span>
                            </div>
                            <div style={{fontSize:12, color:'var(--ink-3)', letterSpacing:1, lineHeight:1.6}}>{d.note}</div>
                          </div>
                        );
                      })}
                    </div>
                    {result.wuZang.tongue_zones && (
                      <div style={{fontSize:13, color:'var(--ink-2)', letterSpacing:1, lineHeight:1.8, padding:'10px 12px', background:'rgba(184,146,84,.06)', borderLeft:'3px solid var(--gold)', borderRadius:2, marginBottom:16}}>
                        <span style={{color:'var(--gold)', fontFamily:'var(--serif)'}}>舌诊分区 · </span>{result.wuZang.tongue_zones}
                      </div>
                    )}
                  </div>
                ) : (
                  <div style={{textAlign:'center', padding:'30px', color:'var(--ink-3)', fontSize:13}}>暂无五脏数据</div>
                )}

                {/* 望诊分析 */}
                {(result.tongueAnalysis || result.faceAnalysis || result.sublingualAnalysis) && (
                  <div style={{marginBottom:20}}>
                    <div style={{fontFamily:'var(--serif)', fontSize:13, letterSpacing:2, marginBottom:10, color:'var(--ink)'}}>望诊分析</div>
                    {result.tongueAnalysis && (
                      <div style={{fontSize:13, color:'var(--ink-2)', letterSpacing:1, lineHeight:1.8, marginBottom:8, padding:'10px 12px', background:'var(--bg-soft)', borderRadius:2}}>
                        <span style={{color:'var(--vermillion)', fontFamily:'var(--serif)'}}>舌 · </span>{result.tongueAnalysis}
                      </div>
                    )}
                    {result.faceAnalysis && (
                      <div style={{fontSize:13, color:'var(--ink-2)', letterSpacing:1, lineHeight:1.8, marginBottom:8, padding:'10px 12px', background:'var(--bg-soft)', borderRadius:2}}>
                        <span style={{color:'var(--vermillion)', fontFamily:'var(--serif)'}}>面 · </span>{result.faceAnalysis}
                      </div>
                    )}
                    {result.sublingualAnalysis && (
                      <div style={{fontSize:13, color:'var(--ink-2)', letterSpacing:1, lineHeight:1.8, padding:'10px 12px', background:'var(--bg-soft)', borderRadius:2}}>
                        <span style={{color:'var(--vermillion)', fontFamily:'var(--serif)'}}>脉 · </span>{result.sublingualAnalysis}
                      </div>
                    )}
                  </div>
                )}
              </div>
            )}

            {/* ══ Tab 2: 体质 ══ */}
            {activeTab === 2 && (
              <div>
                {/* 五行弱脏 */}
                {result.wuXing && (
                  <div style={{marginBottom:20, padding:'14px', background:'rgba(184,146,84,.06)', border:'1px solid rgba(184,146,84,.2)', borderRadius:4}}>
                    <div style={{fontFamily:'var(--serif)', fontSize:13, letterSpacing:2, marginBottom:10, color:'var(--ink)'}}>五行弱脏</div>
                    {result.wuXing.weak_organs && result.wuXing.weak_organs.length > 0 && (
                      <div style={{display:'flex', flexWrap:'wrap', gap:8, marginBottom:8}}>
                        {result.wuXing.weak_organs.map(function(o,i){
                          return <span key={i} style={{padding:'3px 12px', background:'rgba(184,146,84,.18)', fontSize:13, letterSpacing:2, color:'var(--gold)', borderRadius:20, fontFamily:'var(--serif)'}}>{o}</span>;
                        })}
                      </div>
                    )}
                    {result.wuXing.tendency && (
                      <div style={{fontSize:12, color:'var(--vermillion)', letterSpacing:1, marginBottom:8}}>{result.wuXing.tendency}</div>
                    )}
                    {result.wuXing.narrative && (
                      <div style={{fontSize:13, color:'var(--ink-2)', letterSpacing:1, lineHeight:1.8}}>{result.wuXing.narrative}</div>
                    )}
                  </div>
                )}

                {/* 特异体质 */}
                {result.teYiTizhi && result.teYiTizhi.name && (
                  <div style={{marginBottom:20, padding:'14px', background:'rgba(224,92,69,.05)', border:'1px solid rgba(224,92,69,.2)', borderRadius:4}}>
                    <div style={{fontFamily:'var(--serif)', fontSize:13, letterSpacing:2, marginBottom:8, color:'var(--ink)'}}>特异体质</div>
                    <div style={{display:'inline-block', padding:'4px 14px', background:'rgba(224,92,69,.12)', color:'#e05c45', borderRadius:20, fontSize:13, letterSpacing:2, marginBottom:8, fontFamily:'var(--serif)'}}>{result.teYiTizhi.name}</div>
                    {result.teYiTizhi.description && (
                      <div style={{fontSize:13, color:'var(--ink-2)', letterSpacing:1, lineHeight:1.8}}>{result.teYiTizhi.description}</div>
                    )}
                  </div>
                )}

                {/* 症状 */}
                {result.symptoms && result.symptoms.length > 0 && (
                  <div style={{marginBottom:20}}>
                    <div style={{fontFamily:'var(--serif)', fontSize:13, letterSpacing:2, marginBottom:10, color:'var(--ink)'}}>症状特征</div>
                    <div style={{display:'flex', flexWrap:'wrap', gap:8}}>
                      {result.symptoms.map(function(s,i){
                        return <span key={i} style={{padding:'4px 12px', border:'1px solid rgba(184,146,84,.4)', fontSize:12, letterSpacing:1, color:'var(--ink-2)', borderRadius:20}}>{s}</span>;
                      })}
                    </div>
                  </div>
                )}

                {/* 发病倾向 */}
                {result.disease_tendencies && (
                  <div style={{marginBottom:20}}>
                    <div style={{fontFamily:'var(--serif)', fontSize:13, letterSpacing:2, marginBottom:10, color:'var(--ink)'}}>发病倾向</div>
                    {result.disease_tendencies.primary && result.disease_tendencies.primary.length > 0 && (
                      <div style={{marginBottom:10}}>
                        <div style={{fontSize:11, letterSpacing:2, color:'var(--jade)', marginBottom:6}}>主体质</div>
                        <div style={{display:'flex', flexWrap:'wrap', gap:6}}>
                          {result.disease_tendencies.primary.map(function(d,i){
                            return <span key={i} style={{padding:'3px 10px', background:'rgba(71,115,88,.08)', border:'1px solid rgba(71,115,88,.2)', fontSize:12, letterSpacing:1, color:'var(--jade)', borderRadius:2}}>{d}</span>;
                          })}
                        </div>
                      </div>
                    )}
                    {result.disease_tendencies.secondary && result.disease_tendencies.secondary.length > 0 && (
                      <div>
                        <div style={{fontSize:11, letterSpacing:2, color:'var(--gold)', marginBottom:6}}>兼夹体质</div>
                        <div style={{display:'flex', flexWrap:'wrap', gap:6}}>
                          {result.disease_tendencies.secondary.map(function(d,i){
                            return <span key={i} style={{padding:'3px 10px', background:'rgba(184,146,84,.08)', border:'1px solid rgba(184,146,84,.2)', fontSize:12, letterSpacing:1, color:'var(--gold)', borderRadius:2}}>{d}</span>;
                          })}
                        </div>
                      </div>
                    )}
                  </div>
                )}

                {/* 健康风险 */}
                {result.healthRisk && (
                  <div style={{marginBottom:4}}>
                    <div style={{fontFamily:'var(--serif)', fontSize:13, letterSpacing:2, marginBottom:10, color:'var(--ink)'}}>当下健康风险</div>
                    <div style={{padding:'12px 14px', background:'var(--bg-soft)', borderRadius:4}}>
                      {(function(){
                        var r2 = result.healthRisk;
                        var col2 = r2.overall==='低风险' ? 'var(--jade)' : r2.overall==='中等风险' ? '#e6a23c' : '#e05c45';
                        return (
                          <div>
                            <div style={{display:'flex', alignItems:'center', gap:10, marginBottom:10}}>
                              <span style={{display:'inline-block', width:10, height:10, borderRadius:'50%', background:col2}} />
                              <span style={{fontSize:14, color:col2, letterSpacing:2}}>{r2.overall}</span>
                            </div>
                            {r2.main_risks && r2.main_risks.length > 0 && (
                              <div style={{display:'flex', flexWrap:'wrap', gap:6, marginBottom:8}}>
                                {r2.main_risks.map(function(risk,i){
                                  return <span key={i} style={{padding:'3px 10px', border:'1px solid '+col2+'44', fontSize:12, color:col2, borderRadius:2, letterSpacing:1}}>{risk}</span>;
                                })}
                              </div>
                            )}
                            {r2.season_tips && (
                              <div style={{fontSize:12, color:'var(--ink-3)', letterSpacing:1}}>当季提示：{r2.season_tips}</div>
                            )}
                          </div>
                        );
                      })()}
                    </div>
                  </div>
                )}
              </div>
            )}

            {/* ══ Tab 3: 调养 ══ */}
            {activeTab === 3 && (
              <div>
                {/* 四维调养 */}
                {result.advice && (
                  <div style={{marginBottom:20}}>
                    <div style={{fontFamily:'var(--serif)', fontSize:13, letterSpacing:2, marginBottom:12, color:'var(--ink)'}}>四维调养方案</div>
                    {result.advice.principle && (
                      <div style={{marginBottom:10, padding:'10px 14px', borderLeft:'3px solid var(--jade)', background:'rgba(71,115,88,.05)', borderRadius:'0 3px 3px 0'}}>
                        <div style={{fontSize:11, letterSpacing:2, color:'var(--jade)', marginBottom:4}}>养生原则</div>
                        <div style={{fontSize:13, color:'var(--ink-2)', letterSpacing:1, lineHeight:1.8}}>{result.advice.principle}</div>
                      </div>
                    )}
                    {(result.advice.diet_good || result.advice.diet_bad) && (
                      <div style={{marginBottom:10, padding:'10px 14px', borderLeft:'3px solid var(--jade)', background:'rgba(71,115,88,.05)', borderRadius:'0 3px 3px 0'}}>
                        <div style={{fontSize:11, letterSpacing:2, color:'var(--jade)', marginBottom:6}}>饮食宜忌</div>
                        {result.advice.diet_good && result.advice.diet_good.length > 0 && (
                          <div style={{marginBottom:6}}>
                            <span style={{fontSize:11, color:'var(--ink-3)', letterSpacing:1}}>宜：</span>
                            {result.advice.diet_good.map(function(d,i){
                              return <span key={i} style={{display:'inline-block', padding:'2px 8px', background:'rgba(71,115,88,.12)', fontSize:12, color:'var(--jade)', borderRadius:2, marginRight:4, marginBottom:4}}>{d}</span>;
                            })}
                          </div>
                        )}
                        {result.advice.diet_bad && result.advice.diet_bad.length > 0 && (
                          <div>
                            <span style={{fontSize:11, color:'var(--ink-3)', letterSpacing:1}}>忌：</span>
                            {result.advice.diet_bad.map(function(d,i){
                              return <span key={i} style={{display:'inline-block', padding:'2px 8px', background:'rgba(192,57,43,.08)', fontSize:12, color:'#c0392b', borderRadius:2, marginRight:4, marginBottom:4}}>{d}</span>;
                            })}
                          </div>
                        )}
                      </div>
                    )}
                    {result.advice.mental && (
                      <div style={{marginBottom:10, padding:'10px 14px', borderLeft:'3px solid var(--jade)', background:'rgba(71,115,88,.05)', borderRadius:'0 3px 3px 0'}}>
                        <div style={{fontSize:11, letterSpacing:2, color:'var(--jade)', marginBottom:4}}>精神养生</div>
                        <div style={{fontSize:13, color:'var(--ink-2)', letterSpacing:1, lineHeight:1.8}}>{result.advice.mental}</div>
                      </div>
                    )}
                    {result.advice.lifestyle && (
                      <div style={{marginBottom:10, padding:'10px 14px', borderLeft:'3px solid var(--jade)', background:'rgba(71,115,88,.05)', borderRadius:'0 3px 3px 0'}}>
                        <div style={{fontSize:11, letterSpacing:2, color:'var(--jade)', marginBottom:4}}>起居养生</div>
                        <div style={{fontSize:13, color:'var(--ink-2)', letterSpacing:1, lineHeight:1.8}}>{result.advice.lifestyle}</div>
                      </div>
                    )}
                  </div>
                )}

                {/* 推荐本草 */}
                {result.herbs && result.herbs.length > 0 && (
                  <div style={{marginBottom:20}}>
                    <div style={{fontFamily:'var(--serif)', fontSize:13, letterSpacing:2, marginBottom:10, color:'var(--ink)'}}>建议本草</div>
                    <div style={{display:'flex', flexWrap:'wrap', gap:8}}>
                      {result.herbs.map(function(h,i){
                        return <span key={i} style={{padding:'5px 14px', background:'rgba(71,115,88,.1)', border:'1px solid rgba(71,115,88,.25)', fontSize:13, letterSpacing:2, color:'var(--jade)', borderRadius:2, fontFamily:'var(--serif)'}}>{h}</span>;
                      })}
                    </div>
                  </div>
                )}

                {/* 专属调理方案 */}
                {(function(){
                  var name = (result.primary && result.primary.name) || '';
                  // 优先用服务器数据，兜底用本地 LINKS
                  var sourceMap = apiProducts || LINKS;
                  var key  = Object.keys(sourceMap).find(function(k){ return name.indexOf(k) >= 0; });
                  var products = key ? sourceMap[key] : [];
                  if (!products.length) return null;
                  return (
                    <div style={{marginBottom:8}}>
                      <div style={{fontFamily:'var(--serif)', fontSize:13, letterSpacing:2, marginBottom:4, color:'var(--ink)'}}>专属调理方案</div>
                      <div style={{fontSize:11, color:'var(--ink-3)', letterSpacing:1, marginBottom:10}}>根据体质类型为您推荐古柗春特色调理服务</div>
                      <div style={{display:'flex', flexDirection:'column', gap:8}}>
                        {products.map(function(p,i){
                          return (
                            <a key={i} href={p.url} target="_blank" rel="noopener noreferrer"
                              style={{display:'flex', alignItems:'center', justifyContent:'space-between', padding:'12px 14px', border:'1px solid rgba(184,146,84,.35)', background:'rgba(184,146,84,.05)', textDecoration:'none', borderRadius:3}}>
                              <div style={{display:'flex', alignItems:'center', gap:10}}>
                                <span style={{width:5, height:5, borderRadius:'50%', background:'var(--vermillion)', flexShrink:0, display:'inline-block'}} />
                                <span style={{fontFamily:'var(--serif)', fontSize:14, letterSpacing:1, color:'var(--ink)'}}>{p.name}</span>
                              </div>
                              <span style={{fontSize:12, color:'var(--vermillion)', letterSpacing:1, flexShrink:0}}>立即购买 →</span>
                            </a>
                          );
                        })}
                      </div>
                    </div>
                  );
                })()}
              </div>
            )}

            {/* ══ Tab 4: 保存 ══ */}
            {activeTab === 4 && (
              <div>
                {/* 专属链接 */}
                <div style={{marginBottom:16}}>
                  <div style={{fontFamily:'var(--serif)', fontSize:13, letterSpacing:2, marginBottom:12, color:'var(--ink)'}}>专属报告链接</div>
                  {recordId && !shareMode && (
                    <button style={{width:'100%', padding:'13px', border:'1px solid var(--jade)', background:'rgba(71,115,88,.08)', color:'var(--jade)', cursor:'pointer', fontFamily:'var(--sans)', fontSize:13, letterSpacing:2, borderRadius:2, marginBottom:12}}
                      onClick={function(){ setShareMode(true); }}>
                      🔗 生成专属报告链接
                    </button>
                  )}
                  {shareMode && recordId && (
                    <div style={{padding:'14px', background:'rgba(71,115,88,.05)', border:'1px solid rgba(71,115,88,.25)', borderRadius:4, marginBottom:12}}>
                      <div style={{fontSize:11, color:'var(--jade)', letterSpacing:2, marginBottom:8}}>您的专属报告链接</div>
                      <div style={{fontSize:12, color:'var(--ink)', letterSpacing:1, wordBreak:'break-all', padding:'8px 10px', background:'var(--bg-soft)', borderRadius:2, marginBottom:8, userSelect:'all', lineHeight:1.6}}>
                        {window.location.origin + '/report/' + recordId}
                      </div>
                      <div style={{fontSize:11, color:'var(--ink-3)', letterSpacing:1}}>长按链接可复制，发给朋友查看</div>
                    </div>
                  )}
                  {!recordId && (
                    <div style={{fontSize:12, color:'var(--ink-3)', letterSpacing:1, padding:'10px 12px', background:'var(--bg-soft)', borderRadius:3}}>
                      本次分析链接暂不可用，请重新分析后获取
                    </div>
                  )}
                </div>


                {/* 截图保存 */}
                <div style={{padding:'16px', background:'rgba(184,146,84,.06)', border:'1px solid rgba(184,146,84,.2)', borderRadius:4, textAlign:'center', marginBottom:20}}>
                  <div style={{fontSize:16, marginBottom:8}}>📱</div>
                  <div style={{textAlign:"center",padding:"20px 0"}}><button onClick={()=>window.print()} style={{background:"#c0392b",color:"#fff",border:"none",borderRadius:8,padding:"12px 28px",fontSize:15,cursor:"pointer",marginRight:12}}>保存PDF</button><button onClick={()=>{var el=document.querySelector(".modal-content,.result-wrap")||document.body;if(typeof html2canvas==="undefined"){var sc=document.createElement("script");sc.src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js";sc.onload=function(){html2canvas(el,{scale:2,backgroundColor:"#fffdf6"}).then(function(c){var a=document.createElement("a");a.download="体质报告.png";a.href=c.toDataURL();a.click();});};document.head.appendChild(sc);}else{html2canvas(el,{scale:2,backgroundColor:"#fffdf6"}).then(function(c){var a=document.createElement("a");a.download="体质报告.png";a.href=c.toDataURL();a.click();});}}} style={{background:"#2980b9",color:"#fff",border:"none",borderRadius:8,padding:"12px 28px",fontSize:15,cursor:"pointer"}}>保存图片</button></div>
                </div>

                {/* 操作按钮 */}
                <div style={{display:'flex', gap:10}}>
                  <button style={{width:'100%', padding:'12px', border:'1px solid var(--line)', background:'var(--bg-soft)', color:'var(--ink)', cursor:'pointer', fontFamily:'var(--sans)', fontSize:13, letterSpacing:2, borderRadius:2}}
                    onClick={reset}>重新分析</button>
                  <button style={{width:'100%', padding:'13px', border:'none', background:'var(--jade)', color:'#fff', cursor:'pointer', fontFamily:'var(--sans)', fontSize:14, letterSpacing:3, borderRadius:2, flex:1}}
                    onClick={onClose}>完成</button>
                </div>
              </div>
            )}
          </div>
        )}

      </div>
    </div>
  );
}

function Nav({ page, onSearch, onQuiz }) {
  const links = [
    { href: "#/", id: "home", label: "首 页" },
    { href: "#/constitution", id: "constitution", label: "体质调理" },
    { href: "#/terms", id: "terms", label: "节气养生" },
    { href: "#/symptoms", id: "symptoms", label: "症状调理" },
    { href: "#/population", id: "population", label: "人群养生" },
    { href: "#/recipes", id: "recipes", label: "药膳食疗" },
  ];
  return (
    <nav className="nav">
      <div className="nav-left">
        <a href="#/" style={{display:"flex",alignItems:"center",gap:14,textDecoration:"none",color:"inherit"}}>
          <img src="/logo-guqichun.png" alt="古柒春" style={{height:"44px",width:"auto",objectFit:"contain",display:"block"}} />
        </a>
      </div>
      <div className="nav-links">
        {links.map(l => (
          <a key={l.id} href={l.href} className={page === l.id ? "active" : ""}>{l.label}</a>
        ))}
      </div>
      <div className="nav-right">
        <div className="search-box" onClick={onSearch} style={{cursor:"pointer"}}>
          <Icon.search />
          <input placeholder="搜索 气血 / 失眠 / 山药…" readOnly style={{cursor:"pointer"}}/>
        </div>
      </div>
    </nav>
  );
}

// ============= Hero =============
function Hero({ onQuiz, onAI }) {
  return (
    <header className="hero" id="home" data-screen-label="01 首页">
      <div>
        <div className="hero-eyebrow">EST.丙午年 · 专业调理知识平台</div>
        <h1 className="serif">
          顺四时<br/>
          <span className="accent">调</span>百体
        </h1>
        <div className="hero-poem serif">
          "上工治未病，不治已病。"<br/>
          调身、调心、调息——以草木之性，养人之常。
          <span className="cite">—— 黄帝内经 · 素问</span>
        </div>
        <div className="hero-cta">
          <button className="btn btn-primary" onClick={onQuiz}>开始体质自测 <Icon.arrow /></button>
          <button className="btn" onClick={onAI}
            style={{background:"var(--vermillion)",color:"#fff",border:"none",letterSpacing:2,cursor:"pointer"}}>
            AI 拍照测体质
          </button>
          <button className="btn btn-ghost" onClick={() => window.scrollTo({top:600,behavior:"smooth"})}>浏览知识库</button>
        </div>
      </div>
      <SolarCard />
    </header>
  );
}

function SolarCard() {
  const JIEQI = [
    {name:'小寒',py:'Xiǎo Hán',s:'01-05',e:'01-19',season:'冬',sf:'冬·严寒',tune:'养肾御寒',tip:'早卧晚起，防寒保暖；宜食羊肉、核桃、黑芝麻；情志宜静，避免劳累。'},
    {name:'大寒',py:'Dà Hán',s:'01-20',e:'02-03',season:'冬',sf:'冬·极寒',tune:'温阳补肾',tip:'大寒宜进补，温阳固肾；多食姜、桂圆、红枣；避风寒，注意足部保暖。'},
    {name:'立春',py:'Lì Chūn',s:'02-04',e:'02-18',season:'春',sf:'初春·升发',tune:'疏肝养肝',tip:'宜晚睡早起，散步舒展；多食韭菜、香椿、豆芽；情志宜舒畅，忌郁怒。'},
    {name:'雨水',py:'Yǔ Shuǐ',s:'02-19',e:'03-05',season:'春',sf:'仲春·润泽',tune:'健脾祛湿',tip:'湿气渐重，健脾为要；宜食薏米、山药、红豆；注意保暖防湿，避免受寒。'},
    {name:'惊蛰',py:'Jīng Zhé',s:'03-06',e:'03-20',season:'春',sf:'仲春·生机',tune:'养肝护阳',tip:'万物复苏，肝气旺盛；宜食梨、枸杞、菠菜；保持心情平和，多户外运动。'},
    {name:'春分',py:'Chūn Fēn',s:'03-21',e:'04-04',season:'春',sf:'仲春·平衡',tune:'阴阳调和',tip:'春分阴阳各半，调和为要；宜食蜂蜜、百合、荠菜；保持作息规律。'},
    {name:'清明',py:'Qīng Míng',s:'04-05',e:'04-19',season:'春',sf:'暮春·清和',tune:'舒肝明目',tip:'清明宜踏青，舒展筋骨；宜食绿叶菜、菊花茶；情志宜舒畅，避免悲伤。'},
    {name:'谷雨',py:'Gǔ Yǔ',s:'04-20',e:'05-05',season:'春',sf:'暮春·滋润',tune:'祛湿健脾',tip:'谷雨湿气重，防湿健脾；宜食香椿、豆类、茯苓；避免淋雨，注意关节保暖。'},
    {name:'立夏',py:'Lì Xià',s:'05-06',e:'05-20',season:'夏',sf:'初夏·阳长',tune:'养心·健脾',tip:'宜早睡早起，午间小憩；饮食宜清淡苦凉，可食苦瓜、莲子、绿豆；情志保持平和，心静自然凉。'},
    {name:'小满',py:'Xiǎo Mǎn',s:'05-21',e:'06-05',season:'夏',sf:'仲夏·丰盈',tune:'清热·利湿',tip:'小满湿热渐重，清热利湿为要；宜食冬瓜、薏米、苦瓜；避免暴晒，注意防暑。'},
    {name:'芒种',py:'Máng Zhǒng',s:'06-06',e:'06-20',season:'夏',sf:'仲夏·炎热',tune:'解暑·养心',tip:'芒种高温多雨，养心护胃；宜食绿豆、荷叶、西瓜；保持心情平静，多饮水。'},
    {name:'夏至',py:'Xià Zhì',s:'06-21',e:'07-06',season:'夏',sf:'盛夏·极阳',tune:'清心·降火',tip:'夏至阳气最盛，清心降火；宜食百合、酸梅、莲子心；午休半小时，避免午后暴晒。'},
    {name:'小暑',py:'Xiǎo Shǔ',s:'07-07',e:'07-22',season:'夏',sf:'盛夏·暑热',tune:'养心·消暑',tip:'小暑炎热，注意防暑降温；宜食绿豆汤、银耳、荷叶粥；保持情绪稳定，适度运动。'},
    {name:'大暑',py:'Dà Shǔ',s:'07-23',e:'08-07',season:'夏',sf:'盛夏·酷热',tune:'清热·祛湿',tip:'大暑最热，清热祛湿最要紧；多食冬瓜、苦瓜、绿豆；忌贪凉过度，保护阳气。'},
    {name:'立秋',py:'Lì Qiū',s:'08-08',e:'08-22',season:'秋',sf:'初秋·收敛',tune:'润肺·养阴',tip:'立秋贴秋膘，温和进补；宜食莲藕、百合、梨；早睡早起，注意保暖防燥。'},
    {name:'处暑',py:'Chǔ Shǔ',s:'08-23',e:'09-07',season:'秋',sf:'初秋·凉爽',tune:'润燥·益气',tip:'处暑暑气渐退，滋阴润燥；宜食银耳、蜂蜜、芝麻；保持充足睡眠，情志平和。'},
    {name:'白露',py:'Bái Lù',s:'09-08',e:'09-22',season:'秋',sf:'仲秋·清凉',tune:'补肺·益气',tip:'白露天凉，防寒保暖；宜食山药、枸杞、银耳；忌食生冷，注意脚部保暖。'},
    {name:'秋分',py:'Qiū Fēn',s:'09-23',e:'10-07',season:'秋',sf:'仲秋·平分',tune:'滋阴·润燥',tip:'秋分阴阳平衡，润燥为要；宜食梨、藕、蜂蜜；保持乐观心态，适度锻炼。'},
    {name:'寒露',py:'Hán Lù',s:'10-08',e:'10-22',season:'秋',sf:'深秋·凉燥',tune:'养阴·防燥',tip:'寒露渐凉，滋阴防燥；宜食芝麻、核桃、红枣；注意足部保暖，早睡早起。'},
    {name:'霜降',py:'Shuāng Jiàng',s:'10-23',e:'11-06',season:'秋',sf:'深秋·肃杀',tune:'滋补·肝肾',tip:'霜降补冬，滋补肝肾；宜食栗子、山药、牛肉；注意关节保暖，避免受寒。'},
    {name:'立冬',py:'Lì Dōng',s:'11-07',e:'11-21',season:'冬',sf:'初冬·收藏',tune:'养肾·补阳',tip:'立冬进补，养肾固阳；宜食羊肉、黑豆、桂圆；早睡晚起，减少户外活动。'},
    {name:'小雪',py:'Xiǎo Xuě',s:'11-22',e:'12-06',season:'冬',sf:'仲冬·阴寒',tune:'温阳·益气',tip:'小雪阴寒，温阳补气；宜食腊肉、红薯、花生；保持温暖，情志宜平和愉悦。'},
    {name:'大雪',py:'Dà Xuě',s:'12-07',e:'12-21',season:'冬',sf:'仲冬·严寒',tune:'补肾·壮阳',tip:'大雪严寒，藏精固阳；宜食羊肉、核桃；注意保暖，避免受寒伤肾。'},
    {name:'冬至',py:'Dōng Zhì',s:'12-22',e:'01-04',season:'冬',sf:'深冬·极阴',tune:'温补·阳气',tip:'冬至阳生，温补为要；宜食羊肉汤、当归生姜；早睡晚起，注意腰腹保暖。'},
  ];
  const p2 = n => String(n).padStart(2,'0');
  const now = new Date();
  const md = p2(now.getMonth()+1)+'-'+p2(now.getDate());
  const term = JIEQI.find(j => j.s<=j.e ? (md>=j.s&&md<=j.e) : (md>=j.s||md<=j.e)) || JIEQI[9];
  const dateStr = (now.getMonth()+1)+'月'+now.getDate()+'日';
  const sm = parseInt(term.s.split('-')[0]), sd = parseInt(term.s.split('-')[1]);
  const em = parseInt(term.e.split('-')[0]), ed = parseInt(term.e.split('-')[1]);
  return (
    <aside className="solar-card">
      <div className="solar-head">
        <div className="label">今日节气 · TODAY</div>
        <div className="date">{dateStr}</div>
      </div>
      <div className="solar-name serif">
        {term.name}<span className="py">{term.py}</span>
      </div>
      <div className="solar-meta">
        <div>时段<strong>{sm}/{sd} — {em}/{ed}</strong></div>
        <div>主季<strong>{term.sf}</strong></div>
        <div>调理<strong>{term.tune}</strong></div>
      </div>
      <div className="solar-tip">
        <span className="k">{term.name}养生 · </span>
        {term.tip}
      </div>
    </aside>
  );
}

// ============= Five Pillars =============
const PILLARS = [
  {
    id: "constitution", page: "constitution", num: "壹", title: "体质调理", sub: "CONSTITUTION", icon: "body",
    items: ["9 种体质分类", "气虚 · 阳虚 · 阴虚", "针对性调理方案", "体质自测量表"],
    cta: "9 种体质",
  },
  {
    id: "term", page: "terms", num: "贰", title: "节气养生", sub: "SOLAR TERMS", icon: "bowl",
    items: ["24 节气养生指南", "春生 · 夏长", "秋收 · 冬藏", "顺时调理节奏"],
    cta: "24 个节气",
  },
  {
    id: "symptom", page: "symptoms", num: "叁", title: "症状调理", sub: "SYMPTOMS", icon: "symptom",
    items: ["睡眠：失眠多梦", "消化：胃胀便秘", "皮肤：湿疹痘痘", "对症方案 60+"],
    cta: "60+ 方案",
  },
  {
    id: "population", page: "population", num: "肆", title: "人群养生", sub: "POPULATION", icon: "people",
    items: ["女性：气血妇科", "男性：补肾减压", "老人：慢病管理", "儿童：成长免疫"],
    cta: "4 类人群",
  },
  {
    id: "recipe", page: "recipes", num: "伍", title: "药膳食疗", sub: "HERBAL RECIPES", icon: "herb",
    items: ["养生茶饮选粹", "汤品：四神 八珍", "粥品：山药 红枣", "200+ 食疗方"],
    cta: "200+ 食疗",
  },
];

function Pillars() {
  return (
    <section className="section" id="pillars" data-screen-label="02 五大知识板块">
      <div className="section-head">
        <h2 className="section-title">
          <span className="num">— 知识库结构 / 01 —</span>
          知识库结构
        </h2>
        <div className="section-sub">五大体系 · 系统调理 · 一脉相承</div>
      </div>
      <div className="pillars">
        {PILLARS.map(p => {
          const I = Icon[p.icon];
          return (
            <a
              key={p.id}
              href={`#/${p.page}`}
              className="pillar"
              style={{textDecoration:"none",color:"inherit",display:"flex",flexDirection:"column"}}
            >
              <div className="pillar-num">
                <span>{p.num} · {p.sub.slice(0,3)}</span>
                <span className="arrow">→</span>
              </div>
              <div className="pillar-icon"><I /></div>
              <h3 className="pillar-title">{p.title}</h3>
              <div className="pillar-sub">{p.sub}</div>
              <ul className="pillar-items">
                {p.items.map((it, i) => <li key={i}>{it}</li>)}
              </ul>
              <div className="pillar-cta">
                <span>{p.cta}</span>
                <span>进入 →</span>
              </div>
            </a>
          );
        })}
      </div>
    </section>
  );
}

// ============= Constitution Detail Panel =============
function ConstitutionDetail() {
  const [idx, setIdx] = useState(0);
  const c = CONSTITUTIONS[idx];
  return (
    <section className="section" data-screen-label="03 体质调理详情">
      <div className="section-head">
        <h2 className="section-title">
          <span className="num">— 板块详情 / 壹 —</span>
          九种体质 · 针对调理
        </h2>
        <div className="section-sub">中医九分法 · 知体质方知调养</div>
      </div>
      <div className="detail">
        <div className="detail-side">
          <div className="detail-side-head">
            <h3>体质分类</h3>
            <p>BODY CONSTITUTION TYPES</p>
          </div>
          <ul className="detail-list">
            {CONSTITUTIONS.map((it, i) => (
              <li
                key={it.id}
                className={i === idx ? "active" : ""}
                onClick={() => setIdx(i)}
              >
                <span><span style={{color:"var(--ink-mute)", marginRight:8, fontFamily:"var(--serif)"}}>0{i+1}</span>{it.name}</span>
                <span className="tag">{it.tag}</span>
              </li>
            ))}
          </ul>
        </div>
        <div className="detail-main">
          <div className="detail-main-head">
            <div>
              <div className="label">CONSTITUTION · 0{idx+1}</div>
              <h2>{c.name}</h2>
              <div className="h-en">{c.en}</div>
            </div>
            <div className="detail-pill">{c.tag}</div>
          </div>
          <div className="symptom-row">
            <div><span className="k">主症</span>{c.sign}</div>
            <div><span className="k">舌脉</span>{c.desc}</div>
          </div>
          <div className="detail-grid">
            <div className="detail-block">
              <h4>成因 · CAUSE</h4>
              <p>{c.cause}</p>
            </div>
            <div className="detail-block">
              <h4>调理建议 · ADVICE</h4>
              <ul>
                {c.advice.map((a, i) => <li key={i}>{a}</li>)}
              </ul>
            </div>
            <div className="detail-block" style={{gridColumn:"1 / -1"}}>
              <h4>常用本草 · HERBS</h4>
              <div className="herb-chips">
                {c.herbs.map(h => <span key={h} className="herb-chip">{h}</span>)}
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

// ============= Solar Terms Wheel =============
function SolarTermsWheel() {
  const [sel, setSel] = useState(0);
  // 动态设置当前节气（等 SOLAR_TERMS 加载后计算）
  useEffect(() => {
    const terms = window.SOLAR_TERMS;
    if (!terms || !terms.length) return;
    const now = new Date();
    const mm = now.getMonth() + 1;
    const dd = now.getDate();
    const adj = m => m >= 2 ? m : m + 12;
    const todayAdj = adj(mm) * 100 + dd;
    let best = terms.length - 1;
    for (let i = 0; i < terms.length; i++) {
      const parts = terms[i].date.split('/');
      const termAdj = adj(parseInt(parts[0])) * 100 + parseInt(parts[1]);
      if (termAdj <= todayAdj) best = i;
    }
    const fp = terms[0].date.split('/');
    if (todayAdj < adj(parseInt(fp[0])) * 100 + parseInt(fp[1])) best = terms.length - 1;
    setSel(best);
  }, []);
  const [termData, setTermData] = useState([]);

  useEffect(() => {
    fetch(`${API}/solar-terms`).then(r => r.json()).then(setTermData).catch(() => {});
  }, []);

  const terms = termData.length > 0 ? termData : SOLAR_TERMS;
  const cur = terms[sel] || SOLAR_TERMS[sel];
  const detail = cur;
  const cx = 210, cy = 210, r = 165;
  const seasonColor = { 春: "#7EA37A", 夏: "#C25A4A", 秋: "#B89254", 冬: "#5F7C8F" };
  return (
    <section className="section" id="terms" data-screen-label="04 节气养生">
      <div className="section-head">
        <h2 className="section-title">
          <span className="num">— 板块详情 / 贰 —</span>
          二十四节气 · 顺时养生
        </h2>
        <div className="section-sub">春生 · 夏长 · 秋收 · 冬藏</div>
      </div>
      <div className="terms-wrap">
        <div className="terms-wheel">
          <svg viewBox="0 0 420 420" style={{overflow:"visible"}}>
            {/* outer ring */}
            <circle cx={cx} cy={cy} r={r+30} fill="none" stroke="#D8CCB0" strokeWidth="1" />
            <circle cx={cx} cy={cy} r={r-30} fill="none" stroke="#D8CCB0" strokeWidth="1" strokeDasharray="2 3" />
            {/* season arcs */}
            {[0,1,2,3].map(s => {
              const seasons = ["春","夏","秋","冬"];
              const start = s * 6 * 15 - 90;
              const end = (s + 1) * 6 * 15 - 90;
              const x1 = cx + (r+30) * Math.cos(start * Math.PI/180);
              const y1 = cy + (r+30) * Math.sin(start * Math.PI/180);
              const x2 = cx + (r+30) * Math.cos(end * Math.PI/180);
              const y2 = cy + (r+30) * Math.sin(end * Math.PI/180);
              const mid = (start + end) / 2;
              const tx = cx + (r+55) * Math.cos(mid * Math.PI/180);
              const ty = cy + (r+55) * Math.sin(mid * Math.PI/180);
              return (
                <g key={s}>
                  <path
                    d={`M ${x1} ${y1} A ${r+30} ${r+30} 0 0 1 ${x2} ${y2}`}
                    fill="none"
                    stroke={seasonColor[seasons[s]]}
                    strokeWidth="3"
                    opacity={0.45}
                  />
                  <text x={tx} y={ty} textAnchor="middle" dominantBaseline="middle"
                    style={{fontFamily:"var(--serif)", fontSize:"14px", letterSpacing:"4px", fill: seasonColor[seasons[s]]}}>
                    {seasons[s]}
                  </text>
                </g>
              );
            })}
            {/* 24 ticks */}
            {terms.map((t, i) => {
              const angle = (i * 15 - 90) * Math.PI / 180;
              const x = cx + r * Math.cos(angle);
              const y = cy + r * Math.sin(angle);
              const isActive = i === sel;
              const c = seasonColor[t.season];
              return (
                <g key={i} onClick={() => setSel(i)} style={{cursor:"pointer"}} className="wheel-node">
                  <title>{t.name}</title>
                  <circle cx={x} cy={y} r={isActive ? 18 : 8}
                    fill={isActive ? c : "#FBF6EA"}
                    stroke={c}
                    strokeWidth={isActive ? 0 : 1.2}
                  />
                  <text
                  x={210 + (x-210)*1.22}
                  y={210 + (y-210)*1.22}
                  textAnchor={(x-210) > 15 ? "start" : (x-210) < -15 ? "end" : "middle"}
                  dominantBaseline="central"
                  style={{
                    fontFamily:"var(--serif)",
                    fontSize: isActive ? "12px" : "10px",
                    fill: isActive ? c : "#7A6B55",
                    fontWeight: isActive ? 700 : 400,
                    letterSpacing:"0.5px",
                    pointerEvents:"none"
                  }}>{t.name}</text>
                </g>
              );
            })}
          </svg>
          <div className="terms-wheel-center">
            
            <div className="name serif">{cur.name}</div>
            <div className="date">{cur.py} · {cur.date}</div>
            <div className="season" style={{background: seasonColor[cur.season]}}>
              {cur.season}季
            </div>
          </div>
        </div>
        <div className="terms-info">
          <span className="terms-tag">{cur.season}季 · 第 {sel+1} 节</span>
          <h3 className="serif">{cur.name} · {detail.tone || ""}</h3>
          <p className="serif" style={{color:"var(--ink-3)", fontStyle:"italic", marginTop:0}}>"{detail.poem || ""}"</p>
          <p>{detail.desc || ""}</p>
          <div className="terms-advice">
            {(detail.advice || []).map((a, i) => (
              <div className="item" key={i}>
                <div className="k">◆ {a.k}调养</div>
                <div className="v">{a.v}</div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </section>
  );
}

// ============= Symptom Remedy Modal =============
function SymptomModal({ symptom, onClose }) {
  const [data, setData] = useState(null);
  const [activeTab, setActiveTab] = useState("herbs");
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    if (!symptom) return;
    setLoading(true);
    fetch(`${API}/symptoms/remedy/${encodeURIComponent(symptom)}`)
      .then(r => r.json())
      .then(d => { setData(d); setLoading(false); })
      .catch(() => setLoading(false));
  }, [symptom]);

  if (!symptom) return null;
  const s = { padding:"10px 16px", borderBottom:"1px solid rgba(214,180,122,.2)", fontSize:13, lineHeight:1.8 };

  return (
    <div style={{position:"fixed",inset:0,zIndex:1000,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(31,26,18,.65)",backdropFilter:"blur(4px)"}}
      onClick={onClose}>
      <div style={{width:"min(600px,94vw)",maxHeight:"88vh",overflowY:"auto",background:"var(--bg-card)",border:"1px solid var(--line)",boxShadow:"0 24px 60px rgba(0,0,0,.3)"}}
        onClick={e => e.stopPropagation()}>
        <div style={{padding:"20px 28px",borderBottom:"1px solid var(--line)",display:"flex",justifyContent:"space-between",alignItems:"center",background:"var(--jade)"}}>
          <div>
            <div style={{fontSize:11,letterSpacing:4,color:"rgba(255,255,255,.6)"}}>症状调理方案</div>
            <div style={{fontFamily:"var(--serif)",fontSize:22,letterSpacing:4,color:"#fff",marginTop:4}}>{symptom}</div>
          </div>
          <button onClick={onClose} style={{background:"rgba(255,255,255,.15)",border:"none",cursor:"pointer",fontSize:18,color:"#fff",width:32,height:32,borderRadius:"50%"}}>✕</button>
        </div>

        {loading && <div style={{padding:48,textAlign:"center",color:"var(--ink-3)"}}>加载中…</div>}
        {!loading && !data && <div style={{padding:48,textAlign:"center",color:"var(--ink-3)"}}>暂无该症状的详细方案，请咨询中医师。</div>}

        {!loading && data && (
          <div style={{padding:"24px 28px"}}>
            <div style={{background:"rgba(44,74,59,.06)",borderLeft:"3px solid var(--jade)",padding:"12px 16px",marginBottom:20,fontSize:13,color:"var(--ink-2)"}}>
              <span style={{color:"var(--jade)",fontFamily:"var(--serif)",marginRight:8,fontSize:14}}>病因</span>{data.cause}
            </div>
            <div style={{background:"rgba(44,74,59,.06)",borderLeft:"3px solid var(--gold)",padding:"12px 16px",marginBottom:20,fontSize:13,color:"var(--ink-2)"}}>
              <span style={{color:"var(--gold)",fontFamily:"var(--serif)",marginRight:8,fontSize:14}}>常见体质</span>{data.constitution}
            </div>

            <div style={{marginBottom:20}}>
              <div style={{fontFamily:"var(--serif)",fontSize:15,letterSpacing:3,marginBottom:12,color:"var(--ink)",display:"flex",alignItems:"center",gap:8}}>
                <span style={{width:3,height:14,background:"var(--vermillion)",display:"inline-block"}}></span>常用本草
              </div>
              <div style={{display:"flex",flexWrap:"wrap",gap:8}}>
                {data.herbs.map(h => <span key={h} style={{padding:"5px 12px",background:"rgba(184,146,84,.12)",border:"1px solid rgba(184,146,84,.3)",fontFamily:"var(--serif)",fontSize:13,letterSpacing:2}}>{h}</span>)}
              </div>
            </div>

            <div style={{marginBottom:20}}>
              <div style={{fontFamily:"var(--serif)",fontSize:15,letterSpacing:3,marginBottom:12,color:"var(--ink)",display:"flex",alignItems:"center",gap:8}}>
                <span style={{width:3,height:14,background:"var(--jade)",display:"inline-block"}}></span>食疗调理
              </div>
              <div style={{display:"flex",flexWrap:"wrap",gap:8}}>
                {data.foods.map(f => <span key={f} style={{padding:"5px 12px",background:"rgba(44,74,59,.08)",border:"1px solid rgba(44,74,59,.2)",fontSize:13,letterSpacing:1}}>{f}</span>)}
              </div>
            </div>

            <div style={{marginBottom:20}}>
              <div style={{fontFamily:"var(--serif)",fontSize:15,letterSpacing:3,marginBottom:12,color:"var(--ink)",display:"flex",alignItems:"center",gap:8}}>
                <span style={{width:3,height:14,background:"var(--jade)",display:"inline-block"}}></span>穴位按摩
              </div>
              {data.acupoints.map((ap, i) => (
                <div key={i} style={s}>
                  <span style={{color:"var(--vermillion)",marginRight:6}}>◆</span>{ap}
                </div>
              ))}
            </div>

            <div>
              <div style={{fontFamily:"var(--serif)",fontSize:15,letterSpacing:3,marginBottom:12,color:"var(--ink)",display:"flex",alignItems:"center",gap:8}}>
                <span style={{width:3,height:14,background:"var(--jade)",display:"inline-block"}}></span>生活调养
              </div>
              <div style={{fontSize:13,lineHeight:2,color:"var(--ink-2)",padding:"12px 16px",background:"rgba(44,74,59,.04)",borderLeft:"2px solid var(--jade-3,#6E8E78)"}}>{data.lifestyle}</div>
            </div>
            {/* Tab5 */}
            {activeTab === 5 && (
              <div>
                <div style={{fontFamily:'var(--serif)',fontSize:15,letterSpacing:3,color:'var(--jade)',marginBottom:8}}>{'🌿 五运六气健康预测 2026-2035'}</div>
                <div style={{fontSize:12,color:'var(--ink-3)',letterSpacing:1,lineHeight:1.8,marginBottom:16}}>{'根据中医五运六气理论，结合体质特点，预测未来十年五脏健康趋势。'}</div>
                {(function(){
                  var data=[{y:2026,gz:'丙午',yun:'水运太过',risk:[0,2,0,1,1],tip:'防寒护肾，心血管保养'},{y:2027,gz:'丁未',yun:'木运不及',risk:[2,0,1,1,0],tip:'疏肝理气，防秋燥伤肺'},{y:2028,gz:'戊申',yun:'火运太过',risk:[1,1,0,2,0],tip:'清心降火，润肺防燥'},{y:2029,gz:'己酉',yun:'土运不及',risk:[1,0,2,0,1],tip:'健脾化湿，调节饮食'},{y:2030,gz:'庚戌',yun:'金运太过',risk:[2,0,1,1,0],tip:'柔肝养血，防金克木'},{y:2031,gz:'辛亥',yun:'水运不及',risk:[0,1,1,0,2],tip:'补肾纳气，防冬寒'},{y:2032,gz:'壬子',yun:'木运太过',risk:[1,0,2,0,1],tip:'顾护脾胃，防肝旺克脾'},{y:2033,gz:'癸丑',yun:'火运不及',risk:[1,2,0,1,0],tip:'温养心阳，防冬季抑郁'},{y:2034,gz:'甲寅',yun:'土运太过',risk:[0,1,1,0,2],tip:'健脾利水，防土旺克肾'},{y:2035,gz:'乙卯',yun:'木运不及',risk:[1,0,0,2,0],tip:'养肺润燥，防春燥'}];
                  var c=['#4caf50','#ff9800','#e53935'],lb=['平稳','留意','重点防护'],og=['肝','心','脾','肺','肾'],ny=new Date().getFullYear();
                  return <div>{data.map(function(d){var n=d.y===ny;return(<div key={d.y} style={{display:'flex',alignItems:'center',gap:6,padding:'8px 10px',background:n?'rgba(184,146,84,.12)':'transparent',borderBottom:'1px solid var(--line)',borderLeft:n?'3px solid var(--gold)':'3px solid transparent'}}><div style={{width:40,fontFamily:'var(--serif)',fontSize:13,color:n?'var(--gold)':'var(--ink)',flexShrink:0}}>{n?'▶':''}{d.y}</div><div style={{width:64,fontSize:11,color:'var(--ink-2)',flexShrink:0,lineHeight:1.4}}>{d.gz+' '+d.yun}</div><div style={{display:'flex',gap:3,flexShrink:0}}>{d.risk.map(function(r,i){return <div key={i} title={og[i]+':'+lb[r]} style={{width:14,height:14,borderRadius:'50%',background:c[r]}} />;})}</div><div style={{flex:1,fontSize:11,color:'var(--ink-3)'}}>{d.tip}</div></div>);})}</div>;
                })()}
                <div style={{marginTop:10,fontSize:11,color:'var(--ink-3)'}}>{'圆点: 肝·心·脾·肺·肾  ●平稳 ●留意 ●重点防护'}</div>
              </div>
            )}
          </div>
        )}
      </div>
    </div>
  );
}

// ============= Symptom Strip =============
function SymptomStrip() {
  const [selSymptom, setSelSymptom] = useState(null);
  const [symptoms, setSymptoms] = useState(SYMPTOMS);

  useEffect(() => {
    fetch(`${API}/symptoms`).then(r => r.json()).then(setSymptoms).catch(() => {});
  }, []);

  return (
    <section className="section" id="sym" data-screen-label="05 症状调理">
      <SymptomModal symptom={selSymptom} onClose={() => setSelSymptom(null)} />
      <div className="section-head">
        <h2 className="section-title">
          <span className="num">— 板块详情 / 叁 —</span>
          对症调理 · 一症一方
        </h2>
        <div className="section-sub">点选症状 · 直达调理方案</div>
      </div>
      <div className="symstrip">
        <div className="symstrip-head">
          <h2>从<span className="gold">症状</span>出发<br/>找到你的调理路径</h2>
          <p className="lead">"症"是结果，"调"在根本。<br/>点击症状查看详细调理方案。</p>
        </div>
        <div className="symgrid">
          {symptoms.map(s => (
            <div className="symcat" key={s.cat}>
              <h4>{s.cat}</h4>
              <span className="en">{s.en}</span>
              <div className="symcat-items">
                {s.items.map(it => (
                  <span key={it} onClick={() => setSelSymptom(it)}
                    title="点击查看调理方案" style={{cursor:"pointer"}}>{it}</span>
                ))}
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

// ============= Population Detail Modal =============
function PopulationModal({ pop, onClose }) {
  if (!pop || !pop.detail) return null;
  const d = pop.detail;
  return (
    <div style={{position:"fixed",inset:0,zIndex:1000,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(31,26,18,.65)",backdropFilter:"blur(4px)"}}
      onClick={onClose}>
      <div style={{width:"min(640px,94vw)",maxHeight:"88vh",overflowY:"auto",background:"var(--bg-card)",border:"1px solid var(--line)",boxShadow:"0 24px 60px rgba(0,0,0,.3)"}}
        onClick={e => e.stopPropagation()}>
        <div style={{padding:"20px 28px",borderBottom:"1px solid var(--line)",display:"flex",justifyContent:"space-between",alignItems:"center",background:"var(--jade)"}}>
          <div>
            <div style={{fontSize:11,letterSpacing:4,color:"rgba(255,255,255,.6)"}}>{pop.en} · {pop.focus}</div>
            <div style={{fontFamily:"var(--serif)",fontSize:24,letterSpacing:4,color:"#fff",marginTop:4}}>{pop.name}</div>
          </div>
          <button onClick={onClose} style={{background:"rgba(255,255,255,.15)",border:"none",cursor:"pointer",fontSize:18,color:"#fff",width:32,height:32,borderRadius:"50%"}}>✕</button>
        </div>
        <div style={{padding:"24px 28px"}}>
          <p style={{fontSize:14,lineHeight:2,color:"var(--ink-2)",marginBottom:24,borderLeft:"2px solid var(--jade)",paddingLeft:14}}>{d.desc}</p>

          {d.periods && d.periods.map((p, i) => (
            <div key={i} style={{marginBottom:20,padding:"16px 20px",background:"rgba(44,74,59,.04)",border:"1px solid var(--line-soft)"}}>
              <div style={{fontFamily:"var(--serif)",fontSize:15,letterSpacing:3,color:"var(--jade)",marginBottom:10,display:"flex",alignItems:"center",gap:8}}>
                <span style={{width:3,height:14,background:"var(--vermillion)",display:"inline-block"}}></span>{p.title}
              </div>
              <p style={{fontSize:13,lineHeight:2,color:"var(--ink-2)",margin:0}}>{p.content}</p>
            </div>
          ))}

          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:16,marginTop:20}}>
            <div>
              <div style={{fontFamily:"var(--serif)",fontSize:14,letterSpacing:2,marginBottom:10,color:"var(--ink)"}}>常用本草</div>
              <div style={{display:"flex",flexWrap:"wrap",gap:6}}>
                {d.herbs && d.herbs.map(h => <span key={h} style={{padding:"4px 10px",background:"rgba(184,146,84,.12)",border:"1px solid rgba(184,146,84,.3)",fontFamily:"var(--serif)",fontSize:12,letterSpacing:2}}>{h}</span>)}
              </div>
            </div>
            <div>
              <div style={{fontFamily:"var(--serif)",fontSize:14,letterSpacing:2,marginBottom:10,color:"var(--ink)"}}>推荐食物</div>
              <div style={{display:"flex",flexWrap:"wrap",gap:6}}>
                {d.foods && d.foods.map(f => <span key={f} style={{padding:"4px 10px",background:"rgba(44,74,59,.08)",border:"1px solid rgba(44,74,59,.2)",fontSize:12,letterSpacing:1}}>{f}</span>)}
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

// ============= Population =============
function Population() {
  const [selPop, setSelPop] = useState(null);
  const [populations, setPopulations] = useState(POPULATIONS);

  useEffect(() => {
    fetch(`${API}/populations`).then(r => r.json()).then(setPopulations).catch(() => {});
  }, []);

  return (
    <section className="section" id="pop" data-screen-label="06 人群养生">
      <PopulationModal pop={selPop} onClose={() => setSelPop(null)} />
      <div className="section-head">
        <h2 className="section-title">
          <span className="num">— 板块详情 / 肆 —</span>
          四类人群 · 因人调养
        </h2>
        <div className="section-sub">不同体征 · 不同侧重 · 点击查看详情</div>
      </div>
      <div className="popgroup">
        {populations.map((p) => (
          <div className="popcard" key={p.name} onClick={() => setSelPop(p)}
            style={{cursor:"pointer"}}>
            <span className="big serif">{p.big}</span>
            <h4 className="serif">{p.name}</h4>
            <span className="en">{p.en} · {p.focus}</span>
            <ul>
              {p.items.map((it, j) => (
                <li key={j}><span>{it.k}</span><span className="v">{it.v}</span></li>
              ))}
            </ul>
            <div style={{marginTop:16,fontSize:12,color:"var(--jade)",letterSpacing:2,fontFamily:"var(--serif)"}}>点击查看详细方案 →</div>
          </div>
        ))}
      </div>
    </section>
  );
}

// ============= Recipes =============
function RecipeIllustration({ color, name }) {
  // simple ink-style svg illustration of a bowl
  return (
    <svg width="120" height="120" viewBox="0 0 120 120">
      <defs>
        <radialGradient id={`g-${name}`} cx="50%" cy="40%" r="60%">
          <stop offset="0%" stopColor={color} stopOpacity="0.9" />
          <stop offset="100%" stopColor={color} stopOpacity="0.5" />
        </radialGradient>
      </defs>
      {/* bowl liquid */}
      <ellipse cx="60" cy="65" rx="36" ry="6" fill={`url(#g-${name})`} opacity="0.85" />
      {/* bowl */}
      <path d="M22 62 Q22 95 60 98 Q98 95 98 62 Z" fill="none" stroke="#1F1A12" strokeWidth="1.6" />
      <path d="M22 62 H98" stroke="#1F1A12" strokeWidth="1.6" fill="none" />
      {/* steam */}
      <path d="M48 50 Q44 42 50 36 Q54 30 48 22" fill="none" stroke="#7A6E5A" strokeWidth="1.2" opacity="0.55" />
      <path d="M62 48 Q58 40 64 34 Q68 28 62 20" fill="none" stroke="#7A6E5A" strokeWidth="1.2" opacity="0.55" />
      <path d="M74 50 Q70 44 76 38 Q80 32 74 26" fill="none" stroke="#7A6E5A" strokeWidth="1.2" opacity="0.55" />
      {/* garnish dots */}
      <circle cx="55" cy="63" r="2.5" fill={color} opacity="0.9" />
      <circle cx="66" cy="61" r="2" fill={color} opacity="0.7" />
      <circle cx="48" cy="66" r="1.8" fill={color} opacity="0.6" />
    </svg>
  );
}

// ============= Recipe Detail Modal =============
function RecipeModal({ recipe, onClose }) {
  if (!recipe) return null;
  return (
    <div style={{position:"fixed",inset:0,zIndex:1000,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(31,26,18,.65)",backdropFilter:"blur(4px)"}}
      onClick={onClose}>
      <div style={{width:"min(580px,94vw)",maxHeight:"90vh",overflowY:"auto",background:"var(--bg-card)",border:"1px solid var(--line)",boxShadow:"0 24px 60px rgba(0,0,0,.3)"}}
        onClick={e => e.stopPropagation()}>
        <div style={{height:160,background:`linear-gradient(135deg, ${recipe.color}30, ${recipe.color}55)`,position:"relative",display:"grid",placeItems:"center"}}>
          <span style={{position:"absolute",top:14,left:14,padding:"4px 10px",background:"rgba(31,26,18,.7)",color:"var(--bg-card)",fontSize:11,letterSpacing:3,fontFamily:"var(--serif)"}}>{recipe.cat}</span>
          <button onClick={onClose} style={{position:"absolute",top:14,right:14,background:"rgba(31,26,18,.4)",border:"none",cursor:"pointer",fontSize:18,color:"#fff",width:32,height:32,borderRadius:"50%"}}>✕</button>
          <RecipeIllustration color={recipe.color} name={recipe.name} />
        </div>
        <div style={{padding:"24px 28px"}}>
          <div style={{fontSize:11,letterSpacing:4,color:"var(--ink-3)",marginBottom:4}}>{recipe.alt}</div>
          <h2 style={{fontFamily:"var(--serif)",fontSize:28,letterSpacing:4,margin:"0 0 6px",color:"var(--ink)"}}>{recipe.name}</h2>
          <div style={{fontSize:13,color:"var(--vermillion)",letterSpacing:2,fontFamily:"var(--serif)",marginBottom:16}}>{recipe.fn}</div>
          <p style={{fontSize:14,lineHeight:2,color:"var(--ink-2)",marginBottom:16}}>{recipe.desc}</p>

          <div style={{display:"flex",flexWrap:"wrap",gap:10,marginBottom:24,paddingBottom:20,borderBottom:"1px dashed var(--line)"}}>
            {recipe.meta && recipe.meta.map((m, j) => (
              <span key={j} style={{display:"flex",alignItems:"center",gap:4,fontSize:12,color:"var(--ink-3)"}}>
                <span style={{width:4,height:4,background:"var(--vermillion)",borderRadius:"50%",display:"inline-block"}}></span>{m}
              </span>
            ))}
          </div>

          {recipe.ingredients && recipe.ingredients.length > 0 && (
            <div style={{marginBottom:24}}>
              <div style={{fontFamily:"var(--serif)",fontSize:15,letterSpacing:3,marginBottom:12,color:"var(--ink)",display:"flex",alignItems:"center",gap:8}}>
                <span style={{width:3,height:14,background:"var(--vermillion)",display:"inline-block"}}></span>食材清单
              </div>
              <div style={{display:"flex",flexWrap:"wrap",gap:8}}>
                {recipe.ingredients.map((ing, i) => (
                  <span key={i} style={{padding:"6px 12px",background:"rgba(184,146,84,.1)",border:"1px solid rgba(184,146,84,.25)",fontSize:13,letterSpacing:1}}>{ing}</span>
                ))}
              </div>
            </div>
          )}

          {recipe.steps && recipe.steps.length > 0 && (
            <div>
              <div style={{fontFamily:"var(--serif)",fontSize:15,letterSpacing:3,marginBottom:12,color:"var(--ink)",display:"flex",alignItems:"center",gap:8}}>
                <span style={{width:3,height:14,background:"var(--jade)",display:"inline-block"}}></span>制作步骤
              </div>
              {recipe.steps.map((step, i) => (
                <div key={i} style={{display:"flex",gap:14,marginBottom:12,paddingBottom:12,borderBottom:"1px dashed var(--line-soft)"}}>
                  <div style={{flexShrink:0,width:24,height:24,background:"var(--jade)",color:"#fff",display:"grid",placeItems:"center",fontSize:12,fontFamily:"var(--serif)"}}>{i+1}</div>
                  <p style={{margin:0,fontSize:13,lineHeight:1.9,color:"var(--ink-2)"}}>{step}</p>
                </div>
              ))}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

function Recipes() {
  const [selRecipe, setSelRecipe] = useState(null);
  const [recipes, setRecipes] = useState(RECIPES);
  const [filter, setFilter] = useState("全部");
  const cats = ["全部", "茶饮", "汤品", "粥品"];

  useEffect(() => {
    fetch(`${API}/recipes`).then(r => r.json()).then(setRecipes).catch(() => {});
  }, []);

  const filtered = filter === "全部" ? recipes : recipes.filter(r => r.cat === filter);

  return (
    <section className="section" id="recipes" data-screen-label="07 药膳食疗">
      <RecipeModal recipe={selRecipe} onClose={() => setSelRecipe(null)} />
      <div className="section-head">
        <h2 className="section-title">
          <span className="num">— 板块详情 / 伍 —</span>
          药膳食疗 · 食养精选
        </h2>
        <div className="section-sub">茶饮 · 汤品 · 粥品 · 不时不食</div>
      </div>

      <div style={{display:"flex",gap:8,marginBottom:28}}>
        {cats.map(c => (
          <button key={c} onClick={() => setFilter(c)}
            style={{padding:"6px 18px",border:`1px solid ${filter===c?"var(--jade)":"var(--line)"}`,background:filter===c?"var(--jade)":"transparent",color:filter===c?"#fff":"var(--ink-2)",fontSize:13,letterSpacing:2,cursor:"pointer",fontFamily:"inherit",transition:"all .15s"}}>
            {c}
          </button>
        ))}
      </div>

      <div className="recipes">
        {filtered.map((r) => (
          <article className="recipe" key={r.name} onClick={() => setSelRecipe(r)} style={{cursor:"pointer"}}>
            <div className="recipe-img" style={{background: `linear-gradient(135deg, ${r.color}18, ${r.color}30)`}}>
              <span className="recipe-tag">{r.cat}</span>
              <RecipeIllustration color={r.color} name={r.name} />
            </div>
            <div className="recipe-body">
              <h4>{r.name}</h4>
              <div className="alt">{r.alt}</div>
              <div style={{fontSize:13,color:"var(--vermillion)",letterSpacing:2,marginBottom:10,fontFamily:"var(--serif)"}}>{r.fn}</div>
              <p>{r.desc}</p>
              <div className="recipe-meta">
                {r.meta && r.meta.map((m, j) => (
                  <span className="m" key={j}><span className="dot"></span>{m}</span>
                ))}
              </div>
              <div style={{marginTop:12,fontSize:12,color:"var(--jade)",letterSpacing:2}}>点击查看食材与做法 →</div>
            </div>
          </article>
        ))}
      </div>
    </section>
  );
}

// ============= Footer =============
function Footer() {
  return (
    <footer className="footer">
      <div className="footer-grid">
        <div className="footer-brand">
          <div style={{display:"flex", alignItems:"center", gap:12}}>
            <img src="/logo-guqichun.png" alt="古柒春" style={{height:"36px",width:"auto",objectFit:"contain"}} />
          </div>
          <p>以中医传统智慧为根，以现代调理科学为用。专注养生调理，小而精，与君共养。</p>
        </div>
        <div>
          <h5>知识库</h5>
          <ul>
            <li><a href="#/constitution">体质调理</a></li>
            <li><a href="#/terms">节气养生</a></li>
            <li><a href="#/symptoms">症状调理</a></li>
            <li><a href="#/population">人群养生</a></li>
            <li><a href="#/recipes">药膳食疗</a></li>
          </ul>
        </div>
        <div>
          <h5>专业工具</h5>
          <ul>
            <li><a href="#/constitution">九型体质自测</a></li>
            <li><a href="#/terms">节气提醒订阅</a></li>
            <li><a href="#/herbs">本草查询</a></li>
            <li><a href="#/formulas">方剂溯源</a></li>
          </ul>
        </div>
        <div>
          <h5>关于</h5>
          <ul>
            <li><a href="#/about">关于古柒春</a></li>
            <li><a href="#/team">编辑团队</a></li>
            <li><a href="#/advisors">专家顾问</a></li>
            <li><a href="#/cooperation">合作咨询</a></li>
          </ul>
        </div>
      </div>
      <div className="footer-bottom">
        <span>© 古柒春 · 养生调理知识库</span>
        <span>本平台内容仅供养生参考 · 疾病请遵医嘱</span>
      </div>
    </footer>
  );
}

// ============= Mobile Bottom Nav =============
function MobileBottomNav({ page }) {
  const items = [
    { id: "home",         href: "#/",            icon: "home",    label: "首页" },
    { id: "constitution", href: "#/constitution", icon: "body",    label: "体质" },
    { id: "terms",        href: "#/terms",        icon: "bowl",    label: "节气" },
    { id: "symptoms",     href: "#/symptoms",     icon: "symptom", label: "症状" },
    { id: "population",   href: "#/population",   icon: "people",  label: "人群" },
    { id: "recipes",      href: "#/recipes",      icon: "herb",    label: "食疗" },
  ];
  return (
    <nav className="mobile-bottom-nav">
      {items.map(item => {
        const I = Icon[item.icon];
        return (
          <a key={item.id} href={item.href} className={"mobile-nav-item" + (page === item.id ? " active" : "")}>
            <I />
            <span>{item.label}</span>
          </a>
        );
      })}
    </nav>
  );
}

// ============= Home Page =============
function HomePage({ onQuiz, onAI }) {
  return (
    <>
      <Hero onQuiz={onQuiz} onAI={onAI} />
      <Pillars />
    </>
  );
}

// ============= App Root =============

// ═══════════════════════════════════════════════════════════
// 本草查询页面
// ═══════════════════════════════════════════════════════════
function HerbsPage() {
  const [herbs, setHerbs] = React.useState([]);
  const [query, setQuery] = React.useState('');
  const [cat, setCat] = React.useState('全部');
  const [sel, setSel] = React.useState(null);
  const [loading, setLoading] = React.useState(true);

  React.useEffect(() => {
    fetch(API + '/herbs')
      .then(r => r.json())
      .then(d => { setHerbs(d); setLoading(false); })
      .catch(() => setLoading(false));
  }, []);

  const CATS = ['全部','补气药','补血药','补阴药','补阳药','清热药','活血化瘀药','理气药','安神药','温里药','解表药','利水渗湿药'];

  const filtered = herbs.filter(h => {
    const q = query.trim();
    const matchQ = !q || h.name.includes(q) || (h.functions||'').includes(q) || (h.indications||'').includes(q) || (h.pinyin||'').includes(q);
    const matchC = cat === '全部' || h.category === cat;
    return matchQ && matchC;
  });

  return (
    <section className="section" style={{minHeight:'80vh',paddingBottom:60}}>
      <div className="section-head">
        <h2 className="section-title">
          <span className="num">— 专业工具 / 壹 —</span>
          本草查询 · 药材百科
        </h2>
        <div className="section-sub">收录 62 味常用本草 · 性味归经 · 功效主治</div>
      </div>

      <div style={{maxWidth:680,margin:'0 auto 28px',padding:'0 16px'}}>
        <div style={{position:'relative'}}>
          <input type="text" value={query} onChange={e => setQuery(e.target.value)}
            placeholder="搜索药材名称、功效、主治…"
            style={{width:'100%',padding:'13px 20px 13px 44px',fontSize:14,background:'var(--bg-card)',border:'1px solid var(--line)',color:'var(--ink)',boxSizing:'border-box',outline:'none',fontFamily:'var(--serif)',letterSpacing:1}} />
          <span style={{position:'absolute',left:16,top:'50%',transform:'translateY(-50%)',color:'var(--ink-3)',fontSize:16}}>⌕</span>
        </div>
      </div>

      <div style={{display:'flex',flexWrap:'wrap',gap:6,justifyContent:'center',marginBottom:32,padding:'0 16px'}}>
        {CATS.map(c => (
          <button key={c} onClick={() => setCat(c)}
            style={{padding:'5px 14px',fontSize:11,letterSpacing:1,cursor:'pointer',border:'1px solid '+(cat===c?'var(--jade)':'var(--line)'),background:cat===c?'var(--jade)':'transparent',color:cat===c?'#fff':'var(--ink-2)',transition:'all .2s'}}>
            {c}
          </button>
        ))}
      </div>

      {loading ? (
        <div style={{textAlign:'center',color:'var(--ink-3)',padding:60,fontSize:13,letterSpacing:2}}>加载本草数据中…</div>
      ) : (
        <div style={{display:'grid',gridTemplateColumns:'repeat(auto-fill,minmax(210px,1fr))',gap:14,maxWidth:1200,margin:'0 auto',padding:'0 16px'}}>
          {filtered.map(h => (
            <div key={h.id} onClick={() => setSel(h)}
              style={{background:'var(--bg-card)',border:'1px solid var(--line)',padding:'18px 16px',cursor:'pointer',transition:'transform .15s,box-shadow .15s'}}
              onMouseEnter={e=>{e.currentTarget.style.transform='translateY(-2px)';e.currentTarget.style.boxShadow='0 8px 24px rgba(0,0,0,.1)'}}
              onMouseLeave={e=>{e.currentTarget.style.transform='none';e.currentTarget.style.boxShadow='none'}}>
              <div style={{display:'flex',justifyContent:'space-between',alignItems:'flex-start',marginBottom:6}}>
                <div style={{fontFamily:'var(--serif)',fontSize:20,letterSpacing:2,color:'var(--ink)'}}>{h.name}</div>
                <span style={{fontSize:9,color:'var(--jade)',border:'1px solid var(--jade)',padding:'2px 5px',letterSpacing:1,whiteSpace:'nowrap',marginLeft:6,flexShrink:0}}>{h.category}</span>
              </div>
              <div style={{fontSize:11,color:'var(--ink-3)',marginBottom:8,letterSpacing:1}}>{h.pinyin}</div>
              <div style={{fontSize:11,color:'var(--ink-2)',lineHeight:1.6,borderTop:'1px solid var(--line)',paddingTop:8}}>
                <span style={{color:'var(--gold)'}}>{h.nature}，{h.flavor}</span>　{h.meridian}
              </div>
            </div>
          ))}
          {filtered.length === 0 && (
            <div style={{gridColumn:'1/-1',textAlign:'center',color:'var(--ink-3)',padding:60,fontSize:13}}>暂无匹配结果</div>
          )}
        </div>
      )}

      {sel && (
        <div style={{position:'fixed',inset:0,zIndex:1000,display:'flex',alignItems:'center',justifyContent:'center',background:'rgba(31,26,18,.72)',backdropFilter:'blur(4px)'}}
          onClick={() => setSel(null)}>
          <div style={{width:'min(660px,95vw)',maxHeight:'90vh',overflowY:'auto',background:'var(--bg-card)',border:'1px solid var(--line)',boxShadow:'0 24px 60px rgba(0,0,0,.35)'}}
            onClick={e => e.stopPropagation()}>
            <div style={{padding:'20px 28px',background:'var(--jade)',display:'flex',justifyContent:'space-between',alignItems:'center',position:'sticky',top:0}}>
              <div>
                <div style={{fontSize:10,letterSpacing:4,color:'rgba(255,255,255,.55)',marginBottom:4}}>本草档案</div>
                <div style={{fontFamily:'var(--serif)',fontSize:26,letterSpacing:4,color:'#fff'}}>{sel.name}</div>
                <div style={{fontSize:12,color:'rgba(255,255,255,.65)',marginTop:3,letterSpacing:1}}>{sel.pinyin} · {sel.category}</div>
              </div>
              <button onClick={() => setSel(null)} style={{background:'rgba(255,255,255,.15)',border:'none',cursor:'pointer',color:'#fff',width:34,height:34,borderRadius:'50%',fontSize:16,flexShrink:0}}>✕</button>
            </div>
            <div style={{padding:'24px 28px'}}>
              <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:10,marginBottom:20}}>
                {[['性味',sel.nature+'，'+sel.flavor],['归经',sel.meridian],['用量',sel.dosage],['分类',sel.category]].map(([k,v]) => (
                  <div key={k} style={{background:'rgba(44,74,59,.05)',padding:'10px 14px',borderLeft:'2px solid var(--gold)'}}>
                    <div style={{fontSize:10,color:'var(--ink-3)',letterSpacing:2,marginBottom:5}}>{k}</div>
                    <div style={{fontSize:13,color:'var(--ink)',lineHeight:1.6}}>{v}</div>
                  </div>
                ))}
              </div>
              {[['功效','var(--jade)',sel.functions],['主治','var(--gold)',sel.indications],['注意事项','var(--vermillion)',sel.cautions]].map(([k,c,v]) => v && (
                <div key={k} style={{marginBottom:16}}>
                  <div style={{display:'flex',alignItems:'center',gap:8,marginBottom:8}}>
                    <span style={{width:3,height:14,background:c,display:'inline-block'}}></span>
                    <span style={{fontFamily:'var(--serif)',fontSize:14,letterSpacing:2,color:c}}>{k}</span>
                  </div>
                  <div style={{fontSize:13,color:'var(--ink-2)',lineHeight:1.9,background:'rgba(44,74,59,.04)',padding:'12px 14px'}}>{v}</div>
                </div>
              ))}
            </div>
          </div>
        </div>
      )}
    </section>
  );
}

// ═══════════════════════════════════════════════════════════
// 方剂溯源页面
// ═══════════════════════════════════════════════════════════
function FormulasPage() {
  const [formulas, setFormulas] = React.useState([]);
  const [query, setQuery] = React.useState('');
  const [cat, setCat] = React.useState('全部');
  const [sel, setSel] = React.useState(null);
  const [loading, setLoading] = React.useState(true);

  React.useEffect(() => {
    fetch(API + '/formulas')
      .then(r => r.json())
      .then(d => { setFormulas(d); setLoading(false); })
      .catch(() => setLoading(false));
  }, []);

  const CATS = ['全部','补益剂','解表剂','清热剂','和解剂','温里剂','泻下剂','活血化瘀剂','祛湿剂','化痰剂','理气剂','安神剂','滋阴剂'];

  const filtered = formulas.filter(f => {
    const q = query.trim();
    const matchQ = !q || f.name.includes(q) || (f.functions||'').includes(q) || (f.indications||'').includes(q) || (f.source||'').includes(q);
    const matchC = cat === '全部' || f.category === cat;
    return matchQ && matchC;
  });

  return (
    <section className="section" style={{minHeight:'80vh',paddingBottom:60}}>
      <div className="section-head">
        <h2 className="section-title">
          <span className="num">— 专业工具 / 贰 —</span>
          方剂溯源 · 经典方鉴
        </h2>
        <div className="section-sub">收录 40 首经典方剂 · 追溯出处 · 解析组方之道</div>
      </div>

      <div style={{maxWidth:680,margin:'0 auto 28px',padding:'0 16px'}}>
        <div style={{position:'relative'}}>
          <input type="text" value={query} onChange={e => setQuery(e.target.value)}
            placeholder="搜索方名、功效、主治或出处…"
            style={{width:'100%',padding:'13px 20px 13px 44px',fontSize:14,background:'var(--bg-card)',border:'1px solid var(--line)',color:'var(--ink)',boxSizing:'border-box',outline:'none',fontFamily:'var(--serif)',letterSpacing:1}} />
          <span style={{position:'absolute',left:16,top:'50%',transform:'translateY(-50%)',color:'var(--ink-3)',fontSize:16}}>⌕</span>
        </div>
      </div>

      <div style={{display:'flex',flexWrap:'wrap',gap:6,justifyContent:'center',marginBottom:32,padding:'0 16px'}}>
        {CATS.map(c => (
          <button key={c} onClick={() => setCat(c)}
            style={{padding:'5px 14px',fontSize:11,letterSpacing:1,cursor:'pointer',border:'1px solid '+(cat===c?'var(--gold)':'var(--line)'),background:cat===c?'var(--gold)':'transparent',color:cat===c?'#fff':'var(--ink-2)',transition:'all .2s'}}>
            {c}
          </button>
        ))}
      </div>

      {loading ? (
        <div style={{textAlign:'center',color:'var(--ink-3)',padding:60,fontSize:13,letterSpacing:2}}>加载方剂数据中…</div>
      ) : (
        <div style={{display:'grid',gridTemplateColumns:'repeat(auto-fill,minmax(280px,1fr))',gap:16,maxWidth:1200,margin:'0 auto',padding:'0 16px'}}>
          {filtered.map(f => (
            <div key={f.id} onClick={() => setSel(f)}
              style={{background:'var(--bg-card)',border:'1px solid var(--line)',padding:'20px 20px',cursor:'pointer',transition:'transform .15s,box-shadow .15s'}}
              onMouseEnter={e=>{e.currentTarget.style.transform='translateY(-2px)';e.currentTarget.style.boxShadow='0 8px 24px rgba(0,0,0,.1)'}}
              onMouseLeave={e=>{e.currentTarget.style.transform='none';e.currentTarget.style.boxShadow='none'}}>
              <div style={{display:'flex',justifyContent:'space-between',alignItems:'flex-start',marginBottom:8}}>
                <div style={{fontFamily:'var(--serif)',fontSize:18,letterSpacing:3,color:'var(--ink)'}}>{f.name}</div>
                <span style={{fontSize:9,color:'var(--gold)',border:'1px solid var(--gold)',padding:'2px 5px',letterSpacing:1,whiteSpace:'nowrap',marginLeft:8,flexShrink:0}}>{f.category}</span>
              </div>
              <div style={{fontSize:11,color:'var(--ink-3)',marginBottom:10,letterSpacing:1}}>{f.source}</div>
              <div style={{fontSize:12,color:'var(--jade)',marginBottom:8,lineHeight:1.5}}>{f.functions}</div>
              <div style={{fontSize:11,color:'var(--ink-2)',lineHeight:1.7,borderTop:'1px solid var(--line)',paddingTop:8}}>
                {f.composition && f.composition.slice(0,4).join('　')}{f.composition && f.composition.length > 4 ? '…' : ''}
              </div>
            </div>
          ))}
          {filtered.length === 0 && (
            <div style={{gridColumn:'1/-1',textAlign:'center',color:'var(--ink-3)',padding:60,fontSize:13}}>暂无匹配结果</div>
          )}
        </div>
      )}

      {sel && (
        <div style={{position:'fixed',inset:0,zIndex:1000,display:'flex',alignItems:'center',justifyContent:'center',background:'rgba(31,26,18,.72)',backdropFilter:'blur(4px)'}}
          onClick={() => setSel(null)}>
          <div style={{width:'min(700px,95vw)',maxHeight:'90vh',overflowY:'auto',background:'var(--bg-card)',border:'1px solid var(--line)',boxShadow:'0 24px 60px rgba(0,0,0,.35)'}}
            onClick={e => e.stopPropagation()}>
            <div style={{padding:'20px 28px',background:'linear-gradient(135deg,#7a5c28,#b8862a)',display:'flex',justifyContent:'space-between',alignItems:'center',position:'sticky',top:0}}>
              <div>
                <div style={{fontSize:10,letterSpacing:4,color:'rgba(255,255,255,.55)',marginBottom:4}}>方剂档案</div>
                <div style={{fontFamily:'var(--serif)',fontSize:24,letterSpacing:4,color:'#fff'}}>{sel.name}</div>
                <div style={{fontSize:12,color:'rgba(255,255,255,.65)',marginTop:3,letterSpacing:1}}>{sel.source} · {sel.category}</div>
              </div>
              <button onClick={() => setSel(null)} style={{background:'rgba(255,255,255,.15)',border:'none',cursor:'pointer',color:'#fff',width:34,height:34,borderRadius:'50%',fontSize:16,flexShrink:0}}>✕</button>
            </div>
            <div style={{padding:'24px 28px'}}>
              <div style={{marginBottom:20}}>
                <div style={{display:'flex',alignItems:'center',gap:8,marginBottom:12}}>
                  <span style={{width:3,height:14,background:'var(--gold)',display:'inline-block'}}></span>
                  <span style={{fontFamily:'var(--serif)',fontSize:14,letterSpacing:2,color:'var(--gold)'}}>方剂组成</span>
                </div>
                <div style={{display:'flex',flexWrap:'wrap',gap:8}}>
                  {sel.composition && sel.composition.map((item,i) => (
                    <span key={i} style={{fontSize:12,color:'var(--ink)',background:'rgba(184,134,42,.1)',border:'1px solid rgba(184,134,42,.3)',padding:'4px 10px',letterSpacing:1}}>{item}</span>
                  ))}
                </div>
              </div>
              {[['功效','var(--jade)',sel.functions],['主治','var(--gold)',sel.indications],['方解','var(--ink-2)',sel.notes]].map(([k,c,v]) => v && (
                <div key={k} style={{marginBottom:16}}>
                  <div style={{display:'flex',alignItems:'center',gap:8,marginBottom:8}}>
                    <span style={{width:3,height:14,background:c,display:'inline-block'}}></span>
                    <span style={{fontFamily:'var(--serif)',fontSize:14,letterSpacing:2,color:c}}>{k}</span>
                  </div>
                  <div style={{fontSize:13,color:'var(--ink-2)',lineHeight:1.9,background:'rgba(44,74,59,.04)',padding:'12px 14px'}}>{v}</div>
                </div>
              ))}
            </div>
          </div>
        </div>
      )}
    </section>
  );
}

// ═══════════════════════════════════════════════════════════
// 关于页面（占位）
// ═══════════════════════════════════════════════════════════
function AboutPage() {
  return (
    <section className="section" style={{minHeight:'60vh',paddingBottom:60}}>
      <div className="section-head">
        <h2 className="section-title">
          <span className="num">— 关于 / 壹 —</span>
          关于古柒春
        </h2>
        <div className="section-sub">以中医传统智慧为根，以现代调理科学为用</div>
      </div>
      <div style={{maxWidth:760,margin:'0 auto',padding:'0 24px'}}>
        <div style={{background:'var(--bg-card)',border:'1px solid var(--line)',padding:'40px 48px',marginBottom:24}}>
          <div style={{fontFamily:'var(--serif)',fontSize:22,letterSpacing:4,color:'var(--jade)',marginBottom:20}}>品牌理念</div>
          <p style={{fontSize:14,color:'var(--ink-2)',lineHeight:2.2,letterSpacing:1,marginBottom:16}}>
            古柒春，取意"古法养生，七分调理，迎春而生"。我们深信，中医传统智慧历经数千年验证，蕴含着现代人所需的养生之道。
          </p>
          <p style={{fontSize:14,color:'var(--ink-2)',lineHeight:2.2,letterSpacing:1,marginBottom:16}}>
            我们致力于将晦涩难懂的中医知识，转化为每个人都能理解和践行的日常养生方案。从体质辨识到症状调理，从节气养生到药膳食疗，古柒春陪伴您走过每一个节气，调养每一分气血。
          </p>
          <p style={{fontSize:14,color:'var(--ink-2)',lineHeight:2.2,letterSpacing:1}}>
            内容持续完善中，敬请期待。
          </p>
        </div>
        <div style={{display:'grid',gridTemplateColumns:'repeat(3,1fr)',gap:16}}>
          {[['62','味本草收录'],['40','首经典方剂'],['36','种症状调理']].map(([n,t]) => (
            <div key={t} style={{background:'var(--bg-card)',border:'1px solid var(--line)',padding:'24px',textAlign:'center'}}>
              <div style={{fontFamily:'var(--serif)',fontSize:36,color:'var(--jade)',letterSpacing:2}}>{n}</div>
              <div style={{fontSize:12,color:'var(--ink-3)',letterSpacing:2,marginTop:6}}>{t}</div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

function TeamPage() {
  return (
    <section className="section" style={{minHeight:'60vh',paddingBottom:60}}>
      <div className="section-head">
        <h2 className="section-title">
          <span className="num">— 关于 / 贰 —</span>
          编辑团队
        </h2>
        <div className="section-sub">专业内容团队 · 用心打磨每一条养生知识</div>
      </div>
      <div style={{maxWidth:760,margin:'0 auto',padding:'0 24px'}}>
        <div style={{background:'var(--bg-card)',border:'1px solid var(--line)',padding:'48px',textAlign:'center'}}>
          <div style={{fontSize:40,marginBottom:16}}>🌿</div>
          <div style={{fontFamily:'var(--serif)',fontSize:18,letterSpacing:4,color:'var(--jade)',marginBottom:16}}>团队介绍整理中</div>
          <p style={{fontSize:13,color:'var(--ink-3)',lineHeight:2,letterSpacing:1}}>
            我们的内容团队由中医爱好者、健康编辑与养生研究者组成，<br/>正在精心整理团队成员介绍，敬请期待。
          </p>
        </div>
      </div>
    </section>
  );
}

function AdvisorsPage() {
  return (
    <section className="section" style={{minHeight:'60vh',paddingBottom:60}}>
      <div className="section-head">
        <h2 className="section-title">
          <span className="num">— 关于 / 叁 —</span>
          专家顾问
        </h2>
        <div className="section-sub">专业把关 · 确保内容的准确性与权威性</div>
      </div>
      <div style={{maxWidth:760,margin:'0 auto',padding:'0 24px'}}>
        <div style={{background:'var(--bg-card)',border:'1px solid var(--line)',padding:'48px',textAlign:'center'}}>
          <div style={{fontSize:40,marginBottom:16}}>📜</div>
          <div style={{fontFamily:'var(--serif)',fontSize:18,letterSpacing:4,color:'var(--jade)',marginBottom:16}}>顾问团队整理中</div>
          <p style={{fontSize:13,color:'var(--ink-3)',lineHeight:2,letterSpacing:1}}>
            专家顾问团队信息正在整理中，<br/>我们将邀请具有丰富临床经验的中医专家为内容把关。
          </p>
        </div>
      </div>
    </section>
  );
}

function CooperationPage() {
  return (
    <section className="section" style={{minHeight:'60vh',paddingBottom:60}}>
      <div className="section-head">
        <h2 className="section-title">
          <span className="num">— 关于 / 肆 —</span>
          合作咨询
        </h2>
        <div className="section-sub">共同推广中医养生文化</div>
      </div>
      <div style={{maxWidth:760,margin:'0 auto',padding:'0 24px'}}>
        <div style={{background:'var(--bg-card)',border:'1px solid var(--line)',padding:'40px 48px'}}>
          <div style={{fontFamily:'var(--serif)',fontSize:18,letterSpacing:4,color:'var(--jade)',marginBottom:24}}>合作方向</div>
          <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:16,marginBottom:32}}>
            {[['内容合作','中医知识共创、专栏撰稿'],['品牌推广','健康品牌联名与推广'],['学术交流','中医院校与研究机构合作'],['商务洽谈','产品合作与渠道拓展']].map(([t,d]) => (
              <div key={t} style={{padding:'20px',background:'rgba(44,74,59,.05)',borderLeft:'2px solid var(--jade)'}}>
                <div style={{fontFamily:'var(--serif)',fontSize:14,letterSpacing:2,color:'var(--ink)',marginBottom:6}}>{t}</div>
                <div style={{fontSize:12,color:'var(--ink-3)',lineHeight:1.8}}>{d}</div>
              </div>
            ))}
          </div>
          <div style={{borderTop:'1px solid var(--line)',paddingTop:24,fontSize:13,color:'var(--ink-2)',lineHeight:2,letterSpacing:1}}>
            如有合作意向，欢迎通过微信公众号「古柒春」后台留言联系我们，我们将在 1-3 个工作日内回复。
          </div>
        </div>
      </div>
    </section>
  );
}

function App() {
  const getPage = () => {
    const h = window.location.hash;
    if (!h || h === "#" || h === "#/") return "home";
    return h.slice(2);
  };

  const [page, setPage] = useState(getPage);
  const [searchOpen, setSearchOpen] = useState(false);
  const [quizOpen, setQuizOpen] = useState(false);
  const [aiOpen, setAiOpen] = useState(false);

  useEffect(() => {
    const handler = () => { setPage(getPage()); window.scrollTo(0, 0); };
    window.addEventListener("hashchange", handler);
    return () => window.removeEventListener("hashchange", handler);
  }, []);

  useEffect(() => {
    const handler = (e) => {
      if ((e.metaKey || e.ctrlKey) && e.key === "k") { e.preventDefault(); setSearchOpen(true); }
      if (e.key === "Escape") { setSearchOpen(false); setQuizOpen(false); }
    };
    window.addEventListener("keydown", handler);
    return () => window.removeEventListener("keydown", handler);
  }, []);

  const renderPage = () => {
    switch (page) {
      case "constitution": return <ConstitutionDetail />;
      case "terms":        return <SolarTermsWheel />;
      case "symptoms":     return <SymptomStrip />;
      case "population":   return <Population />;
      case "recipes":      return <Recipes />;
    case "herbs":       return React.createElement(HerbsPage, null);
    case "formulas":    return React.createElement(FormulasPage, null);
    case "about":       return React.createElement(AboutPage, null);
    case "team":        return React.createElement(TeamPage, null);
    case "advisors":    return React.createElement(AdvisorsPage, null);
    case "cooperation": return React.createElement(CooperationPage, null);
      default:             return <HomePage onQuiz={() => setQuizOpen(true)} onAI={() => setAiOpen(true)} />;
    }
  };

  return (
    <div className="app">
      <SearchOverlay open={searchOpen} onClose={() => setSearchOpen(false)} />
      <QuizModal open={quizOpen} onClose={() => setQuizOpen(false)} />
      <AIAnalysisModal open={aiOpen} onClose={() => setAiOpen(false)} />
      <Nav page={page} onSearch={() => setSearchOpen(true)} onQuiz={() => setQuizOpen(true)} />
      {renderPage()}
      <Footer />
      <MobileBottomNav page={page} />
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
