/* ==========================================================================
   APPLOFF ENTERTAINMENT — Design System
   "Dark Stage, Loud Color"
   ========================================================================== */

/* ---------- Tokens ---------- */
:root {
  /* Stage */
  --stage-000: #050507;
  --stage-050: #0A0A0E;
  --stage-100: #101017;
  --stage-200: #17171F;
  --stage-300: #22222D;
  --stage-400: #33333F;

  /* Light */
  --white: #FFFFFF;
  --ink-100: #F4F4F7;
  --ink-300: #B9B9C6;
  --ink-500: #83839A;
  --ink-700: #55556A;

  /* ======================================================================
     BRAND COLOURS — change these three lines and the whole site follows.

       --green   Apploff primary   (was #FF2D6F magenta)
       --violet  JAHM Studios      (was #00E0FF cyan)

     TO REVERT to the original pink/gold + cyan scheme:
       --green:      #FF2D6F;
       --green-hot:  #FF4F87;
       --grad-hot:   linear-gradient(100deg, #FF2D6F 0%, #FFC83D 100%);
       --violet:     #00E0FF;
     ...and nothing else needs touching.
     ====================================================================== */

  /* =====================================================================
     THE COLOUR LANES — decided by Jeff, August 2026. Do not let these drift.

       BLUE  #2E6BFF  the work    — primary buttons, big CTAs, things you click
       GREEN #00E36A  the signal  — section markers, links, rules, ghost
                                    accents, live/on-air status, the live dot
       GOLD  #FFC83D  the prestige — subtle only, never headline: the
                                    "Apploff Original" outline badges, the
                                    100th-episode milestone badge, the payoff
                                    marker, ghost-button hovers, Party Polls
                                    scores. Gold on the hero word was tried
                                    and rejected (see .hero-word history).
                                    The hero word and the climbing stats are
                                    GREEN — scarce now that buttons are blue.
       VIOLET #8B5CFF JAHM only. Party Polls keeps its own scoped palette.

     Rationale: green-as-wallpaper is the generic AI-site look. Green demoted
     to signals and gold reserved for winning is what makes this read designed.
     ===================================================================== */
  --blue:       #2E6BFF;   /* the work — buttons, CTAs */
  --blue-hot:   #5B8CFF;
  --on-blue:    #FFFFFF;
  --on-gold:    #241A00;

  --green:      #00E36A;   /* the signal — markers, links, rules, live */
  --green-hot:  #2BFF88;   /* hover / brighter */
  --violet:     #8B5CFF;   /* JAHM Studios */
  --violet-hot: #A98BFF;

  --gold: #FFC83D;         /* milestone badges only */
  --lime: #B6FF3D;         /* success states only */

  /* Flat, not gradient — one committed colour reads as a decision.
     (Kept as a gradient token so every existing rule still works.) */
  --grad-hot:  linear-gradient(100deg, #00E36A 0%, #00E36A 100%);
  --grad-cool: linear-gradient(100deg, #8B5CFF 0%, #C77DFF 100%);
  --grad-full: linear-gradient(100deg, #00E36A 0%, #8B5CFF 100%);

  /* DEPRECATED — do not use these in new rules.

     They date from the magenta/cyan palette and every rule in this file has now
     been migrated to --green / --green-hot / --violet directly. They are kept
     defined only so that a stray hand-edit referencing them still resolves
     rather than silently rendering nothing. Reading "magenta" in a rule and
     seeing green on screen cost more confusion than the aliases ever saved. */
  --magenta: var(--green);
  --magenta-hot: var(--green-hot);
  --cyan: var(--violet);

  /* Readable text colour to sit ON the accent fills */
  --on-green: #04180C;
  --on-violet: #FFFFFF;

  /* Type */
  --font-display: 'Archivo', 'Helvetica Neue', Impact, sans-serif;
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  /* Space */
  --gutter: clamp(1.25rem, 4vw, 4.5rem);
  --section-y: clamp(3.25rem, 7vw, 6.5rem);   /* was 4.5–10rem: too airy, left blank viewports */
  --maxw: 1440px;

  /* Motion */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-sharp: cubic-bezier(0.65, 0, 0.35, 1);

  --radius: 6px;
  --radius-lg: 14px;
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--stage-000);
  color: var(--ink-100);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

body.nav-open { overflow: hidden; }

img, video, iframe, svg { display: block; max-width: 100%; }

/* Anchor landings (Jeff's phone catch): the fixed header covered the top of
   every #anchor target, so "Shows" landed on the headline with the eyebrow
   hidden. Every target now leaves room for the header. */
[id] { scroll-margin-top: 5.25rem; }
img { height: auto; }

a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; border: none; background: none; color: inherit; }
ul, ol { list-style: none; margin: 0; padding: 0; }
h1, h2, h3, h4, h5, p, figure { margin: 0; }

/* White on this green measures about 1.7:1 — selected text was effectively
   unreadable. --on-green is the near-black that the palette defines for
   exactly this job. */
::selection { background: var(--green); color: var(--on-green); }

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

/* Film grain overlay — keeps the black from feeling flat/digital */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 9999;
  opacity: 0.035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---------- Typography ---------- */
.display {
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 112%;
  line-height: 0.88;
  letter-spacing: -0.028em;
  text-transform: uppercase;
  margin: 0;
}

.d-hero  { font-size: clamp(3rem, 10.5vw, 10.5rem); }
.d-xl    { font-size: clamp(2.5rem, 7vw, 6rem); }
.d-lg    { font-size: clamp(2rem, 4.6vw, 3.9rem); }
.d-md    { font-size: clamp(1.5rem, 3vw, 2.5rem); }
.d-sm    { font-size: clamp(1.15rem, 2vw, 1.6rem); line-height: 1; }

.eyebrow {
  font-family: var(--font-body);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-500);
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
.eyebrow::before {
  content: '';
  width: 28px;
  height: 2px;
  background: var(--green);
  flex: none;
}
.eyebrow.no-rule::before { display: none; }

.lede {
  font-size: clamp(1.05rem, 1.55vw, 1.4rem);
  line-height: 1.55;
  color: var(--ink-300);
  max-width: 62ch;
}

.body-copy { color: var(--ink-300); font-size: 1rem; line-height: 1.7; }
.body-copy p + p { margin-top: 1em; }
.body-copy em, .body-copy i { color: var(--ink-100); font-style: italic; }
.body-copy strong { color: var(--white); font-weight: 600; }

/* SIGNAL LANE: headline emphasis stays green — it marks, it doesn't award. */
.gradient-text {
  background: var(--grad-hot);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
/* Violet sibling of .gradient-text — the JAHM Studios lane. Same gradient the
   JAHM wordmark uses, so a coloured phrase on that page belongs to that page
   rather than borrowing the Apploff green. Background-clip only, never a
   filter — a filter on clipped text draws the square halo. */
.violet-text {
  background: var(--grad-cool);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Gold sibling of .gradient-text — for prestige payoffs (the Vault).
   Same rule as always: background-clip only, never a filter. */
.gold-text {
  background: linear-gradient(180deg, #FFE18A 0%, #FFC83D 55%, #F5AE3D 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* ---------- Layout ---------- */
.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.section { padding-block: var(--section-y); position: relative; }
.section-head { margin-bottom: clamp(2rem, 4vw, 3.5rem); }
.section-head .eyebrow { margin-bottom: 1.1rem; }
.divider { height: 1px; background: var(--stage-300); border: 0; margin: 0; }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 1rem 1.9rem;
  border-radius: 100px;
  font-weight: 700;
  font-size: 0.82rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  transition: transform 0.35s var(--ease), background 0.35s var(--ease),
              color 0.35s var(--ease), box-shadow 0.35s var(--ease);
  will-change: transform;
}
.btn:hover { transform: translateY(-3px); }

.btn-primary {
  background: var(--blue);
  color: var(--on-blue);
  box-shadow: 0 6px 30px -8px rgba(46, 107, 255, 0.55);
}
.btn-primary:hover { box-shadow: 0 14px 44px -10px rgba(46, 107, 255, 0.9); }

.btn-ghost {
  border: 1.5px solid var(--stage-400);
  color: var(--white);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  background: rgba(255, 255, 255, 0.04);
}
/* GOLD LANE: secondary buttons warm to prize gold on touch — subtle prestige
   on interaction, per Jeff. Rest state stays neutral so gold remains scarce. */
.btn-ghost:hover {
  border-color: var(--gold);
  color: var(--gold);
  background: rgba(255, 200, 61, 0.07);
}

.btn-arrow { transition: transform 0.35s var(--ease); }
.btn:hover .btn-arrow { transform: translateX(4px); }

/* Text link with animated underline */
.tlink {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 700;
  font-size: 0.78rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--white);
  position: relative;
  padding-bottom: 4px;
}
.tlink::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1.5px;
  background: var(--green);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.4s var(--ease);
}
.tlink:hover::after { transform: scaleX(1); transform-origin: left; }

/* ---------- Badges ---------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.32rem 0.75rem;
  border-radius: 100px;
  font-size: 0.63rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
}
.badge-live {
  background: var(--green);
  color: var(--on-green);          /* dark text — white on bright green is unreadable */
}
.badge-live .dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--on-green);     /* dot must be dark to show on the green pill */
  animation: pulse 1.7s infinite;
}
.badge-gold  { background: var(--gold); color: #1A1204; }
.badge-cyan  { background: var(--violet); color: var(--on-violet); }
.badge-quiet { background: rgba(255,255,255,0.09); color: var(--ink-100); border: 1px solid var(--stage-400); }

@keyframes pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.35; transform: scale(0.75); }
}

/* ==========================================================================
   HEADER
   ========================================================================== */
.header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 1000;
  transition: background 0.4s var(--ease), backdrop-filter 0.4s var(--ease),
              border-color 0.4s var(--ease), padding 0.4s var(--ease);
  padding-block: 1.4rem;
  border-bottom: 1px solid transparent;
}

/* HEADER SCRIM (Jeff, Aug 26: "half on black and half on the screen … it
   almost makes it feel like it's broken").

   Diagnosis: the header had no background of its own until you scrolled, so
   at the top of the page the nav sat directly on the reel. The hero scrim is
   heavy at the bottom and left — built to protect the headline down there —
   but only rgba(5,5,7,0.35) at the top. Thirty-five percent is enough over a
   dark shot and nowhere near enough when the reel cuts to a lit stage, so the
   nav read clearly for a few seconds and then half-vanished. Not a bug, and
   not stylistic either: just unprotected type.

   The fix is a soft top-down gradient that lives behind the header
   permanently. It has no edge and no line, so it never reads as a bar — the
   nav still floats over the film, it just always has darkness under it. This
   is the standard solve for type over video and it costs nothing.

   Deliberately taller than the header itself (170px against roughly 100px) so
   the gradient's falloff finishes below the type rather than cutting across
   it. pointer-events:none so it can never eat a click on the nav. */
.header::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 220px;   /* sized for the 104px logo + padding; was 170 */
  pointer-events: none;
  z-index: -1;
  background: linear-gradient(
    to bottom,
    rgba(5, 5, 7, 0.78) 0%,
    rgba(5, 5, 7, 0.58) 38%,
    rgba(5, 5, 7, 0.26) 72%,
    rgba(5, 5, 7, 0) 100%
  );
  transition: opacity 0.4s var(--ease);
}
/* Once the blurred bar takes over there are two scrims doing one job, so the
   gradient steps back out. */
.header.scrolled::before { opacity: 0; }
.header.scrolled {
  background: rgba(5, 5, 7, 0.82);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  backdrop-filter: blur(20px) saturate(140%);
  border-bottom-color: var(--stage-300);
  padding-block: 0.85rem;
}
.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
}
.brand { display: flex; align-items: center; flex: none; }
/* Logo scale — this is the company's name, it should read at a glance.
   Adjust these two numbers to taste. */
/* The logo's three sizes (Jeff, Sep 4, second pass: "you can't even read
   'entertainment'"). The mark is the stacked tree + APPLOFF + ENTERTAINMENT
   lockup, and the bottom line goes illegible below ~70px. So: full presence
   while the hero plays (104), the old "big" once the headline resolves to
   its corner (76, .brand-mini via app.js §12), and compact only when the
   visitor scrolls and the blurred bar takes over (56). */
.brand img { height: 104px; width: auto; transition: height 0.4s var(--ease); }
.header.brand-mini .brand img { height: 76px; }
.header.scrolled .brand img { height: 56px; }
/* Pulled toward the edge so the mark anchors the corner instead of floating
   in the gutter (Jeff, Sep 4). */
.brand { margin-left: calc(var(--gutter) * -0.45); }
@media (max-width: 700px) {
  .brand img { height: 64px; }
  .header.brand-mini .brand img { height: 52px; }
  .header.scrolled .brand img { height: 44px; }
  .brand { margin-left: 0; }
}

.nav { display: flex; align-items: center; gap: 2.2rem; }
.nav a {
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  /* Brighter than body text on purpose. Over the reel the nav needs contrast
     margin the way a lower third does; once the blurred bar is in it can
     settle back. */
  color: var(--ink-100);
  position: relative;
  padding-block: 4px;
  transition: color 0.3s var(--ease);
}

.header.scrolled .nav a:not(:hover):not([aria-current="page"]) { color: var(--ink-300); }
.nav a::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 2px;
  background: var(--green);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.4s var(--ease);
}
.nav a:hover, .nav a[aria-current="page"] { color: var(--white); }
.nav a:hover::after, .nav a[aria-current="page"]::after { transform: scaleX(1); transform-origin: left; }

.header-cta { display: flex; align-items: center; gap: 1rem; flex: none; }
.header-cta .btn { padding: 0.72rem 1.35rem; font-size: 0.7rem; }

.burger {
  display: none;
  width: 44px; height: 44px;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 6px;
  flex: none;
}
.burger span {
  display: block;
  width: 24px; height: 2px;
  background: var(--white);
  transition: transform 0.4s var(--ease), opacity 0.3s var(--ease);
}
.burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(8px) rotate(45deg); }
.burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-8px) rotate(-45deg); }

.mobile-nav {
  position: fixed;
  inset: 0;
  z-index: 999;
  background: var(--stage-050);
  padding: 7rem var(--gutter) 3rem;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  transform: translateY(-100%);
  transition: transform 0.55s var(--ease);
  overflow-y: auto;
}
.mobile-nav.open { transform: translateY(0); }
.mobile-nav ul { display: flex; flex-direction: column; gap: 0.35rem; }
.mobile-nav ul a {
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 112%;
  text-transform: uppercase;
  font-size: clamp(2.1rem, 11vw, 3.4rem);
  line-height: 1.08;
  letter-spacing: -0.02em;
  color: var(--white);
  display: block;
}
.mobile-nav ul a:hover { color: var(--green); }
.mobile-nav-foot { display: flex; flex-direction: column; gap: 1.25rem; padding-top: 2.5rem; }

/* ==========================================================================
   HERO
   ========================================================================== */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  isolation: isolate;
}
.hero-media {
  position: absolute;
  inset: 0;
  z-index: -2;
  overflow: hidden;
  background: var(--stage-100);
}
/* Background video sized to cover, no letterboxing (self-hosted since Aug 21;
   the same box worked for the old Vimeo iframe) */
