/* ==========================================================
   VTL / VEX — atmosphere + motion layer
   Loaded on every page after vtl.css / the page's own styles.
   Everything here is decorative: it degrades to nothing under
   prefers-reduced-motion and never blocks interaction.
   ========================================================== */

:root{
  --fx-acid:var(--acid,#c8ff2f);
  --fx-violet:var(--violet,#a855f7);
  --fx-void:var(--void,#06050a);
  --fx-ease:var(--ease,cubic-bezier(.16,1,.3,1));
  --fx-spring:cubic-bezier(.34,1.4,.5,1);
}

/* The ambient layers sit at z-index -1, so whatever paints the page
   background has to live on <html> — otherwise body covers them.
   The script copies body's real background up to <html> first and only
   then sets this class, so pages with their own background keep it. */
html{background-color:var(--fx-void)}
html.fx-bg-moved > body{background:transparent!important}

/* vtl.css / vtl-override.css run the page-entry animation on <body> with
   fill-mode "both", which leaves an identity transform on body forever.
   A transformed ancestor becomes the containing block for position:fixed,
   so every .fx-layer stretched to the full document height instead of the
   viewport — the canvas bitmap got smeared over ~7x its height on mobile.
   Same entry animation, opacity only, no transform, no containing block. */
@keyframes vtl-page-in{from{opacity:0}to{opacity:1}}

.fx-layer{position:fixed;inset:0;pointer-events:none;z-index:-1;
  width:100%;height:100%;contain:strict}

/* ---------- 1. drifting aurora ---------- */
#fx-aura{overflow:hidden}
#fx-aura b{
  position:absolute;display:block;border-radius:50%;
  filter:blur(64px);opacity:.7;will-change:transform;
}
#fx-aura b:nth-child(1){
  width:46vw;height:46vw;left:-8vw;top:-10vw;
  background:radial-gradient(circle,rgba(200,255,47,.28),transparent 68%);
  animation:fx-drift-a 26s var(--fx-ease) infinite alternate;
}
#fx-aura b:nth-child(2){
  width:52vw;height:52vw;right:-14vw;top:22vh;
  background:radial-gradient(circle,rgba(168,85,247,.26),transparent 68%);
  animation:fx-drift-b 32s var(--fx-ease) infinite alternate;
}
#fx-aura b:nth-child(3){
  width:38vw;height:38vw;left:24vw;bottom:-14vw;
  background:radial-gradient(circle,rgba(200,255,47,.18),transparent 70%);
  animation:fx-drift-c 38s var(--fx-ease) infinite alternate;
}
@keyframes fx-drift-a{
  0%{transform:translate3d(0,0,0) scale(1)}
  100%{transform:translate3d(14vw,12vh,0) scale(1.25)}
}
@keyframes fx-drift-b{
  0%{transform:translate3d(0,0,0) scale(1.1)}
  100%{transform:translate3d(-16vw,-10vh,0) scale(.85)}
}
@keyframes fx-drift-c{
  0%{transform:translate3d(0,0,0) scale(.9)}
  100%{transform:translate3d(10vw,-16vh,0) scale(1.3)}
}

/* ---------- 2. constellation canvas ---------- */
#fx-canvas{display:block;width:100%;height:100%;opacity:.6}

/* ---------- 2b. dot matrix texture ---------- */
#fx-dots{
  background-image:radial-gradient(rgba(200,255,47,.16) 1px,transparent 1px);
  background-size:34px 34px;
  mask-image:radial-gradient(ellipse 90% 70% at 50% 40%,#000 20%,transparent 78%);
  -webkit-mask-image:radial-gradient(ellipse 90% 70% at 50% 40%,#000 20%,transparent 78%);
  animation:fx-dots-drift 22s linear infinite;opacity:.5;
}
@keyframes fx-dots-drift{
  0%{background-position:0 0}
  100%{background-position:34px 34px}
}

/* ---------- 3. film grain ---------- */
#fx-grain{
  opacity:.045;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
  animation:fx-grain-shift 700ms steps(3) infinite;
}
@keyframes fx-grain-shift{
  0%{transform:translate3d(0,0,0)}
  33%{transform:translate3d(-3%,2%,0)}
  66%{transform:translate3d(2%,-3%,0)}
  100%{transform:translate3d(0,0,0)}
}

