/* ==========================================================================
   Cliick.com redesign prototype — issue #3
   Derived from Figma: Cliick-UX (nodes 878-3893, 908-4101, 909-4340, 1176-5196)
   Type: Poppins only. Colors sampled from the mock frames.
   ========================================================================== */

/* ==========================================================================
   Two layouts: portrait and landscape (#48, #54)
   --------------------------------------------------------------------------
   LANDSCAPE = wider than tall AND at least 520px tall
       @media (orientation: landscape) and (min-height: 520px)
   PORTRAIT  = everything else
       @media not all and (orientation: landscape) and (min-height: 520px)

   Every layout switch — the nav's links or menu button, Home's pinned scenes
   or its stacked version, side-by-side heroes or stacked ones — keys off this
   rule and nothing else. redesign.js mirrors the same query for the scenes
   and the menu. Width breakpoints that remain only resize things on small
   screens; they never change which layout a visitor is in.

   The height minimum is for a phone held sideways: at 390px tall the desktop
   layout would be tiny, so it stays in portrait. An upright iPad and a tall
   narrow window are portrait too.
   ========================================================================== */
:root {
  --font: "Poppins", sans-serif;

  /* ------------------------------------------------------------------
     SCHEME — "gallery" (dark)
     Every colour in the site resolves through this block. A second scheme
     is defined by overriding these values alone; nothing below should
     introduce a new colour literal. Two schemes are planned, visitor
     selectable, so keep it that way.
     ------------------------------------------------------------------ */
  /* The surfaces are near-neutral on purpose. All the warmth in this scheme
     comes from the backdrop light, never from the pigment — bake brown into
     the surfaces themselves and every page turns flat brown-on-brown. Panels
     are translucent so the lit backdrop reads through them. */
  --wall: #16171E;        /* the page itself, behind the backdrop layer */
  --recess: rgba(0, 0, 0, 0.34);            /* tracks, backing panels */
  --surface: rgba(234, 240, 255, 0.055);    /* cards, chips, inputs, rows */
  --surface-2: rgba(234, 240, 255, 0.105);  /* hover, raised knobs */
  --line: rgba(226, 234, 255, 0.14);        /* borders on dark */

  /* Interactive objects — cards, rows, controls. These are NOT the room.
     Surfaces above are environment: translucent, made of the same light.
     A control has to read as a thing placed in the room, so it is near
     opaque (it occludes the backdrop), catches the light on its top lip,
     and casts a real shadow. Keep that distinction in any second scheme:
     if controls are made of the same stuff as the wall, the page reads as
     shelves with no bartender. */
  --panel: rgba(16, 18, 26, 0.80);
  --panel-hover: rgba(24, 27, 38, 0.88);
  --panel-edge: rgba(226, 232, 255, 0.13);
  --panel-lip: rgba(232, 238, 255, 0.20);   /* top edge, lit from above */
  --panel-shadow: 0 24px 52px rgba(0, 0, 0, 0.55), 0 3px 10px rgba(0, 0, 0, 0.38);
  --panel-shadow-sm: 0 10px 24px rgba(0, 0, 0, 0.42), 0 2px 6px rgba(0, 0, 0, 0.30);

  /* A selected control has to read as ON. On a dark scheme the lazy move is
     to make the active segment a slightly lighter dark, which reads as "off
     and more off" rather than as a choice. Selection is lit. */
  /* A tan FILL is a brown block at any size, so filled controls are
     paper-neutral; tan at TEXT weight still reads gold, so --accent stays
     warm and only brightens. That split is why these two do not match. */
  --control-on: #FAF7F1;
  --control-on-ink: #16130E;

  --ink-strong: #F3F2EF;  /* primary copy */
  --ink-muted: #C9C8CC;   /* secondary copy */
  --ink-faint: #9C9BA3;   /* tertiary, eyebrows */
  --ink-on-light: #211D16;/* copy on the one light band */
  --accent: #FBE7BC;      /* links, "learn more" */
  /* Brown is dark orange, so a warm mark goes brown by losing luminance —
     which is exactly what antialiasing does to a hairline. A 1px ring or a
     thin glyph blends toward the dark ground behind it and lands in the mud,
     while the same colour in 600-weight text holds its lightness and reads
     gold. So warmth survives at text weight, not at stroke weight: --accent
     for type, --accent-mark for hairlines, small glyphs and thin bars. */
  --accent-mark: #F6F1E7;

  /* Cool: a warm wash at 10% behind every chip and hairline is what made the
     objects read brown even on a blue page. */
  --glow: 232, 238, 255;  /* the gallery pool, as RGB parts for rgba() */
  --band-alt: rgba(234, 240, 255, 0.035); /* alternating band */
  --band-light: #F2EBDF;  /* the ONE light surface: the beat before the footer */

  /* Legacy names, aliased to the scheme so existing rules follow it. */
  --ink: var(--ink-strong);
  --paper: var(--surface);   /* NOTE: surfaces, not the page — body uses --wall */
  --page-gray: var(--wall);  /* subpage body background */
  --band-gray: var(--band-alt);
  --window-gray: var(--recess); /* phone viewport windows, pill tracks */
  --pill-border: var(--line);

  --radius-card: 22px;
  --radius-window: 30px;
  --radius-pill: 21px;
  --shadow-card: 0 14px 34px rgba(0, 0, 0, 0.42);

  --fs-display: clamp(3.25rem, 6.6vw, 6rem);      /* 96px hero/page titles */
  --fs-h2: clamp(2.25rem, 3.75vw, 3.375rem);      /* 54px section heads */
  --fs-h2-sm: clamp(1.75rem, 3.3vw, 3rem);        /* 48px centered heads */
  --fs-scene: clamp(2.25rem, 4.6vw, 4.2rem);      /* 67px Home's scene heads, hero included (#82) */
  --fs-page-title: clamp(2.5rem, 4.9vw, 4rem);    /* 64px page headlines */
  --fs-body: clamp(1.0625rem, 1.4vw, 1.25rem);    /* 20px body */
  --fs-small: 1rem;                                /* 16px */

  --nav-h: 96px;
  --wrap-pad: clamp(20px, 4.3vw, 62px);
  --phone-w: 403px;
  --phone-h: 869px;
  --window-h: 604px;
}

/* Landscape scales (#55). --u is one pixel of the 1440x900 reference,
   shrunk by whichever of the window's width or height is tighter, and
   never grown past it. Sizes that make up the desktop composition are
   multiples of it, so a short unmaximised window gets the same page,
   smaller, instead of a taller-than-fits one. Not a page transform: that
   blurs text, breaks browser zoom and fights the pinned scenes.

   It is only defined here. Rules that use it write var(--u, 1px), so in
   portrait they fall back to their reference size and the phone layout
   is untouched. Body and small text stop at 15px; headings keep going. */
@media (orientation: landscape) and (min-height: 520px) {
  :root {
    --u: min(1px, calc(100vw / 1440), calc(100vh / 900));
    --fs-display: calc(96 * var(--u));
    --fs-page-title: calc(64 * var(--u));
    --fs-h2: calc(54 * var(--u));
    --fs-h2-sm: calc(48 * var(--u));
    --fs-scene: calc(67 * var(--u));
    --fs-body: max(15px, calc(20 * var(--u)));
    --fs-small: max(15px, calc(16 * var(--u)));
    --nav-h: max(64px, calc(96 * var(--u)));
    --wrap-pad: max(20px, calc(62 * var(--u)));
  }
}
/* The portrait bar is the landscape bar at its floor (#70). It stayed at the
   96px reference with a 34px logo floating in it, so narrowing a window
   across the switch grew the bar 29px and pushed every heading down 48 --
   on the screens with the least room to give. */
@media not all and (orientation: landscape) and (min-height: 520px) {
  :root { --nav-h: 64px; }
}

* { margin: 0; padding: 0; box-sizing: border-box; }

/* Keyboard focus. Nothing suppressed outlines, so the browser default was
   applying — but a default ring is tuned for a generic page, not a dark one
   with its own palette. :where() keeps specificity at zero so any component
   can still override it. --accent resolves per context, so this stays legible
   on the light band as well as the dark. */
:where(a, button, summary, input, [tabindex]):focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
  border-radius: 3px;
}

/* --------------------------------------------------------------------------
   Touch targets
   Links here are set at their text height — nav items came out 23px tall,
   footer links 24px, the scene CTAs 28px. On a touch screen the guidance is
   44px, and the gap is the difference between tapping and aiming. These pad
   the hit area without moving the text: the extra height is centred on the
   label, so layout is unchanged on pointer devices too.
   -------------------------------------------------------------------------- */
@media (hover: none), (pointer: coarse) {
  .nav-links a,
  .footer-bottom a,
  .footer-dl span,
  .fine-print summary,
  .learn-more {
    position: relative;
  }
  .nav-links a::after,
  .footer-bottom a::after,
  .footer-dl span::after,
  .fine-print summary::before,
  .learn-more::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: 44px;
    transform: translateY(-50%);
    /* sits behind the label, so it never covers the arrow glyph */
    z-index: -1;
  }
}

/* Available to the accessibility tree, not to the eye. Used where a region
   needs a heading for the document outline but not a visible one. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  font-family: var(--font);
  font-weight: 400;
  color: var(--ink);
  background: var(--wall);
  -webkit-font-smoothing: antialiased;
}

body.page-gray { background: var(--page-gray); }

/* The subpages take Home's backdrop rather than a paraphrase of it: the same
   hero photograph, unblurred, at full strength. An earlier version blurred a
   copy of it at 26% and the tabs read as a different room. */
body.page-gray::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -2;
  background: url("/images/redesign/hero-bg-sim.svg") center / cover no-repeat;
  pointer-events: none;
}
/* Layer order is the whole game here. On Home the stack is photograph, then
   the pair, then the stage shade on top — the shade is what keeps the left
   side deep. Painting the pair over the shade instead lightens that side and
   the page reads warmer than Home does. A body has two pseudo-elements and
   the photograph needs one, so the shade rides with the pair in a single
   background, above it (first layer paints on top).

   Which means the arrival cannot be element opacity — that would fade the
   shade too. redesign.js folds it into the pair's own alphas, along with the
   0.66 the stage scrim sits at. Zero by default, so nothing shows before the
   script runs. */
body.page-gray::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    linear-gradient(180deg, rgba(0, 0, 0, 0.45) 0%, rgba(0, 0, 0, 0) 18%),
    linear-gradient(90deg, rgba(0, 0, 0, 0.55) 0%, rgba(0, 0, 0, 0.15) 60%),
    radial-gradient(ellipse at 16% var(--pair-cool-y, 46%),
      rgba(var(--pair-cool, 38, 53, 111), var(--pair-cool-a, 0)) 0%,
      rgba(var(--pair-cool, 38, 53, 111), 0) 60%),
    radial-gradient(ellipse at 86% var(--pair-warm-y, 38%),
      rgba(var(--pair-warm, 224, 164, 94), var(--pair-warm-a, 0)) 0%,
      rgba(var(--pair-warm, 224, 164, 94), 0) 58%);
}

img { max-width: 100%; display: block; }
a { color: inherit; }

.wrap {
  /* In a short landscape window the column narrows with --u, so the page
     keeps its proportions rather than going wide and short. */
  max-width: calc(1440 * var(--u, 1px));
  margin-inline: auto;
  padding-inline: var(--wrap-pad);
}

/* --------------------------------------------------------------------------
   Nav (Figma Component 15) — sits over the dark hero photo on every page
   -------------------------------------------------------------------------- */
.nav {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 10;
  height: var(--nav-h);
  display: flex;
  align-items: center;
}
.nav .wrap {
  position: relative; /* the mobile menu panel hangs off this */
  width: 100%;
  display: flex;
  align-items: center;
  gap: 14px;
}
/* Brand lockup. Both marks are inline SVG filled with currentColor, so they
   follow --ink-strong through every context -- and through a second scheme --
   the way the rest of the type does. An <img> could not.

   --wm-cap is the wordmark's CAP height, which is the only metric worth
   setting: the SVG box is taller than the caps because the tittles sit above
   them, so sizing by box height would silently change the letters' size
   whenever the tittle geometry moved. */
