/*
Theme Name: Millennium-power
Theme URI: https://github.com/BoondockWalker/millennium-power
Author: Millennium Control Systems, LLC
Author URI: https://www.m-controls.com
Description: A dark, sleek full-site-editing block theme for Millennium Control Systems. Built for WordPress 6.6+ with a modern violet-to-cyan accent system, fluid typography, and pages (Home, Capabilities, About, Contact) composed of editable block patterns.
Requires at least: 6.6
Tested up to: 6.8
Requires PHP: 8.0
Version: 1.10.40
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: millennium
Tags: full-site-editing, block-styles, block-patterns, dark, business, technology, one-column, custom-colors, custom-logo, custom-menu, editor-style, featured-images, threaded-comments, translation-ready, wide-blocks
*/

/*
 * Almost all styling for this theme lives in theme.json so it can be edited
 * from the Site Editor. The rules below cover the handful of things that
 * theme.json cannot express yet (smooth scrolling, gradient text, subtle
 * surface borders and motion on cards / buttons).
 */

:root {
	--millennium-ring: 0 0 0 1px var(--wp--preset--color--border);
}

html {
	scroll-behavior: smooth;
}

body {
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	text-rendering: optimizeLegibility;
	background-image:
		linear-gradient(
			to right,
			color-mix(in srgb, var(--wp--preset--color--border) 18%, transparent) 1px,
			transparent 1px
		),
		linear-gradient(
			to bottom,
			color-mix(in srgb, var(--wp--preset--color--border) 18%, transparent) 1px,
			transparent 1px
		);
	background-size: 64px 64px;
	background-attachment: fixed;
}

/* ---------------------------------------------------------------- *
 * Background ↔ text-color pairing (safety net)
 *
 * WordPress treats backgroundColor and textColor as independent
 * settings, so it's possible — in Gutenberg or in a pattern — to
 * paint a block with one of the brand backgrounds without also
 * setting a matching text color, leaving white-on-white or
 * dark-on-dark text.
 *
 * The rules below give every branded background-color class a
 * default child text color that pairs with it. Blocks that set
 * their own textColor in the editor still win (their inline class
 * + style is more specific); this just prevents invisible-by-
 * default situations site-wide.
 *
 * Pairing convention:
 *   Dark surfaces  (base, surface, surface-2, brand)     → contrast
 *   Light surfaces (contrast, muted)                     → base
 *   Accent surfaces (primary cyan, secondary teal)       → brand
 *
 * Headings on dark surfaces follow the surface color; on light
 * surfaces they pick up the brand-blue treatment that matches the
 * rest of the design. ---------------------------------------------- */
:is(.has-base-background-color, .has-surface-background-color, .has-surface-2-background-color, .has-brand-background-color) {
	color: var(--wp--preset--color--contrast);
}

:is(.has-base-background-color, .has-surface-background-color, .has-surface-2-background-color, .has-brand-background-color) :is(p, li):not([class*="has-"][class*="-color"]) {
	color: var(--wp--preset--color--contrast);
}

:is(.has-contrast-background-color, .has-muted-background-color) {
	color: var(--wp--preset--color--base);
}

:is(.has-contrast-background-color, .has-muted-background-color) :is(p, li):not([class*="has-"][class*="-color"]) {
	color: var(--wp--preset--color--base);
}

:is(.has-primary-background-color, .has-secondary-background-color) {
	color: var(--wp--preset--color--brand);
}

:is(.has-primary-background-color, .has-secondary-background-color) :is(p, li):not([class*="has-"][class*="-color"]) {
	color: var(--wp--preset--color--brand);
}


/* Gradient text utility, applied via the "Gradient text" block style. */
.is-style-millennium-gradient-text {
	background: var(--wp--preset--gradient--primary-gradient);
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
	color: transparent;
}

/* Card block style: bordered surface that lifts on hover.
 * overflow:hidden lets the 16px border-radius clip any child that
 * extends to the card's edge (e.g. the Locations photo).
 * transform-style: preserve-3d gives JS-driven mouse tilt a real 3D
 * context to work in; the perspective is supplied per-card via the
 * tilt JS so we don't need a parent wrapper. */
.is-style-millennium-card {
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 16px;
	background-color: var(--wp--preset--color--surface);
	overflow: hidden;
	transform-style: preserve-3d;
	transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1), border-color 0.25s ease, box-shadow 0.25s ease;
}

.is-style-millennium-card:hover {
	transform: translateY(-4px);
	border-color: color-mix(in srgb, var(--wp--preset--color--primary) 60%, var(--wp--preset--color--border));
	box-shadow: 0 24px 60px -30px color-mix(in srgb, var(--wp--preset--color--primary) 55%, transparent);
}

/* Card titles take the accent so they pop against the surface fill.
 * Covers core/heading (.wp-block-heading) and core/post-title — including
 * the linked variant, which would otherwise inherit the link colour. */
.is-style-millennium-card .wp-block-heading,
.is-style-millennium-card .wp-block-post-title,
.is-style-millennium-card .wp-block-post-title a {
	color: var(--wp--preset--color--primary);
}

.is-style-millennium-card .wp-block-post-title a:hover {
	color: var(--wp--preset--color--contrast);
}

/* Card content alignment: enforce left-aligned text in every card.
 * Wildcard descendant selector with !important defeats any
 * .has-text-align-center class, inline text-align style, or
 * inherited center alignment baked into stored markup. */
.is-style-millennium-card,
.is-style-millennium-card * {
	text-align: left !important;
}

/* Block-level children of a card span the full card width so short
 * headings can't get centered by WP's constrained-layout margin:auto
 * or flex-column align-items. */
.is-style-millennium-card > .wp-block-heading,
.is-style-millennium-card > .wp-block-group > .wp-block-heading,
.is-style-millennium-card > p,
.is-style-millennium-card > .wp-block-paragraph {
	width: 100%;
	max-width: 100%;
	margin-left: 0 !important;
	margin-right: 0 !important;
	align-self: stretch;
}

/* Single-product page: 4:3 photo shown in the right column. Currently a
 * generic data-center placeholder; swap the wp:html block in
 * templates/single-product.html for wp:post-featured-image once each
 * Product post has its own featured image set. The relative URL below
 * resolves against this stylesheet's location, so it works on any host. */
.millennium-product-photo {
	aspect-ratio: 3 / 4;
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 16px;
	background-color: var(--wp--preset--color--surface);
	background-image: url("./assets/products/placeholder.jpeg");
	background-size: cover;
	background-position: center;
}

/* Location card hero photos. One rule per location keeps each background
 * URL declarative; add a new .millennium-location-photo--<slug> for each
 * additional location card. */
.millennium-location-photo {
	aspect-ratio: 16 / 9;
	width: 100%;
	flex-shrink: 0;
	border-radius: 12px;
	background-color: var(--wp--preset--color--surface);
	background-size: cover;
	background-position: center;
	margin-bottom: 0.25rem;
}

/* When the location photo sits inside a card, it stretches to the card's
 * outer edge — negative margins cancel out the card's interior padding,
 * width grows to compensate, and overflow:hidden on the card (above)
 * lets its 16px border-radius clip the photo's corners cleanly.
 *
 * !important is necessary to defeat WordPress's is-layout-constrained
 * rule, which uses `margin-left: auto !important; margin-right: auto
 * !important;` (via :where()) on every direct child to center it. */
.is-style-millennium-card > .millennium-location-photo {
	margin-top: calc(var(--wp--preset--spacing--50) * -1) !important;
	margin-left: calc(var(--wp--preset--spacing--50) * -1) !important;
	margin-right: calc(var(--wp--preset--spacing--50) * -1) !important;
	margin-bottom: var(--wp--preset--spacing--40);
	width: calc(100% + var(--wp--preset--spacing--50) * 2) !important;
	max-width: none !important;
	border-radius: 0;
}

.millennium-location-photo--beachwood {
	background-image: url("./assets/locations/beachwood.jpg");
}

.millennium-location-photo--newnan {
	background-image: url("./assets/locations/Newnan_GA.webp");
}

/* Compact list of Millennium's "additional locations" shown beside
 * the Beachwood HQ card on the Locations page. Each item is a row
 * with city name (white), role eyebrow (cyan-secondary, uppercase),
 * optional address line (muted). Subtle hairline divider between
 * items via border-bottom. */
