/* ---------------------------------------------------------------------------
   Screen Fasting — landing page.

   Tokens are carried directly from the app (src/styles.css) rather than
   invented, per the IA's visual-language section: near-black ground, brass as
   the single accent used only for actions and decisions, iOS blue confined to
   phone mocks. Serif headings over sans body, hairline rules instead of cards,
   monospace numerals — digits are the product's material.

   Deliberately absent: gradients as decoration, glassmorphism, floating or
   angled mockups, scroll-triggered fades, streaks, emoji, confetti. Motion is
   otherwise confined to the §02 hero animation, which loops a stripped-down
   phone-only version of the arc forever, plus one narrow exception: §04 step 2
   loops a slower, fuller version of the same decoy-typing beats once scrolled
   into view. Nothing else below the hero moves.
   --------------------------------------------------------------------------- */

:root {
  --bg: #0a0b0d;
  --bg-raised: #111317;
  --line: #1e2228;
  --line-strong: #2b3038;

  --text: #e9e7e2;
  --text-dim: #9aa0aa;
  --text-faint: #6b717b;

  --brass: #c9a86a;
  --brass-dim: #8a7346;

  --ios-blue: #0a84ff;

  --font-sans: ui-sans-serif, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-serif: ui-serif, Georgia, 'Times New Roman', serif;
  --font-mono: ui-monospace, 'SF Mono', Menlo, monospace;

  --ease: cubic-bezier(0.32, 0.72, 0, 1);

  --wrap: 1140px;
  --gutter: 28px;

  /* §04's browser+phone duo is a 450px canvas that has to fit between the
     gutters.

     Dividing by 450px, not 450: length / length yields the unitless number
     transform and zoom need; length / number would yield a length, and min()
     cannot compare a length against 1.

     44px is the two 20px gutters at narrow widths, plus 4px of slop for
     subpixel rounding and, in a narrow desktop window, the classic scrollbar
     that 100vw counts but the layout box does not. It caps at 1 above ~494px,
     so the wider 28px gutter above 560px never matters. */
  --mock-fit: min(1, (100vw - 44px) / 450px);

  /* The hero's stage is the phone alone now (202px, its own intrinsic width),
     so it gets its own, smaller-divisor version of the same ratio rather than
     sharing §04's — the two canvases are different sizes and must not drift
     onto the same fit variable. */
  --hero-fit: min(1, (100vw - 44px) / 202px);
}

* {
  box-sizing: border-box;
}

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* A net, not a fix — the real overflow causes are handled at their source.
     clip rather than hidden: hidden would make body a scroll container and
     break the sticky nav, and would force overflow-y from visible to auto. */
  overflow-x: clip;
}

/* The app's single slow radial wash, carried over verbatim. Depth without
   motion — this is the app's existing ground, not decoration added here. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(120% 80% at 50% -10%, #17191f 0%, transparent 60%);
  z-index: 0;
}

body > * {
  position: relative;
  z-index: 1;
}

h1 {
  font-family: var(--font-serif);
  font-weight: 500;
  letter-spacing: -0.015em;
  margin: 0;
}

h2,
h3 {
  font-family: var(--font-serif);
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.25;
  margin: 0;
}

p {
  margin: 0;
}

[hidden] {
  display: none !important;
}

a {
  color: var(--brass);
}

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

/* --- §01 nav ---------------------------------------------------------------
   Sticky on desktop only. No dropdowns. "Sign in" stays a low-emphasis text
   link so it never competes with the CTA, which is itself the signup path. */

.nav {
  border-bottom: 1px solid var(--line);
}

/* Wrapping is always allowed, not just below a breakpoint: .wordmark and
   .nav-auth are both flex:none, so once .nav-links is hidden there is nothing
   left that can shrink. Without flex-wrap the row overflows on a narrow phone,
   and because the nav is the first element in the document that overflow gives
   the entire page a horizontal scrollbar. min-height replaces the fixed height
   so a wrapped second row has somewhere to go; on desktop the content is ~36px
   tall, so min-height wins and this measures 68px exactly as before. */
.nav-inner {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  column-gap: 28px;
  row-gap: 12px;
  min-height: 68px;
  padding-block: 12px;
}

.wordmark {
  display: flex;
  align-items: center;
  flex: none;
}

.nav-links {
  display: flex;
  gap: 26px;
  margin-left: 14px;
  font-size: 15px;
}

.nav-links a {
  color: var(--text-dim);
  text-decoration: none;
  transition: color 0.15s var(--ease);
}

.nav-links a:hover {
  color: var(--text);
}

.nav-auth {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 20px;
  flex: none;
}

.nav-signin {
  font-size: 15px;
  color: var(--text-dim);
  text-decoration: none;
  transition: color 0.15s var(--ease);
}

.nav-signin:hover {
  color: var(--text);
}

/* Invisible at desktop widths: .nav-links and .nav-auth stay direct flex
   children of .nav-inner, unchanged from before this wrapper existed. Below
   860px this switches to the collapsed dropdown panel instead. */
.nav-menu {
  display: contents;
}

.nav-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  margin-left: auto;
  width: 34px;
  height: 34px;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
}

.nav-toggle-bar {
  display: block;
  height: 2px;
  width: 100%;
  background: var(--text);
  border-radius: 1px;
  transition: transform 0.15s var(--ease), opacity 0.15s var(--ease);
}

@media (min-width: 861px) {
  .nav {
    position: sticky;
    top: 0;
    z-index: 20;
    background: #0a0b0dd9;
    backdrop-filter: saturate(140%) blur(10px);
  }

  /* Without this an anchor jump parks the section's top hairline under the
     68px sticky bar and leaves the eyebrow ~20px below it, close enough that
     the nav's own "How it works / Pricing / FAQ" reads as the section header.
     68 + 12px of air, so the hairline clears the nav and the section keeps the
     full 88-96px of top padding it already carries. */
  section[id] {
    scroll-margin-top: 80px;
  }
}

/* --- the one button --------------------------------------------------------
   Brass is reserved for actions and decisions; this is the only place it
   appears as a fill. */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: var(--brass);
  color: #14100a;
  font-family: var(--font-sans);
  font-weight: 600;
  text-decoration: none;
  border-radius: 10px;
  border: 1px solid var(--brass);
  transition: background 0.15s var(--ease), border-color 0.15s var(--ease);
}

.btn:hover {
  background: #d8ba82;
  border-color: #d8ba82;
}

.btn:focus-visible {
  outline: 2px solid var(--brass);
  outline-offset: 3px;
}

.btn-sm {
  font-size: 15px;
  padding: 8px 16px;
}

.btn-lg {
  font-size: 17px;
  padding: 15px 26px;
  letter-spacing: 0.005em;
}

.btn .arrow {
  transition: transform 0.18s var(--ease);
}

.btn:hover .arrow {
  transform: translateX(3px);
}

/* --- §02 hero --------------------------------------------------------------- */

.hero {
  padding: 88px 0 104px;
}

.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 72px;
  align-items: center;
}

.hero-copy {
  max-width: 34rem;
}

/* Four dots — the passcode field, reused as the page's section marker. */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brass);
  margin-bottom: 22px;
}

