/* ============================================================
   Round 2 of gap-fill screens.

   5. Notifications inbox       — alerts/digests/grouped by type
   6. Verification playground   — paste a prompt + draft answer,
                                  see how the system would verify it
                                  in real time. The "wow" demo screen.
   7. Model registry            — which judges are wired up, calibration
                                  metrics, version pinning, shadow trials
   8. User profile + MFA        — personal-account page (your keys,
                                  sessions, MFA, recovery codes,
                                  signing key)
   9. Incident postmortem       — markdown-ish doc capturing what
                                  happened, with the trace, judges,
                                  source, timeline, and remediations.
   ============================================================ */

/* ---------- fixtures ---------- */

const NOTIFICATIONS = [
  { id: "n1", kind: "blocked", urgency: "high", time: "2 min ago", title: "Contradicted claim blocked", body: "Encounter Summary returned a beta-blocker dosing claim that inverts AHA guidance. Sent to Reviews.", trace: "af_pq3…hv6", actor: "System", read: false },
  { id: "n2", kind: "review", urgency: "high", time: "8 min ago", title: "Review assigned to you", body: "Mike Chen escalated rev_x3k…7yv. Reason: pediatric dosing — needs clinical sign-off.", trace: "rev_x3k…7yv", actor: "Mike Chen", read: false },
  { id: "n3", kind: "drift", urgency: "medium", time: "27 min ago", title: "Contradicted-rate trending up", body: "Encounter Summary contradicted-rate is 1.4% over the last hour, up from 0.9% yesterday. Above warning band.", trace: null, actor: "System", read: false },
  { id: "n4", kind: "policy", urgency: "low", time: "1h 02m ago", title: "Policy v7 published", body: "Mike Chen lowered the agreement threshold from 0.92 → 0.90 on \u201cClinical claims must cite FDA or AHA source\u201d.", trace: null, actor: "Mike Chen", read: true },
  { id: "n5", kind: "key", urgency: "medium", time: "3h 12m ago", title: "Production key rotated", body: "Old key af_live_x3k…7yv revoked. New prefix af_live_b9c…42p · grace window closes Oct 31.", trace: null, actor: "Priya Sharma", read: true },
  { id: "n6", kind: "audit", urgency: "low", time: "Yesterday · 17:31", title: "Auditor commented on AC-2", body: "\u201cAccess review is complete but the SAML break-glass account is missing from the export.\u201d", trace: null, actor: "Jordan Hayes (auditor)", read: true },
  { id: "n7", kind: "bulletin", urgency: "low", time: "Yesterday · 09:12", title: "Daily bulletin sealed", body: "Block #1,246 · 5,008 leaves · anchored to chain. Root af3c…91.", trace: null, actor: "System", read: true },
  { id: "n8", kind: "integration", urgency: "medium", time: "Oct 23 · 09:02", title: "Webhook disabled after 12 consecutive 5xx", body: "https://hooks.meridian.health/llm has been auto-paused. Re-enable from Settings → Webhooks.", trace: null, actor: "System", read: true },
  { id: "n9", kind: "calibration", urgency: "low", time: "Oct 22 · 14:00", title: "Judge calibration complete", body: "Lynx-8B v2.4 calibrated on N=4,212 labeled claims. Cohen's κ 0.92. Promoted to primary.", trace: null, actor: "System", read: true },
  { id: "n10", kind: "drift", urgency: "high", time: "Oct 20 · 03:14", title: "Sandbox region degraded", body: "us-east-1 judge endpoints had a 4-minute window of 18% timeouts. All recovered. 14 traces re-queued.", trace: null, actor: "System", read: true },
];

const NOTIF_META = {
  blocked:     { label: "Blocked", icon: "xCircle",       color: "var(--contra)" },
  review:      { label: "Review",  icon: "shieldCheck",   color: "var(--contra)" },
  drift:       { label: "Drift",   icon: "alertTriangle", color: "var(--partial)" },
  policy:      { label: "Policy",  icon: "fileCheck",     color: "var(--verified)" },
  key:         { label: "Keys",    icon: "key",           color: "var(--partial)" },
  audit:       { label: "Audit",   icon: "users",         color: "var(--ink-2)" },
  bulletin:    { label: "Bulletin",icon: "lock",          color: "var(--ink-2)" },
  integration: { label: "Webhook", icon: "webhook",       color: "var(--partial)" },
  calibration: { label: "Calibration", icon: "activity",  color: "var(--verified)" },
};

const MODELS_REGISTRY = [
  {
    id: "lynx-8b",
    name: "Lynx-8B",
    role: "Judge A · primary",
    provider: "Self-hosted · sandbox us-east-1",
    version: "2.4",
    pinned: "v2.4 (Oct 22)",
    status: "healthy",
    enabled: true,
    cohenKappa: 0.92,
    agreement: 0.94,
    calibrationN: 4212,
    p95: 412,
    cost: "—",
    sharePct: 100,
    lastCalibrated: "Oct 22, 2026",
    note: "Self-hosted Lynx fine-tune on Meridian-internal claim labels. Used as primary judge with deterministic rerank.",
    failovers: 0,
    trend: [0.88, 0.89, 0.91, 0.92, 0.92, 0.93, 0.92, 0.92, 0.93],
  },
  {
    id: "claude-35",
    name: "Claude 3.5 Sonnet",
    role: "Judge B",
    provider: "Anthropic",
    version: "claude-3-5-sonnet-20241022",
    pinned: "Oct 22, 2024 build",
    status: "healthy",
    enabled: true,
    cohenKappa: 0.89,
    agreement: 0.93,
    calibrationN: 4212,
    p95: 720,
    cost: "$0.003/call",
    sharePct: 100,
    lastCalibrated: "Oct 22, 2026",
    note: "Used as independent second opinion. Pinned to specific build; we audit drift weekly.",
    failovers: 2,
    trend: [0.87, 0.86, 0.88, 0.89, 0.89, 0.90, 0.89, 0.89, 0.89],
  },
  {
    id: "gemini-15",
    name: "Gemini Pro 1.5",
    role: "Judge C · tiebreaker",
    provider: "Google",
    version: "gemini-1.5-pro-002",
    pinned: "Oct 02, 2024 build",
    status: "degraded",
    enabled: true,
    cohenKappa: 0.84,
    agreement: 0.88,
    calibrationN: 4212,
    p95: 980,
    cost: "$0.0028/call",
    sharePct: 100,
    lastCalibrated: "Oct 14, 2026",
    note: "Tiebreaker when Lynx-8B and Claude disagree. Higher latency; we have a fast-path policy in draft to skip it for AHA-cited cardiology claims.",
    failovers: 8,
    trend: [0.82, 0.83, 0.84, 0.85, 0.84, 0.84, 0.83, 0.84, 0.84],
  },
  {
    id: "phi-4",
    name: "Phi-4 medical",
    role: "Shadow candidate",
    provider: "Self-hosted · sandbox us-east-1",
    version: "0.3.1-rc",
    pinned: "v0.3.1-rc (Oct 18)",
    status: "shadow",
    enabled: false,
    cohenKappa: 0.78,
    agreement: 0.84,
    calibrationN: 612,
    p95: 290,
    cost: "—",
    sharePct: 12,
    lastCalibrated: "Oct 18, 2026",
    note: "Running in shadow mode against 12% of live traffic. Decisions are scored but not applied. Promote at κ ≥ 0.85 over N ≥ 2,000.",
    failovers: 0,
    trend: [0.72, 0.74, 0.74, 0.76, 0.77, 0.78, 0.78, 0.77, 0.78],
  },
];