.hero-media iframe,
.hero-media video {
  object-fit: cover;
  position: absolute;
  top: 50%; left: 50%;
  width: 100vw;
  height: 56.25vw;              /* 16:9 */
  min-height: 100svh;
  min-width: 177.77svh;
  transform: translate(-50%, -50%);
  border: 0;
  pointer-events: none;
}
/* Poster frame sits above the iframe until the video is genuinely playing,
   then cross-fades away. Prevents the blank-hero moment on first load. */
.hero-poster {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 1;
  transition: opacity 1.1s var(--ease);
  pointer-events: none;
}
.hero-poster.gone { opacity: 0; }
.hero-scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(to top, var(--stage-000) 2%, rgba(5,5,7,0.55) 42%, rgba(5,5,7,0.35) 100%),
    linear-gradient(to right, rgba(5,5,7,0.85) 0%, rgba(5,5,7,0.15) 62%);
}
.hero-inner {
  width: 100%;
  padding-bottom: clamp(3.5rem, 7vw, 6rem);
  padding-top: 9rem;
}
.hero h1 { margin-bottom: 1.6rem; max-width: 16ch; }

/* The oversized word has a descender (the g), and .line clips overflow for the
   rise-in animation — so give that line room or the tail gets sliced off. */
.hero-headline .line:last-child { padding-bottom: 0.12em; }

/* "WINNING" gets to be the biggest word on the page and carries the gradient. */
.hero-headline .hero-word {
  /* GREEN, final — after a full tour through gold. The record, so nobody
     repeats the trip: flat gold read muted at this size; gold with a glow
     rendered as a square halo (filter + background-clip:text breaks in real
     browsers); brighter gold Jeff simply hated. Green won because the blue
     buttons made it scarce again — one glowing word, back in its own lane.
     NO filter or text-shadow here, ever. */
  background: var(--grad-hot);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-size: 1.22em;
  display: inline-block;
  line-height: 0.86;
}
/* The word cycle (Jeff, Aug 27): hope -> opportunity -> winning, ONCE, then
   it stays on winning forever. His reasoning, verbatim enough to keep: "it's
   not just about the winning; it's also about the hope, the opportunities."
   Each sentence is true on its own, so this is the thesis in three beats, not
   a word trick. Slot-machine looping is exactly what it must never become.
   JS (app.js §12) sets the text and re-triggers .swap-in per beat; the markup
   keeps "winning." so no-JS and reduced-motion visitors get the brand line. */
.hero-word.swap-in {
  animation: heroWordIn 0.62s cubic-bezier(0.2, 0.9, 0.3, 1) both;
}
@keyframes heroWordIn {
  0%   { opacity: 0; transform: translateY(0.5em) scale(1.14); }
  60%  { opacity: 1; transform: translateY(-0.02em) scale(0.985); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}
.hero-word.swap-out {
  animation: heroWordOut 0.24s var(--ease) both;
}
@keyframes heroWordOut {
  to { opacity: 0; transform: translateY(-0.35em) scale(0.96); }
}
/* NO filter/blur in either keyframe, ever — this word is gradient-clipped
   text and a filter on it draws the square halo. Opacity + transform only. */

/* THE TITLE CARD (desktop; see app.js §12). While staged, the supporting
   furniture holds its breath: pausing the entrance animations freezes them at
   their from-state (opacity 0) INCLUDING the delay countdown, so when the
   staging class lifts they play their normal entrances as if the page had
   just revealed. */
.hero.hw-staging .hero-sub,
.hero.hw-staging .hero-actions,
.hero.hw-staging .scroll-hint {
  /* animation:none + opacity:0, NOT play-state:paused. Pausing raced the
     entrance animations on intro-skipped reloads — sometimes they'd started
     before the JS could pause them, freezing half-visible bullets under the
     title card (Jeff, Sep 4: "sometimes those words are there, sometimes
     they're not"). Killing the animation outright is deterministic, and
     when the class lifts the animation property returns, which restarts the
     entrance from frame zero. */
  animation: none;
  opacity: 0;
}
/* the word starts as nothing — it has to come out of the void.
   CAREFUL: .hero-word IS the third line's direct span, so this rule also has
   to neutralise that span's rise-in entrance — but the zoom/burst rules below
   carry more specificity so THEY always win when their class lands. The first
   version of this block used a `.line > span` selector that out-specified the
   zoom animations and silently killed them: hope and opportunity animated
   into nothing (Jeff: "hope didn't come in, opportunity didn't come in"). */
.hero.hw-staging .hero-word { opacity: 0; animation: none; transform: none; }
/* burst letters must not wrap as they spread */
.hero-word { white-space: nowrap; }
/* the third line clips its overflow for the rise-in curtain — but the zoom
   scales far past the line box and was getting sliced to a strip. While the
   card is staged, that line lets the word fly. */
.hero.hw-staging h1 .line:nth-child(3) { overflow: visible; }

/* the rush out of the depth: tiny and gone -> at your face -> settle */
/* Selector note: `.hero h1 .line > .hero-word.hw-zoom` outranks the base
   `.hero h1 .line > span` rise-in. Without that, the moment staging lifted
   the base rule retook the element and REPLAYED the rise — Jeff's "winning
   is coming up twice." */
.hero.hw-staging .hero-word.hw-zoom,
.hero h1 .line > .hero-word.hw-zoom {
  animation: hwZoom 0.55s cubic-bezier(0.16, 0.9, 0.28, 1) both;
}
@keyframes hwZoom {
  0%   { opacity: 0; transform: scale(0.08); }
  62%  { opacity: 1; transform: scale(1.1); }
  82%  { transform: scale(0.97); }
  100% { opacity: 1; transform: scale(1); }
}
/* the burst: past your ear and apart. Letter-spread does the "explode" —
   scale alone reads as zoom, spacing makes it come apart. */
.hero.hw-staging .hero-word.hw-burst,
.hero h1 .line > .hero-word.hw-burst {
  animation: hwBurst 0.34s cubic-bezier(0.5, 0, 0.9, 0.4) both;
}
@keyframes hwBurst {
  0%   { opacity: 1; transform: scale(1); letter-spacing: 0; }
  100% { opacity: 0; transform: scale(2.2); letter-spacing: 0.42em; }
}
/* "opportunity." is half again as long as "winning." — at the same size it
   would blow through the measure, so the long beat steps down to match the
   others' visual width. */
.hero-word.is-long { font-size: 0.84em; }

.hero h1 .line { display: block; overflow: hidden; }
.hero h1 .line > span {
  display: block;
  transform: translateY(105%);
  animation: riseIn 1.05s var(--ease) forwards;
}
.hero h1 .line:nth-child(1) > span { animation-delay: 0.15s; }
.hero h1 .line:nth-child(2) > span { animation-delay: 0.27s; }
.hero h1 .line:nth-child(3) > span { animation-delay: 0.39s; }

@keyframes riseIn { to { transform: translateY(0); } }

/* The firsts list opens with a lead-in and closes with the payoff; the show
   names carry the weight (team note, Sep 17). */
.hero-firsts .lead {
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink-500);
  margin-bottom: 0.35rem;
}
.hero-firsts strong { color: var(--white); font-weight: 700; }

.hero-sub {
  max-width: 52ch;
  margin-bottom: 2.4rem;
  opacity: 0;
  animation: fadeUp 0.9s var(--ease) 0.62s forwards;
}
.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  opacity: 0;
  animation: fadeUp 0.9s var(--ease) 0.76s forwards;
}
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: translateY(0); }
}

.hero-flag {
  display: inline-flex;
  align-items: center;
  gap: 0.85rem;
  margin-bottom: 1.9rem;
  opacity: 0;
  animation: fadeUp 0.8s var(--ease) 0.05s forwards;
}
.hero-flag .netflix { height: 15px; width: auto; }

/* ==========================================================================
   SIZZLE LIGHTBOX — full-screen player, nothing over the video
   ========================================================================== */
.sizzle {
  position: fixed;
  inset: 0;
  z-index: 3000;
  display: grid;
  place-items: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.4s var(--ease);
}
.sizzle.open { opacity: 1; pointer-events: auto; }

.sizzle-scrim {
  position: absolute;
  inset: 0;
  background: #000;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}

.sizzle-stage {
  position: relative;
  z-index: 2;
  width: min(1500px, 94vw);
  transform: scale(0.97);
  transition: transform 0.45s var(--ease);
}
.sizzle.open .sizzle-stage { transform: scale(1); }

/* 16:9 box that always fits the viewport, so nothing is ever cropped */
.sizzle-frame {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  max-height: 86svh;
  margin-inline: auto;
  background: #000;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 40px 120px -30px rgba(0, 0, 0, 0.9);
}
/* Keep the 16:9 ratio when height is the limiting dimension */
@supports (aspect-ratio: 16/9) {
  .sizzle-frame { width: min(100%, calc(86svh * 16 / 9)); }
}
.sizzle-frame iframe,
.sizzle-frame video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}
/* the native player wears the same stage as the iframe */
.sizzle-frame video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  background: #000;
}
.sizzle-frame video[hidden] { display: none; }

.sizzle-close {
  position: absolute;
  top: clamp(1rem, 3vw, 2rem);
  right: clamp(1rem, 3vw, 2rem);
  z-index: 5;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  color: var(--white);
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.28);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  transition: background 0.3s var(--ease), transform 0.3s var(--ease);
}
.sizzle-close:hover {
  background: var(--green);
  border-color: var(--green);
  /* The X is an SVG stroked with currentColor, so this is load-bearing:
     without it the mark stays white and vanishes into the green on hover. */
  color: var(--on-green);
  transform: rotate(90deg);
}

/* Play affordance inside the hero button */
.play-dot {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--green);
  /* The triangle is fill="currentColor" — white on green fails contrast. */
  color: var(--on-green);
  flex: none;
  transition: transform 0.35s var(--ease);
}
.btn:hover .play-dot { transform: scale(1.14); }


/* ==========================================================================
   OPENING TITLE

   ---------------------------------------------------------------------------
   TO MAKE THE CARD SIT LONGER OR SHORTER, CHANGE ONE NUMBER: --intro-hold.
   Everything downstream — the exit, the veil, the hero's entrance — is
   calculated from it, so nothing else needs touching and nothing can fall out
   of sync. --intro-hold is how long the FINISHED line sits perfectly still
   before anything starts moving away.
   ---------------------------------------------------------------------------

   The sequence (THE BUILD, locked Aug 21 — all-gold words, broadcast tempo):

     0.00s   the mark is already on screen, pulling back as the smoke drifts
     0.48s   impact flash + screen hit as the APPLOFF type lands
     1.77s   the clip has fully played out; the fade begins on its held frame
     2.00s   first gold word punches in; one beat every 0.32s
             (and+produce share beat 2, game+shows share beat 4)
     6.34s   the last word settles — the full message stands; hold starts
     7.44s   the whole message pushes through: scale up, blur, fade
     7.71s   the black veil lifts, revealing the hero already moving
     7.99s   the hero headline rises

   Three principles, in case anyone is tempted to simplify this:

   1. NOTHING FADES IN BY OPACITY ALONE. A bare opacity fade is the cheapest
      transition available and it reads as cheap. Every element here either
      rises out from behind a mask or moves through space.

   2. THE EXIT IS TWO-STAGE. The content dissolves, and only then does the
      black clear. Fading them together reads as a slide change. Staggering
      them reads as a camera moving into the site.

   3. THE STAGES OVERLAP. The hero headline starts at 2.90s while the veil is
      still clearing (2.62s + 0.95s = 3.57s). That overlap is what makes it
      feel continuous instead of sequential. Do not tidy it into neat
      non-overlapping blocks — the seam is the point.
   ========================================================================== */

/* All intro timing lives here, on .hero, because both the title card and the
   hero content underneath it are descendants and so both inherit these.

   --iw-last must equal the highest `--i` in index.html's word spans. There are
   11 words numbered 0-10, so it is 10. Add or remove a word and this changes
   with it, otherwise the hold silently shifts. */
.hero {
  --iw-base: 2.40s;      /* first word punches in — after the clip has fully
                            PLAYED OUT (1.77s) and faded (0.18s). THE RULE: no
                            word may ever share the frame with the logo. */
  --iw-step: 0.32s;      /* broadcast tempo — one beat per word (Jeff's pick) */
  --iw-dur:  0.50s;      /* how long one word takes to punch in and settle */
  --iw-last: 12;         /* final BEAT index (and+produce share beat 2, game+shows beat 4) */

  --intro-hold: 1.10s;   /* <-- THE ONE TO CHANGE. Stillness on the finished message. */

  /* Derived — leave these alone. */
  --intro-push:  calc(var(--iw-base) + var(--iw-last) * var(--iw-step)
                      + var(--iw-dur) + var(--intro-hold));
  --intro-veil:  calc(var(--intro-push) + 0.27s);
  --intro-clear: calc(var(--intro-veil) + 0.28s);
}

.hero-intro {
  position: absolute;
  inset: 0;
  z-index: 6;
  display: grid;
  place-items: center;
  padding-inline: var(--gutter);
  text-align: center;

  /* Pure #000, not --stage-000 (#050507). The clip's own field is a true black
     and its borders are feathered to 0, so matching exactly makes the video's
     rectangle invisible with no blend mode at all. At #050507 the frame would
     sit ~2% darker than the card — slight, but visible as a faint rectangle on
     a good monitor. This is also what frees .hero-intro-stage to be blurred and
     faded: a mix-blend-mode would have been isolated by those effects. */
  background: #000;

  pointer-events: none;

  /* The veil, deliberately later than the content it surrounds. */
  animation: introVeil 0.95s var(--ease) var(--intro-veil) forwards;
}

/* Logo and words move as one object, because they are one object — a title
   card. Scaling up while blurring and fading reads as the camera pushing
   past the title rather than the title politely leaving. The easing is
   deliberately ease-IN so it accelerates away. */
.hero-intro-stage {
  /* FULL BLEED (Jeff's note, Aug 21): the stage now IS the whole card, and
     the clip fills it edge to edge — so there is no video rectangle to see.
     (Video black renders a hair lighter than CSS #000 on good monitors; the
     contained frame was ghosting as "a square inside a square".) */
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* ishake fires at 0.5s — the moment the APPLOFF type lands in the punch cut —
     and is long gone before introPush begins, so the transforms never fight. */
  animation:
    introPush 0.8s cubic-bezier(0.45, 0, 0.75, 0) var(--intro-push) forwards,
    ishake 0.42s var(--ease-sharp) 0.5s;
  will-change: transform, opacity, filter;
}

/* One bright frame as the type lands. Light pop, not a white-out. */
.hero-intro .iflash {
  position: absolute;
  inset: 0;
  background: #fff;
  opacity: 0;
  pointer-events: none;
  animation: iflash 0.24s linear 0.48s both;
}
@keyframes iflash { 0% { opacity: 0; } 30% { opacity: 0.30; } 100% { opacity: 0; } }
@keyframes ishake {
  0%, 100% { transform: none; }
  22% { transform: translateY(6px); }
  48% { transform: translateY(-3px); }
  74% { transform: translateY(1.5px); }
}

@keyframes introPush {
  to { opacity: 0; transform: scale(1.07); filter: blur(10px); }
}

@keyframes introVeil {
  to { opacity: 0; visibility: hidden; }
}