.nav { --wm-cap: max(16px, calc(22 * var(--u, 1px))); }
.nav-logo {
  display: block;
  /* The mark reads best at twice the wordmark's cap height. Below ~1.6x it
     goes subordinate; above ~2.4x it towers over the caps.
     2.04 rather than 2: the asset carries a 4-unit bleed on each side so its
     edges do not sit flush against the viewBox (with no bleed, antialiasing
     has nothing to blend into and the curves read as clipped). That bleed is
     2% of the box, so the multiplier carries 2% to keep the drawn bird at the
     ratio actually chosen. */
  height: calc(var(--wm-cap) * 2.04);
  width: auto;
  color: var(--ink-strong);
  flex: none;
}
.nav-wordmark {
  display: flex;
  align-items: center;
  color: var(--ink-strong);
  text-decoration: none;
}
.nav-wordmark svg {
  display: block;
  /* 1.7 = box height / cap height, straight off the viewBox (170 / 100). */
  height: calc(var(--wm-cap) * 1.7);
  width: auto;
}
/* Sit the wordmark on the mark's OPTICAL centre.

   Box-centring drops the letters low, because the box is taller than the caps.
   But cap-band centring -- (0.5 - capmid) = -0.100 -- overcorrects: the
   tittles put ink above the caps, which lifts the wordmark's centre of mass,
   so the name reads a hair high. That is exactly what reviewers reported.

   -0.074 aligns the two alpha-weighted ink centroids instead. Measured, not
   nudged: rasterised at 600px wide, the mark's centroid sits at 0.515 of its
   box and the wordmark's at 0.592 of its own, which left the wordmark 0.99px
   high at a 22px cap. It is a ratio, so it holds at any --wm-cap. */
.nav-wordmark svg { transform: translateY(calc(var(--wm-cap) * 1.7 * -0.074)); }
.nav-links {
  margin-left: auto;
  display: flex;
  gap: clamp(18px, 2.6vw, 38px);
}
.nav-links a {
  color: var(--ink-strong);
  text-decoration: none;
  font-size: max(15px, calc(20 * var(--u, 1px)));
}
.nav-links a:hover,
.nav-links a[aria-current="page"] { text-decoration: underline; text-underline-offset: 6px; }

/* The nav's CTA. Deliberately not a fifth nav link: "Start a Cliick" is a
   verb, and putting it in the list would make it read as another section of
   the site. It is a lit control, the same ON treatment the billing toggle
   uses, so it reads as the one thing on the bar you are meant to press. */
.nav-cta {
  flex: none;
  margin-left: clamp(18px, 2.6vw, 38px);
  padding: 11px 22px;
  border-radius: var(--radius-pill);
  background: var(--control-on);
  color: var(--control-on-ink);
  font-size: 1.05rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  box-shadow: var(--panel-shadow-sm);
  transition: transform 0.18s ease, filter 0.18s ease;
}
.nav-cta:hover { filter: brightness(1.06); transform: translateY(-1px); }

/* The menu button. Absent above the breakpoint, where the four links sit in
   the bar and there is nothing to toggle. */
.nav-toggle {
  display: none;
  place-items: center;
  width: 44px;
  height: 44px;
  /* auto: with the CTA gone (#46) the toggle is the first thing on the
     right, so it takes the push itself. When the CTA returns it sits
     between, and the rule below hands the push back to it. */
  margin-left: auto;
  flex: none;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink-strong);
  cursor: pointer;
}
.nav-cta + .nav-toggle { margin-left: 6px; }
.nav-toggle-bars,
.nav-toggle-bars::before,
.nav-toggle-bars::after {
  content: "";
  display: block;
  width: 22px;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
  transition: transform 0.22s ease, opacity 0.18s ease;
}
/* Opening changes nothing about the bar. It used to take a ground of its own
   while open, which meant the bar changed colour on the way open and back on
   the way closed, on top of everything else moving. The only thing that
   should happen is the page sliding down. */

.nav-toggle-bars { position: relative; }
.nav-toggle-bars::before { position: absolute; top: -7px; }
.nav-toggle-bars::after { position: absolute; top: 7px; }
/* Open, the bars become the close mark — same three strokes, so the control
   reads as one thing changing state rather than two different buttons. */
body.nav-open .nav-toggle-bars { background: transparent; }
body.nav-open .nav-toggle-bars::before { top: 0; transform: rotate(45deg); }
body.nav-open .nav-toggle-bars::after { top: 0; transform: rotate(-45deg); }

/* Example first Cliicks. Named groups rather than an abstraction: the whole
   job of this page is to make someone think of a specific set of people, and
   "Book Club" does that where "a private group" does not. */
.examples {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-content: center;
}
.examples li {
  padding: 12px 20px;
  border-radius: var(--radius-pill);
  background: var(--surface);
  border: 1px solid var(--line);
  font-size: var(--fs-body);
  line-height: 1.2;
}
/* The doorway. The code is not a download button tidied away at the foot of
   the page -- it is how the follow-along starts, so it takes the hero's object
   slot and is the first thing on the page with any weight to it. */
.doorway {
  display: grid;
  justify-items: center;
  gap: 30px;
  padding: 38px 30px;
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: var(--radius-card);
  box-shadow: var(--panel-shadow), inset 0 1px 0 var(--panel-lip);
}
.doorway-qr { margin: 0; display: grid; justify-items: center; gap: 16px; }
.doorway-qr img {
  width: min(240px, 60vw);
  height: auto;
  border-radius: 16px;
  background: #fff;
  padding: 16px;
}
.doorway-qr figcaption {
  font-size: var(--fs-small);
  color: var(--ink-muted);
  text-align: center;
  max-width: 26ch;
}
.doorway-store { display: grid; justify-items: center; gap: 12px; }
.doorway-note { font-size: var(--fs-small); color: var(--ink-faint); }
/* The doorway's row sits in a grid that shrink-wraps it, so it cannot be a
   size container (it would measure itself as zero wide); it keeps its fixed
   height and its old wrap onto two rows when a narrow phone has no room. */
.doorway .store-badges { --badge-h: 44px; justify-content: center; margin: 0; container-type: normal; flex-wrap: wrap; }
.doorway .store-badges img { height: var(--badge-h); }

/* On a phone the code is useless -- a camera cannot read its own screen -- so
   the store becomes the doorway and stops apologising for itself. */
.is-handheld .doorway-qr { display: none; }
.is-handheld .doorway-note { display: none; }
.is-handheld .doorway .store-badges { --badge-h: 52px; }

/* The start flow's numbered steps. Numbering here is not decoration: these
   are a real sequence, and each rung is a completion the reader can actually
   finish before the next one asks anything of them. */
/* The rung marker. A numeral rather than a word: these steps are a real
   sequence -- each one depends on the one before it -- so the figure is
   carrying information, not decoration. Set large and light so it reads as a
   marker in the margin rather than a badge stuck on the heading. */
/* .two-col .copy p is (0,2,1) and was winning this outright, forcing the
   numeral back to body size -- hence the extra class in the selector. */
.step .copy .step-num {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-top: 0;
  margin-bottom: 12px;
  max-width: none;
  color: var(--accent);
  font-size: clamp(1.8rem, 2.4vw, 2.3rem);
  font-weight: 300;
  line-height: 1;
  letter-spacing: -0.02em;
}
.step-num span {
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.step .copy h2 { margin-top: 0; }

/* Declining the caddy. Someone who already knows they want the app should not
   have to scroll past three things they do not need to reach it. */
.page-decline {
  margin-top: 26px;
  font-size: var(--fs-small);
  color: var(--ink-muted);
}
.page-decline a { color: var(--accent); text-underline-offset: 4px; }

/* Help offered before it is asked for -- the difference between a showroom
   and a lot. */
.help .learn-more { margin-top: 26px; display: inline-block; }

/* A follow-along is read with a phone in the other hand, so its instructions
   want a little more room than body copy usually gets. */
.follow .page-lede { max-width: 46ch; }

/* The hero narrates the whole arrival now -- install, sign-in, look around --
   so its paragraphs need to read as a sequence rather than one block. */
.follow .page-lede + .page-lede { margin-top: 16px; }
.step .copy b { font-weight: 600; color: var(--ink-strong); }


/* In the motion experience the nav rides fixed through the whole page and
   switches skins by scene: transparent white-text over the hero photo,
   frosted light bar with dark text everywhere else (body.nav-solid). */
body.stage-motion .nav {
  position: fixed;
  transition: background-color 0.4s ease, box-shadow 0.4s ease;
}
body.stage-motion .nav-wordmark,
body.stage-motion .nav-links a { transition: color 0.4s ease; }
/* Subpages had the nav absolute, so it scrolled off and only came back when
   you reached the literal top of the document — scroll up a little and the
   bar is half off the top edge, which reads as the menu failing to restore.
   Home already rides fixed; the subpages do the same. .page-hero already
   reserves --nav-h, so nothing moves. */
/* Unconditionally fixed. It used to be fixed only under .stage-motion (the
   homepage, 1200px and up) or .page-gray (the subpages), which meant that on
   a phone the nav scrolled away on Home and stayed pinned on every other
   page — measured at 390px scrolled to 1500: Home absolute at y -1500 and
   gone, About fixed at y 0. It also took the nav off a JS-set class, which
   is the mechanism behind the intermittent Safari displacement: a class
   evaluated against an unsettled viewport could leave it absolute. */
.nav {
  position: fixed;
  transition: background-color 0.4s ease, box-shadow 0.4s ease;
}
/* Fixed over content needs a ground once you leave the top. The scrolled skin
   is declared once, with the wall — see "The nav has to follow the wall"
   further down. nav-stuck is set by scroll position on every page;
   nav-solid by the stage's scene on the homepage. They have to name the same
   pane, or the two halves of the site disagree about what the bar is: this
   rule previously carried rgba(20,17,12,.58), a warm-black left over from
   when the subpages were brown, so About scrolled to a brown bar while Home
   scrolled to a cool one. */
/* --------------------------------------------------------------------------
   Home hero
   -------------------------------------------------------------------------- */
/* The nav rides fixed over this, so the hero has to reserve its height the
   way .page-hero already does. Without it the bar sat on the headline at
   every width below the pinned stage's 1200px. */
.hero {
  position: relative;
  padding-top: var(--nav-h);
  min-height: min(866px, 100vh);
  background: #0C0D13;
  overflow: hidden;
  color: var(--ink-strong);
}
.hero-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(0,0,0,0.45) 0%, rgba(0,0,0,0) 18%),
    linear-gradient(90deg, rgba(0,0,0,0.55) 0%, rgba(0,0,0,0.15) 60%);
  z-index: 1;
}
.hero .wrap {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  align-items: center;
  gap: 40px;
  min-height: inherit;
  padding-top: var(--nav-h);
}
/* The hero headline is a sentence ("Imagine if every post…", #82), not a
   three-word slogan: at full display size it stacked six lines deep. It
   runs at the scene size with a wider measure and balanced lines, so every
   scene's head -- hero, stage, stacked -- is one size. */
.hero-title {
  font-size: var(--fs-scene);
  font-weight: 500;
  line-height: 1.08;
  max-width: 18ch;
  text-wrap: balance;
}
/* One caption style under every scene head -- hero, stage, stacked (#82). */
.hero-tagline,
.scene p,
.showcase-copy p {
  margin-top: 28px;
  font-size: var(--fs-body);
  line-height: 1.5;
  max-width: 44ch;
}
/* The pair always shares one row and scales down to fit it, rather than
   stacking (#82). The row is a size container, so 100cqi is its width:
   both badges side by side are 6.375 heights wide (156/52 + 175.5/52), so
   the height is whatever lets that plus the gap fit, capped at --badge-h.
   A size container cannot take its width from its content, so a row whose
   parent shrink-wraps it opts out (see .doorway). */
.store-badges {
  --badge-h: 52px;
  --badge-gap: 20px;
  margin-top: 36px;
  display: flex;
  gap: var(--badge-gap);
  align-items: center;
  flex-wrap: nowrap;
  container-type: inline-size;
}
/* The badge SVGs carry their own width/height, so width: auto resolves to the
   real 156x52 / 175.5x52. The links must not shrink either: a shrunken link
   caps the image's width via max-width:100% while its height stays pinned,
   which is exactly the distortion the intrinsic size just fixed. object-fit
   letterboxes rather than stretches if anything ever does constrain the box. */
.store-badges a { flex: 0 0 auto; }
.store-badges img {
  height: min(var(--badge-h), calc((100cqi - var(--badge-gap)) / 6.375));
  width: auto;
  flex-shrink: 0;
  object-fit: contain;
}


/* --------------------------------------------------------------------------
   Home showcase — stationary phone, copy scrolls past.
   Each gray window clips its own viewport-fixed phone copy (clip-path makes
   the fixed element paint only inside the window), so scrolling windows
   sweep across a phone that never moves. Screens differ per window.
   -------------------------------------------------------------------------- */
