/* ============================================================
   MOTION
   ------------------------------------------------------------
   Rules this file obeys:
   1. Only transform / opacity / filter are animated.
   2. Every animation expresses cause and effect. Nothing moves
      for decoration alone.
   3. Duration scales with travel distance, not by whim.
   4. prefers-reduced-motion renders the final state instantly.
   ============================================================ */

/* ---------- Scroll reveal ----------
   Elements start hidden ONLY when JS is running (html.js), so a
   failed script can never leave the page blank. */
.js [data-reveal] {
  opacity: 0;
  transform: translate3d(0, 20px, 0);
  transition: opacity var(--dur-reveal) var(--ease-out),
              transform var(--dur-reveal) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
  will-change: opacity, transform;
}
.js [data-reveal="left"]  { transform: translate3d(-24px, 0, 0); }
.js [data-reveal="right"] { transform: translate3d(24px, 0, 0); }
.js [data-reveal="scale"] { transform: scale(.96); }

.js [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* ---------- Hero entrance ---------- */
.js .hero-in {
  opacity: 0;
  transform: translate3d(0, 24px, 0);
  animation: hero-rise 700ms var(--ease-out) forwards;
  animation-delay: var(--reveal-delay, 0ms);
}
@keyframes hero-rise {
  to { opacity: 1; transform: none; }
}

/* ---------- Directional cue on the path cards ----------
   A slow, low-amplitude drift that shows which way the site
   will move when the card is chosen. Pauses on hover so it never
   fights the pointer, and stops entirely for reduced motion. */
.path-card__go .arrow { animation: nudge-right 2.8s var(--ease-in-out) infinite; }
.path-card--left .path-card__go .arrow { animation-name: nudge-left; }
.path-card:hover .path-card__go .arrow,
.path-card:focus-visible .path-card__go .arrow { animation-play-state: paused; }

@keyframes nudge-right {
  0%, 62%, 100% { transform: translateX(0); }
  80%           { transform: translateX(6px); }
}
@keyframes nudge-left {
  0%, 62%, 100% { transform: translateX(0); }
  80%           { transform: translateX(-6px); }
}

/* ---------- Travel scrim ----------
   A faint wash that rises during long journeys so the passing
   panels read as motion blur rather than flicker. */
.travel-scrim {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(120% 60% at 50% 50%, transparent 40%, rgba(15,10,10,.16) 100%);
  transition: opacity var(--dur-state) var(--ease-out);
}
.is-travelling-far .travel-scrim { opacity: 1; }

/* ---------- Rail marker pulse on arrival ---------- */
.rail__marker.just-arrived { animation: marker-settle 420ms var(--ease-spring); }
@keyframes marker-settle {
  0%   { transform: translate3d(var(--marker-x, 0), 0, 0) scaleX(1.06); }
  100% { transform: translate3d(var(--marker-x, 0), 0, 0) scaleX(1); }
}

/* ---------- Form feedback ---------- */
.field--invalid .field__error { animation: error-in 220ms var(--ease-out); }
@keyframes error-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}
.form-success { animation: success-in 420ms var(--ease-spring); }
@keyframes success-in {
  from { opacity: 0; transform: translateY(10px) scale(.985); }
  to   { opacity: 1; transform: none; }
}

/* ---------- Accordion body ---------- */
.accordion details[open] .accordion__body { animation: acc-open 300ms var(--ease-out); }
@keyframes acc-open {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

/* ============================================================
   REDUCED MOTION — honour the system setting completely.
   Travel becomes an instant cut; everything renders final state.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

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

  .js [data-reveal] { opacity: 1 !important; transform: none !important; }
  .js .hero-in { opacity: 1; animation: none; transform: none; }
  .stage.is-travelling { transform: none; }
  .travel-scrim { display: none; }
  .path-card__go .arrow { animation: none; }
  .path-card:hover { transform: none; }
  .card:hover, a.card:hover, button.card:hover { transform: none; }
}
