/* ============================================================
   Mentor — landing page stylesheet
   Tokens from ar-lp-design-system.md. Structure and animation
   patterns ported from the KenAI landing (header choreography,
   footer, scroll reveal), restyled for the Mentor system:
   pure black canvas, one green accent, Lora 400 everywhere.
   ============================================================ */

/* ---------- fonts ---------- */

@font-face {
  font-family: "Lora";
  src: url("../fonts/Lora-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Source Sans 3";
  src: url("../fonts/SourceSans3-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* ---------- tokens ---------- */

:root {
  /* foundation */
  --bg-primary: #000000;
  --bg-secondary: #181818;
  --bg-deep: #0a0a0a; /* deep section band — between the black canvas and --bg-secondary */
  --bg-surface: #262626;
  --bg-overlay: #26262680;

  /* accent — scarce by design */
  --accent: #00bf63;
  --accent-20: #00bf6333;
  --accent-30: #00bf634d;
  --accent-50: #00bf6380;
  --accent-70: #00bf63b3;

  /* text */
  --text-primary: #ffffff;
  --text-secondary: #ffffffb2;
  --text-tertiary: #ffffff80;
  --text-disabled: #ffffff4d;
  --text-inverse: #181818;

  /* lines and states */
  --border-default: #262626;
  --border-subtle: #26262680;
  --border-focus: #00bf63;
  --success: #00bf63;
  --error: #ff4757;
  --info: #00bf6333;
  --glass: #808080;

  /* type scale */
  --fs-display: 36px;
  --fs-xxl: 28px;
  --fs-xl: 20px;
  --fs-heading: 18px;
  --fs-lg: 16px;
  --fs-md: 14px;
  --fs-sm: 12px;
  --fs-xs: 11px;
  --lh-tight: 1.2;
  --lh-normal: 1.4;
  --lh-loose: 1.6;

  /* spacing — 4pt scale */
  --space-xs: 4px;
  --space-sm: 6px;
  --space-md: 8px;
  --space-lg: 16px;
  --space-xl: 24px;
  --space-xxl: 32px;
  --space-xxxl: 48px;

  /* radius */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 16px;
  --radius-xl: 24px;
  --radius-full: 9999px;

  /* type pairing: Lora carries the voice (headings, countdown),
     Source Sans 3 does the reading (body, UI) */
  --font-display: "Lora", Georgia, serif;
  --font-body: "Source Sans 3", -apple-system, "Segoe UI", sans-serif;
  /* the nav runs on a mono face — fixed advance widths keep the
     scramble hover from jittering as letters cycle */
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  /* the nav's two easings, lifted straight from the reference bar */
  --ease-out-expo: cubic-bezier(0.19, 1, 0.22, 1);
  --ease-morph: cubic-bezier(0.6, 0.14, 0, 1);

  /* Liquid glass — the menu pill's recipe, in one place so every surface
     that claims to be "the pill" is literally the same glass. A lifted,
     blurred slab of the canvas rather than a flat band: a deliberate
     tokens-only exception, like the old bar. Used by .nav, .nav-menu and
     the footer's .foot-pill. */
  --glass-fill: rgba(38, 38, 38, 0.55);
  --glass-line: rgba(255, 255, 255, 0.08);
  --glass-blur: blur(20px) saturate(140%);
  --glass-lift: 0 12px 40px rgba(0, 0, 0, 0.45);

  /* Every app mockup on the page is this width, at every viewport — one
     token so they can never drift apart section to section, and a flat
     pixel value so they never resize with the window. Deliberately no
     vw/vh terms: a mockup that shrinks with the screen is a bug here. */
  --mock-w: 272px;
  /* the one narrower width, for the places where mockups stand three to
     a row: the Focus Zone screens under the metrics strip, and the daily
     notifications, which line up with them down the page. Solved from
     the reading measure rather than typed in, so the three screens and
     their two hairline gaps fill a block exactly — 246px today. Still
     flat: --measure is itself a fixed pixel value. */
  --mock-w-focus: calc((var(--measure) - var(--space-md) * 2) / 3);
  /* the phone mockup's height: --mock-w through the 1286/2516 shell
     aspect. It's the tallest thing in a pinned .scrub, so it's what the
     pinned box is really sized by */
  --mock-h: 532px;

  /* the air above every title inside the long "How it works?" stretch —
     one value so the three blocks keep the same rhythm down the page */
  --block-gap: calc(var(--space-xxxl) * 2);

  --header-h: 100px;
  /* where an anchored section's top edge comes to rest, clear of the
     pill — the offset every in-page link scrolls to */
  --anchor-top: 116px;
  /* the pill's natural width on desktop, where it sizes to its own
     content. It's the ceiling everywhere: on tablet and phone the pill
     stretches to the viewport but must never grow past this. */
  --nav-max: 786px;
  /* the pill's height where the menu button lives (tablet and phone):
     the 40px toggle, the pill's 8px of padding either side, and its
     hairline. The menu sheet hangs off this. */
  --nav-pill-h: 58px;
  /* the sheet's own margin — the left edge every label lines up on */
  --menu-pad: 24px;

  /* the one reading column the whole philosophy arc runs in — the pinned
     copy and the mission both share it. It tracks the nav pill's width,
     set this far inside the pill's edges on each side, at every
     viewport. Hence the odd gutter on those blocks: the header's own
     16px plus this inset, rather than the page's usual 20px. */
  --measure-inset: 16px;
  --measure: calc(var(--nav-max) - var(--measure-inset) * 2);
  --measure-gutter: calc(16px + var(--measure-inset));
}

/* half the block rhythm on phones, where each block is already tall */
@media (max-width: 880px) {
  :root { --block-gap: var(--space-xxxl); }
}

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

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

html { scroll-behavior: smooth; scroll-padding-top: var(--anchor-top); }

body {
  background: var(--bg-primary);
  color: var(--text-primary);
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--fs-lg);
  line-height: var(--lh-loose);
  -webkit-font-smoothing: antialiased;
}

/* the display face on everything that speaks with the brand voice */
h1, h2, h3, h4, h5, h6,
.eyebrow,
.cd-digit, .cd-sep, .launch-label {
  font-family: var(--font-display);
}

/* one face, one weight — never let the browser synthesize a bold,
   and no italics: emphasis is size, color, and spacing */
b, strong, h1, h2, h3, h4, h5, h6, th { font-weight: 400; }
em, i { font-style: normal; }

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

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--border-focus);
  outline-offset: 2px;
}

.container { max-width: 1120px; margin: 0 auto; padding: 0 20px; }
.container--narrow { max-width: 840px; }
/* the philosophy column's reading measure — for blocks that have to line
   up with it edge to edge */
.container--measure {
  max-width: calc(var(--measure) + var(--measure-gutter) * 2);
  padding-left: var(--measure-gutter);
  padding-right: var(--measure-gutter);
}
/* the measure is already the reading width — a second cap inside it
   would just pull the copy off the column's right edge */
.container--measure .section-head { max-width: none; }

/* Mockups hold a fixed width at every screen size, so on the narrowest
   phones it's the gutter that gives way, not the artwork. */
