/* ============================================================
   PEEPAL — COMPONENT LAYER
   Styles for markup the CMS introduces that the static prototype
   did not have: media wrappers, feed controls, timeline, hero
   backgrounds, and accessibility utilities.

   Presentational values that the Components plugin will later
   control are expressed as CSS custom properties with sensible
   fallbacks, so injecting a value never needs a template change.
   ============================================================ */

/* ---------- Accessibility utilities ---------- */
.screen-reader-text {
	border: 0;
	clip: rect(1px, 1px, 1px, 1px);
	clip-path: inset(50%);
	height: 1px;
	margin: -1px;
	overflow: hidden;
	padding: 0;
	position: absolute;
	width: 1px;
	word-wrap: normal !important;
}

.skip-link:focus {
	background: var(--paper);
	clip: auto;
	clip-path: none;
	color: var(--ink);
	height: auto;
	left: 12px;
	padding: 14px 22px;
	top: 12px;
	width: auto;
	z-index: 200;
	border-radius: 6px;
	box-shadow: 0 4px 20px rgba(0, 0, 0, .3);
}

:where(a, button, input, select, textarea, summary):focus-visible {
	outline: 2px solid var(--neon);
	outline-offset: 3px;
}

/* Honeypot — off-screen, never shown to real users. */
.peepal-hp {
	left: -9999px;
	position: absolute;
	height: 1px;
	overflow: hidden;
	width: 1px;
}

/* ---------- Media wrapper (peepal_image / peepal_video) ---------- */
.peepal-media {
	display: block;
	margin: 0;
	overflow: hidden;
	position: relative;
	width: 100%;
}

.peepal-media__img,
.peepal-media img,
.peepal-media video {
	display: block;
	/* Phone-recorded HDR clips can raise the display's HDR headroom while
	   playing, which makes every surrounding SDR part of the page appear grey
	   or dim. Keep inline site video at SDR reference white so playback cannot
	   change the perceived brightness of the rest of the page. */
	dynamic-range-limit: standard;
	height: 100%;
	width: 100%;
	object-fit: var(--peepal-fit, cover);
	object-position: var(--peepal-pos, center);
}

@media (max-width: 640px) {
	.peepal-media.peepal-media--mobile-fit .peepal-media__img,
	.peepal-media.peepal-media--mobile-fit img {
		object-fit: var(--peepal-mobile-fit) !important;
	}
}

.peepal-media__caption {
	color: var(--grey-deep);
	font-family: var(--mono);
	font-size: .68rem;
	letter-spacing:calc(.04em * var(--mono-track, 1));
	margin-top: 8px;
	text-transform: uppercase;
}

/* The box takes the video's shape (see peepal_video_ratio()), so a portrait
   clip gets a portrait card rather than a strip of picture between two black
   fields. The dark ground still covers the gap where a shape cannot be known
   and the fallback ratio is a little off. */
.peepal-video {
	aspect-ratio: var(--peepal-video-ratio, 16 / 9);
	background: #111;
	dynamic-range-limit: standard;
	position: relative;
	width: 100%;
	overflow: hidden;
}

/* The slot a deferred provider embed is built into. It holds the player's
   box so nothing shifts when the iframe arrives; the wrapper's dark ground
   shows through until it does. */
.peepal-embed {
	position: absolute;
	inset: 0;
}

/* Click-to-play facade: our own still and play button, standing in for the
   provider's player until someone asks for it. */
.peepal-embed--facade {
	cursor: pointer;
}

.peepal-video__poster {
	display: block;
	height: 100%;
	width: 100%;
	/* A provider thumbnail is 16:9 whatever shape the video is. Cropping to
	   fill is what puts the picture edge to edge in a portrait card — and on
	   a Short's letterboxed still it crops away the bars rather than showing
	   them twice over. */
	object-fit: cover;
	object-position: center;
}

.peepal-video__play {
	align-items: center;
	background: var(--orange);
	border: 0;
	border-radius: 50%;
	cursor: pointer;
	display: flex;
	height: 56px;
	justify-content: center;
	left: 50%;
	position: absolute;
	top: 50%;
	transform: translate(-50%, -50%);
	transition: transform .2s ease, background-color .2s ease;
	width: 56px;
}

.peepal-video__play::after {
	border-bottom: 10px solid transparent;
	border-left: 16px solid #fff;
	border-top: 10px solid transparent;
	content: "";
	margin-left: 4px;
}

.peepal-embed--facade:hover .peepal-video__play,
.peepal-video__play:focus-visible {
	transform: translate(-50%, -50%) scale(1.08);
}

/* Once the player is in, the still and the button are gone — the iframe is
   absolutely positioned over them either way, but leaving them would keep the
   button's pointer target sitting on top of the video. */
.peepal-embed--facade.is-playing .peepal-video__poster,
.peepal-embed--facade.is-playing .peepal-video__play {
	display: none;
}

@media (prefers-reduced-motion: reduce) {
	.peepal-video__play {
		transition: none;
	}

	.peepal-embed--facade:hover .peepal-video__play,
	.peepal-video__play:focus-visible {
		transform: translate(-50%, -50%);
	}
}

/*
 * Sound button — an autoplaying player's only route to audio.
 *
 * Sits over the player rather than beside it: the card is the video, there is
 * no furniture around it to put a control in, and a button under the picture
 * would push the grid out of alignment with the quote cards either side.
 *
 * Bottom-left, because a YouTube player puts its own title top-left and its
 * "Watch on YouTube" and share buttons top-right, and a Short adds its share
 * rail on the right edge. The bottom-left corner is the one place nothing
 * else claims.
 */
.peepal-video__sound {
	align-items: center;
	background: rgba(0, 0, 0, .62);
	border: 0;
	border-radius: 50%;
	bottom: 12px;
	-webkit-backdrop-filter: blur(6px);
	backdrop-filter: blur(6px);
	cursor: pointer;
	display: flex;
	height: 40px;
	justify-content: center;
	left: 12px;
	padding: 0;
	position: absolute;
	transition: background-color .2s ease, transform .2s ease;
	width: 40px;
	z-index: 3;
}

.peepal-video__sound:hover,
.peepal-video__sound:focus-visible {
	background: var(--orange);
	transform: scale(1.06);
}

/*
 * The speaker, drawn rather than set in an icon font: it is two shapes, and a
 * font for two shapes is a network request and a flash of nothing.
 * The cone is a square with a triangle grown off its right edge.
 */
.peepal-video__sound-icon {
	background: #fff;
	display: block;
	height: 9px;
	margin-left: -5px;
	position: relative;
	width: 5px;
}

.peepal-video__sound-icon::before {
	border-bottom: 9px solid transparent;
	border-right: 7px solid #fff;
	border-top: 9px solid transparent;
	content: "";
	left: 5px;
	position: absolute;
	top: -4.5px;
}

/*
 * Muted state: a slash across the speaker. It is the resting state — an
 * autoplaying player always starts muted — so this is what the viewer sees
 * first, and it has to read as "no sound, press me" rather than as decoration.
 */
.peepal-video__sound[data-muted="1"] .peepal-video__sound-icon::after {
	background: #fff;
	content: "";
	height: 2px;
	left: -3px;
	position: absolute;
	top: 3.5px;
	transform: rotate(-45deg);
	width: 22px;
}

/* Unmuted: the two arcs of a sounding speaker. */
.peepal-video__sound[data-muted="0"] .peepal-video__sound-icon::after {
	border: 2px solid #fff;
	border-color: transparent #fff transparent transparent;
	border-radius: 50%;
	content: "";
	height: 14px;
	left: 12px;
	position: absolute;
	top: -2.5px;
	width: 14px;
}

@media (prefers-reduced-motion: reduce) {
	.peepal-video__sound {
		transition: none;
	}

	.peepal-video__sound:hover,
	.peepal-video__sound:focus-visible {
		transform: none;
	}
}

.peepal-video iframe,
.peepal-video video {
	border: 0;
	dynamic-range-limit: standard;
	display: block;
	height: 100%;
	left: 0;
	position: absolute;
	top: 0;
	width: 100%;
}

