/* =============================================================================
 * PerformAd, FRONT PAGE ONLY. All rules scoped under .pa-home.
 *
 * Mechanical port of design-options/option-1-full-throttle.html (the APPROVED prototype) into
 * tokens, visual fidelity over cleverness. Section banners below match the prototype's own
 * stylesheet, in the same order, so this file is easy to diff against the source.
 *
 * NOT ported here, owned elsewhere, do not duplicate:
 *   - nav, footer, buttons (.pa-btn*), .pa-wrap, .pa-eyebrow, .rv, .acc, .pa-num  → components.css
 *   - generic section rhythm (padding-block)                                     → .pa-section utility
 *   - the prototype's `.opt-badge`, a design-file review affordance, not a shipped site element
 *
 * Colour/radius/glow/scrim/ease/duration all come from --pa-* aliases (tokens.css → theme.json).
 * Alpha colours with no matching token use color-mix() against a --pa-* base, never a literal.
 * Motion is transform / opacity / stroke-* only, everything guarded by prefers-reduced-motion.
 * ========================================================================== */

.pa-home {
	padding-block-start: 0;
}

/* Section headings share the prototype's global `h2` treatment (font-size already comes from
 * theme.json's h2 element style, so only the extra presentation is restated here). */
.pa-home h2 {
	text-transform: uppercase;
	letter-spacing: 0.01em;
	margin-block: 1rem 1.1rem;
	text-wrap: balance;
}

/* =================================================================
 * PORT BASELINE
 *
 * The prototype these sections were ported from opens with `*{margin:0;padding:0;box-sizing:border-box}`,
 * so every component was drawn against zero default margins. This theme resets only box-sizing, so
 * each ported heading and paragraph silently regained a user-agent margin: 65 element instances on
 * this page, worth about 500px of accumulated height, which is why the safety rows stood 108px tall
 * against the prototype's 77px.
 *
 * This is deliberately a list of components rather than a blanket `.pa-home p, h3 {margin:0}`. Some
 * margins here ARE declared and match the prototype exactly: h2 carries `1rem 0 1.1rem`, .sol h3
 * carries `.6rem 0 .5rem`, .pillar h3 carries a `.7rem` bottom. A blanket reset flattens those too
 * and jams every sub-heading against its heading. Only the elements the prototype left at zero are
 * listed below.
 * ================================================================== */
.pa-home :is(.sol, .shield, .pillar, .fl, .fm, .how, .hero-note, .cta-note) :is(h3, h4, p) {
	margin-block: 0;
}

/* =================================================================
 * HERO
 * ================================================================== */

/* The hero owns its own top spacing because it sits behind the fixed header. */
.pa-home .hero {
	/* min(100svh, cap): full-viewport on laptops, capped on tall monitors. The cap only drops
	   below 100svh at >=1680px via tokens.css, so nothing changes for ordinary screens. */
	min-block-size: min(100svh, var(--pa-hero-max));
	display: flex;
	align-items: center;
	padding-block-start: calc(var(--pa-nav-h) + var(--pa-lg));
	padding-block-end: var(--pa-xl);
	position: relative;
	isolation: isolate;
	/* Decorative overflow must be clipped by the section that creates it, not left to
	   body{overflow-x:hidden}. Relying on the body hides the scrollbar but still leaves the DOCUMENT
	   wider than the viewport, and a wider document widens the containing block that
	   `position: fixed` resolves against, which is what pushed the header's "Contact Us" button
	   off-screen at 375px. `clip` rather than `hidden`: it does not create a scroll container, so
	   the block axis stays `visible` and nothing that overhangs vertically is cut. */
	overflow-x: clip;
}

.pa-home .hero::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -2;
	background:
		radial-gradient(58% 48% at 78% 30%, var(--pa-glow) 0%, transparent 70%),
		radial-gradient(40% 34% at 12% 82%, color-mix(in srgb, var(--pa-green) 7%, transparent) 0%, transparent 70%);
}

.pa-home .hero::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	opacity: 0.5;
	background-image:
		linear-gradient(var(--pa-border) 1px, transparent 1px),
		linear-gradient(90deg, var(--pa-border) 1px, transparent 1px);
	background-size: 64px 64px;
	/* Alpha-only mask: any fully-opaque colour behaves identically here, so this reuses
	 * --pa-canvas in place of the prototype's literal opaque black, no visual difference. */
	mask-image: radial-gradient(70% 60% at 60% 40%, var(--pa-canvas) 0%, transparent 75%);
}

.pa-home .hero-grid {
	display: grid;
	grid-template-columns: 1.05fr 0.95fr;
	gap: clamp(2rem, 5vw, 4.5rem);
	align-items: center;
}

.pa-home .hero h1 {
	font-size: var(--pa-fs-h1);
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: -0.015em;
	margin-block: 1.2rem 1.4rem;
	margin-inline: 0;
	text-wrap: balance;
}

/* --- hero pillar rail ---------------------------------------------------
 * The 2026-07-29 redesign: the three brand pillars live INSIDE the hero as a stacked rail (they
 * replaced the sub-copy, CTAs, verification note and the manual throttle switch, all removed on
 * client instruction). The standalone pillars section left the homepage at the same time. */

.pa-home .hero-pillars {
	margin-block-start: 1.9rem;
	max-inline-size: 34rem;
}

.pa-home .hero-pillars__eyebrow {
	margin-block-end: 0.35rem;
}

.pa-home .hp-row {
	display: flex;
	align-items: flex-start;
	gap: 1.1rem;
	padding-block: 1.05rem;
	border-block-start: 1px solid var(--pa-border);
}

.pa-home .hp-row:first-of-type {
	border-block-start: 0;
}