@media (max-width: 344px) {
  .container, .container--measure { padding-left: 16px; padding-right: 16px; }
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- type helpers ---------- */

h1 { font-size: var(--fs-display); line-height: var(--lh-tight); }
h2 { font-size: var(--fs-xxl); line-height: var(--lh-tight); }
h3 { font-size: var(--fs-xl); line-height: var(--lh-tight); }

/* emphasis is size, color, and spacing — not weight */
.eyebrow {
  display: block;
  color: var(--text-tertiary);
  font-size: var(--fs-sm);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  margin-bottom: var(--space-lg);
}

.lead {
  color: var(--text-secondary);
  font-size: var(--fs-lg);
  line-height: var(--lh-loose);
  /* the copy under a block title reads as the philosophy column does:
     lines spread to both edges of the measure it runs in */
  text-align: justify;
}

/* ---------- buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-md);
  padding: var(--space-md) var(--space-lg);
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  font-family: var(--font-body);
  font-size: var(--fs-lg);
  line-height: var(--lh-tight);
  cursor: pointer;
  text-decoration: none;
  transition: background-color 0.15s ease, border-color 0.15s ease,
    color 0.15s ease, filter 0.15s ease, transform 0.18s ease;
}
.btn:hover { text-decoration: none; transform: translateY(-2px); }
.btn:active { transform: translateY(0); }

.btn--primary {
  background: var(--accent);
  color: var(--text-inverse);
}
.btn--primary:hover { filter: brightness(1.12); }

.btn--secondary {
  background: transparent;
  border-color: var(--accent-50);
  color: var(--accent);
}
.btn--secondary:hover { background: var(--accent-20); border-color: var(--accent); }

.btn--small { padding: var(--space-md) var(--space-lg); font-size: var(--fs-md); }

/* ============================================================
   Header — a floating glass pill, centred over the page. It stays
   at the top of the viewport the whole way down; nothing hides it.
   ============================================================ */

.site-header {
  position: fixed;
  top: 12px;
  left: 0;
  right: 0;
  z-index: 50;
  display: flex;
  justify-content: center;
  padding: 0 16px;
  /* only the pill itself catches the pointer — the rest of the row
     stays transparent to clicks on the page behind it */
  pointer-events: none;
  transition:
    opacity 0.5s var(--ease-out-expo),
    transform 0.5s var(--ease-out-expo),
    visibility 0.5s var(--ease-out-expo);
}

/* Parked: the footer is this same pill restated, so the two are never
   on screen together. main.js sets this the moment the footer is
   properly in view, and clears it as soon as you scroll away. */
.site-header.is-parked,
.top-scrim.is-parked {
  opacity: 0;
  transform: translateY(-16px);
  /* the pill inside sets pointer-events: auto — only visibility takes
     it out of reach while it's parked */
  visibility: hidden;
}
.top-scrim { transition: opacity 0.5s var(--ease-out-expo), visibility 0.5s var(--ease-out-expo); }
.top-scrim.is-parked { transform: none; }

@media (prefers-reduced-motion: reduce) {
  .site-header.is-parked { transform: none; }
}

/* The scrim: a full-width wash of black under the menu, spanning the
   viewport rather than just the pill, so copy travelling up beside the
   pill sinks away exactly as copy passing behind it does. Solid through
   the pill's full height — nothing shows above or beside the menu —
   then a short taper, so it never spreads into the reading area.
   On for the whole page: anything that scrolls up to the menu has to
   disappear under it, not ride past its edges. */

.top-scrim {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  /* solid only as far as the pill's own bottom edge (74px), then out in
     a short taper: past that line the page should read normally, so the
     wash never eats into content that has already cleared the menu */
  height: 86px;
  /* under the pill, over the page */
  z-index: 49;
  pointer-events: none;
  background: linear-gradient(
    180deg,
    #000 0,
    #000 74px,
    rgba(0, 0, 0, 0.34) 80px,
    rgba(0, 0, 0, 0) 86px
  );
}

/* ---------- the pill ---------- */

.nav {
  pointer-events: auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* pinned, not content-sized: the pill used to be as wide as whatever
     the labels happened to measure, so renaming one resized the header.
     At --nav-max it also finally matches the footer pill, which the
     footer's own comment already claimed it did. */
  width: min(100%, var(--nav-max));
  padding: 8px 8px 8px 20px;
  border: 1px solid var(--glass-line);
  border-radius: var(--radius-lg);
  background: var(--glass-fill);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-lift);
  overflow: hidden;
  -webkit-user-select: none;
  user-select: none;
  transition: width 1s var(--ease-morph);
}

.nav__logo {
  display: inline-flex;
  flex: none;
  /* The mark is a wide one — two circles, 1.77:1 — so it's sized and
     spaced to keep the row inside --nav-max. At 40px tall it ran the
     pill 31px past the cap and clipped the CTA; shorter here, it still
     covers more width than the square tile it replaced. */
  height: 34px;
  margin-right: 16px;
}
.nav__logo img {
  height: 100%;
  width: auto;
  transform-origin: center;
  transition: transform 0.5s var(--ease-out-expo);
}
.nav__logo:hover img { transform: scale(1.12); }

.nav__right {
  display: flex;
  align-items: center;
  gap: 24px;
}

.nav__items {
  display: inline-flex;
  align-items: center;
  gap: 26px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.02em;
}

.nav__item {
  display: inline-flex;
  color: rgba(255, 255, 255, 0.86);
  text-decoration: none;
  white-space: nowrap;
  transition: color 1s var(--ease-out-expo);
}
.nav__item:hover {
  color: var(--text-primary);
  text-decoration: none;
}

/* labelled, but with nowhere to go yet — held back so a click that does
   nothing never reads as a broken link */
.nav__item--pending {
  color: var(--text-disabled);
  cursor: default;
}
.nav__item--pending:hover { color: var(--text-disabled); background: none; }

/* ---------- scramble labels ----------
   main.js splits each label into a live span (the one that cycles)
   and a hidden ghost that holds the real text; the ghost's measured
   width is pinned onto the element so nothing shifts mid-scramble. */

[data-scramble] {
  position: relative;
  width: var(--scramble-width, auto);
}
[data-scramble] > span { pointer-events: none; }
[data-scramble] > .scramble__ghost {
  position: absolute;
  left: 0;
  top: 0;
  visibility: hidden;
}

/* ---------- CTA ---------- */

.nav__cta {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  margin: 0;
  padding: 16px 26px;
  border: none;
  background: transparent;
  -webkit-appearance: none;
  appearance: none;
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
}
/* the fill lives on a pseudo-element so it can drain to transparent
   while the label crosses the other way */
.nav__cta::before {
  content: "";
  position: absolute;
  inset: 0;
  border: 1px solid var(--accent);
  border-radius: var(--radius-lg);
  background: var(--accent);
  transition: background 1s var(--ease-out-expo), border-color 1s var(--ease-out-expo);
}
.nav__cta span {
  position: relative;
  z-index: 1;
  /* white, eased back a touch so it sits into the green rather than
     sitting on top of it */
  color: rgba(255, 255, 255, 0.85);
  white-space: nowrap;
  transition: color 1s var(--ease-out-expo);
}
.nav__cta:hover { text-decoration: none; }
.nav__cta:hover::before { background: transparent; }
.nav__cta:hover span { color: var(--accent); }

/* ---------- menu toggle + panel (tablet / mobile) ---------- */

.nav__toggle {
  display: none;
  align-items: center;
  height: 40px;
  margin-right: 12px;
  padding: 0;
  border: none;
  background: none;
  color: var(--text-primary);
  font-family: var(--font-mono);
  font-size: 12px;
  cursor: pointer;
}

/* The sheet: the pill's own width, hung from just under it and run to
   within a hair of the bottom of the screen. It carries no surface of
   its own — .nav-menu__bg is the glass, so the curtain can drop while
   the labels stagger in over it — and clips, so the curtain is out of
   sight until it travels. */

.nav-menu {
  position: fixed;
  /* 12px header offset + the pill's height + the pill's own gap */
  top: calc(12px + var(--nav-pill-h) + 8px);
  left: 50%;
  transform: translateX(-50%);
  width: min(calc(100vw - 32px), var(--nav-max));
  /* the same 12px of air at the foot as the pill has at the head */
  height: calc(100dvh - 12px - var(--nav-pill-h) - 8px - 12px);
  display: none;
  flex-direction: column;
  /* the block of labels rides the middle of the sheet, flush left */
  justify-content: center;
  align-items: flex-start;
  padding: 0 var(--menu-pad);
  border-radius: var(--radius-lg);
  overflow: clip;
}

/* the glass, as a layer of its own: it hangs above the sheet's top edge
   and drops into place, hinged at the top */
.nav-menu__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  border: 1px solid var(--glass-line);
  border-radius: var(--radius-lg);
  /* denser than the pill — a full-height sheet has to stay legible
     over whatever section it lands on */
  background: rgba(22, 22, 22, 0.86);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-lift);
  transform-origin: top;
  will-change: transform;
  transition: transform 1s var(--ease-morph);
}

.nav-menu__items {
  position: relative;
  z-index: 1;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  /* set well clear of the labels' own line height: the stack reads as a
     list of destinations, not as a paragraph of them */
  gap: 18px;
  text-align: left;
  /* only the labels themselves take the pointer, so the empty column
     beside them stays transparent */
  pointer-events: none;
}

.nav-menu__item {
  pointer-events: auto;
  color: var(--text-primary);
  font-family: var(--font-display);
  font-size: 30px;
  /* set tight, the way a stack of display lines wants to be — a touch
     looser than a sans would take it, since Lora carries descenders */
  line-height: 0.95;
  letter-spacing: -0.01em;
  text-decoration: none;
  transition:
    transform 1.5s var(--ease-out-expo),
    opacity 1.5s var(--ease-out-expo),
    color 1s var(--ease-out-expo);
}
.nav-menu__item:hover { text-decoration: none; }

/* the whole stack recedes while you read one line of it — pointer only,
   since a tap leaves :hover stuck on the line you just left */
@media (hover: hover) {
  .nav-menu__items:hover .nav-menu__item:not(:hover) { color: var(--text-disabled); }
}

/* held back in the sheet too — .nav-menu__item's own colour would
   otherwise win on source order */
