/* ============================================================================
   Loopa — loopahealth.app
   One stylesheet, shared by every page. Extracted from the single-page
   index.html on 2026-08-13 when the site went multi-page; the tokens and
   component classes below are the originals, unchanged, plus the components
   the pillar pages needed (method grid, stat band, feature rows, sitemap
   footer, breadcrumbs, verdict cards).

   Cache-busted with ?v= in every <link>. Bump the token in ALL pages when
   this file changes, or a returning visitor gets the old sheet against new
   markup. `grep -rl 'loopa.css?v=' public/` finds every one.
   ========================================================================= */

/* ============ Typeface ============
   Self-hosted 2026-08-17. Was two preconnects plus a render-blocking stylesheet
   request to fonts.googleapis.com, which itself chains to fonts.gstatic.com --
   two DNS lookups and two TLS handshakes on a third-party path before the first
   character of the page painted. It is also the only reason a visitor's IP
   reached Google at all, on a site whose privacy section argues a health app
   should not be an advertising business.

   One file per subset, not per weight: Plus Jakarta Sans ships as a variable
   font, so a single 27KB latin file covers 400 through 800. latin-ext is here
   for the accented characters in competitor names; it is a separate request the
   browser only makes if a glyph actually needs it.

   U+2192 (the -> in "Files -> Downloads") is in neither subset and falls back
   to the system font. That was already true on Google Fonts -- same subsetting
   -- so this is not a regression. */
@font-face {
  font-family: 'Plus Jakarta Sans';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('/fonts/plus-jakarta-sans-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                 U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
                 U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Plus Jakarta Sans';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('/fonts/plus-jakarta-sans-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ============ Design tokens — "Digital Harmony" ============ */
:root {
  /* ── Loopa Electric ────────────────────────────────────────────────────────
     The vibrant identity, replacing the muted violet-on-cream palette. Every
     value below is measured, and the measurements are the usage rules:

       Electric Purple #6C3BFF  5.29 on the page, 5.66 on a card, and white on
                                it is 5.66 — the only brand colour that is safe
                                BOTH as text on light and as a fill under a
                                white label. It is the dominant mark.
       Aqua           #00C9D8  2.03 on white. NEVER label text on a light
                                surface. It is 7.87 on Deep Ink, so it is a
                                dark-surface colour, a fill under ink labels,
                                or a graphic.
       Pulse Orange   #FF7A00  2.61 on white, same rule as Aqua. 6.11 on Deep
                                Ink, which is where the rate-card kicker and the
                                stat-band lead use it.
       Highlight Lime #B8F23C  1.33 on white — the least usable of the four as
                                text, and the brand book already says to keep it
                                for achievements and streaks. Dark surfaces only
                                (12.02 on Deep Ink).
       Deep Ink       #14213D  14.9 on the page. Body text and every dark band.

     The trap this comment exists to stop: three of the four brand colours fail
     as label text on light, and they look their best on a designer's screen
     exactly where they are least readable. Reach for --purple or --ink for
     anything a person has to READ on a light surface. */
  --bg: #F4F7FF;
  --ink: #14213D;
  --ink-soft: #475569;
  /* 7.07 on the page, 7.58 on white, and still over AA on the #F1F5F9 fill that
     .crumbs and several card captions sit on. */
  --ink-faint: #5C6A7F;
  --purple: #6C3BFF;
  /* A true darkening of Electric Purple rather than the old violet: 7.97 as text
     on the page, and white on it is 8.54. Gradients and anything that needs to
     be stronger than --purple without leaving the hue. */
  --purple-deep: #4A1FD6;
  --mint: #00C9D8;
  /* The confirmation tick beside the pricing and hero notes. A graphic carrying
     meaning, so WCAG wants 3:1; this is over 4.5 on the page. Highlight Lime is
     the brand's success colour but measures 1.24 here, which is why the ticks
     are still green on light and Lime is reserved for dark surfaces. */
  --green: #15803D;
  --amber: #FF7A00;
  /* Sparingly, and on dark only. */
  --lime: #B8F23C;
  --card: #FFFFFF;
  --border: #E6ECFA;
  --radius: 16px;
  --shadow-sm: 0 1px 2px rgba(20, 33, 61, .05), 0 4px 16px rgba(20, 33, 61, .06);
  --shadow-md: 0 4px 8px rgba(20, 33, 61, .06), 0 12px 32px rgba(74, 31, 214, .10);
  --font: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; scroll-padding-top: 84px; }
body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--ink);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
img, svg { display: block; max-width: 100%; }
a { color: inherit; }

/* Arrow glyphs that sit inside a run of text. The reset above makes every svg
   a block, which drops a trailing arrow onto its own line in any link that is
   not already a flex container. */
.iarrow { display: inline-block; vertical-align: -2px; margin-left: 3px; }

.wrap { max-width: 1120px; margin: 0 auto; padding: 0 24px; }
.wrap-narrow { max-width: 820px; margin: 0 auto; padding: 0 24px; }

/* Skip link — first focusable element on every page. */
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--purple-deep); color: #FFFFFF; padding: 12px 20px;
  border-radius: 0 0 12px 0; font-weight: 700; text-decoration: none;
}
.skip:focus { left: 0; }

/* Visually hidden, still read aloud and still counted as anchor text.
   Nine cards on the home page had "Learn more" as their entire accessible name, so a
   screen reader's link list was nine identical entries and a crawler saw nine anchors
   carrying no destination signal. The visible words are unchanged; this carries the
   rest of the sentence. clip-path rather than the old width/height/clip trick so the
   text is not collapsed to a single column when it wraps. */
.vh {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden; white-space: nowrap;
  clip-path: inset(50%);
}

/* ============ Buttons ============ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  font-family: var(--font); font-weight: 700; font-size: 16px;
  padding: 14px 28px; border-radius: 999px; border: 0; cursor: pointer;
  text-decoration: none; transition: transform .15s ease, box-shadow .15s ease, background .15s ease;
}
/* The keyboard ring has to be visible on the surface it lands on, and one colour
   cannot do both here: mint is 7.86:1 on the dark ink panels and 1.77:1 on the
   cream page. It was mint everywhere, so the only affordance a keyboard user
   gets was effectively invisible across most of the site -- a thing no mouse
   user would ever notice. Purple is 8.53:1 on cream and 8.98 on white; mint is
   kept for the dark panels, where purple would drop to 1.63:1. */
.btn:focus-visible, a:focus-visible, summary:focus-visible, button:focus-visible {
  outline: 3px solid var(--purple); outline-offset: 3px;
}
footer a:focus-visible,
footer button:focus-visible,
.final-cta a:focus-visible,
.final-cta button:focus-visible,
.stat-band a:focus-visible {
  outline-color: var(--mint);
}
.btn-primary {
  background: linear-gradient(135deg, var(--purple) 0%, var(--purple-deep) 100%);
  color: #fff; box-shadow: 0 6px 20px rgba(108, 59, 255, .30);
}
.btn-primary:hover { transform: translateY(-2px); box-shadow: 0 10px 28px rgba(108, 59, 255, .38); }
.btn-ghost {
  background: transparent; color: var(--purple-deep);
  border: 2px solid rgba(108, 59, 255, .25);
}
.btn-ghost:hover { border-color: var(--purple); background: rgba(108, 59, 255, .05); }

/* Store badges (pure SVG/CSS — no external images) */
.store-badge {
  display: inline-flex; align-items: center; gap: 12px;
  background: var(--ink); color: #fff; text-decoration: none;
  padding: 11px 22px 11px 18px; border-radius: 14px;
  border: 1px solid rgba(255,255,255,.12);
  transition: transform .15s ease, box-shadow .15s ease;
  min-height: 60px;
}
.store-badge:hover { transform: translateY(-2px); box-shadow: 0 10px 24px rgba(20,33,61,.28); }
.store-badge .sb-text { display: flex; flex-direction: column; line-height: 1.25; text-align: left; }
.store-badge .sb-small { font-size: 11px; font-weight: 500; opacity: .85; letter-spacing: .02em; }
.store-badge .sb-big { font-size: 18px; font-weight: 700; letter-spacing: -.01em; }

/* ============ Sticky header ============ */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: rgba(250, 249, 245, .85);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid rgba(20, 33, 61, .06);
}
.nav { display: flex; align-items: center; justify-content: space-between; height: 72px; }
.logo { display: flex; align-items: center; gap: 10px; text-decoration: none; font-weight: 800; font-size: 22px; letter-spacing: -.02em; color: var(--ink); }
.nav .btn { padding: 11px 22px; font-size: 15px; }
.nav-links { display: flex; align-items: center; gap: 26px; }
.nav-links a.plain { text-decoration: none; font-weight: 600; font-size: 15px; color: var(--ink-soft); transition: color .15s; }
.nav-links a.plain:hover, .nav-links a.plain[aria-current="page"] { color: var(--purple); }
/* Seven links and a button. The 26px gap was set for six short words; "Organizations"
   joining the bar and "Coaches" becoming "Partners/Affiliates" added about 165px, which
   overflowed the row between 860 and roughly 1150px and pushed the CTA off the edge. The
   gap and the type close up first, in two steps, because a nav that hides a link on a
   laptop hides it for good - and the 860px rule below is the one place anything is
   allowed to disappear, since the burger replaces it there. */
@media (max-width: 1180px) { .nav-links { gap: 18px; } .nav-links a.plain { font-size: 14.5px; } }
@media (max-width: 1010px) { .nav-links { gap: 13px; } .nav-links a.plain { font-size: 14px; } }
@media (max-width: 860px) { .nav-links a.plain { display: none; } }

/* ============ Mobile nav ============
   Until 2026-08-17 the rule above was the whole mobile navigation story: the
   five pillar links were hidden below 860px and nothing replaced them, so a
   phone visitor -- which on a site for a phone app is most of them -- could
   reach Food logging, Meal plans, Vitals, Free vs Premium and Compare only by
   scrolling to the footer.

   A <details> disclosure rather than a scripted menu, because the site has no
   build step and this keeps the header working with JavaScript off. The panel
   carries MORE links than the desktop bar, not fewer: the desktop visitor still
   has the footer sitemap in easy reach and the phone visitor does not. */
.mnav { display: none; position: relative; }
.mnav > summary {
  list-style: none; cursor: pointer; width: 44px; height: 44px; margin-right: -10px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 12px; color: var(--ink); transition: background .15s;
}
.mnav > summary::-webkit-details-marker { display: none; }
.mnav > summary:hover { background: rgba(108,59,255,.07); }
.mnav[open] > summary { background: rgba(108,59,255,.10); color: var(--purple-deep); }
/* The two glyphs are one <svg> each; the open state swaps which is shown, so
   the control reads as a toggle rather than a button that only ever opens. */
.mnav .mnav-close, .mnav[open] .mnav-open { display: none; }
.mnav[open] .mnav-close { display: block; }
.mnav-panel {
  position: absolute; right: -24px; top: calc(100% + 14px); z-index: 70;
  min-width: 244px; padding: 10px;
  background: var(--card); border: 1px solid rgba(20,33,61,.10);
  border-radius: 16px; box-shadow: 0 12px 40px rgba(20,33,61,.16);
}
.mnav-panel a {
  display: block; padding: 11px 14px; border-radius: 10px;
  font-size: 15.5px; font-weight: 600; color: var(--ink-soft); text-decoration: none;
}
.mnav-panel a:hover { background: rgba(108,59,255,.06); color: var(--purple-deep); }
.mnav-panel a[aria-current="page"] { color: var(--purple); background: rgba(108,59,255,.06); }
.mnav-sep { height: 1px; background: rgba(20,33,61,.09); margin: 8px 12px; }
.mnav-panel .mnav-cta {
  background: linear-gradient(135deg, var(--purple) 0%, var(--purple-deep) 100%);
  color: #fff; text-align: center; margin-top: 4px; font-weight: 700;
}
.mnav-panel .mnav-cta:hover { color: #fff; background: var(--purple-deep); }
@media (max-width: 860px) { .mnav { display: block; } }

/* ============ Hero ============ */
.hero { position: relative; padding: 72px 0 40px; overflow: hidden; }
.hero::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(600px 400px at 85% 10%, rgba(0, 201, 216, .12), transparent 65%),
    radial-gradient(700px 500px at 5% 80%, rgba(108, 59, 255, .08), transparent 65%);
}
.hero-grid { position: relative; display: grid; grid-template-columns: 1.05fr .95fr; gap: 48px; align-items: center; }
.eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  background: rgba(0, 201, 216, .14); color: #155E75;
  font-size: 13px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  padding: 7px 16px; border-radius: 999px; margin-bottom: 22px;
}
h1 {
  font-size: clamp(38px, 5.4vw, 58px); font-weight: 800; line-height: 1.08;
  letter-spacing: -.03em; margin-bottom: 20px;
}
h1 .accent { color: var(--purple); }
.sub {
  font-size: clamp(17px, 2vw, 20px); color: var(--ink-soft);
  max-width: 34em; margin-bottom: 32px;
}
.store-row { display: flex; flex-wrap: wrap; gap: 14px; margin-bottom: 18px; }
/* The line under the store badges. It exists because the single most common way
   a TestFlight public link fails is not a broken link: someone without TestFlight
   taps Install TestFlight, lands in the App Store, then opens TestFlight from the
   home screen instead of coming back here. An empty TestFlight offers exactly one
   thing -- redeem an invitation code -- and a public link has no code to give, so
   the tester is stuck asking for something that does not exist. Two sentences here
   cost nothing and answer it before it happens. */
.tf-note { margin: -8px 0 18px; font-size: 12.5px; line-height: 1.55; color: var(--ink-faint); max-width: 46ch; }
/* The final CTA sits on the purple gradient, so ink-faint would be unreadable. */
.final-cta .tf-note { color: rgba(255,255,255,.75); max-width: 52ch; margin-left: auto; margin-right: auto; }

/* A ghost button on the purple band was invisible: 1.07 to 1.45 against the gradient,
   the worst contrast on the site by some distance. Two .btn-ghost rules exist and the
   later one paints --ink-soft, which is dark slate, onto a dark violet band. The rule
   that fixed link contrast on this band deliberately excluded .btn
   (`.final-cta a:not(.btn)`), so the buttons were never covered by it.
   Cream measures 6.79 at the lightest end of the gradient and 10.47 at the darkest. */
