/* ============================================================
   NovemBit — dark-committed brand world.
   Design tokens live in theme.json; this sheet aliases them to
   short names and carries the structural work that presets and
   block supports cannot express: the engineering grid, hairline
   card fields, glows, decorative art and the contact panel.
   ============================================================ */

:root {
	--void: var(--wp--preset--color--void);
	--panel: var(--wp--preset--color--panel);
	--panel-hi: var(--wp--preset--color--panel-hi);
	--ivory: var(--wp--preset--color--ivory);
	--slate: var(--wp--preset--color--slate);
	--slate-dim: var(--wp--preset--color--slate-dim);
	--pulse: var(--wp--preset--color--pulse);
	--ember: var(--wp--preset--color--ember);
	--ink: var(--wp--preset--color--ink);

	--pulse-rgb: var(--wp--custom--pulse-rgb);
	--ember-rgb: var(--wp--custom--ember-rgb);
	--stroke: var(--wp--custom--stroke);
	--stroke-hi: var(--wp--custom--stroke-hi);

	--display: var(--wp--preset--font-family--display);
	--body: var(--wp--preset--font-family--body);
	--mono: var(--wp--preset--font-family--mono);

	--r-xs: var(--wp--custom--radius--xs);
	--r-sm: var(--wp--custom--radius--sm);
	--r-md: var(--wp--custom--radius--md);
	--r-lg: var(--wp--custom--radius--lg);
	--r-pill: var(--wp--custom--radius--pill);

	--max: var(--wp--style--global--content-size, 1320px);
	--rail: var(--wp--custom--rail);
	--pad: var(--wp--custom--pad);
	--sec: var(--wp--custom--section);

	--nb-arrow: url('data:image/svg+xml;utf8,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2024%2024%22%3E%3Cpath%20d=%22M2.5%2012H21M13.5%204.5L21%2012l-7.5%207.5%22%20fill=%22none%22%20stroke=%22%23000%22%20stroke-width=%223%22%20stroke-linecap=%22butt%22%20stroke-linejoin=%22miter%22/%3E%3C/svg%3E');
	--nb-arrow-thin: url('data:image/svg+xml;utf8,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2024%2024%22%3E%3Cpath%20d=%22M2.5%2012H21M13.5%204.5L21%2012l-7.5%207.5%22%20fill=%22none%22%20stroke=%22%23000%22%20stroke-width=%222.3%22%20stroke-linecap=%22butt%22%20stroke-linejoin=%22miter%22/%3E%3C/svg%3E');
	--nb-ease: cubic-bezier(0.4, 0, 0.2, 1);
	--nb-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
}

html {
	color-scheme: dark;
	-webkit-text-size-adjust: 100%;
	scroll-behavior: smooth;
	scroll-padding-top: calc(var(--nb-header-h, 5rem) + 0.75rem);
	scrollbar-gutter: stable;
}

body {
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	-webkit-tap-highlight-color: transparent;
	overflow-x: hidden;
}

p,
li {
	text-wrap: pretty;
}

img {
	max-width: 100%;
	height: auto;
}

h1,
h2,
h3,
h4 {
	text-wrap: balance;
}

:focus-visible {
	outline: 2px solid var(--pulse);
	outline-offset: 3px;
	border-radius: var(--r-xs);
}

::selection {
	background: var(--pulse);
	color: var(--ink);
}

/* ------------------------------------------------------------
   BUTTONS — core/button, restyled to the brand's mono capsule.
   ------------------------------------------------------------ */
.wp-block-button__link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.6rem;
	min-height: 46px;
	white-space: nowrap;
	transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease,
		box-shadow 0.24s ease, transform 0.2s ease;
}

.wp-block-button__link:hover {
	transform: translateY(-1px);
	box-shadow: 0 6px 16px -12px rgba(var(--pulse-rgb), 0.45);
}

/* Pressing has to land somewhere: without this the lift stays up under the
   finger and the tap reads as if nothing happened. */
.wp-block-button__link:active {
	transform: translateY(0);
	box-shadow: none;
	transition-duration: 0.06s;
}

.wp-block-button.is-style-outline > .wp-block-button__link {
	background: transparent;
	border-color: var(--stroke-hi);
	color: var(--ivory);
	font-weight: 500;
}

.wp-block-button.is-style-outline > .wp-block-button__link:hover,
.wp-block-button.is-style-outline > .wp-block-button__link:focus {
	background: rgba(var(--pulse-rgb), 0.08);
	border-color: var(--pulse);
	color: var(--pulse);
	box-shadow: none;
	transform: none;
}

/* "With arrow" button style — the glyph is CSS so the block's text
   attribute stays plain and survives round-trips through the editor.

   JetBrains Mono draws its arrow far lighter than its bold letterforms, so
   next to 700-weight capitals the glyph read as a stray mark. The arrow is
   drawn instead, at a stroke that matches the stems beside it, and painted
   through a mask so it still takes its colour from the text. */
/* The same arrow at the weight of body-sized mono rather than a 700 button
   capital: one stroke width does not serve both. */
.nb-arrow-link {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
}

.wp-block-button.is-style-nb-arrow > .wp-block-button__link::after,
.nb-arrow-link::after {
	content: "\2192";
	transition: transform 0.2s ease;
}

.wp-block-button.is-style-nb-arrow > .wp-block-button__link:hover::after,
.nb-popup-trigger:hover .nb-arrow-link::after {
	transform: translateX(3px);
}

@supports (mask-image: linear-gradient(#000, #000)) {
	.wp-block-button.is-style-nb-arrow > .wp-block-button__link::after,
	.nb-arrow-link::after {
		content: "";
		width: 1em;
		height: 1em;
		flex: none;
		background: currentColor;
		-webkit-mask-image: var(--nb-arrow);
		mask-image: var(--nb-arrow);
		-webkit-mask-size: contain;
		mask-size: contain;
		-webkit-mask-position: center;
		mask-position: center;
		-webkit-mask-repeat: no-repeat;
		mask-repeat: no-repeat;
		transition: transform 0.24s cubic-bezier(0.2, 0.9, 0.3, 1);
	}

	.nb-arrow-link::after {
		-webkit-mask-image: var(--nb-arrow-thin);
		mask-image: var(--nb-arrow-thin);
	}

	.wp-block-button.is-style-nb-arrow > .wp-block-button__link:hover::after,
	.nb-popup-trigger:hover .nb-arrow-link::after {
		transform: translateX(4px);
	}
}

/* ------------------------------------------------------------
   TYPE UTILITIES — registered as block style variations.
   ------------------------------------------------------------ */
.is-style-nb-lead {
	font-size: var(--wp--preset--font-size--large);
	color: var(--slate);
	max-width: 56ch;
}

.is-style-nb-mono {
	font-family: var(--mono);
	font-size: var(--wp--preset--font-size--micro);
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--slate-dim);
	line-height: 1.4;
}

.is-style-nb-note {
	display: inline-flex;
	align-items: center;
	gap: 0.55rem;
	font-family: var(--mono);
	font-size: 0.62rem;
	letter-spacing: 0.13em;
	line-height: 1.5;
	text-transform: uppercase;
	color: var(--slate-dim);
	background: rgba(255, 255, 255, 0.022);
	border: 1px dashed rgba(255, 255, 255, 0.16);
	border-radius: var(--r-pill);
	padding: 0.4rem 0.9rem;
	align-self: flex-start;
	width: fit-content;
	max-width: 100%;
}

.is-style-nb-note::before {
	content: "";
	flex: none;
	width: 5px;
	height: 5px;
	border-radius: 50%;
	background: var(--ember);
	box-shadow: 0 0 0 3px rgba(var(--ember-rgb), 0.15);
}

.is-style-nb-ghost {
	font-family: var(--display);
	font-weight: 700;
	font-size: min(4.6rem, 17cqi);
	letter-spacing: -0.05em;
	line-height: 1;
	color: transparent;
	-webkit-text-stroke: 1px rgba(255, 255, 255, 0.11);
	margin-bottom: -0.42em;
	user-select: none;
	pointer-events: none;
}

.nb-mark {
	font-style: normal;
	font-weight: 700;
	color: var(--pulse);
}

/* Gradient rule under a CTA heading — core/separator style variation. */
.wp-block-separator.is-style-nb-rule {
	width: 74px;
	height: 2px;
	border: 0;
	background: linear-gradient(90deg, var(--pulse), var(--ember));
	border-radius: 2px;
	opacity: 1;
	margin-inline: auto;
}

/* ------------------------------------------------------------
   SECTION — the engineering grid: a sticky vertical rail label
   beside the content column, divided by hairlines.
   ------------------------------------------------------------ */
.nb-section {
	display: grid;
	grid-template-columns: var(--rail) minmax(0, 1fr);
	border-top: 1px solid var(--stroke);
	padding-block: var(--sec);
}

.nb-section > .nb-section__rail {
	position: relative;
}

.nb-section__label {
	position: sticky;
	top: 7.5rem;
	writing-mode: vertical-rl;
	transform: rotate(180deg);
	font-family: var(--mono);
	font-size: 0.7rem;
	letter-spacing: 0.28em;
	text-transform: uppercase;
	color: var(--slate-dim);
	white-space: nowrap;
	padding-block: 0.35rem;
	margin: 0;
}

