:root {
  --bg: #0f1115;
  --panel: #171a21;
  --panel-2: #1e222b;
  --line: #2a2f3a;
  --text: #e6e8ed;
  --muted: #8b93a3;
  --accent: #6ea8fe;
  --green: #4ade80;
  --amber: #f5c451;
  --red: #f08a8a;
  font-synthesis: none;
}
* { box-sizing: border-box; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 14px/1.5 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}
.muted { color: var(--muted); }
.hidden { display: none !important; }

.topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 20px; border-bottom: 1px solid var(--line); background: var(--panel);
}
.brand { font-weight: 700; letter-spacing: .2px; }
.brand .dot { margin: 0 6px; color: var(--muted); }
.brand .muted { font-weight: 400; }
.scope { display: flex; align-items: center; gap: 18px; }
.field { color: var(--muted); display: flex; align-items: center; gap: 6px; }
select {
  background: var(--panel-2); color: var(--text); border: 1px solid var(--line);
  border-radius: 8px; padding: 6px 10px; font: inherit;
}
.role strong { color: var(--text); }
.conn { color: var(--muted); font-size: 12px; }
.conn.live { color: #4ade80; }

.tabs { display: flex; gap: 6px; padding: 12px 20px 0; border-bottom: 1px solid var(--line); background: var(--panel); }
.tabs button {
  background: none; border: none; color: var(--muted); font: inherit; cursor: pointer;
  padding: 8px 14px; border-radius: 8px 8px 0 0; border-bottom: 2px solid transparent;
}
.tabs button.active { color: var(--text); border-bottom-color: var(--accent); }
.badge { background: var(--accent); color: #0b1020; border-radius: 999px; padding: 0 7px; font-size: 11px; font-weight: 700; }

main { padding: 22px; max-width: 980px; margin: 0 auto; }
h2 { margin: 0 0 14px; font-size: 18px; }

.card {
  background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
  padding: 16px; margin-bottom: 12px;
}
.card.click { cursor: pointer; }
.card.click:hover { border-color: var(--accent); }
.row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.title { font-weight: 600; }

.pill { font-size: 12px; padding: 2px 9px; border-radius: 999px; border: 1px solid var(--line); color: var(--muted); }
.pill.running { color: var(--accent); border-color: var(--accent); }
.pill.awaiting_human { color: var(--amber); border-color: var(--amber); }
.pill.completed { color: #4ade80; border-color: #2f7d4f; }
.pill.archived { color: var(--muted); border-style: dashed; }
.pill.failed { color: var(--red); border-color: var(--red); }
.failure { margin-top: 6px; font-size: 13px; }
.failure b { color: var(--red); }
.failure .reason { color: var(--muted); margin-top: 2px; white-space: pre-wrap; overflow-wrap: anywhere; }
.board .failure .reason { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }

.consequences { margin-top: 12px; font-size: 13px; }
.consequence { margin-top: 4px; }
.consequence b { color: var(--accent); font-weight: 600; }

/* The thing-type tag: every work item names what kind of thing it is. */
.eyebrow {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .8px;
  color: var(--accent); margin-bottom: 4px;
}
.lead { margin-top: 8px; }
.smallprint { font-size: 12px; margin-top: 12px; }
.linklike { color: var(--accent); cursor: pointer; }
.enginehead { font-size: 12px; text-transform: uppercase; letter-spacing: .6px; margin: 20px 0 8px; }

.artifact { margin-top: 12px; }
.artifact-body {
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 8px;
  padding: 12px; margin: 4px 0 0; font: inherit; white-space: pre-wrap; max-height: 320px; overflow-y: auto;
}
/* The primary artifact (the thing under review) dominates; the rest demote. */
.artifact.primary .artifact-body { border-color: #3d4a63; }
.artifact.secondary .alabel { font-size: 11px; }
.artifact.secondary .artifact-body { font-size: 12px; max-height: 140px; color: var(--muted); padding: 8px 10px; }

/* Journey bar: the whole lifecycle in one strip — ✓ done, ● current, ○ ahead. */
.journey { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; margin-top: 12px; }
.jstep {
  font-size: 12px; padding: 3px 9px; border-radius: 7px;
  background: var(--panel-2); border: 1px solid var(--line); color: var(--muted);
}
.jstep .jicon { margin-right: 3px; }
.jstep.done { color: var(--text); }
.jstep.done .jicon { color: var(--green); }
.jstep.current { color: var(--amber); border-color: var(--amber); font-weight: 600; }
.jstep.current .waiting { font-weight: 400; }
.jstep.stub { opacity: .55; border-style: dashed; }
.jstep .xn { color: var(--amber); font-weight: 700; }
.jstep .loopmark { color: var(--muted); }
.jsep { color: var(--muted); font-size: 11px; }
/* Compact variant for board cards: dots + "3/7 · Your review". */
.jmini { display: flex; align-items: center; gap: 3px; margin-top: 8px; font-size: 12px; }
.jmini .muted { margin-left: 5px; }
.jdot { width: 7px; height: 7px; border-radius: 50%; background: var(--line); display: inline-block; flex: none; }
.jdot.done { background: var(--green); }
.jdot.current { background: var(--amber); }

.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 12px; }
.board { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-top: 20px; align-items: start; }
.board .col { background: rgba(255,255,255,.02); border: 1px dashed var(--line); border-radius: 12px; padding: 10px; }
.colhead { font-size: 12px; text-transform: uppercase; letter-spacing: .6px; margin: 2px 4px 10px; }
.board .card { margin-bottom: 10px; }
.board .empty { padding: 10px; }
.link { color: var(--accent); cursor: pointer; }
h2 .chip { vertical-align: middle; font-weight: 400; }
@media (max-width: 760px) { .board { grid-template-columns: 1fr; } }

.trace { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.chip { font-size: 12px; padding: 3px 9px; border-radius: 7px; background: var(--panel-2); border: 1px solid var(--line); color: var(--muted); }
.chip.resolved { color: var(--text); }
.chip.active { color: var(--accent); border-color: var(--accent); }
.chip.parked { color: var(--amber); border-color: var(--amber); }
.chip.failed { color: var(--red); border-color: var(--red); }
.chip .out { color: var(--muted); }

.btn {
  background: var(--accent); color: #0b1020; border: none; border-radius: 8px;
  padding: 8px 14px; font: inherit; font-weight: 600; cursor: pointer;
}
.btn.ghost { background: var(--panel-2); color: var(--text); border: 1px solid var(--line); }
.btn + .btn { margin-left: 8px; }
.btn.mini { font-size: 11px; font-weight: 400; padding: 2px 8px; color: var(--muted); }
.btn.mini:hover { color: var(--text); }
.cardtools { margin-top: 8px; text-align: right; }
.archrow { margin: 8px 0 12px; font-size: 13px; }
.archtoggle { margin-top: 14px; font-size: 13px; }
.archboard { grid-template-columns: 1fr; margin-top: 10px; }
.archboard .card { opacity: .75; }
/* The decision row. Both outcomes get the SAME weight: at a human review gate the
   interface must not tell the operator which way to go, and a filled "approve" beside
   a ghost "request changes" does exactly that. What each one causes is spelled out
   above (.consequences), which is where the guidance belongs. */
.actions { margin-top: 6px; display: flex; flex-wrap: wrap; gap: 8px; }
.actions .btn + .btn { margin-left: 0; }
.actions .decide { padding: 9px 16px; }
/* Equal weight is not the same as low weight: the row is named, so the most
   consequential act on the card is still the one the eye finds last and lands on. */
.decidelabel { margin-top: 16px; }

input[type=text], textarea.notes {
  width: 100%; background: var(--panel-2); color: var(--text); border: 1px solid var(--line);
  border-radius: 8px; padding: 10px 12px; font: inherit; margin: 8px 0 14px;
}
textarea.notes { margin: 12px 0 0; resize: vertical; }
/* The notes box carries the operator's own words (and any note distilled from a
   conversation), so it is LABELLED rather than explained by a placeholder that
   disappears the moment there is text in it. */
.notelabel { margin-top: 16px; font-size: 13px; }
.notelabel + textarea.notes { margin-top: 6px; }
label.block { color: var(--muted); display: block; }

/* Author view forms (RFC-0009 stage 9). Reuse the input styling; a charter is a
   multi-line brief, and the handler row pairs a kind selector with a ref input. */
textarea.charter {
  width: 100%; background: var(--panel-2); color: var(--text); border: 1px solid var(--line);
  border-radius: 8px; padding: 10px 12px; font: inherit; margin: 8px 0 14px; resize: vertical;
}
/* "Help me write this" assist block (RFC-0015): a lightly-set-off group above the
   manual fields — the manual fields stay fully usable without it, which is the
   fallback for every one of its failure states. */
.assist { border-left: 2px solid var(--line); padding: 2px 0 6px 12px; margin: 0 0 14px; }
.assist textarea.charter { margin-bottom: 8px; }
/* What a routed ("describe a change") draft understood, and the way out when it
   understood wrong. Accent-edged because it is the assist's own claim, not the
   operator's text, and it is the thing to read before trusting the fields below. */
.reading { border-left: 2px solid var(--accent); padding: 2px 0 2px 10px; margin: 8px 0 2px; font-size: 13px; }
.reading b { color: var(--accent); font-weight: 600; }
.reading .sub { font-size: 12px; margin-top: 4px; }
/* A field the assist wrote over text the operator had already put there. Never
   silent: the mark stays until they edit it themselves, the previous value is in the
   title, and "Undo the draft" puts the whole form back. */
.overwritten { border-color: var(--amber) !important; }
#stepForm select, #editFlow { width: 100%; margin: 8px 0 14px; }
.formrow { display: flex; gap: 8px; margin: 8px 0 14px; align-items: center; }
.formrow select { flex: none; margin: 0; }
.formrow input[type=text] { margin: 0; }

/* Author flow diagrams: reuse the journey-bar visual (.journey/.jstep/.jsep) to
   show a flow's shape now and with a step added. The well sits on --bg so the
   panel-2 nodes read as distinct chips; `hi` lights a chosen segment endpoint,
   `ins` is the newly inserted step (filled, distinct from everything present). */
.authorflow { background: var(--bg); border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px; margin: 4px 0 14px; }
.authorflow .journey { margin-top: 6px; }
.flabel { font-size: 11px; text-transform: uppercase; letter-spacing: .6px; }
.jstep.author { color: var(--text); }
.jstep.author.hi { border-color: var(--accent); color: var(--accent); }
.jstep.author.ins { background: var(--accent); color: #0b1020; border-color: var(--accent); font-weight: 700; }
.branchnote { margin-top: 10px; font-size: 12px; }
.branchpick { margin: 2px 0 10px; }
.branchpick b, .branchnote b { color: var(--accent); font-weight: 600; }
#stepForm select.inline { width: auto; margin: 0 2px; padding: 3px 8px; }

/* ---- Properties view (RFC-0009 stage 2): the rubric, seen and edited --------
   Reuses the existing vocabulary — .card, .journey/.jstep for the scope chain,
   .chip-shaped tags, .gate for the "goes to your Inbox first" note — so the
   screen reads as part of the same product rather than a new one. */

/* A config problem the operator must not miss: a set that will not load, a cap
   overflow, a binding naming nothing. Red-edged, never a footnote. */
.card.problem { border-color: var(--red); background: rgba(240,138,138,.06); }
.card.problem b { color: var(--red); }

/* Severity is the single most consequential thing about a property, so the two
   values never look alike: `reject` sends work back (red, filled edge),
   `advise` is a quiet note (muted, dashed). */
.sev {
  font-size: 11px; padding: 1px 8px; border-radius: 999px; white-space: nowrap;
  border: 1px solid var(--red); color: var(--red); background: rgba(240,138,138,.08);
}
.sev.advise { border-color: var(--line); border-style: dashed; color: var(--muted); background: none; }

/* Provenance, inline and small: "from you" / "from this product". The full
   sentence (and where the binding lives) rides the title attribute. */
.scopechip {
  font-size: 11px; padding: 1px 8px; border-radius: 999px; white-space: nowrap;
  border: 1px solid var(--line); color: var(--muted); cursor: help;
}

/* The accumulation strip: tenant first, each later scope adding to it. Joined
   with "+" rather than the journey bar's "›" because this is a sum, not a path. */
.chainstrip { margin: 6px 0 8px; }
.chainstrip .jsep { color: var(--muted); font-weight: 700; }

.setcard .eyebrow { display: inline; margin: 0; }
.setcard.dim { opacity: .8; border-style: dashed; }
.setintent { margin: 8px 0 4px; color: var(--text); }
.proplist { margin-top: 10px; }

/* One property: a scannable line that opens to the rule text itself
   (progressive disclosure — the rubric summarised, details on demand). */
details.prop { border: 1px solid var(--line); border-radius: 8px; background: var(--panel-2); margin-bottom: 6px; }
details.prop > summary {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 12px; cursor: pointer; list-style: none;
}
details.prop > summary::-webkit-details-marker { display: none; }
/* A CSS triangle rather than a glyph: no font can substitute it away. */
details.prop > summary::before {
  content: ""; display: inline-block; flex: none; margin-right: 4px;
  border-left: 5px solid var(--muted); border-top: 4px solid transparent; border-bottom: 4px solid transparent;
  transition: transform .12s ease;
}
details.prop[open] > summary::before { transform: rotate(90deg); border-left-color: var(--accent); }
details.prop[open] > summary { border-bottom: 1px solid var(--line); }
.prophead { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; flex: 1; }
.proptitle { font-weight: 600; }
.propdetail { padding: 10px 12px 12px; }
.propbody { white-space: pre-wrap; }
/* Examples: the bad/good pair is what stops arguments about a property, so it is
   shown as a labelled pair rather than buried in the prose. */
.exline { margin-top: 8px; font-size: 13px; border-left: 2px solid var(--line); padding-left: 10px; }
.exline.bad { border-left-color: var(--red); }
.exline.good { border-left-color: var(--green); }
.exlabel {
  display: inline-block; min-width: 62px; margin-right: 8px; font-size: 10px;
  text-transform: uppercase; letter-spacing: .6px; color: var(--muted);
}
/* The inline editor opens where the property is, so an amendment reads as
   editing this property rather than filling in a form about it. */
.propform { border-top: 1px dashed var(--line); margin-top: 12px; padding-top: 12px; }
.propform select { width: 100%; margin: 8px 0 14px; }
.editslot:empty, .addslot:empty { display: none; }
.addslot .propform { border-top: none; }
details.newset > summary { cursor: pointer; list-style: none; }
details.newset > summary::-webkit-details-marker { display: none; }
details.newset > summary .title::before { content: "+ "; color: var(--accent); }
@media (prefers-reduced-motion: reduce) { details.prop > summary::before { transition: none; } }
.newsetbody { margin-top: 14px; border-top: 1px solid var(--line); padding-top: 12px; }

/* ---- how the work was judged (RFC-0009 §7) ---------------------------------
   The judge's per-property verdicts, as a list a human reads rather than the JSON a
   machine emits. Failures first, each with the offending text quoted. */
.artifact.findings { margin-top: 12px; }
.findinglist { border: 1px solid var(--line); border-radius: 8px; background: var(--panel-2); margin-top: 4px; overflow: hidden; }
.finding { display: flex; gap: 10px; padding: 8px 12px; border-top: 1px solid var(--line); }
.finding:first-child { border-top: none; }
.finding.fail { background: rgba(240,138,138,.05); }
.finding .ficon { flex: none; font-weight: 700; }
.finding.fail .ficon { color: var(--red); }
.finding.pass .ficon { color: var(--green); }
/* A stale finding (RFC-0017) was true of an EARLIER version of this work and cannot be
   re-checked against the one on screen. It is never dropped and never dressed up as
   live: dimmed, struck through, its own quiet icon, and no red anywhere — red means
   "this is wrong now", which is exactly what a stale finding does not mean. */
.finding.stale { opacity: .62; }
.finding.stale .ficon { color: var(--muted); }
.finding.stale .ftitle { font-weight: 400; text-decoration: line-through; }
.finding.stale .fevidence { border-left-color: var(--line); color: var(--muted); text-decoration: line-through; }
.sev.stale { border-color: var(--line); border-style: dashed; color: var(--muted); background: none; }
/* Which version was checked, and who has rewritten it since. */
.fprovenance { margin: 6px 0 0; }
.fbody { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ftitle { font-weight: 600; }
.finding.pass .ftitle { font-weight: 400; color: var(--muted); }
.fid { font-size: 11px; }
/* The evidence: the model's own quote from the draft, so "it broke this one"
   is checkable rather than asserted. */
.fevidence {
  flex-basis: 100%; margin-top: 2px; padding: 6px 10px; border-left: 2px solid var(--red);
  background: rgba(0,0,0,.2); font: 13px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
  white-space: pre-wrap;
}

/* The two-step gate note: prominent, plain-language "goes to your Inbox first". */
.gate { background: rgba(110,168,254,.08); border: 1px solid #33507e; border-radius: 8px; padding: 9px 12px; margin: 12px 0; font-size: 13px; }
.gate b { color: var(--accent); font-weight: 600; }
.gate .sub { color: var(--muted); font-size: 12px; margin-top: 3px; }

.log { background: #0b0d12; border: 1px solid var(--line); border-radius: 10px; padding: 12px; margin-top: 14px;
  font: 12px/1.6 ui-monospace, SFMono-Regular, Menlo, monospace; max-height: 320px; overflow: auto; }
.log .ln { white-space: pre-wrap; }
.log .actor { color: var(--accent); }
.log .ts { color: var(--muted); }
.empty { color: var(--muted); padding: 30px; text-align: center; }
.loading { color: var(--muted); padding: 30px; text-align: center; }
.loading::after {
  content: ""; display: inline-block; width: 12px; height: 12px; margin-left: 8px;
  vertical-align: -1px; border: 2px solid var(--line); border-top-color: var(--accent);
  border-radius: 50%; animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .loading::after { animation: none; } }
.back { color: var(--accent); cursor: pointer; margin-bottom: 12px; display: inline-block; }

/* ---- Talk it through (RFC-0016) --------------------------------------------
   The review card's conversation. It sits INLINE between what is being reviewed
   and the notes box it feeds, collapsed until asked for, because the draft and the
   findings are what the conversation is about and must stay on screen. Reuses the
   assist block (.assist) for its input row, so the message line, the undo and the
   button styling are the ones the operator already knows from the authoring
   surfaces. */
details.talk { border: 1px solid var(--line); border-radius: 10px; background: var(--panel-2); margin-top: 14px; }
details.talk > summary {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  padding: 9px 12px; cursor: pointer; list-style: none;
}
details.talk > summary::-webkit-details-marker { display: none; }
details.talk > summary::before {
  content: ""; display: inline-block; flex: none; align-self: center;
  border-left: 5px solid var(--muted); border-top: 4px solid transparent; border-bottom: 4px solid transparent;
  transition: transform .12s ease;
}
details.talk[open] > summary::before { transform: rotate(90deg); border-left-color: var(--accent); }
details.talk[open] > summary { border-bottom: 1px solid var(--line); }
@media (prefers-reduced-motion: reduce) { details.talk > summary::before { transition: none; } }
.talkhead { font-weight: 600; }
.talkbody { padding: 12px; }
.talkbody .assist { margin: 12px 0 0; }

/* What the companion can see, from the engine's own digest — the answer to "is this
   a black box?", stated before the first turn rather than on request. */
.talkctx { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; }
.ctxchip {
  font-size: 11px; padding: 1px 8px; border-radius: 999px; white-space: nowrap;
  border: 1px solid var(--line); color: var(--muted); background: var(--bg);
}

/* The transcript. The operator's own turns are edge-marked and slightly inset, so a
   long exchange still reads as a conversation and not as one block of prose.
   It scrolls WITHIN a bound, like the draft above it (.artifact-body) and the engine
   log: an unbounded transcript pushes the work under review off the top of the screen
   and the decision buttons off the bottom, which is the one thing this panel must
   never do. */
.turns { display: flex; flex-direction: column; gap: 10px; max-height: 46vh; overflow-y: auto; }
.turns:not(:empty) { padding-right: 4px; }
.turn .who { margin-bottom: 2px; }
.turn .said { white-space: pre-wrap; }
.turn.you { border-left: 2px solid var(--accent); padding-left: 10px; }
.turn.you .who { color: var(--accent); }
.turn.agent { border-left: 2px solid var(--line); padding-left: 10px; }

.talkbusy { color: var(--muted); font-size: 13px; margin-top: 10px; }
.talkbusy::after {
  content: ""; display: inline-block; width: 10px; height: 10px; margin-left: 8px;
  vertical-align: -1px; border: 2px solid var(--line); border-top-color: var(--accent);
  border-radius: 50%; animation: spin .7s linear infinite;
}
@media (prefers-reduced-motion: reduce) { .talkbusy::after { animation: none; } }
/* A failure is never a dead end: the message says what happened, the way out sits
   next to it, and the notes box below always works. Three different pieces of news
   are not dressed alike — a capability that is not configured, or a review already
   decided, is a plain statement (muted); an attempt that failed is red and offers to
   try again. */
.talkproblem { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; color: var(--muted); font-size: 13px; margin-top: 10px; }
.talkproblem.error { color: var(--red); }

/* The other thing a review can conclude: the RULE is wrong, not the work. Offered as
   its own block (never as a verdict on the work) with one way to act on it. */
.ruleoffer { border-left: 2px solid var(--amber); padding: 2px 0 2px 10px; margin-top: 12px; font-size: 13px; }
.ruleoffer b { color: var(--amber); font-weight: 600; }
.famendrow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 6px; }
.finding .famendrow { flex-basis: 100%; }

/* The input row wraps rather than squeezing the buttons on a narrow window, and the
   panel's own margins never collide (.btn + .btn's left margin is the gap here). */
.talkrow { flex-wrap: wrap; gap: 6px 10px; margin-top: 2px; }
/* `auto` rather than space-between, so a long message wraps and the buttons still
   sit at the right-hand end of the row instead of jumping under it. */
.talkbtns { white-space: nowrap; margin-left: auto; }
/* What this surface will not do, and where what you say goes. A footnote by design:
   read once, then out of the way. */
.talkfoot { border-top: 1px dashed var(--line); margin-top: 14px; padding-top: 8px; }
/* The distilled note has just been written into the operator's own field: mark it
   once, briefly, so the eye lands where the words appeared. */
textarea.notes.flash { border-color: var(--accent); }

/* ---- Inbox: the item on its own screen (RFC-0022 §3a) --------------------------
   One narrow rail, one wide pane. The work is the point, so it gets the width, the
   size and the leading; everything else is a label, a value or a consequence. */
.nav { display: flex; gap: 0; margin: -22px; min-height: calc(100vh - 110px); }
.rail { width: 230px; flex: none; border-right: 1px solid var(--line); padding: 8px 6px; }
.railhead { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 8px 8px; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); font-weight: 600; }
.pill.you { color: var(--amber); border-color: var(--amber); }
ul.list { list-style: none; margin: 0; padding: 0; }
li.it { display: flex; flex-direction: column; gap: 2px; padding: 7px 9px; border-radius: 7px; cursor: pointer; font-size: 13px; }
li.it:hover { background: var(--panel); }
li.it[aria-selected="true"] { background: var(--panel-2); }
li.it .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pane { flex: 1; min-width: 0; padding: 24px 32px 60px; }
.item { max-width: 760px; }
.item-title { margin: 0 0 8px; font-size: 18px; font-weight: 600; line-height: 1.4; }
.ah { margin: 26px 0 8px; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); font-weight: 600; display: block; }
.prose { font-size: 15.5px; line-height: 1.72; }
.prose .pb { white-space: pre-wrap; margin: 0 0 1.05em; }
.prose h2.pb, .prose h3.pb { margin: 1.6em 0 .5em; font-size: 15.5px; font-weight: 600; }
.prose ::selection { background: rgba(110,168,254,.35); }
mark.corr { background: none; color: inherit; border-bottom: 2px solid var(--accent); padding-bottom: 1px; cursor: pointer; }
mark.corr.suggest { border-bottom-color: var(--amber); background: rgba(245,196,81,.10); }
mark.corr.comment { border-bottom-color: var(--accent); background: rgba(110,168,254,.10); }
mark.corr.applied { border-bottom-color: var(--green); background: rgba(74,222,128,.10); }
mark.corr.pending { border-bottom-style: dashed; background: rgba(110,168,254,.16); }
.sg { background: rgba(245,196,81,.18); border-bottom: 2px solid var(--amber); outline: none; padding: 0 1px; }
.popover { position: fixed; z-index: 30; display: flex; align-items: center; gap: 8px; padding: 6px 8px; background: var(--panel-2); border: 1px solid var(--line); border-radius: 8px; box-shadow: 0 6px 24px rgba(0,0,0,.35); max-width: 420px; }
.popover textarea { width: 260px; background: var(--bg); color: var(--text); border: 1px solid var(--line); border-radius: 6px; padding: 6px 8px; font: inherit; resize: vertical; }
.popover .problem { color: var(--red); font-size: 12px; }
.popover label { color: var(--muted); display: flex; align-items: center; gap: 4px; }
.corrlist { margin-top: 26px; }
.corr-row { border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; margin-top: 8px; font-size: 13px; }
.corr-row.resolved { opacity: .55; }
.corr-head { display: flex; justify-content: space-between; gap: 12px; }
.corr-verb { font-weight: 600; }
.corr-status { color: var(--muted); }
.corr-row.applied .corr-status { color: var(--green); }
.corr-row.unsent .corr-status { color: var(--amber); }
.corr-row.refused .corr-status, .corr-row.stale .corr-status { color: var(--red); }
.corr-k { font-size: 11px; margin-top: 8px; }
.corr-before, .corr-after, .corr-words { white-space: pre-wrap; margin-top: 2px; }
.corr-before { color: var(--muted); }
.corr-after { color: var(--text); }
.corr-note { margin-top: 6px; font-size: 12px; }
.corr-actions { margin-top: 8px; display: flex; gap: 8px; }
.corr-actions .btn + .btn { margin-left: 0; }
.corr-replybox textarea.notes { margin-top: 8px; }
.decide { margin-top: 30px; border-top: 1px solid var(--line); padding-top: 18px; }
.decide .ah { margin-top: 0; }
/* Where a post made by hand went (RFC-0024): the field sits above the note it
   writes into, because the URL is the fact the record is missing until it is
   typed, and the note is optional. */
.posturl-field .ah { margin-top: 0; }
.posturl-field input { margin-bottom: 4px; }
.posturl-problem { color: var(--red); font-size: 12px; margin: 0 0 10px; }
.opts { display: flex; flex-direction: column; gap: 9px; margin-top: 14px; }
.opt { display: flex; align-items: baseline; gap: 12px; background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; }
.opt button { flex: none; width: 160px; }
.opt p { margin: 0; font-size: 12.5px; line-height: 1.5; }
.item-details { margin-top: 26px; border-top: 1px solid var(--line); padding-top: 14px; }
.item-details summary { cursor: pointer; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); font-weight: 600; width: max-content; }
.meta { margin-top: 12px; }
.mrow { display: flex; justify-content: space-between; gap: 16px; padding: 6px 0; border-bottom: 1px solid var(--line); font-size: 13px; }
.mrow .v { text-align: right; min-width: 0; word-break: break-word; }

/* Sign-in (RFC-0026 §9). The panel covers the application rather than replacing
   it, so an expired session does not cost the operator the page they were on. */
.account { display: flex; align-items: center; gap: 10px; color: var(--muted); font-size: 13px; }
.account strong { color: var(--text); font-weight: 500; }
.account button {
  background: none; border: 1px solid var(--line); color: var(--muted);
  font: inherit; font-size: 12px; padding: 2px 10px; border-radius: 999px; cursor: pointer;
}
.account button:hover { color: var(--text); border-color: var(--accent); }

.signin {
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center;
  background: rgba(15, 17, 21, .92); backdrop-filter: blur(3px);
}
.signin-card {
  display: flex; flex-direction: column; align-items: center; gap: 22px;
  padding: 40px 48px; min-width: 300px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 14px;
}
.signin-card .brand { font-size: 20px; }
.signin-error { margin: 0; color: var(--red); font-size: 13px; text-align: center; }

/* ---- the flow shape (RFC-0027) -------------------------------------------------
   A derived diagram and its transition table, shown together. The canvas is capped
   at roughly half the viewport so the table stays above the fold; the table is a
   peer of the diagram, not its fallback, and is where the keyboard goes. */
main.wide { max-width: 1440px; }
.flowcard { padding: 0; overflow: hidden; }
.flowhead { padding: 10px 14px; border-bottom: 1px solid var(--line); }
.flowlegend { display: flex; gap: 14px; font-size: 12px; }
.fsw { display: inline-block; width: 9px; height: 9px; border-radius: 3px; vertical-align: -1px;
  margin-right: 5px; background: var(--panel-2); border: 1px solid var(--line); }
.fsw.role { border-color: var(--amber); }
.fsw.stub { border-style: dashed; }

.flowcanvas { position: relative; height: clamp(220px, min(46vh, var(--flow-h, 46vh)), 520px); border-bottom: 1px solid var(--line); overflow: hidden; }
.flowsvg { width: 100%; height: 100%; display: block; cursor: grab; touch-action: none; }
.flowsvg.panning { cursor: grabbing; }
.flowzoom { position: absolute; right: 10px; top: 10px; display: flex; flex-direction: column; gap: 5px; }
.zbtn { width: 28px; height: 28px; padding: 0; font: inherit; cursor: pointer; border-radius: 7px;
  background: var(--panel-2); color: var(--text); border: 1px solid var(--line); }
.zbtn:hover { border-color: var(--accent); }

.fnode rect { fill: var(--panel-2); stroke: var(--line); stroke-width: 1.5; }
.fnode.role rect { stroke: var(--amber); }
.fnode.stub rect { stroke-dasharray: 4 3; }
.fnode.terminal rect { fill: var(--panel); }
.fnode.unrouted rect { stroke: var(--red); }
.fnode.failedstep rect { stroke: var(--red); stroke-width: 2.5; }
.fnode.sel rect { stroke: var(--accent); stroke-width: 2.5; }
.fnode.dim { opacity: .42; }
.fnode { cursor: pointer; }
.fnode:hover rect { fill: #262c38; }
.fnode .flabel-n { fill: var(--text); font-size: 13px; font-weight: 500; }
.fnode .fwho { fill: var(--muted); font-size: 10.5px; }

.fedge { fill: none; stroke: #3a4552; stroke-width: 1.6; marker-end: url(#fcArrow); }
.fedge.back { stroke: #5b4a2e; stroke-dasharray: 5 4; marker-end: url(#fcArrowBack); }
.fedge.trod { stroke: var(--accent); stroke-width: 2.4; marker-end: url(#fcArrowTrod); }
.fedge.dim { opacity: .3; }
.flowsvg #fcArrow path { fill: #3a4552; }
.flowsvg #fcArrowBack path { fill: #5b4a2e; }
.flowsvg #fcArrowTrod path { fill: var(--accent); }
.felabel { fill: var(--muted); font-size: 10.5px; }
.felabel.back { fill: #a4884e; }
.felabel.dim { opacity: .35; }
.fhit { stroke: transparent; stroke-width: 16; fill: none; pointer-events: none; }

.fbadge circle { stroke: var(--bg); stroke-width: 2; }
.fbadge text { font-size: 10px; font-weight: 700; fill: #0b1020; }
.fbadge.here circle { fill: var(--accent); }
.fbadge.parked circle { fill: var(--amber); }
.fbadge.failed circle { fill: var(--red); }
.fbadge.visits circle { fill: #39424f; }
.fbadge.visits text { fill: var(--text); }

.flowtable { max-height: 40vh; overflow: auto; }
.ftable { border-collapse: collapse; width: 100%; font-size: 13px; }
.ftable th, .ftable td { text-align: left; padding: 7px 14px; border-bottom: 1px solid var(--line); }
.ftable th { color: var(--muted); font-weight: 500; font-size: 11px; text-transform: uppercase;
  letter-spacing: .6px; position: sticky; top: 0; background: var(--panel); }
.ftable tbody tr:hover { background: var(--panel-2); }
.ftable tr.sel { background: #1b2433; }
.ftable tr.unrouted td { color: var(--red); }
.frisk { color: var(--red); }
.fwhocell { color: var(--muted); }
.fvisit { color: var(--amber); font-size: 11px; }
.fbranch { color: var(--accent); font-size: 11px; }
.funreached { padding: 8px 14px; font-size: 12px; border-bottom: 1px solid var(--line); }

/* The route disclosure on a work item. */
.routerow { margin: -6px 0 12px; }
.disclose { background: none; border: none; color: var(--muted); font: inherit; cursor: pointer; padding: 4px 0; }
.disclose::before { content: "▸"; display: inline-block; margin-right: 6px; }
.disclose[aria-expanded="true"]::before { content: "▾"; }
.disclose:hover { color: var(--text); }

/* Focus, which the interface had none of before the shape needed a keyboard. */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ftable tr:focus-visible { outline-offset: -2px; }
/* ---- triggers (RFC-0023 §9) -------------------------------------------------
   What starts work without anyone asking, on the product it starts it for. The
   row reuses the property disclosure: scannable closed, its runs open. A run
   leads with the slot it stands for, because that is what the operator is looking
   for ("what did Monday's run find?"), and carries the account beneath it. */
details.trigger .propdetail { padding-top: 4px; }
.run { border-top: 1px solid var(--line); padding: 10px 0 8px; }
.run:first-of-type { border-top: none; }
.runsummary { margin-top: 4px; white-space: pre-wrap; }
.skipline { margin-top: 6px; font-size: 12px; }
