/* ==========================================================================
   OVERLAY HEADER, AND HERO BACKGROUND MEDIA
   ==========================================================================

   Written for the Kinetic demo, which has been removed. What is left is
   everything in it that was never demo-specific:

     the overlay header      the 'overlay' header layout, available in every
                             demo from Studio -> Header
     the overlay menu        the full-screen navigation it opens
     the centred hero        the 'centre' hero layout
     hero background media   the frame a background video or embed is
                             painted into

   The three sections it also used to hold — a drag rail, a sideways-scrolling
   pinned section and a drifting photo wall — went with the demo.

   The file keeps its name deliberately. The stylesheet handle, the script
   handle and the dependency chain in functions.php all refer to it, and
   renaming four things to improve one comment is how a working dependency
   graph acquires a broken link.
   ========================================================================== */


/* 5. Overlay header
   --------------------------------------------------------------------------
   Three columns with the wordmark dead centre. Grid rather than flex with
   space-between, because with flex the logo drifts off-centre whenever the
   two sides have different widths — which they always do.
   ========================================================================== */

.u-header-overlay .u-header-bar {
	background: transparent;
	border-bottom: 1px solid transparent;
	transition: background var(--u-response) var(--u-ease-out),
		border-color var(--u-response) var(--u-ease-out);
}

.u-header-overlay.is-scrolled .u-header-bar {
	background: var(--u-glass-bg);
	border-bottom-color: var(--u-border);
	backdrop-filter: blur(var(--u-blur)) saturate(var(--u-saturate));
	-webkit-backdrop-filter: blur(var(--u-blur)) saturate(var(--u-saturate));
}

.u-header-overlay .u-header-row {
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	align-items: center;
	gap: 16px;
	min-height: 76px;
}

.u-header-overlay .u-header-start {
	display: flex;
	align-items: center;
	gap: 8px;
	justify-self: start;
}

.u-header-overlay .u-header-mid {
	justify-self: center;
}

.u-header-overlay .u-header-end {
	display: flex;
	align-items: center;
	gap: 14px;
	justify-self: end;
}

/* The toggle: two rules that become an X. Animated with transform only —
   animating height or margin here would relayout the header every frame. */
.u-overlay-toggle {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	padding: 10px 4px 10px 12px;
	background: none;
	border: 0;
	color: inherit;
	font: inherit;
	cursor: pointer;
}

.u-overlay-toggle-label {
	position: relative;
	display: inline-grid;
	font-size: 0.82rem;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	overflow: hidden;
	height: 1.2em;
}

.u-overlay-word {
	grid-area: 1 / 1;
	transition: transform 320ms var(--u-ease-out), opacity 220ms linear;
}

.u-overlay-word-close {
	transform: translateY(100%);
	opacity: 0;
}

.u-overlay-toggle[aria-expanded="true"] .u-overlay-word-open {
	transform: translateY(-100%);
	opacity: 0;
}

.u-overlay-toggle[aria-expanded="true"] .u-overlay-word-close {
	transform: translateY(0);
	opacity: 1;
}

.u-overlay-toggle-bars {
	position: relative;
	display: block;
	width: 26px;
	height: 12px;
}

.u-overlay-toggle-bars span {
	position: absolute;
	left: 0;
	width: 100%;
	height: 1.5px;
	background: currentColor;
	border-radius: 2px;
	transition: transform 380ms var(--u-ease-out);
}

.u-overlay-toggle-bars span:nth-child(1) { top: 2px; }
.u-overlay-toggle-bars span:nth-child(2) { bottom: 2px; }

.u-overlay-toggle[aria-expanded="true"] .u-overlay-toggle-bars span:nth-child(1) {
	transform: translateY(4px) rotate(45deg);
}

.u-overlay-toggle[aria-expanded="true"] .u-overlay-toggle-bars span:nth-child(2) {
	transform: translateY(-4px) rotate(-45deg);
}


/* 6. Overlay menu
   --------------------------------------------------------------------------
   Full viewport. Opens with a clip-path wipe rather than a fade, because a
   fade over live page content leaves both readable at once for 300ms and
   both look wrong. clip-path also stays on the compositor.
   ========================================================================== */

