/* SME Routing Playground — Chick-fil-A theme.
   Palette + type sourced from @cfacorp/cowponents-native (components/theme.js):
   primary #004F71, tertiary(red) #dd0031, text #5B6770, Apercu type family. */

@font-face {
  font-family: "Apercu";
  src: url("/assets/Apercu-Medium.ttf") format("truetype");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "Apercu";
  src: url("/assets/Apercu-Bold.ttf") format("truetype");
  font-weight: 700;
  font-display: swap;
}

:root {
  /* ---- Raw palette (sourced from cowponents theme.js) ---- */
  --cfa-red: #dd0031;
  --cfa-red-deep: #b8002a;
  --cfa-blue: #004f71;
  --cfa-text: #5b6770;
  --cfa-disabled: #9aa6af;
  --cfa-outline: #d7dde1;
  --cfa-bg: #f5f5f5;
  --cfa-white: #ffffff;
  --cfa-success: #249e6b;
  --cfa-warning: #cca206;
  --cfa-error: #fb4b3e;
  --cfa-gold: #ffb700;
  --cfa-purple: #7b5cd6;

  /* ---- Semantic layer (a later light-dark() pass redefines only these) ---- */
  --color-primary: var(--cfa-red);
  --color-primary-ink: var(--cfa-blue);     /* outlines, secondary buttons, headings */
  --color-danger: var(--cfa-red-deep);      /* destructive actions (outlined, not filled) */
  --color-surface: var(--cfa-white);
  --color-surface-muted: #f4f6f8;
  --color-border: var(--cfa-outline);
  --color-text-muted: #6b7680;              /* AA-passing muted text (~4.5:1 on white) */
  --color-disabled-fill: var(--cfa-disabled); /* light grey: FILLS/borders only, never text */

  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.04), 0 6px 20px rgba(0, 79, 113, 0.06);
  --radius: 12px;
}

* { box-sizing: border-box; }

body {
  font-family: "Apercu", system-ui, -apple-system, sans-serif;
  color: var(--cfa-text);
  background: var(--cfa-bg);
  margin: 0;
  padding: 0 0 3rem;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* ---------- Header banner ---------- */
.app-header {
  background: linear-gradient(135deg, var(--cfa-red) 0%, var(--cfa-red-deep) 100%);
  color: var(--cfa-white);
  padding: 1.4rem 1.5rem;
  box-shadow: 0 2px 12px rgba(184, 0, 42, 0.25);
}
.app-header .header-inner {
  max-width: 960px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 1rem;
}
.logo-chip {
  flex: 0 0 auto;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--cfa-white);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
}
.logo-chip img { width: 40px; height: 40px; display: block; }
.app-header h1 {
  font-size: 1.55rem;
  font-weight: 700;
  margin: 0;
  letter-spacing: -0.01em;
}
.app-header .tagline {
  margin: 0.15rem 0 0;
  font-size: 0.9rem;
  opacity: 0.9;
  font-weight: 400;
}
.app-header .whoami {
  margin-left: auto;
  align-self: flex-start;
  font-size: 0.8rem;
  font-weight: 500;
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.18);
  white-space: nowrap;
}

/* ---------- Layout ---------- */
main {
  max-width: 960px;
  margin: 1.5rem auto 0;
  padding: 0 1.5rem;
}

section {
  background: var(--cfa-white);
  border: 1px solid var(--cfa-outline);
  border-radius: var(--radius);
  padding: 1.25rem 1.4rem 1.4rem;
  margin: 1.1rem 0;
  box-shadow: var(--shadow-card);
}

section h2 {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--cfa-blue);
  margin: 0 0 1rem;
}
.step-badge {
  flex: 0 0 auto;
  width: 1.7rem;
  height: 1.7rem;
  border-radius: 50%;
  background: var(--cfa-red);
  color: var(--cfa-white);
  font-size: 0.9rem;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* ---------- Form controls ---------- */
textarea {
  width: 100%;
  font-family: "SF Mono", ui-monospace, Menlo, monospace;
  font-size: 0.9rem;
  color: var(--cfa-text);
  border: 1px solid var(--cfa-outline);
  border-radius: 8px;
  padding: 0.7rem 0.8rem;
  resize: vertical;
  background: #fcfcfd;
  transition: border-color 0.15s, box-shadow 0.15s;
}
textarea:focus {
  outline: none;
  border-color: var(--cfa-blue);
  box-shadow: 0 0 0 3px rgba(0, 79, 113, 0.12);
}

/* PAI-223 — front-page examples. Quiet, secondary affordances: an SME should read them as
   suggestions, not as a second primary action competing with "Start simulation". */
.examples { margin-bottom: 0.6rem; }
.examples-label { font-size: 0.85rem; color: var(--color-text-muted); }
.chips { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.35rem; }
.chip {
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-primary-ink);
  border-radius: 999px;
  padding: 0.3rem 0.7rem;
  font-size: 0.85rem;
  cursor: pointer;
  font-family: inherit;
}
.chip:hover { border-color: var(--color-primary-ink); background: var(--color-surface-muted); }

/* PAI-223 — the fixture toggles are PRETEND system facts, not questions about the request, so they
   sit in a fieldset with a legend saying so. The group is a block; the inner `.checks` div keeps the
   flex row below. `[hidden]` needs restating for the same reason `.checks[hidden]` does — the
   explicit display rule outranks the UA stylesheet's `[hidden] { display: none }`. */
.checks-group {
  display: block;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: 0.5rem 0.9rem 0.2rem;
  margin: 0.8rem 0 1rem;
}
.checks-group[hidden] { display: none; }
.checks-group > legend { font-size: 0.85rem; color: var(--color-text-muted); padding: 0 0.35rem; }
.checks-hint { margin: 0.1rem 0 0; font-size: 0.8rem; color: var(--color-text-muted); }
/* `.checks` carries its own outer margin for the un-nested case; don't double it inside the group. */
.checks-group > .checks { margin: 0.5rem 0 0.7rem; }
.sim-error { margin: 0.6rem 0 0; color: var(--color-danger); font-size: 0.9rem; font-weight: 600; }