/* ---------- 4. scanline sweep across the viewport ---------- */
#fx-scan{
  height:1px;inset:auto 0 auto 0;
  background:linear-gradient(90deg,transparent,rgba(200,255,47,.55) 30%,
    rgba(200,255,47,.85) 50%,rgba(200,255,47,.55) 70%,transparent);
  box-shadow:0 0 22px rgba(200,255,47,.35);
  animation:fx-scan-run 11s linear infinite;opacity:.5;
}
@keyframes fx-scan-run{
  0%{transform:translate3d(0,-5vh,0);opacity:0}
  8%{opacity:.5}
  92%{opacity:.5}
  100%{transform:translate3d(0,105vh,0);opacity:0}
}

/* ---------- 5. custom cursor ---------- */
.fx-cursor,.fx-cursor-dot{
  position:fixed;top:0;left:0;pointer-events:none;z-index:9999;
  border-radius:50%;will-change:transform;opacity:0;
  transition:opacity .3s,width .25s var(--fx-spring),
             height .25s var(--fx-spring),background-color .25s,border-color .25s;
}
.fx-cursor{width:30px;height:30px;margin:-15px 0 0 -15px;
  border:1px solid rgba(200,255,47,.55)}
.fx-cursor-dot{width:5px;height:5px;margin:-2.5px 0 0 -2.5px;
  background:var(--fx-acid)}
body.fx-cursor-on .fx-cursor,
body.fx-cursor-on .fx-cursor-dot{opacity:1}
body.fx-cursor-hot .fx-cursor{
  width:56px;height:56px;margin:-28px 0 0 -28px;
  border-color:var(--fx-acid);background:rgba(200,255,47,.09)}
body.fx-cursor-hot .fx-cursor-dot{opacity:0}
body.fx-cursor-down .fx-cursor{width:20px;height:20px;margin:-10px 0 0 -10px}

/* ---------- 6. word-by-word headline reveal ---------- */
.fx-split{display:inline}
.fx-w{display:inline-block;overflow:hidden;vertical-align:top;padding-bottom:.08em}
.fx-w > i{
  display:inline-block;font-style:inherit;
  transform:translate3d(0,110%,0) rotate(4deg);opacity:0;
  transition:transform .95s var(--fx-ease),opacity .7s var(--fx-ease);
  transition-delay:var(--wd,0ms);
}
.fx-split.in .fx-w > i{transform:none;opacity:1}

/* ---------- 7. extra reveal directions ---------- */
.rv[data-fx="left"]{transform:translate3d(-42px,0,0)}
.rv[data-fx="right"]{transform:translate3d(42px,0,0)}
.rv[data-fx="scale"]{transform:scale(.9)}
.rv[data-fx="blur"]{filter:blur(11px);transform:translate3d(0,18px,0)}
.rv[data-fx="flip"]{transform:perspective(900px) rotateX(-14deg) translate3d(0,26px,0)}
.rv[data-fx].in{transform:none;filter:none}
.rv[data-fx="blur"]{transition:opacity .85s var(--fx-ease),
  transform .85s var(--fx-ease),filter .85s var(--fx-ease)}

/* ---------- 8. card tilt + cursor spotlight ---------- */
.fx-tilt{
  transform:perspective(1000px)
            rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg))
            translate3d(0,var(--lift,0px),0);
  transition:transform .5s var(--fx-ease),border-color .35s,box-shadow .5s;
  will-change:transform;
}
.fx-tilt.fx-live{transition:transform .12s linear,border-color .35s,box-shadow .5s}
.fx-tilt::after{
  content:'';position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  background:radial-gradient(320px circle at var(--mx,50%) var(--my,50%),
    rgba(200,255,47,.13),transparent 62%);
  opacity:0;transition:opacity .4s;z-index:1;
}
.fx-tilt:hover::after{opacity:1}
.fx-tilt:hover{border-color:rgba(200,255,47,.36);
  box-shadow:0 22px 60px -28px rgba(200,255,47,.34)}

