/*
 * Community Works: the hand-written exceptions (principles.md §1).
 *
 * Everything that can be in theme.json is. Each rule here says why it isn't. Values come
 * from theme.json's presets and custom properties (--wp--preset--*, --wp--custom--*),
 * never typed in. Motion follows the design system: 120–200ms, strong ease-out, hover only
 * with a real pointer, and under reduced motion nothing moves (generated.css zeroes the
 * movement tokens) but presses still answer.
 */

/* Why not theme.json: it has no font-smoothing or tap-highlight properties. */
body {
	-webkit-font-smoothing: antialiased;
}

a,
button {
	-webkit-tap-highlight-color: transparent;
}

/* Why not theme.json: it can't style ::selection. */
::selection {
	background: var(--wp--preset--color--sky);
	color: var(--wp--custom--text--strong);
}

/* Why not theme.json: no text-wrap property. Balanced headings, no orphans in prose. */
:where(h1, h2, h3, h4, h5, h6) {
	text-wrap: balance;
}

:where(p, li) {
	text-wrap: pretty;
}

/*
 * Why not theme.json: it has no text-decoration-thickness or -offset. Links look like
 * links at rest, on every device (design-audit.md #17).
 */
a {
	text-decoration-thickness: 2px;
	text-underline-offset: 3px;
	transition: color var(--wp--custom--motion--duration--fast) var(--wp--custom--motion--ease--out);
}

/*
 * Why not theme.json: it can only style :focus on links and buttons, not :focus-visible on
 * every interactive element. 3px solid, 2px offset, never removed.
 */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
	outline: 3px solid var(--wp--custom--focus--ring);
	outline-offset: 2px;
}

/* Why not theme.json: no width property for a block style; a pill is as wide as its label. */
.is-style-pill,
.is-style-pill-ink,
.is-style-pill-strand {
	width: fit-content;
	max-width: 100%;
}

/*
 * Why not theme.json: constrained layouts centre every child with auto margins, which
 * would centre a narrow pill. Line it up with the left edge of the content column instead.
 * A left-justified column (pages, search) already starts at the left edge.
 */
.is-layout-constrained:not(.is-content-justification-left) > :is(.is-style-pill, .is-style-pill-ink, .is-style-pill-strand) {
	margin-left: max(0px, calc((100% - var(--wp--style--global--content-size)) / 2)) !important;
}

/*
 * Why not theme.json: it can't add pseudo-elements. The QuoteBlock's opening mark, in
 * the strand's text colour.
 */
.wp-block-quote::before {
	content: "\201C";
	display: block;
	height: 2rem;
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--hero);
	font-weight: var(--wp--custom--weight--black);
	line-height: 0.6;
	color: var(--wp--custom--strand--ink);
}

.wp-block-quote > p {
	max-width: var(--wp--custom--measure--narrow);
}

/* Buttons: transitions name their properties, never `all`. */
.wp-element-button,
.wp-block-button__link {
	transition:
		background-color var(--wp--custom--motion--duration--fast) var(--wp--custom--motion--ease--out),
		color var(--wp--custom--motion--duration--fast) var(--wp--custom--motion--ease--out),
		border-color var(--wp--custom--motion--duration--fast) var(--wp--custom--motion--ease--out),
		transform var(--wp--custom--motion--duration--press) var(--wp--custom--motion--ease--out);
}

/* Why not theme.json: no :active state. Press feedback: a slight scale, at once. */
.wp-element-button:active,
.wp-block-button__link:active {
	transform: scale(var(--wp--custom--motion--press-scale));
}

/* ------------------------------------------------------------------------ */
/* Patterns                                                                  */
/* ------------------------------------------------------------------------ */

/*
 * Section heading row: links sit on the heading's baseline, not 45px below it
 * (design-audit.md #4). Why not theme.json: flex layouts offer top, centre and bottom only.
 */
.cw-secthead-row {
	align-items: last baseline;
}

.cw-secthead-link {
	font-weight: var(--wp--custom--weight--bold);
}

/*
 * Cards. Why not theme.json: the whole card is the link (the title's link is stretched
 * over it), cards in a row are equal height with their "details" line at the bottom, and
 * the photo is clipped to the corners. None of that is a theme.json property.
 */
.cw-card,
.cw-linkcard,
.cw-person {
	position: relative;
	height: 100%;
	box-sizing: border-box;
	overflow: hidden;
}

.cw-card .wp-block-post-title a::after,
.cw-linkcard :is(.wp-block-heading, .wp-block-post-title) a::after {
	content: "";
	position: absolute;
	inset: 0;
}

.cw-card__body {
	flex: 1;
}

.cw-card__foot,
.cw-linkcard__go {
	margin-top: auto !important;
	padding-top: var(--wp--preset--spacing--1);
}

.cw-card__meta,
.cw-event__date {
	font-variant-numeric: tabular-nums;
}

.cw-card__media img {
	transition: transform var(--wp--custom--motion--duration--slow) var(--wp--custom--motion--ease--out);
}

/* The focus ring goes round the whole card, not just the title text. */
.cw-card :is(.wp-block-post-title, .wp-block-heading) a:focus-visible,
.cw-linkcard :is(.wp-block-heading, .wp-block-post-title) a:focus-visible {
	outline: none;
}

.cw-card:has(a:focus-visible),
.cw-linkcard:has(a:focus-visible) {
	outline: 3px solid var(--wp--custom--focus--ring);
	outline-offset: 2px;
}

.cw-card:has(a),
.cw-linkcard {
	transition:
		border-color var(--wp--custom--motion--duration--base) var(--wp--custom--motion--ease--out),
		transform var(--wp--custom--motion--duration--base) var(--wp--custom--motion--ease--out),
		box-shadow var(--wp--custom--motion--duration--base) var(--wp--custom--motion--ease--out);
}

/* A press lands fast: 100ms, not the hover's 200ms (design-audit.md #7). */
.cw-card:has(a):active,
.cw-linkcard:active {
	transform: scale(var(--wp--custom--motion--press-scale-card));
	transition-duration: var(--wp--custom--motion--duration--press-card);
}

/* EventCard's date badge: a fixed square beside the title. */
.cw-event__date {
	flex: none;
	width: 4rem;
	box-sizing: border-box;
	border-radius: var(--wp--custom--radius--md) !important;
	text-align: center;
}

.cw-event__date .cw-event__day {
	font-weight: var(--wp--custom--weight--black);
	line-height: 1;
}

/* LinkCard, feature size: tall only where there's room (design-audit.md #5). */
@media (min-width: 760px) {
	.cw-linkcard--feature {
		min-height: 13.75rem;
	}
}

/*
 * On a solid feature card the strand's deep colour would sit on its bold colour, so
 * anything that reads it (the "Find out more" line) takes the "on" colour instead. Why not
 * theme.json: the Meta line style is set once, for every card; this swaps the custom
 * property it reads, inside this card only.
 */
.is-style-card-feature-solid {
	--wp--custom--strand--ink: var(--wp--custom--strand--on);
}

/* StatBlock's figure. Why not theme.json: the black weight is for this one use. */
.cw-stat__value {
	font-weight: var(--wp--custom--weight--black);
	line-height: 1;
}

.cw-stat__label {
	font-weight: var(--wp--custom--weight--semibold);
	line-height: 1.3;
}

/*
 * Person cards keep their own height: with photos on some cards and not others, matching
 * the row would leave the cards without one mostly empty. Why not theme.json: it's the
 * grid item's height, which has no block setting.
 */
.cw-person {
	height: auto;
}

/*
 * A person without a photo gets a silhouette in their card's photo space, in their strand's
 * tint. Why not theme.json: it's a drawing, and the card is an HTML file that can't point
 * at a theme image, so CSS draws it (a head and shoulders, as two radial gradients).
 */
.cw-person__silhouette {
	height: auto !important;
	aspect-ratio: 1;
	margin: 0 !important;
	background:
		radial-gradient(circle at 50% 41%, var(--wp--custom--strand--line) 0 17%, transparent 17.5%),
		radial-gradient(ellipse 38% 34% at 50% 100%, var(--wp--custom--strand--line) 0 99%, transparent 100%),
		var(--wp--custom--strand--tint);
}

/* FactsCard rows: the icon sits in a white circle. */
.cw-facts__ic {
	flex: none;
	width: 2.25rem;
	height: 2.25rem;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--custom--surface--card);
	color: var(--wp--custom--strand--ink);
}

.cw-facts__text {
	min-width: 0;
}

/* A long email address breaks rather than pushing the page sideways on a phone. */
.cw-facts__value {
	font-weight: var(--wp--custom--weight--semibold);
	color: var(--wp--custom--text--strong);
	overflow-wrap: anywhere;
}

.cw-facts__actions,
.cw-facts__actions .wp-block-button {
	width: 100%;
}

.cw-facts__actions .wp-block-button__link {
	width: 100%;
	box-sizing: border-box;
}

/* Partner logos: equal-height boxes, logo contained, full colour. */
.cw-partner {
	height: 7rem;
	box-sizing: border-box;
	transition: box-shadow var(--wp--custom--motion--duration--fast) var(--wp--custom--motion--ease--out);
}

.cw-partner__logo,
.cw-partner__logo a {
	display: grid;
	place-items: center;
	width: 100%;
	height: 100%;
}

/* A partner with no logo yet shows its name in the box instead. */
.cw-partner__name {
	margin: 0;
	text-align: center;
	font-weight: var(--wp--custom--weight--semibold);
	color: var(--wp--custom--text--muted);
}

/* The highlights band's cards: equal height, labels above, "details" lined up. */
.cw-highlights {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(min(18.75rem, 100%), 1fr));
	gap: var(--wp--preset--spacing--6);
}

.cw-highlights__item {
	display: grid;
	grid-template-rows: auto 1fr;
	gap: var(--wp--preset--spacing--2);
}

.cw-highlights__label {
	margin: 0;
	color: var(--wp--custom--text--muted);
}

/*
 * Hero mosaic: one large photo and two smaller ones (decisions.md, 16 October). Why not
 * theme.json: a grid where one item spans two rows, rearranged on small screens.
 */
.cw-mosaic {
	display: grid;
	grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
	grid-template-rows: repeat(2, minmax(0, 1fr));
	gap: var(--wp--preset--spacing--4);
	height: 36rem;
}

.cw-mosaic > * {
	margin: 0 !important;
}

.cw-hero__tile {
	min-height: 0 !important;
	border-radius: var(--wp--custom--radius--xl);
	overflow: hidden;
	padding: var(--wp--preset--spacing--4) !important;
	transition: transform var(--wp--custom--motion--duration--press-card) var(--wp--custom--motion--ease--out);
}