.checks {
  display: flex;
  flex-wrap: wrap;
  gap: 1.2rem;
  margin: 0.8rem 0 1rem;
}
.checks label {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.92rem;
  cursor: pointer;
  user-select: none;
}
/* The `display` rules above outrank the UA stylesheet's `[hidden] { display: none }`, so
   applyDataModeUi's `hidden = true` (live suppliers / live Aravo) left the now-inert toggles on
   screen and clickable. Same guard as .parse-status[hidden] and .mode-banner[hidden].
   The row needs its own override: with all three labels hidden it still has zero height but keeps
   its 0.8rem/1rem margins, leaving ~29px of dead space above "Start simulation". */
.checks label[hidden] { display: none; }
.checks[hidden] { display: none; }
.checks input[type="checkbox"] {
  width: 1.05rem;
  height: 1.05rem;
  accent-color: var(--cfa-red);
  cursor: pointer;
}

/* ---------- Buttons: element base = PRIMARY; variants are classes (no #id styling) ---------- */
button {
  font-family: "Apercu", system-ui, sans-serif;
  font-size: 0.92rem;
  font-weight: 700;
  padding: 0.6rem 1.2rem;
  margin: 0.25rem 0.5rem 0.25rem 0;
  border-radius: 8px;
  border: 2px solid var(--color-primary);
  background: var(--color-primary);
  color: var(--cfa-white);
  cursor: pointer;
  transition: transform 0.06s ease, background 0.15s, box-shadow 0.15s;
  box-shadow: 0 1px 3px rgba(184, 0, 42, 0.25);
}
button:hover { background: var(--cfa-red-deep); border-color: var(--cfa-red-deep); }
button:active { transform: translateY(1px); }
button:focus-visible { outline: 3px solid rgba(221, 0, 49, 0.35); outline-offset: 2px; }
button:disabled {
  background: var(--color-disabled-fill); border-color: var(--color-disabled-fill);
  color: var(--cfa-white); cursor: progress; box-shadow: none; transform: none;
}

/* Secondary — blue outline (Re-evaluate, Propose, Validate, Copy, grade, Enable) */
.btn-secondary {
  background: var(--color-surface); color: var(--color-primary-ink);
  border-color: var(--color-primary-ink); box-shadow: none;
}
.btn-secondary:hover { background: rgba(0, 79, 113, 0.06); border-color: var(--color-primary-ink); }
.btn-secondary:disabled { background: var(--color-surface); color: var(--color-text-muted); border-color: var(--color-border); }

/* Ghost — low emphasis, additive (+condition, +group, Set to always, Add rule, Cancel) */
.btn-ghost {
  background: transparent; color: var(--color-primary-ink);
  border-color: transparent; box-shadow: none; font-weight: 600;
}
.btn-ghost:hover { background: rgba(0, 79, 113, 0.06); border-color: transparent; }

/* Danger — destructive, OUTLINED so it's distinct from filled primary (delete, remove leaf) */
.btn-danger {
  background: var(--color-surface); color: var(--color-danger);
  border-color: var(--color-danger); box-shadow: none;
}
.btn-danger:hover { background: rgba(184, 0, 42, 0.08); border-color: var(--color-danger); }

/* Icon — compact neutral control (rule up/down move) */
.btn-icon {
  padding: 0.2rem 0.55rem; background: transparent; color: var(--cfa-text);
  border-color: var(--color-border); box-shadow: none;
}
.btn-icon:hover { background: var(--color-surface-muted); border-color: var(--color-border); }
.btn-icon:disabled { opacity: 0.35; cursor: default; background: transparent; color: var(--cfa-text); }

/* Action row: button + inline progress status (mirrors cowponents Spinner:
   a spinner and a label in a centered row). */
.action-row { display: flex; align-items: center; gap: 0.85rem; flex-wrap: wrap; }
.parse-status { display: inline-flex; align-items: center; gap: 0.5rem; font-size: 0.9rem; color: var(--cfa-text); }
.parse-status[hidden] { display: none; }
.parse-status.error { color: var(--cfa-red); font-weight: 700; }
.parse-status.error .spinner { display: none; }
.spinner {
  width: 1.15rem;
  height: 1.15rem;
  border: 3px solid rgba(221, 0, 49, 0.2);
  border-top-color: var(--cfa-red);
  border-radius: 50%;
  animation: cfa-spin 0.7s linear infinite;
  flex: none;
}
@keyframes cfa-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation-duration: 2.4s; } }

/* ---------- Decision tree ---------- */
#tree { display: flex; flex-direction: column; align-items: stretch; gap: 0; }
.node {
  border: 1px solid var(--cfa-outline);
  border-radius: 10px;
  padding: 0.7rem 0.9rem;
  background: #fbfcfd;
}
.node.req { border-left: 4px solid var(--cfa-blue); }
.node.branch.llm { border-top: 3px solid var(--cfa-gold); }
.node.branch.rules { border-top: 3px solid var(--cfa-blue); }
.node-title {
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  color: var(--cfa-disabled);
  text-transform: uppercase;
  font-weight: 700;
}
.node-head { font-weight: 700; margin-top: 0.25rem; color: var(--cfa-blue); }
.node-body { font-size: 0.9rem; color: var(--cfa-text); margin-top: 0.25rem; }
.connector { align-self: center; width: 2px; height: 1.1rem; background: var(--cfa-outline); }
.branches { display: flex; gap: 1rem; align-items: flex-start; }
.branch { flex: 1; }
.branch.rules { font-family: "SF Mono", ui-monospace, Menlo, monospace; }