/* ---------- 9. magnetic buttons + shine sweep ---------- */
.fx-mag{
  transform:translate3d(var(--mgx,0px),var(--mgy,0px),0);
  transition:transform .45s var(--fx-spring),background-color .3s,
             color .3s,border-color .3s,box-shadow .4s;
  position:relative;overflow:hidden;
}
.fx-mag::before{
  content:'';position:absolute;top:0;left:-140%;width:65%;height:100%;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.22),transparent);
  transform:skewX(-22deg);transition:left .75s var(--fx-ease);pointer-events:none;
}
.fx-mag:hover::before{left:150%}
.fx-mag:hover{box-shadow:0 12px 34px -14px rgba(200,255,47,.55)}

/* click ripple */
.fx-ripple{
  position:absolute;border-radius:50%;pointer-events:none;
  background:rgba(255,255,255,.4);transform:scale(0);opacity:.7;
  animation:fx-ripple-go .62s var(--fx-ease) forwards;
}
@keyframes fx-ripple-go{to{transform:scale(2.6);opacity:0}}

/* ---------- 10. nav link sweep ---------- */
.nav-links a,.foot-links a{position:relative}
.nav-links a::after,.foot-links a::after{
  content:'';position:absolute;left:0;bottom:-5px;height:1px;width:100%;
  background:var(--fx-acid);transform:scaleX(0);transform-origin:100% 50%;
  transition:transform .45s var(--fx-ease);
}
.nav-links a:hover::after,.foot-links a:hover::after,
.nav-links a[aria-current]::after{transform:scaleX(1);transform-origin:0 50%}

/* ---------- 11. section eyebrow gets a live rule ---------- */
.sec-no,.section-no,.kicker{position:relative}
.sec-no::after,.section-no::after{
  content:'';position:absolute;left:calc(100% + .9rem);top:50%;height:1px;
  width:0;background:linear-gradient(90deg,var(--fx-acid),transparent);
  transition:width 1.1s var(--fx-ease) .15s;
}
.rv.in .sec-no::after,.rv.in .section-no::after,
.sec-head.in .sec-no::after{width:min(28vw,320px)}

/* ---------- 12. headline glow pulse on the acid mark ---------- */
.mark i{
  text-shadow:0 0 18px rgba(200,255,47,.55);
  animation:fx-mark-glow 3.4s ease-in-out infinite;
}
@keyframes fx-mark-glow{
  0%,100%{text-shadow:0 0 14px rgba(200,255,47,.35)}
  50%{text-shadow:0 0 26px rgba(200,255,47,.8)}
}

/* ---------- 13. counters ---------- */
.stat-n,[data-count]{font-variant-numeric:tabular-nums}

/* ---------- 14. marquee ticker strip ---------- */
.fx-ticker{
  position:relative;overflow:hidden;border-top:1px solid var(--rule,rgba(244,245,240,.13));
  border-bottom:1px solid var(--rule,rgba(244,245,240,.13));
  padding:.85rem 0;background:rgba(255,255,255,.015);
}
.fx-ticker-row{display:flex;width:max-content;animation:fx-ticker-run 34s linear infinite}
.fx-ticker:hover .fx-ticker-row{animation-play-state:paused}
.fx-ticker-row span{
  font-family:var(--mono,monospace);font-size:.7rem;letter-spacing:.2em;
  text-transform:uppercase;color:var(--faint,rgba(244,245,240,.28));
  padding:0 2rem;white-space:nowrap;display:flex;align-items:center;gap:2rem;
}
.fx-ticker-row span::after{content:'';width:5px;height:5px;border-radius:50%;
  background:var(--fx-acid);opacity:.55;flex-shrink:0}
@keyframes fx-ticker-run{to{transform:translate3d(-50%,0,0)}}

/* ---------- 15. page exit ---------- */
/* Opacity only — never transform. A transform here makes <body> the
   containing block for position:fixed and the whole ambient layer detaches
   from the viewport mid-navigation. */
