/*
 * Masuria Esport - scroll-triggered entrance reveal (animations.css)
 * ADDED: not in design. Requires tokens.css (--msr-reveal-*, --msr-ease) + assets/js/reveal.js.
 *
 * Progressive enhancement / no-FOUC contract:
 *   The hidden pre-reveal state below is scoped under `html.msr-reveal`, a class that ONLY
 *   assets/js/reveal.js ever adds, and only after it has confirmed IntersectionObserver support and that
 *   the user has not asked for prefers-reduced-motion. Without that script (disabled, blocked, failed to
 *   load, or an old browser) `html.msr-reveal` never appears, this whole file has no effect, and every
 *   element renders exactly as its own section stylesheet already draws it - nothing can ever get stuck
 *   invisible. See reveal.js for the class-adding logic.
 *
 * Opacity contract:
 *   The `.is-revealed` rule intentionally never sets `opacity` - it only clears the transform. Several
 *   elements already carry their own resting opacity as part of the pixel-accurate design (the
 *   dimmed process steps at 0.4, watermarks at 0.1/0.2). Once
 *   `.is-revealed` is added, the `:not(.is-revealed)` rule below stops matching and its `opacity: 0`
 *   stops applying - opacity then falls straight back to whatever the element's own section rule (or the
 *   CSS default of 1) says, so the final look and any hover states are byte-for-byte unaffected.
 *
 * Bug fix (content already in the initial viewport never visibly animating in, only scroll-revealed
 * content did - see memory note scroll-reveal-css-js-gotchas.md for the follow-up):
 *   `transition` below is scoped to `.is-revealed` ONLY (it used to apply unconditionally to every
 *   `[data-msr-reveal]`, hidden or not). Reason: the moment `html.msr-reveal` is added, the element's
 *   opacity target changes to 0 for the FIRST time - if `transition-duration` is already active at that
 *   exact same style recalculation (as it was before this fix), the browser treats it as a real transition
 *   and starts animating FROM the pre-JS painted value (opacity 1) DOWN to 0. For anything revealed again
 *   very soon after (i.e. anything already on screen at load - confirmed via CDP: `.is-revealed` landing
 *   ~15-30ms later), that in-flight "fade to hidden" transition gets reversed before it has travelled any
 *   real distance; CSS's reversing-shortening rule collapses the reversed transition to a near-zero
 *   duration and the browser cancels it outright (`transitioncancel`, confirmed via CDP) instead of
 *   animating it - the element just snaps straight to its final state with no visible motion. Elements
 *   revealed only much later by a real scroll were never affected, because their "fade to hidden" transition
 *   had already finished, undisturbed, long before `.is-revealed` arrived - which is why scrolling always
 *   looked fine. Scoping `transition` to `.is-revealed` means it never exists while the element is merely
 *   hidden, so establishing the hidden state is always an instant, un-transitioned jump (as intended) and
 *   the ONLY transition ever created is the one that visibly reveals the element - regardless of how soon
 *   after load (or at how tall a viewport) that happens.
 */

html.msr-reveal [data-msr-reveal]:not(.is-revealed) {
  opacity: 0;
  transform: translateY(var(--msr-reveal-distance));
}

html.msr-reveal [data-msr-reveal].is-revealed {
  transition:
    opacity var(--msr-reveal-duration) var(--msr-ease),
    transform var(--msr-reveal-duration) var(--msr-ease);
  transition-delay: var(--msr-reveal-delay, 0ms);
  transform: translateY(0);
}

/*
 * The process steps already declare their own `transition: opacity ...`
 * (for their hover/current-step dimming, see assets/css/sections/process.css) - and unlike
 * every other reveal target, that rule is NOT scoped to `html.msr-reveal`, so it is active the whole time,
 * hidden state included. That reopens the exact bug fixed above, just from a different source: the moment
 * `:not(.is-revealed)` sets opacity to 0, THIS always-on rule (not the one above) is what has a
 * transition-duration in scope, so it spuriously animates the hide too, and gets cancelled the same way if
 * `.is-revealed` follows soon after. `transition: none` while hidden neutralises it (specificity beats the
 * section rule); restating the reveal transition on `.is-revealed` (same --msr-duration token as the
 * section's own rule, so the hover timing is unchanged) keeps both transitions working together once
 * revealed, same as before.
 * Kept in sync with assets/css/sections/process.css (.msr-process__step).
 */
html.msr-reveal .msr-process__step[data-msr-reveal]:not(.is-revealed) {
  transition: none;
}

html.msr-reveal .msr-process__step[data-msr-reveal].is-revealed {
  transition:
    opacity var(--msr-duration) var(--msr-ease),
    transform var(--msr-reveal-duration) var(--msr-ease);
}

/* Reduced motion: belt-and-braces on top of reveal.js's own check (which skips adding `.msr-reveal`
   entirely) - if that class ever ends up on <html> anyway, nothing stays hidden and nothing transitions. */
@media (prefers-reduced-motion: reduce) {
  html.msr-reveal [data-msr-reveal]:not(.is-revealed) {
    opacity: 1 !important;
    transform: none !important;
  }

  html.msr-reveal [data-msr-reveal] {
    transition: none !important;
  }
}