.eyebrow .dots {
  letter-spacing: 0.2em;
}

.hero h1 {
  font-size: clamp(2.25rem, 5vw, 3.35rem);
  line-height: 1.12;
  text-wrap: balance;
  margin-bottom: 24px;
}

.standfirst {
  font-size: clamp(1.05rem, 3vw, 1.15rem);
  line-height: 1.62;
  color: var(--text-dim);
  max-width: 33rem;
}

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

.cta-block {
  margin-top: 38px;
}

/* --text-faint (#6b717b) measures 4.0:1 on the ground — it is fine for rules and
   glyphs but fails AA for text, so every small string here uses --text-dim
   (7.5:1) and relies on size, not colour, for its lower rank. */
.micro {
  font-family: var(--font-mono);
  font-size: 12.5px;
  letter-spacing: 0.06em;
  color: var(--text-dim);
  margin-top: 14px;
}

/* The one reassurance that stays out of the FAQ. Nobody opens an accordion
   before deciding, and this is the sentence that turns "absolutely not" into
   "wait, actually?". */
.assure {
  margin-top: 26px;
  padding-left: 14px;
  border-left: 2px solid var(--line-strong);
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--text-dim);
  max-width: 31rem;
}

.returning {
  margin-top: 30px;
  padding-top: 22px;
  border-top: 1px solid var(--line);
  font-size: 14.5px;
  color: var(--text-dim);
  max-width: 33rem;
}

.returning a {
  color: var(--text);
  text-underline-offset: 3px;
}

.returning a:hover {
  color: var(--text);
}

/* --- the stage -------------------------------------------------------------
   One object: the phone, sized to its own intrinsic 202×438 canvas. No
   angle, no float, no drop shadow.

   Everything inside .stage-scene is positioned against that fixed canvas and
   then transform-scaled as a unit, so narrow screens shrink one number
   instead of re-laying out anything. .stage-frame reserves the scaled box in
   normal flow; the caption underneath never scales. */

/* .hero-grid's second column is auto-sized, which means its width comes from
   the max-content size of whatever's inside .hero-device. The phone itself is
   a fixed 202px — but the caption below it (and #stage, which shrink-wraps
   its own children) has no explicit width, so it hugs whichever caption is
   current, and that text changes length between the cluttered and locked
   beats. Left alone, #stage — and with it the phone centered inside —
   resizes and re-centers every time the caption's content changes, which
   reads as the phone sliding sideways.

   Two things fix it together: .hero-device gets an explicit width so its own
   contribution to the grid column never varies with content, and
   align-items:stretch makes #stage fill that width outright instead of
   shrink-wrapping to whichever caption is shorter. max-width covers the
   narrow end, where .hero-grid has already collapsed to one column. */
.hero-device {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 20px;
  flex: none;
  width: 21rem;
  max-width: 100%;
}

.stage {
  --scene-w: 202px;
  --scene-h: 438px;
  --s: var(--hero-fit);
}

.stage-frame {
  width: calc(var(--scene-w) * var(--s));
  height: calc(var(--scene-h) * var(--s));
  /* #stage now stretches to fill .hero-device's fixed width (see its
     comment); this fixed-width box needs its own centering within that. */
  margin-inline: auto;
}

.stage-scene {
  position: relative;
  width: var(--scene-w);
  height: var(--scene-h);
  transform: scale(var(--s));
  transform-origin: top left;
}

/* --- the browser -----------------------------------------------------------
   Our own page, so it is dark. A white Chrome mock would be the only bright
   rectangle on the site and would read as somebody else's software. */

.browser {
  position: absolute;
  top: 0;
  left: 0;
  width: 400px;
  height: 305px;
  background: var(--bg-raised);
  border: 1px solid var(--line-strong);
  border-radius: 12px;
  overflow: hidden;
}

.browser-bar {
  display: flex;
  align-items: center;
  gap: 7px;
  height: 34px;
  padding: 0 13px;
  border-bottom: 1px solid var(--line);
}

.browser-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--line-strong);
  flex: none;
}

.browser-url {
  margin-left: 9px;
  padding: 3px 12px;
  border-radius: 999px;
  background: var(--bg);
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.03em;
  color: var(--text-dim);
}

/* The phone covers everything right of ~245px, so the copy lives in a column
   narrower than the window it sits in. */
.browser-body {
  position: relative;
  height: calc(100% - 34px);
}

/* Centred vertically rather than pinned to the top: the four scenes are
   different heights, and hanging them all from the top left the shortest ones
   floating above a third of an empty window. */
.bscene {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 227px;
  padding: 18px 0 18px 22px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.26s var(--ease), visibility 0.26s;
}

.bscene.is-on {
  opacity: 1;
  visibility: visible;
}

.b-eyebrow {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--brass);
  margin-bottom: 14px;
}

.b-label {
  font-size: 12.5px;
  color: var(--text-dim);
  margin-bottom: 4px;
}

.b-big {
  font-size: 30px;
  line-height: 1.1;
  color: var(--text);
}

.b-code {
  font-size: 38px;
  letter-spacing: 0.12em;
  color: var(--brass);
}

.b-note {
  margin-top: 14px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text-dim);
}

/* The digit being asked for. Brass and boxed, because it is an instruction —
   the one thing on this screen the reader is meant to act on. */
.b-key {
  display: flex;
  align-items: center;
  justify-content: center;
  /* The scene is a stretch-aligned flex column; without this the box would
     widen to the full text measure the moment .is-more drops the fixed size. */
  align-self: flex-start;
  width: 74px;
  height: 74px;
  border: 1px solid var(--brass-dim);
  border-radius: 14px;
  font-family: var(--font-mono);
  font-size: 34px;
  color: var(--brass);
}

/* The tail of the sequence, stated rather than played — six more keypresses
   would be six more seconds of watching someone else type. */
.b-key.is-more {
  width: auto;
  height: auto;
  padding: 12px 16px;
  font-size: 15px;
  letter-spacing: 0.04em;
}

/* --- the phone -------------------------------------------------------------
   Proportions mirror the app's PhoneFrame so the page and the product look
   like the same object. */

.phone {
  position: absolute;
  left: 248px;
  top: 52px;
  width: 202px;
  height: 438px;
  background: #000;
  border-radius: 34px;
  border: 1px solid var(--line-strong);
  padding: 8px;
  /* A seat, not a spotlight. */
  box-shadow: inset 0 0 0 3px #0e1013;
}

/* The hero's stage is the phone alone, sized to fit it exactly — it doesn't
   need the browser's coordinate system to sit next to. Scoped: §04's duo
   still needs the absolute positioning above. */
#stage .phone {
  position: static;
}

.phone-notch {
  position: absolute;
  top: 13px;
  left: 50%;
  transform: translateX(-50%);
  width: 66px;
  height: 17px;
  background: #000;
  border-radius: 999px;
  z-index: 3;
}

.phone-screen {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 27px;
  overflow: hidden;
  background: #000;
}

/* --- the beats -------------------------------------------------------------
   Scenes stacked in the one frame, cross-fading. Sizes here are tuned to a
   184×420 screen — the phone shrank when the browser joined it on the stage,
   so tiles, gaps and keys are all smaller than the app's own. */