.nav-menu__item.nav__item--pending { color: var(--text-disabled); cursor: default; }

/* the quiet pair under the labels: the same left edge, mono, small */
.nav-menu__bottom {
  position: relative;
  z-index: 1;
  width: 100%;
  margin-top: 32px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  pointer-events: none;
}
.nav-menu__sub {
  pointer-events: auto;
  color: var(--text-tertiary);
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1;
  text-decoration: none;
  transition:
    transform 1.5s var(--ease-out-expo),
    opacity 1.5s var(--ease-out-expo),
    color 1s var(--ease-out-expo);
}
.nav-menu__sub:hover { color: var(--text-primary); text-decoration: none; }

/* the CTA sits on the floor of the sheet, spanning the label column */
.nav-menu__cta {
  position: absolute;
  z-index: 1;
  /* the header is pointer-events: none, so the CTA has to claim the
     pointer for itself the way the labels above it do */
  pointer-events: auto;
  left: var(--menu-pad);
  bottom: 24px;
  width: calc(100% - var(--menu-pad) * 2);
  transition:
    transform 1s var(--ease-out-expo),
    opacity 1s var(--ease-out-expo);
}

@media (max-width: 880px) {
  .nav { width: 100%; }
  .nav__items, .nav__right > .nav__cta { display: none; }
  .nav__toggle { display: inline-flex; }
  .nav-menu { display: flex; }

  /* Closed: the glass is parked above its own top edge and every line
     is dropped and faded out. Nothing is hidden — it's all simply off
     the sheet — so opening is one continuous move rather than a
     reveal. The closed state also carries the reversed stagger: the
     last line in leaves first. */
  .site-header:not(.nav-open) .nav-menu,
  .site-header:not(.nav-open) .nav-menu * { pointer-events: none !important; }

  .site-header:not(.nav-open) .nav-menu__bg {
    transform: translateY(-102%);
    transition-delay: 0.5s;
  }
  .site-header:not(.nav-open) .nav-menu__item {
    opacity: 0;
    transform: translateY(48px);
  }
  .site-header:not(.nav-open) .nav-menu__sub {
    opacity: 0;
    transform: translateY(24px);
  }
  .site-header:not(.nav-open) .nav-menu__cta {
    opacity: 0;
    transform: translateY(32px);
    transition-delay: 0s;
  }

  /* out, last line first */
  .site-header:not(.nav-open) .nav-menu__item:nth-child(1) { transition-delay: 0.30s; }
  .site-header:not(.nav-open) .nav-menu__item:nth-child(2) { transition-delay: 0.25s; }
  .site-header:not(.nav-open) .nav-menu__item:nth-child(3) { transition-delay: 0.20s; }
  .site-header:not(.nav-open) .nav-menu__item:nth-child(4) { transition-delay: 0.15s; }
  .site-header:not(.nav-open) .nav-menu__item:nth-child(5) { transition-delay: 0.10s; }
  .site-header:not(.nav-open) .nav-menu__item:nth-child(6) { transition-delay: 0.05s; }
  .site-header:not(.nav-open) .nav-menu__sub { transition-delay: 0s; }

  /* in, first line first, behind the falling glass */
  .site-header.nav-open .nav-menu__bg { transition-delay: 0s; }
  .site-header.nav-open .nav-menu__item:nth-child(1) { transition-delay: 0.30s; }
  .site-header.nav-open .nav-menu__item:nth-child(2) { transition-delay: 0.36s; }
  .site-header.nav-open .nav-menu__item:nth-child(3) { transition-delay: 0.42s; }
  .site-header.nav-open .nav-menu__item:nth-child(4) { transition-delay: 0.48s; }
  .site-header.nav-open .nav-menu__item:nth-child(5) { transition-delay: 0.54s; }
  .site-header.nav-open .nav-menu__item:nth-child(6) { transition-delay: 0.60s; }
  .site-header.nav-open .nav-menu__sub { transition-delay: 0.66s; }
  .site-header.nav-open .nav-menu__cta { transition-delay: 0.55s; }
}

/* small phones: tighten the pill until the row fits */
@media (max-width: 520px) {
  .scrub__sticky { padding-top: calc(60px + var(--space-lg)); }
  .nav { padding: 8px 8px 8px 12px; }
  .nav__logo { height: 34px; margin-right: 16px; }
  .nav__toggle { margin-right: 8px; font-size: 12px; }
  .nav-menu { --menu-pad: 20px; }
  .nav-menu__item { font-size: 26px; }
}

/* the sheet is choreography, not information — with motion damped it
   simply is or isn't there */
@media (prefers-reduced-motion: reduce) {
  .nav-menu__bg,
  .nav-menu__item,
  .nav-menu__sub,
  .nav-menu__cta {
    transition-duration: 0.01ms !important;
    transition-delay: 0s !important;
  }
  .site-header:not(.nav-open) .nav-menu__item,
  .site-header:not(.nav-open) .nav-menu__sub,
  .site-header:not(.nav-open) .nav-menu__cta { transform: none; }
}

/* ============================================================
   Sections
   ============================================================ */

.section { padding: var(--space-xxxl) 0; }
@media (min-width: 768px) {
  .section { padding: calc(var(--space-xxxl) * 2) 0; }
}

/* elevation ladder bands — depth is value, not shadow. Set per
   section rather than by nth-of-type: the philosophy arc (Philosophy,
   Framework, Mission) has to read as one unbroken black canvas, and
   the two Life Area scrubs likewise. */
/* #mind is deliberately absent: it overlaps #body and must not paint
   over it — see `.scrub + .scrub`, which makes it transparent */
#philosophy, #framework, #mission,
#body, #guidance,
/* the page closes the way it opened, on the black canvas — the pricing
   cards carry their own fill, so they don't need a band under them */
#pricing { background: var(--bg-primary); }
/* one continuous band: the Mentor blocks, the tracking strip and the
   daily check-ins read as a single stretch of the page */
#meet, #metrics, #guidance { background: var(--bg-deep); }
/* the team lifts off the canvas on its own band, between the last black
   scrub above it and the black pricing block below */
#why-us { background: var(--bg-deep); }
/* the band opens on the same air its inner blocks are spaced by, so the
   first title sits as far from what's above it as the other two do. The
   mission's own padding is black, before the band starts — that gap
   closes the philosophy arc and is separate from the band's rhythm. */
#mission { padding-bottom: calc(var(--space-xxxl) * 3); }
#meet { padding-top: var(--block-gap); }
/* The last block used to be forced onto the band so it never met the
   black footer flush. Pricing meets it deliberately: the footer's glass
   pill floats clear of the canvas, so the seam reads as air, not as two
   sections running together. */

.section-head { max-width: 720px; margin-bottom: var(--space-xxl); }
.section-head--center { margin-left: auto; margin-right: auto; text-align: center; }
.section-head h2 { margin-bottom: var(--space-lg); }
.section-head .lead { color: var(--text-secondary); }

/* two-column split (copy | mockup) */
.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: calc(var(--space-xxxl) + var(--space-lg));
  align-items: center;
}
@media (max-width: 880px) {
  .split { grid-template-columns: 1fr; gap: var(--space-xxl); }
}
.split--flip > *:first-child { order: 2; }
@media (max-width: 880px) {
  .split--flip > *:first-child { order: 0; }
}

/* a second split row inside the same section */
.split--follow { margin-top: calc(var(--space-xxxl) * 1.5); }

/* plain screenshot mockup — the renders carry their own phone frame,
   so no border or clipping; vh caps keep them whole on laptop screens */
.mockup {
  width: var(--mock-w);
  margin: 0 auto;
}
/* a touch dimmer so the screenshots sit into the dark page rather
   than glowing on top of it */
.mockup img { width: 100%; height: auto; filter: brightness(0.8); }
/* the same dim for sections that don't use .mockup: the Life Area
   phones (shell + canvas dim together, so the screen seam calibration
   in .phone__video keeps holding), the metrics filmstrip, and the
   daily-guidance shots */
.phone,
.day-shot__notif { filter: brightness(0.8); }
/* the plain phone's screen is a flat #181818; this takes it down to the
   band's own #0a0a0a so the handset reads as an outline on the block
   rather than a lighter panel sitting on it */
.day-shot__crop { filter: brightness(0.4167); }


/* ---------- life-area chips (Meet Mentor) ---------- */

/* two columns at every width — the reading measure this block runs in
   has no room for a third */
.area-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-md);
}
/* the same still card as the pricing cards: one fill, one radius, and
   nothing that moves under the pointer — these are six things to read,
   not six things to choose between */
