/* =============================================================================
 * PerformAd, shared chrome
 *
 * Sitewide components: container, header/nav, buttons, eyebrows, sections, footer, reveal + count-up
 * primitives, and form styling on dark. Consumes --pa-* / --wp--* variables ONLY, no raw hex.
 *
 * Page-specific section styles live in home.css (.pa-home) and inner.css (.pa-inner).
 * ========================================================================== */

/* --- container -------------------------------------------------------- */

.pa-wrap {
	max-width: var(--pa-container);
	margin-inline: auto;
	padding-inline: var(--pa-gutter);
}

.pa-section {
	padding-block: var(--pa-section);
	position: relative;
}

/* Header clearance. The nav is fixed, so every non-front main must start below it, this lives here,
 * not in inner.css, because the fixed header is sitewide chrome and inner.css does not load on the
 * front page. .pa-home opts out: its hero deliberately sits behind the header. */
.pa-inner {
	padding-block-start: calc(var(--pa-nav-h) + var(--pa-xl));
}

/* Custom grids: WordPress adds block-gap as margin-block-start to every child after the first,
 * which double-spaces our own gap. Let gap own it. */
.pa-grid > *,
.pa-stats > * {
	margin-block: 0;
}

/* --- type helpers ----------------------------------------------------- */

.pa-eyebrow {
	display: inline-flex;
	align-items: center;
	gap: 0.6rem;
	font-size: var(--pa-fs-xs);
	font-weight: 600;
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--pa-green-400);
	margin: 0;
}

.pa-eyebrow::before {
	content: "";
	inline-size: 26px;
	block-size: 2px;
	background: var(--pa-green);
	border-radius: 2px;
	flex: none;
}

.pa-eyebrow--center {
	justify-content: center;
}

.acc {
	color: var(--pa-green);
}

.pa-lead {
	color: var(--pa-text-2);
	font-size: var(--pa-fs-lead);
	max-width: 56ch;
}

/* Numbers: tabular so count-ups don't reflow their container. */
.pa-num {
	font-variant-numeric: tabular-nums;
	font-feature-settings: "tnum";
	/* inline-block so site.js can pin the box to the final value's width before the count-up blanks
	   it to "0": min-inline-size does nothing on a non-replaced inline box. tabular-nums above then
	   keeps every intermediate frame the same width per digit, so the number never jitters inside
	   the pinned box. See resetCounter() in assets/js/site.js for why this matters (CLS). */
	display: inline-block;
}

/* --- buttons ---------------------------------------------------------- */

.pa-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.55rem;
	font-family: inherit;
	font-size: var(--pa-fs-base);
	font-weight: 600;
	line-height: 1;
	padding: 0.85rem 1.7rem;
	border: 1px solid transparent;
	border-radius: var(--pa-r-pill);
	cursor: pointer;
	text-decoration: none;
	transition:
		transform var(--pa-t-fast) var(--pa-ease),
		background var(--pa-t-fast),
		color var(--pa-t-fast),
		border-color var(--pa-t-fast),
		box-shadow var(--pa-t-fast);
}

.pa-btn:active {
	transform: scale(0.97);
}

.pa-btn svg {
	inline-size: 16px;
	block-size: 16px;
	flex: none;
}

/* Green fill ALWAYS takes near-black text, white on green fails AA at button sizes. */
.pa-btn--primary {
	background: var(--pa-green);
	color: var(--pa-ink);
}

.pa-btn--primary:hover,
.pa-btn--primary:focus-visible {
	background: var(--pa-green-400);
	color: var(--pa-ink);
	box-shadow: 0 8px 30px -6px var(--pa-glow-strong);
}

.pa-btn--ghost {
	border-color: var(--pa-border-strong);
	color: var(--pa-text);
	background: transparent;
}

.pa-btn--ghost:hover,
.pa-btn--ghost:focus-visible {
	border-color: var(--pa-green);
	color: var(--pa-green-400);
}

/* --- header ----------------------------------------------------------- */

.pa-nav {
	position: fixed;
	inset-inline: 0;
	inset-block-start: 0;
	z-index: 100;
	border-block-end: 1px solid transparent;
	transition: background var(--pa-t), border-color var(--pa-t);
}

