/*
 * Field Guide 001 — the house system applied to a long-form publication.
 *
 * User decision 2026-08-07: Field Guides look like ihtech.ba. Every token value
 * below is copied from `shell/shell.css` and `homepage/homepage.css` rather than
 * approximated, so the guide reads as the same product: graphite surfaces, the
 * cyan accent, the site's system sans for all prose and headings, and monospace
 * only at kicker scale for identifiers. The stylesheet stays route-local (nothing
 * is imported) because a guide must load only its own assets.
 *
 * Two rules govern everything below:
 *   1. Layers come from space, then a background step, then a hairline. Depth is
 *      one lit edge on the figure plate, never a drop shadow under content.
 *   2. Nothing is hidden by a state only JavaScript can produce. Every
 *      script-owned state is keyed off a `data-` attribute the module sets, so a
 *      module that never runs leaves a complete document.
 *
 * The one place emphasis is spent is the control loop's evidence return path and
 * the human sign-off marker on it. Everything else is graphite.
 */

:root {
  color-scheme: dark;

  /* Surfaces: page ground, the figure plate, and the cards that sit on it. */
  --paper: oklch(0.145 0.018 245);
  --sheet: oklch(0.165 0.019 245);
  --surface: oklch(0.19 0.02 245);
  --surface-2: oklch(0.225 0.022 245);

  --ink: oklch(0.955 0.009 240);
  --ink-2: oklch(0.8 0.018 240);
  --ink-3: oklch(0.68 0.024 240);

  --rule: oklch(0.255 0.02 242);
  --rule-strong: oklch(0.32 0.024 242);

  --accent: oklch(0.76 0.13 220);
  --accent-deep: oklch(0.7 0.15 220);
  --accent-wash: oklch(0.76 0.13 220 / 0.12);
  --accent-rule: oklch(0.76 0.13 220 / 0.45);
  --on-accent: oklch(0.14 0.02 245);

  --font-sans:
    ui-sans-serif, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial,
    sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;

  /* `--t-kicker` is the house `--step--1`: the only size monospace appears at. */
  --t-kicker: clamp(0.8rem, 0.77rem + 0.14vw, 0.88rem);
  --t-fine: clamp(0.9rem, 0.87rem + 0.14vw, 0.98rem);
  --t-body: clamp(0.98rem, 0.94rem + 0.18vw, 1.08rem);
  --t-lead: clamp(1.1rem, 1.02rem + 0.36vw, 1.28rem);
  --t-h3: clamp(1.3rem, 1.18rem + 0.55vw, 1.58rem);
  --t-h2: clamp(1.625rem, 1.4rem + 1.1vw, 2rem);
  --t-h1: clamp(2.125rem, 1.5rem + 3.2vw, 3.25rem);

  --s1: 4px;
  --s2: 8px;
  --s3: 12px;
  --s4: 16px;
  --s5: 20px;
  --s6: 24px;
  --s7: 32px;
  --s8: 40px;
  --s9: 48px;
  --s10: 64px;
  --s11: 96px;

  --rhythm: clamp(3.5rem, 5vw, 6rem);
  --gutter: clamp(1rem, 4vw, 2.5rem);
  --text-max: 704px;
  --rail: 232px;
  --rail-gap: 64px;
  --break: 0px;

  --r1: 4px;
  --r2: 10px;
  --r3: 18px;

  --fast: 120ms;
  --base: 240ms;
  --move: 320ms;
  --draw: 900ms;
  --ease: cubic-bezier(0.2, 0, 0, 1);
  --ease-out: cubic-bezier(0.33, 1, 0.68, 1);
}

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

*,
*::before,
*::after {
  box-sizing: border-box;
}

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

body {
  margin: 0;
  overflow-x: clip;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--t-body);
  line-height: 1.68;
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
h4,
p,
ul,
ol,
dl,
dd,
figure,
table {
  margin: 0;
  padding: 0;
}

ul,
ol {
  list-style: none;
}

h1 {
  max-width: 22ch;
  font-size: var(--t-h1);
  font-weight: 700;
  line-height: 1.04;
  letter-spacing: -0.042em;
  text-wrap: balance;
}

h2 {
  font-size: var(--t-h2);
  font-weight: 660;
  line-height: 1.15;
  letter-spacing: -0.032em;
  text-wrap: balance;
}

