/* ==========================================================================
   NHID-Clinical component styles
   --------------------------------------------------------------------------
   Loaded AFTER /nhid-clinical-ui.css and /assets/css/premium.css.

   Classes are named for what they are on the page. They used to carry a `ctl-`
   prefix, for a visual language that is no longer the site's identity; the
   prefix outlived it and is gone. No legacy selector is overridden, so
   unmigrated routes keep rendering from the existing stylesheet.

   Token values are taken verbatim from
   docs/cinematic-trust-lattice-handoff/design-system.md §3.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */

:root {
  /* Surfaces and ink */
  --panel-ink-950: #07111f;
  --panel-ink-900: #0b1d35;
  --panel-ink-800: #102b48;
  --panel-text-strong: var(--ink);        /* alias -> canonical */
  --panel-text: var(--body);              /* alias -> canonical */
  --panel-text-muted: #5b636c;            /* muted charcoal; no canonical equivalent */
  --panel-paper: var(--paper);            /* alias -> canonical warm paper */
  --panel-canvas: var(--mist);            /* alias -> canonical */
  --panel-mist: var(--mist);              /* alias -> canonical */
  --panel-line: var(--line);              /* alias -> canonical grey border */

  /* Semantic roles */
  --panel-cobalt: #1e63db;
  --panel-cobalt-hover: #164da8;
  --panel-cobalt-soft: #e8f0ff;
  --panel-teal: var(--teal);              /* alias -> canonical accent */
  --panel-teal-bright: #55d9cb;
  --panel-teal-soft: var(--teal-soft);    /* alias -> canonical */
  --panel-amber: #986600;
  --panel-amber-soft: #fff5d7;
  --panel-red: #b42318;
  --panel-red-soft: #fff0ef;
  --panel-focus: #0b57d0;

  /* Shape and elevation */
  --panel-radius-md: 10px;
  --panel-radius-lg: 14px;
  --panel-shadow-1: 0 2px 8px rgba(16, 35, 61, 0.08);
  --panel-shadow-2: 0 5px 16px rgba(16, 35, 61, 0.12);
  --panel-grid-line: rgba(28, 32, 38, 0.07);   /* neutral, not blue */

  /* Typography and measure */
  --mono: "IBM Plex Mono", ui-monospace, monospace;
  --prose-measure: 68ch;
  --wide-container-max: 1320px;

  /* Motion — §8: 160–220ms deliberate transitions */
  --motion-duration-fast: 160ms;
  --motion-duration: 200ms;
  --motion-ease: cubic-bezier(0.2, 0.6, 0.3, 1);
}

[data-theme="dark"] {
  --panel-text-strong: #f2f7fc;
  --panel-text: #c2d0df;
  --panel-text-muted: #96abc0;
  --panel-paper: #102038;
  --panel-canvas: #07111f;
  --panel-mist: #0d1c30;
  --panel-line: #29445e;
  --panel-cobalt: #79b7ff;
  --panel-cobalt-hover: #afd3ff;
  --panel-cobalt-soft: #142e51;
  --panel-teal: #55d9cb;
  --panel-teal-bright: #75ece0;
  --panel-teal-soft: #103c3b;
  --panel-amber: #ffd26c;
  --panel-amber-soft: #3a2c10;
  --panel-red: #ffaaa4;
  --panel-red-soft: #411f25;
  --panel-focus: #a3caff;
  --panel-shadow-1: 0 2px 10px rgba(0, 0, 0, 0.24);
  --panel-shadow-2: 0 6px 20px rgba(0, 0, 0, 0.34);
  --panel-grid-line: rgba(144, 211, 255, 0.09);
}

/* --------------------------------------------------------------------------
   2. Typography scale (§4)
   -------------------------------------------------------------------------- */

.display-title {
  font-family: var(--sans);
  font-weight: 700;
  font-size: clamp(2.1rem, 3.6vw, 3.4rem);
  line-height: 1.03;
  letter-spacing: -0.022em;
  text-wrap: balance;
  color: var(--panel-text-strong);
  margin: 0;
}

.page-heading {
  font-family: var(--sans);
  font-weight: 700;
  font-size: clamp(2rem, 3.2vw, 3.25rem);
  line-height: 1.08;
  letter-spacing: -0.018em;
  text-wrap: balance;
  color: var(--panel-text-strong);
  margin: 0;
}

.section-title {
  font-family: var(--sans);
  font-weight: 700;
  font-size: clamp(1.35rem, 1.9vw, 1.75rem);
  line-height: 1.18;
  letter-spacing: -0.012em;
  color: var(--panel-text-strong);
  margin: 0;
}

.body-text {
  font-family: var(--sans);
  font-weight: 400;
  font-size: 1.0625rem;
  line-height: 1.72;
  color: var(--panel-text);
}

.lede-text {
  font-family: var(--sans);
  font-weight: 400;
  font-size: clamp(1.05rem, 1.35vw, 1.25rem);
  line-height: 1.65;
  color: var(--panel-text);
  max-width: 58ch;
}

.meta-label {
  font-family: var(--sans);
  font-weight: 600;
  font-size: 0.8125rem;
  line-height: 1.4;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--panel-text-muted);
}

.data-text,
.data-text code,
code.data-text {
  font-family: var(--mono);
  font-weight: 400;
  font-size: 0.875rem;
  line-height: 1.6;
  font-variant-numeric: tabular-nums;
}

.prose-measure {
  max-width: var(--prose-measure);
}

/* Screen-reader-only. Used for table captions that would be redundant visually
   but are required for non-visual navigation. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --------------------------------------------------------------------------
   3. Layout primitives (§5)
   -------------------------------------------------------------------------- */

.wide-container {
  width: 100%;
  max-width: var(--wide-container-max);
  margin-inline: auto;
  padding-inline: clamp(1rem, 3vw, 2.5rem);
}

/* Quiet 42px technical grid — hero and lattice surfaces only, never global */
.surface-technical-grid {
  background-color: var(--panel-ink-950);
  background-image:
    linear-gradient(to right, var(--panel-grid-line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--panel-grid-line) 1px, transparent 1px);
  background-size: 42px 42px;
}

.surface-canvas { background-color: var(--panel-canvas); }
.surface-mist   { background-color: var(--panel-mist); }
.surface-paper  { background-color: var(--panel-paper); }

/* On dark surfaces the ink tokens do not apply — set explicit reading colors */
.on-dark { color: #dce8f5; }
.on-dark .display-title,
.on-dark .page-heading,
.on-dark .section-title { color: #f7fbff; }
.on-dark .lede-text,
.on-dark .body-text { color: #c2d4e6; }
.on-dark .meta-label { color: var(--panel-teal-bright); }

/* --------------------------------------------------------------------------
   4. Hero (§5, §6 CtlHero)
   -------------------------------------------------------------------------- */

.hero-band {
  position: relative;
  overflow: clip;
  padding-block: clamp(3.5rem, 8vw, 7rem);
}

.hero-band-inner {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
}

.hero-band-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 2rem;
}

/* Boundary note — the non-certification line. Text, never a badge. */
.boundary-note {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  margin-top: 1.75rem;
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--panel-text-muted);
}
.on-dark .boundary-note { color: #9fb4c9; }

@media (max-width: 900px) {
  .hero-band-inner { grid-template-columns: minmax(0, 1fr); }
}

/* --------------------------------------------------------------------------
   5. Controls — 6px small, 10px panels, 14px major viz (§2 geometry)
   No pills.
   -------------------------------------------------------------------------- */

.action-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 44px;                 /* §7 touch target */
  padding: 0.7rem 1.4rem;
  border-radius: var(--radius);
  border: 1px solid transparent;
  font-family: var(--sans);
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--motion-duration) var(--motion-ease),
              border-color var(--motion-duration) var(--motion-ease),
              transform var(--motion-duration-fast) var(--motion-ease);
}

