/* 6hands — landing page.
   Tokens are lifted verbatim from DESIGN.md. The landing adds what the app's
   system does not have, because it is a different scene: a display type step
   (desktop headline), breakpoints (the app is phone-only), pointer states (the
   app is touch-only), and the material/optical layer recorded in the surface
   brief under "Deliberate departures". Everything else inherits. */

/* ── Tokens ─────────────────────────────────────────────────────────────── */

:root {
  --bg: #FFF8F4;
  --card: #FFFFFF;
  --line: #F1E6DD;
  --ink: #2E2620;
  --muted: #615850;
  --faint: #7C6D5E;
  --peach: #FCEADF;
  --peach2: #FBE0D2;
  --orange: #F0632A;
  --orange-soft: #F59D6E;
  --orange-deep: #A64B2E;
  --orange-btn: #C2481B;
  --dark: #1B2030;

  --hand-1-bg: #FDEBD7; --hand-1-ink: #C2681F;
  --hand-2-bg: #FCE3D8; --hand-2-ink: #C2551F;
  --hand-3-bg: #F6E8E2; --hand-3-ink: #9C7F72;

  /* Motion — the app's own duration ladder and curves. */
  --ease: cubic-bezier(.3, 0, .2, 1);
  --ease-arrive: cubic-bezier(.16, 1, .3, 1);
  --t-tap: 150ms;
  --t-enter: 280ms;
  --t-draw: 900ms;

  /* A spring, sampled to a curve. --ease-arrive only decelerates; a node
     landing in a graph should settle the way a real control does, with one
     small overshoot (8%) and no second bounce. Damping .62, ω 19 rad/s.
     Spent on the page's one authored moment and on press release — nowhere
     else, or the overshoot stops reading as physics and starts reading as
     decoration. */
  --ease-spring: linear(
    0, 0.114 4.5%, 0.353 9.1%, 0.609 13.6%, 0.821 18.2%, 0.966 22.7%,
    1.048 27.3%, 1.081 31.8%, 1.081 36.4%, 1.064 40.9%, 1.043 45.5%,
    1.023 50%, 1.008 54.5%, 0.999 59.1%, 0.994 63.6%, 0.993 68.2%,
    0.994 72.7%, 0.996 77.3%, 0.997 81.8%, 0.999 86.4%, 1
  );
  --t-press: 110ms;

  /* Optical tracking. Nunito has no optical-size axis, so the behaviour a
     variable face would give for free is written out: tracking closes as type
     grows and opens as it shrinks. The floor is -0.04em. */
  --track-display: -0.038em;
  --track-h2: -0.028em;
  --track-h3: -0.02em;
  --track-caps: 0.6px;

  /* Elevation. DESIGN.md permits exactly this: soft, ambient, warm, with a
     real offset and a wide blur. The tint is Ink, not black, so a card never
     casts a cool shadow onto warm paper. */
  --shadow-raise: 0 1px 2px rgba(46, 38, 32, .035), 0 10px 26px -14px rgba(46, 38, 32, .10);
  --shadow-bar: 0 1px 0 rgba(46, 38, 32, .03), 0 10px 30px -20px rgba(46, 38, 32, .22);

  /* The bar material: paper at 72%, so type and diagram pass visibly beneath
     it instead of disappearing under an opaque strip. Saturation is pushed
     because blur desaturates, and this page's whole argument is colour
     temperature. */
  --material-bar: rgba(255, 248, 244, .82);
  --material-filter: saturate(180%) blur(20px);

  /* The soft edge. Where a fixed surface sits over moving content, the moment
     of passage is drawn — the bar does it with blur, the diagram's stage does
     it with a fade. A hard cut leaves half a line of type sliced off at the
     boundary, which reads as clipping rather than as depth. */
  --edge-fade: 28px;

  /* Radii — DESIGN.md's vocabulary. Nothing reaches zero. */
  --r-pill: 999px;
  --r-card: 20px;
  --r-tile: 16px;
  --r-btn: 15px;
  --r-compact: 12px;

  --hairline: 1.5px;
  --maxw: 1280px;
  --gutter: clamp(1.25rem, 0.6rem + 2.6vw, 4rem);
  --space-section: clamp(4.5rem, 3rem + 6vw, 9rem);
  --bar-h: 64px;

  /* The one step the app's five-size ramp does not have: a page headline
     read at arm's length on a desktop, not one-handed on a phone. */
  --text-display: clamp(2.15rem, 1.1rem + 4.3vw, 4.5rem);
  --text-h2: clamp(1.55rem, 1.05rem + 2vw, 2.55rem);
  --text-h3: clamp(1.15rem, 1.02rem + 0.5vw, 1.35rem);
  --text-lead: clamp(1.05rem, 0.98rem + 0.35vw, 1.25rem);

  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #141824;
    --card: #1D2230;
    --line: #2A3040;
    --ink: #F2EFEA;
    --muted: #9AA0AE;
    --faint: #828A9C;
    --peach: #2A2233;
    --peach2: #241E2C;
    --orange-deep: #F0632A;
    --dark: #0E1119;
    --hand-1-bg: #3A2A1A; --hand-1-ink: #F0A860;
    --hand-2-bg: #3A241A; --hand-2-ink: #F08B54;
    --hand-3-bg: #2B2A31; --hand-3-ink: #A99A92;
    /* Dark material runs more translucent and more saturated: there is less
       luminance behind it to survive the blur. Shadows deepen because the
       surfaces they fall on are darker than the shadow's own tint. */
    --material-bar: rgba(20, 24, 36, .8);
    --material-filter: saturate(190%) blur(22px);
    --shadow-raise: 0 1px 2px rgba(0, 0, 0, .28), 0 12px 30px -16px rgba(0, 0, 0, .5);
    --shadow-bar: 0 1px 0 rgba(0, 0, 0, .3), 0 12px 34px -22px rgba(0, 0, 0, .7);
    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --bg: #141824;
  --card: #1D2230;
  --line: #2A3040;
  --ink: #F2EFEA;
  --muted: #9AA0AE;
  --faint: #828A9C;
  --peach: #2A2233;
  --peach2: #241E2C;
  --orange-deep: #F0632A;
  --dark: #0E1119;
  --hand-1-bg: #3A2A1A; --hand-1-ink: #F0A860;
  --hand-2-bg: #3A241A; --hand-2-ink: #F08B54;
  --hand-3-bg: #2B2A31; --hand-3-ink: #A99A92;
  --material-bar: rgba(20, 24, 36, .8);
  --material-filter: saturate(190%) blur(22px);
  --shadow-raise: 0 1px 2px rgba(0, 0, 0, .28), 0 12px 30px -16px rgba(0, 0, 0, .5);
  --shadow-bar: 0 1px 0 rgba(0, 0, 0, .3), 0 12px 34px -22px rgba(0, 0, 0, .7);
  color-scheme: dark;
}

