/* ============================================================
   Biojrnl — site v2.1 "Lamplight editorial"
   ------------------------------------------------------------
   The notebook aesthetic, lit. Layered ambient light behind
   every page, gradient-filled actions with soft halos, surfaces
   on a real elevation scale, and deep gradient bands for rhythm.

   Three moods, same bones. Palette values transcribed from the
   app's lib/core/theme/tokens.dart; do not invent new ones.
   Fonts self-hosted; the site ships under `script-src 'self'`.

   Owner notes honoured in this revision (2026-08-15):
   - display type scale reduced ("titles too big")
   - flatness replaced with atmosphere and depth
   - waiting-list form removed from the pages (its .waitlist rules stay below, unused)
   ============================================================ */

/* ── Fonts ─────────────────────────────────────────────────── */
@font-face {
  font-family: 'Fraunces';
  src: url('/fonts/Fraunces.woff2') format('woff2');
  font-weight: 100 900; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Fraunces';
  src: url('/fonts/Fraunces-Italic.woff2') format('woff2');
  font-weight: 100 900; font-style: italic; font-display: swap;
}
@font-face {
  font-family: 'Instrument Sans';
  src: url('/fonts/InstrumentSans.woff2') format('woff2');
  font-weight: 400 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Instrument Sans';
  src: url('/fonts/InstrumentSans-Italic.woff2') format('woff2');
  font-weight: 400 700; font-style: italic; font-display: swap;
}

/* ── Moods ─────────────────────────────────────────────────── */
:root,
html[data-theme='tide'] {
  --bg: #EEF2F4;
  --surface: #FFFFFF;
  --surface-soft: #E4EAEE;
  --ink: #0F1B22;
  --ink2: #4A6373;
  --ink3: #566F7E;
  --accent: #3D6E8E;
  --accent-deep: #2C5470;
  --accent-2: #D7E2EA;
  --on-accent: #FFFFFF;
  --halo: rgba(61, 110, 142, .28);
  --btn-a: #47799C; /* was #4E82A6 — nudged to ~4.5:1 under white labels */
  --btn-b: #2C5470;
  /* ambient light field behind the whole page */
  --ambient:
    radial-gradient(900px 620px at 86% -6%, rgba(61, 110, 142, .13), transparent 62%),
    radial-gradient(820px 700px at -12% 32%, rgba(185, 207, 221, .40), transparent 62%),
    radial-gradient(900px 680px at 72% 108%, rgba(215, 226, 234, .55), transparent 60%);
  /* the deep band: the page's low note */
  --band-a: #0F2430;
  --band-b: #17323F;
  --band: #0F2430;
  --band-glow: rgba(143, 182, 206, .20);
  --band-ink: #E7EEF3;
  --band-ink2: #A8C0CF;
  --band-accent: #8FB6CE;
  --band-line: rgba(231, 238, 243, .14);
  --scheme: light;
  --shadow-card: 0 1px 2px rgba(15, 27, 34, .05), 0 12px 32px rgba(15, 27, 34, .07);
  --shadow-lift: 0 2px 4px rgba(15, 27, 34, .06), 0 20px 48px rgba(15, 27, 34, .11);
  --shadow-phone: 0 4px 14px rgba(15, 27, 34, .12), 0 46px 100px rgba(15, 27, 34, .22);
}
html[data-theme='blush'] {
  --bg: #F1D9DD;
  --surface: #FCF1F1;
  --surface-soft: #F7E3E6;
  --ink: #3A2430;
  --ink2: #73505F;
  --ink3: #7A5469;
  --accent: #CF6A86;
  --accent-deep: #883F5A;
  --accent-2: #F5D9E0;
  --on-accent: #FFFFFF;
  --halo: rgba(207, 106, 134, .30);
  --btn-a: #B3576F; /* was #DC8AA0 — white label failed contrast (2.57:1) */
  --btn-b: #883F5A;
  --ambient:
    radial-gradient(900px 620px at 86% -6%, rgba(207, 106, 134, .14), transparent 62%),
    radial-gradient(820px 700px at -12% 32%, rgba(252, 241, 241, .55), transparent 62%),
    radial-gradient(900px 680px at 72% 108%, rgba(237, 191, 201, .48), transparent 60%);
  --band-a: #33202B;
  --band-b: #452939;
  --band: #33202B;
  --band-glow: rgba(231, 160, 180, .18);
  --band-ink: #F7E7EB;
  --band-ink2: #D2AFBB;
  --band-accent: #E7A0B4;
  --band-line: rgba(247, 231, 235, .14);
  --scheme: light;
  --shadow-card: 0 1px 2px rgba(58, 36, 48, .05), 0 12px 32px rgba(58, 36, 48, .08);
  --shadow-lift: 0 2px 4px rgba(58, 36, 48, .06), 0 20px 48px rgba(58, 36, 48, .13);
  --shadow-phone: 0 4px 14px rgba(58, 36, 48, .12), 0 46px 100px rgba(58, 36, 48, .24);
}
html[data-theme='dusk'] {
  --bg: #1E1720;
  --surface: #2E242C;
  --surface-soft: #2A2028;
  --ink: #F2E6D7;
  --ink2: #C1AE99;
  --ink3: #BAB0A6;
  --accent: #E8A34F;
  --accent-deep: #B8772B;
  --accent-2: #3A2E37;
  --on-accent: #2A1A08;
  --halo: rgba(232, 163, 79, .24);
  --btn-a: #F0B269;
  --btn-b: #C08034;
  --ambient:
    radial-gradient(900px 640px at 86% -6%, rgba(232, 163, 79, .13), transparent 62%),
    radial-gradient(820px 700px at -10% 32%, rgba(122, 78, 110, .16), transparent 64%),
    radial-gradient(900px 680px at 72% 110%, rgba(58, 46, 55, .55), transparent 60%);
  --band-a: #140D16;
  --band-b: #221426;
  --band: #140D16;
  --band-glow: rgba(232, 163, 79, .15);
  --band-ink: #F2E6D7;
  --band-ink2: #B7A692;
  --band-accent: #E8A34F;
  --band-line: rgba(242, 230, 215, .12);
  --scheme: dark;
  --shadow-card: 0 1px 2px rgba(0, 0, 0, .32), 0 12px 32px rgba(0, 0, 0, .36);
  --shadow-lift: 0 2px 4px rgba(0, 0, 0, .34), 0 20px 48px rgba(0, 0, 0, .46);
  --shadow-phone: 0 4px 14px rgba(0, 0, 0, .38), 0 46px 100px rgba(0, 0, 0, .55);
}

:root {
  --line: color-mix(in srgb, var(--ink) 12%, transparent);
  --line-soft: color-mix(in srgb, var(--ink) 7%, transparent);

  --ease: cubic-bezier(.4, 0, .2, 1);
  --ease-out: cubic-bezier(.05, .7, .1, 1);
  --t-quick: 180ms;
  --t-std: 420ms;
  --t-slow: 700ms;

  --r-sm: 10px;
  --r-md: 14px;
  --r-lg: 20px;
  --r-xl: 28px;

  --gutter: clamp(20px, 5vw, 64px);
  --measure: 1200px;

  /* Severity, as the app grades it. Calm on purpose, never alarming. */
  --sev-mild: #3B7860;
  --sev-moderate: #966324;
  --sev-severe: #B04A3F;
}
html[data-theme='dusk'] {
  --sev-mild: #74BD9C;
  --sev-moderate: #D7AC6A;
  --sev-severe: #DB958C;
}

/* ── Base ──────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
* { -webkit-tap-highlight-color: transparent; }

html {
  color-scheme: var(--scheme);
  scroll-behavior: smooth;
  scroll-padding-top: 92px;
  -webkit-text-size-adjust: 100%;
  /* Must be on <html>, not only on <body>. The hero glow is deliberately wider
     than the viewport; clipping it on <body> alone lets the overflow escape to
     the document element, which then scrolls sideways on every phone. Measured:
     +117px of horizontal scroll at a 390px viewport before this line existed. */
  overflow-x: hidden; /* iOS ≤15 fallback — clip below is dropped there */
  overflow-x: clip;
}
body {
  background: var(--bg);
  color: var(--ink);
  font-family: 'Instrument Sans', system-ui, -apple-system, sans-serif;
  font-size: 16.5px;
  line-height: 1.6;
  overflow-x: hidden; /* iOS ≤15 fallback — clip below is dropped there */
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  transition: background var(--t-slow) var(--ease), color var(--t-slow) var(--ease);
}
img, svg, video { display: block; max-width: 100%; height: auto; }
button, input, select, textarea { font: inherit; color: inherit; }
button { border: 0; background: none; cursor: pointer; }
a { color: inherit; }
ul { list-style: none; }
::selection { background: color-mix(in srgb, var(--accent) 26%, transparent); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}
/* The accent fails 3:1 as a focus ring in Blush (2.59:1 on the page bg) and
   on the dark band / store badges in Tide — per-surface overrides keep the
   ring visible in every mood. */
html[data-theme='blush'] :focus-visible { outline-color: var(--accent-deep); }
.band :focus-visible, .store-badge:focus-visible { outline-color: var(--band-accent); }

.skip-link {
  position: fixed; left: 16px; top: -70px; z-index: 400;
  background: var(--surface); color: var(--ink);
  padding: 11px 20px; border-radius: 999px;
  box-shadow: var(--shadow-card);
  text-decoration: none; font-weight: 600; font-size: 14px;
  transition: top var(--t-quick) var(--ease);
}
.skip-link:focus { top: 14px; }

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

/* Atmosphere: a fixed field of soft light (z0), then the paper grain (z1).
   All content sits at z2+, and the opaque bands cover both. */
body::after {
  content: '';
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background: var(--ambient);
  transition: opacity var(--t-slow) var(--ease);
}
body::before {
  content: '';
  position: fixed; inset: 0; z-index: 1; pointer-events: none;
  opacity: .038;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 220px 220px;
}
html[data-theme='dusk'] body::before { opacity: .05; }

/* ── Type ──────────────────────────────────────────────────── */
.display {
  font-family: 'Fraunces', Georgia, 'Times New Roman', serif;
  font-weight: 390;
  letter-spacing: -.024em;
  line-height: 1.06;
  text-wrap: balance;
}
.display em { font-style: italic; font-weight: 440; color: var(--accent); }
html[data-theme='tide'] .display em,
html[data-theme='blush'] .display em { color: var(--accent-deep); }

/* Scale reduced by owner request 2026-08-15: the old 104px hero "has taken
   half of the page". Headlines now share the page instead of owning it. */
h1.display { font-size: clamp(35px, 4.4vw, 60px); }
h2.display { font-size: clamp(26px, 3vw, 40px); }
h3.display { font-size: clamp(21px, 2vw, 27px); }
.display--doc { font-size: clamp(29px, 3.2vw, 42px); }

.lede {
  font-family: 'Fraunces', Georgia, serif;
  font-style: italic;
  font-weight: 340;
  font-size: clamp(16.5px, 1.3vw, 19px);
  line-height: 1.62;
  color: var(--ink2);
  max-width: 36em;
  text-wrap: pretty;
}
.eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .19em;
  text-transform: uppercase;
  color: var(--ink3);
  display: inline-flex; align-items: center; gap: 10px;
}
.eyebrow::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent); flex: none;
}
p { text-wrap: pretty; }

/* ── Wordmark. The real asset, never live text. ──────────────
   One whole-italic gradient lockup; -light is FOR light grounds,
   -dark for dark. Any CSS text version is wrong by brand rule. */
.wm { display: inline-block; line-height: 0; text-decoration: none; }
.wm img { width: auto; aspect-ratio: 616 / 207; }
.wm .wm-d { display: none; }
html[data-theme='dusk'] .wm .wm-l { display: none; }
html[data-theme='dusk'] .wm .wm-d { display: block; }

/* ── Layout ────────────────────────────────────────────────── */
.wrap {
  width: 100%; max-width: var(--measure); margin-inline: auto;
  padding-inline: max(var(--gutter), env(safe-area-inset-left))
                  max(var(--gutter), env(safe-area-inset-right));
}
.section { padding-block: clamp(58px, 7vw, 104px); position: relative; z-index: 2; }
.section--tight { padding-block: clamp(44px, 5vw, 76px); }

.sec-head { display: grid; gap: 15px; margin-bottom: clamp(28px, 3.4vw, 46px); }
.sec-rule {
  display: flex; align-items: baseline; gap: 16px;
  border-top: 1px solid var(--line);
  padding-top: 13px;
}
.sec-no {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 13px; font-weight: 500; font-variant-numeric: tabular-nums;
  color: var(--ink3); flex: none; letter-spacing: .02em;
}
.sec-label {
  font-size: 11px; font-weight: 700; letter-spacing: .19em;
  text-transform: uppercase; color: var(--ink3);
}
.sec-head .lede { margin-top: 2px; }

/* ── Buttons ───────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  min-height: 46px;
  padding: 0 22px;
  padding-block: 8px;
  border-radius: 999px;
  font-size: 15px; font-weight: 600; letter-spacing: .005em;
  text-decoration: none;
  /* Labels may wrap: a long label at 200% text scaling must break onto a
     second line inside a 320px viewport instead of overflowing it. Single
     lines still centre in the 46px minimum. */
  white-space: normal; max-width: 100%; text-align: center;
  cursor: pointer;
  transition: transform var(--t-quick) var(--ease-out),
              filter var(--t-quick) var(--ease),
              background var(--t-quick) var(--ease),
              border-color var(--t-quick) var(--ease),
              box-shadow var(--t-quick) var(--ease);
}
.btn svg { width: 15px; height: 15px; flex: none; }
.btn:active { transform: scale(.97); }

.btn--primary {
  background: linear-gradient(135deg, var(--btn-a), var(--btn-b));
  color: var(--on-accent);
  box-shadow: 0 1px 2px color-mix(in srgb, var(--ink) 16%, transparent),
              0 8px 26px var(--halo);
}
.btn--primary:hover { filter: brightness(1.07); transform: translateY(-1px); }

.btn--ghost {
  background: color-mix(in srgb, var(--surface) 55%, transparent);
  color: var(--ink);
  border: 1px solid var(--line);
}
.btn--ghost:hover { border-color: var(--ink3); background: var(--surface); }

.btn--sm { min-height: 41px; padding: 0 17px; font-size: 14px; }

/* Text link with the rule that draws itself in */
.tlink {
  display: inline-flex; align-items: center; gap: 8px;
  font-weight: 600; font-size: 15px; color: var(--accent-deep);
  text-decoration: none; position: relative; padding-bottom: 3px;
}
html[data-theme='dusk'] .tlink { color: var(--accent); }
/* Invisible hit-area extension for touch: the link paints 27px tall; a thumb
   gets 47px. Same device as the mood pill and the demo's back button. Keyed on
   the input, not the width, so a mouse in a narrow window keeps the exact
   hover zone and the underline never draws early. */
@media (hover: none) {
  .tlink::before { content: ''; position: absolute; inset: -10px 0; }
}
.tlink::after {
  content: ''; position: absolute; left: 0; right: 100%; bottom: 0;
  height: 1.5px; background: currentColor;
  transition: right var(--t-std) var(--ease);
}
.tlink:hover::after { right: 0; }
.tlink svg { width: 14px; height: 14px; transition: transform var(--t-std) var(--ease-out); }
.tlink:hover svg { transform: translateX(3px); }

/* ── Store badges: the site's real call to action ──────────── */
.store-badges { display: flex; flex-wrap: wrap; gap: 12px; }
.store-badges--center { justify-content: center; }
.store-badge {
  display: inline-flex; align-items: center; gap: 12px;
  min-height: 56px;
  padding: 8px 22px 8px 17px;
  border-radius: 15px;
  background: linear-gradient(170deg, #1B2127, #0E1216);
  color: #FFFFFF;
  border: 1px solid rgba(255, 255, 255, .10);
  text-decoration: none;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .25), 0 10px 28px color-mix(in srgb, var(--ink) 14%, transparent);
  transition: transform var(--t-quick) var(--ease-out), box-shadow var(--t-quick) var(--ease), border-color var(--t-quick) var(--ease),
              scale 90ms var(--ease-out);
}
.store-badge:hover {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--accent) 60%, #FFFFFF 10%);
  box-shadow: 0 2px 4px rgba(0, 0, 0, .25), 0 16px 40px var(--halo);
}
.store-badge svg { width: 26px; height: 26px; fill: currentColor; flex: none; }
.sb-lines { display: grid; text-align: left; line-height: 1.25; }
.sb-pre { font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase; color: rgba(255, 255, 255, .62); }
.sb-name { font-size: 17px; font-weight: 600; letter-spacing: -.01em; }
.cta-note { font-size: 13.5px; color: var(--ink3); }
.band .cta-note { color: var(--band-ink2); }

/* ── Waitlist (pre-launch) — the download band's email capture ── */
.waitlist {
  display: flex; gap: 10px; max-width: 470px; margin: 28px auto 0;
}
.waitlist .hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.waitlist input[type='email'] {
  flex: 1; min-width: 0; min-height: 52px; padding: 0 20px;
  /* 16px, not 15.5: iOS Safari zooms the page into any field smaller than
     16px on focus, and the band jumped when the keyboard opened. */
  border-radius: 999px; font: inherit; font-size: 16px;
  color: var(--band-ink);
  background: color-mix(in srgb, var(--band-ink) 9%, transparent);
  border: 1px solid color-mix(in srgb, var(--band-ink) 26%, transparent);
  transition: border-color var(--t-quick) var(--ease), background var(--t-quick) var(--ease);
}
.waitlist input[type='email']::placeholder { color: var(--band-ink2); }
.waitlist input[type='email']:focus {
  outline: 2px solid var(--band-accent);
  outline-offset: 2px;
  border-color: var(--band-accent);
  background: color-mix(in srgb, var(--band-ink) 14%, transparent);
}
.waitlist .btn { flex: none; }
/* The Turnstile box breathes below the form instead of hugging it, and sits
   centred in both the dark band and the inline light captures. */
.cf-turnstile { margin-top: 16px; margin-bottom: 4px; display: flex; justify-content: center; }

.form-status { min-height: 24px; margin-top: 12px; font-size: 14.5px; color: var(--band-ink2); }
.form-status.ok { color: var(--band-ink); }
.form-status.err { color: var(--band-accent); font-weight: 600; }
.waitlist-fineprint { margin-top: 4px; font-size: 13px; color: var(--band-ink2); }