/* No entrance animation on the logo. It animates itself — competing motion
   would fight the mark's own choreography.

   On the height: the old GIF was cropped tight, so 260px of GIF was 260px of
   logo. Here the mark occupies only ~61% of the frame height; the rest is black
   field and smoke. A 480px frame is what lands a ~290px mark. Shrink this and
   the logo goes small again, which was the original complaint. */
.hero-intro-logo {
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;      /* full bleed — the clip IS the screen */
  background: #000;
  border: 0;
}

/* Portrait screens: cover would crop the APPLOFF wordmark off the sides, so
   tall screens fit the full frame instead. The letterbox bars are the card's
   own black, which reads as intentional cinema framing on a phone. */
@media (orientation: portrait) {
  .hero-intro-logo { object-fit: contain; }
}

/* ---------- The words ----------

   Bigger than before, and broken by hand rather than by the browser.

   The negative margin is doing real work: the clip's mark sits with roughly 23%
   of the frame height as empty black beneath it, so at a 480px frame there is
   already ~109px of visual gap before any CSS gap applies. Left alone the words
   float far too low and read as detached from the logo — which is exactly how
   they looked. This pulls them back into the lockup. */
/* THE BUILD — full-frame gold words over the empty (post-cut) stage.
   Words sit in their FINAL positions from the start, invisible, so nothing
   reflows: each one punches into a slot that was always waiting for it.
   All gold — the cinema-title echo of the flare in the logo. The cut to the
   white-and-green site afterwards is the palette payoff (Jeff's idea). */
.hero-intro-build {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: clamp(0.3rem, 1.2vw, 1rem);
  text-align: center;
  padding-inline: var(--gutter);
  /* leaves with the same camera-push as the logo did */
  animation: introPush 0.8s cubic-bezier(0.45, 0, 0.75, 0) var(--intro-push) forwards;
  will-change: transform, opacity, filter;
}
.bline {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  column-gap: clamp(0.5rem, 1.7vw, 1.4rem);
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 112%;
  font-size: clamp(1.6rem, 5.5vw, 4.6rem);
  line-height: 1.06;
  letter-spacing: 0.01em;
  text-transform: uppercase;
}
.bw {
  opacity: 0;
  display: inline-block;
  will-change: transform, opacity, filter;
  /* Gold gradient via background-clip. NO filter, NO text-shadow — ever.
     (Square-halo bug; see the hero-word note.) */
  background: linear-gradient(180deg, #FFE18A 0%, #FFC83D 55%, #F5AE3D 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: introWord 0.5s cubic-bezier(0.2, 0.9, 0.3, 1) both;
  animation-delay: calc(var(--iw-base) + var(--i) * var(--iw-step));
}
/* The same camera-punch the logo throws: huge and blurred, slams to a stop
   with a small settle. Each word arrives the way the mark did. */
@keyframes introWord {
  0%   { opacity: 0; transform: scale(1.9); filter: blur(9px); }
  55%  { opacity: 1; transform: scale(0.97); filter: blur(0); }
  78%  { transform: scale(1.015); }
  100% { opacity: 1; transform: scale(1); }
}
/* The video cuts away before the first word — the logo never shares its
   frame with anything. */
/* The punch clip runs 1.77s (Jeff caught the early cut — the smoke settle
   was being clipped). The fade now starts ON the clip's held final frame,
   so every frame of the master plays. */
/* The clip ends at 1.77s and its last frame HOLDS for a beat before the cut
   (team note, Sep 17: "it zips too fast — let it breathe"). The build words
   below wait correspondingly (--iw-base). */
.hero-intro-logo { animation: logoCut 0.18s linear 2.15s forwards; }
@keyframes logoCut { to { opacity: 0; } }

.hero-intro.done {
  animation: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s var(--ease);
}

/* ---------- Seen it already this session ----------

   A 4-second title card is right the first time and irritating the fifth. The
   site is multi-page, so without this, clicking Team and then back to Home
   replays the whole thing — which is exactly the sort of detail that makes a
   site feel like it is performing at you rather than working for you.

   An inline script in index.html's <head> sets `.intro-seen` on <html> before
   first paint, so on a repeat view the card never renders at all and the hero
   arrives immediately. Cleared when the browser tab closes.

   To make it play every single time, delete the <head> script in index.html. */
html.intro-seen .hero-intro { display: none; }
html.intro-seen .hero h1 .line > span,
html.intro-seen .hero-sub,
html.intro-seen .hero-actions,
html.intro-seen .sound-toggle,
html.intro-seen .scroll-hint { animation-delay: 0s !important; }

/* The hero waits for the curtain. */
.hero h1 .line:nth-child(1) > span { animation-delay: var(--intro-clear); }
.hero h1 .line:nth-child(2) > span { animation-delay: calc(var(--intro-clear) + 0.12s); }
.hero h1 .line:nth-child(3) > span { animation-delay: calc(var(--intro-clear) + 0.24s); }
.hero-sub     { animation-delay: calc(var(--intro-clear) + 0.45s); }
.hero-actions { animation-delay: calc(var(--intro-clear) + 0.59s); }
/* The sound toggle no longer waits for the intro to clear — it sits quietly
   in the corner FROM THE START (z-index above the title card), because
   clicking it during the opening restarts the opening with the sting.
   (Jeff's note: otherwise nobody could ever ask for the music.) */
.sound-toggle { animation-delay: 0.6s; }
.scroll-hint  { animation-delay: calc(var(--intro-clear) + 0.90s); }

.hero.intro-done h1 .line > span,
.hero.intro-done .hero-sub,
.hero.intro-done .hero-actions,
.hero.intro-done .sound-toggle,
.hero.intro-done .scroll-hint {
  animation-delay: 0s !important;
}

/* ==========================================================================
   THE BUG MOVE — Jeff's idea, and the page's best structural difference.

   After ~14 seconds of stillness the headline stops blocking the sizzle: it
   shrinks into the bottom-right corner exactly like a network bug, the firsts
   list and scroll hint fade, the buttons dock bottom-left, and the video —
   which was always playing back there — finally gets the stage. Any scroll,
   wheel, touch or click brings everything back.

   The headline's journey is computed in JS (a translate+scale to the exact
   corner, whatever the viewport), so CSS only declares the transitions and the
   fades. Reduced-motion users never get the move at all.
   ========================================================================== */
.hero-inner { position: relative; }

.hero-headline,
.hero-actions {
  transition: transform 1.1s var(--ease);
  will-change: transform;
}
.hero-firsts,
.scroll-hint {
  transition: opacity 0.7s var(--ease), visibility 0.7s var(--ease);
}
/* The company lines are NOT hidden while bugged any more — in the resolve
   model (Jeff, Sep 4) they rise bottom-left AS the headline takes the
   bottom-right corner. Only the scroll hint clears. */
.hero.bugged .scroll-hint {
  /* animation:none matters (Jeff, Sep 4: "a little word pops up"): the hint's
     entrance animation restarts when staging lifts at the resolve, and a
     running animation outranks these declarations — so it faded IN at the
     exact moment it was supposed to be gone. Kill the animation, then hide. */
  animation: none;
  opacity: 0;
  visibility: hidden;
}
/* While bugged, the headline is a corner graphic, not a heading to select. */
.hero.bugged .hero-headline { cursor: pointer; }

/* Small pulsing dot for the "now playing" line on the slate card */
.live-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--green);
  display: inline-block;
  margin-right: 0.5rem;
  animation: pulse 1.7s infinite;
}

@media (max-width: 860px) {
  .bline { font-size: clamp(1.25rem, 6.4vw, 2rem); }
}

/* ---------- Hero sound toggle ---------- */
.sound-toggle {
  /* TOP-RIGHT, under the nav (Jeff, Sep 4). It used to sit vertically
     centred on the hero's right edge — which is exactly the stage the
     title-card words play on, so it photobombed every arrival. Top-right is
     the one corner nothing else ever claims: logo top-left, headline resolves
     bottom-right, company lines bottom-left. Phones already lived here. */
  position: absolute;
  right: var(--gutter);
  top: calc(env(safe-area-inset-top, 0px) + 10.75rem);
  transform: none;
  z-index: 7;   /* above the intro card (6) — reachable during the opening */
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.7rem 1.15rem 0.7rem 0.95rem;
  border-radius: 100px;
  /* State must be readable at a glance (Jeff's note): OFF wears a muted red
     rim — clearly red without screaming "error", since muted is the default
     state everyone arrives in. ON goes full green with a glow. */
  border: 2px solid rgba(224, 104, 96, 0.65);
  background: rgba(5, 5, 7, 0.5);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  color: var(--white);
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  opacity: 0;
  animation: fadeUp 0.9s var(--ease) 1s forwards;
  transition: border-color 0.35s var(--ease), background 0.35s var(--ease);
}
/* Post-intro invitation: replay the opening with sound. Shown briefly by JS
   once the opening finishes (only when the sting file exists). */
.sound-invite {
  position: absolute;
  right: var(--gutter);
  top: calc(50% + 3.4rem);
  z-index: 7;
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font: inherit;
  font-weight: 700;
  font-size: 0.82rem;
  color: var(--on-gold);
  background: linear-gradient(180deg, #FFE18A 0%, #FFC83D 70%);
  border: 0;
  border-radius: 100px;
  padding: 0.6rem 1.1rem;
  cursor: pointer;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.5s var(--ease), transform 0.5s var(--ease);
  pointer-events: none;
}
.sound-invite.show { opacity: 1; transform: none; pointer-events: auto; }

.sound-toggle:hover { background: rgba(5, 5, 7, 0.78); }
.sound-icon { display: grid; place-items: center; width: 19px; height: 19px; }
.sound-icon svg { grid-area: 1 / 1; transition: opacity 0.25s var(--ease); }
.sound-toggle .ico-loud  { opacity: 0; }
.sound-toggle .ico-muted { opacity: 1; }
.sound-toggle.is-on .ico-loud  { opacity: 1; }
.sound-toggle.is-on .ico-muted { opacity: 0; }
.sound-toggle.is-on {
  border-color: var(--green);
  background: rgba(0, 227, 106, 0.18);
  box-shadow: 0 0 0 3px rgba(0, 227, 106, 0.22), 0 0 22px rgba(0, 227, 106, 0.4);
}

@media (max-width: 860px) {
  /* Phones: bottom-of-hero was below the fold and under Safari's own toolbar
     (Jeff's portrait catch). Top-right, just under the menu, always visible. */
  .sound-toggle {
    top: calc(env(safe-area-inset-top, 0px) + 4.75rem);
    bottom: auto;
    right: 1rem;
    transform: none;
    padding: 0.6rem 0.95rem;
  }
  .sound-invite {
    top: calc(env(safe-area-inset-top, 0px) + 7.6rem);
    right: 1rem;
  }
  .sound-label { display: none; }
}

.scroll-hint {
  position: absolute;
  right: var(--gutter);
  bottom: clamp(3.5rem, 7vw, 6rem);
  writing-mode: vertical-rl;
  font-size: 0.63rem;
  font-weight: 700;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--ink-500);
  display: flex;
  align-items: center;
  gap: 1rem;
  opacity: 0;
  animation: fadeUp 1s var(--ease) 1.1s forwards;
}
.scroll-hint::after {
  content: '';
  width: 1px; height: 60px;
  background: linear-gradient(to bottom, var(--ink-700), transparent);
}

/* ==========================================================================
   NUMBERS BAND
   ========================================================================== */
.numbers {
  border-block: 1px solid var(--stage-300);
  background:
    radial-gradient(70% 150% at 50% 0%, rgba(0, 227, 106, 0.10), transparent 70%),
    var(--stage-050);
  padding-block: clamp(3rem, 6vw, 5.5rem);
}
/* Four equal columns, centred, with hairline separators between them.
   Every number sits on the same baseline and every label starts at the
   same height — that's what makes the row read as symmetrical rather
   than as four things that happen to be near each other. */
.numbers-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
}
.stat {
  text-align: center;
  padding-inline: clamp(0.75rem, 2vw, 2rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  border-left: 1px solid var(--stage-300);
}
.stat:first-child { border-left: 0; }

/* Numbers share one optical line regardless of digit count */
.stat-num-wrap {
  display: flex;
  align-items: baseline;
  justify-content: center;
  min-height: 1em;
}
.stat-num {
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 112%;
  font-size: clamp(2.6rem, 6.2vw, 5.4rem);
  line-height: 0.9;
  letter-spacing: -0.035em;
  /* TRIAL (Jeff, Aug 21): the numbers count up in GOLD — light top, rich
     bottom, same trophy gradient as nothing else on the page. His reasoning:
     the page is heavy on green, and numbers-as-money reads naturally in gold.
     TO REVERT to green: replace this gradient with var(--grad-hot). */
  background: linear-gradient(180deg, #FFE18A 0%, #FFC83D 55%, #F5AE3D 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  display: block;
  font-variant-numeric: tabular-nums;
}

/* REVERSED by Jeff after seeing it: the all-white band with one gold number
   read "blah" — and he was right, because the count-up IS the show. A game
   show company's numbers climb in colour. The stats are achievements
   (signal green); gold stays reserved for the hero word, prize copy and
   Party Polls scores. Do not re-whiten these. */
/* All four stats are green. The per-stat colour overrides that used to live here
   were left over from the old pink/gold palette — one of them still held the
   original cyan, which is how stray cyan survived the green switch.
   Violet is JAHM's alone; it must not appear in this band. */
.stat-label {
  margin-top: 1.1rem;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-300);
  line-height: 1.6;
  /* Two lines reserved on every stat so all four labels start and end level,
     even when one of them only needs a single line. */
  min-height: calc(2 * 1.6em);
  display: block;
  text-wrap: balance;
}


/* The two-shows milestone gets its own line under the band — too good to
   cram into a stat label, and a long label would break the row's symmetry. */
.numbers-note {
  margin-top: clamp(2.25rem, 4vw, 3.25rem);
  padding-top: clamp(1.5rem, 2.5vw, 2rem);
  border-top: 1px solid var(--stage-300);
  text-align: center;
  font-size: clamp(0.95rem, 1.25vw, 1.1rem);
  line-height: 1.6;
  color: var(--ink-300);
  max-width: 62ch;
  margin-inline: auto;
  text-wrap: balance;
}
.numbers-note strong { color: var(--white); font-weight: 600; }

/* ==========================================================================
   FORMAT LIBRARY GRID
   ========================================================================== */
.lib-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(285px, 1fr));
  gap: clamp(1rem, 1.8vw, 1.6rem);
}
.lib-card {
  /* Jeff (Aug 26): the badges were covering the artwork. The card used to be
     one full-bleed image with the badge and title floated on top of a bottom
     gradient. Now it is split honestly: the art fills the top, untouched, and
     the badge/title/host live in a solid dark strip beneath it. Nothing sits
     on the picture any more. */
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--stage-200);
  border: 1px solid var(--stage-300);
  text-align: left;
  width: 100%;
  display: block;
  transition: transform 0.55s var(--ease), border-color 0.55s var(--ease),
              box-shadow 0.55s var(--ease);
}
.lib-card:hover {
  transform: translateY(-7px);
  border-color: var(--green);
  box-shadow: 0 24px 60px -22px rgba(0, 227, 106, 0.5);
}
.lib-card img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  /* Far gentler dimming than before — the art no longer has to make room
     for type sitting on it. */
  filter: saturate(0.9) brightness(0.88);
  transition: filter 0.55s var(--ease), transform 1.2s var(--ease);
}
.lib-card:hover img { filter: saturate(1.12) brightness(1); transform: scale(1.04); }
.lib-card-body {
  padding: 1.15rem 1.35rem 1.35rem;
  border-top: 1px solid var(--stage-300);
}
.lib-card-body .badge { margin-bottom: 0.8rem; }
.lib-card h3 {
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 112%;
  text-transform: uppercase;
  font-size: 1.4rem;
  line-height: 0.95;
  letter-spacing: -0.02em;
  color: var(--white);
  margin-bottom: 0.55rem;
}
.lib-card .lib-host {
  font-size: 0.76rem;
  color: var(--ink-300);
  font-weight: 500;
}
.lib-card .lib-more {
  margin-top: 1rem;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--green-hot);
  display: flex;
  align-items: center;
  gap: 0.45rem;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.45s var(--ease), transform 0.45s var(--ease);
}
.lib-card:hover .lib-more { opacity: 1; transform: translateY(0); }

