/**
 * Poulton theme — design details core blocks can't express via theme.json.
 * Tokens come exclusively from theme.json presets (--wp--preset--*, --wp--custom--*).
 *
 * v3 treatment: gradient hero and bands, a floating glass pill for navigation,
 * soft-shadowed cards, and a muted clay accent in place of the old orange.
 */

/* Layout, surface and radius values all come from theme.json (settings.custom),
 * so WordPress generates them as --wp--custom--* and the editor sees the same
 * numbers the front end does. Only genuinely CSS-only things live here. */
:root {
	--poulton-extlink-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M15 3h6v6'/%3E%3Cpath d='M10 14 21 3'/%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'/%3E%3C/svg%3E");
	/* Lucide "mail" — precedes a mailto link for affordance before the reader
	 * reaches the outbound arrow at the end of the text. */
	--poulton-mail-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect width='20' height='16' x='2' y='4' rx='2'/%3E%3Cpath d='m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7'/%3E%3C/svg%3E");
	/* The index rail's footprint. Both the article grid and .poulton-readcol
	 * derive from these, so the column the grid reserves and the offset the
	 * header takes can never drift apart. */
	--poulton-toc-rail: 250px;
	--poulton-toc-gap: 40px;
	/* The reference list's way back to the citation: a return arrow. */
	--poulton-return-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 5v6a4 4 0 0 1-4 4H5'/%3E%3Cpath d='m9 11-4 4 4 4'/%3E%3C/svg%3E");
	/* Lucide `download`, from `npm run icon download`. Masked, so it takes
	 * the button's own ink and follows its hover. */
	--poulton-download-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 15V3'/%3E%3Cpath d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4'/%3E%3Cpath d='m7 10 5 5 5-5'/%3E%3C/svg%3E");
	--poulton-arrow-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23FFFFFF' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h13'/%3E%3Cpath d='m12 5 7 7-7 7'/%3E%3C/svg%3E");
	/* The same arrow turned to point up and restroked in deep blue: the chip's
	 * surface is sand, not the arrow button's solid primary-dark circle, so a
	 * white stroke would vanish. */
	/* The back-to-top chip's footprint at the foot of the window: its 24px
	 * offset, its 40px height and 16px of air. From 1080px the chip and the
	 * contents rail share a column, so the rail's max-height subtracts this to
	 * stop a long index running underneath it. Owned here because two unrelated
	 * components depend on the same number. */
	--poulton-to-top-clear: 80px;
	--poulton-to-top-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23002F6C' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 19V6'/%3E%3Cpath d='m5 13 7-7 7 7'/%3E%3C/svg%3E");
	/* Lucide `play`, filled white — the glyph the Listen chip's disc carries,
	 * as a background for the sheet cards' Listen pill, whose text is a bound
	 * string and cannot hold an inline SVG. */
	--poulton-play-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23ffffff'%3E%3Cpath d='M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z'/%3E%3C/svg%3E");
}

html {
	scroll-padding-top: var(--wp--custom--shell--nav-clear);
}

/* ---------- Navigating between pages ----------
 * The browser holds the outgoing page's pixels and crossfades to the new one,
 * so a reader never sees a bare half-drawn frame mid-navigation.
 *
 * No JavaScript on purpose. A full-screen loader would have hidden the same
 * flash, but it delays content that paints in ~230ms, pushes FCP and LCP the
 * wrong way on a site whose rankings are the standing constraint, and a script
 * failure would leave someone staring at a spinner instead of the article.
 * Browsers without support ignore this entirely and behave exactly as before.
 *
 * This hides a flash; it does not cause one. The font swap that was actually
 * making the hero re-wrap is fixed at source by theme.json's
 * `fontDisplay: optional`. */
@view-transition {
	navigation: auto;
}
/* The fixed pill is on every page, so let it stay put rather than crossfade
 * with the content under it. The name must be unique within a page — this is a
 * template part rendered once, and a duplicate would silently skip the whole
 * transition. */
.poulton-header {
	view-transition-name: poulton-header;
}
/* Sequential, not a crossfade: the delay on the incoming half is the whole
 * point. A crossfade paints both pages at once, and two pages of this site
 * differ enough — a hero against a card grid, headings at different heights —
 * that the overlap reads as one page sliding against another rather than as a
 * transition. Fading the old one out first and the new one in after means
 * there is never a frame with both on screen. Opacity only, for the same
 * reason: a translate on the incoming half gives the eye a second thing to
 * measure the old page against.
 *
 * The header keeps its own name above, so the fixed pill stays put across the
 * whole thing. Nothing else moves during a transition — the entry cascade sits
 * these navigations out (see poulton_print_animation_boot_script). */
::view-transition-old(root) {
	animation: 140ms ease-in both poulton-vt-out;
}
::view-transition-new(root) {
	animation: 180ms 140ms ease-out both poulton-vt-in;
}
@keyframes poulton-vt-out {
	to { opacity: 0; }
}
@keyframes poulton-vt-in {
	from { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
	/* Still navigate, just without the crossfade. */
	::view-transition-old( root ),
	::view-transition-new( root ) {
		animation: none;
	}
}
/* Jumping to a section used to teleport, which on a 9,900-word sheet leaves
 * you with no idea where you landed. CSS rather than a click handler, so it
 * works with JavaScript off too; it composes with the scroll-padding above, so
 * the target still clears the header. */
@media (prefers-reduced-motion: no-preference) {
	html {
		scroll-behavior: smooth;
	}
}

/* ---------- Floating pill navigation ----------
 * The header is fixed rather than sticky so the hero gradient can run to the
 * very top of the page behind it. Out of flow from first paint, so it costs
 * no layout shift; the clearance below puts it back. */
.poulton-header {
	position: fixed;
	inset: 0 0 auto 0;
	z-index: 30;
	background: transparent;
}
.poulton-navpill {
	position: relative;
	gap: 20px;
	/* Left gutter is the shell gutter, so the wordmark lands on the site
	 * column. Right is 8px — matching the vertical padding — so the CTA sits
	 * evenly inside the glass rather than floating a gutter off the edge. */
	padding: 8px 8px 8px var(--wp--custom--shell--gutter);
	border-radius: var(--wp--custom--radius--pill);
}
/* The glass sits on a pseudo-element, NOT on the pill itself. A backdrop-filter
 * other than `none` makes an element a CONTAINING BLOCK for position:fixed
 * descendants — which trapped the mobile menu overlay inside the pill at
 * 340x80 instead of covering the viewport. The pill must stay filter-free. */
.poulton-navpill::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	/* A hairline in ink, not white: over white page content a white border left
	 * the pill with no edge at all, only its shadow. Raised from 0.08 when the
	 * hero was softened — the pill used to get its shape from the mid-blue
	 * behind it (glass against hero measured 3.29:1) and that dropped to 1.38:1
	 * once the gradient went pale, so the border has to do the work the
	 * background was doing. */
	border: 1px solid rgba(6, 32, 62, 0.16);
	border-radius: inherit;
	background: rgba(255, 255, 255, 0.86);
	box-shadow: var(--wp--custom--shadow--pill);
	/* the only blurred surface on the site: blur is expensive during scroll,
	 * and one small element is the whole budget */
	-webkit-backdrop-filter: blur(18px) saturate(140%);
	backdrop-filter: blur(18px) saturate(140%);
}
.poulton-header .wp-block-navigation a {
	color: var(--wp--preset--color--primary-dark);
	text-decoration: none;
}
/* Where you are, in the pill's own vocabulary — a tinted chip inside the glass,
 * the same shape as the pill around it and the category pills in the content.
 *
 * A colour swap alone was not enough for two reasons: hover and the focus ring
 * are both `primary`, so a colour-only hover was indistinguishable from focus;
 * and the active rule keyed on `.current-menu-item`, which core never emitted
 * here (see inc/nav-current.php) — so it had never once fired.
 *
 * The padding lives on the anchor, not the item, because core puts the padding
 * reset there; `blockGap` drops from 28px to 8px so six chips take about the
 * width five bare labels did. NOTE the effects stay on the links: a filter or
 * transform on .poulton-navpill would make it a containing block and trap the
 * mobile overlay inside it (see the ::before comment above). */
.poulton-header .wp-block-navigation .wp-block-navigation-item__content {
	padding: 6px 14px;
	border-radius: var(--wp--custom--radius--pill);
	transition: background-color 120ms ease, color 120ms ease;
}
.poulton-header .wp-block-navigation .wp-block-navigation-item__content:hover {
	/* A wash, not the full chip: hover has to sit clearly BELOW the active
	 * state or the two read as the same thing and the nav stops telling you
	 * where you are. Tinted from primary rather than using `surface` flat, so
	 * it lands about a third of the way to it. */
	background: rgba(1, 87, 155, 0.06);
	color: var(--wp--preset--color--primary);
}
.poulton-header .wp-block-navigation .current-menu-item .wp-block-navigation-item__content,
.poulton-header .wp-block-navigation .wp-block-navigation-item__content[aria-current="page"] {
	background: var(--wp--custom--surface--module);
	color: var(--wp--preset--color--primary);
	font-weight: 500;
}
@media (prefers-reduced-motion: reduce) {
	.poulton-header .wp-block-navigation .wp-block-navigation-item__content {
		transition: none;
	}
}
.poulton-nav-cta {
	flex: none;
}
.poulton-nav-cta .wp-block-button__link {
	padding: 11px 22px;
	font-size: 14px;
}
/* Search and the CTA share one flex item, so the pill keeps its three
 * children — wordmark, links, tools — and space-between still centres the
 * links. The gap lives here rather than as a blockGap on the group, for the
 * same reason the pill's does. */
.poulton-nav-tools {
	flex: none;
	display: flex;
	align-items: center;
	gap: 8px;
}
/* ---------- Search: the nav trigger ----------
 * The pill's secondary button, beside its primary: magnifier + "Search" in
 * .is-style-outline's vocabulary, on the CTA's own metrics (14px/1.45, 11px
 * vertical padding, 1.5px border) so the pair share a height. One departure
 * from the outline recipe — the hairline is the pill's own ink hairline, not
 * the pale one: on the glass the pale hairline vanishes exactly as it did on
 * the pill's outer edge (the note at .poulton-navpill::before). Nothing in
 * here may take a transform or a filter — the pill must stay free of
 * containing blocks. The overlay it opens is at the foot of this file. */
.poulton-search {
	flex: none;
	display: flex;
}
.poulton-search__trigger {
	box-sizing: border-box;
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 11px 18px 11px 14px;
	border: 1.5px solid rgba(6, 32, 62, 0.16);
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--primary-dark);
	font: inherit;
	font-size: 14px;
	font-weight: 500;
	line-height: 1.45;
	letter-spacing: 0;
	white-space: nowrap;
	cursor: pointer;
	transition: background 0.22s ease, color 0.22s ease, border-color 0.22s ease;
}
.poulton-search__trigger:hover {
	border-color: var(--wp--preset--color--primary-light);
	color: var(--wp--preset--color--primary);
}
/* display: inline-flex above would beat the UA sheet's [hidden] — the dock's
 * lesson at .poulton-listen-dock[hidden] — and the scripted button would stand
 * as a dead twin beside the link. */
.poulton-search__trigger[hidden] {
	display: none;
}
/* Phones: the icon alone, as the 44px ghost circle it was. Measured, not
 * guessed: with the label, mark · wordmark · menu · Search · Get in touch
 * holds one row down to 534px, so 556 leaves it 22px of headroom (it was 530
 * over 508 before the mark went in front of the wordmark); below that the
 * icon version has room to spare, and below 506 the CTA has already left the
 * pill for the menu (the rule under the 600px tier), leaving mark · wordmark
 * · search · menu, which clears 320 only once the ≤360px rule has trimmed
 * the mark and the pill's left padding — see there for the margin. MEASURE
 * AGAIN if the wordmark, the mark, the label, the targets or the gaps
 * change. */
@media (max-width: 556px) {
	.poulton-search__label {
		display: none;
	}
	.poulton-search__trigger {
		justify-content: center;
		width: 44px;
		height: 44px;
		padding: 0;
		border-color: transparent;
		border-radius: 50%;
		background: transparent;
		transition: background-color 120ms ease, color 120ms ease;
	}
	.poulton-search__trigger:hover {
		background: rgba(1, 87, 155, 0.06);
		border-color: transparent;
	}
}
/* Text wordmark in place of the retired logo — one weight in both the nav and
 * the footer, only the scale differs. In the nav the site icon's disc (the
 * poulton/mark block) sits to its left, inside the same link. */
.poulton-wordmark {
	margin: 0;
	flex: none; /* must not shrink inside the nav pill's flex row */
	font-size: 19px;
	font-weight: 600;
	line-height: 1.2;
	letter-spacing: -0.02em;
	white-space: nowrap;
}
.poulton-wordmark a {
	display: flex; /* not inline-flex: on the baseline the <p> grows a descender gap under the disc */
	align-items: center;
	gap: 10px;
	color: var(--wp--preset--color--primary-dark);
	text-decoration: none;
	transition: color 0.22s ease;
}
.poulton-wordmark a:hover {
	color: var(--wp--preset--color--primary);
}
/* ---------- The mark ----------
 * The favicon's disc, inline (blocks/mark/render.php owns the drawing;
 * scripts/bake-icon.mjs owns the geometry). 28px beside 19px type: the disc
 * clears the text's line box by a few pixels each side, so it reads as a
 * mark rather than a bullet. The stops are re-stated here so the hover can
 * TRANSITION them — stop-color animates, and CSS on a <stop> beats its
 * presentation attribute.
 *
 * Hover: the disc lights up from below — the deep base and the mid stop
 * rise toward primary, the top note stays — and a soft blue halo lifts it
 * off the glass; the name turns primary with it. No transform: a lift would
 * read as a button, and the pill must stay free of anything that could
 * become a containing block.
 *
 * The lit stops are MEASURED, not chosen. bake-icon's rule is a white P at
 * 4.5:1 or better against every pixel under its ink box, and the first
 * hover (top stop lightened, mid to #2770AE) failed it at 3.98:1 — the
 * bloom already lightens the top-left, and the P's shoulder sits right in
 * it. Sampled the same way as the icon (disc rendered without the glyph,
 * worst pixel under the 156×215 ink box): rest 5.30:1 on #276FAD, this
 * hover 4.80:1 on #3176B3. Lighten the top stop and it fails again. */
.poulton-mark {
	flex: none;
	width: 28px;
	height: 28px;
	border-radius: 50%;
	box-shadow: 0 0 0 0 rgba(127, 168, 217, 0), 0 6px 16px -6px rgba(1, 87, 155, 0);
	transition: box-shadow 0.22s ease;
}
.poulton-mark__top {
	stop-color: var(--wp--preset--color--primary-light);
	transition: stop-color 0.22s ease;
}
.poulton-mark__mid {
	stop-color: var(--wp--preset--color--primary);
	transition: stop-color 0.22s ease;
}
.poulton-mark__base {
	stop-color: var(--wp--preset--color--primary-dark);
	transition: stop-color 0.22s ease;
}
.poulton-wordmark a:hover .poulton-mark {
	box-shadow: 0 0 0 4px rgba(127, 168, 217, 0.28), 0 6px 16px -6px rgba(1, 87, 155, 0.45);
}
.poulton-wordmark a:hover .poulton-mark__mid {
	stop-color: #1160A3;
}
.poulton-wordmark a:hover .poulton-mark__base {
	stop-color: #1467AB;
}
/* Own block, not the shared one above: same specificity, and that block
 * comes earlier, so it would lose the tie. The colour swap stays — it is
 * not motion. */
@media (prefers-reduced-motion: reduce) {
	.poulton-wordmark a,
	.poulton-mark,
	.poulton-mark__top,
	.poulton-mark__mid,
	.poulton-mark__base {
		transition: none;
	}
}
/* Standing alone above the footer's sitemap. Full colour, not the etched
 * treatment the logotype below gets — it is the one saturated object in
 * the footer sky, and that is the point of it. Sized to the sitemap's
 * type, not the nav's. */
.poulton-mark-standalone {
	margin: 0 0 20px;
	line-height: 0; /* the svg is inline; no descender gap under it */
}
.poulton-mark-standalone .poulton-mark {
	width: 44px;
	height: 44px;
}
/* The globe (assets/js/globe.js) draws into a canvas the module appends
 * beside the SVG, then marks the container live; the SVG is its still —
 * no JavaScript, reduced motion, or the moment before the first frame —
 * and simply stays when nothing arrives. Same box as the mark, so the swap
 * moves nothing. */
.poulton-globe canvas {
	display: block;
	width: 44px;
	height: 44px;
}
.poulton-globe.is-live .poulton-mark {
	display: none;
}
/* Etched glass. No longer a link — as a decorative logotype it is exempt from
 * the contrast floor that pinned it at 0.6, so it can sit right back in the
 * surface. The white highlight on the lower edge is what reads as glass. */
.poulton-footer .poulton-wordmark {
	font-size: clamp(30px, 4vw, 52px);
	letter-spacing: -0.03em;
	color: var(--wp--preset--color--primary-dark);
	opacity: 0.32;
	text-shadow: 0 1px 0 rgba(255, 255, 255, 0.55);
}
/* Hamburger sits inside the pill, so it takes the pill's ink */
.poulton-header .wp-block-navigation__responsive-container-open {
	color: var(--wp--preset--color--primary-dark);
}
/* Core paints the open overlay white through
 *   .wp-block-navigation:not(.has-background)
 *     .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay)
 * at specificity 0,5,0. A plainer 0,3,0 rule here LOST that fight, so the menu
 * opened as white links on a white sheet — invisible. Mirror core's own chain
 * one class deeper (0,6,0) to win outright, without !important.
 * Setting backgroundColor on the block instead would add .has-background and
 * paint a dark bar behind the DESKTOP links inside the glass pill. */
.poulton-header .wp-block-navigation:not(.has-background)
	.wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
	background-color: var(--wp--preset--color--primary-dark);
}
.poulton-header .wp-block-navigation:not(.has-text-color)
	.wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
	color: var(--wp--preset--color--base);
}
.poulton-header .wp-block-navigation__responsive-container.is-menu-open {
	padding-top: 64px;
}
.poulton-header .wp-block-navigation__responsive-container.is-menu-open a,
.poulton-header .wp-block-navigation__responsive-container-close {
	color: var(--wp--preset--color--base);
}
/* A left-aligned divided list, not a centred stack. Core centres the overlay
 * list and shrink-wraps it to its widest label, which on a phone leaves seven
 * labels of very different lengths ragged on both edges — and a rule between
 * items has nothing to align to. Stretch the list to the dialog so the rules
 * span the column, and drop the 8px row gap: the rhythm comes from the rows'
 * own padding, so each rule sits centred in the space it divides.
 * 0,4,0 to beat core's own centring at 0,3,0. */
.poulton-header .wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__container {
	width: 100%;
	align-items: stretch;
	row-gap: 0;
}
/* Full-screen menu rows: core's 14px link on a 23px row is a nav-bar metric,
 * not an overlay one. Type up, and padding out past the 44px touch target —
 * 10px of it now that the rows carry the list's whole rhythm.
 * The extra .wp-block-navigation__container in the chain is not decoration —
 * core zeroes the padding on these links from a more specific selector.
 * radius 0 undoes the pill the desktop chip rule sets: full-width rows with
 * stadium ends read as buttons, and they sit badly against the rules. */
.poulton-header .wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__container .wp-block-navigation-item a {
	padding: 10px 16px;
	border-radius: 0;
	font-size: 20px;
}
/* Each row is itself a COLUMN flex container centring its link, which survived
 * stretching the list: the labels stayed centred and the current row's tint
 * shrank to its own text. Stretching the row is what actually left-aligns the
 * menu — the text-align was never the thing centring it. */
.poulton-header .wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__container .wp-block-navigation-item {
	align-items: stretch;
}
/* The hairline between rows. White at 0.14 over the navy sheet is the faintest
 * value that still resolves on a phone in daylight; the palette's `line` is a
 * light-ground token and disappears here. Not above the first row, and not
 * above Contact — that one is a button held off the list by its own margin. */
.poulton-header .wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__container
	.wp-block-navigation-item + .wp-block-navigation-item:not(.poulton-nav-contact) {
	border-top: 1px solid rgba(255, 255, 255, 0.14);
}
/* The current row, on the dark sheet. This must out-specific the row rule
 * above — which paints EVERY overlay link `base` at 0,5,0 — or the current
 * item is styled on desktop and silently plain on a phone. Deeper selector, not
 * !important: the same trade the overlay's own background rule makes. Flat and
 * full-bleed rather than the desktop chip: in a divided list the tint IS the
 * selection, and a floating pill would fight the rules either side of it. */
.poulton-header .wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__container .current-menu-item .wp-block-navigation-item__content {
	background: rgba(255, 255, 255, 0.16);
	color: var(--wp--preset--color--base);
	font-weight: 600;
}
/* Hover, on the dark sheet. The desktop wash is a light-ground state — primary
 * ink on a primary tint — and inside the overlay it painted #01579B on the navy
 * at about 1.3:1, so a moused-over row all but vanished. White tint and white
 * ink instead, one step below the current row so the two still read apart.
 * Neither the current row (it keeps its stronger tint) nor Contact (a white
 * wash over a white pill would erase it) takes this. */
.poulton-header .wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__container
	.wp-block-navigation-item:not(.current-menu-item):not(.poulton-nav-contact)
	.wp-block-navigation-item__content:hover {
	background: rgba(255, 255, 255, 0.08);
	color: var(--wp--preset--color--base);
}
/* The primary menu carries a Contact item (scripts/import.php) that belongs to
 * the phone overlay alone: on desktop contact is the pill's Get in touch button,
 * and an eighth link in the row would move the measured wrap threshold below.
 * Hidden by default, revealed only inside the open overlay at the width where
 * the pill drops its CTA.
 *
 * The chain is not decoration: core paints every item in an OPEN overlay
 * `display: flex` at 0,3,0, so a plainer rule here lost, and between 481 and
 * the wrap threshold below — where the pill still shows Get in touch — the
 * menu offered contact a second time. 0,4,0 beats it; the reveal rule below
 * goes one deeper again. */
.poulton-header .wp-block-navigation__responsive-container
	.wp-block-navigation__container .poulton-nav-contact {
	display: none;
}
/* Core swaps to the overlay at 600px, but the links need far more than that to
 * sit on one row beside the wordmark and the tools. Measured, not guessed: with
 * SEVEN links in chips (Explanation Sheets as the active chip, the widest
 * case) plus the labelled search button (110px) and the CTA in the tools
 * cluster, and the 28px mark with its 10px gap inside the wordmark, the pill
 * holds one row down to 1272px and wraps to two at 1270 (61px tall → 94px).
 * 1320 gives the same 48px of headroom the text-only wordmark's value (1284
 * over 1236), the eight-link value (1344 over 1296), the earlier seven-link
 * labelled-search value (1260 over 1212), the icon-only value (1192 over
 * 1144), the seven-link value (1140 over 1092), the six-link value (1070
 * over 1021) and the five-link value (900 over 852) each had.
 *
 * History: 900 was right for five bare labels; adding Downloads and the active
 * chip left everything between 900 and 1021 broken until it was re-measured
 * at 1070; adding Book moved it to 1140; the search icon to 1192; labelling
 * that icon "Search" to 1260; adding For GPs to 1344; taking Blog out (a
 * shorter label than For GPs, so not back to 1260) to 1284; putting the
 * site icon's disc in front of the wordmark moved it here. ADDING A NAV
 * ITEM — OR RESIZING THE WORDMARK OR ITS MARK, OR CHANGING THE LINK PADDING,
 * OR ANYTHING IN THE TOOLS CLUSTER — MOVES THIS THRESHOLD: re-measure (step
 * the viewport down and read .poulton-navpill's height), don't trust 1320. */
@media (max-width: 1320px) {
	.poulton-header .wp-block-navigation__responsive-container:not(.is-menu-open) {
		display: none;
	}
	.poulton-header .wp-block-navigation__responsive-container-open:not(.always-shown) {
		display: flex;
	}
	/* Hamburger beside the CTA rather than floating mid-pill. margin, not
	 * `order`, so focus order still follows the visual order.
	 * `nav.` matters: core stamps .wp-block-navigation on the <ul> as well, and
	 * the bare class selector shoved the overlay's menu list to the right edge. */
	.poulton-header nav.wp-block-navigation {
		margin-left: auto;
	}
	/* 24x24 is core's default and WCAG 2.5.8's bare minimum. Pad out to a
	 * comfortable 44x44 target. No negative margin to claw the space back —
	 * that pulled the target to within 2px of the CTA, inviting mis-taps.
	 * 44px is shorter than the 45px CTA, so the pill's height is unchanged. */
	.poulton-header .wp-block-navigation__responsive-container-open {
		box-sizing: border-box;
		min-width: 44px;
		min-height: 44px;
		padding: 10px;
		justify-content: center;
		/* Centre, not stretch: the label's box would otherwise be the icon's
		 * 24px and its 14px of text would sit at the top of it. */
		align-items: center;
		gap: 6px;
	}
	/* The word beside the icon. This pill collapses at 1320px, which is most
	 * laptops, and the audit's first-time users did not read a bare ≡ on a
	 * desktop screen as "the site's sections live here". The word is injected
	 * by poulton_label_menu_button in functions.php and is aria-hidden: the
	 * button's own label is still core's "Open menu". */
	.poulton-menu-label {
		font-size: 14px;
		font-weight: 500;
		color: var(--wp--preset--color--primary-dark);
		/* The icon's box, so the word's line box and the icon share a centre
		 * and the font's own metrics place the capitals against the bars. */
		line-height: 24px;
	}
}
@media (max-width: 600px) {
	/* The header's padding is written inline by the block editor, so trimming
	 * the phone-width gutter needs !important — same reason as the modules. */
	.poulton-header {
		padding-left: 16px !important;
		padding-right: 16px !important;
	}
	.poulton-navpill {
		padding: 8px 8px 8px 22px;
		gap: 10px;
	}
	/* The pill runs edge-to-edge at 390px, so the wordmark's extra left padding
	 * has to be paid for: a slightly tighter CTA and one size down on the
	 * wordmark, which still leaves it larger and bolder than before. */
	.poulton-navpill .poulton-wordmark {
		font-size: 18px;
	}
	.poulton-navpill .poulton-wordmark a {
		gap: 8px;
	}
	.poulton-navpill .poulton-mark {
		width: 26px;
		height: 26px;
	}
	.poulton-nav-cta .wp-block-button__link {
		padding: 11px 16px;
	}
}
/* ≤506px: the pill drops its CTA altogether and contact moves into the menu.
 * Measured with the magnifier in place: as text the CTA fits from 468px up
 * (442 before the mark went in front of the wordmark), so 506 keeps the 38px
 * of headroom 480 used to give; below it the pill is mark · wordmark ·
 * search · hamburger, which clears 320px once the ≤360px rule has done its
 * trimming. MEASURE AGAIN if the wordmark, the mark, the targets or the gaps
 * change.
 *
 * The CTA once became a 44px envelope here instead (poulton_nav_cta_icon in
 * functions.php, removed with this rule) — the overlay had no Contact link, so
 * the icon was the only contact affordance on a phone, and below 353px even it
 * gave way. The white button in the overlay replaces both. */
@media (max-width: 506px) {
	/* Specificity has to beat core's .wp-block-buttons { display: flex }. */
	.poulton-navpill .poulton-nav-cta {
		display: none;
	}
	.poulton-header .wp-block-navigation__responsive-container.is-menu-open
		.wp-block-navigation__container .poulton-nav-contact {
		display: flex;
		/* Held off the last row, and sized to its label rather than stretched
		 * with the list. margin-left matches the rows' own 16px inset, so the
		 * button's left edge lines up with the labels above it. */
		align-self: flex-start;
		margin-top: 18px;
		margin-left: 16px;
	}
	/* A white pill on the navy sheet, on the pill button's own metrics
	 * (.wp-block-button__link below: 500 weight, 11px 26px, radius pill) rather
	 * than new numbers — 16px is one step up for the overlay's larger scale.
	 * Two rules above fight this and both are beaten deliberately: the overlay
	 * row rule (padding 6px 16px / 20px) is 0,5,0 to this one's 0,6,0, and the
	 * current-item chip is also 0,6,0 — so ORDER decides it, and this block must
	 * stay after that rule in the file. Otherwise, on /contact/, the chip paints
	 * white text on the white pill. */
	.poulton-header .wp-block-navigation__responsive-container.is-menu-open
		.wp-block-navigation__container .poulton-nav-contact
		.wp-block-navigation-item__content {
		padding: 11px 26px;
		border-radius: var(--wp--custom--radius--pill);
		background: var(--wp--preset--color--base);
		color: var(--wp--preset--color--primary-dark);
		font-size: 16px;
		font-weight: 500;
	}
	/* Same move the white outline button makes on a light ground: the fill steps
	 * to `surface` rather than the ink changing. */
	.poulton-header .wp-block-navigation__responsive-container.is-menu-open
		.wp-block-navigation__container .poulton-nav-contact
		.wp-block-navigation-item__content:hover {
		background: var(--wp--preset--color--surface);
	}
}
/* ≤400px: the pill is width-bound, so the gaps compress — the wordmark
 * holds at 17px rather than shrinking below its old size. */
@media (max-width: 400px) {
	.poulton-navpill {
		padding-left: 18px;
		gap: 8px;
	}
	.poulton-navpill .poulton-wordmark {
		font-size: 17px;
	}
	.poulton-navpill .poulton-wordmark a {
		gap: 6px;
	}
	.poulton-navpill .poulton-mark {
		width: 24px;
		height: 24px;
	}
}
/* ≤360px: the mark's price on the narrowest phones. Measured: mark ·
 * wordmark · search · hamburger overflowed the pill at 322px with the 24px
 * mark and the 18px left padding, so both give — the mark to 22px, the
 * padding to 14px. That buys 6px: at 320 the search circle ends 2px inside
 * the pill's edge (eating into its 8px right padding), and 316 overflows.
 * That is the whole margin; anything wider in the pill needs the wordmark
 * to shrink again. */
@media (max-width: 360px) {
	.poulton-navpill {
		padding-left: 14px;
	}
	.poulton-navpill .poulton-mark {
		width: 22px;
		height: 22px;
	}
}

/* Clearance for the fixed pill. Templates whose <main> carries its own top
 * padding take it there; templates whose <main> is flush (so a full-bleed
 * section can reach the top of the page) push it onto that first section, so
 * its background still starts at y=0 behind the pill. !important because the
 * block editor writes these paddings as inline styles. */
/* The fixed header occupies no space in flow, so core's block-gap margin on
 * the next sibling surfaced as a white strip above the hero. */
.wp-site-blocks > .poulton-main {
	margin-block-start: 0 !important;
}
/* The footer butts straight against the last section — no gap, so no strip of
 * page background shows between content and the footer's own background. */
.wp-site-blocks > footer {
	margin-block-start: 0 !important;
}
.poulton-main {
	padding-top: var(--wp--custom--shell--nav-clear) !important;
}
.poulton-main--flush {
	padding-top: 0 !important;
}
.poulton-main--flush > :first-child:not(.entry-content),
.poulton-main--flush > .entry-content > :first-child {
	padding-top: var(--wp--custom--shell--nav-clear) !important;
}
/* The hero carries more air than a standard page header: it has to clear the
 * pill AND give the gradient room to resolve. Higher specificity than the rule
 * above, which is also !important.
 *
 * The minimums are load-bearing and stay put: 124px is what holds the H1 clear
 * of the pill (whose bottom edge is 85px), and below ~1024px both ends already
 * sit on their minimum. Only the slope and the ceiling came down — the wide-
 * screen hero was around 300px of vertical padding, which pushed everything
 * below the fold for no benefit. Note this rule, not the block's own
 * spacing|70 padding in content/pages/home.html, is what actually renders. */
.poulton-main--flush > .entry-content > .poulton-hero:first-child {
	padding-top: clamp(124px, 9vw, 140px) !important;
	padding-bottom: clamp(96px, 8vw, 112px) !important;
}
/* About opens on its biography module, not a page header. Two traps:
 * the generic first-child rule above would stack the nav clearance INSIDE the
 * tinted card on top of its own padding, and a margin on the module collapses
 * through main (no padding, no BFC) and leaves the wash starting below the
 * pill. So the clearance goes on <main> as padding, the page-sand wash paints
 * on main so the pill keeps its ground, and the module keeps its card padding.
 * (0,4,0) beats every !important competitor on both elements. */
.poulton-main--flush:has(> .entry-content > .poulton-module:first-child) {
	padding-top: var(--wp--custom--shell--nav-clear) !important;
	background-image: var(--wp--preset--gradient--page-sand);
	background-repeat: no-repeat;
	background-size: 100% clamp(300px, 30vw, 420px);
}
.poulton-main--flush > .entry-content > .poulton-module:first-child {
	padding-top: clamp(24px, 4vw, 48px) !important;
}
/* …unless that first module is a BAND (the For GPs page header): a band is
 * the publication hero's shape and runs under the pill the way that does —
 * no wash on main, no clearance on main, the band's own top padding clears
 * the pill. Same specificity as the two rules above, later in the source. */
.poulton-main--flush:has(> .entry-content > .poulton-module--band:first-child) {
	padding-top: 0 !important;
	background-image: none;
}
.poulton-main--flush > .entry-content > .poulton-module--band:first-child {
	padding-top: var(--wp--custom--shell--nav-clear) !important;
}

/* Full-bleed sections butt against each other. Core's block-gap leaves a 24px
 * strip of page background between them, which read as a seam once the slab
 * corners were squared off. Each section carries its own padding, so no gap. */
.entry-content > .poulton-sect,
main > .poulton-sect {
	margin-block-start: 0 !important;
	margin-block-end: 0 !important;
}

/* ---------- Hero ---------- */
.poulton-hero {
	background-image: var(--wp--preset--gradient--hero-sky);
	background-repeat: no-repeat;
}
/* The label grey is set as light as it can go against the module surface (see
 * .poulton-kicker). On the hero's blue ramp it measures ~3.7:1 — a fail at
 * 12.5px, and one axe cannot see, because it records text over a gradient as
 * *incomplete* and Lighthouse scores that as a pass. Deep blue reads as a
 * deliberate label on that ground and clears 8:1. Only the book page has a
 * kicker on the hero; the home page's hero opens on its H1. */
.poulton-hero .poulton-kicker {
	color: var(--wp--preset--color--primary-dark);
}

/* ---------- Page header wash ----------
 * The hero's device in sand rather than blue: every page that is not the
 * homepage used to open on bare white, which left the floating nav pill with no
 * ground under it, and a warm opening never competes with the blue homepage.
 * One exception, added deliberately: /adhd-made-simple/ takes .poulton-hero
 * instead. It is a landing page for one product rather than a section of the
 * site, and the blue carries the book's own cover colour.
 * One radial off the top-right corner (the page-sand preset, built from the
 * `sand` token), fading to transparent over the page's own white.
 *
 * Two geometry rules keep it seamless, and both were once broken here:
 *   1. The ramp must reach transparent INSIDE the tile. The preset's ellipse
 *      is exactly the tile's height (ry = 100%), so the tile's bottom edge
 *      lies on or outside the ellipse across its whole width. An earlier
 *      ramp was 135% tall and only cleared at 84% of that — the tile cut it
 *      at ~19% opacity and drew a line along the bottom-right.
 *   2. The tile must fit inside the element (see background-size below), or
 *      the element cuts the ramp even earlier: Publications' ~330px header
 *      once clipped a 420px tile at ~49% opacity.
 * Paint only: the sizing comes from .poulton-sect and the nav clearance from
 * .poulton-main--flush, exactly as it does for the hero. */
