/*
 * Color More Lines — WordPress bridge layer.
 *
 * Two jobs, and nothing else:
 *
 *   1. Define the responsive custom properties that theme.json references.
 *      These MUST be declared per breakpoint. Below 1024px the root font size
 *      is the browser default (1rem = 16px); at and above 1024px root.css sets
 *      `html { font-size: 0.5208333333vw }` so 1rem = 10px at the 1920px design
 *      width. A single rem value would therefore mean two very different sizes
 *      on either side of that breakpoint — hence the explicit media query.
 *
 *   2. Map core Gutenberg blocks onto the delivered design system, so pages the
 *      client builds from core blocks inherit the same look as the ACF blocks.
 *
 * Load order matters: this file must be enqueued AFTER style.css and after the
 * core block library styles.
 */

/* ------------------------------------------------------------------------- *
 * 1. Responsive tokens consumed by theme.json
 * ------------------------------------------------------------------------- */

:root {
	/* Layout widths — full-bleed on mobile, matching .container above. */
	--cml-content: 100%;
	--cml-wide: 100%;

	/* Spacing scale. Mobile values are fixed px, by design. */
	--cml-space-1: 8px;
	--cml-space-2: 16px;
	--cml-space-3: 24px;
	--cml-space-4: 32px;
	--cml-space-5: 48px;
	--cml-space-6: 60px;
	--cml-space-7: 80px;

	/*
	 * Type scale tokens.
	 *
	 * style.css writes these sizes as literals on the .title-* / .text-*
	 * classes — there were no custom properties for them. These tokens mirror
	 * those literals exactly so theme.json can expose the same scale to the
	 * editor without duplicating values, and so the preset classes WordPress
	 * generates can be aliased onto the design classes further down.
	 *
	 * If a size changes in style.css, change it here in both breakpoints.
	 */
	--fs-title-xl: 48px;
	--fs-title-lg: 36px;
	--fs-title-l: 36px;
	--fs-title-m: 40px;
	--fs-title-sm: 32px;
	--fs-text-xl: 21px;
	--fs-text-lg: 20px;
	--fs-text-m: 18px;
	--fs-body: var(--base-font-size);
}

@media (min-width: 1024px) {
	:root {
		/*
		 * contentSize is a prose measure — 1200px at the 1920px design width.
		 * wideSize matches .container--md (168rem), the widest container the
		 * design actually uses. Plain .container is max-width:none above 1024px
		 * and relies on --container-pad, which theme.json applies as root
		 * padding, so alignfull blocks land in the same gutter as designed
		 * sections.
		 */
		--cml-content: 120rem;
		--cml-wide: 168rem;

		--cml-space-1: 0.8rem;
		--cml-space-2: 1.6rem;
		--cml-space-3: 2.4rem;
		--cml-space-4: 3.2rem;
		--cml-space-5: 4.8rem;
		/*
		 * 6 and 7 are the section rhythm, and style.css has exactly two values
		 * for it above 1024px: `.section` is 6rem and `.section--lg` is 10rem
		 * (style.css:5648 and :5674). These previously read 10rem and 14rem —
		 * 14rem is not a section padding anywhere in the design — which made
		 * every palette band 40px too tall per side at 1920.
		 */
		--cml-space-6: 6rem;
		--cml-space-7: 10rem;

		--fs-title-xl: 18.4rem;
		--fs-title-lg: 15rem;
		--fs-title-l: 14rem;
		--fs-title-m: 10rem;
		--fs-title-sm: 8rem;
		--fs-text-xl: 5rem;
		--fs-text-lg: 3.6rem;
		--fs-text-m: 3.2rem;
	}
}

/* ------------------------------------------------------------------------- *
 * 1b. Preset class aliases
 * ------------------------------------------------------------------------- *
 * theme.json generates .has-{slug}-font-size for each preset. Alias each onto
 * the design's own class so markup authored by hand (.title-l) and markup
 * authored in the editor (.has-title-l-font-size) resolve identically.
 *
 * NOTE: .title-l and .title-lg are different sizes and always have been. That
 * naming is a trap inherited from style.css. Do not "fix" it — style.css is
 * vendor-supplied and renaming would fork it.
 */

.has-title-xl-font-size { font-size: var(--fs-title-xl); }
.has-title-lg-font-size { font-size: var(--fs-title-lg); }
.has-title-l-font-size  { font-size: var(--fs-title-l); }
.has-title-m-font-size  { font-size: var(--fs-title-m); }
.has-title-sm-font-size { font-size: var(--fs-title-sm); }
.has-text-xl-font-size  { font-size: var(--fs-text-xl); }
.has-text-lg-font-size  { font-size: var(--fs-text-lg); }
.has-text-m-font-size   { font-size: var(--fs-text-m); }
.has-body-font-size     { font-size: var(--fs-body); }

/* Background presets alias onto the design's section treatments. */
.has-primary-background-color { background-color: var(--brand-color); }
.has-charcoal-background-color,
.has-near-black-background-color { color: #fff; --heading-color: #fff; }

/* --- Dark CARD surfaces need --heading-color too ------------------------- *
 *
 * theme.json emits an unscoped `h1,…,h6 { color: var(--heading-color) }`. The
 * comps have no such rule, so there a heading with no component class simply
 * INHERITS its surface colour. Here it stops inheriting and takes the token.
 *
 * style.css already set that token up — `.bg-dark`, `.bg-gray`, `.section-hero`
 * and `.footer` each declare `--heading-color: #fff` — but it declares it on
 * SECTIONS only, and never consumes it anywhere. The consumer arrived with
 * theme.json, so every dark surface the vendor did not cover now paints its
 * headings `#333`.
 *
 * These four are `color: #fff; background-color: #333` cards whose titles set no
 * colour of their own, so each rendered charcoal-on-charcoal — invisible:
 *
 *   .blog-card        → .blog-card__title      (cml/post-feed)
 *   .case-card        → .case-card__title      (cml/case-study-slider)
 *   .cards__item      → .cards__title          (cml/icon-cards)
 *   .accordion-details                         (cml/accordion)
 *
 * `.accordion-details__title`, `.features__title` and `.icon-list__title` set
 * `color: #fff` themselves and were never affected; they are covered here anyway
 * so a second heading added inside one behaves like the first.
 *
 * Setting the token rather than `color` on the headings keeps the design's own
 * mechanism intact: anything inside that wants a different heading colour still
 * only has to redeclare the variable. */
.blog-card,
.case-card,
.cards__item,
.accordion-details {
	--heading-color: #fff;
}

/* ------------------------------------------------------------------------- *
 * 2. Core block mapping
 * ------------------------------------------------------------------------- */

/* The delivered markup wraps everything in .wrapper — a full-height flex
   column that keeps the footer at the bottom on short pages. Block themes
   emit .wp-site-blocks in that position, so it inherits the same job. */
.wp-site-blocks {
	display: flex;
	flex-direction: column;
	min-height: 100vh;
	width: 100%;
	position: relative;
}

.wp-site-blocks > .main {
	flex: 1 0 auto;
}

/* --- Sections butt together; core's blockGap must not separate them ------ *
 *
 * The post-content wrapper is `is-layout-constrained`, and core prints:
 *
 *     :root :where(.is-layout-constrained) > * { margin-block-start: var(--wp--style--block-gap) }
 *
 * `--wp--style--block-gap` is `--cml-space-3` here, so every section after the
 * first was pushed 24px (2.4rem) down the page — nine gaps on the home page,
 * and a 24px stripe of page background between every pair of coloured bands
 * where the comps have the two touching. The design spaces sections with their
 * OWN padding (`.section` 60px/6rem, `.section--lg` 10rem, `.section-hero` and
 * friends their own); there is no gap between them to add.
 *
 * Scoped to the theme's own section blocks, every one of which emits
 * `data-block-name` by house rule, plus full-bleed core blocks — a band is a
 * band whoever rendered it. A non-full core block in the content root keeps the
 * gap, which is right: that is prose, and prose wants rhythm.
 *
 * (0,2,0) beats core's (0,1,0) outright, so this does not depend on load order —
 * core prints in the head and the bridge in the footer, but the same rule has to
 * hold inside the editor canvas where that order is not guaranteed.
 *
 * `:first-child`/`:last-child` were already zeroed by core; this is the nine in
 * between. */
.wp-block-post-content > [data-block-name],
.wp-block-post-content > .alignfull,
.entry-content > [data-block-name],
.entry-content > .alignfull {
	margin-block-start: 0;
	margin-block-end: 0;
}

/*
 * Full-bleed breakout is handled by core, not here.
 *
 * theme.json sets useRootPaddingAwareAlignments: true and puts
 * var(--container-pad) in styles.spacing.padding, so core gives constrained
 * containers .has-global-padding and lets .alignfull children escape it with
 * negative margins. Do not add competing padding rules for .alignfull — they
 * fight core's margins and produce a double gutter.
 *
 * ACF section blocks declare "align": ["full"] and set alignfull, which is what
 * puts them edge to edge while prose stays at contentSize.
 */

/* --- Buttons: mirror .btn / .btn--primary ------------------------------- */

.wp-block-button__link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	text-align: center;
	font-family: "Sora", "Arial", "Helvetica Neue", Helvetica, sans-serif;
	font-size: 15px;
	line-height: 1;
	font-weight: 800;
	padding: 8px 30px;
	border: none;
	border-radius: 50px;
	text-decoration: none;
	cursor: pointer;
	background-color: #6fcf97;
	color: #fff;
	transition: color 0.35s ease, background-color 0.35s ease, border-color 0.35s ease;
}