.showcase .row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) min(758px, 52vw);
  align-items: center;
  column-gap: clamp(24px, 3vw, 70px);
  padding-block: 74px;
}
.showcase-copy h3 {
  font-size: var(--fs-scene);
  font-weight: 500;
  line-height: 1.08;
  max-width: 18ch;
  text-wrap: balance;
}
.showcase-copy ul {
  margin-top: 20px;
  list-style: none;
}
.showcase-copy li {
  font-size: var(--fs-body);
  line-height: 2.2;
}
.showcase-copy li::before { content: "•  "; }
.learn-more {
  display: inline-block;
  margin-top: 34px;
  font-size: 1.125rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--accent);
  text-decoration: none;
}
.learn-more::after { content: "  ⟶"; }
.learn-more:hover { text-decoration: underline; text-underline-offset: 8px; }

.win {
  position: relative;
  height: var(--window-h);
  background:
    radial-gradient(
      ellipse at 50% 44%,
      rgba(var(--glow), 0.20) 0%,
      rgba(var(--glow), 0.08) 38%,
      rgba(var(--glow), 0) 72%
    ),
    var(--recess);
  clip-path: inset(0 round var(--radius-window));
}

/* Phone frame (app stills for now — swap img for video when the films land) */
.phone {
  width: var(--phone-w);
  height: var(--phone-h);
  background: #0b0b0b;
  border-radius: 62px;
  padding: 13px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
}
.phone-screen {
  width: 100%;
  height: 100%;
  border-radius: 50px;
  overflow: hidden;
  background: #000;
}
.phone-screen img,
.phone-screen video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #000; /* some app screenshots carry alpha; keep crossfades opaque */
}
.phone-blank {
  background: var(--surface-2);
  box-shadow: none;
}
.phone-blank .phone-screen { background: var(--surface-2); }

/* Static copy: shown on small screens / reduced motion / no JS */
.phone--static {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: 61px;
}

/* --------------------------------------------------------------------------
   Pinned scene stage. The .stage-frame pins (sticky) while the .stage-track
   scrolls through ~4.5 viewport-heights. JS maps scroll progress to a scene
   index (data-scene on the frame + is-past/is-active/is-future on scenes);
   everything else — copy enter/exit, screen crossfade, window and photo
   fades — is CSS keyed off those attributes, so all motion shares one clock.
   Enabled by body.stage-motion (JS + wide viewport + motion allowed);
   otherwise .fallback-flow renders instead.
   -------------------------------------------------------------------------- */
.stage-track { display: none; }
body.stage-motion .stage-track {
  display: block;
  height: 460vh;
}
body.stage-motion .fallback-flow { display: none; }

.stage-frame {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
  background: var(--wall);
  /* The phone's height and vertical centre, here rather than on .stage-phone
     so the scene copy can centre on the same line (#82). Formula notes at
     .stage-phone below. */
  --stage-phone-h: min(869px, calc(100vh - var(--nav-h) - 60px), calc(100vw * 0.5167));
  --stage-phone-mid: calc(var(--nav-h) + (100vh - var(--nav-h)) / 2);
}

/* Hero photo backdrop — only for scene 0 */
.stage-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 1;
  transition: opacity 0.6s ease;
}
.stage-shade {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(0,0,0,0.45) 0%, rgba(0,0,0,0) 18%),
    linear-gradient(90deg, rgba(0,0,0,0.55) 0%, rgba(0,0,0,0.15) 60%);
  opacity: 1;
  transition: opacity 0.6s ease;
}
/* The backdrop does NOT fade when the story starts. Fading it toward the
   wall is what drained the colour out and left the photo's amber half
   smeared across the frame — which is the brown. Hold the photograph; the
   scene scrims below do the colouring. */
.stage-frame:not([data-scene="0"]) .stage-shade { opacity: 1; }

/* Gray mock window — fades in when the story leaves the hero */
.stage-window {
  position: absolute;
  top: calc(50vh - var(--window-h) / 2);
  right: max(var(--wrap-pad), calc((100vw - 1440 * var(--u, 1px)) / 2 + 62 * var(--u, 1px)));
  width: min(calc(758 * var(--u, 1px)), 52vw);
  height: var(--window-h);
  border-radius: var(--radius-window);
  background: var(--window-gray);
  opacity: 0;
  transition: opacity 0.6s ease;
}
.stage-frame:not([data-scene="0"]) .stage-window { opacity: 1; }

/* THE phone — anchored dead center of the window column, never moves */
.stage-phone {
  position: absolute;
  top: calc(50vh - var(--window-h) / 2 + 61px);
  right: calc(max(var(--wrap-pad), calc((100vw - 1440 * var(--u, 1px)) / 2 + 62 * var(--u, 1px))) + min(calc(758 * var(--u, 1px)), 52vw) / 2 - var(--phone-w) / 2);
  width: var(--phone-w);
}
.stage-phone .phone-screen { position: relative; }
.stage-phone .phone-screen img {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 0.5s ease;
}
.stage-phone .phone-screen img.active { opacity: 1; }

/* --------------------------------------------------------------------------
   Full-phone hero (trial — revert this block to restore the cropped device)
   The stage phone is 869px tall but sits 61px below the window's top edge, so
   it normally runs off the bottom of the viewport and the device is cut. This
   caps its height to the space actually available below its anchor, so the
   whole phone reads. The top anchor is untouched, so its composition with the
   stage window and the copy column is unchanged.
   Corner radius and bezel are re-derived from the width to keep the device's
   proportions honest at the smaller size.
   -------------------------------------------------------------------------- */
.stage-phone {
  /* The third term is the width limit: height alone let a 1024x768 window
     keep a 612px phone, which ran into "Reclaim your Feed". 0.5167 is the
     reference's 744 / 1440, so a width-bound window gets the reference
     phone, scaled. */
  --phone-h: var(--stage-phone-h); /* min(869px, room under the nav, 744/1440 of the width) */
  --phone-w: calc(var(--phone-h) * 0.46375);
  /* Centred in the space below the nav, overriding the original anchor. That
     anchor put the phone 61px below the stage window's top edge, which framed
     a device meant to overhang the viewport; once the phone fits, it left the
     device bottom-heavy (209px above, 30px below at 900px tall) and sitting
     ~90px lower than the copy column's optical centre. Centring gives equal
     margins and lets the device be larger for the same fit. */
  top: calc(var(--stage-phone-mid) - var(--phone-h) / 2);
}
.stage-phone .phone {
  border-radius: calc(var(--phone-w) * 0.15385);
  padding: calc(var(--phone-w) * 0.03226);
}
.stage-phone .phone-screen { border-radius: calc(var(--phone-w) * 0.12407); }

/* --------------------------------------------------------------------------
   Dark gallery
   Scenes 1-3 previously switched the backdrop off and put a flat #d9d9d9
   rectangle on #ffffff. With no light source in the frame it read as drab,
   and a rectangle at ~15% contrast with no edge, shadow or tonal jump could
   neither blend nor stand on its own.

   The scenes become a gallery wall: warm charcoal, the hero's backdrop
   carried straight through, and the phone lit by an ambient pool rather than
   backed by a box. Photography is the product, and photographs read on dark
   the way art does on a gallery wall.

   Note this needs no colour correction on the backdrop. An earlier pass kept
   the scenes light and had to lift and sepia() the backdrop hard, because it
   is a night image being forced to behave as a pale wash. On a dark wall it
   simply belongs, which is the main argument for this direction.
   -------------------------------------------------------------------------- */

/* The wall. Warm charcoal, not pure black — pure black reads as "screen off". */
.stage-frame { background: var(--wall); }

/* The grey mock window framed the muted wall; over a live photo it is a
   smudge. */
.stage-frame:not([data-scene="0"]) .stage-window { opacity: 0; }
.stage-frame .stage-bg { z-index: -1; }

/* Copy flips to light. Warm off-white rather than #fff, since the wall is warm. */
.stage-frame:not([data-scene="0"]) { color: var(--ink-strong); }
.stage-frame:not([data-scene="0"]) .scene li { color: var(--ink-muted); }
.stage-frame:not([data-scene="0"]) .learn-more { color: var(--accent); }

/* The grey box is replaced by light. A glow has no edge, so it cannot have
   the "neither blends nor stands alone" problem the rectangle had. */
.stage-window { display: none; }

.stage-phone { z-index: 1; }
.stage-phone::before {
  content: "";
  position: absolute;
  z-index: -1;
  left: 50%;
  top: 50%;
  width: 250%;
  height: 124%;
  transform: translate(-50%, -50%);
  opacity: 0;
  transition: opacity 0.6s ease;
  pointer-events: none;
  background: radial-gradient(
    ellipse at 50% 48%,
    rgba(255, 238, 208, 0.62) 0%,
    rgba(255, 230, 188, 0.38) 20%,
    rgba(255, 224, 178, 0.17) 40%,
    rgba(255, 224, 178, 0.05) 58%,
    rgba(255, 224, 178, 0) 74%
  );
}
.stage-frame:not([data-scene="0"]) .stage-phone::before { opacity: 1; }

/* The device casts into darkness, and takes a faint warm rim so its silhouette
   holds — its bezel is near-black and would otherwise melt into the wall. */
.stage-frame:not([data-scene="0"]) .stage-phone .phone {
  box-shadow:
    0 46px 104px rgba(0, 0, 0, 0.62),
    0 10px 30px rgba(0, 0, 0, 0.44),
    0 0 0 1px rgba(255, 230, 188, 0.22);
}

/* EXPERIMENT — the scrolled bar ghosts white rather than dark. A light veil
   lets the blur carry legibility instead of a dark pane doing it by
   brute force. Revert to rgba(10,11,14,.52) with blur(14px) to go back. */
body.nav-solid .nav,
body.nav-stuck .nav {
  background: rgba(255, 255, 255, 0.12);
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.18);
}
/* The site has exactly one light surface, and a white veil dies on it — over
   the latte band the bar and its light type both vanish into cream. So when
   that band is what is under the nav, the type inverts and the button flips
   to a dark fill. The veil itself stays: it is the contents that have to
   change, not the glass. redesign.js sets the class. */
body.nav-on-light .nav-logo,
body.nav-on-light .nav-wordmark,
body.nav-on-light .nav-links a,
body.nav-on-light .nav-toggle,
body.nav-on-light.nav-solid .nav-wordmark,
body.nav-on-light.nav-solid .nav-links a {
  color: var(--ink-on-light);
}
body.nav-on-light .nav-cta {
  background: #16130E;
  color: #FAF7F1;
}
body.nav-on-light.nav-solid .nav,
body.nav-on-light.nav-stuck .nav {
  background: rgba(255, 255, 255, 0.34);
  box-shadow: 0 1px 0 rgba(64, 48, 22, 0.14);
}
body.nav-solid .nav-wordmark,
body.nav-solid .nav-links a { color: #F2ECDE; }

/* The closing band is the one light surface in the scheme — the "back out into
   the light" beat before the black footer. It is deliberately not dark:
   .latte-fluffy relies on mix-blend-mode:multiply to drop its baked-in white
   background, which only works over a light band. Its copy has to invert. */
.band.latte { background: var(--band-light); color: var(--ink-on-light); }
.band.latte .plans { margin-top: 72px; }

/* The footnote under the membership cards: the quiet register the cards
   already use for their own caps, centred under both of them. */
/* The line the page lands on. At body size it read as one more paragraph
   after the pills and got lost against the footer below it; this gives it
   the weight of a closing statement without making it a heading. */
/* Specificity, not order: .section-sub is defined further down the file and
   would otherwise win on font-size. */
.section-sub.promise-closer {
  margin-top: 44px;
  max-width: 26ch;
  font-size: clamp(1.375rem, 2.1vw, 1.875rem);
  font-weight: 500;
  line-height: 1.35;
  color: var(--ink-strong);
}

/* Below ~992px the two cards go one-up, and a note after them becomes a note
   after Premium: "free for you and five others" lands directly under $6/month
   and 250 members, and "want a bigger Cliick?" follows the bigger plan.
   Stacked, it leads instead — which is what it always was, a preamble to the
   pair rather than a footnote to the last card. */
@media not all and (orientation: landscape) and (min-height: 520px) {
  .page-hero-aside { display: flex; flex-direction: column; }
  .page-hero-aside .plans-note { order: -1; margin: 0 auto 26px; }
}

.plans-note {
  /* Clear of the cards' own shadow, and narrower than they are so it reads
     as a footnote to the pair rather than a third column of text. */
  margin: 22px auto 0;
  max-width: 66ch;
  padding-inline: 12px;
  text-align: center;
  text-wrap: balance;
  font-size: var(--fs-small);
  line-height: 1.65;
  color: var(--ink-muted);
}

/* --------------------------------------------------------------------------
   Objects on the light band
   The object and control tokens above assume a dark room: a panel occludes
   the backdrop by being darker, a selected control is lit. The homepage runs
   the same .plan component inside the light band, where every one of those
   relationships inverts — dark cards on cream read as inactive and dreary.
   Re-point the tokens for this context rather than restyling the component,
   so .plan stays a single component. The light gallery exploration, if we
   take it, is this block applied site-wide.
   -------------------------------------------------------------------------- */
.band.latte {
  --panel: #FFFCF6;               /* on light, an object is raised, not sunken */
  --panel-hover: #FFFFFF;
  --panel-edge: rgba(64, 48, 22, 0.16);
  --panel-lip: rgba(255, 255, 255, 0.95);
  --panel-shadow: 0 20px 44px rgba(72, 52, 22, 0.16), 0 3px 9px rgba(72, 52, 22, 0.10);
  --panel-shadow-sm: 0 8px 20px rgba(72, 52, 22, 0.14);

  --ink-strong: var(--ink-on-light);
  --ink-muted: #5B5245;
  --accent: #7A5210;              /* the warm accent has to darken to hold */
  /* On a light ground the mud problem inverts — a hairline loses luminance
     toward cream, not toward black — so marks and type can share a colour. */
  --accent-mark: var(--accent);
  --recess: rgba(64, 48, 22, 0.10);
  --line: rgba(64, 48, 22, 0.18);
  --glow: 122, 86, 30;            /* the tint darkens with everything else */

  --control-on: #211D16;          /* and ON inverts: dark segment, light copy */
  --control-on-ink: #F6EFE0;
}
/* the top-face sheen is light falling on the card, so on a light band it has
   to be white — the dark-room version tints the top edge downward instead */
.band.latte .plan::before {
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.85) 0%,
    rgba(255, 255, 255, 0.30) 30%,
    rgba(255, 255, 255, 0) 60%
  );
}