.pa-home .hp-row .icon-ring {
	flex: none;
	inline-size: 46px;
	block-size: 46px;
}

.pa-home .hp-row .icon-ring svg {
	inline-size: 21px;
	block-size: 21px;
}

.pa-home .hp-row h2 {
	font-size: 0.88rem;
	font-weight: 700;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	margin-block: 0.15rem 0.3rem;
}

.pa-home .hp-row p {
	font-size: 0.85rem;
	color: var(--pa-text-2);
	margin-block: 0;
	max-inline-size: 48ch;
}

/* Both headline words are always in the DOM (server-rendered); CSS alone owns which shows. */
.pa-home .hero h1 .swap {
	color: var(--pa-muted);
	transition: color 0.5s;
}

.pa-home .hero h1 .swap-perform {
	display: none;
}

.pa-home .hero.throttle h1 .swap {
	color: var(--pa-green);
}

.pa-home .hero.throttle h1 .swap-idle {
	display: none;
}

.pa-home .hero.throttle h1 .swap-perform {
	display: inline;
}

/* --- speed lines -------------------------------------------------------
 * `.speedline` inline styles (top/width/animation-delay) come from the pattern per-instance, 
 * this rule owns position/size/background/animation-name+duration only. */

.pa-home .speedlines {
	position: absolute;
	inset: 0;
	pointer-events: none;
	opacity: 0;
	transition: opacity 0.9s var(--pa-ease);
	z-index: -1;
}

.pa-home .hero.throttle .speedlines {
	opacity: 1;
}

.pa-home .speedline {
	position: absolute;
	block-size: 2px;
	background: linear-gradient(90deg, transparent, var(--pa-green));
	border-radius: 2px;
	animation: pa-zoomline 1.7s linear infinite;
	opacity: 0.4;
}

@keyframes pa-zoomline {
	0% {
		transform: translateX(-30vw);
	}
	100% {
		transform: translateX(130vw);
	}
}

/* --- gauge --------------------------------------------------------------
 * Every paint on the gauge SVG is tokenised here (v0.5.5). It used to be hex literals on the SVG
 * presentation attributes in the pattern, which passed the file-scoped grep gate but still broke
 * rule 7 ("no hard-coded hex in patterns"), and left the tick colour unreachable from theme.json.
 * Painting from CSS instead of from presentation attributes keeps the pattern free of styling and
 * works for gradient stops too (`stop-color` is a CSS property like any other). */

.pa-home .gauge-track {
	stroke: var(--pa-border);
}

.pa-home .gauge-grad-from {
	stop-color: var(--pa-green-700);
}

.pa-home .gauge-grad-to {
	stop-color: var(--pa-green-400);
}

.pa-home .gauge-ticks {
	stroke: var(--pa-decor-tick);
}

.pa-home .needle path {
	fill: var(--pa-text);
}

.pa-home .gauge-hub {
	fill: var(--pa-raised);
	stroke: var(--pa-green);
}

.pa-home .cockpit {
	position: relative;
	display: grid;
	place-items: center;
}

.pa-home .gauge-card {
	background: linear-gradient(160deg, var(--pa-surface), var(--pa-canvas) 70%);
	border: 1px solid var(--pa-border-strong);
	border-radius: var(--pa-r-lg);
	padding: clamp(1.5rem, 3vw, 2.6rem);
	/* 540px, up from 460px: the picked hero option pairs the pillar rail with an oversized gauge. */
	inline-size: min(540px, 100%);
	box-shadow:
		0 30px 80px -30px color-mix(in srgb, var(--pa-canvas) 80%, transparent),
		inset 0 1px 0 color-mix(in srgb, var(--pa-text) 4%, transparent);
	position: relative;
}

.pa-home .gauge-card::before {
	content: "";
	position: absolute;
	inset: -1px;
	border-radius: inherit;
	padding: 1px;
	background: linear-gradient(140deg, var(--pa-glow-strong), transparent 40%);
	/* Border-only mask trick: both layers are fully opaque, so the colour choice is purely
	 * functional (alpha masking), --pa-canvas stands in for the prototype's literal opaque
	 * black, which reads identically here. */
	-webkit-mask: linear-gradient(var(--pa-canvas) 0 0) content-box, linear-gradient(var(--pa-canvas) 0 0);
	-webkit-mask-composite: xor;
	mask-composite: exclude;
	pointer-events: none;
}

.pa-home .gauge-head {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-block-end: 0.6rem;
	font-size: var(--pa-fs-xs);
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--pa-muted);
}

.pa-home .live-dot {
	display: inline-flex;
	align-items: center;
	gap: 0.45rem;
	color: var(--pa-green-400);
	font-weight: 600;
}

.pa-home .live-dot i {
	inline-size: 7px;
	block-size: 7px;
	border-radius: 50%;
	background: var(--pa-green);
	position: relative;
}

/* The halo used to be `animation: pa-pulse` on box-shadow, an every-frame repaint on a loop that
 * never stops (rule 11 is transform/opacity only). A pseudo-element scaling and fading is the same
 * effect on the compositor. `z-index: -1` puts it behind the dot's own background, which is where a
 * box-shadow painted, so the dot colour stays flat instead of being tinted by the halo. The parent
 * is `position: relative` with no stacking context of its own, so the negative index resolves
 * against the dot rather than escaping the card. */
.pa-home .live-dot i::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	border-radius: 50%;
	background: var(--pa-glow-strong);
	animation: pa-pulse 1.8s infinite;
}

/* scale(3): the old spread grew 0 to 7px around a 7px dot, i.e. 7px to 21px across. */
@keyframes pa-pulse {
	0%,
	100% {
		transform: scale(1);
		opacity: 1;
	}
	50% {
		transform: scale(3);
		opacity: 0;
	}
}