/* ── Inline waitlist capture on light pages (pricing, features) ── */
.wl-inline { max-width: 560px; margin: 34px auto 0; text-align: center; }
.wl-inline-lede { font-size: 15px; color: var(--ink2); margin-bottom: 14px; }
.wl-inline .waitlist { margin-top: 0; }
.waitlist--card input[type='email'] {
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
}
.waitlist--card input[type='email']::placeholder { color: var(--ink3); }
.waitlist--card input[type='email']:focus {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-color: var(--accent);
  background: var(--surface);
}
.wl-inline .form-status { color: var(--ink2); }
.wl-inline .form-status.ok { color: var(--ink); }
.wl-inline .form-status.err { color: var(--accent-deep); font-weight: 600; }

/* Deep links from the home teasers land the exact plan card below the bar. */
.plan { scroll-margin-top: 96px; }
.plan:target { box-shadow: var(--shadow-lift); border-color: var(--accent); }
.waitlist-fineprint a { color: var(--band-ink); text-underline-offset: 3px; }
@media (max-width: 560px) {
  .waitlist { flex-direction: column; }
  .waitlist .btn { width: 100%; }
}

/* ── Nav ───────────────────────────────────────────────────── */
.nav {
  position: sticky; top: 0; z-index: 200;
  display: flex; align-items: center; gap: 20px;
  /* viewport-fit=cover opts into the notch: the bar must respect the safe
     areas or the wordmark sits under the iOS status bar / sensor housing. */
  padding: max(15px, env(safe-area-inset-top))
           max(var(--gutter), env(safe-area-inset-right))
           15px
           max(var(--gutter), env(safe-area-inset-left));
  /* padding is not in the list on purpose: animating it re-laid the bar out
     for 420ms on the first swipe of every visit. */
  transition: background var(--t-std) var(--ease), box-shadow var(--t-std) var(--ease);
}
/* One height, scrolled or not: shrinking the bar on scroll moved the page,
   the browser pulled the scroll back over the line, and the bar flipped
   (measured 2026-09-26). Scrolled only changes the look. */
.nav.is-scrolled {
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  -webkit-backdrop-filter: blur(20px) saturate(1.5);
  backdrop-filter: blur(20px) saturate(1.5);
  box-shadow: 0 1px 0 var(--line);
}
.nav .wm img { height: 26px; }
/* 26px wordmark, 44px tap target: pad the link, pull the padding back out
   of the layout so the bar's height does not change. */
.nav .wm { padding-block: 9px; margin-block: -9px; }

/* Desktop: a clean pill cluster, the active page as a raised pill. */
.nav-links {
  display: flex; align-items: center; gap: 2px;
  margin-left: auto;
  font-size: 13.5px; font-weight: 600;
  background: color-mix(in srgb, var(--surface) 58%, transparent);
  border: 1px solid var(--line-soft);
  border-radius: 999px;
  padding: 4px;
}
.nav-links a {
  text-decoration: none; color: var(--ink2);
  padding: 7px 14px; border-radius: 999px;
  transition: color var(--t-quick) var(--ease), background var(--t-quick) var(--ease), box-shadow var(--t-quick) var(--ease);
}
.nav-links a:hover { color: var(--ink); background: color-mix(in srgb, var(--surface) 80%, transparent); }
.nav-links a[aria-current='page'] {
  color: var(--on-accent);
  background: linear-gradient(135deg, var(--btn-a), var(--btn-b));
  box-shadow: 0 3px 10px var(--halo);
}

.nav-side { display: flex; align-items: center; gap: 12px; margin-left: auto; }
.nav .nav-links { margin-left: auto; margin-right: auto; }

