/**
 * Ballpit Countdown template styles.
 * Ported from the Next.js/Payload source (index.scss), same class names
 * (BEM under `.ballpit-countdown`), same responsive tiers. SCSS nesting
 * flattened to plain CSS + custom properties for the one dynamic value
 * (highlight color).
 */

body.page-template-ballpit-countdown-php {
  padding: 0 !important;
}

@font-face {
  font-family: 'LonlyBop';
  src: url('../fonts-ballpit-countdown/LonlyBop-Normal.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'LonlyBopCondensed';
  src: url('../fonts-ballpit-countdown/LonlyBopCondensed-Light.ttf') format('truetype');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}

.ballpit-countdown {
  position: relative;
  overflow: hidden;
  height: 100vh;
  height: 100dvh;
  width: 100%;

  /* WP's admin bar pushes the whole page down via `margin-top` on <html>
     (32px desktop / 46px on its own mobile breakpoint) without shrinking
     the viewport itself, so `100vh`/`100dvh` alone runs exactly that much
     past the visible fold for a logged-in viewer — invisible to a logged
     -out visitor or an automated screenshot (neither carries the admin
     bar), which is why this only ever showed up for a logged-in admin. */
  body.admin-bar & {
    height: calc(100vh - 32px);
    height: calc(100dvh - 32px);
  }

  @media screen and (max-width: 782px) {
    body.admin-bar & {
      height: calc(100vh - 46px);
      height: calc(100dvh - 46px);
    }
  }

  cursor: default;
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
  /* The theme's own global typography sets `line-height` in an absolute
     unit (px/em) on `body`/`p` — that computes to a fixed pixel value which
     descendants inherit verbatim regardless of their own font-size (unlike
     a unitless line-height, which each element recalculates against its own
     font-size). Every heading/label in here is many times the theme's body
     font-size, so that inherited fixed line-height squashed a 128px heading
     into a ~26px line box, throwing off the highlight underline's position
     and any vertical centering. `normal` resets the inheritance chain so
     everything below computes its own line-height off its own font-size. */
  line-height: normal;

  .ballpit-countdown__bg,
  .ballpit-countdown__dot-field-layer {
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
  }

  .ballpit-countdown__dot-field {
    display: block;
    width: 100%;
    height: 100%;
  }

  /* Hidden preview-only control. Remove this display rule in DevTools to
     expose the button without changing the public countdown experience. */
  .ballpit-countdown__landing-preview {
    display: none;
    position: fixed;
    left: 0.75rem;
    bottom: 0.75rem;
    z-index: 1000;
    padding: 0.45rem 0.7rem;
    border: 0;
    border-radius: 999px;
    background: #fc322a;
    color: #fff;
    font: 600 0.75rem/1.2 'Manrope', sans-serif;
    cursor: pointer;
  }

  .ballpit-countdown__reveal-char {
    white-space: pre;
  }

  .ballpit-countdown__content {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    gap: clamp(1rem, 4.9vw, 1.5rem);
    max-width: 100%;
    height: 100%;
    margin: 0 auto;
  }

  @media (min-width: 576px) and (max-width: 1024px) {
    .ballpit-countdown__content {
      gap: clamp(1rem, 3vw, 2rem);
    }
  }

  .ballpit-countdown__lang-toggle {
    position: absolute;
    top: clamp(0.75rem, 3vw, 2rem);
    left: clamp(0.75rem, 3vw, 2rem);
    z-index: 6;
    display: flex;
    gap: clamp(0.15rem, 0.5vw, 0.25rem);
    background: rgba(246, 241, 228, 0.9);
    border-radius: 999px;
    padding: clamp(0.2rem, 0.5vw, 0.25rem);
    box-shadow: 0 4px 0 rgba(0, 0, 0, 0.12);
  }

  .ballpit-countdown__lang-btn {
    font-family: 'Manrope', sans-serif;
    font-weight: 700;
    font-size: clamp(0.65rem, 1.8vw, 0.8rem);
    letter-spacing: 0.02em;
    border: none;
    background: transparent;
    color: #2c2620;
    padding: clamp(0.3rem, 1vw, 0.4rem) clamp(0.55rem, 2vw, 0.9rem);
    border-radius: 999px;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
    white-space: nowrap;
  }

  .ballpit-countdown__lang-btn[aria-pressed="true"] {
    background: var(--bpc-highlight-color, #fc322a);
    color: #fafafa;
  }

  /* Bilingual content: every translatable piece of copy renders both
     `[data-bpc-lang="vi"]` and `[data-bpc-lang="en"]` versions server-side
     (arc/wave-char text is split per-character at render time, so swapping
     `textContent` on the fly would desync those spans) — only one of the pair
     is shown at a time, toggled by the JS-driven attribute below. */
  &[data-bpc-lang-active="vi"] [data-bpc-lang="en"] {
    display: none;
  }

  &[data-bpc-lang-active="en"] [data-bpc-lang="vi"] {
    display: none;
  }

  .ballpit-countdown__logo {
    display: flex;
    justify-content: center;
    padding-top: 1.5rem;
    opacity: 0;
  }

  @media (min-width: 576px) and (max-width: 1024px) {
    .ballpit-countdown__logo {
      padding-top: clamp(2rem, 4vw, 3rem);
    }
  }

  .ballpit-countdown__logo-img {
    width: clamp(6.25rem, 11.3vw, 13rem);
    height: auto;
    object-fit: contain;
  }

  @media (min-width: 576px) and (max-width: 1024px) {
    .ballpit-countdown__logo-img {
      width: 8.5rem;
    }
  }

  .ballpit-countdown__top {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 2rem;
    padding: clamp(1rem, 3vw, 1rem) clamp(2.5rem, 5.4vw, 11rem);
  }

  @media (max-width: 1024px) {
    .ballpit-countdown__top {
      flex-direction: column;
      align-items: center;
      justify-content: flex-start;
      gap: clamp(2rem, 5vw, 3rem);
      padding: clamp(1rem, 3vw, 2rem) clamp(2.5rem, 5.4vw, 11rem);
    }
  }

  @media (max-width: 575px) {
    .ballpit-countdown__top {
      gap: 1.25rem;
      padding: 0.5rem clamp(1.25rem, 6vw, 2rem);
    }
  }

  .ballpit-countdown__heading-group {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
  }

  .ballpit-countdown__heading,
  .ballpit-countdown__highlight {
    font-size: clamp(3.1rem, 7.4vw, 8rem);
  }

  @media (min-width: 576px) and (max-width: 1024px) {

    .ballpit-countdown__heading,
    .ballpit-countdown__highlight {
      font-size: clamp(4rem, 8vw, 6rem);
    }
  }

  @media (max-width: 575px) {

    .ballpit-countdown__heading,
    .ballpit-countdown__highlight {
      font-size: clamp(2.2rem, 8.5vw, 2.8rem);
    }
  }

  .ballpit-countdown__heading {
    font-family: 'LonlyBop', sans-serif;
    font-weight: 800;
    color: #2c2620;
    margin: 0;
    white-space: nowrap;
  }

  .ballpit-countdown__highlight {
    position: relative;
    display: inline-block;
    margin: -0.25em 0 0;
    /* This is a <p> — the theme's own `body p, body li { line-height: 26px }`
       rule in main.min.css targets it directly. A directly-matching rule
       always wins over an inherited value regardless of specificity, so
       resetting line-height up on `.ballpit-countdown` doesn't reach this
       element; it has to be overridden right here. */
    line-height: normal;
    font-family: 'LonlyBop', sans-serif;
    font-weight: 700;
    color: var(--bpc-highlight-color, #fc322a);
    -webkit-text-stroke: 2px #f6f1e4;
    paint-order: stroke fill;
    /* `white-space: nowrap` is inherited from here down into `.highlight-text`
       and its per-character spans — keeps "Sắp trở lại" / "Coming soon" (and
       the decorative quote mark beside it) from breaking onto a second line
       as the heading's own font-size clamp shrinks on narrow viewports. */
    white-space: nowrap;
  }

  .ballpit-countdown__highlight-quote {
    position: absolute;
    left: -0.3em;
    top: 0.45em;
    width: 0.21em;
    height: 0.25em;
  }

  .ballpit-countdown__highlight-text {
    position: relative;
    display: inline-block;
    isolation: isolate;
  }

  .ballpit-countdown__highlight-underline {
    position: absolute;
    left: 29%;
    bottom: 0.15em;
    width: 59%;
    height: 0.3em;
    z-index: -1;
    pointer-events: none;
    transform: rotate(2deg);
  }

  .ballpit-countdown__stats {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    min-width: 195px;
  }

  .ballpit-countdown__pill {
    position: relative;
    background: #ffd366;
    border-radius: 999px;
    padding: clamp(0.5rem, 1.1vw, 1rem) clamp(1rem, 2.2vw, 2rem);
    box-shadow: 0 6px 0 rgba(0, 0, 0, 0.15);
  }

  .ballpit-countdown__pill--full {
    z-index: 2;
    margin-bottom: -0.85rem;
    transform: rotate(3.19deg);
    padding-top: clamp(0.3rem, 0.6vw, 0.5rem);
    padding-bottom: clamp(0.3rem, 0.6vw, 0.5rem);
  }

  .ballpit-countdown__pill--split {
    transform: rotate(-2deg);
    padding-top: clamp(0.3rem, 0.6vw, 0.5rem);
    padding-bottom: clamp(0.3rem, 0.6vw, 0.5rem);
  }

  .ballpit-countdown__pill-reveal {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 0.15rem;
  }

  .ballpit-countdown__pill-reveal--row {
    flex-direction: row;
    gap: 2rem;
    justify-content: center;
  }

  .ballpit-countdown__pill-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 0.15rem;
  }

  .ballpit-countdown__pill-label {
    font-family: 'LonlyBop', sans-serif;
    font-size: clamp(1rem, 1.1vw, 1rem);
    color: #171717;
    white-space: nowrap;
  }

  @media (max-width: 575px) {
    .ballpit-countdown__pill-label {
      font-size: 0.85rem;
    }
  }

  .ballpit-countdown__pill-value {
    font-family: 'LonlyBop', sans-serif;
    font-size: clamp(1.5rem, 2.5vw, 2.25rem);
    font-weight: 700;
    color: #171717;
    white-space: nowrap;
  }

  @media (max-width: 575px) {
    .ballpit-countdown__pill-value {
      font-size: clamp(1.1rem, 4.5vw, 1.4rem);
    }
  }

  .ballpit-countdown__timer {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: clamp(1rem, 4vw, 2.5rem);
    position: relative;
    margin-top: clamp(1rem, 4vw, 2rem);
    /* Hidden by default. The React original never even mounts these balls
       until physics is ready to take over, so there's no flash of the plain
       row before it does — this template renders them unconditionally in
       PHP instead, so without this, reloading shows the balls sitting still
       in a plain row for a moment and then jumping off-screen the instant
       `--physics` gets added, reading as "balls appear then get hidden".
       JS reveals this immediately if physics is never going to run at all
       (`--fallback`, see ballpit-countdown.js); once physics does take over,
       `--physics` below turns it back on at the exact same moment the balls
       are already positioned off-screen, so nothing in between is ever seen. */
    opacity: 0;
  }

  .ballpit-countdown__timer--physics,
  .ballpit-countdown__timer--fallback {
    opacity: 1;
  }

  .ballpit-countdown__timer--physics {
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    z-index: -1;
    margin-top: 0;
  }

  .ballpit-countdown__timer-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    position: relative;
    z-index: 0;
  }

  .ballpit-countdown__timer--physics .ballpit-countdown__timer-item {
    position: absolute;
    top: 0;
    left: 0;
    transform: translate3d(-200vw, -200vh, 0);
    will-change: transform;
  }

  .ballpit-countdown__decorative-ball {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 0;
    pointer-events: none;
    transform: translate3d(-200vw, -200vh, 0);
    will-change: transform;
  }

  .ballpit-countdown__decorative-ball-art {
    display: block;
    width: 100%;
    height: 100%;
  }

  .ballpit-countdown__circle {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.1em;
    width: clamp(3rem, 18vw, 18rem);
    height: clamp(3rem, 18vw, 18rem);
  }

  @media (max-width: 1024px) {
    .ballpit-countdown__circle {
      width: clamp(3rem, 187px, 18rem);
      height: clamp(3rem, 187px, 18rem);
    }
  }

  @media (max-width: 575px) {
    .ballpit-countdown__circle {
      width: clamp(3rem, 33vw, 18rem);
      height: clamp(3rem, 33vw, 18rem);
    }
  }

  .ballpit-countdown__timer--physics .ballpit-countdown__circle {
    width: 100%;
    height: 100%;
  }

  .ballpit-countdown__circle-art {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 0;
  }

  .ballpit-countdown__number {
    position: relative;
    z-index: 1;
    line-height: 1;
    font-family: 'LonlyBopCondensed', sans-serif;
    font-size: clamp(2rem, 7.8vw, 6.1rem);
    font-weight: 800;
    color: #fff;
  }

  .ballpit-countdown__unit {
    position: relative;
    z-index: 1;
    line-height: 1;
    font-family: 'Manrope', sans-serif;
    font-size: clamp(0.9rem, 2.8vw, 1.8rem);
    font-weight: 600;
    color: rgba(255, 255, 255, 0.85);
    padding-top: 0.5em;
  }

  .ballpit-countdown__cta-wrap {
    position: absolute;
    bottom: clamp(1.5rem, 8vw, 3rem);
    left: 50%;
    transform: translateX(-50%);
    z-index: 5;
  }

  .ballpit-countdown__cta {
    display: inline-flex;
    align-items: center;
    gap: clamp(0.4rem, 1.4vw, 0.75rem);
    overflow: hidden;
    background: #7f5bfd;
    border-radius: 999px;
    padding: clamp(0.75rem, 2.8vw, 1.75rem) clamp(1.25rem, 5.6vw, 3.5rem);
    box-shadow: clamp(3px, 0.8vw, 6px) clamp(3px, 0.8vw, 6px) 0 #6a40fd;
    color: #fafafa;
    font-family: 'Manrope', sans-serif;
    font-weight: 800;
    font-size: clamp(1.1rem, 2.8vw, 2.25rem);
    letter-spacing: -0.03em;
    white-space: nowrap;
    pointer-events: auto;
    text-decoration: none;
    /* No `transform` here on purpose — GSAP owns it entirely (hover squish,
       press feedback) once JS runs, writing inline styles every hover/press.
       Those inline styles always beat any stylesheet rule regardless of
       specificity, so a CSS-side transform transition would just fight the
       same property GSAP is already tweening every frame. */
    transition: background-color 0.15s ease, box-shadow 0.15s ease;
  }

  .ballpit-countdown__cta:hover,
  .ballpit-countdown__cta:focus-visible {
    background: #402e7f;
    box-shadow: clamp(3px, 0.8vw, 6px) clamp(3px, 0.8vw, 6px) 0 #553da9;
    color: #fafafa;
  }

  .ballpit-countdown__wave-char {
    display: inline-block;
    white-space: pre;
    transform-origin: 50% 50%;
  }

  .ballpit-countdown__cta-char {
    letter-spacing: 0.05em;
  }

  .ballpit-countdown__cta-swirl {
    position: absolute;
    top: 0;
    left: 0;
    width: clamp(2rem, 6.9vw, 5rem);
    height: clamp(1.1rem, 3.7vw, 2.7rem);
    background-repeat: no-repeat;
    background-size: 100% 100%;
    pointer-events: none;
  }

  .ballpit-countdown__cta-icon {
    position: relative;
    flex-shrink: 0;
    width: clamp(1.1rem, 2.8vw, 2.25rem);
    height: clamp(1.1rem, 2.8vw, 2.25rem);
  }

  /* The CTA exit transition's circle-reveal step — centered exactly on the
     viewport's bottom-middle point, big enough that only its top half is ever
     visible, reading as a dome rising from the bottom edge. GSAP animates
     `scale` (0 -> 1) rather than a `clip-path` radius so it runs on the
     compositor. `position: fixed` covers the whole page regardless of scroll.
     `pointer-events: none` since this always reverses the transition itself
     (see the CTA click handler) rather than actually navigating. */
  .ballpit-countdown__exit-overlay {
    position: fixed;
    left: 50%;
    top: 100%;
    width: 300vmax;
    height: 300vmax;
    margin: -150vmax 0 0 -150vmax;
    border-radius: 50%;
    z-index: 999;
    background: #ffd366;
    transform: scale(0);
    pointer-events: none;
  }

  /* Post-countdown UI — hidden until the CTA exit transition swaps it in for
     `.ballpit-countdown__content` (see ballpit-countdown.js). Positioned to
     fill the root and scroll on its own (rather than sharing the root's own
     `overflow: hidden; height: 100vh`), since it holds a full multi-section
     landing page (see LandingPageDes2026.php), not a single screen. */
  .ballpit-countdown__post-cta {
    position: absolute;
    inset: 0;
    z-index: 1;
    /* Flat Figma background (node 2848:15933) — opaque so it fully covers
       the countdown's own dot-field canvas/cursor-follow stars sitting
       behind it at z-index: 0, rather than layering the two. */
    background: #FDF8EB;
    flex-direction: column;
    align-items: center;
    overflow-y: auto;
    /* Explicit, not left to default — an `overflow-y` other than
       `visible` forces the browser to compute `overflow-x` as `auto`
       too if it isn't set (spec rule, same one worked around inside
       individual sections elsewhere in this file), and several
       sections' own decorative bleed (glow/road/carousel-track
       elements sized past their own box on purpose) was leaking through
       into a page-level horizontal scrollbar as a result. `hidden`
       here doesn't affect any section's *own* independent scroll
       container (e.g. `.benefits-row`'s horizontal drag) — each
       element's overflow is evaluated on its own box. */
    overflow-x: hidden;
    text-align: center;
    padding: 0px;
  }

  /* Without this, every section below is a flex-column item sized against
     this fixed-height (100dvh, via `inset: 0`) container — and since most
     of them set their own `overflow: hidden` for decorative layers, their
     flexbox automatic minimum size resolves to 0 (spec: only an
     `overflow: visible` item keeps its content-based min-height), letting
     the default `flex-shrink: 1` crush all of them down to fit one screen
     instead of stacking at full height and letting `overflow-y: auto`
     above scroll through them. */
  .ballpit-countdown__post-cta > * {
    flex-shrink: 0;
  }

  /* --- Site header (Figma node 3430:12408, "header") ------------------
     `position: fixed` (not `sticky`) — this floats above the whole page
     independent of `.hero`'s own `position: sticky` pin, since stacking a
     second sticky bar above it would push `.hero`'s stick point away from
     `.post-cta`'s actual top edge and desync its entire scroll-scrubbed
     exit animation (that math assumes `.hero` sticks flush at `top: 0`).
     ballpit-countdown.js toggles `--hidden` on scroll direction (down =
     hide, up = reveal) and intercepts each nav link's click to smooth-
     scroll `.post-cta` itself (not the window — see that JS) to the
     matching section id. */
  .ballpit-countdown__site-header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 20;
    background: #fdf8eb;
    padding: 1rem clamp(2rem, 7vw, 9rem);
    transition: transform 0.3s ease;
    width: 101vw;
  }

  .ballpit-countdown__site-header--hidden {
    transform: translateY(-100%);
  }

  .ballpit-countdown__site-header-row {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
  }

  .ballpit-countdown__site-header-logo {
    display: block;
    flex-shrink: 0;
    width: clamp(4.5rem, 6vw, 6rem);
  }

  .ballpit-countdown__site-header-logo img {
    display: block;
    width: 100%;
    height: auto;
  }

  .ballpit-countdown__site-header-nav {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    align-items: center;
    gap: clamp(1.25rem, 3vw, 2.5rem);
  }

  .ballpit-countdown__site-header-nav a {
    position: relative;
    display: inline-flex;
    align-items: center;
    padding: 0.25rem;
    font-family: 'Manrope', sans-serif;
    font-weight: 500;
    font-size: 1rem;
    line-height: 1.3;
    letter-spacing: 0.32px;
    color: #54110e;
    text-decoration: none;
    white-space: nowrap;
    transition: color 0.25s ease, transform 0.25s ease;
  }

  .ballpit-countdown__site-header-nav a::after {
    content: '';
    position: absolute;
    right: 0.25rem;
    bottom: -0.35rem;
    left: 0.25rem;
    height: 0.18rem;
    border-radius: 999px;
    background: #fc322a;
    transform: scaleX(0);
    transform-origin: center;
    transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
  }

  .ballpit-countdown__site-header-nav a:hover,
  .ballpit-countdown__site-header-nav a:focus-visible,
  .ballpit-countdown__site-header-nav a.is-active {
    color: #fc322a;
  }

  .ballpit-countdown__site-header-nav a:hover::after,
  .ballpit-countdown__site-header-nav a:focus-visible::after,
  .ballpit-countdown__site-header-nav a.is-active::after {
    transform: scaleX(1);
  }

  .ballpit-countdown__site-header-cta {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 3rem;
    padding: 0.25rem 1.5rem;
    border-radius: 999px;
    background: #fc322a;
    font-family: 'Manrope', sans-serif;
    font-weight: 700;
    /* 24px flat per explicit request — see `.challenge-apply-btn-label`'s
       own comment (ballpit-countdown.css, Challenge section). */
    font-size: 1.2rem;
    letter-spacing: -0.02em;
    color: #fff;
    text-decoration: none;
    white-space: nowrap;
  }

  /* No hamburger menu — out of scope (Figma is desktop-only here) — the
     centered nav's fixed 5-link/40px-gap width just doesn't fit under
     ~900px, so it drops and the header keeps only the logo + CTA. */
  @media (max-width: 900px) {
    .ballpit-countdown__site-header-nav {
      display: none;
    }
  }

  /* --- Hero section (Figma: DSNT 2026 Website/Sponsor Deck, node 2848:16016)
     The mascots/logo/bg-circle/stars/ribbon are exported as flattened
     images (see LandingPageDes2026.php's comment on why — the source is a
     hand-drawn illustration built from ~150 nested/masked vector paths per
     mascot, not a handful of reusable icons) and positioned to match the
     Figma canvas (1440x900) by percentage, so the whole scene scales as one
     fluid unit at every viewport width — no reflow breakpoint. */
  /* Scroll-driven exit animation spacer: gives `.hero` (sticky, below) room
     to stay stuck in view — as a full-viewport pinned backdrop, not just
     for its own exit animation — for the *whole* remaining scroll through
     Why Vietnam too, which now lives inside this same spacer as an
     absolutely-positioned overlay (see `.ballpit-countdown__wv` below)
     rather than as its own normal-flow section after it.
     Height must always equal `.wv`'s own `top` (below) plus Why Vietnam's
     own natural height (`242.29vw`, from its 1440:3489 canvas ratio —
     `3489/1440*100`) — otherwise there's either a stretch of blank pinned
     backdrop between Why Vietnam's last card and the FAQ section (spacer
     taller than it needs to be) or Why Vietnam's own bottom gets cut off
     (spacer shorter than its content). Currently `-28vw + 2400px + 100dvh`
     (`.wv`'s own `top`) + `242.29vw` = `214.29vw + 2400px + 100dvh`. The
     `2400px` term is `HERO_DECOR_PX` in ballpit-countdown.js's
     `initHeroScrollAnimation` — Why Vietnam's own `top` moved *earlier*
     than the hero's true natural height, 62.5vw from
     `aspect-ratio: 1440/900` — see `.hero-canvas` — so Why Vietnam starts
     overlapping the tail end of the hero's own exit animation rather than
     waiting for it to fully finish, see `.wv`'s own comment. The `100dvh`
     term is that same JS's `HERO_STATIC_PX` (there measured live off
     `postCtaEl.clientHeight`, an admin-bar-adjusted one-viewport
     measurement already — this is just its CSS-side equivalent, not tied
     together programmatically): per the user's own explicit ask, only
     once scroll has gone all the way through `.hero` *itself* — a full
     section, 100dvh tall by its own CSS rule — does phase A's exit
     animation start moving at all; before that the hero just sits there
     completely static. The worm's final stretch — from wherever
     `.wv-char--lua`'s position hands it off, through the rest of this
     whole spacer — is driven by one continuous scrub covering it end to
     end (`end: 'bottom bottom'` in the JS), not a second independent
     trigger, so it isn't affected by exactly where that handoff falls. */
  .ballpit-countdown__hero-scroll-spacer {
    /* `.ballpit-countdown__post-cta` (this element's flex-container parent)
       has `align-items: center`, which — unlike the default `stretch` —
       doesn't size a flex item to the container's cross-axis width on its
       own; explicit `width: 100%` is what `.hero` relied on before it
       became this element's child instead of post-cta's directly.
       `flex-shrink: 0` for the same root cause, different symptom: post-
       cta's own height is fixed (it's `inset: 0` inside the viewport-sized
       `.ballpit-countdown`), so by default flexbox shrinks a column child
       taller than that down to fit rather than letting it overflow — even
       though `overflow-y: auto` is set, that only governs how overflow is
       *displayed*, not whether flex-shrink treats it as available space to
       reclaim in the first place. Without this, the calc() above still
       computes correctly (verified in isolation) but the rendered box was
       a fraction of it — the sticky animation looked entirely broken
       (`.hero` never stuck, since there was no spacer height for it to
       stick through) even though every other part of this was correct. */
    position: relative;
    flex-shrink: 0;
    width: 100%;
    height: calc(214.29vw + 2400px + 100vh);
    height: calc(214.29vw + 2400px + 100dvh);

    body.admin-bar & {
      height: calc(214.29vw + 2400px + 100vh - 32px);
      height: calc(214.29vw + 2400px + 100dvh - 32px);
    }

    @media screen and (max-width: 782px) {
      body.admin-bar & {
        height: calc(214.29vw + 2400px + 100vh - 46px);
        height: calc(214.29vw + 2400px + 100dvh - 46px);
      }
    }
  }

  .ballpit-countdown__hero {
    /* Sized to the full viewport (not just its own ~62.5vw-tall canvas)
       so it reads as a real pinned backdrop with no gap of the wrong color
       below the decorative canvas while stuck — the worm's own camera-pan
       growth (see the JS) fills that extra space as it stretches out
       anyway. Same admin-bar accounting as `.ballpit-countdown` itself
       (the root), since this is just as much a "one viewport" element. */
    position: sticky;
    top: 0;
    z-index: 0;
    container-type: inline-size;
    /* so .hero-worm's `cqw` top-offset (a direct child now) resolves */
    width: 100%;
    height: 100vh;
    height: 100dvh;

    body.admin-bar & {
      height: calc(100vh - 32px);
      height: calc(100dvh - 32px);
    }

    @media screen and (max-width: 782px) {
      body.admin-bar & {
        height: calc(100vh - 46px);
        height: calc(100dvh - 46px);
      }
    }

    overflow: hidden;
    margin: 0 auto;
    background: #FDF8EB !important;

    /* On a narrow/portrait viewport, `.hero-canvas`'s own 1440:900 ratio
       renders it far shorter than this element's full 100dvh (a ~375px
       wide phone gets a ~234px-tall canvas in an 812px-tall viewport) —
       reported directly: the entire bottom half-plus of the screen sits
       empty on first paint, before any scrolling even starts. `.hero-worm`
       stays `position: absolute` (its own rule) so it's unaffected by
       flex here, still positioned/panned exactly as the JS computes it;
       `.hero-scene` is this element's only *normal-flow* child, so
       centering it is what actually closes most of that gap — not a full
       redesign (no mobile-specific Figma reference to build one from),
       just splitting the empty space evenly above/below instead of
       dumping it all beneath the illustration. */
    @media screen and (max-width: 767px) {
      display: flex;
      flex-direction: column;
      justify-content: center;
    }
  }

  .ballpit-countdown__hero-scene {
    /* The squiggle and ribbon images both intentionally bleed past the
       canvas's own edges (negative `left`, >100% `width`/`height` — see
       their own rules below), matching how they bleed past the Hero
       Section artboard in Figma. Clipping both axes here reproduces that
       same artboard clip; confirmed (by screenshotting with the clip
       temporarily removed) that nothing visible is lost on the Y axis —
       what's below the canvas's bottom edge there is empty margin in the
       ribbon asset itself, not visible ink.
       Tried `overflow-x: hidden` alone at one point, meaning to leave Y
       untouched since this element's own height is just auto (sized to
       `.hero-canvas`'s content) and so "has nothing to clip" there — but
       the CSS overflow spec doesn't allow one axis to stay `visible` once
       the other isn't: it silently upgrades the `visible` one to `auto`
       instead, which is exactly what produced an unwanted vertical
       scrollbar. Plain `overflow: hidden` (both axes, neither left at
       `visible`) sidesteps that entirely and is what's actually needed
       here regardless. */
    position: relative;
    width: 100%;
    overflow: hidden;
    padding-bottom: 5rem;
  }

  .ballpit-countdown__hero-canvas {
    /* The actual 1440:900 Figma canvas — every child in it keeps the
       percentage positions computed against that ratio, so the canvas
       always scales as one proportional unit (logo, mascots, card, text
       all staying at the same size relative to each other as in Figma)
       rather than being cropped or independently resized.
       `.hero` (this element's ancestor) is `position: sticky` — pinned in
       place for the *entire* scroll through this section (including the
       new leading dead zone in `initHeroScrollAnimation`) rather than
       scrolling normally, which is exactly why a plain `width: 100%` here
       is a real bug whenever that produces a canvas taller than the
       viewport (a wide-but-short window, or a shorter one still with the
       admin bar's own height subtracted): scrolling *cannot* pan a pinned
       element into view the way it would a normal in-flow one — whatever
       part of a too-tall canvas falls outside `.hero`'s own viewport-
       height box (see its own rule) is clipped by its `overflow: hidden`
       and stays permanently invisible, unreachable by scrolling however
       much further, confirmed directly (reported: the "Register Now"
       button and prize-card date staying clipped off no matter how far
       scrolled). `width: min(100%, 160vh/dvh)` fixes that at the source
       instead of trying to scroll around it: a *uniform* 2D scale (both
       width and the height `aspect-ratio` derives from it shrink by the
       same factor), so none of the composition's own relative proportions
       change — still pixel-for-pixel the same 1440:900 Figma layout, just
       rendered smaller — while guaranteeing it fits one full screen tall
       (160 = 1440/900*100, i.e. "the width that makes this exactly one
       dvh tall at this ratio") on any viewport shape. On a normal/
       portrait-ish viewport `100%` is the smaller value (unchanged from a
       plain `width: 100%`); only on a wide-but-short one does the `160dvh`
       term win, letterboxing with margin left/right rather than clipping
       the bottom off. Same admin-bar accounting as `.hero`/
       `.ballpit-countdown` themselves. A container query container so the
       content block's `cqw`-based sizes below track this canvas's own
       rendered width (which no longer always equals the viewport's, now
       that nested sections can size it) rather than the viewport
       directly. */
    container-type: inline-size;
    position: relative;
    width: min(100%, 160vh);
    width: min(100%, 160dvh);
    aspect-ratio: 1440 / 900;
    margin: 0 auto;

    body.admin-bar & {
      width: min(100%, calc((100vh - 32px) * 1.6));
      width: min(100%, calc((100dvh - 32px) * 1.6));
    }

    @media screen and (max-width: 782px) {
      body.admin-bar & {
        width: min(100%, calc((100vh - 46px) * 1.6));
        width: min(100%, calc((100dvh - 46px) * 1.6));
      }
    }
  }

  .ballpit-countdown__hero-squiggle,
  .ballpit-countdown__hero-bg-circle,
  .ballpit-countdown__hero-star,
  .ballpit-countdown__hero-character,
  .ballpit-countdown__hero-logo {
    position: absolute;
    width: 100%;
    height: auto;
    pointer-events: none;
  }

  .ballpit-countdown__hero-squiggle {
    /* The source vector bleeds well past the Hero Section artboard's own
       left/right edges (Figma's `inset-[-15.97%_-1.01%_-14.86%_-3.62%]`
       on it) — its export is a screenshot of the *node*, which Figma clips
       to the artboard bounds, so the asset itself already comes out
       exactly hero-canvas-width (1440px) with the true, unclipped bleed
       height (~491px in a 1440px-wide export). left/width would otherwise
       be just 0/100%; only `top` needed deriving from the bleed math
       (outer frame top 180.27px minus 15.97% of its own 375.61px height).
       That "100% = full bleed" assumption held as long as `.hero-canvas`
       itself was always exactly viewport-width — no longer true now that
       it letterboxes narrower on a wide-but-short viewport (see its own
       comment). `width: 100vw` / this `left` keep it spanning the actual
       screen edge-to-edge regardless: `(100% - 100vw) / 2` is 0 when the
       canvas is full-width (unchanged from before) and the letterbox's
       own half-gap — negative, i.e. further left — when it isn't. */
    left: calc((100% - 100vw) / 2);
    top: 21.37%;
    width: 100vw;
  }

  /* Scroll-animation ball (Figma 2848:17069 → 18171): one single image,
     `--full`, animated by ballpit-countdown.js rather than crossfaded
     between several — no MorphSVG license (see that file's
     `initHeroScrollAnimation` for the reasoning and the actual timeline),
     but a plain `left`/`top`/`width` tween on one element doesn't need
     one anyway. Two earlier stages lived here: `--half` (a partial-reveal
     "shine" asset) and, before that, a separate `--rest` image for the
     resting state — both dropped per explicit feedback, the second
     specifically because `--rest` was itself a dome (literally half a
     circle, not a complete one) so it read as just as much a "half" ball
     as the asset already removed. `--full` alone now covers the entire
     lifetime: visible (`opacity: 1`) and large from the very start — at
     the same `left`/`top`/`width` `--rest` used to occupy — then the JS
     tweens it down to the small size/position below, which is also
     (unchanged) the exact point `initHeroScrollAnimation`'s worm
     crossfades from once this fades out (`.hero-worm`'s own nudged origin
     targets it directly) — before this JS tween ever runs, that final
     `left`/`top`/`width` only lives as inline styles GSAP writes at
     runtime, not in this rule. */
  .ballpit-countdown__hero-bg-circle--full {
    left: 17.145%;
    top: 43.491%;
    width: 65.939%;
    z-index: 1;
  }

  /* The live "worm" path (see the PHP template's comment by this markup).
     Lives directly in `.hero` now (not nested in `.hero-canvas` with the
     rest of the decorative art), so it can pan/grow across the whole
     pinned viewport instead of being clipped to `.hero-canvas`'s own
     shorter 1440:900 box — which is also why `top` is a `cqw` value here
     rather than a height-relative `%`: `.hero`'s own height is just
     `100vh`, unrelated to its width, so a height-relative `%` would no
     longer mean what it used to. `cqw` keeps this on the *same*
     1440-reference scale as `left`/`width` below (both still simple `%`,
     since those stay width-relative either way) — `.hero-canvas` sits at
     `.hero`'s own top edge unchanged, so a position expressed in
     1440-reference units from that shared top edge lands identically
     whichever box it's actually measured against.
     Position is this path's own natural top-left corner (not a center +
     translate, since the SVG's own top-left is already known directly) —
     nudged from the raw Figma stage-4 metadata (which would start the path
     at canvas ~(640, 430)) so the path's start point instead lands exactly
     on `--full`'s own center (718.4, 507.5) for a seamless crossfade
     hand-off between the two independently-placed decorative elements. */
  .ballpit-countdown__hero-worm {
    position: absolute;
    left: -32.01%;
    top: 19.618cqw;
    /* 282.497 (1440-reference units) / 1440 * 100 */
    width: 134.39%;
    height: auto;
    opacity: 0;
    overflow: visible;
    pointer-events: none;
    transform-origin: top left;
    /* `initHeroScrollAnimation`'s Phase D writes a fresh `translateY`
       here on essentially every scroll tick for most of the page's own
       scroll length (panning the growing tip back to center) — hinting
       `transform` up front means the browser can promote this to its own
       compositor layer before that starts, instead of only realizing it
       needs to partway through the very sustained animation this is. */
    will-change: transform;
  }

  .ballpit-countdown__hero-worm-path {
    /* `stroke-width` lives in the path's own natural coordinate space
       (same as its viewBox and `d`), completely separate from `.hero-worm`'s
       own CSS `width`/position. 450 was Figma's own literal value for this
       road vector's stroke; bumped per explicit request to read closer to
       mindmarket.com's own chunkier reference path (theirs reads as a
       chain of large rounded blobs, not a thin line) while keeping this
       site's own gold rather than switching to their green. 700 (the
       mobile-only value below) read as too heavy at desktop's much wider
       canvas — this stroke scales with canvas *width* like everything
       else here, so the same unit count that looks right on a ~375-428px
       mobile canvas paints a much thicker line on a ~1440px desktop one —
       550 is a smaller bump here instead, kept modest on purpose.
       `initHeroScrollAnimation`'s Phase B reads this value live
       (`getComputedStyle`) to size `--full`'s crossfade target to match —
       exactly the ball's diameter, whatever this number is at the current
       breakpoint — rather than hardcoding it a second time in JS. */
    fill: none;
    stroke: #ffd366;
    stroke-width: 550;
    stroke-linecap: round;
  }

  .ballpit-countdown__hero-star--blue {
    left: -3.21%;
    top: 18.07%;
    width: 6.192%;
  }

  .ballpit-countdown__hero-star--green {
    left: 97.04%;
    top: 41.78%;
    width: 6.813%;

  }

  .ballpit-countdown__hero-character--1 {
    left: 69.58%;
    top: 9%;
    width: 19.746%;
    /* 21.94% * 0.9 */
  }

  .ballpit-countdown__hero-character--2 {
    left: 10.69%;
    top: 21.58%;
    width: 23.94%;
    /* 26.6% * 0.9 */
    z-index: 2;
    /* overlaps the blue star, which is z-index: 0 */
  }

  .ballpit-countdown__hero-character--3 {
    left: 10.65%;
    top: 8.83%;
    width: 13.194%;
    z-index: 2;
    /* 14.66% * 0.9 */
  }

  .ballpit-countdown__hero-character--4 {
    left: 59.14%;
    top: 39.76%;
    width: 26.343%;
    /* 29.27% * 0.9 */
    z-index: 2;
    /* overlaps the green star, which is z-index: 0 */

  }

  /* `left`/`width` recomputed to shrink *around the logo's own visual
     center* (both horizontal, 719.85 of 1440, and now also vertical,
     269.85 of 900) rather than from an unchanged top-left corner, which
     would only shrink the box's own right/bottom edges and leave its top
     edge exactly where it was — per explicit report the logo was reading
     as almost touching the fixed header floating above it (only ~8px of
     clearance at 1440px), a plain width-only shrink wouldn't have moved
     that top edge down at all. ~8% smaller, keeping the same center,
     lands `top` about 1.5 points lower instead. */
  .ballpit-countdown__hero-logo {
    left: 29.489%;
    top: 11.53%;
    width: 41%;
    z-index: 1;
  }

  .ballpit-countdown__hero-ribbon {
    /* Re-measured directly off Figma node 3430:10066 ("Frame 1948756212",
       the current 1440x900 reference for this whole hero, confirmed
       rendering 1:1 against this codebase's own `.hero-canvas`): the
       ribbon's own bounding group (3430:10553, "Group 1707480983") sits at
       x:-40.2225 y:665 w:1518.2225 h:226.606 — no separate asset-vs-frame
       bleed correction needed since this uses that group's own full
       visual box directly, not an inner asset frame with its own inset.
       The previous version's derivation landed at `top: 57.94%` (521px),
       ~143px above this node's actual 665px/73.9% — pulling the ribbon's
       band (and its "Presented by Lollypop" text) up into the quote text
       above it instead of sitting clearly below it like Figma shows.
       Same viewport-bleed letterboxing as `.hero-squiggle` — `left`/
       `width` add `(100vw - 100%)` so this still reaches the actual
       screen edges on a `.hero-canvas` narrower than the viewport. */
    position: absolute;
    left: calc(-6% - (100vw - 100%) / 2);
    bottom: -3rem;
    width: calc(120.378% + (100vw - 100%));
    height: auto;
    pointer-events: none;
    z-index: 3;
  }

  /* Mobile-only counterpart to `.hero-ribbon` above — see the PHP markup's
     own comment on why this is a dedicated asset rather than the desktop
     one repositioned. Hidden by default; shown (and the desktop one
     hidden) in the mobile media query below. */
  .ballpit-countdown__hero-ribbon-mobile {
    display: none;
  }

  .ballpit-countdown__hero-content {
    /* Repositioned from the full-page mockup (node 2821:14941 "Frame
       1948756279"), not the standalone hero component (2848:16016) used
       earlier — the two share every decorative element pixel-for-pixel
       (logo/characters/stars/bg-circle all match exactly) but the content
       block (quote/card/register) sits noticeably lower and wider in the
       full-page version: "Frame 1948756217" at absolute (480, 490),
       479.57 wide, vs. the (507, ~438-after-padding), 426-wide box used
       before.
       left/top below are that metadata position adjusted by a further
       (+18, -27)px — a pixel-comparison against a fresh Figma screenshot
       (matching the rendered card's white background edges) found the
       literal metadata numbers alone still landed consistently 18px left
       and 27px low of the reference, likely from some nested-percentage
       rounding this box's own chain of ancestors doesn't capture; those
       deltas were the same at every point sampled, i.e. a uniform
       translation, not a scale error, so no width/height change needed. */
    position: absolute;
    left: 38.58%;
    top: 52%;
    width: 29.961%;
    /* 33.29% * 0.9 */
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0;
    max-width: min-content;
    /* Was 2 — `.hero-quote`'s own box overlaps `.hero-ribbon`'s bounding
       box (the ribbon's source SVG canvas extends well above its actual
       drawn curve, see that rule's own comment on its `inset` math), and
       the ribbon's `z-index: 3` painted over the quote text there. Per
       explicit report, raised above the ribbon (and everything else in
       this scene) so the quote/card/register block always reads on top
       of it. */
    z-index: 4;

  }

  .ballpit-countdown__hero-quote {
    /* Figma node 3430:10556: 510px wide at the 1440px reference — wider
       than `.hero-content`'s own box (sized to the card+register row,
       ~400px), so this needs its own explicit `cqw` width rather than a
       percentage of that narrower parent. At the old 90%-of-parent width
       this wrapped to 4 lines instead of Figma's 3, pushing the last line
       down into the "Presented by Lollypop" ribbon band below it. */
    width: 35.417cqw;
    max-width: 90vw;
    margin: 0;
    font-family: 'Manrope', sans-serif;
    font-weight: 600;
    font-size: clamp(0rem, 1.25cqw, 1.125rem);
    /* 1.389cqw/1.25rem * 0.9 */
    line-height: 1.4;
    letter-spacing: 0.2px;
    color: #54110e;
    text-align: center;
    /* Now the LAST child (the card+register row moved above it to match
       Figma's actual stacking order — see the PHP markup) so the gap
       belongs before it, not after. */
    margin-top: 1rem;
    /* 2rem * 0.9 */
  }

  .ballpit-countdown__hero-details-row {
    display: flex;
    align-items: center;
  }

  .ballpit-countdown__hero-card {
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    gap: clamp(0rem, 1cqw, 0.7rem);
    /* 1.389cqw/1.25rem * 0.9 */
    width: clamp(0rem, 15.116cqw, 13.604rem);
    /* 16.796cqw/15.116rem * 0.9 */
    padding: clamp(0rem, 1.5cqw, 1.35rem);
    /* 1.667cqw/1.5rem * 0.9 */
    /* Figma's `mr-[-43px]` pulls the register badge's *rotated* bounding
       box 43px into the card's *rotated* bounding box at full (1440px)
       scale. `transform: rotate()` doesn't change what flexbox measures
       for spacing — only what's painted — so this element's own layout
       box (241.858x222, unrotated) needs a smaller negative margin than
       -43px: rotating shrinks the *visual* gap by how much each shape's
       painted extent grows past its own unrotated box — (252.6-241.858)/2
       ≈ 5.37px for this card at 2.85°, (269.95-212)/2 ≈ 28.98px for the
       register at 19.21° (both rotate about their own center, so both
       sides of each grow equally) — so the layout-box margin only needs
       to close the remaining 43 - 5.37 - 28.98 ≈ 8.66px, not the full
       43px, to land the intended 43px *visual* overlap between the two
       rotated shapes. Scaled 10% along with the card/register themselves
       below — a linear function of their (now smaller) rotated sizes, so
       it has to shrink by the same factor to keep the same *visual*
       overlap. */
    margin-right: clamp(-0.487rem, -0.541cqw, 0rem);
    /* -0.541rem/-0.601cqw * 0.9 */
    background: #fff;
    border-radius: 20px;
  }

  .ballpit-countdown__hero-card-item {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    text-align: left;
  }

  .ballpit-countdown__hero-card-label {
    font-family: 'Manrope', sans-serif;
    font-weight: 600;
    font-size: clamp(0rem, 0.75cqw, 0.675rem);
    /* 0.833cqw/0.75rem * 0.9 */
    line-height: 1.25;
    /* Figma node 3430:10559/10563/10567: `text/disabled-on-dark-bg`
       (#525252) — the same grey the label AND the value below it both use
       (confirmed directly in Figma's own output), not the maroon `#54110e`
       the quote text uses elsewhere in this hero. */
    color: #525252;
  }

  .ballpit-countdown__hero-card-value {
    font-family: 'LonlyBop', sans-serif;
    font-weight: 600;
    font-size: clamp(0rem, 1.7cqw, 1.53rem);
    /* 1.889cqw/1.7rem * 0.9 */
    letter-spacing: 1%;
    color: #525252;
    white-space: nowrap;
  }

  .ballpit-countdown__hero-register {
    position: relative;
    z-index: 1;
    flex-shrink: 0;
    display: block;
    width: clamp(0rem, 13.25cqw, 11.925rem);
    /* 14.722cqw/13.25rem * 0.9 */
    transform: rotate(-19.21deg);
    transition: transform 0.3s ease;
  }

  .ballpit-countdown__hero-register:hover {
    transform: rotate(-19.21deg) scale(1.05);
  }

  .ballpit-countdown__hero-register img {
    display: block;
    width: 100%;
    height: auto;
  }

  /* Overlaid star (see its own markup comment in LandingPageDes2026.php):
     stacks exactly on top of the badge below it — both share the same
     212x212 viewBox, so a plain 100%/100% fill lines the star back up with
     where it used to sit baked into that art — instead of following the
     badge's own `width:100%; height:auto` (equivalent here since the badge
     is square, but `.ballpit-countdown__hero-register .hero-register-star`
     below outweighs that shared `.hero-register img` rule on specificity
     alone, so being explicit here isn't load-bearing, just clearer).
     `pointer-events: none` keeps the register link's own click/hover target
     exactly what it was with one image instead of two stacked ones. GSAP
     spins this continuously post-entrance (ballpit-countdown.js,
     `initHeroEntrance()`) — `transform-origin` stays centered so it spins
     in place. */
  .ballpit-countdown__hero-register .ballpit-countdown__hero-register-star {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    transform-origin: 50% 50%;
  }

  /* Hero, mobile (Figma node 3746:1277, "Mobile Breakpoint") — a dedicated
     mobile mockup now exists (there wasn't one when the "no mobile reflow"
     approach above was first written), and it's a *different* composition
     from the desktop 1440:900 canvas, not just that same scene scaled
     down: the logo runs bigger/wider, all four characters regroup around
     it in a tighter cluster, the squiggle/stars drop out entirely, and
     the card+register+quote block sits lower, full-width. Same technique
     as `.wv-canvas`'s own mobile block: swap the canvas's reference
     aspect ratio to this mobile frame's own (375x801) and reposition
     every child by percentage against *that*, with fixed `rem` sizes
     (Figma's own flat mobile type scale) replacing desktop's `cqw` (which
     resolves against `.hero-canvas`'s rendered width — illegibly small
     once that's ~375-428px instead of desktop's ~1440px).
     `hero-bg-circle--full` is the one exception: its Figma layer here
     bleeds almost entirely off-canvas (metadata places it hundreds of px
     past the frame's right edge), which can't be what actually renders
     the visible yellow disc behind the card in the mockup screenshot —
     that position is eyeballed directly against the screenshot instead of
     computed from Figma's own numbers. `!important` throughout for the
     same reason as `.faq`'s own mobile block: a later same-selector rule
     this deep inside a nested `@media` still loses to an earlier one
     outside it without it. */
  @media (max-width: 767px) {
    .ballpit-countdown__site-header{
      padding: 0.5rem 1.6rem;
    }
    .ballpit-countdown__hero-card-item{
      gap: 0rem !important;
    }

    .ballpit-countdown__site-header-cta{
        padding: 0.15rem .5rem;
        font-size: 1rem;
        height: 2rem;
    }
    /* 812, not the 801 this started as — Figma's own mobile frame grew to
       812px tall since this ratio was first set, and every child's `top`
       percentage below is now measured against that current 812 figure;
       leaving this at the stale 801 was the source of a real, measurable
       drift (e.g. `.hero-ribbon-mobile` landing ~11px off from its
       intended spot, on top of whatever a manual `top`/`bottom` edit added
       to that same drift). */
    .ballpit-countdown__hero-canvas {
      aspect-ratio: 375 / 812;
    }

    /* The stars aren't present in Figma's mobile mockup — dropped rather
       than crammed into a composition redrawn without them. The squiggle
       stays (per explicit request) — it's cream-on-cream (`#EFE6CD`
       stroke over this section's own near-identical background), so it
       doesn't show up in a flat screenshot comparison even though it's
       still meant to weave behind the logo/character cluster here, same
       as it does on desktop. Repositioned (not left at its desktop
       `top: 21.37%`) since that number was tuned for the short, wide
       1440:900 canvas — applied as-is to this much taller 375:801 mobile
       one it would sit far above the cluster instead of behind it. */
    .ballpit-countdown__hero-star--blue,
    .ballpit-countdown__hero-star--green {
      display: none;
    }

    /* Mobile keeps the full mindmarket.com-inspired 700 (see the
       unconditional rule's own comment on why desktop uses a smaller 550
       instead) — the mobile canvas is narrow enough that even 700 paints
       a modest, not-overwhelming line. */
    .ballpit-countdown__hero-worm-path {
      stroke-width: 700;
    }

    .ballpit-countdown__hero-squiggle {
      top: 25%;
      transform: scale(2.5);

    }

    .ballpit-countdown__hero-bg-circle--full {
        left: -10%;
        top: 35%;
        width: 120%;
    }

    /* Figma's own logo `y` (30.68px, 3.78% of this frame) sits underneath
       where the fixed site header actually renders (measured: 74px tall,
       9.24% of this canvas) — Figma's isolated hero export has no header
       to clip against, but the real page does, and at rest (scroll 0, the
       header always visible) that top slice of the logo would sit hidden
       behind it. Nudged down to clear the header's own height instead of
       Figma's exact number, per explicit choice over leaving it clipped. */
    .ballpit-countdown__hero-logo {
      left: 16.31%;
      top: 9.24%;
      width: 70.51%;

    }

    .ballpit-countdown__hero-character--1 {
      left: 58.14%;
      top: 17.35%;
      width: 39.88%;
      z-index: 3;
    }

    .ballpit-countdown__hero-character--2 {
      left: 2.67%;
      top: 27.66%;
      width: 49.72%;
    }

    .ballpit-countdown__hero-character--3 {
      left: 15.65%;
      top: 15.73%;
      width: 29.89%;
    }

    .ballpit-countdown__hero-character--4 {
      left: 50.3%;
      top: 32.08%;
      width: 52.22%;
    }

    /* Sized/positioned to the quote's own width below (the widest of the
       three children) rather than the card+register row's narrower one,
       so `align-items: center` centers both correctly instead of clipping
       or off-centering the wider quote against a box sized for the row.
       `top` re-measured off this frame's current 812px height (was 801px
       when first measured — Figma's own frame grew since).
       Shrunk to 75% of Figma's own mobile size, per explicit request that
       it read too big — via smaller `width`/`cqw` values below, not a
       `transform: scale()` on this box: that approach was tried directly
       in this file and produced a stray duplicate-looking smear on the
       card's own edge (the overlap margin trick + a scaled ancestor don't
       compose cleanly) and needed its own repositioning on top of that. */
    .ballpit-countdown__hero-content {
      left: 17.7%;
      top: 44.46%;
      width: 64.6%; /* 86.13% * 0.75 */
      max-width: none;
    }

    /* `cqw` throughout this block, not `rem`/`px` — calibrated to this
       375px-wide mobile reference (`Ncqw = Npx * 100/375`, since `cqw`
       resolves against `.hero-canvas`'s own rendered inline-size, which is
       `container-type: inline-size` already, unconditionally, and equals
       the viewport width at any mobile size). A fixed `rem` value looks
       right only at exactly 375px and stays that same absolute size on a
       wider phone (e.g. iPhone 15 Pro Max, 430px), reading small relative
       to the rest of this now-larger, still-percentage-scaled composition
       — `cqw` grows with it instead, the same way the desktop section
       scales its own type against `.hero-canvas`'s 1440px reference.
       Every value here is Figma's own mobile number * 0.75 (see
       `.hero-content`'s own comment on why it's smaller than Figma at
       all) — not re-derived from a different reference. */
    .ballpit-countdown__hero-quote {
      width: 100%;
      max-width: none;
      font-size: 3cqw !important; /* 15px * 0.75 */
      letter-spacing: 0.03cqw !important; /* 0.15px * 0.75 */
      margin-top: 1.8cqw; /* 24px * 0.75 */
    }

    .ballpit-countdown__hero-card {
      width: 37.2cqw; /* 186px * 0.75 */
      padding: 3.2cqw !important; /* 16px * 0.75 */
      gap: 1.4cqw !important; 
      /* Figma's own mobile metadata: card right edge at 222px (36 + 186),
         register left edge at 159px — a flat 63px overlap, no rotation-
         compensation math needed since the mobile register isn't rotated
         (see below). Scaled by the same 0.75 as everything else here. */
      margin-right: -4.6cqw !important; /* -63px * 0.75 */
    }

    .ballpit-countdown__hero-card-label {
      font-size: 2.4cqw !important; /* 12px * 0.75 */
    }

    /* Figma switched this from the desktop `LonlyBop` display font to
       plain `Manrope Bold` — reads noticeably smaller/lighter than the
       chunky cartoon font it inherited from the unconditional desktop
       rule otherwise, which was the actual source of it looking oversized
       here, more than the raw font-size number. */
    .ballpit-countdown__hero-card-value {
      font-family: 'Manrope', sans-serif !important;
      font-size: 4cqw !important; /* 20px * 0.75 */
      letter-spacing: -0.08cqw !important; /* -0.4px * 0.75 */
    }

    .ballpit-countdown__hero-register {
      width: 40.676cqw; /* 203.38px * 0.75 */
      transform: none !important;
    }

    .ballpit-countdown__hero-register:hover {
      transform: scale(1.05) !important;
    }

    /* Swapped for the dedicated mobile asset below — the desktop ribbon's
       own art (a `text-path` wrapped around a much wider curve) doesn't
       reflow to a narrow crop the way a flat percentage reposition would
       assume. */
    .ballpit-countdown__hero-ribbon {
      display: none;
    }

    /* `top`, not `bottom` — this got flipped back and forth a couple of
       times and each `bottom` value (17%, 20%) pulled the ribbon up over
       the quote text above it (its own opaque band fully covers the
       quote whenever the two overlap, since it paints later/higher
       z-index), because `bottom` here is being measured against this
       canvas's own *current* 801px height, not Figma's 812px reference —
       a 17-20% gap from the bottom lands well above where Figma's own
       fixed `y: 685` position actually falls. `top: 84.36%` is that same
       `685/812` fraction instead, which stays correct regardless of which
       of those two canvas heights is currently in effect. */
    .ballpit-countdown__hero-ribbon-mobile {
      display: block;
      position: absolute;
      left: 0;
      bottom: 17.36%;
      width: 100%;
      height: auto;
      pointer-events: none;
      z-index: 3;
    }
  }

  /* --- FAQ section (Figma: DSNT 2026 Website/Sponsor Deck, node 2848:15933) */
  .ballpit-countdown__faq {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: clamp(1.5rem, 4vw, 2.5rem);
    width: 100%;
    padding: clamp(1.5rem, 4vw, 2.5rem);
    background: #FFD366;
    position: relative;
  }

  /* Same "Circle - section transition" technique as `.challenge::before`
     (see that rule's own comment) — this section's own background color
     bulges up as a flat-bottomed dome over the tail end of the purple
     `.who` section above it, instead of meeting it with a hard flat
     edge. */
  .ballpit-countdown__faq::before {
    content: '';
    position: absolute;
    left: 50%;
    bottom: 99%;
    transform: translateX(-50%);
    width: 140vw;
    /* Shallower than `.challenge::before`'s own dome on purpose: `.who`
       (the section this overlaps) has real staggered card content
       reaching close to its own bottom edge, unlike `.challenge`'s own
       predecessor, which is just a blank pinned backdrop back there — a
       tall dome here would cover actual card copy instead of just empty
       padding. Kept within `.who`'s own `clamp(3rem, 8vw, 6rem)` bottom
       padding (below) so it only ever bites into that reserved space. */
    height: 6vw;
    border-radius: 50% 50% 0 0 / 100% 100% 0 0;
    background: #FFD366;
    pointer-events: none;
    z-index: 1;
  }

  .ballpit-countdown__faq-heading {
    margin: 0;
    line-height: 1.1;
    font-family: 'LonlyBop', sans-serif;
    font-weight: 800;
    font-size: clamp(1.05rem, 4.5vw, 5rem);
    color: #54110e;
    text-align: center;
  }

  .ballpit-countdown__faq-columns {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    gap: clamp(1rem, 2.5vw, 1.5rem);
    width: 100%;
  }

  @media (max-width: 767px) {
    /* Figma node 3469:18999: `px-[8px]` — the base rule above has no side
       padding at all (only top/bottom), so the cards ran flush to the
       screen edges instead of leaving this small margin. */
    .ballpit-countdown__faq {
      padding-left: 0.5rem;
      padding-right: 0.5rem;
    }

    .ballpit-countdown__faq-columns {
      flex-direction: column;
    }

    /* Figma node 3469:18999 (the dedicated mobile mockup, not just the
       desktop layout squeezed narrower) specifies flat sizes here, not a
       point on the shared desktop `clamp()` curve above — at this width
       that curve had bottomed out at its own floor (17.55px/15.2px/14.4px
       measured live), well under half these actual mobile targets.
       `!important`: confirmed engine quirk (see `.footer-card`'s own
       comment above) where a later same-selector rule in a media query
       nested inside another selector's braces still loses to an earlier
       one outside it without this. */
    .ballpit-countdown__faq-heading {
      font-size: 2.25rem !important; /* 36px */
      font-weight: 400 !important; /* Figma: "font weight/regular", not 800 */
    }

    .ballpit-countdown__faq-question-text {
      font-size: 1.25rem !important; /* 20px */
      color: #262626 !important;
      letter-spacing: -0.4px;
    }

    .ballpit-countdown__faq-answer-text {
      font-size: 1rem !important; /* 16px */
      font-weight: 500 !important; /* Figma: Manrope Medium, not Semibold */
      color: #262626 !important;
      letter-spacing: 0.32px !important;
    }
  }

  .ballpit-countdown__faq-column {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    width: 100%;
    max-width: 650px;
  }

  .ballpit-countdown__faq-item {
    width: 100%;
    background: #fff;
    border-radius: 20px;
    overflow: hidden;
    transition: border-radius 0.3s ease, box-shadow 0.3s ease;
  }

  .ballpit-countdown__faq-item.is-open {
    border-radius: 24px;
    box-shadow: 6px 6px 0 rgba(0, 0, 0, 0.15);
  }

  .ballpit-countdown__faq-question {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: clamp(1rem, 3vw, 2.5rem);
    width: 100%;
    min-height: 90px;
    padding: 0.25rem clamp(1.25rem, 3vw, 2.25rem) 0.25rem;
    background: #fff;
    border: none;
    border-radius: inherit;
    text-align: left;
    cursor: pointer;
    font: inherit;
  }

  .ballpit-countdown__faq-question-text {
    flex: 1 1 0;
    font-family: 'Manrope', sans-serif;
    font-weight: 700;
    font-size: clamp(0.95rem, 2vw, 1.25rem);
    line-height: 1.25;
    color: #525252;
  }

  .ballpit-countdown__faq-toggle {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 999px;
    background: var(--color-2, #ffd366);
    transition: transform 0.3s ease;
  }

  .ballpit-countdown__faq-item.is-open .ballpit-countdown__faq-toggle {
    transform: rotate(180deg);
  }

  .ballpit-countdown__faq-toggle img {
    width: 19.2px;
    height: 19.2px;
    display: block;
  }

  /* Animates open/close via a 0fr -> 1fr grid row rather than height: auto
     (which can't be transitioned) or a JS-measured max-height (which needs
     a resize listener to stay correct if the text reflows). The padding
     lives on a further nested `-content` div, not on `-inner` (the item
     the grid track actually sizes) — padding is part of an element's own
     box regardless of its height, so putting it directly on `-inner` left
     a fixed sliver visible even at 0fr; `-inner`'s `overflow: hidden`
     clips `-content`'s padding away along with its text. */
  .ballpit-countdown__faq-answer {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 0.35s ease;
  }

  .ballpit-countdown__faq-item.is-open .ballpit-countdown__faq-answer {
    grid-template-rows: 1fr;
  }

  .ballpit-countdown__faq-answer-inner {
    min-height: 0;
    overflow: hidden;
  }

  .ballpit-countdown__faq-answer-content {
    padding: 0 clamp(1.25rem, 3vw, 2.25rem) 1.5rem;
  }

  .ballpit-countdown__faq-answer-text {
    margin: 0;
    font-family: 'Manrope', sans-serif;
    font-weight: 600;
    font-size: clamp(0.9rem, 2vw, 1rem);
    line-height: 1.4;
    letter-spacing: 0.2px;
    color: #171717;
    text-align: left;
  }

  /* --- Footer (Figma node 3430:13843) ----------------------------------
     Plain white section, no scroll-driven/JS behaviour at all — a white
     "card" (logo+blurb, two nav-link columns, "Follow us"+social icons)
     followed by a flush copyright/legal-links row underneath it (card
     itself ends at y:441 in Figma, that row starts right at y:441 — 0
     gap between them). Side padding matches this file's own established
     `clamp(1rem, 4vw, 4rem)` convention (`.ballpit-countdown__who`'s own
     section padding) since Figma's own 64px side margin against a
     1440-wide canvas is exactly that clamp's own max. `grid` (not flex)
     for the card's own two-column layout: the About block spans both
     rows on the left while Nav sits top-right and Social sits directly
     under it — Figma's own y-coordinates confirm Nav (0-264) and Social
     (263-433) stack with ~0 gap, not sit side by side. */
  .ballpit-countdown__footer {
    /* `.ballpit-countdown__post-cta` (this element's flex-container parent)
       has `align-items: center`, which doesn't stretch a flex item to the
       container's cross-axis width on its own — every other top-level
       section here (`.hero`, `.challenge`, etc.) sets this same explicit
       `width: 100%` for that exact reason; omitting it here is what let
       the card shrink to its own content width and get centered with
       uneven cream margins on either side instead of spanning full width. */
    width: 100%;
    background: #fff;
    padding: clamp(1.5rem, 4vw, 2.5rem) clamp(1rem, 4vw, 4rem) 0;
    /* `.ballpit-countdown` (this element's ancestor) sets a page-wide
       `text-align: center` for the hero/countdown screens above — every
       piece of footer copy (tagline, nav links, copyright, legal links)
       is left/right-flow in Figma, never centered, so reset it once here
       rather than repeating `text-align: left` on each child rule. */
    text-align: left;
  }

  /* Rebuilt to reproduce Figma's actual box model (node 3430:13845, since
     updated by 4088:76015 — see that node's own comment on the About
     column below) instead of the previous flex/grid approximation:
     About, Nav and Social are each their OWN absolutely-positioned/padded
     box (matching Figma's `p-[40px]` on every one of the three
     independently), not one shared card padding + a stretched `1fr` grid
     track. The previous `1fr` track let `.footer-nav`'s flex content
     start immediately after column 1 (~x:633 measured) instead of
     Figma's fixed nav start — a ~350px miss. Both the About column width
     and the Nav/Social start are expressed here as a % of the card's own
     width (34.1845% = 448.5/1312, 31.6311% = 415/1312 — the 415px gap
     between them is unchanged by the 4088:76015 update, only About's own
     column got narrower) so the exact Figma ratio holds at any card
     width the `minmax`/`vw` scaling produces, not just the 1440px
     reference. */
  .ballpit-countdown__footer-card {
    max-width: 1312px;
    margin: 0 auto;
    /* Figma (4088:76015): 546.54px tall at the 1440px reference
       (37.954vw) — up from the old 441px, entirely from the new "About
       Lollypop" block added below the tagline (see that block's own
       comment). This card's height is still decorative/fixed in Figma,
       not purely content-driven, so a min-height reproduces that same
       "extra breathing room" instead of the card shrink-wrapping to
       whichever of About/Nav+Social is tallest — floor scaled up from
       the old rule's own by the same ratio (max / old max) rather than
       guessed. */
    min-height: clamp(23.5rem, 37.954vw, 34.159rem);
    display: grid;
    grid-template-columns: 34.1845% 31.6311% 1fr;
    grid-template-rows: auto 1fr;
    background: #fff;
    border-radius: 24px;
  }

  @media (max-width: 900px) {
    /* `!important` here isn't decorative — without it this loses to the
       base (non-media) rule above despite matching and despite coming
       later in the source. Confirmed via the live CSSOM (both rules are
       present, correctly nested under `.ballpit-countdown`, media
       condition correctly evaluates true at this width) that the
       equal-specificity, later-in-source override still doesn't win here;
       looks like an engine quirk with a rule nested inside `@media` nested
       inside another selector's braces, not a mistake in this rule itself. */
    .ballpit-countdown__footer-card {
      min-height: 0 !important;
      grid-template-columns: 1fr !important;
      grid-template-rows: auto !important;
      /* Figma's own mobile mockup (4088:76099) has no gap of its own
         here either — each of About/Nav/Social now carries its own
         real top/bottom padding (24px/20px/20px, all per that same
         mockup, see each section's own mobile rule), which is what
         actually separates them, not an extra gap stacked on top of
         that padding. */
      gap: 0 !important;
    }

    /* `.footer-about`/`.footer-nav`/`.footer-social` still carry their
       desktop `grid-column`/`grid-row` placements — on a grid redefined to
       a single `1fr` column above, an explicit `grid-column: 3` doesn't
       clip to that column, it creates an *implicit* extra column with no
       width of its own, which pushed the nav/social block (and its 4th
       social icon) off the right edge instead of stacking under the logo
       like every other section's own mobile layout. */
    .ballpit-countdown__footer-about,
    .ballpit-countdown__footer-nav,
    .ballpit-countdown__footer-social {
      grid-column: 1 !important;
      grid-row: auto !important;
    }

    /* Figma node 3469:18939 (the dedicated 350px mobile mockup, not just
       the desktop one squeezed narrower): About and the "Follow us" block
       are *centered* here, not left-aligned like their desktop selves —
       and the card itself spans edge-to-edge with no outer side margin
       (its own x/width exactly match the 350px reference frame). */
    .ballpit-countdown__footer {
      padding-left: 0;
      padding-right: 0;
    }

    .ballpit-countdown__footer-about {
      align-items: center !important;
      text-align: center;
      /* Figma's mobile mockup (4088:76099/76100) only puts 8px between
         the tagline block and the brand block at this outer level — the
         much bigger visual gap that block still reads with comes from
         its own `py-[32px]` instead (see `.footer-brand`'s own mobile
         rule below), not from this gap growing to match desktop's 67px. */
      gap: 0.5rem !important;
      /* Figma mobile (4088:76100): 24px on every side, not desktop's
         40px carried over unchanged. */
      padding: 1.5rem !important;
    }

    /* `!important`: without it this loses to the desktop (non-media)
       `align-items: flex-start` above despite matching, coming later in
       the source, and equal specificity — the same nested-`@media`-
       inside-another-selector's-braces engine quirk `.footer-card`'s own
       mobile rule already has to work around elsewhere in this file.
       Confirmed directly: left off, both boxes (and everything inside
       them — the logos, the tagline, the two paragraphs) stayed flush
       left instead of centering. */
    .ballpit-countdown__footer-about-main,
    .ballpit-countdown__footer-brand {
      align-items: center !important;
    }

    .ballpit-countdown__footer-logo {
      /* Figma: 274px wide at the 350px mobile reference (78.3vw) — flat
         274px (not shrinking further) above that, down to an 11rem floor
         for anything narrower. */
      width: clamp(11rem, 78vw, 17.125rem) !important;
    }

    .ballpit-countdown__footer-tagline {
      text-align: center;
    }

    .ballpit-countdown__footer-brand {
      /* Figma (4088:76104): 32px of padding above/below this block at
         mobile — desktop has no padding of its own here, just the 67px
         gap on the parent (`.footer-about`, overridden to 8px above for
         mobile instead). */
      padding: 2rem 0;
    }

    .ballpit-countdown__footer-brand-text {
      text-align: center;
    }

    .ballpit-countdown__footer-brand-text p {
      /* Figma's mobile mockup uses Medium 13px here, not desktop's
         Semibold 12px — a genuine per-breakpoint type change, same
         pattern as several other components on this page, not an
         oversight carried over from the wrong node. */
      font-weight: 500;
      font-size: 0.8125rem;
    }

    .ballpit-countdown__footer-nav {
      /* Figma's updated mobile mockup (4088:76143/76144) actually uses a
         much *tighter* 12px column gap here — not the same 64px as
         desktop like this rule used to assume (that was true of the
         mockup this replaced, not this one). `justify-content: center`
         (Figma's row is `items-start justify-center`): the pair of
         columns is centered as a group here (each column's own text
         still left-aligned inside it), not flush against the left
         padding edge like desktop. */
      gap: 0.75rem !important;
      justify-content: space-around;
      /* Figma: 20px on every side, not desktop's 40px-sides/0-bottom. */
      padding: 1.25rem !important;
    }

    .ballpit-countdown__footer-nav-col {
      /* Figma: 8px between items in a column at mobile, not desktop's
         24px. */
      gap: 0.5rem !important;
    }

    .ballpit-countdown__footer-social {
      align-items: center !important;
      /* Figma: 20px top/bottom, no side padding of its own (the card
         itself already spans edge-to-edge with none at this width) —
         not desktop's `0 2.5rem 3rem`. */
      padding: 1.25rem 0 !important;
    }

    .ballpit-countdown__footer-social-label {
      text-align: center;
    }

    .ballpit-countdown__footer-social-icons {
      /* Figma: 8px between icons at mobile, not desktop's 12px. */
      gap: 0.5rem;
    }

    /* Figma: copyright and the legal links stack in one centered column
       (12px gap) here, not desktop's side-by-side row. `!important` on the
       properties this shares with the base (non-media) rule for the same
       reason `.footer-card` above needs it — confirmed engine quirk, not
       decorative. */
    .ballpit-countdown__footer-bottom {
      flex-direction: column;
      justify-content: center !important;
      gap: 0.75rem;
    }

    .ballpit-countdown__footer-legal {
      flex-direction: column;
      align-items: center;
      gap: 1rem !important;
    }
  }

  .ballpit-countdown__footer-about {
    grid-column: 1;
    grid-row: 1 / 3;
    box-sizing: border-box;
    padding: 2.5rem; /* Figma 3430:13846: 40px on every side */
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    /* Figma (4088:76018): 67px between the logo+tagline block and the
       new "About Lollypop" block below it (see `.footer-brand`'s own
       comment) — this rule's own gap used to be the 28px between the
       logo and the tagline directly, back when that pair was its only
       content; that 28px moved down onto `.footer-about-main` itself
       (its own two children) instead. */
    gap: 4.1875rem;
  }

  .ballpit-countdown__footer-about-main {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 1.75rem;
  }

  .ballpit-countdown__footer-logo {
    display: block;
    width: clamp(11rem, 20vw, 17.125rem);
    height: auto;
  }

  .ballpit-countdown__footer-tagline {
    margin: 0;
    /* Figma's About column is now 448.5px wide with 40px padding on every
       side (node 4088:76018/76019, was 465px before the 4088:76015
       update), so the tagline's real content width is 448.5 - 40 - 40 =
       368.5px ≈ 23rem — not a guessed value. */
    max-width: 23rem;
    font-family: 'Manrope', sans-serif;
    font-weight: 500;
    font-size: 1rem;
    line-height: 1.3;
    letter-spacing: 0.32px;
    color: #171717;
  }

  /* New block (Figma node 4088:76022, "About Lollypop") added below the
     tagline per that same 4088:76015 update: the Lollypop.Design brand
     lockup plus two paragraphs of real company copy — this section's
     footer previously stopped at the tagline. */
  .ballpit-countdown__footer-brand {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2rem; /* Figma: 32px, logo to the paragraph block */
    width: 100%;
    max-width: 22.3125rem; /* 357px, Figma's own box width for this block */
  }

  .ballpit-countdown__footer-brand-logo {
    display: block;
    width: 8.8283rem; /* 141.252px, Figma-exact */
    height: auto;
  }

  .ballpit-countdown__footer-brand-text {
    display: flex;
    flex-direction: column;
    gap: 1.125rem; /* Figma: 18px, between the two paragraphs */
    width: 100%;
  }

  .ballpit-countdown__footer-brand-text p {
    margin: 0;
    /* Figma: `font-family/body` Semibold at 12px — a noticeably smaller,
       heavier-weight style than `.footer-tagline`'s own Medium 16px
       right above it, not the same paragraph style reused. */
    font-family: 'Manrope', sans-serif;
    font-weight: 600;
    font-size: 0.75rem;
    line-height: 1.25;
    color: #262626;
  }

  /* Grid column 2 (31.6311% ≈ the 415px gap between About's right edge and
     Nav/Social's fixed `left: 880`) is deliberately left empty — a bare
     spacer column, not an element — so column 3 lands exactly where
     Figma's absolute `left: 880` does. */
  .ballpit-countdown__footer-nav {
    grid-column: 3;
    grid-row: 1;
    box-sizing: border-box;
    padding: 2.5rem 2.5rem 0; /* Figma 3430:13850: 40px, row 2 (Social) supplies its own bottom padding */
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem clamp(2rem, 5vw, 4rem); /* Figma: 64px column gap */
  }

  .ballpit-countdown__footer-nav-col {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .ballpit-countdown__footer-nav-col a {
    display: block;
    font-family: 'Manrope', sans-serif;
    font-weight: 500;
    font-size: 1.125rem;
    line-height: 1.4;
    letter-spacing: 0.18px;
    color: #171717;
    text-decoration: none;
  }

  .ballpit-countdown__footer-social {
    grid-column: 3;
    grid-row: 2;
    box-sizing: border-box;
    /* Figma 3430:13860: pinned `bottom: 8px` within the card, plus its own
       40px padding below the icons — align the block to the end of this
       (taller) row so it sits near the card's bottom edge instead of
       directly under Nav, then fold that 8px into the padding itself. */
    align-self: end;
    padding: 0 2.5rem 3rem;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 1.3rem;
  }

  .ballpit-countdown__footer-social-label {
    margin: 0;
    font-family: 'Manrope', sans-serif;
    font-weight: 500;
    font-size: 1rem;
    line-height: 1.3;
    letter-spacing: 0.32px;
    color: #262626;
  }

  .ballpit-countdown__footer-social-icons {
    display: flex;
    align-items: center;
    gap: 0.75rem;
  }

  .ballpit-countdown__footer-social-icons img {
    display: block;
    width: 3rem;
    height: 3rem;
    transition: transform 0.2s ease;
  }

  .ballpit-countdown__footer-social-icons a:hover img {
    transform: translateY(-2px);
  }

  /* Flush against the card above (Figma: card ends at y:441, this row
     starts at y:441 — 0 gap), the subtle top border is what actually
     separates them visually instead of spacing. */
  .ballpit-countdown__footer-bottom {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    max-width: 1312px;
    margin: 0 auto;
    border-top: 1px solid rgba(0, 0, 0, 0.08);
  }

  .ballpit-countdown__footer-copyright {
    margin: 0;
    padding: 1.5rem 0.75rem;
    font-family: 'Manrope', sans-serif;
    font-weight: 500;
    font-size: 1rem;
    line-height: 1.3;
    letter-spacing: 0.32px;
    color: #262626;
    white-space: nowrap;
  }

  .ballpit-countdown__footer-legal {
    display: flex;
    flex-wrap: wrap;
    gap: 3.5rem;
    padding: 1.5rem 0.75rem;
  }

  .ballpit-countdown__footer-legal a {
    font-family: 'Manrope', sans-serif;
    font-weight: 500;
    font-size: 1rem;
    line-height: 1.3;
    letter-spacing: 0.32px;
    color: #262626;
    text-decoration: none;
    white-space: nowrap;
  }

  /* --- "Why Vietnam?" section (Figma node 2848:16015) — same canvas
     -percentage + `cqw` approach as the hero, against this section's own
     1440x3489 reference frame instead of the hero's 1440x900. No mobile
     reflow here either, for the same reason as the hero (see its own
     closing comment above): every child stays percentage/cqw-locked to
     the canvas so the whole scene scales as one proportional unit.
     `position: absolute` (not normal flow) — this is a transparent overlay
     scrolling on top of the hero, which stays pinned as a full-viewport
     backdrop behind it (its own worm growing the whole time this scrolls
     past — see `.hero-scroll-spacer`'s and `.hero-worm`'s own CSS
     comments) — not its own section after the hero the way it used to be.
     `top` used to be the hero's own true natural height (62.5vw) plus its
     exit-animation scroll budget (2400px, `HERO_DECOR_PX` in
     ballpit-countdown.js) — i.e. Why Vietnam waited for the hero to fully
     finish before starting. Deliberately moved earlier since, progressively:
     `20vw` -> `2vw` -> `-13vw` -> now `-28vw` (plus `2400px` throughout), each time to
     make Why Vietnam start scrolling into view sooner — most recently per
     explicit request to bring it in earlier still. `.wv-char--lua` in
     particular needs to reach the pinned worm's ball (see
     `initHeroScrollAnimation`'s own comment on that handoff) within a
     reasonable amount of scrolling, not lag far behind it. The `2400px`
     term still has to stay in sync with `HERO_DECOR_PX`, and
     `.hero-scroll-spacer`'s own height has to stay in sync with whatever
     this is, same as before.
     The extra `100dvh` on top of that is `HERO_STATIC_PX` in that same JS
     (there measured live off `postCtaEl.clientHeight`, the same one
     viewport `.hero` itself is always exactly as tall as) — a leading
     scroll allowance where the hero just sits there completely static
     before phase A's own fade/circle/logo exit animation starts moving at
     all — without it here too, Why Vietnam would start scrolling into
     view at its old, un-delayed position while the hero's own exit
     animation now starts a full viewport later, overlapping a
     still-static hero instead of the tail of its exit animation like it's
     meant to. */
  .ballpit-countdown__wv {
    position: absolute;
    top: calc(100vh + -28vw + 2400px);
    top: calc(100dvh + -28vw + 2400px);
    left: 0;
    z-index: 1;
    width: 100%;

    body.admin-bar & {
      top: calc(100vh - 32px + -28vw + 2400px);
      top: calc(100dvh - 32px + -28vw + 2400px);
    }

    @media screen and (max-width: 782px) {
      body.admin-bar & {
        top: calc(100vh - 46px + -28vw + 2400px);
        top: calc(100dvh - 46px + -28vw + 2400px);
      }
    }
  }

  .ballpit-countdown__wv-scene {
    position: relative;
    width: 100%;
    overflow: hidden;
  }

  .ballpit-countdown__wv-canvas {
    container-type: inline-size;
    position: relative;
    width: 100%;
    aspect-ratio: 1440 / 3489;
  }

  .ballpit-countdown__wv-char {
    position: absolute;
    height: auto;
    pointer-events: none;
    z-index: 1;
  }

  .ballpit-countdown__wv-char--lua {
    left: 50.556%;
    top: 0%;
    width: 41.696%;
    /* 46.329% * 0.9 */
  }

  .ballpit-countdown__wv-char--guitar {
    left: 5.608%;
    top: 42.457%;
    width: 46.607%;
    /* 51.785% * 0.9 */
  }

  .ballpit-countdown__wv-char--earth {
    left: 50%;
    top: 73.084%;
    width: 48.419%;
    /* 53.799% * 0.9 */
  }

  /* Every size below (font/padding/gap in `cqw`, card `width` in `%`) is
     the original Figma value * 0.9 — a flat 10% reduction applied directly
     to each rule (position/`left`/`top` untouched, so anchoring against
     the canvas stays exactly where Figma put it) rather than one
     `transform: scale()` on the whole canvas. More rules to keep in sync
     if Figma's own numbers ever change, but no risk of a transform
     fighting anything else that reads real layout size (`getBoundingClientRect`,
     scroll-trigger math, etc. all see the true post-scale box this way). */
  .ballpit-countdown__wv-card {
    position: absolute;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2cqw;
    /* 2.222cqw * 0.9 */
    background: #fff;
    /* Figma: all four `.wv-card` instances (vn-card/challenges-title/
       align-card/bigger-card) use a flat 32px radius with no drop shadow
       — confirmed on each one's own node individually, not assumed from
       one. Previously 20px + a shadow here (only `.wv-challenges-title`
       had its own correct 32px/no-shadow override; the other three never
       did and were still wrong). */
    border-radius: 32px;
    padding: 2.5cqw;
    /* 2.778cqw * 0.9 */
    /* Figma: every card here (vn-card/challenges-title/align-card/
       bigger-card) is left-aligned. `.wv-card p` already had its own
       `text-align: left` reset, but `h3` never got the same treatment and
       was still inheriting the page-wide `text-align: center` default
       (`.ballpit-countdown`'s own root rule) — same recurring pattern as
       `.who-card-body`/`.stats-copy` earlier in this file. Setting it once
       here, on the shared card, covers both. */
    text-align: left;
  }

  .ballpit-countdown__wv-card h3 {
    margin: 0;
    font-family: 'LonlyBop', sans-serif;
    font-size: 2.25cqw;
    /* 2.5cqw * 0.9 */
    line-height: 1.2;
    letter-spacing: 0.36px;
    color: #525252;
  }

  .ballpit-countdown__wv-card h3 em {
    font-style: normal;
    color: var(--bpc-highlight-color, #fc322a);
  }

  .ballpit-countdown__wv-card p {
    margin: 0;
    font-family: 'Manrope', sans-serif;
    font-weight: 600;
    font-size: 1.25cqw;
    /* 1.389cqw * 0.9 */
    line-height: 1.4;
    letter-spacing: 0.2px;
    color: #171717;
    text-align: left;
  }

  .ballpit-countdown__wv-vn-card {
    left: 5%;
    top: 3.783%;
    width: 30.062%;
    /* 36.736% * 0.9 */
    padding: 2cqw;
    /* 2.222cqw * 0.9 */
  }

  .ballpit-countdown__wv-vn-row {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    width: 100%;
  }

  .ballpit-countdown__wv-flag {
    /* Figma node 3430:10859: a *square* 64x64.58 box (`object-bottom`
       cropping the wider flag source down to just the star, bottom-
       aligned), not the flag's own ~3:2 aspect — `height: auto` here
       previously kept the source's own wide rectangle, so the 45px radius
       barely rounded a short wide strip instead of reading as the round
       badge Figma shows. */
    width: 4.144cqw;
    /* 4.604cqw * 0.9 */
    aspect-ratio: 1;
    height: auto;
    object-fit: cover;
    object-position: bottom;
    border-radius: 45px;
    flex-shrink: 0;
  }

  .ballpit-countdown__wv-badge {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 16.25cqw;
    /* 18.056cqw * 0.9 */
    height: 4cqw;
    /* 4.444cqw * 0.9 */
    padding: 0 1cqw;
    /* 1.111cqw * 0.9 */
    /* Figma 3430:10860: `text/heading-primary-base` (#fc322a) — the app's
       standard red accent, not the darker/more muted flag-red (#da251d)
       this used before. */
    background: #fc322a;
    border-radius: 999px;
    font-family: 'LonlyBop', sans-serif;
    font-size: 2cqw;
    /* 2.222cqw * 0.9 */
    color: #fafafa;
    text-align: center;
    /* Source text is "why Vietnam?" (mixed case) but Figma's own render
       shows it fully uppercase — an explicit style on this text layer,
       not a font quirk (other LonlyBop headings elsewhere keep mixed
       case). */
    text-transform: uppercase;
    white-space: nowrap;
  }

  .ballpit-countdown__wv-challenges-title {
        left: 34.569%;
        top: 18.428%;
        text-align: center;
        padding: 2.222cqw;
        display: flex;
        justify-content: center;
        align-items: center;
  }

  .ballpit-countdown__wv-challenges-title h3 {
    white-space: normal;
  }

  /* Same `gap-px` + own-padding-drives-height trick Figma's own export
     uses for these four pills instead of explicit per-pill offsets: each
     pill's height comes from its padding/content alone, and stacking them
     in a plain flex column with a hairline gap reproduces the slightly
     uneven Figma spacing without needing to hand-place four separate
     `top` values. `align-items: center` (Figma's own parent frame is
     `flex-col items-center`) matters here too — each pill wrapper in
     Figma is its own width (348/436/433/482px, matching that pill's own
     text), centered within the shared parent, not stretched to one
     uniform width like this container's default cross-axis `stretch`
     would otherwise force. */
  .ballpit-countdown__wv-pills {
    position: absolute;
    z-index: 1;
    left: 31.148%;
    top: 24.849%;
    width: 33.933%;
    /* 37.703% * 0.9 */
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1px;
  }

  .ballpit-countdown__wv-pill {
    display: flex;
    align-items: center;
    justify-content: center;
    /* Figma: a symmetric 40px/30px (px-40 py-30), not the previous
       asymmetric right-heavy padding. */
    padding: 2.083cqw 2.778cqw;
    border-radius: 24px;
    font-family: 'LonlyBop', sans-serif;
    font-size: 2.25cqw;
    /* 2.5cqw * 0.9 */
    line-height: 1.2;
    letter-spacing: 0.36px;
    text-align: center;
    white-space: nowrap;
    /* `initWvPillCycle` retargets each pill's `x`/`y`/`rotation` with a
       fresh `gsap.to()` on essentially every scroll tick while its own
       stack-to-spread sequence plays — same reasoning as `.hero-worm`'s
       own `will-change` above. */
    will-change: transform;
  }

  /* Colors, rotation and skew read directly off Figma nodes 3430:10872/
     10874/10876/10878 — each pill has its own bg *and* its own matching
     text color (not one shared dark grey like this used to have), plus a
     slight `skewX` alongside the rotation that the previous version was
     missing entirely. */
  .ballpit-countdown__wv-pill--1 {
    background: #e5deff;
    color: #7f5bfd;
    transform: rotate(-4.87deg) skewX(-0.85deg);
  }

  .ballpit-countdown__wv-pill--2 {
    background: #fed6d4;
    color: #fc322a;
    transform: rotate(1.78deg) skewX(0.72deg);
  }

  .ballpit-countdown__wv-pill--3 {
    background: #d7f7d6;
    color: #599a57;
    transform: rotate(-3.95deg) skewX(-1.6deg);
  }

  .ballpit-countdown__wv-pill--4 {
    background: #d2e9ff;
    color: #1d92fd;
    transform: rotate(4.67deg) skewX(1.89deg);
  }

  .ballpit-countdown__wv-align-card {
    left: 58.264%;
    top: 45.859%;
    width: 33.563%;
    /* 37.292% * 0.9 */
  }

  .ballpit-countdown__wv-bigger-card {
    left: 12.153%;
    top: 81.16%;
    width: 26.625%;
    /* 29.583% * 0.9 */
  }

  /* Fire/Earth/Adapt/Air cards: positioned by their *center* point (via
     `translate(-50%,-50%)`, same bleed/rotation technique as the road
     background above) rather than by top-left corner — Figma rotates
     each of these around its own center, so the rotated bounding box
     Figma's metadata reports and the true unrotated 280x300 card share
     exactly one point in common: that center. Anchoring there and
     rotating the same fixed-size box sidesteps the separate
     rotated-vs-unrotated margin math `.hero-card`/`.hero-register`
     needed elsewhere in this file (those overlap each other and needed
     a precise *gap*, not just a position, which is why that math was
     unavoidable there but isn't here). */
  /* Card sizing/position only here — the white bg/radius/shadow/padding
     that used to live on this rule moved to `.wv-app-card-surface` for
     fire/earth/air (see that class's own comment for why), but `--adapt`
     has no surface wrapper in its markup (it never needed one — nothing
     inside it bleeds past its own edge the way the flame/leaf/swirl image
     does for the other three) so it re-declares them itself below. */
  .ballpit-countdown__wv-app-card {
    position: absolute;
    z-index: 1;
    width: 17.5cqw;
    /* 19.444cqw * 0.9 */
    height: 18.75cqw;
    /* 20.833cqw * 0.9 */
  }

  /* Position/rotation values below are the same four Figma-derived slots
     as before (see the still-applicable comment this rule used to carry,
     preserved on `.wv-app-card--air`), just reassigned to a new left-to-
     right reading order — Earth, Water(`--adapt`), Fire, Air — per
     explicit request (was Fire, Earth, Water, Air): each class keeps its
     own element identity/content, only which of the four screen slots it
     sits in changed, so the row still reads left-to-right in the new
     order instead of the class names implying one order while the screen
     shows another. */
  .ballpit-countdown__wv-app-card--earth {
    left: 18.093%;
    top: 63.978%;
    transform: translate(-50%, -50%) rotate(4.07deg);
  }

  /* `left` nudged from Figma's own raw 37.809% to 41.027% — per explicit
     report/screenshot, this slot and its leftward neighbor read as
     visibly clumped together with a much bigger gap before the next two
     slots. Figma's own hand-placed centers (18.093/37.809/64.129/
     86.895%) are only mildly uneven on their own, but each card is 17.5%
     wide, so that mild center-to-center variance turns into a *very*
     uneven edge-to-edge gap once the cards' own width eats into it
     (measured: ~43px between the first two slots vs. ~169px between the
     second/third at a 1920px viewport). The first and last slots are
     left at their own Figma position as the row's two anchors; the
     middle two now sit at even thirds between them (18.093 + 68.802/3, +
     68.802*2/3) instead. */
  .ballpit-countdown__wv-app-card--adapt {
    left: 41.027%;
    top: 66.078%;
    transform: translate(-50%, -50%) rotate(-3.32deg);
  }

  .ballpit-countdown__wv-app-card--air {
    left: 86.895%;
    top: 64.325%;
    transform: translate(-50%, -50%) rotate(6.27deg);
  }

  .ballpit-countdown__wv-app-card--fire {
    left: 63.961%;
    top: 65.615%;
    transform: translate(-50%, -50%) rotate(8.99deg);
  }

  /* Figma (e.g. 3430:11024 "Fire"): the CTA button bleeds below this
     surface's own bottom edge, unclipped by its `overflow: hidden` (needed
     to clip the flame/leaf/swirl decorative image + round the card's own
     corners) — so the button now lives *outside* this element, as a sibling
     of it inside `.wv-app-card`, which stays `overflow: visible` for
     exactly that reason. */
  .ballpit-countdown__wv-app-card-surface {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: flex-start;
    justify-content: flex-end;
    gap: 1cqw;
    /* 1.111cqw * 0.9 */
    background: #fff;
    border-radius: 40px;
    /* box-shadow: 6px 6px 0 rgba(0, 0, 0, 0.15); */
    padding: 0 0 1.5cqw 1.5cqw;
    /* 1.667cqw * 0.9 */
    overflow: hidden;
  }

  .ballpit-countdown__wv-app-text {
    flex: 1 0 0;
    min-width: 0;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    align-items: flex-start;
    padding-top: 1.5cqw;
    /* 1.667cqw * 0.9 */
    text-align: left;
  }

  .ballpit-countdown__wv-app-label {
    margin: 0;
    font-family: 'LonlyBop', sans-serif;
    font-size: 2.25cqw;
    /* 2.5cqw * 0.9 */
    line-height: 1.2;
    /* Figma (e.g. 3430:11026 "FIRE"): tracking-[0.64px], color
       `text/body-dark` (#262626) — not the #525252/0.36px used on the
       Why-Vietnam cards' own headings above (a different node/style). VI
       source text for this label is mixed/lowercase ("đất", "khí") but
       Figma's own render is fully uppercase even for the EN "earth" —
       an explicit transform on this text layer, not a font quirk. */
    letter-spacing: 0.64px;
    color: #262626;
    text-transform: uppercase;
  }

  .ballpit-countdown__wv-app-title {
    margin: 0;
    /* Figma (e.g. 3430:11028 "Explore new ideas"): `font-family/body`
       (Manrope Medium) at 18px, not LonlyBop — this class name is
       misleading (it's the smaller description under the big label, not
       another title). */
    font-family: 'Manrope', sans-serif;
    font-weight: 500;
    font-size: 1.125cqw;
    /* 1.25cqw * 0.9 */
    line-height: 1.4;
    letter-spacing: 0.18px;
    color: #171717;
  }

  .ballpit-countdown__wv-app-body {
    margin: 0;
    font-family: 'Manrope', sans-serif;
    font-weight: 500;
    font-size: 1cqw;
    /* 1.111cqw * 0.9 */
    line-height: 1.3;
    letter-spacing: 0.32px;
    color: #171717;
    text-align: left;
    position: absolute;
    bottom: 10%;
    left: 10%;
    width: 90%;
  }

  .ballpit-countdown__wv-app-swoosh-col {
    position: relative;
    flex-shrink: 0;
    width: 7cqw;
    /* 7.778cqw * 0.9 */
    height: 75%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    gap: 0.25cqw;
    /* 0.278cqw * 0.9 */
    border-bottom-left-radius: 32px;
    border-bottom-right-radius: 32px;
    overflow: hidden;
  }

  .ballpit-countdown__wv-app-card--fire .ballpit-countdown__wv-app-swoosh-col {
    background: #fd9894;
  }

  .ballpit-countdown__wv-app-card--earth .ballpit-countdown__wv-app-swoosh-col {
    background: #aeefac;
  }

  .ballpit-countdown__wv-app-card--air .ballpit-countdown__wv-app-swoosh-col {
    background: #bfadfe;
  }

  .ballpit-countdown__wv-app-card--adapt .ballpit-countdown__wv-app-swoosh-col {
    background: #b4dbfe;
  }

  .ballpit-countdown__wv-app-swoosh {
    position: absolute;
    left: -9%;
    width: 100%;
    height: 80%;
    pointer-events: none;
    bottom: -15%;

  }

  /* Figma (e.g. 3430:11032 "CTA Button" on the Fire card): this button
     bleeds past the white surface's own bottom edge, unclipped — it's now
     a sibling of `.wv-app-card-surface` (see that class's own comment),
     positioned absolutely against `.wv-app-card` itself instead of being a
     flex child inside the clipped column. `right` centers it under
     `.wv-app-swoosh-col` (7cqw wide, flush against the surface's own right
     edge since the surface has no right padding: (7cqw - this button's own
     4cqw) / 2 = 1.5cqw); `bottom: -2cqw` bleeds it exactly half its own
     height below the surface. */
  .ballpit-countdown__wv-app-cta {
    position: absolute;
    z-index: 1;
    right: 1.5cqw;
    bottom: 1cqw;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 4cqw;
    /* 4.444cqw * 0.9 */
    height: 4cqw;
    /* 4.444cqw * 0.9 */
    border-radius: 999px;
  }

  .ballpit-countdown__wv-app-cta img {
    width: 2.5cqw;
    /* 2.778cqw * 0.9 */
    height: 2.5cqw;
    /* 2.778cqw * 0.9 */
  }

  .ballpit-countdown__wv-app-card--fire .ballpit-countdown__wv-app-cta {
    background: #d22a23;
  }

  .ballpit-countdown__wv-app-card--earth .ballpit-countdown__wv-app-cta {
    background: #70c06d;
  }

  .ballpit-countdown__wv-app-card--air .ballpit-countdown__wv-app-cta {
    background: #6a4cd3;
  }

  .ballpit-countdown__wv-app-card--adapt .ballpit-countdown__wv-app-cta {
    background: #1d92fd;
  }

  /* Hover-flip (Figma node 3670:10040, "Flip card"): `perspective` lives
     on the outer `.wv-app-card` (already a positioned/rotated element) so
     the 3D effect reads correctly without disturbing that card's own
     `rotate(Xdeg)` tilt; the actual `rotateY` lives one level down on
     `.wv-app-card-flip` so the tilt and the flip compose instead of one
     overwriting the other. */
  .ballpit-countdown__wv-app-card--fire,
  .ballpit-countdown__wv-app-card--earth,
  .ballpit-countdown__wv-app-card--air,
  .ballpit-countdown__wv-app-card--adapt {
    perspective: 1600px;
  }

  .ballpit-countdown__wv-app-card-flip {
    position: relative;
    width: 100%;
    height: 100%;
    transform-style: preserve-3d;
    transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1);
  }

  .ballpit-countdown__wv-app-card--fire:hover .ballpit-countdown__wv-app-card-flip,
  .ballpit-countdown__wv-app-card--earth:hover .ballpit-countdown__wv-app-card-flip,
  .ballpit-countdown__wv-app-card--air:hover .ballpit-countdown__wv-app-card-flip,
  .ballpit-countdown__wv-app-card--adapt:hover .ballpit-countdown__wv-app-card-flip {
    transform: rotateY(180deg);
  }

  .ballpit-countdown__wv-app-card-face {
    position: absolute;
    inset: 0;
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
  }

  /* `.wv-app-card-face--front` needs no rules of its own: `.wv-app-card-
     surface` (100%x100%) + `.wv-app-cta` (absolute) inside already
     position/size themselves exactly as they did before this wrapper
     existed. */
  .ballpit-countdown__wv-app-card-face--back {
    transform: rotateY(180deg);
    background: #fff;
    border-radius: 40px;
    box-sizing: border-box;
    padding: 1.8cqw 1.8cqw 1.5cqw 1.8cqw;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    gap: 0.6cqw;
    text-align: left;
    box-shadow: 6px 6px 0 rgba(0, 0, 0, 0.08);
  }

  /* Figma (node 3670:10053 "Adapt to change", the Hover state): the title
     box is only ~162px wide out of the ~256px available — narrower than
     the card, on purpose, so it wraps *before* reaching the icon sitting
     beside it — the icon isn't pushed down after the text like a flex
     sibling would be, it's an independent top-right-corner element the
     whole time (body text below sits low enough, y=167+, to clear it
     without needing the same treatment). */
  .ballpit-countdown__wv-app-title--back {
    font-family: 'Manrope', sans-serif;
    font-weight: 700;
    font-size: 1.35cqw;
    line-height: 1.3;
    letter-spacing: 0.18px;
    color: #171717;
    max-width: 10.2cqw;
  }

  /* Figma's own "CTA Button" on every Hover-state card sits at a fixed
     top-right spot (`x:209,y:7.5,64x64` in this card's local 280x300 box,
     independent of the sibling text nodes — this file's own
     px-in-Figma's-280-wide-space -> cqw conversion is `px * 0.0625` since
     `.wv-app-card` itself is `17.5cqw` for that same 280px, e.g.
     `209 * 0.0625 ≈ 13.06cqw` from the left, `7.5 * 0.0625 ≈ 0.47cqw` from
     the top, expressed here as `right`/`top` insets off the face's own
     border box instead. Previously an `align-self: flex-end` flex child,
     which put it at the *bottom*-right (pushed there by the body text
     above it) instead of pinned top-right like Figma's own hover state. */
  .ballpit-countdown__wv-app-back-icon {
    position: absolute;
    top: 0.45cqw;
    right: 0.4cqw;
    width: 4cqw;
    height: 4cqw;
  }

  /* Mobile-only sticky card stack — see the PHP markup's own comment for
     what this replaces on small screens (the four `.wv-app-card`s above)
     and why. Hidden by default; shown in the mobile block below. */
  .ballpit-countdown__wv-stack {
    display: none;
  }

  /* --- Hero exit + Why Vietnam, mobile (Figma node 3724:15208, "Mobile
     Breakpoint" — combines the hero's own quote/card/register, already
     handled by `.hero-canvas`'s existing viewport-agnostic scaling, with
     Why Vietnam's content from the "why Vietnam?" badge onward, which
     is NOT handled by that same scaling: it's `.wv-canvas`'s own separate
     1440x3489 reference, and its `cqw` type would render illegibly small
     once that canvas is only ~375-428px wide instead of desktop's ~1440px).
     The scroll-jacked pin/worm/ball animation itself (`initHeroScrollAnimation`
     in ballpit-countdown.js) is untouched and keeps running exactly as on
     desktop — per explicit request — since it already measures every
     position it needs live off the DOM (`getBoundingClientRect`) rather
     than assuming desktop-specific pixel numbers; it automatically adapts
     once `.wv`'s own children actually render at the positions below.
     Same technique as desktop: one fixed-aspect-ratio canvas, every child
     positioned by percentage against it — just re-anchored to Figma's own
     mobile frame (375-wide; Why Vietnam's own content starts at that
     frame's y:961) instead of the desktop 1440-wide one, with fixed `rem`
     sizes (Figma's own flat mobile type scale) in place of desktop's
     `cqw`. The reference total below is *not* Figma's own raw span,
     though: several cards (`.wv-challenges-title` most of all) render
     measurably taller at these real font/line-wrap settings than Figma's
     own boxes assumed, so every element's `top` here is rebuilt as
     "previous element's own *measured* bottom + Figma's original gap to
     it" rather than Figma's raw absolute `y`, and the reference total
     (4384px — see `.wv-stack`'s own comment on the +1160px over this
     block's original 3225px) is that chain's own final measured bottom,
     not Figma's literal frame height — confirmed by rendering and reading
     back actual `getBoundingClientRect()`s, not recomputed from Figma's
     numbers alone. `!important` throughout for the same reason as
     `.faq`'s own mobile block: a later same-selector rule this deep
     inside a nested `@media` still loses to an earlier one outside it
     without it. */
  @media (max-width: 767px) {
    /* `.wv`'s own `top` (unchanged here — it derives from `.hero-canvas`'s
       aspect ratio, which has no mobile-specific override) plus this
       canvas's own natural height at any viewport width: `aspect-ratio:
       375/4384` means a full-bleed canvas renders `4384/375*100 = 1168.53vw`
       tall, so `.hero-scroll-spacer` must reserve exactly that much (see
       its own desktop comment for why these two have to stay in lockstep:
       any drift here either strands blank pinned backdrop above FAQ or
       clips Why Vietnam's own bottom off). `-28vw` folded in the same way
       the desktop comment derives its own `214.29vw` from `242.29vw`. */
    .ballpit-countdown__hero-scroll-spacer {
      height: calc(1140.53vw + 2400px + 100vh);
      height: calc(1140.53vw + 2400px + 100dvh);

      body.admin-bar & {
        height: calc(1140.53vw + 2400px + 100vh - 32px);
        height: calc(1140.53vw + 2400px + 100dvh - 32px);
      }

      @media screen and (max-width: 782px) {
        body.admin-bar & {
          height: calc(1140.53vw + 2400px + 100vh - 46px);
          height: calc(1140.53vw + 2400px + 100dvh - 46px);
        }
      }
    }

    .ballpit-countdown__wv-canvas {
      aspect-ratio: 375 / 4384;
    }

    .ballpit-countdown__wv-card {
      gap: 1.25rem !important; /* 20px */
      padding: 1.5rem !important; /* 24px */
      border-radius: 24px !important;
    }

    .ballpit-countdown__wv-card h3 {
      font-size: 1.75rem !important; /* 28px */
      letter-spacing: 0.56px !important;
    }

    .ballpit-countdown__wv-card p {
      font-size: 0.9375rem !important; /* 15px */
      letter-spacing: 0.15px !important;
      line-height: 1.4 !important;
    }

    .ballpit-countdown__wv-vn-card {
      left: 11.47%;
      top: 0%;
      width: 77%;
      padding: 1.25rem !important; /* 20px — this one card alone, per Figma */
      border-radius: 20px !important;
      gap: 1.5rem !important; /* 24px */
    }

    .ballpit-countdown__wv-vn-text {
      font-size: 0.9375rem !important; /* 15px */
      letter-spacing: 0.15px !important;
    }

    .ballpit-countdown__wv-flag {
      width: 3rem !important; /* 48px */
    }

    .ballpit-countdown__wv-badge {
      width: auto !important;
      height: 3rem !important; /* 48px */
      padding: 0.25rem 1rem !important;
      font-size: 1.75rem !important; /* 28px */
    }

    /* This and every other `top` between here and `.wv-align-card` below
       are the original values (measured back when this block's own
       reference total was still 3225px) rescaled by `3225/4384` — the
       stack's own arrival grew that total to 4104px, then its own added
       trailing dwell space grew it again to 4384px (see `.wv-stack`'s
       comment), and every `top` here is a percentage *of that total*, so
       all of them drift to the wrong absolute position whenever it
       changes, not just the ones after the insertion point. Missing this
       the first time around left `.wv-align-card` sitting low enough to
       be physically covered by the stack — reported directly. */
    .ballpit-countdown__wv-char--lua {
      left: -2.13%;
      top: 6.819%;
      width: 109.13%;
    }

    .ballpit-countdown__wv-challenges-title {
      left: 10.13%;
      top: 15.228%;
      width: 80%;
    }

    .ballpit-countdown__wv-pills {
      left: 13.07%;
      top: 20.677%;
      width: 74%;
    }

    /* Figma's own mobile pill widths (229/253/277/235px of a 375px frame)
       — narrower than the natural single-line width of each phrase at
       28px, so `white-space: normal` plus that same max-width reproduces
       the same two-line wrap Figma shows rather than leaving it to wrap
       wherever a wider box happens to break. */
    .ballpit-countdown__wv-pill {
      padding: 1.25rem 1.875rem !important; /* 20px 30px */
      border-radius: 16px !important;
      font-size: 1.75rem !important; /* 28px */
      white-space: normal !important;
    }

    .ballpit-countdown__wv-pill--1 {
      max-width: 14.325rem; /* 229.2px */
    }

    .ballpit-countdown__wv-pill--2 {
      max-width: 15.795rem; /* 252.7px */
    }

    .ballpit-countdown__wv-pill--3 {
      max-width: 17.34rem; /* 277.5px */
    }

    .ballpit-countdown__wv-pill--4 {
      max-width: 14.693rem; /* 235.1px */
    }

    .ballpit-countdown__wv-char--guitar {
      left: 7.45%;
      top: 31.716%;
      width: 102.32%;
    }

    .ballpit-countdown__wv-align-card {
      left: 14.13%;
      top: 39.02%;
      width: 72%;
    }

    /* All four desktop app-cards are replaced by `.wv-stack` below (Figma
       node 3746:1282) — a MindMarket.com-style sticky card stack, not this
       swoosh+CTA layout squeezed into a mobile width nobody designed it
       for. */
    .ballpit-countdown__wv-app-card--fire,
    .ballpit-countdown__wv-app-card--earth,
    .ballpit-countdown__wv-app-card--air,
    .ballpit-countdown__wv-app-card--adapt {
      display: none;
    }

    /* Sticky card stack (Figma node 3746:1282, "Sticky Horizontal Srcoll"
       [sic]) — the mindmarket.com-style effect requested to replace the
       four separate app-cards on mobile: each `.wv-stack-card` sticks at
       its own staggered `top` (0/125/250/375px). Deliberately *no*
       negative `margin-top` pulling cards together in normal flow — tried
       that first (to match Figma's own much shorter 669px wrapper, which
       looked like it assumed pre-collapsed cards), and it reads wrong:
       the cards sit collapsed into their final stacked look from the
       very top of this section instead of entering one at a time as you
       scroll, which is the entire point of the reference effect. Each
       card needs its own *full, non-overlapping* flow slot
       for the sticky offsets to actually stagger the reveal — so this
       wrapper reserves the full sum of all four card heights
       (4 * 280px = 1120px) instead of Figma's own static-mockup number,
       confirmed directly by scrolling through it. This wrapper's height
       (1120px vs. the single old Fire card's 240px) is the +880px this
       whole block's own reference total grew by (3225px -> 4104px, see
       that comment). `left`/`width` below are Figma's own 48/280 (of
       375) converted to %; `top` is unchanged from where the old single
       Fire card sat, kept as this stack's own start point since Figma's
       mobile mockup for this component wasn't placed at a specific point
       in the full combined Why-Vietnam scroll — only its own internal
       layout (card size, stagger amount) was taken from it.

       An extra 280px (one more card-height) of trailing space was added
       on top of that (1120px -> 1400px, the +1160px this block's total
       now reflects: 3225px -> 4384px) so the last card (Air) gets the
       same scroll "dwell" room the others get for free from the next
       card's arrival covering them — without it, Air had zero distance
       between sticking and being forced to release, so scrolling back up
       jumped straight from Air fully covering everything to Adapt with
       no in-between state, unlike Fire/Earth/Adapt which resolve
       gradually. Reported directly ("item cuối cùng ... đè tất cả các
       item khác"). */
    .ballpit-countdown__wv-stack {
      display: block;
      position: absolute;
      left: 12.8%;
      top: 49.751%;
      width: 74.667%;
      height: 373.333cqw; /* 1400px = 4 * 280px + 1 trailing card-height */
    }

    /* `overflow: hidden` here (unconditional, above) silently disables
       `position: sticky` for every descendant in WebKit/Safari — not a
       WordPress/theme bug, a real cross-browser difference: Chromium
       keeps sticky working fine through an `overflow: hidden` ancestor
       that isn't itself the scrolling container, Safari does not. Only
       found by testing this page in an actual WebKit engine — Chromium-
       based testing alone showed the stack working perfectly and gave no
       reason to suspect this. `.wv-canvas`'s own children (the character
       art bleeding slightly past the canvas edge, e.g. `.wv-char--lua` at
       109% width) still can't spill past the *viewport* either way,
       since `.post-cta` (the real scrolling container, several ancestors
       up) already clips its own horizontal overflow — so this has no
       other layout consequence here, just the one that actually matters. */
    .ballpit-countdown__wv-scene {
      overflow: visible;
    }

    .ballpit-countdown__wv-stack-card {
      position: sticky;
      /* `--bpc-wv-stack-nudge` (below) shifts every card's own sticky
         point down by the same amount — per explicit request, so the
         stack settles a little further into the middle of the screen
         instead of snapping flush to the very top edge the instant each
         card sticks. Added once here via a custom property rather than
         baked into each modifier's own `top` below, so the four cards'
         existing relative stagger (0/23.333/46.667/69.333cqw) stays
         exactly as tuned — only their shared starting point moves. */
      --bpc-wv-stack-nudge: 10vh;
      top: var(--bpc-wv-stack-nudge);
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
      width: 100%;
      height: 74.667cqw; /* 280px */
      box-sizing: border-box;
      padding: 0 0 4.267cqw 4.267cqw; /* 16px bottom/left, Figma's own outer-card padding */
      background: #fff;
      border-radius: 24px;
      border: 3px solid #F6F1E4;
    }

    /* Stagger reassigned to the new Earth → Water(`--adapt`) → Fire → Air
       DOM order (was Fire → Earth → Adapt → Air) — each sticky card's own
       `top`/`z-index` has to increase in the same order the cards
       actually appear in the DOM for the stack/reveal effect to work,
       so this had to move along with the reorder, not just the content. */
    .ballpit-countdown__wv-stack-card--earth {
      top: var(--bpc-wv-stack-nudge);
      z-index: 1;
    }

    .ballpit-countdown__wv-stack-card--adapt {
      top: calc(var(--bpc-wv-stack-nudge) + 23.333cqw);
      z-index: 2;
    }

    .ballpit-countdown__wv-stack-card--fire {
      top: calc(var(--bpc-wv-stack-nudge) + 46.667cqw);
      z-index: 3;
    }

    .ballpit-countdown__wv-stack-card--air {
      top: calc(var(--bpc-wv-stack-nudge) + 69.333cqw);
      z-index: 4;
    }

    .ballpit-countdown__wv-stack-card-text {
      display: flex;
      flex: 1 1 0;
      flex-direction: column;
      justify-content: space-between;
      min-width: 0;
      height: 100%;
      padding: 4.267cqw 4.267cqw 0 0; /* 16px top/right */
      text-align: left;
    }

    .ballpit-countdown__wv-stack-card-label {
      margin: 0;
      font-family: 'LonlyBop', sans-serif;
      font-weight: 700;
      font-size: 7.467cqw; /* 28px */
      line-height: 1.25;
      letter-spacing: 0.149cqw; /* 0.56px */
      color: #525252;
    }

    .ballpit-countdown__wv-stack-card-body {
      display: flex;
      flex-direction: column;
      gap: 4.267cqw; /* 16px */
      padding-bottom: 1.067cqw; /* 4px */
    }

    .ballpit-countdown__wv-stack-card-title {
      margin: 0;
      font-family: 'Manrope', sans-serif;
      font-weight: 700;
      font-size: 4.267cqw; /* 16px */
      letter-spacing: 0.0853cqw; /* 0.32px */
      line-height: 1.3;
      color: #262626;
    }

    .ballpit-countdown__wv-stack-card-desc {
      margin: 0;
      font-family: 'Manrope', sans-serif;
      font-weight: 500;
      font-size: 3.467cqw; /* 13px */
      letter-spacing: 0.0693cqw; /* 0.26px */
      line-height: 1.3;
      color: #262626;
    }

    .ballpit-countdown__wv-stack-card-icon {
      flex-shrink: 0;
      position: absolute;
      top: 2.203cqw; /* 8.26px */
      right: 2.331cqw; /* 8.74px */
      width: 17.067cqw; /* 64px */
      height: 17.067cqw;
    }

    .ballpit-countdown__wv-bigger-card {
      left: 14.13%;
      top: 85.128%;
      width: 72%;
    }

    .ballpit-countdown__wv-char--earth {
      left: -1.07%;
      top: 90.005%;
      width: 101.15%;
    }
  }

  /* --- "Ready for the 24-hour challenge?" (Figma node 2848:19280, "DSNT
     Info") ------------------------------------------------------------
     A normal-flow section — nothing here is pinned/scroll-scrubbed like
     hero/Why Vietnam — that starts right where the worm's own scroll
     spacer ends, i.e. exactly when the worm finishes growing. Built with
     plain flexbox + `clamp()`-based responsive sizing (matching
     `.ballpit-countdown__faq`'s own convention below/above), not the
     cqw-on-a-fixed-canvas system hero/wv use — this section's own Figma
     layer tree is auto-layout (flex) throughout, not an illustration
     canvas, so that's the closer match. */
  .ballpit-countdown__challenge {
    position: relative;
    width: 100%;
    padding: clamp(2rem, 6vw, 5rem) clamp(1rem, 4vw, 4rem) clamp(1.5rem, 4vw, 2.5rem);
    margin-top: clamp(1.5rem, 4vw, 2.5rem);
    overflow: visible;
    padding-top: 0px !important;
    /* Figma's own root background for this whole node (2848:19280) —
       matters here specifically because the character PNGs below
       (cheer/day1/day2) all came back as opaque flattened exports (no
       real alpha), each with *this* exact color (or this composited with
       `.challenge-day`'s own `rgba(255,255,255,0.4)` overlay, which — the
       math checks out exactly — is what produces their slightly lighter
       #f5f0e1) already baked into their own corners. Any other page
       background here would show as a visible mismatched rectangle
       around every character. */
    background: #efe6cd;
  }

  /* This section's own tan background doesn't just start with a flat
     horizontal edge where the section above leaves off — it bulges up
     into a dome first, overlapping that section's own tail end. Figma
     (node 2848:16921, "Circle - section transition") does this with a
     giant ellipse sitting mostly off-canvas, reproduced here as a
     `::before` shaped into just the ellipse's own *upper half* directly
     via `border-radius` (a flat-bottomed dome, not a full oval) rather
     than importing that same giant image. `width`/`height` started out
     as Figma's own literal rx/ry in `vw` (rendering the actual Figma
     node at exactly 1440px wide and sampling its pixels gave a dome
     peaking only ~122px above its own edges at that width) — per
     explicit request that read as too flat/subtle, so both are bigger
     than that literal figure now for a visibly more pronounced curve;
     the two still move together (`height` roughly half of `width`) to
     keep the same general dome proportions, just scaled up. */


  .ballpit-countdown__challenge::before {
    content: '';
    position: absolute;
    left: 50%;
    bottom: 99%;
    transform: translateX(-50%);
    width: 140vw;
    height: 22vw;
    border-radius: 50% 50% 0 0 / 100% 100% 0 0;
    background: #efe6cd;
    pointer-events: none;
    z-index: 1;
  }
  /* The floating "cheering" character leans on the stats card's own
     top-left corner, anchored to *this card* (`.challenge-cheering-card`,
     its own `position: relative` below) — checked directly against
     Figma metadata, four separate pieces each with their own
     independent position in the *source* file, not one single image:
     head at (1065.35, 149.17)/343.27×239.94, arm+pointing hand at
     (899.94, 206.46)/379.96×357.62, second hand at
     (1367.89, 309.09)/194.93×171.74, decorative ellipse behind them at
     (1126, 353)/133×103 — all in the same coordinate space as the
     card's own (781.41, 438.10)/607.17×538.33. This wrapper is sized to
     their shared union bounding box (662.88×414.91 — the ellipse sits
     fully inside the head+arm+hand box, so it doesn't change the
     union) so `left`/`top`/`width` on each `<img>` below — percentages
     of *this* box, not the viewport — reproduce their exact relative
     offset regardless of how large the wrapper itself renders;
     `left`/`width` on the wrapper itself are the matching
     19.52%/109.17% of the *card's* own box. `top`, unlike those two, is
     *not* the raw Figma figure (-53.67%) — Figma's own heading sits in
     a narrower text column than this site's (this heading runs the
     font up to 5rem, wider per line, and its own two lines bend along
     an arc — see `.challenge-heading-line`'s own comment — whose end
     characters dip down further than flat text would), so the raw
     offset repeatedly landed her head/arm on top of "24-HOUR
     CHALLENGE?" instead of beside it; nudged down to `0%` (level with
     the card's own top edge) until she actually clears it, checked
     directly on a real render, not recomputed from Figma's own numbers
     again.

     A first attempt at this placement used the old
     `challenge-char-cheer-head.png`/`-body.png` exports and had to be
     reverted — their opaque, non-transparent background showed as a
     visible box over two of the stat numbers underneath.
     `dau_nhan_vat.svg`/`tay_phai.svg`/`tay_trai.svg`/`body_nhan_vat.svg`
     are proper transparent re-exports (real alpha, checked directly
     against a magenta test background) of that same head/arm/hand/
     ellipse, which is what actually makes overlapping the white card
     safe this time.

     This wrapper itself carries neither a `transform` nor a `z-index`
     (on purpose — see `.challenge-cheer-head`'s own comment on why),
     only the plain `position: absolute` + percentages needed to place
     it: a `z-index`/`transform` here would make this wrapper establish
     its *own* stacking context, and every one of its children would
     then be trapped inside it — painted as a single unit, always
     either entirely above or entirely below a sibling like the card's
     own `::before`, no matter what `z-index` those children set on
     themselves individually. Per explicit request,
     `.challenge-cheer-hand-left` needs to do exactly the opposite of
     its siblings (rise *above* the card's own white surface while they
     stay sunk *below* it), which is only possible with all four
     sharing this card's own stacking context directly. */
  .ballpit-countdown__challenge-cheer {
    position: absolute;
    left: 19.52%;
    top: -32%;
    width: 109.17%;
    aspect-ratio: 662.88 / 414.91;
    pointer-events: none;
  }

  /* Each piece counter-rotates *itself* against the card's own
     `rotate(-3.17deg)` (rather than the old single shared rotation on
     the now transform-free `.challenge-cheer` wrapper above) so every
     one stays upright the way Figma shows her, not tilted along with
     the card underneath — a side effect of the wrapper no longer being
     allowed a `transform` of its own (see that rule's own comment). */
  .ballpit-countdown__challenge-cheer-head,
  .ballpit-countdown__challenge-cheer-hand-right,
  .ballpit-countdown__challenge-cheer-hand-left,
  .ballpit-countdown__challenge-cheer-body {
    position: absolute;
    height: auto;
    transform: rotate(3.17deg);
  }

  /* These three sink *under* the card's own white surface (`::before`
     on `.challenge-cheering-card`, `z-index: 1`) and its stat numbers
     (`z-index: 2`) — negative so they land below `::before` regardless,
     while keeping their own relative front-to-back order (head in
     front of the arm/ellipse behind it) the way the three of them
     looked before this stacking rework. */
  .ballpit-countdown__challenge-cheer-head {
    left: 30.96%;
    top: -37%;
    width: 51.78%;
    z-index: 0;
  }

  .ballpit-countdown__challenge-cheer-hand-right {
    left: -9%;
    top: -26.19%;
    width: 57.32%;
    z-index: -2;
  }

  /* Per explicit request, rises *above* the card's own white surface
     and stat numbers instead of sinking under them like its three
     siblings — an outright higher `z-index` than both (`::before`'s 1,
     `.challenge-stat`'s 2), which only actually works because the
     wrapper above no longer traps this element inside its own isolated
     stacking context. */
  .ballpit-countdown__challenge-cheer-hand-left {
    left: 51.6%;
    top: 5.54%;
    width: 29.41%;
    z-index: 3;
  }

  .ballpit-countdown__challenge-cheer-body {
    left: 41.11%;
    top: 10%;
    width: 20.07%;
    z-index: -1;
  }

  @media (max-width: 900px) {
    .ballpit-countdown__challenge-cheer {
      display: none;
    }
  }

  .ballpit-countdown__challenge-intro {
    position: relative;
    z-index: 0;
    display: flex;
    flex-direction: column;
    gap: clamp(4.5rem, 7vw, 7.5rem);
    max-width: 1360px;
    margin: 0 auto;
    margin-bottom: clamp(4.5rem, 7vw, 7.5rem);
    z-index: 1;
  }

  .ballpit-countdown__challenge-heading {
    margin: 0;
    line-height: 1.15;
    width: fit-content;
  }

  /* Two-tone per line — checked directly against Figma (node
     2872:19318/2872:19319): "READY FOR"/"SẴN SÀNG CHO" is the dark line,
     "24-HOUR CHALLENGE?"/"THỬ THÁCH 24 GIỜ?" the red one, not one flat
     color across both lines like this used to be. Same split pattern as
     `.ballpit-countdown__who-heading-line` further down this file, just
     this component's own size/colors — the FAQ heading turned out to be
     a single flat one-color line instead (Figma node 3430:12294).

     Each line's own *text* also bends along a gentle arc in Figma — those
     two nodes are "text on a path", not plain text (the Figma API itself
     rejects a design-context fetch on them: "node type not supported"),
     confirmed by sampling the actual rendered Figma screenshot's pixels
     (the topmost ink of each line rises toward the middle, dips at both
     ends). The PHP side (`LandingPageDes2026.php`) renders each line
     through `bpc_render_arc_text()` — the same per-character
     rotate+translateY helper the hero's own heading/highlight already
     use (`ballpit-countdown.php`) — rather than a second implementation,
     just with a gentler angle/dip than that default (6deg/0.08em, not
     10deg/0.16em): this heading's font-size runs up to 5rem, so the same
     *em*-relative dip is far more pixels here, and the hero's own
     numbers visibly dipped "FOR"/"CHALLENGE?" down into the cheering
     character's own space (see `.challenge-cheer`'s own comment on why
     its `top` is what it is). */
  .ballpit-countdown__challenge-heading-line {
    display: inline-block;
    font-family: 'LonlyBop', sans-serif;
    font-weight: 800;
    font-size: clamp(1.05rem, 4.5vw, 5rem);
  }

  .ballpit-countdown__challenge-heading-line--dark {
    color: #54110e;
  }

  .ballpit-countdown__challenge-heading-line--red {
    color: var(--bpc-highlight-color, #fc322a);
  }

  .ballpit-countdown__challenge-stats-row {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    gap: clamp(1rem, 2.5vw, 1.5rem);
    width: 100%;
    margin-bottom: clamp(1.5rem, 4vw, 2.5rem);
  }

  /* Left-aligned, not centered — checked directly against Figma (node
     2872:19283/2872:19284). Figma's own text paragraph here ("Your next
     design challenge is waiting...") is dropped per explicit request —
     this column now holds only the info card. */
  .ballpit-countdown__challenge-desc-card {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: clamp(1.5rem, 3vw, 3rem);
    flex: 1 1 380px;
    text-align: left;
  }

  /* No `overflow: hidden` here (there used to be one, just to clip
     `.challenge-closing`'s own square top corners into this card's own
     rounded ones — that box now carries its own matching radius
     instead, see below) — checked directly against Figma: the badge
     (`.challenge-badge-star`, negative `top`/`right` to pop out past
     this card's own top-right corner) needs to actually render past
     this box's edge, not get clipped by it. */
  .ballpit-countdown__challenge-info-card {
    position: relative;
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: 23rem;
    border-radius: 32px;
    background: #fafafa;
  }

  .ballpit-countdown__challenge-closing {
    background: #e5deff;
    /* Matches `.challenge-info-card`'s own top corners now that the
       card itself no longer clips this box into shape (see that rule's
       own comment) — needed only on top since this box always sits
       flush at the card's own top edge. */
    border-radius: 32px 32px 0 0;
    padding: clamp(1.25rem, 2.5vw, 2rem);
    /* Figma (node 2872:19288): this text, "Apply now", and "View
       Designathon rule" below all use the same 32px display font
       (LonlyBop Bold) as `.challenge-stat-label`'s own 32px cap — this
       rule (and those two) were still on a much smaller Manrope size,
       which read as noticeably undersized/out of balance against the
       rest of this card per explicit report. */
    font-family: 'Manrope', sans-serif;
    font-weight: 700;
    font-size: clamp(1.2rem, 2vw, 1.5rem);
    line-height: 1.25;
    color: #6a4cd3;
    letter-spacing: -3%;
  }

  /* Theme's own `main.min.css` has `body li, body p { font-size: 16px;
     line-height: 26px; }` (both properties, at `min-width: 768px` too) —
     an explicit rule on the `<p>` element itself always beats an
     inherited value from an ancestor's `font-size`/`line-height`
     regardless of that ancestor's own specificity, so both had to be
     neutralized here with `!important` + `unset` (falls back to the
     normal *inherited* value for these two properties, i.e. whatever
     `.challenge-closing` above actually has), not just `font-size` alone
     — leaving `line-height` unset alone still left these two lines
     visibly cramped at the theme's own flat 26px instead of scaling with
     the bigger text. */
  .ballpit-countdown__challenge-closing p {
    margin: 0;
    font-size: unset !important;
    line-height: unset !important;
  }

  .ballpit-countdown__challenge-badge-star {
    position: absolute;
    right: -1.36rem;
    top: -2.03rem;
    width: clamp(3rem, 6vw, 5.32rem);
    height: auto;
    transform: rotate(18.58deg);
    pointer-events: none;
  }

  .ballpit-countdown__challenge-cta-row {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: clamp(1rem, 2.2vw, 1.5rem);
  }

  /* Checked directly against Figma (node 2872:19293/2872:19294/2872:19296):
     "Apply now" is not one pill with the icon inline at its end — it's a
     rounded-rect text button and a separate full-circle icon button
     sitting flush against each other (same purple, no gap), so the pair
     reads as one capsule with a distinctly round right end. */
  .ballpit-countdown__challenge-apply-btn {
    display: flex;
    align-items: stretch;
    width: 100%;
    text-decoration: none;
  }

  .ballpit-countdown__challenge-apply-btn-label {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 1 1 auto;
    min-height: 4rem;
    padding: 0.5rem 1rem;
    border-radius: 2.5rem;
    background: #9476fd;
    /* 24px flat per explicit request — applied consistently to every
       other CTA-pill button's label on this page too (`.partners-cta-
       btn`, `.stats-register-btn`, `.site-header-cta`, and this button's
       own sibling `.challenge-rules-link` below), not just this one. */
    font-family: 'Manrope', sans-serif;
    font-weight: 700;
    font-size: 1.5rem;
    letter-spacing: -0.03em;
    color: #fafafa;
  }
  .ballpit-countdown__challenge-apply-btn-label .ballpit-countdown__cta-char{
    letter-spacing: 0px !important;
  }

  .ballpit-countdown__challenge-apply-btn-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 4rem;
    height: 4rem;
    background: #9476fd;
    border-radius: 999px;
  }

  .ballpit-countdown__challenge-apply-btn-icon img {
    width: 2rem;
    height: 2rem;
    transform: rotate(3.33deg);
  }

  .ballpit-countdown__challenge-rules-link {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 4rem;
    padding: 0.9rem 1rem;
    border-radius: 20px;
    /* 24px flat per explicit request — see `.challenge-apply-btn-label`
       above's own comment. */
    font-family: 'Manrope', sans-serif;
    font-weight: 700;
    font-size: 1.5rem;
    letter-spacing: -0.03em;
    color: #4d4d4d;
    text-decoration: none;
  }

  /* Per explicit request, `.challenge-cheer` (a child of this card, see
     that class's own comment) now sinks *under* this card's own white
     surface instead of drawing on top of it — only the parts of her
     that stick out past this card's own edges (head, hand) should still
     show; the arm crossing over "03"/"24" should not paint over those
     numbers. A child is always painted after its own parent's `background`
     no matter what `z-index` says (a box's background is part of that
     box itself, not a stacking-order participant of its own children) —
     so making that background "beat" a child in paint order means the
     background can't live on this element directly. It's split onto
     `::before` here instead, given a real `z-index` of its own between
     the cheer (behind) and the stat numbers (in front, see
     `.challenge-stat`'s own `position`/`z-index` below). */
  .ballpit-countdown__challenge-cheering-card {
    position: relative;
    flex: 1 1 380px;
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 2.5rem 0.5rem;
    align-content: center;
    justify-items: center;
    padding: clamp(1.5rem, 3vw, 2.5rem);
    border-radius: 40px;
    transform: rotate(-3.17deg) !important;
  }
  .ballpit-countdown__challenge-cheering-card::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 40px;
    background: #fff;
    z-index: 1;
  }

  .ballpit-countdown__challenge-stat {
    position: relative;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1.5rem;
    text-align: center;
  }

  .ballpit-countdown__challenge-stat-num {
    font-family: 'LonlyBopCondensed', sans-serif;
    font-weight: 300;
    font-size: clamp(2.5rem, 8vw, 6.25rem);
    line-height: 1;
    color: #54110e;
  }

  .ballpit-countdown__challenge-stat-label {
    font-family: 'LonlyBop', sans-serif;
    font-weight: 700;
    font-size: clamp(1.25rem, 2.2vw, 2rem);
    letter-spacing: 0.02em;
    color: #54110e;
  }

  /* --- Day 01 / Day 02 carousel ----------------------------------------
     Redesigned per Figma node 3429:6923 (full)/3429:7137 (Day 01)/
     3429:7425 (Day 02) — the old pinned/scroll-scrubbed road+date-card
     system above is gone entirely; this is now a click-through carousel,
     one slide per day, each slide a colored rounded panel with a
     sticker-outline "DAY 0N"/date tag straddling its own top edge and a
     3x2 grid of schedule cards, plus shared prev/next arrows + a dot
     indicator below. `initChallengeCarousel()` (ballpit-countdown.js)
     drives the actual crossfade+slide transition with a GSAP timeline —
     per explicit request for a more polished/professional feel than a
     plain instant class swap. */
  .ballpit-countdown__challenge-carousel {
    position: relative;
    width: 100%;
    max-width: 1360px;
    margin: 0 auto clamp(1.5rem, 4vw, 2.5rem);
  }

  /* JS sets this to the active slide's own measured height (and tweens it
     to the next slide's height as part of the same GSAP timeline) since
     both slides are `position: absolute` below — taken out of flow so
     they can sit stacked on top of each other mid-transition — which
     would otherwise collapse this wrapper to zero height. */
  .ballpit-countdown__challenge-carousel-track {
    position: relative;
  }

  /* Both slides stay `position: absolute` even at rest (not just mid-
     transition) so `initChallengeCarousel()` can always tween between
     them without a layout jump the instant a transition starts. `.slide`
     itself still gets a `display: none`/`.is-active` fallback for the
     no-JS/`prefers-reduced-motion` case, where the JS swaps `display`
     directly instead of animating. */
  /* `top`/`left`/`right` only — deliberately no `bottom` (i.e. not
     `inset: 0`). This wrapper (`.carousel-track`) has no height of its
     own beyond what JS assigns it, and an absolutely positioned box with
     *both* `top` and `bottom` pinned needs its containing block's height
     to already be definite to resolve that — with none of that height
     set yet, the browser has nothing to resolve `bottom: 0` against and
     the slide collapses to 0px (confirmed directly: `getBoundingClientRect()`
     came back all-zero). Without `bottom`, height instead falls out of
     this slide's own content, which is exactly what `measureHeight()` in
     ballpit-countdown.js needs to read. */
  .ballpit-countdown__challenge-carousel-slide {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    display: none;
  }

  .ballpit-countdown__challenge-carousel-slide.is-active {
    display: block;
  }

  /* Blue for Day 01 (`#b4dbfe`), green for Day 02 (the `--green` modifier
     below) — checked directly against Figma's own two panel exports.
     `overflow: hidden` clips the dot pattern/decor blob to this panel's
     own rounded corner — the sticker tag is a *sibling* of this panel
     (see the PHP markup's own comment), not a child, specifically so
     this clip doesn't also cut off the tag's own top half straddling the
     edge above it (an earlier version nested the tag in here and had
     exactly that bug, reported directly via screenshot). */
  .ballpit-countdown__challenge-carousel-panel {
    position: relative;
    padding: clamp(1.75rem, 5vw, 4rem);
    border-radius: 40px;
    background-color: #b4dbfe;
    overflow: hidden;
  }

  .ballpit-countdown__challenge-carousel-slide--green .ballpit-countdown__challenge-carousel-panel {
    background-color: #d7f7d6;
  }

  /* Figma's own "BG pattern" fill (node 3429:7140/3429:7428) — a flat
     white-dot-on-transparent export, same asset for both days (the panel's
     own colored `background-color` shows through the gaps). `left`/
     `width` reproduce that node's own metadata (x: -102, width: 1440,
     against this 1236-wide panel) so the dot grid's own phase lines up
     with Figma exactly instead of restarting at this panel's own edge. */
  .ballpit-countdown__challenge-carousel-bg-dots {
    position: absolute;
    z-index: 0;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    object-fit: cover;

  }

  /* Large soft corner blob, mostly bleeding off-canvas — Figma's own
     decorative accent behind each panel's grid, exported per day
     (`challenge-carousel-decor-day1/2.svg`). `left`/`top`/`width`/
     `height` below are that same vector's own Figma metadata (x/y/w/h
     within this 1236x546 panel) converted straight to percentages, same
     technique already used for the cheer character's own union box —
     the rotated image is centered inside that box via flex rather than
     sized/positioned directly, matching how Figma itself nests it. */
  .ballpit-countdown__challenge-carousel-decor {
    position: absolute;
    z-index: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    opacity: 0.5;
  }

  .ballpit-countdown__challenge-carousel-decor img {
    display: block;
    height: auto;
  }

  .ballpit-countdown__challenge-carousel-slide--blue .ballpit-countdown__challenge-carousel-decor {
    left: 67.4%;
    top: -80.6%;
    width: 68.1%;
    height: 243.5%;
  }

  .ballpit-countdown__challenge-carousel-slide--blue .ballpit-countdown__challenge-carousel-decor img {
    width: 83.1%;
    transform: rotate(6.73deg);
  }

  .ballpit-countdown__challenge-carousel-slide--green .ballpit-countdown__challenge-carousel-decor {
    left: 69.3%;
    top: 9.7%;
    width: 42.2%;
    height: 121.3%;
  }

  .ballpit-countdown__challenge-carousel-slide--green .ballpit-countdown__challenge-carousel-decor img {
    width: 79.3%;
    transform: rotate(-11.28deg);
  }

  /* Sticker tag straddling the panel's own top edge. `top: -8.6%` is
     Figma's own number for this exact node (3429:7185): its frame sits at
     `y: -47` against this 546px-tall panel (`-47 / 546 = -8.6%`) —
     replaces an earlier `top: 0` + `translateY(-55%)` guess (eyeballed
     against a render, not the actual Figma metadata) once this node's
     real numbers were pulled via `get_metadata`. Horizontal centering
     (`left: 50%` + `translateX(-50%)`) already matched Figma's own
     near-dead-center placement (the frame's own x/width put its center
     0.3px off panel-center — close enough to call centered). */
  .ballpit-countdown__challenge-carousel-tag {
    position: absolute;
    top: -11.6%;
    left: 50%;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.1rem;
    transform: translateX(-50%);
  }

  /* Figma-exported sticker artwork (exact letterforms, curve and spacing —
     see challenge-carousel-tag-day{1,2}-en.svg), used for both languages
     per explicit request rather than generating a separate Vietnamese
     version. Width matches this node's own 225.4px measured against the
     1236px-wide reference panel (~18.2%). */
  .ballpit-countdown__challenge-carousel-tag-image {
    display: block;
    width: clamp(11rem, 18vw, 15.5rem);
    height: auto;
  }

  .ballpit-countdown__challenge-carousel-grid {
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: clamp(0.75rem, 2vw, 1.25rem);
  }

  @media (max-width: 900px) {
    .ballpit-countdown__challenge-carousel-grid {
      grid-template-columns: repeat(2, 1fr);
    }
  }

  @media (max-width: 600px) {
    .ballpit-countdown__challenge-carousel-grid {
      grid-template-columns: 1fr;
      gap: 1.25rem; /* 20px, Figma mobile node 3703:12391 */
    }

    /* `top` above is a % of `.carousel-slide`'s own height, fine on desktop
       where the 3x2 grid keeps that height close to the panel's own
       reference (546px) — but stacking every schedule card into this one
       column makes the slide (and the %) grow with however many items
       there are, dragging the tag up into whatever sits above the carousel
       instead of just straddling the panel's own top edge. A fixed offset
       (Figma's own -47px at the 546px reference) stays put regardless of
       how tall the stacked column ends up. */
    .ballpit-countdown__challenge-carousel-tag {
      top: -7.9rem;
    }
  }

  /* Grid items default-stretch to their row's tallest sibling (plain CSS
     Grid behavior) — matches Figma, where a row holding a two-line
     "Milestone"+caption card is taller than its one-line neighbors and
     all three in that row share that height. */
  .ballpit-countdown__challenge-carousel-item {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
    padding: 1.5rem;
    border-radius: 36px;
    background: #fff;
  }

  .ballpit-countdown__challenge-carousel-pill {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 4rem;
    padding: 0.25rem 1rem;
    border-radius: 66px;
    background: #1d92fd;
    font-family: 'LonlyBop', sans-serif;
    font-weight: 700;
    font-size: clamp(1.25rem, 2.4vw, 2rem);
    letter-spacing: 0.02em;
    color: #fafafa;
    text-align: center;
    white-space: nowrap;
  }

  .ballpit-countdown__challenge-carousel-slide--green .ballpit-countdown__challenge-carousel-pill {
    background: #86e783;
    color: #171717;
  }

  .ballpit-countdown__challenge-carousel-item-body {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.8rem;
    text-align: center;
  }

  .ballpit-countdown__challenge-carousel-item-title {
    margin: 0;
    font-family: 'Manrope', sans-serif;
    font-weight: 700;
    font-size: clamp(1.125rem, 1.8vw, 1.5rem);
    letter-spacing: -0.03em;
    color: #4d4d4d;
  }

  .ballpit-countdown__challenge-carousel-item-desc {
    margin: 0;
    font-family: 'Manrope', sans-serif;
    font-weight: 500;
    font-size: clamp(0.875rem, 1.3vw, 1rem);
    letter-spacing: 0.02em;
    color: #737373;
  }

  /* Present but invisible (`opacity`, not `display: none`) — see the PHP
     template's own comment on `bpc_render_challenge_carousel_item()`:
     this line's height still needs to count so every card (Day 01's own
     one-line items included) ends up the same height as its two-line
     siblings, matching Figma and keeping both slides' grids — and so the
     whole page below this carousel — the same height on every switch. */
  .ballpit-countdown__challenge-carousel-item-desc--hidden {
    opacity: 0;
  }

  .ballpit-countdown__challenge-carousel-pagination {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: clamp(1rem, 3vw, 2.5rem);
    margin-top: clamp(1.5rem, 3vw, 2rem);
  }

  .ballpit-countdown__challenge-carousel-arrow {
    display: flex;
    flex-shrink: 0;
    align-items: center;
    justify-content: center;
    width: 4rem;
    height: 4rem;
    padding: 0;
    border: none;
    border-radius: 999px;
    background: #1d92fd;
    cursor: pointer;
  }

  .ballpit-countdown__challenge-carousel-arrow img {
    width: 2.5rem;
    height: 2.5rem;
  }

  /* Same arrow asset for both buttons, same as Figma's own reuse — only
     the prev button rotates it 180deg rather than exporting a mirrored
     twin. */
  .ballpit-countdown__challenge-carousel-arrow--prev img {
    transform: rotate(180deg);
  }

  .ballpit-countdown__challenge-carousel-dots {
    display: flex;
    align-items: center;
    gap: 0.75rem;
  }

  .ballpit-countdown__challenge-carousel-dot {
    width: 1rem;
    height: 1rem;
    border-radius: 999px;
    background: #d4d4d4;
    cursor: pointer;
  }

  .ballpit-countdown__challenge-carousel-dot.is-active {
    background: #171717;
  }

  /* --- Challenge section mobile (Figma node 3703:12377, "Mobile
     Breakpoint") — flat sizes lifted from that dedicated mobile mockup,
     not points on the shared desktop `clamp()` curves above (those floor
     out well under these targets at phone widths). Same `!important`
     rationale as `.faq`'s own mobile block above: a later same-selector
     rule this deep inside a nested `@media` still loses to an earlier one
     outside it without it. */
  @media (max-width: 767px) {
    .ballpit-countdown__challenge-heading {
      margin: 0 auto;
      text-align: center;
    }

    /* Extra breathing room above the "DAY 01" sticker, per explicit
       feedback that the stats card's own bottom edge and the carousel's
       negative-offset tag (see that rule's own mobile comment) sat too
       close together. This margin collapses with `.carousel`'s own
       `margin-top: 0` (adjoining sibling margins take the larger of the
       two, not their sum) — bump it here on the actual larger side
       instead of on the carousel, where it'd have no effect. */
    .ballpit-countdown__challenge-intro {
      margin-bottom: 10rem;
    }

    .ballpit-countdown__challenge-heading-line {
      font-size: 2.25rem !important; /* 36px */
    }

    .ballpit-countdown__challenge-desc-card {
      align-items: center;
      text-align: center;
    }

    .ballpit-countdown__challenge-closing {
      padding: 2rem !important; /* 32px */
      font-size: 1.75rem !important; /* 28px */
      text-align: center;
    }

    .ballpit-countdown__challenge-badge-star {
      width: 4.2rem !important; /* 67px */
    }

    .ballpit-countdown__challenge-cta-row {
      padding: 1.5rem !important; /* 24px */
    }

    .ballpit-countdown__challenge-apply-btn-label,
    .ballpit-countdown__challenge-rules-link {
      font-size: 1.5rem !important; /* 24px */
    }

    /* Flat, not tilted — Figma's mobile stats card sits square instead of
       rotated like the desktop version. */
    .ballpit-countdown__challenge-cheering-card {
      padding: 2.5rem !important; /* 40px */
      transform: none;
    }

    .ballpit-countdown__challenge-stat-num {
      font-size: 4rem !important; /* 64px */
    }

    .ballpit-countdown__challenge-carousel-panel {
      padding: 1rem !important; /* 16px */
    }

    .ballpit-countdown__challenge-carousel-item {
      padding: 1rem !important; /* 16px */
    }

    .ballpit-countdown__challenge-carousel-pill {
      font-size: 2rem !important; /* 32px */
    }

    .ballpit-countdown__challenge-carousel-item-title {
      font-size: 1.5rem !important; /* 24px */
    }

    .ballpit-countdown__challenge-carousel-item-desc {
      font-size: 1rem !important; /* 16px */
    }

    /* Not a click-through slide on mobile — Figma's own mobile mockup
       (node 3703:12378) shows Day 01 and Day 02 both stacked in one
       column, no prev/next arrows or dots. Both `.carousel-slide`s stay
       `position: relative` (not `static`) rather than losing their
       positioning context entirely, since `.carousel-tag`'s own `top`
       offset (its `position: absolute`) needs to keep resolving against
       its own slide/panel, not against the shared track once it's no
       longer the tag's nearest positioned ancestor. */
    .ballpit-countdown__challenge-carousel-track {
      height: auto !important;
      display: flex;
      flex-direction: column;
      gap: 10.6875rem;
    }

    .ballpit-countdown__challenge-carousel-slide {
      position: relative !important;
      display: block !important;
    }

    .ballpit-countdown__challenge-carousel-pagination {
      display: none;
    }
  }

  /* --- "Who is Designathon for?" ---------------------------------------
     Figma node 3191:6618 ("TA") — a normal-flow section between
     Challenge and FAQ, purple background, two-tone arc heading on the
     left, a smaller (barely-curved) heading + paragraph on the right,
     and three staggered profile cards below. */
  .ballpit-countdown__who {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: clamp(2.5rem, 6vw, 4rem);
    width: 100%;
    padding: clamp(2rem, 6vw, 5rem) clamp(1rem, 4vw, 4rem) clamp(3rem, 8vw, 6rem);
    background: #7f5bfd;
  }

  .ballpit-countdown__who-intro {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: clamp(1.5rem, 4vw, 3rem);
    max-width: 1360px;
    width: 100%;
    margin: 0 auto;
  }

  .ballpit-countdown__who-heading {
    margin: 0;
    line-height: 1.15;
  }

  /* Same `bpc_render_arc_text()` per-character bend as the Challenge
     heading (see that component's own comment on
     `.challenge-heading-line`) — just this section's own size/colors:
     checked directly against Figma, "WHO IS" is white, "DESIGNATHON
     FOR?" the accent yellow, not two shades of the same color. */
  .ballpit-countdown__who-heading-line {
    display: inline-block;
    font-family: 'LonlyBop', sans-serif;
    font-weight: 800;
    font-size: clamp(1.05rem, 4.5vw, 5rem);
  }

  .ballpit-countdown__who-heading-line--white {
    color: #fafafa;
  }

  .ballpit-countdown__who-heading-line--yellow {
    color: #ffd366;
  }

  .ballpit-countdown__who-side {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 1.5rem;
    max-width: 26.6rem;
    text-align: right;
    padding-top: 0.5rem;
  }

  .ballpit-countdown__who-side-heading {
    margin: 0;
    line-height: 1.25;
  }

  /* Also arc text (see `.who-heading-line`'s own comment above) but a
     much gentler bend — checked directly against Figma: this heading's
     own path has a huge radius relative to how little text sits on it,
     so it reads as barely curved, not the pronounced bend the big left
     heading gets. */
  /* Targets the *inner* span, not the `[data-bpc-lang]` one that wraps
     it — see that markup's own comment (LandingPageDes2026.php) for why
     this can't set `display` directly on the language-toggle span
     itself without fighting that rule on specificity. */
  .ballpit-countdown__who-side-heading-text {
    display: inline-block;
    font-family: 'LonlyBop', sans-serif;
    font-weight: 800;
    font-size: clamp(1.5rem, 3vw, 2.5rem);
    color: #fafafa;
  }

  .ballpit-countdown__who-side-text {
    margin: 0;
    font-family: 'Manrope', sans-serif;
    font-weight: 600;
    font-size: clamp(1rem, 1.6vw, 1.25rem);
    line-height: 1.4;
    letter-spacing: 0.2px;
    color: #fafafa;
  }

  .ballpit-countdown__who-cards {
    display: flex;
    flex-wrap: wrap;
    /* Figma: all 3 cards share one common height regardless of how much
       each one's own description text wraps to (not `flex-start`, which
       let each card size to just its own content — obvious once several
       are lined up together, as in a horizontal mobile row). */
    align-items: stretch;
    gap: clamp(1.5rem, 3vw, 2rem);
    max-width: 1360px;
    width: 100%;
    margin: 0 auto;
  }

  /* Transparent wrapper around each `.who-card` — exists only so mobile
     (see the `max-width: 767px` block below) has a real flex item per
     card to snap-scroll a single one at a time onto; `display: contents`
     removes it from the box tree entirely everywhere else, so it has no
     effect on this desktop peek-row layout (the offset stagger margins
     still apply directly to `.who-card`, unaffected by the wrapper). */
  .ballpit-countdown__who-card-slide {
    display: contents;
  }

  /* Mobile-only pagination dots (Figma node 3768:2132) — meaningless on
     this desktop peek-row layout, which has no single "active" card, so
     hidden here and only switched on inside the mobile media query. */
  .ballpit-countdown__who-dots {
    display: none;
  }

  /* The staggered "waterfall" look — checked directly against Figma
     (each card sits further down *and* right than the last) — done as
     an increasing `margin-top` per card rather than reproducing the
     exact absolute px Figma placed them at, so it still staggers
     sensibly at viewport widths Figma's own fixed-width layout never
     had to handle. Collapses to `0` below `.who-cards`'s own wrap
     breakpoint (see the media query further down) since a single
     column of evenly-stacked cards reads better once they're no longer
     side by side. */
  /* Figma's own stagger is uneven, not a steady step per card — card 2
     sits only ~11px below card 1, then card 3 drops a further ~84px
     below *that* (~95px total) — not the evenly-doubled 48px/96px this
     used before. */
  .ballpit-countdown__who-card--offset-1 {
    margin-top: clamp(0.5rem, 1vw, 0.75rem);
  }

  .ballpit-countdown__who-card--offset-2 {
    margin-top: clamp(3rem, 8vw, 6rem);
  }

  .ballpit-countdown__who-card {
    position: relative;
    flex: 1 1 320px;
    max-width: 26.6rem;
    display: flex;
    flex-direction: column;
    border-radius: 40px;
    background: #fff;
    height: fit-content;
  }

  /* No `overflow: hidden` here — checked directly against Figma: each
     card's own photo bleeds up past this header's top-right corner, the
     same "pop out past the rounded corner" technique as
     `.challenge-badge-star`. The header below carries its *own* top
     radius instead of relying on this card clipping it into shape (same
     fix as `.challenge-info-card`'s own comment), which is what actually
     leaves the photo free to bleed past it. */
  .ballpit-countdown__who-card-header {
    position: relative;
    display: flex;
    align-items: center;
    min-height: clamp(5rem, 9vw, 7.5rem);
    padding: clamp(1rem, 2vw, 1.5rem) clamp(1.5rem, 3vw, 2rem);
    border-radius: 40px 40px 0 0;
  }

  .ballpit-countdown__who-card-header--blue {
    background: #1d92fd;
  }

  .ballpit-countdown__who-card-header--green {
    background: #70c06d;
  }

  .ballpit-countdown__who-card-header--red {
    background: #fc322a;
  }

  .ballpit-countdown__who-card-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.75rem 1.25rem;
    border-radius: 999px;
    background: #f6f1e4;
    font-family: 'Manrope', sans-serif;
    font-weight: 700;
    font-size: clamp(1.1rem, 1.8vw, 1.6rem);
    letter-spacing: -0.03em;
    /* Figma (e.g. 3631:12114, "0 - 2 years"): `icon/primary-dark-900`
       (#54110e), not #171717. */
    color: #54110e;
    white-space: nowrap;
  }

  .ballpit-countdown__who-card-photo {
    position: absolute;
    top: -1.75rem;
    right: -1rem;
    width: clamp(8rem, 16vw, 11rem);
    aspect-ratio: 3 / 2;
    object-fit: cover;
    border-radius: 16px;
    transform: rotate(3.31deg);
    box-shadow: 4px 6px 10px rgba(0, 0, 0, 0.2);
    pointer-events: none;
  }

  .ballpit-countdown__who-card-body {
    /* Not inherited `center` (from further up the tree) — Figma's own
       title/desc text is left-aligned (`items-start` in a flex column),
       same as `.benefits-card-body`'s equivalent text. */
    text-align: left;
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
    padding: clamp(1.5rem, 3vw, 2rem);
  }

  .ballpit-countdown__who-card-title {
    /* Figma (node 3430:12811): `font-family/body` (Manrope Bold), not
       the display/LonlyBop face used for the big arc headlines —
       confirmed by the reference render, a clean geometric sans, not
       LonlyBop's hand-wobbly letterforms. Matches `.benefits-card-
       header p`'s own title styling (same card pattern, same font/
       color) elsewhere in this file. */
    margin: 0;
    font-family: 'Manrope', sans-serif;
    font-weight: 700;
    font-size: 1.5rem;
    line-height: 1.15;
    letter-spacing: -0.03em;
    color: #4a445e;
    text-transform: capitalize;
  }

  .ballpit-countdown__who-card-desc {
    margin: 0;
    font-family: 'Manrope', sans-serif;
    font-weight: 500;
    font-size: 1rem;
    line-height: 1.3;
    letter-spacing: 0.32px;
    color: #171717;
  }

  @media (max-width: 900px) {
    .ballpit-countdown__who-intro {
      flex-direction: column;
      align-items: center;
    }

    .ballpit-countdown__who-side {
      align-items: flex-start;
      text-align: left;
    }

    .ballpit-countdown__who-card--offset-1,
    .ballpit-countdown__who-card--offset-2 {
      margin-top: 0;
    }
  }

  @media (max-width: 767px) {
    /* Figma's dedicated mobile mockup (node 3469:19155) shows this
       heading around 40px ("Mobile/Display") — the shared clamp's own
       `4.5vw` slope bottoms out at its 1.05rem floor by this width, same
       recurring pattern as `.faq-heading`/`.partners-heading-line`
       elsewhere in this file. */
    .ballpit-countdown__who-heading-line {
      font-size: 2.5rem;
    }

    /* Figma: this side block (heading + paragraph) is *centered* at
       mobile, not left-aligned like the `@media (max-width: 900px)` rule
       above sets it (that one's tuned against a wider tablet-ish
       breakpoint, not this dedicated narrow mockup) — overrides it back
       to centered here. Also fixes the side-heading's own size (Figma:
       28px, the shared clamp is close but not exact at this width) and
       the paragraph's weight/tracking (Figma: Manrope *Medium* 500 at
       0.32px — this carries a bolder 600/0.2px from its shared desktop
       rule instead). */
    .ballpit-countdown__who-side {
      align-items: center;
      text-align: center;
    }

    .ballpit-countdown__who-side-heading-text {
      font-size: 1.75rem;
    }

    .ballpit-countdown__who-side-text {
      font-weight: 500;
      letter-spacing: 0.32px;
    }

    /* Figma's updated mobile mockup (node 3768:2132) reorders this
       section: heading, then the card slider, then this side block
       (heading + paragraph) last — the opposite of the DOM (side block
       is still markup-adjacent to the heading, inside `.who-intro`, for
       desktop's side-by-side layout). Reordered visually via flex
       `order` rather than in markup —
       `display: contents` here flattens `.who-intro` out of the box tree
       so its two children become direct flex items of `.who` (already
       `display: flex; flex-direction: column`) alongside `.who-cards`,
       letting all three share one `order` sequence instead of being
       stuck in two separate flex contexts. Reported directly ("đổi vị
       trí item"). */
    .ballpit-countdown__who-intro {
      display: contents;
    }

    .ballpit-countdown__who-heading {
      order: 1;
    }

    .ballpit-countdown__who-cards {
      order: 2;
    }

    /* Same `order: 2` as `.who-cards` (not its own step) — ties resolve
       by DOM position, and this sits right after `.who-cards` there, so
       it lands directly under it without needing a `2.5`-style value. */
    .ballpit-countdown__who-dots {
      order: 2;
    }

    .ballpit-countdown__who-side {
      order: 3;
    }

    /* Figma's updated mobile mockup (node 3768:2132) also swaps the
       "slide style": no more a peek row showing a sliver of the next
       card (the old `78vw` cards side by side) — now a real one-card-
       at-a-time slider with a dot indicator below it, checked directly
       off that mockup (solid background on either side of the visible
       card, no peek at all) and its exported dot SVG (white circles,
       inactive ones at 23% opacity). Reported directly ("đổi kiểu
       slide"). Still the same underlying technique as before — a real
       drag/swipe-able `overflow-x: auto` scroller, same as `.benefits-
       row`/`.stats-pills` elsewhere in this file, just switched from
       `proximity` to `mandatory` snapping now that each snap point is a
       full-width slide instead of an arbitrary card edge. */
    .ballpit-countdown__who-cards {
      flex-wrap: nowrap;
      overflow-x: auto;
      -webkit-overflow-scrolling: touch;
      scroll-snap-type: x mandatory;
      scrollbar-width: none;
      -ms-overflow-style: none;
      gap: 0;
      /* Setting only `overflow-x` forces `overflow-y` to compute as `auto`
         too (spec) — same recurring bug as `.benefits-row` elsewhere in
         this file, and it was clipping `.who-card-photo`'s own upward
         bleed past the card's top edge. This padding/negative-margin pair
         reserves that room *inside* the row's own box instead, without
         visually shifting the cards down. */
      padding-top: 2.5rem;
      margin-top: -2.5rem;
    }

    .ballpit-countdown__who-cards::-webkit-scrollbar {
      display: none;
    }

    /* Each slide reserves the *entire* row width as its own snap point
       (not just its card's `78vw`) and centers the card inside that —
       what actually removes the old peek: the next card sits a full
       slide-width away instead of right up against this one. */
    .ballpit-countdown__who-card-slide {
      display: flex;
      flex: 0 0 100%;
      width: 100%;
      justify-content: center;
      scroll-snap-align: center;
    }

    .ballpit-countdown__who-card {
      flex: 0 0 auto;
      width: 78vw;
      max-width: 20rem;
    }

    /* Dot indicator (Figma node 3768:2132) — `initWhoCardsCarousel()`
       (ballpit-countdown.js) toggles `.is-active` to match whichever
       slide is centered in `.who-cards` and scrolls to a slide on click;
       the base rule (above the `900px` media query) hides this whole row
       on desktop, where the peek layout has no single "active" card. */
    .ballpit-countdown__who-dots {
      display: flex;
      justify-content: center;
      align-items: center;
      gap: 0.3125rem; /* 5px — Figma's own 13px dot pitch minus the 8px dot */
      margin-top: -1.25rem; /* 20px */
    }

    .ballpit-countdown__who-dot {
      width: 0.5rem; /* 8px */
      height: 0.5rem;
      border-radius: 999px;
      background: rgba(255, 255, 255, 0.23);
      flex-shrink: 0;
      cursor: pointer;
    }

    .ballpit-countdown__who-dot.is-active {
      background: #fff;
    }
  }
}
/* `.ballpit-countdown {` (opened near the top of this file) closes here —
   pre-existing: this was already the last rule in the file before the
   sections below were added, so the missing brace was silently
   auto-closed at EOF by every browser with no visible effect; appending
   more rules after it is what would have made the gap real (everything
   below nested one level inside `.ballpit-countdown` instead of being
   the plain top-level rules the comments below describe). */

