/* ==========================================================================
   Twentyfive — v3 site
   Layout, motion and colour placement from the Claude Design canvas
   "Twentyfive website: mobile-first working copy". Every hex value comes
   from the Twentyfive design system (Figma + DESIGN.md): the canvas decides
   where a colour goes, the design system decides what the colour is.
   ========================================================================== */

@font-face {
  font-family: "Greed";
  src: url("../assets/fonts/GreedCollectionVF-TRIAL.woff2") format("woff2");
  font-weight: 300 900;
  font-stretch: 75% 130%;
  font-style: normal;
  font-display: swap;
}

:root {
  /* brand */
  --brand-primary: #145d24;
  --brand-secondary: #ea5910;
  --brand-tertiary: #00e7ff;
  --brand-quaternary: #f3de2b;
  --green-light: #1c8734;
  --green-dark: #0b3414;

  /* background */
  --bg-default: #fff6eb;
  --bg-surface: #fffaf5;
  --bg-invert: #041106;
  --bg-invert-surface: #061909;

  /* foreground */
  --fg-primary: #041106;
  --fg-secondary: rgba(4, 17, 6, .7);
  --fg-tertiary: rgba(4, 17, 6, .5);
  --fg-invert: #fffaf5;
  --fg-invert-secondary: rgba(255, 255, 255, .7);

  /* borders */
  --border-solid: #041106;
  --border-invert: #fff6eb;
  --border-subtle: rgba(4, 17, 6, .08);

  /* status */
  --status-success: #25b144;
  --status-warning: #f3de2b;

  /* artwork tints (primitive ramps, illustration only) */
  --cyan-light-x3: #99f5ff;

  /* shape */
  --radius-full: 120px;
  --radius-16: 16px;
  --radius-8: 8px;
  --radius-4: 4px;
  --shadow-xs: 0 2px 0 var(--border-solid);
  --shadow-md: 0 4px 0 var(--border-solid);
  --shadow-invert-md: 0 4px 0 var(--fg-invert);
  --shadow-none: 0 0 0 var(--border-solid);

  /* gradient: only behind text on a photo */
  --grad-photo: linear-gradient(to top, rgba(4, 17, 6, .8) 0%, rgba(4, 17, 6, 0) 100%);

  /* type */
  --font: "Greed", "Archivo", "Helvetica Neue", Arial, sans-serif;

  /* motion (canvas rules) */
  --ease: cubic-bezier(.16, 1, .3, 1);
  --rise: 500ms;
  --stamp-delay: 80ms;

  /* layout (design system breakpoints: xs/sm/md 24 · lg 40 · xl 80).
     Phones keep 1.5rem a side too (Rob, 9 Oct 2026): a 393 screen gets a 345 CTA. */
  --gutter: 1.5rem;
  --header-top: 16px;
  --header-h: 40px;
}

@media (min-width: 768px) { :root { --header-top: 24px; --header-h: 48px; } }
@media (min-width: 992px) { :root { --gutter: 40px; --header-top: 40px; } }
@media (min-width: 1200px) { :root { --gutter: 80px; } }
/* Content never runs wider than 100rem: past that the side margin grows and the column centres. */
:root { --content-max: 100rem; }
@media (min-width: 1200px) { :root { --gutter: max(80px, calc((100vw - var(--content-max)) / 2)); } }

/* ---------- base ---------- */

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

/* The page ground: iOS Safari colours its top and bottom bars from it (it no
   longer reads theme-color). The script paints it (and the edge strips) the
   colour of the scene at the top of the screen (each act's data-bars);
   darkest green until then, cream while the intro shows. Every section paints its own ground on top. */
html { -webkit-text-size-adjust: 100%; background: var(--bg-invert); }
/* No rubber-band or pull-to-refresh at the top of the page: it exposed the photo behind the pinned opening scene. */
html, body { overscroll-behavior-y: none; }
html.dbg-nooverscroll, html.dbg-nooverscroll body { overscroll-behavior-y: auto; } /* debug switch */
html:has(body.is-intro), body.is-intro { background: var(--bg-default); }

/* iOS 26 Safari colours its top and bottom bars from a fixed element at that
   edge: within 4px of the top / 3px of the bottom, at least 80% wide and at
   least 3px tall (jahir.dev/blog/safari-toolbar). It reads the background
   colour even at opacity 0, so these strips carry the current scene's colour
   and are never seen. */
.bars-tint { position: fixed; left: 0; right: 0; z-index: 300; height: 4px; background: var(--bg-invert); opacity: 0; pointer-events: none; }
.bars-tint--top { top: 0; }
.bars-tint--bottom { bottom: 0; }
body.is-intro .bars-tint { background: var(--bg-default); }
/* debug switches while the Safari bars are sorted (see the script) */
html.dbg-bhit .bars-tint { pointer-events: auto; }
html.dbg-bfade .bars-tint { opacity: .01; }
html.dbg-btall .bars-tint--top { height: 12px; }

body {
  margin: 0;
  font-family: var(--font);
  font-stretch: 100%;
  font-weight: 400;
  font-size: 16px;
  line-height: 24px;
  color: var(--fg-primary);
  background: var(--bg-invert);
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}

body.is-locked { overflow: hidden; }

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

h1, h2, h3, p, figure, blockquote, ul, ol { margin: 0; }
ul, ol { padding: 0; list-style: none; }

a { color: inherit; }

button { font: inherit; color: inherit; }

:focus-visible { outline: 2px solid var(--brand-secondary); outline-offset: 3px; }

.skip {
  position: absolute; left: 16px; top: -80px; z-index: 200; /* not fixed: Safari would tint the status bar from it */
  height: 48px; padding: 0 24px; display: inline-flex; align-items: center;
  border: 2px solid var(--border-solid); border-radius: var(--radius-full);
  background: var(--bg-default); font-weight: 600; text-decoration: none;
}
.skip:focus { top: 16px; }


/* ---------- type (design system scale) ----------
   Display: wght 900 (Black), wdth 75 (Condensed).
   Heading: wght 700, wdth 89 (Narrow). Size carries the hierarchy.
   Body and label: wdth 100, Def 400 / Em 600. */

.display-lg, .display-md, .display-sm { font-stretch: 75%; font-weight: 900; }
.heading-xxl, .heading-xl, .heading-lg, .heading-md {
  font-stretch: 89%;
  font-weight: 700;
}
.display-lg { font-size: 160px; line-height: 160px; letter-spacing: -.02em; }
.display-md { font-size: 120px; line-height: 120px; letter-spacing: -.02em; }
.display-sm { font-size: 80px; line-height: 80px; letter-spacing: -.02em; }
.heading-xxl { font-size: 56px; line-height: 64px; letter-spacing: -.02em; }
.heading-xl { font-size: 40px; line-height: 48px; letter-spacing: -.02em; }
.heading-lg { font-size: 32px; line-height: 40px; letter-spacing: -.02em; }
.heading-md { font-size: 24px; line-height: 32px; }

.body-lg { font-size: 20px; line-height: 28px; }
.body-md { font-size: 16px; line-height: 24px; }
.body-sm { font-size: 14px; line-height: 20px; }

.kicker {
  font-size: 14px;
  line-height: 16px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--brand-primary);
}

/* Label / tag: pill, 1px ink border, status fill, ink text. */
.label {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  padding: 6px 16px;
  border: 1px solid var(--border-solid);
  border-radius: var(--radius-full);
  background: var(--brand-secondary);
  color: var(--fg-primary);
  font-size: 16px;
  line-height: 20px;
  font-weight: 400;
  white-space: nowrap;
}
.label--sm { padding: 2px 12px; font-size: 14px; line-height: 16px; }
.label--success { background: var(--status-success); }
.label--warning { background: var(--status-warning); }

.wordmark { display: block; fill: currentColor; }

/* ---------- buttons ----------
   Every button is the same build: pill, 2px border, 4px hard shadow,
   label/md/em. Variants only swap the colour variables; sizes only swap
   height and padding. Hover changes the fill; press moves the button down
   3px while the shadow drops to 1px, so it sinks into the page. */

.btn {
  --btn-bg: var(--bg-default);
 
  --btn-fg: var(--fg-primary);
  --btn-edge: var(--border-solid);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  height: 48px;
  padding: 0 24px;
  border: 2px solid var(--btn-edge);
  border-radius: var(--radius-full);
  background: var(--btn-bg);
  color: var(--btn-fg);
  box-shadow: 0 4px 0 var(--btn-edge);
  font-size: 16px;
  line-height: 20px;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color 150ms, box-shadow 120ms var(--ease), transform 120ms var(--ease);
}
/* No hover state: a button is just its two colours. */
/* Before its section has risen in, the shadow isn't there yet (see "stamp"). */
.btn.is-unstamped { box-shadow: 0 0 0 var(--btn-edge); }
.btn:active, .btn.is-unstamped:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--btn-edge); transition-duration: 60ms; }

/* sizes */
.btn--sm { height: 40px; padding: 0 16px; }
.btn--lg { height: 56px; padding: 0 32px; font-size: 20px; line-height: 24px; font-weight: 700; }
.btn--icon { width: 40px; height: 40px; padding: 0; }
/* Hero button (Figma 25 Marketing website, button 111:951): 56px tall,
   heading/xs label (Narrow Bold 16/24) over label/xs/em (Standard SemiBold
   12/12) in the label colour at 70%, no gap. Label 8px from the top edge,
   second line 12px from the bottom (padding is those minus the 2px border). */