/* ── Base ───────────────────────────────────────────────────────────────── */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Anchors must clear the sticky bar, or #beta lands under it. */
  scroll-padding-top: calc(var(--bar-h) + 12px);
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: 'Nunito', system-ui, sans-serif;
  font-size: 16px;
  font-weight: 700;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* clip, not hidden: `overflow: hidden` on the body turns it into a scroll
     container, which silently breaks every `position: sticky` on the page —
     the diagram, and four section headings. `clip` bounds the same overflow
     without creating one. hidden stays first as the fallback. */
  overflow-x: hidden;
  overflow-x: clip;
}

/* The system accent, so form controls, spinners and text carets take the
   brand rather than the platform blue. */
:root { accent-color: var(--orange); }

::selection { background: var(--peach2); color: var(--ink); }
:root[data-theme="dark"] ::selection { background: #3A241A; color: var(--ink); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) ::selection { background: #3A241A; color: var(--ink); }
}

h1, h2, h3 { margin: 0; font-weight: 900; text-wrap: balance; }
h1 { line-height: 1.02; letter-spacing: var(--track-display); }
h2 { line-height: 1.12; letter-spacing: var(--track-h2); }
h3 { line-height: 1.25; letter-spacing: var(--track-h3); }
p { margin: 0; }
/* pretty on short-to-medium copy only: it pulls the last word back off its own
   line. Long prose and the diagram's own labels are left alone. */
p, li, summary, figcaption { text-wrap: pretty; }
ul, ol { margin: 0; padding: 0; list-style: none; }

a { color: inherit; }

/* Continuous curvature. A CSS radius is a circular arc, which meets the
   straight edge at a visible kink; a superellipse blends into it, which is
   the whole reason Apple's hardware and software agree at the corner. The
   radius vocabulary in DESIGN.md is unchanged — only the curve it draws is.
   Guarded, because a browser without it must fall back to the arc, not to a
   square. */
@supports (corner-shape: squircle) {
  .use, .honest, .callout, .path-step, .icon-btn, .beta-cta, .foot-mail,
  .skip, .qa summary, .beta-link, .langs, .lang, .net-legend .key i,
  .who-item, .use-small {
    corner-shape: squircle;
  }
}

/* The outline already follows the element's own border-radius in every
   browser this page supports, so the ring on a pill stays a pill. The only
   elements that need one supplied are the ones with no radius of their own. */
:focus-visible {
  outline: 2.5px solid var(--orange);
  outline-offset: 3px;
}
.brand:focus-visible { border-radius: var(--r-compact); }

/* fixed, not absolute: an absolutely-positioned skip link parks at the top of
   the document, so focusing it on a scrolled page puts it off-screen. */
.skip {
  position: fixed;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--dark);
  color: #fff;
  padding: 11px 18px;
  border-radius: var(--r-pill);
  font-size: 13.5px;
  font-weight: 800;
  text-decoration: none;
}
.skip:focus { left: var(--gutter); top: 10px; }