@media (min-width: 1024px) {
	.wp-block-button__link {
		font-size: max(15px, 1.5rem);
	}
}

.wp-block-button__link:hover,
.wp-block-button__link:focus {
	background-color: #50ac76;
	color: #fff;
}

/* Outline variant follows the design's white button. */
.wp-block-button.is-style-outline > .wp-block-button__link {
	background-color: #fff;
	color: #246840;
	border: 1px solid currentColor;
}

/* On the dark section backgrounds the design flips button text to charcoal. */
.bg-dark .wp-block-button__link,
.bg-gray .wp-block-button__link,
.has-charcoal-background-color .wp-block-button__link,
.has-near-black-background-color .wp-block-button__link {
	color: #333;
}

/* --- Registered block styles ------------------------------------------- *
 * Each maps a .is-style-* onto the delivered design class. Registered in
 * inc/blocks.php; if you add one there, add its rule here or it does nothing.
 */

/* .btn--white */
.wp-block-button.is-style-cml-white > .wp-block-button__link {
	background-color: #fff;
	color: #246840;
}

.wp-block-button.is-style-cml-white > .wp-block-button__link:hover,
.wp-block-button.is-style-cml-white > .wp-block-button__link:focus {
	background-color: #50ac76;
	color: #fff;
}

/* .btn--border */
.wp-block-button.is-style-cml-border > .wp-block-button__link {
	background-color: transparent;
	border: 1px solid #333;
	color: #333;
}

.wp-block-button.is-style-cml-border > .wp-block-button__link:hover,
.wp-block-button.is-style-cml-border > .wp-block-button__link:focus {
	background-color: #333;
	color: #fff;
}

/*
 * .btn--arrow — in the delivered markup this class only supplies the gap; the
 * arrow itself is an inline <svg class="btn__icon"> the author writes into the
 * anchor. A core button cannot emit that, so the style has to draw it.
 *
 * Drawn with mask-image rather than background-image so it inherits
 * currentColor, which matters: .btn--primary text is #fff normally but #333 on
 * the dark bands, and the arrow has to follow. Same path and 14x11 box as
 * .btn__icon, placed before the label to match .split-card, .tile-card and the
 * footer CTA.
 */
.wp-block-button.is-style-cml-arrow > .wp-block-button__link {
	gap: 6px;
}

.wp-block-button.is-style-cml-arrow > .wp-block-button__link::before {
	content: "";
	flex-shrink: 0;
	width: 14px;
	height: 11px;
	background-color: currentColor;
	-webkit-mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 11"><path d="M0 7V4H9.5L6.5 0H9.5L14 5.5L9.5 11H6.5L9.5 7H0Z"/></svg>');
	mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 11"><path d="M0 7V4H9.5L6.5 0H9.5L14 5.5L9.5 11H6.5L9.5 7H0Z"/></svg>');
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
}

/* .btn--lg exists only above 1024px in the source; match that exactly. */
@media (min-width: 1024px) {
	.wp-block-button.is-style-cml-arrow > .wp-block-button__link {
		gap: max(6px, 0.6rem);
	}

	/* Matches .btn__icon at the desktop breakpoint. */
	.wp-block-button.is-style-cml-arrow > .wp-block-button__link::before {
		width: max(14px, 1.4rem);
		height: max(11px, 1.1rem);
	}

	.wp-block-button.is-style-cml-lg > .wp-block-button__link {
		font-size: 3.5rem;
		padding: 1.6rem 3.5rem;
		gap: 1.2rem;
	}
}

/*
 * .divider in style.css is a section-top device, not a general separator:
 *
 *     .divider { margin-top: calc(var(--section-py) * -1); }
 *
 * --section-py is defined only on .section and its siblings, so that negative
 * margin exists to cancel a section's own top padding and sit the rule flush
 * against the section top. It appears exactly once in the comps, inside
 * `<section class="section section--lg bg-gray">`.
 *
 * Copying the negative margin into a block style was wrong: on an ad-hoc page
 * there is no --section-py to cancel, so the rule pulled itself up into
 * whatever preceded it. The block style is now a plain hairline with even
 * spacing, which is what "Section divider" should do for a client.
 *
 * The ACF section blocks emit the real .divider class in their own markup,
 * inside a real section, so they keep the original behaviour untouched.
 */
.wp-block-separator.is-style-cml-divider {
	margin-top: var(--cml-space-5);
	margin-bottom: var(--cml-space-5);
	border: 0;
	border-top: 1px solid currentColor;
	opacity: 0.18;
}

/* .overline — a pill badge, not a text style. */
.wp-block-heading.is-style-cml-overline {
	display: block;
	font-size: 15px;
	line-height: 1.27;
	padding: 6px 20px;
	font-weight: 800;
	color: #fff;
	min-width: 153px;
	width: fit-content;
	text-align: center;
	background-color: #333;
	border-radius: 80px;
	/*
	 * The design uses this badge both ways: .split-card__content,
	 * .tile-card__content, .lead and .form-tile__intro are flex columns with
	 * align-items: flex-start, so it sits left; .section-head sets
	 * align-items: center with text-align: center, so it sits centred.
	 *
	 * Left is the common case and the default here. Constrained layout gives
	 * every child auto margins on both sides, which would centre a fit-content
	 * box, so the inline start margin is pinned back to 0 — and the block's own
	 * alignment control overrides it below, giving the client both behaviours
	 * without a second block style.
	 */
	margin-inline: 0 auto;
	margin-bottom: 16px;
}

.wp-block-heading.is-style-cml-overline.has-text-align-center {
	margin-inline: auto;
}

.wp-block-heading.is-style-cml-overline.has-text-align-right {
	margin-inline: auto 0;
}

/*
 * The badge's box metrics scale above 1024px; its type does not.
 *
 * style.css:5540 sets padding 0.6rem 2rem, border-radius 8rem and
 * margin-bottom 1.6rem — plain rem, so they track the viewport — while
 * font-size is max(15px, 1.5rem), floored so the label stays legible. The px
 * values above are the mobile set and were held at every width, which happens
 * to be exact at 1920 (0.6rem IS 6px there) and 1.875x too large at 1024.
 *
 * min-width is deliberately not overridden: style.css does not scale it
 * either, so 153px is correct at every width.
 */
@media (min-width: 1024px) {
	.wp-block-heading.is-style-cml-overline {
		font-size: max(15px, 1.5rem);
		padding: 0.6rem 2rem;
		border-radius: 8rem;
		margin-bottom: 1.6rem;
	}
}