/* Mood dots (still used by the theme cards on home) */
.moods { display: flex; align-items: center; gap: 9px; }
.mood {
  width: 21px; height: 21px; border-radius: 50%; position: relative;
  transition: transform var(--t-quick) var(--ease-out);
}
.mood::before {
  content: ''; position: absolute; inset: -4.5px; border-radius: 50%;
  border: 1.5px solid var(--ink2); opacity: 0; transform: scale(.8);
  transition: opacity var(--t-quick) var(--ease), transform var(--t-quick) var(--ease-out);
}
.mood[aria-pressed='true']::before { opacity: .6; transform: scale(1); }
.mood:hover { transform: scale(1.14); }
.mood-tide  { background: linear-gradient(150deg, #6E9CB8, #3D6E8E); }
.mood-blush { background: linear-gradient(150deg, #EFA6B8, #CF6A86); }
.mood-dusk  { background: linear-gradient(150deg, #E8A34F, #8A5A20); }

/* The app's switcher: one pill, tap anywhere, the theme rolls to the next.
   The ring slides dot to dot like the cylinder in the app. */
.mood-cycle {
  position: relative;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 7px 12px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--surface) 70%, transparent);
  border: 1px solid var(--line-soft);
  cursor: pointer;
  transition: transform var(--t-quick) var(--ease-out), border-color var(--t-quick) var(--ease);
}
.mood-cycle:hover { border-color: var(--ink3); }
.mood-cycle:active { transform: scale(.94); }
/* Invisible hit-area extension: the pill is ~29px tall beside a 44px
   hamburger — the site's signature control was its most-missed tap. */
.mood-cycle::after { content: ''; position: absolute; inset: -8px; border-radius: 999px; }
.mc-dot { width: 13px; height: 13px; border-radius: 50%; }
.mc-dot--tide  { background: linear-gradient(150deg, #6E9CB8, #3D6E8E); }
.mc-dot--blush { background: linear-gradient(150deg, #EFA6B8, #CF6A86); }
.mc-dot--dusk  { background: linear-gradient(150deg, #E8A34F, #8A5A20); }
.mc-ring2 {
  position: absolute; top: 50%; left: 12px;
  width: 21px; height: 21px;
  margin: -10.5px 0 0 -4px;
  border: 1.6px solid var(--ink2);
  border-radius: 50%;
  transition: transform 340ms var(--ease-out);
}
.mood-cycle[data-active='blush'] .mc-ring2 { transform: translateX(21px); }
.mood-cycle[data-active='dusk'] .mc-ring2 { transform: translateX(42px); }

/* Mobile menu */
.nav-toggle { display: none; width: 44px; height: 44px; align-items: center; justify-content: center; margin-left: auto; }
.nav-toggle span { display: block; width: 20px; height: 1.6px; background: var(--ink); position: relative; transition: background var(--t-quick) var(--ease); }
.nav-toggle span::before, .nav-toggle span::after {
  content: ''; position: absolute; left: 0; width: 20px; height: 1.6px; background: var(--ink);
  transition: transform var(--t-std) var(--ease-out), top var(--t-std) var(--ease-out);
}
.nav-toggle span::before { top: -6px; }
.nav-toggle span::after { top: 6px; }
.nav-toggle[aria-expanded='true'] span { background: transparent; }
.nav-toggle[aria-expanded='true'] span::before { top: 0; transform: rotate(45deg); }
.nav-toggle[aria-expanded='true'] span::after { top: 0; transform: rotate(-45deg); }

@media (max-width: 900px) {
  .nav-toggle { display: flex; margin-left: 0; }
  .nav-dl { display: none; }
  /* Item 1 (owner-approved): on phones the primary action appears in the bar
     the moment you scroll, instead of hiding ten screens up behind the menu. */
  /* No fill mode: the keyframes end at the natural state, and a `both` fill
     would hold transform:none over the button's own hover and press. */
  .nav.is-scrolled .nav-dl { display: inline-flex; animation: dl-in 320ms var(--ease-out); }
  /* Fallback until app.js has bound the menu (html.nav-ready, set right after
     the hamburger's click handler): the sheet styling never applies, the
     links render as a plain wrapped row on their own line under the bar and
     the (JS-only) hamburger hides, so navigation survives a blocked or broken
     script. html.js is not enough here: boot.js sets it before app.js is
     even requested, so a lost app.js used to leave a hamburger that did
     nothing over hidden links. */
  html:not(.nav-ready) .nav-toggle { display: none; }
  html:not(.nav-ready) .nav { flex-wrap: wrap; }
  html:not(.nav-ready) .nav-links { flex-wrap: wrap; justify-content: flex-start; order: 3; flex-basis: 100%; }
  html.nav-ready .nav-links {
    position: fixed; inset: 0; z-index: 240;
    /* --menu-top is measured from the nav bar's real bottom edge when the
       menu opens (app.js), so the first item always starts BELOW the bar,
       including when something (a preview strip, a scrolled state) moves the
       bar. 84px is only the no-JS fallback. */
    padding: var(--menu-top, 84px) var(--gutter) 26px;
    overflow-y: auto;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--bg);
    border: 0; border-radius: 0;
    font-size: 19px;
    opacity: 0; transform: translateY(-8px);
    /* visibility joins the fade so the closed sheet leaves the tab order and
       the accessibility tree — opacity alone left 8 invisible focus stops. */
    visibility: hidden;
    pointer-events: none;
    overscroll-behavior: contain;
    padding-bottom: calc(26px + env(safe-area-inset-bottom));
    transition: opacity 260ms var(--ease), transform 300ms var(--ease-out),
                visibility 0s 300ms;
  }
  /* The bar's controls float above the open sheet, so the X is always whole
     and tappable — nothing renders half over, half under it. */
  .nav-side, .nav .wm { position: relative; z-index: 260; }
  html.nav-ready .nav-links a {
    padding: 14px 4px; border-radius: 10px; border-bottom: 1px solid var(--line-soft);
    opacity: 0; transform: translateY(-6px);
    transition: opacity 300ms var(--ease), transform 320ms var(--ease-out);
  }
  body.menu-open .nav-links a { opacity: 1; transform: none; }
  body.menu-open .nav-links a:nth-child(1) { transition-delay: 60ms; }
  body.menu-open .nav-links a:nth-child(2) { transition-delay: 100ms; }
  body.menu-open .nav-links a:nth-child(3) { transition-delay: 140ms; }
  body.menu-open .nav-links a:nth-child(4) { transition-delay: 180ms; }
  body.menu-open .nav-links a:nth-child(5) { transition-delay: 220ms; }
  body.menu-open .nav-links a:nth-child(6) { transition-delay: 260ms; }
  body.menu-open .nav-links a:nth-child(7) { transition-delay: 300ms; }
  .nav-links a[aria-current='page'] {
    background: linear-gradient(135deg, var(--btn-a), var(--btn-b));
    color: var(--on-accent);
    border-bottom-color: transparent;
    box-shadow: 0 4px 14px var(--halo);
  }
  .nav-links .nav-cta { margin-top: 18px; border: 0; opacity: 1; transform: none; }
  .nav-links .nav-cta .btn { width: 100%; justify-content: center; }
  /* The CTA keeps its button identity inside the sheet: the sheet's link
     recolor (ink on the page bg) was painting its label dark on the accent
     gradient, and the sheet's row padding + hairline don't belong on a pill. */
  .nav-links .nav-cta a { color: var(--on-accent); border-bottom: 0; padding: 0 22px; }
  .nav-links .nav-moods { display: flex; justify-content: center; padding-top: 20px; border: 0; }
  body.menu-open .nav-links { opacity: 1; transform: none; visibility: visible; transition-delay: 0s; pointer-events: auto; }
  /* backdrop-filter on the sticky nav creates a CONTAINING BLOCK for fixed
     descendants (measured on iOS: the open menu anchored to the nav's box and
     appeared at the top of the DOCUMENT when scrolled down). While the menu is
     open the bar drops its blur so the sheet anchors to the viewport. */
  body.menu-open .nav { -webkit-backdrop-filter: none; backdrop-filter: none; }
  body.menu-open { overflow: hidden; }
  .nav.is-scrolled, body.menu-open .nav {
    background: color-mix(in srgb, var(--bg) 92%, transparent);
  }
}
@media (min-width: 901px) {
  .nav-links .nav-cta { display: none; }
  .nav-toggle { display: none; }
}

/* ── Hero ──────────────────────────────────────────────────── */
.hero-appicon {
  width: clamp(64px, 6.4vw, 84px); height: auto;
  border-radius: 22%;
  box-shadow: 0 4px 12px color-mix(in srgb, var(--ink) 14%, transparent),
              0 14px 34px var(--halo);
}
.hero .hero-appicon + h1 { margin-top: 20px; }
.hero {
  position: relative; z-index: 2;
  padding-block: clamp(30px, 4.5vw, 64px) clamp(48px, 6vw, 88px);
}
.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.08fr) minmax(0, .92fr);
  gap: clamp(30px, 5vw, 72px);
  align-items: center;
}
.hero h1 { margin-top: 20px; }
.hero .lede { margin-top: 20px; }
.hero .store-badges { margin-top: 30px; }
.hero .cta-note { margin-top: 16px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.hero .cta-note .dot { width: 3px; height: 3px; border-radius: 50%; background: currentColor; opacity: .55; }

.hero-glow {
  position: absolute; z-index: 0; pointer-events: none;
  width: min(54vw, 680px); aspect-ratio: 1;
  right: -6%; top: -12%;
  background: radial-gradient(circle at 50% 50%, var(--halo), transparent 64%);
  filter: blur(20px);
}

/* ── Phone ─────────────────────────────────────────────────── */
.phone {
  --bezel: 7px;
  width: 100%; max-width: 306px; margin-inline: auto;
  border-radius: 46px;
  padding: var(--bezel);
  /* Fixed dark, not derived from --ink: on Dusk, --ink is cream, which turned
     the handset into a white phone. A device is a device in all three moods. */
  background: linear-gradient(158deg, #2C3238, #131619);
  box-shadow: var(--shadow-phone);
  position: relative;
}
.phone::after {
  content: ''; position: absolute; inset: 0; border-radius: 46px; pointer-events: none;
  border: 1px solid rgba(255, 255, 255, .14);
}
.phone-screen {
  position: relative;
  border-radius: 36px; overflow: hidden;
  /* iOS Safari promotes the translated/transitioned screenshot <img> to its
     own layer and that layer ignores ancestor border-radius, overflow AND
     clip-path — square screenshot corners poke past the bezel (owner-seen,
     reproduced in the iOS Simulator 2026-08-31). The alpha mask below is the
     one clip Safari applies to composited subtrees; isolation keeps the
     stacking context self-contained. clip-path stays for engines where it is
     the cheapest correct path. */
  clip-path: inset(0 round 36px);
  isolation: isolate;
  -webkit-mask-image: -webkit-radial-gradient(white, black);
  background: var(--bg);
  aspect-ratio: 750 / 1624;
}
/* Direct children only: these rules are for full-screen screenshot plates.
   The demo's small icons live deeper inside .d-screen wrappers and must NOT
   be ripped out of their tiles by this absolute positioning. */
/* A 2px bezel-dark ring OVER the screen edge: the screen's rounded clip and
   the frame's rounded corner rasterize on fractionally different grids, so at
   some zoom levels a hairline of screen shows past the bezel. The ring makes
   the bezel overlap the screen edge instead of merely meeting it. */
.phone-screen::before {
  content: ''; position: absolute; inset: 0; z-index: 3;
  border-radius: inherit; pointer-events: none;
  box-shadow: inset 0 0 0 2px #16191C;
}
.phone-screen > img {
  position: absolute; inset: 0;
  width: 100%; height: auto;
  object-fit: cover; object-position: top center;
  /* Per-screen --shift (set by gen.py's SCREEN_SHIFT) slides the visible
     window down past chrome or empty panels to the information-rich part.
     Percentage of the image's own rendered height. */
  translate: 0 var(--shift, 0%);
}
.phone-screen > img[data-screen] { opacity: 0; transition: opacity var(--t-slow) var(--ease); }
.phone-screen > img[data-screen].is-active, .phone-screen > img[data-screen]:only-child { opacity: 1; }
/* The screenshots are full-length captures; fade the crop into --bg so the cut
   reads as "the screen continues", not a rendering fault. */
.phone-screen::after {
  content: ''; position: absolute; z-index: 1; inset: auto 0 0 0;
  height: 92px; pointer-events: none;
  background: linear-gradient(to bottom, transparent, var(--bg));
}
.phone-screen--tall { aspect-ratio: 750 / 1660; }
.phone--big { max-width: 328px; border-radius: 44px; }
.phone--big::after { border-radius: 44px; }
.phone--tallish { max-width: 330px; border-radius: 44px; }
.phone--tallish::after { border-radius: 44px; }
.phone--tallish .phone-screen { aspect-ratio: 750 / 1600; }
.phone-notch {
  position: absolute; z-index: 2; top: 9px; left: 50%; transform: translateX(-50%);
  width: 86px; height: 22px; border-radius: 999px;
  background: #0C0F11;
}
.phone-wrap { position: relative; }
.plate-caption {
  margin-top: 18px; text-align: center;
  font-size: 12.5px; color: var(--ink3); letter-spacing: .01em;
}
.plate-caption em { font-family: 'Fraunces', Georgia, serif; font-style: italic; }

/* ── Motion system (calm-premium: 350-600ms, no overshoot outside the demo)
   Layer 1, signature: the mood change cross-fades via view transitions.
   Layer 2, tactile: every tappable thing answers the finger.
   Layer 3, ambient: the hero light drifts with scroll (app.js). */
::view-transition-old(root), ::view-transition-new(root) {
  animation-duration: 480ms;
  animation-timing-function: cubic-bezier(.4, 0, .2, 1);
}
.car-tab:active, .price-toggle button:active,
.swipe-btn:active, .nav-links a:active, .tlink:active {
  transform: scale(.97);
  transition-duration: 90ms;
}
/* The bar's Download button used to pop into existence on the first scroll;
   it now arrives like everything else on the page. display cannot transition,
   so a keyframe runs the moment the button is rendered. */
@keyframes dl-in {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: none; }
}
.mood-card:active { transform: translateY(-1px) scale(.98); }
.faq summary:active { opacity: .72; }
.d-cat:active { transform: scale(.94); transition-duration: 90ms; }
/* The journal count answers a saved entry with a small pop (demo only:
   the playful island inside a calm page). */
.is-pop { display: inline-block; animation: num-pop 280ms cubic-bezier(.175, .885, .32, 1.275); }
@keyframes num-pop {
  0% { transform: scale(1); }
  40% { transform: scale(1.22); }
  100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .is-pop { animation: none; }
}
/* A short line ABOVE an exhibit that frames what the reader is looking at. */
.plate-title {
  margin: 0 auto 18px; max-width: 46ch; text-align: center;
  font-family: 'Fraunces', Georgia, serif; font-style: italic;
  font-size: 16px; line-height: 1.5; color: var(--ink2);
  letter-spacing: -.005em;
}

/* Hero presentation: a gentle perspective that settles on hover. */
.hero-phone .phone {
  transform: perspective(1400px) rotateY(-9deg) rotateX(2.5deg) rotate(.6deg);
  transition: transform 650ms var(--ease-out);
}
.hero-phone:hover .phone { transform: perspective(1400px) rotateY(-2deg) rotateX(0deg) rotate(0deg); }
@media (prefers-reduced-motion: reduce) {
  .hero-phone .phone { transform: none; }
}

/* ── Spread (text + phone) ─────────────────────────────────── */
.spread {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
  gap: clamp(28px, 4.5vw, 60px);
  align-items: center;
}
.spread--top { align-items: start; }

/* ── Ledger rows (care points and the features pages) ──────── */
.ledger { border-top: 1px solid var(--line); }
.ledger-row {
  display: grid;
  grid-template-columns: 54px minmax(0, 1fr) minmax(0, 1.25fr);
  gap: clamp(14px, 2.5vw, 34px);
  align-items: baseline;
  padding-block: clamp(18px, 2.2vw, 26px);
  border-bottom: 1px solid var(--line);
  transition: background var(--t-std) var(--ease);
}
.ledger-row:hover { background: color-mix(in srgb, var(--ink) 3%, transparent); }
.ledger-no {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 14px; color: var(--ink3); font-variant-numeric: tabular-nums;
}
.ledger-name {
  font-family: 'Fraunces', Georgia, serif;
  font-size: clamp(19px, 1.7vw, 24px); font-weight: 440;
  letter-spacing: -.018em; line-height: 1.18;
}
.ledger-desc { color: var(--ink2); font-size: 15.5px; }

/* ── Cards ─────────────────────────────────────────────────── */
.cards { display: grid; gap: clamp(14px, 1.8vw, 22px); }
.cards--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.cards--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.card {
  background: linear-gradient(180deg, var(--surface), color-mix(in srgb, var(--surface) 93%, var(--bg)));
  border: 1px solid var(--line-soft);
  border-radius: var(--r-lg);
  padding: clamp(22px, 2.3vw, 30px);
  box-shadow: var(--shadow-card);
  transition: transform var(--t-std) var(--ease-out), box-shadow var(--t-std) var(--ease);
}
.card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lift); }
/* Card titles are h3 under a section h2, or h2 when the cards sit straight
   under the page h1 (legal, privacy-first, support). One look either way. */
.card h3, .card h2 {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 19.5px; font-weight: 460; letter-spacing: -.014em;
  margin-bottom: 8px;
}
.card p { color: var(--ink2); font-size: 15px; }
.card-icon {
  width: 44px; height: 44px; border-radius: 13px;
  display: grid; place-items: center;
  background: linear-gradient(150deg, color-mix(in srgb, var(--accent) 20%, var(--surface)), var(--accent-2));
  border: 1px solid color-mix(in srgb, var(--accent) 18%, transparent);
  color: var(--accent-deep);
  margin-bottom: 16px;
}
html[data-theme='dusk'] .card-icon { color: var(--accent); }
.card-icon svg { width: 21px; height: 21px; }

/* ── The deep band ─────────────────────────────────────────── */
.band {
  background:
    radial-gradient(1100px 540px at 82% -12%, var(--band-glow), transparent 62%),
    linear-gradient(163deg, var(--band-a), var(--band-b));
  color: var(--band-ink);
  position: relative; z-index: 2;
  padding-block: clamp(62px, 7.5vw, 112px);
  transition: background var(--t-slow) var(--ease);
}
/* html[data-theme] lifts this to (0,3,2), above the Tide/Blush `.display em`
   rules at (0,2,2); the plain `.band .display em` was (0,2,1) and lost, so the
   italic word on the dark bands painted --accent-deep, 1.9:1 against the band. */
html[data-theme] .band .display em { color: var(--band-accent); }
.band .lede { color: var(--band-ink2); }
.band .eyebrow { color: var(--band-ink2); }
.band .eyebrow::before { background: var(--band-accent); }
.band .sec-rule { border-color: var(--band-line); }
.band .sec-no, .band .sec-label { color: var(--band-ink2); }
.band-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(18px, 2.6vw, 34px); margin-top: clamp(30px, 3.6vw, 50px); }
.band-tile { border-top: 1px solid var(--band-line); padding-top: 20px; }
.band-tile h3 {
  font-family: 'Fraunces', Georgia, serif; font-weight: 460;
  font-size: 19.5px; letter-spacing: -.014em; margin-bottom: 8px;
}
.band-tile p { color: var(--band-ink2); font-size: 15px; }
.band-tile .bt-icon { color: var(--band-accent); margin-bottom: 14px; }
.band-tile .bt-icon svg { width: 22px; height: 22px; }
.band a { color: var(--band-accent); }
.band .tlink { color: var(--band-accent); }
.band .btn--primary { box-shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 10px 30px var(--band-glow); }
/* `.band a` recolours every link to the band accent, badges included: the
   download band's badges read pale blue while the hero's are white. Same
   component, same colour. */
.band .store-badge { border-color: rgba(255, 255, 255, .14); color: #FFFFFF; }

/* ── App showcase: the accordion tour ──────────────────────── */
.show {
  display: grid;
  grid-template-columns: minmax(0, 1.12fr) minmax(0, .88fr);
  gap: clamp(28px, 4.5vw, 64px);
  align-items: center;
}
.show-list { border-top: 1px solid var(--line); }
.show-item { border-bottom: 1px solid var(--line); }
.show-tab {
  width: 100%;
  display: flex; align-items: center; gap: 15px;
  padding: 17px 4px;
  text-align: left;
  transition: color var(--t-quick) var(--ease);
}
.show-tab .st-icon {
  width: 40px; height: 40px; border-radius: 12px; flex: none;
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--accent) 9%, var(--surface));
  border: 1px solid var(--line-soft);
  color: var(--accent-deep);
  transition: background var(--t-std) var(--ease), color var(--t-std) var(--ease), border-color var(--t-std) var(--ease);
}
html[data-theme='dusk'] .show-tab .st-icon { color: var(--accent); }
.show-tab .st-icon svg { width: 19px; height: 19px; }
.show-tab b {
  font-family: 'Fraunces', Georgia, serif;
  font-size: clamp(18px, 1.6vw, 22px); font-weight: 460; letter-spacing: -.015em;
}
.show-tab .st-chev { margin-left: auto; flex: none; width: 22px; height: 22px; position: relative; }
.show-tab .st-chev::before, .show-tab .st-chev::after {
  content: ''; position: absolute; background: var(--accent); border-radius: 2px;
  transition: transform var(--t-std) var(--ease-out), opacity var(--t-std) var(--ease);
}
.show-tab .st-chev::before { left: 0; top: 10px; width: 22px; height: 1.8px; }
.show-tab .st-chev::after { left: 10px; top: 0; width: 1.8px; height: 22px; }
.show-item.is-open .st-chev::after { transform: rotate(90deg); opacity: 0; }
.show-item.is-open .show-tab .st-icon {
  background: linear-gradient(135deg, var(--btn-a), var(--btn-b));
  border-color: transparent;
  color: var(--on-accent);
}
.show-desc {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows var(--t-std) var(--ease);
}
.show-item.is-open .show-desc { grid-template-rows: 1fr; }
.show-desc > div { overflow: hidden; }
.show-desc p {
  color: var(--ink2); font-size: 15.5px; max-width: 56ch;
  padding: 0 4px 6px 59px;
}
.show-desc .pull {
  font-family: 'Fraunces', Georgia, serif; font-style: italic;
  font-size: 16.5px; color: var(--accent-deep);
  padding-bottom: 18px;
}
html[data-theme='dusk'] .show-desc .pull { color: var(--accent); }
.show-foot { margin-top: 18px; font-size: 13.5px; color: var(--ink3); }

/* ── Mood cards ────────────────────────────────────────────── */
.mood-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(14px, 2vw, 22px); }
.mood-card {
  position: relative; overflow: hidden;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--surface);
  padding: 24px 22px 22px;
  text-align: left;
  min-height: 168px;
  display: flex; flex-direction: column; justify-content: flex-end;
  box-shadow: var(--shadow-card);
  transition: transform var(--t-std) var(--ease-out), border-color var(--t-std) var(--ease), box-shadow var(--t-std) var(--ease);
}
.mood-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lift); }
.mood-card[aria-pressed='true'] { border-color: color-mix(in srgb, var(--accent) 55%, transparent); box-shadow: var(--shadow-lift); }
.mc-wash { position: absolute; inset: 0; z-index: 0; }
.mood-card[data-mood='tide']  .mc-wash { background: linear-gradient(150deg, #EEF2F4 0%, #D7E2EA 46%, #8FB4CB 100%); }
.mood-card[data-mood='blush'] .mc-wash { background: linear-gradient(150deg, #FCF1F1 0%, #F5D9E0 46%, #E092AA 100%); }
.mood-card[data-mood='dusk']  .mc-wash { background: linear-gradient(150deg, #2E242C 0%, #3A2E37 46%, #83531B 100%); }
.mc-body { position: relative; z-index: 1; }
.mc-name {
  display: block;
  font-family: 'Fraunces', Georgia, serif; font-style: italic;
  font-size: 25px; font-weight: 460; letter-spacing: -.02em;
  color: #10202A;
}
.mc-line { display: block; margin-top: 4px; font-size: 13.5px; color: #33505F; }
.mood-card[data-mood='blush'] .mc-name { color: #3A2430; }
.mood-card[data-mood='blush'] .mc-line { color: #4A2F3B; } /* 5.5:1 on the wash's dark end */
.mood-card[data-mood='dusk'] .mc-name { color: #F2E6D7; }
.mood-card[data-mood='dusk'] .mc-line { color: #F2E6D7; } /* 5.3:1 on the wash's amber end */
.mc-tick {
  position: absolute; z-index: 1; top: 16px; right: 16px;
  width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(255, 255, 255, .85); color: #10202A;
  opacity: 0; transform: scale(.7);
  transition: opacity var(--t-std) var(--ease), transform var(--t-std) var(--ease-out);
}
.mood-card[data-mood='dusk'] .mc-tick { background: rgba(242, 230, 215, .9); }
.mood-card[aria-pressed='true'] .mc-tick { opacity: 1; transform: scale(1); }
.mc-tick svg { width: 13px; height: 13px; }

/* ── Pricing teaser (home) ─────────────────────────────────── */
.tease { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(12px, 1.4vw, 18px); }
.tease-card {
  background: linear-gradient(180deg, var(--surface), color-mix(in srgb, var(--surface) 93%, var(--bg)));
  border: 1px solid var(--line-soft);
  border-radius: var(--r-lg);
  padding: 22px;
  box-shadow: var(--shadow-card);
  display: grid; gap: 4px; align-content: start;
  text-decoration: none;
  transition: transform var(--t-std) var(--ease-out), box-shadow var(--t-std) var(--ease), border-color var(--t-std) var(--ease),
              scale 90ms var(--ease-out);
}
/* Press on `scale`: the reveal system owns `transform` AND the transition
   list on these cards (they carry data-reveal), so the 90ms press transition
   has to ride on the reveal rule itself. */
.tease-card:active { scale: .97; }
html.js .tease-card[data-reveal] {
  transition: opacity 700ms var(--ease-out) var(--rd, 0ms),
              transform 700ms var(--ease-out) var(--rd, 0ms),
              scale 90ms var(--ease-out) 0ms;
}
.tease-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lift); border-color: color-mix(in srgb, var(--accent) 35%, transparent); }
.tease-name {
  font-family: 'Fraunces', Georgia, serif; font-style: italic;
  font-size: 21px; font-weight: 460; letter-spacing: -.02em;
}
.tease-price { display: flex; align-items: baseline; gap: 5px; margin-top: 8px; }
.tease-price b {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 29px; font-weight: 430; letter-spacing: -.025em; line-height: 1;
}
.tease-price span { font-size: 13px; color: var(--ink3); }
.tease-for { font-size: 13.5px; color: var(--ink2); margin-top: 6px; }
.tease-card--featured {
  border: 1px solid transparent;
  background:
    linear-gradient(180deg, var(--surface), color-mix(in srgb, var(--surface) 93%, var(--bg))) padding-box,
    linear-gradient(135deg, var(--btn-a), var(--btn-b)) border-box;
  box-shadow: 0 12px 36px var(--halo);
}

/* ── Pricing (full page) ───────────────────────────────────── */
.plans { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(12px, 1.4vw, 18px); align-items: stretch; }
.plan {
  display: flex; flex-direction: column;
  background: linear-gradient(180deg, var(--surface), color-mix(in srgb, var(--surface) 94%, var(--bg)));
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: clamp(20px, 2.1vw, 26px);
  box-shadow: var(--shadow-card);
}
.plan--featured {
  position: relative;
  border: 1px solid transparent;
  background:
    linear-gradient(180deg, var(--surface), color-mix(in srgb, var(--surface) 94%, var(--bg))) padding-box,
    linear-gradient(135deg, var(--btn-a), var(--btn-b)) border-box;
  box-shadow: 0 14px 42px var(--halo);
}
.plan-flag {
  position: absolute; top: -11px; left: 50%; transform: translateX(-50%);
  background: linear-gradient(135deg, var(--btn-a), var(--btn-b));
  color: var(--on-accent);
  font-size: 10.5px; font-weight: 700; letter-spacing: .13em; text-transform: uppercase;
  padding: 4px 12px; border-radius: 999px; white-space: nowrap;
  box-shadow: 0 4px 12px var(--halo);
}
.plan-name {
  font-family: 'Fraunces', Georgia, serif; font-style: italic;
  font-size: 22px; font-weight: 460; letter-spacing: -.02em;
}
.plan-for { font-size: 13px; color: var(--ink3); margin-top: 3px; }
.plan-price {
  display: flex; align-items: baseline; gap: 4px;
  margin-top: 18px; padding-top: 18px; border-top: 1px solid var(--line-soft);
}
.plan-price b {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 33px; font-weight: 430; letter-spacing: -.028em; line-height: 1;
}
.plan-price span { font-size: 13.5px; color: var(--ink3); }
.plan-annual { font-size: 12.5px; color: var(--ink3); margin-top: 7px; min-height: 1.4em; }
.plan ul { margin-top: 18px; display: grid; gap: 8px; font-size: 14px; color: var(--ink2); }
.plan li { display: flex; gap: 9px; align-items: flex-start; }
.plan li svg { width: 14px; height: 14px; margin-top: 4px; flex: none; color: var(--accent); }
.price-toggle {
  display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px;
  max-width: 100%;
  padding: 4px; border-radius: 999px;
  background: color-mix(in srgb, var(--surface-soft) 80%, transparent);
  border: 1px solid var(--line-soft);
}
.price-toggle button {
  min-height: 38px; padding: 0 18px; border-radius: 999px;
  font-size: 14px; font-weight: 600; color: var(--ink2);
  transition: background var(--t-quick) var(--ease), color var(--t-quick) var(--ease), box-shadow var(--t-quick) var(--ease);
}
.price-toggle button[aria-pressed='true'] {
  background: var(--surface); color: var(--ink);
  box-shadow: 0 1px 4px color-mix(in srgb, var(--ink) 14%, transparent);
}

/* ── Comparison table v2: grouped, scannable ───────────────── */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.cmp-card {
  background: linear-gradient(180deg, var(--surface), color-mix(in srgb, var(--surface) 95%, var(--bg)));
  border: 1px solid var(--line-soft);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}
table.compare {
  width: 100%; min-width: 640px;
  border-collapse: collapse;
  font-size: 14px;
}
table.compare th, table.compare td {
  padding: 12px 16px; border-bottom: 1px solid var(--line-soft);
  vertical-align: middle;
}
table.compare thead th {
  padding-block: 16px;
  border-bottom: 1px solid var(--line);
  font-family: 'Fraunces', Georgia, serif; font-style: italic;
  font-size: 17px; font-weight: 460; letter-spacing: -.01em;
  text-align: center;
}
table.compare thead th:first-child {
  font-family: inherit; font-style: normal; font-size: 11px; font-weight: 700;
  letter-spacing: .19em; text-transform: uppercase; color: var(--ink3);
  text-align: left;
}
table.compare tbody th {
  font-weight: 500; color: var(--ink); text-align: left; font-size: 14px;
}
table.compare td { color: var(--ink2); text-align: center; }
/* Group rows: the section labels that make the list scannable. */
tr.cmp-group th {
  padding: 20px 16px 8px;
  font-size: 11px; font-weight: 700; letter-spacing: .17em; text-transform: uppercase;
  color: var(--ink3); border-bottom: 1px solid var(--line-soft);
}
/* The Pro column, gently lit. Pro is always column 3. */
table.compare thead th:nth-child(3),
table.compare tbody tr:not(.cmp-group) td:nth-child(3) {
  background: color-mix(in srgb, var(--accent) 7%, transparent);
}
table.compare thead th:nth-child(3) { color: var(--accent-deep); }
html[data-theme='dusk'] table.compare thead th:nth-child(3) { color: var(--accent); }
/* Value marks: a filled check pill, a number, or a quiet dash. */
.vy {
  display: inline-grid; place-items: center;
  width: 22px; height: 22px; border-radius: 50%;
  background: color-mix(in srgb, var(--accent) 16%, var(--surface));
  color: var(--accent-deep);
}
html[data-theme='dusk'] .vy { color: var(--accent); }
.vy svg { width: 11px; height: 11px; }
.vn { display: inline-block; width: 14px; height: 1.5px; background: var(--line); vertical-align: middle; }
.vnum { font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
/* On a phone the first column stays put while the plans scroll. */
@media (max-width: 900px) {
  table.compare tbody th, table.compare thead th:first-child, tr.cmp-group th {
    position: sticky; left: 0; z-index: 1;
    background: var(--surface);
    box-shadow: 8px 0 12px -10px color-mix(in srgb, var(--ink) 25%, transparent);
  }
}

/* ── Phone plan picker: one plan beside the features ────────
   A five-column table on a 390px screen shows only the Free column and no
   hint the rest exist. Under 640px the picker chips choose which single plan
   column renders; the picker stays stuck under the nav so the plan can be
   switched mid-table. Desktop and tablet keep all columns. */
.cmp-picker-bar { display: none; }
/* html.cmp-ready is set by app.js once the plan picker is wired: without it a
   phone kept only the Pro column and four dead buttons when the script was
   lost, so the collapse now waits for the controls that drive it. */
@media (max-width: 640px) {
  html.cmp-ready .cmp-picker-bar {
    display: flex; justify-content: center;
    position: sticky; z-index: 40;
    /* The bar height is measured into --nav-h by app.js; 66px is only the
       no-JS fallback. Same lesson as the menu sheet: never hardcode where
       the nav ends. */
    top: calc(var(--nav-h, 60px) + 6px);
    margin-bottom: 14px;
  }
  html.cmp-ready .cmp-picker { box-shadow: 0 6px 18px color-mix(in srgb, var(--ink) 12%, transparent); backdrop-filter: blur(10px); }
  html.cmp-ready .cmp-picker button { min-height: 44px; padding: 0 16px; }
  html.cmp-ready table.compare { min-width: 0; }
  /* Hide every plan column, then reveal the picked one. In each row the
     feature name is child 1; Free/Pro/Family/Care are children 2-5. */
  html.cmp-ready table.compare thead th:not(:first-child),
  html.cmp-ready table.compare tbody tr:not(.cmp-group) td { display: none; }
  html.cmp-ready .cmp-card[data-cmp-plan='free'] table.compare thead th:nth-child(2),
  html.cmp-ready .cmp-card[data-cmp-plan='free'] table.compare tbody tr:not(.cmp-group) td:nth-child(2),
  html.cmp-ready .cmp-card[data-cmp-plan='pro'] table.compare thead th:nth-child(3),
  html.cmp-ready .cmp-card[data-cmp-plan='pro'] table.compare tbody tr:not(.cmp-group) td:nth-child(3),
  html.cmp-ready .cmp-card[data-cmp-plan='family'] table.compare thead th:nth-child(4),
  html.cmp-ready .cmp-card[data-cmp-plan='family'] table.compare tbody tr:not(.cmp-group) td:nth-child(4),
  html.cmp-ready .cmp-card[data-cmp-plan='care'] table.compare thead th:nth-child(5),
  html.cmp-ready .cmp-card[data-cmp-plan='care'] table.compare tbody tr:not(.cmp-group) td:nth-child(5) {
    display: table-cell; width: 118px;
  }
  /* Two columns cannot overflow sideways: the frozen-column treatment is
     noise here, and its shadow reads as a smudge. */
  html.cmp-ready table.compare tbody th, html.cmp-ready table.compare thead th:first-child, html.cmp-ready tr.cmp-group th {
    position: static; box-shadow: none; background: transparent;
  }
}

/* ── FAQ ───────────────────────────────────────────────────── */
.faq { border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  display: flex; align-items: flex-start; gap: 18px;
  padding-block: clamp(16px, 1.8vw, 21px);
  cursor: pointer; list-style: none;
  font-family: 'Fraunces', Georgia, serif;
  font-size: clamp(17px, 1.5vw, 20px); font-weight: 440; letter-spacing: -.012em;
  line-height: 1.32;
  transition: color var(--t-quick) var(--ease);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--accent-deep); }
html[data-theme='dusk'] .faq summary:hover { color: var(--accent); }
.faq summary .q-mark { flex: none; margin-left: auto; width: 22px; height: 22px; margin-top: 3px; position: relative; }
.faq summary .q-mark::before, .faq summary .q-mark::after {
  content: ''; position: absolute; background: var(--accent); border-radius: 2px;
  transition: transform var(--t-std) var(--ease-out), opacity var(--t-std) var(--ease);
}
.faq summary .q-mark::before { left: 0; top: 10px; width: 22px; height: 1.8px; }
.faq summary .q-mark::after { left: 10px; top: 0; width: 1.8px; height: 22px; }
.faq details[open] summary .q-mark::after { transform: rotate(90deg); opacity: 0; }
/* FAQ open: the answer eases in instead of snapping. The height interpolation
   is the Chromium 129+ path (::details-content + interpolate-size); browsers
   without it ignore these rules and keep the instant open, and the fade-rise
   on the answer below still softens the jump there. Reduce-motion is covered
   by the global media block. */
.faq { interpolate-size: allow-keywords; }
.faq details::details-content {
  height: 0; overflow: clip;
  transition: height var(--t-std) var(--ease),
              content-visibility var(--t-std) allow-discrete;
}
.faq details[open]::details-content { height: auto; }
.faq details[open] .faq-answer { animation: faq-in 300ms var(--ease-out); }
@keyframes faq-in {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: none; }
}
.faq-answer { padding-bottom: clamp(18px, 2vw, 24px); max-width: 62ch; }
.faq-answer p { color: var(--ink2); font-size: 15px; }
.faq-answer p + p { margin-top: 12px; }

/* ── Prose (legal + long-form) ─────────────────────────────── */
/* Instrument Sans has a wide "0", so 70ch was 769px and ~100 characters a
   line on the legal pages. 56ch lands near 84, inside the readable range,
   and still clears the 560px scrolling-table minimum below. */
.prose { max-width: 56ch; }
.prose h2 {
  font-family: 'Fraunces', Georgia, serif; font-weight: 460;
  font-size: clamp(21px, 1.9vw, 26px); letter-spacing: -.018em; line-height: 1.22;
  margin: 42px 0 13px;
}
.prose h3 {
  font-family: 'Fraunces', Georgia, serif; font-weight: 460;
  font-size: 18.5px; letter-spacing: -.014em; margin: 28px 0 10px;
}
.prose p, .prose li { color: var(--ink2); font-size: 16px; }
.prose p { margin-bottom: 14px; }
.prose ul, .prose ol { margin: 0 0 17px 22px; display: grid; gap: 7px; }
.prose ul { list-style: disc; }
.prose ol { list-style: decimal; }
.prose strong { color: var(--ink); font-weight: 600; }
.prose a { color: var(--accent-deep); text-decoration: underline; text-underline-offset: 3px; }
html[data-theme='dusk'] .prose a { color: var(--accent); }
.prose table { width: 100%; border-collapse: collapse; margin-bottom: 20px; font-size: 14.5px; }
/* Data tables in prose scroll inside their own box on a narrow phone; do NOT
   add overflow-wrap:anywhere here, it breaks words mid-syllable on desktop. */
.prose th, .prose td { padding: 11px 12px; border-bottom: 1px solid var(--line-soft); text-align: left; vertical-align: top; color: var(--ink2); }
.prose th { color: var(--ink); font-weight: 600; }
.prose .table-scroll table { min-width: 560px; }
/* Tables keep the old 70ch width: three columns need it, running text does not. */
.prose .table-scroll { width: min(70ch, 100vw - 2 * var(--gutter)); }
.callout {
  background: linear-gradient(180deg, var(--surface), color-mix(in srgb, var(--surface) 94%, var(--bg)));
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--r-sm);
  box-shadow: var(--shadow-card);
  padding: 18px 20px; margin-bottom: 22px;
}
.callout p:last-child { margin-bottom: 0; }
.page-head { padding-block: clamp(38px, 4.6vw, 64px) clamp(16px, 2.4vw, 30px); position: relative; z-index: 2; }
.page-head .lede { margin-top: 16px; }
.page-meta { margin-top: 13px; font-size: 13.5px; color: var(--ink3); }

/* ── Footer ────────────────────────────────────────────────── */
.footer {
  position: relative; z-index: 2;
  border-top: 1px solid var(--line);
  padding-block: clamp(44px, 5.5vw, 68px) 32px;
  background: color-mix(in srgb, var(--surface) 40%, transparent);
}
.footer-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) repeat(3, minmax(0, 1fr));
  gap: clamp(26px, 4vw, 52px);
}
.footer .wm img { height: 32px; }
.footer-tag { margin-top: 16px; color: var(--ink2); font-size: 14.5px; max-width: 30ch; }
.footer h2 {
  font-size: 11px; font-weight: 700; letter-spacing: .19em; text-transform: uppercase;
  color: var(--ink3); margin-bottom: 14px;
}
.footer-col { display: grid; gap: 9px; font-size: 14.5px; }
.footer-col a { color: var(--ink2); text-decoration: none; transition: color var(--t-quick) var(--ease); width: fit-content; padding-block: 6px; margin-block: -6px; }
.footer-col a:hover { color: var(--ink); }
.footer-base {
  margin-top: clamp(34px, 4.5vw, 54px); padding-top: 22px;
  border-top: 1px solid var(--line);
  display: flex; flex-wrap: wrap; gap: 16px 26px; align-items: center;
  font-size: 12.5px; color: var(--ink3);
}
.footer-social { display: flex; gap: 14px; margin-left: auto; }
.footer-social a { color: var(--ink3); transition: color var(--t-quick) var(--ease); padding: 13px; margin: -13px -4px; }
.footer-social a:hover { color: var(--ink); }
.footer-social svg { width: 18px; height: 18px; }
.footer-disclaimer { flex-basis: 100%; max-width: 78ch; line-height: 1.55; }

/* ── Hero demo: the app's core loop, working ───────────────── */
.demo-wrap { position: relative; }
.demo-flag {
  position: absolute; z-index: 3; top: -10px; right: 4px;
  background: linear-gradient(135deg, var(--btn-a), var(--btn-b));
  color: var(--on-accent);
  font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  padding: 6px 13px; border-radius: 999px;
  box-shadow: 0 6px 18px var(--halo);
  transform: rotate(4deg);
  animation: demo-nod 2.4s var(--ease) infinite;
  transition: opacity var(--t-std) var(--ease), transform var(--t-std) var(--ease);
}
.demo-flag.is-done { opacity: 0; transform: rotate(4deg) scale(.8); }
@keyframes demo-nod {
  0%, 100% { transform: rotate(4deg) translateY(0); }
  50% { transform: rotate(4deg) translateY(-4px); }
}
.phone-screen.demo { background: var(--bg); }
.phone-screen.demo::after { display: none; } /* no crop fade over live UI */
.demo .d-screen {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  padding: 42px 13px 13px;
  opacity: 0; transform: translateX(22px) scale(.985);
  visibility: hidden; /* out of the tab order + a11y tree while hidden */
  transition: opacity 430ms cubic-bezier(.22, 1, .36, 1),
              transform 460ms cubic-bezier(.22, 1, .36, 1),
              visibility 0s 460ms;
  pointer-events: none;
}
.demo .d-screen.is-active { opacity: 1; transform: none; visibility: visible; transition-delay: 0s; pointer-events: auto; }
.d-title {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 18px; font-weight: 470; letter-spacing: -.015em;
  flex: none;
}
.d-title em { font-style: italic; color: var(--accent); }
.d-grid {
  margin-top: 11px; flex: 1;
  /* No overscroll containment: a page-scroll that starts on the tile grid
     must chain to the page at the grid's edge, not trap the thumb. */
  overflow-y: auto;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 7px; align-content: start;
  padding: 2px 2px 8px;
  scrollbar-width: none;
}
.d-grid::-webkit-scrollbar { display: none; }
.d-cat {
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  padding: 9px 4px 8px;
  border-radius: 12px;
  background: color-mix(in srgb, var(--c) 12%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--c) 24%, transparent);
  font-size: 9.5px; font-weight: 600; line-height: 1.2; text-align: center;
  color: color-mix(in srgb, var(--c) 46%, var(--ink));
  cursor: pointer;
  transition: transform var(--t-quick) var(--ease-out), box-shadow var(--t-quick) var(--ease);
}
.d-cat:hover { transform: translateY(-2px); box-shadow: 0 6px 14px color-mix(in srgb, var(--c) 22%, transparent); }
.d-cat img { width: 21px; height: 21px; }
.d-top { display: flex; flex-wrap: wrap; align-items: center; gap: 9px; flex: none; }
.d-back {
  width: 32px; height: 32px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  background: var(--surface); border: 1px solid var(--line-soft);
  color: var(--ink2); cursor: pointer;
  position: relative;
}
/* Invisible hit-area extensions: the demo replica keeps the app's visual
   scale, but real thumbs get ~44px targets. */
.d-back::after, .dj-fcat::after { content: ''; position: absolute; inset: -6px; }
.d-sev button { position: relative; }
.d-sev button::after { content: ''; position: absolute; inset: -6px 0; }
.d-back svg { width: 15px; height: 15px; }
.d-chip {
  display: inline-flex; align-items: center; gap: 7px;
  max-width: 100%;
  padding: 6px 13px 6px 9px; border-radius: 999px;
  background: color-mix(in srgb, var(--c, var(--accent)) 14%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--c, var(--accent)) 26%, transparent);
  font-size: 12px; font-weight: 600;
  color: color-mix(in srgb, var(--c, var(--accent)) 46%, var(--ink));
}
.d-chip img { width: 15px; height: 15px; }
/* The compose header shows category + subcategory as two chips; the second
   simply stays away until a subcategory exists. */
.d-chip--sub { padding: 6px 13px; }
.d-chip--sub:empty { display: none; }

/* ── Demo subcategory step (mirrors log_step_subcategory) ── */
.d-sub .d-title { margin-top: 12px; }
.d-sublist {
  margin-top: 11px; flex: 1;
  overflow-y: auto;
  display: grid; gap: 7px; align-content: start;
  padding: 2px 2px 8px;
  scrollbar-width: none;
}
.d-sublist::-webkit-scrollbar { display: none; }
.d-subtile {
  display: flex; align-items: center; gap: 9px;
  min-height: 38px; padding: 8px 12px;
  border-radius: 12px; text-align: left;
  background: var(--surface);
  border: 1px solid var(--line-soft);
  box-shadow: 0 3px 8px color-mix(in srgb, var(--ink) 4%, transparent);
  font-size: 12px; font-weight: 600; color: var(--ink);
  cursor: pointer;
  transition: transform var(--t-quick) var(--ease-out), box-shadow var(--t-quick) var(--ease);
}
.d-subtile::before {
  content: ''; width: 7px; height: 7px; border-radius: 50%; flex: none;
  background: var(--c, var(--accent));
}
.d-subtile::after {
  content: ''; margin-left: auto; flex: none;
  width: 7px; height: 7px;
  border-top: 2px solid var(--ink3); border-right: 2px solid var(--ink3);
  transform: rotate(45deg); border-radius: 1px;
}
.d-subtile:hover {
  transform: translateY(-1px);
  box-shadow: 0 6px 14px color-mix(in srgb, var(--c, var(--accent)) 20%, transparent);
}
.d-sev { display: flex; gap: 6px; margin-top: 12px; flex: none; }
.d-sev button {
  flex: 1; min-height: 32px; border-radius: 999px;
  font-size: 11.5px; font-weight: 600;
  border: 1px solid var(--line); color: var(--ink2);
  background: var(--surface);
  cursor: pointer;
  transition: background var(--t-quick) var(--ease), color var(--t-quick) var(--ease), border-color var(--t-quick) var(--ease), transform var(--t-quick) var(--ease-out);
}
.d-sev button[data-sev='Mild'] { --sv: var(--sev-mild); }
.d-sev button[data-sev='Moderate'] { --sv: var(--sev-moderate); }
.d-sev button[data-sev='Severe'] { --sv: var(--sev-severe); }
.d-sev button.is-on {
  background: color-mix(in srgb, var(--sv) 14%, var(--surface));
  border-color: color-mix(in srgb, var(--sv) 45%, transparent);
  color: var(--sv);
}
.d-paper {
  flex: 1; margin-top: 12px; min-height: 0;
  background: var(--surface);
  background-image: repeating-linear-gradient(
    to bottom,
    transparent 0, transparent 27px,
    color-mix(in srgb, var(--ink) 5%, transparent) 27px,
    color-mix(in srgb, var(--ink) 5%, transparent) 28px);
  border: 1px solid var(--line-soft);
  border-radius: 13px;
  box-shadow: var(--shadow-card);
  padding: 12px 13px;
  font-family: 'Fraunces', Georgia, serif; font-style: italic;
  font-size: 14px; line-height: 28px; color: var(--ink2);
  overflow: hidden;
}
.d-caret {
  display: inline-block; width: 1.5px; height: .95em;
  background: var(--accent); vertical-align: -2px; margin-left: 1px;
  animation: d-blink 1s steps(1) infinite;
}
@keyframes d-blink { 50% { opacity: 0; } }
.d-save {
  flex: none; margin-top: 12px; min-height: 40px;
  border-radius: 999px;
  background: linear-gradient(135deg, var(--btn-a), var(--btn-b));
  color: var(--on-accent);
  font-size: 13px; font-weight: 600;
  cursor: pointer;
  box-shadow: 0 6px 18px var(--halo);
  transition: filter var(--t-quick) var(--ease), transform var(--t-quick) var(--ease-out);
}
.d-save:hover { filter: brightness(1.07); }
.d-save:active { transform: scale(.97); }
.d-toast {
  position: absolute; z-index: 2; top: 46px; left: 50%; transform: translate(-50%, -8px);
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line-soft);
  font-size: 11px; font-weight: 600;
  padding: 6px 13px; border-radius: 999px;
  box-shadow: var(--shadow-lift);
  opacity: 0; pointer-events: none;
  transition: opacity var(--t-std) var(--ease), transform var(--t-std) var(--ease-out);
}
.d-toast.is-in { opacity: 1; transform: translate(-50%, 0); }
.d-toast { white-space: nowrap; }
/* In the tour the prompt itself says "Saved.", so the toast would only
   repeat it on top of the journal title. */
html.tour .d-toast { display: none; }
/* The journal list scrolls inside the phone once it holds more rows than the
   screen (the three seeds plus what the visitor saves); no overscroll
   containment, so a page scroll that starts on it chains to the page. */
.d-list { display: flex; flex-direction: column; gap: 8px; margin-top: 11px; flex: 1; min-height: 0; overflow-y: auto; scrollbar-width: none; }
.d-list::-webkit-scrollbar { display: none; }
.d-entry {
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-left: 3px solid var(--c, var(--accent));
  border-radius: 12px;
  padding: 9px 11px;
  box-shadow: var(--shadow-card);
  display: grid; gap: 4px;
  animation: d-drop 480ms var(--ease-out);
}
/* The category filters set `hidden` on entries (app.js), but an author
   `display: grid` outranks the browser's [hidden] rule, so nothing ever hid.
   Now a filtered-out entry is gone, as the pressed chip promises. */
.d-entry[hidden] { display: none; }
@keyframes d-drop {
  from { opacity: 0; transform: translateY(-8px); }
  to { opacity: 1; transform: none; }
}
.d-entry-top { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
.d-entry-cat {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 10px; font-weight: 700;
  color: color-mix(in srgb, var(--c, var(--accent)) 46%, var(--ink));
}
.d-entry-cat img { width: 13px; height: 13px; }
.d-entry-sev {
  font-size: 9.5px; font-weight: 700; letter-spacing: .04em;
  color: var(--sv, var(--sev-mild));
  border: 1px solid color-mix(in srgb, var(--sv, var(--sev-mild)) 40%, transparent);
  padding: 2px 8px; border-radius: 999px;
}
.d-entry b {
  font-family: 'Fraunces', Georgia, serif; font-style: italic;
  font-size: 12.5px; font-weight: 460; line-height: 1.35;
}
.d-entry-date { font-size: 10px; color: var(--ink3); }
.d-again {
  flex: none; margin-top: 10px; min-height: 36px;
  border-radius: 999px;
  border: 1px solid var(--line); color: var(--ink2);
  background: var(--surface);
  font-size: 12.5px; font-weight: 600; cursor: pointer;
  transition: border-color var(--t-quick) var(--ease), color var(--t-quick) var(--ease);
}
.d-again:hover { border-color: var(--ink3); color: var(--ink); }

/* ── Screenshot film strip ─────────────────────────────────── */
.strip {
  display: flex; gap: clamp(16px, 2.4vw, 30px);
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  scroll-snap-type: x proximity;
  padding: 10px var(--gutter) 22px;
  scrollbar-width: none;
}
.strip::-webkit-scrollbar { display: none; }
/* The screenshot inside the plate is absolutely positioned, so the figure has
   no intrinsic width; without an explicit one every phone collapses to its
   bezel. Seen in render review as five different-sized slivers. */
.strip-item { flex: none; width: clamp(158px, 15vw, 198px); scroll-snap-align: center; margin: 0; }
.phone--mini { --bezel: 5px; max-width: none; border-radius: 34px; }
.phone--mini::after { border-radius: 34px; }
.phone--mini .phone-screen { border-radius: 26px; clip-path: inset(0 round 26px); }
.strip-item figcaption {
  margin-top: 12px; text-align: center;
  font-size: 12.5px; font-weight: 600; color: var(--ink3);
  letter-spacing: .02em;
}

/* ── Steps strip: first, second, third, spelled out ────────── */
.steps {
  display: flex; align-items: center; justify-content: center;
  gap: clamp(10px, 2vw, 22px); flex-wrap: wrap;
  padding: 16px clamp(14px, 2.4vw, 28px);
  background: linear-gradient(180deg, var(--surface), color-mix(in srgb, var(--surface) 93%, var(--bg)));
  border: 1px solid var(--line-soft);
  border-radius: 999px;
  box-shadow: var(--shadow-card);
  width: fit-content; margin-inline: auto;
}
.step { display: inline-flex; align-items: center; gap: 10px; font-size: 14px; font-weight: 600; color: var(--ink2); }
.step b {
  display: inline-grid; place-items: center;
  width: 24px; height: 24px; border-radius: 50%;
  background: linear-gradient(135deg, var(--btn-a), var(--btn-b));
  color: var(--on-accent);
  font-size: 12px; font-weight: 700;
}
.step-arrow { color: var(--ink3); display: inline-flex; }
.step-arrow svg { width: 14px; height: 14px; }
@media (max-width: 720px) {
  .steps { flex-direction: column; align-items: flex-start; border-radius: var(--r-lg); gap: 10px; }
  .step-arrow { display: none; }
}

/* ── Care cards ────────────────────────────────────────────── */
.care-cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.card--row { display: flex; align-items: flex-start; gap: 14px; padding: 18px; }
.card--row .card-icon { margin-bottom: 0; flex: none; width: 40px; height: 40px; }
.card--row h3, .card--row h2 { font-size: 16.5px; margin-bottom: 3px; }
.card--row p { font-size: 13.5px; }
@media (max-width: 640px) { .care-cards { grid-template-columns: 1fr; } }

/* ── §04 Deliberate absences (No AI / No integrations) ─────── */
.notdo-cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
@media (max-width: 720px) { .notdo-cards { grid-template-columns: 1fr; } }

/* ── Demo journal replica (mirrors the real journal screen) ── */
.dj-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; flex: none; }
.dj-count {
  display: inline-flex; flex: none;
  background: var(--surface); border: 1px solid var(--line-soft);
  border-radius: 11px; box-shadow: var(--shadow-card);
  overflow: hidden;
}
.dj-count > span {
  display: grid; justify-items: center; gap: 0;
  padding: 5px 11px;
  line-height: 1.2;
}
.dj-count > span + span { border-left: 1px solid var(--line-soft); }
.dj-count b {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 14px; font-weight: 550; color: var(--accent-deep);
  font-variant-numeric: tabular-nums;
}
html[data-theme='dusk'] .dj-count b { color: var(--accent); }
.dj-count i { font-style: normal; font-size: 7.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--ink3); }
.dj-search { display: flex; gap: 7px; margin-top: 10px; flex: none; }
.dj-field {
  flex: 1; display: inline-flex; align-items: center; gap: 7px;
  min-height: 32px; padding: 0 12px;
  background: var(--surface-soft); border-radius: 999px;
  font-size: 11.5px; color: var(--ink3);
}
.dj-field svg { width: 13px; height: 13px; flex: none; }
.dj-filter {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 32px; padding: 0 12px;
  background: var(--surface); border: 1px solid var(--line-soft); border-radius: 999px;
  font-size: 11.5px; font-weight: 600; color: var(--ink2);
  box-shadow: var(--shadow-card);
}
.dj-filter svg { width: 13px; height: 13px; }
.dj-monthrow { display: flex; align-items: center; gap: 9px; margin-top: 12px; flex: none; }
.dj-monthrow em {
  font-family: 'Fraunces', Georgia, serif; font-style: italic;
  font-size: 13.5px; font-weight: 480; color: var(--ink);
}
.dj-monthrow i { flex: 1; height: 1px; background: var(--line-soft); }
.dj-monthrow b { font-size: 11px; font-weight: 600; color: var(--ink3); font-variant-numeric: tabular-nums; }
.d-icobubble {
  display: inline-grid; place-items: center; flex: none;
  width: 26px; height: 26px; border-radius: 50%;
  background: color-mix(in srgb, var(--c, var(--accent)) 14%, var(--surface));
}
.d-icobubble img { width: 15px; height: 15px; }
.d-entry-chip {
  padding: 3px 9px; border-radius: 999px;
  background: color-mix(in srgb, var(--c, var(--accent)) 13%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--c, var(--accent)) 24%, transparent);
  font-size: 9.5px; font-weight: 700;
  color: color-mix(in srgb, var(--c, var(--accent)) 46%, var(--ink));
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.d-kebab { margin-left: auto; color: var(--ink3); flex: none; }
.d-kebab svg { width: 14px; height: 14px; }
.d-entry-top { justify-content: flex-start; }
.d-entry-sev { margin-left: auto; }
.d-kebab { margin-left: 0; }
.d-entry-date { display: inline-flex; align-items: center; gap: 5px; }
.d-entry-date svg { width: 11px; height: 11px; }

/* ── Journal replica: segment row, filter squircles, bottom nav ── */
.dj-seg { display: flex; align-items: center; gap: 6px; margin-top: 10px; flex: none; }
.dj-pill {
  display: inline-flex; align-items: center;
  background: var(--surface-soft); border: 1px solid var(--line-soft);
  border-radius: 999px; padding: 2.5px;
  font-size: 10.5px; font-weight: 700;
}
.dj-pill b {
  padding: 4px 12px; border-radius: 999px;
  background: linear-gradient(135deg, var(--btn-a), var(--btn-b));
  color: var(--on-accent);
}
.dj-pill i { font-style: normal; padding: 4px 11px; color: var(--ink2); }
.dj-mini {
  display: inline-flex; align-items: center; justify-content: center; gap: 5px;
  min-width: 30px; min-height: 27px; padding: 0 8px;
  background: var(--surface); border: 1px solid var(--line-soft); border-radius: 10px;
  box-shadow: var(--shadow-card);
  font-size: 10.5px; font-weight: 600; color: var(--ink2);
}
.dj-mini svg { width: 12px; height: 12px; }
.dj-mini--wide { margin-left: auto; }
.dj-cats {
  display: flex; align-items: center; gap: 7px;
  margin-top: 11px; flex: none;
  overflow-x: auto; scrollbar-width: none; padding-bottom: 2px;
}
.dj-cats::-webkit-scrollbar { display: none; }
.dj-fcat {
  flex: none;
  position: relative;
  width: 34px; height: 34px; border-radius: 11px;
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--c, var(--accent)) 13%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--c, var(--accent)) 24%, transparent);
  cursor: pointer;
  transition: transform var(--t-quick) var(--ease-out), box-shadow var(--t-quick) var(--ease);
}
.dj-fcat:hover { transform: translateY(-1.5px); }
.dj-fcat.is-on { box-shadow: 0 0 0 2px color-mix(in srgb, var(--c, var(--accent)) 60%, transparent); }
.dj-fcat--all {
  width: auto; padding: 0 14px; border-radius: 999px;
  background: linear-gradient(135deg, var(--btn-a), var(--btn-b));
  border: 0; color: var(--on-accent);
  font-size: 11px; font-weight: 700;
}
.dj-fcat--all:not(.is-on) { filter: saturate(.4) opacity(.75); }
.dj-fcat img { width: 17px; height: 17px; }
.dj-empty { font-size: 11.5px; color: var(--ink3); padding: 10px 2px; }
.d-nav {
  flex: none;
  display: flex; align-items: center; justify-content: space-between;
  gap: 4px;
  margin: 10px -13px -13px;
  padding: 7px 16px 9px;
  background: var(--surface);
  border-top: 1px solid var(--line-soft);
}
.d-nav > span {
  display: grid; justify-items: center; gap: 3px;
  font-size: 7.5px; font-weight: 600; color: var(--ink3);
}
.d-nav > span svg { width: 16px; height: 16px; }
.d-nav > span.is-on { color: var(--accent-deep); }
html[data-theme='dusk'] .d-nav > span.is-on { color: var(--accent); }
.d-nav .d-fab {
  position: relative;
  width: 52px; height: 52px; border-radius: 50%;
  display: grid; place-items: center; align-self: center;
  background: linear-gradient(135deg, var(--btn-a), var(--btn-b));
  color: var(--on-accent);
  border: 2.5px solid var(--surface);
  box-shadow: 0 4px 14px var(--halo);
  cursor: pointer;
  animation: fab-beat 2.4s var(--ease) infinite;
  transition: transform var(--t-quick) var(--ease-out);
}
.d-nav .d-fab:active { transform: scale(.92); animation: none; }
.d-nav .d-fab svg { width: 22px; height: 22px; }
/* The invite ring: a soft pulse expanding off the tappable + (the hero demo's
   entry point was read as decoration — owner 2026-08-30). Buttons only; the
   static journal-mock plates use a span and stay quiet. */
