/* Hallmark · macrostructure: scroll-film chapters (atmospheric) · theme: studied-DNA (source: the Deskspawn visual study's own tokens)
 * nav: N5 floating pill · footer: Ft5 statement · faces: Syne display, Inter body, mono data/code
 * Hallmark · pre-emit critique: P5 H4 E4 S5 R4 V5
 *
 * site.css — Deskspawn. Mobile-first. No-JS is the default layout: every page reads top to
 * bottom with posters for the scenes. html.js turns on reveals; html.lp-gl (set in <head> only
 * when WebGL2 exists and motion is allowed) turns on pinned scroll films. */
*, *::before, *::after { box-sizing: border-box }
html { -webkit-text-size-adjust: 100%; overflow-x: clip; scroll-padding-top: var(--nav-h) }
body { margin: 0; background: var(--bg); color: var(--fg); font-family: var(--font-sans); font-size: var(--t-md); line-height: 1.6; overflow-x: clip; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility }
img, video, canvas, svg { display: block; max-width: 100% }
a { color: inherit }
ul, ol { margin: 0; padding: 0 }
h1, h2, h3, p, dl, dd, figure { margin: 0 }
h1, h2, h3 { font-family: var(--font-display); font-weight: 700; line-height: 1.06; letter-spacing: -.01em; overflow-wrap: anywhere; min-width: 0; text-wrap: balance }
p { text-wrap: pretty }
.skip { position: absolute; left: -999px; top: var(--s-2); background: var(--fg); color: var(--bg); padding: var(--s-2) var(--s-3); border-radius: var(--radius-sm); z-index: 100; text-decoration: none }
.skip:focus { left: var(--s-2) }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px }
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap }

/* ---------- nav: N5 floating pill ---------- */
.nav { position: fixed; top: var(--s-3); left: 0; right: 0; z-index: var(--z-nav); display: flex; justify-content: center; padding: 0 var(--s-3); pointer-events: none; transition: transform .45s var(--ease), opacity .45s var(--ease) }
.nav.is-hidden { transform: translateY(calc(-100% - var(--s-4))); opacity: 0 }
.nav:focus-within { transform: none; opacity: 1 }
.nav__pill { pointer-events: auto; display: flex; align-items: center; gap: var(--s-2); padding: var(--s-1) var(--s-1) var(--s-1) var(--s-2); border: 1px solid var(--line-2); border-radius: var(--radius-pill); background: var(--scrim); -webkit-backdrop-filter: blur(14px) saturate(1.3); backdrop-filter: blur(14px) saturate(1.3); box-shadow: 0 10px 40px var(--scrim-soft); width: min(100%, 760px) }
.nav__brand { display: inline-flex; align-items: center; gap: var(--s-2); text-decoration: none; line-height: 1; border-radius: var(--radius-pill); flex-shrink: 0 }
.nav__word { font-family: var(--font-display); font-weight: 800; font-size: var(--t-xs); letter-spacing: .16em }
.eye { width: 40px; height: 40px; border-radius: 50%; box-shadow: 0 0 22px var(--eye-halo); overflow: visible }
.eye__ball { transform-box: view-box; transform-origin: 32px 32px; animation: eyeblink 7s infinite }
.eye__pupil { transform-box: view-box; transform-origin: 32px 32px; animation: eyelook 11s var(--ease) infinite }
@keyframes eyeblink { 0%, 44% { transform: scaleY(1) } 46% { transform: scaleY(.05) } 48%, 85% { transform: scaleY(1) } 87% { transform: scaleY(.05) } 89%, 100% { transform: scaleY(1) } }
@keyframes eyelook { 0%, 16% { transform: translate(0, 0) } 22%, 38% { transform: translate(6px, -2px) } 44%, 60% { transform: translate(-6.5px, 1px) } 66%, 78% { transform: translate(2px, 3.5px) } 84%, 100% { transform: translate(0, 0) } }
.nav__links { display: none; margin: 0 auto; gap: var(--s-1); align-items: center }
.nav__links a, .nav__menu a { font-size: var(--t-sm); font-weight: 500; line-height: 1; color: var(--fg-2); text-decoration: none; padding: var(--s-3) var(--s-3); border-radius: var(--radius-pill); white-space: nowrap; transition: color .2s var(--ease), background-color .2s var(--ease) }
.nav__links a:hover, .nav__menu a:hover { color: var(--fg); background-color: var(--line) }
.nav__links a:active, .nav__menu a:active { background-color: var(--line-2) }
.nav__links a[aria-current="page"], .nav__menu a[aria-current="page"] { color: var(--fg) }
.nav__links a[aria-current="page"]::after { content: ""; display: block; height: 1px; margin-top: var(--s-1); background: var(--violet-soft) }
.nav__cta { margin-left: auto }
.nav__menu { margin-left: auto; position: relative }
.nav__menu summary { list-style: none; cursor: pointer; font-size: var(--t-sm); font-weight: 500; line-height: 1; padding: var(--s-3) var(--s-4); border-radius: var(--radius-pill); border: 1px solid var(--line-2); color: var(--fg); white-space: nowrap }
.nav__menu summary::-webkit-details-marker { display: none }
.nav__menu summary:hover { background-color: var(--line) }
.nav__menu[open] summary { background-color: var(--line-2) }
.nav__menu nav { position: absolute; right: 0; top: calc(100% + var(--s-2)); display: grid; min-width: 220px; padding: var(--s-2); border: 1px solid var(--line-2); border-radius: var(--radius); background: var(--bg-2); box-shadow: 0 20px 50px var(--scrim) }
.nav__menu nav a { padding: var(--s-3) var(--s-4); border-radius: var(--radius-sm) }
.nav__menu + .nav__cta { margin-left: 0 }
@media (min-width: 860px) {
  .nav { top: var(--s-4) }
  .nav__links { display: flex }
  .nav__menu { display: none }
}
@media (max-width: 460px) { .nav__word { display: none } .nav__pill { gap: var(--s-1) } .nav__menu summary { padding: var(--s-3) } .nav__cta.btn { padding: 0 var(--s-3) } }