.bg-gray .wp-block-heading.is-style-cml-overline,
.has-charcoal-background-color .wp-block-heading.is-style-cml-overline {
	background-color: #fff;
	color: #333;
}

/* .cml-section — the design's vertical section rhythm on a plain group. */
.wp-block-group.is-style-cml-section {
	padding-top: var(--cml-space-6);
	padding-bottom: var(--cml-space-6);
}

/* ACF wraps every InnerBlocks region in <div class="acf-innerblocks-container">
 * and offers no filter to turn it off. That div is invisible in normal flow, but
 * `.service-card__content` is `display: flex; align-items: flex-start`, which
 * makes it a shrink-to-fit flex ITEM — so the copy inside stops at max-content
 * instead of filling the column, and wraps in places the comps do not.
 *
 * `display: contents` promotes its children to the real parent, which is the
 * structure every design class here was written against. It also removes the
 * same wrapper from cml/section-intro's .lead__text, where the comps likewise
 * have the paragraph as a direct child.
 *
 * NOT in the editor: there the container is InnerBlocks' drop target, and
 * removing its box breaks block insertion and drag-and-drop. */
.acf-innerblocks-container {
	display: contents;
}

.editor-styles-wrapper .acf-innerblocks-container {
	display: block;
}

/* --- Team headshots need the ratio the design forgot to pin ------------- *
 *
 * style.css pins a ratio on every OTHER card that shows an editor-supplied
 * image — `.blog-card__visual img` is `aspect-ratio: 12/8`, `.case-card__visual
 * img` is `16/9`, both with `object-fit: cover`. `.team-card__img img` is the
 * one it left at the image's natural ratio.
 *
 * That works in the comps because all three headshots the design ships are
 * 1000×1408 — exactly 5/7, pre-cropped to match. It stops working the moment
 * anyone uploads a photo shaped differently: the taller image makes its card's
 * image taller, and the position, name and bio under it all sit lower than the
 * rest of the row. A fourth member with a 1486×2382 photo showed it immediately.
 *
 * 5/7 is the design's own headshot ratio, so the three supplied photos are
 * untouched by this and only an odd one gets cropped. `object-position: 50% 0`
 * crops from the bottom, which is what keeps a head in frame — and it is the
 * same value `.blog-card__visual img` uses.
 *
 * `.team-card__img` is already `overflow: hidden` with a radius, so the crop
 * clips cleanly. */
.team-card__img img {
	aspect-ratio: 5 / 7;
	object-fit: cover;
	object-position: 50% 0;
}

/* .cml-callout — style.css's .callout, reachable from a core group.
 *
 * Two of the six service cards in the comps have a .callout as their whole
 * content column, and it appears nowhere else in the nine pages. That is a core
 * group plus a block style, not a block: everything it does is padding, a rule
 * and a type size. Same test that retired cml/cta-button and cml/divider.
 *
 * The properties are restated rather than aliased to `.callout`, because a block
 * style adds `is-style-cml-callout` and nothing else — there is no selector the
 * design's own class arrives on. */
.wp-block-group.is-style-cml-callout {
	padding: 24px 0 24px 24px;
	border-left: 2px solid var(--brand-color);
}

@media (min-width: 1024px) {
	.wp-block-group.is-style-cml-callout {
		padding: 4rem 0 4rem 7.7rem;
		border-left-width: 0.4rem;
		font-size: 3.6rem;
		line-height: 1.3;
	}
}

/* --- SlimSelect tokens -------------------------------------------------- *
 * style.css vendors SlimSelect's stylesheet verbatim and never themes it —
 * the --ss-* tokens sit on :root at their library defaults (40px tall,
 * #dcdee2 border, #8d8d8d placeholder). The design's own text inputs are 55px
 * with a #c3c3c3 border and #6b6b6b placeholder, so a SlimSelect dropdown does
 * not match the field above it anywhere on the site, including in the
 * delivered comps.
 *
 * Retokenising here rather than in the Formidable bridge means the design's
 * own selects are fixed too, not just Formidable's.
 */

:root {
	--ss-main-height: 55px;
	--ss-font-color: #6b6b6b;
	--ss-placeholder-color: #6b6b6b;
	--ss-border-color: #c3c3c3;
	--ss-bg-color: transparent;
	--ss-border-radius: 9px;
	--ss-primary-color: #6fcf97;
	--ss-focus-color: #6fcf97;
	--ss-highlight-color: rgba(111, 207, 151, 0.28);
	--ss-success-color: #50ac76;
	--ss-error-color: #b3261e;
}

.ss-main {
	font-size: 16px;
	padding: 0 20px;
}

/*
 * The open dropdown panel needs two things the vendored CSS does not give it.
 *
 * Background: --ss-bg-color is transparent above, because the design's fields
 * are transparent. The panel shares that token, so without an explicit colour
 * it opens see-through over whatever is underneath.
 *
 * Stacking: .ss-content is position: absolute with no z-index at all, while
 * the design's sections carry z-index: 10. An open dropdown therefore renders
 * behind the section below it.
 */
.ss-content {
	z-index: 100;
	background-color: #fff;
}

.ss-content .ss-list .ss-option:hover,
.ss-content .ss-list .ss-option.ss-highlighted {
	background-color: var(--ss-highlight-color);
	color: #333;
}

/*
 * Match an input's placeholder exactly.
 *
 * Font size was already equal; the visible difference was inset. SlimSelect
 * gives .ss-placeholder its own `padding: var(--ss-spacing-s) var(--ss-spacing-m)`
 * (5px 7px) on top of the control's padding, and `line-height: 1em` against the
 * body line-height an input uses. Zeroing the inner padding lets the control's
 * own `0 20px` govern, which is what a text input does.
 */
.ss-main .ss-values .ss-placeholder,
.ss-main .ss-values .ss-single {
	font-size: 16px;
	line-height: inherit;
	padding: 0;
	margin: 0;
	color: var(--ss-font-color);
}

.ss-main .ss-values .ss-placeholder {
	color: var(--ss-placeholder-color);
}

@media (min-width: 1024px) {
	:root {
		--ss-main-height: max(55px, 6.5rem);
		--ss-border-radius: 0.9rem;
	}

	.ss-main {
		font-size: max(16px, 2.2rem);
		padding: 0 2rem;
	}

	.ss-main .ss-values .ss-placeholder,
	.ss-main .ss-values .ss-single {
		font-size: max(16px, 2.2rem);
	}
}

/* --- Vertical rhythm in prose ------------------------------------------- *
 * The design and core space content in opposite directions, and core wins.
 *
 * style.css uses margin-bottom with margin-top: 0, tuned per heading level:
 * h1 24px, h2 32px, h3 16px, h4-h6 8px, p 24px (3.6/3.2/0.8/0.8/3.2rem on
 * desktop). Core's layout emits
 *
 *     :root :where(.is-layout-constrained) > * {
 *       margin-block-start: var(--wp--style--global--block-gap);
 *       margin-block-end: 0;
 *     }
 *
 * which zeroes every bottom margin and replaces the whole scale with one
 * uniform gap. A Kitchen Sink page therefore had even spacing everywhere,
 * where the design tightens under sub-headings and opens up under h1/h2.
 *
 * Restored here for headings and paragraphs inside post content, in the
 * design's own direction. Other blocks keep core's blockGap, which matches
 * the design's 24px/2.4rem list and component rhythm.
 *
 * Specificity is deliberately 0,1,0 — the SAME as core's layout rule, not
 * higher. The bridge prints in the footer (see inc/assets.php), so equal
 * specificity plus later position beats core. Going higher would also beat the
 * design's own component overrides, e.g. `.split-card__content h2
 * { margin-bottom: 20px }` at 0,1,1, and those must keep winning once ACF
 * section blocks render inside post content. The intended precedence is:
 *
 *     core blockGap (0,1,0, head) < prose rhythm (0,1,0, footer)
 *                                 < design components (0,1,1)
 */

