/* ==========================================================================
   4BIT DIGITAL STUDIO — animations.css
   Keyframes, scroll-reveal system, reduced-motion fallbacks
   ========================================================================== */

/* ==========================================================================
   KEYFRAMES
   ========================================================================== */
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 rgba(33,208,122,.55); }
  70%  { box-shadow: 0 0 0 9px rgba(33,208,122,0); }
  100% { box-shadow: 0 0 0 0 rgba(33,208,122,0); }
}

@keyframes drift1 {
  0%   { transform: translate3d(0,0,0) scale(1); }
  100% { transform: translate3d(9vw, 7vh, 0) scale(1.22); }
}
@keyframes drift2 {
  0%   { transform: translate3d(0,0,0) scale(1.1); }
  100% { transform: translate3d(-11vw, 12vh, 0) scale(.88); }
}
@keyframes drift3 {
  0%   { transform: translate3d(0,0,0) scale(.92); }
  100% { transform: translate3d(7vw, -9vh, 0) scale(1.16); }
}

@keyframes grain {
  0%,100% { transform: translate(0,0); }
  10% { transform: translate(-3%,-4%); }
  20% { transform: translate(-8%,3%); }
  30% { transform: translate(4%,-6%); }
  40% { transform: translate(-2%,7%); }
  50% { transform: translate(-6%,2%); }
  60% { transform: translate(7%,0%); }
  70% { transform: translate(0%,5%); }
  80% { transform: translate(3%,8%); }
  90% { transform: translate(-4%,3%); }
}

@keyframes sheen {
  from { background-position: 160% 0; }
  to   { background-position: -60% 0; }
}

@keyframes bitIn {
  0%   { opacity: 0; transform: scale(.1) rotate(-45deg); }
  60%  { opacity: 1; transform: scale(1.18) rotate(6deg); }
  100% { opacity: 1; transform: scale(1) rotate(0); }
}

@keyframes marquee {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

@keyframes scrollDrop {
  0%   { transform: translateY(-100%); }
  55%  { transform: translateY(0%); }
  100% { transform: translateY(100%); }
}

@keyframes gradShift {
  0%   { background-position: 0% 50%; }
  50%  { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}

@keyframes floaty {
  0%,100% { transform: translateY(0); }
  50%     { transform: translateY(-10px); }
}

/* ==========================================================================
   SCROLL REVEAL
   Only active when JS is running, so no-JS visitors see everything.
   ========================================================================== */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(30px);
  transition:
    opacity .85s var(--e-out),
    transform .85s var(--e-out),
    filter .85s var(--e-out);
  filter: blur(6px);
  will-change: opacity, transform;
}
.js [data-reveal].is-in {
  opacity: 1;
  transform: none;
  filter: none;
}

/* staggered siblings */
.js [data-delay="1"] { transition-delay: .09s; }
.js [data-delay="2"] { transition-delay: .18s; }
.js [data-delay="3"] { transition-delay: .27s; }
.js [data-delay="4"] { transition-delay: .36s; }
.js [data-delay="5"] { transition-delay: .45s; }

/* ==========================================================================
   SPLIT-TEXT REVEAL
   JS wraps each word in .word > span, then --i drives the stagger.
   ========================================================================== */
.js [data-split] .word {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  padding-bottom: .14em;
  margin-bottom: -.14em;
}
/* an element-wrapped word (the hero rotator) claims its own line, so the
   headline never reflows when the phrase width changes */
.js [data-split] .word--block {
  display: block;
  width: max-content;
  max-width: 100%;
}

.js [data-split] .word > span {
  display: inline-block;
  transform: translateY(110%);
  transition: transform .95s var(--e-out);
  transition-delay: calc(var(--i, 0) * 42ms);
  will-change: transform;
}
.js [data-split].is-in .word > span { transform: translateY(0); }

/* once the sweep is finished the clip is released so descenders and the
   rotating phrase are never cut off */
.js [data-split].is-done .word { overflow: visible; }

/* ==========================================================================
   PRELOADER HAND-OFF
   Content is held still until the loader clears, then everything lands.
   ========================================================================== */
.js.is-loading body { overflow: hidden; }
.js.is-loading .header { transform: translateY(-135%); }
.header { transition: transform .7s var(--e-out) .1s; }

/* ==========================================================================
   REDUCED MOTION
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }

  .js [data-reveal] { opacity: 1; transform: none; filter: none; }
  .js [data-split] .word > span { transform: none; }
  .js [data-split] .word { overflow: visible; }

  .bg-noise, .bg-aurora { animation: none; }
  .hero__canvas { opacity: .5; }
  .cursor { display: none !important; }
  html.has-cursor, html.has-cursor a, html.has-cursor button { cursor: auto; }
}
