/*
 * Motion utilities.
 *
 * The safety rule for the whole system: content is visible by default. The
 * starting, hidden state of a reveal is only applied under .afc-js, a class set
 * by a one line script in the head. If scripting is off, or that script never
 * runs, every element below renders in its final state and nothing is lost.
 *
 * prefers-reduced-motion is handled twice over. The duration tokens collapse to
 * 1ms in tokens.css, and the block at the end of this file removes the hidden
 * starting states outright so nothing waits on an observer.
 */

/* ---------------------------------------------------------------------------
 * Fade and translate reveal
 * ------------------------------------------------------------------------ */

.afc-js [data-afc-reveal] {
	opacity: 0;
	transform: translateY(var(--afc-reveal-distance));
	transition:
		opacity var(--afc-duration-reveal) var(--afc-ease-entrance),
		transform var(--afc-duration-reveal) var(--afc-ease-entrance);
	transition-delay: var(--afc-reveal-delay, 0ms);
	will-change: opacity, transform;
}

.afc-js [data-afc-reveal="left"] {
	transform: translateX(calc(var(--afc-reveal-distance) * -1));
}

.afc-js [data-afc-reveal="right"] {
	transform: translateX(var(--afc-reveal-distance));
}

.afc-js [data-afc-reveal="fade"] {
	transform: none;
}

.afc-js [data-afc-reveal="scale"] {
	transform: scale(0.97);
}

.afc-js [data-afc-reveal].is-revealed {
	opacity: 1;
	transform: none;
	will-change: auto;
}

/* Staggered children. The index is set by the script, capped so a long list
   never ends with an absurd delay. */
.afc-js [data-afc-stagger] > * {
	--afc-reveal-delay: calc(var(--afc-reveal-index, 0) * var(--afc-stagger-step));
}

/* ---------------------------------------------------------------------------
 * Image mask reveal
 *
 * The photograph is uncovered rather than faded, which reads as a shutter and
 * suits architectural imagery. clip-path is widely supported, and where it is
 * not the image simply appears.
 * ------------------------------------------------------------------------ */

@supports (clip-path: inset(0)) {
	.afc-js [data-afc-reveal="mask"] {
		opacity: 1;
		transform: none;
		clip-path: inset(0 0 100% 0);
		transition: clip-path var(--afc-duration-reveal) var(--afc-ease-entrance);
		transition-delay: var(--afc-reveal-delay, 0ms);
	}

	.afc-js [data-afc-reveal="mask"].is-revealed {
		clip-path: inset(0 0 0 0);
	}
}

/* ---------------------------------------------------------------------------
 * Architectural line drawing
 *
 * A rule that draws itself across the width of its container once it scrolls
 * into view. Used above section headings and between process steps.
 * ------------------------------------------------------------------------ */

.afc-line {
	position: relative;
	display: block;
	block-size: 2px;
	background: var(--afc-color-border);
	overflow: hidden;
}

.afc-line::after {
	content: "";
	position: absolute;
	inset-block: 0;
	inset-inline-start: 0;
	inline-size: 100%;
	background: var(--afc-color-brand-red);
	transform: scaleX(0);
	transform-origin: left center;
	transition: transform var(--afc-duration-reveal) var(--afc-ease-entrance);
}

.afc-js .afc-line.is-revealed::after,
html:not(.afc-js) .afc-line::after {
	transform: scaleX(1);
}

/* ---------------------------------------------------------------------------
 * Connected line reveal
 *
 * A wrapper that draws a line across its own width, together with the markers sitting
 * on that line, rather than moving itself. Used by the homepage process band, where the
 * four stages share one continuous line and translating the wrapper would drag the line
 * along with it.
 *
 * The wrapper only flips a flag. Each part decides what to do with it, which is how one
 * observer hit can drive a line growing from the left and four nodes popping in
 * sequence. Custom properties are not interpolated themselves, but a transform that
 * substitutes one produces a new computed value, and the transition on transform picks
 * that up normally.
 * ------------------------------------------------------------------------ */

.afc-js [data-afc-reveal="line"] {
	--afc-line-draw: 0;
	/* This wrapper never fades or moves, so the shared reveal above is cancelled. */
	opacity: 1;
	transform: none;
	transition: none;
}

.afc-js [data-afc-reveal="line"].is-revealed {
	--afc-line-draw: 1;
}

/* Without scripting the line is simply drawn, like every other reveal in this file. */
html:not(.afc-js) [data-afc-reveal="line"] {
	--afc-line-draw: 1;
}

/* ---------------------------------------------------------------------------
 * Counter
 *
 * The final value is present in the markup. The script only animates the
 * intermediate numbers, so the correct figure shows without scripting and under
 * reduced motion.
 * ------------------------------------------------------------------------ */

[data-afc-count-to] {
	font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------------
 * Parallax
 *
 * Restricted to large decorative images. The offset is a custom property the
 * script updates inside requestAnimationFrame, and the movement is small enough
 * that no gap can appear at the edge of the frame.
 * ------------------------------------------------------------------------ */

[data-afc-parallax] {
	--afc-parallax-offset: 0px;
}

.afc-js [data-afc-parallax] img {
	block-size: 112%;
	transform: translate3d(0, var(--afc-parallax-offset), 0);
	will-change: transform;
}

/* ---------------------------------------------------------------------------
 * Section divider
 * ------------------------------------------------------------------------ */

.afc-divider {
	border: 0;
	block-size: 1px;
	margin-block: var(--afc-space-xl);
	background: var(--afc-color-border);
}

.afc-divider--accent {
	block-size: var(--afc-rule-weight);
	inline-size: 56px;
	background: var(--afc-color-brand-red);
}

/* ---------------------------------------------------------------------------
 * Reduced motion
 * ------------------------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
	.afc-js [data-afc-reveal],
	.afc-js [data-afc-reveal="mask"] {
		opacity: 1 !important;
		transform: none !important;
		clip-path: none !important;
		transition: none !important;
	}

	.afc-line::after {
		transform: scaleX(1) !important;
		transition: none !important;
	}

	/* The connected line arrives drawn, and its nodes arrive placed. */
	.afc-js [data-afc-reveal="line"] {
		--afc-line-draw: 1;
	}

	.afc-js [data-afc-parallax] img {
		block-size: auto;
		transform: none !important;
	}

	.afc-process__step::before {
		--afc-line-progress: 100%;
		transition: none !important;
	}
}

/* Without scripting the process rule is drawn in full rather than left empty. */
html:not(.afc-js) .afc-process__step::before {
	--afc-line-progress: 100%;
}