/* ── Top bar ────────────────────────────────────────────────────────────── */

/* The scroll edge effect. At the top of the document nothing is underneath the
   bar, so it carries no separator and no shadow — it reads as part of the
   page. The moment content begins to pass beneath it, the material, the
   hairline and the shadow arrive together and say so. main.js owns the flag;
   the bar is opaque and separated without JavaScript. */
.topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  height: var(--bar-h);
  padding: 0 var(--gutter);
  background: var(--bg);
  border-bottom: var(--hairline) solid var(--line);
  transition:
    background-color var(--t-enter) var(--ease),
    border-color var(--t-enter) var(--ease),
    box-shadow var(--t-enter) var(--ease);
}

html[data-scroll="top"] .topbar {
  background: transparent;
  border-bottom-color: transparent;
  box-shadow: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .topbar {
    background: var(--material-bar);
    -webkit-backdrop-filter: var(--material-filter);
    backdrop-filter: var(--material-filter);
    box-shadow: var(--shadow-bar);
  }
}

/* Translucency is a system-level accessibility choice, not a taste one. When
   it is turned off the bar goes solid and keeps its separator. */
@media (prefers-reduced-transparency: reduce) {
  .topbar {
    background: var(--bg);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  html[data-scroll="top"] .topbar { background: var(--bg); }
}

/* Display (26px/900/-0.6px) — DESIGN.md reserves this step for exactly two
   things, and the wordmark in the header is one of them. */
.brand {
  font-size: 26px;
  font-weight: 900;
  letter-spacing: -0.6px;
  text-decoration: none;
  line-height: 1;
}
.brand-mark { color: var(--orange); }

.topbar-tools { display: flex; align-items: center; gap: 8px; }

.langs {
  display: flex;
  gap: 2px;
  padding: 3px;
  background: var(--peach);
  border-radius: var(--r-pill);
}

.lang {
  position: relative;
  border: none;
  background: none;
  cursor: pointer;
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 800;
  color: var(--orange-deep);
  padding: 6px 11px;
  border-radius: var(--r-pill);
  min-height: 32px;
  transition:
    background-color var(--t-tap) var(--ease),
    color var(--t-tap) var(--ease),
    transform var(--t-press) var(--ease-spring);
}
/* The pill stays 32px because a 44px segmented control would dominate a 64px
   bar, but the target does not: the hit area is grown vertically to 44px,
   where there is nothing to collide with. Horizontal is left alone so
   neighbouring languages never steal each other's taps. */
.lang::after {
  content: '';
  position: absolute;
  inset: -6px 0;
}
/* Segment lift — DESIGN.md's own shadow vocabulary, and this is the element it
   was written for: the active pill in a segmented control. */
.lang.is-on {
  background: var(--card);
  color: var(--orange);
  box-shadow: 0 2px 8px rgba(0, 0, 0, .06);
}
@media (hover: hover) {
  .lang:not(.is-on):hover { background: var(--peach2); }
}

.icon-btn {
  position: relative;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border: var(--hairline) solid transparent;
  border-radius: var(--r-compact);
  background: var(--peach);
  color: var(--orange-deep);
  cursor: pointer;
  transition:
    color var(--t-tap) var(--ease),
    border-color var(--t-tap) var(--ease),
    background-color var(--t-tap) var(--ease),
    transform var(--t-press) var(--ease-spring);
}
/* 38px is the visible control; 44×44 is the target. */
.icon-btn::after {
  content: '';
  position: absolute;
  inset: -3px;
}
/* The two glyphs occupy the same cell so the swap can cross-fade instead of
   cutting: sun rotates out and shrinks as moon arrives. */
.icon-btn svg {
  grid-area: 1 / 1;
  width: 19px;
  height: 19px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition:
    opacity var(--t-tap) var(--ease),
    transform var(--t-enter) var(--ease-arrive);
}
.icon-btn .i-sun { opacity: 1; transform: none; }
.icon-btn .i-moon { opacity: 0; transform: scale(.55) rotate(-50deg); }
:root[data-theme="dark"] .icon-btn .i-sun,
.icon-btn[aria-pressed="true"] .i-sun { opacity: 0; transform: scale(.55) rotate(50deg); }
:root[data-theme="dark"] .icon-btn .i-moon,
.icon-btn[aria-pressed="true"] .i-moon { opacity: 1; transform: none; }

@media (hover: hover) {
  .icon-btn:hover {
    color: var(--orange);
    background: var(--peach2);
  }
}

.beta-link {
  font-size: 13.5px;
  font-weight: 800;
  text-decoration: none;
  color: var(--orange-deep);
  background: var(--peach);
  padding: 9px 15px;
  border-radius: var(--r-pill);
  white-space: nowrap;
  transition:
    background-color var(--t-tap) var(--ease),
    transform var(--t-press) var(--ease-spring);
}
@media (hover: hover) { .beta-link:hover { background: var(--peach2); } }

/* Pressed state. Every control on this page reports the press, because a
   control that only reacts to a pointer has nothing to say to a thumb. The
   scale is small and the release rides the spring, so it reads as the surface
   giving rather than as an animation playing. Suppressed under reduced
   motion, where the colour change alone carries it. */
@media (prefers-reduced-motion: no-preference) {
  .lang:active,
  .icon-btn:active,
  .beta-link:active,
  .beta-cta:active,
  .foot-mail:active { transform: scale(.96); }
  .lang:active { transform: scale(.94); }
}

/* The wordmark stays whole at every width — it is the brand. The nav's
   secondary link is what gives way when the bar runs out of room. */
@media (max-width: 460px) {
  .beta-link { display: none; }
  .lang { padding: 6px 9px; }
}

/* ── The building network ───────────────────────────────────────────────── */

.build {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.build-stage {
  position: sticky;
  top: var(--bar-h);
  z-index: 10;
  display: grid;
  place-items: center;
  height: calc(46vh + var(--edge-fade));
  padding-block: 10px calc(6px + var(--edge-fade));
  background: linear-gradient(var(--bg) calc(100% - var(--edge-fade)), transparent);
  /* The bar above is translucent material — 82% alpha over a blur — so
     whatever is underneath shows through it, and underneath was the scrolling
     text of the page: sentences drifting across the top of the diagram. This
     shadow is a hard-edged copy of the panel offset up by exactly the height
     of the bar, filling that strip with the page background so the text passes
     behind it and the bar has something still to blur.
     A shadow rather than a taller panel, because height here is layout and
     would push every step below down by the height of the bar. A shadow rather
     than a pseudo-element, because `overflow` clips descendants but never an
     element's own shadow — and this panel has to keep clipping.
     The bottom edge keeps its deliberate fade: padding holds the drawing clear
     of that band, so only empty background is ever translucent there. */
  box-shadow: 0 calc(-1 * var(--bar-h)) 0 var(--bg);
  overflow: hidden;
}

.net-figure {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  width: 100%;
  height: 100%;
  min-height: 0;
}

.net {
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  max-width: 34vh;
  height: 100%;
  overflow: visible;
}

/* globe.js swaps the SVG for this canvas once the coastline loads. A canvas
   has no intrinsic aspect ratio to preserve, so the square is declared. */
.globe {
  flex: 1 1 auto;
  min-height: 0;
  width: auto;
  height: 100%;
  max-width: 100%;
  aspect-ratio: 1 / 1;
  /* Vertical drags belong to the page — the globe lives inside a sticky panel
     that a thumb has to be able to scroll past. Horizontal drags spin it. */
  touch-action: pan-y;
}
@media (hover: hover) {
  .globe { cursor: grab; }
  .globe.is-held { cursor: grabbing; }
}

.net-edge {
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset var(--t-draw) var(--ease-arrive);
  transition-delay: 0ms;
}

/* Stagger lives here rather than in a style attribute on each element, so the
   page needs no 'unsafe-inline' in style-src. Eight buckets is enough for the
   reveal to read as growth instead of a switch. */
.net-edge:nth-child(8n + 2) { transition-delay: 40ms; }
.net-edge:nth-child(8n + 3) { transition-delay: 80ms; }
.net-edge:nth-child(8n + 4) { transition-delay: 120ms; }
.net-edge:nth-child(8n + 5) { transition-delay: 160ms; }
.net-edge:nth-child(8n + 6) { transition-delay: 200ms; }
.net-edge:nth-child(8n + 7) { transition-delay: 240ms; }
.net-edge:nth-child(8n + 8) { transition-delay: 280ms; }
.net-edge[data-ring="1"] { stroke: var(--hand-1-ink); }
.net-edge[data-ring="2"] { stroke: var(--hand-2-ink); }
.net-edge[data-ring="3"] { stroke: var(--hand-3-ink); }

/* A node does not fade in; it lands. The spring gives it a single 8% overshoot
   and settles — the same physics a control uses when it arrives under your
   thumb. This is the page's one authored moment and the only place the spring
   is spent on entry. */
.net-node {
  transform-box: fill-box;
  transform-origin: center;
  transform: scale(0);
  opacity: 0;
  transition:
    transform 520ms var(--ease-spring),
    opacity var(--t-enter) var(--ease);
  transition-delay: 140ms;
}
.net-node:nth-child(8n + 2) { transition-delay: 180ms; }
.net-node:nth-child(8n + 3) { transition-delay: 220ms; }
.net-node:nth-child(8n + 4) { transition-delay: 260ms; }
.net-node:nth-child(8n + 5) { transition-delay: 300ms; }
.net-node:nth-child(8n + 6) { transition-delay: 340ms; }
.net-node:nth-child(8n + 7) { transition-delay: 380ms; }
.net-node:nth-child(8n + 8) { transition-delay: 420ms; }
.net-node[data-ring="1"] { fill: var(--hand-1-ink); }
.net-node[data-ring="2"] { fill: var(--hand-2-ink); }
.net-node[data-ring="3"] { fill: var(--hand-3-ink); }

.net-me { transform: none; opacity: 1; transition: none; }
.net-me circle { fill: var(--orange); }
/* A geometric mark, not a ramp step: DESIGN.md sizes the letter inside a
   circle at 0.35 × its diameter. This circle is 54 units across. */
.net-me text {
  fill: #fff;
  font-family: 'Nunito', system-ui, sans-serif;
  font-size: 19px;
  font-weight: 900;
}

/* Reveal rings up to the current stage. Six selectors, one per (stage, ring)
   pair that should be visible — cheaper to read than a generated cascade. */
.net[data-stage="1"] [data-ring="1"],
.net[data-stage="2"] [data-ring="1"],
.net[data-stage="2"] [data-ring="2"],
.net[data-stage="3"] [data-ring="1"],
.net[data-stage="3"] [data-ring="2"],
.net[data-stage="3"] [data-ring="3"] {
  opacity: 1;
  transform: scale(1);
  stroke-dashoffset: 0;
}

.net-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: 6px 14px;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--muted);
  text-align: center;
}
.net-count b {
  font-size: 21px;
  font-weight: 900;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.net-keys { display: flex; flex-wrap: wrap; gap: 4px 14px; justify-content: center; }
.key { display: inline-flex; align-items: baseline; gap: 6px; white-space: nowrap; font-size: 13.5px; }
.key b {
  font-variant-numeric: tabular-nums;
  font-weight: 900;
  color: var(--ink);
  min-width: 1.4ch;
  text-align: right;
}
.key i { width: 9px; height: 9px; border-radius: var(--r-pill); flex: none; }
.key[data-ring="1"] i { background: var(--hand-1-ink); }
.key[data-ring="2"] i { background: var(--hand-2-ink); }
.key[data-ring="3"] i { background: var(--hand-3-ink); }
.net-disclaimer { flex-basis: 100%; font-size: 11px; font-weight: 700; color: var(--faint); }

.build-steps { position: relative; z-index: 1; }

.step {
  min-height: 62vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-block: clamp(2.5rem, 6vh, 5rem);
  max-width: 44rem;
}
.step > * + * { margin-top: 1.1rem; }
.step h2 { font-size: var(--text-h2); }
.step p { max-width: 62ch; color: var(--muted); }

/* Sized so the headline and the single node share the first screen: the empty
   network is the argument, and it has to be readable while the claim is read. */
.step-hero { min-height: calc(62vh - var(--bar-h)); justify-content: center; padding-block: 1.5rem; }
.step-hero h1 {
  font-size: var(--text-display);
  line-height: 1.02;
}
.step-hero .lead { font-size: var(--text-lead); color: var(--muted); max-width: 40ch; }
.step-hero .state { color: var(--ink); font-weight: 800; max-width: none; }

.cue {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 13.5px;
  font-weight: 800;
  color: var(--faint);
  max-width: none;
}
.cue-rule { width: 34px; height: var(--hairline); background: var(--line); flex: none; }

.facts { display: grid; gap: 10px; max-width: 58ch; }
.facts li {
  position: relative;
  padding-left: 22px;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--muted);
  line-height: 1.5;
}
.facts li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 9px;
  height: var(--hairline);
  background: var(--orange-soft);
}