/* Uploaded-video controls deliberately avoid a full-width panel or gradient.
   Browser-native controls dim the whole frame while they are visible; these
   buttons paint only their own small circles, leaving every other pixel of
   the video at its original brightness on desktop, tablet and mobile. */
.peepal-video__controls {
	align-items: center;
	display: flex;
	gap: clamp(8px, 2vw, 14px);
	left: 50%;
	position: absolute;
	top: 50%;
	transform: translate(-50%, -50%);
	z-index: 4;
}

.peepal-video__controls button {
	align-items: center;
	background: rgba(0, 0, 0, .68);
	border: 0;
	border-radius: 50%;
	color: #fff;
	cursor: pointer;
	display: flex;
	font: 700 clamp(.7rem, 2vw, 1rem)/1 sans-serif;
	height: clamp(42px, 8vw, 58px);
	justify-content: center;
	padding: 0;
	transition: background-color .18s ease, transform .18s ease;
	width: clamp(42px, 8vw, 58px);
}

.peepal-video__controls .peepal-video__toggle {
	font-size: clamp(1rem, 3vw, 1.45rem);
	height: clamp(54px, 10vw, 72px);
	width: clamp(54px, 10vw, 72px);
}

.peepal-video__controls button:hover,
.peepal-video__controls button:focus-visible {
	background: var(--orange);
	transform: scale(1.06);
}

