/**
 * Modularis - section layer
 *
 * Layout that belongs to a specific section and is not reusable enough to be
 * a block style variation. Kept separate from components.css so it is obvious
 * which rules are system (reusable) and which are page furniture.
 *
 * Zero literal colors.
 */

/* =========================================================================
   STICKY SITE HEADER

   The header template part renders inside its own wrapper - every template
   sets `tagName:"header"` on wp:template-part, so core emits
   <header class="wp-block-template-part"> around parts/header.html. That
   wrapper, not .site-header, is the child of .wp-site-blocks, so it is the
   element that has to be sticky: on the inner .site-header, sticky would only
   have its own box to stick within and nothing would happen.

   Styling the wrapper also means a header part customised in the site editor
   keeps working - the treatment does not depend on .site-header surviving.
   ========================================================================= */

header.wp-block-template-part {
	position: sticky;

	/* Offset by the admin bar so it never covers the nav for logged-in users.
	   The variable is only defined by admin-bar.css (32px, 46px on mobile);
	   everyone else falls back to 0. */
	inset-block-start: var(--wp-admin--admin-bar--height, 0px);
	z-index: 100;
	isolation: isolate;
	border-block-end: 1px solid var(--border-soft);
}

/**
 * The scrim is a pseudo-element rather than a background on the header itself
 * because backdrop-filter makes an element the containing block for fixed
 * positioned descendants - and the mobile nav overlay
 * (.wp-block-navigation__responsive-container.is-menu-open) is fixed. On the
 * header that would trap the open menu inside the 82px header box; on a
 * pseudo-element the blur is free of the nav.
 */
header.wp-block-template-part::before {
	content: "";
	position: absolute;
	z-index: -1;
	inset: 0;
	background: var(--wp--custom--color--nav-scrim);
	backdrop-filter: blur(14px) saturate(140%);
}

/* Without backdrop-filter the 0.72-alpha scrim would let content read through,
   so fall back to the opaque page background. */
@supports not (backdrop-filter: blur(1px)) {
	header.wp-block-template-part::before {
		background: var(--bg);
	}
}

/**
 * Anchor targets (the header's own #contact link, and smooth scrolling from
 * theme.json) must not land underneath the header. --header-h is the rendered
 * header height - 18px padding twice plus the 46px nav button - and is only
 * used for this offset, so an approximation is fine.
 */
html {
	--header-h: 82px;

	scroll-padding-block-start: calc(var(--wp-admin--admin-bar--height, 0px) + var(--header-h) + 16px);
}

/* ------------------------------------------------- Header nav breakpoint */

/**
 * Where the header collapses to the hamburger. THIS IS THE ONLY BREAKPOINT -
 * change the 899.98px and nothing else.
 *
 * Core's navigation block has no setting for it. wp-includes/blocks/navigation/
 * style.css hides the overlay below 600px and then, in two `@media (min-width:
 * 600px)` rules, lays the menu out inline and hides the toggle button. Six items
 * at 14px with a 32px gap measure roughly 500px on their own, which crowds the
 * logo long before 600px, so those two rules are put back for the range in
 * between and the overlay keeps working up to the width chosen here.
 *
 * The values restored are core's own defaults for the mobile state - the closed
 * container is `display: none`, the toggle is `display: flex` - so this reverses
 * the desktop rules rather than inventing a third state.
 *
 * Both selectors are prefixed with .wp-block-navigation to sit one class above
 * core's, because with separate block assets the block's stylesheet can be
 * printed after the theme's and equal specificity would lose.
 *
 * The .98 avoids a dead zone on fractional viewport widths, where a 900px-wide
 * window can measure 899.5px and match neither `max-width: 899px` nor core's
 * `min-width: 600px` desktop rules cleanly.
 */
@media (max-width: 899.98px) {
	.wp-block-navigation .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) {
		display: none;
	}

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

/* ----------------------------------------------------------- Video frame */

/**
 * A 16:9 plate standing in for an embed that does not exist yet. It is
 * deliberately quiet and deliberately not clickable - see platform-video.php.
 * Replacing the group with a core/embed block removes this styling with it,
 * since core's embed carries its own responsive wrapper.
 */
.video-frame {
	display: grid;
	place-items: center;
	aspect-ratio: 16 / 9;
	border: 1px solid var(--border-soft);
	background: var(--surface);
	clip-path: polygon(
		0 0,
		calc(100% - var(--wp--custom--notch--xl)) 0,
		100% var(--wp--custom--notch--xl),
		100% 100%,
		var(--wp--custom--notch--xl) 100%,
		0 calc(100% - var(--wp--custom--notch--xl))
	);
}

.video-frame p {
	margin: 0;
}

/* ----------------------------------------------------------- Compare table */

/**
 * Traditional / vibe coding / Modularis, across five bands. Same approach as
 * the pricing table: selected through the section class so the pattern carries
 * no markup an editor can lose, and written one element deeper than core's
 * `.wp-block-table td` because with separate block assets core's rules can be
 * printed after this file.
 *
 * Wider min-width than the pricing table - four columns, and two of them hold
 * sentences rather than a word - so on a phone the table scrolls inside its own
 * figure instead of crushing.
 */
.compare-table .wp-block-table {
	overflow-x: auto;
}

.compare-table table {
	inline-size: 100%;
	min-inline-size: 860px;
	border-collapse: collapse;
}

.compare-table table th,
.compare-table table td {
	border: 0;
	border-block-end: 1px solid var(--border-soft);
	padding: 13px 18px;
	text-align: start;
	vertical-align: middle;
}

.compare-table table th:not(:first-child),
.compare-table table td:not(:first-child) {
	text-align: center;
}

.compare-table table thead th {
	border-block-end: 1px solid var(--border);
	color: var(--text);
	font-family: var(--display);
	font-size: var(--wp--preset--font-size--md);
	font-weight: 600;
	letter-spacing: var(--wp--custom--tracking--tight);
}

/* The corner cell labels the rows rather than naming an option, so it recedes. */
.compare-table table thead th:first-child {
	color: var(--faint);
	font-family: var(--mono);
	font-size: var(--wp--preset--font-size--eyebrow);
	font-weight: 400;
	letter-spacing: var(--wp--custom--tracking--label);
	text-transform: uppercase;
}

.compare-table table tbody th {
	color: var(--text);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 400;
}

.compare-table table tbody td {
	color: var(--muted);
	font-size: var(--wp--preset--font-size--sm);
}

/**
 * The band rows - Tools, Architecture, Support, Quality, Stacks. They are the
 * only cells that span the table, so [colspan] identifies them without a class
 * the editor could drop.
 */
.compare-table table tbody th[colspan] {
	border-block-end: 1px solid var(--border);
	padding-block: 22px 10px;
	background: none;
	color: var(--primary);
	font-family: var(--mono);
	font-size: var(--wp--preset--font-size--eyebrow);
	letter-spacing: var(--wp--custom--tracking--label);
	text-align: start;
	text-transform: uppercase;
}

/**
 * The column being sold, marked as a lane rather than a tint: a stronger wash,
 * a rule down each side, and text carrying a little more weight than the two
 * columns it is being compared against.
 *
 * The side rules break at each band row, where a single cell spans the table
 * and there is no fourth child to draw them on. That is the right place for the
 * lane to breathe - the bands are the table's own section breaks.
 */
.compare-table table th:nth-child(4),
.compare-table table td:nth-child(4) {
	border-inline: 1px solid var(--wp--custom--color--primary-dim);
	background: var(--wp--custom--color--primary-lane);
	color: var(--text);
	font-weight: 500;
}

/* The column heading, in the brand colour, as the lane's label. */
.compare-table table thead th:nth-child(4) {
	color: var(--primary);
}

/**
 * The stacks band. One answer per column covering five rows - structurally
 * already true, through rowspan - but with nothing to see, the sentence read as
 * text floating between the row hairlines rather than as the block it is.
 *
 * A fill fixes that: each merged cell becomes one uniform box the height of the
 * rows it spans. The row headers beside it keep their separators, so the five
 * stacks stay legible as five while the answers read as one.
 *
 * The Modularis column layers its tint over that fill as a background-image,
 * because two colours cannot go in `background-color` at once - and it has to
 * keep the tint, or the column would break its run at the last band.
 */
.compare-table table td[rowspan] {
	background-color: var(--surface);
	padding: 20px 18px;
	vertical-align: middle;
}

.compare-table table td[rowspan]:nth-child(4) {
	background-image: linear-gradient(
		var(--wp--custom--color--primary-lane),
		var(--wp--custom--color--primary-lane)
	);
}

/* No hairline under the last stacks row - the boxes end the table cleanly. */
.compare-table table tbody tr:last-child th,
.compare-table table tbody tr:last-child td {
	border-block-end: 0;
}

/* --------------------------------------------------------------------- FAQ */

/**
 * Accordion built on core/details, so the open/close behaviour, the keyboard
 * handling and the expanded/collapsed announcement all come from the element
 * rather than from script. Only the marker and the rhythm are ours.
 */
.faq-list .wp-block-details {
	border-block-end: 1px solid var(--border-soft);
	padding-block: 22px;
}

.faq-list .wp-block-details:first-of-type {
	border-block-start: 1px solid var(--border-soft);
}

.faq-list summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
	cursor: pointer;
	color: var(--text);
	font-family: var(--display);
	font-size: var(--wp--preset--font-size--md);
	font-weight: 600;
	letter-spacing: var(--wp--custom--tracking--tight);
	list-style: none;
}

/* Both spellings of "no default triangle" - the flex row supplies its own. */
.faq-list summary::-webkit-details-marker {
	display: none;
}

.faq-list summary:hover {
	color: var(--primary);
}

/* Chevron from two borders: down when closed, up when open. */
.faq-list summary::after {
	content: "";
	flex: none;
	inline-size: 11px;
	block-size: 11px;
	border-inline-end: 2px solid var(--primary);
	border-block-end: 2px solid var(--primary);
	translate: 0 -3px;
	rotate: 45deg;
	transition: rotate var(--wp--custom--effect--dur-base) ease;
}

.faq-list .wp-block-details[open] summary::after {
	translate: 0 2px;
	rotate: 225deg;
}

/* An answer that enumerates keeps its numbers; only the measure is ours. */
.faq-list .wp-block-details ol {
	max-inline-size: 68ch;
	margin-block: 14px;
	padding-inline-start: 22px;
	color: var(--muted);
}

.faq-list .wp-block-details ol li + li {
	margin-block-start: 6px;
}

.faq-list .wp-block-details p {
	max-inline-size: 68ch;
	margin-block: 16px 0;
	color: var(--muted);
}

@media (prefers-reduced-motion: reduce) {
	.faq-list summary::after {
		transition: none;
	}
}

/* ---------------------------------------------------------- Demo form panel */

/**
 * The booking form's column, as a panel. This styles the container; the form
 * that lands in it is styled in assets/css/hubspot-form.css.
 *
 * That file is worth knowing about before touching this one. The embed is
 * started with css:'' so HubSpot loads no stylesheet at all, which means the
 * fields are not being overridden from outside - they have no styling but
 * ours. An earlier version of this comment said the way to theme them was
 * HubSpot's own form editor; that editor assumes a light background and
 * cannot reach the font, the focus ring or the button, so it was the wrong
 * answer.
 */
.demo-form {
	align-self: stretch;
	border: 1px solid var(--border);
	background: var(--surface);
	padding: clamp(26px, 3vw, 38px);
	clip-path: polygon(
		0 0,
		calc(100% - var(--wp--custom--notch--xl)) 0,
		100% var(--wp--custom--notch--xl),
		100% 100%,
		var(--wp--custom--notch--xl) 100%,
		0 calc(100% - var(--wp--custom--notch--xl))
	);
}

.demo-form .hs-form-mount {
	margin-block-start: 4px;
	min-block-size: 60px;
}

/*
 * On the contact page the panel is the left half of the row, so its width comes
 * from the column. It still needs the panel's own floor: an empty mount is a
 * few pixels tall until HubSpot answers, and a panel that grows as the page
 * settles is worse than one that waits at the right size.
 */
.contact-form .hs-form-mount {
	min-block-size: 320px;
}

/* -------------------------------------------------------- Story (single) */

/**
 * A photographic hero. The picture is an Image block pulled out of flow and
 * pinned behind the copy, rather than a CSS background, so it can be swapped in
 * the editor and each story can carry its own.
 *
 * ::after is the scrim; ::before already belongs to the hero glow (see the
 * ambient layer block above), and both sit behind the content because
 * .hero-section isolates its own stacking context.
 */
.story-hero .story-hero-bg {
	position: absolute;
	z-index: -2;
	inset: 0;

	/**
	 * Core caps every child of a constrained container at contentSize, and an
	 * absolutely positioned one is no exception - without this the photograph
	 * is 1280px of picture centred in a full-bleed section, which reads as a
	 * band rather than a background. inset covers the section's padding box,
	 * so lifting the cap takes it the whole way out.
	 */
	max-width: none;
	margin: 0;
}

.story-hero .story-hero-bg img {
	inline-size: 100%;
	block-size: 100%;
	object-fit: cover;
	filter: grayscale(1);
	opacity: 0.38;
}

/* Without a scrim the headline sits on whatever the photograph happens to be
   doing at that point. With one it sits on the page's own ground. */