h3 {
  font-size: var(--t-h3);
  font-weight: 660;
  line-height: 1.25;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

h4 {
  font-size: var(--t-body);
  font-weight: 660;
  line-height: 1.3;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

p,
li,
dd,
figcaption {
  text-wrap: pretty;
}

strong {
  font-weight: 660;
}

.lead {
  font-size: var(--t-lead);
  line-height: 1.55;
  color: var(--ink);
}

.mono,
table,
time,
[class*='-num'] {
  font-variant-numeric: tabular-nums;
}

/* The house kicker, and the only shape monospace takes in this document: a
   short uppercase identifier at `--step--1`. Prose, headings, table headers,
   captions and rail entries are all sans. */
.mono {
  font-family: var(--font-mono);
  font-size: var(--t-kicker);
  font-weight: 560;
  line-height: 1.35;
  letter-spacing: 0.11em;
  text-transform: uppercase;
}

.label {
  color: var(--ink-3);
}

.accent {
  color: var(--accent-deep);
}

a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--accent-rule);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.3em;
  padding-block: 2px;
  transition: text-decoration-color var(--fast) var(--ease);
}

@media (hover: hover) and (pointer: fine) {
  a:hover {
    text-decoration-color: var(--accent);
  }
}

:where(a, button, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--r1);
}

.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.print-only {
  display: none;
}

.skip {
  position: fixed;
  z-index: 100;
  inset-block-start: var(--s3);
  inset-inline-start: var(--s3);
  padding: 0.7rem 1rem;
  border-radius: var(--r2);
  background: var(--ink);
  color: var(--paper);
  font-weight: 660;
  text-decoration: none;
  transform: translateY(calc(-100% - 1.5rem));
  transition: transform var(--base) var(--ease);
}

.skip:focus {
  transform: translateY(0);
}

/* --- containers ---------------------------------------------------------- */

.page,
.shell {
  --cluster: calc(var(--rail) + var(--rail-gap) + var(--text-max));

  max-width: calc(var(--cluster) + 2 * var(--gutter) + 2 * var(--break));
  margin-inline: auto;
  padding-inline: calc(var(--gutter) + var(--break));
  display: grid;
  grid-template-columns: var(--rail) var(--rail-gap) minmax(0, var(--text-max));
}

.page > *,
.shell > * {
  grid-column: 3;
  min-width: 0;
}

.bleed {
  margin-inline: calc(-1 * var(--break));
}

/* The identification band is sheet furniture, not prose: it spans the whole
   container so the lockup sits on the sheet's edge while the title below keeps
   the document's single content edge. */
.masthead-band {
  grid-column: 1 / -1;
  margin-inline: calc(-1 * var(--break));
}

/* --- masthead ------------------------------------------------------------ */

.masthead {
  border-block-end: 1px solid var(--rule);
}

.masthead-band {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3) var(--s5);
  align-items: center;
  justify-content: space-between;
  padding-block: var(--s6);
}

.lockup {
  display: inline-flex;
  gap: var(--s3);
  align-items: center;
  min-height: 44px;
  color: var(--ink);
  font-size: var(--t-fine);
  text-decoration: none;
}

.lockup-mark {
  flex: none;
  color: var(--ink-2);
}

.lockup-name {
  font-weight: 440;
}

.lockup-name strong {
  font-weight: 660;
}

@media (hover: hover) and (pointer: fine) {
  .lockup:hover .lockup-mark {
    color: var(--accent);
  }
}

.reference {
  margin: 0;
  color: var(--ink-3);
}

.breadcrumb ol {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  align-items: center;
  font-size: var(--t-fine);
  color: var(--ink-3);
}

/* Separators trail their own item rather than leading the next one: a leading
   separator lands at the start of a line whenever the trail wraps. */
.breadcrumb li:not(:last-child)::after {
  content: '/';
  margin-inline-start: var(--s2);
  color: var(--rule-strong);
}

.breadcrumb a {
  display: inline-block;
  min-height: 44px;
  line-height: 44px;
  padding-block: 0;
}

.breadcrumb [aria-current='page'] {
  color: var(--ink-2);
}

.masthead-title {
  padding-block: var(--s6) var(--s10);
}

.eyebrow {
  margin-block-end: var(--s9);
}

.masthead-title h1 {
  margin-block-start: 0;
}

.deck {
  max-width: 58ch;
  margin-block-start: var(--s4);
  font-size: var(--t-lead);
  line-height: 1.55;
  color: var(--ink-2);
}

.meta {
  font-size: var(--t-fine);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) var(--s3);
  margin-block-start: var(--s6);
  color: var(--ink-3);
}

.meta li:not(:last-child)::after {
  content: '·';
  margin-inline-start: var(--s3);
  color: var(--rule-strong);
}

.meta time {
  font-variant-numeric: tabular-nums;
}

.draft {
  color: var(--accent-deep);
}

/* --- reading routes ------------------------------------------------------ */

.routes {
  padding-block: var(--s8);
  border-block-end: 1px solid var(--rule);
}

.routes-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s4);
  margin-block-start: var(--s4);
}

.route {
  padding: var(--s5);
  border: 1px solid var(--rule);
  border-radius: var(--r2);
  background: var(--surface);
}

.route-id {
  margin: 0;
  color: var(--ink-3);
}

.route-name {
  margin-block: var(--s2) var(--s3);
  font-size: var(--t-body);
  font-weight: 660;
  line-height: 1.3;
}

