/**
 * Motion tokens + image loading treatment.
 *
 * Policy (evidence-based, see Playbook: Motion-Policy--Perceived-Performance):
 * - Content never waits for motion: above-fold/LCP/hero/text render instantly.
 * - Only BELOW-FOLD lazy images get the treatment (frequency rule).
 * - No-motion-first: all motion lives inside prefers-reduced-motion: no-preference.
 * - Skeleton pulse runs max 2 loops, then holds static (NNG: indicators for
 *   sub-second waits add noise; the skeleton must not outstay its welcome).
 */

:root {
	--motion-duration-instant: 0ms;   /* content, LCP, text, CTAs */
	--motion-duration-fast: 150ms;    /* image cross-fade, hover feedback */
	--motion-duration-base: 250ms;    /* accordions, modals, single scroll reveal */
	--motion-duration-slow: 400ms;    /* ceiling — large transitions only */
	--motion-ease-enter: cubic-bezier(0.05, 0.7, 0.1, 1);
	--motion-ease-exit: cubic-bezier(0.3, 0, 0.8, 0.15);
	--motion-ease-standard: cubic-bezier(0.2, 0, 0, 1);
	--motion-distance-reveal: 16px;   /* max entrance translate */
}

@media (prefers-reduced-motion: no-preference) {

	/* Skeleton on below-fold lazy images only, while loading: two gentle
	   pulses, then a calm static tone (background shows through the empty img
	   box; space is already reserved by width/height attributes).
	   Opacity-only on purpose: <img> can't host pseudo-elements, and
	   background-position animates on the main thread — opacity keeps the
	   skeleton compositor-driven. */
	html.rd-imgfx img[loading="lazy"]:not(.rd-loaded) {
		background: var(--neutral-ultra-light);
		animation: rd-pulse 1.2s ease-in-out 2;
	}

	/* Lazy images that arrive late cross-fade in — fast, per the frequency rule */
	html.rd-imgfx img[loading="lazy"].rd-fade {
		animation: rd-fadein var(--motion-duration-fast) var(--motion-ease-enter);
	}

	@keyframes rd-pulse {
		from, to { opacity: 1; }
		50%      { opacity: 0.55; }
	}

	@keyframes rd-fadein {
		from { opacity: 0.1; } /* never 0: keeps first paint meaningful */
		to   { opacity: 1; }
	}
}