.nb-section__label::after {
	content: "";
	position: absolute;
	left: 50%;
	bottom: -0.95rem;
	translate: -50% 0;
	width: 1px;
	height: 1.1rem;
	background: var(--pulse);
}

.nb-section > .nb-section__body {
	min-width: 0;
}

/* Below the gutter width the rail has nowhere to sit, but the label is how a
   section announces itself — so it lies down above the heading instead of
   disappearing, and the pulse tick turns into the rule beside it. */
@media (max-width: 820px) {
	.nb-section {
		grid-template-columns: minmax(0, 1fr);
	}

	.nb-section > .nb-section__rail {
		margin-bottom: 1.35rem;
	}

	.nb-section__label {
		position: static;
		writing-mode: horizontal-tb;
		transform: none;
		display: flex;
		align-items: center;
		gap: 0.7rem;
		font-size: 0.66rem;
		letter-spacing: 0.22em;
		padding-block: 0;
	}

	.nb-section__label::after {
		position: static;
		translate: none;
		width: 1.75rem;
		height: 1px;
	}
}

/* Section intro — heading plus a short note, held to a readable measure. */
.nb-head {
	max-width: 44ch;
}

/* ------------------------------------------------------------
   HAIRLINE FIELD — a joined grid of cards separated by 1px rules
   rather than gaps. The container paints the rule colour and the
   cells sit on top of it; set the block gap to 1px in the editor.
   ------------------------------------------------------------ */
.is-style-nb-hairline {
	background: var(--stroke);
	border: 1px solid var(--stroke);
	border-radius: var(--r-md);
	overflow: hidden;
}

.is-style-nb-hairline > * {
	background: var(--void);
}

.is-style-nb-hairline.has-panel-background-color > *,
.is-style-nb-hairline.nb-on-panel > * {
	background: var(--panel);
}

/* Nine services close as a clean 3×3. At two columns the last card
   spans both so no row is left holding a single orphan. */
@media (max-width: 980px) {
	.nb-grid-services {
		grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
	}

	.nb-grid-services > :last-child {
		grid-column: span 2;
	}
}

@media (max-width: 620px) {
	.nb-grid-services {
		grid-template-columns: minmax(0, 1fr) !important;
	}

	.nb-grid-services > :last-child {
		grid-column: auto;
	}
}

/* Service card — a pulse-to-ember bar wipes across the top on hover. */
.nb-card {
	position: relative;
	transition: background 0.24s ease;
}

.nb-card:hover {
	background: var(--panel);
}

.nb-card::before {
	content: "";
	position: absolute;
	inset: 0 auto auto 0;
	width: 0;
	height: 2px;
	background: linear-gradient(90deg, var(--pulse), var(--ember));
	transition: width 0.32s cubic-bezier(0.4, 0, 0.2, 1);
}

.nb-card:hover::before {
	width: 100%;
}

.nb-card__index {
	font-family: var(--mono);
	font-size: 0.68rem;
	letter-spacing: 0.14em;
	font-variant-numeric: tabular-nums;
	color: var(--slate-dim);
	margin: 0;
	transition: color 0.24s ease;
}

.nb-card:hover .nb-card__index {
	color: var(--slate);
}

/* The glyph alone floats in the corner; a hairline chip gives it a seat and
   somewhere for the hover to land. */
.nb-card .novembit-icon {
	width: 40px;
	height: 40px;
	align-items: center;
	justify-content: center;
	border: 1px solid var(--stroke);
	border-radius: var(--r-sm);
	background: rgba(255, 255, 255, 0.022);
	transition: border-color 0.24s ease, background 0.24s ease;
}

.nb-card:hover .novembit-icon {
	border-color: rgba(var(--pulse-rgb), 0.42);
	background: rgba(var(--pulse-rgb), 0.09);
}

/* ------------------------------------------------------------
   PANEL — a raised surface with a pulse wash in its top corner.
   ------------------------------------------------------------ */
.is-style-nb-panel {
	background:
		radial-gradient(120% 100% at 0% 0%, rgba(var(--pulse-rgb), 0.07), transparent 55%),
		var(--panel);
	border: 1px solid var(--stroke);
	border-radius: var(--r-lg);
}

/* ------------------------------------------------------------
   HERO — full-bleed. The decorative tile clusters are cropped on
   their outer edge by design and pinned flush to the viewport, so
   the cut tiles read as continuing off-screen.
   ------------------------------------------------------------ */
.nb-hero {
	position: relative;

	/* Only the horizontal crop is wanted: it is what cuts the tile clusters
	   off at the viewport edge. Clipping vertically as well severed the glow
	   at the hero's own top edge, leaving the band the sticky header sits in
	   flat black with a hard seam where the gradient began. Clipping one axis
	   needs `clip` — `hidden visible` computes back to `hidden auto` — so the
	   plain declaration stays ahead of it for browsers without it. */
	overflow: hidden;
	overflow: clip visible;
	isolation: isolate;
	/* Bounded by viewport height as well as width: on a wide but short
	   window 9vw alone is tall enough to push the hero past the fold. */
	padding-block: clamp(3rem, min(9vw, 10vh), 8.5rem)
		clamp(3rem, min(9vw, 10vh), 9rem);

	/* Fills what the sticky header leaves of the viewport. --nb-header-h is
	   measured in theme.js and already includes the admin bar's allowance;
	   the fallback covers the first paint and the no-JS case. min-height,
	   not height, so the stacked clusters can still push it taller on
	   narrow screens. */
	display: flex;
	flex-direction: column;
	justify-content: center;
	min-height: calc(100vh - var(--nb-header-h, 4.5rem));
	min-height: calc(100svh - var(--nb-header-h, 4.5rem));
}

.nb-hero::before {
	content: "";
	position: absolute;
	top: -40%;
	left: 50%;
	translate: -50% 0;
	width: min(64rem, 130vw);
	aspect-ratio: 1;
	background: radial-gradient(
		circle,
		rgba(var(--pulse-rgb), 0.17),
		rgba(var(--pulse-rgb), 0.05) 42%,
		transparent 66%
	);
	pointer-events: none;
	z-index: -1;
}

.nb-hero__copy {
	position: relative;
	max-width: 46rem;
	margin-inline: auto;
	text-align: center;
}

.nb-hero__copy .is-style-nb-lead {
	text-align: center;
	margin-inline: auto;
}

.nb-hero__copy h1 {
	max-width: 16ch;
	margin-inline: auto;
}

/* Three short lines beat four ragged ones on a phone. */
@media (max-width: 600px) {
	.nb-hero__copy h1 {
		max-width: 13ch;
	}

	.nb-hero__copy .is-style-nb-lead {
		max-width: 34ch;
	}
}

/* ------------------------------------------------------------
   CTA — the last lit surface before the page dissolves. The glow
   is painted as gradients sized to the section box rather than an
   oversized circle behind it, so there is no geometry to clip and
   it can never land as a straight edge. Its tail reaches down to
   exactly where the pixel band starts, and the band's own blocks
   carry the light on from there.
   ------------------------------------------------------------ */
.nb-cta {
	position: relative;
	isolation: isolate;
	text-align: center;
	padding-block: clamp(5rem, 10vw, 9rem) clamp(7rem, 14vw, 12.5rem);
	background:
		radial-gradient(
			64% 62% at 50% 52%,
			rgba(var(--pulse-rgb), 0.19),
			rgba(var(--ember-rgb), 0.055) 45%,
			transparent 82%
		),
		radial-gradient(
			34% 30% at 50% 34%,
			rgba(var(--pulse-rgb), 0.1),
			transparent 78%
		);
}

/* The opening hairline fades out before either edge, so the section
   reads as a horizon rather than the top of a box. */
.nb-cta::before {
	content: "";
	position: absolute;
	inset-block-start: 0;
	inset-inline: 0;
	height: 1px;
	background: linear-gradient(
		90deg,
		transparent,
		var(--stroke-hi) 28%,
		var(--stroke-hi) 72%,
		transparent
	);
	opacity: 0.4;
	pointer-events: none;
}

.nb-cta > * {
	position: relative;
	z-index: 1;
}

.nb-cta .is-style-nb-lead {
	text-align: center;
	margin-inline: auto;
}

/* ------------------------------------------------------------
   TESTIMONIALS
   ------------------------------------------------------------ */
.nb-testimonial-intro {
	position: relative;
	container-type: inline-size;
}

.nb-rating {
	display: flex;
	align-items: center;
	gap: 0.8rem;
	flex-wrap: wrap;
}

.nb-rating__text {
	font-family: var(--mono);
	font-size: 0.76rem;
	color: var(--slate);
	line-height: 1.4;
	margin: 0;
}

.nb-rating__text strong {
	color: var(--pulse);
	letter-spacing: 0.08em;
	font-weight: 700;
}

/* Beside a rating the mark is the proof, so it carries a little more weight
   here than it does on the footer's one-line credit. */
.nb-rating__text .nb-clutch-link {
	--nb-clutch-h: 1.35rem;
	margin-top: 0.3rem;
}

/* With the figure gone the stars are the rating, so they are sized to read as
   one rather than as punctuation beside it. */
