/* ── Site-only layout + typography ────────────────────────────────
   The component CSS (.gtg-hero, .pocket-card, .tx-card, .badge, etc.)
   is loaded from _app-styles.css — auto-synced from web/styles.css. We
   rely on that for visual parity with the real app, and only override
   page-level layout, typography, and site-specific sections here.
*/

:root {
  /* Site-only tokens. Brand colors come from the synced app sheet
     (--accent / --green / --red / etc.). These add a soft warm pop and
     a couple of motion curves we use for the bouncy feel. */
  --gold:        #f6c860;
  --gold-soft:   rgba(246, 200, 96, 0.14);
  --accent-glow: rgba(124, 111, 247, 0.28);
  --max-w:       1120px;

  /* Serif headlines = literary / inviting / Hitchhiker-y. The app
     stays sans, so this scope is intentional: site only. */
  --font-serif:  'Iowan Old Style', 'Palatino Linotype', 'Book Antiqua', Palatino, 'PT Serif', Georgia, serif;

  --ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-soft:   cubic-bezier(0.22, 1, 0.36, 1);
}

/* Subtle vertical wash. One gradient stretched the full body height,
   no-repeat — using `background-size: 100% 100%` and `background-repeat:
   no-repeat` keeps it a single continuous fade with no harsh seam. */
body {
  background-color: var(--bg);
  background-image: linear-gradient(180deg,
    rgba(124, 111, 247, 0.12) 0%,
    rgba(124, 111, 247, 0.04) 35%,
    transparent 100%);
  background-repeat: no-repeat;
  background-size: 100% 100%;
  line-height: 1.65;
  min-height: 100vh;
  /* Belt + suspenders against horizontal scroll on mobile: any element
     wider than 100vw shouldn't reveal a scrollbar. The actual culprits
     (decorative glows, off-screen carets) all stay inside the viewport
     thanks to overflow:clip on body, and overflow-x:hidden on html for
     older browsers that don't support `clip`. */
  overflow-x: clip;
}
html { overflow-x: hidden; }
em { font-style: italic; color: var(--accent); }

/* The app sheet has a global `a:hover { text-decoration: underline }` —
   that's the right behavior in-app (auth links, category-rename, etc.)
   but on the site page we want zero underlines anywhere. Override
   for both states so nav links, footer links, anchors, and CTAs stay
   clean. The cursor change already signals "clickable." */
a, a:hover { text-decoration: none; }

/* The app sheet sets `.page { display:none }` — there is no .page in
   site so it's harmless. Same for #app-header / #bottom-nav. */

/* ── Top nav ─────────────────────────────────────────────────────── */
.top-nav {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 28px;
  padding: 16px 28px;
  background: rgba(15, 15, 19, 0.72);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
}
.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
  color: var(--text);
  text-decoration: none;
  transition: opacity 0.18s var(--ease-soft);
}
.brand:hover { opacity: 0.85; }
/* The actual app's .logo-text rule comes from _app-styles.css. We don't
   touch font-family / font-weight / colors here so the wordmark stays
   identical to the app (system sans, weight 800, "by Hoopy" purple). */
.top-nav .logo-text { font-size: 22px; }

.nav-links {
  display: flex;
  gap: 30px;
  flex: 1;
  justify-content: center;
}
.nav-links a {
  color: var(--muted);
  font-size: 14px;
  font-weight: 500;
  padding: 6px 4px;
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.18s var(--ease-soft);
}
.nav-links a:hover { color: var(--text); }

.nav-cta { display: flex; gap: 10px; flex-shrink: 0; }
.nav-cta a { white-space: nowrap; }

/* "Play with Demo" nav entries — link-styled <button>s that launch the demo
   directly. Gold so the try-it action stands out among the section links. */
.nav-demo {
  background: none;
  border: 0;
  cursor: pointer;
  font-family: inherit;
  color: var(--gold);
  font-weight: 600;
  white-space: nowrap;
  transition: color 0.18s var(--ease-soft);
}
.nav-links .nav-demo { font-size: 14px; padding: 6px 4px; }
.nav-links .nav-demo:hover { color: #e9b53a; }

/* Discord entries — purple (the site's other brand color) so the community
   link reads as its own thing without competing with the gold demo CTA. */
.nav-links .nav-discord { color: var(--accent); font-weight: 600; }
.nav-links .nav-discord:hover { color: #fff; }

.nav-burger {
  display: none;
  background: transparent;
  border: 0;
  width: 40px;
  height: 40px;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  padding: 0;
}
.nav-burger span {
  display: block;
  width: 22px;
  height: 2px;
  background: var(--text);
  border-radius: 1px;
  transition: transform 0.22s var(--ease-bounce), opacity 0.2s;
}
.nav-burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav-burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

.nav-drawer {
  display: none;
  position: fixed;
  top: 64px;
  left: 0;
  right: 0;
  z-index: 49;
  flex-direction: column;
  padding: 18px 28px;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
  gap: 4px;
}
.nav-drawer a {
  padding: 14px 4px;
  font-size: 16px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
  color: var(--text);
  text-decoration: none;
}
.nav-drawer a:last-child { border-bottom: 0; }
.nav-drawer .nav-demo {
  display: block;
  width: 100%;
  text-align: left;
  padding: 14px 4px;
  font-size: 16px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
}
.nav-drawer .drawer-discord { color: var(--accent); font-weight: 600; }
.nav-drawer .drawer-signin { color: var(--muted); margin-top: 8px; }
.nav-drawer .drawer-signup { color: var(--gold); font-weight: 600; }
.nav-drawer.open { display: flex; }

/* ── Buttons (bouncy, but no tilt) ───────────────────────────────── */
/* These override the app's .btn-primary base with site variants —
   pill shape, lift on hover, no rotation. */
.btn-primary, .btn-ghost {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 11px 20px;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  border: 1px solid transparent;
  white-space: nowrap;
  text-decoration: none;
  width: auto;
  transition:
    background 0.2s var(--ease-soft),
    border-color 0.2s var(--ease-soft),
    color 0.2s var(--ease-soft),
    transform 0.25s var(--ease-bounce),
    box-shadow 0.25s var(--ease-soft);
}
/* Gold CTA — the complement of the site's purple, so the primary action
   pops off the page (drives the eye to it). Dark ink for contrast on gold. */
.btn-primary {
  background: var(--gold);
  color: #1c1730;
  box-shadow: 0 4px 14px rgba(246, 200, 96, 0.30);
}
/* :not(:disabled) matches the synced app sheet's specificity
   (.btn-primary:hover:not(:disabled) → purple --accent-dim); without it the
   app rule outranks this one and the gold button reverts to purple on hover /
   click. Same specificity + loaded later = the gold wins. */
.btn-primary:hover:not(:disabled) {
  /* Deeper gold on hover + a stronger gold glow — matches the gold fill
     instead of the old purple hover/glow. */
  background: #e9b53a;
  box-shadow: 0 8px 24px rgba(246, 200, 96, 0.50);
}
/* Solid purple secondary — gold owns the primary CTA, so the secondary is a
   filled purple button (the site's other brand color) rather than an outline.
   Gold + purple side by side reads as a deliberate pair. */
.btn-ghost {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
  box-shadow: 0 4px 14px rgba(173, 161, 255, 0.30);   /* glow matches --accent */
}
.btn-ghost:hover {
  /* --accent-dim is the app's button-press purple (picked deliberately there);
     match it here so the pressed/hover shade is identical across app + site. */
  background: var(--accent-dim);
  border-color: var(--accent-dim);
  color: #fff;
  box-shadow: 0 8px 22px rgba(124, 113, 201, 0.42);   /* glow matches --accent-dim */
}
.btn-lg { padding: 15px 28px; font-size: 16px; }

/* Kill the mechanism, not the symptom. The app stylesheet (_app-styles.css,
   synced from web/styles.css) has a global `button:active { transform:
   scale(0.97) }`. On a mouse it fires on mousedown and, because `transform`
   is a single property, it REPLACES any centering transform — so a button
   centered with `translate(-50%)` snaps sideways out from under the cursor and
   the click never lands. We used to paper over it per-button (the removed
   `.btn-*:active { transform: translateY(1px) }` rules); instead neutralize the
   global here. Buttons that need positioning now use the standalone `translate`
   property (see .pq-arrow / .demo-play / .demo-exit), which this doesn't touch. */
button:active { transform: none; }

/* The app's standard "?" help icon (.info-q in _app-styles.css) is written for
   a <span role="button">, so it never has to undo native button chrome. The
   site's hero "?" stays a real <button> for keyboard operability, which means
   knocking out the app sheet's generic `button` background + weight here. The
   circle, size, muted color, and hover all still come from .info-q, so the
   site icon tracks any future change to the app's standard automatically. */
button.info-q {
  appearance: none;
  -webkit-appearance: none;
  background: none;
  font-weight: 400;
}

/* ── Sections ────────────────────────────────────────────────────── */
main { max-width: var(--max-w); margin: 0 auto; padding: 0 28px; }
.section { padding: 110px 0; }
.section-inner { max-width: 880px; margin: 0 auto; }
.section-eyebrow {
  display: inline-block;
  text-transform: uppercase;
  letter-spacing: 2px;
  font-size: 12px;
  font-weight: 700;
  color: var(--accent);
  margin-bottom: 18px;
}
.section-h {
  font-family: var(--font-serif);
  font-size: clamp(30px, 4.4vw, 46px);
  font-weight: 700;
  letter-spacing: -0.8px;
  line-height: 1.15;
  margin-bottom: 18px;
  color: var(--text);
}
.section-h em { color: var(--accent); font-style: italic; }
/* Mobile: smaller section headlines so longer ones (e.g. "…Let's fix that in
   three steps.") stay tidy and fit in fewer lines. Every .section-h uses this
   one rule — no per-section overrides — so they all match. Desktop keeps the
   larger size above. */
@media (max-width: 640px) {
  .section-h { font-size: clamp(22px, 6vw, 30px); }
}
.section-lede {
  font-size: 18px;
  color: var(--muted);
  max-width: 640px;
  margin-bottom: 56px;
  line-height: 1.6;
}
.section-lede em { color: var(--text); font-style: italic; }
.section-tail {
  font-size: 17px;
  color: var(--muted);
  max-width: 640px;
  margin-top: 40px;
  line-height: 1.7;
}
.section-tail em { color: var(--text); font-style: italic; }

/* ── Hero ──────────────────────────────────────────────────────────
   Three items inside .hero-inner: text-top, hero-preview, text-bottom.
   Desktop uses grid-template-areas to put text on the left (top + bot
   stacked) and the preview on the right spanning both rows. Mobile
   collapses to a single column with the preview between the two text
   blocks — CTA lands directly below what it's referring to. */
.hero { padding: 80px 0 110px; }
.hero-inner {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  grid-template-rows: auto 1fr;
  grid-template-areas:
    "top    preview"
    "bottom preview";
  gap: 0 64px;
  align-items: start;
}
.hero-text-top    { grid-area: top; }
.hero-preview     { grid-area: preview; align-self: center; justify-self: stretch; }
.hero-text-bottom { grid-area: bottom; padding-top: 28px; }
.hero-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 1.5px;
  color: var(--gold);
  text-transform: uppercase;
  padding: 6px 14px;
  background: var(--gold-soft);
  border: 1px solid rgba(246, 200, 96, 0.3);
  border-radius: 999px;
  margin-bottom: 22px;
  transform: rotate(-1.5deg);
  animation: gentleBob 4s var(--ease-soft) infinite;
}
@keyframes gentleBob {
  0%, 100% { transform: rotate(-1.5deg) translateY(0); }
  50%      { transform: rotate(-1deg) translateY(-3px); }
}
.hero-eyebrow .dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--gold);
  box-shadow: 0 0 10px var(--gold);
}