.route-sections a {
  display: block;
  min-height: 44px;
  padding-block: var(--s2);
  font-size: var(--t-fine);
  line-height: 1.45;
  color: var(--ink-2);
}

/* --- contents rail ------------------------------------------------------- */

.rail {
  grid-column: 1;
  position: sticky;
  inset-block-start: var(--s7);
  align-self: start;
  max-height: calc(100vh - var(--s10));
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-block: var(--s10) var(--s6);
}

.rail-heading {
  margin-block-end: var(--s3);
}

/* The lens tag follows its label immediately rather than being pushed to the
   rail's far edge: right-aligned tags read as loose marks floating in the margin
   between the rail and the article, and they are the first thing a bleeding
   figure would collide with. */
.rail-list a {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--s3);
  align-items: baseline;
  justify-content: flex-start;
  min-height: 44px;
  padding-block: var(--s2);
  padding-inline-end: var(--s4);
  padding-inline-start: var(--s3);
  border-inline-start: 2px solid transparent;
  font-size: var(--t-fine);
  line-height: 1.4;
  color: var(--ink-3);
  text-decoration: none;
  transition:
    color var(--fast) var(--ease),
    border-color var(--fast) var(--ease);
}

.rail-list a[aria-current='true'] {
  border-inline-start-color: var(--accent);
  color: var(--ink);
}

/* The rail's smallest type. It sits at 11px rather than the 10px the composition
   was drawn at: the tag is a real word a reader has to identify, and the width
   the extra pixel costs is given back by tighter tracking, so the rail keeps its
   one-line-per-entry rhythm. */
.rail-lens {
  flex: none;
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  color: var(--ink-3);
}

@media (hover: hover) and (pointer: fine) {
  .rail-list a:hover {
    color: var(--ink);
  }
}

/* --- sections ------------------------------------------------------------ */

main {
  padding-block: var(--s10) var(--s11);
}

.section + .section {
  margin-block-start: var(--rhythm);
}

.section-head {
  display: flex;
  gap: var(--s5);
  align-items: baseline;
  justify-content: space-between;
  margin-block-end: var(--s4);
}

h2[id],
h3[id] {
  scroll-margin-block-start: var(--s10);
}

.lens {
  flex: none;
  margin: 0;
  color: var(--ink-3);
}

.section p + p {
  margin-block-start: var(--s5);
}

.section > p,
.section > .lead {
  margin-block-start: var(--s5);
}

/* --- prose furniture ----------------------------------------------------- */

.pull {
  margin-block-start: var(--s6);
  padding: var(--s5);
  border-inline-start: 2px solid var(--accent);
  border-radius: var(--r2);
  background: var(--surface);
}

.pull p {
  color: var(--ink);
}

.port-list,
.port-ledger {
  margin-block-start: var(--s5);
}

.port-list li,
.port-ledger li {
  position: relative;
  padding-inline-start: var(--s6);
  color: var(--ink-2);
}

.port-list li + li,
.port-ledger li + li {
  margin-block-start: var(--s4);
}

.port-list li::before {
  content: '';
  position: absolute;
  inset-block-start: 0.62em;
  inset-inline-start: 0;
  width: 7px;
  height: 7px;
  border-radius: 1.5px;
  background: var(--ink-2);
}

.port-ledger .port {
  position: absolute;
  inset-block-start: 0.62em;
  inset-inline-start: 0;
  width: 7px;
  height: 7px;
  border-radius: 1.5px;
  background: var(--ink-2);
}

.port-ledger p {
  margin: 0;
  color: var(--ink-2);
}

.port-ledger strong {
  color: var(--ink);
}

.exclusion {
  margin-block-start: var(--s7);
  padding: var(--s6);
  border: 1px solid var(--rule-strong);
  border-radius: var(--r2);
}

.exclusion > p + p,
.exclusion > .port-list + p {
  margin-block-start: var(--s4);
}

.exclusion .label {
  margin-block-end: var(--s4);
}

.ledger {
  margin-block-start: var(--s6);
}

.ledger > li {
  display: grid;
  grid-template-columns: var(--s8) minmax(0, 1fr);
  padding-block: var(--s6);
  border-block-start: 1px solid var(--rule);
}

.ledger > li:last-child {
  border-block-end: 1px solid var(--rule);
}

.ledger-num {
  color: var(--accent-deep);
}

.ledger-body > * + * {
  margin-block-start: var(--s4);
}

.ledger-body p {
  color: var(--ink-2);
}

/* The bolded lead-in of an authored list row. It reads at heading weight without
   being one, because the same words also title a principle further down. */