.millennium-location-list {
	list-style: none;
	margin: 0;
	padding: 0;
}

.millennium-location-list__item {
	padding: 0.9rem 0 1rem;
	border-bottom: 1px solid var(--wp--preset--color--border);
}

.millennium-location-list__item:first-child {
	padding-top: 0;
}

.millennium-location-list__item:last-child {
	border-bottom: none;
	padding-bottom: 0;
}

.millennium-location-list__city {
	color: var(--wp--preset--color--contrast);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 600;
	line-height: 1.3;
}

.millennium-location-list__role {
	color: var(--wp--preset--color--secondary);
	font-size: 0.72rem;
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	margin-top: 0.25rem;
}

.millennium-location-list__address {
	color: var(--wp--preset--color--muted);
	font-size: 0.85rem;
	line-height: 1.5;
	margin-top: 0.35rem;
}

/* Careers page team gallery: 3-column grid on desktop, 2-column on
 * tablets, single column on small phones. Each photo is cropped to
 * 4:3 via object-fit so the row reads as a tidy grid regardless of
 * source aspect ratios. */
.millennium-careers-gallery .wp-block-gallery {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--wp--preset--spacing--30);
}

.millennium-careers-gallery .wp-block-gallery > figure.wp-block-image {
	width: 100% !important;
	margin: 0;
}

.millennium-careers-gallery .wp-block-gallery > figure.wp-block-image img {
	width: 100%;
	height: auto;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border-radius: 12px;
	display: block;
}

@media (max-width: 1024px) {
	.millennium-careers-gallery .wp-block-gallery {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 540px) {
	.millennium-careers-gallery .wp-block-gallery {
		grid-template-columns: 1fr;
	}
}

/* Leadership LinkedIn icon — sits under the name. Uses the brand
 * primary cyan instead of the default LinkedIn-blue so the icon reads
 * as part of this site's palette rather than a generic social widget.
 * The is-style-logos-only style on the social-links block already
 * drops the colored backgrounds. */
.millennium-leader-social .wp-social-link {
	background: transparent !important;
	color: var(--wp--preset--color--primary) !important;
	transition: color 0.2s ease, transform 0.2s ease;
	padding: 0;
}

.millennium-leader-social .wp-social-link a {
	padding: 0;
}

.millennium-leader-social .wp-social-link svg {
	width: 28px;
	height: 28px;
}

.millennium-leader-social .wp-social-link:hover {
	color: var(--wp--preset--color--contrast) !important;
	transform: translateY(-1px);
}

/* News page editorial press-coverage band.
 *
 * The cards section is full-bleed with a subtle surface-2 background
 * and 1px top + bottom borders so the band reads as a distinct
 * "editorial / blog" zone regardless of monitor calibration. The
 * hero and closing CTA stay on the base background outside the band.
 *
 * Inside the band, the three press stories sit in a 3-up card grid
 * (image at top, then source + date + headline + excerpt below).
 * Each card is a darker surface tile on the lighter band, with a
 * 1px border and 16px corner radius. The image bleeds to the card's
 * top edges; padding lives only on the body.
 *
 * Hover lifts the whole card 4px, scales the image 1.04, paints the
 * headline cyan with an underline, and nudges the ↗ arrow up-right.
 * All transitions respect prefers-reduced-motion. */
.millennium-news-band {
	border-top: 1px solid var(--wp--preset--color--border);
	border-bottom: 1px solid var(--wp--preset--color--border);
}

.millennium-news-card {
	background-color: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 16px;
	overflow: hidden;
	transition: transform 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease;
}

.millennium-news-card:hover {
	transform: translateY(-4px);
	border-color: color-mix(in srgb, var(--wp--preset--color--primary) 50%, var(--wp--preset--color--border));
	box-shadow: 0 24px 60px -30px color-mix(in srgb, var(--wp--preset--color--primary) 55%, transparent);
}

.millennium-news-card__image {
	margin: 0;
	overflow: hidden;
}

.millennium-news-card__image img {
	transition: transform 0.5s ease;
	display: block;
	width: 100%;
}

.millennium-news-card:hover .millennium-news-card__image img {
	transform: scale(1.04);
}

.millennium-news-card__body h3 {
	margin: 0;
	line-height: 1.35;
}

.millennium-news-card__body h3 a {
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
	transition: color 0.2s ease;
}

.millennium-news-card:hover .millennium-news-card__body h3 a {
	color: var(--wp--preset--color--primary);
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 4px;
}

.millennium-news-card__arrow {
	display: inline-block;
	margin-left: 0.25em;
	color: var(--wp--preset--color--secondary);
	font-weight: 500;
	transition: transform 0.2s ease, color 0.2s ease;
}

.millennium-news-card:hover .millennium-news-card__arrow {
	color: var(--wp--preset--color--primary);
	transform: translate(2px, -2px);
}

@media (prefers-reduced-motion: reduce) {
	.millennium-news-card,
	.millennium-news-card__image img,
	.millennium-news-card__arrow {
		transition: none;
	}
	.millennium-news-card:hover {
		transform: none;
	}
	.millennium-news-card:hover .millennium-news-card__image img {
		transform: none;
	}
	.millennium-news-card:hover .millennium-news-card__arrow {
		transform: none;
	}
}

/* Locations page interactive map (Leaflet + OpenStreetMap tiles).
 *
 * No frame: the map sits directly on the page's dark blue background,
 * with no border, border-radius or wrapper surface — the bright light
 * tiles read as a key visual against the dark page.
 *
 * Tiles use their natural light OSM color (no dark-mode filter),
 * lightly desaturated so the green/blue cartography reads as a clean
 * neutral white-ish map rather than a busy colorful one.
 *
 * Markers are custom div-icons in the brand palette: brand-blue dots
 * for the two main offices (HQ tier with pulse halo), smaller teal
 * dots for sales & service satellites. Dots have white halos so they
 * pop against the light map. Popups are re-skinned to match the
 * site's surface cards. */
/* World network map on the Locations page. Floats on the dark page
 * background — no border, no card surface, no raster tiles. Country
 * shapes are drawn from a 110m-scale TopoJSON (loaded at runtime from
 * the unpkg CDN by millennium-map.js) with very faint white fills and
 * strokes so the geography reads as a quiet anchor for the brighter
 * marker dots without competing with them. A subtle radial vignette
 * behind the map dims the edges to sell the "floating" feel.
 *
 * Markers are custom div-icons in two brand palettes:
 *  - Millennium: cyan dots (HQ pulses, satellites quiet).
 *  - Grenzebach: red dots (parent-group international footprint, no
 *    pulse — Millennium is the primary brand on this site). */
.millennium-locations-map {
	/* Break out of the section's root-padding box to span the full
	 * viewport width. WP's constrained-layout CSS forces
	 *   margin-left: auto !important; margin-right: auto !important
	 * on children, which cancels any margin-based pull-back. Using
	 * transform: translateX(-50%) sidesteps that — transforms aren't
	 * touched by WP's margin rules. */
	position: relative;
	width: 100vw;
	left: 50%;
	transform: translateX(-50%);
	max-width: none;
	aspect-ratio: 1.92 / 1;
	/* Leaflet sets its internal panes to z-index 200-700; without a new
	 * stacking context here those escape the section and sit on top of
	 * the sticky header's dropdowns. isolation:isolate (and the
	 * defensive position:relative + z-index:0) caps the map's stacking
	 * inside this container so the header always wins. */
	position: relative;
	z-index: 0;
	isolation: isolate;
}

/* Soft cyan glow centered behind the map. Sized explicitly (60% × 50%
 * of the container) and faded to fully transparent at 100% so the
 * radial edge never clips the container's bottom — at the new wider
 * aspect ratio a 65%-stop gradient was hitting the container edge
 * mid-fade and showing a visible horizontal seam. */
.millennium-locations-map::before {
	content: "";
	position: absolute;
	inset: 0;
	background: radial-gradient(ellipse 60% 50% at 50% 50%,
		color-mix(in srgb, var(--wp--preset--color--primary) 12%, transparent),
		transparent 100%);
	pointer-events: none;
	z-index: -1;
}

/* The Leaflet container class lands on the SAME element as
 * .millennium-locations-map (Leaflet adds it during L.map()), so the
 * background override has to target the same element, not a
 * descendant. Without this rule, Leaflet's default #ddd shows through
 * and the map reads as a light panel on the dark page. */
.millennium-locations-map.leaflet-container,
.millennium-locations-map .leaflet-container {
	background: transparent !important;
	font-family: inherit;
	outline: none;
}

.millennium-map-marker {
	position: relative;
	width: 100%;
	height: 100%;
}

.millennium-map-marker__dot {
	position: absolute;
	inset: 0;
	border-radius: 50%;
	border: 2px solid #ffffff;
}

/* Millennium markers — cyan (HQ slightly larger via iconSize in JS). */
.millennium-map-marker--millennium .millennium-map-marker__dot {
	background: var(--wp--preset--color--primary);
	box-shadow: 0 0 0 1px var(--wp--preset--color--primary), 0 4px 14px rgba(0, 0, 0, 0.5);
}

/* Grenzebach markers — red, matching the PDF brand fill. */
.millennium-map-marker--grenzebach .millennium-map-marker__dot {
	background: #e3000f;
	box-shadow: 0 0 0 1px #e3000f, 0 4px 14px rgba(0, 0, 0, 0.5);
}

.millennium-map-marker__pulse {
	position: absolute;
	inset: 0;
	border-radius: 50%;
	background: var(--wp--preset--color--primary);
	opacity: 0.45;
	animation: millennium-map-pulse 2.4s ease-out infinite;
	pointer-events: none;
}

@keyframes millennium-map-pulse {
	0%   { transform: scale(1);   opacity: 0.55; }
	100% { transform: scale(2.8); opacity: 0;    }
}

@media (prefers-reduced-motion: reduce) {
	.millennium-map-marker__pulse {
		animation: none;
		opacity: 0.3;
	}
}

.millennium-locations-map .leaflet-popup-content-wrapper {
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--contrast);
	border-radius: 12px;
	border: 1px solid var(--wp--preset--color--border);
	box-shadow: 0 18px 40px -18px rgba(0, 0, 0, 0.7);
	padding: 4px;
}