/*
 * `:where(:not([class]), .wp-block-heading)` — the guard that keeps this rhythm
 * off designed components. It was missing, and the omission was live.
 *
 * The precedence note above assumed design components sit at 0,1,1, like
 * `.split-card__content h2`. Many sit at 0,1,0 — `.blog-card__title`,
 * `.section-head__title`, `.section-results__title`, `.icon-list__title`,
 * `.service-card__title`, `.features__title`. Those tie with this rule, and the
 * bridge prints in the FOOTER while style.css prints in the head, so the tie
 * went to the bridge and every one of them lost its designed margin. The blog
 * card was the visible case: 0.8rem under the title instead of 1.8rem.
 *
 * The guard reads as "editor prose": no class at all (a raw <h3> from a WYSIWYG
 * field) or core's own heading class. A component class means the design has an
 * opinion about this heading, and the design wins. Specificity is unchanged —
 * :where() contributes nothing — so the intended order still holds:
 *
 *     core blockGap (0,1,0, head) < prose rhythm (0,1,0, footer)
 *                                 < design components (0,1,0 and 0,1,1)
 */

.entry-content :where(h1, h2, h3, h4, h5, h6):where(:not([class]), .wp-block-heading),
.wp-block-post-content :where(h1, h2, h3, h4, h5, h6):where(:not([class]), .wp-block-heading),
.entry-content :where(p),
.wp-block-post-content :where(p) {
	margin-block-start: 0;
}

.entry-content :where(h1):where(:not([class]), .wp-block-heading),
.wp-block-post-content :where(h1):where(:not([class]), .wp-block-heading) { margin-block-end: 24px; }

.entry-content :where(h2):where(:not([class]), .wp-block-heading),
.wp-block-post-content :where(h2):where(:not([class]), .wp-block-heading) { margin-block-end: 32px; }

.entry-content :where(h3):where(:not([class]), .wp-block-heading),
.wp-block-post-content :where(h3):where(:not([class]), .wp-block-heading) { margin-block-end: 16px; }

.entry-content :where(h4, h5, h6):where(:not([class]), .wp-block-heading),
.wp-block-post-content :where(h4, h5, h6):where(:not([class]), .wp-block-heading) { margin-block-end: 8px; }

/* p needs no guard: 24px / 3.2rem is exactly what style.css already gives a bare
   <p>, so this only restates it for content core would otherwise leave to
   blockGap. Nothing in the design overrides a paragraph margin by class. */
.entry-content :where(p),
.wp-block-post-content :where(p) { margin-block-end: 24px; }

@media (min-width: 1024px) {
	.entry-content :where(h1):where(:not([class]), .wp-block-heading),
	.wp-block-post-content :where(h1):where(:not([class]), .wp-block-heading) { margin-block-end: 3.6rem; }

	.entry-content :where(h2):where(:not([class]), .wp-block-heading),
	.wp-block-post-content :where(h2):where(:not([class]), .wp-block-heading) { margin-block-end: 3.2rem; }

	.entry-content :where(h3, h4, h5, h6):where(:not([class]), .wp-block-heading),
	.wp-block-post-content :where(h3, h4, h5, h6):where(:not([class]), .wp-block-heading) { margin-block-end: 0.8rem; }

	.entry-content :where(p),
	.wp-block-post-content :where(p) { margin-block-end: 3.2rem; }
}

/* --- Prose links -------------------------------------------------------- *
 * style.css sets `a { color: inherit; text-decoration: none }` globally,
 * because every link in the comps gets its appearance from a component class
 * (.menu__link, .btn, .row-list__action…). root.css defines --base-link-color
 * but nothing ever consumes it.
 *
 * That leaves an editorial link inside post content visually identical to the
 * text around it — colour alone is not even available as a cue, let alone a
 * sufficient one. That is a WCAG 1.4.1 failure, so the token is put to work
 * here, scoped to content only. Buttons and any block that styles its own
 * links are excluded.
 *
 * This lives in the bridge rather than theme.json because theme.json's element
 * styles are emitted in global-styles-inline-css, which loads BEFORE
 * style.css — so a link colour set there loses to `a { color: inherit }`.
 */

/*
 * Scoped two ways, and BOTH are load-bearing.
 *
 * 1. Text-flow containers, not "any link inside .entry-content" — the intent is
 *    editorial prose, and naming the containers says so.
 * 2. `:not([class])` — the link must carry no class at all.
 *
 * Scoping by container alone was not enough. `.row-list__item` is an <li>, so
 * the case-study arrow link `.row-list__action` matched, and at (0,1,1) it beat
 * `.row-list__action`'s own (0,1,0): the arrow and its ring took the editorial
 * colour instead of white, and gained an underline. Every designed component in
 * this markup is class-driven — that is the premise style.css's global
 * `a { color: inherit }` rests on — so "has no class" is exactly "was typed by
 * an editor", and it cannot drift as blocks are added.
 *
 * :where() keeps the guard at zero specificity, so this stays at (0,1,1) and
 * does not start beating component rules it does still match.
 */
/*
 * Editorial links use the theme green, not the blue --base-link-color token.
 *
 * The brand green (--brand-color, #6fcf97) is a surface colour: as text on
 * white it lands near 1.9:1, far under the 4.5:1 WCAG 1.4.3 needs. The theme's
 * dark accent (--accent-color-dark, #387852) is the same hue family and clears
 * AA comfortably, so it is used here. On the dark bands the light brand green
 * is correct and is applied further down.
 */
/*
 * `li` on its own was too wide, and `:not([class])` did not save it.
 *
 * `.blog-list > li` is a layout list, and the blog card's title link inside it
 * carries no class — the comps write it as a bare `<a href="…">`. So the rule
 * matched at 0,1,1, beat `a { color: inherit }`, and the card title rendered
 * dark green and underlined on a charcoal card instead of plain white.
 *
 * Naming the two list types that actually hold prose fixes it, and fixes the
 * `.row-list__action` case the note above wrestles with more directly than the
 * class guard did: `.wp-block-list` is core's, `.list` is the design's own dot
 * list. Every other <li> in this markup — .blog-list, .row-list__item,
 * .icon-list__item, .cards__item — is layout.
 */
.entry-content :where(p, dd, dt, td, th, blockquote, figcaption, .wp-block-list li, .list li) a:where(:not([class])),
.wp-block-post-content :where(p, dd, dt, td, th, blockquote, figcaption, .wp-block-list li, .list li) a:where(:not([class])) {
	color: var(--accent-color-dark);
	text-decoration: underline;
	text-underline-offset: 0.18em;
}

.entry-content :where(p, dd, dt, td, th, blockquote, figcaption, .wp-block-list li, .list li) a:where(:not([class])):hover,
.wp-block-post-content :where(p, dd, dt, td, th, blockquote, figcaption, .wp-block-list li, .list li) a:where(:not([class])):hover {
	text-decoration: none;
}

/* Never restyle links inside header/footer template parts. */
.wp-block-template-part a {
	text-decoration: inherit;
}

/*
 * On the dark bands the editorial link colour fails contrast; use the brand
 * green. Same `:not([class])` guard, and for the same reason — .bg-gray is an
 * ancestor of every case-study list, so without it this rule also repainted
 * .row-list__action, and being later in the file it won the tie.
 */
.has-charcoal-background-color a:where(:not([class])),
.has-near-black-background-color a:where(:not([class])),
.bg-dark a:where(:not([class])),
.bg-gray a:where(:not([class])) {
	color: var(--brand-color);
}

/* --- Lists: apply the design's .list treatment by default -------------- *
 * Not a block style — prose lists should look right without the client
 * having to pick anything.
 */

.wp-block-list {
	display: flex;
	flex-direction: column;
	margin-bottom: var(--cml-space-3);
	padding-left: 0;
	list-style: none;
}

.wp-block-list:last-child {
	margin-bottom: 0;
}

.wp-block-list > li {
	position: relative;
	padding-left: 28px;
}

.wp-block-list > li::before {
	content: "";
	position: absolute;
	top: 0;
	left: 0;
	width: 6px;
	height: 6px;
	margin-left: 10px;
	margin-top: 0.6em;
	background-color: currentColor;
	border-radius: 50%;
}