/* Below 900px the hero comes first in flow and the stage only starts sticking
   once the first real step arrives — otherwise a half-empty diagram would push
   the headline off the first screen. Above 900px the stage moves to its own
   column and spans both rows, so the hero keeps its lone node. */
@media (min-width: 900px) {
  .build {
    display: grid;
    grid-template-columns: minmax(0, 1.02fr) minmax(0, 1fr);
    grid-template-areas:
      "hero  stage"
      "steps stage";
    column-gap: clamp(2rem, 4vw, 5rem);
    align-items: start;
  }
  .step-hero { grid-area: hero; }
  .build-steps { grid-area: steps; }
  .build-stage {
    grid-area: stage;
    align-self: start;
    height: 100vh;
    top: 0;
    padding-block: 0;
    background: none;
  }
  /* Its own column, nothing scrolling behind it, and no panel background to
     continue — the plate would only be a bar-shaped block of colour. */
  .build-stage { box-shadow: none; }
  /* In its own full-height column the figure centres as a group; the flexible
     drawing that makes the short mobile stage fit would otherwise grow into
     the whole column and strand the legend at the bottom of the screen. */
  .net-figure { height: auto; }
  .net {
    flex: 0 0 auto;
    height: auto;
    max-width: min(100%, 58vh);
  }
  .globe {
    flex: 0 0 auto;
    width: min(100%, 58vh);
    height: auto;
  }
  .step { min-height: 88vh; }
  .step-hero { min-height: calc(100vh - var(--bar-h)); justify-content: center; }
}