.d-nav button.d-fab::after {
  content: ''; position: absolute; inset: -2.5px; border-radius: 50%;
  border: 2px solid var(--accent);
  animation: fab-ping 2.4s var(--ease) infinite;
  pointer-events: none;
}
@keyframes fab-beat {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.09); }
}
@keyframes fab-ping {
  0%, 30% { opacity: .5; transform: scale(1); }
  85%, 100% { opacity: 0; transform: scale(1.6); }
}
@media (prefers-reduced-motion: reduce) {
  .d-nav .d-fab { animation: none; }
  .d-nav button.d-fab::after { animation: none; opacity: 0; }
}

/* ── Appointment cards (built, as in the app) ──────────────── */
.appt-stack { display: grid; gap: 12px; max-width: 640px; margin-bottom: 8px; }
.appt-card {
  display: flex; align-items: center; gap: 16px;
  background: linear-gradient(180deg, var(--surface), color-mix(in srgb, var(--surface) 94%, var(--bg)));
  border: 1px solid var(--line-soft);
  border-left: 3px solid var(--accent);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-card);
  padding: 16px 18px;
}
.appt-card--past { border-left-color: var(--sev-mild); opacity: .92; }
.appt-date {
  flex: none; display: grid; justify-items: center;
  width: 52px; padding: 8px 0;
  background: color-mix(in srgb, var(--accent) 10%, var(--surface));
  border-radius: 12px;
}
.appt-date b {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 21px; font-weight: 500; line-height: 1; color: var(--accent-deep);
}
html[data-theme='dusk'] .appt-date b { color: var(--accent); }
.appt-date i { font-style: normal; font-size: 9.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--ink3); }
.appt-body { display: grid; gap: 3px; min-width: 0; }
.appt-body > b { font-family: 'Fraunces', Georgia, serif; font-size: 17px; font-weight: 480; letter-spacing: -.015em; }
.appt-body > span { font-size: 12.5px; color: var(--ink3); }
.appt-chips { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 4px; }
.appt-chip {
  display: inline-flex; align-items: center; gap: 4px;
  font-style: normal; font-size: 10.5px; font-weight: 700;
  padding: 3px 9px; border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 10%, var(--surface));
  color: var(--accent-deep);
  border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
}
html[data-theme='dusk'] .appt-chip { color: var(--accent); }
.appt-chip--done {
  background: color-mix(in srgb, var(--sev-mild) 12%, var(--surface));
  color: var(--sev-mild);
  border-color: color-mix(in srgb, var(--sev-mild) 30%, transparent);
}
.appt-chip svg { width: 9px; height: 9px; }
.appt-arrow { margin-left: auto; color: var(--ink3); flex: none; }
.appt-arrow svg { width: 16px; height: 16px; }