/* Solid scrim, never backdrop-filter, blur stalls the compositor on long scrolling pages. */
.pa-nav.is-scrolled {
	background: var(--pa-scrim-nav);
	border-block-end-color: var(--pa-border);
}

.pa-nav-in {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--pa-md);
	block-size: var(--pa-nav-h);
}

.pa-logo {
	display: flex;
	align-items: center;
	flex: none;
}

.pa-logo img {
	block-size: 30px;
	inline-size: auto;
}

/* The <nav> landmark wraps the list for screen-reader navigation, but must not become a layout box:
 * `.pa-nav-in` is a flex row with a gap, and an extra wrapper would add an extra gap. It matters at
 * <=640px, where `.pa-nav-links` is `display: none` and therefore not a flex item at all, while an
 * empty wrapper still would be, widening an already tight mobile header. `display: contents` keeps
 * the list itself as the flex item, so every rule below (including the open-drawer state) applies
 * unchanged. Browsers have kept display:contents elements in the accessibility tree since
 * Chrome 89 / Firefox 74 / Safari 15.4, so the landmark is still exposed. */
.pa-nav-primary {
	display: contents;
}

.pa-nav-links {
	display: flex;
	gap: 2.2rem;
	margin: 0;
	padding: 0;
	list-style: none;
	font-size: var(--pa-fs-base);
	font-weight: 500;
}

.pa-nav-links a {
	position: relative;
	display: inline-block;
	padding-block: 0.4rem;
	color: var(--pa-text-2);
	text-decoration: none;
	transition: color var(--pa-t-fast);
}

.pa-nav-links a::after {
	content: "";
	position: absolute;
	inset-inline-start: 0;
	inset-block-end: 0;
	inline-size: 0;
	block-size: 2px;
	background: var(--pa-green);
	transition: inline-size var(--pa-t-fast) var(--pa-ease);
}

.pa-nav-links a:hover,
.pa-nav-links a:focus-visible,
.pa-nav-links a.is-active {
	color: var(--pa-text);
}

.pa-nav-links a:hover::after,
.pa-nav-links a:focus-visible::after,
.pa-nav-links a.is-active::after {
	inline-size: 100%;
}

.pa-nav-cta {
	display: flex;
	align-items: center;
	gap: 0.8rem;
	flex: none;
}

.pa-nav .pa-btn {
	padding: 0.65rem 1.35rem;
	font-size: var(--pa-fs-sm);
}

.pa-burger {
	display: none;
	background: none;
	border: 0;
	padding: 0.5rem;
	cursor: pointer;
	line-height: 0;
}

.pa-burger span {
	display: block;
	inline-size: 22px;
	block-size: 2px;
	margin-block: 5px;
	background: var(--pa-text);
	border-radius: 2px;
	transition: transform var(--pa-t-fast), opacity var(--pa-t-fast);
}

.pa-nav.is-open .pa-burger span:nth-child(1) {
	transform: translateY(7px) rotate(45deg);
}

.pa-nav.is-open .pa-burger span:nth-child(2) {
	opacity: 0;
}

.pa-nav.is-open .pa-burger span:nth-child(3) {
	transform: translateY(-7px) rotate(-45deg);
}

/* --- pointer target size ----------------------------------------------
 *
 * WCAG 2.5.8 (AA) asks for 24x24 and this build already cleared that; the project's own rule asks
 * for 44x44, and the signed-off design draws these controls smaller than that (the nav CTA is 36px
 * tall, the logo 30px, a nav link 37px). Target size is measured on the POINTER TARGET, not on the
 * visual, so each one gets an invisible 44px-tall overlay instead of being redrawn. Nothing about
 * the design changes and nothing here paints.
 *
 * `::before`, not `::after`: the nav link's underline and the throttle switch's knob are already
 * `::after`, and overwriting either would be a visible regression.
 *
 * Growth is vertical only, and centred, so a control cannot grow into its horizontal neighbour.
 * Inline text links (the mailto addresses in prose, for instance) are deliberately NOT included:
 * WCAG exempts targets in a sentence, and expanding them would overlap the surrounding lines,
 * which trades a size problem for a mis-click problem. */

.pa-nav-links a,
.pa-nav .pa-btn,
.pa-logo {
	position: relative;
}