/* ======================================================================
   Gallery (Figma node 3430:12686, "IMG slider") — masked into an arch
   (`gallery-arc-mask.svg`, the real Figma source shape — its top edge
   rises toward the horizontal center, which is why the "middle" of the
   visible strip always reads taller than the edges regardless of which
   photo is scrolled under it). Plain selectors here (not nested under
   `.ballpit-countdown`) since everything below reuses that class's own
   cascaded base styles (line-height, box-sizing, etc.) through normal
   DOM inheritance rather than through this file's nesting syntax.
   `.gallery-track`'s own horizontal motion is entirely GSAP-driven
   (`initGalleryScrollSlider()`, ballpit-countdown.js — a continuously
   looping strip whose speed/direction react to live scroll velocity),
   so there's no CSS `animation` on it below; nothing here pins or
   switches to `position: fixed` either. */
.ballpit-countdown__gallery {
  position: relative;
  width: 100%;
  /* Its own exact fill per Figma (`bg-[#f0e7ce]`) — close to, but not
     the same swatch as, `.ballpit-countdown__challenge`'s `#efe6cd`. */
  background: #f0e7ce;
  padding: clamp(2rem, 5vw, 4rem) 0 clamp(4rem, 10vw, 7rem);
  overflow: hidden;
}

.ballpit-countdown__gallery-viewport {
  position: relative;
  width: 100%;
  height: clamp(11rem, 26vw, 26rem);
  overflow: hidden;
  /* Inlined as a data URI (the file itself is a tiny 352-byte path,
     `gallery-arc-mask.svg`, downloaded verbatim from the Figma source)
     rather than referenced by `url()` — an external mask resource was
     silently never applying in testing here (renders fine as a plain
     `<img>`, just not as a mask source), while the inlined version is
     unaffected by whatever that load-timing quirk was. */
  -webkit-mask-image: url("data:image/svg+xml;base64,PHN2ZyBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJub25lIiBvdmVyZmxvdz0idmlzaWJsZSIgc3R5bGU9ImRpc3BsYXk6IGJsb2NrOyIgd2lkdGg9IjE0NTYiIGhlaWdodD0iNDUxIiB2aWV3Qm94PSIwIDAgMTQ1NiA0NTEiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGlkPSJWZWN0b3IgNDA3NSIgZD0iTTczMCAzNjJDNDE3LjIgMzYyIDExMyA0MjEuMzMzIDAgNDUxVjg0QzEzMSA1NiAyODUuNSAwIDczMCAwQzExNDguNSAwIDEzMjYuMzMgNTYgMTQ1NiA4NFY0NTFDMTM0NC4zMyA0MjEuMzMzIDEwNDIuOCAzNjIgNzMwIDM2MloiIGZpbGw9IiM3RjVCRkQiLz4KPC9zdmc+Cg==");
  mask-image: url("data:image/svg+xml;base64,PHN2ZyBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJub25lIiBvdmVyZmxvdz0idmlzaWJsZSIgc3R5bGU9ImRpc3BsYXk6IGJsb2NrOyIgd2lkdGg9IjE0NTYiIGhlaWdodD0iNDUxIiB2aWV3Qm94PSIwIDAgMTQ1NiA0NTEiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGlkPSJWZWN0b3IgNDA3NSIgZD0iTTczMCAzNjJDNDE3LjIgMzYyIDExMyA0MjEuMzMzIDAgNDUxVjg0QzEzMSA1NiAyODUuNSAwIDczMCAwQzExNDguNSAwIDEzMjYuMzMgNTYgMTQ1NiA4NFY0NTFDMTM0NC4zMyA0MjEuMzMzIDEwNDIuOCAzNjIgNzMwIDM2MloiIGZpbGw9IiM3RjVCRkQiLz4KPC9zdmc+Cg==");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  -webkit-mask-position: center;
  mask-position: center;
}