.scene {
  position: absolute;
  inset: 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.26s var(--ease), visibility 0.26s;
}

/* The hero's only crossfade — cluttered to locked — gets a slower fade than
   §04's. A quick swap would read as a UI trick; a slow one reads as
   something actually happening to the phone, which is the point of the
   whole beat. */
#stage .scene {
  transition: opacity 1.4s var(--ease), visibility 1.4s;
}

.scene.is-on {
  opacity: 1;
  visibility: visible;
}

/* The first and last beats — the phone as it is now. Plain tinted tiles rather
   than imitations of anybody's app icons. */
.ios-grid {
  padding: 40px 12px 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px 10px;
}

.ios-app {
  position: relative;
  aspect-ratio: 1;
  border-radius: 9px;
  background: var(--t, #48484a);
}

.ios-app.badge::after {
  content: '';
  position: absolute;
  top: -2px;
  right: -2px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #ff3b30;
  border: 1.5px solid #000;
}

.ios-dock {
  position: absolute;
  left: 9px;
  right: 9px;
  bottom: 10px;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  padding: 8px;
  border-radius: 17px;
  background: #ffffff1f;
}

/* --- the Assistive Access keypad, shared ------------------------------------
   Base rules for the passcode screen's dots and keypad. Both the hero's phone
   (§02) and row 02's mock (§04) draw this object, at different sizes: the base
   is authored here and each caller scales it from its own block. It mirrors
   src/components/phone.css, which is why it looks like iOS rather than like
   this page — the reader is meant to read it as their phone.

   Nothing on this page makes these keys interactive: both instances are spans,
   so there are no hover, cursor or focus rules to write.

   These were two tiers — a base size plus a .stage-scene override — back when
   §04 drew the same keypad in a 260px panel. Both callers now render it at one
   size inside a 184px phone screen, so there is one set of numbers. */

.aa-dots {
  display: flex;
  gap: 13px;
  justify-content: center;
  margin: 18px 0 14px;
}

.aa-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  border: 1.2px solid #fff;
  transition: background 0.18s var(--ease);
}

.aa-dot.filled {
  background: #fff;
}

.aa-keypad {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  /* Pins the pad to the bottom of the screen, the way iOS does. */
  margin-top: auto;
  gap: 9px 12px;
  justify-items: center;
}

.aa-key {
  position: relative;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: #ffffff26;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-sans);
  font-size: 19px;
  line-height: 1;
  user-select: none;
}

.aa-key.blank {
  background: transparent;
}

.aa-key.wide {
  background: transparent;
  font-size: 10.5px;
}

/* The key being asked for. Brass because it is the one action available. */
.aa-key.active {
  background: var(--brass);
  color: #14100a;
  font-weight: 600;
}

/* The pulse around that key. Built at runtime by the hero's animation, and
   by §04's short step-2 replay, which reuses this same ring rather than
   inventing a second one. */
.aa-key-ring {
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  border: 1.5px solid var(--brass);
  animation: key-pulse 1.1s var(--ease) infinite;
  pointer-events: none;
}

@keyframes key-pulse {
  0% {
    transform: scale(1);
    opacity: 0.9;
  }
  70%,
  100% {
    transform: scale(1.22);
    opacity: 0;
  }
}

/* --- the typing beats ------------------------------------------------------
   Apple's own passcode screen, at hero size: this phone is 184px wide, so the
   shared dots and keys above are scaled down to fit it. */

.aa-pass {
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: 34px 14px 12px;
  background: #000;
  color: #fff;
  font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', system-ui, sans-serif;
}

.aa-lock {
  display: block;
  color: var(--ios-blue);
  margin-bottom: 10px;
}

.aa-title {
  font-family: inherit;
  font-size: 15px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
  margin: 0 0 5px;
}

.aa-sub {
  font-size: 10.5px;
  line-height: 1.35;
  color: #ebebf599;
}

/* Beat 1b — the transformation, and the only staggered animation on the page.
   It earns the exception by being the entire promise: the badges go first (the
   noise stops), then the apps you didn't keep dissolve one at a time rather
   than all at once, so it reads as something being taken away rather than a
   cross-fade. --i on each tile is its place in the queue. */

.ios-app.badge::after {
  transition: opacity 0.3s var(--ease);
}

.scene-home.is-leaving .ios-app.badge::after {
  opacity: 0;
}

.ios-app {
  transition: opacity 0.3s var(--ease), transform 0.3s var(--ease);
}

.scene-home.is-leaving .ios-app {
  opacity: 0;
  transform: scale(0.62);
  transition-delay: calc(0.16s + var(--i, 0) * 21ms);
}

/* The dock is a translucent pill behind the last four tiles; without this it
   outlives them and hangs on an empty screen. It goes once they have. */
.ios-dock {
  transition: opacity 0.3s var(--ease);
}

.scene-home.is-leaving .ios-dock {
  opacity: 0;
  transition-delay: 0.68s;
}

/* --- what sits under the frame --------------------------------------------
   Fixed minimum height so the layout never jumps vertically as the caption's
   text length changes between beats. (.hero-device carries the fix for
   sideways jumping — see its comment above.) */

.stage-foot {
  margin-top: 20px;
  min-height: 44px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 9px;
  text-align: center;
}

.mono {
  font-family: var(--font-mono);
  letter-spacing: 0.04em;
}

.stage-caption {
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--text-dim);
  max-width: 21rem;
  /* Only the two scene-change swaps (cluttered <-> locked) use this — it
     lets the caption settle alongside the phone's own 1.4s crossfade
     instead of snapping ahead of it. The per-second countdown ticks update
     with a plain instant swap, no fade: a real clock's digits don't fade
     between seconds, and doing it here read as a blink on every tick. */
  transition: opacity 0.4s var(--ease);
}

.stage-caption.is-fading {
  opacity: 0;
}

/* The locked beat's caption: a lock glyph and the countdown digits in one
   small badge, so "can't get out" and "not forever" read as a single glance
   rather than a sentence you have to parse. */
.stage-caption.is-locked {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--brass);
  background: rgba(201, 168, 106, 0.08);
  border: 1px solid var(--brass-dim);
  border-radius: 999px;
  padding: 6px 16px 6px 13px;
  font-family: var(--font-mono);
  letter-spacing: 0.02em;
}

.stage-lock-icon {
  flex: none;
  color: var(--brass);
}

/* The arc as text. Visually hidden while the animation can speak for itself,
   but always in the accessibility tree — and laid out for real when there is
   no JavaScript to run the sequence. */
.stage-steps {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Scoped to #stage, and it matters: the hero is the only place where a scene
   is chosen at runtime. §04's row 02 draws the same .scene classes but
   authors its one frame in the markup, so an unscoped rule here would blank a
   picture that has no script to bring it back.

   No separate "which scene stays visible" override is needed here — the
   markup already authors is-on directly on .scene-aa, so hiding every .scene
   by default and never re-showing one under .no-js leaves that frame as the
   one exception, same as it would look with JS disabled entirely. */
.no-js #stage .scene {
  opacity: 0;
  visibility: hidden;
}