/* ---------- buttons ---------- */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2); min-height: 44px; padding: 0 var(--s-5); border-radius: var(--radius-pill); font: inherit; font-size: var(--t-sm); font-weight: 600; line-height: 1; white-space: nowrap; text-decoration: none; border: 1px solid var(--line-2); cursor: pointer; position: relative; overflow: hidden; transition: background-color .2s var(--ease), color .2s var(--ease), border-color .2s var(--ease) }
.btn--solid { background: var(--fg); color: var(--bg); border-color: var(--fg) }
.btn--solid:hover { background: var(--violet-soft); border-color: var(--violet-soft) }
.btn--solid:active { background: var(--violet); border-color: var(--violet); color: var(--fg) }
.btn--ghost { background: transparent; color: var(--fg) }
.btn--ghost:hover { border-color: var(--fg-2) }
.btn--ghost:active { background: var(--line) }
.btn[aria-disabled="true"], .btn:disabled { opacity: .55; cursor: not-allowed; pointer-events: none }
.nav__cta.btn { min-height: 40px; padding: 0 var(--s-4) }
/* light sweep: a thin band of flash light crosses the button once on hover */
.btn::after { content: ""; position: absolute; inset: 0; background: linear-gradient(100deg, var(--scrim-none) 30%, var(--flash) 50%, var(--scrim-none) 70%); opacity: .35; transform: translateX(-120%); pointer-events: none }
.btn:hover::after { transform: translateX(120%); transition: transform .7s var(--ease) }

/* ---------- shared type and layout ---------- */
.wrap { width: min(100% - 2 * var(--gutter), 1240px); margin-inline: auto }
.label { font-family: var(--font-mono); font-size: var(--t-xs); letter-spacing: .08em; color: var(--fg-3); text-transform: uppercase; line-height: 1.4 }
.lede { font-size: var(--t-lg); color: var(--fg-2); line-height: 1.55; max-width: var(--measure) }
.h1 { font-size: var(--t-3xl); font-weight: 700 }
.h2 { font-size: var(--t-2xl); font-weight: 700 }
.h3 { font-size: var(--t-xl); font-weight: 600 }
.prose { max-width: var(--measure); color: var(--fg-2) }
.prose p + p { margin-top: var(--s-4) }
.prose--gap { margin-top: var(--s-5) }
.label--head { margin-bottom: var(--s-5) }
.prose strong { color: var(--fg); font-weight: 600 }
.link { color: var(--violet-soft); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 2px; transition: color .2s var(--ease) }
.link:hover { color: var(--flash) }
.link:active { color: var(--violet) }
.wordmark { font-family: var(--font-display); font-weight: 800; font-size: var(--t-sm); letter-spacing: .22em; color: var(--fg); text-shadow: 0 0 2px var(--glow-1), 0 0 9px var(--glow-2), 0 0 22px var(--glow-3), 0 0 52px var(--glow-4) }
.src { font-family: var(--font-mono); font-size: var(--t-xs); color: var(--fg-3); line-height: 1.5 }
.cta-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3); margin-top: var(--s-6) }