.action-button-primary {
  background: var(--panel-cobalt);
  color: #ffffff;
}
[data-theme="dark"] .action-button-primary { color: #06152b; }
.action-button-primary:hover { background: var(--panel-cobalt-hover); transform: translateY(-1px); }

.action-button-secondary {
  background: transparent;
  color: var(--panel-cobalt);
  border-color: var(--panel-cobalt);
}
.action-button-secondary:hover { background: var(--panel-cobalt-soft); transform: translateY(-1px); }

.on-dark .action-button-secondary { color: #a8ccff; border-color: #4f7fc4; }
.on-dark .action-button-secondary:hover { background: rgba(30, 99, 219, 0.18); }

/* --------------------------------------------------------------------------
   6. Focus — §7: minimum 3px solid, visible offset, never glow-only
   -------------------------------------------------------------------------- */

.scope-note a:focus-visible,
.scope-note button:focus-visible,
.scope-note input:focus-visible,
.scope-note select:focus-visible,
.scope-note textarea:focus-visible,
.scope-note summary:focus-visible,
.scope-note [tabindex]:focus-visible,
a.action-button:focus-visible,
button.action-button:focus-visible,
.skip-link:focus-visible {
  outline: 3px solid var(--panel-focus);
  outline-offset: 3px;
  border-radius: 2px;
}

/* Skip link — visible on focus, not permanently hidden from keyboard users */
.skip-link {
  position: absolute;
  left: 0.75rem;
  top: -100%;
  z-index: 999;
  padding: 0.75rem 1.25rem;
  background: var(--panel-paper);
  color: var(--panel-text-strong);
  border: 1px solid var(--panel-line);
  border-radius: var(--radius);
  font-weight: 600;
  text-decoration: none;
  transition: top var(--motion-duration-fast) var(--motion-ease);
}
.skip-link:focus { top: 0.75rem; }

/* --------------------------------------------------------------------------
   7. Metric rail (§6 CtlMetricRail)
   Values must come from repository sources — see the drift guard.
   -------------------------------------------------------------------------- */

.metric-rail {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 1px;
  background: var(--panel-line);
  border-block: 1px solid var(--panel-line);
}

.metric {
  background: var(--panel-canvas);
  padding: clamp(1.25rem, 2.5vw, 2rem) clamp(1rem, 2vw, 1.75rem);
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.metric-value {
  font-family: var(--sans);
  font-size: clamp(1.75rem, 3vw, 2.5rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--panel-cobalt);
  font-variant-numeric: tabular-nums;
}

.metric-label {
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--panel-text-muted);
}

/* --------------------------------------------------------------------------
   8. Status — §7: never hue alone. Text + icon/pattern + color.
   -------------------------------------------------------------------------- */

.evidence-status {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.25rem 0.6rem;
  border-radius: var(--radius);
  border: 1px solid currentColor;
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.35;
}
.evidence-status::before { font-family: var(--mono); font-weight: 700; }

.evidence-status-verified { color: var(--panel-teal);   background: var(--panel-teal-soft); }
.evidence-status-verified::before { content: "\2713"; }          /* ✓ */

.evidence-status-review   { color: var(--panel-amber);  background: var(--panel-amber-soft); }
.evidence-status-review::before { content: "\26A0"; }            /* ⚠ */

.evidence-status-blocked  { color: var(--panel-red);    background: var(--panel-red-soft); }
.evidence-status-blocked::before { content: "\2717"; }           /* ✗ */

.evidence-status-info     { color: var(--panel-cobalt); background: var(--panel-cobalt-soft); }
.evidence-status-info::before { content: "\2022"; }              /* • */

/* --------------------------------------------------------------------------
   9. Panels, control cards, evidence frames (§6)
   -------------------------------------------------------------------------- */

.panel {
  background: var(--panel-paper);
  border: 1px solid var(--panel-line);
  border-radius: var(--panel-radius-md);
  padding: clamp(1.25rem, 2.5vw, 1.75rem);
  box-shadow: var(--panel-shadow-1);
}

.panel-viz { border-radius: var(--panel-radius-lg); }

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 1.25rem;
}

.control-card { display: flex; flex-direction: column; gap: 0.6rem; }

.control-card-id {
  font-family: var(--mono);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--panel-teal);
}

/* Evidence frame: claim / evidence / limitation / source */
.evidence-frame {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  border-left: 3px solid var(--panel-cobalt);
  padding-left: 1.1rem;
}
.evidence-limitation {
  font-size: 0.9375rem;
  color: var(--panel-text-muted);
  border-top: 1px solid var(--panel-line);
  padding-top: 0.75rem;
}

/* Trace panel — raw text stays selectable and scrollable */
.evidence-trace-panel {
  background: var(--panel-ink-900);
  border: 1px solid var(--panel-line);
  border-radius: var(--panel-radius-md);
  padding: 1rem 1.15rem;
  overflow-x: auto;
  color: #d6e6f6;
}
.evidence-trace-panel pre,
.evidence-trace-panel code {
  font-family: var(--mono);
  font-size: 0.8125rem;
  line-height: 1.65;
  user-select: text;
  white-space: pre;
}

/* --------------------------------------------------------------------------
   10. Document shell (§5, template 3)
   -------------------------------------------------------------------------- */

.doc-shell {
  display: grid;
  grid-template-columns: minmax(12rem, 16rem) minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: start;
}

.doc-toc {
  position: sticky;
  top: 1.5rem;
  align-self: start;
  max-height: calc(100vh - 3rem);
  overflow-y: auto;
  font-size: 0.9375rem;
  line-height: 1.7;
}
.doc-toc ol, .doc-toc ul { list-style: none; margin: 0; padding: 0; }
.doc-toc a { color: var(--panel-text); text-decoration: none; display: block; padding: 0.2rem 0; }
.doc-toc a:hover { color: var(--panel-cobalt); text-decoration: underline; }
.doc-toc [aria-current="true"] { color: var(--panel-cobalt); font-weight: 600; }

.doc-body { max-width: var(--prose-measure); }

/* Normative callout — for MUST/SHOULD spec text */
.normative-block {
  background: var(--panel-cobalt-soft);
  border-left: 3px solid var(--panel-cobalt);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: 1rem 1.25rem;
  margin-block: 1.25rem;
}

/* Wide content never scrolls the page body sideways */
.scroll-x { overflow-x: auto; max-width: 100%; }

.content-table { width: 100%; border-collapse: collapse; font-size: 0.9375rem; }
.content-table th, .content-table td {
  text-align: left;
  padding: 0.65rem 0.85rem;
  border-bottom: 1px solid var(--panel-line);
  vertical-align: top;
}
.content-table th { font-weight: 700; color: var(--panel-text-strong); }
.content-table td { color: var(--panel-text); }

@media (max-width: 900px) {
  .doc-shell { grid-template-columns: minmax(0, 1fr); }
  .doc-toc { position: static; max-height: none; }
}

/* --------------------------------------------------------------------------
   11. Trust Lattice (§6 TrustLattice, §8 motion)
   -------------------------------------------------------------------------- */

.diagram-layers { width: 100%; height: auto; display: block; }

/* One token travels the five layers once, 2.4–3.2s, on entry only */
.diagram-token {
  animation: diagram-token-travel 2.8s var(--motion-ease) 1 both;
}

@keyframes diagram-token-travel {
  from { opacity: 0; transform: translateY(-58px); }
  12%  { opacity: 1; }
  to   { opacity: 1; transform: translateY(96px); }
}

/* Text/list equivalent for the diagram — §7 diagrams requirement */
.diagram-layers-alt {
  margin: 1rem 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  font-size: 0.875rem;
}
.diagram-layers-alt li {
  border: 1px solid var(--panel-line);
  border-radius: var(--radius);
  padding: 0.3rem 0.6rem;
  color: var(--panel-text-muted);
}

/* --------------------------------------------------------------------------
   12. Loading / empty / error states (app-wide-system.md)
   -------------------------------------------------------------------------- */

.phase-state {
  border: 1px dashed var(--panel-line);
  border-radius: var(--panel-radius-md);
  padding: 1.5rem;
  color: var(--panel-text-muted);
  text-align: left;
}
.phase-state-title { font-weight: 700; color: var(--panel-text-strong); margin: 0 0 0.35rem; }

.skeleton {
  background: linear-gradient(90deg, var(--panel-mist), var(--panel-canvas), var(--panel-mist));
  border-radius: var(--radius);
  height: 0.9rem;
  margin-block: 0.4rem;
}

/* --------------------------------------------------------------------------
   13. Responsive + motion fallback (§7, §8)
   -------------------------------------------------------------------------- */