.pa-home .gauge {
	inline-size: 100%;
	block-size: auto;
}

.pa-home .needle {
	transform-origin: 160px 150px;
	transform: rotate(-118deg);
	transition: transform 1.9s cubic-bezier(0.34, 1.3, 0.35, 1);
}

.pa-home .gauge-arc {
	stroke-dasharray: 396;
	stroke-dashoffset: 396;
	transition: stroke-dashoffset 1.9s var(--pa-ease);
}

/* Single state class drives the whole hero (switch, headline, chips, speed lines), the gauge
 * sweep keys off `.hero.throttle` too, rather than a second, separately-toggled `.gauge.on` flag. */
.pa-home .hero.throttle .needle {
	transform: rotate(87deg);
}

.pa-home .hero.throttle .gauge-arc {
	stroke-dashoffset: 72;
}

.pa-home .gauge-read {
	text-align: center;
	margin-block-start: -1rem;
}

.pa-home .gauge-read .big {
	font-size: clamp(1.5rem, 3vw, 2rem);
	font-weight: 800;
	color: var(--pa-muted);
	letter-spacing: 0.06em;
	text-transform: uppercase;
	transition: color 0.4s;
}

.pa-home .hero.throttle .gauge-read .big {
	color: var(--pa-green-400);
}

.pa-home .gauge-read .lbl {
	font-size: var(--pa-fs-xs);
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--pa-muted);
}

.pa-home .chip {
	position: absolute;
	background: var(--pa-scrim-chip);
	border: 1px solid var(--pa-border-strong);
	border-radius: 12px;
	padding: 0.6rem 0.9rem;
	font-size: 0.78rem;
	font-weight: 600;
	display: flex;
	align-items: center;
	gap: var(--pa-xs);
	box-shadow: 0 14px 34px -12px color-mix(in srgb, var(--pa-canvas) 70%, transparent);
	animation: pa-float 6s ease-in-out infinite;
	opacity: 0;
	transition: opacity var(--pa-t-reveal) var(--pa-ease);
}

.pa-home .hero.throttle .chip {
	opacity: 1;
}

.pa-home .chip-2 {
	transition-delay: 0.25s;
}

.pa-home .chip-3 {
	transition-delay: 0.5s;
}

.pa-home .chip b {
	color: var(--pa-green-400);
	font-variant-numeric: tabular-nums;
}

.pa-home .chip svg {
	inline-size: 14px;
	block-size: 14px;
	color: var(--pa-green);
}

.pa-home .chip-1 {
	inset-block-start: -5%;
	inset-inline-start: -6%;
	animation-delay: 0s;
}

.pa-home .chip-2 {
	inset-block-start: 44%;
	/* Flush to the cockpit edge rather than the prototype's -7% overhang: the live grid column is
	 * narrower than the prototype's, so a negative inset pushed this chip past the viewport, where
	 * body{overflow-x:hidden} silently clipped its right half. It still overlaps the gauge card. */
	inset-inline-end: 0;
	animation-delay: 1.6s;
}

.pa-home .chip-3 {
	inset-block-end: -4%;
	inset-inline-start: 6%;
	animation-delay: 3.1s;
}

@keyframes pa-float {
	0%,
	100% {
		transform: translateY(0);
	}
	50% {
		transform: translateY(-9px);
	}
}

/* =================================================================
 * MARQUEE
 * ================================================================== */

.pa-home .trust {
	padding-block: 2.4rem;
	border-block: 1px solid var(--pa-border);
	background: var(--pa-surface);
}

.pa-home .trust p {
	text-align: center;
	font-size: var(--pa-fs-xs);
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--pa-muted);
	margin-block-end: 1.4rem;
}

.pa-home .marquee {
	overflow: hidden;
	position: relative;
	/* Alpha-only fade mask, --pa-canvas stands in for the prototype's literal opaque black;
	 * only the alpha at each stop shapes the fade, so the hue is irrelevant. */
	mask-image: linear-gradient(90deg, transparent, var(--pa-canvas) 8%, var(--pa-canvas) 92%, transparent);
}

.pa-home .marquee-track {
	display: flex;
	gap: var(--pa-2xl);
	inline-size: max-content;
	animation: pa-scroll 36s linear infinite;
}

/* home.js wraps the duplicated half in an aria-hidden span so screen readers do not hear all
   sixteen client names twice. `display: contents` keeps that wrapper out of the box tree, so the
   copied items stay direct flex items of the track and the gap between the two halves is identical
   to every other gap. The keyframe translates by exactly -50%, so any change here that gives the
   wrapper a box of its own would desynchronise the loop. */
.pa-home .marquee-clone {
	display: contents;
}

/* --- compact home form (client request, 2026-07-29) --------------------
 * Placeholders act as the visible labels on the HOMEPAGE form only; /contact/ keeps its labels.
 * The real <label> elements stay in the markup for assistive tech, visually clipped rather than
 * display:none so every input keeps the same computed accessible name (the goal select points at
 * its label via aria-labelledby). Short fields pair up two per row; select, message and submit
 * stay full width. */