.poulton-pagehead {
	background-image: var(--wp--preset--gradient--page-sand);
	background-repeat: no-repeat;
	/* A fixed depth rather than the header's own height: the Contact page
	 * once carried its whole form inside this header (658px against ~330px
	 * everywhere else), and sizing to the box gave it twice the wash of its
	 * neighbours. Contact has since moved to the surface band, but the cap
	 * stays for any tall header (search results, a topic). Capped by the
	 * element's height (min) so a short header can never clip the ramp; on a
	 * tall one the tile ends where the ramp is already transparent. */
	background-size: 100% min(100%, clamp(300px, 30vw, 420px));
}

/* ---------- Kicker: uppercase label ----------
 * A quiet type label, not a chip: no background, no dot. block, not flex —
 * a flex container ignores the constrained-layout max-width, which pushed the
 * kicker off the section's left edge.
 *
 * The grey is as light as it can go: at 12.5px this is normal-size text, so it
 * needs 4.5:1, and the pale module surface (not white) is the binding
 * background. Anything lighter than this fails there. */
/* ---------- Tag ----------
 * The third of the site's three label devices, and when each is used:
 *   kicker (.poulton-kicker)  an eyebrow over a heading — grey caps, no box
 *   pill   (.poulton-pill)    a category chip: a topic, a sheet number, the
 *                             card's corner tab
 *   tag    (.poulton-tag)     a filled label that classifies the thing it
 *                             sits on — who it is for, what state it is in
 * The tag is what a GP-series paper opens with ("For general
 * practitioners", printed by poulton_gp_series_hero after the breadcrumbs),
 * and the same words on the For GPs page header and the home page's For
 * GPs band, where they replaced the kicker: the way clinical publishers
 * flag a page "for healthcare professionals". Filled, not outlined, so it
 * reads as a classification and not a link; sat with the title so it is
 * read first. A tag, not a button: small type and tight padding keep it
 * from the buttons' scale even at the same rounded shape. One size on
 * every screen — 11px caps is the floor for a label and a tag is read,
 * not scanned, so phones get the same. The colour lives on a modifier
 * with the lilac one as the default, so a bare `poulton-tag` in the
 * editor is right; `--surface` is the blue for a future tag. In content,
 * a paragraph with the class. */
.poulton-tag {
	display: inline-block;
	width: fit-content;
	margin-block-end: 0; /* the top margin is the column's own flow gap */
	margin-inline: 0;
	padding: 4px 12px;
	border-radius: var(--wp--custom--radius--pill);
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.08em;
	line-height: 1.5;
	text-transform: uppercase;
	/* lilac-line — a step darker than the lilac band, the seal's ground —
	 * with the dark violet on it (8.1:1). The solid violet with white read
	 * as a button; violet-light was still a shade too heavy. */
	background: var(--wp--preset--color--lilac-line);
	color: var(--wp--preset--color--violet-dark);
}
.poulton-tag--surface {
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--primary);
}
/* The tag and the heading it labels are one unit: half the header's
 * rhythm between them. The gap is the heading's top margin (core's flow
 * gap sits on the following block — see the heading-spacing note), so
 * that is what moves. */
.poulton-tag + :is(h1, h2, h3, .wp-block-post-title) {
	margin-block-start: 14px !important;
}
.poulton-kicker {
	display: block;
	width: fit-content;
	margin-bottom: 2px;
	color: var(--wp--custom--label--color);
	font-size: 12.5px;
	font-weight: 600;
	line-height: 1.4;
	letter-spacing: 0.1em;
	text-transform: uppercase;
}
/* Dr Poulton's credential line — "Senior Lecturer in Paediatrics, Sydney
 * Medical School Nepean, The University of Sydney".
 *
 * It is a HEADING, not a paragraph, and must stay one. On the live site it is
 * an <h2>, and it is the only place "Lecturer", "Sydney" and "University of
 * Sydney" appear together — the on-page basis for the credential/location
 * queries the site ranks for. It was a muted <p> here until we compared the two
 * word by word. See the `seo-guardrails` skill; verify-redirects asserts it.
 *
 * These rules only undo the heading LOOK, so it reads as the standfirst it is:
 * theme.json gives h2/h3 a tighter line-height and negative tracking, which on
 * a three-clause line sets it too tight. Size and colour come from the block's
 * own preset classes, which are !important and therefore already win. */
.poulton-credential {
	font-weight: 400;
	line-height: 1.5;
	letter-spacing: normal;
	text-wrap: pretty;
}
.poulton-module .poulton-pill {
	/* a tint chip on a tint card is invisible — go white */
	--pill-bg: var(--wp--custom--surface--raised);
}

/* ---------- Modules ----------
 * A tinted section is a card floating on the page: the same shell as the nav
 * pill and the footer, so its content sits on the same column as everything
 * else. The horizontal padding MUST stay equal to the shell gutter — that
 * equality is what keeps the column aligned. */
.poulton-module {
	/* The surface comes from the block's own backgroundColor attribute, not
	 * from here — otherwise a module with no attribute still gets painted, and
	 * there is no way to have an untinted one. */
	border-radius: var(--wp--custom--radius--module);
}
.entry-content > .poulton-module,
main > .poulton-module {
	/* !important on all three: these sections are alignfull, and core's
	 * `.wp-container-… > .alignfull { max-width: none }` ties on specificity */
	max-width: var(--wp--custom--shell--width) !important;
	margin-inline: auto !important;
	padding: clamp(24px, 4vw, 48px) !important;
}
/* Adjacent modules need their own gap: the v3.3 seam rule zeroes section
 * margins, and where a white section sits between two, its padding does it. */
.poulton-module + .poulton-module {
	margin-block-start: var(--wp--custom--space--section) !important;
}
/* A card module as the last thing in main — the book at the foot of every
 * sheet (poulton/book-band in its template). Its rounded corners and the
 * footer's rounded top would otherwise touch, two shapes butted together;
 * the pages avoid this by ending on white. The same section gap the seam
 * rule takes away, put back below. Full-bleed bands are excluded: their
 * square corners are meant to meet the footer, which paints behind them. */
main > .poulton-module:not(.poulton-module--band):last-child,
.entry-content > .poulton-module:not(.poulton-module--band):last-child {
	margin-block-end: var(--wp--custom--space--section) !important;
}
/* Band variant: the surface runs edge to edge and the corners square off, but
 * the content stays on the same column via the 24px site gutter. Declared after
 * the card rules above so it wins the specificity tie. */
.entry-content > .poulton-module--band,
main > .poulton-module--band {
	max-width: none !important;
	/* alignfull breaks out of the root padding with negative margins; zeroing
	 * them would leave the surface inset by the gutter instead of reaching the
	 * viewport edge. Restore them, then pad back in so the content column
	 * still lands where every other section's does. */
	margin-inline: calc(-1 * var(--wp--style--root--padding-left))
		calc(-1 * var(--wp--style--root--padding-right)) !important;
	padding: var(--wp--custom--space--section) 24px !important;
	border-radius: 0;
}

/* A band whose heading lives in the section above it (sheets hub) — the
 * band rule's !important section padding would leave ~150px of dead white
 * between heading and cards, so this modifier must out-specific it. */
.entry-content > .poulton-module--band.poulton-band--flush-top,
main > .poulton-module--band.poulton-band--flush-top {
	padding-top: var(--wp--preset--spacing--40) !important;
}

/* The warm bands get soft top corners. Each of them (the sheet grids on the
 * home and About pages, Research papers on Downloads, the free-resources band
 * on the book page) sits on the white page with an untinted section directly
 * above, and a square edge running the full width of the viewport read as a
 * rule drawn across the page rather than one section giving way to the next.
 *
 * Keyed on the sand surface, not a modifier class, because that IS what these
 * sections are — the warm resource band. The other bands are `surface`, and
 * they are article headers sitting directly under the nav pill: nothing above
 * them to separate from, and a curve there would look like a mistake. Keying
 * on the colour keeps the two apart with no markup change, so the four
 * hand-copied card grids stay byte-identical and need no re-seed.
 *
 * The module radius. The card's 24px was tried first and was too quiet in
 * situ: across the full width of a viewport, a curve that reads clearly in a
 * side-by-side comparison barely registers on the page. Bottom corners stay
 * square — a band's bottom is where a section ends, not a seam against the
 * page above it. The one exception is the header band, below.
 * The lilac rule skips the page's first band: the page and GP-series
 * headers are lilac too, and a curve under the nav would be a mistake. */
.entry-content > .poulton-module--band.has-sand-background-color,
main > .poulton-module--band.has-sand-background-color,
.entry-content > .poulton-module--band.has-lilac-background-color:not(:first-child),
main > .poulton-module--band.has-lilac-background-color:not(:first-child) {
	border-radius: var(--wp--custom--radius--module) var(--wp--custom--radius--module) 0 0;
}
/* The header band — the tinted opening every post-type page, the For GPs
 * page and Downloads start on — is the one band whose bottom IS a seam:
 * the article starts on white directly under it. So it rounds at the
 * bottom, at the module radius like every other shoulder on the site, and
 * stays square on top where it runs up under the nav pill. */
.poulton-main--flush > .poulton-module--band:first-child,
.poulton-main--flush > .entry-content > .poulton-module--band:first-child {
	border-radius: 0 0 var(--wp--custom--radius--module) var(--wp--custom--radius--module);
	/* Above whatever tucks in under it (next rule). */
	position: relative;
	z-index: 1;
}
/* A band that follows the header band directly — the sheets hub's sand card
 * grid — meets it with no white between: the adjacent-module gap goes, the
 * band's own top corners square off (a curve against a curve pinches), and
 * it slides up under the header by the module radius so the header's rounded
 * corners curve over sand rather than over a strip of page. The padding it
 * gives up to the overlap is added back, so the cards sit where they would. */
.poulton-main--flush > .entry-content > .poulton-module--band:first-child + .poulton-module--band,
.poulton-main--flush > .poulton-module--band:first-child + .poulton-module--band {
	margin-block-start: calc(-1 * var(--wp--custom--radius--module)) !important;
	padding-top: calc(var(--wp--custom--space--section) + var(--wp--custom--radius--module)) !important;
	border-start-start-radius: 0;
	border-start-end-radius: 0;
}
/* The page-header bands (Contact, Downloads, Publications, Explanation
 * Sheets, For GPs) read tight: their top was only the nav clearance and
 * their bottom the bare section space. One step (24px) more of each, here
 * rather than in the five pages' markup, whose padding the band rule
 * above overrides anyway. Scoped to the header band so the hero, the home
 * GP band and every other band keep their rhythm; the templates' sand-wash
 * headers (404, search, archives) are a different treatment and untouched.
 * Wins on specificity over the first-child rule that sets the top. */
.poulton-main--flush > .entry-content > .poulton-module--band.poulton-pagehead-band:first-child {
	padding-top: calc(var(--wp--custom--shell--nav-clear) + var(--wp--preset--spacing--50)) !important;
	padding-bottom: calc(var(--wp--custom--space--section) + var(--wp--preset--spacing--50)) !important;
}
/* Under the title, one measure on every post type: the citation card on a
 * publication, the lede on a sheet, the date row on a post. 40px — a
 * step more than the 28px the rest of the header keeps — so the title
 * stands a little apart from what describes it. */
/* The title's size measurer (poulton_post_title_size) prints an inline
 * <script> right after the title, so the block below is either the next
 * sibling or the one after that script. */
.poulton-main--flush > .poulton-module--band:first-child .wp-block-post-title + :not(script),
.poulton-main--flush > .poulton-module--band:first-child .wp-block-post-title + script + * {
	margin-block-start: 40px !important;
}
/* On the home page the band is rounded on all four corners, because there its
 * bottom is a seam too: the sheet grid sits mid-page, with ~100px of white
 * below it before the biography module's inset card. On the other three pages
 * the band is the last section in the flow and runs into the footer, where a
 * curve would be closing something that has not ended. */
body.home .entry-content > .poulton-module--band.has-sand-background-color,
body.home main > .poulton-module--band.has-sand-background-color,
body.home .entry-content > .poulton-module--band.has-lilac-background-color,
body.home main > .poulton-module--band.has-lilac-background-color {
	border-radius: var(--wp--custom--radius--module);
}
/* The For GPs band on the home page: text beside a fan of the four
 * clinical-tool pages. The pictures are the bare first pages (gp-page-*,
 * no tile ground — bake-gp-tools.mjs), so they read as loose sheets on
 * the surface. Four absolutely placed figures, each with its own tilt and
 * offset; the box keeps its ratio so the fan holds its shape at any
 * column width. The band runs tighter than the section rhythm — one
 * short column and a picture, and the section padding was mostly air —
 * at the band rule's own weight, later in the source. */
.entry-content > .poulton-module--band.poulton-gp-band,
main > .poulton-module--band.poulton-gp-band {
	padding-block: var(--wp--preset--spacing--60) !important;
}
.poulton-gp-fan {
	position: relative;
	aspect-ratio: 1;
	max-width: 560px;
	margin-inline: auto;
}
.poulton-gp-fan-page {
	position: absolute;
	width: 52%; /* an A4 page: 52% wide is 74% tall, so the lowest one ends inside the box */
	margin: 0;
	border-radius: var(--wp--custom--radius--figure);
	box-shadow: var(--wp--custom--shadow--card);
	overflow: hidden;
}
.poulton-gp-fan-page img {
	display: block;
	width: 100%;
	height: auto;
}
/* Kept inside the box: the right-most page ends at 90% before its tilt,
 * so nothing is clipped by the band's edge at any column width. */
.poulton-gp-fan-page:nth-child(1) { top: 6%;  left: 4%;  transform: rotate(-8deg); }
.poulton-gp-fan-page:nth-child(2) { top: 0;   left: 21%; transform: rotate(-3deg); }
.poulton-gp-fan-page:nth-child(3) { top: 6%;  left: 40%; transform: rotate(3deg); }
.poulton-gp-fan-page:nth-child(4) { top: 20%; left: 26%; transform: rotate(7deg); }
/* The seal on the pile: a round sticker on the front page's top corner
 * saying what the pages are — free, and PDFs. Inline SVG in the content
 * (a wp:html block), painted from the tokens: the ground is lilac-line, a
 * step darker than the band rather than a new hue, and the text is
 * violet-dark on it. The ring text closes the circle exactly (textLength
 * is the ring's circumference, 2π·40) and turns once a minute; the mark
 * in the centre stays upright. Decoration only (aria-hidden — the band's
 * copy already says free to download), so the turn is gated on motion
 * preference and nothing depends on it. Sized off the fan so it keeps
 * its proportion to the pages; the floor keeps the ring text legible on
 * a 320px phone fan. The tilt matches the front page's. */
.poulton-gp-seal {
	position: absolute;
	top: 3%;
	right: 5%;
	width: 24%;
	min-width: 108px; /* ring text at 8.5px on a 320px phone fan; 7.6px at 96 was too fine */
	aspect-ratio: 1;
	transform: rotate(8deg);
	z-index: 1; /* above the pages, whose `rotate` (the pile) stacks them over an auto-level sibling */
	border-radius: 50%;
	box-shadow: var(--wp--custom--shadow--card);
}
.poulton-gp-seal svg {
	display: block;
	width: 100%;
	height: 100%;
	overflow: visible;
}
.poulton-gp-seal-ground {
	fill: var(--wp--preset--color--lilac-line);
}
.poulton-gp-seal-line {
	fill: none;
	stroke: var(--wp--preset--color--violet-light);
	stroke-width: 1;
}
.poulton-gp-seal-text {
	fill: var(--wp--preset--color--violet-dark);
	font-family: inherit;
	font-size: 9.5px;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}
.poulton-gp-seal-mark {
	fill: var(--wp--preset--color--violet-dark);
	font-family: inherit;
	font-size: 22px;
	font-weight: 700;
	letter-spacing: -0.01em;
	text-anchor: middle;
	/* Centred on the baseline (y = 60 + half the cap height at 22 units),
	 * not with dominant-baseline: central — Chrome painted that text at the
	 * wrong size and off-centre when the seal was in the first screen,
	 * while the DOM swore it was centred. */
}
.poulton-gp-seal-turn {
	transform-origin: 60px 60px;
}
@media (prefers-reduced-motion: no-preference) {
	.poulton-gp-seal-turn {
		animation: poulton-seal-turn 60s linear infinite;
	}
}
@keyframes poulton-seal-turn {
	to {
		rotate: 360deg;
	}
}
/* The For GPs page header carries the same fan beside its title (the
 * synced block content/blocks/gp-fan.html, so the two are one). Smaller
 * than on the home band — a page header's picture supports the title, it
 * does not compete with it — and stacked on a phone the title stays
 * first: the h1 is what the page is. */
.poulton-pagehead-band .poulton-gp-fan {
	max-width: 440px;
}
@media (max-width: 781px) {
	.poulton-pagehead-columns {
		row-gap: 36px;
	}
	.poulton-pagehead-band .poulton-gp-fan {
		max-width: 320px;
	}
}
/* ---------- The header figures ----------
 * The paper-plane boy in a page header's right column: on Contact with a
 * phone in one hand and a letter held out in the other, on Downloads at a
 * laptop holding up a page with the download mark, on Publications at his
 * books with a paper in hand, on the sheets hub with a sheet in hand and
 * a butterfly to watch (uploads, content/media/*-figure.webp). Sized by
 * HEIGHT, to the band: the header bands are one height across
 * Publications, the sheets hub, Downloads and Contact — a kicker, a title
 * and a two-line lede between the band's padding, which is 220px of
 * content at 1440 — and a picture given its own height made a band half
 * as tall again. At 220px the drawings are 280–410px wide and the bands
 * match within a few pixels at every width (where the lede is one line
 * the picture, not the words, sets the row). On a phone, where the
 * columns stack, a drawing sits under the text at up to 320px wide — the
 * fan's phone width — on the text's left edge, as the For GPs header puts
 * its fan. Same pencil, same ink token (inkMask, optimize-images.mjs), so
 * his drawings are one hand. */
.poulton-pagehead-figure {
	margin: 0;
	height: 220px;
	display: flex;
	justify-content: center;
}
.poulton-pagehead-figure img {
	display: block;
	height: 100%;
	width: auto;
	max-width: 100%;
	object-fit: contain;
}
@media (max-width: 781px) {
	.poulton-pagehead-figure {
		display: block;
		height: auto;
		max-width: 320px;
	}
	.poulton-pagehead-figure img {
		height: auto;
		width: 100%;
	}
}

/* ---------- The lost figure ----------
 * The paper-plane boy (blocks/lost-figure): the 404 page's picture, beside
 * the title in the GP header's columns, and a small one above the sentence
 * on every empty state. Ink on alpha, so he sits on the sand wash with no
 * frame — the sheet figures' hairline-and-tint treatment is for artwork on
 * white paper, and this one has no paper. The header size is the fan's
 * (above), for the same reason: a page header's picture supports the
 * title, it does not compete with it. */
.poulton-lost-figure {
	margin: 0;
}
.poulton-lost-figure img {
	display: block;
	width: 100%;
	height: auto;
}
.poulton-lost-figure--header {
	max-width: 440px;
	margin-inline: auto;
}
.poulton-lost-figure--small {
	max-width: 180px;
	margin-bottom: var(--wp--preset--spacing--40);
}
/* Stacked on a phone the boy leads and the title follows — the home band's
 * order (below), not the GP page header's (above), on purpose. There the h1
 * is what the page is; here the page is a dead end, and the picture is what
 * says so before the reader has parsed a word (the Headspace / Charma
 * stack). He is kept small so the h1 is still on the first screen. Under
 * the list, where the columns would put him unswapped, he read as an
 * afterthought — the band's finding. `order`, not column-reverse, for the
 * reason at .poulton-hero-columns. */
@media (max-width: 781px) {
	.error404 .poulton-pagehead-columns {
		row-gap: 28px;
	}
	.error404 .poulton-pagehead-columns > .wp-block-column:first-child {
		order: 2;
	}
	.error404 .poulton-pagehead-columns > .wp-block-column:last-child {
		order: 1;
	}
	.poulton-lost-figure--header {
		max-width: 220px;
		margin-inline: 0;
	}
}

/* Stacked: the fan leads and the words follow, as the home hero's books
 * do — swapped with `order` for the reason given at .poulton-hero-columns.
 * The fan is the band's picture; under the text it read as an afterthought
 * the reader had already scrolled past. */
@media (max-width: 781px) {
	.poulton-gp-columns {
		row-gap: 28px;
	}
	.poulton-gp-columns > .wp-block-column:first-child {
		order: 2;
	}
	.poulton-gp-columns > .wp-block-column:last-child {
		order: 1;
	}
	.poulton-gp-fan {
		max-width: 320px;
	}
}

/* ---------- Cards ----------
 * Cards sit inside modules; these rules follow the module block above.
 */
.poulton-card {
	border-radius: var(--wp--custom--radius--card);
	display: flex;
	flex-direction: column;
	gap: 10px;
}
.poulton-card a:not(.wp-block-button__link):not(.poulton-readmore) {
	color: var(--wp--preset--color--primary);
}
.poulton-card .wp-block-post-title a {
	color: var(--wp--preset--color--primary-dark);
	text-decoration: none;
}
.poulton-card .wp-block-post-title a:hover {
	color: var(--wp--preset--color--primary);
}
/* Actions sit on the baseline of every card in a row, whatever the excerpt length.
 * Keep the markup free of an inline margin-top here — it would beat `auto`. */
.poulton-card .poulton-card-actions {
	margin-top: auto;
	padding-top: 6px;
}
.poulton-card .wp-block-post-title {
	margin-block: 2px 0;
}
.poulton-card .wp-block-post-excerpt {
	margin-block: 0;
}
.poulton-card .wp-block-post-excerpt__more-text {
	display: none;
}
/* Raised card: the tile recipe (white, hairline, soft shadow) at card scale,
 * for static content on a white section — the About projects. No hover: a
 * lift on a card that goes nowhere is the stated anti-pattern. The number
 * chips flip to surface here; base + hairline is for chips ON a surface. */
.poulton-card--raised {
	background: var(--wp--custom--surface--raised);
	border: 1px solid var(--wp--preset--color--line);
	box-shadow: var(--wp--custom--shadow--card);
}
.poulton-card--raised ol.wp-block-list > li::before {
	background: var(--wp--preset--color--surface);
	border-color: transparent;
}
/* The About research cards: a left-to-right ramp of the blue. Card one is
 * the surface token by attribute; two and three take custom tokens by class
 * because core writes the preset background with !important and a custom
 * token has no preset class. Derived from surface and primary-light, not
 * new hexes — the same reasoning as sandSoft. Ink on the deepest step is
 * about 8:1. */
.poulton-card--mid {
	background: var(--wp--custom--surface--blue-mid);
}
.poulton-card--deep {
	background: var(--wp--custom--surface--blue-deep);
}
/* Icon chip above a card heading: a 40px square in the dl-icon / chip
 * family, holding a 20px Lucide stroke icon (pasted from `npm run icon`,
 * inside a core/html block — the only way an inline SVG gets into content).
 * Decorative, so the wrapper is aria-hidden in the markup. */
.poulton-card-icon {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: 40px;
	height: 40px;
	border-radius: 12px;
	background: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--line);
	color: var(--wp--preset--color--primary);
}
/* Surface on surface: on a tinted card the chip's fill is the card's own, so
 * only the hairline separated them and the icon sat in a ghost of a box. White
 * gives it an edge to stand on. Same trade, and the same reason, as
 * `.poulton-module .poulton-pill` above. Raised cards keep the tinted chip —
 * there the card is white and the tint is what reads. */
.poulton-card.has-surface-background-color .poulton-card-icon {
	background: var(--wp--custom--surface--raised);
}
/* The card's own gap is enough between chip and heading; drop the layout
 * block-gap margin the group puts on every child after the first. */
.poulton-card-icon + .wp-block-heading,
.poulton-card-photo + .wp-block-heading {
	margin-block-start: 0;
}
/* A photograph capping a card, in place of the icon chip. The 16:9 and the
 * cover fit are the block's own attributes (core writes them inline), and so
 * is the radius — theme.json rounds every image to 14px and core's inline
 * style is the only thing that beats it. What is left is the width: core
 * gives an unaligned image max-width but not width, so without this it sits
 * at its intrinsic size instead of filling the card. */
.poulton-card-photo {
	margin: 0;
}
.poulton-card-photo img {
	display: block;
	width: 100%;
}

/* ---------- Biography portrait ----------
 * The source is 500x692, head to waist. Everywhere it shows it is cropped
 * to a square: on desktop a rounded square at the column's width, on a
 * phone a 112px circle (stacked, the column goes full width and the
 * uncropped photo ran ~340x470 — a screenful before the name).
 *
 * Anchored to the top, not centred: the top of her hair is about 25px in,
 * so a centred crop cuts the head. A top-anchored square of this source
 * ends just under the neckline, which is the framing wanted.
 *
 * !important on the phone radius only: core writes the block's 20px
 * corner as an inline style on the <img>, and nothing else beats that. */
.poulton-portrait img {
	width: 100%;
	aspect-ratio: 1;
	object-fit: cover;
	object-position: 50% 0;
}
@media (max-width: 781px) {
	.poulton-portrait img {
		width: 112px;
		height: 112px;
		border-radius: 50% !important;
	}
}

.poulton-hairline-card {
	background: var(--wp--preset--color--base);
	border: 1px solid rgba(226, 232, 238, 0.9);
	border-radius: var(--wp--custom--radius--card);
	box-shadow: var(--wp--custom--shadow--card);
	transition: transform 0.28s ease, box-shadow 0.28s ease;
}
.poulton-hairline-card:hover {
	transform: translateY(-2px);
	box-shadow: var(--wp--custom--shadow--lift);
}
/* The v3 scale pushed xx-large to 32px, which is a section heading, not a card
 * title. Core emits preset font sizes with !important, so this has to match. */
.poulton-hairline-card .wp-block-post-title {
	font-size: 21px !important;
	line-height: 1.25;
	letter-spacing: -0.015em;
}
.poulton-hairline-card .wp-block-post-title a {
	color: var(--wp--preset--color--primary-dark);
	text-decoration: none;
}
.poulton-hairline-card .wp-block-post-title a:hover {
	color: var(--wp--preset--color--primary);
}

/* Typographic document cover (fallback when a sheet has no cover image) */
.poulton-doc-cover {
	aspect-ratio: 3 / 4;
	border-radius: var(--wp--custom--radius--image);
	background: var(--wp--preset--color--surface);
	display: flex;
	align-items: center;
	justify-content: center;
	font-family: var(--wp--preset--font-family--heading);
	font-size: 84px;
	font-weight: 350;
	color: var(--wp--preset--color--primary);
	line-height: 1;
}

/* ---------- Breadcrumbs ----------
 * The path to a single sheet, publication or blog post: ancestors as plain
 * links, chevrons between them, and on a sheet one inert last item — the
 * sheet's number. Nothing in the row is filled or bordered. The last step
 * used to be a white pill, and a pill in a line of text links reads as the one
 * thing that can be clicked, when it was the one thing that couldn't.
 *
 * The page's own title is never in the row — it is the H1 directly beneath.
 *
 * The type is the pill's (11px/500) rather than the kicker's uppercase
 * treatment: uppercase at this size competes with the H1 immediately under
 * it. Links are `primary`, not the label grey, because they are links — and
 * the grey is set at the threshold for non-link text on the module surface
 * (see .poulton-kicker), with no headroom left to spend on a link affordance.
 */
.poulton-crumbs-list {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	/* Row gap for the wrap on a phone: "Home > Explanation Sheets > Explanation
	 * Sheet 1" is about 300px at this size, so it fits 375px unwrapped. */
	gap: 2px 6px;
	margin: 0;
	padding: 0;
	list-style: none;
}
.poulton-crumbs-list li {
	display: flex;
	align-items: center;
	gap: 6px;
}
/* padding-block on 11px/1.5 text makes the target 24.5px tall — clear of
 * SC 2.5.8's 24px. The inert item carries the same padding so every item in
 * the row shares one box and one centre line. */
.poulton-crumbs-link,
.poulton-crumbs-current {
	display: inline-block;
	padding-block: 4px;
	font-size: 11px;
	font-weight: 500;
	line-height: 1.5;
	letter-spacing: 0.01em;
}
.poulton-crumbs-link {
	color: var(--wp--preset--color--primary);
	text-decoration: none;
}
.poulton-crumbs-link:hover,
.poulton-crumbs-link:focus-visible {
	text-decoration: underline;
}
/* Where you are: the label grey, so it is visibly not a link. It is normal-
 * size text for contrast purposes and the grey measures 4.66:1 on the
 * surface — it passes, with nothing to spare; do not lighten it. */
.poulton-crumbs-current {
	color: var(--wp--custom--label--color);
}
/* aria-hidden, so this is decoration and not text — but it sits between two
 * pieces of type at the same size, and anything lighter than the label grey
 * reads as a rendering fault rather than a separator. */
.poulton-crumbs-sep {
	color: var(--wp--custom--label--color);
	font-size: 11px;
	line-height: 1;
}

/* ---------- Pill / tab ----------
 * One label component site-wide (sheet number, category, publication type).
 * Size, type and colour are defined here and nowhere else. Two shapes:
 *   - in a page header it is this rounded pill, in flow;
 *   - on a card it becomes a TAB hanging from the card's top edge: a hanging
 *     tag, square at the top, sides slanting slightly inward, rounded at the
 *     bottom, with a hairline outline on the sides and bottom only (the top
 *     sits on the card's edge). The shape lives on a ::before pseudo-element
 *     tilted in perspective (rotateX about its top edge) so the border and
 *     bottom radius follow the slant natively; the text on the <p> itself is
 *     untransformed. Two placements: the CORNER tab (every card on the tile
 *     recipe — sheets, publications, blog) is absolute, inset from the right
 *     a little more than the card's padding; the ROW tab (Downloads — a wide
 *     flex row with a button at the far right) is a flex item in the slot
 *     after the text column, so it fills the empty run between text and
 *     button and lands where the text ends. Below 782px the row stacks and it
 *     too is a corner tab.
 * The background is routed through --pill-bg so the context overrides
 * (`.poulton-module`, `.poulton-tile`) reach the pseudo, and the outline is
 * mixed from it so a white tab gets a matching pale outline.
 * A card that carries a corner tab reserves 44px of headroom (the tab is
 * ~25px) so a title's first line can never run under it. */
.poulton-pill {
	--pill-bg: var(--wp--preset--color--surface);
	display: inline-block;
	background: var(--pill-bg);
	color: var(--wp--preset--color--primary);
	border-radius: var(--wp--custom--radius--pill);
	padding: 4px 12px;
	font-size: 11px;
	font-weight: 500;
	line-height: 1.5;
	letter-spacing: 0.01em;
	width: fit-content;
}
/* The tab shape. Each card is position: relative. The <p> is a transparent,
 * un-rounded host; isolation keeps the z-index:-1 pseudo inside the pill
 * rather than behind the card's background. */
.poulton-tile > .poulton-tile-text > .poulton-pill,
.poulton-tile > .poulton-tile-text > .poulton-pill-tabs > .poulton-pill,
.poulton-dl-tile > .poulton-pill {
	margin: 0;
	background: transparent;
	border-radius: 0;
	isolation: isolate;
}
.poulton-tile > .poulton-tile-text > .poulton-pill::before,
.poulton-tile > .poulton-tile-text > .poulton-pill-tabs > .poulton-pill::before,
.poulton-dl-tile > .poulton-pill::before {
	content: "";
	position: absolute;
	inset: 0 0 -1px; /* the tilt foreshortens the height by about a pixel */
	z-index: -1;
	background: var(--pill-bg);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--primary) 14%, var(--pill-bg));
	border-top: 0; /* no outline where it meets the card edge */
	border-radius: 0 0 10px 10px;
	transform-origin: 50% 0;
	transform: perspective(80px) rotateX(-8deg);
}
/* Corner tab. */
.poulton-tile > .poulton-tile-text > .poulton-pill {
	position: absolute;
	top: 0;
	right: 24px;
}
/* A publication card hangs up to two tabs, one per topic
 * (poulton_topic_pills): the row takes the corner and each tab is its own
 * tab shape. The row never wraps and never stacks — a second row ate the
 * headroom and a stack read as a different card — so a card too narrow for
 * both drops the second tab instead (the container query at
 * .poulton-tile--pub, which knows the card's width where a viewport query
 * cannot: the same card is two-up in the hub, three-up in the Related row
 * and alone on a phone). */
.poulton-tile > .poulton-tile-text > .poulton-pill-tabs {
	position: absolute;
	top: 0;
	right: 24px;
	display: flex;
	flex-wrap: nowrap;
	justify-content: flex-end;
	gap: 0 8px;
}
.poulton-tile > .poulton-tile-text > .poulton-pill-tabs > .poulton-pill {
	position: relative;
	flex: none;
}

/* Row tab: a flex item hanging from the top edge. The negative margin equals
 * the tile's inline padding-top (18px, in the block markup). */
.poulton-dl-tile > .poulton-pill {
	position: relative;
	align-self: flex-start;
	margin-top: -18px;
}
@media (max-width: 782px) {
	/* Stacked: a wrapped flex item with a negative top margin would climb into
	 * the line above, and the title is now the first thing at the top edge.
	 * Corner tab plus headroom; !important because the padding is inline. */
	.poulton-dl-tile > .poulton-pill {
		position: absolute;
		top: 0;
		right: 24px;
		margin: 0;
	}
	.poulton-dl-tile:has(> .poulton-pill) {
		padding-top: 44px !important;
	}
}

.poulton-pill,
.poulton-pill a,
.wp-block-post-terms a {
	text-decoration: none;
}
.poulton-pill a:hover,
.wp-block-post-terms a:hover {
	text-decoration: none;
	opacity: 0.8;
}

/* ---------- Buttons ----------
 * Filled, outlined and read-more must share one box model, or cards show
 * mismatched pill sizes. Every variant: 15px text, same padding, 1.5px border.
 */
.wp-block-button__link,
.poulton-readmore,
.wp-block-search__button {
	font-size: 15px;
	font-weight: 500;
	line-height: 1.45;
	letter-spacing: 0;
	border-radius: var(--wp--custom--radius--pill);
	border: 1.5px solid transparent;
	padding: 11px 26px;
	text-decoration: none;
	display: inline-block;
	transition: background 0.22s ease, color 0.22s ease, border-color 0.22s ease;
}
/* Two sizes site-wide. Size follows the block's own font-size control rather
 * than a style variation, so it composes with outline/accent/arrow — block
 * style variations are single-select and couldn't stack with those. */
.wp-block-button.has-small-font-size .wp-block-button__link,
.poulton-readmore.has-small-font-size {
	padding: 8px 18px;
}
.wp-block-button.has-small-font-size .wp-block-button__link {
	/* the preset class sits on the outer div; the inner anchor needs it too */
	font-size: var(--wp--preset--font-size--small);
}

/* Secondary treatment, matching .is-style-outline exactly — read-more is an
 * anchor rather than a button block, so it can't carry the style class. */