@media (max-width: 720px) {
  .hero-band { padding-block: clamp(2.5rem, 9vw, 4rem); }
  .hero-band-actions .action-button { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .scope-note *,
  .scope-note *::before,
  .scope-note *::after,
  .diagram-token {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
    transition-duration: 0.01ms !important;
  }
  .diagram-token { transform: none; opacity: 1; }
  .action-button:hover { transform: none; }
}

@media (forced-colors: active) {
  .action-button,
  .panel,
  .evidence-status { border: 1px solid CanvasText; }
}

/* ── Regulatory evidence index ─────────────────────────────────────────────
   A reference table, not a badge wall: each row states what the instrument
   establishes AND what it does not, so the page cannot be read as claiming the
   three add up to one rule. Thin rules and neutral surfaces per the evidence
   surface treatment; no colour carries meaning on its own. */
.regulatory-index{
  width:100%; border-collapse:collapse; margin-top:1.5rem;
  font-size:.9375rem; line-height:1.6;
}
.regulatory-index th, .regulatory-index td{
  text-align:left; vertical-align:top; padding:.85rem .9rem;
  border-top:1px solid var(--border,rgba(0,0,0,.14));
}
.regulatory-index thead th{
  font-size:.6875rem; text-transform:uppercase; letter-spacing:.07em;
  font-weight:600; opacity:.65; border-top:0; padding-bottom:.5rem;
}
.regulatory-index tbody th{ font-weight:600; width:11rem; }
.regulatory-index td:nth-child(2){ white-space:nowrap; font-variant-numeric:tabular-nums; opacity:.75; }
.regulatory-subnote{ display:block; font-weight:400; font-size:.8125rem; opacity:.6; margin-top:.15rem; }
.sr-only-text{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}
/* Small screens: the table becomes labelled blocks rather than a scroll. */
@media (max-width: 900px) {
  .regulatory-index thead{ display:none; }
  .regulatory-index tr{ display:block; border-top:1px solid var(--border,rgba(0,0,0,.14)); padding:.9rem 0; }
  .regulatory-index th, .regulatory-index td{ display:block; border:0; padding:.15rem 0; width:auto; }
  .regulatory-index td:nth-child(3)::before{ content:"Establishes: "; font-weight:600; }
  .regulatory-index td:nth-child(4)::before{ content:"Does not: "; font-weight:600; }
}

/* Compact hero proof line — the technical evidence, kept visually dominant
   over the regulatory reference row above it. */
.proof-line{
  margin:1.15rem 0 0; font-size:.9375rem; font-weight:600;
  letter-spacing:.01em; font-variant-numeric:tabular-nums;
}

/* ── Control-system table ──────────────────────────────────────────────────
   The controls are a control system, not a feature list, so they are set as a
   table with one row per control: what triggers it, what it decides, what it
   records. Monospace on the identifiers and reason codes per the evidence
   treatment — those are literal strings from the engine, and reading them as
   prose would be wrong. */
.control-table{
  width:100%; border-collapse:collapse; margin-top:.5rem;
  font-size:.9375rem; line-height:1.6;
}
.control-table th, .control-table td{
  text-align:left; vertical-align:top; padding:.9rem .9rem;
  border-top:1px solid var(--border,rgba(0,0,0,.14));
}
.control-table thead th{
  font-size:.6875rem; text-transform:uppercase; letter-spacing:.07em;
  font-weight:600; opacity:.65; border-top:0; padding-bottom:.5rem;
}
.control-table tbody th{ width:13rem; font-weight:400; }
.control-table-id{
  display:inline-block; font-weight:600; font-size:.875rem;
  letter-spacing:.02em;
}
.control-table-name{ display:block; font-size:.8125rem; opacity:.7; margin-top:.2rem; }
.control-table-optional{
  font-size:.6875rem; text-transform:uppercase; letter-spacing:.06em;
  border:1px solid currentColor; border-radius:2px; padding:0 .3em;
  margin-left:.4em; opacity:.7;
}
.control-table-action, .control-table-code{ font-size:.8125rem; overflow-wrap:anywhere; }
.control-table-action{ font-weight:600; }
.control-table-code{ opacity:.78; }

@media (max-width: 900px) {
  .control-table thead{ display:none; }
  .control-table tr{
    display:block; border-top:1px solid var(--border,rgba(0,0,0,.14)); padding:.9rem 0;
  }
  .control-table th, .control-table td{ display:block; border:0; padding:.2rem 0; width:auto; }
  .control-table td:nth-child(2)::before{ content:"Trigger: "; font-weight:600; }
  .control-table td:nth-child(3)::before{ content:"Decision: "; font-weight:600; }
  .control-table td:nth-child(4)::before{ content:"Evidence: "; font-weight:600; }
}

/* ── Before/after control sequences ────────────────────────────────────────
   The problem is shown as two numbered sequences side by side so the control
   boundary is visible without reading a paragraph. Built in HTML rather than
   as an image so it stays accurate, selectable, translatable and readable by
   assistive technology, and so it reflows to one column on narrow screens
   instead of scrolling. The risk step is marked by a rule and a label, never
   by colour alone. */
.sequence-pair{
  display:grid; gap:1.5rem; grid-template-columns:repeat(auto-fit,minmax(19rem,1fr));
  align-items:start;
}
.sequence{ border:1px solid var(--border,rgba(0,0,0,.14)); padding:1.1rem 1.2rem 1.3rem; }
.sequence-heading{
  font-size:.6875rem; text-transform:uppercase; letter-spacing:.08em;
  font-weight:600; opacity:.7; margin:0 0 .9rem;
}
.sequence-step-list{ list-style:none; margin:0; padding:0; counter-reset:none; }
.sequence-step{
  display:flex; align-items:baseline; gap:.7rem;
  padding:.5rem 0; border-top:1px solid var(--border,rgba(0,0,0,.09));
  font-size:.875rem; line-height:1.45;
}
.sequence-step:first-child{ border-top:0; }
.sequence-step-number{
  flex:0 0 auto; min-width:1.35rem; font-size:.6875rem; font-weight:600;
  opacity:.55; font-variant-numeric:tabular-nums;
}
.sequence-step-title{ letter-spacing:.02em; }
.sequence-step-copy{
  display:inline-block; margin-left:.5rem; font-size:.6875rem;
  border:1px solid currentColor; border-radius:2px; padding:0 .3em; opacity:.65;
}
/* The exposure step: marked structurally (heavier rule + weight), not by hue. */
.sequence-step-risk{ border-top-width:2px; font-weight:600; }
.sequence-step-risk .sequence-step-title::after{
  content:" — exposure point"; font-weight:400; opacity:.6; letter-spacing:0;
}

.evidence-latency-note{
  margin-top:1.5rem; padding:1.1rem 1.2rem;
  border-left:3px solid var(--teal,currentColor);
  background:var(--bg-alt,transparent);
}
.evidence-latency-heading{ font-size:1rem; margin:0 0 .5rem; }
.evidence-latency-note p{ margin:0; color:var(--body); line-height:1.75; max-width:70ch; }
.evidence-latency-caveat{ margin-top:.6rem !important; font-size:.85rem; opacity:.75; }

/* ── Shadow evaluation phases ──────────────────────────────────────────────
   Three phases as an ordered list: the sequence is the meaning, so it is real
   list markup rather than styled divs. */
.phase-row{
  list-style:none; margin:0; padding:0;
  display:grid; gap:1.25rem; grid-template-columns:repeat(auto-fit,minmax(16rem,1fr));
}
.phase{ border-top:2px solid var(--teal,currentColor); padding-top:.9rem; }
.phase-number{
  display:block; font-size:.6875rem; font-weight:600; letter-spacing:.08em;
  opacity:.55; font-variant-numeric:tabular-nums;
}
.phase-heading{
  font-size:.9375rem; letter-spacing:.09em; text-transform:uppercase;
  margin:.3rem 0 .5rem;
}
.phase p{ margin:0; color:var(--body); font-size:.9375rem; line-height:1.7; }

/* ── Evidence surfaces ─────────────────────────────────────────────────────
   Quiet, neutral panes holding literal input and literal engine output.
   Monospace throughout because these are exact strings; a reader should be
   able to match them against the repository character for character. Code
   scrolls horizontally on small screens rather than wrapping, which would
   change the alignment that makes the output readable. */
.evidence{
  display:grid; gap:1rem; grid-template-columns:repeat(auto-fit,minmax(19rem,1fr));
  align-items:start;
}
.evidence-pane{ border:1px solid var(--border,rgba(0,0,0,.14)); }
.evidence-label{
  margin:0; padding:.6rem .85rem; font-size:.6875rem; font-weight:600;
  text-transform:uppercase; letter-spacing:.07em; opacity:.7;
  border-bottom:1px solid var(--border,rgba(0,0,0,.14));
}
.evidence-label code{ text-transform:none; letter-spacing:0; opacity:.9; }
.evidence-code{
  margin:0; padding:.85rem; overflow-x:auto;
  font-size:.8125rem; line-height:1.65; tab-size:2;
}
.evidence-code code{ white-space:pre; }
.evidence-repro{
  margin-top:1rem; font-size:.9rem; color:var(--ink-soft); line-height:1.7; max-width:70ch;
}

/* ── Narrow-viewport table containment ─────────────────────────────────────
   Data tables on specification.html and evidence-pack.html pushed the page
   wider than the viewport on mobile (up to 543px of content in a 390px
   window), so the whole page scrolled sideways. A table that is genuinely
   wider than a phone should scroll inside its own box, not drag the document
   with it.

   The two tables that already reflow into labelled blocks at this width are
   excluded — they need no scroll area, and giving them one would reintroduce
   the horizontal scroll this rule exists to remove. */
@media (max-width: 900px) {
  main table:not(.control-table):not(.regulatory-index),
  .premium-metrics{
    display:block;
    width:100%;
    max-width:100%;
    overflow-x:auto;
    -webkit-overflow-scrolling:touch;
  }
}

/* ──────────────────────────────────────────────────────────────────────────
   Layout containment — added 2026-09-05 (Phase D)
   ──────────────────────────────────────────────────────────────────────────
   Four destinations scrolled horizontally at a 390px viewport: faq.html to
   574px, sms-opt-in.html to 459px, developers.html to 446px, evidence-pack.html
   to 417px. Measured with Playwright at 390x900; index.html and the other seven
   destinations were already clean, which is why this is containment rather than
   a layout rewrite.

   Three distinct causes, and the first two are the same bug wearing different
   clothes: a flex or grid item defaults to `min-width: auto`, so it refuses to
   shrink below the max-content width of the prose inside it. `.faq-item` is a
   grid child and the SMS consent copy is a flex child; both sized to their
   longest line and pushed the page wider than the screen.

   Scoped deliberately. A blanket `* { min-width: 0 }` would also flatten the
   intrinsic sizing that data tables and code blocks rely on to stay readable,
   so each rule names what it contains. */

/* 1. Prose inside a flex or grid container must be allowed to wrap. */
.faq-item,
.faq-list > * {
  min-width: 0;
}

/* The consent row is a checkbox beside a paragraph of required disclosure
   copy. It was an inline `display:flex` with no min-width on either the label
   or its text, so both sized to the copy's longest line — 424px of content in
   a 320px column. Named here so the containment travels with the component
   instead of living in a page's style attribute. */
.consent-form {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  margin: 1rem 0;
  min-width: 0;
}

.consent-row {
  display: flex;
  gap: 0.6rem;
  align-items: flex-start;
  font-size: 0.9rem;
  line-height: 1.5;
  min-width: 0;
}

.consent-row > input[type="checkbox"] {
  margin-top: 0.25rem;
  flex-shrink: 0;
}

.consent-copy {
  flex: 1 1 auto;
  min-width: 0;
}

/* 2. A long unbreakable token — an import path, a URL, a file path — is the
      only thing on the line that cannot wrap, so it alone gets to break.
      `<pre>` is excluded: it scrolls inside its own box on purpose, and
      breaking it would corrupt copy-pasted commands. */
code {
  overflow-wrap: anywhere;
}

pre code {
  overflow-wrap: normal;
}

/* 3. A visually-hidden <caption> still participates in table layout: the
      `position: absolute` in .visually-hidden does not take a caption out of
      flow the way it does a div, so its `white-space: nowrap` text — 663px on
      the evidence-pack conformance table — set the table's minimum width. The
      caption stays in the accessibility tree; only its layout contribution
      goes. */
caption.visually-hidden {
  display: block;
  white-space: normal;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}

/* ──────────────────────────────────────────────────────────────────────────
   Maturity language — added 2026-09-05 (Phase D)
   ──────────────────────────────────────────────────────────────────────────
   NHID-Clinical publishes work at six very different standings, and before this
   the site had no way to say which was which. Status was carried by whatever
   pill a page happened to use — .primary-pill, .spec-badge, .console-pill,
   .layer-tag — none of which meant anything in particular, and the words
   "implemented", "verified" and "future" appeared as labels almost nowhere.
   A reader could not tell a deterministic engine with a passing test suite from
   a registry that does not exist.

   The six states are NOT invented here. They are the standings already recorded
   in docs/claim-boundaries.md §"Maturity boundaries", which is the authoritative
   claims document, and tests/test_maturity_language.py pins them to it.

     verified     measured evidence exists and is reproducible
     implemented  code exists, runs, and is covered by the suite
     reference    a working primitive, deliberately not deployed infrastructure
     conceptual   a documented production path that is not built
     research     a research component, explicitly not a product capability
     future       does not exist; named so it cannot be mistaken for shipped

   Accessibility: state is never carried by colour alone. Each chip renders its
   own word, and each carries a distinct leading glyph, so the distinction
   survives greyscale, colour-blindness and a screen reader. The glyph is
   decorative (aria-hidden via ::before) because the word is already the label. */

.maturity {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4em;
  padding: 0.15em 0.6em 0.2em;
  border: 1px solid var(--maturity-line);
  border-radius: 2em;
  background: var(--maturity-bg);
  color: var(--maturity-ink);
  font-family: var(--sans);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  vertical-align: baseline;
  min-width: 0;
}

.maturity::before {
  content: var(--maturity-glyph);
  font-weight: 700;
  letter-spacing: 0;
}

/* Evidence exists and can be re-run. The strongest claim the project makes. */
.maturity-verified {
  --maturity-ink: #10603f;
  --maturity-bg: #e8f5ee;
  --maturity-line: #9ecbb4;
  --maturity-glyph: "✓";
}

/* Code exists and the suite covers it. */
.maturity-implemented {
  --maturity-ink: #14778f;
  --maturity-bg: var(--teal-soft);
  --maturity-line: #9cc5cf;
  --maturity-glyph: "▪";
}

/* A working primitive. Deliberately not deployed infrastructure. */
.maturity-reference {
  --maturity-ink: #0b6ebc;
  --maturity-bg: var(--blue-soft);
  --maturity-line: #a8c6e0;
  --maturity-glyph: "◆";
}

/* Documented production path, not built. */
.maturity-conceptual {
  --maturity-ink: #6a5330;
  --maturity-bg: #f7f1e4;
  --maturity-line: #d6c4a0;
  --maturity-glyph: "◇";
}

/* Research component. Not a product capability, not to be sold as one. */
.maturity-research {
  --maturity-ink: #6b4a86;
  --maturity-bg: #f3edf9;
  --maturity-line: #c9b3dd;
  --maturity-glyph: "◐";
}

/* Does not exist. Named so it cannot be mistaken for shipped. */
.maturity-future {
  --maturity-ink: #5b6472;
  --maturity-bg: #eef0f3;
  --maturity-line: #c3cad3;
  --maturity-glyph: "○";
}

/* Dark theme: the same six states, re-grounded rather than inverted, so each
   keeps its contrast against the dark paper instead of glowing. */
[data-theme="dark"] .maturity-verified {
  --maturity-ink: #7fd8ab; --maturity-bg: #0b2a1d; --maturity-line: #1f5c3f;
}
[data-theme="dark"] .maturity-implemented {
  --maturity-ink: #5fd3d3; --maturity-bg: #08222a; --maturity-line: #1d5462;
}
[data-theme="dark"] .maturity-reference {
  --maturity-ink: #7cc2f5; --maturity-bg: #0a2033; --maturity-line: #1e4c72;
}
[data-theme="dark"] .maturity-conceptual {
  --maturity-ink: #d8c191; --maturity-bg: #2a2317; --maturity-line: #5e5031;
}
[data-theme="dark"] .maturity-research {
  --maturity-ink: #c3a6dd; --maturity-bg: #221a2c; --maturity-line: #4d3d61;
}
[data-theme="dark"] .maturity-future {
  --maturity-ink: #9aa5b3; --maturity-bg: #1a1f26; --maturity-line: #39414c;
}

/* A legend, for the one page that should explain the scale rather than use it. */
.maturity-legend {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
  gap: 0.75rem 1.5rem;
  margin: 1.5rem 0;
  padding: 0;
  list-style: none;
  min-width: 0;
}

.maturity-legend > li {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  min-width: 0;
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--body);
}

