/* ==========================================================================
   TogNinja — Motion
   Principle: motion carries meaning (work moving through the system) or it
   does not ship. Nothing animates purely because it can.
   ========================================================================== */

/* --- Reveal on scroll -----------------------------------------------------
   Elements start displaced and settle once observed. The .no-js and
   reduced-motion fallbacks below guarantee content is ALWAYS visible. */
[data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity var(--tn-dur-slow) var(--tn-ease),
              transform var(--tn-dur-slow) var(--tn-ease);
  transition-delay: var(--reveal-delay, 0ms);
  will-change: opacity, transform;
}
[data-reveal].is-revealed {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* Hero headline reveals line by line for a cinematic entrance. */
.hero h1 .line {
  opacity: 0;
  transform: translateY(0.35em);
  animation: tn-rise var(--tn-dur-slow) var(--tn-ease) forwards;
}
.hero h1 .line:nth-child(1) { animation-delay: 120ms; }
.hero h1 .line:nth-child(2) { animation-delay: 240ms; }

@keyframes tn-rise {
  to { opacity: 1; transform: none; }
}

/* Panel events cascade in, mimicking a live feed. */
.panel__body .event {
  opacity: 0;
  transform: translateX(12px);
  animation: tn-slide-in var(--tn-dur-slow) var(--tn-ease) forwards;
}
.panel__body .event:nth-child(1) { animation-delay: 620ms; }
.panel__body .event:nth-child(2) { animation-delay: 820ms; }
.panel__body .event:nth-child(3) { animation-delay: 1020ms; }
.panel__body .event:nth-child(4) { animation-delay: 1220ms; }
.panel__body .event:nth-child(5) { animation-delay: 1420ms; }

@keyframes tn-slide-in {
  to { opacity: 1; transform: none; }
}

/* Live pip on the "system active" chip. */
@keyframes tn-pip {
  0%   { box-shadow: 0 0 0 0 rgba(114, 216, 154, 0.55); }
  70%  { box-shadow: 0 0 0 7px rgba(114, 216, 154, 0); }
  100% { box-shadow: 0 0 0 0 rgba(114, 216, 154, 0); }
}

/* Filmstrip frames breathe very slightly so the cull view feels alive. */
.frame--pick { animation: tn-breathe 4.5s var(--tn-ease-io) infinite; }
@keyframes tn-breathe {
  0%, 100% { box-shadow: 0 0 24px -8px rgba(114,216,154,0.30); }
  50%      { box-shadow: 0 0 30px -4px rgba(114,216,154,0.55); }
}

/* ==========================================================================
   NO-JS FALLBACK
   If JS never runs, reveal-targets must not stay invisible.
   ========================================================================== */
.no-js [data-reveal] { opacity: 1; transform: none; }
.no-js .stages__progress { display: none; }

/* ==========================================================================
   REDUCED MOTION
   Honour the OS setting. Content still renders; it simply stops moving.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  [data-reveal],
  .hero h1 .line,
  .panel__body .event {
    opacity: 1 !important;
    transform: none !important;
  }

  .btn:hover, .card:hover { transform: none; }
  .chip__pip { animation: none; }
  .hero__canvas { opacity: 0.4; }   /* static single frame, drawn once by JS */
}