.poulton-readmore {
	background: var(--wp--preset--color--base);
	border-color: rgba(226, 232, 238, 0.9);
	color: var(--wp--preset--color--primary-dark);
	transition: color 0.22s ease, border-color 0.22s ease;
}
.poulton-readmore:hover {
	border-color: var(--wp--preset--color--primary-light);
	color: var(--wp--preset--color--primary);
}
/* A text link, not a pill — the third action in a publications row */
.poulton-readmore-quiet {
	font-size: 14px;
	font-weight: 500;
	color: var(--wp--preset--color--primary);
	text-decoration: none;
}
.poulton-readmore-quiet:hover {
	color: var(--wp--preset--color--primary-dark);
	text-decoration: underline;
}

/* Highlight: the deep clay, white ink. The one warm button in the system —
 * used for the book CTA, the sheet downloads and the homepage's Explanation
 * Sheets action. (The nav pill's Get in touch is NOT this: it takes the plain
 * blue button default.) */
.wp-block-button.is-style-highlight .wp-block-button__link {
	background: var(--wp--preset--color--highlight);
	color: var(--wp--preset--color--base);
}
.wp-block-button.is-style-highlight .wp-block-button__link:hover {
	background: var(--wp--custom--highlight--hover);
	color: var(--wp--preset--color--base);
}

/* Listen: the narration's play button (blocks/listen). The same box as every
 * button above — 15px/500, the same padding and 1.5px border — in the
 * highlight colours, because on a sheet it is now the primary action and the
 * PDF has stepped back to the outline beside it. It is a <button> (or, before
 * view.js runs, an <a> with the same class), so the box model is restated
 * rather than inherited from .wp-block-button__link, which core scopes to its
 * own block. inline-flex puts the icon, the words and "· 14 min" on one line;
 * the words change with state ("Pause · 8 min left") at close to the same
 * length, so the row does not reflow under the pointer. */
.poulton-listen__cta {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	font: inherit;
	font-size: 15px;
	font-weight: 500;
	line-height: 1.45;
	letter-spacing: 0;
	border-radius: var(--wp--custom--radius--pill);
	border: 1.5px solid transparent;
	padding: 11px 26px 11px 22px;
	text-decoration: none;
	cursor: pointer;
	background: var(--wp--preset--color--highlight);
	color: var(--wp--preset--color--base);
	transition: background 0.22s ease, color 0.22s ease, border-color 0.22s ease;
}
.poulton-listen__cta:hover {
	background: var(--wp--custom--highlight--hover);
	color: var(--wp--preset--color--base);
}
.poulton-listen__cta:disabled {
	cursor: default;
	opacity: 0.6;
}
/* An author `display` beats the UA sheet's [hidden] — same as .poulton-share. */
.poulton-listen [hidden] {
	display: none !important;
}
.poulton-listen__icon {
	flex: none;
}
.poulton-listen__icon--pause,
.poulton-listen.is-playing .poulton-listen__icon:not(.poulton-listen__icon--pause) {
	display: none;
}
.poulton-listen.is-playing .poulton-listen__icon--pause {
	display: block;
}
/* Lighter by weight only: white at any opacity on the clay drops below 4.5:1
 * (Lighthouse measured 4.13 at 0.85), while solid white reads 7.3:1. */
.poulton-listen__meta {
	font-weight: 400;
}
/* Visually hidden, kept for assistive tech: the note that the voice is
 * synthetic. Core's block library references .screen-reader-text but this
 * theme never defined it, so the block carries its own. */
.poulton-sr,
.poulton-listen__sr,
.poulton-search__sr {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}
/* Secondary: white fill, neutral hairline, navy ink. Still core's `outline`
 * slot — registering a separate `secondary` style would leave core's own
 * unstyled Outline sitting next to it in the editor. Flat: the drop shadow read
 * as a raised card next to the flat primary and highlight buttons, so the hover
 * affordance is the border tint darkening with the ink. */
.wp-block-button.is-style-outline .wp-block-button__link {
	background: var(--wp--preset--color--base);
	border-color: rgba(226, 232, 238, 0.9);
	color: var(--wp--preset--color--primary-dark);
	transition: background 0.22s ease, color 0.22s ease, border-color 0.22s ease;
}
.wp-block-button.is-style-outline .wp-block-button__link:hover {
	border-color: var(--wp--preset--color--primary-light);
	color: var(--wp--preset--color--primary);
}

/* Tertiary: a plain text link. No fill, no border — the third rung below the
 * filled primary and the white secondary. Keeps vertical padding so the target
 * still clears WCAG 2.2's 24px minimum. */
.wp-block-button.is-style-tertiary .wp-block-button__link {
	background: transparent;
	border-color: transparent;
	box-shadow: none;
	color: var(--wp--preset--color--primary);
	padding: 8px 4px;
}
.wp-block-button.is-style-tertiary .wp-block-button__link:hover {
	background: transparent;
	color: var(--wp--preset--color--primary-dark);
	/* a non-colour-only affordance alongside the darkening */
	text-decoration: underline;
}

/* White pill with a dark arrow chip */
.wp-block-button.is-style-arrow .wp-block-button__link {
	display: inline-flex;
	align-items: center;
	gap: 14px;
	padding: 7px 7px 7px 26px;
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--primary-dark);
	border-color: rgba(226, 232, 238, 0.9);
	box-shadow: var(--wp--custom--shadow--card);
}
.wp-block-button.is-style-arrow .wp-block-button__link::after {
	content: "";
	width: 34px;
	height: 34px;
	border-radius: 50%;
	flex: none;
	background: var(--wp--preset--color--primary-dark) var(--poulton-arrow-icon) center / 15px no-repeat;
	transition: transform 0.22s ease;
}
.wp-block-button.is-style-arrow .wp-block-button__link:hover::after {
	transform: translateX(3px);
}

/* ---------- Pagination ----------
 * Core's query pagination arrives as bare links. The numbers are 44px round
 * chips in the nav links' vocabulary — ghost at rest, their wash on hover —
 * and the current page wears the nav's own "you are here" chip (surface
 * tint, primary, medium): both carry aria-current="page", so the site says
 * "current" one way. Previous and Next are the arrow button's navy chip at
 * target size, icon only; core writes the label as aria-label on the link
 * when it is hidden, so the name is kept, and the glyph it prints is
 * aria-hidden and replaced by the site's own arrow. */
.wp-block-query-pagination {
	align-items: center;
	flex-wrap: wrap;
	gap: 8px;
	margin-top: var(--wp--preset--spacing--60);
	font-size: 15px;
	font-weight: 500;
}
.wp-block-query-pagination-numbers {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 4px;
}
.wp-block-query-pagination .page-numbers {
	box-sizing: border-box;
	display: grid;
	place-items: center;
	min-width: 44px;
	height: 44px;
	padding: 0 8px;
	border-radius: var(--wp--custom--radius--pill);
	color: var(--wp--preset--color--primary-dark);
	text-decoration: none;
	transition: background-color 120ms ease, color 120ms ease;
}
.wp-block-query-pagination a.page-numbers:hover {
	background: rgba(1, 87, 155, 0.06);
	color: var(--wp--preset--color--primary);
}
.wp-block-query-pagination .page-numbers.current {
	background: var(--wp--custom--surface--module);
	color: var(--wp--preset--color--primary);
}
.wp-block-query-pagination .page-numbers.dots {
	min-width: 24px;
	padding: 0;
	color: var(--wp--preset--color--muted);
}
/* The arrow chip from .is-style-arrow above, grown to a 44px target. The
 * link's only visible content is its background; its name is the aria-label.
 * rotate/translate are the individual properties so they compose — and
 * translation applies outermost, so the turned Previous still needs its own
 * sign to nudge the way it points. */
.wp-block-query-pagination-previous,
.wp-block-query-pagination-next {
	display: block;
	width: 44px;
	height: 44px;
	margin: 0;
	border-radius: 50%;
	background: var(--wp--preset--color--primary-dark) var(--poulton-arrow-icon) center / 16px no-repeat;
	transition: translate 0.22s ease;
}
.wp-block-query-pagination-previous {
	rotate: 180deg; /* the site draws one arrow; Previous is it, turned */
}
.wp-block-query-pagination-next:hover {
	translate: 3px 0;
}
.wp-block-query-pagination-previous:hover {
	translate: -3px 0;
}
/* Core shows the glyph at 0,2,0 (.wp-block-query-pagination .…-arrow), so
 * this has to out-specific it rather than rely on order. */
.wp-block-query-pagination .wp-block-query-pagination-previous > .wp-block-query-pagination-previous-arrow,
.wp-block-query-pagination .wp-block-query-pagination-next > .wp-block-query-pagination-next-arrow {
	display: none;
}
@media (max-width: 480px) {
	.wp-block-query-pagination .page-numbers {
		min-width: 40px;
		height: 40px;
	}
	.wp-block-query-pagination-previous,
	.wp-block-query-pagination-next {
		width: 40px;
		height: 40px;
	}
}

/* Panel prose: left-aligned in a default-layout group, so a max-width here
 * caps the measure without re-centring (no auto margins involved). */
.poulton-panel > p,
.poulton-panel > .wp-block-heading {
	max-width: 46rem;
}

/* ---------- Carousel dots ----------
 * One control, shared by every rail that pages horizontally: the endorsement
 * quotes in the book module and the explanation-sheet cards on phones. Both
 * build it in JavaScript (assets/js/rail-dots.js), so a reader without it
 * gets the underlying content in order and no controls that do nothing.
 *
 * It lives here, above both consumers, because it is a component rather than
 * part of either rail. It used to sit inside the endorsement rail's section
 * with the sheets' overrides a thousand lines EARLIER in the file — they won
 * on specificity alone, which is not an ordering anyone should have to
 * reconstruct. */
.poulton-rail-dots {
	display: flex;
	/* No gap, and that is the spacing decision rather than the absence of one.
	 * Each button is 24px around a 6px dot, so the buttons sit edge to edge at
	 * a 24px pitch and their own empty space sets the rhythm — 18px between
	 * the visible dots. Anything tighter has to overlap the buttons, and an
	 * overlapped target is one WCAG 2.5.8 counts as obscured: the rule
	 * measures the unobstructed box, so 6px of overlap turned a 24x24 target
	 * into 18x24 and failed the audit on every page carrying dots. A flex gap
	 * in the other direction pushed them 28px apart, which read as separate
	 * controls rather than one group. */
	gap: 0;
	justify-content: center;
	/* The endorsement rail's arrows make the row 32px; the 24px dots centre
	 * in it rather than hanging from its top. */
	align-items: center;
	/* Set by the context, not the component: how far the dots sit from what
	 * they page depends on whether that thing is a card, a strip of cards or
	 * a quote with its own padding. */
	margin-top: var(--rail-dots-space, 16px);
}
.poulton-rail-dot {
	/* box-sizing is not global here, and a <button> takes it from the UA sheet
	 * — the same trap .poulton-share__btn documents. Without it the padding
	 * and border below would land outside the 24px and the target would drift
	 * off the WCAG 2.5.8 floor it is set to hit exactly. */
	box-sizing: border-box;
	width: 24px;
	height: 24px;
	padding: 0;
	border: 0;
	background: none;
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
}
.poulton-rail-dot::before {
	content: "";
	/* 6px, not the 8px this started at: six dots under a card at 8px read as a
	 * control strip competing with the card, and two at 6px still read as a
	 * pair. The target stays 24px either way — only the mark shrinks. */
	width: 6px;
	height: 6px;
	border-radius: 50%;
	/* A dot is a control, so it needs 3:1 against what it sits on (WCAG
	 * 1.4.11) — and what it sits on is the module's tint, not the white card
	 * above it. That sets the floor on how faint the inactive dot can be:
	 * primary at 0.7 composites to 3.47:1, and 0.6 would be 2.83:1 and fail.
	 * primary-light, the obvious pick, is 2.17:1 even at full opacity. */
	background: var(--wp--preset--color--primary);
	opacity: 0.7;
	transition: background-color 0.2s ease, opacity 0.2s ease, transform 0.2s ease;
}
.poulton-rail-dot:hover::before {
	opacity: 1;
}
.poulton-rail-dot[aria-current]::before {
	background: var(--wp--preset--color--primary-dark);
	opacity: 1;
	transform: scale(1.15);
}
/* Previous / next, either side of the dots on the endorsement rail. Two 6px
 * dots were the only visible control and the audit's readers never found the
 * second quote. Same 3:1 floor as the dots (WCAG 1.4.11): primary at full
 * opacity on the module tint. quote-rail.js creates them; they are hidden
 * once the track becomes a swipeable scroller (≤700px), where the cards
 * themselves show there is more. */
.poulton-rail-arrow {
	box-sizing: border-box;
	width: 32px;
	height: 32px;
	padding: 0;
	border: 1px solid var(--wp--preset--color--primary);
	border-radius: 50%;
	background: none;
	color: var(--wp--preset--color--primary);
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: center;
	/* 24px pitch between the dots; a little more before the arrow. */
	margin-inline: 8px;
}
.poulton-rail-arrow svg {
	width: 16px;
	height: 16px;
	stroke: currentColor;
	fill: none;
	stroke-width: 2;
	stroke-linecap: round;
	stroke-linejoin: round;
}
.poulton-rail-arrow:hover {
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--base);
}
.poulton-rail-arrow:focus-visible {
	outline: 3px solid var(--wp--preset--color--primary);
	outline-offset: 2px;
}
/* On a phone the track is a scroller and takes focus itself (quote-rail.js
 * sets tabindex only then), so it needs the site's ring; the arrows go. */
.poulton-rail-track:focus-visible {
	outline: 3px solid var(--wp--preset--color--primary);
	outline-offset: 4px;
}
@media (max-width: 700px) {
	.poulton-rail-arrow {
		display: none;
	}
}

/* ---------- Stat cards ---------- */
.poulton-stat {
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	gap: 40px;
	min-height: 230px;
	padding: 28px;
	border-radius: var(--wp--custom--radius--card);
	background: var(--wp--preset--color--surface);
}
.poulton-stat-label {
	margin: 0;
	font-size: 15px;
	line-height: 1.45;
	color: var(--wp--preset--color--muted);
}
.poulton-stat-figure {
	margin: 0;
	font-size: clamp(40px, 6vw, 60px);
	font-weight: 400;
	line-height: 1;
	letter-spacing: -0.03em;
	color: var(--wp--preset--color--primary-dark);
}

/* ---------- Hero book animation ----------
 * The still covers are the loading state: real artwork from first paint, laid
 * out at the 3D rest pose's footprint (measured identical at 1280px). The
 * container has a fixed aspect, so the canvas arriving causes no layout
 * shift. .is-3d — added by the module only after its first frame is drawn —
 * swaps the canvas in for the still in a single frame, no fade (see the note
 * on the shadow below). .is-static (reduced motion, no WebGL, a texture that failed) only
 * records that no canvas is coming; the stills need no rule for it.
 *
 * There is deliberately no separate placeholder. The one this replaced was a
 * blue book-shaped skeleton with a shimmer, and it had two failure modes:
 * twice it went invisible against the gradient (the trap in CLAUDE.md), and
 * when it was visible it read as a solid-blue flash for as long as Three.js
 * took to arrive — the real picture was underneath it the whole time. */
.poulton-hero-books {
	position: relative;
	width: 100%;
	aspect-ratio: 10 / 9;
	max-height: 460px;
	overflow: hidden;
	/* Decorative (role="img"), and on phones it is pulled over its neighbours
	 * by the negative margins below — a transparent corner of it must never
	 * take a click or swallow a text selection. */
	pointer-events: none;
}
.poulton-hero-books--small {
	max-height: 320px;
}
.poulton-hero-books--large {
	max-height: 600px;
}
.poulton-hero-books canvas,
.poulton-sheet-cover canvas {
	position: absolute;
	inset: 0;
	width: 100% !important;
	height: 100% !important;
	display: block;
	opacity: 0;
}
.poulton-hero-books.is-3d canvas,
.poulton-sheet-cover.is-3d canvas {
	opacity: 1;
}
/* Placement for the still layer comes from the custom properties render.php
 * writes per cover, so one to four covers all lay out correctly. */
.poulton-hero-books-fallback img,
.poulton-sheet-cover-fallback img {
	position: absolute;
	top: 50%;
	left: 50%;
	display: block;
	width: var(--pltn-w, 29%);
	z-index: var(--pltn-z, 1);
	transform: translate(-50%, -50%) translate(var(--pltn-x, 0%), var(--pltn-y, 0%)) rotateY(var(--pltn-r, 0deg));
	height: auto;
	border-radius: 3px;
}

/* The still layer, visible by default: the loading state, the reduced-motion
 * / no-WebGL / no-JS picture, and the editor preview. Nothing invented, so the
 * placeholder-contrast trap cannot recur here. Its perspective makes it its
 * own stacking context, so --pltn-z on the images cannot climb above the
 * canvas, which is appended after it and paints on top. */
.poulton-hero-books-fallback,
.poulton-sheet-cover-fallback {
	position: absolute;
	inset: 0;
	perspective: 1200px;
	opacity: 1;
}
/* The baked still (bundled composition only): one image of the rest pose,
 * cropped to the camera's fit box, so object-fit: contain lands it exactly
 * where the canvas draws the books at any frame shape — the same rule the
 * camera applies, see resize() in hero-books.js. Overrides the per-cover
 * placement above, which is for the flat covers. */
.poulton-hero-books-fallback img.poulton-hero-books-baked {
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	object-fit: contain;
	transform: none;
	border-radius: 0;
	z-index: auto;
}
/* The sheet's baked still: same idea, one image of the booklet's rest pose
 * cropped to that camera's fit box. */
.poulton-sheet-cover-fallback img.poulton-sheet-cover-baked {
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	object-fit: contain;
	transform: none;
	border-radius: 0;
	z-index: auto;
}
/* The swap is instant, and deliberately has no transition on either layer.
 * The still IS the canvas's first frame (baked from it), so there is nothing
 * for a fade to hide — and a fade of any length does harm here. The books are
 * opaque, so the canvas covers the still and an overlap shows nothing; the
 * shadow under them is an 11%-transparent material, and for as long as both
 * layers are on screen two shadows composite on top of each other. Measured
 * with the previous 0.4s fade, the shadow's darkest point went from 217 to
 * 196 and snapped back to 216 when the still dropped: a near-doubling, then
 * a jump, and it read as a glitch. Both layers now flip in the same style
 * recalc, so at no moment is the shadow drawn twice. */
.poulton-hero-books.is-3d .poulton-hero-books-fallback,
.poulton-sheet-cover.is-3d .poulton-sheet-cover-fallback {
	opacity: 0;
}

/* ---------- Sheet hero: the opening cover ----------
 * Desktop only. Below the rail breakpoint the container has no box at all and
 * render.php's <picture> resolves to a 1px data URI, so nothing is fetched;
 * the hero is exactly what it was before the block existed.
 *
 * Above it the band becomes a grid whose second column is the index rail's
 * footprint (rail + gap). That makes the first column exactly the article's
 * text column, and core's own auto margins then centre the 900px text group
 * on it — the same sum .poulton-article and the .poulton-readcol rule below
 * do, so hero title and article text share a left edge at every width by
 * construction. No column-gap: it would push the text off that edge. The text
 * group therefore does NOT carry .poulton-readcol (it would be shifted twice).
 * A sheet with too few headings for an index (sheet 03) still reserves the
 * column on the article side (toc.php), so the edge holds there too. */
.poulton-sheet-cover {
	display: none;
}
@media (min-width: 1080px) {
	.poulton-sheet-hero {
		display: grid;
		grid-template-columns: minmax(0, 1fr) calc(var(--poulton-toc-rail) + var(--poulton-toc-gap));
		align-items: center;
	}
	.poulton-sheet-hero > .poulton-sheet-hero-text {
		grid-column: 1;
	}
	/* Selector is (0,2,0) on purpose: core's constrained-layout rules for
	 * direct children set max-width and auto inline margins with !important
	 * at (0,1,0), and this box has to sit outside its column.
	 *
	 * The frame has to be wide enough for the open cover's sweep, so at rest
	 * the booklet occupies less than half of it. Left in the rail's column the
	 * booklet would therefore drift away from the title as the viewport grew —
	 * the text keeps its measure, and all the extra width turns into empty
	 * frame between them. So the frame is pulled left by the slack either
	 * side of that measure, less a fixed step, which holds the booklet about
	 * the same distance from the text at every width. Its own width is
	 * capped, or the dead space would just grow back inside it.
	 *
	 * The slack is the viewport less everything the row already holds: the
	 * measure, the rail's footprint and the band's 48px of padding — spelt
	 * out from the tokens, so it moves with the measure.
	 *
	 * pointer-events: none because the pulled frame overlaps the text column
	 * and is decorative — an invisible transparent corner of it must never
	 * take the click meant for the Download button. */
	.poulton-sheet-hero > .poulton-sheet-cover {
		--pltn-overhang: max(
			0px,
			(
					100vw - var(--wp--style--global--content-size) - var(--poulton-toc-rail) -
						var(--poulton-toc-gap) - 48px
				) / 2 - 24px
		);
		display: block;
		position: relative;
		pointer-events: none;
		grid-column: 2;
		justify-self: start;
		/* Portrait, like the booklet: a frame near square is mostly empty
		 * either side of it, and that emptiness is what reads as a gap. Wide
		 * enough for the cover to swing open without clipping, and no wider.
		 * The camera fits to the frame's height, so the ratio and the cap
		 * together set how big the booklet renders. */
		width: clamp(190px, 18vw, 240px);
		aspect-ratio: 3 / 5;
		max-height: 380px;
		max-width: none !important;
		margin-left: calc(-1 * var(--pltn-overhang)) !important;
		margin-right: 0 !important;
		margin-block: 0 !important;
		overflow: hidden;
	}
}

@media (max-width: 781px) {
	/* Stacked, the hero is roughly twice as tall, so the shared ramp's 90% white
	 * point would hold colour down most of a phone screen. Same tokens as
	 * hero-sky, stops compressed to resolve by ~58%. (The old copy also existed
	 * to keep the navy covers off mid-blue — that reason went with the pale
	 * gradient; the height one is what remains.) */
	.poulton-hero {
		background-image:
			radial-gradient(90% 34% at 24% 30%, color-mix(in srgb, var(--wp--preset--color--base) 70%, transparent) 0%, transparent 66%),
			linear-gradient(
				180deg,
				color-mix(in srgb, var(--wp--preset--color--primary-light) 62%, var(--wp--preset--color--base)) 0%,
				color-mix(in srgb, var(--wp--preset--color--primary-light) 52%, var(--wp--preset--color--base)) 14%,
				color-mix(in srgb, var(--wp--preset--color--primary-light) 26%, var(--wp--preset--color--base)) 34%,
				var(--wp--preset--color--base) 60%
			);
	}
	.poulton-hero-books {
		/* One shape for every phone. The frame used to keep 4/3 only until a
		 * height cap bit, so from ~500px up it went wider and wider (2.4:1 at
		 * 781px) — the camera moved in to fit, the composition touched the top
		 * of the frame, and the baked still (rendered at one camera distance)
		 * could no longer coincide with the canvas. Capping the width instead
		 * keeps the aspect, and with it the camera distance, constant across
		 * the whole phone range, so one phone bake is exact everywhere. */
		aspect-ratio: 4 / 3;
		max-width: 400px;
		margin-inline: auto;
		/* The frame is sized for the composition's widest moment — the books
		 * spread out and the pile turning — so at rest it carries transparent
		 * margin above and below them: measured at 390px, 49px above and 33px
		 * below. Stacked on a phone that lands on top of the section's own
		 * padding and the column gap, which is why the hero read as mostly
		 * empty blue — 101px between the nav pill and the books, 61px between
		 * the books and the heading, about double what the design intends.
		 *
		 * Take the frame's own slack back rather than trimming the section, so
		 * the books keep their size and the page keeps its rhythm. Asymmetric
		 * because the slack is: the composition sits above centre. That leaves
		 * ~51px and ~31px. The slack scales with the frame, so these hold
		 * across the phone range without cutting into the section's padding.
		 *
		 * Its own selector, and !important, because the frame is the only
		 * child of its column and core's flow layout zeroes margin-block on a
		 * first and last child — set plainly above, these compute to 0. */
	}
	.wp-block-column > .poulton-hero-books {
		margin-block-start: -50px !important;
		margin-block-end: -30px !important;
	}
	/* The single book (the book page) is taller than the 4/3 frame is, so its
	 * fit is height-governed and the slack is a tenth of the frame above and
	 * below — nothing like the trio's. The trio's values would drag it under
	 * the nav pill. Measured at 390px, as the trio's were: with these, the
	 * book's top edge sits ~46px under the pill and its shadow ends ~22px
	 * above the kicker. */
	.wp-block-column > .poulton-hero-books--preset-book {
		margin-block-start: -16px !important;
		margin-block-end: -12px !important;
	}
	.poulton-hero-books--small {
		max-width: 320px;
	}
	.poulton-hero-books--large {
		max-width: 506px;
	}
	/* Stacked hero: the books lead, the words follow. Reordering with `order`
	 * rather than column-reverse — core forces flex-wrap:wrap on
	 * .wp-block-columns below 782px, and a reversed column direction wraps
	 * unpredictably against it. */
	.poulton-hero-columns {
		row-gap: 28px;
	}
	.poulton-hero-columns > .wp-block-column:first-child {
		order: 2;
	}
	.poulton-hero-columns > .wp-block-column:last-child {
		order: 1;
	}
}

/* The card rail's dots. Everything about how they look is the shared Carousel
 * dots component above; all that belongs here is where they appear. They only
 * mean something on the phone strip — above that breakpoint the cards are a
 * two-column grid with nothing to page through — so they are hidden here and
 * shown in the media query. */
.poulton-tiles .poulton-rail-dots {
	display: none;
	/* Tighter to the cards than the endorsement rail's, which stands alone in
	 * its own section. Six dots under a card want to read as its footer. */
	--rail-dots-space: 12px;
}

/* ---------- Explanation-sheet tiles ----------
 * Cover-led tiles replacing the index rows: no description at all, since the
 * legacy excerpts (25-40 words) were what made the rows tall and ragged. */
.poulton-tiles .wp-block-post-template {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 24px;
	margin: 0;
	padding: 0;
	list-style: none;
}
.poulton-tiles .wp-block-post {
	display: flex;
	margin: 0;
}
.poulton-tile {
	/* fill the grid cell in both axes so every tile in a row matches */
	flex: 1 1 auto;
	display: flex;
	flex-direction: row;
	align-items: stretch;
	gap: 20px;
	height: 100%;
	padding: 20px;
	border-radius: var(--wp--custom--radius--card);
	/* White at rest with the standard hairline: the tile sits on the warm band
	 * (home, About) AND on the white sheets page, where a borderless white
	 * card would vanish. */
	background: var(--wp--preset--color--base);
	border: 1px solid rgba(226, 232, 238, 0.9);
	/* The whole tile is the link now (see .poulton-tile-title a::after): one
	 * destination, the sheet page, since the View PDF link left the card. This
	 * is the containing block for that stretched anchor. */
	position: relative;
	transition: transform 0.28s ease, box-shadow 0.28s ease;
}
/* Desktop only: a lift on hover. The card IS clickable, so the affordance is
 * honest — the v3.27 reason for removing it no longer holds. Gated on a real
 * pointer so the phone scroller stays flat. The resting card shadow, not
 * --shadow--lift: at this tile size the lift read as a slab. */
@media (hover: hover) and (pointer: fine) {
	.poulton-tile:hover {
		transform: translateY(-2px);
		box-shadow: var(--wp--custom--shadow--card);
	}
	.poulton-tile:hover .poulton-tile-title a {
		color: var(--wp--preset--color--primary);
	}

	/* ---------- Edge glow (desktop) ----------
	 * A port of React Bits' BorderGlow. assets/js/card-glow.js marks each
	 * clickable tile `has-glow`, appends the halo span, and keeps two custom
	 * properties current from the pointer: --edge-proximity (0 at the centre,
	 * 100 on an edge) and --cursor-angle (clockwise from the top). Three
	 * layers read them: a mesh-gradient ring on the card's own hairline, a
	 * faint edge fill, and an outer halo, all masked to a cone facing the
	 * cursor. Colours come from custom.glow in theme.json (primary-light for
	 * the light and the mesh, surface for the fill) through color-mix, in
	 * place of the component's HSL strings. Same gate as the lift above, so
	 * touch devices never carry the layers. */
	.poulton-tile.has-glow {
		/* The palette, as three local properties so a variant can swap the set
		 * in one rule (the GP cards below). Defaults are the site's blue. */
		--glow-color: var(--wp--custom--glow--color);
		--glow-fill: var(--wp--custom--glow--fill);
		--glow-accent: var(--wp--custom--glow--accent);
		--edge-proximity: 0;
		--cursor-angle: 45deg;
		/* Where the layers start, as edge proximity (0 centre, 100 edge). The
		 * component's 30/50 meant nothing showed until the last fifth of the
		 * card; these open the band so the light comes up from mid-card. */
		--edge-sensitivity: 12;
		--color-sensitivity: 30;
		--cone-spread: 25;
		/* Strength caps for the three layers at a full edge — subtle by brief. */
		--glow-strength: 0.55;
		--mesh-strength: 0.7;
		--fill-strength: 0.18;
		--glow-100: var(--glow-color);
		--glow-60: color-mix(in srgb, var(--glow-color) 60%, transparent);
		--glow-50: color-mix(in srgb, var(--glow-color) 50%, transparent);
		--glow-40: color-mix(in srgb, var(--glow-color) 40%, transparent);
		--glow-30: color-mix(in srgb, var(--glow-color) 30%, transparent);
		--glow-20: color-mix(in srgb, var(--glow-color) 20%, transparent);
		--glow-10: color-mix(in srgb, var(--glow-color) 10%, transparent);
		/* the component's three mesh colours, from the token */
		--mesh-a: var(--glow-color);
		--mesh-b: color-mix(in srgb, var(--glow-color) 55%, var(--wp--preset--color--base));
		--mesh-c: color-mix(in srgb, var(--glow-accent) 55%, var(--glow-color));
		/* its seven radial positions with its 0,1,2,0,1,2,1 colour map */
		--mesh-one: radial-gradient(at 80% 55%, var(--mesh-a) 0px, transparent 50%);
		--mesh-two: radial-gradient(at 69% 34%, var(--mesh-b) 0px, transparent 50%);
		--mesh-three: radial-gradient(at 8% 6%, var(--mesh-c) 0px, transparent 50%);
		--mesh-four: radial-gradient(at 41% 38%, var(--mesh-a) 0px, transparent 50%);
		--mesh-five: radial-gradient(at 86% 85%, var(--mesh-b) 0px, transparent 50%);
		--mesh-six: radial-gradient(at 82% 18%, var(--mesh-c) 0px, transparent 50%);
		--mesh-seven: radial-gradient(at 51% 4%, var(--mesh-b) 0px, transparent 50%);
		--mesh-base: linear-gradient(var(--mesh-a) 0 100%);
		/* the negative-z layers must paint above the card's own white, not
		 * behind the card — the component relies on the same isolation */
		isolation: isolate;
	}
	/* GP-topic cards: the tab is lilac (data-topic, inc/block-bindings.php),
	 * so the glow follows it into the violet set. Keyed on the same attribute
	 * as the tab, so the two can never disagree — and on the topic, not series
	 * membership, so the research about GPs is in as well. Glow only: title
	 * and pill hovers stay the site's blue. */
	.poulton-tile.has-glow:has(.poulton-pill[data-topic="gp-led-adhd-care"]) {
		--glow-color: var(--wp--custom--glow--gp--color);
		--glow-fill: var(--wp--custom--glow--gp--fill);
		--glow-accent: var(--wp--custom--glow--gp--accent);
	}
	.poulton-tile.has-glow::before,
	.poulton-tile.has-glow::after,
	.poulton-tile.has-glow > .poulton-tile-glow {
		content: "";
		position: absolute;
		/* on the card's hairline, so the mesh ring replaces it inside the cone */
		inset: -1px;
		border-radius: inherit;
		z-index: -1;
		pointer-events: none;
		transition: opacity 0.25s ease-out;
	}
	.poulton-tile.has-glow:not(:hover)::before,
	.poulton-tile.has-glow:not(:hover)::after,
	.poulton-tile.has-glow:not(:hover) > .poulton-tile-glow {
		opacity: 0;
		transition: opacity 0.75s ease-in-out;
	}
	/* mesh-gradient ring, in the cone facing the cursor */
	.poulton-tile.has-glow::before {
		border: 1px solid transparent;
		background:
			linear-gradient(var(--wp--preset--color--base) 0 100%) padding-box,
			var(--mesh-one) border-box,
			var(--mesh-two) border-box,
			var(--mesh-three) border-box,
			var(--mesh-four) border-box,
			var(--mesh-five) border-box,
			var(--mesh-six) border-box,
			var(--mesh-seven) border-box,
			var(--mesh-base) border-box;
		opacity: calc(var(--mesh-strength) * (var(--edge-proximity) - var(--color-sensitivity)) / (100 - var(--color-sensitivity)));
		-webkit-mask-image: conic-gradient(from var(--cursor-angle) at center, black calc(var(--cone-spread) * 1%), transparent calc((var(--cone-spread) + 15) * 1%), transparent calc((100 - var(--cone-spread) - 15) * 1%), black calc((100 - var(--cone-spread)) * 1%));
		mask-image: conic-gradient(from var(--cursor-angle) at center, black calc(var(--cone-spread) * 1%), transparent calc((var(--cone-spread) + 15) * 1%), transparent calc((100 - var(--cone-spread) - 15) * 1%), black calc((100 - var(--cone-spread)) * 1%));
	}
	/* edge fill: a whisper of surface near the lit edge. The component's
	 * light-surface variant blends normal, not soft-light — soft-light over
	 * white does nothing. Kept faint so navy text near an edge keeps its
	 * contrast. */
	.poulton-tile.has-glow::after {
		border: 1px solid transparent;
		background:
			var(--mesh-one) padding-box,
			var(--mesh-two) padding-box,
			var(--mesh-three) padding-box,
			var(--mesh-four) padding-box,
			var(--mesh-five) padding-box,
			var(--mesh-six) padding-box,
			var(--mesh-seven) padding-box,
			linear-gradient(var(--glow-fill) 0 100%) padding-box;
		-webkit-mask-image:
			linear-gradient(to bottom, black, black),
			radial-gradient(ellipse at 50% 50%, black 40%, transparent 65%),
			radial-gradient(ellipse at 66% 66%, black 5%, transparent 40%),
			radial-gradient(ellipse at 33% 33%, black 5%, transparent 40%),
			radial-gradient(ellipse at 66% 33%, black 5%, transparent 40%),
			radial-gradient(ellipse at 33% 66%, black 5%, transparent 40%),
			conic-gradient(from var(--cursor-angle) at center, transparent 5%, black 15%, black 85%, transparent 95%);
		mask-image:
			linear-gradient(to bottom, black, black),
			radial-gradient(ellipse at 50% 50%, black 40%, transparent 65%),
			radial-gradient(ellipse at 66% 66%, black 5%, transparent 40%),
			radial-gradient(ellipse at 33% 33%, black 5%, transparent 40%),
			radial-gradient(ellipse at 66% 33%, black 5%, transparent 40%),
			radial-gradient(ellipse at 33% 66%, black 5%, transparent 40%),
			conic-gradient(from var(--cursor-angle) at center, transparent 5%, black 15%, black 85%, transparent 95%);
		-webkit-mask-composite: source-out, source-over, source-over, source-over, source-over, source-over;
		mask-composite: subtract, add, add, add, add, add;
		opacity: calc(var(--fill-strength) * (var(--edge-proximity) - var(--color-sensitivity)) / (100 - var(--color-sensitivity)));
	}
	/* outer halo: sized to the gutter (custom.glow.radius = the grid gap), so
	 * it never reaches the neighbouring card */
	.poulton-tile.has-glow > .poulton-tile-glow {
		inset: calc(-1 * var(--wp--custom--glow--radius));
		z-index: 1;
		opacity: calc(var(--glow-strength) * (var(--edge-proximity) - var(--edge-sensitivity)) / (100 - var(--edge-sensitivity)));
		-webkit-mask-image: conic-gradient(from var(--cursor-angle) at center, black 2.5%, transparent 10%, transparent 90%, black 97.5%);
		mask-image: conic-gradient(from var(--cursor-angle) at center, black 2.5%, transparent 10%, transparent 90%, black 97.5%);
	}
	.poulton-tile.has-glow > .poulton-tile-glow::before {
		content: "";
		position: absolute;
		inset: var(--wp--custom--glow--radius);
		border-radius: inherit;
		/* the component's ladder, its outset reach scaled from 50px to the
		 * 24px radius the halo is allowed */
		box-shadow:
			inset 0 0 0 1px var(--glow-100),
			inset 0 0 1px 0 var(--glow-60),
			inset 0 0 3px 0 var(--glow-50),
			inset 0 0 6px 0 var(--glow-40),
			inset 0 0 12px 0 var(--glow-30),
			inset 0 0 18px 1px var(--glow-20),
			inset 0 0 24px 1px var(--glow-10),
			0 0 1px 0 var(--glow-60),
			0 0 3px 0 var(--glow-50),
			0 0 6px 0 var(--glow-40),
			0 0 10px 0 var(--glow-30),
			0 0 16px 1px var(--glow-20),
			0 0 24px 1px var(--glow-10);
	}
}
/* Keyboard: ring the tile, not the inline title text under the stretched
 * anchor. */
