:root {
    --bg: #f4f5f6;
    --surface: #e9ebee;
    --surface-raised: #fbfbfc;
    --text: #111418;
    --muted: #4a5260;
    --accent: #0b4a8f;
    --accent-soft: #dfe8f3;
    --accent-contrast: #ffffff;
    --support: #34505e;
    --border: #d3d7dd;
    --border-strong: #6b7380;
    --focus: #0b4a8f;
    --signal: #c8f000;
    --signal-ink: #111418;
    --graphite: #16191e;
    --on-graphite: #e9ecef;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #101216;
    --surface: #171a1f;
    --surface-raised: #1d2127;
    --text: #e8eaed;
    --muted: #a3abb6;
    --accent: #8fb8ff;
    --accent-soft: #1a2535;
    --accent-contrast: #0b0d10;
    --support: #9fb8c4;
    --border: #2a2f37;
    --border-strong: #7d8693;
    --focus: #c8f000;
    --signal: #c8f000;
    --signal-ink: #0b0d10;
    --graphite: #07080a;
    --on-graphite: #e8eaed;
  }
}

/* Schibsted Grotesk, served from this origin (SIL Open Font License 1.1,
   /fonts/OFL.txt). One variable file covers weights 400-900 for the Latin range
   the site is written in; anything outside it falls back to the system stack. */
@font-face {
  font-family: 'Schibsted Grotesk';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url('/fonts/schibsted-grotesk-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* DEV-WEB educational website — base stylesheet.
   Colour custom properties are generated from website/lib/tokens.mjs and
   prepended at build time. No JavaScript is used anywhere on the site, so
   keyboard operation and reduced-capability browsers keep working.

   Identity (redesign approved 2026-10-30): the site is drawn as a technical
   drawing of itself. Graphite neutrals, hairline rules, near-square corners,
   one deep ink for links, and one hi-vis signal used only as a fill or a mark.
   Labels are set in the system monospace, the way a drawing annotates its
   parts; reading text stays in the sans. Deliberately not the warm cream
   paper, editorial serif, deep green, and rust signal of the PAB-AEOS
   reference site, which informed how this site *explains* a system and not
   how it looks. */

/* --- scale ---------------------------------------------------------------
   Corners are near-square on purpose: containment is drawn with a hairline,
   not with a soft card. Type follows a 1.333 modular scale from the body
   size, so a heading is visibly a different thing from the text under it.
   There are only three small sizes: the mono label, the body, and the first
   heading step. Secondary text is told apart by colour, not by a size one
   pixel smaller (Impeccable flat-type-hierarchy, 2026-10-30). */
:root {
  --radius-sm: 2px;
  --radius-md: 4px;
  --radius-lg: 6px;
  --masthead-h: 3.5rem;
  --mono: ui-monospace, "Cascadia Mono", "SF Mono", Menlo, Consolas, monospace;
  --step--1: 0.8125rem;
  --step-small: 1em;
  --step-1: 1.333rem;
  --step-2: 1.777rem;
  --step-3: 2.369rem;
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--masthead-h) + 1rem);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: 'Schibsted Grotesk', ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 1rem;
  line-height: 1.65;
  overflow-wrap: break-word;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

@media (min-width: 48rem) {
  body {
    font-size: 1.0625rem;
  }
}

h1,
h2,
h3 {
  line-height: 1.15;
  text-wrap: balance;
  margin: 0 0 0.5em;
  letter-spacing: -0.02em;
  font-weight: 700;
}

h1 {
  font-weight: 800;
  letter-spacing: -0.03em;
}

h3 {
  font-size: var(--step-1);
  letter-spacing: -0.01em;
}

p {
  margin: 0 0 1em;
}

b {
  font-weight: 650;
}

code {
  font-family: var(--mono);
  font-size: var(--step--1);
}

a {
  color: var(--accent);
  text-underline-offset: 0.2em;
  text-decoration-thickness: 1px;
}

a:hover {
  text-decoration-thickness: 2px;
}

:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Motion is used only to soften state changes, and only for readers who want it. */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    transition-duration: 0.001ms !important;
    animation-duration: 0.001ms !important;
    /* A staggered entrance whose delays survive is still motion: the reader
       watches pieces jump into place one after another. Neutralising the delays
       as well means the page is simply already settled. */
    transition-delay: 0ms !important;
    animation-delay: 0ms !important;
  }
}

/* The shared annotation voice: small monospace labels, the way a drawing names
   its parts. Uppercase is never tracked wider than 0.04em. */