.hero-text-top h1 {
  font-family: var(--font-serif);
  font-size: clamp(44px, 6.4vw, 72px);
  font-weight: 700;
  letter-spacing: -2px;
  line-height: 1.02;
  margin-bottom: 24px;
  color: var(--text);
}
.hero-text-top h1 em { color: var(--accent); font-style: italic; }
.hero-sub {
  font-size: 19px;
  color: var(--muted);
  max-width: 520px;
  line-height: 1.6;
}
.hero-sub em { color: var(--text); font-style: italic; }
.hero-cta {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}
/* Really skinny screens: once the Get started / Learn more pair can no longer
   sit side by side, stack them and let each fill the full width (bigger tap
   targets, cleaner than two centered pills). Only kicks in this narrow — wider
   screens keep them side by side at natural width. */
@media (max-width: 380px) {
  .hero-cta { flex-direction: column; align-items: stretch; }
  .hero-cta .btn-lg { width: 100%; }
}
.hero-fineprint {
  font-size: 13px;
  color: var(--muted);
  opacity: 0.8;
  max-width: 480px;
}

/* Hero preview — bare GTG hero, identical to the running app. The
   .gtg-hero element pulls every visual rule from the synced app
   stylesheet, so we don't override anything here. */
.hero-preview { position: relative; }

/* ── Why ─────────────────────────────────────────────────────────── */
.why-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}
.why-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 26px 24px 22px;
  transition: border-color 0.2s var(--ease-soft), box-shadow 0.32s var(--ease-soft);
}
.why-card:hover {
  border-color: var(--accent);
  box-shadow: 0 12px 28px rgba(124, 111, 247, 0.12);
}
.why-x {
  width: 38px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(248, 113, 113, 0.1);
  border-radius: 12px;
  color: var(--red);
  font-size: 18px;
  font-weight: 700;
  margin-bottom: 16px;
}
.why-card h3 {
  font-family: var(--font-serif);
  font-size: 19px;
  font-weight: 700;
  margin-bottom: 8px;
  color: var(--text);
}
.why-card p { font-size: 14px; color: var(--muted); line-height: 1.6; }

/* ── How ─────────────────────────────────────────────────────────── */
.how-formula {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 32px 28px;
  margin-bottom: 56px;
  font-variant-numeric: tabular-nums;
}
.formula-piece {
  flex: 1;
  min-width: 140px;
  text-align: center;
}
.formula-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 1.5px;
  color: var(--muted);
  opacity: 0.8;
  margin-bottom: 8px;
}
.formula-val { font-size: 26px; font-weight: 700; color: var(--text); }
.formula-val.gtg-green { color: var(--green); }
.formula-op {
  font-size: 28px;
  color: var(--muted);
  opacity: 0.7;
  font-weight: 300;
  flex-shrink: 0;
}

/* The three steps are <button> elements now — clicking one swaps the
   visible .step-panel below. Reset the browser's default button look
   so they read like cards, then add an .active state that signals the
   selected step (purple border + soft fill). */
.how-steps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}
.how-step {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 18px 20px;
  font-family: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  width: 100%;
  /* Number + title on a single row, vertically centered. */
  display: flex;
  align-items: center;
  gap: 12px;
  transition: border-color 0.2s var(--ease-soft), background 0.2s var(--ease-soft);
}
.how-step:hover { border-color: var(--accent); }
.how-step.active {
  border-color: var(--accent);
  background: rgba(124, 111, 247, 0.08);
  box-shadow: 0 0 0 1px var(--accent);
}
.step-num {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  background: var(--accent);
  color: #fff;
  border-radius: 50%;
  font-weight: 700;
  font-size: 13px;
  box-shadow: 0 4px 12px rgba(124, 111, 247, 0.35);
}
.how-step h3 {
  font-family: var(--font-serif);
  font-size: 17px;
  font-weight: 700;
  margin: 0;
  color: var(--text);
  line-height: 1.2;
}

/* Step panels — only the matching one is visible. Grid-stack so the
   stage sizes to the tallest panel and switching has zero layout shift. */