.cw-hero__tile:first-child {
	grid-row: span 2;
}

.cw-hero__tile:active {
	transform: scale(var(--wp--custom--motion--press-scale-card));
}

/* Large surfaces never zoom (design-audit.md #19). */
.cw-hero__tile .wp-block-cover__image-background {
	transform: none !important;
}

@media (max-width: 960px) {
	.cw-mosaic {
		height: auto;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		grid-template-rows: auto;
	}

	.cw-hero__tile:first-child {
		grid-row: auto;
		grid-column: span 2;
		aspect-ratio: 4 / 3;
	}

	.cw-hero__tile:not(:first-child) {
		aspect-ratio: 1;
	}
}

/* ------------------------------------------------------------------------ */
/* Header and footer (parts/header.html, parts/footer.html)                  */
/* ------------------------------------------------------------------------ */

/*
 * Why not theme.json: the five-colour strip is a pseudo-element, and the rule under the
 * header is a border, which isn't offered to editors. The strip is 6px, in strand order,
 * never recoloured (design system README § Visual foundations).
 */
.cw-header {
	position: relative;
	padding-top: 6px;
	background: var(--wp--custom--surface--card);
	border-bottom: var(--wp--custom--border-width--regular) solid var(--wp--custom--border--subtle);
}

.cw-header::before {
	content: "";
	position: absolute;
	inset: 0 0 auto;
	height: 6px;
	background: linear-gradient(
		to right,
		var(--wp--custom--strands--children--fill) 0 20%,
		var(--wp--custom--strands--wellbeing--fill) 20% 40%,
		var(--wp--custom--strands--older--fill) 40% 60%,
		var(--wp--custom--strands--skills--fill) 60% 80%,
		var(--wp--custom--strands--nursery--fill) 80%
	);
}

/* The wordmark: the site title, never underlined, never shrinking. */
.cw-header__mark {
	flex: none;
}

.cw-header__name {
	font-weight: var(--wp--custom--weight--bold);
	line-height: 1;
}

.cw-header__name a {
	color: var(--wp--custom--text--strong);
	text-decoration: none;
}

/* Why not theme.json: the label size without the label's capitals and tracking. */
.cw-header__tag {
	font-size: var(--wp--preset--font-size--label);
	line-height: 1;
}

/*
 * Menu links are pills; the current section's takes its strand's tint, or warm paper
 * with no strand. Why not theme.json: Navigation has no style for the current item.
 */
/* Scoped to the bar throughout: core's layout and block rules otherwise win. */
.cw-header__bar .cw-header__nav {
	margin-left: auto;
}

.cw-header__bar .cw-header__nav .wp-block-navigation-item__content {
	padding: var(--wp--preset--spacing--3) var(--wp--preset--spacing--4);
	border-radius: var(--wp--custom--radius--pill);
	color: var(--wp--custom--text--strong);
	font-size: var(--wp--preset--font-size--small);
	font-weight: var(--wp--custom--weight--semibold);
	line-height: 1;
	text-decoration: none;
	white-space: nowrap;
	transition:
		background-color var(--wp--custom--motion--duration--fast) var(--wp--custom--motion--ease--out),
		color var(--wp--custom--motion--duration--fast) var(--wp--custom--motion--ease--out);
}

.cw-header__bar .cw-header__nav .current-menu-item > .wp-block-navigation-item__content {
	background: var(--wp--custom--strand--tint);
	color: var(--wp--custom--strand--ink);
}

/* The Donate inside the menu is for phones only, where the header has no room for it. */
.cw-header__nav .cw-header__menu-donate {
	display: none;
}

/*
 * The Menu and Close buttons, in words: many visitors don't read the hamburger icon
 * (design system SiteHeader). Why not theme.json: Navigation's buttons have no styles.
 */
.cw-header__bar .cw-header__nav :is(.wp-block-navigation__responsive-container-open, .wp-block-navigation__responsive-container-close) {
	position: static;
	align-items: center;
	min-height: var(--wp--custom--hit-min);
	padding: 0 var(--wp--preset--spacing--4);
	border: var(--wp--custom--border-width--regular) solid var(--wp--custom--border--strong);
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--custom--surface--card);
	color: var(--wp--custom--text--strong);
	font-size: var(--wp--preset--font-size--small);
	font-weight: var(--wp--custom--weight--bold);
	transition:
		background-color var(--wp--custom--motion--duration--fast) var(--wp--custom--motion--ease--out),
		transform var(--wp--custom--motion--duration--press) var(--wp--custom--motion--ease--out);
}

.cw-header__nav :is(.wp-block-navigation__responsive-container-open, .wp-block-navigation__responsive-container-close):active {
	transform: scale(var(--wp--custom--motion--press-scale));
}

/* The open menu: the design system's panel rows, 56px tall, in the display face. */
.cw-header__nav .wp-block-navigation__responsive-container.is-menu-open {
	padding: var(--wp--preset--spacing--4) var(--wp--preset--spacing--6) var(--wp--preset--spacing--6);
	background: var(--wp--custom--surface--card);
	color: var(--wp--custom--text--strong);
}

.cw-header__nav .is-menu-open .wp-block-navigation__responsive-close {
	max-width: none;
}

.cw-header__nav .is-menu-open .wp-block-navigation__responsive-container-content {
	padding-top: var(--wp--preset--spacing--16);
}

.cw-header__nav .is-menu-open .wp-block-navigation__container {
	align-items: stretch;
	width: 100%;
	gap: 0;
}

.cw-header__nav .is-menu-open .wp-block-navigation-item {
	width: 100%;
}

.cw-header__bar .cw-header__nav .is-menu-open .wp-block-navigation-item__content {
	display: flex;
	align-items: center;
	box-sizing: border-box;
	width: 100%;
	min-height: 56px;
	padding: 0 var(--wp--preset--spacing--3);
	border-bottom: var(--wp--custom--border-width--hairline) solid var(--wp--custom--border--subtle);
	border-radius: var(--wp--custom--radius--sm);
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--lead);
}

/*
 * Why not theme.json: Navigation collapses at 600px, a breakpoint it fixes. The menu
 * labels wrap below 1024px, so it collapses there instead (design-audit.md § Status).
 */
@media (min-width: 600px) and (max-width: 1023.98px) {
	.cw-header__nav .wp-block-navigation__responsive-container-open:not(.always-shown) {
		display: flex;
	}

	.cw-header__nav .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) {
		display: none;
	}
}

/* Collapsed: wordmark, then Donate and Menu together on the right. */
@media (max-width: 1023.98px) {
	.cw-header__bar.cw-header__bar {
		gap: var(--wp--preset--spacing--3);
	}

	.cw-header__bar .cw-header__donate {
		order: 1;
		margin-left: auto;
	}

	.cw-header__bar .cw-header__nav {
		order: 2;
		margin-left: 0;
	}
}

/* A phone: the strapline goes, and Donate moves into the menu so the wordmark never squeezes. */
@media (max-width: 599.98px) {
	.cw-header__tag {
		display: none;
	}
}

@media (max-width: 479.98px) {
	.cw-header__bar .cw-header__donate {
		display: none;
	}

	.cw-header__bar .cw-header__nav {
		margin-left: auto;
	}

	/* After the links, as in the design system's panel (core gives the link list order 2). */
	.cw-header__nav .is-menu-open .cw-header__menu-donate {
		display: flex;
		order: 3;
		width: 100%;
		padding-top: var(--wp--preset--spacing--5);
	}
}

/*
 * Footer, on charcoal. Why not theme.json: the light greys for secondary text are
 * custom properties, not palette colours, so they can't be picked per block; and the
 * link lists drop their bullets and underlines.
 */
.cw-footer__name {
	color: var(--wp--custom--text--inverse);
	font-weight: var(--wp--custom--weight--bold);
	line-height: 1;
}

.cw-footer__tag {
	color: var(--wp--custom--text--inverse-muted);
}

.cw-footer__donate {
	padding-top: var(--wp--preset--spacing--4);
}

.cw-footer .cw-footer__label {
	color: var(--wp--custom--text--inverse-quiet);
}

.cw-footer__addr {
	color: var(--wp--custom--text--inverse-soft);
}

/* A long email address breaks rather than pushing the page sideways on a phone. */
.cw-footer__email {
	overflow-wrap: anywhere;
}

/* The footer menus: plain links, a line each, with no padding of the menu block's own. */
.cw-footer__links .wp-block-navigation-item__content {
	padding: 0;
}

.cw-footer :is(.cw-footer__links, .cw-footer__cols p) a {
	color: var(--wp--custom--text--inverse);
	text-decoration: none;
}

/* The legal line, under a faint rule (the design system's 18% white on charcoal). */
.cw-footer__legal {
	border-top: var(--wp--custom--border-width--hairline) solid color-mix(in srgb, var(--wp--preset--color--paper) 18%, transparent);
	color: var(--wp--custom--text--inverse-quiet);
}

/* ------------------------------------------------------------------------ */
/* Search (templates/search.html, templates/404.html)                        */
/* ------------------------------------------------------------------------ */

/*
 * The search box: the design system's Input beside a primary Button. Why not theme.json:
 * core Search's input and label have no style slots, only its button.
 */
.cw-search .wp-block-search__label {
	margin-bottom: var(--wp--preset--spacing--2);
	color: var(--wp--custom--text--strong);
	font-weight: var(--wp--custom--weight--semibold);
}

.cw-search .wp-block-search__inside-wrapper {
	gap: var(--wp--preset--spacing--3);
	border: 0;
	padding: 0;
}

.cw-search .wp-block-search__input {
	min-height: var(--wp--custom--hit-min);
	padding: 0 var(--wp--preset--spacing--4);
	border: var(--wp--custom--border-width--regular) solid var(--wp--custom--border--strong);
	border-radius: var(--wp--custom--radius--sm);
	background: var(--wp--custom--surface--card);
	color: var(--wp--custom--text--strong);
	font-size: var(--wp--preset--font-size--body);
}

.cw-search .wp-block-search__button {
	margin-left: 0;
	min-height: var(--wp--custom--hit-min);
	border-radius: var(--wp--custom--radius--pill);
}

/*
 * No count when nothing was found: "Nothing found" says it. Why not theme.json: hiding
 * one block because a sibling is showing needs :has().
 */
.wp-block-query:has(.wp-block-query-no-results) .cw-search__count {
	display: none;
}

