/*
 * Page CSS for /ai/ (post "ai").
 * Lifted out of the page's Custom HTML blocks so it lives in the theme and in git instead of
 * in the database. Enqueued from functions.php for that page only, after style.css, which is
 * the same order the inline tags had. Section order below matches the page.
 */


/* =============================================================================
   1. pl-hero-default__art
   ============================================================================= */
/* /copilot/ hero art — the orb and its pipework, sliced out of background.svg.
   The pipes are the original organic routing, kept at their natural scale and centred on the orb,
   so they never stretch and never stop mid-air: at any viewport they simply reveal more of the run
   and leave through a turn. Everything hangs off one horizontal line (the orb centre), anchored to
   the hero's bottom edge, so the composition keeps the same relationship to the copy at any width.
   Page-specific art: lives here, not in the theme. */
/* same full-bleed mechanism the theme uses for .pl-section.alignfull, so the art can reach the
   viewport edges instead of being clipped to the 1152 content column */
.pl-hero-default.alignfull {
	width: 100vw;
	max-width: 100vw;
	margin-left: calc(50% - 50vw);
	margin-right: calc(50% - 50vw);
}
.pl-hero-default {
	position: relative;
	isolation: isolate;
	/* the hero is full-width, so this clips the art at the viewport and never adds sideways scroll */
	overflow-x: clip;
}
.pl-hero-default > *:not(.pl-hero-default__art) {
	position: relative;
	z-index: 1;
}
/* This hero sits tighter under the header than the shared pattern's 30x (120px). Only on this page,
   and !important because the block writes its padding as an inline style. */
.pl-hero-default {
	padding-top: 80px !important;
}
.pl-hero-default__title {
	margin-top: var(--wp--preset--spacing--6-x);
}
.pl-hero-default__sub {
	max-width: 872px;
	margin-top: var(--wp--preset--spacing--9-x);
	margin-inline: auto;
}
.pl-hero-default__actions {
	margin-top: var(--wp--preset--spacing--12-x);
}

/* The orb-centre line: 33px above the hero's bottom edge, as in the UI Kit. Every fixed-size piece
   of the artwork scales from one factor and about its own anchor point, so the pipes keep meeting
   the orb and the glow keeps its focus under it at any viewport. */
.pl-hero-default__art {
	--pl-art-scale: 1;
	--pl-orb: calc(160px * var(--pl-art-scale));
	position: absolute;
	left: 50%;
	width: 100vw;
	bottom: 33px;
	height: 0;
	transform: translateX(-50%);
	z-index: 0;
	pointer-events: none;
}

/* pipework at 1:1 — local (1580, 646.65) is the orb centre, pinned to the line above */
.pl-hero-default__pipes {
	position: absolute;
	left: 50%;
	top: 0;
	width: 4160px;
	height: 1250px;
	margin-left: -1580px;
	margin-top: -646.65px;
	transform: scale(var(--pl-art-scale));
	transform-origin: 1580px 646.65px;
	z-index: 1;
}
.pl-hero-default__orb {
	position: absolute;
	left: 50%;
	top: 0;
	width: var(--pl-orb);
	height: var(--pl-orb);
	transform: translate(-50%, -50%);
	z-index: 2;
}

/* ---- The backdrop. Figma group 9743:26220 holds five ellipses, so this is five divs with one blur
   each, in the group's paint order: Ellipse 226, Ellipse 229, Ellipse 228, Ellipse, nuevo.
   The parent is a zero-size box pinned to the orb-centre line and scaled about that very point, so
   the children are authored at 1:1 in the node's own numbers and the blurs scale with them.
   Two knobs, both on the parent:
     --pl-glow-scale   how big the whole backdrop is; follows the artwork unless overridden
     --pl-glow         how strong it is, 0 to 1
   Figma's group carries no opacity of its own, so 1 is the faithful value. ---- */
.pl-gradient-back-hero-ai {
	--pl-glow-scale: var(--pl-art-scale);
	--pl-glow: 1;
	position: absolute;
	left: 50%;
	top: 0;
	width: 0;
	height: 0;
	z-index: 0;
	pointer-events: none;
	opacity: var(--pl-glow);
	transform: scale(var(--pl-glow-scale));
	transform-origin: 0 0;
}
.pl-gradient-back-hero-ai > span {
	position: absolute;
	left: 0;
	top: 0;
	display: block;
	border-radius: 50%;
	transform: translate(-50%, -50%);
}
/* 1. Ellipse 226 (9743:26221) — the wide violet field, 28.43 under the orb centre.
      Figma blurs a 668x754 ellipse by 484.9. Reproducing that literally as filter: blur(484.9px)
      is what caused the ripples across the hero: at that radius the browser's Gaussian quantises
      and the falloff steps instead of sliding. A radial gradient gives the same soft field with a
      smooth ramp — and no 485px blur to composite. The box is Figma's own filter region
      (2608.04 x 2693.44), so the light reaches exactly as far as the node says it does. */
.pl-gradient-back-hero-ai__field {
	width: 2608.04px;
	height: 2693.44px;
	margin-top: 28.432px;
	background: radial-gradient(
		closest-side,
		rgba(119, 0, 255, 0.4) 0%,
		rgba(70, 1, 190, 0.26) 26%,
		rgba(20, 2, 130, 0.13) 50%,
		rgba(0, 2, 114, 0.04) 72%,
		rgba(0, 2, 114, 0) 88%
	);
}
/* 2. Ellipse 229 (9770:6863) — the bright core, the only tight blur of the four. Its gradient sits
      high in the shape (at 25.6%), which is what gives the pool its top edge. */
