/* ============================================================================
   views.css — styles specific to individual section views
   ========================================================================== */

/* ---- Header extra fields -------------------------------------------------- */
.viewmode-field { display: flex; flex-direction: column; gap: 4px; }
.ctrl-label-inline { font-size: var(--fs-xs); color: var(--text-faint); text-transform: uppercase; letter-spacing: 0.08em; }
.seed-field { display: flex; flex-direction: column; gap: 4px; }
.seed-field label { font-size: var(--fs-xs); color: var(--text-faint); text-transform: uppercase; letter-spacing: 0.08em; }
.foot-note { color: var(--text-faint); max-width: 46ch; }

/* ---- Overview ------------------------------------------------------------- */
.ov-dynamic { margin: var(--sp-4) 0; }
.sr-diagram { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: var(--sp-4); margin-bottom: var(--sp-3); }
.sr-node { background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-md); padding: var(--sp-3) var(--sp-4); }
.sr-node-title { font-weight: 750; letter-spacing: 0.06em; color: var(--accent); margin-bottom: 4px; }
.sr-node-desc { font-size: var(--fs-sm); color: var(--text-dim); }
.sr-link { display: flex; flex-direction: column; align-items: center; gap: 6px; min-width: 120px; }
.sr-track { position: relative; width: 100%; height: 3px; background: linear-gradient(90deg, var(--accent), var(--accent-2)); border-radius: var(--r-pill); overflow: visible; }
.sr-link-label { font-size: var(--fs-xs); color: var(--text-faint); }
/* Three passes, not `infinite`. This dot starts on its own, sits beside the
   Overview's body text, and used to run forever with no way to pause, stop or
   hide it — the exact profile WCAG 2.2.2 Pause, Stop, Hide is written for. It is
   decorative and aria-hidden, and the prefers-reduced-motion block in base.css
   already stops it dead for anyone who has set that OS preference, so the SC is
   arguable either way; a conformance claim that does not have to argue is worth
   more than 7.2 seconds of perpetual motion. Three passes still says "a signal
   travels this link" and then stops. */
.sr-dot { top: -5px; left: 0; animation: srtravel 2.4s var(--ease) 3; }
@keyframes srtravel { 0% { left: 0; } 100% { left: calc(100% - 12px); } }

.rep-list { display: flex; flex-direction: column; gap: var(--sp-2); }
.rep-bits { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; margin-bottom: var(--sp-2); }
.rep-row { display: grid; grid-template-columns: 190px 1fr; gap: var(--sp-3); align-items: center; padding: var(--sp-2) 0; border-bottom: 1px solid var(--border-faint); }
.rep-head { display: flex; flex-direction: column; }
.rep-name { font-weight: 600; color: var(--text); font-size: var(--fs-sm); }
.rep-rule { font-size: var(--fs-xs); color: var(--text-faint); }
.rep-inline { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
.rep-cell { font-family: var(--font-mono); font-size: var(--fs-xs); padding: 2px 5px; border-radius: var(--r-sm); background: var(--surface-inset); border: 1px solid var(--border-faint); color: var(--text-dim); }
.rep-cell.b1 { color: var(--bit-1); border-color: color-mix(in srgb, var(--bit-1) 40%, transparent); }
.rep-cell.b0 { color: var(--bit-0); border-color: color-mix(in srgb, var(--bit-0) 40%, transparent); }
.rep-cell.gap { display: inline-flex; align-items: center; height: 20px; }
.gap-bar { height: 6px; background: currentColor; border-radius: var(--r-pill); display: inline-block; }
.rep-dns { color: var(--covert); }
@media (max-width: 560px) { .rep-row { grid-template-columns: 1fr; gap: 4px; } .sr-diagram { grid-template-columns: 1fr; } }

/* ---- DNS ------------------------------------------------------------------ */
.dns-encode { display: flex; flex-direction: column; gap: var(--sp-2); }
.enc-step { display: grid; grid-template-columns: 110px 1fr; gap: var(--sp-3); align-items: start; }
.enc-label { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-faint); padding-top: 4px; }
.enc-content { min-width: 0; overflow-wrap: anywhere; }
.dns-b32 { color: var(--covert); word-break: break-all; }
.dns-labels { display: flex; flex-wrap: wrap; gap: 4px; }
.dns-label-chip { background: color-mix(in srgb, var(--covert) 12%, var(--surface-inset)); border: 1px solid color-mix(in srgb, var(--covert) 30%, transparent); color: var(--covert); border-radius: var(--r-sm); padding: 2px 6px; font-size: var(--fs-xs); }
.query-list { display: flex; flex-direction: column; gap: 4px; margin-bottom: var(--sp-3); }
.query-chip { font-size: var(--fs-xs); color: var(--text-dim); background: var(--surface-inset); border-radius: var(--r-sm); padding: 3px 6px; border: 1px solid var(--border-faint); }
.query-chip.q-covert { color: var(--covert); border-color: color-mix(in srgb, var(--covert) 30%, transparent); }
.char-list { margin: 0; padding-left: 1.1em; font-size: var(--fs-xs); color: var(--text-faint); }
.covert-col { background: color-mix(in srgb, var(--covert) 14%, transparent) !important; color: var(--covert) !important; font-weight: 650; }