.area-chip {
  background: var(--bg-secondary);
  border-radius: var(--radius-lg);
  padding: var(--space-lg);
}
.area-chip h3 { font-size: var(--fs-heading); margin-bottom: var(--space-sm); }
.area-chip ul {
  list-style: none;
  color: var(--text-tertiary);
  font-size: var(--fs-sm);
  line-height: var(--lh-normal);
}
.area-chip li {
  position: relative;
  padding-left: var(--space-lg);
  margin-bottom: 2px;
}
.area-chip li::before {
  content: "";
  position: absolute;
  left: var(--space-xs);
  top: 0.55em;
  width: 3px;
  height: 3px;
  border-radius: var(--radius-full);
  background: var(--text-disabled);
}

/* ============================================================
   Meet Mentor — two plain blocks stacked down the page: the Life
   Area cards beside the home screen, then the example questions
   beside the chat. No pin, no scrub; each block reveals on scroll.
   ============================================================ */

/* the whole thing runs in the same reading measure as the philosophy
   column and the mission band */
.meet__wrap {
  width: 100%;
  max-width: calc(var(--measure) + var(--measure-gutter) * 2);
  padding-left: var(--measure-gutter);
  padding-right: var(--measure-gutter);
}
.meet__block + .meet__block { margin-top: var(--block-gap); }

/* the heading band runs the block's full width, sitting right on top
   of the cards and the phone, close enough to read as one unit */
.meet__head { max-width: none; margin-bottom: var(--space-xxxl); }

.meet__grid {
  display: grid;
  /* the phone column sizes to the phone itself, so the copy keeps
     everything else — and the two sit close together */
  grid-template-columns: 1fr auto;
  gap: var(--space-lg);
  /* the row is as tall as the phone, and the cards or the questions
     fill it, so both halves square off top and bottom */
  align-items: stretch;
}
/* the second block runs the other way round: phone first */
.meet__grid--flip { grid-template-columns: auto 1fr; }

.meet__mock {
  margin: 0;
  align-self: start; /* the phone keeps its own height */
  justify-self: end; /* flush with the block's edge, like the header CTA */
}
.meet__grid--flip .meet__mock { justify-self: start; }

/* the rows stay content-tall, so every card keeps the same inner
   padding; the height left over to reach the phone goes into the gaps
   between rows instead of inflating the cards */
.meet__grid .area-grid { height: 100%; align-content: space-between; }
.meet__grid .ask-list { height: 100%; justify-content: space-between; }

/* example questions — quiet chat bubbles, the flattened corner marks
   them as the user's side of the conversation */
.ask-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-md);
}
.ask-list li {
  padding: var(--space-md) var(--space-lg);
  background: var(--bg-secondary);
  border-radius: var(--radius-lg);
  border-bottom-left-radius: var(--radius-sm);
  color: var(--text-secondary);
  font-size: var(--fs-md);
  line-height: var(--lh-normal);
}

@media (max-width: 880px) {
  /* one column: copy first, then the phone under it — in both blocks */
  .meet__grid,
  .meet__grid--flip {
    grid-template-columns: 1fr;
    gap: var(--space-xl);
  }
  /* both mockups sit on the copy's left edge, not centred — the column
     reads down one margin */
  .meet__mock,
  .meet__grid--flip .meet__mock {
    justify-self: start;
    order: 1;
  }
  /* nothing to stretch to any more — let both sides size themselves */
  .meet__grid .area-grid,
  .meet__grid .ask-list { height: auto; }
}

/* ============================================================
   Typing reveal — a ghost copy of the line holds the space (and
   the accessible text) while an absolutely-positioned live copy
   types itself over it, so nothing reflows mid-reveal.
   Wired up by initType() in main.js.
   ============================================================ */

.type { position: relative; }
/* the ghost is invisible but still in flow, so it has to stay out of
   selection — otherwise copying a line yields the text twice */
.type__ghost {
  opacity: 0;
  -webkit-user-select: none;
          user-select: none;
}
.type__live {
  position: absolute;
  inset: 0;
  /* the live copy repeats the ghost verbatim — it can never overflow */
  overflow: hidden;
}
.type__caret {
  display: inline-block;
  width: 2px;
  height: 0.92em;
  /* zero net advance: the caret must never change where a line wraps,
     or the last word would jump as it types */
  margin-left: 0.08em;
  margin-right: calc(-2px - 0.08em);
  vertical-align: -0.12em;
  background: var(--accent);
  animation: caret-blink 1.05s steps(1, end) infinite;
}
@keyframes caret-blink {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

/* ============================================================
   Philosophy — the opening block. The frame holds still and only
   the column of text travels up through it (main.js drives the
   track's transform from scroll progress).
   ============================================================ */

.phil {
  position: relative;
  min-height: 100vh;
  background: var(--bg-primary);
}
.phil__sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  /* the header's gutter plus the inset, so the column tracks the pill */
  padding: 0 var(--measure-gutter);
  overflow: hidden;
}
.phil__frame {
  position: relative;
  width: min(var(--measure), 100%);
  height: 100%;
  overflow: hidden;
  /* text dissolves at both ends of the frame instead of clipping — the
     bottom fade is shallow so the last line can rest close to the edge
     without dimming */
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 14%, #000 93%, transparent 100%);
          mask-image: linear-gradient(180deg, transparent 0, #000 14%, #000 93%, transparent 100%);
}
.phil__track {
  /* the top pad clears the header pill and starts the copy inside the
     opaque middle of the frame mask; the bottom one only has to clear
     that shallow bottom fade — half what it was, so the column closes
     up under its last line. Fixed px, not vh: the column reads the same
     on every screen and only the travel distance changes. */
  padding: 162px 0 40px;
  will-change: transform;
}

.phil__title {
  /* same size as the section headings across the page (.section-head h2
     and friends) — this is a heading, not a display line */
  font-size: var(--fs-xxl);
  line-height: var(--lh-tight);
  /* the subtitle carries the wide rhythm below the pair, so the gap here
     is only what separates a title from its own subtitle */
  margin-bottom: var(--space-md);
}
.phil__subtitle {
  /* one step down the scale and one step down the text ramp: it reads as
     the title's second line, not as a heading of its own */
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  line-height: var(--lh-tight);
  color: var(--text-tertiary);
  /* the rhythm is deliberately wide: the column has to be taller than
     the frame for the travel to read as travel */
  margin-bottom: 72px;
}
.phil__p {
  margin-bottom: 81px;
  color: var(--text-secondary);
  font-size: clamp(16px, 1.4vw, 19px);
  line-height: 1.72;
  /* lines spread to the full column width, same as the legal pages */
  text-align: justify;
  /* a newline in the markup is a line break here; runs of spaces still
     collapse, so the source can stay indented */
  white-space: pre-line;
}
.phil__p:last-child { margin-bottom: 0; }

/* no pin without motion: the whole column just sits in the page */
.phil--static { min-height: 0; }
.phil--static .phil__sticky {
  position: static;
  height: auto;
  padding: calc(var(--space-xxxl) * 2) var(--measure-gutter);
  overflow: visible;
}
.phil--static .phil__frame {
  height: auto;
  -webkit-mask-image: none;
          mask-image: none;
}
.phil--static .phil__track {
  padding: 0;
  transform: none !important;
}

/* ============================================================
   The Prime Framework — pinned: the diagram holds in place while
   scroll scrubs it through its stages.
   ============================================================ */

.fw {
  position: relative;
  height: 300vh;
  background: var(--bg-primary);
}
.fw__sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  display: flex;
  align-items: center;
  overflow: hidden;
}
.fw__inner {
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 100%;
  height: 100%;
  /* the reading column's own gutter — the diagram lands on exactly the
     body text's width */
  max-width: calc(var(--measure) + var(--measure-gutter) * 2);
  padding-left: var(--measure-gutter);
  padding-right: var(--measure-gutter);
  /* symmetric, so the diagram sits dead centre: equal air above and
     below. It only bites on short viewports, where it keeps the diagram
     clear of the header pill */
  padding-top: 80px;
  padding-bottom: 80px;
}
/* the stage is sized from its own width and the drawing's proportions,
   never from what's left of the viewport — otherwise a shorter window
   scales the whole diagram down with it */
.fw__stage {
  flex: none;
  width: 100%;
  aspect-ratio: 1140.6 / 793.05;
  display: flex;
}
/* the portrait drawing stands taller than the column is wide, so it is
   the one that also has to answer to the viewport — past that it would
   be cut by the pin rather than merely small */