const INCIDENTS = [
  {
    id: "INC-2026-09",
    title: "Encounter Summary contradicted Discharge Plan on beta-blocker titration",
    severity: "sev2",
    status: "resolved",
    opened: "Oct 20, 2026 · 03:14 UTC",
    detected: "Oct 20, 2026 · 03:18 UTC",
    resolved: "Oct 20, 2026 · 09:55 UTC",
    duration: "6h 41m",
    ic: "Priya Sharma",
    apps: ["Encounter Summary", "Discharge Plan"],
    summary: "An update to the AHA/ACC source index caused 14 Encounter Summary drafts to claim rapid beta-blocker up-titration was acceptable. All 14 were caught by the verification chain and blocked at the API boundary; no contradicted answer reached clinical staff. Reviews queue handled the disposition within SLA. We disabled the affected index segment and rebuilt it from a verified snapshot.",
    blastRadius: { traces: 14, users: 9, claims: 17, sealed: true, reachedUsers: 0 },
    timeline: [
      { t: "03:14:02", kind: "system", body: "Drift detector flagged contradicted-rate spike on Encounter Summary (0.9% → 4.2% over 4 min)." },
      { t: "03:18:30", kind: "system", body: "Pager sent to on-call (Priya). Bulletin auto-paused for affected app." },
      { t: "03:32:11", kind: "human", actor: "Priya Sharma", body: "Confirmed contradicted answers all reference §7.3.3 of AHA/ACC 2024. Source index segment 4B/12 is suspect." },
      { t: "04:01:55", kind: "human", actor: "Priya Sharma", body: "Disabled source index segment 4B/12. New Encounter Summary calls fall back to v4.2 protocol citation only." },
      { t: "06:22:09", kind: "system", body: "Re-indexed segment 4B/12 from verified snapshot. Hash matches expected af3c…91." },
      { t: "07:14:48", kind: "system", body: "Replayed 14 affected traces through new index. All now verified or quarantined." },
      { t: "09:55:00", kind: "human", actor: "Priya Sharma", body: "Resolved. Postmortem opened." },
    ],
    rootCause: "A reindex job at 02:58 UTC was interrupted mid-batch by a sandbox restart. Segment 4B/12 was left in a partially-written state: the manifest claimed verified content, but ~12% of vectors pointed to the previous snapshot. Verification was unaffected (sources are read whole), but the embedding-side retrieval pulled stale spans for some queries — leading the LLM to over-confidently produce claims our judges then contradicted.",
    impact: "Zero contradicted output reached clinicians (the wrap caught all 14). Latency p95 on Encounter Summary rose from 1.4s to 2.6s for 14 minutes while the system re-routed. No HIPAA exposure (no PHI traversed an unwrapped path).",
    remediations: [
      { id: "r1", text: "Reindex jobs must complete or roll back atomically — implemented as a single manifest swap.", owner: "Mike Chen", due: "Oct 27", status: "done" },
      { id: "r2", text: "Sandbox restarts must drain re-index queue before proceeding (pre-empt drain).", owner: "Mike Chen", due: "Oct 28", status: "done" },
      { id: "r3", text: "Drift detector alarm fires within 60 seconds instead of 4 minutes.", owner: "Priya Sharma", due: "Nov 03", status: "in_progress" },
      { id: "r4", text: "Add canary cohort — 0.5% of traffic uses last-known-good index for 24h after every reindex.", owner: "Aisha Patel", due: "Nov 10", status: "in_progress" },
      { id: "r5", text: "Run game-day on the same failure mode quarterly.", owner: "Priya Sharma", due: "Q1 2027", status: "pending" },
    ],
    related: [{ id: "af_x3k…7yv", desc: "First contradicted trace" }, { id: "af_5bp…ku9", desc: "Second contradicted trace" }, { id: "rev_x3k…7yv", desc: "Review record" }],
  },
];

/* ============================================================
   NOTIFICATIONS INBOX
   ============================================================ */

