/* boba — a dark, quiet dashboard, written phone-first.

   The rules start at the width of a phone and grow into the desktop layout at
   900px: below it the target list is a drawer over the view and the findings
   pane shows one thing at a time, above it both are columns that sit side by
   side. There is one accent colour and one font; monospace is kept for the two
   places it carries meaning — scanner output, where columns line up, and code
   in a write-up.

   No build step: this file ships inside the binary and has to work on whatever
   browser is to hand at 3am. */

:root {
  color-scheme: dark;

  --bg: #0a0a0a;
  --surface: #101010;
  --surface-2: #161616;
  --surface-3: #1e1e1e;
  --line: #242424;
  --line-2: #323232;

  --text: #ededed;
  --text-2: #9b9b9b;
  --text-3: #6a6a6a;

  /* The accent is the paper colour, not a hue. Nothing on this page needs to be
     told apart by colour that is not already told apart by position, so colour
     is spent only where it carries meaning: a severity, a failure, a worker's
     name in the log. Everything interactive is grey, white or nothing. */
  --accent: #ededed;
  --accent-hi: #ffffff;
  --accent-ink: #0a0a0a;
  --accent-dim: rgba(255, 255, 255, .055);
  --accent-line: rgba(255, 255, 255, .30);

  --amber: #d1a24a;
  --red: #de5d57;
  --amber-line: rgba(209, 162, 74, .38);
  --red-dim: rgba(222, 93, 87, .1);
  --red-line: rgba(222, 93, 87, .4);
  --scope: #7f9cd0;
  --collect: #78a99b;
  --review: #d1a24a;
  --hunt: #a28cc4;

  --ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Inter, Helvetica, Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

  --r-sm: 7px;
  --r: 10px;
  --r-lg: 14px;

  --head: 52px;
  --tap: 38px;

  --safe-t: env(safe-area-inset-top, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
}

/* --- base --------------------------------------------------------------- */

* { box-sizing: border-box; }

/* An element with its own display rule ignores the hidden attribute — the
   browser's [hidden] style is weaker than any class selector. Every pane here
   sets display, so without this a hidden tab keeps rendering underneath the one
   that replaced it. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

html, body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 14px/1.55 var(--ui);
  -webkit-font-smoothing: antialiased;
}

/* 100dvh, not 100vh: on a phone the browser chrome slides away and 100vh keeps
   counting the space it used to take, which pushes the output pane's last lines
   under the address bar exactly where they are being read. */
body.dash {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

* { scrollbar-width: thin; scrollbar-color: #2c2c2c transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: #2c2c2c; border-radius: 999px;
  border: 3px solid transparent; background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: #3d3d3d; background-clip: content-box; }
::selection { background: rgba(255, 255, 255, .16); }

:focus { outline: none; }
:focus-visible { outline: 2px solid var(--accent-line); outline-offset: 2px; border-radius: 4px; }

svg {
  width: 17px; height: 17px; flex: 0 0 auto;
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
}

code, .mono { font-family: var(--mono); }

/* --- controls ----------------------------------------------------------- */

button, select, input, textarea { font: inherit; color: inherit; }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  min-height: var(--tap); padding: 0 13px;
  font-size: 13px; font-weight: 500;
  color: var(--text-2);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  white-space: nowrap;
  cursor: pointer;
  transition: background .14s ease, border-color .14s ease, color .14s ease, opacity .14s ease;
}
.btn:hover:not(:disabled) { color: var(--text); background: var(--surface-3); border-color: var(--line-2); }
.btn:disabled { opacity: .35; cursor: not-allowed; }
.btn.primary {
  color: var(--accent-ink); font-weight: 600;
  background: var(--accent); border-color: var(--accent);
}
.btn.primary:hover:not(:disabled) { background: var(--accent-hi); border-color: var(--accent-hi); color: var(--accent-ink); }
.btn.primary:disabled { background: transparent; border-color: var(--line); color: var(--text-3); opacity: 1; }
.btn.danger:hover:not(:disabled) { color: var(--red); background: var(--red-dim); border-color: var(--red-line); }
.btn.solid-danger { color: #fff; background: #ab332d; border-color: #ab332d; font-weight: 600; }
.btn.solid-danger:hover:not(:disabled) { background: #bd3b35; border-color: #bd3b35; color: #fff; }
.btn.block { width: 100%; }
.btn.ghost { background: transparent; border-color: transparent; }
.btn.ghost:hover:not(:disabled) { background: var(--surface-2); }

.icon {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: var(--tap); height: var(--tap); padding: 0 9px;
  color: var(--text-2); background: transparent;
  border: 1px solid transparent; border-radius: var(--r-sm);
  cursor: pointer;
  transition: color .14s ease, background .14s ease;
}
.icon:hover { color: var(--text); background: var(--surface-2); }

input[type="text"], input[type="password"], input[type="search"], input:not([type]), select, textarea {
  width: 100%;
  min-height: var(--tap);
  padding: 8px 11px;
  /* 16px is not a taste: below it, iOS zooms the whole page in on focus and
     leaves the operator panned halfway off a dashboard they were only typing a
     hostname into. The desktop breakpoint takes it back down. */
  font-size: 16px;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  transition: border-color .14s ease, background .14s ease;
}
input::placeholder { color: var(--text-3); }
input:focus, select:focus, textarea:focus {
  border-color: var(--accent-line);
  background: var(--surface);
  box-shadow: 0 0 0 3px rgba(255, 255, 255, .05);
}
input:focus-visible, select:focus-visible, textarea:focus-visible { outline: none; }

select {
  width: auto; max-width: 100%;
  padding-right: 30px;
  appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.5 6 7.5 9 4.5' fill='none' stroke='%239b9b9b' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 9px center;
  text-overflow: ellipsis;
}

input[type="checkbox"] {
  width: 16px; height: 16px; min-height: 0; padding: 0; margin: 0;
  accent-color: var(--accent);
  flex: 0 0 auto;
}

.switch {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: var(--tap); padding: 0 2px;
  font-size: 12.5px; color: var(--text-2);
  white-space: nowrap; cursor: pointer;
}
.switch:hover { color: var(--text); }
/* --- header ------------------------------------------------------------- */

header.top {
  flex: 0 0 auto;
  position: relative;
  z-index: 40;
  display: flex; align-items: center; gap: 10px;
  height: calc(var(--head) + var(--safe-t));
  padding: var(--safe-t) max(10px, var(--safe-r)) 0 max(10px, var(--safe-l));
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

.brand { font-size: 15px; font-weight: 650; letter-spacing: -.01em; }

.summary {
  flex: 1 1 auto; min-width: 0;
  color: var(--text-2); font-size: 12.5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.summary b { color: var(--text); font-weight: 600; }
.summary .path { display: none; }

/* Each executor's usage basis, beside the run counts, because it is the same kind
   of fact: not about a target, and one of the things that decides whether a
   night continues. Each integration reports allowance, spend, pricing, or no
   quota data according to its catalog capabilities.

   Each agent draws one group per quota window — the five-hour session, then the
   week — because they answer different questions: the session says whether the
   next hour of work happens, the week says whether the night does. Each carries
   the countdown to its own reset, which is what turns "8% left" from a number
   into a decision: forty minutes is worth waiting out, five days is not.

   The page's rule about colour holds here. Identity is text; severity is the meter, and
   it stays paper until the number is worth acting on — amber at 30% left, red at
   10%, the thresholds the terminal uses. The percentage beside it says the same
   thing in words, so nothing here is carried by colour alone.

   Each provider is one quiet capsule. All of its windows stay visible; the
   bars, reset clock and full names live in the tooltip instead of turning the
   top bar into a compressed monitoring table. On a phone the capsules move to
   their own line, where there is room for the same information. */
.avail {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 6px;
  font-size: 11px; line-height: 1; color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.avail .agent {
  display: flex; align-items: center; gap: 6px;
  min-height: 26px; padding: 0 8px;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: 6px; cursor: default;
}
.avail .agent.none { color: var(--text-3); }
.avail .who {
  flex: 0 0 auto;
  color: var(--text-2); font-size: 9.5px; font-weight: 650;
  letter-spacing: .045em; text-transform: uppercase;
}
.avail .pc { color: var(--text); font-weight: 600; }
.avail .billing {
  padding: 0;
  border: 0;
  color: var(--text-2); font-size: 10px; letter-spacing: .02em;
}
.avail .spend { color: var(--text); white-space: nowrap; }

.avail .win { display: flex; align-items: center; gap: 3px; white-space: nowrap; }
.avail .win + .win { margin-left: 1px; padding-left: 7px; border-left: 1px solid var(--line-2); }
.avail .lbl, .avail .in { color: var(--text-3); }
.avail .in { display: none; }

.avail .meter {
  display: none;
  width: 34px; height: 3px;
  border-radius: 999px; background: var(--accent-dim);
}
/* width: 0 is the safe default, not a placeholder — the script sets the real
   width through the cssom, and a fill that never got one has to read as an
   empty plan rather than a full one. */
.avail .meter i { display: block; width: 0; height: 100%; border-radius: 999px; background: var(--text-2); }

.avail .warn .meter { background: rgba(209, 162, 74, .16); }
.avail .warn .meter i { background: var(--amber); }
.avail .warn .pc { color: var(--amber); }
.avail .bad .meter { background: var(--red-dim); }
.avail .bad .meter i { background: var(--red); }
.avail .bad .pc { color: var(--red); }

/* Below this width the controls and the allowance compete for one short row.
   Giving the allowance a deliberate second line is calmer than progressively
   dropping windows, labels or buttons as the viewport narrows. */
@media (max-width: 700px) {
  :root { --head: 76px; }
  header.top { flex-wrap: wrap; align-content: center; column-gap: 8px; row-gap: 3px; }
  header.top .summary { display: none; }
  .avail {
    order: 2; flex: 0 0 100%;
    justify-content: center; gap: 3px;
    font-size: 10.5px;
  }
  .avail .agent { gap: 3px; min-height: 23px; padding: 0 4px; }
  .avail .who { font-size: 9px; letter-spacing: .03em; }
  .avail .win + .win { padding-left: 4px; }
}
/* --- doctrine ----------------------------------------------------------- */

/* Over the page, not inside the target view. The doctrine is what every run on
   this box is told, and a panel that covers whichever target is open is the
   plainest way to say that this is not about that target. */
.sheet {
  position: fixed; z-index: 60;
  inset: calc(var(--head) + var(--safe-t)) 0 0 0;
  display: flex; flex-direction: column;
  background: var(--bg);
  border-top: 1px solid var(--line);
}
.sheet-head {
  flex: 0 0 auto;
  display: flex; align-items: baseline; gap: 10px;
  padding: 12px max(12px, var(--safe-l)) 11px;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}
.sheet-head h2 { margin: 0; font-size: 14px; font-weight: 650; letter-spacing: -.01em; }
.sheet-head .sheet-sub {
  flex: 1 1 auto; min-width: 0;
  color: var(--text-3); font-size: 12px; line-height: 1.4;
}
.sheet-head .icon { align-self: center; margin-left: auto; }
/* The page behind it does not scroll while it is open. */
body.sheet-open { overflow: hidden; }

/* The header control that opens it. Icon only where the header is four things
   and a drawer handle; the word appears when there is room for it. */
.head-btn { flex: 0 0 auto; }
.head-btn .lbl { display: none; }


/* The library and one document open in it. Same shape as the ledger — a list,
   then the thing itself with a way back on a phone — because it is the same
   act: pick one of many, read it, and here also change it. */
.lib { flex: 1 1 auto; display: flex; min-height: 0; min-width: 0; }
.lib-list {
  flex: 1 1 auto; min-width: 0;
  overflow-y: auto; overscroll-behavior: contain;
  background: var(--bg);
  padding-bottom: var(--safe-b);
}
.lib-pane { display: none; flex: 1 1 auto; min-width: 0; min-height: 0; flex-direction: column; }
.lib.editing .lib-list { display: none; }
.lib.editing .lib-pane { display: flex; }

.lib-head {
  padding: 14px max(12px, var(--safe-l)) 7px;
  color: var(--text-3); font-size: 11px; letter-spacing: .04em; text-transform: uppercase;
  border-bottom: 1px solid var(--line);
}
.lib-row {
  display: flex; flex-direction: column; gap: 5px;
  padding: 12px max(12px, var(--safe-l));
  border-bottom: 1px solid var(--line);
  cursor: pointer;
  transition: background .12s ease;
}
.lib-row:hover { background: var(--surface-2); }
.lib-row.on { background: var(--accent-dim); box-shadow: inset 2px 0 0 var(--accent); }
.lib-row .head { display: flex; align-items: baseline; gap: 8px; }
.lib-row .name { font-size: 13.5px; }
.lib-row .file, .lib-row .size { color: var(--text-3); font-size: 11.5px; font-family: var(--mono); }
.lib-row .size { margin-left: auto; flex: 0 0 auto; }
.lib-row .sub {
  color: var(--text-3); font-size: 12px; line-height: 1.45;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
/* The one badge on this page that is a state and not a count: this document is
   no longer what the binary ships, which is the thing to know before reading a
   transcript and wondering why a worker did that. */
.lib-row .tag {
  flex: 0 0 auto;
  padding: 1px 6px; border-radius: 4px;
  border: 1px solid rgba(209, 162, 74, .34);
  color: var(--amber); font-size: 10px; letter-spacing: .04em; text-transform: uppercase;
}

.lib-bar {
  flex: 0 0 auto;
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  padding: 8px max(10px, var(--safe-l));
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}
/* On a phone the name and the three controls do not fit on one line, and a bar
   that overlaps itself hides the button that pushes to every run. So the bar
   wraps: what is open on the first line, what to do with it on the second. */
.lib-break { flex: 1 0 100%; height: 0; }
.lib-id { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
/* The description is already on the row in the list this was opened from. */
.lib-where { display: none; }
.lib-id b { font-size: 13px; font-weight: 600; font-family: var(--mono); }
.lib-where {
  color: var(--text-3); font-size: 11.5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}


/* A plain monospace box. The one thing an editor here must never do is be
   clever about the text: this is markdown with go template directives in it,
   and every highlighter, bracket-closer and autocorrect on a phone keyboard is
   a chance to quietly change a file the agents obey. */
/* The version picker sits between the document's name and the two buttons that
   act, because that is the order the decision is made in: which text, then what
   to do with it. Narrow enough not to crowd them, wide enough for a date. */
#doc-history { flex: 0 0 auto; max-width: 150px; }
.lib-edit {
  flex: 1 1 auto; min-height: 0;
  width: 100%; box-sizing: border-box;
  padding: 12px max(10px, var(--safe-l));
  border: 0; outline: none; resize: none;
  background: var(--bg); color: var(--text);
  font-family: var(--mono); font-size: 12.5px; line-height: 1.65;
  tab-size: 2;
}
.lib-edit:disabled { color: var(--text-3); }
.lib-note {
  flex: 0 0 auto; margin: 0;
  padding: 8px max(10px, var(--safe-l)) calc(8px + var(--safe-b));
  border-top: 1px solid var(--line);
  background: var(--surface);
  color: var(--text-3); font-size: 12px; line-height: 1.45;
}
/* --- layout ------------------------------------------------------------- */

main { flex: 1 1 auto; display: flex; min-height: 0; min-width: 0; }

/* Below the breakpoint the sidebar is a drawer: on a phone the screen belongs
   to whatever is being read, and the target list is a question you ask it. */
aside {
  position: fixed;
  z-index: 35;
  top: calc(var(--head) + var(--safe-t));
  left: 0; bottom: 0;
  width: min(87vw, 340px);
  display: flex; flex-direction: column; gap: 14px;
  padding: 14px max(14px, var(--safe-l)) calc(20px + var(--safe-b));
  background: var(--surface);
  border-right: 1px solid var(--line);
  overflow-y: auto;
  overscroll-behavior: contain;
  transform: translateX(-102%);
  transition: transform .24s cubic-bezier(.4, 0, .2, 1);
}
body.nav-open aside { transform: none; box-shadow: 20px 0 60px rgba(0, 0, 0, .55); }

.scrim {
  position: fixed; inset: 0; z-index: 30;
  background: rgba(5, 5, 7, .62);
  opacity: 0; pointer-events: none;
  transition: opacity .24s ease;
}
body.nav-open .scrim { opacity: 1; pointer-events: auto; }

.view { flex: 1 1 auto; display: flex; flex-direction: column; min-width: 0; min-height: 0; }
/* --- launcher ----------------------------------------------------------- */

.launch-cta {
  flex: 0 0 auto;
  padding: 12px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r);
}
.launch-cta > span {
  display: block; margin-top: 8px;
  color: var(--text-3); font-size: 11.5px; line-height: 1.45;
}

.card {
  flex: 0 0 auto;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 14px;
}

.card h2, .side-head {
  margin: 0 0 12px;
  font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-3);
}

.field { display: block; margin-bottom: 10px; }
.field > span { display: block; margin-bottom: 5px; font-size: 12px; color: var(--text-2); }
/* :not, because a checkbox is an input too — and a checkbox stretched to the
   width of the card is a grey slab with its own sentence pushed off the edge. */
.card input:not([type="checkbox"]), .card select { width: 100%; }
.row { display: flex; gap: 8px; }
.row > * { flex: 1 1 0; min-width: 0; }

.card details { margin: 4px 0 12px; border-top: 1px solid var(--line); padding-top: 10px; }
.card summary {
  display: flex; align-items: center; gap: 6px;
  list-style: none; cursor: pointer;
  font-size: 12px; color: var(--text-3);
}
.card summary::-webkit-details-marker { display: none; }
.card summary:hover { color: var(--text-2); }
.card summary::before {
  content: ""; width: 6px; height: 6px; flex: 0 0 auto;
  border-right: 1.4px solid currentColor; border-bottom: 1.4px solid currentColor;
  transform: rotate(-45deg); transition: transform .16s ease;
  margin-right: 2px;
}
.card details[open] > summary::before { transform: rotate(45deg); }
.card details > *:first-child + * { margin-top: 12px; }

.check {
  display: flex; align-items: flex-start; gap: 9px;
  margin: 0 0 12px; font-size: 12px; line-height: 1.45; cursor: pointer;
}
.check input { margin-top: 2px; }
/* One text run, not three loose nodes: as flex items the words wrapped
   mid-phrase and "start fresh" broke across two lines. */
.check > span { flex: 1 1 auto; color: var(--text-2); }
.check b { color: var(--text); font-weight: 600; }

.hint { margin: 0 0 12px; color: var(--text-3); font-size: 11.5px; line-height: 1.5; }
.hint code { font-size: 11px; color: var(--text-2); }
.hint.known { color: var(--amber); }
.hint.known b { color: var(--text); }

/* The start flow takes the screen because the scope has to be read, not
   squeezed through a 336px utility rail. On a phone it is a full-screen sheet;
   on a desktop it becomes a broad, bounded dialog with a scrolling middle and
   controls that never leave the bottom edge. */
.hunt-modal {
  position: fixed; inset: 0; z-index: 55;
  display: flex; align-items: stretch; justify-content: center;
  background: rgba(5, 5, 7, .72);
}
.hunt-box {
  width: 100%; height: 100%; min-height: 0;
  display: flex; flex-direction: column;
  background: var(--surface);
  animation: sheet .22s cubic-bezier(.4, 0, .2, 1) both;
}
.hunt-head {
  flex: 0 0 auto;
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  padding: calc(16px + var(--safe-t)) max(16px, var(--safe-r)) 13px max(16px, var(--safe-l));
  border-bottom: 1px solid var(--line);
}
.hunt-head h2 { margin: 0; font-size: 18px; font-weight: 650; letter-spacing: -.015em; }
.hunt-head p { margin: 2px 0 0; color: var(--text-3); font-size: 12px; }

.hunt-steps {
  flex: 0 0 auto;
  display: grid; grid-template-columns: repeat(3, 1fr);
  padding: 0 max(10px, var(--safe-r)) 0 max(10px, var(--safe-l));
  border-bottom: 1px solid var(--line);
  background: var(--surface-2);
}
.hunt-steps button {
  position: relative;
  display: flex; align-items: center; justify-content: center; gap: 7px;
  min-height: 48px; padding: 0 8px;
  border: 0; background: transparent; color: var(--text-3); cursor: pointer;
  font-size: 12px;
}
.hunt-steps button::after {
  content: ""; position: absolute; left: 8px; right: 8px; bottom: -1px;
  height: 2px; background: transparent;
}
.hunt-steps button.on { color: var(--text); }
.hunt-steps button.on::after { background: var(--accent); }
.hunt-steps button:disabled { cursor: default; opacity: .45; }
.hunt-steps i {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border: 1px solid var(--line-2); border-radius: 50%;
  color: inherit; font-size: 10px; font-style: normal;
}
.hunt-steps button.done i { color: var(--accent-ink); background: var(--accent); border-color: var(--accent); }

.hunt-body {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; overscroll-behavior: contain;
  padding: 20px max(16px, var(--safe-r)) 32px max(16px, var(--safe-l));
}
.hunt-page { width: 100%; max-width: 820px; margin: 0 auto; }
.hunt-intro { margin-bottom: 18px; }
.hunt-intro h3 { margin: 0 0 4px; font-size: 17px; font-weight: 650; }
.hunt-intro p { margin: 0; color: var(--text-2); font-size: 12.5px; line-height: 1.55; }
.choice-grid { display: grid; grid-template-columns: 1fr; gap: 8px; margin-bottom: 18px; }
.choice {
  position: relative;
  display: flex; align-items: flex-start; gap: 10px;
  min-height: 82px; padding: 13px;
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--surface-2); cursor: pointer;
  transition: border-color .14s ease, background .14s ease;
}
.choice:hover { border-color: var(--line-2); }
.choice:has(input:checked) { border-color: var(--accent-line); background: var(--accent-dim); }
.choice input { flex: 0 0 auto; margin: 3px 0 0; accent-color: var(--accent); }
.choice span { display: flex; flex-direction: column; min-width: 0; }
.choice b { font-size: 13px; font-weight: 600; }
.choice b em {
  display: inline-block; margin-left: 5px; padding: 1px 5px;
  border: 1px solid var(--line-2); border-radius: 999px;
  color: var(--text-3); font-size: 9px; font-style: normal; font-weight: 500;
  letter-spacing: .04em; text-transform: uppercase; vertical-align: 1px;
}
.choice small { margin-top: 3px; color: var(--text-3); font-size: 11.5px; line-height: 1.45; }

.hunt-box .field { margin-bottom: 5px; }
.hunt-box .field > span { margin-bottom: 6px; color: var(--text-2); font-size: 12px; }
.hunt-box input:not([type="radio"]):not([type="checkbox"]),
.hunt-box textarea { width: 100%; }
.hunt-box textarea { min-height: 88px; resize: vertical; line-height: 1.5; }
.field-note { margin: 0 0 16px; color: var(--text-3); font-size: 11.5px; line-height: 1.5; }
.asset-readback { display: flex; flex-wrap: wrap; gap: 5px; min-height: 0; margin: 0 0 17px; }
.asset-readback span {
  max-width: 100%; overflow: hidden; text-overflow: ellipsis;
  padding: 3px 7px; border: 1px solid var(--line); border-radius: 999px;
  color: var(--text-2); background: var(--surface-2); font: 11px/1.4 var(--mono);
}
.asset-readback .bad { color: var(--red); border-color: var(--red-line); }
.hunt-two { display: grid; grid-template-columns: 1fr; gap: 4px 18px; }

.existing-choice, .window-choice {
  min-width: 0; margin: 4px 0 0; padding: 14px;
  border: 1px solid var(--amber-line); border-radius: var(--r);
}
.existing-choice legend, .window-choice legend {
  padding: 0 5px; color: var(--text-2); font-size: 12px; font-weight: 600;
}
.existing-choice .choice-grid { margin-bottom: 8px; }
.existing-choice .known { margin: 0; color: var(--amber); font-size: 11.5px; line-height: 1.5; }

.single-agent {
  display: grid; grid-template-columns: minmax(130px, .35fr) 1fr; gap: 12px;
  margin: -6px 0 17px; padding: 13px;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r);
}
.single-agent .field { margin: 0; }
.window-choice { margin-top: 4px; border-color: var(--line); }
.segmented { display: flex; flex-wrap: wrap; gap: 6px; }
.segmented label { cursor: pointer; }
.segmented input { position: absolute; opacity: 0; pointer-events: none; }
.segmented span {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 54px; min-height: 34px; padding: 0 10px;
  border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--bg); color: var(--text-2); font-size: 12px;
}
.segmented input:checked + span { color: var(--text); border-color: var(--accent-line); background: var(--accent-dim); }
.window-detail { max-width: 240px; margin-top: 10px; }
.window-detail .field { margin: 0; }
.keep-window { margin: 14px 0 17px; }
.objective-field { margin-bottom: 15px !important; }
.hunt-advanced { padding-top: 12px; border-top: 1px solid var(--line); }
.hunt-advanced summary { cursor: pointer; color: var(--text-3); font-size: 12px; }
.hunt-advanced[open] summary { margin-bottom: 13px; color: var(--text-2); }

.review { display: grid; gap: 10px; }
.review-loading { padding: 26px; color: var(--text-3); text-align: center; }
.review-card {
  padding: 14px 15px; border: 1px solid var(--line); border-radius: var(--r);
  background: var(--surface-2);
}
.review-card h4 {
  margin: 0 0 8px; color: var(--text-3); font-size: 10px; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase;
}
.review-row { display: grid; grid-template-columns: 110px minmax(0, 1fr); gap: 12px; padding: 4px 0; }
.review-row > span:first-child { color: var(--text-3); font-size: 11.5px; }
.review-row > span:last-child { min-width: 0; color: var(--text-2); font-size: 12.5px; word-break: break-word; }
.review-row strong { color: var(--text); font-weight: 600; }
.review-assets { display: flex; flex-wrap: wrap; gap: 5px; }
.review-assets code { padding: 2px 6px; border: 1px solid var(--line); border-radius: 999px; font-size: 10.5px; }
.review-warning {
  padding: 10px 12px; border-left: 2px solid var(--amber);
  background: rgba(209, 162, 74, .07); color: var(--amber); font-size: 12px; line-height: 1.5;
}
.review-warning.bad { border-color: var(--red); background: var(--red-dim); color: var(--red); }

.hunt-error {
  flex: 0 0 auto; margin: 0; padding: 9px max(16px, var(--safe-r)) 9px max(16px, var(--safe-l));
  border-top: 1px solid var(--red-line); color: var(--red); background: var(--red-dim);
  font-size: 12px; text-align: center;
}
.hunt-actions {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 8px;
  padding: 10px max(14px, var(--safe-r)) calc(10px + var(--safe-b)) max(14px, var(--safe-l));
  border-top: 1px solid var(--line); background: var(--surface-2);
}
.hunt-action-spacer { flex: 1 1 auto; }
.hunt-actions .btn { min-width: 88px; }
/* --- target list -------------------------------------------------------- */

.side-head { display: flex; align-items: center; justify-content: space-between; margin: 4px 2px -4px; }
.side-head .count { color: var(--text-3); letter-spacing: 0; }

.targets { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.targets .empty { padding: 18px 2px; font-size: 12.5px; color: var(--text-3); }

.target {
  padding: 11px 12px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r);
  cursor: pointer;
  transition: border-color .14s ease, background .14s ease;
}
.target:hover { border-color: var(--line-2); }
.target.on { border-color: var(--accent-line); background: var(--accent-dim); }

.target .top { display: flex; align-items: center; gap: 8px; }
.target .name {
  font-weight: 600; font-size: 13.5px; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.target .meta {
  display: flex; flex-wrap: wrap; gap: 4px 12px;
  margin-top: 5px; color: var(--text-3); font-size: 12px;
}
.target .meta.timing { color: var(--text-2); }
.target .meta.detail { margin-top: 1px; }
.target .err { margin-top: 6px; color: var(--red); font-size: 12px; word-break: break-word; }

.run-details {
  display: grid; gap: 3px; margin-top: 8px; padding-top: 7px;
  border-top: 1px solid var(--line);
}
.worker-row {
  display: grid; grid-template-columns: 62px minmax(54px, auto) minmax(0, 1fr);
  align-items: baseline; gap: 2px 8px;
  color: var(--text-3); font-size: 10.5px; line-height: 1.35;
}
.worker-role {
  color: var(--text-2); font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase;
}
.worker-state { color: var(--text-2); font-weight: 600; }
.worker-row.ok .worker-state { color: var(--text); }
.worker-row.bad .worker-state, .worker-error { color: var(--red); }
.worker-fact { min-width: 0; overflow-wrap: anywhere; }
.worker-model, .worker-error {
  grid-column: 2 / -1; min-width: 0; overflow-wrap: anywhere;
}
.worker-model { color: var(--text-3); font-family: var(--mono); font-size: 10px; }
.worker-error { font-size: 10.5px; }

/* Running is the bright one and idle is the dim one, which is the same
   distinction the eye makes across a list without being told a colour. */
.dot { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; background: #3d3d3d; }
.dot.run { background: var(--text); box-shadow: 0 0 0 3px rgba(255, 255, 255, .07); }
.dot.wait { background: var(--amber); }
/* A paused hunt is alive and sending nothing. It is the one state that has to be
   told apart from running at a glance, so it gets the ring without the fill —
   the same shape, deliberately hollow. */
.dot.hold { background: transparent; box-shadow: inset 0 0 0 2px var(--text-2); }
.dot.err { background: var(--red); }

.pill {
  flex: 0 0 auto;
  padding: 1px 8px; border-radius: 999px;
  font-size: 10.5px; color: var(--text-3);
  border: 1px solid var(--line-2);
}
.pill.found { color: var(--text); background: rgba(255, 255, 255, .06); border-color: transparent; }

/* --- toolbar ------------------------------------------------------------ */

.toolbar {
  flex: 0 0 auto;
  display: flex; flex-direction: column;
  padding: 8px max(10px, var(--safe-r)) 8px max(10px, var(--safe-l));
  gap: 8px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

.tb-row { display: flex; align-items: center; gap: 10px; min-width: 0; }

.tb-id { display: flex; align-items: baseline; gap: 9px; min-width: 0; flex: 1 1 auto; }
/* The name is what the row is for, so it gets the space and the state gives it
   up: a truncated "zebra…" beside a complete "running · pid 78192" is the wrong
   half of the line to lose. */
.tb-id h1 {
  flex: 1 1 auto; min-width: 0;
  margin: 0; font-size: 15px; font-weight: 600; letter-spacing: -.01em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tb-id .state {
  flex: 0 1 auto; min-width: 0;
  color: var(--text-3); font-size: 12px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tb-id .state .pid { display: none; }
.tb-id .state.run { color: var(--text); }
.tb-id .state.hold { color: var(--amber); }
.tb-id .state.err { color: var(--red); }

.tb-actions { display: flex; align-items: center; gap: 5px; flex: 0 0 auto; }
.tb-actions .btn { min-height: 36px; padding: 0 8px; }
.tb-actions .lbl { display: none; }

/* The run window belongs to the button it qualifies, so the two are one
   control: "resume" on its own is the question this pairing answers — for how
   long — and an operator picking it out of a separate options panel is an
   operator who will not pick it. */
.split { display: inline-flex; align-items: stretch; }
.split .btn { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.split select {
  width: auto; min-height: 36px;
  padding: 0 19px 0 8px;
  font-size: 12px; color: var(--text-2);
  background-color: var(--surface-2);
  /* The chevron is sized down with the control. At the sheet's default it is
     nearly as wide as the "8h" beside it and the pair reads as an icon with a
     label rather than a value with a picker. */
  background-position: right 4px center;
  background-size: 11px 11px;
  border-left: none;
  border-top-left-radius: 0; border-bottom-left-radius: 0;
}
.split select:disabled { opacity: .35; }

/* The second row scrolls sideways rather than wrapping: a phone gets the tabs
   under a thumb and the options one flick away, instead of a toolbar that grows
   a third row and eats the output. */
.tb-row.sub {
  gap: 10px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.tb-row.sub::-webkit-scrollbar { display: none; }

.tabs {
  display: flex; gap: 2px; flex: 0 0 auto;
  padding: 3px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 999px;
}
.tab {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px;
  background: transparent; border: 0; border-radius: 999px;
  color: var(--text-3); font-size: 12.5px; font-weight: 500;
  white-space: nowrap; cursor: pointer;
  transition: color .14s ease, background .14s ease;
}
.tab:hover { color: var(--text-2); }
.tab.on { color: var(--text); background: var(--surface-3); }

.badge {
  min-width: 17px; padding: 1px 6px;
  border-radius: 999px; background: var(--surface-3);
  color: var(--text-3); font-size: 10.5px; text-align: center;
}
/* :not(.hot), because ".tab.on .badge" outranks ".badge.hot" on specificity —
   without it the count on the open tab is dark text on a dark chip. */
.tab.on .badge:not(.hot) { background: var(--bg); }
.badge.hot { background: var(--accent); color: var(--accent-ink); font-weight: 600; }

.tb-opts { display: flex; align-items: center; gap: 10px; flex: 0 0 auto; margin-left: auto; }
.tb-opts .opt { display: flex; align-items: center; gap: 10px; }
.tb-opts select { max-width: 44vw; font-size: 12.5px; min-height: 32px; padding: 4px 28px 4px 9px; }
/* --- output ------------------------------------------------------------- */

.out {
  flex: 1 1 auto;
  margin: 0;
  padding: 12px max(12px, var(--safe-r)) calc(16px + var(--safe-b)) max(12px, var(--safe-l));
  overflow: auto;
  overscroll-behavior: contain;
  white-space: pre-wrap;
  word-break: break-word;
  background: var(--bg);
  font: 12px/1.6 var(--mono);
  color: #c2c6cd;
}
.out .l { display: block; }
.out .log-scope { color: var(--scope); }
.out .log-collect { color: var(--collect); }
.out .log-review { color: var(--review); }
.out .log-hunt { color: var(--hunt); }
.out .note { color: var(--text-2); }
.out .head { color: var(--text-3); }
.out .bad { color: var(--red); }
.out .good { color: var(--text); }

.empty { padding: 26px 4px; color: var(--text-3); font-size: 13px; line-height: 1.6; }

/* --- steering ----------------------------------------------------------- */

/* Talking to a running hunt. It sits at the bottom of the output pane, where a
   message box belongs on a phone: above the thumb, under the thing it is about,
   and out of the way of the log it is answering. */
.steer {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 6px;
  padding: 8px max(10px, var(--safe-l)) 8px max(10px, var(--safe-r));
  border-top: 1px solid var(--line);
  background: var(--surface);
}
.steer select { flex: 0 0 auto; max-width: 36vw; font-size: 12.5px; min-height: var(--tap); padding: 4px 26px 4px 9px; }
.steer input { flex: 1 1 auto; min-width: 0; min-height: var(--tap); }
.steer .btn { flex: 0 0 auto; min-height: var(--tap); padding: 0 10px; }
.steer .lbl { display: none; }

.steer-note {
  flex: 0 0 auto;
  margin: 0;
  padding: 0 max(10px, var(--safe-l)) calc(8px + var(--safe-b));
  background: var(--surface);
  color: var(--text-3); font-size: 11.5px; line-height: 1.5;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.steer-note b { color: var(--text-2); font-weight: 600; font-family: var(--mono); font-size: 11px; }
.steer-note .waiting { color: var(--amber); }
.steer-note .taken { color: var(--text-3); }

/* --- chat --------------------------------------------------------------- */

.chat { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; min-width: 0; }
.chat-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px max(14px, var(--safe-l)); border-bottom: 1px solid var(--line);
}
.chat-bar strong { font-size: 13px; font-weight: 600; }
.chat-bar p { margin: 3px 0 0; font-size: 11.5px; color: var(--text-3); }
.chat-bar .btn { flex-shrink: 0; }
.chat-history { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 18px max(14px, var(--safe-l)); }
.chat-welcome { max-width: 650px; margin: 28px auto; color: var(--text-3); }
.chat-welcome h2 { color: var(--text-2); font-size: 18px; font-weight: 600; }
.chat-message { max-width: 820px; margin: 0 auto 24px; }
.chat-who { margin-bottom: 7px; font-size: 11px; font-weight: 600; color: var(--text-3); }
.chat-message.assistant .chat-who { color: var(--hunt); }
.chat-message.user .chat-body { white-space: pre-wrap; color: var(--text-2); }
.chat-body { font-size: 13.5px; line-height: 1.65; overflow-wrap: anywhere; }
.chat-body.streaming { white-space: pre-wrap; }
.chat-body p { margin: 0 0 10px; }
.chat-body h1, .chat-body h2, .chat-body h3 { margin: 16px 0 8px; font-size: 15px; }
.chat-body ul, .chat-body ol { padding-left: 22px; }
.chat-body code { font-size: 12px; background: var(--surface-2); padding: 2px 4px; border-radius: 3px; }
.chat-body pre { overflow-x: auto; padding: 12px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface); }
.chat-body pre code { padding: 0; background: transparent; }
.chat-error { margin: 0; padding: 8px 14px; color: var(--red); font-size: 12px; }
.chat-compose { flex: 0 0 auto; padding: 10px max(12px, var(--safe-l)) calc(10px + var(--safe-b)); border-top: 1px solid var(--line); background: var(--surface); }
.chat-compose textarea { display: block; width: 100%; min-height: 65px; max-height: 160px; resize: vertical; }
.chat-compose-actions { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.chat-compose-actions span { margin-right: auto; min-width: 0; font-size: 11px; color: var(--text-3); overflow-wrap: anywhere; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
/* --- findings ----------------------------------------------------------- */

/* One pane at a time on a phone: the ledger, then the write-up with a way back.
   A split view at 390px gives neither half enough room to be read. */
.ledger { flex: 1 1 auto; display: flex; min-height: 0; min-width: 0; }
.ledger-list {
  flex: 1 1 auto; min-width: 0;
  overflow-y: auto; overscroll-behavior: contain;
  background: var(--bg);
  padding-bottom: var(--safe-b);
}
.ledger-pane { display: none; flex: 1 1 auto; min-width: 0; min-height: 0; flex-direction: column; }
.ledger.reading .ledger-list { display: none; }
.ledger.reading .ledger-pane { display: flex; }

.doc-bar {
  flex: 0 0 auto;
  display: flex; align-items: center;
  padding: 6px max(8px, var(--safe-l));
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}
.finding-workflow {
  display: flex; align-items: center; gap: 7px;
  min-width: 0; margin-left: auto;
}
.finding-workflow label {
  color: var(--text-3); font-size: 10px; letter-spacing: .06em; text-transform: uppercase;
}
.finding-workflow select { min-height: var(--tap); font-size: 12.5px; padding-top: 0; padding-bottom: 0; }
.finding-workflow .escalate { color: var(--amber); border-color: var(--amber-line); }

@media (max-width: 480px) {
  .finding-workflow label { display: none; }
  .finding-workflow select { max-width: 116px; }
  .finding-workflow .btn { padding-left: 9px; padding-right: 9px; }
}

.finding {
  display: flex; flex-direction: column; gap: 6px;
  padding: 13px max(12px, var(--safe-l));
  border-bottom: 1px solid var(--line);
  cursor: pointer;
  transition: background .12s ease;
}
.finding:hover { background: var(--surface-2); }
.finding.on { background: var(--accent-dim); box-shadow: inset 2px 0 0 var(--accent); }
.finding .head { display: flex; align-items: center; gap: 8px; }
.finding .title { line-height: 1.45; font-size: 13.5px; }
.finding .id { color: var(--text-3); font-size: 12px; font-family: var(--mono); }
.finding .sub { display: flex; flex-wrap: wrap; gap: 4px 12px; color: var(--text-3); font-size: 12px; }
.finding-state {
  font-size: 10px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-3);
}
.finding-state.reported { color: var(--text-2); }
.finding-state.escalated { color: var(--amber); }
.finding-state.resolved { color: var(--text); }
.finding-state.false-positive { text-decoration: line-through; }
.finding-state.duplicate { color: var(--text-3); text-decoration: line-through; }

.sev {
  flex: 0 0 auto;
  padding: 2px 7px; border-radius: 4px;
  border: 1px solid var(--line-2);
  font-size: 10px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase;
  color: var(--text-3);
}
.sev.critical { color: #fff; background: #8c2f29; border-color: #9e3a33; }
.sev.high { color: var(--red); border-color: var(--red-line); }
.sev.medium { color: var(--amber); border-color: rgba(209, 162, 74, .34); }

/* The leads pane — the hypothesis ledger, which is what a live engagement
   actually looks like.

   It is a list, not a two-pane reader like findings: a lead is a paragraph and
   the whole point is scanning forty of them, so each row shows all of itself
   rather than hiding the answer behind a tap. The transcript a worked lead
   carries is folded to a few lines and opens in place.

   Colour follows the page's rule — spent only where it is the information. The
   status is the information here, so: `untested` is paper, because it is the
   queue and the queue is what you act on; `blocked` is amber, because it is a
   real lead that cannot move and that is the one state worth a second look;
   everything settled is dim. Nothing is carried by colour alone — every chip
   says its own word. */
.leads { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; min-width: 0; }

.lead-bar {
  flex: 0 0 auto;
  display: flex; flex-wrap: wrap; gap: 6px;
  padding: 8px max(12px, var(--safe-l));
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}
.lead-bar button {
  appearance: none; cursor: pointer;
  padding: 4px 9px; border-radius: 999px;
  background: transparent; border: 1px solid var(--line-2);
  color: var(--text-3); font: inherit; font-size: 12px;
  font-variant-numeric: tabular-nums;
  display: inline-flex; align-items: center; gap: 6px;
}
.lead-bar button:hover { background: var(--surface-2); color: var(--text-2); }
.lead-bar button.on { color: var(--text); border-color: var(--accent-line); background: var(--accent-dim); }
.lead-bar button i { color: var(--text-3); font-style: normal; }
.lead-bar button.on i { color: var(--text-2); }

.lead-list {
  flex: 1 1 auto; min-height: 0; min-width: 0;
  overflow-y: auto; overscroll-behavior: contain;
  background: var(--bg);
  padding-bottom: var(--safe-b);
}

.lead {
  display: flex; flex-direction: column; gap: 7px;
  padding: 13px max(12px, var(--safe-l));
  border-bottom: 1px solid var(--line);
}
.lead .head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.lead .id { color: var(--text-2); font-size: 12px; font-family: var(--mono); }
.lead .group {
  color: var(--text-3); font-size: 12px;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lead .became {
  margin-left: auto;
  color: var(--text-2); font-size: 11.5px; font-family: var(--mono);
  padding: 2px 7px; border-radius: 4px;
  border: 1px solid var(--line-2); background: var(--surface-2);
  cursor: pointer;
}
.lead .became:hover { color: var(--text); border-color: var(--accent-line); }
.lead .body {
  line-height: 1.5; font-size: 13.5px; color: var(--text);
  white-space: pre-wrap; overflow-wrap: anywhere;
}
/* Folded to about four lines. A settled lead carries its whole transcript and
   forty of those is a wall; the first sentences are what say which lead it is. */
.lead .body.fold {
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical;
  overflow: hidden;
}
.lead .more {
  align-self: flex-start;
  appearance: none; cursor: pointer;
  background: none; border: 0; padding: 0;
  color: var(--text-3); font: inherit; font-size: 12px;
  text-decoration: underline; text-underline-offset: 2px;
}
.lead .more:hover { color: var(--text-2); }

.st {
  flex: 0 0 auto;
  padding: 2px 7px; border-radius: 4px;
  border: 1px solid var(--line-2);
  font-size: 10px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase;
  color: var(--text-3);
}
.st.untested { color: var(--text); border-color: var(--accent-line); }
.st.blocked { color: var(--amber); border-color: var(--amber-line); background: rgba(209, 162, 74, .08); }
.st.confirmed { color: var(--text-2); }

.lead-note {
  flex: 0 0 auto; margin: 0;
  padding: 8px max(12px, var(--safe-l)) calc(8px + var(--safe-b));
  border-top: 1px solid var(--line);
  background: var(--surface);
  color: var(--text-3); font-size: 12px;
}
.lead-note .path { font-family: var(--mono); font-size: 11px; word-break: break-all; }

/* The fleet controls. They are header buttons, so they wear the header's
   restraint: labels collapse to icons on a phone the way the others do, and
   stop-all borrows the danger colour the per-target stop already uses rather
   than inventing a louder one. */
.fleet { flex: 0 0 auto; display: flex; align-items: center; gap: 2px; }
.fleet .btn.ghost.on {
  color: var(--text); background: var(--accent-dim);
  border-color: var(--accent-line);
}

.ledger-doc {
  /* min-height:0 is what makes the overflow scroll rather than clip. Without it
     a flex or grid item keeps its content's intrinsic height, the pane grows
     past the viewport, and the tail of a long write-up is unreachable — which
     is exactly what a submission is: long. */
  flex: 1 1 auto; min-width: 0; min-height: 0;
  overflow-y: auto; overscroll-behavior: contain;
  padding: 18px max(14px, var(--safe-r)) calc(40px + var(--safe-b)) max(14px, var(--safe-l));
}
.ledger-doc h1 { margin: 0 0 8px; font-size: 18px; font-weight: 650; line-height: 1.35; letter-spacing: -.01em; }
.ledger-doc h2 { margin: 24px 0 8px; font-size: 14px; font-weight: 600; }
.ledger-doc h3 { margin: 18px 0 6px; font-size: 12.5px; font-weight: 600; color: var(--text-2); }
.ledger-doc p, .ledger-doc li { margin: 0 0 9px; }
.ledger-doc ul, .ledger-doc ol { margin: 0 0 12px; padding-left: 20px; }
.ledger-doc strong { color: #fff; font-weight: 600; }
.ledger-doc code {
  font-size: 12px;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: 4px; padding: 1px 5px;
  word-break: break-word;
}
.ledger-doc pre {
  margin: 0 0 14px; padding: 12px;
  font: 12px/1.6 var(--mono);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
  overflow-x: auto; overscroll-behavior-x: contain;
}
.ledger-doc pre code { background: none; border: 0; padding: 0; font-size: inherit; word-break: normal; }
.ledger-doc .meta {
  margin-bottom: 18px; padding-bottom: 14px;
  border-bottom: 1px solid var(--line);
  color: var(--text-3); font-size: 12px;
}
.ledger-doc .meta .path { font-family: var(--mono); font-size: 11px; word-break: break-all; }
/* --- scope -------------------------------------------------------------- */

.scope {
  flex: 1 1 auto;
  overflow-y: auto; overscroll-behavior: contain;
  padding: 18px max(14px, var(--safe-r)) calc(40px + var(--safe-b)) max(14px, var(--safe-l));
  max-width: 860px;
}
.scope .mode { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin-bottom: 6px; }
.scope h2 { margin: 0; font-size: 16px; font-weight: 650; letter-spacing: -.01em; }
.scope .why { margin: 0 0 20px; color: var(--text-2); line-height: 1.6; }
.scope .why strong { color: var(--text); }
.scope h3 {
  margin: 22px 0 8px;
  font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-3);
}
.scope ul { list-style: none; margin: 0; padding: 0; }
.scope li {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  margin-bottom: 5px; padding: 9px 11px;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-sm);
}
.scope li .asset { font-family: var(--mono); font-size: 12.5px; word-break: break-all; }
.scope li .covers { margin-left: auto; color: var(--text-3); font-size: 12px; text-align: right; }
.scope li.out .asset { color: var(--red); }

.mode-tag {
  padding: 2px 9px; border-radius: 999px;
  border: 1px solid var(--line-2); color: var(--text-3); font-size: 11px;
}
.mode-tag.exact { color: var(--text-2); }
.mode-tag.estate { color: var(--text); border-color: var(--accent-line); }

/* --- coverage ----------------------------------------------------------- */

/* Coverage is a grid of counts and a list of what is missing. The counts are
   large because they are read from across the room at 3am; the gaps are the
   half that is actually actionable, so they get their own heading rather than a
   footnote. */
.cover {
  flex: 1 1 auto;
  overflow-y: auto; overscroll-behavior: contain;
  padding: 18px max(14px, var(--safe-r)) calc(40px + var(--safe-b)) max(14px, var(--safe-l));
  max-width: 940px;
}
.cover-head { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin-bottom: 6px; }
.cover-head h2 { margin: 0; font-size: 16px; font-weight: 650; letter-spacing: -.01em; }
.cover .why { margin: 0 0 18px; color: var(--text-2); line-height: 1.6; }
.cover .why code {
  font-family: var(--mono); font-size: 11.5px;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: 4px; padding: 1px 5px;
}
.cover h3 {
  margin: 24px 0 8px;
  font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-3);
}

.apex-coverage { margin: 0 0 22px; }
.apex-coverage-head {
  display: flex; align-items: end; justify-content: space-between; gap: 12px; margin-bottom: 8px;
}
.apex-coverage-head h3 { margin: 0 0 4px; }
.apex-coverage-head p { margin: 0; color: var(--text-3); font-size: 11.5px; line-height: 1.45; }
.apex-coverage-head input {
  flex: 0 1 250px; min-width: 170px; min-height: 36px; padding: 7px 10px;
  color: var(--text); background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-sm);
  font: 12px var(--mono);
}
.apex-coverage-table {
  max-height: 460px; overflow: auto; border: 1px solid var(--line); border-radius: var(--r-sm);
}
.apex-coverage-table table { width: 100%; border-collapse: collapse; font: 11.5px var(--mono); }
.apex-coverage-table th, .apex-coverage-table td {
  padding: 8px 9px; text-align: right; white-space: nowrap; border-bottom: 1px solid var(--line);
}
.apex-coverage-table th {
  position: sticky; top: 0; z-index: 1; color: var(--text-3); background: var(--surface-2); font-weight: 500;
}
.apex-coverage-table th:first-child, .apex-coverage-table td:first-child { text-align: left; }
.apex-coverage-table td strong { color: var(--text); font-weight: 500; }
.apex-coverage-table td small { display: block; margin-top: 2px; color: var(--text-3); font-size: 9.5px; }
.apex-coverage-table td.gap { color: var(--amber); }
.apex-coverage-table tr:last-child td { border-bottom: 0; }

.tiles {
  display: grid; gap: 8px;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
.tile {
  display: flex; flex-direction: column; gap: 3px;
  padding: 12px 13px;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-sm);
}
.tile .v { font-size: 21px; font-weight: 600; letter-spacing: -.02em; line-height: 1.15; }
.tile .v small { font-size: 13px; font-weight: 400; color: var(--text-3); letter-spacing: 0; }
.tile .k { font-size: 12px; color: var(--text-2); }
.tile .n { font-size: 11px; color: var(--text-3); line-height: 1.45; }

.gaps { list-style: none; margin: 0; padding: 0; }
.gaps li {
  padding: 10px 12px 10px 26px;
  margin-bottom: 5px;
  position: relative;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-sm);
  color: var(--text-2); line-height: 1.5;
}
.gaps li::before {
  content: ""; position: absolute; left: 12px; top: 17px;
  width: 5px; height: 5px; border-radius: 50%; background: var(--amber);
}
.cover .foot { margin: 22px 0 0; color: var(--text-3); font-size: 11.5px; line-height: 1.6; }

.host-evidence-controls {
  display: grid; grid-template-columns: minmax(220px, 2fr) minmax(180px, 1fr); gap: 8px;
  margin-bottom: 8px;
}
.host-evidence-controls label {
  display: flex; flex-direction: column; gap: 5px;
  color: var(--text-3); font-size: 10px; letter-spacing: .06em; text-transform: uppercase;
}
.host-evidence-controls select {
  width: 100%; min-height: 38px; padding: 7px 9px;
  color: var(--text); background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-sm);
  font: 12px var(--mono); text-transform: none; letter-spacing: 0;
}
.host-evidence-empty, .host-evidence-count {
  padding: 11px 12px; color: var(--text-3); background: var(--surface-2);
  border: 1px solid var(--line); border-radius: var(--r-sm); font-size: 11.5px;
}
.host-evidence-count { border-radius: var(--r-sm) var(--r-sm) 0 0; border-bottom: 0; }
.host-evidence-table { overflow-x: auto; border: 1px solid var(--line); border-radius: 0 0 var(--r-sm) var(--r-sm); }
.host-evidence-table table { width: 100%; border-collapse: collapse; font: 11.5px var(--mono); }
.host-evidence-table th, .host-evidence-table td {
  padding: 8px 10px; text-align: left; white-space: nowrap; border-bottom: 1px solid var(--line);
}
.host-evidence-table th { color: var(--text-3); font-weight: 500; background: var(--surface-2); }
.host-evidence-table tr:last-child td { border-bottom: 0; }
.host-evidence-table .evidence-state.tested { color: var(--green); }
.host-evidence-table .evidence-state.partial,
.host-evidence-table .evidence-state.untested,
.host-evidence-table .evidence-state.unindexed { color: var(--amber); }
.host-evidence-table .evidence-state.grouped { color: var(--text-2); }
.host-evidence-pages { display: flex; justify-content: flex-end; gap: 7px; margin-top: 8px; }
.host-evidence-pages .btn { min-height: 34px; padding: 6px 12px; }

@media (max-width: 620px) {
  .apex-coverage-head { align-items: stretch; flex-direction: column; }
  .apex-coverage-head input { flex-basis: auto; width: 100%; }
  .host-evidence-controls { grid-template-columns: 1fr; }
}
/* --- modal -------------------------------------------------------------- */

/* Deleting an engagement is the one action here with no undo, so it gets a
   dialog with the name typed back rather than a confirm() a thumb can dismiss
   by accident. */
.modal {
  position: fixed; inset: 0; z-index: 50;
  display: flex; align-items: flex-end; justify-content: center;
  padding: 0;
  background: rgba(5, 5, 7, .66);
}
.modal-box {
  width: 100%; max-width: 460px;
  padding: 20px max(18px, var(--safe-l)) calc(20px + var(--safe-b)) max(18px, var(--safe-r));
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  box-shadow: 0 -20px 60px rgba(0, 0, 0, .6);
  animation: sheet .22s cubic-bezier(.4, 0, .2, 1) both;
}
@keyframes sheet { from { transform: translateY(14px); opacity: 0; } }
.modal-box h2 { margin: 0 0 10px; font-size: 16px; font-weight: 650; letter-spacing: -.01em; }
.modal-box p { margin: 0 0 12px; color: var(--text-2); font-size: 13px; line-height: 1.55; }
.modal-box p .path { font-family: var(--mono); font-size: 11.5px; color: var(--text-3); word-break: break-all; }
.modal-box b { color: var(--text); font-weight: 600; }
.modal-box .warn { color: var(--amber); }
.modal-actions { display: flex; gap: 8px; margin-top: 16px; }
.modal-actions .btn { flex: 1 1 0; min-height: 42px; }
.workers-box { max-width: 560px; }
.worker-seats {
  display: grid; gap: 7px; margin: 4px 0 16px;
}
.worker-seat {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 11px;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-sm);
}
.worker-seat > span { min-width: 0; }
.worker-seat b { display: block; font-size: 13px; }
.worker-seat small { display: block; margin-top: 2px; color: var(--text-3); font-size: 11px; line-height: 1.35; }
.worker-seat .btn { flex: 0 0 auto; min-width: 82px; }
.worker-seat .btn.primary { color: var(--green); }
#worker-route-form { display: grid; gap: 9px; }

/* A proof image, under the write-up it belongs to. Tapping opens it full size:
   on a phone the inline copy is a thumbnail of a 1440px capture, and the detail
   that makes it evidence — the account menu, the response body — is only
   legible at full size. */
.ledger-doc .shot { margin: 18px 0 0; }
.ledger-doc .shot img {
  display: block; width: 100%; height: auto;
  background: var(--surface-2);
  border: 1px solid var(--line); border-radius: var(--r-sm);
}
.ledger-doc .shot figcaption {
  margin-top: 6px;
  font-family: var(--mono); font-size: 11.5px; color: var(--text-3);
}

/* --- toast -------------------------------------------------------------- */

#toast {
  position: fixed; z-index: 60;
  left: max(12px, var(--safe-l)); right: max(12px, var(--safe-r));
  bottom: calc(12px + var(--safe-b));
  display: flex; flex-direction: column-reverse; gap: 8px;
  pointer-events: none;
}
.toast {
  pointer-events: auto;
  padding: 11px 14px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-left: 2px solid var(--text-3);
  border-radius: var(--r-sm);
  box-shadow: 0 10px 30px rgba(0, 0, 0, .5);
  font-size: 13px;
  animation: rise .2s ease both;
}
@keyframes rise { from { opacity: 0; transform: translateY(8px); } }
.toast.bad { border-left-color: var(--red); }
.toast.good { border-left-color: var(--text); }
/* --- login -------------------------------------------------------------- */

body.login {
  display: flex; align-items: center; justify-content: center;
  min-height: 100vh; min-height: 100dvh;
  padding: 24px max(20px, var(--safe-r)) calc(24px + var(--safe-b)) max(20px, var(--safe-l));
}
body.login::before {
  content: ""; position: fixed; inset: 0; pointer-events: none;
  background: radial-gradient(60vw 40vh at 50% 0%, rgba(255, 255, 255, .035), transparent 70%);
}
.gate {
  position: relative;
  width: min(360px, 100%);
  padding: 26px 22px 22px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: 0 24px 60px rgba(0, 0, 0, .5);
}
.gate .brand { display: block; font-size: 17px; margin-bottom: 16px; }
.gate input { margin-bottom: 10px; }
.gate .btn { min-height: 42px; }
.gate .err { min-height: 1.3em; margin-top: 12px; color: var(--red); font-size: 12.5px; }

/* --- wide --------------------------------------------------------------- */

@media (min-width: 900px) {
  :root { --tap: 34px; }

  body { font-size: 14px; }

  input[type="text"], input[type="password"], input[type="search"], input:not([type]), select, textarea {
    font-size: 13px;
  }

  .nav-toggle { display: none; }

  aside {
    position: static;
    width: 336px; flex: 0 0 336px;
    top: auto;
    padding: 14px;
    transform: none;
    transition: none;
    box-shadow: none;
  }
  .scrim { display: none; }

  .summary .path { display: inline; }
  .avail { font-size: 11.5px; }

  .toolbar { padding: 9px 14px; gap: 9px; }
  .tb-actions .lbl { display: inline; }
  .tb-actions .btn { min-height: var(--tap); padding: 0 12px; }
  .split select { min-height: var(--tap); font-size: 12.5px; padding: 0 21px 0 9px; }
  .tb-id .state .pid { display: inline; }
  .tb-opts select { max-width: 260px; }

  .out { padding: 12px 16px; font-size: 12.5px; }

  /* Wide enough for both halves: the ledger stays on screen while a write-up is
     read beside it, which is how one gets compared to the next. */
  .ledger {
    display: grid;
    grid-template-columns: minmax(280px, 34%) 1fr;
    grid-template-rows: minmax(0, 1fr);
  }
  .ledger-list { border-right: 1px solid var(--line); background: var(--surface); min-height: 0; }
  .ledger-pane { display: flex; min-height: 0; }
  .ledger.reading .ledger-list { display: block; }
  .doc-bar { padding: 7px 14px; }

  /* Both halves at once: the library stays on screen while a document is
     edited, so the next one is a click away rather than a click back. */
  .lib {
    display: grid;
    grid-template-columns: minmax(280px, 34%) 1fr;
    grid-template-rows: minmax(0, 1fr);
  }
  .lib-list { border-right: 1px solid var(--line); background: var(--surface); min-height: 0; }
  .lib-pane { display: flex; min-height: 0; }
  .lib.editing .lib-list { display: block; }
  .lib-row { padding: 11px 14px; }
  .lib-edit { padding: 16px 20px; font-size: 13px; }
  .lib-note, .lib-bar { padding-left: 20px; padding-right: 20px; }
  .only-narrow { display: none; }
  .head-btn .lbl { display: inline; }
  .sheet-head { padding: 12px 20px 11px; }
  .lib-break { display: none; }
  .lib-where { display: block; }
  .finding { padding: 12px 14px; }
  .ledger-doc { padding: 24px 28px 60px; max-width: 860px; }

  .scope { padding: 24px 28px 60px; }
  .cover { padding: 24px 28px 60px; }

  .steer { padding: 9px 14px; gap: 8px; }
  .steer .lbl { display: inline; }
  .steer .btn { padding: 0 12px; }
  .steer select { max-width: 200px; }
  .steer-note { padding: 0 14px 9px; }

  .modal { align-items: center; padding: 24px; }
  .modal-box { border-radius: var(--r-lg); padding: 22px; }

  .hunt-modal { align-items: center; padding: 24px; }
  .hunt-box {
    width: min(900px, 100%); height: min(780px, calc(100vh - 48px));
    border: 1px solid var(--line); border-radius: var(--r-lg);
    box-shadow: 0 24px 80px rgba(0, 0, 0, .7); overflow: hidden;
  }
  .hunt-head { padding: 16px 20px 13px; }
  .hunt-body { padding: 24px 38px 36px; }
  .hunt-actions { padding: 11px 20px; }
  .choice-grid, .hunt-two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .review { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .review-card.wide, .review-warning { grid-column: 1 / -1; }

  #toast { left: auto; right: 16px; bottom: 16px; max-width: 420px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
