/* ==========================================================================
   Foresight Premier — product page
   ========================================================================== */

@font-face {
  font-family: "TT Interphases Pro";
  /* woff2 first — same variable font at a third of the bytes (699KB -> 242KB);
     the ttf stays as the fallback for anything that cannot take it */
  src: url("../fonts/TTInterphasesProVariable.woff2") format("woff2-variations"),
       url("../fonts/TTInterphasesProVariable.ttf") format("truetype-variations");
  font-weight: 100 900;
  font-stretch: 75% 100%;
  font-display: swap;
}

@font-face {
  font-family: "TT Interphases Pro Mono";
  src: url("../fonts/TTInterphasesProMonoVar.woff2") format("woff2-variations"),
       url("../fonts/TTInterphasesProMonoVar.ttf") format("truetype-variations");
  font-weight: 400 700;
  font-display: swap;
}

:root {
  /* Palette = Product UI Library tokens (Figma). Base/Black·White, Brand/500·600,
     and the Alpha system: text on dark = Alpha/Text (#fafafa at 100/80/60),
     inks on light = alpha-black-90/70/50, hairlines = alpha 10. */
  --black: #000;              /* Base/Black */
  --elev: #0d0d0d;            /* alpha-white-5 over black */
  --card-dark: #1a1a1a;       /* alpha-white-10 over black */
  --light: #f5f5f6;           /* Gray (dark mode)/50 */
  --white: #fff;              /* Base/White */

  --ink-d1: #f5f5f6;                    /* text-primary (dark) */
  --ink-d2: rgba(250, 250, 250, .6);    /* Alpha/Text/Tertiary */
  --ink-d3: rgba(255, 255, 255, .5);    /* alpha-white-50 */
  --ink-l1: rgba(0, 0, 0, .9);          /* alpha-black-90 */
  --ink-l2: rgba(0, 0, 0, .7);          /* alpha-black-70 */

  --blue: #0348d9;            /* Brand/500 */
  --blue-light: #3ba5ff;      /* no library equivalent — loose value */
  --grad-blue: linear-gradient(94deg, #8fd8ff 0%, #3ba5ff 48%, #1e6dff 100%);

  --line-d: rgba(255, 255, 255, .1);    /* alpha-white-10 */
  --line-l: rgba(0, 0, 0, .1);          /* alpha-black-10 */

  --r-card: 28px;
  --r-panel: 18px;

  /* Scroll parallax: how far a media plate overhangs its clipped window on
     each side (percent of the window's HEIGHT — top/bottom insets resolve
     against it). The JS travel is 5.5%, so this leaves 2.5% of slack; without
     it the plate's edge slips into frame on short cards, where the Foresight+
     deck clamps to 420px and the overhang shrinks with it. */
  --par-over: 8%;

  --font: "TT Interphases Pro", -apple-system, BlinkMacSystemFont,
          "Helvetica Neue", Helvetica, Arial, sans-serif;
  --mono: "TT Interphases Pro Mono", ui-monospace, "SF Mono", SFMono-Regular, Menlo, monospace;

  --ease: cubic-bezier(.22, .61, .36, 1);
  --nav-h: 52px;
}

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

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

/* Safari drew the whole page oblique (user 2026-09-18): TT Interphases Pro's
   slnt axis runs 0..11 — positive, where OpenType expects negative — and at
   font-style: normal WebKit lands on the far end of it (measured 11.1deg in
   Safari 26.4, 0 in Chrome). Pinning the axis is the one thing that holds it
   upright there; no font-style range or @font-face setting does.
   On every element and !important because the `font` shorthand resets
   font-variation-settings wherever it is used, and that failure is silent
   outside Safari. Nothing here drives an axis by hand: weight and width go
   through font-weight / font-stretch. */
*, *::before, *::after { font-variation-settings: "slnt" 0 !important; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 12px);
  -webkit-text-size-adjust: 100%;
}

body {
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.5;
  letter-spacing: -.011em;
  background: var(--black);
  color: var(--ink-d1);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
}

img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
ul { list-style: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

::selection { background: rgba(59, 165, 255, .35); }

:focus-visible {
  outline: 2px solid var(--blue-light);
  outline-offset: 3px;
  border-radius: 4px;
}

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}

/* ---------- Layout helpers ---------- */

.container        { width: min(1080px, 92vw); margin-inline: auto; }
.container-wide   { width: min(1320px, 94vw); margin-inline: auto; }
.container-narrow { width: min(760px, 92vw);  margin-inline: auto; }

.theme-dark  { background: var(--black); color: var(--ink-d1); }
.theme-light { background: var(--light); color: var(--ink-l1); }

/* ---------- Type ---------- */

/* Display 2xl/Bold — 72/90, −2% (Product UI Library). The old 4.2rem/1.06
   ramp was off-system: it capped at 67px and ran a much tighter leading. */
.h2 {
  font-size: clamp(2.4rem, 5.4vw, 4.5rem);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -.02em;
}
/* Display 3xl/Bold — 96/120, −2%; same step as the hero H1 */
.h2--xl { font-size: clamp(2.7rem, 6.4vw, 6rem); }

.h3-lg {
  font-size: clamp(1.7rem, 3.2vw, 2.4rem);
  font-weight: 700;
  letter-spacing: -.018em;
}

.lede {
  font-size: clamp(1.12rem, 1.9vw, 1.4rem);
  line-height: 1.42;
  letter-spacing: -.013em;
  max-width: 46ch;
  /* Optical gap, not box gap: the h2's line-height went 1.06 → 1.25 with the
     Display 2xl ramp, which added ~5px of half-leading between title and lede
     for free. Pulled 1.1rem → .8rem so the SEEN gap lands back at ~23px. */
  margin-top: .8rem;
}
.theme-dark .lede  { color: var(--ink-d2); }
.theme-light .lede { color: var(--ink-l2); }

/* Corner-bracket tag (per Figma 11720:28332) — Mono sm caps between hairline
   brackets. White on dark, black on light; the brackets follow currentColor. */