const NotificationsInbox = ({ pushToast, onOpenTrace }) => {
  const [filter, setFilter] = React.useState("all");
  const [items, setItems] = React.useState(NOTIFICATIONS);
  const [selectedId, setSelectedId] = React.useState(NOTIFICATIONS[0].id);

  const unread = items.filter((i) => !i.read).length;
  const visible = items.filter((i) => filter === "all" ? true : filter === "unread" ? !i.read : i.kind === filter);
  const selected = items.find((i) => i.id === selectedId) || visible[0];

  const markRead = (id) => setItems((prev) => prev.map((it) => it.id === id ? { ...it, read: true } : it));
  const markAllRead = () => { setItems((prev) => prev.map((it) => ({ ...it, read: true }))); pushToast && pushToast({ kind: "success", title: "All notifications marked as read" }); };

  return (
    <>
      <header className="page-header">
        <div className="page-header__inner">
          <div className="page-header__eyebrow">Inbox</div>
          <h1>Notifications<span className="inbox-count">{unread > 0 ? unread : ""}</span></h1>
          <p className="page-header__sub">
            Operational alerts, audit threads, and digests — grouped by category, persisted for 90 days, and exportable on demand.
          </p>
        </div>
        <div className="page-actions">
          <Button variant="ghost" size="sm" icon={window.Icon.checkSimple({ size: 13 })} onClick={markAllRead} disabled={unread === 0}>Mark all read</Button>
          <Button variant="secondary" size="sm" icon={window.Icon.settings({ size: 13 })}>Preferences</Button>
        </div>
      </header>

      <div className="inbox-layout">
        <aside className="inbox-side">
          <div className="inbox-side__head">Categories</div>
          <button className={`inbox-cat ${filter === "all" ? "inbox-cat--active" : ""}`} onClick={() => setFilter("all")}>
            <span className="inbox-cat__label">All</span>
            <span className="inbox-cat__count mono tabular">{items.length}</span>
          </button>
          <button className={`inbox-cat ${filter === "unread" ? "inbox-cat--active" : ""}`} onClick={() => setFilter("unread")}>
            <span className="inbox-cat__label inbox-cat__label--bold">Unread</span>
            <span className="inbox-cat__count mono tabular">{unread}</span>
          </button>
          <div className="inbox-side__sep" />
          {Object.entries(NOTIF_META).map(([k, m]) => {
            const count = items.filter((i) => i.kind === k).length;
            if (!count) return null;
            return (
              <button key={k} className={`inbox-cat ${filter === k ? "inbox-cat--active" : ""}`} onClick={() => setFilter(k)}>
                <span className="inbox-cat__icon" style={{ color: m.color }}>{window.Icon[m.icon]({ size: 13 })}</span>
                <span className="inbox-cat__label">{m.label}</span>
                <span className="inbox-cat__count mono tabular">{count}</span>
              </button>
            );
          })}
          <div className="inbox-side__sep" />
          <div className="inbox-side__head">Delivery</div>
          <button className="inbox-cat inbox-cat--row">
            <span className="text-sm">Email digest</span>
            <span className="text-xs muted">daily 8:00</span>
          </button>
          <button className="inbox-cat inbox-cat--row">
            <span className="text-sm">Slack</span>
            <span className="text-xs muted">high only</span>
          </button>
          <button className="inbox-cat inbox-cat--row">
            <span className="text-sm">PagerDuty</span>
            <span className="text-xs muted">sev1 + sev2</span>
          </button>
        </aside>

        <section className="inbox-list">
          {visible.length === 0 ? (
            <div className="inbox-empty">
              <div className="inbox-empty__icon">{window.Icon.checkSimple({ size: 28 })}</div>
              <h3>Inbox zero</h3>
              <p className="text-sm muted">Nothing in this category.</p>
            </div>
          ) : visible.map((n) => {
            const m = NOTIF_META[n.kind] || { label: n.kind, icon: "shield", color: "var(--ink-3)" };
            return (
              <button key={n.id}
                className={`inbox-row ${selectedId === n.id ? "inbox-row--active" : ""} ${n.read ? "inbox-row--read" : ""}`}
                onClick={() => { setSelectedId(n.id); markRead(n.id); }}>
                <span className="inbox-row__dot" data-read={n.read} />
                <span className="inbox-row__icon" style={{ color: m.color }}>{window.Icon[m.icon]({ size: 14 })}</span>
                <span className="inbox-row__main">
                  <span className="inbox-row__title">{n.title}</span>
                  <span className="inbox-row__body">{n.body}</span>
                  <span className="inbox-row__meta">
                    <span className={`urgency-pill urgency-pill--${n.urgency}`}>{n.urgency}</span>
                    <span className="text-xs muted">· {n.actor}</span>
                    {n.trace && <span className="mono text-xs muted">· {n.trace}</span>}
                  </span>
                </span>
                <span className="inbox-row__time text-xs muted">{n.time}</span>
              </button>
            );
          })}
        </section>

        <aside className="inbox-detail">
          {selected ? (
            <>
              <div className="inbox-detail__head">
                <div className="row gap-2" style={{ alignItems: "center" }}>
                  <span style={{ color: NOTIF_META[selected.kind]?.color || "var(--ink-3)" }}>
                    {window.Icon[NOTIF_META[selected.kind]?.icon || "shield"]({ size: 16 })}
                  </span>
                  <span className="text-xs muted mono" style={{ letterSpacing: "0.06em", textTransform: "uppercase" }}>{NOTIF_META[selected.kind]?.label || selected.kind}</span>
                  <span className={`urgency-pill urgency-pill--${selected.urgency}`}>{selected.urgency}</span>
                </div>
                <h2 className="inbox-detail__title">{selected.title}</h2>
                <div className="text-xs muted" style={{ marginTop: 2 }}>{selected.time} · from <strong>{selected.actor}</strong></div>
              </div>
              <p className="inbox-detail__body">{selected.body}</p>
              {selected.trace && (
                <div className="inbox-detail__panel">
                  <div className="text-xs muted mono" style={{ letterSpacing: "0.06em", textTransform: "uppercase", marginBottom: 6 }}>Linked record</div>
                  <div className="row gap-2" style={{ alignItems: "center" }}>
                    <HashChip value={selected.trace} short={selected.trace} />
                    <Button variant="ghost" size="sm" icon={window.Icon.arrowRight({ size: 13 })} onClick={() => onOpenTrace && onOpenTrace(selected.trace)}>Open</Button>
                  </div>
                </div>
              )}
              <div className="inbox-detail__actions">
                <Button variant="secondary" size="sm" icon={window.Icon.checkSimple({ size: 13 })}>Mark resolved</Button>
                <Button variant="ghost" size="sm" icon={window.Icon.share({ size: 13 })}>Forward</Button>
                <Button variant="ghost" size="sm" icon={window.Icon.x({ size: 13 })}>Snooze 1h</Button>
              </div>
            </>
          ) : (
            <div className="inbox-empty">
              <div className="inbox-empty__icon">{window.Icon.bell({ size: 28 })}</div>
              <h3>Pick a notification</h3>
            </div>
          )}
        </aside>
      </div>
    </>
  );
};

/* ============================================================
   VERIFICATION PLAYGROUND
   ============================================================ */

const PLAYGROUND_PROMPT = "What's the recommended approach to initiating beta-blockers in a newly diagnosed HFrEF patient with LVEF 28%?";
const PLAYGROUND_DRAFT_BAD = "For newly diagnosed HFrEF patients, beta-blockers should be initiated at the maximum tolerated dose on day one to achieve rapid heart-rate control. Continue ACE inhibitors at standard dosing.";
const PLAYGROUND_DRAFT_GOOD = "For newly diagnosed HFrEF patients with LVEF ≤40%, initiate a guideline-recommended beta-blocker (e.g., carvedilol or metoprolol succinate) at a low starting dose. Titrate to target doses over weeks to months, monitoring heart rate, blood pressure, and signs of decompensation at each step. Initiate or continue an ACEi or ARNI in parallel unless contraindicated.";