.nb-rating__text .nb-clutch-stars {
	display: inline-block;
	font-size: 1rem;
	line-height: 1.2;
}

.nb-quote__name {
	font-size: 0.94rem;
	font-weight: 500;
	color: var(--ivory);
	margin: 0;
}

.nb-quote__role {
	font-size: 0.8rem;
	color: var(--slate-dim);
	margin: 0;
}

/* ------------------------------------------------------------
   QUOTE DRIFT — each quote is its own bordered card and the
   stack creeps upward through a masked viewport. The track
   carries a trailing pad the size of the gap so the doubled
   list is two exactly identical blocks, and -50% comes back
   round without a seam.
   ------------------------------------------------------------ */
.nb-quotes {
	--nb-quotes-h: clamp(24rem, 44vh, 32rem);
	--nb-quotes-dur: 58s;
	--nb-quotes-delay: 1.2s;
	--nb-quote-gap: 0.85rem;
}

@media (max-width: 781px) {
	.nb-quotes {
		--nb-quotes-h: clamp(21rem, 58vh, 27rem);
	}
}

/* The hairline field is for the joined services grid; on the drift stack it
   draws a rim around cards that already carry their own, on the same ground.
   Live content seeded before the class came off the pattern still asks for
   it, so the stack refuses it here. */
.nb-quotes.is-style-nb-hairline {
	background: none;
	border: 0;
	border-radius: 0;
	overflow: visible;
}

.nb-quotes.is-style-nb-hairline > * {
	background: none;
}

.nb-quotes__viewport {
	overflow: hidden;
}

.nb-quotes__track {
	display: flex;
	flex-direction: column;
	gap: var(--nb-quote-gap);
	padding-bottom: var(--nb-quote-gap);
}

.nb-quotes__track > .nb-quote {
	border: 1px solid var(--stroke);
	border-radius: var(--r-md);
	background: var(--panel);
	transition: border-color 0.24s ease;
}

/* The drift pauses on hover, so the card under the cursor can afford
   to answer. */
.nb-quotes__track > .nb-quote:hover {
	border-color: var(--stroke-hi);
}

html.nb-js:not(.nb-reduced) .nb-quotes__viewport {
	height: var(--nb-quotes-h);
	-webkit-mask-image: linear-gradient(
		to bottom,
		transparent 0,
		#000 10%,
		#000 90%,
		transparent 100%
	);
	mask-image: linear-gradient(
		to bottom,
		transparent 0,
		#000 10%,
		#000 90%,
		transparent 100%
	);
}

/* Linear, always: any easing curve makes a continuous loop visibly
   pulse once per cycle. The delay only spends itself on the first
   iteration, and a paused animation does not spend it at all, so the
   stack holds still until the block is revealed and then holds a beat
   longer — long enough to read the quote that was there on arrival. */
html.nb-js:not(.nb-reduced) .nb-quotes__track {
	animation: nb-quotes-drift var(--nb-quotes-dur) linear var(--nb-quotes-delay)
		infinite;
	will-change: transform;
}

html.nb-js:not(.nb-reduced) .nb-quotes.nb-reveal:not(.nb-in) .nb-quotes__track,
html.nb-js:not(.nb-reduced)
	.nb-quotes.is-style-nb-reveal:not(.nb-in)
	.nb-quotes__track {
	animation-play-state: paused;
}

html.nb-js:not(.nb-reduced) .nb-quotes:hover .nb-quotes__track,
html.nb-js:not(.nb-reduced) .nb-quotes:focus-within .nb-quotes__track {
	animation-play-state: paused;
}

@keyframes nb-quotes-drift {
	from {
		transform: translate3d(0, 0, 0);
	}

	to {
		transform: translate3d(0, -50%, 0);
	}
}

/* ------------------------------------------------------------
   HEADER
   ------------------------------------------------------------ */
.nb-header {
	/* The pill floats --nb-float clear of the viewport edge; --nb-pill-x is the
	   breathing room between its rim and the content. Adding pill-x to the
	   header's own inline padding is what buys that room: the pill is capped at
	   the content width plus twice pill-x, so the two stay in step at every
	   width instead of the capsule ballooning past the nav on wide screens. */
	--nb-float: 1.1rem;
	--nb-pill-x: clamp(0.9rem, 1.6vw, 1.65rem);
	--nb-pill-y: 0.72rem;

	padding-block: calc(var(--nb-float) + var(--nb-pill-y));
	z-index: 60;
}

.nb-header.has-global-padding {
	padding-inline: calc(var(--pad) + var(--nb-pill-x));
}

/* A sticky element can only travel inside its own parent's box, and the div
   the template part is rendered into is exactly as tall as the header — so
   the header stuck for zero pixels. Dropping the wrapper's box promotes the
   header to a child of the page column, which is what it has to stick
   against. The editor's own block wrapper keeps its box: it carries the
   selection and toolbar UI. */
.wp-site-blocks
	> .wp-block-template-part:has(> .nb-header):not(.block-editor-block-list__block) {
	display: contents;
}

/* The root layout drops a block gap after every top-level block, including
   the header part. The pill's float gap already separates it from what comes
   next, and the hero below is measured against the viewport, so that gap has
   to go. */
.wp-site-blocks > .wp-block-template-part:first-child + * {
	margin-block-start: 0;
}

/* The frosted ground is painted by a pseudo-element rather than the header
   itself: backdrop-filter would otherwise make the header a containing block
   for fixed positioning, trapping the mobile menu overlay inside it. */
.nb-header::before {
	content: "";
	position: absolute;
	top: var(--nb-float);
	bottom: var(--nb-float);
	left: var(--pad);
	right: var(--pad);
	max-width: calc(var(--max) + 2 * var(--nb-pill-x));
	margin-inline: auto;
	z-index: -1;
	border-radius: var(--r-lg);

	/* Glass: a tinted ground the page shows through, a top-weighted sheen for
	   the light-from-above read, a bright crescent on the upper rim for the
	   specular edge, a faint full rim to keep the capsule's shape against pale
	   content, and a soft cast underneath to lift it off the page. */
	background:
		linear-gradient(
			180deg,
			rgba(255, 255, 255, 0.085) 0%,
			rgba(255, 255, 255, 0.022) 45%,
			rgba(255, 255, 255, 0) 78%
		),
		rgba(10, 10, 13, 0.55);
	backdrop-filter: blur(20px) saturate(165%);
	-webkit-backdrop-filter: blur(20px) saturate(165%);
	box-shadow:
		inset 0 1px 0 rgba(255, 255, 255, 0.13),
		inset 0 0 0 1px rgba(255, 255, 255, 0.06),
		0 16px 34px -18px rgba(0, 0, 0, 0.85);
}

.nb-header .wp-block-navigation__container {
	gap: 1.9rem;
}

.nb-header .wp-block-navigation-item__content {
	position: relative;
	transition: color 0.18s ease;
}

.nb-header .wp-block-navigation-item__content::after {
	content: "";
	position: absolute;
	left: 0;
	bottom: -4px;
	width: 0;
	height: 1px;
	background: var(--pulse);
	transition: width 0.22s ease;
}

.nb-header .wp-block-navigation-item__content:hover {
	color: var(--ivory);
}

.nb-header .wp-block-navigation-item__content:hover::after {
	width: 100%;
}

.nb-header .wp-block-button__link {
	padding: 0.7rem 1.15rem;
	min-height: 42px;
}

/* Once the page has moved the pill has content behind it rather than the top
   of the hero, so the glass is darkened and its rim brought up. Nothing here
   changes the header's height: the hero is measured against it. */
html.nb-scrolled .nb-header::before {
	background:
		linear-gradient(
			180deg,
			rgba(255, 255, 255, 0.075) 0%,
			rgba(255, 255, 255, 0.018) 45%,
			rgba(255, 255, 255, 0) 78%
		),
		rgba(8, 8, 11, 0.74);
	box-shadow:
		inset 0 1px 0 rgba(255, 255, 255, 0.16),
		inset 0 0 0 1px rgba(255, 255, 255, 0.075),
		0 20px 42px -20px rgba(0, 0, 0, 0.95);
}

/* ------------------------------------------------------------
   NAVIGATION — inline row, and the overlay it collapses into.

   Core swaps the two at 600px, which is far below the width the
   four labels plus the logo and the call to action actually need:
   between 600 and roughly 840 the row wrapped onto a second line
   and the capsule grew lopsided around it. Both of core's
   min-width rules are therefore re-asserted up to the width where
   the row genuinely fits.
   ------------------------------------------------------------ */
@media (min-width: 600px) and (max-width: 899.98px) {
	.nb-header
		.wp-block-navigation__responsive-container:not(.hidden-by-default):not(
			.is-menu-open
		) {
		display: none;
	}

	.nb-header .wp-block-navigation__responsive-container-open:not(.always-shown) {
		display: flex;
	}
}

/* The row must never wrap even if a label is added later: it goes to the
   overlay instead. */
.nb-header .wp-block-navigation__responsive-container:not(.is-menu-open)
	.wp-block-navigation__container {
	flex-wrap: nowrap;
}

/* The toggle is a 44px target in its own right — as shipped it is a bare 24px
   glyph with no hit area and nothing separating it from the button beside it. */
