/*
 * cinematic.css — Phase 2A cinematic opening prototype.
 *
 * Placeholders only: CSS gradients and an abstract marker stand in for
 * future footage. Nothing here depicts or redesigns the Blue Bird.
 *
 * Loaded on the front page only (see functions.php).
 *
 * How the pieces fit:
 *   html.bb-cine-play    stage is showing (set pre-paint by the inline
 *                        head script, or by the controller on replay)
 *   html.bb-cine-reveal  film finished/skipped: hero reveal is running
 *   html.bb-cine-quick   reveal is fade-only (skip and reduced motion)
 *   .bb-stage.is-running film animations are live; the controller sets the
 *                        per-scene timing custom properties first
 *   .bb-r / .bb-l        reveal items / typed title letters
 *
 * Scene timing (--s, --e, --d, --s-<id>, --d-<id>, --a-<id>) is written by
 * assets/js/cinematic.js from assets/cinematic/manifest.json. Scenes absent
 * from the active profile get --a-<id>: none and the [hidden] attribute.
 */

/* ------------------------------------------------------------------ Stage */

.bb-sprite {
	position: absolute;
	width: 0;
	height: 0;
	overflow: hidden;
}

.bb-stage {
	--bb-charcoal: #1b1d23;
	--bb-graphite: #2a2d36;
	--bb-slate: #4a5261;
	--bb-violet: #2c1a4a;
	--bb-purple: #4b2b80;
	--bb-wine: #5b2438;
	--bb-amber: 231, 169, 74;
	--bird: clamp(9rem, 26vmin, 17rem);
	--fade: 400ms;

	position: fixed;
	inset: 0;
	z-index: 99990;
	display: none;
	overflow: hidden;
	color: var(--wp--preset--color--white);
}

.bb-stage [hidden] {
	display: none !important;
}

html.bb-cine-play {
	overflow: hidden;
}

html.bb-cine-play .bb-stage {
	display: block;
}

.bb-stage__scenes {
	position: absolute;
	inset: 0;
	background: var(--bb-charcoal);
}

.bb-stage__center {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	pointer-events: none;
}

.bb-stage__controls {
	position: absolute;
	right: clamp(1rem, 3vw, 2.5rem);
	bottom: clamp(1rem, 3vw, 2.25rem);
	z-index: 2;
}

/* ----------------------------------------------------------------- Scenes */

.bb-scene {
	position: absolute;
	inset: 0;
	overflow: hidden;
	opacity: 0;
}

.bb-stage.is-running .bb-scene {
	animation:
		bb-in var(--fade) ease-out var(--s, 0ms) both,
		bb-out var(--fade) ease-in var(--e, 0ms) forwards;
}

/* The last scene never fades out: it matches the hero background. */
.bb-stage.is-running .bb-scene--logo {
	animation: bb-in var(--fade) ease-out var(--s, 0ms) both;
}

/* Real media layers are appended by the controller above the placeholder. */
.bb-scene .bb-layer {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	background: transparent;
}

/* Desktop-only Three.js storm canvas (see assets/js/three-storm.js). Sits
 * between the breakthrough and sky scenes in DOM order, so it paints over
 * the storm/struggle/determination/breakthrough CSS backgrounds while they
 * are the active scenes, and is naturally hidden behind sky and later
 * scenes once the controller hides it. Never present unless WebGL succeeded. */
.bb-three-canvas {
	position: absolute;
	inset: 0;
	display: none;
	width: 100%;
	height: 100%;
}

.bb-three-canvas.is-active {
	display: block;
}

/* While the WebGL storm is active, the CSS storm animations underneath
 * would otherwise keep running unseen; pausing them is a small performance
 * courtesy, not a visual requirement (the canvas already fully covers them). */
.bb-stage--three .bb-scene--storm::before,
.bb-stage--three .bb-scene--struggle::before,
.bb-stage--three .bb-scene--determination::before,
.bb-stage--three .bb-scene--storm::after,
.bb-stage--three .bb-scene--struggle::after,
.bb-stage--three .bb-scene--determination::after,
.bb-stage--three .bb-scene--breakthrough::before,
.bb-stage--three .bb-scene--breakthrough::after {
	animation-play-state: paused;
}

.bb-scene.has-media::before {
	display: none;
}

