(()=>{
// === User-side screens ===
const { Card, Btn, Badge, RiskChip, Kicker, SectionHeader, StatTile, Stepper, KV, RiskCard } = window.UI;
const { RiskGauge, OralImage, ColorChecker, HistoryChart } = window.Viz;
const { PATIENT, CAPTURE, RISKS, ROIS, ADVICE, HISTORY } = window.DATA;

// ---------- Home / Overview ----------
const ScreenHome = ({ nav }) => {
  const risks = Object.values(RISKS);
  const highCount = risks.filter(r=>r.level==="high").length;
  const midCount  = risks.filter(r=>r.level==="mid").length;
  return (
    <div className="fade-in space-y-6">
      <SectionHeader
        kicker="01 — Patient Dashboard"
        title="健康总览"
        sub="基于最近一次口腔图像分析（2026-05-11 09:42）生成。下方四个慢性病风险评分均为模型预测概率的标准化分数。"
        action={<Btn variant="primary" icon="camera" onClick={()=>nav("capture")}>新建检测</Btn>}
      />

      {/* Patient strip */}
      <div className="card shadow-card p-5 flex items-center gap-5">
        <div className="w-14 h-14 rounded-full bg-clinic-100 border border-clinic-200 flex items-center justify-center text-clinic-700 font-semibold text-lg serif-zh">王</div>
        <div className="flex-1">
          <div className="flex items-center gap-2">
            <div className="text-lg font-semibold serif-zh">{PATIENT.name}</div>
            <Badge color="ink">{PATIENT.age} 岁 · {PATIENT.gender}</Badge>
            <Badge color="blue">编号 CS-2025-00142</Badge>
          </div>
          <div className="text-xs text-ink-500 mt-1">{PATIENT.history.join(" · ")} · BMI {PATIENT.bmi}</div>
        </div>
        <div className="grid grid-cols-3 gap-6 text-right">
          <div><div className="num text-xl font-semibold">{PATIENT.totalChecks}</div><div className="text-[11px] text-ink-500">累计检测</div></div>
          <div><div className="num text-xl font-semibold text-risk-high">{highCount}</div><div className="text-[11px] text-ink-500">高风险项</div></div>
          <div><div className="num text-xl font-semibold text-risk-mid">{midCount}</div><div className="text-[11px] text-ink-500">中风险项</div></div>
        </div>
      </div>

      {/* Risk grid */}
      <div className="grid grid-cols-4 gap-4">
        {risks.map(r=>(
          <RiskCard key={r.key} risk={r} onClick={()=>nav("detail", r.key)}/>
        ))}
      </div>

      <div className="grid grid-cols-3 gap-4">
        {/* Latest summary */}
        <Card title="本次检测要点" kicker="Summary" className="col-span-2">
          <div className="space-y-3">
            <div className="flex gap-3 items-start">
              <div className="w-1 self-stretch bg-risk-high rounded"/>
              <div>
                <div className="text-sm font-medium">糖尿病风险显著上升至 <span className="num">72</span> 分</div>
                <p className="text-xs text-ink-500 mt-1">牙龈区域 a* 值 18.4（参考 10–14），HSV 饱和度 0.41，红色炎症特征强。预测 HbA1c ≈ 7.2%，建议 30 日内做静脉血复测。</p>
              </div>
            </div>
            <div className="flex gap-3 items-start">
              <div className="w-1 self-stretch bg-risk-mid rounded"/>
              <div>
                <div className="text-sm font-medium">心血管风险维持中等 (<span className="num">45</span> 分)</div>
                <p className="text-xs text-ink-500 mt-1">口腔菌群指征中性偏高，结合既往高血压病史建议监测颈动脉。</p>
              </div>
            </div>
            <div className="flex gap-3 items-start">
              <div className="w-1 self-stretch bg-risk-low rounded"/>
              <div>
                <div className="text-sm font-medium">肾病 / 贫血信号正常</div>
                <p className="text-xs text-ink-500 mt-1">舌面 b* 通道与黏膜苍白指数均在参考区间。</p>
              </div>
            </div>
          </div>
        </Card>

        <Card title="近期趋势" kicker="6 Checks">
          <div className="h-[180px] overflow-hidden">
            <HistoryChart data={HISTORY.slice(-6)} width={320} height={180}/>
          </div>
          <div className="text-xs text-ink-500 mt-2">糖尿病评分自 2025-08 起持续上升，斜率 +5.7 / 月。</div>
        </Card>
      </div>

      {/* Quick actions */}
      <div className="grid grid-cols-4 gap-3">
        {[
          { icon:"camera", title:"新建检测", sub:"约 90 秒",  k:"capture" },
          { icon:"history", title:"历史记录", sub:"14 条", k:"history" },
          { icon:"lightbulb", title:"健康建议", sub:"分病种", k:"advice" },
          { icon:"user", title:"个人档案", sub:"管理资料", k:"profile" },
        ].map(a=>(
          <button key={a.k} onClick={()=>nav(a.k)}
            className="card-tight p-4 text-left hover:border-clinic-300 hover:shadow-cardHover transition flex items-center gap-3">
            <div className="w-10 h-10 rounded-md bg-clinic-100 text-clinic-700 flex items-center justify-center"><Icon name={a.icon}/></div>
            <div className="flex-1">
              <div className="text-sm font-medium">{a.title}</div>
              <div className="text-xs text-ink-500">{a.sub}</div>
            </div>
            <Icon name="chevron-right" size={16} className="text-ink-400"/>
          </button>
        ))}
      </div>
    </div>
  );
};

// ---------- Capture wizard ----------
const ScreenCapture = ({ nav }) => {
  const [step, setStep] = React.useState(0);
  const steps = ["拍摄准备", "对焦取景", "图像确认", "AI 分析"];

  React.useEffect(()=>{
    if (step === 3) {
      const t = setTimeout(()=>nav("results"), 4200);
      return () => clearTimeout(t);
    }
  }, [step]);

  return (
    <div className="fade-in space-y-6">
      <SectionHeader kicker="02 — Capture" title="新建口腔图像检测" sub="请按提示完成 4 个步骤。整个过程约需 90 秒。"/>

      <div className="card p-5">
        <Stepper steps={steps} current={step}/>
      </div>

      {step === 0 && <CaptureStep0 onNext={()=>setStep(1)}/>}
      {step === 1 && <CaptureStep1 onNext={()=>setStep(2)} onBack={()=>setStep(0)}/>}
      {step === 2 && <CaptureStep2 onNext={()=>setStep(3)} onBack={()=>setStep(1)}/>}
      {step === 3 && <CaptureStep3/>}
    </div>
  );
};

// Step 0 — prep / instructions
const CaptureStep0 = ({ onNext }) => (
  <div className="grid grid-cols-3 gap-5">
    <Card title="拍摄要求" kicker="Pre-flight" className="col-span-2">
      <ol className="space-y-4">
        {[
          { n:"01", t:"在 自然光 或 5000K 白光下拍摄", d:"避开窗边强光与暖黄色灯光，环境光照度需 > 300 lux（系统自动检测）。" },
          { n:"02", t:"将 标准色卡 贴在脸颊旁", d:"色卡用于色彩仿射校正。如无色卡，将启用环境光传感器替代方案（精度略降）。" },
          { n:"03", t:"清洁口腔，张嘴呈 \"啊\" 状", d:"舌头自然伸出 1–2 厘米，露出上下牙龈与两侧黏膜。请勿食用染色食物。" },
          { n:"04", t:"前置摄像头距离约 15–20 厘米", d:"系统会实时检测对焦清晰度与拍摄角度，姿势达标后自动快门。" },
        ].map(s=>(
          <li key={s.n} className="flex gap-4">
            <div className="num text-xs font-semibold text-clinic-600 w-6 pt-1">{s.n}</div>
            <div>
              <div className="text-sm font-medium">{s.t}</div>
              <div className="text-xs text-ink-500 mt-0.5">{s.d}</div>
            </div>
          </li>
        ))}
      </ol>
      <div className="mt-6 flex items-center justify-between border-t border-ink-100 pt-4">
        <Badge color="blue"><Icon name="shield" size={12}/> 图像本地预处理，仅上传 20 维特征向量</Badge>
        <Btn icon="camera" iconRight="chevron-right" onClick={onNext}>开始拍摄</Btn>
      </div>
    </Card>

    <Card title="环境检测" kicker="Live Sensors">
      <div className="space-y-3">
        <SensorRow label="环境光照度" value={`${CAPTURE.ambientLux} lux`} ok={CAPTURE.ambientLux>300} hint="> 300 lux"/>
        <SensorRow label="色温估算" value="5180 K" ok hint="4500–6500 K"/>
        <SensorRow label="陀螺仪稳定度" value="98%" ok hint="> 90%"/>
        <SensorRow label="色卡识别" value={CAPTURE.colorCardDetected?"已识别":"未检测"} ok={CAPTURE.colorCardDetected} hint="X-Rite 24 patches"/>
        <SensorRow label="摄像头" value={CAPTURE.device} ok hint="主摄优先"/>
      </div>
    </Card>
  </div>
);

const SensorRow = ({ label, value, ok, hint }) => (
  <div className="flex items-center gap-3">
    <div className={`w-2 h-2 rounded-full ${ok?"bg-mint-500 pulse-dot":"bg-risk-mid"}`}/>
    <div className="flex-1">
      <div className="text-xs text-ink-500">{label}</div>
      <div className="text-sm font-medium num">{value}</div>
    </div>
    <div className="text-[10px] text-ink-400 num">{hint}</div>
  </div>
);

// Step 1 — viewfinder
const CaptureStep1 = ({ onNext, onBack }) => {
  const [pose, setPose] = React.useState(0.62);
  const [focus, setFocus] = React.useState(0.71);
  React.useEffect(()=>{
    let raf;
    const tick = () => {
      setPose(p => Math.min(0.96, p + 0.012 + Math.random()*0.005));
      setFocus(f => Math.min(0.97, f + 0.010 + Math.random()*0.006));
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, []);
  const ready = pose > 0.9 && focus > 0.9;
  return (
    <div className="grid grid-cols-3 gap-5">
      <Card title="实时取景" kicker="Viewfinder" className="col-span-2">
        <div className="relative bg-ink-900 rounded-md overflow-hidden">
          <OralImage width={520} height={340} raw={false}/>
          {/* corner reticles */}
          {[[8,8],[8,332],[512,8],[512,332]].map(([x,y],i)=>(
            <svg key={i} className="absolute" style={{left:`${(x/520)*100}%`, top:`${(y/340)*100}%`, transform:`translate(-50%,-50%)`}} width="22" height="22" viewBox="0 0 22 22">
              <path d="M 1 8 V 1 H 8" stroke={ready?"#13A37D":"#FBF8F0"} strokeWidth="2" fill="none"/>
              <path d="M 14 1 H 21 V 8" stroke={ready?"#13A37D":"#FBF8F0"} strokeWidth="2" fill="none"/>
              <path d="M 21 14 V 21 H 14" stroke={ready?"#13A37D":"#FBF8F0"} strokeWidth="2" fill="none"/>
              <path d="M 8 21 H 1 V 14" stroke={ready?"#13A37D":"#FBF8F0"} strokeWidth="2" fill="none"/>
            </svg>
          ))}
          {/* ROI dashed guides */}
          <svg className="absolute inset-0 w-full h-full" viewBox="0 0 520 340">
            <ellipse cx="260" cy="170" rx="170" ry="100" fill="none" stroke="#FBF8F0" strokeWidth="1" strokeDasharray="3 3" opacity="0.5"/>
            <text x="260" y="40" textAnchor="middle" fontSize="11" fill="#FBF8F0" opacity="0.8">请将口腔置于虚线椭圆内</text>
          </svg>
          {/* color checker in corner */}
          <div className="absolute right-3 bottom-3">
            <div className="text-[9px] text-white/80 mb-1 num text-right">COLOR CARD ✓</div>
            <ColorChecker size={60}/>
          </div>
          {/* scan bar */}
          <div className="absolute inset-x-0 top-0 bottom-0 overflow-hidden pointer-events-none">
            <div className="scan-bar"/>
          </div>
        </div>
        <div className="grid grid-cols-3 gap-3 mt-4">
          <Meter label="对焦清晰度" value={focus} ready={focus>0.9}/>
          <Meter label="姿势对齐度" value={pose} ready={pose>0.9}/>
          <Meter label="色卡同框" value={1.0} ready={true}/>
        </div>
        <div className="flex justify-between items-center mt-4">
          <Btn variant="ghost" icon="chevron-left" onClick={onBack}>返回</Btn>
          <div className="text-xs text-ink-500">{ready ? "✓ 满足拍摄条件，请按下快门" : "调整中…"}</div>
          <Btn icon="camera" iconRight="chevron-right" onClick={onNext} disabled={!ready}>{ready?"按下快门":"等待…"}</Btn>
        </div>
      </Card>

      <Card title="拍摄日志" kicker="EXIF + Sensor">
        <div className="space-y-0">
          <KV k="设备" v={CAPTURE.device}/>
          <KV k="ISO" v={CAPTURE.iso}/>
          <KV k="快门" v={CAPTURE.shutter}/>
          <KV k="白平衡" v="Auto → D65"/>
          <KV k="环境光" v={`${CAPTURE.ambientLux} lux`}/>
          <KV k="色卡检测" v="✓ 24 patches"/>
          <KV k="时间戳" v={CAPTURE.timestamp}/>
        </div>
        <div className="mt-4 bg-clinic-50 border border-clinic-200 rounded p-3 text-xs text-clinic-700">
          <div className="flex items-center gap-1 font-medium mb-1"><Icon name="info" size={12}/> 隐私提示</div>
          原始图像在本地完成 SAM2 分割与色彩校正，仅 20 维特征向量与 ROI mask 元数据被加密上传。
        </div>
      </Card>
    </div>
  );
};

const Meter = ({ label, value, ready }) => (
  <div className="card-tight p-3">
    <div className="flex items-center justify-between">
      <span className="text-[11px] text-ink-500">{label}</span>
      <span className={`num text-[11px] ${ready?"text-mint-600":"text-ink-600"}`}>{(value*100).toFixed(0)}%</span>
    </div>
    <div className="h-1.5 rounded-full bg-ink-100 mt-2 overflow-hidden">
      <div className={`h-full rounded-full transition-all duration-300 ${ready?"bg-mint-500":"bg-clinic-500"}`} style={{width:`${value*100}%`}}/>
    </div>
  </div>
);

// Step 2 — preview
const CaptureStep2 = ({ onNext, onBack }) => (
  <div className="grid grid-cols-3 gap-5">
    <Card title="原始照片预览" kicker="Raw Capture" className="col-span-2">
      <div className="relative rounded-md overflow-hidden border border-ink-200">
        <OralImage width={520} height={340} raw={true}/>
        <div className="absolute right-3 bottom-3"><ColorChecker size={64}/></div>
        <div className="absolute left-3 top-3 bg-white/90 rounded px-2 py-1 text-[10px] num text-ink-700">2026-05-11 09:42 · IMG-00142.jpg</div>
      </div>
      <div className="grid grid-cols-4 gap-3 mt-4">
        <StatTile label="对焦清晰度" value="93" unit="%"/>
        <StatTile label="姿势对齐度" value="94" unit="%"/>
        <StatTile label="ROI 完整度" value="3/3" sub="牙龈/舌面/黏膜"/>
        <StatTile label="质量等级" value="A" sub="可分析"/>
      </div>
      <div className="flex justify-between items-center mt-4">
        <Btn variant="ghost" icon="refresh" onClick={onBack}>重新拍摄</Btn>
        <Btn icon="cpu" iconRight="chevron-right" onClick={onNext}>提交分析</Btn>
      </div>
    </Card>

    <Card title="质量自动校验" kicker="QA Checklist">
      <ul className="space-y-2 text-sm">
        {[
          ["色卡可见且未遮挡", true],
          ["上下牙龈完整可见", true],
          ["舌体伸出 ≥ 1cm", true],
          ["无运动模糊 (≤ 0.15)", true],
          ["无染色食物干扰", true],
          ["光照均匀 (var < 0.08)", true],
        ].map(([t,ok],i)=>(
          <li key={i} className="flex items-center gap-2">
            <div className={`w-5 h-5 rounded-full flex items-center justify-center ${ok?"bg-mint-600 text-white":"bg-risk-high text-white"}`}>
              <Icon name={ok?"check":"x"} size={12}/>
            </div>
            <span className="text-ink-700">{t}</span>
          </li>
        ))}
      </ul>
    </Card>
  </div>
);

// Step 3 — analyzing
const CaptureStep3 = () => {
  const [stage, setStage] = React.useState(0);
  const stages = [
    { t:"色彩标准化", d:"检测色卡 → LAB 仿射变换 → 归一化到 D65", icon:"sun" },
    { t:"SAM2 分割",   d:"3 个 ROI 区域定位 (牙龈 / 舌面 / 黏膜)", icon:"target" },
    { t:"特征工程",    d:"20 维 LAB + HSV + 纹理特征向量提取",     icon:"filter" },
    { t:"XGBoost 推理", d:"4 棵独立树模型 + SHAP 解释",            icon:"cpu" },
  ];
  React.useEffect(()=>{
    const t = setInterval(()=>setStage(s=>Math.min(s+1, stages.length)), 1000);
    return () => clearInterval(t);
  }, []);
  return (
    <div className="grid grid-cols-3 gap-5">
      <Card title="AI 推理中" kicker="Inference" className="col-span-2">
        <div className="relative h-[280px] rounded-md overflow-hidden border border-ink-200 bg-ink-900">
          <OralImage width={520} height={280} raw={true}/>
          <div className="absolute inset-0 bg-clinic-900/20"/>
          <div className="scan-bar"/>
          {/* moving processing dots */}
          <div className="absolute inset-x-0 bottom-3 flex justify-center">
            <div className="bg-white/90 rounded-full px-3 py-1 text-xs num text-clinic-700 flex items-center gap-2">
              <span className="w-1.5 h-1.5 rounded-full bg-clinic-600 pulse-dot"/>
              处理中 · {stage<stages.length?stages[stage]?.t:"完成"} ({stage+1}/{stages.length})
            </div>
          </div>
        </div>
        <div className="grid grid-cols-4 gap-3 mt-4">
          {stages.map((s,i)=>(
            <div key={i} className={`card-tight p-3 transition-all ${i<stage?"border-mint-300 bg-mint-50":i===stage?"border-clinic-300 bg-clinic-50":""}`}>
              <div className="flex items-center justify-between">
                <Icon name={s.icon} size={14} className={i<stage?"text-mint-600":i===stage?"text-clinic-600":"text-ink-400"}/>
                {i<stage && <Icon name="check" size={12} className="text-mint-600"/>}
                {i===stage && <span className="w-1.5 h-1.5 rounded-full bg-clinic-600 pulse-dot"/>}
              </div>
              <div className="text-xs font-medium mt-2">{s.t}</div>
              <div className="text-[10px] text-ink-500 mt-1 leading-tight">{s.d}</div>
            </div>
          ))}
        </div>
      </Card>

      <Card title="实时日志" kicker="stdout">
        <div className="font-mono text-[11px] text-ink-600 space-y-1 leading-relaxed">
          <div className="text-mint-700">$ chronicsense analyze IMG-00142.jpg</div>
          <div>[1/4] detecting color card... ✓ 24 patches, ΔE76 baseline=18.4</div>
          {stage>=1 && <div>[1/4] LAB affine fitted (R²=0.987). ΔE76 → 2.7</div>}
          {stage>=1 && <div className="text-clinic-700">[2/4] loading sam2_oral_v3.onnx (47MB)...</div>}
          {stage>=2 && <div>[2/4] segmenting 3 ROIs... gum/tongue/mucosa ✓ IoU≈0.91</div>}
          {stage>=2 && <div className="text-clinic-700">[3/4] extracting features...</div>}
          {stage>=3 && <div>[3/4] 20-dim vector ready</div>}
          {stage>=3 && <div className="text-clinic-700">[4/4] xgb_diabetes.predict → 0.72</div>}
          {stage>=3 && <div>[4/4] xgb_cv.predict → 0.45 | xgb_kd → 0.18 | xgb_an → 0.12</div>}
          {stage>=4 && <div className="text-mint-700">✓ done in 187 ms (on-device)</div>}
        </div>
      </Card>
    </div>
  );
};

// ---------- Results ----------
const ScreenResults = ({ nav }) => {
  const risks = Object.values(RISKS);
  const dm = RISKS.diabetes;
  return (
    <div className="fade-in space-y-6">
      <SectionHeader
        kicker="03 — Results"
        title="风险评分结果"
        sub="本次检测共生成 4 个慢性病风险评分，下方仪表盘显示模型预测概率（已校准）。"
        action={
          <div className="flex gap-2">
            <Btn variant="ghost" icon="refresh" onClick={()=>nav("capture")}>重测</Btn>
            <Btn icon="lightbulb" onClick={()=>nav("advice")}>查看建议</Btn>
          </div>
        }
      />

      <div className="grid grid-cols-4 gap-4">
        {risks.map(r=>(
          <button key={r.key} onClick={()=>nav("detail", r.key)}
            className={`card text-left p-5 hover:shadow-cardHover transition`}>
            <div className="flex items-center justify-between mb-1">
              <div className="flex items-center gap-2">
                <Icon name={r.icon} size={14} className="text-ink-500"/>
                <span className="text-sm font-medium">{r.name}</span>
              </div>
              <RiskChip level={r.level}/>
            </div>
            <div className="mt-2 flex justify-center">
              <RiskGauge score={r.score} level={r.level} size={170}/>
            </div>
            <p className="text-xs text-ink-500 mt-2 line-clamp-2">{r.summary}</p>
            <div className="mt-3 pt-3 border-t border-ink-100 flex items-center justify-between text-xs">
              <span className="text-ink-500">14 天变化</span>
              <span className={`num font-medium flex items-center gap-1 ${r.trend>0?"text-risk-high":r.trend<0?"text-risk-low":"text-ink-500"}`}>
                <Icon name={r.trend>0?"trending-up":r.trend<0?"trending-down":"arrow-right"} size={12}/>
                {r.trend>0?"+":""}{r.trend}
              </span>
            </div>
          </button>
        ))}
      </div>

      <Card title="重点提示" kicker="Primary Concern" className="border-risk-high/30">
        <div className="flex gap-5 items-start">
          <div className="w-12 h-12 rounded-full bg-risk-highSoft text-risk-high flex items-center justify-center"><Icon name="warn"/></div>
          <div className="flex-1">
            <div className="text-base font-semibold">糖尿病风险评分 <span className="num text-risk-high">72</span> · 高风险</div>
            <p className="text-sm text-ink-600 mt-1">模型基于牙龈区域 a* 通道（红绿轴）的显著偏移、HSV 饱和度上升与纹理熵增加，推算 HbA1c ≈ <span className="num font-medium">7.2%</span>（参考 &lt; 6.5%）。结合家族糖尿病史，建议 30 日内至医院做 静脉血糖化血红蛋白 复测。</p>
            <div className="flex gap-2 mt-3">
              <Btn size="sm" onClick={()=>nav("detail", "diabetes")} iconRight="chevron-right">查看完整解释</Btn>
              <Btn size="sm" variant="ghost" icon="hospital">附近医院</Btn>
              <Btn size="sm" variant="ghost" icon="phone">家庭医生</Btn>
            </div>
          </div>
        </div>
      </Card>
    </div>
  );
};

// ---------- Disease detail (with SHAP) ----------
const ScreenDetail = ({ nav, target="diabetes" }) => {
  const r = RISKS[target] || RISKS.diabetes;
  const { ShapWaterfall } = window.Viz;
  const { SHAP_DIABETES, BASE_LOG_ODDS, FEATURES } = window.DATA;
  return (
    <div className="fade-in space-y-6">
      <div className="flex items-center gap-2 text-sm text-ink-500">
        <button onClick={()=>nav("results")} className="hover:text-clinic-600 flex items-center gap-1"><Icon name="chevron-left" size={14}/>风险评分</button>
        <span>/</span>
        <span className="text-ink-900 font-medium">{r.name}</span>
      </div>

      <div className="card p-6">
        <div className="flex items-start justify-between">
          <div>
            <Kicker>Detail · ICD-11: 5A11</Kicker>
            <h2 className="text-3xl font-semibold serif-zh mt-1">{r.name} 风险解析</h2>
            <p className="text-sm text-ink-500 mt-2 max-w-2xl">{r.summary}</p>
          </div>
          <RiskGauge score={r.score} level={r.level} size={160}/>
        </div>

        <div className="grid grid-cols-4 gap-3 mt-6 pt-6 border-t border-ink-100">
          <StatTile label="风险分数" value={r.score} unit="/ 100" level={r.level}/>
          <StatTile label="预测 HbA1c" value="7.2" unit="%" sub="参考 < 6.5%" level="high"/>
          <StatTile label="14 天变化" value="+5" sub="加速上升"/>
          <StatTile label="模型置信度" value="91" unit="%" sub="校准后"/>
        </div>
      </div>

      <div className="grid grid-cols-5 gap-5">
        {/* SHAP */}
        <Card title="SHAP 特征贡献 (瀑布图)" kicker="Explainability" className="col-span-3">
          <ShapWaterfall items={SHAP_DIABETES} base={BASE_LOG_ODDS} width={620} height={360}/>
          <div className="text-xs text-ink-500 mt-2">
            <span className="inline-block w-2 h-2 bg-risk-high rounded-sm mr-1"/>红色 = 推高风险，
            <span className="inline-block w-2 h-2 bg-clinic-500 rounded-sm mx-1"/>蓝色 = 拉低风险。
            条目越长表示该特征对最终概率的影响越大。
          </div>
        </Card>

        {/* Top features */}
        <Card title="主要风险因素" kicker="Top Drivers" className="col-span-2">
          <div className="space-y-3">
            {SHAP_DIABETES.slice(0, 5).filter(s=>s.value>0).map((s,i)=>{
              const feat = FEATURES.find(f=>f.name.startsWith(s.feature.split(" ")[1]?.replace("(","")||"")) || FEATURES[i];
              return (
                <div key={i} className="border-l-2 border-risk-high pl-3">
                  <div className="text-sm font-medium">{s.feature}</div>
                  <div className="text-xs text-ink-500 mt-0.5">
                    实测 <span className="num text-ink-900">{feat?.value}</span>
                    {feat?.ref && <> · 参考 <span className="num">{feat.ref}</span></>}
                    {feat?.note && <> · {feat.note}</>}
                  </div>
                  <div className="text-[11px] text-risk-high num mt-1">
                    SHAP +{s.value.toFixed(3)} · 推高风险约 {(s.value*100).toFixed(1)}%
                  </div>
                </div>
              );
            })}
          </div>
        </Card>
      </div>

      {/* Reasoning narrative */}
      <Card title="临床推理逻辑" kicker="Clinical Reasoning">
        <ol className="grid grid-cols-3 gap-4">
          {[
            ["牙周炎 ↔ 胰岛素抵抗", "糖尿病患者牙周炎发生率约为正常人 3 倍。慢性炎症释放的 IL-6 / TNF-α 会拮抗胰岛素信号传导。", "Mealey & Oates, 2006"],
            ["a* 通道偏移", "牙龈 a* 值反映牙龈组织血红蛋白浓度，与炎症水肿正相关；HbA1c 升高的患者常见 a* > 17。", "Yamamoto et al., 2018"],
            ["纹理熵 ↑", "炎症期牙龈表面失去 stippling，粒度结构变得无序，灰度共生矩阵 (GLCM) 熵值上升。", "Liu et al., 2022"],
          ].map(([t,d,c],i)=>(
            <li key={i} className="card-tight p-4">
              <div className="num text-xs text-ink-400">0{i+1}</div>
              <div className="text-sm font-medium mt-1">{t}</div>
              <div className="text-xs text-ink-500 mt-2">{d}</div>
              <div className="text-[10px] text-ink-400 mt-2 italic">{c}</div>
            </li>
          ))}
        </ol>
      </Card>

      <div className="flex justify-end gap-2">
        <Btn variant="ghost" onClick={()=>nav("results")} icon="chevron-left">返回结果</Btn>
        <Btn onClick={()=>nav("advice")} icon="lightbulb" iconRight="chevron-right">健康建议</Btn>
      </div>
    </div>
  );
};

// ---------- Advice ----------
const ScreenAdvice = ({ nav }) => {
  const [target, setTarget] = React.useState("diabetes");
  const adv = ADVICE[target] || ADVICE.diabetes;
  return (
    <div className="fade-in space-y-6">
      <SectionHeader kicker="04 — Recommendations" title="健康建议与就医推荐" sub="基于本次模型输出 + 您的既往史与生活习惯自动生成。"/>

      <div className="flex gap-2">
        {Object.values(RISKS).filter(r=>r.level!=="low").map(r=>(
          <button key={r.key} onClick={()=>setTarget(r.key)}
            className={`px-3 h-9 rounded-md border text-sm flex items-center gap-2 ${target===r.key?"bg-clinic-100 border-clinic-300 text-clinic-700":"bg-white border-ink-200 text-ink-700 hover:border-ink-300"}`}>
            <span className={`w-1.5 h-1.5 rounded-full ${r.level==="high"?"bg-risk-high":"bg-risk-mid"}`}/>
            {r.name} · {r.score}
          </button>
        ))}
      </div>

      <div className="grid grid-cols-3 gap-5">
        <div className="col-span-2 space-y-3">
          {adv.map((a,i)=>(
            <div key={i} className="card p-4 flex items-start gap-4">
              <div className="w-10 h-10 rounded-md bg-clinic-100 text-clinic-700 flex items-center justify-center flex-shrink-0">
                <Icon name={a.icon}/>
              </div>
              <div className="flex-1">
                <div className="flex items-center gap-2">
                  <Badge color="blue">{a.tier}</Badge>
                  <span className="text-[11px] text-ink-400 num">建议 #{String(i+1).padStart(2,"0")}</span>
                </div>
                <div className="text-base mt-2">{a.text}</div>
              </div>
            </div>
          ))}
        </div>

        <Card title="附近医疗资源" kicker="Nearby">
          <ul className="space-y-3">
            {[
              ["北京协和医院 内分泌科", "1.8 km · 三甲", "周二 / 周四 上午"],
              ["朝阳社区卫生服务中心", "0.4 km · 一级", "工作日 全天"],
              ["东直门社区口腔门诊", "1.1 km · 牙周专科", "周一至周六"],
            ].map(([n,m,h],i)=>(
              <li key={i} className="border-b last:border-0 border-ink-100 pb-3 last:pb-0">
                <div className="text-sm font-medium">{n}</div>
                <div className="text-xs text-ink-500 mt-0.5">{m}</div>
                <div className="text-[11px] num text-clinic-600 mt-1">{h}</div>
              </li>
            ))}
          </ul>
        </Card>
      </div>
    </div>
  );
};

// ---------- History ----------
const ScreenHistory = ({ nav }) => {
  return (
    <div className="fade-in space-y-6">
      <SectionHeader kicker="05 — History" title="历史趋势" sub="自 2025-08 起的 14 次检测记录。"/>

      <Card title="风险评分演变" kicker="6 Months" action={<Badge color="ink">每 14 天 1 次</Badge>}>
        <HistoryChart data={HISTORY}/>
      </Card>

      <Card title="检测记录列表" kicker="14 Logs">
        <table className="w-full text-sm">
          <thead>
            <tr className="text-left text-xs text-ink-500 border-b border-ink-100">
              <th className="py-2 font-medium">日期</th>
              <th className="font-medium">糖尿病</th>
              <th className="font-medium">心血管</th>
              <th className="font-medium">肾病</th>
              <th className="font-medium">贫血</th>
              <th className="font-medium">备注</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {HISTORY.slice().reverse().map((row,i)=>{
              const isLatest = i === 0;
              return (
                <tr key={i} className="border-b border-ink-100 last:border-0 hover:bg-ink-50">
                  <td className="py-3 num text-ink-700">{row.date} {isLatest && <Badge color="blue" className="ml-1">最新</Badge>}</td>
                  <td className="num text-risk-high font-medium">{row.dm}</td>
                  <td className="num text-risk-mid">{row.cv}</td>
                  <td className="num">{row.kd}</td>
                  <td className="num">{row.an}</td>
                  <td className="text-ink-500 text-xs">{isLatest ? "首次进入高风险区" : "—"}</td>
                  <td><Btn size="sm" variant="ghost" iconRight="chevron-right" onClick={()=>nav("results")}>查看</Btn></td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </Card>
    </div>
  );
};

// ---------- Profile ----------
const ScreenProfile = ({ nav }) => (
  <div className="fade-in space-y-6">
    <SectionHeader kicker="06 — Profile" title="个人档案" sub="档案信息用于个性化模型校准与建议生成。"/>

    <div className="grid grid-cols-3 gap-5">
      <Card title="基本信息" kicker="Identity">
        <div className="space-y-0">
          <KV k="姓名" v={PATIENT.name} mono={false}/>
          <KV k="昵称" v={PATIENT.nickname} mono={false}/>
          <KV k="性别 / 年龄" v={`${PATIENT.gender} · ${PATIENT.age} 岁`}/>
          <KV k="身高 / 体重" v={`${PATIENT.height} cm · ${PATIENT.weight} kg`}/>
          <KV k="BMI" v={`${PATIENT.bmi} (超重)`}/>
          <KV k="联系方式" v={PATIENT.phone}/>
          <KV k="档案编号" v="CS-2025-00142"/>
          <KV k="加入时间" v={PATIENT.enrolled}/>
        </div>
      </Card>

      <Card title="既往病史 & 用药" kicker="Medical">
        <div className="text-xs text-ink-500 mb-2">既往史</div>
        <ul className="space-y-1.5 text-sm">
          {PATIENT.history.map((h,i)=>(<li key={i} className="flex items-center gap-2"><Icon name="check" size={12} className="text-clinic-600"/>{h}</li>))}
        </ul>
        <div className="text-xs text-ink-500 mt-4 mb-2">长期用药</div>
        <ul className="space-y-1.5 text-sm">
          {PATIENT.meds.map((h,i)=>(<li key={i} className="flex items-center gap-2"><Icon name="droplet" size={12} className="text-clinic-600"/>{h}</li>))}
        </ul>
      </Card>

      <Card title="生活习惯" kicker="Lifestyle">
        <ul className="space-y-1.5 text-sm">
          {PATIENT.lifestyle.map((h,i)=>(<li key={i} className="flex items-center gap-2"><Icon name="warn" size={12} className="text-risk-mid"/>{h}</li>))}
        </ul>
        <div className="mt-4 pt-4 border-t border-ink-100">
          <div className="text-xs text-ink-500 mb-2">家庭医生</div>
          <div className="flex items-center gap-3">
            <div className="w-10 h-10 rounded-full bg-mint-100 border border-mint-200 flex items-center justify-center text-mint-700 font-semibold">陈</div>
            <div>
              <div className="text-sm font-medium">陈淑芬 医生</div>
              <div className="text-[11px] text-ink-500">朝阳社区卫生服务中心 · 内科</div>
            </div>
          </div>
        </div>
      </Card>
    </div>
  </div>
);

window.ScreensUser = { ScreenHome, ScreenCapture, ScreenResults, ScreenDetail, ScreenAdvice, ScreenHistory, ScreenProfile };

})();