const VerificationPlayground = ({ pushToast }) => {
  const [prompt, setPrompt] = React.useState(PLAYGROUND_PROMPT);
  const [draft, setDraft] = React.useState(PLAYGROUND_DRAFT_BAD);
  const [policy, setPolicy] = React.useState("p_clinical_cite");
  const [judgeCount, setJudgeCount] = React.useState(3);
  const [phase, setPhase] = React.useState("idle"); // idle | redacting | extracting | judging | done
  const [progress, setProgress] = React.useState(0);
  const [showResults, setShowResults] = React.useState(true);

  // Mock extracted claims by heuristic — count sentences and synthesize ratings
  const claims = React.useMemo(() => {
    const isBad = draft.includes("maximum tolerated dose on day one") || draft.includes("immediately") || draft.includes("rapid heart-rate");
    if (isBad) {
      return [
        { idx: 1, text: "Beta-blockers should be initiated at the maximum tolerated dose on day one", verdict: "contradicted", source: "AHA/ACC HF 2024 §7.3.3", score: 96, quote: "Beta-blockers in HFrEF should be initiated at low doses and titrated to target doses over weeks to months. Rapid up-titration is not recommended and may precipitate decompensation." },
        { idx: 2, text: "To achieve rapid heart-rate control", verdict: "unverif", source: null, score: 0, quote: null },
        { idx: 3, text: "Continue ACE inhibitors at standard dosing", verdict: "partial", source: "AHA/ACC HF 2024 §7.3.1", score: 71, quote: "An ACEi (or ARB if intolerant) or ARNI is recommended; specific dosing is patient-specific." },
      ];
    } else {
      return [
        { idx: 1, text: "Initiate a guideline-recommended beta-blocker at a low starting dose", verdict: "verified", source: "AHA/ACC HF 2024 §7.3.3", score: 94, quote: "Beta-blockers should be initiated at low doses and titrated to target doses over weeks to months." },
        { idx: 2, text: "Titrate to target doses over weeks to months, monitoring at each step", verdict: "verified", source: "AHA/ACC HF 2024 §7.3.3", score: 96, quote: "Up-titrate at intervals appropriate to clinical status, typically every 2–4 weeks." },
        { idx: 3, text: "Initiate or continue an ACEi or ARNI in parallel unless contraindicated", verdict: "verified", source: "AHA/ACC HF 2024 §7.3.1", score: 92, quote: "An ACEi (or ARB if intolerant) or ARNI is recommended to reduce morbidity and mortality." },
      ];
    }
  }, [draft]);

  const overall = (() => {
    if (claims.some((c) => c.verdict === "contradicted")) return "contradicted";
    if (claims.some((c) => c.verdict === "partial")) return "partial";
    if (claims.some((c) => c.verdict === "unverif")) return "unverif";
    return "verified";
  })();

  const run = () => {
    setShowResults(false);
    setPhase("redacting");
    setProgress(8);
    const steps = [
      [600, () => { setPhase("redacting"); setProgress(22); }],
      [900, () => { setPhase("extracting"); setProgress(46); }],
      [1300, () => { setPhase("judging"); setProgress(78); }],
      [1900, () => { setPhase("done"); setProgress(100); setShowResults(true); }],
    ];
    steps.forEach(([ms, fn]) => setTimeout(fn, ms));
  };

  const phaseLabel = { idle: "Idle", redacting: "Redacting PHI", extracting: "Extracting claims", judging: "Running 3 judges", done: "Sealed" };

  return (
    <>
      <header className="page-header">
        <div className="page-header__inner">
          <div className="page-header__eyebrow">Operations · sandbox</div>
          <h1>Verification playground</h1>
          <p className="page-header__sub">
            Paste a prompt and a draft answer. See exactly how the verification chain would respond — claims extracted, sources fetched, judges scored, verdicts assigned. Nothing here is billed or sealed.
          </p>
        </div>
        <div className="page-actions">
          <Button variant="secondary" size="sm" icon={window.Icon.fileText({ size: 13 })}>Save scenario</Button>
          <Button variant="secondary" size="sm" icon={window.Icon.replay({ size: 13 })} onClick={() => { setDraft(PLAYGROUND_DRAFT_BAD); setPhase("idle"); setShowResults(true); }}>Load contradicted example</Button>
        </div>
      </header>

      <div className="pg-layout">
        <div className="pg-input">
          <div className="pg-config">
            <div className="pg-config__row">
              <span className="text-xs muted mono pg-config__key">POLICY</span>
              <select className="activity-select" value={policy} onChange={(e) => setPolicy(e.target.value)}>
                <option value="p_clinical_cite">Clinical claims must cite FDA or AHA source · v7</option>
                <option value="p_pedi_unanimous">Pediatric · unanimous 3-judge agreement</option>
                <option value="p_block_contradiction">Block on contradiction (default)</option>
              </select>
            </div>
            <div className="pg-config__row">
              <span className="text-xs muted mono pg-config__key">JUDGES</span>
              <div className="seg">
                {[1, 2, 3].map((n) => (
                  <button key={n} className={`seg__btn ${judgeCount === n ? "seg__btn--active" : ""}`} onClick={() => setJudgeCount(n)}>{n}</button>
                ))}
              </div>
              <span className="text-xs muted">Lynx-8B, Claude 3.5, Gemini Pro 1.5</span>
            </div>
          </div>

          <div className="pg-block">
            <div className="pg-block__head">
              <span className="text-xs muted mono">USER PROMPT</span>
              <span className="text-xs muted">{prompt.length} chars</span>
            </div>
            <textarea className="pg-textarea" value={prompt} onChange={(e) => setPrompt(e.target.value)} rows={3} />
          </div>

          <div className="pg-block">
            <div className="pg-block__head">
              <span className="text-xs muted mono">DRAFT LLM ANSWER</span>
              <div className="row gap-1">
                <button className="pg-link" onClick={() => setDraft(PLAYGROUND_DRAFT_BAD)}>Bad example</button>
                <span className="text-xs muted">·</span>
                <button className="pg-link" onClick={() => setDraft(PLAYGROUND_DRAFT_GOOD)}>Good example</button>
              </div>
            </div>
            <textarea className="pg-textarea pg-textarea--tall" value={draft} onChange={(e) => setDraft(e.target.value)} rows={7} />
          </div>

          <div className="pg-run">
            <Button variant="primary" size="lg" icon={window.Icon.zap({ size: 14 })} onClick={run} disabled={phase !== "idle" && phase !== "done"}>
              {phase === "done" ? "Run again" : phase === "idle" ? "Verify" : "Verifying…"}
            </Button>
            <span className="text-xs muted">Estimate · ~1.8s · ~$0.012 · not billed</span>
          </div>
        </div>

        <div className="pg-output">
          <div className="pg-output__head">
            <div className="row gap-2" style={{ alignItems: "center" }}>
              <span className="text-xs muted mono" style={{ letterSpacing: "0.06em", textTransform: "uppercase" }}>Pipeline · {phaseLabel[phase]}</span>
              <span className={`pg-phase-dot pg-phase-dot--${phase === "idle" ? "idle" : phase === "done" ? "done" : "run"}`} />
            </div>
            <div className="pg-progress"><div className="pg-progress__fill" style={{ width: `${progress}%` }} /></div>
          </div>

          <div className="pg-stages">
            <PGStage label="Redact PHI" done={progress >= 22} sub="4 identifiers found" />
            <PGStage label="Extract claims" done={progress >= 46} sub={`${claims.length} extracted`} />
            <PGStage label="Verify" done={progress >= 78} sub={`${judgeCount} judges · ${claims.length} claims`} />
            <PGStage label="Seal" done={progress >= 100} sub="Ed25519 · bulletin pending" />
          </div>

          {showResults && (
            <>
              <div className={`pg-verdict pg-verdict--${overall}`}>
                <div className="pg-verdict__icon">
                  {window.Icon[VERDICT[overall].iconName]({ size: 20 })}
                </div>
                <div>
                  <div className="text-xs muted mono" style={{ letterSpacing: "0.06em", textTransform: "uppercase" }}>Overall verdict</div>
                  <div className="pg-verdict__title">{VERDICT[overall].label}</div>
                  <div className="text-sm muted" style={{ marginTop: 2 }}>
                    {overall === "verified" ? "All claims independently corroborated by registered sources." :
                     overall === "contradicted" ? "At least one claim is contradicted by a registered source. Policy would block." :
                     overall === "partial" ? "Some claims have only weak corroboration. Routed to review." :
                     "Claims cannot be verified against any registered source. Warned and sealed."}
                  </div>
                </div>
                <span className="spacer" />
                <Button variant="secondary" size="sm" icon={window.Icon.share({ size: 13 })}>Share scenario</Button>
              </div>

              <div className="pg-claims">
                {claims.map((c) => (
                  <div key={c.idx} className={`pg-claim pg-claim--${c.verdict}`}>
                    <div className="pg-claim__head">
                      <span className="pg-claim__idx mono">{String(c.idx).padStart(2, "0")}</span>
                      <Verdict kind={c.verdict === "contradicted" ? "contradicted" : c.verdict} />
                      {c.source && <span className="text-xs muted">· source score <span className="mono tabular fw-600" style={{ color: "var(--ink-1)" }}>{c.score}</span></span>}
                    </div>
                    <div className="pg-claim__text">{c.text}</div>
                    {c.source ? (
                      <div className="pg-claim__source">
                        <div className="text-xs muted">SOURCE · {c.source}</div>
                        <blockquote className="pg-quote">
                          <span className={`pg-quote__rule pg-quote__rule--${c.verdict}`} />
                          {c.quote}
                        </blockquote>
                      </div>
                    ) : (
                      <div className="pg-claim__source pg-claim__source--empty">
                        No registered source matched this claim.
                      </div>
                    )}
                  </div>
                ))}
              </div>
            </>
          )}
        </div>
      </div>
    </>
  );
};

const PGStage = ({ label, done, sub }) => (
  <div className={`pg-stage ${done ? "pg-stage--done" : ""}`}>
    <span className="pg-stage__check">
      {done ? window.Icon.checkSimple({ size: 11 }) : <span className="pg-stage__pulse" />}
    </span>
    <div>
      <div className="pg-stage__label">{label}</div>
      <div className="pg-stage__sub text-xs muted">{sub}</div>
    </div>
  </div>
);