.millennium-locations-map .leaflet-popup-content {
	margin: 14px 18px;
	line-height: 1.5;
}

.millennium-locations-map .leaflet-popup-tip {
	background: var(--wp--preset--color--surface);
	border-right: 1px solid var(--wp--preset--color--border);
	border-bottom: 1px solid var(--wp--preset--color--border);
}

.millennium-locations-map .leaflet-popup-close-button {
	color: var(--wp--preset--color--muted) !important;
	font-size: 1.4rem;
	padding: 6px 8px 0 0 !important;
}

.millennium-locations-map .leaflet-popup-close-button:hover {
	color: var(--wp--preset--color--contrast) !important;
}

/* Permanent city labels next to each marker — small, uppercase, white
 * with a heavy text-shadow so they read against both the dim country
 * fills and the dark page background. No tooltip arrow / background. */
.leaflet-tooltip.millennium-map-label {
	background: transparent;
	border: none;
	box-shadow: none;
	padding: 0;
	color: var(--wp--preset--color--contrast);
	font-family: inherit;
	font-size: 0.72rem;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9), 0 0 8px rgba(0, 0, 0, 0.7);
	white-space: nowrap;
	pointer-events: none;
}

.leaflet-tooltip.millennium-map-label::before {
	display: none;
}

/* Zoom +/- control: skin to match the dark theme. */
.millennium-locations-map .leaflet-control-zoom {
	border: none;
	box-shadow: none;
}

.millennium-locations-map .leaflet-control-zoom a {
	background-color: color-mix(in srgb, var(--wp--preset--color--surface) 92%, transparent);
	color: var(--wp--preset--color--contrast);
	border: 1px solid var(--wp--preset--color--border);
	width: 30px;
	height: 30px;
	line-height: 28px;
	font-size: 18px;
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
}

.millennium-locations-map .leaflet-control-zoom a:first-child {
	border-top-left-radius: 6px;
	border-top-right-radius: 6px;
}

.millennium-locations-map .leaflet-control-zoom a:last-child {
	border-top: none;
	border-bottom-left-radius: 6px;
	border-bottom-right-radius: 6px;
}

.millennium-locations-map .leaflet-control-zoom a:hover {
	background-color: var(--wp--preset--color--surface-2);
	color: var(--wp--preset--color--primary);
}

.millennium-map-popup__role {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	color: var(--wp--preset--color--secondary);
	margin-bottom: 6px;
}

.millennium-map-popup__name {
	font-size: var(--wp--preset--font-size--large);
	font-weight: 600;
	color: var(--wp--preset--color--contrast);
	margin: 0 0 8px;
	line-height: 1.3;
}

.millennium-map-popup__address {
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--muted);
	line-height: 1.6;
	margin: 0;
}

/* Inline industry / service icons (Lucide, MIT licensed). Tinted in the brand
 * accent via currentColor so all icons read as a unified set. */
.millennium-icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	color: var(--wp--preset--color--primary);
}

/* Centered icon block above a hero H1 on the Markets sub-pages.
 * Larger size (64px) so it carries visual weight against the
 * clamp(2.5rem, 5vw, 4rem) headline; soft cyan glow ring picks up
 * the section's existing accent. */
.millennium-hero-icon {
	display: flex;
	justify-content: center;
	margin-bottom: var(--wp--preset--spacing--30);
}

.millennium-hero-icon .millennium-icon {
	width: 64px;
	height: 64px;
	padding: 14px;
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--primary) 35%, transparent);
	border-radius: 16px;
	background-color: color-mix(in srgb, var(--wp--preset--color--primary) 10%, transparent);
}

/* Partner / parent-company logo cards on the Company page sit on a
 * white "contrast" background and host the brand SVGs. Defensive
 * rules to make sure the SVG inside renders at its native colors
 * (no inherited filter from the dark surrounding theme, full
 * opacity, real width) so the logo never reads as "white on white".
 *
 * Flex centering + a small margin-top "cheat" optically centers the
 * wordmark inside the card — the italic diagonals on the Millennium
 * mark push the geometric center of the bitmap upward, so a literal
 * vertical center would read as top-heavy. */
.millennium-partner-logo {
	display: flex;
	align-items: center;
	justify-content: center;
}

.millennium-partner-logo img {
	max-width: 100%;
	width: 100%;
	height: auto;
	display: block;
	opacity: 1;
	filter: none;
	mix-blend-mode: normal;
	margin-block: 4px 0;
}

/* Footer "Navigate" row — single inline paragraph of dot-separated
 * links. The class wraps a constrained group so the muted hover
 * styling applies to every nested anchor without having to lock the
 * paragraph node down by itself. */
.millennium-footer-nav p {
	margin: 0;
}

.millennium-footer-nav a {
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
	transition: color 0.2s ease;
}

.millennium-footer-nav a:hover,
.millennium-footer-nav a:focus {
	color: var(--wp--preset--color--primary);
}

.millennium-icon svg {
	width: 100%;
	height: 100%;
	stroke: currentColor;
	fill: none;
	stroke-width: 1.5;
	stroke-linecap: round;
	stroke-linejoin: round;
}

/* Cards inside a Columns or a Query post-template grid should stretch to the
 * tallest sibling so the grid reads as an even matrix instead of ragged tiles.
 */
.wp-block-column > .is-style-millennium-card,
.wp-block-post-template > li > .is-style-millennium-card {
	height: 100%;
	display: flex;
	flex-direction: column;
}

/* Center the product cards on a product-category archive, with the
 * Switchgear category's two products forced side-by-side. Most other
 * categories only have one product (and the main nav now skips their
 * archives anyway), so the 1-card / 2-card cases are the realistic
 * targets here.
 *
 * The previous rule used minmax(280px, 380px), which broke into a
 * single stacked column whenever the container wasn't comfortably
 * wider than ~600px. Lowering the min to 240px and capping the grid
 * to 840px wide via max-width keeps a 2-up at any reasonable desktop
 * width while still leaving room for the cards to scale up and stay
 * readable. justify-content: center handles the 1-card case.
 */