.no-js #stage .scene-aa {
  opacity: 1;
  visibility: visible;
}

.no-js .stage-foot {
  display: none;
}

.no-js .stage-steps {
  position: static;
  width: auto;
  height: auto;
  margin: 24px 0 0;
  padding: 0 0 0 20px;
  overflow: visible;
  clip: auto;
  clip-path: none;
  white-space: normal;
  max-width: 21rem;
  font-size: 14px;
  line-height: 1.55;
  color: var(--text-dim);
}

.no-js .stage-steps li {
  margin-bottom: 8px;
}

/* Assistive Access home grid — the after-state, and now the beat the whole
   animation is built to arrive at. Large tiles, large labels,
   nothing else reachable. iOS system colours are confined to this mock. */
.aa-home {
  height: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-auto-rows: 1fr;
  gap: 9px;
  padding: 42px 11px 18px;
  font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', system-ui, sans-serif;
}

.aa-tile {
  background: #1c1c1e;
  border-radius: 14px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 8px;
}

.aa-icon {
  color: var(--tint);
  display: flex;
}

.aa-icon svg {
  width: 26px;
  height: 26px;
}

.aa-label {
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

/* --- the Select Apps screen --------------------------------------------------
   Apple's real "Select Apps" screen (src/screens/setup/phoneSteps.tsx's
   GUIDE[3], src/ios/setupPlates.tsx's WzSelectApps), authored once at the
   phone's native 202×438 like .aa-pass and .aa-home above, so it inherits
   the same --step-scale zoom used in §04 for free. It has one caller
   (row 01's mock in §04) — there is no hero twin to keep in step. */

.aa-select {
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: 34px 12px 12px;
  background: #000;
  color: #fff;
  font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', system-ui, sans-serif;
}

.aa-select-list {
  margin-top: 8px;
}

/* 40px rows ran the list past the bottom of the 202×438 screen, pushing the
   Continue pill below the visible area — .step-phone-screen's overflow:
   hidden was clipping it rather than the screen actually being too short. */
.aa-select-row {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 36px;
  border-bottom: 1px solid #ffffff1f;
}

.aa-select-row:last-child {
  border-bottom: 0;
}

.aa-select-icon {
  flex: none;
  width: 18px;
  height: 18px;
  color: var(--tint);
  display: flex;
}

.aa-select-icon svg {
  width: 18px;
  height: 18px;
}

.aa-select-name {
  flex: 1;
  min-width: 0;
  font-size: 13px;
  font-weight: 500;
}

.aa-select-mark {
  flex: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  line-height: 1;
  border: 1.4px solid #30d158;
  color: #30d158;
}

/* Checked. Filled solid rather than outlined — the one visual difference
   between "kept" and "everything else", on a row whose whole claim is that
   the difference is real. */
.aa-select-mark.is-on {
  background: #30d158;
  border-color: #30d158;
  color: #fff;
}

.aa-select-foot {
  margin-top: auto;
  padding-top: 10px;
}

.aa-select-more {
  margin: 0 0 10px;
  font-size: 10px;
  color: #ebebf599;
}

.aa-select-continue {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 30px;
  border-radius: 15px;
  background: var(--ios-blue);
  color: #fff;
  font-size: 12px;
  font-weight: 600;
}

/* --- responsive -------------------------------------------------------------
   The stage is a fixed 450px canvas now that the browser sits beside the
   phone, so the two-column hero runs out of room well before the rest of the
   page does. It stacks at 1040px; everything else still turns at 860px.
   Below that the stage stops re-laying out and simply scales. */

@media (max-width: 1040px) {
  /* minmax(0, 1fr), not a bare 1fr: bare 1fr means minmax(auto, 1fr), whose
     automatic minimum is the item's min-content width — .stage-frame's explicit
     450px * var(--s). That floor-locks the column to the mock and stops it
     shrinking. .step already does this correctly further down. */
  .hero-grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 56px;
    justify-items: start;
  }

  .hero-device {
    align-self: center;
    margin-inline: auto;
  }
}

/* Below this, .nav-menu (nav links + Sign in + CTA) collapses into the
   .nav-toggle dropdown instead of rendering inline. */
@media (max-width: 860px) {
  .nav-menu {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    gap: 18px;
    padding: 20px var(--gutter) 24px;
    background: #0a0b0dfa;
    border-bottom: 1px solid var(--line);
  }

  .nav-menu.is-open {
    display: flex;
  }

  .nav-links {
    flex-direction: column;
    gap: 16px;
    margin-left: 0;
  }

  .nav-auth {
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
    margin-left: 0;
  }

  .nav-toggle {
    display: flex;
  }

  .nav {
    position: relative;
    z-index: 20;
  }

  /* Without JS the toggle can't open anything, so .no-js renders the menu
     open and static instead of leaving it stuck behind a dead button. */
  .no-js .nav-menu {
    display: flex;
    position: static;
    flex-basis: 100%;
    background: none;
    border-bottom: 0;
    padding: 4px 0 0;
  }

  .no-js .nav-toggle {
    display: none;
  }
}

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

  .hero {
    padding: 56px 0 72px;
  }

  .btn-lg {
    width: 100%;
    justify-content: center;
    padding: 16px 20px;
    font-size: 16px;
  }

  /* The label wraps to two lines at this width; balance it so the arrow
     doesn't end up beside a long line and a short one. */
  .btn-lg .btn-label {
    text-wrap: balance;
    text-align: center;
  }

  /* The phone and its contents are inside .stage-scene, which scales as a
     unit — nothing in here needs resizing by hand any more. */
}

/* --- §03 the gap ------------------------------------------------------------
   The ladder is a fact sheet, not a pricing table: hairline rules, square
   corners, no fills except the one step of ground that gives our row its
   standing. Brass appears exactly once, as the hairline capping that row — it
   is a marker, not a highlight.

   The argument is carried by one column, not by the copy. The cost cells on
   the four alternatives are monospace and dim, so they read down the page as
   four measurements; ours is neither, so it breaks the run. That break is the
   section. Everything else is quiet enough to let it happen.

   Nothing in this section animates. */

.gap {
  border-top: 1px solid var(--line);
  padding: 96px 0 104px;
}

.gap-title {
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: clamp(2rem, 4.2vw, 2.75rem);
  line-height: 1.14;
  letter-spacing: -0.015em;
  margin: 0 0 28px;
}

/* The hook — the one line a reader is likely to recognise as their own, so it
   gets the serif and a size over body copy. Rank comes from size, never from a
   fainter grey. */
.gap-lede {
  max-width: 36rem;
  font-family: var(--font-serif);
  font-size: clamp(1.2rem, 2.6vw, 1.4rem);
  line-height: 1.45;
  color: var(--text-dim);
}

.gap-lede strong {
  color: var(--text);
  font-weight: 600;
}

/* --- the exit ladder --------------------------------------------------------
   No scroll container, no width floor, no "scroll sideways" hint. The cells
   are short phrases rather than sentences, so the sheet fits a phone — which
   is the whole point, because the row that wins the argument used to be the
   one off the right edge of the screen. */