.step-stage {
  display: grid;
  grid-template-columns: 1fr;
  margin-top: 36px;
  position: relative;
}
.step-panel {
  grid-column: 1;
  grid-row: 1;
  display: flex;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  visibility: hidden;
  transform: translateY(8px);
  transition: opacity 0.4s var(--ease-soft), transform 0.4s var(--ease-bounce);
}
.step-panel.active {
  opacity: 1;
  pointer-events: auto;
  visibility: visible;
  transform: translateY(0);
}
/* phone-sm — locked to a phone-shaped ratio so all step screenshots
   are exactly the same height + width regardless of content. The
   screen is overflow:hidden so longer content gets clipped at the
   bottom (acceptable: the visible top is the part that demos best). */
.phone-sm { width: 320px; }
.phone-sm .phone-screen { height: 600px; min-height: 0; overflow: hidden; }

/* Step panel layout — text on the left, phone on the right (desktop).
   Stacks on mobile: text first, phone below (since the user is reading
   downward, the explanation sets up the visual). Top-aligned so the
   step heading sits flush with the top of the phone screenshot —
   centering looked floaty when the detail copy was shorter than the
   phone. */
.step-panel-inner {
  display: grid;
  grid-template-columns: 1fr 320px;
  gap: 48px;
  align-items: start;
  max-width: 880px;
  margin: 0 auto;
}
.step-detail h3 {
  font-family: var(--font-serif);
  font-size: clamp(22px, 2.6vw, 30px);
  font-weight: 700;
  letter-spacing: -0.5px;
  color: var(--text);
  margin-bottom: 14px;
}
.step-detail p {
  font-size: 16px;
  color: var(--muted);
  line-height: 1.65;
  margin-bottom: 14px;
  max-width: 460px;
}
.step-detail p:last-child { margin-bottom: 0; }
.step-detail em { color: var(--text); font-style: italic; }
@media (max-width: 880px) {
  .step-panel-inner {
    grid-template-columns: 1fr;
    gap: 28px;
    justify-items: center;
  }
  .step-detail { text-align: center; }
  .step-detail p { margin-left: auto; margin-right: auto; }
  /* Phone is the second item in DOM, so on mobile it lands below the
     text — text reads first, screenshot reinforces. */
}

/* Funding Schedule mock — the markup mirrors the live #pc-modal-overlay
   in web/index.html. The .fh-row, .fh-info, .fh-date, .fh-trigger,
   .fh-amount classes come from the synced app sheet. The only
   site-only addition is the wrapper that frames the history block
   with a label, which the live modal renders via _renderCardCollapse
   (a JS helper) — we substitute static markup for the demo. */
.fs-history-block {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}
.fs-history-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 1.5px;
  color: var(--muted);
  font-weight: 700;
  margin-bottom: 8px;
}
.fs-history-chev {
  font-size: 14px;
  letter-spacing: 0;
  font-weight: 400;
  opacity: 0.7;
}
/* Tighten the freq-settings-bubble + buttons inside the narrow phone-sm
   so 320px reads cleanly. The freq picker normally lives in a 520px
   modal; in a 288px content area we shrink chrome but keep the visual. */
.phone-sm .freq-settings-bubble {
  font-size: 12px;
  padding: 8px 10px;
  gap: 5px;
  min-height: 0;
}
.phone-sm .freq-num-btn,
.phone-sm .freq-day-chip {
  font-size: 12px;
  padding: 3px 8px;
  min-width: 0;
}
.phone-sm .field-label { font-size: 11px; }
.phone-sm .modal-header h2 { font-size: 16px; }
.phone-sm .input-group { gap: 10px; }
.phone-sm .modal-header { padding-bottom: 6px; margin-bottom: 8px; }

/* Pocket badges row — mirrors the new app rule so the site preview
   stays in sync. The synced app sheet now defines this same selector;
   keeping it in site-only as a defensive fallback in case the sync
   script lags behind. */
.pocket-badges {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 4px;
  margin-top: 4px;
}

/* ── What ────────────────────────────────────────────────────────── */
.what-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}
.what-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 24px 22px;
  transition: border-color 0.2s var(--ease-soft);
}
.what-card:hover { border-color: var(--accent); }
.what-card h3 {
  font-family: var(--font-serif);
  font-size: 17px;
  font-weight: 700;
  margin-bottom: 8px;
  color: var(--text);
}
.what-card p { font-size: 14px; color: var(--muted); line-height: 1.6; }

/* ── Pull-quote slider ────────────────────────────────────────────────
   Auto-rotates; pauses on hover/swipe. Desktop: tall skinny < / >
   chevrons positioned near the section edges (no circles). Mobile:
   carets hidden, swipe gesture takes over. Two purple quote marks
   frame the slide: open mark top-left, close mark bottom-right of
   the frame, vertically centered around the quote. Slides translate
   horizontally on change (direction-aware via inline style in JS). */
.pull-quote-slider {
  position: relative;
  max-width: var(--max-w);
  margin: 0 auto;
  padding: 90px 80px 80px;
}
.pq-frame {
  position: relative;
  max-width: 720px;
  margin: 0 auto;
  min-height: 220px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  text-align: center;
}
.pq-mark {
  position: absolute;
  font-family: var(--font-serif);
  font-size: 96px;
  line-height: 0.8;
  color: var(--accent);
  opacity: 0.45;
  pointer-events: none;
  user-select: none;
}
.pq-mark-open  { top: -36px; left: -10px; }
.pq-mark-close { bottom: -50px; right: -10px; }

/* Grid-stack the slides so switching is a pure crossfade with no
   layout shift. Slides translate horizontally on change — direction
   is set inline by the slider JS (forward = exit left, enter from
   right; backward = mirror). */
.pull-quote-stage {
  display: grid;
  grid-template-columns: 1fr;
  overflow: hidden;
}
.pq-slide {
  grid-column: 1;
  grid-row: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  opacity: 0;
  transform: translateX(100%);
  transition: opacity 0.45s var(--ease-soft), transform 0.55s var(--ease-bounce);
  pointer-events: none;
  visibility: hidden;
  padding: 0 16px;
}
.pq-slide.active {
  opacity: 1;
  transform: translateX(0);
  pointer-events: auto;
  visibility: visible;
}
.pq-slide p {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: clamp(20px, 2.4vw, 28px);
  color: var(--text);
  line-height: 1.4;
  max-width: 640px;
}
.pq-slide cite {
  font-size: 13px;
  color: var(--muted);
  font-style: normal;
  letter-spacing: 0.5px;
}

/* Carets — tall skinny chevrons, no chrome. Positioned near the
   section edges (capped by the section's max-width container). */
.pq-arrow {
  position: absolute;
  top: 50%;
  /* Center vertically with the standalone `translate` property, NOT `transform`,
     so the app sheet's global `button:active { transform: scale(...) }` can't
     drop the centering and make the arrow jump on click. */
  translate: 0 -50%;
  width: 28px;
  height: 88px;
  background: transparent;
  border: 0;
  color: var(--muted);
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: 64px;
  line-height: 0.7;
  cursor: pointer;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color 0.18s var(--ease-soft), translate 0.2s var(--ease-bounce);
}
.pq-arrow:hover { color: var(--accent); }
.pq-arrow-prev { left: 24px; }
.pq-arrow-next { right: 24px; }
.pq-arrow-prev:hover { translate: -2px -50%; }
.pq-arrow-next:hover { translate: 2px -50%; }

@media (max-width: 720px) {
  /* Carets vanish on small screens — let the user swipe. */
  .pq-arrow { display: none; }
  .pull-quote-slider { padding: 70px 20px 64px; }
  .pq-mark { font-size: 64px; }
  .pq-mark-open  { top: -22px; left: -6px; }
  .pq-mark-close { bottom: -32px; right: -6px; }
}