/* Entry fade — a veil, not body opacity.
   Holding <body> transparent means anything that stalls leaves a blank
   page, and the fade was over before first paint anyway. This paints the
   page normally and fades a cover off the top of it, released on `load`
   so the first frame underneath is guaranteed to exist. */
html.fx-boot::before{
  content:'';position:fixed;inset:0;z-index:99999;pointer-events:none;
  background:var(--fx-void);opacity:1;
  /* ease-in-out, not ease-out: an ease-out curve dumps most of the
     change in the first 300ms and spends the rest on an invisible
     tail, so a 1.1s fade still read as short. */
  transition:opacity 1.2s cubic-bezier(.45,.05,.55,.95);
  /* safety net: if the script never runs, drop the veil at 3s anyway.
     forwards-only fill means this does nothing until the delay elapses,
     so it never fights the transition above. */
  animation:fx-veil-kill 0s linear 3s forwards;
}
html.fx-boot.fx-ready::before{opacity:0}
@keyframes fx-veil-kill{to{opacity:0;visibility:hidden}}

/* vtl.css and vtl-override.css still declare the old body animation */
body{animation:none;transition:opacity .3s var(--fx-ease)}

/* Exit fade — opacity only. A transform here would make body the containing
   block for position:fixed and detach the whole ambient layer mid-click. */
body.fx-leaving{opacity:0}

/* ---------- 16. scroll rail gets a glow head ---------- */
.prog{box-shadow:0 0 14px rgba(200,255,47,.75),0 0 3px rgba(200,255,47,1)}

/* ---------- 17. images / frames breathe on hover ---------- */
.widget-frame,.shot,.clip,.thumb{overflow:hidden}
.widget-frame:hover,.shot:hover,.clip:hover,.thumb:hover{
  border-color:rgba(200,255,47,.35)}

/* ---------- 18. anything acid gets a soft hover lift ---------- */
.btn-fill:hover{transform:translate3d(var(--mgx,0px),calc(var(--mgy,0px) - 2px),0)}

/* ---------- reduced motion: strip all of it ---------- */
@media(prefers-reduced-motion:reduce){
  #fx-aura,#fx-grain,#fx-scan,#fx-canvas,#fx-dots,
  .fx-cursor,.fx-cursor-dot{display:none!important}
  .fx-w > i{transform:none!important;opacity:1!important;transition:none!important}
  .fx-tilt{transform:none!important}
  .fx-mag{transform:none!important}
  .fx-mag::before{display:none}
  .mark i{animation:none}
  .fx-ticker-row{animation:none}
  .rv[data-fx]{transform:none!important;filter:none!important}
  html.fx-boot::before{display:none}
  body.fx-leaving{opacity:1}
}

/* ---------- touch / coarse pointer: no cursor, lighter canvas ---------- */
@media(pointer:coarse){
  .fx-cursor,.fx-cursor-dot{display:none!important}
  .fx-tilt{transform:none!important}
  #fx-scan{display:none}
}

/* ==========================================================
   Second motion pass
   ========================================================== */

/* ---------- 19. rotating border beam on hover ---------- */
.fx-beam{position:relative}
.fx-beam::before{
  content:'';position:absolute;inset:-1px;border-radius:inherit;padding:1px;
  background:conic-gradient(from var(--beam,0deg),transparent 0deg,
    var(--fx-acid) 40deg,rgba(168,85,247,.9) 80deg,transparent 130deg,
    transparent 360deg);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask:linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);mask-composite:exclude;
  opacity:0;transition:opacity .45s var(--fx-ease);pointer-events:none;z-index:2;
}
.fx-beam:hover::before{opacity:1;animation:fx-beam-spin 2.6s linear infinite}
@property --beam{syntax:'<angle>';initial-value:0deg;inherits:false}
@keyframes fx-beam-spin{to{--beam:360deg}}

/* ---------- 20. heading flares as it lands ---------- */
.fx-split.in{animation:fx-headglow 1.6s var(--fx-ease) .3s 1 both}
@keyframes fx-headglow{
  0%{text-shadow:0 0 0 rgba(200,255,47,0)}
  30%{text-shadow:0 0 30px rgba(200,255,47,.55),0 0 8px rgba(200,255,47,.35)}
  100%{text-shadow:0 0 0 rgba(200,255,47,0)}
}