@media (max-width: 767px) {
  .ballpit-countdown__gallery-viewport {
    /* Per explicit request: bigger photos, less curve. `mask-size:
       100% 100%` above stretches the arch mask (native ratio 1456:451
       = 3.23) to fit whatever box it's given — at this width that box
       was noticeably squarer (375:176 = 2.13) than the mask's own
       proportions, which reads as a much steeper/deeper arch than
       Figma's. Taller box first (13rem vs. the clamp's 11rem floor —
       "bigger"), then a wider mask (180% of the box's own width, not
       100% — "less curve"): 375px × 1.8 ÷ 13rem(208px) ≈ 3.25, almost
       exactly the mask's native ratio, so the visible curve reads at
       close to its original flatness again despite the box itself
       being squarer than that. */
    height: 17rem !important;
    -webkit-mask-size: 180% 100% !important;
    mask-size: 180% 100% !important;
  }
}

.ballpit-countdown__gallery-track {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  gap: clamp(0.75rem, 1.6vw, 1.5rem);
  width: max-content;
}

.ballpit-countdown__gallery-photo {
  flex-shrink: 0;
  height: 100%;
  width: auto;
  aspect-ratio: 800 / 480;
  object-fit: cover;
  border-radius: 8px;
  display: block;
}

/* ======================================================================
   Prizes (Figma node 3430:12699, "More than one way to win") — first of
   five sections sharing one unbroken purple backdrop (Prizes / Benefits /
   Who / Partners / Stats all `background: #7f5bfd`, no seam between
   them); only this one carries the dome bulging up over Gallery's tail,
   same technique as `.ballpit-countdown__challenge::before`. Decorative
   layers below (glow/spotlight/road/confetti) are real Figma-exported
   assets positioned as percentages of the section's own 1440px-wide
   Figma canvas, each `pointer-events:none` and stacked at `z-index:0`
   (below the heading/card/nav content) — `mix-blend-mode:color-dodge`
   on the spotlight and the blur on both glows are baked into the SVGs
   themselves / applied as plain CSS, not reproduced by hand. */