.millennium-category-grid.is-layout-grid {
	grid-template-columns: repeat(auto-fit, minmax(240px, 400px));
	justify-content: center;
	max-width: 840px;
	margin-left: auto;
	margin-right: auto;
}

/* Soft glow behind the hero. */
.is-style-millennium-glow {
	position: relative;
	isolation: isolate;
}

.is-style-millennium-glow::before {
	content: "";
	position: absolute;
	inset: -20% 0 auto 50%;
	translate: -50% 0;
	width: min(900px, 90%);
	height: 520px;
	background: radial-gradient(ellipse at center, color-mix(in srgb, var(--wp--preset--color--primary) 35%, transparent), color-mix(in srgb, var(--wp--preset--color--secondary) 12%, transparent) 45%, transparent 70%);
	filter: blur(20px);
	z-index: -1;
	pointer-events: none;
}

/* Hero with background video. The video sits at z-index -3 inside the
 * hero's stacking context, the gradient overlay at -2 darkens it for
 * legibility, and the existing glow ::before at -1 sits between the
 * overlay and the content. Content has no explicit z-index — it stays
 * at the top of the stack.
 *
 * The 100vw + calc(50% - 50vw) trick forces the section to extend to
 * the viewport edges regardless of its parent's constraints. WP's own
 * .alignfull rules give us max-width:none, but they only emit the
 * negative-margin breakout when the parent has has-global-padding —
 * which page-no-title.html's core/post-content wrapper does not. */
/* Make any alignfull section inside core/post-content actually extend
 * to the viewport edges. WP's .alignfull only removes max-width by
 * default; it doesn't break out through the constrained-layout
 * wrappers (post-content, main) that the page-no-title template
 * nests sections inside. Same viewport-width math as .millennium-hero,
 * generalized so any new full-bleed section (e.g. the light-alt home
 * page's color-blocked bands) renders edge-to-edge without needing
 * its own custom class. */
.wp-block-post-content > .alignfull {
	width: 100vw !important;
	max-width: 100vw !important;
	margin-left: 0 !important;
	margin-right: 0 !important;
	position: relative;
	left: calc(50% - 50vw);
	box-sizing: border-box;
}

.millennium-hero {
	position: relative;
	/* No overflow:hidden — the video container clips itself and is
	 * absolutely positioned to extend past the section's bounds to
	 * viewport width. */
}

/* Subtle drop shadow on the hero copy so the headline, tagline and
 * lead paragraph stay legible over whatever frame the background
 * video happens to be on. Shadow uses the base navy at low alpha,
 * which reads as a darkening rather than a black glow. */
.millennium-hero h1,
.millennium-hero p {
	text-shadow: 0 2px 14px rgba(10, 20, 38, 0.55);
}

/* Break the video container out to 100vw via viewport-centered
 * absolute positioning. This is independent of whatever width WP
 * gives the section (constrained, alignfull, etc.) — the video just
 * spans the viewport regardless. The left:calc trick (50% of the
 * section minus 50vw) lands the video's left edge at the viewport's
 * left edge as long as the section itself is horizontally centered,
 * which is the default for any WP constrained-layout child. Uses
 * `left` rather than `transform: translateX` so the transform
 * property stays free for the scroll-drift animation. */
.millennium-hero-video,
.millennium-hero-photo {
	position: absolute;
	top: 0;
	bottom: 0;
	left: calc(50% - 50vw) !important;
	right: calc(50% - 50vw) !important;
	width: 100vw !important;
	max-width: 100vw !important;
	min-width: 100vw !important;
	z-index: -3;
	overflow: hidden;
	pointer-events: none;
}

.millennium-hero-video video {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
	display: block;
}

/* Photo variant of the hero backdrop — same viewport-bleed positioning
 * as the video, but with a static image set via inline background-image
 * on the .millennium-hero-photo element itself. The dark gradient
 * overlay (.millennium-hero-overlay) sits inside and matches the home
 * page video hero's treatment so the hero copy stays legible over any
 * photo. */
.millennium-hero-photo {
	background-size: cover;
	background-position: center;
	background-repeat: no-repeat;
}

.millennium-hero-overlay {
	position: absolute;
	inset: 0;
	pointer-events: none;
	background:
		linear-gradient(
			180deg,
			var(--wp--preset--color--base) 0%,
			color-mix(in srgb, var(--wp--preset--color--base) 90%, transparent) 8%,
			color-mix(in srgb, var(--wp--preset--color--base) 75%, transparent) 30%,
			color-mix(in srgb, var(--wp--preset--color--base) 65%, transparent) 55%,
			color-mix(in srgb, var(--wp--preset--color--base) 85%, transparent) 85%,
			var(--wp--preset--color--base) 100%
		),
		radial-gradient(
			ellipse 80% 60% at 50% 50%,
			color-mix(in srgb, var(--wp--preset--color--primary) 18%, transparent) 0%,
			transparent 70%
		);
}

/* Reduced-motion: hide the video so the browser doesn't autoplay. The
 * overlay + existing glow stay so the hero still reads as a hero. */
@media (prefers-reduced-motion: reduce) {
	.millennium-hero-video,
	.millennium-hero-split__video video {
		display: none;
	}
}

/* Split-layout hero: copy on the left, video on the right. The video
 * sits in its own column so it never has text laid over it; the brand
 * glow on the section gives the left column a soft backdrop without
 * affecting legibility. */
.millennium-hero-split__video {
	position: relative;
	width: 100%;
	aspect-ratio: 16 / 10;
	border-radius: 18px;
	overflow: hidden;
	background-color: var(--wp--preset--color--surface);
	box-shadow:
		0 30px 80px -40px color-mix(in srgb, var(--wp--preset--color--primary) 60%, transparent),
		0 0 0 1px var(--wp--preset--color--border);
}

