/*
 * Page morphs (D-017, D-019, D-022). Without cross-document view transitions this is a
 * normal navigation. The head script (src/scripts/transitions.js) adds the direction
 * types and names the home window on the other side "station" and its heading
 * "station-name".
 *
 * Contract for station builders (keep it when restyling):
 * - the window root keeps id="<slug>" and its heading keeps id="<slug>-name": that
 *   heading morphs into the h1;
 * - don't set view-transition-name "station", "station-name" or "dial" on anything.
 */

/* Ungated: browsers without it ignore the at-rule. */
@view-transition {
	navigation: auto;
}

@layer chassis.transitions {
	/* Every page swap: old page out, a static frame, new page in; never two pages at once. */
	:root {
		--vt-out: 160ms;
		--vt-gap: 120ms;
		--vt-in: 220ms;
		--vt-at: calc(var(--vt-out) + var(--vt-gap));
		/* The new header waits for the moving title, so it never lands on the tagline. */
		--vt-arrive: var(--vt-at);
		--vt-ease-out: cubic-bezier(0.4, 0, 1, 1);
		--vt-ease-in: cubic-bezier(0, 0, 0.2, 1);
		--vt-static: var(--grain), oklch(46% 0 0);
	}

	@media (width < 40rem) {
		:root {
			--vt-arrive: 360ms;
		}
	}

	@media (prefers-reduced-motion: no-preference) {
		/* Morph targets on station pages; unnamed on station-to-station swaps. */
		#station-header {
			view-transition-name: station;
		}

		#station-header h1 {
			view-transition-name: station-name;
		}

		nav.dial {
			view-transition-name: dial;
		}

		/* The frame: whatever no snapshot covers is static. */
		::view-transition {
			background: var(--vt-static);
		}

		/* A tuner snaps: the new dial is simply there. */
		::view-transition-group(dial),
		::view-transition-new(dial) {
			animation: none;
		}

		::view-transition-old(dial),
		::view-transition-old(station-name) {
			animation: none;
			opacity: 0;
		}

		/* One title that moves and resizes, drawn from the new page only (N2a). */
		::view-transition-group(station-name) {
			animation-duration: var(--st-dur, 420ms);
			animation-timing-function: var(--st-ease, cubic-bezier(0.2, 0, 0, 1));
		}

		::view-transition-new(station-name) {
			animation: none;
		}

		@supports (view-transition-class: station) {
			#station-header {
				view-transition-class: station;
			}

			::view-transition-group(.station) {
				animation-duration: var(--st-dur, 420ms);
				animation-timing-function: var(--st-ease, cubic-bezier(0.2, 0, 0, 1));
			}

			::view-transition-old(.station) {
				animation: var(--vt-out) var(--vt-ease-out) both vt-fade-out;
			}

			::view-transition-new(.station) {
				animation: var(--vt-in) var(--vt-ease-in) var(--vt-arrive) both
					vt-fade-in;
			}
		}

		/* Untyped fallback is the default root crossfade. */
		@supports selector(:active-view-transition-type(x)) {
			/* Home → station cuts the band around the window to static at once. */
			html:active-view-transition-type(to-station)::view-transition-old(root) {
				animation: none;
				opacity: 0;
			}

			html:active-view-transition-type(to-home) {
				/* Home's ground shows through the window's hole: make it static, not black. */
				background: var(--vt-static);

				&::view-transition-old(root) {
					animation: var(--vt-out) var(--vt-ease-out) both vt-fade-out;
				}
			}

			html:active-view-transition-type(
					to-station,
					to-home
				)::view-transition-new(root) {
				animation: var(--vt-in) var(--vt-ease-in) var(--vt-at) both vt-fade-in;
			}

			/* Station → station. Higher frequency moves the page left, lower right. */
			html:active-view-transition-type(forward) {
				&::view-transition-old(root) {
					animation: var(--vt-out) var(--vt-ease-out) both vt-out-left;
				}

				&::view-transition-new(root) {
					animation: var(--vt-in) var(--vt-ease-in) var(--vt-at) both
						vt-in-right;
				}
			}

			html:active-view-transition-type(backward) {
				&::view-transition-old(root) {
					animation: var(--vt-out) var(--vt-ease-out) both vt-out-right;
				}

				&::view-transition-new(root) {
					animation: var(--vt-in) var(--vt-ease-in) var(--vt-at) both vt-in-left;
				}
			}
		}
	}

	/* Reduced motion: no names, no types, no frame; a short crossfade of the whole page. */
	@media (prefers-reduced-motion: reduce) {
		::view-transition-group(*),
		::view-transition-old(*),
		::view-transition-new(*) {
			animation-duration: 150ms;
		}
	}

	@keyframes vt-fade-out {
		to {
			opacity: 0;
		}
	}

	@keyframes vt-fade-in {
		from {
			opacity: 0;
		}
	}

	@keyframes vt-out-left {
		to {
			opacity: 0;
			translate: -6vw 0;
		}
	}

	@keyframes vt-in-right {
		from {
			opacity: 0;
			translate: 6vw 0;
		}
	}

	@keyframes vt-out-right {
		to {
			opacity: 0;
			translate: 6vw 0;
		}
	}

	@keyframes vt-in-left {
		from {
			opacity: 0;
			translate: -6vw 0;
		}
	}
}