.pa-nav-links a::before,
.pa-nav .pa-btn::before,
.pa-logo::before {
	content: "";
	position: absolute;
	inset-inline: 0;
	inset-block-start: 50%;
	block-size: 44px;
	transform: translateY(-50%);
}

/* The burger is short on BOTH axes (38x42), so it gets a centred square rather than a full-width
   band. It grows 3px per side, well inside the 8px gap to the CTA beside it, so the two targets
   cannot overlap. */
.pa-burger {
	position: relative;
}

.pa-burger::before {
	content: "";
	position: absolute;
	inset-block-start: 50%;
	inset-inline-start: 50%;
	inline-size: 44px;
	block-size: 44px;
	transform: translate(-50%, -50%);
}

/* --- section background: data grid ------------------------------------
 * The picked abstract background treatment (2026-07-29, option B of the background sheet): a fine
 * dot-matrix field with two soft green glows breathing very slowly. A sitewide utility so any
 * section can opt in with one class; currently on the homepage brand-safety and CTA sections, with
 * a second treatment to alternate coming once picked. Pure gradients, no images, no blur filters;
 * the breathing is opacity-only on its own layer, so it composites without repaints. Decoration
 * stays behind content (z-index -1 against the section's own stacking context) and is clipped by
 * the section itself, never by the body. */

.pa-bg-grid {
	position: relative;
	isolation: isolate;
	overflow-x: clip;
}

.pa-bg-grid::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background-image:
		radial-gradient(color-mix(in srgb, var(--pa-silver) 14%, transparent) 1px, transparent 1.5px),
		radial-gradient(color-mix(in srgb, var(--pa-green) 20%, transparent) 1px, transparent 1.5px);
	background-size: 26px 26px, 130px 130px;
	background-position: 0 0, 13px 13px;
	opacity: 0.5;
	mask-image: radial-gradient(90% 80% at 50% 45%, var(--pa-canvas) 30%, transparent 100%);
}

.pa-bg-grid::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background:
		radial-gradient(42% 55% at 12% 20%, color-mix(in srgb, var(--pa-green) 7%, transparent), transparent 72%),
		radial-gradient(38% 50% at 88% 85%, color-mix(in srgb, var(--pa-green) 6%, transparent), transparent 70%);
	opacity: 0.85;
}

@media (prefers-reduced-motion: no-preference) {
	.pa-bg-grid::after {
		animation: pa-breathe 16s ease-in-out infinite alternate;
	}
}

@keyframes pa-breathe {
	from {
		opacity: 0.45;
	}
	to {
		opacity: 1;
	}
}

/* --- section background: radar sweep ----------------------------------
 * The second picked treatment (2026-07-30, option E of the round-2 sheet). Structure is the static
 * SVG from pa_bg_radar() in functions.php; every paint lives here, tokens only. Rings and spokes
 * are static; the beam sweeps the visible quadrant, the dashed tick ring creeps, two blips ping.
 * All motion is transform/opacity inside no-preference, and a frozen frame reads as a complete
 * still (a sonar at rest), so reduced motion loses nothing. */

.pa-bg-radar {
	position: relative;
	isolation: isolate;
	overflow: clip;
}

.pa-bg-radar__art {
	position: absolute;
	inset: 0;
	z-index: -1;
}

.pa-bg-radar__art svg {
	display: block;
	inline-size: 100%;
	block-size: 100%;
}

.pa-bg-radar .radar-ring,
.pa-bg-radar .radar-spoke {
	fill: none;
	stroke-width: 1;
}

.pa-bg-radar .radar-ring--g,
.pa-bg-radar .radar-spoke--g {
	stroke: color-mix(in srgb, var(--pa-green) 7%, transparent);
}

.pa-bg-radar .radar-ring--g4 {
	stroke: color-mix(in srgb, var(--pa-green-400) 10%, transparent);
}

.pa-bg-radar .radar-ring--sv,
.pa-bg-radar .radar-spoke--sv {
	stroke: color-mix(in srgb, var(--pa-silver) 5%, transparent);
}

.pa-bg-radar .radar-ring--dim {
	stroke: color-mix(in srgb, var(--pa-green-600) 6%, transparent);
}

.pa-bg-radar .radar-ring--faint,
.pa-bg-radar .radar-spoke--f {
	stroke: color-mix(in srgb, var(--pa-silver) 4%, transparent);
}