/* ---------- 21. wordmark glitch on hover ---------- */
.mark{position:relative}
.mark:hover{animation:fx-glitch .34s steps(2,end) 2}
@keyframes fx-glitch{
  0%{transform:translate3d(0,0,0)}
  20%{transform:translate3d(-2px,1px,0);text-shadow:2px 0 var(--fx-violet),-2px 0 var(--fx-acid)}
  40%{transform:translate3d(2px,-1px,0);text-shadow:-2px 0 var(--fx-violet),2px 0 var(--fx-acid)}
  60%{transform:translate3d(-1px,0,0);text-shadow:1px 0 var(--fx-acid)}
  100%{transform:translate3d(0,0,0);text-shadow:none}
}

/* ---------- 22. list items arrive one at a time ---------- */
.fx-li{opacity:0;transform:translate3d(-14px,0,0);
  transition:opacity .6s var(--fx-ease),transform .6s var(--fx-ease);
  transition-delay:var(--ld,0ms)}
.fx-li.in{opacity:1;transform:none}

/* ---------- 23. frames wipe open ---------- */
.fx-wipe{clip-path:inset(0 100% 0 0);
  transition:clip-path 1s var(--fx-ease) .1s}
.fx-wipe.in{clip-path:inset(0 0 0 0)}

/* ---------- 24. pills breathe ---------- */
.chip,.tag,.pill,.badge{animation:fx-float 6s ease-in-out infinite;
  animation-delay:var(--fd,0ms)}
@keyframes fx-float{
  0%,100%{transform:translate3d(0,0,0)}
  50%{transform:translate3d(0,-3px,0)}
}

/* ---------- 25. scroll-velocity lean ----------
   The transform is applied inline only while scrolling and cleared on
   settle: a permanent skewY(0deg) still counts as a transform, and a
   transformed ancestor becomes the containing block for position:fixed. */
.wrap > section{transition:transform .5s var(--fx-ease)}

/* ---------- 26. cursor trail ---------- */
.fx-trail{position:fixed;top:0;left:0;width:4px;height:4px;border-radius:50%;
  background:var(--fx-acid);pointer-events:none;z-index:9998;opacity:0;
  will-change:transform,opacity}
body.fx-cursor-on .fx-trail{opacity:var(--to,.35)}

/* ---------- 26b. reduced motion / touch ---------- */
@media(prefers-reduced-motion:reduce){
  .fx-beam::before{display:none}
  .fx-split.in{animation:none}
  .mark:hover{animation:none}
  .fx-li{opacity:1!important;transform:none!important;transition:none!important}
  .fx-wipe{clip-path:none!important;transition:none!important}
  .chip,.tag,.pill,.badge{animation:none}
  .wrap > section{transform:none!important;transition:none!important}
  .fx-trail{display:none!important}
}
@media(pointer:coarse){
  .fx-trail{display:none!important}
  .fx-beam::before{display:none}
}

/* ==========================================================
   Third motion pass
   ========================================================== */

/* ---- 27. click burst ---- */
.fx-spark{position:fixed;width:6px;height:6px;border-radius:50%;pointer-events:none;
  z-index:9997;will-change:transform,opacity}

/* ---- 28. section rail ---- */
.fx-rail{position:fixed;right:clamp(.7rem,2vw,1.6rem);top:50%;z-index:180;
  transform:translateY(-50%);display:flex;flex-direction:column;gap:.7rem;
  pointer-events:none;opacity:0;transition:opacity .5s var(--fx-ease)}
.fx-rail.on{opacity:1}
.fx-rail i{display:block;width:6px;height:6px;border-radius:99px;
  background:rgba(244,245,240,.22);pointer-events:auto;cursor:pointer;
  transition:height .45s var(--fx-spring),background-color .35s,box-shadow .35s}
.fx-rail i:hover{background:rgba(200,255,47,.6)}
.fx-rail i.on{height:26px;background:var(--fx-acid);
  box-shadow:0 0 12px rgba(200,255,47,.6)}
