/* ============================================================
   New screens — gap-filling for the operational loop.

   1. Policies     — the rules engine; how Attestia decides
                     what to verify, block, escalate.
   2. Live monitor — real-time stream of verifications. Demo-
                     cinematic; pause to inspect.
   3. Reviews queue — human-in-the-loop triage for flagged
                      claims. Approve override · quarantine · escalate.
   4. Activity log  — internal who-did-what audit trail of
                      admin actions (rotated key, edited policy).

   Style: stays inside the Attestia editorial system — Geist sans,
   Geist Mono for evidence, Instrument Serif italic at display moments,
   hairline rules, ochre/sage/brick verdict palette.
   ============================================================ */

/* ---------- Fixtures ---------- */

const POLICIES = [
  {
    id: "p_clinical_cite",
    name: "Clinical claims must cite FDA or AHA source",
    eyebrow: "HIPAA · core",
    enabled: true,
    severity: "blocking",
    apps: ["encounter-summary", "discharge-bot"],
    judges: 3,
    threshold: 0.9,
    onContradicted: "block",
    onPartial: "human_review",
    onUnverif: "warn",
    matches30d: 8412,
    blocks30d: 18,
    author: "Priya Sharma",
    updated: "Oct 22, 2026 · 14:21",
    version: 7,
    description: "Every clinical recommendation produced by Encounter Summary or Discharge must be verifiable against a registered FDA prescribing-information document or AHA/ACC guideline. Internal protocols may corroborate but cannot stand alone.",
    notify: ["#meridian-llm-ops", "priya@meridian.health"],
  },
  {
    id: "p_pedi_unanimous",
    name: "Pediatric dosing requires unanimous 3-judge agreement",
    eyebrow: "HIPAA · pediatric",
    enabled: true,
    severity: "blocking",
    apps: ["encounter-summary"],
    judges: 3,
    threshold: 1.0,
    onContradicted: "block",
    onPartial: "block",
    onUnverif: "block",
    matches30d: 612,
    blocks30d: 4,
    author: "Dr. Aisha Patel",
    updated: "Oct 18, 2026 · 09:04",
    version: 3,
    description: "For any claim mentioning a patient under 18 or any pediatric dosage, all three judges must independently return verified. Anything less is blocked at the API boundary before the response reaches the calling app.",
    notify: ["#meridian-pediatrics", "aisha@meridian.health"],
  },
  {
    id: "p_block_contradiction",
    name: "Block on contradiction",
    eyebrow: "HIPAA · default",
    enabled: true,
    severity: "blocking",
    apps: ["*"],
    judges: 3,
    threshold: 0.85,
    onContradicted: "block",
    onPartial: "warn",
    onUnverif: "warn",
    matches30d: 24891,
    blocks30d: 112,
    author: "System",
    updated: "Aug 12, 2026 · 11:00",
    version: 1,
    description: "Catch-all: any response containing a claim contradicted by a registered source is held and routed to Reviews. The user receives a soft-fallback message; the original is sealed for audit.",
    notify: ["#meridian-llm-ops"],
  },
  {
    id: "p_user_override",
    name: "Allow user override on partial verdict",
    eyebrow: "Encounter Summary",
    enabled: false,
    severity: "advisory",
    apps: ["encounter-summary"],
    judges: 2,
    threshold: 0.7,
    onContradicted: "block",
    onPartial: "allow_with_banner",
    onUnverif: "warn",
    matches30d: 0,
    blocks30d: 0,
    author: "Mike Chen",
    updated: "Oct 14, 2026 · 16:48",
    version: 2,
    description: "Drafted but not active. Would let clinicians ship a partial-verdict draft if they acknowledge the unverified spans via signed ack. Pending legal review.",
    notify: ["#meridian-clinical"],
  },
  {
    id: "p_cardio_fast",
    name: "Cardiology fast-path · skip Judge C on AHA-cited claims",
    eyebrow: "Encounter Summary · experimental",
    enabled: false,
    severity: "advisory",
    apps: ["encounter-summary"],
    judges: 2,
    threshold: 0.9,
    onContradicted: "block",
    onPartial: "human_review",
    onUnverif: "warn",
    matches30d: 0,
    blocks30d: 0,
    author: "Priya Sharma",
    updated: "Oct 11, 2026 · 10:30",
    version: 1,
    description: "Draft: in cardiology purposes only, drop Judge C when the AHA guideline is cited at score ≥ 92. Saves ~280ms p95. Holding for calibration sign-off — cohort N=2,114 currently insufficient.",
    notify: [],
  },
];

const POLICY_VERSIONS = [
  { v: 7, when: "Oct 22 · 14:21", who: "Priya Sharma", what: "Lowered threshold from 0.92 → 0.90 after Q3 calibration review." },
  { v: 6, when: "Oct 14 · 09:55", who: "Mike Chen", what: "Added AHA/ACC Heart Failure 2024 to allowed sources." },
  { v: 5, when: "Oct 02 · 13:10", who: "Priya Sharma", what: "Scoped to Encounter Summary + Discharge only (excluded Triage)." },
  { v: 4, when: "Sep 18 · 11:34", who: "System auto-tune", what: "Promoted from advisory to blocking after 30d shadow trial." },
];