.story-hero::after {
	content: "";
	position: absolute;
	z-index: -1;
	inset: 0;
	background: linear-gradient(
		180deg,
		var(--wp--custom--color--nav-scrim),
		var(--wp--custom--color--primary-veil)
	);
	pointer-events: none;
}

/**
 * Prose beside its own index.
 *
 * The summary is navigation, not an introduction: it names the sections and
 * stays with the reader while they move through them. Sticky rather than fixed,
 * so it scrolls out with the section it belongs to instead of following people
 * into the carousel.
 */
.story-layout {
	display: grid;
	grid-template-columns: minmax(170px, 230px) minmax(0, 1fr);
	gap: clamp(28px, 5vw, 72px);
	align-items: start;
}

.story-nav {
	position: sticky;

	/* Clear of the sticky header, and of the admin bar when there is one. */
	inset-block-start: calc(var(--wp-admin--admin-bar--height, 0px) + var(--header-h) + 28px);
}

.story-nav .story-summary {
	/*
	 * No marker and no indent: the source page numbers these items inside the
	 * text of each link ("1. ...", "2. ..."), so a list marker would number
	 * them a second time. The numerals stay with the words they belong to.
	 */
	list-style: none;
	margin-block: 4px 0;
	padding-inline-start: 0;
	color: var(--muted);
	font-size: var(--wp--preset--font-size--sm);
	line-height: var(--wp--custom--leading--snug);
}

.story-nav .story-summary li + li {
	margin-block-start: 12px;
}

.story-nav .story-summary a {
	color: inherit;
	text-decoration: none;
}

.story-nav .story-summary a:hover,
.story-nav .story-summary a:focus-visible {
	color: var(--primary);
}

/**
 * A case study is the one thing on this site somebody reads top to bottom, so
 * the body gets a column built for reading - about 68 characters - rather than
 * the width the grid would give it.
 */
.story-body {
	max-inline-size: 68ch;
}

.story-body > * + * {
	margin-block-start: 1.1em;
}

.story-body p {
	color: var(--muted);
	line-height: var(--wp--custom--leading--lead);
}

.story-body h3 {
	margin-block-start: 2em;
	color: var(--text);
	font-family: var(--display);
	font-size: var(--wp--preset--font-size--xl);
	font-weight: 600;
	letter-spacing: var(--wp--custom--tracking--tight);

	/* Anchored from the summary, so it must clear the sticky header. */
	scroll-margin-block-start: calc(var(--header-h) + 32px);
}

.story-body .wp-block-quote {
	margin-block: 2em;
}

/**
 * The photographs that break up the prose. They are stock imagery carrying a
 * section change rather than evidence, so they get the reading column's width
 * and nothing else - no caption, no frame, no full-bleed moment that would
 * make the reader stop and look for meaning that is not in them.
 */
.story-body .story-figure {
	margin-block: 2em;
}

.story-body .story-figure img {
	display: block;
	inline-size: 100%;
}

/**
 * THE PULL QUOTE BAND
 *
 * The quote that closes a story, at full width and centred. Inside the prose it
 * read as one more paragraph; given a band it reads as the point.
 *
 * The bare quote style already supplies the portrait at portrait size - this
 * only changes the axis: a column, centred, with the attribution under the
 * words rather than beside them, because centred text with a left-aligned
 * credit looks like a mistake.
 */
/*
 * The marks are decoration, so they hang off the section rather than sitting
 * in the markup: an editor cannot delete half a quotation mark by accident,
 * and the quote block stays a plain quote block.
 *
 * They are placed against the section's own edges, not the text's, which is
 * what opens the gap the reference has - the words in the middle, the marks
 * out at the margins holding them.
 */
.story-pull {
	position: relative;
}

.story-pull::before,
.story-pull::after {
	content: "";
	position: absolute;
	inline-size: clamp(74px, 8.5vw, 148px);
	aspect-ratio: 100 / 76;
	background: url("../img/quote-mark.svg") no-repeat center / contain;
}

.story-pull::before {
	inset-block-start: clamp(24px, 4vw, 56px);
	inset-inline-start: clamp(16px, 7vw, 132px);
}

/* The closing pair is the opening pair upside down - which is what it is. */
.story-pull::after {
	inset-block-end: clamp(24px, 4vw, 56px);
	inset-inline-end: clamp(16px, 7vw, 132px);
	transform: rotate(180deg);
}

/*
 * Wide enough for the quote to break into two full lines rather than four
 * short ones. At 26ch it was a narrow column adrift in a full-width band with
 * the marks a long way off on either side; around 48ch the words reach far
 * enough that the three parts read as one composition.
 */
.story-pull .wp-block-quote {
	align-items: center;
	max-inline-size: 48ch;
	margin-inline: auto;
	text-align: center;
}

.story-pull .wp-block-quote p {
	color: var(--text);
	font-family: var(--display);
	font-size: var(--wp--preset--font-size--xl);
	font-weight: 500;
	line-height: var(--wp--custom--leading--snug);
	letter-spacing: var(--wp--custom--tracking--tight);
}

/*
 * A column rather than a row, so the face sits above the name. `margin-block-
 * start: auto` from the shared cite rule would push this to the floor of a
 * flex column that has no spare height anyway - reset it so the spacing here
 * is the padding below, not whatever is left over.
 */
.story-pull .wp-block-quote cite {
	flex-direction: column;
	gap: 10px;
	margin-block-start: 0;
	padding-block-start: 28px;
	text-align: center;
}

/* No room for marks and words both - the words win. */
@media (max-width: 782px) {
	.story-pull::before,
	.story-pull::after {
		display: none;
	}
}

/* Stacked, the index goes back to being a list at the top of the prose. */
@media (max-width: 900px) {
	.story-layout {
		grid-template-columns: 1fr;
	}

	.story-nav {
		position: static;
	}
}

/* =========================================================================
   TECH 360 - the assessment landing page.
   ========================================================================= */

/*
 * Five promises across the opener. auto-fit rather than a fixed five, because
 * five equal columns on a laptop gives each one about 200px and a two-word
 * heading wraps to three lines; this lets them fall to three and two instead.
 */
.wp-block-columns.promise-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
	gap: 16px;
	margin-block-start: clamp(40px, 4.4vw, 60px);
}

.wp-block-columns.promise-grid > .wp-block-column {
	flex-basis: auto;
}

.promise .pillar-title {
	font-size: var(--wp--preset--font-size--lg);
}

/*
 * The questions, two to a row. Seven short questions down a single column is a
 * long thin list that reads as a form; in two columns they read as a set.
 *
 * A grid, not CSS columns: .is-style-hexlist is display:flex, and the columns
 * property does nothing at all on a flex container - which is why asking for
 * two of them the first time changed nothing on the page.
 */
.question-list.is-style-hexlist {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 14px clamp(24px, 3.4vw, 56px);
	max-inline-size: 1000px;
}

/* The offer that answers them, set apart from the list above it. */
.t360-lifeline {
	max-inline-size: 760px;
	margin-block-start: clamp(40px, 4.6vw, 64px);
	padding: clamp(28px, 3vw, 42px);
}

.t360-lifeline .h-card {
	margin-block: 0 14px;
}

/*
 * The process: steps centred, and the head centred by the rule above with the
 * other centred heads. The step component is start-aligned everywhere else, so
 * this is scoped rather than changed in the component, which the home page
 * also uses.
 */
.t360-steps .step {
	text-align: center;
}

/*
 * The copy is capped at 32ch by the component, and a 32ch box sits at the
 * start of its column however the text inside it is aligned - so centring the
 * text was not enough, the box has to be centred too. Same for the title,
 * which has no cap but can be given one by a future edit.
 */
.t360-steps .step-title,
.t360-steps .step-copy {
	margin-inline: auto;
}

/*
 * Titles on one line, copy on another, across all three steps.
 *
 * Each step is its own box, so a two-line title in one of them pushes that
 * step's paragraph down and the row goes ragged. Subgrid hands the steps the
 * parent's rows, so every title shares a row and every paragraph shares the
 * next. Browsers without subgrid ignore the value and get today's behaviour,
 * which is the ragged version rather than a broken one.
 */
.t360-steps .timeline {
	grid-template-rows: auto auto;
}

.t360-steps .timeline > .step {
	display: grid;
	grid-row: span 2;
	grid-template-rows: subgrid;
	row-gap: 10px;
	align-content: start;
}

/*
 * The numbered hexagon over each step. The component pins it to the left of
 * the card - inset-inline-start: 26px, and 28px for the face that sits inside
 * the ring - so centring it means overriding both, and the +2px that insets
 * the face becomes a vertical offset only: once ring and face are both centred
 * on the same axis, the face is centred inside the ring by construction.
 */
.t360-steps .timeline > .step::before,
.t360-steps .timeline > .step::after {
	inset-inline-start: 50%;
	transform: translateX(-50%);
}

/* The film in the lifeline card, at its own width rather than the card's. */
.t360-video {
	max-inline-size: 520px;
	margin-block: 0 26px;
}

/* The claim and the evidence, side by side, aligned at the top. */
.t360-proof-row {
	align-items: flex-start;
}

/*
 * The form panel, wearing the same treatment as the booking form elsewhere.
 * It needs a floor: an empty mount is a few pixels tall until HubSpot answers,
 * and a column that grows as the page settles pushes the row about.
 */
.t360-form {
	padding: clamp(24px, 2.6vw, 36px);
}

.t360-form .hs-form-mount {
	min-block-size: 320px;
}

/*
 * The guide form on the post-acquisition page: one column under its own copy
 * rather than beside it, so it takes a width of its own instead of the band's.
 */
.pas-form {
	max-inline-size: 620px;
	margin-inline: auto;
	margin-block-start: clamp(30px, 3.4vw, 44px);
	padding: clamp(24px, 2.6vw, 36px);
}

.pas-form .hs-form-mount {
	min-block-size: 280px;
}

/*
 * The line that introduces a list of worries or deliverables. Smaller than a
 * section heading, because the section heading is above it - this one only has
 * to say "here they come".
 */
.question-lead {
	margin-block: clamp(26px, 3vw, 38px) 18px;
	color: var(--text);
	font-family: var(--display);
	font-size: var(--wp--preset--font-size--xl);
	font-weight: 600;
	letter-spacing: var(--wp--custom--tracking--tight);
}

.pdr-deliverables {
	margin-block-start: clamp(34px, 4vw, 52px);
}

.pdr-steps-lead {
	margin-block-start: clamp(34px, 4vw, 52px);
}

/* The closing offer beside its photograph, and the heading over the three
   reasons under it. */
.plw-close-art img {
	inline-size: 100%;
	block-size: auto;
}

.plw-why-head {
	margin-block-start: clamp(48px, 5.4vw, 76px);
}

/* Six claims and no prose under them, so the card is the heading. */
.pas-capabilities .pillar-title {
	margin-block-end: 0;
	font-size: var(--wp--preset--font-size--lg);
}

/* The customer result, under the row rather than in it, at a width that keeps
   the quote from running the whole page. */
.t360-case {
	max-inline-size: 880px;
	margin-block-start: clamp(40px, 4.4vw, 64px);
	padding: clamp(24px, 2.6vw, 36px);
}

.t360-case-logo {
	margin-block: 0 20px;
}

.t360-case-logo img {
	inline-size: auto;
	max-block-size: 34px;
}

.t360-case .pillar-title {
	font-size: var(--wp--preset--font-size--lg);
}

.t360-case .wp-block-quote {
	margin-block: 22px;
}

@media (max-width: 720px) {
	.question-list.is-style-hexlist {
		grid-template-columns: 1fr;
	}
}

/* =========================================================================
   THE RESOURCES INDEX - a tab strip over a list of posts.
   ========================================================================= */

/*
 * The tabs. Links, not buttons, because that is what they are without the
 * script: each one goes to the category archive it names. The chosen one is
 * marked by JS with .is-selected; before that runs the first is chosen by the
 * same rule, so the strip never renders with nothing selected.
 */
.tab-strip {
	gap: 8px;
	justify-content: center;
	margin-block-end: clamp(30px, 3.4vw, 46px);
	border-block-end: 1px solid var(--border);
	padding-block-end: 18px;
}

.tab-strip .tab {
	margin: 0;
}

.tab-strip a {
	display: inline-block;
	border: 1px solid transparent;
	padding: 9px 20px;
	color: var(--muted);
	font-family: var(--mono);
	font-size: var(--wp--preset--font-size--eyebrow);
	letter-spacing: var(--wp--custom--tracking--eyebrow);
	text-transform: uppercase;
	text-decoration: none;
	transition:
		color var(--wp--custom--effect--dur-fast) ease,
		border-color var(--wp--custom--effect--dur-fast) ease;
}

.tab-strip a:hover,
.tab-strip a:focus-visible {
	color: var(--text);
	border-color: var(--border);
}

.tab-strip a.is-selected,
.tab-strip .tab:first-child a:only-child:not([aria-selected="false"]) {
	border-color: var(--primary);
	color: var(--primary);
}

/* Each panel's own heading, for the no-JS case; the script hides them. */
.tab-panel-title {
	margin-block: 0 22px;
	color: var(--text);
	font-family: var(--display);
	font-size: var(--wp--preset--font-size--xl);
	font-weight: 600;
	letter-spacing: var(--wp--custom--tracking--tight);
}

.tab-panel + .tab-panel {
	margin-block-start: clamp(40px, 5vw, 64px);
}