.ballpit-countdown__prizes {
  /* Thin unclipped shell around `.prizes-inner` (below) — exists purely
     so `::before`'s dome can bulge up *over* Gallery's tail. It used to
     live directly on this element with `overflow: hidden` set here too,
     which silently clipped it away: `bottom: 100%` puts the dome
     entirely outside this box, and an overflow-hidden box clips an
     absolutely-positioned descendant the instant it steps outside that
     box's own edge, regardless of *why* it stepped outside. Everything
     that actually needs clipping (confetti/glow/spotlight bleeding
     above their own edges) now lives on `.prizes-inner` instead, so
     moving the dome here didn't just uncover it — it stopped clipping
     it in the first place. */
  position: relative;
  width: 100%;
}

.ballpit-countdown__prizes-inner {
  position: relative;
  width: 100%;
  background: #7f5bfd;
  padding: clamp(1rem, 3vw, 2rem) clamp(1rem, 4vw, 4rem) clamp(3rem, 7vw, 5.5rem);
  overflow: hidden;
  text-align: center;
  min-height: 100vh;
}

.ballpit-countdown__prizes::before {
  content: '';
  position: absolute;
  left: 50%;
  /* Flush with `.prizes-inner`'s own top edge (100%, not e.g. 90%) —
     anything less leaves a gap between this dome and the solid purple
     below it, showing Gallery's cream through the seam. */
  bottom: 80%;
  transform: translateX(-50%);
  width: 140vw;
  height: 18vw;
  border-radius: 50% 50% 0 0 / 100% 100% 0 0;
  background: #7f5bfd;
  pointer-events: none;
}