/* ============================================================
   MODEL REGISTRY
   ============================================================ */

const ModelRegistry = ({ pushToast }) => {
  const [selectedId, setSelectedId] = React.useState(MODELS_REGISTRY[0].id);
  const selected = MODELS_REGISTRY.find((m) => m.id === selectedId);

  return (
    <>
      <header className="page-header">
        <div className="page-header__inner">
          <div className="page-header__eyebrow">Operations · model registry</div>
          <h1>Judges &amp; models</h1>
          <p className="page-header__sub">
            The independent verifiers wired into the chain. Each is pinned to a build, calibrated against your labeled set, and rotated only with explicit sign-off. Shadow candidates run in parallel without affecting outcomes.
          </p>
        </div>
        <div className="page-actions">
          <Button variant="secondary" size="sm" icon={window.Icon.fileText({ size: 13 })}>Calibration log</Button>
          <Button variant="primary" size="sm" icon={window.Icon.plus({ size: 13 })}>Add candidate</Button>
        </div>
      </header>

      <div className="reg-strip">
        <div className="reg-strip__cell">
          <div className="text-xs muted mono" style={{ letterSpacing: "0.06em", textTransform: "uppercase" }}>Active</div>
          <div className="reg-strip__value">3<span className="reg-strip__unit">judges</span></div>
        </div>
        <div className="reg-strip__cell">
          <div className="text-xs muted mono" style={{ letterSpacing: "0.06em", textTransform: "uppercase" }}>Cohen's κ · ensemble</div>
          <div className="reg-strip__value reg-strip__value--ok">0.92</div>
          <div className="text-xs muted">strong calibrated agreement</div>
        </div>
        <div className="reg-strip__cell">
          <div className="text-xs muted mono" style={{ letterSpacing: "0.06em", textTransform: "uppercase" }}>Shadow trials</div>
          <div className="reg-strip__value">1</div>
          <div className="text-xs muted">Phi-4 medical · 12% traffic</div>
        </div>
        <div className="reg-strip__cell">
          <div className="text-xs muted mono" style={{ letterSpacing: "0.06em", textTransform: "uppercase" }}>Last calibration</div>
          <div className="reg-strip__value reg-strip__value--mono">Oct 22</div>
          <div className="text-xs muted">N=4,212 · expires Nov 22</div>
        </div>
      </div>

      <div className="reg-layout">
        <aside className="reg-list">
          {MODELS_REGISTRY.map((m) => (
            <button key={m.id}
              className={`reg-card ${selectedId === m.id ? "reg-card--active" : ""}`}
              onClick={() => setSelectedId(m.id)}>
              <div className="reg-card__head">
                <div>
                  <div className="reg-card__name">{m.name}</div>
                  <div className="text-xs muted mono">{m.role}</div>
                </div>
                <span className={`reg-status reg-status--${m.status}`}>
                  <span className="reg-status__dot" />
                  {m.status}
                </span>
              </div>
              <div className="reg-card__metrics">
                <span><span className="muted text-xs">κ</span> <span className="mono tabular fw-600">{m.cohenKappa.toFixed(2)}</span></span>
                <span><span className="muted text-xs">p95</span> <span className="mono tabular fw-600">{m.p95}ms</span></span>
                <span><span className="muted text-xs">share</span> <span className="mono tabular fw-600">{m.sharePct}%</span></span>
              </div>
              <Sparkline values={m.trend} color="var(--ink-2)" w={140} h={20} />
            </button>
          ))}
        </aside>

        <section className="reg-detail">
          <div className="reg-detail__head">
            <div>
              <div className="text-xs muted mono" style={{ letterSpacing: "0.06em", textTransform: "uppercase" }}>{selected.role}</div>
              <h2 className="reg-detail__title"><em>{selected.name}</em></h2>
              <div className="text-sm muted" style={{ marginTop: 6 }}>{selected.note}</div>
            </div>
            <span className={`reg-status reg-status--${selected.status} reg-status--lg`}>
              <span className="reg-status__dot" />
              {selected.status}
            </span>
          </div>

          <div className="reg-grid">
            <RegField label="Provider" value={selected.provider} mono />
            <RegField label="Version" value={selected.version} mono />
            <RegField label="Pinned" value={selected.pinned} mono />
            <RegField label="Failovers · 30d" value={selected.failovers.toString()} mono ok={selected.failovers <= 2} />
            <RegField label="p95 latency" value={`${selected.p95}ms`} mono />
            <RegField label="Cost" value={selected.cost} mono />
          </div>

          <div className="reg-section">
            <div className="reg-section__head">
              <h3>Calibration</h3>
              <span className="text-xs muted">last run {selected.lastCalibrated} · N={selected.calibrationN.toLocaleString()}</span>
            </div>
            <div className="reg-calib">
              <div className="reg-calib__metric">
                <div className="reg-calib__label">Cohen's κ</div>
                <div className="reg-calib__value mono">{selected.cohenKappa.toFixed(2)}</div>
                <div className="reg-calib__bar"><div className="reg-calib__fill" style={{ width: `${selected.cohenKappa * 100}%`, background: selected.cohenKappa >= 0.85 ? "var(--verified)" : selected.cohenKappa >= 0.75 ? "var(--partial)" : "var(--contra)" }} /></div>
                <div className="text-xs muted">{selected.cohenKappa >= 0.85 ? "Strong" : selected.cohenKappa >= 0.75 ? "Substantial" : "Below promotion bar"}</div>
              </div>
              <div className="reg-calib__metric">
                <div className="reg-calib__label">Raw agreement vs ensemble</div>
                <div className="reg-calib__value mono">{(selected.agreement * 100).toFixed(1)}%</div>
                <div className="reg-calib__bar"><div className="reg-calib__fill" style={{ width: `${selected.agreement * 100}%`, background: "var(--ink-1)" }} /></div>
                <div className="text-xs muted">across {selected.calibrationN.toLocaleString()} labeled claims</div>
              </div>
            </div>
          </div>

          <div className="reg-section">
            <div className="reg-section__head">
              <h3>κ trend · last 9 calibrations</h3>
              <span className="text-xs muted">monthly cadence</span>
            </div>
            <Sparkline values={selected.trend} color="var(--ink-1)" w={520} h={56} />
          </div>

          <div className="reg-foot">
            <Button variant="ghost" size="sm" icon={window.Icon.fileText({ size: 13 })}>View calibration set</Button>
            <span className="spacer" />
            {selected.status === "shadow" ? (
              <>
                <Button variant="secondary" size="sm">Pause shadow</Button>
                <Button variant="primary" size="sm" disabled={selected.cohenKappa < 0.85}>Promote</Button>
              </>
            ) : (
              <>
                <Button variant="ghost" size="sm" icon={window.Icon.replay({ size: 13 })}>Recalibrate</Button>
                <Button variant="secondary" size="sm">Pin new build</Button>
                <Button variant="destructive" size="sm" icon={window.Icon.xCircle({ size: 13 })}>Disable judge</Button>
              </>
            )}
          </div>
        </section>
      </div>
    </>
  );
};

const RegField = ({ label, value, mono, ok }) => (
  <div className="reg-field">
    <div className="text-xs muted mono" style={{ letterSpacing: "0.06em", textTransform: "uppercase" }}>{label}</div>
    <div className={`reg-field__val ${mono ? "mono" : ""}`} style={{ color: ok === false ? "var(--partial)" : "var(--ink-1)" }}>{value}</div>
  </div>
);