/* ── Phone mockup — used inside the How It Works step panels ─────── */
.phone {
  background: linear-gradient(180deg, #1f1f2c 0%, #181820 100%);
  border: 1px solid var(--border);
  border-radius: 28px;
  padding: 14px 14px 28px;
  box-shadow:
    0 30px 80px rgba(0, 0, 0, 0.45),
    0 0 0 1px rgba(255, 255, 255, 0.04) inset;
  position: relative;
}
.phone::before {
  content: '';
  position: absolute;
  top: 8px;
  left: 50%;
  transform: translateX(-50%);
  width: 80px;
  height: 5px;
  background: rgba(255, 255, 255, 0.1);
  border-radius: 99px;
}
.phone-screen {
  background: var(--bg);
  border-radius: 18px;
  padding: 22px 16px 16px;
  min-height: 540px;
}
.phone-tab-label {
  font-size: 22px;
  font-weight: 700;
  margin-bottom: 14px;
  color: var(--text);
}
/* Section header inside the transactions phone — small caps that the
   real app uses too (in app.js render code, not in styles.css yet, so
   we define it here). */
.tx-section-header {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 1.5px;
  color: var(--muted);
  margin: 14px 0 8px;
  font-weight: 700;
}
.tx-section-header:first-child { margin-top: 4px; }

/* ── Discord CTA ──────────────────────────────────────────────────
   Last thing before the footer. Deliberately unboxed — just centered copy
   and the button on the page background — so it reads as a closing aside
   and doesn't compete with the .cta-band sign-up card above it. */
.discord-cta {
  max-width: 620px;
  margin: 0 auto 96px;
  text-align: center;
}
.discord-cta p {
  margin: 0 0 20px;
  font-size: 15px;
  line-height: 1.6;
  color: var(--muted);
}

/* ── CTA band ────────────────────────────────────────────────────── */
.cta-band {
  margin: 32px 0 80px;
  background:
    radial-gradient(circle at 20% 0%, rgba(124, 111, 247, 0.3), transparent 55%),
    radial-gradient(circle at 80% 100%, rgba(246, 200, 96, 0.18), transparent 55%),
    var(--surface);
  border: 1px solid var(--border);
  border-radius: 28px;
  padding: 80px 32px;
  text-align: center;
  position: relative;
  overflow: hidden;
}
.cta-inner h2 {
  font-family: var(--font-serif);
  font-size: clamp(30px, 4.4vw, 46px);
  font-weight: 700;
  letter-spacing: -0.8px;
  margin-bottom: 16px;
  color: var(--text);
}
.cta-inner p {
  font-size: 17px;
  color: var(--muted);
  max-width: 560px;
  margin: 0 auto 32px;
  line-height: 1.6;
}
.cta-buttons {
  display: flex;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
}
/* Skinny screens: stack Sign up / I have an account and fill the full width,
   same as the hero CTAs. Wider screens keep them side by side. */
@media (max-width: 380px) {
  .cta-buttons { flex-direction: column; align-items: stretch; }
  .cta-buttons .btn-lg { width: 100%; }
}
/* The secondary is a solid purple button now, so it reads fine on the CTA
   band's gradient with no override needed — it uses the shared .btn-ghost. */
/* ── Pre-launch note ─────────────────────────────────────────────
   Lives just below the CTA band, outside its fancy gradient, so the
   "free now / paid later" caveat reads as a sincere aside rather than
   marketing copy. Soft gold wash to match the site's accent palette. */
@media (max-width: 560px) {
}

/* ── Info modals — opened by the hero ? and pill ─────────────────── */
.info-modal[hidden] { display: none; }
.info-modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  background: rgba(0, 0, 0, 0.62);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  animation: infoFade 0.18s var(--ease-soft);
}
@keyframes infoFade { from { opacity: 0; } to { opacity: 1; } }
.info-modal-card {
  position: relative;
  max-width: 440px;
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 26px 24px 22px;
  color: var(--text);
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.5);
  animation: infoLift 0.28s var(--ease-bounce);
}
@keyframes infoLift {
  from { transform: translateY(14px) scale(0.97); opacity: 0; }
  to   { transform: translateY(0) scale(1); opacity: 1; }
}
.info-modal-card h3 {
  font-family: var(--font-serif);
  font-size: 22px;
  font-weight: 700;
  margin-bottom: 14px;
  padding-right: 28px;
  color: var(--text);
}
.info-modal-card p {
  font-size: 14px;
  line-height: 1.6;
  color: var(--text);
  margin-bottom: 12px;
}
.info-modal-card p strong { color: var(--text); font-weight: 700; }
.info-modal-card p em { color: var(--accent); font-style: italic; }
.info-fineprint {
  font-size: 12px !important;
  color: var(--muted) !important;
  margin-top: 14px !important;
}
/* Close button visual (color + size + hover) comes from the synced
   app sheet's .btn-icon. Site-only positioning sits it in the corner. */
.info-close {
  position: absolute;
  top: 12px;
  right: 12px;
}
.info-got-it {
  width: 100%;
  margin-top: 8px;
}

/* ── Document modal (Terms / Privacy iframe) ─────────────────────── */
.doc-modal[hidden] { display: none; }
.doc-modal {
  position: fixed;
  inset: 0;
  z-index: 210;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(0, 0, 0, 0.62);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  animation: infoFade 0.18s var(--ease-soft);
}
.doc-modal-card {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 820px;
  height: 90vh;
  height: 90dvh;
  max-height: 900px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.5);
  animation: infoLift 0.28s var(--ease-bounce);
}
.doc-modal-head {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px 12px 10px 20px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.doc-modal-title {
  font-family: var(--font-serif);
  font-size: 17px;
  font-weight: 700;
  color: var(--text);
  margin-right: auto;
}
.doc-modal-open {
  color: var(--muted);
  text-decoration: none;
  font-size: 16px;
  line-height: 1;
  padding: 8px 10px;
  border-radius: 8px;
}
.doc-modal-open:hover { color: var(--accent); }
/* .btn-icon (from the synced app sheet) supplies the close button's look;
   override the info-modal's absolute positioning so it sits in the header. */
.doc-modal-close { position: static; }
.doc-modal-frame {
  flex: 1;
  width: 100%;
  border: 0;
  background: var(--bg);
}
@media (max-width: 640px) {
  .doc-modal { padding: 0; }
  .doc-modal-card {
    max-width: none;
    height: 100dvh;
    max-height: none;
    border-radius: 0;
    border: none;
  }
}

/* ── Footer ──────────────────────────────────────────────────────── */
.footer {
  border-top: 1px solid var(--border);
  padding: 48px 28px 64px;
  background: rgba(0, 0, 0, 0.18);
}
.footer-inner {
  max-width: var(--max-w);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}
.footer-brand {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--text);
}
.footer-tag {
  color: var(--muted);
  font-size: 14px;
  font-style: italic;
  font-family: var(--font-serif);
}
.footer-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 22px;
  margin-top: 8px;
}
.footer-links a {
  color: var(--muted);
  font-size: 14px;
  text-decoration: none;
  transition: color 0.18s var(--ease-soft);
}
.footer-links a:hover { color: var(--text); }
.footer-fineprint {
  color: var(--muted);
  opacity: 0.75;
  font-size: 12px;
  margin-top: 18px;
  text-align: center;
  line-height: 1.6;
}
.footer-fineprint em {
  color: var(--gold);
  font-style: italic;
  font-family: var(--font-serif);
}

/* ── Reveal-on-scroll ────────────────────────────────────────────── */
.reveal {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.7s var(--ease-soft), transform 0.7s var(--ease-bounce);
}
.reveal.in { opacity: 1; transform: translateY(0); }

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