/* Three to a row, dropping to two and then one. */
.post-list-items {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 16px;
	margin: 0;
	padding: 0;
	list-style: none;
}

/*
 * The card stands up: picture, then title, then summary. A column, not a grid,
 * so the words start at the same height on every card in a row whatever the
 * picture's shape, and the summary can take the height it needs.
 */
.post-card {
	display: flex;
	flex-direction: column;
	block-size: 100%;
	border: 1px solid var(--border);
	background: var(--surface);
	padding: clamp(14px, 1.4vw, 18px);
	transition: border-color var(--wp--custom--effect--dur-fast) ease;
}

.post-card:hover {
	border-color: var(--primary);
}

.post-card-thumb {
	margin-block: 0 16px;
}

.post-card-thumb img {
	display: block;
	inline-size: 100%;
	block-size: auto;
	aspect-ratio: 3 / 2;
	object-fit: cover;
}

/* A post with no picture starts at the top of the card rather than leaving a
   gap where one would have been. */
.post-card:not(:has(.post-card-thumb img)) .post-card-thumb {
	display: none;
}

.post-card-title {
	margin-block: 0 10px;
	color: var(--text);
	font-family: var(--display);
	font-size: var(--wp--preset--font-size--lg);
	font-weight: 600;
	line-height: var(--wp--custom--leading--snug);
	letter-spacing: var(--wp--custom--tracking--tight);
}

.post-card-title a {
	color: inherit;
	text-decoration: none;
}

.post-card-title a:hover,
.post-card-title a:focus-visible {
	color: var(--primary);
}

.post-card-excerpt {
	margin-block: 0;
	color: var(--muted);
	font-size: var(--wp--preset--font-size--sm);
	line-height: var(--wp--custom--leading--lead);
}

/* "See More" sits in the excerpt, so it is styled where it lands. */
.post-card-excerpt .wp-block-post-excerpt__more-link {
	display: inline-block;
	margin-block-start: 10px;
	color: var(--primary);
	font-family: var(--mono);
	font-size: var(--wp--preset--font-size--eyebrow);
	letter-spacing: var(--wp--custom--tracking--eyebrow);
	text-transform: uppercase;
	text-decoration: none;
}

.post-card-excerpt .wp-block-post-excerpt__more-link:hover,
.post-card-excerpt .wp-block-post-excerpt__more-link:focus-visible {
	text-decoration: underline;
}

.post-list-empty {
	color: var(--muted);
	font-family: var(--mono);
	font-size: var(--wp--preset--font-size--sm);
}

.blog-tabs .wp-block-buttons {
	margin-block-start: clamp(26px, 3vw, 38px);
}

/*
 * The page numbers. Squares rather than a row of underlined digits, so the
 * current page reads at a glance and the targets are big enough to hit.
 */
.post-pagination {
	gap: 8px;
	justify-content: center;
	margin-block-start: clamp(28px, 3.2vw, 42px);
}

.post-pagination .wp-block-query-pagination-numbers {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	align-items: center;
}

.post-pagination a,
.post-pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-inline-size: 38px;
	block-size: 38px;
	border: 1px solid var(--border);
	padding-inline: 12px;
	color: var(--muted);
	font-family: var(--mono);
	font-size: var(--wp--preset--font-size--eyebrow);
	letter-spacing: var(--wp--custom--tracking--eyebrow);
	text-transform: uppercase;
	text-decoration: none;
	transition:
		color var(--wp--custom--effect--dur-fast) ease,
		border-color var(--wp--custom--effect--dur-fast) ease;
}

.post-pagination a:hover,
.post-pagination a:focus-visible {
	border-color: var(--primary);
	color: var(--primary);
}

.post-pagination .page-numbers.current {
	border-color: var(--primary);
	background: var(--wp--custom--color--primary-wash2);
	color: var(--primary);
}

/* The gap marker is not a target, so it does not wear a box. */
.post-pagination .page-numbers.dots {
	border-color: transparent;
	min-inline-size: 0;
	padding-inline: 2px;
}

@media (max-width: 1080px) {
	.post-list-items {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 720px) {
	.post-list-items {
		grid-template-columns: 1fr;
	}

	.tab-strip {
		gap: 6px;
	}

	.tab-strip a {
		padding: 8px 14px;
	}
}

/* =========================================================================
   THE POST VIEW - a cover header over the featured image, then the article.
   ========================================================================= */

/*
 * The header is a cover block, so its padding is core's until it is told
 * otherwise, and its content is centred as a column rather than a row.
 */
.post-header {
	padding-block: clamp(96px, 10vw, 132px) clamp(64px, 7vw, 92px);
	text-align: center;
}

.post-header .wp-block-cover__inner-container {
	display: grid;
	justify-items: center;
}

/* The picture, when the post has one. Held back so type stays readable over
   it - the overlay does most of that, this stops a bright photo fighting. */
.post-header .wp-block-cover__image-background {
	filter: saturate(0.55);
}

.post-meta {
	gap: 18px 22px;
	justify-content: center;
	margin-block-end: 22px;
}

.post-categories {
	margin: 0;
	color: var(--primary);
	font-family: var(--mono);
	font-size: var(--wp--preset--font-size--eyebrow);
	letter-spacing: var(--wp--custom--tracking--eyebrow);
	text-transform: uppercase;
}

.post-categories a {
	color: inherit;
	text-decoration: none;
}

.post-categories a:hover,
.post-categories a:focus-visible {
	text-decoration: underline;
}

/*
 * Under the headline now, so it carries its own space above it. The category
 * keeps the line over the title; this is the one element in the band that asks
 * for an action, and it reads better after the thing being shared.
 */
.post-share {
	display: flex;
	gap: 12px;
	align-items: center;
	margin-block-start: 26px;
}

.post-share-label {
	color: var(--faint);
	font-family: var(--mono);
	font-size: var(--wp--preset--font-size--eyebrow);
	letter-spacing: var(--wp--custom--tracking--eyebrow);
	text-transform: uppercase;
}

.post-share-link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	inline-size: 34px;
	block-size: 34px;
	border: 1px solid var(--border);
	color: var(--muted);
	transition:
		color var(--wp--custom--effect--dur-fast) ease,
		border-color var(--wp--custom--effect--dur-fast) ease;
}

.post-share-link svg {
	fill: currentcolor;
}

.post-share-link:hover,
.post-share-link:focus-visible {
	border-color: var(--primary);
	color: var(--primary);
}

/* Centred, and stopped short of the full measure: a headline running the whole
   width of a cover reads as a banner rather than a title. */
.post-title {
	margin-block: 0;
	max-inline-size: 22ch;
}

/*
 * The portrait beside the prose, and the prose beside it. The face column is
 * narrow on purpose: it holds one object, and anything wider reads as an empty
 * sidebar somebody forgot to fill.
 *
 * The two tracks are sized to what they hold and the pair is centred, rather
 * than the text track taking the rest of the row. With a 1fr text column the
 * prose still stops at its measure, so everything left over piles up on one
 * side and the page looks like it is sliding off the screen. Centring the pair
 * splits that space evenly instead.
 */
.post-layout {
	display: grid;
	grid-template-columns: minmax(0, 150px) minmax(0, 74ch);
	justify-content: center;
	gap: clamp(24px, 3.6vw, 60px);
	align-items: start;
}

.post-aside {
	position: sticky;
	inset-block-start: calc(var(--header-h) + 28px);
}

.author-portrait img {
	display: block;
	inline-size: 120px;
	block-size: auto;
	aspect-ratio: 1 / 1.09;
	object-fit: cover;
	clip-path: var(--hex);
}

/*
 * "By <name>" under the face, the role under that - the source's author box,
 * in its order.
 *
 * The prefix is generated rather than typed: the name is a block WordPress
 * fills from the profile, and there is nowhere in front of it to put a word.
 * The role is the Biographical Info field, so an author who has not filled it
 * in has no third line rather than an empty one.
 */
.post-aside .author-name {
	margin-block: 16px 2px;
	color: var(--text);
	font-family: var(--display);
	font-size: var(--wp--preset--font-size--md);
	font-weight: 600;
	line-height: var(--wp--custom--leading--snug);
	letter-spacing: var(--wp--custom--tracking--tight);
}

.post-aside .author-name::before {
	content: "By ";
	color: var(--muted);
	font-weight: 400;
}

.post-aside .author-name a {
	color: inherit;
	text-decoration: none;
}

.post-aside .author-name a:hover,
.post-aside .author-name a:focus-visible {
	color: var(--primary);
}

.post-aside .author-bio {
	margin-block: 0;
	color: var(--muted);
	font-family: var(--mono);
	font-size: var(--wp--preset--font-size--eyebrow);
	letter-spacing: var(--wp--custom--tracking--eyebrow);
	text-transform: uppercase;
}

/* An author with an empty profile leaves an empty paragraph behind. */
.post-aside .author-bio:empty {
	display: none;
}

/*
 * The measure now belongs to the grid track above, so the article only has to
 * agree not to overflow it - a wide table or a code block would otherwise push
 * the column past the size the row was balanced around.
 */
.post-article {
	min-inline-size: 0;
	max-inline-size: 100%;
}

/*
 * Article headings are not section headings. h2 inherits h-section from
 * theme.json - clamp(34px, 4.6vw, 66px), sized to open a whole band - and at
 * that size a heading every few paragraphs reads as a series of new pages.
 * Scoped here rather than changed in theme.json, which would resize every
 * section heading on the site.
 */
.post-article :where(h2) {
	margin-block-start: 1.8em;
	font-size: clamp(24px, 3.6vw, 46px);
	font-family: var(--display);
	line-height: var(--wp--custom--leading--snug);
	letter-spacing: var(--wp--custom--tracking--tight);
}

.post-article :where(h3) {
	margin-block-start: 1.5em;
}

.post-article :where(img) {
	block-size: auto;
	max-inline-size: 100%;
}

/*
 * Nothing to show, nothing to say: on a site with fewer than two posts the
 * loop comes back empty and the heading would sit over a rule with a blank
 * space under it. The heading lives outside the loop, so hiding it takes the
 * whole block.
 */
.related-articles:not(:has(.wp-block-post)) {
	display: none;
}

/* Three titles under a rule - no thumbnails, as on the source. */
.related-articles {
	margin-block-start: clamp(48px, 6vw, 76px);
	border-block-start: 1px solid var(--border);
	padding-block-start: clamp(26px, 3vw, 38px);
}

.related-title {
	margin-block: 0 18px;
	color: var(--text);
	font-family: var(--display);
	font-size: var(--wp--preset--font-size--xl);
	font-weight: 600;
	letter-spacing: var(--wp--custom--tracking--tight);
}

.related-list {
	display: grid;
	gap: 0;
}

.related-post {
	margin-block: 0;
	border-block-end: 1px solid var(--border-soft);
	padding-block: 16px;
	font-family: var(--display);
	font-size: var(--wp--preset--font-size--md);
	font-weight: 500;
	line-height: var(--wp--custom--leading--snug);
}

.related-post a {
	color: var(--text);
	text-decoration: none;
	transition: color var(--wp--custom--effect--dur-fast) ease;
}

.related-post a:hover,
.related-post a:focus-visible {
	color: var(--primary);
}

/*
 * Stacked, the column becomes a byline row above the article: face on the
 * left, name and role beside it. Keeping it as a column would put a lone
 * portrait over a heading with the name floating under it.
 */
@media (max-width: 860px) {
	.post-layout {
		grid-template-columns: 1fr;
		gap: 24px;
	}

	.post-aside {
		position: static;
		display: grid;
		grid-template-columns: auto 1fr;
		column-gap: 16px;
		align-items: center;
		border-block-end: 1px solid var(--border);
		padding-block-end: 22px;
	}

	.post-aside .author-portrait {
		grid-row: 1 / span 2;
	}

	.author-portrait img {
		inline-size: 72px;
	}

	.post-aside .author-name {
		margin-block: 0;
		align-self: end;
	}

	.post-aside .author-bio {
		align-self: start;
	}
}

@media (max-width: 600px) {
	.post-meta {
		flex-direction: column;
		gap: 16px;
	}
}

/* =========================================================================
   PODCAST - the show, its episodes, its host.
   ========================================================================= */

/* The illustration beside the opener: its own size, never wider than the column. */
.podcast-art img {
	inline-size: 100%;
	block-size: auto;
}

/*
 * One episode per row, thumbnail then copy. Not a grid of cards: every episode
 * carries a paragraph of description, and at three-up those paragraphs become
 * columns of three-word lines - the same reason the stories grid went to one
 * per row.
 */
.episode-list {
	display: grid;
	gap: 18px;
}

.episode {
	display: grid;
	grid-template-columns: minmax(0, 300px) minmax(0, 1fr);
	gap: clamp(18px, 2.4vw, 34px);
	align-items: start;
	border: 1px solid var(--border);
	background: var(--surface);
	padding: clamp(16px, 1.8vw, 22px);
	transition: border-color var(--wp--custom--effect--dur-fast) ease;
}

.episode:hover {
	border-color: var(--primary);
}

.episode-thumb {
	margin: 0;
}

/*
 * The play badge is drawn here rather than shipped as an image: a triangle in a
 * ring, over the middle of the thumbnail. Built on the anchor so it only
 * appears where the thumbnail is actually a link.
 */
.episode-thumb a {
	position: relative;
	display: block;
}