.exits {
  width: 100%;
  margin-top: 40px;
  border-collapse: collapse;
  text-align: left;
  font-size: 15px;
}

.exits th,
.exits td {
  padding: 15px 20px;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
  font-weight: 400;
}

/* The row-header column runs to the gutter, so the sheet starts flush with the
   prose above it. */
.exits th:first-child,
.exits td:first-child {
  padding-left: 0;
}

/* A transparent top border on every column header keeps the labels on one
   baseline once the row below takes a brass rule. */
.exits thead th,
.exits thead td {
  padding: 12px 20px 13px;
  border-top: 1px solid transparent;
  border-bottom: 1px solid var(--line-strong);
  font-family: var(--font-sans);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.exits tbody th {
  width: 34%;
  color: var(--text);
  font-weight: 600;
}

.exits tbody td {
  color: var(--text-dim);
}

/* The Reddit point — App Store blockers inherit Screen Time's door — as a
   second line inside its row rather than a paragraph of its own. */
.exit-sub {
  display: block;
  margin-top: 3px;
  font-size: 13px;
  font-weight: 400;
  line-height: 1.35;
  color: var(--text-faint);
}

/* The column that is the argument. Four measurements in the mono face, dim,
   stacked — the reader compares them without being asked to. */
.exit-cost {
  width: 26%;
  font-family: var(--font-mono);
}

/* Our row: the ground lifts one step and a brass hairline caps it. That is
   the entire treatment — no border box, no rounded corner, no badge. It
   should read as the row being pointed at, not sold; the weight comes from
   the page's own accent color, not a new shape.

   The rule sits on the cells, not the <tr>: with border-collapse a row-level
   border loses to the cell borders it overlaps. */
.exits .exit-ours th,
.exits .exit-ours td {
  padding-top: 19px;
  padding-bottom: 19px;
  background: var(--bg-raised);
  border-top: 2px solid var(--brass);
}

.exits .exit-ours th {
  color: var(--brass);
}

/* Deliberately not monospace, and deliberately not dim. Every other cell in
   this column is a measurement; this one refuses to be, and on a page where
   digits are the material that absence is the loudest thing in the section. */
.exits .exit-ours .exit-cost {
  font-family: var(--font-sans);
  color: var(--brass);
  font-weight: 600;
}

.gap-after {
  max-width: 36rem;
  margin-top: 32px;
  color: var(--text-dim);
  line-height: 1.62;
}

.gap-after strong {
  color: var(--text);
  font-weight: 600;
}

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

/* --- responsive -------------------------------------------------------------
   Same breakpoints as §01/§02. */

@media (max-width: 860px) {
  .gap {
    padding: 72px 0 84px;
  }

  .exits th,
  .exits td {
    padding: 14px 14px;
  }

  .exits thead th,
  .exits thead td {
    padding: 12px 14px 13px;
  }
}

/* Below 560px the three columns stop being columns. Each row becomes two
   lines: the method and its price on the first, the way out underneath. The
   cost column survives as a right-aligned edge, which is non-negotiable —
   reading those five prices in a stack is the entire argument, and a phone is
   where most of this page is read. */
@media (max-width: 560px) {
  .gap {
    padding: 60px 0 68px;
  }

  .exits {
    margin-top: 28px;
    font-size: 14.5px;
  }

  .exits thead {
    display: none;
  }

  .exits tbody,
  .exits tr {
    display: block;
  }

  .exits tr {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: baseline;
    column-gap: 16px;
    padding: 14px 0;
    border-bottom: 1px solid var(--line);
  }

  .exits th,
  .exits td {
    display: block;
    padding: 0;
    border: 0;
  }

  /* Every cell is placed explicitly. Auto-placement can't produce this layout:
     .exit-how spans both columns, so anything flowing after it is pushed to a
     third row — which drops the price onto a line of its own and destroys the
     column that carries the argument. */
  .exits tbody th {
    grid-column: 1;
    grid-row: 1;
    width: auto;
  }

  .exit-cost {
    grid-column: 2;
    grid-row: 1;
    width: auto;
    text-align: right;
  }

  .exit-how {
    grid-column: 1 / -1;
    grid-row: 2;
    margin-top: 4px;
    font-size: 14px;
  }

  /* The ground and the brass rule move from the cells to the row, since the
     cells no longer have edges of their own to carry them. */
  .exits .exit-ours th,
  .exits .exit-ours td {
    padding: 0;
    background: none;
    border-top: 0;
  }

  .exits .exit-ours {
    margin-top: 2px;
    padding: 16px 14px;
    background: var(--bg-raised);
    border-top: 2px solid var(--brass);
  }

  /* The only row whose price is a phrase rather than a measurement, so it is
     the only one that can crowd the name beside it. Cap the price and let it
     wrap; the name must not, because "Screen / Fasting" split across two lines
     reads as a layout accident on the row that closes the argument. */
  .exits .exit-ours th {
    white-space: nowrap;
  }

  .exits .exit-ours .exit-cost {
    max-width: 10.5em;
  }

  .gap-after {
    margin-top: 28px;
  }
}

/* --- §04 how it works ------------------------------------------------------
   Three hairline rows: copy on the left, one picture on the right. No boxes.

   This was the one boxed section on the page — raised ground, a border on four
   sides, and a 1fr/1.4fr/1fr grid stretched to fit a mock rather than to weight
   content. Every other section argues in hairlines and space (§03's exits
   sheet, §05's two columns, §06's FAQ list, §07's length picker), and the old
   defence of the cards — that hairlines would read as one continuous strip
   rather than three units — is contradicted by all three. Rows also hand
   --bg-raised back to §03, where as page furniture it means "this is the row
   being pointed at" and should appear exactly once.

   Rows do not have to end level, which removes the machinery the cards needed:
   no fixed media height, no pair of scale variables tuned so two
   differently-shaped mocks land on one baseline, and no strip of empty space
   reserved in every card for a Replay button only one of them ever had.

   One --step-scale drives every mock here. Row 01's phone and the phone inside
   row 02's two-device canvas are the same object and now the same size; they
   used to differ by 20px, which read as a drawing error rather than a decision.
   Both are drawn at native size and scaled with `zoom` rather than
   `transform: scale()` — scale rasterizes at native size and then shrinks the
   bitmap, which is what was blurring the type inside them.

   All three pictures are stills. Row 02 used to play a trimmed copy of the
   hero's own opening sequence when scrolled into view, which made it the only
   moving thing below the hero and spent that exception on a beat the hero had
   already shown; it holds the first frame instead. */

.how {
  border-top: 1px solid var(--line);
  padding: 88px 0 96px;

  /* Every mock in this section, at one size — and on desktop that size is the
     one they were drawn at, which is the rule .stage already follows in §02
     (--s: 1 until the viewport can no longer hold 450px).

     §04 used to scale on desktop by choice, and unequally: 0.95 for row 01's
     phone, 0.85 for row 02's canvas, and no scale at all for row 03's panel,
     which a comment exempted on the grounds that scaled type goes blurry.
     That was true of transform: scale(), which rasterizes at native size and
     shrinks the bitmap; it is not true of zoom, which re-lays-out. So the
     exemption bought nothing and cost the section its type scale: .b-eyebrow
     rendered at 7.9px in row 02 and 10.5px in row 03, one row apart, in the
     same browser window. One variable, applied to all three, and 1 on
     desktop. */
  --step-scale: var(--mock-fit);

  /* The widest mock at full size: row 02's two-device canvas. Row 03's panel
     is 400px and row 01's phone 202px, both pinned to the same right edge. */
  --step-media-w: 450px;
}

/* The sheet's h2/h3 rule already supplies the serif face, the weight and the
   zeroed margin; only size, leading and the tighter tracking a display size
   wants are set here, scoped so no other section is affected. */
.how h2 {
  font-size: clamp(1.85rem, 3.6vw, 2.4rem);
  line-height: 1.16;
  letter-spacing: -0.015em;
  text-wrap: balance;
  margin-bottom: 20px;
}

/* Matched to .pricing-head, which sits above the same eyebrow/h2/standfirst
   stack. It was 30px here, so §04's head sat tighter to its content than the
   identically-built section two below it. */
.how-head {
  margin-bottom: 46px;
}

/* The container carries the opening rule and each row closes itself — the same
   hairline pattern as .faq-list / .faq-item in §06. */
.steps {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--line);
}