.nb-header .wp-block-navigation__responsive-container-open {
	width: 42px;
	height: 42px;
	align-items: center;
	justify-content: center;
	border: 1px solid var(--stroke);
	border-radius: var(--r-sm);
	background: rgba(255, 255, 255, 0.025);
	color: var(--slate);
	transition: color 0.18s ease, border-color 0.18s ease, background 0.18s ease;
}

.nb-header .wp-block-navigation__responsive-container-open:hover {
	color: var(--ivory);
	border-color: var(--stroke-hi);
	background: rgba(255, 255, 255, 0.05);
}

.nb-header .wp-block-navigation__responsive-container-open svg {
	width: 20px;
	height: 20px;
}

/* ------------------------------------------------------------
   NAVIGATION OVERLAY — a full screen of its own rather than the
   default cluster of links in one corner. The list runs down the
   left under a numbered rail, each row a full-width target, over
   the same pulse wash the hero opens with.
   ------------------------------------------------------------ */
.wp-block-navigation__responsive-container.is-menu-open {
	padding: 0 !important;
	isolation: isolate;
}

.wp-block-navigation__responsive-container.is-menu-open::before {
	content: "";
	position: fixed;
	inset: 0;
	background:
		radial-gradient(
			85% 50% at 100% 0%,
			rgba(var(--pulse-rgb), 0.22),
			transparent 66%
		),
		radial-gradient(
			75% 45% at 0% 100%,
			rgba(var(--ember-rgb), 0.1),
			transparent 68%
		);
	pointer-events: none;
	z-index: -1;
}

.nb-header
	.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__responsive-close,
.nb-header
	.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__responsive-dialog {
	display: flex;
	flex-direction: column;
	flex: 1;
	min-height: 0;
}

.nb-header
	.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__responsive-container-content {
	flex: 1;
	align-items: stretch;
	justify-content: center;
	/* Matched top and bottom: the group is centred inside the padding box, so
	   an uneven pair reads as a group sitting off-centre on the screen. The top
	   figure is what clears the close button. */
	padding: calc(env(safe-area-inset-top) + 6.5rem) var(--pad)
		calc(env(safe-area-inset-bottom) + 6.5rem);
}

.nb-header
	.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__container {
	align-items: stretch;
	/* none, or the list grows to fill the screen it is supposed to sit in the
	   middle of and the rows collect at the top again. */
	flex: none;
	gap: 0 !important;
	counter-reset: nb-nav;
	width: 100%;
	max-width: 32rem;
}

.nb-header
	.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation-item {
	align-items: stretch;
	border-top: 1px solid var(--stroke);
	counter-increment: nb-nav;
}

.nb-header
	.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation-item:last-child {
	border-bottom: 1px solid var(--stroke);
}

.nb-header
	.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__responsive-container-content
	.wp-block-navigation-item__content {
	display: flex;
	align-items: baseline;
	gap: 1.1rem;
	font-family: var(--display);
	font-size: clamp(1.9rem, 9vw, 2.6rem);
	font-weight: 500;
	letter-spacing: -0.035em;
	line-height: 1;
	padding-block: clamp(0.95rem, 3.2vw, 1.35rem);
	transition: color 0.2s ease, padding-inline-start 0.28s var(--nb-ease-out, ease);
}

.nb-header
	.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation-item__content::before {
	content: counter(nb-nav, decimal-leading-zero);
	font-family: var(--mono);
	font-size: 0.66rem;
	font-weight: 500;
	letter-spacing: 0.16em;
	color: var(--slate-dim);
	flex: none;
	transition: color 0.2s ease;
}

.nb-header
	.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__responsive-container-content
	.wp-block-navigation-item__content:hover,
.nb-header
	.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__responsive-container-content
	.wp-block-navigation-item__content:focus-visible {
	color: var(--pulse);
	padding-inline-start: 0.55rem;
}

.nb-header
	.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation-item__content:hover::before {
	color: var(--pulse);
}

.nb-header
	.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation-item__content::after {
	display: none;
}

/* The row is the target, so the ring belongs around the row and not around the
   words inside it. */
.nb-header
	.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation-item__content:focus-visible {
	outline-offset: -2px;
	border-radius: var(--r-sm);
}

/* The close sits where the toggle was, dressed to match it. */
.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__responsive-container-close {
	position: absolute;
	top: calc(env(safe-area-inset-top) + 1.22rem);
	right: calc(var(--pad) + 0.5rem);
	width: 42px;
	height: 42px;
	display: flex;
	align-items: center;
	justify-content: center;
	border: 1px solid var(--stroke);
	border-radius: var(--r-sm);
	background: rgba(255, 255, 255, 0.025);
	color: var(--slate);
	transition: color 0.18s ease, border-color 0.18s ease, background 0.18s ease;
}

.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__responsive-container-close:hover {
	color: var(--ivory);
	border-color: var(--stroke-hi);
	background: rgba(255, 255, 255, 0.05);
}

.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__responsive-container-close svg {
	width: 18px;
	height: 18px;
}

/* Rows arrive one after another so the panel resolves rather than appears.
   The delay is per position, capped at the six rows a header menu can hold. */
html.nb-js:not(.nb-reduced)
	.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation-item {
	animation: nb-nav-in 0.5s cubic-bezier(0.16, 1, 0.3, 1) both;
}

html.nb-js:not(.nb-reduced)
	.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation-item:nth-child(1) {
	animation-delay: 0.04s;
}

html.nb-js:not(.nb-reduced)
	.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation-item:nth-child(2) {
	animation-delay: 0.09s;
}

html.nb-js:not(.nb-reduced)
	.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation-item:nth-child(3) {
	animation-delay: 0.14s;
}

html.nb-js:not(.nb-reduced)
	.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation-item:nth-child(4) {
	animation-delay: 0.19s;
}

html.nb-js:not(.nb-reduced)
	.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation-item:nth-child(n + 5) {
	animation-delay: 0.24s;
}

/* Standing details under the list, appended by the theme script — see the
   note there. Held to the list's own measure so the two share a left edge. */
/* The container is not hidden when the row is inline — core just lays it out
   in flow — so the footer has to opt out of every state but the overlay. */
.wp-block-navigation__responsive-container:not(.is-menu-open) .nb-navfoot {
	display: none;
}

.nb-navfoot {
	width: 100%;
	max-width: 32rem;
	margin-top: clamp(2.25rem, 7vw, 3.25rem);
	padding-top: 1.35rem;
	border-top: 1px solid var(--stroke);
}

.nb-navfoot__label {
	font-family: var(--mono);
	font-size: 0.62rem;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--slate-dim);
	margin: 0 0 0.4rem;
}

.nb-navfoot__mail {
	display: inline-flex;
	align-items: center;
	min-height: 34px;
	font-size: 1.02rem;
	color: var(--slate);
	text-decoration: none;
	transition: color 0.18s ease;
}

.nb-navfoot__mail:hover {
	color: var(--pulse);
}

html.nb-js:not(.nb-reduced)
	.wp-block-navigation__responsive-container.is-menu-open
	.nb-navfoot {
	animation: nb-nav-in 0.5s cubic-bezier(0.16, 1, 0.3, 1) 0.28s both;
}