.final-cta .btn-ghost {
  color: #FFFFFF;
  border-color: rgba(254, 250, 234, .55);
  background: transparent;
}
.final-cta .btn-ghost:hover,
.final-cta .btn-ghost:focus-visible {
  color: #FFFFFF;
  border-color: #FFFFFF;
  background: rgba(254, 250, 234, .12);
}
.final-cta .btn-ghost:focus-visible { outline: 3px solid #FFFFFF; outline-offset: 2px; }
.quiz-link {
  display: inline-flex; align-items: center; gap: 8px;
  font-weight: 700; font-size: 15px; color: var(--purple-deep);
  text-decoration: none; border-bottom: 2px solid rgba(108,59,255,.25);
  padding-bottom: 2px; transition: border-color .15s;
}
.quiz-link:hover { border-color: var(--purple); }
.hero-note { margin-top: 20px; font-size: 13.5px; color: var(--ink-faint); display: flex; align-items: center; gap: 8px; }
.phone-stage { position: relative; display: flex; justify-content: center; align-items: center; padding: 20px 0; }
.hero-shot {
  height: auto; width: 262px; max-width: 80%; border-radius: 34px;
  border: 1px solid rgba(20,33,61,.14);
  box-shadow: 0 26px 52px rgba(20,33,61,.22), 0 8px 20px rgba(20,33,61,.14);
  transform: rotate(2deg);
}
@media (prefers-reduced-motion: reduce) { .hero-shot { transform: none; } }

/* Breadcrumbs — pillar pages only. */
.crumbs { font-size: 13.5px; color: var(--ink-faint); padding: 18px 0 0; }
.crumbs ol { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; }
.crumbs li::after { content: "/"; margin-left: 8px; color: rgba(20,33,61,.28); }
.crumbs li:last-child::after { content: ""; }
.crumbs a { color: var(--purple-deep); text-decoration: none; font-weight: 600; }
.crumbs a:hover { text-decoration: underline; }

/* ============ Trust bar ============ */
.trust { border-top: 1px solid rgba(20,33,61,.06); border-bottom: 1px solid rgba(20,33,61,.06); background: rgba(255,255,255,.5); }
.trust-row { display: flex; flex-wrap: wrap; justify-content: center; gap: 16px 44px; padding: 22px 0; }
.trust-item { display: flex; align-items: center; gap: 9px; font-size: 14.5px; font-weight: 600; color: var(--ink-soft); }

/* ============ Sections ============ */
section { padding: 84px 0; }
.section-head { text-align: center; max-width: 680px; margin: 0 auto 52px; }
.kicker { display: inline-block; font-size: 13px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--purple); margin-bottom: 12px; }
h2 { font-size: clamp(28px, 3.6vw, 40px); font-weight: 800; letter-spacing: -.025em; line-height: 1.15; margin-bottom: 14px; }
.section-head p { color: var(--ink-soft); font-size: 17px; }
.tint { background: linear-gradient(180deg, rgba(108,59,255,.04), transparent 40%); }

/* ============ Stat band ============
   Where a competitor site puts "10M users / 4.9 stars", this puts numbers
   that can be counted in the app. No user counts, no star ratings, no
   pounds-lost totals — Loopa is in beta and has none of them to report. */
.stat-band { background: var(--ink); color: #FFFFFF; border-radius: 24px; padding: 38px 34px; }
.stat-band .stat-lead { text-align: center; font-size: 14px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--amber); margin-bottom: 26px; }
.stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 26px; }
.stat { text-align: center; }
.stat b { display: block; font-size: clamp(28px, 4vw, 40px); font-weight: 800; letter-spacing: -.03em; line-height: 1.05; color: #FFFFFF; }
.stat span { display: block; font-size: 14px; color: #AEB7C2; margin-top: 7px; line-height: 1.45; }
@media (max-width: 780px) { .stat-grid { grid-template-columns: repeat(2, 1fr); gap: 24px 18px; } .stat-band { padding: 30px 22px; } }

/* ============ Method grid — the ways to log ============ */
/* Five cards across at full width. They carry one short paragraph each, so ~195px
   a card is enough; below that the count steps down rather than squeezing. */
/* auto-fit with a real minimum, not a hard 5. Five across put each card at ~145px on a
   1500px screen, which broke "Coaches & trainers" and "Creators & influencers" onto two
   lines and ragged every paragraph inside them. This wraps to three-and-two instead, and
   still gives five columns to anyone with the width for it. */
.method-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 18px; }
.method {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); padding: 28px 24px; position: relative;
  transition: transform .2s ease, box-shadow .2s ease;
  display: flex; flex-direction: column;
}
.method:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }
.method-ico { width: 44px; height: 44px; border-radius: 13px; display: flex; align-items: center; justify-content: center; margin-bottom: 16px; }
.method h3 { font-size: 17.5px; font-weight: 800; letter-spacing: -.015em; margin-bottom: 8px; }
.method p { color: var(--ink-soft); font-size: 14px; flex: 1 1 auto; }
.pill {
  display: inline-block; align-self: flex-start; margin-top: 14px;
  font-size: 11px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  padding: 4px 11px; border-radius: 999px;
}
/* Contrast, computed rather than eyeballed. At 11px/800 these are SMALL text under
   WCAG (bold only counts as large from 18.66px), so the bar is 4.5:1 against the
   BLENDED backdrop, not against white. The previous pair measured 4.50 and 4.43 on
   the card surface, i.e. one exactly on the line and one under it, and Lighthouse
   failed both at 4.49/4.42. These are 6.60 and 6.18, which leaves room for the
   backdrop to shift without falling through again. */