.ledger-lead {
  color: var(--ink);
  font-size: var(--t-h3);
  font-weight: 660;
  line-height: 1.25;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.ledger-lead strong {
  font-weight: inherit;
}

.phases {
  margin-block-start: var(--s6);
}

.phase {
  padding-block: var(--s6);
  border-block-start: 1px solid var(--rule);
}

.phase:last-child {
  border-block-end: 1px solid var(--rule);
}

.phase .label {
  margin-block-end: var(--s3);
}

.well {
  margin-block-start: var(--s7);
  padding: var(--s5);
  border-radius: var(--r2);
  background: var(--surface);
}

.well .label {
  margin-block-end: var(--s3);
}

.repair {
  margin-block-start: var(--s4);
  padding: var(--s4);
  border-radius: var(--r1);
  background: var(--surface);
}

.repair .label {
  margin-block-end: var(--s2);
}

.repair p {
  font-size: var(--t-fine);
}

/* --- the control-loop figure --------------------------------------------- */

.figure {
  /* The one use of a shadow on this page, and it is a lit edge rather than a
     float: on a dark ground a raised surface reads through its highlight. */
  box-shadow: inset 0 1px 0 oklch(1 0 0 / 0.045);
  margin-block-start: var(--s7);
  padding: var(--s5);
  border: 1px solid var(--rule-strong);
  border-radius: var(--r3);
  background: var(--sheet);
}

.fig {
  display: block;
  width: 100%;
  height: auto;
}

.fig-narrow {
  display: none;
}

.figure figcaption {
  margin-block-start: var(--s4);
  font-size: var(--t-fine);
  line-height: 1.55;
  color: var(--ink-3);
}

.fig text {
  font-family: var(--font-mono);
  fill: var(--ink-3);
}

.fig-sheet,
.fig-id,
.fig-badge-text,
.fig-path-label {
  font-weight: 560;
  letter-spacing: 0.12em;
}

.fig-sheet {
  font-size: 13px;
  /* The sheet furniture is authored in sentence case and shouted here, so the
     string a screen reader announces is not an all-caps one. A browser that
     ignores `text-transform` inside SVG still prints a readable label. */
  text-transform: uppercase;
}

.fig-id {
  font-size: 12px;
  letter-spacing: 0.14em;
  font-variant-numeric: tabular-nums;
}

.fig-badge-text {
  font-size: 11px;
}

/* The station verb and the legend read as prose, so they leave the mono set. */
.fig text.fig-verb {
  font-family: var(--font-sans);
  font-size: 12px;
  letter-spacing: 0;
  fill: var(--ink-3);
}

.fig text.fig-legend-label {
  font-family: var(--font-sans);
  font-size: 13px;
  letter-spacing: 0;
  fill: var(--ink-3);
}

/* The forward labels sit in a 72-unit channel between two station frames and a
   9-character label tracked at 0.12em is 71 units wide, so the tracking is
   tightened here rather than letting a label cross a hairline. */
.fig-path-label {
  font-size: 11px;
  letter-spacing: 0.06em;
}

/* Both selectors carry the element so they outrank `.fig text`; without it the
   station names and row labels inherit the mono stack and overrun their frame. */
.fig text.fig-name {
  font-family: var(--font-sans);
  font-size: 21px;
  font-weight: 660;
  letter-spacing: -0.02em;
  fill: var(--ink);
}

.fig text.fig-row {
  font-family: var(--font-sans);
  font-size: 14px;
  letter-spacing: 0;
  fill: var(--ink-2);
}

.fig-gate-label,
.fig-return-label,
.fig-trunk-label {
  font-size: 11px;
  font-weight: 560;
  letter-spacing: 0.12em;
  fill: var(--accent-deep);
}

.fig-trunk-label {
  font-size: 12px;
  letter-spacing: 0.16em;
}

.fig-frame {
  fill: var(--surface);
  stroke: var(--ink-3);
  stroke-width: 1;
}

.fig-halo {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.6;
  opacity: 0;
  transition: opacity var(--base) var(--ease);
}

.fig-divider {
  stroke: var(--rule-strong);
  stroke-width: 1;
}

.fig-rule {
  stroke: var(--rule);
  stroke-width: 1;
}

.fig-rule-strong {
  stroke: var(--rule-strong);
  stroke-width: 1;
}

.fig-port {
  fill: var(--ink-2);
}

.fig-badge {
  fill: none;
  stroke: var(--rule-strong);
  stroke-width: 1;
}

/* The forward path is deliberately quieter than the accent return path: with the
   house cyan at almost the same lightness as `--ink-2`, a 28px legend sample of
   each was hard to tell apart, and the figure's whole asymmetry is that ordinary
   work is neutral while evidence is emphasized. */
.fig-work {
  stroke: var(--ink-3);
  stroke-width: 1.4;
  fill: none;
}

.fig-arrow-work {
  fill: var(--ink-3);
}

.fig-evidence,
.fig-evidence-static {
  stroke: var(--accent);
  stroke-width: 1.8;
  fill: none;
  stroke-linejoin: round;
}

.fig-arrow-evidence {
  fill: var(--accent);
}

.fig-gate {
  stroke: var(--accent);
  stroke-width: 1.8;
}

.fig-gate-cap {
  fill: var(--accent);
}

/* The narrow plate is a 360-unit composition, so its type is set at the sizes
   that composition was drawn for rather than inheriting the wide plate's. The
   badge widths are derived from these sizes, so the two must agree. */
.fig-narrow text.fig-sheet,
.fig-narrow text.fig-id,
.fig-narrow text.fig-verb {
  font-size: 11px;
}

.fig-narrow text.fig-name {
  font-size: 19px;
}

.fig-narrow text.fig-badge-text,
.fig-narrow text.fig-path-label,
.fig-narrow text.fig-gate-label,
.fig-narrow text.fig-return-label,
.fig-narrow text.fig-trunk-label {
  font-size: 10px;
}

.fig-narrow text.fig-legend-label {
  font-size: 12px;
}

/* The one expressive moment: the return path draws itself once. Both states
   declare the dash pattern so the transition cannot start from no pattern, and
   an absent attribute means the path is simply complete. */
.figure[data-draw='pending'] .fig-evidence {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}

.figure[data-draw='done'] .fig-evidence {
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
  transition: stroke-dashoffset var(--draw) var(--ease);
}

.figure[data-tabs='on'] .station {
  cursor: pointer;
}

.station.is-selected .fig-halo {
  opacity: 1;
}

@media (hover: hover) and (pointer: fine) {
  .figure[data-tabs='on'] .station:hover .fig-halo {
    opacity: 0.4;
  }

  .figure[data-tabs='on'] .station.is-selected:hover .fig-halo {
    opacity: 1;
  }
}

/* --- station selector and briefs ---------------------------------------- */

.station-select {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--s2);
  margin-block-start: var(--s6);
}