/* ---------- Execution section ---------- */
.exec-body { max-width: 62ch; }
/* One voice, one size (Jeff, Sep 4): everything under "has to be perfect"
   reads at the same scale as the paragraph directly beneath the headline —
   no big-opener-then-small-print step-down in this section. Each paragraph
   opens with a bolded white thesis sentence, same pattern throughout. */
.exec .exec-body .body-copy {
  font-size: clamp(1.05rem, 1.55vw, 1.4rem);
  line-height: 1.55;
}
.exec .lede strong { color: var(--white); font-weight: 700; }
/* The section-head gap was sized for a lede-then-small-print layout; with all
   three paragraphs at one size they read as one block (Jeff, Sep 4: "shouldn't
   they all kind of be together?"). Match the inter-paragraph rhythm. */
.exec .section-head { margin-bottom: 0; }   /* the grid row-gap IS the spacing */
.exec-body .body-copy { color: var(--ink-300); line-height: 1.75; margin-bottom: 1.4rem; }
.exec-body .body-copy strong { color: var(--white); }
.exec-body .tlink { margin-top: 0.4rem; }

/* ---------- Modal ---------- */
.modal {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: grid;
  place-items: center;
  padding: var(--gutter);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.4s var(--ease);
}
.modal.open { opacity: 1; pointer-events: auto; }
.modal-scrim {
  position: absolute;
  inset: 0;
  background: rgba(3, 3, 5, 0.86);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}
.modal-card {
  position: relative;
  z-index: 2;
  width: min(920px, 100%);
  max-height: 86svh;
  overflow-y: auto;
  background: var(--stage-100);
  border: 1px solid var(--stage-300);
  border-radius: var(--radius-lg);
  transform: translateY(26px) scale(0.98);
  transition: transform 0.45s var(--ease);
}
.modal.open .modal-card { transform: translateY(0) scale(1); }
.modal-hero { position: relative; aspect-ratio: 21 / 9; overflow: hidden; background: var(--stage-200); }
.modal-hero img { width: 100%; height: 100%; object-fit: cover; }
.modal-hero::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(to top, var(--stage-100), transparent 65%);
}
.modal-body { padding: clamp(1.6rem, 3.5vw, 2.75rem); margin-top: -3.5rem; position: relative; z-index: 2; }
.modal-body .badge { margin-bottom: 1rem; }
.modal-body h2 { margin-bottom: 0.8rem; }
.modal-close {
  position: absolute;
  top: 1rem; right: 1rem;
  z-index: 5;
  width: 42px; height: 42px;
  border-radius: 50%;
  background: rgba(5,5,7,0.7);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border: 1px solid var(--stage-400);
  display: grid;
  place-items: center;
  transition: background 0.3s var(--ease), transform 0.3s var(--ease);
}
/* currentColor again — the X needs the dark ink once the fill goes green. */
.modal-close:hover { background: var(--green); color: var(--on-green); transform: rotate(90deg); }

/* ==========================================================================
   THE ZAG / FIRSTS TIMELINE
   ========================================================================== */
.firsts {
  position: relative;
  isolation: isolate;
}
.firsts::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(48% 60% at 85% 18%, rgba(139, 92, 255, 0.13), transparent 68%);
}

.firsts-line {
  margin-top: clamp(3rem, 6vw, 5rem);
  display: flex;
  flex-direction: column;
}

.first-item {
  display: grid;
  grid-template-columns: 56px 1fr;
  gap: clamp(1.25rem, 3vw, 2.75rem);
  padding-bottom: clamp(2.75rem, 5vw, 4.5rem);
}
.first-item:last-child { padding-bottom: 0; }

/* The rail with the travelling dot */
.first-rail {
  position: relative;
  display: flex;
  justify-content: center;
}
.first-rail::before {
  content: '';
  position: absolute;
  top: 22px;
  bottom: -1px;
  width: 2px;
  background: linear-gradient(to bottom, var(--stage-400), var(--stage-300));
}
.first-item:last-child .first-rail::before {
  background: linear-gradient(to bottom, var(--green), transparent);
}
.first-dot {
  position: relative;
  z-index: 2;
  width: 15px; height: 15px;
  margin-top: 8px;
  border-radius: 50%;
  background: var(--stage-000);
  border: 2px solid var(--stage-400);
  transition: border-color 0.5s var(--ease), box-shadow 0.5s var(--ease),
              background 0.5s var(--ease);
  flex: none;
}
.first-item:hover .first-dot {
  border-color: var(--green);
  box-shadow: 0 0 0 6px rgba(0, 227, 106, 0.14);
}
.first-item.is-now .first-dot {
  background: var(--green);
  border-color: var(--green);
  box-shadow: 0 0 0 6px rgba(0, 227, 106, 0.18);
  animation: pulseRing 2.4s infinite;
}
@keyframes pulseRing {
  0%, 100% { box-shadow: 0 0 0 6px rgba(0, 227, 106, 0.18); }
  50%      { box-shadow: 0 0 0 13px rgba(0, 227, 106, 0.03); }
}

.first-year {
  display: inline-block;
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 112%;
  font-size: clamp(0.95rem, 1.4vw, 1.15rem);
  letter-spacing: 0.06em;
  color: var(--ink-500);
  margin-bottom: 0.7rem;
  transition: color 0.45s var(--ease);
}
.first-item:hover .first-year { color: var(--green-hot); }
.first-item.is-now .first-year { color: var(--green-hot); }

.first-body h3 { margin-bottom: 0.9rem; color: var(--white); }

/* The claim is the punchline of each entry, so it gets `balance` rather than
   the `pretty` that every other <p> inherits.

   The difference matters here. `pretty` only prevents a last-line orphan;
   `balance` evens the length of ALL the lines, so a three-line claim reads as a
   tidy block instead of two full lines and a stub. These six claims run from 30
   to 98 characters, and without balancing that spread is what made the column
   look ragged.

   The measure went 46ch -> 52ch for the same reason: at 46ch the two longest
   claims spilled to three lines while the shortest sat on one. At 52ch every
   claim lands on one or two lines, so the section has a rhythm. Widening
   further would start to hurt readability at this size. */
.first-claim {
  font-size: clamp(1.05rem, 1.65vw, 1.42rem);
  line-height: 1.4;
  font-weight: 600;
  color: var(--ink-100);
  margin-bottom: 0.9rem;
  max-width: 52ch;
  text-wrap: balance;
  border-left: 2px solid var(--green);
  padding-left: 1.1rem;
}
/* ==========================================================================
   MERGED STORY ENTRIES — the old Current Slate lives inside the timeline now
   (Jeff's condensation note, Aug 21). Each entry can carry key art with live
   badges and a watch action, so story + status read in one pass.

   Layout: the entry body becomes a two-column grid — text left, media right.
   Everything except .first-media flows in column 1; the figure occupies
   column 2 for the full height. On small screens it stacks below the text.
   ========================================================================== */
.first-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(230px, 26vw, 330px);
  column-gap: clamp(1.5rem, 3.5vw, 3rem);
  align-items: start;
}
.first-body > *:not(.first-media) { grid-column: 1; }
.first-media {
  grid-column: 2;
  /* span more rows than any entry has children, so the figure always runs the
     full height of the text column regardless of paragraph count */
  grid-row: 1 / span 9;
  position: relative;
  margin: 0;
}
.first-media img {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  border-radius: 12px;
  border: 1px solid var(--stage-300);
  display: block;
}
/* Broadcast status line (Jeff, Aug 22): the chip pills read as pushable
   buttons. Status is now a lettered line — a live dot and spaced caps —
   which reads as information, not a control. Sits ABOVE the art (never on
   it — the show logos live in the artwork). */
.fm-status {
  display: flex; align-items: center; gap: 0.5rem;
  margin: 0 0 0.7rem;
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--green);
}
/* "Watch the Sizzle" on a timeline entry (Sep 4, BGL first): a quiet text
   control under the caption. Deliberately NOT a solid button — the purge of
   Aug 22 was about loud chips leading nowhere; this is small, honest, and
   plays our own file. */
.fm-sizzle {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  margin-top: 0.6rem;
  padding: 0.45rem 0.9rem;
  border-radius: 100px;
  border: 1px solid var(--stage-300);
  background: transparent;
  color: var(--ink-200);
  font: inherit;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color 0.3s var(--ease), color 0.3s var(--ease);
}
.fm-sizzle:hover { border-color: var(--green); color: var(--white); }
.fm-sizzle svg { color: var(--green); }

.fm-status .dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--green);
  box-shadow: 0 0 0 3px rgba(0, 227, 106, 0.18);
  animation: pulse 2.2s ease-in-out infinite;
}
.first-media figcaption {
  display: flex; align-items: center; justify-content: space-between;
  gap: 0.75rem; flex-wrap: wrap;
  margin-top: 0.7rem;
  font-size: 0.78rem; color: var(--ink-500);
}
.btn-sm { padding: 0.55rem 1rem; font-size: 0.8rem; }

@media (max-width: 900px) {
  .first-body { grid-template-columns: 1fr; }
  .first-media { grid-column: 1; grid-row: auto; margin-top: 1.1rem; max-width: 480px; }
}

.first-note {
  color: var(--ink-500);
  font-size: 0.98rem;
  line-height: 1.7;
  max-width: 62ch;
}

/* ==========================================================================
   JAHM STUDIOS BAND
   ========================================================================== */
.jahm-band {
  position: relative;
  isolation: isolate;
  border-block: 1px solid var(--stage-300);
  background: var(--stage-050);
  overflow: hidden;
}
.jahm-band::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(55% 85% at 8% 12%, rgba(139, 92, 255, 0.20), transparent 66%),
    radial-gradient(50% 80% at 92% 88%, rgba(139, 92, 255, 0.14), transparent 66%);
}
.jahm-inner {
  display: grid;
  grid-template-columns: 1fr 420px;
  gap: clamp(2.5rem, 5vw, 5rem);
  align-items: center;
}
.jahm-copy .eyebrow::before { background: var(--violet); }
.jahm-copy h2 {
  background: var(--grad-cool);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.jahm-card {
  display: block;
  border: 1px solid var(--stage-400);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--stage-100);
  transition: transform 0.5s var(--ease), border-color 0.5s var(--ease),
              box-shadow 0.5s var(--ease);
}
.jahm-card:hover {
  transform: translateY(-8px);
  border-color: var(--violet);
  box-shadow: 0 28px 66px -24px rgba(139, 92, 255, 0.42);
}
.jahm-card-art {
  aspect-ratio: 1200 / 630;
  overflow: hidden;
  background: #5B21B6;
}
.jahm-card-art img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 1.1s var(--ease);
}
.jahm-card:hover .jahm-card-art img { transform: scale(1.05); }
.jahm-card-body { padding: clamp(1.4rem, 2.5vw, 1.9rem); }

/* ==========================================================================
   TYPOGRAPHY BALANCING
   Browsers do the line-breaking maths so headlines don't leave stragglers
   and body copy doesn't strand a single word on the last line.
   ========================================================================== */
h1, h2, h3, .display, .balance { text-wrap: balance; }
p, li, .lede, .body-copy { text-wrap: pretty; }

/* ==========================================================================
   APPLOFF ORIGINAL BADGE
   Marks the five formats Jeff created, so the distinction is visible at a
   glance without the copy having to claim anything.
   ========================================================================== */
.badge-original {
  background: transparent;
  color: var(--gold);
  border: 1.5px solid var(--gold);
  letter-spacing: 0.16em;
}
.lib-card:hover .badge-original,
.slate-item:hover .badge-original {
  background: var(--gold);
  color: #1A1204;
}

/* ==========================================================================
   HERO FIRSTS — four stacked lines, not a paragraph
   ========================================================================== */
.hero-firsts {
  list-style: none;
  margin: 0 0 2.4rem;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-width: 46ch;
}
.hero-firsts li {
  position: relative;
  padding-left: 1.4rem;
  line-height: 1.35;
  text-wrap: pretty;
}
.hero-firsts li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 8px;
  height: 2px;
  background: var(--green);
}
.hero-firsts .payoff {
  color: var(--white);
  font-weight: 600;
  margin-top: 0.45rem;
}
.hero-firsts .payoff::before { background: var(--gold); width: 14px; }

/* ==========================================================================
   TALENT WALL
   ========================================================================== */
.talent-wall {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.55rem 2.4rem;
  align-items: baseline;
}
.talent-wall li {
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 112%;
  text-transform: uppercase;
  font-size: clamp(1.35rem, 3.4vw, 2.9rem);
  line-height: 1.14;
  letter-spacing: -0.022em;
  color: var(--ink-500);
  transition: color 0.4s var(--ease);
  cursor: default;
}
.talent-wall li:hover { color: var(--white); }
/* ONE TIER (Jeff, Sep 11): every name reads at full strength — the old
   is-marquee bright tier is retired. "The Best Say Yes" admits no B-list. */
.talent-wall li { color: var(--ink-100); }

/* ==========================================================================
   INTERNATIONAL
   ========================================================================== */
.intl { position: relative; isolation: isolate; }
.intl::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(50% 90% at 82% 30%, rgba(139, 92, 255, 0.09), transparent 68%);
}
.intl-inner {
  display: grid;
  grid-template-columns: 1fr 1.15fr;
  gap: clamp(2rem, 5vw, 5rem);
  align-items: start;
}
.intl-flags {
  list-style: none;
  margin: 2rem 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}
/* Plain lettered line (Jeff, Aug 22): the bordered chips looked pushable. */
.intl-flags li {
  padding: 0;
  border: 0;
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink-100);
  transition: border-color 0.35s var(--ease), color 0.35s var(--ease);
}
/* Separator between countries. The dot is written as a CSS escape and the
   spacing comes from margin, not from padded whitespace inside content()
   — an earlier version of this rule shipped raw bytes and rendered
   garbage on the live page (Jeff, Aug 25). */
.intl-flags li + li::before {
  content: "\00b7";
  color: var(--stage-400);
  margin-right: 0.6rem;
}

@media (max-width: 1080px) {
  .intl-inner { grid-template-columns: 1fr; }
}

