:root {
  /* Both themes live in this one token set. light-dark() resolves against the
     effective colour-scheme, so switching themes only has to change that
     single property — there is no second copy of the palette to keep in sync,
     and every rule below stays theme-agnostic. */
  color-scheme: light dark;
  --ink: light-dark(#181a19, #e9ede9);
  --muted: light-dark(#656b67, #9ba49e);
  --faint: light-dark(#8c928e, #79837d);
  --line: light-dark(#dfe3e0, #262c29);
  --wash: light-dark(#f4f6f4, #151917);
  --paper: light-dark(#fbfcfb, #0c0f0e);
  /* An emphasised surface, one step brighter than --wash. In light that is
     simply the paper; in dark, paper is the darkest thing on the page, so
     "brighter" has to be its own colour rather than a reuse of --paper. */
  --lift: light-dark(#fbfcfb, #1d2320);
  --accent: light-dark(#176b58, #54d3ab);
  --accent-wash: light-dark(#e7f1ed, rgb(84 211 171 / 0.13));
  /* The header is the paper again, translucent, behind a blur. */
  --veil: light-dark(rgb(251 252 251 / 0.92), rgb(12 15 14 / 0.84));
  --veil-line: light-dark(rgb(223 227 224 / 0.8), rgb(38 44 41 / 0.9));
  /* Ambient light. Deliberately absent in light mode: the flat paper is the
     look that page has always had, and the glow is what makes the dark one
     read as a lit room instead of an inverted document. */
  --ambient-1: light-dark(transparent, rgb(66 205 166 / 0.085));
  --ambient-2: light-dark(transparent, rgb(76 136 194 / 0.07));
  --ambient-floor: light-dark(transparent, rgb(0 0 0 / 0.42));
  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif;
  --sans: "Avenir Next", Avenir, "Segoe UI", Helvetica, Arial, sans-serif;
  --mono: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
  --page: min(1120px, calc(100vw - 48px));
  --reading: 720px;
}

/* An explicit choice, stamped on <html> by /theme.js before first paint.
   With no attribute at all the page follows the operating system, which is
   the default state — the toggle only ever overrides. */
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

* { box-sizing: border-box; }
/* The page colour sits on <html>, not <body>, so body::before below can paint
   the ambient wash between the two without being buried by body's own
   background. It is also what /theme.js reads back for the browser chrome. */
html {
  scroll-behavior: smooth;
  background: var(--paper);
}
body {
  margin: 0;
  color: var(--ink);
  background: transparent;
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
}
/* Ambient layer: fixed, so it reads as the room the page sits in rather than
   as decoration that scrolls away with the first screen. Fully transparent in
   light mode, where it costs one composited layer and nothing else. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(1200px 700px at 6% -12%, var(--ambient-1), transparent 68%),
    radial-gradient(1000px 620px at 97% 0%, var(--ambient-2), transparent 66%),
    linear-gradient(to bottom, transparent 40%, var(--ambient-floor));
}
a { color: inherit; text-decoration-color: var(--line); text-underline-offset: 4px; }
a:hover { color: var(--accent); text-decoration-color: currentColor; }
img, svg { display: block; max-width: 100%; }
button, input { font: inherit; }

.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  border-bottom: 1px solid var(--veil-line);
  background: var(--veil);
  backdrop-filter: blur(16px);
}
.header-inner {
  width: var(--page);
  min-height: 68px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}
.wordmark {
  font-family: var(--serif);
  font-size: 23px;
  font-weight: 600;
  text-decoration: none;
  letter-spacing: -0.02em;
}
.wordmark span { color: var(--accent); }
.site-nav {
  display: flex;
  align-items: center;
  /* Seven items don't fit on one line below ~1000px. Let whole items drop to
     a second right-aligned row there, rather than breaking a link mid-word. */
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 8px 24px;
  padding: 8px 0;
  font-size: 14px;
  /* The auto margin, not space-between, is what holds the nav right, so the
     theme toggle can sit after it as a third child without the header
     re-centring everything. */
  margin-left: auto;
}
.site-nav a { text-decoration: none; color: var(--muted); white-space: nowrap; }
.site-nav a:hover, .site-nav a[aria-current="page"] { color: var(--ink); }
.header-cta {
  padding: 8px 14px;
  border: 1px solid var(--ink);
  border-radius: 999px;
  color: var(--ink) !important;
}
.menu-toggle { display: none; }

/* Theme toggle. Weighted to read as one more quiet mark in the header rather
   than as a control: no chrome at rest, and the surrounding wash only on
   hover. Hidden until /theme.js marks the document, because without the
   script the button cannot do anything and a dead control is worse than an
   absent one. */
.theme-toggle { display: none; }
:root.js .theme-toggle {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 999px;
  background: none;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  transition: border-color .18s ease, background-color .18s ease;
}
.theme-toggle:hover { border-color: var(--line); background: var(--wash); }
.theme-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Both glyphs occupy the same grid cell and the one that does not apply is
   drawn in transparent ink. That keeps "which icon shows" inside the same
   light-dark() token system as everything else, instead of needing a second
   copy of the light/dark condition in a media query and an attribute rule. */
.theme-icon {
  grid-area: 1 / 1;
  width: 15px;
  height: 15px;
  fill: none;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: stroke .18s ease;
}
.theme-icon-moon { stroke: light-dark(var(--muted), transparent); }
.theme-icon-sun { stroke: light-dark(transparent, var(--muted)); }
.theme-toggle:hover .theme-icon-moon { stroke: light-dark(var(--ink), transparent); }
.theme-toggle:hover .theme-icon-sun { stroke: light-dark(transparent, var(--accent)); }

.page {
  width: var(--page);
  margin: 0 auto;
}
.hero {
  min-height: 74vh;
  display: grid;
  align-content: center;
  padding: 120px 0 104px;
  border-bottom: 1px solid var(--line);
}
.hero.compact {
  min-height: auto;
  padding: 104px 0 84px;
}
.kicker, .section-label {
  margin: 0 0 20px;
  color: var(--accent);
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
h1, h2, h3 {
  font-family: var(--serif);
  font-weight: 500;
  text-wrap: balance;
}
h1 {
  max-width: 980px;
  margin: 0;
  font-size: clamp(54px, 8.2vw, 108px);
  line-height: 0.98;
  letter-spacing: -0.055em;
}
.compact h1 { max-width: 850px; font-size: clamp(48px, 7vw, 84px); }
.hero-copy {
  max-width: 700px;
  margin: 36px 0 0;
  color: var(--muted);
  font-size: clamp(19px, 2vw, 24px);
  line-height: 1.55;
}
.definition {
  max-width: 880px;
  margin-top: 52px;
  padding-left: 24px;
  border-left: 3px solid var(--accent);
  font-family: var(--serif);
  font-size: clamp(24px, 3vw, 34px);
  line-height: 1.4;
}

.chapter {
  padding: 112px 0;
  border-bottom: 1px solid var(--line);
}
.chapter-grid {
  display: grid;
  grid-template-columns: minmax(180px, 0.7fr) minmax(0, 2fr);
  gap: 80px;
}
.chapter h2 {
  max-width: 760px;
  margin: 0 0 30px;
  font-size: clamp(38px, 5vw, 64px);
  line-height: 1.08;
  letter-spacing: -0.035em;
}
.chapter h3 {
  margin: 48px 0 10px;
  font-size: 28px;
  line-height: 1.25;
}
.prose { max-width: var(--reading); }
.prose > :first-child { margin-top: 0; }
.prose p { margin: 0 0 24px; }
.prose .lead {
  color: var(--ink);
  font-family: var(--serif);
  font-size: 27px;
  line-height: 1.48;
}
.muted { color: var(--muted); }

.curve {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  margin-top: 56px;
  border-top: 1px solid var(--ink);
}
.curve article {
  min-height: 250px;
  padding: 24px 28px 28px 0;
  border-right: 1px solid var(--line);
}
.curve article + article { padding-left: 28px; }
.curve article:last-child { border-right: 0; }
.curve .index {
  color: var(--accent);
  font-family: var(--mono);
  font-size: 12px;
}
.curve h3 { margin: 52px 0 10px; font-size: 28px; }
.curve p { margin: 0; color: var(--muted); font-size: 15px; }

.comparison {
  display: grid;
  grid-template-columns: 1fr 1fr;
  margin-top: 56px;
  border: 1px solid var(--line);
}
.comparison article { padding: 36px; }
.comparison article + article { border-left: 1px solid var(--line); background: var(--wash); }
.comparison h3 { margin: 0 0 28px; font-size: 27px; }
.steps { margin: 0; padding: 0; list-style: none; counter-reset: steps; }
.steps li {
  counter-increment: steps;
  display: grid;
  grid-template-columns: 32px 1fr;
  gap: 10px;
  padding: 12px 0;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 15px;
}
.steps li::before {
  content: counter(steps, decimal-leading-zero);
  color: var(--faint);
  font-family: var(--mono);
  font-size: 11px;
  padding-top: 4px;
}
.after-state {
  min-height: 242px;
  display: grid;
  place-items: center;
  padding: 48px 24px;
  text-align: center;
  font-family: var(--serif);
  font-size: 30px;
}
.measure {
  margin-top: 32px;
  color: var(--accent);
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.03em;
}

/* Kinetic pieces (kinetic.css) placed on these pages. */
/* The board fills the gap the other two columns leave above their headings (h3 margin 52px),
   so all three headings stay on one line. */
.curve .k-flap { display: flex; margin-top: 8px; }
.curve .k-flap + h3 { margin-top: 11px; }
.after-state-kinetic { gap: 14px; padding: 36px 24px 32px; }
.after-state-kinetic .k-kicker { margin: 0; }
.after-state-kinetic .k-odometer { --k-row: clamp(40px, 5vw, 60px); }
.after-line { margin: 4px 0 0; font-family: var(--serif); font-size: clamp(22px, 2.6vw, 30px); line-height: 1.2; }
.hero-render { margin-top: clamp(56px, 7vw, 92px); }
.ambient-grid {
  display: grid;
  grid-template-columns: minmax(0, .78fr) minmax(0, 1.22fr);
  gap: clamp(28px, 4vw, 56px);
  align-items: start;
  margin-top: 48px;
}
.ambient-grid .artifact { margin-top: 0; }
.privacy-flap { margin-top: 48px; }
.privacy-flap .k-kicker { margin-bottom: 14px; }
.privacy-flap .k-flap { display: flex; }

.use-list { margin-top: 36px; }
.use {
  display: grid;
  grid-template-columns: 160px 1fr;
  gap: 40px;
  padding: 38px 0;
  border-top: 1px solid var(--line);
}
.use:last-child { border-bottom: 1px solid var(--line); }
.use h3 { margin: 0; font-size: 24px; }
.use p { max-width: 640px; margin: 0; color: var(--muted); }

.principle {
  max-width: 900px;
  padding: 64px;
  border: 1px solid var(--line);
  background: var(--wash);
  font-family: var(--serif);
  font-size: clamp(25px, 3.2vw, 38px);
  line-height: 1.42;
}

.artifact {
  margin-top: 48px;
  border-top: 1px solid var(--ink);
}
.artifact-row {
  display: grid;
  grid-template-columns: 120px 1fr 180px;
  gap: 24px;
  padding: 22px 0;
  border-bottom: 1px solid var(--line);
  align-items: baseline;
}
.artifact-row time, .artifact-row span:last-child {
  color: var(--faint);
  font-family: var(--mono);
  font-size: 11px;
}
.artifact-row span:last-child { text-align: right; }

.privacy-strip {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  margin-top: 48px;
  border-top: 1px solid var(--ink);
  border-bottom: 1px solid var(--line);
}
.privacy-strip div { padding: 30px 28px 30px 0; }
.privacy-strip div + div { padding-left: 28px; border-left: 1px solid var(--line); }
.privacy-strip strong { display: block; margin-bottom: 8px; font-size: 15px; }
.privacy-strip span { color: var(--muted); font-size: 14px; }

/* The relay diagram. One 15s loop: a token advances along the rail and parks
   on each node, and the stage under that node fills in while it sits there.
   Pure CSS — these pages carry no scripts, and this does not change that.
   Every claim is real text in the DOM, so the figure reads the same frozen;
   prefers-reduced-motion holds it in the finished state with all three stages
   complete. Nodes sit at the three column centres (1/6, 1/2, 5/6). */
.relay { margin-top: 56px; }

.relay-rail { position: relative; height: 9px; margin-bottom: 30px; }
/* The rail runs exactly node-to-node, so a completed run fills it end to end
   instead of trailing off past the last stop. */
.relay-rail::before {
  content: "";
  position: absolute;
  top: 4px;
  left: 16.667%;
  right: 16.667%;
  height: 1px;
  background: var(--line);
}
.relay-fill {
  position: absolute;
  top: 4px;
  left: 16.667%;
  width: 0;
  height: 1px;
  background: var(--accent);
  animation: relay-fill 15s ease-in-out infinite;
}
.relay-node {
  position: absolute;
  top: 0;
  width: 9px;
  height: 9px;
  margin-left: -4.5px;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--paper);
  animation: 15s ease-in-out infinite;
}
.relay-node-1 { left: 16.667%; animation-name: relay-node-1; }
.relay-node-2 { left: 50%; animation-name: relay-node-2; }
.relay-node-3 { left: 83.333%; animation-name: relay-node-3; }
.relay-token {
  position: absolute;
  top: 1.5px;
  left: 16.667%;
  width: 6px;
  height: 6px;
  margin-left: -3px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-wash);
  animation: relay-token 15s ease-in-out infinite;
}
@keyframes relay-token {
  0% { left: 16.667%; opacity: 0; }
  4%, 26% { left: 16.667%; opacity: 1; }
  34%, 58% { left: 50%; opacity: 1; }
  66%, 92% { left: 83.333%; opacity: 1; }
  97%, 100% { left: 83.333%; opacity: 0; }
}
/* Widths are the span from node 1, not absolute positions: node 2 is a third
   of the rail along, node 3 is two thirds. */
@keyframes relay-fill {
  0% { width: 0; opacity: 0; }
  4%, 26% { width: 0; opacity: 1; }
  34%, 58% { width: 33.333%; opacity: 1; }
  66%, 92% { width: 66.667%; opacity: 1; }
  97%, 100% { width: 66.667%; opacity: 0; }
}
@keyframes relay-node-1 {
  0%, 2%, 30%, 100% { background: var(--paper); border-color: var(--line); transform: scale(1); }
  6%, 26% { background: var(--accent); border-color: var(--accent); transform: scale(1.3); }
}
@keyframes relay-node-2 {
  0%, 30%, 62%, 100% { background: var(--paper); border-color: var(--line); transform: scale(1); }
  36%, 58% { background: var(--accent); border-color: var(--accent); transform: scale(1.3); }
}
@keyframes relay-node-3 {
  0%, 62%, 96%, 100% { background: var(--paper); border-color: var(--line); transform: scale(1); }
  68%, 92% { background: var(--accent); border-color: var(--accent); transform: scale(1.3); }
}

/* Columns divided like .curve, so the diagram sits in the same grid language
   as the rest of the page. */
.relay-stages { display: grid; grid-template-columns: repeat(3, 1fr); }
.relay-stage { display: flex; flex-direction: column; padding: 0 28px 0 0; border-right: 1px solid var(--line); }
.relay-stage + .relay-stage { padding-left: 28px; }
.relay-stage:last-child { border-right: 0; padding-right: 0; }
.relay-index { color: var(--faint); font-family: var(--mono); font-size: 12px; animation: 15s ease-in-out infinite; }
.relay-stage-1 .relay-index { animation-name: relay-index-1; }
.relay-stage-2 .relay-index { animation-name: relay-index-2; }
.relay-stage-3 .relay-index { animation-name: relay-index-3; }
@keyframes relay-index-1 { 0%, 2%, 30%, 100% { color: var(--faint); } 6%, 26% { color: var(--accent); } }
@keyframes relay-index-2 { 0%, 30%, 62%, 100% { color: var(--faint); } 36%, 58% { color: var(--accent); } }
@keyframes relay-index-3 { 0%, 62%, 96%, 100% { color: var(--faint); } 68%, 92% { color: var(--accent); } }
/* Reserved height keeps the three panels starting on one line whether a title
   runs to one line or two. */
.relay-stage h3 { min-height: 2.5em; margin: 14px 0 18px; font-size: 24px; line-height: 1.25; }
.relay-stage > p { margin: 18px 0 0; color: var(--muted); font-size: 15px; line-height: 1.6; }

.relay-panel {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-height: 214px;
  padding: 18px;
  border: 1px solid var(--line);
  background: var(--wash);
  animation: 15s ease-in-out infinite;
}
.relay-stage-1 .relay-panel { animation-name: relay-panel-1; }
.relay-stage-2 .relay-panel { animation-name: relay-panel-2; }
.relay-stage-3 .relay-panel { animation-name: relay-panel-3; }
/* The active surface is --lift, not --paper. In dark mode paper is the
   darkest colour on the page, so lighting a stage up with it would dim the
   panel at the exact moment the rail says it is the live one. */
@keyframes relay-panel-1 {
  0%, 2%, 30%, 100% { border-color: var(--line); background: var(--wash); opacity: .62; }
  6%, 26% { border-color: var(--accent); background: var(--lift); opacity: 1; }
}
@keyframes relay-panel-2 {
  0%, 30%, 62%, 100% { border-color: var(--line); background: var(--wash); opacity: .62; }
  36%, 58% { border-color: var(--accent); background: var(--lift); opacity: 1; }
}
@keyframes relay-panel-3 {
  0%, 62%, 96%, 100% { border-color: var(--line); background: var(--wash); opacity: .62; }
  68%, 92% { border-color: var(--accent); background: var(--lift); opacity: 1; }
}

/* Waveform. Each bar carries its own resting scaleY so freezing the animation
   leaves a waveform rather than a flat row. */
.relay-wave { display: flex; align-items: center; justify-content: space-between; height: 52px; }
.relay-wave i {
  flex: 0 0 5px;
  height: 100%;
  background: var(--accent);
  opacity: .55;
  animation: relay-wave 1s ease-in-out infinite alternate;
}
@keyframes relay-wave { from { transform: scaleY(.16); } to { transform: scaleY(1); } }
.relay-wave i:nth-child(1) { transform: scaleY(.34); animation-duration: .86s; animation-delay: -.55s; }
.relay-wave i:nth-child(2) { transform: scaleY(.62); animation-duration: 1.04s; animation-delay: -.19s; }
.relay-wave i:nth-child(3) { transform: scaleY(.95); animation-duration: .74s; animation-delay: -.72s; }
.relay-wave i:nth-child(4) { transform: scaleY(.48); animation-duration: .96s; animation-delay: -.34s; }
.relay-wave i:nth-child(5) { transform: scaleY(.80); animation-duration: 1.18s; animation-delay: -.88s; }
.relay-wave i:nth-child(6) { transform: scaleY(.28); animation-duration: .82s; animation-delay: -.41s; }
.relay-wave i:nth-child(7) { transform: scaleY(.68); animation-duration: 1.1s; animation-delay: -.66s; }
.relay-wave i:nth-child(8) { transform: scaleY(.42); animation-duration: .9s; animation-delay: -.12s; }
.relay-wave i:nth-child(9) { transform: scaleY(.86); animation-duration: 1.26s; animation-delay: -.79s; }
.relay-wave i:nth-child(10) { transform: scaleY(.55); animation-duration: .88s; animation-delay: -.27s; }
.relay-wave i:nth-child(11) { transform: scaleY(.31); animation-duration: 1.14s; animation-delay: -.94s; }
.relay-wave i:nth-child(12) { transform: scaleY(.74); animation-duration: .78s; animation-delay: -.48s; }
.relay-wave i:nth-child(13) { transform: scaleY(.45); animation-duration: 1s; animation-delay: -.07s; }

.relay-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: auto; }
.relay-chips em {
  padding: 3px 8px;
  border: 1px solid var(--line);
  background: var(--lift);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 10px;
  font-style: normal;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.relay-lines { display: flex; flex-direction: column; gap: 10px; margin: 0; padding: 0; list-style: none; }
.relay-lines li {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  gap: 9px;
  align-items: baseline;
  font-size: 14px;
  line-height: 1.45;
  opacity: 0;
  animation: 15s ease-in-out infinite;
}
.relay-lines b { color: var(--accent); font-family: var(--mono); font-size: 10px; font-weight: 400; letter-spacing: 0.06em; text-transform: uppercase; }
/* Qualified by the li so these outrank the animation shorthand above, which
   would otherwise reset animation-name back to none. */
.relay-lines li.relay-in-a { animation-name: relay-in-a; }
.relay-lines li.relay-in-b { animation-name: relay-in-b; }
.relay-lines li.relay-in-c { animation-name: relay-in-c; }

.relay-mark {
  align-self: flex-start;
  margin-top: auto;
  padding: 5px 10px;
  border: 1px solid var(--accent);
  background: var(--accent-wash);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  opacity: 0;
  animation: relay-in-d 15s ease-in-out infinite;
}

.relay-chat { display: flex; flex-direction: column; gap: 10px; margin-top: auto; }
.relay-ask, .relay-reply { margin: 0; padding: 9px 12px; font-size: 14px; line-height: 1.45; opacity: 0; animation: 15s ease-in-out infinite; }
.relay-ask { align-self: flex-end; max-width: 92%; background: var(--ink); color: var(--paper); animation-name: relay-in-e; }
.relay-reply { align-self: flex-start; border: 1px solid var(--line); background: var(--lift); animation-name: relay-in-f; }

/* Handoff destinations, in the same row idiom as .artifact-row. */
/* Centred rather than top-anchored: the other two panels push their last
   element to the bottom, so this would otherwise leave dead space below. */
.relay-outs { display: flex; flex-direction: column; margin: auto 0; padding: 0; list-style: none; border-top: 1px solid var(--line); }
.relay-outs li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
  font-size: 14px;
  opacity: 0;
  animation: 15s ease-in-out infinite;
}
.relay-outs em { flex: 0 0 auto; color: var(--faint); font-family: var(--mono); font-size: 10px; font-style: normal; letter-spacing: 0.06em; text-transform: uppercase; }
.relay-outs li.relay-in-e { animation-name: relay-in-e; }
.relay-outs li.relay-in-f { animation-name: relay-in-f; }
.relay-outs li.relay-in-g { animation-name: relay-in-g; }

@keyframes relay-in-a { 0%, 38% { opacity: 0; transform: translateY(6px); } 42%, 92% { opacity: 1; transform: none; } 100% { opacity: 0; transform: translateY(6px); } }
@keyframes relay-in-b { 0%, 43% { opacity: 0; transform: translateY(6px); } 47%, 92% { opacity: 1; transform: none; } 100% { opacity: 0; transform: translateY(6px); } }
@keyframes relay-in-c { 0%, 48% { opacity: 0; transform: translateY(6px); } 52%, 92% { opacity: 1; transform: none; } 100% { opacity: 0; transform: translateY(6px); } }
@keyframes relay-in-d { 0%, 53% { opacity: 0; transform: translateY(6px); } 57%, 92% { opacity: 1; transform: none; } 100% { opacity: 0; transform: translateY(6px); } }
@keyframes relay-in-e { 0%, 70% { opacity: 0; transform: translateY(6px); } 74%, 94% { opacity: 1; transform: none; } 100% { opacity: 0; transform: translateY(6px); } }
@keyframes relay-in-f { 0%, 76% { opacity: 0; transform: translateY(6px); } 80%, 94% { opacity: 1; transform: none; } 100% { opacity: 0; transform: translateY(6px); } }
@keyframes relay-in-g { 0%, 82% { opacity: 0; transform: translateY(6px); } 86%, 94% { opacity: 1; transform: none; } 100% { opacity: 0; transform: translateY(6px); } }

.cta {
  padding: 112px 0 124px;
  text-align: center;
}
.cta h2 {
  max-width: 780px;
  margin: 0 auto 28px;
  font-size: clamp(42px, 6vw, 72px);
  line-height: 1.05;
  letter-spacing: -0.04em;
}
.cta p { max-width: 600px; margin: 0 auto 34px; color: var(--muted); }
.button-row { display: flex; justify-content: center; gap: 12px; flex-wrap: wrap; }
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 0 20px;
  border: 1px solid var(--ink);
  border-radius: 999px;
  text-decoration: none;
  font-size: 14px;
  font-weight: 600;
}
.button.primary { background: var(--ink); color: var(--paper); }
.button:hover { border-color: var(--accent); color: var(--accent); }
/* Paper rather than white: indistinguishable against the light accent, and
   the only readable choice against the dark one, which is a bright mint. */
.button.primary:hover { background: var(--accent); color: var(--paper); }
.cta form {
  width: min(100%, 560px);
  margin: 0 auto;
}
.cta form label {
  display: block;
  margin-bottom: 8px;
  font-size: 14px;
  font-weight: 600;
}
.cta form input[type="email"] {
  width: 100%;
  min-height: 52px;
  padding: 0 16px;
  border: 1px solid var(--line);
  border-radius: 10px;
  color: var(--ink);
  background: var(--paper);
}
.cta form input[type="email"]:focus {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.cta form .button { cursor: pointer; }
.access-hp {
  position: absolute;
  left: -10000px;
}

.docs-layout {
  display: grid;
  grid-template-columns: 230px minmax(0, var(--reading));
  gap: 80px;
  align-items: start;
  padding: 80px 0 120px;
}
.docs-toc {
  position: sticky;
  top: 104px;
  display: grid;
  gap: 4px;
  font-size: 13px;
}
.docs-toc strong {
  margin-bottom: 12px;
  color: var(--faint);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.docs-toc a { padding: 5px 0; color: var(--muted); text-decoration: none; }
.docs-content section { padding: 0 0 72px; scroll-margin-top: 100px; }
.docs-content section + section { padding-top: 72px; border-top: 1px solid var(--line); }
.docs-content h2 {
  margin: 0 0 28px;
  font-size: 42px;
  line-height: 1.12;
  letter-spacing: -0.03em;
}
.docs-content h3 { margin: 42px 0 12px; font-size: 25px; }
.docs-content p { margin: 0 0 20px; }
.docs-content ul, .docs-content ol { margin: 0 0 24px; padding-left: 24px; }
.docs-content li { margin-bottom: 10px; }
.note {
  margin: 28px 0;
  padding: 20px 22px;
  border-left: 3px solid var(--accent);
  background: var(--accent-wash);
  font-size: 15px;
}
.path {
  font-family: var(--mono);
  font-size: 0.88em;
}
.table-wrap { overflow-x: auto; margin: 30px 0; }
table { width: 100%; min-width: 620px; border-collapse: collapse; font-size: 14px; }
caption { margin-bottom: 10px; color: var(--muted); text-align: left; font-size: 13px; }
th, td { padding: 15px 12px; border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; }
th { color: var(--ink); font-weight: 600; }
thead th { color: var(--faint); font-family: var(--mono); font-size: 10px; letter-spacing: 0.06em; text-transform: uppercase; }
td { color: var(--muted); }
code { padding: 2px 5px; background: var(--wash); font-family: var(--mono); font-size: 0.85em; }
pre {
  max-width: 100%;
  margin: 28px 0;
  padding: 20px 22px;
  overflow-x: auto;
  border: 1px solid var(--line);
  background: var(--wash);
  color: var(--ink);
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.65;
  tab-size: 2;
  -webkit-overflow-scrolling: touch;
}
pre code { padding: 0; background: transparent; color: inherit; font-size: inherit; }

.site-footer { border-top: 1px solid var(--line); }
.footer-inner {
  width: var(--page);
  margin: 0 auto;
  padding: 42px 0;
  display: flex;
  justify-content: space-between;
  gap: 32px;
  color: var(--muted);
  font-size: 13px;
}
.footer-links { display: flex; gap: 18px; flex-wrap: wrap; }
.footer-links a { text-decoration: none; }

@media (max-width: 780px) {
  :root { --page: min(100% - 32px, 1120px); }
  body { font-size: 16px; }
  .header-inner { min-height: 60px; }
  .site-nav a:not(.header-cta) { display: none; }
  .hero, .hero.compact { min-height: auto; padding: 88px 0 72px; }
  h1, .compact h1 { font-size: clamp(46px, 15vw, 68px); }
  .chapter { padding: 80px 0; }
  .chapter-grid, .docs-layout { grid-template-columns: 1fr; gap: 32px; }
  .chapter-grid > .section-label { margin-bottom: 0; }
  .curve, .comparison, .privacy-strip { grid-template-columns: 1fr; }
  .curve article, .curve article + article { min-height: auto; padding: 24px 0; border-right: 0; border-bottom: 1px solid var(--line); }
  .curve h3 { margin-top: 26px; }
  .curve .k-flap { margin-top: 6px; }
  .curve .k-flap + h3 { margin-top: 12px; }
  .comparison article + article { border-left: 0; border-top: 1px solid var(--line); }
  .ambient-grid { grid-template-columns: 1fr; }
  .ambient-grid .render-stage { max-width: 420px; }
  .use { grid-template-columns: 1fr; gap: 10px; }
  .principle { padding: 36px 28px; }
  .artifact-row { grid-template-columns: 80px 1fr; }
  .artifact-row span:last-child { display: none; }
  .privacy-strip div, .privacy-strip div + div { padding: 24px 0; border-left: 0; border-bottom: 1px solid var(--line); }
  .docs-layout { padding-top: 48px; }
  .docs-toc { position: static; grid-template-columns: 1fr 1fr; padding-bottom: 32px; border-bottom: 1px solid var(--line); }
  .docs-toc strong { grid-column: 1 / -1; }
  .footer-inner { flex-direction: column; }
  /* Stacked, the rail has nothing left to span and only one stage is on screen
     at a time, so the sequenced reveal would read as a broken panel rather than
     a story. The rail goes, and every stage shows complete. */
  .relay-rail { display: none; }
  .relay-stages { grid-template-columns: 1fr; }
  .relay-stage, .relay-stage + .relay-stage {
    padding: 24px 0;
    border-right: 0;
    border-bottom: 1px solid var(--line);
  }
  /* The chapter already closes with its own rule — a stage border here would
     double it. */
  .relay-stage:last-child { padding-bottom: 0; border-bottom: 0; }
  .relay-stage h3 { min-height: 0; }
  .relay-panel { min-height: 0; }
  .relay-panel,
  .relay-index,
  .relay-lines li,
  .relay-mark,
  .relay-ask,
  .relay-reply,
  .relay-outs li { animation: none; opacity: 1; transform: none; }
  .relay-panel { border-color: var(--line); background: var(--wash); }
  .relay-index { color: var(--accent); }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  /* Held in the finished state: rail fully run, every stage complete. */
  .relay-fill,
  .relay-token,
  .relay-node,
  .relay-index,
  .relay-panel,
  .relay-wave i,
  .relay-lines li,
  .relay-mark,
  .relay-ask,
  .relay-reply,
  .relay-outs li { animation: none; }
  .relay-fill { width: 66.667%; opacity: 1; }
  .relay-token { left: 83.333%; opacity: 1; }
  .relay-node { background: var(--accent); border-color: var(--accent); }
  .relay-index { color: var(--accent); }
  .relay-panel { border-color: var(--accent); background: var(--lift); opacity: 1; }
  .relay-lines li,
  .relay-mark,
  .relay-ask,
  .relay-reply,
  .relay-outs li { opacity: 1; transform: none; }
}