.band { position: relative; padding: var(--sec-pad) 0 }
.band--rule { border-top: 1px solid var(--line) }
.band--tint { background: var(--bg-2); border-block: 1px solid var(--line) }
.band__head { display: grid; gap: var(--s-4); max-width: 46rem; margin-bottom: var(--s-8) }

/* reveals only exist when JS can reveal them */
html.js [data-reveal] { opacity: 0; transform: translateY(18px); transition: opacity .9s var(--ease), transform .9s var(--ease) }
html.js [data-reveal].is-in { opacity: 1; transform: none }

/* ---------- Living scenes (.lp) ---------- */
/* default = static: the poster behind the words, words in normal flow. Used with no JS, no
   WebGL2, reduced motion, or a scene that failed to start. */
.lp { position: relative; background: var(--bg) }
.lp-pin { position: relative; isolation: isolate; overflow: hidden; min-height: min(100svh, 60rem); display: grid; align-content: end; padding: calc(var(--nav-h) + var(--s-8)) var(--gutter) var(--s-9); background-color: var(--bg); background-image: linear-gradient(180deg, var(--scrim-none) 36vw, var(--bg) 62.5vw), var(--lp-poster, none); background-size: 100% auto; background-position: 50% 0; background-repeat: no-repeat }
.lp-pin::before { content: ""; position: absolute; inset: 0; z-index: var(--z-scrim); pointer-events: none; background: linear-gradient(90deg, var(--scrim) 0%, var(--scrim-soft) 48%, var(--scrim-none) 78%) }
.lp-canvas { display: none }
.lp-beats { position: relative; z-index: var(--z-content); display: grid; gap: var(--s-8); width: min(100%, 38rem) }
.lp-beat { max-width: 36rem }
.lp-beat--lead { max-width: 46rem }
.lp-beat > * + * { margin-top: var(--s-4) }
.lp-beat .h1 + .lede, .lp-beat .h2 + .lede { margin-top: var(--s-5) }
.lp-step { display: flex; align-items: baseline; gap: var(--s-3) }
.lp-step .label { color: var(--violet-soft) }
.lp-fig { font-family: var(--font-mono); font-size: var(--t-sm); color: var(--fg); line-height: 1.5; padding-left: var(--s-4); border-left: 1px solid var(--violet) }
.lp-fig .src { display: block; margin-top: var(--s-1) }
.lp-note { font-family: var(--font-mono); font-size: var(--t-xs); color: var(--fg-3) }
.lp-hint { display: none }
/* one pause for every clock on the page (WCAG 2.2.2): living.js unhides it once a scene is live, so it
   never shows without JavaScript, without WebGL or under reduced motion */
.lp-pause { position: absolute; z-index: var(--z-content); top: calc(var(--nav-h) + var(--s-4)); right: var(--gutter); min-height: 32px; padding: var(--s-2) var(--s-3); font-family: var(--font-sans); font-size: var(--t-xs); font-weight: 500; line-height: 1; color: var(--fg-2); white-space: nowrap; background: var(--scrim); border: 1px solid var(--line-2); border-radius: var(--radius-pill); cursor: pointer; transition: color .2s var(--ease), border-color .2s var(--ease) }
.lp-pause[hidden] { display: none }
.lp-pause:hover { color: var(--fg); border-color: var(--violet-soft) }
.lp-pause:active { background: var(--line) }
.lp-pause:disabled { opacity: .55; cursor: not-allowed }
.lp-paused .eye__ball, .lp-paused .eye__pupil { animation-play-state: paused }
@media (max-width: 699px), (orientation: portrait) and (max-width: 1180px) {
  .lp-pin { background-image: linear-gradient(180deg, var(--scrim-none) 110vw, var(--bg) 216vw), var(--lp-poster-sm, var(--lp-poster, none)); padding-top: 70vw }
  .lp-pin::before { background: linear-gradient(180deg, var(--scrim-none) 0%, var(--scrim-soft) 28%, var(--scrim) 52%) }
}