/* ==========================================================================
   PLAY A ROUND — the interactive moment
   ========================================================================== */
.playnow { position: relative; isolation: isolate; }
/* Side-by-side on big screens (Jeff, Aug 27: the widget capped at 780px and
   hung left, leaving "a void" on the right of a large monitor). Text and the
   playable round now share the row; below 1080px it stacks as before. */
@media (min-width: 1080px) {
  .playnow .wrap {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 640px);
    gap: clamp(2.5rem, 5vw, 5.5rem);
    align-items: center;
  }
  .playnow .section-head { margin-bottom: 0; }
  .playnow .pn { margin-top: 0; }
}
.playnow::before {
  content: '';
  position: absolute; inset: 0; z-index: -1;
  background: radial-gradient(55% 90% at 78% 25%, rgba(139, 92, 255, 0.11), transparent 68%);
}
/* ==========================================================================
   PLAY A ROUND — skinned as Party Polls, not as this site

   This module used to wear the site's palette: dark grey card, green accents.
   It was described, accurately, as "all black, just dark." A game embedded in
   a page should look like the game, otherwise it reads as a mock-up of the
   game.

   Every value below was sampled from screenshots of the real app rather than
   guessed — the purple gradient, the gold, the near-black chips, the round
   scoring colours, and the warm-to-cool gradient on the primary button.

   SCOPING. All of it hangs off custom properties declared on `.pn`, so the
   Party Polls palette cannot leak into the rest of the site. The page's green
   and violet are untouched. The one deliberate exception is `.pn-accent` on
   the section heading, which goes gold so the brand is signalled before you
   reach the card.

   NO JS CHANGED. Every class name and data attribute is exactly as it was, so
   app.js drives this new skin without a single edit.
   ========================================================================== */

/* The heading accent — gold rather than the site's violet, so "Play a round."
   already belongs to Party Polls. */
.pn-accent {
  background: none;
  -webkit-background-clip: initial;
  background-clip: initial;
  color: #F4D464;
}

.pn {
  /* ---- the Party Polls palette, scoped to this component ---- */
  --pp-bg-top:    #6327BA;   /* top of the app's background gradient        */
  --pp-bg-mid:    #5022A6;
  --pp-bg-bot:    #3F1B85;   /* bottom of the gradient                      */
  --pp-bloom:     #8F2AAE;   /* magenta bloom that sits top-centre          */
  --pp-sheet:     #3B167E;   /* the darker bottom sheet the question sits on */
  --pp-gold:      #F4D464;   /* pills, labels, scores — the signature colour */
  --pp-gold-deep: #ECB448;
  --pp-chip:      #281C30;   /* near-black chip behind ACTUAL / your guess   */
  --pp-good:      #70C488;   /* a well-read round                           */
  --pp-poor:      #E06860;   /* a badly-read round                          */
  --pp-panel:     rgba(255, 255, 255, 0.11);
  --pp-panel-hi:  rgba(255, 255, 255, 0.17);
  --pp-line:      rgba(255, 255, 255, 0.20);
  --pp-dim:       #CBBCEA;   /* secondary text on purple                    */

  position: relative;
  isolation: isolate;
  overflow: hidden;
  margin-top: clamp(2.5rem, 5vw, 4rem);
  border: 0;
  border-radius: 28px;
  padding: clamp(2rem, 4vw, 3rem);
  max-width: 780px;
  min-height: 480px;
  /* COLUMN, not row — the brand art sits ON TOP of the game, never beside it.
     (Jeff's note: the row default squeezed the art and game side by side.) */
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  gap: clamp(0.4rem, 1vw, 0.8rem);

  background:
    radial-gradient(90% 55% at 50% 0%, var(--pp-bloom) 0%, transparent 62%),
    linear-gradient(180deg, var(--pp-bg-top) 0%, var(--pp-bg-mid) 46%, var(--pp-bg-bot) 100%);
  box-shadow: 0 30px 90px -30px rgba(60, 20, 130, 0.75);
}

.pn-stage { width: 100%; }
.pn-stage[hidden] { display: none; }

/* ---------- the round pill, like the app's STEP 1 / ROUND 3 OF 5 ---------- */
/* The game's real share art as the card's masthead — actual Party Polls
   branding, hotlinked from partypolls.com like the JAHM page does. Sized as
   a banner, rounded to sit naturally on the violet card. */
.pn-brand-art {
  display: block;
  width: min(340px, 72%);
  margin: 0 auto clamp(1.4rem, 3vw, 2.2rem);
  border-radius: 12px;
  box-shadow: 0 10px 34px -14px rgba(0, 0, 0, 0.55);
}

.pn-round {
  display: inline-block;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--pp-chip);
  background: var(--pp-gold);
  padding: 0.42rem 0.9rem;
  border-radius: 100px;
  margin-bottom: clamp(1.1rem, 2.4vw, 1.6rem);
}

/* ---------- the question ---------- */
.pn-q {
  color: #FFFFFF;
  margin-inline: auto;
  max-width: 24ch;
  margin-bottom: clamp(1.4rem, 3vw, 2rem);
  text-wrap: balance;
  line-height: 1.14;
}

.pn-q-small {
  font-size: clamp(1.02rem, 1.6vw, 1.28rem);
  font-weight: 700;
  line-height: 1.3;
  color: #FFFFFF;
  text-wrap: balance;
  margin-bottom: clamp(1.1rem, 2.2vw, 1.5rem);
}

/* The gold caption above the question — the app's "QUESTION FOR YOU" and
   "191 answered, what percentage said YES?" */
.pn-prompt {
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--pp-gold);
  margin-bottom: clamp(1rem, 2.2vw, 1.4rem);
  line-height: 1.5;
}
.pn-prompt strong { color: #FFFFFF; font-weight: 800; }

/* ---------- YES / NO ---------- */
.pn-yesno {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(0.7rem, 1.8vw, 1.1rem);
}

/* Big translucent slabs, exactly as in the app — not outlined buttons. */
.pn-choice {
  padding: clamp(1.5rem, 3.6vw, 2.4rem) 1rem;
  border-radius: 20px;
  border: 1px solid var(--pp-line);
  background: linear-gradient(160deg, var(--pp-panel-hi), var(--pp-panel));
  color: #FFFFFF;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.5rem, 3.6vw, 2.3rem);
  letter-spacing: 0.01em;
  text-transform: uppercase;
  transition: background 0.25s var(--ease), transform 0.25s var(--ease),
              border-color 0.25s var(--ease);
}
.pn-choice:hover {
  background: linear-gradient(160deg, rgba(255,255,255,0.26), rgba(255,255,255,0.15));
  border-color: rgba(255, 255, 255, 0.34);
  transform: translateY(-2px);
}
.pn-choice:active { transform: translateY(0); }
.pn-choice.picked {
  background: var(--pp-gold);
  border-color: var(--pp-gold);
  color: var(--pp-chip);
}

/* ---------- the guess slider ---------- */
.pn-slider-wrap { margin-bottom: clamp(1.6rem, 3vw, 2.25rem); }

.pn-readout {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 0.55rem;
  margin-bottom: clamp(0.9rem, 2vw, 1.3rem);
}

/* The oversized number, as in the app. The shadow rather than a stroke keeps
   the numerals crisp at small sizes — a text-stroke thickens the digits and
   makes them muddy once they scale down on a phone. */
.pn-value {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(3.6rem, 11vw, 6rem);
  line-height: 0.9;
  color: #FFFFFF;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 6px 0 rgba(38, 12, 84, 0.55);
}

/* The gold-outlined "% YES" chip that sits beside the number. */
.pn-unit {
  display: inline-flex;
  align-items: baseline;
  gap: 0.28em;
  border: 1.5px solid var(--pp-gold);
  border-radius: 100px;
  padding: 0.34rem 0.8rem;
  white-space: nowrap;
}
.pn-pct,
.pn-said {
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--pp-gold);
}

.pn-slider {
  width: 100%;
  appearance: none;
  -webkit-appearance: none;
  background: none;
  cursor: grab;
}
.pn-slider:active { cursor: grabbing; }
.pn-slider::-webkit-slider-runnable-track {
  height: 14px; border-radius: 100px;
  background: rgba(255, 255, 255, 0.26);
}
.pn-slider::-moz-range-track {
  height: 14px; border-radius: 100px;
  background: rgba(255, 255, 255, 0.26);
}
.pn-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 34px; height: 34px;
  margin-top: -10px;
  border-radius: 50%;
  background: #FFFFFF;
  border: 0;
  box-shadow: 0 4px 14px rgba(30, 8, 70, 0.5);
  transition: transform 0.2s var(--ease);
}
.pn-slider::-moz-range-thumb {
  width: 34px; height: 34px;
  border-radius: 50%;
  background: #FFFFFF;
  border: 0;
  box-shadow: 0 4px 14px rgba(30, 8, 70, 0.5);
}
.pn-slider:hover::-webkit-slider-thumb { transform: scale(1.08); }
.pn-slider:active::-webkit-slider-thumb { transform: scale(0.96); }

.pn-scale {
  display: flex;
  justify-content: space-between;
  margin-top: 0.7rem;
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--pp-dim);
}

/* ---------- LOCK IT IN — the app's warm-to-cool gradient ---------- */
.pn .pn-lock {
  width: 100%;
  justify-content: center;
  border: 0;
  color: #FFFFFF;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding-block: 1.05rem;
  border-radius: 100px;
  background: linear-gradient(90deg,
    #EFC04A 0%, #E5945E 16%, #DD6B80 30%, #D36193 42%,
    #BF63A7 52%, #9868CE 66%, #8874D8 74%, #7D89D9 82%,
    #759FD7 90%, #7CB0C6 100%);
  box-shadow: 0 10px 30px -8px rgba(221, 107, 128, 0.5);
}
.pn .pn-lock:hover { transform: translateY(-2px); filter: brightness(1.06); }
.pn .pn-lock:active { transform: translateY(0); }

/* ---------- the reveal ---------- */

/* Gold, matching the app's big score. The verdict classes carry the app's own
   round-scoring colours: green for a well-read round, gold for close, and a
   plain light tone rather than red for a miss — the app only reddens a genuinely
   poor round, and calling a first-time visitor's guess "bad" in red is a worse
   trade than the accuracy is worth. */
.pn-verdict {
  margin-bottom: 0.8rem;
  color: var(--pp-gold);
  text-shadow: 0 4px 24px rgba(244, 212, 100, 0.3);
}
.pn-verdict.nailed { color: var(--pp-good); }
.pn-verdict.close  { color: var(--pp-gold); }
.pn-verdict.miss   { color: #FFFFFF; }

.pn-crowd-read {
  font-size: clamp(0.95rem, 1.4vw, 1.1rem);
  line-height: 1.6;
  color: var(--pp-dim);
  margin-bottom: clamp(1.2rem, 2.4vw, 1.6rem);
  text-wrap: pretty;
}
.pn-crowd-read b { color: #FFFFFF; font-weight: 800; }

/* The comparison band. In the app this whole area carries a gold glow at the
   moment of reveal, which is what makes the payoff feel like a payoff. */
.pn-bars {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  margin-bottom: 1.4rem;
  padding: clamp(1rem, 2.2vw, 1.4rem);
  border-radius: 18px;
  background: rgba(20, 6, 52, 0.34);
  border: 1px solid rgba(244, 212, 100, 0.4);
  box-shadow: 0 0 0 4px rgba(244, 212, 100, 0.1),
              0 0 34px -6px rgba(244, 212, 100, 0.34);
}

.pn-bar {
  display: grid;
  grid-template-columns: 116px 1fr 72px;
  align-items: center;
  gap: 1rem;
}
.pn-bar-label {
  font-size: 0.63rem; font-weight: 800; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--pp-dim);
}
.pn-track {
  height: 14px; border-radius: 100px;
  background: rgba(255, 255, 255, 0.16);
  overflow: hidden;
}
.pn-fill {
  height: 100%; width: 0; border-radius: 100px;
  transition: width 1.1s var(--ease);
}
/* Your guess reads as neutral white; the crowd's real answer is the gold
   number, which is the one the app treats as the truth. */
.pn-fill-you  { background: rgba(255, 255, 255, 0.62); }
.pn-fill-real { background: var(--pp-gold); }

/* Dark chips with gold numerals — the app's ACTUAL 70% and 79% tags. */
.pn-bar-num {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 0.95rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
  color: var(--pp-gold);
  background: var(--pp-chip);
  border-radius: 8px;
  padding: 0.26rem 0.4rem;
}

.pn-gap {
  font-size: 0.95rem;
  color: var(--pp-dim);
  line-height: 1.6;
  padding-top: 1.2rem;
  border-top: 1px solid rgba(255, 255, 255, 0.16);
  margin-bottom: 1.6rem;
  text-wrap: pretty;
}
.pn-gap strong { color: var(--pp-gold); font-weight: 800; }

.pn-actions { display: flex; flex-wrap: wrap; gap: 0.9rem; }

/* Both action buttons are restyled for the purple card — the site's green
   primary would be the one jarring note in here. */
.pn .pn-actions .btn-ghost {
  border-color: var(--pp-line);
  color: #FFFFFF;
}
.pn .pn-actions .btn-ghost:hover {
  background: var(--pp-panel);
  border-color: rgba(255, 255, 255, 0.36);
}
.pn .pn-actions .btn-primary {
  background: var(--pp-gold);
  color: var(--pp-chip);
  border-color: var(--pp-gold);
}
.pn .pn-actions .btn-primary:hover {
  background: #FFE49A;
  border-color: #FFE49A;
}

.pn-streak {
  margin-top: 1.3rem;
  font-size: 0.68rem; font-weight: 800;
  letter-spacing: 0.15em; text-transform: uppercase;
  color: var(--pp-dim);
}
.pn-streak b { color: var(--pp-gold); }

@media (max-width: 560px) {
  .pn { min-height: 0; padding: 1.3rem; border-radius: 22px; }
  .pn-bar { grid-template-columns: 1fr auto; gap: 0.45rem 0.75rem; }
  .pn-bar-label { grid-column: 1 / -1; }
  .pn-track { grid-column: 1; }
  .pn-choice { padding: 1.3rem 0.75rem; border-radius: 16px; }
  .pn-actions { flex-direction: column; }
  .pn-actions .btn { width: 100%; justify-content: center; }
}

/* ==========================================================================
   SHORT VIEWPORTS — landscape phones (QA pass, Aug 22)
   Everything above sizes type by viewport WIDTH; a phone on its side is wide
   but only ~390px tall, so width-sized headlines overflow the screen. Height-
   capped sizes for any short landscape window.
   ========================================================================== */
/* SHORT DESKTOP WINDOWS (Jeff, Sep 4: an un-maximised Safari window cut the
   words off and hid the buttons). The display type sizes track viewport
   WIDTH, so a wide-but-short window used to get full-size type with no room
   left for the bullets and buttons beneath it. Between here and the
   landscape-phone block below, the hero now also answers to HEIGHT: type and
   spacing step down so the whole composition — headline, four bullets,
   buttons — fits any window it's given. */
@media (min-width: 701px) and (max-height: 820px) {
  .hero .d-hero { font-size: clamp(3rem, 11.5vh, 7.5rem); }
  .hero h1 { margin-bottom: 1.1rem; }
  .hero-sub { margin-bottom: 1.2rem; }
  .hero-sub li { margin-bottom: 0.2rem; }
  .hero .hero-inner { padding-top: 7rem; padding-bottom: 1.6rem; }
  .sound-toggle { top: calc(env(safe-area-inset-top, 0px) + 8.5rem); }
}
@media (min-width: 701px) and (max-height: 660px) {
  .hero .d-hero { font-size: clamp(2.2rem, 10vh, 5rem); }
  .hero h1 { margin-bottom: 0.8rem; }
  .hero-sub { font-size: 0.85rem; margin-bottom: 1rem; }
  .hero .hero-inner { padding-top: 5.5rem; padding-bottom: 1.2rem; }
  .hero-actions .btn { padding: 0.7rem 1.2rem; }
  .scroll-hint { display: none; }
}

@media (max-height: 520px) and (orientation: landscape) {
  .d-hero { font-size: clamp(2rem, 13vh, 3.4rem); }
  .hero-sub { font-size: 0.85rem; margin-top: 0.8rem; }
  .hero-sub li { margin-bottom: 0.15rem; }
  .hero-actions { margin-top: 1rem; }
  .scroll-hint { display: none; }
  .bline { font-size: clamp(0.95rem, 7.5vh, 1.9rem); }
  .hero-intro-build { gap: clamp(0.15rem, 1vh, 0.5rem); }
  .sound-toggle { top: calc(env(safe-area-inset-top, 0px) + 0.9rem); bottom: auto; transform: none; }
  .sound-invite { top: calc(env(safe-area-inset-top, 0px) + 4rem); }
}

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

/* ==========================================================================
   APP-LOFF BAND — the name reveal
   ========================================================================== */
.apploff-band {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: clamp(4rem, 9vw, 8rem);
  border-top: 1px solid var(--stage-300);
  background: var(--stage-000);
}
.apploff-band::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(58% 100% at 50% 50%, rgba(0, 227, 106, 0.13), transparent 68%);
}
.apploff-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 1.75rem;
}
.apploff-inner .eyebrow { justify-content: center; }