.btn--hero { flex-direction: column; justify-content: flex-start; gap: 0; height: 56px; padding: 6px 56px 10px; }
.btn--hero .btn__label { font-size: 16px; line-height: 24px; font-stretch: 89%; font-weight: 700; }
.btn--hero .btn__sub { font-size: 12px; line-height: 12px; font-stretch: 100%; font-weight: 600; color: color-mix(in srgb, var(--btn-fg) 70%, transparent); }

/* colours */
.btn--primary { --btn-bg: var(--brand-primary); --btn-fg: var(--fg-invert); }
.btn--secondary { --btn-bg: var(--bg-default); --btn-fg: var(--fg-primary); }

/* Inverted, on dark grounds: cream border and shadow. */
.on-dark .btn { --btn-edge: var(--border-invert); }
.on-dark .btn--primary { --btn-bg: var(--green-light); }
.on-dark .btn--secondary { --btn-bg: var(--bg-invert); --btn-fg: var(--fg-invert); }

/* The header button always contrasts with the act behind it (data-cta,
   set by the script): cream by default, or orange, aqua or green. Ink edge
   and shadow on every one. */
.header .btn { --btn-edge: var(--border-solid); --btn-bg: var(--bg-default); --btn-fg: var(--fg-primary); }
.header[data-cta="orange"] .btn { --btn-bg: var(--brand-secondary); }
.header[data-cta="aqua"] .btn { --btn-bg: var(--brand-tertiary); }
.header[data-cta="yellow"] .btn { --btn-bg: var(--brand-quaternary); }
.header[data-cta="green"] .btn { --btn-bg: var(--brand-primary); --btn-fg: var(--fg-invert); }

/* After any call to action is pressed (see initComing): every coloured button goes white and every white one goes
   green, and they all read "Coming Nov ’26". The header button is coloured in every act but cream, so it follows
   its own data-cta; the phones' own buttons are pictures, so .pbtn paints a white pill over them. */
.is-coming a.btn--primary { --btn-bg: var(--bg-default); --btn-fg: var(--fg-primary); }
.is-coming a.btn--secondary { --btn-bg: var(--brand-secondary); --btn-fg: var(--fg-primary); } /* the footer's store buttons: brand orange */
.is-coming .header[data-cta] .btn { --btn-bg: var(--bg-default); --btn-fg: var(--fg-primary); }
.is-coming .header[data-cta="cream"] .btn { --btn-bg: var(--green-light); --btn-fg: var(--fg-invert); }
/* The button keeps its size: its own content stays in place, unseen, and the new label sits centred over it. */
.btn { position: relative; }
.btn__orig { visibility: hidden; display: contents; }
.btn__coming { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; gap: 4px; }

/* ---------- tabs (Figma: 25 Product v2 · Tabs / inline, Tabs / fixed) ----------
   Pill, 1px ink border, 2px hard shadow, 40px tall (md). Inactive: cream,
   label/md/def (Narrow Regular). Hover: surface. Active: orange, label/md/em
   (Standard SemiBold). Fixed tabs share the row in equal widths. */

.tab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  height: 40px;
  padding: 0 16px;
  border: 1px solid var(--border-solid);
  border-radius: var(--radius-full);
  background: var(--bg-default);
  box-shadow: var(--shadow-xs);
  color: var(--fg-primary);
  font-size: 16px;
  line-height: 20px;
  font-stretch: 89%;
  font-weight: 400;
  white-space: nowrap;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color 120ms linear;
}
.tab:hover { background: var(--bg-surface); }
.tab.is-active { background: var(--brand-secondary); font-stretch: 100%; font-weight: 600; cursor: default; }
.tab--fixed { flex: 1 1 0; min-width: 0; }

/* ---------- motion: rise + hard-shadow stamp ---------- */

.js [data-rise] {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity var(--rise) var(--ease) var(--d, 0ms), transform var(--rise) var(--ease) var(--d, 0ms);
}
.js [data-rise].is-in { opacity: 1; transform: none; }
.js [data-rise]:not(.is-in) { pointer-events: none; } /* not yet risen in: invisible, so it can't take a press meant for what is on show (the hero's button sits over the phone's) */

/* The hard shadow lands 80ms after the element settles (a stamp hitting
   paper): JS removes .is-unstamped from the buttons at that moment. */

/* ==========================================================================
   Act 0 · Intro overlay
   ========================================================================== */

.intro { display: none; }

.js .intro {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: block;
  cursor: pointer;
}
.intro__bg { position: absolute; inset: 0; background: var(--bg-default); }
.intro__inner {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
}
.intro__mark {
  width: clamp(250px, 34.8vw, 501px);
  height: auto;
  aspect-ratio: 376 / 120;
  color: var(--brand-primary);
  transform-origin: 0 0;
}
.intro__sub { min-height: 28px; font-size: 20px; line-height: 28px; }
@media (min-width: 768px) { .intro__inner { gap: 24px; } }

/* ==========================================================================
   Header (transparent and sticky on every section)
   ========================================================================== */

.header {
  position: fixed;
  top: var(--header-top);
  left: var(--gutter);
  right: var(--gutter);
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  pointer-events: none;
}
.header > * { pointer-events: auto; }
/* Out of the way once the footer arrives: the footer carries its own wordmark and buttons. */
.header { transition: transform 300ms var(--ease), opacity 200ms linear; }
.header.is-hidden { transform: translateY(-140%); opacity: 0; }
.header.is-hidden > * { pointer-events: none; }

.header__logo { display: block; color: var(--brand-primary); } /* green on every act... */
.header.logo-white .header__logo { color: var(--fg-invert); } /* ...except white on the green grounds */
.header__logo .wordmark { width: 125.3px; height: 40px; } /* logo = CTA height */
@media (min-width: 768px) { .header__logo .wordmark { width: 150.4px; height: 48px; } }
.is-intro .header__logo { visibility: hidden; }

.header__nav { display: flex; align-items: center; gap: 8px; color: var(--fg-invert); }
.header[data-nav="dark"] .header__nav { color: var(--fg-primary); }

.header__cta-more { display: none; }

@media (min-width: 768px) {
  .header__nav { gap: 24px; }
  .header__cta { height: 48px; padding: 0 24px; }
  .header__cta-more { display: inline; }
}
@media (min-width: 992px) { .header__nav { gap: 40px; } }

/* ==========================================================================
   Act 1 · Hero (pinned, 4 states)
   ========================================================================== */

/* Every section fills at least one screen. */
/* Every section fills the *tall* screen (Safari's toolbar shrunk), so the next
   section never shows as a strip underneath when the toolbar shrinks.
   Centred or bottom-anchored content allows for --bar-now so it sits in the
   part of the screen that's visible. On desktop lvh = svh, so nothing changes. */
main section { min-height: 100vh; min-height: 100svh; min-height: 100lvh; }

/* Mobile Safari: --bar-gap is how much taller the screen gets when the
   toolbar shrinks (lvh - svh). 0 on desktop. */
:root { --bar-gap: 0px; --bar-now: 0px; }
@supports (height: 100lvh) { :root { --bar-gap: calc(100lvh - 100svh); } }
/* How far bottom-anchored copy lifts off the tall screen's bottom edge. On
   iOS 26 the full toolbar is about 40px taller than the floating pill: copy
   sits about 3.5rem above the pill and 1rem above the full toolbar. (dvh doesn't track the iOS 26
   toolbar, so it can't be used here.) */
:root { --bar-now: max(0px, calc(var(--bar-gap) - 24px)); } /* fallback only: the script measures the real toolbar and overrides this */

/* Darkest green ground: while the hero is held, Safari colours its bars from it. */
.hero { position: relative; background: var(--bg-invert); color: var(--fg-invert); }

.hero__stage { position: absolute; inset: 0; overflow: hidden; }

.hero__plates, .hero__plate { position: absolute; inset: 0; }
.hero__plates { z-index: 0; isolation: isolate; }
.hero__plate { visibility: hidden; }
.hero__plate.is-active { visibility: visible; }
.hero__plate.is-entering { visibility: visible; z-index: 1; }
.hero__plate img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.hero__video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity .6s ease; }
.hero__video.is-playing { opacity: 1; }
/* Videos are landscape: they only show where the landscape still does. */
@media (prefers-reduced-motion: reduce), (max-width: 767px), (max-width: 1199px) and (orientation: portrait) { .hero__video { display: none; } }

/* Scrim (Figma "scrim", Act 2 frames): bottom 55% of the visible screen, clear
   at the top, 80% ink by 80% of its height, then flat. Same on every plate.
   It runs on under the toolbar to the very bottom: no seam of bare photo. */
.hero__plate::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: calc((100% - var(--bar-now)) * .55 + var(--bar-now) + 1px);
  background: linear-gradient(to bottom, rgba(4, 17, 6, 0), rgba(4, 17, 6, .8) calc((100% - var(--bar-now) - 1px) * .8));
  pointer-events: none;
}

/* Tagline: body/md/em on phones, centred on two set lines. */
.hero__tagline { font-size: 16px; line-height: 24px; font-weight: 600; }
@media (min-width: 768px) { .hero__tagline { font-size: 28px; line-height: 36px; font-weight: 500; } }
/* Phones: "Everything that matters, / in one secure place." on two lines. */
.hero__line { display: block; }
@media (min-width: 768px) { .hero__line { display: inline; } }
/* .ml = a line set by hand on phones (each span its own line); runs on as normal text from tablet up. */
.ml { display: block; }
@media (min-width: 768px) { .ml { display: inline; } }

/* The hero copy is one centred block: tagline sitting straight on the title,
   then the button 24px below (Figma 115:1569). */