.fw__stage--port {
  display: none;
  aspect-ratio: 796.5 / 1118.75;
  max-height: 100%;
}
.fw__svg {
  width: 100%;
  height: 100%;
  display: block;
}
.fw__svg text {
  font-family: var(--font-body);
  font-weight: 400;
  letter-spacing: 0.02em;
}
.fw-node { font-size: 30px; }
.fw-label { font-size: 23px; }
/* the portrait drawing carries its own type scale: its circles are
   drawn larger than the wide one's, so the sizes aren't shared. The
   sizes also answer to the box — the drawing spans a wider viewBox than
   it once did, so every user unit lands smaller on the phone; these
   carry the matching 6.7% back, keeping the type where it read before */
.fw__svg--port .fw-node { font-size: 36.3px; }
.fw__svg--port .fw-node--space { font-size: 32px; }
.fw__svg--port .fw-label { font-size: 23.5px; }

/* the surface of both wells keeps moving — ambient, not scroll-driven */
@keyframes fw-wave-shift {
  from { transform: translateX(0); }
  to { transform: translateX(-70px); }
}
.fw-wave { animation: fw-wave-shift 2.2s linear infinite; }

/* narrow screens: the diagram is much smaller, so the labels inside
   the circles need the size back */
@media (max-width: 880px) {
  .fw { height: 320vh; }
  .fw-node { font-size: 36px; }
  .fw-label { font-size: 30px; }
}

/* phones: the portrait drawing takes over — it uses the height a phone
   actually has instead of squeezing the wide one into a strip. The
   inner box keeps its air, but weighted: on a short phone the drawing
   fills that box exactly, and only the top of it is crowded — by the
   menu pill, which sits 12px down and stands 58px tall. Same 160px in
   total as everywhere else, just not split evenly. */
@media (max-width: 700px) {
  .fw__stage--land { display: none; }
  .fw__stage--port { display: flex; }
  .fw__inner {
    padding-top: 96px;
    padding-bottom: 64px;
  }
}

/* no pin without motion: the diagram just rests in its final state */
.fw--static { height: auto; }
.fw--static .fw__sticky {
  position: static;
  height: auto;
  overflow: visible;
}
.fw--static .fw__inner {
  height: auto;
  padding-top: var(--space-xxxl);
  padding-bottom: var(--space-xxxl);
}

/* ============================================================
   Mission — the close of the philosophy arc
   ============================================================ */

/* the closing block carries on in the same column as the pinned copy,
   rather than the wider --narrow container — gutter included, so the
   two match edge to edge at every width */
.mission-band .container {
  max-width: calc(var(--measure) + var(--measure-gutter) * 2);
  padding-left: var(--measure-gutter);
  padding-right: var(--measure-gutter);
}
/* the diagram carries its own air above this block — the section's
   usual top padding would only add more dead space to scroll through */
.mission-band { padding-top: var(--space-xl); }

/* the two closing lines speak in the same voice, at the same size —
   the display face at --fs-heading */
.phil__saying,
.mission__statement {
  color: var(--text-primary);
  font-family: var(--font-display);
  font-size: var(--fs-heading);
  line-height: var(--lh-normal);
}
.phil__saying { margin-top: var(--space-xxl); }
/* the mission reads as one statement, spread to the column like the
   body copy above it */
.mission__statement { text-align: justify; }

.mission {
  margin-top: calc(var(--space-xxxl) * 1.5);
  padding-top: var(--space-xxl);
  border-top: 1px solid var(--border-default);
}

/* ============================================================
   Phone frame with live video screen (scrub sections)
   ============================================================ */

.phone {
  position: relative;
  width: var(--mock-w);
  aspect-ratio: 1286 / 2516;
  flex: none;
  /* side mockups sit flush with the container edge, in line with the
     header's logo (left) and CTA (right) */
  justify-self: start;
}
.scrub--flip .scrub__grid > .phone { justify-self: end; }
.phone__shell {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  pointer-events: none;
}
/* sits OVER the shell, covering its static print — same stacking as the
   source body-screen-video.html; the #1c1c1c bg blends into the screen.
   brightness(1.08) lifts the frames' rgb(26) video-encode background to
   the shell screen's rgb(28) so the seam disappears */
.phone__video {
  position: absolute;
  z-index: 2;
  filter: brightness(1.08);
  /* #1c1c1c matches the pixel value of the screen inside the shell
     render — a deliberate exception to the tokens-only rule.
     The poster shows until the frame sequence has loaded. */
  background-color: #1c1c1c;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}
.phone--body .phone__video {
  left: 28.23%; top: 40.58%; width: 43.47%; height: 39.55%;
  background-image: url("../assets/video/body-poster.webp");
}
.phone--mind .phone__video {
  left: 26.28%; top: 47.04%; width: 47.43%; height: 25.16%;
  background-image: url("../assets/video/mind-poster.webp");
}

/* ---------- scroll-scrubbed pinned sections ---------- */

/* two steps per block, not three, and each is one line — so the pin
   needs far less scroll than it used to. */
.scrub { height: 200vh; position: relative; }

/* The pinned box is a full viewport tall, but the mockup it holds is
   only --mock-h — centered, so there's dead air above and below it. At
   the seam the slack under Body meets the slack over Mind and reads as a
   hole between the two blocks. Pull Mind up by that slack, keeping one
   block-gap of deliberate breath. Never positive: a viewport shorter
   than the mockup has no slack to reclaim. Section height is untouched,
   so each block's own scrub progress is unaffected. */
.scrub + .scrub {
  margin-top: min(0px, calc(var(--mock-h) + var(--space-xxxl) - 100vh));
  /* the pull makes this block overlap the tail of the one before it, and
     it paints later — an opaque background would slice the outgoing
     mockup off at this block's top edge. The page behind is already the
     same black (see the elevation ladder), so paint nothing. */
  background: transparent;
}
/* nothing is pinned in the static fallback — the blocks just follow one
   another, and pulling them together would overlap them */
.scrub--static + .scrub,
.scrub + .scrub--static { margin-top: 0; }
.scrub__sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  display: flex;
  /* held at a flat drop rather than centered, so the eyebrow lands at
     the same height whatever the viewport — see padding-top */
  align-items: flex-start;
  overflow: hidden;
  /* The run of black above this band has to read the same as the one
     above "How it works?": there it's #mission's 144px tail plus
     #meet's 96px opening, 240px in all. #guidance leaves only its own
     96px behind this band, so the band itself opens on the other 144px.
     Every .scrub gets the same figure, so Body and Mind start level.
     The min() only bites on viewports too short to hold the mockup
     underneath, where it gives space back instead of clipping the
     phone; the max() keeps the content clear of the pill when it
     does. */
  padding-top: min(
    calc(var(--block-gap) + var(--space-xxxl)),
    max(var(--header-h), calc(100vh - var(--mock-h) - var(--space-lg)))
  );
}
/* the band runs in the philosophy column, not the page container: same
   width, same gutters, so it lines up with the copy above it. The phone
   column is the mockup's own fixed width — nothing to negotiate. */
.scrub__grid {
  display: grid;
  grid-template-columns: var(--mock-w) 1fr;
  gap: var(--space-xxl);
  /* the copy column is shorter than the mockup — start it at the
     mockup's top edge rather than floating it in the middle */
  align-items: start;
  width: 100%;
  max-width: calc(var(--measure) + var(--measure-gutter) * 2);
  padding-left: var(--measure-gutter);
  padding-right: var(--measure-gutter);
}
/* flipped variant: steps left, phone right — the narrow column swaps
   sides too, so the phone stays aligned with the container edge */
.scrub--flip .scrub__grid { grid-template-columns: 1fr var(--mock-w); }
.scrub--flip .scrub__grid > .phone { order: 2; }

/* the eyebrow stays fixed above the stack. The steps don't take turns:
   each one holds its place in the flow from the start (invisible), so
   the column never reflows — scroll only fades them in, one settling
   under the last. Hence the stack is top-aligned, not centered. */
.scrub__steps { display: flex; flex-direction: column; }
.scrub__stack {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-md);
}
.scrub-step {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.45s ease, transform 0.45s cubic-bezier(0.16, 1, 0.3, 1);
}
.scrub-step.is-active { opacity: 1; transform: none; }

/* each step is one numbered line on a quiet card — no hover, nothing to
   click, it's a list that builds itself as you scroll */
.scrub-card {
  display: flex;
  align-items: baseline;
  gap: var(--space-lg);
  padding: var(--space-lg);
  background: var(--bg-secondary);
  border-radius: var(--radius-lg);
}
.scrub-card__num {
  flex: none;
  min-width: 1.2em;
  font-family: var(--font-display);
  font-size: var(--fs-heading);
  line-height: var(--lh-tight);
  color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}
/* a list item, not a section heading — one size down from the h2 default */
.scrub-card h2 {
  font-size: var(--fs-xl);
  line-height: var(--lh-tight);
}
/* the number aligns to the title's baseline, so title and note travel
   together in their own column beside it */