/* Results: one per row, under a hairline, the title a plain link as on the board. */
.cw-search__count {
	color: var(--wp--custom--text--strong);
	font-weight: var(--wp--custom--weight--semibold);
}

.cw-results {
	margin-top: var(--wp--preset--spacing--2);
}

.cw-result {
	border-bottom: var(--wp--custom--border-width--hairline) solid var(--wp--custom--border--subtle);
}

.cw-result .wp-block-post-title a {
	color: var(--wp--custom--text--link);
	text-decoration: underline;
	text-decoration-thickness: 1px;
}

.cw-result .wp-block-post-excerpt__excerpt {
	margin: 0;
}

/* ------------------------------------------------------------------------ */
/* Pages and activities (templates/page.html, patterns/activity-*.php)       */
/* ------------------------------------------------------------------------ */

/*
 * A page's body: ordinary blocks start at the wide container's left edge, in line with
 * the title above, while full-width sections still run edge to edge. Why not
 * theme.json: a left-justified layout can't also let children break out to full width.
 */
.cw-page-body > :where(:not(.alignwide):not(.alignfull):not(.alignleft):not(.alignright)),
.cw-page-body > :is(.is-style-pill, .is-style-pill-ink, .is-style-pill-strand) {
	margin-left: max(0px, calc((100% - var(--wp--style--global--wide-size)) / 2)) !important;
}

/*
 * An activity's header takes its strand's tint (Main board). Why not theme.json: the
 * band section styles are one per strand; this one follows the post's own strand.
 */
.cw-band-strand {
	background-color: var(--wp--custom--strand--tint);
}

/* A plain pill is the strand's tint too, so on this band it turns white or it would vanish. */
.cw-band-strand .is-style-pill {
	background: var(--wp--custom--surface--card);
}

/*
 * Strand landing pages (patterns/strand-landing.php). Why not theme.json: the short
 * strand bar is a Spacer with a fill (a Spacer, not an empty Group, which the editor
 * shows as a layout picker), and an eyebrow is a label without a block style of its own.
 */
.cw-strand-bar {
	width: 6rem;
	height: 6px;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--custom--strand--fill);
}

.cw-eyebrow {
	margin: 0;
	color: var(--wp--custom--strand--ink);
}

/* The strand landing page's closing band: the ink band, rounded as on the board. The ink band is also used edge to edge, so the corners can't be part of its style. */
.cw-cta.is-style-band-ink {
	border-radius: var(--wp--custom--radius--xl);
}

/*
 * The section's pages beside a sub-page (the design system's SubNav): a plain list, the
 * current page marked with the strand's edge and tint. Why not theme.json: Page List has
 * no styles for its items or the current page.
 */
.cw-subnav__title a {
	color: var(--wp--custom--text--muted);
	text-decoration: none;
}

.cw-subnav .wp-block-page-list {
	margin: var(--wp--preset--spacing--3) 0 0;
	padding: 0;
	list-style: none;
}

.cw-subnav .wp-block-pages-list__item__link {
	display: block;
	padding: var(--wp--preset--spacing--3) var(--wp--preset--spacing--4);
	border-left: var(--wp--custom--border-width--chunky) solid var(--wp--custom--border--subtle);
	color: var(--wp--custom--text--strong);
	font-weight: var(--wp--custom--weight--semibold);
	text-decoration: none;
	transition: background-color var(--wp--custom--motion--duration--fast) var(--wp--custom--motion--ease--out);
}

.cw-subnav .current-menu-item > .wp-block-pages-list__item__link {
	border-left-color: var(--wp--custom--strand--fill);
	background: var(--wp--custom--strand--tint);
	color: var(--wp--custom--strand--ink);
}

.cw-subnav .wp-block-page-list ul {
	padding-left: var(--wp--preset--spacing--4);
	list-style: none;
}

/* "When it runs" and "Where": one bound paragraph each, its spans set as lines. */
.cw-when,
.cw-where {
	display: grid;
	gap: var(--wp--preset--spacing--3);
}

.cw-when__group,
.cw-where__venue {
	display: grid;
	gap: 2px;
}

.cw-when__group + .cw-when__group {
	padding-top: var(--wp--preset--spacing--3);
	border-top: var(--wp--custom--border-width--hairline) solid var(--wp--custom--border--subtle);
}

.cw-when__label {
	color: var(--wp--custom--strand--ink);
	font-size: var(--wp--preset--font-size--label);
	font-weight: var(--wp--custom--weight--bold);
	letter-spacing: var(--wp--custom--tracking--label);
	text-transform: uppercase;
}

.cw-when__time,
.cw-where__venue strong {
	color: var(--wp--custom--text--strong);
	font-weight: var(--wp--custom--weight--semibold);
	font-variant-numeric: tabular-nums;
}

.cw-when__at,
.cw-where__notes {
	color: var(--wp--custom--text--muted);
	font-size: var(--wp--preset--font-size--small);
}

/* The archive's empty state: a dashed box, as on the board. */
.cw-empty {
	border: var(--wp--custom--border-width--regular) dashed var(--wp--custom--border--subtle);
	border-radius: var(--wp--custom--radius--lg);
}

/*
 * DownloadLink (the job's application pack). Why not theme.json: the links come from a
 * binding as one paragraph of markup, which has no block of its own to style.
 */
.cw-downloads {
	display: grid;
	gap: var(--wp--preset--spacing--2);
}

.cw-download {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--3);
	min-height: 3.5rem;
	padding: var(--wp--preset--spacing--3) var(--wp--preset--spacing--4);
	border: var(--wp--custom--border-width--regular) solid var(--wp--custom--border--subtle);
	border-radius: var(--wp--custom--radius--md);
	background: var(--wp--custom--surface--card);
	color: var(--wp--custom--text--strong);
	text-decoration: none;
	transition: border-color var(--wp--custom--motion--duration--fast) var(--wp--custom--motion--ease--out);
}

.cw-download__ic {
	display: inline-flex;
	flex: none;
	align-items: center;
	justify-content: center;
	width: 2.25rem;
	height: 2.25rem;
	border-radius: var(--wp--custom--radius--sm);
	background: var(--wp--custom--surface--page-alt);
	transition: background-color var(--wp--custom--motion--duration--fast) var(--wp--custom--motion--ease--out);
}

.cw-download__text {
	display: grid;
	gap: 2px;
	min-width: 0;
}

.cw-download__label {
	font-weight: var(--wp--custom--weight--semibold);
	overflow-wrap: anywhere;
}

.cw-download__meta {
	color: var(--wp--custom--text--muted);
	font-size: var(--wp--preset--font-size--small);
}

/* The news list's Newer/Older links, at each end of the row. Why not theme.json: pagination has no gap or alignment for its links. */
.cw-pager {
	padding-top: var(--wp--preset--spacing--8);
	font-weight: var(--wp--custom--weight--semibold);
}

/*
 * The centre map (community-works/map): a box asking to show Google's map, then the map
 * itself in the same space. Why not theme.json: it's a dynamic block's own markup.
 */
/* A figure's own margins go; the space above is the column's gap (blockGap), like any block's. */
.cw-map {
	margin-inline: 0;
	margin-bottom: 0;
}

.cw-map__placeholder,
.cw-map__frame {
	display: block;
	width: 100%;
	aspect-ratio: 4 / 3;
	border: 0;
	border-radius: var(--wp--custom--radius--lg);
	box-sizing: border-box;
}

.cw-map__placeholder {
	display: grid;
	align-content: center;
	justify-items: center;
	gap: var(--wp--preset--spacing--3);
	padding: var(--wp--preset--spacing--6);
	border: var(--wp--custom--border-width--regular) dashed var(--wp--custom--border--subtle);
	background: var(--wp--custom--surface--page-alt);
	text-align: center;
}

.cw-map__placeholder p {
	margin: 0;
}

.cw-map__place {
	color: var(--wp--custom--text--strong);
	font-weight: var(--wp--custom--weight--semibold);
}

.cw-map__note {
	color: var(--wp--custom--text--muted);
	font-size: var(--wp--preset--font-size--small);
}

.cw-map__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: var(--wp--preset--spacing--4);
}

/*
 * Stories: the quote on a story card and page is set like a quotation, and a testimonial's
 * quote reads as the main thing in its box. Why not theme.json: these are paragraphs that
 * only become quotes inside these patterns.
 */
.cw-story__quote,
.cw-testimonial__quote {
	font-style: italic;
}

.cw-testimonial__quote {
	color: var(--wp--custom--strand--ink);
	font-family: var(--wp--preset--font-family--display);
	line-height: 1.35;
}

.cw-testimonial__who {
	margin-top: auto !important;
	color: var(--wp--custom--strand--ink);
	font-weight: var(--wp--custom--weight--semibold);
}

/*
 * "In their words" (patterns/stories-here.php and the strand landing page): a band in the
 * strand's deep colour, with paper text (every strand's ink passes contrast with paper),
 * showing one story at a time. Why not theme.json: the band follows the page's strand
 * (the band section styles are one per strand) and the stories are a scroll-snap row with
 * dots that quotes.js adds.
 */
.cw-quotes {
	background-color: var(--wp--custom--strand--ink);
	color: var(--wp--preset--color--paper);
}

.cw-quotes :is(h2, a) {
	color: inherit;
}

.cw-quotes .wp-block-post-template {
	display: grid;
	grid-auto-columns: 100%;
	grid-auto-flow: column;
	gap: var(--wp--preset--spacing--8);
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scroll-snap-type: x mandatory;
}

.cw-quotes .wp-block-post-template > li {
	margin: 0;
	scroll-snap-align: start;
}

/* With the dots there to move between stories, the row's scrollbar goes. */
.cw-quotes.is-ready .wp-block-post-template {
	scrollbar-width: none;
}

.cw-quotes.is-ready .wp-block-post-template::-webkit-scrollbar {
	display: none;
}

.cw-quote__text {
	margin: 0;
	font-family: var(--wp--preset--font-family--display);
	font-weight: var(--wp--custom--weight--semibold);
	line-height: 1.3;
	text-wrap: pretty;
}

.cw-quote__who {
	margin: 0;
	font-weight: var(--wp--custom--weight--semibold);
}

.cw-quote__more {
	text-decoration: underline;
	text-underline-offset: 0.2em;
}

.cw-quotes__dots {
	display: flex;
	gap: var(--wp--preset--spacing--1);
	margin-left: -0.5rem;
}