/* ── Uses ───────────────────────────────────────────────────────────────── */

.uses {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: var(--space-section) var(--gutter) 0;
  display: grid;
  gap: 14px;
}
.uses > h2 { font-size: var(--text-h2); margin-bottom: 0.4rem; }

.use {
  background: var(--card);
  border: var(--hairline) solid var(--line);
  border-radius: var(--r-card);
  padding: clamp(1.1rem, 2.4vw, 2rem);
  box-shadow: var(--shadow-raise);
}
.use h3 { font-size: var(--text-h3); }
.use p { color: var(--muted); max-width: 60ch; margin-top: 0.6rem; }

.path {
  display: flex;
  flex-direction: column;
  gap: 0;
  margin-top: 1.4rem;
}
.path-step {
  display: flex;
  align-items: baseline;
  gap: 9px;
  flex-wrap: wrap;
  padding: 10px 15px;
  border: var(--hairline) solid var(--line);
  border-radius: var(--r-tile);
  background: var(--bg);
  align-self: flex-start;
}
.path-step b { font-size: 16px; font-weight: 800; color: var(--ink); }
.path-step span { font-size: 13.5px; font-weight: 700; color: var(--muted); }
.path-step[data-ring="0"] { background: var(--peach); border-color: var(--peach2); }
.path-step[data-ring="0"] b { color: var(--orange-deep); }