.millennium-hero-split__video video {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

/* On narrow viewports the columns stack and the video sits below the
 * copy at a more landscape ratio so it reads as a banner instead of a
 * tall block. */
@media (max-width: 781px) {
	.millennium-hero-split__video {
		aspect-ratio: 16 / 9;
	}
}

/* Light alt home — video frame used in the showcase section. Same
 * shape as the split hero's frame but with an aqua-tinted glow that
 * reads well against the sky-gradient background. */
.millennium-light-video-frame {
	position: relative;
	width: 100%;
	aspect-ratio: 16 / 10;
	border-radius: 18px;
	overflow: hidden;
	background-color: rgba(255, 255, 255, 0.08);
	box-shadow:
		0 30px 80px -40px rgba(0, 0, 0, 0.55),
		0 0 0 1px rgba(255, 255, 255, 0.18);
}

.millennium-light-video-frame video {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

@media (max-width: 781px) {
	.millennium-light-video-frame {
		aspect-ratio: 16 / 9;
	}
}

/* Inline highlight format: keep the accent text colour, drop the browser's
 * default yellow mark background. (Marks with has-inline-color carry their
 * colour inline, which still wins over this rule.)
 */
mark {
	background-color: transparent;
	color: inherit;
}

/* Spec / data tables — technical grid look: fine rule lines, muted label
 * column, and a subtle alternating row tone that works on the dark base
 * (instead of core's light-grey "stripes" which disappear on dark).
 */
.wp-block-table table {
	border-collapse: collapse;
	width: 100%;
	color: var(--wp--preset--color--contrast);
}

.wp-block-table th,
.wp-block-table td {
	padding: 0.75rem 1rem;
	border-bottom: 1px solid var(--wp--preset--color--border);
	text-align: left;
	vertical-align: top;
}

.wp-block-table tr:last-child th,
.wp-block-table tr:last-child td {
	border-bottom: none;
}

.wp-block-table th {
	font-weight: 600;
}

.wp-block-table tbody tr > :first-child {
	color: var(--wp--preset--color--muted);
	font-weight: 600;
	border-right: 1px solid var(--wp--preset--color--border);
	width: 40%;
}

.wp-block-table.is-style-stripes tbody tr:nth-child(odd) {
	background-color: color-mix(in srgb, var(--wp--preset--color--surface-2) 55%, transparent);
}

.wp-block-table.is-style-stripes tbody tr:nth-child(even) {
	background-color: transparent;
}

.wp-block-table.is-style-stripes {
	border-bottom: 0;
}

/* Buttons: gentle motion + glow on the primary fill. */
.wp-element-button,
.wp-block-button__link {
	transition: transform 0.2s ease, box-shadow 0.2s ease, opacity 0.2s ease,
		background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}

.wp-block-button:not(.is-style-outline) .wp-block-button__link:hover {
	transform: translateY(-2px);
	box-shadow: 0 18px 40px -18px color-mix(in srgb, var(--wp--preset--color--primary) 80%, transparent);
}

/* Outline buttons (e.g. "Explore capabilities") transform into a filled
 * treatment on hover — secondary teal-green fill, white text, plus
 * lift+glow motion. Distinct from the primary "Get in touch" button's
 * resting cyan, so the two buttons never visually compete when sitting
 * next to each other. */
.is-style-outline .wp-block-button__link:hover,
.is-style-outline .wp-block-button__link:focus {
	background-color: var(--wp--preset--color--secondary);
	border-color: var(--wp--preset--color--secondary);
	color: var(--wp--preset--color--contrast);
	transform: translateY(-2px);
	box-shadow: 0 18px 40px -18px color-mix(in srgb, var(--wp--preset--color--secondary) 80%, transparent);
}

/* Sticky header. The sticky behaviour lives on the outer <header> element
 * (template-part wrapper) so its containing block is the document, not the
 * inner .millennium-header div — sticking against itself unsticks immediately
 * on long pages like the Home page. */
.wp-site-blocks > header,
body > header {
	position: sticky;
	top: 0;
	z-index: 1000;
}

.millennium-header {
	backdrop-filter: saturate(160%) blur(12px);
	-webkit-backdrop-filter: saturate(160%) blur(12px);
	background-color: color-mix(in srgb, var(--wp--preset--color--base) 78%, transparent);
	border-bottom: 1px solid var(--wp--preset--color--border);
}

/* FAQ details pills (Resources page). Surface fill lifts each pill off
 * the base background so the questions read as a list; generous padding
 * gives the touch / click target real weight; a custom chevron marker
 * (rotates 180° when open) replaces the browser's default triangle. */
.wp-block-details {
	background-color: var(--wp--preset--color--surface);
	margin-top: 0.75rem;
	overflow: hidden;
}

.wp-block-details > summary {
	list-style: none;
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1.5rem;
	padding: 1.25rem 1.5rem;
	font-weight: 600;
	font-size: 1.0625rem;
	color: var(--wp--preset--color--contrast);
	transition: color 0.2s ease;
}

.wp-block-details > summary::-webkit-details-marker {
	display: none;
}

.wp-block-details > summary::after {
	content: "";
	flex-shrink: 0;
	width: 0.625rem;
	height: 0.625rem;
	border-right: 2px solid var(--wp--preset--color--primary);
	border-bottom: 2px solid var(--wp--preset--color--primary);
	transform: rotate(45deg) translate(-2px, -2px);
	transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}

.wp-block-details[open] > summary::after {
	transform: rotate(-135deg) translate(-2px, -2px);
}

.wp-block-details[open] > summary {
	color: var(--wp--preset--color--primary);
}

.wp-block-details > :not(summary) {
	margin: 0;
	padding: 0 1.5rem 1.25rem;
	color: var(--wp--preset--color--muted);
	line-height: 1.65;
}

/* Navigation hover treatment. */
.wp-block-navigation .wp-block-navigation-item__content {
	opacity: 0.78;
	transition: opacity 0.2s ease;
}

.wp-block-navigation .wp-block-navigation-item__content:hover {
	opacity: 1;
}

/* Top-level nav links keep their hover underline (set globally on
 * elements.link in theme.json) but with more breathing room between
 * the underline and the text baseline so the affordance reads as
 * intentional, not crowded. Targets items inside the top-level
 * .wp-block-navigation__container UL (excluding dropdowns, which
 * live under .wp-block-navigation__submenu-container). */
.millennium-header .wp-block-navigation__container > .wp-block-navigation-item > .wp-block-navigation-item__content:hover,
.millennium-header .wp-block-navigation__container > .wp-block-navigation-item > .wp-block-navigation-item__content:focus-visible {
	text-underline-offset: 10px;
	text-decoration-thickness: 1px;
}

/* Desktop submenu dropdown — sits 24px below the nav bar as a clearly
 * detached elevated surface. The ::before pseudo-element is a 24px
 * invisible bridge over the gap so the cursor travels from the parent
 * nav item into the dropdown without dropping out of :hover (CSS
 * :hover propagates from descendants up to ancestors, so the bridge
 * being inside the dropdown is enough to keep the parent <li> hovered).
 * All four corners get a clean 12px radius — the border is a flat 1px
 * on all sides, so the radius curves through real visible border on
 * every corner. Subtle slide-down + fade-in entrance polishes the
 * reveal without adding weight; respects prefers-reduced-motion.
 * Scoped to desktop via min-width media query so the mobile overlay
 * keeps its own styling. */
@media (min-width: 782px) {
	.millennium-header .wp-block-navigation__submenu-container {
		top: 100%;
		margin-top: 24px;
		border-radius: 12px;
		border: 1px solid var(--wp--preset--color--border);
		background-color: var(--wp--preset--color--surface);
		box-shadow: 0 28px 56px -16px rgba(0, 0, 0, 0.7);
		padding: 6px;
		min-width: 260px;
		transform: translateY(-6px);
		opacity: 0;
		transition: transform 180ms ease, opacity 180ms ease;
	}

	.millennium-header .wp-block-navigation-item:hover > .wp-block-navigation__submenu-container,
	.millennium-header .wp-block-navigation-item:focus-within > .wp-block-navigation__submenu-container,
	.millennium-header .wp-block-navigation__submenu-container.is-open {
		transform: translateY(0);
		opacity: 1;
	}

	.millennium-header .wp-block-navigation__submenu-container::before {
		content: "";
		position: absolute;
		top: -24px;
		left: 0;
		right: 0;
		height: 24px;
	}

	.millennium-header .wp-block-navigation__submenu-container .wp-block-navigation-item {
		border-radius: 8px;
		transition: background-color 0.18s ease;
	}

	.millennium-header .wp-block-navigation__submenu-container .wp-block-navigation-item:hover,
	.millennium-header .wp-block-navigation__submenu-container .wp-block-navigation-item:focus-within {
		background-color: var(--wp--preset--color--base);
	}

	.millennium-header .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
		opacity: 1;
		color: var(--wp--preset--color--contrast);
		padding: 6px 14px;
		border-radius: 6px;
		display: block;
		width: 100%;
		line-height: 1.3;
		text-decoration: none;
	}

	/* The pill background already signals hover on dropdown items, so
	 * the global elements.link:hover underline is redundant noise.
	 * Suppress it across hover/focus on dropdown links only. */
	.millennium-header .wp-block-navigation__submenu-container .wp-block-navigation-item__content:hover,
	.millennium-header .wp-block-navigation__submenu-container .wp-block-navigation-item__content:focus,
	.millennium-header .wp-block-navigation__submenu-container .wp-block-navigation-item__content:focus-visible {
		text-decoration: none;
	}

	.millennium-header .wp-block-navigation__submenu-container .wp-block-navigation-item__content:focus-visible {
		outline: 2px solid var(--wp--preset--color--primary);
		outline-offset: -2px;
	}

	@media (prefers-reduced-motion: reduce) {
		.millennium-header .wp-block-navigation__submenu-container {
			transition: none;
			transform: none;
		}
	}
}

/* Site logo (header + footer wordmark). */
.millennium-logo {
	margin: 0;
}

.millennium-logo img {
	display: block;
	height: 72px;
	width: auto;
}

/* Larger logo in the nav bar; smaller wordmark stays in the footer.
 * The visual size is bumped 15% via transform so the rendered wordmark
 * reads bigger without growing the layout box — header padding +
 * total header height stay identical. Anchored left so it grows
 * rightward; the bit that overhangs vertically sits inside the
 * existing header padding so nothing clips. */
.millennium-header .millennium-logo img {
	height: 99px;
	margin-block: -6.5px;
}

@media (max-width: 600px) {
	.millennium-header .millennium-logo img {
		height: 87px;
	}
}

/* Keep the header bar single-row at every desktop/tablet width:
 * the nav has flexWrap:"wrap" baked into its block attrs, which on
 * narrow desktops drops "About" (and possibly later items) onto a
 * second line — doubling header height. Force-nowrap and let the
 * mobile overlay handle wrapping below 600px instead. */
.millennium-header .wp-block-navigation {
	flex-wrap: nowrap;
}

/* "Contact Us" CTA always single-line, regardless of viewport.
 * The mobile shrink rule still applies below 600px. */
.millennium-header .wp-block-button__link {
	white-space: nowrap;
}

/* Tight padding variant for the header "Contact Us" button so it
 * doesn't tower over the nav row. Font size matches core/navigation
 * (preset:small, set in theme.json) so the pill reads as part of the
 * nav rather than a louder hero CTA. */
.millennium-cta-tight .wp-block-button__link {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	padding-top: 0.55em;
	padding-bottom: 0.55em;
	padding-left: 1.1em;
	padding-right: 1.1em;
}

/* ============================================================
 * Mobile navigation overlay.
 *
 * The header's <wp:navigation> block is configured with
 * overlayMenu:"mobile" + overlayBackgroundColor:"brand" +
 * overlayTextColor:"contrast", which gives WP the inputs to render a
 * full-viewport brand-blue overlay with light text. The rules below
 * size up the menu items for touch, center them vertically and
 * horizontally, soften the sub-menu hierarchy, and pin the open/close
 * buttons to the brand palette.
 * ============================================================ */

/* The overlay container itself — make sure background is solid even
 * if WP's default tries to blend or fade it, and force full-viewport
 * sizing regardless of breakpoint. WP only makes the responsive
 * container full-screen below ~600px by default, which means the
 * overlay opens as a small floating panel on tablets and narrow
 * desktops. Lock it to 100vw × 100vh whenever it's open. */
.wp-block-navigation__responsive-container.is-menu-open {
	position: fixed !important;
	top: 0 !important;
	right: 0 !important;
	bottom: 0 !important;
	left: 0 !important;
	width: 100vw !important;
	height: 100vh !important;
	height: 100svh !important;
	max-width: 100vw !important;
	max-height: 100vh !important;
	z-index: 100000 !important;
	overflow: auto !important;
	background-color: var(--wp--preset--color--brand) !important;
	padding: 1.5rem !important;
}

/* Menu list — stack vertically, center on screen, tighter leading.
 * Apply to every nested ul/li/anchor so the original right-justified
 * flex layout from the header bar can't leak into the overlay. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container,
.wp-block-navigation__responsive-container.is-menu-open ul {
	display: flex !important;
	flex-direction: column !important;
	align-items: center !important;
	justify-content: flex-start !important;
	width: 100% !important;
	max-width: 100% !important;
	margin: 0 !important;
	padding: 0 !important;
	list-style: none !important;
	gap: 0.5rem !important;
	text-align: center !important;
}

/* Top-level container fills the viewport vertically + horizontally
 * centers along its main axis so the whole menu sits in the centre
 * of the screen. */
.wp-block-navigation__responsive-container.is-menu-open > .wp-block-navigation__container {
	justify-content: center !important;
	min-height: 100vh;
	min-height: 100svh;
}

/* Each li — full-width row anchored centre. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container li,
.wp-block-navigation__responsive-container.is-menu-open ul li {
	display: flex !important;
	flex-direction: column !important;
	align-items: center !important;
	width: 100% !important;
	margin: 0 !important;
	padding: 0 !important;
	text-align: center !important;
}

/* Submenu container — kill the popover styling (background, border,
 * absolute positioning) and inline it under the parent item. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container {
	position: static !important;
	min-width: 0 !important;
	background: transparent !important;
	border: 0 !important;
	box-shadow: none !important;
	padding: 0.5rem 0 0 !important;
	margin: 0 !important;
	gap: 0.75rem !important;
	opacity: 1;
}

/* Submenu reveal arrow is redundant when items inline — hide it. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-icon {
	display: none !important;
}

/* Close (X) button — pin to the same screen position the hamburger
 * occupied before the menu opened.
 *
 * Why position: absolute (not fixed): the .millennium-header carries
 * a backdrop-filter, which in modern browsers establishes a containing
 * block for `position: fixed` descendants — so a fixed-positioned X
 * inside the header's DOM subtree gets pinned to the header's box,
 * not the viewport, and lands wherever the header happens to be sized
 * to. Using `position: absolute` instead anchors the X to the
 * `.wp-block-navigation__responsive-container` (which we've set to
 * position:fixed inset:0, so it IS at viewport coordinates), giving
 * a stable top-left-of-screen anchor. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close,
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close.wp-block-navigation__responsive-container-close {
	position: absolute !important;
	top: 1.5rem !important;
	right: var(--wp--style--root--padding-right, 1.5rem) !important;
	left: auto !important;
	bottom: auto !important;
	z-index: 100001 !important;
	padding: 0.5rem !important;
	color: var(--wp--preset--color--contrast) !important;
}

/* Top-level menu items — big, light, full-tap targets. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
	color: var(--wp--preset--color--contrast) !important;
	opacity: 1 !important;
	font-size: 1.875rem !important;
	font-weight: 600 !important;
	line-height: 1.15 !important;
	letter-spacing: -0.01em !important;
	padding: 0.3rem 0.75rem !important;
	text-align: center !important;
	display: inline-block !important;
}

/* Submenu items — slightly smaller and lighter to read as secondary. */
.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__submenu-container .wp-block-navigation-item__content {
	font-size: 1.25rem !important;
	font-weight: 400 !important;
	line-height: 1.2 !important;
	opacity: 0.8 !important;
	padding: 0.2rem 0.75rem !important;
}

/* Submenu container — keep it tight to its parent item. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container {
	gap: 0.4rem !important;
	padding-top: 0.4rem !important;
}

/* Submenu container inside the overlay: center, no card framing. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container {
	background-color: transparent !important;
	border: 0;
	padding: 0.5rem 0;
	gap: 0.75rem;
	text-align: center;
}

/* Submenu reveal arrow — light, slightly larger. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-icon svg {
	fill: var(--wp--preset--color--contrast);
}

/* Hamburger (open) and X (close) buttons — match the brand. */
.wp-block-navigation__responsive-container-open,
.wp-block-navigation__responsive-container-close {
	color: var(--wp--preset--color--contrast) !important;
}

.wp-block-navigation__responsive-container-open svg,
.wp-block-navigation__responsive-container-close svg {
	width: 28px;
	height: 28px;
}

/* ============================================================
 * General mobile polish.
 * ============================================================ */

@media (max-width: 600px) {
	/* Tighter vertical rhythm — every full-section spacing token drops
	 * a tier on small screens so pages don't feel airy on phones. */
	:root {
		--wp--preset--spacing--70: 3.5rem;
		--wp--preset--spacing--60: 2.5rem;
		--wp--preset--spacing--50: 1.75rem;
	}

	/* Hero CTAs stack instead of sitting side-by-side. */
	.millennium-hero .wp-block-buttons,
	.millennium-hero-split .wp-block-buttons {
		flex-direction: column;
		align-items: stretch;
		width: 100%;
	}

	.millennium-hero .wp-block-buttons .wp-block-button,
	.millennium-hero-split .wp-block-buttons .wp-block-button {
		width: 100%;
	}

	.millennium-hero .wp-block-button__link,
	.millennium-hero-split .wp-block-button__link {
		display: block;
		text-align: center;
	}

	/* Specs / data tables: smaller label column on phones so the
	 * value column has room to breathe. */
	.wp-block-table tbody tr > :first-child {
		width: 45%;
		font-size: 0.875rem;
	}

	/* Card padding lighter on mobile so cards don't feel mostly margin. */
	.is-style-millennium-card {
		padding: var(--wp--preset--spacing--40) !important;
	}

	/* Header "Get in touch" CTA shrinks on mobile so it doesn't dominate
	 * the bar or wrap to two lines next to the logo and hamburger. */
	.millennium-header .wp-block-buttons {
		flex-shrink: 0;
		order: -1;
	}

	.millennium-header .wp-block-button__link {
		font-size: 0.8125rem !important;
		padding: 0.55rem 1rem !important;
		white-space: nowrap !important;
		letter-spacing: 0 !important;
	}

	/* Hamburger sits to the right of the CTA — the visual order on
	 * mobile becomes Logo | Get-in-touch | Hamburger, so the menu
	 * affordance is the rightmost element. */
	.millennium-header .wp-block-navigation {
		order: 1;
	}
}

/* Contact form (rendered by the [millennium_contact_form] shortcode).
 * Plain inputs on the dark base — generous touch targets, accent focus
 * ring, full-width textarea. Honeypot is visually hidden but stays in
 * the DOM so bots fill it. */
.millennium-contact-form {
	display: flex;
	flex-direction: column;
	gap: 1rem;
}

.millennium-contact-form__honeypot {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

.millennium-contact-form__row {
	display: flex;
	flex-direction: column;
	gap: 1rem;
}

.millennium-contact-form__field {
	display: flex;
	flex-direction: column;
	gap: 0.35rem;
	min-width: 0;
	font-size: 0.875rem;
	color: var(--wp--preset--color--muted);
}

.millennium-contact-form__field > span > [aria-hidden="true"] {
	color: var(--wp--preset--color--primary);
}

.millennium-contact-form__field input,
.millennium-contact-form__field textarea {
	box-sizing: border-box;
	width: 100%;
	max-width: 100%;
	padding: 0.75rem 0.9rem;
	font: inherit;
	color: var(--wp--preset--color--contrast);
	background-color: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 10px;
	transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.millennium-contact-form__field textarea {
	resize: vertical;
	min-height: 7.5rem;
}

.millennium-contact-form__field input:focus,
.millennium-contact-form__field textarea:focus {
	outline: none;
	border-color: var(--wp--preset--color--primary);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--wp--preset--color--primary) 30%, transparent);
}

.millennium-contact-form button[type="submit"] {
	align-self: flex-start;
	margin-top: 0.25rem;
}

.millennium-contact-notice {
	margin: 0 0 0.5rem;
	padding: 0.75rem 1rem;
	border-radius: 10px;
	border: 1px solid var(--wp--preset--color--border);
	font-size: 0.9375rem;
}

.millennium-contact-notice.is-success {
	border-color: color-mix(in srgb, var(--wp--preset--color--primary) 60%, var(--wp--preset--color--border));
	background-color: color-mix(in srgb, var(--wp--preset--color--primary) 12%, transparent);
	color: var(--wp--preset--color--contrast);
}

.millennium-contact-notice.is-error {
	border-color: color-mix(in srgb, #f87171 60%, var(--wp--preset--color--border));
	background-color: color-mix(in srgb, #f87171 12%, transparent);
	color: var(--wp--preset--color--contrast);
}

/* ============================================================
 * Motion: scroll-driven reveals, hero cascade and scrolled header.
 *
 * The companion script in assets/js/millennium-motion.js adds the
 * .millennium-motion-reveal class to top-level sections (skipping the
 * hero), assigns a --millennium-stagger-i index to each card in a grid,
 * and toggles body.is-scrolled past 120px. Everything here is no-op
 * when the user prefers reduced motion.
 * ============================================================ */

/* Hero copy fade-up on first paint. Each direct child of the hero
 * .is-style-millennium-glow runs the cascade with a stepped delay. */
.is-style-millennium-glow > *,
.is-style-millennium-glow > * > * {
	animation: millennium-fade-up 0.8s ease both;
}
.is-style-millennium-glow > *:nth-child(2),
.is-style-millennium-glow > * > *:nth-child(2) { animation-delay: 0.10s; }
.is-style-millennium-glow > *:nth-child(3),
.is-style-millennium-glow > * > *:nth-child(3) { animation-delay: 0.20s; }
.is-style-millennium-glow > *:nth-child(4),
.is-style-millennium-glow > * > *:nth-child(4) { animation-delay: 0.30s; }
.is-style-millennium-glow > *:nth-child(5),
.is-style-millennium-glow > * > *:nth-child(5) { animation-delay: 0.40s; }

/* Hero glow gradient: a slow, subtle breath (pulse only animates scale
 * so it can share the element with the scroll-driven fadeout below). */
.is-style-millennium-glow::before {
	animation: millennium-glow-pulse 9s ease-in-out infinite;
}

/* Hero scroll-drift: as the hero exits the viewport, the glow fades and
 * softens, the video drifts down + scales up slightly and dims, and the
 * overlay deepens — all on the same view-timeline so they read as one
 * coordinated transition. Pure CSS scroll-driven animation, gated by
 * @supports so non-supporting browsers keep the static hero. */
@supports (animation-timeline: view()) {
	.is-style-millennium-glow {
		view-timeline-name: --millennium-hero;
	}

	.is-style-millennium-glow::before {
		animation:
			millennium-glow-pulse 9s ease-in-out infinite,
			millennium-glow-drift linear both;
		animation-timeline: auto, --millennium-hero;
		animation-range: normal, exit 0% exit 100%;
	}

	.millennium-hero-video {
		animation: millennium-hero-video-drift linear both;
		animation-timeline: --millennium-hero;
		animation-range: exit 0% exit 100%;
	}

	.millennium-hero-overlay {
		animation: millennium-hero-overlay-drift linear both;
		animation-timeline: --millennium-hero;
		animation-range: exit 0% exit 100%;
	}
}

@keyframes millennium-glow-drift {
	to {
		opacity: 0;
		filter: blur(40px);
	}
}

@keyframes millennium-hero-video-drift {
	to {
		transform: translateY(8%) scale(1.06);
		filter: blur(6px) brightness(0.55);
	}
}

@keyframes millennium-hero-overlay-drift {
	to {
		opacity: 1.4;
	}
}

@keyframes millennium-fade-up {
	from { opacity: 0; transform: translateY(14px); }
	to   { opacity: 1; transform: none; }
}

@keyframes millennium-glow-pulse {
	0%, 100% { transform: scale(1); }
	50%      { transform: scale(1.06); }
}

/* Section reveal: invisible until the IntersectionObserver flips on
 * .is-in-view, then fades + lifts into place. Every other section gets
 * .millennium-motion-reveal--lateral via JS so the direction alternates
 * between fade-up and fade-from-the-left for a livelier cadence. */
.millennium-motion-reveal {
	opacity: 0;
	transform: translateY(20px);
	transition:
		opacity 0.8s cubic-bezier(0.16, 1, 0.3, 1),
		transform 0.8s cubic-bezier(0.16, 1, 0.3, 1);
	will-change: opacity, transform;
}

.millennium-motion-reveal--lateral {
	transform: translateX(-24px);
}

.millennium-motion-reveal.is-in-view {
	opacity: 1;
	transform: none;
	will-change: auto;
}

/* Card stagger: once a revealed section is in view, its child cards
 * animate in with a per-card delay based on --millennium-stagger-i. */
.millennium-motion-reveal.is-in-view .is-style-millennium-card {
	animation: millennium-fade-up 0.6s cubic-bezier(0.16, 1, 0.3, 1) both;
	animation-delay: calc( var( --millennium-stagger-i, 0 ) * 80ms );
}

/* Icon stroke-draw is now driven from JS so the property change is
 * reliably observed by the browser regardless of when classes flip.
 * See millennium-motion.js for the timing; nothing for icons lives in
 * CSS anymore (other than the reduced-motion guard at the bottom). */

/* Scrolled header: firm up the backdrop tint once the user has scrolled past
 * the hero. The logo stays full size — the client asked that it not shrink on
 * scroll — so only the background tint changes (the sticky header stays). */
.millennium-header {
	transition: background-color 0.3s ease, border-color 0.3s ease, padding 0.3s ease;
}

body.is-scrolled .millennium-header {
	background-color: color-mix(in srgb, var(--wp--preset--color--base) 94%, transparent);
}

/* Respect reduced-motion preferences. */
@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}

	.is-style-millennium-card,
	.wp-element-button,
	.wp-block-button__link {
		transition: none;
	}

	.is-style-millennium-glow > *,
	.is-style-millennium-glow > * > *,
	.is-style-millennium-glow::before,
	.millennium-motion-reveal,
	.millennium-motion-reveal.is-in-view,
	.millennium-motion-reveal.is-in-view .is-style-millennium-card,
	.millennium-header {
		animation: none !important;
		transition: none !important;
		opacity: 1 !important;
		transform: none !important;
	}

	/* Logo img keeps its static scale(1.15) — only animation /
	 * transition / opacity are reset, not transform. */
	.millennium-header .millennium-logo img {
		animation: none !important;
		transition: none !important;
		opacity: 1 !important;
	}
}

/* ---------- Header search ----------
 * The core/search block is configured with buttonPosition=button-only +
 * buttonUseIcon=true, so it ships as a single magnifier icon that
 * expands to reveal the input when clicked (WordPress wires the click
 * handler automatically). These rules just dress the chrome to match
 * the dark header — icon button on a transparent base, pill-shaped
 * input in the same surface-2 color used elsewhere. */

.millennium-header-search.wp-block-search {
	margin: 0;
}

.millennium-header-search .wp-block-search__button {
	background: transparent;
	color: var(--wp--preset--color--contrast);
	border: 1px solid transparent;
	border-radius: 999px;
	width: 36px;
	height: 36px;
	padding: 6px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	transition: background-color 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}

.millennium-header-search .wp-block-search__button:hover,
.millennium-header-search .wp-block-search__button:focus-visible {
	background-color: rgba(255, 255, 255, 0.06);
	border-color: var(--wp--preset--color--border);
	color: var(--wp--preset--color--primary);
}

.millennium-header-search .wp-block-search__button svg {
	fill: currentColor;
	width: 20px;
	height: 20px;
}

.millennium-header-search .wp-block-search__input {
	background-color: var(--wp--preset--color--surface-2);
	color: var(--wp--preset--color--contrast);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 999px;
	padding: 8px 16px;
	width: 240px;
	min-width: 0;
	font-size: 0.95rem;
	/* Multi-property transition for the slide-open animation triggered
	 * by the core/search button click. WP toggles
	 * .wp-block-search__searchfield-hidden (on the input in older WP,
	 * on the form in newer WP) — both selectors are handled below. */
	transition:
		width 0.30s cubic-bezier(0.4, 0.0, 0.2, 1),
		padding 0.30s cubic-bezier(0.4, 0.0, 0.2, 1),
		opacity 0.20s ease 0.05s,
		border-color 0.18s ease;
}

/* Collapsed state. Override WP core's screen-reader-style hiding
 * (position: absolute + clip + width: 1px), because clip and
 * position changes don't transition smoothly. Replace it with a
 * width/padding/opacity collapse that the transition above can
 * interpolate, so the pill slides out from the icon instead of
 * popping into existence. */
.millennium-header-search .wp-block-search__input.wp-block-search__searchfield-hidden,
.millennium-header-search.wp-block-search__searchfield-hidden .wp-block-search__input {
	width: 0;
	min-width: 0;
	padding-left: 0;
	padding-right: 0;
	opacity: 0;
	border-color: transparent;
	position: static;
	clip: auto;
	height: auto;
	margin: 0;
	overflow: hidden;
}

.millennium-header-search .wp-block-search__input:focus {
	outline: none;
	border-color: var(--wp--preset--color--primary);
}

.millennium-header-search .wp-block-search__input::placeholder {
	color: var(--wp--preset--color--muted);
}

/* Tighten the expanded input on smaller desktops so it doesn't shove
 * the Contact CTA off the row. */
@media (max-width: 1023px) {
	.millennium-header-search .wp-block-search__input {
		width: 160px;
	}
}

/* ---------- Search results — post-type eyebrow label ----------
 * Rendered by the [millennium_post_type_label] shortcode in
 * templates/search.html. Gives each result an at-a-glance "PRODUCT",
 * "PAGE", or "NEWS" tag in the cyan accent so visitors can tell what
 * kind of thing they're about to click. */

.millennium-result-type {
	display: inline-block;
	font-size: 0.72rem;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--wp--preset--color--primary);
	margin-bottom: 0.4rem;
}