.episode-thumb img {
	display: block;
	inline-size: 100%;
	block-size: auto;
	aspect-ratio: 16 / 9;
	object-fit: cover;
}

/* The ring. */
.episode-thumb a::before {
	content: "";
	position: absolute;
	inset-block-start: 50%;
	inset-inline-start: 50%;
	inline-size: 52px;
	block-size: 52px;
	transform: translate(-50%, -50%);
	border: 2px solid var(--primary);
	border-radius: 50%;
	background: var(--wp--custom--color--primary-wash2);
	transition: transform var(--wp--custom--effect--dur-fast) ease;
}

/*
 * And the triangle inside it, drawn with borders rather than a background:
 * a background can only paint a rectangle, and a square in a ring is a stop
 * button. Nudged right of centre because a triangle's visual centre is not
 * its bounding box's.
 */
.episode-thumb a::after {
	content: "";
	position: absolute;
	inset-block-start: 50%;
	inset-inline-start: 50%;
	inline-size: 0;
	block-size: 0;
	transform: translate(-40%, -50%);
	border-block: 9px solid transparent;
	border-inline-start: 15px solid var(--primary);
	border-inline-end: 0;
	transition: transform var(--wp--custom--effect--dur-fast) ease;
}

.episode:hover .episode-thumb a::before {
	transform: translate(-50%, -50%) scale(1.08);
}

.episode:hover .episode-thumb a::after {
	transform: translate(-40%, -50%) scale(1.08);
}

.episode-meta {
	margin-block: 0 8px;
	color: var(--muted);
	font-family: var(--mono);
	font-size: var(--wp--preset--font-size--eyebrow);
	letter-spacing: var(--wp--custom--tracking--eyebrow);
	text-transform: uppercase;
}

.episode-title {
	margin-block: 0 6px;
	color: var(--text);
	font-family: var(--display);
	font-size: var(--wp--preset--font-size--lg);
	font-weight: 600;
	line-height: var(--wp--custom--leading--snug);
	letter-spacing: var(--wp--custom--tracking--tight);
}

.episode-title a {
	color: inherit;
	text-decoration: none;
}

.episode-title a:hover,
.episode-title a:focus-visible {
	color: var(--primary);
}

/* The guest, set like an attribution - it names a person, not a section. */
.episode-guest {
	margin-block: 0 12px;
	color: var(--primary);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
}

.episode-blurb {
	margin-block: 0;
	color: var(--muted);
	font-size: var(--wp--preset--font-size--sm);
	line-height: var(--wp--custom--leading--lead);
}

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

/* ------------------------------------------------------------- The host */

.host-portrait {
	margin: 0;
}

.host-portrait img {
	inline-size: 100%;
	max-inline-size: 260px;
	block-size: auto;
	aspect-ratio: 1 / 1.09;
	object-fit: cover;
	clip-path: var(--hex);
}

/*
 * The four numbers, under the biography they belong to. A plain row: the
 * figures are large enough to be the structure, and boxing each one would make
 * four cards out of one claim.
 */
.wp-block-columns.stat-row {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 16px;
	margin-block-start: clamp(36px, 4vw, 56px);
	border-block-start: 1px solid var(--border);
	padding-block-start: clamp(28px, 3vw, 40px);
}

.wp-block-columns.stat-row > .wp-block-column {
	flex-basis: auto;
}

.stat-figure {
	margin-block: 0 4px;
	color: var(--primary);
	font-family: var(--display);
	font-size: var(--wp--preset--font-size--2xl);
	font-weight: 700;
	line-height: 1;
	letter-spacing: var(--wp--custom--tracking--tighter);
}

.stat-label {
	margin-block: 0;
	color: var(--muted);
	font-family: var(--mono);
	font-size: var(--wp--preset--font-size--eyebrow);
	letter-spacing: var(--wp--custom--tracking--eyebrow);
	text-transform: uppercase;
}

@media (max-width: 720px) {
	.wp-block-columns.stat-row {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 28px 16px;
	}
}

/* =========================================================================
   CONTACT - the two states, the three ways in, the three accounts.
   ========================================================================= */

/*
 * Two halves: the form, and everything you would reach for instead of filling
 * one in. core/columns already does the split; this only keeps the details
 * column from stretching to the form panel's height.
 */
.contact-columns {
	align-items: flex-start;
}

/*
 * The map is a small illustration, not a photograph: held to its own size
 * rather than stretched to the column, and aligned with the column it sits in
 * rather than centred in it.
 */
.contact-map {
	display: flex;
	justify-content: flex-start;
	margin-block: 0 14px;
}

.contact-map img {
	inline-size: auto;
	max-inline-size: min(100%, 420px);
	block-size: auto;
}

.contact-locations {
	margin-block-end: 36px;
	color: var(--muted);
	font-family: var(--mono);
	font-size: var(--wp--preset--font-size--sm);
	letter-spacing: var(--wp--custom--tracking--eyebrow);
}

/*
 * The phone number and the address are set as ghost buttons beside a solid
 * one, so the booking link stays the primary action without making the two
 * details that people actually came for look secondary.
 */
/*
 * The three ways in, stacked. Side by side they wrapped mid-column and the
 * phone number ended up on its own line anyway; down the column each is a
 * target the width of the thing beside it.
 */
.contact-details .wp-block-buttons {
	flex-direction: column;
	align-items: flex-start;
	gap: 10px;
	margin-block-end: 44px;
}

/* A section heading inside a column, so it steps down a size and loses the
   space a section head would carry above it. */
.contact-connect-title {
	margin-block: 0 18px;
	font-size: var(--wp--preset--font-size--xl);
}

/* Logos-only social links inherit currentcolor; the block's own icon colour
   is set in the markup, this only sizes and spaces them. */
.contact-details .wp-block-social-links {
	gap: 18px;
}

.contact-details .wp-block-social-link {
	transition: transform var(--wp--custom--effect--dur-fast) ease;
}

.contact-details .wp-block-social-link:hover {
	transform: translateY(-2px);
}

/* =========================================================================
   EXECUTIVE TEAM - three people, three faces.

   Plain columns, not cards: the portrait is the object here, and a panel
   around a face reads as a product listing.
   ========================================================================= */

.wp-block-columns.team-grid {
	gap: clamp(20px, 3vw, 40px);
}

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

/*
 * The same hexagon the quote attributions clip a face to, at the size a face
 * can carry a column on its own. `inline-size` needs !important for the same
 * reason it does on the quote portraits: core prints a width on the image
 * wrapper that would otherwise win.
 */
/*
 * The figure centres its own image rather than inheriting text-align from the
 * column. core/image's figure is styled differently depending on the block's
 * options - flex here, shrink-wrapped elsewhere - and a portrait sitting off
 * to one side of a centred name is the failure that causes, so the centring is
 * structural instead of inherited.
 */
.team-portrait {
	display: flex;
	justify-content: center;
	margin-block: 0 22px;
	margin-inline: auto;
}

/*
 * Block and auto margins, not inherited text-align. An image is inline by
 * default, so a centred parent usually centres it - but core prints its own
 * rules on .wp-block-image and the figure is doing nothing else here, so the
 * centring is stated rather than assumed.
 */
.team-portrait img {
	display: block;
	margin-inline: auto;
	inline-size: clamp(132px, 14vw, 180px) !important;
	block-size: auto;
	aspect-ratio: 1 / 1.09;
	object-fit: cover;
	clip-path: var(--hex);
}

.team-member .pillar-title {
	margin-block-end: 6px;
}

/*
 * The title, set like an eyebrow but without its hexagon bullet - centred
 * under a name, a marker on one side would pull the line off its axis.
 */
.team-role {
	color: var(--muted);
	font-family: var(--mono);
	font-size: var(--wp--preset--font-size--eyebrow);
	letter-spacing: var(--wp--custom--tracking--eyebrow);
}

@media (max-width: 780px) {
	.wp-block-columns.team-grid {
		gap: 36px;
	}
}

/* ------------------------------------------------------- Success stories */

/**
 * Two tiles to a row rather than three. Each card carries a photograph, a logo,
 * an outcome and a quote - four things - and at a third of the row that stack
 * gets narrow enough that every outcome wraps to four or five lines. Halving
 * the row gives each tile about 630px, which is where the quote reads as a
 * quote instead of a column of two-word lines.
 *
 * Scoped to #stories: .feature-grid is three-up wherever else it is used.
 */
/**
 * One story to a row, and the story split in two: who and what on the left,
 * what they said on the right.
 *
 * A full-width tile is the only shape that lets both halves read at once - at
 * two or three to a row the quote was a column of two-word lines. It also
 * suits the material: fourteen entries that each want a sentence of outcome
 * and a sentence of testimony, rather than fourteen thumbnails.
 */
#stories .wp-block-columns.feature-grid {
	grid-template-columns: 1fr;
	gap: 20px;
}

#stories .story-card {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
	gap: clamp(22px, 4vw, 56px);
	align-items: start;
	padding: clamp(28px, 3.2vw, 46px);
}

/* Left: the mark and the outcome. Right: the quote, spanning both rows. */
#stories .story-card .story-logo {
	grid-column: 1;
	grid-row: 1;
}

#stories .story-card .pillar-title {
	grid-column: 1;
	grid-row: 2;
	align-self: start;
	font-size: var(--wp--preset--font-size--2xl);
}

/*
 * The way into the story, under the outcome it summarises.
 *
 * The card places every child explicitly, so a new one has to be told where to
 * go or it lands in whatever cell auto-placement finds - here, beside the
 * quote. Its own row, under the headline, keeps the left column reading as one
 * thing: mark, outcome, way in. `margin-block-start: auto` pins it to the
 * floor so the buttons line up across cards whose outcomes wrap differently.
 */
#stories .story-card .wp-block-buttons {
	grid-column: 1;
	grid-row: 3;
	margin-block-start: auto;
	padding-block-start: 22px;
}

#stories .story-card .story-video,
#stories .story-card .wp-block-quote {
	grid-column: 2;

	/* Spans the mark, the outcome and the button - the whole left column. */
	grid-row: 1 / span 3;

	/* The separating rule turns with the layout: a line down the middle rather
	   than across the card. */
	margin-block-start: 0;
	border-block-start: 0;
	border-inline-start: 1px solid var(--border-soft);
	padding-block-start: 0;
	padding-inline-start: clamp(22px, 3vw, 44px);
}

#stories .story-card .story-logo img {
	max-inline-size: clamp(130px, 14vw, 180px);
	max-block-size: 40px;
}

/* The two cards that carry a film instead of a quote: same cell, no rule beside
   it - a video is already a bounded object and does not need framing. */
#stories .story-card .story-video {
	margin: 0;
	align-self: center;
}

/* A card with neither a quote nor a film has no second column to fill. */
#stories .story-card:not(:has(.wp-block-quote)):not(:has(.story-video)) {
	grid-template-columns: 1fr;
}

@media (max-width: 860px) {
	#stories .story-card {
		grid-template-columns: 1fr;
	}

	#stories .story-card .story-logo,
	#stories .story-card .pillar-title,
	#stories .story-card .story-video,
	#stories .story-card .wp-block-buttons,
	#stories .story-card .wp-block-quote {
		grid-column: 1;
		grid-row: auto;
	}

	/* Stacked, the button follows the quote instead of the outcome, so it is
	   the last thing in the card rather than a divider in the middle of it. */
	#stories .story-card .wp-block-buttons {
		order: 1;
		margin-block-start: 0;
	}

	/* Stacked, the rule goes back to being a horizontal one. */
	#stories .story-card .wp-block-quote {
		border-block-start: 1px solid var(--border-soft);
		border-inline-start: 0;
		padding-block-start: 20px;
		padding-inline-start: 0;
	}
}

/**
 * The stories hero centres its head. base.css start-aligns .section-head to the
 * content column, which is what keeps a head flush with the grid beneath it -
 * here the head IS the section, so it takes the middle instead.
 */
/*
 * Centred openers. base.css start-aligns .section-head to the content column
 * and caps it at 720px, which is right for a section head over a grid and
 * wrong for a page opener meant to sit over the middle of what follows - the
 * text centres inside a box that is itself off to the left, which reads as a
 * mistake rather than a choice.
 *
 * Listed by page rather than given a class of its own because these are the
 * openers, a closed set; if a fourth kind of page wants it, that is the moment
 * to make it .section-head--center instead.
 */
.stories-hero .wp-block-group.section-head,
.blog-hero .wp-block-group.section-head,
.pas-guide .wp-block-group.section-head,
.t360-steps .wp-block-group.section-head {
	margin-inline: auto !important;
	text-align: center;
}

.stories-hero .section-head .is-style-lead,
.blog-hero .section-head .is-style-lead,
.pas-guide .section-head .is-style-lead {
	margin-inline: auto !important;
}

/* --------------------------------------------------------------- Proof bar */

.logo-wordmark {
	display: flex;
	align-items: center;
	gap: 8px;
	color: var(--text);
	opacity: 0.42;
	transition: opacity var(--wp--custom--effect--dur-base) ease;
}

.logo-wordmark:hover {
	opacity: 0.85;
}

/* Hex mark before each wordmark - generated, so the markup stays clean. */
.logo-wordmark::before {
	content: "";
	flex: none;
	inline-size: 13px;
	block-size: 14px;
	background: currentcolor;
	clip-path: var(--hex);
}

