/**
 * Immersive hero.
 *
 * Loaded on the front page only. The stage is a sticky viewport inside a tall
 * scroll track: the track supplies the scroll distance, the stage stays put,
 * and `sequence.js` scrubs the canvas as the track passes.
 *
 * Two custom properties drive everything that reacts:
 *   --seq-progress  0-1 scroll position through the explode
 *   --seq-px/py     cursor offset, -1..1, for the parallax
 *
 * The stage colour is #73a76a — the exact backdrop baked into the render,
 * measured as the median of the frame border. Because they match, the frame
 * has no visible edge: the image bleeds into the page and the plant simply
 * stands in the room. Change one and you must change the other; the value is
 * printed by pauda-project/scripts/build-sequence.py on every build.
 */

.p-seq {
	--seq-progress: 0;
	--seq-px: 0;
	--seq-py: 0;
	--seq-backdrop: #73a76a;
	position: relative;
	background: var(--seq-backdrop);
	color: var(--p-ivory-100);
}

/* 560vh, of which the last ~100vh is the hold at the end of the sequence.
   See HOLD in assets/js/modules/sequence.js. */
.p-seq__track {
	height: 560vh;
}

@media (max-width: 767px) {
	.p-seq__track {
		height: 440vh;
	}
}

.p-seq__stage {
	position: sticky;
	top: 0;
	height: 100vh;
	height: 100svh;
	display: grid;
	place-items: center;
	overflow: hidden;
	/*
	 * A warm, clean room rather than a flat fill: light pooling from above,
	 * the faintest warmth gathering at the floor. Peach-ivory throughout, so
	 * the plant's own soft edges have nothing to contrast against and the
	 * cut-out disappears.
	 */
	/*
	 * Flat, matching the render. The source has only the faintest gradient of
	 * its own, so anything stronger here would read as a halo around the frame
	 * rather than as light in the room.
	 */
	background: var(--seq-backdrop);
}

/* Natural vignette, deepening as the column separates. */
.p-seq__stage::after {
	content: "";
	position: absolute;
	inset: 0;
	pointer-events: none;
	background: radial-gradient(
		ellipse 62% 70% at 50% 46%,
		transparent 0%,
		rgba(28, 58, 30, calc(0.05 + var(--seq-progress) * 0.06)) 74%,
		rgba(28, 58, 30, calc(0.13 + var(--seq-progress) * 0.09)) 100%
	);
}

/* Ambient glow behind the plant — the light the render is standing in. */
.p-seq__glow {
	display: none;
	position: absolute;
	top: 50%;
	left: 50%;
	width: min(74vh, 640px);
	height: min(84vh, 760px);
	transform: translate(-50%, -52%)
		translate(calc(var(--seq-px) * -10px), calc(var(--seq-py) * -8px));
	pointer-events: none;
	background: radial-gradient(
		ellipse at 50% 34%,
		rgba(255, 252, 244, 0.85) 0%,
		rgba(246, 238, 226, 0.42) 40%,
		transparent 72%
	);
	filter: blur(14px);
}

/* ---- The figure -------------------------------------------------------- */

.p-seq__figure {
	position: relative;
	/*
	 * The figure fills the whole stage. Frames are padded to 1.6:1 with their
	 * own backdrop, so on a normal window the image reaches every edge by
	 * itself; where the window is a different shape, `contain` letterboxes and
	 * the stage's matching green fills the remainder invisibly.
	 *
	 * `contain` rather than `cover` is the point: cover crops, and cropping
	 * this frame cuts the plant.
	 */
	width: 100%;
	height: 100%;
	display: grid;
	place-items: center;
	/* Parallax: the plant leads, the environment trails. */
	transform: translate3d(calc(var(--seq-px) * 14px), calc(var(--seq-py) * 10px), 0);
	transition: transform 620ms cubic-bezier(0.16, 1, 0.3, 1);
	will-change: transform;
}