.nav__label,
.nav__wheregroup,
.primer__heading,
.example__label,
.compare caption,
.flow__stagelabel,
.map__tag,
.map__arrow,
.trace__heading,
.spatial__kicker,
.slab__index,
.slab__zone,
.deck__seamlabel,
.rail__phases,
.gate__barlabel,
.plate__index,
.plate__zone {
  font-family: var(--mono);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1.4;
}

/* --- skip link ---------------------------------------------------------- */

.skip {
  position: absolute;
  left: 0.75rem;
  top: -4rem;
  z-index: 60;
  padding: 0.65rem 1.1rem;
  background: var(--signal);
  color: var(--signal-ink);
  border-radius: 0 0 var(--radius-md) var(--radius-md);
  text-decoration: none;
  font-weight: 700;
}

/* No transition here on purpose. A skip link that animates into place does not
   appear at all where transitions never advance, which would make the one
   control a keyboard user needs first the most fragile one on the page. */
.skip:focus {
  top: 0;
}

/* --- shell -------------------------------------------------------------- */

.shell {
  width: 100%;
  max-width: 82rem;
  margin: 0 auto;
  padding: 0 1rem;
}

@media (min-width: 48rem) {
  .shell {
    padding: 0 2rem;
  }
}

/* --- masthead and navigation -------------------------------------------- */

/* One row. The site map is a native disclosure, so the first screen belongs
   to the page, and every route is still in the DOM of every page. */
.masthead {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in oklab, var(--bg) 88%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--border);
}

.masthead__bar {
  display: flex;
  align-items: center;
  gap: 1rem;
  min-height: var(--masthead-h);
}

.brand {
  display: inline-flex;
  align-items: baseline;
  gap: 0.6rem;
  color: var(--text);
  text-decoration: none;
  flex: none;
}

/* The wordmark's mark is the signal square: the one fill on the page that is
   not information, kept as identity. */
.brand__mark {
  width: 0.7rem;
  height: 0.7rem;
  background: var(--signal);
  outline: 1px solid var(--text);
  align-self: center;
  flex: none;
}

.brand__name {
  font-weight: 800;
  letter-spacing: -0.01em;
}

.brand__role {
  display: none;
  font-size: var(--step--1);
  color: var(--muted);
}

@media (min-width: 40rem) {
  .brand__role {
    display: inline;
  }
}

.nav {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 1rem;
  min-width: 0;
}