/* Ordered lists keep their numbers — the dot treatment is for bullets only. */
.wp-block-list:where([type="1"], [type="a"], [type="A"], [type="i"], [type="I"]),
ol.wp-block-list {
	list-style: decimal;
	padding-left: 1.4em;
}

ol.wp-block-list > li {
	padding-left: 0;
}

ol.wp-block-list > li::before {
	content: none;
}

/*
 * The bullet geometry scales above 1024px. style.css:5584 switches .list li to
 * padding-left 2.8rem and the dot to 0.6rem square at margin-left 1rem; the px
 * values above are its mobile set, which was held at every width. Exact at
 * 1920 — 2.8rem IS 28px there — and 1.875x too wide at 1024.
 *
 * margin-bottom moves off --cml-space-3 here because the design does not keep
 * the two in step: .list is 24px at mobile (which space-3 matches) and 3.2rem
 * above 1024, where space-3 is 2.4rem. No single token carries both.
 */
@media (min-width: 1024px) {
	.wp-block-list {
		margin-bottom: 3.2rem;
	}

	.wp-block-list:last-child {
		margin-bottom: 0;
	}

	.wp-block-list > li {
		padding-left: 2.8rem;
	}

	.wp-block-list > li::before {
		width: 0.6rem;
		height: 0.6rem;
		margin-left: 1rem;
	}

	ol.wp-block-list > li {
		padding-left: 0;
	}
}

/* --- Quote: mirror .quote ---------------------------------------------- */

.wp-block-quote {
	font-family: "Avenir", Georgia, serif;
	font-style: italic;
	border-left: 3px solid #6fcf97;
	padding-left: var(--cml-space-3);
	margin-left: 0;
}

.wp-block-quote cite {
	display: block;
	margin-top: var(--cml-space-2);
	font-family: "Sora", sans-serif;
	font-style: normal;
	font-weight: 600;
	font-size: var(--h6);
	color: #6fcf97;
}

/* --- Separator: mirror .divider ---------------------------------------- */

.wp-block-separator {
	border: 0;
	border-top: 1px solid currentColor;
	opacity: 0.18;
	margin-block: var(--cml-space-5);
}

/* --- Lists: see the mapping further up this file ------------------------ *
 * A second `.wp-block-list` block used to sit here, from an early pass before
 * the `.list` mapping above existed:
 *
 *     .wp-block-list    { padding-left: 1.2em }
 *     .wp-block-list li { margin-bottom: var(--cml-space-1) }
 *
 * Both are 0,1,0 / 0,1,1 and both are LATER in the file than the mapping, so
 * they won their ties on source order and quietly reverted two of its
 * declarations everywhere:
 *
 *   - `padding-left: 1.2em` beat the mapping's `padding-left: 0`, so every
 *     prose list carried ~19px of indent on the <ul> ON TOP OF the 28px/2.8rem
 *     the <li> already has. The design puts the indent entirely on the item;
 *     the list itself is flush.
 *   - `li { margin-bottom }` added 8px (0.8rem above 1024) between items. The
 *     design's `.list` is a flex column with no gap and no item margin — the
 *     spacing between lines IS the 1.55 line-height and nothing else. The extra
 *     margin is what made the list read as too loosely leaded.
 *
 * Both deleted rather than merged. Ordered lists keep their own indent from
 * `ol.wp-block-list` at 0,1,1 above, which outranked the stray rule anyway.
 */

/* --- Columns ------------------------------------------------------------ *
 * There is no single "column gap" in this design to inherit. The four grids
 * disagree, and two of them do not even scale the same way:
 *
 *     .features    16px -> 3.4rem      .cards       24px, never scales
 *     .blog-list   24px -> 2.4rem      .case-list   24px -> 6.4rem
 *
 * --cml-space-3 is .blog-list's pair exactly (24px below 1024, 2.4rem above),
 * chosen as the editorial default: it is the design's own two-up content grid,
 * which is what a client reaches for core/columns to build. The previous
 * --cml-space-4 (32px / 3.2rem) matched none of the four.
 *
 * A block that needs .features' or .case-list's rhythm should be an ACF block
 * emitting that class, not a core Columns block re-tuned to match.
 */

.wp-block-columns {
	gap: var(--cml-space-3);
}

/*
 * Core stacks columns below 782px; this design goes two-up at 768px. In the
 * 14px between them a core Columns block is stacked while .cards, .features
 * and .blog-list beside it are not — and 768 is one of the three review
 * viewports, so the mismatch shows up exactly where it is looked for.
 *
 * Core owns both sides of this with !important:
 *
 *     .wp-block-columns { flex-wrap: wrap !important }
 *     @media (max-width: 781px) { … > .wp-block-column {
 *         flex-basis: 100% !important } }
 *
 * so !important is the only way through. The query is bounded on BOTH sides —
 * core is already correct from 782px up, and re-stating it there would mean
 * two rules to keep in step instead of one.
 *
 * Specificity deliberately equals core's (0,3,0) rather than exceeding it, per
 * 11.14; the bridge prints in the footer, so equal weight plus later position
 * wins. `:not(.is-not-stacked-on-mobile)` mirrors core's own guard so the
 * "never stack" option keeps behaving as the client set it.
 *
 * One consequence, accepted: `flex-basis: 0 !important` also overrides an
 * inline column width, so manually weighted columns render equal inside this
 * band. That matches the design — every one of its 768px grids is an equal
 * `repeat(2, 1fr)` or `repeat(3, 1fr)`, so there is no unequal two-up to
 * preserve. Core's own `[style*=flex-basis] { flex-grow: 0 }` companion is
 * deliberately NOT copied: against a forced `flex-basis: 0` it would collapse
 * a sized column to zero width rather than preserve it.
 */
@media (min-width: 768px) and (max-width: 781px) {
	.wp-block-columns:not(.is-not-stacked-on-mobile) {
		flex-wrap: nowrap !important;
	}

	.wp-block-columns:not(.is-not-stacked-on-mobile) > .wp-block-column {
		flex-basis: 0 !important;
		flex-grow: 1;
	}
}

/* --- Images ------------------------------------------------------------- */

.wp-block-image img {
	max-width: 100%;
	height: auto;
}

.wp-block-image.is-style-rounded img,
.wp-block-image .is-style-cml-rounded img {
	border-radius: 20px;
}

/* --- Details / disclosure ---------------------------------------------- *
 * style.css carries an old normalize block that sets `summary { display:
 * block }` for IE 10/11. A <summary> only paints its disclosure triangle at
 * `display: list-item`, so core/details renders with no affordance at all —
 * the client sees a heading that happens to be clickable.
 *
 * Rather than restoring the browser default, this mirrors the design's own
 * accordion toggle (.accordion-details__toggle): a 22px brand-green disc with
 * a chevron that points down when closed and up when open. The chevron is the
 * same path used in the delivered markup.
 */

.wp-block-details {
	border-bottom: 1px solid rgba(51, 51, 51, 0.12);
	padding-bottom: var(--cml-space-2);
	margin-bottom: var(--cml-space-2);
}

.wp-block-details > summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--cml-space-2);
	cursor: pointer;
	font-weight: 800;
	list-style: none;
}

/* Both are needed: the pseudo-element for WebKit, list-style for the rest. */
.wp-block-details > summary::-webkit-details-marker {
	display: none;
}

.wp-block-details > summary::after {
	content: "";
	flex-shrink: 0;
	width: 22px;
	height: 22px;
	border-radius: 50%;
	background-color: #6fcf97;
	background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 13 8" fill="%23333"><path d="M12.6195 6.16992C12.9899 6.54025 12.9899 7.14139 12.6195 7.51172C12.2492 7.88204 11.6481 7.88204 11.2777 7.51172L6.44864 2.68262L1.61954 7.51172C1.24922 7.88204 0.648068 7.88204 0.277744 7.51172C-0.0925812 7.14139 -0.0925812 6.54025 0.277744 6.16992L6.44864 0L12.6195 6.16992Z"/></svg>');
	background-repeat: no-repeat;
	background-position: center;
	background-size: 13px 8px;
	/* Closed points down; the source chevron points up, so rotate it. */
	transform: rotate(180deg);
	transition: transform 0.25s ease;
}