/* Vertical padding only, so the copy starts flush with the section's left edge
   the way .exits th:first-child does in §03. */
.step {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--step-media-w);
  column-gap: 56px;
  align-items: center;
  padding: 40px 0;
  border-bottom: 1px solid var(--line);
}

/* The same measure .hero-copy keeps. A full-width row would otherwise run
   15px type to eighty-odd characters a line. */
.step-copy {
  max-width: 34rem;
}

/* Monospace, not brass: brass is reserved for actions and decisions, and an
   index is neither. Rank comes from typeface, not colour — --text-faint is
   4.0:1 on this ground and fails AA for text, per the note on .micro. */
.step-n {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.08em;
  color: var(--text-dim);
  margin-bottom: 12px;
}

/* 1.12rem, the same as .faq-q — the nearest thing to it on the page, and the
   two used to sit 0.3px apart for no reason anyone could name. */
.step-title {
  font-size: 1.12rem;
  line-height: 1.3;
  text-wrap: balance;
  margin-bottom: 10px;
}

/* 1rem, matching .faq-a. Both are explanatory prose in a hairline row, so they
   are the same rank and should be the same size. 15px was set for a narrow
   card column; in a full-width row at a 34rem measure it read as a caption
   sitting next to §03's 17px prose. */
.step-text {
  font-size: 1.05rem;
  line-height: 1.6;
  color: var(--text-dim);
}

/* The exact Settings location, as a quiet reference line rather than a
   clause in the sentence above — a path is something you scan for, not
   read as part of the pitch. Icon follows .aa-select-icon's grammar: a bare
   coloured line glyph, no badge shape. */
.step-path {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 14px;
  font-size: 13px;
  color: var(--text-dim);
}

.step-path-icon {
  flex: none;
  width: 15px;
  height: 15px;
  color: #8e8e93;
  display: flex;
}

.step-path-icon svg {
  width: 15px;
  height: 15px;
}

/* No height and no baseline to hold: rows end where their content ends.

   Pinned to the row's right edge, not centred. The three pictures are three
   different widths, so centring them lines up their middles and nothing else;
   pinning them gives the section one firm right margin against the hairlines,
   which run the full width and want both ends acknowledged. It is the same
   left-label/right-figure idiom as .plan-spec in §05 and the exits rows in
   §03 below 560px. */
.step-media {
  display: grid;
  place-items: center end;
  min-width: 0;
}

/* `zoom` shrinks the layout box along with what you see, so a phone drawn at
   the hero's exact 202×438 occupies its scaled size in the row and the mock's
   internals — .aa-select, .aa-pass, .aa-home — need no second set of numbers.
   The frame is the box that reserves it. */
.step-phone-frame {
  width: calc(202px * var(--step-scale));
  height: calc(438px * var(--step-scale));
}

.step-phone {
  /* .phone-notch, borrowed from §02, hangs off this. */
  position: relative;
  width: 202px;
  height: 438px;
  background: #000;
  border-radius: 34px;
  border: 1px solid var(--line-strong);
  padding: 8px;
  /* A seat, not a spotlight. */
  box-shadow: inset 0 0 0 3px #0e1013;
  zoom: var(--step-scale);
}

.step-phone-screen {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 27px;
  overflow: hidden;
  background: #000;
}

/* --- row 02's two-device mock ----------------------------------------------
   The hero's stage, reused: the same .browser/.bscene/.phone/.scene classes it
   already draws, unscoped in this file and so already safe to reuse wherever
   those class names appear again. The only new things are this frame/scene
   wrapper and the short beat sequence §04's JS steps it through on scroll
   into view. It runs on --step-scale, not a variable of its own, which is
   what makes its phone and row 01's the same size. */

.step-duo-frame {
  width: calc(450px * var(--step-scale));
  height: calc(490px * var(--step-scale));
}

.step-duo-scene {
  position: relative;
  width: 450px;
  height: 490px;
  zoom: var(--step-scale);
}

/* Row 03 is a browser, not a phone: the code arrives on the other device, and
   the odd one out says the two-device requirement one more time for free. It
   is drawn at the hero browser's own 400px, so it needs none of the
   hand-shrunk chrome the narrow card column used to force on it — and it
   rides the same --step-scale as its neighbours, through the same frame/zoom
   pairing, so .b-eyebrow and .b-note are one size across the section. */
.step-panel-frame {
  width: calc(400px * var(--step-scale));
}

.step-panel {
  width: 400px;
  background: var(--bg);
  border: 1px solid var(--line-strong);
  border-radius: 12px;
  overflow: hidden;
  zoom: var(--step-scale);
}

.step-panel-body {
  padding: 24px 18px 26px;
}

/* The one place on the page a version number appears. */
.how-platform {
  margin-top: 26px;
}

/* --- responsive -------------------------------------------------------------
   Two moves, kept apart on purpose: where the row stops being two columns, and
   where the mocks stop fitting at full size. They are not the same width.

   The row stacks at 1040 — the same breakpoint the hero stacks on, and for the
   same reason: a 450px picture beside copy runs the copy under about forty
   characters a line well before the rest of the page is in trouble.

   The scale ladder below is the hero's own — .stage scales at 530 / 460 / 400
   for a canvas that is also 450px wide, so §04's mock and §02's shrink in
   lockstep and the page has one ladder for one object rather than two. Between
   1040 and 531 nothing scales at all: stacked, a full-width row holds 450px
   down to a 490px viewport. */

@media (max-width: 1040px) {
  .how {
    padding: 72px 0 80px;
  }

  .how-head {
    margin-bottom: 38px;
  }

  .step {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 28px;
    padding: 36px 0;
  }

  /* One column, so there is no second edge to pin against: the picture centres
     under the copy, the same move .hero-device makes when the hero stacks. */
  .step-media {
    place-items: center;
  }
}

@media (max-width: 560px) {
  .how {
    padding: 56px 0 64px;
  }

  .step {
    row-gap: 24px;
    padding: 32px 0;
  }

  .step-title {
    font-size: 1.05rem;
  }
}