.maturity-legend .maturity {
  flex: 0 0 auto;
}

@media (prefers-reduced-motion: no-preference) {
  .maturity {
    transition: background-color 120ms ease, border-color 120ms ease;
  }
}

/* ──────────────────────────────────────────────────────────────────────────
   Canonical visual model — the five controls (Phase D)
   ──────────────────────────────────────────────────────────────────────────
   The framework is five controls, and four of them are not like the fifth.
   IDG-01, PDX-01, DBC-01 and EIT-01 act on the call; ATR-01 records what they
   decided and changes no behaviour. That distinction has been misstated
   repeatedly — the site and its PDFs have each at some point described "four
   controls" — so the diagram encodes it structurally: the four sit on the call
   timeline, ATR-01 sits beneath it, spanning the whole call, tied upward to
   each gate. A reader who never gets past the picture still gets the shape.

   Scales with the container via the viewBox; every colour comes from the theme
   tokens so it re-grounds in dark rather than glowing. */

.control-model {
  margin: 1.75rem 0 0;
  padding: 1.5rem 1.25rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--paper);
  min-width: 0;
  overflow-x: auto;
}

.control-model svg {
  min-width: 34rem;    /* below this the labels collide; the figure scrolls instead */
}

.cm-axis {
  stroke: var(--line);
  stroke-width: 2;
}

.cm-arrowhead {
  fill: var(--line);
}