.eyebrow {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 400;
  line-height: 1.2;
  letter-spacing: .1em; /* 1.2px at 12px */
  text-transform: uppercase;
  color: #fff;
  margin-bottom: .9rem;
}
.theme-light .eyebrow { color: #000; }

.eyebrow::before,
.eyebrow::after {
  content: "";
  flex: none;
  height: 20.03px;
  background: currentColor;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
}
.eyebrow::before {
  width: 5.132px;
  -webkit-mask-image: url("../assets/tag-bracket-l.svg");
  mask-image: url("../assets/tag-bracket-l.svg");
}
.eyebrow::after {
  width: 5px;
  -webkit-mask-image: url("../assets/tag-bracket-r.svg");
  mask-image: url("../assets/tag-bracket-r.svg");
}

/* Gradient text. Unused on the home since 2026-07-31 (the Foresight+ headline
   went flat white) — kept because the cinematic still builds on --grad-blue. */
.grad {
  background: var(--grad-blue);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.footnote {
  font-size: .8rem;
  line-height: 1.5;
  letter-spacing: 0;
  color: var(--ink-l2);
  max-width: 64ch;
}
.theme-dark .footnote { color: var(--ink-d3); }

/* ---------- Buttons & links ---------- */

.cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  align-items: center;
  margin-top: 1.9rem;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 13px 26px;
  border-radius: 980px;
  font-size: 1rem; /* Text md/Semibold */
  font-weight: 600;
  letter-spacing: -.01em;
  transition: transform .35s var(--ease), filter .35s var(--ease),
              background .35s var(--ease), border-color .35s var(--ease);
  white-space: nowrap;
}
.btn:active { transform: scale(.97); }

.btn--primary {
  /* FSP Button — brand gradient 600→500 */
  background: linear-gradient(90deg, #0342c6, #0348d9);
  border: 1px solid rgba(255, 255, 255, .1);
  color: #fff;
}
.btn--primary:hover { filter: brightness(1.18); transform: translateY(-1px); }

.btn--ghost {
  border: 1.5px solid currentColor;
  color: var(--ink-d1);
}
.theme-light .btn--ghost { color: var(--ink-l1); }
.btn--ghost:hover { transform: translateY(-1px); background: rgba(127,127,127,.09); }

.btn--mini { padding: 8px 14px; font-size: .875rem; line-height: 1.43; } /* Text sm/Semibold, FSP sm */

/* Label roll — the capsule stays still, the text rolls up on hover.
   Markup: <span class="roll"><b>Label</b><b aria-hidden="true">Label</b></span> */
.btn .roll { display: grid; overflow: hidden; }
.btn .roll b {
  grid-area: 1 / 1;
  font-weight: inherit;
  transition: transform .35s var(--ease);
  will-change: transform;
}
.btn .roll b:nth-child(2) { transform: translateY(115%); }
.btn:hover .roll b:first-child,
.btn:focus-visible .roll b:first-child { transform: translateY(-115%); }
.btn:hover .roll b:nth-child(2),
.btn:focus-visible .roll b:nth-child(2) { transform: translateY(0); }

.link-arrow {
  display: inline-block;
  position: relative;
  font-weight: 600;
  font-size: 1.05rem;
  color: #fff;
}
.theme-light .link-arrow { color: var(--ink-l1); }
/* underline is always on; hover renews it — it runs out the right edge and
   re-enters from the left (transform-origin swaps mid-keyframes) */
.link-arrow::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -.18em;
  height: 1.5px;
  background: currentColor;
  transform: scaleX(1);
}
.link-arrow:hover::after,
.link-arrow:focus-visible::after { animation: link-renew .91s var(--ease); }

@keyframes link-renew {
  0%   { transform: scaleX(1); transform-origin: right center; }
  49%  { transform: scaleX(0); transform-origin: right center; }
  50%  { transform: scaleX(0); transform-origin: left center; }
  100% { transform: scaleX(1); transform-origin: left center; }
}
.link-arrow--lg { margin-top: 1.8rem; }

/* ---------- Reveal-on-scroll ---------- */

.reveal {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity .9s var(--ease) var(--d, 0s),
              transform .9s var(--ease) var(--d, 0s);
}
.reveal.in { opacity: 1; transform: none; }

/* ==========================================================================
   LOCAL NAV
   ========================================================================== */

/* ==========================================================================
   0 · GLOBAL NAV — matches the CURRENT foresightsports.com header (user
   2026-08-14): logo left, uppercase dropdown nav, Specials + Contact Sales
   pills, search and cart. Sits in flow at the very top so it scrolls away;
   the fixed localnav starts just under it and rides up to the viewport top
   (offset in main.js). The slide-in drawer below remains the mobile menu.
   ========================================================================== */

.gnav {
  --gnav-h: 64px;
  position: relative;
  z-index: 101; /* above the localnav (100) while both are on screen */
  height: var(--gnav-h);
  background: #000;
  font-family: "Termina", "Roboto", var(--font);
}
.gnav__inner {
  height: 100%;
  display: flex;
  align-items: center;
  gap: clamp(16px, 2vw, 36px);
  padding-inline: max(3vw, calc((100vw - 1760px) / 2));
}
.gnav__brand { line-height: 0; flex: 0 0 auto; }
.gnav__brand img { display: block; height: 17px; width: auto; }
.gnav__nav {
  display: flex;
  align-items: center;
  gap: clamp(14px, 1.6vw, 30px);
  margin-inline: auto;
}
.gnav__item { position: relative; }
.gnav__link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 22px 2px; /* tall hit area bridges the hover gap to the dropdown */
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  white-space: nowrap;
  color: rgba(255, 255, 255, .85);
  transition: color .25s var(--ease);
}
.gnav__link:hover { color: #fff; }
.gnav__caret { width: 9px; height: 6px; opacity: .7; transition: transform .25s var(--ease); }
.gnav__item:hover .gnav__caret,
.gnav__item:focus-within .gnav__caret { transform: rotate(180deg); }
/* ---------- mega menus (2026-08-25) ----------
   Rebuilt to match foresightsports.com: a full-width strip under the bar
   rather than a floating card. Launch Monitors carries four product cards and
   a side column of links; every other tab is a centred row of links.
   The panel spans the header, not the item, so .gnav__item--mega goes static
   and the panel positions against .gnav itself. */
.gnav__item--mega { position: static; }
.gnav__mega {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  z-index: 100;
  background: #111;
  border-top: 1px solid rgba(255, 255, 255, .06);
  opacity: 0;
  visibility: hidden;
  transition: opacity .2s var(--ease), visibility 0s linear .2s;
}
.gnav__item--mega:hover .gnav__mega,
.gnav__item--mega:focus-within .gnav__mega {
  opacity: 1;
  visibility: visible;
  transition: opacity .2s var(--ease);
}
.gnav__mega-inner {
  width: min(1152px, 100%);
  margin-inline: auto;
  padding: 3px 24px 5px;
}
.gnav__mega-inner--cards {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 220px;
  gap: 18px;
}
.gnav__cards {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 15px;
  padding-right: 32px;
  border-right: 1px solid rgba(255, 255, 255, .08);
}
.gnav__card {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 12px 0;
  color: #fff;
  text-decoration: none;
}
.gnav__card-media {
  display: flex;
  align-items: center;
  justify-content: center;
  /* clips rather than trusting the image to constrain itself: in a grid area
     sized by its own content, max-height:100% has nothing definite to resolve
     against and the renders spilled straight out of the panel */
  overflow: hidden;
  width: 100%;
  height: 130px;
  padding: 8px;
  border-radius: 14px;
  background: rgba(255, 255, 255, .06);
  transition: background .2s var(--ease);
}
.gnav__card:hover .gnav__card-media { background: rgba(255, 255, 255, .11); }
.gnav__card-media img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.gnav__card-title { margin-top: 10px; font-size: 16px; font-weight: 700; }
.gnav__card-sub { margin-top: 2px; font-size: 13px; color: #00b3fe; }
.gnav__mega-links {
  display: flex;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
}
.gnav__mega-links--side {
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-start;
  gap: 2px;
  padding-top: 8px;
}
.gnav__mega-links a {
  padding: 9px 6px;
  font-size: 15px;
  font-weight: 500;
  color: rgba(255, 255, 255, .7);
  text-decoration: none;
  transition: color .2s var(--ease);
}
.gnav__mega-links a:hover { color: #fff; }
.gnav__mega-links a[aria-current="page"] { color: #00b3fe; }
/* divides the FSX links from our own three pages in the Software panel */
.gnav__mega-sep {
  width: 1px;
  align-self: stretch;
  margin: 6px 10px;
  background: rgba(255, 255, 255, .14);
}
.gnav__mega-links--side .gnav__mega-sep { width: auto; height: 1px; align-self: stretch; margin: 6px 0; }

/* ---- the strips retire exactly where the bar does, at 1060px, where the
   burger drawer takes over. 1280 was wrong: between 1060 and 1280 the desktop
   nav is still on screen, so the tabs sat there with no menus at all. ---- */
@media (max-width: 1060px) {
  .gnav__mega { display: none; }
}

.gnav__dd {
  position: absolute;
  left: 50%;
  top: 100%;
  transform: translateX(-50%) translateY(6px);
  min-width: 230px;
  padding: 10px;
  border-radius: 14px;
  background: rgba(8, 8, 10, .96);
  border: 1px solid rgba(255, 255, 255, .1);
  box-shadow: 0 18px 50px rgba(0, 0, 0, .5);
  opacity: 0;
  visibility: hidden;
  transition: opacity .25s var(--ease), transform .25s var(--ease), visibility 0s linear .25s;
}
.gnav__item:hover .gnav__dd,
.gnav__item:focus-within .gnav__dd {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
  transition: opacity .25s var(--ease), transform .25s var(--ease);
}
.gnav__dd a {
  display: block;
  padding: 9px 12px;
  border-radius: 8px;
  font-size: 13.5px;
  font-weight: 500;
  color: rgba(255, 255, 255, .8);
  transition: background .2s var(--ease), color .2s var(--ease);
}
.gnav__dd a:hover { background: rgba(255, 255, 255, .08); color: #fff; }
.gnav__dd a[aria-current="page"] { color: #00b3fe; }
.gnav__actions { display: flex; align-items: center; gap: 12px; flex: 0 0 auto; margin-left: auto; }
.gnav__pill {
  font-size: 13px;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
  padding: 10px 18px;
  border-radius: 27px;
  color: #fff;
  transition: background .25s var(--ease), border-color .25s var(--ease);
}
/* Brand/500, not the old cyan (user 2026-08-25) — the same blue the primary
   CTA is built from, so the bar's one colour accent matches the buttons */
.gnav__pill--specials { background: var(--blue, #0348d9); }
.gnav__pill--specials:hover { background: #1257ea; }
.gnav__pill--ghost { border: 1.5px solid rgba(255, 255, 255, .85); }
.gnav__pill--ghost:hover { border-color: #fff; background: rgba(255, 255, 255, .08); }
.gnav__icon {
  position: relative;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  color: #fff;
}
.gnav__icon svg { width: 20px; height: 20px; }
.gnav__burger {
  display: none; /* mobile only — the drawer takes over below 1280px */
  appearance: none;
  background: none;
  border: 0;
  cursor: pointer;
  flex-direction: column;
  gap: 5px;
  padding: 10px 2px;
}
.gnav__burger span { display: block; width: 22px; height: 2px; background: #fff; border-radius: 1px; }
.gnav__scrim {
  position: fixed;
  inset: 0;
  z-index: 190;
  background: rgba(0, 0, 0, .5);
  opacity: 0;
  visibility: hidden;
  transition: opacity .4s var(--ease), visibility 0s linear .4s;
}
/* right-hand drawer, same recipe as the live site's burger menu */
.gnav__menu {
  position: fixed;
  inset: 0 0 0 auto;
  z-index: 200;
  width: min(600px, 100vw);
  background: #000;
  padding: clamp(56px, 9vh, 84px) clamp(28px, 5vw, 60px) 48px;
  overflow-y: auto;
  transform: translateX(100%);
  visibility: hidden;
  transition: transform .5s var(--ease), visibility 0s linear .5s;
}
.gnav.menu-open .gnav__scrim { opacity: 1; visibility: visible; transition: opacity .4s var(--ease); }
.gnav.menu-open .gnav__menu { transform: none; visibility: visible; transition: transform .5s var(--ease); }
.gnav__close {
  position: absolute;
  top: 20px;
  right: 24px;
  appearance: none;
  background: none;
  border: 0;
  cursor: pointer;
  color: #fff;
  padding: 8px;
}
.gnav__close svg { width: 18px; height: 18px; display: block; }
.gnav__group { margin-bottom: clamp(28px, 4.5vh, 44px); }
.gnav__group-title {
  display: inline-block;
  font-family: "Termina", "Roboto", var(--font);
  font-size: clamp(26px, 3.2vw, 34px);
  font-weight: 700;
  letter-spacing: .01em;
  color: #fff;
  margin-bottom: 14px;
}
.gnav__group ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  column-gap: 28px;
  row-gap: 12px;
}
.gnav__group ul a { color: rgba(255, 255, 255, .6); font-size: 17px; transition: color .2s var(--ease); }
.gnav__group ul a:hover { color: #fff; }
.gnav__group ul a[aria-current="page"] { color: #00b3fe; }
.gnav__foot { display: flex; gap: 28px; margin-top: 8px; }
.gnav__foot a {
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.gnav__foot a:hover { color: #00b3fe; }
/* squeeze tier: keep the full nav alive on laptop widths before collapsing */
@media (max-width: 1380px) {
  .gnav__inner { gap: 14px; }
  .gnav__brand img { height: 16px; }
  .gnav__nav { gap: 11px; }
  .gnav__link { font-size: 11px; letter-spacing: .05em; }
  .gnav__pill { font-size: 12px; padding: 9px 14px; }
  .gnav__icon { width: 32px; }
  .gnav__actions { gap: 8px; }
}
@media (max-width: 1060px) {
  .gnav__nav,
  .gnav__pill--ghost { display: none; }
  .gnav__burger { display: inline-flex; }
}
@media (max-width: 640px) {
  .gnav__pill--specials,
  .gnav__icon--cart { display: none; }
  .gnav__brand img { height: 16px; }
}

.localnav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  background: rgba(8, 8, 10, .4);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid transparent;
  transition: background .4s var(--ease), border-color .4s var(--ease);
}
.localnav.scrolled {
  background: rgba(8, 8, 10, .72);
  border-color: rgba(255, 255, 255, .08);
}

.localnav__inner {
  width: min(1320px, 94vw); /* matches .container-wide — the why-cards row sets the page max width */
  margin-inline: auto;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

.localnav__brand { display: flex; align-items: center; }
.localnav__brand img { height: 14px; width: auto; }

.localnav__links {
  position: relative;
  display: flex;
  gap: 28px;
  font-size: .875rem; /* Text sm/Semibold */
  font-weight: 600;
  line-height: 1.43;
  color: var(--ink-d2);
}
.localnav__links a { transition: color .3s; }
.localnav__links a:hover,
.localnav__links a.active { color: var(--ink-d1); }

.localnav__ind {
  position: absolute;
  top: calc(100% + 3px);
  left: 0;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--blue);
  opacity: 0;
  pointer-events: none;
  transition: transform .45s var(--ease), opacity .3s var(--ease);
  will-change: transform;
}
.localnav__ind.on { opacity: 1; }

.localnav__actions { display: flex; align-items: center; gap: 14px; }

.localnav__burger {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 34px;
  height: 34px;
  padding: 6px;
}
.localnav__burger span {
  display: block;
  height: 1.5px;
  background: var(--ink-d1);
  transition: transform .35s var(--ease), opacity .35s;
}
.menu-open .localnav__burger span:first-child { transform: translateY(3.25px) rotate(45deg); }
.menu-open .localnav__burger span:last-child  { transform: translateY(-3.25px) rotate(-45deg); }

.localnav__sheet {
  display: none;
  flex-direction: column;
  padding: 12px 4vw 26px;
  gap: 4px;
}
.localnav__sheet a {
  padding: 12px 4px;
  font-size: 1.125rem; /* Text lg/Semibold */
  font-weight: 600;
  color: var(--ink-d1);
  border-bottom: 1px solid rgba(255, 255, 255, .08);
}
.menu-open .localnav__sheet { display: flex; }
.menu-open { background: rgba(8, 8, 10, .96); }

/* ==========================================================================
   1 · HERO
   ========================================================================== */

.hero {
  padding: calc(var(--nav-h) + clamp(64px, 11vh, 120px)) 0 40px;
  text-align: center;
  position: relative;
  overflow: clip;
}
.hero::before {
  /* soft brand glow behind the stage */
  content: "";
  position: absolute;
  left: 50%;
  top: 46%;
  width: 1200px;
  height: 700px;
  transform: translateX(-50%);
  background: radial-gradient(closest-side, rgba(3, 72, 217, .18), transparent 70%);
  pointer-events: none;
  z-index: 1; /* glow above the dot field — same stack as the closer */
}
.hero__copy { position: relative; z-index: 2; }

/* Ambient dot-field canvas (js/dot-field.js), per Figma 11902:3701. The
   design's overlay is a black gradient born opaque at the bottom edge and
   gone by half height (transform resolves to exactly 2×), so the dots live
   in the top half and dissolve behind the copy. Over a black section a mask
   is visually identical to that overlay and keeps the glow stacking simple. */
.hero__shader {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  display: block;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(to top, transparent 0%, #000 50%);
          mask-image: linear-gradient(to top, transparent 0%, #000 50%);
}

.hero__kicker { display: flex; justify-content: center; }
.hero__kicker img { height: clamp(15px, 1.6vw, 21px); width: auto; }

.hero__title {
  /* Display 3xl/Bold — 96/120, −2% */
  font-size: clamp(3.2rem, 8.5vw, 6rem);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -.02em;
  margin-top: .5rem;
}

.hero__lede {
  /* Text xl — 20/30 */
  font-size: clamp(1.1rem, 1.4vw, 1.25rem);
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: 0;
  color: var(--ink-d2);
  max-width: 46ch;
  margin: 1.4rem auto 0;
}

.hero .cta-row { justify-content: center; }

/* --- Legend dots --- */

.dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--blue-light);
  display: inline-block;
  flex: none;
}
.dot--white { background: #f5f5f7; }
.dot--green { background: var(--blue-light); }

/* ==========================================================================
   3 · WHY PREMIER — three exported artboards (per Figma)
   ========================================================================== */

.why {
  padding: clamp(90px, 11.1vw, 160px) 0; /* py-160 per Figma */
  background: var(--white);
}

.why__head { text-align: center; }

.why__title {
  /* Display xl/Bold — 60/72, −2% per Figma */
  font-size: clamp(2.3rem, 4.17vw, 3.75rem);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -.02em;
  color: #000;
}

.why__sub {
  margin-top: .8rem; /* was 8px — the one header running tighter than the rest */
  font-size: clamp(1.25rem, 1.67vw, 1.5rem);
  font-weight: 600;
  letter-spacing: -.01em;
  line-height: 1.333;
  color: rgba(0, 0, 0, .5);
}

/* Card geometry + caption ramp mirror the analysis gallery (`.ag`) 1:1 —
   user 2026-07-30: "misma sección See every shot". Tiles 372×450 r28 gap 20. */
.why__grid {
  margin-top: clamp(44px, 6vh, 72px);
  width: min(1156px, 94vw); /* 3×372 + 2×20, like the ag tile row */
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}

/* min-width: 0 defeats the automatic minimum size of a grid/flex item. Without
   it WebKit sizes .why-card from its aspect-ratio and never shrinks it back
   when the column narrows — the card kept a stale 343px inside a 328px grid
   after a viewport change and hung 15px past the margin. Chrome reflows it, so
   this only ever showed up on Safari (i.e. on a phone being rotated). */
.why-col { display: flex; flex-direction: column; min-width: 0; }

.why-card {
  aspect-ratio: 372 / 450;
  min-width: 0;
  border-radius: 28px;
  overflow: hidden;
  background: #222;
}
.why-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.why-cap {
  /* = .ag-tile__caption */
  padding: 28px 0 0;
  font-size: 17px;
  line-height: 1.2353;
  font-weight: 600;
  letter-spacing: -.022em;
  color: var(--ink-l2);
}
.why-cap h3 { font: inherit; color: var(--ink-l1); }
.why-cap p { margin: .35em 0 0; }

/* ==========================================================================
   4 · PLAY — parallax hero (per Figma)
   ========================================================================== */

/* Everything is measured in design px of the 1440×850 Figma frame through the
   local --px unit: proportional below 1440, capped at 1:1 above it, so the
   type stays pixel-registered with the horizon at every width. */
.playhero {
  --px: min(0.069444vw, 1px); /* 1 design px */
  position: relative;
  height: calc(850 * var(--px));
  overflow: clip;
  isolation: isolate;
  background: #0a1520;
}

.playhero__layer {
  /* one 2624-wide scene render, centered; the cutout is the same render
     cropped to the top 552 with the sky alpha'd out (assets pre-cropped) */
  position: absolute;
  left: 50%;
  top: 0;
  width: calc(2624 * var(--px));
  max-width: none;
  height: auto;
  transform: translateX(-50%);
  will-change: transform;
}
.playhero__scene { z-index: 0; }
.playhero__cutout { z-index: 3; }

.playhero__fade {
  /* sits UNDER the type per Figma — it darkens the scene, not the headline */
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: calc(301 * var(--px));
  background: linear-gradient(0deg, #000, transparent);
  z-index: 1;
}

.playhero__back, .playhero__front {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.playhero__back { z-index: 2; }
.playhero__back--ghost { z-index: 4; }
.playhero__front { z-index: 5; }

.playhero__l1, .playhero__l2 {
  position: absolute;
  font-size: calc(196.579 * var(--px));
  font-weight: 700;
  line-height: .8;
  letter-spacing: -.05em;
  /* Word gap = 35.57 + this (natural space 45.4 + tracking −9.83). Figma's
     16.25 read glued on screen (the y tail eats the air), so this runs wider:
     ≈28 design px. To open it further, make the number less negative. */
  word-spacing: calc(-7.6 * var(--px));
  color: #fff;
  white-space: nowrap;
}
.playhero__l1 { left: calc(64 * var(--px)); top: calc(307.93 * var(--px)); }
.playhero__l2 { right: calc(64 * var(--px)); top: calc(436 * var(--px)); }
.playhero__back--ghost .playhero__l1 { color: transparent; }
.playhero__back--ghost b { color: #fff; font-weight: inherit; }

/* copy (per Figma 11802:93794) — Text/DemiBold 24/1.2, centered 540 box,
   bottom-anchored over the fade; floors keep it readable below ~900px */
.playhero__copy {
  position: absolute;
  left: 50%;
  bottom: max(calc(33.83 * var(--px)), 14px);
  transform: translateX(-50%);
  width: max(calc(540 * var(--px)), min(88vw, 400px)); /* floor only bites below ~1060px */
  font-size: clamp(0.95rem, calc(24 * var(--px)), 1.5rem);
  font-weight: 584;
  line-height: 1.2;
  text-align: center;
  color: #fff;
  z-index: 6;
}

/* ==========================================================================
   1b+2 · VIDEO → PRACTICE, PLAY, COMPETE (texto calado, per Figma 11843:2669)
   Coreografía 100% scroll-nativa: el pin del video y el panel calado son DOS
   stickies hermanos. El panel (slab negro con la tipografía calada vía SVG
   <mask> inline — un data-URI no puede usar la fuente del documento) entra
   1:1 con el scroll sobre el video clavado, dockea arriba y ambos quedan
   ~60vh con el video corriendo dentro de las letras. Al asomar el panel, el
   frame escala a full-bleed por detrás (solo transform, GPU) para que las
   letras siempre calen sobre video.
   ========================================================================== */

.vt {
  height: 215vh; /* 100vh pin + 100vh panel travel + 15vh hold.
                    HARD FLOOR IS 200vh: below that the panel never reaches
                    top:0, `is-docked` never fires and the white sub never
                    appears. The old 60vh hold read as the page freezing at
                    the end of the section (user 2026-08-03). */
  background: var(--black);
  position: relative;
}

.vt__pin {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  display: grid;
  place-items: start center; /* el frame pega a la sección de arriba */
  overflow: clip;
}

.vt__frame {
  position: relative;
  width: min(1360px, 95.5vw); /* ya grande por default — no hay fase de growth */
  aspect-ratio: 1312 / 738;
  max-height: 92svh;          /* ratio+max-height: el ancho queda, cover absorbe */
  min-height: 84svh;          /* viewports angostos: sin esto el 16:9 queda corto
                                 y las letras caladas caen sobre negro */
  background: var(--card-dark);
  border-radius: 28px;
  overflow: hidden;
  transform-origin: 50% 0;
  transition: transform 1.1s var(--ease), border-radius 1.1s var(--ease);
  will-change: transform;
}
.vt.is-fill .vt__frame {
  transform: scale(var(--fs, 1.2)); /* --fs = max(vw/frameW, vh/frameH), via JS */
  border-radius: 0;
}

.vt__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  animation: vt-drift 16s ease-in-out infinite alternate; /* Ken Burns en las letras */
}
@keyframes vt-drift {
  from { transform: scale(1); }
  to   { transform: scale(1.06); }
}

/* Panel negro con la tipografía calada — sticky, sube en flujo normal */
.vt__panel {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  z-index: 2;
  /* the maskart enters at scale(1.035), so it pokes ~3.5% past both sides and
     that became document scroll width (the mobile sideways-swipe). The panel
     is exactly viewport-wide, so clipping here costs nothing visually — the
     bleed was always meant to sit off-screen. */
  overflow: hidden;
}
@supports (overflow: clip) {
  /* clip keeps the panel from becoming a scroll container */
  .vt__panel { overflow: clip; }
}

.vt__maskart {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  transform: scale(1.035);     /* micro-settle: entra 3.5% grande y asienta */
  transform-origin: 50% 41%;   /* centro óptico del bloque de texto */
  transition: transform .9s var(--ease);
}
.vt.is-docked .vt__maskart { transform: none; }

.vt__masktext {
  font-family: var(--font);
  font-weight: 900; /* Black, per Figma */
  font-size: 141.068px;
  letter-spacing: -2.8214px; /* −2% per Figma 11843:2653 */
  /* The tspan y's are fixed attributes, so the gap/size relationship (125.3 /
     141.068 = .89) only holds at THIS font size — shrinking the font alone
     stretched the lines apart. Fit narrow screens by scaling the whole block
     instead: --ms is measured in main.js so the widest line always lands
     inside the screen, and the proportions stay exactly as designed. */
  transform: scale(var(--ms, 1));
  transform-box: view-box;
  transform-origin: 720px 331px; /* centre of the three-line block */
}

/* White-10% veil between the video and the black calado (user 2026-07-31):
   lifts the footage read through the letters so it separates from the #000
   mask. Fades in with .is-rising so the takeover phase keeps the clean video. */
.vt__veil {
  position: absolute;
  inset: 0;
  background: rgba(255, 255, 255, .1); /* alpha-white-10 */
  opacity: 0;
  transition: opacity .8s var(--ease);
  pointer-events: none;
  z-index: 1; /* over the video, under the media toggle (z2) */
}
.vt.is-rising .vt__veil { opacity: 1; }

/* El sub viaja EN el panel y entra CASI JUNTO al calado (user 2026-07-31):
   .is-rising se prende cuando el panel escaló la mitad del viewport, no al
   dockear — .is-docked queda para el settle del masktext. */
.vt__sub {
  position: absolute;
  left: 50%;
  top: 74.5%;
  transform: translate(-50%, 14px);
  width: min(700px, 86vw);
  text-align: center;
  font-size: clamp(1.05rem, 1.67vw, 1.5rem); /* Display xs/Semibold */
  font-weight: 584;
  line-height: 1.34;
  color: #fff;
  opacity: 0;
  transition: opacity .6s var(--ease) .18s, transform .6s var(--ease) .18s;
}
.vt.is-rising .vt__sub {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* Media play/pause toggle */
.media-toggle {
  position: absolute;
  top: 50%;
  right: 20px;
  transform: translateY(-50%);
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: rgba(210, 210, 215, .64);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  display: grid;
  place-items: center;
  z-index: 2;
  transition: background .3s var(--ease), transform .3s var(--ease);
}
.media-toggle:hover { background: rgba(223, 223, 227, .72); }
.media-toggle:active { transform: translateY(-50%) scale(.94); }
.media-toggle svg { width: 36px; height: 36px; fill: #1d1d1f; }
.media-toggle .media-toggle__play { display: none; }
.media-toggle.is-paused .media-toggle__pause { display: none; }
.media-toggle.is-paused .media-toggle__play { display: block; }

/* ==========================================================================
   4b2 · FSX COURSE MARQUEE (per Figma 11755:90740)
   Each course card is a real component built in HTML over a clean photo (see
   .crs below and js/course-cards.js) — it replaced Figma's baked 551×600 PNG
   exports, which had the type flattened into the pixels. Desktop card =
   275.217px wide with a 19.355px gap (ratio .070325), per the updated node.
   The belt loops forever in JS (rAF) and speeds up while the user scrolls;
   see main.js.
   ========================================================================== */

.fsx {
  --cw: clamp(216px, 66vw, 275.217px);
  --gap: calc(var(--cw) * .070325);
  padding: 96px 0 clamp(96px, 12vh, 160px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 48px;
}

/* clip solo en X: el arc wheel (main.js) baja las cards de los bordes ~60px
   y un clip vertical las cortaría recto */
.fsx__viewport { width: 100%; overflow-x: clip; overflow-y: visible; }

.fsx__track {
  display: flex;
  gap: var(--gap);
  width: max-content;
  padding-inline: var(--gap);
}

/* CTA — Figma FSP Button (16/10, Text md/Semibold), no trailing icon */
.fsx__cta {
  padding: 10px 16px;
  font-weight: 584;
  line-height: 1.5;
}

/* ==========================================================================
   COURSE CARD (user 2026-08-21) — replaces the baked 551x600 PNGs with a real
   component: a clean photo plus live type. Per the brief this card carries no
   bookmark, no download button and no difficulty dots — just where it is,
   what it is, and how it plays. Proportions follow the old export (551:600)
   so the marquee's rhythm is unchanged.
   ========================================================================== */

.crs { flex: none; width: var(--cw); will-change: transform; }
.crs__card {
  position: relative;
  margin: 0;
  aspect-ratio: 551 / 600;
  /* 8% of the card, not of the viewport: the PNGs this replaced carried a
     constant ~22px radius on a 275px card, and a vw-based clamp only
     reached that above a 1571px window — every real screen got a tighter
     corner than the original. --cw is the card width, so this tracks it. */
  border-radius: calc(var(--cw) * .08);
  overflow: clip;
  background: #0b0d0f;
  container-type: inline-size;   /* type scales with the card, not the page */
  /* The belt rotates each card ±3deg (the arc wheel in main.js). Without its
     own compositing layer the rounded clip is a geometric op applied at
     composite time, with no alpha ramp to rotate — so the corners stair-step
     at these shallow angles. The cards this replaced were PNGs whose rounded
     corners were baked in as an antialiased alpha ramp, which is why the old
     belt read smooth. Promoting the card rasterises the clip WITH antialiasing
     once, and the GPU then filters that texture through the rotation. */
  will-change: transform;
  backface-visibility: hidden;
}
.crs__art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* The type sits on a plain black ramp over the bottom quarter (user
   2026-08-24). This replaced a progressive blur — three blurred copies of the
   art, masked at increasing depths — which softened the bottom third of every
   card and read as airbrushed. These are 4K course renders and the section's
   whole claim is "rendered in 4K", so holding them sharp to the edge matters
   more than the depth effect. Dropping it also takes 3 of the 4 <img> per card
   and every blur() out of the compositing path. */
.crs__card::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(0, 0, 0, 0) 62%,
    rgba(0, 0, 0, .72) 82%,
    rgba(0, 0, 0, .90) 100%);
}
.crs__body {
  position: absolute;
  z-index: 1;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 0 8.5cqw 8cqw;
  text-align: center;
}
.crs__loc {
  margin: 0 0 2.2cqw;
  font-family: var(--mono);
  font-size: 3.1cqw;
  font-weight: 400;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .82);
}
.crs__name {
  margin: 0;
  font-size: 7.4cqw;
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -.02em;
  color: #fff;
}
.crs__spec {
  margin: 3cqw 0 0;
  font-family: var(--mono);
  font-size: 3.1cqw;
  font-weight: 400;
  letter-spacing: .06em;
  color: rgba(255, 255, 255, .74);
}

/* ==========================================================================
   4b3 · COURSE SHOWCASE (per Figma 11784:92145)
   Cash-App-style pinned media. The sticky stage holds one 958×539 r24 frame
   (x 634 on the 1440 canvas — it bleeds ~152px off the right edge) while the
   alternating black/white panels scroll behind it. Images stack inside the
   frame; layers 2+ are revealed with clip-path driven by their panel's top
   edge (main.js), so the section boundary doubles as the wipe line.
   ========================================================================== */

.showcase { position: relative; }

/* Full-viewport sticky stage; the panels wrapper's negative top margin lays
   the panels underneath it. The negative margin must live on the WRAPPER —
   on the sticky element itself it zeroes the sticky constraint height and
   the frame stays pinned into the next section. With it here, the stage
   unpins exactly when one viewport of section remains, so the frame rides
   out together with panel 3. */
.showcase__stage {
  position: sticky;
  top: 0;
  height: 100svh;
  z-index: 2;
  pointer-events: none;
  /* the frame is anchored at right:-8.5vw so ~16% of the card runs off-screen
     by design — clip it here instead of leaning on body's overflow-x, which
     iOS ignores (that's what let the page swipe sideways in production) */
  overflow: hidden;
}
@supports (overflow: clip) {
  .showcase__stage { overflow: clip; }
}
.showcase__panels { margin-top: -100svh; }

.showcase__frame {
  position: absolute;
  right: -8.5vw; /* keeps the design's crop: ~16% of the card runs off-edge */
  top: 50%;
  translate: 0 -50%;
  width: min(53.2vw, 108svh); /* design size −20%; height ≤ 61svh via ratio */
  aspect-ratio: 958 / 539;
  border-radius: 24px;
  overflow: hidden;
  background: var(--elev);
}
/* Split layers: the wrapper carries the wipe clip (scrubbed in main.js), the
   par shell carries the scroll parallax, and the img carries the Ken Burns
   drift. All three must stay separate — a transform on the clipped element
   drags the wipe line, and the drift would fight the parallax offset. */
.showcase__layer {
  position: absolute;
  inset: 0;
}
/* Overhangs the frame by --par-over top and bottom, so the image has room to
   drift against the scroll without ever exposing an edge — an oversized
   plate inside a clipped window. */
.showcase__par {
  position: absolute;
  inset: calc(var(--par-over) * -1) 0;
  transform: translate3d(0, var(--par, 0px), 0);
  will-change: transform;
}
.showcase__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  will-change: transform;
  animation: showcase-drift 16s ease-in-out infinite alternate;
}
/* out of phase per layer so the panels never breathe in sync */
.showcase__layer:nth-child(2) .showcase__img { animation-delay: -6s; animation-direction: alternate-reverse; }
.showcase__layer:nth-child(3) .showcase__img { animation-delay: -11s; }

/* slow zoom + diagonal drift; starts pre-scaled so edges never show */
@keyframes showcase-drift {
  from { transform: scale(1.06) translate3d(1.6%, -1%, 0); }
  to   { transform: scale(1.15) translate3d(-1.8%, 1.3%, 0); }
}

/* layers 2+ start hidden; main.js scrubs the inset down to 0 as their panel
   edge sweeps up across the frame */
.showcase__layer + .showcase__layer { clip-path: inset(100% 0 0 0); }

.showcase__panel {
  min-height: 100svh;
  display: flex;
  align-items: center;
  background: var(--black);
  color: var(--ink-d1);
}
.showcase__panel--light {
  background: var(--white);
  color: #06090f;
}

.showcase__inner { width: min(1320px, 94vw); margin-inline: auto; }

/* per-panel stills: mobile-only replacement for the pinned frame */
.showcase__still { display: none; }

.showcase__copy {
  width: min(428px, 38vw); /* stays clear of the frame at every desktop width */
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 24px;
}

/* pill tag — Text sm/Medium under the library's soft top-light */
.showcase__tag {
  padding: 9px 14px;
  border-radius: 28px;
  font-size: .875rem;
  font-weight: 492;
  line-height: 1.43;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: rgba(250, 250, 250, .6);
  background:
    radial-gradient(56% 90% at 50% 0%, rgba(185, 192, 204, .22), rgba(138, 148, 165, .04) 40%, rgba(138, 148, 165, 0) 70%),
    rgba(0, 0, 0, .2);
  border: 1px solid rgba(232, 236, 243, .08);
}
.showcase__panel--light .showcase__tag {
  color: rgba(6, 9, 15, .6);
  background: radial-gradient(56% 90% at 50% 0%, rgba(185, 192, 204, .3), rgba(138, 148, 165, .06) 40%, rgba(138, 148, 165, 0) 70%);
  border-color: rgba(6, 9, 15, .08);
}

.showcase__title {
  /* Display lg/Bold — 48/50, −2% */
  font-size: clamp(2.1rem, 3.34vw, 3rem);
  font-weight: 700;
  line-height: 1.042;
  letter-spacing: -.02em;
}
.showcase__text {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 7px; /* 24 + 7 = Figma's 31 title→text */
}
.showcase__sub {
  font-size: 1.25rem; /* Text xl/Semibold — 20/30 */
  font-weight: 584;
  line-height: 1.5;
}
.showcase__body {
  font-size: 1.125rem; /* Text lg/Medium — 18/28 */
  font-weight: 492;
  line-height: 1.556;
  color: rgba(250, 250, 250, .6);
}
.showcase__panel--light .showcase__body { color: rgba(6, 9, 15, .6); }

@media (max-width: 820px) {
  /* The pinned stage + boundary wipe is a desktop pattern. On mobile each
     panel carries its own still IN FLOW, sitting right above its tag — fixed
     to the section, not the device (user call, 2026-07-30). */
  .showcase__stage { display: none; }
  .showcase__panels { margin-top: 0; } /* no stage to overlap anymore */
  /* The still deliberately bleeds 7vw past the right edge (3vw offset +
     104vw). Nothing was cutting it, so it became the document's scroll width
     and the page swiped sideways on mobile — `body { overflow-x: clip }` masks
     this in Chrome but iOS ignores it. The panel is exactly viewport-wide, so
     clipping HERE kills the overflow at its source and keeps the crop. */
  .showcase__panel { overflow-x: hidden; }
  @supports (overflow: clip) {
    /* clip doesn't create a scroll container the way hidden does */
    .showcase__panel { overflow-x: clip; }
  }
  .showcase__still {
    display: block;
    /* left edge on the text margin, right side crops off-screen */
    width: 104vw;
    max-width: none; /* the global img reset caps width at 100% */
    height: auto;    /* the height attr would otherwise pin 1078px */
    aspect-ratio: 958 / 539;
    object-fit: cover;
    border-radius: 24px;
    margin-bottom: 28px;
  }
  .showcase__copy { width: 100%; max-width: 520px; }
}

/* ==========================================================================
   CAROUSEL MACHINERY (partly live since 2026-07-30)
   `.paddle` is now used by the analysis gallery (`.ag`), whose stepping
   lives in main.js. The `.gallery` / `.gallery-wrap` scroll-snap row below
   is still dormant (the old 4c course slider); reviving it needs its own
   wiring — main.js now targets `.ag__scroller`, not `.gallery`.
   ========================================================================== */

.gallery-wrap { margin-top: clamp(48px, 7vh, 90px); padding-bottom: clamp(90px, 12vh, 150px); }

.gallery {
  display: flex;
  gap: clamp(20px, 2.8vw, 40px);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: max(4vw, calc((100vw - 1320px) / 2));
  scrollbar-width: none;
  padding: 6px max(4vw, calc((100vw - 1320px) / 2)) 26px;
}
.gallery::-webkit-scrollbar { display: none; }

.gallery-paddles {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}
.paddle {
  /* media-control style */
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: rgba(210, 210, 215, .64);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  color: #1d1d1f;
  display: grid;
  place-items: center;
  transition: background .3s, opacity .3s, transform .3s var(--ease);
}
.paddle svg { width: 36px; height: 36px; transition: transform .35s var(--ease); }
.paddle:hover:not(:disabled) { background: rgba(223, 223, 227, .72); }
/* the chevron peeks 2px in its travel direction */
.paddle:hover:not(:disabled) svg { transform: translateX(2px); }
.paddle[data-dir="-1"]:hover:not(:disabled) svg { transform: translateX(-2px); }
.paddle:active:not(:disabled) { transform: scale(.94); }
.paddle:disabled { opacity: .36; cursor: default; }

/* ==========================================================================
   5 · REALISM SPLIT
   ========================================================================== */

/* Full-bleed video background with the copy over it (per Figma 11753:6362 —
   video plus a flat rgba(0,0,0,.2) scrim). The scrubbed split graphic is gone,
   so the section no longer needs the sticky pin. */
.realism {
  position: relative;
  isolation: isolate;
  overflow: clip;
  display: flex;
  align-items: center;
  min-height: min(720px, 86vh);
  padding: clamp(64px, 10vh, 120px) 0;
}

/* Expanding mask, shared by every [data-clip] plate (the realism video and the
   venues backdrop): one progress value drives BOTH the side inset and the
   corner radius, so the window widens and squares off in a single move.
   --clip runs 1 → 0 (windowed → full-bleed), scrubbed in main.js. The inset
   is horizontal only — the band's own height frames it. */
[data-clip] {
  --clip: 1;
  clip-path: inset(0 calc(var(--clip) * 6.25vw) round calc(var(--clip) * 28px));
  will-change: clip-path;
}
.realism__media {
  position: absolute;
  inset: 0;
  z-index: -1;
}

.realism__video {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.realism__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  /* Figma specifies a flat rgba(0,0,0,.2), but its mock used a much darker frame
     than this footage: over the bright grass the gray lede fell to 4.4:1. Raised
     to .35 and the lede is white here, which puts both well past AA. */
  background: rgba(0, 0, 0, .35);
}

.realism__head { text-align: center; }
.realism__head .lede {
  max-width: 48ch;
  margin-inline: auto;
  font-weight: 600;
  color: rgba(255, 255, 255, .85);
}

/* ==========================================================================
   6 · ANALYSIS BENTO
   ========================================================================== */

.analysis { padding: clamp(96px, 14vh, 170px) 0; }
.analysis__pin > .container:first-of-type { text-align: center; }
.analysis__pin > .container:first-of-type .lede { margin-inline: auto; }

/* --- Analysis gallery — caption-tile carousel.
   Card 372×450 (344×416 ≤1068), radius 28, gap 20,
   caption 17/600 below the tile, full-bleed snap row starting at the
   content inset. ≤734 stacks the tiles (user request). Gray card blocks
   are placeholders until the real imagery lands. --- */

.ag {
  --ag-inset: max(3vw, calc((100vw - 1320px) / 2));
  --ag-card-w: 372px;
  --ag-card-h: 450px;
  --ag-gap: 20px;
  margin-top: clamp(44px, 6vh, 72px);
}
.ag__scroller {
  overflow-x: scroll;
  scrollbar-width: none;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--ag-inset);
  /* breathing room so nothing clips, mirrored away */
  padding: 10px 0 14px;
  margin: -10px 0 -14px;
}
.ag__scroller::-webkit-scrollbar { display: none; }

.ag__set {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: var(--ag-card-w);
  gap: 0 var(--ag-gap);
  width: fit-content;
  padding-inline: var(--ag-inset);
  margin: 0;
}

.ag-tile { display: flex; flex-direction: column; scroll-snap-align: start; }
.ag-tile:last-child { scroll-snap-align: end; }

/* the media card — Figma 2x exports; gray shows only while loading */
.ag-tile__card {
  order: 1;
  height: var(--ag-card-h);
  border-radius: 28px;
  background: #e3e3e8;
  overflow: hidden;
}
.ag-tile__card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
}

/* caption under the card: title on top, copy below, flush with the card
   edge (user 2026-07-30 — no side inset) */
.ag-tile__caption {
  order: 2;
  padding: 28px 0 0;
  font-size: 17px;
  line-height: 1.2353;
  font-weight: 600;
  letter-spacing: -.022em;
  color: var(--ink-l2);
}
.ag-tile__caption h3 { display: block; font: inherit; color: var(--ink-l1); }
.ag-tile__caption p  { display: block; margin: .35em 0 0; }

.ag__paddles {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  margin-top: 28px;
  padding-inline: var(--ag-inset);
}

@media (max-width: 1068px) {
  .ag { --ag-card-w: 344px; --ag-card-h: 416px; }
}
@media (max-width: 734px) {
  /* mobile: stacked, one tile under the other, full image (no crop) */
  .ag__scroller { overflow-x: visible; padding: 0; margin: 0; }
  .ag__set {
    grid-auto-flow: row;
    grid-auto-columns: unset;
    gap: 40px 0;
    width: auto;
  }
  .ag-tile__card { width: 100%; height: auto; }
  .ag-tile__card img { height: auto; }
  /* Text md/Semibold (16/24) — the caption reads too small at 14 on a phone */
  .ag-tile__caption { padding-top: 24px; font-size: 16px; line-height: 1.5; letter-spacing: -.016em; }
  .ag__paddles { display: none; }
}

/* Desktop scroll-driven mode: main.js adds .analysis--pin (≥735, motion OK),
   sizes --ag-extra to the row's overflow, and scrubs scrollLeft against the
   pin. Without JS or with reduced motion the class never lands and the
   carousel stays free-scrolling. */
.analysis--pin {
  /* the user's "3×" air lives OUTSIDE the pinned frame, as white entry/exit
     stretches around it — cramming it INSIDE the 100svh pin shrank the tiles
     until the whole row fit and the carousel had nothing to scroll */
  --ag-air-t: clamp(120px, 15svh, 210px);
  --ag-air-b: clamp(96px, 12svh, 170px);
  padding: 0;
  height: calc(100svh + var(--ag-extra, 820px) + var(--ag-air-t) + var(--ag-air-b));
  /* BFC: without this the pin's --ag-air margins collapse through the
     section edge and render as a BLACK band over <main> between the realism
     video and this white section (the "video cortado" bug) */
  display: flow-root;
}
.analysis--pin .analysis__pin {
  position: sticky;
  top: 0;
  height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* compact breathing room inside the pinned frame */
  padding: max(5svh, 40px) 0 max(4svh, 32px);
  margin-top: var(--ag-air-t);
  margin-bottom: var(--ag-air-b);
}
.analysis--pin .ag__scroller { scroll-snap-type: none; }

/* pinned mode fits ONE viewport: the tile scales with svh (same 372:450
   ratio as the 744×900 exports, so cover never crops) and the vertical
   chrome compresses on short screens */
.analysis--pin .ag {
  --ag-card-h: min(450px, 54svh);
  --ag-card-w: calc(min(450px, 54svh) * .82667);
  margin-top: clamp(16px, 3.5svh, 56px);
}
/* pinned: page scroll IS the control, so the paddles are redundant — hidden
   (user 2026-07-30). They still render in the fallback free-scroll row, where
   they're the only way to advance. */
.analysis--pin .ag__paddles { display: none; }
.analysis--pin .ag-tile__caption {
  padding-top: clamp(14px, 2.6svh, 28px);
  /* type follows the tile so long captions stop forcing tiny cards:
     17px at the full 372 width, floor 13.5px */
  font-size: clamp(13.5px, calc(var(--ag-card-w) / 22), 17px);
}
/* (short-viewport residue is trimmed by the JS fit pass in sizePin —
   it measures real overflow instead of guessing with svh tiers) */

.analysis .footnote { margin-top: clamp(44px, 6vh, 64px); margin-inline: auto; text-align: center; }

/* --- LEGACY BENTO (markup now lives only in analysis-lab.html as reference;
   these rules stay so the lab keeps rendering the old SVG mocks) --- */

.bento {
  margin-top: clamp(40px, 6vh, 70px);
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 18px;
}

.bento-card {
  background: var(--white);
  border-radius: var(--r-card);
  padding: clamp(24px, 2.6vw, 34px);
  display: flex;
  flex-direction: column;
  gap: 22px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, .05);
}
.bento-card--7 { grid-column: span 6; }
.bento-card--5 { grid-column: span 6; }
.bento-card--4 { grid-column: span 4; }

.bento-card h3 {
  font-size: 1.4rem;
  font-weight: 700;
  letter-spacing: -.017em;
  margin-bottom: .45rem;
}
.bento-card header p { color: var(--ink-l2); font-size: .99rem; max-width: 46ch; }

.panel {
  background: #0d0d10;
  border-radius: var(--r-panel);
  padding: 18px;
  margin-top: auto;
  color: var(--ink-d1);
}
.panel--center { display: flex; flex-direction: column; align-items: center; gap: 10px; }

/* Data tiles */
.tiles {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}
.tile {
  background: #17171b;
  border-radius: 12px;
  padding: 12px 12px 10px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}
.tile span {
  font-size: .56rem;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--ink-d3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tile b {
  font-family: var(--mono);
  font-size: clamp(.95rem, 1.6vw, 1.3rem);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.tile i { font-style: normal; font-size: .6rem; color: var(--ink-d2); text-transform: uppercase; letter-spacing: .08em; }

/* Dispersion + face */
.disp, .face { width: 100%; height: auto; }
.legend {
  display: flex;
  gap: 18px;
  font-family: var(--mono);
  font-size: .66rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-d2);
}
.legend span { display: inline-flex; align-items: center; gap: 7px; }
.legend--chips { flex-wrap: wrap; gap: 8px; }
.chip-sm {
  padding: 5px 10px;
  border-radius: 8px;
  background: #1b1b20;
  border: 1px solid rgba(255, 255, 255, .1);
  font-size: .62rem;
  white-space: nowrap;
}

/* Tags */
.tagcloud { display: flex; flex-wrap: wrap; gap: 9px; margin-top: auto; }
.tag {
  padding: 8px 15px;
  border-radius: 980px;
  border: 1px solid var(--line-l);
  font-size: .86rem;
  font-weight: 600;
  color: var(--ink-l2);
  background: var(--white);
}
.tag--on {
  background: #041030;
  border-color: #041030;
  color: #7fb2ff;
}
.tag--ghost { border-style: dashed; color: rgba(29, 29, 31, .45); }

/* MyBag */
.bag { display: flex; flex-direction: column; gap: 9px; }
.bag__row {
  display: grid;
  grid-template-columns: 30px 1fr 40px;
  align-items: center;
  gap: 12px;
  font-family: var(--mono);
  font-size: .78rem;
}
.bag__row span { color: var(--ink-d3); text-transform: uppercase; }
.bag__row b { font-variant-numeric: tabular-nums; text-align: right; font-weight: 600; }
.bag__bar { height: 7px; border-radius: 4px; background: #202026; overflow: hidden; }
.bag__bar i {
  display: block;
  height: 100%;
  width: var(--w);
  border-radius: 4px;
  background: linear-gradient(90deg, #1e6dff, var(--blue-light));
}
.bag__gap {
  justify-self: start;
  margin-left: 42px;
  padding: 3px 9px;
  border-radius: 6px;
  border: 1px dashed rgba(255, 214, 10, .5);
  color: #ffd60a;
  font-family: var(--mono);
  font-size: .6rem;
  letter-spacing: .09em;
  text-transform: uppercase;
}

.analysis .footnote { margin-top: 26px; text-align: center; }

/* ==========================================================================
   8 · FORESIGHT+
   ========================================================================== */

/* bottom −32.5% total (user 2026-07-31: −25%, then −10% more): the deck→Tiers
   gap is this padding + the stack's own padding-bottom + .tiers' padding-top,
   so all three are cut by the same factor to shrink the total evenly at every
   viewport instead of collapsing at one breakpoint */
.plus { padding: clamp(96px, 14vh, 170px) 0 clamp(65px, 9.45vh, 115px); }
.plus__head { text-align: center; }
.plus__head .lede { margin-inline: auto; }

/* Stacked cards: Mobile slides up over Premier on scroll (sticky deck).
   Geometry per Figma 11712:27951 — 1204×520 cards, radius 26. */
.stack {
  width: min(1204px, 94vw);
  display: flex;
  flex-direction: column;
  gap: 40px;
  margin-top: clamp(80px, 12vh, 140px);
  padding-bottom: 10.8vh; /* was 16vh — same −32.5% pass as .plus/.tiers */
}

.stack-card {
  position: sticky;
  overflow: hidden;
  border-radius: 26px;
  background: #080507;
  height: clamp(420px, 36.12vw, 520px);
  isolation: isolate;
  will-change: transform;
}
.stack-card--sim {
  top: calc(var(--nav-h) + 24px);
  transform-origin: top center;
  background: #151515;
}
.stack-card--sim::before {
  width: 8.5%;
  background: linear-gradient(90deg, rgba(21, 21, 21, 0), #151515);
}
.stack-card--sim::after {
  height: 26%;
  background: linear-gradient(180deg, rgba(21, 21, 21, 0), #151515);
}
.stack-card--mobile { top: calc(var(--nav-h) + 69px); }

/* oversized plate so the photo can drift with the scroll (see --par-over) */
.stack-card__par {
  position: absolute;
  inset: calc(var(--par-over) * -1) 0;
  z-index: 0;
  transform: translate3d(0, var(--par, 0px), 0);
  will-change: transform;
}
.stack-card__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}

.stack-card__art {
  position: absolute;
  left: 46.7%;
  top: -43%;
  width: 63%;
  /* parallax rides in front of the pose — the rotation must stay last */
  transform: translate3d(0, var(--par, 0px), 0) rotate(-24.47deg);
  z-index: 0;
  will-change: transform;
}
.stack-card__art img { width: 100%; height: auto; }

/* right + bottom fades per Figma */
.stack-card::before,
.stack-card::after {
  content: "";
  position: absolute;
  z-index: 1;
  pointer-events: none;
}
.stack-card::before {
  /* right fade hangs partly off-card per Figma (visible ≈ 5.6%) */
  top: 0; bottom: 0;
  right: -2.9%;
  width: 8.5%;
  background: linear-gradient(90deg, rgba(0, 0, 0, 0), #000);
}
.stack-card::after {
  /* bottom fade: right-anchored under the art, darkest point clipped below
     the card edge, left flank feathered so no seam shows */
  right: -3%; bottom: -8%;
  width: 48%;
  height: 34%;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0), #000);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 38%);
  mask-image: linear-gradient(90deg, transparent, #000 38%);
}

.stack-card__copy {
  position: absolute;
  z-index: 2;
  top: clamp(24px, 3vw, 43px);
  left: clamp(22px, 2.8vw, 40px);
  max-width: min(525px, 86%);
}
.stack-card__tag {
  /* Mono md/Regular — 16/24 */
  font-family: var(--mono);
  font-size: clamp(.85rem, 1.11vw, 1rem);
  line-height: 1.5;
  text-transform: uppercase;
  color: #fff;
}
.stack-card__copy h3 {
  /* Display lg/Semibold — 48/60, −2% */
  margin-top: 2px;
  font-size: clamp(1.8rem, 3.33vw, 3rem);
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -.02em;
  color: #fff;
}
.stack-card__copy p:last-child {
  /* Text lg/Medium — 18/28, 60% white */
  margin-top: 16px;
  font-size: clamp(1rem, 1.25vw, 1.125rem);
  font-weight: 500;
  line-height: 1.556;
  letter-spacing: 0;
  color: rgba(250, 250, 250, .6); /* Alpha/Text/Tertiary */
  max-width: min(393px, 90%);
}

/* ==========================================================================
   9 · TIERS
   ========================================================================== */

.tiers { padding: clamp(65px, 9.45vh, 115px) 0 clamp(96px, 14vh, 170px); background: var(--black); } /* top −32.5%, see .plus */
.tiers > .container:first-of-type { text-align: center; }
.tiers > .container:first-of-type .lede { margin-inline: auto; }

.tiers__grid {
  margin-top: clamp(40px, 6vh, 64px);
  width: min(1204px, 94vw); /* 3×388 + 2×20 per Figma */
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  align-items: stretch;
}

/* Glass tier cards (per Figma): radial glow from top center + tinted border.
   The glow lives on ::before so it can breathe (slow pulse + drift). */
.tier-card {
  position: relative;
  overflow: hidden;
  border-radius: 28px;
  padding: clamp(28px, 2.8vw, 40px);
  display: flex;
  flex-direction: column;
  gap: 14px;
  color: var(--ink-d1);
  border: none; /* the line is the gradient ring layer per Figma */
  background: rgba(0, 0, 0, .2);
}
.tier-card--gold { gap: 16px; }
.tier-card > * { position: relative; z-index: 2; }
.tier-card {
  transition: opacity .9s var(--ease) var(--d, 0s), transform .5s var(--ease);
}
.tier-card:hover { transform: scale(1.02); }
.tier-card::before {
  content: "";
  position: absolute;
  inset: -12% -10%;
  z-index: 1;
  background: radial-gradient(70% 42% at 50% 6%, rgba(76, 76, 76, .24), rgba(76, 76, 76, .05) 42%, transparent 70%);
  animation: glow-breathe 7s ease-in-out infinite alternate;
  pointer-events: none;
}

/* rotating border line (Silver/Gold): luminous arc merging into black; Free stays static */
.tier-card .tier-card__ring {
  position: absolute;
  inset: 0; /* must stay inside the padding box — .tier-card's overflow:hidden clips there */
  border-radius: 27px;
  overflow: hidden;
  z-index: 0;
  pointer-events: none;
  /* Figma stroke: diagonal #E8ECF3→#B9C0CC→#8A94A5 at 10% */
  background: linear-gradient(108deg,
    rgba(232, 236, 243, .1), rgba(185, 192, 204, .1) 55%, rgba(138, 148, 165, .1));
}
.tier-card--silver .tier-card__ring {
  /* same ramp, born transparent, at 20% */
  background: linear-gradient(108deg,
    rgba(232, 236, 243, 0), rgba(185, 192, 204, .2) 55%, rgba(138, 148, 165, .2));
}
.tier-card--gold .tier-card__ring {
  /* Figma stroke: transparent → #F5C260 45% → #C88A1F, full opacity */
  background: linear-gradient(108deg,
    rgba(255, 233, 168, 0), #f5c260 45%, #c88a1f);
}
.tier-card--free .tier-card__ring i { display: none; }
.tier-card__ring i {
  /* Silver & Gold: identical geometry — same from-angle, same stops (0/55/110°),
     same duration, zero delay. Only the color differs. */
  position: absolute;
  inset: -60%;
  background: conic-gradient(from 0deg,
    transparent 0deg, rgba(201, 210, 223, .85) 55deg, transparent 110deg);
  animation: line-rotate 6s linear infinite;
}
.tier-card--gold .tier-card__ring i {
  background: conic-gradient(from 0deg,
    transparent 0deg, rgba(255, 223, 154, .95) 55deg, transparent 110deg);
}
.tier-card__ring b {
  position: absolute;
  inset: 1px;
  border-radius: 26px;
  background: #000; /* matches the page black so Silver/Gold read like Free's fill */
}
@keyframes line-rotate { to { transform: rotate(360deg); } }
.tier-card--silver::before {
  background: radial-gradient(70% 42% at 50% 6%, rgba(185, 192, 204, .24), rgba(138, 148, 165, .05) 42%, transparent 70%);
}
.tier-card--gold::before {
  background: radial-gradient(70% 42% at 50% 6%, rgba(245, 194, 96, .3), rgba(200, 138, 31, .09) 42%, transparent 70%);
}

@keyframes glow-breathe {
  from { opacity: .6; transform: translateY(0) scale(1); }
  to   { opacity: 1;  transform: translateY(3.5%) scale(1.07); }
}

.tier-card__head {
  display: flex;
  align-items: center;
  gap: 20px;
  padding-bottom: 14px;
  border-bottom: 1px solid rgba(255, 255, 255, .1);
  min-height: 86px; /* 72 head + 14 divider gap per Figma */
}
/* Figma clips the 72px medal into a 59.143px badge box, trimming its transparent
   margin. Negative insets give the same layout width without cropping the art. */
.tier-card__medal { width: 72px; height: 72px; flex: none; margin-inline: -6.43px; }
/* Video medals (Silver/Gold): the mp4 is cropped to the medal's edge — no
   transparent margin like the PNGs — so it renders at 69px (tiers-lab tuning)
   while keeping the PNG's 59.14px layout footprint. mix-blend-mode: screen
   drops the video's black background over the dark card. */
.tier-card__medal--video {
  width: 69px;
  height: 69px;
  margin-inline: -4.93px; /* (59.14 − 69) / 2 */
  object-fit: cover;
  mix-blend-mode: screen;
  pointer-events: none;
}
.tier-card__medal--silver { filter: grayscale(1) brightness(.91) contrast(1.01); }

.tier-card__name {
  font-size: 1.125rem; /* Text lg/Semibold — 18/28, wght 584 per the library style */
  font-weight: 584;
  line-height: 1.556;
  color: rgba(250, 250, 250, .6); /* Alpha/Text/Tertiary */
}
.tier-card h3 {
  /* Display sm/Bold — 30/38 */
  font-size: clamp(1.5rem, 2.1vw, 1.875rem);
  font-weight: 700;
  letter-spacing: 0;
  line-height: 1.267;
  color: #f5f5f6;
}
.tier-card__kicker {
  /* Text lg/Semibold — 18/28, wght 584 */
  font-size: 1.125rem;
  font-weight: 584;
  line-height: 1.556;
  color: rgba(250, 250, 250, .8); /* Alpha/Text/Secondary */
}

.tier-card ul {
  /* Text md/Regular — 16/24, rows gap 8, kicker→list 20 per Figma */
  margin-top: 6px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: clamp(.95rem, 1.15vw, 1rem);
  color: rgba(250, 250, 250, .8); /* Alpha/Text/Secondary */
}
.tier-card li {
  position: relative;
  padding-left: 30.755px; /* 18.755 check + 12 gap per Figma */
  line-height: 1.5;
}
.tier-card li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 2px;
  width: 18.755px;
  height: 18.755px;
  border-radius: 50%;
  background: #8a919c;
  -webkit-mask: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M10 1a9 9 0 100 18 9 9 0 000-18zm4.2 6.4l-4.9 5.4a.9.9 0 01-1.32.03L5.7 10.5a.9.9 0 111.27-1.27l1.6 1.6 4.28-4.7a.9.9 0 111.34 1.2z"/></svg>') center / contain no-repeat;
  mask: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M10 1a9 9 0 100 18 9 9 0 000-18zm4.2 6.4l-4.9 5.4a.9.9 0 01-1.32.03L5.7 10.5a.9.9 0 111.27-1.27l1.6 1.6 4.28-4.7a.9.9 0 111.34 1.2z"/></svg>') center / contain no-repeat;
}
.tier-card--silver li::before { background: #c3cbd6; }
.tier-card--gold li::before { background: #e5b34c; }

/* the Compare Plans trigger rides the footer's own 14px flex gap —
   same rhythm as Premier's "Learn more" above its footnote */
.tiers__foot .link-arrow--lg {
  margin-top: 0;
  margin-bottom: 0;
}

.tiers__foot {
  margin-top: clamp(40px, 4.6vh, 56px);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 14px;
}
.tiers__foot .footnote { max-width: 58ch; }

/* ==========================================================================
   10 · COURSE LIBRARY
   ========================================================================== */

.library { padding: clamp(96px, 14vh, 170px) 0; }
.library > .container:first-of-type { text-align: center; }
.library > .container:first-of-type .lede { margin-inline: auto; }

/* Course fan (per Figma 11720:28361) — Figma's own isolated card renders
   (get_screenshot contentsOnly:true; flat exports bake the #F5F5F5 canvas),
   layered so the fan can open slightly. Shown at 70% of the design's 402×268.
   Offsets are the design's geometry in % of the 402×268 box; the centre one
   was cross-checked against the flat render by pixel correlation (<1px off).
   The downward dissolve is the flat render's own alpha ramp, measured:
   opaque to 64/268, gone by 175/268. */
.fan {
  --w: min(281px, 62vw); /* 402 × 0.7 */
  position: relative;
  width: var(--w);
  aspect-ratio: 402 / 268;
  /* the dissolve leaves the box's bottom empty — close the gap */
  margin: 0 auto calc(var(--w) * -.14);
}
/* Downward dissolve as a black overlay instead of a mask: any mask-image
   clips every overflowing card to the border box, which cut the fan's
   open/hover swing at the box edges. Painting black over the black section
   is visually identical and clips nothing. Stops are the flat render's
   measured ramp in box space (opaque to 64/268, gone by 175/268); the
   overlay reaches past the sides to cover the swung-out cards' bottoms. */
.fan::after {
  content: "";
  position: absolute;
  inset: 0 -20%;
  z-index: 1;
  background: linear-gradient(180deg, transparent 23.9%, #000 65.4%);
  pointer-events: none;
}
/* the heading overlaps the fan's dissolved bottom (negative margin), so it
   must paint above the ::after black — the mask never painted, this does */
.library .h2,
.library .lede { position: relative; z-index: 2; }

/* The fan opens as it scrolls through the viewport, then opens a touch further
   on hover. Both feed ONE transform per card, composed from two inherited
   numbers so they never fight each other:
     --o  scroll openness 0→1 (scrubbed in main.js off viewport progress)
     --h  hover boost 0→1 (CSS :hover)
   At --o:0 the cards sit closed (the old pre-reveal pose); at 1 they rest in
   the Figma pose; --h adds the extra spread on top. */
.fan { --o: 0; --h: 0; }
.fan:hover { --h: 1; }

.fan__card {
  position: absolute;
  height: auto;
  /* short, so the scroll scrub still tracks the wheel but hover eases */
  transition: transform .3s var(--ease);
  will-change: transform;
}
.fan__card--l {
  left: -.97%; top: 1.53%; width: 55.72%; transform-origin: 75% 90%;
  transform: rotate(calc(3.5deg * (1 - var(--o)) + -1.5deg * var(--h)))
             translate(calc(3.5% * (1 - var(--o)) + -1.8% * var(--h)),
                       calc(1%   * (1 - var(--o)) + -0.7% * var(--h)));
}
.fan__card--r {
  left: 45.25%; top: 1.53%; width: 55.72%; transform-origin: 25% 90%;
  transform: rotate(calc(-3.5deg * (1 - var(--o)) + 1.5deg * var(--h)))
             translate(calc(-3.5% * (1 - var(--o)) + 1.8% * var(--h)),
                       calc(1%    * (1 - var(--o)) + -0.7% * var(--h)));
}
.fan__card--c {
  left: 26.62%; top: -.15%; width: 46.77%; transform-origin: 50% 100%;
  transform: translateY(calc(2% * (1 - var(--o)) + -1% * var(--h)));
}

.passes {
  margin-top: clamp(40px, 6vh, 64px);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
}

/* Pass cards mirror the tier cards exactly (fondo/glow/line), mapped
   Free → Course Pass (static neutral line) and Gold → Pro (celeste). */
.pass-card {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-card);
  border: none; /* the line is the ring layer, like the tiers */
  background: rgba(0, 0, 0, .2);
  padding: clamp(28px, 3vw, 42px);
  display: flex;
  flex-direction: column;
  transition: opacity .9s var(--ease) var(--d, 0s), transform .5s var(--ease);
}
.pass-card:hover { transform: scale(1.02); }
.pass-card > * { position: relative; z-index: 2; }

/* breathing top glow — Pro breathes celeste the way Gold breathes gold */
.pass-card::before {
  content: "";
  position: absolute;
  inset: -12% -10%;
  z-index: 1;
  background: radial-gradient(70% 42% at 50% 6%, rgba(76, 76, 76, .24), rgba(76, 76, 76, .05) 42%, transparent 70%);
  animation: glow-breathe 7s ease-in-out infinite alternate;
  pointer-events: none;
}
.pass-card--pro::before {
  background: radial-gradient(70% 42% at 50% 6%, rgba(59, 165, 255, .3), rgba(30, 109, 255, .09) 42%, transparent 70%);
}

/* border line = ring layer. overflow:hidden clips at the padding box, so the
   ring sits at inset 0 (not -1px) — same gotcha as .tier-card__ring. */
.pass-card .pass-card__ring {
  position: absolute;
  inset: 0;
  border-radius: calc(var(--r-card) - 1px);
  overflow: hidden;
  z-index: 0;
  pointer-events: none;
  /* Free's static edge: gray ramp at 10% */
  background: linear-gradient(108deg,
    rgba(232, 236, 243, .1), rgba(185, 192, 204, .1) 55%, rgba(138, 148, 165, .1));
}
.pass-card--pro .pass-card__ring {
  /* gold's edge in celeste: transparent → celeste → blue */
  background: linear-gradient(108deg,
    rgba(143, 216, 255, 0), #3ba5ff 45%, #1e6dff);
}
.pass-card:not(.pass-card--pro) .pass-card__ring i { display: none; }
.pass-card__ring i {
  position: absolute;
  inset: -60%;
  background: conic-gradient(from 0deg,
    transparent 0deg, rgba(143, 216, 255, .95) 55deg, transparent 110deg);
  animation: line-rotate 6s linear infinite;
}
.pass-card__ring b {
  position: absolute;
  inset: 1px;
  border-radius: calc(var(--r-card) - 2px);
  background: #000; /* page black, same trick as the tiers */
}

/* Dot field on hover (js/dot-field.js), per Figma 12040:6161 — the same
   halftone grid the hero and the closer carry, at the same 1:1 scale, but
   living inside the card and only while the pointer is on it.
   The design tops it with a black diagonal (30.638deg) so the dots survive
   only in the upper-right corner; over a black card a mask is identical to
   that overlay and keeps the stacking simple.
   The mask is painted at 240% and slides into place, so the field sweeps in
   from outside the corner instead of just fading — mask-position animates,
   while interpolating the gradient's own stops would need @property. */
.pass-card > .pass-card__shader {
  position: absolute;
  inset: 1px;              /* the 1px canto belongs to .pass-card__ring */
  z-index: 1;              /* over the breathing glow, under the copy (z2) */
  width: calc(100% - 2px);
  height: calc(100% - 2px);
  display: block;
  pointer-events: none;
  opacity: 0;
  -webkit-mask-image: linear-gradient(30.638deg, transparent 42%, #000 78%);
          mask-image: linear-gradient(30.638deg, transparent 42%, #000 78%);
  -webkit-mask-size: 240% 240%;
          mask-size: 240% 240%;
  -webkit-mask-position: 0% 100%;
          mask-position: 0% 100%;
  transition: opacity .6s var(--ease),
              -webkit-mask-position .9s var(--ease),
                      mask-position .9s var(--ease);
}
/* the class is toggled by dot-field.js, not :hover — the canvas has to keep
   drawing through the fade-out, so JS owns both ends of the state */
.pass-card.is-dots > .pass-card__shader {
  opacity: 1;
  -webkit-mask-position: 62% 38%;
          mask-position: 62% 38%;
}
/* no pointer, no field — and JS skips the WebGL context entirely there */
@media (hover: none) {
  .pass-card > .pass-card__shader { display: none; }
}

.pass-card__name {
  /* Text lg/Semibold — same ramp as .tier-card__name (Silver/Gold) */
  font-size: 1.125rem;
  font-weight: 584;
  line-height: 1.556;
  color: rgba(250, 250, 250, .6); /* Alpha/Text/Tertiary */
}
/* PRO chip (Figma 11890:3610). It is a PARALLELOGRAM, not a rect — the vector
   path runs 3.09px of lean over 18.56px of height, i.e. exactly 1:6 → 9.46°.
   The 40.21 in Figma is the slanted bounding box; the face itself is 37.11
   wide, so that is the CSS width and the skew re-creates the overhang.
   Skewing the box (rather than a backdrop layer) also makes `overflow: hidden`
   clip the shine to the slanted edges; only the label counter-skews. */
.pass-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: relative;
  overflow: hidden;
  isolation: isolate;
  margin-left: 5px;
  /* `vertical-align: middle` lands on the x-height midpoint, not the line-box
     one, which left it 1.8px low against the 18/28 name — Figma has it dead
     centre, so the nudge puts it back */
  vertical-align: middle;
  top: -2px;
  width: 37.1px;
  height: 18.6px;
  border-radius: 1.5px;
  transform: skewX(-9.46deg);
  background: linear-gradient(180deg, rgba(255, 255, 255, .5), rgba(255, 255, 255, .1));
  -webkit-backdrop-filter: blur(6.2px);
  backdrop-filter: blur(6.2px);
  box-shadow: 0 0 43px rgba(255, 180, 60, .18);
  font-size: 12.4px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0;
  color: #fff;
}
.pass-badge i { font-style: normal; transform: skewX(9.46deg); } /* label stays upright */
.pass-badge::after {
  content: "";
  position: absolute;
  inset: -1px;
  background: linear-gradient(105deg,
    transparent 38%, rgba(255, 255, 255, .9) 50%, transparent 62%);
  translate: -160% 0;
  animation: pass-badge-shine 5.2s var(--ease) infinite;
  pointer-events: none;
}
/* the sweep runs in the last ~28% of the cycle; the rest is the rest */
@keyframes pass-badge-shine {
  0%, 72% { translate: -160% 0; }
  100%    { translate: 160% 0; }
}

.pass-card__price {
  margin-top: 1rem;
  font-size: clamp(2.6rem, 4.6vw, 3.6rem);
  font-weight: 700;
  letter-spacing: -.025em;
  line-height: 1;
}
.pass-card__price span { font-size: .38em; font-weight: 600; color: var(--ink-d2); letter-spacing: 0; }
.pass-card__req {
  /* plain quiet caps — the capsule chrome was removed (user 2026-07-30) */
  margin-top: .8rem;
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--ink-d2);
}
.pass-card__body { margin-top: 1.2rem; color: var(--ink-d2); max-width: 40ch; }

/* Course belt — replaces the placeholder discs with real course chips that
   loop sideways inside the card. Geometry is Figma 12027:4095: 40px disc,
   8px to the label, name 12 / location 10 at 30%, and a 1×39 divider that
   fades out at both ends. The strip is DESIGNED to overflow — in Figma it is
   794 wide inside 489 of usable card — so the card crops it and the loop
   just keeps it moving. */
.courses {
  /* Pinned to the card's foot rather than the flow: both cards are the same
     height (the grid stretches them) but the body runs one line on Course Pass
     and two on Pro, which left the belts at different heights. The auto margin
     eats the slack so both sit on the card's bottom padding; the minimum air
     comes from the body's margin-bottom below. */
  margin-top: auto;
  height: 40px;
  overflow: hidden;
  /* the label fades out instead of being sliced at the crop line */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.pass-card__body { margin-bottom: 32px; } /* = Figma's 32 sp before the strip */

.courses__track {
  display: flex;
  width: max-content;
  height: 100%;
  align-items: center;
  will-change: transform;
}
/* main.js clones the set; the loop shifts by exactly one set's width, so
   -50% of the two-set track lands on the seam. Without JS the strip simply
   sits still — which is the Figma mock.
   Speed is 18px/s — slow enough to read a course name as it goes by. main.js
   sets --courses-dur per belt from its own measured set width, because the two
   cards carry different line-ups and a shared duration would run them at
   different speeds. The value here is only the no-JS fallback. */
.courses { --courses-dur: 45s; }
.courses--run .courses__track { animation: courses-run var(--courses-dur) linear infinite; }
@keyframes courses-run { to { transform: translateX(-50%); } }

/* 24 each side of the 1px divider = 49px chip to chip. Figma has 20 (41px);
   the user opened it up for air. Widening this lengthens the set, but the
   duration is measured, so the belt keeps its 18px/s. */
.courses__set { display: flex; align-items: center; gap: 24px; padding-right: 24px; }

.course-chip { display: flex; align-items: center; gap: 8px; flex: none; }
.course-chip__crest {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  /* most crests sit on white; a few carry the club's own colour and set
     --crest-bg inline (Gearhart gray, Glen Abbey navy, Olympic Club red) */
  background: var(--crest-bg, #fff);
  display: grid;
  place-items: center;
  flex: none;
  overflow: hidden;
}
.course-chip__crest img { display: block; }

.course-chip__txt { display: flex; flex-direction: column; line-height: 1; }
.course-chip__txt b {
  font-size: 12px;
  font-weight: 584;
  letter-spacing: -.01em;
  color: #fff;
  white-space: nowrap;
}
.course-chip__txt i {
  font-style: normal;
  font-size: 10px;
  font-weight: 584;
  color: rgba(255, 255, 255, .3);
  margin-top: 1px;
  white-space: nowrap;
}

.course-chip__sep {
  flex: none;
  width: 1px;
  height: 39px;
  background: linear-gradient(180deg, rgba(3, 72, 217, 0), var(--blue) 50%, rgba(3, 72, 217, 0));
}
/* ==========================================================================
   12 · VENUES
   ========================================================================== */

/* Rebuilt to Figma 13042:1106 (2026-08-27). The plate is no longer BEHIND the
   copy: the render sits on top in its own cropped window, the copy below it on
   flat black. Gone with it — the halftone grid, the radial scrim and the blue
   brand cast, none of which the new composition has anything to sit over. The
   old .venues__bg / __grid / __field / __grade / __scrim rules went with them. */

.venues {
  position: relative;
  background: #000;

  /* The band's framing, two numbers — "crop A" from the lab (user
     2026-08-28, after trying the tighter/taller crop B: 1.235/.82):
     --venues-crop trims the render's sides as a zoom factor — 1.061 takes
     ~3% off each side and keeps all three screens whole.
     --venues-vshow is how much of the render's height the window reveals;
     .78043 is the Figma framing (632.414/810.345). RAISING it is what makes
     the band taller — magnification alone only buys the zoom factor. The
     render below the window is simply unseen now that the plate is static.
     Height, plate geometry and the sofa fades all derive from these two. */
  --venues-crop: 1.061;
  --venues-vshow: .78043;
}

/* ---- the cropped window ----
   1440 x 632.414 in the Figma, holding a render that is 1440 x 810.345 and
   top-aligned: the window shows the top 78% and the floor runs off the bottom.
   That leftover 22% is exactly what the parallax drifts into. */
.venues__media {
  position: relative;
  width: 100%;
  /* 1440 x 632.414 in the Figma, then divided by the crop: trimming the sides
     magnifies everything, so the band has to grow by the same factor or the
     zoom would eat the room from the top and bottom instead.
     --venues-vshow is how much of the render's HEIGHT the window shows —
     .78043 is the Figma framing (632.414/810.345), and raising it is what
     makes the band taller, since magnification alone only ever buys the zoom
     factor. The render below the window is simply unseen: the plate is
     static (the parallax this pair used to feed came out 2026-08-28).
     At crop 1.061 / vshow .78043 this resolves to 1440 x 671. */
  aspect-ratio: calc(1440 / 810.345 / (var(--venues-crop) * var(--venues-vshow, .78043)));
  /* the band is ~47% of the viewport width, which on a phone is a 180px letter
     slot — too short to read as a room. Floor it. The framing below the floor
     is not designed yet (no mobile Figma for this section). */
  min-height: calc(320px * var(--venues-crop));
  overflow: hidden;
  background: #000;
}

/* The drifting plate. data-par-anchor="top" tells the shared parallax loop
   (js/main.js) to run --par from 0 to -2x travel instead of the centred
   +/- range every other plate uses: there is 178px of spare render BELOW the
   window and none above, so the drift can only ever go down. At --par: 0 —
   no JS, or prefers-reduced-motion, which opts out of the loop entirely —
   the plate is exactly the Figma frame. */
.venues__plate {
  position: absolute;
  top: 0;
  /* wider than the window by the crop factor, centred — that overhang IS the
     side trim. The height stays 810.345/632.414 of the window because the
     window grew by the same factor, so the vertical framing is untouched. */
  left: calc((100% - 100% * var(--venues-crop)) / 2);
  width: calc(100% * var(--venues-crop));
  height: calc(100% / var(--venues-vshow, .78043));   /* 128.138% at the Figma framing */
}
.venues__photo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 0;
  /* no brightness knock-back any more: nothing sits on top of the render */
}

/* The power-on canvas sits exactly on the plate, so its uv IS the render's
   uv (js/venues-poweron.js). Hidden = the plain <img> carries the band: the
   state before the dark renders load, after the effect lands, with no
   WebGL, and under prefers-reduced-motion (the script removes it). */
.venues__fx {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}
.venues__fx[hidden] { display: none; }

/* ---- the four fades, above the plate and static while it drifts ---- */
.venues__fade { position: absolute; pointer-events: none; }
/* 13042:1111 — sinks the ceiling into the black above the section.
   The Figma node sits at y 2.76 (0.437%), which is almost certainly loose
   placement rather than intent: that strip leaves the render's top rows
   unfaded, and the ceiling is dark grey, not black, so against the section
   above it reads as a hard horizontal cut right across the band. Anchored
   at 0 instead, with the height carrying the offset so the gradient still
   ENDS where the Figma's does (0.437 + 43.185). */
.venues__fade--top {
  left: 0;
  top: 0;
  width: 100%;
  height: 43.622%;
  background: linear-gradient(180deg, #000, rgba(0, 0, 0, 0));
}
/* 13042:1113 — the wide floor fade */
.venues__fade--floor {
  left: 0;
  top: 85.278%;
  width: 100%;
  height: 17.013%;
  background: linear-gradient(0deg, #000, rgba(0, 0, 0, 0));
  filter: blur(clamp(8px, .89vw, 16px));
}
/* 13042:1112 + :1114 — two narrow, barely-blurred fades that kill the hard
   bottom edge of each sofa silhouette without dimming the floor between them.
   These are the one thing the crop can break: they are placed against the
   RENDER, not the window, so their Figma percentages have to be mapped through
   the same zoom and re-centred or they slide off the sofas. Vertical
   percentages need no such treatment — the crop is horizontal only. */
.venues__fade--spot {
  top: 92.148%;
  width: calc(23.036% * var(--venues-crop));
  height: 8.179%;
  background: linear-gradient(0deg, #000, rgba(0, 0, 0, 0));
  filter: blur(1.5px);
}
.venues__fade--spot-l {
  left: calc(17.768% * var(--venues-crop) + (100% - 100% * var(--venues-crop)) / 2);
}
.venues__fade--spot-r {
  left: calc(59.195% * var(--venues-crop) + (100% - 100% * var(--venues-crop)) / 2);
}

/* ---- the black below ----
   Not an overlay on the picture: the page's own black, carrying the copy with
   it. The lip is a feathered band ABOVE the join, so the render dissolves into
   the section instead of stopping at a cut, and the black itself never moves. */
.venues__below {
  position: relative;
  z-index: 1;
  background: #000;
  padding-top: clamp(56px, 6.1vw, 96px);      /* Figma: 87.586 at 1440 */
  /* 70% of the shared dark-section token: the FAQ below opens with zero top
     padding, so this padding IS the whole seam — at the full token the two
     sections drifted apart (user 2026-08-28: -30%) */
  padding-bottom: clamp(77px, 11.2vh, 133px);
}
/* Desktop and tablet close the seam to the FAQ by another 30% (user
   2026-09-02): the CTA-to-bay-window distance read as dead air. Phones keep
   the base value. The other half of the cut is .faq__grid's padding-top
   in plus.css. */
@media (min-width: 701px) {
  .venues__below { padding-bottom: clamp(54px, 7.84vh, 93px); }
}
.venues__below::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  height: clamp(72px, 8.6vw, 150px);          /* 124 at 1440 */
  background: linear-gradient(180deg, rgba(0, 0, 0, 0), #000);
  pointer-events: none;
}

/* Figma stacks these on explicit gaps (31 eyebrow->title, 30 title->lede)
   rather than on the margins the old block layout inherited, so the column
   is a flex stack and .eyebrow's own margin-bottom is zeroed out of it. */
.venues__inner {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(20px, 2.1vw, 30px);
  text-align: center;
}
.venues__inner .eyebrow { margin-bottom: 0; }
/* The lede speaks in the same voice as the "This is Foresight+" tail
   (.thisis__lede — Text xl/Semibold, user 2026-08-28) rather than the base
   .lede ramp, which runs a step larger. Only the type is borrowed: measure
   and spacing stay the section's own. The negative margin takes 30% back
   out of the column gap between the title and this block alone — the
   eyebrow -> title gap keeps the full token. */
.venues__inner .lede {
  max-width: 56ch;
  margin-inline: auto;
  margin-top: calc(clamp(20px, 2.1vw, 30px) * -.3);
  font-size: clamp(1.05rem, 1.39vw, 1.25rem);
  font-weight: 584;
  line-height: 1.5;
  letter-spacing: normal;
  color: rgba(245, 245, 246, .6);
}
/* Lede -> button distance, carried over from Premier so the two landings
   read the same: there the first clamp is the "This is Foresight+" tail's
   own token and this page has no tail, so the value is literal here. It
   subtracts the column's flex gap, so the TOTAL equals the token — the calc
   may go negative at some widths, which is correct, not a bug. */
.venues__cta { margin-top: calc(clamp(22px, 3.5vh, 40px) - clamp(20px, 2.1vw, 30px)); }

/* DISPLAY TITLE. On Premier this shares one rule with .compat__title — this
   page has no compatibility band, so the same treatment is declared in full
   here. Keep the two in step by hand if either moves. */
.venues__title {
  max-width: min(15em, 94vw);
  margin: 0 auto;
  text-wrap: balance;
  font-size: clamp(38px, 5.2vw, 92px);
  font-weight: 640;
  line-height: 1.04;
  letter-spacing: -.03em;
  background: linear-gradient(180deg, #fff 8%, #d9dbdf 46%, #55585e 96%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* ==========================================================================
   13 · FAQ
   ========================================================================== */

.faq { padding: clamp(96px, 14vh, 170px) 0; }

.faq__grid {
  display: grid;
  grid-template-columns: 5fr 7fr;
  gap: clamp(36px, 5vw, 90px);
  align-items: start;
}
.faq__head { position: sticky; top: calc(var(--nav-h) + 48px); }
.faq__head .h2 {
  /* Display lg/Bold — 48/60, −2%: keeps the title on two lines */
  font-size: clamp(2rem, 3.33vw, 3rem);
  line-height: 1.25;
}
.faq__list { margin-top: 6px; }

.qa { border-top: 1px solid var(--line-l); }
.qa:last-child { border-bottom: 1px solid var(--line-l); }

.qa summary {
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 26px 2px;
  font-size: clamp(1.1rem, 1.39vw, 1.25rem); /* Text xl/Semibold */
  font-weight: 600;
  line-height: 1.5;
  letter-spacing: -.01em;
  cursor: pointer;
  transition: color .3s;
}
.qa summary::-webkit-details-marker { display: none; }
.qa summary:hover { color: var(--blue); }

.qa__icon {
  position: relative;
  flex: none;
  width: 22px;
  height: 22px;
}
.qa__icon::before, .qa__icon::after {
  content: "";
  position: absolute;
  inset: 50% auto auto 50%;
  width: 15px;
  height: 1.8px;
  background: var(--ink-l2);
  transform: translate(-50%, -50%);
  transition: transform .4s var(--ease);
}
.qa__icon::after { transform: translate(-50%, -50%) rotate(90deg); }
.qa[open] .qa__icon::after { transform: translate(-50%, -50%) rotate(0deg); }
.qa[open] .qa__icon::before { transform: translate(-50%, -50%) rotate(0deg); }

.qa__panel { overflow: hidden; }
.qa__panel p {
  padding: 0 40px 28px 2px;
  font-size: clamp(1rem, 1.25vw, 1.125rem); /* Text lg/Medium */
  font-weight: 500;
  line-height: 1.556;
  color: var(--ink-l2);
  max-width: 60ch;
}

/* ==========================================================================
   14 · CLOSER
   ========================================================================== */

.closer {
  /* top matched to bottom (user 2026-07-31) — it was clamp(168px, 26vh, 300px),
     roughly 36% taller than the foot, which read as a lopsided module */
  padding: clamp(124px, 19vh, 220px) 0;
  text-align: center;
  position: relative;
  overflow: clip;
}
.closer::before {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -320px;
  width: 1100px;
  height: 640px;
  transform: translateX(-50%);
  background: radial-gradient(closest-side, rgba(3, 72, 217, .2), transparent 70%);
  pointer-events: none;
  z-index: 1; /* glow above the dot field */
}

.closer__inner { position: relative; z-index: 2; }
/* midway between .h2's 1.25 and the band headline's .875 (user 2026-08-19),
   mirrored from Premier's closer. */
.closer__inner .h2--xl { line-height: 1.06; }
@media (max-width: 1024px) {
  .closer__inner .h2--xl { line-height: 1.135; }
}

/* Ambient dot-field canvas (js/dot-field.js) — behind the glow and content.
   Without the explicit z-indexes the canvas paints OVER ::before (pseudo is
   first in paint order). Mask fades the grid at the section's edges. */
.closer__shader {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  display: block;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 12%, #000 88%, transparent);
          mask-image: linear-gradient(to bottom, transparent, #000 12%, #000 88%, transparent);
}

/* 3D glass app icon (Figma 11802:93118) — replaces the eyebrow tag here.
   JS scrubs its entrance + float/tilt; static and fully visible without it. */
.closer__icon {
  display: block;
  width: clamp(133px, 11.9vw, 171px);
  height: auto;
  aspect-ratio: 1; /* <video> won't infer it from the attrs before metadata lands */
  margin: 0 auto 1.05rem;
  will-change: transform, opacity;
}
.closer .lede { margin-inline: auto; }
.closer .cta-row { justify-content: center; }

/* ==========================================================================
   FOOTER
   ========================================================================== */

.footer {
  background: var(--black);
  border-top: 1px solid rgba(255, 255, 255, .1); /* alpha-white-10 */
  padding: 34px 0 46px;
  text-align: left;
  font-size: .74rem;
  line-height: 1.7;
  color: var(--ink-d3);
}
.footer p + p { margin-top: .5rem; }
.footer__legal { padding-top: 1rem; color: rgba(255, 255, 255, .4); font-weight: 500; } /* alpha-white-40 */

/* ==========================================================================
   FLOATING COMPATIBILITY PILL
   Capsule geometry (360×42, 4px inset, 34px round button) wearing the
   localnav's glass. The scroll choreography runs in two beats and reverses:
   leaving — the capsule furls toward its button cap (clip-path), then the cap
   slides off past the right edge; returning — it slides back in first, then
   unfurls leftward. Driven from main.js: visible near the top and again near
   the end of the page, furled away in between. The × dismisses it for good.
   ========================================================================== */

.pill {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 90; /* under the nav (100), over everything else */
  display: flex;
  align-items: center;
  gap: 4px;
  width: min(360px, calc(100vw - 32px));
  height: 42px;
  padding: 4px 4px 4px 0;
  border-radius: 980px;
  border: 1px solid rgba(255, 255, 255, .08);
  background: rgba(8, 8, 10, .4);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  backdrop-filter: saturate(180%) blur(20px);
  box-shadow: 0 4px 24px rgba(0, 0, 0, .35);
  clip-path: inset(0 0 0 0 round 980px);
  translate: 0 0;
  opacity: 1;
  /* return beat: slide in, then unfurl */
  transition:
    translate .5s var(--ease),
    clip-path .55s var(--ease) .22s,
    opacity .25s var(--ease);
}
.pill--away {
  /* leaving beat: furl to the cap, then slip off the edge */
  clip-path: inset(0 0 0 calc(100% - 42px) round 980px);
  translate: calc(100% + 32px) 0;
  opacity: 0;
  pointer-events: none;
  transition:
    clip-path .5s var(--ease),
    translate .55s var(--ease) .2s,
    opacity .3s var(--ease) .45s;
}

.pill__text {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  /* dissolve only where the text exits, toward the button */
  -webkit-mask-image: linear-gradient(90deg, #000 0, #000 75%, transparent 100%);
  mask-image: linear-gradient(90deg, #000 0, #000 75%, transparent 100%);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
}

.pill__track {
  display: flex;
  width: max-content;
  animation: pill-ticker 30s linear infinite;
}
@keyframes pill-ticker { to { transform: translateX(-50%); } }
.pill:hover .pill__track { animation-play-state: paused; }

.pill__item {
  padding-left: 18px; /* clears the capsule curve */
  padding-right: 2em;
  font-size: 15px;
  line-height: 24px;
  font-weight: 492;
  white-space: nowrap;
  color: rgba(250, 250, 250, .8); /* Alpha/Text/Secondary */
}

.pill__btn {
  flex: none;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .08);
  color: #fff;
  cursor: pointer;
  transition: background .25s ease;
}
.pill__btn:hover { background: rgba(255, 255, 255, .16); }
.pill__btn:active { background: rgba(255, 255, 255, .22); }
.pill__btn svg { width: 16px; height: 16px; transition: transform .4s var(--ease); }
.pill__btn:hover svg { transform: rotate(90deg); }

/* ==========================================================================
   BREAKPOINTS
   ========================================================================== */

@media (max-width: 1068px) {
  .why__grid { grid-template-columns: 1fr; max-width: 560px; margin-inline: auto; }
  .faq__grid { grid-template-columns: 1fr; }
  .faq__head { position: static; }
  .bento-card--7, .bento-card--5 { grid-column: span 12; }
  .bento-card--4 { grid-column: span 6; }
  .tiers__grid { grid-template-columns: 1fr; max-width: 640px; margin-inline: auto; }
}

@media (max-width: 820px) {
  .localnav__links { display: none; }
  .localnav__burger { display: flex; }

  .passes { grid-template-columns: 1fr; }
  .why-cap { padding-top: 24px; font-size: 16px; line-height: 1.5; letter-spacing: -.016em; } /* = ag stacked caption, Text md/Semibold */
  .stack-card__art { width: 82%; left: auto; right: -24%; top: 4%; }
  .bento-card--4 { grid-column: span 12; }

  /* +20% module height on mobile (user 2026-07-30): 14vh → 20.3vh padding
     measured to land total height at 1.2× (513 → 616 at 375×812) */
  .realism { min-height: 0; padding: clamp(130px, 20.3vh, 240px) 0; }
  /* the expanding mask is off at this breakpoint — a 6.25vw inset is a
     sliver here, and the rounded window just eats the frame */
  [data-clip] { --clip: 0 !important; clip-path: none; }

  /* el calado en pantallas angostas: el slice del viewBox recorta los lados,
     así que la máscara baja de cuerpo para que las tres líneas entren */
  /* (the old `font-size: 88px` override lived here — it fitted the width but
     left the fixed line gaps at 1.42× the font instead of .89×, which is what
     read as "muy separado". --ms replaces it.) */

  /* Composition on mobile (user 2026-07-31). The panel is exactly one screen
     and the calado+sub group only fills ~half, so ~434px of air has to live
     somewhere — top and bottom trade against each other and can't both shrink.
     Two passes, measured at 390×844:
       1. gap 166 → 83 (halved) by dropping the mask block, bottom 125 → 90;
       2. top 344 → 258 (−25%, same move as the module margins) by lifting the
          whole group 86px — which is why the bottom lands back at ~176.
     The mask translate is in viewBox units so it rides the slice scale and
     holds the same proportion at every width; the sub stays a %. */
  .vt__masktext { transform: translateY(30.5px) scale(var(--ms, 1)); }
  .vt__sub { top: 68.5%; }

  .gallery { gap: 14px; }
  .gallery-paddles { display: none; }
}

@media (max-width: 480px) {
  /* One gutter for the whole phone layout. The containers are percentage-based
     (92vw / 94vw), so they drifted apart on a narrow screen — 15px for .container
     against 11px for .container-wide. A flat 16px lines every section up on the
     same edge; --ag-inset carries it into the stacked analysis tiles, and the
     showcase still measures its 104vw bleed from that same margin. */
  .container, .container-wide, .container-narrow,
  .showcase__inner { width: calc(100% - 32px); } /* .showcase__inner repeats the 94vw formula as its own class */
  .ag { --ag-inset: 16px; }
  .hero__title { font-size: clamp(2.9rem, 15vw, 3.9rem); }
  .btn { width: 100%; }
  .cta-row { flex-direction: column; align-items: stretch; }
  .hero .cta-row, .closer .cta-row { align-items: center; }
  .hero .btn, .closer .btn { width: auto; min-width: 230px; }
  .fsx__cta { width: auto; } /* the marquee CTA hugs its label, per Figma */
  .pill { right: 16px; bottom: 16px; }
  .tiles { grid-template-columns: repeat(2, 1fr); }
}

/* ==========================================================================
   REDUCED MOTION
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  /* the scrub job never registers here — land on the open state, not the window */
  [data-clip] { --clip: 0; clip-path: none; }
  .showcase__img { animation: none; }
  .tier-card::before { animation: none; }
  .tier-card__ring i { animation: none; }
  .pass-card::before { animation: none; }
  .pass-card > .pass-card__shader { display: none; } /* pure decoration, hover-only */
  .pass-badge::after { animation: none; translate: -160% 0; }
  .pass-card__ring i { animation: none; }
  .tier-card:hover { transform: none; }
  .pass-card:hover { transform: none; }
  .paddle, .btn { transition: none; }
  .btn .roll b, .paddle svg, .pill__btn svg { transition: none; }
  /* roll frozen: first copy always in place, second always parked below */
  .btn .roll b:first-child { transform: none !important; }
  .btn .roll b:nth-child(2) { transform: translateY(115%) !important; }
  .link-arrow::after { animation: none; }
  .fsx__viewport { overflow-x: auto; } /* JS belt is off; row scrolls by hand */
  .pill, .pill--away { transition: none; }
  .pill__track { animation: none; }
  .playhero__layer, .playhero__back, .playhero__front { transform: none !important; opacity: 1 !important; }
  .playhero__layer { transform: translateX(-50%) !important; }
  /* vt: sin transiciones ni drift; la composición calada queda estática
     (el sub visible, el frame a su tamaño de reposo — min-height cubre el hold) */
  .vt__frame { transition: none; transform: none !important; border-radius: 28px !important; }
  .vt__video { animation: none; }
  .vt__maskart { transition: none; transform: none; }
  .vt__sub { transition: none; opacity: 1; transform: translate(-50%, 0); }
  .vt__veil { transition: none; opacity: 1; } /* the is-rising job never runs here */
  .fan__card { transition: none !important; transform: none !important; }
}


/* ============================================================
   9 · COMPARE PLANS — full-bleed overlay + slide-up module
   Figma: 12228:3770 (Table-1), 12228:4220 (Table module),
          12228:4743 (scroll behaviour).

   The panel is a FIXED 833-tall window (the Figma module height,
   clamped to the viewport). Everything inside scrolls — including
   the close button and title — except the Free/Silver/Gold header,
   which sticks to the top of its own table container. Rows blur
   away behind that header and fade at both edges of the window.
   ============================================================ */

/* plate = alpha-white-5 composited over --elev; used by the sticky
   header and the fade ramps so rows dissolve into the same value. */
:root { --cmp-plate: #191919; }

.compare {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px 16px;
  visibility: hidden;
  pointer-events: none;
  /* hold visibility until the exit transition has played out */
  transition: visibility 0s linear .5s;
}
.compare.is-open {
  visibility: visible;
  pointer-events: auto;
  transition-delay: 0s;
}

.compare__scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, .72);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  opacity: 0;
  transition: opacity .42s var(--ease);
  cursor: pointer;
}
.compare.is-open .compare__scrim { opacity: 1; }

/* The module — eases up on open, back down and out on close. */
.compare__panel {
  position: relative;
  width: 633px;
  max-width: 100%;
  height: min(833px, calc(100vh - 48px));
  background: var(--elev);
  border: 1px solid rgba(255, 255, 255, .05);
  border-radius: var(--r-card);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  /* the close button keeps the panel's own 24px; the headline and the
     table plate sit a further 40px in, for the 64px gutter in Figma */
  --cmp-inset: 40px;
  padding: 24px 24px 24px;
  opacity: 0;
  transform: translateY(56px);
  transition: opacity .42s var(--ease), transform .52s var(--ease);
}
.compare.is-open .compare__panel { opacity: 1; transform: none; }


.compare__close {
  flex: none;
  align-self: flex-start;
  width: 44px;
  height: 44px;
  padding: 0;
  position: relative;
  border: 1px solid var(--line-d);
  border-radius: 50%;
  background: rgba(255, 255, 255, .06);
  cursor: pointer;
  transition: background .2s var(--ease), border-color .2s var(--ease);
}
.compare__close:hover { background: rgba(255, 255, 255, .12); border-color: rgba(255, 255, 255, .22); }
.compare__close:focus-visible { outline: 2px solid var(--blue-light); outline-offset: 3px; }
.compare__close::before,
.compare__close::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 14px;
  height: 1.5px;
  margin: -.75px 0 0 -7px;
  background: var(--ink-d1);
  border-radius: 2px;
}
.compare__close::before { transform: rotate(45deg); }
.compare__close::after  { transform: rotate(-45deg); }

.compare__head {
  flex: none;
  text-align: center;
  padding: 10px 0 20px;
  margin: 0 var(--cmp-inset);
}
.compare__head .eyebrow { margin-bottom: 8px; }
.compare__title {
  margin: 0;
  font-family: var(--font);
  font-weight: 600;                /* Demibold */
  font-size: 36px;                 /* display-md */
  line-height: 44px;
  letter-spacing: -.72px;
  color: var(--ink-d1);
}

/* ---- table plate: alpha-white-5, radius-2xl, 24 padding ---- */
.compare__table {
  position: relative;
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: rgba(255, 255, 255, .05);
  border-radius: 16px;
  padding: 0 24px;
  margin: 0 var(--cmp-inset);
}

.compare__cols,
.compare__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) repeat(3, 80px);
  gap: 4px;
  align-items: center;
}

/* Free / Silver / Gold — fixed with the rest of the header block.
   Bottom-aligned so FREE sits on the same line as the Silver/Gold
   prices rather than floating between name and price. */
.compare__cols {
  flex: none;
  align-items: end;
  padding: 24px 0 8px;
}

/* The only scrolling region. Rows dissolve into both edges of the
   window via a mask, so nothing hard-clips at the plate bounds. */
.compare__rows {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
  /* top pad + the group's own 20px lands the first heading at 28px,
     just clear of the 22px ramp */
  padding: 8px 0 20px;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 22px, #000 calc(100% - 38px), transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 22px, #000 calc(100% - 38px), transparent 100%);
}
.compare__rows::-webkit-scrollbar { width: 0; height: 0; }

.compare__plan { text-align: center; }
.compare__plan-name {
  display: block;
  font-size: 16px;
  font-weight: 500;
  color: var(--ink-d1);
  letter-spacing: -.01em;
}
.compare__plan-price {
  display: block;
  margin-top: 1px;
  font-family: var(--mono);
  font-size: 11px;
  line-height: 16px;
  color: var(--ink-d2);
}
.compare__plan--free .compare__plan-name {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-d2);
}

.compare__group {
  padding: 20px 0 8px;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.01em;
  color: var(--ink-d1);
}

.compare__row {
  padding: 9px 0;
  border-top: 1px solid rgba(255, 255, 255, .07);
}
.compare__label {
  font-size: 14px;          /* text-sm */
  line-height: 20px;
  font-weight: 500;         /* Medium */
  color: var(--ink-d1);
}
.compare__cell {
  text-align: center;
  font-size: 14px;
  color: var(--ink-d1);
}

/* included — the circle-check mask the tier cards use */
.compare__yes {
  display: inline-block;
  width: 16px;
  height: 16px;
  vertical-align: -2px;
  background: var(--ink-d1);
  -webkit-mask: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M10 1a9 9 0 100 18 9 9 0 000-18zm4.2 6.4l-4.9 5.4a.9.9 0 01-1.32.03L5.7 10.5a.9.9 0 111.27-1.27l1.6 1.6 4.28-4.7a.9.9 0 111.34 1.2z"/></svg>') center / contain no-repeat;
  mask: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M10 1a9 9 0 100 18 9 9 0 000-18zm4.2 6.4l-4.9 5.4a.9.9 0 01-1.32.03L5.7 10.5a.9.9 0 111.27-1.27l1.6 1.6 4.28-4.7a.9.9 0 111.34 1.2z"/></svg>') center / contain no-repeat;
}
.compare__no { font-weight: 600; color: rgba(255, 255, 255, .28); }

/* ---- Scroll indicator -------------------------------------------
   Sits in the panel's right gutter, outside the table plate, and
   spans exactly the plate's height (Figma 12237:5221). Hidden until
   you hover the module, and flashes briefly while scrolling. */

.compare__bar {
  position: absolute;
  top: 4px;                 /* iOS insets the indicator from the scroll bounds */
  bottom: 4px;
  right: calc(-1 * var(--cmp-inset) - 9px);   /* 15px in from the panel edge */
  width: 6px;
  border-radius: 999px;
  opacity: 0;
  pointer-events: none;
  /* out: lingers, then eases away. in: effectively instant. */
  transition: opacity .4s var(--ease) .45s;
}
.compare__panel:hover .compare__bar,
.compare__bar.is-active {
  opacity: 1;
  pointer-events: auto;
  transition: opacity .05s linear;
}
.compare__thumb {
  display: block;
  width: 100%;
  border-radius: 999px;
  background: rgba(255, 255, 255, .4);
  transition: background .15s var(--ease);
  cursor: grab;
}
.compare__bar:hover .compare__thumb { background: rgba(255, 255, 255, .52); }
.compare__bar.is-dragging .compare__thumb { background: rgba(255, 255, 255, .62); cursor: grabbing; }



@media (max-width: 560px) {
  .compare { padding: 16px 12px; }
  .compare__panel { height: calc(100vh - 32px); border-radius: var(--r-panel); --cmp-inset: 0px; }
  .compare__panel { padding: 20px 16px; }
  .compare__table { padding: 0 16px; }
  .compare__cols { padding: 16px 0 12px; }
  .compare__cols,
  .compare__row { grid-template-columns: minmax(0, 1fr) repeat(3, 56px); gap: 4px; }
  .compare__title { font-size: 27px; line-height: 34px; }
  .compare__label { font-size: 12px; }
}

@media (prefers-reduced-motion: reduce) {
  .compare__scrim,
  .compare__panel { transition: opacity .2s linear; }
  .compare__panel { transform: none; }
}

/* ---- Course list variant (Figma 12237:5221) ---------------------
   Same shell as Compare plans, but two 80px plan columns, brighter
   row labels, and rows separated by a 12px gap instead of rules. */

.compare--courses .compare__cols,
.compare--courses .compare__row {
  grid-template-columns: minmax(0, 1fr) 80px 80px;
}
.compare--courses .compare__cols {
  align-items: start;
  padding: 24px 0 8px;
}
.compare--courses .compare__plan-name {
  font-size: 16px;
  line-height: 18px;
}
.compare--courses .compare__rows {
  display: flex;
  flex-direction: column;
  gap: 19px;              /* 21px row + 19px = 40px pitch, same as Compare plans */
  padding: 20px 0 20px;
}
.compare--courses .compare__row {
  padding: 0;
  border-top: 0;
}

@media (max-width: 560px) {
  .compare--courses .compare__cols,
  .compare--courses .compare__row { grid-template-columns: minmax(0, 1fr) 68px 68px; }
  .compare--courses .compare__plan-name { font-size: 14px; }
}

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

/* sub header appears on scroll only, on tablet/phone (user 2026-08-18) */
@media (max-width: 1024px) {
  .localnav {
    transform: translateY(-14px);
    opacity: 0;
    pointer-events: none;
    transition: opacity .35s var(--ease), transform .35s var(--ease);
  }
  .localnav.scrolled {
    transform: none;
    opacity: 1;
    pointer-events: auto;
  }
}

/* return-scroll global header on tablet/phone (user 2026-08-18) */
@media (max-width: 1024px) {
  .gnav--fixed {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 70;
    transform: translateY(-100%);
    transition: transform .35s var(--ease);
  }
  .gnav--fixed.gnav--reveal { transform: translateY(0); }
}

/* The button's display style must not override its initial/recovery hidden state. */
[data-course-retry][hidden] { display: none; }