.p-seq__poster,
.p-seq__canvas {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: contain;
	/*
	 * Layered ambient shadow cast by the plant itself rather than a box —
	 * drop-shadow follows the alpha channel, so it hugs the leaves and the
	 * discs instead of a rectangle.
	 */
	/*
	 * No drop-shadow. The render is a full-frame studio photograph with its
	 * own lighting and its own shadow under the pot; adding ours would cast a
	 * second shadow from a rectangle.
	 */
}

.p-seq__poster {
	z-index: 1;
	opacity: 1;
	transition: opacity 420ms var(--p-ease);
}

.p-seq__poster.is-out {
	opacity: 0;
}

.p-seq__canvas {
	opacity: 0;
	transition: opacity 420ms var(--p-ease);
}

.p-seq__canvas.is-live {
	opacity: 1;
}

/* Contact shadow on the floor, tightening as the column lifts apart. */
.p-seq__contact {
	display: none;
	position: absolute;
	left: 50%;
	bottom: 2%;
	width: calc(58% - var(--seq-progress) * 16%);
	height: 3.2%;
	transform: translateX(-50%);
	pointer-events: none;
	border-radius: 50%;
	background: radial-gradient(
		ellipse at 50% 50%,
		rgba(96, 84, 64, calc(0.34 - var(--seq-progress) * 0.14)) 0%,
		transparent 72%
	);
	filter: blur(7px);
}

/* No JS, reduced motion or a metered connection: the poster is the hero. */
.p-seq.is-static .p-seq__canvas {
	display: none;
}

.p-seq.is-static .p-seq__points,
.p-seq.is-static .p-seq__word--close {
	opacity: 1;
	transform: none;
	pointer-events: auto;
}

.p-seq.is-static .p-seq__cue {
	display: none;
}

/* ---- Typography -------------------------------------------------------- */

.p-seq__words {
	position: absolute;
	inset-inline: 0;
	top: clamp(var(--p-space-6), 9vh, 7rem);
	display: grid;
	justify-items: center;
	pointer-events: none;
	padding-inline: var(--p-gutter);
	text-align: center;
	z-index: 3;
}

.p-seq__word {
	grid-area: 1 / 1;
	font-family: var(--p-font-serif);
	font-size: clamp(1.75rem, 1.1rem + 2.8vw, 3.25rem);
	font-weight: 300;
	line-height: var(--p-leading-snug);
	color: #fff;
	letter-spacing: -0.01em;
	text-shadow: 0 2px 20px rgba(20, 48, 24, 0.32);
	transition:
		opacity 700ms var(--p-ease),
		transform 700ms var(--p-ease);
}

.p-seq__word--close {
	opacity: 0;
	transform: translateY(14px);
}

.p-seq.is-begun .p-seq__word--open {
	opacity: 0;
	transform: translateY(-14px);
}

.p-seq.is-exploded .p-seq__word--close {
	opacity: 1;
	transform: none;
}

/* ---- Scroll cue -------------------------------------------------------- */

.p-seq__cue {
	position: absolute;
	bottom: var(--p-space-6);
	left: 50%;
	transform: translateX(-50%);
	display: grid;
	justify-items: center;
	gap: var(--p-space-3);
	font-size: var(--p-text-micro);
	letter-spacing: var(--p-track-label);
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.72);
	opacity: calc(1 - var(--seq-progress) * 6);
	pointer-events: none;
	z-index: 3;
}

.p-seq__cueline {
	width: 1px;
	height: 40px;
	background: linear-gradient(to bottom, rgba(255, 255, 255, 0.8), transparent);
	animation: p-seq-cue 2.4s var(--p-ease) infinite;
	transform-origin: top;
}

@keyframes p-seq-cue {
	0% { transform: scaleY(0); opacity: 0; }
	40% { transform: scaleY(1); opacity: 1; }
	100% { transform: scaleY(1) translateY(40px); opacity: 0; }
}

/* ---- Hotspots ---------------------------------------------------------- */

/*
 * The hotspot layer must match the *picture*, not the figure. The frame is
 * letterboxed inside the figure by object-fit: contain, so a layer filling the
 * figure would drift off the plant on any window that is not 1.6:1. Mirroring
 * the aspect ratio and centring with auto margins reproduces `contain` exactly.
 */