.wp-block-details[open] > summary::after {
	transform: rotate(0deg);
}

@media (prefers-reduced-motion: reduce) {
	.wp-block-details > summary::after {
		transition: none;
	}
}

/* --- Tables ------------------------------------------------------------- */

/* --- Tables: the design's green-outlined card, restated over core ------- *
 *
 * style.css:2775 draws a table as a rounded card — a 1px #6fcf97 outline with a
 * 12px radius, a solid green header band, green rules between cells and centred
 * text. None of it survived contact with core, whose block stylesheet is inlined
 * in the head and ships:
 *
 *     .wp-block-table table          { border-collapse: collapse }
 *     .wp-block-table thead          { border-bottom: 3px solid }
 *     .wp-block-table td, … th       { border: 1px solid; padding: .5em }
 *
 * all at 0,1,1, against the design's bare `table`, `table th` and `table th + th`
 * at 0,0,1 to 0,0,3. Core wins every one of them. So the table rendered with
 * square corners, a black 1px grid, a 3px rule under the header and no green
 * anywhere except the outer border.
 *
 * An earlier pass removed a `border-collapse: collapse` from THIS file for
 * squaring the corners, which was correct as far as it went and fixed nothing:
 * core was setting the same thing at the same weight. Deleting a duplicate of
 * someone else's rule does not remove theirs.
 *
 * Everything below is style.css's own values at block scope. `overflow: hidden`
 * on the table is the design's, and it is what clips the radius — with
 * `border-collapse: separate` it works, which is why the pair has to travel
 * together.
 */

/* The figure scrolls; the table inside it keeps its shape. */
.wp-block-table {
	overflow-x: auto;
	margin-block: 24px;
}

.wp-block-table table {
	width: 100%;
	border-collapse: separate;
	border-spacing: 0;
	border: 1px solid #6fcf97;
	border-radius: 12px;
	overflow: hidden;
}

/* Core draws 3px rules the design does not have. */
.wp-block-table thead,
.wp-block-table tfoot {
	border: 0;
}

/*
 * Cell padding tracks style.css:2786 (14px 20px) and :5599 (2.1rem 2.4rem)
 * rather than --cml-space-2/-3, which resolved to 16px 24px and 1.6rem 2.4rem
 * — 2px out at mobile and 5px out vertically at 1920.
 *
 * `border: 0` first, then the separators, exactly as style.css orders them: the
 * design draws lines BETWEEN cells rather than around them, so an outer cell has
 * no edge of its own and the card's own border serves.
 */
.wp-block-table th,
.wp-block-table td {
	padding: 14px 20px;
	text-align: center;
	border: 0;
}

.wp-block-table th + th,
.wp-block-table td + td {
	border-left: 1px solid #6fcf97;
}

.wp-block-table tbody tr td {
	border-top: 1px solid #6fcf97;
}

.wp-block-table thead th {
	background-color: #6fcf97;
	color: #fff;
	font-weight: 800;
}

.wp-block-table tbody td {
	color: #333;
}

@media (min-width: 1024px) {
	.wp-block-table {
		margin-block: 3.2rem;
	}

	.wp-block-table table {
		border-radius: 1.2rem;
	}

	.wp-block-table th,
	.wp-block-table td {
		padding: 2.1rem 2.4rem;
	}

	/*
	 * thead is restated because style.css:5601 gives header cells their own
	 * 2.6rem vertical padding at 0,0,3; the block-scoped rule above is 0,1,1
	 * and would otherwise flatten them to the body-cell value.
	 */
	.wp-block-table thead th {
		padding-top: 2.6rem;
		padding-bottom: 2.6rem;
	}
}

/* --- Groups carrying a palette background get the design's section rhythm - */

.wp-block-group.has-background {
	padding-top: var(--cml-space-6);
	padding-bottom: var(--cml-space-6);
}

/*
 * A background group that is NOT full-width still needs its own horizontal
 * inset.
 *
 * Core zeroes horizontal padding on any nested .has-global-padding that is not
 * .alignfull, to stop the gutter being applied twice. That is right for a
 * transparent wrapper — the outer container already provides the gutter — but
 * a group with a background has visible edges of its own, so the rule leaves
 * text sitting flush against the colour.
 *
 * In this design, colour bands are full-bleed; patterns that carry one set
 * align:full and are excluded from core's rule. This is the safety net for a
 * client who adds a background group without setting full width.
 *
 * Specificity here (0,3,0) deliberately beats core's (0,1,0) so load order
 * cannot change the outcome.
 */
.wp-block-group.has-background:not(.alignfull) {
	padding-left: var(--cml-space-4);
	padding-right: var(--cml-space-4);
}

/* Dark palette backgrounds are handled in §1b alongside the other preset
   aliases, so the mapping lives in one place. */

/* --- ACF InnerBlocks wrapper ------------------------------------------- *
 * ACF wraps <InnerBlocks /> in a .acf-innerblocks-container div, both on the
 * front end and in the editor. Several designed containers are flex columns —
 * .tile-card__content is `display:flex; flex-direction:column;
 * align-items:flex-start` — and that wrapper would become the single flex child,
 * so alignment and spacing apply to it rather than to the prose inside it.
 *
 * display:contents removes the box from the layout tree without removing the
 * element from the DOM, which ACF still needs as its editor drop target. A plain
 * <div> carries no semantics, so there is nothing for the known
 * display:contents accessibility bug to strip.
 *
 * Applies in the editor too, deliberately — Archetype D is only worth having if
 * what the client composes looks the same in both places.
 */
.acf-innerblocks-container {
	display: contents;
}

/* ------------------------------------------------------------------------- *
 * .post-single — the article body, which is core blocks
 * ------------------------------------------------------------------------- *
 * Comp 07's article is the one page in the design made almost entirely of
 * prose, and the client writes it with core blocks. style.css styles it as
 * hand-authored markup: `.post-single__title` on every section heading,
 * `ul.list` on every list, `blockquote.blockquote` on the pull quote. Asking
 * editors to type those classes is how a site ends up with half its articles
 * unstyled, so the design's selectors are extended to the core equivalents
 * instead.
 *
 * `.post-single__headline` is NOT caught by these rules: cml/post-single renders
 * it, so it carries its own class and no `.wp-block-heading`.
 */

/*
 * A section heading inside the article. The design fixes the size only above
 * 1024px — below that `.post-single__title` is a plain h3 — so only the desktop
 * half is restated here.
 *
 * The top spacing is PADDING in this component, not margin: style.css puts it on
 * the sibling pairs below. So the prose rhythm's margin-top is cleared, or the
 * two would stack and every heading would sit twice as far down as designed.
 */
.post-single :is(h2, h3, h4).wp-block-heading {
	margin-block-start: 0;
}

/*
 * style.css:4409 — the pairs it spaces are p, ul.list, blockquote and another
 * title. The core equivalents are p, .wp-block-list, .wp-block-quote and a
 * second heading. `.wp-block-table` is added because core wraps a table in a
 * figure, so `p + h3` no longer matches across one.
 */
.post-single :is(p, .wp-block-list, .wp-block-quote, .wp-block-table, .list, blockquote) + :is(h2, h3, h4).wp-block-heading,
.post-single :is(h2, h3, h4).wp-block-heading + :is(h2, h3, h4).wp-block-heading {
	padding-block-start: 36px;
}

/* style.css:4415 — the pull quote gets extra air after a list. */
.post-single .wp-block-list + .wp-block-quote {
	margin-block-start: 60px;
}

/*
 * `.post-figure` — a core image inside the article. The design's single-image
 * figure is the shape a client can produce with `core/image`, so it is mapped
 * here rather than given a block of its own. The two-up `--pair` is `cml/image-pair`,
 * which emits `.post-figure` itself and needs nothing from this file.
 */
.post-single .wp-block-image {
	padding-block: 36px 60px;
	margin-block: 0;
}

