/**
 * Scroll-reveal utilities.
 * main.js toggles `.is-visible` on `.js-reveal` elements via
 * IntersectionObserver. Kept as pure CSS transitions (no JS-driven
 * inline styles) so the effect degrades gracefully with JS disabled —
 * the .no-js fallback below removes the hidden state entirely.
 */
.js-reveal {
	opacity: 0;
	transform: translateY(24px);
	transition: opacity var(--duration-slow) var(--ease-out),
		transform var(--duration-slow) var(--ease-out);
	will-change: opacity, transform;
}

.js-reveal.is-visible {
	opacity: 1;
	transform: translateY(0);
}

.js-reveal--fade {
	transform: none;
}

.js-reveal--left {
	transform: translateX(-32px);
}

.js-reveal--left.is-visible {
	transform: translateX(0);
}

.js-reveal--right {
	transform: translateX(32px);
}

.js-reveal--right.is-visible {
	transform: translateX(0);
}

.js-reveal--scale {
	transform: scale(0.94);
}

.js-reveal--scale.is-visible {
	transform: scale(1);
}

/* Stagger children within a revealed group via inline --delay custom prop. */
.js-reveal {
	transition-delay: var(--reveal-delay, 0ms);
}

/* No-JS fallback: everything just shows immediately. */
html.no-js .js-reveal {
	opacity: 1;
	transform: none;
}

@media (prefers-reduced-motion: reduce) {
	.js-reveal {
		opacity: 1;
		transform: none;
		transition: none;
	}
}
@media (max-width: 900px) {
	.js-reveal--left,
	.js-reveal--right {
		transform: translateY(24px);
	}

	.js-reveal--left.is-visible,
	.js-reveal--right.is-visible {
		transform: translateY(0);
	}
}