@media (max-width: 480px) {
	.peepal-video__controls {
		gap: 7px;
	}

	.peepal-video__controls button {
		height: 40px;
		width: 40px;
	}

	.peepal-video__controls .peepal-video__toggle {
		height: 52px;
		width: 52px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.peepal-video__controls button {
		transition: none;
	}
}

/* Wallpaper, not a player. The hero already blocks pointer events on the
   whole background, but a video used as a background elsewhere needs the same
   guarantee, or hovering it summons the player's own overlay. */
.peepal-video--background,
.peepal-video--background iframe,
.peepal-video--background video {
	pointer-events: none;
}

/* The industry illustration fallback fills its card exactly like an image.
   Scoped past .peepal-scene__defs: the shared gradient <defs> svg lives in the
   same wrapper and must stay a zero-sized, inert node. */
.peepal-scene,
.peepal-scene > svg:not(.peepal-scene__defs) {
	display: block;
	height: 100%;
	width: 100%;
}

.peepal-scene > svg:not(.peepal-scene__defs) {
	object-fit: cover;
}

.peepal-scene > .peepal-scene__defs {
	position: absolute;
	height: 0;
	width: 0;
	overflow: hidden;
	pointer-events: none;
}

/* ---------- Hero background media ---------- */
.hero--media {
	position: relative;
	isolation: isolate;
}

.hero__bg {
	inset: 0;
	position: absolute;
	z-index: -2;
	/* Decorative: the player must never take a click meant for the hero. */
	pointer-events: none;
}

.hero__bg .peepal-media,
.hero__bg .peepal-video,
.hero__image,
.hero__video {
	height: 100%;
	width: 100%;
}

/* Hero background layers — video and images alike — cross-fade; only the
   active one is visible. */
.hero__layer {
	inset: 0;
	opacity: 0;
	position: absolute;
	transition: opacity 1.2s ease;
}

.hero__layer.is-active {
	opacity: 1;
}

/*
 * A provider iframe keeps its own 16:9 box, so stretching it to the hero would
 * letterbox or squash it. Oversize the player against the shorter axis instead
 * and centre it, which crops exactly like object-fit: cover.
 */
.hero__video iframe {
	height: 56.25vw;
	left: 50%;
	min-height: 100%;
	min-width: 100%;
	position: absolute;
	top: 50%;
	transform: translate(-50%, -50%);
	width: 177.7778vh;
}

.hero__video video {
	object-fit: cover;
}

.hero__scrim {
	background: rgba(0, 0, 0, var(--peepal-overlay, .55));
	inset: 0;
	position: absolute;
	z-index: -1;
}

/* ---------- Services ---------- */
/*
 * The service card renders as <a> when it points at a landing page and <div>
 * when it does not. Anchors are display:inline by default, which stops the
 * hover background painting as a full-width band, so pin it to block.
 */
.svc {
	display: block;
}

/* ---------- Logo marquee additions ---------- */
.track {
	animation-duration: var(--peepal-marquee-duration, 34s);
}

.fold2.is-paused .track {
	animation-play-state: paused;
}

/*
 * The gap lives on the set, not the track, and each set carries a matching
 * trailing gap — so the two sets are exactly equal in width and the -50%
 * translate lands on a perfect seam. With the gap on the track instead, the
 * boundary between the two sets is half a gap short and the loop visibly jumps.
 */
.fold2 .track {
	gap: 0;
	align-items: center;
}

.track__set {
	display: flex;
	align-items: center;
	flex: 0 0 auto;
	gap: var(--peepal-marquee-gap, 64px);
	padding-right: var(--peepal-marquee-gap, 64px);
}

.logo {
	display: flex;
	align-items: center;
	flex: 0 0 auto;
}

/*
 * Logo images sit on a fixed rail height and are never cropped. The generic
 * media wrapper defaults to width:100% with object-fit:cover and a tinted
 * background — all three are wrong for a logo, so they are reset here.
 */
.logo .logo__img {
	background: none;
	height: var(--peepal-logo-height, 44px);
	max-height: none;
	overflow: visible;
	width: auto;
}

.logo .logo__img img {
	height: 100%;
	width: auto;
	max-width: 190px;
	object-fit: contain;
}

/* ---------- Feed controls ---------- */
.cs-controls .feed-controls {
	display: flex;
	flex-direction: column;
	gap: 16px;
}

.feed-search {
	position: relative;
}

.feed-search input {
	background: transparent;
	border: 0;
	border-bottom: 1px solid rgba(0, 0, 0, .18);
	border-radius: 0;
	color: inherit;
	font-family: var(--body);
	font-size: clamp(1rem, 2vw, 1.25rem);
	padding: 12px 0;
	width: 100%;
	transition: border-color .2s, box-shadow .2s;
}

.feed-search input:focus {
	border-bottom-color: var(--neon);
	box-shadow: 0 1px 0 0 var(--neon);
	outline: none;
}

.feed-help {
	color: var(--grey-deep);
	font-size: .88rem;
	margin: 0;
}

.feed-filters {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
}

.feed-filter {
	position: relative;
}

.feed-filter__toggle {
	background: transparent;
	border: 1px solid rgba(0, 0, 0, .18);
	border-radius: 30px;
	color: inherit;
	display: inline-flex;
	align-items: center;
	gap: 8px;
	font-family: var(--mono);
	font-size: .7rem;
	letter-spacing:calc(.048em * var(--mono-track, 1));
	padding: 9px 16px;
	text-transform: uppercase;
	transition: border-color .2s, background .2s;
}

.feed-filter__toggle:hover,
.feed-filter__toggle[aria-expanded="true"] {
	border-color: var(--neon);
	background: var(--orange-soft);
}

.feed-filter__menu {
	background: var(--paper);
	border: 1px solid #e6e6e6;
	border-radius: 12px;
	box-shadow: 0 18px 44px rgba(0, 0, 0, .16);
	left: 0;
	max-height: 300px;
	min-width: 230px;
	overflow-y: auto;
	padding: 10px;
	position: absolute;
	top: calc(100% + 8px);
	z-index: 40;
}

.feed-filter__option {
	align-items: center;
	border-radius: 7px;
	cursor: pointer;
	display: flex;
	font-size: .92rem;
	gap: 10px;
	padding: 8px 10px;
}

.feed-filter__option:hover {
	background: var(--mist);
}

.feed-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

.feed-chip {
	background: var(--orange-soft);
	border: 1px solid var(--neon);
	border-radius: 30px;
	color: var(--orange);
	cursor: pointer;
	font-family: var(--mono);
	font-size: .66rem;
	letter-spacing:calc(.04em * var(--mono-track, 1));
	padding: 6px 12px;
	text-transform: uppercase;
}

.feed-chip::after {
	content: " ✕";
}

.feed-status {
	color: var(--grey-deep);
	font-family: var(--mono);
	font-size: .74rem;
	letter-spacing:calc(.056em * var(--mono-track, 1));
	padding: 26px 0;
	text-align: center;
	text-transform: uppercase;
}

/* ---------- Feed highlights ---------- */
.hl-slim {
	align-items: center;
	background: var(--ink);
	border-radius: 16px;
	color: #fff;
	display: flex;
	gap: 20px;
	grid-column: 1 / -1;
	padding: 30px 34px;
	text-decoration: none;
	transition: background .3s;
}

.hl-slim:hover {
	background: #111;
}

.hl-slim h3 {
	flex: 1;
	font-family: var(--display);
	font-size: var(--fs-h3,clamp(1.15rem, 2.2vw, 1.6rem));
	font-weight: 600;
	line-height: 1.25;
	margin: 0;
}

.hl-slim .arw {
	color: var(--neon);
	font-size: 1.4rem;
	transition: transform .2s;
}

.hl-slim:hover .arw {
	transform: translateX(6px);
}

.hl-card {
	color: #fff;
	isolation: isolate;
	min-height: 80vh;
	display: flex;
	align-items: flex-end;
	padding: 0 0 clamp(40px, 6vw, 80px);
	position: relative;
}

.hl-card__media {
	inset: 0;
	position: absolute;
	z-index: -2;
}

.hl-card__media .peepal-media,
.hl-card__media .peepal-scene {
	height: 100%;
}

.hl-card__scrim {
	background: linear-gradient(180deg, rgba(0, 0, 0, .25), rgba(0, 0, 0, .85));
	inset: 0;
	position: absolute;
	z-index: -1;
}

.hl-card__body h2 {
	font-size: var(--fs-h2,clamp(2rem, 5vw, 3.6rem));
	margin: 14px 0;
	max-width: 20ch;
}

.hl-card__body h2 a {
	color: inherit;
	text-decoration: none;
}

.hl-card__body p {
	color: rgba(255, 255, 255, .82);
	max-width: 56ch;
}

.hl-card__meta {
	color: var(--grey);
	font-family: var(--mono);
	font-size: .7rem;
	letter-spacing:calc(.056em * var(--mono-track, 1));
	text-transform: uppercase;
}

/* ---------- Article (single) layout ---------- */
.csd-layout {
	align-items: start;
	display: grid;
	gap: clamp(28px, 5vw, 64px);
	grid-template-columns: minmax(0, 1fr) 320px;
	padding: clamp(40px, 6vw, 80px) var(--pad);
}

.csd-rail {
	position: sticky;
	top: 108px;
}

/*
 * The article's vertical rhythm, stated once.
 *
 * Every gap in a piece of writing comes from one of these three values, and
 * they are named rather than repeated so that a fold heading and a heading
 * typed into the body cannot drift apart — which is exactly how a page ends up
 * with two different amounts of air under two headings that look identical.
 *
 * The values are the ones the article already used; naming them changed no
 * spacing on any existing page.
 */
.csd-body {
	--prose-gap: 1.1em;          /* between one block and the next */
	--prose-heading-top: 2em;    /* the break before a heading */
	--prose-heading-lead: .5em;  /* a heading to the text it introduces */
	--prose-sub-top: 1.6em;      /* the smaller break before h3/h4 */
}

.csd-fold {
	margin-bottom: clamp(36px, 5vw, 64px);
	max-width: 68ch;
}

/*
 * A fold heading needs no break above it — the space between folds is the
 * break, and adding the heading's own on top of it would double the gap. The
 * space *below* is shared with every other heading, so the distance from a
 * heading to its first line of text is the same wherever the heading came
 * from.
 */
.csd-fold h2 {
	font-size: var(--fs-h2,clamp(1.6rem, 3.2vw, 2.4rem));
	margin: 10px 0 var(--prose-heading-lead);
}

.csd-prose {
	font-size: 1.05rem;
	line-height: 1.7;
}

.csd-prose > * + * {
	margin-top: var(--prose-gap);
}

/*
 * The same rhythm, one level into whatever a paste brought with it.
 *
 * The rules above address direct children, which is every piece of content an
 * editor types. Content pasted from a document often arrives wrapped — a div,
 * a figure, a section around a run of paragraphs — and inside that wrapper the
 * direct-child rules no longer apply, so the pasted passage sets its own
 * spacing while the paragraphs either side of it keep the page's. That is the
 * "it goes wrong when I paste" half of the problem, and it is invisible in the
 * editor because the wrapper has no appearance of its own.
 */
.csd-prose :is(div, section, article, figure, blockquote) > * + * {
	margin-top: var(--prose-gap);
}

.csd-prose :is(div, section, article) > * + h2 {
	margin-top: var(--prose-heading-top);
}

/* The smaller break, matching the top-level rule below rather than the h2 one
   — a subheading is a subheading whatever it happens to be wrapped in. */
.csd-prose :is(div, section, article) > * + :is(h3, h4) {
	margin-top: var(--prose-sub-top);
}

/*
 * Nothing hangs off the top or the bottom of a fold. A trailing margin on the
 * last paragraph adds to the fold's own margin and makes one gap between two
 * sections larger than the next, for no reason a reader could name.
 */
.csd-prose > :first-child,
.csd-fold > :first-child {
	margin-top: 0;
}

.csd-prose > :last-child,
.csd-fold > :last-child {
	margin-bottom: 0;
}

.csd-prose img {
	border-radius: 12px;
	height: auto;
}

/* A fold body is authored in the editor, so it can carry anything the
   toolbar emits. Lists need their marker and indent stated outright — the
   `> * + *` rule above spaces the block, not the items inside it. */
.csd-prose ul,
.csd-prose ol {
	padding-left: 1.35em;
}

.csd-prose ul { list-style: disc; }
.csd-prose ol { list-style: decimal; }

.csd-prose li + li {
	margin-top: .4em;
}

/*
 * Headings in prose. base.css sizes h1/h2 for section banners and leaves
 * h3/h4 at browser defaults, which in a long legal page reads as a wall of
 * near-identical bold lines. These give the page its two working levels —
 * numbered section, lettered subsection — and more air above a heading than
 * between paragraphs, so the breaks are visible while scrolling.
 */
.csd-prose h2 {
	font-size: clamp(1.35rem, 2.4vw, 1.75rem);
	line-height: 1.2;
	/*
	 * Put the section break on the heading itself. Gutenberg can wrap a
	 * heading in a Group/Columns block, so an adjacent-sibling selector on
	 * .csd-prose does not always see the paragraph that precedes it. Keeping
	 * the margin here makes the rhythm survive those invisible wrappers.
	 */
	margin-top: var(--prose-heading-top);
}

.csd-prose h3,
.csd-prose h4 {
	font-family: var(--body);
	font-size: 1.05rem;
	font-weight: 600;
	line-height: 1.35;
	margin-bottom: 0;
	margin-top: var(--prose-sub-top);
}

/* A heading that opens a prose field has nothing above it to separate from. */
.csd-prose > :is(h2, h3, h4):first-child {
	margin-top: 0;
}

.csd-prose > h2 + *,
.csd-prose > h3 + *,
.csd-prose > h4 + *,
.csd-prose :is(div, section, article) > :is(h2, h3, h4) + * {
	margin-top: var(--prose-heading-lead);
}

.csd-prose > * + h2 {
	margin-top: var(--prose-heading-top);
}

.csd-prose > * + h3,
.csd-prose > * + h4 {
	margin-top: var(--prose-sub-top);
}

.csd-prose blockquote {
	border-left: 2px solid var(--neon);
	font-family: var(--display);
	font-style: italic;
	margin-left: 0;
	padding-left: 18px;
}

.csd-prose a {
	text-decoration: underline;
	text-underline-offset: 2px;
}

/*
 * Tables in prose — the retention table on the Privacy Policy is the first
 * one, and the site drops wp-block-library, so the core table block arrives
 * with no styling of its own. The wrapper scrolls rather than the page: a
 * three-column table of sentences is wider than a phone, and a body that
 * scrolls sideways breaks every other section with it.
 */
.csd-prose .wp-block-table {
	margin-left: 0;
	margin-right: 0;
	overflow-x: auto;
}

.csd-prose table {
	border-collapse: collapse;
	font-size: .95rem;
	min-width: 34rem;
	width: 100%;
}

.csd-prose th,
.csd-prose td {
	border: 1px solid rgba(0, 0, 0, .12);
	padding: 10px 12px;
	text-align: left;
	vertical-align: top;
}

.csd-prose thead th {
	background: var(--mist);
	font-weight: 600;
}

/*
 * The strip shares its row with the sticky rail, so it has to stay inside the
 * article column no matter how many metrics a fold carries.
 *
 * `minmax(max-content, 1fr)` used to size each column to its own widest line
 * so no label ever folded. But max-content is a floor, not a preference: once
 * the labels together outgrew the column the grid could not shrink, so it
 * overflowed to the right — under the rail, and under the CTA button sitting
 * in it. Four metrics with a long label already crossed that line, and each
 * one added pushed further across.
 *
 * A 0 floor lets the columns give way instead, so the strip always ends where
 * the article column ends and the gap beside the rail is preserved. The cost
 * is that a long label now wraps rather than running on — which is the right
 * way round: a folded label is a smaller problem than one printed across a
 * button.
 */
.csd-metrics {
	column-gap: 14px;
	display: grid;
	grid-auto-columns: minmax(0, 1fr);
	grid-auto-flow: column;
	/* Matches .stats — figures share one row, labels the next. The row gap
	   stays at 0 because .lbl carries its own margin above it. */
	grid-template-rows: auto auto;
	margin: 22px 0 26px;
	max-width: 100%;
	row-gap: 0;
}

/*
 * Held a little below the strip's own scale, because the label — set in mono
 * with wide tracking — is usually the widest thing in the cell, not the
 * number. Both are allowed to fold: a two-word figure like "12 Years" breaking
 * across two lines is fine, whereas holding it on one line in a column too
 * narrow for it simply prints it over the figure in the next column.
 */
.csd-metrics .num {
	font-size: clamp(1.7rem, 2.8vw, 2.3rem);
	line-height: 1.05;
	overflow-wrap: break-word;
}

.csd-metrics .lbl {
	font-size: .62rem;
	letter-spacing:calc(.048em * var(--mono-track, 1));
	overflow-wrap: break-word;
}

.csd-metrics .stat {
	padding: clamp(20px, 2.4vw, 28px) clamp(14px, 1.8vw, 22px);
}

.csd-metrics .stat:first-child {
	border-left: 0;
}

.csd-metrics .stat--align-left { text-align: left; }
.csd-metrics .stat--align-center { text-align: center; }
.csd-metrics .stat--align-right { text-align: right; }

/* Too narrow to hold four readable columns — stack them, where each has the
   full measure to itself and still needs no wrapping. The rail appears at
   960px and takes 320px with it, so the squeeze starts above the old 860. */
@media (max-width: 1024px) {
	.csd-metrics {
		grid-auto-flow: row;
		grid-template-columns: 1fr;
		grid-template-rows: none;
	}

	.csd-metrics .stat {
		border-left: 0;
		border-top: 1px solid #ececec;
		grid-row: auto;
		grid-template-rows: auto auto;
	}

	.csd-metrics .stat:first-child {
		border-top: 0;
	}
}

/* ---------- The rail box: Popular Insights, and Related in an article ----
   One definition, two users. It lived in page-insights.css, which the article
   page does not load, so the related list was given a near-copy of it — and a
   near-copy is how the two stop matching. Both read from here now. */
.side-box{background:#fff;border:1px solid #ececec;border-radius:14px;padding:22px}
.side-box h4{font-family:var(--mono);font-size:.68rem;letter-spacing:calc(.072em * var(--mono-track, 1));text-transform:uppercase;color:var(--grey-deep);margin:0 0 18px}
.pop{display:flex;flex-direction:column}
.pop a{display:flex;gap:14px;text-decoration:none;color:inherit;padding:13px 0;border-top:1px solid #f0f0f0}
.pop a:first-child{border-top:0;padding-top:0}
.pop .rank{font-family:var(--mono);font-size:.9rem;color:var(--neon);flex:0 0 auto;padding-top:2px}
.pop .pt{font-family:var(--display);font-size:1rem;line-height:1.3;font-weight:600;margin:0}
.pop .pm{font-family:var(--mono);font-size:.6rem;letter-spacing:calc(.04em * var(--mono-track, 1));text-transform:uppercase;color:var(--grey-deep);margin-top:5px}
/* The reference leaves both spans inline, so the meta line lands on top of the
   title and its margin-top is ignored. Stacking them is plainly the intent. */
.pop .pt,.pop .pm{display:block}

/* No overrides for the article rail. It is the same box, deliberately — the
   point of the change was that the two lists stop looking like two designs. */

/* ---------- Closing CTA, at the foot of an article ---------- */
.csd-cta {
	background: var(--mist);
	border-top: 1px solid #ececec;
	padding: clamp(48px, 7vw, 88px) 0;
	text-align: center;
}

.csd-cta__lead {
	font-family: var(--display);
	font-size: clamp(1.3rem, 2.4vw, 1.9rem);
	font-weight: 700;
	line-height: 1.25;
	margin: 0 0 24px;
}

/* Sized by its own text here — full width was a rail constraint, and this band
   is the whole page wide. */
.csd-cta__btn {
	display: inline-flex;
}

.csd-hero {
	display: grid;
	gap: 0;
	grid-template-columns: 1fr 1fr;
	min-height: 70vh;
}

.csd-hero__copy {
	align-content: center;
	display: grid;
	padding: clamp(80px, 10vw, 140px) clamp(24px, 5vw, 72px) clamp(40px, 5vw, 72px);
}

.csd-hero__copy h1 {
	font-size: var(--fs-h1,clamp(2rem, 4.6vw, 3.4rem));
	margin: 12px 0 18px;
}

.csd-hero__sub {
	color: #444;
	font-family: var(--display);
	font-size: clamp(1.05rem, 1.8vw, 1.35rem);
	font-style: italic;
	font-weight: 400;
	line-height: 1.45;
	max-width: 44ch;
}

/*
 * An editor who wants part of the line upright can mark it up; the italic is
 * only the default, not a lock.
 */
.csd-hero__sub em,
.csd-hero__sub i {
	font-style: normal;
}

.csd-hero__meta {
	align-items: center;
	display: flex;
	flex-wrap: wrap;
	gap: 14px;
	margin-top: 22px;
}

.csd-hero__time {
	color: var(--grey-deep);
	font-family: var(--mono);
	font-size: .7rem;
	letter-spacing:calc(.056em * var(--mono-track, 1));
	text-transform: uppercase;
}

.csd-hero__media,
.csd-hero__media .peepal-media,
.csd-hero__media .peepal-scene {
	height: 100%;
	min-height: 320px;
}

/* ---------- Service / industry pages ---------- */
.sv-hero {
	align-items: flex-end;
	color: #fff;
	display: flex;
	isolation: isolate;
	min-height: 70vh;
	/*
	 * The nav is position:absolute over this hero, so the hero has to reserve
	 * its own headroom — nothing in normal flow does it for us. Without this
	 * the copy, which is bottom-aligned, rises into the bar the moment 70vh
	 * stops being taller than the copy plus its bottom padding. On a 1366x625
	 * laptop window — the ordinary Windows 1366x768 screen once browser chrome
	 * is taken off — that is every service page: the eyebrow and the headline
	 * sat behind the logo and the menu.
	 *
	 * It costs nothing on a tall screen. flex-end aligns inside the content
	 * box, so where there is room to spare this is simply unused space above
	 * copy that is already resting on the bottom padding.
	 *
	 * Asked for as "the header, plus air" rather than as a number: --nav-h is
	 * the bar's real height at this breakpoint (see base.css), so this stays
	 * correct when the bar changes and there is no second place to update.
	 */
	padding-top: calc(var(--nav-h) + var(--sv-hero-air, clamp(28px, 5vh, 68px)));
	padding-bottom: var(--sv-hero-pad-bottom, clamp(48px, 7vw, 96px));
	position: relative;
	background: var(--ink);
}

/*
 * Short viewports — the laptop band, matching the max-height:900px tier in
 * base.css that already tightens the homepage.
 *
 * The header is not adjusted here any more: --nav-h shrinks with the bar on
 * its own. What is left is the part that is this hero's own judgement — how
 * much air sits between the bar and the eyebrow, and how deep the foot is. At
 * 625px of viewport the longest service headline needs both tightened before
 * the hero starts pushing the fold below it off the screen.
 */
@media (max-height: 900px) and (min-width: 901px) {
	.sv-hero {
		--sv-hero-air: clamp(22px, 4vh, 40px);
		--sv-hero-pad-bottom: clamp(32px, 5vh, 56px);
	}
}

.sv-hero__media {
	inset: 0;
	position: absolute;
	z-index: -2;
}

.sv-hero__media .peepal-media {
	height: 100%;
}

.sv-hero__scrim {
	background: linear-gradient(180deg, rgba(0, 0, 0, .3), rgba(0, 0, 0, .8));
	inset: 0;
	position: absolute;
	z-index: -1;
}

.sv-hero__copy h1 {
	font-size: var(--fs-h1,clamp(2.2rem, 6vw, 4.2rem));
	margin: 12px 0 18px;
}

.sv-hero__copy .sub {
	color: rgba(255, 255, 255, .82);
	font-family: var(--display);
	font-size: clamp(1.05rem, 2vw, 1.35rem);
	font-style: italic;
	max-width: 40ch;
}

.sv-explainer {
	padding: clamp(48px, 7vw, 88px) 0 0;
}

.sv-steps,
.sv-diffs {
	padding: clamp(40px, 6vw, 80px) 0;
}

/*
 * Two gaps, not one. A single value has to serve both directions, and the two
 * are not doing the same job: sideways, 20px is a column rule between cards
 * standing level with each other; downwards, the same 20px puts the next
 * card's 2px top border almost against the last line of the card above, and
 * the border reads as an underline for that paragraph rather than as the start
 * of something new. The rows need enough space to say "this is a new card".
 *
 * The row gap is a variable so the editor can set it per page — steps carrying
 * one line each want less air than steps carrying six.
 */
.steps {
	display: grid;
	column-gap: 20px;
	row-gap: var(--steps-row-gap, 96px);
	grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
	margin-top: 30px;
}

.step {
	border-top: 2px solid var(--neon);
	padding-top: 18px;
}

.step__idx {
	color: var(--neon);
	font-family: var(--mono);
	font-size: .74rem;
	letter-spacing:calc(.08em * var(--mono-track, 1));
}

.step h3 {
	font-family: var(--display);
	font-size: var(--fs-h3,1.4rem);
	margin: 8px 0 10px;
}

.step p {
	color: #555;
	line-height: 1.6;
	margin: 0;
}

.diffs {
	display: grid;
	gap: 20px;
	grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
	margin-top: 30px;
}

.diff {
	background: var(--mist);
	border-radius: 16px;
	padding: 26px;
}

.diff h3 {
	font-family: var(--display);
	font-size: var(--fs-h3,1.3rem);
	margin: 0 0 10px;
}

.diff p {
	color: #555;
	line-height: 1.6;
	margin: 0;
}

/*
 * Service-page CTA. The reference draws this as a single centred button on the
 * page's own background — not the dark band this used to paint, which is why
 * the class now carries the reference's rules.
 */
/*
 * The reference keeps this inside the preceding section, so its spacing is
 * measured from the cards above (100px) and the section's own bottom padding
 * below (120px). As its own section here, the top gap is what the section
 * above does not already contribute, and the bottom gap is restated — without
 * it the next band butts straight up against the button.
 */
.sv-cta-sec {
	padding-bottom: clamp(64px, 9vw, 120px);
}

.sv-cta {
	/* Exactly the reference's 56-100px gap, less what the section above already
	   contributes as its bottom padding — so the two agree at every width. */
	margin-top: calc(clamp(56px, 8vw, 100px) - clamp(40px, 6vw, 80px));
	text-align: center;
}

.sv-cta-btn {
	align-items: center;
	-webkit-appearance: none;
	appearance: none;
	background: var(--orange);
	/*
	 * With no link set this control renders as a <button> so it can open the
	 * contact modal, and a bare <button> carries the browser's own border.
	 */
	border: 0;
	border-radius: 8px;
	color: #111;
	display: inline-flex;
	font-family: var(--mono);
	font-size: .82rem;
	font-weight: 600;
	gap: 14px;
	letter-spacing:calc(.08em * var(--mono-track, 1));
	padding: 19px 44px;
	text-decoration: none;
	text-transform: uppercase;
	transition: filter .2s;
}

.sv-cta-btn:hover {
	filter: brightness(1.06);
}

.sv-cta-btn span {
	transition: transform .2s;
}

.sv-cta-btn:hover span {
	transform: translateX(6px);
}

/* Optional copy above the button, for pages that set a heading. */
.sv-cta h2 {
	font-size: var(--fs-h2,clamp(1.6rem, 3.4vw, 2.4rem));
	margin: 10px 0 14px;
}

.sv-cta p {
	color: var(--grey-deep);
	margin: 0 auto 26px;
	max-width: 52ch;
}

/* ---------- About additions ---------- */
.ab-cols {
	display: grid;
	gap: clamp(22px, 4vw, 52px);
	grid-template-columns: 1fr 1fr;
	margin-top: 20px;
}

.ab-col {
	color: #444;
	line-height: 1.7;
}

.ab-timeline {
	margin-top: clamp(32px, 5vw, 56px);
	position: relative;
}

.ab-timeline__track {
	display: flex;
	gap: 22px;
	overflow-x: auto;
	padding-bottom: 22px;
	scroll-snap-type: x proximity;
	scrollbar-width: none;
}

.ab-timeline__track::-webkit-scrollbar {
	display: none;
}

.ab-ms {
	background: var(--paper);
	border: 1px solid #ececec;
	border-radius: 14px;
	flex: 0 0 min(320px, 76vw);
	padding: 24px;
	scroll-snap-align: start;
}

.ab-ms__year {
	color: var(--neon);
	font-family: var(--mono);
	font-size: .78rem;
	letter-spacing:calc(.072em * var(--mono-track, 1));
}

.ab-ms h3 {
	font-family: var(--display);
	font-size: var(--fs-h3,1.25rem);
	margin: 8px 0 10px;
}

.ab-ms p {
	color: #555;
	line-height: 1.6;
	margin: 0;
}

/* The timeline's own baseline doubles as the scroll indicator. */
.ab-timeline__bar {
	background: rgba(0, 0, 0, .1);
	border-radius: 2px;
	height: 3px;
	position: relative;
	transition: opacity .2s;
}

.ab-timeline__thumb {
	background: var(--neon);
	border-radius: 2px;
	box-shadow: var(--neon-glow);
	cursor: grab;
	height: 100%;
	left: 0;
	position: absolute;
	top: 0;
	touch-action: none;
	width: 20%;
}

.ab-timeline__thumb.drag {
	cursor: grabbing;
}

.ab-mv__pair {
	display: grid;
	gap: 20px;
	grid-template-columns: 1fr 1fr;
	margin-top: 24px;
}

.ab-mv__card {
	background: var(--paper);
	border: 1px solid #ececec;
	border-radius: 16px;
	padding: 28px;
}

.ab-values,
.ab-bento {
	display: grid;
	gap: 18px;
	grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
	margin-top: 26px;
}

.ab-value,
.ab-bento__card {
	background: var(--paper);
	border: 1px solid #ececec;
	border-radius: 14px;
	padding: 24px;
}

.ab-achievements {
	margin-top: clamp(32px, 5vw, 56px);
	overflow: hidden;
}

/*
 * Flat track: the spacing has to ride on the items, not the track. A track
 * `gap` sits between the two passes as well, which leaves the halves half a
 * gap apart and makes the -50% loop jump every cycle.
 */
.ab-achievements .track {
	animation: scroll var(--peepal-marquee-duration, 40s) linear infinite;
	display: flex;
	gap: 0;
	width: max-content;
}

.ab-achievements:hover .track {
	animation-play-state: paused;
}

.ab-achievement {
	margin-right: 44px;
	color: var(--grey-deep);
	font-family: var(--mono);
	font-size: .78rem;
	letter-spacing:calc(.064em * var(--mono-track, 1));
	text-transform: uppercase;
	white-space: nowrap;
}

.ab-leaders {
	display: grid;
	gap: 24px;
	grid-template-columns: 1fr 1fr;
	margin-top: 28px;
}

.ab-leader {
	background: var(--paper);
	border: 1px solid #ececec;
	border-radius: 18px;
	overflow: hidden;
}

.ab-leader__photo .peepal-media {
	aspect-ratio: 4 / 3;
}

.ab-leader__body {
	padding: 24px;
}

.ab-leader__role,
.ab-member__role {
	color: var(--grey-deep);
	display: block;
	font-family: var(--mono);
	font-size: .68rem;
	letter-spacing:calc(.056em * var(--mono-track, 1));
	margin-bottom: 10px;
	text-transform: uppercase;
}

.ab-leader__li svg,
.ab-member svg {
	height: 18px;
	width: 18px;
}

.ab-roster {
	display: grid;
	gap: 18px;
	grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
	margin-top: 30px;
}

.ab-member {
	text-align: center;
}

.ab-member__photo {
	aspect-ratio: 1;
	border-radius: 50%;
	margin: 0 auto 10px;
	max-width: 96px;
}

.ab-member__name {
	display: block;
	font-weight: 500;
}

.ab-foundation__grid {
	display: grid;
	gap: clamp(24px, 5vw, 56px);
	grid-template-columns: 1fr 1fr;
}

.ab-foundation__gallery {
	display: grid;
	gap: 14px;
	grid-template-columns: 1fr 1fr;
}

.ab-foundation__img {
	border-radius: 12px;
}

.ab-foundation__quote {
	border-left: 2px solid var(--neon);
	margin: 22px 0;
	padding-left: 20px;
}

.ab-foundation__quote blockquote {
	font-family: var(--display);
	font-size: 1.15rem;
	font-style: italic;
	margin: 0 0 8px;
}

.ab-video__placeholder {
	align-items: center;
	aspect-ratio: 16 / 9;
	background: linear-gradient(135deg, #1a1a1a, #333);
	border-radius: 16px;
	display: flex;
	flex-direction: column;
	gap: 16px;
	justify-content: center;
}

/* Still-image hero. No aspect-ratio: a group photo is much wider than 16:9
   and cropping it to the video box loses the people at either end. */
.ab-video__still {
	border-radius: 16px;
	overflow: hidden;
}

.ab-video__still-img {
	display: block;
	height: auto;
	width: 100%;
}

.ab-video__label {
	color: rgba(255, 255, 255, .8);
	font-family: var(--mono);
	font-size: .72rem;
	letter-spacing:calc(.072em * var(--mono-track, 1));
	text-transform: uppercase;
}

/* ---------- eBook page ----------
   The landing page's own styling lives in page-ebook.css, which follows the
   approved prototype markup exactly. The block that used to sit here styled an
   earlier attempt (.book__face, .lp-ribbon__band) and no longer matched
   anything the templates render, while its responsive .book rule still fought
   the real one. Removed rather than left to rot. */

/* ---------- FAQ / contact ---------- */
.peepal-faq {
	padding: clamp(48px, 7vw, 88px) 0;
}

.peepal-faq__item {
	border-bottom: 1px solid #ececec;
	padding: 18px 0;
}

/*
 * The question and the +/− are two columns, not text with something floated
 * after it. As a float the marker joined the end of the text flow, so a
 * question long enough to fill the row pushed it onto a line of its own — it
 * appeared below the question, sitting on the divider.
 *
 * Baseline alignment, so on a question that wraps to two lines the marker sits
 * against the first one rather than centred against the pair.
 */
.peepal-faq__item summary {
	cursor: pointer;
	display: flex;
	align-items: baseline;
	/* Narrower on a phone, where 28px of gap is most of a word. The marker
	   still has a column of its own at every width. */
	gap: clamp(14px, 3vw, 28px);
	font-family: var(--display);
	font-size: 1.15rem;
	font-weight: 600;
	list-style: none;
}

.peepal-faq__item summary::-webkit-details-marker {
	display: none;
}

/*
 * Hovering a question grows it. The transform sits on the inner span, not on
 * the <summary>: the summary spans the full row, so scaling it would push the
 * text past the container's gutter and drag the +/- marker along with it.
 * A transform also costs no reflow, so the row does not jump under the
 * pointer the way an animated font-size would.
 */
.peepal-faq__q {
	display: inline-block;
	/* Takes the row; min-width lets a long question wrap instead of forcing
	   the marker out of the row. */
	flex: 1 1 auto;
	min-width: 0;
	transform-origin: left center;
	transition: transform .22s ease, color .22s ease;
}

/*
 * A scale grows the text by a percentage of its own width, and a transform
 * does not take up layout space — so on a question that already fills the row,
 * 6% was another sixty-odd pixels of text sliding under the marker on hover.
 * Two per cent keeps the lift within the gap above at any length. The colour
 * was always doing most of the work here anyway.
 */
.peepal-faq__item summary:hover .peepal-faq__q,
.peepal-faq__item summary:focus-visible .peepal-faq__q,
.peepal-faq__item[open] > summary .peepal-faq__q {
	color: var(--orange);
	transform: scale(1.02);
}

@media (prefers-reduced-motion: reduce) {
	.peepal-faq__q {
		transition: none;
	}

	.peepal-faq__item summary:hover .peepal-faq__q,
	.peepal-faq__item summary:focus-visible .peepal-faq__q,
	.peepal-faq__item[open] > summary .peepal-faq__q {
		transform: none;
	}
}

.peepal-faq__item summary::after {
	color: var(--neon);
	content: "+";
	/* Its own column: never shrinks, never wraps, always the same width open
	   or closed so the questions do not shift when one is opened. */
	flex: 0 0 auto;
	width: 1ch;
	text-align: center;
}

.peepal-faq__item[open] summary::after {
	content: "–";
}

.peepal-faq__answer {
	color: #555;
	line-height: 1.7;
	padding-top: 12px;
}

.peepal-contact {
	padding: clamp(48px, 7vw, 96px) 0;
}

.peepal-contact__inner {
	display: grid;
	gap: clamp(28px, 5vw, 64px);
	grid-template-columns: 1fr 1fr;
}

/* ---------- Generic page / archive ---------- */
.peepal-main {
	padding: clamp(96px, 12vw, 160px) var(--pad) clamp(56px, 8vw, 96px);
}

.peepal-archive__header {
	margin-bottom: clamp(28px, 4vw, 48px);
}

.peepal-archive__header h1 {
	font-size: var(--fs-h1,clamp(2rem, 4.4vw, 3rem));
}

.peepal-page__header {
	padding: clamp(110px, 13vw, 170px) var(--pad) 0;
}

.peepal-page__header h1 {
	font-size: var(--fs-h1,clamp(2.2rem, 5vw, 3.4rem));
}

.peepal-page__body {
	padding: clamp(24px, 4vw, 44px) var(--pad) clamp(56px, 8vw, 96px);
	max-width: 74ch;
}

/*
 * Privacy Policy — the shared page shell, with the two things a legal page
 * needs that a plain page does not.
 *
 * Everything else it gets from .csd-prose: the heading rhythm, the lists, and
 * the scrolling table box that keeps a three-column retention table from
 * dragging the page sideways on a phone.
 */
.peepal-privacy__updated {
	color: var(--grey-deep);
	font-family: var(--mono);
	font-size: .72rem;
	letter-spacing:calc(.04em * var(--mono-track, 1));
	margin: 14px 0 0;
	text-transform: uppercase;
}

/*
 * A policy is read by someone looking for one clause, not front to back, so
 * the numbered headings carry more weight than prose headings would — they
 * are the index. The body stays at .peepal-page__body's reading measure.
 */
.peepal-privacy .peepal-privacy__section {
	border-top: 1px solid #ececec;
	padding-top: .9em;
}

.peepal-privacy .csd-prose > .peepal-privacy__section:first-child {
	border-top: 0;
	padding-top: 0;
}

/*
 * The table is the one element allowed out of the reading measure — three
 * columns of sentences inside 74ch is four words per column.
 */
.peepal-privacy__table {
	margin-left: 0;
	margin-right: 0;
	width: 100%;
}

.peepal-404 {
	text-align: center;
}

.peepal-404__more {
	margin-top: clamp(40px, 6vw, 72px);
}

.icard--plain .cbody {
	min-height: 190px;
}

.peepal-pagination {
	display: flex;
	gap: 10px;
	justify-content: center;
	padding: 40px 0;
}

.peepal-pagination .page-numbers {
	border: 1px solid #ddd;
	border-radius: 8px;
	padding: 9px 15px;
	text-decoration: none;
}

.peepal-pagination .page-numbers.current,
.peepal-pagination .page-numbers:hover {
	background: var(--orange-soft);
	border-color: var(--neon);
}

/* ---------- Footer additions ---------- */
.f-contact {
	display: flex;
	flex-direction: column;
	font-style: normal;
	gap: 6px;
	margin-top: 22px;
}

.f-contact__line {
	color: var(--text-dim);
	font-size: .9rem;
}

a.f-contact__line:hover {
	color: #fff;
}

.f-legal {
	display: flex;
	flex-wrap: wrap;
	gap: 18px;
	justify-content: center;
}

.f-legal a {
	color: var(--grey);
	font-size: .8rem;
}

.f-legal a:hover {
	color: #fff;
}

.f-news__msg {
	color: var(--neon);
	font-family: var(--mono);
	font-size: .7rem;
	letter-spacing:calc(.04em * var(--mono-track, 1));
	margin: 10px 0 0;
	min-height: 1em;
}

.f-brand__logo {
	margin-bottom: 16px;
	max-width: 200px;
}

/* ---------- Responsive ---------- */
@media (max-width: 960px) {
	.csd-layout {
		grid-template-columns: 1fr;
	}

	.csd-rail {
		position: static;
	}

	.ab-foundation__grid,
	.ab-leaders,
	.ab-mv__pair,
	.ab-cols,
	.peepal-contact__inner {
		grid-template-columns: 1fr;
	}
}

@media (max-width: 760px) {
	.csd-hero {
		grid-template-columns: 1fr;
		min-height: 0;
	}

	.csd-hero__media {
		min-height: 260px;
		order: -1;
	}

	.hl-card {
		min-height: 60vh;
	}

	.hl-slim {
		flex-direction: column;
		align-items: flex-start;
		gap: 12px;
	}

}

@media (prefers-reduced-motion: reduce) {
	.ab-achievements .track,
	.inf-line,
	.track {
		animation: none;
	}

	.hero__layer {
		transition: none;
	}
}

/* ============================================================
   RICH TEXT
   Body copy authored through the CMS editor. Inline colour, size
   and font come through as inline styles; these rules cover the
   block-level tags the toolbar can produce.
   ============================================================ */
.peepal-rich {
	font-family: var(--body);
	font-size: var(--fs-body,1rem);
}

.peepal-rich > *:first-child {
	margin-top: 0;
}

.peepal-rich > *:last-child {
	margin-bottom: 0;
}

.peepal-rich p {
	margin: 0 0 1em;
}

/*
 * Two paragraphs of card copy read as two paragraphs.
 *
 * Card components reset their copy to `margin: 0` — written when a card held
 * one paragraph, and correct for that. The moment an editor puts a blank line
 * in the field, the reset throws it away: the paragraphs come out as separate
 * <p> elements butted together, so the editor's spacing "does not get
 * implemented" and the only fix is to stop writing two paragraphs.
 *
 * Both shapes are covered, because peepal_paragraphs() emits two of them —
 * plain text becomes sibling <p class="peepal-item-text">, rich text becomes
 * one wrapper holding <p> children. Neither rule touches a card with a single
 * paragraph, so nothing that reads correctly today moves.
 *
 * The gap itself is a variable: the plugin's "Between paragraphs in cards"
 * control sets it per section, and it falls back to the same 1em the section
 * prose uses.
 */
.peepal-item-text + .peepal-item-text,
.peepal-item-text p + p {
	margin-top: var(--peepal-card-text-space, 1em);
}

/*
 * The same guarantee for a section's own copy, which a few folds reset the
 * same way (.ab-history, for one). Because adjacent margins collapse, this
 * only ever raises a gap that is smaller than the floor — a section that
 * already spaces its paragraphs by 24px keeps its 24px.
 */
.peepal-prose + .peepal-prose,
.peepal-prose p + p {
	margin-top: var(--peepal-text-space, 1em);
}

.peepal-rich ul,
.peepal-rich ol {
	margin: 0 0 1em;
	padding-left: 1.35em;
}

.peepal-rich li {
	margin-bottom: .4em;
}

.peepal-rich h1,
.peepal-rich h2,
.peepal-rich h3,
.peepal-rich h4,
.peepal-rich h5 {
	font-family: var(--display);
	font-weight: 700;
	line-height: 1.2;
	margin: 1.4em 0 .5em;
}

.peepal-rich h1 {
	font-size: var(--fs-h1,clamp(2.2rem,5vw,3.6rem));
	line-height: 1.05;
}

.peepal-rich h2 {
	font-size: var(--fs-h2,clamp(1.7rem,3.4vw,2.4rem));
	line-height: 1.1;
}

.peepal-rich h3 { font-size: var(--fs-h3,1.5rem); }
.peepal-rich h4 { font-size: 1.25rem; }
.peepal-rich h5 { font-size: 1.08rem; }

.peepal-rich a {
	text-decoration: underline;
	text-underline-offset: 2px;
}

.peepal-rich blockquote {
	border-left: 2px solid var(--neon);
	font-family: var(--display);
	font-style: italic;
	margin: 1.2em 0;
	padding-left: 18px;
}

/* TinyMCE's alignment buttons may emit either inline text-align or these
   WordPress classes, depending on the core editor version. */
.peepal-rich .alignleft   { text-align: left; }
.peepal-rich .aligncenter { text-align: center; }
.peepal-rich .alignright  { text-align: right; }
.peepal-rich .alignjustify{ text-align: justify; }

/* The editor emits <u>/<s>; browsers style them, but keep the offset sane. */
.peepal-rich u,
u {
	text-underline-offset: 2px;
}

/* ============================================================
   CONTACT MODAL
   Rendered by footer.php on every page, so it belongs in the
   global layer. It used to live in page-home.css, which meant
   that anywhere else the overlay had no styles at all and
   opening it dropped the form inline at the foot of the page.
   The .field and .btn-primary rules it builds on are in base.css.
   ============================================================ */
/* ============================================================
   CONTACT MODAL
   ============================================================ */
.modal-overlay{
  position:fixed;inset:0;z-index:200;
  background:rgba(0,0,0,.6);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  display:flex;align-items:center;justify-content:center;
  opacity:0;visibility:hidden;transition:opacity .3s ease,visibility .3s;
}
.modal-overlay.open{opacity:1;visibility:visible}
/* The markup ships with `hidden`; a class rule setting display would beat the
   browser default, so state it explicitly. */
.modal-overlay[hidden]{display:none}
.modal-card{
  background:var(--ink);border:1px solid rgba(255,255,255,.1);border-radius:20px;
  padding:clamp(28px,4vw,48px);width:min(500px,92vw);max-height:90vh;overflow-y:auto;
  position:relative;
  transform:translateY(24px) scale(.97);transition:transform .35s cubic-bezier(.22,1,.36,1);
  box-shadow:0 40px 80px rgba(0,0,0,.5);
}
.modal-overlay.open .modal-card{transform:translateY(0) scale(1)}
.modal-close{
  position:absolute;top:18px;right:18px;
  width:44px;height:44px;border-radius:50%;border:1px solid rgba(255,255,255,.18);
  background:transparent;color:#fff;font-size:1.2rem;
  display:flex;align-items:center;justify-content:center;cursor:pointer;
  transition:background .2s,border-color .2s;
}
.modal-close:hover{background:rgba(255,255,255,.08);border-color:rgba(255,255,255,.3)}
.modal-card .eyebrow{margin-bottom:8px}
.modal-card h2{
  font-family:var(--display);font-size:var(--fs-h2,clamp(1.5rem,3vw,2rem));font-weight:700;color:#fff;
  margin:0 0 32px;letter-spacing:-.01em;
}

/* ============================================================
   PROMOTIONAL POP-UP
   Shares the contact modal's language — dark card, blurred
   ground, one round close button — because it is the same kind
   of interruption and should not look like a different site.
   ============================================================ */
.promo-pop {
	align-items: center;
	backdrop-filter: blur(10px);
	-webkit-backdrop-filter: blur(10px);
	background: rgba(0, 0, 0, .6);
	display: flex;
	inset: 0;
	justify-content: center;
	opacity: 0;
	padding: 20px;
	position: fixed;
	transition: opacity .3s ease, visibility .3s;
	visibility: hidden;
	z-index: 210;
}

.promo-pop[hidden] {
	display: none;
}

.promo-pop.open {
	opacity: 1;
	visibility: visible;
}

.promo-pop__card {
	background: var(--ink);
	border: 1px solid rgba(255, 255, 255, .1);
	border-radius: 20px;
	box-shadow: 0 40px 80px rgba(0, 0, 0, .5);
	color: #fff;
	max-height: 90vh;
	overflow: hidden auto;
	position: relative;
	transform: translateY(24px) scale(.97);
	transition: transform .35s cubic-bezier(.22, 1, .36, 1);
	width: min(560px, 100%);
}

.promo-pop.open .promo-pop__card {
	transform: translateY(0) scale(1);
}

/* The image is a banner across the top, so it keeps the card's
   rounded corners rather than sitting in a square inside them. */
.promo-pop__media {
	aspect-ratio: 2 / 1;
	overflow: hidden;
}

.promo-pop__media .peepal-media,
.promo-pop__img {
	height: 100%;
	width: 100%;
}

.promo-pop__body {
	padding: clamp(26px, 4vw, 44px);
}

.promo-pop__body .eyebrow {
	margin-bottom: 10px;
}

.promo-pop__body h2 {
	color: #fff;
	font-family: var(--display);
	font-size: var(--fs-h2, clamp(1.5rem, 3vw, 2.1rem));
	font-weight: 700;
	letter-spacing: -.01em;
	line-height: 1.1;
	margin: 0;
}

.promo-pop__meta {
	color: var(--neon);
	font-family: var(--mono);
	font-size: .74rem;
	letter-spacing:calc(.048em * var(--mono-track, 1));
	margin: 14px 0 0;
	text-transform: uppercase;
}

.promo-pop__text,
.promo-pop__text p {
	color: rgba(255, 255, 255, .82);
	font-size: .98rem;
	line-height: 1.65;
	margin: 16px 0 0;
}

.promo-pop__actions {
	align-items: center;
	display: flex;
	flex-wrap: wrap;
	gap: 18px;
	margin-top: 28px;
}

/* Deliberately quiet: the way out should be findable, not competing
   with the thing the panel is there to ask for. */
.promo-pop__no {
	background: none;
	border: 0;
	color: rgba(255, 255, 255, .6);
	cursor: pointer;
	font-family: var(--mono);
	font-size: .72rem;
	letter-spacing:calc(.056em * var(--mono-track, 1));
	padding: 0;
	text-transform: uppercase;
	transition: color .2s;
}

.promo-pop__no:hover {
	color: #fff;
}

/* ---- Corner card -------------------------------------------------
   The default placement, and a different kind of thing from the panel
   above: it takes a corner of the screen rather than the screen. The
   page behind stays lit, readable and scrollable, and the card waits
   to be dealt with instead of demanding it. */
.promo-pop--corner {
	align-items: flex-end;
	backdrop-filter: none;
	-webkit-backdrop-filter: none;
	background: none;
	inset: auto 0 0 auto;
	justify-content: flex-end;
	max-width: min(420px, 100%);
	padding: clamp(14px, 2vw, 26px);
	/* The wrapper still covers its corner of the viewport. Only the card
	   may take a click, or this would swallow whatever sits underneath —
	   which at the bottom right of a long page is usually a footer link. */
	pointer-events: none;
}

.promo-pop--corner .promo-pop__card {
	border-radius: 16px;
	box-shadow: 0 18px 44px rgba(0, 0, 0, .3);
	max-height: min(72vh, 620px);
	pointer-events: auto;
	/* Rises into place rather than zooming: at this size a scale reads as
	   a wobble. */
	transform: translateY(20px);
	width: min(360px, 100%);
}

.promo-pop--corner.open .promo-pop__card {
	transform: none;
}

/* Everything a step down from the centred panel — this is read out of the
   corner of the eye, not walked up to. */
.promo-pop--corner .promo-pop__media {
	aspect-ratio: 16 / 9;
}

.promo-pop--corner .promo-pop__body {
	padding: 22px;
}

.promo-pop--corner .promo-pop__body h2 {
	font-size: clamp(1.15rem, 2.2vw, 1.4rem);
}

.promo-pop--corner .promo-pop__meta {
	font-size: .68rem;
	margin-top: 10px;
}

.promo-pop--corner .promo-pop__text,
.promo-pop--corner .promo-pop__text p {
	font-size: .9rem;
	margin-top: 12px;
}

.promo-pop--corner .promo-pop__actions {
	gap: 14px;
	margin-top: 20px;
}

/* The site's button is sized for a fold — 34px of side padding and .22em of
   tracking. In a 360px card that is wider than the card itself, so it fills
   the width and breaks its label across two lines, which reads as a banner
   rather than a button. Scaled to the card: the same button, at the size the
   card is. */
.promo-pop--corner .promo-pop__actions .btn-primary {
	font-size: .72rem;
	gap: 10px;
	letter-spacing:calc(.048em * var(--mono-track, 1));
	margin-top: 0;
	padding: 13px 22px;
}

.promo-pop--corner .promo-pop__actions .btn-primary .arw {
	font-size: .95rem;
}

/* On a phone a 360px card in the corner is the whole width anyway, so it
   becomes a bar across the bottom instead of a card floating near an edge. */
@media (max-width: 560px) {
	.promo-pop--corner {
		inset: auto 0 0 0;
		max-width: none;
		padding: 12px;
	}

	.promo-pop--corner .promo-pop__card {
		width: 100%;
	}
}

@media (prefers-reduced-motion: reduce) {
	.promo-pop,
	.promo-pop__card {
		transition: none;
	}

	.promo-pop__card {
		transform: none;
	}
}

/* ============================================================
   FRAMED PREVIEW
   The CMS renders the real page inside a panel a few hundred
   pixels wide. Anything anchored to the viewport is anchored to
   that panel instead, where it sits on top of the thing being
   previewed — so the fixed furniture stands down. It is a
   preview of the content, not of the chrome.
   ============================================================ */
body.peepal-framed .rail,
body.peepal-framed .promo-pop {
	display: none !important;
}

/*
 * The dialog while it is fetching a button's own form.
 *
 * The form already in it stays visible and simply stops accepting input —
 * blanking it would flash an empty dialog for the length of one request, and
 * if the request fails there would be nothing to fall back to.
 */
.modal-overlay.is-loading [data-modal-form] {
	opacity: .45;
	pointer-events: none;
	transition: opacity .15s ease;
}