/*
 * style.css:4431 zeroes the top padding on consecutive figures, but it only
 * matches `.post-figure + .post-figure` — and one of the two figures in this
 * article is now a core image with a different class. Naming both on both sides
 * covers all four orders; without it, stacking a pair on a single image doubles
 * the gap between them.
 */
.post-single :is(.wp-block-image, .post-figure) + :is(.wp-block-image, .post-figure) {
	padding-block-start: 0;
}

.post-single .wp-block-image img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: 20px;
}

/*
 * Tables and article figures fill the column below 1024px.
 *
 * The inset they were carrying is normalize.css's, shipped inside style.css:
 *
 *     figure { margin: 1em 40px; }          <- style.css:191, 0,0,1
 *
 * Both blocks ARE figures — `.wp-block-table` and `.wp-block-image` each render
 * a `<figure>` wrapper — and nothing on either side of the stack resets the
 * inline axis. Core's block CSS touches `img` and `table`, not the wrapper's
 * margin; this file's own rules are `margin-block: 24px` on the table and
 * `margin-block: 0` on the figure. Block axis both times. So 40px of left and
 * right margin survived from a CSS reset into every article table and every
 * article image.
 *
 * `margin-inline: 0` cancels exactly that and leaves the block margins alone.
 * `width: 100%` and `max-width: none` then let the element fill the column it
 * sits in — `.post-single` inside `.main-content`, which is where the text
 * measure already is, so the table lines up with the paragraphs above it.
 *
 * Unscoped, because the 40px is not a mobile problem — normalize's rule carries
 * no media query, so the offset was present at every width. It started life in a
 * `max-width: 1023px` query and was widened once desktop was looked at.
 *
 * `max-width: none` here is what lets it bind above 1024. The desktop rule below
 * used to cap the figure at `120rem`, mirroring `.post-figure` at style.css:6295
 * — the design's own value. That cap is deliberately dropped: it is the one
 * thing that would stop a wide article image from filling the column, and with
 * `margin-inline: 0` it would also have left the image sitting to the left of
 * its own column rather than centred in it. Reinstate both together or neither.
 *
 * The table keeps the `overflow-x: auto` it already has, so one wider than the
 * column scrolls inside a full-width box rather than a 40px-inset one.
 */
.post-single .wp-block-table,
.post-single .wp-block-image {
	margin-inline: 0;
	width: 100%;
	max-width: none;
}

/*
 * The article's pull quote is `.blockquote`, a THIRD quote treatment — the
 * design also has a bare `blockquote` (centred, cite over a rule) and `.quote`
 * (green left border, which the global mapping above gives `core/quote`).
 * Inside `.post-single` the design uses `.blockquote` every time, so the mapping
 * is narrowed here rather than asking the client to pick a block style.
 *
 * `3rem` and `9rem` are copied verbatim on purpose: they are the design's own
 * values and ride the same fluid root, so restating them in px would freeze what
 * style.css scales. The desktop half is restated below because style.css
 * restates it — the audit in 11.23.
 */
.post-single .wp-block-quote {
	font-family: "Avenir", Georgia, serif;
	font-style: italic;
	font-weight: 800;
	text-align: left;
	border-left: 0;
	padding-left: 50px;
	margin-left: 0;
	margin-bottom: 24px;
	position: relative;
}

.post-single .wp-block-quote::before {
	content: "\201C";
	font-family: "Sora", sans-serif;
	font-style: normal;
	font-weight: 800;
	font-size: 3rem;
	position: absolute;
	top: 0;
	left: 0;
	line-height: 1;
	color: #6fcf97;
}

.post-single .wp-block-quote p {
	margin-bottom: 5px;
}

/* .blockquote cite drops everything the .quote cite adds. */
.post-single .wp-block-quote cite {
	border: 0;
	padding: 0;
	margin-top: 0;
	font-family: "Avenir", Georgia, serif;
	font-style: italic;
	font-weight: 400;
	color: inherit;
}

@media (min-width: 1024px) {
	.post-single :is(h2, h3, h4).wp-block-heading {
		font-size: 4.5rem;
		margin-block-end: 3rem;
	}

	.post-single :is(p, .wp-block-list, .wp-block-quote, .wp-block-table, .list, blockquote) + :is(h2, h3, h4).wp-block-heading,
	.post-single :is(h2, h3, h4).wp-block-heading + :is(h2, h3, h4).wp-block-heading {
		padding-block-start: 4.8rem;
	}

	.post-single .wp-block-list + .wp-block-quote {
		margin-block-start: 8rem;
	}

	/*
	 * `max-width: 120rem` was here, mirroring `.post-figure` at style.css:6295.
	 * Removed so article figures fill the content column at every width — see
	 * the note beside the unscoped rule above. The padding is untouched.
	 */
	.post-single .wp-block-image {
		padding-block: 4.8rem 8rem;
	}

	.post-single .wp-block-image img {
		border-radius: 3.6rem;
	}

	.post-single .wp-block-quote {
		font-size: 3rem;
		padding-left: 9rem;
		margin-bottom: 3.2rem;
	}

	.post-single .wp-block-quote::before {
		font-size: 14.6rem;
	}

	.post-single .wp-block-quote p {
		margin-bottom: 0.8rem;
	}

	.post-single .wp-block-quote cite {
		font-size: max(18px, 2rem);
	}
}

/* ------------------------------------------------------------------------- *
 * .section-hero--tint — a green wash over the hero photograph
 * ------------------------------------------------------------------------- *
 * Theme-authored, not from the comps: an addition asked for on the case study
 * single, exposed as `cml/hero`'s `image_tint` field so the other eight heroes
 * are untouched.
 *
 * `.bg-stretch` is already `position: absolute; inset: 0; z-index: -1`
 * (style.css:3014), so a pseudo-element inside it paints over the photograph and
 * still sits behind the copy. No new stacking context and no z-index arithmetic.
 *
 * Two layers, and both are needed. `multiply` alone reads as a dirty green on a
 * light photograph and washes out on a dark one; a flat green alone flattens the
 * image to a colour field. Multiply carries the photograph's own tonality into
 * the green, and the charcoal scrim underneath holds the contrast the white h1
 * depends on — `.section-hero` is `color: #fff`, and a mid-green at full
 * strength would drop it to roughly 2:1.
 *
 * `background-color` on the ::after rather than a gradient, so the two layers
 * can carry different blend modes.
 */
.section-hero--tint .bg-stretch::before,
.section-hero--tint .bg-stretch::after {
	content: "";
	position: absolute;
	inset: 0;
	pointer-events: none;
}

.section-hero--tint .bg-stretch::before {
	background-color: #141414;
	opacity: 0.45;
}

.section-hero--tint .bg-stretch::after {
	background-color: var(--brand-color, #6fcf97);
	opacity: 0.55;
	mix-blend-mode: multiply;
}

/*
 * Safari and Firefox honour mix-blend-mode here, but a browser that does not
 * would paint flat green at 55% and bury the photograph. Isolating the layer
 * costs nothing where blending works and keeps the photo visible where it does
 * not.
 */
@supports not (mix-blend-mode: multiply) {
	.section-hero--tint .bg-stretch::after {
		opacity: 0.35;
	}
}

/* ------------------------------------------------------------------------- *
 * .stat — the case study's headline figure
 * ------------------------------------------------------------------------- *
 * Two routes. The design's own drawn number is an SVG, and where one exists it
 * is used: `.stat__value` keeps the fixed box style.css gives it and the artwork
 * scales into it, which is the whole reason a fixed box was drawn. `illustration()`
 * emits an `<img>`, so it needs the sizing the comp's inline `<svg>` got for free.
 */
.stat__value img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: contain;
}

/*
 * The figure overhangs its own column on purpose — 80.8rem of artwork in a 68rem
 * `.tile-card__content` — so the section has to be allowed to contain it rather
 * than let it reach the edge of the page. Cheap insurance either way: bundled
 * artwork the design vendor supplies later is not guaranteed to be 808 units
 * wide, and nothing in this section is meant to break out of it.
 */
[data-block-name="tile-card"] {
	overflow: hidden;
}

