/*
  Spiral Co. motion. The single source of truth for animation.

  Only five types exist. Components opt in with data-motion, never with their own keyframes.
    shift-in  Fades in while rising --shift-distance. Text, cards, header, messages.
    sweep     Spectrum strip bands grow blue to red, then the absorption lines slide to their
              redshifted positions. Every spectrum strip.
    whirl     The logo's triangles appear one round at a time, edge to center. The hero logo only.
    feedback  Fast color change and arrow nudge on hover and focus. Built into spiral.css classes.
    drift     Absorption lines ease slowly back and forth. One element per page.

  Starting states apply only after html.motion-ready is set, so the page is complete without
  JavaScript, and motion.js never sets it when the visitor prefers reduced motion.
*/

:root {
  --dur-fast: 160ms;
  --dur-base: 320ms;
  --dur-slow: 700ms;
  --dur-signature: 1400ms;
  --dur-ambient: 6s;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --stagger: 70ms;
  --shift-distance: 24px;
  --line-shift: 32px;
  --drift-distance: 6px;
}

@keyframes motion-shift-in {
  from { opacity: 0; transform: translateY(var(--shift-distance)); }
  to { opacity: 1; transform: none; }
}

@keyframes motion-band {
  from { transform: scaleX(0); }
  to { transform: none; }
}

@keyframes motion-redshift {
  from { opacity: 0; transform: translateX(calc(-1 * var(--line-shift))); }
  to { opacity: 1; transform: none; }
}

@keyframes motion-drift {
  from { transform: none; }
  to { transform: translateX(var(--drift-distance)); }
}

@keyframes motion-appear {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Shift in */
.motion-ready [data-motion~="shift-in"] { opacity: 0; }
.motion-ready [data-motion~="shift-in"].is-in {
  animation: motion-shift-in var(--motion-dur, var(--dur-base)) var(--ease-out) both;
  animation-delay: calc(var(--i, 0) * var(--stagger));
}

/* Spectrum sweep: bands in order, then the lines shift toward red. */
.motion-ready [data-motion~="sweep"] .sc-band { transform: scaleX(0); transform-origin: left center; }
.motion-ready [data-motion~="sweep"] .sc-line { opacity: 0; }
.motion-ready [data-motion~="sweep"].is-in .sc-band {
  animation: motion-band var(--dur-slow) var(--ease-in-out) both;
  animation-delay: calc(var(--b, 0) * var(--stagger));
}
.motion-ready [data-motion~="sweep"].is-in .sc-line {
  animation: motion-redshift var(--dur-slow) var(--ease-out) both;
  animation-delay: calc(var(--dur-slow) + var(--l, 0) * var(--stagger));
}

/* Drift: chained after the sweep when both are set. */
.motion-ready [data-motion~="drift"].is-in .sc-line {
  animation:
    motion-redshift var(--dur-slow) var(--ease-out) both,
    motion-drift var(--dur-ambient) var(--ease-in-out) infinite alternate;
  animation-delay:
    calc(var(--dur-slow) + var(--l, 0) * var(--stagger)),
    calc(var(--dur-slow) * 2 + var(--l, 0) * var(--stagger));
}

/* Whirl build: outline first, then each round of triangles from the edge in. */
.motion-ready [data-motion~="whirl"] .whirl-outline,
.motion-ready [data-motion~="whirl"] .whirl-step { opacity: 0; }
.motion-ready [data-motion~="whirl"].is-in .whirl-outline {
  animation: motion-appear var(--dur-base) var(--ease-out) both;
}
.motion-ready [data-motion~="whirl"].is-in .whirl-step {
  animation: motion-appear var(--dur-base) var(--ease-out) both;
  animation-delay: calc(var(--dur-signature) * var(--i) / var(--n, 16));
}

@media (prefers-reduced-motion: reduce) {
  [data-motion], [data-motion] * { animation: none !important; opacity: 1 !important; transform: none !important; }
}