.p-seq__points {
	position: absolute;
	inset: 0;
	margin: auto;
	aspect-ratio: 1984 / 1240;
	width: auto;
	height: auto;
	max-width: 100%;
	max-height: 100%;
	list-style: none;
	padding: 0;
	z-index: 4;
	pointer-events: none;
}

/*
 * Hotspots hang off the outer edges of the figure, never over it: the dot sits
 * just beyond the silhouette, a hairline runs outward, and the glass card sits
 * at the end of it. The centre of the plant stays completely clear.
 */
.p-seq__point {
	position: absolute;
	top: var(--y);
	transform: translateY(-50%);
}

.p-seq__point--right {
	left: var(--x, 80%);
}

.p-seq__point--left {
	right: calc(100% - var(--x, 20%));
}

.p-seq__pin {
	display: flex;
	align-items: center;
	gap: 0;
	color: #fff;
	text-decoration: none;
}

.p-seq__point--left .p-seq__pin {
	flex-direction: row-reverse;
}

/* The indicator. */
.p-seq__dot {
	position: relative;
	flex-shrink: 0;
	width: 9px;
	height: 9px;
	border-radius: 50%;
	background: #fff;
	box-shadow:
		0 0 0 1px rgba(255, 255, 255, 0.5),
		0 0 14px 3px rgba(255, 255, 255, 0.5);
	opacity: 0;
	transform: scale(0.4);
	transition:
		opacity 240ms var(--p-ease),
		transform 240ms var(--p-ease);
}

.p-seq__dot::after {
	content: "";
	position: absolute;
	inset: -6px;
	border-radius: 50%;
	border: 1px solid rgba(255, 255, 255, 0.6);
	opacity: 0;
	animation: p-seq-pulse 3.4s var(--p-ease) infinite;
}

@keyframes p-seq-pulse {
	0% { transform: scale(0.6); opacity: 0; }
	35% { opacity: 0.5; }
	100% { transform: scale(1.9); opacity: 0; }
}

/* The connector: a hairline that grows outward from the dot. */
.p-seq__wire {
	flex-shrink: 0;
	height: 1px;
	width: var(--wire, clamp(64px, 9vw, 190px));
	background: linear-gradient(
		to right,
		rgba(255, 255, 255, 0.7),
		rgba(255, 255, 255, 0.2)
	);
	transform: scaleX(0);
	transform-origin: left center;
	transition: transform 420ms var(--p-ease);
}

.p-seq__point--left .p-seq__wire {
	background: linear-gradient(
		to left,
		rgba(255, 255, 255, 0.7),
		rgba(255, 255, 255, 0.2)
	);
	transform-origin: right center;
}

/* The frosted glass card. */
.p-seq__card {
	display: grid;
	gap: 2px;
	padding: 0.6rem 0.95rem;
	border-radius: 18px;
	/*
	 * Frosted glass, inverted for a light ground. The brief specified
	 * rgba(255,255,255,0.08) with white text — that is a dark-hero recipe and
	 * would be invisible here. Same material, same blur, same restraint: a
	 * translucent white pane with ink text, which is what actually reads on
	 * ivory.
	 */
	background: rgba(255, 255, 255, 0.14);
	backdrop-filter: blur(20px) saturate(1.3);
	-webkit-backdrop-filter: blur(20px) saturate(1.3);
	border: 1px solid rgba(255, 255, 255, 0.28);
	box-shadow: 0 8px 30px rgba(20, 48, 24, 0.2);
	white-space: nowrap;
	opacity: 0;
	transform: translateX(-10px);
	transition:
		opacity 320ms var(--p-ease),
		transform 320ms var(--p-ease),
		border-color 260ms var(--p-ease),
		background 260ms var(--p-ease);
}

.p-seq__point--left .p-seq__card {
	transform: translateX(10px);
	text-align: right;
}

.p-seq__labeltext {
	font-size: var(--p-text-small);
	font-weight: 500;
	letter-spacing: var(--p-track-btn);
	color: #fff;
}

.p-seq__labelnote {
	font-size: var(--p-text-micro);
	color: rgba(255, 255, 255, 0.7);
}