/* Generators for the live monitor — synthetic data, not network-bound. */
const APPS_SHORT = ["Encounter Summary", "Discharge Plan", "Intake Triage"];
const PURPOSES = ["discharge_summary", "med_review", "symptom_summary", "care_plan", "imaging_summary"];
const MODELS = ["gpt-4o-mini", "claude-3-5-sonnet", "gemini-pro-1.5"];
const VERDICT_WEIGHTS = ["verified","verified","verified","verified","verified","verified","verified","verified","verified","partial","partial","unverif","contradicted"];
const sampleId = () => "af_" + Array.from({length:3}, () => Math.random().toString(36).slice(2,5)).join("") + "…" + Math.random().toString(36).slice(2,5);
const sampleEvent = () => {
  const v = VERDICT_WEIGHTS[Math.floor(Math.random() * VERDICT_WEIGHTS.length)];
  return {
    id: sampleId(),
    t: new Date().toISOString().slice(11,19) + "." + String(Math.floor(Math.random()*1000)).padStart(3,"0"),
    app: APPS_SHORT[Math.floor(Math.random()*APPS_SHORT.length)],
    purpose: PURPOSES[Math.floor(Math.random()*PURPOSES.length)],
    model: MODELS[Math.floor(Math.random()*MODELS.length)],
    claims: 1 + Math.floor(Math.random()*4),
    verdict: v,
    ms: 280 + Math.floor(Math.random()*1800),
    cost: (0.002 + Math.random()*0.018).toFixed(3),
    user: "clinician-" + (1000 + Math.floor(Math.random()*9000)),
  };
};