/* Other Products page: centered flex-wrap so a trailing partial row
 * (e.g. the last 2 placeholder boxes) centers instead of left-aligning in a
 * fixed 3-column grid. Three across on desktop; full-width stacked on mobile. */
.millennium-otherprod-grid {
	display: flex !important;
	flex-wrap: wrap;
	justify-content: center;
}

.millennium-otherprod-grid > * {
	flex: 0 1 calc((100% - 2 * var(--wp--preset--spacing--50)) / 3);
}

@media (max-width: 781px) {
	.millennium-otherprod-grid > * {
		flex-basis: 100%;
	}
}


/* Hide the Featured Image on the single view of the "Tech-Forward in
 * Beachwood, Ohio" news post (id 409). body.postid-409 is only on that
 * post's own page, so the News listing thumbnail is unaffected. */
.postid-409 .wp-block-post-featured-image {
	display: none;
}


/* Tech-Forward news post (id 409): Issuu flipbook fills full content width,
 * keeping aspect ratio (responsive). */
.postid-409 .wp-block-embed iframe {
	width: 100% !important;
	height: auto !important;
	aspect-ratio: 500 / 383;
}


/* Mobile nav overlay (open menu): collapsible dropdowns.
 * The overlay shows only the four top-level sections (Products, Services,
 * Markets, About); each is a real link plus a chevron. Tapping the chevron
 * expands that section's children inline (native core/navigation toggle —
 * we just reveal the submenu that WordPress already marks aria-expanded),
 * so nothing runs off-screen the way the old flat list of every link did.
 * Every rule is scoped to .is-menu-open, which only the mobile hamburger
 * sets, so the DESKTOP nav (hover-to-open, top-level items still direct
 * links) is completely unaffected. Also constrains the fixed container to
 * the viewport (it rendered wider than the screen, pushing items off-center). */