/* ── Responsive ──────────────────────────────────────────────────── */
@media (max-width: 880px) {
  /* Single column. The grid-template-areas reorder is the load-bearing
     line — it puts the preview between text-top and text-bottom so the
     CTA buttons land below the thing the heading is talking about. */
  .hero-inner {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto auto;
    grid-template-areas:
      "top"
      "preview"
      "bottom";
    gap: 32px;
  }
  .hero-text-bottom { padding-top: 0; }
  /* Single-column hero: center the Get started / Learn more buttons under
     the centered preview instead of leaving them left-aligned. */
  .hero-cta { justify-content: center; }
  .hero-preview { justify-self: center; max-width: 380px; width: 100%; }
  .why-grid, .how-steps, .what-grid { grid-template-columns: 1fr; }
  /* Formula stays in a single horizontal row on mobile — there's
     plenty of width to read the three numbers. Just shrink the
     padding, font sizes, and let the pieces fit. */
  .how-formula { padding: 18px 12px; gap: 6px; }
  .formula-piece { min-width: 0; }
  .formula-label { font-size: 9px; letter-spacing: 1px; margin-bottom: 4px; }
  .formula-val { font-size: 16px; }
  .formula-op { font-size: 18px; }
  .section { padding: 80px 0; }
  .hero { padding: 40px 0 80px; }
}
@media (max-width: 480px) {
  /* Even narrower — keep labels visible (they're short, 4-7 chars), just
     shrink everything proportionally. The Bank − Pockets = GTG layout is
     the whole point; losing the labels makes it cryptic. */
  .how-formula { padding: 14px 6px; gap: 4px; }
  .formula-label { font-size: 8px; letter-spacing: 0.5px; margin-bottom: 3px; }
  .formula-val { font-size: 13px; }
  .formula-op { font-size: 14px; }
}

/* Tighten the nav before it would wrap: shrink gaps + link font so the
   single row keeps fitting between full width and the first collapse.
   The first step used to start at 1185px, which was already too late —
   the row overflowed from ~1300px down and clipped the Sign Up button on
   a 1280-wide laptop. It now starts at 1400px (and the Discord link adds
   one more item to fit), so the shrink happens before anything collides. */
@media (max-width: 1400px) {
  .top-nav { gap: 18px; padding: 16px 22px; }
  .nav-links { gap: 18px; }
  .nav-links a, .nav-links .nav-demo { font-size: 13px; padding: 6px 2px; }
  .nav-cta { gap: 8px; }
}
@media (max-width: 1250px) {
  .top-nav { gap: 12px; }
  .nav-links { gap: 12px; }
  .nav-links a, .nav-links .nav-demo { font-size: 12.5px; }
  .nav-cta a { padding: 10px 16px; }
}
/* Last squeeze before the Sign in / Sign up pair folds into the burger at
   1100px — without it the row overflows by a few px right at that seam. */
@media (max-width: 1150px) {
  .nav-links { gap: 10px; }
  .nav-cta a { padding: 10px 13px; }
}

/* Stage 1 (≤1100px): the Sign in / Sign up buttons are what run out of room
   first, so fold JUST those into the burger. The nav links stay in the bar. */
@media (max-width: 1100px) {
  .nav-cta { display: none; }
  .nav-burger { display: flex; }
  /* At this stage the drawer holds sign in / sign up + Discord — the section
     links are still visible in the bar, so hide them inside the drawer. The
     demo entry is still in the bar too (inside .nav-links), so hide its
     drawer copy. Discord is the exception: with seven links + the demo button
     the bar runs out of room around 1050px, so the Discord link folds into the
     burger at this same stage and the drawer copy (which carries the full
     "Join the Discord" wording) takes over from here down. */
  .nav-drawer a:not(.drawer-signin):not(.drawer-signup):not(.drawer-discord),
  .nav-drawer .nav-demo { display: none; }
  .nav-links .nav-discord { display: none; }
}

/* Give the links a touch more shrink room now that they own the middle.
   The gap keeps stepping DOWN from the queries above (18 → 12 → 10 → 9);
   it used to jump back up to 14px here, which overflowed the row in the
   890–920px band just above the point the links fold away entirely. */
@media (max-width: 1000px) {
  .top-nav { gap: 12px; }
  .nav-links { gap: 9px; }
  .nav-links a { font-size: 12.5px; }
}

/* Stage 2 (≤880px): drop everything into the burger — matches the point the
   page itself collapses to a single column. The restore selector mirrors the
   Stage-1 :not() specificity so it actually wins the cascade. */
@media (max-width: 880px) {
  .nav-links { display: none; }
  /* Mirrors the Stage-1 hide selector's :not() chain exactly — including
     :not(.drawer-discord) — so it wins on equal specificity + later order.
     Drop one :not() here and the Stage-1 rule outranks this and the section
     links stay hidden in the drawer. */
  .nav-drawer a:not(.drawer-signin):not(.drawer-signup):not(.drawer-discord) { display: block; }
  .nav-drawer .nav-demo { display: block; }
  .top-nav { gap: 0; padding: 12px 20px; justify-content: space-between; }
  main { padding: 0 20px; }
  .cta-band { padding: 56px 24px; border-radius: 20px; }
}

/* Smooth scroll offset for sticky nav */
section[id] { scroll-margin-top: 84px; }
html { scroll-behavior: smooth; }

/* ── How it works — scroll-pinned live walkthrough ─────────────────── */
/* Base (no-JS / reduced motion): a normal stacked block. The .scrolly class
   (added by main.js) turns on the tall track + sticky pin + scroll driving. */
.section-how-scroll { position: relative; padding: 60px 0; }
/* Catch zone for the down-only pager: taller than one screen so a fast fling
   still registers as "entered" before it can shoot past. Stepping itself is
   handled by the scroll-lock overlay, not by scrolling this track. */
.section-how-scroll.scrolly { padding: 0; height: 180vh; }

.section-how-scroll.scrolly .how-pin {
  position: sticky; top: 0;
  height: 100vh; height: 100dvh;
  overflow: hidden;
  display: flex;
}
/* Engaged: the pin is promoted to a fixed overlay while the page is scroll-
   locked, so the walkthrough owns the viewport and momentum can't leak past. */
.section-how-scroll.scrolly .how-pin.engaged {
  position: fixed; inset: 0; z-index: 40;
  height: 100vh; height: 100dvh;
}
.how-pin-inner {
  flex: 1; min-height: 0; width: 100%;
  max-width: 620px; margin: 0 auto;
  display: flex; flex-direction: column;
  padding: 0 8px;
  transition: max-width 0.5s var(--ease-soft), padding 0.5s var(--ease-soft);
}

/* Top half: copy that cross-fades between steps. On expand it collapses to 0 —
   a binary snap (class toggle + transition), not a scroll-linked crawl. */