.poulton-tile:has(.poulton-tile-title a:focus-visible) {
	outline: 3px solid var(--wp--preset--color--primary);
	outline-offset: 2px;
}
.poulton-tile .poulton-tile-title a:focus-visible {
	outline: none;
}
/* The tab's tint is restated because `.poulton-module .poulton-pill` paints
 * pills white for tint-on-tint — but these tiles are white cards ON the band,
 * so a white tab vanished there (home, About). Same specificity; this is later.
 * Shape and position come from the pill component rules. */
.poulton-tile .poulton-pill {
	--pill-bg: var(--wp--preset--color--surface);
}
/* The GP-led ADHD care topic wears the GP series' lilac wherever it is a
 * pill — the card tab, the hero — so the audience colour reads across the
 * site. The tab shape paints --pill-bg, so the token does the work. Stated
 * after the tile rule above at the same weight, so it wins on the card. */
.poulton-pill[data-topic="gp-led-adhd-care"],
.poulton-tile .poulton-pill[data-topic="gp-led-adhd-care"] {
	--pill-bg: var(--wp--preset--color--lilac);
}
.poulton-pill--soft[data-topic="gp-led-adhd-care"] {
	background: var(--wp--preset--color--lilac);
	border-color: var(--wp--preset--color--lilac-line);
}
/* …except on the lilac band itself, where lilac-on-lilac would vanish:
 * there the pill stays the white it was. */
.has-lilac-background-color .poulton-pill--soft[data-topic="gp-led-adhd-care"] {
	background: var(--wp--preset--color--base);
	border-color: var(--wp--preset--color--line);
}
/* Spacing here is the flex gap above. Core's flow-layout margin would land on
 * the text column, and a flex item with a block margin does not stretch — it
 * gets pushed down and bottom-anchored, which is what made the card look
 * top-heavy with the buttons jammed against the bottom edge. */
.poulton-tile > * {
	margin-block: 0;
}
.poulton-tile-cover {
	flex: 0 0 124px;
	align-self: flex-start;
	margin: 0;
}
.poulton-tile-cover img {
	width: 100%;
	height: auto;
	border-radius: 8px;
	display: block;
}
/* The loading state for the flat cover only: the booklet still that
 * replaces it is transparent with its own shadow, and a tint behind it
 * would show. */
.poulton-tile-cover img:not(.poulton-tile-still) {
	background: var(--wp--preset--color--surface);
}
/* The booklet still (plugin: inc/sheet-tiles.php swaps it in for the flat
 * cover at render time). It is transparent with its own shadow, so no
 * radius; and it is the frame the hover canvas draws into, so the canvas
 * covers it exactly and the two are exchanged with no transition — any
 * overlap would draw the semi-transparent shadow twice (the lesson from the
 * hero). A little wider than the flat cover's box, because the booklet sits
 * inside its frame with room for its shadow and the cover's sweep. */
.poulton-tile-cover img.poulton-tile-still {
	border-radius: 0;
}
.poulton-tile-cover canvas {
	/* Hidden by visibility, not display: the canvas has to be laid out while
	 * hidden so its first frame can be drawn at the right size BEFORE the
	 * swap reveals it. display: none would give it no box, the draw would
	 * find nothing to size to, and the swap would show an empty frame. */
	visibility: hidden;
	pointer-events: none; /* the card is one stretched link; the canvas must never take the click */
}
.poulton-tile-cover.is-3d canvas {
	visibility: visible;
}
.poulton-tile-cover.is-3d img {
	visibility: hidden;
}
/* Desktop: the figure keeps a fixed layout box, and the picture — still and
 * canvas alike, the same frame — is taller than it (3:5 against the box's
 * ~3:4), centred on it, overhanging into the card's own padding above and
 * below. The open cover's top corner swings toward the camera and projects
 * higher than the resting booklet; without this headroom it was cut off at
 * the frame's top edge, and the alternative — a taller box — would have
 * grown the card. The overhang is ~20px, inside the card's 20px padding, and
 * the frame's corners are transparent, so nothing meets the card's edge. */
@media (min-width: 701px) {
	.poulton-tile-cover:has(.poulton-tile-still) {
		flex-basis: 132px;
		aspect-ratio: 600 / 818;
		position: relative;
	}
	.poulton-tile-cover img.poulton-tile-still,
	.poulton-tile-cover canvas {
		position: absolute;
		left: 0;
		top: 50%;
		width: 100%;
		height: auto;
		aspect-ratio: 600 / 1000;
		transform: translateY(-50%);
	}
}
.poulton-tile-text {
	flex: 1 1 auto;
	min-width: 0;
	display: flex;
	flex-direction: column;
	/* top-aligned, not centred: the actions row takes the spare height */
	justify-content: flex-start;
	gap: 8px;
}
/* Text-only variant (blog, archive, search): no cover, so the text column is
 * the whole card. */
.poulton-tile--text {
	flex-direction: column;
}
/* Publication cards: a small square cover at the left — a licensed figure,
 * the paper's first page, or a journal-name tile (bake-pub-covers.mjs). One
 * frame for all three, so the list reads as a list and not a scrapbook. The
 * square is fixed and the text column takes the rest; at phone width the
 * row holds rather than stacking, because 72px beside the text costs less
 * than a full-width image above it 25 times over. */
.poulton-tile--pub {
	align-items: flex-start;
	/* The card is the query container for its own topic tabs. It is already
	 * the containing block for the tab row and the stretched title link, so
	 * the layout containment this brings changes nothing; and every card
	 * sits in a sized cell (the hub grid's minmax(0, 1fr) through a flex
	 * <li>, the Related grid, the phone rail's flex-basis), so inline-size
	 * containment cannot collapse it. */
	container-type: inline-size;
	container-name: pub-tile;
}
/* Two tabs need one row of the TEXT column, not of the card — the row is
 * right-anchored and would otherwise run left over the cover. The column
 * is the card less 40px padding, the cover and the 20px gap; the longest
 * pair (ADHD services and policy + Stimulant dosing and growth) is ~300px
 * plus the 8px gap, so it needs the card at 472px with the 96px cover and
 * 448px with the 72px one. One threshold, the larger. Below it the second
 * tab goes and the first — ~170px at most — has the column to itself.
 * Re-measure if a topic is renamed or the cover size changes. */
@container pub-tile (max-width: 471px) {
	.poulton-pill-tabs > .poulton-pill:nth-child(2) {
		display: none;
	}
}
.poulton-pub-cover {
	flex: none;
	width: 96px;
	margin: 0;
}
.poulton-pub-cover img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 1;
	object-fit: cover;
	border-radius: 8px;
	border: 1px solid var(--wp--preset--color--line);
	/* The loading state: a cover that has not arrived is a soft surface
	 * square in its frame, not white. Width and height are set on the
	 * image, so nothing moves when it lands. */
	background: var(--wp--preset--color--surface);
}
@media (max-width: 599px) {
	.poulton-tile--pub {
		gap: 14px;
	}
	.poulton-pub-cover {
		width: 72px;
	}
}
/* ---------- The foot of a publication page ----------
 * Source box → share → related row → previous/next. The related row is the
 * hub card three-up at the wide size — the same card, so the page ends in the
 * component the reader arrived through — and the list itself is the small
 * link in the row's heading rather than a bare "← All publications" line. */
/* A note that carries a heading is a box, not an aside: its text takes the
 * column rather than the 72ch advisory measure, and the rows breathe.
 * row-gap rather than margins, because the note zeroes its children's
 * margins (core's blockGap never reaches them). The single-paragraph notes
 * — the sheet template's, the Explanation Sheets page's — have no heading
 * and keep the aside treatment. */
.wp-block-group[class*="is-style-note-"]:has(> h2, > h3) {
	row-gap: 10px;
}
.wp-block-group[class*="is-style-note-"]:has(> h2, > h3) > * {
	max-width: none;
}
.wp-block-group[class*="is-style-note-"]:has(> h2, > h3) > .wp-block-buttons {
	margin-block-start: 12px;
}
.poulton-source-title {
	margin: 0;
}
/* The note style is a two-column grid — icon track, then text — built for a
 * one-paragraph note. This box has four children, and auto-placement would
 * drop every second one into the 28px icon track. All of them belong in
 * the text column. The track also grows to its widest unbreakable content,
 * so a DOI in the citation would push every sibling past the box on a
 * phone: let the citation break anywhere rather than widen the track. */
.poulton-source > * {
	grid-column: 2;
	min-width: 0;
	overflow-wrap: anywhere;
}
/* Every button in the source box is the white outline: the box is already a
 * tinted panel, and a filled primary inside it competed with the page's own
 * call to action in the hero. Which button is first no longer changes its
 * weight. Stated at this weight because the note style colours every link
 * in its ink. */
.wp-block-group.is-style-note-info.poulton-source .wp-block-button__link {
	background: var(--wp--preset--color--base);
	border-color: rgba(226, 232, 238, 0.9);
	color: var(--wp--preset--color--primary-dark);
	transition: background 0.22s ease, color 0.22s ease, border-color 0.22s ease;
}
.wp-block-group.is-style-note-info.poulton-source .wp-block-button__link:hover {
	border-color: var(--wp--preset--color--primary-light);
	color: var(--wp--preset--color--primary);
}
/* --- the Publications hub's filters (blocks/publication-filters) ---------
 * A caption ("Filter by topic"), a row of chips, then a status line. The chip is the site's
 * pill at a pressable size — a button, with aria-pressed the only state;
 * `fchip`, because `.poulton-chip` is the tray's Back-to-top / Listen chip —
 * and the pressed one is the pill inverted. Nothing here animates: a card
 * hidden by a filter is hidden, and one that returns is simply there. */
.poulton-filters {
	margin-top: var(--wp--preset--spacing--40);
	display: grid;
	gap: 12px;
}
.poulton-filters-row {
	display: grid;
	row-gap: 6px;
}
/* Above the chips, not beside them: the caption names what the chips ARE
 * (the topic taxonomy), and above is where a reader's eye meets it first —
 * the pattern the reference filter sheets use. Same voice as the kickers. */
.poulton-filters-label {
	color: var(--wp--custom--label--color);
	font-size: 11.5px;
	font-weight: 600;
	line-height: 1.4;
	letter-spacing: 0.1em;
	text-transform: uppercase;
}
.poulton-filters-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}
.poulton-fchip {
	appearance: none;
	display: inline-flex;
	align-items: baseline;
	gap: 6px;
	margin: 0;
	padding: 6px 14px;
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--primary-dark);
	border: 1px solid rgba(226, 232, 238, 0.9);
	border-radius: var(--wp--custom--radius--pill);
	font: inherit;
	font-size: 13px;
	font-weight: 500;
	line-height: 1.5;
	cursor: pointer;
	transition: border-color 0.18s ease, color 0.18s ease, background 0.18s ease;
}
.poulton-fchip:hover {
	border-color: var(--wp--preset--color--primary-light);
	color: var(--wp--preset--color--primary);
}
.poulton-fchip:focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 2px;
}
.poulton-fchip[aria-pressed="true"] {
	background: var(--wp--preset--color--primary);
	border-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--base);
}
.poulton-fchip-count {
	font-size: 12px;
	font-weight: 400;
	color: var(--wp--preset--color--muted);
}
/* Not primary-light: #7FA8D9 on the pressed chip's primary is 2.99:1 at 12px,
 * the one contrast failure axe found on the site (WCAG 1.4.3 wants 4.5). The
 * base ink at 85% is ~5.9:1 and still reads as the quieter of the two. */
.poulton-fchip[aria-pressed="true"] .poulton-fchip-count {
	color: var(--wp--preset--color--base);
	opacity: 0.85;
}
.poulton-filters-status {
	margin: 2px 0 0;
	font-size: 14px;
	line-height: 1.5;
	color: var(--wp--preset--color--muted);
}
.poulton-filters-status a {
	color: var(--wp--preset--color--primary);
}
/* A card the filter has hidden. The li is display:flex by the tile recipe,
 * and an author display beats the hidden attribute's UA one — so said again
 * here at the weight the recipe cannot tie. */
.poulton-tiles .wp-block-post[hidden] {
	display: none !important;
}
/* The strip pins under the nav pill while the list scrolls — 27 cards, and
 * the row was gone after two of them. Same offset and layer as the article's
 * "On this page" strip (.poulton-toc): the pill's bottom edge sits 16px
 * inside --nav-clear, and 20 keeps it under the header (30) and over the
 * cards. It sticks only for its section, because the section is its
 * containing block. view.js adds is-stuck from a sentinel — CSS has no
 * :stuck — and that class is the compact state: the status out of the way
 * (it stays in the tree, still a live region), the caption kept, the chips
 * a step smaller, on a white panel with a hairline so cards passing beneath
 * do not bleed through. A rectangle with softened corners, not a pill: two
 * lines of content in a pill read as a blob. 14px sits between the figure
 * (8) and image (18) radii; the chips inside are the pills. The gradient
 * above and below is the toc strip's, so the cards fade out under it rather
 * than being cut. */
.poulton-filters {
	position: sticky;
	top: calc(var(--wp--custom--shell--nav-clear) - 16px);
	z-index: 20;
}
.poulton-filters.is-stuck::before {
	content: "";
	position: absolute;
	left: -24px;
	right: -24px;
	top: -22px;
	bottom: -14px;
	background: linear-gradient(
		rgba(255, 255, 255, 0),
		var(--wp--preset--color--base) 22%,
		var(--wp--preset--color--base) 95%,
		rgba(255, 255, 255, 0)
	);
	pointer-events: none;
	z-index: -1;
}
.poulton-filters.is-stuck .poulton-filters-row {
	padding: 8px 10px 10px;
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: 14px;
	box-shadow: 0 1px 2px rgba(6, 32, 62, 0.05),
		0 4px 10px -6px rgba(6, 32, 62, 0.16);
}
.poulton-filters.is-stuck .poulton-filters-status {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}
.poulton-filters.is-stuck .poulton-fchip {
	padding: 4px 12px;
}
/* On a phone the seven chips would wrap to three rows. Instead — pinned or
 * not — they are one line that scrolls sideways, the sheet rail's recipe,
 * bleeding to the screen edge so the last chip in view is cut by it. The cue
 * that there is more is YouTube's: a chevron on a solid white strip at the
 * edge, the cut chip fading into the strip beside it. A fade alone was tried
 * first and read as a dimmed chip, not as "more". The chevrons are buttons
 * (view.js builds them) that page the row; the left one appears once the
 * row has scrolled and the right one leaves at the end, so what is shown
 * always says what a tap will do. The chips are buttons too, so the
 * scroller has focusable content and needs no tabindex of its own; the 3px
 * of padding is room for the focus ring. */
.poulton-filters-arrow {
	display: none;
}
@media (max-width: 600px) {
	.poulton-filters-row {
		position: relative;
	}
	.poulton-filters-chips {
		/* Not global in this theme: without it the gutter padding below is
		 * added outside the width and the row pushes the layout viewport
		 * wider than the phone — the page zooms out. */
		box-sizing: border-box;
		flex-wrap: nowrap;
		overflow-x: auto;
		/* No scroll-snap, unlike the card rails: chips are short, a snap
		 * point every 100px adds nothing to a thumb, and it fought the
		 * keyboard — a focused chip scrolled clear of the edge was pulled
		 * back under it by the nearest snap. */
		-webkit-overflow-scrolling: touch;
		overscroll-behavior-x: contain;
		scrollbar-width: none;
		width: calc(100% + 48px);
		margin: -3px -24px;
		padding: 3px 24px;
	}
	.poulton-filters-chips::-webkit-scrollbar {
		display: none;
	}
	.poulton-fchip {
		flex: 0 0 auto;
	}
	/* The strip and its chevron. Absolutely placed over the chips line —
	 * the last 40px of the grid row, so the caption above stays clear — at
	 * the row's bleed edge. The strip's ground is the page's white, which is
	 * also the pinned panel's; the chip fades into it over the first third. */
	.poulton-filters-arrow {
		display: flex;
		align-items: center;
		justify-content: flex-end;
		position: absolute;
		bottom: -3px;
		height: 40px;
		width: 64px;
		padding: 0 12px 0 0;
		margin: 0;
		border: 0;
		background: linear-gradient(to right, rgba(255, 255, 255, 0), var(--wp--preset--color--base) 38%);
		cursor: pointer;
		z-index: 1;
	}
	.poulton-filters-arrow--next {
		right: -24px;
	}
	.poulton-filters-arrow--prev {
		left: -24px;
		justify-content: flex-start;
		padding: 0 0 0 12px;
		background: linear-gradient(to left, rgba(255, 255, 255, 0), var(--wp--preset--color--base) 38%);
	}
	.poulton-filters-arrow[hidden] {
		display: none;
	}
	/* A bare chevron on the white safe area, as YouTube draws it — no ring:
	 * the strip is the button and the ring read as a second control. Drawn
	 * on a span so the strip can be the whole hit area; the span is what the
	 * focus ring goes round. */
	.poulton-filters-arrow__glyph {
		box-sizing: border-box;
		width: 32px;
		height: 32px;
		border-radius: 8px;
		color: var(--wp--preset--color--primary-dark);
		display: flex;
		align-items: center;
		justify-content: center;
	}
	.poulton-filters-arrow__glyph svg {
		width: 22px;
		height: 22px;
		stroke: currentColor;
		fill: none;
		stroke-width: 2;
		stroke-linecap: round;
		stroke-linejoin: round;
	}
	.poulton-filters-arrow:hover .poulton-filters-arrow__glyph {
		color: var(--wp--preset--color--primary);
	}
	.poulton-filters-arrow:focus-visible {
		outline: none;
	}
	.poulton-filters-arrow:focus-visible .poulton-filters-arrow__glyph {
		outline: 3px solid var(--wp--preset--color--primary);
		outline-offset: 0;
	}
	/* Inside the pinned panel the row runs to the panel's own edge instead
	 * of the screen's: its padding is the gutter there, and the chips are a
	 * step smaller, so the arrows move in and shrink with them. */
	.poulton-filters.is-stuck .poulton-filters-chips {
		width: calc(100% + 20px);
		margin: -3px -10px;
		padding: 3px 10px;
	}
	.poulton-filters.is-stuck .poulton-filters-arrow {
		height: 36px;
		width: 56px;
		/* The panel's 10px of bottom padding sits between the chips line and
		 * the box the arrow is placed against; without this it hung 10px
		 * below the chips, off the grid the chips set. */
		bottom: 7px;
	}
	/* The chips there bleed only to the panel's padding edge, which is the
	 * row's own box: the arrows sit at 0, not out past the border. */
	.poulton-filters.is-stuck .poulton-filters-arrow--next {
		right: 0;
	}
	.poulton-filters.is-stuck .poulton-filters-arrow--prev {
		left: 0;
	}
}
/* Where the list lands when a chip is chosen while the strip is pinned:
 * its top under the strip, not under the pill. */
.poulton-filters + .wp-block-query .wp-block-post-template {
	scroll-margin-top: calc(var(--wp--custom--shell--nav-clear) + 78px);
}
/* The tools box under a paper's text (blocks/paper-tools). The tiles are
 * the Downloads page's — same classes, same type — but drawn in PHP, so the
 * flex that core generates per Query Loop tile is stated here instead. */
.poulton-paper-tools {
	margin-top: var(--wp--preset--spacing--70);
}
/* A module heading — the size of "More for GPs" below it. */
.poulton-paper-tools-title {
	margin: 0 0 6px;
	font-size: var(--wp--preset--font-size--x-large);
}
.poulton-paper-tools-lead {
	margin: 0 0 18px;
	color: var(--wp--preset--color--muted);
}
.poulton-paper-tools-list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 12px;
}
/* The tile a paper's text sent the reader to ("Appendix 2" → #tool-…):
 * the references' landing treatment, on a card — a ring of the surface
 * tint and the light-blue edge, until the hash changes. */
.poulton-paper-tools .poulton-dl-tile:target {
	border-color: var(--wp--preset--color--primary-light);
	box-shadow: 0 0 0 4px var(--wp--preset--color--surface);
}
.poulton-paper-tools .poulton-dl-tile {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 16px;
	padding: 18px 20px;
}
.poulton-paper-tools .poulton-dl-tile > .wp-block-group > * + * {
	margin-top: 2px;
}
.poulton-paper-tools .wp-block-buttons {
	/* core's buttons layout, which the Query Loop tiles get for free: the
	 * same flex, wrap and gap (theme.json, core/buttons) */
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
}
/* "Used in AJGP 2026 · JPCH 2024" under a tool's description on the tiles. */
.poulton-dl-used {
	margin: 4px 0 0;
	font-size: 13px;
	line-height: 1.5;
	color: var(--wp--preset--color--muted);
}
.poulton-dl-used a {
	color: var(--wp--preset--color--primary);
	text-decoration: none;
}
.poulton-dl-used a:hover {
	text-decoration: underline;
}
.poulton-related {
	margin-top: var(--wp--preset--spacing--70);
}
.poulton-related-head {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 8px 20px;
	margin-bottom: 20px;
}
.poulton-related-title {
	margin: 0;
	font-size: var(--wp--preset--font-size--x-large);
}
.poulton-related-all {
	font-weight: 600;
	text-decoration: none;
	white-space: nowrap;
}
.poulton-related-all:hover {
	text-decoration: underline;
}
.poulton-related-list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 20px;
}
/* The card is one <a> only in the hub (the title link is stretched by
 * .poulton-tile-title a::after); here the same rule applies because the
 * markup is the same, so the whole card is the link there too. */
.poulton-tile--related {
	position: relative;
	width: auto;
	/* The tile's height: 100% was written for the hub, where a flex <li>
	 * wraps it. Here the tile IS the grid item, and 100% of a row sized
	 * from its content box left every card its padding taller than its
	 * row — painting over the next one on a phone. Auto; the grid's
	 * stretch keeps a row's cards level at three-up. */
	height: auto;
}
.poulton-tile--related .poulton-pub-cover {
	width: 72px;
}
.poulton-tile--related .poulton-tile-title {
	font-size: 16px;
}
.poulton-tile--related .poulton-tile-meta {
	margin: 0;
	color: var(--wp--preset--color--muted);
}
@media (max-width: 900px) {
	.poulton-related-list {
		grid-template-columns: 1fr;
	}
}
/* A reproduced paper's reference list: present, because the licence asks for
 * the work to be complete and a reader may want it, but folded — thirty
 * citations are the longest thing on the page and the least read. Core's
 * details block, so it opens without JavaScript. */
/* In-text citations: a superscript of linked numbers, one style whether the
 * source wrote [13] or <sup>13</sup> (inc/citations.php). line-height 0 so
 * a citation never opens the line it sits on; the padding is the hit area. */
.poulton-cites {
	font-size: 0.72em;
	line-height: 0;
	vertical-align: baseline;
	position: relative;
	top: -0.55em;
	white-space: nowrap;
}
/* ---------- Prose links ----------
 * A link in running text — "Appendix 2" in a paper, a link in a sheet's
 * paragraph — kept the browser's own underline, a 1px line in the full
 * link colour on the baseline, and read as the one untouched default on
 * a set page. Still blue, still underlined (the affordance is the point),
 * but drawn: a thin line in a tint of the link colour, set a little
 * below the baseline with the descenders skipped, that fills to the full
 * colour on hover; the word a half-step heavier than the body so it holds
 * its own in the line. The scope is the classless anchor: every other
 * link on the site carries a class (buttons, .poulton-cite, the crumbs,
 * pills, read-more, the reference back-links) and sets itself, so an
 * <a> with no class inside prose IS a prose link. External ones are
 * given .poulton-extlink at render (inc/external-links.php, for the
 * arrow), so they are named alongside. Paragraphs, table cells, captions
 * and the items of a content list (`.wp-block-list`) — not any <li>: the
 * "On this page" index and the card grids are lists too, and their links
 * are furniture, not prose. */
:is(.entry-content, .poulton-article, .poulton-readcol) :is(p, td, th, dd, figcaption, .wp-block-list li) :is(a:not([class]), a.poulton-extlink) {
	color: var(--wp--preset--color--primary);
	font-weight: 500;
	text-decoration: underline;
	text-decoration-thickness: 1.5px;
	text-underline-offset: 0.16em;
	text-decoration-color: color-mix(in srgb, var(--wp--preset--color--primary) 40%, transparent);
	text-decoration-skip-ink: auto;
	transition: text-decoration-color 0.15s ease, color 0.15s ease;
}
:is(.entry-content, .poulton-article, .poulton-readcol) :is(p, td, th, dd, figcaption, .wp-block-list li) :is(a:not([class]), a.poulton-extlink):is(:hover, :focus-visible) {
	color: var(--wp--preset--color--primary-dark);
	text-decoration-color: currentColor;
}
.poulton-cite {
	padding: 4px 1px;
	color: var(--wp--preset--color--primary);
	font-weight: 600;
	text-decoration: none;
}
.poulton-cite:hover,
.poulton-cite:focus-visible {
	text-decoration: underline;
}
/* The entry a citation lands on, and its way back. */
.poulton-references li:target {
	background: var(--wp--preset--color--surface);
	box-shadow: 0 0 0 6px var(--wp--preset--color--surface);
	border-radius: 4px;
}
/* The way back from a reference to its citation: a drawn return arrow in
 * a round target, not a character — U+21A9 is emoji on iOS, and the phone
 * showed a blue square where the desktop showed an arrow. The anchor is
 * empty; its aria-label is its name. 1.6em is 27px at the list's size,
 * over the 24px a tap target needs. */
.poulton-ref-back {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1.6em;
	height: 1.6em;
	margin-left: 4px;
	vertical-align: -0.4em;
	border-radius: 999px;
	/* Drawn as a control at rest — a pale disc with the hairline — because
	 * a bare grey arrow after a citation read as punctuation, not a way back. */
	background: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--surface-line);
	color: var(--wp--preset--color--primary);
	text-decoration: none;
}
.poulton-ref-back::before {
	content: "";
	width: 0.95em;
	height: 0.95em;
	background-color: currentColor;
	-webkit-mask: var(--poulton-return-icon) center / contain no-repeat;
	mask: var(--poulton-return-icon) center / contain no-repeat;
}
.poulton-ref-back:hover,
.poulton-ref-back:focus-visible {
	color: var(--wp--preset--color--base);
	background: var(--wp--preset--color--primary);
	border-color: var(--wp--preset--color--primary);
}
/* Closed, it is a pill the width of its own word — a full-width box with
 * one word in it read as an empty panel. Open, the list sits below it in a
 * quiet frame at a citation-sized type. */
.poulton-references {
	margin-top: var(--wp--preset--spacing--60);
}
.poulton-references > summary {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	width: fit-content;
	padding: 8px 16px 8px 14px;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: 999px;
	background: var(--wp--preset--color--base);
	cursor: pointer;
	font-size: 14px;
	font-weight: 600;
	color: var(--wp--preset--color--primary-dark);
	list-style: none;
}
.poulton-references > summary::-webkit-details-marker {
	display: none;
}
.poulton-references > summary::before {
	content: "";
	width: 8px;
	height: 8px;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: rotate(-45deg) translateY(1px);
	transition: transform 0.18s ease;
}
.poulton-references[open] > summary::before {
	transform: rotate(45deg) translateY(-1px);
}
.poulton-references > summary:hover {
	border-color: var(--wp--preset--color--primary-light);
}
/* Selector weight matters here: ol.wp-block-list zeroes its own padding and
 * hangs the numbered chip at the item's left edge, so a lighter rule would
 * leave the chips on the frame. Citation-sized type, a smaller chip, and the
 * list's own rhythm tightened to match. */
.poulton-references ol.wp-block-list {
	margin: 12px 0 0;
	padding: 16px 20px;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--card);
	background: var(--wp--preset--color--base);
	font-size: 16px; /* two steps under the 18px body — a citation, not prose */
	line-height: 1.5;
	color: var(--wp--preset--color--muted);
}
/* Outweighs the article prose rule (`:is(.single-…) .entry-content :is(p, li)`),
 * which would otherwise set every item back to reading size. */
.entry-content .poulton-references ol.wp-block-list > li {
	padding-left: 34px;
	font-size: inherit;
	line-height: inherit;
}
.poulton-references ol.wp-block-list > li + li {
	margin-top: 8px;
}
.poulton-references ol.wp-block-list > li::before {
	width: 22px;
	height: 22px;
	font-size: 11px;
}
/* A table's caption is a caption: the figure treatment, so the two read as
 * one family under the article's text. */
.poulton-article .wp-block-table figcaption,
.entry-content .wp-block-table figcaption {
	margin: 0;
	padding: 10px 16px 12px;
	border-top: 1px solid var(--wp--preset--color--line);
	font-size: 13.5px;
	line-height: 1.55;
	color: var(--wp--preset--color--muted);
	text-align: left;
}
/* A note under a table — the lettered footnotes, "Note:", the
 * abbreviations line (fetch-publication.py writes them from the journal's
 * footnote block). Caption type, tucked up into the table's own bottom
 * margin so the run of notes hangs off the frame, each note a line of its
 * own with no bullet: these were once a list, and a bullet with a raised
 * letter hanging off it read as an error. The paragraph after the last
 * note keeps the prose gap. */
.entry-content .wp-block-table + .poulton-table-note {
	margin-top: calc(-1 * var(--wp--preset--spacing--60) + 12px);
}
.entry-content .poulton-table-note {
	margin-top: 4px;
	padding-inline: 16px;
	font-size: 13.5px;
	line-height: 1.55;
	color: var(--wp--preset--color--muted);
}
.entry-content .poulton-table-note + .poulton-table-note {
	margin-top: 4px;
}
.entry-content .poulton-table-note sup {
	margin-right: 2px;
}
/* ---------- The publication hero ----------
 * Academic titles run to 200+ characters; at the sheets' display size a long
 * one is seven lines ending in a lone word. The title steps down when it
 * would run past three lines (poulton_publication_title_size measures and
 * adds the class), and wraps `balance` so the lines it does take are even —
 * "practical clinical pearls / for GPs" becomes "practical / clinical
 * pearls for GPs" — with `pretty` as the fallback for a browser without
 * balance, which at least keeps a lone word off the last line. Under it the
 * citation is a card of labelled rows — AUTHORS / PUBLISHED IN / TOPICS — the
 * shape a paper's metadata takes on Elicit's paper page: a reader finds the
 * journal by its label, not by guessing which muted line is which. */
/* The title is the theme's h1 (display, 40–72px) on every single — the
 * size the sheets always had. Set as classes, not the block's fontSize
 * preset: core prints a preset as `has-…-font-size` with !important,
 * which no length class could override. */
.single-publication .wp-block-post-title,
.single-explanation_sheet .wp-block-post-title,
.single-post .wp-block-post-title {
	text-wrap: pretty;
	text-wrap: balance;
}
/* Past three lines at full size the title takes the H2's size and setting
 * (theme.json's h2), so it is never smaller than the article's own
 * headings below it. poulton_post_title_size adds the class. */
.single-publication .wp-block-post-title.is-long-title,
.single-explanation_sheet .wp-block-post-title.is-long-title,
.single-post .wp-block-post-title.is-long-title {
	font-size: var(--wp--preset--font-size--xxx-large);
	line-height: 1.15;
	letter-spacing: -0.028em;
}
.poulton-pub-meta {
	/* Stated, not the hero's blockGap: this rule outweighs core's gap margin,
	 * so a relative nudge here read as "no gap". 40px — the measure under a
	 * title on every header band (the rule beside the band radii). */
	margin-top: 40px !important;
	/* A card: a translucent white on the band — the tint shows through, so
	 * the card belongs to the hero rather than sitting on it — softly
	 * rounded, padded. 40% white: at 55% it still read as a slab on the
	 * lighter bands. The pills inside are solid white and rely on their
	 * hairline; the GP series' lilac pill reads on the veil as on the blue. */
	background: rgba(255, 255, 255, 0.4);
	border-radius: var(--wp--custom--radius--image);
	padding: 20px 24px;
	/* The three cells share one row while they fit and wrap as they need
	 * to — a short author list sits beside the journal, ten authors take a
	 * row of their own. No dividers, no icons: each cell is named by its
	 * label, and 40px of air does the rest. */
	display: flex;
	flex-wrap: wrap;
	gap: 16px 40px;
	/* Top-aligned, not stretched: stretched, a two-line author cell made the
	 * topics cell as tall, its value grew to fill, and the pills grew with
	 * it into 56px slabs. */
	align-items: flex-start;
}
.poulton-pub-meta > .poulton-pub-meta-row {
	flex: 0 1 auto;
	min-width: 0;
	max-width: 100%;
	margin-top: 0 !important; /* the group's own child gap; the flex gap rules */
}
.poulton-pub-meta > .poulton-pub-meta-row:first-child {
	/* The authors take whatever the other two leave, but never less than a
	 * readable column: the basis is the floor, so when two pills and a long
	 * journal name leave less than that, the journal wraps to its own row
	 * instead of the names being squeezed into a five-line sliver. Never
	 * more than their own words need, so a short list does not push the
	 * other cells to the far edge. */
	flex: 1 1 320px;
	max-width: max-content;
}
/* Only the authors cell may give way: a squeezed topics cell broke its
 * pills onto two lines, and the journal line is short enough to keep. */
.poulton-pub-meta > .poulton-pub-meta-row--topics,
.poulton-pub-meta > .poulton-pub-meta-row--journal {
	flex-shrink: 0;
}
/* The rows the template writes are flex groups; the topics row is printed
 * by poulton_render_private_terms without core's layout classes, so the row
 * carries its own flex here and both look the same. */