/* ---- Timing --------------------------------------------------------------- */
.timing-topbar { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); margin-bottom: var(--sp-3); flex-wrap: wrap; }
.lab-line { margin: var(--sp-3) 0 var(--sp-2); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.08em; }
.timeline.animate .tl-packet { animation: tlpop 320ms var(--ease) both; }
@keyframes tlpop { from { transform: scale(0.2); opacity: 0; } to { transform: scale(1); opacity: 1; } }

/* ---- Storage -------------------------------------------------------------- */
.mb-line { font-size: var(--fs-sm); color: var(--text-dim); margin-bottom: var(--sp-2); }
.mb-break { margin-top: var(--sp-2); font-size: var(--fs-sm); color: var(--warn); border-top: 1px solid var(--border-faint); padding-top: var(--sp-2); }

/* ---- Ordering ------------------------------------------------------------- */
.ord-stream { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-bottom: var(--sp-3); }
.ord-pair { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: var(--sp-2); border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface-1); }
.ord-pair.reordered { border-color: var(--warn); box-shadow: 0 0 0 1px color-mix(in srgb, var(--warn) 40%, transparent); }
.ord-events { display: flex; gap: 4px; }
.ord-ev { width: 24px; height: 24px; display: grid; place-items: center; border-radius: var(--r-sm); font-family: var(--font-mono); font-weight: 700; font-size: var(--fs-sm); }
.ev-a { background: color-mix(in srgb, var(--accent) 22%, var(--surface-inset)); color: var(--accent); }
.ev-b { background: color-mix(in srgb, var(--accent-2) 22%, var(--surface-inset)); color: var(--accent-2); }
.ord-bit { font-family: var(--font-mono); font-weight: 700; font-size: var(--fs-xs); padding: 1px 4px; border-radius: var(--r-sm); }
.ord-bit.b0 { color: var(--bit-0); }
.ord-bit.b1 { color: var(--bit-1); }
.ord-bit.err { outline: 1.5px solid var(--bit-err); }
.ord-flip { color: var(--warn); font-weight: 700; font-size: var(--fs-sm); }
.metric-flag { color: var(--warn); font-size: 0.85em; }

/* ---- Stego ---------------------------------------------------------------- */
.file-label { display: flex; flex-direction: column; gap: 4px; font-size: var(--fs-sm); color: var(--text-dim); }
.file-input { font-size: var(--fs-xs); color: var(--text-faint); }
.file-input::file-selector-button { background: var(--surface-2); color: var(--text); border: 1px solid var(--border-control); border-radius: var(--r-sm); padding: 4px 10px; margin-right: 8px; cursor: pointer; }
.degrade-result { justify-content: flex-start; }

/* ---- Detection Console ---------------------------------------------------- */
.det-console { background: linear-gradient(180deg, var(--surface-1), var(--surface-0)); }
.det-console-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); margin-bottom: var(--sp-3); }
.det-overview { margin-bottom: var(--sp-4); }
.gauge-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr)); gap: var(--sp-3); }
.gauge-tile { border: 1px solid var(--border); border-radius: var(--r-md); padding: var(--sp-3); background: var(--surface-inset); }
.gauge-tile.selected { border-color: var(--accent); box-shadow: var(--glow-accent); }
.gauge-tile.level-high { border-left: 3px solid var(--anom-high); }
.gauge-tile.level-moderate { border-left: 3px solid var(--anom-mod); }
.gauge-tile.level-low { border-left: 3px solid var(--anom-low); }
.gauge-tile-label { font-size: var(--fs-sm); font-weight: 650; margin-bottom: var(--sp-2); }
.det-selector { margin: var(--sp-4) 0; }
.det-detail-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-5); align-items: start; }
@media (max-width: 800px) { .det-detail-grid { grid-template-columns: 1fr; } }