/* Storm, struggle, determination: charcoal, graphite, violet, wine, slate. */
.bb-scene--storm {
	--lx: 70%;
	background: linear-gradient(180deg, var(--bb-charcoal) 0%, var(--bb-graphite) 55%, #2b2130 100%);
}

.bb-scene--struggle {
	--lx: 28%;
	background: linear-gradient(180deg, #15161c 0%, #26232e 55%, #3a1f2f 100%);
}

.bb-scene--determination {
	--lx: 60%;
	background: linear-gradient(180deg, #1a1626 0%, #33224a 62%, #6a4a3a 100%);
}

.bb-scene--storm::before,
.bb-scene--struggle::before,
.bb-scene--determination::before {
	content: "";
	position: absolute;
	inset: -15% -25%;
	background:
		radial-gradient(60% 40% at 20% 15%, rgba(74, 82, 97, 0.4), transparent 72%),
		radial-gradient(55% 35% at 82% 18%, rgba(43, 33, 48, 0.5), transparent 74%),
		radial-gradient(48% 32% at 28% 52%, rgba(75, 43, 128, 0.55), transparent 70%),
		radial-gradient(44% 30% at 76% 60%, rgba(91, 36, 56, 0.5), transparent 70%),
		radial-gradient(56% 34% at 50% 92%, rgba(74, 82, 97, 0.55), transparent 70%),
		radial-gradient(120% 85% at 50% 50%, transparent 52%, rgba(0, 0, 0, 0.4) 100%);
}

/* Slow, weighted drift: eased rather than linear, smaller excursions so the
 * clouds feel heavy and atmospheric rather than sliding on a track. */
.bb-stage.is-running .bb-scene--storm::before,
.bb-stage.is-running .bb-scene--determination::before {
	animation: bb-drift calc(var(--d, 2000ms) + var(--fade)) ease-in-out var(--s, 0ms) both;
}

.bb-stage.is-running .bb-scene--struggle::before {
	animation: bb-drift-strong calc(var(--d, 2000ms) + var(--fade)) ease-in-out var(--s, 0ms) both;
}

/* Subtle amber lightning: one low-luminance double flicker per scene,
 * well under the three-flashes-per-second threshold (WCAG 2.3.1). */
.bb-scene--storm::after,
.bb-scene--struggle::after,
.bb-scene--determination::after {
	content: "";
	position: absolute;
	inset: 0;
	opacity: 0;
	background:
		linear-gradient(105deg, transparent calc(var(--lx) - 1%), rgba(255, 244, 214, 0.85) calc(var(--lx) - 0.25%), rgba(var(--bb-amber), 0.8) var(--lx), transparent calc(var(--lx) + 1%)),
		radial-gradient(38% 46% at var(--lx) 18%, rgba(var(--bb-amber), 0.5), transparent 72%);
}

/* One restrained strike per scene (well under 3 flashes/sec at low luminance,
 * per WCAG 2.3.1), timed to land after the clouds have had a moment to read. */
.bb-stage.is-running .bb-scene--storm::after,
.bb-stage.is-running .bb-scene--struggle::after,
.bb-stage.is-running .bb-scene--determination::after {
	animation: bb-flash 2.6s linear calc(var(--s, 0ms) + 900ms) 1 both;
}

/* Breakthrough: violet, then warm gold, then clean blue. */
.bb-scene--breakthrough {
	background: var(--bb-violet);
}

.bb-scene--breakthrough::before {
	content: "";
	position: absolute;
	top: 0;
	right: 0;
	left: 0;
	height: 300%;
	background: linear-gradient(
		180deg,
		var(--bb-purple) 0%,
		var(--bb-violet) 18%,
		var(--bb-wine) 30%,
		var(--wp--preset--color--champagne-gold) 42%,
		#f6e6c1 55%,
		var(--wp--preset--color--electric-blue) 68%,
		var(--wp--preset--color--electric-blue) 100%
	);
}

.bb-stage.is-running .bb-scene--breakthrough::before {
	animation: bb-rise calc(var(--d, 1500ms) + var(--fade)) ease-in-out var(--s, 0ms) both;
}

/* Dramatic release: a burst of light expands from the centre as the storm
 * gives way, layered above the rising violet-gold-blue band. */
.bb-scene--breakthrough::after {
	content: "";
	position: absolute;
	inset: -40%;
	border-radius: 50%;
	background: radial-gradient(circle, rgba(255, 255, 255, 0.9) 0%, rgba(216, 184, 120, 0.55) 30%, rgba(47, 124, 255, 0) 70%);
	opacity: 0;
}

.bb-stage.is-running .bb-scene--breakthrough::after {
	animation: bb-burst calc(var(--d, 1500ms) + var(--fade)) cubic-bezier(.2, .7, .2, 1) var(--s, 0ms) both;
}

/* Open sky, world, flight, banking, landing: blue, white, champagne. */
.bb-scene--sky {
	background: linear-gradient(180deg, var(--wp--preset--color--electric-blue) 0%, #a9c9ff 50%, #ffffff 80%, #f2e2bd 100%);
}

.bb-scene--world {
	background:
		radial-gradient(70% 45% at 50% 108%, rgba(216, 184, 120, 0.85), transparent 70%),
		linear-gradient(180deg, #6fa5ff 0%, #cfe0ff 60%, #ffffff 100%);
}

.bb-scene--world::before {
	content: "";
	position: absolute;
	right: -30%;
	bottom: -72%;
	left: -30%;
	height: 100%;
	border-top: 2px solid rgba(255, 255, 255, 0.7);
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.35);
}

.bb-stage.is-running .bb-scene--world::before {
	animation: bb-zoom calc(var(--d, 1000ms) + var(--fade)) cubic-bezier(.16, 1, .3, 1) var(--s, 0ms) both;
}

.bb-scene--flight {
	background: linear-gradient(180deg, #5b96ff 0%, #bcd6ff 55%, #ffffff 100%);
}

.bb-scene--flight::before {
	content: "";
	position: absolute;
	inset: 0 -50%;
	background:
		linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.7), transparent) 12% 22% / 22% 2px no-repeat,
		linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.6), transparent) 55% 41% / 30% 2px no-repeat,
		linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.65), transparent) 30% 68% / 26% 2px no-repeat;
}

.bb-stage.is-running .bb-scene--flight::before {
	animation: bb-streak calc(var(--d, 1000ms) + var(--fade)) linear var(--s, 0ms) both;
}