/* No --step-scale ladder here any more. It was three fixed rungs (0.86 / 0.74 /
   0.66) that ran out at 400px, so anything narrower than ~337px overflowed
   unconditionally and 375px cleared by 2px. Both mocks now take --mock-fit from
   :root, which fits the canvas to the measured width at any size. */

/* --- §05 pricing -----------------------------------------------------------
   Two columns split by a single vertical hairline — no cards, no rounded boxes,
   no badge. Prices and spec values are monospace: they're figures, and figures
   on this page look like input rather than marketing.

   The columns are a subgrid so the price block, the spec rows and the closing
   line sit on the same lines across both plans. Where subgrid is unavailable
   the declaration is simply dropped and each column stacks at its own height,
   which is a degradation in alignment only. */

.pricing {
  border-top: 1px solid var(--line);
  padding: 88px 0 96px;
}

/* The sheet's h2/h3 rule already supplies the serif face, the weight and the
   zeroed margin; only size, leading and the tighter tracking a display size
   wants are set here, scoped so no other section is affected. */
.pricing h2 {
  font-size: clamp(1.85rem, 3.6vw, 2.4rem);
  line-height: 1.16;
  letter-spacing: -0.015em;
  margin-bottom: 20px;
}

.pricing-head {
  margin-bottom: 46px;
}

.plans {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: auto auto auto;
  row-gap: 28px;
}

.plan {
  display: grid;
  grid-row: span 3;
  grid-template-rows: subgrid;
  row-gap: 28px;
  min-width: 0;
}

.plan:first-child {
  padding-right: 48px;
}

/* The only divider between the two offers. */
.plan + .plan {
  border-left: 1px solid var(--line);
  padding-left: 48px;
}

.plan-name {
  font-size: 1.25rem;
  margin-bottom: 16px;
}

.plan-price {
  display: flex;
  align-items: baseline;
  gap: 1px;
}

.plan-amount {
  font-family: var(--font-mono);
  font-size: 2.4rem;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--text);
}

.plan-period {
  font-family: var(--font-mono);
  font-size: 1rem;
  color: var(--text-dim);
}

/* The annual price as a fact, not a toggle and not a savings badge. */
.plan-alt {
  font-family: var(--font-mono);
  font-size: 12.5px;
  letter-spacing: 0.05em;
  color: var(--text-dim);
  margin-top: 12px;
}

.plan-specs {
  margin: 0;
  padding: 0;
}

.plan-spec {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  padding: 13px 0;
  border-top: 1px solid var(--line);
}

.plan-spec:last-child {
  border-bottom: 1px solid var(--line);
}

.plan-spec dt {
  color: var(--text-dim);
  font-size: 0.9rem;
}

.plan-spec dd {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.875rem;
  color: var(--text);
  text-align: right;
}

/* Free closes on the button; Pro closes on a sentence. Centring the sentence
   against the button's height is what keeps that asymmetry looking deliberate. */
.plan-tail {
  display: flex;
  align-items: center;
}

.plan-note {
  font-size: 14.5px;
  color: var(--text-dim);
}

/* Microcopy, not a section. The second sentence is load-bearing: without it the
   refund reads as a way to buy your way out of a fast early. */
.refund {
  margin-top: 36px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
}

/* The rule runs the full width of the table above it; the sentence keeps a
   readable measure inside it. */
.refund p {
  max-width: 46rem;
  font-size: 14.5px;
  line-height: 1.62;
  color: var(--text-dim);
}

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

@media (max-width: 860px) {
  .pricing {
    padding: 72px 0 80px;
  }

  .pricing-head {
    margin-bottom: 38px;
  }

  /* Stacked: the vertical hairline becomes a horizontal one. */
  .plans {
    grid-template-columns: 1fr;
    grid-template-rows: none;
  }

  .plan {
    grid-row: auto;
    grid-template-rows: none;
  }

  .plan:first-child {
    padding-right: 0;
  }

  /* margin-top sits on top of the grid's own 28px row gap, so it stays small;
     the rule wants roughly equal air above and below it. */
  .plan + .plan {
    border-left: 0;
    padding-left: 0;
    border-top: 1px solid var(--line);
    margin-top: 12px;
    padding-top: 36px;
  }
}

@media (max-width: 560px) {
  .pricing {
    padding: 56px 0 64px;
  }

  .plan-amount {
    font-size: 2.1rem;
  }

  /* The button goes full-width here, so the tail is no longer a single centred
     row of two unequal things. */
  .plan-tail {
    display: block;
  }
}

/* --- §06 FAQ ---------------------------------------------------------------
   Native <details>/<summary>, no script: the section is fully usable with
   JavaScript off, which is the same promise the rest of the page makes about
   the product. Heading sits in its own column on desktop so the answers keep a
   readable measure instead of running the full 1140px.

   The disclosure marker is drawn in CSS — two 1px brass bars, the vertical one
   collapsing on open. It reuses the page's hairline vocabulary rather than
   introducing an icon set, and it is aria-hidden because the <summary> element
   already announces its own expanded state. */

.faq {
  padding: 96px 0;
}

.faq-grid {
  display: grid;
  grid-template-columns: minmax(0, 18rem) minmax(0, 1fr);
  gap: 72px;
  align-items: start;
}

.faq h2 {
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: clamp(1.75rem, 3.2vw, 2.3rem);
  line-height: 1.16;
  letter-spacing: -0.015em;
  text-wrap: balance;
  margin: 0;
}

/* Hairlines between items, and one closing the list. Never a card. */
.faq-list {
  border-top: 1px solid var(--line);
}

.faq-item {
  border-bottom: 1px solid var(--line);
}

.faq-item > summary {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 28px;
  /* Generous hit area: the whole row, not just the words. */
  padding: 22px 0;
  cursor: pointer;
  list-style: none;
  transition: color 0.15s var(--ease);
}

/* Safari still draws its own triangle without this. */
.faq-item > summary::-webkit-details-marker {
  display: none;
}

.faq-item > summary:hover .faq-q {
  color: var(--brass);
}

.faq-item > summary:focus-visible {
  outline: 2px solid var(--brass);
  outline-offset: 2px;
}

.faq-q {
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: 1.12rem;
  line-height: 1.35;
  letter-spacing: -0.005em;
  color: var(--text);
  transition: color 0.15s var(--ease);
}

.faq-mark {
  position: relative;
  flex: none;
  width: 13px;
  height: 13px;
  /* Optically centred on the first line of the question, not the whole block. */
  margin-top: 0.32em;
}

.faq-mark::before,
.faq-mark::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  background: var(--brass);
}

.faq-mark::before {
  width: 13px;
  height: 1px;
  transform: translate(-50%, -50%);
}

.faq-mark::after {
  width: 1px;
  height: 13px;
  transform: translate(-50%, -50%);
  transition: transform 0.18s var(--ease);
}

.faq-item[open] .faq-mark::after {
  transform: translate(-50%, -50%) scaleY(0);
}

.faq-a {
  padding: 0 0 26px;
  max-width: 40rem;
  color: var(--text-dim);
  font-size: 1rem;
  line-height: 1.65;
}

