/* ──────────────────────────────────────────────────────────────────
   RepChef landing — "The Midnight Spread"
   Two canvases, one typographic DNA. The app's logo film first, on its own
   ground; then the story on the app's graphite aurora with a pinned phone
   that walks the product one still per scroll step; plans and FAQ on
   porcelain. Crimson Velvet is the only hue. Schibsted Grotesk 800 at
   monumental scale; every figure in JetBrains Mono. Pills only.
   ────────────────────────────────────────────────────────────────── */

@font-face { font-family: "Schibsted Grotesk"; src: url("assets/fonts/SchibstedGrotesk.woff2") format("woff2"); font-weight: 400 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Schibsted Grotesk"; src: url("assets/fonts/SchibstedGrotesk-Italic.woff2") format("woff2"); font-weight: 400 900; font-style: italic; font-display: swap; }
@font-face { font-family: "JetBrains Mono"; src: url("assets/fonts/JetBrainsMono.woff2") format("woff2"); font-weight: 500 700; font-style: normal; font-display: swap; }

:root {
  color-scheme: dark;
  /* story track */
  --night: #0f0f10;   /* one tint for the whole dark track - the nav's veil colour - with the glows through it (owner, round 20) */
  --night-2: #0a0a0a;
  --on-dark: #ffffff;
  --shade-40: #c4c4cb;
  --shade-60: #52525b;
  --hair-dark: rgba(255, 255, 255, 0.10);
  --sheen: rgba(255, 255, 255, 0.05);
  /* transactional track — RepChef porcelain (Aurora light) */
  --porcelain: #ebebeb;
  --paper: #ffffff;
  --ink: #1c1c1e;
  --ink-2: #5c5c5f;
  --hair-light: rgba(28, 28, 30, .12);   /* translucent: it has to sit on a wash */
  --rose-fill: #f3dee0;
  /* the one hue */
  --accent-dark: #cb7c82;
  --accent-light: #a13a43;
  --wm-1: #e3a9ae; --wm-2: #cb7b82; --wm-3: #a04a52;
  --screen: #131315;

  --font: "Schibsted Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "JetBrains Mono", ui-monospace, "Cascadia Mono", Menlo, monospace;
  --ease: cubic-bezier(.22, 1, .36, 1);
  /* Motion is the app's own. A screen change is its Mist (core/design/Mist.kt): the old screen stays on top
     and turns to mist over 900 ms — fading on FastOutLinearIn, blurring, lifting — while the new one settles
     in beneath after 200 ms on the house curve. A step change is its onboarding step
     (feature/onboarding/OnboardingScreen.kt): 550 ms on the step curve, in from 48dp with a 220 ms fade,
     out only 16dp with a 220 ms fade. */
  --mist: 900ms; --mist-delay: 200ms;
  --slide: 550ms; --slide-fade: 220ms;
  --ease-step: cubic-bezier(.32, .72, 0, 1);
  --ease-out-in: cubic-bezier(.4, 0, 1, 1);
  --step: clamp(180px, 26vh, 260px);   /* the scroll distance one still holds for */
  --wrap: 1200px;
  --gutter: clamp(20px, 5vw, 56px);
  --air: clamp(96px, 14vw, 192px);
  --nav-h: 72px;
  /* the phone: width drives everything; 1080:2400 screen inside a 12px bezel */
  --pw: min(340px, calc((100vh - 140px) * 0.45));
}

/* ── Base ───────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body { margin: 0; background: var(--night); color: var(--on-dark); font-family: var(--font); font-size: 1rem; line-height: 1.5; overflow-x: clip; scrollbar-color: #3f3f46 var(--night); caret-color: var(--accent-dark); }
::selection { background: rgba(203, 124, 130, .35); }
:focus-visible { outline: 2px solid currentColor; outline-offset: 4px; }
img, svg { display: block; max-width: 100%; }
[hidden] { display: none !important; }
p, h1, h2, h3, h4, dl, dd { margin: 0; }
h1, h2, h3, h4 { font-weight: 800; letter-spacing: -0.02em; text-wrap: balance; }
a { color: inherit; text-decoration: none; }
ul, ol { margin: 0; padding: 0; list-style: none; }
strong { font-weight: 700; color: inherit; }
table { border-collapse: collapse; }
.num { font-family: var(--mono); font-weight: 500; font-variant-numeric: tabular-nums; }
.ico { width: 1.1em; height: 1.1em; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; flex: none; }
.accent { font-style: normal; color: var(--accent-dark); }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.wrap { width: min(100% - 2 * var(--gutter), var(--wrap)); margin-inline: auto; }
.wrap--narrow { max-width: 760px; }
.sec { padding-top: var(--air); }
/* The ground (round 28; owner: "tint the page with flares and glows subtle, nothing loud, must be visible"). Rounds
   21-22 tried four neutral grey spots at the corners; they banded, and the last read as a grey blob under the wordmark
   (round 26: "needs to be gone"). What is here instead is hued and placed: a cool violet-blue from the film's neon at
   the upper right, the accent's rose at the lower left, one soft diagonal flare - each a cosine falloff at eleven stops,
   very low, over the one tint - and a grain on body::after that dithers them so nothing bands. The subjects carry
   their own light: a backlight behind the film's figure, a studio light behind the phone. */
body::before {
  content: ""; position: fixed; inset: 0; z-index: -2; pointer-events: none;
  background:
    radial-gradient(62vmax 46vmax at 86% 10%, rgba(128,148,255,0.0700) 0%, rgba(128,148,255,0.0683) 10%, rgba(128,148,255,0.0633) 20%, rgba(128,148,255,0.0556) 30%, rgba(128,148,255,0.0458) 40%, rgba(128,148,255,0.0350) 50%, rgba(128,148,255,0.0242) 60%, rgba(128,148,255,0.0144) 70%, rgba(128,148,255,0.0067) 80%, rgba(128,148,255,0.0017) 90%, rgba(128,148,255,0.0000) 100%),
    radial-gradient(56vmax 42vmax at 8% 90%, rgba(203,124,130,0.0550) 0%, rgba(203,124,130,0.0537) 10%, rgba(203,124,130,0.0497) 20%, rgba(203,124,130,0.0437) 30%, rgba(203,124,130,0.0360) 40%, rgba(203,124,130,0.0275) 50%, rgba(203,124,130,0.0190) 60%, rgba(203,124,130,0.0113) 70%, rgba(203,124,130,0.0053) 80%, rgba(203,124,130,0.0013) 90%, rgba(203,124,130,0.0000) 100%),
    linear-gradient(112deg, rgba(200,210,255,0) 34%, rgba(200,210,255,0.02) 44%, rgba(255,255,255,0.04) 50%, rgba(200,210,255,0.02) 56%, rgba(200,210,255,0) 66%),
    #0f0f10;
}
body::after {
  content: ""; position: fixed; inset: 0; z-index: -2; pointer-events: none; opacity: .03;
  background: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22160%22%20height%3D%22160%22%3E%3Cfilter%20id%3D%22n%22%3E%3CfeTurbulence%20type%3D%22fractalNoise%22%20baseFrequency%3D%22.9%22%20numOctaves%3D%222%22%20stitchTiles%3D%22stitch%22%2F%3E%3CfeColorMatrix%20type%3D%22saturate%22%20values%3D%220%22%2F%3E%3C%2Ffilter%3E%3Crect%20width%3D%22160%22%20height%3D%22160%22%20filter%3D%22url(%23n)%22%2F%3E%3C%2Fsvg%3E") 0 0 / 160px 160px repeat;
}
/* The app's intro figure behind the page: one blurred frame of the sprite, chosen by the scroll
   position (main.js). The sprite's ground is levelled to black and vignetted, and the canvas
   multiplies a radial matte, so screen blending adds only the figure's light onto the tint —
   no tile edge at any viewport; it is cut out behind the nav, the hero and the text sections. Without JS or under reduced motion there is no figure. */
.figure { position: fixed; inset: 0; z-index: -1; pointer-events: none; mix-blend-mode: screen; opacity: .62; background: #000; }
.skip { position: absolute; left: 12px; top: -48px; padding: 8px 14px; background: var(--on-dark); color: var(--night); border-radius: 999px; font-weight: 700; z-index: 100; }
.skip:focus { top: 12px; }

/* ── Type stair: 96 → 70 → 55, at 800 ──────────────────────── */
.d-xxl { font-size: clamp(44px, 2rem + 4.6vw, 96px); font-weight: 800; line-height: 1.0; letter-spacing: -0.035em; max-width: 19ch; }
.d-xl  { font-size: clamp(36px, 1.6rem + 3.2vw, 70px); font-weight: 800; line-height: 1.02; letter-spacing: -0.03em; max-width: 16ch; }
.d-lg  { font-size: clamp(32px, 1.6rem + 2.2vw, 55px); font-weight: 800; line-height: 1.08; letter-spacing: -0.025em; max-width: 18ch; }
.lede  { font-size: clamp(17px, 1rem + 0.4vw, 20px); font-weight: 500; line-height: 1.55; color: var(--shade-40); max-width: 44ch; margin-top: 28px; text-wrap: pretty; }
.lead  { font-size: 17px; font-weight: 500; line-height: 1.55; color: var(--shade-40); max-width: 52ch; margin-top: 22px; text-wrap: pretty; }
h3 { font-size: 28px; font-weight: 700; letter-spacing: -0.02em; line-height: 1.2; }

/* ── Pills: the only button shape ───────────────────────────── */
.pill { display: inline-flex; align-items: center; gap: .55em; border-radius: 9999px; padding: 12px 24px; font-size: 16px; font-weight: 700; letter-spacing: 0; white-space: nowrap; line-height: 1; min-height: 44px; transition: background-color .25s var(--ease), color .25s var(--ease), transform .25s var(--ease); }
.pill--solid { background: var(--on-dark); color: var(--night); }
.pill--solid:hover, .pill--solid:focus-visible { background: #e4e4e7; }
.pill--outline { background: transparent; color: var(--on-dark); box-shadow: inset 0 0 0 2px var(--on-dark); }
.pill--outline:hover, .pill--outline:focus-visible { background: var(--on-dark); color: var(--night); }
.pill--dark { background: var(--ink); color: var(--paper); }
.pill--dark:hover, .pill--dark:focus-visible { background: #3f3f46; }
.pill--lg { padding: 16px 32px; font-size: 17px; }
.pill:active { transform: translateY(1px); }
.link { color: var(--ink-2); font-weight: 600; display: inline-flex; align-items: center; gap: .35em; text-decoration: underline; text-underline-offset: 5px; text-decoration-thickness: 1px; }
.link:hover { color: var(--ink); }

/* ── Store badges ───────────────────────────────────────────── */
.stores { display: flex; align-items: center; flex-wrap: wrap; gap: 12px 14px; }
.badge img { height: 40px; width: auto; }            /* Google's minimum; the asset carries its own clear space */
.badge { display: inline-block; }
.badge:focus-visible { outline-offset: 2px; }
.stores--lg .badge img { height: 56px; }

/* ── Wordmark ───────────────────────────────────────────────── */
.wordmark { font-weight: 800; font-size: 22px; letter-spacing: -0.02em; line-height: 1; }
.wordmark__rep { background: linear-gradient(135deg, var(--wm-1), var(--wm-2) 45%, var(--wm-3)); -webkit-background-clip: text; background-clip: text; color: transparent; }

/* ── Nav ────────────────────────────────────────────────────── */
.nav { position: sticky; top: 0; z-index: 20; background: none; }
/* The veil: part of the ground, not a bar. A soft graphite gradient and a blur that fade out
   along the lower edge, so nothing draws a line under the wordmark. The tail is short (32px) so
   it never dims the first line of a pinned title. */
.nav::before {
  content: ""; position: absolute; inset: 0 0 -32px; z-index: -1; pointer-events: none;
  background: linear-gradient(180deg, rgba(21, 21, 23, .92) 0, rgba(21, 21, 23, .86) var(--nav-h), rgba(21, 21, 23, 0) 100%);   /* one shade above the tint (round 30: "top can be little lighter"; then "too light, just a shade lighter than the earlier black" - 30,30,33 was five), the page's glows faint through it */
  -webkit-backdrop-filter: blur(18px); backdrop-filter: blur(18px);
  -webkit-mask-image: linear-gradient(#000 var(--nav-h), transparent); mask-image: linear-gradient(#000 var(--nav-h), transparent);
}
.nav__row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 16px; min-height: var(--nav-h); }   /* the links sit on the page's centre line */
.brand { display: inline-flex; align-items: center; justify-self: start; }   /* the wordmark alone (owner, round 17: "get rid of the logo beside RepChef") */
.nav__menu { display: flex; gap: clamp(14px, 2.4vw, 28px); justify-self: center; }
.nav__menu a { font-weight: 700; font-size: 15px; color: var(--shade-40); padding: 8px 0; transition: color .25s var(--ease); }
.nav__menu a:hover, .nav__menu a[aria-current="page"] { color: var(--on-dark); }
.nav__links { gap: 10px; justify-self: end; }
/* On the pale pages (plans, FAQ) the veil and the links go pale with the page; the footer keeps the aurora. */
.brand .wordmark { font-size: 28px; }   /* round 44 (owner: "the logo can be made bit bigger"): the nav's wordmark up from 22px */
@media (max-width: 899px) { .brand .wordmark { font-size: 24px; } }
@media (max-width: 480px) { .brand .wordmark { font-size: 21px; } }   /* the wordmark stays at every width; smaller where the row is tight (was 18px) */
@media (max-width: 480px) {
  /* The Play badge stays — it is the only call on the one platform that can install — so the row's
     gaps tighten until the brand, the links and the badge all fit with the links centred, on the
     page's own gutter (exact at 360, 390, 414 and 480px). */
  .nav .nav__row { gap: 8px; }
  .nav__menu { gap: 10px; }
  .nav__menu a { font-size: 14px; }
}

/* ── Hero: the brand film, scrubbed by the scroll, on its own ground ── */
/* The film is frames on a canvas (sprite sheets; never a <video>, never an autoplaying image): the
   scroll position picks the frame, forward on the way down and back on the way up, while the
   block pins for --hn steps and the offers step beside it. The film sits on near-black, not the
   aurora, so the pin carries that black continued outward and lets it ease, over its lower half,
   from the film's floor tone into the aurora — one long fade, no band. Only the film's top and
   bottom edges are masked (the floor glow under the figure's feet dissolves into the ground). */
.hero { position: relative; min-height: 100vh; margin-top: calc(-1 * var(--nav-h)); }
.hero__pin { position: relative; min-height: 100vh; padding-top: var(--nav-h); display: grid; align-items: center; }   /* no ground of its own: the film's floor is transparent (keyed in the asset), so the hero sits on the page's tint and glows like everything else */
.hero__grid { display: grid; gap: 36px; padding-block: 16px 88px; width: min(100% - 2 * var(--gutter), 1600px); }   /* wider than the page's wrap: the film wants the room */
.hero__pin { overflow-x: clip; }   /* clip, not hidden (the pin must still stick): neither the scaled film (mid widths) nor the backlight behind it may widen the page */
.hero__film { position: relative; width: 100%; aspect-ratio: 4 / 3; justify-self: center; isolation: isolate; }   /* isolate: the backlight's z -1 stays behind the film only */
.hero__film::before { content: ""; position: absolute; inset: -30% -30%; z-index: -1; pointer-events: none;   /* a studio backdrop light behind the figure (round 28); the ellipse ends inside the box */
  background: radial-gradient(ellipse 30% 40% at 50% 48%, rgba(226,232,255,0.1100) 0%, rgba(226,232,255,0.1073) 10%, rgba(226,232,255,0.0995) 20%, rgba(226,232,255,0.0873) 30%, rgba(226,232,255,0.0720) 40%, rgba(226,232,255,0.0550) 50%, rgba(226,232,255,0.0380) 60%, rgba(226,232,255,0.0227) 70%, rgba(226,232,255,0.0105) 80%, rgba(226,232,255,0.0027) 90%, rgba(226,232,255,0.0000) 100%); }
.hero__clip, .hero__canvas { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 4%, #000 78%, transparent); mask-image: linear-gradient(180deg, transparent, #000 4%, #000 78%, transparent); }
.hero__canvas { opacity: 0; }
.hero.is-drawn .hero__canvas { opacity: 1; }
.hero.is-drawn .hero__clip { opacity: 0; }   /* the poster hands over once the first sheet is drawn */
.hero__copy .d-lg { font-size: clamp(32px, 1.2rem + 2.1vw, 55px); line-height: 1.1; max-width: 22ch; }   /* the definition: display-lg's cap, a size down at narrower columns so it stays three lines, with air (owner, round 11) */
.hero__copy .lead { margin-top: 28px; max-width: 50ch; }
/* what you get: the same caption mechanics as the chapters, without the numerals */
.captions--hero { gap: 10px; margin-top: 36px; }
.captions--hero .caption > span { display: block; font-size: 17px; line-height: 1.5; color: var(--shade-40); max-width: 52ch; text-wrap: pretty; }
.captions--hero b { color: var(--on-dark); font-weight: 700; }
.hero .stores { margin-top: 36px; }
.hero .badge img { height: 48px; }
.hero .close__free { margin-top: 12px; }
.cue { position: absolute; left: 50%; bottom: 22px; transform: translateX(-50%); display: inline-flex; align-items: center; gap: 6px; font-family: var(--mono); font-size: 12px; font-weight: 500; letter-spacing: .08em; text-transform: uppercase; color: var(--shade-40); }
.cue:hover { color: var(--on-dark); }
@media (min-width: 900px) {
  /* the text on the left, the film on the right and as big as the viewport's height allows (owner, round 10) */
  .hero__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr); gap: clamp(40px, 5vw, 72px); align-items: center; padding-block: 16px 44px; }
  .hero__copy { order: -1; }
  .hero__film { max-width: calc((100vh - var(--nav-h) - 64px) * 4 / 3); }
  /* the pin: one viewport, held for --hn steps of scroll while the film scrubs and the offers step */
  .js .hero { height: calc(100vh + (var(--hn, 4) + var(--hold, 0)) * var(--step)); }   /* --hold: steps the last frame stays before the story */
  .js .hero__pin { position: sticky; top: 0; height: 100vh; }
}
@media (min-width: 900px) and (max-width: 1439px) {
  .hero__film { transform: scale(1.14); transform-origin: 55% 50%; }   /* the figure a little bigger at mid widths (round 22: "the side guy can be a bit bigger"); the film's floor is transparent, so the frame may grow past its column */
}
@media (max-width: 899px) {
  /* Phones (round 18): the same block as on wide screens, stacked — the film band on top, the copy under it with
     the offers stepping sideways — pinned for the same steps, so nothing scrolls under the band and nothing
     scrolls vertically while the reader is here. No Play badge (the nav has it). */
  .js .hero { height: calc(100vh + (var(--hn, 4) + var(--hold, 0)) * var(--step)); z-index: 6; }   /* above the story's band (5): the outgoing block is ON TOP while it thins, as in the app's Mist; the nav (20) stays over both */
  .js .hero__pin { position: sticky; top: 0; height: 100vh; align-items: start; }
  .hero__grid { gap: 22px; padding-block: 8px 24px; align-content: start; }
  .hero__film { width: min(100vw, 36vh * 4 / 3); margin-inline: calc((100% - min(100vw, 36vh * 4 / 3)) / 2); max-width: none; }   /* full-bleed on tall phones (out past the gutters), capped and centred on short ones, still 4:3 */
  .hero__copy .d-lg { font-size: clamp(28px, 8.5vw, 34px); }
  .hero__copy .lead { margin-top: 16px; font-size: 15px; line-height: 1.5; }
  .captions--hero { margin-top: 20px; }
  .captions--hero .caption > span { font-size: 15px; }
  .hero .stores { display: none; }
  .cue { display: none; }
  /* the seam (round 22): at the seam the hero block turns to mist BY ITSELF - the app's Mist, 900 ms on FastOutLinearIn,
     thinning, blurring, lifting, sliding left - while the story's phone and copy, pinned beneath, wait 200 ms and settle in
     on the house curve. main.js only flips the classes at a line one step before the hero's end (round 22; owner: "dont let
     us pause the scroll to these merge point … make it transition quick and smooth"). */
  .js .hero__pin { transition: transform var(--mist) var(--ease-out-in), opacity var(--mist) var(--ease-out-in), visibility 0s; will-change: transform, opacity; }
  .js .hero__grid { transition: filter var(--mist) var(--ease-out-in); will-change: filter; }
  .js .hero.is-past .hero__pin { transform: translateX(-20vw) translateY(-20px) scale(1.03); opacity: 0; visibility: hidden; transition-delay: 0s, 0s, var(--mist); }   /* hidden once the mist is done: no stolen taps */
  .js .hero.is-past .hero__grid { filter: blur(14px); }
}

/* ── Story: sticky phone + chapters ─────────────────────────── */
.story { padding-top: 0; overflow-x: clip; }   /* clip, not hidden (the pins must still stick): the phone's light may spill past its column, never widen the page */
#contrast .lede { margin-top: 24px; margin-bottom: 48px; }
#numbers { padding-top: var(--air); }   /* the numbers under the contrast copy, the old section gap kept */
.story__grid { display: grid; gap: 40px; }
@media (min-width: 900px) {
  .story__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); gap: clamp(48px, 6vw, 96px); align-items: start; }
}
/* device height = 2.082 × width: the screen is (pw − 2 × pw·12/340) × 2337/1080, plus the two paddings */
.device__note { margin-top: 14px; font-size: 12px; color: var(--shade-40); text-align: center; }
.story__phone { position: sticky; top: max(var(--nav-h), calc(var(--nav-h) + (100vh - var(--nav-h) - var(--pw) * 2.082 - 54px) / 2)); display: flex; flex-direction: column; align-items: center; }
.device {
  width: var(--pw); padding: calc(var(--pw) * 12 / 340); border-radius: calc(var(--pw) * 48 / 340); background: var(--night-2);
  box-shadow: inset 0 1px 0 var(--sheen), 0 0 0 1px var(--hair-dark); position: relative; z-index: 0;   /* z-index: the torch's -1 stays inside the phone's own stack */
}
/* the studio light behind the phone (round 28; owner: "try to put studio light kind of light behind the mobile"; it
   replaces round 22's small torch): a key glow taller than wide and brighter above centre - mostly behind the device, a
   soft halo around it - a softbox spill from above, and a floor bounce; cosine falloffs; it moves with the phone and may
   spill past the phone's column (the section clips sideways, so the page never widens) */
.device::before { content: ""; position: absolute; inset: -60% -70%; z-index: -1; pointer-events: none;   /* the box is generous and every layer ends inside it: a gradient larger than its box is cut flat at the edge (round 28b: "this artifacting does not look right") */
  background:
    radial-gradient(ellipse 34% 43% at 50% 42%, rgba(226,232,255,0.1400) 0%, rgba(226,232,255,0.1366) 10%, rgba(226,232,255,0.1266) 20%, rgba(226,232,255,0.1111) 30%, rgba(226,232,255,0.0916) 40%, rgba(226,232,255,0.0700) 50%, rgba(226,232,255,0.0484) 60%, rgba(226,232,255,0.0289) 70%, rgba(226,232,255,0.0134) 80%, rgba(226,232,255,0.0034) 90%, rgba(226,232,255,0.0000) 100%),
    radial-gradient(ellipse 44% 13% at 50% 14%, rgba(226,232,255,0.0600) 0%, rgba(226,232,255,0.0585) 10%, rgba(226,232,255,0.0543) 20%, rgba(226,232,255,0.0476) 30%, rgba(226,232,255,0.0393) 40%, rgba(226,232,255,0.0300) 50%, rgba(226,232,255,0.0207) 60%, rgba(226,232,255,0.0124) 70%, rgba(226,232,255,0.0057) 80%, rgba(226,232,255,0.0015) 90%, rgba(226,232,255,0.0000) 100%),
    radial-gradient(ellipse 34% 8% at 50% 91%, rgba(226,232,255,0.0400) 0%, rgba(226,232,255,0.0390) 10%, rgba(226,232,255,0.0362) 20%, rgba(226,232,255,0.0318) 30%, rgba(226,232,255,0.0262) 40%, rgba(226,232,255,0.0200) 50%, rgba(226,232,255,0.0138) 60%, rgba(226,232,255,0.0082) 70%, rgba(226,232,255,0.0038) 80%, rgba(226,232,255,0.0010) 90%, rgba(226,232,255,0.0000) 100%); }
.device__screen { position: relative; aspect-ratio: 1080 / 2337; border-radius: calc(var(--pw) * 38 / 340); overflow: hidden; background: var(--screen); }   /* the status bar is cropped out of the clips */
.frame { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; visibility: hidden; z-index: 0; background: var(--screen); }   /* hidden, not just clear: the loops among them stop decoding until shown */
.frame.is-on, .frame.is-off { visibility: visible; }
/* the app's Mist: the outgoing screen on top, turning to mist; the incoming one settling in beneath it
   (dp → px through the phone's width: the app's screen is 411dp wide, ours --pw) */
.frame.is-on { opacity: 1; z-index: 1; animation: mist-in calc(var(--mist) - var(--mist-delay)) var(--ease) var(--mist-delay) both; }
.frame.is-off { z-index: 2; animation: mist-out var(--mist) var(--ease-out-in) forwards; }   /* held by main.js for --mist, then dropped */
@keyframes mist-in { from { opacity: 0; filter: blur(calc(var(--pw) * 10 / 411)); transform: scale(.985); } to { opacity: 1; filter: blur(0); transform: none; } }
@keyframes mist-out { from { opacity: 1; filter: blur(0); transform: none; } to { opacity: 0; filter: blur(calc(var(--pw) * 24 / 411)); transform: scale(1.03) translateY(calc(var(--pw) * -20 / 411)); } }
.device { cursor: pointer; user-select: none; -webkit-user-select: none; }
.device:focus-visible { outline: 2px solid var(--on-dark); outline-offset: 6px; }
/* one dot per screen; the lit one is the screen showing */
.dots { display: flex; gap: 6px; justify-content: center; margin-top: 14px; min-height: 8px; }
.dot { width: 6px; height: 6px; border-radius: 50%; background: var(--shade-60); border: 0; padding: 0; cursor: pointer; transition: background-color .25s var(--ease), transform .25s var(--ease); }
.dot.is-on { background: var(--on-dark); transform: scale(1.35); }
.dot:focus-visible { outline: 2px solid var(--on-dark); outline-offset: 3px; }
/* the captions: one row per screen, the lit row is the screen showing; press a row to show it.
   On wide screens with JS only the lit one is on show, sliding in from the side of the scroll. */
.captions { display: grid; gap: 2px; margin-top: 22px; counter-reset: step; }
.step { display: grid; grid-template-columns: 22px 1fr; gap: 12px; align-items: baseline; width: 100%; text-align: left; background: none; border: 0; padding: 8px 10px 8px 6px; margin-inline: -6px; border-radius: 12px; color: var(--shade-40); font: inherit; font-size: 16px; line-height: 1.45; cursor: pointer; transition: background-color .25s var(--ease), color .25s var(--ease); }
.step::before { counter-increment: step; content: counter(step, decimal-leading-zero); font-family: var(--mono); font-size: 12px; color: var(--shade-60); transform: translateY(-1px); }
.step > span { display: block; }
.step b { color: var(--on-dark); font-weight: 700; }
.step:hover { color: var(--on-dark); }
.step.is-on { background: rgba(255, 255, 255, .06); color: var(--on-dark); }
.step.is-on::before { color: var(--accent-dark); }
.step:focus-visible { outline: 2px solid var(--on-dark); outline-offset: 2px; }
.story__chapters { display: grid; }
/* One pinned block for the whole story: every chapter's copy stacked in one cell, the active one on
   show; a chapter change slides sideways exactly as a caption does, so nothing scrolls vertically
   while the phone is pinned (owner, round 11). The empty .chapter spacers give the scroll its length. */
.story__pin { display: grid; align-content: center; gap: 16px; --slide-x: 64px; }   /* the copy centred beside the phone (the row is the tallest chapter's, so the title keeps one y) */
.chapter__copy { display: grid; gap: 16px; align-content: start; }
.chapter__copy .d-xl { max-width: 14ch; }
.chapter { display: none; }
/* Scroll-driven at every width: the block pins under the nav for the story's whole length — one --step per still,
   plus one step's hold at the end — while main.js maps the scroll position to chapter, still and caption. */
.js .story__pin { position: sticky; top: var(--nav-h); height: calc(100vh - var(--nav-h)); }
.js .chapter { display: block; height: calc(var(--n, 5) * var(--step)); }
.js .story__chapters::after { content: ""; display: block; height: calc((1 + var(--lead, 0)) * var(--step)); }   /* the lead in (the first still held) and the last still's hold - in-flow content, not padding: a sticky child may not
   enter its parent's padding, so padding would have let the copy go a hold early while the phone stayed (round 20) */
/* slides: the children of a .slides container share one cell; only .is-on shows, entering from the side of
   travel while the outgoing one leaves the other way (the captions, the hero's offers, the chapter blocks) */
.js .slides { display: grid; gap: 0; overflow: hidden; }   /* hidden slides wait beyond the edge; clipped, they never widen the page */
/* the app's onboarding step: in from --slide-x on the side of travel with a short linear fade, out only a third
   of that the other way with the same short fade, both on the step curve — the two texts barely overlap */
.js .slides > .slide { grid-area: 1 / 1; opacity: 0; visibility: hidden; transform: translateX(var(--slide-x, 48px)); }
.js .slides > .slide.is-on { opacity: 1; visibility: visible; transform: none; transition: transform var(--slide) var(--ease-step), opacity var(--slide-fade) linear; }
.js .slides > .slide.is-off { opacity: 0; visibility: visible; transform: translateX(calc(var(--slide-x, 48px) / -3)); transition: transform var(--slide) var(--ease-step), opacity var(--slide-fade) linear, visibility 0s var(--slide); }
.js .slides[data-dir="back"] > .slide { transform: translateX(calc(-1 * var(--slide-x, 48px))); }
.js .slides[data-dir="back"] > .slide.is-off { transform: translateX(calc(var(--slide-x, 48px) / 3)); }
.js .slides[data-dir="back"] > .slide.is-on { transform: none; }   /* the attribute selector outweighs .is-on alone */
.js .step { font-size: 17px; padding: 6px 0; margin: 0; }
.js .step.is-on { background: none; }
@media (max-width: 899px) {
  :root { --pw: min(270px, 58vw, calc((100vh - 435px) / 2.082)); --band: calc(var(--pw) * 2.082 + 40px); }   /* the phone as big as the copy under it allows (round 24: "lot of space between dots, can we make the mobile bigger?"): 435 = nav 72 + the band's 40 of padding and dots + a 323px budget for the tallest chapter copy (291px at 412 wide) with a 32px floor; --band: the phone's band — its padding and the dots (no note on phones) */
  /* Phones (round 18): the phone is a band under the nav and the chapter copy pins under the band, the captions
     and the chapter blocks stepping sideways exactly as on wide screens; the story starts a step early so its
     block is already pinned beneath the hero's while that slides out (the seam). */
  .js .story { margin-top: calc(-1 * (200vh - 2 * var(--nav-h) - var(--band) + 1.5 * var(--step))); }   /* early enough that the band AND the copy are stuck beneath the hero half a step before the seam line (the copy's pin sits under the band, so it needs the band's whole flow height to pass first) */
  .js .hero.is-past .hero__pin { visibility: hidden; }   /* once the seam is done the block, though transparent, must not sit over the phone's taps */
  .story__grid { gap: 0; }
  .story__phone { position: sticky; top: var(--nav-h); z-index: 5; padding-block: 12px calc(100vh - var(--nav-h) - var(--band)); margin-inline: calc(-1 * var(--gutter)); pointer-events: none; }   /* no veil (round 19); the band's box runs to the viewport's foot, where the copy's box ends too, so the two un-stick on the same pixel and leave together (round 20: "the last pointers scroll behind the phone") - the tail is empty and lets taps through */
  .js .story__phone > * { pointer-events: auto; }
  .device__note { display: none; }   /* owner, round 19: "in mobile get rid of have a taste of UI" */
  .dots { margin-top: 10px; }
  .js .story__pin { top: calc(var(--nav-h) + var(--band)); height: calc(100vh - var(--nav-h) - var(--band)); gap: 10px; --slide-x: 48px; align-content: start; }   /* the copy right under the dots; the slack, if any, below the text (round 24) */
  .chapter__copy { gap: 10px; }
  .chapter__copy .d-xl { font-size: clamp(26px, 7.5vw, 32px); max-width: 16ch; }
  .chapter__copy .lead { font-size: 14px; line-height: 1.45; margin-top: 0; }
  .captions { margin-top: 6px; }
  .js .step { font-size: 14px; padding: 4px 0; }
  /* the incoming side of the seam (mist-in: from 48px right, a hair small, the copy from a blur), and the outgoing side of the
     next one (the story mists out to the left as the numbers block arrives, round 22); the band's children - the phone AND
     its dots - go together (round 23: "the previous slide dots are artifacting here" - the dots had stayed over the numbers) */
  .js .story__phone > *, .js .story__pin { transition: transform calc(var(--mist) - var(--mist-delay)) var(--ease) var(--mist-delay), opacity calc(var(--mist) - var(--mist-delay)) var(--ease) var(--mist-delay), filter calc(var(--mist) - var(--mist-delay)) var(--ease) var(--mist-delay); will-change: transform, opacity; }
  .js .story:not(.is-in) .story__phone > *, .js .story:not(.is-in) .story__pin { transform: translateX(48px) scale(.985); opacity: 0; }
  .js .story:not(.is-in) .story__pin { filter: blur(8px); }
  .js .story.is-out .story__phone > *, .js .story.is-out .story__pin { transform: translateX(-20vw) translateY(-20px) scale(1.03); opacity: 0; visibility: hidden; transition: transform var(--mist) var(--ease-out-in), opacity var(--mist) var(--ease-out-in), filter var(--mist) var(--ease-out-in), visibility 0s var(--mist); }
  .js .story.is-out .story__pin { filter: blur(14px); }
  .js .story__chapters { overflow-x: clip; }   /* clip, not hidden: no scroll container, so the pin still sticks */
}
@media (max-width: 899px) and (max-height: 720px) {   /* a short phone: the film smaller and the ledes give way so each block fits its viewport */
  .hero__film { width: min(100vw, 31vh * 4 / 3); margin-inline: calc((100% - min(100vw, 31vh * 4 / 3)) / 2); }
  .hero__copy .lead { font-size: 14px; }
  .chapter__copy .lead { display: none; }
  :root { --pw: min(270px, 58vw, calc((100vh - 340px) / 2.082)); }   /* the chapter copy is 204px here (no lede), so the phone gets the rest */
}

/* ── Features page: copy beside one still, nine times ───────── */
.page__intro { padding-top: calc(var(--air) * .55); }
.feat { padding-top: var(--air); overflow-x: clip; }   /* the phone's light may spill past its column, never widen the page */
.feat__grid { display: grid; gap: 40px; align-items: center; }
.feat__copy p { color: var(--shade-40); font-size: 17px; line-height: 1.55; max-width: 56ch; margin-top: 18px; text-wrap: pretty; }
.feat__copy .d-lg + p { margin-top: 24px; }
.facts { display: grid; gap: 10px; margin-top: 26px; color: var(--shade-40); font-size: 16px; line-height: 1.5; max-width: 56ch; text-wrap: pretty; }
.facts li { display: flex; gap: 12px; align-items: baseline; }
.facts li::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--accent-dark); flex: none; transform: translateY(-3px); }
.facts b { color: var(--on-dark); font-weight: 700; }
.feat__phone { --pw: min(280px, 60vw); display: flex; justify-content: center; }
.device--still { cursor: default; }
.link--dark { color: var(--shade-40); } .link--dark:hover { color: var(--on-dark); }
@media (min-width: 900px) {
  .feat__grid { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: clamp(48px, 6vw, 96px); }
  .feat__phone { --pw: min(280px, 24vw); }
}
.faq__group { margin-top: 56px; font-size: 22px; }
.faq .lead { max-width: 60ch; }
.faq .stores--track { margin-top: 56px; }