.station-select a {
  display: flex;
  gap: var(--s2);
  align-items: center;
  min-height: 48px;
  padding-inline: var(--s5);
  border: 1px solid var(--rule-strong);
  border-radius: var(--r2);
  background: var(--paper);
  color: var(--ink-2);
  font-size: var(--t-fine);
  text-decoration: none;
  transition:
    background-color var(--fast) var(--ease),
    border-color var(--fast) var(--ease),
    color var(--fast) var(--ease),
    transform var(--fast) var(--ease);
}

.station-select a:active {
  transform: translateY(1px);
}

.station-select a[aria-selected='true'] {
  border-color: var(--accent);
  background: var(--accent-wash);
  color: var(--accent-deep);
}

@media (hover: hover) and (pointer: fine) {
  .station-select a:hover {
    border-color: var(--ink-3);
    color: var(--ink);
  }

  .station-select a[aria-selected='true']:hover {
    border-color: var(--accent);
    color: var(--accent-deep);
  }
}

.glyph {
  flex: none;
  width: 8px;
  height: 8px;
  border: 1.5px solid currentColor;
  border-radius: 1.5px;
}

.station-select a[aria-selected='true'] .glyph {
  background: currentColor;
}

.num {
  letter-spacing: 0.1em;
}

.briefs-heading {
  margin-block-start: var(--s8);
}

.briefs {
  margin-block-start: var(--s4);
  display: grid;
  gap: var(--s3);
}

.brief {
  padding: var(--s4);
  border: 1px solid var(--rule);
  border-radius: var(--r2);
  background: var(--paper);
}

/* A label, not a heading: the four stations already own real headings below the
   briefs, so this carries the `h4` type treatment without entering the outline. */
.brief-title {
  margin-block-end: var(--s3);
  font-size: var(--t-body);
  font-weight: 660;
  line-height: 1.3;
  letter-spacing: -0.01em;
}

.brief-row {
  display: grid;
  grid-template-columns: 132px minmax(0, 1fr);
  gap: var(--s3);
  padding-block: var(--s2);
}

.brief-row + .brief-row {
  border-block-start: 1px solid var(--rule);
}

.brief dt {
  font-size: var(--t-fine);
  font-weight: 620;
  color: var(--ink-3);
}

.brief dd {
  font-size: var(--t-fine);
  line-height: 1.5;
  color: var(--ink);
}

.brief-link {
  display: inline-block;
  min-height: 44px;
  margin-block-start: var(--s3);
  font-size: var(--t-fine);
  color: var(--ink-2);
}

.brief[role='tabpanel'] {
  animation: brief-in var(--move) var(--ease-out) both;
}