.ballpit-countdown__prizes-glow-top,
.ballpit-countdown__prizes-glow-bottom,
.ballpit-countdown__prizes-road,
.ballpit-countdown__prizes-spotlight,
.ballpit-countdown__prizes-confetti {
  position: absolute;
  z-index: 0;
  max-width: none;
  pointer-events: none;
}

.ballpit-countdown__prizes-glow-top {
  left: 50%;
  top: -8.5vw;
  transform: translateX(-50%);
  width: 100vw;
  min-width: 100vw;
  z-index: 1;
}

.ballpit-countdown__prizes-glow-bottom {
    left: -29%;
    top: 24.5vw;
    width: 170vw;
    min-width: 170vw;
    height: 80vh;
    z-index: 1;
}

.ballpit-countdown__prizes-road {
    left: -10%;
    top: 33%;
    width: 130vw;
    min-width: 130vw;
    z-index: 1;

}

.ballpit-countdown__prizes-spotlight {
  left: 4%;
  top: -2.2vw;
  width: 92%;
  min-width: 1200px;
  mix-blend-mode: color-dodge;
}

.ballpit-countdown__prizes-confetti {
  left: 50%;
  top: -20.6vw;
  transform: translateX(-50%);
  width: 100%;
  min-width: 1440px;
  z-index: 1;
}

