/* =========================================================
   Northern Geek — animation.css
   Keyframes, scroll-reveal states, and motion effects.
   ========================================================= */

/* ---------- Scroll reveal (driven by IntersectionObserver in animation.js) ---------- */
.reveal {
  opacity: 0;
  transform: translateY(36px);
  transition:
    opacity 0.8s var(--ease),
    transform 0.8s var(--ease);
}
.reveal.in-view {
  opacity: 1;
  transform: translateY(0);
}

/* ---------- Hero load-in reveal (plays immediately, staggered via --d) ---------- */
.reveal-load {
  opacity: 0;
  transform: translateY(24px);
  animation: revealLoad 0.9s var(--ease) forwards;
  animation-delay: var(--d, 0s);
}
@keyframes revealLoad {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* ---------- Hero blob drift ---------- */
.blob-1 {
  animation: driftOne 16s ease-in-out infinite;
}
.blob-2 {
  animation: driftTwo 18s ease-in-out infinite;
}
@keyframes driftOne {
  0%,
  100% {
    transform: translate(0, 0) scale(1);
  }
  50% {
    transform: translate(60px, 40px) scale(1.1);
  }
}
@keyframes driftTwo {
  0%,
  100% {
    transform: translate(0, 0) scale(1);
  }
  50% {
    transform: translate(-50px, -30px) scale(1.08);
  }
}

/* ---------- Floating particles ---------- */
.hero-particles span {
  animation: floatParticle linear infinite;
}
@keyframes floatParticle {
  0% {
    transform: translateY(0) translateX(0);
    opacity: 0;
  }
  10% {
    opacity: 0.8;
  }
  90% {
    opacity: 0.4;
  }
  100% {
    transform: translateY(-120vh) translateX(20px);
    opacity: 0;
  }
}

/* ---------- Scroll indicator bounce ---------- */
.scroll-indicator .wheel {
  animation: wheelDrop 1.8s ease-in-out infinite;
}
@keyframes wheelDrop {
  0% {
    top: 6px;
    opacity: 1;
  }
  70% {
    top: 22px;
    opacity: 0;
  }
  71% {
    top: 6px;
    opacity: 0;
  }
  100% {
    top: 6px;
    opacity: 1;
  }
}
.scroll-indicator {
  animation: floatY 2.4s ease-in-out infinite;
}
@keyframes floatY {
  0%,
  100% {
    transform: translate(-50%, 0);
  }
  50% {
    transform: translate(-50%, -8px);
  }
}

/* ---------- Ripple ---------- */
@keyframes rippleAnim {
  to {
    transform: scale(2.6);
    opacity: 0;
  }
}

/* ---------- Device glow rotation ---------- */
.device-glow {
  animation: spinGlow 12s linear infinite;
}
@keyframes spinGlow {
  to {
    transform: rotate(360deg);
  }
}

/* ---------- Loader spinner bar ---------- */
.loader-bar span {
  animation: loadBar 1.3s ease-in-out infinite;
}
@keyframes loadBar {
  0% {
    transform: translateX(-100%);
  }
  50% {
    transform: translateX(120%);
  }
  100% {
    transform: translateX(-100%);
  }
}
.loader-mark img {
  animation: pulseMark 1.6s ease-in-out infinite;
}
@keyframes pulseMark {
  0%,
  100% {
    opacity: 0.6;
    transform: scale(0.96);
  }
  50% {
    opacity: 1;
    transform: scale(1.04);
  }
}

/* ---------- Testimonial card entrance handled by track transform (script.js) ---------- */

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.2s !important;
    scroll-behavior: auto !important;
  }
  .blob-1,
  .blob-2,
  .hero-particles span,
  .scroll-indicator,
  .device-glow,
  .loader-bar span,
  .loader-mark img {
    animation: none !important;
  }
}