const REVIEWS = [
  {
    id: "rev_x3k…7yv",
    traceId: "af_x3k…7yv",
    app: "Encounter Summary",
    purpose: "discharge_summary",
    verdict: "contradicted",
    age: "8m",
    ageSort: 8,
    urgency: "high",
    user: "clinician-9847",
    claim: "Patients with HFrEF should be initiated on beta-blockers at the maximum tolerated dose immediately on admission to ensure rapid symptom control.",
    source: { name: "AHA/ACC Heart Failure Guidelines 2024", span: "§7.3.3 Beta-blocker initiation, p. 68", 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." },
    judges: [
      { name: "Lynx-8B", verdict: "contradicted", conf: 0.96 },
      { name: "Claude 3.5", verdict: "contradicted", conf: 0.95 },
      { name: "Gemini Pro 1.5", verdict: "contradicted", conf: 0.93 },
    ],
    policy: "Clinical claims must cite FDA or AHA source",
    note: "Source explicitly recommends slow titration. Claim recommends opposite.",
  },
  {
    id: "rev_8nm…rt4",
    traceId: "af_8nm…rt4",
    app: "Discharge Plan",
    purpose: "med_review",
    verdict: "partial",
    age: "23m",
    ageSort: 23,
    urgency: "medium",
    user: "clinician-4421",
    claim: "Hold metformin for 48 hours after contrast administration; restart after renal function reassessment.",
    source: { name: "Meridian Clinical Protocols v4.2", span: "§5.1 Contrast media, p. 52", quote: "Hold metformin prior to and following IV contrast administration. Duration is institution-defined; reassess SCr before resuming." },
    judges: [
      { name: "Lynx-8B", verdict: "partial", conf: 0.82 },
      { name: "Claude 3.5", verdict: "verified", conf: 0.71 },
      { name: "Gemini Pro 1.5", verdict: "partial", conf: 0.88 },
    ],
    policy: "Block on contradiction",
    note: "Internal protocol doesn't specify 48h; FDA label doesn't either. The number is novel.",
  },
  {
    id: "rev_w2k…aa1",
    traceId: "af_w2k…aa1",
    app: "Encounter Summary",
    purpose: "discharge_summary",
    verdict: "unverif",
    age: "1h 12m",
    ageSort: 72,
    urgency: "low",
    user: "clinician-2017",
    claim: "Schedule cardiology follow-up at 30 days post-discharge for all patients with NYHA Class III symptoms.",
    source: { name: null, span: null, quote: null },
    judges: [
      { name: "Lynx-8B", verdict: "unverif", conf: 0.69 },
      { name: "Claude 3.5", verdict: "unverif", conf: 0.72 },
      { name: "Gemini Pro 1.5", verdict: "partial", conf: 0.51 },
    ],
    policy: "Block on contradiction",
    note: "No registered source supports the 30-day specifier. Closest match suggests 7-14 days.",
  },
  {
    id: "rev_pq3…hv6",
    traceId: "af_pq3…hv6",
    app: "Intake Triage",
    purpose: "symptom_summary",
    verdict: "contradicted",
    age: "2h 04m",
    ageSort: 124,
    urgency: "high",
    user: "clinician-7710",
    claim: "Aspirin is contraindicated in all adults presenting with suspected acute coronary syndrome.",
    source: { name: "AHA/ACC Heart Failure Guidelines 2024", span: "§3.2 Acute MI, p. 22", quote: "Chewable aspirin 162–325 mg should be administered as soon as possible to all patients with suspected ACS unless a true contraindication exists." },
    judges: [
      { name: "Lynx-8B", verdict: "contradicted", conf: 0.98 },
      { name: "Claude 3.5", verdict: "contradicted", conf: 0.97 },
      { name: "Gemini Pro 1.5", verdict: "contradicted", conf: 0.96 },
    ],
    policy: "Clinical claims must cite FDA or AHA source",
    note: "Direct inversion of source recommendation. High kappa across all judges.",
  },
];

const ACTIVITY = [
  { id: 1, t: "Oct 24 · 10:34", who: { name: "Priya Sharma", initials: "PS" }, verb: "approved override on", obj: "rev_pq3…hv6", kind: "review", ip: "10.4.2.18", meta: "Quarantined original · sent fallback to clinician-7710" },
  { id: 2, t: "Oct 24 · 10:21", who: { name: "Priya Sharma", initials: "PS" }, verb: "rotated production key", obj: "af_live_x3k…7yv", kind: "key", ip: "10.4.2.18", meta: "Reason: 90-day scheduled rotation. Old key revoked at 10:24." },
  { id: 3, t: "Oct 24 · 09:50", who: { name: "Mike Chen", initials: "MC" }, verb: "edited policy", obj: "Clinical claims must cite FDA or AHA source", kind: "policy", ip: "10.4.7.42", diff: { from: "threshold: 0.92", to: "threshold: 0.90" }, meta: "v6 → v7 · effective immediately" },
  { id: 4, t: "Oct 24 · 09:12", who: { name: "System", initials: "SY", system: true }, verb: "sealed daily bulletin", obj: "Block #1,247 · 5,117 leaves", kind: "bulletin", ip: "internal", meta: "Anchored to Ed25519 chain · root af3c…91" },
  { id: 5, t: "Oct 24 · 08:44", who: { name: "Aisha Patel", initials: "AP" }, verb: "uploaded source", obj: "Meridian Clinical Protocols v4.2", kind: "source", ip: "10.4.3.07", meta: "412 KB · 96 pages · indexed in 38s" },
  { id: 6, t: "Oct 23 · 17:31", who: { name: "Priya Sharma", initials: "PS" }, verb: "generated evidence pack", obj: "Encounter Summary — October", kind: "pack", ip: "10.4.2.18", meta: "1,082 calls · 412 KB · shared with HIPAA Audit Partners" },
  { id: 7, t: "Oct 23 · 14:08", who: { name: "Mike Chen", initials: "MC" }, verb: "invited member", obj: "jordan@meridian.health", kind: "team", ip: "10.4.7.42", meta: "Role: Compliance reviewer · expires Oct 30" },
  { id: 8, t: "Oct 23 · 11:55", who: { name: "Priya Sharma", initials: "PS" }, verb: "exported audit log", obj: "Sep 1 — Oct 23 · 18,402 entries", kind: "export", ip: "10.4.2.18", meta: "CSV · hashed and chain-anchored" },
  { id: 9, t: "Oct 23 · 09:02", who: { name: "System", initials: "SY", system: true }, verb: "auto-disabled webhook", obj: "https://hooks.meridian.health/llm", kind: "webhook", ip: "internal", meta: "12 consecutive 5xx · re-enable from Settings → Webhooks" },
  { id: 10, t: "Oct 22 · 16:48", who: { name: "Priya Sharma", initials: "PS" }, verb: "edited redaction profile", obj: "HIPAA · production", kind: "redaction", ip: "10.4.2.18", diff: { from: "MRN: [REDACTED-{n}]", to: "MRN: [PT-{hash6}]" }, meta: "Deterministic surrogate enabled for cross-trace linkage" },
  { id: 11, t: "Oct 22 · 14:21", who: { name: "Priya Sharma", initials: "PS" }, verb: "signed BAA addendum", obj: "HIPAA Audit Partners LLC", kind: "legal", ip: "10.4.2.18", meta: "Effective Oct 22 · sealed via Ed25519 · view in Trust Center" },
  { id: 12, t: "Oct 22 · 10:04", who: { name: "Aisha Patel", initials: "AP" }, verb: "archived app", obj: "Intake Triage (legacy v1)", kind: "app", ip: "10.4.3.07", meta: "Sealed final evidence pack · 14,892 calls archived" },
];

/* ============================================================
   POLICY STUDIO
   ============================================================ */

const PolicyStudio = ({ pushToast }) => {
  const [selectedId, setSelectedId] = React.useState(POLICIES[0].id);
  const selected = POLICIES.find((p) => p.id === selectedId);
  const [enabled, setEnabled] = React.useState(selected.enabled);
  React.useEffect(() => setEnabled(selected.enabled), [selected]);

  const active = POLICIES.filter((p) => p.enabled).length;
  const drafts = POLICIES.length - active;

  return (
    <>
      <header className="page-header">
        <div className="page-header__inner">
          <div className="page-header__eyebrow">Compliance · controls</div>
          <h1>Verification policies</h1>
          <p className="page-header__sub">
            The rules that decide what gets verified, what gets blocked, and who gets paged. Every wrapped call is matched against the policy chain in order; the first blocking match wins.
          </p>
        </div>
        <div className="page-actions">
          <Button variant="secondary" size="sm" icon={window.Icon.fileText({ size: 13 })}>Policy as code</Button>
          <Button variant="primary" size="sm" icon={window.Icon.plus({ size: 13 })}>New policy</Button>
        </div>
      </header>

      <div className="policy-stats">
        <div className="policy-stat">
          <div className="policy-stat__label">Active</div>
          <div className="policy-stat__value">{active}<span className="policy-stat__unit">of {POLICIES.length}</span></div>
        </div>
        <div className="policy-stat">
          <div className="policy-stat__label">Blocks · 30d</div>
          <div className="policy-stat__value">134</div>
          <div className="policy-stat__delta">−12% vs prior period</div>
        </div>
        <div className="policy-stat">
          <div className="policy-stat__label">Routed to review</div>
          <div className="policy-stat__value">387</div>
          <div className="policy-stat__delta">avg 14m to disposition</div>
        </div>
        <div className="policy-stat">
          <div className="policy-stat__label">Drafts</div>
          <div className="policy-stat__value">{drafts}</div>
          <div className="policy-stat__delta">2 awaiting legal review</div>
        </div>
      </div>

      <div className="policy-layout">
        <aside className="policy-list">
          <div className="policy-list__head">
            <span className="text-xs muted mono" style={{ letterSpacing: "0.08em", textTransform: "uppercase" }}>Chain · evaluated in order</span>
          </div>
          {POLICIES.map((p, i) => (
            <button key={p.id}
              onClick={() => setSelectedId(p.id)}
              className={`policy-row ${selectedId === p.id ? "policy-row--active" : ""} ${!p.enabled ? "policy-row--draft" : ""}`}>
              <div className="policy-row__order mono">{String(i + 1).padStart(2, "0")}</div>
              <div className="policy-row__body">
                <div className="policy-row__head">
                  <span className={`policy-dot policy-dot--${p.enabled ? "on" : "off"}`} />
                  <span className="policy-row__name">{p.name}</span>
                </div>
                <div className="policy-row__meta">
                  <span className="mono text-xs muted">{p.eyebrow}</span>
                  <span className="text-xs muted">·</span>
                  <span className="text-xs muted">v{p.version}</span>
                  {p.enabled && <span className="text-xs muted">· {p.matches30d.toLocaleString()} matches/30d</span>}
                </div>
              </div>
              {p.enabled
                ? <span className={`policy-pill policy-pill--${p.severity === "blocking" ? "block" : "advisory"}`}>{p.severity === "blocking" ? "Blocking" : "Advisory"}</span>
                : <span className="policy-pill policy-pill--draft">Draft</span>}
            </button>
          ))}
        </aside>

        <section className="policy-detail">
          <div className="policy-detail__head">
            <div>
              <div className="text-xs mono muted" style={{ letterSpacing: "0.08em", textTransform: "uppercase" }}>{selected.eyebrow}</div>
              <h2 className="policy-detail__title"><em>{selected.name}</em></h2>
              <div className="text-sm muted" style={{ marginTop: 6, maxWidth: 680 }}>{selected.description}</div>
            </div>
            <div className="row gap-2" style={{ alignItems: "center" }}>
              <button
                className={`policy-toggle ${enabled ? "policy-toggle--on" : ""}`}
                onClick={() => { setEnabled((e) => !e); pushToast && pushToast({ kind: "success", title: enabled ? "Policy disabled" : "Policy enabled", sub: selected.name }); }}>
                <span className="policy-toggle__dot" />
                <span className="policy-toggle__label">{enabled ? "Active" : "Disabled"}</span>
              </button>
              <Button variant="ghost" size="sm" icon={window.Icon.more({ size: 14 })} />
            </div>
          </div>

          <div className="policy-rule">
            <div className="rule-row">
              <div className="rule-row__key">WHEN</div>
              <div className="rule-row__value">
                a call to <PolicyChip>{selected.apps[0] === "*" ? "any app" : selected.apps.length + " app(s)"}</PolicyChip>
                {" "}produces a claim categorised as <PolicyChip>clinical_recommendation</PolicyChip>
              </div>
            </div>
            <div className="rule-divider" />
            <div className="rule-row">
              <div className="rule-row__key">VERIFY WITH</div>
              <div className="rule-row__value">
                <PolicyChip mono>{selected.judges}</PolicyChip> judges in parallel ·
                {" "}agreement threshold <PolicyChip mono>{(selected.threshold * 100).toFixed(0)}%</PolicyChip>
                <div className="judge-list">
                  <span className="judge-list__item"><span className="dot dot--on" /> Lynx-8B <span className="muted text-xs">primary</span></span>
                  <span className="judge-list__item"><span className="dot dot--on" /> Claude 3.5 Sonnet</span>
                  <span className="judge-list__item"><span className={`dot ${selected.judges >= 3 ? "dot--on" : "dot--off"}`} /> Gemini Pro 1.5</span>
                </div>
              </div>
            </div>
            <div className="rule-divider" />
            <div className="rule-row">
              <div className="rule-row__key">SOURCES</div>
              <div className="rule-row__value">
                <PolicyChip>FDA prescribing-info corpus</PolicyChip>
                <PolicyChip>AHA/ACC guidelines 2024</PolicyChip>
                <PolicyChip>Meridian Clinical Protocols</PolicyChip>
                <PolicyChip muted>+ 2 more</PolicyChip>
              </div>
            </div>
            <div className="rule-divider" />
            <div className="rule-row">
              <div className="rule-row__key">IF VERDICT IS…</div>
              <div className="rule-row__value">
                <div className="verdict-actions">
                  <VerdictAction kind="contradicted" action={selected.onContradicted} />
                  <VerdictAction kind="partial" action={selected.onPartial} />
                  <VerdictAction kind="unverif" action={selected.onUnverif} />
                  <VerdictAction kind="verified" action="allow" />
                </div>
              </div>
            </div>
            <div className="rule-divider" />
            <div className="rule-row">
              <div className="rule-row__key">NOTIFY</div>
              <div className="rule-row__value">
                {selected.notify.length === 0
                  ? <span className="muted text-sm">No subscribers yet</span>
                  : selected.notify.map((n) => <PolicyChip key={n} icon={n.startsWith("#") ? window.Icon.webhook({ size: 10 }) : window.Icon.bell({ size: 10 })}>{n}</PolicyChip>)}
                <button className="policy-add">{window.Icon.plus({ size: 11 })} Add channel</button>
              </div>
            </div>
          </div>

          <div className="policy-grid">
            <div className="policy-coverage">
              <div className="policy-coverage__head">
                <h3>Coverage · 30 days</h3>
                <Button variant="ghost" size="sm" iconRight={window.Icon.arrowRight({ size: 11 })}>View in analytics</Button>
              </div>
              <PolicyCoverageBar />
              <div className="coverage-stats">
                <div><span className="muted text-xs">Matched</span><div className="mono tabular fw-600">{selected.matches30d.toLocaleString()}</div></div>
                <div><span className="muted text-xs">Blocked</span><div className="mono tabular fw-600" style={{ color: "var(--contra)" }}>{selected.blocks30d}</div></div>
                <div><span className="muted text-xs">Reviewed</span><div className="mono tabular fw-600" style={{ color: "var(--partial)" }}>42</div></div>
                <div><span className="muted text-xs">Allowed</span><div className="mono tabular fw-600" style={{ color: "var(--verified)" }}>{(selected.matches30d - selected.blocks30d - 42).toLocaleString()}</div></div>
              </div>
            </div>

            <div className="policy-history">
              <div className="policy-coverage__head">
                <h3>Version history</h3>
                <span className="text-xs muted mono">v{selected.version} · current</span>
              </div>
              <ol className="version-list">
                {POLICY_VERSIONS.map((v) => (
                  <li key={v.v} className="version-row">
                    <div className="version-row__head">
                      <span className="mono fw-600">v{v.v}</span>
                      <span className="text-xs muted">· {v.when}</span>
                      <span className="text-xs muted">· {v.who}</span>
                    </div>
                    <div className="text-sm" style={{ color: "var(--ink-2)", marginTop: 2 }}>{v.what}</div>
                  </li>
                ))}
              </ol>
              <button className="policy-add policy-add--inline">{window.Icon.replay({ size: 11 })} Compare versions</button>
            </div>
          </div>

          <div className="policy-matches">
            <div className="policy-coverage__head">
              <h3>Recent matches</h3>
              <Button variant="ghost" size="sm" iconRight={window.Icon.arrowRight({ size: 11 })}>Open in Traces</Button>
            </div>
            <table className="table table--compact">
              <thead><tr><th>Time</th><th>Trace</th><th>App</th><th>Verdict</th><th>Action taken</th><th>Latency</th></tr></thead>
              <tbody>
                {[
                  { t: "10:34:01", id: "af_x3k…7yv", app: "Encounter Summary", v: "contradicted", action: "Blocked + queued for review", ms: "1.78s" },
                  { t: "10:31:12", id: "af_q2m…1de", app: "Encounter Summary", v: "verified", action: "Allowed · sealed", ms: "1.42s" },
                  { t: "10:29:47", id: "af_5bp…ku9", app: "Encounter Summary", v: "contradicted", action: "Blocked + queued for review", ms: "1.91s" },
                  { t: "10:27:03", id: "af_pq3…hv6", app: "Intake Triage", v: "verified", action: "Allowed · sealed", ms: "0.94s" },
                  { t: "10:25:18", id: "af_w2k…aa1", app: "Encounter Summary", v: "unverif", action: "Warned + sealed", ms: "1.55s" },
                ].map((r, i) => (
                  <tr key={i} className="clickable">
                    <td className="mono text-sm muted">{r.t}</td>
                    <td><HashChip value={r.id} short={r.id} /></td>
                    <td className="text-sm">{r.app}</td>
                    <td><Verdict kind={r.v} /></td>
                    <td className="text-sm muted">{r.action}</td>
                    <td className="mono tabular text-sm">{r.ms}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>

          <div className="policy-foot">
            <div className="text-xs muted">
              Last edited by <strong>{selected.author}</strong> · {selected.updated} · v{selected.version}
            </div>
            <div className="row gap-2">
              <Button variant="ghost" size="sm">Discard draft</Button>
              <Button variant="secondary" size="sm">Save as draft</Button>
              <Button variant="primary" size="sm" icon={window.Icon.checkSimple({ size: 13 })}>Publish v{selected.version + 1}</Button>
            </div>
          </div>
        </section>
      </div>
    </>
  );
};

const PolicyChip = ({ children, mono, muted, icon }) => (
  <span className={`policy-chip ${mono ? "policy-chip--mono" : ""} ${muted ? "policy-chip--muted" : ""}`}>
    {icon}<span>{children}</span>
  </span>
);

const VerdictAction = ({ kind, action }) => {
  const labels = {
    allow: "Allow",
    block: "Block",
    warn: "Warn + seal",
    human_review: "Send to Reviews",
    allow_with_banner: "Allow w/ banner",
  };
  return (
    <div className="verdict-action">
      <Verdict kind={kind} />
      <span className="verdict-action__arrow">{window.Icon.arrowRight({ size: 11 })}</span>
      <span className={`verdict-action__do verdict-action__do--${action === "block" ? "block" : action === "allow" ? "ok" : "soft"}`}>{labels[action] || action}</span>
    </div>
  );
};

const PolicyCoverageBar = () => (
  <div className="cov-bar">
    <div className="cov-seg cov-seg--ok" style={{ width: "94%" }} />
    <div className="cov-seg cov-seg--soft" style={{ width: "4.7%" }} />
    <div className="cov-seg cov-seg--block" style={{ width: "1.3%" }} />
  </div>
);

/* ============================================================
   LIVE MONITOR
   ============================================================ */

const LiveMonitor = ({ onOpenTrace }) => {
  const [events, setEvents] = React.useState(() => Array.from({ length: 18 }, sampleEvent));
  const [paused, setPaused] = React.useState(false);
  const [filterApp, setFilterApp] = React.useState("all");
  const [filterVerdict, setFilterVerdict] = React.useState("all");
  const [perMin, setPerMin] = React.useState(412);

  React.useEffect(() => {
    if (paused) return;
    const tick = setInterval(() => {
      setEvents((prev) => {
        const n = 1 + Math.floor(Math.random() * 2);
        const news = Array.from({ length: n }, sampleEvent);
        return [...news, ...prev].slice(0, 36);
      });
      setPerMin((v) => Math.max(380, Math.min(460, v + (Math.random() < 0.5 ? -2 : 2))));
    }, 1300);
    return () => clearInterval(tick);
  }, [paused]);

  const filtered = events.filter((e) =>
    (filterApp === "all" || e.app === filterApp) &&
    (filterVerdict === "all" || e.verdict === filterVerdict)
  );

  const verifiedPct = Math.round((events.filter((e) => e.verdict === "verified").length / events.length) * 100);

  return (
    <>
      <header className="page-header">
        <div className="page-header__inner">
          <div className="page-header__eyebrow">Operations · live stream</div>
          <h1 className="live-title">
            Live monitor
            <span className={`live-status ${paused ? "live-status--paused" : ""}`}>
              <span className="live-dot" />
              {paused ? "Paused" : "Streaming"}
            </span>
          </h1>
          <p className="page-header__sub">
            Real-time verification activity across all wrapped apps. Click any row for the full trace.
          </p>
        </div>
        <div className="page-actions">
          <Button variant="secondary" size="sm" icon={paused ? window.Icon.replay({ size: 13 }) : <PauseIcon />} onClick={() => setPaused((p) => !p)}>{paused ? "Resume" : "Pause"}</Button>
          <Button variant="secondary" size="sm" icon={window.Icon.download({ size: 13 })}>Export window</Button>
        </div>
      </header>

      <div className="live-strip">
        <div className="live-stat">
          <div className="live-stat__label">Per minute</div>
          <div className="live-stat__value mono tabular">{perMin}</div>
          <div className="live-stat__sub">peak today 487</div>
        </div>
        <div className="live-stat">
          <div className="live-stat__label">Verdict mix · last 100</div>
          <PolicyCoverageBar />
          <div className="live-stat__legend">
            <span><span className="dot" style={{ background: "var(--verified)" }} /> verified {verifiedPct}%</span>
            <span><span className="dot" style={{ background: "var(--partial)" }} /> partial</span>
            <span><span className="dot" style={{ background: "var(--contra)" }} /> contra</span>
          </div>
        </div>
        <div className="live-stat">
          <div className="live-stat__label">p95 latency</div>
          <div className="live-stat__value mono tabular">612<span className="live-stat__unit">ms</span></div>
          <div className="live-stat__sub">SLO 800ms</div>
        </div>
        <div className="live-stat">
          <div className="live-stat__label">Sandbox</div>
          <div className="live-stat__value mono tabular live-stat__value--ok">
            <span className="live-pulse" />3/3
          </div>
          <div className="live-stat__sub">judges healthy</div>
        </div>
      </div>

      <div className="live-filters">
        <span className="text-xs muted mono" style={{ letterSpacing: "0.08em", textTransform: "uppercase" }}>Filters</span>
        <div className="seg">
          {["all", ...APPS_SHORT].map((a) => (
            <button key={a} className={`seg__btn ${filterApp === a ? "seg__btn--active" : ""}`} onClick={() => setFilterApp(a)}>{a === "all" ? "All apps" : a}</button>
          ))}
        </div>
        <div className="seg">
          {[
            { v: "all", l: "All verdicts" },
            { v: "verified", l: "Verified" },
            { v: "partial", l: "Partial" },
            { v: "unverif", l: "Unverif." },
            { v: "contradicted", l: "Contradicted" },
          ].map((it) => (
            <button key={it.v} className={`seg__btn ${filterVerdict === it.v ? "seg__btn--active" : ""}`} onClick={() => setFilterVerdict(it.v)}>{it.l}</button>
          ))}
        </div>
        <span className="spacer" />
        <span className="text-xs muted">{filtered.length} of {events.length} visible</span>
      </div>

      <div className="live-stream">
        <div className="live-stream__header">
          <span>Time</span>
          <span>Trace</span>
          <span>App</span>
          <span>Purpose</span>
          <span>Model</span>
          <span>Claims</span>
          <span>Verdict</span>
          <span style={{ textAlign: "right" }}>Latency</span>
          <span style={{ textAlign: "right" }}>Cost</span>
        </div>
        <div className="live-stream__body">
          {filtered.map((e, i) => (
            <div key={e.id + e.t} className={`live-row ${i === 0 && !paused ? "live-row--new" : ""}`} onClick={() => onOpenTrace && onOpenTrace(e.id)}>
              <span className="mono text-sm muted">{e.t}</span>
              <span><HashChip value={e.id} short={e.id} /></span>
              <span className="text-sm">{e.app}</span>
              <span className="mono text-xs muted">{e.purpose}</span>
              <span className="mono text-xs muted">{e.model}</span>
              <span className="mono tabular text-sm">{e.claims}</span>
              <span><Verdict kind={e.verdict === "contradicted" ? "contradicted" : e.verdict} /></span>
              <span className="mono tabular text-sm" style={{ textAlign: "right", color: e.ms > 1500 ? "var(--partial)" : "var(--ink-2)" }}>{e.ms}ms</span>
              <span className="mono tabular text-sm muted" style={{ textAlign: "right" }}>${e.cost}</span>
            </div>
          ))}
        </div>
        <div className="live-stream__foot">
          <span className="text-xs muted">Showing rolling 30s window · scroll to load older</span>
        </div>
      </div>
    </>
  );
};

const PauseIcon = () => (
  <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
    <rect x="6" y="5" width="4" height="14" rx="1" />
    <rect x="14" y="5" width="4" height="14" rx="1" />
  </svg>
);

/* ============================================================
   REVIEWS QUEUE
   ============================================================ */

const ReviewsQueue = ({ pushToast, onOpenTrace }) => {
  const [selectedId, setSelectedId] = React.useState(REVIEWS[0].id);
  const [filter, setFilter] = React.useState("all");
  const [reason, setReason] = React.useState("");
  const selected = REVIEWS.find((r) => r.id === selectedId);
  const filtered = REVIEWS.filter((r) => filter === "all" || r.urgency === filter);

  const decide = (action) => {
    const labels = { approve: "Override approved", quarantine: "Quarantined", escalate: "Escalated to clinical lead", send_back: "Sent back to drafter" };
    pushToast && pushToast({ kind: action === "quarantine" ? "warn" : "success", title: labels[action], sub: `${selected.traceId} · ${selected.app}` });
    setReason("");
  };

  return (
    <>
      <header className="page-header">
        <div className="page-header__inner">
          <div className="page-header__eyebrow">Compliance · human-in-the-loop</div>
          <h1>Reviews queue</h1>
          <p className="page-header__sub">
            Claims routed here when the verification chain disagrees with a registered source. Triage decides whether to override, quarantine, escalate, or send back.
          </p>
        </div>
        <div className="page-actions">
          <Button variant="secondary" size="sm" icon={window.Icon.fileText({ size: 13 })}>Reviewer playbook</Button>
          <Button variant="secondary" size="sm" icon={window.Icon.share({ size: 13 })}>Assign to me</Button>
        </div>
      </header>

      <div className="review-strip">
        <div className="review-stat">
          <div className="review-stat__label">Pending</div>
          <div className="review-stat__value">{REVIEWS.length}</div>
          <div className="review-stat__sub">{REVIEWS.filter((r) => r.urgency === "high").length} high urgency</div>
        </div>
        <div className="review-stat">
          <div className="review-stat__label">Oldest</div>
          <div className="review-stat__value mono tabular">{REVIEWS.sort((a,b) => b.ageSort - a.ageSort)[0].age}</div>
          <div className="review-stat__sub">SLA breach at 4h</div>
        </div>
        <div className="review-stat">
          <div className="review-stat__label">Avg disposition</div>
          <div className="review-stat__value mono tabular">14m</div>
          <div className="review-stat__sub">last 30 days</div>
        </div>
        <div className="review-stat">
          <div className="review-stat__label">Override rate</div>
          <div className="review-stat__value mono tabular">22%</div>
          <div className="review-stat__sub">78% blocked or sent back</div>
        </div>
      </div>

      <div className="review-layout">
        <aside className="review-list">
          <div className="review-list__head">
            <div className="seg seg--sm">
              {["all", "high", "medium", "low"].map((f) => (
                <button key={f} className={`seg__btn ${filter === f ? "seg__btn--active" : ""}`} onClick={() => setFilter(f)}>{f === "all" ? "All" : f}</button>
              ))}
            </div>
          </div>
          {filtered.map((r) => (
            <button key={r.id}
              className={`review-card ${selectedId === r.id ? "review-card--active" : ""}`}
              onClick={() => setSelectedId(r.id)}>
              <div className="review-card__head">
                <Verdict kind={r.verdict === "contradicted" ? "contradicted" : r.verdict} />
                <span className={`urgency-pill urgency-pill--${r.urgency}`}>{r.urgency}</span>
                <span className="spacer" />
                <span className="text-xs muted mono">{r.age} ago</span>
              </div>
              <div className="review-card__claim">{r.claim}</div>
              <div className="review-card__foot">
                <span className="mono text-xs muted">{r.traceId}</span>
                <span className="text-xs muted">· {r.app}</span>
                <span className="spacer" />
                <span className="text-xs muted">{r.judges.filter((j) => j.verdict === r.verdict).length}/{r.judges.length} judges agree</span>
              </div>
            </button>
          ))}
        </aside>

        <section className="review-detail">
          <div className="review-detail__head">
            <div>
              <div className="row gap-2" style={{ alignItems: "center" }}>
                <Verdict kind={selected.verdict === "contradicted" ? "contradicted" : selected.verdict} size="lg" />
                <span className={`urgency-pill urgency-pill--${selected.urgency}`}>{selected.urgency} urgency</span>
                <span className="text-xs muted">· age {selected.age}</span>
              </div>
              <h2 className="policy-detail__title" style={{ marginTop: 10 }}>{selected.app} · <em>{selected.purpose}</em></h2>
              <div className="text-sm muted" style={{ marginTop: 4 }}>
                Routed by policy <strong style={{ color: "var(--ink-1)" }}>{selected.policy}</strong> · trace <HashChip value={selected.traceId} short={selected.traceId} /> · caller <span className="mono">{selected.user}</span>
              </div>
            </div>
            <Button variant="ghost" size="sm" icon={window.Icon.external({ size: 13 })} onClick={() => onOpenTrace && onOpenTrace(selected.traceId)}>Open full trace</Button>
          </div>

          <div className="review-claim">
            <div className="text-xs muted mono" style={{ letterSpacing: "0.08em", textTransform: "uppercase" }}>Claim under review</div>
            <div className="review-claim__text">{selected.claim}</div>
          </div>

          {selected.source.name ? (
            <div className="review-source">
              <div className="review-source__head">
                <span className="text-xs muted mono" style={{ letterSpacing: "0.08em", textTransform: "uppercase" }}>Source the system consulted</span>
                <span className="text-xs muted">{selected.source.span}</span>
              </div>
              <div className="review-source__name">
                {window.Icon.fileCheck({ size: 14 })} {selected.source.name}
              </div>
              <blockquote className="review-source__quote">
                <span className="review-source__rule" />
                {selected.source.quote}
              </blockquote>
              <div className="review-note">
                <span className="review-note__icon" style={{ color: "var(--contra)" }}>{window.Icon.alertTriangle({ size: 13 })}</span>
                <span>{selected.note}</span>
              </div>
            </div>
          ) : (
            <div className="review-source review-source--empty">
              <div className="text-xs muted mono" style={{ letterSpacing: "0.08em", textTransform: "uppercase" }}>No supporting source found</div>
              <div className="text-sm" style={{ marginTop: 8, color: "var(--ink-2)" }}>{selected.note}</div>
            </div>
          )}

          <div className="review-judges">
            <div className="text-xs muted mono" style={{ letterSpacing: "0.08em", textTransform: "uppercase", marginBottom: 10 }}>Judge votes</div>
            <div className="judge-grid">
              {selected.judges.map((j) => (
                <div key={j.name} className={`judge-card judge-card--${j.verdict === "contradicted" ? "contradicted" : j.verdict}`}>
                  <div className="judge-card__name">{j.name}</div>
                  <Verdict kind={j.verdict === "contradicted" ? "contradicted" : j.verdict} />
                  <div className="judge-card__conf mono tabular">{(j.conf * 100).toFixed(0)}%</div>
                </div>
              ))}
            </div>
          </div>

          <div className="review-action">
            <div className="review-action__head">
              <span className="text-xs muted mono" style={{ letterSpacing: "0.08em", textTransform: "uppercase" }}>Reviewer decision</span>
              <span className="text-xs muted">Logged to activity log · signed with your key</span>
            </div>
            <textarea
              className="review-reason"
              placeholder="Reason (required for override · 200 chars min · attached to evidence chain)"
              value={reason}
              onChange={(e) => setReason(e.target.value)}
            />
            <div className="review-buttons">
              <Button variant="destructive" size="sm" icon={window.Icon.xCircle({ size: 13 })} onClick={() => decide("quarantine")}>Quarantine</Button>
              <Button variant="secondary" size="sm" icon={window.Icon.replay({ size: 13 })} onClick={() => decide("send_back")}>Send back to drafter</Button>
              <Button variant="secondary" size="sm" icon={window.Icon.share({ size: 13 })} onClick={() => decide("escalate")}>Escalate</Button>
              <span className="spacer" />
              <Button variant="primary" size="sm" icon={window.Icon.checkSimple({ size: 13 })} disabled={reason.length < 8} onClick={() => decide("approve")}>Approve override</Button>
            </div>
          </div>
        </section>
      </div>
    </>
  );
};

/* ============================================================
   ACTIVITY LOG
   ============================================================ */

const KIND_ICON = {
  review: "shieldCheck", key: "key", policy: "fileCheck", bulletin: "lock",
  source: "folder", pack: "fileCheck", team: "users", export: "download",
  webhook: "webhook", redaction: "shield", legal: "fileText", app: "cpu",
};

const KIND_LABEL = {
  review: "Reviews", key: "API keys", policy: "Policies", bulletin: "Bulletin",
  source: "Sources", pack: "Evidence packs", team: "Team", export: "Export",
  webhook: "Webhooks", redaction: "Redaction", legal: "Legal", app: "Apps",
};

const ActivityLog = () => {
  const [kindFilter, setKindFilter] = React.useState("all");
  const [actorFilter, setActorFilter] = React.useState("all");
  const [search, setSearch] = React.useState("");

  const kinds = ["all", ...Array.from(new Set(ACTIVITY.map((a) => a.kind)))];
  const actors = ["all", ...Array.from(new Set(ACTIVITY.map((a) => a.who.name)))];

  const filtered = ACTIVITY.filter((a) =>
    (kindFilter === "all" || a.kind === kindFilter) &&
    (actorFilter === "all" || a.who.name === actorFilter) &&
    (!search || (a.verb + " " + a.obj + " " + a.meta).toLowerCase().includes(search.toLowerCase()))
  );

  // Group by day label.
  const byDay = filtered.reduce((acc, a) => {
    const day = a.t.split(" · ")[0];
    (acc[day] = acc[day] || []).push(a);
    return acc;
  }, {});

  return (
    <>
      <header className="page-header">
        <div className="page-header__inner">
          <div className="page-header__eyebrow">Security · audit trail</div>
          <h1>Activity log</h1>
          <p className="page-header__sub">
            Every admin action — sealed, signed, and exportable for HIPAA &amp; SOC2 evidence. Retention is 7 years; the chain is daily-anchored to the public bulletin.
          </p>
        </div>
        <div className="page-actions">
          <Button variant="secondary" size="sm" icon={window.Icon.download({ size: 13 })}>Export CSV</Button>
          <Button variant="secondary" size="sm" icon={window.Icon.external({ size: 13 })}>Stream to SIEM</Button>
        </div>
      </header>

      <div className="activity-filters">
        <div className="activity-search">
          {window.Icon.search({ size: 13 })}
          <input value={search} onChange={(e) => setSearch(e.target.value)} placeholder="Filter by action, object, IP, or member…" />
        </div>
        <select className="activity-select" value={actorFilter} onChange={(e) => setActorFilter(e.target.value)}>
          {actors.map((a) => <option key={a} value={a}>{a === "all" ? "All actors" : a}</option>)}
        </select>
        <select className="activity-select" value={kindFilter} onChange={(e) => setKindFilter(e.target.value)}>
          {kinds.map((k) => <option key={k} value={k}>{k === "all" ? "All categories" : (KIND_LABEL[k] || k)}</option>)}
        </select>
        <span className="spacer" />
        <span className="text-xs muted mono">{filtered.length.toLocaleString()} of {ACTIVITY.length.toLocaleString()} entries</span>
      </div>

      <div className="activity-timeline">
        {Object.entries(byDay).map(([day, entries]) => (
          <div key={day} className="activity-day">
            <div className="activity-day__head">
              <span className="mono text-xs" style={{ color: "var(--ink-3)", letterSpacing: "0.06em", textTransform: "uppercase" }}>{day}</span>
              <span className="text-xs muted">· {entries.length} event{entries.length === 1 ? "" : "s"}</span>
            </div>
            <div className="activity-entries">
              {entries.map((a) => (
                <div key={a.id} className={`activity-entry ${a.who.system ? "activity-entry--system" : ""}`}>
                  <div className={`avatar ${a.who.system ? "avatar--system" : ""}`} style={{ width: 28, height: 28, flexShrink: 0 }}>
                    {a.who.initials}
                  </div>
                  <div className="activity-entry__body">
                    <div className="activity-entry__head">
                      <strong className="text-sm">{a.who.name}</strong>
                      <span className="text-sm muted">{a.verb}</span>
                      <span className="text-sm fw-500">{a.obj}</span>
                      <span className="spacer" />
                      <span className={`activity-kind activity-kind--${a.kind}`}>
                        {window.Icon[KIND_ICON[a.kind] || "shieldCheck"]({ size: 10 })}
                        {KIND_LABEL[a.kind] || a.kind}
                      </span>
                    </div>
                    {a.diff && (
                      <div className="activity-diff">
                        <div className="activity-diff__row activity-diff__row--from">
                          <span className="mono">−</span><span className="mono">{a.diff.from}</span>
                        </div>
                        <div className="activity-diff__row activity-diff__row--to">
                          <span className="mono">+</span><span className="mono">{a.diff.to}</span>
                        </div>
                      </div>
                    )}
                    <div className="activity-entry__meta">
                      <span className="text-xs muted mono">{a.t.split(" · ")[1] || a.t}</span>
                      <span className="text-xs muted">· {a.meta}</span>
                      <span className="text-xs muted">· IP <span className="mono">{a.ip}</span></span>
                    </div>
                  </div>
                </div>
              ))}
            </div>
          </div>
        ))}
      </div>
    </>
  );
};

/* Export to window */
Object.assign(window, { PolicyStudio, LiveMonitor, ReviewsQueue, ActivityLog });