/* ── The close ───────────────────────────────────────────────── */
.close { padding-block: var(--air); text-align: left; }
.close .d-xxl { max-width: 13ch; text-wrap: balance; }
.close .accent { white-space: nowrap; }
.close .stores { margin-top: 40px; }
.close__free { margin-top: 18px; font-size: 14px; font-weight: 600; color: var(--shade-40); }

/* ── Figures, monumental ────────────────────────────────────── */
.figs { display: grid; gap: 40px; border-top: 1px solid var(--hair-dark); padding-top: 48px; }
@media (min-width: 900px) { .figs { grid-template-columns: repeat(4, 1fr); gap: 32px; } }
@media (max-width: 899px) {
  /* Phones (round 21; owner: "this section should also come sideways in mobile, like it was done for 1st and 2nd
     section"): the block pins under the nav for four steps and the four figures step in sideways, one at a time -
     main.js gives the list the slide classes there and maps the scroll to the figure. */
  .js #contrast { height: calc(100vh + 5 * var(--step)); padding-top: 0; margin-top: calc(-1 * (100vh - var(--nav-h) + var(--step))); overflow-x: clip; }   /* starts a viewport and a step early, so its pin is stuck under the story's half a step before that mists out (round 22); the pin travels five steps - the first is the arrival (the story's mist, round 23: the first figure had only a third of a step), then one per figure; clip: the waiting block sits 48px right */
  .js .stats__pin { transition: transform calc(var(--mist) - var(--mist-delay)) var(--ease) var(--mist-delay), opacity calc(var(--mist) - var(--mist-delay)) var(--ease) var(--mist-delay), filter calc(var(--mist) - var(--mist-delay)) var(--ease) var(--mist-delay); }
  .js #contrast:not(.is-in) .stats__pin { transform: translateX(48px) scale(.985); opacity: 0; filter: blur(8px); pointer-events: none; }
  /* the block's own seam into the close (round 34): the block mists out to the left as the close, pinned beneath, settles in */
  .js #contrast { position: relative; z-index: 3; }
  .js #contrast.is-out .stats__pin { transform: translateX(-20vw) translateY(-20px) scale(1.03); opacity: 0; visibility: hidden; filter: blur(14px); pointer-events: none;
    transition: transform var(--mist) var(--ease-out-in), opacity var(--mist) var(--ease-out-in), filter var(--mist) var(--ease-out-in), visibility 0s var(--mist); }
  .js .close { position: relative; z-index: 2; height: calc(100vh + 4 * var(--step)); margin-top: calc(-1 * (100vh - var(--nav-h) + 2 * var(--step))); padding: 0; overflow-x: clip; }   /* starts a viewport and two steps early, so its pin is stuck under the numbers block well before that mists out (at 1.5 steps it stuck 6px late); four steps of travel: it arrives at ~.29 of them, mists out to the footer at .6, and never un-pins - the page ends first (round 36) */
  .js .close__grid { position: sticky; top: var(--nav-h); height: calc(100vh - var(--nav-h)); align-content: start; padding-top: 4vh;   /* the film and the call up, the slack below (round 36: "pull the video and text a bit above as there is space") */
    transition: transform calc(var(--mist) - var(--mist-delay)) var(--ease) var(--mist-delay), opacity calc(var(--mist) - var(--mist-delay)) var(--ease) var(--mist-delay), filter calc(var(--mist) - var(--mist-delay)) var(--ease) var(--mist-delay); }
  .js .close:not(.is-in) .close__grid { transform: translateX(48px) scale(.985); opacity: 0; filter: blur(8px); pointer-events: none; }
  /* the close's own seam into the footer (round 36; owner: "from here even to go to footer same sideway swipe as it is for every
     section"): at .6 of the close's travel it mists out to the left and the footer - a pinned screen beneath, which the page
     ends on - settles in. A sticky footer that is the last thing on the page can never be scrolled past its own stick point,
     so the footer's box is a step and a half taller than its pin: that is the hold after the seam. */
  .js .close.is-out .close__grid { transform: translateX(-20vw) translateY(-20px) scale(1.03); opacity: 0; visibility: hidden; filter: blur(14px); pointer-events: none;
    transition: transform var(--mist) var(--ease-out-in), opacity var(--mist) var(--ease-out-in), filter var(--mist) var(--ease-out-in), visibility 0s var(--mist); }
  .js .footer--seam { position: relative; z-index: 1; height: calc(100vh - var(--nav-h) + 2.5 * var(--step)); margin-top: calc(-1 * (100vh - var(--nav-h) + 2.5 * var(--step))); border-top: 0; padding: 0; overflow-x: clip; }   /* only after a close (main.js sets the class on the landing page); its box ends exactly where the close's does, so the page ends with the footer's pin still stuck; clip: the waiting pin sits 48px right */
  .js .footer--seam .footer__pin { position: sticky; top: var(--nav-h); height: calc(100vh - var(--nav-h)); box-sizing: border-box; padding: 40px 0 24px; display: grid; align-content: start;
    transition: transform calc(var(--mist) - var(--mist-delay)) var(--ease) var(--mist-delay), opacity calc(var(--mist) - var(--mist-delay)) var(--ease) var(--mist-delay), filter calc(var(--mist) - var(--mist-delay)) var(--ease) var(--mist-delay); }
  .js .footer--seam:not(.is-in) .footer__pin { transform: translateX(48px) scale(.985); opacity: 0; filter: blur(8px); pointer-events: none; }
  .js .stats__pin { position: sticky; top: var(--nav-h); height: calc(100vh - var(--nav-h)); display: grid; align-content: center; gap: 0; }
  .js .stats__pin { text-align: center; justify-items: center; }   /* round 25 (owner: "would this look better center aligned?"): one centred column - heading, lede, figure, badge, line */
  .js #contrast .d-xxl, .js #contrast .lede { margin-inline: auto; }   /* both carry a max-width */
  .js #contrast .d-xxl { font-size: 44px; }
  .js #contrast .lede { font-size: 16px; margin-top: 18px; margin-bottom: 36px; }
  .js #numbers { padding-top: 0; }
  /* round 23 ("these numbers and what they denote can come in central aligned and in better sizing"): the lit figure and
     its caption centred in the shared cell, the number nearly a quarter of the width, the caption one size up */
  .js .figs { border-top: 0; padding-top: 0; --slide-x: 48px; justify-items: center; text-align: center; }
  .js .figs dt { font-size: clamp(64px, 22vw, 92px); }
  .js .figs dd { font-size: 16px; line-height: 1.45; margin: 12px auto 0; max-width: 24ch; }
  /* the close on phones (round 33; owner: "in mobile i cant see the 4th section where i can see that 3mins thingy" - round 24
     had folded its badge and line into the numbers block and hidden it): one column, centred - the film on top, capped like
     the hero's, then the call, the badge and the line */
  .close { padding-block: 40px 72px; text-align: center; }
  .close__grid { display: grid; gap: 24px; justify-items: center; }
  .close__copy { display: grid; justify-items: center; }
  .close__film { order: -1; position: relative; aspect-ratio: 4 / 3; width: min(100%, 40vh * 4 / 3); isolation: isolate; }   /* 40vh (round 36: the spare room under the nav goes to the figure) */
  .close .d-xxl { font-size: clamp(34px, 9.6vw, 44px); max-width: none; }
  .close .stores { margin-top: 28px; justify-content: center; }
  .close__free { font-size: 13px; margin-top: 14px; }
}
@media (max-width: 899px) and (max-height: 720px) {   /* a short phone: the pinned numbers block still fits its pin */
  .js #contrast .lede { margin-top: 14px; margin-bottom: 28px; }
}
@media (max-width: 899px) and (max-height: 720px) { .js .figs dt { font-size: 64px; } }   /* a short phone: the pinned block (the heading, the lede, the figure, the badge) still fits its pin */
.figs dt { font-size: clamp(56px, 2.4rem + 3.6vw, 96px); line-height: 1; letter-spacing: -0.03em; }
.figs dt.fig-word, .js .figs dt.fig-word { font-family: var(--font); font-weight: 800; letter-spacing: -0.02em; line-height: 1.05; font-size: clamp(34px, 10vw, 46px); }   /* round 40: plain promises in the headline face, not figures in the mono (owner: "normal people dont understand these type of numerical jargons") */
@media (min-width: 900px) { .js .figs dt.fig-word, .figs dt.fig-word { font-size: clamp(26px, 2.4vw, 38px); } }
.figs dd { color: var(--shade-40); margin-top: 16px; font-size: 14px; line-height: 1.5; max-width: 26ch; text-wrap: pretty; }
@media (min-width: 900px) {
  /* Wide screens (round 27; owner: "in desktop this should be the 3rd section that goes sideways: first the texts, then
     numbers stuff one by one … 2,400+ will come slide from side and its text pops up from below it, then 6 comes and
     pushes 2,400+ towards left while it itself takes mid … by end all 4 numbers are there with their text"): the block
     pins under the nav for five steps; the heading and lede step in from the right as the section arrives; then the
     figures one by one - each a column a quarter of the wrap wide, all in one grid cell, placed by a transform from its
     index --i and the count on show --k (data-k, main.js): the shown ones are a row of k columns centred in the wrap, so
     a newcomer lands right of the axis and the ones before it shift left; at k = 4 the row is the full wrap. */
  .js #contrast { height: calc(100vh + 5 * var(--step)); padding-top: 0; overflow-x: clip; }
  .js .stats__pin { position: sticky; top: var(--nav-h); height: calc(100vh - var(--nav-h)); display: grid; align-content: center; }
  .js #contrast .d-xxl { font-size: clamp(44px, 2rem + 3.4vw, 76px); }   /* the pinned block fits a 700px-tall window */
  .js #contrast .lede { margin-bottom: 40px; }
  .js #numbers { padding-top: 0; }
  .js #contrast .d-xxl, .js #contrast .lede { transition: transform var(--slide) var(--ease-step), opacity var(--slide-fade) linear; }
  .js #contrast .lede { transition-delay: 120ms; }
  .js #contrast:not(.is-in) .d-xxl, .js #contrast:not(.is-in) .lede { transform: translateX(48px); opacity: 0; }
  .js .figs { grid-template-columns: 1fr; gap: 0; padding-top: 40px; }
  .js .figs > div { grid-area: 1 / 1; width: 25%; justify-self: start; text-align: center; --i: 0; --k: 0;
    transform: translateX(calc((4 - var(--k)) / 2 * 100% + var(--i) * 100%)); transition: transform var(--slide) var(--ease-step), opacity var(--slide-fade) linear; }
  .js .figs > div:nth-child(2) { --i: 1; }
  .js .figs > div:nth-child(3) { --i: 2; }
  .js .figs > div:nth-child(4) { --i: 3; }
  .js .figs[data-k="1"] > div { --k: 1; }
  .js .figs[data-k="2"] > div { --k: 2; }
  .js .figs[data-k="3"] > div { --k: 3; }
  .js .figs[data-k="4"] > div { --k: 4; }
  /* not yet on show: 40 % of a column further right, unseen; it slides in from there when its turn comes */
  .js .figs > div.is-out { transform: translateX(calc((4 - var(--k)) / 2 * 100% + var(--i) * 100% + 40%)); opacity: 0; }
  .js .figs dt { font-size: clamp(48px, 5.2vw, 72px); }   /* 2,400+ (3.6 em in the mono) inside a quarter of the wrap */
  .js .figs dd { margin-inline: auto; font-size: 15px; max-width: 24ch; transition: transform var(--slide) var(--ease-step) 260ms, opacity .3s linear 260ms; }   /* the caption from below, once the number has landed */
  .js .figs > div.is-out dd { transform: translateY(14px); opacity: 0; transition-delay: 0s; }
  /* the close's film (round 31; owner: "here right add this video like done above … this video was supposed to be right of
     12 questions 3 mins"): the copy left, the push-ups on the right - the floor keyed to the tint and a backlight behind it
     as in the hero; it plays while the close is in view (main.js) */
  .close__grid { display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); gap: clamp(40px, 5vw, 80px); align-items: center; }
  .close__film { position: relative; aspect-ratio: 4 / 3; width: 100%; justify-self: end; isolation: isolate; transform: scale(1.22); transform-origin: 50% 55%; }   /* the figure bigger (round 32: "make him bit bigger on desktop"): the film's floor is transparent, so its frame may grow past its column; the section clips sideways */
  .close .d-xxl { font-size: clamp(36px, 1.2rem + 3.6vw, 72px); max-width: none; }   /* a little smaller than the other displays, so "12 questions." holds its first line beside the film (round 32) */
}
.close__film::before { content: ""; position: absolute; inset: -30% -30%; z-index: -1; pointer-events: none;
    background: radial-gradient(ellipse 30% 40% at 50% 48%, rgba(226,232,255,0.1100) 0%, rgba(226,232,255,0.1073) 10%, rgba(226,232,255,0.0995) 20%, rgba(226,232,255,0.0872) 30%, rgba(226,232,255,0.0715) 40%, rgba(226,232,255,0.0550) 50%, rgba(226,232,255,0.0385) 60%, rgba(226,232,255,0.0228) 70%, rgba(226,232,255,0.0105) 80%, rgba(226,232,255,0.0027) 90%, rgba(226,232,255,0) 100%); }