@keyframes nb-nav-in {
	from {
		opacity: 0;
		transform: translateY(14px);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

/* Below the nav breakpoint the row is logo + menu toggle + call to action.
   The button's text cannot wrap, so the row's own gaps have to give first. */
@media (max-width: 899.98px) {
	.nb-header .wp-block-group {
		gap: 1rem;
	}
}

@media (max-width: 600px) {
	.nb-header {
		--nb-pill-x: 0.75rem;
	}

	.nb-header .wp-block-group {
		gap: 0.7rem;
	}

	.nb-header .wp-block-button__link {
		padding: 0.7rem 0.95rem;
		font-size: 0.74rem;
		letter-spacing: 0.06em;
	}
}

@media (max-width: 400px) {
	.nb-header .wp-block-button__link {
		padding: 0.65rem 0.8rem;
		font-size: 0.7rem;
		letter-spacing: 0.04em;
	}
}

/* ------------------------------------------------------------
   FOOTER
   ------------------------------------------------------------ */
.nb-footer {
	background: var(--panel);
	position: relative;
	z-index: 2;
}

.nb-footer__col a {
	color: var(--slate);
	transition: color 0.18s ease;
	width: fit-content;
	max-width: 100%;
}

.nb-footer__col a:hover {
	color: var(--pulse);
}

/* The column's link colour is meant for the text lists under each heading.
   The logo is a link too, and it keeps the brand colour the header gives it. */
.nb-footer__col .novembit-logo {
	color: var(--pulse);
}

/* Link rows in a stacked footer are the smallest targets on the page; on
   touch widths they get the height a thumb needs. */
@media (max-width: 781px) {
	.nb-footer__col p a {
		display: flex;
		align-items: center;
		min-height: 38px;
	}
}

.nb-footer__col p,
.nb-footer__col li {
	font-size: 0.94rem;
	color: var(--slate);
	margin: 0;
}

.nb-footer__col h5 {
	padding-bottom: 0.7rem;
	border-bottom: 1px solid var(--stroke);
	margin-bottom: 0.5rem;
}

.nb-footer__tagline {
	max-width: 24ch;
}

.nb-footer__clutch {
	display: flex;
	align-items: center;
	gap: 0.55rem;
	padding-top: 0.9rem;
	border-top: 1px solid var(--stroke);
	flex-wrap: wrap;
	width: 100%;
	font-family: var(--mono);
	font-size: 0.72rem;
	color: var(--slate-dim);
	margin: 0;
}

/* The line is short but its parts must never break mid-word. */
.nb-footer__clutch > *,
.nb-footer__clutch .nb-clutch-link > * {
	white-space: nowrap;
}

.nb-footer__clutch .nb-clutch-link {
	color: var(--slate-dim);
}

.nb-footer__clutch .nb-clutch-link:hover {
	color: var(--slate);
}

.nb-footer .wp-block-social-links .wp-social-link {
	background: transparent;
	border: 1px solid var(--stroke);
	border-radius: var(--r-sm);
	width: 40px;
	height: 40px;
	display: grid;
	place-items: center;
	color: var(--slate);
	transition: color 0.18s ease, border-color 0.18s ease, background 0.18s ease;
}

.nb-footer .wp-block-social-links .wp-social-link:hover {
	color: var(--pulse);
	border-color: rgba(var(--pulse-rgb), 0.5);
	background: rgba(var(--pulse-rgb), 0.08);
	transform: none;
}

.nb-footer .wp-block-social-links .wp-social-link svg {
	width: 15px;
	height: 15px;
	fill: currentColor;
}

.nb-footer__bottom {
	border-top: 1px solid var(--stroke);
	font-family: var(--mono);
	font-size: 0.74rem;
	letter-spacing: 0.06em;
	color: var(--slate-dim);
	padding-bottom: calc(2.25rem + env(safe-area-inset-bottom)) !important;
}

.nb-footer__bottom p {
	margin: 0;
}

.nb-footer__bottom .nb-popup-trigger p {
	transition: color 0.18s ease;
}

/* The script gives every trigger the button role and a tab stop; the ring has
   to land on the control rather than on the box the block wraps it in. */
.nb-popup-trigger [role="button"]:focus-visible {
	outline: 2px solid var(--pulse);
	outline-offset: 3px;
	border-radius: var(--r-sm);
}

.nb-footer__bottom .nb-popup-trigger:hover p {
	color: var(--pulse);
}

/* Stacked, the four columns run together as one long list; a rule between
   them keeps the groups legible without adding markup. */
@media (max-width: 781px) {
	.nb-footer .wp-block-columns {
		gap: 2.1rem !important;
	}

	.nb-footer__col + .nb-footer__col {
		padding-top: 1.9rem;
		border-top: 1px solid var(--stroke);
	}

	.nb-footer__col h5 {
		border-bottom: 0;
		padding-bottom: 0;
		margin-bottom: 0.15rem;
	}

	.nb-footer__bottom {
		row-gap: 0.9rem !important;
	}
}

/* ------------------------------------------------------------
   SEARCH & PAGINATION — core blocks the archive and search
   templates use. Neither carries enough block supports to reach
   the brand's field treatment, and untouched they render as a
   white box and two blue links on the dark ground.
   ------------------------------------------------------------ */
.wp-block-search__inside-wrapper {
	border: 1px solid var(--stroke-hi);
	border-radius: var(--r-sm);
	background: var(--panel);
	padding: 0.3rem;
	max-width: 34rem;
	transition: border-color 0.18s ease, box-shadow 0.18s ease;
}

.wp-block-search__inside-wrapper:focus-within {
	border-color: var(--pulse);
	box-shadow: 0 0 0 3px rgba(var(--pulse-rgb), 0.16);
}

.wp-block-search__input {
	background: transparent;
	border: 0;
	color: var(--ivory);
	font-family: var(--body);
	font-size: 1rem;
	padding: 0.55rem 0.75rem;
}

.wp-block-search__input::placeholder {
	color: var(--slate-dim);
}

.wp-block-search__input:focus {
	outline: none;
}

.wp-block-search__button {
	background: var(--pulse);
	color: var(--ink);
	border: 0;
	border-radius: calc(var(--r-sm) - 2px);
	font-family: var(--mono);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 700;
	letter-spacing: 0.09em;
	text-transform: uppercase;
	padding: 0.7rem 1.15rem;
	cursor: pointer;
	transition: background 0.18s ease;
}

.wp-block-search__button:hover {
	background: #ff3d6c;
}

.wp-block-query-pagination {
	font-family: var(--mono);
	font-size: 0.78rem;
	letter-spacing: 0.08em;
	padding-top: 1.4rem;
	border-top: 1px solid var(--stroke);
}

.wp-block-query-pagination a,
.wp-block-query-pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 40px;
	min-height: 40px;
	padding-inline: 0.5rem;
	border: 1px solid transparent;
	border-radius: var(--r-xs);
	color: var(--slate);
	transition: color 0.18s ease, border-color 0.18s ease;
}

.wp-block-query-pagination a:hover {
	color: var(--ivory);
	border-color: var(--stroke-hi);
}

.wp-block-query-pagination .page-numbers.current {
	color: var(--pulse);
	border-color: rgba(var(--pulse-rgb), 0.45);
}

/* ------------------------------------------------------------
   CLUTCH — the review badge, linking to the profile the rating
   comes from. Official geometry, taken from the mark Clutch
   serves itself; only the wordmark is reversed out for the dark
   ground, and the dot keeps the brand red.
   ------------------------------------------------------------ */
.nb-clutch {
	display: inline-block;
	flex: none;
	width: calc(var(--nb-clutch-h, 1.05rem) * 3.528);
	height: var(--nb-clutch-h, 1.05rem);
	background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20405.7%20115%22%3E%3Ccircle%20cx%3D%22299.2%22%20cy%3D%2275.3%22%20r%3D%2213.3%22%20fill%3D%22%23E62415%22%2F%3E%3Cpath%20fill%3D%22%23F2F2F0%22%20d%3D%22M105.6%200h17.6v113.5h-17.6V0zm81.7%2078.5c0%2017.6-14.4%2019-18.8%2019-11%200-12.6-10.3-12.6-16.5V37.1h-17.7v43.8c-.1%2010.9%203%2019.9%209%2025.9a32.1%2032.1%200%200040.1%202.1v4.6H205V37.1h-17.7v41.4zm55.9-67.1h-17.7v25.7h-12.3v16.7h12.3v59.7h17.7V53.8h14.5V37.1h-14.5V11.4zM315%2091.8c-4%203.6-9.3%205.6-15.1%205.6a21.6%2021.6%200%2001-22.2-22.3c0-12.9%209.1-21.9%2022.2-21.9%205.7%200%2011.1%201.9%2015.2%205.5l2.8%202.4%2012.4-12.4-3.1-2.8a40.6%2040.6%200%2000-27.3-10.3c-23%200-39.7%2016.6-39.7%2039.4a39%2039%200%200039.7%2039.9c10.5%200%2020.3-3.7%2027.5-10.4l3-2.8-12.6-12.4-2.8%202.5zm81.7-48a32.1%2032.1%200%2000-40.1-2.1V0h-17.7v113.5h17.7V72.2c0-17.6%2014.4-19%2018.8-19%2011%200%2012.6%2010.3%2012.6%2016.5v43.9h17.7V69.7a36%2036%200%2000-9-25.9zM79.5%2086.3A36.7%2036.7%200%200153%2097.4c-20.5%200-35.4-16.1-35.4-38.2C17.6%2037%2032.5%2020.9%2053%2020.9c9.9%200%2019.3%203.9%2026.4%2011l2.8%202.8%2012.3-12.3-2.7-2.8A54.2%2054.2%200%200052.9%203.4C22.8%203.4%200%2027.4%200%2059.3%200%2091%2022.8%20115%2052.9%20115c14.9%200%2028.7-5.8%2038.9-16.3l2.7-2.8-12.2-12.5-2.8%202.9z%22%2F%3E%3C%2Fsvg%3E");
	background-repeat: no-repeat;
	background-position: center;
	background-size: contain;
	vertical-align: -0.16em;
	transition: opacity 0.18s ease;
}

.nb-clutch-link {
	display: inline-flex;
	align-items: center;
	gap: 0.55rem;
	flex-wrap: wrap;
}

.nb-clutch-link:hover .nb-clutch {
	opacity: 0.75;
}

.nb-clutch-stars {
	color: var(--pulse);
	letter-spacing: 0.12em;
	font-size: 0.86rem;
}

/* Utility the theme was leaning on without defining: the plugin scopes its
   own copy to the logo block, so anything else using it fell back to nothing. */
.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	border: 0;
	white-space: nowrap;
}

/* ------------------------------------------------------------
   REVEAL — opt in per block with the "Reveal on scroll" style.
   ------------------------------------------------------------ */
html.nb-js:not(.nb-reduced) .nb-reveal,
html.nb-js:not(.nb-reduced) .is-style-nb-reveal {
	opacity: 0;
	transform: translateY(14px);
	transition: opacity 0.6s cubic-bezier(0.2, 0.6, 0.2, 1),
		transform 0.6s cubic-bezier(0.2, 0.6, 0.2, 1);
}

html.nb-js:not(.nb-reduced) .nb-reveal.nb-in,
html.nb-js:not(.nb-reduced) .is-style-nb-reveal.nb-in {
	opacity: 1;
	transform: none;
}