/* ---- Compare -------------------------------------------------------------- */
.compare-table td { white-space: normal; vertical-align: top; min-width: 110px; }
.compare-table td .cellwrap { display: block; max-width: 220px; }
.compare-note { font-size: var(--fs-xs); color: var(--text-faint); margin-top: 4px; }

/* ---- Defense / references ------------------------------------------------- */
.refs { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)); gap: var(--sp-5); }
.ref-cat { font-size: var(--fs-sm); color: var(--accent); margin-bottom: var(--sp-2); }
/* Not `display: flex`. Making the <li>s flex items blockifies their `display`
   away from `list-item`, which drops the listitem role in Chromium and costs the
   Further Reading list its "list of N items" announcement (1.3.1). Margin gives
   the same spacing and keeps the semantics. `list-style: none` also suppresses
   the role in Safari/VoiceOver; that half is covered by the explicit role="list"
   / role="listitem" defenseView.js now sets, which this stylesheet cannot add. */
.ref-list { list-style: none; padding: 0; margin: 0; }
.ref-item { border-left: 2px solid var(--border-strong); padding-left: var(--sp-3); margin: 0; }
.ref-item + .ref-item { margin-top: var(--sp-3); }
.ref-title { font-weight: 600; color: var(--text); font-size: var(--fs-sm); }
.ref-cite { font-size: var(--fs-xs); color: var(--text-faint); margin-top: 2px; }
.ref-note { font-size: var(--fs-xs); color: var(--text-dim); margin-top: 2px; }

/* ---- Glossary ------------------------------------------------------------- */
.glossary-toolbar { margin-bottom: var(--sp-4); max-width: 320px; }
.glossary-search { width: 100%; }

/* ---- Quiz ----------------------------------------------------------------- */
.quiz-list { display: flex; flex-direction: column; }
.quiz-score-line { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); margin-bottom: var(--sp-4); flex-wrap: wrap; }
.quiz-num { color: var(--accent); }

/* ---- Trade-off instrument ------------------------------------------------- */
.tradeoff-card { border-color: color-mix(in srgb, var(--covert) 22%, var(--border)); }
.tradeoff-card .tri-meters { margin-bottom: var(--sp-3); }
.cap-breakdown { display: flex; flex-direction: column; gap: 2px; margin-bottom: var(--sp-3); padding: var(--sp-2) var(--sp-3); background: var(--surface-inset); border-radius: var(--r-md); }
.cap-row { display: grid; grid-template-columns: 8.5em 6.5em 1fr; gap: var(--sp-2); align-items: baseline; font-size: var(--fs-xs); }
.cap-label { color: var(--text-dim); font-weight: 600; }
.cap-val { color: var(--accent); text-align: right; }
.cap-note { font-size: var(--fs-xs); }
/* The note is what distinguishes the three capacity numbers from one another —
   "structural maximum for this carrier" vs "what this encoder emits" vs
   "recovered correctly, after errors" — and three-numbers-not-one is the whole
   teaching point of the panel. `display: none` at 480px dropped it, which is a
   loss of information at the narrow widths SC 1.4.10 Reflow is about. Wrapping
   it onto its own row costs a line of height and keeps the meaning. */
@media (max-width: 480px) {
  .cap-row { grid-template-columns: 1fr auto; row-gap: 0; }
  .cap-note { grid-column: 1 / -1; }
}
/* Still decorative reference, and deliberately below the axis in weight — but
   --border-faint was 1.11:1 against a card, which is not a grid so much as a
   rumour. --border-strong is 1.79:1 and stays subordinate to the 3.55:1 axis. */
.chart-grid { stroke: var(--border-strong); stroke-width: 1; stroke-dasharray: 2 3; }
.curve-xlabel { text-align: center; margin-top: 2px; }