@keyframes brief-in {
  from {
    opacity: 0;
    transform: translateY(4px);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

.stations {
  margin-block-start: var(--s10);
}

.station-detail + .station-detail {
  margin-block-start: var(--s10);
}

.station-detail > * + * {
  margin-block-start: var(--s5);
}

/* --- team grid and trade-offs ------------------------------------------- */

.team-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  margin-block-start: var(--s6);
  background: var(--rule);
  border-block: 1px solid var(--rule);
}

.team-cell {
  padding: var(--s6);
  background: var(--paper);
}

.team-cell p {
  margin-block-start: var(--s3);
  color: var(--ink-2);
}

.trades {
  margin-block-start: var(--s6);
}

.trade {
  display: grid;
  grid-template-columns: 224px minmax(0, 1fr);
  gap: var(--s6);
  padding-block: var(--s6);
  border-block-start: 1px solid var(--rule);
}

.trade:last-child {
  border-block-end: 1px solid var(--rule);
}

.trade-versus {
  display: block;
  color: var(--ink-3);
  font-weight: 560;
}

.trade h3 {
  font-size: var(--t-h3);
}

.trade-body p {
  color: var(--ink-2);
}

/* --- fit table ---------------------------------------------------------- */

.table-block {
  margin-block-start: var(--s7);
}

.scroll-x {
  overflow-x: auto;
  scrollbar-width: thin;
}

.fit-table {
  table-layout: fixed;
  width: 100%;
  min-width: 720px;
  border-collapse: collapse;
  font-size: var(--t-fine);
}

.table-caption {
  margin-block-end: var(--s3);
  font-size: var(--t-fine);
  color: var(--ink-3);
}

.only-narrow {
  display: none;
}

.fit-table th,
.fit-table td {
  padding: var(--s3) var(--s4);
  text-align: start;
  vertical-align: top;
  border-block-end: 1px solid var(--rule);
}

.fit-table thead th {
  border-block-end: 1px solid var(--rule-strong);
  font-weight: 620;
  color: var(--ink-3);
}

.fit-table thead th:first-child {
  width: 200px;
}

.fit-table thead th + th {
  width: 260px;
}

.fit-table tbody th {
  font-weight: 660;
  color: var(--ink);
}

.fit-table td {
  color: var(--ink-2);
}

.verdict-glyph {
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-inline-end: var(--s2);
  border: 1.5px solid var(--ink-3);
  border-radius: 1.5px;
}

.verdict-glyph.filled {
  background: var(--ink-3);
}

/* --- checklist, tracks, transitions ------------------------------------- */

.checklist {
  margin-block-start: var(--s5);
}

.checklist li {
  display: grid;
  grid-template-columns: var(--s7) minmax(0, 1fr);
  align-items: start;
  padding-block: var(--s4);
  border-block-start: 1px solid var(--rule);
}

.checklist li:last-child {
  border-block-end: 1px solid var(--rule);
}

.check {
  width: 14px;
  height: 14px;
  margin-block-start: 0.4em;
  border: 1px solid var(--rule-strong);
  border-radius: var(--r1);
}

/* Both the question and its parenthetical are explicitly placed in the text
   column. Without this the aside is a third grid child, so it lands in the 32px
   marker track and wraps one word per line. */
.question,
.question-aside {
  grid-column: 2;
}

.question-aside {
  display: block;
  margin-block-start: var(--s1);
  font-size: var(--t-fine);
  color: var(--ink-3);
}

.tracks-head {
  display: flex;
  gap: var(--s5);
  align-items: baseline;
  justify-content: space-between;
  margin-block-start: var(--s9);
}

.tracks-marker {
  flex: none;
  margin: 0;
  color: var(--ink-3);
}

.tracks-note {
  margin-block-start: var(--s3);
  font-size: var(--t-fine);
  color: var(--ink-3);
}

.tracks {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s4);
  margin-block-start: var(--s4);
}

.track {
  padding: var(--s6);
  border: 1px solid var(--rule);
  border-radius: var(--r2);
  background: var(--surface);
}

.track h4 {
  margin-block: var(--s3) var(--s3);
}

.track p {
  color: var(--ink-2);
}

.chip {
  display: inline-block;
  margin-block-end: var(--s5);
  padding: var(--s2) var(--s3);
  border: 1px solid var(--accent-rule);
  border-radius: var(--r1);
  color: var(--accent-deep);
}

/* Three observations, one row where the column allows it. Stacked full-width
   they read as three unrelated fragments; side by side the figures share a
   baseline and the set reads as one comparable group. */
.transitions {
  display: grid;
  gap: var(--s8) var(--s6);
  margin-block-start: var(--s7);
}

@media (min-width: 701px) {
  .transitions {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-template-rows: auto auto;
    gap: var(--s6) var(--s7);
  }

  /* Subgrid so the three labels share one baseline even though one figure
     carries a qualifier line the other two do not. Without it the odd tile's
     label sits lower than its neighbours and the row stops reading as a set. */
  .transition {
    display: grid;
    grid-row: span 2;
    grid-template-rows: subgrid;
  }
}

.transition-terms {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--s4);
  align-items: baseline;
  font-size: var(--t-h3);
  font-weight: 660;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