/* live heroes: the canvas sits behind content that stays in normal flow */
html.lp-gl .lp.live:not(.static):not(.nogl) .lp-pin { background-image: none }
html.lp-gl .lp.live:not(.static):not(.nogl) .lp-hint { display: block; position: absolute; right: var(--gutter); bottom: var(--s-6); z-index: var(--z-content) }
html.lp-gl .lp.live:not(.static):not(.nogl) .lp-canvas { display: block; position: absolute; inset: 0; width: 100%; height: 100%; z-index: var(--z-canvas) }

/* pinned films: only when the head script saw WebGL2 and motion is allowed */
html.lp-gl .lp.pinned:not(.static):not(.nogl) { height: calc(var(--lp-len, 300) * 1svh) }
html.lp-gl .lp.pinned:not(.static):not(.nogl) .lp-pin { position: sticky; top: 0; height: 100svh; min-height: 0; padding: 0; display: block; background-image: none }
html.lp-gl .lp.pinned:not(.static):not(.nogl) .lp-canvas { display: block; position: absolute; inset: 0; width: 100%; height: 100%; z-index: var(--z-canvas) }
html.lp-gl .lp.pinned:not(.static):not(.nogl) .lp-beats { position: absolute; inset: 0; width: auto; display: block; pointer-events: none }
html.lp-gl .lp.pinned:not(.static):not(.nogl) .lp-beat { position: absolute; left: var(--gutter); bottom: clamp(var(--s-8), 14vh, 160px); width: min(100% - 2 * var(--gutter), 36rem); opacity: var(--o, 0); transform: translateY(calc((1 - var(--o, 0)) * 14px)); pointer-events: none }
html.lp-gl .lp.pinned:not(.static):not(.nogl) .lp-beat:first-child { --o: 1; pointer-events: auto }
html.lp-gl .lp.pinned:not(.static):not(.nogl) .lp-beat--lead { width: min(100% - 2 * var(--gutter), 46rem) }
html.lp-gl .lp.pinned:not(.static):not(.nogl) .lp-beat[data-pos="top"] { bottom: auto; top: calc(var(--nav-h) + var(--s-8)) }
html.lp-gl .lp.pinned:not(.static):not(.nogl) .lp-hint { display: block; position: absolute; right: var(--gutter); bottom: var(--s-6); z-index: var(--z-content) }
@media (max-width: 699px), (orientation: portrait) and (max-width: 1180px) {
  html.lp-gl .lp.pinned:not(.static):not(.nogl) .lp-beat { bottom: var(--s-7); width: auto; right: var(--gutter) }
  html.lp-gl .lp.pinned:not(.static):not(.nogl) .lp-beat[data-pos="top"] { top: auto; bottom: var(--s-7) }
  html.lp-gl .lp.pinned:not(.static):not(.nogl) .lp-hint { display: none }
  html.lp-gl .lp.pinned:not(.static):not(.nogl) { height: calc(var(--lp-len, 300) * .8svh) }   /* pins shorten on phones */
}
/* a reduced-motion scene keeps one finished frame, one screen tall, at the top of the static column
   (a column-sized canvas would render a stretched portrait frame), fading into the page below */
.lp.static .lp-canvas.is-still { display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100svh; z-index: var(--z-canvas); -webkit-mask-image: linear-gradient(180deg, var(--bg) 55%, var(--scrim-none)); mask-image: linear-gradient(180deg, var(--bg) 55%, var(--scrim-none)) }
.lp.static .lp-pin:has(.lp-canvas.is-still) { background-image: none }