/* The four behavioural gates. */
.cm-gate rect {
  fill: var(--teal-soft);
  stroke: #9cc5cf;
  stroke-width: 1.5;
}

/* ATR-01. Deliberately not a gate: no fill from the gate palette, a dashed
   edge, and it spans the full width rather than occupying a slot. */
.cm-audit rect {
  fill: none;
  stroke: var(--blue);
  stroke-width: 1.5;
  stroke-dasharray: 6 4;
  opacity: 0.85;
}

.cm-tie path {
  stroke: var(--line);
  stroke-width: 1.5;
  stroke-dasharray: 3 3;
  fill: none;
}

.cm-id {
  fill: var(--ink);
  font-family: var(--sans);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: 0.04em;
}

.cm-name {
  fill: var(--ink-soft);
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 600;
}

.cm-act {
  fill: var(--body);
  font-family: var(--sans);
  font-size: 12.5px;
}

.cm-eyebrow,
.cm-note {
  fill: var(--body);
  font-family: var(--sans);
  font-size: 11.5px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  font-weight: 700;
}

.cm-note {
  letter-spacing: 0.02em;
  text-transform: none;
  font-weight: 400;
  font-size: 12.5px;
}

[data-theme="dark"] .cm-gate rect {
  fill: #08222a;
  stroke: #1d5462;
}

[data-theme="dark"] .cm-audit rect {
  stroke: #58b4f0;
}

/* ──────────────────────────────────────────────────────────────────────────
   Canonical visual model — the interaction boundary (Phase D)
   ──────────────────────────────────────────────────────────────────────────
   positioning.md states the thesis in one sentence: NHID-Clinical "does not
   govern the AI model. It governs the moment a non-human actor crosses an
   organizational boundary." The most common misreading of this project is that
   it is healthcare AI governance broadly, so the diagram draws the scope
   line rather than asserting it — the model sits inside the provider
   organization, greyed and dashed and labelled "Not governed here", while
   NHID-Clinical sits on the boundary itself and nowhere else.

   The out-of-scope block is deliberately the visually quietest thing in the
   figure. It is there to be excluded, not to compete. */

.boundary-model {
  margin: 1.75rem 0 0;
  padding: 1.5rem 1.25rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--paper);
  min-width: 0;
  overflow-x: auto;
}

.boundary-model svg {
  min-width: 36rem;
}

.ib-org rect {
  fill: none;
  stroke: var(--line);
  stroke-width: 1.5;
}

.ib-org-label {
  fill: var(--body);
  font-family: var(--sans);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
}

/* Out of scope: quiet, dashed, and stated. */
.ib-outside rect {
  fill: var(--mist);
  stroke: var(--line);
  stroke-width: 1;
  stroke-dasharray: 4 4;
}

.ib-outside-title {
  fill: var(--body);
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 600;
}

.ib-outside-note {
  fill: var(--body);
  font-family: var(--sans);
  font-size: 12px;
  opacity: 0.85;
}

.ib-actor rect {
  fill: var(--teal-soft);
  stroke: #9cc5cf;
  stroke-width: 1.25;
}

.ib-actor-label {
  fill: var(--ink-soft);
  font-family: var(--sans);
  font-size: 12.5px;
  font-weight: 600;
}

.ib-boundary {
  stroke: var(--ink);
  stroke-width: 2;
  stroke-dasharray: 8 5;
  opacity: 0.55;
}

.ib-boundary-label {
  fill: var(--ink);
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  opacity: 0.75;
}

.ib-call {
  stroke: var(--blue);
  stroke-width: 2;
}

.ib-call-head {
  fill: var(--blue);
}

/* The only filled, emphasised element: what this project actually governs. */
.ib-gate rect {
  fill: var(--blue-soft);
  stroke: var(--blue);
  stroke-width: 2;
}

.ib-gate-title {
  fill: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 700;
}

.ib-gate-q {
  fill: var(--ink-soft);
  font-family: var(--sans);
  font-size: 12.5px;
}

.ib-note {
  fill: var(--body);
  font-family: var(--sans);
  font-size: 12.5px;
}