/* ---- Lab notebook (export) ------------------------------------------------ */
.notebook { margin-top: var(--sp-4); border-top: 1px solid var(--border-faint); padding-top: var(--sp-3); }
/* 2px of padding takes the <summary>'s 21px line box past the 24px minimum of
   WCAG 2.2 SC 2.5.8, so it does not have to lean on the Spacing exception. */
.notebook-summary { cursor: pointer; font-size: var(--fs-sm); color: var(--accent); font-weight: 600; padding: 2px 0; }
.notebook-summary:hover { text-decoration: underline; }
.notebook-body { margin-top: var(--sp-3); }
.notebook-actions { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; margin-bottom: var(--sp-2); }
/* This was a scroll container on BOTH axes: `max-height: 260px` against 340-400px
   of content, and `white-space: pre` on lines as long as the shareable link.
   Safari does not add scroll containers to the sequential focus order, so a
   keyboard-only user could not reach the bottom of the exhibit's own take-home
   artefact (2.1.1). Wrapping removes the horizontal axis, so what is left is one
   ordinary vertical scroller of the kind this project already handles by making
   it a labelled focusable region — the tabindex/role/aria-label that needs is
   markup, and belongs in tradeoffView.js. */
.notebook-md { background: var(--surface-inset); border: 1px solid var(--border-faint); border-radius: var(--r-md); padding: var(--sp-3); overflow-x: auto; font-size: var(--fs-xs); color: var(--text-dim); max-height: 260px; overflow-y: auto; }
.notebook-md code { background: none; border: none; padding: 0; color: inherit; white-space: pre-wrap; overflow-wrap: anywhere; }

/* ---- Detector Validation Lab ---------------------------------------------- */
/* minmax()'s first argument is a hard floor: auto-fill collapses to one track,
   but the track keeps its 320px base size and overflows a 288px content column,
   scrolling the whole page sideways at the 320x256 viewport the reflow test uses
   (1.4.10). min(320px, 100%) lets the floor collapse instead. */
.validation-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr)); gap: var(--sp-4); }
.val-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
.val-auc { display: flex; flex-direction: column; align-items: center; line-height: 1; }
.val-auc-num { font-size: var(--fs-xl); font-weight: 800; }
.val-auc-lab { font-size: var(--fs-xs); color: var(--text-faint); letter-spacing: 0.08em; }
.val-auc.good .val-auc-num { color: var(--ok); }
.val-auc.warn .val-auc-num { color: var(--warn); }
.val-auc.bad .val-auc-num { color: var(--danger); }
.val-body { display: flex; gap: var(--sp-3); align-items: center; flex-wrap: wrap; margin: var(--sp-3) 0; }
.roc-chart { width: 150px; height: 150px; flex: none; }
.confusion { display: grid; grid-template-columns: auto 1fr 1fr; gap: 3px; font-size: var(--fs-xs); flex: 1 1 160px; }
.cm-corner { }
.cm-colhead, .cm-rowhead { color: var(--text-faint); font-size: 10px; display: flex; align-items: center; justify-content: center; text-align: center; }
.cm-rowhead { justify-content: flex-end; padding-right: 4px; }
.cm-cell { padding: var(--sp-2); border-radius: var(--r-sm); display: grid; place-items: center; }
.cm-cell.tp { background: color-mix(in srgb, var(--ok) 22%, transparent); }
.cm-cell.tn { background: color-mix(in srgb, var(--ok) 12%, transparent); }
.cm-cell.fp { background: color-mix(in srgb, var(--danger) 20%, transparent); }
.cm-cell.fn { background: color-mix(in srgb, var(--danger) 20%, transparent); }
.cm-v { font-weight: 700; font-size: var(--fs-md); }
.val-rates { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-2); margin-top: var(--sp-2); }
.val-rate { display: flex; justify-content: space-between; gap: var(--sp-2); font-size: var(--fs-xs); }
.val-rate-label { color: var(--text-faint); }
.val-rate-val.good { color: var(--ok); }
.val-rate-val.warn { color: var(--warn); }
.val-rate-val.bad { color: var(--danger); }