@media(max-width:720px){.fx-rail{display:none}}

/* ---- 29. depth inside tilted cards ---- */
.fx-tilt > *{transform:translate3d(0,0,var(--depth,0px))}
.fx-tilt{transform-style:preserve-3d}
.fx-tilt h2,.fx-tilt h3,.fx-tilt .stat-n,.fx-tilt .tier-name,.fx-tilt .mod-name{
  --depth:26px}
.fx-tilt p,.fx-tilt ul,.fx-tilt .stat-l{--depth:12px}

/* ---- 30. idle breathing on the primary CTA ---- */
.fx-breathe{animation:fx-breathe 3.6s ease-in-out infinite}
@keyframes fx-breathe{
  0%,100%{box-shadow:0 0 0 0 rgba(200,255,47,.34)}
  50%{box-shadow:0 0 0 12px rgba(200,255,47,0)}
}

/* ---- 31. underline draws under section titles ---- */
.sec-title,.section-h,.page-title{position:relative}
.fx-underline::after{content:'';position:absolute;left:0;bottom:-.28em;height:2px;
  width:100%;background:linear-gradient(90deg,var(--fx-acid),transparent);
  transform:scaleX(0);transform-origin:0 50%;border-radius:2px;
  transition:transform 1.1s var(--fx-ease) .2s}
.fx-underline.in::after{transform:scaleX(1)}

/* ---- 32. skeleton shimmer while lists load ---- */
.fx-skeleton{position:relative;overflow:hidden;
  background:rgba(255,255,255,.03);border-radius:var(--r,16px);min-height:110px}
.fx-skeleton::after{content:'';position:absolute;inset:0;
  background:linear-gradient(100deg,transparent 20%,rgba(200,255,47,.10) 50%,
    transparent 80%);transform:translateX(-100%);
  animation:fx-shimmer 1.5s linear infinite}
@keyframes fx-shimmer{to{transform:translateX(100%)}}

/* ---- 33. party mode (konami) ---- */
html.fx-party{animation:fx-hue 6s linear infinite}
@keyframes fx-hue{to{filter:hue-rotate(360deg)}}
html.fx-party .mark i{animation:fx-mark-glow .6s ease-in-out infinite}

/* ---- reduced motion / touch ---- */
@media(prefers-reduced-motion:reduce){
  .fx-spark{display:none!important}
  .fx-rail{display:none!important}
  .fx-breathe{animation:none}
  .fx-underline::after{transform:scaleX(1)!important;transition:none}
  .fx-skeleton::after{animation:none}
  html.fx-party{animation:none}
}
@media(pointer:coarse){
  .fx-tilt > *{transform:none}
}

/* ==========================================================
   Fourth motion pass
   ========================================================== */

/* ---- 34. navigation progress bar ---- */
.fx-nav-bar{position:fixed;top:0;left:0;height:3px;width:100%;z-index:9999;
  transform-origin:0 50%;transform:scaleX(0);pointer-events:none;
  background:linear-gradient(90deg,var(--fx-acid),var(--fx-violet),var(--fx-acid));
  background-size:200% 100%;
  box-shadow:0 0 14px rgba(200,255,47,.8);opacity:0;
  transition:transform .28s cubic-bezier(.2,.8,.3,1),opacity .25s;
  animation:fx-navshine 1.4s linear infinite}
.fx-nav-bar.on{opacity:1}
@keyframes fx-navshine{to{background-position:200% 0}}

/* ---- 35. liquid button fill from the cursor ---- */
.fx-liquid{position:relative;overflow:hidden;isolation:isolate}
.fx-liquid::after{content:'';position:absolute;left:var(--lx,50%);top:var(--ly,50%);
  width:0;height:0;border-radius:50%;background:var(--fx-acid);
  transform:translate(-50%,-50%);transition:width .55s var(--fx-ease),
  height .55s var(--fx-ease),opacity .4s;opacity:.16;z-index:-1;pointer-events:none}
.fx-liquid:hover::after{width:260%;height:260%}

