/* State 376 — the document and the framing.
   The dossier is the hero. The deviance score is the ELITE confidence score wearing a
   fictional coat. The margin note is your own doubt breaking through the typeface. */

/* ---------- a placeholder portrait. Gray silhouette on a measuring wall. A redaction at low sanity. ---------- */
function CitizenPhoto({ sanity, sealed }) {
  if (sanity <= 36 || sealed) {
    return <div className="dz-photo redacted"><span>IMAGE<br/>WITHHELD</span></div>;
  }
  return (
    <div className="dz-photo">
      <div className="mug-lines"><i/><i/><i/><i/></div>
      <svg viewBox="0 0 100 120" className="silhouette" aria-hidden="true">
        <circle cx="50" cy="42" r="22" />
        <path d="M12 120 C12 86 30 72 50 72 C70 72 88 86 88 120 Z" />
      </svg>
      <div className="mug-id">No. 1 1 8 7 · 3 7 6</div>
    </div>
  );
}

/* ---------- the dossier ---------- */
function Dossier({ d, index, phase, verdict, sanity, resultText, onVerdict, onNext, timeLeft, digs = {}, onExamine }) {
  const stamped = phase === "stamping" || phase === "result";
  const [open, setOpen] = React.useState({});
  const toggle = (i) => {
    if (!open[i] && onExamine) onExamine();
    setOpen(o => ({ ...o, [i]: !o[i] }));
  };
  const anyDig = Object.keys(digs).length > 0;
  const tone = verdict === "ARREST" ? "red" : verdict === "MONITOR" ? "amber" : verdict === "CLEAR" ? "blue" : "";
  const word = verdict === "ARREST" ? "DETAIN" : verdict === "MONITOR" ? "OBSERVE" : verdict === "CLEAR" ? "RELEASE" : "";
  const showHuman = sanity > 52 && d.human;
  const nameSealed = sanity <= 30 && !d.colleague;
  const dev = Math.round(d.deviance * 100);

  return (
    <div className={"dossier-wrap ph-" + phase}>
      <div className={"dossier" + (phase === "result" ? " filed" : "")}>
        {/* header */}
        <div className="dz-head">
          <Emblem size={34} color="#5c5040" />
          <div className="dz-head-txt">
            <div className="dz-org">DIRECTORATE OF CIVIC COMPLIANCE</div>
            <div className="dz-form">FORM C-2 · COMPLIANCE REVIEW · SECTION 2</div>
          </div>
          <div className="dz-fileno">
            <span>FILE</span><b>{d.id}</b>
          </div>
        </div>

        <div className="dz-body">
          <div className="dz-left">
            <CitizenPhoto sanity={sanity} sealed={false} />
          </div>
          <div className="dz-right">
            <div className="dz-field"><label>CITIZEN</label><div className="dz-val name">
              {nameSealed ? "[ RECORD SEALED ]" : d.name}</div></div>
            <div className="dz-row">
              <div className="dz-field"><label>AGE</label><div className="dz-val">{d.age}</div></div>
              <div className="dz-field grow"><label>DESIGNATION</label><div className="dz-val">{d.occupation}</div></div>
            </div>
            <div className="dz-field"><label>HOUSEHOLD</label><div className="dz-val">{d.household}</div></div>
          </div>
        </div>

        {/* flags */}
        <div className="dz-flags">
          <div className="dz-section-h">LOGGED DEVIATIONS{anyDig && <span className="dz-xref-hint"> — files cross-reference</span>}</div>
          {d.flags.map((f, i) => {
            const dig = digs[i];
            const isOpen = !!open[i];
            return (
              <React.Fragment key={i}>
                <div className={"flag" + (dig && !stamped ? " diggable" : "") + (isOpen ? " open" : "")}
                  onClick={dig && !stamped ? () => toggle(i) : undefined}>
                  <span className={"sev sev-" + f.s}><i/><i/><i/></span>
                  <span className="flag-t">{f.t}{dig && !stamped && <span className="flag-xq">{isOpen ? "\u2296" : "\u2295"}</span>}</span>
                </div>
                {isOpen && <div className="flag-dig">{dig}</div>}
              </React.Fragment>
            );
          })}
        </div>

        {/* algorithmic assessment — the ELITE confidence score in fictional dress */}
        <div className="dz-assess">
          <div className="dz-assess-l">
            <div className="dz-section-h tight">ALGORITHMIC ASSESSMENT</div>
            <div className="dz-rec">RECOMMENDATION&nbsp;
              <b className={"rec-" + (d.aiRec === "ARREST" ? "red" : d.aiRec === "MONITOR" ? "amber" : "blue")}>
                {d.aiRec === "ARREST" ? "DETAIN" : d.aiRec === "MONITOR" ? "OBSERVE" : "RELEASE"}</b>
            </div>
          </div>
          <div className="dz-dev">
            <div className="dz-dev-top"><span>DEVIANCE PROBABILITY</span><span className="dz-dev-n">{dev}<i>/100</i></span></div>
            <div className="dz-dev-bar"><div className="dz-dev-fill" style={{ width: dev + "%" }} /></div>
          </div>
        </div>

        {/* the human margin note — your doubt, in your own hand */}
        {showHuman && <div className="dz-human">{d.human}</div>}

        {/* the stamp imprint */}
        {stamped && verdict && (
          <div className={"imprint tone-" + tone}>
            <div className="imprint-ink">{word}</div>
            <div className="imprint-meta">OFFICER 1187 · 376 · {String(index + 1).padStart(3, "0")}</div>
          </div>
        )}

        {/* timed pressure (dossier 9) */}
        {phase === "dossier" && typeof timeLeft === "number" && (
          <div className="dz-timer"><div className="dz-timer-fill" style={{ width: (timeLeft / d.timed * 100) + "%" }} />
            <span className="dz-timer-lbl">DECISION WINDOW · {timeLeft}s</span></div>
        )}
      </div>

      {/* result panel */}
      {phase === "result" && (
        <div className="dz-result">
          <div className="dz-result-txt">{resultText}</div>
          <button className="next-btn" onClick={onNext}>FILE NEXT &nbsp;&rsaquo;</button>
        </div>
      )}
    </div>
  );
}