/* Scenes — copy panels in a reserved left region; enter from below,
   exit upward, direction-aware on reverse scroll */
/* Each scene centres on the phone's centre line (#82). It used to centre
   on the window (top: 50%) while the phone centres in the space under the
   nav, so the copy sat 48px above the phone at 900px tall -- and, under a
   max-height: 860px rule that re-centred it under the nav + 44px, 22px
   below it at 820px. Sharing the phone's line makes both one rule, and
   still keeps short windows' heads clear of the nav. */
.scene {
  position: absolute;
  top: var(--stage-phone-mid);
  left: max(calc(var(--wrap-pad) + 62 * var(--u, 1px)), calc((100vw - 1440 * var(--u, 1px)) / 2 + 124 * var(--u, 1px)));
  width: calc(640 * var(--u, 1px)); /* the hero's column: every scene head is the hero's size (#82) */
  transform: translateY(-50%);
  opacity: 1;
  transition: opacity 0.5s ease, transform 0.5s ease;
  pointer-events: none;
}
.scene.is-active { pointer-events: auto; }
.scene.is-past {
  opacity: 0;
  transform: translateY(calc(-50% - 70px));
}
.scene.is-future {
  opacity: 0;
  transform: translateY(calc(-50% + 70px));
}
.scene h3 {
  font-size: var(--fs-scene);
  font-weight: 500;
  line-height: 1.08;
  max-width: 18ch;
  text-wrap: balance;
}
.scene ul { margin-top: 20px; list-style: none; }
.scene li { font-size: var(--fs-body); line-height: 1.9; }
.scene li::before { content: "•  "; }

/* Scene 0 = the hero copy. It uses the same ink as scenes 1-3: as a literal
   white it was the one headline in the site not lit by the room's lamp, and
   it changed colour at 1200 as the stage handed over to the fallback flow. */
.scene--hero { width: calc(640 * var(--u, 1px)); }

/* The stage in a portrait window 480px and wider (see STAGE in redesign.js):
   the same composition the stacked Home uses there -- copy left, device
   right -- but pinned, so the device stays put and the copy changes, rather
   than every section's phone queueing down the page. The geometry above is
   landscape's (a 758px window column, --u); here the phone is sized from
   the width in the same steps as the stacked Home's, and the copy takes
   what is left. */
@media not all and (orientation: landscape) and (min-height: 520px) {
  @media (min-width: 480px) and (min-height: 520px) {
    .stage-frame {
      --stage-z: 0.6;
      --stage-gap: clamp(18px, 4vw, 40px);
      --stage-phone-h: min(calc(869px * var(--stage-z)), calc(100vh - var(--nav-h) - 60px));
    }
    .stage-phone {
      right: var(--wrap-pad);
    }
    .scene,
    .scene--hero {
      left: var(--wrap-pad);
      width: calc(100vw - 2 * var(--wrap-pad) - 403px * var(--stage-z) - var(--stage-gap));
    }
  }
  @media (min-width: 480px) and (max-width: 720px) {
    .stage-frame { --stage-z: 0.5; }
  }
  @media (min-width: 480px) and (max-width: 600px) {
    .stage-frame { --stage-z: 0.42; }
  }
}

/* --------------------------------------------------------------------------
   Latte band (home) + pricing cards (home & membership)
   -------------------------------------------------------------------------- */
.band { background: var(--band-gray); }
.latte {
  padding: 90px 0 110px;
  text-align: center;
}
.latte-fluffy {
  width: min(340px, 70vw);
  margin-inline: auto;
  mix-blend-mode: multiply; /* the source art has a white background; blend it into the band */
}
.latte h2 {
  font-size: var(--fs-h2-sm);
  font-weight: 500;
  line-height: 1.25;
  margin-top: 8px;
}
.latte .sub,
.section-sub {
  margin: 18px auto 0;
  font-size: var(--fs-body);
  line-height: 1.5;
  max-width: 62ch;
  /* These run two or three lines, which is too short for text-wrap: pretty to
     help — pretty only tunes the last few lines of a longer block. balance
     evens every line instead, so no single word is left trailing. */
  text-wrap: balance;
}

.plans {
  margin-top: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 440px));
  gap: 28px;
  justify-content: center;
  text-align: left;
}
.plan {
  position: relative;
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: var(--radius-card);
  box-shadow: var(--panel-shadow), inset 0 1px 0 var(--panel-lip);
  padding: 40px 42px 48px;
}
/* the room's light falling across the top face of the card */
.plan::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(
    180deg,
    rgba(var(--glow), 0.10) 0%,
    rgba(var(--glow), 0.03) 26%,
    rgba(var(--glow), 0) 55%
  );
}
.plan > * { position: relative; }
.plan h3 {
  font-size: calc(36 * var(--u, 1px));
  font-weight: 500;
}
.plan-price {
  margin-top: 28px;
  font-weight: 500;
  letter-spacing: -0.03em;
}
.plan-price .amount { font-size: calc(48 * var(--u, 1px)); }
.plan-price .term-note {
  display: block;
  margin-top: 4px;
  font-size: var(--fs-small);
  color: var(--ink-muted);
}
.plan-price .term {
  font-size: var(--fs-small);
  font-weight: 400;
  letter-spacing: -0.03em;
}
.plan-note,
.plan-toggle {
  margin-top: 20px;
  border: 1px solid var(--pill-border);
  background: var(--recess);
  border-radius: var(--radius-pill);
  font-size: var(--fs-small);
  line-height: 2.5;
  text-align: center;
}
.plan-note {
  background: rgba(var(--glow), 0.10);
  border-color: rgba(var(--glow), 0.24);
  /* The pill's ground and ring are --glow, which is cool; warm type inside a
     cool ring is the clash, not the warmth itself. It is a quiet statement
     rather than a link, so it takes the mark: still lit, and brighter than
     --ink-muted, without pulling a second temperature into the object. */
  color: var(--accent-mark);
}
.plan-toggle {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  cursor: pointer;
  user-select: none;
}
.plan-toggle .knob {
  position: absolute;
  top: 2px;
  bottom: 2px;
  left: 2px;
  width: calc(50% - 4px);
  background: var(--control-on);
  border-radius: calc(var(--radius-pill) - 3px);
  box-shadow: 0 2px 7px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.55);
  transition: transform 0.25s ease;
}
.plan-toggle[data-cycle="monthly"] .knob { transform: translateX(calc(100% + 4px)); }
.plan-toggle span {
  position: relative;
  z-index: 1;
  /* One line per segment. In a 1024px landscape window the card is ~290px
     wide and "Annual save 25%" broke after "Annual", doubling the toggle's
     height — and the Guest card's pill with it, since the two share a row. */
  white-space: nowrap;
  color: var(--ink-muted);
  transition: color 0.25s ease;
}
/* The saving sits on the control rather than in the selected plan's copy, so
   it is legible from either side of the toggle. Inherits its colour so it
   works both on the lit knob and on the dark track. */
.plan-toggle .save {
  font-size: 0.72em;
  font-weight: 600;
  letter-spacing: 0.02em;
  opacity: 0.72;
  margin-left: 4px;
  white-space: nowrap;
}
.plan-toggle[data-cycle="annual"] span:nth-of-type(1),
.plan-toggle[data-cycle="monthly"] span:nth-of-type(2) {
  color: var(--control-on-ink);
  font-weight: 600;
}
/* Capacity scale. The plans differ by one number that matters — 6 members per
   Cliick against 250 — and it was a bullet among four. The fill is each plan's
   share of the larger cap, so the comparison is to scale rather than decorative. */
.plan-scale {
  margin-top: 14px;
}
.plan-scale-track {
  display: block;
  height: 8px;
  border-radius: 99px;
  background: var(--recess);
  border: 1px solid var(--panel-edge);
  overflow: hidden;
}
.plan-scale-fill {
  display: block;
  width: var(--fill);
  height: 100%;
  border-radius: 99px;
  background: linear-gradient(90deg, rgba(var(--glow), 0.55), var(--accent-mark));
}
.plan-scale--guest { --fill: 2.4%; }
.plan-scale--premium { --fill: 100%; }
/* A warm tip where the bar reaches the cap. Only on the premium bar: the
   gradient is painted across the FILL, not the track, so on the 2.4% guest
   bar the same stop would land as a one-pixel warm edge — a hairline, which
   is the thing --accent-mark exists to keep off. The tip also means
   something here, since guest never arrives at the end. */
.plan-scale--premium .plan-scale-fill {
  background: linear-gradient(
    90deg,
    rgba(var(--glow), 0.55) 0%,
    var(--accent-mark) 58%,
    var(--accent) 100%
  );
}
.plan-scale-label {
  margin-top: 10px;
  font-size: var(--fs-small);
  color: var(--ink-muted);
}
.plan-cap {
  margin-top: 14px;
  font-size: var(--fs-small);
  color: var(--ink-muted);
}
/* BEST VALUE, as the app marks the annual row. Only meaningful while annual is
   the selected cycle, so it hides when the toggle moves to monthly. */
/* The chip sits on its own line under the title rather than trailing it.
   Inline, it wrapped or not depending on the card's width, so the title's
   height changed as you resized -- and on the Membership subgrid that pulled
   the neighbouring card with it.

   Every title reserves the line via the ::after placeholder, whether or not it
   carries a chip, and the chip is laid into that reserved space. So all four
   cards keep one title height: prices share a baseline on the homepage band,
   which is not a subgrid, and toggling the cycle cannot resize anything. */
.best-chip,
.plan h3::after {
  display: block;
  width: fit-content;
  margin-top: 14px;
  /* 0.4em of the card title is 14.4px at the reference; the title scales
     with --u, so the chip is held at 12px rather than following it to 10. */
  font-size: max(12px, 0.4em);
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  white-space: nowrap;
  border-radius: 4px;
  padding: 4px 8px;
}
.plan h3 { position: relative; }
.plan h3::after { content: "Best value"; visibility: hidden; }
.best-chip {
  position: absolute;
  inset: auto auto 0 0;
  color: var(--control-on-ink);
  background: var(--control-on);
}
.plan[data-cycle="monthly"] .best-chip { visibility: hidden; }

.plan-scale-label b {
  color: var(--ink-strong);
  font-weight: 600;
}

/* --------------------------------------------------------------------------
   Subpage hero band
   -------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------
   Page header
   One pattern for every page below Home. Previously a bare <h1> bottom-aligned
   in a fixed 366px band: the space above the title was leftover rather than
   composed, and the title had nothing to hand off to, so the eye fell straight
   into the content below.

   The header is now a composed block — title, lede, and a slot for supporting
   art — with its rhythm set by padding rather than a fixed height, so it grows
   with its content instead of trapping it. Any page added later gets a
   coherent header by using this markup:

     <section class="page-hero">
       <div class="wrap">
         <div class="page-head">
           <h1>Title</h1>
           <p class="page-lede">One line on what the page is for.</p>
         </div>
         <img class="page-hero-art" src="..." alt="..." />   <- optional
       </div>
     </section>
   -------------------------------------------------------------------------- */