.pa-home .pa-form .ff-el-input--label {
	position: absolute;
	inline-size: 1px;
	block-size: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

.pa-home .pa-form .fluentform fieldset {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 0.7rem 0.8rem;
	border: 0;
	margin: 0;
	padding: 0;
}

.pa-home .pa-form .fluentform .ff-el-group {
	margin-block: 0;
}

.pa-home .pa-form .fluentform .ff-el-group:has(select),
.pa-home .pa-form .fluentform .ff-el-group:has(textarea),
.pa-home .pa-form .fluentform .ff_submit_btn_wrapper {
	grid-column: 1 / -1;
}

/* One column again where two would squeeze the placeholders. */
@media (max-width: 560px) {
	.pa-home .pa-form .fluentform fieldset {
		grid-template-columns: 1fr;
	}
}

/* Pointer-target expansion for the front-page control the shared rule in components.css does not
   reach: each solution card's "Learn more" (24px). Same technique, same reason, see the note
   there. (The hero throttle switch used to be listed here too; it was removed with the 2026-07-29
   hero redesign.) */

.pa-home .sol > a::before {
	content: "";
	position: absolute;
	inset-inline: 0;
	inset-block-start: 50%;
	block-size: 44px;
	transform: translateY(-50%);
}

.pa-home .sol > a {
	position: relative;
}

/* Hover is the only pause since 2026-08-02 (the visible control was removed on client
   instruction; deviation recorded in the build log). */
.pa-home .marquee:hover .marquee-track {
	animation-play-state: paused;
}

@keyframes pa-scroll {
	to {
		transform: translateX(-50%);
	}
}

.pa-home .mk {
	font-weight: 700;
	font-size: 1.05rem;
	letter-spacing: 0.06em;
	color: var(--pa-silver);
	opacity: 0.55;
	white-space: nowrap;
	transition: opacity var(--pa-t-fast), color var(--pa-t-fast);
}

.pa-home .mk:hover {
	opacity: 1;
	color: var(--pa-text);
}

/* Logo items in the scrolling strip (the client's pick, 2026-08-02, over the static wall below).
 * Same silhouette logic as the wall: brightness(0) invert(1) flattens any source to white, so the
 * mixed-provenance files read as one system; opacity matches the text fallback's silver weight. */
.pa-home .mk-logo {
	display: inline-flex;
	align-items: center;
	flex: none;
}

.pa-home .mk-img {
	block-size: 32px;
	inline-size: auto;
	max-inline-size: 160px;
	object-fit: contain;
	filter: brightness(0) invert(1);
	opacity: 0.6;
	transition: opacity var(--pa-t-fast);
}

.pa-home .mk-logo:hover .mk-img {
	opacity: 0.95;
}

/* Publicis runs taller than it is wide (lion above the wordmark), so the shared 32px cap renders
 * its text illegibly small; client asked for a touch more (2026-08-02). Keyed on the alt text,
 * which comes from the entry title, so it survives reordering. */
.pa-home .mk-img[alt="PUBLICIS"] {
	block-size: 44px;
}

/* --- logo wall (static grid, 2026-08-02): DORMANT ALTERNATIVE ----------
 * Built, shown, and set aside the same day: the client saw this static-wall presentation and chose
 * the scrolling strip above instead. Kept (there is no git here) so flipping back is a markup-only
 * change in home-logos.php; nothing below matches any current markup. ------------------------
 * Rendered instead of the marquee once Client Logos entries exist: a static hairline grid of
 * cells, one mark each, name pill on hover (the composition Mark asked to mirror from his reference build's client
 * wall, re-tokened for the dark canvas). The 1px gaps ARE the borders: cells sit on a
 * border-colored backdrop with a 1px gap, which draws the full lattice without double borders. */

.pa-home .logo-wall {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 1px;
	background: var(--pa-border);
	border: 1px solid var(--pa-border);
	border-radius: var(--pa-r-md);
	overflow: clip;
}

@media (min-width: 640px) {
	.pa-home .logo-wall {
		grid-template-columns: repeat(4, 1fr);
	}
}

@media (min-width: 1100px) {
	.pa-home .logo-wall {
		grid-template-columns: repeat(8, 1fr);
	}
}

.pa-home .logo-wall__c {
	position: relative;
	background: var(--pa-canvas);
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 1.5rem 1rem;
	min-block-size: 96px;
	transition: background var(--pa-t-fast);
}

.pa-home .logo-wall__c:hover {
	background: var(--pa-surface);
}

.pa-home .logo-wall__c img {
	max-block-size: 38px;
	inline-size: auto;
	max-inline-size: 86%;
	object-fit: contain;
	opacity: 0.62;
	transition: opacity var(--pa-t-fast);
}

.pa-home .logo-wall__c:hover img {
	opacity: 1;
}

/* Default treatment: every mark flattened to a white silhouette. brightness(0) then invert(1)
 * lands on pure white whatever the source colours, so mixed files read as one system on the dark
 * canvas (several of the sourced marks are near-black and would vanish without this). Remove the
 * --mono class to show original colours instead. Transparent source files are required either
 * way: a baked-in background flattens to a solid block. */
.pa-home .logo-wall--mono .logo-wall__c img {
	filter: brightness(0) invert(1);
}

/* Name pill on hover. Hidden where hover does not exist; the name is
 * still real text for everyone via the .pa-sr span in the cell. */
.pa-home .logo-wall__c[data-name]::after {
	content: attr(data-name);
	position: absolute;
	inset-inline: 0;
	inset-block-end: 0.45rem;
	margin-inline: auto;
	inline-size: max-content;
	max-inline-size: 92%;
	background: var(--pa-raised);
	color: var(--pa-text);
	font-weight: 600;
	font-size: 0.64rem;
	letter-spacing: 0.04em;
	line-height: 1.2;
	white-space: nowrap;
	padding: 0.24rem 0.6rem;
	border-radius: var(--pa-r-pill);
	border: 1px solid var(--pa-border-strong);
	opacity: 0;
	transform: translateY(5px);
	pointer-events: none;
	transition: opacity var(--pa-t-fast), transform var(--pa-t-fast);
	z-index: 2;
}

.pa-home .logo-wall__c[data-name]:hover::after {
	opacity: 1;
	transform: translateY(0);
}

@media (hover: none) {
	.pa-home .logo-wall__c[data-name]::after {
		display: none;
	}
}

/* =================================================================
 * STATS
 * ================================================================== */

.pa-home .stats {
	background: var(--pa-canvas);
}

/* =================================================================
 * PILLARS
 * ================================================================== */

.pa-home .pillars-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 1.4rem;
	margin-block-start: 2.6rem;
}