.film__poster, .film__canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.film__canvas { opacity: 0; }
.close__film.is-drawn .film__canvas { opacity: 1; }
.close__film.is-drawn .film__poster { opacity: 0; }   /* the poster hands over once the first sheet is drawn */
.close { overflow-x: clip; }   /* the backlight may not widen the page */
@media (min-width: 900px) {
  .js .close { padding-top: max(64px, calc(var(--air) * .25)); }
}

/* ── Light track: porcelain, black pills, rose featured tier ── */
/* The pages' track (round 35; owner: "apply same colour and background page schemes in plans and FAQ pages too, as they
   are light coloured now"): plans.html and faq.html sit on the same tint, glows and grain as the landing page. They were
   the porcelain track (rounds 1-34: a pale ground "for the parts where the reader decides"); the components keep their
   tokens and the track sets them for the dark ground - the tiers a hair of white over the tint with the dark hairline,
   the featured tier a rose tint, the accent the dark track's rose. */
.track { --ink: var(--on-dark); --ink-2: var(--shade-40); --paper: rgba(255, 255, 255, .045); --hair-light: var(--hair-dark); --rose-fill: rgba(203, 124, 130, .13); --accent-light: var(--accent-dark);
  margin-top: 0; min-height: 100vh; color: var(--on-dark); color-scheme: dark; padding-bottom: var(--air); }