.page-hero {
  position: relative;
  padding-top: calc(var(--nav-h) + 62 * var(--u, 1px));
  padding-bottom: calc(64 * var(--u, 1px));
  overflow: hidden;
  color: var(--ink-strong);
}
.page-hero .wrap {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: 48px;
}
.page-head { max-width: min(640px, 62%); }
.page-hero h1,
.about-pinned h1 {
  font-size: var(--fs-page-title);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.01em;
  /* Page headlines are sentences now, and the aside layout gives them a narrow
     column — without balancing, a short final word strands on its own line. */
  text-wrap: balance;
}
/* The page name survives as the eyebrow rather than a billboard: the nav
   already marks the current page, and Home does not announce itself either. */
.page-eyebrow {
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  /* --ink-muted, matching .eyebrow. The
     white it replaces composited to about the same lightness over the header
     scrim, so this is the token swap, not a dimming. */
  color: var(--ink-muted);
  margin-bottom: 18px;
}
.page-kicker {
  margin-top: 16px;
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--ink-strong);
}
.page-lede {
  margin-top: 22px;
  max-width: 48ch;
  font-size: var(--fs-body);
  line-height: 1.55;
  color: var(--ink-muted);
}
/* The header is a darkened region of the page's own lit space, not a band with
   its own backdrop — it previously painted #130e04 plus its own copy of the
   backdrop at a different crop, which left a hard seam. The scrim is masked so
   it fades out at the bottom rather than ending on an edge, and sits under
   .wrap (z-index 2) so it never dims the copy. */
/* The page-hero used to carry its own left-dark scrim. That is the job the
   stage shade in body::after now does one layer down, and two stacked made
   the tall heroes (About, Membership, Start) read darker than the short one
   (FAQ) and darker than Home. Keep one. */
body.page-gray .page-hero h1,
body.page-gray .about-pinned h1 { text-shadow: 0 1px 12px rgba(0, 0, 0, 0.35); }

/* Aside column — the site's spatial grammar.
   The homepage stage puts the argument on the left and the thing itself on the
   right, and holds them there while you scroll. Subpages had abandoned that and
   stacked everything centre, so each page read as a different site. .page-hero
   --aside lets a page keep the grammar: headline and lede left, the subject
   right, composed together rather than sequentially. */
/* Landscape now starts at a 1024px-wide window (#54), where 300px minimums
   for the heading column and for each card no longer fit: two cards needed
   622px beside the heading and 586px was left, so the second card wrapped
   under the first and dragged the heading down the page. The minimums and
   the gap give a little so the pair stays side by side; the rest of the
   composition scales with --u (#55). */
.page-hero--aside .wrap {
  grid-template-columns: minmax(260px, 32%) minmax(0, 1fr);
  align-items: center;
  gap: clamp(28px, 3.6vw, 56px);
}
.page-hero--aside .page-head { max-width: none; }
.page-hero--aside .page-lede { max-width: 38ch; }
.page-hero-aside { min-width: 0; }
/* the cards size to the column they are in rather than a fixed 440 */
.page-hero-aside .plans {
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  /* Six rows: name, price, control, scale, label, caption. Keep this in step
     with the card's child count or the subgrid stops aligning — it has moved
     with the content three times now (7 with feature lists, 6 without, 5 once
     the live-region paragraph went, 6 again with the app's plan captions). */
  grid-template-rows: repeat(6, auto);
  gap: 22px;
}
.page-hero-aside .plan {
  display: grid;
  grid-template-rows: subgrid;
  grid-row: span 6;
  align-content: start;
  /* The card is its own container, so the toggle below can respond to how
     wide the card actually is rather than to the window. */
  container-type: inline-size;
}
/* A narrow card — about 290px in a 1024px landscape window — makes each half
   of the Annual/Monthly toggle about 115px, and "Annual save 25%" is wider
   than that: it ran edge to edge on the knob with "25%" clipped. The label
   tightens its spacing instead; the type stays at the 15px floor. The saving
   is still on the card twice ("$72 a year", "save 3 months"), so "save 25%"
   gives way if tightening is not enough. */
/* Landscape only: stacked in portrait, the cards run the full column and
   match Home's cards at the same size — tightening them there made the same
   control two different sizes on two pages. */
@media (orientation: landscape) and (min-height: 520px) {
  @container (max-width: 330px) {
    .plan-toggle .save { margin-left: 3px; letter-spacing: 0; }
  }
  /* Measured against the card's content box (inside its padding): ~244px at
     1024 wide, where the label is 112px in a 117px knob and fits. It only
     gives way below that. */
  @container (max-width: 225px) {
    .plan-toggle .save { display: none; }
  }
}
/* Tighter side padding only while the cards are squeezed into the split's
   right-hand column. Stacked, they use the site-wide card padding so they
   match the homepage band at every width. */
@media (orientation: landscape) and (min-height: 520px) {
  .page-hero-aside .plan { padding: calc(32 * var(--u)) max(18px, calc(30 * var(--u))) calc(36 * var(--u)); }
}

@media not all and (orientation: landscape) and (min-height: 520px) {
  .page-hero--aside .wrap { grid-template-columns: minmax(0, 1fr); gap: 44px; }
  .page-hero--aside .page-lede { max-width: 48ch; }
  /* Stacked: copy and cards share one measure and one left edge, so the
     column the split establishes survives the breakpoint instead of the copy
     running full width while the cards sit centred inside it. The measure is
     908 = two 440 cards plus the 28 gutter; at the old 900 the band could
     never go two-up, leaving 960-1199 as one card beside an empty half. */
  .page-hero--aside .page-head,
  .page-hero--aside .page-hero-aside { width: min(100%, 908px); margin-inline: 0; }
  /* Stacked, the cards are no longer sizing to the split's narrow column, so
     the 1fr override has nothing left to do but let them balloon (548px in a
     600px viewport). Hand them back to the site-wide card measure and the
     centring the homepage band uses. */
  .page-hero-aside .plans {
    grid-template-columns: repeat(auto-fit, minmax(300px, 440px));
    justify-content: center;
    gap: 28px;
  }
}

/* Optional supporting art. Sized so it can never crowd the title, and dropped
   entirely on narrow viewports rather than shrinking to a stamp. */
.page-hero-art {
  width: min(360px, 32vw);
  height: auto;
  border-radius: var(--radius-card);
  align-self: end;
}

/* A hero with nothing beside the title. The .page-head cap above exists only
   to keep the title clear of .page-hero-art; with no art in the second track
   it just folds a two-word title onto two lines on wide viewports and pushes
   the whole page down. FAQ is the only page here for now. */
.page-hero--solo .page-head { max-width: none; }

@media not all and (orientation: landscape) and (min-height: 520px) {
  .page-hero .wrap { grid-template-columns: minmax(0, 1fr); }
  .page-hero-art { display: none; }
  .page-hero { padding-top: calc(var(--nav-h) + 46px); padding-bottom: 54px; }
}
/* A phone gets less: 43px between the logo and the heading, not 80 -- a
   tenth of the screen before the page says anything. Home's hero takes the
   same value below, so every page's heading starts at the same height. */
@media (max-width: 720px) {
  .page-hero { padding-top: calc(var(--nav-h) + 28px); }
}

/* --------------------------------------------------------------------------
   Generic sections (About & Membership)
   -------------------------------------------------------------------------- */
.section { padding: 90px 0; }
/* The first section carries the header's own bottom padding already;
   without this the two stack into a gap nothing lives in. */
.page-hero + .section { padding-top: 30px; }
/* Same problem one step further down, and it was an oversight rather than a
   decision: two adjacent sections stacked 90 + 90 and opened a 190px void
   where the hero boundary opens 104. Only About currently has this
   adjacency, so nothing else moves. */
.section + .section { padding-top: 24px; }
.section--center { text-align: center; }
.eyebrow {
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
  text-align: center;
}
.section h2 {
  font-size: var(--fs-h2);
  font-weight: 600;
  line-height: 1.3;
  margin-top: 10px;
}
.section--center h2 { margin-inline: auto; max-width: 24ch; }
.section--center .section-sub { max-width: 48ch; }
.section-sub strong { font-weight: 500; }
.section-sub + .section-sub { margin-top: 24px; }

.two-col {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
  gap: clamp(32px, 5vw, 90px);
}
/* The ledger row wants a wider prose column than an even split: the copy
   carries a heading and two paragraphs, the object is one 440 stack. */
.two-col--wide { grid-template-columns: minmax(0, 1fr) minmax(0, 0.82fr); }
/* Object left, prose right -- alternating down the page the way the homepage
   scenes do, so three consecutive rows do not read as a list. */
.two-col--flip { grid-template-columns: minmax(0, 0.82fr) minmax(0, 1fr); }
@media not all and (orientation: landscape) and (min-height: 520px) {
  /* Stacked, copy always leads: a screenshot above the heading is a picture of
     something you have not been told about yet. */
  .two-col--flip .win,
  .two-col--flip .money-flow { order: 2; }
}
/* Narrower column than a full-width section, so the heading needs balancing
   for the same reason the page titles do: without it a short last word
   strands on its own line. */
.two-col h2 { margin-top: 0; text-wrap: balance; }
.two-col .copy p {
  margin-top: 22px;
  font-size: var(--fs-body);
  line-height: 1.5;
  max-width: 46ch;
}

/* The About ledger: what we hold, beside what we have nowhere to put. Two
   panels rather than prose, because the point is that it is a list you can
   check against the schema -- prose invites skimming, a ledger invites
   auditing. The "none" column is the one that matters, so it carries the
   accent rule while the "held" column stays quiet. */
/* .section-sub centres itself, which is right in .section--center and wrong
   anywhere else -- in a left-aligned section it reads as a stray indent under
   a flush heading. Every centred use is inside .section--center, so scoping by
   that is safe. */
.section:not(.section--center) > .wrap > .section-sub { margin-inline: 0; }

/* The ledger is the object in a prose-left / object-right row, so the panels
   stack down the right column rather than sitting side by side. Held to 440,
   the same measure the plan cards use. */
.ledger {
  display: grid;
  grid-template-columns: minmax(0, 440px);
  gap: 18px;
  justify-content: start;
}
.ledger-col {
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: var(--radius-card);
  box-shadow: var(--panel-shadow), inset 0 1px 0 var(--panel-lip);
  padding: 30px 32px 34px;
}
.ledger-col h3 {
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.ledger-col ul { list-style: none; margin-top: 18px; }
.ledger-col li {
  --li-pad: 9px;
  font-size: var(--fs-body);
  line-height: 1.45;
  padding: var(--li-pad) 0 var(--li-pad) 26px;
  position: relative;
}
.ledger-col li + li { border-top: 1px solid var(--line); }
/* Green for what Cliick holds, red for what it doesn't ask for, so the two
   columns separate at a glance. Both are bright and fairly light on purpose:
   a mark this small loses luminance to antialiasing, and a dark red or green
   hairline on this ground goes muddy the same way the tan ones did. The
   shapes still differ — an open ring against a struck one — so the meaning
   holds for anyone who can't tell the two colours apart. */
.ledger-col li::before {
  content: "";
  position: absolute;
  left: 2px;
  /* Centred on the item's first line: its padding, then half the line box
     (line-height 1.45) less half the mark. A fixed 1.02em sat 1.5-2.5px low,
     and 4-5px low once the pinned About tightened the rows (#72). */
  top: calc(var(--li-pad) + (1.45em - 10px) / 2);
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 1.5px solid #5FD39A;
}
/* And a struck-through dot for what is not: the absence is the product. */
.ledger-col--none li::before {
  border-color: #FF6B6B;
  background: linear-gradient(
    to bottom right,
    transparent calc(50% - 0.75px), #FF6B6B calc(50% - 0.75px),
    #FF6B6B calc(50% + 0.75px), transparent calc(50% + 0.75px)
  );
}
.ledger-col--none li { color: var(--ink-strong); }
.ledger-note { margin-top: 26px; font-size: var(--fs-small); color: var(--ink-muted); }
.ledger-note code {
  font: 0.92em/1 ui-monospace, SFMono-Regular, Menlo, monospace;
  padding: 2px 6px;
  border-radius: 5px;
  background: var(--recess);
  border: 1px solid var(--line);
}

/* A hero with a real object beside the title, rather than the 360px plate
   .page-hero-art provides. About puts the founders' photograph here; Start a
   Cliick puts a phone.

   This variant has to exist because .page-hero .wrap sets its second track to
   `auto`, which collapses to zero for any child whose contents are absolutely
   positioned -- which is every .win on the site. */
.page-hero--split .wrap {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr);
  /* Top, not centre: the photograph starts level with the heading. Centred
     beside a story that wraps long in a narrow window, it floated halfway
     down the copy and read as belonging to nothing (#68). */
  align-items: start;
  gap: clamp(30px, 4.6vw, 68px);
}
.page-hero--split .page-head { max-width: none; }
.hero-people { margin: 0; }
.hero-people img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-card);
  border: 1px solid var(--panel-edge);
  box-shadow: var(--panel-shadow);
}
@media not all and (orientation: landscape) and (min-height: 520px) {
  .page-hero--split .wrap { grid-template-columns: minmax(0, 1fr); row-gap: 0; }
  /* Stacked: heading, then the photograph and its quote, then the story.
     Photo-first put a face on the first screen but pushed the heading off it
     at 320x640; heading-first opened with a wall of text before any face.
     Splitting .page-head lets the photograph sit between the two. Scoped to
     .hero-people -- a phone mockup between title and copy would just push
     the copy down. */
  .page-hero--split:has(.hero-people) .page-head { display: contents; }
  .page-hero--split:has(.hero-people) .page-head > h1 { order: -2; }
  .page-hero--split .hero-people { order: -1; margin: 26px 0 30px; }
}