/**
 * .logo-bar
 *
 * The image counterpart to the wordmarks above. Customer logos arrive at
 * whatever size and colour their owner ships them in - here a 6.5:1 lockup sits
 * next to a near-square mark - so the row is normalised twice over.
 *
 * Size: both axes are capped and neither is set, so each logo scales down to
 * fit the box on whichever axis binds first and keeps its own proportions. A
 * fixed height would blow the wide lockups off the end of the strip; a fixed
 * width would tower the square ones over everything else.
 *
 * Tone: every asset is a transparent cut-out, so brightness(0) flattens the ink
 * to black and invert(1) lifts it to white, alpha untouched. That gives one
 * quiet row instead of five competing palettes, without anyone hand-preparing
 * white versions. Hover drops the filter and returns the brand colour - the
 * same reveal-on-hover the wordmarks do with opacity. Delete the filter
 * declarations if the logos should always be full colour.
 */
.logo-bar .wp-block-image {
	margin-block: 0;
}

.logo-bar img {
	inline-size: auto;
	block-size: auto;
	max-inline-size: clamp(96px, 13vw, 168px);
	max-block-size: clamp(24px, 3.4vw, 34px);
	opacity: 0.55;
	filter: brightness(0) invert(1);
	transition:
		opacity var(--wp--custom--effect--dur-base) ease,
		filter var(--wp--custom--effect--dur-base) ease;
}

.logo-bar img:hover {
	opacity: 1;
	filter: none;
}

/* ------------------------------------------------------------- Pricing head */

/**
 * The page opens on a centred head with a glow behind it, so the table below
 * reads as the answer to a question the top of the page asked.
 *
 * Centring takes two overrides, both !important, because the rules being beaten
 * carry it: base.css start-aligns .section-head to the content column, and
 * components.css start-aligns .is-style-lead the same way. Neither is wrong -
 * they are what keeps every other section's head flush with the content beneath
 * it - so this reverses them for one section rather than weakening them.
 *
 * text-align does the rest. The eyebrow is an inline-flex box, which means it
 * is an inline-level box and therefore centres with the text; it does not need
 * a rule of its own.
 */
.pricing-plans .wp-block-group.section-head {
	margin-inline: auto !important;
	text-align: center;
}

.pricing-plans .section-head .is-style-lead {
	margin-inline: auto !important;
}

/**
 * The glow. Top centre, fading out before it reaches the table - the ambient
 * layer rules above give it its position, z-index and isolation, so all this
 * adds is where it sits and how far down it reaches. The gradient is a real
 * preset (tools/build-tokens.mjs), not a hand-rolled radial with a literal
 * colour in it.
 */
.pricing-plans::before {
	inset: 0 0 auto;
	block-size: min(560px, 60%);
	background: var(--wp--preset--gradient--head-glow);
}

/* ------------------------------------------------------------ Pricing table */

/**
 * Plan comparison. Selected through the section class rather than a class on
 * the table, so the pattern carries no markup an editor can lose, and written
 * one element deeper than core's `.wp-block-table td` - with separate block
 * assets those rules can be printed after this file.
 */
.pricing-plans .wp-block-table {
	overflow-x: auto;
}

.pricing-plans table {
	inline-size: 100%;
	min-inline-size: 660px;
	border-collapse: collapse;
}

.pricing-plans table th,
.pricing-plans table td {
	border: 0;
	border-block-end: 1px solid var(--border-soft);
	padding: 14px 18px;
	text-align: start;
	vertical-align: middle;
}

/* The plan columns are a set of values, so they centre under their heading. */
.pricing-plans table th:not(:first-child),
.pricing-plans table td:not(:first-child) {
	text-align: center;
}

.pricing-plans table thead th {
	border-block-end: 1px solid var(--border);
	color: var(--text);
	font-family: var(--display);
	font-size: var(--wp--preset--font-size--xl);
	font-weight: 600;
	letter-spacing: var(--wp--custom--tracking--tighter);
}

/* The corner cell labels the rows rather than naming a plan, so it recedes. */
.pricing-plans table thead th:first-child {
	color: var(--faint);
	font-family: var(--mono);
	font-size: var(--wp--preset--font-size--eyebrow);
	font-weight: 400;
	letter-spacing: var(--wp--custom--tracking--label);
	text-transform: uppercase;
}

.pricing-plans table tbody th {
	color: var(--text);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 400;
}

.pricing-plans table tbody td {
	color: var(--muted);
	font-size: var(--wp--preset--font-size--sm);
}

/* The middle tier is the one the price sheet tints. */
.pricing-plans table th:nth-child(3),
.pricing-plans table td:nth-child(3) {
	background: var(--wp--custom--color--primary-veil);
}

/* The fee row closes the table, so it carries the weight and drops the rule. */
.pricing-plans table tfoot th,
.pricing-plans table tfoot td {
	border-block-end: 0;
	color: var(--text);
	font-size: var(--wp--preset--font-size--md);
	font-weight: 600;
	padding-block: 22px;
}

/**
 * The fee cells hold the plan CTAs. They are links rather than button blocks,
 * because a table cell is rich text and rich text cannot nest a block - so the
 * button treatment is applied from the cell. A class on the anchor would not
 * survive: core's rich text keeps an href, not a class.
 *
 * Same chamfer and hover lift as the theme's buttons, one size down, matching
 * the nav's own call to action.
 */
.pricing-plans table tfoot a {
	--notch: var(--wp--custom--notch--xs);

	display: inline-block;
	padding: 12px 22px;
	background: var(--primary);
	color: var(--bg);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
	letter-spacing: var(--wp--custom--tracking--tight);
	text-decoration: none;
	clip-path: polygon(0 0, calc(100% - var(--notch)) 0, 100% var(--notch), 100% 100%, 0 100%);
	transition:
		transform var(--wp--custom--effect--dur-fast) ease,
		box-shadow var(--wp--custom--effect--dur-base) ease;
}

/* The colour is restated because theme.json turns links primary on hover, which
   here would be orange on orange. */
.pricing-plans table tfoot a:hover {
	transform: translateY(-2px);
	box-shadow: var(--wp--preset--shadow--glow-primary);
	color: var(--bg);
}

/* clip-path crops an outline, so focus inverts the button instead - the same
   trade the carousel controls make. */
.pricing-plans table tfoot a:focus-visible {
	outline: 2px solid transparent;
	background: var(--text);
	color: var(--bg);
}

@media (prefers-reduced-motion: reduce) {
	.pricing-plans table tfoot a,
	.pricing-plans table tfoot a:hover {
		transform: none;
		transition: none;
	}
}

/* ------------------------------------------------------------ Partner band */

/**
 * Logo beside a single line of copy. Both are selected structurally - the band
 * holds one image and one paragraph - so the pattern carries no extra classes.
 * The lockup is wider than it is tall, so it is sized on the inline axis and
 * left to keep its own aspect ratio.
 */
.partner-band .wp-block-image img {
	inline-size: clamp(170px, 18vw, 224px);
	block-size: auto;
}

/* Two comfortable lines at the band's full width, as in the reference. */
.partner-band p {
	max-width: 62ch;
}

/* ---------------------------------------------------------------- Pillars */

.pillar-grid {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 16px;
}

/* The hex frame inside a pillar card is smaller than the default 64px. */
.pillar-title {
	margin: 0 0 10px;
	color: var(--text);
	font-family: var(--display);
	font-size: var(--wp--preset--font-size--xl);
	font-weight: 600;
	letter-spacing: var(--wp--custom--tracking--tighter);
	line-height: 1.1;
}

.pillar-copy {
	margin: 0;
	color: var(--muted);
	font-size: var(--wp--preset--font-size--sm);
	line-height: var(--wp--custom--leading--snug);
}

/* =========================================================================
   PROCESS TIMELINE - the "How it works" steps and the engagement phases.

   The numbered hexagon node is generated, not authored: ::before is the ring,
   ::after is the face and prints the number from a counter. So the step markup
   is pure content, an editor cannot break the sequence, and a step added or
   removed renumbers the rest.
   ========================================================================= */

.wp-block-columns.timeline {
	/**
	 * Pointy-top hexagon - the orientation every generated frame uses (the
	 * icon SVGs in tools/build-decor.mjs, and .hex-frame). It is --hex turned
	 * 90deg, and it is local because the token pipeline only exposes the
	 * pointy-side --hex used for bullets and swatches.
	 */
	--hex-frame: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
	--node: 64px;

	position: relative;
	display: grid;
	/* auto-fit rather than a fixed 3: the engagement phases are four. */
	grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
	counter-reset: step;
	gap: 0;
	margin-block-start: 24px;
}

.wp-block-columns.timeline > .wp-block-column {
	flex-basis: auto;
}

/* The rail. Fades out before the section edges so it reads as a span between
   the nodes rather than a rule across the page. It is the grid's own ::before,
   so the step pseudo-elements paint over it and mask it at each node. */
.timeline::before {
	content: "";
	position: absolute;
	inset-block-start: calc(var(--node) / 2 - 1px);
	inset-inline: 8%;
	block-size: 1px;
	background: linear-gradient(90deg, transparent, var(--primary), var(--primary), transparent);
	opacity: 0.35;
}

.timeline > .step {
	position: relative;
	counter-increment: step;
	padding-block-start: calc(var(--node) + 28px);
	padding-inline: 26px;
}

/* Ring and face are the same hexagon, the face inset by 2px. */
.timeline > .step::before,
.timeline > .step::after {
	content: "";
	position: absolute;
	inset-block-start: 0;
	inset-inline-start: 26px;
	inline-size: var(--node);
	block-size: var(--node);
	clip-path: var(--hex-frame);
	background: var(--primary);
}

.timeline > .step::after {
	content: counter(step);
	display: grid;
	place-items: center;
	inset-block-start: 2px;
	inset-inline-start: 28px;
	inline-size: calc(var(--node) - 4px);
	block-size: calc(var(--node) - 4px);
	background: var(--surface-2);
	color: var(--primary);
	font-family: var(--display);
	font-size: var(--wp--preset--font-size--xl);
	font-weight: 800;
}

.step-phase {
	margin-block-end: 8px;
	color: var(--faint);
	font-family: var(--mono);
	font-size: var(--wp--preset--font-size--eyebrow);
	letter-spacing: var(--wp--custom--tracking--label);
	text-transform: uppercase;
}

.step-title {
	margin-block-end: 12px;
	font-family: var(--display);
	font-size: var(--wp--preset--font-size--2xl);
	font-weight: 600;
	letter-spacing: var(--wp--custom--tracking--tighter);
}

.step-copy {
	max-width: 32ch;
	color: var(--muted);
	line-height: var(--wp--custom--leading--snug);
}

/* Stacked, the rail has nothing to connect. */
@media (max-width: 820px) {
	.wp-block-columns.timeline {
		grid-template-columns: 1fr;
		gap: 44px;
	}

	.timeline::before {
		display: none;
	}
}

/* =========================================================================
   PLATFORM COMPONENTS - the timeline, with the sequence taken back out.

   Libraries, Architect, Assistant and Support are four parts of one platform,
   not four stages of anything, so this section drops the rail and the numbers
   that the shared .timeline component prints. What replaces the numbered
   hexagon is a short rule: a marker that reads as "one of a set" rather than
   "the third of four", identical on all four so none of them leads.

   The name carries the weight instead. It takes the display size the tagline
   used to have, so the section's typographic palette and vertical rhythm are
   unchanged - the prominence simply moves from the phrase to the product.

   Selected by position, not by class, deliberately: the name is the first
   element and the tagline the second whichever tag each one uses, so this holds
   whether the markup leads with a paragraph (as the published page does) or
   with the heading (as the pattern now does).
   ========================================================================= */

#components .timeline > .step::before {
	display: none;
}

/**
 * What ties the four together: one hairline running the full width of the row,
 * with each component's marker sitting on it as a thickened segment. Four posts
 * under one beam - it says "parts of one platform" where the old rail, with its
 * numbered nodes and its fade from one end to the other, said "first, then,
 * then, finally".
 *
 * Squared off at both ends and evenly weighted on purpose. A gradient that
 * faded at one end, or an arrowhead, would put the sequence straight back.
 */
#components .timeline::before {
	display: block;
	inset-block-start: 0;
	inset-inline: 0;
	block-size: 1px;
	background: var(--wp--custom--color--primary-dim);
	opacity: 1;
}

/**
 * The numbered face becomes the marker: a short, heavier segment of the beam
 * above it, at full strength where the beam is dimmed. Same anchor point the
 * number used, no sequence.
 */
#components .timeline > .step::after {
	content: "";
	inset-block-start: 0;
	inset-inline-start: 26px;
	inline-size: 44px;
	block-size: 3px;
	clip-path: none;
	background: var(--primary);
}

/* The node reserved 92px of head room; the rule needs a fraction of it. */
#components .timeline > .step {
	padding-block-start: 30px;
}

/**
 * The component name, which is the thing a reader is scanning for. Up from the
 * 2xl step to the card-heading clamp and from 600 to 700 - two words in a
 * quarter-width column, so it sets on two lines at every desktop width and the
 * four names stack into a consistent block rather than a ragged one.
 */
#components .timeline > .step > :first-child {
	margin-block-end: 8px;
	color: var(--text);
	font-family: var(--display);
	font-size: var(--wp--preset--font-size--h-card);
	font-weight: 700;
	letter-spacing: var(--wp--custom--tracking--tighter);
	line-height: 1.05;
	text-transform: none;
}