.nav__where {
  display: none;
  margin: 0;
  min-width: 0;
  font-size: var(--step-small);
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

@media (min-width: 56rem) {
  .nav__where {
    display: block;
  }
}

.nav__wheregroup {
  color: var(--support);
}

.nav__wheregroup::after {
  content: " /";
}

.nav__wherepage {
  color: var(--text);
  font-weight: 600;
}

.sitemap__toggle {
  cursor: pointer;
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.8rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  font-weight: 650;
  font-size: var(--step-small);
  white-space: nowrap;
  transition: background-color 160ms var(--ease-out), border-color 160ms var(--ease-out);
}

.sitemap__toggle::-webkit-details-marker {
  display: none;
}

.sitemap__toggle::before {
  content: "+";
  font-family: var(--mono);
  font-weight: 700;
}

.sitemap[open] .sitemap__toggle::before {
  content: "–";
}

.sitemap__toggle:hover,
.sitemap[open] .sitemap__toggle {
  background: var(--surface);
  border-color: var(--text);
}

/* The opened map spans the masthead (the nearest positioned ancestor) and
   lines its columns up with the page shell. */
.sitemap .nav__groups {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  max-height: calc(100vh - var(--masthead-h));
  overflow-y: auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1.25rem;
  padding: 1.25rem max(1rem, calc((100vw - 82rem) / 2 + 2rem)) 1.5rem;
  background: var(--bg);
  border-bottom: 1px solid var(--border-strong);
}

/* Said outright rather than left to the engine: an engine that does not hide
   a closed disclosure's content once it is given a display value would
   otherwise paint the whole map over the page. */
.sitemap:not([open]) .nav__groups {
  display: none;
}

@media (min-width: 34rem) {
  .sitemap .nav__groups {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 62rem) {
  .sitemap .nav__groups {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 2rem;
  }
}

.nav__label {
  margin: 0 0 0.4rem;
  padding-bottom: 0.4rem;
  border-bottom: 1px solid var(--border);
  color: var(--support);
}

.nav__list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.15rem;
}

.nav__link {
  display: block;
  padding: 0.3rem 0;
  text-decoration: none;
  color: var(--text);
  line-height: 1.35;
}

.nav__link:hover {
  color: var(--accent);
  text-decoration: underline;
}

/* The current page is marked with weight, colour, and the signal square that
   the wordmark uses: "you are here" on the map. */
.nav__link[aria-current="page"] {
  font-weight: 700;
  color: var(--accent);
}

.nav__link[aria-current="page"]::before {
  content: "";
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  margin-right: 0.45rem;
  background: var(--signal);
  outline: 1px solid var(--text);
  vertical-align: 0.1em;
}

/* --- page hero (every page but home) ------------------------------------ */

.hero {
  padding: 3rem 0 2.25rem;
  border-bottom: 1px solid var(--border);
}

@media (min-width: 48rem) {
  .hero {
    padding: 4.5rem 0 3rem;
  }
}

.hero__title {
  font-size: clamp(2.3rem, 1.6rem + 2.8vw, var(--step-3) * 1.5);
  max-width: 22ch;
  margin-bottom: 0.9rem;
  line-height: 1.05;
}

.hero__lede {
  margin: 0;
  max-width: 44rem;
  font-size: var(--step-1);
  line-height: 1.5;
  color: var(--muted);
}

/* --- home: the exploded view -------------------------------------------- */

/* The drawing sheet: a faint construction grid behind the one place on the
   site that shows the whole stack. */
.exploded {
  position: relative;
  border-bottom: 1px solid var(--border);
  background-color: var(--bg);
  background-image:
    linear-gradient(color-mix(in oklab, var(--border) 45%, transparent) 1px, transparent 1px),
    linear-gradient(90deg, color-mix(in oklab, var(--border) 45%, transparent) 1px, transparent 1px);
  background-size: 2rem 2rem;
}

.exploded__stage {
  padding: 2.5rem 0 3rem;
}

.exploded__grid {
  display: grid;
  gap: 2.25rem;
}

@media (min-width: 64rem) {
  .exploded__stage {
    padding: 2rem 0 2.5rem;
  }

  .exploded__grid {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: 3.5rem;
    align-items: center;
  }
}

.exploded .hero__title {
  font-size: clamp(3rem, 1.6rem + 6vw, 5.5rem);
  letter-spacing: -0.04em;
  line-height: 0.95;
  margin-bottom: 1.1rem;
}

.exploded .hero__lede {
  color: var(--text);
}

.exploded__cue {
  margin: 1.75rem 0 0;
  padding-top: 1rem;
  border-top: 1px solid var(--text);
  max-width: 30rem;
  font-size: var(--step-small);
  font-weight: 600;
  line-height: 1.5;
  letter-spacing: 0;
  color: var(--muted);
}

/* Static default, and the whole lesson where motion is not welcome: the plates
   already apart, each stepped a little to the right of the one above, joined
   by a dashed construction line. */
.plates {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.9rem;
}

.plate {
  --n: 0;
  position: relative;
  z-index: var(--n);
  margin-left: calc(var(--n) * 0.4rem);
  padding: 0.95rem 1.1rem 1rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  box-shadow: 5px 5px 0 var(--border);
}

@media (min-width: 40rem) {
  .plate {
    margin-left: calc(var(--n) * 0.85rem);
  }
}

.plate + .plate::before {
  content: "";
  position: absolute;
  left: 1.5rem;
  bottom: 100%;
  height: 0.9rem;
  border-left: 1px dashed var(--border-strong);
}

.plate--1 { --n: 1; }
.plate--2 { --n: 2; }
.plate--3 { --n: 3; }
.plate--4 { --n: 4; }

.plate__meta {
  margin: 0 0 0.35rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
}

.plate__index {
  padding: 0.05rem 0.4rem;
  background: var(--signal);
  color: var(--signal-ink);
  font-variant-numeric: tabular-nums;
}

.plate__zone {
  color: var(--muted);
}

.plate__zone--bound {
  color: var(--text);
}

.plate__name {
  margin: 0 0 0.2rem;
  font-size: var(--step-1);
}

.plate__name a {
  color: inherit;
  text-decoration-color: var(--border-strong);
}

.plate__name a:hover {
  text-decoration-color: currentColor;
}

.plate__body {
  margin: 0;
  max-width: 46rem;
  font-size: var(--step-small);
  color: var(--muted);
}

/* The kernel is the layer that binds, so it is the one dark plate. */
.plate--4 {
  background: var(--graphite);
  border-color: var(--graphite);
  color: var(--on-graphite);
}

.plate--4 .plate__zone,
.plate--4 .plate__zone--bound,
.plate--4 .plate__body,
.plate--4 .plate__name a {
  color: var(--on-graphite);
}

.plate--4 .plate__name a {
  text-decoration-color: var(--signal);
}

/* Plate 0's schematic of the page itself: header bar, title, three lines.
   From tablet width it sits beside the text, so plate 0 is no taller than the
   layers under it. */
@media (min-width: 40rem) {
  .plate--0 {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 8.5rem;
    column-gap: 1.1rem;
  }

  .plate--0 > :not(.plate__sketch) {
    grid-column: 1;
  }

  .plate--0 .plate__sketch {
    grid-column: 2;
    grid-row: 1 / span 3;
    align-self: center;
    margin-top: 0;
  }
}

.plate__sketch {
  display: grid;
  gap: 0.35rem;
  margin-top: 0.85rem;
  padding: 0.6rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
}

.sketch__bar,
.sketch__title,
.sketch__line {
  display: block;
  height: 0.4rem;
  background: var(--border);
}

.sketch__bar {
  height: 0.55rem;
  margin-bottom: 0.3rem;
  background: var(--text);
}

.sketch__title {
  width: 45%;
  height: 0.8rem;
  background: var(--muted);
}

.sketch__line--short {
  width: 62%;
}

/* --- page ---------------------------------------------------------------- */

.page {
  padding: 2.5rem 0 3.5rem;
}

@media (min-width: 48rem) {
  .page {
    padding: 3.5rem 0 5rem;
  }
}

/* The diagrams inside live at the prose measure, not at the viewport width, so
   they size against their container. A viewport media query would promise a
   three-column layout that this column is never wide enough to receive. */
.prose {
  max-width: 60rem;
  container-type: inline-size;
  container-name: prose;
}

.section + .section {
  margin-top: 3.5rem;
}

.section__heading {
  font-size: clamp(1.6rem, 1.3rem + 1.2vw, var(--step-2) * 1.15);
  padding-top: 0.9rem;
  border-top: 1px solid var(--text);
}

/* --- beginner primer ------------------------------------------------------ */

/* The block every reader is meant to read first: drawn as a framed sheet with
   its own title strip, not as one more card. */
.primer {
  margin: 0 0 3.5rem;
  padding: 0 1.25rem 0.5rem;
  border: 1px solid var(--text);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  max-width: 64rem;
}

.primer__heading {
  margin: 0 -1.25rem 1.1rem;
  padding: 0.55rem 1.25rem;
  background: var(--graphite);
  color: var(--on-graphite);
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}

.primer__list {
  margin: 0;
  display: grid;
  gap: 0.9rem;
}

@media (min-width: 46rem) {
  .primer__list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1rem 2rem;
  }
}