/* ---------- figures (.fx) ---------- */
.fx { position: relative }
.fx-stage { position: relative; border: 1px solid var(--line); border-radius: var(--radius); background: var(--bg-3); overflow: hidden }
.fx-stage canvas { width: 100%; height: 100%; position: absolute; inset: 0 }
.fx-cap { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4); justify-content: space-between; margin-top: var(--s-3) }
.fx-tag { font-family: var(--font-mono); font-size: var(--t-xs); letter-spacing: .08em; text-transform: uppercase; color: var(--fg-2); border: 1px solid var(--line-2); border-radius: var(--radius-pill); padding: var(--s-1) var(--s-3); white-space: nowrap }

/* ---------- home: split (words + figure) ---------- */
.split { display: grid; gap: var(--s-8); align-items: center }
@media (min-width: 960px) { .split { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--s-9) } .split--flip { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr) } .split--flip > :first-child { order: 2 } }
.noapi .fx-stage { aspect-ratio: 16 / 11 }
.verbs { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-6); list-style: none }
.verbs li { font-family: var(--font-mono); font-size: var(--t-sm); color: var(--fg); border: 1px solid var(--line-2); border-radius: var(--radius-sm); padding: var(--s-2) var(--s-3); line-height: 1; transition: border-color .3s var(--ease), color .3s var(--ease), background-color .3s var(--ease) }
.verbs li.is-on { border-color: var(--amber); color: var(--amber); background: var(--bg-3) }

/* ---------- measured ---------- */
.measured__grid { display: grid; gap: var(--s-8) }
.chart .fx-stage { aspect-ratio: auto; height: clamp(360px, 44vw, 520px) }
.chart--mem .fx-stage { height: clamp(220px, 22vw, 280px) }
.mtable { width: 100%; border-collapse: collapse; font-size: var(--t-sm) }
.mtable caption { text-align: left; padding-bottom: var(--s-3) }
.mtable th, .mtable td { text-align: left; vertical-align: top; padding: var(--s-3) var(--s-4) var(--s-3) 0; border-top: 1px solid var(--line) }
.mtable th { font-weight: 500; color: var(--fg) }
.mtable td { color: var(--fg-2) }
.mtable td.num { font-family: var(--font-mono); color: var(--fg); white-space: nowrap }
.mtable thead th { font-family: var(--font-mono); font-size: var(--t-xs); letter-spacing: .08em; text-transform: uppercase; color: var(--fg-3); font-weight: 400; border-top: 0 }
.mtable .src { display: block; margin-top: var(--s-1) }
.fx.has-chart .mtable-wrap { margin-top: var(--s-6) }
@media (max-width: 699px) {
  .mtable thead { display: none }
  .mtable tr { display: grid; grid-template-columns: minmax(0, 1fr); padding: var(--s-3) 0; border-top: 1px solid var(--line) }
  .mtable th, .mtable td { border-top: 0; padding: var(--s-1) 0 }
}
.counts { display: grid; gap: var(--s-5); grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); list-style: none }
.counts li { border-top: 1px solid var(--line-2); padding-top: var(--s-4) }
.counts .big { display: block; font-family: var(--font-display); font-weight: 700; font-size: clamp(28px, 3.2vw, 44px); line-height: 1; color: var(--fg); white-space: nowrap }
.counts p { margin-top: var(--s-3); color: var(--fg-2); font-size: var(--t-sm) }

/* ---------- chapters (links onward) ---------- */
.chapters { list-style: none; border-top: 1px solid var(--line) }
.chapters li { border-bottom: 1px solid var(--line) }
.chapters a { display: grid; gap: var(--s-2); padding: var(--s-6) 0; text-decoration: none }
.chapters a > * { transition: transform .4s var(--ease) }
.chapters a:hover > * { transform: translateX(var(--s-4)) }
.chapters .h3 { transition: color .3s var(--ease) }
.chapters a:hover .h3 { color: var(--violet-soft) }
.chapters a:active .h3 { color: var(--violet) }
.chapters p { color: var(--fg-2); max-width: var(--measure) }
@media (min-width: 900px) { .chapters a { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); align-items: baseline; gap: var(--s-7) } }

