/* ═══════════════════════════════════════════════════════════
   OpAgent Inside — C8.1 Shield (+ CPT / MTG lookup)
   ═══════════════════════════════════════════════════════════ */
(function () {
  const { useMemo, useState, useEffect, useRef } = React;
  const FM = "var(--fm)", FB = "var(--fb)", FD = "var(--fd)";

  function statusTone(status) {
    const s = String(status || "").toLowerCase();
    if (s === "recommended") return { bg: "#F6ECD7", fg: "#8C6D2F", label: "MTG recommended" };
    if (s === "permitted_no_par") return { bg: "#E6F1EA", fg: "#1F5238", label: "No PAR if criteria met" };
    if (s === "optional_prior_approval") return { bg: "#F1E7D6", fg: "#9A6B2E", label: "Optional prior approval" };
    if (s === "not_recommended") return { bg: "#F7E4E2", fg: "#B3261E", label: "Not recommended" };
    return { bg: "#EFEBE2", fg: "#6E6A61", label: status || "—" };
  }

  function verdictTone(v) {
    // Staff language: defend the claim vs abandon (mapped from Defendable / At fault).
    if (v === "DEFENDABLE") return { bg: "#E6F1EA", fg: "#1F5238", border: "var(--forest-bord)", label: "Defend", action: "defend" };
    if (v === "AT_FAULT") return { bg: "#F7E4E2", fg: "#B3261E", border: "#E2B4B0", label: "Abandon", action: "abandon" };
    return { bg: "#F6ECD7", fg: "#8C6D2F", border: "#E0CFA8", label: "Needs review", action: "review" };
  }

  function letterFoundViaLabel(via, extractMethodLabel) {
    if (extractMethodLabel) return extractMethodLabel;
    const v = String(via || "").toLowerCase();
    if (v === "era_view_eob" || v.includes("era") || v.includes("view_eob") || v.includes("view-eob")) {
      return "ASC C-8.1 / View EOB";
    }
    if (v === "billing_notes" || v.includes("billing")) return "Billing notes";
    if (v === "chart_pdf" || v.includes("chart")) return "Chart PDF";
    if (v === "upload") return "Staff upload";
    if (v === "status_queue" || v.includes("queue")) return "Denial queue";
    return "";
  }

  function evidenceTone(s) {
    if (s === "met") return { bg: "#E6F1EA", fg: "#1F5238", label: "Met" };
    if (s === "contradicted") return { bg: "#F7E4E2", fg: "#B3261E", label: "Contradicted" };
    if (s === "missing") return { bg: "#F6ECD7", fg: "#8C6D2F", label: "Missing" };
    if (s === "not_applicable") return { bg: "#EFEBE2", fg: "#6E6A61", label: "N/A" };
    return { bg: "#EFEBE2", fg: "#6E6A61", label: "Unknown" };
  }

  function Chip({ children, tone }) {
    return (
      <span style={{
        display: "inline-flex", alignItems: "center", gap: 6,
        padding: "4px 10px", borderRadius: 999,
        background: tone?.bg || "var(--canvas-mid)",
        color: tone?.fg || "var(--ink-soft)",
        fontFamily: FM, fontSize: 11, letterSpacing: ".04em", fontWeight: 600,
      }}>{children}</span>
    );
  }

  function Field({ label, children }) {
    return (
      <div style={{ marginBottom: 14 }}>
        <div style={{
          fontFamily: FM, fontSize: 10, letterSpacing: ".14em",
          textTransform: "uppercase", color: "var(--ink-faint)", marginBottom: 5,
        }}>{label}</div>
        <div style={{ fontSize: 14, color: "var(--ink)", lineHeight: 1.45 }}>{children}</div>
      </div>
    );
  }

  function CheckList({ items, accent }) {
    if (!items || !items.length) return null;
    return (
      <ul style={{ margin: 0, padding: 0, listStyle: "none" }}>
        {items.map((p, i) => (
          <li key={i} style={{
            display: "flex", gap: 10, alignItems: "flex-start",
            marginBottom: 8, fontSize: 13.5, lineHeight: 1.45, color: "var(--ink)",
          }}>
            <span style={{
              flex: "0 0 16px", width: 16, height: 16, marginTop: 2,
              borderRadius: 4, border: `1.5px solid ${accent || "var(--forest-bord)"}`,
              background: "var(--pure)",
            }} />
            <span>{p}</span>
          </li>
        ))}
      </ul>
    );
  }

  function PanelTab({ id, active, onClick, children }) {
    return (
      <button
        onClick={() => onClick(id)}
        style={{
          padding: "10px 16px", borderRadius: 10,
          border: active ? "1.5px solid var(--gilt)" : "1.5px solid var(--canvas-dark)",
          background: active ? "var(--gilt-pale)" : "var(--pure)",
          boxShadow: "var(--shadow-sm)",
          fontFamily: FB, fontSize: 13, fontWeight: 600, color: "var(--ink)",
          cursor: "pointer",
        }}
      >{children}</button>
    );
  }

  /** Strip PDF / § section / bibliography chrome from staff-facing copy. */
  function staffClean(text) {
    if (!text) return "";
    return String(text)
      .replace(/\b[\w.-]*(?:MidandLowBack|NeckInjury|NonAcutePain|CRPS|MTG)\w*\.pdf\b/gi, "")
      .replace(/\bsourceDocs?\b[:\s].*/gi, "")
      .replace(/\b(?:also\s+)?§\s*[A-Z]?\d+(?:\.\d+[a-z]?)?(?:\s*\/\s*§\s*[A-Z]?\d+(?:\.\d+[a-z]?)?)*/gi, "")
      .replace(/\[\s*(?:Neck|Mid|Low|Non.?Acute|CRPS|MTG|§)[^\]]{0,80}\]/gi, "")
      .replace(/\(\s*§[^)]+\)/g, "")
      .replace(/\s{2,}/g, " ")
      .replace(/\s+([.,;:])/g, "$1")
      .trim();
  }

  function clinicalChapter(ch) {
    return staffClean(String(ch || "").replace(/\s*[·•]\s*§.*$/, "").replace(/\s*§.*$/, ""));
  }

  function isoDaysAgo(days) {
    const d = new Date();
    d.setDate(d.getDate() - days);
    return d.toISOString().slice(0, 10);
  }

  function isoToday() {
    return new Date().toISOString().slice(0, 10);
  }

  async function fetchJson(url, opts, timeoutMs) {
    const ac = new AbortController();
    const timer = setTimeout(() => ac.abort(), timeoutMs || 30_000);
    try {
      const res = await fetch(url, { ...(opts || {}), signal: ac.signal });
      const json = await res.json().catch(() => ({}));
      return { res, json };
    } finally {
      clearTimeout(timer);
    }
  }

  function caseStatusTone(status) {
    const s = String(status || "").toLowerCase();
    if (s === "responded") return { bg: "#E6F1EA", fg: "#1F5238", label: "Response on file" };
    if (s === "unanswered") return { bg: "#F6ECD7", fg: "#8C6D2F", label: "Needs review" };
    return { bg: "#EFEBE2", fg: "#6E6A61", label: "Needs review" };
  }

  /** Last Shield analysis chip for the case list. */
  function analysisListTone(status) {
    const s = String(status || "NOT_RUN").toUpperCase();
    if (s === "DEFENDABLE") return { bg: "#E6F1EA", fg: "#1F5238", label: "Defend" };
    if (s === "AT_FAULT") return { bg: "#F7E4E2", fg: "#B3261E", label: "Abandon" };
    if (s === "NEEDS_REVIEW") return { bg: "#F6ECD7", fg: "#8C6D2F", label: "Needs review" };
    return { bg: "#EFEBE2", fg: "#6E6A61", label: "Not run" };
  }

  /** Client-side mojibake check — mirrors server isGarbledExtractedText. */
  function looksGarbledText(text) {
    const sample = String(text || "").slice(0, 12_000);
    const len = sample.length;
    if (len < 20) return false;
    let yCount = 0;
    let alnum = 0;
    let space = 0;
    for (let i = 0; i < len; i++) {
      const code = sample.charCodeAt(i);
      const ch = sample[i];
      if (ch === "ÿ" || code === 0xff || ch === "\uFFFD") yCount += 1;
      if (/[A-Za-z0-9]/.test(ch)) alnum += 1;
      if (/\s/.test(ch)) space += 1;
    }
    const yRatio = yCount / len;
    const alnumAmongNonSpace = alnum / Math.max(1, len - space);
    if (yCount >= 12 && yRatio >= 0.04) return true;
    if (yCount >= 40) return true;
    if (len >= 40 && alnumAmongNonSpace < 0.18) return true;
    return false;
  }

  function isUsableLetterText(text, minLen) {
    const t = String(text || "").trim();
    if (t.length < (minLen || 40)) return false;
    return !looksGarbledText(t);
  }

  function looksLikeDenialLetterClient(text) {
    const t = String(text || "");
    if (!isUsableLetterText(t, 40)) return false;
    const hasC81 = /c[\s._-]*8[\s._-]*\.?\s*1|\bc81\b|form\s*c[\s._-]*8/i.test(t);
    const hasEor = /explanation\s*of\s*review|\bEOR\b|treatment\s*issue|denial|denied/i.test(t);
    if (/conciliation|proposed\s+decision|notice\s+of\s+decision/i.test(t) && !hasC81 && !/eor|denial/i.test(t)) {
      return false;
    }
    return hasC81 || hasEor;
  }

  /**
   * Honest case-list letter status — never claim a denial was "read" from a
   * garbled extract or empty chars on an attached doc.
   */
  function letterListStatus(c) {
    const refs = Array.isArray(c?.denialDocRefs) ? c.denialDocRefs : [];
    const summary = String(c?.denialSummary || "").trim();
    const hasDoc = refs.length > 0 || Number(c?.denialDocCount || 0) > 0;
    const readableChars = refs.some((r) => Number(r?.chars || 0) >= 40 && r?.extractMethod && r.extractMethod !== "none" && r.extractMethod !== "error");
    if (looksLikeDenialLetterClient(summary)) {
      return { kind: "readable", label: "Letter on file", tone: { bg: "#E6F1EA", fg: "#1F5238" } };
    }
    if (hasDoc || readableChars || (summary.length >= 20 && (looksGarbledText(summary) || !looksLikeDenialLetterClient(summary)))) {
      return {
        kind: "unreadable",
        label: "Letter found — could not read",
        tone: { bg: "#F6ECD7", fg: "#8C6D2F" },
      };
    }
    return { kind: "none", label: "No letter read yet", tone: { bg: "#EFEBE2", fg: "#6E6A61" } };
  }

  function inputStyle() {
    return {
      display: "block", width: "100%", marginTop: 5, padding: "10px 12px",
      borderRadius: 8, border: "1.5px solid var(--canvas-dark)",
      background: "var(--canvas)", fontFamily: FB, fontSize: 13,
    };
  }

  /** Deterministic CPT → staff category (mirrors src/workflows/wc-mtg/cpt-category.ts). */
  function categorizeCptClient(code) {
    const c = String(code || "").trim().toUpperCase();
    if (!c) return "Other";
    if (/^992\d{2}$|^993\d{2}$|^994\d{2}$/.test(c)) return "E/M";
    if (/^803\d{2}$|^80[0-2]\d{2}$|^82\d{3}$|^83\d{3}$/.test(c)
      || ["36415", "36416", "99000", "99001"].includes(c)) return "Lab/Tox";
    if (/^7[0-8]\d{3}$/.test(c) || ["77003", "77002", "76000"].includes(c)) return "Imaging";
    if ([
      "27096", "62321", "62323", "64483", "64484", "64479", "64480",
      "64490", "64491", "64492", "64493", "64494", "64495",
      "64633", "64634", "64635", "64636", "20552", "20553", "64405", "64450", "64451",
      "63650", "63655", "63663", "63664", "63685", "63688",
      "64555", "64575", "64590", "64595", "62290", "62291", "72275",
    ].includes(c)
      || /^6232\d$/.test(c) || /^644[5-9]\d$/.test(c) || /^6463[3-6]$/.test(c)
      || /^6365\d$|^6368\d$|^6455\d$|^6457\d$|^6459\d$/.test(c)) return "Intervention";
    if (/^\d{5}$/.test(c)) {
      const n = Number(c);
      if (n >= 10021 && n <= 69990) return "Surgery";
    }
    return "Other";
  }

  function primaryDeniedCptClient(list) {
    const arr = (Array.isArray(list) ? list : []).map((x) => String(x || "").trim()).filter(Boolean);
    if (!arr.length) return "";
    const rank = (code) => {
      const cat = categorizeCptClient(code);
      if (cat === "Intervention") return 0;
      if (cat === "Imaging") return 1;
      if (cat === "Surgery") return 2;
      if (cat === "Other") return 3;
      if (cat === "E/M") return 8;
      if (cat === "Lab/Tox") return 9;
      return 5;
    };
    return [...arr].sort((a, b) => rank(a) - rank(b) || a.localeCompare(b))[0] || "";
  }

  function casePrimaryCpt(c) {
    return (c && (c.primaryCpt || primaryDeniedCptClient(c.cpt))) || "";
  }

  function caseCptCategory(c) {
    if (c && c.cptCategory) return c.cptCategory;
    const p = casePrimaryCpt(c);
    return p ? categorizeCptClient(p) : "Other";
  }

  /** True when the row has actual C-8.1 denial evidence (letter/ERA/EOB/notes), not just queue membership. */
  function caseHasDenialEvidence(c) {
    if (!c) return false;
    if ((c.denialDocCount || 0) > 0) return true;
    if (c.denialSummary && String(c.denialSummary).trim()) return true;
    const via = String(c.letterFoundVia || "").toLowerCase();
    if (via && via !== "status_queue") return true;
    if (/\+\s*C-?8\.?1\s*(ERA|note)/i.test(c.billingStatus || "")) return true;
    if (c.hasAnalysis || c.hasStaffResponse) return true;
    return false;
  }

  /** Category II performance codes (e.g. 1036F) are never C-8.1 procedure denials. */
  function isCategoryTwoCpt(code) {
    return /^\d{4}F$/i.test(String(code || "").trim());
  }

  /** Row is a plausible C-8.1 case: has at least one CPT and its lead CPT isn't a Category II code. */
  function caseIsC81Candidate(c) {
    const codes = (c && c.cpt) || [];
    if (!codes.length) return false;
    const primary = casePrimaryCpt(c);
    if (primary && isCategoryTwoCpt(primary)) return false;
    return codes.some((code) => !isCategoryTwoCpt(code));
  }

  function cptCategoryTone(category) {
    const c = category || "Other";
    if (c === "Intervention") return { bg: "#E6F1EA", fg: "#1F5238", label: c };
    if (c === "Imaging") return { bg: "#E4EEF7", fg: "#1E4F78", label: c };
    if (c === "E/M") return { bg: "#EFEBE2", fg: "#6E6A61", label: c };
    if (c === "Lab/Tox") return { bg: "#F6ECD7", fg: "#8C6D2F", label: c };
    if (c === "Surgery") return { bg: "#F1E7D6", fg: "#9A6B2E", label: c };
    return { bg: "#EFEBE2", fg: "#6E6A61", label: c };
  }

  /* ─── C8.1 Shield ───────────────────────────────────────── */
  function C81ShieldPanel() {
    const [dateFrom, setDateFrom] = useState(() => isoDaysAgo(90));
    const [dateTo, setDateTo] = useState(() => isoToday());
    const [payerFilter, setPayerFilter] = useState("");
    const [statusFilter, setStatusFilter] = useState("all");
    const [cptFilter, setCptFilter] = useState("");
    const [cptSelect, setCptSelect] = useState("");
    const [categoryFilter, setCategoryFilter] = useState("all");
    const [showAllCandidates, setShowAllCandidates] = useState(false);
    const [cases, setCases] = useState([]);
    const [selectedId, setSelectedId] = useState(null);
    const [scanBusy, setScanBusy] = useState(false);
    const [scanProgress, setScanProgress] = useState("");
    const [scanSummary, setScanSummary] = useState("");
    const [caseCount, setCaseCount] = useState(0);
    const [error, setError] = useState("");

    // Case dashboard fields
    const [c81Text, setC81Text] = useState("");
    const [cpt, setCpt] = useState("");
    const [icd, setIcd] = useState("");
    const [dos, setDos] = useState("");
    const [payer, setPayer] = useState("");
    const [denialCode, setDenialCode] = useState("");
    const [denialReason, setDenialReason] = useState("");
    const [noteText, setNoteText] = useState("");
    const [uploadName, setUploadName] = useState("");
    const [uploadMeta, setUploadMeta] = useState(null);
    const [filePayload, setFilePayload] = useState(null);
    const [denialUnderstanding, setDenialUnderstanding] = useState(null);
    const [ocrBusy, setOcrBusy] = useState(false);
    const [ocrDone, setOcrDone] = useState(false);
    const [letterMissing, setLetterMissing] = useState(false);
    const [letterUnreadable, setLetterUnreadable] = useState(false);
    const [wrongDocKind, setWrongDocKind] = useState("");
    const [showOcrPreview, setShowOcrPreview] = useState(false);
    const [allowLive, setAllowLive] = useState(true);
    const [running, setRunning] = useState(false);
    const [analyzeStage, setAnalyzeStage] = useState(0);
    const [analyzeDoneFlash, setAnalyzeDoneFlash] = useState(false);
    const [staffResponse, setStaffResponse] = useState(null);
    const [responseBusy, setResponseBusy] = useState(false);
    const [responseCopied, setResponseCopied] = useState(false);
    const [letterAdjuster, setLetterAdjuster] = useState("");
    const [letterClaimNumber, setLetterClaimNumber] = useState("");
    const [billedServicesUsd, setBilledServicesUsd] = useState("");
    const [anesthesiaUsd, setAnesthesiaUsd] = useState("");
    const [firstSiInjection, setFirstSiInjection] = useState(false);
    const [carrierStatusNote, setCarrierStatusNote] = useState("");
    const [result, setResult] = useState(null);
    const [restoreBusy, setRestoreBusy] = useState(false);
    const [workSavedAt, setWorkSavedAt] = useState("");
    const [previousAnalyzedAt, setPreviousAnalyzedAt] = useState("");
    const saveTimerRef = useRef(null);
    const selectedIdRef = useRef(null);
    const skipAutosaveRef = useRef(true);

    const ANALYZE_STAGES = [
      { id: "denial", label: "Reading denial", detail: "Confirming CPT, DOS, and carrier language from the C-8.1 / denial letter." },
      { id: "notes", label: "Pulling chart notes", detail: "Collecting SI / lumbar WC notes across the appointment timeline." },
      { id: "mtg", label: "Matching MTG", detail: "Scoring Medical Treatment Guideline criteria against chart evidence." },
      { id: "verdict", label: "Drafting verdict", detail: "Preparing Defend / Abandon / Needs review with an MTG criteria checklist." },
    ];

    /** Readable letter from paste / OCR / upload — preferred path. */
    const letterReady = Boolean(
      isUsableLetterText(c81Text, 20) ||
      (denialUnderstanding && denialUnderstanding.ok && (denialUnderstanding.chars || 0) >= 20
        && isUsableLetterText(denialUnderstanding.textPreview || c81Text, 20)),
    );
    /**
     * Staff override when OCR failed: confirmed denied CPT + DOS + short reason.
     * Never dead-end a case because the letter could not be read.
     */
    const staffOverrideReady = Boolean(
      ocrDone &&
      !letterReady &&
      cpt.trim() &&
      !isEmOrAncillaryCpt(cpt.trim()) &&
      !isLabOrToxCpt(cpt.trim()) &&
      String(dos || "").trim().length >= 6 &&
      String(denialReason || "").trim().length >= 8,
    );
    const canAnalyze = letterReady || staffOverrideReady;
    const analyzeBlocked = running || ocrBusy || restoreBusy || !ocrDone || !canAnalyze || responseBusy;

    useEffect(() => {
      if (!running) return undefined;
      setAnalyzeStage(0);
      const timers = [
        setTimeout(() => setAnalyzeStage(1), 1800),
        setTimeout(() => setAnalyzeStage(2), 7000),
        setTimeout(() => setAnalyzeStage(3), 14000),
      ];
      return () => timers.forEach(clearTimeout);
    }, [running]);

    const selected = useMemo(
      () => cases.find((c) => c.id === selectedId) || null,
      [cases, selectedId],
    );

    const cptOptions = useMemo(() => {
      const set = new Set();
      for (const c of cases) {
        const p = casePrimaryCpt(c);
        if (p) set.add(p);
        for (const code of (c.cpt || [])) {
          const t = String(code || "").trim();
          if (t) set.add(t);
        }
      }
      return [...set].sort();
    }, [cases]);

    const visibleCases = useMemo(() => {
      const needle = String(cptFilter || "").trim();
      return cases.filter((c) => {
        // Default view: only rows with real C-8.1 denial evidence and a plausible procedure CPT.
        if (!showAllCandidates && !(caseHasDenialEvidence(c) && caseIsC81Candidate(c))) return false;
        if (statusFilter === "needs_review" && c.responseStatus === "responded") return false;
        if (statusFilter === "response_on_file" && c.responseStatus !== "responded") return false;
        const primary = casePrimaryCpt(c);
        const cat = caseCptCategory(c);
        if (categoryFilter !== "all" && cat !== categoryFilter) return false;
        if (cptSelect && primary !== cptSelect && !(c.cpt || []).includes(cptSelect)) return false;
        if (needle) {
          const hay = [primary, ...(c.cpt || [])].join(" ");
          if (!hay.includes(needle)) return false;
        }
        return true;
      });
    }, [cases, statusFilter, cptFilter, cptSelect, categoryFilter, showAllCandidates]);

    useEffect(() => {
      loadSavedCases();
    }, []);

    useEffect(() => {
      selectedIdRef.current = selectedId;
    }, [selectedId]);

    async function loadSavedCases() {
      try {
        const { res, json } = await fetchJson("/api/wc-mtg/c81/learning/cases?limit=150", null, 20_000);
        if (res.ok && Array.isArray(json.cases)) {
          setCases(json.cases);
          setCaseCount(json.count || json.cases.length);
          if (!scanSummary && json.cases.length) {
            setScanSummary(`${json.cases.length} saved case${json.cases.length === 1 ? "" : "s"}`);
          }
        }
        const st = await fetchJson("/api/wc-mtg/c81/learning/status", null, 10_000);
        if (st.res.ok) setCaseCount(st.json.caseCount || json.count || 0);
      } catch { /* keep empty list */ }
    }

    function parseMoneyInput(raw) {
      const s = String(raw || "").replace(/[$,\s]/g, "").trim();
      if (!s) return null;
      const n = Number(s);
      return Number.isFinite(n) ? n : null;
    }

    function buildLetterFactsPayload() {
      const services = parseMoneyInput(billedServicesUsd);
      const anesthesia = parseMoneyInput(anesthesiaUsd);
      return {
        adjuster: letterAdjuster.trim() || undefined,
        claimNumber: letterClaimNumber.trim() || undefined,
        appointmentId: selected?.appointmentId || undefined,
        billedServicesUsd: services == null ? undefined : services,
        anesthesiaUsd: anesthesia == null ? undefined : anesthesia,
        firstSiInjection: firstSiInjection === true ? true : undefined,
        carrierStatusNote: carrierStatusNote.trim() || undefined,
      };
    }

    function buildWorkspacePayload() {
      return {
        c81Text,
        cpt,
        icd,
        dos,
        payer,
        denialCode,
        denialReason,
        noteText,
        denialUnderstanding,
        letterMissing,
        letterUnreadable,
        wrongDocKind,
        ocrDone,
        uploadName,
        letterFacts: {
          adjuster: letterAdjuster.trim() || undefined,
          claimNumber: letterClaimNumber.trim() || undefined,
          billedServicesUsd: parseMoneyInput(billedServicesUsd),
          anesthesiaUsd: parseMoneyInput(anesthesiaUsd),
          firstSiInjection: firstSiInjection === true,
          carrierStatusNote: carrierStatusNote.trim() || undefined,
        },
      };
    }

    async function persistWorkspace(opts) {
      const c = opts?.caseRow || selected;
      if (!c?.id && !c?.patientId) return;
      try {
        const { res, json } = await fetchJson("/api/wc-mtg/c81/workspace", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            caseId: c.id,
            patientId: c.patientId,
            appointmentId: c.appointmentId,
            patientName: c.patientName,
            workspace: opts?.workspace || buildWorkspacePayload(),
          }),
        }, 20_000);
        if (res.ok && json.savedAt) setWorkSavedAt(json.savedAt);
      } catch { /* non-blocking auto-save */ }
    }

    function scheduleWorkspaceSave() {
      if (skipAutosaveRef.current || !selectedIdRef.current) return;
      if (saveTimerRef.current) clearTimeout(saveTimerRef.current);
      saveTimerRef.current = setTimeout(() => {
        void persistWorkspace();
      }, 900);
    }

    useEffect(() => {
      scheduleWorkspaceSave();
      return () => {
        if (saveTimerRef.current) clearTimeout(saveTimerRef.current);
      };
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [c81Text, cpt, icd, dos, payer, denialCode, denialReason, noteText,
      letterAdjuster, letterClaimNumber, billedServicesUsd, anesthesiaUsd, firstSiInjection, carrierStatusNote]);

    function applyWorkspace(ws) {
      if (!ws || typeof ws !== "object") return false;
      if (typeof ws.cpt === "string" && ws.cpt.trim()) setCpt(ws.cpt);
      if (typeof ws.icd === "string") setIcd(ws.icd);
      if (typeof ws.dos === "string" && ws.dos.trim()) setDos(ws.dos);
      if (typeof ws.payer === "string" && ws.payer.trim()) setPayer(ws.payer);
      if (typeof ws.denialCode === "string") setDenialCode(ws.denialCode);
      if (typeof ws.denialReason === "string") setDenialReason(ws.denialReason);
      if (typeof ws.noteText === "string") setNoteText(ws.noteText);
      if (typeof ws.c81Text === "string" && isUsableLetterText(ws.c81Text, 20)) {
        setC81Text(ws.c81Text);
      } else if (typeof ws.c81Text === "string" && ws.c81Text.trim()) {
        setC81Text(ws.c81Text);
      }
      if (ws.denialUnderstanding) setDenialUnderstanding(ws.denialUnderstanding);
      if (typeof ws.letterMissing === "boolean") setLetterMissing(ws.letterMissing);
      if (typeof ws.letterUnreadable === "boolean") setLetterUnreadable(ws.letterUnreadable);
      if (typeof ws.wrongDocKind === "string") setWrongDocKind(ws.wrongDocKind);
      if (typeof ws.uploadName === "string") setUploadName(ws.uploadName);
      if (ws.letterFacts && typeof ws.letterFacts === "object") {
        const lf = ws.letterFacts;
        if (typeof lf.adjuster === "string") setLetterAdjuster(lf.adjuster);
        if (typeof lf.claimNumber === "string") setLetterClaimNumber(lf.claimNumber);
        if (typeof lf.billedServicesUsd === "number") setBilledServicesUsd(String(lf.billedServicesUsd));
        if (typeof lf.anesthesiaUsd === "number") setAnesthesiaUsd(String(lf.anesthesiaUsd));
        if (typeof lf.firstSiInjection === "boolean") setFirstSiInjection(lf.firstSiInjection);
        if (typeof lf.carrierStatusNote === "string") setCarrierStatusNote(lf.carrierStatusNote);
      }
      if (ws.ocrDone || isUsableLetterText(ws.c81Text, 20) || ws.denialUnderstanding) {
        setOcrDone(true);
      }
      if (ws.savedAt) setWorkSavedAt(ws.savedAt);
      return Boolean(
        isUsableLetterText(ws.c81Text, 20) ||
        ws.denialUnderstanding ||
        (ws.cpt && ws.dos && ws.denialReason),
      );
    }

    function isLabOrToxCpt(code) {
      const c = String(code || "").trim();
      if (!c) return false;
      if (/^803\d{2}$/.test(c)) return true;
      if (/^80[0-2]\d{2}$/.test(c)) return true;
      if (/^82\d{3}$|^83\d{3}$/.test(c)) return true;
      return ["36415", "36416", "99000", "99001"].includes(c);
    }

    function isEmOrAncillaryCpt(code) {
      const c = String(code || "").trim().toUpperCase();
      if (!c) return false;
      if (/^9920[2-5]$|^9921[1-5]$/.test(c)) return true;
      if (/^G\d{4}$/.test(c) || /^\d{4}F$/.test(c)) return true;
      if (isLabOrToxCpt(c)) return true;
      return ["99070", "99080", "99401"].includes(c);
    }

    function firstDefenseCpt(list) {
      const arr = Array.isArray(list) ? list : [];
      return arr.find((c) => c && !isEmOrAncillaryCpt(c) && !isLabOrToxCpt(c)) || "";
    }

    function applyParsedFields(p, understanding, queueCpts) {
      if (!p && !understanding) return;
      const parsed = p || {};
      // Letter CPT wins; else API/queue interventional hints. Never clear a valid queue CPT to "".
      const fromLetter = firstDefenseCpt(understanding?.ok ? understanding.cpt : null);
      const fromParsed = firstDefenseCpt(parsed.cpt);
      const fromQueue = firstDefenseCpt(queueCpts);
      const nextCpt = fromLetter || fromParsed || fromQueue;
      // Prefill when we have a defense CPT; never wipe a queue-seeded CPT after OCR failure.
      if (nextCpt) setCpt(nextCpt);
      if (parsed.icd && parsed.icd.length) setIcd(parsed.icd.join(", "));
      else if (understanding?.icd?.length) setIcd(understanding.icd.join(", "));
      if (parsed.dos) setDos(parsed.dos);
      else if (understanding?.dos && understanding.dos !== "Not found on letter") setDos(understanding.dos);
      if (parsed.payer) setPayer(parsed.payer);
      else if (understanding?.payer && understanding.payer !== "Not found on letter") setPayer(understanding.payer);
      if (parsed.denialCodes && parsed.denialCodes.length) setDenialCode(parsed.denialCodes.join(", "));
      else if (understanding?.denialCodes?.length) setDenialCode(understanding.denialCodes.join(", "));
      if (parsed.denialReason) setDenialReason(parsed.denialReason);
      else if (understanding?.whySummary && understanding.whySummary !== "Not found on letter") {
        setDenialReason(understanding.whySummary);
      }
    }

    function billingNoteDenialReason(c) {
      const raw = String(c?.billingSignals || c?.denialSummary || "");
      if (!raw) return "";
      const hit =
        raw.match(/C-?8\.?1\s+denial[^.!?\n]{0,280}/i)?.[0] ||
        raw.match(/ASC\s+C-?8\.?1[^.!?\n]{0,280}/i)?.[0] ||
        raw.match(/Based on no auth denial[^.!?\n]{0,160}/i)?.[0] ||
        raw.match(/deviates from the MTG[^.!?\n]{0,280}/i)?.[0] ||
        "";
      return String(hit || "").replace(/\s+/g, " ").trim().slice(0, 320);
    }

    async function openCase(c) {
      skipAutosaveRef.current = true;
      if (saveTimerRef.current) clearTimeout(saveTimerRef.current);
      setSelectedId(c.id);
      selectedIdRef.current = c.id;
      // Prefill queue denied CPT immediately (editable). Never seed E/M/lab.
      setCpt(firstDefenseCpt(c.cpt) || "");
      setIcd("");
      setDos(c.dos || "");
      setPayer(c.payer || "");
      setDenialCode("");
      // Prefill from billing-note C-8.1 language so Analyze unlocks when OCR has no DOS-matched PDF.
      setDenialReason(billingNoteDenialReason(c));
      setC81Text("");
      setNoteText("");
      setUploadName("");
      setUploadMeta(null);
      setFilePayload(null);
      setDenialUnderstanding(null);
      setOcrDone(false);
      setLetterMissing(false);
      setLetterUnreadable(false);
      setWrongDocKind("");
      setShowOcrPreview(false);
      setResult(null);
      setStaffResponse(null);
      setResponseCopied(false);
      setLetterAdjuster("");
      setLetterClaimNumber("");
      setBilledServicesUsd("");
      setAnesthesiaUsd("");
      setFirstSiInjection(false);
      setCarrierStatusNote("");
      // Leslie-confirmed Conway tip facts (first SI under $1k) — seed only when opening that case.
      if (String(c.appointmentId || "") === "396402377") {
        setFirstSiInjection(true);
        setBilledServicesUsd("594.03");
        setAnesthesiaUsd("148.55");
        setCarrierStatusNote("Adjuster sent claim back for review.");
      }
      setAnalyzeDoneFlash(false);
      setAnalyzeStage(0);
      setError("");
      setAllowLive(true);
      setWorkSavedAt("");
      setPreviousAnalyzedAt("");
      setRestoreBusy(true);

      let restoredUseful = false;
      try {
        const { res, json } = await fetchJson(
          `/api/wc-mtg/c81/learning/cases/${encodeURIComponent(c.id)}`,
          null,
          20_000,
        );
        if (selectedIdRef.current !== c.id) return;
        if (res.ok && json.case) {
          const detail = json.case;
          if (detail.workspace) {
            restoredUseful = applyWorkspace(detail.workspace);
          }
          if (detail.analysis && detail.analysis.ok) {
            setResult(detail.analysis);
            setOcrDone(true);
            restoredUseful = true;
            if (detail.analyzedAt) setWorkSavedAt(detail.analyzedAt);
          }
          if (detail.staffResponse && detail.staffResponse.text) {
            setStaffResponse(detail.staffResponse);
            restoredUseful = true;
          }
          if (detail.previousAnalyzedAt) setPreviousAnalyzedAt(detail.previousAnalyzedAt);
          // Merge list row analysis status so chips stay accurate after reopen.
          setCases((prev) => prev.map((row) => (
            row.id === c.id
              ? {
                  ...row,
                  analysisStatus: detail.analysisStatus || row.analysisStatus,
                  analyzedAt: detail.analyzedAt || row.analyzedAt,
                  hasAnalysis: detail.hasAnalysis,
                  hasStaffResponse: detail.hasStaffResponse,
                  hasWorkspace: detail.hasWorkspace,
                }
              : row
          )));
        }
      } catch { /* fall through to extract */ }

      if (selectedIdRef.current !== c.id) return;
      setRestoreBusy(false);
      // Re-extract only when nothing durable was restored (blank slate).
      if (!restoredUseful) {
        void runCaseExtract(c).finally(() => {
          skipAutosaveRef.current = false;
        });
      } else {
        skipAutosaveRef.current = false;
      }
    }

    function backToList() {
      skipAutosaveRef.current = true;
      if (saveTimerRef.current) clearTimeout(saveTimerRef.current);
      // Flush pending field edits before leaving the case.
      if (selected) void persistWorkspace({ caseRow: selected });
      setSelectedId(null);
      setResult(null);
      setStaffResponse(null);
      setResponseCopied(false);
      setAnalyzeDoneFlash(false);
      setAnalyzeStage(0);
      setError("");
      setDenialUnderstanding(null);
      setOcrBusy(false);
      setOcrDone(false);
      setLetterMissing(false);
      setLetterUnreadable(false);
      setWrongDocKind("");
      setRestoreBusy(false);
      setWorkSavedAt("");
      setPreviousAnalyzedAt("");
      void loadSavedCases();
    }

    async function runCaseExtract(c, extra) {
      setOcrBusy(true);
      setError("");
      try {
        const body = {
          caseId: c?.id || selected?.id,
          patientId: c?.patientId || selected?.patientId,
          dos: c?.dos || dos || undefined,
          payer: c?.payer || payer || undefined,
          cpt: (c?.cpt && c.cpt.length) ? c.cpt : (cpt.trim() ? [cpt.trim()] : undefined),
          persist: true,
          allowLiveChart: true,
          ...(extra || {}),
        };
        const { res, json } = await fetchJson("/api/wc-mtg/c81/case-extract", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(body),
        }, 120_000);
        if (!res.ok && json.error) throw new Error(json.error);
        setDenialUnderstanding(json.denialUnderstanding || null);
        const text = String(json.c81Text || "");
        const usable = isUsableLetterText(text, 20);
        // Never wipe staff-pasted denial text when chart OCR fails.
        setC81Text((prev) => (usable ? text : (isUsableLetterText(prev, 20) ? prev : "")));
        applyParsedFields(json.parsed, json.denialUnderstanding, c?.cpt || selected?.cpt);
        const wrongKind = String(json.wrongDocKind || "").trim();
        setWrongDocKind(wrongKind);
        const unreadable = !wrongKind && (json.letterUnreadable === true ||
          (Boolean(text) && !usable) ||
          ((selected?.denialDocRefs || c?.denialDocRefs || []).length > 0 && !usable && json.ok === false));
        const missing = !unreadable && !wrongKind && (
          json.letterMissing === true ||
          !usable ||
          (json.denialUnderstanding && json.denialUnderstanding.ok === false && !usable)
        );
        setLetterMissing(missing);
        setLetterUnreadable(unreadable);
        // Keep / restore billing-note denial reason so Analyze stays unlocked without OCR.
        if (!usable) {
          const fromLetter = String(json.denialUnderstanding?.whySummary || "").trim();
          const fromBilling = billingNoteDenialReason(c || selected);
          setDenialReason((prev) => {
            if (prev && prev.length >= 8) return prev;
            if (fromLetter && fromLetter !== "Not found on letter" && fromLetter.length >= 8) return fromLetter;
            return fromBilling || prev;
          });
        }
        setOcrDone(true);
        setUploadMeta({
          ok: json.ok && usable,
          extractor: json.extractMethod,
          needsReviewFields: json.needsReviewFields,
          limits: json.limits,
          source: json.source,
          letterMissing: missing,
          letterUnreadable: unreadable,
          wrongDocKind: wrongKind || undefined,
        });
        if (wrongKind) {
          setError(
            wrongKind === "conciliation"
              ? "Chart document looks like a conciliation / board decision, not a C-8.1 denial — upload or paste the denial letter."
              : "Chart document does not look like a C-8.1 / EOR denial — upload or paste the denial letter.",
          );
        } else if (unreadable) {
          setError("Letter found — could not read (retry OCR / upload).");
        } else if (missing) {
          setError("Denial letter not found on chart — upload or paste the letter, or confirm CPT/DOS and a short denial reason to proceed.");
        }
      } catch (err) {
        setOcrDone(true);
        setLetterMissing(true);
        setLetterUnreadable(false);
        setDenialUnderstanding((prev) => prev || {
          whatWasDenied: "Not found on letter",
          denialCodesDisplay: "Not found on letter",
          whySummary: "Not found on letter",
          extractMethodLabel: "No readable denial text yet",
          textPreview: "",
          ok: false,
          chars: 0,
          limits: [err.message || "Could not read denial letter"],
        });
        if (err.name !== "AbortError") {
          setError(err.message || "Denial letter not found on chart — upload required.");
        }
      } finally {
        setOcrBusy(false);
      }
    }

    function readFileAsBase64(file) {
      return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = () => {
          const s = String(reader.result || "");
          const i = s.indexOf(",");
          resolve(i >= 0 ? s.slice(i + 1) : s);
        };
        reader.onerror = () => reject(new Error("Could not read file"));
        reader.readAsDataURL(file);
      });
    }

    async function onPickFile(e) {
      const file = e.target.files && e.target.files[0];
      if (!file) return;
      setError("");
      setUploadName(file.name);
      setOcrBusy(true);
      setShowOcrPreview(false);
      try {
        const b64 = await readFileAsBase64(file);
        setFilePayload({ fileName: file.name, mimeType: file.type || undefined, fileBase64: b64 });
        const { res, json } = await fetchJson("/api/wc-mtg/c81/case-extract", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            caseId: selected?.id || undefined,
            patientId: selected?.patientId || undefined,
            fileName: file.name,
            mimeType: file.type || undefined,
            fileBase64: b64,
            dos: dos || selected?.dos || undefined,
            payer: payer || selected?.payer || undefined,
            cpt: (selected?.cpt && selected.cpt.length) ? selected.cpt : (cpt.trim() ? [cpt.trim()] : undefined),
            persist: true,
          }),
        }, 120_000);
        if (!res.ok && json.error) throw new Error(json.error);
        setUploadMeta(json);
        setDenialUnderstanding(json.denialUnderstanding || null);
        const text = String(json.c81Text || "");
        const usable = isUsableLetterText(text, 20);
        setC81Text(usable ? text : "");
        applyParsedFields(json.parsed, json.denialUnderstanding, selected?.cpt);
        const wrongKind = String(json.wrongDocKind || "").trim();
        setWrongDocKind(wrongKind);
        const unreadable = !wrongKind && (json.letterUnreadable === true || (Boolean(file) && !usable));
        const missing = !unreadable && !wrongKind && (json.letterMissing === true || !usable);
        setLetterMissing(missing);
        setLetterUnreadable(unreadable);
        setOcrDone(true);
        if (wrongKind) {
          setError("Uploaded file does not look like a C-8.1 / EOR denial — try another file or paste the letter.");
        } else if (unreadable) setError("Letter found — could not read (retry OCR / upload).");
        else if (missing) setError("Could not read usable text from that file — try another PDF or paste the letter.");
        else setError("");
      } catch (err) {
        setUploadMeta(null);
        setFilePayload(null);
        setLetterMissing(true);
        setLetterUnreadable(false);
        setError(err.name === "AbortError" ? "Upload timed out — try a smaller file" : (err.message || "Upload failed"));
      } finally {
        setOcrBusy(false);
        e.target.value = "";
      }
    }

    async function runScan() {
      setScanBusy(true);
      setError("");
      setScanSummary("");
      setScanProgress("Starting C-8.1 search…");
      setSelectedId(null);
      setResult(null);
      try {
        if (!dateFrom || !dateTo) throw new Error("Choose a from and to date");
        if (dateFrom > dateTo) throw new Error("From date must be on or before the to date");

        const { res: startRes, json: startJson } = await fetchJson("/api/wc-mtg/c81/scan-queue", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            startDate: dateFrom,
            endDate: dateTo,
            payer: payerFilter.trim() || undefined,
            depth: "queue",
            maxPatients: 100,
            enrichTopPerPatient: 0,
            persist: true,
          }),
        }, 45_000);

        if (!startRes.ok && startJson.error) throw new Error(startJson.error);
        const jobId = startJson.jobId;
        if (!jobId) throw new Error("Search did not start — reconnect DrChrono and try again");
        if (startJson.accepted === false) {
          setScanProgress("A search is already running — waiting for it to finish…");
        }

        const deadline = Date.now() + 200_000;
        let json = null;
        while (Date.now() < deadline) {
          await new Promise((r) => setTimeout(r, 2000));
          let poll;
          try {
            poll = await fetchJson(`/api/wc-mtg/c81/scan-queue/${jobId}`, null, 20_000);
          } catch (err) {
            if (err.name === "AbortError") {
              setScanProgress("Still searching… (slow response from DrChrono)");
              continue;
            }
            throw err;
          }
          const pj = poll.json;
          if (!poll.res.ok && pj.error) throw new Error(pj.error);
          if (pj.progress?.message) setScanProgress(pj.progress.message);
          else if (pj.running) setScanProgress("Searching C-8.1 denials queue…");
          if (!pj.running) {
            json = pj.result || pj;
            break;
          }
        }

        if (!json) {
          throw new Error("Search timed out. Narrow the date range and try again.");
        }
        if (json.error && json.ok === false) throw new Error(json.error);

        const found = Array.isArray(json.cases) ? json.cases : [];
        setCases(found);
        setCaseCount(found.length);
        setScanSummary(
          found.length
            ? `${found.length} case${found.length === 1 ? "" : "s"} found`
            : "No cases found in this date range",
        );
        setScanProgress("");
      } catch (err) {
        setScanProgress("");
        setError(
          err.name === "AbortError"
            ? "Search request timed out — check DrChrono session and try again"
            : (err.message || "Search failed"),
        );
      } finally {
        setScanBusy(false);
      }
    }

    async function runAnalyze() {
      if (!selected || running || ocrBusy) return;
      if (!canAnalyze && !filePayload) {
        setError("Upload or paste the denial letter, or confirm CPT, DOS, and a short denial reason to proceed.");
        return;
      }
      // Lab / visit codes are not the denied procedure — clear and let documentation path run.
      let analyzeCpt = cpt.trim();
      if (analyzeCpt && (isEmOrAncillaryCpt(analyzeCpt) || isLabOrToxCpt(analyzeCpt))) {
        setCpt("");
        analyzeCpt = "";
      }
      if (!letterReady && staffOverrideReady && !analyzeCpt) {
        setError("Enter the denied CPT (from the queue or letter) before analyzing without OCR.");
        return;
      }
      setRunning(true);
      setError("");
      setResult(null);
      setStaffResponse(null);
      setResponseCopied(false);
      setAnalyzeDoneFlash(false);
      setAnalyzeStage(0);
      try {
        // Put confirmed codes/reason into letter text so denial-type routing can see them.
        const staffOverrideBanner = (!letterReady && staffOverrideReady)
          ? "Proceeding without OCR’d letter. Staff-confirmed CPT, DOS, and denial reason."
          : "";
        const letterForAnalyze = [
          staffOverrideBanner,
          denialCode.trim() ? `Reason codes: ${denialCode.trim()}` : "",
          denialReason.trim() ? `Denial reason: ${denialReason.trim()}` : "",
          analyzeCpt ? `CPT: ${analyzeCpt}` : "",
          (dos.trim() || selected.dos) ? `DOS: ${dos.trim() || selected.dos}` : "",
          c81Text.trim(),
        ].filter(Boolean).join("\n");
        const body = {
          caseId: selected.id || undefined,
          patientId: selected.patientId || undefined,
          appointmentId: selected.appointmentId || undefined,
          c81Text: letterForAnalyze || undefined,
          cpt: analyzeCpt || undefined,
          icd: icd.trim() || undefined,
          dos: dos.trim() || selected.dos || undefined,
          denialReason: denialReason.trim() || undefined,
          denialCode: denialCode.trim() || undefined,
          payer: payer.trim() || selected.payer || undefined,
          noteText: noteText.trim() || undefined,
          source: allowLive ? "live" : "auto",
          allowLive: allowLive === true,
          generativeDraft: false,
          staffOverrideNoOcr: Boolean(!letterReady && staffOverrideReady),
          extractMethod: uploadMeta?.extractor
            || (denialUnderstanding && /view eob|era/i.test(String(denialUnderstanding.extractMethodLabel || ""))
              ? "era-view-eob"
              : undefined)
            || selected.letterFoundVia
            || undefined,
          letterSourceLabel: (denialUnderstanding && denialUnderstanding.extractMethodLabel)
            || letterFoundViaLabel(selected.letterFoundVia)
            || undefined,
        };
        if (!body.c81Text && filePayload) {
          body.fileName = filePayload.fileName;
          body.mimeType = filePayload.mimeType;
          body.fileBase64 = filePayload.fileBase64;
        }
        const { res, json } = await fetchJson("/api/wc-mtg/c81/analyze", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(body),
        }, 240_000);
        if (!res.ok && json.error) throw new Error(json.error);
        setAnalyzeStage(ANALYZE_STAGES.length - 1);
        setResult(json);
        setAnalyzeDoneFlash(true);
        if (json.upload) setUploadMeta((m) => ({ ...(m || {}), ...json.upload }));
        if (json.persisted?.analyzedAt) {
          setPreviousAnalyzedAt((prev) => workSavedAt || prev);
          setWorkSavedAt(json.persisted.analyzedAt);
        }
        if (json.persisted?.analysisStatus) {
          setCases((prev) => prev.map((row) => (
            row.id === selected.id
              ? {
                  ...row,
                  analysisStatus: json.persisted.analysisStatus,
                  analyzedAt: json.persisted.analyzedAt,
                  hasAnalysis: true,
                }
              : row
          )));
        }
        // Persist confirmed fields alongside analysis (belt-and-suspenders).
        void persistWorkspace({
          caseRow: selected,
          workspace: { ...buildWorkspacePayload(), ocrDone: true },
        });
      } catch (e) {
        setResult(null);
        setAnalyzeDoneFlash(false);
        setError(
          e.name === "AbortError"
            ? "Analysis timed out while pulling the chart — reconnect DrChrono and try again, or paste notes."
            : (e.message || "Analysis failed"),
        );
      } finally {
        setRunning(false);
      }
    }

    async function runGenerateResponse() {
      if (!result || !result.ok || responseBusy || running) return;
      setResponseBusy(true);
      setError("");
      setResponseCopied(false);
      try {
        const { res, json } = await fetchJson("/api/wc-mtg/c81/generate-response", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            analysis: {
              ...result,
              patient: {
                ...(result.patient || {}),
                name: result.patient?.name || selected?.patientName || undefined,
              },
              claim: {
                ...(result.claim || {}),
                claimNumber: letterClaimNumber.trim() || result.claim?.claimNumber,
              },
            },
            caseId: selected?.id,
            patientId: selected?.patientId,
            appointmentId: selected?.appointmentId,
            letterFacts: buildLetterFactsPayload(),
          }),
        }, 45_000);
        if (!res.ok && json.error) throw new Error(json.error);
        setStaffResponse(json.draftArgument || null);
        if (!json.draftArgument?.text) throw new Error("No response letter was generated");
        if (json.persisted?.responseGeneratedAt) setWorkSavedAt(json.persisted.responseGeneratedAt);
        if (selected?.id) {
          setCases((prev) => prev.map((row) => (
            row.id === selected.id ? { ...row, hasStaffResponse: true } : row
          )));
        }
      } catch (e) {
        setStaffResponse(null);
        setError(e.name === "AbortError" ? "Response generation timed out" : (e.message || "Could not generate response"));
      } finally {
        setResponseBusy(false);
      }
    }

    async function copyStaffResponse() {
      const text = staffResponse?.text || result?.draftArgument?.text || "";
      if (!text) return;
      try {
        await navigator.clipboard.writeText(text);
        setResponseCopied(true);
      } catch {
        setResponseCopied(false);
        setError("Could not copy to clipboard — select the letter text manually.");
      }
    }

    const vt = result ? verdictTone(result.verdict) : null;

    /* ── Case dashboard ───────────────────────────────────── */
    if (selected) {
      return (
        <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap" }}>
            <button
              type="button"
              onClick={backToList}
              style={{
                padding: "8px 12px", borderRadius: 8,
                border: "1.5px solid var(--canvas-dark)", background: "var(--pure)",
                fontFamily: FB, fontSize: 13, fontWeight: 600, color: "var(--ink)", cursor: "pointer",
              }}
            >← Back to cases</button>
            <div style={{ flex: 1, minWidth: 200 }}>
              <div style={{ fontFamily: FD, fontSize: 22, fontWeight: 700, color: "var(--forest)" }}>
                {selected.patientName || "Patient"}
              </div>
              <div style={{ fontSize: 13, color: "var(--ink-soft)", marginTop: 2, display: "flex", flexWrap: "wrap", gap: 8, alignItems: "center" }}>
                <span>
                  DOS {selected.dos || dos || "—"}
                  {cpt || casePrimaryCpt(selected) ? ` · CPT ${cpt || casePrimaryCpt(selected)}` : ""}
                  {selected.payer ? ` · ${selected.payer}` : ""}
                </span>
                {(cpt || casePrimaryCpt(selected)) ? (
                  <Chip tone={cptCategoryTone(
                    (result && (result.cptCategory || result.claim?.cptCategory))
                    || categorizeCptClient(cpt || casePrimaryCpt(selected))
                    || caseCptCategory(selected)
                  )}>
                    {(result && (result.cptCategory || result.claim?.cptCategory))
                      || categorizeCptClient(cpt || casePrimaryCpt(selected))
                      || caseCptCategory(selected)}
                  </Chip>
                ) : null}
              </div>
            </div>
            <Chip tone={analysisListTone(selected.analysisStatus || (result && result.verdict) || "NOT_RUN")}>
              {analysisListTone(selected.analysisStatus || (result && result.verdict) || "NOT_RUN").label}
            </Chip>
            {workSavedAt ? (
              <span style={{ fontSize: 12, color: "var(--ink-soft)" }}>
                Saved {new Date(workSavedAt).toLocaleString()}
                {previousAnalyzedAt ? ` · prior ${new Date(previousAnalyzedAt).toLocaleString()}` : ""}
              </span>
            ) : null}
            {restoreBusy ? (
              <span style={{ fontSize: 12, color: "var(--ink-soft)" }}>Restoring saved work…</span>
            ) : null}
          </div>

          <div style={{
            display: "grid", gridTemplateColumns: "minmax(280px, 360px) 1fr",
            gap: 16, alignItems: "start",
          }}>
            <div style={{
              background: "var(--pure)", border: "1px solid var(--canvas-dark)",
              borderRadius: 14, padding: 18, boxShadow: "var(--shadow-sm)",
            }}>
              <div style={{
                fontFamily: FM, fontSize: 10, letterSpacing: ".14em",
                textTransform: "uppercase", color: "var(--ink-faint)", marginBottom: 12,
              }}>Case workspace</div>

              <div style={{ marginBottom: 12 }}>
                <div style={{ color: "var(--ink-soft)", fontSize: 13, marginBottom: 5 }}>
                  Upload denial (PDF / DOC / DOCX)
                </div>
                <label style={{
                  display: "flex", alignItems: "center", justifyContent: "center",
                  padding: "14px 12px", borderRadius: 10, cursor: ocrBusy ? "wait" : "pointer",
                  border: "1.5px dashed var(--canvas-dark)", background: "var(--canvas)",
                  fontFamily: FB, fontSize: 13, fontWeight: 600, color: "var(--forest)",
                  opacity: ocrBusy ? 0.7 : 1,
                }}>
                  <input
                    type="file"
                    accept=".pdf,.doc,.docx,application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document"
                    onChange={onPickFile}
                    disabled={ocrBusy}
                    style={{ display: "none" }}
                  />
                  {ocrBusy ? "Reading denial letter…" : (uploadName ? `Attached · ${uploadName}` : "Choose denial file…")}
                </label>
                {uploadMeta ? (
                  <div style={{ marginTop: 8, fontSize: 12, color: "var(--ink-soft)", lineHeight: 1.4 }}>
                    {uploadMeta.ok ? "Denial letter read" : "Could not fully read denial letter"}
                    {(uploadMeta.needsReviewFields || []).length
                      ? ` · please confirm: ${uploadMeta.needsReviewFields.join(", ")}`
                      : ""}
                  </div>
                ) : null}
              </div>

              {/* Denial understanding — always shown before analysis */}
              <div style={{
                marginBottom: 14, padding: 14, borderRadius: 12,
                border: "1.5px solid var(--gilt)", background: "var(--gilt-pale)",
              }}>
                <div style={{
                  fontFamily: FM, fontSize: 10, letterSpacing: ".14em",
                  textTransform: "uppercase", color: "var(--ink-faint)", marginBottom: 8,
                }}>
                  Denial letter · review before analysis
                </div>
                {ocrBusy ? (
                  <div style={{ fontSize: 13, color: "var(--ink-soft)", lineHeight: 1.45 }}>
                    Reading the C-8.1 / denial letter…
                  </div>
                ) : (
                  <>
                    <div style={{ marginBottom: 10 }}>
                      <div style={{ fontSize: 11, color: "var(--ink-faint)", marginBottom: 3 }}>What was denied</div>
                      <div style={{ fontSize: 13.5, color: "var(--ink)", lineHeight: 1.4, fontWeight: 600 }}>
                        {(denialUnderstanding && denialUnderstanding.whatWasDenied) || "Not found on letter"}
                      </div>
                    </div>
                    <div style={{ marginBottom: 10 }}>
                      <div style={{ fontSize: 11, color: "var(--ink-faint)", marginBottom: 3 }}>Denial / reason codes</div>
                      <div style={{ fontSize: 13.5, color: "var(--ink)", lineHeight: 1.4 }}>
                        {(denialUnderstanding && denialUnderstanding.denialCodesDisplay) || "Not found on letter"}
                      </div>
                    </div>
                    <div style={{ marginBottom: 10 }}>
                      <div style={{ fontSize: 11, color: "var(--ink-faint)", marginBottom: 3 }}>Why (from letter)</div>
                      <div style={{ fontSize: 13.5, color: "var(--ink)", lineHeight: 1.45 }}>
                        {(denialUnderstanding && denialUnderstanding.whySummary) || "Not found on letter"}
                      </div>
                    </div>
                    {denialUnderstanding?.extractMethodLabel ? (
                      <div style={{ fontSize: 11.5, color: "var(--ink-soft)", marginBottom: 8 }}>
                        {denialUnderstanding.extractMethodLabel}
                      </div>
                    ) : null}
                    <button
                      type="button"
                      onClick={() => setShowOcrPreview((v) => !v)}
                      style={{
                        padding: "6px 10px", borderRadius: 8,
                        border: "1px solid var(--canvas-dark)", background: "var(--pure)",
                        fontFamily: FB, fontSize: 12, fontWeight: 600, color: "var(--forest)",
                        cursor: "pointer",
                      }}
                    >
                      {showOcrPreview ? "Hide letter text" : "Show letter text (verify OCR)"}
                    </button>
                    {showOcrPreview ? (
                      <pre style={{
                        marginTop: 8, maxHeight: 180, overflow: "auto",
                        padding: 10, borderRadius: 8, background: "var(--pure)",
                        border: "1px solid var(--canvas-dark)",
                        fontFamily: FB, fontSize: 11, lineHeight: 1.4, whiteSpace: "pre-wrap",
                        color: "var(--ink-soft)",
                      }}>
                        {(denialUnderstanding && denialUnderstanding.textPreview)
                          || c81Text
                          || "No letter text available yet. Upload the denial PDF or paste text below."}
                      </pre>
                    ) : null}
                  </>
                )}
              </div>

              <div style={{
                fontFamily: FM, fontSize: 10, letterSpacing: ".14em",
                textTransform: "uppercase", color: "var(--ink-faint)", marginBottom: 8,
              }}>Confirm fields (editable)</div>

              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8, marginBottom: 10 }}>
                <label style={{ display: "block", fontSize: 13 }}>
                  <span style={{ color: "var(--ink-soft)" }}>CPT</span>
                  <input value={cpt} onChange={(e) => setCpt(e.target.value)} placeholder="e.g. 64490" style={inputStyle()} />
                </label>
                <label style={{ display: "block", fontSize: 13 }}>
                  <span style={{ color: "var(--ink-soft)" }}>DOS</span>
                  <input value={dos} onChange={(e) => setDos(e.target.value)} placeholder="MM/DD/YYYY" style={inputStyle()} />
                </label>
              </div>

              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8, marginBottom: 10 }}>
                <label style={{ display: "block", fontSize: 13 }}>
                  <span style={{ color: "var(--ink-soft)" }}>ICD</span>
                  <input value={icd} onChange={(e) => setIcd(e.target.value)} placeholder="e.g. M47.812" style={inputStyle()} />
                </label>
                <label style={{ display: "block", fontSize: 13 }}>
                  <span style={{ color: "var(--ink-soft)" }}>Payer</span>
                  <input value={payer} onChange={(e) => setPayer(e.target.value)} placeholder="Carrier name" style={inputStyle()} />
                </label>
              </div>

              <label style={{ display: "block", marginBottom: 10, fontSize: 13 }}>
                <span style={{ color: "var(--ink-soft)" }}>Denial code(s)</span>
                <input
                  value={denialCode}
                  onChange={(e) => setDenialCode(e.target.value)}
                  placeholder="Codes from letter, if any"
                  style={inputStyle()}
                />
              </label>

              <label style={{ display: "block", marginBottom: 10, fontSize: 13 }}>
                <span style={{ color: "var(--ink-soft)" }}>Denial reason (from letter or staff)</span>
                <input
                  value={denialReason}
                  onChange={(e) => setDenialReason(e.target.value)}
                  placeholder="Short reason — required to analyze if letter is unreadable"
                  style={inputStyle()}
                />
              </label>

              <label style={{ display: "block", marginBottom: 10, fontSize: 13 }}>
                <span style={{ color: "var(--ink-soft)" }}>Denial / C-8.1 text</span>
                <textarea
                  value={c81Text}
                  onChange={(e) => {
                    const v = e.target.value;
                    setC81Text(v);
                    setOcrDone(true);
                    setLetterMissing(v.trim().length < 20);
                    if (v.trim().length >= 20) setError("");
                  }}
                  rows={3}
                  placeholder="Paste denial notice text if upload is unavailable"
                  style={{ ...inputStyle(), resize: "vertical", fontFamily: FB }}
                />
              </label>

              {ocrDone && !ocrBusy && !letterReady ? (
                <div style={{
                  marginBottom: 14, padding: 12, borderRadius: 10,
                  background: "var(--deny-pale)", border: "1.5px solid var(--deny)",
                  color: "var(--deny)", fontSize: 13, fontWeight: 600, lineHeight: 1.45,
                }}>
                  {wrongDocKind === "conciliation"
                    ? "Chart document looks like a conciliation / board decision, not a C-8.1 denial — upload or paste the denial letter."
                    : wrongDocKind
                      ? "Chart document does not look like a C-8.1 / EOR denial — upload or paste the denial letter."
                      : letterUnreadable
                        ? "Letter found — could not read (retry OCR / upload)."
                        : "Denial letter not found on chart — upload, paste, or confirm CPT/DOS and a short denial reason."}
                  <div style={{ marginTop: 8, display: "flex", flexWrap: "wrap", gap: 8 }}>
                    <button
                      type="button"
                      disabled={ocrBusy}
                      onClick={() => void runCaseExtract(selected)}
                      style={{
                        padding: "6px 10px", borderRadius: 8, border: "1px solid var(--deny)",
                        background: "var(--pure)", color: "var(--deny)",
                        fontFamily: FB, fontSize: 12, fontWeight: 700, cursor: "pointer",
                      }}
                    >Retry OCR</button>
                  </div>
                  {staffOverrideReady ? (
                    <div style={{ marginTop: 8, fontWeight: 600, fontSize: 12.5, color: "var(--ink)" }}>
                      Proceeding without OCR’d letter — CPT, DOS, and denial reason confirmed by staff.
                    </div>
                  ) : (
                    <div style={{ marginTop: 8, fontWeight: 500, fontSize: 12.5 }}>
                      To analyze without a readable letter: confirm the queue CPT and DOS, type a short denial reason, then Analyze unlocks.
                    </div>
                  )}
                  {selected?.cpt?.some?.((c) => isEmOrAncillaryCpt(c)) && !firstDefenseCpt(selected.cpt) ? (
                    <div style={{ marginTop: 6, fontWeight: 500, fontSize: 12.5 }}>
                      Queue visit codes ({(selected.cpt || []).filter(isEmOrAncillaryCpt).slice(0, 3).join(", ")})
                      {" "}are not the denied procedure — enter the denied CPT from the letter.
                    </div>
                  ) : null}
                </div>
              ) : null}

              <label style={{ display: "block", marginBottom: 10, fontSize: 13 }}>
                <span style={{ color: "var(--ink-soft)" }}>Staff notes / context</span>
                <textarea
                  value={noteText}
                  onChange={(e) => setNoteText(e.target.value)}
                  rows={3}
                  placeholder="Optional notes for OpAgent"
                  style={{ ...inputStyle(), resize: "vertical" }}
                />
              </label>

              <label style={{
                display: "flex", alignItems: "center", gap: 8, marginBottom: 14,
                fontSize: 12.5, color: "var(--ink-soft)", cursor: "pointer",
              }}>
                <input type="checkbox" checked={allowLive} onChange={(e) => setAllowLive(e.target.checked)} />
                Pull chart notes from DrChrono for this patient
              </label>

              <button
                type="button"
                onClick={runAnalyze}
                disabled={analyzeBlocked}
                title={
                  running ? "Analysis in progress — please wait"
                    : ocrBusy ? "Reading the denial letter…"
                      : !ocrDone ? "Wait for denial letter review to finish"
                        : !canAnalyze
                          ? "Paste/upload the letter, or confirm CPT + DOS + a short denial reason"
                          : staffOverrideReady && !letterReady
                            ? "Proceeding without OCR’d letter"
                            : undefined
                }
                style={{
                  width: "100%", padding: "12px 16px", borderRadius: 10,
                  border: "none", background: "var(--forest)", color: "#FDFCF9",
                  fontFamily: FB, fontSize: 14, fontWeight: 700,
                  cursor: analyzeBlocked ? "not-allowed" : "pointer",
                  opacity: analyzeBlocked ? 0.55 : 1,
                }}
              >
                {running
                  ? (ANALYZE_STAGES[analyzeStage]?.label || "Analyzing…") + "…"
                  : (ocrBusy ? "Reading denial…" : (result ? "Re-analyze case" : "Ask OpAgent to analyze"))}
              </button>
              {ocrBusy ? (
                <div style={{ marginTop: 8, fontSize: 12, color: "var(--ink-soft)" }}>
                  Reading the C-8.1 from the chart — you can still paste text or confirm CPT/DOS while this runs.
                </div>
              ) : running ? (
                <div style={{ marginTop: 8, fontSize: 12, color: "var(--ink-soft)" }}>
                  Analysis in progress — submit is locked so the chart pull is not interrupted.
                </div>
              ) : !ocrDone ? (
                <div style={{ marginTop: 8, fontSize: 12, color: "var(--ink-soft)" }}>
                  Review the denial letter summary above, then analyze.
                </div>
              ) : staffOverrideReady && !letterReady ? (
                <div style={{ marginTop: 8, fontSize: 12, color: "var(--gilt-deep, #8C6D2F)" }}>
                  Proceeding without OCR’d letter — staff-confirmed CPT, DOS, and denial reason.
                </div>
              ) : !canAnalyze ? (
                <div style={{ marginTop: 8, fontSize: 12, color: "var(--deny)" }}>
                  Upload or paste the denial letter, or confirm CPT, DOS, and a short denial reason to unlock Analyze.
                </div>
              ) : (
                <div style={{ marginTop: 8, fontSize: 12, color: "var(--ink-soft)" }}>
                  OpAgent reads the denial, pulls the WC note timeline, matches MTG criteria, and returns a staff action.
                </div>
              )}

              {result?.ok && !running ? (
                <div style={{
                  marginTop: 12, padding: 12, borderRadius: 10,
                  border: "1px solid var(--canvas-dark)", background: "var(--canvas)",
                }}>
                  <div style={{ fontFamily: FB, fontSize: 12.5, fontWeight: 700, color: "var(--ink)", marginBottom: 8 }}>
                    Letter facts (optional — Leslie tip)
                  </div>
                  <div style={{ fontSize: 11.5, color: "var(--ink-soft)", marginBottom: 8, lineHeight: 1.4 }}>
                    For SI + prior-auth denials: confirm first SI and billed services + anesthesia under $1,000 to include the no-PAR / reprocess paragraph. Leave blank if unknown.
                  </div>
                  <label style={{ display: "flex", alignItems: "center", gap: 8, fontSize: 12.5, marginBottom: 8, cursor: "pointer" }}>
                    <input
                      type="checkbox"
                      checked={firstSiInjection}
                      onChange={(e) => setFirstSiInjection(e.target.checked)}
                    />
                    First SI joint injection
                  </label>
                  <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8, marginBottom: 8 }}>
                    <input
                      placeholder="Billed services $"
                      value={billedServicesUsd}
                      onChange={(e) => setBilledServicesUsd(e.target.value)}
                      style={{
                        width: "100%", padding: "8px 10px", borderRadius: 8, border: "1px solid var(--canvas-dark)",
                        fontFamily: FB, fontSize: 12.5,
                      }}
                    />
                    <input
                      placeholder="Anesthesia $"
                      value={anesthesiaUsd}
                      onChange={(e) => setAnesthesiaUsd(e.target.value)}
                      style={{
                        width: "100%", padding: "8px 10px", borderRadius: 8, border: "1px solid var(--canvas-dark)",
                        fontFamily: FB, fontSize: 12.5,
                      }}
                    />
                  </div>
                  <input
                    placeholder="Claim # (if known)"
                    value={letterClaimNumber}
                    onChange={(e) => setLetterClaimNumber(e.target.value)}
                    style={{
                      width: "100%", padding: "8px 10px", borderRadius: 8, border: "1px solid var(--canvas-dark)",
                      fontFamily: FB, fontSize: 12.5, marginBottom: 8,
                    }}
                  />
                  <input
                    placeholder="Adjuster (if known)"
                    value={letterAdjuster}
                    onChange={(e) => setLetterAdjuster(e.target.value)}
                    style={{
                      width: "100%", padding: "8px 10px", borderRadius: 8, border: "1px solid var(--canvas-dark)",
                      fontFamily: FB, fontSize: 12.5, marginBottom: 8,
                    }}
                  />
                  <input
                    placeholder="Carrier status note (optional)"
                    value={carrierStatusNote}
                    onChange={(e) => setCarrierStatusNote(e.target.value)}
                    style={{
                      width: "100%", padding: "8px 10px", borderRadius: 8, border: "1px solid var(--canvas-dark)",
                      fontFamily: FB, fontSize: 12.5,
                    }}
                  />
                </div>
              ) : null}

              {result?.ok && !running ? (
                <button
                  type="button"
                  onClick={runGenerateResponse}
                  disabled={responseBusy}
                  style={{
                    width: "100%", marginTop: 10, padding: "12px 16px", borderRadius: 10,
                    border: "1.5px solid var(--forest)", background: responseBusy ? "var(--canvas)" : "var(--pure)",
                    color: "var(--forest)", fontFamily: FB, fontSize: 14, fontWeight: 700,
                    cursor: responseBusy ? "wait" : "pointer",
                  }}
                >
                  {responseBusy ? "Generating response…" : "Generate response to C-8.1"}
                </button>
              ) : null}
              {result?.ok && !running ? (
                <div style={{ marginTop: 6, fontSize: 12, color: "var(--ink-soft)", lineHeight: 1.4 }}>
                  Builds a real letter (practice block, claim header, body, closing) from the denial, notes, and MTG evidence — no invented clinical facts.
                </div>
              ) : null}

              {error ? (
                <div style={{
                  marginTop: 12, padding: 12, borderRadius: 10,
                  background: "var(--deny-pale)", color: "var(--deny)", fontSize: 13, lineHeight: 1.45,
                }}>
                  <strong>Could not finish.</strong> {error}
                </div>
              ) : null}
              {analyzeDoneFlash && result?.ok && !running && !error ? (
                <div style={{
                  marginTop: 12, padding: 12, borderRadius: 10,
                  background: "#E6F1EA", color: "#1F5238", fontSize: 13, lineHeight: 1.45,
                  border: "1px solid var(--forest-bord)",
                }}>
                  Analysis complete — review the verdict and evidence on the right.
                </div>
              ) : null}
            </div>

            <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
              {running ? (
                <div style={{
                  background: "var(--pure)", border: "1px solid var(--canvas-dark)",
                  borderRadius: 14, padding: 22, boxShadow: "var(--shadow-sm)",
                }}>
                  <div style={{ fontFamily: FD, fontSize: 18, fontWeight: 700, color: "var(--forest)", marginBottom: 6 }}>
                    Analyzing this C-8.1
                  </div>
                  <div style={{ fontSize: 13, color: "var(--ink-soft)", marginBottom: 16, lineHeight: 1.45 }}>
                    OpAgent is working through the denial, chart notes, and MTG match. This panel updates as each stage completes.
                  </div>
                  <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
                    {ANALYZE_STAGES.map((stage, idx) => {
                      const done = idx < analyzeStage;
                      const active = idx === analyzeStage;
                      return (
                        <div key={stage.id} style={{
                          display: "flex", gap: 12, alignItems: "flex-start",
                          padding: "10px 12px", borderRadius: 10,
                          background: active ? "var(--gilt-pale)" : done ? "#E6F1EA" : "var(--canvas)",
                          border: `1px solid ${active ? "var(--gilt)" : done ? "var(--forest-bord)" : "var(--canvas-dark)"}`,
                        }}>
                          <div style={{
                            flex: "0 0 22px", width: 22, height: 22, marginTop: 1, borderRadius: 999,
                            display: "flex", alignItems: "center", justifyContent: "center",
                            background: done ? "var(--forest)" : active ? "var(--gilt)" : "var(--pure)",
                            color: done || active ? "#FDFCF9" : "var(--ink-faint)",
                            fontFamily: FM, fontSize: 11, fontWeight: 700,
                          }}>
                            {done ? "✓" : idx + 1}
                          </div>
                          <div>
                            <div style={{
                              fontSize: 13.5, fontWeight: 700,
                              color: active ? "var(--ink)" : done ? "#1F5238" : "var(--ink-soft)",
                            }}>
                              {stage.label}
                              {active ? " — in progress" : done ? " — done" : ""}
                            </div>
                            <div style={{ marginTop: 2, fontSize: 12.5, color: "var(--ink-soft)", lineHeight: 1.4 }}>
                              {stage.detail}
                            </div>
                          </div>
                        </div>
                      );
                    })}
                  </div>
                </div>
              ) : !result ? (
                <div style={{
                  background: "var(--pure)", border: "1px solid var(--canvas-dark)",
                  borderRadius: 14, padding: 28, color: "var(--ink-soft)", lineHeight: 1.5,
                }}>
                  <div style={{ fontFamily: FD, fontSize: 18, fontWeight: 700, color: "var(--forest)", marginBottom: 8 }}>
                    {ocrBusy ? "Reading denial letter…" : error ? "Analysis did not complete" : "Confirm denial understanding"}
                  </div>
                  {error ? (
                    <>
                      Fix the issue shown on the left, then run Analyze again.
                      OpAgent will re-read the denial, pull the note timeline, and return a fresh verdict.
                    </>
                  ) : (
                    <>
                      Review what the letter denied, the reason codes, and the carrier language on the left.
                      Correct any fields if needed, then ask OpAgent to analyze the chart.
                      OpAgent checks NY Workers’ Comp MTG criteria against documentation and returns{" "}
                      <strong>Defend</strong>, <strong>Abandon</strong>, or{" "}
                      <strong>Needs review</strong>. Generate a response letter after analysis when you are ready.
                    </>
                  )}
                </div>
              ) : (
                <>
                  <div style={{
                    background: result.staffAction === "defend" || result.verdict === "DEFENDABLE"
                      ? "linear-gradient(135deg, #1A2E24 0%, #2F5A42 55%, #3D6B4F 100%)"
                      : result.staffAction === "abandon" || result.verdict === "AT_FAULT"
                        ? "linear-gradient(135deg, #3A1212 0%, #6B1E1E 55%, #8C2A2A 100%)"
                        : "linear-gradient(135deg, #3A1A12 0%, #6B2E14 55%, #8C4A1A 100%)",
                    color: "#FDFCF9", borderRadius: 14, padding: "18px 22px",
                    boxShadow: "var(--shadow)",
                  }}>
                    <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12, flexWrap: "wrap" }}>
                      <div>
                        <div style={{ fontFamily: FM, fontSize: 11, letterSpacing: ".14em", textTransform: "uppercase", color: "#F4E4D4" }}>
                          {result.analysisPath === "documentation"
                            ? "Documentation denial · "
                            : result.analysisPath === "mtg_treatment"
                              ? "MTG procedure · "
                              : ""}
                          {result.confidence} confidence
                        </div>
                        <div style={{ fontFamily: FD, fontWeight: 700, fontSize: 26, marginTop: 4 }}>
                          {vt.label}
                        </div>
                        <div style={{ marginTop: 4, fontSize: 13, color: "#F4E4D4" }}>
                          {vt.action === "defend"
                            ? "Defend the claim — within-MTG response is supportable"
                            : vt.action === "abandon"
                              ? "Abandon within-MTG defense — do not claim guideline compliance"
                              : ((result.reviewGaps || []).length
                                ? `Needs review — ${result.reviewGaps.length} item${result.reviewGaps.length === 1 ? "" : "s"} for you below`
                                : "Needs review — see specific items below")}
                        </div>
                      </div>
                      <Chip tone={vt}>{vt.label}</Chip>
                    </div>
                    <div style={{ marginTop: 10, fontSize: 14, color: "#F4E4D4", lineHeight: 1.5 }}>
                      {staffClean(result.summary)}
                    </div>
                    {(result.reviewGaps || []).length ? (
                      <div style={{ marginTop: 12 }}>
                        <div style={{
                          fontFamily: FM, fontSize: 11, letterSpacing: ".12em",
                          textTransform: "uppercase", color: "#F4E4D4", marginBottom: 6,
                        }}>What we need from you</div>
                        <ul style={{ margin: 0, paddingLeft: 18, fontSize: 13.5, lineHeight: 1.45, color: "#FDFCF9" }}>
                          {result.reviewGaps.map((g, i) => (
                            <li key={i} style={{ marginBottom: 4 }}>{staffClean(g)}</li>
                          ))}
                        </ul>
                      </div>
                    ) : null}
                    <div style={{ marginTop: 10, fontSize: 12.5, color: "#E8D0B8", display: "flex", flexWrap: "wrap", gap: 8, alignItems: "center" }}>
                      <span>
                        {result.claim?.cpt
                          ? `CPT ${result.claim.cpt}`
                          : "CPT not on letter"}
                        {result.mtg?.treatment ? ` · ${result.mtg.treatment}` : ""}
                        {result.claim?.bodyRegion ? ` · ${result.claim.bodyRegion}` : ""}
                        {result.denialTypeLabel ? ` · ${result.denialTypeLabel}` : ""}
                      </span>
                      {(result.cptCategory || result.claim?.cptCategory || (result.claim?.cpt && categorizeCptClient(result.claim.cpt))) ? (
                        <Chip tone={cptCategoryTone(result.cptCategory || result.claim?.cptCategory || categorizeCptClient(result.claim.cpt))}>
                          {result.cptCategory || result.claim?.cptCategory || categorizeCptClient(result.claim.cpt)}
                        </Chip>
                      ) : null}
                    </div>
                  </div>

                  <div style={{
                    background: "var(--pure)", border: "1px solid var(--canvas-dark)",
                    borderRadius: 14, padding: 20, boxShadow: "var(--shadow-sm)",
                  }}>
                    <div style={{
                      fontFamily: FD, fontSize: 18, fontWeight: 700, color: "var(--forest)", marginBottom: 12,
                    }}>How the denial was found</div>
                    <div style={{ fontSize: 14, fontWeight: 600, color: "var(--ink)", marginBottom: 8 }}>
                      {staffClean(
                        result.letterSourceLabel
                        || (denialUnderstanding && denialUnderstanding.extractMethodLabel)
                        || letterFoundViaLabel(selected?.letterFoundVia)
                        || "Denial letter on file",
                      )}
                    </div>
                    {result.denialSummary ? (
                      <div style={{ display: "grid", gap: 8, fontSize: 13.5, lineHeight: 1.45 }}>
                        <div><span style={{ color: "var(--ink-soft)" }}>What was denied: </span>
                          {staffClean(result.denialSummary.whatWasDenied || "—")}</div>
                        <div><span style={{ color: "var(--ink-soft)" }}>Codes: </span>
                          {(result.denialSummary.codes || []).length
                            ? result.denialSummary.codes.join(", ")
                            : (denialCode || "—")}</div>
                        <div><span style={{ color: "var(--ink-soft)" }}>Why (from letter): </span>
                          {staffClean(result.denialSummary.why || denialReason || "—")}</div>
                      </div>
                    ) : null}
                    {(result.whatChecked || []).length ? (
                      <ul style={{ margin: "12px 0 0", paddingLeft: 18, fontSize: 13.5, lineHeight: 1.45, color: "var(--ink)" }}>
                        {result.whatChecked.map((w, i) => <li key={i}>{staffClean(w)}</li>)}
                      </ul>
                    ) : null}
                    {result.nextAction ? (
                      <div style={{
                        marginTop: 12, padding: 12, borderRadius: 10,
                        background: vt.action === "abandon" ? "#F7E4E2" : "#E6F1EA",
                        border: `1px solid ${vt.action === "abandon" ? "#E2B4B0" : "var(--forest-bord)"}`,
                        fontSize: 13.5,
                        color: vt.action === "abandon" ? "#B3261E" : "#1F5238",
                        lineHeight: 1.45,
                      }}>
                        <strong>Next action: </strong>{staffClean(result.nextAction)}
                      </div>
                    ) : null}
                  </div>

                  <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 10 }}>
                    {[
                      [result.analysisPath === "documentation" ? "Checks met" : "Criteria met", result.factPackStats?.hardMet],
                      ["Missing", result.factPackStats?.hardMissing],
                      ["Contradicted", result.factPackStats?.hardContradicted],
                      ["Notes used", result.notes?.bodyPartFilter?.includedCount ??
                        (result.notes?.timeline || []).filter((n) => n.included).length],
                    ].map(([label, val]) => (
                      <div key={label} style={{
                        background: "var(--pure)", border: "1px solid var(--canvas-dark)",
                        borderRadius: 12, padding: "12px 14px",
                      }}>
                        <div style={{
                          fontFamily: FM, fontSize: 10, letterSpacing: ".12em",
                          textTransform: "uppercase", color: "var(--ink-faint)",
                        }}>{label}</div>
                        <div style={{ fontFamily: FD, fontSize: 22, fontWeight: 700, color: "var(--forest)", marginTop: 4 }}>
                          {val ?? "—"}
                        </div>
                      </div>
                    ))}
                  </div>

                  {((result.notes?.bodyPartFilter?.includedCount ??
                    (result.notes?.timeline || []).filter((n) => n.included).length) === 0) ? (
                    <div style={{
                      padding: 12, borderRadius: 10, background: "#F6ECD7",
                      border: "1px solid #E0CFA8", fontSize: 13, color: "#6E5520", lineHeight: 1.45,
                    }}>
                      <strong>Notes used: 0</strong>
                      {" — "}
                      {staffClean(
                        (result.limits || []).find((l) => /^Notes used: 0/i.test(l) || /^Notes:/i.test(l))
                        || (result.patient?.noteSource === "none"
                          ? "No chart notes pulled — check DrChrono session or turn on chart note pull."
                          : "Pulled notes did not match the claimed body part, or the chart has no locked notes."),
                      )}
                      {result.nextAction ? (
                        <div style={{ marginTop: 6 }}>{staffClean(result.nextAction)}</div>
                      ) : null}
                    </div>
                  ) : (
                    <div style={{
                      padding: "10px 12px", borderRadius: 10, background: "#E6F1EA",
                      border: "1px solid var(--forest-bord)", fontSize: 13, color: "#1F5238", lineHeight: 1.45,
                    }}>
                      Chart notes:{" "}
                      <strong>
                        {result.notes?.bodyPartFilter?.includedCount
                          ?? (result.notes?.timeline || []).filter((n) => n.included).length}
                      </strong>
                      {" used"}
                      {result.notes?.bodyPartFilter?.totalPulled != null
                        ? ` of ${result.notes.bodyPartFilter.totalPulled} pulled`
                        : ""}
                      {(result.notes?.timeline || []).filter((n) => n.included && n.date).length
                        ? ` · dates ${(result.notes.timeline || []).filter((n) => n.included && n.date).map((n) => n.date).slice(0, 6).join(", ")}`
                        : ""}
                    </div>
                  )}

                  {(result.notes?.timeline || []).length ? (
                    <div style={{
                      background: "var(--pure)", border: "1px solid var(--canvas-dark)",
                      borderRadius: 14, padding: 20, boxShadow: "var(--shadow-sm)",
                    }}>
                      <div style={{
                        fontFamily: FD, fontSize: 18, fontWeight: 700, color: "var(--forest)", marginBottom: 6,
                      }}>Chart notes used</div>
                      <div style={{ fontSize: 12.5, color: "var(--ink-soft)", marginBottom: 12, lineHeight: 1.45 }}>
                        Notes related to{" "}
                        <strong>{result.notes?.bodyPartFilter?.targetLabel || "the claimed body part"}</strong>
                        {result.notes?.bodyPartFilter?.uncertain ? " (filter uncertain — included broadly)" : ""}.
                      </div>
                      <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
                        {result.notes.timeline.map((n) => (
                          <div key={n.noteId} style={{
                            display: "flex", justifyContent: "space-between", gap: 10, flexWrap: "wrap",
                            padding: "8px 10px", borderRadius: 8,
                            background: n.included ? "var(--canvas)" : "#F7E4E2",
                            border: "1px solid var(--canvas-dark)",
                            fontSize: 12.5, color: "var(--ink)",
                          }}>
                            <span>
                              <span className="mono">{n.date || "—"}</span>
                              {n.reason ? ` · ${staffClean(n.reason)}` : ""}
                            </span>
                            <span style={{ fontFamily: FM, fontSize: 10, letterSpacing: ".06em", color: "var(--ink-faint)" }}>
                              {n.included ? "USED" : "SKIPPED"}
                            </span>
                          </div>
                        ))}
                      </div>
                    </div>
                  ) : null}

                  <div style={{
                    background: "var(--pure)", border: "1px solid var(--canvas-dark)",
                    borderRadius: 14, padding: 20, boxShadow: "var(--shadow-sm)",
                  }}>
                    <div style={{
                      fontFamily: FD, fontSize: 18, fontWeight: 700, color: "var(--forest)", marginBottom: 12,
                    }}>{result.analysisPath === "documentation" ? "Chart evidence vs letter" : "MTG criteria checklist"}</div>
                    <div style={{ fontSize: 12.5, color: "var(--ink-soft)", marginBottom: 12, lineHeight: 1.4 }}>
                      Staff view — met / missing / contradicted against reviewed notes (no guideline PDF chrome).
                    </div>
                    {(result.evidence || []).length === 0 ? (
                      <div style={{
                        padding: 14, borderRadius: 10, background: "#F7E4E2",
                        border: "1px solid #E2B4B0", color: "#6B1E1E", fontSize: 13.5, lineHeight: 1.45,
                      }}>
                        {result.abandonRationale
                          ? staffClean(result.abandonRationale.split("\n")[0] || "")
                          : null}
                        <div style={{ marginTop: result.abandonRationale ? 8 : 0 }}>
                          {result.nextAction
                            ? staffClean(result.nextAction)
                            : "No MTG criteria scored for this denial type — review the letter path and chart notes, then decide defend vs abandon."}
                        </div>
                      </div>
                    ) : (
                      <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
                        {result.evidence.map((e) => {
                          const t = evidenceTone(e.status);
                          return (
                            <div key={e.criterionId} style={{
                              padding: 12, borderRadius: 10,
                              border: "1px solid var(--canvas-dark)", background: "var(--canvas)",
                            }}>
                              <div style={{ display: "flex", justifyContent: "space-between", gap: 10, alignItems: "flex-start" }}>
                                <div style={{ fontSize: 13.5, fontWeight: 600, color: "var(--ink)", lineHeight: 1.4 }}>
                                  {e.label}
                                  <span style={{
                                    marginLeft: 8, fontFamily: FM, fontSize: 10, fontWeight: 600,
                                    color: "var(--ink-faint)", letterSpacing: ".06em",
                                  }}>{e.weight === "hard" ? "REQUIRED" : "SUPPORTING"}</span>
                                </div>
                                <Chip tone={t}>{t.label}</Chip>
                              </div>
                              <div style={{ marginTop: 6, fontSize: 12.5, color: "var(--ink-soft)", lineHeight: 1.4 }}>
                                {staffClean(e.detail || e.mtg?.text || "")}
                              </div>
                              {(e.supportingFacts || []).filter((f) => f.source === "note").slice(0, 2).map((f, i) => (
                                <div key={i} style={{
                                  marginTop: 6, fontSize: 12.5, color: "var(--ink)",
                                  fontStyle: "italic", lineHeight: 1.4,
                                }}>
                                  “{f.quote}”
                                  {f.noteDate ? (
                                    <span style={{ fontStyle: "normal", color: "var(--ink-faint)", marginLeft: 6 }}>
                                      ({f.noteDate})
                                    </span>
                                  ) : null}
                                </div>
                              ))}
                            </div>
                          );
                        })}
                      </div>
                    )}
                  </div>

                  {(result.abandonRationale
                    && result.verdict === "NEEDS_REVIEW"
                    && result.draftArgument?.text
                    && result.abandonRationale !== result.draftArgument.text
                    && !(staffResponse?.text)) ? (
                    <div style={{
                      background: "var(--pure)",
                      border: "1px solid #E0CFA8",
                      borderRadius: 14, padding: 20, boxShadow: "var(--shadow-sm)",
                    }}>
                      <div style={{
                        fontFamily: FD, fontSize: 18, fontWeight: 700,
                        color: "#8C6D2F",
                        marginBottom: 8,
                      }}>
                        Why defend is not ready yet
                      </div>
                      <div style={{ fontSize: 12.5, color: "var(--ink-soft)", marginBottom: 10, lineHeight: 1.4 }}>
                        Clear explanation of what failed — not an empty “no rule” wall.
                      </div>
                      <pre style={{
                        margin: 0, whiteSpace: "pre-wrap", fontFamily: FB, fontSize: 13.5,
                        lineHeight: 1.55, color: "var(--ink)",
                      }}>{staffClean(result.abandonRationale)}</pre>
                    </div>
                  ) : null}

                  {(staffResponse?.text || result.draftArgument?.text) ? (
                    <div style={{
                      background: "var(--pure)",
                      border: `1.5px solid ${result.verdict === "DEFENDABLE" ? "var(--forest-bord)" : "var(--gilt)"}`,
                      borderRadius: 14, padding: 20, boxShadow: "var(--shadow-sm)",
                    }}>
                      <div style={{
                        display: "flex", justifyContent: "space-between", gap: 10, alignItems: "center",
                        flexWrap: "wrap", marginBottom: 10,
                      }}>
                        <div style={{
                          fontFamily: FD, fontSize: 18, fontWeight: 700, color: "var(--forest)",
                        }}>
                          {staffResponse?.text
                            ? "C-8.1 response letter"
                            : result.verdict === "DEFENDABLE"
                              ? "Draft defense response"
                              : result.verdict === "AT_FAULT"
                                ? "Close / abandon rationale"
                                : (result.analysisPath === "documentation"
                                  ? "Draft documentation response"
                                  : "Draft staff response")}
                        </div>
                        <button
                          type="button"
                          onClick={copyStaffResponse}
                          style={{
                            padding: "7px 12px", borderRadius: 8,
                            border: "1px solid var(--forest-bord)", background: "var(--pure)",
                            fontFamily: FB, fontSize: 12, fontWeight: 700, color: "var(--forest)",
                            cursor: "pointer",
                          }}
                        >{responseCopied ? "Copied" : "Copy letter"}</button>
                      </div>
                      <div style={{ fontSize: 12.5, color: "var(--ink-soft)", marginBottom: 10, lineHeight: 1.4 }}>
                        {staffResponse?.text
                          ? "Staff-generated from this analysis — grounded in the denial letter, reviewed notes, and MTG evidence only."
                          : result.verdict === "DEFENDABLE"
                            ? "Solid draft to defend — grounded in the letter, chart notes, and MTG checklist. Use Generate response to C-8.1 to refresh."
                            : "Auto-draft from this analysis. Use Generate response to C-8.1 for an explicit staff letter on any verdict."}
                      </div>
                      <pre style={{
                        margin: 0, whiteSpace: "pre-wrap", fontFamily: FB, fontSize: 13.5,
                        lineHeight: 1.55, color: "var(--ink)",
                      }}>{staffClean(staffResponse?.text || result.draftArgument.text)}</pre>
                    </div>
                  ) : result?.ok ? (
                    <div style={{
                      background: "var(--gilt-pale)", border: "1.5px solid var(--gilt)",
                      borderRadius: 14, padding: 18, color: "var(--ink)", fontSize: 13.5, lineHeight: 1.45,
                    }}>
                      <strong>Generate response to C-8.1</strong> is ready on the left — builds a copy-ready letter from the denial, notes, and MTG checklist.
                    </div>
                  ) : null}

                  {(result.limits || []).length ? (
                    <div style={{
                      padding: 14, borderRadius: 12, background: "#F6ECD7",
                      border: "1px solid #E0CFA8", fontSize: 12.5, color: "#6E5520", lineHeight: 1.45,
                    }}>
                      <strong>Limits</strong>
                      <ul style={{ margin: "6px 0 0", paddingLeft: 18 }}>
                        {result.limits.map((l, i) => <li key={i}>{staffClean(l)}</li>)}
                      </ul>
                    </div>
                  ) : null}
                </>
              )}
            </div>
          </div>
        </div>
      );
    }

    /* ── Case list + scan controls ────────────────────────── */
    return (
      <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
        <div style={{
          background: "var(--pure)", border: "1px solid var(--canvas-dark)",
          borderRadius: 14, padding: 18, boxShadow: "var(--shadow-sm)",
        }}>
          <div style={{
            fontFamily: FM, fontSize: 10, letterSpacing: ".14em",
            textTransform: "uppercase", color: "var(--ink-faint)", marginBottom: 12,
          }}>Search C-8.1 denials</div>

          <div style={{
            display: "grid",
            gridTemplateColumns: "repeat(auto-fit, minmax(140px, 1fr))",
            gap: 10, alignItems: "end",
          }}>
            <label style={{ display: "block", fontSize: 13 }}>
              <span style={{ color: "var(--ink-soft)" }}>From (DOS)</span>
              <input type="date" value={dateFrom} onChange={(e) => setDateFrom(e.target.value)} style={inputStyle()} />
            </label>
            <label style={{ display: "block", fontSize: 13 }}>
              <span style={{ color: "var(--ink-soft)" }}>To (DOS)</span>
              <input type="date" value={dateTo} onChange={(e) => setDateTo(e.target.value)} style={inputStyle()} />
            </label>
            <label style={{ display: "block", fontSize: 13 }}>
              <span style={{ color: "var(--ink-soft)" }}>Payer (optional)</span>
              <input
                value={payerFilter}
                onChange={(e) => setPayerFilter(e.target.value)}
                placeholder="e.g. NYSIF"
                style={inputStyle()}
              />
            </label>
            <label style={{ display: "block", fontSize: 13 }}>
              <span style={{ color: "var(--ink-soft)" }}>Status</span>
              <select value={statusFilter} onChange={(e) => setStatusFilter(e.target.value)} style={inputStyle()}>
                <option value="all">All</option>
                <option value="needs_review">Needs review</option>
                <option value="response_on_file">Response on file</option>
              </select>
            </label>
            <label style={{ display: "block", fontSize: 13 }}>
              <span style={{ color: "var(--ink-soft)" }}>CPT (search)</span>
              <input
                value={cptFilter}
                onChange={(e) => setCptFilter(e.target.value)}
                placeholder="e.g. 72148"
                list="c81-cpt-filter-list"
                style={inputStyle()}
              />
              <datalist id="c81-cpt-filter-list">
                {cptOptions.map((code) => (
                  <option key={code} value={code} />
                ))}
              </datalist>
            </label>
            <label style={{ display: "block", fontSize: 13 }}>
              <span style={{ color: "var(--ink-soft)" }}>CPT (list)</span>
              <select value={cptSelect} onChange={(e) => setCptSelect(e.target.value)} style={inputStyle()}>
                <option value="">All CPTs</option>
                {cptOptions.map((code) => (
                  <option key={code} value={code}>
                    {code} · {categorizeCptClient(code)}
                  </option>
                ))}
              </select>
            </label>
            <label style={{ display: "block", fontSize: 13 }}>
              <span style={{ color: "var(--ink-soft)" }}>Category</span>
              <select value={categoryFilter} onChange={(e) => setCategoryFilter(e.target.value)} style={inputStyle()}>
                <option value="all">All</option>
                <option value="Intervention">Intervention</option>
                <option value="Imaging">Imaging</option>
                <option value="E/M">E/M</option>
                <option value="Lab/Tox">Lab/Tox</option>
                <option value="Surgery">Surgery</option>
                <option value="Other">Other</option>
              </select>
            </label>
            <button
              type="button"
              onClick={runScan}
              disabled={scanBusy}
              style={{
                padding: "12px 16px", borderRadius: 10, border: "none",
                background: "var(--forest)", color: "#FDFCF9",
                fontFamily: FB, fontSize: 14, fontWeight: 700,
                cursor: scanBusy ? "wait" : "pointer", opacity: scanBusy ? 0.75 : 1,
              }}
            >{scanBusy ? "Searching…" : "Scan C8.1"}</button>
          </div>

          <div style={{
            marginTop: 12, display: "flex", flexWrap: "wrap", gap: 8, alignItems: "center",
          }}>
            <button type="button" disabled={scanBusy} onClick={() => { setDateFrom(isoDaysAgo(30)); setDateTo(isoToday()); }}
              style={{ padding: "6px 10px", borderRadius: 8, border: "1px solid var(--canvas-dark)", background: "var(--canvas)", fontSize: 12, cursor: "pointer" }}>
              Last 30 days
            </button>
            <button type="button" disabled={scanBusy} onClick={() => { setDateFrom(isoDaysAgo(90)); setDateTo(isoToday()); }}
              style={{ padding: "6px 10px", borderRadius: 8, border: "1px solid var(--canvas-dark)", background: "var(--canvas)", fontSize: 12, cursor: "pointer" }}>
              Last 90 days
            </button>
            {scanBusy && scanProgress ? (
              <span style={{ fontSize: 13, color: "var(--ink-soft)" }}>{scanProgress}</span>
            ) : null}
            {!scanBusy && scanSummary ? (
              <span style={{
                fontSize: 13, fontWeight: 600,
                color: caseCount ? "var(--forest)" : "var(--ink-soft)",
              }}>{scanSummary}</span>
            ) : null}
          </div>

          {error ? (
            <div style={{
              marginTop: 12, padding: 12, borderRadius: 10,
              background: "var(--deny-pale)", color: "var(--deny)", fontSize: 13,
            }}>{error}</div>
          ) : null}
        </div>

        <div style={{
          background: "var(--pure)", border: "1px solid var(--canvas-dark)",
          borderRadius: 14, boxShadow: "var(--shadow-sm)", overflow: "hidden",
        }}>
          <div style={{
            padding: "14px 18px", borderBottom: "1px solid var(--canvas-dark)",
            display: "flex", justifyContent: "space-between", alignItems: "center", gap: 10,
          }}>
            <div style={{ fontFamily: FD, fontSize: 18, fontWeight: 700, color: "var(--forest)" }}>
              Cases
            </div>
            <div style={{ display: "flex", alignItems: "center", gap: 14, fontSize: 12.5, color: "var(--ink-soft)" }}>
              <label style={{ display: "flex", alignItems: "center", gap: 6, cursor: "pointer", userSelect: "none" }}>
                <input
                  type="checkbox"
                  checked={showAllCandidates}
                  onChange={(e) => setShowAllCandidates(e.target.checked)}
                />
                <span>Show all scanned candidates ({cases.length})</span>
              </label>
              <span>
                {visibleCases.length} shown
                {cases.length !== visibleCases.length ? ` · ${cases.length} scanned` : ""}
              </span>
            </div>
          </div>

          {!visibleCases.length ? (
            <div style={{ padding: 28, color: "var(--ink-soft)", lineHeight: 1.5, fontSize: 14 }}>
              {scanBusy
                ? "Searching the C-8.1 denials queue…"
                : cases.length
                  ? "No cases with detected C-8.1 denial evidence match these filters. Check \u201CShow all scanned candidates\u201D to see every scanned WC claim."
                  : "No cases yet. Set a date range and click Scan C8.1 to pull denials from DrChrono."}
            </div>
          ) : (
            <div style={{ overflowX: "auto" }}>
              <table style={{ width: "100%", borderCollapse: "collapse", fontSize: 13.5 }}>
                <thead>
                  <tr style={{ textAlign: "left", color: "var(--ink-faint)", fontFamily: FM, fontSize: 10, letterSpacing: ".08em" }}>
                    <th style={{ padding: "10px 16px", fontWeight: 600 }}>PATIENT</th>
                    <th style={{ padding: "10px 12px", fontWeight: 600 }}>DOS</th>
                    <th style={{ padding: "10px 12px", fontWeight: 600 }}>CPT</th>
                    <th style={{ padding: "10px 12px", fontWeight: 600 }}>CATEGORY</th>
                    <th style={{ padding: "10px 12px", fontWeight: 600 }}>PAYER</th>
                    <th style={{ padding: "10px 12px", fontWeight: 600 }}>FOUND VIA</th>
                    <th style={{ padding: "10px 12px", fontWeight: 600 }}>LETTER</th>
                    <th style={{ padding: "10px 16px", fontWeight: 600 }}>ACTION</th>
                  </tr>
                </thead>
                <tbody>
                  {visibleCases.map((c) => {
                    const st = analysisListTone(c.analysisStatus || "NOT_RUN");
                    const letter = letterListStatus(c);
                    const primary = casePrimaryCpt(c);
                    const cat = caseCptCategory(c);
                    const catTone = cptCategoryTone(cat);
                    const foundVia = letterFoundViaLabel(c.letterFoundVia)
                      || (/\+ C-8\.1 ERA/i.test(c.billingStatus || "") ? "ASC C-8.1 / View EOB" : "")
                      || (/\+ C-8\.1 note/i.test(c.billingStatus || "") ? "Billing notes" : "")
                      || (letter.kind !== "none" ? "Denial letter" : "—");
                    const foundViaTone = /View EOB|ERA/i.test(foundVia)
                      ? { bg: "#E6F1EA", fg: "#1F5238" }
                      : /Billing/i.test(foundVia)
                        ? { bg: "#F6ECD7", fg: "#8C6D2F" }
                        : { bg: "#EFEBE2", fg: "#6E6A61" };
                    return (
                      <tr
                        key={c.id}
                        onClick={() => openCase(c)}
                        style={{
                          borderTop: "1px solid var(--canvas-dark)",
                          cursor: "pointer",
                          background: "var(--pure)",
                        }}
                        onMouseEnter={(e) => { e.currentTarget.style.background = "var(--canvas)"; }}
                        onMouseLeave={(e) => { e.currentTarget.style.background = "var(--pure)"; }}
                      >
                        <td style={{ padding: "12px 16px", fontWeight: 600, color: "var(--ink)" }}>
                          {c.patientName || "Unknown patient"}
                          {c.hasStaffResponse ? (
                            <div style={{ fontSize: 11, fontWeight: 500, color: "var(--forest)", marginTop: 2 }}>
                              Response draft saved
                            </div>
                          ) : null}
                        </td>
                        <td style={{ padding: "12px 12px", color: "var(--ink-soft)", whiteSpace: "nowrap" }}>
                          {c.dos || "—"}
                        </td>
                        <td style={{ padding: "12px 12px", color: "var(--ink)", fontFamily: FM }}>
                          {primary || "—"}
                        </td>
                        <td style={{ padding: "12px 12px" }}>
                          {primary ? <Chip tone={catTone}>{catTone.label}</Chip> : <span style={{ color: "var(--ink-faint)" }}>—</span>}
                        </td>
                        <td style={{ padding: "12px 12px", color: "var(--ink-soft)" }}>
                          {c.payer || "—"}
                        </td>
                        <td style={{ padding: "12px 12px" }}>
                          <Chip tone={foundViaTone}>{foundVia}</Chip>
                        </td>
                        <td style={{ padding: "12px 12px" }}>
                          <Chip tone={letter.tone}>{letter.label}</Chip>
                        </td>
                        <td style={{ padding: "12px 16px" }}>
                          <Chip tone={st}>{st.label}</Chip>
                        </td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>
          )}
        </div>
      </div>
    );
  }

  /* ─── CPT Lookup (secondary) ────────────────────────────── */
  function CptLookupPanel() {
    const seed = window.WC_MTG || { RULES: {}, SHORTCUTS: [] };
    const shortcuts = seed.SHORTCUTS || seed.DEMOS || [];
    const [activeId, setActiveId] = useState((shortcuts[0] && shortcuts[0].id) || "");
    const [cpt, setCpt] = useState((shortcuts[0] && shortcuts[0].cpt) || "27096");
    const [payer, setPayer] = useState((shortcuts[0] && shortcuts[0].payer) || "NYSIF");
    const [bodyRegion, setBodyRegion] = useState((shortcuts[0] && shortcuts[0].bodyRegion) || "Mid/Low Back");

    function loadShortcut(d) {
      if (!d) return;
      setActiveId(d.id);
      setCpt(d.cpt);
      setPayer(d.payer || payer);
      setBodyRegion(d.bodyRegion);
    }

    const rule = useMemo(() => {
      const key = String(cpt || "").trim();
      return seed.RULES[key] || null;
    }, [cpt, seed.RULES]);

    const tone = statusTone(rule && rule.primaryStatus);

    return (
      <div style={{
        display: "grid", gridTemplateColumns: "minmax(260px, 320px) 1fr",
        gap: 16, alignItems: "start",
      }}>
        <div style={{
          background: "var(--pure)", border: "1px solid var(--canvas-dark)",
          borderRadius: 14, padding: 18, boxShadow: "var(--shadow-sm)",
        }}>
          <div style={{
            fontFamily: FM, fontSize: 10, letterSpacing: ".14em",
            textTransform: "uppercase", color: "var(--ink-faint)", marginBottom: 12,
          }}>Lookup</div>

          <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 14 }}>
            {shortcuts.map((d) => (
              <button
                key={d.id}
                onClick={() => loadShortcut(d)}
                style={{
                  padding: "6px 10px", borderRadius: 8,
                  border: activeId === d.id ? "1.5px solid var(--gilt)" : "1.5px solid var(--canvas-dark)",
                  background: activeId === d.id ? "var(--gilt-pale)" : "var(--pure)",
                  fontFamily: FB, fontSize: 11.5, fontWeight: 600, color: "var(--ink)",
                }}
              >{d.label}</button>
            ))}
          </div>

          <label style={{ display: "block", marginBottom: 12, fontSize: 13 }}>
            <span style={{ color: "var(--ink-soft)" }}>Payer</span>
            <select
              value={payer}
              onChange={(e) => setPayer(e.target.value)}
              style={{
                display: "block", width: "100%", marginTop: 5, padding: "10px 12px",
                borderRadius: 8, border: "1.5px solid var(--canvas-dark)",
                background: "var(--canvas)", fontFamily: FB, fontSize: 14,
              }}
            >
              <option>NYSIF</option>
              <option>CNA</option>
              <option>NY Workers' Comp</option>
            </select>
          </label>

          <label style={{ display: "block", marginBottom: 12, fontSize: 13 }}>
            <span style={{ color: "var(--ink-soft)" }}>CPT</span>
            <input
              value={cpt}
              onChange={(e) => { setCpt(e.target.value); setActiveId(""); }}
              style={{
                display: "block", width: "100%", marginTop: 5, padding: "10px 12px",
                borderRadius: 8, border: "1.5px solid var(--canvas-dark)",
                background: "var(--canvas)", fontFamily: FM, fontSize: 14,
              }}
            />
          </label>

          <label style={{ display: "block", marginBottom: 4, fontSize: 13 }}>
            <span style={{ color: "var(--ink-soft)" }}>Body region</span>
            <select
              value={bodyRegion}
              onChange={(e) => setBodyRegion(e.target.value)}
              style={{
                display: "block", width: "100%", marginTop: 5, padding: "10px 12px",
                borderRadius: 8, border: "1.5px solid var(--canvas-dark)",
                background: "var(--canvas)", fontFamily: FB, fontSize: 14,
              }}
            >
              <option>Mid/Low Back</option>
              <option>Neck</option>
              <option>Non-Acute / Implantable</option>
            </select>
          </label>
        </div>

        <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          {!rule ? (
            <div style={{
              background: "var(--pure)", border: "1px solid var(--canvas-dark)",
              borderRadius: 14, padding: 28, color: "var(--ink-soft)",
            }}>
              No verified MTG guideline loaded for CPT <span className="mono">{cpt || "—"}</span>.
              Try 27096, 62323, 64483, 64493, 64635, 62321, 64490, 64633, or 64479.
            </div>
          ) : (
            <>
              <div style={{
                background: "linear-gradient(135deg, #3A1A12 0%, #6B2E14 55%, #8C4A1A 100%)",
                color: "#FDFCF9", borderRadius: 14, padding: "16px 20px",
                boxShadow: "var(--shadow)",
              }}>
                <div style={{
                  fontFamily: FD, fontWeight: 700, fontSize: 20, lineHeight: 1.3,
                }}>{rule.preventionBanner}</div>
                <div style={{
                  marginTop: 8, fontSize: 13, color: "#F4E4D4", lineHeight: 1.45,
                }}>
                  {rule.treatment} · {payer} · {bodyRegion}
                  {rule.verified ? " · MTG verified" : ""}
                </div>
              </div>

              <div style={{
                background: "var(--pure)", border: "1px solid var(--canvas-dark)",
                borderRadius: 14, padding: 20, boxShadow: "var(--shadow-sm)",
              }}>
                <div style={{
                  display: "flex", alignItems: "center", justifyContent: "space-between",
                  gap: 12, flexWrap: "wrap", marginBottom: 16,
                }}>
                  <div>
                    <div style={{ fontFamily: FM, fontSize: 12, color: "var(--ink-faint)" }}>
                      CPT {rule.cpt}
                    </div>
                    <div style={{ fontFamily: FD, fontSize: 22, fontWeight: 700, color: "var(--forest)" }}>
                      {rule.descriptor}
                    </div>
                    <div style={{ fontSize: 13, color: "var(--ink-soft)", marginTop: 2 }}>
                      {clinicalChapter(rule.chapter) || rule.treatment}
                    </div>
                  </div>
                  <Chip tone={tone}>{tone.label}</Chip>
                </div>

                {rule.recommendedFor && rule.recommendedFor.length ? (
                  <Field label="Recommended when">
                    <CheckList items={rule.recommendedFor} />
                  </Field>
                ) : null}

                <Field label="Prerequisites">
                  <CheckList items={rule.prerequisites || []} />
                </Field>

                <div style={{
                  display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, marginBottom: 14,
                }}>
                  <div style={{
                    padding: 14, borderRadius: 12, background: "#EEF4F8",
                    border: "1px solid #C5D6E2",
                  }}>
                    <div style={{
                      fontFamily: FM, fontSize: 10, letterSpacing: ".12em",
                      textTransform: "uppercase", color: "#3A5F73", marginBottom: 6,
                    }}>Fluoro / imaging</div>
                    <div style={{ fontSize: 13, color: "var(--ink)", lineHeight: 1.4 }}>
                      {rule.fluoroRequired || "—"}
                    </div>
                  </div>
                  <div style={{
                    padding: 14, borderRadius: 12, background: "var(--canvas)",
                    border: "1px solid var(--canvas-dark)",
                  }}>
                    <div style={{
                      fontFamily: FM, fontSize: 10, letterSpacing: ".12em",
                      textTransform: "uppercase", color: "var(--ink-faint)", marginBottom: 6,
                    }}>Frequency / course</div>
                    <div style={{ fontSize: 13, color: "var(--ink)", lineHeight: 1.4 }}>
                      {rule.frequencyLimit}
                    </div>
                  </div>
                </div>

                {rule.notRecommended && rule.notRecommended.length ? (
                  <div style={{
                    marginBottom: 14, padding: 14, borderRadius: 12,
                    background: "var(--deny-pale)", border: "1px solid #E2B4B0",
                  }}>
                    <div style={{
                      fontFamily: FM, fontSize: 10, letterSpacing: ".12em",
                      textTransform: "uppercase", color: "var(--deny)", marginBottom: 8,
                    }}>Not recommended</div>
                    <CheckList items={rule.notRecommended} accent="#E2B4B0" />
                  </div>
                ) : null}
              </div>
            </>
          )}
        </div>
      </div>
    );
  }

  function WcMtgModule() {
    const [panel, setPanel] = useState("c81");

    return (
      <div className="screen" style={{ maxWidth: 1120 }}>
        <div style={{
          display: "flex", alignItems: "flex-end", justifyContent: "space-between",
          gap: 16, marginBottom: 18, flexWrap: "wrap",
        }}>
          <div>
            <div style={{
              fontFamily: FM, fontSize: 11, letterSpacing: ".18em",
              textTransform: "uppercase", color: "var(--gilt-dark)",
            }}>OpAgent Inside · NY Workers’ Comp</div>
            <h2 style={{
              fontFamily: FD, fontWeight: 700, fontSize: 28, color: "var(--forest)",
              marginTop: 6, letterSpacing: "-.01em",
            }}>C8.1 Shield</h2>
            <div style={{ fontSize: 14, color: "var(--ink-soft)", marginTop: 6, maxWidth: 680 }}>
              Search the C-8.1 denials queue by date, open a case, attach the denial, and ask
              OpAgent to analyze the chart against NY Workers’ Comp MTG criteria.
            </div>
          </div>
          <div style={{ display: "flex", gap: 8 }}>
            <PanelTab id="c81" active={panel === "c81"} onClick={setPanel}>C8.1 Shield</PanelTab>
            <PanelTab id="lookup" active={panel === "lookup"} onClick={setPanel}>CPT Lookup</PanelTab>
          </div>
        </div>

        {panel === "c81" ? <C81ShieldPanel /> : <CptLookupPanel />}
      </div>
    );
  }

  window.WcMtgModule = WcMtgModule;
})();