.pa-bg-radar .radar-tickring {
	fill: none;
	stroke: color-mix(in srgb, var(--pa-silver) 7%, transparent);
	stroke-width: 1.5;
	stroke-dasharray: 2 12;
	transform-box: view-box;
	transform-origin: 1560px -120px;
}

.pa-bg-radar .radar-beam {
	transform-box: view-box;
	transform-origin: 1560px -120px;
}

.pa-bg-radar .radar-beam__edge {
	stroke: color-mix(in srgb, var(--pa-green-400) 14%, transparent);
	stroke-width: 1;
}

.pa-bg-radar .radar-beam-a {
	stop-color: var(--pa-green);
	stop-opacity: 0.12;
}

.pa-bg-radar .radar-beam-b {
	stop-color: var(--pa-green);
	stop-opacity: 0.05;
}

.pa-bg-radar .radar-beam-c {
	stop-color: var(--pa-green);
	stop-opacity: 0;
}

.pa-bg-radar .radar-hub-a {
	stop-color: var(--pa-green);
	stop-opacity: 0.1;
}

.pa-bg-radar .radar-hub-b {
	stop-color: var(--pa-green);
	stop-opacity: 0.04;
}

.pa-bg-radar .radar-hub-c {
	stop-color: var(--pa-green);
	stop-opacity: 0;
}

.pa-bg-radar .radar-ping {
	fill: none;
	stroke: var(--pa-green);
	stroke-width: 1;
	opacity: 0.16;
	transform-box: fill-box;
	transform-origin: center;
}

.pa-bg-radar .radar-dot {
	fill: var(--pa-green-400);
	opacity: 0.5;
}

.pa-bg-radar .radar-dot--2 {
	opacity: 0.4;
}

/* Short hub heroes crop the composition to its densest zone (the hub sits just above the corner),
   so the sweeping wedge reads as a bright diagonal stripe instead of a beam. On those, rings,
   ticks and blips carry the treatment and the whole layer is eased back; the full sweep runs only
   on tall sections (the homepage solutions band and the 404, which keeps its beam explicitly). */
.pa-hero.pa-bg-radar:not(.error-404):not(.pa-bg-radar--flow) .radar-beam {
	display: none;
}

.pa-hero.pa-bg-radar:not(.error-404):not(.pa-bg-radar--flow) .pa-bg-radar__art {
	opacity: 0.75;
}

/* --flow: one radar spanning a hero AND the section(s) below it, anchored at the top of the page
 * so the scan starts from the header (contact page). The art extends past its own section; the
 * later sibling sections paint on top of it in stacking order, so it stays decoration UNDER their
 * content exactly as if each had its own layer. The taller box also re-scales the slice-cropped
 * SVG, so the full composition (beam included) has room. Bottom edge fades out via an alpha mask
 * rather than stopping on a hard line. No overflow clip here, on purpose: the overhang IS the
 * feature, and the art has no inline-axis overhang to clip. */
.pa-bg-radar--flow {
	overflow: visible;
}

.pa-bg-radar--flow .pa-bg-radar__art {
	block-size: calc(100% + 880px);
	/* Alpha-only mask: any fully-opaque colour behaves identically, reusing --pa-canvas per house
	   style. */
	mask-image: linear-gradient(to bottom, var(--pa-canvas) 72%, transparent);
}

@media (prefers-reduced-motion: no-preference) {
	.pa-bg-radar .radar-beam {
		animation: pa-radar-sweep 34s ease-in-out infinite alternate;
	}

	.pa-bg-radar .radar-tickring {
		animation: pa-radar-spin 240s linear infinite;
	}

	.pa-bg-radar .radar-ping--1 {
		animation: pa-radar-ping 8s ease-out infinite 1.2s;
	}

	.pa-bg-radar .radar-ping--2 {
		animation: pa-radar-ping 9.5s ease-out infinite 4.6s;
	}
}

@keyframes pa-radar-sweep {
	from {
		transform: rotate(-24deg);
	}
	to {
		transform: rotate(36deg);
	}
}

@keyframes pa-radar-spin {
	from {
		transform: rotate(0deg);
	}
	to {
		transform: rotate(360deg);
	}
}