.u-overlay {
	position: fixed;
	inset: 0;
	z-index: 900;

	/* Fully opaque. This covers live page content — headlines, photographs,
	   other cards — so any transparency here means two layers of text on
	   top of each other and neither one readable. The blur is a second
	   line of defence for browsers that ignore the paint order. */
	background: var(--u-bg);
	backdrop-filter: blur(28px) saturate(1.4);
	-webkit-backdrop-filter: blur(28px) saturate(1.4);

	overflow-y: auto;
	overscroll-behavior: contain;
	clip-path: inset(0 0 100% 0);
	transition: clip-path 520ms var(--u-ease-out);
}

.u-overlay[hidden] {
	display: none;
}

.u-overlay.is-open {
	clip-path: inset(0 0 0 0);
}

:root.u-overlay-open,
:root.u-overlay-open body {
	overflow: hidden;
}

/*
 * The header has to outrank the panel while it is open.
 *
 * The overlay is fixed at z-index 900 and the header sits at 100, so
 * without this the panel covers its own toggle: the button that closes it
 * is underneath it, and the menu/close word swap happens out of sight.
 * Raising the header only while open keeps the normal stacking otherwise.
 */
:root.u-overlay-open .u-header {
	z-index: 950;
}

.u-overlay-inner {
	min-height: 100%;
	display: flex;
	align-items: center;
	padding-block: clamp(90px, 12vh, 160px) clamp(40px, 8vh, 90px);
}

.u-overlay-inner > .u-container {
	display: grid;
	grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
	gap: clamp(32px, 6vw, 90px);
	align-items: start;
	width: 100%;
}

.u-overlay-nav .u-menu {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: clamp(4px, 0.8vw, 10px);
}

.u-overlay-nav .u-menu > li > a {
	display: block;
	padding: clamp(4px, 0.8vw, 10px) 0;
	font-family: var(--u-font-heading);
	font-size: clamp(2rem, 6.5vw, 4.6rem);
	line-height: 1.02;
	letter-spacing: -0.035em;
	text-decoration: none;
	color: var(--u-text);

	/* Each item starts low and rises in. The delay is set per item below
	   rather than by script, so it works even if script only toggles the
	   class. */
	opacity: 0;
	transform: translate3d(0, 34px, 0);
	transition:
		opacity 420ms var(--u-ease-out),
		transform 520ms var(--u-ease-out),
		color 200ms linear;
}

.u-overlay.is-open .u-menu > li > a {
	opacity: 1;
	transform: none;
}

/* Stagger. Seven is enough for any sane primary menu; anything past it
   simply arrives with the seventh rather than never arriving. */
.u-overlay .u-menu > li:nth-child(1) > a { transition-delay: 90ms; }
.u-overlay .u-menu > li:nth-child(2) > a { transition-delay: 140ms; }
.u-overlay .u-menu > li:nth-child(3) > a { transition-delay: 190ms; }
.u-overlay .u-menu > li:nth-child(4) > a { transition-delay: 240ms; }
.u-overlay .u-menu > li:nth-child(5) > a { transition-delay: 290ms; }
.u-overlay .u-menu > li:nth-child(6) > a { transition-delay: 340ms; }
.u-overlay .u-menu > li:nth-child(n+7) > a { transition-delay: 390ms; }

@media (hover: hover) {
	.u-overlay-nav .u-menu > li > a:hover {
		color: var(--u-primary);
	}
}

.u-overlay-nav .u-menu > li > a:focus-visible {
	outline: 2px solid var(--u-primary);
	outline-offset: 6px;
}

/* Submenus are flattened into a small inline list. A full-screen menu with
   hover flyouts inside it is two navigation systems fighting. */
.u-overlay-nav .sub-menu {
	list-style: none;
	margin: 6px 0 14px;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 6px 20px;
}

.u-overlay-nav .sub-menu a {
	color: var(--u-muted);
	text-decoration: none;
	font-size: 0.98rem;
}

.u-overlay-nav .sub-menu a:hover {
	color: var(--u-text);
}

.u-overlay-aside {
	display: grid;
	gap: clamp(18px, 2.5vw, 30px);
	opacity: 0;
	transform: translate3d(0, 20px, 0);
	transition:
		opacity 420ms var(--u-ease-out) 340ms,
		transform 520ms var(--u-ease-out) 340ms;
}

.u-overlay.is-open .u-overlay-aside {
	opacity: 1;
	transform: none;
}

.u-overlay-block p,
.u-overlay-block a {
	margin: 0;
	color: var(--u-text);
	text-decoration: none;
	font-size: 1.02rem;
	line-height: 1.6;
}