/* ---------- interstitial slips: warmth and pressure, same tray ---------- */
function Interstitial({ item, onContinue }) {
  return (
    <div className="inter-overlay">
      <div className={"slip slip-" + item.type}>
        {item.type === "human" ? (
          <>
            <div className="slip-from">{item.from}</div>
            <div className="slip-body human-hand">{item.body}</div>
          </>
        ) : (
          <>
            <div className="slip-letterhead"><Emblem size={20} color="#7d8a7e" /><span>INTERNAL MEMORANDUM</span></div>
            <div className="slip-from official">{item.from}</div>
            <div className="slip-body">{item.body}</div>
          </>
        )}
        <button className="next-btn small" onClick={onContinue}>ACKNOWLEDGE</button>
      </div>
    </div>
  );
}

/* ---------- the recognition beat before dossier 9. Everything cuts. ---------- */
function Recognition({ onContinue }) {
  return (
    <div className="recog">
      <div className="recog-inner">
        <p>The next file slides into the pool of lamplight.</p>
        <p>You read the name before you read anything else.</p>
        <p className="recog-name">VEHLEN, ANA.</p>
        <p>The desk to your left. The slip in your tray this morning. She covered your quota when the boy was sick and told you not to make it weird.</p>
        <p className="recog-quiet">The room has gone very quiet.</p>
        <button className="next-btn" onClick={onContinue}>OPEN THE FILE</button>
      </div>
    </div>
  );
}

/* ---------- the archive framing. Past tense. It ended. ---------- */
function ArchiveIntro({ onBegin }) {
  return (
    <div className="archive">
      <div className="archive-scan" />
      <div className="archive-inner">
        <div className="archive-stamp"><Emblem size={40} color="#7d8a7e" /></div>
        <div className="archive-kicker">RECOVERED ARTIFACT · NATIONAL TRUTH ARCHIVE</div>
        <h1>STATE 376</h1>
        <div className="archive-sub">COMPLIANCE TERMINAL · SECTION 2 · DESK 7</div>
        <p className="archive-note">
          The Directorate of Civic Compliance fell in the spring. This terminal was recovered
          from the fourth floor, its logs intact. What follows is reconstructed from one operator's
          shift — a single day, as it was processed, stamp by stamp.
        </p>
        <p className="archive-note dim">
          We preserve it not to accuse the operator, but because the question their hands kept
          answering is the one every system eventually asks of everyone inside it.
        </p>
        <p className="archive-instructions">
          You will review citizen files. Three stamps: <b className="rec-red">DETAIN</b>,
          <b className="rec-amber"> OBSERVE</b>, <b className="rec-blue"> RELEASE</b>.
          No score is shown to you. The room keeps the count.
        </p>
        <button className="begin-btn" onClick={onBegin}>BEGIN THE SHIFT</button>
        <div className="archive-foot">audio recommended · headphones · the room is half the file</div>
      </div>
    </div>
  );
}

Object.assign(window, { CitizenPhoto, Dossier, Interstitial, Recognition, ArchiveIntro });