/* ── The GP export, as a document ──────────────────────────── */
.gpdoc-wrap { max-width: 620px; margin-inline: auto; }
.gpdoc {
  background: linear-gradient(180deg, var(--surface), color-mix(in srgb, var(--surface) 96%, var(--bg)));
  border: 1px solid var(--line-soft);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-lift);
  padding: clamp(24px, 3vw, 36px);
  position: relative;
}
.gpdoc::before {
  content: ''; position: absolute; inset: 0 0 auto 0; height: 4px;
  border-radius: var(--r-md) var(--r-md) 0 0;
  background: linear-gradient(90deg, var(--btn-a), var(--btn-b));
}
.gpdoc-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.gpdoc-brand { font-size: 10px; font-weight: 700; letter-spacing: .18em; color: var(--ink3); }
.gpdoc-kind {
  font-size: 10px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--accent-deep);
}
html[data-theme='dusk'] .gpdoc-kind { color: var(--accent); }
.gpdoc h3 {
  font-family: 'Fraunces', Georgia, serif;
  font-size: clamp(22px, 2.2vw, 28px); font-weight: 440; letter-spacing: -.02em;
  margin-top: 14px;
}
.gpdoc h3 em { font-style: italic; color: var(--accent-deep); }
html[data-theme='dusk'] .gpdoc h3 em { color: var(--accent); }
.gpdoc-meta { display: grid; gap: 6px; margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--line-soft); }
.gpdoc-meta span { font-size: 13.5px; color: var(--ink2); display: flex; gap: 12px; }
.gpdoc-meta i {
  font-style: normal; flex: none; width: 64px;
  font-size: 10px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink3); padding-top: 2px;
}
.gpdoc-sec { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line-soft); }
.gpdoc-sec h5 { font-size: 10.5px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--ink3); margin-bottom: 5px; }
.gpdoc-sec p { font-size: 14px; color: var(--ink2); }
.gpdoc-sec p b { color: var(--ink); font-weight: 600; }
.gpdoc-foot {
  margin-top: 20px; padding-top: 14px; border-top: 1px solid var(--line-soft);
  font-size: 11px; color: var(--ink3); letter-spacing: .04em;
}

/* ── Sitter's note: the guest note and the reply ───────────── */
.sitter {
  background: linear-gradient(180deg, var(--surface), color-mix(in srgb, var(--surface) 94%, var(--bg)));
  border: 1px solid var(--line-soft);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-card);
  padding: 18px 20px;
  margin-top: 18px;
}
.sitter-head { display: flex; align-items: center; gap: 12px; }
.sitter-ava {
  width: 36px; height: 36px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  background: color-mix(in srgb, #DB2777 12%, var(--surface));
  border: 1px solid color-mix(in srgb, #DB2777 24%, transparent);
}
.sitter-ava img { width: 18px; height: 18px; }
.sitter-who { display: grid; line-height: 1.3; }
.sitter-who b { font-family: 'Fraunces', Georgia, serif; font-size: 16.5px; font-weight: 480; letter-spacing: -.015em; }
.sitter-who i { font-style: normal; font-size: 12px; color: var(--ink3); }
.sitter-head .appt-chip { margin-left: auto; }
.sitter-msg {
  font-family: 'Fraunces', Georgia, serif; font-style: italic;
  font-size: 15px; line-height: 1.55; color: var(--ink2);
  margin-top: 12px;
}
.sitter-reply {
  display: flex; align-items: flex-start; gap: 11px;
  margin-top: 14px; padding: 12px 14px;
  background: color-mix(in srgb, var(--sev-mild) 7%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--sev-mild) 20%, transparent);
  border-radius: 12px;
}
.sitter-ava--r {
  width: 28px; height: 28px;
  background: color-mix(in srgb, var(--sev-mild) 16%, var(--surface));
  border-color: color-mix(in srgb, var(--sev-mild) 32%, transparent);
  color: var(--sev-mild); font-size: 12.5px; font-weight: 700;
}
.sitter-body { font-size: 13.5px; color: var(--ink2); line-height: 1.45; }
.sitter-body b { color: var(--ink); font-weight: 600; margin-right: 6px; }
.sitter-body i { font-style: normal; font-size: 11px; color: var(--ink3); }
.sitter-body > span { display: block; margin-top: 2px; }
.sitter-tick { margin-left: auto; flex: none; color: var(--sev-mild); }
.sitter-tick svg { width: 14px; height: 14px; }

/* Handover: the allergies-and-conditions card above the note */
.ho-allergy {
  margin-top: 12px;
  background: var(--surface);
  border: 1px solid color-mix(in srgb, var(--sev-severe) 30%, transparent);
  border-radius: 15px;
  box-shadow: var(--shadow-card);
  padding: 12px 13px;
}
.ho-alg-head {
  display: flex; align-items: center; gap: 7px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink2);
}
.ho-alg-head svg { width: 14px; height: 14px; color: var(--sev-severe); }
.ho-alg-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 9px; }
.ho-alg {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px; border-radius: 999px;
  background: color-mix(in srgb, var(--sv) 12%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--sv) 34%, transparent);
  font-size: 11.5px; font-weight: 700; color: var(--ink);
}
.ho-alg b { font-size: 9px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--sv); }
.ho-conds { margin-top: 9px; font-size: 11.5px; color: var(--ink2); }
.ho-conds i {
  display: block; font-style: normal;
  font-size: 9px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink3); margin-bottom: 2px;
}
.ho-conds b { color: var(--ink); font-weight: 600; }
.d-nav--ho { margin-top: auto; }
/* Scoped to .d-nav so it outranks the beat rule above: the plain class lost
   the cascade and every decorative + on the static plates pulsed too. */
.d-nav .d-fab--still { animation: none; }

/* The built Documents screen (filters live INSIDE the phone) */
.phone-screen.docs-screen { display: flex; flex-direction: column; padding: 8px 13px 13px; }
.phone-screen.docs-screen::after { display: none; }
.dx-add {
  flex: none; align-self: center;
  padding: 6px 13px; border-radius: 999px;
  background: linear-gradient(135deg, var(--btn-a), var(--btn-b));
  color: var(--on-accent);
  font-size: 11.5px; font-weight: 700;
}
.dx-pills { display: flex; gap: 5px; margin-top: 10px; background: var(--surface-soft); border-radius: 999px; padding: 3px; flex: none; }
.dx-pills .docsx-pill { flex: 1; }
.dx-list { display: flex; flex-direction: column; margin-top: 2px; overflow: hidden; min-height: 0; }
.docs-screen .docsx-row { padding: 9px 2px; }
.docs-screen .docsx-name b { font-size: 12.5px; }
.docs-screen .docsx-name i { font-size: 10.5px; }

