/* ==========================================================================
   motion.css — entrance animations, and the way out of them
   --------------------------------------------------------------------------
   The source template hides every entrance element with `opacity: 0` in CSS
   and reveals it from GSAP/scrollCue. With JavaScript disabled, or a JS error,
   or a slow connection where the library times out, the page is simply blank —
   which is the single worst defect in the original design.

   The rule here is the inverse: **content is visible by default**, and JS opts
   an element INTO the hidden state only once it knows it can also take it back
   out (`html.js` + `.reveal`). A failure anywhere leaves the page readable.

   Three gates in order:
     1. `no-preference` + JS  → full motion
     2. `no-preference` + no JS → everything visible, transitions off
     3. `reduce` → everything visible, transitions off, marquee stopped
   ========================================================================== */

/* ---- Reveal ------------------------------------------------------------
   Applied by JS: `.reveal` is added, then removed when the element enters the
   viewport. `.reveal` is only ever present when `html.js` exists, so a no-JS
   visitor never sees the hidden state. */
html.js .reveal {
	opacity: 0;
	transform: translateY(18px);
	transition: opacity 0.6s var(--ease-out), transform 0.6s var(--ease-out);
	transition-delay: var(--reveal-delay, 0s);
	will-change: opacity, transform;
}

html.js .reveal.is-in {
	opacity: 1;
	transform: none;
	/* Release the compositing hint once the animation is done: keeping
	   will-change on a dozen elements holds layers and costs memory on mobile. */
	will-change: auto;
}

/* The template's second reveal idiom: a wrapper whose children animate in
   sequence (`data-cues="fadeIn"`). */
html.js .reveal-group > * {
	opacity: 0;
	transform: translateY(14px);
	transition: opacity 0.5s var(--ease-out), transform 0.5s var(--ease-out);
	transition-delay: calc(var(--i, 0) * 0.06s);
}

html.js .reveal-group.is-in > * {
	opacity: 1;
	transform: none;
}

/* ---- Per-character headline reveal ------------------------------------
   JS splits the element into <span>s. Until it does, the text is untouched and
   therefore readable — that is the whole point: the split is an enhancement. */
html.js .split {
	display: inline-block;
}

html.js .split > span {
	display: inline-block;
	opacity: 0;
	transform: translateY(0.4em);
	transition: opacity 0.5s var(--ease-out), transform 0.5s var(--ease-out);
	transition-delay: calc(var(--i, 0) * 0.022s);
}

html.js .split.is-in > span {
	opacity: 1;
	transform: none;
}

/* ---- Scroll-driven extras ---------------------------------------------- */

/* Image cards tilt in from the side (template: rotateY 90 → 0 with
   back.out(1.7)). A CSS approximation: the element starts rotated and
   slightly scaled, lands flat. The overshoot is dropped — it reads as a
   wobble at 60fps and the template's own timing makes it feel accidental. */
html.js .tilt {
	opacity: 0;
	transform: perspective(900px) rotateY(28deg) translateY(10px);
	transform-origin: top center;
	transition: opacity 0.6s var(--ease-out), transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
	transition-delay: calc(var(--i, 0) * 0.09s);
}

html.js .tilt.is-in {
	opacity: 1;
	transform: none;
}

/* Parallax backgrounds. The template ships the parallaxie plugin (a scroll
   listener per element). Here the image is a real <img> translated by a value
   the JS sets from one shared rAF loop — one listener for all of them. */
.parallax-img {
	will-change: transform;
}

/* ---- Reduced motion ---------------------------------------------------
   Everything that moves, stops moving; nothing that reveals, stays hidden.
   This is deliberately at the end of the cascade so it wins over the rules
   above without !important on each one. */
@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}

	html.js .reveal,
	html.js .reveal-group > *,
	html.js .split > span,
	html.js .tilt {
		opacity: 1 !important;
		transform: none !important;
		transition: none !important;
	}

	.marquee__track {
		animation: none !important;
		/* Without the animation the track is just a static row of duplicate
		   text; hide the second copy so it doesn't read as a mistake. */
	}

	.marquee__group[aria-hidden="true"] {
		display: none;
	}

	.btn-circle--ripple::before,
	.btn-circle--ripple::after {
		animation: none !important;
		opacity: 0.5;
	}

	.preloader::after {
		animation: none !important;
		background: var(--line);
	}

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

/* ---- No-JS belt and braces -------------------------------------------
   If a browser somehow has JS off but a stale `.reveal` in the markup (e.g.
   cached HTML from a previous version), this keeps the page readable. */
html:not(.js) .reveal,
html:not(.js) .reveal-group > *,
html:not(.js) .split > span,
html:not(.js) .tilt {
	opacity: 1;
	transform: none;
}
