/* ════════════════════════════════
   ANIMATIONS — single source of truth for all motion
   Three patterns:

   1. ENTRANCE  — fires immediately on page load.
      How: element selector is listed in the group rule below.
      Control timing: set --anim-delay on the element.
      Override duration: set --anim-dur on the element.

   2. REVEAL    — fires when JS adds .in-view to a parent.
      How: add class="reveal" to the element in HTML.
      Control timing: set --reveal-delay on the element.
      Override duration: set --reveal-dur on the element.

   3. WORD DRIFT — staggered word-by-word entrance.
      How: JS splitWords(el) wraps each word in <span class="word" style="--i:N">.
      Can be used for entrance (page load) or reveal (scroll).
      Entrance: add element to the .word-drift-entrance group below.
      Timing: each word delays by --i * 0.12s from a base of 0.3s.
      Duration: 0.85s per word, ease-out-expo, 16px travel up.
════════════════════════════════ */


/* ── Keyframes ─────────────────────────────────── */

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

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

/* Pattern 3: word drift — used by .op-bio .word (entrance)
   and .op-backdrop-text .word (scroll reveal via transition) */
@keyframes wordDrift {
  from { opacity: 0; translate: 0 16px; }
  to   { opacity: 1; translate: 0 0; }
}

@keyframes orbGrowIn {
  from { transform: scale(0.3); }
  to   { transform: scale(1); }
}

@keyframes chevron-race {
  0%, 45%, 100% { color: rgba(255, 99, 0, 0.2); }
  15%, 30%      { color: #FF3C00; }
}

@keyframes chevron-enter {
  from { opacity: 0; translate: 0 -8px; }
  to   { opacity: 1; translate: 0 0; }
}

@keyframes ship-hover {
  0%, 100% { transform: translateY(calc(-50% + 0px))   rotate(0deg);    }
  40%       { transform: translateY(calc(-50% - 8px))  rotate(0.5deg);  }
  70%       { transform: translateY(calc(-50% + 4px))  rotate(-0.3deg); }
}

@keyframes flow-drift {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

@keyframes nav-btn-in {
  0%   { opacity: 0; translate: 0 28px; }
  55%  { opacity: 1; translate: 0 -8px; }
  75%  {             translate: 0 4px;  }
  90%  {             translate: 0 -2px; }
  100% { opacity: 1; translate: 0 0;    }
}



/* ── Pattern 1: Entrance ────────────────────────
   All page-load slideUp elements share one animation declaration.
   Each element sets its own --anim-delay (and --anim-dur if needed). */

.op-header-name,
.op-sys-strip,
.op-header-left,
.op-header-bottom-row,
.op-header-top-left,
.op-header-top-right {
  opacity: 0;
  animation: slideUp var(--anim-dur, var(--dur-base)) var(--ease-out-expo) var(--anim-delay, 0s) both;
}

/* ── Pattern 3: Bio word drift entrance ── */
.op-bio .word {
  opacity: 0;
  animation: wordDrift 0.85s var(--ease-out-expo) var(--anim-delay, 0.3s) both;
}

.op-orb-col {
  animation: orbGrowIn var(--anim-dur, 0.9s) var(--ease-out-expo) var(--anim-delay, 0s) both;
}

/* chevrons handle their own entrance — no fadeIn on the container */

/* ── Pause all entrance animations while the loading screen is active ──
   body.loading is removed by loader.js when the counter reaches 100%,
   causing all paused animations to play from their start simultaneously. */
body.loading .op-header-name,
body.loading .op-sys-strip,
body.loading .op-header-left,
body.loading .op-header-bottom-row,
body.loading .op-header-top-left,
body.loading .op-header-top-right,
body.loading .op-orb-col,
body.loading .op-bio .word,
body.loading .op-chevron {
  animation-play-state: paused;
}


/* ── Pattern 2: Reveal (IntersectionObserver) ───
   Add class="reveal" to any element. JS adds .in-view to its parent.
   Element starts hidden, slides up + fades in when section enters view. */

.reveal {
  opacity: 0;
  translate: 0 16px;
  transition:
    opacity   var(--reveal-dur, 0.85s) var(--ease-out-expo) var(--reveal-delay, 0s),
    translate var(--reveal-dur, 0.85s) var(--ease-out-expo) var(--reveal-delay, 0s);
}

.in-view .reveal,
.reveal.in-view {
  opacity: 1;
  translate: 0 0;
}