/* ---- Learning outcomes ---------------------------------------------------- */
.outcomes { margin-top: var(--sp-4); padding: var(--sp-3) var(--sp-4); background: color-mix(in srgb, var(--accent) 7%, var(--surface-1)); border: 1px solid color-mix(in srgb, var(--accent) 25%, var(--border)); border-radius: var(--r-md); max-width: 68ch; }
.outcomes-title { display: block; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.1em; color: var(--accent); font-weight: 700; margin-bottom: var(--sp-2); }
.outcomes-list { margin: 0; padding-left: 1.2em; }
.outcomes-list li { font-size: var(--fs-sm); color: var(--text-dim); }

/* ---- Detection Challenge --------------------------------------------------- */
.challenge-bar { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; margin-bottom: var(--sp-4); }
.challenge-tally { margin-bottom: var(--sp-5); }
.challenge-list { display: flex; flex-direction: column; gap: var(--sp-4); }
.challenge-case { border-left: 3px solid var(--border-strong); }
.challenge-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); margin-bottom: var(--sp-3); flex-wrap: wrap; }
.challenge-answer { margin-top: var(--sp-4); padding-top: var(--sp-3); border-top: 1px solid var(--border-faint); }
.challenge-q { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-3); font-size: var(--fs-sm); color: var(--text-dim); flex-wrap: wrap; }
.challenge-q .ctrl { min-width: 220px; }
.challenge-calls { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.challenge-reveal { margin-top: var(--sp-4); padding: var(--sp-4); border-radius: var(--r-md); border: 1px solid var(--border); background: var(--surface-inset); }
.challenge-reveal.ok { border-color: color-mix(in srgb, var(--ok) 45%, var(--border)); }
.challenge-reveal.bad { border-color: color-mix(in srgb, var(--danger) 45%, var(--border)); }
.reveal-verdict { display: flex; gap: var(--sp-2); flex-wrap: wrap; margin-bottom: var(--sp-3); }
.reveal-detector { margin-top: var(--sp-3); padding-top: var(--sp-3); border-top: 1px solid var(--border-faint); }
.reveal-fired { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin: var(--sp-2) 0; }
.reveal-named { font-size: var(--fs-sm); color: var(--text-dim); margin-top: var(--sp-2); }

/* ---- HTTP header channel -------------------------------------------------- */
.header-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.http-reqs { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
.http-req { flex: 1 1 220px; min-width: 200px; background: var(--surface-inset); border: 1px solid var(--border); border-radius: var(--r-md); padding: var(--sp-2) var(--sp-3); }
.http-req-line { color: var(--accent); font-size: var(--fs-sm); margin-bottom: var(--sp-2); }
.http-headers { display: flex; flex-direction: column; gap: 1px; }
.http-header { display: flex; justify-content: space-between; gap: var(--sp-2); font-size: var(--fs-xs); padding: 1px 4px; border-radius: var(--r-sm); }
/* `.hh-val` holds the actual header values — the content this module asks the
   reader to inspect — and it used to be --text-faint at `opacity: 0.7`, which
   composites to 3.34:1 on --surface-inset and 2.96:1 on a highlighted covert row
   (1.4.3). Lightening the token did not rescue it and never could: opacity
   multiplies whatever margin the token has. De-emphasis now runs the other way:
   the name is the quiet part and the value is legible everywhere — 9.46:1 on
   --surface-inset, 7.64:1 on a covert row. */
.http-header .hh-name { color: var(--text-faint); }
.http-header .hh-val { color: var(--text-dim); }
.http-header.reorderable { background: color-mix(in srgb, var(--covert) 12%, transparent); }
.http-header.reorderable .hh-name { color: var(--covert); font-weight: 650; }

/* ---- Carrier Atlas -------------------------------------------------------- */
.atlas-group-title { font-size: var(--fs-lg); margin: var(--sp-6) 0 var(--sp-3); }
.atlas-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr)); gap: var(--sp-4); }
.atlas-card.concept { border-style: dashed; }
.atlas-card-head { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--sp-2); margin-bottom: var(--sp-2); }
.atlas-card-title { font-size: var(--fs-md); }
.atlas-badges { display: flex; gap: 4px; flex-wrap: wrap; flex: none; }
.atlas-kv { display: flex; gap: var(--sp-2); font-size: var(--fs-xs); margin-top: var(--sp-2); }
.atlas-kv-label { color: var(--text-faint); font-weight: 650; flex: none; min-width: 8.5em; text-transform: uppercase; letter-spacing: 0.04em; }
.atlas-kv-value { color: var(--text-dim); }
.atlas-open { margin-top: var(--sp-3); }
.atlas-conceptmark { display: block; margin-top: var(--sp-3); font-size: var(--fs-xs); color: var(--warn); }
.atlas-cite { font-size: var(--fs-xs); margin-top: var(--sp-3); }
.taxo-family { margin-top: var(--sp-4); }
.taxo-fam-title { font-size: var(--fs-base); margin-bottom: var(--sp-2); }
.fidelity-card { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-2); margin-top: var(--sp-3); }
.fidelity-col { background: var(--surface-inset); border-radius: var(--r-sm); padding: var(--sp-2); border-top: 2px solid var(--border-strong); }
.fidelity-col.fid-good { border-top-color: var(--ok); }
.fidelity-col.fid-warn { border-top-color: var(--warn); }
.fidelity-col.fid-neutral { border-top-color: var(--accent-2); }
.fidelity-col-title { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-faint); font-weight: 650; margin-bottom: 4px; }
.fidelity-col ul { margin: 0; padding-left: 1em; }
.fidelity-col li { font-size: var(--fs-xs); color: var(--text-dim); }
@media (max-width: 560px) { .fidelity-card { grid-template-columns: 1fr; } }