/* --------------------------------------------------------------------------
   About: the photo, then the ledger, stay in view (#68)
   redesign.js builds .about-pinned where the window fits and moves the story,
   the photo, the secret copy and the ledger into it; everywhere else the page
   is the two sections above. It carries .section and .two-col so the moved
   pieces keep today's type exactly.
   -------------------------------------------------------------------------- */
.about-pinned {
  --about-pin-top: calc(var(--nav-h) + 62 * var(--u, 1px));
  padding: var(--about-pin-top) 0 0;
}
/* An upright iPad runs this too; its heading starts where every other
   portrait page's does (see .page-hero above). */
@media not all and (orientation: landscape) and (min-height: 520px) {
  .about-pinned { --about-pin-top: calc(var(--nav-h) + 46px); }
}
/* Beats .two-col, which stacks in portrait -- an upright iPad runs this too. */
.about-pinned .about-pinned-grid {
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr);
  align-items: start;
  gap: clamp(30px, 4.6vw, 68px);
}
.about-pinned .page-head { max-width: none; }
/* Air between the scenes: once the story has gone, the photo holds on its
   own for half a screen before the secret arrives; a quarter screen after
   the secret before "What's missing". */
.about-pinned-secret { margin-top: 50vh; padding-bottom: 28vh; }
/* The side column's height is set by redesign.js so it lets go just before
   the secret heading reaches the pinned line; align-self keeps the grid from
   stretching it back to the text column's height. */
.about-pinned-side { align-self: start; }
.about-pinned-pin {
  position: sticky;
  top: var(--about-pin-top);
  height: calc(100vh - var(--about-pin-top) - 24px);
}
.about-pinned-obj {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  transition: opacity 0.6s ease, transform 0.6s ease;
}
.about-pinned-obj.is-off {
  opacity: 0;
  transform: translateY(24px);
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .about-pinned-obj { transition: none; }
  .about-pinned-obj.is-off { transform: none; }
}
/* The photo gives way in a short window; the quote and caption stay whole. */
.about-pinned .hero-people {
  display: flex;
  flex-direction: column;
  min-height: 0;
  max-height: 100%;
}
.about-pinned .hero-people img {
  flex: 0 1 auto;
  min-height: 120px;
  object-fit: cover;
  object-position: 50% 40%;
}
.about-pinned .founders-caption { flex: none; }
/* The ledger fills the column, stacked; redesign.js tries tighter rows, then
   side by side, before giving up on the pinned column. */
.about-pinned .ledger {
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
  gap: max(12px, calc(18 * var(--u, 1px)));
}
.about-pinned .ledger-col {
  padding: calc(30 * var(--u, 1px)) max(16px, calc(26 * var(--u, 1px))) calc(34 * var(--u, 1px));
}
.about-pinned .ledger-col ul { margin-top: calc(18 * var(--u, 1px)); }
.about-pinned .ledger.is-compact { gap: 12px; }
.about-pinned .ledger.is-compact .ledger-col {
  padding: calc(22 * var(--u, 1px)) max(16px, calc(26 * var(--u, 1px))) calc(22 * var(--u, 1px));
}
.about-pinned .ledger.is-compact .ledger-col ul { margin-top: 8px; }
.about-pinned .ledger.is-compact .ledger-col li { --li-pad: 5px; }
.about-pinned .ledger.is-side { grid-template-columns: 1fr 1fr; }

/* The About close: the promise, centred on the page's own ground. It opts
   out of the tightened .section + .section boundary above it -- this is the
   pause before the last word, not a boundary between arguments. Specificity
   matches the rule it overrides, so it has to come after it. */
.section + .about-close { padding-top: 96px; }
.about-close { padding-bottom: 120px; }
.about-close .learn-more { margin-top: 30px; }

/* Draft signatures. A handwriting face stands in until Nina and John sign
   for real; swap this for their signature images. */
.signatures {
  margin-top: 30px;
  display: flex;
  justify-content: center;
  align-items: baseline;
  gap: 18px;
  font-family: "Caveat", cursive;
  font-size: clamp(2.2rem, 3.4vw, 3rem);
  line-height: 1;
  color: var(--ink-strong);
}
.signatures-amp { font-size: 0.6em; color: var(--ink-faint); }

/* The three structural oddities: no profile page, no search, a code you can
   change. Panels rather than prose, for the same reason the ledger is a
   ledger — these are properties of the build, and a row of objects reads as
   a specification where a paragraph reads as a boast. */
.oddities {
  /* Three to a row at full width, so five items break 3 + 2 rather than
     stranding one on its own line. */
  margin: 44px auto 0;
  max-width: 1040px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 20px;
  text-align: left;
}
.oddity {
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: var(--radius-card);
  box-shadow: var(--panel-shadow-sm), inset 0 1px 0 var(--panel-lip);
  padding: 28px 28px 30px;
}
.oddity h3 {
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.oddity p {
  margin-top: 14px;
  font-size: var(--fs-body);
  line-height: 1.5;
  color: var(--ink-strong);
}

/* One layer down: the facts behind a feeling, for the few who go looking.
   The summary reads like the site's other text links, and says so when it
   opens. */
.fine-print { margin-top: 26px; max-width: 46ch; }
.fine-print summary {
  display: inline-block;
  cursor: pointer;
  list-style: none;
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--accent);
}
.fine-print summary::-webkit-details-marker { display: none; }
.fine-print summary::after { content: "  +"; }
.fine-print[open] summary::after { content: "  \2212"; }
.fine-print summary:hover { text-decoration: underline; text-underline-offset: 6px; }
.fine-print p,
.fine-print ul {
  margin-top: 14px;
  font-size: var(--fs-small);
  line-height: 1.55;
  color: var(--ink-muted);
}
.two-col .copy .fine-print p { font-size: var(--fs-small); margin-top: 14px; }
.fine-print ul { padding-left: 1.1em; }
.fine-print li + li { margin-top: 6px; }
.fine-print code {
  font: 0.92em/1 ui-monospace, SFMono-Regular, Menlo, monospace;
  padding: 2px 6px;
  border-radius: 5px;
  background: var(--recess);
  border: 1px solid var(--line);
}

/* Follow the money: you -> Cliick, with everyone else struck off to the
   side. The same panel and the same struck dot as the ledger's "none"
   column, so the two read as one argument. */
.money-flow {
  justify-self: center;
  width: min(100%, 440px);
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: var(--radius-card);
  box-shadow: var(--panel-shadow), inset 0 1px 0 var(--panel-lip);
  padding: 40px 36px;
}
.flow-row {
  display: flex;
  align-items: center;
  gap: 14px;
}
.flow-node {
  flex: none;
  padding: 12px 22px;
  border-radius: 999px;
  border: 1px solid var(--panel-edge);
  background: var(--recess);
  font-weight: 600;
  font-size: 1.125rem;
}
.flow-node--us { color: #16130E; background: var(--accent); border-color: transparent; }
.flow-arrow {
  flex: 1;
  height: 2px;
  background: var(--accent);
  position: relative;
}
.flow-arrow::after {
  content: "";
  position: absolute;
  right: -1px;
  top: 50%;
  width: 10px;
  height: 10px;
  border-top: 2px solid var(--accent);
  border-right: 2px solid var(--accent);
  transform: translateY(-50%) rotate(45deg);
}
.flow-none {
  list-style: none;
  margin-top: 30px;
  padding-top: 22px;
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: 10px 22px;
}
.flow-none li {
  color: var(--ink-faint);
  text-decoration: line-through;
  text-decoration-color: var(--accent);
  text-decoration-thickness: 1.5px;
}


/* The founders' quote, set as a caption under their photo: centred beneath
   it like a gallery label, but at a size and weight that holds its own
   against the headline beside it -- small and quiet got lost on the page. */
.founders-caption {
  margin-top: 22px;
  padding-inline: 8px;
  text-align: center;
}
.founders-caption-quote {
  display: block;
  font-size: clamp(1.375rem, 2vw, 1.75rem);
  font-style: italic;
  font-weight: 500;
  line-height: 1.4;
  color: var(--ink-strong);
  text-wrap: balance;
}
.founders-caption-by {
  display: block;
  margin-top: 14px;
  font-size: 0.9rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  /* letter-spacing trails the last letter too, which nudges a centred line
     left; widening the box by the same amount re-centres it on the letters */
  margin-right: -0.18em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.founders-caption-by::before { content: "\2014\00a0\00a0"; }
/* Place and occasion, the way a gallery label carries them under the title:
   quieter than the attribution, and the tie between the photo and the story
   the page opens with. */
.founders-caption-where {
  display: block;
  margin-top: 6px;
  font-size: 0.8rem;
  font-style: italic;
  color: var(--ink-faint);
}

/* The close: the founders' role under their signatures, then the host line
   that hands off to Membership. */
.founders-role {
  margin-top: 10px;
  font-size: var(--fs-small);
  letter-spacing: 0.02em;
  color: var(--ink-faint);
}

/* Phone-in-window, static (About) */
.win--inline { max-width: 758px; width: 100%; justify-self: center; }
/* A shot that already includes its own device frame. Centred in the window at
   its natural size -- it is 462px wide, so scaling it up would only soften it. */
.win-mockup {
  position: absolute;
  inset: 0;
  margin: 0;
  display: grid;
  place-items: center;
}
.win-mockup img {
  display: block;
  max-width: min(82%, 462px);
  max-height: 86%;
  width: auto;
  height: auto;
}

/* Steps (About) */
.steps { list-style: none; max-width: 420px; }
/* In a two-column row the steps have their own track, so the 350 measure that
   kept them from sprawling under full-width copy only makes them cramped --
   and there they are the row's object, not a footnote, so they get numerals
   and a heavier title. The list was already an <ol> with its markers
   suppressed, which threw away the one thing a sequence needs to read as a
   sequence. */
.two-col .steps { max-width: none; counter-reset: step; }
.two-col .steps li {
  counter-increment: step;
  position: relative;
  padding-left: 52px;
  min-height: 34px;
}
.two-col .steps li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: -3px;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--surface);
  border: 1px solid var(--line);
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--ink-muted);
}
.two-col .steps li + li { margin-top: 30px; }
.two-col .steps .step-title { font-size: var(--fs-body); font-weight: 600; }
.steps li + li { margin-top: 26px; }
.steps .step-title {
  font-weight: 500;
  font-size: var(--fs-small);
}
.steps p { font-size: var(--fs-small); line-height: 1.5; }

.jump-in-cols {
  margin-top: 64px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
  gap: clamp(32px, 5vw, 90px);
  text-align: left;
}
.jump-in-cols .phone { justify-self: center; height: auto; aspect-ratio: 403 / 800; max-width: min(340px, 80vw); width: 100%; }

