/**
 * Scrolling Scenes
 *
 * The unenhanced layout is the one written first here: a stack of full-screen scenes, each
 * readable on its own. Everything under `.is-pinned` is the enhancement JavaScript turns on.
 *
 * `--scene-band` is how much scroll a scene owns, in viewports, and the track is that times the
 * count plus the one viewport the sticky stage occupies. The tripwire rail is the same arithmetic,
 * and script.js measures a tripwire rather than assuming, so the band is changed here and nowhere
 * else. A phone takes less of it: a full screen of scroll per scene is a long way down on a device
 * that is scrolled in flicks.
 *
 * Under the pin a scene arrives as one beat: script.js names the current scene and every layer
 * moves together on `--scene-arrival-duration`. Nothing is staggered and nothing is delayed — the
 * scene is a frame that cuts in, not a sequence the scroll scrubs through. Re-time it with that
 * one token; anything that gives a layer its own delay puts the sequence back.
 *
 * Every length in the pinned geometry is dvh. The sticky stage is what fills the screen and a
 * mobile browser's toolbar collapses as you scroll: sized to the small viewport the stage falls
 * short of the screen once it does, and the page shows through under it. The track and the
 * tripwire rail are measured against the stage, so mixing units unsticks the last scene early by
 * whatever the toolbar is worth.
 *
 * `.scene-link` restates the global anchor transition to add `visibility 0s`. That rule is
 * `transition: all`, `all` covers `visibility`, and `visibility` is discrete — so it flips at half
 * the duration, leaving a link hidden for 125ms after its scene becomes current. focus() drops a
 * call on a hidden element rather than erroring, which is what made Tab land a keypress behind the
 * page. The instant `box-shadow` and `outline-*` come with it; dropping them fades the focus ring.
 *
 * Below 650 the sunburst answers to `--sunburst-position-mobile` if the scene sets one, and is
 * otherwise placed off the foreground's band — which is why `--foreground-height` rides the layer
 * stack instead of the photograph that reads it. The mark's height follows the viewport's width
 * and its authored foot is a share of the scene's height, so on a phone the desktop number stops
 * meaning what it meant: it lands a long way inside a band that runs to the foot of the screen,
 * covered by the cutout and under the dark end of the scrim. The automatic placement clears the
 * photograph, but it is the same height on every scene and so sits outside each one's own
 * composition — which is what the per-scene control is for.
 */

.module.scenes .state-dots {
	list-style: none;
	margin: 0;
	padding: 0;
}

.module.scenes .scene {
	align-content: end;
	display: grid;
	isolation: isolate;
	min-height: 100dvh;
	position: relative;
	--focus-ring: var(--white); /* Dark band: a charcoal ring disappears into the scrim */
}

/** Layers — background, sunburst, foreground, scrim, bottom-anchored in that order **/

.module.scenes .layers {
	inset: 0;
	position: absolute;
	z-index: -1;
}

.module.scenes .media {
	aspect-ratio: auto;
	inset: 0;
	position: absolute;
}

.module.scenes .media.backdrop img {
	object-position: bottom center;
}

.module.scenes .media.fore {
	height: var(--foreground-height, 72%);
	top: auto;
}

.module.scenes .media.fore.focus-top img {
	object-position: top center;
}

.module.scenes .media.fore.focus-center img {
	object-position: center;
}

.module.scenes .media.fore.focus-bottom img {
	object-position: bottom center;
}

.module.scenes .sunburst {
	aspect-ratio: 990 / 434;
	bottom: calc(var(--sunburst-anchor, var(--sunburst-position, 33%)) + var(--sunburst-lift, 0px));
	color: var(--white);
	display: block;
	left: 0;
	margin-inline: auto;
	opacity: var(--sunburst-opacity, 0.12);
	position: absolute;
	right: 0;
	width: min(76.7%, 131svh);
}

.module.scenes .sunburst svg {
	display: block;
	height: 100%;
	max-width: none;
	width: 100%;
}

.module.scenes .layers::after {
	background: linear-gradient(180deg, transparent 0%, var(--overlay-scrim-strong) 55%, var(--overlay-darker) 100%);
	bottom: 0;
	content: '';
	height: 58%;
	left: 0;
	position: absolute;
	right: 0;
}

/** Copy **/

.module.scenes .content {
	align-items: end;
	display: flex;
	gap: var(--text-spacing-medium);
	justify-content: space-between;
	padding-block: var(--module-spacing-small);
}