.primer__q {
  margin: 0 0 0.2rem;
  font-weight: 700;
}

.primer__a {
  margin: 0 0 0.75rem;
  font-size: var(--step-small);
  color: var(--muted);
}

/* --- content blocks ------------------------------------------------------- */

.list {
  margin: 0 0 1.25rem;
  padding-left: 1.15rem;
}

.list li + li {
  margin-top: 0.4rem;
}

.steps {
  margin: 0 0 1.35rem;
  padding: 0;
  list-style: none;
  counter-reset: step;
  display: grid;
  gap: 0.5rem;
}

.steps li {
  counter-increment: step;
  display: grid;
  grid-template-columns: 2rem 1fr;
  gap: 0.15rem 0.75rem;
  padding: 0.8rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  transition: border-color 160ms var(--ease-out);
}

.steps li:hover {
  border-color: var(--border-strong);
}

.steps li::before {
  content: counter(step, decimal-leading-zero);
  grid-row: span 2;
  align-self: start;
  justify-self: start;
  padding: 0.05rem 0.3rem;
  background: var(--signal);
  color: var(--signal-ink);
  font-family: var(--mono);
  font-size: var(--step--1);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.step__term {
  font-weight: 650;
}

.step__gloss {
  font-size: var(--step-small);
  color: var(--muted);
}

.levels {
  margin: 0 0 1.35rem;
  display: grid;
  gap: 0.6rem;
}

/* L0 through L4 is an ascending scale of blast radius, not five unrelated
   facts, so the row carries that before a reader reaches the words: a meter
   along the top edge grows with the level. It is a measure, drawn as one, not
   a coloured side tab. */
.level {
  --level-reach: 0.2;
  position: relative;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  padding: 1.05rem 1.15rem 0.95rem;
  overflow: hidden;
}

.level::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  height: 4px;
  width: 100%;
  background: var(--text);
  transform: scaleX(var(--level-reach));
  transform-origin: left center;
}