.scrub-card__body { min-width: 0; }
.scrub-card p {
  margin-top: var(--space-md);
  color: var(--text-secondary);
  font-size: var(--fs-md);
  line-height: var(--lh-normal);
  /* the page's reading copy spreads to both edges of whatever column it
     runs in — here that's the card, not the measure */
  text-align: justify;
}

@media (max-width: 880px) {
  /* breathing room below the fixed menu — the mockup keeps its size.
     Anchor content to the top so the eyebrow and card always stay in
     view; the mockup takes whatever the viewport has left below */
  .scrub__sticky { padding-top: calc(var(--header-h) + var(--space-lg)); align-items: flex-start; }
  .scrub__grid,
  .scrub--flip .scrub__grid {
    grid-template-columns: 1fr;
    gap: var(--space-sm);
    justify-items: center;
    text-align: center;
    align-content: start;
  }
  /* title and body text first, mockup below */
  .scrub__grid > .phone,
  .scrub--flip .scrub__grid > .phone { order: 2; justify-self: center; }
  .scrub__steps { width: 100%; order: 1; }
  /* card copy reads from the left on mobile; the centered grid would
     otherwise center every line */
  .scrub-card { text-align: left; }
  /* the note is ragged-right down here: justified lines on a column this
     narrow tear open on the long words */
  .scrub-card p { text-align: left; }
  /* every title holds one line. The longest of the four measures 15.5×
     its own font-size in Lora, i.e. it fits whenever the face is at most
     6.44% of the column beside the number — so the column is made a
     query container and the title sized off it, at 6.2cqw for slack.
     Measuring the column rather than the viewport keeps it honest under
     a desktop scrollbar, and the flex-grow is what gives the contained
     body a width at all (containment zeroes its intrinsic one). */
  .scrub-card__body { container-type: inline-size; flex: 1; }
  .scrub-card h2 { font-size: min(var(--fs-xl), 6.2cqw); }
}

/* same deal as .container: below this the gutter gives way, never the
   mockup. Lives here, after the measure gutters above, so it wins. */
@media (max-width: 344px) {
  .scrub__grid { padding-left: 16px; padding-right: 16px; }
}

/* static fallback (reduced motion, video failure, or small screens) */
.scrub--static { height: auto; }
.scrub--static .scrub__sticky { position: static; height: auto; padding: var(--space-xxxl) 0; }
.scrub--static .scrub-step {
  opacity: 1;
  transform: none;
}

/* mobile: the pinned choreography gives way to the same four cards in
   one plain stack (markup lives at the end of #body); the Mind section
   disappears entirely — its two cards ride in the stack */
.areas-carousel { display: none; }
@media (max-width: 880px) {
  #body .scrub__sticky,
  #mind { display: none; }
  .areas-carousel { display: block; padding: var(--space-xxl) 0 var(--space-lg); text-align: left; }
  .areas-carousel__track {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
    padding: 0 20px;
  }
}
/* narrowest phones: the gutter gives way here too, the 16px the rest of
   the page falls back to */
@media (max-width: 344px) {
  .areas-carousel__track { padding-left: 16px; padding-right: 16px; }
}

/* the mobile layout carries "Why it matters?" on the cards alone — the
   Body and Mind screens don't follow it down the page */
@media (max-width: 880px) {
  .scrub--static .phone { display: none; }
}

/* ---------- scroll reveal (class added by JS) ---------- */

.reveal {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity 0.7s ease, transform 0.7s cubic-bezier(0.16, 1, 0.3, 1);
  transition-delay: var(--reveal-delay, 0s);
  will-change: opacity, transform;
}
.reveal--in { opacity: 1; transform: none; }

/* ============================================================
   Metrics — drifting filmstrip of example screens
   ============================================================ */

/* it reads as a continuation of the Mentor blocks above, so it sits
   right under them rather than opening its own section of space. Both
   edges are flush: --block-gap on the next block owns the spacing. */
#metrics { padding-top: 0; padding-bottom: 0; }
/* the three Focus Zone screens under the strip, side by side. They carry
   .mockup for the phone frame and the shell dim; the row and the one
   width that isn't --mock-w live here.

   The group is meant to measure the same as every other block on the
   page, which is what --mock-w-focus is solved for. */
.focus-mocks {
  display: flex;
  justify-content: center;
  /* tight: the three read as one exhibit of the same Focus Zone, not as
     three separate figures the eye has to travel between */
  gap: var(--space-md);
  margin-top: var(--space-xxxl);
}
/* .mockup centres itself with auto side margins, which as a flex item
   would eat the free space and push the three back apart — the gap is
   the only thing allowed to separate them here */
.focus-mocks .mockup {
  width: var(--mock-w-focus);
  margin-left: 0;
  margin-right: 0;
}
/* full-width mockups never fit a phone side by side, so they stack the
   way every other pair on the page does — flush left, on the same edge
   the copy above them runs from rather than floating mid-column */
@media (max-width: 880px) {
  .focus-mocks { flex-direction: column; align-items: flex-start; }
}

/* the heading sits on the reading measure, but the strip runs the full
   width of the viewport — it should read as passing through the page */
.filmstrip {
  overflow: hidden;
  margin-top: var(--space-xxl);
  /* just enough of a fade to soften the cut at each edge — over this
     narrower strip a wider one swallows the outer cards */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 2% 98%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 2% 98%, transparent);
}
.filmstrip__track {
  display: flex;
  gap: var(--space-lg);
  width: max-content;
  animation: strip-drift 48s linear infinite;
}
/* metric cards riding the strip: icon, the number, what it measures,
   and where it lives — real values from the app's metric tables */