/* ---------- details / status ---------- */
.qa { max-width: 52rem; border-top: 1px solid var(--line) }
.qa details { border-bottom: 1px solid var(--line) }
.qa summary { cursor: pointer; list-style: none; display: flex; justify-content: space-between; align-items: center; gap: var(--s-4); padding: var(--s-5) 0; font-weight: 600; font-size: var(--t-lg); line-height: 1.3 }
.qa summary::-webkit-details-marker { display: none }
.qa summary::after { content: "+"; font-family: var(--font-mono); color: var(--fg-3); font-weight: 400; transition: transform .3s var(--ease) }
.qa details[open] summary::after { transform: rotate(45deg) }
.qa summary:hover { color: var(--violet-soft) }
.qa .prose { padding-bottom: var(--s-6) }
.qa ul { padding-left: var(--s-5); display: grid; gap: var(--s-2) }

/* ---------- lists of facts ---------- */
.facts { list-style: none; display: grid; gap: 0; border-top: 1px solid var(--line) }
.facts li { display: grid; gap: var(--s-2); padding: var(--s-5) 0; border-bottom: 1px solid var(--line) }
.facts h3 { font-family: var(--font-sans); font-size: var(--t-lg); font-weight: 600; letter-spacing: 0; line-height: 1.35 }
.facts p { color: var(--fg-2); max-width: var(--measure) }
@media (min-width: 900px) { .facts li { grid-template-columns: minmax(0, 4fr) minmax(0, 7fr); gap: var(--s-7) } }
.facts--limits h3 { color: var(--fg) }
.facts--limits h3::before { content: "Open"; display: block; margin-bottom: var(--s-2); font-family: var(--font-mono); font-size: var(--t-xs); letter-spacing: .08em; text-transform: uppercase; color: var(--fg-3); font-weight: 400; line-height: 1.4 }

/* ---------- developers: code + timeline ---------- */
.dev { display: grid; gap: var(--s-7); align-items: start }
@media (min-width: 1040px) { .dev { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr) } }
.code { position: relative; border: 1px solid var(--line-2); border-radius: var(--radius); background: var(--bg-3); overflow: hidden }
.code__bar { display: flex; justify-content: space-between; gap: var(--s-3); padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line) }
.code pre { margin: 0; padding: var(--s-5) var(--s-4); overflow-x: auto; font-family: var(--font-mono); font-size: var(--t-sm); line-height: 1.7; color: var(--fg); tab-size: 4 }
.code .c { color: var(--fg-3) }
.code .k { color: var(--violet-soft) }
.code .s { color: var(--amber) }
.code .ln { display: block; border-left: 2px solid transparent; margin-left: calc(-1 * var(--s-4)); padding-left: calc(var(--s-4) - 2px); transition: border-color .3s var(--ease), background-color .3s var(--ease) }
.code .ln.is-on { border-left-color: var(--amber); background: var(--bg-2) }
/* typing: characters are revealed by JS; without JS the whole sample is there */
.code .ty { visibility: var(--ty, visible) }
.reqs { list-style: none; display: grid; gap: 0; border-top: 1px solid var(--line); counter-reset: req }
.reqs li { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: baseline; gap: var(--s-1) var(--s-3); padding: var(--s-3) 0; border-bottom: 1px solid var(--line); transition: background-color .3s var(--ease) }
.reqs .m { font-family: var(--font-mono); font-size: var(--t-xs); color: var(--amber); min-width: 4.5em }
.reqs code { font-family: var(--font-mono); font-size: var(--t-sm); color: var(--fg); overflow-wrap: anywhere }
.reqs p { grid-column: 2; color: var(--fg-2); font-size: var(--t-sm) }
.reqs li.is-on { background: var(--bg-2) }
.reqs li.is-on code { color: var(--flash) }
/* the calls: a sequence-diagram column (canvas) beside the list it draws */
.dev__calls { display: grid; grid-template-columns: minmax(120px, 3fr) minmax(0, 7fr); column-gap: var(--s-4) }
.dev-lanes { grid-column: 1; display: grid; grid-template-columns: repeat(3, 1fr); text-align: center; padding-bottom: var(--s-2); font-size: 10px; letter-spacing: .04em; white-space: nowrap }
.dev__lanes { grid-column: 1; grid-row: 2; position: relative; min-height: 100% }
.dev__lanes canvas { position: absolute; inset: 0; width: 100%; height: 100% }
.dev__calls .reqs { grid-column: 2; grid-row: 2 }
@media (max-width: 560px) { .dev__calls { grid-template-columns: 72px minmax(0, 1fr); column-gap: var(--s-3) } .dev-lanes { font-size: 9px; letter-spacing: 0 } .code pre { font-size: var(--t-xs) } }
.code .tx { display: inline-block; white-space: pre; clip-path: inset(0 calc(100% - var(--n, 999) * 1ch) 0 0) }
.code .ln { position: relative }
.code .ln.is-typing::after { content: ""; position: absolute; top: .2em; left: calc(var(--s-4) - 2px + var(--n, 0) * 1ch); width: .55ch; height: 1.2em; background: var(--amber) }
.dev-hero { padding-top: calc(var(--nav-h) + var(--s-8)) }
.api code { font-family: var(--font-mono); font-size: var(--t-sm); color: var(--fg); overflow-wrap: anywhere }