.module.scenes .text {
	color: var(--white);
	display: flex;
	flex-direction: column;
	gap: var(--text-spacing-small);
	min-width: 0;
	overflow-wrap: anywhere;
}

.module.scenes .text .main {
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.module.scenes .text :is(p, h1, h2, h3, h4, h5, h6) {
	margin: 0;
}

.module.scenes .scene-link {
	color: inherit;
	text-decoration: none;
	transition: all var(--motion) var(--ease-out), box-shadow 0s, outline-color 0s, outline-offset 0s, outline-width 0s, visibility 0s;
}

.module.scenes .scene-link:focus-visible {
	box-shadow: 0 0 0 2px var(--focus-halo);
	outline: 2px solid var(--focus-ring);
	outline-offset: 2px;
}

.module.scenes .scene-link::after {
	content: '';
	inset: 0;
	position: absolute;
	z-index: 1;
}

.module.scenes .btn.secondary.mega {
	flex: none;
	margin-bottom: var(--text-spacing-xxsmall);
}

.module.scenes .content:hover .btn.secondary.mega .arrow,
.module.scenes .content:focus-within .btn.secondary.mega .arrow {
	background: var(--sun-light);
}

/* The arrow is the band's link drawn as a button, so it wears the link's focus ring too — otherwise
   it reads as a control the keyboard never reaches. No halo: a white one fuses with the pale pill,
   and the dark band showing through the offset is what makes the ring read as a ring. */
.module.scenes .content:has(.scene-link:focus-visible) .btn.secondary.mega .arrow {
	box-shadow: none;
	outline: 2px solid var(--focus-ring);
	outline-offset: 4px;
}

/** State dots — position, not navigation **/

.module.scenes .state-dots {
	display: none;
}

/***********************************************************************/
/***********************************************************************/

.module.scenes.is-pinned .track {
	height: calc((var(--scene-count) * var(--scene-band, 1) + 1) * 100dvh);
	position: relative;
}

.module.scenes .scene-rail {
	bottom: auto;
	height: calc(var(--scene-count) * var(--scene-band, 1) * 100dvh);
	left: 0;
	pointer-events: none;
	position: absolute;
	right: 0;
	top: 50dvh;
	visibility: hidden;
	z-index: -1;
}

.module.scenes .scene-rail span {
	display: block;
	height: calc(var(--scene-band, 1) * 100dvh);
}

.module.scenes.is-pinned .stage {
	height: 100dvh;
	overflow: clip;
	position: sticky;
	top: 0;
}

.module.scenes.is-pinned .scene-list {
	display: grid;
	height: 100%;
}

.module.scenes.is-pinned {
	--scene-arrival-duration: 700ms;
	--scene-band: 1;
}

.module.scenes.is-pinned .scene {
	grid-area: 1 / 1;
	min-height: 0;
	opacity: 0;
	transition: opacity var(--scene-arrival-duration) var(--ease-out),
	            visibility 0s linear var(--scene-arrival-duration);
	visibility: hidden;
}

.module.scenes.is-pinned .scene.is-current {
	opacity: 1;
	transition: opacity var(--scene-arrival-duration) var(--ease-out), visibility 0s;
	visibility: visible;
}

.module.scenes.is-pinned .scene.is-visible {
	visibility: visible;
}

/** Arrival — the whole scene cuts in at once, every layer on the one duration **/

.module.scenes.is-pinned .scene .media.backdrop {
	scale: 1.08;
	transition: scale var(--scene-arrival-duration) var(--ease-out);
}

.module.scenes.is-pinned .scene .media.fore {
	scale: 1.06;
	transition: scale var(--scene-arrival-duration) var(--ease-out),
	            translate var(--scene-arrival-duration) var(--ease-out);
	translate: 0 40px;
}

.module.scenes.is-pinned .scene .sunburst {
	--sunburst-opacity: 0;
	transition: opacity var(--scene-arrival-duration) var(--ease-out),
	            translate var(--scene-arrival-duration) var(--ease-out);
	translate: 0 45%;
}

.module.scenes.is-pinned .scene .content {
	opacity: 0;
	transition: opacity var(--scene-arrival-duration) var(--ease-out),
	            translate var(--scene-arrival-duration) var(--ease-out);
	translate: 0 24px;
}

.module.scenes.is-pinned .scene.is-current :is(.media.backdrop, .media.fore, .sunburst, .content) {
	scale: 1;
	translate: 0 0;
}

.module.scenes.is-pinned .scene.is-current .sunburst {
	--sunburst-opacity: 0.12;
}

.module.scenes.is-pinned .scene.is-current .content {
	opacity: 1;
}

/** Settling — the track parks on a scene rather than between two **/

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

	html:has(.module.scenes.is-pinned) {
		scroll-snap-type: y proximity;
	}

	.module.scenes.is-pinned .scene-rail span {
		scroll-snap-align: center;
	}

}