/* Each dot's button is 2.75rem square, however small the dot (WCAG 2.5.8). */
.cw-quotes__dot {
	display: grid;
	place-items: center;
	width: 2.75rem;
	height: 2.75rem;
	padding: 0;
	border: 0;
	background: none;
	cursor: pointer;
}

.cw-quotes__dot::before {
	content: "";
	width: 0.75rem;
	height: 0.75rem;
	border: 2px solid currentcolor;
	border-radius: var(--wp--custom--radius--pill);
	color: var(--wp--preset--color--paper);
	transition: width 0.2s ease, background-color 0.2s ease;
}

.cw-quotes__dot[aria-current="true"]::before {
	width: 2rem;
	background: currentcolor;
}

.cw-quotes__dot:focus-visible {
	outline: 2px solid var(--wp--preset--color--paper);
	outline-offset: -4px;
}

@media (prefers-reduced-motion: reduce) {
	.cw-quotes__dot::before {
		transition: none;
	}
}

/*
 * The Photo hero (the plugin's community-works/hero-photos block, the HeroRotator board):
 * the photos share one stage and fade between each other, the panel sits over the
 * bottom-left, and the script's buttons sit underneath. Why not theme.json: it's a dynamic
 * block's own markup, with stacking and fading slides and markup the script adds. Only once
 * the script has started (.is-ready, which the block's editor sets too): without the
 * script, the photos stay one under another.
 */
.cw-rotator.is-ready {
	position: relative;
}

.cw-rotator__panel {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--wp--preset--spacing--4);
}

.cw-rotator__panel > * {
	margin: 0;
}

.cw-rotator.is-ready .cw-rotator__stage {
	position: relative;
	height: 38.75rem;
	overflow: hidden;
	border-radius: var(--wp--custom--radius--xl);
	background: var(--wp--custom--surface--page-alt);
}

.cw-rotator.is-ready .cw-rotator__slide {
	position: absolute;
	inset: 0;
	margin: 0;
	opacity: 0;
	transition: opacity var(--wp--custom--motion--duration--slow) var(--wp--custom--motion--ease--out);
}

.cw-rotator.is-ready .cw-rotator__slide.is-on {
	opacity: 1;
}

.cw-rotator.is-ready .cw-rotator__slide figure,
.cw-rotator.is-ready .cw-rotator__slide img {
	display: block;
	width: 100%;
	height: 100%;
	margin: 0;
	object-fit: cover;
}

/* The label and caption are read into the buttons and the caption line. */
.cw-rotator.is-ready .cw-rotator__label,
.cw-rotator.is-ready .cw-rotator__caption {
	display: none;
}

.cw-rotator.is-ready .cw-rotator__panel {
	position: absolute;
	/* Over the photo's bottom-left corner, above the buttons under the photo. */
	top: calc(38.75rem - var(--wp--preset--spacing--8));
	left: var(--wp--preset--spacing--8);
	width: min(35rem, calc(100% - 4rem));
	transform: translateY(-100%);
	margin: 0;
	padding: var(--wp--preset--spacing--8);
	box-sizing: border-box;
	border-radius: var(--wp--custom--radius--lg);
	background: var(--wp--custom--surface--card);
	box-shadow: var(--wp--preset--shadow--soft);
}

.cw-rotator__bar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--3);
	padding-top: var(--wp--preset--spacing--4);
}

.cw-rotator__tabs,
.cw-rotator__side {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--wp--preset--spacing--2) var(--wp--preset--spacing--4);
}

.cw-rotator__tab {
	display: inline-flex;
	align-items: center;
	gap: var(--wp--preset--spacing--2);
	min-height: 44px;
	padding: 0 var(--wp--preset--spacing--4);
	border: var(--wp--custom--border-width--regular) solid var(--wp--custom--border--subtle);
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--custom--surface--card);
	color: var(--wp--custom--text--strong);
	font: inherit;
	font-weight: var(--wp--custom--weight--semibold);
	cursor: pointer;
}

.cw-rotator__tab[aria-pressed="true"] {
	border-color: var(--wp--preset--color--ink);
	background: var(--wp--preset--color--ink);
	color: var(--wp--custom--text--inverse);
}

.cw-rotator__dot {
	width: 10px;
	height: 10px;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--custom--strand--fill);
}

.cw-rotator__cap {
	color: var(--wp--custom--text--muted);
	font-size: var(--wp--preset--font-size--small);
}

.cw-rotator__pause {
	min-height: 44px;
	padding: 0 var(--wp--preset--spacing--4);
	border: 0;
	background: none;
	color: var(--wp--custom--text--link);
	font: inherit;
	font-weight: var(--wp--custom--weight--semibold);
	text-decoration: underline;
	cursor: pointer;
}

/* On a phone the panel goes under the photo, and the photo keeps a 4:3 shape. */
@media (max-width: 760px) {
	.cw-rotator.is-ready .cw-rotator__stage {
		height: auto;
		aspect-ratio: 4 / 3;
	}

	.cw-rotator.is-ready .cw-rotator__panel {
		position: static;
		width: auto;
		transform: none;
		padding: var(--wp--preset--spacing--6) 0 0;
		background: none;
		box-shadow: none;
	}
}

@media (prefers-reduced-motion: reduce) {
	.cw-rotator.is-ready .cw-rotator__slide {
		transition: none;
	}
}

/* What's on: the event cards go without photos, so the timetable stays near the top on a phone (decisions.md, 22 October 2026). */
.cw-whatson-events .cw-card__media {
	display: none;
}

/*
 * The weekly timetable (community-works/timetable): the design system's Timetable, one
 * column per day. Why not theme.json: it's a dynamic block's own markup, with no
 * block supports for a grid of lists.
 */
.cw-tt {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(16.25rem, 100%), 1fr));
	gap: var(--wp--preset--spacing--8) var(--wp--preset--spacing--6);
	align-items: start;
}

/* Each day is a card (decisions.md, 30 October 2026: the timetable has one look, on What's on). */
.cw-tt__day {
	padding: var(--wp--preset--spacing--5) var(--wp--preset--spacing--6);
	border: var(--wp--custom--border-width--regular) solid var(--wp--custom--border--subtle);
	border-radius: var(--wp--custom--radius--lg);
	background: var(--wp--custom--surface--card);
}

.cw-tt__dayname {
	margin: 0;
	padding-bottom: var(--wp--preset--spacing--2);
	border-bottom: var(--wp--custom--border-width--regular) solid var(--wp--custom--border--subtle);
	color: var(--wp--custom--text--muted);
	font-family: var(--wp--preset--font-family--body);
}

.cw-tt__rows {
	margin: 0;
	padding: 0;
	list-style: none;
}

.cw-tt__row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--4);
	padding: var(--wp--preset--spacing--3) 0;
	border-bottom: var(--wp--custom--border-width--hairline) solid var(--wp--custom--border--subtle);
}

.cw-tt__name {
	display: flex;
	align-items: baseline;
	gap: var(--wp--preset--spacing--3);
	color: var(--wp--custom--text--strong);
	font-weight: var(--wp--custom--weight--semibold);
	line-height: 1.3;
	text-decoration: none;
}

/* The dot is the strand's fill; with no strand, neutral like everything else. */
.cw-tt__dot {
	flex: none;
	width: 10px;
	height: 10px;
	border-radius: var(--wp--custom--radius--circle);
	background: var(--wp--custom--strand--fill);
}

/* A session's label (Entry level 1b) goes under the activity's name, not after it. */
.cw-tt__label {
	display: block;
	color: var(--wp--custom--text--muted);
	font-weight: var(--wp--custom--weight--regular);
}

.cw-tt__time {
	flex: none;
	color: var(--wp--custom--text--body);
	font-size: var(--wp--preset--font-size--small);
	font-weight: var(--wp--custom--weight--semibold);
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}

/*
 * Filter chips (community-works/filter-chips): the design system's FilterChip, as links.
 * The chip in force has aria-current; Area chips fill with their strand, Day chips with
 * ink. Why not theme.json: a dynamic block's markup, and states on an attribute.
 */
.cw-filters {
	display: grid;
	gap: var(--wp--preset--spacing--4);
}

.cw-chips {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--wp--preset--spacing--2);
}

.cw-filters__label {
	width: 4.5rem;
	color: var(--wp--custom--text--muted);
}

.cw-chip {
	display: inline-flex;
	align-items: center;
	min-height: var(--wp--custom--hit-min);
	box-sizing: border-box;
	padding: 0 var(--wp--preset--spacing--4);
	border: var(--wp--custom--border-width--regular) solid var(--wp--custom--border--subtle);
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--custom--surface--card);
	color: var(--wp--custom--text--strong);
	font-size: var(--wp--preset--font-size--small);
	font-weight: var(--wp--custom--weight--semibold);
	line-height: 1;
	text-decoration: none;
	transition:
		background-color var(--wp--custom--motion--duration--fast) var(--wp--custom--motion--ease--out),
		border-color var(--wp--custom--motion--duration--fast) var(--wp--custom--motion--ease--out),
		color var(--wp--custom--motion--duration--fast) var(--wp--custom--motion--ease--out),
		transform var(--wp--custom--motion--duration--press) var(--wp--custom--motion--ease--out);
}

.cw-chip:active {
	transform: scale(var(--wp--custom--motion--press-scale));
}

.cw-chip[aria-current] {
	border-color: var(--wp--preset--color--ink);
	background: var(--wp--preset--color--ink);
	color: var(--wp--custom--text--inverse);
}

.cw-chip--strand[aria-current] {
	border-color: var(--wp--custom--strand--fill);
	background: var(--wp--custom--strand--fill);
	color: var(--wp--custom--strand--on);
}

.cw-filters__status {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--wp--preset--spacing--3);
	margin: 0;
	padding-top: var(--wp--preset--spacing--3);
	border-top: var(--wp--custom--border-width--hairline) solid var(--wp--custom--border--subtle);
	color: var(--wp--custom--text--strong);
	font-weight: var(--wp--custom--weight--semibold);
}

/*
 * Why not theme.json: its :hover styles can't be limited to devices with a real pointer,
 * and a tap on a phone would leave them stuck on. Every hover effect lives here.
 */
