/* =============================================================================
   NEXILIA NETWORK — animations.css
   Shared keyframes + scroll-reveal utility. Respects prefers-reduced-motion
   via the blanket rule in base.css.
   ============================================================================= */

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

@keyframes toastOut {
  from { opacity: 1; transform: translateY(0) scale(1); }
  to   { opacity: 0; transform: translateY(8px) scale(0.96); }
}

@keyframes skeletonSweep {
  from { transform: translateX(-100%); }
  to   { transform: translateX(100%); }
}

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

@keyframes driftA {
  0%, 100% { transform: translate(0, 0); }
  50%      { transform: translate(50px, 34px); }
}

@keyframes driftB {
  0%, 100% { transform: translate(0, 0); }
  50%      { transform: translate(-40px, -46px); }
}

@keyframes auroraDrift {
  0%, 100% { transform: translate(0, 0) rotate(0deg); }
  50%      { transform: translate(6%, 4%) rotate(3deg); }
}

/* Item 6 — background system: space dust twinkles in and out rather than
   sitting at a fixed opacity, and the volumetric beams sway a few degrees
   like light shifting through moving air, instead of standing perfectly
   still (which is what would have read as "AI wallpaper"). */
@keyframes dustTwinkle {
  0%, 100% { opacity: 0.5; }
  50%      { opacity: 1; }
}

@keyframes beamDrift {
  0%, 100% { transform: translateX(-50%) rotate(-2deg); opacity: 0.55; }
  50%      { transform: translateX(-50%) rotate(2deg); opacity: 0.8; }
}

/* cubeFloat's rotate3d wobble is for flat decorative shapes; a real 3D
   isometric cube needs its base rotateX/rotateY preserved every frame (an
   animation completely replaces `transform`, it doesn't add to a static
   rule), so item 7's voxel cubes use this dedicated keyframe instead. */
@keyframes voxelFloat {
  0%, 100% { transform: translateY(0) rotateX(-24deg) rotateY(34deg); }
  50%      { transform: translateY(-22px) rotateX(-24deg) rotateY(46deg); }
}

@keyframes pulseDot {
  0%, 100% { box-shadow: 0 0 0 0 rgba(46, 212, 122, 0.55); }
  50%      { box-shadow: 0 0 0 6px rgba(46, 212, 122, 0); }
}

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

/* ---- Hero "Nexilia Core" emblem (home.css) ---- */
@keyframes emblemRotate {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

@keyframes emblemBreathe {
  0%, 100% { filter: drop-shadow(0 0 30px rgba(138, 43, 226, 0.55)); }
  50%      { filter: drop-shadow(0 0 46px rgba(138, 43, 226, 0.8)); }
}

@keyframes emblemNodePulse {
  0%, 100% { opacity: 0.75; transform: scale(1); }
  50%      { opacity: 1; transform: scale(1.35); }
}

/* -----------------------------------------------------------------------
   Hero load sequence — plays once on page load, independent of scroll.
   Six beats (eyebrow, title x2, subtitle, actions, HUD) enter on a fixed
   cascade so the first five seconds read as one choreographed moment
   instead of the page just appearing fully rendered.
   ----------------------------------------------------------------------- */
@keyframes heroBeat {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes emblemMaterialize {
  from { stroke-dashoffset: 440; opacity: 0; }
  to   { stroke-dashoffset: 0; opacity: 1; }
}

@keyframes navActiveDraw {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

/* Slow drift across the gradient headline text — the same
   --gradient-primary already used nowhere else but the primary button and
   this one hero line (see tokens.css), just given a few px of horizontal
   motion so it reads as living light instead of a static paint fill. */
@keyframes gradientShift {
  0%, 100% { background-position: 0% 50%; }
  50%      { background-position: 100% 50%; }
}
.reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
}

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

.reveal-stagger > * {
  transition-delay: calc(var(--stagger-index, 0) * 70ms);
}