/* The hand gradient carries distance here as a marker, not as text colour:
   these inks are specified for 11px badges and land under 4.5:1 at name size,
   so the dot does the encoding and the name stays on Ink. */
.path-step::before {
  content: '';
  width: 9px;
  height: 9px;
  border-radius: var(--r-pill);
  background: var(--orange);
  flex: none;
}
.path-step[data-ring="1"]::before { background: var(--hand-1-ink); }
.path-step[data-ring="2"]::before { background: var(--hand-2-ink); }
.path-step[data-ring="3"]::before { background: var(--hand-3-ink); }

/* The connector takes ::after — ::before is the distance marker above. */
.path-step + .path-step { margin-top: 22px; position: relative; }
.path-step + .path-step::after {
  content: '';
  position: absolute;
  left: 24px;
  top: -22px;
  width: var(--hairline);
  height: 22px;
  background: var(--line);
}

.synthetic { font-size: 11px; font-weight: 700; color: var(--faint); margin-top: 1rem; }

.callout {
  margin-top: 1rem;
  background: var(--peach);
  color: var(--orange-deep);
  border-radius: var(--r-tile);
  padding: 12px 15px;
  font-size: 13.5px;
  font-weight: 800;
  max-width: none;
}

/* Deliberately not cards. Three identical bordered boxes would turn the row
   into the page's structure; a hairline rule keeps them subordinate to the
   two surfaces above and lets the section breathe. */
.use-rest { display: grid; gap: 14px; margin-top: 10px; }
.use-small {
  border-top: var(--hairline) solid var(--line);
  padding: 18px 2px 0;
}
.use-small h3 { font-size: 16px; font-weight: 800; margin-top: 0.7rem; }
.use-small p { color: var(--muted); font-size: 13.5px; margin-top: 0.4rem; }
.ico {
  width: 24px;
  height: 24px;
  display: block;
  fill: none;
  stroke: var(--orange);
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}

@media (min-width: 760px) {
  .uses { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .uses > h2 { grid-column: 1 / -1; }
  .use-path { grid-column: span 4; }
  .use-match { grid-column: span 2; }
  .use-rest {
    grid-column: 1 / -1;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: clamp(1.5rem, 3vw, 3rem);
  }

  .path { flex-direction: row; align-items: stretch; flex-wrap: wrap; gap: 0; }
  .path-step { align-self: stretch; align-items: center; flex-direction: column; gap: 3px; text-align: center; flex: 1 1 0; min-width: 8rem; }
  .path-step::before { margin-bottom: 2px; }
  .path-step + .path-step { margin-top: 0; margin-left: 26px; }
  .path-step + .path-step::after {
    left: -26px;
    top: 50%;
    width: 26px;
    height: var(--hairline);
  }
}

/* ── Absences ───────────────────────────────────────────────────────────── */

.absent {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: var(--space-section) var(--gutter) 0;
}
.absent > h2 { font-size: var(--text-h2); }

.absent-list {
  margin-top: 1.6rem;
  border-top: var(--hairline) solid var(--line);
}
.absent-list li {
  padding: 16px 0;
  border-bottom: var(--hairline) solid var(--line);
  color: var(--muted);
}
.absent-list b { color: var(--ink); font-weight: 900; }

.honest {
  margin-top: 20px;
  background: var(--card);
  border: var(--hairline) solid var(--line);
  border-radius: var(--r-card);
  padding: 16px 18px;
  box-shadow: var(--shadow-raise);
}
.honest h3 { font-size: 16px; font-weight: 800; }
.honest p { margin-top: 0.4rem; color: var(--muted); font-size: 13.5px; }

/* The heading holds the left column while the content runs down the right,
   the same two-column rhythm the build section establishes above. */
@media (min-width: 900px) {
  .absent {
    display: grid;
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.4fr);
    column-gap: clamp(2rem, 4vw, 5rem);
    align-items: start;
  }
  .absent > h2 {
    position: sticky;
    top: calc(var(--bar-h) + 2rem);
    align-self: start;
  }
  .absent-list { margin-top: 0; }
}