.pa-home .pillar {
	background: var(--pa-surface);
	border: 1px solid var(--pa-border);
	border-radius: var(--pa-r-lg);
	padding: 2.2rem;
	transition: transform var(--pa-t) var(--pa-ease), border-color var(--pa-t), box-shadow var(--pa-t);
}

.pa-home .pillar:hover {
	transform: translateY(-6px);
	border-color: var(--pa-green-700);
	box-shadow: 0 24px 50px -24px var(--pa-glow-strong);
}

.pa-home .pillar:hover .icon-ring {
	border-color: var(--pa-green-400);
}

.pa-home .pillar h3 {
	font-size: var(--pa-fs-lg);
	text-transform: uppercase;
	letter-spacing: 0.04em;
	margin-block-end: 0.7rem;
}

.pa-home .pillar p {
	font-size: var(--pa-fs-base);
	color: var(--pa-text-2);
}

/* =================================================================
 * SOLUTIONS
 * ================================================================== */

.pa-home .solutions {
	background: var(--pa-surface);
	border-block: 1px solid var(--pa-border);
}

.pa-home .sol-head {
	display: flex;
	justify-content: space-between;
	align-items: end;
	gap: var(--pa-lg);
	flex-wrap: wrap;
}

.pa-home .sol-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 1.4rem;
	margin-block-start: 2.8rem;
}

.pa-home .sol {
	background: var(--pa-canvas);
	border: 1px solid var(--pa-border);
	border-radius: var(--pa-r);
	padding: 1.9rem;
	position: relative;
	overflow: hidden;
	transition: border-color var(--pa-t), transform var(--pa-t) var(--pa-ease);
}

.pa-home .sol::before {
	content: "";
	position: absolute;
	inset-inline: 0;
	inset-block-start: 0;
	block-size: 2px;
	background: linear-gradient(90deg, var(--pa-green), transparent);
	transform: scaleX(0);
	/* Equivalent to the prototype's `transform-origin: left` (0% ≡ left for the horizontal
	 * component), expressed without a physical keyword; this is LTR-only so no behaviour change. */
	transform-origin: 0%;
	transition: transform 0.4s var(--pa-ease);
}

.pa-home .sol:hover {
	border-color: var(--pa-border-strong);
	transform: translateY(-4px);
}

.pa-home .sol:hover::before {
	transform: scaleX(1);
}

.pa-home .sol .n {
	font-size: var(--pa-fs-xs);
	font-weight: 700;
	color: var(--pa-green-600);
	letter-spacing: 0.15em;
}

.pa-home .sol h3 {
	font-size: 1.05rem;
	margin-block: 0.6rem var(--pa-xs);
	margin-inline: 0;
}

.pa-home .sol p {
	font-size: 0.87rem;
	color: var(--pa-text-2);
}

.pa-home .sol a {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	/* An inline-flex row of 14px text sits at 22px tall, just under WCAG 2.5.8's 24px minimum
	   target size. This is a standalone card action, not a link inside a sentence, so the
	   inline-text exemption does not apply to it. */
	min-block-size: 24px;
	margin-block-start: var(--pa-sm);
	font-size: var(--pa-fs-sm);
	font-weight: 600;
	color: var(--pa-green-400);
}

.pa-home .sol a svg {
	inline-size: 14px;
	block-size: 14px;
	transition: transform 0.25s;
}

.pa-home .sol a:hover svg {
	transform: translateX(4px);
}

/* =================================================================
 * AI ENGINE (PULSE)
 * ================================================================== */

/* --- merged stats + engine ("wired band", 2026-07-29 redesign) ----------
 * The stats band and the PULSE section are one section now: header centred, the three stat tiles
 * in a band, a dashed feed line per tile running into the panel below, orbit visual left (scaled
 * up on client request), the four capability rows stacked on the right. */

.pa-home .es-head {
	text-align: center;
	max-inline-size: 46rem;
	margin-inline: auto;
}

.pa-home .es-head .sub {
	margin-block-end: 0;
}

.pa-home .es-stats {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	margin-block-start: 2.4rem;
	background: var(--pa-raised);
	border: 1px solid var(--pa-border);
	border-radius: var(--pa-r-md);
}

.pa-home .es-stats .stat {
	padding: 1.6rem 1.8rem 1.4rem;
	border-inline-start: 1px solid var(--pa-border);
}

.pa-home .es-stats .stat:first-child {
	border-inline-start: 0;
}

/* The wiring. Each line is one grid cell wide so it stays centred under its tile at every width.
   The travelling dot is transform/opacity only and pauses entirely under reduced motion (the
   static dashed line and end dot remain, so the connection still reads). */
.pa-home .es-links {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	block-size: 48px;
}

.pa-home .es-link {
	position: relative;
	justify-self: center;
	inline-size: 0;
	block-size: 100%;
	border-inline-start: 2px dashed var(--pa-border-strong);
}

.pa-home .es-link::before {
	content: "";
	position: absolute;
	inset-block-end: -3px;
	inset-inline-start: -4px;
	inline-size: 6px;
	block-size: 6px;
	border-radius: 50%;
	background: var(--pa-green);
}