/* ---- Shared-Resource Matrix ----------------------------------------------- */
.srm-table td, .srm-table th { vertical-align: middle; }
.srm-level { color: var(--text-faint); font-size: var(--fs-xs); }
.srm-cell { text-align: center; }
.srm-rm-pair { display: inline-flex; gap: 4px; }
.srm-rm { width: 28px; height: 28px; border-radius: var(--r-sm); border: 1px solid var(--border-control); background: var(--surface-inset); color: var(--text-faint); font-family: var(--font-mono); font-weight: 700; cursor: pointer; }
.srm-rm:hover { border-color: var(--accent); }
.srm-rm.on { background: var(--accent); color: var(--text-invert); border-color: transparent; }
.srm-channel-row td { background: color-mix(in srgb, var(--covert) 10%, transparent); }
.srm-flag { color: var(--covert); font-weight: 700; font-size: var(--fs-xs); }
.srm-finding { border-left: 3px solid var(--covert); padding: var(--sp-2) var(--sp-3); background: var(--surface-inset); border-radius: var(--r-sm); margin-top: var(--sp-2); }
.srm-finding-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); margin-bottom: 4px; }
.srm-finding-name { font-weight: 650; }
.srm-finding p { font-size: var(--fs-sm); }

/* ---- Per-channel accents --------------------------------------------------
   Each channel section re-points --accent so a module has its own identity.
   Scoped to #sec-<id>, so the global brand accent in base.css is untouched and
   every other surface (nav, header, analysis views) keeps the house colour.

   These values are deliberately distinct from the SEMANTIC tokens in base.css
   (--covert, --ok, --warn, --danger, --info, --bit-0, --bit-1, --accent-2),
   because those appear side by side with the accent inside a channel view.
   Colour is decorative only — it is never the sole carrier of meaning.
   -------------------------------------------------------------------------- */
#sec-dns      { --accent: #2dd4bf; --accent-deep: #14b8a6; } /* teal   */
#sec-timing   { --accent: #22d3ee; --accent-deep: #06b6d4; } /* cyan   */
#sec-storage  { --accent: #4ade80; --accent-deep: #22c55e; } /* green  */
#sec-ordering { --accent: #a78bfa; --accent-deep: #8b5cf6; } /* violet */
#sec-http     { --accent: #e879f9; --accent-deep: #d946ef; } /* fuchsia*/
#sec-icmp     { --accent: #f472b6; --accent-deep: #ec4899; } /* pink   */
#sec-hopping  { --accent: #818cf8; --accent-deep: #6366f1; } /* indigo */
#sec-stego    { --accent: #bef264; --accent-deep: #a3e635; } /* lime   */
#sec-metadata { --accent: #5eead4; --accent-deep: #2dd4bf; } /* mint   */
#sec-physical { --accent: #fb923c; --accent-deep: #f97316; } /* orange */
#sec-cache    { --accent: #c084fc; --accent-deep: #a855f7; } /* purple */