/* ── Beta ───────────────────────────────────────────────────────────────── */

.beta {
  max-width: var(--maxw);
  margin: var(--space-section) auto 0;
  padding: 0 var(--gutter);
}
.beta > h2 { font-size: var(--text-h2); }
.beta-lead { margin-top: 0.8rem; font-size: var(--text-lead); color: var(--muted); max-width: 52ch; }
.facts-beta { margin-top: 1.4rem; }
.beta-note { margin-top: 1.6rem; font-size: 13.5px; font-weight: 800; color: var(--faint); max-width: 52ch; }

.beta-cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 1rem;
  padding: 13px 22px;
  border-radius: var(--r-btn);
  border: var(--hairline) solid var(--line);
  background: var(--card);
  color: var(--orange-deep);
  font-size: 16px;
  font-weight: 800;
  text-decoration: none;
  transition:
    border-color var(--t-tap) var(--ease),
    background-color var(--t-tap) var(--ease),
    transform var(--t-press) var(--ease-spring);
}
.beta-cta::after {
  content: '';
  width: 7px;
  height: 7px;
  border-right: 2px solid currentColor;
  border-top: 2px solid currentColor;
  transform: rotate(45deg);
}
@media (hover: hover) {
  .beta-cta:hover { border-color: var(--orange-soft); background: var(--peach); }
}

@media (min-width: 900px) {
  .beta {
    display: grid;
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.4fr);
    column-gap: clamp(2rem, 4vw, 5rem);
    align-items: start;
  }
  .beta > h2 { grid-column: 1; grid-row: 1; }
  .beta-lead { grid-column: 1; grid-row: 2; }
  .beta-body { grid-column: 2; grid-row: 1 / span 2; }
  .facts-beta { margin-top: 0.5rem; }
}

/* ── Footer ─────────────────────────────────────────────────────────────── */

/* The layout lives in the later `.foot` block, below; these two are the only
   rules the earlier duplicate contributed. */
.foot-brand { font-size: 16px; font-weight: 900; letter-spacing: -0.3px; }
.foot-line { font-size: 13.5px; font-weight: 700; color: var(--faint); }

/* ── Reduced motion ─────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  .net-edge, .net-node {
    transition-duration: 1ms;
    transition-delay: 0ms;
  }
  /* The spring's overshoot is the one curve that moves an element past where
     it is going. Under reduced motion every spring collapses to the system's
     own ease, so nothing on the page travels further than its destination. */
  :root { --ease-spring: var(--ease); }
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
  }
}

/* ── Forced colours ─────────────────────────────────────────────────────── */

/* In a forced-colours mode the page's own palette is replaced, which would
   erase the one thing the diagram encodes: distance as temperature. The graph
   keeps its own colours; everything else takes the user's. */
@media (forced-colors: active) {
  .net-edge, .net-node, .key i, .path-step::before { forced-color-adjust: none; }
  .topbar {
    background: Canvas;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    border-bottom-color: CanvasText;
  }
  html[data-scroll="top"] .topbar { background: Canvas; border-bottom-color: CanvasText; }
  .use, .honest, .beta-cta, .foot-mail, .icon-btn { border: var(--hairline) solid CanvasText; }
}

/* ── Strapline ──────────────────────────────────────────────────────────── */

/* The business plan's own line. Sits between the lead and the state as the
   one piece of ambition on a page that otherwise only makes narrow claims. */
.strapline {
  font-size: var(--text-h3);
  font-weight: 900;
  letter-spacing: var(--track-h3);
  color: var(--orange-deep);
  max-width: 30ch;
}

/* ── Who it is for ──────────────────────────────────────────────────────── */

.who {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: var(--space-section) var(--gutter) 0;
}
.who > h2 { font-size: var(--text-h2); }
.who-lead { margin-top: 0.8rem; color: var(--muted); max-width: 56ch; font-size: var(--text-lead); }

/* Hairline rules rather than six identical boxes: a uniform card grid would
   read as the page's structure, and the structure here is the network. */
.who-grid { display: grid; gap: 22px; margin-top: clamp(1.8rem, 4vw, 3rem); }
.who-item { border-top: var(--hairline) solid var(--line); padding: 18px 2px 0; }
.who-item h3 { font-size: 16px; font-weight: 800; margin-top: 0.7rem; }
.who-item p { font-size: 13.5px; color: var(--muted); margin-top: 0.4rem; }