.u-overlay-block a:hover {
	color: var(--u-primary);
}

.u-overlay-label {
	display: block;
	margin-bottom: 6px;
	font-size: 0.74rem;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--u-muted);
}

.u-overlay-block .u-social-menu {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 8px 18px;
}

/* A full-bleed dismiss target behind the content. Sits at the back so it
   never intercepts a click meant for a link. */
.u-overlay-dismiss {
	position: absolute;
	inset: 0;
	z-index: -1;
	background: none;
	border: 0;
	cursor: default;
}

@media (max-width: 860px) {
	.u-overlay-inner > .u-container {
		grid-template-columns: minmax(0, 1fr);
		gap: 36px;
	}

	.u-header-overlay .u-header-row {
		min-height: 64px;
	}

	/* On a phone the wordmark takes the left,
	because a centred logo with a
	   toggle beside it leaves too little room for either. */
	.u-header-overlay .u-header-row {
		grid-template-columns: auto 1fr;
	}

	.u-header-overlay .u-header-start {
		display: none;
	}

	.u-header-overlay .u-header-mid {
		justify-self: start;
	}
}


/* 7. Reduced motion, reduced transparency, contrast, print
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
	/* Everything below is a real layout,
	not a disabled effect. The menu
	   still opens,
	the rail still scrolls,
	the panels still read. */


	.u-overlay {
		clip-path: none;
		transition: opacity 1ms linear;
		opacity: 0;
	}

	.u-overlay.is-open {
		opacity: 1;
	}

	.u-overlay-nav .u-menu > li > a,
	.u-overlay-aside {
		opacity: 1;
		transform: none;
		transition: none;
		transition-delay: 0s;
	}

	.u-slide,
	.u-overlay-word,
	.u-overlay-toggle-bars span {
		transition: none;
	}


	/* The rail is already a plain scroller, so nothing needs returning —
	   but the scrollbar comes back, because without momentum or a visible
	   drag cue it is the only remaining indication that the row moves. */

}

@media (prefers-reduced-transparency: reduce) {
	.u-header-overlay.is-scrolled .u-header-bar {
		background: var(--u-surface);
		backdrop-filter: none;
		-webkit-backdrop-filter: none;
	}
}

@media (prefers-contrast: more) {
	.u-slide,
	.u-side-panel,
	.u-side-num {
		color: var(--u-text);
		-webkit-text-stroke: 0;
	}
}

@media print {
	.u-overlay {
		display: none !important;
	}




	.u-slide,
	.u-side-panel {
		width: auto;
		break-inside: avoid;
		box-shadow: none;
	}
}


/* 8. Centred hero
   --------------------------------------------------------------------------
   Structure only — the palette and the type belong to whichever style layer
   is active. Lives here rather than in a demo layer because the layout is a
   setting (Colours & Design → Hero layout) available in every demo.

   The scrim is the important part. Text over an arbitrary photograph has no
   contrast guarantee: the image can be swapped for a paler one at any time
   and the headline silently becomes unreadable. The overlay makes
   legibility a property of the design rather than of whichever picture
   happens to be uploaded, which is why it is not optional and why the
   setting has a floor documented in the dashboard.
   ========================================================================== */

.u-hero-centre {
	position: relative;
	display: grid;

	/*
	 * align-content, NOT place-items.
	 *
	 * place-items: center is the obvious way to centre a hero and it is
	 * wrong here, because it also sets justify-items: center — which sizes
	 * the grid item to its own content instead of letting it stretch. The
	 * container then collapses to the width of the widest line inside it
	 * and the whole hero renders at roughly half the screen.
	 *
	 * align-content centres the row vertically and leaves horizontal
	 * sizing alone, which is the only part that was ever wanted. The
	 * horizontal centring is the container's own margin-inline: auto plus
	 * text-align, exactly as everywhere else in the theme.
	 */
	align-content: center;
	justify-items: stretch;

	min-height: clamp(520px, 78vh, 860px);
	padding-block: clamp(90px, 12vh, 150px);
	overflow: hidden;
	text-align: center;
	isolation: isolate;
}

.u-hero-centre .u-hero-inner {
	max-width: 760px;
	margin-inline: auto;
	text-align: center;
	align-items: center;
	justify-items: center;
}

.u-hero-centre .u-hero-actions { justify-content: center; }