.module.scenes.is-pinned .state-dots {
	background: var(--overlay-scrim-strong);
	border-radius: 40px;
	display: flex;
	flex-direction: column;
	padding: 6px 3px;
	position: absolute;
	right: 21px;
	top: 50%;
	translate: 0 -50%;
	z-index: 3;
}

.module.scenes.is-pinned .state-dots li {
	display: flex;
}

.module.scenes.is-pinned .state-dots a {
	border-radius: 50%;
	display: block;
	padding: 9px;
}

/* The column sits on a scrim because a dot over a sky is the one place on the page where white
   has nothing to contrast with; on it, a resting dot at .7 clears 3:1 wherever the photograph
   lands (WCAG 1.4.11). */
.module.scenes.is-pinned .state-dots a::before {
	background: var(--white);
	border-radius: 50%;
	content: '';
	display: block;
	height: 6px;
	opacity: 0.7;
	transition: background-color var(--motion) var(--ease-out), opacity var(--motion) var(--ease-out);
	width: 6px;
}

.module.scenes.is-pinned .state-dots li.is-current a::before {
	background: var(--sun);
	opacity: 1;
}

.module.scenes.is-pinned .state-dots a:focus-visible {
	box-shadow: 0 0 0 2px var(--focus-halo);
	outline: 2px solid var(--focus-ring);
	outline-offset: 2px;
}

/***************************************************************************************************************************************************************************************/
/* MQ MAX-WIDTH 950 - Tablet Sizes */
/***************************************************************************************************************************************************************************************/

@media only screen and (max-width: calc(950rem/16)) {

	.module.scenes .content {
		align-items: start;
		flex-direction: column;
		gap: var(--text-spacing-medium);
	}

	.module.scenes .text .main {
		gap: var(--text-spacing-xxsmall);
	}

	.module.scenes .sunburst {
		--sunburst-lift: 1vw;
	}

	.module.scenes .btn.secondary.mega {
		margin-bottom: 0;
	}

	.module.scenes.is-pinned .state-dots {
		right: 11px;
	}

}

/***************************************************************************************************************************************************************************************/
/* MQ MAX-WIDTH 650 - Mobile Sizes */
/***************************************************************************************************************************************************************************************/

@media only screen and (max-width: calc(650rem/16)) {

	.module.scenes .content {
		align-items: center;
		text-align: center;
	}

	.module.scenes .sunburst {
		--sunburst-anchor: var(--sunburst-position-mobile, calc(var(--foreground-height, 72%) - 23.5vw));
		--sunburst-lift: 0px;
	}

	.module.scenes.is-pinned {
		--scene-arrival-duration: 500ms;
		--scene-band: 0.6;
	}

}

/***************************************************************************************************************************************************************************************/
/* REDUCED MOTION                                                                                                                                                                       */
/***************************************************************************************************************************************************************************************/

/* A screen shorter than a scene's copy — 400% zoom on a laptop — gets the same stack, so the
   heading is never held above an edge it cannot scroll past. The script stops pinning at the
   same line; this is the fallback if the class is ever there anyway. */
@media (prefers-reduced-motion: reduce), (max-height: 500px) {

	.module.scenes.is-pinned .track {
		height: auto;
	}

	.module.scenes.is-pinned .stage {
		height: auto;
		overflow: visible;
		position: static;
	}

	.module.scenes.is-pinned .scene-list {
		display: block;
		height: auto;
	}

	.module.scenes.is-pinned .scene {
		min-height: 100dvh;
		opacity: 1;
		pointer-events: auto;
		transition: none;
		visibility: visible;
	}

	.module.scenes.is-pinned .scene :is(.media.backdrop, .media.fore, .content) {
		opacity: 1;
		scale: 1;
		transition: none;
		translate: 0 0;
	}

	.module.scenes.is-pinned .scene .sunburst {
		--sunburst-opacity: 0.12;
		scale: 1;
		transition: none;
		translate: 0 0;
	}

	.module.scenes.is-pinned .state-dots {
		display: none;
	}

}