.hero__bottom {
  position: absolute;
  left: var(--gutter);
  right: var(--gutter);
  bottom: 40px; /* 2.5rem: bottom-aligned content sits close to the screen edge */
  margin-bottom: var(--bar-now); /* stays clear of the toolbar showing now */
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.hero__cta { margin-top: 24px; }
@media (min-width: 768px) { .hero__bottom { bottom: 96px; } .hero__cta { margin-top: 32px; } }
@media (min-width: 1200px) { .hero__bottom { bottom: 120px; } }

/* display/sm on phones, display/md on tablets, display/lg on desktop.
   "Your" and the noun sit on one line, centred. */
.hero__title {
  display: flex;
  justify-content: center;
  align-items: flex-end;
  gap: .11em; /* a word space: "Your wishes" is 330px wide at 80px, as in Figma */
  font-stretch: 75%;
  font-weight: 900;
  font-size: 80px;
  line-height: 80px;
  letter-spacing: -.02em;
}
.hero__your, .hero__noun { display: block; height: 1em; }
.hero__your { color: #fff; }
/* Narrow phones (360px and under): a touch smaller so "Your wishes" stays on one line. */
@media (max-width: 365px) { .hero__title { font-size: 72px; line-height: 72px; } }
@media (min-width: 768px) and (min-height: 760px) { .hero__title { font-size: 120px; line-height: 120px; } }
@media (min-width: 1200px) { .hero__title { gap: .14em; font-size: 120px; line-height: 120px; } }
@media (min-width: 1200px) and (min-height: 760px) { .hero__title { font-size: 160px; line-height: 160px; } }

/* The noun box: its width animates to fit the incoming word. */
.hero__noun {
  position: relative;
  height: 1em;
  color: var(--brand-secondary);
  transition: width 400ms var(--ease);
}
.hero__word {
  position: absolute;
  left: 0;
  top: 0;
  white-space: nowrap;
  clip-path: inset(-25% -5% -35% -5%);
}
.hero__word:not(.is-active) { clip-path: inset(-25% -5% 125% -5%); }

.hero .btn--primary { --btn-edge: var(--border-solid); --btn-bg: var(--brand-primary); }
.hero__cta { display: flex; align-self: stretch; justify-content: center; }
.hero__cta .btn { width: 100%; }
@media (min-width: 768px) { .hero__cta .btn { width: auto; } }

/* ==========================================================================
   Act 4a · The taboo (ink, then the light comes on)
   ========================================================================== */

.taboo { position: relative; background: var(--bg-invert); color: var(--fg-invert); }
.taboo.is-lit { background: var(--bg-default); color: var(--fg-primary); }

.taboo__inner { position: relative; min-height: 100vh; min-height: 100svh; }
/* Held by the browser (see held() in the script): the section is as tall as the whole hold and the stage sticks to the top of the screen. */
.taboo.is-sticky { height: calc(100vh + var(--pin)); height: calc(100lvh + var(--pin)); }
.taboo.is-sticky .taboo__inner { position: sticky; top: 0; height: 100vh; height: 100lvh; min-height: 0; }

.taboo__title {
  position: absolute;
  left: max(var(--gutter), calc((100% - 960px) / 2));
  right: max(var(--gutter), calc((100% - 960px) / 2));
  top: 22svh;
  font-stretch: 75%;
  font-weight: 900;
  font-size: 80px;
  line-height: 80px;
  letter-spacing: -.02em;
  text-wrap: pretty;
}
/* Phones and tablets (Figma 113:995): the headline block sits centred on the screen. */
@media (max-width: 991px) { .taboo__title { top: 50svh; transform: translateY(-50%); } } /* centred on the screen as it was drawn (svh), not on the stage, which is a tall screen high */
@media (min-width: 992px) { .taboo__title { top: 30svh; font-size: 120px; line-height: 120px; } }

.taboo__a { display: inline; }
/* "Except death." and "Let's change that." share one spot: the second
   replaces the first in place (Figma 113:995, scene 3). */
.taboo__swap { display: inline-grid; } /* runs on from "anything." as in the canvas */
.taboo__b, .taboo__c { grid-area: 1 / 1; }
/* Low light: the headline sits at 40% in the dark scene. */
.taboo:not(.is-lit) .taboo__a { color: color-mix(in srgb, var(--bg-default) 40%, transparent); }
.taboo__b { visibility: hidden; color: var(--brand-primary); opacity: clamp(0, calc(1 - (var(--w, 0) - .1) * 3), 1); }
.taboo.is-lit .taboo__b { visibility: visible; animation: fade-in 400ms var(--ease) backwards; } /* opacity only: nothing on the headline moves */

/* Scene 3, scrolled in (--w, 0 to 1, set from the script): "We'll talk about anything." and "Except death." fade out
   quickly while "Let's change that." is written in over the same spot, a word at a time, softly. */
.taboo.is-writing .taboo__a.is-in { opacity: clamp(0, calc(1 - var(--w, 0) * 3), 1); transition: none; }
.taboo__c { color: var(--brand-primary); }
.taboo__c > span { opacity: clamp(0, calc((var(--w, 0) - .3 - var(--i) * .15) * 4), 1); }

@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

/* Hand-over to the 25 Cards (Act 4a into 4b) and to the sign-off (Act 7 into 8), as the hero's phone into its first
   photo (see curtain() in the script). The section sits in a .curtain-slot that starts one curtain length above where the
   section fills the screen; the section is position: sticky inside it, so for those screens the browser itself holds
   it at the top of the screen, and --r (0 to 1) only scales it up from its top edge, rounded, and lifts it from the
   bottom edge. The slot's end spacer is the sticky run; its negative margin leaves the page the same length as a
   plain section. Without the script it is a plain section. */
.curtain-slot.has-curtain { margin-top: calc(-100vh - var(--d, 160vh)); margin-top: calc(-100lvh - var(--d, 160lvh)); }
.curtain-slot.has-curtain::after { content: ""; display: block; height: var(--d, 160vh); }
.cards.has-curtain, .signoff.has-curtain { position: sticky; top: 0; z-index: 3;
  transform-origin: 50% 0;
  translate: 0 calc((1 - var(--r, 0)) * 100vh); translate: 0 calc((1 - var(--r, 0)) * 100lvh);
  transform: scale(calc(.55 + .45 * var(--r, 0)));
  border-radius: calc((1 - var(--r, 0)) * 32px) calc((1 - var(--r, 0)) * 32px) 0 0; }
.cards.has-curtain.is-full, .signoff.has-curtain.is-full { translate: none; transform: none; border-radius: 0; will-change: auto; } /* a plain layer once it fills the screen */
.taboo.has-curtain .taboo__title { translate: 0 calc(var(--r, 0) * -70vh); }
/* The sign-off is as tall as the part of the screen that is visible (a tall screen less the toolbar showing), so
   the page ends exactly where its scale-up does: on a phone a full tall screen left one more scroll to make. */
.signoff.has-curtain { min-height: 0; height: calc(100vh - var(--bar-now)); height: calc(100lvh - var(--bar-now)); padding-bottom: 96px; }
.signoff.has-curtain .signoff__legal { bottom: 40px; }
/* Once it fills the screen, the sign-off carries its own green below it (a shadow adds no scroll length), so nothing of the held Act 7 photo can show underneath when the toolbar folds away or the page is pulled past its end. */
.signoff.has-curtain.is-full { box-shadow: 0 200px 0 var(--brand-primary); }

/* ==========================================================================
   Act 3 · Product: one phone, ten screens wiping inside it
   ========================================================================== */

.product { position: relative; display: flex; flex-direction: column; background: var(--brand-primary); color: var(--fg-invert); }

.product__stage {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 16px;
  flex: 1;
  padding: calc(var(--header-top) + var(--header-h) + 24px) 0 32px;
  overflow: hidden;
}
/* Phones: the head only holds the visually hidden title, so it takes no space. */
.product__head { display: contents; }
.product__head .kicker { font-size: 12px; }
.product__title { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* Phones: the tabs are a snap rail that bleeds off both edges. */
.product__tabs {
  display: flex;
  gap: 4px;
  padding: 0 var(--gutter) 4px;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
}
.product__tabs::-webkit-scrollbar { display: none; }
.product__tabs li { flex: none; scroll-snap-align: start; scroll-margin-left: var(--gutter); }

/* Tabs: the design-system inline tab (see "tabs" above). The number reads as
   part of the label, a step quieter. */
.product__num { opacity: .6; }
.product__tab.is-active .product__num { opacity: 1; }

/* On the timer (see initProduct): the active pill is cream and the orange fills it over 4s, then the next tab starts. */
.product__tabs.is-timed .product__tab { position: relative; overflow: hidden; }
.product__tabs.is-timed .product__tab.is-active { background: var(--bg-default); }
.product__tabs.is-timed .product__tab > * { position: relative; }
.product__tabs.is-timed .product__tab.is-active::before {
  content: ""; position: absolute; inset: 0; background: var(--brand-secondary);
  transform: scaleX(0); transform-origin: 0 50%;
}
.product__tabs.is-timed .product__tab.is-timing::before { animation: tab-fill 4s linear forwards; }
@keyframes tab-fill { to { transform: scaleX(1); } }

.product__device {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
  padding: 8px var(--gutter) 0;
}
/* Phones and tablets: tabs sit a little lower under the header, and the phone
   grows to fill whatever height is left down to the bottom of the screen. */
@media (max-width: 991px) {
  .product { height: 100vh; height: 100lvh; } /* a fixed height, so the phone can take a share of it */
  .product__stage { padding: calc(var(--header-top) + var(--header-h) + 24px) 0 calc(24px + var(--bar-now)); }
  /* Phones' heading for the act (desktop shows the full title instead; screen readers get that one). */
  .product__mtitle { padding: 0 var(--gutter); text-align: center; white-space: nowrap; font-stretch: 89%; font-weight: 700; font-size: min(24px, 6.4vw); line-height: 32px; } /* heading/md, one line down to narrow phones */
  .product__device { flex: 1; min-height: 0; justify-content: center; padding-top: 16px; }
}

/* iPhone 17 Pro: titanium band, black bezel, Dynamic Island, side buttons.
   Sized off its own width so the frame scales as one piece. The screen is
   393 x 852, the app's artboard size. */
.phone {
  position: relative;
  container-type: inline-size;
  width: 283px; /* phones fill the height left (see Act 3 phones); desktop sets its own */
  aspect-ratio: 100 / 207.45;
  touch-action: pan-y;
  user-select: none;
}
@media (max-width: 991px) { .phone { width: auto; height: min(100%, calc(86vw * 2.0745), 830px); } }
.phone__frame {
  --bezel: 4cqw;
  position: absolute;
  inset: 0;
  padding: var(--bezel);
  border-radius: 17cqw;
  background: #0b0b0c;
  box-shadow: inset 0 0 0 .7cqw #8e8a85, inset 0 0 0 1.1cqw #3b3936;
}
/* side buttons: action + volume on the left, power and camera control on the right */
.phone__frame::before, .phone__frame::after {
  content: "";
  position: absolute;
  width: 1.1cqw;
  border-radius: 1cqw;
  background: #6f6b66;
}
.phone__frame::before {
  left: -.9cqw;
  top: 20%;
  height: 7%;
  box-shadow: 0 9.5cqw 0 #6f6b66, 0 25cqw 0 #6f6b66;
}
.phone__frame::after {
  right: -.9cqw;
  top: 28%;
  height: 14%;
  box-shadow: 0 34cqw 0 -.1cqw #6f6b66;
}
.phone__screen {
  position: relative;
  height: 100%;
  border-radius: 13cqw;
  overflow: hidden;
  background: var(--bg-surface);
}
.phone__island {
  position: absolute;
  top: calc(var(--bezel) + 2.6cqw);
  left: 50%;
  z-index: 3;
  width: 30cqw;
  height: 8.6cqw;
  border-radius: 6cqw;
  background: #000;
  transform: translateX(-50%);
}
.product__screen { position: absolute; inset: 0; visibility: hidden; }
.product__screen.is-active, .product__screen.is-entering { visibility: visible; }
.product__screen.is-entering { z-index: 1; }
.product__screen img { width: 100%; height: 100%; object-fit: cover; object-position: top; -webkit-user-drag: none; pointer-events: none; }

@media (min-width: 992px) { .product__mtitle { display: none; } }

/* Desktop: everything on one centre line. Title, then the feature tabs as a
   centred row of pills, then the phone filling the height left. */
@media (min-width: 992px) {
  .product__stage {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 24px;
    padding: 112px var(--gutter) 40px;
  }
  .product__head { display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 0; text-align: center; }
  .product__head .kicker { font-size: 14px; }
  .product__title {
    position: static; width: auto; height: auto; overflow: visible; clip: auto; white-space: normal;
    max-width: 760px;
    font-stretch: 89%; font-weight: 700; font-size: 56px; line-height: 1.05; letter-spacing: -.02em;
  }
  .product__tabs { flex-wrap: wrap; justify-content: center; gap: 8px; max-width: 900px; padding: 0; overflow: visible; }
  .product__device { flex: 1; min-height: 0; justify-content: center; padding: 0; }
  .phone { width: min(320px, calc((100svh - 400px) * .482)); }
}

/* ==========================================================================
   Act 1 · the opening scene, inside the hero's pinned stage (Figma Act 1).
   Stop 0: headline, sentence and the phone anchored to the bottom, its tiles
   lighting up, then the phone moves up under the headline. Stop 2: the
   phone has left and the first photo has scaled out to fill the screen
   (that last move is two screens of scroll long: no stop in between).
   The script scrubs custom properties as the page scrolls: --a (phone up under
   the headline), --f (the sentence fades), --c (headline leaves), --b (phone
   leaves) and --t (photo rises and scales out; 1 = full screen, also the no-JS
   state); tiles get .is-on as the scroll reaches them.
   Sizes are Figma units times --k: phones are drawn on 393 x 852, desktop on 1512 x 982.
   ========================================================================== */

.hero {
  --vis: calc(100vh - var(--bar-hero, var(--bar-now)));
  --k: min(calc(100vw / 393), calc(var(--vis) / 852));
  --lead-top: 110; --lead-w: 345; --h1: 56; --h1-lh: 64; --h1-lines: 2; --gap: 24; --sub: 16; --sub-lh: 24;
  --ph-w: 311; --ph-top: 358; --s0: .6;
}
@supports (height: 100lvh) { .hero { --vis: calc(100lvh - var(--bar-hero, var(--bar-now))); } }
@media (min-width: 992px) {
  .hero {
    --k: min(calc(100vw / 1512), calc(var(--vis) / 982));
    --lead-top: 150; --lead-w: 1065; --h1: 120; --h1-lh: 120; --h1-lines: 1; --gap: 32; --sub: 24; --sub-lh: 32;
    --ph-w: 358; --ph-top: 437; --s0: .55;
  }
}

.hero__stage { background: var(--bg-default); }
.hero__act1 { position: absolute; inset: 0; z-index: 1; color: var(--fg-primary); }
/* Without the script the scene isn't played: its words stay for screen readers only. */
.hero:not(.has-act1) .hero__act1 { inset: auto; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
body.is-intro .hero__h1 { visibility: hidden; } /* the intro's own line flies into it */

.hero__lead {
  position: absolute;
  top: calc(var(--lead-top) * var(--k));
  left: 50%;
  width: calc(var(--lead-w) * var(--k));
  margin-left: calc(var(--lead-w) * var(--k) / -2);
  text-align: center;
  transform: translateY(calc(var(--c, 0) * (-100% - var(--lead-top) * var(--k) - 8px)));
}
.hero__h1 {
  font-stretch: 75%;
  font-weight: 900;
  letter-spacing: -.02em;
  font-size: calc(var(--h1) * var(--k));
  line-height: calc(var(--h1-lh) * var(--k));
}
.hl { display: block; }
@media (min-width: 992px) { .hl { display: inline; } .hero__h1 { white-space: nowrap; } }
.hero__sub {
  margin-top: calc(var(--gap) * var(--k));
  font-stretch: 100%;
  font-weight: 400;
  font-size: calc(var(--sub) * var(--k));
  line-height: calc(var(--sub-lh) * var(--k));
}
.hero__sub-in { display: block; opacity: calc(1 - var(--f, 0) * 2); } /* gone by halfway through the phone's move */
.b-d { display: none; }
@media (min-width: 992px) { .b-d { display: inline; } .b-m { display: none; } }

.hero__phone {
  position: absolute;
  top: calc(var(--ph-top) * var(--k));
  left: 50%;
  width: calc(var(--ph-w) * var(--k));
  margin-left: calc(var(--ph-w) * var(--k) / -2);
}
.hero__phone-in {
  --ph: calc(var(--ph-w) * var(--k) * 2.0745);
  /* --a: up a little, to sit under the headline; --b: on up and off the top. */
  --top2: calc(var(--lead-top) + var(--h1-lines) * var(--h1-lh) + var(--gap));
  transform: translateY(calc(var(--a, 0) * (var(--top2) - var(--ph-top)) * var(--k) - var(--b, 0) * (var(--top2) * var(--k) + var(--ph) + 24px)));
  will-change: transform;
}
.hero .phone { width: 100%; height: auto; }
.hero__dash { display: block; width: 100%; height: 100%; object-fit: cover; }

/* A tile that lights up is a slice of the filled dashboard laid over the empty
   one (rects in the 393 x 852 screen). --d is its turn in the sequence. */
.lt {
  position: absolute;
  left: calc(var(--x) / 393 * 100%);
  top: calc(var(--y) / 852 * 100%);
  width: calc(var(--w) / 393 * 100%);
  height: calc(var(--h) / 852 * 100%);
  overflow: hidden;
  opacity: 0;
}
.lt img {
  position: absolute;
  max-width: none;
  width: calc(393 / var(--w) * 100%);
  height: auto;
  left: calc(var(--x) / var(--w) * -100%);
  top: calc(var(--y) / var(--h) * -100%);
}
.lt.is-on { animation: lt-on 600ms var(--ease) both; }
/* A button drawn on the phone's own button (the screenshots have one baked in), in the screenshot's own pixels
   (923 x 2000). Invisible until a call to action has been pressed; then it is the white "Coming Nov ’26" pill. */
.phone__screen { container-type: inline-size; }
.pbtn {
  position: absolute;
  z-index: 2;
  left: calc(var(--x) / 923 * 100%);
  top: calc(var(--y) / 2000 * 100%);
  width: calc(var(--w) / 923 * 100%);
  height: calc((var(--h) - 12) / 2000 * 100%); /* the baked button's 12px hard shadow is the pill's own, below */
  padding: 0;
  border: 0 solid var(--border-solid);
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--fg-primary);
  font: inherit;
  font-stretch: 89%;
  font-weight: 700;
  font-size: 5.6cqw;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.is-coming .pbtn { border-width: .5cqw; background: var(--bg-default); box-shadow: 0 1.3cqw 0 var(--border-solid); }

@keyframes lt-on {
  0% { opacity: 0; transform: scale(1); }
  35% { opacity: 1; transform: scale(1.05); }
  100% { opacity: 1; transform: scale(1); }
}

/* The photos come up from the bottom edge and scale out over the cream. */
.hero__plates {
  z-index: 2;
  overflow: hidden;
  transform-origin: 50% 0;
  /* waits a whole tall screen below (not --vis, which is frozen at the toolbar's tallest and would let the photo's edge peek in once the toolbar folds away) */
  transform: translateY(calc((1 - var(--t, 1)) * 100vh)) scale(calc(var(--s0) + (1 - var(--s0)) * var(--t, 1)));
  transform: translateY(calc((1 - var(--t, 1)) * 100lvh)) scale(calc(var(--s0) + (1 - var(--s0)) * var(--t, 1)));
  border-radius: calc((1 - var(--t, 1)) * 32px) calc((1 - var(--t, 1)) * 32px) 0 0;
  will-change: transform;
}
.hero__bottom { z-index: 3; }
/* Once the photo fills the screen it is the plain full-bleed layer it always was: no
   transform (a transformed layer can leave a hairline of the cream ground at the edge on a
   phone) and a dark ground behind it, so nothing pale can show at the edges. */
.hero.is-lit .hero__stage { background: var(--bg-invert); }
/* ...and the opening scene is switched off behind it (a sliver of the phone's bottom edge showed at the top on an iPhone). */
.hero.is-lit .hero__act1 { visibility: hidden; }
.hero.is-lit .hero__plates { transform: none; border-radius: 0; will-change: auto; inset: -2px; } /* a little over-scan: no hairline of the ground at the edges */

/* ==========================================================================
   Act 5 · Gatekeepers: For now (cream) vs For later (dark green). One big
   word across the top that inverts with the view (Robbie, 9 Oct 2026).
   ========================================================================== */

.gk {
  --word: calc((100vw - 2 * var(--gutter)) * .21); /* "Gatekeepers" edge to edge */
  position: relative;
  background: var(--bg-default);
  --x: 50%;
}
/* Colours follow data-theme, the content (which view is showing) follows data-view: on a phone the takeover swaps the content at once and sweeps the colours across (see setView). */
.gk[data-theme="later"] { background: var(--green-dark); }

.gk__word, .gk__mword {
  display: block;
  font-size: var(--word);
  line-height: .82;
  font-weight: 900;
  font-stretch: 75%;
  letter-spacing: -.02em;
  text-align: center;
  white-space: nowrap;
  color: var(--fg-primary);
}
.gk[data-theme="later"] .gk__mword { color: var(--fg-invert); }
.gk__panel--later .gk__word { color: var(--fg-invert); }

.gk__toggle {
  position: relative;
  z-index: 2;
  display: flex;
  gap: 8px;
  justify-content: center;
}
/* Tabs: two 100px pills, 4px apart, centred (Figma 115:1200). */
.gk__seg { display: flex; gap: 4px; }
.gk__seg .gk__tbtn { flex: none; width: 100px; padding: 0; transition: none; } /* instant switch, no fade or wipe */

.gk__stage { position: relative; }
.gk__panel--later { color: var(--fg-invert); }
.gk__panel--later .kicker { color: var(--bg-default); }

.gk__head { display: flex; flex-direction: column; align-items: center; gap: 16px; text-align: center; }
.gk__points { display: flex; flex-direction: column; gap: 16px; max-width: 600px; }
.gk__q { display: none; font-size: 16px; line-height: 22px; font-weight: 700; }
.gk__d, .gk__m { display: block; font-size: 16px; line-height: 22px; font-weight: 400; }
.gk__d { display: none; } /* long copy from desktop up; one-liners on phones (Figma) */
.gk__body { display: flex; justify-content: center; }
/* Gatekeeper invitation scrolls inside the phone. */
.gk__scroll { overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none; touch-action: pan-y; user-select: auto; }
.gk__scroll::-webkit-scrollbar { display: none; }
.gk .phone__screen img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: top; -webkit-user-drag: none; }
.gk .gk__scroll img { height: auto; }

/* Phones: big word, pills, then the open view's points and screen, all in one screen. */
@media (max-width: 991px) {
  .gk {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;
    height: 100svh;
    overflow: hidden;
    padding: calc(var(--header-top) + var(--header-h) + 16px) var(--gutter) 0;
  }
  .gk__word, .gk__panel .kicker, .gk__divider, .gk__handle { display: none; }
  /* Both views share one grid: the points sit in one cell (so it is as tall as the longer set) and the
     phones in the next, so the phone stays put when you flip between For now and For later. */
  .gk__stage { width: 100%; flex: 1; min-height: 0; display: grid; grid-template-rows: auto auto; justify-items: center; align-content: start; row-gap: 20px; }
  .gk__panel { display: contents; }
  .gk__head { grid-area: 1 / 1; }
  .gk__body { grid-area: 2 / 1; flex: none; width: 100%; }
  .gk[data-view="now"] .gk__panel--later,
  .gk[data-view="later"] .gk__panel--now { visibility: hidden; }
  .gk__panel--now, .gk__panel--later { color: var(--fg-primary); } /* the text takes the theme's colour, not its own panel's */
  .gk[data-theme="later"] .gk__panel--now, .gk[data-theme="later"] .gk__panel--later { color: var(--fg-invert); }
  .gk .phone { width: min(320px, 85vw); height: auto; } /* Figma: 320 wide, runs off the bottom of the screen */
}
/* Phones: the takeover between For now and For later (see setView in the script). The copy of the act in its new
   state sits over the real one, revealed through a moving edge; the edge gets the same 2px ink line as the desktop slider. */
.gk.gk--sweep { position: absolute; left: 0; margin: 0; z-index: 4; pointer-events: none; } /* top, width and height come from the script */
.gk__sweepline { position: absolute; top: 0; bottom: 0; z-index: 5; width: 2px; margin-left: -1px; background: var(--border-solid); pointer-events: none; }
@media (max-width: 991px) and (max-height: 700px) {
  .gk { gap: 12px; }
  .gk__points { gap: 8px; }
  .gk__m { font-size: 14px; line-height: 20px; }
}

/* Desktop: drag the bar to compare. Each panel carries the word in the same
   place in opposite colours, so it inverts right at the split. */
@media (min-width: 992px) {
  /* Laid out as the Figma frame (1512 x 982): --u is one Figma px, so it all scales with the window.
     --x0 / --y0 centre the frame, so wider or taller windows just get more ground around it. */
  .gk {
    --H: max(100svh, 720px);
    --u: min(100vw / 1512, var(--H) / 982);
    --x0: calc((100vw - 1512 * var(--u)) / 2);
    --y0: calc((var(--H) - 982 * var(--u)) / 2);
    min-height: var(--H);
    background: var(--green-dark);
    overflow: hidden;
  }
  .gk__mword, .gk__toggle { display: none; }
  .gk__stage { position: absolute; inset: 0; touch-action: pan-y; }
  .gk__panel {
    position: absolute;
    inset: 0;
    isolation: isolate; /* keeps the phone's island inside its own panel */
  }
  .gk__panel--later { background: var(--green-dark); }
  .gk__panel--now { background: var(--bg-default); clip-path: inset(0 calc(100% - var(--x)) 0 0); }
  .gk__word {
    position: absolute;
    left: 50%;
    top: calc(var(--y0) + 111 * var(--u));
    translate: -50% 0;
    font-size: calc(283.9 * var(--u));
    line-height: calc(232.8 * var(--u));
    letter-spacing: calc(-5.7 * var(--u));
  }

  .gk__head { position: absolute; left: var(--gutter); /* the logo's left edge */ top: calc(var(--y0) + 477 * var(--u)); width: calc(594 * var(--u)); gap: calc(24 * var(--u)); }
  .gk__panel--later .gk__head { left: auto; right: var(--gutter); width: calc(595 * var(--u)); } /* the button's right edge */
  .gk__head .kicker { font-size: calc(14 * var(--u)); line-height: calc(16 * var(--u)); letter-spacing: calc(1.7 * var(--u)); }
  .gk__points { gap: calc(24 * var(--u)); max-width: none; }
  .gk__q, .gk__d { font-size: calc(20 * var(--u)); line-height: calc(28 * var(--u)); }
  .gk__q { display: block; font-weight: 600; }
  .gk__d { display: block; font-weight: 300; }
  .gk__m { display: none; }

  /* The phone: same spot in both views, in the half the points are not in. */
  .gk__body { --bx: 995.8; position: absolute; left: calc(var(--x0) + var(--bx) * var(--u)); top: calc(var(--y0) + 368.8 * var(--u)); width: calc(276.3 * var(--u)); height: calc(573.2 * var(--u)); }
  .gk__panel--later .gk__body { --bx: 239.8; }
  .gk .phone { width: 100%; height: 100%; }

  .gk__divider {
    display: block;
    position: absolute;
    top: 0;
    bottom: 0;
    left: calc(var(--x) - 1px);
    width: 2px;
    background: var(--border-solid);
    pointer-events: none;
  }
  .gk__handle {
    display: flex;
    position: absolute;
    top: calc(var(--y0) + 589.2 * var(--u));
    left: var(--x);
    z-index: 3;
    align-items: center;
    justify-content: center;
    width: 80px;
    height: 40px;
    margin: -20px 0 0 -40px;
    padding: 0;
    cursor: ew-resize;
    touch-action: none;
  }
  .gk__handle.is-pulsing { animation: nudge 1400ms var(--ease) 300ms 1; }
}

@keyframes nudge {
  0%, 100% { transform: none; }
  15% { transform: scale(1.12); }
  35% { transform: translateX(-20px); }
  55% { transform: translateX(20px); }
  75% { transform: translateX(-8px); }
}
@keyframes wipe-in-up { from { clip-path: inset(100% 0 0 0); } to { clip-path: inset(0 0 0 0); } }

/* ==========================================================================
   Act 5 · The 25 Card (cream ground, cyan and yellow as artwork)
   ========================================================================== */

.cards {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: calc(var(--header-top) + var(--header-h) + 24px) 0 32px;
  background: var(--brand-tertiary);
  overflow: hidden;
}

.cards__copy { display: contents; }
.cards__title {
  position: relative;
  order: 1;
  padding: 0 var(--gutter);
  font-stretch: 89%;
  font-weight: 700;
  font-size: 40px;
  line-height: 44px;
  letter-spacing: -.02em;
}
/* Phones: the deck sits in the flow, centred. Extra room above and below
   so the tilted cards behind don't touch the title or the quote. */
.cards__deck { order: 2; position: relative; flex: 1 1 0; min-height: 160px; margin: 28px 0 24px; container-type: size; touch-action: pan-y; outline-offset: -4px; }
.cards__quote { order: 3; position: relative; display: flex; flex-direction: column; gap: 8px; padding: 16px var(--gutter) 0; }
/* Figma Act 4b: the caption ("Why Jordan signed up") sits above the quote, Standard Regular; the quote is SemiBold, Narrow on phones and Standard from desktop. */
.cards__q { font-size: 16px; line-height: 24px; font-stretch: 89%; font-weight: 600; }
.cards__who { font-size: 16px; line-height: 24px; font-weight: 400; }
.cards__cta { order: 4; position: relative; margin: 24px var(--gutter) 0; }
.cards__cta .btn { width: 100%; }
.cards__quote.is-swapping { animation: wipe-in-up 400ms var(--ease) both; }

/* Phones and tablets: the act is exactly one screen. The deck takes whatever
   height is left once the title, quote and button are placed, and the cards
   are sized from that height (capped at the desktop size). */
@media (max-width: 991px) { .cards { height: 100vh; height: 100svh; height: 100lvh; padding-bottom: calc(40px + var(--bar-now)); } }
/* Shorter phones: tighter title and quote so the cards keep their size. */
@media (max-width: 767px) and (max-height: 700px) {
  .cards { padding-top: calc(var(--header-top) + var(--header-h) + 16px); }
  .cards__title { font-size: 32px; line-height: 36px; }
  .cards__q, .cards__who { font-size: 14px; line-height: 20px; }
  .cards__quote { gap: 4px; padding-top: 8px; }
  .cards__cta { margin-top: 16px; }
  .cards__deck { margin: 22px 0 16px; }
}
/* Small phones (SE with the toolbar showing). */
@media (max-width: 767px) and (max-height: 600px) {
  .cards__deck { margin: 20px 0 14px; }
  .cards__title { font-size: 32px; line-height: 36px; }
  .cards__q, .cards__who { font-size: 14px; line-height: 20px; }
  .cards__cta { margin-top: 16px; }
}
/* The fanned stack, angles from the Figma footer-lg frame, on every screen.
   Tap, click or swipe: the front card flicks out and goes to the back, the
   rest step forward. */
.cards__stack {
  position: absolute;
  left: 50%;
  top: 50%;
  height: min(100cqh, 613px);
  width: calc(min(100cqh, 613px) * 690 / 1226);
  transform: translate(-50%, -50%);
}

/* 25 card: one finished image (frame, photo, pills, tiles and shadow are in the artwork). */
.card25 {
  position: absolute;
  inset: 0;
  transform-origin: 50% 50%;
  will-change: transform;
  user-select: none;
  -webkit-user-select: none;
}
.card25 img { width: 100%; height: auto; -webkit-user-drag: none; pointer-events: none; }
.card25[data-slot="0"] { cursor: grab; }
.card25.is-dragging { cursor: grabbing; }

@media (min-width: 992px) {
  .cards { display: block; min-height: max(100svh, 820px); padding: 0; }
  .cards__copy {
    position: absolute;
    left: calc(var(--gutter) + 80px);
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 40px;
    width: min(560px, 42vw);
  }
  .cards__title { order: 0; padding: 0; font-size: 80px; line-height: 80px; font-stretch: 75%; font-weight: 900; }
  .cards__quote { order: 0; padding: 0; max-width: 560px; }
  .cards__q, .cards__who { font-size: 20px; line-height: 28px; }
  .cards__q { font-stretch: 100%; }
  .cards__cta { order: 0; margin: -16px 0 0; } /* 24px under the quote */
  .cards__cta .btn { width: auto; }

  .cards__deck {
    position: absolute;
    left: calc(74.2% - 172.5px);
    top: calc(52% - 306.5px);
    width: 345px;
    height: 613px;
    margin: 0;
    zoom: var(--deck-zoom, 1);
  }
  .cards__stack { position: relative; left: auto; top: auto; width: 100%; height: 100%; transform: none; }
}
@media (min-width: 992px) and (max-width: 1299px) { .cards__deck { --deck-zoom: .8; } .cards__copy { left: var(--gutter); } }
@media (min-width: 992px) and (max-height: 800px) { .cards__deck { --deck-zoom: .8; } }

/* ==========================================================================
   Act 6 · Use cases (fast: margin notes, no cards, no grid)
   ========================================================================== */

.uses {
  position: relative;
  padding: calc(var(--header-top) + var(--header-h) + 24px) var(--gutter) 24px;
  background: var(--bg-surface);
  overflow: hidden;
}
.uses__title {
  max-width: 900px;
  font-stretch: 89%;
  font-weight: 700;
  font-size: 32px;
  line-height: 36px;
  letter-spacing: -.02em;
}
/* Phones: title and all nine notes on one screen, the notes spread evenly
   down whatever height is left, with the doodles tucked into the gap on the
   other side of each note. */
.uses__list { display: flex; flex-direction: column; gap: min(12px, 1.4svh); margin-top: min(24px, 2.6svh); }
@media (max-width: 767px) {
  .uses { display: flex; flex-direction: column; padding-bottom: calc(40px + var(--bar-now)); }
  .uses__list { flex: 1; justify-content: space-evenly; }
  .note { position: relative; }
  .note__doodle {
    display: block;
    position: absolute;
    top: 0;
    bottom: 0;
    margin: auto 0;
    pointer-events: none;
  }
  /* Pinned to the far content edge (not hung off the note), so they never
     leave the screen. */
  .note--l .note__doodle { right: calc(100% - (100vw - 2 * var(--gutter))); }
  .note--r .note__doodle { left: calc(100% - (100vw - 2 * var(--gutter))); }
}

.note { display: flex; align-items: center; gap: 20px; max-width: 82%; transform: rotate(var(--rot)); }
@media (max-width: 767px) { .note { max-width: 76%; } }
.note--l { align-self: flex-start; text-align: left; }
.note--r { align-self: flex-end; text-align: right; }
.note__text { font-size: 15px; line-height: 21px; }
@media (max-width: 767px) and (max-height: 700px) {
  .uses { padding-top: calc(var(--header-top) + var(--header-h) + 16px); padding-bottom: calc(24px + var(--bar-now)); }
  .note__text { font-size: 13px; line-height: 17px; }
}
@media (max-width: 767px) and (max-height: 600px) { .uses__title { font-size: 28px; line-height: 32px; } .note__text { font-size: 12px; line-height: 15px; } }
.note__doodle { flex: none; }

.js .note { opacity: 0; transform: translateX(var(--from, -40px)) rotate(var(--rot)); }
.js .note--r { --from: 40px; }
.js .uses.is-in .note {
  opacity: 1;
  transform: rotate(var(--rot));
  transition: opacity 600ms var(--ease) var(--d), transform 600ms var(--ease) var(--d);
}
.js .note__doodle { opacity: 0; transform: scale(.6) rotate(-12deg); }
.js .uses.is-in .note__doodle {
  opacity: 1;
  transform: none;
  transition: opacity 400ms var(--ease) calc(var(--d) + 250ms), transform 400ms var(--ease) calc(var(--d) + 250ms);
}

@media (min-width: 768px) {
  .uses { padding-top: 128px; padding-bottom: 40px; }
  .uses__title { font-size: 80px; line-height: 80px; font-stretch: 75%; font-weight: 900; }
  .uses__list { margin-top: 32px; gap: min(16px, 1.2svh); }
  .note { max-width: 760px; }
  .note--l { margin-left: var(--indent); }
  .note--r { margin-right: var(--indent); }
  .note__text { font-size: 20px; line-height: 28px; }
  .note__doodle { display: block; }
}
@media (min-width: 768px) and (max-height: 860px) {
  .uses { padding-top: 112px; }
  .uses__title { font-size: 56px; line-height: 64px; font-stretch: 89%; font-weight: 700; }
  .note__text { font-size: 16px; line-height: 24px; }
  .note__doodle { transform-origin: center; zoom: .8; }
}

/* Act 6 notes: doodles are the Figma assets (assets/doodles, lg and sm sets); sizes below are the Figma frame sizes. */
.uses__stage { display: contents; }
.lg-br, .sm-br { display: none; }
.note__doodle { background: no-repeat 0 0 / 100% 100%; width: calc(var(--lw) * 1px); height: calc(var(--lh) * 1px); }
.uses__list .note:nth-child(1) .note__doodle { --lw: 73.6; --lh: 43; --sw: 65.4; --sh: 38.2; background-image: url(../assets/doodles/lg-1.svg); }
.uses__list .note:nth-child(2) .note__doodle { --lw: 73.3; --lh: 46.2; --sw: 65.2; --sh: 41.1; background-image: url(../assets/doodles/lg-2.svg); }
.uses__list .note:nth-child(3) .note__doodle { --lw: 57; --lh: 49.2; --sw: 47.5; --sh: 41; background-image: url(../assets/doodles/lg-3.svg); }
.uses__list .note:nth-child(4) .note__doodle { --lw: 49.3; --lh: 49.3; --sw: 41.1; --sh: 41.1; background-image: url(../assets/doodles/lg-4.svg); }
.uses__list .note:nth-child(5) .note__doodle { --lw: 49.8; --lh: 49.8; --sw: 41.5; --sh: 41.5; background-image: url(../assets/doodles/lg-6.svg); }
.uses__list .note:nth-child(6) .note__doodle { --lw: 41.8; --lh: 65.1; --sw: 26.1; --sh: 40.7; background-image: url(../assets/doodles/lg-7.svg); }
.uses__list .note:nth-child(7) .note__doodle { --lw: 53.6; --lh: 49.8; --sw: 44.7; --sh: 41.5; background-image: url(../assets/doodles/lg-8.svg); }
.uses__list .note:nth-child(8) .note__doodle { --lw: 52.9; --lh: 49.1; --sw: 44.2; --sh: 41; background-image: url(../assets/doodles/lg-9.svg); }
@media (max-width: 767px) {
  .sm-br { display: inline; }
  .note { max-width: none; }
  .note__doodle { width: calc(var(--sw) * 1px); height: calc(var(--sh) * 1px); }
  .note__text { max-width: 100%; }
  .uses__list .note:nth-child(1) .note__doodle { background-image: url(../assets/doodles/sm-1.svg); }
  .uses__list .note:nth-child(1) .note__text { width: 251.2px; }
  .uses__list .note:nth-child(2) .note__doodle { background-image: url(../assets/doodles/sm-2.svg); }
  .uses__list .note:nth-child(2) .note__text { width: 251.05px; }
  .uses__list .note:nth-child(3) .note__doodle { background-image: url(../assets/doodles/sm-3.svg); }
  .uses__list .note:nth-child(3) .note__text { width: 268px; }
  .uses__list .note:nth-child(4) .note__doodle { background-image: url(../assets/doodles/sm-4.svg); rotate: -4.76deg; }
  .uses__list .note:nth-child(4) .note__text { width: 309.2px; }
  .uses__list .note:nth-child(5) .note__doodle { background-image: url(../assets/doodles/sm-6.svg); rotate: 7.12deg; }
  .uses__list .note:nth-child(5) .note__text { width: 268px; }
  .uses__list .note:nth-child(6) .note__doodle { background-image: url(../assets/doodles/sm-7.svg); }
  .uses__list .note:nth-child(6) .note__text { width: 268px; }
  .uses__list .note:nth-child(7) .note__doodle { background-image: url(../assets/doodles/sm-8.svg); rotate: -1.3deg; }
  .uses__list .note:nth-child(7) .note__text { width: 268px; }
  .uses__list .note:nth-child(8) .note__doodle { background-image: url(../assets/doodles/sm-9.svg); rotate: -1.52deg; }
  .uses__list .note:nth-child(8) .note__text { width: 285.6px; }
  /* Figma sm positions: each text block and doodle nudged from where the one-screen flow puts it to its Figma spot (frame 393x852). Measured; re-measure if the flow changes. */
  .uses__list .note:nth-child(1) .note__text { translate: 1px -4px; }
  .uses__list .note:nth-child(2) .note__text { translate: 0px -8px; }
  .uses__list .note:nth-child(3) .note__text { translate: 0px -12px; }
  .uses__list .note:nth-child(4) .note__text { translate: 2px -10px; }
  .uses__list .note:nth-child(5) .note__text { translate: -3px -4px; }
  .uses__list .note:nth-child(6) .note__text { translate: 1px -8px; }
  .uses__list .note:nth-child(7) .note__text { translate: -2px -15px; }
  .uses__list .note:nth-child(8) .note__text { translate: 15px -10px; }
  .uses__list .note:nth-child(1) .note__doodle { translate: -29px -3px; }
  .uses__list .note:nth-child(2) .note__doodle { translate: 60px -6px; }
  .uses__list .note:nth-child(3) .note__doodle { translate: -33px -12px; }
  .uses__list .note:nth-child(4) .note__doodle { translate: 43px -27px; }
  .uses__list .note:nth-child(5) .note__doodle { translate: 30px -3px; }
  .uses__list .note:nth-child(6) .note__doodle { translate: -49px -8px; }
  .uses__list .note:nth-child(7) .note__doodle { translate: 75px -7px; }
  .uses__list .note:nth-child(8) .note__doodle { translate: -3px -8px; }
}

/* Desktop (lg Figma frame 1512x982): a stage that scales to fit the window, laid out in Figma coordinates, so the wording breaks on
   the same lines as the design at any laptop size. --u is one Figma px. Notes sit in full-size layers; text is centred on the
   centre of its Figma box (rotated about that centre), doodles at their Figma boxes. */
@media (min-width: 992px) {
  .uses { padding: 0; height: 100svh; display: grid; place-items: center; }
  .uses__stage { display: block; position: relative; width: min(100vw, calc(100svh * 1512 / 982)); aspect-ratio: 1512 / 982; container-type: inline-size; --u: calc(100cqw / 1512); }
  .lg-br { display: inline; }
  .uses__title { position: absolute; left: 50%; top: calc(127.5 / 982 * 100%); translate: -50% 0; max-width: none; margin: 0; white-space: nowrap; font-stretch: 75%; font-weight: 900; font-size: calc(80 * var(--u)); line-height: calc(80 * var(--u)); }
  .uses__list { position: absolute; inset: 0; display: block; margin: 0; }
  .note { position: absolute; inset: 0; width: 100%; height: 100%; display: block; max-width: none; margin: 0; transform: none; pointer-events: none; }
  .js .uses .note { transform: translateX(var(--from, -40px)); }
  .js .uses.is-in .note { transform: none; }
  .note__text { position: absolute; left: calc(var(--cx) / 1512 * 100%); top: calc(var(--cy) / 982 * 100%); translate: -50% -50%; rotate: var(--rot); width: max-content; white-space: nowrap; font-size: calc(20 * var(--u)); line-height: calc(28 * var(--u)); }
    .note__doodle { position: absolute; zoom: 1; left: calc(var(--dl) / 1512 * 100%); top: calc(var(--dt) / 982 * 100%); width: calc(var(--dw) * var(--u)); height: calc(var(--dh) * var(--u)); rotate: var(--dr, 0deg); }
  .uses__list .note:nth-child(1) .note__text { width: calc(var(--tw) * var(--u)); white-space: normal; --cx: 497.0; --cy: 266.4; --tw: 674; }
  .uses__list .note:nth-child(1) .note__doodle { --dl: 79.3; --dt: 257.4; --dw: 73.6; --dh: 43; }
  .uses__list .note:nth-child(2) .note__text { --cx: 1075.0; --cy: 331.8; }
  .uses__list .note:nth-child(2) .note__doodle { --dl: 1319.3; --dt: 314; --dw: 73.3; --dh: 46.2; }
  .uses__list .note:nth-child(3) .note__text { width: calc(var(--tw) * var(--u)); white-space: normal; --cx: 565.5; --cy: 393.0; --tw: 690; }
  .uses__list .note:nth-child(3) .note__doodle { --dl: 159.7; --dt: 363.1; --dw: 57; --dh: 49.2; }
  .uses__list .note:nth-child(4) .note__text { width: calc(var(--tw) * var(--u)); white-space: normal; --cx: 989.0; --cy: 449.05; --tw: 522.281; }
  .uses__list .note:nth-child(4) .note__doodle { --dl: 1261.62; --dt: 414.62; --dw: 49.3; --dh: 49.3; --dr: -1.46deg; }
  .uses__list .note:nth-child(5) .note__text { --cx: 756; --cy: 516.7; }
  .uses__list .note:nth-child(5) .note__doodle { --dl: 377.6; --dt: 473.7; --dw: 49.8; --dh: 49.8; }
  .uses__list .note:nth-child(6) .note__text { width: calc(var(--tw) * var(--u)); white-space: normal; --cx: 505.6; --cy: 578.5; --tw: 706; }
  .uses__list .note:nth-child(6) .note__doodle { --dl: 119.4; --dt: 539.1; --dw: 41.8; --dh: 65.1; }
  .uses__list .note:nth-child(7) .note__text { width: calc(var(--tw) * var(--u)); white-space: normal; --cx: 1028.9; --cy: 650.8; --tw: 694; }
  .uses__list .note:nth-child(7) .note__doodle { --dl: 641; --dt: 633.0; --dw: 53.6; --dh: 49.8; }
  .uses__list .note:nth-child(8) .note__text { --cx: 459.0; --cy: 726.9; }
  .uses__list .note:nth-child(8) .note__doodle { --dl: 199.4; --dt: 704.6; --dw: 52.9; --dh: 49.1; }
}

/* ==========================================================================
   Act 7 · Benefits (pinned, 3 beats)
   ========================================================================== */

.benefits { position: relative; background: var(--bg-invert); color: var(--fg-invert); }
.benefits__stage { position: absolute; inset: 0; overflow: hidden; }
.benefits.is-sticky { height: calc(100vh + var(--pin)); height: calc(100lvh + var(--pin)); }
.benefits.is-sticky .benefits__stage { position: sticky; inset: auto; top: 0; height: 100vh; height: 100lvh; }

/* Every photo stays "visible" (just stacked under the active one, and nearly transparent), so a phone keeps all three
   decoded and ready: a photo hidden with visibility can be dropped from memory, and then flashed dark as it wiped in. */
.beat { position: absolute; inset: 0; z-index: 0; opacity: .01; pointer-events: none; background: var(--bg-invert); }
.beat.is-active, .beat.is-entering, .beat.is-leaving { opacity: 1; }
.beat.is-active { z-index: 1; }
.beat.is-entering, .beat.is-leaving { z-index: 2; }

.beat__img, .beat__img img { position: absolute; inset: 0; width: 100%; height: 100%; }
.beat__img img { object-fit: cover; }
/* Scrim (Figma "scrim", Act 7 frames): bottom 55% of the frame, clear at the top, 80% ink by 80% of its height, then flat. */
.beat::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 55%; background: linear-gradient(to bottom, rgba(4, 17, 6, 0), rgba(4, 17, 6, .8) 80%); pointer-events: none; }

.beat__copy {
  position: absolute;
  left: var(--gutter);
  right: var(--gutter);
  /* Figma Act 7: the headline's last line ends at the same height on every beat (sm 140px above the frame bottom,
     lg 200px); the headline grows upward from there and the sub hangs below it, so a longer sub never moves the headline. */
  top: calc(100% - 140px - var(--bar-now)); /* --bar-now keeps it clear of the toolbar showing now */
  transition: top 250ms var(--ease); /* and glides as the toolbar comes and goes, rather than hopping */
  z-index: 1;
  display: flex;
  flex-direction: column;
  max-width: 900px;
}
.beat__title { position: absolute; left: 0; right: 0; bottom: 100%; font-stretch: 89%; font-weight: 700; font-size: 40px; line-height: 44px; letter-spacing: -.02em; }
.beat__sub { max-width: 620px; margin-top: 12px; font-size: 16px; line-height: 24px; }
/* Beat 2 sub is two sentences, one per line at every size (Figma: 56px tall on lg); the .ml runs-on-from-tablet rule would strand "life." */
.beat[data-beat="1"] .beat__sub .ml { display: block; }
@media (min-width: 768px) {
  .beat__copy { right: 120px; top: calc(100% - 200px - var(--bar-now)); }
  .beat__title { font-size: 80px; line-height: 80px; font-stretch: 75%; font-weight: 900; }
  .beat__sub { margin-top: 24px; font-size: 20px; line-height: 28px; }
}

/* ==========================================================================
   Act 8 · Sign-off (ink, cream wordmark)
   ========================================================================== */

.signoff {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 96px var(--gutter);
  padding-bottom: calc(96px + var(--bar-now)); /* centred in the visible screen */
  background: var(--brand-primary);
  color: var(--fg-invert);
  text-align: center;
}
.signoff__inner { display: flex; flex-direction: column; align-items: center; gap: 40px; width: 100%; }
.signoff__brand { display: flex; flex-direction: column; align-items: center; gap: 20px; }

/* Cream wordmark (the logo SVG used as a mask). */
.signoff__mark {
  width: 300px;
  max-width: 100%;
  aspect-ratio: 376 / 120;
  background-color: var(--fg-invert);
  -webkit-mask: url("../images/logo/twentyfive-logo-full-light.svg") center / contain no-repeat;
          mask: url("../images/logo/twentyfive-logo-full-light.svg") center / contain no-repeat;
}

.signoff__tag { font-stretch: 89%; font-weight: 400; font-size: 16px; line-height: 24px; }

/* Phones: three full-width buttons, stores first. */
.signoff__ctas { display: flex; flex-direction: column; gap: 8px; width: 100%; } /* phones: full width inside the 1.5rem gutters */
.signoff__ctas .btn { width: 100%; }
.signoff__try { order: 3; }

.signoff__legal { position: absolute; left: 0; right: 0; bottom: calc(40px + var(--bar-now)); display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 0 var(--gutter); font-stretch: 100%; font-size: 14px; line-height: 20px; }
@media (min-width: 768px) { .signoff__legal { flex-direction: row; justify-content: center; gap: 24px; } }

/* Legal links: footer of the home page and the legal pages. "Cookie settings"
   is a button (it opens the consent panel) styled to match the links. */
.legal-links { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 16px; }
.legal-links a, .legal-links button { padding: 0; border: 0; background: none; font: inherit; color: inherit; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.legal-links a:hover, .legal-links button:hover { text-decoration-thickness: 2px; }

/* Tablet: bigger wordmark, store buttons side by side, Try underneath. */
@media (min-width: 768px) {
  .signoff__mark { width: 501px; }
  .signoff__tag { font-stretch: 100%; font-size: 24px; line-height: normal; }
  .signoff__ctas { flex-direction: row; flex-wrap: wrap; justify-content: center; gap: 24px; max-width: 560px; }
  .signoff__ctas .btn { width: auto; }
}

/* Desktop: full-width wordmark, all three buttons in a row, Try in the middle. */
@media (min-width: 1200px) {
  .signoff__inner { gap: 80px; }
  .signoff__brand { gap: 40px; }
  .signoff__mark { width: 1003px; }
  .signoff__ctas { flex-wrap: nowrap; max-width: none; }
  .signoff__try { order: 0; }
}

/* ==========================================================================
   Centred text, every act and scene, phones and desktop (Robbie, 8 Oct 2026).
   Exceptions on purpose: the Life's too short notes keep their zigzag, the
   UI inside the summary cards and phone keeps its own alignment, and the
   phones' Act 3 tab rail scrolls sideways from the left edge.
   ========================================================================== */

/* Act 4a · Taboo */
.taboo__title { text-align: center; }
.taboo__swap { justify-items: center; }

/* Act 4 · Cards: title, quote and button centred (desktop: centred in the copy column) */
.cards__title, .cards__quote { text-align: center; }
.cards__quote { align-items: center; }
@media (min-width: 992px) { .cards__copy { align-items: center; text-align: center; } }

/* Act 6: the title (the notes keep their zigzag) */
.uses__title { margin-left: auto; margin-right: auto; text-align: center; }

/* Act 7: each beat's copy centred */
.beat__copy { align-items: center; text-align: center; margin-left: auto; margin-right: auto; }
@media (min-width: 768px) { .beat__copy { right: var(--gutter); } }

/* ==========================================================================
   Reduced motion: keep the content and states, drop the movement.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 1ms !important; animation-delay: 0ms !important; transition-duration: 1ms !important; transition-delay: 0ms !important; }
  .js [data-rise], .js .note, .js .note__doodle { opacity: 1; transform: none; }
  .js .note { transform: rotate(var(--rot)); }
}

/* Text for screen readers and crawlers only. */
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }

/* ==========================================================================
   Legal pages: /privacy, /cookies, /terms. Cream page, green wordmark home
   link and a "Back to home" button in a sticky bar, readable measure,
   the same legal links at the foot. No site.js on these pages.
   ========================================================================== */

html.legal-page, .legal-page body { background: var(--bg-default); }

.legal-bar {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 16px var(--gutter);
  background: var(--bg-default);
}
.legal-bar__logo { display: block; color: var(--brand-primary); }
.legal-bar__logo .wordmark { display: block; width: 87.7px; height: 28px; }
@media (min-width: 768px) { .legal-bar { padding-top: 24px; padding-bottom: 24px; } .legal-bar__logo .wordmark { width: 112.8px; height: 36px; } }

.legal {
  max-width: 720px;
  margin: 0 auto;
  padding: 32px var(--gutter) 96px;
  color: var(--fg-primary);
}
@media (min-width: 768px) { .legal { padding-top: 56px; } }
.legal__title { margin-bottom: 8px; }
@media (max-width: 767px) { .legal__title.heading-xl { font-size: 32px; line-height: 40px; } }
.legal__meta { color: var(--fg-secondary); font-size: 14px; line-height: 20px; }
.legal__draft {
  margin: 32px 0 8px;
  padding: 16px 20px;
  border: 2px solid var(--border-solid);
  border-radius: var(--radius-16);
  background: var(--brand-quaternary);
  font-size: 14px;
  line-height: 20px;
  font-weight: 600;
}
.legal h2 { margin: 40px 0 12px; font-stretch: 89%; font-weight: 700; font-size: 24px; line-height: 32px; }
.legal h3 { margin: 24px 0 8px; font-weight: 600; font-size: 16px; line-height: 24px; }
.legal p, .legal ul, .legal table { margin-bottom: 16px; }
.legal ul { padding-left: 20px; list-style: disc; }
.legal li + li { margin-top: 4px; }
.legal a:not(.btn) { text-underline-offset: 3px; }
.legal__actions { margin: 8px 0 24px; }

.legal table { width: 100%; border-collapse: collapse; font-size: 14px; line-height: 20px; }
.legal th, .legal td { padding: 12px 12px 12px 0; text-align: left; vertical-align: top; border-bottom: 2px solid var(--border-subtle); }
.legal th { font-weight: 600; }
.legal__table-wrap { overflow-x: auto; }

.legal-foot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  padding: 40px var(--gutter) calc(40px + env(safe-area-inset-bottom, 0px));
  background: var(--brand-primary);
  color: var(--fg-invert);
  font-size: 14px;
  line-height: 20px;
  text-align: center;
}
.legal-foot .btn { --btn-edge: var(--border-invert); }

/* Phones: each table row becomes a stacked block, cells labelled from the header. */
@media (max-width: 767px) {
  .legal table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .legal table, .legal tbody, .legal tr, .legal td { display: block; }
  .legal tr { padding: 12px 0; border-bottom: 2px solid var(--border-subtle); }
  .legal td { padding: 4px 0; border: 0; }
  .legal td::before { content: attr(data-label); display: block; font-weight: 600; }
}