.poulton-pub-meta-row {
	display: flex;
	flex-direction: column; /* label above its value, at every width */
	gap: 3px;
}
.poulton-pub-meta-label {
	margin: 0;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--wp--custom--label--color);
	line-height: 1.7;
}
/* On the GP series' lilac band the label grey measures 4.46:1 — under the
 * line by a hair (it is 4.66 on the surface, itself marginal). One step
 * darker on that band only; the token stays what it is elsewhere. */
.is-gp-series .poulton-pub-meta-label,
.has-lilac-background-color .poulton-kicker {
	color: #626669;
}

/* The values — names, journal · year — at the cards' small size: the card
 * is a caption to the title, not a second paragraph. */
.poulton-pub-meta-value {
	flex: 1 1 0;
	min-width: 0;
	margin: 0;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--contrast);
}
/* The journal · year pair reuses the card's dot separator (.poulton-tile-meta). */
.poulton-pub-meta-value.poulton-tile-meta > p {
	margin: 0;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--contrast);
}
.poulton-pills-list {
	display: inline-flex;
	flex-wrap: wrap;
	align-items: flex-start;
	align-content: flex-start;
	gap: 6px;
}
.poulton-pill--soft {
	--pill-bg: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--line);
	font-size: 12px;
	padding: 4px 11px;
	transition: border-color 0.18s ease, color 0.18s ease;
}
/* A topic pill is a link to the topic's page; the hover is the outline
 * button's, so it reads as the same kind of thing. */
a.poulton-pill--soft:hover {
	border-color: var(--wp--preset--color--primary-light);
	color: var(--wp--preset--color--primary-dark);
}
/* The topic page's intro: one sentence, the reading measure, under the
 * name. */
.poulton-topic-intro {
	margin-top: 12px;
	/* A reading measure on the column's left edge. Core centres a capped
	 * child with auto margins, which would float a 62ch box in the middle of
	 * the 1280 column; this puts the same offset core would give a full-width
	 * child on the left margin only, so the intro starts where the heading
	 * does at every width (and at zero once the column is the viewport).
	 * The page head's column is the WIDE size (the template sets its
	 * contentSize to 1280, which core applies per block, not through the
	 * global content-size property — that stays at the 720px prose measure). */
	max-width: 62ch;
	margin-inline: max(0px, calc((100% - var(--wp--style--global--wide-size)) / 2)) auto !important;
}
@media (max-width: 599px) {
	/* One cell per row on a phone: the wrap would do it anyway at this
	 * width, but stated so a short row never sits beside a pill row. */
	.poulton-pub-meta > .poulton-pub-meta-row {
		flex-basis: 100%;
		max-width: none;
	}
}

/* Headroom for a corner tab wherever the title would otherwise start at the
 * top edge: text-only cards always; cover cards once they stack (below). */
.poulton-tile--text:has(.poulton-pill) {
	padding-top: 44px;
}
/* Cover cards in the row layout: the text column is top-aligned beside the
 * cover, so a long title's first line would otherwise sit right under the
 * tab. Pad the column, not the card — the cover stays where it is. */
.poulton-tile:not(.poulton-tile--text):has(.poulton-pill) > .poulton-tile-text {
	padding-top: 20px;
}
/* Core's own grid post-template (blog, 3 per row) — stretch the cell the way
 * .poulton-tiles does, so height: 100% on the tile fills it. */
.wp-block-post-template.is-layout-grid > .wp-block-post {
	display: flex;
}
/* Three lines is the cap on a card title, the way two is on the excerpt: a
 * rule in lines, not characters, because the same paper wraps to two lines
 * on a hub card and six on a phone. Clamped by CSS, the full title is still
 * the link's text (read out whole; visible whole on the post), and the
 * stretched anchor below is not clipped — the heading is not its containing
 * block, so its overflow does not reach it. */
.poulton-tile-title {
	margin: 0;
	font-size: 18px;
	font-weight: 500;
	line-height: 1.3;
	letter-spacing: -0.015em;
	display: -webkit-box;
	-webkit-line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
.poulton-tile-title a {
	color: var(--wp--preset--color--primary-dark);
	text-decoration: none;
	/* Core's post-title block makes its link an inline-block, and a clamp
	 * counts an inline-block as one line however many it holds inside — so
	 * the hub titles ran to five lines with the clamp "on". Inline, the
	 * heading's own line boxes are the ones being counted. */
	display: inline;
}
.poulton-tile-title a:hover {
	color: var(--wp--preset--color--primary);
}
/* Stretched link: the title anchor's box covers the whole tile, so the cover,
 * the excerpt and the blank card all go to the sheet. No JS, no wrapper. */
.poulton-tile-title a::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: inherit;
}
/* Two lines is a hard cap: the legacy excerpts run 25-40 words, and uneven
 * wrapping is what made the previous listing ragged. */
.poulton-tile-excerpt {
	margin: 0;
	font-size: 14px;
	line-height: 1.5;
	color: var(--wp--preset--color--muted);
}
.poulton-tile-excerpt .wp-block-post-excerpt__excerpt {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	margin: 0;
}
.poulton-tile-excerpt .wp-block-post-excerpt__more-text {
	display: none;
}
/* One muted line under the title: the post date, or journal · year. */
.poulton-tile-meta {
	margin: 0;
	font-size: 14px;
	line-height: 1.5;
	color: var(--wp--preset--color--muted);
}
.poulton-tile-meta > p {
	margin: 0;
}
/* journal · year are two bound paragraphs, either of which may be absent */
.poulton-tile-meta > p + p::before {
	content: "·";
	margin-right: 8px; /* the flex gap sits before the dot; mirror it after */
}
.poulton-tile-actions {
	/* Pinned to the card's bottom edge, so the pills in a row line up whatever
	 * the title and excerpt lengths above them. The auto margin absorbs the
	 * spare height; the text above it sits at the top. */
	margin-top: auto;
	padding-top: 6px;
	gap: 18px;
	align-items: center;
	/* above the stretched anchor, so Read more keeps its own hover and click */
	position: relative;
	z-index: 1;
}
/* The sheet cards' second action: "Listen · 15 min", a core/button bound to
 * the poulton/narration source (plugin: inc/narrations.php), which also drops
 * the whole button on a sheet without a narration. Outline colours, hover and
 * the small size come from is-style-outline; this only adds the solid clay
 * play disc the Listen chip carries — the hero Listen button's colour — so the
 * card, the chip, the dock and the hero read as one family. A ::before
 * because the bound text cannot hold markup. */
.poulton-listen-link .wp-block-button__link {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding-left: 11px; /* the chip's inset: the disc sits closer to the edge than text would */
}
.poulton-listen-link .wp-block-button__link::before {
	content: "";
	flex: none;
	/* 20px: with the small pill's 8px vertical padding this lands on the same
	 * 39px height as the text-only Read more beside it; 22 made it 41. */
	width: 20px;
	height: 20px;
	border-radius: 50%;
	background: var(--wp--preset--color--highlight) var(--poulton-play-icon) 55% 50% / 9px no-repeat;
	transition: background-color 0.22s ease;
}
.poulton-listen-link .wp-block-button__link:hover::before {
	background-color: var(--wp--custom--highlight--hover);
}
/* On the phone strip a sheet card is vw - 80 wide (see the strip rules
 * below), and "Read more" + "Listen · 15 min" do not fit one row until about
 * 430px, so they stack. The 18px row gap that separates pills side by side
 * reads as a hole between stacked ones; close it to the group's own 10px. */
@media (max-width: 700px) {
	.poulton-tile-actions:has(.poulton-listen-link) {
		row-gap: 10px;
	}
}
@media (max-width: 900px) {
	.poulton-tiles .wp-block-post-template {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* Phones: one horizontal row that scrolls, next tile peeking */
@media (max-width: 700px) {
	/* The scroller clips its own content, but the tiles still widen the
	 * ancestors' scrollable area, which scrolled the whole page sideways.
	 * Clipping at the module also keeps the strip inside its rounded corners —
	 * the -24px bleed below now reaches the card edge, since the module's
	 * mobile padding is 24px too. */
	.poulton-module {
		overflow-x: clip;
	}

	.poulton-tiles:not(.poulton-tiles--stack) .wp-block-post-template {
		display: flex;
		grid-template-columns: none;
		gap: 16px;
		overflow-x: auto;
		scroll-snap-type: x mandatory;
		-webkit-overflow-scrolling: touch;
		padding-bottom: 8px;
		/* Bleed past the section's 24px padding so the peeking tile runs off the
		 * screen edge instead of being clipped short of it — a card stopping in
		 * from the edge reads as broken, not as "there is more to scroll".
		 * The inline padding keeps the first tile on the content edge and gives
		 * the last one trailing room. */
		/* WP caps this element at max-width:100%, so a negative margin alone only
		 * shifts it left and leaves the right edge 48px short. Grow it too. */
		width: calc(100% + 48px);
		max-width: none;
		margin-inline: -24px;
		padding-inline: 24px;
		scroll-padding-inline: 24px;
	}
	.poulton-tiles:not(.poulton-tiles--stack) .wp-block-post {
		flex: 0 0 72%;
		scroll-snap-align: start;
	}

	/* ---------- Sheet grids: the strip is a pager ----------
	 * :has() picks the sheet grids out by the data-sheet the render filter
	 * stamps on every sheet card (plugin: inc/sheet-tiles.php). The rail
	 * script uses the same test, so the two cannot disagree, and the
	 * Publications grid — which shares the strip CSS — keeps the plain
	 * strip. No markup changes, so no re-seed. */
	.poulton-tiles:not(.poulton-tiles--stack):has(.poulton-tile-cover[data-sheet]) .wp-block-post-template {
		/* A swipe at either end must not trigger the browser's own back or
		 * forward gesture. That, more than anything, is what makes a web
		 * carousel feel like a web page instead of an app. */
		overscroll-behavior-x: contain;
		/* The peeking card and the dots below both say "there is more", so
		 * the scrollbar has nothing left to add and its reserved strip goes
		 * back. This reaches a narrow desktop window too, where the dots
		 * become the way to move without a bar to drag. */
		padding-bottom: 0;
		scrollbar-width: none;
	}
	.poulton-tiles:not(.poulton-tiles--stack):has(.poulton-tile-cover[data-sheet]) .wp-block-post-template::-webkit-scrollbar {
		display: none;
	}
	/* One card per swipe, done by the browser rather than by us: a scroller
	 * will not skip a snap point marked `always`, so a hard flick lands on
	 * the next card and stops. Nothing intercepts touch, so the momentum,
	 * the rubber-banding at the ends and the platform's own feel are the
	 * real ones. Where it is unsupported a flick can still travel further,
	 * which is exactly what it did before — it degrades to the old
	 * behaviour, not to something broken. */
	.poulton-tiles:not(.poulton-tiles--stack):has(.poulton-tile-cover[data-sheet]) .wp-block-post {
		scroll-snap-stop: always;
		/* A sliver of the next card, not a slice of it. At 72% the peek ran to
		 * ~104px, which read as two cards fighting and shoved the one you are
		 * meant to be reading off to the left. This holds the peek at a flat
		 * 40px on every phone: the flex base resolves against the track's
		 * content box, which is the viewport less the 24px gutters, so
		 * card = vw - 80, it sits from 24 to vw - 56, the next starts a 16px
		 * gap later, and vw cancels out. Constant by construction rather than
		 * a percentage that grows the peek as the screen does. */
		flex-basis: calc(100% - 32px);
	}
	.poulton-tiles:has(.poulton-tile-cover[data-sheet]) .poulton-rail-dots {
		display: flex;
	}
	/* Cover back on top inside the scroller: at 72% of a phone screen a
	 * side-by-side cover leaves the title about 130px, which is unreadable.
	 * The scrolling behaviour itself is unchanged. */
	.poulton-tile {
		flex-direction: column;
		gap: 16px;
	}
	/* Top padding clears the corner tab: with the cover centred up here it
	 * otherwise runs under the tab's left end. The text column's own headroom
	 * (row layout only) is not needed once the cover sits above it. */
	.poulton-tile:has(.poulton-pill) {
		padding-top: 44px;
	}
	.poulton-tile:not(.poulton-tile--text):has(.poulton-pill) > .poulton-tile-text {
		padding-top: 0; /* same selector as the row rule, so it wins by order */
	}
	.poulton-tile-cover {
		flex: 0 0 auto;
		align-self: center;
	}
	/* Publication cards keep the row: a 72px square beside the text leaves
	 * the title ~230px on a 390px phone, which reads fine — and stacked, 25
	 * of them would each be a cover's height taller for no information. The
	 * tab clearance is on the card, like every other tile at this width
	 * (the sheet-tile rule above zeroes the text column's padding at a
	 * weight the pub rule could not beat, which is how the pill came to sit
	 * on the title): 44px clears the 26px tab with the same air the sheets
	 * have, and the cover tops out level with the title. */
	.poulton-tile--pub {
		flex-direction: row;
	}
	.poulton-pub-meta {
		padding: 16px 20px;
	}
	.poulton-tile--pub:has(.poulton-pill) {
		padding-top: 44px;
	}
	.poulton-tile--pub:not(.poulton-tile--text):has(.poulton-pill) > .poulton-tile-text {
		padding-top: 0;
	}
	.poulton-tile-cover img {
		width: auto;
		height: 168px;
	}
	.poulton-tile-cover img.poulton-tile-still {
		height: 224px; /* in flow here (no canvas on phones); the booklet fills ~70% of the frame's height, so this keeps the printed cover the size the flat one was */
	}
	.poulton-tile-cover canvas {
		/* The strip stacks the cover above the text and sizes it by height, in
		 * flow — the canvas is absolutely positioned for the desktop layout
		 * and would land in the wrong place, so it never shows here. */
		display: none;
	}
	.poulton-tile-cover.is-3d img {
		/* ...which means the still has to stay. A narrow window with a MOUSE
		 * passes the hover gate, so the module does run, builds a canvas and
		 * adds .is-3d — and .is-3d hides the still for the canvas that is
		 * about to replace it. With the canvas hidden here too, that left
		 * nothing on screen at all: hover made the book vanish. It is the
		 * still's layer that wins on this side of the breakpoint. */
		visibility: visible;
	}
	/* The cursor halo is a pointer affordance for the two-column grid, and
	 * inside the strip it is also a bug: card-glow.js appends it absolutely
	 * positioned and 23px taller than the card at each end, and an element
	 * overflowing a scroll container gives it scrollable overflow — the strip
	 * became vertically scrollable by 23px and the cards read as cut off.
	 * Not scoped to the sheet grids: every .poulton-tiles strip gets the glow
	 * and had the same scroll. */
	.poulton-tile-glow {
		display: none;
	}
}

/* ---------- Download tile ---------- */
.poulton-dl-tile {
	/* flat at rest, like every other card on the tile recipe */
	background: var(--wp--preset--color--base);
	border: 1px solid rgba(226, 232, 238, 0.9);
	border-radius: var(--wp--custom--radius--card);
}
/* icon | text | action on one row; the text block is the flexible column
 * (its constrained layout would otherwise take 100% and force a wrap) */
.poulton-dl-tile > .wp-block-group {
	flex: 1 1 260px;
	min-width: 0;
	/* a readable measure — un-constrained, the description ran the full 980px */
	max-width: 72ch;
}
.poulton-dl-tile > .wp-block-buttons {
	margin-left: auto;
	flex: 0 0 auto;
}
/* The download's own first page, generated from the PDF — a real cover reads
 * as the document itself where the old PDF/A4 chip was just a label. */
.poulton-dl-cover {
	flex: none;
	width: 72px;
	margin: 0;
	/* Top of the row at every width, while the text and the buttons stay
	 * centred on each other: a cover floating mid-way down a long
	 * description read as misplaced. */
	align-self: flex-start;
}
.poulton-dl-cover img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: 6px;
	border: 1px solid var(--wp--preset--color--line);
	background: var(--wp--preset--color--surface); /* the loading state, as on .poulton-pub-cover */
}
/* Title + description now come from the Download post, so they need the styles
 * the hand-written paragraphs used to carry inline. */
/* Same type as the sheet tile (title 18/500, 14px muted two-line text). */
.poulton-dl-title {
	margin: 0;
	font-size: 18px;
	font-weight: 500;
	line-height: 1.3;
	letter-spacing: -0.015em;
	color: var(--wp--preset--color--primary-dark);
}
.poulton-dl-desc {
	margin: 0;
	font-size: 14px;
	line-height: 1.5;
	color: var(--wp--preset--color--muted);
}
.poulton-dl-desc p {
	margin: 0;
}
.poulton-dl-desc .wp-block-post-excerpt__excerpt {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
.poulton-dl-desc .wp-block-post-excerpt__more-text {
	display: none;
}
@media (max-width: 782px) {
	/* Stacked under the text, the button sits on the text's left edge rather
	 * than being pushed to a phantom right one. */
	.poulton-dl-tile > .wp-block-buttons {
		margin-left: 0;
	}
}
/* On a phone Preview and Download do the same thing — pdf-preview.js hands
 * the file to the browser's own viewer instead of the dialog, and Download
 * opens the same file in a new tab — so the pair collapses to Download,
 * everywhere the pair appears. The same width the script switches at. */
@media (max-width: 700px) {
	.wp-block-button:has(> .poulton-btn-preview) {
		display: none;
	}
}
/* Containing block for the sheet-number tab (pill component rules). */
.poulton-dl-tile {
	position: relative;
}
/* Kept for the download-tile pattern, which has no attachment to point at. */
.poulton-dl-icon {
	width: 40px;
	height: 48px;
	border-radius: 8px;
	background: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--line);
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.04em;
	color: var(--wp--preset--color--primary);
	flex: none;
}

/* ---------- Footer ----------
 * A light surface like the hero rather than a deep blue block, so the page
 * opens and closes on the same material. The ink is navy throughout: white
 * text measures about 2.8:1 on a wash this light, nowhere near AA. */
/* Full-bleed surface, site-column content. The footer group's constrained
 * layout caps its .alignwide children at wideSize (1280px) and centres them, so
 * with the site's own 24px page gutter the footer's columns land on exactly the
 * same edges as every section — at any width, not just above a max-width. */
.poulton-footer {
	background-image: var(--wp--preset--gradient--footer-sky);
	/* Same soft shoulder as the warm bands: the footer is the last full-bleed
	 * surface on every page, and a square top edge across the viewport read as
	 * the same hard rule. Bottom corners stay square — the page ends there. */
	border-radius: var(--wp--custom--radius--module) var(--wp--custom--radius--module) 0 0;
	/* !important: the block editor writes these as inline styles */
	padding: clamp(48px, 6vw, 80px) 24px !important;
}
/* The corners cut the footer's surface away, so they show whatever is behind
 * it — the white page. That is right on most pages, where the section above
 * IS white, but wrong on the three that end with a sand band (About,
 * Downloads, the book page): there the cut-outs read as two white wedges
 * against the cream.
 *
 * So when the last section on the page is a sand band, paint that colour
 * behind the footer's corner band. It goes on the <footer> template-part
 * wrapper, which is transparent, exactly full-bleed, and sits behind the
 * group that paints the gradient. A strip the height of the radius rather
 * than a plain background-color: the gradient's base layer is opaque today,
 * so a full backdrop would be invisible anyway, but a strip cannot leak below
 * the footer or under some later translucent gradient, and it says what it is
 * for.
 *
 * :has() because the footer sits outside .entry-content, so the condition can
 * only be read upward. Tied to :last-child, so it stops applying by itself if
 * a section is ever added after the band. This is a matched pair — a page
 * ending in a different tint needs its own pair. The blog and single
 * templates don't use main > .entry-content and end white, so they need
 * nothing. */
.wp-site-blocks:has(main > .entry-content > .poulton-module--band.has-sand-background-color:last-child) > footer {
	background-image: linear-gradient(var(--wp--preset--color--sand), var(--wp--preset--color--sand));
	background-repeat: no-repeat;
	background-size: 100% var(--wp--custom--radius--module);
}
.poulton-footer-nav {
	margin: 0;
	line-height: 2.1;
	/* was inline list-style:none, which core/list can't serialize */
	list-style: none;
}
.poulton-footer-lede {
	margin: 0;
	font-weight: 350;
	line-height: 1.25;
	letter-spacing: -0.02em;
	max-width: 22ch;
	text-wrap: pretty; /* the markup's nbsp is the guaranteed no-orphan fallback */
}
/* Footer links read as navigation, not prose — underlines look default here.
 * Hover/focus still give a clear, non-colour-only affordance. */
.poulton-footer a {
	color: var(--wp--preset--color--primary-dark);
	text-decoration: none;
}
.poulton-footer a:hover {
	color: var(--wp--preset--color--primary);
}
/* The footer list is hand-written markup, so it gets its aria-current from
 * inc/nav-current.php too. No chip down here — the footer is a quiet index, and
 * a tinted pill on a gradient would read as a button. */
.poulton-footer-nav a[aria-current="page"] {
	color: var(--wp--preset--color--primary);
	font-weight: 600;
}
.poulton-footer-contact {
	margin: 0;
	line-height: 1.9;
}
/* The footer's search field: the site-wide field recipe (under "Search: the
 * results page") needs nothing here, but core prints the visible <label>
 * unstyled. The section-label idiom — small, spaced, uppercase — in the
 * footer's own navy rather than the kicker's grey: every other line of ink
 * down here is navy, and the grey is at its contrast floor on the pale
 * module surface, which this gradient resembles. */
.poulton-footer-search .wp-block-search__label {
	display: block;
	margin-bottom: 10px;
	color: var(--wp--preset--color--primary-dark);
	font-size: 12.5px;
	font-weight: 600;
	line-height: 1.4;
	letter-spacing: 0.1em;
	text-transform: uppercase;
}
.poulton-footer-logo {
	margin: 0;
}
@media (max-width: 781px) {
	.poulton-module {
		/* 40px is too round for a ~340px-wide card */
		border-radius: 24px;
	}
	.poulton-footer-top {
		row-gap: 28px;
	}
	.poulton-footer-bottom {
		margin-top: var(--wp--preset--spacing--60) !important;
	}
	.poulton-footer-logo {
		margin-bottom: 20px;
	}
}

/* Outbound/mail link marker — masked SVG so it inherits the text colour.
 *
 * .poulton-extlink is no longer applied by hand: poulton-core/inc/external-
 * links.php adds it at render to every anchor whose host is not this site's,
 * along with target="_blank". So this rule now covers inline prose links
 * (the IntechOpen chapter link in the sheet captions) AND, via the override
 * below, every external button. One glyph, one meaning: you are leaving
 * poultonadhd.com.au. PDFs are on this host and never get it. */
.poulton-extlink::after {
	content: "";
	display: inline-block;
	width: 0.95em;
	height: 0.95em;
	margin-left: 6px;
	vertical-align: -0.14em;
	background-color: currentColor;
	-webkit-mask: var(--poulton-extlink-icon) center / contain no-repeat;
	mask: var(--poulton-extlink-icon) center / contain no-repeat;
}

/* Mail icon ahead of the address — affordance before the reader reaches the
 * outbound arrow at the end of the text. Scoped to mailto so a plain external
 * link using .poulton-extlink still gets only the trailing arrow. */
a[href^="mailto:"].poulton-extlink::before {
	content: "";
	display: inline-block;
	width: 0.85em;
	height: 0.85em;
	margin-right: 6px;
	vertical-align: -0.12em;
	background-color: currentColor;
	-webkit-mask: var(--poulton-mail-icon) center / contain no-repeat;
	mask: var(--poulton-mail-icon) center / contain no-repeat;
}
/* Inside a button the glyph is a touch larger and further from the label,
 * matching the sheet-foot download icon so the two button glyphs sit
 * identically. is-style-arrow already uses ::after for its arrow chip and is
 * excluded — an external arrow button would otherwise grow a second icon. */
.wp-block-button:not(.is-style-arrow) .wp-block-button__link.poulton-extlink::after {
	width: 1em;
	height: 1em;
	margin-left: 8px;
	vertical-align: -0.16em;
}
/* On an arrow button the base rule's mask would still clip the arrow chip
 * into the outbound glyph's silhouette, so the mask is switched off there and
 * the chip's own background shows. The arrow keeps the new tab behaviour; it
 * just does not grow a second icon. */
.wp-block-button.is-style-arrow .wp-block-button__link.poulton-extlink::after {
	-webkit-mask: none;
	mask: none;
}

/* ---------- Quote ---------- */
.wp-block-quote cite {
	display: block;
	margin-top: 14px;
	font-family: var(--wp--preset--font-family--body);
	font-size: 14px;
	font-style: normal;
	font-weight: 500;
	letter-spacing: 0;
	color: var(--wp--preset--color--muted);
}

/* Endorsement: the same card recipe as .poulton-hairline-card, with the
 * quotation mark doing the job the old 2px left rule was failing at. */
.wp-block-quote.is-style-endorsement {
	padding: 32px;
	background: var(--wp--custom--surface--raised);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--card);
	box-shadow: var(--wp--custom--shadow--card);
	/* Body type, not core/quote's x-large heading face. theme.json styles a
	 * quote as a display pull-quote — right for one line set as a feature,
	 * far too loud for an endorsement of several sentences, which is read
	 * rather than admired. Same move, and the same reason, as
	 * .poulton-book-rail below. */
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 400;
	line-height: 1.65;
	letter-spacing: 0;
}
.wp-block-quote.is-style-endorsement::before {
	content: "\201C";
	display: block;
	margin-bottom: -4px;
	/* Inter draws U+201C as two flat prime marks; a serif gives the proper
	 * curled shape. A single ornamental glyph in a system serif, not a second
	 * typeface — headings and body remain Inter. */
	font-family: Georgia, "Times New Roman", serif;
	font-size: 72px;
	line-height: 1;
	color: var(--wp--preset--color--highlight);
}
.wp-block-quote.is-style-endorsement > p:last-of-type {
	margin-bottom: 0;
}
.wp-block-quote.is-style-endorsement cite {
	margin-top: 22px;
	padding-top: 16px;
	border-top: 1px solid var(--wp--preset--color--line);
	line-height: 1.5;
}
/* The pair takes the section's own column, one card each, so its edges are the
 * heading's edges. It was capped at 960px and pinned left, which lined up at
 * 1280 and nowhere above it: past the wide size the cap stopped tracking the
 * column, the pinned margin held the pair against the section's padding, and
 * the heading went on centring in the 1280 column without it. Core's alignwide
 * margins already do the right thing here — the fix is to stop overriding
 * them. The quotes read at this width because they are body type now; at
 * core/quote's x-large they did not.
 *
 * The named margin-block keeps the columns block from taking the flow gap
 * twice, since the block above it already carries one. */
.wp-block-columns.poulton-quote-pair {
	margin-block: 0;
}
/* Equal heights. Core stretches the COLUMN to the row, but not the quote
 * inside it, and core/quote supports no minHeight to do this from the markup —
 * so the shorter card would float with a ragged bottom beside the taller one. */
.poulton-quote-pair .wp-block-column {
	display: flex;
}
.poulton-quote-pair .wp-block-quote {
	flex: 1;
	margin: 0;
	/* A column, so the attribution can be pushed to the foot of the card.
	 * Without it the shorter quote's cite sits where its text happens to end
	 * and the two cards' rules land at different heights, which reads as a
	 * mistake rather than as a pair. */
	display: flex;
	flex-direction: column;
}
.poulton-quote-pair .wp-block-quote cite {
	margin-top: auto;
}

/* ---------- Book section: cover | copy | endorsement rail ----------
 * Replaces the old stacked treatment, where the CTA floated centred at the
 * bottom, detached from the book it sells, and the endorsement card outweighed
 * the cover. The buy action now sits with the copy that motivates it and the
 * endorsement becomes a supporting sidebar. */
.poulton-book-cols figure {
	margin: 0;
}
.poulton-book-cols img {
	display: block;
	width: 100%;
	height: auto;
	/* The cover's white studio ground is cut to transparency in the image
	 * pipeline, so there is no rectangle left to round off — the corners this
	 * used to soften are not there any more.
	 *
	 * drop-shadow, NOT box-shadow: it follows the alpha silhouette, so the
	 * shadow hugs the stepped edge of the book stack instead of drawing a
	 * rectangle around it. This is shadow--card translated by hand, because
	 * drop-shadow takes no spread value and so cannot use the token directly.
	 * The mockup was lit for a white page and casts no shadow of its own; on the
	 * tint it needs something to stand on. */
	filter: drop-shadow(0 1px 1px rgba(6, 32, 62, 0.06))
		drop-shadow(0 10px 16px rgba(6, 32, 62, 0.18));
}
.poulton-book-cta {
	align-items: center;
}
.poulton-book-cta .wp-block-buttons {
	margin: 0;
}
/* The rail: a quiet card in the book module's sidebar. Overrides the default
 * quote type (21px) — sidebar copy reads at 15px, which is why this exists
 * rather than is-style-endorsement, whose type is sized for a full-width column.
 *
 * White on the module's tint, NOT tinted itself: the module and the rail used to
 * take the same `surface` token, so once the book module became tinted on both
 * pages the rail would have been the same fill as the thing behind it. */
.wp-block-quote.poulton-book-rail {
	margin: 0;
	padding: 28px 26px;
	background: var(--wp--custom--surface--raised);
	border: 1px solid var(--wp--preset--color--line);
	box-shadow: var(--wp--custom--shadow--card);
	border-radius: var(--wp--custom--radius--card);
	font-family: var(--wp--preset--font-family--body);
	font-size: 15px;
	font-weight: 400;
	line-height: 1.62;
	letter-spacing: 0;
	color: var(--wp--preset--color--primary-dark);
}
.wp-block-quote.poulton-book-rail::before {
	content: "";
	display: block;
	width: 24px;
	height: 24px;
	margin-bottom: 16px;
	background: var(--wp--preset--color--highlight);
	-webkit-mask: var(--rail-quote) no-repeat center / contain;
	mask: var(--rail-quote) no-repeat center / contain;
	--rail-quote: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9.5 5.5C6.8 6.9 5 9.4 5 12.4V18h5.6v-5.6H8.1c0-2 .7-3.6 2.4-4.7l-1-2.2Zm9 0c-2.7 1.4-4.5 3.9-4.5 6.9V18h5.6v-5.6h-2.5c0-2 .7-3.6 2.4-4.7l-1-2.2Z' fill='black'/%3E%3C/svg%3E");
}
.wp-block-quote.poulton-book-rail p {
	margin: 0;
}
.wp-block-quote.poulton-book-rail cite {
	display: block;
	margin-top: 18px;
	padding-top: 16px;
	/* the card's own hairline colour — the rail is white now, not blue */
	border-top: 1px solid var(--wp--preset--color--line);
	font-size: 13.5px;
	font-style: normal;
	font-weight: 600;
	line-height: 1.45;
	color: var(--wp--preset--color--primary-dark);
}
/* ---------- The endorsement rail, as a carousel ----------
 * Two states, because the enhanced one would be wrong without the script that
 * drives it. Base: ordinary flow, both quotes readable one after the other,
 * which is exactly what a reader with no JavaScript should get. The rail card
 * zeroes its own margin, so the gap belongs here.
 *
 * assets/js/quote-rail.js adds .is-carousel once it has built the dots. */
.poulton-rail-quotes > .wp-block-quote + .wp-block-quote {
	margin-top: 16px;
}
/* Enhanced, on a pointer: one grid cell, both slides in it, cross-fading.
 * quote-rail.js moves the slides into a track of their own so the dots can sit
 * outside it — on a phone that track becomes a scroller (further down) and the
 * dots must not swipe away with the cards. The track is then as tall as
 * the taller quote by construction — no measuring, no reflow on the swap, and
 * the module's height is the same on either slide, which is the whole point.
 *
 * visibility, NOT display: display:none would take the hidden slide out of the
 * grid's sizing and the fixed height would collapse to whichever quote happens
 * to be showing. visibility keeps the box while still removing the slide from
 * the accessibility tree and the tab order, which is what we want on all three
 * counts. Anyone "tidying" this to display:none breaks the height. */
.poulton-rail-quotes.is-carousel .poulton-rail-track {
	display: grid;
}
.poulton-rail-quotes.is-carousel .poulton-rail-track > .wp-block-quote {
	grid-area: 1 / 1;
	margin-top: 0;
	visibility: hidden;
	opacity: 0;
	transition: opacity var(--rail-fade, 400ms) ease;
	/* A column, so the attribution can sit at the foot of the card. The cell is
	 * the taller quote's height, so without this the shorter quote's cite floats
	 * wherever its text happens to stop and the two slides' rules land at
	 * different heights — the same reason .poulton-quote-pair does it. */
	display: flex;
	flex-direction: column;
}
.poulton-rail-quotes.is-carousel .poulton-rail-track > .wp-block-quote cite {
	margin-top: auto;
}
.poulton-rail-quotes.is-carousel .poulton-rail-track > .wp-block-quote.is-current {
	visibility: visible;
	opacity: 1;
}
/* The safety net the fixed height needs: a quote long enough to double the
 * rail would push the module taller on both pages it appears on. Eleven lines
 * is about 330 characters at this measure — clear of both quotes we ship, so
 * nothing is cut today. */
.poulton-rail-quotes .wp-block-quote > p {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 11;
	overflow: hidden;
}
/* Phones: the track becomes a swipeable row, next card peeking.
 * Same recipe as the sheet tiles' scroller above — and the same breakpoint,
 * because the bleed below is only safe while `.poulton-module { overflow-x:
 * clip }` is in force, which is declared in that block. At a wider one the
 * track would widen its ancestors and scroll the whole page sideways.
 *
 * The gesture is the browser's, not ours: scroll-snap gives finger tracking,
 * momentum, rubber-banding and keyboard scrolling, all of which a hand-written
 * pointer handler would only approximate. A pair of 8px dots does not tell a
 * thumb it can swipe; an edge running off the card does.
 *
 * quote-rail.js reads the mode off the layout — a track wider than its box is
 * a scroller — so the 700px lives here and only here, and it stops
 * auto-advancing on its own. */