@keyframes pa-radar-ping {
	0% {
		transform: scale(0.35);
		opacity: 0.5;
	}
	60% {
		transform: scale(2.4);
		opacity: 0;
	}
	100% {
		transform: scale(2.4);
		opacity: 0;
	}
}

/* --- reveal / count-up primitives (shared by home.js and inner.js) ----
 *
 * EVERY rule below is scoped to `.js`, the class the inline flag in functions.php puts on <html>.
 * Without that scope, `.rv { opacity: 0 }` is an unconditional promise that JavaScript will arrive
 * and undo it: if the script is blocked, fails, or is switched off, all 47 reveal elements on the
 * homepage (and every card on every other page) stay invisible forever and the site reads as blank
 * below the hero. Scoping to `.js` means the hidden state only ever exists where something is
 * guaranteed to be able to reveal it. Do not unscope these. */

.js .rv {
	opacity: 0;
	transform: translateY(26px);
	transition:
		opacity var(--pa-t-reveal) var(--pa-ease),
		transform var(--pa-t-reveal) var(--pa-ease);
}

.js .rv.in {
	opacity: 1;
	transform: none;
}

/* Also `.js`-scoped, and deliberately: at (0,2,0) it has to outrank `.js .rv` above, which an
   unscoped `.rv` at (0,1,0) would not, and reduced-motion users would lose the reveal entirely. */
@media (prefers-reduced-motion: reduce) {
	.js .rv {
		opacity: 1;
		transform: none;
	}
}

/* --- footer ----------------------------------------------------------- */

.pa-foot {
	border-block-start: 1px solid var(--pa-border);
	background: var(--pa-surface);
	padding-block: var(--pa-2xl) var(--pa-xl);
	font-size: var(--pa-fs-base);
}

.pa-foot-grid {
	display: grid;
	grid-template-columns: 1.6fr 1fr 1fr 1fr;
	gap: var(--pa-xl);
}

.pa-foot .pa-logo img {
	block-size: 26px;
}

.pa-foot-tag {
	color: var(--pa-muted);
	font-size: var(--pa-fs-sm);
	max-width: 34ch;
	margin-block: var(--pa-sm) 0;
}

.pa-foot-tag--brand {
	color: var(--pa-text-2);
	font-weight: 600;
	letter-spacing: 0.14em;
}

.pa-foot-tag--brand .acc {
	color: var(--pa-green);
}

.pa-foot h2 {
	font-size: var(--pa-fs-xs);
	font-weight: 600;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--pa-muted);
	margin: 0 0 1.1rem;
}

.pa-foot ul {
	display: grid;
	gap: 0.6rem;
	margin: 0;
	padding: 0;
	list-style: none;
	color: var(--pa-text-2);
}

.pa-foot a {
	color: inherit;
	text-decoration: none;
}

.pa-foot a:hover,
.pa-foot a:focus-visible {
	color: var(--pa-green-400);
	text-decoration: underline;
}

.pa-legal {
	display: flex;
	justify-content: space-between;
	gap: var(--pa-sm);
	flex-wrap: wrap;
	border-block-start: 1px solid var(--pa-border);
	margin-block-start: var(--pa-xl);
	padding-block-start: var(--pa-md);
	color: var(--pa-muted);
	font-size: var(--pa-fs-sm);
}

/* --- forms on dark (Fluent Forms) ------------------------------------- */

.pa-form .fluentform .ff-el-input--label label,
.pa-form .fluentform label {
	color: var(--pa-text-2);
	font-size: var(--pa-fs-sm);
	font-weight: 500;
}

.pa-form .fluentform input[type="text"],
.pa-form .fluentform input[type="email"],
.pa-form .fluentform input[type="tel"],
.pa-form .fluentform input[type="url"],
.pa-form .fluentform select,
.pa-form .fluentform textarea {
	inline-size: 100%;
	font-family: inherit;
	font-size: var(--pa-fs-base);
	color: var(--pa-text);
	background: var(--pa-canvas);
	border: 1px solid var(--pa-border-strong);
	border-radius: var(--pa-r-sm);
	padding: 0.85rem 1rem;
	transition: border-color var(--pa-t-fast), box-shadow var(--pa-t-fast);
}

.pa-form .fluentform input::placeholder,
.pa-form .fluentform textarea::placeholder {
	color: var(--pa-muted);
}