.pa-home .es-link::after {
	content: "";
	position: absolute;
	inset-block-start: 0;
	inset-inline-start: -3px;
	inline-size: 4px;
	block-size: 4px;
	border-radius: 50%;
	background: var(--pa-green-400);
	opacity: 0;
}

@media (prefers-reduced-motion: no-preference) {
	.pa-home .es-link::after {
		animation: pa-feed 2.6s linear infinite;
	}

	.pa-home .es-link:nth-child(2)::after {
		animation-delay: 0.9s;
	}

	.pa-home .es-link:nth-child(3)::after {
		animation-delay: 1.7s;
	}
}

@keyframes pa-feed {
	0% {
		transform: translateY(0);
		opacity: 0;
	}
	15% {
		opacity: 1;
	}
	85% {
		opacity: 1;
	}
	100% {
		transform: translateY(44px);
		opacity: 0;
	}
}

.pa-home .es-panel {
	display: grid;
	grid-template-columns: 1.05fr 0.95fr;
	gap: clamp(2rem, 4vw, 3.5rem);
	align-items: center;
	background: var(--pa-surface);
	border: 1px solid var(--pa-border-strong);
	border-radius: var(--pa-r-lg);
	padding: clamp(1.6rem, 3vw, 2.8rem);
}

.pa-home .es-feats .feat:first-child {
	padding-block-start: 0;
}

.pa-home .es-feats .feat:last-child {
	padding-block-end: 0;
}

.pa-home .engine-visual {
	position: relative;
	/* No border or surface fill of its own since the 2026-07-29 merge: the visual now lives inside
	   the .es-panel card, and a card-within-a-card read as clutter. Just the glow on the panel. */
	border: 0;
	border-radius: var(--pa-r-lg);
	/* A circle, centred on the rings. This was an ellipse at 50% 40%, which put the halo about 56px
	   above the core and made the only luminous element in the panel disagree with a composition
	   built entirely from concentric circles. */
	background:
		radial-gradient(circle 340px at 50% 50%, color-mix(in srgb, var(--pa-green) 11%, transparent), transparent 76%);
	padding: clamp(1.5rem, 3vw, 3rem);
	display: grid;
	place-items: center;
	/* The composition is concentric, so the frame has to be square at every width. Height used to
	   come from a viewport clamp while width came from the grid column, so the aspect drifted as the
	   viewport changed and reached 1.89 once the grid stacked: a letterbox around a circle. */
	aspect-ratio: 1;
	/* The orbits are position:absolute and can still exceed the frame at the narrowest widths. Clip
	   here, same reasoning as .hero above: an unclipped decorative overflow widens the document and
	   therefore the containing block of the fixed header. */
	overflow-x: clip;
}

.pa-home .core {
	/* 150px, up from 120px: the picked engine option scales the whole orbit system up. The rings
	   below grew with it (260/365/470, from 220/310/400). */
	inline-size: 150px;
	block-size: 150px;
	border-radius: 50%;
	background: radial-gradient(circle at 34% 30%, var(--pa-green-400), var(--pa-green-700) 72%);
	display: grid;
	place-items: center;
	color: var(--pa-ink);
	font-weight: 800;
	letter-spacing: 0.08em;
	box-shadow: 0 0 70px var(--pa-glow-strong);
	position: relative;
	z-index: 2;
}

.pa-home .orbit {
	position: absolute;
	border: 1px dashed var(--pa-border-strong);
	border-radius: 50%;
	animation: pa-spin linear infinite;
}

/* Scaled up to fill the square frame. The rings are position:absolute so the panel padding does not
   constrain them: clearance is measured from the border, and o3 at 400 in a 524 frame leaves 62px. */
.pa-home .o1 {
	inline-size: 260px;
	block-size: 260px;
	animation-duration: 26s;
}

.pa-home .o2 {
	inline-size: 365px;
	block-size: 365px;
	animation-duration: 42s;
	animation-direction: reverse;
}

.pa-home .o3 {
	inline-size: 470px;
	block-size: 470px;
	animation-duration: 60s;
}

.pa-home .node {
	position: absolute;
	inset-block-start: -7px;
	inset-inline-start: 50%;
	inline-size: 13px;
	block-size: 13px;
	border-radius: 50%;
	background: var(--pa-green);
	box-shadow: 0 0 14px var(--pa-glow-strong);
}

.pa-home .o2 .node {
	background: var(--pa-silver);
}

/* A second node opposite the first. With one dot per ring and three independent rotation speeds and
   directions, the centre of mass wandered, so the panel was balanced differently on every page load
   and every screenshot. An opposed pair keeps the centre of mass on the ring centre at every phase.
   The pseudo-element rides the parent's rotation, so the existing reduced-motion rule covers it. */
.pa-home .orbit::after {
	content: "";
	position: absolute;
	inset-block-end: -7px;
	inset-inline-start: 50%;
	inline-size: 13px;
	block-size: 13px;
	border-radius: 50%;
	background: var(--pa-green);
	box-shadow: 0 0 14px var(--pa-glow-strong);
}

.pa-home .o2::after {
	background: var(--pa-silver);
}

.pa-home .feat {
	display: flex;
	gap: var(--pa-sm);
	padding-block: 1.1rem;
	padding-inline: 0;
	border-block-end: 1px solid var(--pa-border);
}

.pa-home .feat:last-child {
	border-block-end: 0;
}

.pa-home .feat svg {
	inline-size: 20px;
	block-size: 20px;
	color: var(--pa-green);
	flex: none;
	margin-block-start: 0.2rem;
}

