/* ============================================================
   ANIMATIONS — keyframes, scroll reveals, cursor, transitions
   ============================================================ */

/* ------------------------- KEYFRAMES ------------------------- */
@keyframes grainDrift{
  0%{transform:translate(0,0)}      20%{transform:translate(-4%,3%)}
  40%{transform:translate(3%,-4%)}  60%{transform:translate(-3%,-3%)}
  80%{transform:translate(4%,2%)}   100%{transform:translate(0,0)}
}
@keyframes kenBurns{
  0%  { transform: scale(1.06) translate3d(0,0,0); }
  100%{ transform: scale(1.20) translate3d(-1.6%,-1.4%,0); }
}
@keyframes floatY{
  0%,100%{ transform:translateY(0) }
  50%    { transform:translateY(-13px) }
}
@keyframes spinSlow{ to{ transform:rotate(360deg) } }
@keyframes marquee{ from{ transform:translate3d(0,0,0) } to{ transform:translate3d(-50%,0,0) } }
@keyframes marqueeRev{ from{ transform:translate3d(-50%,0,0) } to{ transform:translate3d(0,0,0) } }
@keyframes pulseRing{
  0%  { transform:scale(.85); opacity:.85 }
  70% { transform:scale(1.45); opacity:0 }
  100%{ transform:scale(1.45); opacity:0 }
}
@keyframes shimmer{ 0%{ background-position:-160% 0 } 100%{ background-position:260% 0 } }
@keyframes fadeUp{ from{ opacity:0; transform:translateY(26px) } to{ opacity:1; transform:none } }
@keyframes drawIn{ from{ stroke-dashoffset: var(--dash, 900) } to{ stroke-dashoffset:0 } }
@keyframes scrollNudge{
  0%  { transform:translateY(-60%); opacity:0 }
  35% { opacity:1 }
  100%{ transform:translateY(190%); opacity:0 }
}
@keyframes haloDrift{
  0%,100%{ transform:translate3d(0,0,0) scale(1) }
  33%    { transform:translate3d(6%,-5%,0) scale(1.12) }
  66%    { transform:translate3d(-5%,4%,0) scale(.94) }
}
@keyframes curtainIn { from{ transform:scaleY(0) } to{ transform:scaleY(1) } }
@keyframes curtainOut{ from{ transform:scaleY(1) } to{ transform:scaleY(0) } }

/* ------------------------- SCROLL REVEALS ------------------------- */
/* Applied by js/motion.js via [data-reveal] */
[data-reveal]{
  opacity:0;
  transition:
    opacity  var(--d-mid) var(--e-out),
    transform var(--d-slow) var(--e-out),
    clip-path var(--d-slow) var(--e-out),
    filter   var(--d-mid) var(--e-out);
  transition-delay: var(--rd, 0ms);
  will-change: opacity, transform;
}
[data-reveal="up"]     { transform: translate3d(0, 44px, 0); }
[data-reveal="down"]   { transform: translate3d(0,-34px, 0); }
[data-reveal="left"]   { transform: translate3d(-52px,0,0); }
[data-reveal="right"]  { transform: translate3d( 52px,0,0); }
[data-reveal="scale"]  { transform: scale(.90); }
[data-reveal="blur"]   { filter: blur(14px); transform: translate3d(0,22px,0); }
[data-reveal="zoom"]   { transform: scale(1.14); }
[data-reveal="fade"]   { transform:none; }

[data-reveal].is-in{
  opacity:1; transform:none; filter:none;
}

/* ---- wipe reveals ----
   IMPORTANT: never put clip-path on the observed element itself. Chrome
   clips the IntersectionObserver rectangle by clip-path, so an element
   hidden with `inset(0 0 100% 0)` reports zero intersection and can never
   become visible — it stays hidden forever. Clip the children instead:
   the observed element keeps a plain opacity/transform hidden state. */
[data-reveal="mask"]{ transform: translate3d(0,18px,0); }
[data-reveal="mask"] > *{
  clip-path: inset(0 0 100% 0);
  transition: clip-path var(--d-slow) var(--e-out);
  transition-delay: var(--rd, 0ms);
}
[data-reveal="mask"].is-in > *{ clip-path: inset(0 0 0 0); }