@media (max-width: 1024px) {
  /* All five of these are actually still present in Figma's own mobile
     mockup (node 3469:19056) — confirmed directly, not assumed — just
     repositioned/rescaled from the desktop numbers above (some, like
     `.prizes-spotlight`'s `min-width: 1200px`, are hard desktop pixel
     floors that would otherwise force this same width at *any*
     viewport, including a 375px phone). A previous pass here just
     hid three of the five outright instead of re-deriving their mobile
     numbers, which is why they were missing entirely. Every value
     below is `(Figma px offset ÷ 375 mobile frame width) × 100`,
     matching whichever unit (`%` vs `vw`) that element's own desktop
     rule above already uses for that property, not guessed.

     Every one of these five source SVGs is authored with
     `preserveAspectRatio="none"` (real attribute, checked directly in
     the asset files) — its artwork deliberately stretches to whatever
     box it's given rather than staying pinned to the file's own native
     width/height ratio. Figma's own frame for each one (what these
     width/height numbers come from) very much doesn't share that
     native ratio, so leaving `height` on `auto` here (which falls back
     to the raw file's intrinsic ratio, not Figma's cropped one) came
     out a visibly different height/shape than Figma at every one of
     these except `.prizes-glow-bottom` — the one below that already
     had an explicit `height` from the desktop rule it was overriding.
     Each now gets that same explicit height, same px-ratio math. */
  .ballpit-countdown__prizes-glow-top {
    top: -24.5vw !important;
    width: 151.5vw !important;
    height: 39.2vw !important;
    min-width: 0 !important;
  }

  .ballpit-countdown__prizes-glow-bottom {
    display: block !important;
    left: 50% !important;
    /* Not `vw`, unlike this block's other `top` values — this one and
       `.prizes-road`'s below are meant to land at a specific spot
       *relative to the card*, not the section's own top edge. The
       heading+subtext block above the card is sized in `rem`, not
       `vw`, so it renders the same height in px at any mobile width
       (measured: card start sits at a constant 202.375px regardless of
       viewport, 320-428px) — a `vw` offset from the section top would
       drift out of alignment with the card at every width except the
       one it was tuned against. `17.09rem` = 202.375px (card's own
       measured top) + 71px (this element's Figma offset *into* the
       card, i.e. its Figma `top` minus the card's own Figma `top`). */
    top: 17.09rem !important;
    width: 439vw !important;
    min-width: 0 !important;
    height: 145vw !important;
    transform: translateX(-50%);
  }

  .ballpit-countdown__prizes-road {
    display: block !important;
    left: 50% !important;
    /* Same reasoning as `.prizes-glow-bottom` above: 202.375px (card's
       measured top) + 80px (Figma offset into the card) = 282.375px. */
    top: 17.65rem !important;
    width: 335.5vw !important;
    height: 74.1vw !important;
    min-width: 0 !important;
    transform: translateX(-50%);
  }

  .ballpit-countdown__prizes-spotlight {
    left: -22.6% !important;
    top: -24.5vw !important;
    width: 145.5% !important;
    height: 143.3vw !important;
    min-width: 0 !important;
  }

  .ballpit-countdown__prizes-confetti {
    display: block !important;
    top: -51.5vw !important;
    width: 291vw !important;
    height: 224.3vw !important;
    min-width: 0 !important;
  }
}

.ballpit-countdown__prizes-heading {
  position: relative;
  z-index: 1;
  margin: 0 0 1rem;
  line-height: 1.1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
}

.ballpit-countdown__prizes-heading-line {
  display: block;
  font-family: 'LonlyBop', sans-serif;
  font-weight: 800;
  font-size: clamp(1.05rem, 4.5vw, 5rem);
  width: fit-content;
}

@media (max-width: 1024px) {
  /* Same clamp-bottoms-out pattern as `.faq-heading`/`.partners-
     heading-line`/`.who-heading-line`/`.benefits-heading-line`
     elsewhere in this file — missed here specifically until now.
     Figma's own mobile type style for this heading ("Mobile/Display")
     is a flat 40px, not a continuation of the desktop clamp's curve. */
  .ballpit-countdown__prizes-heading-line {
    font-size: 2.5rem;
  }
}

.ballpit-countdown__prizes-heading-line--white {
  color: #fafafa;
}

.ballpit-countdown__prizes-heading-line--yellow {
  color: #ffd366;
}

.ballpit-countdown__prizes-subtext {
  position: relative;
  z-index: 1;
  max-width: 32rem;
  margin: 0 auto clamp(2rem, 5vw, 3.5rem);
  font-family: 'Manrope', sans-serif;
  font-weight: 500;
  font-size: 1.125rem;
  line-height: 1.4;
  letter-spacing: 0.18px;
  color: #fafafa;
}

.ballpit-countdown__prizes-carousel {
  /* Nav buttons overlay the card's own edges (`position: absolute`
     below) rather than sitting beside it as flex-row siblings — sharing
     row space with them was squeezing the card (and on narrow phones
     pushing the "next" button clean off-screen) at exactly the widths
     where the card can least afford to give any width up. */
  position: relative;
  z-index: 1;
  /* Matches `.prizes-card`'s own max-width (Figma: 616px card) rather
     than a wider, independent 900px — the blob/nav offsets below are
     percentages of *this* box, so it has to equal the card's box for
     them to land on the card's actual edges instead of floating in
     empty space beside a card that no longer stretches to fill 900px. */
  max-width: 38.5rem;
  margin: 0 auto;
}

/* The light purple-300 pill sitting behind the card on each side (Figma:
   `bg-[#bfadfe]`, a large rounded rect peeking out past the card's own
   edges) — nav buttons sit on top of these rather than floating bare,
   each with its own soft glow ellipse (the real Figma asset) tucked
   toward its outer edge. Sizing/position measured directly off the
   Figma export at 1440px: each pill is ~73% of the card's own width,
   tucked in so ~34% of that sticks out past the card's edge and the
   rest is hidden behind it. */
.ballpit-countdown__prizes-blob {
  position: absolute;
  top: 50%;
  width: 73%;
  max-width: 28rem;
  height: 14rem;
  background: #bfadfe;
  border-radius: 40px;
  overflow: hidden;
  z-index: 0;
}

.ballpit-countdown__prizes-blob--left {
  left: -34%;
  transform: translateY(-50%) rotate(-3deg);
}

.ballpit-countdown__prizes-blob--right {
  right: -34%;
  transform: translateY(-50%) rotate(3deg);
}

.ballpit-countdown__prizes-blob-glow {
  position: absolute;
  top: 100%;
  width: 92%;
  max-width: none;
  transform: translateY(-50%);
  opacity: 0.8;
  pointer-events: none;
}

.ballpit-countdown__prizes-blob--left .ballpit-countdown__prizes-blob-glow {
  left: -30%;
}

.ballpit-countdown__prizes-blob--right .ballpit-countdown__prizes-blob-glow {
  right: -30%;
}

.ballpit-countdown__prizes-nav {
  position: absolute;
  bottom: 0%;
  z-index: 2;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3.5rem;
  height: 3.5rem;
  border: 0;
  /* No button chrome of its own in Figma — the arrow glyph sits directly
     on the blob's own light-purple surface. */
  background: transparent;
  cursor: pointer;
  transition: transform 0.15s ease;
}

.ballpit-countdown__prizes-nav--prev {
  /* Centered on the visible (non-card-occluded) sliver of the blob
     behind it, not on the card's own edge (0%) — measured off Figma. */
  left: -24%;
  transform: translate(-50%, -50%);
}

.ballpit-countdown__prizes-nav--next {
  right: -24%;
  transform: translate(50%, -50%);
}

.ballpit-countdown__prizes-nav--prev:hover {
  transform: translate(-50%, -50%) translateY(-2px);
}

.ballpit-countdown__prizes-nav--next:hover {
  transform: translate(50%, -50%) translateY(-2px);
}

.ballpit-countdown__prizes-nav--prev img {
  /* `prizes-arrow-left.svg` is, as exported, pixel-identical to
     `prizes-arrow-right.svg` (both point right) rather than a mirrored
     glyph — flipped here instead of hand-editing the SVG path. */
  transform: scaleX(-1);
}

.ballpit-countdown__prizes-nav img {
  width: 1.75rem;
  height: 1.75rem;
}

/* Wrapper that gives the stack of `.prizes-card` slides below their
   shared box — takes over `.prizes-card`'s old job of being the flex
   child that actually sizes `.prizes-carousel` (each individual card is
   `position: absolute` now, so none of them can size a parent on their
   own). */
.ballpit-countdown__prizes-cards {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  height: 19rem;
}

.ballpit-countdown__prizes-card {
  /* Figma (node 3430:14942) pins `card-info` to the *right* edge
     (`justify-content: flex-end`) at a fixed 429px of the 616px card,
     leaving the left ~187px an open gap the badge floats over — it's
     not a flex sibling sharing row space with the surface at all, it's
     `position: absolute` straight off this card. Reproduced the same
     way below rather than approximated with flex gap/margin math. */
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  min-width: 0;
  /* Figma's own "prize card" (this element) carries the cream fill
     across the *full* 616px, not just under `.prizes-card-surface`'s
     69.64% — without it, the ~30% gap the badge floats over (open flow
     space, no element of its own) showed the purple section behind it
     instead of cream. No `overflow: hidden` here, unlike
     `.prizes-card-surface` below: this element's only child that'd
     bleed past its rounded corners is the badge, and it's *meant* to —
     `border-radius` still paints correctly on an el with default
     overflow, it just wouldn't get clipped, which is exactly right
     here. */
  border-radius: 40px;
  background: #f6f1e4;
  text-align: left;
  height: 19rem;
  /* All four cards stack on top of each other here (see `.prizes-cards`
     above); only `.is-active` is actually visible. Same division of
     labor as `.challenge-carousel-slide` elsewhere in this file: this
     plain `.is-active` toggle is only the *fallback* for no-JS/reduced-
     motion (an instant cut, no fade/slide) — `ballpit-countdown.js`'s
     `initPrizesCarousel()` drives the real fade+slide-in-from-the-side
     transition itself via GSAP tweens on these same opacity/transform
     properties, not a CSS transition. */
  opacity: 0;
  pointer-events: none;
  z-index: 0;
}

.ballpit-countdown__prizes-card.is-active {
  opacity: 1;
  pointer-events: auto;
  z-index: 1;
}

.ballpit-countdown__prizes-card-surface {
  position: relative;
  /* Figma: card-info is a fixed 429px inside a 616px card (69.6%), not
     a column that grows to fill whatever's left of the row — using a
     percentage of the card's own box keeps that ratio at any size. */
  width: 69.64%;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  padding: clamp(1.5rem, 3vw, 2.5rem);
  border-radius: 40px;
  overflow: hidden;
  height: 19rem;
  /* Belt-and-suspenders solid fallback in the *same* color `::before`'s
     own ellipse below uses (set per tint further down) — that ellipse is
     deliberately oversized specifically to bleed past this box's own
     edges at every corner (see its own comment), so this should never
     actually show, but costs nothing to have in place in case some
     future viewport ratio ever left a sliver of a corner uncovered. */
  background: #f6f1e4;
}

.ballpit-countdown__prizes-card-surface::before {
  /* The colored panel's own "bulging" background *is* this ellipse —
     there's no separate flat rect underneath it in the Figma source
     (confirmed directly: node 4053:41275's own "card info" panel has
     exactly one fill layer, this same oversized circle, nothing else).
     543x441 positioned at `left: calc(50% + 61px)` inside a 429px-wide
     card-info — i.e. ~127% wide, centered ~64% across — lands its own
     left edge almost flush with card-info's own left edge (just a
     sliver of the fallback color above past it) and its right edge
     100+px past the card's own right edge, clipped away by this
     element's `overflow: hidden`. */
  content: '';
  position: absolute;
  left: 64.2%;
  top: 50%;
  width: 127%;
  aspect-ratio: 543 / 441;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  z-index: 0;
  pointer-events: none;
}

/* Per-tint ellipse/fallback color — same 4 hex values Figma's own export
   uses. Token Leader and Fan Favourite share the exact same green in the
   Figma source itself, not a mistake made copying these over. */
.ballpit-countdown__prizes-card--champion .ballpit-countdown__prizes-card-surface,
.ballpit-countdown__prizes-card--champion .ballpit-countdown__prizes-card-surface::before {
  background: #ffd366;
}

.ballpit-countdown__prizes-card--runner-up .ballpit-countdown__prizes-card-surface,
.ballpit-countdown__prizes-card--runner-up .ballpit-countdown__prizes-card-surface::before {
  background: #1d92fd;
}

.ballpit-countdown__prizes-card--token-leader .ballpit-countdown__prizes-card-surface,
.ballpit-countdown__prizes-card--token-leader .ballpit-countdown__prizes-card-surface::before {
  background: #70c06d;
}
.ballpit-countdown__prizes-card--fan-favourite .ballpit-countdown__prizes-card-surface,
.ballpit-countdown__prizes-card--fan-favourite .ballpit-countdown__prizes-card-surface::before {
  background: #d22a23;
}


.ballpit-countdown__prizes-mascot {
  /* Figma: `left: -113px` (Champion/Runner-up/Token Leader) or `-109px`
     (Fan Favourite — a 4px variance in the source itself, not worth
     reproducing per-card), `size: 280px` against the 616px card — i.e.
     ~-18.3% / 45.45% of it — floating in the open gap left of
     `.prizes-card-surface`, not nudged out from beside it. */
  position: absolute;
  left: -18.3%;
  top: 50%;
  transform: translateY(-50%);
  z-index: 1;
  width: 45.45%;
  aspect-ratio: 1 / 1;
  object-fit: contain;
  pointer-events: none;
}

.ballpit-countdown__prizes-card-info {
  /* A positioned element (`.prizes-card-surface::before`) always paints
     above a non-positioned one regardless of DOM order — without this,
     the ellipse sat on top of the card copy instead of behind it. */
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  flex: 1 1 auto;
  text-align: center;
}

.ballpit-countdown__prizes-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.75rem;
  padding: 0.25rem 1.25rem;
  border-radius: 66px;
  background: #f6f1e4;
  font-family: 'Manrope', sans-serif;
  font-weight: 700;
  font-size: 1.1rem;
  letter-spacing: -0.03em;
  color: #54110e;
}

.ballpit-countdown__prizes-award-label {
  margin: 0;
  font-family: 'Manrope', sans-serif;
  font-weight: 700;
  font-size: 1.1rem;
  letter-spacing: -0.03em;
  color: #54110e;
}

.ballpit-countdown__prizes-award-value {
  margin: 0;
  font-family: 'LonlyBop', sans-serif;
  font-size: clamp(2.25rem, 5vw, 3.75rem);
  color: #54110e;
}

.ballpit-countdown__prizes-award-desc {
  max-width: 15rem;
  margin: 0;
  font-family: 'Manrope', sans-serif;
  font-weight: 500;
  font-size: 0.95rem;
  line-height: 1.3;
  letter-spacing: 0.32px;
  color: #54110e;
  margin-top: 0.5rem;
}

/* The three non-Champion awards flip the award copy to white so it still
   reads against their own solid tint (set on `.prizes-card-surface`/its
   `::before` ellipse further up) — the badge pill itself stays cream/dark
   on every variant, same as Champion's, since it's never sitting
   directly on the tint. */