.rule-row {
  display: flex;
  align-items: baseline;
  padding: 0.2rem 0.45rem;
  border-radius: 5px;
  font-size: 0.83rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin: 0.1rem 0;
}
.rule-row.fired { background: #e6f5ee; color: var(--cfa-success); font-weight: 700; }
.rule-row.gated { background: #fdf6e3; color: #9a7b06; }
.rule-row.false { color: var(--cfa-disabled); text-decoration: line-through; }
.rule-row.not_reached { color: #c4ccd1; }

/* PAI-218: the walk's no-match rows carry a prose label now, so the state cannot be concatenated
   onto it — nine of the fifteen labels contain an em-dash and one contains a comma. Separate
   spans, separated visually rather than by punctuation. */
/* min-width: 0 overrides the flex-item default of min-width: auto, which otherwise refuses to
   shrink below the label's content size and defeats .rule-row's own overflow/ellipsis — same
   fix as .rule-summary-text above. overflow/text-overflow move here because a flex CONTAINER's
   text-overflow does not truncate a child's content; it has to live on the item holding the prose. */
.rule-row-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.rule-row-state { opacity: 0.7; margin-left: 0.5rem; white-space: nowrap; }
.rule-mark { margin-right: 0.4rem; }

/* PAI-222 — the rule walk leads with its conclusion; gated and non-matching rules collapse behind a
   summary. Gated rules group by the signal that blocked them, so 14 amber warnings read as 8
   uncaptured signals. */
.gated-group { margin-top: 0.4rem; }
.gated-group > summary {
  cursor: pointer;
  font-size: 0.83rem;
  color: var(--color-text-muted);
  padding: 0.2rem 0.45rem;
}
.gated-group > summary:hover { color: var(--color-primary-ink); }
/* Stacked, not a space-between row: this panel is the narrow right-hand branch of the tree, and a
   two-column row wraps the label across three lines with the detail floating mid-line. */
.gated-signal { padding: 0.3rem 0.45rem; font-size: 0.83rem; }
.gated-label { display: block; color: var(--cfa-text); }
.gated-detail { display: block; color: var(--color-text-muted); font-size: 0.78rem; }

.verdict {
  text-align: center;
  font-weight: 700;
  padding: 0.7rem;
  border-radius: 10px;
  letter-spacing: 0.01em;
}
.verdict.diverge { background: #fce8e6; color: var(--cfa-red); border: 1px solid #f6c9c4; }
.verdict.agree { background: #e6f5ee; color: var(--cfa-success); border: 1px solid #bfe6d3; }
.verdict.neutral { background: #eef1f3; color: var(--cfa-text); }

#ruleset_errors:not(:empty) {
  margin-top: 0.8rem;
  padding: 0.6rem 0.8rem;
  background: #fce8e6;
  color: var(--cfa-red);
  border-radius: 8px;
  font-size: 0.88rem;
  font-weight: 700;
}

/* ---------- Transcript & reference disclosure blocks ---------- */
#transcript details, #reference details {
  border: 1px solid var(--cfa-outline);
  border-radius: 10px;
  padding: 0.5rem 0.7rem;
  margin: 0.5rem 0;
  background: #fbfcfd;
}
#transcript summary, #reference summary { cursor: pointer; font-weight: 700; color: var(--cfa-blue); }
#transcript pre, #reference pre, #reference .narrative {
  white-space: pre-wrap;
  word-break: break-word;
  background: #f4f6f8;
  padding: 0.6rem 0.7rem;
  border-radius: 6px;
  margin: 0.3rem 0 0.6rem;
  font-family: "SF Mono", ui-monospace, Menlo, monospace;
  font-size: 0.82rem;
  border: 1px solid #eaeef1;
}
#transcript .sent-label, #transcript .recv-label {
  font-size: 0.82rem;
  color: var(--cfa-disabled);
  font-weight: 700;
  margin-top: 0.35rem;
}
.muted { color: var(--color-text-muted); font-style: italic; }
#reference h3 { margin: 1rem 0 0.35rem; font-size: 0.98rem; color: var(--cfa-red); }

#propose_out:not(:empty) {
  white-space: pre-wrap;
  word-break: break-word;
  background: #f4f6f8;
  padding: 0.7rem;
  border-radius: 8px;
  margin-top: 0.7rem;
  font-family: "SF Mono", ui-monospace, Menlo, monospace;
  font-size: 0.82rem;
  border: 1px solid #eaeef1;
}

/* ---------- Confidence panel ---------- */
#confidence { margin-top: 1rem; }
.conf-header { display: flex; gap: 0.9rem; align-items: baseline; flex-wrap: wrap; font-weight: 700; }
.conf-score { font-size: 1.1rem; color: var(--cfa-blue); }
.conf-band { color: var(--cfa-disabled); font-weight: 400; }
.conf-gate.ok { color: var(--cfa-success); }
.conf-gate.warn { color: var(--cfa-red); }
/* Categorical HITL / policy-review gate — same treatment as the confidence gate (PAI-45 AC#3). */
.policy-gate.ok { color: var(--cfa-success); }
.policy-gate.warn { color: var(--cfa-red); }
.conf-bar {
  position: relative;
  display: flex;
  height: 1.5rem;
  margin: 0.6rem 0;
  background: #eef1f3;
  border-radius: 6px;
  overflow: hidden;
}
.conf-seg { height: 100%; }
/* Signal segments + matching legend swatches, recolored to the CFA palette */
.conf-seg.rule, .conf-swatch.rule { background: var(--cfa-blue); }
.conf-seg.data, .conf-swatch.data { background: var(--cfa-success); }
.conf-seg.aravo, .conf-swatch.aravo { background: var(--cfa-purple); }
.conf-seg.llm, .conf-swatch.llm { background: var(--cfa-gold); }
.conf-gate-mark { position: absolute; top: -2px; bottom: -2px; width: 2px; background: var(--cfa-red); }

.conf-caption { font-size: 0.8rem; color: var(--color-text-muted); margin: 0.1rem 0 0.5rem; }
.conf-legend { display: flex; flex-wrap: wrap; gap: 0.3rem 1.2rem; font-size: 0.85rem; color: var(--cfa-text); }
.conf-legend-row { display: flex; align-items: center; gap: 0.4rem; min-width: 15rem; }
.conf-legend-row.zero { color: var(--cfa-disabled); }
.conf-legend-row.zero .conf-swatch { opacity: 0.35; }
.conf-legend-name { flex: 1; }
.conf-legend-val { font-variant-numeric: tabular-nums; color: var(--cfa-disabled); }
.conf-swatch { display: inline-block; width: 0.8em; height: 0.8em; border-radius: 2px; flex: none; }
.conf-cap { font-size: 0.85rem; color: var(--cfa-red); margin-top: 0.35rem; font-weight: 700; }
.conf-note { font-size: 0.85rem; color: var(--cfa-warning); margin-top: 0.35rem; }

/* ---------- Footer ---------- */
.app-footer {
  max-width: 960px;
  margin: 2rem auto 0;
  padding: 1rem 1.5rem 0;
  text-align: center;
  color: var(--cfa-disabled);
  font-size: 0.82rem;
}
.app-footer strong { color: var(--cfa-red); }

/* PAI-240 — footer build stamp: an inert identity pill plus a Copy button, on one centred row.
   `flex-wrap` so the row breaks instead of overflowing once PAI-255 lights `env` and adds a segment.

   The `[hidden]` restatement is LOAD-BEARING, not defensive boilerplate: `display: flex` here
   outranks the UA stylesheet's `[hidden] { display: none }`, so without it app.js's `hidden` would be
   silently ignored and a failed /api/version probe would leave an empty pill on screen. That exact
   bug shipped once (see data_mode.test.js — the inert-toggle hiding was a browser no-op for weeks),
   which is why .parse-status, .mode-banner and .checks all carry the same guard. */
.app-footer .build-stamp {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 0.4rem;
  margin: 0.5rem 0 0;
}
.app-footer .build-stamp[hidden] { display: none; }

/* The identity itself. Monospace so a sha is legible character by character, and deliberately WITHOUT
   `cursor: pointer` — it performs no action, and the previous version's pointer cursor on inert text
   was half the reason it read as a broken button.

   Colour is stated, not inherited: on the old red header `color: inherit` resolved to white, but the
   footer inherits --cfa-disabled, which the token block explicitly reserves for FILLS/borders and
   never text. --color-text-muted is the AA-passing equivalent. */
.app-footer .build-id {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.72rem;
  font-weight: 500;
  color: var(--color-text-muted);
  padding: 0.28rem 0.6rem;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  background: var(--color-surface);
  white-space: nowrap;
}

/* Copy carries .btn-secondary in the markup (the house class for Copy affordances — see the
   button-style block above), so hover, focus-visible and the blue-outline treatment all come from
   there. This only shrinks it to footer register: the base `button` is 0.92rem/bold with a 2px border,
   which beside a 0.72rem pill would make the loudest thing on the page a provenance control. */
.app-footer .build-copy {
  font-size: 0.72rem;
  font-weight: 600;
  padding: 0.24rem 0.6rem;
  margin: 0;
  border-width: 1px;
  border-radius: 999px;
  min-width: 7.5rem;   /* holds "Select, then ⌘C" without the row reflowing mid-interaction */
}

/* ---------- Small screens ---------- */
@media (max-width: 640px) {
  main { padding-inline: 1rem; }
  .branches { flex-direction: column; }
  .app-header h1 { font-size: 1.25rem; }
  .app-header .tagline { font-size: 0.82rem; }
  .card-facts { grid-template-columns: 1fr; }        /* stack label/value on narrow screens */
  .edit-field { grid-template-columns: 1fr; }
}

/* ---------- Rule-card editor ---------- */
.rules-hint { color: var(--color-text-muted); font-size: 0.9rem; margin: 0 0 0.75rem; }
.rule-card {
  border: 1px solid var(--color-border); border-radius: var(--radius);
  margin-bottom: 0.4rem; background: var(--color-surface);
}
.rule-card.disabled { opacity: 0.55; }
.rule-card.disabled .rule-id { text-decoration: line-through; }

/* PAI-224 — rule cards collapse to one line. Padding lives on the summary and the body, not the
   container, so a collapsed card is a single compact row. */
details.rule-card > summary.rule-summary {
  cursor: pointer;
  padding: 0.45rem 0.7rem;
  font-size: 0.88rem;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  border-radius: var(--radius);
}
details.rule-card > summary.rule-summary:hover { background: var(--color-surface-muted); }
details.rule-card[open] > summary.rule-summary { border-bottom: 1px solid var(--color-border); border-radius: var(--radius) var(--radius) 0 0; }
details.rule-card > .rule-body { padding: 0.6rem 1rem 0.85rem; }
.rule-summary-text { flex: 1; min-width: 0; }
.rule-flag {
  font-size: 0.72rem;
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 0.05rem 0.45rem;
  white-space: nowrap;
}
details.rule-card.disabled > summary .rule-summary-text { text-decoration: line-through; }
.rule-header { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.5rem; flex-wrap: wrap; }
.rule-ordinal { font-size: 0.8rem; color: var(--color-text-muted); }
.rule-id { font-weight: 600; font-family: "SF Mono", ui-monospace, Menlo, monospace; }
.field-row { display: block; margin: 0.35rem 0; font-size: 0.9rem; }
.field-row input, .field-row select { margin-left: 0.4rem; }
.add-rule { margin-bottom: 0.75rem; }
.rules-actions { display: flex; gap: 0.5rem; margin-bottom: 0.5rem; flex-wrap: wrap; }
#raw_inspector { margin-top: 0.75rem; }
#raw_inspector pre { max-height: 320px; overflow: auto; background: var(--color-surface-muted); padding: 0.5rem; border-radius: 6px; }

/* ---------- Condition tree ---------- */
.cond-label { font-size: 0.85rem; color: var(--cfa-text); margin: 0.4rem 0 0.2rem; }
.cond-group { border-left: 3px solid var(--color-border); padding: 0.4rem 0 0.4rem 0.6rem; margin: 0.3rem 0; }
.cond-group-head { display: flex; align-items: center; gap: 0.5rem; }
.cond-children { margin: 0.3rem 0 0.3rem 0.4rem; }
.leaf-row { display: flex; align-items: center; gap: 0.4rem; margin: 0.25rem 0; min-width: 0; flex-wrap: wrap; }
.leaf-field, .leaf-op, .leaf-value { font-size: 0.85rem; }
.leaf-remove, .cond-add { font-size: 0.8rem; padding: 0.1rem 0.4rem; }
.cond-always { font-style: italic; color: var(--color-text-muted); display: flex; gap: 0.6rem; align-items: center; }

/* ---------- Rule ops ---------- */
.rule-move, .rule-toggle, .rule-delete { font-size: 0.8rem; padding: 0.1rem 0.45rem; }
.rule-delete { margin-left: auto; }
.rule-id-error { color: var(--color-danger); font-size: 0.8rem; min-height: 1em; }

/* PAI-218: the rule code is lineage, not the thing you read first. Muted and smaller than the
   business label above it, but still an editable input — see rule_editor.js renderCard.
   PAI-218 review: scoped to the ordinal/label/id text only, NOT the whole .rule-header — the
   header also holds the ↑ / ↓ / Disable / ✕ buttons, and opacity: 0.75 was muting the
   danger-red delete button along with them, which was never the intent. */
.rule-header.lineage .rule-ordinal,
.rule-header.lineage .lineage-label,
.rule-header.lineage .rule-id { font-size: 0.85rem; opacity: 0.75; }
.rule-header.lineage .lineage-label { margin-right: 0.35rem; }
/* The generic `.field-row input` rule is (0,1,1) specificity (class + type selector); a bare
   `.rule-alias` is only (0,1,0) and LOSES that fight regardless of source order, leaving its
   margin-left: 0 dead and the input overflowing its row by ~6.4px. Qualifying with the parent
   class makes this (0,2,0), which beats (0,1,1) unambiguously. */
.field-row .rule-alias { font-weight: 600; width: 100%; margin-left: 0; }
/* Matches .rule-id-error above exactly — one error treatment on the card, not two. */
.rule-alias-error { color: var(--color-danger); font-size: 0.8rem; min-height: 1em; }

/* ---------- Sim chat transcript ---------- */
.mode-banner {
  display: flex;
  gap: .55rem;
  align-items: flex-start;
  margin-top: 1rem;
  padding: .65rem .8rem;
  font-size: .85rem;
  line-height: 1.4;
  color: var(--cfa-text);
  background: color-mix(in srgb, var(--cfa-warning) 14%, var(--cfa-white));
  border: 1px solid color-mix(in srgb, var(--cfa-warning) 45%, var(--cfa-white));
  border-radius: 8px;
}
.mode-banner[hidden] { display: none; }
.mode-banner-icon { color: var(--cfa-warning); font-size: 1rem; line-height: 1.3; flex: none; }
.mode-banner code { font-size: .82em; background: color-mix(in srgb, var(--cfa-warning) 18%, var(--cfa-white)); padding: 0 .25em; border-radius: 3px; }

.transcript { display: flex; flex-direction: column; gap: .5rem; margin-top: 1rem; }
.bubble { max-width: min(42rem, 100%); padding: .5rem .75rem; border-radius: .75rem; overflow-wrap: anywhere; }
.bubble .who { display: block; font-size: .72rem; opacity: .6; margin-bottom: .15rem; }
.bubble .msg { white-space: pre-wrap; }
.bubble.bot { align-self: flex-start; background: var(--cfa-bg); }
.bubble.requester { align-self: flex-end; background: color-mix(in srgb, var(--cfa-red) 10%, var(--cfa-white)); }

.clarify { display: flex; flex-direction: column; gap: .4rem; align-self: flex-start; margin: .3rem 0; }
.clarify-field { display: grid; gap: .2rem; }
.clarify-field span { font-size: .88rem; color: var(--cfa-text); }
/* `.clarify` is a flex column, so its children stretch to the widest one — which is the question,
   a full sentence. Left alone that drags the control and the Send button out to sentence width
   (PAI-142's question is ~65 characters, so they rendered ~530px). Cap the control and let the
   button size to its own text. */
.clarify input,
.clarify select {
  padding: .4rem .5rem;
  border: 1px solid var(--cfa-outline);
  border-radius: 6px;
  font-family: "Apercu", system-ui, sans-serif;
  font-size: .9rem;
  color: var(--cfa-text);
  max-width: 22rem;
  width: 100%;
}
/* The picker is a real <select> — keep the platform chevron and menu behaviour (free keyboard and
   screen-reader semantics) rather than restyling it into something that only looks like one. */
.clarify select { background-color: var(--cfa-surface, #fff); }
.clarify input:focus,
.clarify select:focus {
  outline: none;
  border-color: var(--cfa-blue);
  box-shadow: 0 0 0 3px rgba(0, 79, 113, 0.12);
}
.clarify button { align-self: flex-start; }

/* PAI-272 — the stated spend-class assumption, appended to whichever clarify ask was already
   happening (never a turn of its own). A row of its own, not a `.clarify-field`, because it is a
   yes/no confirm/deny, not a value to type. */
.clarify-assumption { display: grid; gap: .3rem; }
.clarify-assumption p { font-size: .88rem; color: var(--cfa-text); margin: 0; }
.clarify-assumption-actions { display: flex; gap: .4rem; }
.clarify-assumption-actions button {
  padding: .35rem .7rem;
  border: 1px solid var(--cfa-outline);
  border-radius: 6px;
  background: var(--cfa-surface, #fff);
  font-family: "Apercu", system-ui, sans-serif;
  font-size: .85rem;
  color: var(--cfa-text);
  cursor: pointer;
}
.clarify-assumption-actions button[aria-pressed="true"] {
  background: color-mix(in srgb, var(--cfa-blue) 16%, var(--cfa-white));
  border-color: var(--cfa-blue);
}

/* ---------- Adaptive card (sim) ---------- */
.card-host { margin-top: 1rem; }
.adaptive-card {
  border: 1px solid var(--cfa-outline);
  border-radius: var(--radius);
  padding: 1rem 1.25rem;
  box-shadow: var(--shadow-card);
  background: var(--cfa-white);
  max-width: 40rem;
}
.card-title { font-size: 1.1rem; font-weight: 700; margin: 0 0 .5rem; color: var(--cfa-blue); }
.card-facts { display: grid; grid-template-columns: minmax(0, max-content) minmax(0, 1fr); gap: .15rem .75rem; margin: .5rem 0; }
/* PAI-148 — Camille asked for the headings bold (2026-08-05). Teams' native FactSet renderer
   already bolds fact titles; this surface FADED them, so the playground was misrepresenting the
   card it is supposed to mirror. */
.card-facts dt { font-weight: 700; }
.card-facts dd { margin: 0; }
/* The channel line carries its own inline <strong> on the label now, so the whole block is no
   longer bold — that was the "some things bolded and some plain" she flagged. */
.card-channel { color: var(--cfa-red); }
.card-risk { color: var(--cfa-warning); }
.card-subtle { color: var(--color-text-muted); font-size: .9rem; }
.card-actions { display: flex; gap: .5rem; margin-top: .75rem; flex-wrap: wrap; }

/* PAI-253 — Clarify is one button that asks every outstanding question in one turn; these list
   WHICH questions are coming underneath it, so a single button doesn't read as one vague ask. */
.card-clarify-note { margin: .5rem 0 0; }
.card-clarify-signals { margin: .25rem 0 0; padding-left: 1.2rem; font-size: .9rem; color: var(--color-text-muted); }

/* PAI-148 — collapsed audit trail on the review card. Quiet by default: build-team detail that must
   stay reachable without competing with the recommendation above it. */
.card-audit { margin-top: .75rem; border-top: 1px solid var(--color-border); padding-top: .5rem; }
.card-audit > summary { cursor: pointer; font-size: .9rem; color: var(--color-text-muted); }
.card-audit > summary:hover { color: var(--color-primary-ink); }
.card-audit .card-subtle { margin: .5rem 0 0; }

/* ---------- Edit form (Task 4) ---------- */
.edit-form { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.edit-field { display: grid; grid-template-columns: minmax(0, 160px) minmax(0, 1fr); align-items: center; gap: 8px; }
.edit-field > span { font-weight: 600; }
.edit-field input, .edit-field select { padding: 4px 6px; }

/* ---------- Verdict banner (routing verdict) ---------- */
.verdict-host { margin-top: 12px; display: flex; flex-direction: column; gap: 6px; }
.verdict-conf { font-size: 0.9em; font-weight: 600; }
.verdict-details { align-self: flex-start; background: none; border: none; padding: 0;
  color: var(--cfa-red); cursor: pointer; text-decoration: underline; font: inherit; }
.outcome-note { margin: 0 0 8px; font-size: 0.85em; color: var(--cfa-text); }

/* ---------- Propose actions (Copy for PAI-91) ---------- */
.propose-actions { display: flex; gap: 8px; align-items: center; margin-top: 8px; }
.propose-actions a { color: var(--cfa-red); text-decoration: underline; font-size: 0.9em; }

/* ---------- Grade-in-place form ---------- */
.grade-form { display: flex; flex-direction: column; gap: 6px; margin-top: 10px;
  padding-top: 10px; border-top: 1px solid var(--cfa-outline); }
.grade-prompt { font-weight: 600; }
.grade-name { padding: 4px 6px; width: 12rem; }
.grade-why { padding: 4px 6px; resize: vertical; }
.grade-actions { display: flex; gap: 8px; }
.grade-done { margin-top: 10px; font-weight: 600; color: var(--cfa-success); }
.grade-error { color: var(--cfa-red); font-size: 0.9em; }
.grade-expected { display: block; margin-top: 0.5rem; width: 100%; }
/* The `[hidden]` restatement is LOAD-BEARING, not defensive boilerplate: `display: block` above
   outranks the UA stylesheet's `[hidden] { display: none }`, so without it renderGradeForm's
   `expected.hidden = true` would be silently ignored and the picker would show before the first
   override click — same guard as .parse-status, .mode-banner, .checks and .build-stamp. */
.grade-expected[hidden] { display: none; }
.grade-download { margin-top: 0.75rem; }
.grade-download-hint { font-size: 0.85rem; opacity: 0.8; margin-bottom: 0.4rem; }

/* ---------- Definitions editor (Task 1.8, signal cards Task 2.6) ---------- */
.def-group-title { margin: 1rem 0 0.5rem; font-size: 1rem; color: var(--cfa-text); }
.def-group-title:first-child { margin-top: 0; }
.def-card {
  border: 1px solid var(--color-border); border-radius: var(--radius);
  padding: 0.75rem 1rem; margin-bottom: 0.75rem; background: var(--color-surface);
}
.def-card.def-out { opacity: 0.55; }   /* out-of-scope channels / disabled signals are dimmed, not hidden */
.def-header { margin-bottom: 0.35rem; }
.def-name { font-weight: 700; font-family: "SF Mono", ui-monospace, Menlo, monospace; color: var(--cfa-blue); }
.def-field { display: block; margin: 0.4rem 0; }
.def-field > .def-textarea { display: block; margin-top: 0.2rem; }
.def-textarea { width: 100%; min-height: 2.6rem; }
.def-toggle { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.9rem; margin-top: 0.3rem; }
.definitions-actions { display: flex; gap: 0.5rem; margin-bottom: 0.5rem; flex-wrap: wrap; }

/* ---------- Add-signal card (Task 3.4): editable name + "needs engineering" chip ---------- */
.def-name-input {
  font-weight: 700; font-family: "SF Mono", ui-monospace, Menlo, monospace; color: var(--cfa-blue);
  border: 1px solid var(--color-border); border-radius: 4px; padding: 0.1rem 0.4rem; min-width: 12rem;
}
/* Same warning pair the A/B "changed" summary already uses, so both readings of "this needs
   attention before it's committed" share one visual language. */
.chip-eng {
  display: inline-block; font-size: 0.75rem; padding: 0.1rem 0.5rem; border-radius: 999px;
  background: #fdf6e3; color: #9a7b06; margin-left: 0.5rem; vertical-align: middle;
}
.engineering-required {
  margin-top: 0.5rem; padding: 0.6rem 0.8rem; border-radius: 8px; background: #fdf6e3; color: #9a7b06;
}
.eng-required-title { font-weight: 700; margin-bottom: 0.3rem; }
.engineering-required ul { margin: 0; padding-left: 1.2rem; }
#definitions_raw_inspector { margin-top: 0.75rem; }
#definitions_raw_inspector pre { max-height: 320px; overflow: auto; background: var(--color-surface-muted); padding: 0.5rem; border-radius: 6px; }

/* ---------- A/B experiment view (Task 1.8) ---------- */
.ab-result { margin-top: 0.5rem; }
/* PAI-229 Task 6 — a lane fell back to the rules, so delta.summary below is describing something
   the SME's edits didn't cause. Same warning token as .mode-banner (the established treatment for
   "the model, not the rules, is the problem"), sized to at least match .ab-summary's prominence
   since it qualifies that very sentence and must not read as subordinate to it. */
.ab-llm-warning {
  font-weight: 700;
  padding: 0.6rem 0.8rem;
  border-radius: 8px;
  margin-bottom: 0.5rem;
  color: var(--cfa-text);
  background: color-mix(in srgb, var(--cfa-warning) 14%, var(--cfa-white));
  border: 1px solid color-mix(in srgb, var(--cfa-warning) 45%, var(--cfa-white));
}
/* #7a6205 measures 5.24:1 on this background (color-mix(in srgb, #cca206 14%, white) =
   rgb(248,242,220)) — AA with margin. Required ratio is 4.5:1, not 3:1: this text is 16px bold,
   and WCAG "large text" bold doesn't start until 18.66px, so the normal-text threshold applies.
   var(--cfa-warning) (#cca206) itself is only 2.14:1 here. Do NOT "restore consistency" by
   reverting to #9a7b06 (3.59:1, still fails) or to match .ab-summary.changed /
   .engineering-required (~3.74:1, also non-compliant) — those two are known-non-AA and are being
   ticketed separately; this line was deliberately fixed first because AC2's whole intent is that
   the title gets read first. */
.ab-llm-warning-title { color: #7a6205; }
.ab-llm-warning div + div { font-weight: 400; font-size: 0.85rem; margin-top: 0.2rem; }
.ab-summary { font-weight: 700; padding: 0.6rem 0.8rem; border-radius: 8px; background: #eef1f3; color: var(--cfa-text); }
.ab-summary.changed { background: #fdf6e3; color: #9a7b06; }
.ab-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-top: 0.6rem; }
.ab-col h4 { margin: 0 0 0.4rem; font-size: 0.95rem; color: var(--cfa-blue); }
.ab-signals { font-size: 0.85rem; color: var(--color-text-muted); margin-top: 0.35rem; }
.ab-signal-deltas { margin: 0.6rem 0 0; padding-left: 1.2rem; font-size: 0.85rem; color: var(--color-text-muted); }
@media (max-width: 640px) {
  .ab-cols { grid-template-columns: 1fr; }
}

/* ---------- IA: hide result sections until a sim populates them ---------- */
/* Uses :has() — requires a modern (evergreen) browser; fine for this internal tool. */
#outcome:not(:has(#tree > *)):not(:has(#confidence > *)) { display: none; }
#llm_transcript_section:not(:has(#transcript > *)) { display: none; }

/* PAI-224 — Validate/Propose sat below ~6,200px of cards; pin them to the bottom of the section. */
.rules-actions, .definitions-actions {
  position: sticky;
  bottom: 0;
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
  padding: 0.6rem 0;
  z-index: 2;
}
.editor-filter { display: block; font-size: 0.85rem; color: var(--color-text-muted); margin: 0.4rem 0 0.2rem; }
.editor-filter input {
  margin-left: 0.4rem;
  padding: 0.28rem 0.5rem;
  border: 1px solid var(--color-border);
  border-radius: 6px;
  font: inherit;
  min-width: 18rem;
}
.editor-filter-count { margin: 0 0 0.4rem; font-size: 0.8rem; color: var(--color-text-muted); }
.rule-flag.fired { color: var(--cfa-success); border-color: var(--cfa-success); font-weight: 700; }
.rule-flag.gated { color: #9a7b06; border-color: #e3d08a; }

/* PAI-224 — definition cards collapse. Signal headings lead with the plain-English label and keep
   the raw key as a chip, because the key is what appears in a rule. */
details.def-card > summary.def-summary {
  cursor: pointer;
  padding: 0.45rem 0.7rem;
  font-size: 0.88rem;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  border-radius: var(--radius);
}
details.def-card > summary.def-summary:hover { background: var(--color-surface-muted); }
details.def-card[open] > summary.def-summary { border-bottom: 1px solid var(--color-border); border-radius: var(--radius) var(--radius) 0 0; }
.def-summary-text { flex: 1; min-width: 0; font-weight: 600; }
.def-key {
  font-family: "SF Mono", ui-monospace, Menlo, monospace;
  font-size: 0.75rem;
  color: var(--color-text-muted);
  background: var(--color-surface-muted);
  border-radius: 5px;
  padding: 0.05rem 0.4rem;
}
.def-textarea { width: 100%; overflow-y: hidden; }

/* PAI-149 — elapsed counter beside the spinner. Tabular numerals so the row doesn't jitter as the
   digits change; muted because it is reassurance, not the message. */
.elapsed {
  font-size: 0.82rem;
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
  min-width: 2.2rem;
}

/* ---------- "Check against examples" eval panel (PAI-252) ---------- */
.eval-status { color: var(--color-text-muted); font-size: 0.9rem; }
.eval-warning { color: var(--cfa-warning); font-weight: 600; font-size: 0.9rem; }
.eval-cache-note { color: var(--cfa-warning); font-size: 0.85rem; margin: 0.2rem 0 0.6rem; }
.eval-case-list {
  list-style: none;
  margin: 0.4rem 0;
  padding: 0;
  max-height: 16rem;
  overflow-y: auto;
  border: 1px solid var(--color-border);
  border-radius: 8px;
}
.eval-case-list li { padding: 0.3rem 0.6rem; border-bottom: 1px solid var(--color-border); }
.eval-case-list li:last-child { border-bottom: none; }
.eval-case-list label { display: flex; align-items: center; gap: 0.4rem; font-size: 0.9rem; }
.eval-case-channel {
  font-size: 0.78rem;
  background: var(--color-surface-muted);
  border-radius: 5px;
  padding: 0.05rem 0.4rem;
}
.eval-cost-preview { font-size: 0.85rem; color: var(--color-text-muted); margin: 0.4rem 0; }
.eval-run-actions { display: flex; align-items: center; gap: 0.7rem; margin: 0.5rem 0; }
.eval-run-status { font-size: 0.85rem; color: var(--color-text-muted); }
.eval-results { margin-top: 0.6rem; }
.eval-summary { margin-bottom: 0.6rem; }
.eval-partial-banner {
  background: #fdf6e3;
  color: #9a7b06;
  font-weight: 700;
  padding: 0.5rem 0.7rem;
  border-radius: 8px;
  margin: 0 0 0.4rem;
}
.eval-headline { font-weight: 700; color: var(--cfa-blue); margin: 0 0 0.2rem; }
.eval-run-stamp { font-size: 0.8rem; color: var(--color-text-muted); margin: 0; }
.eval-badge {
  display: inline-block;
  font-size: 0.75rem;
  color: var(--color-text-muted);
  background: var(--color-surface-muted);
  border-radius: 5px;
  padding: 0.02rem 0.35rem;
  margin-top: 0.1rem;
}
/* PAI-281 — a case whose expected answer cannot be scored yet (GC33 awaits the must-ask set,
   GC35 awaits "Needs human routing" in the card vocabulary). Deliberately warning-coloured rather
   than muted like .eval-badge: "not scoreable" is a gap in what we can measure, and reading as
   ordinary metadata is how the previous corpus's blind spots stayed invisible. Both classes are
   applied together, so this only overrides colour — the inline-block display still comes from
   .eval-badge and cannot be lost here. */
.eval-badge-blocked { color: #9a7b06; background: #fdf6e3; font-weight: 700; }

/* The workbook row carried no free text, so the prompt is built from form answers alone. Muted:
   this is context for reading a result, not a warning. */
.eval-badge-sparse { font-style: italic; }

/* A disabled checkbox alone is easy to miss at a glance down a 46-row list. */
.eval-case-list li:has(input:disabled) { opacity: 0.72; }

.eval-results-table { width: 100%; border-collapse: collapse; margin-top: 0.4rem; font-size: 0.88rem; }
.eval-results-table th, .eval-results-table td {
  text-align: left;
  padding: 0.35rem 0.5rem;
  border-bottom: 1px solid var(--color-border);
  vertical-align: top;
}
.eval-row-error { color: var(--cfa-red); }
/* Verdict-cell coloring mirrors the drawer's agree/diverge/neutral vocabulary (.verdict above):
   a fix is good news (green), a regression is bad news (red), everything else is neutral-to-mild. */
.eval-verdict-fix .eval-verdict-cell { color: var(--cfa-success); font-weight: 700; }
.eval-verdict-regression .eval-verdict-cell { color: var(--cfa-red); font-weight: 700; }
.eval-verdict-changed-still-wrong .eval-verdict-cell,
.eval-verdict-same-channel-different-reasoning .eval-verdict-cell { color: #9a7b06; }
.eval-verdict-unchanged-still-wrong .eval-verdict-cell { color: var(--cfa-disabled); }

/* ---------- PAI-265: the SME usage guide ---------- */

/* A string the SME will actually see printed on screen, quoted inside the guide. Marked as a whole
   element because test_app.py strips these before checking the guide's own voice for build words:
   the guide has to print "shadow ruleset inconclusive" verbatim while never saying "shadow" itself.
   So this is load-bearing, not decorative — if it stops looking like a quoted string, authors stop
   using it and the ban starts firing on legitimate copy. Modelled on `.mode-banner code` above. */
#guide code.ui-string {
  font-size: .88em;
  background: var(--color-surface-muted);
  border: 1px solid var(--color-border);
  padding: 0 .3em;
  border-radius: 3px;
}

/* Symptom → action lookup. Modelled on .eval-results-table (line 907) rather than inventing a second
   table treatment on the same page — font-size and cell padding differ, so this is not an exact
   mirror. */
.guide-table { width: 100%; border-collapse: collapse; margin-top: 0.4rem; }
.guide-table th, .guide-table td {
  text-align: left;
  padding: 0.4rem 0.5rem;
  border-bottom: 1px solid var(--color-border);
  vertical-align: top;
}
.guide-table th { color: var(--color-primary-ink); }
#guide ol { margin: 0.4rem 0 0.8rem 1.2rem; }
#guide ol li { margin-bottom: 0.35rem; }