@media (max-width: 700px) {
	.poulton-rail-quotes.is-carousel .poulton-rail-track {
		/* One number for the card's share of the track: the peek is what is
		 * left of it, and so is the trailing room below. */
		--rail-card: 80%;
		display: flex;
		gap: 12px;
		overflow-x: auto;
		scroll-snap-type: x mandatory;
		-webkit-overflow-scrolling: touch;
		overscroll-behavior-x: contain;
		/* Bleed to the module's edge so the peek runs off it rather than
		 * stopping short — a card that stops short reads as broken, not as
		 * "there is more". WP caps this at max-width:100%, so the negative
		 * margin alone would only shift it left and leave the right edge 48px
		 * short: it has to grow too. The inline padding puts the first card
		 * back on the content edge, and scroll-padding makes snapping land
		 * there. Straight from the tiles' scroller. */
		width: calc(100% + 48px);
		max-width: none;
		margin-inline: -24px;
		padding-inline: 24px;
		scroll-padding-inline: 24px;
		/* overflow-x: auto makes overflow-y compute to auto too, so the box
		 * clips vertically whether we want it to or not — and the card's
		 * shadow reaches about 12px below it (shadow--card is y+10, blur 30,
		 * spread -14). Pad past that or every card sits on a cut-off shadow.
		 * The dots' own margin comes down to match, below. */
		padding-bottom: 18px;
		scrollbar-width: none;
	}
	.poulton-rail-quotes.is-carousel .poulton-rail-track::-webkit-scrollbar {
		display: none;
	}
	/* The track's shadow room already provides most of the gap. */
	.poulton-rail-quotes.is-carousel .poulton-rail-dots {
		/* The track above already carries 18px of padding-bottom to clear the
		 * cards' shadow, so the dots need almost nothing of their own. */
		--rail-dots-space: 2px;
	}
	.poulton-rail-quotes.is-carousel .poulton-rail-track > .wp-block-quote {
		/* Every card is really present in a scroller, so the stacking above is
		 * undone in full — a slide left at visibility:hidden would swipe to a
		 * blank space. */
		grid-area: auto;
		/* A percentage, like the tiles', because the peek has to survive the
		 * clip. The track bleeds 24px past the module on each side but the
		 * module clips at its own edge, so a card sized to nearly the full
		 * track pushes the next one past that edge and the peek vanishes
		 * entirely — measure it against the module's edge, not the screen's.
		 * 80% leaves about 32px showing and still gives the quote a 220px
		 * measure, a line more than it took as a full-width card. */
		flex: 0 0 var(--rail-card);
		scroll-snap-align: start;
		visibility: visible;
		opacity: 1;
		transition: none;
	}
	/* Trailing room, or the last card can never reach the content edge.
	 * Without it the track runs out of scroll while that card is still
	 * overhanging the module, which clips it — a reader swipes and lands on a
	 * quote with its right edge cut off. The leftover is exactly what the peek
	 * costs, so it is the same number, and percentages here resolve against
	 * the track's content box just as the card's basis does. */
	.poulton-rail-quotes.is-carousel .poulton-rail-track > .wp-block-quote:last-child {
		margin-inline-end: calc(100% - var(--rail-card));
	}
}

.wp-block-quote.poulton-book-rail cite br {
	/* the role line reads as secondary to the name above it */
	line-height: 2.2;
}
/* The book page's cover column stays put while the copy beside it scrolls.
 * On the COLUMN, not the figure: core's .is-vertically-aligned-top gives the
 * column align-self: flex-start, so it is content-height inside the tall row
 * and has room to travel. Nothing between it and the viewport carries a
 * transform, filter or overflow (CLAUDE.md's containing-block trap), so this
 * needs no !important and no restructuring — but the column must carry no
 * gsap-* class of its own: a tween's inline transform would pin it. */
.poulton-sticky-col {
	position: sticky;
	top: calc(var(--wp--custom--shell--nav-clear) + 8px);
}
/* Tablets and small laptops: the cover takes a line of its own, and the copy
 * and the rail share the line below it.
 *
 * The three-column row is 300px of cover plus 340px of rail plus two 56px
 * gaps before the copy gets anything at all — 752px of furniture. It needs
 * about 1250px of viewport before the middle column has a readable measure,
 * and below that it collapsed catastrophically rather than gracefully: at
 * 900px the copy column was 28px wide and the paragraph broke one character
 * per line.
 *
 * Wrapping the rail alone fixed that but spent the width badly: the rail sat
 * under a half-empty row with 500px of nothing beside it. Breaking after the
 * cover instead keeps the pairing that matters — the copy and the endorsement
 * beside it — and lets the cover lead the module the way it does on a phone.
 * Core pins the row to nowrap above 782px, so the wrap has to be forced. */
@media (min-width: 782px) and (max-width: 1279px) {
	.poulton-book-cols {
		flex-wrap: wrap !important;
	}
	/* Positional, because the columns carry no classes of their own — this is
	 * a synced block with a fixed shape, so the order is not going to drift.
	 * 1: the cover, alone on the first line. 2: the copy. 3: the rail. */
	.poulton-book-cols > .wp-block-column:first-child {
		/* A full basis is what breaks the line; the figure below is what stops
		 * the cover growing into it. */
		flex-basis: 100% !important;
	}
	.poulton-book-cols > .wp-block-column:first-child figure {
		max-width: 220px;
	}
	.poulton-book-cols > .wp-block-column:nth-child(2),
	.poulton-book-cols > .wp-block-column:last-child {
		/* The cover row sets no row-gap of its own — the block only carries a
		 * column gap — so the second line has to space itself. */
		margin-top: var(--wp--preset--spacing--50);
	}
	.poulton-book-cols > .wp-block-column:nth-child(2) {
		/* The copy takes what the rail leaves. The min-width is the floor that
		 * keeps the pair honest: flex clamps a basis by max-width BEFORE it
		 * breaks lines, so stating what the copy needs is both truer and the
		 * thing flex will honour.
		 *
		 * 380 is set above what the copy would otherwise be given, so that at
		 * the narrow end of this range the rail is the column that gives way
		 * rather than the prose: at 834 — iPad portrait, the width that
		 * matters most here — a 320px floor left the heading breaking across
		 * two lines and the two buttons stacking. Below about 790px nothing
		 * shrinks far enough and the rail drops to a third line instead,
		 * which is the right answer at that width. */
		min-width: 380px;
		max-width: 46rem;
	}
	.poulton-book-cols > .wp-block-column:last-child {
		/* The basis is 280 and the cap is 340, which is not the same thing as
		 * a 340 basis that shrinks. Flex breaks a line using the base size and
		 * only then distributes what is left, so an item never shrinks its way
		 * out of wrapping — with a 340 basis the rail dropped to a third row
		 * at 834 instead of narrowing. Starting small and growing into the cap
		 * is the only way a flex item gives ground to its neighbour. */
		flex: 1 1 280px !important;
		max-width: 340px;
	}
}
@media (max-width: 781px) {
	/* stacked: the rail is no longer a sidebar, so let it breathe full width */
	.poulton-book-cols .wp-block-column {
		flex-basis: 100% !important;
	}
	/* The cover owns a whole row here, and at the column's full width it is a
	 * screenful of book before a reader reaches a word about it. The artwork
	 * is a 3D mockup with its own shadow, so it carries a small size well. */
	.poulton-book-cols figure {
		max-width: 190px;
	}
	/* stacked: the cover leads the copy, and a sticky cover would sit over it */
	.poulton-sticky-col {
		position: static;
	}
}

/* ---------- Focus visibility (WCAG) ---------- */
a:focus-visible,
button:focus-visible,
.wp-block-button__link:focus-visible,
input:focus-visible,
textarea:focus-visible,
.wp-block-navigation a:focus-visible {
	outline: 3px solid var(--wp--preset--color--primary);
	outline-offset: 2px;
}

/* ---------- Section measure ----------
 * Section headers now share the site column's left edge with the cards below
 * them. Prose inside those sections keeps a readable measure via padding, not
 * max-width — max-width would re-centre the block and break the left edge.
 * max(0px, …) makes this a no-op wherever the container is already narrow. */
.poulton-sect > p {
	max-width: 46rem;
	/* hold the site column's left edge while capping the measure: padding or a
	 * bare max-width would either fill the box or re-centre the block */
	/* core's constrained layout sets these auto margins with !important, so the
	 * override has to match it or the capped block re-centres */
	margin-left: max(0px, calc((100% - var(--wp--custom--shell--content)) / 2)) !important;
	margin-right: auto !important;
}

/* ---------- Prose ---------- */
h1, h2, h3, h4 {
	text-wrap: balance;
}
.entry-content p {
	text-wrap: pretty;
}

/* Article reading rhythm.
 *
 * Scoped to the long-form bodies — the same three post types
 * poulton_toc_is_article() calls an article (plugin/poulton-core/inc/toc.php).
 * Pages, tiles and cards also use .entry-content and must not move.
 *
 * The problem this solves: core's flow layout gives every block in the body the
 * same 24px blockGap (theme.json styles.spacing.blockGap), so a new topic, a
 * sub-topic and the next sentence are all separated by exactly the same gap.
 * The type scale already separates the levels; the space did not, and scanning
 * works on proximity. These are the only heading margin rules in this file.
 *
 * Space goes ABOVE a heading, never below it. Core sets margin-block-start on
 * every flow sibling and adjacent margins collapse, so a margin-block-end on
 * the heading loses to the following block's 24px. Tightening the gap under a
 * heading means shrinking the FOLLOWING element's margin — hence the `+ *`
 * rules. Above/below asymmetry is what binds a heading to the text it
 * introduces instead of leaving it floating between two blocks.
 *
 * Raw px rather than spacing presets: the scale steps 24 -> 40 -> 56..104 with
 * nothing between, and 40px is already the figure gap (.poulton-sheet-figure).
 * The resulting ladder is paragraph 24 < figure 40 < h4 40 < h3 60 < h2 88. */
:is(.single-explanation_sheet, .single-post, .single-publication) .entry-content > :is(h2, h3, h4):where(:not(:first-child)) {
	margin-block-start: clamp(32px, 3vw, 40px);
}
:is(.single-explanation_sheet, .single-post, .single-publication) .entry-content > h3:where(:not(:first-child)) {
	margin-block-start: clamp(40px, 4.5vw, 60px);
}
:is(.single-explanation_sheet, .single-post, .single-publication) .entry-content > h2:where(:not(:first-child)) {
	margin-block-start: clamp(56px, 7vw, 88px);
}

/* A section opens with a line. On the three article types every h2 that is
 * not the opener carries the site's hairline above it, so a reader scrolling
 * a 9,000-word sheet or a full paper sees where one section ends without
 * counting white space — the pattern of a single-column help article
 * (Nothing, Sunsama on Refero). Done here rather than as separator blocks
 * in the content: nothing to insert across twelve papers, six sheets and
 * every future post, and a heading the client types gets it too. The h2
 * step above is split into margin (above the line) and padding (line to
 * heading) so the total stays on the ladder and the `h2 + *` binding below
 * is untouched. h3/h4 divide by space alone — sub-topics, not sections. */
:is(.single-explanation_sheet, .single-post, .single-publication) .entry-content > h2:where(:not(:first-child)) {
	margin-block-start: clamp(40px, 5vw, 60px);
	padding-block-start: clamp(24px, 3vw, 36px);
	border-top: 1px solid var(--wp--preset--color--line);
}

/* …and whatever a heading introduces pulls in close under it. The `:not()`
 * lists keep a heading of the same or higher rank on its own step — an h2 that
 * follows an h3 still opens a topic, and two sibling h3s stay sub-topics — so
 * only content a heading actually introduces is pulled in. A heading of LOWER
 * rank is part of the same unit and does bind (h2 then h3).
 *
 * The :where() above holds the heading rules at (0,2,1) so these, at (0,2,2),
 * win the ties. They also out-specify .poulton-sheet-figure's margin shorthand
 * (0,1,0), so a figure directly under a heading binds to it too. */
:is(.single-explanation_sheet, .single-post, .single-publication) .entry-content > h4 + :not(h2, h3, h4) {
	margin-block-start: 12px;
}
:is(.single-explanation_sheet, .single-post, .single-publication) .entry-content > h3 + :not(h2, h3) {
	margin-block-start: 14px;
}
:is(.single-explanation_sheet, .single-post, .single-publication) .entry-content > h2 + :not(h2) {
	margin-block-start: 16px;
}

/* Article pages read wider than the site. theme.json's contentSize (720px)
 * is right for a page of prose, but the sheets set their illustrations at
 * 900px and 720px of text inside them read as a narrow strip — so on the
 * three article templates the text, the hero's text column and the figures
 * all share one measure, `custom.measure.article`.
 *
 * Done by redefining core's own custom property on the body class rather
 * than by setting contentSize per block: every constrained child (the post
 * content, the hero text group, each .poulton-readcol block) and the rail
 * sums further down all read this property, so one line moves all of them
 * together and the hero/article left-edge alignment holds by construction.
 * body:is() is (0,1,1) against core's :root (0,1,0). The block editor still
 * shows 720px — it reads theme.json directly — which is accepted, because
 * content is edited in files, not in the editor. */
body:is(.single-explanation_sheet, .single-post, .single-publication) {
	--wp--style--global--content-size: var(--wp--custom--measure--article);
}
/* Article body text is a step up from the site's default body size. At the
 * 900px measure `large` runs roughly 85 characters a line — above the 65-75
 * band, and chosen with that in view: one edge with the figures mattered
 * more than the last ten characters. Blocks that set their own size keep
 * it, and captions stay small. */
:is(.single-explanation_sheet, .single-post, .single-publication) .entry-content :is(p, li):not([class*="font-size"]):not(.poulton-table-note) {
	font-size: var(--wp--preset--font-size--large);
}

@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after {
		animation-duration: 0.01ms !important;
		transition-duration: 0.01ms !important;
	}
	/* .poulton-sheetnav-card is deliberately NOT in this list: its hover is
	 * declared further down the file, so an entry here would lose the tie on
	 * source order and silently do nothing. It carries its own reduced-motion
	 * override next to the rule instead. */
	.poulton-hairline-card:hover,
	.poulton-tile:hover {
		transform: none;
	}
}

/* ---------- Scroll-reveal animations (GSAP) ----------
 * Initial states for the gsap-* classes, and nothing else — the motion itself
 * is assets/js/animations.js. Every rule is scoped to html.gsap-pending, a
 * class that only the inline boot script in functions.php adds, and only when
 * the page carries gsap-* markup and the reader has not asked for reduced
 * motion. So with JavaScript off, with GSAP missing, or in the editor these
 * rules match nothing and the page is exactly as before. The class comes off
 * again the instant the script has set its own inline start values (same
 * tick, no flash), or after the script's own failsafe if it never arrives.
 * :not([data-gsap-done]) keeps a finished element visible if the class is
 * ever re-added (bfcache restore, late failsafe). Parallax has no start state
 * on purpose — it must never hide anything. */
html.gsap-pending .gsap-reveal:not([data-gsap-done]),
html.gsap-pending .gsap-reveal-up:not([data-gsap-done]),
html.gsap-pending .gsap-section:not([data-gsap-done]),
html.gsap-pending .gsap-scale:not([data-gsap-done]),
html.gsap-pending .gsap-stagger:not([data-gsap-done]) > *,
html.gsap-pending .gsap-intro:not([data-gsap-done]) > * {
	opacity: 0;
}
/* The For GPs fan's pages (assets/js/gp-fan.js, its own module): held
 * back the same way until the module writes its start pose. */
html.gsap-pending .poulton-gp-fan-page:not([data-gsap-done]),
html.gsap-pending .poulton-gp-seal:not([data-gsap-done]) {
	opacity: 0;
}
/* A lead hides only its plain-text children: anything carrying a preset of
 * its own, or wrapping one, animates itself and must not be hidden twice.
 * A heading inside a lead keeps gsap-text-reveal, so the clip rule below
 * still covers it. Browsers without :has() drop this one rule and those
 * children simply fade in from visible — nothing is ever lost. */
html.gsap-pending .gsap-lead:not([data-gsap-done]) > *:not([class*="gsap-"]):not(:has([class*="gsap-"])) {
	opacity: 0;
}
html.gsap-pending .gsap-image-reveal:not([data-gsap-done]) {
	clip-path: inset(0 0 100% 0);
}
html.gsap-pending .gsap-text-reveal:not([data-gsap-done]) {
	clip-path: inset(100% 0 0 0);
}

/* ---------- Lists ----------
 * Site-wide treatment for content lists (About projects, sheet articles, 404):
 * numbers sit in the same chip family as .poulton-dl-icon / .poulton-pill,
 * bullets become primary dots on the same 28px rail so ol and ul text edges
 * align. The footer nav also carries .wp-block-list — keep it excluded. */
ol.wp-block-list,
ul.wp-block-list:not(.poulton-footer-nav) {
	list-style: none;
	padding-left: 0;
	/* no margin reset here — it would override the layout blockGap margin and
	 * glue the list to the heading above it */
}
/* The rail is padding with an absolutely placed marker, NOT a two-column grid.
 * A grid makes every child of the <li> its own item, so an item that mixes a
 * link with text — "<a>Explanation Sheets</a> — free plain-language guides" on
 * the 404 — put the link in the text column and dropped the rest into the 28px
 * marker column, one word per line. Padding leaves the item as ordinary inline
 * flow, which is what a list item is. */
ol.wp-block-list > li,
ul.wp-block-list:not(.poulton-footer-nav) > li {
	position: relative;
	padding-left: 42px; /* the 28px marker rail plus its 14px gap */
}
ol.wp-block-list > li + li,
ul.wp-block-list:not(.poulton-footer-nav) > li + li {
	margin-top: 14px;
}
ol.wp-block-list {
	counter-reset: poulton-ol;
}
ol.wp-block-list > li::before {
	counter-increment: poulton-ol;
	content: counter(poulton-ol);
	position: absolute;
	left: 0;
	top: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
	margin-top: -1px; /* optically centre the chip on the first text line */
	border-radius: 50%;
	/* base + hairline, not surface: half these lists sit ON a surface module
	 * (About projects), where a surface chip vanishes into the background */
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--line);
	color: var(--wp--preset--color--primary);
	font-size: 13.5px;
	font-weight: 600;
	line-height: 1;
}
ul.wp-block-list:not(.poulton-footer-nav) > li::before {
	content: "";
	position: absolute;
	left: 10.5px; /* centred on the 28px rail */
	top: 10px; /* on the first text line */
	width: 7px;
	height: 7px;
	border-radius: 50%;
	background: var(--wp--preset--color--primary-light);
}
/* Spec list (the book page's Details): label + value rows on hairlines, the
 * shape a retailer's product table takes, in place of the bullet rail. The
 * label is the item's leading <strong> — ordinary list markup the editor can
 * write, no custom block. Overrides the site treatment above rule for rule. */
ul.wp-block-list.poulton-specs {
	max-width: 46rem;
	/* Same sum as `.poulton-sect > p`, and for the same reason: a bare
	 * max-width inside core's constrained layout re-centres the block, which
	 * left the table floating in the middle of the section under a
	 * left-aligned heading. Core sets those auto margins with !important, so
	 * this has to match. */
	margin-left: max(0px, calc((100% - var(--wp--custom--shell--content)) / 2)) !important;
	margin-right: auto !important;
}
ul.wp-block-list.poulton-specs > li {
	display: flex;
	gap: 16px;
	padding: 10px 0;
	border-top: 1px solid var(--wp--preset--color--line);
}
ul.wp-block-list.poulton-specs > li:last-child {
	border-bottom: 1px solid var(--wp--preset--color--line);
}
ul.wp-block-list.poulton-specs > li + li {
	margin-top: 0;
}
ul.wp-block-list.poulton-specs > li::before {
	content: none;
}
ul.wp-block-list.poulton-specs > li > strong {
	flex: 0 0 120px;
	color: var(--wp--preset--color--muted);
	font-weight: 500;
}

/* ---------- Notes (feedback callouts) ----------
 * Semantic notice component on the custom.feedback tokens. Applied via the
 * registered core/group styles (is-style-note-*) or the bare classes. The
 * icon is a masked SVG so it always takes the modifier's ink colour. */
.poulton-note {
	--note-ink: var(--wp--custom--feedback--info--ink);
	--note-tint: var(--wp--custom--feedback--info--tint);
	--note-line: var(--wp--custom--feedback--info--line);
	--note-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cline x1='12' y1='11' x2='12' y2='16.5'/%3E%3Ccircle cx='12' cy='7.6' r='0.4' fill='black'/%3E%3C/svg%3E");
	display: grid;
	grid-template-columns: 28px 1fr;
	column-gap: 14px;
	align-items: start;
	padding: 20px;
	background: var(--note-tint);
	border: 1px solid var(--note-line);
	border-radius: var(--wp--custom--radius--card);
}
.poulton-note::before {
	content: "";
	width: 22px;
	height: 22px;
	margin-top: 1px;
	justify-self: center;
	background: var(--note-ink);
	-webkit-mask: var(--note-icon) no-repeat center / contain;
	mask: var(--note-icon) no-repeat center / contain;
}
.poulton-note > * {
	margin: 0;
	/* advisory copy: keep a readable measure even in a full-width note */
	max-width: 72ch;
}
.poulton-note a {
	color: var(--note-ink);
	font-weight: 600;
}
.poulton-note.poulton-note--success {
	--note-ink: var(--wp--custom--feedback--success--ink);
	--note-tint: var(--wp--custom--feedback--success--tint);
	--note-line: var(--wp--custom--feedback--success--line);
	--note-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M8.5 12.4l2.4 2.4 4.6-5'/%3E%3C/svg%3E");
}
.poulton-note.poulton-note--warning {
	--note-ink: var(--wp--custom--feedback--warning--ink);
	--note-tint: var(--wp--custom--feedback--warning--tint);
	--note-line: var(--wp--custom--feedback--warning--line);
	--note-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 4L2.8 19.5h18.4z'/%3E%3Cline x1='12' y1='10' x2='12' y2='14'/%3E%3Ccircle cx='12' cy='16.8' r='0.4' fill='black'/%3E%3C/svg%3E");
}
.poulton-note.poulton-note--error {
	--note-ink: var(--wp--custom--feedback--error--ink);
	--note-tint: var(--wp--custom--feedback--error--tint);
	--note-line: var(--wp--custom--feedback--error--line);
	--note-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cline x1='9' y1='9' x2='15' y2='15'/%3E%3Cline x1='15' y1='9' x2='9' y2='15'/%3E%3C/svg%3E");
}
/* The registered block styles (Styles picker) are the same component. CSS
 * can't compose classes, so the style spellings restate the modifier vars. */
.wp-block-group.is-style-note-info,
.wp-block-group.is-style-note-success,
.wp-block-group.is-style-note-warning,
.wp-block-group.is-style-note-error {
	--note-ink: var(--wp--custom--feedback--info--ink);
	--note-tint: var(--wp--custom--feedback--info--tint);
	--note-line: var(--wp--custom--feedback--info--line);
	--note-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cline x1='12' y1='11' x2='12' y2='16.5'/%3E%3Ccircle cx='12' cy='7.6' r='0.4' fill='black'/%3E%3C/svg%3E");
	display: grid;
	grid-template-columns: 28px 1fr;
	column-gap: 14px;
	align-items: start;
	padding: 20px;
	background: var(--note-tint);
	border: 1px solid var(--note-line);
	border-radius: var(--wp--custom--radius--card);
}
.wp-block-group.is-style-note-info::before,
.wp-block-group.is-style-note-success::before,
.wp-block-group.is-style-note-warning::before,
.wp-block-group.is-style-note-error::before {
	content: "";
	width: 22px;
	height: 22px;
	margin-top: 1px;
	justify-self: center;
	background: var(--note-ink);
	-webkit-mask: var(--note-icon) no-repeat center / contain;
	mask: var(--note-icon) no-repeat center / contain;
}
.wp-block-group.is-style-note-info > *,
.wp-block-group.is-style-note-success > *,
.wp-block-group.is-style-note-warning > *,
.wp-block-group.is-style-note-error > * {
	margin: 0;
	/* Against the icon, never centred in the track. A note is a constrained
	 * group, and core gives every child of one auto inline margins with
	 * !important — which, on a grid item, centres the capped paragraph and
	 * turns the cap's slack into a gap beside the icon. Same weight, higher
	 * specificity, so this wins. */
	margin-inline: 0 !important;
	/* advisory copy: keep a readable measure even in a full-width note */
	max-width: 72ch;
}
.wp-block-group.is-style-note-info a,
.wp-block-group.is-style-note-success a,
.wp-block-group.is-style-note-warning a,
.wp-block-group.is-style-note-error a {
	color: var(--note-ink);
	font-weight: 600;
}
.wp-block-group.is-style-note-success {
	--note-ink: var(--wp--custom--feedback--success--ink);
	--note-tint: var(--wp--custom--feedback--success--tint);
	--note-line: var(--wp--custom--feedback--success--line);
	--note-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M8.5 12.4l2.4 2.4 4.6-5'/%3E%3C/svg%3E");
}
.wp-block-group.is-style-note-warning {
	--note-ink: var(--wp--custom--feedback--warning--ink);
	--note-tint: var(--wp--custom--feedback--warning--tint);
	--note-line: var(--wp--custom--feedback--warning--line);
	--note-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 4L2.8 19.5h18.4z'/%3E%3Cline x1='12' y1='10' x2='12' y2='14'/%3E%3Ccircle cx='12' cy='16.8' r='0.4' fill='black'/%3E%3C/svg%3E");
}
.wp-block-group.is-style-note-error {
	--note-ink: var(--wp--custom--feedback--error--ink);
	--note-tint: var(--wp--custom--feedback--error--tint);
	--note-line: var(--wp--custom--feedback--error--line);
	--note-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cline x1='9' y1='9' x2='15' y2='15'/%3E%3Cline x1='15' y1='9' x2='9' y2='15'/%3E%3C/svg%3E");
}

/* ---------- Sheet-to-sheet navigation (paired cover cards) ---------- */
.poulton-sheetnav {
	gap: 16px;
}
.poulton-sheetnav-card {
	/* Basis = exactly half the row minus the gap, grow 0: the pair fills the
	 * row, and a LONE first/last card stays the same half width instead of
	 * growing into a giant empty box. Shrink handles narrower rows. Relative,
	 * because the row is the article's reading measure (.poulton-readcol on
	 * the template's nav group), not the 1280 wide size it once was. */
	flex: 0 1 calc(50% - 8px);
	box-sizing: border-box; /* or the padding+border ride on top of the basis */
	display: flex;
	align-items: center;
	gap: 16px;
	padding: 16px;
	background: var(--wp--preset--color--base);
	border: 1px solid rgba(226, 232, 238, 0.9);
	border-radius: var(--wp--custom--radius--card);
	text-decoration: none;
	transition: transform 0.28s ease, box-shadow 0.28s ease;
}
.poulton-sheetnav-card--next {
	/* mirror the row so the pair reads outward: ← card | card → */
	flex-direction: row-reverse;
	text-align: right;
}
/* A lone Next card (first sheet) belongs on the right, not at flex-start.
 * Two classes: core's `.is-layout-flex > * { margin: 0 }` reset outranks a
 * single-class rule by order. */
.poulton-sheetnav .poulton-sheetnav-card--next {
	margin-left: auto;
}
.poulton-sheetnav-cover {
	flex: none;
	width: 56px;
	height: auto;
	border-radius: 6px;
	border: 1px solid var(--wp--preset--color--line);
	display: block;
}
.poulton-sheetnav-text {
	display: block;
	min-width: 0;
}
.poulton-sheetnav-kicker {
	display: block;
	margin-bottom: 4px;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--wp--custom--label--color);
}
.poulton-sheetnav-title {
	display: block;
	font-size: 17px;
	font-weight: 600;
	line-height: 1.35;
	color: var(--wp--preset--color--primary-dark);
	transition: color 0.18s ease;
}
/* Desktop only: the same lift .poulton-tile uses, for the same reason — the
 * whole card is one <a>, so the affordance is honest. Gated on a real pointer
 * so the phone scroller stays flat, and --shadow--card rather than
 * --shadow--lift because at this card size the heavier one reads as a slab.
 *
 * Safe against the reveal: gsap-reveal sits on the .poulton-sheetnav PARENT and
 * has y:0, so no inline transform is ever written to these cards. Switch that
 * wrapper to gsap-reveal-up or gsap-stagger and this lift would lose to the
 * inline transform mid-tween — see docs/animations.md. */
@media (hover: hover) and (pointer: fine) {
	.poulton-sheetnav-card:hover {
		transform: translateY(-2px);
		box-shadow: var(--wp--custom--shadow--card);
	}
	.poulton-sheetnav-card:hover .poulton-sheetnav-title {
		color: var(--wp--preset--color--primary);
	}
}
/* Must live here, not in the shared reduced-motion block above: same
 * specificity, and that block comes earlier in the file, so it would lose the
 * tie. The colour swap stays — it is not motion. */
@media (prefers-reduced-motion: reduce) {
	.poulton-sheetnav-card:hover {
		transform: none;
	}
}
/* Stacked below 782px (the figures' breakpoint too). With the row on the
 * reading measure a half card under that is below ~350px, and a title such
 * as "Oppositional defiant disorder and MERIM" runs to three lines beside
 * its cover; from 783px up each card has room for the title on one. */
@media (max-width: 782px) {
	.poulton-sheetnav-card,
	.poulton-sheetnav-card--next {
		flex: 0 1 100%;
	}
}

/* ---------- Sheet figures ----------
 * The explanation sheets' illustrations, restored from the source PDFs. They
 * are line art on white, so they sit on a faint tinted ground with a hairline
 * rather than floating on the page. */
/* The figure's blur-up placeholder is inlined by poulton-core/inc/figures.php
 * as the image's background, origin and clip included (the frame rule below
 * sets `background` shorthand at a higher weight, which would reset a clip
 * set here — so it is set inline, beside the image). Nothing to draw. */
.poulton-sheet-figure {
	margin: var(--wp--preset--spacing--60) auto;
}
/* Figures take exactly the text measure, so illustration and paragraph share
 * both edges — on the rail pages, where the column leaves 21px beside them
 * at a 1280px viewport and 45px once the shell is at its full width, and
 * on the pages without one. Needs to out-specific core's
 * `.is-layout-constrained > .alignwide` (0,2,0), which otherwise opens these
 * to the full 1280 wide size. They keep `alignwide` all the same: it is what
 * lets them escape core's content cap in the editor. */
.is-layout-constrained > .poulton-sheet-figure.alignwide {
	max-width: min(var(--wp--style--global--content-size), 100%);
}
/* Article figures: the framed-image treatment.
 *
 * One rule for all three long-form post types — the same "what counts as an
 * article" selector the prose rhythm uses further up — so an image block
 * dropped into a future blog post or publication gets this frame automatically.
 * The explanation sheets' figures are core image blocks
 * (<figure class="wp-block-image … poulton-sheet-figure">), so they are covered
 * by the same rule rather than by a copy of it.
 *
 * --radius--figure, NOT --radius--image: despite its name, the image token is a
 * general UI radius shared by the TOC panel, the search results and the "top"
 * button. The figures were softened to 8px deliberately; the rounding is on the
 * frame, and the artwork inside keeps square corners behind the 12px padding —
 * a print-figure look rather than a card.
 *
 * The border is the `line` hairline on purpose. A primary-light border was
 * tried and rejected — on line art the blue frame competed with the drawing. */
:is(.single-explanation_sheet, .single-post, .single-publication) .entry-content .wp-block-image img {
	display: block;
	width: 100%;
	height: auto;
	padding: 12px;
	box-sizing: border-box;
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--figure);
}
.poulton-sheet-figure figcaption {
	margin-top: 12px;
	font-size: 13.5px;
	line-height: 1.55;
	color: var(--wp--preset--color--muted);
	text-align: left;
}
/* The credit line is a credit, not a caption — it carries the attribution the
 * artwork used to carry as pixels, so it must be legible, but it should not
 * compete with the figure. */
.poulton-fig-credit {
	color: var(--wp--custom--label--color);
	font-size: 12.5px;
}
.poulton-sheet-figure figcaption a {
	color: var(--wp--preset--color--primary);
}
@media (max-width: 782px) {
	.is-layout-constrained > .poulton-sheet-figure.alignwide {
		max-width: 100%;
	}
}

/* ---------- Article tables ----------
 * Every table on the three article types, by selector rather than by class:
 * the sheets' two comparisons, the reproduced papers' results tables, and
 * whatever the client pastes into a post all take the same look with
 * nothing to remember. The frame is the figure frame's — hairline, the
 * figure radius — so a table and an illustration read as the same kind of
 * object; the head is a surface tint under a primary-light rule; cells are
 * divided by hairlines and the frame supplies the outer edge. The sheets'
 * own class stays as an alias. */
:is(.single-explanation_sheet, .single-post, .single-publication) .entry-content .wp-block-table,
.poulton-sheet-table {
	margin: var(--wp--preset--spacing--60) 0;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--figure);
	background: var(--wp--preset--color--base);
	/* the frame clips the corners; a wide table scrolls inside it on a phone */
	overflow: hidden;
	overflow-x: auto;
}
/* The figure is focusable so that scroll can be driven by a keyboard
 * (inc/tables.php); the site's ring, on the frame. */
:is(.single-explanation_sheet, .single-post, .single-publication) .entry-content .wp-block-table:focus-visible,
.poulton-sheet-table:focus-visible {
	outline: 3px solid var(--wp--preset--color--primary);
	outline-offset: 3px;
}
:is(.single-explanation_sheet, .single-post, .single-publication) .entry-content .wp-block-table table,
.poulton-sheet-table table {
	border-collapse: collapse;
	table-layout: auto; /* a label column sizes to its labels, not to a fixed share */
	width: 100%;
	margin: 0;
	border: 0;
}
:is(.single-explanation_sheet, .single-post, .single-publication) .entry-content .wp-block-table :is(th, td),
.poulton-sheet-table :is(th, td) {
	padding: 12px 16px;
	border: 1px solid var(--wp--preset--color--line);
	text-align: left;
	vertical-align: top;
	font-size: 15px;
	line-height: 1.55;
	color: var(--wp--preset--color--contrast);
}
/* No outer cell borders — the frame is the edge. */
:is(.single-explanation_sheet, .single-post, .single-publication) .entry-content .wp-block-table tr > :first-child,
.poulton-sheet-table tr > :first-child {
	border-left: 0;
}
:is(.single-explanation_sheet, .single-post, .single-publication) .entry-content .wp-block-table tr > :last-child,
.poulton-sheet-table tr > :last-child {
	border-right: 0;
}
/* …the table's first and last rows, not each section's: the head's last
 * row keeps its rule under it. */
:is(.single-explanation_sheet, .single-post, .single-publication) .entry-content .wp-block-table table > :first-child > tr:first-child > *,
.poulton-sheet-table table > :first-child > tr:first-child > * {
	border-top: 0;
}
:is(.single-explanation_sheet, .single-post, .single-publication) .entry-content .wp-block-table table > :last-child > tr:last-child > *,
.poulton-sheet-table table > :last-child > tr:last-child > * {
	border-bottom: 0;
}
:is(.single-explanation_sheet, .single-post, .single-publication) .entry-content .wp-block-table thead th,
.poulton-sheet-table thead th {
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--primary-dark);
	font-weight: 600;
	line-height: 1.4;
	border-bottom: 2px solid var(--wp--preset--color--primary-light);
}
/* The row label: a table with a head reads its first column as labels. */
:is(.single-explanation_sheet, .single-post, .single-publication) .entry-content .wp-block-table thead ~ tbody > tr > td:first-child,
.poulton-sheet-table thead ~ tbody > tr > td:first-child {
	font-weight: 500;
}
/* A section inside a table: a row whose one cell is a bold phrase and
 * nothing else (AJGP's boxes — "Stage 1: …"). The converter writes these;
 * the client can make one by bolding a full-row cell. Tinted like the
 * head, so the table reads in parts. */
:is(.single-explanation_sheet, .single-post, .single-publication) .entry-content .wp-block-table tbody > tr > td:only-child:has(> strong:only-child),
.poulton-sheet-table tbody > tr > td:only-child:has(> strong:only-child) {
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--primary-dark);
	font-size: 14px;
	padding-block: 10px;
}
/* Core's own figure styles would otherwise put a border on the table and a
 * caption centred beneath it; ours are set above and on the caption rule. */
:is(.single-explanation_sheet, .single-post, .single-publication) .entry-content .wp-block-table.has-fixed-layout table {
	table-layout: auto;
}