@media (hover: hover) and (pointer: fine) {
	a:where(:not(.wp-element-button)):hover {
		color: var(--wp--custom--text--link-hover);
	}

	/* Buttons don't move on hover: the fill changes, that's all (decisions.md, 27 October 2026, night). */
	.wp-element-button:hover,
	.wp-block-button__link:hover {
		background-color: var(--wp--custom--action--primary-hover);
		color: var(--wp--custom--action--primary-on);
	}

	.wp-block-button.is-style-button-secondary .wp-block-button__link:hover,
	.is-style-band-action .wp-element-button:hover {
		background-color: var(--wp--preset--color--ink);
		color: var(--wp--custom--text--inverse);
	}

	/* On the ink band the ink hover would vanish into the band, so it turns to a white outline instead. */
	.is-style-band-ink .wp-block-button.is-style-button-secondary .wp-block-button__link:hover {
		background-color: transparent;
		border-color: var(--wp--custom--text--inverse);
		color: var(--wp--custom--text--inverse);
	}

	.wp-block-button.is-style-button-strand .wp-block-button__link:hover {
		background-color: var(--wp--custom--strand--ink);
		color: var(--wp--preset--color--paper);
	}

	.wp-block-button.is-style-button-ghost .wp-block-button__link:hover {
		background-color: var(--wp--custom--strand--tint);
		color: var(--wp--custom--strand--ink);
	}

	.cw-card:has(a):hover,
	.cw-linkcard:hover {
		border-color: var(--wp--custom--strand--fill);
		transform: var(--wp--custom--motion--lift-hover);
		box-shadow: var(--wp--preset--shadow--soft);
	}

	.cw-card:hover .cw-card__media img {
		transform: scale(var(--wp--custom--motion--media-zoom));
	}

	.cw-card:hover .cw-card__foot .cw-icon,
	.cw-linkcard:hover .cw-icon {
		transform: translateX(var(--wp--custom--motion--nudge));
	}

	.cw-rotator__tab:not([aria-pressed="true"]):hover {
		border-color: var(--wp--preset--color--ink);
	}

	.cw-download:hover {
		border-color: var(--wp--preset--color--ink);
		color: var(--wp--custom--text--strong);
	}

	.cw-download:hover .cw-download__ic {
		background-color: var(--wp--preset--color--ink);
	}

	/* The icon is an image (a bound paragraph can't hold SVG), so it turns white by inverting. */
	.cw-download:hover .cw-download__ic img {
		filter: invert(1);
	}

	.cw-partner:hover {
		box-shadow: var(--wp--preset--shadow--soft);
	}

	.cw-header__nav .wp-block-navigation-item__content:hover,
	.cw-header__nav :is(.wp-block-navigation__responsive-container-open, .wp-block-navigation__responsive-container-close):hover {
		background-color: var(--wp--preset--color--paper-warm);
		color: var(--wp--custom--text--strong);
	}

	.cw-header__nav .current-menu-item > .wp-block-navigation-item__content:hover {
		background-color: var(--wp--custom--strand--tint);
		color: var(--wp--custom--strand--ink);
	}

	.cw-chip:hover {
		border-color: var(--wp--custom--text--strong);
		color: var(--wp--custom--text--strong);
	}

	.cw-chip[aria-current]:hover {
		color: var(--wp--custom--text--inverse);
	}

	.cw-chip--strand[aria-current]:hover {
		border-color: var(--wp--custom--strand--ink);
		color: var(--wp--custom--strand--on);
	}

	.cw-subnav .wp-block-pages-list__item__link:hover {
		background: var(--wp--preset--color--paper-warm);
	}

	.cw-subnav .current-menu-item > .wp-block-pages-list__item__link:hover {
		background: var(--wp--custom--strand--tint);
	}

	.cw-tt__name:hover {
		color: var(--wp--custom--text--strong);
		text-decoration: underline;
	}

	/* Lime on charcoal, underlined: the link colour's orange would fail contrast here. */
	.cw-footer :is(.cw-footer__links, .cw-footer__cols p) a:hover {
		color: var(--wp--preset--color--lime);
		text-decoration: underline;
	}

	/* Press wins over hover while the pointer is down. */
	.wp-element-button:active,
	.wp-block-button__link:active {
		transform: scale(var(--wp--custom--motion--press-scale));
	}

	.cw-card:has(a):active,
	.cw-linkcard:active {
		transform: scale(var(--wp--custom--motion--press-scale-card));
	}
}

.cw-icon {
	display: inline-flex;
	transition: transform var(--wp--custom--motion--duration--base) var(--wp--custom--motion--ease--out);
}

/* Under reduced motion a press still answers, with colour instead of movement (design-audit.md #9). */
@media (prefers-reduced-motion: reduce) {
	.wp-element-button:active,
	.wp-block-button__link:active,
	.cw-chip:active,
	.cw-header__nav :is(.wp-block-navigation__responsive-container-open, .wp-block-navigation__responsive-container-close):active {
		filter: brightness(0.92);
	}

	.cw-card:has(a):active,
	.cw-linkcard:active {
		background-color: var(--wp--custom--surface--page-alt);
	}
}

/* ------------------------------------------------------------------------ */
/* The homepage: depth and a little motion (decisions.md,                   */
/* 25 October 2026, later)                                                   */
/* ------------------------------------------------------------------------ */

/*
 * A sheet: a full-width band drawn as a rounded sheet inset from the screen's edges, so
 * the page reads as paper laid on paper rather than stripes of colour. Why not theme.json:
 * a full-width group's side margins and corners aren't block settings, and the band
 * section styles are also used edge to edge, so the shape can't be part of their style.
 */
.cw-sheet.alignfull {
	margin-left: var(--wp--preset--spacing--4) !important;
	margin-right: var(--wp--preset--spacing--4) !important;
	border-radius: var(--wp--custom--radius--xl);
}

@media (min-width: 760px) {
	.cw-sheet.alignfull {
		margin-left: var(--wp--preset--spacing--6) !important;
		margin-right: var(--wp--preset--spacing--6) !important;
	}
}

/* On a phone the sheet's own edge is the margin, so its inside padding is a step smaller. Why not theme.json: padding per screen size. */
@media (max-width: 599.98px) {
	.cw-sheet.alignfull {
		padding-left: var(--wp--preset--spacing--5) !important;
		padding-right: var(--wp--preset--spacing--5) !important;
	}
}

/*
 * A list page's header (the activities, events, jobs and news lists, the timetable) is a
 * sand band like every page header, and what follows it starts a step below. Why not
 * theme.json: the gap belongs to whatever block comes next, which varies by template.
 */
.cw-page-head + * {
	margin-top: var(--wp--preset--spacing--8) !important;
}

/*
 * A single page's opening photo is a feature (decisions.md, 27 October 2026, later): the
 * photo runs the width of the page, rounded, and the title panel is laid over its foot, as
 * on the homepage hero. The title stays first in the markup, so it's still what a screen
 * reader meets first; the grid draws the photo above it. Without a photo the header is as
 * it was. Why not theme.json: a two-row grid with an overlap, depending on whether the
 * featured image rendered.
 */
.cw-feature-head:has(> .cw-feature-head__photo) {
	display: grid;
	grid-template-columns: minmax(0, 1fr) min(var(--wp--style--global--wide-size), 100%) minmax(0, 1fr);
}

.cw-feature-head:has(> .cw-feature-head__photo) > * {
	grid-column: 2;
	margin-left: 0 !important;
	margin-right: 0 !important;
}

.cw-feature-head > .cw-feature-head__photo {
	grid-row: 1;
	margin: 0 !important;
	overflow: hidden;
	border-radius: var(--wp--custom--radius--xl);
	box-shadow: var(--wp--preset--shadow--photo);
}

.cw-feature-head > .cw-feature-head__photo img {
	border-radius: 0 !important;
}

.cw-feature-head:has(> .cw-feature-head__photo) > :not(.cw-feature-head__photo) {
	grid-row: 2;
	position: relative;
	/* Over the photo, which comes after it in the markup. */
	z-index: 1;
	justify-self: start;
	box-sizing: border-box;
	width: min(40rem, calc(100% - var(--wp--preset--spacing--8)));
	margin: calc(-1 * var(--wp--preset--spacing--16)) 0 0 var(--wp--preset--spacing--8) !important;
	padding: var(--wp--preset--spacing--8);
	border-radius: var(--wp--custom--radius--lg);
	background: var(--wp--custom--surface--card);
	box-shadow: var(--wp--preset--shadow--soft);
}

/* On the white panel a plain pill takes the strand's tint again (on the band it is white). */
.cw-feature-head:has(> .cw-feature-head__photo) .is-style-pill {
	background: var(--wp--custom--strand--tint);
}

@media (max-width: 599.98px) {
	/* A phone is narrow, so the wide photo would be a strip: it takes a 3:2 shape instead. */
	.cw-feature-head > .cw-feature-head__photo img {
		aspect-ratio: 3 / 2 !important;
	}

	.cw-feature-head:has(> .cw-feature-head__photo) > :not(.cw-feature-head__photo) {
		width: auto;
		margin: calc(-1 * var(--wp--preset--spacing--10)) var(--wp--preset--spacing--2) 0 !important;
		padding: var(--wp--preset--spacing--5);
	}
}

/*
 * An eyebrow on the ink band: the neutral strand's text colour is ink, which would vanish.
 * Why not theme.json: the eyebrow is a class on a paragraph, not a block style.
 */
.is-style-band-ink .cw-eyebrow {
	color: var(--wp--custom--text--inverse-soft);
}

/*
 * A sheet keeps a gap above and below it, so it never touches a header or another sheet, as
 * two pieces of paper wouldn't. Why not theme.json: block spacing between full-width
 * sections is zero on purpose; only sheets need the gap.
 */
.cw-sheet.alignfull {
	margin-top: var(--wp--preset--spacing--6) !important;
	margin-bottom: var(--wp--preset--spacing--6) !important;
}

/*
 * The five-colour strip, short, as a section's opening mark: all five strands together
 * mean the whole centre, never one strand. Why not theme.json: a Spacer has no gradient
 * fill (and the design system keeps gradients out of the palette); this is the header's
 * strip, drawn the same way.
 */
.cw-strip {
	width: 7.5rem !important;
	height: 6px !important;
	border-radius: var(--wp--custom--radius--pill);
	background: linear-gradient(
		to right,
		var(--wp--custom--strands--children--fill) 0 20%,
		var(--wp--custom--strands--wellbeing--fill) 20% 40%,
		var(--wp--custom--strands--older--fill) 40% 60%,
		var(--wp--custom--strands--skills--fill) 60% 80%,
		var(--wp--custom--strands--nursery--fill) 80%
	);
}

/*
 * In line with the wide column's left edge, as a pill is: constrained layouts centre it, and
 * the editor's layout rule is more specific than a single class.
 */
.is-layout-constrained > .cw-strip.cw-strip {
	margin-left: max(0px, calc((100% - var(--wp--style--global--wide-size)) / 2)) !important;
}

