/**
 * ZZB Animations — keyframes and reveal classes.
 * Triggered by reveal.js (added classes on IntersectionObserver intersect).
 * All keyframes respect prefers-reduced-motion via tokens.css global rule.
 */

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

@keyframes zzb-fade-up {
  from { opacity: 0; transform: translateY(40px); }
  to   { opacity: 1; transform: translateY(0);    }
}

@keyframes zzb-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes zzb-fade-left {
  from { opacity: 0; transform: translateX(-40px); }
  to   { opacity: 1; transform: translateX(0);     }
}

@keyframes zzb-fade-right {
  from { opacity: 0; transform: translateX(40px); }
  to   { opacity: 1; transform: translateX(0);    }
}

@keyframes zzb-ken-burns {
  0%   { transform: scale(1.05); }
  50%  { transform: scale(1);    }
  100% { transform: scale(1.05); }
}

@keyframes zzb-pulse {
  0%, 100% { transform: translateY(0);   opacity: 1;   }
  50%      { transform: translateY(8px); opacity: 0.4; }
}

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

@keyframes zzb-marquee-rev {
  from { transform: translateX(-50%); }
  to   { transform: translateX(0);    }
}

@keyframes zzb-stroke-draw {
  to { stroke-dashoffset: 0; }
}

/* ---------- REVEAL CLASSES (added by reveal.js) ---------- */

/* No-JS / pre-JS fallback: content visible by default.
   JS adds `zzb-js-ready` to <body>, which gates the initial hidden state. */
.zzb-js-ready [data-zzb-reveal] {
  opacity: 0;
  will-change: opacity, transform;
}
.zzb-js-ready [data-zzb-reveal="fade-up"] {
  transform: translateY(40px);
}
.zzb-js-ready [data-zzb-reveal="fade-in"] {
  /* opacity only */
}
.zzb-js-ready [data-zzb-reveal="fade-left"] {
  transform: translateX(-40px);
}
.zzb-js-ready [data-zzb-reveal="fade-right"] {
  transform: translateX(40px);
}

[data-zzb-reveal].is-visible {
  opacity: 1;
  transform: none;
  transition:
    opacity var(--dur-cinema) var(--ease-cinema),
    transform var(--dur-cinema) var(--ease-cinema);
}

/* Stagger delays for grids — applied via CSS variable from JS */
[data-zzb-reveal][style*="--zzb-stagger"] {
  transition-delay: var(--zzb-stagger);
}

/* ---------- KEN BURNS HERO BG ---------- */

.zzb-ken-burns {
  animation: zzb-ken-burns 8s var(--ease-in-out) infinite;
}

/* ---------- SCROLL INDICATOR ---------- */

.zzb-scroll-hint {
  animation: zzb-pulse 2s var(--ease-in-out) infinite;
}

/* ---------- MARQUEE TRACK ---------- */

.zzb-marquee__track {
  display: flex;
  gap: var(--space-8);
  width: max-content;
  animation: zzb-marquee var(--dur-marquee) linear infinite;
  animation-play-state: running;
}
.zzb-marquee__track--rev {
  animation-name: zzb-marquee-rev;
}
.zzb-marquee:hover .zzb-marquee__track {
  animation-play-state: paused;
}

/* ---------- HERO MASKED TEXT REVEAL (per-word) ---------- */

.zzb-mask-word {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  margin-right: 0.25em;
}
.zzb-mask-word > span {
  display: inline-block;
  transform: translateY(110%);
  transition: transform var(--dur-cinema) var(--ease-cinema);
  transition-delay: var(--zzb-mask-delay, 0ms);
}
.zzb-mask-ready .zzb-mask-word > span {
  transform: translateY(0);
}

/* ---------- SVG STROKE DRAW (icons) ---------- */

.zzb-stroke-draw path,
.zzb-stroke-draw line,
.zzb-stroke-draw circle,
.zzb-stroke-draw rect {
  stroke-dasharray: 800;
  stroke-dashoffset: 800;
}
.zzb-stroke-draw.is-visible path,
.zzb-stroke-draw.is-visible line,
.zzb-stroke-draw.is-visible circle,
.zzb-stroke-draw.is-visible rect {
  animation: zzb-stroke-draw var(--dur-cinema) var(--ease-out) forwards;
}