/* ============================================================
   USER PROFILE + MFA
   ============================================================ */

const UserProfile = ({ pushToast }) => {
  const [tab, setTab] = React.useState("profile");
  return (
    <>
      <header className="page-header">
        <div className="page-header__inner">
          <div className="page-header__eyebrow">Your account</div>
          <h1>Profile &amp; security</h1>
          <p className="page-header__sub">
            Personal account — distinct from the workspace. Your MFA, signing key, and active sessions live here.
          </p>
        </div>
      </header>

      <Tabs
        items={[
          { value: "profile", label: "Profile" },
          { value: "security", label: "Security · MFA" },
          { value: "sessions", label: "Active sessions" },
          { value: "keys", label: "Personal access tokens" },
          { value: "signing", label: "Signing key" },
        ]}
        value={tab}
        onChange={setTab}
      />

      {tab === "profile" && <ProfileBasics />}
      {tab === "security" && <ProfileSecurity pushToast={pushToast} />}
      {tab === "sessions" && <ProfileSessions />}
      {tab === "keys" && <ProfilePATs pushToast={pushToast} />}
      {tab === "signing" && <ProfileSigning pushToast={pushToast} />}
    </>
  );
};

const ProfileBasics = () => (
  <div className="profile-grid">
    <div className="card card--padded profile-card">
      <div className="profile-head">
        <div className="profile-avatar">PS</div>
        <div>
          <div className="profile-name">Priya Sharma</div>
          <div className="text-sm muted">Director, AI Risk · Meridian Health Network</div>
          <div className="text-xs muted mono" style={{ marginTop: 4 }}>priya@meridian.health</div>
        </div>
        <span className="spacer" />
        <Button variant="secondary" size="sm">Edit</Button>
      </div>
      <div className="profile-fields">
        <Field label="Display name"><input className="input" defaultValue="Priya Sharma" /></Field>
        <Field label="Role" hint="Workspace role; ask an admin to change."><input className="input" defaultValue="Director, AI Risk" disabled /></Field>
        <Field label="Timezone"><select className="input"><option>America/New_York (ET)</option><option>America/Los_Angeles</option><option>Europe/London</option><option>UTC</option></select></Field>
        <Field label="Locale"><select className="input"><option>English (US)</option><option>English (UK)</option></select></Field>
      </div>
    </div>

    <div className="profile-side">
      <div className="card card--padded">
        <div className="text-xs muted mono" style={{ letterSpacing: "0.06em", textTransform: "uppercase" }}>Workspace</div>
        <div style={{ fontFamily: "var(--font-display)", fontStyle: "italic", fontSize: 24, marginTop: 6 }}>Meridian Health Network</div>
        <div className="text-sm muted">HIPAA · Healthcare · Growth plan</div>
        <div className="text-xs muted" style={{ marginTop: 8 }}>Joined Aug 12, 2026 · admin</div>
        <Button variant="ghost" size="sm" iconRight={window.Icon.chevronDown({ size: 12 })} style={{ marginTop: 12 }}>Switch workspace</Button>
      </div>
      <div className="card card--padded">
        <div className="text-xs muted mono" style={{ letterSpacing: "0.06em", textTransform: "uppercase" }}>Activity · 30d</div>
        <div className="profile-stats">
          <div><div className="mono tabular fw-600" style={{ fontSize: 20 }}>1,284</div><div className="text-xs muted">traces opened</div></div>
          <div><div className="mono tabular fw-600" style={{ fontSize: 20 }}>87</div><div className="text-xs muted">reviews handled</div></div>
          <div><div className="mono tabular fw-600" style={{ fontSize: 20 }}>4</div><div className="text-xs muted">policies edited</div></div>
          <div><div className="mono tabular fw-600" style={{ fontSize: 20 }}>2</div><div className="text-xs muted">packs sealed</div></div>
        </div>
      </div>
    </div>
  </div>
);

const ProfileSecurity = ({ pushToast }) => (
  <div className="col gap-5">
    <div className="card card--padded">
      <div className="row gap-3" style={{ alignItems: "flex-start" }}>
        <div className="profile-mfa-icon">{window.Icon.shieldCheck({ size: 22 })}</div>
        <div style={{ flex: 1 }}>
          <h3 className="profile-section-title">Two-factor authentication</h3>
          <div className="text-sm muted">Required for your role. You currently use a hardware security key as primary and TOTP as backup.</div>
        </div>
        <Badge tone="sealed" icon={window.Icon.checkSimple({ size: 11 })}>Active</Badge>
      </div>
      <div className="mfa-list">
        <div className="mfa-row">
          <div className="mfa-row__icon">{window.Icon.key({ size: 16 })}</div>
          <div className="mfa-row__body">
            <div className="fw-500">YubiKey 5C NFC</div>
            <div className="text-xs muted">Primary · added Sep 04 · last used 2 min ago</div>
          </div>
          <Button variant="ghost" size="sm">Manage</Button>
        </div>
        <div className="mfa-row">
          <div className="mfa-row__icon">{window.Icon.zap({ size: 16 })}</div>
          <div className="mfa-row__body">
            <div className="fw-500">Authenticator app · 1Password</div>
            <div className="text-xs muted">Backup · added Aug 12 · TOTP</div>
          </div>
          <Button variant="ghost" size="sm">Manage</Button>
        </div>
        <div className="mfa-row mfa-row--add">
          <div className="mfa-row__icon">{window.Icon.plus({ size: 14 })}</div>
          <div className="mfa-row__body">
            <div className="fw-500">Add a passkey</div>
            <div className="text-xs muted">Sign in with Face ID, Touch ID, or Windows Hello</div>
          </div>
          <Button variant="secondary" size="sm">Add</Button>
        </div>
      </div>
    </div>

    <div className="card card--padded">
      <div className="row gap-3" style={{ justifyContent: "space-between", alignItems: "flex-start" }}>
        <div>
          <h3 className="profile-section-title">Recovery codes</h3>
          <div className="text-sm muted">10 one-time codes — generated Sep 04. 9 unused. Store them somewhere safe; we'll never show them again.</div>
        </div>
        <Button variant="secondary" size="sm" icon={window.Icon.replay({ size: 13 })} onClick={() => pushToast && pushToast({ kind: "warn", title: "Confirm — regenerate codes?", sub: "This invalidates all 10 existing codes." })}>Regenerate</Button>
      </div>
      <div className="recovery-grid">
        {["x3k2-qz9a-8mn4","lp2r-t7yv-WERr","af3c-91b9-c4d2","7afe-102d-11c8","44b1-aa97-ee03","3d8f-0b22-9a17","b2e9-71fa-MJ02","afnq-9912-pp00","wkj2-8821-ck72","jx2e-bb12-dt03"].map((c, i) => (
          <div key={i} className={`recovery-code ${i === 0 ? "recovery-code--used" : ""}`}>
            <span className="mono">{c}</span>
            {i === 0 && <span className="text-xs muted">· used Sep 18</span>}
          </div>
        ))}
      </div>
    </div>

    <div className="card card--padded">
      <h3 className="profile-section-title">Password</h3>
      <div className="text-sm muted">Last changed 47 days ago. Workspace policy requires rotation every 90 days for admins.</div>
      <div className="row gap-2" style={{ marginTop: 12 }}>
        <Button variant="secondary" size="sm">Change password</Button>
        <Button variant="ghost" size="sm">View password policy</Button>
      </div>
    </div>
  </div>
);