/* The wordmark: APP lights up, LOFF stays quiet */
.apploff-mark {
  font-size: clamp(3.4rem, 15vw, 13rem);
  line-height: 0.82;
  letter-spacing: -0.045em;
  display: flex;
  align-items: baseline;
  justify-content: center;
}
.apploff-mark .app {
  background: var(--grad-hot);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  position: relative;
  /* The tight tracking (-0.045em) lets the second p's bowl poke past the
     span's paint box, and background-clip:text has no gradient out there —
     so the P's right edge rendered clipped (Jeff's catch). The padding
     extends the paint box; the negative margin gives the space back so the
     hyphen doesn't move. */
  padding-right: 0.07em;
  margin-right: -0.07em;
}
/* Soft glow behind APP so it reads as the lit part of the sign */
.apploff-mark .app::after {
  content: '';
  position: absolute;
  inset: -12% -6%;
  z-index: -1;
  background: radial-gradient(50% 60% at 50% 50%, rgba(0, 227, 106, 0.32), transparent 70%);
  filter: blur(26px);
}
.apploff-mark .hyphen {
  color: var(--ink-700);
  margin-inline: 0.04em;
}
.apploff-mark .loff { color: var(--white); }

.apploff-copy { max-width: 64ch; }
.apploff-copy .lede { margin-inline: auto; }
.apploff-copy .body-copy { color: var(--ink-500); }

/* The three App-loff claims. Each is its own line rather than one run-on
   sentence, so the three shows read as three separate proofs of the same point.

   `balance` on the items matters here: the middle claim is roughly twice the
   length of the other two, and left to wrap raw it would strand a word or two
   on its own line and break the set. Balanced, all three read as tidy blocks
   of one or two lines. */
.apploff-lines {
  display: flex;
  flex-direction: column;
  gap: clamp(0.7rem, 1.4vw, 1.1rem);
  font-size: clamp(1.05rem, 1.5vw, 1.32rem);
  line-height: 1.45;
  color: var(--ink-200);
  max-width: 46ch;
  margin-inline: auto;
}

.apploff-lines li {
  text-wrap: balance;
}

.apploff-lines strong {
  color: var(--white);
  font-weight: 700;
}

/* The closing turn. This is the whole point of the band, so it gets its own
   weight and a rule above it to separate it from the three proofs. */
.apploff-turn {
  max-width: 44ch;
  margin: clamp(1.6rem, 3vw, 2.4rem) auto 0;
  padding-top: clamp(1.4rem, 2.6vw, 2rem);
  border-top: 1px solid var(--stage-300);
  font-size: clamp(1.1rem, 1.7vw, 1.45rem);
  line-height: 1.5;
  color: var(--ink-200);
  text-wrap: balance;
}
.apploff-turn strong {
  display: block;
  margin-top: 0.55rem;
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 108%;
  font-size: clamp(1.5rem, 3.4vw, 2.5rem);
  line-height: 1.05;
  letter-spacing: 0.005em;
  text-transform: uppercase;
}
.apploff-turn strong:not(.gradient-text):not(.gold-text) { color: var(--white); }

/* ---------- JAHM Studios page ---------- */
.jahm-hero::before {
  background:
    radial-gradient(60% 120% at 10% 0%, rgba(139, 92, 255, 0.24), transparent 64%),
    radial-gradient(55% 100% at 90% 20%, rgba(139, 92, 255, 0.15), transparent 66%);
}
.jahm-wordmark {
  background: var(--grad-cool);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.jahm-tagline {
  margin-top: 1.6rem;
  color: var(--ink-100);
  letter-spacing: -0.02em;
}
.jahm-why {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: clamp(2rem, 5vw, 5rem);
  align-items: start;
}

/* The name reveal: J-A-H-M lights up inside the founders' names */
.jahm-name {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: clamp(1.75rem, 4vw, 4rem);
  align-items: center;
  padding: clamp(1.75rem, 3.5vw, 2.75rem);
  border: 1px solid var(--stage-300);
  border-radius: var(--radius-lg);
  background: var(--stage-050);
}
.jahm-name .display { line-height: 1.02; }
.jahm-initial {
  background: var(--grad-cool);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Jam Jam teaser */
.jahm-teaser {
  text-align: center;
  padding-block: clamp(2rem, 5vw, 4rem);
  position: relative;
  isolation: isolate;
}
.jahm-teaser::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(50% 90% at 50% 50%, rgba(139, 92, 255, 0.12), transparent 68%);
}
.jahm-teaser h2 {
  background: var(--grad-cool);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.jahm-teaser .lede { margin-inline: auto; }

@media (max-width: 860px) {
  .jahm-name { grid-template-columns: 1fr; gap: 1.5rem; }
}
.jahm-next {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: clamp(2rem, 4vw, 4rem);
  align-items: end;
}
.jahm-next-actions { display: flex; flex-direction: column; gap: 0.9rem; align-items: stretch; }
.jahm-next-actions .btn { justify-content: center; }

@media (max-width: 1080px) {
  .jahm-why, .jahm-next { grid-template-columns: 1fr; }
  .jahm-next-actions { flex-direction: row; flex-wrap: wrap; }
}

/* ==========================================================================
   GET THE APP — QR + store buttons
   ========================================================================== */
.getapp {
  display: flex;
  align-items: center;
  gap: clamp(1.25rem, 2.5vw, 2rem);
  margin-top: 1.9rem;
  padding: clamp(1.1rem, 2vw, 1.5rem);
  border: 1px solid var(--stage-300);
  border-radius: var(--radius-lg);
  background: var(--stage-100);
}
.getapp-qr {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
}
.getapp-qr img {
  width: 128px;
  height: 128px;
  border-radius: 8px;
  background: #fff;
  padding: 7px;
}
.getapp-qr span {
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-500);
}
.getapp-side { flex: 1; min-width: 0; }
.getapp-lead {
  color: var(--ink-300);
  font-size: 0.96rem;
  line-height: 1.55;
  margin-bottom: 1rem;
}
.getapp-lead strong { color: var(--white); font-weight: 600; }

.store-row { display: flex; flex-wrap: wrap; gap: 0.7rem; }
.store-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.62rem 1.1rem;
  border-radius: 9px;
  border: 1px solid var(--stage-400);
  background: var(--stage-000);
  color: var(--white);
  transition: border-color 0.35s var(--ease), background 0.35s var(--ease),
              transform 0.35s var(--ease);
}
.store-btn:hover {
  border-color: var(--white);
  background: var(--stage-200);
  transform: translateY(-2px);
}
.store-btn span {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
  font-size: 0.95rem;
  font-weight: 600;
}
.store-btn small {
  font-size: 0.58rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-500);
}

/* On a phone a QR code is useless — drop it, keep the buttons. */
@media (max-width: 860px) {
  .getapp { flex-direction: column; align-items: stretch; }
  .getapp-qr { display: none; }
}

/* ---------- Party Polls Live ---------- */
/* Party Polls Live — the arena render sits above the copy as a wide band, so
   the primetime scale is the first thing you register (Jeff, Aug 26). */
.pplive-art {
  margin: clamp(2.5rem, 4vw, 3.5rem) 0 0;
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid var(--stage-300);
  line-height: 0;
}
.pplive-art img {
  width: 100%;
  height: auto;
  display: block;
}
.pplive-art + .pplive {
  margin-top: clamp(1.6rem, 2.6vw, 2.2rem);
  padding-top: clamp(1.6rem, 2.6vw, 2.2rem);
}

/* Next out of the studio — a compact card, deliberately not a hero. */
.nextup {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: clamp(1.5rem, 3vw, 3rem);
  align-items: center;
  padding: clamp(1.5rem, 3vw, 2.4rem);
  border: 1px solid var(--stage-300);
  border-radius: 16px;
  background: var(--stage-050);
}
.nextup-body { max-width: 52ch; }
.nextup-mark img {
  width: clamp(96px, 16vw, 148px);
  height: auto;
  display: block;
  filter: drop-shadow(0 10px 26px rgba(0, 0, 0, 0.5));
}
@media (max-width: 760px) {
  .nextup { grid-template-columns: 1fr; text-align: left; }
  .nextup-mark img { width: 104px; }
}

.pplive {
  margin-top: clamp(2.5rem, 4vw, 3.5rem);
  padding-top: clamp(2rem, 3vw, 2.6rem);
  border-top: 1px solid var(--stage-300);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(1.5rem, 3vw, 3rem);
  align-items: center;
}
.pplive h3 {
  background: var(--grad-cool);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.pplive-note {
  color: var(--ink-500);
  font-size: 0.97rem;
  border-left: 2px solid var(--violet);
  padding-left: 1.2rem;
}
@media (max-width: 860px) {
  .pplive { grid-template-columns: 1fr; }
}

/* ---------- Library footer ---------- */
.lib-foot {
  margin-top: clamp(2.5rem, 4vw, 3.5rem);
  padding-top: clamp(2rem, 3vw, 2.5rem);
  border-top: 1px solid var(--stage-300);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
}

/* ==========================================================================
   PRESS
   ========================================================================== */
.quote-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(1rem, 2vw, 1.75rem);
}
.quote-card {
  background: var(--stage-100);
  border: 1px solid var(--stage-300);
  border-radius: var(--radius-lg);
  padding: clamp(1.6rem, 3vw, 2.4rem);
  display: flex;
  flex-direction: column;
  gap: 1.4rem;
  transition: border-color 0.45s var(--ease), transform 0.45s var(--ease),
              background 0.45s var(--ease);
}
.quote-card:hover { border-color: var(--stage-400); transform: translateY(-5px); background: var(--stage-200); }
/* cards are <a> now — inherit ink, never underline, and close each one with
   an explicit "Read the full story" so nobody wonders if it's clickable */
a.quote-card { color: inherit; text-decoration: none; }
.quote-read {
  margin-top: auto;
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--green);
}
/* Show art on the press cards (team note, Sep 17) — OUR key art, never the
   publications' photos (photo-agency bots enforce those automatically; Jeff's
   decision, and it's final). */
.quote-art {
  width: calc(100% + 2 * clamp(1.6rem, 3vw, 2.4rem));
  margin: calc(-1 * clamp(1.6rem, 3vw, 2.4rem)) calc(-1 * clamp(1.6rem, 3vw, 2.4rem)) 0;
  max-width: none;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  display: block;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}

.quote-mark {
  font-family: var(--font-display);
  font-size: 3.2rem;
  line-height: 0.6;
  background: var(--grad-hot);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.quote-card blockquote {
  margin: 0;
  font-size: clamp(1.02rem, 1.35vw, 1.22rem);
  line-height: 1.5;
  color: var(--ink-100);
  font-weight: 500;
  flex: 1;
}
.quote-src {
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-500);
  padding-top: 1.2rem;
  border-top: 1px solid var(--stage-300);
}
.quote-src strong { color: var(--white); display: block; margin-bottom: 0.3rem; letter-spacing: 0.16em; }

/* Press archive rows */
.press-list { border-top: 1px solid var(--stage-300); }
.press-row {
  display: grid;
  grid-template-columns: 190px 1fr auto;
  gap: 1.5rem;
  align-items: center;
  padding: 1.45rem 0.4rem;
  border-bottom: 1px solid var(--stage-300);
  transition: background 0.4s var(--ease), padding-inline 0.4s var(--ease);
}
.press-row:hover { background: var(--stage-100); padding-inline: 1.1rem 0.9rem; }
.press-outlet {
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink-500);
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}
.press-outlet strong { color: var(--green-hot); letter-spacing: 0.15em; }
/* These are real press headlines, so their length is not negotiable — they run
   from about 40 to 150 characters with a median of 87. They are marked up as
   <span>, which means they were missing out on the `p, li { text-wrap: pretty }`
   baseline and wrapping raw. Across 34 stacked rows that produced a lot of
   one-word last lines.

   `balance` rather than `pretty` because these behave like headings: short,
   emphatic, and read as a block. */
.press-title {
  font-size: clamp(0.98rem, 1.25vw, 1.15rem);
  font-weight: 500;
  line-height: 1.4;
  color: var(--ink-100);
  text-wrap: balance;
  transition: color 0.3s var(--ease);
}
.press-row:hover .press-title { color: var(--white); }
.press-go {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--ink-700);
  transition: color 0.35s var(--ease), transform 0.35s var(--ease);
  flex: none;
}
.press-row:hover .press-go { color: var(--green); transform: translate(3px, -3px); }

/* ==========================================================================
   PARTNER MARQUEE
   ========================================================================== */
/* ==========================================================================
   PARTNER WALL — two counter-scrolling rows (form three; history in the HTML)

   The scroll is back by Jeff's call, but split in two so nothing hides: nine
   logos per row means everything is on screen about half the time, against a
   sixteenth of it in the single-belt version. The rows travel in opposite
   directions; hovering either row pauses both, because you pause to read.

   app.js doubles each track's content, so travelling exactly -50% brings the
   second copy to where the first began: a seamless infinite loop. If the
   rows ever freeze, check the scrollX keyframe exists FIRST — it was once
   destroyed in a section rewrite and the wall sat dead for days.
   ========================================================================== */