.transition-arrow {
  color: var(--ink-3);
  font-size: var(--t-body);
  letter-spacing: 0;
}

/* The hedge the source states, printed at the figure rather than under it, so
   the multiple is never read as a measured value. */
.transition-qualifier {
  width: 100%;
  margin-block-start: var(--s1);
  font-size: var(--t-fine);
  font-weight: 500;
  letter-spacing: 0;
  color: var(--ink-3);
}

.transition-label {
  margin-block-start: var(--s2);
  font-size: var(--t-fine);
  color: var(--ink-3);
}

/* --- apparatus ---------------------------------------------------------- */

.apparatus {
  margin-block-start: var(--s6);
  padding: var(--s6);
  border-radius: var(--r3);
  background: var(--surface);
}

.apparatus-block + .apparatus-block {
  margin-block-start: var(--s6);
  padding-block-start: var(--s6);
  border-block-start: 1px solid var(--rule);
}

.apparatus-block .label {
  margin-block-end: var(--s3);
}

.apparatus-block p {
  color: var(--ink-2);
}

.apparatus-well {
  margin-block-start: var(--s6);
  padding: var(--s4);
  border-radius: var(--r1);
  background: var(--paper);
}

.apparatus-well p {
  color: var(--ink-2);
}

.apparatus-date {
  margin-block-start: var(--s3);
  font-size: var(--t-fine);
  color: var(--ink-3);
}

/* --- colophon ----------------------------------------------------------- */

.colophon {
  border-block-start: 1px solid var(--rule);
}

.colophon > .page {
  padding-block: var(--s10);
}

.colophon-line {
  color: var(--ink-2);
}

.action {
  /* A grid item stretches by default, which would turn the page's one filled
     action into a full-width bar. */
  justify-self: start;
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  margin-block-start: var(--s6);
  padding-inline: var(--s6);
  border-radius: var(--r2);
  background: var(--accent-deep);
  color: var(--on-accent);
  font-weight: 660;
  text-decoration: none;
  transition:
    transform var(--fast) var(--ease),
    background-color var(--fast) var(--ease);
}

.action:active {
  transform: translateY(1px);
}

@media (hover: hover) and (pointer: fine) {
  .action:hover {
    background: var(--accent);
  }
}

.colophon-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3) var(--s6);
  margin-block-start: var(--s6);
  color: var(--ink-3);
}

.colophon-links a {
  display: inline-block;
  min-height: 44px;
  line-height: 44px;
  padding-block: 0;
}

.colophon-meta {
  margin-block-start: var(--s6);
  font-size: var(--t-fine);
  color: var(--ink-3);
}

/* --- responsive recomposition ------------------------------------------- */

/* How far a plate may break past the text column. It stays under the 64px rail
   gap so a bleeding figure can never reach the contents rail: the design's 100px
   break was authored against the text column alone and would overlap the rail by
   36px once the two-column shell is present. */
@media (min-width: 821px) {
  :root {
    --break: 40px;
  }
}

@media (min-width: 1024px) {
  :root {
    --break: 48px;
  }
}

/* Below the two-column shell the rail leaves the page: the three route cards
   already carry an anchor to every section, so nothing becomes unreachable, and
   one static document cannot both open and close a disclosure by viewport. */
@media (max-width: 1239px) {
  .page,
  .shell {
    --cluster: var(--text-max);

    grid-template-columns: minmax(0, var(--text-max));
  }

  .page > *,
  .shell > * {
    grid-column: 1;
  }

  .rail {
    display: none;
  }
}

@media (max-width: 820px) {
  .team-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .trade {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s3);
  }

  .tracks {
    grid-template-columns: minmax(0, 1fr);
  }

  .only-narrow {
    display: block;
    margin-block-start: var(--s1);
  }

  /*
   * The criterion column is pinned so both verdicts stay readable against the
   * row they belong to. The header's first cell is pinned with it: without that
   * the column headings scroll away from the column they name, and by the second
   * verdict nobody can tell which one they are reading.
   *
   * The hairline and the short scrim are what make the pin legible. Scrolled
   * cells pass *under* this column, so with no edge the two texts butt together
   * and read as one broken word; the shadow says "this text continues behind
   * here" and the padding gives the criterion its own gutter to end in.
   */
  .fit-table thead th:first-child,
  .fit-table tbody th {
    position: sticky;
    inset-inline-start: 0;
    z-index: 1;
    padding-inline-end: var(--s5);
    background: var(--paper);
    /* "specification" is wider than the pinned column at 320px, and a word that
       cannot fit spills past its padding and out of the cell box entirely —
       which is what put a scrolled letter flush against it. */
    overflow-wrap: anywhere;
    box-shadow:
      inset -1px 0 0 0 var(--rule-strong),
      8px 0 10px -8px oklch(0.04 0.02 245 / 0.85);
  }

  .fit-table thead th:first-child {
    z-index: 2;
  }
}