.pa-form .fluentform input:focus,
.pa-form .fluentform select:focus,
.pa-form .fluentform textarea:focus {
	border-color: var(--pa-green);
	box-shadow: 0 0 0 3px var(--pa-glow);
	outline: none;
}

.pa-form .fluentform .ff-btn-submit {
	background: var(--pa-green);
	color: var(--pa-ink);
	font-family: inherit;
	font-weight: 600;
	border: 0;
	border-radius: var(--pa-r-pill);
	padding: 0.9rem 1.9rem;
	cursor: pointer;
	transition: background var(--pa-t-fast), box-shadow var(--pa-t-fast);
}

.pa-form .fluentform .ff-btn-submit:hover,
.pa-form .fluentform .ff-btn-submit:focus-visible {
	background: var(--pa-green-400);
	color: var(--pa-ink);
	box-shadow: 0 8px 30px -6px var(--pa-glow-strong);
}

.pa-form .fluentform .error,
.pa-form .fluentform .text-danger,
.pa-form .fluentform .ff-el-is-error input,
.pa-form .fluentform .ff-el-is-error textarea {
	color: var(--pa-error);
	border-color: var(--pa-error);
}

.pa-form .fluentform .ff-el-is-error .error {
	font-size: var(--pa-fs-sm);
}

.pa-form .fluentform .ff-message-success {
	color: var(--pa-green-400);
	border: 1px solid var(--pa-green-700);
	border-radius: var(--pa-r-sm);
	padding: var(--pa-md);
	background: var(--pa-surface);
}

/* --- responsive ------------------------------------------------------- */

@media (max-width: 1024px) {
	.pa-foot-grid {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (max-width: 640px) {
	.pa-nav-links {
		display: none;
	}

	.pa-burger {
		display: block;
	}

	/* At 375px the header did not fit: a 30px-tall logo is 202px wide, and 202 + 24 gap + 170 CTA +
	   40 gutter = 436px inside a 375px viewport. body{overflow-x:hidden} hid the damage, so the
	   "Contact Us" button simply sat 101px off-screen instead of showing a scrollbar. Shrink the
	   logo and tighten the CTA, and, more importantly, let the logo SHRINK rather than overflow,
	   so a longer nav CTA label (it is client-editable in Settings → Site Text) can never push the
	   button off the screen again. */
	.pa-nav-in {
		gap: var(--pa-sm);
	}

	.pa-logo {
		flex: 0 1 auto;
		min-inline-size: 0;
	}

	.pa-logo img {
		block-size: 24px;
		max-inline-size: 100%;
		object-fit: contain;
		object-position: 0 50%;
	}

	.pa-nav-cta {
		gap: var(--pa-xs);
	}

	.pa-nav .pa-btn {
		padding: 0.55rem 0.9rem;
		font-size: var(--pa-fs-xs);
		white-space: nowrap;
	}

	.pa-nav.is-open .pa-nav-links {
		display: flex;
		position: fixed;
		inset-block-start: var(--pa-nav-h);
		inset-inline: 0;
		flex-direction: column;
		gap: var(--pa-md);
		padding: var(--pa-lg) var(--pa-gutter);
		background: var(--pa-canvas);
		border-block-end: 1px solid var(--pa-border);
	}

	.pa-foot-grid {
		grid-template-columns: 1fr;
	}
}


/* =============================================================================
 * SHARED PAGE SECTIONS
 *
 * Component families used by BOTH the homepage and inner pages (stat tiles, case cards, icon rings,
 * partner tiles). They were lifted out of home.css, which only loads on the front page, so the
 * Solutions/Success Stories/About pages get them too. One definition, no divergence.
 *
 * home.css keeps only its own responsive overrides for these, scoped to .pa-home.
 * ========================================================================== */

.stats-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 1px;
	background: var(--pa-border);
	border: 1px solid var(--pa-border);
	border-radius: var(--pa-r-lg);
	overflow: hidden;
}

.stat {
	background: var(--pa-surface);
	padding: 2.2rem 1.8rem;
	position: relative;
	transition: background var(--pa-t);
}

.stat:hover {
	background: var(--pa-raised);
}

.stat .num {
	font-size: var(--pa-fs-stat);
	font-weight: 800;
	color: var(--pa-green);
	letter-spacing: -0.02em;
	font-variant-numeric: tabular-nums;
	line-height: 1.1;
}

.stat .lab {
	margin-block-start: var(--pa-xs);
	font-size: 0.85rem;
	color: var(--pa-text-2);
	font-weight: 500;
}

.stat .src {
	margin-block-start: 0.3rem;
	font-size: 0.7rem;
	color: var(--pa-muted);
}

.icon-ring {
	inline-size: 56px;
	block-size: 56px;
	border-radius: 50%;
	border: 1.5px dashed var(--pa-green-600);
	display: grid;
	place-items: center;
	margin-block-end: 1.4rem;
	animation: pa-spin 30s linear infinite;
}

.icon-ring svg {
	inline-size: 24px;
	block-size: 24px;
	color: var(--pa-green-400);
	animation: pa-spin 30s linear infinite reverse;
}

/* --- success story cards: split ledger (client pick, 2026-08-05) --------
 * Horizontal card: logo panel on a faint green wash (left), result + summary (right), and the
 * campaign's own numbers along a ledger foot spanning both. Two columns rather than three,
 * because the split needs the width; that makes the hub taller and was accepted on that basis.
 * Shared by the homepage cases section and the stories hub, so both stay one component. */

.case-grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 1.25rem;
	margin-block-start: 2.8rem;
}