/* Carousel's built screens (the interactive journal) */
.car-screen {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  padding: 8px 13px 13px;
  opacity: 0; pointer-events: none;
  visibility: hidden; /* out of the tab order + a11y tree while hidden */
  /* 200ms, the same as the screenshot plates: the built Journal used to fade
     for 700ms and ghost through the incoming screen after the turn. */
  transition: opacity 200ms var(--ease), visibility 0s 200ms;
}
.car-screen.is-active { opacity: 1; visibility: visible; transition-delay: 0s; pointer-events: auto; }

/* Documents category row */
.docsx-cats { margin: 2px 0 8px; }

/* ── Documents exhibit with working filters ────────────────── */
.docsx {
  background: linear-gradient(180deg, var(--surface), color-mix(in srgb, var(--surface) 94%, var(--bg)));
  border: 1px solid var(--line-soft);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-card);
  padding: 16px 18px;
}
.docsx-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.docsx-head > b { font-family: 'Fraunces', Georgia, serif; font-size: 17.5px; font-weight: 480; letter-spacing: -.015em; }
.docsx-pills { display: inline-flex; gap: 4px; background: var(--surface-soft); border-radius: 999px; padding: 3px; }
.docsx-pill {
  min-height: 28px; padding: 0 13px; border-radius: 999px;
  font-size: 12px; font-weight: 600; color: var(--ink2); cursor: pointer;
  transition: background var(--t-quick) var(--ease), color var(--t-quick) var(--ease);
}
.docsx-pill { position: relative; }
/* 28px pills, 44px to the thumb (invisible, like the journal chips). */
.docsx-pill::after { content: ''; position: absolute; inset: -8px 0; }
.docsx-pill.is-on {
  background: linear-gradient(135deg, var(--btn-a), var(--btn-b));
  color: var(--on-accent);
}
.docsx-row {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 2px;
  border-top: 1px solid var(--line-soft);
}
/* Same author-beats-UA trap as .d-entry: the exhibit filters set `hidden`. */
.docsx-row[hidden] { display: none; }
.docsx-ico {
  flex: none; width: 38px; height: 30px; border-radius: 8px;
  display: grid; place-items: center;
  font-size: 9px; font-weight: 700; letter-spacing: .08em;
  background: color-mix(in srgb, var(--accent) 12%, var(--surface));
  color: var(--accent-deep);
}
html[data-theme='dusk'] .docsx-ico { color: var(--accent); }
.docsx-ico--pdf { background: color-mix(in srgb, var(--sev-severe) 10%, var(--surface)); color: var(--sev-severe); }
.docsx-name { display: grid; line-height: 1.35; min-width: 0; }
.docsx-name b { font-size: 13.5px; font-weight: 600; }
.docsx-name i { font-style: normal; font-size: 11.5px; color: var(--ink3); }

/* ── The GP export: an actual page, letterhead and all ─────────
   A document is white with dark ink whatever mood the site wears. */