.wp-block-navigation__responsive-container.is-menu-open {
	left: 0 !important;
	right: 0 !important;
	width: auto !important;
	box-sizing: border-box;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content {
	align-items: center !important;
	justify-content: flex-start !important;
	width: auto !important;
	margin: 0 !important;
	padding: 40px 16px 32px !important;
	box-sizing: border-box;
	overflow-y: auto;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container {
	gap: 22px !important;
	align-items: center !important;
	justify-content: flex-start !important;
	text-align: center;
	width: 100%;
}

/* Each section is a centered block; its label + chevron sit inline on one line,
 * the submenu drops below when expanded. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item.has-child {
	display: block !important;
	text-align: center;
	margin: 0 !important;
	width: 100%;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item.has-child > .wp-block-navigation-item__content {
	display: inline !important;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
	font-size: 1.5rem !important;
	line-height: 1.15 !important;
	padding: 2px 4px !important;
}

/* Reveal the expand/collapse chevron (core hides it in the overlay) and make it
 * a comfortable tap target. The chevron is a stroked SVG path, so it needs
 * `stroke`, not `fill`. Rotates 180° when its section is open. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-icon {
	display: inline-flex !important;
	vertical-align: middle;
	align-items: center;
	justify-content: center;
	width: auto !important;
	height: auto !important;
	margin: 0 0 0 4px !important;
	padding: 4px !important;
	transition: transform 0.2s ease;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-icon svg {
	width: 18px !important;
	height: 18px !important;
	display: block;
	flex: none;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-icon svg path {
	stroke: currentColor;
	stroke-width: 1.8;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-icon[aria-expanded="true"] {
	transform: rotate(180deg);
}

/* Collapse every submenu by default; reveal only the section whose chevron
 * WordPress has marked expanded. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container {
	display: none !important;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-icon[aria-expanded="true"] + .wp-block-navigation__submenu-container {
	display: flex !important;
	flex-direction: column;
	position: static !important;
	align-items: center !important;
	gap: 2px;
	margin: 8px 0 2px !important;
	padding: 0 !important;
	background: transparent !important;
	border: 0 !important;
	min-width: 0 !important;
	box-shadow: none !important;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
	font-size: 1.1rem !important;
	opacity: 0.82;
	padding: 5px 4px !important;
}

/* "Overview" links: mobile overlay menu only. In the desktop hover dropdown the
 * top-level item already links to the section landing page, so the extra
 * "… Overview" row is redundant there — hide it. Keep it in the mobile overlay,
 * where tapping the section header only expands (never navigates), so the
 * landing page needs its own tappable row. */
.wp-block-navigation-item.millennium-overview-link {
	display: none;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item.millennium-overview-link {
	display: block;
}