[data-theme="dark"] .ib-outside rect { fill: #12202f; }
[data-theme="dark"] .ib-actor rect   { fill: #08222a; stroke: #1d5462; }
[data-theme="dark"] .ib-gate rect    { fill: #0a2033; stroke: #58b4f0; }

/* ──────────────────────────────────────────────────────────────────────────
   Canonical visual model — shadow evaluation (Phase D)
   ──────────────────────────────────────────────────────────────────────────
   The property readers most often get wrong is that a shadow evaluation
   intercepts the call. It does not: it reads traces the adopter already holds.
   Prose has said "observe-only, non-intercepting" on this page for a long time
   and it kept being misread, so the diagram makes it structural — the live call
   sits above a divider, the evaluation below it, and exactly one arrow crosses,
   downward, representing recording that already happens. There is deliberately
   no upward arrow anywhere in the figure, because there is no mechanism for
   one. */

.shadow-model {
  margin: 1.5rem 0 0;
  padding: 1.5rem 1.25rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--paper);
  min-width: 0;
  overflow-x: auto;
}

.shadow-model svg { min-width: 36rem; }

.sm-live rect {
  fill: var(--mist);
  stroke: var(--line);
  stroke-width: 1.25;
}

.sm-eval rect {
  fill: var(--teal-soft);
  stroke: #9cc5cf;
  stroke-width: 1.25;
}

.sm-call, .sm-flow { stroke: var(--body); stroke-width: 2; }
.sm-call-head, .sm-flow-head { fill: var(--body); }

/* The one crossing. Dashed, because it is a recording that already exists
   rather than a connection this framework installs. */
.sm-tap { stroke: var(--blue); stroke-width: 1.75; stroke-dasharray: 5 4; }
.sm-tap-head { fill: var(--blue); }

.sm-divider { stroke: var(--line); stroke-width: 1.5; stroke-dasharray: 3 4; }

.sm-zone {
  fill: var(--body); font-family: var(--sans); font-size: 11.5px;
  font-weight: 700; letter-spacing: 0.11em;
}

.sm-label { fill: var(--ink); font-family: var(--sans); font-size: 14px; font-weight: 600; }
.sm-sub   { fill: var(--body); font-family: var(--sans); font-size: 11.5px; }
.sm-note  { fill: var(--body); font-family: var(--sans); font-size: 12px; }

[data-theme="dark"] .sm-live rect { fill: #12202f; }
[data-theme="dark"] .sm-eval rect { fill: #08222a; stroke: #1d5462; }
[data-theme="dark"] .sm-tap       { stroke: #58b4f0; }
[data-theme="dark"] .sm-tap-head  { fill: #58b4f0; }

/* ──────────────────────────────────────────────────────────────────────────
   Canonical visual model — reference architecture (Phase D)
   ──────────────────────────────────────────────────────────────────────────
   An architecture diagram that draws only what works is a sales diagram. This
   one is split: everything above the divider is built and covered by the
   suite, everything below it is not built and is drawn where it would go.
   claim-boundaries.md records key custody as a documented path that is not
   built, the registry as future work requiring a neutral operator, and
   federation as an open problem — so those three appear as hollow, dashed
   placeholders rather than as components.

   The gap between the halves is the point of the figure: it is the difference
   between a reference implementation and deployable infrastructure. */

.arch-model {
  margin: 1.25rem 0 2rem;
  padding: 1.5rem 1.25rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--paper);
  min-width: 0;
  overflow-x: auto;
}

.arch-model svg { min-width: 38rem; }

.ra-box rect {
  fill: var(--teal-soft);
  stroke: #9cc5cf;
  stroke-width: 1.25;
}

/* The engine is the one component everything else exists to serve. */
.ra-core rect {
  fill: var(--blue-soft);
  stroke: var(--blue);
  stroke-width: 2;
}

/* Not built. Hollow and dashed, so it cannot be mistaken for a component. */
.ra-absent rect {
  fill: none;
  stroke: var(--line);
  stroke-width: 1.25;
  stroke-dasharray: 5 4;
}

.ra-flow { stroke: var(--body); stroke-width: 1.75; }
.ra-flow-head { fill: var(--body); }
.ra-divider { stroke: var(--line); stroke-width: 1.5; stroke-dasharray: 3 4; }

.ra-zone {
  fill: var(--body); font-family: var(--sans); font-size: 11.5px;
  font-weight: 700; letter-spacing: 0.11em;
}

.ra-zone-absent { opacity: 0.75; }

.ra-title  { fill: var(--ink); font-family: var(--sans); font-size: 14px; font-weight: 600; }
.ra-sub    { fill: var(--body); font-family: var(--sans); font-size: 11.5px; }
.ra-title-absent { fill: var(--body); font-family: var(--sans); font-size: 14px; font-weight: 600; opacity: 0.9; }
.ra-sub-absent   { fill: var(--body); font-family: var(--sans); font-size: 11.5px; opacity: 0.8; }
.ra-note   { fill: var(--body); font-family: var(--sans); font-size: 12.5px; }

[data-theme="dark"] .ra-box rect  { fill: #08222a; stroke: #1d5462; }
[data-theme="dark"] .ra-core rect { fill: #0a2033; stroke: #58b4f0; }

/* ──────────────────────────────────────────────────────────────────────────
   Canonical visual model — evidence lifecycle (Phase D)
   ──────────────────────────────────────────────────────────────────────────
   project-state.md §5 opens "Evidence — four distinct bodies, never to be
   merged", and the repository has had to restate that repeatedly, because a
   reader looking at four percentages naturally wants to average them. The
   figure makes the rule structural: one path across the top produces every
   measurement, and below the divider the four bodies sit side by side as peers
   with no arrow between them and no total beneath them. There is nowhere for a
   combined number to go. */

.evidence-model {
  margin: 1.25rem 0 2rem;
  padding: 1.5rem 1.25rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--paper);
  min-width: 0;
  overflow-x: auto;
}

.evidence-model svg { min-width: 38rem; }

.ev-box rect  { fill: var(--mist); stroke: var(--line); stroke-width: 1.25; }
.ev-core rect { fill: var(--blue-soft); stroke: var(--blue); stroke-width: 2; }
.ev-body rect { fill: var(--teal-soft); stroke: #9cc5cf; stroke-width: 1.25; }

.ev-flow { stroke: var(--body); stroke-width: 1.75; }
.ev-flow-head { fill: var(--body); }
.ev-divider { stroke: var(--line); stroke-width: 1.5; stroke-dasharray: 3 4; }

.ev-zone {
  fill: var(--body); font-family: var(--sans); font-size: 11.5px;
  font-weight: 700; letter-spacing: 0.11em;
}
.ev-title { fill: var(--ink); font-family: var(--sans); font-size: 14px; font-weight: 600; }
.ev-sub   { fill: var(--body); font-family: var(--sans); font-size: 11.5px; }
.ev-note  { fill: var(--body); font-family: var(--sans); font-size: 12px; }
.ev-warn  { fill: var(--ink-soft); font-family: var(--sans); font-size: 12.5px; font-weight: 600; }

[data-theme="dark"] .ev-box rect  { fill: #12202f; }
[data-theme="dark"] .ev-core rect { fill: #0a2033; stroke: #58b4f0; }
[data-theme="dark"] .ev-body rect { fill: #08222a; stroke: #1d5462; }

/* ──────────────────────────────────────────────────────────────────────────
   The Trust Gateway (Phase D)
   ──────────────────────────────────────────────────────────────────────────
   This replaces an illustration. The component it supersedes carried the
   disclaimer "Illustrative — dialogue, mock config payloads, and artwork are
   for explanation only", which is the correct disclaimer for a mock and the
   wrong artifact for a page arguing that the controls are checkable.

   Every action, reason code and violation rendered here came out of
   `evaluate_all`, recorded by scripts/build_gateway_fixture.py replaying real
   corpus scenarios. The markup is generated and committed, so:

     - it reads correctly with JavaScript disabled — the stepper is an
       enhancement over content that is already complete;
     - it needs no network, no server, and no API key;
     - a test regenerates it, so "real engine output" stays true rather than
       becoming a claim about the past.

   The action colours reuse the maturity palette's logic (semantic, not
   decorative) but are their own scale: an enforcement outcome is not a
   maturity standing, and conflating them would make both meaningless. */

.trust-gateway {
  margin: 1.5rem 0 0;
  padding: 1.25rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--paper);
  min-width: 0;
}

.tg-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 1.25rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--line);
  min-width: 0;
}

.tg-step {
  padding: 0.45rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--mist);
  color: var(--ink-soft);
  font: inherit;
  font-size: 0.86rem;
  font-weight: 600;
  cursor: pointer;
}

.tg-step:hover:not(:disabled) { border-color: var(--blue); color: var(--blue); }
.tg-step:disabled { opacity: 0.45; cursor: default; }
.tg-step:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.tg-step-quiet { margin-left: auto; }

.tg-position {
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--body);
}

.tg-scenario + .tg-scenario {
  margin-top: 2rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--line);
}

.tg-scenario-title { margin: 0 0 0.25rem; font-size: 1.02rem; }
.tg-scenario-note  { margin: 0 0 1rem; color: var(--body); font-size: 0.9rem; line-height: 1.65; }

.tg-turns { margin: 0; padding: 0; list-style: none; display: grid; gap: 0.9rem; min-width: 0; }

.tg-turn {
  padding: 0.9rem 1rem;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--mist);
  min-width: 0;
}

.tg-said { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.55rem; min-width: 0; }

.tg-turn-no {
  flex: 0 0 auto;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--body);
}

.tg-said q { min-width: 0; color: var(--ink-soft); font-size: 0.94rem; line-height: 1.6; }

.tg-verdict {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.55rem;
  margin-top: 0.7rem;
  min-width: 0;
}

.tg-action {
  padding: 0.15em 0.6em 0.2em;
  border: 1px solid currentColor;
  border-radius: 2em;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  white-space: nowrap;
}

/* The enforcement ladder, most restrictive first. */
.tg-action-deny     { color: #9b2c2c; background: #fdeaea; }
.tg-action-escalate { color: #8a5a12; background: #fdf2e0; }
.tg-action-disclose { color: #0b6ebc; background: var(--blue-soft); }
.tg-action-log      { color: #6b4a86; background: #f3edf9; }
.tg-action-continue { color: #10603f; background: #e8f5ee; }

.tg-reason {
  min-width: 0;
  overflow-wrap: anywhere;
  font-size: 0.8rem;
  color: var(--body);
}

.tg-violations { margin: 0.7rem 0 0; padding-left: 1.1rem; display: grid; gap: 0.4rem; min-width: 0; }
.tg-violations li { color: var(--body); font-size: 0.86rem; line-height: 1.6; }

.tg-sev {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
}

.tg-clean { margin: 0.7rem 0 0; color: var(--body); font-size: 0.86rem; opacity: 0.8; }

[data-theme="dark"] .tg-turn { background: #12202f; }
[data-theme="dark"] .tg-step { background: #12202f; }
[data-theme="dark"] .tg-action-deny     { color: #f2a2a2; background: #2c1414; }
[data-theme="dark"] .tg-action-escalate { color: #e0bd7c; background: #2a2114; }
[data-theme="dark"] .tg-action-disclose { color: #7cc2f5; background: #0a2033; }
[data-theme="dark"] .tg-action-log      { color: #c3a6dd; background: #221a2c; }
[data-theme="dark"] .tg-action-continue { color: #7fd8ab; background: #0b2a1d; }

@media (prefers-reduced-motion: no-preference) {
  .tg-turn { transition: opacity 140ms ease; }
}

/* ──────────────────────────────────────────────────────────────────────────
   Journey wayfinder (Phase D)
   ──────────────────────────────────────────────────────────────────────────
   The IA consolidation mapped every destination to a journey, but only inside
   ia-disposition.md. A reader landing on evidence-pack.html from a search
   result had no way to see they were partway through an arc, or what came
   before and after.

   Deliberately quiet. It sits at the foot of the content, after the reader has
   what they came for, and it is a <nav> with its own label so a screen reader
   can skip it or seek it. It is not a progress bar: a reader does not owe the
   site a linear traversal, and half of them will only ever want one page. */

.wayfinder {
  margin: 3rem 0 0;
  padding: 1.25rem 1.25rem 1.4rem;
  border-top: 1px solid var(--line);
  min-width: 0;
}

.wayfinder-here {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.6rem;
  margin: 0 0 1rem;
  min-width: 0;
}

.wayfinder-journey {
  flex: 0 0 auto;
  padding: 0.14em 0.6em 0.2em;
  border: 1px solid var(--line);
  border-radius: 2em;
  background: var(--mist);
  color: var(--body);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.wayfinder-question {
  min-width: 0;
  color: var(--ink);
  font-family: var(--display);
  font-size: 1.02rem;
  font-weight: 700;
}

.wayfinder-steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr));
  gap: 0.9rem 1.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
  min-width: 0;
}

.wayfinder-steps li {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  min-width: 0;
}

.wayfinder-steps span {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--body);
  opacity: 0.85;
}

.wayfinder-steps a {
  min-width: 0;
  color: var(--blue);
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.wayfinder-steps a:hover { text-decoration: underline; }
.wayfinder-steps a:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }

[data-theme="dark"] .wayfinder-journey { background: #12202f; }

/* ── Disclosure-gate sequence (specification.html) ──────────────────────────
   Replaces a Mermaid diagram that was rendered at runtime from
   cdn.jsdelivr.net. That made the specification page's only sequence visual a
   third-party dependency: no CDN, no diagram, and the fallback was raw
   `sequenceDiagram` source text on a white card. It also carried Mermaid's own
   visual language rather than this project's.

   This is the same flat, token-driven, 880-wide grammar as the five canonical
   models, so it inherits both themes for free and needs no JavaScript. The
   ordered list beneath it is not a fallback for failure — it is the readable
   form of the same sequence, present for everyone.
   -------------------------------------------------------------------------- */
.sequence-model {
  margin: 1.75rem 0 0;
  padding: 1.5rem 1.25rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--paper);
  min-width: 0;
  overflow-x: auto;
}

.sequence-model svg {
  min-width: 36rem;    /* below this the lane labels collide; the figure scrolls */
}

/* Lane headers — one per actor. */
.sq-lane rect {
  fill: var(--teal-soft);
  stroke: #9cc5cf;
  stroke-width: 1.5;
}
.sq-lane-name {
  font-family: var(--sans);
  font-size: 12.5px;
  font-weight: 650;
  fill: var(--ink);
}
.sq-lane-role {
  font-family: var(--sans);
  font-size: 10.5px;
  fill: var(--body);
}

/* The vertical lifeline each actor occupies for the duration of the call. */
.sq-life {
  stroke: var(--line);
  stroke-width: 1.5;
  stroke-dasharray: 3 5;
}

/* Messages. Solid for a call, dashed for a return. */
.sq-msg { stroke: var(--teal); stroke-width: 1.8; }
.sq-msg-head { fill: var(--teal); }
.sq-return { stroke: var(--blue); stroke-width: 1.8; stroke-dasharray: 6 4; }
.sq-return-head { fill: var(--blue); }

.sq-step {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 10px;
  font-weight: 500;
  fill: var(--body);
}
.sq-label {
  font-family: var(--sans);
  font-size: 11.5px;
  fill: var(--ink-soft);
}
.sq-call {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 11px;
  fill: var(--ink);
}

/* The gate itself: the line the interaction may not cross until disclosure is
   confirmed. Dashed and full-width, the same treatment ATR-01 gets in the
   control model — it is a boundary, not a step. */
.sq-gate line {
  stroke: var(--blue);
  stroke-width: 1.5;
  stroke-dasharray: 6 4;
  opacity: 0.9;
}
.sq-gate-label {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 9.5px;
  letter-spacing: 0.1em;
  fill: var(--blue);
}

/* Engine output, quoted verbatim in monospace. */
.sq-out rect {
  fill: var(--blue-soft);
  stroke: var(--blue);
  stroke-width: 1.2;
}
.sq-out-key {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 10px;
  fill: var(--body);
}
.sq-out-val {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 10px;
  font-weight: 500;
  fill: var(--ink);
}

/* The prose form of the same sequence. */
.sequence-steps {
  margin: 1.25rem 0 0;
  padding-left: 1.15rem;
  color: var(--body);
  font-size: 0.93rem;
  line-height: 1.7;
}
.sequence-steps li { margin-bottom: 0.4rem; }
.sequence-steps code {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 0.84em;
  background: var(--bg-alt, var(--mist));
  padding: 0.08rem 0.28rem;
  border-radius: 3px;
}

/* ── Generated evidence figures ─────────────────────────────────────────────
   Three figures produced by scripts/build_evidence_visuals.py, which replays
   committed repository data through the real engine. They share the canonical
   880-wide flat grammar and take every colour from a token, so both themes
   work with no per-theme asset.
   -------------------------------------------------------------------------- */

/* The generic figure frame. `.evidence-model` is NOT this — it is one of the
   five canonical model classes and means the evidence lifecycle model on
   evidence-pack.html specifically. Any new figure uses this instead, so it
   never shadows a named model that other code looks for by class. */
.figure-frame {
  margin: 1.75rem 0 0;
  padding: 1.5rem 1.25rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--paper);
  min-width: 0;
  overflow-x: auto;
}

/* Shared: the provenance block every generated figure carries. The visual
   audit found that no image asset on the site recorded where it came from,
   while the framework's whole discipline is that a claim carries its source.
   This is that discipline applied to pictures. */
.visual-provenance {
  margin: 0.9rem 0 0;
  padding: 0.75rem 0.9rem;
  border-left: 3px solid var(--blue);
  background: var(--mist);
  border-radius: 0 8px 8px 0;
  font-size: 0.8rem;
  line-height: 1.65;
  color: var(--body);
}
.visual-provenance p { margin: 0 0 0.25rem; }
.visual-provenance p:last-child { margin-bottom: 0; }
.visual-provenance code {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 0.92em;
  background: var(--paper);
  padding: 0.05rem 0.3rem;
  border-radius: 3px;
  border: 1px solid var(--line);
}
.visual-provenance strong { color: var(--ink); font-weight: 650; }

/* ── Enforcement ladder ──────────────────────────────────────────────────── */
.enforcement-ladder svg { min-width: 40rem; }

.el-zone, .el-colhead {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 9.5px;
  letter-spacing: 0.11em;
  fill: var(--body);
  text-transform: uppercase;
}
.el-colhead { text-transform: none; letter-spacing: 0.02em; font-size: 10.5px; }
.el-node rect { fill: var(--paper); stroke: var(--line); stroke-width: 1.5; }
.el-title { font-family: var(--sans); font-size: 12.5px; font-weight: 650; fill: var(--ink); }
.el-sub { font-family: var(--sans); font-size: 10.5px; fill: var(--body); }
.el-ctlbox rect { fill: var(--teal-soft); stroke: #9cc5cf; stroke-width: 1.4; }
/* ATR-01 is not a gate; it gets the dashed treatment it has in the control model. */
.el-auditbox rect { fill: none; stroke: var(--blue); stroke-width: 1.4; stroke-dasharray: 5 3; }
.el-ctlname {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 10.5px; font-weight: 500; fill: var(--ink);
}
.el-flow { stroke: var(--line); stroke-width: 1.6; fill: none; }
.el-flow-head { fill: var(--line); }
.el-divider { stroke: var(--line); stroke-width: 1; }
.el-rung { fill: var(--teal-soft); stroke: #9cc5cf; stroke-width: 1.2; }
.el-pri {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 11px; font-weight: 500; fill: var(--teal);
}
.el-action {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 10.5px; fill: var(--ink);
}
.el-count {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 10px; fill: var(--body);
}
.el-ctl {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 10.5px; fill: var(--ink);
}
.el-winbar { fill: var(--blue); opacity: 0.55; }
.el-note { font-family: var(--sans); font-size: 10.5px; fill: var(--body); }

/* ── Shadow outcome chart ────────────────────────────────────────────────── */
.shadow-outcomes svg { min-width: 34rem; }

.ev-cat {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 11px; fill: var(--ink);
}
.ev-val {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 11px; font-weight: 500; fill: var(--ink);
}
.ev-pct { fill: var(--body); font-weight: 400; }
.ev-sub { font-family: var(--sans); font-size: 11px; fill: var(--body); }
.ev-headline { font-family: var(--sans); font-size: 12.5px; font-weight: 650; fill: var(--ink); }
.ev-divider { stroke: var(--line); stroke-width: 1; }
/* Two tones only, and they carry meaning: what the engine let through, and
   what it would have acted on. Not a decorative per-series palette. */
.ev-bar[data-tone="continue"] { fill: var(--teal-bright, #14b8a6); opacity: 0.4; }
.ev-bar[data-tone="enforce"] { fill: var(--blue); opacity: 0.72; }

/* ── Evidence scorecard ──────────────────────────────────────────────────── */
.sc-wrap { margin: 1.25rem 0 0; overflow-x: auto; }

.scorecard-table {
  width: 100%;
  min-width: 42rem;
  border-collapse: collapse;
  font-size: 0.85rem;
}
.scorecard-table caption {
  caption-side: top;
  text-align: left;
  font-size: 0.8rem;
  color: var(--body);
  padding-bottom: 0.6rem;
}
.scorecard-table th, .scorecard-table td {
  text-align: left;
  vertical-align: top;
  padding: 0.7rem 0.75rem;
  border-bottom: 1px solid var(--line);
}
.scorecard-table thead th {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 0.68rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--body);
  font-weight: 500;
  border-bottom: 1.5px solid var(--line);
}
.scorecard-table tbody th {
  font-weight: 650;
  color: var(--ink);
  width: 22%;
}
/* Size stays narrow; result and reproduction need the room. */
.scorecard-table th:nth-child(2), .scorecard-table td:nth-child(2) { width: 15%; }
.scorecard-table th:nth-child(3), .scorecard-table td:nth-child(3) { width: 33%; }
.scorecard-table th:nth-child(4), .scorecard-table td:nth-child(4) { width: 30%; }
.sc-measures, .sc-src {
  display: block;
  font-weight: 400;
  font-size: 0.74rem;
  color: var(--body);
  margin-top: 0.15rem;
}
.sc-src { font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace); font-size: 0.7rem; }
.sc-size {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 0.78rem;
  white-space: nowrap;
}
.scorecard-table code {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 0.72rem;
  background: var(--mist);
  padding: 0.1rem 0.3rem;
  border-radius: 3px;
  word-break: break-word;
}
.sc-rate {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-weight: 500;
  color: var(--teal);
  white-space: nowrap;
}

/* ── Latency distribution (shadow-evaluation-guide.html) ────────────────────
   Replaces a glossy 3D "with/without a standard" illustration. That figure
   asserted a contrast; this one shows the recorded distribution of the field
   the corpus actually carries, and separates what was measured from what the
   corpus was authored to contain.
   -------------------------------------------------------------------------- */
.latency-distribution svg { min-width: 36rem; }

.lt-grid { stroke: var(--line); stroke-width: 1; stroke-dasharray: 3 4; }
.lt-tick {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 9.5px; fill: var(--body);
}
.lt-cat {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 11px; fill: var(--ink);
}
.lt-n {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 9px; fill: var(--body);
}
/* The span between p50 and p95 is the point of the figure: the spread, not a
   single headline number. */
.lt-span { stroke: var(--blue); stroke-width: 5; stroke-linecap: round; opacity: 0.32; }
.lt-p50 { fill: var(--teal-bright, #14b8a6); }
.lt-p95 { fill: var(--blue); }
.lt-val {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 9.5px; fill: var(--body);
}

/* ── Trust-stack cross-section ──────────────────────────────────────────────
   One canonical figure on three pages, replacing a glossy isometric SVG and a
   raster render whose provenance was a bare UUID. Flat, tokenised, and it
   distinguishes what NHID-Clinical actually is (layer 2) from its optional
   extension (layer 3) and from the standards it merely emits into.
   -------------------------------------------------------------------------- */
.trust-stack-model svg, 

.ts-zone, .ob-zone {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 9.5px; letter-spacing: .11em; text-transform: uppercase; fill: var(--body);
}
.ts-layer rect { stroke-width: 1.5; }
.ts-layer[data-kind="core"] rect     { fill: var(--teal-soft); stroke: var(--teal); stroke-width: 2.5; }
.ts-layer[data-kind="extension"] rect{ fill: var(--blue-soft); stroke: var(--blue); }
.ts-layer[data-kind="external"] rect { fill: var(--paper); stroke: var(--line); }
.ts-num {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 12px; font-weight: 500; fill: var(--body);
}
.ts-name { font-family: var(--sans); font-size: 12.5px; font-weight: 650; fill: var(--ink); }
.ts-purpose { font-family: var(--sans); font-size: 10.5px; fill: var(--body); }
.ts-evidence {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 10px; fill: var(--body);
}
/* Layer 0 is the absence the stack exists to address, so it is drawn as a gap
   rather than as a sixth layer. */
.ts-gap rect { fill: none; stroke: var(--line); stroke-width: 1.4; stroke-dasharray: 6 4; }
.ts-gapname { font-family: var(--sans); font-size: 11px; font-style: italic; fill: var(--body); }
.ts-key { font-family: var(--sans); font-size: 10px; fill: var(--body); }
.ts-key-core { fill: var(--teal); }
.ts-key-ext { fill: var(--blue); }
.ts-key-ext-o { fill: var(--line); }

/* ── Obligation-to-control map ─────────────────────────────────────────────
   Replaces a decorative lattice. The vocabulary was worth keeping; what it
   lacked was any statement of which obligation is carried by which control,
   and which two are not carried by a v1.3 control at all.
   -------------------------------------------------------------------------- */
.ob-row rect { stroke-width: 1.5; }
.ob-row[data-kind="control"] rect  { fill: var(--teal-soft); stroke: var(--teal); }
.ob-row[data-kind="adjacent"] rect { fill: none; stroke: var(--line); stroke-dasharray: 5 3; }
.ob-name {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 11.5px; font-weight: 500; fill: var(--ink); letter-spacing: .04em;
}
.ob-meaning { font-family: var(--sans); font-size: 11.5px; fill: var(--ink-soft); }
.ob-flow { stroke: var(--line); stroke-width: 1.6; fill: none; }
.ob-flow-head { fill: var(--line); }
.ob-control {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 11px; font-weight: 500;
}
.ob-control[data-kind="control"]  { fill: var(--teal); }
.ob-control[data-kind="adjacent"] { fill: var(--body); }

/* The cross-section is the overview and the tab list beside it is the
   drill-down, so the figure spans the grid rather than being squeezed into one
   column. The layer tabs and their detail panel are unchanged and still work. */
.stack-wrap > .stack-figure { grid-column: 1 / -1; }

/* ── Framework relationship map ─────────────────────────────────────────────
   Replaces a 19-colour mind map that carried its own typography. Colour here
   marks the ROLE a destination plays, not the destination — four accents, not
   nineteen — and the branches are the site's own four journeys.
   -------------------------------------------------------------------------- */
.framework-map svg { min-width: 40rem; }
.fm-root rect { fill: var(--teal-soft); stroke: var(--teal); stroke-width: 2.5; }
.fm-roottitle { font-family: var(--display); font-size: 15px; font-weight: 700; fill: var(--ink); }
.fm-rootsub { font-family: var(--sans); font-size: 10.5px; fill: var(--body); }
.fm-head rect { fill: none; stroke: var(--line); stroke-width: 1.4; }
.fm-journey {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 10px; letter-spacing: .1em; fill: var(--body);
}
.fm-spine { stroke: var(--line); stroke-width: 1.4; fill: none; }
.fm-node rect { stroke-width: 1.4; }
.fm-node[data-kind="framework"] rect { fill: var(--teal-soft); stroke: var(--teal); }
.fm-node[data-kind="measure"] rect   { fill: var(--blue-soft); stroke: var(--blue); }
.fm-node[data-kind="build"] rect     { fill: var(--paper); stroke: var(--ink-soft); }
.fm-node[data-kind="context"] rect   { fill: var(--paper); stroke: var(--line); }
.fm-label { font-family: var(--sans); font-size: 11.5px; fill: var(--ink); }
.framework-map a { text-decoration: none; }
.framework-map a:hover .fm-label { text-decoration: underline; }
.framework-map a:focus-visible rect { outline: 2px solid var(--teal-bright); outline-offset: 2px; }
.fm-key { font-family: var(--sans); font-size: 10px; fill: var(--body); }
.fm-k1 { fill: var(--teal); } .fm-k2 { fill: var(--blue); }
.fm-k3 { fill: var(--ink-soft); } .fm-k4 { fill: var(--line); }

/* ── Integration ladder ─────────────────────────────────────────────────────
   The concept was sound; what it never showed was the evidence each rung
   produces, which is the reason to climb one.
   -------------------------------------------------------------------------- */
.integration-ladder-model svg { min-width: 42rem; }
.il-tier rect { fill: var(--paper); stroke: var(--line); stroke-width: 1.5; }
.il-num {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 22px; font-weight: 500; fill: var(--teal);
}
.il-name { font-family: var(--sans); font-size: 13px; font-weight: 650; fill: var(--ink); }
.il-work { font-family: var(--sans); font-size: 11.5px; fill: var(--body); }
.il-meta {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 10px; fill: var(--ink-soft);
}
.il-key { fill: var(--body); letter-spacing: .08em; }

/* ── NHID-Auth credential chain ─────────────────────────────────────────────
   Four ordered steps ending in the six checks the payer side actually runs.
   -------------------------------------------------------------------------- */
.credential-chain svg { min-width: 42rem; }
.cc-zone {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 9.5px; letter-spacing: .11em; fill: var(--body);
}
.cc-step rect { fill: var(--paper); stroke: var(--line); stroke-width: 1.5; }
.cc-num {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 16px; font-weight: 500; fill: var(--teal);
}
.cc-title { font-family: var(--sans); font-size: 11.5px; font-weight: 650; fill: var(--ink); }
.cc-body {
  font-family: var(--sans); font-size: 10px; line-height: 1.35; color: var(--body);
  display: block;
}
.cc-flow { stroke: var(--line); stroke-width: 1.6; fill: none; }
.cc-flow-head { fill: var(--line); }
.cc-check rect { fill: var(--blue-soft); stroke: var(--blue); stroke-width: 1.2; }
.cc-checktext {
  font-family: var(--mono, "IBM Plex Mono", ui-monospace, monospace);
  font-size: 9px; fill: var(--ink);
}
