/* ==========================================================================
   motion.css — Atmosphere layer styles
   Companion to assets/js/motion.js.
   Uses only design tokens from tokens.css. No hard-coded colors.
   ========================================================================== */

/* ── Film grain overlay ───────────────────────────────────────────────────
   Injected by motion.js as .polish-grain. Fixed, full-viewport, non-
   interactive, rendered above everything so grain covers all content.
   mix-blend-mode: overlay lets underlying colors bleed through.           */

.polish-grain {
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
  opacity: 0.035;
  mix-blend-mode: overlay;
  /* Prevent the grain SVG from triggering scroll */
  overflow: hidden;
}

.polish-grain svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* ── Scroll-progress bar ──────────────────────────────────────────────────
   Injected by motion.js as .polish-progress. Fixed at top of viewport,
   full width, scaled on the X axis from 0→1 by JS (or CSS scroll-timeline
   when available).                                                         */

.polish-progress {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 2px;
  z-index: 10000;
  pointer-events: none;
  background: var(--orange);
  transform: scaleX(0);
  transform-origin: left center;
  /* Smooth the JS-driven updates */
  will-change: transform;
}

/* CSS scroll-driven animation (progressive enhancement).
   When the browser supports it, JS bails out and this takes over.         */
@supports (animation-timeline: scroll(root)) {
  .polish-progress {
    animation: scroll-progress linear;
    animation-timeline: scroll(root);
    transform: none;
  }

  @keyframes scroll-progress {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
  }
}

/* ── data-motion reveal ───────────────────────────────────────────────────
   Rules are gated on `html.motion-ready` which JS adds only when:
     - JS is running, AND
     - prefers-reduced-motion is NOT set.
   Without JS (or under reduced motion) the class is never added, so
   [data-motion] elements carry no opacity or transform — always visible.  */

html.motion-ready [data-motion] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}

html.motion-ready [data-motion].is-revealed {
  opacity: 1;
  transform: none;
}

/* ── Count-up numbers ─────────────────────────────────────────────────────
   [data-count] elements are driven by JS. No extra styles needed beyond
   ensuring the text renders without layout shift.                          */

[data-count] {
  font-variant-numeric: tabular-nums;
}

/* ── Reduced-motion overrides ─────────────────────────────────────────────
   All motion.js behaviors already check window.matchMedia at runtime and
   skip animations. These CSS rules provide a belt-and-suspenders guard
   for anything that slips through via CSS alone.                           */

@media (prefers-reduced-motion: reduce) {
  /* Hide grain — it's visual noise that moves on scroll */
  .polish-grain {
    display: none;
  }

  /* Hide the progress bar — JS never injects it under reduced motion */
  .polish-progress {
    animation: none !important;
    transform: none !important;
    width: 0;
  }

  /* Kill all CSS transitions and animations site-wide (belt + suspenders) */
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