@media (min-width: 640px) { .who-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(1.5rem, 3vw, 3rem); } }
@media (min-width: 980px) { .who-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* ── FAQ ────────────────────────────────────────────────────────────────── */

.faq {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: var(--space-section) var(--gutter) 0;
}
.faq > h2 { font-size: var(--text-h2); }
.faq-list { margin-top: 1.6rem; border-top: var(--hairline) solid var(--line); }

.qa { border-bottom: var(--hairline) solid var(--line); }
.qa summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 17px 0;
  cursor: pointer;
  font-size: 16px;
  font-weight: 800;
  list-style: none;
  border-radius: var(--r-compact);
}
.qa summary::-webkit-details-marker { display: none; }
/* A drawn chevron, not a glyph: it rotates to report the open state. */
.qa summary::after {
  content: '';
  flex: none;
  width: 9px;
  height: 9px;
  border-right: 2px solid var(--orange);
  border-bottom: 2px solid var(--orange);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform var(--t-tap) var(--ease);
}
.qa[open] summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.qa p { padding: 0 0 18px; color: var(--muted); max-width: 72ch; }
@media (hover: hover) { .qa summary:hover { color: var(--orange-deep); } }
.qa summary:active { color: var(--orange); }

@supports (interpolate-size: allow-keywords) and selector(::details-content) {
  :root { interpolate-size: allow-keywords; }
  .qa::details-content {
    block-size: 0;
    overflow: clip;
    opacity: 0;
    transition:
      block-size var(--t-enter) var(--ease),
      opacity var(--t-enter) var(--ease),
      content-visibility var(--t-enter) allow-discrete;
  }
  .qa[open]::details-content { block-size: auto; opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .qa::details-content { transition-duration: 1ms; }
}

@media (min-width: 900px) {
  .faq {
    display: grid;
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.4fr);
    column-gap: clamp(2rem, 4vw, 5rem);
    align-items: start;
  }
  .faq > h2 { position: sticky; top: calc(var(--bar-h) + 2rem); align-self: start; }
  .faq-list { margin-top: 0; }
}

/* ── What comes next ────────────────────────────────────────────────────── */

.next {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: var(--space-section) var(--gutter) 0;
}
.next > h2 { font-size: var(--text-h2); }
.next-lead { color: var(--faint); font-size: 13.5px; font-weight: 800; }
.next-list { margin-top: 1.2rem; display: grid; gap: 12px; max-width: 60ch; }
.next-list li {
  position: relative;
  padding-left: 26px;
  font-size: 16px;
  font-weight: 700;
  color: var(--muted);
}
/* Open circles, not ticks: none of this is done yet. */
.next-list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.45em;
  width: 10px;
  height: 10px;
  border: var(--hairline) solid var(--orange-soft);
  border-radius: var(--r-pill);
}

@media (min-width: 900px) {
  .next {
    display: grid;
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.4fr);
    column-gap: clamp(2rem, 4vw, 5rem);
    align-items: start;
  }
  .next-body { grid-column: 2; }
}
@media (max-width: 899px) { .next-body { margin-top: 1rem; } }

/* ── Footer with contacts ───────────────────────────────────────────────── */

.foot {
  max-width: var(--maxw);
  margin: var(--space-section) auto 0;
  padding: clamp(2.5rem, 5vw, 4rem) var(--gutter) calc(28px + env(safe-area-inset-bottom));
  border-top: var(--hairline) solid var(--line);
  display: grid;
  gap: clamp(2rem, 4vw, 4rem);
  align-items: start;
}
.foot > h2, .foot-contact h2 { font-size: var(--text-h2); }
.foot-lead { margin-top: 0.7rem; color: var(--muted); max-width: 40ch; }

.foot-mail {
  display: inline-block;
  margin-top: 1.1rem;
  padding: 13px 22px;
  border-radius: var(--r-btn);
  background: var(--orange-btn);
  color: #fff;
  font-size: 16px;
  font-weight: 800;
  text-decoration: none;
  box-shadow: var(--shadow-raise);
  transition:
    background-color var(--t-tap) var(--ease),
    box-shadow var(--t-tap) var(--ease),
    transform var(--t-press) var(--ease-spring);
}
@media (hover: hover) { .foot-mail:hover { background: var(--orange-deep); } }

.foot-label {
  font-size: 11px;
  font-weight: 900;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--faint);
}
.team { margin-top: 12px; display: grid; gap: 14px; }
.team li { display: grid; gap: 2px; }
.team b { font-size: 16px; font-weight: 800; }
.team span { font-size: 13.5px; font-weight: 700; color: var(--muted); }
.foot-place { margin-top: 16px; font-size: 13.5px; font-weight: 700; color: var(--faint); }

.foot-end {
  border-top: var(--hairline) solid var(--line);
  padding-top: 20px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 20px;
  justify-content: space-between;
  align-items: baseline;
}

@media (min-width: 760px) {
  .foot { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); }
  .foot-end { grid-column: 1 / -1; }
}