.pa-home .feat h3 {
	/* h3 rather than h4: the section heading is an h2, so a feature title is the next level down.
	   The size is set here (not inherited from the element defaults) precisely so the level can be
	   correct without changing the rendered design. */
	font-size: 0.98rem;
	font-weight: 600;
	/* The UA stylesheet gives a heading a 1.33em block margin and it was never reset. That pushed
	   every title about 17px below its own icon, so the icon read as a stray mark in the margin
	   rather than a label for the row, and it left only 10px between "inside a row" and "between
	   rows", so the four rows never grouped. */
	margin-block: 0 var(--pa-xs);
}

.pa-home .feat p {
	font-size: 0.85rem;
	color: var(--pa-text-2);
	margin-block: 0;
}

/* =================================================================
 * CASES
 * ================================================================== */

.pa-home .cases {
	background: var(--pa-surface);
	border-block: 1px solid var(--pa-border);
}

/* =================================================================
 * SAFETY
 * ================================================================== */

.pa-home .safety-in {
	display: grid;
	grid-template-columns: 1.1fr 0.9fr;
	gap: clamp(2rem, 5vw, 4rem);
	align-items: center;
}

.pa-home .shield-list {
	display: grid;
	gap: var(--pa-sm);
	margin-block-start: 1.8rem;
}

.pa-home .shield {
	display: flex;
	gap: var(--pa-sm);
	align-items: start;
	background: var(--pa-surface);
	border: 1px solid var(--pa-border);
	border-radius: var(--pa-r);
	padding: 1.2rem 1.4rem;
}

.pa-home .shield svg {
	inline-size: 20px;
	block-size: 20px;
	color: var(--pa-green);
	flex: none;
	margin-block-start: 0.15rem;
}

.pa-home .shield p {
	font-size: 0.88rem;
	color: var(--pa-text-2);
}

.pa-home .shield b {
	color: var(--pa-text);
	font-weight: 600;
}

/* =================================================================
 * CTA
 * ================================================================== */

.pa-home .cta {
	padding-block: clamp(5rem, 10vw, 8rem);
}

.pa-home .cta-card {
	position: relative;
	border-radius: calc(var(--pa-r-lg) + 6px);
	overflow: hidden;
	/* No token matches this bespoke very-dark-green corner exactly; approximated as a 30% mix
	 * of green-700 into canvas, within a few RGB units of the source colour, and it fades to
	 * --pa-canvas within the same gradient anyway, so the difference is not visible. */
	background: linear-gradient(135deg, color-mix(in srgb, var(--pa-green-700) 30%, var(--pa-canvas)) 0%, var(--pa-canvas) 60%);
	border: 1px solid var(--pa-green-700);
	padding: clamp(3rem, 6vw, 5rem);
	text-align: center;
	isolation: isolate;
}

.pa-home .cta-card::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background: radial-gradient(50% 80% at 50% 0%, var(--pa-glow-strong), transparent 70%);
}

.pa-home .cta-card h2 {
	margin-inline: auto;
	max-width: 22ch;
}

.pa-home .cta-card .sub {
	margin-block: 0 2.4rem;
	margin-inline: auto;
}

.pa-home .cta-ctas {
	display: flex;
	gap: var(--pa-sm);
	justify-content: center;
	flex-wrap: wrap;
}

/* =================================================================
 * WHY PERFORMAD (flow)
 * ================================================================== */

.pa-home .why {
	background: var(--pa-surface);
	border-block: 1px solid var(--pa-border);
}

.pa-home .flow-svg {
	display: block;
	inline-size: 100%;
	block-size: auto;
	margin-block-start: 2.6rem;
}

/* Flow-diagram paint. Tokenised in v0.5.5; these were hex literals on the SVG markup, including
 * two PHP ternaries that picked a colour per node tone. Tone now picks a class, never a colour. */

.pa-home .flow-lines {
	stroke: var(--pa-decor-flowline);
}

.pa-home .flow-glow-in,
.pa-home .flow-glow-out {
	stop-color: var(--pa-green);
}

.pa-home .flow-disc {
	fill: var(--pa-raised);
	stroke: var(--pa-border-strong);
}

.pa-home .flow-ic {
	stroke: var(--pa-green-400);
}

.pa-home .flow-ic--silver {
	stroke: var(--pa-silver);
}

.pa-home .flow-ai {
	fill: var(--pa-silver);
}

.pa-home .rocket-body {
	fill: var(--pa-muted);
}

.pa-home .rocket-window {
	fill: var(--pa-canvas);
}

.pa-home .rocket-fin {
	fill: var(--pa-decor-fin);
}

.pa-home .rocket-flame {
	stroke: var(--pa-green);
}

.pa-home .flowline {
	animation: pa-dashdrift 18s linear infinite;
}

@keyframes pa-dashdrift {
	to {
		stroke-dashoffset: -180;
	}
}

.pa-home .ring {
	stroke: var(--pa-green);
	transform-box: fill-box;
	transform-origin: center;
	animation: pa-spin 46s linear infinite;
}

.pa-home .ring-rev {
	animation-direction: reverse;
}

/* The silver ring is quieter than the green one, it was `stroke-opacity=".45"` on the element. */
.pa-home .flow-ring--silver {
	stroke: var(--pa-silver);
	stroke-opacity: 0.45;
}

.pa-home .flow-labels {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 1.2rem;
	text-align: center;
	margin-block-start: 1.6rem;
}

.pa-home .fl h3 {
	font-size: 1rem;
	font-weight: 700;
}

.pa-home .fl h3 b {
	color: var(--pa-green-400);
}

.pa-home .fl p {
	font-size: var(--pa-fs-sm);
	color: var(--pa-text-2);
	max-width: 28ch;
	margin-block: var(--pa-xs) 0;
	margin-inline: auto;
}