/* ---------- "On this page" ----------
 * One component, two presentations. The markup (plugin/poulton-core/inc/toc.php)
 * is a <nav> holding a <details>, rendered collapsed.
 *
 * Under 1080px it is a slim pill that STAYS under the header for the whole
 * article: a small "ON THIS PAGE" kicker over the name of the section you are
 * in, with a hairline progress line along its bottom edge; tapping it drops
 * the full index down. From 1080px up the same element becomes a card in the
 * right margin with the index open.
 *
 * The surface is `surface.sandSoft` — the `sand` token mixed a quarter of the
 * way to white (theme.json). The Explanation Sheets band is full sand; this sits on body
 * text next to white tiles, so it takes the lighter mix. It is a mix rather
 * than a second hex so there is still exactly one warm value in the palette
 * (docs/design-direction.md, "Sand: one warm surface, one warm accent").
 *
 * <details> means the disclosure works with no JavaScript at all; toc.js only
 * marks the section you are reading and fills in its name.
 *
 * The strip is opaque on purpose. The header pill is the site's ONLY blurred
 * surface (see .poulton-navpill::before) because blur is expensive during
 * scroll, and this element is sticky during scroll — a second backdrop-filter
 * would spend that budget twice for no visible gain. */
.poulton-article {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: 28px;
}
.poulton-toc {
	--poulton-read: 0%;
	position: sticky;
	/* The header pill's bottom edge is 72px and --nav-clear is 96px at phone
	 * widths, so the strip floats 8px under it — the same gap the header keeps
	 * from the top of the window. It sticks only while .poulton-article is in
	 * view, which is exactly the span you are reading. */
	top: calc(var(--wp--custom--shell--nav-clear) - 16px);
	z-index: 20; /* under the header (30) */
	font-size: 14px;
	line-height: 1.45;
	/* The strip's footprint in the flow. The panel itself is taken OUT of flow
	 * below, so opening it paints over the article instead of growing the page
	 * — a sticky element that grows reflows everything under it, and the words
	 * you were reading jump. Two lines once the scroll-spy has located you —
	 * kicker over section name — so it is taller than a single-line pill;
	 * the scroll-padding-top under 1080px below is tied to this number. */
	min-height: 52px;
}
.poulton-toc-details {
	position: absolute;
	inset: 0 0 auto 0;
	/* The theme sets no global border-box, so without this the 1px border is
	 * added outside any max-width and the strip sits past the column edge. */
	box-sizing: border-box;
}
/* Clear space for the strip, full-bleed so it covers the page gutters as well
 * as the article column.
 *
 * Sized to the strip's SHADOW, not to its box. When it stopped 8px below, the
 * lower two-thirds of the shadow was painted over a fading veil and then over
 * live article text — which made the shadow look patchy, the hairline look
 * broken, and left this band's own fade boundary showing as a ghost edge
 * around the control. It is opaque from the top of the strip through the
 * shadow's 8px of reach below it, and fades only where it is hidden behind the
 * header pill above and over the last 4px below — a skirt any deeper visibly
 * veils the heading underneath.
 *
 * Painted before the strip: both are absolute in the nav's stacking context,
 * so tree order puts the strip on top. */
.poulton-toc::before {
	content: "";
	position: absolute;
	left: -24px;
	right: -24px;
	top: -22px;
	bottom: -14px;
	background: linear-gradient(
		rgba(255, 255, 255, 0),
		var(--wp--preset--color--base) 22%,
		var(--wp--preset--color--base) 95%,
		rgba(255, 255, 255, 0)
	);
	pointer-events: none;
}
.poulton-toc-details {
	background: var(--wp--custom--surface--sand-soft);
	border: 1px solid var(--wp--preset--color--line);
	/* The card's radius, not the pill's: two lines of text in a capsule read
	 * as a button, and the open panel already uses this radius. */
	border-radius: var(--wp--custom--radius--image);
	/* Not --shadow--pill: that is sized for the header floating over a hero.
	 * This is a 46px strip sitting on body text, and every pixel the shadow
	 * reaches has to be backed by opaque clear space — which is content the
	 * strip then hides. So it is drawn tight: 8px of reach, not 26. */
	box-shadow: 0 1px 2px rgba(6, 32, 62, 0.05),
		0 4px 10px -6px rgba(6, 32, 62, 0.16);
	/* Padding lives on the summary and the list, never here: an open <details>
	 * puts its children in a ::details-content box, so a height or flex rule on
	 * <details> never reaches the list — which also makes <details> itself the
	 * only workable scroll container. */
	padding: 0;
}
.poulton-toc-details[open] {
	right: 0;
	border-radius: var(--wp--custom--radius--image);
	max-height: 60vh;
	overflow-y: auto;
	overscroll-behavior: contain;
	scrollbar-width: thin;
}
/* More index below the fold. An INSET shadow, not the overlay the card uses:
 * inset shadows are painted against the scroll container's own box and stay
 * pinned, where an absolutely positioned overlay would have to hang off the
 * nav — and here the nav is only as tall as the strip, because the panel is
 * out of flow. */
.poulton-toc.has-more .poulton-toc-details[open] {
	box-shadow: 0 1px 2px rgba(6, 32, 62, 0.05),
		0 4px 10px -6px rgba(6, 32, 62, 0.16),
		inset 0 -16px 14px -14px rgba(6, 32, 62, 0.18);
}
.poulton-toc summary {
	position: sticky;
	top: 0;
	z-index: 1;
	/* A grid, not a flex row: the caption and the section name are siblings
	 * (no wrapper in the markup, and toc.js writes into .poulton-toc-here), so
	 * stacking them means the icon and chevron span two rows. With no section
	 * named yet the second row is empty and collapses to 0 (see :empty below),
	 * and align-content keeps the lone caption centred rather than letting the
	 * empty row take half the height. */
	display: grid;
	grid-template-columns: auto minmax(0, 1fr) auto;
	grid-template-areas:
		"icon caption chevron"
		"icon here chevron";
	column-gap: 10px;
	align-items: center;
	align-content: center;
	/* 44px: a comfortable target rather than the 24px WCAG floor, and the
	 * height the strip is designed around. Border-box, because once located
	 * the summary carries vertical padding, and a content-box minimum would
	 * add the 44px on top of it (measured: a 64px strip). */
	box-sizing: border-box;
	min-height: 44px;
	padding: 0 16px;
	background: var(--wp--custom--surface--sand-soft);
	/* Stated, never inherited. A <details> slots its children into a
	 * ::details-content box, so `border-radius: inherit` here resolves against
	 * THAT box's initial 0 rather than against <details> — and the summary's
	 * opaque background then painted a square white rectangle over the pill's
	 * rounded ends, which is why the corners looked clipped. (Same root cause
	 * as ::details-content swallowing height rules, further up.) */
	border-radius: var(--wp--custom--radius--image);
	cursor: pointer;
	list-style: none;
	color: var(--wp--preset--color--contrast);
}
.poulton-toc summary::-webkit-details-marker {
	display: none;
}
/* Three stacked rules — a contents mark. Drawn in borders so it costs no
 * request and inherits the label colour. */
.poulton-toc-icon {
	grid-area: icon;
	flex: none;
	position: relative;
	width: 13px;
	height: 9px;
	border-top: 1.5px solid var(--wp--custom--label--color);
	border-bottom: 1.5px solid var(--wp--custom--label--color);
}
.poulton-toc-icon::after {
	content: "";
	position: absolute;
	left: 0;
	top: 50%;
	width: 9px;
	border-top: 1.5px solid var(--wp--custom--label--color);
	transform: translateY(-50%);
}
.poulton-toc-caption {
	grid-area: caption;
	font-weight: 600;
	letter-spacing: -0.005em;
}
/* One label at a time (see toc.php). display:none on purpose: the unused
 * label must leave the accessible name, not just the screen. */
.poulton-toc-caption-here {
	display: none;
}
/* Never rendered: it exists only to separate the two halves of the summary's
 * accessible name. Present only while there are two halves to separate. */
.poulton-toc-sep {
	display: none;
}
/* Once the scroll-spy knows a section, the separator is hidden VISUALLY only —
 * it stays in the accessible name ("On this page: Side effects") so the
 * control still reads as one phrase. The clip technique is load-bearing:
 * display:none would drop it out of the accessibility tree entirely, which is
 * the whole thing it exists for. (The caption used to be clipped here too; it
 * now stays on screen as the kicker, styled in the phone media query below.) */
.poulton-toc.is-located .poulton-toc-sep {
	display: inline;
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}
.poulton-toc-here {
	grid-area: here;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-size: 13.5px;
	font-weight: 500;
	line-height: 1.3;
	color: var(--wp--preset--color--contrast);
}
/* Empty until toc.js names a section: collapse the row so the caption sits
 * alone, single-line, exactly as before the scroll-spy runs. */
.poulton-toc-here:empty {
	display: none;
}
/* Chevron drawn from two borders, so it rotates with the disclosure state. */
.poulton-toc summary::after {
	content: "";
	grid-area: chevron;
	justify-self: end;
	flex: none;
	margin-left: auto;
	width: 8px;
	height: 8px;
	border-right: 1.6px solid var(--wp--custom--label--color);
	border-bottom: 1.6px solid var(--wp--custom--label--color);
	transform: translateY(-2px) rotate(45deg);
	transition: transform 0.2s ease;
}
/* Open, the summary caps a scrolling panel: round the top only, or the list
 * would run under a rounded bottom edge. */
.poulton-toc-details[open] summary {
	border-radius: var(--wp--custom--radius--image) var(--wp--custom--radius--image) 0 0;
}
.poulton-toc-details[open] summary::after {
	transform: translateY(1px) rotate(-135deg);
}
.poulton-toc summary:focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: -3px;
}
/* How far through the article you are. It sits on the SUMMARY, not on
 * <details>: on <details> it would scroll out of the panel the moment the
 * index opened. */
.poulton-toc-progress {
	position: absolute;
	left: 16px;
	right: 16px;
	bottom: 6px;
	/* 3px, not a hairline: it is the one reading gauge on the phone and has
	 * to register under a two-line strip. */
	height: 3px;
	border-radius: 3px;
	background: rgba(6, 32, 62, 0.06);
	overflow: hidden;
}
.poulton-toc-progress::after {
	content: "";
	display: block;
	width: var(--poulton-read);
	height: 100%;
	border-radius: inherit;
	background: var(--wp--preset--color--primary);
}

.poulton-toc-list,
.poulton-toc-sub {
	list-style: none;
	margin: 0;
	padding: 0;
}
.poulton-toc-list {
	padding: 2px 12px 14px;
}
.poulton-toc-sub {
	/* Indented against the rule, not with it, so the hierarchy reads without
	 * a second border. */
	padding-left: 14px;
}
.poulton-toc a {
	display: block;
	/* 32px rows: taller than the 24px WCAG floor, and the padding does the
	 * separating so the list needs no rules. */
	padding: 6px 10px;
	border-radius: 8px;
	color: var(--wp--preset--color--muted);
	text-decoration: none;
	transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease;
}
.poulton-toc-list > li > a {
	font-weight: 500;
	color: var(--wp--preset--color--contrast);
}
.poulton-toc a:hover,
.poulton-toc a[aria-current="true"] {
	color: var(--wp--preset--color--primary);
	border-left-color: var(--wp--preset--color--primary);
}
.poulton-toc a[aria-current="true"] {
	font-weight: 600;
	background: var(--wp--preset--color--surface);
}
.poulton-toc a:focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: -2px;
}

@media (max-width: 1079px) {
	/* A tapped anchor has to clear the strip as well as the header. :has()
	 * keeps this to the pages that actually carry an index — everywhere else
	 * the plain scroll-padding-top at the top of this file still applies.
	 * The constant is the strip's min-height (above) plus 8px of air. */
	:root:has(.poulton-toc) {
		scroll-padding-top: calc(var(--wp--custom--shell--nav-clear) + 60px);
	}
	/* Located: the caption shrinks to a kicker above the section name. Top
	 * padding is lighter than bottom because the progress line lives in the
	 * bottom 6px and the name must not sit on it. */
	.poulton-toc.is-located summary {
		/* Bottom-heavy: the progress line lives in the bottom 6px and the
		 * section name must not sit on it. */
		padding: 7px 16px 11px;
		row-gap: 2px;
	}
	.poulton-toc.is-located .poulton-toc-caption-index {
		display: none;
	}
	.poulton-toc.is-located .poulton-toc-caption-here {
		display: inline;
	}
	/* A touch larger on the phone, where it is the only mark on the strip. */
	.poulton-toc-icon {
		width: 16px;
		height: 11px;
		border-width: 2px;
	}
	.poulton-toc-icon::after {
		width: 11px;
		border-top-width: 2px;
	}
	.poulton-toc.is-located .poulton-toc-caption {
		font-size: 10.5px;
		line-height: 1.2;
		letter-spacing: 0.06em;
		text-transform: uppercase;
		color: var(--wp--custom--label--color);
	}
}

@media (min-width: 1080px) {
	/* The rail takes the right margin the 900px measure already leaves inside
	 * the 1280px article. The content column (≈990px) holds the measure with
	 * 45px to spare either side, so nothing about the reading column changes.
	 * The second column may be empty: a sheet without an index still reserves
	 * it so its article lines up with its hero (toc.php). */
	.poulton-article {
		grid-template-columns: minmax(0, 1fr) var(--poulton-toc-rail);
		gap: var(--poulton-toc-gap);
		align-items: start;
	}
	.poulton-article > .entry-content {
		grid-column: 1;
		grid-row: 1;
	}
	.poulton-toc {
		grid-column: 2;
		grid-row: 1;
		top: var(--wp--custom--shell--nav-clear);
		min-height: 0;
	}
	/* Blocks that share the article's reading measure but sit OUTSIDE the grid
	 * — each template's hero, the sheets' closing note. Left to core they
	 * centre their 900px in the full width, which is 145px right of where the
	 * article's text now sits, because the rail took 290px out of it.
	 *
	 * This is the same sum the grid does — centre in what is left once the rail
	 * is reserved — so the two agree at every width by construction rather than
	 * by coincidence. !important because core's constrained layout sets these
	 * auto margins with !important. A right rail is a page-level decision:
	 * anything sharing the measure has to know it exists.
	 *
	 * Keyed on the wrapper, not the index: a sheet reserves the column even
	 * when it has no index to put in it (toc.php), and these blocks have to
	 * follow the column, not the nav. */
	/* A publication's hero takes the wide column — the measure plus the
	 * rail — so the citation card and the buttons use the width the article
	 * below has; only the title stays on the measure, for its line length.
	 * The readcol's left margin (the rule below) is unchanged, so the column
	 * sits inset 21px each side of the article container, as the text is. */
	.single-publication main:has(.poulton-article) .poulton-module--band .poulton-readcol {
		max-width: calc(var(--wp--style--global--content-size) + var(--poulton-toc-rail) + var(--poulton-toc-gap));
	}
	.single-publication .poulton-module--band .poulton-readcol > .wp-block-post-title {
		/* a little wider than the measure: at the display size a title's
		 * lines are short in words, and 120px more keeps them from breaking
		 * every three or four */
		max-width: calc(var(--wp--style--global--content-size) + 120px);
	}
	main:has(.poulton-article) .poulton-readcol {
		margin-left: max(
			0px,
			calc(
				(
						100% - var(--poulton-toc-rail) - var(--poulton-toc-gap) -
							var(--wp--style--global--content-size)
					) / 2
			)
		) !important;
		margin-right: auto !important;
	}
	/* Back in flow: the card lives in its own grid column, so its height never
	 * touches the reading column and it can size to the index. */
	.poulton-toc-details {
		position: static;
	}
	/* Here the component is a card rather than a strip, and the index is open
	 * inside it. Long ones (sheet 06 has 44 entries, ~1960px) scroll within
	 * the card instead of running off the bottom of the screen. */
	.poulton-toc-details,
	.poulton-toc-details[open] {
		border-radius: var(--wp--custom--radius--image);
		box-shadow: var(--wp--custom--shadow--card);
		/* The bottom gap was 32px, which is what the card wants for itself. It
		 * is now the back-to-top chip's footprint instead: the chip is aligned
		 * to this card's left edge and sits at the foot of the same column, so
		 * without the extra clearance a maxed index (this sheet's 44 entries)
		 * runs to 32px off the bottom and the chip paints over its last
		 * entries. Costs the index 48px of visible height; it scrolls. */
		max-height: calc(
			100vh - var(--wp--custom--shell--nav-clear) -
				var(--poulton-to-top-clear)
		);
		overflow-y: auto;
		overscroll-behavior: contain;
		scrollbar-width: thin;
	}
	/* Full-bleed white, so the index passes cleanly under it as it scrolls. */
	.poulton-toc summary,
	.poulton-toc-details[open] summary {
		/* Flex again: the icon is hidden here, and the phone grid would keep a
		 * 10px column gap for its empty track. */
		display: flex;
		min-height: 0;
		padding: 15px 16px 11px;
		font-size: 12.5px;
		font-weight: 600;
		letter-spacing: 0.06em;
		text-transform: uppercase;
		color: var(--wp--custom--label--color);
	}
	/* The card's own radius, for the same reason as the strip's: an opaque
	 * summary with square corners paints over the rounded ones beneath it.
	 * The base rule for [open] (0,2,1) still rounds only the top when the
	 * index is showing. */
	.poulton-toc summary {
		border-radius: var(--wp--custom--radius--image);
	}
	/* The card keeps its heading at the summary's own size; the phone kicker
	 * sizing is scoped to the max-width query so nothing to undo here. */
	.poulton-toc-caption {
		font-size: inherit;
		letter-spacing: inherit;
	}
	/* The highlighted row already says where you are, and the card is not
	 * sticky chrome you glance at — so no section name and no progress line. */
	.poulton-toc-here,
	.poulton-toc-progress,
	.poulton-toc::before {
		display: none;
	}
	.poulton-toc.is-located .poulton-toc-sep {
		display: none;
	}
	/* The rule doubles as the active-position indicator — only useful here,
	 * where the whole list is on screen beside the text. In the phone panel it
	 * would just be 44 stripes. */
	.poulton-toc a {
		margin-left: 4px;
		padding-left: 14px;
		border-left: 2px solid var(--wp--preset--color--line);
		border-radius: 0 8px 8px 0;
	}
	.poulton-toc-sub {
		padding-left: 12px;
	}
	/* More index below the fold: fade the card's bottom edge so the clipped row
	 * reads as "there is more" rather than as a mis-drawn border. Painted on
	 * the nav, not inside the scroller, where it would scroll away with the
	 * list — which is why it is a card-only device: on the phone the panel is
	 * out of flow and the nav's bottom edge is the strip's, not the panel's.
	 * Only while toc.js says there is more to see; a permanent fade over the
	 * last entry once you have reached the end looks like a fault. */
	.poulton-toc.has-more::after {
		content: "";
		position: absolute;
		left: 1px;
		right: 1px;
		bottom: 1px;
		height: 32px;
		border-radius: 0 0 var(--wp--custom--radius--image) var(--wp--custom--radius--image);
		background: linear-gradient(
			transparent,
			var(--wp--custom--surface--sand-soft) 78%
		);
		pointer-events: none;
	}
}

@media (prefers-reduced-motion: reduce) {
	.poulton-toc summary::after,
	.poulton-toc a {
		transition: none;
	}
}

/* ---------- Share this page ----------
 * Monochrome circles on the site's own tokens, rather than a plugin's brand
 * colours and icon sprite. Every link is a plain href, so nothing is fetched
 * from Meta, LinkedIn or X until a reader actually clicks — which is the whole
 * reason this is 40 lines of CSS instead of a plugin. */
/* An author `display` beats the UA sheet's [hidden] rule, so the two
 * JavaScript-only controls would render as dead buttons for everyone. They ship
 * hidden; view.js reveals whichever one the browser can actually honour. */
.poulton-share [hidden] {
	display: none !important;
}
.poulton-share__list {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	margin: 10px 0 0;
	padding: 0;
	list-style: none;
}
.poulton-share__btn {
	/* 40px: comfortably past the 24px WCAG 2.5.8 floor without the row
	 * becoming the loudest thing at the end of the article. */
	display: flex;
	align-items: center;
	justify-content: center;
	/* The theme sets no global border-box, and <button> takes it from the UA
	 * sheet while <a> does not — so without this the links come out 42px and
	 * the copy button 40px. */
	box-sizing: border-box;
	width: 40px;
	height: 40px;
	padding: 0;
	/* Solid ink with the mark knocked out in white. A hairline circle on white
	 * left the marks barely there; this is the most visible treatment that
	 * still ends a quiet article in one colour rather than five brand ones. */
	background: var(--wp--preset--color--contrast);
	border: 0;
	border-radius: 50%;
	color: var(--wp--preset--color--base);
	cursor: pointer;
	/* 0.22s, the Contact page's copy button's timing, so the two confirm at
	 * the same pace. */
	transition: background-color 0.22s ease;
}
.poulton-share__btn:hover {
	background: var(--wp--preset--color--primary);
}
/* Copied: the Contact page's confirmation — success palette for two seconds,
 * then back — adapted to a solid circle. Contact's button is tint, hairline
 * and ink; a knocked-out mark on a tint would vanish, so the circle takes the
 * success INK solid and the mark stays white. Hover mid-confirm stays green,
 * or the button would flash blue in the middle of saying "done". */
.poulton-share__btn.is-copied,
.poulton-share__btn.is-copied:hover {
	background: var(--wp--custom--feedback--success--ink);
}
.poulton-share__icon {
	flex: none;
}
/* The copy button's two marks, one at a time. Both 19px, so the swap moves
 * nothing. */
.poulton-share__icon--done,
.is-copied .poulton-share__icon--idle {
	display: none;
}
.is-copied .poulton-share__icon--done {
	display: block;
}
/* Each control's accessible name. Hidden from sight, never from the
 * accessibility tree — display:none would take it out of the name entirely,
 * which is the one thing it exists for. */
.poulton-share__name {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}
/* The device's own share sheet, on a phone. Built to the same 40px height as
 * the row it replaces, so swapping them shifts nothing below. */
.poulton-share__native {
	display: flex;
	align-items: center;
	gap: 8px;
	height: 40px;
	margin-top: 10px;
	padding: 0 20px;
	background: var(--wp--custom--surface--raised);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--pill);
	color: var(--wp--preset--color--contrast);
	font-size: 14px;
	font-weight: 600;
	cursor: pointer;
}
.poulton-share.is-native .poulton-share__list {
	display: none;
}
/* ---------- The foot of a sheet: share + download ----------
 * On the sheet template the share block sits in a flex row with the PDF
 * button on the far side (template: .poulton-sheet-foot). The download is an
 * end-of-read action there, not a hero one: a PDF button at the top invites
 * the reader off the page before they have read it, and the sheet IS the
 * article. Publications keep theirs in the hero — the paper is the thing.
 *
 * The row carries .poulton-readcol and so does the share block inside it
 * (render.php, for the templates where it stands alone). No double shift:
 * the rail offset is max(0px, (100% - rail - gap - measure) / 2), and inside
 * a row that is already the measure that sum is negative, so it clamps to
 * zero. Bottom-aligned so the button's baseline meets the 40px circles. */
/* The download glyph used to be a ::after here; it is now the site-wide
 * ::before every PDF button carries (.poulton-btn-pdf, marked at render by
 * poulton-core/inc/pdf-links.php), so this row needs nothing of its own. */
/* "Link copied", beside the check for the two seconds the check shows. Hung
 * off the copy button with absolute positioning, so it takes no room in the
 * row: a line that appeared under the circles moved the foot of the article
 * each time, which is why it left there. Fades and slides in at the same
 * 0.22s as the circle's colour; :empty is the resting state, so clearing the
 * text is what fades it out. The list carries the marks' colour weight, so
 * this is success ink, not another circle. */
.poulton-share__copy {
	position: relative;
}
.poulton-share__status {
	position: absolute;
	top: 50%;
	left: calc(100% + 12px);
	margin: 0;
	font-size: 14px;
	font-weight: 600;
	line-height: 1;
	white-space: nowrap;
	color: var(--wp--custom--feedback--success--ink);
	opacity: 1;
	transform: translate(0, -50%);
	transition: opacity 0.22s ease, transform 0.22s ease;
}
.poulton-share__status:empty {
	opacity: 0;
	transform: translate(-6px, -50%);
}

/* ---------- Contact form ----------
 * The two panes on /contact/: the form, and beside it the address card and
 * the For GPs card. A grid on the group rather than core Columns, which is
 * how every other side-by-side on the site is built. The row is the form's
 * height and the right column is asked to match it: the address card keeps
 * its own height and the For GPs card takes the rest (its rule below). */
.poulton-contact {
	display: grid;
	grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
	gap: 20px;
	align-items: stretch;
}
/* The grid supplies the gap; core's flow layout would add its
 * margin-block-start to the second pane on top of it. */
.poulton-contact > .wp-block-group {
	margin-block-start: 0;
}
/* Below this the aside's two-fifths, less the card's 40px padding, no
 * longer holds the address pill on one line (~276px at 15px for the current
 * address), so the panes stack. Measured at 960: aside 357px, inner 277px.
 * Re-measure if the address, the pill's padding or the card padding
 * changes. */
@media (max-width: 959px) {
	.poulton-contact {
		grid-template-columns: minmax(0, 1fr);
	}
}
/* The right column: the address card, then the For GPs card, at the
 * grid's own gap. A flex column rather than two grid cells, so the pair
 * still lands as one cell when the grid collapses to a single column. */
.poulton-contact__side {
	display: flex;
	flex-direction: column;
	gap: 20px;
}
.poulton-contact__side > .wp-block-group {
	margin-block-start: 0;
}
/* The For GPs card fills whatever the row leaves under the address card,
 * so the two columns end on one line. Its words sit at the top; the home
 * band's fan of clinical-tool pages (the gp-fan synced block, last in the
 * card) is not a pile above them but a PEEK: the pages slide out from
 * under the card's bottom-right corner, clipped by its rounded edge, and
 * take exactly the height that is spare — 150px at 1440, less on a
 * narrower desktop, none if the copy wraps enough to use it all. A square
 * picture could never do that; it needs the same height at every width. */
.poulton-contact__gp {
	flex: 1 1 auto;
	position: relative;
	overflow: hidden; /* the clip: pages outside the card are not drawn */
}
/* The fan box: the card's last flex item, the spare height and no more.
 * min-height: 0 is what stops the box adding to the card's own minimum, so
 * the column never grows past the form on its account. It bleeds to the
 * card's right and bottom edges (the negative margins undo the card's
 * padding) so the pages can run off the corner. */
.poulton-contact__gp .poulton-gp-fan {
	flex: 1 1 0;
	min-height: 0;
	aspect-ratio: auto;
	max-width: none;
	width: auto;
	margin: 0 calc(-1 * var(--wp--preset--spacing--60)) calc(-1 * var(--wp--preset--spacing--60)) 0;
	/* A size container, so the pages can be dropped when the box is too
	 * short to show more than a sliver of them (the query below). */
	container-type: size;
}
/* The pages hang from the box's TOP edge and the card's bottom edge clips
 * them: what shows is exactly the box's height, so the peek is 110px deep
 * at 1440 and shallower as the copy takes more of the card. 160px wide —
 * the phone band's page — and spread along the card's whole width (the
 * offsets are shares of the box, so the spread scales with the card) with
 * each top a few pixels off the last and its own tilt, so they read as a
 * row of forms laid out rather than a stack in the corner. The front page
 * runs off the right edge. Only `top`/`right` and the tilt differ from
 * the pile's rules, so gp-fan.js's rise (a `translate` that composes with
 * the rotate) plays unchanged. */
.poulton-contact__gp .poulton-gp-fan-page {
	left: auto;
	width: 160px;
}
.poulton-contact__gp .poulton-gp-fan-page:nth-child(1) { top: 18px; right: 62%; transform: rotate(-9deg); }
.poulton-contact__gp .poulton-gp-fan-page:nth-child(2) { top: 4px;  right: 41%; transform: rotate(-3deg); }
.poulton-contact__gp .poulton-gp-fan-page:nth-child(3) { top: 10px; right: 20%; transform: rotate(3deg); }
.poulton-contact__gp .poulton-gp-fan-page:nth-child(4) { top: 0;    right: -2%; transform: rotate(8deg); }
/* On a phone nothing stretches the card, so the box holds a short band
 * for the peek instead, and the row of pages closes up: four 160px pages
 * across a ~290px box at the desktop spread ran the back page off the
 * card's LEFT edge, which is the one edge they should not cross. */
@media (max-width: 959px) {
	.poulton-contact__gp .poulton-gp-fan {
		flex-basis: 150px;
	}
	.poulton-contact__gp .poulton-gp-fan-page:nth-child(1) { right: 44%; }
	.poulton-contact__gp .poulton-gp-fan-page:nth-child(2) { right: 29%; }
	.poulton-contact__gp .poulton-gp-fan-page:nth-child(3) { right: 14%; }
}
/* Under 56px the box shows only a sliver of page tops along the card's
 * edge — a smudge, not a picture — so the pages go. That is the case on a
 * narrow desktop (960–1100), where the copy wraps to four lines. */
@container (max-height: 56px) {
	.poulton-gp-fan-page {
		display: none;
	}
}
/* The seal sat on the pile's top-right corner, which is now the part of
 * the pile under the card. The copy already says the PDFs are free. */
.poulton-contact__gp .poulton-gp-seal {
	display: none;
}

.poulton-contact-form__form {
	display: flex;
	flex-direction: column;
	gap: 16px;
	margin-top: 6px;
}
.poulton-contact-form__field {
	display: flex;
	flex-direction: column;
	gap: 6px;
}
.poulton-contact-form__field label {
	font-size: 14px;
	font-weight: 600;
	color: var(--wp--preset--color--contrast);
}
/* The search field's recipe (.wp-block-search__input), at the same height,
 * on the card radius: a pill reads as one line, and the message field is
 * not. Same radius on the single-line fields too, so the three stack as one
 * family rather than two pills and a box. 16px, so iOS does not zoom the
 * page on focus. */
.poulton-contact-form__input {
	box-sizing: border-box;
	width: 100%;
	min-height: 48px;
	padding: 11px 16px;
	border: 1.5px solid var(--wp--preset--color--line);
	border-radius: 14px;
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
	font: inherit;
	font-size: 16px;
	line-height: 1.5;
	appearance: none;
	transition: border-color 0.18s ease;
}
.poulton-contact-form__input:hover {
	border-color: var(--wp--preset--color--primary-light);
}
/* Focus is the border going to ink plus a soft halo on the field's own
 * radius, instead of the site's 3px offset outline. On a stack of fields
 * 16px apart the outline + offset landed 5px past the box and crowded the
 * next label — it read as the fields jumping. The halo stays inside the
 * gap and follows the corners in every browser. */
.poulton-contact-form__input:focus-visible {
	outline: none;
	border-color: var(--wp--preset--color--primary);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--wp--preset--color--primary) 22%, transparent);
}
.poulton-contact-form__textarea {
	min-height: 160px;
	resize: vertical;
}
/* The honeypot: off-canvas, never display:none — a script that skips hidden
 * fields would skip the one field meant to catch it. aria-hidden and
 * tabindex=-1 on the markup keep it out of the reading order and the Tab
 * order; this only keeps it out of sight. */
.poulton-contact-form__hp {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}
.poulton-contact-form__status {
	margin: 0;
	font-size: 14px;
	color: var(--wp--custom--feedback--error--ink);
}
.poulton-contact-form__status:empty {
	display: none;
}
/* "All fields are required" — said once, up front, instead of learned one
 * browser bubble at a time. */
.poulton-contact-form__hint {
	margin: 0;
	font-size: 14px;
	color: var(--wp--preset--color--muted);
}
/* The per-field error view.js writes under an invalid field. It stays on the
 * page, unlike the browser's bubble, and the field points at it through
 * aria-describedby. The border picks the same ink so a colour-blind reader
 * has the text and a screen reader has the description. */
.poulton-contact-form__error {
	margin: 0;
	font-size: 14px;
	color: var(--wp--custom--feedback--error--ink);
}
.poulton-contact-form__field [aria-invalid="true"] {
	border-color: var(--wp--custom--feedback--error--ink);
}
.poulton-contact-form__actions {
	margin-top: 4px;
}
.poulton-contact-form__actions .wp-block-button__link {
	cursor: pointer;
}
.poulton-contact-form__actions .wp-block-button__link[disabled] {
	opacity: 0.7;
	cursor: progress;
}
/* The note that replaces the form. The success note's grid puts the icon in
 * its own column; the tabindex is for the focus view.js moves here, and the
 * outline that would follow a programmatic focus is not wanted. */
.poulton-contact-form__done,
.poulton-contact-form__failed {
	margin-top: 6px;
}
.poulton-contact-form__done:focus {
	outline: none;
}

/* The address pill and its copy button. The copy button ships hidden and an
 * author display would beat [hidden] (see .poulton-share [hidden]). */
.poulton-copy-email [hidden] {
	display: none !important;
}
.poulton-copy-email {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px;
	margin-top: 4px;
}
.poulton-copy-email__link {
	/* Core gives every .wp-block-button__link `height: 100%` — of its own
	 * shrink-wrapped .wp-block-button that is nothing, but here the link is
	 * a flex item, and once the Copy button wraps to a second line on a
	 * phone, 100% is the whole two-line container: a 125px pill with the
	 * button hanging out under it. Its own height, then. */
	height: auto;
	/* On a phone the address is wider than the card. render.php prints it as
	 * two inline-block halves split after the @, so the pill wraps there and
	 * only there — "contact@ / poultonadhd.com.au" — and never mid-word. */
	text-align: left;
}
.poulton-copy-email__part {
	display: inline-block;
}
.poulton-copy-email__copy {
	/* The outline button, restated: CSS cannot compose is-style-outline. */
	display: inline-flex;
	align-items: center;
	gap: 8px;
	box-sizing: border-box;
	/* the pill's own padding, so the two come out the same height */
	padding: 11px 18px;
	background: var(--wp--preset--color--base);
	border: 1.5px solid rgba(226, 232, 238, 0.9);
	border-radius: var(--wp--custom--radius--pill);
	color: var(--wp--preset--color--primary-dark);
	font: inherit;
	font-size: 15px;
	font-weight: 500;
	line-height: 1.45;
	cursor: pointer;
	transition: background 0.22s ease, color 0.22s ease, border-color 0.22s ease;
}
.poulton-copy-email__copy:hover {
	border-color: var(--wp--preset--color--primary-light);
	color: var(--wp--preset--color--primary);
}
.poulton-copy-email__copy.is-copied {
	background: var(--wp--custom--feedback--success--tint);
	border-color: var(--wp--custom--feedback--success--line);
	color: var(--wp--custom--feedback--success--ink);
}
.poulton-copy-email__icon {
	flex: none;
}
/* The rest of the accessible name ("Copy email address"), out of sight. */
.poulton-copy-email__name {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}
/* The live region for "Email address copied": for screen readers only. The
 * button's own label is the visible feedback, and a line that appears for
 * two seconds under the pill moved the card's bottom edge each time. */