/* ------------------------------------------------------------------------- *
 * .stat__value--text — the same figure with no artwork drawn for it
 * ------------------------------------------------------------------------- *
 * Comp 09 draws this number as an inline `<svg viewBox="0 0 808 325">` of three
 * outlined glyph paths. That is artwork, not content: it cannot be typed, cannot
 * be translated, cannot be read by a screen reader, and a new case study would
 * need the design shop to draw a new one. So `cml/tile-card` renders a text
 * field and this restores the scale the artwork had.
 *
 * `.stat__value` is a fixed 300x120 / 80.8rem x 32.5rem box in style.css, sized
 * to hold that SVG, and text in a fixed box either overflows it or floats in it.
 * So the box is released and the type sized from the design's own WIDTH.
 *
 * ## Size from the width, not the height
 *
 * The obvious move — pick a font-size matching the comp's 316px cap height — is
 * wrong, and was the first attempt here. `font-size` sets the height and the
 * width falls out of the string, so a size that fits `72K` does not fit `700%`:
 * `%` is nearly twice a digit, and that figure rendered 1136px wide inside a
 * 790px column and left the side of the page.
 *
 * `--stat-em` is the string's total advance, measured per instance by
 * `cml_stat_advance()`. Dividing the design's width by it makes every figure
 * span the same 80.8rem the artwork did — a longer value is SHORTER, not wider,
 * which is what a fixed box always implied. 78rem rather than 80.8rem leaves
 * about 3.5% for the advance table being approximate; erring small keeps the
 * figure inside the column, erring large is the bug above.
 *
 * `nowrap` because the size assumes one line. That is not a limitation to work
 * around — a headline figure that wraps has stopped being one.
 */
.stat__value--text {
	width: auto;
	height: auto;
	margin-bottom: 10px;
	font-family: "Sora", sans-serif;
	font-weight: 800;
	white-space: nowrap;
	color: var(--brand-color, #6fcf97);
	/*
	 * The comp's box is 32.5rem tall around glyphs that are 31.5rem — tight to the
	 * ink, because an SVG has no ascender or descender space. A text line box at
	 * `line-height: 1` would be the full 41.5rem em and open about 90px of air
	 * above the figure that the artwork never had. 0.8 puts the box back at 33rem
	 * for the same figure, and at exactly the comp's 120px on mobile.
	 */
	line-height: 0.8;
	/*
	 * The mobile box is 300px, and the container is narrower than that under
	 * about 366px, so the smaller of the two governs.
	 */
	font-size: min(150px, calc(min(300px, 82vw) / var(--stat-em, 1.88)));
}

@media (min-width: 1024px) {
	.stat__value--text {
		/*
		 * style.css:6401 writes this gap as `1em`, and on the comp that resolves
		 * against the INHERITED size — the span holds an SVG and sets no font-size
		 * of its own, so 1em is body copy, about 22px. Here the span carries a
		 * ~290px font-size, so the same `1em` would open a 290px hole between the
		 * figure and its caption. `--base-font-size` is what the comp's 1em
		 * actually meant.
		 */
		margin-bottom: var(--base-font-size, 16px);
		/*
		 * The ceiling matters for a short value: `5x` would otherwise be sized to
		 * span 78rem and tower over the section. 44rem puts its cap height a
		 * little above the comp's, which is the right way round.
		 */
		font-size: min(44rem, calc(78rem / var(--stat-em, 1.88)));
	}
}

/* ------------------------------------------------------------------------- *
 * No top-level child of .wp-site-blocks carries a gap of its own
 * ------------------------------------------------------------------------- *
 * Core prints three rules against the root flex column:
 *
 *     :where(.wp-site-blocks) > *            { margin-block-start: var(--cml-space-3) }
 *     :where(.wp-site-blocks) > :first-child { margin-block-start: 0 }
 *     :where(.wp-site-blocks) > :last-child  { margin-block-end: 0 }
 *
 * `--wp--style--block-gap` is `--cml-space-3` here, so every child but the first
 * is pushed down — 24px below 1024, 2.4rem above. The design has these elements
 * touching; sections carry their own padding, which is the same principle the
 * `.is-layout-constrained` rule further up this file rests on.
 *
 * This started life scoped to `.wp-block-template-part`, which was the wrong
 * half of the problem. There are exactly three children — the header part,
 * `<main class="main">`, and the footer part — and of those:
 *
 *   - the header part is `:first-child`, so core already zeroes it;
 *   - the footer part was covered by the old scoped rule;
 *   - `<main>` was covered by NOTHING, and it is the one in the middle.
 *
 * So the visible gap was between the header and the first section on every
 * page, while the rule that was supposed to fix gaps like it was busy
 * re-zeroing a footer core had partly handled and a header core had fully
 * handled. Scoping to `> *` is both simpler and the version that works: no
 * top-level child in this theme has block spacing worth preserving.
 *
 * 0,1,0 against core's 0,0,0 — `:where()` contributes nothing to specificity,
 * so this wins on weight and does not depend on load order.
 */
.wp-site-blocks > * {
	margin-block: 0;
}

/* ------------------------------------------------------------------------- *
 * A search input is border-box like everything else
 * ------------------------------------------------------------------------- *
 * style.css carries normalize.css's `input[type=search] { box-sizing:
 * content-box }` at 0,1,1, which outranks its own `* { box-sizing: border-box }`
 * reset at 0,0,0. The comps never hit it because their search field is
 * `type="text"`; this theme uses `type="search"`, which is the better element —
 * it gets the clear-field affordance and announces itself as a search box.
 *
 * The cost was invisible until it was not. `input.search-form__input` is
 * `width: 100%` with `padding-left: 44px` and `padding-right: 20px`, so under
 * content-box the field rendered 66px wider than `.search-form__field` and hung
 * out of the filter panel on the blog and case study archives.
 *
 * 0,1,1 ties normalize's rule and this file loads later. Not scoped to
 * `.search-form__input`, because `core/search` emits `input[type="search"]` too
 * and would arrive with exactly the same overflow the day a client inserts one.
 */
input[type="search"] {
	box-sizing: border-box;
}

/* ------------------------------------------------------------------------- *
 * Flow containers add no gap of their own
 * ------------------------------------------------------------------------- *
 * Core prints `:root :where(.is-layout-flow) > * { margin-block-start:
 * var(--wp--style--global--block-gap) }`, and `<main class="wp-block-group main">`
 * is a flow container on every template-driven page. So the sections inside it —
 * hero, cta-banner, post-archive, the case study body — each took a 24px / 2.4rem
 * push, putting a stripe of page background between coloured bands that the comps
 * have touching.
 *
 * This is the same fault the section rule near the top of this file fixes, in the
 * container that rule does not reach: it covers `.wp-block-post-content` and
 * `.entry-content`, which is the right scope for a page built from post content,
 * and the Phase 9 templates put their blocks straight into `<main>` instead.
 *
 * Matched at core's own 0,1,0 and printed later. The design carries vertical
 * rhythm on the BOTTOM — `.section` padding, `p`/`.wp-block-list` margin-bottom,
 * the article's own padding pairs — so removing the top gap takes nothing with
 * it that something else was not already providing.
 */
:root :where(.is-layout-flow) > * {
	margin-block-start: 0;
}

/* ------------------------------------------------------------------------- *
 * Case study / blog filter panel — full-width pill bar on desktop
 * ------------------------------------------------------------------------- *
 * `style.css` leaves `.filter-panel__list` to size to its content, and the panel
 * sets `align-items: flex-start`, so the bar ends up as wide as the categories
 * happen to be. The comps hide that with eleven placeholder categories; a real
 * taxonomy has four or five and the bar reads as a stray box.
 *
 * Safe in both of the panel's states. Between 1024 and 1199 it is a column, so
 * this simply spans the container. From 1200 it is a row alongside `.search-form`
 * — and that form is `flex-shrink: 0` at a fixed `max(280px, 29rem)`, so it holds
 * its designed width and the list shrinks from 100% into whatever is left. Full
 * width either way, with nothing to squeeze.
 */
@media (min-width: 1024px) {
	.filter-panel__list {
		width: 100%;
	}
}