/* ---- Air-gap optical ------------------------------------------------------ */
.ook-strip { display: flex; flex-wrap: nowrap; gap: 6px; padding: var(--sp-2) 0; }
.ook-sym { display: flex; flex-direction: column; align-items: center; gap: 3px; min-width: 30px; padding: 4px 2px; border-radius: var(--r-sm); background: var(--surface-inset); }
.ook-sym.lit { background: color-mix(in srgb, var(--accent) 18%, var(--surface-inset)); }
.ook-sym.err { outline: 1.5px solid var(--bit-err); }
.ook-lamp { font-size: var(--fs-md); line-height: 1; color: var(--text-faint); }
.ook-sym.lit .ook-lamp { color: var(--accent); text-shadow: 0 0 8px color-mix(in srgb, var(--accent) 70%, transparent); }
/* The lux reading is a measured value, and on a lit symbol it sits on
   `color-mix(--accent 18%, --surface-inset)` — a tint bright enough to take
   --text-faint under 4.5:1 in every section (4.24:1 on physical's orange, 3.20:1
   on stego's lime, measured with --text-faint at #7c8da2). --text-dim clears it
   everywhere: 6.12:1 at worst, 9.46:1 on an unlit symbol. */
.ook-lux { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--text-dim); }
/* The lit lamp tints its own background warm, which drags --text-faint under 4.5:1
   there even though it clears on every flat surface. Scoped, so the unlit lamp keeps
   the quieter token and the two states stay visually distinct. */
.ook-sym.lit .ook-lux { color: var(--text-dim); }
.ook-bit { font-family: var(--font-mono); font-weight: 700; font-size: var(--fs-xs); padding: 1px 4px; border-radius: var(--r-sm); }
.ook-bit.b0 { color: var(--bit-0); }
.ook-bit.b1 { color: var(--bit-1); }
.ook-bit.err { outline: 1.5px solid var(--bit-err); }

/* ---- Shared cache --------------------------------------------------------- */
.data-table tr.row-err td { background: color-mix(in srgb, var(--bit-err) 14%, transparent); }

/* ---- Carrier Atlas: described-only carriers with a sibling deep dive ------- */
.atlas-concept-footer { display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-2); }
.atlas-deepdive-note { margin: 0; font-size: var(--fs-xs); }
a.atlas-deepdive { text-decoration: none; }

/* ---- ICMP echo channel ---------------------------------------------------- */
/* `ch` tracks font-size but not letter-spacing or word-spacing, so applying the
   WCAG 1.4.12 Text Spacing test values widened this hex string inside a box that
   did not widen with it and clipped bytes that nothing else could recover — the
   cell has no title and no expander, and icmpView.js has already truncated the
   payload before it gets here. Wrapping keeps the width budget and loses
   nothing at any spacing. */
.icmp-data { max-width: 34ch; white-space: normal; overflow-wrap: anywhere; }
.icmp-stamp { color: var(--text-dim); }
.icmp-payload { color: var(--text-dim); }
.icmp-payload.covert { color: var(--covert); }

/* ---- Protocol-hopping channel --------------------------------------------- */
/* The flow list sits directly inside a .table-wrap, which is built for tables
   and gives its child no padding — so it needs its own. */