.metric-card {
  flex: none;
  /* one uniform width, sized so the longest one-line label fits */
  width: 224px;
  display: flex;
  flex-direction: column;
  padding: var(--space-lg);
  background: var(--bg-secondary);
  border-radius: var(--radius-lg);
}
/* icon sits in its own quiet tile, half a step above the card */
.metric-card svg {
  color: var(--text-tertiary);
  width: 38px;
  height: 38px;
  padding: 9px;
  background: var(--bg-overlay);
  border-radius: var(--radius-md);
  margin-bottom: var(--space-xl);
}
.metric-card b {
  font-family: var(--font-display);
  font-size: var(--fs-xxl);
  line-height: var(--lh-tight);
  margin-bottom: var(--space-xs);
}
.metric-card span {
  color: var(--text-secondary);
  font-size: var(--fs-md);
  line-height: var(--lh-normal);
  white-space: nowrap;
}
.metric-card i {
  margin-top: auto;
  padding-top: var(--space-lg);
  color: var(--text-tertiary);
  font-size: var(--fs-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
@keyframes strip-drift {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

/* ============================================================
   Daily guidance — the arc of a day: a vertical rail with two
   check-in moments and a closing node
   ============================================================ */

/* carries on from the focus visuals above rather than opening its own
   section of space; the pool of light behind each notification spills
   past the block's edge, so clip it and it can't widen the page */
#guidance { padding-top: var(--block-gap); overflow: hidden; }

/* the rail runs down the right edge of the notification column, so it
   sits between the shots and the copy rather than splitting the block */
.day-line {
  --day-gap: var(--space-xxxl);
  --day-rail-x: calc(var(--mock-w-focus) + var(--day-gap) / 2);
  position: relative;
  margin-top: calc(var(--space-xxxl) + var(--space-lg));
  padding-bottom: var(--space-lg);
}
.day-line__rail {
  position: absolute;
  left: var(--day-rail-x);
  top: -12px;
  bottom: 0;
  width: 1px;
  transform: translateX(-50%);
  background: linear-gradient(
    to bottom,
    transparent,
    var(--bg-surface) 12%,
    var(--bg-surface) 88%,
    transparent
  );
}

.day-moment {
  position: relative;
  display: grid;
  grid-template-columns: var(--mock-w-focus) 1fr;
  column-gap: var(--day-gap);
  align-items: center;
  margin-bottom: calc(var(--space-xxxl) + var(--space-xl));
}
/* the travelling node: one dot on the rail, driven down it by scroll.
   JS sets --day-dot-y; without it the dot rests on the first moment. */
.day-line__dot {
  position: absolute;
  left: var(--day-rail-x);
  top: var(--day-dot-y, 0px);
  width: 9px;
  height: 9px;
  margin: -4.5px 0 0 -4.5px;
  border-radius: var(--radius-full);
  background: var(--accent);
  will-change: top;
}

/* both moments read the same way: notification, then rail, then copy */
.day-moment__meta { text-align: left; }

.day-time {
  display: block;
  color: var(--accent);
  font-size: var(--fs-sm);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  margin-bottom: var(--space-md);
}
.day-moment h3 { font-size: var(--fs-xl); margin-bottom: var(--space-md); }
.day-moment p {
  color: var(--text-secondary);
  font-size: var(--fs-md);
  line-height: var(--lh-loose);
  text-align: justify;
}

/* the banner floats in a soft pool of light, hugging the rail */
.day-moment__shot {
  position: relative;
  isolation: isolate;
  /* matches a single Focus Zone screen above, so the notification column
     and that row read as the same handset down the page */
  width: var(--mock-w-focus);
  justify-self: start;
}
.day-moment:last-child { margin-bottom: 0; }
/* a plain phone, cropped and fading out below — the notification
   lands on its screen */
.day-shot__crop {
  overflow: hidden;
  aspect-ratio: 1286 / 1250;
  -webkit-mask-image: linear-gradient(to bottom, #000 45%, transparent 96%);
          mask-image: linear-gradient(to bottom, #000 45%, transparent 96%);
}
.day-shot__phone { width: 100%; display: block; }
/* the banner and the app icon that sits in its gutter travel together */
.day-shot__notif {
  position: absolute;
  top: 9%;
  left: 50%;
  width: 84%;
  transform: translateX(-50%);
  transition: transform 0.2s ease;
}
.day-moment__shot:hover .day-shot__notif { transform: translate(-50%, -3px); }
.day-shot__banner { width: 100%; display: block; }
/* the banners were redrawn with the icon slot left empty; these figures
   put it back where iOS had it — centred in the bubble's left gutter,
   sized and inset off the banner's own width so it scales with it */
.day-shot__icon {
  position: absolute;
  left: 6.8%;
  top: 50%;
  width: 9.9%;
  height: auto;
  transform: translateY(-50%);
  border-radius: 22.5%;
}

.pill-row {
  display: flex;
  gap: var(--space-md);
  margin-top: var(--space-lg);
}

@media (max-width: 720px) {
  /* no room for two columns beside a fixed-width notification: the rail
     moves to the left edge and each moment stacks, shot above copy */
  .day-line__rail { left: 4px; transform: none; }
  .day-moment {
    grid-template-columns: 1fr;
    row-gap: var(--space-lg);
    padding-left: var(--space-xxl);
    margin-bottom: var(--space-xxxl);
  }
  .day-line__dot { left: 4px; }
}
.pill {
  padding: var(--space-sm) var(--space-lg);
  background: var(--bg-surface);
  border-radius: var(--radius-full);
  color: var(--text-secondary);
  font-size: var(--fs-md);
}

/* ============================================================
   Countdown
   ============================================================ */

.launch { text-align: center; }

/* subtle card around the countdown — one value step above the deep band,
   the edge is the value change, no border or shadow */
.launch-card {
  background: var(--bg-secondary);
  border-radius: var(--radius-xl);
  padding: var(--space-xxl) var(--space-xl);
  max-width: 560px;
  margin: 0 auto;
}
.launch-label {
  color: var(--text-secondary);
  font-size: var(--fs-xl);
}

.countdown {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: var(--space-md);
  margin: var(--space-xl) 0 var(--space-lg);
}
.cd-group { display: flex; flex-direction: column; align-items: center; gap: var(--space-md); }
.cd-digits { display: flex; gap: 2px; }
.cd-digit {
  overflow: hidden;
  height: 1em;
  line-height: 1;
  font-size: clamp(28px, 4vw, 40px);
  color: var(--text-primary);
}
/* the days group carries the section's single accent */
.cd-group--days .cd-digit { color: var(--accent); }
.cd-digit__reel {
  display: flex;
  flex-direction: column;
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}
.cd-label {
  color: var(--text-tertiary);
  font-size: var(--fs-sm);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.cd-sep {
  font-size: clamp(20px, 3vw, 30px);
  color: var(--text-disabled);
  line-height: 1;
  transform: translateY(-0.35em);
}
.launch-note { color: var(--text-tertiary); font-size: var(--fs-md); }
.launch-closer { margin-top: var(--space-xl); color: var(--text-tertiary); font-size: var(--fs-md); }

@media (max-width: 400px) {
  .countdown { gap: var(--space-xs); }
  .cd-digit { font-size: 30px; }
  .cd-sep { font-size: 24px; }
}

/* ============================================================
   Why us — the team
   ============================================================ */

/* a card each, side by side under the copy, across the reading measure */
.team-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-lg);
}
/* same fill and radius as every other card on the page — the portrait
   sits in it beside the name */
.team-card {
  display: flex;
  align-items: center;
  gap: var(--space-lg);
  min-width: 0;
  background: var(--bg-secondary);
  border-radius: var(--radius-lg);
  padding: var(--space-lg);
}

/* the sources are colour studio shots; they sit grey and dimmed into
   the card at rest and come up in their own colour on hover — the one
   place on the page where colour arrives on contact */
.team-card__photo {
  flex: none;
  width: 112px;
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border-radius: var(--radius-md);
  filter: grayscale(1) brightness(0.72);
  transition:
    filter 0.5s ease,
    transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}
.team-card:hover .team-card__photo,
.team-card:focus-within .team-card__photo {
  filter: grayscale(0) brightness(1);
  transform: translateY(-4px);
}

.team-card__meta { min-width: 0; }
.team-card__meta h3 { font-size: var(--fs-heading); margin-bottom: var(--space-xs); }
.team-card__meta span {
  display: block;
  color: var(--text-tertiary);
  font-size: var(--fs-sm);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* the footer's social button, one step down in size — it sits inside a
   card rather than under the whole page */
.team-card__link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  margin-top: var(--space-lg);
  border-radius: var(--radius-full);
  background: var(--bg-surface);
  color: var(--text-secondary);
  transition: background-color 0.15s ease, color 0.15s ease, transform 0.15s ease;
}
/* the footer's social button again: the disc fills, the mark stays
   white */
.team-card__link:hover {
  background: var(--accent);
  color: var(--text-primary);
  transform: translateY(-2px);
}

/* side by side, a phone leaves no room for the name beside the
   portrait — the two cards stack instead */
@media (max-width: 620px) {
  .team-grid { grid-template-columns: 1fr; }
}

/* nothing to hover on a touch screen — the portraits would stay grey
   forever, so they simply arrive in colour there */
@media (hover: none) {
  .team-card__photo { filter: grayscale(0) brightness(0.85); }
}

@media (prefers-reduced-motion: reduce) {
  .team-card:hover .team-card__photo,
  .team-card:focus-within .team-card__photo { transform: none; }
}

/* ============================================================
   Pricing — three cards across the reading measure. One fill, one
   radius, and no card marked above the others: the three are the
   same object three times, and they stay that way under the pointer
   too. The only thing that moves in this block is the menu's own CTA
   at the foot of each card.
   ============================================================ */

/* the row runs on the grid below it and the switch takes the last
   column, so the control is exactly one card wide and lines up with the
   Deep card's edges however the measure resolves */
.price-switch-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-lg);
  margin-bottom: var(--space-lg);
}
.price-switch { grid-column: 3; }

/* a segmented pill: the thumb slides between two fixed-width halves, so
   nothing reflows as the labels change state */
.price-switch {
  position: relative;
  display: inline-flex;
  padding: 4px;
  border-radius: var(--radius-full);
  background: var(--bg-secondary);
}
.price-switch__thumb {
  position: absolute;
  top: 4px;
  bottom: 4px;
  left: 4px;
  width: calc(50% - 4px);
  border-radius: var(--radius-full);
  background: var(--bg-surface);
  transition: transform 0.35s var(--ease-out-expo);
}
/* exactly its own width, which is exactly one option */
.price-switch.is-yearly .price-switch__thumb { transform: translateX(100%); }

/* the nav's labels: mono, so the two halves can't shift width. Each
   takes half the card between them */
.price-switch__opt {
  position: relative;
  z-index: 1;
  flex: 1 1 0;
  min-width: 0;
  padding: var(--space-md) var(--space-lg);
  border: none;
  background: none;
  -webkit-appearance: none;
  appearance: none;
  color: var(--text-tertiary);
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
  transition: color 0.25s ease;
}
.price-switch__opt[aria-pressed="true"] { color: var(--text-primary); }

.price-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-lg);
  align-items: stretch;
}

.price-card {
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--bg-secondary);
  border-radius: var(--radius-lg);
  padding: var(--space-lg);
}

/* The plan name is the first thing in the card now. A tag row sat above
   it and a one-line description below; both are gone, but the card keeps
   their space — the air around the name is what gives the price room to
   land, so the two are held here as margins rather than lost. */
.price-card h3 {
  font-size: var(--fs-heading);
  margin-top: calc(22px + var(--space-md));                    /* the tag row */
  margin-bottom: calc(var(--space-xs) + 17px + var(--space-lg)); /* the description line */
}