.ballpit-countdown__prizes-card--runner-up .ballpit-countdown__prizes-award-label,
.ballpit-countdown__prizes-card--runner-up .ballpit-countdown__prizes-award-value,
.ballpit-countdown__prizes-card--runner-up .ballpit-countdown__prizes-award-desc,
.ballpit-countdown__prizes-card--token-leader .ballpit-countdown__prizes-award-label,
.ballpit-countdown__prizes-card--token-leader .ballpit-countdown__prizes-award-value,
.ballpit-countdown__prizes-card--token-leader .ballpit-countdown__prizes-award-desc,
.ballpit-countdown__prizes-card--fan-favourite .ballpit-countdown__prizes-award-label,
.ballpit-countdown__prizes-card--fan-favourite .ballpit-countdown__prizes-award-value,
.ballpit-countdown__prizes-card--fan-favourite .ballpit-countdown__prizes-award-desc {
  color: #fafafa;
}

@media (max-width: 1400px) {
  .ballpit-countdown__prizes::before {
    bottom: 88%;
  }
  
}

@media (max-width: 1024px) {

    .ballpit-countdown__prizes::before {
    content: '';
    position: absolute;
    left: 50%;
    bottom: 100%;
    transform: translateX(-50%);
    width: 140vw;
    height: 18vw;
    border-radius: 50% 50% 0 0 / 100% 100% 0 0;
    background: #7f5bfd;
    pointer-events: none;
  }

  /* Figma's own mobile frame (node 3469:19056) is 975px tall and its
     content — heading, subtext, one card, the nav row — fills basically
     all of it with no dead space at the bottom; `min-height: 100vh`
     below is sized for *desktop*, where the row layout's content
     happens to run tall enough to roughly fill a typical viewport on
     its own. In the mobile column layout, the same content is much
     shorter, so the same rule was forcing a viewport-tall purple box
     regardless — a few hundred px of empty purple between the nav
     arrows and the next section that isn't part of the design at all. */
  .ballpit-countdown__prizes-inner {
    min-height: 100vh;
  }

  .ballpit-countdown__prizes-blob {
    display: none;
  }

  /* Figma's dedicated mobile mockup (node 3469:19056, "Mobile
     Breakpoint") doesn't float the nav arrows beside the card at all —
     there's no wide blob left at this width for them to sit on — it
     lays them out as a plain centered row underneath the card instead
     (`data-name="Navigation"`, `gap: 40px`). Desktop's `position:
     absolute` + `left/right: -24%` math would otherwise push them
     straight past the edge of a narrow viewport with nothing to catch
     them, which is exactly what left them unreachable/off-screen
     before this rule existed — dropping back into normal flow here
     instead avoids that regardless of viewport width. */
  .ballpit-countdown__prizes-carousel {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1.5rem;
    position: relative;
    width: 100%;
    margin-top: 10rem;
  }

  /* `align-items: center` above sizes every flex-column child to its own
     *content* width instead of stretching it — harmless for the nav
     row, but `.prizes-cards`' own children are all `position: absolute`
     (contribute no intrinsic size at all), so without this it collapsed
     to 0 width and dragged every card inside it down to 0 width too. */
  .ballpit-countdown__prizes-cards {
    width: 90%;
  }

  .ballpit-countdown__prizes-nav-row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 2.5rem;
  }

  .ballpit-countdown__prizes-nav {
    position: static !important;
    transform: none !important;
    /* No blob surface to land on anymore — a flat purple-300 circle of
       its own instead (Figma: `bg-[var(--brand/secondary-purple/100,
       #d4c8fe)]`, `size-[64.781px]`). */
    width: 4rem !important;
    height: 4rem !important;
    background: #d4c8fe !important;
    border-radius: 999px;
  }

  .ballpit-countdown__prizes-nav--prev:hover,
  .ballpit-countdown__prizes-nav--next:hover {
    transform: translateY(-2px) !important;
  }

  /* Same breakpoint as the blob/nav-row rules above (was 600px here,
     then 700px — both mismatches with that rule's own threshold left a
     dead zone in between: blobs already hidden and the nav arrows
     already dropped into their own row, but the card was still laid
     out as a wide desktop row — the mascot's `left: -17.69%` float
     (tuned for a ~616px-wide card) pushed it straight off the left
     edge of anything narrower than that). */
  .ballpit-countdown__prizes-card {
    flex-direction: column;
    /* Figma's own card anchors its content to the *bottom* of a fixed
       515px-tall box (mascot bleeding upward past the top instead of
       sitting inside normal flow) — `flex-end` here is the closest a
       purely in-flow mascot+surface stack gets to that same look:
       empty cream space collects above the mascot instead of as a gap
       of bare purple below the card (which `center` — tuned back when
       this card's own height was still `auto` and always exactly
       matched its content either way — would leave now that height is
       fixed to match `.prizes-cards` below). */
    justify-content: flex-end;
    text-align: center;
    /* Was `auto` (this rule used to size itself to exactly whatever
       its content needed) — fixed to match `.prizes-cards` below now
       that the mascot is sized close to Figma's true ~280px and the
       four cards' content heights genuinely vary (473-493px): a
       shared fixed height keeps every card's cream background filling
       the same box, `justify-content: flex-end` above included, rather
       than each card's own bottom edge landing at a different height.
       `!important`: overriding the same property the base (non-media)
       rule also sets, which this stylesheet's own nesting quirk (see
       the note on the other 700px block above) can make lose to that
       earlier rule without it. */
    height: 32.25rem !important;
  }

  .ballpit-countdown__prizes-mascot {
    /* The off-canvas float only makes sense floating over open space
       beside the surface in a row — stacked above it here, so this
       drops out of `position: absolute` back into normal flow instead
       of overlapping the surface at a fixed offset that no longer
       means anything once the row becomes a column. */
    position: static;
    left: auto;
    top: auto;
    transform: none;
    transform: translateY(4rem);
    /* Figma's mobile "placeholder-Icon" box is 280px — the *same* fixed
       size as desktop's (this file's desktop `.prizes-mascot` rule is
       also 280px, `45.45%` of the 616px card), not scaled down for
       mobile the way the previous `clamp(8rem, 40vw, 12rem)` here
       assumed (that topped out at 150px at this width — noticeably
       smaller than Figma's mascot, and the main reason this whole card
       rendered shorter than Figma's 515px overall). `57vw` = 280px at
       the 375px-wide mobile frame the rest of this section's numbers
       are all derived from. */
    width: clamp(17rem, 80vw, 28rem);
    margin: 0 auto 1rem;
  }

  .ballpit-countdown__prizes-card-surface {
    width: 100%;
    /* `overflow: hidden` stays on (not overridden here, unlike `height`)
       — it's the only thing clipping `::before`'s oversized decorative
       ellipse back down to this card's own rounded shape;
       an earlier version of this rule also set `overflow: visible`
       here, which "fixed" a content-clipping bug that was actually
       caused by `.prizes-cards` collapsing to 0 width elsewhere (long
       since fixed) — but as a side effect let the glow balloon out
       past the card's edges uncontained. */
    height: 70% !important;
    /* Figma's mobile "card info" padding is `pt-16 pb-48 px-8`, not the
       desktop rule's uniform `clamp(1.5rem, 3vw, 2.5rem)` (24px on
       every side at this width) — mobile spends far less on the sides
       (giving the award copy more width to breathe on) and far more on
       the bottom. */
    padding: 5rem 0.5rem 3rem;
  }

  /* All four cards stack absolutely inside `.prizes-cards` (see the
     carousel CSS above) — none of them can size that box on their own
     once `height` is `auto` here, so it needs its own explicit height,
     same as the desktop row's 19rem does for the same reason. Measured
     off the tallest of the four actual rendered cards at this width
     (mascot + gap + badge + award copy: Token Leader/Fan Favourite's
     longer 3-line descriptions render tallest, at 493px) — close to,
     with a little headroom over, Figma's own 515px card. */
  .ballpit-countdown__prizes-cards {
    height: 32.25rem;
  }

  /* Re-centered for the mobile card's own stacked (column, not row)
     layout — `top: 65%`, not the desktop rule's `50%`, since the badge
     now sits *above* card-info in normal flow instead of floating
     beside it, shifting where this ellipse needs to sit to stay behind
     the award copy rather than behind empty space above it. */
  .ballpit-countdown__prizes-card-surface::before {
    left: 50%;
    top: 65%;
  }

  /* Figma's mobile "card info" (node 3469:19079) nests two different
     gaps — 24px between the badge and the award block, 26px between
     the award number and the description — not the one flat 12px this
     rule's own `gap` applies to all four children alike (this file's
     markup keeps badge/label/value/desc as flat siblings, unlike
     Figma's nested grouping, so `gap` alone can't express two
     different spacings between them — done as margin-top on each
     instead). The 12px between "Award" and "50.000.000" was already
     right, so `.prizes-award-value` needs no margin change. */
  .ballpit-countdown__prizes-card-info {
    gap: 0 !important;
  }

  .ballpit-countdown__prizes-badge {
    /* Figma: 64px tall, 24px text (this rule's own 44px/17.6px are both
       noticeably smaller) — `min-width` rather than Figma's literal
       fixed 224px, since that number comes from the "CHAMPION" mobile
       mockup specifically and the other three awards' longer labels
       ("TOKEN LEADER", "FAN FAVOURITE") would clip inside a hard 224px
       box at this font-size. */
    min-height: 4rem;
    min-width: 14rem;
    padding: 0.25rem 1rem;
    font-size: 1.5rem;
  }

  .ballpit-countdown__prizes-award-label {
    margin-top: 1.5rem;
    font-size: 1.5rem;
  }

  .ballpit-countdown__prizes-award-value {
    /* Same clamp-bottoms-out pattern as the heading elsewhere in this
       file: `5vw` at this width is well under the 2.25rem floor, so
       this was rendering at 36px instead of Figma's flat 48px. */
    font-size: 3rem;
    /* Restores the 12px gap `.prizes-card-info`'s own `gap` used to
       provide before this block zeroed it out (needed variable gaps
       elsewhere it couldn't express — see that rule's comment). */
    margin-top: 0.75rem;
  }

  .ballpit-countdown__prizes-award-desc {
    margin-top: 1.625rem;
    max-width: 13.625rem;
    font-size: 1rem;
  }
}

/* ======================================================================
   Benefits (Figma node 3430:11240, "Why you can't miss Designathon") —
   continues the same unbroken purple backdrop; no `::before` dome here,
   since it isn't a color change from the section above. */
.ballpit-countdown__benefits {
  position: relative;
  width: 100%;
  background: #7f5bfd;
  /* Bottom padding has to clear more than the row itself — `.benefits-
     road` dips well below `.benefits-row`'s own bottom edge (the big
     loop between cards 2-3), and anything past this section's own
     bottom edge gets painted over by the next section's opaque
     background rather than clipped, since it's a normal sibling, not
     actually clipped content. 5.5rem left ~50px of the road's lowest
     point covered; bumped enough to clear it with some margin. */
  padding: clamp(1rem, 3vw, 2rem) clamp(1rem, 4vw, 4rem) clamp(4.5rem, 10vw, 9rem);
  text-align: center;
  /* Safety net, not the fix itself: the arc-heading helper joins words
     with `&nbsp;` (see `bpc_render_arc_text()`), so a long line can never
     wrap — sized to fit at every width via the clamp on `.benefits-
     heading-line` below, but this catches any residual overflow instead
     of ever widening the page. */
  overflow-x: hidden;
  min-height: 100vh;
}

/* Shared box for the road + the card row — exists so the road can be a
   plain sibling of `.benefits-row` (not nested inside the row of
   cards, which is what `.benefits-row` is actually *for*) while still
   sharing its exact width/centering: this wrapper carries the
   `max-width` + `margin: auto` that used to live on `.benefits-row`
   itself, and the row now just fills it at `width: 100%`. Since the
   row is this wrapper's only in-flow child (the road is
   `position: absolute`, out of flow), the wrapper's own rendered box
   is pixel-identical to what the row's box was before — the road's
   percentages below didn't need to change at all. */
.ballpit-countdown__benefits-cards-wrap {
  position: relative;
  max-width: 1620px;
  margin: 0 auto;
}

/* The winding yellow road strung behind the four cards (Figma: real
   exported asset, `Vector 4005`). Positioned as a percentage of
   `.benefits-cards-wrap` above, *not* the section (like
   `.ballpit-countdown__prizes-road` is relative to `.prizes`) — this
   section's height is plain content-driven flow (heading + subtext +
   cards, no fixed-aspect canvas), so it doesn't reproduce Figma's own
   1000px-tall frame proportionally the way prizes' fixed structure
   does; anchoring to a box that always matches the row's own width
   keeps the math correct regardless of how tall the surrounding copy
   ends up being. `.benefits-card` below is `position: relative` +
   `z-index: 1` and comes after this in the DOM, which is what puts
   the cards above it. */
.ballpit-countdown__benefits-road {
  position: absolute;
  z-index: 0;
  left: -10%;
  top: 40.46%;
  width: 120%;
  max-width: none;
  pointer-events: none;
}

.ballpit-countdown__benefits-road--mobile {
  display: none;
}

@media (max-width: 767px) {
  .ballpit-countdown__benefits-road--desktop {
    display: none;
  }

  .ballpit-countdown__benefits-road--mobile {
    display: block;
  }
}

.ballpit-countdown__benefits-heading {
  margin: 0 0 1rem;
  line-height: 1.1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
}

.ballpit-countdown__benefits-heading-line {
  display: block;
  font-family: 'LonlyBop', sans-serif;
  font-weight: 800;
  font-size: clamp(1.05rem, 4.5vw, 5rem);
  width: fit-content;
}

.ballpit-countdown__benefits-heading-line--white {
  color: #fafafa;
}

.ballpit-countdown__benefits-heading-line--yellow {
  color: #ffd366;
}

.ballpit-countdown__benefits-subtext {
  max-width: 46rem;
  margin: 0 auto clamp(2.5rem, 6vw, 4rem);
  font-family: 'Manrope', sans-serif;
  font-weight: 500;
  font-size: 1.125rem;
  line-height: 1.4;
  letter-spacing: 0.18px;
  color: #e5e5e5;
}

.ballpit-countdown__benefits-row {
  position: relative;
  display: flex;
  align-items: stretch;
  /* Not `center` — on an overflowing (scrollable) flex container,
     `center` centers the *scroll position* by default too, clipping
     the first and last card equally instead of starting scrolled all
     the way to the first one like a normal carousel. Doesn't cost
     anything in the non-scrolling case: the cards already fill this
     row's full width via `flex-grow` whenever there's room, so there's
     essentially never leftover space for `center` vs `flex-start` to
     visibly differ on. */
  justify-content: flex-start;
  /* Figma's own gap here is 56px (3.5rem), not the ~32px this capped
     out at before — undersized relative to the road's fixed SVG path
     underneath meant the gaps between cards fell narrower than what
     the road was actually drawn to peek through, hiding more of it
     behind the cards than intended. */
  gap: clamp(1.5rem, 4vw, 3.5rem);
  /* `max-width`/centering now live on `.benefits-cards-wrap` (this
     element's parent) instead — this just fills that box exactly. */
  width: 100%;
  /* Per explicit request: when all 4 cards don't fit, scroll them
     horizontally instead of wrapping to a second row. `.benefits-card`
     below gets `flex-shrink: 0` to match — without it, cards would
     squeeze narrower and narrower before ever triggering scroll. */
  flex-wrap: nowrap;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: x proximity;
  /* Setting only `overflow-x` doesn't leave `overflow-y` at `visible`
     — per spec, a non-`visible` value on one axis forces the other to
     compute as `auto` too, so this row was silently clipping anything
     poking outside its own box vertically, `.benefits-card-icon`'s
     upward bleed included. This padding-top reserves room for that
     bleed *inside* the row's own box instead, so there's nothing left
     for the (unavoidable) auto-clipping to cut off. */
  padding-top: 2rem;
  margin-top: -2rem;
  /* Scrollable, but reads as a drag-able row of cards rather than a
     literal scroll widget — the native scrollbar stays fully
     functional (mouse wheel, trackpad swipe, touch drag, keyboard),
     just not painted. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.ballpit-countdown__benefits-row::-webkit-scrollbar {
  display: none;
}

.ballpit-countdown__benefits-card {
  position: relative;
  z-index: 1;
  flex: 1 1 260px;
  flex-shrink: 0;
  scroll-snap-align: start;
  /* Figma's card is 364px, not 368px (23rem) — that stray 4px × 4
     cards was just enough to push the row's natural width (1640px)
     past `.benefits-cards-wrap`'s own 1620px cap, so the row scrolled
     by a few pixels even at comfortably wide desktop sizes. */
  max-width: 22.75rem;
  display: flex;
  flex-direction: column;
  border-radius: 32px;
  background: #fafafa;
  text-align: left;
  overflow: visible;
}

.ballpit-countdown__benefits-card-header {
  position: relative;
  min-height: 6.8rem;
  display: flex;
  align-items: center;
  padding: 2rem 1.5rem;
  border-radius: 32px 32px 0 0;
  overflow: hidden;
}

.ballpit-countdown__benefits-card-header p {
  margin: 0;
  font-family: 'Manrope', sans-serif;
  font-weight: 700;
  font-size: 1.5rem;
  line-height: 1.15;
  letter-spacing: -0.03em;
  color: #4a445e;
  text-transform: capitalize;
}