/* A large figure on the ink band: the stat without its tinted box. Why not theme.json: the inverse greys are custom properties, not palette colours. */
.cw-figure .cw-stat__value {
	margin: 0;
	color: var(--wp--custom--text--inverse);
}

.cw-figure .cw-stat__label {
	max-width: 18rem;
	margin: 0;
	color: var(--wp--custom--text--inverse-soft);
}

/*
 * A strand tile's photo, flush with the tile's top edge, as every card's photo is (cards:
 * photo flush, words below; decisions.md, 27 October 2026, later). Why not theme.json: the
 * photo reaches past the tile's padding with negative margins. It stays still on hover
 * (decisions.md, 27 October 2026, night).
 */
/*
 * A card's colour stops inside its (transparent) border, so a flush photo meets the page,
 * not a hairline of the card's colour. Why not theme.json: no background-clip property.
 */
.cw-card,
.cw-linkcard {
	background-clip: padding-box;
}

/* Its width is set, not stretched, or a small photo sizes the tile by its own width first. */
.cw-tile__photo {
	flex-shrink: 0;
	width: calc(100% + 2 * var(--wp--preset--spacing--6));
	max-width: none;
	margin: calc(-1 * var(--wp--preset--spacing--6)) calc(-1 * var(--wp--preset--spacing--6)) var(--wp--preset--spacing--2) !important;
	overflow: hidden;
}

.cw-tile__photo img {
	display: block;
	width: 100%;
	border-radius: 0 !important;
}

/*
 * On a phone the tiles are rows, so the photo fills the tile's left edge, top to bottom,
 * and the five fit in about a screen.
 */
@media (max-width: 599.98px) {
	.cw-linkcard--feature:has(.cw-tile__photo) {
		display: grid !important;
		grid-template-columns: 6.5rem minmax(0, 1fr);
		column-gap: var(--wp--preset--spacing--5);
		align-content: start;
		padding-left: 0 !important;
	}

	.cw-linkcard--feature:has(.cw-tile__photo) > * {
		grid-column: 2;
		margin: 0 !important;
	}

	.cw-linkcard--feature .cw-tile__photo {
		grid-column: 1;
		grid-row: 1 / span 3;
		align-self: stretch;
		width: auto;
		margin: calc(-1 * var(--wp--preset--spacing--6)) 0 !important;
	}

	.cw-linkcard--feature .cw-tile__photo img {
		height: 100%;
		aspect-ratio: auto !important;
		object-fit: cover;
	}
}

/*
 * A photo set on the page with depth, and the nursery band's quote laid over its corner as
 * a white card. Why not theme.json: the overlap is a negative margin, and the quote's card
 * look applies only here, not to every quote.
 */
.cw-photo img,
.cw-photo-quote .wp-block-image img {
	width: 100%;
	box-shadow: var(--wp--preset--shadow--photo);
}

.cw-photo-quote .wp-block-image {
	margin: 0;
}

.cw-photo-quote .wp-block-quote {
	position: relative;
	max-width: 26rem;
	margin: calc(-1 * var(--wp--preset--spacing--16)) 0 0 var(--wp--preset--spacing--6) !important;
	padding: var(--wp--preset--spacing--6) !important;
	border-radius: var(--wp--custom--radius--lg);
	background: var(--wp--custom--surface--card);
	box-shadow: var(--wp--preset--shadow--soft);
	font-size: var(--wp--preset--font-size--heading-4);
}

.cw-photo-quote .wp-block-quote::before {
	height: 1.5rem;
}

@media (max-width: 599.98px) {
	.cw-photo-quote .wp-block-quote {
		margin: calc(-1 * var(--wp--preset--spacing--10)) var(--wp--preset--spacing--3) 0 !important;
	}
}

/* The hero's stage sits on the sand with depth. Why not theme.json: the stage is the Photo hero block's own markup. */
.cw-rotator.is-ready .cw-rotator__stage {
	box-shadow: var(--wp--preset--shadow--photo);
}

/*
 * The chosen photo's button fills with a thin line while its photo is showing, so it's clear
 * the photos turn and when the next will come. The line is the clock: view.js moves on when
 * it finishes, so pausing it (hover, focus, Pause, a hidden tab) pauses the turn. Why not
 * theme.json: a pseudo-element, keyframes and states set by the script.
 */
.cw-rotator__tab {
	position: relative;
	overflow: hidden;
}

.cw-rotator__tab::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 3px;
	background: var(--wp--custom--text--inverse);
	transform: scaleX(0);
	transform-origin: left;
}

@keyframes cw-turn {
	to {
		transform: scaleX(1);
	}
}

.cw-rotator.is-turning .cw-rotator__tab[aria-pressed="true"]::after {
	animation: cw-turn var(--wp--custom--motion--duration--photo-turn) linear forwards;
}

.cw-rotator.is-turning.is-holding .cw-rotator__tab[aria-pressed="true"]::after {
	animation-play-state: paused;
}

/*
 * On a phone the panel is a card that overlaps the photo's foot, rather than plain text
 * under it: the same depth as the desktop panel. Why not theme.json: the Photo hero's own
 * markup, and a negative margin.
 */
@media (max-width: 760px) {
	.cw-rotator.is-ready .cw-rotator__panel {
		position: relative;
		top: auto;
		left: auto;
		width: auto;
		transform: none;
		margin: calc(-1 * var(--wp--preset--spacing--10)) var(--wp--preset--spacing--3) 0;
		padding: var(--wp--preset--spacing--6);
		border-radius: var(--wp--custom--radius--lg);
		background: var(--wp--custom--surface--card);
		box-shadow: var(--wp--preset--shadow--soft);
	}
}

/* On a small phone the panel takes the photo's full width, so the title keeps to three lines. Why not theme.json: as above. */
@media (max-width: 599.98px) {
	.cw-rotator.is-ready .cw-rotator__panel {
		margin-left: 0;
		margin-right: 0;
		padding: var(--wp--preset--spacing--5);
	}
}

/*
 * The hero's controls on a phone: the photos don't turn by themselves there (view.js), so
 * there's no Pause, and the caption goes with it. The photo buttons become ink dots, the
 * one showing stretched, like the "In their words" dots; each is still a 44px button named
 * by its label (the label is kept for screen readers). Why not theme.json: the buttons are
 * markup the script adds.
 */
@media (max-width: 760px) {
	.cw-rotator__side {
		display: none;
	}

	.cw-rotator__bar {
		justify-content: center;
		padding-top: var(--wp--preset--spacing--3);
	}

	.cw-rotator__tabs {
		gap: 0;
	}

	.cw-rotator__tab,
	.cw-rotator__tab[aria-pressed="true"] {
		justify-content: center;
		width: var(--wp--custom--hit-min);
		min-height: var(--wp--custom--hit-min);
		padding: 0;
		border: 0;
		background: none;
	}

	.cw-rotator__tab .cw-rotator__dot {
		width: 10px;
		height: 10px;
		box-shadow: inset 0 0 0 2px var(--wp--custom--text--strong);
		background: transparent;
		transition: width var(--wp--custom--motion--duration--base) var(--wp--custom--motion--ease--out);
	}

	.cw-rotator__tab[aria-pressed="true"] .cw-rotator__dot {
		width: 1.75rem;
		box-shadow: none;
		background: var(--wp--custom--text--strong);
	}

	.cw-rotator__tablabel {
		position: absolute;
		width: 1px;
		height: 1px;
		overflow: hidden;
		clip-path: inset(50%);
		white-space: nowrap;
	}
}

/*
 * What's happening and the news on a phone: a row to swipe, the next card peeking in, rather
 * than three tall cards one under another. Why not theme.json: it's the highlights block's
 * own grid, and a Post Template's grid has no "row on small screens" setting.
 */
@media (max-width: 599.98px) {
	.cw-highlights,
	.cw-swipe.wp-block-post-template {
		display: grid;
		grid-auto-flow: column;
		grid-auto-columns: 84%;
		grid-template-columns: none !important;
		gap: var(--wp--preset--spacing--4);
		margin-left: calc(-1 * var(--wp--style--root--padding-left)) !important;
		margin-right: calc(-1 * var(--wp--style--root--padding-right)) !important;
		padding: var(--wp--preset--spacing--1) var(--wp--style--root--padding-right) var(--wp--preset--spacing--6) var(--wp--style--root--padding-left);
		overflow-x: auto;
		overscroll-behavior-x: contain;
		scroll-snap-type: x mandatory;
		scroll-padding-inline: var(--wp--style--root--padding-left);
	}

	.cw-highlights__item,
	.cw-swipe.wp-block-post-template > li {
		scroll-snap-align: start;
	}
}

/*
 * Sections marked cw-reveal ease up into place the first time they come on screen (reveal.js
 * sets the classes, so without the script, or with reduced motion, nothing is ever hidden).
 * Once only, never tied to the scroll position, and cards in a row follow each other by
 * 70ms. reveal.js takes the class off again once an item has arrived, so its slow
 * transition never stands in for a card's own quick hover. Why not theme.json: states set
 * by a script.
 */
.cw-reveal-item {
	transition:
		opacity var(--wp--custom--motion--duration--reveal) var(--wp--custom--motion--ease--out),
		transform var(--wp--custom--motion--duration--reveal) var(--wp--custom--motion--ease--out);
	transition-delay: calc(var(--cw-i, 0) * var(--wp--custom--motion--stagger));
}

.cw-reveal-item.is-pending {
	opacity: 0;
	transform: translateY(var(--wp--custom--motion--reveal-y));
}

@media print {
	.cw-reveal-item.is-pending {
		opacity: 1;
		transform: none;
	}
}

@media (hover: hover) and (pointer: fine) {
	/*
	 * On a bold tile the title keeps its "on" colour: the link hover colour (deep orange)
	 * would sit on the strand's fill, which fails contrast on orange.
	 */
	.is-style-card-feature-solid a:hover {
		color: var(--wp--custom--strand--on);
	}

	/* A bold tile lifts with its own colour's shadow, not the grey one. */
	.cw-linkcard.is-style-card-feature-solid:hover {
		box-shadow: var(--wp--custom--shadow--strand-hover);
	}
}

/* ------------------------------------------------------------------------ */
/* Fluent Forms (decisions.md, 27 October 2026, night)                       */
/* ------------------------------------------------------------------------ */