.case {
	display: grid;
	grid-template-columns: 212px 1fr;
	grid-template-rows: 1fr auto;
	background: var(--pa-surface);
	border: 1px solid var(--pa-border);
	border-radius: var(--pa-r-lg);
	/* clip, not hidden: keeps the panel wash inside the rounded corner without making the card a
	   scroll container. */
	overflow: clip;
	transition: transform var(--pa-t) var(--pa-ease), border-color var(--pa-t), box-shadow var(--pa-t);
	position: relative;
}

.case:hover {
	transform: translateY(-5px);
	border-color: var(--pa-green-700);
	box-shadow: 0 24px 55px -26px var(--pa-glow-strong);
}

/* Left panel: the brand, on a green-tinted wash that separates it from the result. */
.case-panel {
	grid-column: 1;
	grid-row: 1;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 1rem;
	padding: 1.6rem 1.1rem;
	background:
		linear-gradient(
			165deg,
			color-mix(in srgb, var(--pa-green-700) 15%, var(--pa-surface)),
			color-mix(in srgb, var(--pa-green-700) 5%, var(--pa-surface))
		);
	border-inline-end: 1px solid var(--pa-border);
	text-align: center;
}

/* Wordmark fallback for a brand with no logo file: styled deliberately, not left as stray text. */
.case-panel .client-mark {
	font-size: 1.05rem;
	font-weight: 700;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--pa-silver);
	line-height: 1.2;
}

.case-panel .panel-sector {
	font-size: 0.62rem;
	font-weight: 600;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--pa-text-2);
}

.case-body {
	grid-column: 2;
	grid-row: 1;
	display: flex;
	flex-direction: column;
	justify-content: center;
	padding: 1.5rem 1.6rem;
}

.case .metric-row {
	display: flex;
	align-items: baseline;
	gap: 0.7rem;
	flex-wrap: wrap;
}

.case .metric {
	font-size: 2.7rem;
	font-weight: 800;
	color: var(--pa-green-400);
	letter-spacing: -0.02em;
	line-height: 1;
	font-variant-numeric: tabular-nums;
}

.case .what {
	font-size: 0.88rem;
	font-weight: 600;
	color: var(--pa-text);
}

.case .how {
	font-size: 0.83rem;
	color: var(--pa-muted);
	margin-block: 0.7rem 0;
}

/* Ledger foot: the campaign's own figures, spanning both columns. */
.case-ledger {
	grid-column: 1 / -1;
	grid-row: 2;
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 0.5rem;
	padding: 0.7rem 1.6rem;
	border-block-start: 1px solid var(--pa-border);
	background: color-mix(in srgb, var(--pa-canvas) 55%, var(--pa-surface));
	font-size: 0.68rem;
	font-weight: 500;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--pa-muted);
}

.case-ledger::before {
	content: "";
	inline-size: 6px;
	block-size: 6px;
	border-radius: 2px;
	background: var(--pa-green-600);
	flex: none;
}