/* Reveal: dot, then line, then card, then text — 300-500ms end to end. */
.p-seq.is-exploded .p-seq__point {
	pointer-events: auto;
}

.p-seq.is-exploded .p-seq__dot {
	opacity: 1;
	transform: scale(1);
}

.p-seq.is-exploded .p-seq__wire {
	transform: scaleX(1);
	transition-delay: 140ms;
}

.p-seq.is-exploded .p-seq__card {
	opacity: 1;
	transform: none;
	transition-delay: 300ms;
}

/* Stagger between hotspots. */
.p-seq.is-exploded .p-seq__point:nth-child(2) .p-seq__dot { transition-delay: 80ms; }
.p-seq.is-exploded .p-seq__point:nth-child(2) .p-seq__wire { transition-delay: 220ms; }
.p-seq.is-exploded .p-seq__point:nth-child(2) .p-seq__card { transition-delay: 380ms; }
.p-seq.is-exploded .p-seq__point:nth-child(3) .p-seq__dot { transition-delay: 160ms; }
.p-seq.is-exploded .p-seq__point:nth-child(3) .p-seq__wire { transition-delay: 300ms; }
.p-seq.is-exploded .p-seq__point:nth-child(3) .p-seq__card { transition-delay: 460ms; }
.p-seq.is-exploded .p-seq__point:nth-child(4) .p-seq__dot { transition-delay: 240ms; }
.p-seq.is-exploded .p-seq__point:nth-child(4) .p-seq__wire { transition-delay: 380ms; }
.p-seq.is-exploded .p-seq__point:nth-child(4) .p-seq__card { transition-delay: 540ms; }

a.p-seq__pin:hover .p-seq__card {
	background: rgba(255, 255, 255, 0.24);
	border-color: rgba(255, 255, 255, 0.5);
}

a.p-seq__pin:hover .p-seq__dot {
	box-shadow:
		0 0 0 2px rgba(255, 255, 255, 0.7),
		0 0 22px 6px rgba(255, 255, 255, 0.75);
}

a.p-seq__pin:focus-visible .p-seq__card {
	outline: 2px solid #fff;
	outline-offset: 3px;
}

.p-seq__point.is-soon .p-seq__card {
	opacity: 0.5;
}

.p-seq__point.is-soon .p-seq__pin {
	cursor: default;
}

.p-seq.is-exploded .p-seq__point.is-soon .p-seq__card {
	opacity: 0.5;
}

/* Small screens: the cards would collide with the plant, so they tuck in and
   drop their secondary line. */
@media (max-width: 767px) {
	.p-seq__point--right { left: var(--x, 60%); }
	.p-seq__point--left { right: calc(100% - var(--x, 44%)); }

	.p-seq__wire {
		width: clamp(24px, 7vw, 54px);
	}

	.p-seq__card {
		padding: 0.4rem 0.6rem;
		border-radius: 14px;
	}

	.p-seq__labelnote {
		display: none;
	}

	.p-seq__labeltext {
		font-size: var(--p-text-micro);
	}
}

/* ---- Header over the stage --------------------------------------------- */

/*
 * White links over the green. There is no bar: the header is transparent
 * everywhere and hides itself until reached for — see .p-header in
 * components.css.
 */
.p-body--immersive .p-header:not(.is-onlight) .p-nav__link,
.p-body--immersive .p-header:not(.is-onlight) .p-iconbtn,
.p-body--immersive .p-header:not(.is-onlight) .p-header__burger {
	color: #fff;
}

.p-body--immersive .p-header:not(.is-onlight) .p-nav__link::after {
	background: #fff;
}

@media (prefers-reduced-motion: reduce) {
	.p-seq__track {
		height: auto;
	}

	.p-seq__stage {
		position: static;
		height: auto;
		padding-block: var(--p-section-y);
	}

	.p-seq__figure {
		transform: none;
		transition: none;
	}

	.p-seq__cueline,
	.p-seq__dot::after {
		animation: none;
	}

	.p-seq__dot,
	.p-seq__wire,
	.p-seq__card {
		opacity: 1;
		transform: none;
		transition: none;
	}
}
