/* ============================================================
   M3U-EDIT.COM v2 — Animation Library
   Location: assets/css/animations.css

   Goals:
   - Vanilla CSS keyframes (no JS deps)
   - Pair with IntersectionObserver in homepage.js for scroll reveals
   - Respect prefers-reduced-motion — instant-mode fallback at bottom
   - Safe on all theme variants ([data-theme="dark"] / default light)

   Convention:
   - Keyframes are GLOBAL names (camelCase) so other pages can opt in
   - Utility classes use .anim-* prefix to avoid collisions with
     existing flat class names (.hero, .tool-card, etc.)
   ============================================================ */

/* ---------- KEYFRAMES ---------- */

@keyframes fadeUp {
  from { opacity: 0; transform: translate3d(0, 20px, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

@keyframes fadeDown {
  from { opacity: 0; transform: translate3d(0, -20px, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

@keyframes fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes fadeInLeft {
  from { opacity: 0; transform: translate3d(-20px, 0, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

@keyframes fadeInRight {
  from { opacity: 0; transform: translate3d(20px, 0, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

@keyframes scaleIn {
  from { opacity: 0; transform: scale(0.95); }
  to   { opacity: 1; transform: scale(1); }
}

@keyframes pulseSoft {
  0%, 100% { opacity: 1;   transform: scale(1); }
  50%      { opacity: 0.85; transform: scale(1.02); }
}

@keyframes pulseRing {
  0%   { box-shadow: 0 0 0 0 rgba(99, 102, 241, 0.45); }
  70%  { box-shadow: 0 0 0 12px rgba(99, 102, 241, 0); }
  100% { box-shadow: 0 0 0 0 rgba(99, 102, 241, 0); }
}

@keyframes shimmer {
  0%   { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}

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

@keyframes floatSlow {
  0%, 100% { transform: translateY(0) rotate(0); }
  50%      { transform: translateY(-12px) rotate(1.5deg); }
}

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

@keyframes spinSlow {
  to { transform: rotate(360deg); }
}

@keyframes blink {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.35; }
}

@keyframes drawLine {
  to { stroke-dashoffset: 0; }
}

@keyframes morphIcon {
  0%   { transform: scale(1) rotate(0); }
  50%  { transform: scale(0.85) rotate(180deg); }
  100% { transform: scale(1) rotate(360deg); }
}

/* ---------- BASE REVEAL (paired with IntersectionObserver) ----------
   Mark elements with .reveal — they start invisible.
   homepage.js adds .is-visible when the element enters the viewport.
   ------------------------------------------------------------------ */

.reveal {
  opacity: 0;
  transform: translate3d(0, 20px, 0);
  transition:
    opacity   600ms cubic-bezier(0.16, 1, 0.3, 1),
    transform 600ms cubic-bezier(0.16, 1, 0.3, 1);
  will-change: opacity, transform;
}

.reveal.is-visible {
  opacity: 1;
  transform: translate3d(0, 0, 0);
}

/* Reveal variants */
.reveal-fade { transform: none; }
.reveal-fade.is-visible { opacity: 1; }

.reveal-left { transform: translate3d(-24px, 0, 0); }
.reveal-left.is-visible { transform: translate3d(0, 0, 0); opacity: 1; }

.reveal-right { transform: translate3d(24px, 0, 0); }
.reveal-right.is-visible { transform: translate3d(0, 0, 0); opacity: 1; }

.reveal-scale { transform: scale(0.95); }
.reveal-scale.is-visible { transform: scale(1); opacity: 1; }

/* ---------- STAGGER UTILITIES ----------
   Apply to children inside a .reveal-stagger parent — each child
   animates with an incremental delay (per data-stagger-index set by JS,
   OR use these explicit nth-child overrides for static markup).
   --------------------------------------------------------------- */

.stagger-1 { transition-delay: 60ms;  }
.stagger-2 { transition-delay: 120ms; }
.stagger-3 { transition-delay: 180ms; }
.stagger-4 { transition-delay: 240ms; }
.stagger-5 { transition-delay: 300ms; }
.stagger-6 { transition-delay: 360ms; }
.stagger-7 { transition-delay: 420ms; }
.stagger-8 { transition-delay: 480ms; }

.reveal-stagger > .reveal:nth-child(1) { transition-delay: 60ms;  }
.reveal-stagger > .reveal:nth-child(2) { transition-delay: 120ms; }
.reveal-stagger > .reveal:nth-child(3) { transition-delay: 180ms; }
.reveal-stagger > .reveal:nth-child(4) { transition-delay: 240ms; }
.reveal-stagger > .reveal:nth-child(5) { transition-delay: 300ms; }
.reveal-stagger > .reveal:nth-child(6) { transition-delay: 360ms; }
.reveal-stagger > .reveal:nth-child(7) { transition-delay: 420ms; }
.reveal-stagger > .reveal:nth-child(8) { transition-delay: 480ms; }

/* ---------- ONE-SHOT ANIMATION UTILITIES ----------
   Use when you want a one-time entrance on page load (no scroll trigger).
   --------------------------------------------------------------------- */

.anim-fade-up    { animation: fadeUp        600ms cubic-bezier(0.16, 1, 0.3, 1) both; }
.anim-fade-down  { animation: fadeDown      600ms cubic-bezier(0.16, 1, 0.3, 1) both; }
.anim-fade-in    { animation: fadeIn        600ms ease-out both; }
.anim-fade-left  { animation: fadeInLeft    600ms cubic-bezier(0.16, 1, 0.3, 1) both; }
.anim-fade-right { animation: fadeInRight   600ms cubic-bezier(0.16, 1, 0.3, 1) both; }
.anim-scale-in   { animation: scaleIn       700ms cubic-bezier(0.16, 1, 0.3, 1) both; }

/* Delay helpers for chained entrances */
.anim-delay-100 { animation-delay: 100ms; }
.anim-delay-200 { animation-delay: 200ms; }
.anim-delay-300 { animation-delay: 300ms; }
.anim-delay-400 { animation-delay: 400ms; }
.anim-delay-500 { animation-delay: 500ms; }
.anim-delay-600 { animation-delay: 600ms; }
.anim-delay-700 { animation-delay: 700ms; }
.anim-delay-800 { animation-delay: 800ms; }

/* Continuous loops */
.anim-float       { animation: float 4s ease-in-out infinite; }
.anim-float-slow  { animation: floatSlow 6s ease-in-out infinite; }
.anim-pulse       { animation: pulseSoft 3s ease-in-out infinite; }
.anim-pulse-ring  { animation: pulseRing 2.2s ease-out infinite; }
.anim-spin-slow   { animation: spinSlow 12s linear infinite; }
.anim-blink       { animation: blink 1.5s ease-in-out infinite; }
.anim-shimmer {
  background: linear-gradient(
    100deg,
    transparent 0%,
    rgba(255, 255, 255, 0.18) 50%,
    transparent 100%
  );
  background-size: 200% 100%;
  animation: shimmer 2s linear infinite;
}

/* Animated gradient text — for hero highlight phrases */
.anim-gradient-text {
  background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #ec4899 100%);
  background-size: 200% 100%;
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
          color: transparent;
  animation: gradientShift 6s ease-in-out infinite;
}

/* "Live" status dot — used in social proof bar + activity ticker */
.live-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #10b981;
  position: relative;
  vertical-align: middle;
}
.live-dot::before {
  content: '';
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  background: #10b981;
  opacity: 0.4;
  animation: pulseRing 2s ease-out infinite;
  pointer-events: none;
}

/* Hover lift — works on cards out of the box */
.hover-lift {
  transition:
    transform   300ms cubic-bezier(0.16, 1, 0.3, 1),
    box-shadow  300ms cubic-bezier(0.16, 1, 0.3, 1),
    border-color 200ms ease;
  will-change: transform;
}
.hover-lift:hover { transform: translateY(-4px); }

.hover-lift-strong {
  transition:
    transform   300ms cubic-bezier(0.16, 1, 0.3, 1),
    box-shadow  300ms cubic-bezier(0.16, 1, 0.3, 1);
  will-change: transform;
}
.hover-lift-strong:hover { transform: translateY(-8px); }

/* Icon micro-interactions */
.icon-rotate-on-hover { transition: transform 300ms cubic-bezier(0.34, 1.56, 0.64, 1); }
.icon-rotate-on-hover:hover,
*:hover > .icon-rotate-on-hover { transform: rotate(8deg) scale(1.08); }

/* Underline-grow link effect — pairs with ::after pseudo */
.link-underline {
  position: relative;
  display: inline-block;
}
.link-underline::after {
  content: '';
  position: absolute;
  left: 0; bottom: -2px;
  width: 100%;
  height: 2px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 280ms cubic-bezier(0.16, 1, 0.3, 1);
}
.link-underline:hover::after { transform: scaleX(1); }

/* ---------- WORD-STAGGER HEADLINE ----------
   homepage.js wraps each word in <span class="word">.
   Each word fades up with a 60ms cascade.
   ------------------------------------------- */

.word-stagger .word {
  display: inline-block;
  opacity: 0;
  transform: translate3d(0, 0.4em, 0);
  animation: fadeUp 700ms cubic-bezier(0.16, 1, 0.3, 1) both;
}
/* Per-word delays driven by inline style (--i) set by JS — falls back
   to nth-child for the first 12 words if JS is disabled. */
.word-stagger .word { animation-delay: calc(60ms * var(--i, 0)); }
.word-stagger .word:nth-child(1)  { --i: 0;  }
.word-stagger .word:nth-child(2)  { --i: 1;  }
.word-stagger .word:nth-child(3)  { --i: 2;  }
.word-stagger .word:nth-child(4)  { --i: 3;  }
.word-stagger .word:nth-child(5)  { --i: 4;  }
.word-stagger .word:nth-child(6)  { --i: 5;  }
.word-stagger .word:nth-child(7)  { --i: 6;  }
.word-stagger .word:nth-child(8)  { --i: 7;  }
.word-stagger .word:nth-child(9)  { --i: 8;  }
.word-stagger .word:nth-child(10) { --i: 9;  }
.word-stagger .word:nth-child(11) { --i: 10; }
.word-stagger .word:nth-child(12) { --i: 11; }

/* ---------- REDUCED-MOTION GUARD ----------
   Per WCAG 2.1 SC 2.3.3 — turn EVERYTHING down to a near-instant
   crossfade for users who set "Reduce motion" at the OS level.
   ------------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  /* Still let reveals show their final state — just instantly */
  .reveal,
  .reveal-fade,
  .reveal-left,
  .reveal-right,
  .reveal-scale {
    opacity: 1 !important;
    transform: none !important;
  }

  /* Word stagger collapses to instant visible */
  .word-stagger .word {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
  }

  /* Hide purely decorative looping animations */
  .anim-float,
  .anim-float-slow,
  .anim-pulse,
  .anim-pulse-ring,
  .anim-spin-slow,
  .anim-blink,
  .anim-shimmer { animation: none !important; }

  .live-dot::before { animation: none !important; opacity: 0; }
}