/* ---- 36. glass sweep across cards on hover ---- */
.fx-sheen{position:relative;overflow:hidden}
.fx-sheen::before{content:'';position:absolute;top:-60%;left:-80%;width:45%;height:220%;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.10),transparent);
  transform:rotate(14deg);transition:left .85s var(--fx-ease);pointer-events:none;z-index:2}
.fx-sheen:hover::before{left:150%}

/* ---- 37. the standing grid lines travel ---- */
.grid-lines span{position:relative;overflow:hidden}
.grid-lines span::after{content:'';position:absolute;left:-1px;top:0;width:1px;height:22%;
  background:linear-gradient(180deg,transparent,rgba(200,255,47,.55),transparent);
  animation:fx-gridrun 7s linear infinite;animation-delay:var(--gd,0s)}
@keyframes fx-gridrun{
  0%{transform:translateY(-30vh);opacity:0}
  10%{opacity:1}
  90%{opacity:1}
  100%{transform:translateY(130vh);opacity:0}
}

/* ---- 38. hero load choreography ---- */
.fx-cue{opacity:0;transform:translate3d(0,18px,0);
  animation:fx-cue-in .85s var(--fx-ease) forwards;
  animation-delay:var(--cue,0ms)}
@keyframes fx-cue-in{to{opacity:1;transform:none}}

/* ---- 39. wordmark letters react one at a time ---- */
.fx-letter{display:inline-block;transition:transform .3s var(--fx-spring),color .3s}
.mark:hover .fx-letter{transform:translateY(-4px)}
.mark:hover .fx-letter:nth-child(2){transition-delay:.04s}
.mark:hover .fx-letter:nth-child(3){transition-delay:.08s}

/* ---- 40. nav mark drifts gently at rest ---- */
.mark{animation:fx-mark-drift 7s ease-in-out infinite}
@keyframes fx-mark-drift{
  0%,100%{transform:translate3d(0,0,0)}
  50%{transform:translate3d(0,-2px,0)}
}

/* ---- reduced motion / touch ---- */
@media(prefers-reduced-motion:reduce){
  .fx-nav-bar{display:none!important}
  .fx-liquid::after{display:none}
  .fx-sheen::before{display:none}
  .grid-lines span::after{display:none}
  .fx-cue{opacity:1!important;transform:none!important;animation:none!important}
  .fx-letter{transition:none}
  .mark{animation:none}
}
@media(pointer:coarse){
  .fx-liquid::after{display:none}
  .fx-sheen::before{display:none}
}

/* ==========================================================
   41. popup / modal entrance
   These overlays toggle display:none -> flex, and display is not a
   transitionable property — which is why they snapped open with no
   animation. A keyframe animation does run when an element becomes
   displayed, so the entrance is driven by animation rather than
   transition.
   ========================================================== */
.pay-overlay.open,
.modal-overlay.open,
.modal-overlay.active,
.modal-overlay.show,
.modal-overlay[style*="flex"]{
  animation:fx-mask-in .3s var(--fx-ease) both;
}
.pay-overlay.open > .pay,
.modal-overlay.open > .modal,
.modal-overlay.active > .modal,
.modal-overlay.show > .modal,
.modal-overlay[style*="flex"] > .modal{
  animation:fx-dialog-in .42s var(--fx-spring) both;
}
@keyframes fx-mask-in{
  from{opacity:0;backdrop-filter:blur(0)}
  to{opacity:1}
}
@keyframes fx-dialog-in{
  from{opacity:0;transform:translate3d(0,22px,0) scale(.955)}
  to{opacity:1;transform:none}
}

/* the review dialog already eases itself; just give it the same curve */
.rv-mask.open .rv-dlg{
  animation:fx-dialog-in .42s var(--fx-spring) both;
}

@media(prefers-reduced-motion:reduce){
  .pay-overlay.open,.modal-overlay.open,.modal-overlay.active,
  .modal-overlay.show,.modal-overlay[style*="flex"],
  .pay-overlay.open > .pay,.modal-overlay.open > .modal,
  .modal-overlay.active > .modal,.modal-overlay.show > .modal,
  .rv-mask.open .rv-dlg{animation:none}
}