.track .accent { color: var(--accent-dark); }
.track .lead { color: var(--shade-40); }
.track :focus-visible { outline-color: var(--on-dark); }
.free-start { margin-top: 40px; padding: 20px 24px; border-radius: 12px; background: var(--paper); border: 1px solid var(--hair-light); color: var(--ink-2); font-size: 16px; line-height: 1.5; }   /* round 41: the free week said once, above the paid plans (owner: "this is just a demo plan, do we need to put this up as one of our paid plans?") */
.free-start b { color: var(--accent-dark); }
.free-start + .tiers { margin-top: 16px; }
.legal .wrap--narrow { max-width: 600px; }   /* round 48: the reading column itself centred on the page (was 60ch hugging the left of a 760px wrap) */
.legal .lead { max-width: none; }   /* round 45: the legal pages, held while their texts are reviewed */
.legal .held { margin-top: 40px; padding: 20px 24px; border-radius: 12px; background: var(--paper); border: 1px solid var(--hair-light); color: var(--ink-2); font-size: 16px; line-height: 1.5; }
.legal .held b { color: var(--accent-dark); }
.legal .steps-list { margin: 32px 0 0; padding-left: 1.4em; list-style: decimal; display: grid; gap: 12px; font-size: 18px; line-height: 1.5; color: var(--ink-2); }
.legal .steps-list b { color: var(--ink); }
.legal .steps-list li::marker { color: var(--accent-dark); font-weight: 700; }
.legal .steps-list + .held { margin-top: 32px; }
.legal .prose { max-width: none; }   /* round 46: refunds filled - Google Play's own process, no promises of ours */
.legal .prose h2 { margin-top: 48px; font-size: 22px; }
.legal .prose p { margin-top: 12px; font-size: 17px; line-height: 1.6; color: var(--ink-2); }
.legal .stores--track { margin-top: 48px; }   /* round 47: the About page ends on the badge, like the FAQ */
:root { --mint: #5fd3a0; }   /* the app's go-ahead green (its ticks and filled sliders) */
.track .compare thead th:first-child, .track .compare tbody th { background: #131315; }   /* the sticky column needs an opaque ground over what scrolls under it */
.tiers { display: grid; gap: 16px; margin-top: 48px; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }   /* five tiers since round 38 (the app's Pricing v3): as many columns as fit */
.tier { position: relative; background: var(--paper); border-radius: 12px; padding: 32px 28px; display: grid; gap: 12px; align-content: start; border: 1px solid var(--hair-light);
  box-shadow: 0 8px 8px rgba(0,0,0,.04), 0 4px 4px rgba(0,0,0,.04), 0 2px 2px rgba(0,0,0,.04), 0 0 0 1px rgba(0,0,0,.02); }
.tier h3 { font-size: 22px; }
.tier__sub { color: var(--ink-2); font-size: 14px; line-height: 1.5; }
.price { display: flex; align-items: baseline; gap: 8px; }   /* round 42: USD a month, one line, every card alike */
.price .num { font-size: 36px; line-height: 1; letter-spacing: -0.02em; color: var(--ink); }
.price .alt { font-size: 16px; color: var(--ink-2); }
.price .per { font-size: 14px; color: var(--ink-2); }
.price .twin { display: inline-flex; align-items: baseline; gap: 10px; white-space: nowrap; }
.checks { display: grid; gap: 9px; margin-top: 8px; padding-top: 16px; border-top: 1px solid var(--hair-light); font-size: 14px; line-height: 1.4; color: var(--ink); }
.checks li { display: flex; align-items: baseline; gap: 10px; }
.checks .ico { width: 16px; height: 16px; stroke-width: 2.6; color: var(--accent-light); flex: none; transform: translateY(2px); }
.compare__title { margin-top: 64px; font-size: 22px; }
.compare { margin-top: 20px; overflow-x: auto; contain: paint; -webkit-overflow-scrolling: touch; border: 1px solid var(--hair-light); border-radius: 12px; background: var(--paper); }
.compare table { width: 100%; min-width: 760px; font-size: 14px; }   /* six columns */
.compare th, .compare td { padding: 14px 16px; text-align: left; border-bottom: 1px solid var(--hair-light); vertical-align: middle; }
.compare thead th { font-size: 12px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-2); background: var(--paper); }
.compare thead th:first-child, .compare tbody th { position: sticky; left: 0; background: var(--paper); }
.compare tbody th { font-weight: 600; color: var(--ink); }
.compare tr.group th { padding-top: 22px; font-size: 12px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--accent-light); border-bottom-color: var(--ink); }
.compare td { color: var(--ink); }
.compare td.num { font-size: 14px; }
.compare td.no { color: var(--ink-2); }
.compare td.yes { color: var(--accent-light); }
.compare td.yes .ico { width: 18px; height: 18px; stroke-width: 2.6; }
.compare tbody tr:last-child th, .compare tbody tr:last-child td { border-bottom: 0; }
.foot { margin-top: 20px; color: var(--ink-2); font-size: 14px; display: flex; flex-wrap: wrap; gap: 6px 16px; align-items: center; max-width: 70ch; }
.stores--track { margin-top: 32px; }