.bb-scene--banking {
	background: linear-gradient(180deg, #4f8dff 0%, #b9d3ff 50%, #ffffff 100%);
}

.bb-scene--banking::before {
	content: "";
	position: absolute;
	inset: -25%;
	background: linear-gradient(180deg, transparent 48%, rgba(255, 255, 255, 0.75) 50%, #ffffff 52%);
}

.bb-stage.is-running .bb-scene--banking::before {
	animation: bb-tilt calc(var(--d, 750ms) + var(--fade)) ease-in-out var(--s, 0ms) both;
}

.bb-scene--landing {
	background: linear-gradient(180deg, #cfe0ff 0%, #f4f8ff 55%, #ffffff 100%);
}

/* Logo scene = hero background, so the reveal is seamless. */
.bb-scene--logo {
	background: linear-gradient(180deg, var(--wp--preset--color--white) 0%, var(--wp--preset--color--light-neutral) 100%);
}

/* ------------------------------------------- Bird placeholder (abstract) */

.bb-mk-lower {
	fill: var(--wp--preset--color--cobalt-blue);
}

.bb-mk-upper {
	fill: var(--wp--preset--color--electric-blue);
}

.bb-mk-accent {
	stroke: var(--wp--preset--color--champagne-gold);
	stroke-width: 3;
	stroke-linecap: round;
}

.bb-mark-svg {
	display: block;
	width: 100%;
	height: 100%;
}

.bb-bird {
	position: absolute;
	top: 50%;
	left: 50%;
	width: var(--bird);
	height: var(--bird);
	margin: calc(var(--bird) / -2) 0 0 calc(var(--bird) / -2);
	opacity: 0;
}

/* One pose animation per scene, forwards-fill only, so the latest active
 * scene always wins. --a-<id> is set to "none" for scenes absent from the
 * active profile. */
.bb-stage.is-running .bb-bird {
	opacity: 1;
	will-change: transform, opacity;
	animation:
		var(--a-storm, bb-p-storm) var(--d-storm, 1ms) ease-in-out var(--s-storm, 0ms) forwards,
		var(--a-struggle, bb-p-struggle) var(--d-struggle, 1ms) ease-in-out var(--s-struggle, 0ms) forwards,
		var(--a-determination, bb-p-determination) var(--d-determination, 1ms) ease-in-out var(--s-determination, 0ms) forwards,
		var(--a-breakthrough, bb-p-breakthrough) var(--d-breakthrough, 1ms) ease-in-out var(--s-breakthrough, 0ms) forwards,
		var(--a-sky, bb-p-sky) var(--d-sky, 1ms) ease-in-out var(--s-sky, 0ms) forwards,
		var(--a-world, bb-p-world) var(--d-world, 1ms) ease-in-out var(--s-world, 0ms) forwards,
		var(--a-flight, bb-p-flight) var(--d-flight, 1ms) ease-in-out var(--s-flight, 0ms) forwards,
		var(--a-banking, bb-p-banking) var(--d-banking, 1ms) ease-in-out var(--s-banking, 0ms) forwards,
		var(--a-landing, bb-p-landing) var(--d-landing, 1ms) ease-in-out var(--s-landing, 0ms) forwards,
		var(--a-logo, bb-p-logo) var(--d-logo, 1ms) ease-in-out var(--s-logo, 0ms) forwards;
}

/* Compact profile merges scenes, so three poses cover a longer path. */
.bb-stage[data-profile="compact"] {
	--a-struggle: bb-p-struggle-c;
	--a-sky: bb-p-sky-c;
	--a-flight: bb-p-flight-c;
}

/* --------------------------------------------------------------- Lockup */

.bb-lockup {
	display: inline-flex;
	align-items: center;
	gap: 0.85em;
	font-family: var(--wp--preset--font-family--manrope);
	font-size: var(--lk, 1rem);
	color: var(--wp--preset--color--deep-navy);
	transform-origin: 0 0;
}

.bb-mark {
	display: block;
	flex: none;
	width: 3.2em;
	height: 3.2em;
}

.bb-mark img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: contain;
}

.bb-wordmark {
	font-size: 1em;
	font-weight: 800;
	line-height: 1.1;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

.bb-wordmark > span {
	display: block;
}

.bb-wordmark img {
	display: block;
	height: 3.2em;
	width: auto;
}

.bb-lockup--stage {
	--lk: clamp(1.15rem, 3.4vmin, 2rem);

	opacity: 0;
}

.bb-lockup--slot {
	--lk: 1.05rem;
}

.bb-stage.is-running .bb-lockup--stage {
	animation: bb-fade calc(var(--d-logo, 1000ms) * 0.6) ease-out calc(var(--s-logo, 0ms) + var(--d-logo, 1000ms) * 0.25) both;
}

/* -------------------------------------------------------------- Controls */

.bb-skip {
	min-height: 44px;
	padding: 0.8rem 1.25rem;
	border: 1px solid rgba(255, 255, 255, 0.55);
	border-radius: 999px;
	background: rgba(7, 20, 38, 0.82);
	color: var(--wp--preset--color--white);
	font: 600 0.875rem/1 var(--wp--preset--font-family--manrope);
	letter-spacing: 0.04em;
	cursor: pointer;
}

.bb-skip:hover {
	background: var(--wp--preset--color--cobalt-blue);
}

/* White ring inside a navy ring: visible on both dark and light scenes. */
.bb-skip:focus-visible {
	outline: 3px solid var(--wp--preset--color--white);
	outline-offset: 2px;
	box-shadow: 0 0 0 6px var(--wp--preset--color--deep-navy);
}

html.bb-cine-reveal .bb-stage__controls {
	visibility: hidden;
}

/* Skip needs JS: never show a dead button if the controller has not started. */
html:not(.bb-cine-live) .bb-skip {
	display: none;
}

/* ------------------------------------------------------- Hero (minimal) */

.bb-page {
	display: flex;
	flex-direction: column;
	min-height: 100vh;
	min-height: 100svh;
	background: linear-gradient(180deg, var(--wp--preset--color--white) 0%, var(--wp--preset--color--light-neutral) 100%);
	color: var(--wp--preset--color--deep-navy);
}

.bb-hero__bar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 2rem;
	padding: clamp(1.25rem, 3vw, 2.25rem) clamp(1.25rem, 5vw, 4rem);
}

/* Reserved: the future navigation mounts here and reuses .bb-r--nav. */
.bb-nav-hook {
	min-width: 1px;
	min-height: 2.5rem;
}

.bb-hero {
	display: flex;
	flex: 1;
	flex-direction: column;
	justify-content: center;
	width: 100%;
	max-width: 90rem;
	margin: 0 auto;
	padding: clamp(1.5rem, 5vw, 4rem) clamp(1.25rem, 5vw, 4rem) clamp(3rem, 8vw, 6rem);
}

.bb-hero__title {
	position: relative;
	margin: 0;
	color: var(--wp--preset--color--deep-navy);
	font-size: clamp(2.25rem, 10.5vw, 9rem);
	font-weight: 800;
	line-height: 0.95;
	letter-spacing: -0.035em;
}

.bb-sr {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	border: 0;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
}

.bb-hero__lede {
	max-width: 36rem;
	margin: clamp(1.5rem, 3vw, 2.5rem) 0 0;
	font-size: clamp(1.05rem, 1.5vw, 1.3rem);
	line-height: 1.55;
}

.bb-hero .bb-cta {
	display: flex;
	flex-wrap: wrap;
	gap: 1rem;
	margin-top: clamp(1.75rem, 3vw, 2.75rem);
}

.bb-cta .wp-block-button__link {
	padding: 0.95rem 1.75rem;
	border: 2px solid var(--wp--preset--color--cobalt-blue);
	border-radius: 999px;
	font-size: 1rem;
	font-weight: 700;
	line-height: 1.2;
	text-decoration: none;
	transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.bb-btn--primary .wp-block-button__link {
	background: var(--wp--preset--color--cobalt-blue);
	color: var(--wp--preset--color--white);
}

.bb-btn--primary .wp-block-button__link:hover {
	border-color: var(--wp--preset--color--deep-navy);
	background: var(--wp--preset--color--deep-navy);
}

.bb-btn--secondary .wp-block-button__link {
	border-color: var(--wp--preset--color--deep-navy);
	background: transparent;
	color: var(--wp--preset--color--deep-navy);
}

.bb-btn--secondary .wp-block-button__link:hover {
	background: var(--wp--preset--color--deep-navy);
	color: var(--wp--preset--color--white);
}

.bb-cta .wp-block-button__link:focus-visible,
.bb-replay:focus-visible {
	outline: 3px solid var(--wp--preset--color--deep-navy);
	outline-offset: 3px;
}

.bb-replay {
	align-self: flex-start;
	margin-top: clamp(2rem, 4vw, 3rem);
	padding: 0.5rem 0;
	border: 0;
	background: none;
	color: var(--wp--preset--color--deep-navy);
	font: 600 0.875rem/1.2 var(--wp--preset--font-family--manrope);
	text-decoration: underline;
	text-underline-offset: 0.25em;
	cursor: pointer;
}

/* Replay needs JS; hide it when the controller has not started. */
html:not(.bb-cine-live) .bb-replay {
	display: none;
}

/* --------------------------------------------------------------- Reveal */

/* Hidden while the stage plays; without the play class everything is
 * visible, which is the no-JS, already-seen and reduced-motion state. */
html.bb-cine-play .bb-r,
html.bb-cine-play .bb-l {
	opacity: 0;
}

html.bb-cine-reveal .bb-r {
	animation: bb-fade-up calc(500ms * var(--rv, 1)) ease-out var(--rd, 0ms) both;
}

html.bb-cine-reveal .bb-r--lockup {
	--rd: var(--flip, 0ms);

	animation: bb-fade 60ms linear var(--flip, 0ms) both;
}

html.bb-cine-reveal .bb-r--nav {
	--rd: calc(var(--flip, 0ms) + 100ms * var(--rv, 1));
}

html.bb-cine-reveal .bb-r--lede {
	--rd: calc(var(--flip, 0ms) + 1200ms * var(--rv, 1));
}

html.bb-cine-reveal .bb-r--cta {
	--rd: calc(var(--flip, 0ms) + 1500ms * var(--rv, 1));
}

html.bb-cine-reveal .bb-r--replay {
	--rd: calc(var(--flip, 0ms) + 1900ms * var(--rv, 1));
}

/* Title typing: one letter at a time; --i is set by the controller. */
html.bb-cine-reveal .bb-l {
	animation: bb-fade 40ms linear calc(var(--flip, 0ms) + 100ms * var(--rv, 1) + var(--i, 0) * 55ms * var(--rv, 1)) both;
}

/* Hand-off: the stage fades out behind the travelling lockup. */
html.bb-cine-reveal .bb-stage {
	pointer-events: none;
}

html.bb-cine-reveal:not(.bb-cine-quick) .bb-stage__scenes {
	animation: bb-fade-out calc(var(--flip, 0ms) * 0.6) ease-out calc(var(--flip, 0ms) * 0.2) forwards;
}

/* Quick reveal (skip and reduced motion): opacity only, no travel, no typing. */
html.bb-cine-quick .bb-stage {
	animation: bb-fade-out calc(600ms * var(--rv, 1)) ease-out forwards;
}

html.bb-cine-quick .bb-r {
	animation-name: bb-fade;
}

html.bb-cine-quick .bb-r--lockup {
	animation-duration: calc(500ms * var(--rv, 1));
}

html.bb-cine-quick .bb-l {
	animation-duration: calc(500ms * var(--rv, 1));
	animation-delay: calc(var(--flip, 0ms) + 100ms * var(--rv, 1));
}

/* ------------------------------------------- Reduced-motion film variant */

/* Crossfade only: no bird, no drift, no streaks, no tilt, no lightning. */
.bb-stage[data-profile="reduced"] .bb-bird,
.bb-stage[data-profile="reduced"] .bb-scene::after {
	display: none;
}

.bb-stage[data-profile="reduced"] .bb-scene::before {
	animation: none;
}

.bb-stage[data-profile="reduced"] .bb-scene--breakthrough::before {
	transform: translateY(-33%);
}

@media (prefers-reduced-motion: reduce) {
	.bb-cta .wp-block-button__link {
		transition: none;
	}
}

/* ------------------------------------------------------------ Keyframes */

@keyframes bb-in {
	from { opacity: 0; }
	to { opacity: 1; }
}

@keyframes bb-out {
	from { opacity: 1; }
	to { opacity: 0; }
}

@keyframes bb-fade {
	from { opacity: 0; }
	to { opacity: 1; }
}

@keyframes bb-fade-out {
	from { opacity: 1; }
	to { opacity: 0; }
}

@keyframes bb-fade-up {
	from { opacity: 0; transform: translateY(0.75rem); }
	to { opacity: 1; transform: none; }
}

@keyframes bb-drift {
	from { transform: translate3d(-4%, 0, 0); }
	to { transform: translate3d(4%, 0, 0); }
}

@keyframes bb-drift-strong {
	from { transform: translate3d(-8%, 0, 0); }
	to { transform: translate3d(8%, 0, 0); }
}

@keyframes bb-flash {
	0% { opacity: 0; }
	9% { opacity: 0.11; }
	13% { opacity: 0.02; }
	18% { opacity: 0.07; }
	26%,
	100% { opacity: 0; }
}

@keyframes bb-rise {
	from { transform: translateY(0); }
	to { transform: translateY(-66.6667%); }
}

@keyframes bb-burst {
	0% { transform: scale(0.15); opacity: 0; }
	35% { transform: scale(0.55); opacity: 0.85; }
	100% { transform: scale(2.2); opacity: 0; }
}

@keyframes bb-zoom {
	from { transform: translateY(6%) scale(1); }
	to { transform: translateY(0) scale(1.08); }
}

@keyframes bb-streak {
	from { transform: translateX(-25%); }
	to { transform: translateX(0); }
}

@keyframes bb-tilt {
	from { transform: rotate(-8deg); }
	to { transform: rotate(0deg); }
}

/* Bird poses: translate (from centre), scale (of --bird), rotate. Each
 * scene's end pose equals the next scene's start pose. */
@keyframes bb-p-storm {
	from { transform: translate(28vw, 6vh) scale(0.1) rotate(-6deg); }
	to { transform: translate(24vw, 8vh) scale(0.13) rotate(-4deg); }
}

/* Slow, weighted flight against the wind: two broad, eased sweeps rather
 * than a fast multi-point zigzag. Each stop carries its own easing so the
 * bird visibly gathers and sheds momentum instead of moving at one constant
 * rate (a "loading spinner" reads as constant-speed, evenly-spaced motion). */
@keyframes bb-p-struggle {
	0% { transform: translate(24vw, 8vh) scale(0.13) rotate(-4deg); animation-timing-function: cubic-bezier(.45, 0, .2, 1); }
	42% { transform: translate(13vw, 11vh) scale(0.24) rotate(-11deg); animation-timing-function: cubic-bezier(.45, 0, .2, 1); }
	100% { transform: translate(4vw, 8vh) scale(0.38) rotate(-12deg); }
}

@keyframes bb-p-determination {
	0% { transform: translate(4vw, 8vh) scale(0.38) rotate(-12deg); animation-timing-function: cubic-bezier(.45, 0, .2, 1); }
	100% { transform: translate(2vw, 4vh) scale(0.62) rotate(-24deg); }
}

@keyframes bb-p-breakthrough {
	from { transform: translate(2vw, 4vh) scale(0.62) rotate(-24deg); }
	to { transform: translate(0, -16vh) scale(0.78) rotate(-38deg); }
}

@keyframes bb-p-sky {
	from { transform: translate(0, -16vh) scale(0.78) rotate(-38deg); }
	to { transform: translate(6vw, -14vh) scale(0.7) rotate(-20deg); }
}

@keyframes bb-p-world {
	from { transform: translate(6vw, -14vh) scale(0.7) rotate(-20deg); }
	to { transform: translate(-10vw, -8vh) scale(0.5) rotate(-6deg); }
}

@keyframes bb-p-flight {
	from { transform: translate(-10vw, -8vh) scale(0.5) rotate(-6deg); }
	to { transform: translate(16vw, -6vh) scale(0.55) rotate(0deg); }
}

@keyframes bb-p-banking {
	from { transform: translate(16vw, -6vh) scale(0.55) rotate(0deg); }
	to { transform: translate(8vw, 4vh) scale(0.65) rotate(18deg); }
}

@keyframes bb-p-landing {
	from { transform: translate(8vw, 4vh) scale(0.65) rotate(18deg); }
	to { transform: translate(0, 2vh) scale(0.75) rotate(-8deg); }
}

/* Logo transformation: the marker settles onto the lockup's mark position
 * (--mark-x/y/s are measured by the controller) and fades out as the
 * lockup fades in. */
@keyframes bb-p-logo {
	from { transform: translate(0, 2vh) scale(0.75) rotate(-8deg); opacity: 1; }
	70% { opacity: 1; }
	to { transform: translate(var(--mark-x, 0px), var(--mark-y, 0px)) scale(var(--mark-s, 0.4)) rotate(0deg); opacity: 0; }
}

/* Compact profile variants (merged scenes). */
@keyframes bb-p-struggle-c {
	0% { transform: translate(24vw, 8vh) scale(0.13) rotate(-4deg); animation-timing-function: cubic-bezier(.45, 0, .2, 1); }
	35% { transform: translate(14vw, 11vh) scale(0.22) rotate(-10deg); animation-timing-function: cubic-bezier(.45, 0, .2, 1); }
	68% { transform: translate(7vw, 6vh) scale(0.34) rotate(-2deg); animation-timing-function: cubic-bezier(.45, 0, .2, 1); }
	100% { transform: translate(2vw, 4vh) scale(0.62) rotate(-24deg); }
}

@keyframes bb-p-sky-c {
	from { transform: translate(0, -16vh) scale(0.78) rotate(-38deg); }
	to { transform: translate(-10vw, -8vh) scale(0.5) rotate(-6deg); }
}

@keyframes bb-p-flight-c {
	0% { transform: translate(-10vw, -8vh) scale(0.5) rotate(-6deg); }
	45% { transform: translate(16vw, -6vh) scale(0.55) rotate(0deg); }
	70% { transform: translate(9vw, 3vh) scale(0.65) rotate(18deg); }
	100% { transform: translate(0, 2vh) scale(0.75) rotate(-8deg); }
}


/* ------------------------------------------------ Bird character (Phase 2B)
 * The .bb-bird box keeps its existing flight path and logo hand-off; only its
 * artwork changes: a flapping cut-out rig (storm -> breakthrough), the
 * side-view glide (sky -> landing), the perched pose (landing), then the
 * original mark fades back in to become the logo. Reduced profile still
 * hides .bb-bird entirely (rule above). */
.bb-rig,
.bb-pose {
	position: absolute;
	top: 50%;
	left: 50%;
	opacity: 0;
	pointer-events: none;
	transform: translate(-50%, -50%);
}
.bb-rig { width: 260%; aspect-ratio: 955 / 606; }
.bb-rig img { position: absolute; inset: 0; width: 100%; height: 100%; }
.bb-pose img { display: block; width: 100%; height: 100%; }
.bb-wing--l { transform-origin: 40.8% 44.9%; }
.bb-wing--r { transform-origin: 54.5% 44.9%; }
.bb-pose--glide { width: 250%; aspect-ratio: 913 / 493; }
.bb-pose--perch { height: 165%; aspect-ratio: 300 / 575; }
.bb-bird.has-rig .bb-mark-svg { opacity: 0; }

.bb-stage.is-running .bb-bird.has-rig .bb-mark-svg {
	animation: bb-on 500ms ease var(--s-logo, 13000ms) forwards;
}
.bb-stage.is-running .bb-rig {
	animation:
		bb-on 250ms ease 0ms forwards,
		bb-buffet 1.3s ease-in-out 0ms infinite,
		bb-off 450ms ease var(--s-sky, 9000ms) forwards;
}
.bb-stage.is-running .bb-wing--l {
	animation:
		bb-flap-l 0.62s ease-in-out 0ms infinite,
		bb-flap-l 0.95s ease-in-out var(--s-breakthrough, 7500ms) infinite;
}
.bb-stage.is-running .bb-wing--r {
	animation:
		bb-flap-r 0.62s ease-in-out 0ms infinite,
		bb-flap-r 0.95s ease-in-out var(--s-breakthrough, 7500ms) infinite;
}
.bb-stage.is-running .bb-pose--glide {
	animation:
		bb-on 450ms ease var(--s-sky, 9000ms) forwards,
		bb-glide 2.4s ease-in-out var(--s-sky, 9000ms) infinite,
		bb-off 450ms ease var(--s-landing, var(--s-logo, 13000ms)) forwards;
}
.bb-stage.is-running .bb-pose--perch {
	animation:
		bb-on 450ms ease var(--s-landing, var(--s-logo, 13000ms)) forwards,
		bb-off 600ms ease var(--s-logo, 13000ms) forwards;
}

@keyframes bb-on { from { opacity: 0; } to { opacity: 1; } }
@keyframes bb-off { from { opacity: 1; } to { opacity: 0; } }
/* Wind shoves the bird off line: uneven sideways/vertical jolts and tilt. */
@keyframes bb-buffet {
	0%, 100% { transform: translate(-50%, -50%) rotate(0deg); }
	22% { transform: translate(-47%, -53%) rotate(5deg); }
	48% { transform: translate(-53%, -48%) rotate(-7deg); }
	71% { transform: translate(-49%, -52%) rotate(3deg); }
}
/* Forceful down-stroke, slower recovery; right wing mirrors the left. */
@keyframes bb-flap-l {
	0%, 100% { transform: rotate(24deg); }
	40% { transform: rotate(-20deg); }
	55% { transform: rotate(-22deg); }
}
@keyframes bb-flap-r {
	0%, 100% { transform: rotate(-24deg); }
	40% { transform: rotate(20deg); }
	55% { transform: rotate(22deg); }
}
@keyframes bb-glide {
	0%, 100% { transform: translate(-50%, -50%) rotate(0deg); }
	50% { transform: translate(-50%, -54%) rotate(-2deg); }
}
@media (prefers-reduced-motion: reduce) {
	.bb-wing, .bb-rig, .bb-pose--glide { animation-name: none !important; }
}

/* ------------------------------------------ Storm struggle (Stage A, desktop)
 * Desktop-only choreography: the bird is larger and recognisable from the
 * first frame, gusts shove it back and down, it recovers and presses on.
 * Tilt stays within about +/-12deg. Compact and reduced keep their own paths.
 * The sky pose starts where the new breakthrough ends and ends exactly where
 * the original did, so the rest of the film is unchanged. */
.bb-stage[data-profile="desktop"] {
	--a-storm: bb-p-storm-x;
	--a-struggle: bb-p-struggle-x;
	--a-determination: bb-p-determination-x;
	--a-breakthrough: bb-p-breakthrough-x;
	--a-sky: bb-p-sky-x;
}
@keyframes bb-p-storm-x {
	0% { transform: translate(30vw, 12vh) scale(0.26) rotate(-4deg); }
	35% { transform: translate(24vw, 8vh) scale(0.32) rotate(-9deg); animation-timing-function: cubic-bezier(.2, .9, .3, 1); }
	52% { transform: translate(31vw, 15vh) scale(0.3) rotate(8deg); animation-timing-function: cubic-bezier(.5, 0, .3, 1); }
	100% { transform: translate(22vw, 10vh) scale(0.38) rotate(-6deg); }
}
@keyframes bb-p-struggle-x {
	0% { transform: translate(22vw, 10vh) scale(0.38) rotate(-6deg); animation-timing-function: cubic-bezier(.5, 0, .3, 1); }
	26% { transform: translate(14vw, 7vh) scale(0.46) rotate(-10deg); animation-timing-function: cubic-bezier(.2, .9, .3, 1); }
	38% { transform: translate(22vw, 16vh) scale(0.44) rotate(10deg); animation-timing-function: cubic-bezier(.5, 0, .3, 1); }
	60% { transform: translate(12vw, 9vh) scale(0.5) rotate(-8deg); animation-timing-function: cubic-bezier(.2, .9, .3, 1); }
	72% { transform: translate(17vw, 15vh) scale(0.5) rotate(7deg); animation-timing-function: cubic-bezier(.5, 0, .3, 1); }
	100% { transform: translate(6vw, 6vh) scale(0.58) rotate(-9deg); }
}
@keyframes bb-p-determination-x {
	0% { transform: translate(6vw, 6vh) scale(0.58) rotate(-9deg); }
	45% { transform: translate(4vw, 7vh) scale(0.62) rotate(4deg); animation-timing-function: cubic-bezier(.4, 0, .2, 1); }
	100% { transform: translate(0, 2vh) scale(0.7) rotate(-8deg); }
}
@keyframes bb-p-breakthrough-x {
	from { transform: translate(0, 2vh) scale(0.7) rotate(-8deg); }
	to { transform: translate(0, -16vh) scale(0.78) rotate(-12deg); }
}
@keyframes bb-p-sky-x {
	from { transform: translate(0, -16vh) scale(0.78) rotate(-12deg); }
	to { transform: translate(6vw, -14vh) scale(0.7) rotate(-20deg); }
}

/* Rig: short wind shudder on top of the gust path; storm lighting darkens
 * the bird and every lightning strike (same moments as three-storm.js,
 * 9 s storm window) lights it up, easing to full daylight at breakthrough. */
.bb-stage[data-profile="desktop"].is-running .bb-rig {
	animation:
		bb-on 250ms ease 0ms forwards,
		bb-shudder 0.9s ease-in-out 0ms infinite,
		bb-storm-light 9000ms linear 0ms forwards,
		bb-off 450ms ease var(--s-sky, 9000ms) forwards;
}
.bb-stage[data-profile="desktop"].is-running .bb-wing--l {
	animation:
		bb-beat-l 1.45s cubic-bezier(.45, 0, .55, 1) 0ms infinite,
		bb-flap-l 0.95s ease-in-out var(--s-breakthrough, 7500ms) infinite;
}
.bb-stage[data-profile="desktop"].is-running .bb-wing--r {
	animation:
		bb-beat-r 1.45s cubic-bezier(.45, 0, .55, 1) -0.07s infinite,
		bb-flap-r 0.95s ease-in-out var(--s-breakthrough, 7500ms) infinite;
}
@keyframes bb-shudder {
	0%, 100% { transform: translate(-50%, -50%) rotate(0deg); }
	20% { transform: translate(-49%, -51.5%) rotate(3deg); }
	45% { transform: translate(-51.5%, -49%) rotate(-4deg); }
	70% { transform: translate(-49.5%, -50.5%) rotate(2deg); }
}
/* Uneven, effortful beats: a hard power stroke, a weaker one, then a
 * strained hold with wings pinned down against the wind. */
@keyframes bb-beat-l {
	0% { transform: rotate(26deg); }
	13% { transform: rotate(-24deg); }
	30% { transform: rotate(16deg); }
	42% { transform: rotate(-14deg); }
	52% { transform: rotate(-22deg); }
	66% { transform: rotate(-20deg); }
	100% { transform: rotate(26deg); }
}
@keyframes bb-beat-r {
	0% { transform: rotate(-26deg); }
	13% { transform: rotate(24deg); }
	30% { transform: rotate(-16deg); }
	42% { transform: rotate(14deg); }
	52% { transform: rotate(22deg); }
	66% { transform: rotate(20deg); }
	100% { transform: rotate(-26deg); }
}
@keyframes bb-storm-light {
	0%, 5%, 8%, 16%, 19%, 29%, 32%, 41%, 44%, 52%, 56% { filter: brightness(0.72) contrast(1.12) saturate(0.9); }
	6%, 17%, 30%, 42%, 53% { filter: brightness(1.7) contrast(1.05) saturate(1.1); }
	7%, 18%, 31%, 43%, 54% { filter: brightness(1.15) contrast(1.08) saturate(1); }
	70% { filter: brightness(0.85) contrast(1.08) saturate(0.95); }
	88%, 100% { filter: brightness(1.05) contrast(1) saturate(1.05); }
}


/* ------------------------------------------------------ Film mode (video)
 * The Media Library video replaces the built-in scenes. Cover-fit fills the
 * viewport at any aspect ratio without distortion (edges crop on narrow
 * screens). It sits inside .bb-stage__scenes, so the existing hand-off fade
 * and quick-reveal rules apply to it unchanged. */
.bb-film {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: 50% 50%;
	background: var(--bb-charcoal);
}
.bb-stage--film .bb-scene,
.bb-stage--film .bb-bird,
.bb-stage--film .bb-three-canvas,
.bb-stage--film .bb-stage__center {
	display: none !important;
}

/* Closing logo card on tall screens (see startFilm): full frame, letterboxed
 * on the card's own light gradient so the seam is invisible. */
.bb-film {
	transition: opacity 250ms ease;
}
.bb-film.is-endfade {
	opacity: 0;
}
.bb-film.is-endcard {
	object-fit: contain;
	background: linear-gradient(#fafcfe, #e4ecf8);
}
.bb-stage--endcard .bb-stage__scenes {
	background: linear-gradient(#fafcfe, #e4ecf8);
}

/* Sound toggle (film mode): same pill as Skip, icon + label, sits left of it. */
.bb-stage__controls {
	display: flex;
	gap: 0.625rem;
	align-items: center;
}
.bb-sound {
	display: inline-flex;
	gap: 0.5rem;
	align-items: center;
}
.bb-sound svg {
	width: 1.125rem;
	height: 1.125rem;
	flex: none;
}
.bb-sound[aria-pressed="true"] {
	background: var(--wp--preset--color--cobalt-blue);
}
@media (max-width: 480px) {
	.bb-sound span {
		position: absolute;
		width: 1px;
		height: 1px;
		overflow: hidden;
		clip: rect(0 0 0 0);
		white-space: nowrap;
	}
	.bb-sound {
		min-width: 44px;
		justify-content: center;
		padding-inline: 0.75rem;
	}
}

/* Official logo: keep its own proportions (526 x 448) at the lockup height. */
.bb-mark {
	width: 3.76em;
}


/* Sound button v2: action labels ("Tap for sound" / "Mute"), visible on
 * every screen size, a short attention pulse, and a "Sound on" toast. */
.bb-sound .bb-sound__icon {
	font-size: 1rem;
	line-height: 1;
}
@media (max-width: 480px) {
	.bb-sound span {
		position: static;
		width: auto;
		height: auto;
		overflow: visible;
		clip: auto;
	}
	.bb-sound {
		padding-inline: 0.9rem;
	}
}
.bb-sound.is-pulse {
	animation: bb-sound-pulse 1.6s ease-out 600ms 3;
}
@keyframes bb-sound-pulse {
	0% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.55); }
	70% { box-shadow: 0 0 0 14px rgba(255, 255, 255, 0); }
	100% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); }
}
.bb-sound-toast {
	position: absolute;
	top: calc(clamp(1.25rem, 4vh, 2.5rem) + var(--wp-admin--admin-bar--height, 0px));
	left: 50%;
	z-index: 3;
	padding: 0.6rem 1.1rem;
	border-radius: 999px;
	background: rgba(7, 20, 38, 0.82);
	color: var(--wp--preset--color--white);
	font: 600 0.875rem/1 var(--wp--preset--font-family--manrope);
	letter-spacing: 0.04em;
	opacity: 0;
	transform: translate(-50%, -6px);
	transition: opacity 250ms ease, transform 250ms ease;
	pointer-events: none;
}
.bb-sound-toast.is-show {
	opacity: 1;
	transform: translate(-50%, 0);
}
@media (prefers-reduced-motion: reduce) {
	.bb-sound.is-pulse { animation: none; }
}