.case-ledger .v {
	color: var(--pa-text-2);
	font-weight: 600;
	font-variant-numeric: tabular-nums;
}

.case-ledger .sep {
	color: var(--pa-border-strong);
}

/* The whole card is the target, via one overlay anchor carrying a screen-reader-only label. It is
 * inside .case-body but stretches over the entire card, so the ledger and panel are clickable too.
 * Without the inset rule the anchor is a zero-height strip and the card only LOOKS clickable. */
.case-link {
	position: absolute;
	inset: 0;
	border-radius: inherit;
}

/* --- client logo lockups (2026-08-02) ----------------------------------
 * Brand marks on case cards and on a story article. Same white-silhouette flatten as the marquee,
 * so mixed-provenance source files read as one system on the dark canvas. The NAME always stays in
 * the markup (the logo is aria-hidden with an empty alt), visually hidden where the logo shows it,
 * so brands remain crawlable text per golden rule 6. */

.pa-clogo {
	block-size: 30px;
	inline-size: auto;
	max-inline-size: 136px;
	object-fit: contain;
	filter: brightness(0) invert(1);
	opacity: 0.8;
	flex: none;
}

.case:hover .pa-clogo {
	opacity: 1;
}

/* Article size. Larger than the card mark because there it stands in for the page heading. */
.pa-clogo--lg {
	block-size: 46px;
	max-inline-size: 220px;
	opacity: 0.9;
}

.partners {
	display: grid;
	gap: var(--pa-sm);
}

.partner {
	border: 1px solid var(--pa-border-strong);
	border-radius: var(--pa-r);
	padding: var(--pa-md);
	text-align: center;
	font-weight: 700;
	letter-spacing: 0.1em;
	color: var(--pa-silver);
	background: var(--pa-surface);
	transition: border-color var(--pa-t), color var(--pa-t);
}

.partner:hover {
	border-color: var(--pa-green-600);
	color: var(--pa-text);
}

.partner small {
	display: block;
	margin-block-start: 0.3rem;
	font-size: 0.68rem;
	font-weight: 500;
	letter-spacing: 0.14em;
	color: var(--pa-muted);
}

/* --- shared sections: responsive ---------------------------------------- */

@media (max-width: 1024px) {
	.stats-grid {
		grid-template-columns: repeat(2, 1fr);
	}
}

/* One split-ledger card per row below this: two of them would each be about 420px, and the fixed
   212px logo panel plus the metric's own width no longer leave the summary a usable column. */
@media (max-width: 900px) {
	.case-grid {
		grid-template-columns: 1fr;
	}
}

@media (max-width: 640px) {
	.stats-grid {
		grid-template-columns: 1fr;
	}
}

/* Stack the card itself on a phone. The panel is a FIXED 212px track, so under roughly 430px of
   card width the body column falls below its own min-content (a metric like "56,641" at 2.7rem is
   ~130px before padding) and the grid refuses to shrink further: the card then pushes the DOCUMENT
   wider than the viewport, and a wider document widens the containing block `position: fixed`
   resolves against, which drags the header CTA off-screen. That is the trap already documented for
   the hero; this is the same failure with a different cause, so the card stacks before it can
   happen. Verified at 375px: document scrollWidth back to viewport width. */
@media (max-width: 560px) {
	.case {
		grid-template-columns: 1fr;
	}

	.case-panel {
		grid-column: 1;
		grid-row: 1;
		flex-direction: row;
		align-items: center;
		justify-content: flex-start;
		gap: 0.9rem;
		padding: 0.9rem 1.3rem;
		text-align: start;
		border-inline-end: 0;
		border-block-end: 1px solid var(--pa-border);
	}

	.case-body {
		grid-column: 1;
		grid-row: 2;
		padding: 1.2rem 1.3rem;
	}

	.case-ledger {
		grid-row: 3;
		padding-inline: 1.3rem;
	}
}

/* --- shared sections: reduced motion ------------------------------------ */

@media (prefers-reduced-motion: reduce) {
	.icon-ring,
	.icon-ring svg {
		animation: none;
	}
}


/* Rotation for .icon-ring / .ring / .orbit, defined here because .icon-ring is shared. */
@keyframes pa-spin {
	to {
		transform: rotate(360deg);
	}
}