.faq__list { margin-top: 36px; border-top: 1px solid var(--hair-light); }
details { border-bottom: 1px solid var(--hair-light); }
summary { list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 20px; padding: 22px 2px; font-weight: 700; font-size: 16px; letter-spacing: -0.01em; }
summary::-webkit-details-marker { display: none; }
summary .ico { color: var(--ink-2); transition: transform .3s var(--ease); }
details[open] summary .ico { transform: rotate(180deg); }
details p { padding: 0 2px 24px; color: var(--ink-2); max-width: 64ch; line-height: 1.55; text-wrap: pretty; }

/* ── Close ──────────────────────────────────────────────────── */

/* ── Footer ─────────────────────────────────────────────────── */
.footer { border-top: 1px solid var(--hair-dark); padding-block: 56px 32px; font-size: 14px; }
.footer__grid { display: grid; gap: 32px; }
@media (min-width: 720px) { .footer__grid { grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: 48px; } }
.footer__tag { color: var(--shade-40); font-style: italic; margin-top: 14px; }   /* round 29: the brand line above it ("RepChef: the plan that checks back.") went - "this is not required" */
.footer nav { display: grid; gap: 10px; align-content: start; }
.footer nav a { color: var(--shade-40); } .footer nav a:hover { color: var(--on-dark); text-decoration: underline; text-underline-offset: 4px; }
.footer h4 { font-size: 12px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--shade-40); margin-bottom: 4px; }
.footer__base { margin-top: 48px; padding-top: 20px; border-top: 1px solid var(--hair-dark); display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px 20px; color: var(--shade-40); font-size: 12px; }
.footer__legal { display: inline-flex; gap: 18px; }
.footer__legal a:hover { color: var(--on-dark); text-decoration: underline; text-underline-offset: 4px; }
.footer nav .badge { margin-top: 2px; }   /* the Download column is the badge (round 30), not a text link */
@media (max-width: 719px) {   /* phones (round 30; owner: "make footer better in mobile"): the brand across, Product and Resources side by side, the badge across, the base stacked */
  .footer { padding-block: 40px 24px; }
  .footer__grid { grid-template-columns: 1fr 1fr; gap: 28px 24px; }
  .footer__brand, .footer nav[aria-label="Download"] { grid-column: 1 / -1; }
  .footer__base { margin-top: 32px; flex-direction: column; gap: 10px; }
}