.pa-home .rocket-anim {
	animation: pa-float 5s ease-in-out infinite;
}

.pa-home .flow-mobile {
	display: none;
}

.pa-home .fm {
	display: flex;
	gap: 1.1rem;
	align-items: start;
	padding-block: 1.05rem;
	padding-inline: 0;
	position: relative;
}

.pa-home .fm:not(:last-child)::after {
	content: "";
	position: absolute;
	inset-inline-start: 27px;
	inset-block-start: 66px;
	inset-block-end: -6px;
	border-inline-start: 2px dashed var(--pa-border-strong);
}

.pa-home .fm-ic {
	inline-size: 54px;
	block-size: 54px;
	border-radius: 50%;
	flex: none;
	display: grid;
	place-items: center;
	background: var(--pa-raised);
	border: 1.5px dashed var(--pa-green-600);
	/* The icon inside strokes with currentColor, so tone is set here rather than on the SVG.
	   Only the icon changes between tones: the dashed border stays green on both, as before. */
	color: var(--pa-green-400);
}

.pa-home .fm-ic--silver {
	color: var(--pa-silver);
}

.pa-home .fm-ic svg {
	inline-size: 24px;
	block-size: 24px;
}

.pa-home .fm h3 {
	font-size: 0.98rem;
	font-weight: 700;
}

.pa-home .fm h3 b {
	color: var(--pa-green-400);
}

.pa-home .fm p {
	font-size: 0.84rem;
	color: var(--pa-text-2);
	margin-block-start: 0.25rem;
}

/* =================================================================
 * RESPONSIVE
 * ================================================================== */

/* Large screens: the container and type grow via tokens.css; the gauge card grows with them so
   the hero's right column does not read as a small card floating in a wide cell. */
@media (min-width: 1680px) {
	.pa-home .gauge-card {
		inline-size: min(620px, 100%);
	}
}

@media (max-width: 1024px) {
	.pa-home .hero-grid,
	.pa-home .es-panel,
	.pa-home .safety-in {
		grid-template-columns: 1fr;
	}

	.pa-home .cockpit {
		margin-block-start: var(--pa-sm);
	}

	/* Once the grid stacks, the panel would take the whole 944px column and, being square, stand
	   944px tall. Cap it and centre it. The explicit inline-size is required, not optional:
	   justify-self on its own makes a square grid item shrink to fit its contents, and the orbits
	   are absolutely positioned so they contribute none, which collapses the panel entirely. */
	.pa-home .engine-visual {
		inline-size: min(520px, 100%);
		justify-self: center;
	}

	.pa-home .stats-grid {
		grid-template-columns: repeat(2, 1fr);
	}

	.pa-home .sol-grid,
	.pa-home .case-grid,
	.pa-home .pillars-grid {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (max-width: 760px) {
	.pa-home .flow-svg,
	.pa-home .flow-labels {
		display: none;
	}

	.pa-home .flow-mobile {
		display: grid;
		margin-block-start: 1.6rem;
	}
}

@media (max-width: 640px) {
	.pa-home .sol-grid,
	.pa-home .case-grid,
	.pa-home .pillars-grid,
	.pa-home .stats-grid,
	.pa-home .es-stats {
		grid-template-columns: 1fr;
	}

	/* With the tiles stacked, three side-by-side feed lines no longer point at anything. */
	.pa-home .es-links {
		display: none;
	}

	.pa-home .es-panel {
		margin-block-start: var(--pa-md);
	}

	.pa-home .es-stats .stat {
		border-inline-start: 0;
		border-block-start: 1px solid var(--pa-border);
	}

	.pa-home .es-stats .stat:first-child {
		border-block-start: 0;
	}

	.pa-home .chip-1 {
		inset-inline-start: 0;
	}

	.pa-home .chip-2 {
		inset-inline-end: 0;
	}

	/* The frame is square and capped at the viewport width here, so the desktop rings would overrun
	   it. Scale the whole system down instead, so the orbits sit inside the frame on a phone the
	   same way they do on a desktop. The glow scales with them. */
	.pa-home .engine-visual {
		background:
			radial-gradient(circle 190px at 50% 50%, color-mix(in srgb, var(--pa-green) 11%, transparent), transparent 76%),
			var(--pa-surface);
	}

	.pa-home .core {
		inline-size: 100px;
		block-size: 100px;
	}

	.pa-home .o1 {
		inline-size: 140px;
		block-size: 140px;
	}

	.pa-home .o2 {
		inline-size: 195px;
		block-size: 195px;
	}

	.pa-home .o3 {
		inline-size: 250px;
		block-size: 250px;
	}
}

/* =================================================================
 * REDUCED MOTION
 *
 * tokens.css already forces every animation/transition duration to ~0 sitewide; the rules below
 * are the explicit, semantic settle-states the task calls out by name (speed lines, marquee,
 * orbit/ring spins, needle sweep, float) so nothing is left mid-keyframe with an odd fill state
 * (e.g. the marquee track sitting half-translated with no duplicated second half to cover it).
 * ================================================================== */

@media (prefers-reduced-motion: reduce) {
	.pa-home .speedline {
		animation: none;
		opacity: 0.15;
	}

	.pa-home .marquee-track {
		animation: none;
		transform: none;
	}

	.pa-home .orbit,
	.pa-home .ring,
	.pa-home .icon-ring,
	.pa-home .icon-ring svg {
		animation: none;
	}

	.pa-home .needle,
	.pa-home .gauge-arc {
		transition: none;
	}

	.pa-home .chip,
	.pa-home .rocket-anim,
	.pa-home .live-dot i::after {
		animation: none;
	}

	.pa-home .flowline {
		animation: none;
	}
}