/* ------------------------------------------------------------
   CONTACT PANEL — an XPAC popup (lightbox, right) dressed as an
   ivory panel sliding over the dark site. Light surface tokens are
   scoped to the panel only.

   XPAC's own rules are nested under .xpac-popup, so every override
   here carries that class too: matching their specificity and
   loading later is what makes these win.
   ------------------------------------------------------------ */
.xpac-popup.nb-contact-panel {
	/* The one light surface on a dark-committed site, and the only place the
	   browser needs telling — everything it renders itself in here has to flip
	   with the panel, not with the page behind it. */
	color-scheme: light;

	--cu-bg: #f1f1f1;
	--cu-ink: #141414;
	--cu-muted: #6a6a72;
	--cu-line: rgba(20, 20, 20, 0.42);
	--cu-field: #ffffff;

	--xpac-pp-space-x: 0;
	--xpac-pp-space-y: 0;
	--xpac-pp-shadow: none;
	--xpac-pp-close-top: 1.15rem;
	--xpac-pp-close-right: clamp(1.15rem, 4vw, 2.75rem);

	/* The cross is two rotated bars the plugin paints from these: -size is the
	   bar's thickness and -height its length. The default length filled the chip
	   rim to rim, so it is cut back to something that sits inside it. The hover
	   colour is the bar's, not the chip's — pulse on both is what made the cross
	   vanish the moment the cursor arrived. */
	--xpac-pp-close-size: 1.5px;
	--xpac-pp-close-height: 15px;
	--xpac-pp-close-color: #141414;
	--xpac-pp-close-hover-color: #ffffff;
	--xpac-pp-container-bg: var(--cu-bg);
	--xpac-pp-container-padd: 0;
	--xpac-pp-container-color: var(--cu-ink);

	box-shadow: none;
}

.xpac-popup.nb-contact-panel.has-xpac-place-right {
	top: 0;
	right: 0;
	left: auto;
	height: 100%;
	width: min(660px, 100%);
	max-width: 100%;
	max-height: 100%;
	animation: nb-panel-in 0.9s cubic-bezier(0.76, 0, 0.12, 1) both;
}

@keyframes nb-panel-in {
	from {
		transform: translateX(calc(100% + 14vw));
	}
	to {
		transform: none;
	}
}

/* XPAC removes the panel from the DOM the instant it closes, so the slide in
   had nothing going the other way — the panel simply blinked out. The script
   leaves a still copy behind while the real node goes; what follows is what
   that copy plays on its way off screen. */
.nb-panel-ghost,
.nb-overlay-ghost {
	pointer-events: none;
}

/* The place-right rule centres the panel with a -50% of its own height, and
   only the slide in's resting frame was cancelling it out. Naming both ends
   here keeps the exit on one axis — inherit that -50% as the starting frame
   and the panel drifts upward as it leaves. */
.xpac-popup.nb-contact-panel.has-xpac-place-right.nb-panel-ghost {
	animation: nb-panel-out 0.52s cubic-bezier(0.55, 0, 0.85, 0.25) both;
}

/* The overlay copy cannot keep the plugin's own class: closing ends by
   removing every element carrying it, which took the copy with it. It is
   dressed here instead, from the same custom properties. */
.nb-overlay-ghost {
	position: fixed;
	inset: 0;
	z-index: var(--xpac-pp-overlay-zindex);
	background: var(--xpac-pp-overlay-bg, rgba(4, 4, 6, 0.66));
	-webkit-backdrop-filter: blur(20px);
	backdrop-filter: blur(20px);
}

/* The staircase edge is painted by a keyframe sequence rather than a static
   rule, so cancelling the animation would leave it unmasked — a solid slab
   riding out alongside the panel. It holds the frame the sequence rests on. */
.xpac-popup.nb-contact-panel.nb-panel-ghost::before {
	animation: none;
	-webkit-mask-image: var(--nb-stair-1);
	mask-image: var(--nb-stair-1);
}

.nb-overlay-ghost {
	animation: nb-overlay-out 0.52s ease both;
}

@keyframes nb-panel-out {
	from {
		transform: none;
	}
	to {
		transform: translateX(calc(100% + 14vw));
	}
}

@keyframes nb-overlay-out {
	to {
		opacity: 0;
	}
}

.xpac-popup.nb-contact-panel .xpac-popup-wrap {
	height: 100%;
	max-height: 100%;
	/* The staircase edge hangs outside the panel, and the inner body owns the
	   scrolling — so this wrapper must not clip or scroll anything. */
	overflow: visible;
}

.xpac-popup.nb-contact-panel .xpac-popup-container {
	position: relative;
	height: 100%;
	max-height: 100%;
	padding: 0;
	background: var(--cu-bg);
	color: var(--cu-ink);
	display: flex;
	flex-direction: column;
}

.xpac-popup.nb-contact-panel .xpac-popup-inner {
	padding: clamp(3.5rem, 8vw, 4.75rem) clamp(1.35rem, 4vw, 2.75rem)
		calc(clamp(1.5rem, 4vw, 2.5rem) + env(safe-area-inset-bottom));
	overflow-y: auto;
	overscroll-behavior: contain;
	flex: 1;
}

/* The close floats over a body that scrolls underneath it, so it needs its
   own ground — as shipped the form's first field slid straight through it. */
.xpac-popup.nb-contact-panel .xpac-popup-close {
	z-index: 3;
	width: 42px;
	height: 42px;
	display: grid;
	place-items: center;
	padding: 0;
	border: 1px solid rgba(20, 20, 20, 0.12);
	border-radius: 50%;
	background: var(--cu-bg);
	box-shadow: 0 8px 22px -10px rgba(20, 20, 20, 0.45);
	transition: background 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}

.xpac-popup.nb-contact-panel .xpac-popup-close:hover,
.xpac-popup.nb-contact-panel .xpac-popup-close:focus-visible {
	background: var(--pulse);
	border-color: var(--pulse);
	color: #fff;
}

/* The bars are placed with maths against the plugin's own default box width,
   which no longer matches the chip — so they are centred outright instead. The
   rotation has to be restated, since it rides on the same transform. */
.xpac-popup.nb-contact-panel .xpac-popup-close::before,
.xpac-popup.nb-contact-panel .xpac-popup-close::after {
	left: 50%;
	border-radius: 1px;
}

.xpac-popup.nb-contact-panel .xpac-popup-close::before {
	transform: translate(-50%, -50%) rotate(45deg);
}

.xpac-popup.nb-contact-panel .xpac-popup-close::after {
	transform: translate(-50%, -50%) rotate(-45deg);
}

.xpac-popup.nb-contact-panel .xpac-popup-close:focus-visible {
	outline: 2px solid var(--pulse);
	outline-offset: 3px;
}

/* Pixel staircase carried over from the current build: a 37.5px block
   edge that dissolves the panel into the page behind it. It hangs off the
   panel root, the only ancestor that does not clip. */
.xpac-popup.nb-contact-panel::before {
	content: "";
	position: absolute;
	top: 0;
	left: 1px;
	height: 100%;
	width: min(188px, 20.9vh);
	translate: -100% 0;
	background: var(--cu-bg);
	pointer-events: none;
	-webkit-mask-size: 100% 100%;
	mask-size: 100% 100%;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	animation: nb-stair 1.2s steps(1, end) 1 both;
}

@media (max-width: 860px) {
	.xpac-popup.nb-contact-panel::before {
		display: none;
	}

	.xpac-popup.nb-contact-panel.has-xpac-place-right {
		width: 100%;
	}
}

.xpac-popup-overlay {
	--xpac-pp-overlay-bg: rgba(4, 4, 6, 0.66);
	backdrop-filter: blur(20px);
	-webkit-backdrop-filter: blur(20px);
}

/* Panel typography sits on the light ground. */
/* The 14ch cap is what breaks the heading over two lines. It also makes the
   heading the one box in the panel narrower than its column, and the
   constrained layout centres every child it is given slack on — so the cap
   alone had it sitting inset from the copy and fields beneath it. That
   centring is core's `margin-inline: auto !important`, which no amount of
   specificity answers; countering it in kind is the only way to pin the
   heading to the same edge as everything under it. */
.nb-contact-panel h2 {
	color: var(--pulse);
	font-size: clamp(1.9rem, 1.2rem + 2.2vw, 2.9rem);
	max-width: 14ch;
	margin-inline: 0 !important;
}

.nb-contact-panel h3,
.nb-contact-panel h4 {
	color: var(--cu-ink);
}

.nb-contact-panel .is-style-nb-lead {
	color: var(--cu-muted);
	font-size: 1.04rem;
	max-width: 46ch;
}

.nb-contact-panel .is-style-nb-mono {
	color: var(--cu-muted);
	border-top: 1px solid rgba(20, 20, 20, 0.14);
	padding-top: 1rem;
	letter-spacing: 0.06em;
	text-transform: none;
	font-size: 0.72rem;
	line-height: 1.75;
}

.nb-contact-panel .is-style-nb-mono a {
	color: var(--cu-ink);
	text-decoration: underline;
	text-underline-offset: 2px;
}