.pill-free { background: rgba(74,222,128,.18); color: #12632F; }
.pill-prem { background: rgba(255,122,0,.16); color: #8F4408; }
@media (max-width: 1060px) { .method-grid { grid-template-columns: repeat(3, 1fr); gap: 22px; } }
@media (max-width: 760px) { .method-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .method-grid { grid-template-columns: 1fr; } }

/* ============ Alternating feature rows — pillar pages ============ */
.frow { display: grid; grid-template-columns: 1fr 1fr; gap: 56px; align-items: center; padding: 54px 0; border-top: 1px solid rgba(20,33,61,.08); }
.frow:first-of-type { border-top: 0; padding-top: 18px; }
.frow.flip .frow-media { order: -1; }
.frow-media { display: flex; justify-content: center; }
.frow-media img { width: 250px; height: auto; border-radius: 26px; border: 1px solid rgba(20,33,61,.14); box-shadow: 0 18px 40px rgba(20,33,61,.16); background: #E6ECFA; }
.frow-media.wide img { width: 100%; max-width: 420px; border-radius: 18px; }
.frow h3 { font-size: clamp(22px, 2.6vw, 28px); font-weight: 800; letter-spacing: -.02em; margin-bottom: 12px; }
.frow p { color: var(--ink-soft); font-size: 16px; margin-bottom: 14px; }
.frow ul { list-style: none; display: grid; gap: 10px; margin-top: 16px; }
.frow li { font-size: 15px; line-height: 1.55; color: var(--ink-soft); padding-left: 28px; position: relative; }
.frow li::before {
  content: ""; position: absolute; left: 0; top: 6px; width: 15px; height: 8px;
  border-left: 2.5px solid var(--purple-deep); border-bottom: 2.5px solid var(--purple-deep); transform: rotate(-45deg);
}
@media (max-width: 900px) {
  .frow { grid-template-columns: 1fr; gap: 30px; padding: 40px 0; }
  .frow.flip .frow-media { order: 0; }
}

/* ============ How it works ============ */
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
.step-card {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); padding: 32px 28px; position: relative;
  transition: transform .2s ease, box-shadow .2s ease;
}
.step-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }
/* The coach page's steps carry the same weight as the install steps on /download/:
   the numeral is what the eye resolves first, the words second. */
.steps .step-num { width: 44px; height: 44px; font-size: 21px; font-weight: 900;
  display: flex; align-items: center; justify-content: center; border-radius: 50%;
  font-variant-numeric: tabular-nums; margin-bottom: 14px; }
.step-num {
  width: 44px; height: 44px; border-radius: 14px; display: flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 18px; margin-bottom: 18px;
}
.step-card h3 { font-size: 20px; font-weight: 800; letter-spacing: -.015em; margin-bottom: 10px; }
.step-card p { color: var(--ink-soft); font-size: 15.5px; }

/* ============ Feature grid ============ */
.features { background: linear-gradient(180deg, rgba(108,59,255,.04), transparent 40%); }
.feat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; }
.feat-grid.two { grid-template-columns: repeat(2, 1fr); gap: 24px; }
.feat-card {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); padding: 30px 26px;
  transition: transform .2s ease, box-shadow .2s ease;
  display: flex; flex-direction: column;
}
.feat-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }
.feat-icon { width: 52px; height: 52px; border-radius: 16px; display: flex; align-items: center; justify-content: center; margin-bottom: 18px; }
.feat-tag {
  display: inline-block; align-self: flex-start; font-size: 11px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  padding: 4px 12px; border-radius: 999px; margin-bottom: 12px;
}
.feat-card h3 { font-size: 19px; font-weight: 800; letter-spacing: -.015em; margin-bottom: 9px; }
.feat-card p { color: var(--ink-soft); font-size: 15px; flex: 1 1 auto; }
.feat-card a.more { margin-top: 15px; font-size: 14.5px; font-weight: 700; color: var(--purple-deep); text-decoration: none; border-bottom: 2px solid rgba(108,59,255,.22); align-self: flex-start; padding-bottom: 1px; }
.feat-card a.more:hover { border-color: var(--purple); }
@media (max-width: 980px) { .feat-grid, .feat-grid.two { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px) { .feat-grid, .feat-grid.two { grid-template-columns: 1fr; } }

/* ============ FAQ ============ */
.faq-list { max-width: 780px; margin: 0 auto; display: grid; gap: 14px; }
details {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); overflow: hidden;
}
summary {
  list-style: none; cursor: pointer; padding: 22px 26px;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
summary::-webkit-details-marker { display: none; }
summary h3 { font-size: 17.5px; font-weight: 700; letter-spacing: -.01em; }
.chev { flex-shrink: 0; transition: transform .25s ease; color: var(--purple); }
details[open] .chev { transform: rotate(180deg); }
.faq-answer { padding: 0 26px 24px; color: var(--ink-soft); font-size: 15.5px; max-width: 62em; }
.faq-answer + .faq-answer { padding-top: 0; }
.faq-answer a { color: var(--purple-deep); }

/* ============ Final CTA ============ */
.final-cta {
  background: linear-gradient(135deg, var(--purple-deep) 0%, var(--purple) 55%, #6D28D9 100%);
  border-radius: 28px; padding: 64px 40px; text-align: center; color: #fff;
  position: relative; overflow: hidden;
}
.final-cta::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(500px 300px at 80% 0%, rgba(0,201,216,.25), transparent 60%);
}
.final-cta > * { position: relative; }
/* A primary button inside the purple band was a purple gradient on purple: the one
   action the section exists for, and it was the least visible thing in it. The home
   page never hit this because its closing band carries store badges, which are ink.
   Inverted here rather than changing .btn-primary, which is correct everywhere else. */
.final-cta .btn-primary {
  background: #E6ECFA; color: var(--purple-deep);
  box-shadow: 0 8px 24px rgba(15,23,42,.28);
}
.final-cta .btn-primary:hover { background: #fff; box-shadow: 0 12px 30px rgba(15,23,42,.34); }
.final-cta h2 { color: #fff; }
.final-cta p { color: rgba(255,255,255,.85); font-size: 17px; max-width: 36em; margin: 0 auto 32px; }
.final-cta .store-badge { background: rgba(255,255,255,.1); border-color: rgba(255,255,255,.25); }
.final-cta .store-badge:hover { background: rgba(255,255,255,.16); }

/* ============ Footer ============ */
footer { background: var(--ink); color: #CBD5E1; padding: 60px 0 32px; margin-top: 96px; }
.footer-top { display: grid; grid-template-columns: 1.5fr 2.6fr; gap: 48px; margin-bottom: 40px; }
.footer-brand p { font-size: 14.5px; color: #94A3B8; margin-top: 14px; max-width: 30em; }
.footer-badges { display: grid; gap: 12px; justify-items: start; margin-top: 22px; }
.footer-badges .store-badge { background: rgba(255,255,255,.06); min-height: 54px; padding: 9px 18px 9px 15px; }
.sitemap { display: grid; grid-template-columns: repeat(4, 1fr); gap: 34px 26px; }
footer h4, footer .foot-h { color: #fff; font-size: 13px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; margin-bottom: 15px; }
.footer-links { list-style: none; display: grid; gap: 10px; }
.footer-links a { text-decoration: none; font-size: 14.5px; color: #94A3B8; transition: color .15s; }
.footer-links a:hover { color: var(--mint); }
.footer-bottom {
  border-top: 1px solid rgba(255,255,255,.09); padding-top: 26px;
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px;
  /* #64748B measured 3.07:1 on the #14213D footer -- a fail at any text size.
     #A0AEC0 is 6.49:1 and still reads as the quiet line it is meant to be. This
     block is on all 34 pages, so it was 34 pages failing on one declaration. */
  font-size: 13.5px; color: #A0AEC0;
}
.footer-bottom a { color: #CBD5E1; text-decoration: underline; text-underline-offset: 3px; }
/* The legal row sat at roughly 15px tall, under the 24px minimum a touch target needs,
   with the separators putting the neighbours inside each other's hit area. Padding is
   enough on its own — inline-block is what makes the block padding count. */
.footer-bottom a, .footer-bottom .ck-link { display: inline-block; padding: 5px 2px; }
@media (max-width: 900px) { .footer-top { grid-template-columns: 1fr; gap: 34px; } .sitemap { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .sitemap { grid-template-columns: 1fr; } }

/* "Not checked" in the comparison table. Was an inline #94A3B8 on white, 2.56:1 --
   the worst contrast on the site, and inline so no stylesheet audit would ever
   catch it. #556575 is 5.99:1 and still clearly the quietest cell in the row. */
.cmp-unknown { color: #556575; }

/* ============ Contact hub ============
   Scoped .wz-form .ct-route, not .ct-route. The wizard's own `.wz-form label`
   (display:block) and `.cf-row > label` (flex-basis:220px) are both 0,0,1,1 and both
   sit later in the file, so the unscoped class lost every declaration that mattered
   and the routing choices rendered as bare browser radios with the label text run
   together. Two class selectors is 0,0,2,0 and wins on specificity rather than order.
   Prefixed ct- rather than cf-. The cf- set belongs to the coach wizard and .cf-opt
   there is the small "optional" tag next to a field label, so reusing that name for a
   routing choice would have restyled the wizard from a page it has nothing to do with. */
.wz-form fieldset.cf-row { border: 0; padding: 0; margin: 0 0 24px; }
.wz-form fieldset.cf-row legend { padding: 0; margin-bottom: 10px; }
.wz-form .ct-route {
  display: flex; gap: 12px; align-items: flex-start;
  flex: 1 1 100%; padding: 14px 16px; margin: 0;
  border: 1.5px solid rgba(20,33,61,.14); border-radius: 12px;
  background: var(--card); cursor: pointer;
  transition: border-color .15s, background .15s;
}
.wz-form .ct-route:hover { border-color: var(--purple); }
.wz-form .ct-route input { margin-top: 3px; flex: 0 0 auto; width: 18px; height: 18px; accent-color: var(--purple-deep); }
.wz-form .ct-route span { display: block; }
.wz-form .ct-route strong { display: block; font-size: 15px; color: var(--ink); }
.wz-form .ct-route em { display: block; font-style: normal; font-size: 13.5px; line-height: 1.55; color: var(--ink-soft); margin-top: 2px; }
.wz-form .ct-route:has(input:checked) { border-color: var(--purple); background: rgba(108,59,255,.04); }
.wz-form .ct-route:focus-within { outline: 3px solid var(--purple); outline-offset: 2px; }

.ct-note { margin-top: 14px; font-size: 13.5px; color: var(--ink-soft); }
.ct-alt { margin-top: 40px; padding-top: 28px; border-top: 1px solid rgba(20,33,61,.1); }
.ct-alt h2 { font-size: 20px; margin-bottom: 10px; }
.ct-alt p { font-size: 15px; line-height: 1.65; color: var(--ink-soft); margin-top: 8px; }
.ct-addr { font-size: 13.5px; color: var(--ink-faint); margin-top: 18px !important; }

/* A button that has to sit in a row of links without looking like a stranger. */
.ck-link {
  background: none; border: 0; padding: 0; margin: 0;
  font: inherit; color: inherit; cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px;
}
.ck-link:hover { color: var(--mint, #CBD5E1); }
.ck-link:focus-visible { outline: 3px solid var(--purple); outline-offset: 2px; }

/* ============ Cookie preferences ============
   A bottom sheet rather than a full-screen interstitial: the policy promises a choice,
   not a toll gate, and blocking the page to collect one is the pattern regulators keep
   naming. Reopenable from the footer on every page, because a preference you cannot
   revisit is not a preference. */
.ck {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  display: flex; justify-content: center;
  padding: 16px; padding-bottom: max(16px, env(safe-area-inset-bottom));
  pointer-events: none;
}
.ck-box {
  pointer-events: auto;
  width: 100%; max-width: 560px;
  background: var(--card); color: var(--ink);
  border: 1px solid rgba(20,33,61,.14); border-radius: 16px;
  box-shadow: 0 18px 48px rgba(15,23,42,.22);
  padding: 20px 22px;
}
.ck-h { font-size: 18px; margin: 0 0 6px; }
.ck-p { font-size: 14px; line-height: 1.6; color: var(--ink-soft); margin: 0 0 14px; }
.ck-rows { display: flex; flex-direction: column; gap: 10px; margin-bottom: 16px; }
.ck-row { display: flex; gap: 10px; align-items: flex-start; cursor: pointer; margin: 0; }
.ck-row input { margin-top: 3px; width: 18px; height: 18px; flex: 0 0 auto; accent-color: var(--purple-deep); }
.ck-row input:disabled { cursor: not-allowed; }
.ck-row-txt strong { display: block; font-size: 14.5px; }
.ck-row-txt em { display: block; font-style: normal; font-size: 13px; line-height: 1.5; color: var(--ink-soft); margin-top: 1px; }
.ck-acts { display: flex; gap: 10px; flex-wrap: wrap; }
.ck-btn {
  flex: 1 1 auto; min-height: 44px; padding: 10px 18px;
  font-family: var(--font); font-size: 15px; font-weight: 700;
  border-radius: 12px; cursor: pointer;
  background: transparent; border: 1.5px solid #CBD5E1; color: var(--ink-soft);
}
.ck-btn:hover { border-color: var(--purple); color: var(--purple-deep); }
.ck-btn--primary {
  background: linear-gradient(135deg, var(--purple) 0%, var(--purple-deep) 100%);
  border-color: transparent; color: #FFFFFF;
}
.ck-btn:focus-visible { outline: 3px solid var(--purple); outline-offset: 2px; }
.ck-more { margin: 14px 0 0; font-size: 13px; }
.ck-more a { color: var(--purple-deep); display: inline-block; padding: 5px 0; }
@media (max-width: 520px) { .ck-box { padding: 18px; } }

/* ============ Scroll reveal ============ */
@media (prefers-reduced-motion: no-preference) {
  .js .reveal { opacity: 0; transform: translateY(22px); transition: opacity .6s ease, transform .6s ease; }
  .js .reveal.in { opacity: 1; transform: none; }
  .js .reveal:nth-child(2) { transition-delay: .1s; }
  .js .reveal:nth-child(3) { transition-delay: .2s; }
  .js .reveal:nth-child(4) { transition-delay: .3s; }
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* ============ Android direct download ============ */
.dl-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; margin-top: 30px; align-items: stretch; }
.dl-card { background: #fff; border: 1px solid rgba(20,33,61,.12); border-radius: 20px; padding: 28px; display: flex; flex-direction: column; }
.dl-card h3 { font-size: 19px; font-weight: 800; letter-spacing: -.02em; margin-bottom: 6px; }
.dl-card .dl-meta { font-size: 13px; color: var(--ink-faint); margin-bottom: 16px; }
.dl-btn { display: inline-flex; align-items: center; gap: 10px; background: #4A1FD6; color: #FFFFFF; font-weight: 700;
          font-size: 16px; padding: 13px 24px; border-radius: 14px; text-decoration: none; transition: background .15s; }
.dl-btn:hover { background: #3d1778; }
.dl-steps { counter-reset: step; margin-top: 18px; flex: 1 1 auto; }
.dl-steps li { list-style: none; counter-increment: step; position: relative; padding-left: 34px; margin-bottom: 12px; font-size: 14.5px; line-height: 1.65; color: var(--ink-soft); }
.dl-steps li::before { content: counter(step); position: absolute; left: 0; top: 1px; width: 23px; height: 23px; border-radius: 50%;
                       background: #FF7A00; color: #14213D; font-size: 12.5px; font-weight: 800; display: flex; align-items: center; justify-content: center; }
.dl-note { margin-top: auto; padding: 14px 16px; background: #FFF1E5; border: 1px solid rgba(255,122,0,.4); border-radius: 12px; font-size: 13.5px; line-height: 1.6; color: #14213D; }
.dl-hash { margin-top: 14px; font-size: 11.5px; color: var(--ink-faint); word-break: break-all; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.dl-head { display: flex; align-items: center; gap: 14px; margin-bottom: 4px; }
.dl-mark { width: 46px; height: 46px; border-radius: 12px; display: flex; align-items: center; justify-content: center; flex: 0 0 46px; }
.dl-mark.ios { background: #14213D; color: #FFFFFF; }
.dl-mark.droid { background: #4A1FD6; color: #FFFFFF; }
@media (max-width: 900px) { .dl-grid { grid-template-columns: 1fr; } }

/* ============ Free / Premium tiers ============ */
.tiers { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; margin-top: 34px; align-items: stretch; }
/* Three tiers since the 2026-08-16 price split: Free, Premium, Premium Family.
   A third card in the 1fr-1fr grid would sit alone on a second row at half
   width, so the count is declared on the element rather than assumed. Narrower
   than 1100px it drops to two columns before the shared 900px single-column
   rule takes over — three 30px-padded cards side by side stop being readable
   well before the tablet breakpoint. */
.tiers.three { grid-template-columns: 1fr 1fr 1fr; }
@media (max-width: 1100px) { .tiers.three { grid-template-columns: 1fr 1fr; } }
.tier { background: #fff; border: 1px solid rgba(20,33,61,.12); border-radius: 22px; padding: 30px; position: relative; display: flex; flex-direction: column; }
.tier.free { border: 2px solid #4A1FD6; }
.tier-flag { position: absolute; top: -13px; left: 30px; background: #4A1FD6; color: #FFFFFF; font-size: 12px;
             font-weight: 800; letter-spacing: .06em; text-transform: uppercase; padding: 6px 14px; border-radius: 100px; }
.tier-more { color: #4A1FD6; font-weight: 700; display: inline-block; padding: 4px 0; }
.tier h2, .tier h3 { font-size: 22px; font-weight: 800; letter-spacing: -.02em; margin-bottom: 2px; }
.tier-price { font-size: 38px; font-weight: 800; letter-spacing: -.03em; color: #4A1FD6; line-height: 1.1; margin: 10px 0 2px; }
.tier-price small { font-size: 15px; font-weight: 600; color: var(--ink-faint); letter-spacing: 0; }
/* Four subscriptions, four prices. Both cadences are stated AS prices rather
   than one headline with the other buried in the note under it -- a buyer
   comparing plans is comparing four numbers, and they should all be legible
   at the same glance. Wraps on narrow screens rather than shrinking. */
.price-pair { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 18px; margin: 10px 0 2px; }
.price-pair .tier-price { margin: 0; }
.price-pair .tier-price.alt { color: var(--ink-soft); }
.price-pair .tier-price.alt::before { content: "or"; font-size: 14px; font-weight: 600;
   color: var(--ink-faint); letter-spacing: 0; margin-right: 6px; }
.tier-note { font-size: 13.5px; color: var(--ink-faint); margin-bottom: 20px; }
/* align-content:start matters once the two cards have different list lengths.
   The ul is a flex child with flex:1 1 auto so both cards' CTAs land on one
   plane, which makes the shorter card's ul taller than its rows need; a grid
   with the default align-content then stretches those rows and the free tier
   reads as double-spaced next to Premium. */
.tier ul { list-style: none; display: grid; gap: 11px; flex: 1 1 auto; align-content: start; }
.tier li { font-size: 15px; line-height: 1.55; color: var(--ink-soft); padding-left: 28px; position: relative; }
.tier li::before { content: ""; position: absolute; left: 0; top: 6px; width: 16px; height: 9px;
                   border-left: 2.5px solid #4A1FD6; border-bottom: 2.5px solid #4A1FD6; transform: rotate(-45deg); }
.tier.prem li::before { border-color: #FF7A00; }
.tier-cta { display: block; text-align: center; margin-top: auto; background: #4A1FD6; color: #FFFFFF;
            font-weight: 700; font-size: 16px; padding: 14px 20px; border-radius: 14px; text-decoration: none; }
.tier-cta:hover { background: #3d1778; }
.tier.prem .tier-cta { background: transparent; color: #4A1FD6; border: 1.5px solid rgba(74,31,214,.35); }
.tier-foot { margin-top: 26px; font-size: 14px; color: var(--ink-faint); text-align: center; }
/* .tiers.three is two classes; this rule was one, so at 900px and below the
   three-tier grid never collapsed however narrow the screen got. The comment above
   says it drops "before the shared 900px single-column", and it never did: at 375px
   three cards were laying out 440px wide inside a 327px column, saved from being a
   sideways scroll only by overflow-x:hidden on body. Matching the specificity is the
   fix; raising the other rule's would only move the problem. */
@media (max-width: 900px) {
  .tiers,
  .tiers.three { grid-template-columns: 1fr; }
}

/* ============ Carousel ============ */
.car { position: relative; margin-top: 26px; }
.car-track { display: flex; gap: 26px; overflow-x: auto; scroll-snap-type: x mandatory;
             scroll-behavior: smooth; padding: 8px 4px 24px; scrollbar-width: none; }
.car-track::-webkit-scrollbar { display: none; }
/* Slide width and the screenshot aspect ratio are declared once here so the
   arrow offset below can be derived from them. It used to be a bare top:190px,
   which was correct for exactly these dimensions and would have drifted
   silently the first time either changed. */
.car { --car-slide-w: 252px; --car-shot-h: calc(var(--car-slide-w) * 1792 / 828); }
.car-slide { flex: 0 0 var(--car-slide-w); scroll-snap-align: center; }
.car-slide img { width: 100%; height: auto; border-radius: 26px; border: 1px solid rgba(20,33,61,.14);
                 box-shadow: 0 18px 40px rgba(20,33,61,.16); display: block; background: #E6ECFA; }
.car-slide h3 { font-size: 16px; font-weight: 800; letter-spacing: -.015em; margin: 16px 0 5px; }
.car-slide p { font-size: 14px; line-height: 1.6; color: var(--ink-soft); }
/* Amber, the brand's fourth color and the same one the app's add button uses.
   The chevron is Midnight, not white: Midnight on Amber is the sanctioned
   pairing (~8:1), where white on Amber is about 2:1 and unreadable. */
.car-btn { position: absolute; top: calc(var(--car-shot-h) / 2 - 23px); width: 46px; height: 46px; border-radius: 50%; border: 1px solid rgba(20,33,61,.14);
           background: #FF7A00; color: #14213D; display: flex; align-items: center; justify-content: center; cursor: pointer;
           box-shadow: 0 6px 18px rgba(255,122,0,.42); z-index: 2; transition: transform .12s, background .15s, opacity .15s; }
.car-btn:hover:not(:disabled) { transform: scale(1.06); background: #FBBF24; }
.car-btn:disabled { opacity: .34; cursor: default; transform: none; }
.car-prev { left: -14px; } .car-next { right: -14px; }
/* The dot you see is 9px, but the thing you tap is 24px. Painting the dot on a
   pseudo-element separates the two, so the target meets the minimum without the pager
   turning into a row of large circles. Fifteen 24px targets do not fit one line on a
   360px phone, hence the wrap. */
.car-dots { display: flex; flex-wrap: wrap; justify-content: center; gap: 2px; margin-top: 6px; }
.car-dot { width: 24px; height: 24px; border: 0; padding: 0; cursor: pointer;
           background: transparent; display: grid; place-items: center; }
.car-dot::before { content: ""; display: block; width: 9px; height: 9px; border-radius: 50%;
           background: rgba(74,31,214,.24); transition: background .15s, width .15s; }
.car-dot[aria-current="true"]::before { background: #4A1FD6; width: 20px; border-radius: 100px; }
@media (max-width: 900px) { .car-btn { display: none; } }

/* ============ iPad strip ============ */
.ipad-strip { display: flex; gap: 22px; overflow-x: auto; scroll-snap-type: x mandatory;
              padding: 8px 4px 20px; margin-top: 26px; scrollbar-width: none;
              -webkit-overflow-scrolling: touch; }
.ipad-strip::-webkit-scrollbar { display: none; }
.ipad-shot { flex: 0 0 320px; scroll-snap-align: center; }
.ipad-shot img { width: 100%; height: auto; border-radius: 18px; display: block;
                 background: #E6ECFA; border: 1px solid rgba(20,33,61,.14);
                 box-shadow: 0 18px 40px rgba(20,33,61,.16); }
.ipad-shot figcaption { margin-top: 13px; font-size: 14px; font-weight: 700; color: var(--ink-soft); text-align: center; }
@media (max-width: 600px) { .ipad-shot { flex: 0 0 250px; } }

/* ============ Comparison table ============ */
.cmp-wrap { overflow-x: auto; margin-top: 30px; -webkit-overflow-scrolling: touch; }
.cmp { width: 100%; border-collapse: separate; border-spacing: 0; min-width: 760px; background: #fff;
       border: 1px solid rgba(20,33,61,.12); border-radius: 18px; overflow: hidden; }
.cmp th, .cmp td { padding: 15px 16px; text-align: left; font-size: 14.5px; border-bottom: 1px solid rgba(20,33,61,.08); }
.cmp thead th { background: #FFF1E5; font-size: 13px; font-weight: 800; letter-spacing: .02em; color: #14213D; }
.cmp thead th.us { background: #4A1FD6; color: #FFFFFF; }
.cmp td:first-child, .cmp th:first-child { font-weight: 700; color: var(--ink); }
.cmp td.us { background: rgba(74,31,214,.05); font-weight: 650; }
.cmp tbody th[scope="rowgroup"] {
  background: #F8FAFC; font-size: 12px; font-weight: 800; letter-spacing: .07em;
  text-transform: uppercase; color: var(--ink-faint); padding: 11px 16px;
}
.cmp tr:last-child td { border-bottom: 0; }
.cmp-note { margin-top: 14px; font-size: 13px; color: var(--ink-faint); line-height: 1.65; }
.cmp-note a { color: var(--purple-deep); }

/* ============ Purple call-out strip ============ */
.only-strip { background: #4A1FD6; color: #FFFFFF; border-radius: 20px; padding: 26px 30px; margin-top: 30px; }
.only-title { font-size: 17px; font-weight: 800; letter-spacing: -.015em; margin-bottom: 14px; color: #FFFFFF; }
.only-strip p { font-size: 15px; line-height: 1.65; color: rgba(254,250,234,.92); margin-bottom: 14px; }
.only-strip p:last-child { margin-bottom: 0; }
.only-strip strong { color: #FCD34D; }
.only-list { list-style: none; display: grid; grid-template-columns: 1fr 1fr; gap: 10px 26px; }
.only-list li { font-size: 14.5px; line-height: 1.55; padding-left: 26px; position: relative; color: rgba(254,250,234,.92); }
.only-list li::before { content: ""; position: absolute; left: 0; top: 6px; width: 14px; height: 8px;
                        border-left: 2.5px solid #FF7A00; border-bottom: 2.5px solid #FF7A00; transform: rotate(-45deg); }
@media (max-width: 760px) { .only-list { grid-template-columns: 1fr; } .only-strip { padding: 22px 20px; } }

/* ============ Sticky mobile CTA ============ */
.sticky-cta { position: fixed; left: 0; right: 0; bottom: 0; z-index: 60; display: none;
              gap: 10px; padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
              background: rgba(255,255,255,.94); backdrop-filter: blur(12px);
              border-top: 1px solid rgba(20,33,61,.12); box-shadow: 0 -6px 24px rgba(20,33,61,.10); }
.sticky-cta a { flex: 1; text-align: center; font-size: 15px; font-weight: 700; padding: 13px 10px;
                border-radius: 13px; text-decoration: none; }
.sticky-cta .s-ios { background: #4A1FD6; color: #FFFFFF; }
.sticky-cta .s-and { background: #FF7A00; color: #14213D; }
@media (max-width: 900px) { .sticky-cta { display: flex; } body { padding-bottom: 76px; } }
/* The install bar and the cookie banner are both fixed to bottom:0, so on a phone the
   bar sat underneath the banner and its hit area swallowed the "Read the cookie notice"
   link. Consent is the decision that comes first; the bar waits its turn. */
body.ck-open .sticky-cta { display: none; }
body.ck-open { padding-bottom: 0; }

/* ============ Privacy panel ============ */
.priv { background: #14213D; color: #E5E7EB; border-radius: 24px; padding: 44px 40px; margin-top: 8px; }
.priv h2 { color: #fff; }
.priv > p { color: #B6BEC9; max-width: 44em; }
.priv-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 26px; margin-top: 30px; }
.priv-item h3 { color: #fff; font-size: 16px; font-weight: 800; margin-bottom: 7px; letter-spacing: -.01em; }
.priv-item p { font-size: 14.5px; line-height: 1.65; color: #AEB7C2; }
.priv-ico { width: 38px; height: 38px; border-radius: 11px; background: rgba(255,122,0,.16); color: #FF7A00;
            display: flex; align-items: center; justify-content: center; margin-bottom: 13px; }
@media (max-width: 860px) { .priv-grid { grid-template-columns: 1fr; } .priv { padding: 34px 24px; } }

/* ============ Beta offer banner ============ */
.offer { background: linear-gradient(135deg,#4A1FD6 0%,#6D28D9 100%); color: #FFFFFF;
         border-radius: 22px; padding: 30px 34px; margin-bottom: 30px; display: flex; gap: 26px; align-items: center; }
.offer-badge { flex: 0 0 auto; background: #FF7A00; color: #14213D; font-size: 12px; font-weight: 800;
               letter-spacing: .07em; text-transform: uppercase; padding: 8px 15px; border-radius: 100px; white-space: nowrap; }
.offer h3 { font-size: 23px; font-weight: 800; letter-spacing: -.02em; margin-bottom: 8px; color: #FFFFFF; line-height: 1.25; }
.offer p { font-size: 15px; line-height: 1.65; color: rgba(254,250,234,.90); margin: 0; }
.offer strong { color: #FCD34D; }
@media (max-width: 760px) { .offer { flex-direction: column; align-items: flex-start; gap: 16px; padding: 26px 22px; }
                            .offer h3 { font-size: 20px; } }

/* ============ Cross-links between pillar pages ============ */
/* auto-fit rather than a hard repeat(3): a fourth card used to land alone on a second
   row at a third of the width, and the fix for that is not a .xlinks.four modifier --
   that is the shape of the .tiers.three specificity bug, where a two-class rule outsat
   the one-class breakpoint and the grid never collapsed. auto-fit collapses the empty
   tracks, so three cards still render as three columns and four render as four. */
.xlinks { display: grid; grid-template-columns: repeat(auto-fit, minmax(232px, 1fr)); gap: 18px; margin-top: 12px; }
.xlink { background: var(--card); border: 1px solid var(--border); border-radius: 14px; box-shadow: var(--shadow-sm);
         padding: 20px 22px; text-decoration: none; display: block; transition: transform .18s ease, box-shadow .18s ease; }
.xlink:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
.xlink b { display: block; font-size: 16px; font-weight: 800; letter-spacing: -.015em; margin-bottom: 5px; color: var(--ink); }
.xlink span { font-size: 14px; color: var(--ink-soft); }
@media (max-width: 860px) { .xlinks { grid-template-columns: 1fr; } }

/* ============ Prose — long-form copy blocks ============ */
.prose p { font-size: 16.5px; line-height: 1.75; color: var(--ink-soft); margin-bottom: 18px; }
.prose h2, .prose h3 { font-size: 21px; font-weight: 800; letter-spacing: -.02em; margin: 32px 0 12px; color: var(--ink); }
.prose strong { color: var(--ink); }
.prose a { color: var(--purple-deep); }

/* ============ Responsive ============ */
@media (max-width: 900px) {
  .hero-grid { grid-template-columns: 1fr; gap: 40px; text-align: center; }
  .hero-grid .sub { margin-left: auto; margin-right: auto; }
  .store-row { justify-content: center; }
  .steps { grid-template-columns: 1fr; }
}
@media (max-width: 520px) {
  section { padding: 60px 0; }
  .store-row { flex-direction: column; align-items: stretch; }
  .store-badge { justify-content: center; }
  .final-cta { padding: 48px 24px; }
}

/* ============ Lead capture ============
   The form that catches the visitor who is interested but is not going to
   sideload an APK tonight. It sits BELOW the two download cards on purpose:
   anyone ready to install is still one tap from installing, and this picks up
   the rest rather than standing between them and the button.

   min-height matches the form's own data-height. The vendor iframe ships with
   height:100%, which in normal flow resolves to nothing until form_embed.js
   measures and resizes it -- so without a reserved box the whole section below
   jumps once the script lands. Every image on this site declares its dimensions
   for the same reason; an iframe is no different. */
.capture {
  background: var(--card); border: 1px solid rgba(20,33,61,.12); border-radius: 22px;
  padding: 30px 32px; margin-top: 26px;
}
.capture-head { max-width: 62ch; margin-bottom: 6px; }
.capture h3 { font-size: 22px; font-weight: 800; letter-spacing: -.02em; margin-bottom: 8px; }
.capture-head p { color: var(--ink-soft); font-size: 15.5px; }
.capture-frame { position: relative; min-height: 643px; margin-top: 4px; }
.capture-frame iframe { display: block; width: 100%; min-height: 643px; border: 0; border-radius: 10px; }
@media (max-width: 640px) { .capture { padding: 24px 18px; border-radius: 18px; } }

/* ============ Footer social ============ */
.footer-social { display: flex; gap: 10px; margin-top: 20px; }
.footer-social a {
  width: 38px; height: 38px; border-radius: 11px; display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,.06); color: #CBD5E1; transition: background .15s, color .15s;
}
.footer-social a:hover { background: rgba(0,201,216,.16); color: var(--mint); }

/* ============ Chat widget clearance ============
   The LeadConnector bubble is fixed to the bottom-right. So is .sticky-cta,
   which is 76px tall and spans the full width below 900px -- the bubble lands
   on top of the Android and iPhone buttons, covering one of them. Lifting the
   widget clears the bar.

   Selectors are deliberately redundant: the vendor has shipped this widget as
   a custom element and as a plain div under at least two different ids, and the
   loader is remote so the markup can change under us without warning. A rule
   that matches nothing costs nothing; a rule that stops matching costs a CTA. */
@media (max-width: 900px) {
  chat-widget, #chat-widget, #chat-widget-container,
  [id^="lc_text_widget"], .lc_text-widget {
    bottom: 84px !important;
  }
}

/* ============ Lead form ============
   Replaces the third-party iframe that used to sit in .capture-frame. Owning
   the markup means the fields, the validation and the failure states are ours,
   and there is no cross-origin frame to size or to trust with a visitor's
   email.

   Progressive enhancement, deliberately: this is a real <form> with a real
   action and method, so it still submits if the script never runs. The script
   upgrades it to a fetch and an inline thank-you rather than being the only
   thing holding it together. */
.lf { display: grid; gap: 16px; max-width: 34em; }
.lf-row { display: grid; gap: 6px; }
.lf label { font-size: 14px; font-weight: 700; color: var(--ink); letter-spacing: -.005em; }
.lf .lf-opt { font-weight: 500; color: var(--ink-faint); }
.lf input[type="text"], .lf input[type="email"] {
  font-family: var(--font); font-size: 16px; color: var(--ink);
  background: var(--card); border: 1.5px solid rgba(20,33,61,.18); border-radius: 12px;
  padding: 12px 14px; width: 100%; transition: border-color .15s, box-shadow .15s;
}
/* 16px on the inputs is not a style choice -- iOS Safari zooms the viewport on
   focus for anything smaller, which on a phone throws the page sideways mid-form. */
.lf input:focus { outline: none; border-color: var(--purple); box-shadow: 0 0 0 3px rgba(108,59,255,.15); }
.lf input:focus-visible { outline: 3px solid var(--purple); outline-offset: 2px; }
.lf input[aria-invalid="true"] { border-color: #B42318; }
.lf-err { font-size: 13px; font-weight: 600; color: #B42318; min-height: 0; }
.lf-err:empty { display: none; }

/* Platform is a radio group styled as two cards: it is two mutually exclusive
   options and a native select would bury the choice behind a tap. */
.lf-seg { display: flex; gap: 10px; flex-wrap: wrap; }
.lf-seg label {
  flex: 1 1 130px; display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 12px 14px; border: 1.5px solid rgba(20,33,61,.18); border-radius: 12px;
  cursor: pointer; font-weight: 600; font-size: 15px; color: var(--ink-soft);
  transition: border-color .15s, background .15s, color .15s;
}
.lf-seg input { position: absolute; opacity: 0; width: 0; height: 0; }
.lf-seg label:hover { border-color: rgba(108,59,255,.4); }
.lf-seg input:checked + span { color: var(--purple-deep); }
.lf-seg label:has(input:checked) { border-color: var(--purple); background: rgba(108,59,255,.06); color: var(--purple-deep); }
.lf-seg label:has(input:focus-visible) { outline: 3px solid var(--purple); outline-offset: 2px; }

/* The honeypot. Not display:none -- a bot that reads styles skips those, and a
   screen reader should never reach it either, hence aria-hidden and tabindex. */
.lf-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.lf-submit {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  background: #4A1FD6; color: #FFFFFF; font-family: var(--font); font-weight: 700;
  font-size: 16px; padding: 14px 26px; border: 0; border-radius: 14px; cursor: pointer;
  justify-self: start; transition: background .15s, opacity .15s;
}
.lf-submit:hover:not(:disabled) { background: #3d1778; }
.lf-submit:disabled { opacity: .6; cursor: default; }
.lf-fine { font-size: 12.5px; line-height: 1.55; color: var(--ink-faint); max-width: 44ch; }
.lf-fine a { color: var(--purple-deep); }

/* Form-level status. aria-live so the outcome is announced, not just painted. */
.lf-status { font-size: 14.5px; font-weight: 600; }
.lf-status.err { color: #B42318; }
.capture-done {
  display: none; background: rgba(21,128,61,.07); border: 1px solid rgba(21,128,61,.3);
  border-radius: 14px; padding: 22px 24px;
}
.capture-done h4 { font-size: 18px; font-weight: 800; letter-spacing: -.015em; margin-bottom: 6px; color: var(--ink); }
.capture-done p { font-size: 15px; color: var(--ink-soft); margin: 0; }
.capture.is-done .lf, .capture.is-done .capture-head { display: none; }
.capture.is-done .capture-done { display: block; }

/* ============ TestFlight instructions ============
   Replaces the .tf-note paragraph, which said the right thing in 12.5px grey
   prose and was therefore not read. The failure it exists to prevent is
   specific and common: someone without TestFlight taps the button, lands in the
   App Store, installs TestFlight, then opens TestFlight from the home screen
   instead of returning here. An empty TestFlight offers exactly one action --
   redeem an invitation code -- and a public link has no code to give, so the
   tester concludes the beta is closed and leaves.

   So the sequence is numbered, the return step is called out as the one people
   miss, and the warning is a separate high-contrast row rather than a clause
   at the end of a sentence. */
.tf-help {
  background: var(--card); border: 1px solid rgba(20,33,61,.14); border-radius: 16px;
  padding: 18px 20px; margin: 0 0 18px; max-width: 32em; text-align: left;
}
.tf-help-lead { font-size: 19px; font-weight: 800; letter-spacing: -.02em; color: var(--ink); margin-bottom: 16px; }
.tf-help-sub { font-size: 13.5px; color: var(--ink-soft); margin-bottom: 14px; }
.tf-steps { list-style: none; counter-reset: tf; display: grid; gap: 16px; }
/* NOT display:flex. Making the li a flex container turns every inline <strong> into a
   flex ITEM, so "We don't use codes" became its own column and the sentence broke into
   three ragged stacks. The numeral is absolutely positioned; the text just needs room
   for it. */
.tf-steps li {
  counter-increment: tf; position: relative; padding-left: 52px;
  font-size: 15.5px; line-height: 1.55; color: var(--ink-soft);
  min-height: 38px; display: block; padding-top: 7px; padding-bottom: 7px;
}
/* The numeral is the design. It was a 24px chip with 13px type, which at a glance was
   a bullet with a digit in it; the steps read as a paragraph and people skipped step 2,
   which is the one that decides whether the install works at all. Now it is a 38px
   circle carrying 19px/900 type — big enough that "1, 2, 3" is the first thing the eye
   resolves, and the words are what you read second. */
.tf-steps li::before {
  content: counter(tf); position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 38px; height: 38px; border-radius: 50%;
  background: var(--purple); color: #FFFFFF;
  font-size: 19px; font-weight: 900; font-variant-numeric: tabular-nums;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 2px 8px rgba(108,59,255,.28);
}
.tf-steps strong { color: var(--ink); font-weight: 800; }
/* The step everyone misses gets the only colour in the list. */
.tf-steps .tf-key { color: var(--ink); font-weight: 600; }
.tf-steps .tf-key::before { background: var(--amber); color: #14213D; box-shadow: 0 2px 8px rgba(255,122,0,.36); }
.tf-warn {
  display: flex; gap: 10px; align-items: flex-start;
  margin-top: 14px; padding: 12px 14px;
  background: #FFF1E5; border: 1px solid rgba(255,122,0,.45); border-radius: 11px;
  font-size: 13.5px; line-height: 1.5; color: #14213D;
}
.tf-warn svg { flex: 0 0 auto; margin-top: 1px; }
.tf-warn strong { font-weight: 800; }

/* On the purple final-CTA panel the card would fight the gradient, so it goes
   translucent and the type inverts. Same content, same order. */
.final-cta .tf-help {
  background: rgba(255,255,255,.10); border-color: rgba(255,255,255,.22);
  margin-left: auto; margin-right: auto;
}
.final-cta .tf-help-lead { color: #fff; }
.final-cta .tf-help-sub { color: rgba(255,255,255,.75); }
.final-cta .tf-steps li { color: rgba(255,255,255,.86); }
.final-cta .tf-steps strong, .final-cta .tf-steps .tf-key { color: #fff; }
.final-cta .tf-steps li::before { background: #E6ECFA; color: #4A1FD6; box-shadow: 0 2px 10px rgba(0,0,0,.22); }
.final-cta .tf-steps .tf-key::before { background: var(--amber); color: #14213D; box-shadow: 0 2px 8px rgba(255,122,0,.36); }
.final-cta .tf-warn { background: rgba(255,122,0,.16); border-color: rgba(252,211,77,.45); color: #FDE9B8; }
.final-cta .tf-warn strong { color: #FCD34D; }

@media (max-width: 520px) { .tf-help { padding: 16px 15px; } }

/* ============ Coach application wizard (/coaches/apply/) ============
   Four pages, one shape. Everything here is scoped under .wz-* so it cannot
   reach the marketing pages, and it reuses the same tokens as the rest of the
   site rather than inventing a form palette. */

/* The progress rail. A list, in order, with the completed steps as links —
   so it doubles as the way back and needs no separate breadcrumb. */
.wz-rail { list-style: none; display: flex; flex-wrap: wrap; gap: 6px 4px; margin: 0 0 26px; padding: 0; }
.wz-step { display: flex; align-items: center; flex: 1 1 0; min-width: 0; gap: 9px; }
.wz-step > a, .wz-step > .wz-dot { text-decoration: none; }
.wz-step > a { display: flex; align-items: center; gap: 9px; min-width: 0; }
.wz-dot {
  flex: 0 0 auto; width: 27px; height: 27px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 800; letter-spacing: 0;
  border: 2px solid rgba(20,33,61,.16); background: var(--card); color: var(--ink-faint);
}
.wz-label {
  font-size: 13.5px; font-weight: 700; color: var(--ink-faint);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.wz-done .wz-dot  { background: var(--purple-deep); border-color: var(--purple-deep); color: #fff; }
.wz-done .wz-label{ color: var(--purple-deep); }
.wz-done > a:hover .wz-label { text-decoration: underline; }
.wz-now .wz-dot   { background: var(--card); border-color: var(--purple); color: var(--purple); box-shadow: 0 0 0 4px rgba(108,59,255,.12); }
.wz-now .wz-label { color: var(--ink); }
/* The connector between steps. Drawn on the step, not between them, so it
   cannot desync from the flex wrapping on a narrow screen. */
.wz-step + .wz-step::before {
  content: ""; flex: 1 1 auto; height: 2px; min-width: 10px;
  background: rgba(20,33,61,.12); border-radius: 2px; margin-right: 4px; order: -1;
}
.wz-done + .wz-step::before, .wz-now + .wz-step::before { background: rgba(108,59,255,.28); }
@media (max-width: 620px) {
  .wz-label { display: none; }
  .wz-step { flex: 0 0 auto; }
  .wz-step + .wz-step::before { min-width: 22px; }
}

.wz-count { font-size: 12.5px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--purple); margin: 0 0 8px; }
.wz-h1 { font-size: clamp(27px, 4vw, 38px); font-weight: 800; letter-spacing: -.025em; line-height: 1.15; margin: 0 0 12px; }
.wz-lede { font-size: 17px; line-height: 1.65; color: var(--ink-soft); max-width: 60ch; margin: 0 0 26px; }
.wz-lede strong { color: var(--ink); }

/* Errors. Listed at the top rather than beside each field: with the answers
   preserved in the boxes, a short list of what to change reads faster than
   hunting for red outlines. */
.wz-alert {
  background: #FEF2F2; border: 1px solid rgba(255,122,0,.5); border-left-width: 4px;
  border-radius: 12px; padding: 14px 18px; margin: 0 0 24px; color: #7F1D1D; font-size: 14.5px;
}
.wz-alert ul { margin: 8px 0 0; padding-left: 20px; }
.wz-alert li { margin-bottom: 4px; line-height: 1.5; }

.wz-form { max-width: 720px; }
.wz-form label { display: block; margin-bottom: 22px; font-weight: 700; font-size: 15px; color: var(--ink); }
.wz-form input[type="text"], .wz-form input[type="email"], .wz-form input[type="tel"],
.wz-form input[type="url"], .wz-form select, .wz-form textarea {
  display: block; width: 100%; margin-top: 7px; padding: 12px 14px;
  font: inherit; font-weight: 500; font-size: 16px; color: var(--ink); background: #fff;
  border: 1.5px solid #CBD5E1; border-radius: 11px; transition: border-color .15s, box-shadow .15s;
}
.wz-form textarea { resize: vertical; line-height: 1.6; }
.wz-form :is(input, select, textarea):focus-visible {
  outline: none; border-color: var(--purple); box-shadow: 0 0 0 4px rgba(108,59,255,.13);
}
.cf-hint { display: block; margin-top: 7px; font-size: 13px; font-weight: 500; line-height: 1.5; color: var(--ink-faint); }
.cf-opt { font-weight: 600; color: var(--ink-faint); font-size: 13px; }
.cf-row { display: flex; gap: 16px; flex-wrap: wrap; }
.cf-row > label { flex: 1 1 220px; }
.cf-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.wz-fs { border: 0; padding: 0; margin: 0 0 26px; }
.wz-fs legend { font-weight: 700; font-size: 15px; color: var(--ink); margin-bottom: 11px; padding: 0; }

/* Chips: a radio/checkbox row that reads as a set of choices rather than a
   column of dots. The input stays in the DOM (keyboard, screen readers, and
   the no-JS submit all depend on it) and is visually replaced. */
.wz-chips { display: flex; flex-wrap: wrap; gap: 9px; }
.wz-chip { margin: 0 !important; }
.wz-chip input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.wz-chip span {
  display: inline-block; padding: 9px 16px; border-radius: 999px;
  border: 1.5px solid #CBD5E1; background: var(--card);
  font-size: 14.5px; font-weight: 600; color: var(--ink-soft); cursor: pointer;
  transition: border-color .15s, background .15s, color .15s;
}
.wz-chip span:hover { border-color: var(--purple); color: var(--purple-deep); }
.wz-chip input:checked + span { background: var(--purple-deep); border-color: var(--purple-deep); color: #fff; }
.wz-chip input:focus-visible + span { outline: 3px solid var(--purple); outline-offset: 2px; }

/* Stacked options, for choices that need a line of explanation each. */
.wz-stack { display: grid; gap: 10px; }
.wz-opt { display: flex; gap: 13px; align-items: flex-start; margin: 0 !important;
  padding: 15px 17px; border: 1.5px solid #CBD5E1; border-radius: 13px; background: var(--card);
  cursor: pointer; transition: border-color .15s, box-shadow .15s; font-weight: 500; }
.wz-opt:hover { border-color: var(--purple); }
.wz-opt input { margin-top: 3px; flex: 0 0 auto; accent-color: var(--purple-deep); width: 18px; height: 18px; }
.wz-opt span { display: block; }
.wz-opt strong { display: block; font-weight: 700; font-size: 15.5px; color: var(--ink); }
.wz-opt em { display: block; font-style: normal; font-size: 13.5px; line-height: 1.5; color: var(--ink-faint); margin-top: 3px; }
.wz-opt:has(input:checked) { border-color: var(--purple-deep); box-shadow: 0 0 0 3px rgba(108,59,255,.12); }

.cf-check { display: flex; gap: 12px; align-items: flex-start; margin-bottom: 16px !important;
  font-weight: 500; font-size: 15px; line-height: 1.6; color: var(--ink-soft); }
.cf-check input { margin-top: 4px; flex: 0 0 auto; width: 18px; height: 18px; accent-color: var(--purple-deep); }

.wz-nav { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; margin-top: 34px;
  padding-top: 26px; border-top: 1px solid rgba(20,33,61,.1); }
.btn-ghost { background: transparent; border: 1.5px solid #CBD5E1; color: var(--ink-soft); }
.btn-ghost:hover { border-color: var(--purple); color: var(--purple-deep); transform: none; box-shadow: none; }

/* The review summary. A definition list with an edit link per row, so
   "change that one thing" never means walking the whole form again. */
.wz-sum { display: grid; gap: 0; margin: 0 0 26px; border: 1px solid var(--border);
  border-radius: var(--radius); overflow: hidden; background: var(--card); }
.wz-sum-row { display: grid; grid-template-columns: 190px 1fr auto; gap: 16px; align-items: baseline;
  padding: 13px 18px; border-top: 1px solid var(--border); }
.wz-sum-row:first-child { border-top: 0; }
.wz-sum dt { font-weight: 700; font-size: 14px; color: var(--ink-faint); margin: 0; }
.wz-sum dd { margin: 0; font-size: 15px; font-weight: 600; color: var(--ink); word-break: break-word; }
.wz-none { font-weight: 500; color: var(--ink-faint); }
.wz-edit { font-size: 13.5px; font-weight: 700; color: var(--purple-deep); text-decoration: none; white-space: nowrap; }
.wz-edit:hover { text-decoration: underline; }
@media (max-width: 620px) {
  .wz-sum-row { grid-template-columns: 1fr auto; }
  .wz-sum dt { grid-column: 1 / -1; }
}

.wz-about { position: relative; background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 18px 20px; margin-bottom: 20px; }
.wz-about h2 { font-size: 15px; font-weight: 700; color: var(--ink-faint); margin-bottom: 8px; letter-spacing: 0; }
.wz-about p { font-size: 15px; line-height: 1.65; color: var(--ink); margin: 0; }
.wz-about .wz-edit { position: absolute; top: 18px; right: 20px; }

.wz-next { background: linear-gradient(180deg, rgba(108,59,255,.06), rgba(108,59,255,.02));
  border: 1px solid rgba(108,59,255,.18); border-radius: var(--radius); padding: 22px 24px; margin-bottom: 30px; }
.wz-next h2 { font-size: 19px; margin-bottom: 12px; }
.wz-next ol { margin: 0; padding-left: 22px; display: grid; gap: 11px; }
.wz-next li { font-size: 15px; line-height: 1.65; color: var(--ink-soft); }
.wz-next strong { color: var(--ink); }

.wz-done { text-align: center; max-width: 560px; margin: 20px auto 0; }
.wz-done h2 { margin: 16px 0 12px; }
.wz-done p { font-size: 16px; line-height: 1.7; color: var(--ink-soft); margin-bottom: 14px; }
.wz-done .cf-hint { font-size: 14px; }

/* ============ Coach page — the mobieusVerified panel ============
   The one section on /coaches/ that is not built from the shared primitives.
   It earns that: the blue check is a specific, recognisable thing and washing
   it in the site's purple would make it look like a Loopa invention rather
   than the platform-wide mark it actually is. */
.coach-cta { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; margin-top: 26px; }
.coach-cta-note { font-size: 14px; color: var(--ink-faint); font-weight: 600; }

.verified-panel {
  display: grid; grid-template-columns: auto 1fr; gap: 26px; align-items: start;
  background: var(--card); border: 1px solid rgba(44,124,255,.28);
  border-left: 5px solid #2C7CFF; border-radius: 22px;
  padding: 38px 40px; box-shadow: var(--shadow-sm);
}
.vp-mark { flex: 0 0 auto; line-height: 0; }
.vp-body .kicker { color: #1D62CC; }
.vp-body h2 { font-size: clamp(25px, 3vw, 34px); }
.vp-body p { color: var(--ink-soft); font-size: 16px; line-height: 1.7; margin-bottom: 14px; max-width: 62ch; }

.vp-facts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; margin: 24px 0 20px; }
.vp-fact { background: rgba(44,124,255,.06); border: 1px solid rgba(44,124,255,.18);
  border-radius: 14px; padding: 16px 18px; }
.vp-fact b { display: block; font-size: 16.5px; font-weight: 800; letter-spacing: -.015em; color: var(--ink); margin-bottom: 6px; }
.vp-fact span { display: block; font-size: 13.5px; line-height: 1.55; color: var(--ink-soft); }

.vp-not { background: rgba(20,33,61,.04); border-radius: 12px; padding: 14px 18px;
  font-size: 15px !important; margin-bottom: 0 !important; }
.vp-not strong { color: var(--ink); }

@media (max-width: 860px) {
  .verified-panel { grid-template-columns: 1fr; gap: 18px; padding: 28px 24px; }
  .vp-facts { grid-template-columns: 1fr; gap: 12px; }
}

/* Lists inside a feature card. The card primitive never carried one — the
   checkmark treatment lives on .frow li, and a bare <ul> in a card falls back
   to browser bullets and an indent that lines up with nothing. Same marker as
   the feature rows so the two read as one system. */
.feat-card ul { list-style: none; display: grid; gap: 9px; margin: 16px 0 0; padding: 0; }
.feat-card li { font-size: 14.5px; line-height: 1.55; color: var(--ink-soft); padding-left: 26px; position: relative; }
.feat-card li::before {
  content: ""; position: absolute; left: 0; top: 5px; width: 14px; height: 7px;
  border-left: 2.5px solid var(--purple-deep); border-bottom: 2.5px solid var(--purple-deep);
  transform: rotate(-45deg);
}

/* A plain block of prose in a section that has no cards. Constrained to a
   readable measure and centred, rather than left in a full-width column where
   a line runs to 140 characters. */
.coach-prose { max-width: 68ch; margin: 0 auto; }
.coach-prose p { color: var(--ink-soft); font-size: 16.5px; line-height: 1.75; margin-bottom: 16px; }
.coach-prose p:last-child { margin-bottom: 0; }

/* ============ Founding member band (front page) ============
   The one loud thing on the page. Dark ground so it reads as an announcement
   rather than another content section, and amber on ink because that pairing is
   already the site's "pay attention" combination on the stat band. Amber is
   never used as body text on a light surface, per the brand rule; here it sits
   on Midnight, which is what it is for. */
.founders-band { padding: 0 0 8px; }
.founders-band .fb-inner {
  background: linear-gradient(135deg, var(--ink) 0%, #0F172A 100%);
  border-radius: 24px; padding: 34px 38px; color: #FFFFFF;
  display: grid; grid-template-columns: auto 1fr auto; gap: 28px; align-items: center;
  position: relative; overflow: hidden;
}
.founders-band .fb-inner::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(120% 140% at 100% 0%, rgba(255,122,0,.20), transparent 55%);
  pointer-events: none;
}
.fb-badge {
  position: relative; align-self: start;
  background: var(--amber); color: #14213D;
  font-size: 12px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase;
  padding: 7px 13px; border-radius: 999px; white-space: nowrap;
}
.fb-copy { position: relative; }
.fb-copy h2 {
  font-size: clamp(23px, 2.7vw, 31px); line-height: 1.2; margin-bottom: 10px; color: #FFFFFF;
}
.fb-copy p { font-size: 15.5px; line-height: 1.7; color: #D5DBE5; margin-bottom: 8px; max-width: 62ch; }
.fb-copy p:last-child { margin-bottom: 0; }
.fb-note { font-size: 14px !important; color: #AEB7C2 !important; }
.fb-cta { position: relative; display: grid; gap: 8px; justify-items: center; }
.fb-cta span { font-size: 12.5px; color: #AEB7C2; }

@media (max-width: 960px) {
  .founders-band .fb-inner { grid-template-columns: 1fr; gap: 18px; padding: 26px 24px; }
  .fb-cta { justify-items: start; }
}

/* A quieter sibling of the founders band, for pages whose whole subject is
   pricing. They describe the tiers as they will be after launch, which is
   currently not what anybody is paying, so they say so up front rather than
   letting the reader work it out. */
.founders-strip { padding: 0 0 6px; }
.founders-strip p {
  background: #FFF1E5; border: 1px solid rgba(255,122,0,.45); border-radius: 14px;
  padding: 14px 18px; margin: 0; font-size: 15px; line-height: 1.65; color: #14213D;
}
.founders-strip strong { font-weight: 800; }
.founders-strip a { color: var(--purple-deep); font-weight: 700; }

/* ---------------------------------------------------------------- beta feedback ---
   A <dialog>, not a hand-built overlay: the browser gives focus trapping, Esc to
   close, inert background and the top layer for free, and every one of those is a
   thing a hand-rolled modal gets subtly wrong.

   The form reuses .lf wholesale — same inputs, same focus ring, same 16px that stops
   iOS Safari zooming the viewport on focus. A second visual language for the same job
   would be the drift the chrome lint exists to stop, one layer down. */
/* A PEER of the two store badges, not a footnote under them: same 60px height, same
   14px radius, same icon-then-two-lines structure, sitting in the same flex row. The
   first version was a thin outlined button on its own line below the badges, which read
   as a different species of control that had wandered into the wrong section.

   Purple where the badges are ink, because it is a different KIND of action — those two
   install something, this one talks to us — and the colour is what says so without a
   third row of explanatory text. Filled rather than outlined so it holds its own weight
   beside two solid badges; an outline next to two filled cards always looks unfinished. */
.fb-open {
  display: inline-flex; align-items: center; gap: 12px;
  background: var(--purple); color: #FFFFFF; font-family: var(--font);
  padding: 11px 22px 11px 18px; border-radius: 14px;
  border: 1px solid rgba(255,255,255,.14);
  min-height: 60px; cursor: pointer; text-align: left;
  transition: transform .15s ease, box-shadow .15s ease, background .15s ease;
}
.fb-open:hover { transform: translateY(-2px); box-shadow: 0 10px 24px rgba(108,59,255,.32); background: #4A1FD6; }
.fb-open:focus-visible { outline: 3px solid var(--purple); outline-offset: 3px; }
.fb-open svg { flex: 0 0 auto; }
.fb-open .sb-text { display: flex; flex-direction: column; line-height: 1.25; text-align: left; }
.fb-open .sb-small { font-size: 11px; font-weight: 500; opacity: .88; letter-spacing: .02em; }
.fb-open .sb-big { font-size: 18px; font-weight: 700; letter-spacing: -.01em; }

/* The download page's own row: the two install cards are stacked in a grid there, so
   this gets a centred band of its own beneath them rather than a seat in a row that
   does not exist. Same button, different container. */
.fb-invite { display: flex; justify-content: center; margin: 26px 0 0; }

.fb-modal {
  border: 1px solid var(--border); border-radius: 16px; padding: 0;
  width: min(38em, calc(100vw - 32px)); max-height: min(86vh, 900px);
  background: var(--card); color: var(--ink);
  box-shadow: 0 24px 60px rgba(15,23,42,.22);
  /* The UA centres a modal dialog with `margin: auto`, and the site's reset zeroes
     margins on everything — so without this the dialog pins to the top-left corner.
     It looked like a layout bug and was a reset winning a specificity tie. */
  margin: auto;
}
.fb-modal::backdrop { background: rgba(15,23,42,.55); }
/* position: relative so the close button's absolute positioning has something local to
   resolve against. A dialog in the top layer otherwise sends it to the initial
   containing block, which happens to look right until the page scrolls. */
.fb-modal-inner { position: relative; padding: 26px 26px 24px; overflow-y: auto; max-height: inherit; }
.fb-modal h2 { font-size: 22px; font-weight: 800; letter-spacing: -.02em; margin: 0 0 6px; }
.fb-modal .fb-lead { color: var(--ink-soft); font-size: 15px; margin: 0 0 20px; }
.fb-close {
  position: absolute; top: 12px; right: 12px; width: 34px; height: 34px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 0; border-radius: 8px; cursor: pointer;
  color: var(--ink-faint); font-size: 22px; line-height: 1;
}
.fb-close:hover { background: rgba(20,33,61,.06); color: var(--ink); }
.fb-close:focus-visible { outline: 3px solid var(--purple); outline-offset: 2px; }

/* select and textarea are not in .lf because nothing else on the site uses them.
   Matched to .lf input by hand rather than by widening that rule, so a change to
   the lead form cannot silently restyle this one. */
.fb-modal .lf select,
.fb-modal .lf textarea {
  font-family: var(--font); font-size: 16px; color: var(--ink);
  background: var(--card); border: 1.5px solid rgba(20,33,61,.18); border-radius: 12px;
  padding: 12px 14px; width: 100%; transition: border-color .15s, box-shadow .15s;
}
.fb-modal .lf textarea { min-height: 8.5em; resize: vertical; line-height: 1.55; }
.fb-modal .lf select:focus,
.fb-modal .lf textarea:focus { outline: none; border-color: var(--purple); box-shadow: 0 0 0 3px rgba(108,59,255,.15); }
.fb-modal .lf select:focus-visible,
.fb-modal .lf textarea:focus-visible { outline: 3px solid var(--purple); outline-offset: 2px; }
.fb-modal .lf { max-width: none; }
.fb-actions { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.fb-submit {
  display: inline-flex; align-items: center; gap: 10px; background: var(--purple); color: #FFFFFF;
  font-family: var(--font); font-weight: 700; font-size: 15.5px; line-height: 1;
  border: 0; border-radius: 12px; padding: 14px 24px; cursor: pointer;
}
.fb-submit:hover { background: #3d1778; }
.fb-submit:disabled { opacity: .6; cursor: default; }
.fb-submit:focus-visible { outline: 3px solid var(--purple); outline-offset: 2px; }
.fb-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* The thank-you replaces the form in place rather than opening a second dialog. */
.fb-done { text-align: center; padding: 8px 4px 4px; }
.fb-done .fb-tick {
  display: inline-flex; align-items: center; justify-content: center;
  width: 54px; height: 54px; border-radius: 50%;
  background: rgba(108,59,255,.10); color: var(--purple); font-size: 27px; margin-bottom: 14px;
}
.fb-done h2 { margin-bottom: 10px; }
.fb-done p { color: var(--ink-soft); font-size: 15.5px; margin: 0 auto 14px; max-width: 40ch; }
.fb-perk {
  background: rgba(108,59,255,.07); border: 1px solid rgba(108,59,255,.18); border-radius: 12px;
  padding: 14px 16px; margin: 18px auto 20px; max-width: 44ch;
  font-size: 14.5px; line-height: 1.6; color: var(--ink);
}

/* ============ Links inside the purple call-to-action ============
   Measured, not noticed: `.cmp-note a` is --purple-deep (#4A1FD6), and the final CTA paints
   a #4A1FD6 -> #6C3BFF gradient behind it. That is a contrast ratio of 1.22:1 — the link was
   the same colour as the panel it sat on, so on every page carrying a link in that block the
   text was legible and the link inside it was not.

   Cream, and underlined. The underline matters independently of the colour: a link that is
   only identifiable by hue is invisible to anyone who cannot separate these two purples, and
   this one could not be separated by anybody. */
.final-cta a:not(.btn):not(.store-badge) {
  color: #FFFFFF;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  text-decoration-color: rgba(254, 250, 234, .55);
  transition: text-decoration-color .15s;
}
.final-cta a:not(.btn):not(.store-badge):hover { text-decoration-color: #FFFFFF; }
.final-cta a:not(.btn):not(.store-badge):focus-visible {
  outline: 3px solid #FFFFFF; outline-offset: 3px; border-radius: 3px;
}

/* The CTA centres its heading and its paragraph, so a single store badge left-aligned
   underneath them read as a mistake rather than a choice. */
.final-cta .store-row { justify-content: center; }

/* ============ Period calculator ============
   Its own page (/period-calculator/) rather than a widget bolted onto a feature
   page: it has one job and it is the reason somebody arrives.

   THE SIGNATURE IS THE UNCERTAINTY. This calculator's whole claim is that it
   widens its fertile window as your cycles vary, and withholds it entirely when
   they vary a lot. That was prose in an earlier version, which is the same as
   hiding it: the bands are now DRAWN, they visibly grow as you move along the
   regularity control, and the sixth projection is visibly vaguer than the first.
   Nobody else shows you the error, which is exactly why it is the thing to show. */
:root { --pc-control-h: 50px; }

.pc-card {
  max-width: 760px; margin: 0 auto 26px; background: var(--card);
  border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); padding: 26px 23px 22px;   /* 1px border + 23 = the 24px plane */
}
/* Stretch the cells to a common height and push the label to the top of each and the control
   to the bottom, so all three labels start on one line and all three controls sit on another.
   `align-items: end` alone bottom-aligned the controls but let the labels float to wherever
   their own text height put them; a two-line label and a one-line label then started 3px
   apart, which is exactly the kind of near-miss that reads as sloppy without being nameable. */
.pc-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); gap: 18px; margin-bottom: 22px; align-items: stretch; }
.pc-field { display: flex; flex-direction: column; justify-content: space-between; gap: 8px; font-size: 13.5px; font-weight: 700; color: var(--ink); }
.pc-field em { display: block; font-style: normal; font-weight: 500; font-size: 12px; color: var(--ink-faint); margin-top: 2px; }
/* One control height for the whole row. A date input and a stepper compute their intrinsic
   heights completely differently — 53px against 49px here — so the row only lines up if both
   are told what height to be. */
.pc-field input[type="date"] {
  font: inherit; font-weight: 600; font-size: 16px; color: var(--ink);
  padding: 0 13px; border: 1.5px solid #CBD5E1; border-radius: 12px;
  background: var(--bg); width: 100%; height: var(--pc-control-h); box-sizing: border-box;
}

/* Steppers, because a cycle length is nudged far more often than it is typed. */
.pc-stepper { display: flex; align-items: stretch; border: 1.5px solid #CBD5E1; border-radius: 12px; background: var(--bg); overflow: hidden; height: var(--pc-control-h); box-sizing: border-box; }
.pc-step {
  flex: 0 0 40px; border: 0; background: transparent; color: var(--purple);
  font-size: 19px; font-weight: 700; line-height: 1; cursor: pointer;
  transition: background .15s;
}
.pc-step:hover { background: rgba(108,59,255,.08); }
.pc-step:focus-visible { outline: 3px solid var(--purple); outline-offset: -3px; }
.pc-stepper input {
  flex: 1 1 auto; min-width: 0; width: 100%; border: 0; background: transparent; text-align: right;
  font: inherit; font-weight: 800; font-size: 18px; color: var(--ink); padding: 0; -moz-appearance: textfield;
}
.pc-stepper input::-webkit-outer-spin-button, .pc-stepper input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.pc-unit { align-self: center; font-size: 12.5px; font-weight: 600; color: var(--ink-faint); padding: 0 8px 0 5px; }

.pc-seg { border: 0; padding: 0; margin: 0 0 4px; }
.pc-seg legend { font-size: 13.5px; font-weight: 700; color: var(--ink); padding: 0; }
.pc-seg-why { font-size: 12.5px; line-height: 1.6; color: var(--ink-faint); margin: 6px 0 12px; max-width: 62ch; }
.pc-seg-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 8px; }
.pc-seg-opt { position: relative; }
.pc-seg-opt input { position: absolute; opacity: 0; width: 0; height: 0; }
.pc-seg-opt span {
  display: block; text-align: center; padding: 11px 10px; border-radius: 12px;
  border: 1.5px solid #CBD5E1; background: var(--bg); cursor: pointer;
  font-size: 13.5px; font-weight: 700; color: var(--ink-soft); transition: all .15s;
}
.pc-seg-opt span:hover { border-color: var(--purple); color: var(--purple); }
.pc-seg-opt input:checked + span { background: var(--purple); border-color: var(--purple); color: #FFFFFF; }
.pc-seg-opt input:focus-visible + span { outline: 3px solid var(--purple); outline-offset: 2px; }

.pc-hint { font-size: 12.5px; color: var(--ink-faint); margin: 16px 0 0; }

.pc-result { max-width: 760px; margin: 0 auto; }
.pc-headline { background: var(--ink); border-radius: 20px; padding: 26px 24px; margin-bottom: 18px; }  /* no border, so a flat 24 */
.pc-headline .pc-when { font-size: clamp(24px, 3.4vw, 34px); font-weight: 800; letter-spacing: -.02em; line-height: 1.16; color: #FFFFFF; }
.pc-headline .pc-give { font-size: 14.5px; color: rgba(254,250,234,.82); margin-top: 9px; }

/* The timeline. One row per projected cycle; the pale bar is when the period could
   START and the solid bar is the projection itself, so the pale bar growing row by
   row IS the compounding error. */
.pc-chart { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); padding: 20px 23px 16px; margin-bottom: 18px; box-shadow: var(--shadow-sm); }
.pc-chart h3 { font-size: 14px; font-weight: 800; color: var(--ink); margin: 0 0 3px; }
.pc-chart .pc-chart-sub { font-size: 12.5px; color: var(--ink-faint); margin: 0 0 16px; }
.pc-key { display: flex; flex-wrap: wrap; gap: 6px 16px; margin-bottom: 14px; font-size: 12px; color: var(--ink-soft); font-weight: 600; }
.pc-key i { display: inline-block; width: 18px; height: 9px; border-radius: 3px; margin-right: 6px; vertical-align: -1px; }
.pc-key .k-period { background: var(--purple); }
.pc-key .k-range  { background: rgba(108,59,255,.20); }
.pc-key .k-fert   { background: #99F6E4; }

.pc-row { display: grid; grid-template-columns: 62px 1fr; align-items: center; gap: 12px; margin-bottom: 9px; }
.pc-row-label { font-size: 11.5px; font-weight: 700; color: var(--ink-faint); text-align: right; }
.pc-track { position: relative; height: 26px; background: var(--bg); border-radius: 8px; overflow: hidden; }
.pc-band { position: absolute; top: 0; bottom: 0; border-radius: 6px; transition: left .35s ease, width .35s ease; }
.pc-band--range  { background: rgba(108,59,255,.20); }
.pc-band--fert   { background: #99F6E4; top: 6px; bottom: 6px; border-radius: 4px; }
.pc-band--period { background: var(--purple); }
.pc-axis { display: flex; justify-content: space-between; font-size: 11px; color: var(--ink-faint); margin-top: 8px; padding-left: 74px; }

.pc-list { list-style: none; margin: 0 0 18px; padding: 0; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--card); }
/* The same two-column rhythm as the chart above it — a 62px label, a 12px gap — so the
   period names stack under the chart's date labels and the dates under its tracks. The list
   is the chart's accessible twin; reading as one grid is the point. */
.pc-list li { display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: baseline; padding: 13px 23px; border-top: 1px solid var(--border); }
.pc-list li:first-child { border-top: 0; }
.pc-list .pc-n { font-weight: 800; font-size: 12px; color: var(--purple); flex: 0 0 62px; letter-spacing: .02em; }
.pc-list .pc-dates { font-weight: 700; }
.pc-list .pc-fertile { font-size: 13px; color: var(--ink-soft); }
.pc-list .pc-range { font-size: 12px; color: var(--ink-faint); width: 100%; }

.pc-note { font-size: 13.5px; line-height: 1.65; color: var(--ink-soft); background: rgba(108,59,255,.05);
           border-left: 3px solid var(--purple); border-radius: 0 12px 12px 0;
           padding: 14px 24px 14px 21px; margin-bottom: 14px; }   /* 3px border + 21 = the plane */
.pc-flag { border-left-color: #B45309; background: rgba(180,83,9,.06); }

@media (max-width: 560px) {
  .pc-card { padding: 20px 15px 18px; }
  .pc-chart { padding: 18px 15px 14px; }
  .pc-list li { padding: 13px 15px; }
  .pc-note { padding: 13px 16px 13px 13px; }
  .pc-headline { padding: 22px 16px; }
  .pc-row { grid-template-columns: 52px 1fr; gap: 12px; }
  .pc-list .pc-n { flex: 0 0 52px; }
  .pc-axis { padding-left: 64px; }
}
@media (prefers-reduced-motion: reduce) {
  .pc-band, .pc-step, .pc-seg-opt span { transition: none; }
}

/* ============================================================================
   Coaching pages — /coaching/ and /program-builder/
   Added 2026-08-22. Two components, one per page, because the coach-facing
   tools are desktop web and there is no capture of them: a marketing page
   cannot show a screenshot it does not have, and dressing a diagram up as one
   would be a lie about the product. Both of these are openly diagrams.
   ========================================================================= */

/* --- The consent switchboard -------------------------------------------
   Ten categories, every one of them drawn in the off position, because off
   is the shipped default and the whole argument of the page. Dark ground so
   the panel reads as a console against the cream page, and so the absence of
   any purple in it is the thing you notice. Nothing here animates: a row of
   switches that flicked on under a scroll trigger would be selling the
   opposite of what the copy says. */
/* text-align is pinned left because .hero-grid centers everything under 900px,
   and a list of settings centered in its own panel reads as a poster rather
   than a screen. */
.swb {
  background: var(--ink); color: #E5E7EB; border-radius: 22px;
  padding: 26px 26px 22px; box-shadow: var(--shadow-md); text-align: left;
}
.swb-head { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; flex-wrap: wrap; margin-bottom: 4px; }
.swb-title { font-size: 15px; font-weight: 800; letter-spacing: -.01em; color: #FFFFFF; }
.swb-count { font-size: 11.5px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: #FF7A00; }
.swb-sub { font-size: 13px; line-height: 1.6; color: #AEB7C2; margin-bottom: 18px; }
.swb-list { list-style: none; display: grid; grid-template-columns: 1fr 1fr; gap: 2px 22px; margin: 0; padding: 0; }
.swb-row {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 0; border-top: 1px solid rgba(229,231,235,.10);
}
.swb-list > .swb-row:first-child,
.swb-list > .swb-row:nth-child(2) { border-top: 0; }
.swb-name { flex: 1 1 auto; font-size: 14px; font-weight: 600; color: #E5E7EB; }
.swb-state { font-size: 11px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: #7E8A99; }
/* The track is decoration for a state the row already states in words, so it
   is hidden from assistive tech and the .swb-state text carries the meaning. */
.swb-track {
  flex: 0 0 auto; width: 38px; height: 22px; border-radius: 11px;
  background: rgba(229,231,235,.13); border: 1px solid rgba(229,231,235,.16);
  position: relative;
}
.swb-track::after {
  content: ""; position: absolute; top: 3px; left: 3px;
  width: 14px; height: 14px; border-radius: 50%; background: #7E8A99;
}
.swb-foot {
  margin-top: 18px; padding-top: 16px; border-top: 1px solid rgba(229,231,235,.10);
  font-size: 13px; line-height: 1.65; color: #AEB7C2;
}
.swb-foot b { color: #FFFFFF; font-weight: 700; }
@media (max-width: 900px) {
  .swb { padding: 22px 20px 18px; }
  .swb-list { grid-template-columns: 1fr; gap: 0; }
  .swb-list > .swb-row:nth-child(2) { border-top: 1px solid rgba(229,231,235,.10); }
}

/* --- The program grid ---------------------------------------------------
   Weeks down, days across, which is the axis order the builder actually
   uses and the shape a coach already writes a block in. A real table: the
   column headers are days, the row headers are weeks, and a screen reader
   gets the same two axes a sighted reader does. Scrolls inside its own
   container rather than pushing the page sideways. */
.pgwrap { overflow-x: auto; -webkit-overflow-scrolling: touch; margin-top: 28px; padding-bottom: 4px; }
/* table-layout: fixed so the seven days are seven equal columns. Left to size
   themselves, Tuesday came out twice the width of Thursday because one holds a
   two-word routine and the other holds "Rest", and a calendar whose days are
   different widths does not read as a calendar.
   No overflow:hidden here, deliberately: it clips the <caption>, which belongs
   to the table box. The corners are rounded on the corner cells instead. */
.pg {
  width: 100%; min-width: 900px; table-layout: fixed;
  border-collapse: separate; border-spacing: 0;
  background: var(--card); border: 1px solid rgba(20,33,61,.12);
  border-radius: 18px; box-shadow: var(--shadow-sm);
}
.pg caption {
  caption-side: top; text-align: left; font-size: 13px; color: var(--ink-faint);
  padding: 0 0 12px; line-height: 1.6;
}
.pg th, .pg td { padding: 12px 14px; text-align: left; vertical-align: top; border-top: 1px solid var(--border); }
.pg thead th {
  border-top: 0; background: rgba(108,59,255,.05); font-size: 12px; font-weight: 800;
  letter-spacing: .06em; text-transform: uppercase; color: var(--purple); white-space: nowrap;
}
.pg thead tr > *:first-child { border-top: 0; background: rgba(108,59,255,.05); border-radius: 17px 0 0 0; width: 108px; }
.pg thead tr > *:last-child { border-radius: 0 17px 0 0; }
.pg tbody tr:last-child > *:first-child { border-radius: 0 0 0 17px; }
.pg tbody tr:last-child > *:last-child { border-radius: 0 0 17px 0; }
.pg tbody th {
  font-size: 13px; font-weight: 700; color: var(--ink-soft); white-space: nowrap;
  background: rgba(20,33,61,.02);
}
.pg-chip {
  display: inline-block; font-size: 13px; font-weight: 700; line-height: 1.35;
  border-radius: 9px; padding: 7px 11px; background: rgba(108,59,255,.12);
  color: var(--purple-deep); border: 1px solid rgba(108,59,255,.28);
}
.pg-chip small { display: block; font-size: 11.5px; font-weight: 600; color: var(--ink-faint); margin-top: 2px; }
/* A finished day. Muted rather than crossed out: it happened, it counts, and
   the point of the styling is that it is no longer yours to move. The cell is
   tinted as well as the chip, so the boundary between what is done and what is
   still open reads as a shape — including when it falls mid-week, which is the
   case the rule exists for. */
.pg td.pg-done { background: rgba(20,33,61,.04); }
.pg-done .pg-chip { background: transparent; color: var(--ink-faint); border-color: rgba(20,33,61,.16); border-style: dashed; }
.pg-done .pg-chip small { color: var(--ink-faint); }
.pg-rest { font-size: 13px; color: var(--ink-faint); }
.pg-key { display: flex; flex-wrap: wrap; gap: 8px 22px; margin-top: 16px; font-size: 13px; color: var(--ink-soft); font-weight: 600; }
.pg-key i { display: inline-block; width: 15px; height: 15px; border-radius: 5px; margin-right: 8px; vertical-align: -3px; }
.pg-key .k-open { background: rgba(108,59,255,.12); border: 1px solid rgba(108,59,255,.28); }
.pg-key .k-done { background: rgba(20,33,61,.04); border: 1px dashed rgba(20,33,61,.28); }

/* --- Rule cards ---------------------------------------------------------
   The four progression rules. A list, not a sequence, so no numbering: a
   coach picks one, they do not run in order. */
.rules { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 18px; margin-top: 30px; }
.rule {
  background: var(--card); border: 1px solid rgba(20,33,61,.12); border-radius: var(--radius);
  padding: 24px 22px; box-shadow: var(--shadow-sm);
}
.rule h3 { font-size: 17px; letter-spacing: -.015em; margin-bottom: 8px; }
.rule p { font-size: 14.5px; line-height: 1.65; color: var(--ink-soft); }
.rule-math {
  display: inline-block; margin-bottom: 14px; font-size: 12.5px; font-weight: 700;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  background: rgba(108,59,255,.07); color: var(--purple-deep);
  border-radius: 8px; padding: 5px 10px;
}

/* A screenshot we do not have yet.
   Coach-side surfaces (the roster, a client's detail, session review, the program
   builder) live behind a coach sign-in, so no capture rig reaches them and the pages
   that describe them were shipping with client-app screenshots or with nothing. A
   labelled empty frame is honest about that and is a drop-in target: replace the whole
   .shot-slot element with the <picture> block once the capture exists.
   Sized to the same 16:10 a desktop screen wants, rather than the 828x1792 phone
   frames, because every one of these is a browser window. */
.shot-slot { display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; aspect-ratio: 16 / 10; max-height: 380px; min-height: 200px; width: 100%;
  margin-top: 26px; border: 2px dashed rgba(74,31,214,.35);
  border-radius: 16px; background: rgba(74,31,214,.04); color: #4A1FD6; text-align: center;
  padding: 24px; }
.shot-slot b { font-size: 15px; font-weight: 800; letter-spacing: -.01em; }
.shot-slot span { font-size: 13px; color: #6B7280; max-width: 44ch; line-height: 1.45; }
:root[data-theme="dark"] .shot-slot,
:root:not([data-theme="light"]) .shot-slot { background: rgba(255,255,255,.03); }

/* ============ Partner economics: the rate, the two ways in, the perks ============ */
/* The commission was four sections down and phrased as "the standard partner terms",
   which is a rate nobody can read and therefore a rate nobody believes. It is 20%,
   recurring, and it now appears three times on the coaches page -- the hero flag, the
   two track cards, the perk list -- deliberately, because each of those is read by
   somebody who scrolled past the other two. */
.pay-flag {
  display: flex; align-items: center; gap: 20px; margin: 26px 0 22px;
  background: linear-gradient(135deg, #4A1FD6 0%, #6D28D9 100%);
  color: #FFFFFF; border-radius: 18px; padding: 20px 24px;
  box-shadow: 0 10px 28px rgba(74, 31, 214, .24);
}
/* #FCD34D measures 5.4:1 against the light end of that gradient and 8.1 against the
   dark end, so the number carries at any width the band collapses to. */
.pay-flag > b {
  flex: 0 0 auto; font-size: clamp(36px, 6vw, 48px); font-weight: 800;
  letter-spacing: -.04em; line-height: 1; color: #FCD34D;
}
.pay-flag strong { display: block; font-size: 16px; font-weight: 800; letter-spacing: -.01em; }
.pay-flag span { display: block; font-size: 14px; line-height: 1.55; color: rgba(254, 250, 234, .90); margin-top: 4px; }
/* Below this the number and the sentence are fighting for the same 340px and the
   sentence loses -- it was wrapping every three words beside a 48px numeral. Stacked,
   the number gets its own line and the paragraph gets the full width, which is also
   how the rest of the hero behaves on a phone. */
@media (max-width: 560px) {
  .pay-flag { flex-direction: column; align-items: center; text-align: center; gap: 8px; padding: 22px 20px; }
  .pay-flag > b { font-size: 46px; }
  .pay-flag span { font-size: 14.5px; }
}

.ways { display: grid; grid-template-columns: repeat(2, 1fr); gap: 22px; align-items: stretch; }
.way {
  position: relative; display: flex; flex-direction: column;
  background: var(--card); border: 1px solid var(--border); border-radius: 20px;
  box-shadow: var(--shadow-sm); padding: 30px 28px;
  transition: transform .2s ease, box-shadow .2s ease;
}
.way:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }
/* The coach card is the wider offer, so it carries the accent rule. Not a different
   colour system: the same violet the rest of the page uses for anything primary. */
.way-coach { border-color: rgba(108, 59, 255, .28); box-shadow: var(--shadow-md); }
.way-coach::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 4px;
  border-radius: 20px 20px 0 0;
  background: linear-gradient(90deg, var(--purple) 0%, var(--mint) 100%);
}
.way-kind {
  font-size: 12px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase;
  color: var(--purple);
}
.way-rate { display: flex; align-items: baseline; gap: 9px; margin: 12px 0 0; }
.way-rate b { font-size: clamp(38px, 5vw, 46px); font-weight: 800; letter-spacing: -.04em;
              line-height: 1; color: var(--purple-deep); }
.way-rate span { font-size: 15px; font-weight: 700; color: var(--ink-soft); }
.way h3 { font-size: 20px; font-weight: 800; letter-spacing: -.02em; margin: 16px 0 8px; line-height: 1.3; }
.way > p { font-size: 15.5px; line-height: 1.7; color: var(--ink-soft); }
.way ul { list-style: none; display: grid; gap: 9px; margin: 16px 0 24px; padding: 0; }
.way li { font-size: 14.5px; line-height: 1.55; color: var(--ink-soft); padding-left: 26px; position: relative; }
.way li::before {
  content: ""; position: absolute; left: 0; top: 5px; width: 14px; height: 7px;
  border-left: 2.5px solid var(--purple-deep); border-bottom: 2.5px solid var(--purple-deep);
  transform: rotate(-45deg);
}
/* auto, not a fixed gap: the two cards are equal height and the coach one carries a
   longer list, so a fixed margin left the affiliate CTA floating in the middle of its
   card with dead space under it. Both CTAs now sit on the same line. */
.way .btn { margin-top: auto; align-self: flex-start; }
@media (max-width: 820px) { .ways { grid-template-columns: 1fr; } }

/* The seven things both tracks get. Two columns of ticks rather than one long list:
   a list this length reads as fine print in a single column, and every line in it is
   something somebody would otherwise have to ask us for. */
.perks {
  margin-top: 24px; background: var(--card); border: 1px solid var(--border);
  border-radius: 20px; box-shadow: var(--shadow-sm); padding: 30px 30px 26px;
}
.perks h3 { font-size: 19px; font-weight: 800; letter-spacing: -.02em; margin-bottom: 18px; }
.perk-list { list-style: none; margin: 0; padding: 0;
             display: grid; grid-template-columns: repeat(2, minmax(240px, 1fr)); gap: 12px 30px; }
.perk-list li { position: relative; padding-left: 28px; font-size: 15.5px; line-height: 1.55; color: var(--ink); }
.perk-list li::before {
  content: ""; position: absolute; left: 0; top: 6px; width: 15px; height: 8px;
  border-left: 2.6px solid var(--green); border-bottom: 2.6px solid var(--green);
  transform: rotate(-45deg);
}
.perk-list li strong { font-weight: 800; }
.perks-note {
  margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--border);
  font-size: 15px; line-height: 1.65; color: var(--ink-soft);
}
@media (max-width: 720px) { .perk-list { grid-template-columns: 1fr; } .perks { padding: 26px 22px 22px; } }

/* ============ The commission ladder ============ */
/* Three rungs on a dark band, because the rate rising is the whole argument and a rate
   that rises is not something a bullet in a card can carry. Same ink ground and the same
   amber the stat band uses, so it reads as one system rather than a second brand. */
.ladder-band {
  background: var(--ink); color: #FFFFFF; border-radius: 24px; padding: 40px 36px;
}
.ladder-head { text-align: center; margin-bottom: 30px; }
.ladder-head .kicker { color: var(--amber); }
.ladder-head h2 { color: #FFFFFF; margin-bottom: 10px; }
.ladder-head p { color: #AEB7C2; font-size: 16.5px; line-height: 1.65; max-width: 60ch; margin: 0 auto; }
.ladder { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; align-items: stretch; }
.rung {
  background: rgba(255, 255, 255, .06); border: 1px solid rgba(255, 255, 255, .13);
  border-radius: 18px; padding: 26px 24px; display: flex; flex-direction: column;
}
/* Top rung. Violet into mint at low opacity over the ink ground: #FCD34D still measures
   above 7:1 on it, which the flat white tint does at 9.9. */
.rung-top {
  background: linear-gradient(135deg, rgba(108, 59, 255, .55) 0%, rgba(0, 201, 216, .16) 100%);
  border-color: rgba(252, 211, 77, .40);
}
.rung-name {
  display: block; font-size: 12px; font-weight: 800; letter-spacing: .13em;
  text-transform: uppercase; color: #AEB7C2; margin-bottom: 12px;
}
.rung b {
  display: block; font-size: clamp(40px, 5vw, 54px); font-weight: 800;
  letter-spacing: -.04em; line-height: 1; color: #FCD34D;
}
.rung-when { display: block; margin-top: 10px; font-size: 15.5px; font-weight: 700; color: #FFFFFF; line-height: 1.4; }
.rung p { margin-top: 10px; font-size: 14.5px; line-height: 1.6; color: #D5DBE3; }
.ladder-note {
  margin-top: 26px; padding-top: 22px; border-top: 1px solid rgba(255, 255, 255, .14);
  font-size: 14.5px; line-height: 1.75; color: #AEB7C2;
}
.ladder-note strong { color: #FFFFFF; font-weight: 700; }
@media (max-width: 820px) { .ladder { grid-template-columns: 1fr; gap: 16px; }
                            .ladder-band { padding: 32px 22px; } }

/* ============ The Partner Referral Bonus panel ============ */
/* A fourth rung would have been the wrong shape: this is a different KIND of money, one
   level deep and deliberately terminal, and putting it beside 20/25/30 invites exactly the
   downline reading the copy spends its next three lines refusing. Own panel, own colour. */
.bonus-panel {
  margin-top: 22px; display: grid; grid-template-columns: auto 1fr; gap: 30px;
  align-items: start; background: var(--card); border: 1px solid rgba(0, 201, 216, .40);
  border-left: 5px solid #155E75; border-radius: 22px; padding: 34px 36px;
  box-shadow: var(--shadow-sm);
}
.bonus-rate { text-align: center; }
.bonus-rate b {
  display: block; font-size: clamp(42px, 6vw, 56px); font-weight: 800;
  letter-spacing: -.04em; line-height: 1; color: #155E75;
}
.bonus-rate span {
  display: block; margin-top: 6px; font-size: 12px; font-weight: 800; letter-spacing: .12em;
  text-transform: uppercase; color: var(--ink-faint);
}
.bonus-panel h3 { font-size: 22px; font-weight: 800; letter-spacing: -.02em; margin-bottom: 10px; }
.bonus-panel p { font-size: 15.5px; line-height: 1.7; color: var(--ink-soft); }
.bonus-panel p + p { margin-top: 12px; }
/* The stop. Three short lines set apart from the prose, because "and that is where it
   stops" is the sentence somebody is scanning for and it must not be inside a paragraph. */
.bonus-stop {
  margin-top: 18px; padding: 16px 18px; background: rgba(15, 118, 110, .07);
  border-radius: 14px; font-size: 15px; line-height: 1.7; color: var(--ink);
}
.bonus-stop b { font-weight: 800; }
@media (max-width: 720px) {
  .bonus-panel { grid-template-columns: 1fr; gap: 18px; padding: 28px 22px; }
  .bonus-rate { text-align: left; }
}

/* The commission illustration. Deliberately plain and deliberately labelled: an earnings
   figure on a recruiting page needs a reasonable basis and needs to say what it is, and a
   box that looks like a testimonial is doing the opposite of that. */
.illus {
  margin-top: 20px; border: 1px dashed rgba(74, 31, 214, .35); border-radius: 16px;
  background: rgba(74, 31, 214, .035); padding: 22px 24px;
}
.illus h3 { font-size: 16px; font-weight: 800; letter-spacing: -.01em; margin-bottom: 10px; }
.illus p { font-size: 14.5px; line-height: 1.7; color: var(--ink-soft); }
.illus-note { margin-top: 12px; font-size: 13.5px; line-height: 1.65; color: var(--ink-faint); }

/* Per-member figures on the rate card. A percentage is an abstraction; "$2.60 a month, per
   member, every month" is the thing somebody can actually multiply by their own audience,
   which is the arithmetic they were going to do in their head anyway and get wrong. */
.rung-permember {
  display: block; margin-top: 14px; padding-top: 12px;
  border-top: 1px solid rgba(255, 255, 255, .16);
  font-size: 14px; line-height: 1.5; color: #D5DBE3;
}
.rung-permember b { display: block; font-size: 19px; font-weight: 800; color: #FFFFFF; letter-spacing: -.02em; }
.bonus-example {
  margin-top: 16px; font-size: 15px; line-height: 1.7; color: var(--ink-soft);
  background: rgba(15, 118, 110, .05); border-radius: 12px; padding: 14px 16px;
}
.bonus-example b { color: var(--ink); font-weight: 800; }
