/* ══════════════════════════════════════════════════════════════
   ACE BOUNCE — hero
   Two acts, one pinned stage:
     1 FILM  a continuous scroll-driven timelapse, golden hour -> night,
             ending on a slow push-in. One canvas, no cuts.
     2 TYPE  macro footage inside letterforms

   No sound.

   NOTE: no filter:blur() on any full-bleed layer. It tanks framerate on
   mid-range Android. Where softness is needed it's a gradient or a
   pre-blurred asset.
   ══════════════════════════════════════════════════════════════ */

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--ink);color:var(--line);
  font-family:var(--font-body);
  overflow-x:hidden;
}
img{display:block;max-width:100%}

/* ── progress rail ─────────────────────────────────────────── */
.rail{position:fixed;top:0;left:0;right:0;height:2px;z-index:60;background:rgba(255,255,255,.06)}
.rail i{display:block;height:100%;width:0;background:var(--lime);transform-origin:0 50%}

/* ── stage ─────────────────────────────────────────────────── */
.hero{position:relative}
.stage{
  position:relative;height:100svh;width:100%;
  overflow:hidden;background:var(--ink);
}
/* Flex + absolutely-positioned headlines, NOT grid.
   `display:grid; place-items:center` with two children creates two implicit
   rows and stacks them vertically — the headline overflowed the stage. */
.act{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}

/* ══ ACT 1 · TIME ══════════════════════════════════════════
   Visible from the first frame — the hero opens on the court, not on
   a blueprint. (The technical drawing now lives in §01 The Court.) */
.act--time{opacity:1}
.plates{position:absolute;inset:0;overflow:hidden}
.poster,.seq{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;display:block;
}
/* poster holds the opening frame until the sequence decodes, then hands over */
.poster{z-index:1;transition:opacity .45s ease}
.seq{z-index:2;will-change:transform;transform-origin:50% 55%}

/* cutouts — three parallax depths */
.cutouts{position:absolute;inset:0;pointer-events:none;opacity:0}
.cut{
  position:absolute;bottom:6%;left:var(--x);
  transform:translate(-50%,0) scale(var(--s));
  transform-origin:50% 100%;
  will-change:transform;
}
.d-bg{height:12vh;filter:none}
.d-mg{height:20vh}
.d-fg{height:34vh}
/* soft contact shadow — a radial gradient, not a blur filter */
.cut::after{
  content:"";position:absolute;left:50%;bottom:-2%;
  width:120%;height:14px;transform:translateX(-50%);
  background:radial-gradient(ellipse at center,rgba(0,0,0,.55),transparent 70%);
}

/* ══ ACT 3 · TYPE ══════════════════════════════════════════ */
.act--type{opacity:0}
.beat--3{text-align:center;max-width:92vw}
.fill i{
  background-repeat:no-repeat;background-size:cover;background-position:center;
  -webkit-background-clip:text;background-clip:text;
  color:transparent;
}
.fill--shoe   i{background-image:url(../assets/macro/macro-shoe.webp)}
.fill--paddle i{background-image:url(../assets/macro/macro-paddle.webp)}

.outro{position:absolute;bottom:8vh;display:grid;justify-items:center;gap:22px;opacity:0}
.mark{width:74px;height:74px}
.cta{
  position:relative;display:inline-block;text-decoration:none;overflow:hidden;
  font-weight:600;letter-spacing:.16em;text-transform:uppercase;font-size:13px;
  color:var(--lime);border:1px solid var(--lime);padding:17px 38px;
  will-change:transform;
}
.cta span{position:relative;z-index:1;display:block;will-change:transform}
.cta::before{
  content:"";position:absolute;inset:0;background:var(--lime);
  transform:scaleY(0);transform-origin:50% 100%;transition:transform .45s cubic-bezier(.16,1,.3,1);
}
.cta:hover{color:var(--ink)}
.cta:hover::before{transform:scaleY(1)}
.sub{font-size:11px;letter-spacing:.18em;opacity:.5;text-transform:uppercase;margin:0}

/* ══ TYPE ══════════════════════════════════════════════════ */
.beat{
  position:relative;z-index:5;margin:0;
  font-family:var(--font-display);text-transform:uppercase;
  letter-spacing:-.02em;line-height:.86;
  font-size:clamp(30px,7.4vw,116px);
}
/* absolute so they overlay the act rather than sharing flow with it */
.beat--1,.beat--2{position:absolute;left:7vw;bottom:11vh;margin:0;max-width:86vw}
.beat .ln{display:block;overflow:hidden}
.beat .ln i{display:block;font-style:normal;transform:translateY(105%)}

/* ══ OVERLAYS ══════════════════════════════════════════════ */
.vig{
  position:absolute;inset:0;pointer-events:none;z-index:15;
  background:radial-gradient(ellipse 120% 90% at 50% 45%,transparent 45%,rgba(0,0,0,.55) 100%);
}
.grain{
  position:absolute;inset:0;pointer-events:none;z-index:30;
  background:url(../assets/vector/grain.png);opacity:.05;
  mix-blend-mode:overlay;
}

/* ══ CURSOR ════════════════════════════════════════════════ */
.dot{
  position:fixed;top:0;left:0;width:26px;height:26px;border-radius:50%;
  border:1px solid var(--lime);pointer-events:none;z-index:70;
  transform:translate(-50%,-50%);mix-blend-mode:difference;
}
@media (hover:none){.dot{display:none}}

/* ══ RESPONSIVE ════════════════════════════════════════════ */
@media (max-width:760px){
  .beat--1,.beat--2{margin:0 0 16vh 6vw}
  .beat{font-size:clamp(28px,9.4vw,60px)}
  .d-bg{display:none}          /* fewer layers, keeps 60fps on mid-range */
  .d-mg{height:15vh}
  .d-fg{height:26vh}
  .grain{opacity:.04}
}

/* ══ REDUCED MOTION ════════════════════════════════════════
   Show the final state of every act rather than animating through.
   Scroll still works; nothing moves on its own. */
@media (prefers-reduced-motion:reduce){
  .act--time,.act--type,.cutouts,.outro{opacity:1}
  .beat .ln i{transform:none}
    .scroll-hint{display:none}
}