/*
 * Every Fluent Forms form, drawn as the design system's form controls (Input, Select,
 * Checkbox, ErrorSummary, SuccessPanel). functions.php makes every form "Inherit theme
 * style" and leaves out Fluent Forms' own skin, so nothing here competes with it, and no
 * one styles a form in its sidebar. Why not theme.json: it has no styles for form fields,
 * and this is another plugin's markup. Fluent Forms' layout sheet reads a few variables of
 * its own (the required mark, error borders); they're set to ours.
 */
.fluentform {
	--fluentform-primary: var(--wp--custom--focus--ring);
	--fluentform-secondary: var(--wp--custom--text--body);
	--fluentform-danger: var(--wp--custom--state--danger);
	--fluentform-border-color: var(--wp--custom--color--grey);
	--fluentform-border-radius: var(--wp--custom--radius--md);
	max-width: var(--wp--style--global--content-size);
	font-family: var(--wp--preset--font-family--body);
	color: var(--wp--custom--text--body);
}

.fluentform .ff-el-group {
	margin-bottom: var(--wp--preset--spacing--6);
}

.fluentform .ff-el-input--label {
	margin-bottom: var(--wp--preset--spacing--2);
}

.fluentform .ff-el-input--label label {
	font-size: var(--wp--preset--font-size--small);
	font-weight: var(--wp--custom--weight--semibold);
	line-height: 1.3;
	color: var(--wp--custom--text--strong);
}

/* The required mark is deep orange, as on the boards (Field's required mark). */
.fluentform .ff-el-input--label.ff-el-is-required.asterisk-right label::after,
.fluentform .ff-el-input--label.ff-el-is-required.asterisk-left label::before {
	color: var(--wp--preset--color--orange-deep);
}

/*
 * Text boxes, the message box and the dropdown. The edge is mid grey, not the design
 * system's hairline grey: a field's edge needs 3:1 against the page (WCAG 2.2, 1.4.11),
 * and #8a8b8f on white is 3.5:1.
 */
.fluentform .ff-el-form-control {
	box-sizing: border-box;
	width: 100%;
	min-height: var(--wp--custom--hit-min);
	padding: var(--wp--preset--spacing--2) var(--wp--preset--spacing--4);
	font-family: inherit;
	font-size: var(--wp--preset--font-size--body);
	line-height: var(--wp--custom--leading--normal);
	color: var(--wp--custom--text--strong);
	background-color: var(--wp--custom--surface--card);
	border: var(--wp--custom--border-width--regular) solid var(--wp--custom--color--grey);
	border-radius: var(--wp--custom--radius--md);
	box-shadow: none;
	transition:
		border-color var(--wp--custom--motion--duration--fast) var(--wp--custom--motion--ease--out),
		box-shadow var(--wp--custom--motion--duration--fast) var(--wp--custom--motion--ease--out);
}

.fluentform textarea.ff-el-form-control {
	min-height: 7.5rem;
	padding-top: var(--wp--preset--spacing--3);
	padding-bottom: var(--wp--preset--spacing--3);
	line-height: var(--wp--custom--leading--body);
	resize: vertical;
}

/* The dropdown's own arrow, drawn in ink, so it looks the same in every browser. */
.fluentform select.ff-el-form-control {
	appearance: none;
	padding-right: var(--wp--preset--spacing--10);
	background-image:
		linear-gradient(45deg, transparent 50%, var(--wp--custom--text--strong) 50%),
		linear-gradient(135deg, var(--wp--custom--text--strong) 50%, transparent 50%);
	background-position: calc(100% - 20px) 50%, calc(100% - 14px) 50%;
	background-size: 6px 6px, 6px 6px;
	background-repeat: no-repeat;
	cursor: pointer;
}

.fluentform .ff-el-form-control::placeholder {
	color: var(--wp--custom--text--muted);
	opacity: 1;
}

/* On hover the edge darkens to ink (not on a field with a problem, which stays red), on
 * devices with a real pointer, as every hover here. */
@media (hover: hover) and (pointer: fine) {
	.fluentform .ff-el-group:not(.ff-el-is-error) .ff-el-form-control:hover:not(:focus) {
		border-color: var(--wp--custom--border--strong);
	}
}

/* Focus: the blue ring, on the field's edge rather than outside it, as on Input. */
.fluentform .ff-el-form-control:focus {
	border-color: var(--wp--custom--focus--ring);
	box-shadow: var(--wp--custom--shadow--focus);
	outline: none;
}

/* Tick boxes and radio buttons: 24px, ink edged, filled with blue when chosen (Checkbox). */
.fluentform .ff-el-form-check {
	margin: 0;
}

.fluentform .ff-el-form-check-label {
	display: flex;
	gap: var(--wp--preset--spacing--3);
	align-items: flex-start;
	min-height: var(--wp--custom--hit-min);
	padding: var(--wp--preset--spacing--2) 0;
	font-size: var(--wp--preset--font-size--body);
	line-height: var(--wp--custom--leading--normal);
	color: var(--wp--custom--text--body);
	cursor: pointer;
}

.fluentform .ff-el-form-check-input {
	appearance: none;
	flex: none;
	width: 1.5rem;
	height: 1.5rem;
	margin: 0;
	background-color: var(--wp--custom--surface--card);
	background-position: center;
	background-repeat: no-repeat;
	background-size: 100%;
	border: var(--wp--custom--border-width--regular) solid var(--wp--custom--border--strong);
	border-radius: var(--wp--custom--radius--sm);
	cursor: pointer;
	transition: background-color var(--wp--custom--motion--duration--fast) var(--wp--custom--motion--ease--out);
}

.fluentform .ff-el-form-check-radio {
	border-radius: var(--wp--custom--radius--circle);
}

.fluentform .ff-el-form-check-input:checked {
	background-color: var(--wp--custom--focus--ring);
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 12.5l4 4 8-9'/%3E%3C/svg%3E");
	border-color: var(--wp--custom--focus--ring);
}

.fluentform .ff-el-form-check-radio:checked {
	background-image: radial-gradient(circle, var(--wp--preset--color--paper) 0 28%, transparent 31%);
}

/*
 * First and last name side by side. Fluent Forms sits each box at the foot of its column,
 * so a reason shown under one ("This field is required") pushes the other box down; from
 * the top they stay level, whatever appears under either.
 */
.fluentform .ff-name-field-wrapper .ff-t-cell {
	justify-content: flex-start;
}

/* Fluent Forms nudges the box up 2px to sit on a smaller line; ours is set by the row. */
.fluentform .ff-el-form-check-label .ff-el-form-check-input {
	top: 0;
}

/*
 * The consent box: the same tick box, its words beside it. Fluent Forms lays it out as a
 * table with a 20px first cell, too narrow for the 24px box, and pads it with !important,
 * which only !important can undo.
 */
.fluentform .ff-el-tc {
	display: block;
}

.fluentform .ff-el-tc label.ff_tc_label {
	display: flex;
}

.fluentform .ff-el-tc label.ff_tc_label > span,
.fluentform .ff-el-tc label.ff_tc_label > div {
	display: block;
	width: auto;
	padding-top: 0 !important;
}

.fluentform .ff_t_c {
	margin: 0;
	padding: 0;
}

/*
 * A field with a problem: a red edge and the reason below it, in red, semibold (Field's
 * error). The words of a tick box stay in their own colour; only the reason is red.
 */
.fluentform .ff-el-is-error .ff-el-form-control,
.fluentform .ff-el-is-error .ff-el-form-check-input:not(:checked) {
	border-color: var(--wp--custom--state--danger);
}

.fluentform .ff-el-is-error .ff-el-form-check-label,
.fluentform .ff-el-is-error .ff-el-form-check-label a {
	color: var(--wp--custom--text--body);
}

.fluentform .error.text-danger {
	margin-top: var(--wp--preset--spacing--2);
	font-size: var(--wp--preset--font-size--small);
	font-weight: var(--wp--custom--weight--semibold);
	line-height: 1.4;
	color: var(--wp--custom--state--danger);
}

/* The submit button is the site's button (functions.php adds wp-element-button). */
.fluentform .ff_submit_btn_wrapper {
	margin-top: var(--wp--preset--spacing--8);
	margin-bottom: 0;
}

.fluentform .ff-btn-submit.wp-element-button {
	min-height: var(--wp--custom--hit-min);
	cursor: pointer;
}

.fluentform .ff-btn-submit.wp-element-button:disabled {
	cursor: progress;
	opacity: 0.7;
}

/* Problems the server sends back, listed above the button (ErrorSummary). */
.fluentform .ff-errors-in-stack {
	padding: var(--wp--preset--spacing--6);
	background-color: var(--wp--custom--surface--card);
	border: var(--wp--custom--border-width--chunky) solid var(--wp--custom--state--danger);
	border-radius: var(--wp--custom--radius--lg);
}

.fluentform .ff-errors-in-stack .error {
	font-size: var(--wp--preset--font-size--body);
	font-weight: var(--wp--custom--weight--semibold);
	color: var(--wp--custom--state--danger);
}

/*
 * The thank-you message that takes the form's place (SuccessPanel): mint, rounded, easing
 * in rather than appearing at once (design-audit.md #23). Under reduced motion it only fades.
 */
.ff-message-success {
	margin-top: 0;
	padding: var(--wp--preset--spacing--8);
	font-size: var(--wp--preset--font-size--body);
	color: var(--wp--custom--text--strong);
	background-color: var(--wp--custom--surface--mint);
	border: 0;
	border-radius: var(--wp--custom--radius--lg);
	box-shadow: none;
	transition:
		opacity var(--wp--custom--motion--duration--base) var(--wp--custom--motion--ease--out),
		transform var(--wp--custom--motion--duration--base) var(--wp--custom--motion--ease--out);
}

@starting-style {
	.ff-message-success {
		opacity: 0;
		transform: translateY(8px);
	}
}

@media (prefers-reduced-motion: reduce) {
	@starting-style {
		.ff-message-success {
			transform: none;
		}
	}
}

/* ------------------------------------------------------------------------ */
/* About us, Useful links, Policies and privacy (decisions.md, 30 October)   */
/* ------------------------------------------------------------------------ */

/*
 * Our story (page-about): the years down a line, a dot on each. Why not theme.json: a
 * line joining a run of groups, and a dot on each, are drawn with pseudo-elements.
 */
.cw-timeline {
	position: relative;
	display: grid;
	gap: var(--wp--preset--spacing--8);
	padding-left: var(--wp--preset--spacing--8);
}

.cw-timeline::before {
	content: "";
	position: absolute;
	top: 0.75rem;
	bottom: 0.75rem;
	left: 0.4375rem;
	width: var(--wp--custom--border-width--regular);
	background: var(--wp--custom--border--subtle);
}