.hop-stream-wrap { padding: var(--sp-3); }
.hop-stream { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.hop-flow {
  display: flex; flex-direction: column; gap: 2px; min-width: 92px;
  padding: var(--sp-2); border: 1px solid var(--border-faint);
  border-radius: var(--r-md); background: var(--surface-1);
}
.hop-flow.covert { border-color: color-mix(in srgb, var(--covert) 40%, transparent); background: color-mix(in srgb, var(--covert) 8%, var(--surface-1)); }
.hop-flow.sync { border-style: dashed; }
.hop-proto { font-size: var(--fs-sm); font-weight: 650; }
/* --text-faint has 5.15:1 on --surface-1 to spend, and the covert tint a hopping
   flow is drawn on spends it: `color-mix(--covert 8%, --surface-1)` takes the
   token to 4.42:1 (1.4.3). Both of these appear on covert
   flows — .hop-bits.empty is what the rendezvous flow shows, and that flow is
   always covert — so both move to --text-dim: 7.40:1 on the tint, 8.62:1 off it,
   and still clearly subordinate to the --covert bits and the --text protocol. */
.hop-dest { font-size: var(--fs-xs); color: var(--text-dim); }
.hop-bits { font-size: var(--fs-xs); color: var(--covert); letter-spacing: 0.08em; }
.hop-bits.empty { color: var(--text-dim); }

/* Transition matrix. The count is always rendered as text; the tint is a
   redundant cue only, so the table stays readable without colour. */
.transition-matrix td { text-align: center; }
.transition-matrix th[scope="row"] { color: var(--text-dim); font-weight: 600; }
.transition-matrix .tm-cell.used {
  background: color-mix(in srgb, var(--accent) calc(var(--tm-fill, 0) * 26%), transparent);
}
/* The comment above is right that the count is always text — and that text was
   the thing failing. --text-faint over the striped half of the hatch measures
   4.00:1 (1.4.3): the hatch lightens the background by more than the token has
   margin to give, even after the token was lightened. --text-dim over the same
   stripe is 6.70:1, and still reads as recessed against a live cell's --text. */
.transition-matrix .tm-cell.diag {
  background: repeating-linear-gradient(45deg,
    transparent, transparent 4px,
    color-mix(in srgb, var(--text-faint) 18%, transparent) 4px,
    color-mix(in srgb, var(--text-faint) 18%, transparent) 8px);
  color: var(--text-dim);
}

/* ---- Active Warden lab ----------------------------------------------------- */
#sec-warden { --accent: #38bdf8; --accent-deep: #0ea5e9; } /* sky */
.warden-switches .control-group { display: grid; gap: var(--sp-3); }
.warden-buttons { display: flex; gap: var(--sp-2); margin-top: var(--sp-3); flex-wrap: wrap; }
.warden-table th[scope="row"] { color: var(--text); font-weight: 650; }
.warden-table .obs-drop { color: var(--ok); }
.warden-why { display: block; margin-top: 4px; font-size: var(--fs-xs); color: var(--text-dim); white-space: normal; max-width: 40ch; }

/* ---- Learned-detector comparison ------------------------------------------ */
.learned-card { margin-top: var(--sp-5); }
.learned-table th[scope="row"] { color: var(--text); font-weight: 650; white-space: normal; max-width: 24ch; }
.learned-table .classical-row td, .learned-table .classical-row th { border-top: 2px solid var(--border); }
.val-auc-cell.good { color: var(--ok); }
.val-auc-cell.warn { color: var(--warn); }
.val-auc-cell.bad  { color: var(--danger); }
.rep-cell.hop { font-size: var(--fs-xs); font-weight: 650; color: var(--covert); }
.rep-cell.hop.sync { color: var(--text-dim); font-weight: 500; }

/* ---- Case Studies ---------------------------------------------------------- */
#sec-cases { --accent: #fb7185; --accent-deep: #f43f5e; } /* rose */
.case-grid { display: grid; gap: var(--sp-4); }
@media (min-width: 1100px) { .case-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.case-card { display: flex; flex-direction: column; gap: var(--sp-3); }
/* The printer entry is the one no detector here reaches; it reads as an aside
   rather than a finding, and the dashed edge says so without relying on colour. */
.case-card.case-none { border-style: dashed; }
.case-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-3); }
.case-head .card-title { margin-bottom: 2px; }
.case-when { font-size: var(--fs-xs); color: var(--text-dim); }
.case-sub {
  font-size: var(--fs-xs); color: var(--text-dim); font-weight: 650;
  text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: var(--sp-2);
}
.case-source { font-size: var(--fs-xs); color: var(--text-dim); }
.case-link { color: var(--accent); font-weight: 600; }
.case-link:hover, .case-link:focus-visible { text-decoration: underline; }
.case-fires .block-list { margin: 0; }
.case-caveat {
  display: flex; gap: 6px; font-size: var(--fs-xs); color: var(--text-dim);
  border-top: 1px solid var(--border-faint); padding-top: var(--sp-3); margin-top: auto;
}
.case-caveat-tag {
  color: var(--warn); font-weight: 650; flex: none;
  text-transform: uppercase; letter-spacing: 0.06em;
}