/* The decorative stage belongs to the split layout. Two focal points in one
   hero is one too many. */
.u-hero-centre .u-hero-stage,
.u-hero-centre .u-hero-panel,
.u-hero-centre .u-orbit,
.u-hero-centre .u-hero-bars { display: none; }

.u-hero-bg {
	position: absolute;
	inset: 0;
	z-index: -1;

	/*
	 * No image set: a warm gradient wash rather than an empty box. This is
	 * a designed fallback, not a placeholder — a site can ship without ever
	 * uploading a photograph and still look finished.
	 */
	background:
		radial-gradient(120% 90% at 20% 0%, rgba(var(--u-primary-rgb), 0.18), transparent 60%),
		radial-gradient(100% 80% at 85% 20%, rgba(var(--u-accent-rgb), 0.16), transparent 62%),
		linear-gradient(180deg, var(--u-surface), var(--u-bg));
}

.u-hero.has-image .u-hero-bg {
	background-image: var(--u-hero-image);
	background-size: cover;
	background-position: center;
	background-repeat: no-repeat;
}

/*
 * The scrim. A separate layer rather than a semi-transparent background on
 * the image itself, so the darkness can be tuned without touching the
 * photograph, and so it composites on the GPU.
 *
 * --u-hero-tint lets a style layer warm or cool it. Neutral black over a
 * warm photograph greys it out, which is rarely what anyone wants.
 */
.u-hero.has-image .u-hero-bg::after {
	content: "";
	position: absolute;
	inset: 0;
	background:
		linear-gradient(
			180deg,
			rgba(var(--u-hero-tint, 12, 14, 18), calc(var(--u-hero-scrim, 0.5) * 1.15)) 0%,
			rgba(var(--u-hero-tint, 12, 14, 18), var(--u-hero-scrim, 0.5)) 45%,
			rgba(var(--u-hero-tint, 12, 14, 18), calc(var(--u-hero-scrim, 0.5) * 1.3)) 100%
		);
}

/* Video. Covers the hero the same way the image does, sits under the same
   scrim, and is invisible until it can actually play — a black rectangle
   fading in over the poster is worse than never showing the video. */
.u-hero-video {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	opacity: 0;
	transition: opacity 600ms var(--u-ease-out);
	pointer-events: none;
}

.u-hero.is-playing .u-hero-video { opacity: 1; }

/*
 * YouTube / Vimeo background.
 *
 * An iframe cannot be told to object-fit: cover — the player inside keeps
 * its own 16:9 no matter what the frame is sized to, so a frame stretched
 * to the hero would letterbox with black bars top and bottom. The frame is
 * instead made deliberately larger than the hero in whichever direction is
 * needed and centred, so the overflow is cropped exactly the way cover
 * crops a photograph.
 *
 * min-width/min-height with aspect-ratio does that in one rule: the frame
 * is never smaller than the hero on either axis and always 16:9, so the
 * larger axis spills and is clipped by the hero's overflow: hidden.
 */
.u-hero-embed {
	position: absolute;
	inset: 0;
	overflow: hidden;

	/* The player has its own background and it is not yours. Hiding it
	   until the first frame has had time to arrive means the hero never
	   flashes someone else's logo on a black rectangle. */
	opacity: 0;
	transition: opacity 700ms var(--u-ease-out);
}

.u-hero.is-playing .u-hero-embed { opacity: 1; }

.u-hero-embed iframe {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	width: auto;
	height: auto;
	min-width: 100%;
	min-height: 100%;
	aspect-ratio: 16 / 9;
	border: 0;

	/*
	 * Not interactive, and this is not cosmetic. A live player sitting
	 * behind the headline would swallow clicks meant for the buttons in
	 * front of it, and YouTube's chrome offers links out of your site from
	 * underneath your own copy.
	 */
	pointer-events: none;
}

/* Older engines without aspect-ratio fall back to a viewport-relative
   version of the same idea. Slightly less exact when the hero is not full
   height, and still better than black bars. */
@supports not (aspect-ratio: 16 / 9) {
	.u-hero-embed iframe {
		width: 100vw;
		height: 56.25vw;
		min-height: 100%;
		min-width: 177.78vh;
	}
}

/* With a video the scrim has to exist even when no poster was set, or the
   text sits directly on the footage. */