.pl-gradient-back-hero-ai__core {
	width: 432px;
	height: 367px;
	margin-left: -11px;
	margin-top: 353.852px;
	background: radial-gradient(58.78% 74.4% at 50% 25.6%, #3e11ff 0%, rgba(132, 74, 255, 0.8) 100%);
	filter: blur(60px);
}
/* 3. Ellipse 228 (9743:26243) — the same violet again, flatter and at half strength. Same 484.9
      blur, so the same treatment, sized to its own filter region (2608.04 x 2415.11). */
.pl-gradient-back-hero-ai__lift {
	width: 2608.04px;
	height: 2415.11px;
	margin-top: 167.599px;
	background: radial-gradient(
		closest-side,
		rgba(119, 0, 255, 0.4) 0%,
		rgba(70, 1, 190, 0.26) 26%,
		rgba(20, 2, 130, 0.13) 50%,
		rgba(0, 2, 114, 0.04) 72%,
		rgba(0, 2, 114, 0) 88%
	);
	opacity: 0.5;
}
/* 4. Ellipse (9743:26203) — flat #201872, no gradient, painted last of the four. */
.pl-gradient-back-hero-ai__base {
	width: 898.814px;
	height: 870.894px;
	margin-left: -1.474px;
	margin-top: 229.081px;
	background-color: #201872;
	filter: blur(147.244px);
}
/* 5. nuevo (9774:11614) — same box as __core but painted last, so it is the one you actually see.
      Three things make it read brighter than its twin: blur 85 instead of 60, no alpha on the outer
      stop, and a much larger gradient (96.23% x 121.82% against 58.78% x 74.4%). */
.pl-gradient-back-hero-ai__nuevo {
	width: 432px;
	height: 367px;
	margin-left: -11px;
	margin-top: 353.852px;
	background: radial-gradient(96.23% 121.82% at 50% 25.6%, #3e11ff 0%, #844aff 100%);
	filter: blur(85px);
}

/* The tight halo hugging the orb: node 9743:26206 is a 216.74px circle of #3532F9 under a 44.17
   blur, centred 3.08px below the orb centre. The orb is drawn over it, so it reads as a rim. */
.pl-hero-default__halo {
	position: absolute;
	left: 50%;
	top: 0;
	width: calc(216.74px * var(--pl-art-scale));
	height: calc(216.74px * var(--pl-art-scale));
	margin-top: calc(3.083px * var(--pl-art-scale));
	transform: translate(-50%, -50%);
	border-radius: 50%;
	background-color: #3532f9;
	filter: blur(calc(44.17px * var(--pl-art-scale)));
	z-index: 1;
	animation: pl-halo 22s ease-in-out infinite;
}
@keyframes pl-halo {
	0%, 100% { opacity: 0.82; }
	50%      { opacity: 1; }
}

/* The trace is static, deliberately, and this is the honest state of it.
   What is inside the orb is not a sphere wireframe — it is one routed circuit trace, a single motif
   that neither repeats nor wraps. Two things have been tried and both looked wrong:
     rotating it about the centre swept the whole drawing round, which reads as the lines leaving
       the circle rather than turning with it;
     scrolling three copies of it horizontally shows arbitrary fragments, because the motif does not
       tile — its left and right ends do not meet.
   A convincing spin needs artwork that can wrap: either a sphere wireframe (meridians and
   parallels, where the meridians' horizontal radius is what animates) or a trace authored to be
   seamless across its own width. That has to come from the UI Kit, not be invented here.
   The masked group and the faded mask are left in place, so dropping in tileable artwork is a
   one-line change: give this rule back its animation. */
@keyframes pl-wire {
	from { transform: translateX(0); }
	to   { transform: translateX(-222.678px); }
}

/* ---- one point of light per pipe. A zero-length dash with a round cap renders as a circle, so
   this reads as a travelling dot that follows every turn — never as a glowing line. ---- */
.pl-hero-default__beam {
	fill: none;
	stroke-linecap: round;
}
.pl-hero-default__beam-halo {
	stroke: #29c6ff;
	stroke-width: 11;
	opacity: 0.14;
}
.pl-hero-default__beam-core {
	stroke: #8fe3ff;
	stroke-width: 3.5;
	opacity: 0.8;
}
/* Slow, and deliberately out of step: the three durations share no small common multiple, the
   delays keep them from entering together, and the middle one runs the other way
   (animation-direction: reverse plays the same keyframes backwards, i.e. left to right). */
.pl-hero-default__beam--a { stroke-dasharray: 2 2500; animation: pl-beam-a 38s linear infinite; }
.pl-hero-default__beam--b { stroke-dasharray: 2 1900; animation: pl-beam-b 29s linear infinite 12s reverse; }
.pl-hero-default__beam--c { stroke-dasharray: 2 2250; animation: pl-beam-c 47s linear infinite 25s; }
@keyframes pl-beam-a { from { stroke-dashoffset: 0; }    to { stroke-dashoffset: -2580; } }
@keyframes pl-beam-b { from { stroke-dashoffset: 1980; } to { stroke-dashoffset: 0; } }
@keyframes pl-beam-c { from { stroke-dashoffset: 2330; } to { stroke-dashoffset: 0; } }

/* The junction dots breathe together — no per-dot delay, and a narrow opacity range, so the board
   reads as one soft pulse instead of three lights blinking in sequence. */
.pl-hero-default__node {
	animation: pl-node 9s ease-in-out infinite;
}
@keyframes pl-node {
	0%, 100% { opacity: 0.78; }
	50%      { opacity: 1; }
}

/* Each junction lights up exactly when its beam arrives. The moment is computed, not guessed:
   the node's distance along its own pipe divided by the distance the dash travels in one cycle,
   with the same duration and delay as that beam. Path lengths check out against
   getTotalLength() (2449 / 1824 / 2197), so the three coincide on screen.
     node 1 on beam A -> 33.71% of 38s, no delay
     node 2 on beam B -> 85.23% of 29s, 12s delay  (beam B runs reversed; this is wall-clock)
     node 3 on beam C -> 62.88% of 47s, 25s delay */
.pl-hero-default__node-flash {
	opacity: 0;
	transform-box: fill-box;
	transform-origin: center;
	animation-timing-function: ease-out;
	animation-iteration-count: infinite;
}
.pl-hero-default__node-flash--1 { animation-name: pl-node-flash-a; animation-duration: 38s; }
.pl-hero-default__node-flash--2 { animation-name: pl-node-flash-b; animation-duration: 29s; animation-delay: 12s; }
.pl-hero-default__node-flash--3 { animation-name: pl-node-flash-c; animation-duration: 47s; animation-delay: 25s; }
@keyframes pl-node-flash-a {
	0%, 32.1%   { opacity: 0; transform: scale(0.7); }
	33.71%      { opacity: 0.85; transform: scale(1.15); }
	35.5%, 100% { opacity: 0; transform: scale(2); }
}
@keyframes pl-node-flash-b {
	0%, 83.6%   { opacity: 0; transform: scale(0.7); }
	85.23%      { opacity: 0.85; transform: scale(1.15); }
	87%, 100%   { opacity: 0; transform: scale(2); }
}
@keyframes pl-node-flash-c {
	0%, 61.3%   { opacity: 0; transform: scale(0.7); }
	62.88%      { opacity: 0.85; transform: scale(1.15); }
	64.7%, 100% { opacity: 0; transform: scale(2); }
}

/* ---- a sparse dust field drifting across the hero ---- */
.pl-hero-default__dust {
	position: absolute;
	left: 0;
	bottom: 0;
	width: 100%;
	height: 780px;
	overflow: hidden;
	z-index: 0;
}
/* The dust is #5F3AFF, cycled through a lighter and a darker sibling every third particle so the
   field has depth instead of reading as one flat colour. The nth-child(3n) groups cut across the
   per-particle rules below, which only ever set position, size, drift and timing. */
.pl-hero-default__dust i {
	position: absolute;
	border-radius: 50%;
	background-color: #5f3aff;
	opacity: 0;
	animation-name: pl-dust;
	animation-timing-function: ease-in-out;
	animation-iteration-count: infinite;
}
.pl-hero-default__dust i:nth-child(3n+1) {
	background-color: #b7a5ff; /* #5F3AFF lightened, the ones that read as nearest */
}
.pl-hero-default__dust i:nth-child(3n+2) {
	background-color: #6d4bd8; /* and darkened, so they sit back into the glow */
}
/* --pl-op is set per particle further down and was tuned against a much darker backdrop; the
   multiplier lifts the whole field in one place rather than editing 32 rules, and min() keeps it
   from ever going over 1. */
@keyframes pl-dust {
	0%   { opacity: 0; transform: translate(0, 0); }
	18%  { opacity: min(1, calc(var(--pl-op) * 2.2)); }
	82%  { opacity: min(1, calc(var(--pl-op) * 2.2)); }
	100% { opacity: 0; transform: translate(var(--pl-drift), var(--pl-rise)); }
}
.pl-hero-default__dust i:nth-child(1) {
	left: 0.00%;
	top: 4.00%;
	width: 2px;
	height: 2px;
	--pl-rise: -36px;
	--pl-drift: -18px;
	--pl-op: 0.3;
	animation-duration: 24s;
	animation-delay: -0.0s;
}
.pl-hero-default__dust i:nth-child(2) {
	left: 61.80%;
	top: 73.45%;
	width: 2px;
	height: 2px;
	--pl-rise: -47px;
	--pl-drift: 14px;
	--pl-op: 0.22;
	animation-duration: 31s;
	animation-delay: -3.7s;
}
.pl-hero-default__dust i:nth-child(3) {
	left: 23.61%;
	top: 50.90%;
	width: 3px;
	height: 3px;
	--pl-rise: -58px;
	--pl-drift: -9px;
	--pl-op: 0.38;
	animation-duration: 38s;
	animation-delay: -7.4s;
}
.pl-hero-default__dust i:nth-child(4) {
	left: 85.41%;
	top: 28.35%;
	width: 2px;
	height: 2px;
	--pl-rise: -69px;
	--pl-drift: 22px;
	--pl-op: 0.26;
	animation-duration: 45s;
	animation-delay: -11.1s;
}
.pl-hero-default__dust i:nth-child(5) {
	left: 47.21%;
	top: 5.79%;
	width: 3px;
	height: 3px;
	--pl-rise: -80px;
	--pl-drift: 6px;
	--pl-op: 0.34;
	animation-duration: 29s;
	animation-delay: -0.8s;
}
.pl-hero-default__dust i:nth-child(6) {
	left: 9.02%;
	top: 75.24%;
	width: 2px;
	height: 2px;
	--pl-rise: -41px;
	--pl-drift: -13px;
	--pl-op: 0.18;
	animation-duration: 36s;
	animation-delay: -4.5s;
}
.pl-hero-default__dust i:nth-child(7) {
	left: 70.82%;
	top: 52.69%;
	width: 2px;
	height: 2px;
	--pl-rise: -52px;
	--pl-drift: -18px;
	--pl-op: 0.3;
	animation-duration: 43s;
	animation-delay: -8.2s;
}
.pl-hero-default__dust i:nth-child(8) {
	left: 32.62%;
	top: 30.14%;
	width: 2px;
	height: 2px;
	--pl-rise: -63px;
	--pl-drift: 14px;
	--pl-op: 0.22;
	animation-duration: 27s;
	animation-delay: -11.9s;
}
.pl-hero-default__dust i:nth-child(9) {
	left: 94.43%;
	top: 7.59%;
	width: 3px;
	height: 3px;
	--pl-rise: -74px;
	--pl-drift: -9px;
	--pl-op: 0.38;
	animation-duration: 34s;
	animation-delay: -1.6s;
}
.pl-hero-default__dust i:nth-child(10) {
	left: 56.23%;
	top: 77.04%;
	width: 2px;
	height: 2px;
	--pl-rise: -85px;
	--pl-drift: 22px;
	--pl-op: 0.26;
	animation-duration: 41s;
	animation-delay: -5.3s;
}
.pl-hero-default__dust i:nth-child(11) {
	left: 18.03%;
	top: 54.49%;
	width: 3px;
	height: 3px;
	--pl-rise: -46px;
	--pl-drift: 6px;
	--pl-op: 0.34;
	animation-duration: 25s;
	animation-delay: -9.0s;
}
.pl-hero-default__dust i:nth-child(12) {
	left: 79.84%;
	top: 31.94%;
	width: 2px;
	height: 2px;
	--pl-rise: -57px;
	--pl-drift: -13px;
	--pl-op: 0.18;
	animation-duration: 32s;
	animation-delay: -12.7s;
}
.pl-hero-default__dust i:nth-child(13) {
	left: 41.64%;
	top: 9.38%;
	width: 2px;
	height: 2px;
	--pl-rise: -68px;
	--pl-drift: -18px;
	--pl-op: 0.3;
	animation-duration: 39s;
	animation-delay: -2.4s;
}
.pl-hero-default__dust i:nth-child(14) {
	left: 3.44%;
	top: 78.83%;
	width: 2px;
	height: 2px;
	--pl-rise: -79px;
	--pl-drift: 14px;
	--pl-op: 0.22;
	animation-duration: 46s;
	animation-delay: -6.1s;
}
.pl-hero-default__dust i:nth-child(15) {
	left: 65.25%;
	top: 56.28%;
	width: 3px;
	height: 3px;
	--pl-rise: -40px;
	--pl-drift: -9px;
	--pl-op: 0.38;
	animation-duration: 30s;
	animation-delay: -9.8s;
}
.pl-hero-default__dust i:nth-child(16) {
	left: 27.05%;
	top: 33.73%;
	width: 2px;
	height: 2px;
	--pl-rise: -51px;
	--pl-drift: 22px;
	--pl-op: 0.26;
	animation-duration: 37s;
	animation-delay: -13.5s;
}
.pl-hero-default__dust i:nth-child(17) {
	left: 88.85%;
	top: 11.18%;
	width: 3px;
	height: 3px;
	--pl-rise: -62px;
	--pl-drift: 6px;
	--pl-op: 0.34;
	animation-duration: 44s;
	animation-delay: -3.2s;
}
.pl-hero-default__dust i:nth-child(18) {
	left: 50.66%;
	top: 80.63%;
	width: 2px;
	height: 2px;
	--pl-rise: -73px;
	--pl-drift: -13px;
	--pl-op: 0.18;
	animation-duration: 28s;
	animation-delay: -6.9s;
}
.pl-hero-default__dust i:nth-child(19) {
	left: 12.46%;
	top: 58.08%;
	width: 2px;
	height: 2px;
	--pl-rise: -84px;
	--pl-drift: -18px;
	--pl-op: 0.3;
	animation-duration: 35s;
	animation-delay: -10.6s;
}
.pl-hero-default__dust i:nth-child(20) {
	left: 74.26%;
	top: 35.53%;
	width: 2px;
	height: 2px;
	--pl-rise: -45px;
	--pl-drift: 14px;
	--pl-op: 0.22;
	animation-duration: 42s;
	animation-delay: -0.3s;
}
.pl-hero-default__dust i:nth-child(21) {
	left: 36.07%;
	top: 12.97%;
	width: 3px;
	height: 3px;
	--pl-rise: -56px;
	--pl-drift: -9px;
	--pl-op: 0.38;
	animation-duration: 26s;
	animation-delay: -4.0s;
}
.pl-hero-default__dust i:nth-child(22) {
	left: 97.87%;
	top: 82.42%;
	width: 2px;
	height: 2px;
	--pl-rise: -67px;
	--pl-drift: 22px;
	--pl-op: 0.26;
	animation-duration: 33s;
	animation-delay: -7.7s;
}
.pl-hero-default__dust i:nth-child(23) {
	left: 59.67%;
	top: 59.87%;
	width: 3px;
	height: 3px;
	--pl-rise: -78px;
	--pl-drift: 6px;
	--pl-op: 0.34;
	animation-duration: 40s;
	animation-delay: -11.4s;
}
.pl-hero-default__dust i:nth-child(24) {
	left: 21.48%;
	top: 37.32%;
	width: 2px;
	height: 2px;
	--pl-rise: -39px;
	--pl-drift: -13px;
	--pl-op: 0.18;
	animation-duration: 24s;
	animation-delay: -1.1s;
}
.pl-hero-default__dust i:nth-child(25) {
	left: 83.28%;
	top: 14.77%;
	width: 2px;
	height: 2px;
	--pl-rise: -50px;
	--pl-drift: -18px;
	--pl-op: 0.3;
	animation-duration: 31s;
	animation-delay: -4.8s;
}
.pl-hero-default__dust i:nth-child(26) {
	left: 45.08%;
	top: 84.22%;
	width: 2px;
	height: 2px;
	--pl-rise: -61px;
	--pl-drift: 14px;
	--pl-op: 0.22;
	animation-duration: 38s;
	animation-delay: -8.5s;
}
.pl-hero-default__dust i:nth-child(27) {
	left: 6.89%;
	top: 61.67%;
	width: 3px;
	height: 3px;
	--pl-rise: -72px;
	--pl-drift: -9px;
	--pl-op: 0.38;
	animation-duration: 45s;
	animation-delay: -12.2s;
}
.pl-hero-default__dust i:nth-child(28) {
	left: 68.69%;
	top: 39.12%;
	width: 2px;
	height: 2px;
	--pl-rise: -83px;
	--pl-drift: 22px;
	--pl-op: 0.26;
	animation-duration: 29s;
	animation-delay: -1.9s;
}
.pl-hero-default__dust i:nth-child(29) {
	left: 30.50%;
	top: 16.56%;
	width: 3px;
	height: 3px;
	--pl-rise: -44px;
	--pl-drift: 6px;
	--pl-op: 0.34;
	animation-duration: 36s;
	animation-delay: -5.6s;
}
.pl-hero-default__dust i:nth-child(30) {
	left: 92.30%;
	top: 86.01%;
	width: 2px;
	height: 2px;
	--pl-rise: -55px;
	--pl-drift: -13px;
	--pl-op: 0.18;
	animation-duration: 43s;
	animation-delay: -9.3s;
}
.pl-hero-default__dust i:nth-child(31) {
	left: 54.10%;
	top: 63.46%;
	width: 2px;
	height: 2px;
	--pl-rise: -66px;
	--pl-drift: -18px;
	--pl-op: 0.3;
	animation-duration: 27s;
	animation-delay: -13.0s;
}
.pl-hero-default__dust i:nth-child(32) {
	left: 15.91%;
	top: 40.91%;
	width: 2px;
	height: 2px;
	--pl-rise: -77px;
	--pl-drift: 14px;
	--pl-op: 0.22;
	animation-duration: 34s;
	animation-delay: -2.7s;
}

@media (prefers-reduced-motion: reduce) {
	.pl-hero-default__beam,
	.pl-hero-default__halo,
	.pl-hero-default__node,
	.pl-hero-default__dust i,
	.pl-hero-default__node-flash {
		animation: none;
	}
	.pl-hero-default__beam {
		display: none;
	}
	.pl-hero-default__dust {
		display: none;
	}
}

@media (max-width: 1023px) {
	.pl-hero-default__art { --pl-art-scale: 0.68; bottom: 28px; }
	.pl-hero-default__dust { height: 620px; }
}
@media (max-width: 600px) {
	.pl-hero-default__art { --pl-art-scale: 0.44; bottom: 24px; }
	.pl-hero-default__dust { height: 520px; }
}

/* =============================================================================
   2. pl-card-image-row__cut
   ============================================================================= */
	/* .pl-section sets overflow:hidden; this section opts out so the corner light can spill past its
	   edges and be cut by section 3 instead of by the section's own box (same escape hatch
	   .pl-section--intelligent-modeling uses in style.css). */
	.pl-card-image-row__section {
		overflow: visible;
	}

	/* Section 2 lighting. Both layers are page-specific art from the Media Library and sit under the
	   card; .pl-section already gives this section position/isolation and clips them at its edges. */
	.pl-card-image-row__section > .pl-card-image-row__cut {
		position: absolute;
		z-index: 0;
		margin: 0;
		max-width: none;
		pointer-events: none;
	}
	/* bottom-right pool of light: pinned to that corner, and the next section cuts it off, which is
	   what makes the transition between the two read as a hard edge */
	.pl-card-image-row__section > .pl-card-image-row__cut {
		/* Sized off the section, not in pixels, so it tracks any viewport. bottom/right 0 puts the
		   box's corner on the section's corner; translating it by half its own size then puts its
		   focal point there. */
		bottom: 0;
		right: 0;
		width: 100%;
		height: 200%;
		transform: translate(50%, 50%);
		border-radius: 50%;
		background: radial-gradient(
			closest-side,
			rgba(34, 25, 88, 0.95) 0%,
			rgba(34, 25, 88, 0.44) 38%,
			rgba(34, 25, 88, 0) 74%
		);
	}

/* =============================================================================
   3. pl-card-image-row__connectors
   ============================================================================= */
	.pl-card-image-row__connectors {
		/* flush to the card edge: x=47.5 in the SVG is where the boxes start, and the card clips the rest */
		position: absolute;
		top: 0;
		right: 0;
		/* the theme blockGap lands on this img as margin-block-start; absolute or not, it shifts it */
		margin: 0;
		z-index: 0;
		pointer-events: none;
	}
	.pl-card-image-row__square {
		position: relative;
		z-index: 1;
	}
	.pl-card-image-row__square img {
		width: 172px;
		height: 172px;
	}
	/* Once the columns stack, the art cannot stay pinned to the right: it would lie across the copy.
	   So it takes a quarter turn and becomes a band along the bottom of the card, with the One layer
	   tile centred on it — the same two pieces, re-laid for a narrow screen.

	   Everything here is a ratio, never a pixel, so it holds at any width. The art is 358 x 640; a
	   quarter turn swaps those, so for its long side to span the card its width must be set to
	   358/640 of the card and its height follows from the intrinsic ratio, landing at exactly the
	   card's width. Rotation is about the centre, so the two translate values then re-centre it and
	   drop it onto the bottom edge — and because translate percentages are of the *un-rotated* box,
	   the same ratio comes back in the vertical one. */
	@media (max-width: 781px) {
		.pl-card-image-row__card {
			/* 16x is fluid and bottoms out at 24px, which is too tight for a card this dense.
			   A flat 8x gives the copy room without reaching for the desktop inset.
			   !important because the block writes its padding as an inline style, and nothing but
			   !important outranks that. */
			padding: var(--wp--preset--spacing--8-x) !important;
		}
		.pl-card-image-row__connectors {
			--pl-conn-ratio: 0.559375; /* 358 / 640 */
			--pl-conn-inset: var(--wp--preset--spacing--8-x);
			top: auto;
			right: auto;
			/* inset by the card's own padding, so the band lines up exactly with the figure below it
			   — the figure lives inside that padding, and matching the two is what lets the tile
			   centre on the band with no fudge factor */
			bottom: var(--pl-conn-inset);
			left: 50%;
			width: calc(var(--pl-conn-ratio) * (100% - 2 * var(--pl-conn-inset)));
			height: auto;
			transform: translate(-50%, calc(50% - var(--pl-conn-ratio) * 50%)) rotate(90deg);
		}
		/* The tile sits over the band and centres in it: the same ratio inverted gives the figure
		   the band's own height, so centring in the figure centres on the band.
		   Scoped through the card to clear 0,2,0 — WordPress's global styles zero the block margin
		   through :where(.is-layout-flow) > :first-child, which ties on specificity and is printed
		   after this file, so a bare class loses the tie. */
		.pl-card-image-row__card .pl-card-image-row__square {
			display: flex;
			align-items: center;
			justify-content: center;
			aspect-ratio: 640 / 358;
			margin-top: var(--wp--preset--spacing--8-x);
		}
	}

/* =============================================================================
   4. pl-icon-card-grid__gridbg
   ============================================================================= */
	/* Section 3 background grid — page-specific asset from the Media Library, covering the section.
	   .pl-section already provides position/isolation and clips it at the edges. */
	.pl-icon-card-grid__section > .pl-icon-card-grid__gridbg {
		position: absolute;
		inset: 0;
		z-index: 0;
		background-image: url("/wp-content/uploads/2026/08/gridsquares.svg");
		background-size: cover;
		background-position: center;
		background-repeat: no-repeat;
		pointer-events: none;
	}

/* =============================================================================
   5. pl-chat-mock
   ============================================================================= */
/* /copilot/ — animated SqlDBM AI conversation mockup (page-specific).

   Sizing model: one root font-size drives the whole mock and every measurement is in em, so the
   proportions hold while the TEXT STAYS LEGIBLE. The earlier version scaled everything by a single
   pixel factor, which shrank the copy to nothing on a phone; here the type only steps down a
   little and the window grows taller instead. The container has no fixed height at all — the front
   window's own content sets it, and the conversation area has its own height with the thread
   scrolling inside, so nothing has to be squashed to fit. */
.pl-chat-mock {
	--pl-chat-h: 21em;          /* height of the conversation area  */
	/* How far the thread rides up is no longer a hand-set number. --pl-chat-end measures it: the
	   thread's own height (100%) less the visible height, so its LAST line always lands on the
	   bottom edge of the window — real autoscroll, at any font size and on any phone. min() keeps
	   it from ever scrolling downwards if the thread is shorter than the view. */
	--pl-chat-view: calc(var(--pl-chat-h) - 1em);
	--pl-chat-end: min(0px, calc(var(--pl-chat-view) - 100%));
	position: relative;
	width: 100%;
	max-width: 61.5em;          /* 984 / 16 */
	font-size: clamp(11px, 1.15vw, 16px);
	margin-inline: auto;
	/* No room above: in the UI Kit the front window is the TOPMOST of the three and each window
	   behind it steps DOWN and OUT, so the stack fans towards the bottom of the section. */
	padding-top: 0;
	/* and the stack runs off the bottom edge: the composer stays visible, the window's bottom border
	   does not. Measured off node 9743:27186. This section carries overflow:visible (its closing
	   glow needs to spill), so the cut is not made here — the NEXT section's own background paints
	   over what hangs below, which is the same mechanism section 2 uses for its corner light. */
	margin-bottom: -0.8em;
	font-family: var(--wp--preset--font-family--open-sans);
}
.pl-chat-mock__win {
	border-radius: 1em;
	background-color: var(--wp--preset--color--gray-900);
}
.pl-chat-mock__win::before {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: inherit;
	padding: 1px;
	background: linear-gradient(165deg, #01eaff 0%, #6161ff 49%, #bb4eff 100%);
	-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
	-webkit-mask-composite: xor;
	mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
	mask-composite: exclude;
	pointer-events: none;
}
/* the two decorative windows sit behind and are anchored to the front one's box */
.pl-chat-mock__win--back,
.pl-chat-mock__win--mid {
	position: absolute;
	z-index: 0;
}
/* Offsets read off node 9743:27186 at its authored 1920 width, where the mock's em is 16px:
   the front window's top is 503, --mid is 579 (+76px = 4.75em) and --back is 651 (+148px = 9.25em).
   Each one keeps the front window's height and is simply pushed down, so the negative bottom
   mirrors the top — and the section clips whatever hangs below it. */
.pl-chat-mock__win--back {
	left: 0;
	right: 0.05em;
	top: 9.25em;
	bottom: -9.25em;
}
.pl-chat-mock__win--back::before {
	opacity: 0.24;
}
.pl-chat-mock__win--mid {
	left: 2.9375em;
	right: 2.9375em;
	top: 4.75em;
	bottom: -4.75em;
}
.pl-chat-mock__win--mid::before {
	opacity: 0.48;
	background: linear-gradient(161deg, #01eaff 0%, #6161ff 49%, #bb4eff 100%);
}
/* the front window is in normal flow: it is what gives the whole mock its height */
.pl-chat-mock__win--front {
	position: relative;
	z-index: 1;
	margin-inline: 5.75em;
	display: flex;
	flex-direction: column;
}
.pl-chat-mock__win--front::before {
	background: linear-gradient(194deg, #c81fff 0%, #ffb700 100%);
}

/* The two light lines passing behind the browser, drawn in CSS.
   This used to be the exported SVG with the whole group translated sideways, and that is exactly
   why it looked fake: sliding the drawing reads as a picture moving, not as light travelling. Now
   the line STAYS PUT and a bright segment runs along it, which is what the eye expects.
   It still lives inside the mock so it anchors itself: top 52% is the middle of the window stack
   whatever height the mock ends up with, and the windows are opaque, so the lines show only to the
   left and right of them. */
.pl-chat-mock__beam {
	position: absolute;
	left: 50%;
	top: 52%;
	z-index: 0;
	width: 100vw;
	max-width: none;
	height: 14.75em;
	transform: translate(-50%, -50%);
	pointer-events: none;
}
/* the resting line: 1px, and faded at both ends so it never stops at a hard edge */
.pl-chat-mock__beam i {
	position: absolute;
	left: -8%;
	width: 116%;
	height: 1px;
	border-radius: 1px;
	background: linear-gradient(
		90deg,
		rgba(95, 58, 255, 0) 0%,
		rgba(95, 58, 255, 0.5) 14%,
		rgba(95, 58, 255, 0.5) 86%,
		rgba(95, 58, 255, 0) 100%
	);
}
/* and the light that travels along it — a short bright segment whose background-position moves */
.pl-chat-mock__beam i::after {
	content: "";
	position: absolute;
	inset: -1px 0;
	background: linear-gradient(
		90deg,
		rgba(123, 92, 255, 0) 0%,
		#7b5cff 40%,
		#d0a6ff 50%,
		#7b5cff 60%,
		rgba(123, 92, 255, 0) 100%
	);
	background-repeat: no-repeat;
	background-size: 32% 100%;
	animation: pl-beam-run 7s linear infinite;
}
@keyframes pl-beam-run {
	from { background-position: -34% 0; }
	to   { background-position: 134% 0; }
}
/* two lines, tilted against each other, and out of step so they never cross together */
.pl-chat-mock__beam i:nth-child(1) {
	top: 34%;
	transform: rotate(-1.5deg);
}
.pl-chat-mock__beam i:nth-child(2) {
	top: 68%;
	transform: rotate(1.1deg);
}
.pl-chat-mock__beam i:nth-child(2)::after {
	animation-delay: -3.4s;
}

/* Title bar. No mark: the label starts at the same inset as the composer's placeholder — the
   input's own margin (1.5em) plus its padding (1.125em). */
.pl-chat-mock__bar {
	display: flex;
	align-items: center;
	flex: 0 0 auto;
	min-height: 4.75em;
	padding: 0 2.875em 0 2.625em;
	border-bottom: 1px solid var(--wp--preset--color--slate-800);
}
.pl-chat-mock__name {
	font-family: var(--wp--preset--font-family--gilmer);
	font-size: 1.25em;
	line-height: 1;
	color: #d3d6da;
}

/* Conversation area: its own height, its own overflow, the thread rides up inside it. */
.pl-chat-mock__body {
	position: relative;
	flex: 0 0 auto;
	height: var(--pl-chat-h);
	padding: 1em 2.25em 0;
	font-size: 0.875em;
	line-height: 1.6;
	color: #d3d6da;
	overflow: hidden;
}
.pl-chat-mock__thread {
	animation: plcm-scroll 15s linear infinite;
}
.pl-chat-mock__user {
	display: flex;
	justify-content: flex-end;
}
.pl-chat-mock__user--2 {
	margin-top: 1.714em;
}
.pl-chat-mock__bubble {
	margin: 0;
	max-width: 28em;
	padding: 0.5em 1.285em;
	border-radius: 1.285em;
	background-color: #393e59;
}
.pl-chat-mock__pill {
	display: inline-flex;
	align-items: center;
	gap: 0.571em;
	margin-top: 1.714em;
	padding: 0.285em 1.142em;
	border: 1px solid #3f4248;
	border-radius: 1.107em;
}
/* spinner and check share one slot, so the pill never changes width */
.pl-chat-mock__status {
	position: relative;
	display: inline-block;
	width: 1em;
	height: 1em;
	vertical-align: -0.14em;
}
.pl-chat-mock__spin {
	position: absolute;
	inset: 1px;
	border-radius: 50%;
	border: 1.5px solid #3f4248;
	border-top-color: #969aa3;
}
.pl-chat-mock__check {
	position: absolute;
	inset: 0;
	line-height: 1;
	color: #17cc86;
}
.pl-chat-mock__reply > *,
.pl-chat-mock__reply2 > * {
	margin: 0;
}
.pl-chat-mock__reply,
.pl-chat-mock__reply2,
.pl-chat-mock__reply p + p,
.pl-chat-mock__reply ul + p,
.pl-chat-mock__reply ul,
.pl-chat-mock__reply2 p + p {
	margin-top: 1.142em;
}
.pl-chat-mock__reply ul {
	list-style: none;
	padding-left: 0.857em;
}
.pl-chat-mock__reply li::before {
	content: "· ";
	color: #969aa3;
}
.pl-chat-mock__code {
	color: #5090ff;
}
.pl-chat-mock__ok {
	color: #17cc86;
}

/* Composer. flex-shrink: 0 is the fix for the bar that got squashed: the body used to be the
   flexible one and the input paid for the extra content. */
.pl-chat-mock__input {
	position: relative;
	display: flex;
	align-items: center;
	flex: 0 0 auto;
	gap: 0.857em;
	height: 3.428em;
	margin: 0 1.714em 2.785em;
	padding: 0 0.571em 0 1.285em;
	border: 1px solid rgba(248, 250, 252, 0.12);
	border-radius: 0.571em;
	background-color: rgba(11, 12, 15, 0.48);
	font-size: 0.875em;
	color: #969aa3;
}
.pl-chat-mock__field {
	position: relative;
	flex: 1 1 auto;
	min-width: 0;
	white-space: nowrap;
	overflow: hidden;
}
.pl-chat-mock__ph,
.pl-chat-mock__typed {
	display: block;
}
.pl-chat-mock__typed {
	position: absolute;
	top: 0;
	left: 0;
	width: max-content;
	max-width: 0;
	overflow: hidden;
	color: #d3d6da;
}
.pl-chat-mock__caret {
	display: inline-block;
	width: 1px;
	height: 1.142em;
	margin-left: 1px;
	vertical-align: -0.21em;
	background-color: #d3d6da;
}
.pl-chat-mock__clip {
	width: 1.285em;
	height: 1.285em;
	flex-shrink: 0;
	opacity: 0.5;
}
.pl-chat-mock__send {
	display: grid;
	place-items: center;
	width: 2.357em;
	height: 2.357em;
	flex-shrink: 0;
	border-radius: 0.5em;
	background-color: var(--wp--preset--color--blue-600);
}
.pl-chat-mock__send svg {
	width: 1em;
	height: 1em;
}

/* ---- The exchange, on one shared 15s timeline so every step stays in sync ----
   type the question -> send it -> query the model -> answer -> the user confirms -> it documents. */
.pl-chat-mock__user,
.pl-chat-mock__pill,
.pl-chat-mock__l1,
.pl-chat-mock__l2,
.pl-chat-mock__l3,
.pl-chat-mock__l4,
.pl-chat-mock__reply2 {
	opacity: 0;
}
.pl-chat-mock__typed,
.pl-chat-mock__typed2,
.pl-chat-mock__ph,
.pl-chat-mock__caret,
.pl-chat-mock__caret2,
.pl-chat-mock__spin,
.pl-chat-mock__check,
.pl-chat-mock__user,
.pl-chat-mock__pill,
.pl-chat-mock__l1,
.pl-chat-mock__l2,
.pl-chat-mock__l3,
.pl-chat-mock__l4,
.pl-chat-mock__reply2 {
	animation-duration: 15s;
	animation-iteration-count: infinite;
	animation-timing-function: linear;
}
.pl-chat-mock__typed { animation-name: plcm-type; }
@keyframes plcm-type {
	0%, 1.8%   { max-width: 0; opacity: 1; }
	9.1%       { max-width: 26em; opacity: 1; }
	9.9%       { max-width: 26em; opacity: 1; }
	10%, 100%  { max-width: 26em; opacity: 0; }
}
.pl-chat-mock__typed2 { animation-name: plcm-type2; }
@keyframes plcm-type2 {
	0%, 31.8%   { max-width: 0; opacity: 0; }
	31.9%       { max-width: 0; opacity: 1; }
	35.5%       { max-width: 3em; opacity: 1; }
	36.3%       { max-width: 3em; opacity: 1; }
	36.4%, 100% { max-width: 3em; opacity: 0; }
}
.pl-chat-mock__ph { animation-name: plcm-placeholder; }
@keyframes plcm-placeholder {
	0%, 1.7%     { opacity: 1; }
	1.8%, 9.9%   { opacity: 0; }
	10%, 31.8%   { opacity: 1; }
	31.9%, 36.3% { opacity: 0; }
	36.4%, 100%  { opacity: 1; }
}
.pl-chat-mock__caret { animation-name: plcm-caret; animation-timing-function: steps(1, end); }
@keyframes plcm-caret {
	0%, 1.7%    { opacity: 0; }
	1.8%, 3.4%  { opacity: 1; }
	3.5%, 5.1%  { opacity: 0; }
	5.2%, 6.8%  { opacity: 1; }
	6.9%, 8.4%  { opacity: 0; }
	8.5%, 9.9%  { opacity: 1; }
	10%, 100%   { opacity: 0; }
}
.pl-chat-mock__caret2 { animation-name: plcm-caret2; animation-timing-function: steps(1, end); }
@keyframes plcm-caret2 {
	0%, 31.8%    { opacity: 0; }
	31.9%, 33.4% { opacity: 1; }
	33.5%, 34.8% { opacity: 0; }
	34.9%, 36.3% { opacity: 1; }
	36.4%, 100%  { opacity: 0; }
}
.pl-chat-mock__user--1 { animation-name: plcm-user; }
@keyframes plcm-user {
	0%, 9.9%     { opacity: 0; transform: translateY(6px); }
	10.9%, 88.6% { opacity: 1; transform: none; }
	93.6%, 100%  { opacity: 0; transform: none; }
}
.pl-chat-mock__pill { animation-name: plcm-pill; }
@keyframes plcm-pill {
	0%, 11.7%    { opacity: 0; transform: translateY(6px); }
	12.7%, 88.6% { opacity: 1; transform: none; }
	93.6%, 100%  { opacity: 0; transform: none; }
}
.pl-chat-mock__spin { animation-name: plcm-spin; }
@keyframes plcm-spin {
	0%          { transform: rotate(0deg); opacity: 1; }
	17.2%       { transform: rotate(1080deg); opacity: 1; }
	17.3%, 100% { transform: rotate(1080deg); opacity: 0; }
}
.pl-chat-mock__check { animation-name: plcm-check; }
@keyframes plcm-check {
	0%, 17.2%    { opacity: 0; }
	17.3%, 88.6% { opacity: 1; }
	93.6%, 100%  { opacity: 0; }
}
.pl-chat-mock__l1 { animation-name: plcm-l1; }
.pl-chat-mock__l2 { animation-name: plcm-l2; }
.pl-chat-mock__l3 { animation-name: plcm-l3; }
.pl-chat-mock__l4 { animation-name: plcm-l4; }
@keyframes plcm-l1 {
	0%, 18.1%    { opacity: 0; transform: translateY(6px); }
	19.1%, 88.6% { opacity: 1; transform: none; }
	93.6%, 100%  { opacity: 0; transform: none; }
}
@keyframes plcm-l2 {
	0%, 19.9%    { opacity: 0; transform: translateY(6px); }
	20.9%, 88.6% { opacity: 1; transform: none; }
	93.6%, 100%  { opacity: 0; transform: none; }
}
@keyframes plcm-l3 {
	0%, 22.2%    { opacity: 0; transform: translateY(6px); }
	23.2%, 88.6% { opacity: 1; transform: none; }
	93.6%, 100%  { opacity: 0; transform: none; }
}
@keyframes plcm-l4 {
	0%, 24.5%    { opacity: 0; transform: translateY(6px); }
	25.5%, 88.6% { opacity: 1; transform: none; }
	93.6%, 100%  { opacity: 0; transform: none; }
}
.pl-chat-mock__user--2 { animation-name: plcm-user2; }
@keyframes plcm-user2 {
	0%, 36.3%    { opacity: 0; transform: translateY(6px); }
	37.3%, 88.6% { opacity: 1; transform: none; }
	93.6%, 100%  { opacity: 0; transform: none; }
}
.pl-chat-mock__reply2 { animation-name: plcm-reply2; }
@keyframes plcm-reply2 {
	0%, 38.1%    { opacity: 0; transform: translateY(6px); }
	39.1%, 88.6% { opacity: 1; transform: none; }
	93.6%, 100%  { opacity: 0; transform: none; }
}
/* Two steps, each timed to the message that needs the room, not to a round number:
     stage 1 at 26-31%  the four reply lines have finished landing (l4 at 25.5%)
     stage 2 at 39-44%  the closing reply has appeared (reply2 at 38.1%), and this step takes the
                        thread all the way to its end, so that last message is never cut off. */
@keyframes plcm-scroll {
	0%, 26%     { transform: translateY(0); }
	31%, 39%    { transform: translateY(calc(0.5 * var(--pl-chat-end))); }
	44%, 88.6%  { transform: translateY(var(--pl-chat-end)); }
	93.7%, 100% { transform: translateY(0); }
}

/* Phones: the type only steps down a little and the window gets TALLER instead, so the
   conversation stays readable. Both knobs are single values you can tune. */
@media (max-width: 781px) {
	.pl-chat-mock {
		--pl-chat-h: 30em;
		font-size: 13px;
		padding-top: 0;
	}
	.pl-chat-mock__win--front {
		margin-inline: 2.5em;
	}
	/* Same fan as desktop, tightened: on a narrow screen the offsets have to stay small or the
	   windows behind eat the section. */
	.pl-chat-mock__win--mid {
		left: 1.25em;
		right: 1.25em;
		top: 2.75em;
		bottom: -2.75em;
	}
	.pl-chat-mock__win--back {
		top: 5.5em;
		bottom: -5.5em;
	}
	.pl-chat-mock__bar {
		padding-inline: 1.75em;
	}
	.pl-chat-mock__body {
		padding-inline: 1.5em;
	}
	.pl-chat-mock__input {
		margin-inline: 1.1em;
	}
}
@media (max-width: 480px) {
	.pl-chat-mock {
		--pl-chat-h: 34em;
		font-size: 12px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.pl-chat-mock__typed,
	.pl-chat-mock__typed2,
	.pl-chat-mock__ph,
	.pl-chat-mock__caret,
	.pl-chat-mock__caret2,
	.pl-chat-mock__spin,
	.pl-chat-mock__check,
	.pl-chat-mock__user,
	.pl-chat-mock__pill,
	.pl-chat-mock__l1,
	.pl-chat-mock__l2,
	.pl-chat-mock__l3,
	.pl-chat-mock__l4,
	.pl-chat-mock__reply2,
	.pl-chat-mock__thread,
	.pl-chat-mock__beam i::after {
		animation: none;
	}
	.pl-chat-mock__user,
	.pl-chat-mock__pill,
	.pl-chat-mock__l1,
	.pl-chat-mock__l2,
	.pl-chat-mock__l3,
	.pl-chat-mock__l4,
	.pl-chat-mock__reply2 {
		opacity: 1;
	}
	.pl-chat-mock__typed,
	.pl-chat-mock__typed2,
	.pl-chat-mock__spin,
	.pl-chat-mock__caret,
	.pl-chat-mock__caret2 {
		display: none;
	}
	.pl-chat-mock__thread {
		transform: translateY(var(--pl-chat-end));
	}
}

/* ---- The platform grid and the integration tiles are two patterns but one block in the UI Kit
   (9770:6868 above 9743:27303), so they must not be separated by two section paddings — that was
   the ~600px void. 64px between them, built out of a token rather than typed as a pixel value.
   !important on both because each block writes its padding as an inline style. ---- */
.pl-platform-grid__section {
	padding-bottom: 0 !important;
}
.pl-integration-tiles__section {
	padding-top: calc(var(--wp--preset--spacing--8-x) * 2) !important;
}

/* 200px between the closing card and the footer, which is exactly what 50x resolves to.
   The card is the last thing in this section, so this is the section's own bottom padding — no
   margin on the card, which would only stack on top of it.
   !important because the block writes its padding as an inline style. */
.pl-roadmap-list__section {
	padding-bottom: var(--wp--preset--spacing--50-x) !important;
}

/* =============================================================================
   6. pl-intro-mockup__cut
   ============================================================================= */
	/* Section 4 backdrop. .pl-section sets overflow:hidden; this section opts out so the closing
	   glow can spill past the bottom edge and be cut by the next section instead of by its own box
	   (same escape hatch .pl-section--intelligent-modeling uses in style.css).
	   The light beam is not here: it lives inside the mock, so that it anchors to the window stack
	   itself rather than to a guess about where the mock ends up. */
	.pl-intro-mockup__section {
		overflow: visible;
	}
	.pl-intro-mockup__section > .pl-intro-mockup__cut {
		position: absolute;
		z-index: 0;
		margin: 0;
		/* the constrained layout caps direct children at the content width */
		max-width: none;
		pointer-events: none;
		bottom: 0;
		left: 50%;
		width: 140%;
		height: 120%;
		transform: translate(-50%, 50%);
		border-radius: 50%;
		background: radial-gradient(
			closest-side,
			rgba(34, 25, 88, 0.9) 0%,
			rgba(34, 25, 88, 0.4) 40%,
			rgba(34, 25, 88, 0) 74%
		);
	}

/* =============================================================================
   8. pl-joinline__svg
   ============================================================================= */
	/* The routed line that joins this section to the next. Kept at its natural size and centred
	   (preserveAspectRatio="slice"), so it never stretches: wider viewports simply reveal more of
	   the run. The section is only as tall as the line. */
	/* The section takes no vertical space of its own: it is a zero-height marker and the line is
	   absolutely positioned off it, hanging up over the section above. */
	.pl-joinline {
		position: relative;
		height: 0;
		line-height: 0;
		overflow: visible;
		z-index: 0;
	}
	.pl-joinline__svg {
		position: absolute;
		left: 0;
		right: 0;
		bottom: 0;
		display: block;
		width: 100%;
		height: 469px;
		max-width: none;
		pointer-events: none;
	}
	@media (max-width: 1023px) {
		.pl-joinline__svg { height: 300px; }
	}
	@media (max-width: 600px) {
		.pl-joinline__svg { height: 200px; }
	}

/* =============================================================================
   9. pl-roadmap-list__wave
   ============================================================================= */
	/* The dot wave behind the roadmap. Exported from the UI Kit vector (Figma 9743:27374) as a PNG:
	   the vector is 17,801 separate paths / 9.2 MB, which is not shippable, and the raster already
	   carries the layer's 0.16 opacity and lighten blend. Anchored to the bottom edge and kept at
	   its own 1918x1065 ratio, so it never squashes. */
	.pl-roadmap-list__section > .pl-roadmap-list__wave {
		position: absolute;
		z-index: 0;
		left: 50%;
		bottom: 0;
		width: 100%;
		min-width: 1200px;
		max-width: none;
		margin: 0;
		transform: translateX(-50%);
		aspect-ratio: 1918 / 1065;
		background-image: url("/wp-content/uploads/2026/08/dotwave.png");
		background-size: 100% 100%;
		background-position: center bottom;
		background-repeat: no-repeat;
		pointer-events: none;
	}