.gppdf {
  background: #FFFFFF;
  color: #14202A;
  border: 1px solid rgba(20, 32, 42, .12);
  border-radius: 6px;
  box-shadow: 0 2px 6px rgba(15, 27, 34, .10), 0 24px 60px rgba(15, 27, 34, .18);
  padding: clamp(26px, 3.4vw, 44px);
}
.gppdf-lh {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 14px;
  padding-bottom: 16px;
  border-bottom: 2px solid #14202A;
}
.gppdf-lh img { width: 118px; height: auto; }
.gppdf-kind {
  text-align: right;
  font-size: 10px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: #5A6E7C; line-height: 1.5;
}
.gppdf-patient {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px;
  padding: 14px 0;
  border-bottom: 1px solid rgba(20, 32, 42, .14);
}
.gppdf-patient span { display: grid; line-height: 1.4; }
.gppdf-patient i { font-style: normal; font-size: 9px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: #5A6E7C; }
.gppdf-patient b { font-size: 13px; font-weight: 600; }
.gppdf-sec { padding-top: 16px; }
.gppdf-sec h5 {
  font-size: 10px; font-weight: 700; letter-spacing: .15em; text-transform: uppercase;
  color: #5A6E7C; margin-bottom: 7px;
}
.gppdf-sec table { width: 100%; border-collapse: collapse; }
.gppdf-sec td {
  padding: 6px 10px 6px 0;
  font-size: 12.5px; color: #2A3B48;
  border-bottom: 1px solid rgba(20, 32, 42, .08);
  vertical-align: top;
}
.gppdf-sec tr td:first-child { font-weight: 600; color: #14202A; white-space: nowrap; }
.gppdf-sec p { font-size: 12.5px; color: #2A3B48; padding: 3px 0; }
.gppdf-foot {
  display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  margin-top: 22px; padding-top: 12px;
  border-top: 1px solid rgba(20, 32, 42, .14);
  font-size: 10px; color: #5A6E7C; letter-spacing: .03em;
}
@media (max-width: 640px) { .gppdf-patient { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* ── The GP export: the app's own report page, replicated ─────
   Fixed document palette from onboarding_gp_extract.dart / report_pdf.dart.
   A picture of a printed page: theme-independent on purpose. */
.gpx {
  background: #FFFFFF;
  color: #22201E;
  border: 1px solid #E6DDCF;
  border-radius: 8px;
  box-shadow: 0 1px 2px rgba(36, 32, 24, .05), 0 5px 10px rgba(36, 32, 24, .08),
              0 16px 28px rgba(36, 32, 24, .14);
  overflow: hidden;
}
.gpx-mast {
  background: #FCF9F4;
  border-bottom: 2px solid #4B3150;
  padding: 18px 22px 14px;
  display: grid; grid-template-columns: auto 1fr; gap: 4px 14px; align-items: center;
}
.gpx-mast img { width: 108px; height: auto; }
.gpx-kind {
  justify-self: end;
  font-size: 10px; font-weight: 700; letter-spacing: .18em; text-transform: uppercase;
  color: #4B3150;
}
.gpx-meta {
  grid-column: 1 / -1;
  display: flex; gap: 18px; flex-wrap: wrap;
  padding-top: 10px; margin-top: 6px;
  border-top: 1px solid #E6DDCF;
}
.gpx-meta span { display: grid; line-height: 1.35; }
.gpx-meta i { font-style: normal; font-size: 8.5px; font-weight: 700; letter-spacing: .13em; text-transform: uppercase; color: #5C544F; }
.gpx-meta b { font-size: 12px; font-weight: 600; color: #22201E; }
.gpx-body { padding: 16px 22px 14px; }
.gpx-glance {
  border: 1px solid #E6DDCF; border-radius: 8px;
  background: #FCF9F4;
  padding: 12px 14px;
}
.gpx-glance h3 {
  font-size: 9px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: #5C544F; margin-bottom: 8px;
}
.gpx-alert {
  display: flex; gap: 10px; align-items: baseline;
  background: #FBE7E3; color: #B1372B;
  border-left: 3px solid #C0392B;
  border-radius: 4px;
  padding: 7px 10px; margin-bottom: 7px;
  font-size: 12px; font-weight: 600;
}
.gpx-alert i, .gpx-row i {
  font-style: normal; flex: none; width: 74px;
  font-size: 8.5px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  padding-top: 2px;
}
.gpx-alert i { color: #B1372B; }
.gpx-row { display: flex; gap: 10px; align-items: baseline; padding: 4px 10px; font-size: 12px; color: #5C544F; }
.gpx-row i { color: #5C544F; }
.gpx-band {
  margin-top: 14px;
  background: #F2EBDF;
  border-radius: 5px;
  padding: 6px 12px;
  font-size: 9.5px; font-weight: 700; letter-spacing: .15em; text-transform: uppercase;
  color: #5C544F;
}
.gpx-entry { padding: 12px 4px 2px; border-bottom: 1px solid #E6DDCF; }
.gpx-entry:last-of-type { border-bottom: 0; }
.gpx-etop { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.gpx-etop > b { font-size: 12px; font-weight: 700; color: #22201E; font-variant-numeric: tabular-nums; }
.gpx-cat {
  font-size: 10.5px; font-weight: 700;
  padding: 3px 9px; border-radius: 999px;
  background: color-mix(in srgb, var(--c) 14%, #FFFFFF);
  color: var(--c);
  border: 1px solid color-mix(in srgb, var(--c) 32%, transparent);
}
.gpx-st {
  margin-left: auto;
  font-style: normal; font-size: 9.5px; font-weight: 700; letter-spacing: .05em;
  padding: 2.5px 9px; border-radius: 999px; border: 1.2px solid currentColor;
}
.gpx-st--ok { color: #1E8A4C; }
.gpx-st--same { color: #B07A1E; }
.gpx-entry > p { font-size: 12.5px; line-height: 1.55; color: #5C544F; margin-top: 6px; }
.gpx-update {
  margin: 8px 0 10px 16px; padding: 8px 12px;
  border-left: 2px solid #E6DDCF;
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
}
.gpx-update i {
  font-style: normal; font-size: 8.5px; font-weight: 700; letter-spacing: .13em;
  text-transform: uppercase; color: #5C544F;
}
.gpx-update .gpx-st { margin-left: 0; }
.gpx-update p { flex-basis: 100%; font-size: 12px; line-height: 1.5; color: #5C544F; }
.gpx-foot {
  display: flex; justify-content: space-between; gap: 10px; flex-wrap: wrap;
  margin-top: 14px; padding-top: 10px; border-top: 1px solid #E6DDCF;
  font-size: 9.5px; color: #5C544F; letter-spacing: .02em;
}

/* ── Comparison v3: zebra, column rules, group icon chips ──── */
table.compare tbody tr:not(.cmp-group):nth-child(even) { background: color-mix(in srgb, var(--ink) 2.5%, transparent); }
table.compare th + td, table.compare td + td { border-left: 1px solid var(--line-soft); }
table.compare thead th + th { border-left: 1px solid var(--line-soft); }
.cmp-gi {
  display: inline-grid; place-items: center; vertical-align: -7px;
  width: 24px; height: 24px; border-radius: 8px; margin-right: 9px;
  background: color-mix(in srgb, var(--accent) 12%, var(--surface));
  color: var(--accent-deep);
}
html[data-theme='dusk'] .cmp-gi { color: var(--accent); }
.cmp-gi svg { width: 13px; height: 13px; }
.vy { width: 24px; height: 24px; }
.vy svg { width: 12px; height: 12px; }

/* Carousel tab icons */
.ct-icon {
  width: 28px; height: 28px; border-radius: 9px; flex: none;
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--c, var(--accent)) 14%, var(--surface));
  color: color-mix(in srgb, var(--c, var(--accent)) 55%, var(--ink));
}
.ct-icon svg { width: 15px; height: 15px; }
.ct-icon img { width: 16px; height: 16px; }
.car-tab { display: inline-flex; align-items: center; gap: 10px; padding: 0 16px 0 8px; }
.car-tab.is-active .ct-icon { background: rgba(255, 255, 255, .22); color: var(--on-accent); }

.card-icon--img { background: color-mix(in srgb, var(--accent) 8%, var(--surface)); }
.card-icon--img img { width: 22px; height: 22px; }

/* ── Screens carousel ──────────────────────────────────────── */
.car {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: clamp(26px, 4vw, 56px);
  align-items: center;
}
.car-tabs { display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.car-tab {
  min-height: 42px; padding: 0 18px; border-radius: 999px;
  background: color-mix(in srgb, var(--surface) 60%, transparent);
  border: 1px solid var(--line);
  font-size: 14px; font-weight: 600; color: var(--ink2);
  cursor: pointer;
  transition: background var(--t-quick) var(--ease), color var(--t-quick) var(--ease),
              border-color var(--t-quick) var(--ease), transform var(--t-quick) var(--ease-out),
              box-shadow var(--t-quick) var(--ease);
}
.car-tab:hover { transform: translateX(3px); border-color: var(--ink3); color: var(--ink); }
.car-tab.is-active {
  background: linear-gradient(135deg, var(--btn-a), var(--btn-b));
  border-color: transparent;
  color: var(--on-accent);
  box-shadow: 0 6px 18px var(--halo);
}
/* pan-y: a sideways finger on the phone is a swipe between screens (app.js),
   an up-and-down one is still the page scrolling; pinch-zoom stays the
   browser's. */
.car-stage { perspective: 1700px; touch-action: pan-y pinch-zoom; }
/* The turn: 280ms out, the screen swaps at the edge, 280ms back (app.js
   unlocks at 560ms). It used to be 420ms each way with input unlocked
   halfway through the return, and an animated brightness filter on top. */
.car-stage .phone {
  transition: transform 280ms cubic-bezier(.45, 0, .2, 1);
}
.car-stage.is-turn .phone {
  transform: rotateY(72deg) translateX(-14px) scale(.93);
}
.car-caption { min-height: 1.4em; }
@media (max-width: 900px) {
  .car { grid-template-columns: 1fr; }
  /* Thumb zone: on a phone the tabs sit BELOW the screen, where the thumb
     already rests, so switching screens is repeated taps in place instead
     of a reach to the top (owner ruling 2026-08-18). The screen NAME reads
     ABOVE the phone (it is a label, not a control) and the phone itself is
     smaller so name + screen + tabs land in one view. */
  .car-stage { display: flex; flex-direction: column; }
  .car-stage .car-caption {
    order: -1; margin: 0 0 14px;
    font-family: 'Fraunces', Georgia, serif; font-style: italic;
    font-size: 17px; color: var(--ink);
  }
  .car-stage .phone { max-width: 250px; }
  /* Owner 2026-08-31: the features-page swipe phones read oversized beside the
     home carousel on a handset; both now share the 250px pocket size. */
  .swipe .phone--big { max-width: 250px; }
  .car-tabs {
    order: 2;
    flex-direction: row; overflow-x: auto; padding: 10px var(--gutter) 4px;
    /* Full-bleed: the strip runs to the physical screen edge so the clipped
       pill itself advertises that the row scrolls. */
    margin-inline: calc(var(--gutter) * -1);
    width: auto; align-self: stretch;
    scroll-padding-inline: var(--gutter);
    scrollbar-width: none; flex-wrap: nowrap;
  }
  .car-tabs::-webkit-scrollbar { display: none; }
  .car-tab { flex: none; }
  .car-stage .phone { max-width: 260px; }
}

/* ── Toggles: the active pill wears the theme gradient ─────── */
.toggles { display: flex; gap: 10px; flex-wrap: wrap; }
.price-toggle button[aria-pressed='true'] {
  background: linear-gradient(135deg, var(--btn-a), var(--btn-b));
  color: var(--on-accent);
  box-shadow: 0 4px 14px var(--halo);
}

/* ── Comparison header prices ──────────────────────────────── */
.th-price {
  display: block;
  font-family: 'Instrument Sans', system-ui, sans-serif;
  font-style: normal; font-size: 11px; font-weight: 600;
  letter-spacing: .01em; color: var(--ink3);
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}
/* The yearly line sits directly under the monthly price, one register down. */
.th-price--yr { margin-top: 0; font-weight: 500; opacity: .78; }

/* ── Small strips (features chapters) ──────────────────────── */
.strip--sm { justify-content: center; }
.strip--sm .strip-item { width: clamp(140px, 13.5vw, 172px); }
@media (max-width: 720px) { .strip--sm { justify-content: flex-start; } }

/* ── Swipe carousels: one big phone, swipe or arrow between screens ── */
.swipe-wrap {
  position: relative;
  display: grid; grid-template-columns: 44px minmax(0, 1fr) 44px;
  align-items: center; gap: 6px;
  max-width: 520px; margin-inline: auto;
}
.swipe-wrap--single { grid-template-columns: minmax(0, 1fr); max-width: 420px; }
.swipe {
  display: flex;
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  border-radius: 46px;
}
.swipe::-webkit-scrollbar { display: none; }
.swipe-slide {
  flex: none; width: 100%;
  scroll-snap-align: center; scroll-snap-stop: always;
  display: grid; justify-items: center; gap: 14px;
  /* Rows size to content: without this, a shorter screenshot slide stretches
     its phone frame to the tallest slide in the row and the leftover paints
     as a dark bezel slab under the screen. */
  align-content: start;
  padding: 6px 4px 2px;
}
.swipe-slide figcaption, .swipe-slide .plate-caption {
  font-size: 13px; font-weight: 600; color: var(--ink3); text-align: center; margin: 0;
}
.swipe-btn {
  width: 44px; height: 44px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--surface); border: 1px solid var(--line);
  color: var(--ink2); cursor: pointer;
  box-shadow: var(--shadow-card);
  transition: transform var(--t-quick) var(--ease-out), border-color var(--t-quick) var(--ease), color var(--t-quick) var(--ease);
}
.swipe-btn:hover { transform: scale(1.06); border-color: var(--ink3); color: var(--ink); }
.swipe-btn svg { width: 17px; height: 17px; }
.swipe-dots { grid-column: 1 / -1; display: flex; justify-content: center; padding-top: 4px; }
/* Dots are BUTTONS with a finger-sized padded hit area; only the content
   box paints, so the visual stays a quiet 8px dot. */
.swipe-dot {
  box-sizing: content-box;
  width: 8px; height: 8px; padding: 18px; border-radius: 50%;
  background: var(--line);
  background-clip: content-box;
  transition: background var(--t-quick) var(--ease), transform var(--t-quick) var(--ease-out);
}
.swipe-dot.is-on { background: var(--accent); background-clip: content-box; transform: scale(1.12); }
.swipe-dot:active { transform: scale(.9); }
@media (max-width: 640px) {
  .swipe-wrap { grid-template-columns: minmax(0, 1fr); }
  .swipe-btn { display: none; }
}

/* ── Handover note screen (replicated from the app) ────────── */
.phone-screen.ho { display: flex; flex-direction: column; padding: 40px 12px 12px; }
.phone-screen.ho::after { display: none; }
.ho-manage {
  display: flex; align-items: center; gap: 6px;
  margin: 0 -12px; padding: 8px 16px;
  background: color-mix(in srgb, var(--accent) 9%, var(--surface-soft));
  font-size: 12px; font-weight: 600; color: var(--accent-deep);
}
html[data-theme='dusk'] .ho-manage { color: var(--accent); }
.ho-manage svg { width: 13px; height: 13px; margin-left: auto; }
.ho-card {
  margin-top: 12px;
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: 15px;
  box-shadow: var(--shadow-card);
  padding: 13px 14px;
}
.ho-head { display: flex; align-items: center; gap: 9px; }
.ho-ico {
  width: 30px; height: 30px; border-radius: 9px; flex: none;
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--accent) 11%, var(--surface));
  color: var(--accent-deep);
}
html[data-theme='dusk'] .ho-ico { color: var(--accent); }
.ho-ico svg { width: 15px; height: 15px; }
.ho-head b { font-size: 11px; font-weight: 700; letter-spacing: .13em; text-transform: uppercase; color: var(--ink2); }
.ho-edit {
  margin-left: auto;
  display: inline-flex; align-items: center; gap: 5px;
  min-height: 30px; padding: 0 13px; border-radius: 999px;
  background: linear-gradient(135deg, var(--btn-a), var(--btn-b));
  color: var(--on-accent);
  font-size: 11.5px; font-weight: 700;
}
.ho-edit svg { width: 11px; height: 11px; }
.ho-for {
  display: flex; align-items: center; gap: 7px;
  margin-top: 11px; padding: 8px 12px;
  background: var(--surface-soft); border-radius: 11px;
  font-size: 12px; color: var(--ink2);
}
.ho-for svg { width: 13px; height: 13px; }
.ho-for b { color: var(--ink); font-weight: 700; }
.ho-text { font-size: 14px; line-height: 1.5; color: var(--ink); margin-top: 11px; }
.ho-meta {
  display: flex; align-items: center; gap: 6px;
  margin-top: 11px; padding-top: 10px;
  border-top: 1px solid var(--line-soft);
  color: var(--ink3);
}
.ho-meta svg { width: 12px; height: 12px; }
.ho-meta i { font-family: 'Fraunces', Georgia, serif; font-style: italic; font-size: 11.5px; }
.ho-reply {
  margin: 10px 0 0 6px; padding: 10px 12px;
  background: var(--surface);
  border-left: 3px solid var(--accent);
  border-radius: 4px 12px 12px 4px;
  box-shadow: var(--shadow-card);
  display: grid; gap: 3px;
}
.ho-reply b { font-size: 13px; font-weight: 600; }
.ho-reply > span { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; color: var(--ink3); }
.ho-reply svg { width: 11px; height: 11px; }
.ho-add {
  margin-top: 10px; padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: 12px;
  display: flex; align-items: center; gap: 8px;
  font-size: 12.5px; font-weight: 600; color: var(--ink2);
}
.ho-add svg { width: 13px; height: 13px; }
.ho-add .ho-chev { margin-left: auto; }

/* ── Reveal. Visible unless JS says otherwise: a failed observer
      can never blank the page. boot.js sets html.js. ─────────── */
html.js [data-reveal] {
  opacity: 0;
  transform: translateY(18px) scale(.992);
  transition: opacity 700ms var(--ease-out) var(--rd, 0ms),
              transform 700ms var(--ease-out) var(--rd, 0ms);
}
html.js [data-reveal].is-in { opacity: 1; transform: none; }

/* ── Motion layer v2 (2026-08-25) — richer entrances, ambient life.
      Everything transform/opacity-only; the global reduced-motion
      block below kills all of it with !important durations. ────── */

/* The section rule draws itself in as the head arrives. */
html.js .sec-rule[data-reveal] { position: relative; border-top-color: transparent; }
html.js .sec-rule[data-reveal]::after {
  content: ''; position: absolute; top: -1px; left: 0; right: 0; height: 1px;
  background: var(--line);
  transform: scaleX(0); transform-origin: left center;
  transition: transform 480ms var(--ease) calc(var(--rd, 0ms) + 120ms);
}
html.js .band .sec-rule[data-reveal]::after { background: var(--band-line); }
html.js .sec-rule[data-reveal].is-in::after { transform: scaleX(1); }

/* The three steps walk in one after the other. */
html.js .steps[data-reveal] > * {
  opacity: 0; transform: translateX(-10px);
  transition: opacity 460ms var(--ease-out), transform 460ms var(--ease-out);
}
html.js .steps[data-reveal] > :nth-child(2) { transition-delay: 90ms; }
html.js .steps[data-reveal] > :nth-child(3) { transition-delay: 180ms; }
html.js .steps[data-reveal] > :nth-child(4) { transition-delay: 270ms; }
html.js .steps[data-reveal] > :nth-child(5) { transition-delay: 360ms; }
html.js .steps[data-reveal].is-in > * { opacity: 1; transform: none; }

/* The hero phone breathes — ambient layer, desktop only. */
@media (min-width: 981px) {
  .hero .demo-wrap .phone { animation: hero-float 7s ease-in-out infinite alternate; }
}
@keyframes hero-float {
  from { transform: translateY(0); }
  to { transform: translateY(-7px); }
}

/* Carousel screenshots arrive with a settle, not just a fade. The fade must
   COMPLETE inside the 280ms return of the phone turn, or the outgoing screen
   ghosts through the incoming one once the phone faces forward again. */
.phone-screen > img[data-screen] {
  transform: translateX(10px);
  visibility: hidden; /* keeps eight hidden screens out of the a11y tree */
  transition: opacity 200ms var(--ease), transform 200ms var(--ease-out),
              visibility 0s 200ms;
}
.phone-screen > img[data-screen].is-active,
.phone-screen > img[data-screen]:only-child { transform: none; visibility: visible; transition-delay: 0s; }

/* The primary action blooms its halo on approach. */
.btn--primary:hover {
  box-shadow: 0 2px 5px rgba(0, 0, 0, .14), 0 16px 38px var(--halo);
}

/* Demo category tiles answer the finger. */
.d-cat:active { transform: scale(.96); }

/* The two declarations: each icon pops in, then its cross strikes through.
   The second card's --rd (90ms) staggers the sequence card by card. The
   stroke starts at 420ms, while the icon is still settling (it lands at
   640ms), so the two read as one gesture; the thud that used to follow is
   gone and the whole thing now reads in under a second. */
html.js .notdo-cards .card-icon {
  opacity: 0; transform: scale(.6) rotate(-8deg);
  transition: opacity 420ms var(--ease-out) calc(var(--rd, 0ms) + 160ms),
              transform 480ms var(--ease-out) calc(var(--rd, 0ms) + 160ms);
}
html.js .notdo-cards [data-reveal].is-in .card-icon { opacity: 1; transform: none; }
html.js .notdo-cards .notdo-slash { stroke-dasharray: 22; stroke-dashoffset: 22; }
html.js .notdo-cards [data-reveal].is-in .notdo-slash {
  animation: slash-draw 420ms cubic-bezier(.3, 0, .2, 1)
      calc(var(--rd, 0ms) + 420ms) forwards;
}
@keyframes slash-draw { to { stroke-dashoffset: 0; } }

/* The deep bands carry a slow drift of lamplight. The light is larger than
   the band and the band clips it: at inset 0 the drift slid the light's own
   edge into view, a pale rectangle on every band (Codex 2026-09-26). */
.band { overflow: hidden; overflow: clip; }
.band::after {
  content: ''; position: absolute; inset: -64px; pointer-events: none;
  background: radial-gradient(900px 480px at 16% 112%, var(--band-glow), transparent 62%);
  animation: band-drift 14s ease-in-out infinite alternate;
}
.band > .wrap { position: relative; z-index: 1; }
@keyframes band-drift {
  from { transform: translate3d(0, 12px, 0); opacity: .5; }
  to { transform: translate3d(46px, -14px, 0); opacity: .95; }
}

/* ── Motion layer v3 (2026-08-26) — hero choreography + button physics.
      The reduced-motion block below still kills all of it. ─────── */

/* Hero headline: the two lines rise out of their own clips. The clip gets
   descender room (padding pulled back by the margin) so italic tails are
   never cut by overflow:hidden. */
.hl .hl-clip { display: block; overflow: hidden; padding-bottom: .14em; margin-bottom: -.14em; }
html.js .hl[data-reveal] { transform: none; }
html.js .hl[data-reveal] .hl-line {
  display: block;
  transform: translateY(112%);
  transition: transform 820ms var(--ease-out) var(--rd, 0ms);
}
html.js .hl[data-reveal] .hl-clip:nth-child(2) .hl-line {
  transition-delay: calc(var(--rd, 0ms) + 110ms);
}
html.js .hl[data-reveal].is-in .hl-line { transform: none; }
/* Phones: the headline carries the entrance on its own. Everything else in
   the hero (icon, eyebrow, lede, badges, note, the demo phone) is simply
   there, so the one-liner and the store links can be read at once and nothing
   competes with the two rising lines, which arrive faster (480ms, 80ms apart)
   because a phone visitor is already reading. */
@media (max-width: 980px) {
  html.js .hero [data-reveal]:not(.hl),
  html.js .hero .hl[data-reveal] { opacity: 1; transform: none; transition: none; }
  html.js .hero [data-reveal] .store-badge { opacity: 1; transform: none; transition: scale 90ms var(--ease-out); }
  /* The walk-in's second-badge delay list would otherwise land on the one
     transition left here and hold the Google Play press back by 330ms. */
  html.js .hero [data-reveal] .store-badge:nth-child(2) { transition-delay: 0ms; }
  html.js .hero .hero-appicon[data-reveal].is-in { animation: none; }
  html.js .hero .hl[data-reveal] .hl-line { transition-duration: 480ms; transition-delay: 0ms; }
  html.js .hero .hl[data-reveal] .hl-clip:nth-child(2) .hl-line { transition-delay: 80ms; }
}

/* The app icon settles with a soft pop instead of a plain rise. */
html.js .hero-appicon[data-reveal] {
  transform: none;
  transition: opacity 520ms var(--ease) var(--rd, 0ms);
}
html.js .hero-appicon[data-reveal].is-in {
  animation: rv-pop 520ms var(--ease-out) var(--rd, 0ms) both;
}
@keyframes rv-pop {
  0% { transform: scale(.82); }
  62% { transform: scale(1.035); }
  100% { transform: scale(1); }
}

/* Store badges walk in one after the other, wherever they appear. */
html.js [data-reveal] .store-badge {
  opacity: 0; transform: translateY(12px);
  transition: opacity 480ms var(--ease-out) var(--rd, 0ms),
              transform 480ms var(--ease-out) var(--rd, 0ms),
              scale 90ms var(--ease-out) 0ms;
}
html.js [data-reveal] .store-badge:nth-child(2) {
  transition-delay: calc(var(--rd, 0ms) + 90ms), calc(var(--rd, 0ms) + 90ms), 0ms;
}
html.js [data-reveal].is-in .store-badge { opacity: 1; transform: none; }

/* Button physics the site was missing. The press lives on `scale`, its own
   property: the walk-in above owns `transform` on every revealed badge and
   used to swallow the press, so the launch page's main action never answered
   the finger. */
.store-badge:active { scale: .97; }
.car-tab {
  transition: color var(--t-quick) var(--ease), background var(--t-quick) var(--ease),
              border-color var(--t-quick) var(--ease),
              box-shadow var(--t-quick) var(--ease), transform var(--t-quick) var(--ease-out);
}
.car-tab:hover { transform: translateY(-1px); }
.car-tab:active { transform: scale(.96); }
.mood-card:active { transform: translateY(-1px) scale(.985); }

/* The compose screen assembles: severity pills cascade, the paper follows. */
.demo .d-compose.is-active .d-sev button { animation: chip-in 360ms var(--ease-out) both; }
.demo .d-compose.is-active .d-sev button:nth-child(2) { animation-delay: 60ms; }
.demo .d-compose.is-active .d-sev button:nth-child(3) { animation-delay: 120ms; }
.demo .d-compose.is-active .d-paper { animation: chip-in 420ms var(--ease-out) 90ms both; }
@keyframes chip-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}

/* Section headings arrive a beat faster than the rest of the page. The blur
   they used to sharpen out of is gone: an animated filter on large serif text
   is the one effect that drops frames on a mid-range phone, and it kept the
   heading unreadable for most of a second on every section. */
html.js .sec-head .display[data-reveal] {
  transition: opacity 480ms var(--ease-out) var(--rd, 0ms),
              transform 480ms var(--ease-out) var(--rd, 0ms);
}

/* Band tiles' icons pop in after their tile lands. */
html.js .band-tile[data-reveal] .bt-icon svg {
  opacity: 0; transform: scale(.5);
  transition: opacity 380ms var(--ease) calc(var(--rd, 0ms) + 140ms),
              transform 460ms var(--ease-out) calc(var(--rd, 0ms) + 140ms);
}
html.js .band-tile[data-reveal].is-in .bt-icon svg { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  html.js [data-reveal] { opacity: 1; transform: none; transition: none; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    /* Delays too: a reduced-motion reader used to get the staggers (menu
       links 60 to 300ms, the 3s reveal fallback) as delayed snaps. */
    animation-delay: 0s !important;
    transition-delay: 0s !important;
  }
}

/* Support contact cards: the address is the only thing to tap in a big card;
   give it a 44px-tall band, the address's own width, without moving the text. */
.support-email { position: relative; }
.support-email::after { content: ''; position: absolute; inset-inline: 0; top: 50%; height: 44px; transform: translateY(-50%); }

/* ── Creator kit (press/) — organized, downloadable app screens ── */
.kit-all {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  margin-top: 26px;
}
.kit-all-meta { font-size: 13.5px; color: var(--ink3); }
.kit-group { margin-top: 44px; }
.kit-group h2 {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 23px; font-weight: 470; letter-spacing: -.015em;
  margin-bottom: 4px;
}
.kit-group > p { color: var(--ink2); font-size: 15px; margin-bottom: 18px; }
.kit {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px;
}
.kit-card { padding: 14px 14px 16px; text-align: left; }
.kit-shot {
  border-radius: 12px; overflow: hidden;
  border: 1px solid var(--line-soft);
  background: var(--surface-soft);
  aspect-ratio: 750 / 980;
}
/* The film frames take the film's own shape (720x1280 portrait recordings),
   so object-fit: cover fills them without cutting the top and bottom of the
   screen; the still frames keep the 750 / 980 crop above. Specificity beats
   the 760px override below, so this holds at every width. */
.kit-shot:has(video) { aspect-ratio: 720 / 1280; }
.kit-shot img { width: 100%; height: 100%; object-fit: cover; object-position: top center; display: block;
  transition: transform 600ms var(--ease); }
.kit-card:hover .kit-shot img { transform: scale(1.025); }
.kit-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-top: 12px;
}
.kit-name { font-size: 14px; font-weight: 600; color: var(--ink); }
.kit-name i { display: block; font-style: normal; font-weight: 500; font-size: 12px; color: var(--ink3); margin-top: 1px; }
.kit-dl {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 44px; padding: 0 16px;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--accent) 32%, transparent);
  color: var(--accent-deep);
  font-size: 13px; font-weight: 600;
  text-decoration: none; white-space: nowrap;
  transition: background var(--t-quick) var(--ease), color var(--t-quick) var(--ease),
              transform var(--t-quick) var(--ease-out), box-shadow var(--t-quick) var(--ease);
}
.kit-dl svg { width: 14px; height: 14px; }
.kit-dl:hover {
  background: linear-gradient(135deg, var(--btn-a), var(--btn-b));
  color: var(--on-accent); border-color: transparent;
  box-shadow: 0 8px 22px var(--halo);
  transform: translateY(-1px);
}
.kit-dl:active { transform: scale(.97); }
html[data-theme='dusk'] .kit-dl { color: var(--accent); }
html[data-theme='dusk'] .kit-dl:hover { color: var(--on-accent); }
@media (max-width: 760px) {
  .kit { grid-template-columns: 1fr; }
  .kit-shot { aspect-ratio: 750 / 760; }
}

/* ── Self-heal: reveals must never depend on app.js arriving ──
      boot.js sets html.js (hiding every reveal); app.js sets js-live.
      If app.js is lost (flaky network, mid-deploy 404), everything
      un-hides itself at 3s. With app.js alive, js-live is present and
      none of this applies — scroll reveals keep their entrances. */
html.js:not(.js-live) [data-reveal],
html.js:not(.js-live) .hl[data-reveal] .hl-line,
html.js:not(.js-live) .steps[data-reveal] > *,
html.js:not(.js-live) [data-reveal] .store-badge,
html.js:not(.js-live) .band-tile[data-reveal] .bt-icon svg,
html.js:not(.js-live) .notdo-cards .card-icon {
  animation: rv-fallback 1ms linear 3s forwards;
}
html.js:not(.js-live) .sec-rule[data-reveal]::after { animation: rv-fallback-rule 1ms linear 3s forwards; }
html.js:not(.js-live) .notdo-cards .notdo-slash { animation: rv-fallback-slash 1ms linear 3s forwards; }
@keyframes rv-fallback { to { opacity: 1; transform: none; filter: none; } }
@keyframes rv-fallback-rule { to { transform: scaleX(1); } }
@keyframes rv-fallback-slash { to { stroke-dashoffset: 0; } }

/* ── Document callouts (delete-account) — classes the page already
      uses but the stylesheet never defined. ─────────────────── */
.danger {
  border: 1px solid color-mix(in srgb, var(--sev-severe) 38%, transparent);
  background: color-mix(in srgb, var(--sev-severe) 7%, var(--surface));
  border-radius: var(--r-md);
  padding: 16px 18px;
  margin-block: 18px;
}
/* a.email-btn + the .prose-scoped repeat: the legal pages' `.prose a` link
   rule (accent ink + underline) was out-specifying the pill and painting the
   label accent-on-accent — invisible in Dusk (owner catch 2026-08-30). */
.prose a.email-btn,
html[data-theme='dusk'] .prose a.email-btn { color: var(--on-accent); text-decoration: none; }
a.email-btn {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 46px; padding: 0 22px;
  border-radius: 999px;
  background: linear-gradient(135deg, var(--btn-a), var(--btn-b));
  color: var(--on-accent);
  font-size: 15px; font-weight: 600;
  text-decoration: none;
  box-shadow: 0 10px 26px var(--halo);
  transition: transform var(--t-quick) var(--ease-out), filter var(--t-quick) var(--ease);
}
a.email-btn:hover { filter: brightness(1.06); }
a.email-btn:active { transform: scale(.97); }
ol.doc-steps { margin: 14px 0 18px; padding-left: 22px; display: grid; gap: 8px; }

/* ── Responsive ────────────────────────────────────────────── */
@media (max-width: 1080px) {
  .plans, .tease { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .plan-flag { left: 24px; transform: none; }
}
@media (max-width: 980px) {
  .hero-grid { grid-template-columns: 1fr; gap: 40px; }
  /* Phone-first: identity before the demo. An ad click should read the name
     and the one-liner in the first screen, then meet the working demo —
     so the copy keeps its DOM-order lead and the phone follows, larger. */
  .hero .phone { max-width: 310px; }
  .hero-phone .phone { transform: none; }
  .hero-glow { right: -30%; top: -6%; width: 90vw; }
  .spread, .show { grid-template-columns: 1fr; }
  .spread .phone, .show .phone { max-width: 300px; }
  /* The handover replica is built from fixed-size parts: at this 300px phone
     the ratio-derived screen (610px) was 44px short of its content (654px)
     and the bottom nav was cut in half. Let the built screen size to what is
     on it. Desktop keeps the ratio (there the content fills it to the pixel). */
  .phone--tallish .phone-screen.ho { aspect-ratio: auto; }
  .cards--3, .band-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ledger-row { grid-template-columns: 40px minmax(0, 1fr); }
  .ledger-desc { grid-column: 2; margin-top: 6px; }
  .footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .show-desc p { padding-left: 55px; }
}
@media (max-width: 640px) {
  body { font-size: 16px; }
  .cards--3, .cards--2, .band-tiles, .plans, .tease { grid-template-columns: 1fr; }
  /* Theme cards share one row on phones (owner-approved item 13): the plans
     section arrives a full screen sooner; tap behaviour identical. */
  .mood-cards { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
  .mood-card { min-height: 140px; }
  /* The cards bottom-align their text, so a shorter description left its
     name below the others (Tide sat 22px low at 390px). Every card reserves
     the same number of description lines, stepped by width from the measured
     wraps (1.6em per line): two lines to 640px, three from 470px down, four
     from 352px down. Plain CSS in every browser; the look is unchanged. */
  .mood-card .mc-line { min-height: 3.2em; }
  .footer-grid { grid-template-columns: 1fr; }
  .footer-social { margin-left: 0; }
  .store-badge { flex: 1 1 100%; justify-content: center; }
  .plan-flag { left: 20px; }
  /* Stacked, the flag hangs above its own card and lands on the card above. */
  .plan--featured { margin-top: 14px; }
  .show-desc p { padding-left: 4px; }
}
@media (max-width: 470px) { .mood-card .mc-line { min-height: 4.8em; } }
@media (max-width: 352px) { .mood-card .mc-line { min-height: 6.4em; } }

/* ═══════════════════════════════════════════════════════════════════
   SOCIAL PAGE — ported 2026-09-02 from the retired site.css so /social/
   shares this sheet, this nav and this footer with every other page.
   Same tokens, same reveal system, same hover and press feel.
   ═══════════════════════════════════════════════════════════════════ */
.follow-row {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(12px, 1.6vw, 20px);
}
.follow-card {
  display: flex; align-items: center; gap: 16px;
  padding: 20px 22px; text-decoration: none;
}
.follow-card .fc-icon {
  width: 46px; height: 46px; border-radius: var(--r-md); flex: none;
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--accent) 11%, var(--surface));
  color: var(--accent-deep);
  transition: transform var(--t-quick) var(--ease-out);
}
html[data-theme='dusk'] .follow-card .fc-icon { color: var(--accent); }
.follow-card:hover .fc-icon { transform: translateY(-2px); }
.follow-card .fc-icon svg { width: 21px; height: 21px; }
.follow-card .fc-name { display: block; font-weight: 650; font-size: 15.5px; letter-spacing: -.01em; }
.follow-card .fc-handle { font-size: 13px; color: var(--ink3); }
@media (max-width: 720px) { .follow-row { grid-template-columns: 1fr; } }

.feed-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 20px; flex-wrap: wrap; margin-bottom: clamp(22px, 3vw, 34px);
}
.feed-count { font-size: 12px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--ink3); }

.feed-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
  gap: clamp(14px, 1.8vw, 22px);
}
.feed-card {
  position: relative; display: block; width: 100%; padding: 0; text-align: left;
  background: var(--surface); border: 1px solid var(--line-soft);
  border-radius: var(--r-xl); overflow: clip;
  box-shadow: var(--shadow-card);
  transition: transform var(--t-std) var(--ease-out), box-shadow var(--t-std) var(--ease-out);
}
.feed-card:hover { transform: translateY(-5px); box-shadow: var(--shadow-lift); }
.feed-card:active { transform: translateY(-2px) scale(.99); }
.feed-media {
  position: relative; aspect-ratio: 4 / 5; overflow: hidden;
  background: var(--surface-soft);
}
.feed-media img, .feed-media video {
  width: 100%; height: 100%; object-fit: cover; object-position: center top;
  transition: transform 900ms var(--ease);
}
.feed-card:hover .feed-media img { transform: scale(1.045); }
.feed-badge {
  position: absolute; top: 14px; left: 14px; z-index: 5;
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 10px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  background: rgba(12, 16, 20, .55); color: #FFF;
  padding: 6px 11px; border-radius: 999px;
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
.feed-badge svg { width: 11px; height: 11px; }
.feed-caption { padding: 16px 18px 18px; }
.feed-caption p {
  font-family: 'Fraunces', Georgia, serif; font-style: italic;
  font-size: 14.5px; color: var(--ink); line-height: 1.5;
}
.feed-caption time {
  display: block; margin-top: 7px;
  font-size: 11.5px; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink3);
}
.feed-dots {
  position: absolute; bottom: 12px; left: 50%; transform: translateX(-50%);
  display: flex; gap: 5px; z-index: 5;
}
.feed-dots i {
  width: 5px; height: 5px; border-radius: 50%;
  background: rgba(255, 255, 255, .5);
  transition: background var(--t-quick) var(--ease), transform var(--t-quick) var(--ease-out);
}
.feed-dots i.on { background: #FFF; transform: scale(1.25); }

.feed-empty {
  border: 1.5px dashed var(--line); border-radius: var(--r-xl);
  padding: clamp(50px, 8vh, 90px) 30px; text-align: center;
}
.feed-empty .fe-mark { width: 74px; margin: 0 auto 22px; opacity: .9; }
.feed-empty h3 {
  font-family: 'Fraunces', Georgia, serif; font-style: italic; font-weight: 400;
  font-size: 22px; margin-bottom: 8px;
}
.feed-empty p { color: var(--ink2); font-size: 14.5px; max-width: 380px; margin: 0 auto; }

/* Lightbox: modal weight, so a 450ms settle with no overshoot. */
.lightbox {
  position: fixed; inset: 0; z-index: 400; display: none;
  align-items: center; justify-content: center;
  padding: clamp(16px, 4vw, 60px);
  background: rgba(10, 12, 16, .82);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
}
.lightbox.is-open { display: flex; }
.lightbox-inner {
  position: relative; max-width: min(920px, 94vw); max-height: 88svh;
  display: flex; flex-direction: column;
  animation: lb-in 450ms var(--ease-out) both;
}
@keyframes lb-in {
  from { opacity: 0; transform: translateY(22px) scale(.985); }
  to   { opacity: 1; transform: none; }
}
.lightbox-stage {
  border-radius: var(--r-lg); overflow: hidden; background: #000;
  max-height: 76svh; display: flex; align-items: center; justify-content: center;
}
.lightbox-stage img, .lightbox-stage video {
  max-width: 100%; max-height: 76svh; width: auto; height: auto; object-fit: contain;
}
.lightbox-caption {
  margin-top: 14px; color: rgba(255, 255, 255, .85);
  font-family: 'Fraunces', Georgia, serif; font-style: italic;
  font-size: 15px; text-align: center;
}
.lightbox-close {
  position: absolute; top: -50px; right: 0;
  width: 44px; height: 44px; border-radius: 50%;
  display: grid; place-items: center;
  color: #FFF; opacity: .85; background: rgba(255, 255, 255, .1);
  transition: opacity var(--t-quick) var(--ease), transform var(--t-quick) var(--ease-out);
}
.lightbox-close:hover { opacity: 1; transform: scale(1.06); }
.lightbox-nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 44px; height: 44px; border-radius: 50%;
  background: rgba(255, 255, 255, .12); color: #FFF;
  display: grid; place-items: center;
  transition: background var(--t-quick) var(--ease), transform var(--t-quick) var(--ease-out);
}
.lightbox-nav:hover { background: rgba(255, 255, 255, .22); transform: translateY(-50%) scale(1.06); }
.lightbox-nav.prev { left: -58px; }
.lightbox-nav.next { right: -58px; }
.lightbox-nav svg { width: 18px; height: 18px; }
.lightbox :focus-visible { outline: 2px solid #FFF; outline-offset: 3px; }
@media (max-width: 1080px) {
  .lightbox-nav.prev { left: 8px; }
  .lightbox-nav.next { right: 8px; }
}
@media (prefers-reduced-motion: reduce) {
  .lightbox-inner { animation: none; }
  .feed-card, .feed-media img, .follow-card .fc-icon { transition: none; }
}

/* ── Hero demo: Meds / More / real app screens (owner 2026-09-24) ── */
.d-nav > .d-navbtn {
  display: grid; justify-items: center; gap: 3px;
  font: inherit; font-size: 7.5px; font-weight: 600; color: var(--ink3);
  background: none; border: 0; padding: 0; cursor: pointer;
  position: relative;
}
.d-nav > .d-navbtn::after { content: ''; position: absolute; inset: -8px -6px; }
.d-nav > .d-navbtn svg { width: 16px; height: 16px; }
.d-nav > .d-navbtn:hover { color: var(--accent-deep); }
.demo .d-shot, .demo .d-more { padding: 0; }
/* The real More screen fills the phone; its tap zones sit over the tiles in
   percentages of the image, so they line up at any phone width. */
.d-realscreen { position: relative; flex: 1; overflow: hidden; }
.d-realscreen img { display: block; width: 100%; height: auto; }
.d-hot {
  position: absolute; z-index: 1;
  background: transparent; border: 0; padding: 0;
  border-radius: 12px; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.d-hot:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.d-hot:active { background: color-mix(in srgb, var(--accent) 16%, transparent); transition: background 60ms; }
.d-hot--nav { border-radius: 14px; }
/* The screen a More tile opens is one full screen, no scrolling. A plain,
   visible Back button sits in the status-bar band, clear of the notch. */
.d-backpill {
  position: absolute; z-index: 4; left: 10px; top: 7px;
  display: inline-flex; align-items: center; gap: 3px;
  padding: 5px 11px 5px 6px; border-radius: 999px;
  background: var(--ink); color: var(--bg);
  border: 0; cursor: pointer;
  font: inherit; font-size: 10.5px; font-weight: 600;
  box-shadow: 0 4px 12px rgba(0, 0, 0, .18);
}
.d-backpill::after { content: ''; position: absolute; inset: -8px -6px; }
.d-backpill svg { width: 13px; height: 13px; }
.d-backpill:active { transform: scale(.95); }

/* ── Guided tour (html.tour, set by app.js; ?tour=1 while a mockup) ── */
.demo .is-coached {
  z-index: 2;
  outline: 2.5px solid var(--accent); outline-offset: 2px;
  animation: coach-glow 1.5s var(--ease) infinite;
}
/* Lift an in-flow target above its neighbours; the absolute tap zones over
   the real More screen must keep their own positioning. */
.demo .is-coached:not(.d-hot):not(.d-backpill) { position: relative; }
@keyframes coach-glow {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 55%, transparent); }
  70%  { box-shadow: 0 0 0 12px color-mix(in srgb, var(--accent) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 0%, transparent); }
}
/* The other tiles step back while one is being pointed at. */
.demo .d-grid .d-cat { transition: transform var(--t-quick) var(--ease-out), box-shadow var(--t-quick) var(--ease), opacity .3s var(--ease), filter .3s var(--ease); }
/* Step the other tiles back evenly: fading alone leaves the saturated ones
   (Men's blue, Women's pink) loud while the pastel ones vanish. */
.demo.is-coaching .d-grid .d-cat:not(.is-coached) { opacity: .55; filter: saturate(.3); }
.d-coach {
  position: absolute; z-index: 5;
  max-width: 78%;
  padding: 8px 12px;
  border-radius: 12px;
  background: var(--ink); color: var(--bg);
  font-size: 11.5px; font-weight: 500; line-height: 1.35;
  box-shadow: 0 8px 22px rgba(0, 0, 0, .22);
  pointer-events: none;
  /* Invisible until app.js has measured and placed it (.is-shown), so it
     never shows the next line in the last step's spot and then jumps. */
  opacity: 0; transform: translateY(5px);
  transition: opacity .24s var(--ease), transform .28s var(--ease-out);
}
.d-coach.is-shown { opacity: 1; transform: none; animation: coach-bob 2.4s var(--ease) .6s infinite; }
.d-coach b { font-weight: 700; }
.d-coach::after {
  content: ''; position: absolute; left: var(--ax, 50%); bottom: -5px;
  width: 10px; height: 10px; margin-left: -5px;
  background: inherit; transform: rotate(45deg); border-radius: 2px;
}
.d-coach.is-below::after { bottom: auto; top: -5px; }
.d-coach[hidden] { display: none; }
@keyframes coach-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes coach-bob { 0%, 100% { translate: 0 0; } 50% { translate: 0 -3px; } }
.d-finale {
  position: absolute; inset: 0; z-index: 6;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 10px; padding: 28px 22px; text-align: center;
  background: color-mix(in srgb, var(--bg) 94%, transparent);
  backdrop-filter: blur(6px);
  animation: coach-in .45s var(--ease-out) both;
}
.d-finale[hidden] { display: none; }
.d-finale img { width: 54px; height: 54px; border-radius: 14px; box-shadow: 0 8px 22px var(--halo); }
.d-finale .d-title { font-size: 24px; }
.d-finale-sub { font-size: 12px; line-height: 1.45; color: var(--ink2); margin-bottom: 6px; }
.d-finale-btn {
  display: block; width: 100%;
  padding: 11px 14px; border-radius: 999px;
  background: linear-gradient(135deg, var(--btn-a), var(--btn-b));
  color: var(--on-accent); text-decoration: none;
  font-size: 12.5px; font-weight: 600;
  box-shadow: 0 6px 18px var(--halo);
}
.d-finale-btn--alt { background: var(--surface); color: var(--ink); border: 1px solid var(--line-soft); box-shadow: none; }
.d-finale-more {
  margin-top: 4px; background: none; border: 0; cursor: pointer;
  font: inherit; font-size: 11.5px; color: var(--ink3); text-decoration: underline;
}

/* Tour on a phone: the demo comes up into the first screen, right under
   the headline, instead of below the whole hero. The analytics showed
   most visitors never scroll far enough to meet it (2026-09-24). */
@media (max-width: 980px) {
  html.tour .hero-grid { row-gap: 0; }
  html.tour .hero-grid > div:first-child { display: contents; }
  html.tour .hero .hero-appicon { display: none; }
  html.tour .hero .eyebrow { order: 1; }
  html.tour .hero h1 { order: 2; margin-top: 6px; }
  html.tour .hero .demo-wrap { order: 3; margin-top: 18px; }
  html.tour .hero .lede { order: 4; margin-top: 26px; }
  html.tour .hero-grid > div:first-child > div { order: 5; }
  html.tour .hero .cta-note { order: 6; }
  html.tour .hero .phone { max-width: 272px; }
}
@media (prefers-reduced-motion: reduce) {
  .demo .is-coached, .d-coach, .d-coach.is-shown, .d-finale { animation: none; }
}

/* ── Launch offer banner (js/offer.js, owner 2026-09-25) ── */
.offer {
  position: relative; z-index: 210;
  background: linear-gradient(120deg, #13232E, #1F3A4B 55%, #2D5670);
  color: #F4F7F9;
  padding: max(12px, env(safe-area-inset-top)) max(var(--gutter), env(safe-area-inset-right)) 12px max(var(--gutter), env(safe-area-inset-left));
}
.offer[hidden] { display: none; }
/* The nav below keeps its own safe-area padding for when it sticks; while the
   offer sits above it, the notch is already cleared. */
html.has-offer .nav { padding-top: 12px; }
.offer-in {
  max-width: 1180px; margin-inline: auto;
  display: grid; grid-template-columns: auto auto auto; align-items: center;
  justify-content: space-between; gap: 6px 22px;
}
.offer-head { font-size: 15px; line-height: 1.3; margin: 0; }
.offer-head b { font-family: 'Fraunces', Georgia, serif; font-weight: 600; font-size: 18px; letter-spacing: -.01em; }
.offer-head span { color: #F2C98A; font-weight: 600; white-space: nowrap; }
.offer-count { display: block; margin-top: 2px; font-size: 13px; color: #DDE7EE !important; font-weight: 500 !important; }
.offer.is-scarce .offer-count { color: #F6B37A !important; font-weight: 700 !important; }
.offer-btn[aria-busy="true"] { opacity: .75; animation: none; }
.offer.is-closed .offer-in { grid-template-columns: 1fr; justify-items: center; text-align: center; }
.offer-clock { display: flex; align-items: center; gap: 6px; }
.offer-ends { font-size: 11px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; opacity: .8; margin-right: 2px; }
.oc {
  display: grid; justify-items: center; min-width: 44px;
  padding: 5px 6px 4px; border-radius: 9px;
  background: rgba(255, 255, 255, .1); border: 1px solid rgba(255, 255, 255, .14);
}
.oc b { font-size: 19px; font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.1; }
.oc i { font-style: normal; font-size: 9px; letter-spacing: .08em; text-transform: uppercase; opacity: .7; }
.offer.is-last-day .oc { background: rgba(232, 150, 80, .22); border-color: rgba(242, 201, 138, .5); }
.offer-cta { display: flex; gap: 8px; }
.offer-btn {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 11px 18px; border-radius: 999px;
  background: #F2C98A; color: #1B2A33; text-decoration: none;
  font-size: 14px; font-weight: 700; white-space: nowrap;
  box-shadow: 0 6px 18px rgba(242, 201, 138, .28);
  animation: offer-pulse 2.6s var(--ease) infinite;
}
.offer-btn + .offer-btn { background: rgba(255, 255, 255, .12); color: #F4F7F9; box-shadow: none; animation: none; }
.offer-btn:active { transform: scale(.97); }
@keyframes offer-pulse {
  0%, 100% { box-shadow: 0 6px 18px rgba(242, 201, 138, .28); }
  50% { box-shadow: 0 6px 26px rgba(242, 201, 138, .6); }
}
/* Turnstile's box, shown only if Cloudflare wants a tick. */
.offer-ts { grid-column: 1 / -1; display: flex; justify-content: center; }
.offer-ts:empty { display: none; }
.offer-fine { grid-column: 1 / -1; margin: 0; font-size: 11px; opacity: .7; text-align: center; }
@media (max-width: 980px) {
  .offer-in { grid-template-columns: 1fr; justify-items: center; text-align: center; gap: 9px; }
  .offer-head b { display: block; font-size: 20px; }
  .offer-cta { width: 100%; }
  .offer-btn { flex: 1; }
}
@media (prefers-reduced-motion: reduce) { .offer-btn { animation: none; } }