const ProfileSessions = () => (
  <Card title="Active sessions" padded={false}
    action={<Button variant="destructive" size="sm" icon={window.Icon.xCircle({ size: 12 })}>Sign out everywhere else</Button>}>
    <table className="table">
      <thead><tr><th>Device</th><th>Location</th><th>IP</th><th>Last active</th><th></th></tr></thead>
      <tbody>
        <tr>
          <td>
            <div className="row gap-2"><span style={{ color: "var(--ink-2)" }}>{window.Icon.cpu({ size: 14 })}</span><div><div className="fw-500">MacBook Pro · Safari 18</div><div className="text-xs muted">This session</div></div></div>
          </td>
          <td className="text-sm">Brooklyn, NY · US</td>
          <td className="mono text-sm">10.4.2.18</td>
          <td className="text-sm muted">Now</td>
          <td><Badge tone="sealed" icon={window.Icon.checkSimple({ size: 11 })}>Current</Badge></td>
        </tr>
        <tr>
          <td><div className="row gap-2"><span style={{ color: "var(--ink-2)" }}>{window.Icon.cpu({ size: 14 })}</span><div><div className="fw-500">iPhone 15 Pro · Safari</div></div></div></td>
          <td className="text-sm">Brooklyn, NY · US</td>
          <td className="mono text-sm">10.4.2.92</td>
          <td className="text-sm muted">2 hours ago</td>
          <td><Button variant="ghost" size="sm">Sign out</Button></td>
        </tr>
        <tr>
          <td><div className="row gap-2"><span style={{ color: "var(--ink-2)" }}>{window.Icon.cpu({ size: 14 })}</span><div><div className="fw-500">Linux desktop · Firefox</div></div></div></td>
          <td className="text-sm">Manhattan, NY · US</td>
          <td className="mono text-sm">10.4.7.42</td>
          <td className="text-sm muted">Yesterday</td>
          <td><Button variant="ghost" size="sm">Sign out</Button></td>
        </tr>
      </tbody>
    </table>
  </Card>
);

const ProfilePATs = ({ pushToast }) => (
  <Card title="Personal access tokens" padded={false}
    action={<Button variant="primary" size="sm" icon={window.Icon.plus({ size: 12 })} onClick={() => pushToast && pushToast({ kind: "success", title: "Token generated", sub: "Stored locally; you won't see it again." })}>New token</Button>}>
    <div style={{ padding: "16px 20px", borderBottom: "1px solid var(--rule)", background: "var(--paper-alt)" }}>
      <div className="text-sm">Use personal tokens to script against your workspace from the terminal or notebooks. They inherit your permissions — never share them.</div>
    </div>
    <table className="table">
      <thead><tr><th>Name</th><th>Prefix</th><th>Scope</th><th>Created</th><th>Expires</th><th>Last used</th><th></th></tr></thead>
      <tbody>
        <tr>
          <td className="fw-500">CLI · laptop</td>
          <td><HashChip value="af_pat_ze72…aa1" short="af_pat_ze72…aa1" /></td>
          <td><Badge tone="info">read-write</Badge></td>
          <td className="text-sm muted">Sep 18, 2026</td>
          <td className="text-sm">Dec 17, 2026</td>
          <td className="text-sm muted">2h ago</td>
          <td><Button variant="ghost" size="sm">Revoke</Button></td>
        </tr>
        <tr>
          <td className="fw-500">Audit notebook</td>
          <td><HashChip value="af_pat_44b1…0e2" short="af_pat_44b1…0e2" /></td>
          <td><Badge tone="neutral">read-only</Badge></td>
          <td className="text-sm muted">Aug 22, 2026</td>
          <td className="text-sm">Never</td>
          <td className="text-sm muted">Yesterday</td>
          <td><Button variant="ghost" size="sm">Revoke</Button></td>
        </tr>
      </tbody>
    </table>
  </Card>
);

const ProfileSigning = ({ pushToast }) => (
  <div className="col gap-5">
    <div className="card card--padded">
      <div className="row gap-3" style={{ alignItems: "flex-start" }}>
        <div className="profile-mfa-icon">{window.Icon.lock({ size: 22 })}</div>
        <div style={{ flex: 1 }}>
          <h3 className="profile-section-title">Reviewer signing key</h3>
          <div className="text-sm muted">Every review decision you publish is signed with this Ed25519 key. Auditors can verify your sign-off without trusting Attestia.</div>
        </div>
        <Badge tone="sealed" icon={window.Icon.checkSimple({ size: 11 })}>Active</Badge>
      </div>
      <div className="signing-key-block">
        <div className="text-xs muted mono" style={{ letterSpacing: "0.06em", textTransform: "uppercase", marginBottom: 8 }}>Public key · share freely</div>
        <pre className="signing-key"><code>ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILqf5d3kT4PSh7y+vEoQ
2nHpwj9zN8cFJ+QmA2RpAyJK priya@meridian.health</code></pre>
        <div className="text-xs muted mono" style={{ marginTop: 8 }}>Fingerprint <span className="mono">SHA256:af3c…91b9c4d27f201e8b9</span></div>
      </div>
      <div className="row gap-2" style={{ marginTop: 14 }}>
        <Button variant="secondary" size="sm" icon={window.Icon.download({ size: 13 })}>Download public key</Button>
        <Button variant="ghost" size="sm" icon={window.Icon.replay({ size: 13 })}>Rotate</Button>
        <span className="spacer" />
        <span className="text-xs muted">Created Sep 04 · used on 87 reviews</span>
      </div>
    </div>

    <div className="card card--padded">
      <h3 className="profile-section-title">Last 5 signed decisions</h3>
      <table className="table table--compact" style={{ marginTop: 12 }}>
        <thead><tr><th>Review</th><th>Verdict applied</th><th>Signed at</th><th>Signature</th></tr></thead>
        <tbody>
          <tr><td><HashChip value="rev_pq3…hv6" short="rev_pq3…hv6" /></td><td><Verdict kind="contradicted" /></td><td className="mono text-sm muted">10:34 today</td><td className="mono text-xs">af3c91…b9c4</td></tr>
          <tr><td><HashChip value="rev_w2k…aa1" short="rev_w2k…aa1" /></td><td><Verdict kind="unverif" /></td><td className="mono text-sm muted">Yesterday 16:12</td><td className="mono text-xs">7afe10…11c8</td></tr>
          <tr><td><HashChip value="rev_8nm…rt4" short="rev_8nm…rt4" /></td><td><Verdict kind="partial" /></td><td className="mono text-sm muted">Yesterday 11:47</td><td className="mono text-xs">44b1aa…ee03</td></tr>
          <tr><td><HashChip value="rev_lm9…c0e" short="rev_lm9…c0e" /></td><td><Verdict kind="verified" /></td><td className="mono text-sm muted">Oct 22 14:08</td><td className="mono text-xs">3d8f0b…9a17</td></tr>
          <tr><td><HashChip value="rev_jx2…3vb" short="rev_jx2…3vb" /></td><td><Verdict kind="contradicted" /></td><td className="mono text-sm muted">Oct 22 09:55</td><td className="mono text-xs">b2e971…fa02</td></tr>
        </tbody>
      </table>
    </div>
  </div>
);

/* ============================================================
   INCIDENT POSTMORTEM
   ============================================================ */