.cw-timeline__item {
	position: relative;
}

.cw-timeline__item::before {
	content: "";
	position: absolute;
	top: 0.5rem;
	left: calc(-1 * var(--wp--preset--spacing--8));
	box-sizing: border-box;
	width: 1rem;
	height: 1rem;
	border: 3px solid var(--wp--custom--text--strong);
	border-radius: var(--wp--custom--radius--circle);
	background: var(--wp--custom--surface--card);
}

.cw-timeline .cw-timeline__when {
	margin: 0;
}

.cw-timeline__item > p {
	max-width: var(--wp--custom--measure--body);
	margin-top: var(--wp--preset--spacing--2);
}

/* From a tablet up, the year sits beside its words. */
@media (min-width: 760px) {
	.cw-timeline__item {
		display: grid;
		grid-template-columns: 7rem minmax(0, 1fr);
		column-gap: var(--wp--preset--spacing--6);
		align-items: baseline;
	}

	.cw-timeline__item > p {
		margin-top: 0;
	}
}

/*
 * A list of links to other websites (Useful links): one link a row, a line between rows,
 * the external-link mark at the end. Why not theme.json: list items have no style slots,
 * and the mark is a pseudo-element.
 */
.cw-linklist {
	margin: 0;
	padding: 0;
	list-style: none;
}

.cw-linklist li + li {
	border-top: 1px solid var(--wp--custom--border--subtle);
}

.cw-linklist a {
	display: flex;
	gap: var(--wp--preset--spacing--3);
	align-items: flex-start;
	justify-content: space-between;
	padding: var(--wp--preset--spacing--3) 0;
	color: var(--wp--custom--text--link);
	font-weight: var(--wp--custom--weight--semibold);
	text-decoration: none;
}

.cw-linklist a::after {
	content: "";
	flex: none;
	width: 1rem;
	height: 1rem;
	margin-top: 0.3em;
	background: currentColor;
	-webkit-mask: 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='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") center / contain no-repeat;
	mask: 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='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") center / contain no-repeat;
}

/*
 * Documents (Policies and privacy): each File block drawn as the design system's
 * DownloadLink, the row the job pages use. Why not theme.json: the File block has no
 * style slots for its link, and core shrinks it to 0.8em. The document mark is drawn in
 * ink (#2c2e35) inside the data URI, which can't read a custom property.
 */
.cw-docs .wp-block-file {
	margin: 0;
	font-size: var(--wp--preset--font-size--body);
}

.cw-docs .wp-block-file a {
	display: flex;
	gap: var(--wp--preset--spacing--3);
	align-items: center;
	box-sizing: border-box;
	min-height: 3.5rem;
	padding: var(--wp--preset--spacing--3) var(--wp--preset--spacing--4);
	border: var(--wp--custom--border-width--regular) solid var(--wp--custom--border--subtle);
	border-radius: var(--wp--custom--radius--md);
	background: var(--wp--custom--surface--card);
	color: var(--wp--custom--text--strong);
	font-weight: var(--wp--custom--weight--semibold);
	text-decoration: none;
	transition: border-color var(--wp--custom--motion--duration--fast) var(--wp--custom--motion--ease--out);
}

.cw-docs .wp-block-file a::before {
	content: "";
	flex: none;
	width: 2.25rem;
	height: 2.25rem;
	border-radius: var(--wp--custom--radius--sm);
	background: var(--wp--custom--surface--page-alt) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%232c2e35' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z'/%3E%3Cpath d='M14 2v4a2 2 0 0 0 2 2h4'/%3E%3Cpath d='M16 13H8'/%3E%3Cpath d='M16 17H8'/%3E%3C/svg%3E") center / 1.25rem no-repeat;
}

.cw-docs__label {
	color: var(--wp--custom--text--muted);
	font-size: var(--wp--preset--font-size--small);
	font-weight: var(--wp--custom--weight--semibold);
}

/* "Need help now?" and "Worried about someone's safety?": the alert mark in red, as the design system's alerts. */
.cw-urgent .cw-icon {
	color: var(--wp--custom--state--danger);
}

@media (hover: hover) and (pointer: fine) {
	.cw-linklist a:hover {
		color: var(--wp--custom--text--link-hover);
		text-decoration: underline;
	}

	.cw-docs .wp-block-file a:hover {
		border-color: var(--wp--custom--border--strong);
	}
}

/*
 * A strand landing page opens with its photo (decisions.md, 2 November 2026, and
 * 3 November): the featured image floats at the right of the page, rising about halfway
 * into the strand's band beside the title. The page's own content wraps beside it, and
 * any full-width or wide section in the content (the Nursery's Ofsted, rooms and team
 * sections) clears the photo and runs the full width below it. On a phone the photo
 * comes straight after the band, overlapping its edge. Without a featured image the
 * content is an ordinary page body. Why not theme.json: a float, a negative margin that
 * pulls the photo into the band above, and layouts that depend on whether there's a photo
 * (:has()).
 */
.cw-strand-intro {
	display: flow-root;
}

.cw-strand-intro > .cw-strand-photo {
	position: relative;
	z-index: 1;
}

.cw-strand-intro > .cw-strand-photo img {
	box-shadow: var(--wp--preset--shadow--photo);
}

/*
 * The content is an ordinary block, not its own formatting context (as WordPress makes
 * post content), so its text wraps beside the photo instead of the whole column shrinking.
 */
.cw-strand-intro > .cw-strand-body {
	display: block;
	padding-top: var(--wp--preset--spacing--10);
}

.cw-strand-body > :is(.alignfull, .alignwide) {
	clear: both;
}

@media (min-width: 782px) {
	.cw-strand-head {
		padding-bottom: var(--wp--preset--spacing--16) !important;
	}

	/* Without a photo there's nothing to rise into the band, so it keeps its usual depth. */
	main:not(:has(.cw-strand-photo img)) .cw-strand-head {
		padding-bottom: var(--wp--preset--spacing--8) !important;
	}

	/* The title and summary keep to the left of the photo. */
	main:has(.cw-strand-photo img) .cw-strand-head__text > * {
		max-width: 48%;
	}

	.cw-strand-intro > .cw-strand-photo {
		float: right;
		width: calc(min(100%, var(--wp--style--global--wide-size)) * 0.46);
		max-width: none !important;
		margin: -7rem max(0px, calc((100% - var(--wp--style--global--wide-size)) / 2)) var(--wp--preset--spacing--8) var(--wp--preset--spacing--12) !important;
	}
}

@media (max-width: 781.98px) {
	.cw-strand-intro > .cw-strand-photo {
		margin-top: calc(-1 * var(--wp--preset--spacing--6)) !important;
	}

	.cw-strand-intro:has(.cw-strand-photo img) .cw-strand-body {
		padding-top: var(--wp--preset--spacing--8);
	}
}

/* ------------------------------------------------------------------------ */
/* Sections for any page: facts, steps, questions, gallery (3 November)      */
/* ------------------------------------------------------------------------ */

/*
 * A list of things that are true (the Ofsted judgements): a tick in a circle in place of
 * each bullet. Why not theme.json: list markers have no style slot; the tick is drawn.
 */
.cw-checks {
	padding-left: 0;
	list-style: none;
}

.cw-checks li {
	position: relative;
	padding-left: 2rem;
}

.cw-checks li + li {
	margin-top: var(--wp--preset--spacing--2);
}

.cw-checks li::before {
	content: "";
	position: absolute;
	top: 0.2em;
	left: 0;
	width: 1.25rem;
	height: 1.25rem;
	border-radius: var(--wp--custom--radius--circle);
	background: var(--wp--custom--text--strong) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 12.5l4 4 8-9'/%3E%3C/svg%3E") center / 0.875rem no-repeat;
}

/* A key fact: the figure sits tight above its line. Why not theme.json: margin between two siblings in one card. */
.cw-fact .cw-fact__figure {
	margin: 0;
	line-height: 1;
}

/*
 * Numbered steps: each number in an ink circle beside its step. Why not theme.json: an
 * ordered list's numbers have no style slot, so they're drawn with a counter.
 */
.cw-steps {
	padding-left: 0;
	list-style: none;
	counter-reset: cw-step;
}

.cw-steps li {
	position: relative;
	min-height: 2.5rem;
	padding-left: 3.5rem;
	counter-increment: cw-step;
}

.cw-steps li + li {
	margin-top: var(--wp--preset--spacing--6);
}

.cw-steps li::before {
	content: counter(cw-step);
	position: absolute;
	top: -0.2rem;
	left: 0;
	display: grid;
	place-items: center;
	width: 2.5rem;
	height: 2.5rem;
	border-radius: var(--wp--custom--radius--circle);
	background: var(--wp--custom--text--strong);
	color: var(--wp--custom--text--inverse);
	font-family: var(--wp--preset--font-family--display);
	font-weight: var(--wp--custom--weight--bold);
}

.cw-steps li strong {
	display: block;
	color: var(--wp--custom--text--strong);
}

/*
 * Questions and answers: each Details block a row between hairlines, the question in
 * semibold with a chevron that turns as it opens. Why not theme.json: the Details block's
 * summary and open state have no style slots.
 */
.cw-faq .wp-block-details:first-child {
	border-top: 1px solid var(--wp--custom--border--subtle);
}

.cw-faq .wp-block-details {
	margin: 0;
	padding: var(--wp--preset--spacing--4) 0;
	border-bottom: 1px solid var(--wp--custom--border--subtle);
}

.cw-faq summary {
	display: flex;
	gap: var(--wp--preset--spacing--3);
	align-items: center;
	justify-content: space-between;
	min-height: var(--wp--custom--hit-min);
	color: var(--wp--custom--text--strong);
	font-weight: var(--wp--custom--weight--semibold);
	list-style: none;
	cursor: pointer;
}

.cw-faq summary::-webkit-details-marker {
	display: none;
}

.cw-faq summary::after {
	content: "";
	flex: none;
	width: 0.6rem;
	height: 0.6rem;
	margin-right: 0.3rem;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: rotate(45deg);
	transition: transform var(--wp--custom--motion--duration--fast) var(--wp--custom--motion--ease--out);
}

.cw-faq details[open] summary::after {
	transform: rotate(-135deg);
}

.cw-faq details > :not(summary) {
	margin-top: var(--wp--preset--spacing--2);
}

/* A gallery's photos take the site's tile corners. Why not theme.json: the gallery's own images inherit the image block's larger radius. */
.cw-gallery .wp-block-image img {
	border-radius: var(--wp--custom--radius--md);
}