/* ── Reduced motion ─────────────────────────────────────────── */
/* The OS's reduced-motion setting turns off the decorative motion — smooth scrolling here, the figure sprite
   and the hero's easing in main.js — and the hover/press transitions. The mist and the steps stay: they are
   the product's own transitions and the reader drives every one of them by scrolling (owner, round 13: the
   owner's machine has Windows' animation effects off and saw every change as a cut). */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .pill, summary .ico, .dot, .step { transition: none !important; }
}

/* round 54: the plans page's switches - Monthly | Yearly above the cards, and Trainer Studio's seats (10 / 15 / 25 clients) */
.seg { display: inline-flex; gap: 4px; padding: 4px; border-radius: 999px; background: rgba(255, 255, 255, .06); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .08); }
.seg button { font: inherit; font-size: 14px; font-weight: 700; color: var(--shade-40); background: transparent; border: 0; border-radius: 999px; padding: 8px 16px; min-height: 36px; cursor: pointer; transition: background-color .2s var(--ease), color .2s var(--ease); }
.seg button:hover { color: var(--on-dark); }
.seg button[aria-pressed="true"] { background: var(--on-dark); color: var(--night); }
.seg--billing { display: flex; width: fit-content; margin: 28px auto 0; }   /* centred over the cards (owner, round 55) */
.free-start + .seg--billing + .tiers { margin-top: 20px; }
.seg--seats { margin-top: 2px; justify-self: start; }
.seg--seats { align-items: center; }
.seg--seats button { font-size: 13px; padding: 6px 12px; min-height: 32px; min-width: 40px; }
.seg__label { font-size: 12px; font-weight: 700; color: var(--ink-2); margin-top: 2px; }   /* round 56: the seats' label sits above the switch, so 10 | 15 | 25 | Custom fits a narrow card */
.seg__label + .seg--seats { margin-top: -4px; }
.seat-custom { font-size: 14px; line-height: 1.45; color: var(--ink-2); }
.seat-custom a { color: var(--on-dark); text-decoration: underline; text-underline-offset: 3px; }
.plans-js .seat-custom { display: none; }   /* with script: only when Custom is picked, as a button */
.plans-js .is-custom .seat-custom { display: block; font-size: 0; }
.plans-js .is-custom .seat-custom a { display: inline-flex; align-items: center; min-height: 40px; padding: 10px 18px; border-radius: 999px; font-size: 14px; font-weight: 700; text-decoration: none; background: var(--on-dark); color: var(--night); }
.is-custom .price .per { display: none; }
.is-custom .price .num { font-family: var(--font); font-weight: 800; letter-spacing: -0.03em; }   /* a word, not a figure: the display face */
.price { flex-wrap: wrap; row-gap: 2px; }   /* a long yearly price drops its label to the next line whole */
.price .per { white-space: nowrap; }
.compare td.yes--note .note { display: block; margin-top: 4px; font-size: 12px; color: var(--ink-2); }
@media (prefers-reduced-motion: reduce) { .seg button { transition: none; } }
.seg .save { margin-left: 6px; padding: 2px 8px; border-radius: 999px; font-size: 12px; font-weight: 700; background: rgba(95, 211, 160, .18); color: #8fe0bb; }   /* round 55: the yearly saving, a third off */
.seg button[aria-pressed="true"] .save { background: rgba(15, 15, 16, .12); color: #1f7a55; }

/* round 57 (owner: "show the colours of different cards used in app to show different tiers"): the app's tier metals, from
   its account drawer (AccountDrawer.kt: silver own/engine, gold both, ruby coach), 3 stops top-left to bottom-right, text in
   the tier's ink. Adaptive has a blue tint on the site (owner: "Adaptive can have blueish tint"); the app is plain silver.
   Round 58: the dark cards with a metal band won (owner: "this looks better"); the full-metal variant is gone. */
.tier--tracker  { --m1: #C4C8D0; --m2: #A9AEB8; --m3: #BCC0C8; --mink: #1E2026; --mlight: #D3D6DC; }
.tier--adaptive { --m1: #C3CEDF; --m2: #A2B2CA; --m3: #B9C6D9; --mink: #162131; --mlight: #C4D1E4; }
.tier--pro      { --m1: #D4B662; --m2: #B8973A; --m3: #C9AA52; --mink: #2A1E08; --mlight: #E0C574; }
.tier--trainer  { --m1: #9E2A3C; --m2: #741B2B; --m3: #8C2536; --mink: #FBEDEF; --mlight: #E58A98; }
.tiers[data-cards="accent"] .tier { border-color: color-mix(in srgb, var(--m2) 45%, transparent); overflow: hidden; }
.tiers[data-cards="accent"] .tier::before { content: ""; position: absolute; inset: 0 0 auto; height: 4px; background: linear-gradient(90deg, var(--m1), var(--m2), var(--m3)); }
.tiers[data-cards="accent"] .tier h3 { color: var(--mlight); }
.tiers[data-cards="accent"] .tier .checks .ico { color: var(--mlight); }
.tiers[data-cards="accent"] .tier .checks li::before { background: var(--mlight); }
/* round 57 (owner: "i need the original price slashes to show the new price effect"): in Yearly, twelve months' price struck
   through above the yearly one */
.was { display: none; font-family: var(--mono); font-size: 15px; font-weight: 500; text-decoration: line-through; text-decoration-thickness: 1.5px; opacity: .6; }
.price .was { flex-basis: 100%; margin-bottom: -2px; }
.is-yearly .was:not([hidden]) { display: block; }
.is-custom .was { display: none !important; }
.compare .was { font-size: 12px; margin-bottom: 2px; }

/* round 57b (owner: "this need correction"): a card is never widened by what is in it - the seats switch had set the Trainer
   Studio card's minimum width and pushed "Custom" and the list past its edge. The switch now fills the card in four equal
   parts; prices step down in narrow cards so "a month" stays beside them. */
.tier { min-width: 0; container-type: inline-size; }
.tier__sub, .checks li { overflow-wrap: anywhere; }
.tiers .tier .seg--seats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); width: 100%; }   /* four equal seat bands (tiers v4: 10 / 15 / 25 / 50; the wide "Custom" slot went with the Custom button) */
.tiers .tier .seg--seats button { min-width: 0; padding: 6px 2px; white-space: nowrap; text-align: center; }
.tiers .tier .price .num { white-space: nowrap; }
@container (max-width: 250px) { .tiers .tier .price .num { font-size: 32px; } }
@container (max-width: 215px) { .tiers .tier .seg--seats button { font-size: 12px; } .tiers .tier .price .num { font-size: 29px; } }

/* round 58 (owner: "make the colours of the text look more glossy and shiny cool"): each tier's name in polished metal - a
   bright top highlight, the metal body, a darker reflection band under the middle, a lighter lower edge - clipped to the
   text, with a soft glow in the metal's colour. The darkest stops are lifted so the names read on the dark card. A light
   sweeps across once as the cards scroll in (decorative: not under reduced motion; the static gloss is the finished look). */
.tier--tracker  { --g1: #F5F7FB; --g2: #CDD2DA; --g3: #7C8390; --g4: #DADEE5; --g5: #F7F8FB; }
.tier--adaptive { --g1: #F0F5FC; --g2: #C2CEE0; --g3: #70839F; --g4: #CDD8E8; --g5: #F2F6FC; }
.tier--pro      { --g1: #FFF2C4; --g2: #E8C86E; --g3: #9C7722; --g4: #EDCF77; --g5: #FFF4CF; }
.tier--trainer  { --g1: #FFD6DD; --g2: #E57287; --g3: #A8354B; --g4: #EA8497; --g5: #FFDCE2; }
.tiers[data-cards="accent"] .tier::before { height: 4px; background: linear-gradient(90deg, var(--g3), var(--g1) 28%, var(--g2) 50%, var(--g5) 72%, var(--g3)); box-shadow: 0 0 18px color-mix(in srgb, var(--g2) 45%, transparent); }
.tiers[data-cards="accent"] .tier .checks li::before { background: var(--g2); }
.tiers[data-cards="accent"] .tier .checks .ico { color: var(--g2); }
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .tiers[data-cards="accent"] .tier h3, .compare thead .gloss {   /* round 59: the table's plan names share the cards' gloss */
    background-image: linear-gradient(105deg, transparent 42%, rgba(255, 255, 255, .85) 50%, transparent 58%),
                      linear-gradient(180deg, var(--g1) 0%, var(--g2) 47%, var(--g3) 50%, var(--g4) 78%, var(--g5) 100%);   /* a chrome horizon: bright above, a sharp dark band at the middle */
    background-size: 260% 100%, 100% 100%; background-position: 160% 0, 0 0; background-repeat: no-repeat;
    -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; color: transparent;
    filter: drop-shadow(0 1px 0 rgba(0, 0, 0, .55)) drop-shadow(0 0 14px color-mix(in srgb, var(--g2) 38%, transparent));
  }
  @supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
      .tiers[data-cards="accent"] .tier h3 { animation: tier-sheen linear both; animation-timeline: view(); animation-range: entry 30% cover 45%; }
    }
  }
}
@keyframes tier-sheen { from { background-position: 160% 0, 0 0; } to { background-position: -60% 0, 0 0; } }

/* round 59 (owner: "the colours are not here?"): the comparison table's plan names in their tier metals - the cards' gloss
   (the shared rule above), title case like the cards, and a thin metal line under each tier's header. The free week stays
   plain, as in the app. */
.compare thead th[class*="tier--"] { position: relative; text-transform: none; letter-spacing: -0.01em; font-size: 15px; font-weight: 800; }
.compare thead .gloss { color: var(--mlight); display: inline-block; }
.compare thead th[class*="tier--"]::after { content: ""; position: absolute; left: 16px; right: 16px; bottom: 0; height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, var(--g3), var(--g1) 30%, var(--g2) 50%, var(--g5) 70%, var(--g3)); }
.compare thead th { text-transform: none; letter-spacing: -0.01em; font-size: 15px; font-weight: 800; color: var(--on-dark); }   /* round 59: the whole header in title case, like the cards; the free week plain white */

/* round 60 (owner: "pin the feature names and let columns slide"): phones keep the feature names pinned in a narrow column
   and slide the plan columns under it, snapping one column at a time - two in view and the next peeking, so it reads as
   more to the right. ("main .track" outranks version B's own table padding.) */
@media (max-width: 719px) {
  main .track .compare { scroll-snap-type: x mandatory; scroll-padding-left: 124px; overscroll-behavior-x: contain; }
  main .track .compare table { min-width: 0; width: max-content; font-size: 13px; }
  main .track .compare th, main .track .compare td { padding: 12px 10px; }
  main .track .compare thead th:first-child, main .track .compare tbody th { width: 124px; min-width: 124px; max-width: 124px; white-space: normal; z-index: 1; box-shadow: 10px 0 14px -10px rgba(0, 0, 0, .75); }
  main .track .compare thead th:not(:first-child), main .track .compare td { width: 100px; min-width: 100px; max-width: 100px; }
  main .track .compare thead th:not(:first-child) { scroll-snap-align: start; }
  main .track .compare thead th { font-size: 13px; }
  main .track .compare thead th[class*="tier--"]::after { left: 10px; right: 10px; }
}
.close .nw { white-space: nowrap; }   /* round 61: "Answer a few / questions." rather than "Answer a / few questions." */