.faq-a p + p {
  margin-top: 14px;
}

.faq-a a {
  color: var(--text);
  text-underline-offset: 3px;
}

@media (max-width: 860px) {
  .faq {
    padding: 80px 0;
  }

  .faq-grid {
    grid-template-columns: 1fr;
    gap: 40px;
  }
}

@media (max-width: 560px) {
  .faq {
    padding: 64px 0;
  }

  .faq-item > summary {
    gap: 20px;
    padding: 20px 0;
  }

  .faq-q {
    font-size: 1.05rem;
  }
}

/* --- §07 closing + first-fast length picker --------------------------------
   Three cells on hairlines, in the same material as the §03 exits table: mono
   numerals, dim prose, and brass on exactly the thing you can act on. The
   selected cell is the only one at full text strength, so the current choice
   is legible from across the room and from the corner of the eye on the way to
   the button.

   The radios themselves are moved offscreen rather than hidden, so the label
   is the whole target and the platform still supplies focus and arrow keys. */

.close {
  padding: 96px 0 112px;
}

.close h2 {
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: clamp(1.75rem, 3.2vw, 2.3rem);
  line-height: 1.16;
  letter-spacing: -0.015em;
  text-wrap: balance;
  margin: 0 0 40px;
}

/* --- the picker ------------------------------------------------------------
   Same 41rem measure as .close-cta below, so the two hairlines line up rather
   than stepping. */

.lengths {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  max-width: 41rem;
  /* <fieldset> arrives with a border, padding and a min-width that ignores the
     grid; all three have to go before it behaves like a plain box. */
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

/* Without the script the label and href can't follow the selection, so the
   picker would be a control that silently lies. The section still closes on the
   2-hour button it ships with. */
.no-js .lengths {
  display: none;
}

.length {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  padding: 22px 20px 24px;
  cursor: pointer;
  transition: background-color 0.15s var(--ease);
}

.length + .length {
  border-left: 1px solid var(--line);
}

/* Offscreen rather than display:none — the input has to keep its place in the
   tab order and its arrow-key behaviour. */
.length input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.length-h {
  font-size: 1.25rem;
  letter-spacing: -0.02em;
  color: var(--text-dim);
  transition: color 0.15s var(--ease);
}

.length-note {
  font-size: 0.9rem;
  line-height: 1.45;
  color: var(--text-dim);
}

.length:hover .length-h {
  color: var(--text);
}

/* The selected cell: brass rule along the top edge, drawn inside the padding so
   it sits on the fieldset's own hairline instead of beside it. */
.length:has(input:checked)::before {
  content: '';
  position: absolute;
  inset: -1px 0 auto;
  height: 2px;
  background: var(--brass);
}

.length:has(input:checked) .length-h {
  color: var(--text);
}

.length:has(input:focus-visible) {
  outline: 2px solid var(--brass);
  outline-offset: -2px;
}

/* --- the close -------------------------------------------------------------
   Same button, same label as the hero. A second offer here would read as a
   second product. */

/* Same measure as .lengths so the two hairlines line up rather than stepping. */
.close-cta {
  max-width: 41rem;
  margin-top: 64px;
  padding-top: 48px;
  border-top: 1px solid var(--line);
}

.pull {
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: clamp(1.3rem, 2.6vw, 1.7rem);
  line-height: 1.35;
  letter-spacing: -0.01em;
  color: var(--text);
  max-width: 26rem;
  text-wrap: balance;
  margin-bottom: 32px;
}

@media (max-width: 860px) {
  .close {
    padding: 80px 0 96px;
  }
}

@media (max-width: 560px) {
  .close {
    padding: 64px 0 80px;
  }

  .close h2 {
    margin-bottom: 32px;
  }

  /* Stacked: three columns at this width squeeze each note to two words a line
     and turn the row into a wall of hyphens. */
  .lengths {
    grid-template-columns: 1fr;
  }

  .length {
    padding: 18px 0 20px;
  }

  .length + .length {
    border-left: 0;
    border-top: 1px solid var(--line);
  }

  /* The rule reads as a left edge once the cells are rows — a bar across the
     top of a stacked row looks like a section divider instead of a selection. */
  .length:has(input:checked)::before {
    inset: 0 auto 0 -12px;
    width: 2px;
    height: auto;
  }

  .close-cta {
    margin-top: 52px;
    padding-top: 40px;
  }
}

/* --- §13 legal pages --------------------------------------------------------
   Shared skeleton for /terms and /privacy: plain prose, no cards, same
   hairline-and-serif vocabulary as the rest of the site. These are drafts —
   the .legal-draft banner says so out loud rather than quietly shipping
   placeholder text as if it were real. Narrower measure than .wrap's 1140px
   because unbroken paragraph text that wide is hard to read. */

.legal {
  padding: 64px 0 96px;
}

.legal-wrap {
  max-width: 720px;
}

.legal-eyebrow {
  font-size: 13.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 0 0 12px;
}

.legal h1 {
  font-size: clamp(2rem, 4vw, 2.6rem);
  line-height: 1.15;
}

.legal-draft {
  margin-top: 20px;
  padding: 14px 18px;
  border: 1px solid var(--line-strong);
  background: var(--bg-raised);
  color: var(--text-dim);
  font-size: 14.5px;
  line-height: 1.55;
}

.legal-body {
  margin-top: 48px;
}

.legal-body h2 {
  font-size: 1.2rem;
  margin-top: 40px;
}

.legal-body h2:first-child {
  margin-top: 0;
}

.legal-body p {
  margin-top: 12px;
  color: var(--text-dim);
  font-size: 16px;
}

.legal-body p + h2 {
  border-top: 1px solid var(--line);
  padding-top: 40px;
}

/* --- footer ----------------------------------------------------------------
   Hairline top rule, --text-dim throughout, no link farm. The wordmark repeats
   the nav's treatment without touching .wordmark, since the nav's copy is
   sticky and this one is not. */

.site-foot {
  border-top: 1px solid var(--line);
  padding: 40px 0 56px;
}

.site-foot-inner {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 16px 32px;
}

.site-foot-mark {
  font-family: var(--font-serif);
  font-size: 18px;
  letter-spacing: -0.01em;
  color: var(--text);
  text-decoration: none;
  flex: none;
}

.site-foot-links {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 26px;
  font-size: 14.5px;
}

.site-foot-links a {
  color: var(--text-dim);
  text-decoration: none;
  transition: color 0.15s var(--ease);
}

.site-foot-links a:hover {
  color: var(--text);
}

.site-foot-links a:focus-visible {
  outline: 2px solid var(--brass);
  outline-offset: 3px;
}

.site-foot-copy {
  margin-left: auto;
  font-size: 13.5px;
  color: var(--text-dim);
}

@media (max-width: 560px) {
  .site-foot {
    padding: 32px 0 44px;
  }

  .site-foot-inner {
    display: block;
  }

  .site-foot-links {
    margin-top: 18px;
  }

  .site-foot-copy {
    margin-top: 22px;
    margin-left: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  * {
    transition: none !important;
    animation: none !important;
  }
}
