/**
 * Wakeford Motion — scroll-reveal presentation layer.
 *
 * Every rule is gated behind `.wf-motion-ready` on the root element, which is
 * added by a tiny inline script only when JavaScript runs and the visitor has
 * not asked for reduced motion. Without that class nothing here applies, so
 * content is fully visible for no-JS visitors, crawlers, print and reader
 * modes, and there is never a flash of hidden content.
 *
 * Theme-agnostic: no colours, fonts or spacing are set here.
 */

.wf-motion-ready [data-wf-motion] {
	--wf-m-dur: 800ms;
	--wf-m-delay: 0ms;
	--wf-m-dist: 24px;
	--wf-m-ease: cubic-bezier(0.22, 1, 0.36, 1);
	--wf-m-blur: 8px;
	--wf-m-scale: 1.06;
	--wf-m-stagger: 80ms;
	--wf-m-i: 0;

	transition-delay: calc(var(--wf-m-delay) + var(--wf-m-i) * var(--wf-m-stagger));
	transition-duration: var(--wf-m-dur);
	transition-property: opacity, transform, filter;
	transition-timing-function: var(--wf-m-ease);
	will-change: opacity, transform;
}

/* Resting (out of view) states. */
.wf-motion-ready [data-wf-motion="fade"],
.wf-motion-ready [data-wf-motion="fade-up"],
.wf-motion-ready [data-wf-motion="fade-down"],
.wf-motion-ready [data-wf-motion="fade-left"],
.wf-motion-ready [data-wf-motion="fade-right"],
.wf-motion-ready [data-wf-motion="zoom-in"],
.wf-motion-ready [data-wf-motion="zoom-out"],
.wf-motion-ready [data-wf-motion="blur-in"] {
	opacity: 0;
}

.wf-motion-ready [data-wf-motion="fade-up"] {
	transform: translate3d(0, var(--wf-m-dist), 0);
}

.wf-motion-ready [data-wf-motion="fade-down"] {
	transform: translate3d(0, calc(var(--wf-m-dist) * -1), 0);
}

.wf-motion-ready [data-wf-motion="fade-left"] {
	transform: translate3d(var(--wf-m-dist), 0, 0);
}

.wf-motion-ready [data-wf-motion="fade-right"] {
	transform: translate3d(calc(var(--wf-m-dist) * -1), 0, 0);
}

.wf-motion-ready [data-wf-motion="zoom-in"] {
	transform: scale(calc(2 - var(--wf-m-scale)));
}

.wf-motion-ready [data-wf-motion="zoom-out"] {
	transform: scale(var(--wf-m-scale));
}

.wf-motion-ready [data-wf-motion="blur-in"] {
	filter: blur(var(--wf-m-blur));
	transform: scale(calc(1 + (var(--wf-m-scale) - 1) * 0.4));
}

/* Wipes are done with a mask, not clip-path.
 *
 * clip-path shrinks the element's intersection rectangle, so a tall element
 * clipped to nothing has its only visible sliver at the far edge — often below
 * the fold. IntersectionObserver then never reports it, it is never revealed,
 * and it stays hidden forever. A mask hides paint without touching the box the
 * observer measures, so the reveal can always fire.
 */
.wf-motion-ready [data-wf-motion^="reveal-"],
.wf-motion-ready [data-wf-motion="image-reveal"] {
	-webkit-mask-image: linear-gradient(#000, #000);
	mask-image: linear-gradient(#000, #000);
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	transition-property: opacity, transform, filter, -webkit-mask-size, mask-size;
}

.wf-motion-ready [data-wf-motion="reveal-up"],
.wf-motion-ready [data-wf-motion="image-reveal"] {
	-webkit-mask-position: 0 100%;
	mask-position: 0 100%;
	-webkit-mask-size: 100% 0%;
	mask-size: 100% 0%;
}

.wf-motion-ready [data-wf-motion="reveal-left"] {
	-webkit-mask-position: 100% 0;
	mask-position: 100% 0;
	-webkit-mask-size: 0% 100%;
	mask-size: 0% 100%;
}

.wf-motion-ready [data-wf-motion="reveal-right"] {
	-webkit-mask-position: 0 0;
	mask-position: 0 0;
	-webkit-mask-size: 0% 100%;
	mask-size: 0% 100%;
}

.wf-motion-ready [data-wf-motion="image-reveal"] img,
.wf-motion-ready [data-wf-motion="image-reveal"] video {
	transform: scale(var(--wf-m-scale));
	transform-origin: center;
	transition:
		transform calc(var(--wf-m-dur) * 1.25) var(--wf-m-ease)
		calc(var(--wf-m-delay) + var(--wf-m-i) * var(--wf-m-stagger));
}

/* Split text. The wrapper hides the overflow so each unit rises out of nothing.
   The padding/margin pair keeps descenders from being clipped by that mask. */
.wf-motion-ready .wf-m-unit {
	display: inline-block;
	margin-bottom: -0.18em;
	overflow: hidden;
	padding-bottom: 0.18em;
	vertical-align: top;
}

.wf-motion-ready .wf-m-unit > span {
	display: inline-block;
	transform: translate3d(0, 110%, 0);
	transition:
		transform var(--wf-m-dur, 800ms)
		var(--wf-m-ease, cubic-bezier(0.22, 1, 0.36, 1))
		calc(var(--wf-m-delay, 0ms) + var(--wf-m-unit-i, 0) * var(--wf-m-stagger, 80ms));
	will-change: transform;
}

.wf-motion-ready [data-wf-motion="words"],
.wf-motion-ready [data-wf-motion="lines"] {

	/* The units animate, not the block; keep the block itself painted. */
	opacity: 1;
}

/* In-view states. */
.wf-motion-ready [data-wf-motion][data-wf-inview] {
	filter: none;
	opacity: 1;
	transform: none;
}

.wf-motion-ready [data-wf-motion^="reveal-"][data-wf-inview],
.wf-motion-ready [data-wf-motion="image-reveal"][data-wf-inview] {
	-webkit-mask-size: 100% 100%;
	mask-size: 100% 100%;
}

.wf-motion-ready [data-wf-motion="image-reveal"][data-wf-inview] img,
.wf-motion-ready [data-wf-motion="image-reveal"][data-wf-inview] video {
	transform: scale(1);
}

.wf-motion-ready [data-wf-inview] .wf-m-unit > span {
	transform: translate3d(0, 0, 0);
}

/* Release compositor hints once the reveal has finished, so a long page does
   not keep dozens of promoted layers alive. */
.wf-motion-ready [data-wf-settled],
.wf-motion-ready [data-wf-settled] .wf-m-unit > span {
	will-change: auto;
}

/* Continuous parallax. Driven by a single shared rAF loop; the element only
   ever receives a transform, so it stays on the compositor. */
.wf-motion-ready [data-wf-parallax] {
	transform: translate3d(0, var(--wf-p-y, 0), 0);
	will-change: transform;
}

/* Honour the OS setting even if the gate class was somehow applied. */
@media (prefers-reduced-motion: reduce) {

	.wf-motion-ready [data-wf-motion],
	.wf-motion-ready [data-wf-parallax] {
		-webkit-mask-image: none !important;
		clip-path: none !important;
		filter: none !important;
		mask-image: none !important;
		opacity: 1 !important;
		transform: none !important;
		transition: none !important;
	}

	.wf-motion-ready .wf-m-unit > span {
		transform: none !important;
		transition: none !important;
	}
}