.level--0 { --level-reach: 0.12; }
.level--1 { --level-reach: 0.3; }
.level--2 { --level-reach: 0.5; }
.level--3 { --level-reach: 0.75; }
.level--4 { --level-reach: 1; }

.level__head {
  margin: 0 0 0.3rem;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.6rem;
}

.level__id {
  display: inline-block;
  padding: 0.05rem 0.4rem;
  background: var(--signal);
  color: var(--signal-ink);
  font-family: var(--mono);
  font-weight: 600;
  font-size: var(--step--1);
  font-variant-numeric: tabular-nums;
}

.level__name {
  font-weight: 650;
}

.level__body {
  margin: 0;
  font-size: var(--step-small);
  color: var(--muted);
}

.level__meta {
  margin: 0.4rem 0 0;
  font-size: var(--step-small);
  color: var(--support);
}

.cards {
  display: grid;
  gap: 0.75rem;
  margin: 0 0 1.35rem;
}

@media (min-width: 44rem) {
  .cards {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.card {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  padding: 1.1rem 1.25rem;
  transition: border-color 160ms var(--ease-out);
}

.card:hover {
  border-color: var(--border-strong);
}

.card__title {
  margin: 0 0 0.3rem;
  font-size: var(--step-1);
}

.card__body {
  margin: 0;
  font-size: var(--step-small);
  color: var(--muted);
}

.choices {
  display: grid;
  gap: 0.75rem;
  margin: 0 0 1.35rem;
}

@media (min-width: 44rem) {
  .choices {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.choice {
  position: relative;
  display: block;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  padding: 1.1rem 3rem 1.1rem 1.25rem;
  text-decoration: none;
  color: var(--text);
  transition: border-color 160ms var(--ease-out), background-color 160ms var(--ease-out);
}

.choice:hover {
  border-color: var(--text);
  background: var(--surface);
}

.choice:hover .choice__go {
  transform: translateX(3px);
}

.choice__label {
  display: block;
  font-weight: 700;
  color: var(--accent);
  margin-bottom: 0.3rem;
}

.choice__detail {
  display: block;
  font-size: var(--step-small);
  color: var(--muted);
}

.choice__go {
  position: absolute;
  top: 1.05rem;
  right: 1.2rem;
  color: var(--accent);
  font-weight: 700;
  display: inline-block;
  transition: transform 160ms var(--ease-out);
}

.note,
.example,
.disclaimer {
  margin: 0 0 1.35rem;
  padding: 0.95rem 1.15rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--surface);
  font-size: var(--step-small);
}

.example {
  border-style: dashed;
}

.example__label {
  margin: 0 0 0.3rem;
  color: var(--support);
}

.example__body,
.disclaimer__body {
  margin: 0;
}

.disclaimer {
  border-color: var(--text);
}

.disclaimer__title {
  margin: 0 0 0.3rem;
  font-weight: 700;
}

/* --- progressive disclosure ---------------------------------------------- */

.more {
  margin: 0 0 1.35rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
}

.more__summary {
  cursor: pointer;
  padding: 0.75rem 1.05rem;
  font-weight: 650;
  color: var(--accent);
  border-radius: var(--radius-md);
  list-style: none;
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.more__summary::-webkit-details-marker {
  display: none;
}

.more__summary::before {
  content: "+";
  display: grid;
  place-items: center;
  width: 1.25rem;
  height: 1.25rem;
  flex: none;
  border: 1px solid currentColor;
  border-radius: var(--radius-sm);
  font-family: var(--mono);
  font-weight: 700;
}

.more[open] .more__summary::before {
  content: "–";
}

.more__body {
  padding: 0 1.05rem 0.35rem;
}

.more__body > *:last-child {
  margin-bottom: 0.9rem;
}

/* --- comparison table ----------------------------------------------------- */

.tablewrap {
  overflow-x: auto;
  margin: 0 0 1.35rem;
}

/* No forced minimum width on a phone: cells wrap instead of pushing the table
   into a scroll container the reader has to discover. The container keeps its
   overflow rule as a safety net for very long words, not as the normal path. */
.compare {
  border-collapse: collapse;
  width: 100%;
  font-size: var(--step-small);
}

@media (min-width: 34rem) {
  .compare {
    min-width: 28rem;
  }
}

.compare caption {
  text-align: left;
  color: var(--support);
  padding-bottom: 0.5rem;
}

.compare th,
.compare td {
  border: 1px solid var(--border);
  padding: 0.55rem 0.75rem;
  text-align: left;
  vertical-align: top;
}

.compare thead th {
  background: var(--surface);
}

.compare tbody th {
  font-weight: 650;
  color: var(--muted);
  width: 30%;
}

/* --- diagrams -------------------------------------------------------------- */

.figure {
  margin: 0 0 1.75rem;
}

.figure__caption {
  margin-top: 0.7rem;
  font-size: var(--step-small);
  color: var(--muted);
}

.flow {
  display: grid;
  gap: 0.75rem;
  padding: 1rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

@container prose (min-width: 34rem) {
  .flow {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1rem;
  }
}

.flow__stagelabel {
  margin: 0 0 0.5rem;
  color: var(--support);
}

.flow__nodes {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.4rem;
}

.flow__node {
  padding: 0.65rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  transition: border-color 160ms var(--ease-out);
}

.flow__node:hover {
  border-color: var(--text);
}

.flow__name {
  display: block;
  font-weight: 700;
  color: var(--accent);
}

.flow__meaning {
  display: block;
  font-size: var(--step-small);
  color: var(--muted);
}

.map {
  display: grid;
  gap: 0.6rem;
  padding: 1rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

@container prose (min-width: 40rem) {
  .map {
    grid-template-columns: 1fr auto 1fr;
    align-items: stretch;
    gap: 0.9rem;
  }
}

.map__space {
  padding: 0.9rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
}

/* The canonical space binds, so it is drawn on graphite, like the kernel plate
   on the home page. */
.map__space--kernel {
  background: var(--graphite);
  border-color: var(--graphite);
  color: var(--on-graphite);
}

.map__space--kernel .map__item span {
  color: var(--on-graphite);
}

.map__label {
  margin: 0 0 0.6rem;
  font-weight: 700;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}

.map__tag {
  padding: 0.05rem 0.4rem;
  background: var(--signal);
  color: var(--signal-ink);
}

.map__tag--muted {
  background: transparent;
  outline: 1px solid var(--border-strong);
  color: var(--muted);
}

.map__items {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.55rem;
}

.map__item b {
  display: block;
}

.map__item span {
  display: block;
  font-size: var(--step-small);
  color: var(--muted);
}

.map__link {
  display: grid;
  place-items: center;
  padding: 0.25rem 0;
}

.map__arrow {
  color: var(--support);
  position: relative;
  padding: 0 0.6rem;
}

.map__arrow::after {
  content: "↓";
  display: block;
  text-align: center;
  font-size: 1rem;
}

@container prose (min-width: 40rem) {
  .map__arrow::after {
    content: "→";
  }
}

/* --- traceability and related links -------------------------------------- */

.trace {
  margin-top: 3.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--text);
  max-width: 64rem;
}

.trace__heading {
  color: var(--support);
  margin-bottom: 0.5rem;
}

.trace__note {
  font-size: var(--step-small);
  color: var(--muted);
  margin-bottom: 0.75rem;
}

.trace__list {
  margin: 0 0 1.75rem;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.trace__list code {
  display: inline-block;
  padding: 0.25rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--muted);
}

.related {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.related a {
  display: inline-block;
  padding: 0.45rem 0.85rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  text-decoration: none;
  transition: background-color 140ms var(--ease-out), border-color 140ms var(--ease-out);
}

.related a:hover {
  background: var(--surface);
  border-color: var(--text);
  text-decoration: underline;
}

/* --- footer -------------------------------------------------------------- */

.footer {
  border-top: 1px solid var(--graphite);
  background: var(--graphite);
  padding: 2rem 0 2.5rem;
  font-size: var(--step-small);
  color: var(--on-graphite);
}

.footer__line {
  max-width: 64rem;
}

.footer__line:last-child {
  margin-bottom: 0;
}

/* --- spatial architecture map -------------------------------------------- */
/* The primary /architecture diagram. It is authored as a plain, complete stack
   of labelled blocks, and depth is added only inside a container wide enough to
   carry it. Nothing is drawn: elevation comes from CSS 3D transforms on real
   text, so the map keeps working with no styling, no motion, and no pointer.
   The settle animation moves transforms only and never opacity, so no part of
   the explanation can arrive by animation or fail to arrive without it. */

.spatial {
  display: grid;
  gap: 1.5rem;
  padding: 1.15rem 1rem 1.35rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  background: var(--surface);
  overflow: clip;
}

.spatial__part {
  display: grid;
  gap: 0.65rem;
}

.spatial__kicker {
  margin: 0;
  color: var(--support);
}

.spatial__title {
  margin: 0;
  font-weight: 700;
  line-height: 1.45;
}

.spatial__note {
  margin: 0;
  font-size: var(--step-small);
  color: var(--muted);
}

.deck {
  display: grid;
  gap: 0.5rem;
}

.deck__list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.5rem;
}

.slab {
  padding: 0.85rem 0.95rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
}

.slab__meta {
  margin: 0 0 0.35rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: baseline;
}

.slab__index {
  color: var(--muted);
}

.slab__zone {
  padding: 0 0.4rem;
  border: 1px solid var(--border);
  color: var(--muted);
}

.slab__zone--bound {
  border-color: var(--signal);
  background: var(--signal);
  color: var(--signal-ink);
}

.slab__name {
  margin: 0 0 0.25rem;
  font-size: var(--step-1);
}

.slab__body {
  margin: 0;
  font-size: var(--step-small);
  color: var(--muted);
}

.slab--4 {
  background: var(--graphite);
  border-color: var(--graphite);
  color: var(--on-graphite);
}

.slab--4 .slab__index,
.slab--4 .slab__body {
  color: var(--on-graphite);
}

.deck__seam {
  margin: 0;
  display: grid;
  gap: 0.2rem;
  padding: 0.6rem 0.85rem;
  border: 1px dashed var(--text);
  border-radius: var(--radius-md);
  background: var(--bg);
}

.deck__seamlabel {
  color: var(--text);
}

.deck__seamnote {
  font-size: var(--step-small);
  color: var(--muted);
}

.rail,
.gates {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.5rem;
}

.rail__step {
  display: grid;
  gap: 0.2rem;
  padding: 0.8rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
}

.rail__order {
  justify-self: start;
  padding: 0.05rem 0.4rem;
  background: var(--signal);
  color: var(--signal-ink);
  font-family: var(--mono);
  font-size: var(--step--1);
  font-weight: 600;
}

.rail__stage {
  font-weight: 700;
}

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

.rail__meaning {
  font-size: var(--step-small);
  color: var(--muted);
}

.gate {
  display: grid;
  gap: 0.35rem;
  padding: 0.85rem 0.95rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
}

.gate__from,
.gate__to,
.gate__bar {
  margin: 0;
}

.gate__from,
.gate__to {
  font-weight: 700;
}

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

.gate__barlabel {
  display: inline-block;
  padding: 0.1rem 0.5rem;
  border: 1px dashed var(--text);
  background: var(--bg);
  color: var(--text);
}

.gate__body {
  margin: 0.1rem 0 0;
  font-size: var(--step-small);
  color: var(--muted);
}

/* Depth is opt-in and container-driven. A phone gets the flat stack, which is
   the same information without the elevation, and never a squeezed 3D scene. */
@container prose (min-width: 34rem) {
  .deck {
    gap: 0.65rem;
    padding: 0.35rem 2.4rem 0.75rem;
    perspective: 1500px;
    perspective-origin: 50% 12%;
  }

  /* One shared tilt across all three children, so the two lists and the seam
     between them read as one receding stack rather than as three scenes. */
  .deck__list,
  .deck__seam {
    transform-style: preserve-3d;
    transform: rotateX(7deg);
  }

  .slab {
    transform: translate3d(var(--slide), 0, var(--lift));
    box-shadow: 0 var(--shadow-y) var(--shadow-blur) color-mix(in oklab, var(--text) var(--shadow-strength), transparent);
    animation: slab-settle 700ms var(--ease-out) var(--delay) both;
  }

  .slab--1 {
    --slide: 0.4rem;
    --lift: 70px;
    --delay: 0ms;
    --shadow-y: 22px;
    --shadow-blur: 38px;
    --shadow-strength: 22%;
  }

  .slab--2 {
    --slide: 0.2rem;
    --lift: 46px;
    --delay: 90ms;
    --shadow-y: 16px;
    --shadow-blur: 30px;
    --shadow-strength: 18%;
  }

  .slab--3 {
    --slide: 0rem;
    --lift: 22px;
    --delay: 180ms;
    --shadow-y: 10px;
    --shadow-blur: 22px;
    --shadow-strength: 14%;
  }

  .slab--4 {
    --slide: -0.2rem;
    --lift: 0px;
    --delay: 270ms;
    --shadow-y: 6px;
    --shadow-blur: 14px;
    --shadow-strength: 10%;
  }

  .deck__seam {
    transform: rotateX(7deg) translate3d(0, 0, 34px);
  }

  .rail {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.7rem;
    padding: 0.2rem 0.35rem 0.35rem;
    perspective: 1100px;
  }

  .rail__step {
    transform: rotateY(var(--turn)) translateZ(var(--lift));
    box-shadow: 0 10px 22px color-mix(in oklab, var(--text) 10%, transparent);
    animation: rail-settle 650ms var(--ease-out) var(--delay) both;
  }

  .rail__step--1 {
    --turn: 7deg;
    --lift: 0px;
    --delay: 320ms;
  }

  .rail__step--2 {
    --turn: 0deg;
    --lift: 16px;
    --delay: 400ms;
  }

  .rail__step--3 {
    --turn: -7deg;
    --lift: 0px;
    --delay: 480ms;
  }

  .gates {
    padding: 0.2rem 0.35rem 0.35rem;
    perspective: 1000px;
  }

  .gate {
    transform: translateZ(10px) rotateX(3deg);
    box-shadow: 0 10px 20px color-mix(in oklab, var(--text) 10%, transparent);
    animation: gate-settle 650ms var(--ease-out) var(--delay) both;
  }

  .gate:first-child {
    --delay: 540ms;
  }

  .gate:last-child {
    --delay: 620ms;
  }
}

@container prose (min-width: 40rem) {
  .gates {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* Every keyframe below moves transforms only, and each one ends at the element's
   own declared position. Where animation never advances — reduced motion, an old
   engine, a printed page — the map is already in its final, readable state. */
@keyframes slab-settle {
  from {
    transform: translate3d(0, 0.55rem, 0);
  }
}

@keyframes rail-settle {
  from {
    transform: rotateY(0deg) translate3d(0, 0.45rem, 0);
  }
}

@keyframes gate-settle {
  from {
    transform: rotateX(0deg) translate3d(0, 0.4rem, 0);
  }
}

/* --- scroll reveal ------------------------------------------------------- */

/* No script: where the browser supports scroll-driven animations, blocks slide
   the last few pixels into place as they enter the viewport. Only transforms
   move, so nothing is ever hidden waiting for an animation (the rule the
   keyframe test enforces), and readers who prefer reduced motion, or browsers
   without the feature, get the settled page. `backwards` fill hands every
   element back to its own styles once its range ends. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .section,
    .trace,
    .card,
    .choice,
    .level,
    .steps li,
    .primer,
    .flow__node {
      animation: reveal-rise linear backwards;
      animation-timeline: view();
      animation-range: entry 0% entry 55%;
    }

    .level {
      view-timeline-name: --level;
    }

    .level::before {
      animation: reveal-meter linear backwards;
      animation-timeline: --level;
      animation-range: entry 25% entry 100%;
    }
  }

  /* exploded view motion */
  @media (prefers-reduced-motion: no-preference) and (min-width: 64rem) {
    /* The section is taller than the screen and its stage is pinned, so the
       plates come apart while they stay in view, at the reader's own scroll
       speed. The first 55vh of scrolling pulls the stack apart; after that the
       stage simply scrolls away. */
    .exploded {
      min-height: calc(100vh + 55vh);
    }

    .exploded__stage {
      position: sticky;
      top: var(--masthead-h);
    }

    .plates {
      perspective: 1800px;
      transform-style: preserve-3d;
    }

    /* Before the reader scrolls, the five plates sit stacked tight, like a
       deck of sheets: each one covers the body of the sheet above and leaves
       its number and name in view. Scrolling spreads them to their places. */
    .plate {
      animation: plate-explode linear both;
      animation-timeline: scroll(root);
      animation-range: 0 55vh;
    }
  }
}

@keyframes plate-explode {
  from {
    transform: translate3d(calc(var(--n) * -0.6rem), calc(var(--n) * -5.2rem), 0);
  }
}

@keyframes reveal-rise {
  from { transform: translateY(20px); }
  to { transform: none; }
}

@keyframes reveal-meter {
  from { transform: scaleX(0); }
  to { transform: scaleX(var(--level-reach)); }
}