[data-reveal="curtain"] > *{
  clip-path: inset(0 100% 0 0);
  transition: clip-path var(--d-slow) var(--e-out);
  transition-delay: var(--rd, 0ms);
}
[data-reveal="curtain"].is-in > *{ clip-path: inset(0 0 0 0); }

/* Stagger children */
[data-stagger] > *{ opacity:0; transform:translate3d(0,34px,0); }
[data-stagger].is-in > *{
  animation: fadeUp .55s var(--e-out) forwards;
  animation-delay: calc(var(--i, 0) * var(--step, 55ms));
}

/* ------------------------- SPLIT TEXT ------------------------- */
.split{ display:block; }
.split .line{
  display:block; overflow:hidden;
  padding-bottom:.14em; margin-bottom:-.06em;
}
.split .word{
  display:inline-block;
  transform: translate3d(0,110%,0) rotate(3deg);
  opacity:0;
  transition: transform .62s var(--e-out), opacity .4s var(--e-out);
  transition-delay: calc(var(--wi,0) * 26ms + var(--rd, 0ms));
  will-change: transform;
}
.split.is-in .word{ transform:none; opacity:1; }

/* ------------------------- CUSTOM CURSOR ------------------------- */
.cursor-dot,.cursor-ring{
  position:fixed; top:0; left:0; z-index:var(--z-cursor);
  pointer-events:none; border-radius:50%;
  mix-blend-mode:difference;
  will-change: transform;
}
.cursor-dot{ width:7px; height:7px; background:#fff; margin:-3.5px 0 0 -3.5px; }
.cursor-ring{
  width:38px; height:38px; margin:-19px 0 0 -19px;
  border:1px solid rgba(255,255,255,.7);
  transition: width .35s var(--e-out), height .35s var(--e-out),
              margin .35s var(--e-out), border-color .35s var(--e-out),
              opacity .3s linear, background-color .35s var(--e-out);
}
.cursor-ring.is-hot{
  width:74px; height:74px; margin:-37px 0 0 -37px;
  border-color: transparent; background: rgba(255,255,255,.92);
}
.cursor-ring.is-view{
  width:96px; height:96px; margin:-48px 0 0 -48px;
  border-color: rgba(255,255,255,.9);
}
.cursor-ring .cur-label{
  position:absolute; inset:0; display:grid; place-items:center;
  font-family:var(--f-body); font-size:9.5px; letter-spacing:.22em;
  text-transform:uppercase; color:#fff; opacity:0;
  transition:opacity .25s linear;
}
.cursor-ring.is-view .cur-label{ opacity:1; }
.cursor-hidden .cursor-dot,.cursor-hidden .cursor-ring{ opacity:0; }
@media (hover:none), (pointer:coarse){ .cursor-dot,.cursor-ring{ display:none !important; } }

/* ------------------------- SCROLL PROGRESS ------------------------- */
.scroll-rail{
  position:fixed; top:0; left:0; right:0; height:3px;
  z-index: calc(var(--z-header) + 5);
  pointer-events:none;
  background: color-mix(in srgb, var(--text) 8%, transparent);
}
.scroll-progress{
  position:absolute; inset:0;
  transform-origin:0 50%; transform:scaleX(0);
  background-image: var(--grad-hot);
  box-shadow: 0 0 14px rgba(225,29,110,.55);
}

/* the glowing head that rides the leading edge of the bar */
.scroll-dot{
  position:absolute; top:50%; left:0;
  width:11px; height:11px; margin:-5.5px 0 0 -5.5px;
  border-radius:50%;
  background-image: var(--grad-hot);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--bg) 80%, transparent),
              0 0 16px 2px rgba(225,29,110,.7);
  opacity:0;
  transition: opacity .35s var(--e-out);
}
.scroll-rail.is-active .scroll-dot{ opacity:1; }
.scroll-rail.is-active .scroll-dot::after{
  content:""; position:absolute; inset:-4px; border-radius:50%;
  border:1px solid var(--accent);
  animation: pulseRing 1.8s var(--e-out) infinite;
}
@media (prefers-reduced-motion: reduce){
  .scroll-dot,.scroll-rail.is-active .scroll-dot::after{ animation:none; }
}