.ballpit-countdown__benefits-card-header--purple { background: #e5deff; }
.ballpit-countdown__benefits-card-header--blue { background: #d2e9ff; }
.ballpit-countdown__benefits-card-header--yellow { background: #fff6e0; }
.ballpit-countdown__benefits-card-header--green { background: #e7fae6; }

.ballpit-countdown__benefits-card-icon {
  /* A sibling of `.benefits-card-header` now (not nested inside it) —
     the header has its own `overflow: hidden` (needed to keep its
     colored fill inside the card's rounded top corners), which was
     silently clipping the top half of this icon the instant it poked
     up past the header's own top edge via `top: -1.5rem`. Sitting on
     `.benefits-card` instead (`overflow: visible`) fixes that, and the
     offsets below are unchanged: the header spans the card's own full
     width starting at its top edge, so "-1.5rem/-0.75rem from the
     header" and "-1.5rem/-0.75rem from the card" land in the same
     spot. */
  position: absolute;
  z-index: 2;
  top: -1.5rem;
  right: -0.75rem;
  width: 3.5rem;
  height: 3.5rem;
  transform: rotate(18deg);
  pointer-events: none;
}

.ballpit-countdown__benefits-card-body {
  padding: 1.5rem;
}

.ballpit-countdown__benefits-card-body p {
  margin: 0;
  font-family: 'Manrope', sans-serif;
  font-weight: 500;
  font-size: 1rem;
  line-height: 1.3;
  letter-spacing: 0.32px;
  color: #171717;
}

@media (max-width: 767px) {
  /* Figma's dedicated mobile mockup (node 3469:19098, "Mobile
     Breakpoint") is a genuine structural change, not just a narrower
     reflow of the desktop row: the four cards stack in a single
     column (`gap: 40px` in Figma) instead of scrolling horizontally. */
  .ballpit-countdown__benefits-heading-line {
    /* Same clamp-bottoms-out pattern as `.faq-heading`/`.partners-
       heading-line`/`.who-heading-line` elsewhere in this file — the
       shared `4.5vw` slope floors out at 1.05rem well before this
       width. */
    font-size: 2.5rem;
  }

  .ballpit-countdown__benefits-subtext {
    /* Figma's mobile node (3469:19107) sizes/colors this smaller and
       brighter than desktop's 1.125rem `#e5e5e5` — confirmed directly
       against that node, not assumed from the desktop rule. */
    font-size: 1rem;
    color: #fafafa;
  }

  .ballpit-countdown__benefits-row {
    flex-direction: column;
    flex-wrap: wrap;
    gap: 2.5rem;
    /* No longer a horizontal scroller at this width, so none of the
       desktop row's scroll machinery applies — including the
       `padding-top`/`margin-top` pair that only existed to reserve
       room the forced `overflow-y: auto` would've otherwise clipped. */
    overflow-x: visible;
    overflow-y: visible;
    scroll-snap-type: none;
    padding-top: 0;
    margin-top: 0;
  }

  .ballpit-countdown__benefits-card {
    flex: 1 1 auto;
    width: 100%;
    max-width: none;
  }

  /* The winding road behind the cards uses a different asset at this
     breakpoint (see the `<picture>` swap in the template) — Figma's
     own "Vector 4006" is a shorter squiggle sized/placed for the
     vertical stack, only ever passing behind card 1 and the top of
     card 2, not all four cards like the desktop S-curve. Percentages
     below are relative to `.benefits` (this element's actual
     containing block — a plain sibling of `.benefits-cards-wrap`, not
     nested inside it, same as `.partners-cta-road`'s own containing
     block elsewhere in this file), derived from Figma's mobile frame
     (375×1655) and cross-checked against the live render. */
  .ballpit-countdown__benefits-road {
    left: -100%;
    top: 22%;
    width: 300%;
  }
}

/* ======================================================================
   Partners (Figma node 3430:11329, "Partner") — continues the same
   purple backdrop; sponsor logos are placeholders (see the PHP comment
   right above `bpc_render_sponsor_tier_row()`'s calls) until real ones
   are confirmed. Each tier is an infinite marquee: the track holds two
   identical copies of its logo set side by side and scrolls exactly
   -50%, so the loop point is invisible. */
.ballpit-countdown__partners {
  position: relative;
  width: 100%;
  background: #7f5bfd;
  padding: clamp(1rem, 3vw, 2rem) 0 clamp(3rem, 7vw, 5.5rem);
  text-align: center;
  overflow: hidden;
}

.ballpit-countdown__partners-heading {
  margin: 0 0 clamp(2rem, 5vw, 3.5rem);
  line-height: 1.1;
  padding: 0 clamp(1rem, 4vw, 4rem);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
}

.ballpit-countdown__partners-heading-line {
  display: block;
  font-family: 'LonlyBop', sans-serif;
  font-weight: 800;
  font-size: clamp(1.05rem, 4.5vw, 5rem);
  width: fit-content;
}

@media (max-width: 767px) {
  /* Figma's dedicated mobile mockup (node 3631:11141) shows this heading
     around 40px per line — the shared clamp's own `4.5vw` slope bottoms
     out at its 1.05rem (16.8px) floor by this width, well under half
     that, same pattern as `.faq-heading` elsewhere in this file. */
  .ballpit-countdown__partners-heading-line {
    font-size: 2.5rem;
  }
}

.ballpit-countdown__partners-heading-line--white { color: #fafafa; }
.ballpit-countdown__partners-heading-line--yellow { color: #ffd366; }

.ballpit-countdown__partners-rows {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  margin-bottom: clamp(2.5rem, 6vw, 4rem);
}

.ballpit-countdown__partners-row {
  width: 100%;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}

.ballpit-countdown__partners-track {
  display: flex;
  align-items: center;
  width: max-content;
  /* Same gap as `.partners-track-set` below, between the two copies
     themselves — without this, the seam where the loop restarts had a
     *different* (bigger, from that set's own now-removed padding)
     gap than every other item-to-item gap in the row, reading as a
     visible stutter once a cycle. Matching the two makes the seam
     indistinguishable from any other gap, which is what actually
     makes the loop read as seamless. */
  gap: clamp(1rem, 2.5vw, 1rem);
  /* Each row sets its own `--bpc-partners-duration` inline (see
     `bpc_render_partner_row()`) — same direction/keyframe for all
     three, just a different pace, per explicit request (row 1
     slowest, row 2 a little faster, row 3 fastest/default). The
     `28s` here is only a fallback for the (non-existent) case where
     that custom property is missing. */
  animation: bpc-partners-marquee var(--bpc-partners-duration, 28s) linear infinite;
  /* Per explicit request: draggable, not just a passive auto-scroll —
     `initPartnersDrag()` in ballpit-countdown.js hands each track from
     this plain CSS animation over to a JS-driven position the instant a
     user first grabs it. `grab`/`grabbing` here regardless of whether
     that handoff has happened yet, so the row visibly invites dragging
     even before its very first drag. `touch-action: pan-y`: this page's
     own scroll container is vertical (Lenis, on `.post-cta`) — without
     this a touch drag here could get interpreted as an attempt to
     scroll *that*, fighting the drag rather than just panning the
     track horizontally. `user-select: none`: without it, a drag that
     starts on top of a text pill (`.partners-pill`) highlights its text
     instead of moving the track, on both mouse and touch. */
  cursor: grab;
  touch-action: pan-y;
  user-select: none;
}

.ballpit-countdown__partners-track-set {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  gap: clamp(1rem, 2.5vw, 1rem);
  /* No side padding here (used to be `padding: 0 clamp(1rem,3vw,2rem)`)
     — that's what created the uneven seam `.partners-track`'s own
     comment above describes: each copy's own left/right padding added
     together right at the loop point, on top of the regular gap. */
}

.ballpit-countdown__partners-pill {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Figma frames (e.g. 3430:12831 vs 3430:12833, 3430:12940 vs
     3430:12942): the pill frame and the logo-chip frame in the same
     row always share one identical height (120px / 96px) — must match
     `.partners-logo-chip`'s height below so the row doesn't look like
     the pills are "shrunk" against taller logo chips. */
  height: clamp(4.5rem, 7.5vw, 5.5rem);
  padding: 0 clamp(1.25rem, 2.5vw, 1.75rem);
  /* Figma (nodes 3430:12831/12940/13478): a rounded *rectangle* at
     20px, the same radius `.partners-logo-chip` uses — not a full
     pill/capsule shape like this previously was. */
  border-radius: 20px;
  /* `font-family/display` (LonlyBop), confirmed on all three tier
     labels directly in Figma — not Manrope; that mix-up came from
     `.who-card-title` elsewhere in this file actually using Manrope
     (a *different* node, correctly), which doesn't carry over here. */
  font-family: 'LonlyBop', sans-serif;
  font-weight: 700;
  font-size: clamp(1rem, 1.6vw, 1.25rem);
  letter-spacing: -0.03em;
  text-transform: capitalize;
  white-space: nowrap;
}

/* Colors/text checked directly against Figma: yellow for Platinum,
   green for both Gold and Silver (row 2 shares the one color across
   its two tiers), navy for AI Partner. */
.ballpit-countdown__partners-pill--yellow {
  background: #ffd366;
  color: #554622;
}

.ballpit-countdown__partners-pill--white {
  background: #ffffff;
  color: #000000;
}

.ballpit-countdown__partners-pill--green {
  background: #86e783;
  color: #171717;
}

.ballpit-countdown__partners-pill--navy {
  background: #402e7f;
  color: #fafafa;
}

.ballpit-countdown__partners-logo-chip {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Every logo asset here (Cool Mate, Arena Multimedia, the university
     seal) shares the same 2.25:1 chip proportion in Figma (270x120,
     216x96), so one aspect-ratio covers all three rather than sizing
     each row's chip separately. */
  height: clamp(4.5rem, 7.5vw, 5.5rem);
  aspect-ratio: 2.25 / 1;
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.1);
  overflow: hidden;
  user-select: none;
}

.ballpit-countdown__partners-logo-chip img {
  /* A fixed inset, not a percentage — CSS `padding` percentages always
     resolve against the containing block's *width*, on every side,
     even top/bottom. On this chip's 2.25:1 box, an 18% padding was 18%
     of the width on top/bottom too, which ate ~80% of the chip's own
     (much smaller) height — object-fit:contain then had almost no
     vertical room left to fit the logo into, and shrank it to a
     sliver. */
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: 0.85rem 1.5rem;
  /* The newer sponsor logos (Figma nodes 4095:4162/4269 — YBOX.VN,
     Aniday, designare, etc.) are plain PNG exports in their own source
     color (mostly black), not pre-colored white SVGs like the original
     3 assets (Arena/the university seal) — Figma itself recolors them
     white by using each as a mask over a solid white fill rather than
     shipping a white source file. `brightness(0) invert(1)` reproduces
     that here regardless of source color: it forces every opaque pixel
     to black first, then flips black to white, so it's a no-op on the
     already-white SVGs and correctly recolors the new black PNGs alike
     — one rule instead of needing to know which of the two each asset
     is. Excluded on `--full` (Cool Mate's own multi-color chip asset,
     see that modifier's own comment) via the sibling selector below. */
  filter: brightness(0) invert(1);
  /* Confirmed directly: an `<img>` is natively draggable by the browser
     on its own, entirely separate from `.partners-track`'s own custom
     drag-to-scroll (see that rule's own comment) — starting a mouse drag
     with the cursor over one of these logo images hands the gesture to
     the browser's native image-drag instead, which fires a
     `pointercancel` right after `pointerdown` and kills
     `initPartnersDrag()`'s own tracking before a single `pointermove`
     gets through. `-webkit-user-drag: none` (the property Chrome/Safari
     actually use for this — `draggable="false"` the *attribute* would be
     the standards path but can't be set from pure CSS) stops that native
     drag from ever engaging, so the pointer sequence stays with the
     track's own handlers instead. */
  -webkit-user-drag: none;
}

/* Cool Mate's own SVG already bakes in its chip look (a 270x120
   translucent-white rounded rect drawn as part of the asset itself,
   unlike Arena/the university seal which are just the bare mark) — the
   wrapper's own background/radius/padding would just double up on top
   of that, so this variant clears all three and lets the asset fill
   the chip on its own. */
.ballpit-countdown__partners-logo-chip--full {
  background: none;
  border-radius: 0;
}

.ballpit-countdown__partners-logo-chip--full img {
  padding: 0;
  /* Undoes `.partners-logo-chip img`'s own recolor filter above — this
     asset is already its own multi-color chip, not a plain mark meant
     to always render white. */
  filter: none;
}

@keyframes bpc-partners-marquee {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

.ballpit-countdown__partners-track.is-dragging {
  cursor: grabbing;
}

/* Figma node 3430:13720 ("Frame 1948756296") — a two-tone card (light-blue
   contact note on top, white button row below) sitting on a big rotated
   yellow S-curve (3430:13721/"Vector 4074") with a clover badge tucked into
   its top-right corner, plus two overlapping "onward" arrow icons
   (3430:13734) drawn on the curve just to the card's lower-left. All three
   decorative layers are positioned by percentage of this wrapper, tuned
   against the same ~1440px reference frame the rest of `.partners` uses
   (Figma's own absolute px positions there converted to %) — like the
   other road/curve decorations in this file, this stays accurate at that
   reference width and only approximately proportional elsewhere, since the
   card itself is capped by `max-width` rather than scaling with the
   viewport the way the curve/arrows (pure %) do. */
.ballpit-countdown__partners-cta-wrap {
  position: relative;
  width: 100%;
  display: flex;
  justify-content: center;
  padding: clamp(2.5rem, 8vw, 3.5rem) 1rem clamp(2.5rem, 6vw, 4.5rem);
}

.ballpit-countdown__partners-cta-road {
    position: absolute;
    z-index: 0;
    left: -10%;
    top: 64.46%;
    width: 120%;
    transform: rotate(8.41deg);
    max-width: none;
    pointer-events: none;
}

@media (max-width: 767px) {
  /* Figma's dedicated mobile mockup (node 3631:11141) nests this road
     vector inside the CTA card frame itself, at local coords x:-1031.27
     y:-193.57 w:2505.64 h:719.21 against a 343x251 card — way bigger than,
     and centered behind, just the card. But `.partners-cta-road` in this
     codebase's own markup is a child of `<section class="…__partners">`
     directly (rendered first, before the heading/marquee rows even) —
     *not* nested inside `.partners-cta-wrap` — so its `top`/`left`
     percentages resolve against this whole section's own height (the
     heading + all 3 marquee rows + the CTA wrap combined, ~810px tall at
     this width), not the much shorter CTA-wrap-sized box the desktop
     percentages above were tuned against. Re-derived here directly:
     scaled by this card's own rendered width (311px measured / 343px
     Figma reference ≈ 0.907), added to the card's own measured offset
     within the section (32px, 480px), then expressed as % of the
     section's own box. */
  .ballpit-countdown__partners-cta-road {
    left: -241%;
    top: 53%;
    width: 606%;
    transform: rotate(8.41deg);
  }
}

.ballpit-countdown__partners-cta-nav {
  position: absolute;
  top: 54%;
  left: 24%;
  z-index: 1;
  width: clamp(3.5rem, 6vw, 4.5rem);
  height: clamp(3.5rem, 6vw, 4.5rem);
  pointer-events: none;
}

.ballpit-countdown__partners-cta-nav-arrow {
  position: absolute;
  inset: 0;
}

.ballpit-countdown__partners-cta-nav-arrow--2 {
  /* Figma 3430:13742 vs 3430:13735: the second arrow sits up and to the
     right of the first by (66px, -21px) — in rem (16px root), not % of
     this box's own size, so the offset stays a fixed real-world distance
     as the icons themselves grow/shrink via their own clamp(). */
  transform: translate(4.125rem, -1.3125rem);
}

.ballpit-countdown__partners-cta-nav-arrow img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.ballpit-countdown__partners-cta {
  /* Explicit rather than relying on the theme's own global `*{box-
     sizing:border-box}` reset (main.min.css) — without it, `padding`
     would add on top of `width`/`max-width` instead of being carved out
     of them, silently widening this card past the viewport below. */
  box-sizing: border-box;
  position: relative;
  z-index: 2;
  width: calc(100% - 2rem);
  max-width: 25.375rem; /* Figma 3430:13720: 406px at the 1440px reference */
  margin: 0 auto;
  border-radius: 20px;
  background: #fafafa;
  text-align: left;
  overflow: visible;
}

.ballpit-countdown__partners-cta-badge {
  position: absolute;
  top: -2rem;
  right: -1.35rem;
  width: 5.3rem;
  height: 5.3rem;
  transform: rotate(18.58deg);
  z-index: 3;
}

.ballpit-countdown__partners-cta-header {
  background: #d2e9ff;
  /* All 4 corners rounded, not just the top two — this used to butt up
     against the "Become a partner" button row below (itself squaring
     off this box's own bottom edge to sit flush against it), but that
     row is gone per explicit request, so this is now `.partners-cta`'s
     only child and needs its own matching bottom corners instead of a
     sharp square edge cutting across the card's rounded shape. */
  border-radius: 20px;
  padding: 1.5rem;
}

.ballpit-countdown__partners-cta-header p {
  margin: 0;
  font-family: 'Manrope', sans-serif;
  font-weight: 500;
  font-size: 1.125rem;
  line-height: 1.4;
  letter-spacing: 0.18px;
  color: #1361a9;
}

.ballpit-countdown__partners-cta-header a {
  color: inherit;
  text-decoration: underline;
}

/* The "Become a partner" CTA button row (`.partners-cta-row`/`-btn`/
   `-icon`) that used to sit below `.partners-cta-header` here is removed
   per explicit request — see that header rule's own comment on why its
   border-radius picked up the bottom corners this row used to own. */

@media (max-width: 767px) {
  /* Figma's dedicated mobile mockup for this card (node 3768:3089) uses a
     bolder, darker, tighter-tracking text style here (Bold 700, #4a445e,
     -0.36px) than the desktop one just above (Medium 500, #1361a9,
     0.18px) — checked directly against both that node and its desktop
     counterpart (3430:13720, "Body-m") to confirm this is a genuine
     mobile-specific style the shared rule was missing, not the same text
     just needing a generic mobile size tweak. Font-size (18px) is
     unchanged, so not repeated here. Placed after (not inside) the
     earlier `.partners-cta-road`-only 767px block above so it wins the
     cascade against these same-specificity unconditional rules — a media
     query earlier in source order loses a specificity tie to a later
     unconditional one, regardless of viewport. */
  .ballpit-countdown__partners-cta-header p {
    font-weight: 700;
    letter-spacing: -0.36px;
    color: #4a445e;
  }

  /* Same node: the badge shrinks from the desktop rule's 5.3rem (85.11px
     Figma) to 3.17rem (50.66px) and sits closer to the card's own corner
     (top -15.17px, right -4.26px vs desktop's -32.4px/-21.48px) —
     proportional to the smaller mobile card, not a value shared with
     desktop's larger one. */
  .ballpit-countdown__partners-cta-badge {
    top: -0.95rem;
    right: -0.27rem;
    width: 3.17rem;
    height: 3.17rem;
  }



  .ballpit-countdown__stats-copy .ballpit-countdown__stats-heading{
    text-align: center !important;
    align-items: center;
  }
}

/* ======================================================================
   Stats + registration CTA (Figma node 3430:12255) — last section on the
   purple backdrop; FAQ's own `::before` dome (yellow) is what curves up
   over this section's own tail end, not the other way around. */
/* `.ballpit-countdown__stats-section`, not the shorter `…__stats` — that
   bare class name already belongs to an unrelated pre-countdown hero pill
   list (ballpit-countdown.php:194, styled elsewhere in this file next to
   `.ballpit-countdown__pill`/`.highlight-underline`). Reusing it here would
   silently leak that rule's `display:flex;flex-direction:column;
   min-width:195px` onto this section (higher specificity there since it's
   nested under `.ballpit-countdown`), and broke Playwright's own
   `.ballpit-countdown__stats` lookup by matching two elements. */
.ballpit-countdown__stats-section {
  position: relative;
  width: 100%;
  background: #7f5bfd;
  padding: clamp(1rem, 3vw, 2rem) clamp(1rem, 4vw, 4rem) clamp(4rem, 9vw, 6.5rem);
}

/* Figma node 3430:13769 ("Frame 1948756223") — the white "challenge" card:
   arc heading + copy on the left, a separate grey "Event Registration"
   sub-card on the right. No photo in here — that's its own block below
   (`.stats-photo-wrap`), not merged into this card like it used to be. */
.ballpit-countdown__stats-card {
  /* Explicit rather than relying on the theme's own global `*{box-
     sizing:border-box}` reset (main.min.css) — without it, `padding`
     would add on top of `max-width` instead of being carved out of it,
     silently widening this card past its intended cap. */
  box-sizing: border-box;
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  max-width: 1200px;
  margin: 0 auto;
  /* Figma 3430:13769: 501px tall at the 1200px reference width — needs a
     much taller top/bottom padding than a "normal" card to match (measured
     off the render: ~119px above the heading, ~24px below the paragraph),
     not just enough to clear the content. */
  padding: clamp(3rem, 8.3vw, 6.5rem) clamp(1.5rem, 4vw, 3.5rem);
  border-radius: 40px;
  background: #fff;
}

.ballpit-countdown__stats-copy {
  flex: 1 1 20rem;
  min-width: 0;
  display: flex;
  flex-direction: column;
  /* Figma: ~113px between the heading and the paragraph below it — much
     more breathing room than a "normal" heading+body stack. */
  gap: clamp(1.5rem, 4.5vw, 4.5rem);
  padding-top: 0.5rem;
  /* Explicit — an ancestor further up (same pattern hit on `.who-card-body`
     earlier in this file) forces `text-align:center`, which is invisible
     on the arc heading (its lines run near the card's full width) but
     visibly re-centers the shorter `.stats-desc` paragraph lines. */
  text-align: left;
}

.ballpit-countdown__stats-heading {
  margin: 0;
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  justify-content: center;
  align-items: flex-start;
}

.ballpit-countdown__stats-heading-line {
  width: fit-content;
  display: block;
  /* `font-family/display` (LonlyBop) per Figma's own "Desktop/Heading 1"
     style on this node — a smaller/contained heading than the big
     full-bleed arc headlines elsewhere on the page (48px at the 1440px
     reference, not 80-90px), since it lives inside this card rather than
     spanning the viewport. */
  font-family: 'LonlyBop', sans-serif;
  font-weight: 400;
  font-size: clamp(1.75rem, 3.2vw, 3rem);
  line-height: 1.2;
}

.ballpit-countdown__stats-heading-line--dark {
  color: #54110e; /* Figma 3430:13784 ("Heading H1") sampled directly off the render */
}

.ballpit-countdown__stats-heading-line--red {
  color: #fc322a; /* Figma 3430:13785 — same red as the CTA buttons on this card */
}

.ballpit-countdown__stats-desc {
  margin: 0;
  max-width: 34rem;
  font-family: 'Manrope', sans-serif;
  font-weight: 500;
  font-size: 1.125rem;
  line-height: 1.4;
  letter-spacing: 0.18px;
  color: #171717;
}

.ballpit-countdown__stats-register {
  position: relative;
  box-sizing: border-box;
  flex: 0 1 22.75rem; /* Figma 3430:13772: 363.8px at the 1440px reference */
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.5rem;
  padding: 2rem;
  border-radius: 32px;
  background: #f5f5f5;
  text-align: left;
}

.ballpit-countdown__stats-register-badge {
  position: absolute;
  top: -2rem;
  right: -1.35rem;
  width: 5.3rem;
  height: 5.3rem;
  transform: rotate(22.37deg);
}

.ballpit-countdown__stats-register-title {
  margin: 0;
  font-family: 'Manrope', sans-serif;
  font-weight: 700;
  font-size: 1.5rem;
  letter-spacing: -0.03em;
  color: #262626;
}

.ballpit-countdown__stats-register-desc {
  margin: 0;
  font-family: 'Manrope', sans-serif;
  font-weight: 500;
  font-size: 1rem;
  line-height: 1.3;
  letter-spacing: 0.32px;
  color: #262626;
}

.ballpit-countdown__stats-register-row {
  display: flex;
  align-items: stretch;
  width: 100%;
}

.ballpit-countdown__stats-register-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1 1 auto;
  min-height: 4rem;
  padding: 0.5rem 1rem;
  border-radius: 2.5rem;
  background: #fc322a;
  font-family: 'Manrope', sans-serif;
  font-weight: 700;
  /* Figma (3430:10086/3469:20086, both the desktop and mobile "Register
     now" nodes): 24px — this was actually still 1.2rem/19.2px despite
     the comment already saying 24px; fixed to match, and to the same
     flat 24px used consistently on every other CTA-pill button's label
     on this page now (see `.challenge-apply-btn-label`'s own comment,
     Challenge section). */
  font-size: 1.5rem;
  letter-spacing: -0.03em;
  color: #fafafa;
  text-decoration: none;
  white-space: nowrap;
}

.ballpit-countdown__stats-register-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 4rem;
  height: 4rem;
  border-radius: 50%;
  background: #fc322a;
  transform: rotate(-45deg);
}

.ballpit-countdown__stats-register-icon img {
  width: 1.75rem;
  height: 1.75rem;
}

@media (max-width: 900px) {
  .ballpit-countdown__stats-register {
    flex-basis: 100%;
  }

  /* Figma node 3469:20071 (dedicated mobile mockup): this paragraph is
     centered here, not left-aligned like the desktop node, and uses the
     smaller "Body SM" style (16px/0.32px) instead of desktop's 18px/0.18px. */
  .ballpit-countdown__stats-desc {
    text-align: center;
    font-size: 1rem;
    letter-spacing: 0.32px;
  }
}

/* Figma node 3430:13750 ("Frame 1948756327") — the group photo, sitting
   below the white card (not inside it), with the three "X+ Applicants"
   pills overlapping its lower edge and the yellow wave (3430:14042)
   closing the section out. */
.ballpit-countdown__stats-photo-wrap {
  position: relative;
  /* Plain `max-width: 1202px` alone left a real gap: the 3 pills below
     deliberately bleed past this box's own edges by a fixed ~6.7% of
     its own rendered width (Figma's own scattered-sticker layout, see
     `.stats-pill--left/--right`'s own comment) — at the 1440px
     reference that bleed lands inside the extra centering margin this
     box picks up once it hits its 1202px cap, but *below* that cap
     (roughly 1000-1300px viewports) this box's own width tracks the
     viewport almost 1:1 with very little of that margin to spare, so
     the bleed spilled past the section's own edge instead — confirmed
     directly (left pill measured at x:-29px, clipped, at a 1024px
     viewport). `min()` here guarantees at least 88px clear on each
     side (comfortably over the ~80.5px worst-case bleed at this box's
     own 1202px cap) at every width instead of only above it — self-
     scaling, since a narrower result here also shrinks the bleed itself
     (a % of this same box's width) well under that 88px. */
  max-width: 1202px;
  margin: clamp(2rem, 5vw, 3.5rem) auto 0;
}

.ballpit-countdown__stats-photo {
  /* Was a single `<img>` directly — now a wrapper around a stack of
     `.stats-photo-slide`s (same 6-photo set `.gallery-viewport` uses,
     per explicit request) that `initStatsPhotoCycle()` in ballpit-
     countdown.js crossfades between automatically every 3s. Every size/
     shape property below is unchanged from when this was the `<img>`
     itself — `position: relative` + `overflow: hidden` are the only
     additions, so the slides (each `position: absolute; inset: 0`) have
     a box to fill and stay clipped to this element's own rounded
     corners. */
  position: relative;
  overflow: hidden;
  display: block;
  width: 100%;
  /* Figma: 570px tall at the 1440px reference width (39.6vw), capped at
     570px itself since `.stats-photo-wrap`'s own 1202px max-width means
     the ratio stops needing to grow past that reference anyway. Previously
     computed against the wrong base (570/1202 as a raw fraction of *this
     element's own width* isn't the same as the vw the viewport-relative
     clamp needs) and came out ~190px short of Figma. */
  height: clamp(14rem, 39.6vw, 35.625rem);
  border-radius: 60px;
  cursor: pointer;
  outline: none;
}

.ballpit-countdown__stats-photo:focus-visible {
  outline: 3px solid #ffd366;
  outline-offset: 4px;
}

/* Plain crossfade (opacity) plus a slow continuous zoom while a slide is
   active (a "Ken Burns" pan/zoom, here just the zoom half since these
   are static group photos, not wide landscapes with obvious pan
   headroom) — per explicit request for some mood/motion here rather
   than a flat hard image swap. `animation` (not `transition`) for the
   zoom specifically: a transition only animates between two explicit
   end states on a property *change*, but every slide needs the *same*
   1 → 1.08 scale replayed from its own start each time it becomes
   active, which is exactly what re-triggering a class's own animation
   (by toggling that class off/on) gives for free. 4s, not the 3s the
   slide is actually the target `is-active` slide for: lets the zoom
   still be mid-motion (never obviously resets/snaps) through the ~1s
   opacity crossfade into the *next* slide, since this one keeps
   animating right up until its own `is-active` class is removed. */
.ballpit-countdown__stats-photo-slide {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transform: scale(1);
  transition: opacity 1s ease;
}

.ballpit-countdown__stats-photo-slide.is-active {
  opacity: 1;
  animation: bpc-stats-photo-kenburns 4s ease-out forwards;
}

@keyframes bpc-stats-photo-kenburns {
  from {
    transform: scale(1);
  }
  to {
    transform: scale(1.08);
  }
}

@media (prefers-reduced-motion: reduce) {
  .ballpit-countdown__stats-photo-slide {
    transition: none;
  }

  .ballpit-countdown__stats-photo-slide.is-active {
    animation: none;
  }
}

.ballpit-countdown__stats-pills {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: clamp(1rem, 1vw, 2rem);
  margin-top: clamp(-6rem, -9vw, -4rem);
  flex-wrap: wrap;
  width: 90%;
  margin: 0 auto;
}

.ballpit-countdown__stats-pill {
  flex-shrink: 0;
  /* Figma: 448px wide inside a 1312px card (~34%) — scaled the same
     ratio here instead of the noticeably smaller size this used to be. */
  width: clamp(11rem, 22vw, 19rem);
  padding: 1.75rem 1rem 1.5rem;
  border-radius: 999px;
  background: #fff;
  text-align: center;
  transform: rotate(var(--bpc-pill-rotate, 0deg));
}

.ballpit-countdown__stats-pill--center {
  margin: 0 -0.5rem;
  z-index: 1;
}

.ballpit-countdown__stats-pill-num {
  margin: 0;
  /* Was 'LonlyBop Condensed' (with a space) — that name matches no
     registered `@font-face` (the actual family this file registers is
     'LonlyBopCondensed', one word, near the top of this stylesheet), so
     it silently fell through to the 'LonlyBop' fallback instead: the
     plain (not condensed) display font, noticeably wider per character
     — the real cause of these numbers reading oversized/crowding their
     own pill, not just the font-size values themselves. */
  font-family: 'LonlyBopCondensed', 'LonlyBop', sans-serif;
  font-weight: 300;
  font-size: clamp(2.25rem, 5.5vw, 4rem);
  line-height: 1;
  color: #171717;
}

.ballpit-countdown__stats-pill-num span {
  font-family: 'LonlyBop', sans-serif;
  font-size: 0.7em;
}

.ballpit-countdown__stats-pill-label {
  margin: 0.35rem 0 0;
  font-family: 'Manrope', sans-serif;
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: -0.03em;
  color: #262626;
}

@media (max-width: 700px) {
  .ballpit-countdown__stats-pills {
    gap: 0.75rem;
  }

  .ballpit-countdown__stats-pill--center {
    margin: 0;
  }
}

@media (max-width: 900px) {
  /* Per explicit request (matching mubadala.com's own "Latest News &
     Stories" row): the three pills become a real drag/swipe-able
     horizontal scroller at mobile, not just a static bleed clipped by
     `.post-cta`'s own `overflow-x: hidden` — same technique as
     `.benefits-row` elsewhere in this file (a local `overflow-x: auto`
     still scrolls independently underneath a hidden-overflow ancestor;
     only *that* ancestor's own bounds get clipped, not this element's own
     scroll). `justify-content: center` (set outside this query, for the
     non-scrolling desktop case) had to go here specifically: on a
     scrollable flex row it only *visually* centers the content at
     `scrollLeft: 0` by shifting the flex line start into negative
     territory — since `scrollLeft` can't go negative, that permanently
     stranded the left pill half off-screen with no way to scroll to it.
     `flex-start` + matching edge padding instead (below) centers pill 1
     at rest the same way, but leaves *equal* room to scroll fully to
     either end — confirmed by scripting `scrollLeft` to both extremes and
     screenshotting each. */
  .ballpit-countdown__stats-pills {
    flex-wrap: nowrap;
    justify-content: flex-start;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
    -ms-overflow-style: none;
    /* `.stats-pill`'s own `clamp(11rem, 22vw, 19rem)` bottoms out at its
       11rem floor for any viewport this query applies to (22vw stays
       under 11rem below ~800px) — so this can safely assume a flat 11rem
       pill width rather than tracking the clamp with a custom property. */
    padding-left: calc(50% - 5.5rem);
    padding-right: calc(50% - 5.5rem);
  }

  .ballpit-countdown__stats-pills::-webkit-scrollbar {
    display: none;
  }

  .ballpit-countdown__stats-pill {
    scroll-snap-align: center;
  }

  /* The negative side-margins that squeeze the 3 pills together on
     desktop would eat directly into the new edge padding above at this
     width — 0 here instead, with the scroll container's own `gap` (still
     set on the base rule) providing the actual spacing between pills. */
  .ballpit-countdown__stats-pill--center {
    margin: 0;
  }
}

@media (max-width: 767px) {
  /* Figma's own dedicated mobile mockup for this component (node
     3768:3473) doesn't carry over the horizontal-scroll treatment above
     (that one was this file's own explicit-request substitute for
     whatever Figma showed at the time) — it's back to the desktop's
     "scattered overlapping rotated pills" idea, just with its own mobile-
     specific rotation angles/positions/photo shape, checked directly off
     that node's own resolved geometry (below) rather than the ~900px
     block's swipe-row. Overrides *every* layout property that block set
     on `.stats-pills`/`.stats-pill`/`.stats-pill--center` (not just the
     ones this changes) since both blocks share those selectors at equal
     specificity and this one only wins by coming later in the file. */
  .ballpit-countdown__stats-photo {
    /* Figma: 343x341 at this 375px-wide mockup (near-square, not the
       desktop 39.6vw-tall/60px-radius treatment) — `aspect-ratio` instead
       of a fixed height keeps it exact while still scaling with whatever
       width `.stats-photo-wrap` actually renders at down to narrow phones. */
    height: auto;
    aspect-ratio: 343 / 341;
    border-radius: 1.25rem; /* 20px */
  }

  .ballpit-countdown__stats-pills {
    display: block;
    position: relative;
    width: 100%;
    /* Figma: 355x232 pill-cluster box sitting 47px below the photo above
       (measured off both elements' own resolved Y positions in that same
       mockup, not a value this box's own children could derive on their
       own) — `aspect-ratio` again instead of a fixed height so the 3
       pills' own `top`/`left` percentages below keep landing on the same
       relative spot as the box scales with viewport width. */
    aspect-ratio: 355 / 232;
    margin-top: 2.9375rem; /* 47px */
    overflow: visible;
    flex-wrap: unset;
    justify-content: unset;
    overflow-x: visible;
    scroll-snap-type: none;
    padding-left: 0;
    padding-right: 0;
    gap: 0;
  }

  /* Figma positions each pill as a *rotated* sticker, anchored by its
     post-rotation bounding box — but a rotated box's own center is
     invariant to that rotation, so anchoring by center instead (`left`/
     `top` at the center point, `translate(-50%, -50%)` to pull the box
     back so that point lands on its own center, then `rotate()`) sidesteps
     having to reverse-derive each pill's true unrotated corner from that
     bounding box, and stays exact regardless of this box's real rendered
     height (padding/line-height make that slightly taller than Figma's
     own 182x112px pill, which would otherwise throw off a corner-based
     reverse calc).

     The 3 centers below are measured directly off Figma's own rendered
     PNG for this node (pixel-analyzed), not this node's raw metadata —
     this component's `get_metadata` `x`/`y` for the two *rotated* pills
     didn't line up with what the design actually renders (reverse-
     computing a corner from them the naive way put both rotated pills
     visibly further right/down than Figma shows, confirmed by comparing
     screenshots directly), so only the *unrotated* pill (`--right`,
     0deg) uses its metadata position as-is; the other two are read off
     the rendered pixels instead. As % of the 355x232 cluster box: left
     (138.5, 60), center (272, 168), right (91, 176) px — `--right`'s
     matches metadata exactly since no rotation is involved there to
     cause the same mismatch.

     This also sets `transform` directly instead of going through
     `--bpc-pill-rotate` (the desktop rule's own indirection, set via
     inline `style` in `bpc_render_stat_pill()`) — simpler than fighting
     that inline style's specificity, and safe because this selector is
     already both more specific (two classes) and later in the file than
     the plain `.stats-pill` rule that reads the custom property. */
  .ballpit-countdown__stats-pill,
  .ballpit-countdown__stats-pill--center {
    position: absolute;
    width: 51.27%;
    margin: 0;
    /* Desktop's own 28px/16px/24px (`.stats-pill` above) is tuned for its
       much bigger pill; Figma's mobile pill uses equal 24px top/bottom,
       and matching that here (rather than keeping the desktop split)
       brings this pill's real rendered height down close enough to
       Figma's own 112px that the center-point math above lands the 3
       pills' overlap at roughly what Figma itself shows, instead of
       several extra px of it from this box simply being taller. */
    padding: 1.5rem 1rem;
  }

  .ballpit-countdown__stats-pill--left {
    left: 39%;
    top: 25.86%;
    transform: translate(-50%, -50%) rotate(-6.32deg);
  }

  .ballpit-countdown__stats-pill--center {
    left: 76.6%;
    top: 72.4%;
    transform: translate(-50%, -50%) rotate(21.67deg);
  }

  .ballpit-countdown__stats-pill--right {
    left: 25.63%;
    top: 75.86%;
    transform: translate(-50%, -50%) rotate(0deg);
  }

  /* Figma's mobile "Applicants" label uses its own smaller/lighter
     "Mobile/Body-sm" style (Medium 500, 13px, 0.26px tracking) rather
     than the desktop label's bolder one (Bold 700, 16px, -0.03em) — same
     genuinely-different-per-breakpoint pattern as `.partners-cta-header
     p`'s own mobile override elsewhere in this file. The number's own
     40px size is also Figma-exact here rather than the shared clamp's
     36px floor at this width. */
  .ballpit-countdown__stats-pill-num {
    font-size: 2.5rem; /* 40px */
  }

  .ballpit-countdown__stats-pill-label {
    font-weight: 500;
    font-size: 0.8125rem; /* 13px */
    letter-spacing: 0.26px;
  }
}

@media (min-width: 901px) {
  /* Figma's desktop mockup for this component was revised too (node
     3724:14888, at this file's usual 1440px reference width) — bigger
     pills (448.373px, up from the previous ~19rem/304px cap) in a
     slightly different scattered arrangement, checked directly against
     that node's own resolved geometry. Scoped to `min-width: 901px` (not
     just left as the unconditional base rule) specifically so the
     ≤900px tablet swipe-row block above — a separate, still-current
     explicit request, not something this Figma update touched — keeps
     working unchanged; this only overrides the *wider* case, and has to
     come after every rule above to win the resulting specificity ties. */
  .ballpit-countdown__stats-pills {
    display: block;
    position: absolute;
    inset: 0;
    margin-top: 0;
    gap: 0;
  }

  /* With the pills now `position: absolute` (above), `.stats-photo-wrap`'s
     own height collapses to just `.stats-photo`'s 570px — it no longer
     gets any implicit height from the old flex row's own in-flow box.
     But the outer two pills' rotated bounding boxes still reach past the
     photo's own bottom edge by ~131px at the 1440px reference, and
     `.faq::before` right after this section (a decorative dome bulging
     *up* over whatever sits above it, per that rule's own comment) peaks
     a further ~86px above FAQ's own flat top edge, dead center — right
     where the (unrotated, so *shallower*-overflowing) center pill sits.
     Both were confirmed by direct measurement to actually clip the
     pills' own "Applicants" labels without this — the outer two from
     FAQ's flat top (a fixed ~131px at this section's own capped size),
     the center one from the dome specifically, whose own height is
     *not* capped the same way (still a plain `6vw`, so it keeps growing
     past 1440px even once `.stats-photo`/`.stats-pills` themselves stop
     growing). The two terms below are additive rather than one combined
     clamp for that reason: `clamp(...)` self-caps to match the pill
     overflow's own fixed px past ~1494px wide, while the bare `6vw`
     tracks the dome's own uncapped growth exactly at any width (checked
     directly at 1920px, where a single capped clamp alone had fallen
     behind the dome's own taller reach there and let it clip again).
     This is deliberately worst-case for both pills at once (the dome is
     actually shorter out at the *outer* pills' own position, and the
     *center* pill overflows less than the outer two do) rather than a
     tighter per-pill fit, trading a bit of extra bottom whitespace for
     staying correct at every viewport width. Goes on `.stats-section`
     (the outer section) rather than `.stats-photo-wrap` itself
     specifically so it doesn't touch `.stats-photo-wrap`'s own box —
     `.stats-pills` is `inset: 0` on that box, and its own percentages
     above are all relative to that box staying exactly 570px tall;
     padding here would grow it and throw every one of those percentages
     off. */
  .ballpit-countdown__stats-section {
    padding-bottom: calc(clamp(6rem, 9.1vw, 8.5rem) + 6vw);
  }

  /* Same "anchor by center, `translate(-50%,-50%)` + `rotate()`" technique
     as the mobile block above, for the same reason: Figma's own reported
     position for a *rotated* layer is its post-rotation bounding box, and
     reverse-deriving that rotated box's true unrotated corner is both
     fiddly and (confirmed directly, see the mobile block's own comment)
     easy to get visibly wrong — anchoring by the rotation-invariant
     center sidesteps it entirely. Percentages are of `.stats-pills`'
     own box, which now spans exactly `.stats-photo`'s 1202x570 (Figma:
     119,89 is that photo's own top-left in the 1440px reference, so
     each pill's absolute center minus that offset, divided by 1202/570,
     is that pill's % position here) — not the old flex row's own
     content-sized box. */
  .ballpit-countdown__stats-pill,
  .ballpit-countdown__stats-pill--center {
    position: absolute;
    width: 37.3%; /* 448.373 / 1202 */
    margin: 0;
  }

  .ballpit-countdown__stats-pill--left {
    left: 11.95%;
    top: 103.05%;
    transform: translate(-50%, -50%) rotate(-5.72deg);
  }

  .ballpit-countdown__stats-pill--center {
    left: 50.02%;
    top: 99.01%;
    transform: translate(-50%, -50%) rotate(0deg);
  }

  .ballpit-countdown__stats-pill--right {
    left: 88.96%;
    top: 103.09%;
    transform: translate(-50%, -50%) rotate(5.66deg);
  }

  /* Figma: 100px number (up from this file's previous 4rem/64px cap) and
     a 24px label (up from 1rem/16px) — both scaled via the same vw-at-
     1440px-baseline convention the rest of this file already uses for
     this component (`.stats-pill`'s own comment above), not a flat px
     value, so they keep tracking the pill's own `clamp()`-free 37.3%
     width reasonably as the viewport moves through the desktop range. */
  .ballpit-countdown__stats-pill-num {
    font-size: clamp(3rem, 6.94vw, 6.25rem); /* 100px */
  }

  .ballpit-countdown__stats-pill-num span {
    /* Figma: the "+" sits at 81.861px against a 100px number (81.9%),
       not this file's previous 0.7em ratio. */
    font-size: 0.819em;
  }

  .ballpit-countdown__stats-pill-label {
    font-size: clamp(1rem, 1.67vw, 1.5rem); /* 24px */
  }
}