const IncidentPostmortem = ({ pushToast }) => {
  const inc = INCIDENTS[0];
  const done = inc.remediations.filter((r) => r.status === "done").length;

  return (
    <>
      <header className="page-header">
        <div className="page-header__inner">
          <div className="page-header__eyebrow">Operations · postmortem</div>
          <div className="row gap-3" style={{ alignItems: "baseline" }}>
            <h1 style={{ margin: 0 }}>{inc.title}</h1>
          </div>
          <div className="incident-meta">
            <span className="incident-pill incident-pill--sev2">{inc.severity.toUpperCase()}</span>
            <span className="incident-pill incident-pill--resolved">Resolved</span>
            <span className="text-sm muted mono">{inc.id}</span>
            <span className="text-sm muted">· {inc.duration} duration</span>
            <span className="text-sm muted">· IC <strong style={{ color: "var(--ink-1)" }}>{inc.ic}</strong></span>
          </div>
        </div>
        <div className="page-actions">
          <Button variant="secondary" size="sm" icon={window.Icon.share({ size: 13 })}>Share</Button>
          <Button variant="secondary" size="sm" icon={window.Icon.download({ size: 13 })}>Export PDF</Button>
          <Button variant="primary" size="sm" icon={window.Icon.lock({ size: 13 })} onClick={() => pushToast && pushToast({ kind: "success", title: "Postmortem sealed", sub: "Anchored to bulletin · auditor-visible" })}>Seal</Button>
        </div>
      </header>

      <div className="incident-grid">
        <div className="incident-main">
          {/* Blast radius card */}
          <div className="incident-card incident-card--radius">
            <div className="text-xs muted mono" style={{ letterSpacing: "0.06em", textTransform: "uppercase" }}>Blast radius</div>
            <div className="blast-grid">
              <div><div className="blast-value mono tabular">{inc.blastRadius.traces}</div><div className="text-xs muted">Traces affected</div></div>
              <div><div className="blast-value mono tabular">{inc.blastRadius.claims}</div><div className="text-xs muted">Claims contradicted</div></div>
              <div><div className="blast-value mono tabular" style={{ color: "var(--verified)" }}>{inc.blastRadius.reachedUsers}</div><div className="text-xs muted">Reached users</div></div>
              <div><div className="blast-value mono tabular">{inc.blastRadius.users}</div><div className="text-xs muted">Callers retried</div></div>
            </div>
            <div className="blast-callout">
              <span style={{ color: "var(--verified)" }}>{window.Icon.checkSimple({ size: 14 })}</span>
              <strong>The wrap held.</strong> No contradicted output left the API. All {inc.blastRadius.claims} bad claims were blocked at the boundary.
            </div>
          </div>

          {/* Summary */}
          <div className="incident-card">
            <h3 className="incident-h">Summary</h3>
            <p className="incident-prose">{inc.summary}</p>
          </div>

          {/* Timeline */}
          <div className="incident-card">
            <h3 className="incident-h">Timeline</h3>
            <ol className="incident-timeline">
              {inc.timeline.map((t, i) => (
                <li key={i} className={`incident-step incident-step--${t.kind}`}>
                  <div className="incident-step__time mono tabular">{t.t}</div>
                  <div className="incident-step__dot" />
                  <div className="incident-step__body">
                    {t.actor && <strong style={{ fontSize: 13 }}>{t.actor}</strong>}
                    <div className="text-sm" style={{ color: "var(--ink-1)" }}>{t.body}</div>
                  </div>
                </li>
              ))}
            </ol>
          </div>

          {/* Root cause */}
          <div className="incident-card">
            <h3 className="incident-h">Root cause</h3>
            <p className="incident-prose">{inc.rootCause}</p>
          </div>

          {/* Impact */}
          <div className="incident-card">
            <h3 className="incident-h">Impact</h3>
            <p className="incident-prose">{inc.impact}</p>
          </div>

          {/* Remediations */}
          <div className="incident-card">
            <div className="row gap-2" style={{ alignItems: "baseline", justifyContent: "space-between" }}>
              <h3 className="incident-h" style={{ margin: 0 }}>Remediations <span className="text-xs muted mono">{done}/{inc.remediations.length}</span></h3>
              <Button variant="ghost" size="sm" icon={window.Icon.plus({ size: 12 })}>Add</Button>
            </div>
            <div className="remediation-list">
              {inc.remediations.map((r) => (
                <div key={r.id} className={`remediation remediation--${r.status}`}>
                  <span className={`remediation__check remediation__check--${r.status}`}>
                    {r.status === "done" ? window.Icon.checkSimple({ size: 12 }) : r.status === "in_progress" ? <span className="remediation__half" /> : null}
                  </span>
                  <div className="remediation__body">
                    <div className="text-sm">{r.text}</div>
                    <div className="text-xs muted" style={{ marginTop: 3 }}>
                      <strong style={{ color: "var(--ink-2)" }}>{r.owner}</strong> · due {r.due}
                    </div>
                  </div>
                  <span className={`incident-pill incident-pill--${r.status === "done" ? "resolved" : r.status === "in_progress" ? "wip" : "pending"}`}>
                    {r.status === "in_progress" ? "in progress" : r.status}
                  </span>
                </div>
              ))}
            </div>
          </div>
        </div>

        <aside className="incident-side">
          <div className="incident-card">
            <div className="text-xs muted mono" style={{ letterSpacing: "0.06em", textTransform: "uppercase", marginBottom: 10 }}>Key times</div>
            <div className="incident-times">
              <div><span className="muted text-xs">Opened</span><div className="mono">{inc.opened}</div></div>
              <div><span className="muted text-xs">Detected</span><div className="mono">{inc.detected}</div></div>
              <div><span className="muted text-xs">Mitigated</span><div className="mono">Oct 20 · 04:01 UTC</div></div>
              <div><span className="muted text-xs">Resolved</span><div className="mono">{inc.resolved}</div></div>
            </div>
          </div>
          <div className="incident-card">
            <div className="text-xs muted mono" style={{ letterSpacing: "0.06em", textTransform: "uppercase", marginBottom: 10 }}>Affected apps</div>
            {inc.apps.map((a) => (
              <div key={a} className="row gap-2" style={{ marginBottom: 6, alignItems: "center" }}>
                <span style={{ color: "var(--ink-3)" }}>{window.Icon.cpu({ size: 13 })}</span>
                <span className="text-sm">{a}</span>
              </div>
            ))}
          </div>
          <div className="incident-card">
            <div className="text-xs muted mono" style={{ letterSpacing: "0.06em", textTransform: "uppercase", marginBottom: 10 }}>Linked traces</div>
            {inc.related.map((r) => (
              <div key={r.id} className="incident-link">
                <HashChip value={r.id} short={r.id} />
                <span className="text-xs muted" style={{ marginLeft: 8 }}>{r.desc}</span>
              </div>
            ))}
          </div>
          <div className="incident-card incident-card--seal">
            <div className="row gap-2" style={{ alignItems: "center" }}>
              <span>{window.Icon.lock({ size: 14 })}</span>
              <span className="text-xs muted mono" style={{ letterSpacing: "0.06em", textTransform: "uppercase" }}>Will be sealed</span>
            </div>
            <div className="text-sm" style={{ marginTop: 6 }}>Once sealed, this postmortem is chain-anchored and immutable. Auditors will see it in the next evidence pack.</div>
          </div>
        </aside>
      </div>
    </>
  );
};

/* Export */
Object.assign(window, {
  NotificationsInbox,
  VerificationPlayground,
  ModelRegistry,
  UserProfile,
  IncidentPostmortem,
});