/* What it does, in the label voice the names used to wear. */
#components .timeline > .step > :nth-child(2) {
	margin-block-end: 14px;
	color: var(--primary);
	font-family: var(--mono);
	font-size: var(--wp--preset--font-size--eyebrow);
	font-weight: 400;
	letter-spacing: var(--wp--custom--tracking--label);
	line-height: 1.4;
	text-transform: uppercase;
}

/* --------------------------------------------------------------- AI band */

.ai-band {
	background: var(--wp--custom--color--ai-canvas);
}

.ai-band .ai-lead {
	color: var(--wp--custom--color--ai-lead);
	max-width: 56ch;
}

.ai-band .ai-list > li {
	color: var(--wp--custom--color--ai-body);
}

.ai-band .ai-list > li::before {
	background: var(--violet-light);
}

.ai-band .ai-list strong {
	color: var(--text);
	font-weight: 600;
}


/* =========================================================================
   AMBIENT DECORATION
   These layers used to be `wp:html` blocks inside the patterns, which put
   decoration into post_content where an editor could break it. They are now
   pseudo-elements, so the section markup an editor sees contains only content.

   `isolation: isolate` scopes the z-index:-1 to the section, so the layer sits
   behind the section's own content without falling behind the page background.
   ========================================================================= */

.hero-section,
.cta-section,
.ai-band,
.pricing-plans {
	position: relative;
	overflow: hidden;
	isolation: isolate;
}

.hero-section::before,
.cta-section::before,
.ai-band::before,
.ai-band::after,
.pricing-plans::before {
	content: "";
	position: absolute;
	z-index: -1;
	pointer-events: none;
}

/* Hero: warm glow from the upper right, matching the prototype. */
.hero-section::before {
	inset: 0;
	background: var(--wp--preset--gradient--hero-glow);
}

/**
 * The breathing hexagon grid, injected by assets/js/hex-grid.js.
 *
 * z-index -2 puts it above the section's own background but below the ::before
 * glow at -1, which is the prototype's layer order: grid first, glow over it.
 *
 * `margin: 0` is not decorative. Core's constrained-layout rules give every
 * child of the group a block-start margin, and on an inset:0 absolute box that
 * would push the canvas down and shrink it. Those rules are :where()-wrapped,
 * so a single class overrides them.
 */
.hex-grid {
	position: absolute;
	z-index: -2;
	inset: 0;
	margin: 0;
	inline-size: 100%;
	block-size: 100%;
	pointer-events: none;
}

/* =========================================================================
   PLATFORM HERO - copy on the right, depth field on the left.

   The row is reversed here rather than in the markup, so the headline stays
   first in the document for screen readers and tab order while sitting second
   on screen. Core stacks columns at 781px by wrapping them, not by changing
   direction, so the reversal has to be undone there or the mobile order would
   come out animation-first.
   ========================================================================= */

.platform-hero .wp-block-columns {
	flex-direction: row-reverse;
}

/**
 * The canvas mount. It keeps the lattice column's height so the hero's balance
 * is unchanged, but carries no background of its own - what fills it is
 * assets/js/hex-depth.js, and with JS off it is simply empty space, which is
 * what the old static lattice would have been anyway if the SVG failed.
 */
.platform-hero .hero-depth {
	position: relative;
	display: grid;
	place-items: center;
	align-self: stretch;
	min-block-size: 460px;
	overflow: hidden;
}

/**
 * The foreground figure (assets/js/hero-core.js). It shares the column with the
 * canvas and paints over it, which is the whole arrangement: hairlines drifting
 * behind, mass in front.
 *
 * Sized against the column rather than the viewport so it keeps its relationship
 * to the copy at every width, and capped so it never outgrows the hero.
 */
.platform-hero .hero-core {
	position: relative;
	z-index: 1;
	display: block;
	inline-size: min(100%, 420px);
	block-size: auto;
	margin-inline: auto;
	overflow: visible;
	filter: drop-shadow(0 18px 40px var(--wp--custom--color--shadow-deep));
}

/* Top faces: the plate you look down on. */
.platform-hero .hero-core__face {
	fill: var(--surface-2);
	stroke: var(--primary);
	stroke-width: 1.5;
	stroke-linejoin: round;
}

/* Front edges: the same plate's thickness, in shadow. */
.platform-hero .hero-core__edge {
	fill: var(--bg-2);
	stroke: var(--wp--custom--color--primary-dim);
	stroke-width: 1;
	stroke-linejoin: round;
}

/* The one solid mark, and the only saturated area in the hero. */
.platform-hero .hero-core__cell {
	fill: var(--primary);
}

/**
 * A long, shallow float - seven seconds, six pixels - with each plate a beat
 * behind the one above it, so the stack settles and lifts rather than bobbing
 * in unison. Any faster and it would pull attention off the headline, which is
 * the one thing this graphic must not do.
 */
.platform-hero .hero-core__plate {
	animation: hero-core-float 7s ease-in-out infinite;
	animation-delay: calc(var(--i, 0) * -0.9s);
	transform-box: fill-box;
	transform-origin: center;
}

@keyframes hero-core-float {
	0%,
	100% {
		translate: 0 0;
	}

	50% {
		translate: 0 -6px;
	}
}

.platform-hero .hero-core__cell {
	animation: hero-core-breathe 6s ease-in-out infinite;
}

@keyframes hero-core-breathe {
	0%,
	100% {
		opacity: 0.72;
	}

	50% {
		opacity: 1;
	}
}

@media (prefers-reduced-motion: reduce) {
	.platform-hero .hero-core__plate,
	.platform-hero .hero-core__cell {
		animation: none;
	}

	.platform-hero .hero-core__cell {
		opacity: 1;
	}
}

.platform-hero .hex-depth {
	position: absolute;
	z-index: 0;
	inset: 0;
	display: block;
	inline-size: 100%;
	block-size: 100%;
	margin: 0;
	pointer-events: none;
}

@media (max-width: 1080px) {
	.platform-hero .hero-depth {
		min-block-size: 300px;
		opacity: 0.6;
	}
}

@media (max-width: 781px) {
	.platform-hero .wp-block-columns {
		flex-direction: row;
	}
}

/* Hero lattice: a generated SVG (see tools/build-decor.mjs), loaded as a
   background so it stays out of the block markup entirely. */
.hero-lattice {
	min-block-size: 460px;
	background: url("../img/hex-lattice.svg") no-repeat center / contain;
}

@media (max-width: 1080px) {
	.hero-lattice {
		min-block-size: 300px;
		opacity: 0.6;
	}
}

/* Final CTA: centred glow. */
.cta-section::before {
	inset: 0;
	background: var(--wp--preset--gradient--cta-glow);
}

/**
 * AI band: violet core (::before) and the bedrock section (::after).
 *
 * The cluster that used to sit here was another comb, which said nothing the
 * rest of the page was not already saying. The section's argument is that
 * generated code needs something underneath it, so the figure is a foundation
 * detail: a shaft sunk through fill and fractured rock into a footing.
 *
 * This one is supplied artwork rather than a generated asset - assets/img/
 * bedrock.png, a transparent PNG, so it sits on the band without a plate behind
 * it. It is the only decorative image in the theme that is not built from
 * tokens, which means its colour does not follow the palette if the palette
 * moves; see the note on the ratio below.
 */
.ai-band::before {
	inset: 50% auto auto 92%;
	inline-size: 360px;
	block-size: 360px;
	translate: -50% -50%;
	background: radial-gradient(circle, var(--wp--custom--color--violet-core), transparent 60%);
	filter: blur(30px);
}

.ai-band::after {
	inset: 50% -2% auto auto;

	/* 1024 x 891 - the height follows the width so the drawing never squashes. */
	inline-size: min(560px, 52vw);
	aspect-ratio: 1024 / 891;
	translate: 0 -50%;
	background: url("../img/bedrock.png") no-repeat center / contain;
	opacity: 0.85;
}

@media (max-width: 1080px) {
	.ai-band::before,
	.ai-band::after {
		opacity: 0.3;
	}
}

/* =========================================================================
   HEXAGON ICONS
   Registered as block style variations on core/group and core/column, so a
   card's icon is a class the editor picks from the Styles menu - not markup.
   Each SVG is generated from tokens.json.
   ========================================================================= */

[class*="is-style-hexicon-"]::before {
	content: "";
	display: block;
	inline-size: 56px;
	block-size: 56px;
	margin-block-end: 24px;
	background-repeat: no-repeat;
	background-position: center;
	background-size: contain;
}

.is-style-hexicon-chart::before   { background-image: url("../img/hexicon-chart.svg"); }
.is-style-hexicon-trend::before   { background-image: url("../img/hexicon-trend.svg"); }
.is-style-hexicon-cost::before    { background-image: url("../img/hexicon-cost.svg"); }
.is-style-hexicon-service::before { background-image: url("../img/hexicon-service.svg"); }
.is-style-hexicon-stack::before   { background-image: url("../img/hexicon-stack.svg"); }
.is-style-hexicon-hexagon::before { background-image: url("../img/hexicon-hexagon.svg"); }
.is-style-hexicon-team::before    { background-image: url("../img/hexicon-team.svg"); }
.is-style-hexicon-check::before   { background-image: url("../img/hexicon-check.svg"); }
.is-style-hexicon-cloud::before   { background-image: url("../img/hexicon-cloud.svg"); }
.is-style-hexicon-code::before    { background-image: url("../img/hexicon-code.svg"); }
.is-style-hexicon-devices::before { background-image: url("../img/hexicon-devices.svg"); }
.is-style-hexicon-cycle::before   { background-image: url("../img/hexicon-cycle.svg"); }
.is-style-hexicon-flow::before    { background-image: url("../img/hexicon-flow.svg"); }
.is-style-hexicon-support::before { background-image: url("../img/hexicon-support.svg"); }
.is-style-hexicon-plug::before    { background-image: url("../img/hexicon-plug.svg"); }
.is-style-hexicon-docs::before    { background-image: url("../img/hexicon-docs.svg"); }

/* =========================================================================
   PRINCIPLE PILLARS - the four timeless principles, standing up.

   Scoped to #principles, the anchor that section already carries, so nothing
   else on the site changes. The cards keep every class they had - notch card,
   hexicon, reveal - and every block inside them; what changes is that each one
   is now read as a column holding something up rather than a box sitting on a
   shelf.

   Three cues do the work, all of them parts the theme already owns:
   a capital (the primary rule the carousel cards use across their top),
   a shaft (a vertical wash from the raised surface down to the page ground, so
   the foot of the pillar meets the floor rather than stopping on it), and a
   plinth (::after - the hexicon has already claimed ::before).
   ========================================================================= */

/**
 * The quadrant. It sits to the right of the head, abstracting what the four
 * principles are for: a grey dot where a product is now, a dashed run to the
 * top right, the hexagon where it lands.
 *
 * A background rather than an image block, the way .hero-lattice and the AI
 * band's cluster are done: it is decoration, so it stays out of post_content
 * where an editor could break it, and out of the accessibility tree where it
 * would only repeat what the heading beside it already says.
 *
 * --column-inset (base.css) pins its right edge to the content column rather
 * than the section's padding edge, so it lines up with the pillar on the end
 * however wide the viewport is. The head is given the graphic's height as a
 * floor, which is what keeps the pillars clear of it without either knowing
 * about the other.
 */
#principles {
	--quadrant: clamp(220px, 23vw, 316px);

	position: relative;
}

/*
 * Was #principles::after with a background-image. It is a real <img> now,
 * because an SVG referenced from CSS renders in "secure static mode" and its
 * animation never starts; see the note in platform-principles.php. The
 * positioning is unchanged - only what carries it.
 */
.quadrant-art {
	position: absolute;
	inset-block-start: var(--section-pad);
	inset-inline-end: var(--column-inset);
	inline-size: var(--quadrant);
	block-size: var(--quadrant);
	margin: 0;
	pointer-events: none;
}

.quadrant-art img {
	inline-size: 100%;
	block-size: 100%;
	object-fit: contain;
}

#principles .section-head {
	min-block-size: var(--quadrant);
}

/**
 * The head is capped at 720px and the graphic needs its own width beside it,
 * which the content column only has from about 1130px up. Below that the
 * graphic goes rather than shrinking into an unreadable thumbnail or sliding
 * under the heading - 1180px leaves a margin for error on the arithmetic.
 */
@media (max-width: 1180px) {
	.quadrant-art {
		display: none;
	}

	#principles .section-head {
		min-block-size: 0;
	}
}

#principles .pillar-grid > .wp-block-column {
	display: flex;
	flex-direction: column;
	align-items: center;
	min-block-size: clamp(230px, 17vw, 262px);
	padding: 32px 22px 38px;
	border-block-start: 2px solid var(--primary);
	background:
		linear-gradient(
			180deg,
			var(--surface-2) 0%,
			var(--surface) 46%,
			var(--bg) 100%
		);
	text-align: center;
}

/* The card's hover rule resets border-color on all four sides. */
#principles .pillar-grid > .wp-block-column:hover {
	border-block-start-color: var(--primary);
}

/* The capital ornament: the existing hexagon icon, centred under the rule. */
#principles .pillar-grid > .wp-block-column::before {
	inline-size: 48px;
	block-size: 48px;
	margin-inline: auto;
	margin-block-end: 20px;
}