/* the price, set exactly as the plan name above it — same face, same
   size, same line height, so the two read as one heading in two lines
   rather than a title with a number shouting under it. Baseline aligned
   with its period, so amount and suffix stay one phrase. */
.price-card__price {
  /* the face sits on the whole block, not just the number — the period
     is part of the price, so it can't drop into the body font */
  font-family: var(--font-display);
  margin-bottom: var(--space-lg);
  padding-bottom: var(--space-lg);
  border-bottom: 1px solid var(--border-default);
}
.price-card__figure {
  display: flex;
  align-items: baseline;
  gap: var(--space-xs);
  flex-wrap: wrap;
}
/* the full year, struck, next to what you actually pay — the saving
   shown rather than asserted. Empty on a monthly card, and an empty one
   is taken out of the row so it can't open a gap before the number. */
.price-card__was {
  color: var(--text-disabled);
  font-size: var(--fs-sm);
  text-decoration: line-through;
}
.price-card__was:empty { display: none; }
.price-card__amt {
  font-size: var(--fs-heading);
  line-height: var(--lh-tight);
}
.price-card__per {
  color: var(--text-tertiary);
  font-size: var(--fs-sm);
}

.price-feat {
  list-style: none;
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  line-height: var(--lh-normal);
  /* the air above the button — the list can only ever be pushed further
     from it by the auto margin below, never closer */
  margin-bottom: var(--space-xl);
}
.price-feat li {
  position: relative;
  padding-left: var(--space-xl);
  margin-bottom: var(--space-md);
}
.price-feat li:last-child { margin-bottom: 0; }
/* a tick rather than the chips' dot: these lines are things you get,
   not things you'd read down a list */
.price-feat li::before {
  content: "\2713";
  position: absolute;
  left: var(--space-xs);
  top: 0;
  color: var(--text-disabled);
  font-size: var(--fs-sm);
  line-height: var(--lh-normal);
}

/* the header's CTA, at the foot of a card: full width, pushed down so
   the three line up across the row however long the lists run, and
   sitting on its own air above and below rather than on the card's
   padding alone */
.price-card__cta {
  width: 100%;
  margin-top: auto;
  margin-bottom: var(--space-md);
}
/* The menu's button, outlined rather than filled: white line and white
   label on the card at rest, and both crossing to the accent under the
   pointer — the box never fills, so the colour arrives as a line rather
   than as a slab. Same pseudo-element and same 1s easing as .nav__cta;
   only the colours at each end differ. */
.price-card__cta::before {
  background: transparent;
  border-color: var(--text-primary);
}
.price-card__cta span { color: var(--text-primary); }
/* the fill stays transparent — .nav__cta:hover::before already holds it
   there, and nothing here puts it back */
.price-card__cta:hover::before { border-color: var(--accent); }
.price-card__cta:hover span { color: var(--accent); }

/* three cards can't hold their measure much under the reading column —
   below that they stack, still in the same order */
@media (max-width: 760px) {
  .price-grid { grid-template-columns: 1fr; }
  .price-card { padding: var(--space-xl); }
  /* one column: the switch is a card's width here too, which is now the
     full column */
  .price-switch-row { grid-template-columns: 1fr; }
  .price-switch { grid-column: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .price-switch__thumb { transition: none; }
}

/* ============================================================
   Footer
   ============================================================ */

.site-footer {
  background: var(--bg-primary);
  /* the header's own gutter, so the pill below lines up with the menu
     above it at every width */
  padding: 44px 16px 40px;
  color: var(--text-tertiary);
  font-size: 13.5px;
  line-height: 1.7;
}

/* The menu pill, restated at the foot of the page: the same width and
   the same glass, off the same tokens as .nav — and roughly three times
   the height, because it carries the whole footer rather than one row
   of labels. Nothing here may override --glass-*: the slab has to read
   identically at both ends of the page, hover included. */
.foot-pill {
  display: flex;
  max-width: min(100%, var(--nav-max));
  min-height: 186px; /* 3x the pill's own 62px */
  margin: 0 auto;
  /* tighter top and bottom than the sides: the three columns have to
     land near that 186px, and the copy column has no slack to give */
  padding: var(--space-lg) var(--space-xl);
  border: 1px solid var(--glass-line);
  border-radius: var(--radius-lg);
  background: var(--glass-fill);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-lift);
}

.foot-flex {
  display: flex;
  flex: 1;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-xl);
  flex-wrap: wrap;
  min-width: 0;
}

.foot-text { max-width: 340px; }
/* the menu's mark, at the menu's size — .nav__logo restated, down to
   the hover */
.foot-logo {
  height: 40px;
  width: auto;
  margin-bottom: var(--space-md);
  transform-origin: left center;
  transition: transform 0.5s var(--ease-out-expo);
}
.foot-logo:hover { transform: scale(1.12); }
.foot-desc { color: var(--text-secondary); margin-bottom: var(--space-md); }
.foot-text p { margin-bottom: 2px; }
.foot-legal a { color: var(--text-disabled); text-decoration: underline; }
.foot-legal a:hover { color: var(--text-secondary); }
.foot-text a { color: var(--text-secondary); text-decoration: underline; }
.foot-text a:hover { color: var(--text-primary); }
.foot-copy { margin-top: var(--space-sm); color: var(--text-disabled); }

/* the labels run on the menu's mono face: they carry the same
   [data-scramble] hover, and fixed advance widths are what stop the
   letters twitching as they cycle */
.foot-nav {
  display: flex;
  align-items: flex-start;
  flex-direction: column;
  gap: 4px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.02em;
  line-height: 1.7;
}
/* .nav__item, restated — same rest colour, same target, same easing,
   and nothing else moving: the scramble is the whole effect */
.foot-nav a {
  display: inline-flex;
  color: rgba(255, 255, 255, 0.86);
  text-decoration: none;
  white-space: nowrap;
  transition: color 1s var(--ease-out-expo);
}
.foot-nav a:hover {
  color: var(--text-primary);
  text-decoration: none;
}
.fn-head {
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.fn-head--gap { margin-top: var(--space-md); }

.foot-social { display: flex; gap: var(--space-md); }
.foot-social a {
  width: 34px;
  height: 34px;
  border-radius: var(--radius-full);
  background: rgba(255, 255, 255, 0.08);
  color: var(--text-primary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition:
    background-color 0.5s var(--ease-out-expo),
    color 0.5s var(--ease-out-expo),
    transform 0.5s var(--ease-out-expo);
}
/* only the disc changes — the mark stays white right through, so the
   icon reads the same before and after the fill arrives */
.foot-social a:hover {
  background: var(--accent);
  transform: translateY(-3px);
}

/* ============================================================
   Legal page (privacy policy) — standalone, no header/footer
   ============================================================ */

.legal { padding: var(--space-xxxl) 0; }
.legal h1 { margin-bottom: var(--space-lg); }
.legal h2 {
  font-size: var(--fs-xl);
  margin: var(--space-xxl) 0 var(--space-md);
}
.legal h3 {
  font-size: var(--fs-heading);
  margin: var(--space-xl) 0 var(--space-md);
}
.legal p, .legal li {
  color: var(--text-secondary);
  font-size: var(--fs-lg);
  line-height: var(--lh-loose);
  margin-bottom: var(--space-md);
  /* justified body — lines spread to the full column width */
  text-align: justify;
}
.legal ul { padding-left: var(--space-xl); margin-bottom: var(--space-lg); }
/* emphasis without italics — brighter text carries the weight */
.legal em { color: var(--text-primary); }
.legal-meta { color: var(--text-tertiary); font-size: var(--fs-md); margin-bottom: var(--space-xxl); }
.legal-links {
  display: flex;
  gap: var(--space-lg);
  margin-bottom: var(--space-xxl);
}
.legal-links a {
  display: inline-flex;
  align-items: center;
  gap: var(--space-md);
  color: var(--text-secondary);
  font-size: var(--fs-md);
}
.legal-links a:hover { color: var(--text-primary); }

/* ============================================================
   Reduced motion: switch it all off
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; }

  /* philosophy + framework: the static layouts (.phil--static /
     .fw--static, added by main.js) carry these — here just make sure
     nothing is left mid-reveal */
  .type__ghost {
    opacity: 1;
    -webkit-user-select: text;
            user-select: text;
  }
  .type__live, .type__caret { display: none; }
  .fw-wave { animation: none; }

  .filmstrip__track { animation: none; transform: none; }

  /* card hover keeps its color shift but drops every movement */
  .area-chip, .area-chip::before, .area-chip li { transition: none; }
  .area-chip:hover { transform: none; }
  .area-chip:hover li { transform: none; }
}