.poulton-copy-email__status {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

/* ---------- The tray: Listen chip + Back to top ----------
 * The row of chips at the foot of the window (functions.php,
 * poulton_render_tray). Two members, each fading on its own timetable:
 *
 *   .poulton-listen-chip  "Listen · 15 min" — on pages with a narration, while
 *                         the hero's Listen button is off-screen and nothing is
 *                         playing. blocks/listen/view.js decides; it is the
 *                         second way in for the reader who scrolled past the
 *                         hero and then decided to listen. The moment play
 *                         starts it goes, and the docked player takes over.
 *   .poulton-to-top       "Top" — on pages long enough to have lost their own
 *                         top. assets/js/back-to-top.js owns the decision: at
 *                         least three viewports tall, and the reader a screen
 *                         and a half down.
 *
 * Both ship hidden and the scripts add .is-visible. Everything about how they
 * look is here; everything about when they show is there.
 *
 * The tray, not the chips, is what is positioned, and TOP NEVER MOVES. It
 * holds the corner on a phone and the rail's left edge on desktop, and the
 * Listen chip grows out beside it — to Top's left on the phone, to its right
 * on desktop — and collapses away again. A reader who has located Top must
 * never find it somewhere else because a second chip came or went; the
 * chip that appears is the one that moves.
 *
 * Done as a two-column grid whose Listen column animates 0fr ↔ 1fr, the
 * standard way to animate to an auto width: the tray is shrink-to-fit, so
 * 1fr resolves to the chip's own width, and 0fr with min-width:0 on the chip
 * is nothing at all. The column gap animates with it, so a collapsed chip
 * leaves no 8px hole beside Top. (The first cut kept a hidden chip's box in
 * a flex row; Top then floated 170px in from the phone's corner with nothing
 * beside it for the first screen and a half of every sheet.) */
.poulton-tray {
	position: fixed;
	right: 24px;   /* the shell's own gutter — header and footer pad to the same */
	bottom: 24px;
	/* Over the contents rail (20), under the header pill (30) — so the pill and
	 * its mobile overlay always win. */
	z-index: 25;
	display: grid;
	grid-template-columns: auto 0fr; /* [Top] [Listen →] from the rail's edge */
	align-items: center;
	column-gap: 0;
	transition: grid-template-columns 0.22s ease, column-gap 0.22s ease;
	/* The tray's own box — the gap, and a collapsing chip's — must never
	 * swallow a tap meant for the text underneath it. */
	pointer-events: none;
}
.poulton-tray:has(.poulton-listen-chip.is-visible) {
	grid-template-columns: auto 1fr;
	column-gap: 8px;
}
.poulton-tray > * {
	pointer-events: auto;
}
/* Placed explicitly, so on a page with no Listen chip (/contact/) Top still
 * takes the auto column rather than the 0fr one. The row too: the chip comes
 * first in the DOM, and auto-placement never walks back, so a Top told only
 * "column 1" would land on a second row under it. */
.poulton-to-top {
	grid-column: 1;
	grid-row: 1;
}
.poulton-listen-chip {
	grid-column: 2;
	grid-row: 1;
	min-width: 0;     /* lets the 0fr column reach zero */
	overflow: hidden; /* the disc and the words clip as the column narrows */
}
/* min-width:0 only lets the CONTENT reach zero; the 25px of padding and the
 * hairline would still hold a 27px stub open beside Top. Both go to nothing
 * with the column, on the same clock. The transition lists below are the
 * chip's own (further down) plus these two properties, and carry the tray's
 * selector so they outrank .poulton-chip / .poulton-chip.is-visible, which
 * come later in the file and would otherwise win on equal specificity. */
.poulton-tray .poulton-listen-chip:not(.is-visible) {
	padding: 0;
	border-width: 0;
}
.poulton-tray .poulton-listen-chip {
	transition: opacity 0.22s ease, transform 0.22s ease, visibility 0s linear 0.22s,
		padding 0.22s ease, border-width 0.22s ease;
}
.poulton-tray .poulton-listen-chip.is-visible {
	transition: opacity 0.22s ease, transform 0.22s ease, visibility 0s,
		padding 0.22s ease, border-width 0.22s ease;
}
@media (max-width: 1079px) {
	/* [← Listen] [Top] into the corner */
	.poulton-tray {
		grid-template-columns: 0fr auto;
	}
	.poulton-tray:has(.poulton-listen-chip.is-visible) {
		grid-template-columns: 1fr auto;
	}
	.poulton-to-top {
		grid-column: 2;
	}
	.poulton-listen-chip {
		grid-column: 1;
	}
}
.poulton-chip {
	display: flex;
	align-items: center;
	gap: 6px;
	/* 40px clears the 24px WCAG 2.5.8 floor with room, the same call the TOC
	 * summary makes. */
	height: 40px;
	padding: 0 14px 0 11px;
	background: var(--wp--custom--surface--sand-soft);
	/* Not the `line` token. Over the footer's pale-blue gradient a hairline in
	 * that grey leaves the chip with no edge at all — exactly what happened to
	 * the nav pill when the hero was softened, which is why its border is ink
	 * at this alpha (see .poulton-navpill::before). Same value, same reason. */
	border: 1px solid rgba(6, 32, 62, 0.16);
	/* The card's 24px on a 40px-tall chip is three-quarters of the way to a
	 * capsule and stops reading as a rectangle; 18px keeps the flat edges. The
	 * contents card lands on the same value for the same reason. */
	border-radius: var(--wp--custom--radius--image);
	box-shadow: var(--wp--custom--shadow--pill);
	/* The site's small-label idiom, lifted from the desktop TOC summary — but
	 * in primary-dark rather than the label grey, so the word carries the same
	 * weight as the arrow beside it. */
	color: var(--wp--preset--color--primary-dark);
	font: inherit;
	font-size: 12.5px;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	white-space: nowrap;
	cursor: pointer;
	opacity: 0;
	visibility: hidden;
	transform: translateY(6px);
	/* visibility is stepped, not eased: it holds through the fade out and
	 * switches instantly on the way in. Hidden it leaves the tab order, so the
	 * chip is never a focus stop on a page that has not shown it. */
	transition: opacity 0.22s ease, transform 0.22s ease, visibility 0s linear 0.22s;
}
.poulton-chip.is-visible {
	opacity: 1;
	visibility: visible;
	transform: none;
	transition: opacity 0.22s ease, transform 0.22s ease, visibility 0s;
}
/* The global reduced-motion sweep is declared earlier in the file and loses on
 * source order here — the rule carries its own, as the dock does. */
@media (prefers-reduced-motion: reduce) {
	.poulton-chip,
	.poulton-tray,
	.poulton-tray .poulton-listen-chip,
	.poulton-tray .poulton-listen-chip.is-visible {
		transition: none;
	}
}
/* Shadow and surface only, no transform: a transform hover would need its own
 * line in the reduced-motion sweep above, and this reads as well without one. */
.poulton-chip:hover {
	background: var(--wp--preset--color--sand);
	box-shadow: var(--wp--custom--shadow--lift);
}
/* Focus comes from the global button:focus-visible ring. */
.poulton-to-top-arrow {
	width: 18px;
	height: 18px;
	background: var(--poulton-to-top-icon) center / contain no-repeat;
}
/* A solid clay disc with the play glyph — the dock's play button at 24px, in
 * the hero Listen button's colour. In a row of two look-alike sand pills this
 * is what says "audio" at a glance; the word alone would not. */
.poulton-listen-chip__icon {
	display: grid;
	place-items: center;
	width: 24px;
	height: 24px;
	border-radius: 50%;
	background: var(--wp--preset--color--highlight);
	color: var(--wp--preset--color--base);
	transition: background 0.22s ease;
}
.poulton-listen-chip:hover .poulton-listen-chip__icon {
	background: var(--wp--custom--highlight--hover);
}
.poulton-listen-chip__icon svg {
	margin-left: 1px; /* the play glyph sits a hair left of centre in its box */
}
/* "· 15 min" in the muted grey the dock's clock uses, so the verb leads. */
.poulton-listen-chip__meta {
	color: var(--wp--preset--color--muted);
	font-weight: 500;
}
.poulton-listen-chip:disabled {
	cursor: default;
}

/* Core's mobile navigation overlay covers the whole viewport; the tray must not
 * float on top of it. */
html.has-modal-open .poulton-tray {
	opacity: 0;
	visibility: hidden;
}

/* The explanation sheets get printed. */
@media print {
	.poulton-tray {
		display: none;
	}
}

/* From 1080px the contents index becomes a sticky right rail capped at
 * calc(100vh - nav-clear - 32px), so a long one — ADHD in adulthood runs to 49
 * screens — reaches within 32px of the bottom of the window, and a chip in the
 * corner would sit on its last entries. Step left of the rail's footprint on
 * the pages that have one, using the rail's own tokens so the two cannot drift.
 *
 * Aligned to the RAIL'S LEFT EDGE, so the tray reads as the foot of the index
 * column rather than floating loose in the margin. That edge is the content
 * column's right edge less the rail, and the column centres itself once the
 * window is wider than 1280px — so the sum has to be done, not guessed: a plain
 * offset from the window edge tracks the rail only while the column is
 * full-width, and at 1920 it landed the chip 250px INSIDE the index.
 *
 * Percentages, not 100vw. For a fixed element both resolve against the viewport
 * except that 100vw INCLUDES the classic scrollbar and the containing block
 * does not, which would push the chip half a scrollbar right of the edge it is
 * supposed to line up with — invisible here, visible on Windows.
 *
 * Sharing the column also means sharing the vertical space: the rail subtracts
 * --poulton-to-top-clear from its max-height so a long index stops above the
 * tray rather than behind it.
 *
 * Keyed on the article wrapper rather than the index, so a sheet that
 * reserves the column without filling it (sheet 03) still parks the tray in
 * it, and the tray sits in the same place on every sheet. */
@media (min-width: 1080px) {
	:root:has(.poulton-article) .poulton-tray {
		right: auto;
		left: calc(
			100% - max(24px, (100% - var(--wp--custom--shell--content)) / 2) -
				var(--poulton-toc-rail)
		);
	}
}

/* ---------- Listen: the docked player ----------
 * Appears at the foot of the window the moment play is first pressed, and
 * stays until Close or the end of the narration (blocks/listen/view.js
 * decides; the markup is printed by blocks/listen/dock.php into <body>, past
 * every transformed ancestor — see the containing-block note there).
 *
 * Its footprint is 16px + 56px = 72px, inside --poulton-to-top-clear (80px),
 * so from 1080px the contents rail already stops above it. Centred and no
 * wider than 520px it also clears the back-to-top chip at the rail's left
 * edge at every desktop width (at 1080 the dock's right edge is 800px and
 * the chip starts at 806). Below 1080 the chip sits bottom-right and would
 * land on the dock, so it steps up while the dock is showing — further down.
 *
 * z-index 25: over the contents rail (20), under the header pill (30), the
 * same layer as the chip. Like the chip, visibility is stepped so the dock
 * leaves the tab order when hidden. */
.poulton-listen-dock {
	position: fixed;
	left: 50%;
	bottom: calc(16px + env(safe-area-inset-bottom, 0px));
	z-index: 25;
	box-sizing: border-box;
	width: min(520px, 100% - 32px);
	height: 56px;
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 0 8px;
	/* The contents card's sand, not the raised white: floating over a white
	 * article the white dock read as part of the page, and the tint is what
	 * sets it off. The tray's chips and the "On this page" card sit on the
	 * same surface, so the three pieces of floating chrome match. The speed
	 * button stays white, so it still stands off the dock (below). */
	background: var(--wp--custom--surface--sand-soft);
	/* Ink at this alpha, not the `line` token — the chip's reason, above. */
	border: 1px solid rgba(6, 32, 62, 0.16);
	border-radius: var(--wp--custom--radius--pill);
	box-shadow: var(--wp--custom--shadow--lift);
	color: var(--wp--preset--color--primary-dark);
	opacity: 0;
	visibility: hidden;
	transform: translate(-50%, 8px);
	transition: opacity 0.22s ease, transform 0.22s ease, visibility 0s linear 0.22s;
}
/* The global reduced-motion sweep is declared earlier in the file, so it loses
 * this tie on source order — the rule carries its own, as the chip does. */
@media (prefers-reduced-motion: reduce) {
	.poulton-listen-dock {
		transition: none;
	}
}
/* display:flex above would beat the UA sheet's [hidden]. */
.poulton-listen-dock[hidden] {
	display: none !important;
}
.poulton-listen-dock.is-visible {
	opacity: 1;
	visibility: visible;
	transform: translate(-50%, 0);
	transition: opacity 0.22s ease, transform 0.22s ease, visibility 0s;
}
.poulton-listen-dock button {
	font: inherit;
	cursor: pointer;
	flex: none;
}
/* 40px: comfortably past the 24px WCAG 2.5.8 floor, the share buttons' size. */
.poulton-listen-dock__play {
	display: grid;
	place-items: center;
	width: 40px;
	height: 40px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	/* Highlight clay, the hero Listen button's own colour: the play disc is
	 * the same clay in the dock, in the tray chip and on the sheet cards, so
	 * "clay disc = listen" reads everywhere. White glyph on it: 5.07:1. */
	background: var(--wp--preset--color--highlight);
	color: var(--wp--preset--color--base);
	transition: background 0.22s ease;
}
.poulton-listen-dock__play:hover {
	background: var(--wp--custom--highlight--hover);
}
.poulton-listen-dock__icon--pause,
.poulton-listen-dock.is-playing .poulton-listen-dock__icon--play {
	display: none;
}
.poulton-listen-dock.is-playing .poulton-listen-dock__icon--pause {
	display: block;
}
/* The play glyph sits a hair left of centre in its box; nudge it. */
.poulton-listen-dock__icon--play {
	margin-left: 2px;
}
.poulton-listen-dock__body {
	flex: 1 1 auto;
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 0;
}
/* The site's small-label idiom, as on the chip and the desktop contents
 * summary. */
.poulton-listen-dock__label {
	font-size: 11.5px;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	line-height: 1.2;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
/* The seek bar is the browser's own range input, tinted. It is keyboard-
 * operable as it stands (arrow keys step a second, Home/End jump), which no
 * hand-built slider gets without a page of ARIA. */
.poulton-listen-dock__seek {
	display: block;
	width: 100%;
	/* 28, not 20: the input's box is the touch target and WCAG 2.5.8 wants
	 * 24 — at 20px on a phone the thumb was the easiest miss in the dock. The
	 * track the browser draws stays thin; only the hit area grows. */
	height: 28px;
	margin: 0;
	padding: 0;
	cursor: pointer;
	accent-color: var(--wp--preset--color--primary);
}
.poulton-listen-dock__time {
	flex: none;
	min-width: 5.5ch;
	text-align: right;
	font-size: 13px;
	font-variant-numeric: tabular-nums;
	color: var(--wp--preset--color--muted);
}
.poulton-listen-dock__rate {
	height: 32px;
	min-width: 50px;
	padding: 0 10px;
	border: 1.5px solid rgba(226, 232, 238, 0.9);
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--primary-dark);
	font-size: 13px;
	font-weight: 600;
	font-variant-numeric: tabular-nums;
	transition: border-color 0.22s ease, color 0.22s ease;
}
.poulton-listen-dock__rate:hover {
	border-color: var(--wp--preset--color--primary-light);
	color: var(--wp--preset--color--primary);
}
.poulton-listen-dock__close {
	display: grid;
	place-items: center;
	width: 32px;
	height: 32px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: transparent;
	color: var(--wp--preset--color--muted);
	transition: background 0.22s ease, color 0.22s ease;
}
.poulton-listen-dock__close:hover {
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--primary-dark);
}
/* Focus comes from the global button:focus-visible ring. */

/* Core's mobile navigation overlay covers the whole viewport; the dock must
 * not float on top of it — the chip's rule, repeated. */
html.has-modal-open .poulton-listen-dock {
	opacity: 0;
	visibility: hidden;
}

/* Below the rail breakpoint the tray is bottom-right and the two would
 * overlap; while the dock is showing, the tray steps up over it (its 24px
 * offset + the dock's 56px + 12px of air). */
@media (max-width: 1079px) {
	:root:has(.poulton-listen-dock.is-visible) .poulton-tray {
		bottom: calc(24px + 56px + 12px + env(safe-area-inset-bottom, 0px));
	}
}
/* The dock is fixed over the page, so without this the last lines of a sheet
 * and the footer's email sit under it for as long as the audio plays. Room
 * for the dock, its 16px offset and a little air, on the body so every page
 * bottom moves together. Goes with the dock's visibility, not its [hidden]:
 * the padding must appear the moment the dock does. */
:root:has(.poulton-listen-dock.is-visible) body {
	padding-bottom: calc(56px + 16px + 16px + env(safe-area-inset-bottom, 0px));
}

/* On a phone the label gives its room to the seek bar; the time stays. */
@media (max-width: 599px) {
	.poulton-listen-dock {
		width: calc(100% - 24px);
		gap: 8px;
	}
	.poulton-listen-dock__label {
		display: none;
	}
}

/* The explanation sheets get printed. */
@media print {
	.poulton-listen,
	.poulton-listen-dock {
		display: none;
	}
}

/* ---------- Search: the results page ----------
 * The field is the core search block, which arrives unstyled — the site had
 * no text field before search. Its input takes the overlay's field recipe
 * and its button joins the pills (the box-model rule under Buttons), so the
 * 404 page's copy of the block is dressed the same way for free. */
.wp-block-search {
	max-width: 560px;
}
.wp-block-search__inside-wrapper {
	gap: 8px;
}
.wp-block-search__input {
	box-sizing: border-box;
	flex: 1 1 auto;
	min-width: 0;
	height: 48px;
	padding: 0 18px;
	border: 1.5px solid rgba(226, 232, 238, 0.9);
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
	font: inherit;
	font-size: 16px;
	appearance: none;
}
.wp-block-search__input:hover,
.wp-block-search__input:focus-visible {
	border-color: var(--wp--preset--color--primary-light);
}
.wp-block-search__input::placeholder {
	color: var(--wp--preset--color--muted);
	opacity: 1;
}
.wp-block-search__button {
	margin-left: 0;
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--base);
	cursor: pointer;
}
.wp-block-search__button:hover {
	background: var(--wp--preset--color--primary-dark);
}
/* The field is capped at 560px so it does not run the width of the column —
 * and core's constrained layout centres any child narrower than the column
 * with `margin-inline: auto !important`, which floated the field 80px in from
 * the heading above it. The same sum as `.poulton-sect > p` under Sections,
 * against the shell width the search header uses. The 404's field needs no
 * such rule: it sits inside a column there, which is flow layout, and a
 * column child is not centred. */
.poulton-sect.poulton-pagehead > .wp-block-search {
	margin-left: max(0px, calc((100% - var(--wp--custom--shell--content)) / 2)) !important;
	margin-right: auto !important;
}
/* Results are core's three-column grid, the blog's and the archive's. Core
 * holds those three columns all the way down to its own 600px collapse, which
 * leaves three ~230px tiles through the 601-900 band — a seven-line tower for
 * a publication title that runs 130 characters. Two through that band; below
 * 600 core's own rule takes it to one. Measured, not guessed: three columns
 * are 268px at 900 and 201px at 700. */
@media (min-width: 601px) and (max-width: 900px) {
	.search .wp-block-post-template.is-layout-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}
/* Three lines, not the listing's two: the snippet is the sentence that says
 * why this result matched, and at a third of the column ~160 characters is
 * three lines. The grid equalises row height anyway (.poulton-tile-actions
 * pins Read more to the bottom edge), so the longer clamp costs no
 * raggedness. */
.search .poulton-tile-excerpt .wp-block-post-excerpt__excerpt {
	-webkit-line-clamp: 3;
}
.poulton-search-empty {
	max-width: 46rem;
}
/* The matched words, in the overlay and on the results page. Surface blue
 * rather than the sand: a third warm value is what the palette note forbids,
 * and deep blue on the surface tint is ~11.6:1 at any size. */
.poulton-search-dialog mark,
.search .poulton-tile mark {
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--primary-dark);
	padding: 0 2px;
	margin: 0 -2px;
	border-radius: 3px;
}

/* ---------- Search: the overlay ----------
 * A native <dialog> (blocks/search/overlay.php) opened with showModal(), so
 * it sits in the top layer: above the pill with no z-index, and outside any
 * containing block. Top-anchored like a command palette, not centred — the
 * list under the field grows and shrinks as the reader types, and a centred
 * box would jump with it. The page behind is dimmed, not blurred: the nav
 * pill is the site's one blurred surface, on purpose (its note). */
/* ---------- PDF buttons and the preview dialog ----------
 * Every PDF link is marked at render (poulton-core/inc/pdf-links.php):
 * Download PDF carries the download glyph, Preview the eye. The glyph is a
 * mask painted in currentColor, so it reads on the filled highlight, the
 * outline and the source box's white buttons alike. Lucide, as data URIs. */
.poulton-btn-pdf,
.poulton-btn-preview {
	display: inline-flex;
	align-items: center;
	gap: 8px;
}
.poulton-btn-pdf::before,
.poulton-btn-preview::before {
	content: "";
	flex: none;
	width: 16px;
	height: 16px;
	background: currentColor;
	-webkit-mask: var(--pdf-icon) no-repeat center / contain;
	mask: var(--pdf-icon) no-repeat center / contain;
}
.has-small-font-size .poulton-btn-pdf::before,
.has-small-font-size .poulton-btn-preview::before,
.poulton-btn-pdf.has-small-font-size::before {
	width: 14px;
	height: 14px;
}
.poulton-btn-pdf {
	/* the site's one download glyph, defined at :root */
	--pdf-icon: var(--poulton-download-icon);
}
.poulton-btn-preview {
	--pdf-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.06 12.35a1 1 0 0 1 0-.7 10.75 10.75 0 0 1 19.88 0 1 1 0 0 1 0 .7 10.75 10.75 0 0 1-19.88 0'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E");
}

/* The preview dialog: the search dialog's shell (see .poulton-search-dialog
 * for why the backdrop colour is a literal and how it arrives), sized for a
 * page of A4 rather than a list. */
.poulton-pdf-dialog {
	box-sizing: border-box;
	width: min(1100px, 100% - 32px);
	height: min(88dvh, 900px);
	max-height: 88vh;
	margin: auto;
	padding: 0;
	border: 1px solid rgba(6, 32, 62, 0.16);
	border-radius: var(--wp--custom--radius--card);
	background: var(--wp--custom--surface--raised);
	box-shadow: var(--wp--custom--shadow--lift);
	color: var(--wp--preset--color--contrast);
	overflow: hidden;
}
.poulton-pdf-dialog::backdrop {
	background: rgba(0, 47, 108, 0.32);
}
.poulton-pdf-dialog[open] {
	opacity: 1;
	translate: 0 0;
	transition: opacity 160ms ease, translate 160ms ease;
}
@starting-style {
	.poulton-pdf-dialog[open] {
		opacity: 0;
		translate: 0 -8px;
	}
}
html.poulton-pdf-open {
	overflow: hidden;
	scrollbar-gutter: stable;
}
.poulton-pdf__panel {
	display: flex;
	flex-direction: column;
	height: 100%;
}
.poulton-pdf__head {
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 12px 12px 12px 20px;
	border-bottom: 1px solid var(--wp--preset--color--line);
}
.poulton-pdf__title {
	flex: 1 1 auto;
	min-width: 0;
	margin: 0;
	font-size: 16px;
	font-weight: 500;
	line-height: 1.3;
	color: var(--wp--preset--color--primary-dark);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.poulton-pdf__download {
	flex: none;
	padding: 8px 16px;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--base);
	font-size: 14px;
	font-weight: 500;
	text-decoration: none;
	transition: background 0.22s ease;
}
.poulton-pdf__download:hover {
	background: var(--wp--preset--color--primary-dark);
}
.poulton-pdf__close {
	flex: none;
	display: grid;
	place-items: center;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: transparent;
	color: var(--wp--preset--color--muted);
	cursor: pointer;
	transition: background 0.22s ease, color 0.22s ease;
}
.poulton-pdf__close:hover {
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--primary-dark);
}
.poulton-pdf__status {
	margin: 0;
	padding: 8px 20px;
	font-size: 14px;
	color: var(--wp--preset--color--muted);
}
.poulton-pdf__status[hidden] {
	display: none;
}
/* The body holds the frame and, under it, a page-shaped placeholder that
 * shows until the PDF paints: a sheet of A4 on the surface, with a slow
 * shimmer. This is the one loading state on the site that stands in for
 * content still to come — a multi-page PDF really does take a moment,
 * and the frame was blank until it arrived. The card grids get no such
 * thing: they are server-rendered, so a skeleton there would be painted
 * over content already on the page (and the hero's book skeleton was
 * removed for exactly that, see .poulton-hero-books). The frame's own
 * background is transparent so the sheet shows through; a PDF paints
 * its pages opaque, so nothing shows through once it has. */
.poulton-pdf__body {
	position: relative;
	flex: 1 1 auto;
	min-height: 0;
	overflow: hidden; /* a page taller than the frame is cut at the foot, as a real page would be */
	background: var(--wp--preset--color--surface);
}
.poulton-pdf__frame {
	position: relative;
	z-index: 1;
	width: 100%;
	height: 100%;
	border: 0;
	background: transparent;
}
.poulton-pdf__page {
	position: absolute;
	top: 24px;
	left: 50%;
	width: min(100% - 48px, 640px);
	aspect-ratio: 1 / 1.414; /* A4; never squashed to fit — the body clips it */
	translate: -50% 0;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: 4px;
	background: var(--wp--preset--color--base);
	box-shadow: var(--wp--custom--shadow--card);
	overflow: hidden;
}
.poulton-pdf__page[hidden] {
	display: none;
}
@media (prefers-reduced-motion: no-preference) {
	.poulton-pdf__page::after {
		content: "";
		position: absolute;
		inset: 0;
		background: linear-gradient(100deg, transparent 30%, var(--wp--preset--color--surface) 50%, transparent 70%);
		background-size: 250% 100%;
		animation: poulton-shimmer 1.6s linear infinite;
	}
}
@keyframes poulton-shimmer {
	from { background-position: 150% 0; }
	to { background-position: -50% 0; }
}

.poulton-search-dialog {
	box-sizing: border-box;
	width: min(640px, 100% - 32px);
	max-height: 80vh;
	max-height: min(80dvh, 720px);
	margin: max(12vh, 24px) auto auto;
	padding: 0;
	border: 1px solid rgba(6, 32, 62, 0.16);
	border-radius: var(--wp--custom--radius--card);
	background: var(--wp--custom--surface--raised);
	box-shadow: var(--wp--custom--shadow--lift);
	color: var(--wp--preset--color--contrast);
	overflow: hidden;
}
/* A literal, not the primary-dark token: Chromium before 122 cannot resolve a
 * custom property inside ::backdrop. */
.poulton-search-dialog::backdrop {
	background: rgba(0, 47, 108, 0.32);
}
/* Arrives rather than appears. @starting-style is the only way to transition
 * from display: none; a browser without it simply shows the dialog. */
.poulton-search-dialog[open] {
	opacity: 1;
	translate: 0 0;
	transition: opacity 160ms ease, translate 160ms ease;
}
@starting-style {
	.poulton-search-dialog[open] {
		opacity: 0;
		translate: 0 -8px;
	}
}
/* The dialog does not lock the page behind it; the class view.js sets does.
 * scrollbar-gutter keeps the width a classic scrollbar was taking, so the
 * fixed pill does not shift when the bar goes. */
html.poulton-search-open {
	overflow: hidden;
	scrollbar-gutter: stable;
}
.poulton-search__panel {
	display: flex;
	flex-direction: column;
	gap: 16px;
	box-sizing: border-box;
	max-height: 80vh;
	max-height: min(80dvh, 720px);
	padding: 16px;
	overflow: auto;
	overscroll-behavior: contain;
}
.poulton-search__form {
	display: flex;
	align-items: center;
	gap: 8px;
}
.poulton-search__field {
	position: relative;
	flex: 1 1 auto;
	min-width: 0;
}
.poulton-search__glass {
	position: absolute;
	left: 18px;
	top: 50%;
	translate: 0 -50%;
	color: var(--wp--preset--color--muted);
	pointer-events: none;
}
.poulton-search__input {
	box-sizing: border-box;
	width: 100%;
	height: 52px;
	padding: 0 18px 0 48px;
	border: 1.5px solid rgba(226, 232, 238, 0.9);
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
	font: inherit;
	/* 16px is where iOS stops zooming a focused field; 18 is what the
	 * dialog's one job deserves. */
	font-size: 18px;
	appearance: none;
}
.poulton-search__input::placeholder {
	color: var(--wp--preset--color--muted);
	opacity: 1;
}
.poulton-search__input::-webkit-search-cancel-button,
.poulton-search__input::-webkit-search-decoration {
	-webkit-appearance: none;
	appearance: none;
}
.poulton-search__input:hover,
.poulton-search__input:focus-visible {
	border-color: var(--wp--preset--color--primary-light);
}
.poulton-search__close {
	flex: none;
	display: grid;
	place-items: center;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: transparent;
	color: var(--wp--preset--color--muted);
	cursor: pointer;
	transition: background 0.22s ease, color 0.22s ease;
}
.poulton-search__close:hover {
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--primary-dark);
}
/* The idle state: the six sheets as chips. Their own class, not .poulton-pill
 * — that is an 11px label in a 24px box, too small to be a target. */
.poulton-search__idle {
	display: flex;
	flex-direction: column;
	gap: 10px;
}
.poulton-search__idle[hidden] {
	display: none;
}
.poulton-search__kicker {
	margin: 0;
	font-size: 11.5px;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	line-height: 1.2;
	color: var(--wp--preset--color--muted);
}
.poulton-search__topics {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}
.poulton-search__topic {
	display: inline-block;
	padding: 8px 14px;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--primary);
	font-size: 13.5px;
	font-weight: 500;
	line-height: 1.4;
	text-decoration: none;
	transition: background 0.22s ease, color 0.22s ease;
}
.poulton-search__topic:hover {
	background: color-mix(in srgb, var(--wp--preset--color--surface) 70%, var(--wp--preset--color--primary-light));
	color: var(--wp--preset--color--primary-dark);
}
/* Results: kind, title, the sentence that matched. The row is one link. */
.poulton-search__results {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 2px;
}
.poulton-search__results[hidden] {
	display: none;
}
.poulton-search__result-link {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 4px;
	padding: 12px 14px;
	border-radius: var(--wp--custom--radius--image);
	color: inherit;
	text-decoration: none;
	transition: background 0.16s ease;
}
.poulton-search__result-link:hover,
.poulton-search__result-link:focus-visible {
	background: var(--wp--preset--color--surface);
}
.poulton-search__title {
	font-size: 16px;
	font-weight: 500;
	line-height: 1.3;
	letter-spacing: -0.01em;
	color: var(--wp--preset--color--primary-dark);
}
.poulton-search__snippet {
	font-size: 14px;
	line-height: 1.5;
	color: var(--wp--preset--color--muted);
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	overflow: hidden;
}
.poulton-search__status {
	margin: 0;
	font-size: 13.5px;
	line-height: 1.5;
	color: var(--wp--preset--color--muted);
}
.poulton-search__status:empty {
	display: none;
}
.poulton-search__all {
	align-self: flex-start;
}
/* .poulton-readmore is inline-block, which would beat the UA [hidden]. */
.poulton-search__all[hidden] {
	display: none;
}
@media (max-width: 600px) {
	.poulton-search-dialog {
		width: calc(100% - 16px);
		max-height: calc(100vh - 16px);
		max-height: calc(100dvh - 16px);
		margin: 8px auto auto;
	}
	.poulton-search__panel {
		max-height: calc(100vh - 16px);
		max-height: calc(100dvh - 16px);
	}
}
/* Reduced motion: the global sweep under Prose zeroes every transition,
 * including the dialog's arrival — nothing to add here. */
@media print {
	.poulton-search,
	.poulton-search-dialog {
		display: none;
	}
}

/* ---------- PHN webinar (For GPs page) ----------
 * The still with its play disc beside a short text column, in one card. The
 * video block (blocks/video) is a facade: view.js swaps the still for the
 * YouTube iframe on a press, and the frame takes the still's box exactly, so
 * nothing moves when it does. */
.poulton-webinar {
	margin-top: var(--wp--preset--spacing--70);
	display: grid;
	grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
	gap: clamp(24px, 4vw, 56px);
	align-items: center;
	padding: clamp(16px, 2.4vw, 28px);
	background: var(--wp--preset--color--lilac);
	border-radius: var(--wp--custom--radius--module);
}
.poulton-webinar > * {
	margin-block: 0;
}
.poulton-webinar__text {
	padding-right: clamp(0px, 2vw, 24px);
}
.poulton-webinar__text h3 {
	margin-block-start: 8px;
}
.poulton-webinar__meta {
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--muted);
}
.poulton-webinar__link a {
	font-weight: 600;
	color: var(--wp--preset--color--primary-dark);
	text-underline-offset: 3px;
}
.poulton-webinar__link a::after {
	content: " ↗";
}
@media (max-width: 899px) {
	.poulton-webinar {
		grid-template-columns: minmax(0, 1fr);
		border-radius: var(--wp--custom--radius--card);
	}
	.poulton-webinar__text {
		padding: 0 8px 8px;
	}
}

.poulton-video {
	position: relative;
	aspect-ratio: 16 / 9;
	border-radius: var(--wp--custom--radius--card);
	overflow: hidden;
	background: var(--wp--preset--color--contrast);
	box-shadow: var(--wp--custom--shadow--card);
	transition: box-shadow 0.3s ease;
}
.poulton-video:hover,
.poulton-video:focus-within {
	box-shadow: var(--wp--custom--shadow--lift);
}
.poulton-video__poster,
.poulton-video__frame {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	border: 0;
	display: block;
}
.poulton-video__poster {
	cursor: pointer;
	color: var(--wp--preset--color--base);
}
.poulton-video__poster:focus-visible {
	outline: 3px solid var(--wp--preset--color--primary);
	outline-offset: -6px;
	border-radius: var(--wp--custom--radius--card);
}
.poulton-video__poster img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}
/* The play control sits bottom-left as a pill, not a disc in the centre: a
 * centred disc landed on the title of the PHN's slide. */
.poulton-video__play {
	position: absolute;
	left: clamp(12px, 2vw, 20px);
	bottom: clamp(12px, 2vw, 20px);
	display: inline-flex;
	align-items: center;
	gap: 10px;
	padding: 6px 16px 6px 6px;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
	font-size: 15px;
	font-weight: 600;
	box-shadow: 0 10px 28px -10px rgba(6, 32, 62, 0.55);
	transition: transform 0.25s ease;
}
.poulton-video__icon {
	width: 40px;
	height: 40px;
	display: grid;
	place-items: center;
	border-radius: 50%;
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--base);
	transition: background-color 0.25s ease;
}
.poulton-video__icon svg {
	margin-left: 2px; /* optical centre of the triangle */
}
.poulton-video__duration {
	color: var(--wp--preset--color--muted);
	font-weight: 500;
}
.poulton-video__duration::before {
	content: "·";
	margin-right: 8px;
}
.poulton-video__poster:hover .poulton-video__play,
.poulton-video__poster:focus-visible .poulton-video__play {
	transform: translateY(-2px);
}
.poulton-video__poster:hover .poulton-video__icon,
.poulton-video__poster:focus-visible .poulton-video__icon {
	background: var(--wp--preset--color--primary-dark);
}
/* On a phone the poster is ~180px tall: a smaller pill keeps the slide readable. */
@media (max-width: 599px) {
	.poulton-video__play {
		gap: 8px;
		padding: 4px 12px 4px 4px;
		font-size: 13px;
	}
	.poulton-video__icon {
		width: 30px;
		height: 30px;
	}
	.poulton-video__icon svg {
		width: 14px;
		height: 14px;
	}
}
@media (prefers-reduced-motion: reduce) {
	.poulton-video,
	.poulton-video__play {
		transition: none;
	}
	.poulton-video__poster:hover .poulton-video__play,
	.poulton-video__poster:focus-visible .poulton-video__play {
		transform: none;
	}
}
