/* ==========================================================================
   Zerbetto Tech Hub — Animation Library
   Keyframes + scroll-reveal choreography. Components opt in via
   data-animate attributes toggled by js/ui.js (IntersectionObserver).
   ========================================================================== */

@keyframes fadeInUp {
  from { opacity: 0; transform: translateY(18px); }
  to { opacity: 1; transform: translateY(0); }
}

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

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

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

@keyframes pulseDot {
  0% { box-shadow: 0 0 0 0 rgba(26, 163, 122, 0.35); }
  70% { box-shadow: 0 0 0 8px rgba(26, 163, 122, 0); }
  100% { box-shadow: 0 0 0 0 rgba(26, 163, 122, 0); }
}

.update-strip__live {
  animation: pulseDot 2.4s var(--ease-in-out) infinite;
}

/* Scroll reveal: elements start hidden, JS adds .is-visible when in view */
[data-animate] {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
}

[data-animate].is-visible {
  opacity: 1;
  transform: translateY(0);
}

[data-animate="fade"] { transform: none; }

/* Stagger children within a revealed group */
[data-animate-group] > * { transition-delay: calc(var(--stagger-index, 0) * 70ms); }

/* Hero entrance (plays once on load, independent of scroll observer) */
.hero-slide.is-active .hero-slide__title { animation: fadeInUp var(--dur-slow) var(--ease-out) both; animation-delay: 80ms; }
.hero-slide.is-active .hero-slide__subtitle { animation: fadeInUp var(--dur-slow) var(--ease-out) both; animation-delay: 160ms; }
.hero-slide.is-active .hero-slide__desc { animation: fadeInUp var(--dur-slow) var(--ease-out) both; animation-delay: 240ms; }
.hero-slide.is-active .hero-slide__visual { animation: scaleIn var(--dur-slower) var(--ease-out) both; animation-delay: 200ms; }

/* Search results mount */
.search-result { animation: fadeIn var(--dur-fast) var(--ease-out) both; }

/* Skeleton loading shimmer (used before JSON hydration completes) */
@keyframes shimmer {
  0% { background-position: -420px 0; }
  100% { background-position: 420px 0; }
}

.skeleton {
  background: linear-gradient(90deg, var(--color-surface-alt) 0%, #eef1f8 50%, var(--color-surface-alt) 100%);
  background-size: 840px 100%;
  animation: shimmer 1.4s linear infinite;
  border-radius: var(--radius-md);
}