/* The plinth. Inset from the sides so the shaft reads as standing on it. */
#principles .pillar-grid > .wp-block-column::after {
	content: "";
	position: absolute;
	inset-inline: 10px;
	inset-block-end: 12px;
	block-size: 3px;
	background: var(--wp--custom--color--primary-dim);
}

/**
 * The copy follows its title directly.
 *
 * It used to take the slack with `margin-block-start: auto`, on the reasoning
 * that pinning it to the floor would align the four. It does - but the four
 * titles are single words that already sit at the same height, so all the rule
 * really did was collect the shaft's spare height into one gap in the middle of
 * every pillar. The shaft is shorter now as well, which is where the rest of
 * that space went.
 */
#principles .pillar-grid .pillar-copy {
	padding-block-start: 10px;
}

/**
 * One per row on a phone: a 290px-tall pillar four times over is a lot of
 * scrolling for four short sentences, so the shaft collapses to the height of
 * its content and keeps only the capital and the plinth.
 */
@media (max-width: 560px) {
	#principles .pillar-grid > .wp-block-column {
		min-block-size: 0;
		padding-block: 26px 34px;
	}

	#principles .pillar-grid .pillar-copy {
		padding-block-start: 8px;
	}
}

/* =========================================================================
   PILLAR GRID
   core/columns is flex and stacks straight from 4 to 1. The design calls for
   4 / 2 / 1, so the grid is taken over here. Double class beats core's
   single-class rule regardless of stylesheet order.
   ========================================================================= */

.wp-block-columns.pillar-grid {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 16px;
}

.wp-block-columns.pillar-grid > .wp-block-column {
	flex-basis: auto;
}

@media (max-width: 1080px) {
	.wp-block-columns.pillar-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 560px) {
	.wp-block-columns.pillar-grid {
		grid-template-columns: 1fr;
	}
}

/**
 * .feature-grid
 *
 * The three-column relative of .pillar-grid, for the sections that come in
 * threes and sixes rather than fours. Same reason for taking the grid over from
 * core/columns: flex columns go straight from N to 1, and six cards dropping to
 * one column skips the two-up step that reads best on a tablet.
 */
.wp-block-columns.feature-grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 16px;
}

.wp-block-columns.feature-grid > .wp-block-column {
	flex-basis: auto;
}

@media (max-width: 1080px) {
	.wp-block-columns.feature-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/**
 * A card that runs the width of the grid. Its heading sits beside its copy
 * rather than above it: across three columns of width, a paragraph under a
 * heading would set to a measure nobody can read comfortably.
 */
/**
 * Six tracks rather than three, so the grid can do both rhythms: the ordinary
 * cards take two each and still run three up, while the pair at the foot take
 * three each and split the row in half. A three-column grid cannot halve a row.
 */
#capabilities .wp-block-columns.feature-grid {
	grid-template-columns: repeat(6, minmax(0, 1fr));
}

#capabilities .feature-grid > .wp-block-column {
	grid-column: span 2;
}

#capabilities .feature-grid > .wide-card {
	grid-column: span 3;
}

@media (max-width: 1080px) {
	#capabilities .feature-grid > .wp-block-column {
		grid-column: span 3;
	}

	#capabilities .feature-grid > .wide-card {
		grid-column: span 6;
	}
}

@media (max-width: 560px) {
	#capabilities .feature-grid > .wp-block-column {
		grid-column: span 6;
	}
}

.wp-block-columns.feature-grid > .wide-card {
	grid-column: 1 / -1;
	display: grid;
	grid-template-columns: auto minmax(170px, 1fr) 2.4fr;
	gap: clamp(14px, 3vw, 46px);
	align-items: center;
}

/**
 * The hexicon is a ::before, so in a grid it is simply the first item - which
 * is why the row above has three columns rather than two. Centred on the row
 * and stripped of the stacked card's bottom margin, since here it sits beside
 * the heading rather than above it.
 */
.wp-block-columns.feature-grid > .wide-card::before {
	align-self: center;
	margin-block-end: 0;
}

.wp-block-columns.feature-grid > .wide-card .pillar-title {
	margin-block-end: 0;
}

@media (max-width: 780px) {
	.wp-block-columns.feature-grid > .wide-card {
		grid-template-columns: 1fr;
	}

	.wp-block-columns.feature-grid > .wide-card::before {
		margin-block-end: 14px;
	}

	.wp-block-columns.feature-grid > .wide-card .pillar-title {
		margin-block-end: 10px;
	}
}

@media (max-width: 560px) {
	.wp-block-columns.feature-grid {
		grid-template-columns: 1fr;
	}
}

/* ------------------------------------------- Call-outs inside a post body */

/**
 * The panels that the imported posts carry in their bodies: the LinkedIn
 * call-out at the end of all 66, and the modernization plan in one of them.
 * They arrive as [elementor-template] shortcodes and are rendered from theme
 * patterns - see modularis_render_pattern() in functions.php.
 *
 * The source draws a flat grey box with a square orange link. This is the
 * theme's panel instead - the notched card that /getademo/ and the solution
 * pages already use - because the point of the port is that a reader moving
 * between an article and a solution page sees one site, not two.
 *
 * No alignment and no section padding: unlike nearly every other pattern here
 * this one renders inside the article column, so its width is the prose
 * measure and its margins are the gap between two paragraphs.
 */
.post-callout {
	margin-block: clamp(36px, 4.4vw, 56px);
	border: 1px solid var(--border);
	background: var(--surface);
	padding: clamp(26px, 3vw, 40px);
	clip-path: polygon(
		0 0,
		calc(100% - var(--wp--custom--notch--xl)) 0,
		100% var(--wp--custom--notch--xl),
		100% 100%,
		var(--wp--custom--notch--xl) 100%,
		0 calc(100% - var(--wp--custom--notch--xl))
	);
}

/*
 * An h2 in the markup so the article's outline stays honest, but not an
 * article heading: those open a section and are sized to be seen coming from
 * a paragraph away. This one labels the panel it sits in.
 */
.post-callout .post-callout-title {
	margin-block: 0 22px;
	color: var(--text);
	font-family: var(--display);
	font-size: var(--wp--preset--font-size--lg);
	font-weight: 600;
	line-height: var(--wp--custom--leading--snug);
	letter-spacing: var(--wp--custom--tracking--tight);
}

.post-callout > :last-child {
	margin-block-end: 0;
}

/* The plan's cover beside its form. */
.post-guide .hs-form-mount {
	min-block-size: 320px;
}

.post-guide-cover {
	margin-block: 0;
}

/* ---------------------------------------------- Video inside a post body */

/**
 * An embedded film fills the column.
 *
 * Classic [embed] content keeps whatever size the provider was asked for on
 * the day the post was written - width="500" height="281" on most of these,
 * 560x315 on the one that was pasted in as a raw iframe - and WordPress
 * prints those attributes verbatim. In a 74ch column that leaves a third of
 * the row empty beside the picture. The block editor answers this with a
 * figure and an aspect-ratio class, but classic content has no wrapper to
 * hang one on, so the iframe carries it itself.
 *
 * NOT done in PHP, deliberately. The provider's HTML is cached per post in
 * postmeta, so asking oEmbed for a wider frame would invalidate all fifteen
 * of those caches and send fifteen requests the next time the posts are read
 * - and any that failed would leave a bare link where a film used to be.
 * Styling what is already stored cannot fail and costs nothing.
 */
.post-article :where(iframe) {
	display: block;
	inline-size: 100%;
	max-inline-size: 100%;
}

/*
 * The ratio has to be stated rather than inferred, because the width and
 * height attributes are the very thing being overridden: left to them the
 * frame keeps its 281px and letterboxes the film inside a full-width box.
 *
 * By provider, not by every iframe. Everything WordPress calls an embed
 * arrives as one - a SoundCloud player among them - and those carry a height
 * of their own that a film's proportions would wreck.
 */
.post-article :where(
		iframe[src*="youtube.com"],
		iframe[src*="youtube-nocookie.com"],
		iframe[src*="youtu.be"],
		iframe[src*="player.vimeo.com"],
		iframe[src*="wistia.net"],
		iframe[src*="loom.com"]
	) {
	block-size: auto;
	aspect-ratio: 16 / 9;
}

/*
 * The one post that carries its film as an upload rather than an embed.
 * [video] writes the file's pixel width onto the wrapper as an inline style -
 * 1920px here - which only an !important can answer; core caps it at the
 * column with max-width, so today it happens to fill, but a 640px source
 * would sit in the middle of the row instead. MediaElement is initialised
 * with stretching:"responsive", so sizing the wrapper is all it needs.
 */
.post-article .wp-video {
	inline-size: 100% !important;
}

/* With scripts off MediaElement never runs, and the height attribute is left
   to letterbox the file inside its own frame. */
.post-article :where(video) {
	block-size: auto;
	max-inline-size: 100%;
}

/* --------------------------------------------- Downloadable (lead magnet) */

/**
 * The seven posts in the Downloadables category. Not an article: a centred
 * title and one line of copy, then the cover of the PDF beside the form that
 * sends it. templates/single-downloadable.html and the block behind it.
 *
 * Measurements are the source's. 880px is narrower than anything else on this
 * site, and that is the point - the page is one form, and a form that runs the
 * full width of a screen reads as a chore.
 */
.lead-magnet {
	max-inline-size: 880px;
	margin-inline: auto;
	padding-block: clamp(50px, 8vw, 80px);
	padding-inline: var(--gutter);
}

.lead-magnet-title {
	margin-block: 0 18px;
	color: var(--text);
	font-family: var(--display);
	font-size: clamp(28px, 3.4vw, 38px);
	font-weight: 700;
	line-height: 1.3;
	letter-spacing: var(--wp--custom--tracking--tight);
	text-align: center;
}

.lead-magnet-lead {
	color: var(--muted);
	font-size: var(--wp--preset--font-size--md);
	line-height: var(--wp--custom--leading--lead);
	text-align: center;
}

.lead-magnet-lead > :last-child {
	margin-block-end: 0;
}

/*
 * The cover and the form. The source splits them roughly a third to two
 * thirds, which is what a 240px picture next to a column of fields wants -
 * an even split would leave the cover swimming.
 */
.lead-magnet-row {
	display: grid;
	grid-template-columns: minmax(0, 34%) minmax(0, 66%);
	gap: 60px;
	align-items: start;
	margin-block-start: clamp(34px, 4.5vw, 50px);
}

/*
 * The tilt is the source's, and it is the one piece of styling on this page
 * that is doing real work: it says "this is a thing you are being handed"
 * rather than "this is a picture of a page". Kept at every width for that
 * reason.
 */
.lead-magnet-cover img {
	display: block;
	inline-size: 240px;
	max-inline-size: 100%;
	block-size: auto;
	margin-inline: auto;
	box-shadow: 0 8px 30px -6px var(--wp--custom--color--shadow-deep);
	transform: rotate(-10deg);
}

.lead-magnet-form {
	padding-block-start: 20px;
	min-block-size: 320px;
}

.lead-magnet-fallback {
	margin-block: 0;
	color: var(--faint);
	font-family: var(--mono);
	font-size: 13px;
}

/*
 * Stacked, the cover goes above the form rather than beside it. The tilt
 * needs room that a full-width column does not leave at the edges, so the
 * picture keeps its own margin under it - the source does the same.
 */
@media (max-width: 767px) {
	.lead-magnet-row {
		grid-template-columns: 1fr;
		gap: 30px;
	}

	.lead-magnet-cover {
		margin-block-end: 30px;
	}

	.lead-magnet-form {
		padding-block-start: 0;
	}
}

/* ------------------------------------------------- Longform document pages */

/**
 * The shell the two reference pages share: the privacy notice and the AI
 * information page. Both are documents rather than marketing - long, read in
 * one column, arrived at by somebody looking for one specific thing - so both
 * drop the site's section furniture and keep a single reading measure.
 *
 * Page-specific treatment lives under .policy-* and .aiinfo-* below. This is
 * only what the two genuinely share.
 */

/*
 * One measure for the whole document, in absolute units.
 *
 * This was 72ch, which was wrong in a way worth recording: ch resolves against
 * the font size of the element it is set on. The body text is 17px, so 72ch
 * was about 640px - right. A title at h-section, up to 66px, took the same
 * 72ch to near 2300px and simply filled the content width. The result was a
 * headline twice the width of everything beneath it: the page read as two
 * columns that had lost each other rather than as one document.
 *
 * A fixed value keeps the head and the body on the same edges at every size,
 * which is the only thing that makes a page this long look deliberate.
 */
.longform-head,
.longform-body {
	--doc-measure: 640px;
}

.longform-head {
	padding-block-end: 0;
}

.longform-head > *,
.longform-body > * {
	max-inline-size: var(--doc-measure);
	margin-inline: auto;
}

.longform-body {
	padding-block-start: clamp(28px, 3.4vw, 44px);
}

/*
 * The title, centred over the document and sized well below h-section. At
 * h-section's upper end a title of any length wraps to three lines inside the
 * measure, and a three-line headline on a reference page is shouting at
 * somebody who came to read the small print. The privacy page's source sets
 * its own h1 to 40px, which is where this lands.
 *
 * Centred here and nowhere else: body copy stays ranged left, because centred
 * text is read by finding each new line's start in a different place, and
 * there are thousands of words of it.
 */
.longform-title {
	font-size: clamp(28px, 3.4vw, 40px);
	line-height: var(--wp--custom--leading--snug);
	text-align: center;
}

