/* ════════════════════════════════════════════════════════════════════════
   VICTORY LAP · MOTION LAYER
   The Finer Details Club motion system, adapted to Victory Lap's dark theme.
   Loaded after style.css on every page, driven by motion.js.

   Nothing here hides content unless motion.js is confirmed running: every
   "starts invisible" rule is gated behind html.reveal-ready, which the inline
   head script sets and removes again if motion.js never arrives.
   ════════════════════════════════════════════════════════════════════════ */

:root{
  --m-ease:cubic-bezier(.22,.61,.36,1);
  --m-ease-out:cubic-bezier(.16,1,.3,1);
}

/* ── Lenis (from lenis@1.3.26/dist/lenis.css) ── */
html.lenis,html.lenis body{height:auto}
.lenis:not(.lenis-autoToggle).lenis-stopped{overflow:clip}
.lenis [data-lenis-prevent],.lenis [data-lenis-prevent-wheel],.lenis [data-lenis-prevent-touch]{overscroll-behavior:contain}
.lenis.lenis-smooth iframe{pointer-events:none}
/* style.css sets html{scroll-behavior:smooth}; with Lenis driving the scroll
   that double-smooths every jump, so it's switched off while Lenis is active */
html.lenis{scroll-behavior:auto!important}

/* clip rather than hidden: hidden can turn body into a scroll container, which
   silently breaks position:sticky (the hero and the word stacks both need it) */
body{overflow-x:hidden;overflow-x:clip}

/* ── Scroll reveals: blur + rise ── */
html:not(.reveal-ready) [data-reveal]{opacity:1!important;transform:none!important;filter:none!important}
html.reveal-ready [data-reveal]{
  opacity:0;transform:translateY(28px);filter:blur(10px);
  transition:opacity .95s var(--m-ease),transform .95s var(--m-ease),filter .95s var(--m-ease);
}
html.reveal-ready [data-reveal].in{opacity:1;transform:none;filter:blur(0)}

/* ── Hero copy entrance ── */
.hero-anim{animation-duration:1.15s;animation-timing-function:var(--m-ease)}

/* ── Floating pill nav ── */
.navbar{
  top:14px;left:14px;right:14px;margin:0 auto;max-width:1320px;
  border-radius:18px;padding:0 12px 0 24px;
  background:rgba(9,11,15,0);border:1px solid rgba(255,255,255,0);
  /* always a (zero) backdrop filter: that keeps the navbar the containing block
     for the fixed mobile menu in both states, so the menu never jumps position */
  -webkit-backdrop-filter:blur(0px);backdrop-filter:blur(0px);
  box-shadow:none;
  transition:background .35s,border-color .35s,box-shadow .35s,-webkit-backdrop-filter .35s,backdrop-filter .35s;
}
.navbar.scrolled,.navbar.menu-open{
  background:rgba(10,12,16,.74);border-color:rgba(255,255,255,.07);
  -webkit-backdrop-filter:blur(18px) saturate(160%);backdrop-filter:blur(18px) saturate(160%);
  box-shadow:0 14px 34px -20px rgba(0,0,0,.85);
}
.navbar .nav-cta{border-radius:12px!important}
@media(max-width:1100px){
  .navbar{left:10px;right:10px;top:10px;padding:0 10px 0 18px}
  .navbar .nav-links{
    top:calc(100% + 8px)!important;left:0!important;right:0!important;
    border-radius:16px;border:1px solid rgba(255,255,255,.08)!important;
    background:rgba(10,12,16,.96)!important;
  }
}

/* ════════════════════════════════════════════════════════════════════════
   HOMEPAGE HERO · the Range Rover gets washed as you scroll
   ════════════════════════════════════════════════════════════════════════ */
.hero-pin{position:relative;height:210vh}
.hero-pin>.hero-photo{position:sticky;top:0}
/* first frame is the dirty car, but only when the scene will actually run;
   without JS or with reduced motion the inline style's clean frame stays */
html.reveal-ready .hero-pin .hero-photo-bg{background-image:url('images/hero-wash/f1.webp')!important}
.hero-wash{position:absolute;inset:0;width:100%;height:100%;z-index:0;pointer-events:none;opacity:0;transition:opacity .4s}
.hero-wash.ready{opacity:1}

.hero-cue{
  position:absolute;left:50%;bottom:26px;transform:translateX(-50%);z-index:3;
  display:flex;flex-direction:column;align-items:center;gap:10px;
  font-family:'Inter',sans-serif;font-size:.62rem;font-weight:700;letter-spacing:.28em;text-transform:uppercase;
  color:rgba(255,255,255,.55);pointer-events:none;transition:opacity .3s;
}
.hero-cue i{position:relative;display:block;width:1px;height:38px;background:rgba(255,255,255,.14);overflow:hidden}
.hero-cue i::after{content:'';position:absolute;left:0;top:-40%;width:1px;height:40%;background:rgba(255,255,255,.85);animation:cueDrop 1.9s var(--m-ease) infinite}
@keyframes cueDrop{to{top:100%}}