.u-hero.has-video .u-hero-bg::after {
	content: "";
	position: absolute;
	inset: 0;
	background:
		linear-gradient(
			180deg,
			rgba(var(--u-hero-tint, 12, 14, 18), calc(var(--u-hero-scrim, 0.5) * 1.15)) 0%,
			rgba(var(--u-hero-tint, 12, 14, 18), var(--u-hero-scrim, 0.5)) 45%,
			rgba(var(--u-hero-tint, 12, 14, 18), calc(var(--u-hero-scrim, 0.5) * 1.3)) 100%
		);
	z-index: 1;
}

/*
 * .u-hero-bg sits at z-index: -1, which only stays inside the hero if the
 * hero is a stacking context. .u-hero-centre isolates itself; the split
 * hero does not, so without this the background escapes upward and paints
 * behind the page instead — visible as a hero that looks completely
 * unchanged no matter what image is set.
 */
.u-hero.has-image,
.u-hero.has-video { isolation: isolate; }

/* A photograph is atmosphere enough. */
.u-hero-centre .u-aurora,
.u-hero.has-image .u-hero-glow,
.u-hero.has-video .u-hero-glow,
.u-hero.has-image .u-aurora,
.u-hero.has-video .u-aurora { display: none; }

/* Two focal points in one hero is one too many, whichever layout is on. */
.u-hero.has-image .u-hero-stage,
.u-hero.has-image .u-hero-panel,
.u-hero.has-image .u-orbit,
.u-hero.has-image .u-hero-bars,
.u-hero.has-video .u-hero-stage,
.u-hero.has-video .u-hero-panel,
.u-hero.has-video .u-orbit,
.u-hero.has-video .u-hero-bars { display: none; }

/*
 * Text over media.
 *
 * This has to live here, at the structural level, rather than in a style
 * layer. The palette a demo sets is dark ink on a light page; put a
 * photograph behind it and the headline is dark-on-dark and effectively
 * gone. Ember shipped its own version of this rule, which was fine while
 * the media was Ember-only — but the background is a setting available in
 * every demo, so the contrast rule has to be too. Otherwise turning on a
 * hero image in Studio produces an invisible headline and no explanation.
 *
 * White rather than a palette variable on purpose: the scrim underneath is
 * a known darkness, so white is the one value guaranteed to clear contrast
 * against it no matter which palette is loaded.
 */
.u-hero.has-image,
.u-hero.has-video,
.u-hero.has-image .u-hero-title,
.u-hero.has-video .u-hero-title {
	color: #fff;
}

.u-hero.has-image .u-lead,
.u-hero.has-image .u-eyebrow,
.u-hero.has-video .u-lead,
.u-hero.has-video .u-eyebrow {
	color: rgba(255, 255, 255, 0.88);
}

.u-hero.has-image .u-eyebrow::before,
.u-hero.has-video .u-eyebrow::before {
	background: #fff;
}

/* The ghost button borrows the page border colour, which is a pale hairline
   meant for a light surface and disappears entirely over a photograph. */
.u-hero.has-image .u-btn-ghost,
.u-hero.has-video .u-btn-ghost {
	color: #fff;
	border-color: rgba(255, 255, 255, 0.45);
}

@media (hover: hover) {
	.u-hero.has-image .u-btn-ghost:hover,
	.u-hero.has-video .u-btn-ghost:hover {
		background: rgba(255, 255, 255, 0.12);
		border-color: rgba(255, 255, 255, 0.7);
	}
}

@media (max-width: 720px) {
	.u-hero-centre {
		min-height: clamp(440px, 68vh, 620px);
		padding-block: clamp(70px, 10vh, 110px);
	}
}

@media (prefers-contrast: more) {
	/* Whatever the setting says,
	the floor rises — this is the only thing
	   keeping the headline readable over an arbitrary image. */
	.u-hero.has-image,
	.u-hero.has-video { --u-hero-scrim: 0.72; }
}

@media (prefers-reduced-motion: reduce) {
	/* The script already declines to load either kind,
	but if one somehow
	   arrived it must not move. */
	.u-hero-video,
	.u-hero-embed { display: none; }
}

@media print {
	.u-hero-centre { min-height: 0; }
	.u-hero-bg,
	.u-hero-embed { display: none; }
	.u-hero.has-image,
	.u-hero.has-video,
	.u-hero.has-image .u-hero-title,
	.u-hero.has-video .u-hero-title { color: #000; }
}