/*
 * Body text one step up from the theme's default. At the size the rest of the
 * site uses, a wall of prose this long becomes hard work, and these pages have
 * nothing else competing for the space.
 */
.longform-body p {
	color: var(--muted);
	font-size: var(--wp--preset--font-size--md);
	line-height: var(--wp--custom--leading--lead);
}

.longform-body a {
	color: var(--primary);
	overflow-wrap: anywhere;
}

.longform-body strong {
	color: var(--text);
	font-weight: 600;
}

/* ------------------------------------------------------- Legal (policy page) */

/**
 * The privacy notice. Nobody reads this for pleasure: they arrive looking for
 * one section, and the page's work is to let them find it and then read it
 * without strain. Hence the rule above every numbered section.
 */
/* The date the notice was last changed - the source's own first line. */
.policy-updated {
	margin-block-end: clamp(26px, 3vw, 36px);
	color: var(--faint);
	font-family: var(--mono);
	font-size: var(--wp--preset--font-size--xs);
	letter-spacing: var(--wp--custom--tracking--caps);
	text-transform: uppercase;
}

.policy-updated strong {
	font-weight: 400;
}

/*
 * The thirteen numbered sections. The rule above each one is what makes the
 * document skimmable: at this length a reader scrolling for "12.) YOUR
 * CALIFORNIA PRIVACY RIGHTS" needs the sections to be visible as they go past,
 * and a size change alone is not enough when every heading is short.
 */
.policy-h2 {
	margin-block: clamp(44px, 5vw, 64px) 18px;
	padding-block-start: clamp(22px, 2.6vw, 30px);
	border-block-start: 1px solid var(--border);
	color: var(--text);
	font-family: var(--display);
	font-size: clamp(20px, 2.2vw, 26px);
	font-weight: 600;
	line-height: var(--wp--custom--leading--snug);
	letter-spacing: var(--wp--custom--tracking--tight);
}

/* The first one opens the document; it needs no rule above it. */
.policy-body > .policy-h2:first-child {
	margin-block-start: 0;
	padding-block-start: 0;
	border-block-start: 0;
}

.policy-h3 {
	margin-block: clamp(30px, 3.4vw, 40px) 14px;
	color: var(--text);
	font-family: var(--display);
	font-size: var(--wp--preset--font-size--lg);
	font-weight: 600;
	line-height: var(--wp--custom--leading--snug);
}

/*
 * The source's lead-in bullets. Seventeen of the eighteen hold a single item,
 * each one introducing the paragraph beneath it, so they are set as a line
 * that leans on the text rather than as a list that happens to have one entry.
 */
.policy-list {
	margin-block: clamp(22px, 2.6vw, 30px) 10px;
	padding-inline-start: 22px;
	color: var(--text);
	font-size: var(--wp--preset--font-size--md);
	font-weight: 500;
	line-height: var(--wp--custom--leading--snug);
}

.policy-list li {
	margin-block-end: 8px;
}

.policy-list li::marker {
	color: var(--primary);
}


/* ---------------------------------------------------- AI information page */

/**
 * The page Modularis publishes for AI assistants to quote. It shares the
 * longform shell above with the privacy notice - same measure, same prose -
 * and adds the shapes this one needs: a fact sheet, three kinds of list, and
 * eight customer results each with a quotation.
 *
 * Styled for reading even though its first audience is machines. A person
 * checking what the assistants are being told is exactly the person most
 * likely to open it, and a wall of undifferentiated text would hide the
 * structure that makes the page worth publishing.
 */
.aiinfo-subtitle {
	margin-block: 10px 0;
	color: var(--muted);
	font-family: var(--display);
	font-size: var(--wp--preset--font-size--lg);
	font-weight: 500;
	line-height: var(--wp--custom--leading--snug);
	text-align: center;
}

/*
 * The note saying who the page is for. Set apart because it is the one
 * paragraph addressed to the reader rather than about the company.
 */
.aiinfo-intro {
	margin-block-start: clamp(20px, 2.4vw, 28px);
	padding-inline-start: 16px;
	border-inline-start: 2px solid var(--primary);
	color: var(--muted);
	font-size: var(--wp--preset--font-size--md);
	line-height: var(--wp--custom--leading--lead);
}

/* The sections: Basic Information, Background, Core Services and the rest. */
.aiinfo-h3 {
	margin-block: clamp(46px, 5.2vw, 68px) 20px;
	padding-block-start: clamp(22px, 2.6vw, 30px);
	border-block-start: 1px solid var(--border);
	color: var(--text);
	font-family: var(--display);
	font-size: clamp(21px, 2.3vw, 28px);
	font-weight: 600;
	line-height: var(--wp--custom--leading--snug);
	letter-spacing: var(--wp--custom--tracking--tight);
}

.aiinfo-body > .aiinfo-h3:first-child {
	margin-block-start: 0;
	padding-block-start: 0;
	border-block-start: 0;
}

/* A customer name, a platform name, or one differentiator. */
.aiinfo-h4 {
	margin-block: clamp(30px, 3.4vw, 40px) 12px;
	color: var(--text);
	font-family: var(--display);
	font-size: var(--wp--preset--font-size--lg);
	font-weight: 600;
	line-height: var(--wp--custom--leading--snug);
}

/*
 * The fact sheet: name, type of business, founders, headquarters. Every line
 * is "label: value", so the label gets the column and the value gets the rest.
 * This is the part of the page most likely to be read as data, and a grid
 * makes the pairing explicit instead of leaving it to a colon.
 */
.fact-list {
	margin-block: 0;
	padding-inline-start: 0;
	list-style: none;
}

.fact-list li {
	margin-block-end: 0;
	border-block-end: 1px solid var(--border-soft);
	padding-block: 11px;
	color: var(--muted);
	font-size: var(--wp--preset--font-size--sm);
	line-height: var(--wp--custom--leading--body);
}

.fact-list li strong {
	display: block;
	color: var(--text);
	font-family: var(--mono);
	font-size: var(--wp--preset--font-size--xs);
	font-weight: 400;
	letter-spacing: var(--wp--custom--tracking--caps);
	text-transform: uppercase;
}

@media (min-width: 620px) {
	.fact-list li {
		display: grid;
		grid-template-columns: minmax(0, 190px) minmax(0, 1fr);
		gap: 18px;
		align-items: baseline;
	}
}

/*
 * The five services and the six platform benefits. Both are a name followed
 * by its explanation in one run of text, so the name is lifted onto its own
 * line - the difference between a list you can scan and a list you have to
 * read twice to find the boundary in.
 */
.service-list,
.benefit-list {
	margin-block: 0;
	padding-inline-start: 0;
	list-style: none;
}

.service-list li,
.benefit-list li {
	margin-block-end: clamp(20px, 2.4vw, 28px);
	color: var(--muted);
	font-size: var(--wp--preset--font-size--sm);
	line-height: var(--wp--custom--leading--body);
}

.service-list li > a,
.service-list li > a > strong,
.benefit-list li > strong {
	display: block;
	margin-block-end: 5px;
	color: var(--text);
	font-family: var(--display);
	font-size: var(--wp--preset--font-size--md);
	font-weight: 600;
	letter-spacing: var(--wp--custom--tracking--tight);
	overflow-wrap: normal;
}

.service-list li > a {
	text-decoration: none;
}

.service-list li > a:hover > strong,
.service-list li > a:focus-visible > strong {
	color: var(--primary);
}

/* The audience, the thought-leadership channels, the assistant guidelines. */
.reason-list {
	margin-block: 0;
	padding-inline-start: 22px;
	color: var(--muted);
	font-size: var(--wp--preset--font-size--sm);
	line-height: var(--wp--custom--leading--body);
}

.reason-list li {
	margin-block-end: 12px;
}

.reason-list li::marker {
	color: var(--primary);
}

/*
 * A customer quotation. The source sets these as plain paragraphs; here they
 * are real blockquotes, so the mark is drawn rather than implied and the
 * attribution is attached to the thing it attributes.
 */
.aiinfo-quote {
	margin-block: clamp(18px, 2.2vw, 24px) 0;
	padding-inline-start: clamp(18px, 2.4vw, 26px);
	border-inline-start: 2px solid var(--border);
}

.aiinfo-quote p {
	margin-block: 0;
	color: var(--text);
	font-size: var(--wp--preset--font-size--sm);
	font-style: italic;
	line-height: var(--wp--custom--leading--lead);
}

.aiinfo-quote cite {
	display: block;
	margin-block-start: 10px;
	color: var(--faint);
	font-family: var(--mono);
	font-size: var(--wp--preset--font-size--xs);
	font-style: normal;
}

/* The two closing lines: when this was written, and where to go next. */
.aiinfo-meta {
	margin-block-start: clamp(14px, 1.8vw, 20px);
	color: var(--faint);
	font-family: var(--mono);
	font-size: var(--wp--preset--font-size--xs);
	letter-spacing: var(--wp--custom--tracking--caps);
	text-transform: uppercase;
}

.aiinfo-body .aiinfo-meta + .aiinfo-meta {
	margin-block-start: 4px;
}

/**
 * The platform hero's artwork: three stacked hexagonal platforms, animated.
 *
 * assets/img/platform-hexstack.svg, supplied artwork rather than a generated
 * asset - the same footing as bedrock.png further up, and the reason the
 * colour audit skips assets/img. Its orange is the palette's primary written
 * out as a literal, so if the palette moves this file has to move by hand.
 *
 * Referenced by <img>, never inlined. The file carries its own stylesheet,
 * which defines .core, .detail, .ring, .shadow and :root, and whose
 * reduced-motion rule is `* { animation: none !important }`. Inline, all of
 * that would apply to the whole page. Through an <img> the SVG is its own
 * document and none of it escapes, while CSS animation still runs - only
 * scripting is switched off in an image-referenced SVG, and this one has none.
 *
 * It replaced a 1024x1024 PNG that said the same thing without moving.
 */
.platform-hero-art {
	margin: 0;
}

.platform-hero-art img {
	display: block;
	inline-size: 100%;
	max-inline-size: 100%;
	block-size: auto;
}

/**
 * The iceberg in "Generate value, not slop": a small lit peak above the
 * waterline and a far larger mass below it, which is the section's whole
 * argument drawn rather than written.
 *
 * assets/img/iceberg.svg, supplied artwork on the same footing as
 * platform-hexstack.svg above. It animates with SMIL rather than CSS, so
 * inlining it would not leak styles the way that one would - but it is
 * referenced by <img> all the same, which keeps the two consistent, keeps
 * 15KB of drawing out of post_content, and lets the browser cache it.
 *
 * It arrived painted on a night-blue sky and sea, which read as a framed
 * picture dropped onto the page rather than as part of it. The opaque sky is
 * gone, so the page background is the sky; the water and the ice keep their
 * gradients, rewritten in the theme's own greys - surface fading to base -
 * so the waterline still reads without a colour that belongs to no other
 * part of the site. The only hues left in the file are the orange and one
 * white flash on the peak.
 *
 * The side edges are handled inside the file too, by a mask rather than by
 * anything here: a horizontal ramp fades the whole scene out over the outer
 * 16% on each side, so the water, the drifting wave lines and the grid all
 * dissolve into the page instead of stopping at a straight vertical seam.
 * The iceberg spans x=145..604 of 750 and clears both fade zones by about
 * 25px, so the subject itself is never touched - worth re-checking if the
 * artwork is ever redrawn wider.
 *
 * It replaced a 963x1024 PNG of the same scene.
 */
.iceberg-art {
	margin: 0;
}

.iceberg-art img {
	display: block;
	inline-size: 100%;
	max-inline-size: 100%;
	block-size: auto;
}

/*
 * The offer injected into every long enough article, before its first
 * heading. It wears .post-callout and .post-guide so it matches the closing
 * LinkedIn call-out and the modernization guide exactly - this rule only
 * separates it from the paragraph above and the heading below, which is
 * further than a panel between two blocks of prose normally needs.
 */
.article-offer {
	margin-block: clamp(40px, 5vw, 62px);
}

.post-article .article-offer + h2,
.post-article .post-shortcode + h2 {
	margin-block-start: 0;
}

/*
 * The injected offer's cover is line art on a transparent ground, not a
 * photograph of a cover, so it wants none of the drop shadow or the tilt the
 * downloadable pages give theirs - and it is landscape where those are
 * portrait, so it is held back from filling its column at full width.
 */
.article-offer-art img {
	display: block;
	inline-size: 100%;
	max-inline-size: 100%;
	block-size: auto;
	margin-inline: auto;
}

/*
 * Centre the cover against the form beside it.
 *
 * NOT done with align-items on the row, which is the obvious way and does
 * nothing: core ships `.wp-block-columns { align-items: normal !important }`,
 * and normal computes to stretch, so the columns are already equal height and
 * the picture is simply sitting at the top of its own full-height column.
 * Even core's own .are-vertically-aligned-center loses to that !important.
 *
 * So the column becomes the flex container instead and centres its one child.
 * Selected by what it holds rather than by position, because the cover is the
 * first column today and that is not a promise.
 *
 * On a narrow screen core stacks the columns and each one is only as tall as
 * its contents, which makes this a no-op rather than a thing to undo.
 */
.post-guide-row > .wp-block-column:has(.post-guide-cover) {
	display: flex;
	flex-direction: column;
	justify-content: center;
}