@media(max-width:900px){
  .hero-pin{height:auto}
  .hero-pin>.hero-photo{position:relative}
  .hero-cue{display:none}
}
@media(prefers-reduced-motion:reduce){
  .hero-pin{height:auto}
  .hero-pin>.hero-photo{position:relative}
  .hero-cue,.hero-wash{display:none}
}

/* ════════════════════════════════════════════════════════════════════════
   WORD STACK · pinned process steps (desktop)
   motion.js wraps an existing [data-stack] list. Below 901px none of the pin
   rules apply and the original list shows exactly as it always has.
   ════════════════════════════════════════════════════════════════════════ */
.stack-words,.stack-prog{display:none}
@media(min-width:901px) and (prefers-reduced-motion:no-preference){
  .stack-pin{position:relative;height:calc(var(--n,4) * 58vh + 100vh)}
  .stack-sticky{
    position:sticky;top:0;height:100vh;
    display:grid;grid-template-columns:minmax(0,1.2fr) minmax(0,1fr);align-items:center;gap:64px;
  }
  .stack-words{display:block;user-select:none}
  .stack-word.hf{
    display:block;font-size:clamp(3rem,6.6vw,6.6rem)!important;line-height:.94;letter-spacing:-.01em;
    color:rgba(255,255,255,.075);transition:color .55s var(--m-ease),text-shadow .55s var(--m-ease);
  }
  .stack-word.hf.on{color:#fff;text-shadow:0 0 50px rgba(180,200,240,.16)}
  /* only the lit word's full stop is accented; on faded words it fades too */
  .stack-word .dot{color:inherit;transition:color .55s var(--m-ease),text-shadow .55s var(--m-ease)}
  .stack-word.hf.on .dot{color:var(--green);text-shadow:0 0 22px rgba(230,235,242,.7)}

  /* the original steps become captions, one visible at a time */
  .stack-sticky .stack-caps{display:block!important;position:relative;min-height:320px;max-width:none;margin:0;grid-template-columns:none}
  html .stack-sticky .stack-caps>*{
    position:absolute;left:0;right:0;top:50%;
    opacity:0!important;filter:blur(8px)!important;transform:translateY(calc(-50% + 22px))!important;
    transition:opacity .6s var(--m-ease),transform .6s var(--m-ease),filter .6s var(--m-ease)!important;
    transition-delay:0s!important;pointer-events:none;
  }
  html .stack-sticky .stack-caps>.on{opacity:1!important;filter:none!important;transform:translateY(-50%)!important;pointer-events:auto}
  .stack-sticky .step-card{text-align:left}

  .stack-prog{display:flex;gap:8px;position:absolute;left:calc(54.5% + 32px);bottom:14vh}
  .stack-prog i{display:block;width:26px;height:2px;border-radius:2px;background:rgba(255,255,255,.14);transition:background .4s,width .4s}
  .stack-prog i.on{width:44px;background:var(--green)}
}

/* ════════════════════════════════════════════════════════════════════════
   TIMELINE · a line that fills as you scroll past each step
   ════════════════════════════════════════════════════════════════════════ */
.tl{position:relative;padding-left:46px}
.tl::before,.tl::after{content:'';position:absolute;left:17px;top:34px;bottom:34px;width:2px;border-radius:2px}
.tl::before{background:rgba(255,255,255,.09)}
.tl::after{background:linear-gradient(to bottom,rgba(230,235,242,.25),var(--green));bottom:auto;height:calc((100% - 68px) * var(--tl,0));box-shadow:0 0 14px rgba(230,235,242,.35)}
.tl>.process-step{position:relative}
.tl>.process-step::before{
  content:'';position:absolute;left:-35px;top:31px;width:10px;height:10px;border-radius:50%;
  background:#0b0d11;border:2px solid rgba(255,255,255,.2);z-index:1;
  transition:background .4s,border-color .4s,box-shadow .4s;
}
.tl>.process-step.passed::before{background:var(--green);border-color:var(--green);box-shadow:0 0 0 5px rgba(230,235,242,.08),0 0 16px rgba(230,235,242,.55)}
.tl>.process-step.passed{border-color:rgba(255,255,255,.16)}
@media(max-width:600px){
  .tl{padding-left:34px}
  .tl::before,.tl::after{left:11px}
  .tl>.process-step::before{left:-27px}
}

/* ════════════════════════════════════════════════════════════════════════
   REVIEW MARQUEE
   ════════════════════════════════════════════════════════════════════════ */
.marquee .carousel-wrap{
  overflow:hidden;
  -webkit-mask-image:linear-gradient(to right,transparent 0,#000 6%,#000 94%,transparent 100%);
          mask-image:linear-gradient(to right,transparent 0,#000 6%,#000 94%,transparent 100%);
}
.marquee .carousel-track{transition:none!important;will-change:transform;touch-action:pan-y;cursor:grab;padding:8px 0 14px}
.marquee .carousel-track.dragging{cursor:grabbing;user-select:none}
.marquee .carousel-track>.review-card{min-width:0}
@media(min-width:901px){ .marquee .carousel-track>.review-card{flex:0 0 400px!important;max-width:400px} }
@media(max-width:900px){ .marquee .carousel-track>.review-card{flex:0 0 min(82vw,380px)!important;max-width:380px} }