/* ------------------------------------------------------------
   XPAC FORM — colour, size and spacing come from the
   settings.custom.xpForm tokens in theme.json, which resolve
   against --cu-* inside the contact panel and against the dark
   palette anywhere else. Only what those tokens cannot express
   lives here.
   ------------------------------------------------------------ */
.xp-block-form {
	display: flex;
	flex-direction: column;
	gap: 1.15rem;
}

.xp-block-form .wp-block-columns {
	gap: 1.15rem;
	margin-bottom: 0;
}

.xp-block-form-field {
	display: flex;
	flex-direction: column;
}

.xp-block-form-field__label,
.xp-block-form-field__description,
.xp-block-form-field__validation {
	font-family: var(--mono);
}

.xp-block-form-field__label {
	letter-spacing: 0.16em;
	text-transform: uppercase;
}

/* A field the browser recognises is painted by the browser: background-color
   is ignored on an autofilled control, and the colour it chooses comes from the
   page's scheme rather than the panel's — which is what put a black box on the
   light ground for Name and Company but not Email. An inset shadow is the only
   thing that repaints that ground, and text-fill-color the only thing that
   recolours the text. Both read the form tokens, so they resolve light in the
   panel and dark outside it. */
.xp-block-form input:-webkit-autofill,
.xp-block-form input:-webkit-autofill:hover,
.xp-block-form input:-webkit-autofill:active,
.xp-block-form textarea:-webkit-autofill,
.xp-block-form select:-webkit-autofill {
	-webkit-box-shadow: 0 0 0 100px var(--wp--custom--xp-form--input-bg-color) inset;
	box-shadow: 0 0 0 100px var(--wp--custom--xp-form--input-bg-color) inset;
	-webkit-text-fill-color: var(--wp--custom--xp-form--input-color);
	caret-color: var(--wp--custom--xp-form--input-color);
}

/* Focus used to stack a ring on top of this fill; the field now marks focus
   with its border alone, so the fill is all that is left to carry over. It
   still has to be restated here — the focus rule would otherwise drop the
   inset fill and hand the autofilled field back to the browser's colour. */
.xp-block-form input:-webkit-autofill:focus,
.xp-block-form textarea:-webkit-autofill:focus,
.xp-block-form select:-webkit-autofill:focus {
	-webkit-box-shadow: 0 0 0 100px var(--wp--custom--xp-form--input-bg-color)
		inset;
	box-shadow: 0 0 0 100px var(--wp--custom--xp-form--input-bg-color) inset;
	-webkit-text-fill-color: var(--wp--custom--xp-form--input-color);
}

.xp-block-form-field.xp-block-form-field--textarea textarea {
	height: auto;
	min-height: 7rem;
	resize: vertical;
}

/* Safari on iOS zooms the page whenever a field it is focusing sits below
   16px, and the panel has no way back out of that zoom. The fields are set
   below it for the sake of the panel's scale, so the full 16px is handed
   back wherever the input is a touch one and the zoom would trigger. */
@media (pointer: coarse) {
	.xp-block-form {
		--wp--custom--xp-form--input-font-size: 1rem;
	}
}

/* With the focus ring gone the border is the whole signal, and a hairline
   changing colour was too quiet to catch. It doubles on focus instead —
   the field is border-box but its height is its content's, so the second
   pixel would push the field down and shove the text across. The padding
   gives that pixel back on each side, and nothing moves. The two lengths
   are the input-padding pair from theme.json; they travel together. */
.xp-block-form .xp-block-form-field.xp-block-form-field--input input:focus,
.xp-block-form
	.xp-block-form-field.xp-block-form-field--textarea
	textarea:focus {
	border-width: 2px;
	padding: calc(0.8rem - 1px) calc(0.9rem - 1px);
}

/* Choices as chips — the label carries the whole affordance, so the
   native control is taken out of flow rather than hidden outright.

   The two lists answer different questions, so the chip is one shape
   throughout and the marker alone carries the difference: a ring for the
   one answer a radio list takes, a box with a tick for the any-number a
   checklist takes. It is the convention every platform already uses, and
   holding the chip itself steady keeps the panel reading as one thing. */
.xp-block-form-field--radiolist .xp-block-form-field__control,
.xp-block-form-field--checklist .xp-block-form-field__control,
.xp-block-form-field--checklist fieldset {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
}

/* The checklist block wraps its choices in a fieldset once there is more
   than one — a grouping element the browser gives a border and padding of
   its own, and one more flex level between the control and the chips. */
.xp-block-form-field--checklist fieldset {
	flex: 1 0 100%;
	min-width: 0;
	margin: 0;
	padding: 0;
	border: 0;
}

/* The description is a sibling of the chips inside the flex control, so it
   is sent to its own line rather than left to sit at the end of the row. */
.xp-block-form-field--radiolist .xp-block-form-field__description,
.xp-block-form-field--checklist .xp-block-form-field__description {
	flex: 1 0 100%;
	margin-top: 0.15rem;
}

.xp-block-form-field__radio,
.xp-block-form-field__check {
	position: relative;
}

.xp-block-form-field__radio input,
.xp-block-form-field__check input {
	position: absolute;
	opacity: 0;
	width: 0;
	height: 0;
	margin: 0;
}

.xp-block-form-field .xp-block-form-field__radiolabel,
.xp-block-form-field .xp-block-form-field__checklabel {
	position: relative;
	display: inline-block;
	font-family: var(--mono);
	font-size: 0.75rem;
	font-weight: 400;
	letter-spacing: 0.04em;
	text-transform: none;
	color: var(--cu-muted, var(--slate));
	background: var(--cu-field, var(--panel));
	border: 1px solid var(--cu-line, var(--stroke-hi));
	border-radius: var(--r-pill);
	padding: 0.45rem 0.9rem 0.45rem 1.95rem;
	margin: 0 !important;
	cursor: pointer;
	transition: border-color 0.18s ease, color 0.18s ease, background 0.18s ease;
}

/* The plugin sizes the checklist's labels with font-size: inherit, off a
   selector carrying one class more than the shared chip rule above — so the
   checkboxes took the control's 16px while the radios kept 0.75rem and the
   two rows came out at different sizes. Matching its shape wins it back. */
.xp-block-form-field.xp-block-form-field--checklist
	.xp-block-form-field__check
	.xp-block-form-field__checklabel {
	font-size: 0.75rem;
}

/* The marker itself: a ring for one-of, a box for any-of. Both sit on the
   chip's own colour, so they follow it through hover and checked without
   needing a rule of their own for each state. */
.xp-block-form-field .xp-block-form-field__radiolabel::before,
.xp-block-form-field .xp-block-form-field__checklabel::before {
	content: '';
	position: absolute;
	top: 50%;
	left: 0.72rem;
	width: 0.68rem;
	height: 0.68rem;
	border: 1px solid currentColor;
	opacity: 0.5;
	transform: translateY(-50%);
	transition: opacity 0.18s ease, background 0.18s ease;
}

.xp-block-form-field .xp-block-form-field__radiolabel::before {
	border-radius: 50%;
}

.xp-block-form-field .xp-block-form-field__checklabel::before {
	border-radius: 2.5px;
}

.xp-block-form-field .xp-block-form-field__radiolabel:hover,
.xp-block-form-field .xp-block-form-field__checklabel:hover {
	border-color: var(--cu-ink, var(--ivory));
	color: var(--cu-ink, var(--ivory));
}

.xp-block-form-field .xp-block-form-field__radiolabel:hover::before,
.xp-block-form-field .xp-block-form-field__checklabel:hover::before {
	opacity: 0.8;
}

.xp-block-form-field__radio input:checked + .xp-block-form-field__radiolabel,
.xp-block-form-field__check input:checked + .xp-block-form-field__checklabel {
	border-color: var(--pulse);
	background: var(--pulse);
	color: var(--ink);
	font-weight: 700;
}

/* Checked, the marker fills with the chip's text colour and the chip's own
   background is punched back through it — an inset ring reads as a dot, a
   pair of borders as a tick. */
.xp-block-form-field__radio
	input:checked
	+ .xp-block-form-field__radiolabel::before {
	background: currentColor;
	box-shadow: inset 0 0 0 2px var(--pulse);
	opacity: 1;
}

.xp-block-form-field__check
	input:checked
	+ .xp-block-form-field__checklabel::before {
	background: currentColor;
	opacity: 1;
}

.xp-block-form-field__check
	input:checked
	+ .xp-block-form-field__checklabel::after {
	content: '';
	position: absolute;
	top: 50%;
	left: 0.94rem;
	width: 0.22rem;
	height: 0.42rem;
	border: solid var(--pulse);
	border-width: 0 1.5px 1.5px 0;
	transform: translateY(-62%) rotate(45deg);
}

.xp-block-form-field__radio input:focus-visible + .xp-block-form-field__radiolabel,
.xp-block-form-field__check
	input:focus-visible
	+ .xp-block-form-field__checklabel {
	outline: 2px solid var(--pulse);
	outline-offset: 2px;
}

/* Submit — core/button styling already applies; it just needs to fill
   the column. */
.xp-block-form-field--submit .wp-block-button__link {
	width: 100%;
	justify-content: center;
}

.xp-block-form.xp-is-loading {
	opacity: 0.6;
	pointer-events: none;
}