.wrap-wide { max-width: 1500px; margin-inline: auto; }
.marquee {
  overflow: hidden;
  position: relative;
  padding-block: 0.6rem;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 9%, #000 91%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 9%, #000 91%, transparent);
}
.marquee + .marquee { margin-top: clamp(0.8rem, 2vw, 1.6rem); }
.marquee-track {
  display: flex;
  gap: clamp(2.5rem, 5vw, 5rem);
  width: max-content;
  animation: scrollX 38s linear infinite;
  align-items: center;
}
.marquee-rev .marquee-track { animation-direction: reverse; }
.marquee:hover .marquee-track,
.marquee:hover ~ .marquee .marquee-track { animation-play-state: paused; }
.wrap-wide:hover .marquee-track { animation-play-state: paused; }
@keyframes scrollX {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .marquee-track { animation: none; flex-wrap: wrap; width: auto; justify-content: center; }
}
.marquee-track a {
  flex: none;
  display: grid;
  place-items: center;
  padding: 0.5rem 0;
  transition: transform 0.4s var(--ease);
}
.marquee-track a:hover { transform: translateY(-3px) scale(1.08); }
.marquee-track img {
  /* Optical sizing: cap BOTH dimensions so a tall mark and a wide wordmark
     carry the same visual weight rather than the same bounding box. */
  max-height: clamp(26px, 3.1vw, 38px);
  max-width: clamp(96px, 11vw, 150px);
  width: auto;
  height: auto;
  object-fit: contain;
  /* NO FILTER, deliberately: the files are purpose-built for a black
     background. Full opacity — Bunim Murray's navy and Lionsgate's dark blue
     measure only ~3:1 against the page black even at full strength. */
}
/* Near-square marks read ~a third the area of a wordmark at the same height
   cap, so they get a taller one: ABC, Apple, Hungry McBear, Warner. */
.marquee-track img[data-shape="square"] {
  max-height: clamp(38px, 4.4vw, 54px);
}

/* Jeff's note: the logo you're pointing at should come forward. The whole
   track already pauses on hover (rule above), so the grow reads as picking
   one out of the parade rather than fighting the motion. */

/* ==========================================================================
   SPLIT CTA
   ========================================================================== */
.split-cta {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--stage-300);
  border: 1px solid var(--stage-300);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.cta-panel {
  background: var(--stage-050);
  padding: clamp(2rem, 3.6vw, 3.2rem);
  display: flex;
  flex-direction: column;
  gap: 1rem;
  position: relative;
  isolation: isolate;
  transition: background 0.5s var(--ease);
  min-height: 290px;
}
.cta-panel::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0;
  transition: opacity 0.55s var(--ease);
}
.cta-panel:nth-child(1)::before { background: radial-gradient(90% 110% at 0% 100%, rgba(0, 227, 106, 0.20), transparent 70%); }
.cta-panel:nth-child(2)::before { background: radial-gradient(90% 110% at 0% 100%, rgba(139, 92, 255, 0.18), transparent 70%); }
.cta-panel:nth-child(3)::before { background: radial-gradient(90% 110% at 0% 100%, rgba(255,200,61,0.18), transparent 70%); }
.cta-panel:hover { background: var(--stage-100); }
.cta-panel:hover::before { opacity: 1; }
.cta-panel h3 { margin-bottom: 0.2rem; }
.cta-panel p { color: var(--ink-300); font-size: 0.94rem; line-height: 1.6; flex: 1; }
.cta-panel .tlink { align-self: flex-start; }

/* ==========================================================================
   PAGE HERO (interior pages)
   ========================================================================== */
.page-hero {
  padding-top: clamp(9rem, 16vw, 13rem);
  padding-bottom: clamp(2.5rem, 5vw, 4.5rem);
  position: relative;
  isolation: isolate;
  border-bottom: 1px solid var(--stage-300);
}
.page-hero::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(65% 130% at 12% 0%, rgba(0, 227, 106, 0.15), transparent 62%),
              radial-gradient(50% 100% at 88% 10%, rgba(139, 92, 255, 0.10), transparent 65%);
}
.page-hero .eyebrow { margin-bottom: 1.3rem; }
.page-hero h1 { margin-bottom: 1.4rem; }

/* ==========================================================================
   TEAM
   ========================================================================== */
.team-list { display: flex; flex-direction: column; gap: clamp(3rem, 6vw, 5.5rem); }
.team-item {
  display: grid;
  grid-template-columns: 340px 1fr;
  gap: clamp(2rem, 4.5vw, 4rem);
  align-items: start;
}
.team-photo {
  border-radius: var(--radius-lg);
  overflow: hidden;
  aspect-ratio: 4 / 5;
  background: var(--stage-200);
  border: 1px solid var(--stage-300);
  position: relative;
}
.team-photo img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center top;
  filter: grayscale(1) contrast(1.03);
  transition: filter 0.6s var(--ease), transform 1.1s var(--ease);
}
.team-item:hover .team-photo img { filter: grayscale(0); transform: scale(1.04); }
.team-role {
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--green-hot);
  margin-bottom: 0.6rem;
}
.team-item h2 { margin-bottom: 1.4rem; }

/* ==========================================================================
   FORMS
   ========================================================================== */
.form-layout {
  display: grid;
  grid-template-columns: 1fr 1.25fr;
  gap: clamp(2.5rem, 6vw, 6rem);
  align-items: start;
}
.form-aside { position: sticky; top: 7rem; }
.form-aside .body-copy { margin-bottom: 2rem; }
.info-list { display: flex; flex-direction: column; gap: 1.5rem; }
.info-item { padding-top: 1.3rem; border-top: 1px solid var(--stage-300); }
.info-item dt {
  font-size: 0.65rem;
  font-weight: 800;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--ink-500);
  margin-bottom: 0.45rem;
}
.info-item dd { margin: 0; font-size: 1rem; color: var(--ink-100); }
.info-item dd a:hover { color: var(--green-hot); }

.form { display: flex; flex-direction: column; gap: 1.35rem; }
.field { display: flex; flex-direction: column; gap: 0.55rem; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1.35rem; }
.field label {
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink-300);
}
.field label .req { color: var(--green); }
.field input,
.field select,
.field textarea {
  width: 100%;
  background: var(--stage-100);
  border: 1px solid var(--stage-300);
  border-radius: var(--radius);
  padding: 0.95rem 1.05rem;
  color: var(--white);
  font-family: var(--font-body);
  font-size: 0.97rem;
  transition: border-color 0.3s var(--ease), background 0.3s var(--ease),
              box-shadow 0.3s var(--ease);
}
.field textarea { resize: vertical; min-height: 150px; line-height: 1.6; }
.field select { appearance: none; cursor: pointer; padding-right: 2.6rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9' fill='none'%3E%3Cpath d='M1 1L7 7L13 1' stroke='%2383839A' stroke-width='2'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1.05rem center;
}
.field input::placeholder, .field textarea::placeholder { color: var(--ink-700); }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-color: var(--green);
  background: var(--stage-200);
  box-shadow: 0 0 0 3px rgba(0, 227, 106, 0.14);
}
.form-note { font-size: 0.82rem; color: var(--ink-500); line-height: 1.6; }
.form-note a { color: var(--ink-300); text-decoration: underline; text-underline-offset: 3px; }
.form .btn { align-self: flex-start; }

.form-status {
  padding: 1rem 1.2rem;
  border-radius: var(--radius);
  font-size: 0.9rem;
  display: none;
}
.form-status.show { display: block; }
.form-status.ok { background: rgba(182,255,61,0.10); border: 1px solid rgba(182,255,61,0.35); color: var(--lime); }
.form-status.err { background: rgba(0, 227, 106, 0.10); border: 1px solid rgba(0, 227, 106, 0.35); color: var(--green-hot); }

/* ==========================================================================
   CASTING
   ========================================================================== */
.cast-strip {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(1rem, 2vw, 1.6rem);
}
.cast-card {
  border: 1px solid var(--stage-300);
  border-radius: var(--radius-lg);
  padding: clamp(1.5rem, 3vw, 2.2rem);
  background: var(--stage-050);
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}
.cast-card .num {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 2rem;
  line-height: 1;
  background: var(--grad-hot);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.cast-card h3 { font-size: 1.05rem; font-weight: 700; color: var(--white); }
.cast-card p { font-size: 0.92rem; color: var(--ink-300); line-height: 1.6; }

/* ==========================================================================
   FOOTER
   ========================================================================== */
.footer {
  border-top: 1px solid var(--stage-300);
  padding-top: clamp(3.5rem, 7vw, 6rem);
  padding-bottom: 2.5rem;
  background: var(--stage-050);
  position: relative;
  isolation: isolate;
}
.footer::before {
  content: '';
  position: absolute; inset: 0; z-index: -1;
  background: radial-gradient(60% 120% at 50% 100%, rgba(0, 227, 106, 0.09), transparent 70%);
}
.footer-top {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: clamp(2rem, 4vw, 3.5rem);
  padding-bottom: clamp(3rem, 5vw, 4.5rem);
}
.footer-brand img { height: 40px; width: auto; margin-bottom: 1.4rem; }
.footer-brand p { color: var(--ink-500); font-size: 0.92rem; line-height: 1.65; max-width: 34ch; }
.footer-col h4 {
  font-size: 0.65rem;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-700);
  margin-bottom: 1.2rem;
}
.footer-col ul { display: flex; flex-direction: column; gap: 0.7rem; }
.footer-col a { font-size: 0.93rem; color: var(--ink-300); transition: color 0.3s var(--ease); }
.footer-col a:hover { color: var(--green-hot); }
.footer-bottom {
  border-top: 1px solid var(--stage-300);
  padding-top: 1.8rem;
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  align-items: center;
  justify-content: space-between;
  font-size: 0.79rem;
  color: var(--ink-700);
}
.footer-bottom nav { display: flex; gap: 1.6rem; flex-wrap: wrap; }
.footer-bottom a:hover { color: var(--ink-300); }
.social { display: flex; gap: 0.7rem; }
.social a {
  width: 38px; height: 38px;
  border-radius: 50%;
  border: 1px solid var(--stage-400);
  display: grid;
  place-items: center;
  color: var(--ink-300);
  transition: background 0.35s var(--ease), color 0.35s var(--ease),
              border-color 0.35s var(--ease), transform 0.35s var(--ease);
}
.social a:hover { background: var(--white); color: var(--stage-000); border-color: var(--white); transform: translateY(-3px); }

/* ==========================================================================
   SCROLL REVEAL
   ========================================================================== */
/* ---- Numbers landing beat (guru pass, Aug 21) ----
   The counter overshoots a hair and settles when it lands; the label rises in
   a beat later. JS adds .landed to the number and .done to the .stat. */
.stat-num { display: inline-block; }
@keyframes statLand { 0% { transform: scale(1); } 55% { transform: scale(1.05); } 100% { transform: scale(1); } }
.stat-num.landed { animation: statLand 0.5s var(--ease); }
/* Labels show WITH the counters, not after (Jeff, Aug 22): a climbing
   number without its unit is a mystery, and mysteries need payoffs.
   "8,500 episodes" climbing together is the impressive version. The
   number's settle-pop (.landed) stays. */

/* ---- The timeline draws itself (guru pass, Aug 21) ----
   As each entry scrolls into view (.lit via JS), its rail segment draws down
   in green and the dot ignites. The story literally draws its own line. */
.first-rail::after {
  content: '';
  position: absolute;
  top: 22px;
  bottom: -1px;
  width: 2px;
  background: var(--green);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.95s var(--ease) 0.12s;
}
.first-item.lit .first-rail::after { transform: scaleY(1); }
.first-dot { transition: border-color 0.4s var(--ease), box-shadow 0.4s var(--ease); }
.first-item.lit .first-dot {
  border-color: var(--green);
  box-shadow: 0 0 0 6px rgba(0, 227, 106, 0.14);
}
.first-year { transition: color 0.4s var(--ease); }
.first-item.lit .first-year { color: var(--green-hot); }

/* ---- Talent wall cascades in like credits (guru pass, Aug 21) ---- */
.talent-wall.reveal li {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.55s var(--ease), transform 0.55s var(--ease);
}
.talent-wall.reveal.in li { opacity: 1; transform: none; }
.talent-wall.reveal.in li:nth-child(1) { transition-delay: 0.04s; }
.talent-wall.reveal.in li:nth-child(2) { transition-delay: 0.07s; }
.talent-wall.reveal.in li:nth-child(3) { transition-delay: 0.11s; }
.talent-wall.reveal.in li:nth-child(4) { transition-delay: 0.14s; }
.talent-wall.reveal.in li:nth-child(5) { transition-delay: 0.18s; }
.talent-wall.reveal.in li:nth-child(6) { transition-delay: 0.21s; }
.talent-wall.reveal.in li:nth-child(7) { transition-delay: 0.25s; }
.talent-wall.reveal.in li:nth-child(8) { transition-delay: 0.28s; }
.talent-wall.reveal.in li:nth-child(9) { transition-delay: 0.32s; }
.talent-wall.reveal.in li:nth-child(10) { transition-delay: 0.35s; }
.talent-wall.reveal.in li:nth-child(11) { transition-delay: 0.39s; }
.talent-wall.reveal.in li:nth-child(12) { transition-delay: 0.42s; }
.talent-wall.reveal.in li:nth-child(13) { transition-delay: 0.46s; }
.talent-wall.reveal.in li:nth-child(14) { transition-delay: 0.49s; }
.talent-wall.reveal.in li:nth-child(15) { transition-delay: 0.53s; }
.talent-wall.reveal.in li:nth-child(16) { transition-delay: 0.56s; }
.talent-wall.reveal.in li:nth-child(17) { transition-delay: 0.60s; }
.talent-wall.reveal.in li:nth-child(18) { transition-delay: 0.63s; }
.talent-wall.reveal.in li:nth-child(19) { transition-delay: 0.67s; }
.talent-wall.reveal.in li:nth-child(20) { transition-delay: 0.70s; }

/* ---- The Vault deals its cards (guru pass, Aug 21) ---- */
.lib-card.reveal { transform: translateY(30px) rotate(1.4deg) scale(0.985); }
.lib-card.reveal.in { transform: none; }
.lib-grid .lib-card:nth-child(1) { transition-delay: 0.06s; }
.lib-grid .lib-card:nth-child(2) { transition-delay: 0.12s; }
.lib-grid .lib-card:nth-child(3) { transition-delay: 0.18s; }
.lib-grid .lib-card:nth-child(4) { transition-delay: 0.24s; }
.lib-grid .lib-card:nth-child(5) { transition-delay: 0.30s; }
.lib-grid .lib-card:nth-child(6) { transition-delay: 0.36s; }
.lib-grid .lib-card:nth-child(7) { transition-delay: 0.42s; }
.lib-grid .lib-card:nth-child(8) { transition-delay: 0.48s; }