/* ------------------------- PAGE TRANSITION ------------------------- */
.page-curtain{
  position:fixed; inset:0; z-index:var(--z-overlay);
  pointer-events:none; display:grid;
  grid-template-columns:repeat(5,1fr);
}
.page-curtain span{
  background: var(--bg-invert);
  transform: scaleY(0); transform-origin: bottom;
}
.page-curtain.is-out span{
  animation: curtainIn .55s var(--e-in-out) forwards;
  animation-delay: calc(var(--ci, 0) * 55ms);
  transform-origin: bottom;
}
.page-curtain.is-in span{
  transform: scaleY(1); transform-origin: top;
  animation: curtainOut .55s var(--e-in-out) forwards;
  animation-delay: calc(var(--ci, 0) * 55ms);
}

/* ------------------------- PRELOADER ------------------------- */
.loader{
  position:fixed; inset:0; z-index:var(--z-loader);
  background: var(--bg);
  display:grid; place-items:center;
  transition: opacity .38s var(--e-out), visibility .38s;
}
.loader.is-done{ opacity:0; visibility:hidden; }
.loader__inner{ display:grid; place-items:center; gap:1.6rem; text-align:center; }
.loader__mark{ width:clamp(72px,10vw,104px); color:var(--accent); }
.loader__mark path,.loader__mark circle,.loader__mark line{
  stroke: currentColor; fill:none; stroke-width:1.2;
  stroke-dasharray: var(--dash,900); stroke-dashoffset: var(--dash,900);
  animation: drawIn 1.5s var(--e-out) forwards;
}
.loader__word{
  font-family:var(--f-body); font-size:var(--t-xs);
  letter-spacing:.42em; text-transform:uppercase; color:var(--text-mut);
}
.loader__bar{
  width:min(210px,42vw); height:1px; background:var(--line); position:relative; overflow:hidden;
}
.loader__bar i{
  position:absolute; inset:0; background:var(--accent);
  transform:scaleX(0); transform-origin:0 50%;
  transition: transform .35s linear;
}
.loader__num{
  font-family:var(--f-mono); font-size:var(--t-xs);
  color:var(--text-mut); letter-spacing:.1em;
}

/* ------------------------- MISC MOTION ------------------------- */
.float{ animation: floatY 6.5s ease-in-out infinite; }
.spin-slow{ animation: spinSlow 26s linear infinite; }

.shimmer-text{
  background: linear-gradient(100deg,
    var(--text) 20%, var(--accent-hi) 42%, var(--accent) 52%, var(--text) 74%);
  background-size: 260% 100%;
  -webkit-background-clip:text; background-clip:text;
  color:transparent;
  animation: shimmer 6.5s linear infinite;
}

/* Parallax hooks — js/motion.js writes --py */
[data-parallax]{ will-change: transform; }
[data-parallax] > img,[data-parallax] > .px-img{
  transform: translate3d(0, var(--py, 0px), 0) scale(var(--pscale,1.16));
  transition: transform .08s linear;
}

/* Magnetic buttons — js writes --mx/--my */
[data-magnetic]{
  transform: translate3d(var(--mx,0px), var(--my,0px), 0);
  transition: transform .45s var(--e-out);
}

/* Tilt cards — js writes --rx/--ry */
[data-tilt]{
  transform: perspective(1100px) rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg));
  transition: transform .5s var(--e-out);
  transform-style: preserve-3d;
}

/* ------------------------- REDUCED MOTION ------------------------- */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
    scroll-behavior:auto !important;
  }
  [data-reveal],[data-stagger] > *,.split .word,
  [data-reveal="mask"] > *,[data-reveal="curtain"] > *{
    opacity:1 !important; transform:none !important;
    filter:none !important; clip-path:none !important;
  }
  .cursor-dot,.cursor-ring{ display:none !important; }
  .page-curtain{ display:none !important; }
}