/* Promise pills (Membership) */
.pills {
  margin: 44px auto 40px;
  display: grid;
  grid-template-columns: repeat(3, max-content);
  justify-content: center;
  gap: 14px 16px;
}
@media (max-width: 720px) {
  .pills { grid-template-columns: repeat(2, max-content); }
}
@media (max-width: 520px) {
  .pills { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pills span { padding: 6px 14px; }
}
.pills span {
  text-align: center;
  background: var(--paper);
  border-radius: var(--radius-pill);
  padding: 6px 26px;
  font-size: var(--fs-small);
  line-height: 2;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
}

/* --------------------------------------------------------------------------
   FAQ
   -------------------------------------------------------------------------- */
.faq-search-wrap {
  max-width: 900px;
  margin-inline: auto;
  padding: 0 var(--wrap-pad) 44px;
  display: flex;
  justify-content: center;
  position: relative;
}
/* The magnifier sits inside the field at the right, where apps put it. It
   is decoration on a labelled input, so it takes no pointer events and is
   hidden from assistive tech in the markup. Positioned off the wrap's own
   right gutter so it tracks the field at every width. */
.faq-search-icon {
  position: absolute;
  right: calc(var(--wrap-pad) + 26px);
  top: calc((69px - 22px) / 2);
  width: 22px;
  height: 22px;
  color: var(--ink-muted);
  pointer-events: none;
}
.faq-search {
  width: 100%;
  height: 69px;
  border: 1px solid var(--line);
  border-radius: 40px;
  background: var(--recess);
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.18);
  font: inherit;
  font-size: var(--fs-body);
  /* right padding clears the magnifier */
  padding: 0 64px 0 34px;
}
/* The browser's own clear button would land on top of the magnifier. */
.faq-search::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.faq-search::placeholder { color: var(--ink-muted); opacity: 1; }
.faq-search:focus { outline: 3px solid var(--accent); outline-offset: 2px; }

.faq-list {
  max-width: 900px;
  margin-inline: auto;
  padding: 0 var(--wrap-pad) 96px;
}
.faq-section + .faq-section { margin-top: 64px; }
.faq-section-title {
  font-size: 1.75rem;
  font-weight: 600;
  margin: 0 0 18px;
}
.faq-list details:first-of-type { margin-top: 0; }
.faq-list details {
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: 14px;
  margin-top: 14px;
  box-shadow: var(--panel-shadow-sm), inset 0 1px 0 var(--panel-lip);
  overflow: hidden;
  transition: background 0.18s ease, transform 0.18s ease, box-shadow 0.18s ease;
}
.faq-list details:hover { background: var(--panel-hover); }
.faq-list details[open] {
  background: var(--panel-hover);
  border-color: rgba(var(--glow), 0.22);
}
.faq-list summary {
  cursor: pointer;
  list-style: none;
  padding: 18px 56px 18px 24px;
  font-size: var(--fs-body);
  font-weight: 500;
  position: relative;
}
.faq-list summary::-webkit-details-marker { display: none; }
.faq-list summary::after {
  content: "+";
  position: absolute;
  right: 24px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 1.35rem;
  line-height: 1;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  /* 500 rather than 400: at 1.35rem a single stroke is thin enough to
     antialias into the chip behind it. */
  font-weight: 500;
  color: var(--accent-mark);
  background: rgba(var(--glow), 0.10);
  border: 1px solid rgba(var(--glow), 0.18);
}
.faq-list details[open] summary::after { content: "–"; }
.faq-list .answer {
  padding: 0 24px 22px;
  font-size: var(--fs-small);
  line-height: 1.6;
}
.faq-list .answer ul { margin: 10px 0 0 22px; }
.faq-list .answer li { margin-top: 8px; }
.faq-empty {
  display: none;
  text-align: center;
  font-size: var(--fs-body);
  padding: 60px 0;
}

/* --------------------------------------------------------------------------
   Footer (Figma Group 155)
   -------------------------------------------------------------------------- */
.footer-v2 {
  background: #000;
  color: var(--ink-strong);
  text-align: center;
  padding: 96px 0 20px;
}
/* The sign-off answers the page's opener, so it takes the same display size
   as "Reclaim your Feed" rather than sitting a step below it. */
.footer-v2 h2 {
  font-size: var(--fs-display);
  font-weight: 500;
  line-height: 1.05;
}
.footer-dl {
  margin-top: 26px;
  font-size: var(--fs-body);
  display: flex;
  justify-content: center;
  gap: 0.35em 2.5em;
  flex-wrap: wrap;
}
.footer-v2 .store-badges {
  justify-content: center;
  margin-top: 30px;
}
.footer-qr {
  width: 148px;
  margin: 56px auto 0;
  border-radius: 6px;
}
/* You cannot scan a code with the device that is showing it. .is-handheld
   already hides the Start page's doorway QR on a touch device; the footer
   one was never covered, so it sat at 148px on every page on a phone. The
   width rule is the belt: pointer:coarse does not fire in a desktop
   browser's device emulation, and this needs to be right in both. */
.is-handheld .footer-qr,
.is-handheld .footer-qr-caption { display: none; }
@media (max-width: 700px) {
  .footer-qr,
  .footer-qr-caption { display: none; }
  /* The badges become the only way through, so give them the room the code
     was taking. */
  .footer-v2 .store-badges { margin-top: 26px; }
}
.footer-qr-caption { margin-top: 14px; font-size: var(--fs-body); }
/* Four links now — Terms, Privacy, Account deletion, Support — which wraps
   on a phone. Inline "|" text stranded a bar at the end of the first line,
   so the bars are their own elements and the row is a wrapping flex line;
   on a phone the bars go and the gap does the separating. */
.footer-legal {
  margin-top: 48px;
  font-size: var(--fs-body);
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px 12px;
}
@media (max-width: 720px) {
  .footer-legal { column-gap: 24px; }
  .footer-legal .sep { display: none; }
}
.footer-legal a { text-decoration: none; }
.footer-legal a:hover { text-decoration: underline; }
.footer-bottom {
  margin-top: 56px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  font-size: var(--fs-body);
  text-align: left;
}
.footer-bottom nav { display: flex; gap: 28px; flex-wrap: wrap; }
.footer-bottom a { text-decoration: none; }
.footer-bottom a:hover { text-decoration: underline; }

/* --------------------------------------------------------------------------
   Responsive
   -------------------------------------------------------------------------- */
@media not all and (orientation: landscape) and (min-height: 520px) {
  .showcase .row { padding-block: 48px; }
  .two-col,
  .jump-in-cols { grid-template-columns: 1fr; }
  /* The hero sizes to its content. At full-screen height an upright iPad
     centred ~300px of copy in 866px, leaving a band of bare backdrop above
     the headline. Phones get a tighter top in the 720 block below. */
  .hero { min-height: 0; padding-top: calc(var(--nav-h) + 46px); padding-bottom: 0; }
  .hero .wrap { padding-block: 0; }
}
/* Real phones (440px and under) stack: copy, then the device. */
@media not all and (orientation: landscape) and (min-height: 520px) {
  /* Nested, not "and (max-width)": a leading `not` negates the whole query,
     width included, so the flat form matched every landscape window. */
  @media (max-width: 479px) {
    /* One gap throughout, 60px between device and copy in both directions --
       the hero phone to the first heading, which was the comfortable one.
       Copy to its phone was 52 and a phone to the next heading 108, since
       each row padded both ends. The .win adds 12 of its own each side. */
    .showcase .row {
      grid-template-columns: 1fr;
      row-gap: 52px;
      padding-block: 24px;
    }
    .showcase .row:first-child { padding-top: 48px; }
    .showcase .row:last-child { padding-bottom: 48px; }
    /* Measured to the ink, not the boxes: a paragraph's box runs ~8px below
       its last baseline and a heading's starts ~12px above its capitals, so
       equal boxes read as unequal gaps. These give 72px of visible space
       between text and device in both directions. The shadow is kept nearly
       centred here: at 24px down it read as part of the device and made the
       space below each phone look ~25px shorter than the space above. */
    .fallback-flow .phone { box-shadow: 0 6px 48px rgba(0, 0, 0, 0.4); }
    .showcase .win { order: 2; }
    /* The badges to the hero phone take the same 72 (60 + the .win's 12). */
    .hero .wrap { grid-template-columns: 1fr; row-gap: 60px; }
  }
}
/* Anything wider -- a desktop window at its ~500px minimum, an upright
   iPad, a phone on its side -- keeps copy left and phone right. Stacked, a
   500px window held a 240px phone alone in its row with the rest empty.
   The phone column is the device's own width, so the copy takes all that
   is left; the device shrinks a step in the narrowest band to leave the
   headings a readable measure. */
@media not all and (orientation: landscape) and (min-height: 520px) {
  @media (min-width: 480px) {
    .hero .wrap,
    .showcase .row {
      grid-template-columns: minmax(0, 1fr) auto;
      column-gap: clamp(18px, 4vw, 40px);
    }
    .fallback-flow .win { width: calc(var(--phone-w) * var(--mock-zoom)); }
  }
}
/* The fallback flow renders from 1199px down, so its lit space has to start
   there too. Scoped to 720 this left a band from 721 to 1199 still running
   the old treatment — a dark #130e04 hero carrying its own backdrop, with
   the sections on flat wall — which is why the window appeared to change
   colour between widths. */
/* Not gated on width any more (#54). The stacked Home renders wherever the
   scenes do not run — portrait, and landscape with reduced motion — and it
   needs its backdrop in every one of those. Below-1200px gating left a
   desktop visitor with reduced motion on the stacked Home with no backdrop. */
/* --- One lit space, as on the subpages ---------------------------------
   Collapsed, the hero was a dark band carrying its own copy of the backdrop
   while the scenes below sat on flat wall colour, so the hero read as a
   different design from the sections it introduces. The backdrop becomes one
   fixed layer for the whole flow and the hero becomes a darkened region of
   it, with its scrim masked so it fades out instead of ending on an edge —
   the same treatment that removed the seam on About and Membership. */
/* The narrow homepage takes the same backdrop as everything else: the
   photograph at full strength with the stage shade over it.

   It used to carry the pre-#37 treatment — cropped to 76% across, which is
   the photo's amber half, then blurred, desaturated, brightened 1.22 and
   dropped to 0.58 opacity. That is exactly the fade-toward-the-wall that the
   whole colour pass removed, and it is what "brown" meant. It survived
   because it only renders below 1200px, so every capture taken at desktop
   width looked correct. Measured across widths with content hidden: the
   backdrop went 22,23,30 above 1200 and 78,68,68 below it, warming to
   89,75,69 by 500px. Now flat. */
.fallback-flow::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -2;
  background: url("/images/redesign/hero-bg-sim.svg") center / cover no-repeat;
  pointer-events: none;
}
.fallback-flow::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    linear-gradient(180deg, rgba(0, 0, 0, 0.45) 0%, rgba(0, 0, 0, 0) 18%),
    linear-gradient(90deg, rgba(0, 0, 0, 0.55) 0%, rgba(0, 0, 0, 0.15) 60%);
}
.fallback-flow .hero { background: transparent; }
.fallback-flow .hero > .hero-bg { display: none; }
/* The hero's own scrim is gone: that is the shade's job one layer down, and
   two stacked is what made this section read darker than the rest. Removing
   the fallback's override was not enough — the base .hero::after carries the
   same two gradients and took over, so it is switched off here explicitly.
   Measured: the fallback backdrop read 51,41,37 against the stage's
   70,57,52 with both shades stacked. */
.fallback-flow .hero::after { display: none; }
/* No clipping here: overflow: hidden was for the full-bleed .hero-bg, which
   this flow does not show, and it sliced the hero phone's shadow off at the
   section's bottom edge. */
.fallback-flow .hero { color: var(--ink-strong); overflow: visible; }


@media (max-width: 720px) {
  /* The hero loses its phone at this width, so a 100vh opener is left holding
     about 310px of copy in an 844px screen — half the first view is backdrop,
     and everything that would invite a scroll is pushed under the fold. Size
     it to its content instead, so the section below peeks into view. */
  /* The hero keeps its subject. Deleting the phone was what emptied it: a
     product site's hero with no product is just a paragraph on a photo. It is
     scaled to about half, which leaves a composition rather than filling the
     screen, and it keeps its crop at the hero's bottom edge. */
  .hero {
    min-height: 0;
    padding-top: calc(var(--nav-h) + 28px);
    padding-bottom: 0;
  }
  .hero .wrap { padding-block: 0; }

  /* A tighter gap on a phone; the badges scale to whatever row is left. */
  .store-badges { --badge-gap: 12px; }

  .win { height: 480px; }
  /* The hero's device scales with the scenes', since it now shares their
     window. transform-origin matters as much as the scale: without top center
     the phone shrinks about its middle and drops 236px into the window instead
     of 40, so it is cut by 282px rather than 81. */
  .showcase .phone--static,
  .phone--static { top: 40px; transform: translateX(-50%) scale(0.82); transform-origin: top center; }
  .plan { padding: 30px 26px 36px; }
  .footer-bottom { justify-content: center; text-align: center; }
}

/* Portrait gets the menu button (#54). It used to appear below 720px wide,
   which gave a phone held sideways (844x390) the full desktop link row. */
