/**
 * Scroll-reveal entrance animations (mirrors the staging .reveal system).
 *
 * Add one of these classes to any element — an Oxygen component, a shortcode's
 * markup, the timeline — and reveal.js adds `.in` when it scrolls into view
 * (one-shot). Stagger siblings with the Tailwind delay-* utilities
 * (e.g. cur-reveal delay-200). Reduced motion shows everything immediately.
 *
 *   cur-reveal        fade + rise (default)
 *   cur-reveal-fast   shorter fade + small rise
 *   cur-reveal-slow   blurred, scaled, slow settle (big media)
 *   cur-reveal-year   blurred scale fade (oversized numbers/words)
 *   cur-reveal-title  clip-path curtain rise (headings)
 *
 * The bare `reveal*` aliases exist because sections authored in the Oxygen
 * builder mirror the staging markup and use the staging class names; both
 * families behave identically and reveal.js observes both.
 */

.cur-reveal,
.reveal {
	opacity: 0;
	transform: translateY(28px);
	transition: opacity 0.7s var( --ease-smooth, cubic-bezier( 0.25, 1, 0.5, 1 ) ),
		transform 0.7s var( --ease-smooth, cubic-bezier( 0.25, 1, 0.5, 1 ) );
}
.cur-reveal.in,
.reveal.in {
	opacity: 1;
	transform: none;
}

.cur-reveal-fast,
.reveal-fast {
	opacity: 0;
	transform: translateY(12px);
	transition: opacity 0.3s var( --ease-smooth, cubic-bezier( 0.25, 1, 0.5, 1 ) ),
		transform 0.3s var( --ease-smooth, cubic-bezier( 0.25, 1, 0.5, 1 ) );
}
.cur-reveal-fast.in,
.reveal-fast.in {
	opacity: 1;
	transform: none;
}

.cur-reveal-slow,
.reveal-slow {
	opacity: 0;
	filter: blur(14px);
	transform: translateY(40px) scale(1.05);
	transition: opacity 1.2s var( --ease-smooth, cubic-bezier( 0.25, 1, 0.5, 1 ) ),
		transform 1.2s var( --ease-smooth, cubic-bezier( 0.25, 1, 0.5, 1 ) ),
		filter 1.2s var( --ease-smooth, cubic-bezier( 0.25, 1, 0.5, 1 ) );
}
.cur-reveal-slow.in,
.reveal-slow.in {
	opacity: 1;
	filter: blur(0);
	transform: none;
}

/* Year: subtle scale + blur fade for editorial pop. */
.cur-reveal-year,
.reveal-year {
	opacity: 0;
	filter: blur(6px);
	transform: translateY(20px) scale(0.96);
	transition: opacity 0.9s var( --ease-smooth, cubic-bezier( 0.25, 1, 0.5, 1 ) ),
		transform 0.9s var( --ease-smooth, cubic-bezier( 0.25, 1, 0.5, 1 ) ),
		filter 0.9s var( --ease-smooth, cubic-bezier( 0.25, 1, 0.5, 1 ) );
}
.cur-reveal-year.in,
.reveal-year.in {
	opacity: 1;
	filter: blur(0);
	transform: none;
}

/* Title: clip-path curtain-rise reveal. */
.cur-reveal-title,
.reveal-title {
	opacity: 0;
	clip-path: inset(0 0 100% 0);
	transform: translateY(8px);
	transition: opacity 1s var( --ease-smooth, cubic-bezier( 0.25, 1, 0.5, 1 ) ),
		clip-path 1s var( --ease-smooth, cubic-bezier( 0.25, 1, 0.5, 1 ) ),
		transform 1s var( --ease-smooth, cubic-bezier( 0.25, 1, 0.5, 1 ) );
}
.cur-reveal-title.in,
.reveal-title.in {
	opacity: 1;
	clip-path: inset(0 0 0 0);
	transform: none;
}

/* Lazy image fade.
 *
 * Native loading="lazy" paints an image the instant it decodes, which reads as a
 * hard pop against the reserved (aspect-ratio) frame — and worse when a
 * cur-reveal* wrapper has already faded an empty box in ahead of it. reveal.js
 * stamps data-curel-fade on each lazy image and flips it to "in" on load.
 *
 * The hidden state keys off the attribute, never off a root class: if the script
 * never runs, nothing is stamped and every image simply stays visible. Same
 * reason the error path in reveal.js also flips to "in" — a 404 must not leave an
 * invisible hole.
 *
 * Lazy images only. The LCP candidate (the PDP featured image: fetchpriority=high,
 * not lazy) is never stamped, so the largest paint is untouched. The frames
 * already reserve their space, so nothing here can shift layout.
 */
img[data-curel-fade] {
	opacity: 0;
	transition: opacity 0.5s var( --ease-smooth, cubic-bezier( 0.25, 1, 0.5, 1 ) );
}
img[data-curel-fade="in"] {
	opacity: 1;
}

@media ( prefers-reduced-motion: reduce ) {
	.cur-reveal,
	.cur-reveal-fast,
	.cur-reveal-slow,
	.cur-reveal-year,
	.cur-reveal-title,
	.reveal,
	.reveal-fast,
	.reveal-slow,
	.reveal-year,
	.reveal-title {
		opacity: 1 !important;
		filter: none !important;
		clip-path: none !important;
		transform: none !important;
		transition: none !important;
	}
	/* reveal.js skips stamping under reduced motion; this covers the image already
	   stamped when the setting is turned on mid-session. */
	img[data-curel-fade] {
		opacity: 1 !important;
		transition: none !important;
	}
}