/* ------------------------------------------------------------
   Layout corrections where a block's own layout rules and the
   design's structure need reconciling.
   ------------------------------------------------------------ */

/* A popup trigger wraps whatever opens the panel. It shrinks to its contents
   so only the control itself is clickable, and still takes a block gap from
   the layout around it — which display:contents would have dropped. */
.nb-popup-trigger {
	display: flex;
	width: fit-content;
	max-width: 100%;
	cursor: pointer;
}

/* The clusters span the full-bleed hero, not the constrained column — that is
   the whole point of pinning each one flush to a viewport edge. */
.novembit-clusters {
	max-width: none;
}

/* The block is aligned full so it can break the root padding once it stacks.
   While it is still absolutely positioned, inset already spans the hero's
   padding box, and those same negative margins would push it a further
   padding-width past each edge — cropping more of the art than intended. */
.nb-hero > .novembit-clusters {
	margin-inline: 0;
}

/* The codex values must absorb the leftover height, otherwise the container's
   own background — which is the 1px divider colour — shows as a grey strip
   under the last card. */
.nb-codex__values {
	height: 100%;
}

.nb-codex__values > * {
	flex: 1 1 auto;
}

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

	*,
	*::before,
	*::after {
		animation-duration: 0.001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.001ms !important;
	}

	/* No JS to add .nb-reduced, so the drift viewport has to be
	   unwound here too: a full-height list, no clipping, no fade. */
	.nb-quotes__viewport {
		height: auto !important;
		-webkit-mask-image: none !important;
		mask-image: none !important;
	}
}

/* ------------------------------------------------------------
   CONTACT PANEL STAIRCASE — three frames of a 37.5px block edge.
   The panel resolves through them as it slides in, then holds on
   the first: a permanent shimmer would pull attention off the form.
   ------------------------------------------------------------ */
.xpac-popup.nb-contact-panel {
	--nb-stair-1: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20188%20900%22%20preserveAspectRatio%3D%22none%22%3E%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M113%2037.5H75.5H38V0H75.5H113V37.5ZM150.5%20187.5V150H113H75.5V112.5H113V75V37.5H150.5V0H188V37.5V75V112.5V150V187.5H150.5ZM150.5%20525V487.5H113V450V412.5H75.5V375H113H150.5V337.5H113V300V262.5V225V187.5H150.5V225H188V262.5H150.5V300H188V337.5V375V412.5V450V487.5V525H150.5ZM113%20562.5V525H150.5V562.5H113ZM113%20600H75.5V562.5H113V600ZM113%20600H150.5H188V637.5H150.5H113V600ZM113%20675V712.5V750H150.5V787.5H113H75.5V825H113V862.5H150.5V900H188V862.5H150.5V825H188V787.5V750V712.5H150.5V675H113ZM38%20225V262.5H0.5V300H38V262.5H75.5V225H38ZM38%20862.5V900H75.5V862.5H38Z%22%2F%3E%3C%2Fsvg%3E');
	--nb-stair-2: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20188%20900%22%20preserveAspectRatio%3D%22none%22%3E%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M112.5%2037.5H75H37.5V0H75H112.5V37.5ZM112.5%2075V112.5H75V150H38V187.5H75H75.5H112.5V225V262.5H75V225H37.5V262.5H0L1.90735e-06%20300H37.5H75H112.5V337.5H150H187.5V300H150V262.5H187.5V225H150V187.5H112.5V150V112.5H150V150H187.5V112.5H150V75H112.5ZM0%20337.5V375H37.5V337.5H0ZM38%20487.5V450H75.5H112.5V412.5H75V375H112.5H150H187.5V412.5V450H150H113V487.5H75.5H38ZM113%20487.5H150H150.5H187.5V525H150.5H150H113V487.5ZM75%20525V562.5V600H112.5V637.5H150V674.5H187.5V637H150V600H112.5V562.5V525H75ZM0%20675L3.33786e-06%20712.5H37.5L37.5%20675H0ZM75%20712.5V675H112.5V712.5H150V750H187.5V787.5V825H150V787.5H112.5V750H75V712.5ZM112.5%20825V787.5H75V825H37.5V862.5H75V900H112.5V862.5H150V825H112.5ZM112.5%20825V862.5H75V825H112.5ZM150%2037.5V0H187.5V37.5H150Z%22%2F%3E%3C%2Fsvg%3E');
	--nb-stair-3: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20188%20900%22%20preserveAspectRatio%3D%22none%22%3E%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M75%2037.5H112.5V0H75H37.5V37.5H75ZM112.5%2075V112.5H75V75H37.5V112.5H0V150H37.5V187.5H75H112.5V225V262.5H75V225H37.5V262.5H0L2.14577e-06%20300H37.5H75H112.5V337.5H75V375V412.5V450H37.5V412.5H0V450H37.5V487.5V525H75V562.5V600H112.5V637V637.5V674.5H150H187.5V637H150V600H187.5V562.5V525V487.5V450H150V412.5V375H187.5V337.5V300H150V262.5H187.5V225V187.5H150H112.5V150V112.5H150V150H187.5V112.5V75H150H112.5ZM150%20375V337.5H112.5V375H150ZM150%20450V487.5H113V525H150V562.5V600H112.5V562.5V525H75V487.5V450H112.5H150ZM37.5%20150H75V112.5H37.5V150ZM3.57628e-06%20712.5L1.9371e-06%20675H37.5V712.5H3.57628e-06ZM75%20675V712.5V750H112.5V787.5H75V825H112.5V862.5H75V900H112.5H150H187.5V862.5H150V825H187.5V787.5V750H150V712.5H112.5V675H75ZM150%200V37.5H187.5V0H150ZM0%20825V862.5H37.5V825H0Z%22%2F%3E%3C%2Fsvg%3E');
}

@keyframes nb-stair {
	0% {
		-webkit-mask-image: var(--nb-stair-1);
		mask-image: var(--nb-stair-1);
	}
	7% {
		-webkit-mask-image: var(--nb-stair-2);
		mask-image: var(--nb-stair-2);
	}
	14% {
		-webkit-mask-image: var(--nb-stair-3);
		mask-image: var(--nb-stair-3);
	}
	22% {
		-webkit-mask-image: var(--nb-stair-1);
		mask-image: var(--nb-stair-1);
	}
	31% {
		-webkit-mask-image: var(--nb-stair-2);
		mask-image: var(--nb-stair-2);
	}
	42% {
		-webkit-mask-image: var(--nb-stair-3);
		mask-image: var(--nb-stair-3);
	}
	55% {
		-webkit-mask-image: var(--nb-stair-1);
		mask-image: var(--nb-stair-1);
	}
	72% {
		-webkit-mask-image: var(--nb-stair-2);
		mask-image: var(--nb-stair-2);
	}
	100% {
		-webkit-mask-image: var(--nb-stair-1);
		mask-image: var(--nb-stair-1);
	}
}

/* ------------------------------------------------------------
   The contact panel is the one light surface on the site. XPAC's
   form tokens are emitted at :root against the dark ground, and a
   custom property is substituted where it is declared — so the
   ground-dependent ones are re-declared here, where --cu-* exists.
   ------------------------------------------------------------ */
.xpac-popup.nb-contact-panel {
	--wp--custom--xp-form--label-color: var(--cu-muted);
	--wp--custom--xp-form--info-color: var(--cu-muted);
	--wp--custom--xp-form--input-color: var(--cu-ink);
	--wp--custom--xp-form--input-bg-color: var(--cu-field);
	--wp--custom--xp-form--input-brd-color: var(--cu-line);
	--wp--custom--xp-form--input-placeholder-color: var(--cu-muted);
	--wp--custom--xp-form--input-hover-brd-color: var(--cu-line);

	/* The plugin derives a bg and a text colour for every interaction state from
	   the resting pair, and emits the lot at :root — against the dark ground.
	   Overriding only the resting pair left hover, focus and the validation
	   states resolving to the page's panel colour, so a field went black under
	   the cursor. Each derived state has to be brought over too. */
	--wp--custom--xp-form--input-hover-bg-color: var(--cu-field);
	--wp--custom--xp-form--input-hover-color: var(--cu-ink);
	--wp--custom--xp-form--input-focus-bg-color: var(--cu-field);
	--wp--custom--xp-form--input-focus-color: var(--cu-ink);
	--wp--custom--xp-form--input-error-bg-color: var(--cu-field);
	--wp--custom--xp-form--input-error-color: var(--cu-ink);
	--wp--custom--xp-form--input-error-focus-bg-color: var(--cu-field);
	--wp--custom--xp-form--input-error-focus-color: var(--cu-ink);
	--wp--custom--xp-form--input-success-bg-color: var(--cu-field);
	--wp--custom--xp-form--input-success-color: var(--cu-ink);
	--wp--custom--xp-form--input-success-focus-bg-color: var(--cu-field);
	--wp--custom--xp-form--input-success-focus-color: var(--cu-ink);

	--wp--custom--xp-form--input-disabled-color: var(--cu-muted);
	--wp--custom--xp-form--input-disabled-bg-color: var(--cu-field);
	--wp--custom--xp-form--input-disabled-brd-color: rgba(20, 20, 20, 0.14);
	--wp--custom--xp-form--alert-success-color: var(--cu-ink);
}