@media not all and (orientation: landscape) and (min-height: 520px) {
  /* Four links and a button do not fit on one row — shrinking both far
     enough put the button's right edge at 421px on a 390px viewport, off the
     screen entirely, and took the links below a tappable size on the way.
     The links go behind a menu button, which is what the pattern is for.
     The CTA stays in the bar: it is the one thing on the page worth acting
     on, and burying it behind a tap is the mistake this replaces. */
  /* The wordmark used to hide here too, to make room for that button. With
     the CTA parked (#46) the bar has the room, so the lockup stays whole;
     it just sizes down, the mark to the 34px it already had. */
  .nav { --wm-cap: 16.7px; }
  .nav-cta {
    margin-left: auto;
    padding: 8px 15px;
    font-size: 0.9rem;
  }
  .nav-toggle { display: grid; }

  /* The panel drops from under the bar rather than covering the page: at
     four items a sheet would be more ceremony than the content deserves. */
  .nav-links {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 6px 0 10px;
    /* No ground of its own. The page is scrolled to the top and then
       displaced, so the space the menu opens into is genuinely empty and
       what sits behind it is the site's own backdrop. Nothing to hide, so
       nothing to hide it with — and no backdrop-filter, which would sample
       content that is moving for the length of the animation and re-tint the
       panel every frame. */
    background: none;
    box-shadow: none;
    /* Closed is display:none, not opacity or height: a panel that is merely
       invisible still takes focus and still reads to a screen reader. */
    display: none;
  }
  body.nav-open .nav-links { display: flex; }

  /* The page is displaced rather than covered. Everything but the bar slides
     down by the panel's height, so the menu opens into space instead of on
     top of the argument. redesign.js measures the panel and sets --menu-h.
     Home's two versions each keep their backdrop in place (below): the
     backdrop is the room, not the page. */
  body > *:not(.nav) {
    transition: transform 0.34s cubic-bezier(0.32, 0.72, 0, 1);
  }
  body.nav-open > *:not(.nav) {
    transform: translateY(var(--menu-h, 0px));
  }
  /* .fallback-flow carries the homepage's backdrop as a position:fixed
     ::before with a negative inset. Transforming the element makes it the
     containing block for that pseudo, so the backdrop travelled down with the
     page and its negative top edge landed right behind the menu — which is
     where the brown came from. The backdrop is the room, not the page, so it
     stays put and the sections inside move instead. */
  body.nav-open .fallback-flow { transform: none; }
  .fallback-flow > * {
    transition: transform 0.34s cubic-bezier(0.32, 0.72, 0, 1);
  }
  body.nav-open .fallback-flow > * {
    transform: translateY(var(--menu-h, 0px));
  }
  @media (prefers-reduced-motion: reduce) {
    .fallback-flow > * { transition: none; }
  }
  /* The stage runs in portrait too from 480px wide (#66). Sliding the whole
     track took its photograph and scrims down with it and left bare wall
     behind the menu -- the same fault as the fallback's backdrop above. The
     track stays; the phone and the scene copy move. `translate` rather than
     `transform`, because the scenes' own enter/exit motion is a transform
     and the two have to add, not replace each other. */
  body.nav-open .stage-track { transform: none; }
  .stage-frame .stage-phone,
  .stage-frame .scene {
    transition: opacity 0.5s ease, transform 0.5s ease,
      translate 0.34s cubic-bezier(0.32, 0.72, 0, 1);
  }
  body.nav-open .stage-frame .stage-phone,
  body.nav-open .stage-frame .scene { translate: 0 var(--menu-h, 0px); }
  @media (prefers-reduced-motion: reduce) {
    body > *:not(.nav) { transition: none; }
  }
  /* Pure white and a touch heavier, not because the panel is dark but
     because it is not: the menu sits on the site's own backdrop, and on the
     homepage that backdrop is the brightest of the five. --ink-strong
     measured 4.29:1 there, just under the 4.5 minimum; white clears it
     without putting anything behind the type. */
  .nav-links a {
    padding: 14px var(--wrap-pad);
    font-size: 1rem;
    font-weight: 500;
    color: #FFFFFF;
    text-decoration: none;
  }
  /* The current page is marked by the edge alone. A full-width fill behind
     the row reads as a stripe across the glass rather than as a marker,
     which is most of what looked banded here. */
  .nav-links a[aria-current="page"] {
    text-decoration: none;
    box-shadow: inset 3px 0 0 var(--accent-mark);
  }
}

/* --------------------------------------------------------------------------
   Legal pages
   The body is long-form reading on the same backdrop as every other page, so
   it gets a reading measure and a quiet type scale rather than a surface of
   its own.
   -------------------------------------------------------------------------- */
.legal-section { padding-top: 8px; }
.legal {
  max-width: 68ch;
  font-size: var(--fs-body);
  line-height: 1.7;
  color: var(--ink-strong);
  /* The synced text carries a 63-character Apple EULA address with nothing
     to break on, which pushed Terms to 353px on a 320px phone. Fixed here,
     not in the synced file, so the next sync cannot bring it back. */
  overflow-wrap: anywhere;
}
.legal > * + * { margin-top: 1em; }
/* Sections, not chapters: a legal page has twenty of them, and headings at
   the site's h3 size turned every one into a billboard. */
.legal h2 {
  margin-top: 2em;
  font-size: clamp(1.2rem, 1.5vw, 1.45rem);
  font-weight: 600;
  line-height: 1.3;
}
.legal h3 {
  margin-top: 1.8em;
  font-size: 1.125rem;
  font-weight: 600;
}
.legal h2 + *,
.legal h3 + * { margin-top: 0.6em; }
.legal ul,
.legal ol { padding-left: 1.3em; }
.legal li + li { margin-top: 0.45em; }
.legal a {
  color: var(--accent);
  text-underline-offset: 3px;
}
.legal-status { color: var(--ink-muted); }

/* The deletion page's "On this page" list and its one aside. Both quiet: the
   page is policy, and the reading column is the point. */
.legal-toc {
  max-width: 68ch;
  margin-bottom: 36px;
  padding-left: 16px;
  border-left: 2px solid var(--line);
}
.legal-toc-title {
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  /* --ink-faint measured 3.98:1 here on a phone; small type on the photo
     backdrop needs the strong ink. */
  color: var(--ink-strong);
}
.legal-toc ul { list-style: none; margin-top: 10px; }
.legal-toc li + li { margin-top: 6px; }
/* Stacked links sit one line apart, so each needs its own 24px of height to
   meet the WCAG 2.2 target minimum; they measured 23. */
.legal-toc a {
  display: inline-block;
  padding-block: 2px;
  color: var(--accent);
  text-underline-offset: 3px;
}
.legal h2:first-child { margin-top: 0; }
.legal-note {
  padding: 4px 0 4px 16px;
  border-left: 3px solid var(--accent-mark);
  color: var(--ink-muted);
}

/* Support: a mailto form. Fields take the FAQ search's material — recessed,
   hairline edge, the page's own type — so they read as part of this site
   rather than the old one's white boxes. */
.support-form {
  max-width: 68ch;
  margin-top: 26px;
  display: grid;
  gap: 18px;
}
.support-field { display: grid; gap: 8px; }
.support-field label {
  font-size: var(--fs-small);
  font-weight: 600;
  /* --ink-muted measured 3.6:1 on a phone where the backdrop is brightest. */
  color: var(--ink-strong);
}
.support-field input,
.support-field textarea {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--recess);
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.18);
  color: var(--ink-strong);
  font: inherit;
  font-size: var(--fs-body);
  padding: 14px 18px;
}
.support-field textarea { resize: vertical; min-height: 150px; line-height: 1.55; }
.support-field input::placeholder,
.support-field textarea::placeholder { color: var(--ink-faint); opacity: 1; }
.support-field input:focus,
.support-field textarea:focus { outline: 3px solid var(--accent); outline-offset: 2px; }
/* An empty required field is marked only after a submit attempt, not on
   arrival — red boxes on a page you have just opened read as an accusation. */
.support-form.was-submitted :invalid { border-color: #FF6B6B; }
.support-submit {
  justify-self: start;
  padding: 12px 26px;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--control-on);
  color: var(--control-on-ink);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  box-shadow: var(--panel-shadow-sm);
}
.support-submit:hover { filter: brightness(1.06); }
.support-status { min-height: 1.4em; color: var(--ink-muted); font-size: var(--fs-small); }
.support-alt { max-width: 68ch; margin-top: 30px; color: var(--ink-muted); }
.support-alt a { display: inline-block; padding-block: 2px; color: var(--accent); text-underline-offset: 3px; }

/* --------------------------------------------------------------------------
   Phones in the stacked layout (#48)
   The stacked Home used to sit each phone inside its own recessed, glowing
   panel and crop it at the panel's bottom edge — a second background on top
   of the page's own, with a phone that never ends. The phones now sit on the
   page with nothing behind them, whole, and smaller: the whole device is the
   point, not a slice of its screen. zoom rather than a transform, so the
   layout box shrinks with the phone and nothing reserves empty space below
   it. The device keeps its own drop shadow for depth.
   -------------------------------------------------------------------------- */
.fallback-flow { --mock-zoom: 0.6; }
.fallback-flow .win {
  height: auto;
  background: none;
  clip-path: none;
  display: flex;
  justify-content: center;
  padding-block: 12px;
}
.fallback-flow .win .phone--static {
  position: static;
  transform: none;
}
.fallback-flow .win .phone--static { zoom: var(--mock-zoom); }
@media (max-width: 720px) {
  /* The phone scales with the screen showing it: about half the width of a
     390px phone, so the whole device fits well inside one screen. */
  .fallback-flow { --mock-zoom: 0.5; }
  .fallback-flow .win .phone--static { top: auto; transform: none; }
}
/* Side by side in the narrowest wide-portrait band (see the 480px rules
   above): the device steps down so the headings keep a readable measure. */
@media not all and (orientation: landscape) and (min-height: 520px) {
  @media (min-width: 480px) and (max-width: 600px) {
    .fallback-flow { --mock-zoom: 0.42; }
  }
}

/* ==========================================================================
   The scene scrims (#37)
   --------------------------------------------------------------------------
   The landing reads royal — blue and gold — because the hero photograph is
   at full strength. The original design faded it toward the wall as the
   story started, and what was left once the colour drained out was brown:
   not the wall, but the photo's own amber half blurred across the frame.
   Deepening the wall made it worse. Holding the photograph is what worked.

   On top of the held photograph, each scene gets a pair: a cool side and its
   warm complement, moving together. An earlier pass tinted only the left,
   which left the amber doing the same thing in every scene.

   The subpages walk the same three pairs continuously against scroll rather
   than stepping — see body.page-gray::after above and redesign.js. If these
   values change, change them in both places; they are meant to be identical.
   ========================================================================== */

.stage-frame::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  /* background-image rather than background: the drift below rides on
     background-position, and transitioning the shorthand would animate every
     frame of it into a smear. */
  transition: opacity 0.9s ease, background-image 0.9s ease;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  /* The two pools drift in opposite directions as the stage plays, the way
     they do down a subpage — see redesign.js. The colours still step per
     scene; it is the light that moves. */
  background-position: 0 var(--stage-cool-d, 0px), 0 var(--stage-warm-d, 0px);
}

/* indigo <-> gold */
.stage-frame[data-scene="1"]::before {
  background-image:
    radial-gradient(ellipse at 16% 46%, rgba(38, 53, 111, 0.82) 0%, rgba(38, 53, 111, 0) 60%),
    radial-gradient(ellipse at 86% 38%, rgba(224, 164, 94, 0.42) 0%, rgba(224, 164, 94, 0) 58%);
}
/* plum <-> rose-gold */
.stage-frame[data-scene="2"]::before {
  background-image:
    radial-gradient(ellipse at 16% 46%, rgba(52, 54, 104, 0.70) 0%, rgba(58, 47, 110, 0) 60%),
    radial-gradient(ellipse at 86% 38%, rgba(224, 144, 126, 0.44) 0%, rgba(224, 144, 126, 0) 58%);
}
/* violet <-> amber, handing off to the gold of the band below */
.stage-frame[data-scene="3"]::before {
  background-image:
    radial-gradient(ellipse at 16% 46%, rgba(62, 56, 108, 0.68) 0%, rgba(74, 46, 112, 0) 60%),
    radial-gradient(ellipse at 86% 38%, rgba(217, 160, 91, 0.46) 0%, rgba(217, 160, 91, 0) 58%);
}
.stage-frame:not([data-scene="0"])::before { opacity: 0.66; }

/* The latte band stays warm on purpose. Its ground is cream because the
   photograph above it is a cup of coffee — cool it and the one warm beat in
   the site turns into a cold room with a hot drink in it. It is a single
   band, it is light, and nothing about it reads brown. Left alone. */