/* ---------- roadmap ---------- */
.route { list-style: none; position: relative; display: grid; gap: 0; padding-left: var(--s-7); --lp-route: 0 }
.route::before { content: ""; position: absolute; left: 11px; top: 8px; bottom: 8px; width: 2px; background: var(--line-2) }
.route::after { content: ""; position: absolute; left: 11px; top: 8px; width: 2px; height: calc((100% - 16px) * var(--lp-route)); background: linear-gradient(var(--violet), var(--flash)); box-shadow: 0 0 12px var(--violet) }
.route > li { position: relative; padding: 0 0 var(--s-8) }
.route > li::before { content: ""; position: absolute; left: calc(-1 * var(--s-7) + 5px); top: 6px; width: 14px; height: 14px; border-radius: 50%; border: 2px solid var(--line-2); background: var(--bg); transition: border-color .4s var(--ease), background-color .4s var(--ease), box-shadow .4s var(--ease) }
.route > li.done::before { border-color: var(--violet-soft); background: var(--violet) }
.route > li.lit::before { border-color: var(--flash); box-shadow: 0 0 16px var(--violet) }
.route .state { font-family: var(--font-mono); font-size: var(--t-xs); letter-spacing: .08em; text-transform: uppercase; color: var(--fg-3) }
.route > li.done .state { color: var(--violet-soft) }
.route h3 { margin-top: var(--s-2); font-size: var(--t-xl) }
.route p { margin-top: var(--s-3); color: var(--fg-2); max-width: var(--measure) }
.route ul { margin-top: var(--s-3); padding-left: var(--s-5); color: var(--fg-2); display: grid; gap: var(--s-2) }

/* ---------- contact ---------- */
.contact-card { display: grid; gap: var(--s-5); max-width: 40rem }

/* ---------- footer: Ft5 statement ---------- */
.foot { position: relative; z-index: var(--z-content); border-top: 1px solid var(--line); background: var(--bg-3); padding: var(--s-9) 0 var(--s-7) }
.foot__line { font-family: var(--font-display); font-weight: 700; font-size: var(--t-2xl); line-height: 1.06; max-width: 18ch }
.foot__meta { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: var(--s-4); margin-top: var(--s-8); padding-top: var(--s-5); border-top: 1px solid var(--line) }
.foot__meta p { font-family: var(--font-mono); font-size: var(--t-xs); color: var(--fg-3); letter-spacing: .06em }
.foot nav { display: flex; flex-wrap: wrap; gap: var(--s-1) var(--s-4) }
.foot nav a { font-size: var(--t-sm); color: var(--fg-2); text-decoration: none; white-space: nowrap; padding: var(--s-2) 0; transition: color .2s var(--ease) }
.foot nav a:hover { color: var(--fg) }
.foot nav a:active { color: var(--violet-soft) }

.grain { position: fixed; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: var(--z-grain); mix-blend-mode: overlay }

@media (prefers-reduced-motion: reduce) {
  .eye__ball, .eye__pupil { animation: none }
  html.js [data-reveal] { opacity: 1; transform: none; transition: none }
  .btn::after { display: none }
  .nav, .chapters a > *, .route > li::before { transition: none }
  .chapters a:hover > * { transform: none }
  .qa summary::after { transition: none }
}