.reveal {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity 0.85s var(--ease), transform 0.85s var(--ease);
}
.reveal.in { opacity: 1; transform: none; }
.reveal-d1 { transition-delay: 0.09s; }
.reveal-d2 { transition-delay: 0.18s; }
.reveal-d3 { transition-delay: 0.27s; }
.reveal-d4 { transition-delay: 0.36s; }

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */
@media (max-width: 1080px) {
  .nav, .header-cta .btn { display: none; }
  .burger { display: flex; }
  /* 2x2 keeps the symmetry — never three-and-one */
  .numbers-grid { grid-template-columns: repeat(2, 1fr); row-gap: 3rem; }
  .stat:nth-child(odd) { border-left: 0; }
  .quote-grid { grid-template-columns: 1fr; }
  .split-cta { grid-template-columns: 1fr; }
  .cta-panel { min-height: auto; }
  .footer-top { grid-template-columns: 1fr 1fr; }
  .footer-brand { grid-column: 1 / -1; }
  .form-layout { grid-template-columns: 1fr; }
  .form-aside { position: static; }
  .cast-strip { grid-template-columns: 1fr; }
  .jahm-inner { grid-template-columns: 1fr; }
  .jahm-card { max-width: 520px; }
}

@media (max-width: 860px) {
  .slate-item { grid-template-columns: 1fr; gap: 1.75rem; }
  .slate-item:nth-child(even) .slate-art { order: 0; }
  .team-item { grid-template-columns: 1fr; gap: 1.5rem; }
  .team-photo { max-width: 300px; aspect-ratio: 1; }
  .press-row { grid-template-columns: 1fr auto; gap: 0.6rem 1rem; }
  .press-outlet { grid-column: 1 / -1; flex-direction: row; gap: 0.7rem; }
  .field-row { grid-template-columns: 1fr; }
  .scroll-hint { display: none; }
  .hero-media iframe, .hero-media video { min-width: 240svh; }   /* crop harder on portrait */
}

@media (max-width: 560px) {
  .numbers-grid { grid-template-columns: 1fr; gap: 2.5rem; }
  .stat { border-left: 0; padding-inline: 0; }
  .stat-label { max-width: none; }
  .lib-grid { grid-template-columns: 1fr; }
  /* Full-width single column (Jeff's portrait catch, round 2): forcing ANY
     fixed frame crops someone's key art — the shapes vary show to show. On
     phones the card now takes the image's own natural shape. Nothing is
     ever cropped. */
  .lib-card img { aspect-ratio: auto; height: auto; }
  /* The 2.4rem desktop column-gap stranded short names (Rob Lowe, Sheila E.)
     visually far from their neighbours on a 390px screen (Jeff's catch).
     Tighter gaps, slightly smaller names — the wall reads as one block. */
  .talent-wall { gap: 0.4rem 1.1rem; }
  .talent-wall li { font-size: clamp(1.15rem, 5.4vw, 1.6rem); }
  .footer-top { grid-template-columns: 1fr; }
  .footer-bottom { flex-direction: column; align-items: flex-start; }
  .btn { padding: 0.9rem 1.5rem; }
}

/* ---------- Accessibility ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .reveal { opacity: 1; transform: none; }
  .talent-wall.reveal li { opacity: 1; transform: none; }
  .lib-card.reveal { transform: none; }
  .first-rail::after { transition: none; }
  .hero h1 .line > span { transform: none; }
  .hero-sub, .hero-actions, .hero-flag, .scroll-hint { opacity: 1; }
  /* No opening title card when motion is reduced — it would just sit there. */
  .hero-intro { display: none; }
  /* Belt and braces: if the card is ever made visible under reduced motion,
     the masked words must not stay parked below their masks. */
  .bw { transform: none; opacity: 1; animation: none; }
  .hero-intro-stage { opacity: 1; transform: none; filter: none; animation: none; }
}

@media print {
  .header, .footer, .hero-media, .logo-wall { display: none; }
  body { background: #fff; color: #000; }
}

/* ==========================================================================
   ADDITIONS — contact.html & casting.html
   Appended 2026. Everything above this line is untouched.
   ========================================================================== */

/* Two-panel variant of the three-up split CTA (contact.html) */
.split-cta.split-cta-2 { grid-template-columns: repeat(2, 1fr); }

/* Casting hero — row of "now casting" badges */
.cast-flags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.55rem;
  margin-top: 1.9rem;
}

/* Casting advice — two-column copy block, mirrors .jahm-why proportions */
.cast-advice {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: clamp(2rem, 5vw, 5rem);
  align-items: start;
}

/* Advice list with magenta markers (the global reset strips list styles) */
.tick-list { display: flex; flex-direction: column; gap: 1.15rem; }
.tick-list li { position: relative; padding-left: 1.7rem; }
.tick-list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 9px;
  height: 2px;
  background: var(--green);
}

/* Casting closing block — play Party Polls now */
.cast-play {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: clamp(2rem, 4vw, 4rem);
  align-items: end;
}
.cast-play-actions { display: flex; flex-direction: column; gap: 0.9rem; align-items: stretch; }
.cast-play-actions .btn { justify-content: center; }

@media (max-width: 1080px) {
  .split-cta.split-cta-2 { grid-template-columns: 1fr; }
  .cast-advice, .cast-play { grid-template-columns: 1fr; }
  .cast-play-actions { flex-direction: row; flex-wrap: wrap; }
}

/* ==========================================================================
   PULL QUOTE — an outside voice

   Built for the Howie Mandel quote (Aug 26), designed to be reusable as the
   others land. Deliberately restrained: no card, no border box, no quotation
   graphic the size of a house. A rule above, big light type, and the name.
   The quote should feel like it was said, not like it was designed.

   No filter and no text-shadow anywhere near this type — standing rule of the
   whole stylesheet, because a filter on clipped or gradient text draws the
   square halo.
   ========================================================================== */
/* Two or more quotes ride side by side; each keeps the .pullquote treatment
   but the shared rule and centering move to the row. Type steps down a size —
   two voices at solo scale would shout at each other. */
.quote-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 4vw, 4rem);
  margin: clamp(2.8rem, 5vw, 4.5rem) auto 0;
  padding-top: clamp(1.8rem, 3vw, 2.6rem);
  border-top: 1px solid var(--stage-300);
  max-width: 100ch;
}
.quote-row .pullquote { margin: 0; padding-top: 0; border-top: 0; max-width: none; }
.quote-row .pullquote blockquote { font-size: clamp(1.15rem, 1.9vw, 1.55rem); }
@media (max-width: 860px) {
  .quote-row { grid-template-columns: 1fr; gap: 2.4rem; }
}

.pullquote {
  margin: clamp(2.8rem, 5vw, 4.5rem) auto 0;
  max-width: 46ch;
  padding-top: clamp(1.8rem, 3vw, 2.6rem);
  border-top: 1px solid var(--stage-300);
  text-align: center;
}
.pullquote blockquote {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-stretch: 104%;
  font-size: clamp(1.3rem, 2.6vw, 2.05rem);
  line-height: 1.28;
  letter-spacing: -0.01em;
  color: var(--ink-100);
  text-wrap: balance;
}
/* Hanging opening quote mark: sits in the margin so the first word still
   lines up with the block, which is the whole point of hanging punctuation. */
.pullquote blockquote::before {
  content: '\201C';
  color: var(--green);
  margin-right: 0.06em;
  margin-left: -0.42em;
}
.pullquote blockquote::after {
  content: '\201D';
  color: var(--green);
  margin-left: 0.04em;
}
.pullquote figcaption {
  margin-top: clamp(1.1rem, 2vw, 1.6rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
}
.pq-name {
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--white);
}
.pq-role {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--ink-600);
}
@media (max-width: 560px) {
  .pullquote { max-width: 100%; }
  .pullquote blockquote::before { margin-left: 0; }
}

/* ==========================================================================
   NETWORK STRIP — DORMANT (Jeff, Aug 26)
   Built, then pulled. Jeff's read: the page already establishes the networks
   four other ways (the status line on every timeline entry, the captions, the
   Vault badges, the partners row), so this was the fifth telling of something
   the timeline tells better. It also landed straight after the hero reel,
   which meant following the most cinematic moment on the site with a row of
   small dimmed logos — awe, then reassurance, which reads as a let-down.
   Left in the stylesheet so restoring it is one <section> in the HTML.

   Original note: the credit line under the hero
   Quiet on purpose. Logos sit at low opacity and come up on hover, so the row
   reads as a fact about the company rather than a wall of advertising.
   ========================================================================== */
.netstrip {
  padding: clamp(1.6rem, 3vw, 2.4rem) 0;
  border-bottom: 1px solid var(--stage-300);
}
.netstrip-label {
  margin: 0 0 1.1rem;
  text-align: center;
  font-size: 0.64rem;
  font-weight: 800;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-600);
}
.netstrip-row {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: clamp(1.6rem, 4vw, 3.4rem);
}
.netstrip-row img {
  height: clamp(15px, 2.1vw, 22px);
  width: auto;
  display: block;
  opacity: 0.5;
  transition: opacity 0.35s var(--ease);
}
.netstrip-row li:hover img { opacity: 1; }
/* ABC and Syfy are raster and read heavier than the SVG marks at the same
   height, so they get trimmed back to match optically. */
.netstrip-row img[alt="ABC"] { height: clamp(13px, 1.85vw, 19px); }
@media (max-width: 560px) {
  .netstrip-row { gap: 1.3rem 1.7rem; }
}

/* Timeline motion (Aug 26). A silent loop stands in for the still on entries
   where we have footage; it is styled identically so a mixed timeline of
   stills and clips reads as one set. */
.first-media .fm-loop {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  border-radius: 12px;
  border: 1px solid var(--stage-300);
  display: block;
  background: #000;
}

/* Vault cards lift slightly on hover, so it is obvious they open. */
.lib-card {
  transition: transform 0.4s var(--ease), border-color 0.4s var(--ease);
}
@media (hover: hover) {
  .lib-card:hover { transform: translateY(-4px); }
}

/* ==========================================================================
   AUG 26 LATE BATCH — QR hero card, international route map, execution photo
   ========================================================================== */

/* --- JAHM hero: text left, get-the-app card right (Jeff: the right half was
       "practically the only space in the whole website that's just
       completely black"). --- */
.jahm-hero-grid {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: clamp(2rem, 5vw, 5rem);
  align-items: center;
}
.qr-card {
  border: 1px solid var(--stage-300);
  border-radius: 18px;
  background: var(--stage-050);
  padding: clamp(1.4rem, 2.4vw, 2rem);
  text-align: center;
  max-width: 300px;
}
.qr-card-head {
  margin: 0 0 1rem;
  font-size: 0.95rem;
  color: var(--ink-200);
}
.qr-card-head strong { color: var(--white); }
/* The QR sits on a white plate because scanners want dark-on-light with a
   quiet zone; the site black around it is not negotiable, so the plate is. */
.qr-card-code {
  display: inline-block;
  background: #fff;
  border-radius: 12px;
  padding: 10px;
  line-height: 0;
}
.qr-card-code img { width: 164px; height: 164px; display: block; }
.qr-card-hint {
  margin: 0.9rem 0 1.1rem;
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--ink-500);
}
.qr-card .store-row { justify-content: center; }
@media (max-width: 900px) {
  .jahm-hero-grid { grid-template-columns: 1fr; }
  .qr-card { max-width: 420px; }
  /* A QR is useless on the device it points at — phones get the buttons. */
  .qr-card-code, .qr-card-hint { display: none; }
}

/* --- International route map. Labels are SVG <text>; they style from here
       so the map inherits the site's type without inline attributes. --- */
.intl-map { margin: 2rem 0 0; }
.intl-map svg { width: 100%; height: auto; display: block; }
.im-label {
  fill: var(--ink-300);
  font-family: var(--font-body, inherit);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.16em;
}
.im-label.im-home { fill: var(--gold, #FFC83D); }

/* --- Execution: the floor photo. Portrait, so it takes a narrow right
       column and runs beside both the head and the body copy. --- */
.exec .wrap {
  display: grid;
  grid-template-columns: 1.15fr minmax(260px, 400px);
  /* row-gap and column-gap split on purpose (Jeff, Sep 4): the wide gap is
     for the photo column; between the stacked paragraphs it must match the
     1.4rem paragraph rhythm or P1->P2 yawns wider than P2->P3. */
  gap: 1.4rem clamp(2rem, 4.5vw, 4.5rem);
  align-items: start;
}
.exec .section-head { grid-column: 1; }
.exec .exec-body { grid-column: 1; }
.exec .exec-photo {
  grid-column: 2;
  grid-row: 1 / span 2;
  margin: 0;
}
.exec-photo img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: 14px;
  border: 1px solid var(--stage-300);
}
.exec-photo figcaption {
  margin-top: 0.8rem;
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  color: var(--ink-500);
}
.exec-photo figcaption em { color: var(--ink-300); font-style: italic; }
@media (max-width: 900px) {
  .exec .wrap { grid-template-columns: 1fr; }
  .exec .exec-photo { grid-column: 1; grid-row: auto; max-width: 440px; }
}

.press-row:hover .press-go { color: var(--green); }
@media (max-width: 700px) {
  .press-go { font-size: 0; gap: 0; }   /* words hide on phones; arrow stays */
  .press-go svg { width: 15px; height: 15px; }
}

/* Execution's buyer quote — compact, left-aligned, sits above the CTA */
.exec-quote {
  margin: 1.8rem 0 1.6rem;
  padding-left: 1.2rem;
  border-left: 3px solid var(--green);
  max-width: 46ch;
}
.exec-quote blockquote {
  margin: 0 0 0.7rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-stretch: 104%;
  font-size: clamp(1.15rem, 1.9vw, 1.5rem);
  line-height: 1.35;
  color: var(--ink-100);
  text-wrap: balance;
}
.exec-quote figcaption { display: flex; flex-direction: column; gap: 0.25rem; }

/* Party Polls title card on the casting page (team note, Sep 17). */
.cast-play-art {
  display: block;
  max-width: 560px;
  margin: 1.6rem 0;
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid var(--stage-300);
  line-height: 0;
  transition: transform 0.4s var(--ease), border-color 0.4s var(--ease);
}
.cast-play-art:hover { transform: translateY(-4px); border-color: var(--green); }
.cast-play-art img { width: 100%; height: auto; display: block; }

/* Casting: the contestants grid (team note, Sep 17; photos Oct 8). Mixed
   aspect ratios on purpose — a uniform crop would make real moments look
   like stock. Two tall portraits anchor the corners on desktop. */
.greats-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(0.8rem, 1.6vw, 1.2rem);
}
.greats-grid img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 12px;
  border: 1px solid var(--stage-300);
  display: block;
  aspect-ratio: 3 / 2;
}
.greats-grid img:nth-child(3),
.greats-grid img:nth-child(5) {
  grid-row: span 2;
  aspect-ratio: auto;
}
@media (max-width: 760px) {
  .greats-grid { grid-template-columns: repeat(2, 1fr); }
  .greats-grid img:nth-child(3),
  .greats-grid img:nth-child(5) { grid-row: auto; aspect-ratio: 3 / 2; }
}

/* Party Polls demo: the reveal pan (team note 5, timing from the real app's
   screen recording). While the crowd bar hunts, the verdict lines hold their
   breath; when it lands, a ring flash marks the answer and the text drops. */
.pn-held { opacity: 0; transform: translateY(6px); }
.pn-verdict, .pn-crowd-read, .pn-gap {
  transition: opacity 0.45s var(--ease), transform 0.45s var(--ease);
}
.pn-fill.pn-landed { animation: pnLand 0.7s var(--ease); }
@keyframes pnLand {
  0%   { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.55); }
  100% { box-shadow: 0 0 0 14px rgba(255, 255, 255, 0); }
}