@media (max-width: 700px) {
  /* The heading row has no margin left to hold a tag beside a wrapping h2; the
     route cards carry route membership at every width, so the tag steps out
     rather than competing with the heading for the same line. */
  .lens {
    display: none;
  }

  .fig-wide {
    display: none;
  }

  .fig-narrow {
    display: block;
  }

  .routes-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .station-select {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .ledger > li,
  .checklist li {
    grid-template-columns: var(--s7) minmax(0, 1fr);
  }

  .figure,
  .apparatus,
  .exclusion,
  .track,
  .team-cell {
    padding: var(--s4);
  }

  .brief-row {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s1);
  }
}

@media (max-width: 430px) {
  :root {
    --gutter: 20px;
  }

  /* The meta strip wraps to two or three lines here, and a separator hanging at
     the end of a line reads as a typo. The flex gap separates the items. */
  .meta {
    gap: var(--s2) var(--s5);
  }

  .meta li:not(:last-child)::after {
    content: none;
  }
}

@media (max-width: 360px) {
  :root {
    --gutter: 16px;
  }

  .fit-table {
    min-width: 532px;
  }

  .fit-table thead th:first-child {
    width: 132px;
  }

  .fit-table thead th + th {
    width: 200px;
  }

  .transition-terms {
    flex-direction: column;
    gap: var(--s1);
    align-items: start;
  }

  .transition-arrow {
    transform: rotate(90deg);
  }
}

/* Short landscape viewports: nothing may hold a sticky band, and no element
   depends on viewport height. The skip link stays fixed — it is off-canvas until
   focused, and making it static would print it across the masthead. */
@media (max-height: 460px) and (orientation: landscape) {
  .rail {
    position: static;
    display: none;
  }

  :root {
    --rhythm: 40px;
  }

  .masthead-band {
    padding-block: var(--s4);
  }

  .masthead-title {
    padding-block: var(--s4) var(--s7);
  }

  h1 {
    font-size: 28px;
  }

  .deck {
    font-size: var(--t-body);
  }
}

/* --- reduced motion ----------------------------------------------------- */

/* Less movement, not less feedback: every state change above still happens, and
   only displacement is removed. The return path renders complete because the
   module never installs the draw under this preference. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }

  .figure[data-draw] .fig-evidence {
    stroke-dasharray: none;
    stroke-dashoffset: 0;
  }

  .brief[role='tabpanel'] {
    animation: brief-fade 120ms linear both;
  }

  .station-select a:active {
    transform: none;
    background: var(--surface);
  }

  .action:active {
    transform: none;
  }

  @keyframes brief-fade {
    from {
      opacity: 0;
    }

    to {
      opacity: 1;
    }
  }
}

/* --- print -------------------------------------------------------------- */

/* Print is this design's native state, so the print rules are removals. The
   light token block is forced so a reader on a dark OS does not print a black
   page, and the figure keeps its one accent stroke because that stroke is the
   figure's meaning. */
@media print {
  :root {
    color-scheme: light;

    --paper: #ffffff;
    --surface: #f4f6f8;
    --sheet: #ffffff;
    --ink: #15181d;
    --ink-2: #3c4249;
    --ink-3: #5a616a;
    --rule: #d8dde2;
    --rule-strong: #b9c0c8;
    --accent: #0b6f95;
    --accent-deep: #085a7a;
    --accent-wash: transparent;
    --accent-rule: #c1bdb8;
    --break: 0px;
    --rhythm: 28px;
  }

  @page {
    margin: 16mm;
  }

  body {
    background: #ffffff;
    font-size: 10.5pt;
  }

  .print-only {
    display: block;
    margin-block-end: var(--s4);
  }

  .skip,
  .rail,
  .station-select,
  .only-narrow,
  .brief-arrow {
    display: none;
  }

  .routes .route-sections {
    display: none;
  }

  .fig-wide {
    display: block;
  }

  .fig-narrow {
    display: none;
  }

  #fig-loop {
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
  }

  [role='tabpanel'][hidden] {
    display: block !important;
  }

  .scroll-x {
    overflow: visible;
  }

  .fit-table {
    min-width: 0;
  }

  .fit-table thead th:first-child,
  .fit-table tbody th {
    position: static;
    box-shadow: none;
  }

  .figure,
  .apparatus,
  .brief,
  .well,
  .pull,
  .repair,
  .track,
  table,
  tr,
  li {
    break-inside: avoid;
  }

  h1,
  h2,
  h3,
  h4 {
    break-after: avoid-page;
  }

  a[href^='http']::after {
    content: ' (' attr(href) ')';
    font-size: 0.85em;
    color: var(--ink-3);
  }

  a {
    text-decoration-color: var(--rule-strong);
  }

  .figure {
    box-shadow: none;
  }
}
