/* AGES — scroll-triggered, scientifically-themed animations.
   Pattern: every animated element gets `animation: none` by default and only
   receives its real keyframe animation once a JS IntersectionObserver adds
   `.is-visible` to the `.anim-scene` ancestor. This guarantees animations
   never run on load, only once scrolled into view, and are trivial to kill
   for prefers-reduced-motion (see bottom of file). */

/* .anim-scene is a pure behavior hook (IntersectionObserver target + .is-visible
   state) — deliberately carries NO layout/sizing rules so it never fights with
   the element's own display/width, whether that's an <svg>, a flex row, etc. */
svg.anim-scene { width: 100%; height: auto; display: block; overflow: visible; }
.anim-caption { font-size: 0.85rem; color: var(--slate-500); margin-top: 14px; text-align: center; }

/* ============ 1. Battery charging ============ */
.anim-battery .cell-seg { animation: none; opacity: 0.18; transform-origin: center; }
.anim-scene.is-visible .anim-battery .cell-seg {
  animation: chargeSeg 2.8s ease-in-out infinite;
}
.anim-battery .cell-seg:nth-child(1) { animation-delay: 0s; }
.anim-battery .cell-seg:nth-child(2) { animation-delay: 0.22s; }
.anim-battery .cell-seg:nth-child(3) { animation-delay: 0.44s; }
.anim-battery .cell-seg:nth-child(4) { animation-delay: 0.66s; }
.anim-battery .cell-seg:nth-child(5) { animation-delay: 0.88s; }
.anim-battery .charge-glow { animation: none; opacity: 0; }
.anim-scene.is-visible .anim-battery .charge-glow { animation: glowSweep 2.8s ease-in-out infinite; }
@keyframes chargeSeg { 0%, 8% { opacity: 0.18; } 40%, 78% { opacity: 1; } 100% { opacity: 0.18; } }
@keyframes glowSweep { 0%, 70% { opacity: 0; transform: translateY(0); } 80% { opacity: 0.9; } 100% { opacity: 0; transform: translateY(-70px); } }

/* ============ 2. Energy flow (solar/wind -> BESS -> grid/home/EV) ============ */
.flow-dot { offset-rotate: 0deg; animation: none; opacity: 0; }
.anim-scene.is-visible .flow-dot { animation: flowMove 3.4s linear infinite; }
.flow-dot:nth-of-type(2) { animation-delay: 0.9s !important; }
.flow-dot:nth-of-type(3) { animation-delay: 1.8s !important; }
.flow-dot:nth-of-type(4) { animation-delay: 2.4s !important; }
@keyframes flowMove {
  0% { offset-distance: 0%; opacity: 0; }
  8% { opacity: 1; }
  92% { opacity: 1; }
  100% { offset-distance: 100%; opacity: 0; }
}

/* ============ 3. Lithium-ion intercalation (charge/discharge shuttle) ============ */
.anim-ions .ion { animation: none; }
.anim-scene.is-visible .anim-ions .ion {
  animation: ionShuttle 3.6s cubic-bezier(.45,0,.55,1) infinite alternate;
}
.anim-ions .ion:nth-child(2) { animation-delay: 0.35s !important; }
.anim-ions .ion:nth-child(3) { animation-delay: 0.7s !important; }
@keyframes ionShuttle { 0% { transform: translateX(0); } 100% { transform: translateX(96px); } }

/* ============ 4. Stack build-up (cell -> module -> pack -> rack -> container) ============ */
.stack-build .stack-item {
  opacity: 0;
  transform: translateY(16px) scale(0.92);
  transition: opacity 0.55s ease, transform 0.55s ease;
  transition-delay: var(--d, 0s);
}
.stack-build.anim-scene.is-visible .stack-item {
  opacity: 1;
  transform: translateY(0) scale(1);
}

/* ============ 5. Crystal lattice shimmer (AMAT materials) ============ */
.anim-lattice .lattice-node { animation: none; opacity: 0.35; }
.anim-scene.is-visible .anim-lattice .lattice-node { animation: latticePulse 3s ease-in-out infinite; }
.anim-lattice .lattice-node[data-col="0"] { animation-delay: 0s !important; }
.anim-lattice .lattice-node[data-col="1"] { animation-delay: 0.25s !important; }
.anim-lattice .lattice-node[data-col="2"] { animation-delay: 0.5s !important; }
.anim-lattice .lattice-node[data-col="3"] { animation-delay: 0.75s !important; }
.anim-lattice .lattice-node[data-col="4"] { animation-delay: 1s !important; }
@keyframes latticePulse { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }

/* ============ 6. Circular recycling loop (AMAT) ============ */
.anim-recycle .recycle-track { animation: none; }
.anim-scene.is-visible .anim-recycle .recycle-track { animation: recycleRotate 3.6s linear infinite; }
.anim-recycle .recycle-track { transform-box: fill-box; transform-origin: center; }
@keyframes recycleRotate { to { stroke-dashoffset: -240; } }

/* ============ 7. Self-drawing test/cycling curve (ATIC) ============ */
.anim-curve .draw-path {
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  transition: stroke-dashoffset 1.6s ease-out;
}
.anim-scene.is-visible .anim-curve .draw-path { stroke-dashoffset: 0; }
.anim-curve .draw-path.d2 { transition-delay: 0.3s; }

/* ============ 8. Pulse ring (BMS monitor / IP / knowledge nodes) ============ */
.pulse-ring { animation: none; opacity: 0; }
.anim-scene.is-visible .pulse-ring { animation: pulseRing 2.4s cubic-bezier(0,.5,.5,1) infinite; }
.pulse-ring.r2 { animation-delay: 0.8s !important; }
@keyframes pulseRing {
  0% { transform: scale(0.55); opacity: 0.55; }
  70% { transform: scale(1.5); opacity: 0; }
  100% { opacity: 0; }
}
.pulse-dot { animation: none; }
.anim-scene.is-visible .pulse-dot { animation: dotBeat 2.4s ease-in-out infinite; }
@keyframes dotBeat { 0%, 100% { opacity: 0.85; } 50% { opacity: 1; } }

/* ============ Respect reduced motion: freeze everything to a static, fully-visible state ============ */
@media (prefers-reduced-motion: reduce) {
  .anim-scene * {
    animation: none !important;
    transition: none !important;
  }
  .anim-battery .cell-seg,
  .anim-lattice .lattice-node,
  .pulse-dot { opacity: 0.9 !important; }
  .flow-dot,
  .anim-battery .charge-glow,
  .pulse-ring { opacity: 0 !important; }
  .anim-curve .draw-path { stroke-dashoffset: 0 !important; }
  .stack-build .stack-item { opacity: 1 !important; transform: none !important; }
}