.how-copy {
  flex: 0 0 32vh;
  display: flex; flex-direction: column; justify-content: center;
  padding: 6px 6px 10px;
  overflow: hidden;
  transition: flex-basis 0.5s var(--ease-soft),
              opacity 0.35s var(--ease-soft),
              padding 0.5s var(--ease-soft);
}
.how-pin.expanded .how-copy { flex-basis: 0; opacity: 0; padding-top: 0; padding-bottom: 0; }
.how-copy .section-eyebrow { margin-bottom: 12px; }
.how-copy-stack { position: relative; min-height: clamp(120px, 17vh, 170px); }
.how-panel {
  position: absolute; inset: 0;
  opacity: 0; transform: translateY(12px);
  transition: opacity 0.5s var(--ease-soft), transform 0.5s var(--ease-soft);
  pointer-events: none;
}
.how-panel.active { opacity: 1; transform: none; pointer-events: auto; }
.how-panel h3 {
  font-family: var(--font-serif); font-size: clamp(24px, 5.4vw, 34px);
  font-weight: 700; letter-spacing: -0.5px; color: var(--text);
  display: flex; align-items: center; gap: 12px; margin-bottom: 14px;
}
.how-step-num {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: 50%;
  background: var(--accent); color: #fff; font-size: 16px; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
.how-panel p { font-size: 16px; line-height: 1.6; color: var(--muted); }
.how-panel em { color: var(--text); font-style: italic; }
.how-dots { display: flex; gap: 8px; margin-top: 20px; }
.how-dots span { width: 8px; height: 8px; border-radius: 99px; background: var(--border); transition: background 0.35s, width 0.35s; }
.how-dots span.active { background: var(--accent); width: 24px; }

/* Bottom half: the pinned live app. Fills the remaining height and grows to
   full-screen as --expand goes 0→1. Slides up from the bottom edge. */
.how-stage {
  flex: 1 1 auto; min-height: 0;
  display: flex; justify-content: center; align-items: flex-end;
}
.how-stage .demo-phone {
  width: 100%; max-width: none; height: 100%;
  padding: 0; margin: 0;
  border: 1px solid var(--border); border-bottom: 0;
  border-radius: 26px 26px 0 0;
  background: linear-gradient(180deg, #1f1f2c 0%, #181820 100%);
  box-shadow: 0 -26px 60px rgba(0,0,0,0.5), 0 0 0 1px rgba(255,255,255,0.04) inset;
  overflow: hidden; position: relative;
}
.how-stage .demo-phone::before {
  content: ''; position: absolute; top: 7px; left: 50%; transform: translateX(-50%);
  width: 64px; height: 5px; background: rgba(255,255,255,0.14); border-radius: 99px; z-index: 3;
}

/* The viewport clips the scaled-down app. --app-scale renders the app at a
   canonical phone width, then shrinks the whole thing so MORE of it shows at a
   smaller size — a true zoom-out, no reflow, nothing squished. width/height are
   the inverse of the scale so the visual result exactly fills the viewport. */
.how-stage .demo-viewport {
  position: absolute; inset: 9px 9px 0;
  border-radius: 18px 18px 0 0; overflow: hidden; background: var(--bg);
}
.how-stage .demo-phone iframe {
  display: block; border: 0; background: var(--bg);
  width: calc(100% / var(--app-scale, 0.86));
  height: calc(100dvh / var(--app-scale, 0.86));
  transform: scale(var(--app-scale, 0.86));
  transform-origin: top left;   /* left-anchored so the compensated width fills
                                   the frame exactly — top-center overflows right */
  pointer-events: none;                       /* inert during the scroll tour */
}

/* Snap-to-fullscreen (pinned): copy has collapsed, so the app fills the pin.
   Go edge-to-edge — drop the phone frame, side gutters, and handle bar so it
   reads as the app taking over the screen. */
.how-pin.expanded .how-pin-inner { max-width: none; padding: 0; }
.how-pin.expanded .how-stage .demo-phone {
  border-radius: 0; border-left: 0; border-right: 0;
}
.how-pin.expanded .how-stage .demo-phone::before { opacity: 0; }
.how-pin.expanded .how-stage .demo-viewport { inset: 0; border-radius: 0; }

/* Play button — bottom-middle, above the app's own nav bar. Hidden until the app
   has expanded to fill the screen (added via [hidden] toggle in JS). */
.demo-play {
  position: absolute; left: 50%; bottom: 26px; translate: -50% 0;
  z-index: 4; cursor: pointer;
  background: var(--accent, #ada1ff); color: #14141d;
  font-size: 14px; font-weight: 700; letter-spacing: 0.2px;
  padding: 12px 22px; border: 0; border-radius: 99px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.45), 0 0 0 4px rgba(173,161,255,0.18);
  animation: demoPulse 2.4s ease-in-out infinite;
}
.demo-play[hidden] { display: none; }
/* Mobile: once the phone snaps to the top, the play button floats on-screen —
   pinned to the viewport bottom (or the phone's bottom, via an inline `bottom`
   set in JS). Fixed positioning + a high z-index keep it above the page. */
.demo-play.floating { position: fixed; z-index: 60; }
@keyframes demoPulse {
  0%, 100% { box-shadow: 0 10px 30px rgba(0,0,0,0.45), 0 0 0 4px rgba(173,161,255,0.18); }
  50%      { box-shadow: 0 10px 30px rgba(0,0,0,0.45), 0 0 0 9px rgba(173,161,255,0.05); }
}

/* Fullscreen interactive mode — the pinned phone is promoted to a fixed modal
   that covers the viewport, and the iframe becomes live. */
.how-stage .demo-phone.fullscreen {
  position: fixed; inset: 0; z-index: 1200;
  width: 100vw; height: 100vh; height: 100dvh;
  max-width: none; padding: 0; border: 0; border-radius: 0;
  box-shadow: none;
}
.how-stage .demo-phone.fullscreen::before { display: none; }
.how-stage .demo-phone.fullscreen .demo-viewport { inset: 0; border-radius: 0; }
.how-stage .demo-phone.fullscreen iframe {
  width: 100%; height: 100%; transform: none; pointer-events: auto;
}
.how-stage .demo-phone.fullscreen .demo-play { display: none; }

/* Exit button — bottom-middle, hovering above the app's nav bar (so it never
   overlaps the Good to Go number top-right or the logo top-left). */
.demo-exit {
  position: fixed; left: 50%; bottom: 84px; translate: -50% 0;
  z-index: 1300; cursor: pointer;
  background: rgba(20,20,29,0.9); color: #fff;
  font-size: 14px; font-weight: 600;
  padding: 11px 22px; border: 1px solid rgba(255,255,255,0.18); border-radius: 99px;
  backdrop-filter: blur(6px);
  box-shadow: 0 10px 30px rgba(0,0,0,0.5);
}
.demo-exit[hidden] { display: none; }

/* No-JS / no-.scrolly fallback: lay the panels out in normal flow, all visible,
   with the app below. Nothing pins, nothing cross-fades. */
.section-how-scroll:not(.scrolly) .how-copy-stack { position: static; min-height: 0; }
.section-how-scroll:not(.scrolly) .how-panel {
  position: static; opacity: 1; transform: none; pointer-events: auto;
  margin-bottom: 26px;
}
.section-how-scroll:not(.scrolly) .how-dots { display: none; }
.section-how-scroll:not(.scrolly) .how-stage .demo-phone { height: 620px; }

/* Desktop: cap the app width so the mobile-shaped UI doesn't stretch, and give
   the copy a bit more room. */
@media (min-width: 861px) {
  .how-pin-inner { max-width: 940px; }
  .how-copy { flex-basis: 30vh; align-items: center; text-align: center; }
  .how-panel h3 { justify-content: center; }
  .how-dots { justify-content: center; }
  .how-stage .demo-phone { max-width: 460px; border-radius: 30px 30px 0 0; }
  .how-stage .demo-phone.fullscreen { max-width: none; }
  /* Snap fills the width on desktop too. */
  .how-pin.expanded .how-stage .demo-phone { max-width: 520px; border-radius: 0; }
}

/* Respect reduced-motion: no pulsing play button. */
@media (prefers-reduced-motion: reduce) {
  .demo-play { animation: none; }
}

/* ── How it works — gentle auto-play walkthrough (ALL devices) ────────────
   main.js tags the section `.how-auto` (never `.scrolly`) and skips every bit
   of scroll-jacking. The section sizes to ~one viewport and softly snaps into
   view; the steps auto-play in sequence, each driving the embedded phone. The
   phone keeps a fixed, on-page size and NEVER grows to fullscreen. Rules are
   scoped `.section-how-scroll.how-auto …` (specificity 0,3,x) so they win over
   the base rules and the `:not(.scrolly)` fallback. Mobile-first here; the wide
   two-column card layout is in the media query below. */
.section-how-scroll.how-auto {
  height: auto;
  padding: 20px 0 40px;              /* steps at top; the phone runs off the bottom */
  /* No CSS snap on mobile — main.js runs a custom down-only two-stage snap
     (steps, then phone). Desktop keeps CSS center-snap (media query below). */
}
.section-how-scroll.how-auto .how-pin {
  position: static; height: auto; overflow: visible; display: block; width: 100%;
}
.section-how-scroll.how-auto .how-pin-inner {
  max-width: 880px; margin: 0 auto; padding: 0; width: 100%;
  display: flex; flex-direction: column; gap: 16px; transition: none;
}

/* Section header — the eyebrow + serif headline. Both show on every size:
   mobile gets a smaller, centered headline under the eyebrow; the wide media
   query below scales it up for desktop. */
.section-how-scroll.how-auto .how-header {
  padding: 0; text-align: left;
}
.section-how-scroll.how-auto .how-header .section-eyebrow { margin-bottom: 10px; }
/* Reveal it and let it inherit the standard .section-h look so it matches
   every other section header on mobile. The wide media query below swaps in
   this section's own desktop size. */
.section-how-scroll.how-auto .how-header .section-h { display: block; }

/* Steps + phone wrapper. Mobile: single stacked column (steps, then phone). */
.section-how-scroll.how-auto .how-cols {
  display: flex; flex-direction: column; gap: 16px;
}

/* Copy — ONE step at a time on mobile (cross-fade), centered. */
.section-how-scroll.how-auto .how-copy {
  flex: none; display: block; overflow: visible;
  padding: 0 20px; opacity: 1; text-align: center; transition: none;
}
.section-how-scroll.how-auto .how-copy .section-eyebrow { margin-bottom: 10px; }
/* Grid-stack the three steps in ONE cell: they overlap for the cross-fade, but
   the cell (and the stack) sizes to the TALLEST step's text. So when the OS/
   browser scales text up for accessibility, the stack grows and pushes the dots
   + phone down instead of the text overflowing a fixed height and colliding
   with them. min-height is just a floor for normal text. */
.section-how-scroll.how-auto .how-copy-stack {
  position: relative; display: grid; min-height: clamp(130px, 22vh, 176px); margin: 0;
}
.section-how-scroll.how-auto .how-panel {
  grid-area: 1 / 1; margin: 0;
  opacity: 0; transform: translateY(10px); pointer-events: none;
  transition: opacity 0.45s var(--ease-soft), transform 0.45s var(--ease-soft);
  background: transparent; border: 0; padding: 0; text-align: center;
}
.section-how-scroll.how-auto .how-panel.active {
  opacity: 1; transform: none; pointer-events: auto;
}
.section-how-scroll.how-auto .how-panel h3 { justify-content: center; }
.section-how-scroll.how-auto .how-dots { display: flex; justify-content: center; margin-top: 12px; }

/* Phone — a COMPLETE phone (all four corners + full border), locked to the
   Pixel 6a screen ratio (1080×2400 → 9:20). Width tracks the viewport; height
   follows the ratio. The snap targets the STEPS (the section, above), so this
   tall phone simply extends past the bottom of the viewport — you see its top,
   scroll to reveal the rest and its rounded bottom. Fullscreen only on Play.
   The app renders a touch wider than shown and scales down so data breathes. */
.section-how-scroll.how-auto .how-stage {
  flex: none; display: flex; justify-content: center; align-items: flex-start; margin: 0;
}
.section-how-scroll.how-auto .how-stage .demo-phone {
  /* The mock matches the visitor's own VIEWPORT ratio (--vp-ratio = innerWidth /
     innerHeight, set in JS and updated on resize) so it reads like their actual
     device. Width tracks the viewport; height follows that ratio. */
  width: min(88vw, 440px);
  height: auto;
  aspect-ratio: var(--vp-ratio, 0.46);
  padding: 0; margin: 0;
  border: 1px solid var(--border);
  border-radius: 44px;
}
.section-how-scroll.how-auto .how-stage .demo-phone::before { top: 12px; }
.section-how-scroll.how-auto .how-stage .demo-viewport { inset: 11px; border-radius: 34px; }
.section-how-scroll.how-auto .how-stage .demo-phone iframe {
  --app-scale: 0.85;
  width: calc(100% / var(--app-scale));
  height: calc(100% / var(--app-scale));
  transform: scale(var(--app-scale));
  transform-origin: top left;   /* left-anchored so the compensated width fills
                                   the frame exactly. The scroll "channel" is
                                   hidden at the source (demo hides its own
                                   scrollbar when embedded) — see web/index.html. */
}
.section-how-scroll.how-auto .how-stage .demo-phone.interactive iframe {
  pointer-events: auto;
}

/* Play button sits in normal flow (never floats): desktop = under the steps
   (in the steps column), mobile = directly under the phone. JS reparents it per
   breakpoint; this just makes it a static, centered pill in both spots. */
.section-how-scroll.how-auto .demo-play {
  position: static; left: auto; bottom: auto; translate: none;
  align-self: center; margin-top: 18px;
}

/* Play → true fullscreen (mobile). These outrank the base `.how-auto` phone
   rules (which are more specific than the generic `.demo-phone.fullscreen`
   rules elsewhere), so the frame really covers the viewport when playing. */
.section-how-scroll.how-auto .how-stage .demo-phone.fullscreen {
  position: fixed; inset: 0; z-index: 1200;
  width: 100vw; height: 100vh; height: 100dvh; max-width: none;
  border: 0; border-radius: 0;
  /* env(safe-area-inset-bottom) is 0 INSIDE the cross-origin /demo iframe, so
     the app's own bottom-nav padding can't clear the Android gesture bar. The
     SITE is top-level, so env() resolves here: inset the iframe's bottom by it
     (below) and paint the strip in the nav-bar colour so it reads as the nav
     extending into the safe area — matching a direct /demo visit. */
  background: #1a1a22;
  scroll-snap-align: none; scroll-margin-top: 0;
}
.section-how-scroll.how-auto .how-stage .demo-phone.fullscreen::before { display: none; }
.section-how-scroll.how-auto .how-stage .demo-phone.fullscreen .demo-viewport {
  inset: 0 0 env(safe-area-inset-bottom) 0; border-radius: 0;
}
.section-how-scroll.how-auto .how-stage .demo-phone.fullscreen iframe {
  width: 100%; height: 100%; transform: none; pointer-events: auto;
}

/* Desktop: Play opens the demo in a MODAL over the site — a 20px margin all
   round, the app rendered at full DESKTOP width (no phone frame, no scale) so
   its own side panels behave like the real desktop app. The huge box-shadow
   dims the page behind; an X in the corner closes it. Higher specificity than
   the desktop phone rules so it wins. */
.section-how-scroll.how-auto .how-stage .demo-phone.demo-modal {
  position: fixed; inset: 20px; z-index: 1200;
  width: auto; height: auto; max-width: none;
  aspect-ratio: auto;
  border: 1px solid var(--border); border-radius: 16px;
  box-shadow: 0 0 0 100vmax rgba(0, 0, 0, 0.62);
}
.section-how-scroll.how-auto .how-stage .demo-phone.demo-modal::before { display: none; }
.section-how-scroll.how-auto .how-stage .demo-phone.demo-modal .demo-viewport { inset: 0; border-radius: 16px; }
.section-how-scroll.how-auto .how-stage .demo-phone.demo-modal iframe {
  width: 100%; height: 100%; transform: none; pointer-events: auto;
}
/* Close X — top-right of the modal, shown only while the modal is open. */
.demo-modal-close {
  position: absolute; top: 12px; right: 12px; z-index: 5;
  width: 40px; height: 40px; display: none;
  align-items: center; justify-content: center;
  background: rgba(20, 20, 29, 0.92); color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 50%;
  font-size: 20px; line-height: 1; cursor: pointer;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  transition: background 0.18s var(--ease-soft), border-color 0.18s var(--ease-soft);
}
.demo-modal-close:hover { background: rgba(40, 40, 54, 0.95); border-color: var(--accent); }
.demo-phone.demo-modal .demo-modal-close { display: flex; }

/* Wide screens: steps become a stacked column of CARDS to the LEFT of a full
   phone card (all cards visible, the active one highlighted; dots hidden). The
   section centers in ~one viewport and the phone caps at ~82svh so it fits. */
@media (min-width: 940px) {
  .section-how-scroll.how-auto {
    padding: 72px 0;
  }
  /* Header stacks on TOP (full thinner width); the steps + phone row sits
     directly under it. Content is capped at the same 880px thinner width the
     other sections use, so the steps/phone don't stretch to the page edges. */
  .section-how-scroll.how-auto .how-pin-inner {
    max-width: 880px;
    display: flex; flex-direction: column; align-items: stretch; gap: 26px;
  }
  .section-how-scroll.how-auto .how-header { text-align: left; padding: 0; }
  /* Inherit the shared .section-h size (no override) so this header matches
     every other section header; just drop the bottom margin for this layout. */
  .section-how-scroll.how-auto .how-header .section-h {
    display: block; margin-bottom: 0;
  }
  /* Steps (left) + phone (right), TOPS aligned. `stretch` makes the steps
     column fill the row height set by the phone, so the three cards (each
     flex:1) end up as tall/skinny buttons that stack to exactly the phone's
     height. */
  /* Steps + phone as a centered pair (no edge void), TOPS aligned. `stretch`
     makes the steps column fill the phone's height, so the three cards (flex:1)
     stack to exactly the phone's height. */
  /* Steps (left, filling the leftover width) + phone (right). The steps group
     is its NATURAL height and is vertically CENTERED against the taller phone. */
  .section-how-scroll.how-auto .how-cols {
    display: flex; flex-direction: row;
    justify-content: center; align-items: center; gap: 56px;
  }
  .section-how-scroll.how-auto .how-copy {
    flex: 1; text-align: left; padding: 0;
    display: flex; flex-direction: column;
  }
  .section-how-scroll.how-auto .how-copy-stack {
    position: static; min-height: 0; margin-top: 0;
    display: flex; flex-direction: column; gap: 16px;
  }
  .section-how-scroll.how-auto .how-panel {
    position: static; inset: auto; opacity: 1; transform: none;
    pointer-events: auto; cursor: pointer;
    transition: border-color 0.2s var(--ease-soft), background 0.2s var(--ease-soft);
    background: var(--surface); border: 1px solid var(--border);
    border-radius: 14px; padding: 20px 22px; text-align: left; margin: 0;
  }
  .section-how-scroll.how-auto .how-panel:hover { border-color: var(--accent); }
  /* Clicking a step selects it and drives the phone to that step's screen. */
  .section-how-scroll.how-auto .how-panel.active {
    border-color: var(--accent); background: rgba(124, 111, 247, 0.08);
    box-shadow: 0 0 0 1px var(--accent);
  }
  .section-how-scroll.how-auto .how-panel h3 {
    font-size: 20px; justify-content: flex-start; margin-bottom: 8px;
  }
  .section-how-scroll.how-auto .how-panel p { font-size: 15px; }
  .section-how-scroll.how-auto .how-dots { display: none; }
  .section-how-scroll.how-auto .how-stage { flex: 0 0 auto; align-items: center; justify-content: center; margin: 0; }
  /* Height-driven here, with a FIXED portrait ratio (a desktop viewport is
     landscape, so matching --vp-ratio would make a wide box — force 9:18 here).
     Trimmed so the header + phone + the play button below all clear the fold. */
  .section-how-scroll.how-auto .how-stage .demo-phone {
    width: auto;
    height: min(680px, 74svh);
    aspect-ratio: 9 / 18;
    border-radius: 44px;
    scroll-snap-align: none; scroll-margin-top: 0;
  }
  .section-how-scroll.how-auto .how-stage .demo-viewport { inset: 12px; border-radius: 34px; }
}

/* Reduced motion: autoplay + cross-fade are off (main.js skips the timers), so
   reveal every step stacked — nothing should hide behind an animation the
   visitor will never see. Desktop already stacks all cards; this covers mobile. */
@media (prefers-reduced-motion: reduce) {
  .section-how-scroll.how-auto .how-copy-stack {
    position: static; min-height: 0;
    display: flex; flex-direction: column; gap: 12px;
  }
  .section-how-scroll.how-auto .how-panel {
    position: static; inset: auto; opacity: 1; transform: none; pointer-events: auto;
  }
  .section-how-scroll.how-auto .how-dots { display: none; }
}

/* ── Free vs Premium comparison ─────────────────────────────────────── */
.section-premium .section-inner { max-width: 900px; }


.cmp-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
/* Roadmap/pricing disclaimer under the Free vs Premium table. Fills the full
   section width so it lines up with the table above it (no early wrap). */
.cmp-table {
  width: 100%;
  table-layout: fixed;            /* fixed columns so all three fit — no sideways scroll */
  min-width: 320px;              /* readable floor: only truly tiny viewports scroll sideways */
  border-collapse: collapse;
}
.cmp-table th,
.cmp-table td {
  padding: 15px 14px;
  border-bottom: 1px solid var(--border);
  text-align: center;
  vertical-align: middle;
}
.cmp-table thead th {
  font-size: 12.5px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
  border-bottom: 2px solid var(--border);
}
/* "Free" / "Premium" never break, and run a touch smaller than the row
   labels so they sit centered with breathing room instead of edge-to-edge. */
.cmp-table thead .cmp-col { white-space: nowrap; font-size: 11px; letter-spacing: 0.04em; }
.cmp-table tbody tr:last-child td { border-bottom: none; }

.cmp-table .cmp-feat { text-align: left; width: auto; }  /* flexes to whatever's left */
.cmp-table thead .cmp-feat { color: var(--muted); }
.cmp-col { width: 108px; white-space: normal; word-break: normal; overflow-wrap: break-word; }

/* Premium column gets a soft accent wash + rounded top so it reads as the
   highlighted plan. */
.cmp-col-prem { background: rgba(124, 111, 247, 0.07); }
.cmp-table thead .cmp-col-prem { color: var(--accent); font-weight: 700; }

/* Plan price under each column header — its own line, not uppercase, smaller +
   lighter than the label so the $ amount reads as a subtitle. */
.cmp-price {
  display: block;
  margin-top: 4px;
  font-size: 10.5px;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  line-height: 1.25;
  color: var(--muted);
  /* Wrap within the column — the header cells are nowrap, which would otherwise
     force "$6/mo or $60/yr" onto one line and push the table past the viewport. */
  white-space: normal;
}
.cmp-table tbody tr:first-child .cmp-col-prem { border-top-left-radius: 12px; border-top-right-radius: 12px; }
.cmp-table tbody tr:last-child  .cmp-col-prem { border-bottom-left-radius: 12px; border-bottom-right-radius: 12px; }

/* "Coming soon" qualifies the WHOLE row, so it rides the name rather than
   trailing the description, where it read as one more detail of the feature
   and was invisible until you had read four lines. */
.cmp-soon {
  display: inline-block; margin-left: 8px; padding: 2px 8px; border-radius: 999px;
  background: rgba(255,255,255,0.08); border: 1px solid var(--border);
  font-size: 11px; font-weight: 600; letter-spacing: 0.02em;
  color: var(--muted); vertical-align: middle; white-space: nowrap;
}
.cmp-name { display: block; font-weight: 600; color: var(--text); font-size: 15.5px; }
.cmp-desc { display: block; margin-top: 3px; color: var(--muted); font-size: 13px; line-height: 1.45; }

.cmp-yes { color: var(--green); font-weight: 700; font-size: 19px; line-height: 1; }
.cmp-no  { color: var(--muted); opacity: 0.45; font-size: 19px; line-height: 1; }
/* Value labels ("Unlimited", "On demand") wrap and shrink so they never
   crowd the column edge. */
.cmp-val { display: block; color: var(--text); font-weight: 600; font-size: 14px; line-height: 1.25; overflow-wrap: break-word; }
.cmp-col-prem .cmp-val { color: var(--accent); }

/* Inline "Learn more" — link-styled button, no chrome. */
.cmp-learn {
  display: inline;
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  font-weight: 600;
  color: var(--accent);
  cursor: pointer;
  white-space: nowrap;
}
.cmp-learn:hover { text-decoration: underline; }

@media (max-width: 560px) {
  .cmp-table th, .cmp-table td { padding: 13px 6px; }
  /* Keep the value columns just wide enough to hold "Premium" on one line,
     and let the Feature column take the (smaller) remainder. */
  .cmp-col { width: 70px; }
  .cmp-name { font-size: 14px; }
  .cmp-desc { font-size: 12.5px; }
  .cmp-val { font-size: 11.5px; }
  .cmp-table thead th { font-size: 10.5px; letter-spacing: 0.02em; }
  .cmp-table thead .cmp-col { font-size: 10px; letter-spacing: 0.02em; }
}
@media (max-width: 380px) {
  .cmp-table th, .cmp-table td { padding: 12px 4px; }
  .cmp-col { width: 66px; }
  .cmp-val { font-size: 11px; }
}
