/**
 * Block style variations and per-block refinements.
 *
 * Loaded on the front end AND passed to add_editor_style(), so the editor and
 * the site render these identically from one source. Contains no width or
 * layout rules — those belong to theme.json alone.
 */

/* ---------------------------------------------------------------------------
   Block styles registered in functions.php
   ------------------------------------------------------------------------ */

/* Group → "Card" */
.wp-block-group.is-style-aspire-card {
	background-color: var(--wp--preset--color--white);
	border: 1px solid var(--wp--preset--color--hairline);
	border-radius: 8px;
	padding: var(--wp--preset--spacing--50);
	transition: box-shadow 150ms ease, border-color 150ms ease;
}

.wp-block-group.is-style-aspire-card:hover {
	border-color: var(--wp--preset--color--muted);
	box-shadow: var(--wp--preset--shadow--soft);
}

/* Paragraph / Heading → "Proof figure" */
.is-style-aspire-figure {
	font-family: var(--wp--preset--font-family--display);
	font-weight: 600;
	font-variant-numeric: tabular-nums;
	line-height: 1;
	letter-spacing: -0.01em;
	margin-block: 0;
}

/* Separator → "Hairline rule" */
.wp-block-separator.is-style-aspire-hairline {
	border: none;
	border-top: 1px solid var(--wp--preset--color--hairline);
	opacity: 1;
	width: 100%;
}

/* ---------------------------------------------------------------------------
   Navigation
   ------------------------------------------------------------------------ */

/* Give the mobile overlay the brand's type and comfortable hit areas. */
.wp-block-navigation__responsive-container.is-menu-open {
	font-family: var(--wp--preset--font-family--display);
}

/* 44px minimum touch target on the mobile menu toggle. */
.wp-block-navigation__responsive-container-open,
.wp-block-navigation__responsive-container-close {
	min-width: 44px;
	min-height: 44px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

/* ---------------------------------------------------------------------------
   Buttons
   ------------------------------------------------------------------------ */

/* Outline variant reads as a secondary action, per the design system. */
.wp-block-button.is-style-outline > .wp-block-button__link {
	border-width: 1px;
	background-color: transparent;
	color: var(--wp--preset--color--deep-blue);
}

.wp-block-button.is-style-outline > .wp-block-button__link:hover,
.wp-block-button.is-style-outline > .wp-block-button__link:focus {
	background-color: var(--wp--preset--color--pale-blue);
	color: var(--wp--preset--color--deep-blue);
}

/* On a Bathsheba Blue ground the primary fill disappears — invert it.
   (Design-system rule, not a visual preference.) */
.has-bathsheba-blue-background-color .wp-block-button:not(.is-style-outline) > .wp-block-button__link {
	background-color: var(--wp--preset--color--white);
	color: var(--wp--preset--color--deep-blue);
}

/* ...but a white card sitting on that blue ground restores the normal fill.
   Same specificity, declared later, so the nearest surface wins. */
.has-white-background-color .wp-block-button:not(.is-style-outline) > .wp-block-button__link {
	background-color: var(--wp--preset--color--deep-blue);
	color: var(--wp--preset--color--white);
}

.wp-block-button:active > .wp-block-button__link {
	transform: scale(0.98);
}

/* Filter chip — the cohort index's SECTOR/STATUS row. A white pill with a
   hairline border and ink text, distinct from "Outline" (deep-blue border
   and text — a secondary CTA elsewhere, e.g. "Audited financials [PDF]").
   The active chip in the same row needs no rule here: it is a plain button
   with no style class, so it already gets the default filled deep-blue pill. */
.wp-block-button.is-style-aspire-chip > .wp-block-button__link {
	background-color: var(--wp--preset--color--white);
	border: 1px solid var(--wp--preset--color--hairline);
	color: var(--wp--preset--color--ink);
}

.wp-block-button.is-style-aspire-chip > .wp-block-button__link:hover,
.wp-block-button.is-style-aspire-chip > .wp-block-button__link:focus-visible {
	background-color: var(--wp--preset--color--sand);
	border-color: var(--wp--preset--color--muted);
	color: var(--wp--preset--color--ink);
}

/* The number on a STATUS chip ("Graduated 14"), appended inside the link by
   aspire_lb_status_chip_counts() in functions.php.

   Subordinate to the label: the chip's job is still to say what it filters.
   Colour is inherited rather than set, so this reads correctly on both chip
   states — muted-on-white for an inactive chip, and white-on-deep-blue for the
   active one, where a hard-coded grey would have been close to unreadable. */
.wp-block-button > .wp-block-button__link > .aspire-chip-count {
	margin-left: 0.5em;
	opacity: 0.6;
	font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------------
   Post content niceties
   ------------------------------------------------------------------------ */

.wp-block-post-navigation-link {
	font-family: var(--wp--preset--font-family--display);
	font-weight: 500;
}

/* ---------------------------------------------------------------------------
   Target size (WCAG 2.2 SC 2.5.8)
   Measured in-browser: navigation links rendered at 20px and social icons at
   22px, both below the 24px minimum. Buttons are taken to 44px so they also
   satisfy the stricter SC 2.5.5 guidance on touch.
   ------------------------------------------------------------------------ */

.wp-element-button,
.wp-block-button__link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 44px;
}

.wp-block-navigation .wp-block-navigation-item__content {
	padding-block: 0.4rem;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
	padding-block: 0.75rem;
}

.wp-block-social-links .wp-block-social-link a {
	display: flex;
	align-items: center;
	justify-content: center;
	min-width: 28px;
	min-height: 28px;
}

/* A proof figure is a single token — never let it break across lines. */
.is-style-aspire-figure {
	white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   Proof band — between 782px and 1023px four figures share too little width
   and the largest ($960,000) overflows its column. Go two-up in that band
   rather than shrinking the figures at every size.
   ------------------------------------------------------------------------ */

@media (min-width: 782px) and (max-width: 1023px) {
	.wp-block-columns.aspire-proof-columns {
		flex-wrap: wrap !important;
	}

	/* Written when this row held four cards, where 50% gave a clean 2x2. The
	   client review removed the graduation-count card, so three cards at 50%
	   wrap as 2 + 1 and strand the last one beside empty space. Letting the
	   basis be a floor rather than a fixed width lets a final odd card expand
	   to fill its row, which reads as deliberate at any card count. */
	.wp-block-columns.aspire-proof-columns > .wp-block-column {
		flex-basis: calc(50% - var(--wp--preset--spacing--60)) !important;
		flex-grow: 1;
	}

	/* The footer's four columns leave the contact column ~124px in this band,
	   which breaks the email address mid-word. Go two-up here as well. */
	.wp-block-columns.aspire-footer-columns {
		flex-wrap: wrap !important;
	}

	.wp-block-columns.aspire-footer-columns > .wp-block-column {
		flex-basis: calc(50% - var(--wp--preset--spacing--70)) !important;
		flex-grow: 0;
	}
}

/* ---------------------------------------------------------------------------
   Cohort index — card grid, GRADUATED badge.

   Client review (2026): the card no longer carries an "Open dossier" link
   (the client switched that route off — see build_cohort.py) and the badge
   text changed from "Certified" to "Graduated" (slug unchanged — see
   cohort_data.py). The .wp-block-read-more rules further down this section
   are dormant, not deleted: turning the route back on only needs the block
   markup re-added (build_cohort.py's card()), and this styling is already
   here waiting for it.

   The badge is a core/post-terms {"term":"post_tag"} instance. A card carries
   at most one status tag (Graduated or In programme — see cohort_data.py),
   so this never has to pick one term out of a list. It floats right so the
   heading floods over the top of it — the same wrapping the design's
   reference shows — the title row's own overflow:hidden clears the float
   before the description paragraph beneath it.
   ------------------------------------------------------------------------ */

.cohort-card-title-row {
	overflow: hidden;
}

/* The badge's own pill styling (background, padding, radius) lives in the
   "Cohort dossier" rule block below, shared with the dossier template's
   badge — both are built from the same aspire_lb_filter_status_badge()
   PHP filter in functions.php. .cohort-badge only needs its card-specific
   float positioning here.

   WHICH pill a card shows is decided in PHP (aspire_lb_filter_status_badge(),
   hooked to render_block_core/post-terms), never by hiding a tag's rendered
   link here by matching its href — a selector keyed to the tag archive's
   permalink breaks the moment that permalink base changes, at which point
   every card would show whatever pill the selector stopped catching.

   Three states, two of which draw something: GRADUATED (filled, below),
   IN PROGRAMME (.is-in-programme, outline) and status-not-recorded (no pill
   at all). The two visible ones are not peers on purpose — see the PHP. */
.cohort-badge {
	float: right;
	margin-left: 12px;
	margin-top: 2px;
	padding: 4px 12px;
}

/* CSS Grid already stretches each <li> to the row's full height by default
   (align-items: stretch) — scoped to .cohort-card specifically so this never
   touches the Field Notes / home grid, whose cards use a different (flow)
   layout and must keep their existing shrink-to-content height. */
.wp-block-post-template.is-layout-grid > .wp-block-post > .cohort-card {
	width: 100%;
	height: 100%;
	box-sizing: border-box;
}

/* A vertical flex Group (used so the footer cluster can be pushed to the
   card's bottom edge with justify-content: space-between) defaults its
   children to align-items: flex-start — i.e. shrink-wrapped to content
   width. Force them back to the card's full width so the footer row has
   room to work (previously a sector-label / "Open dossier" space-between;
   now just the sector label, left-aligned — see build_cohort.py). */
.cohort-card.is-layout-flex > * {
	width: 100%;
}

/* The sector term in the card footer is a real category link, but the design
   shows plain muted uppercase text, not an underlined link — the underline
   comes from the theme's global link style otherwise. Keep it discoverable
   on hover/keyboard focus instead. */
.cohort-card-footer .wp-block-post-terms a {
	text-decoration: none;
}

.cohort-card-footer .wp-block-post-terms a:hover,
.cohort-card-footer .wp-block-post-terms a:focus-visible {
	text-decoration: underline;
}

/* Dormant, not dead: no card currently renders a read-more block (the
   "Open dossier" route is off — see the section header above), but this
   stays so the route can be switched back on with a markup-only change. */
.cohort-card-footer .wp-block-read-more {
	background: transparent;
	color: var(--wp--preset--color--deep-blue);
	font-family: var(--wp--preset--font-family--display);
	font-weight: 700;
	font-size: 0.875rem;
	text-decoration: none;
	padding: 0;
	min-height: 24px;
}

.cohort-card-footer .wp-block-read-more:hover,
.cohort-card-footer .wp-block-read-more:focus {
	text-decoration: underline;
}

/* ---------------------------------------------------------------------------
   Cohort dossier (templates/single-cohort.html + patterns/dossier-body.php)
   ------------------------------------------------------------------------ */

/* Breadcrumb: core/post-terms gets an uppercase Jost eyebrow treatment
   globally (theme.json), which is right for the GRADUATED badge and the
   card's sector footer but wrong for a breadcrumb, which reads as plain
   sentence-case text in the design. */
.dossier-breadcrumb .wp-block-post-terms {
	font-family: var(--wp--preset--font-family--body);
	text-transform: none;
	letter-spacing: normal;
}

/* Every crumb link (the hand-written "The Cohort" link and the dynamic
   sector term) reads as plain muted breadcrumb text, not the theme's
   default deep-blue link colour — with underline kept for hover/keyboard
   discoverability since colour alone is not a sufficient link affordance. */
.dossier-breadcrumb a {
	color: var(--wp--preset--color--muted);
	text-decoration: none;
}

.dossier-breadcrumb a:hover,
.dossier-breadcrumb a:focus-visible {
	text-decoration: underline;
}

/* The "Graduated" pill above the title. Rendered only when the post carries
   the "certified"-slug tag (display name "Graduated" — see cohort_data.py)
   — see aspire_lb_filter_status_badge() in functions.php, which also fully
   replaces the cohort card's GRADUATED badge markup so both share this one
   rule instead of two near-duplicates. */
.dossier-badge,
.cohort-badge {
	display: inline-block;
	background-color: var(--wp--preset--color--pale-blue);
	color: var(--wp--preset--color--deep-blue);
	border-radius: 999px;
	line-height: 1.4;
}

.dossier-badge {
	padding: 6px 16px;
}

.cohort-badge a {
	color: inherit;
	text-decoration: none;
}

/* "In programme" — a state, not an achievement.
 *
 * Deliberately quieter than the Graduated pill: no fill, a hairline border,
 * muted text. A funder scanning the grid should be able to tell the two apart
 * without reading either, and should read GRADUATED first.
 *
 * Colour is not carrying the distinction on its own: filled-vs-outline is a
 * shape difference, which survives greyscale printing and every form of colour
 * blindness. Checked against the same criteria as the six value-bar hues.
 *
 * The ring is an inset box-shadow rather than a border, and that is not a style
 * preference. These pills are inline-block with no set width or height, so their
 * box is content + padding + border whatever box-sizing says — a 1px border adds
 * 2px of height that the filled pill beside it does not have, and the badge
 * floats right against the card title, so 2px is enough to knock adjacent card
 * titles out of line. An inset shadow paints the ring and occupies no layout. */
.dossier-badge.is-in-programme,
.cohort-badge.is-in-programme {
	background-color: transparent;
	color: var(--wp--preset--color--muted);
	box-shadow: inset 0 0 0 1px var(--wp--preset--color--hairline);
}

/* Windows High Contrast / forced-colors throws away both background-color and
   box-shadow, which would leave the two pills identical. Restate the ring as an
   OUTLINE, which forced-colors does honour and which — unlike a border — takes
   up no layout box, so the height match above survives. */
@media (forced-colors: active) {
	.dossier-badge.is-in-programme,
	.cohort-badge.is-in-programme {
		outline: 1px solid currentColor;
		outline-offset: -1px;
	}
}

/* AT A GLANCE panel — the Sector row's value is a live core/post-terms
   block (so it can never drift from the post's own assigned category), but
   it must read as a plain value line like Parish or Entered cohort, not
   another eyebrow badge. */
.dossier-glance-value,
.dossier-glance-value a {
	display: block;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 400;
	text-transform: none;
	letter-spacing: normal;
	color: var(--wp--preset--color--slate);
	text-decoration: none;
}

.dossier-glance-value a:hover,
.dossier-glance-value a:focus-visible {
	text-decoration: underline;
}

/* "Also in <Sector>" — the sector name is a real link to that category
   archive, styled to match the heading beside it rather than looking like
   a stray blue link, with underline kept for hover/keyboard discoverability. */
.dossier-related-term,
.dossier-related-term a {
	text-transform: none;
	letter-spacing: normal;
	text-decoration: none;
}

.dossier-related-term a:hover,
.dossier-related-term a:focus-visible {
	text-decoration: underline;
}

/* RECORD table year column — core/column resets min-width to 0 and adds
   word-break: break-word so long text can wrap in a narrow column. At 72px
   wide that lets a 4-digit year ("2022") break mid-digit under any flex
   shrink pressure, which is never the intent for a single unbreakable
   token. */
.dossier-record-year {
	white-space: nowrap;
}

/* Pull quote portrait placeholder — a flat circle until a real photograph
   replaces it; never stretched or squashed by the flex row it sits in. */
.dossier-quote-portrait {
	flex: 0 0 auto;
	width: 64px;
	height: 64px;
	border-radius: 999px;
	background-color: var(--wp--preset--color--pale-blue);
}

/* ---------------------------------------------------------------------------
   Full-bleed sections are never rounded.

   A section that spans the viewport has no visible outer edge, so a corner
   radius only ever shows as a clipped notch against the browser chrome. The
   theme's own patterns no longer set one, but !important is required here to
   also correct pages that were imported or authored before this rule existed:
   those carry the radius as an inline style, which no ordinary selector can
   outrank. Cards and images INSIDE a section keep their radius.
   ------------------------------------------------------------------------ */

.wp-block-group.alignfull {
	border-radius: 0 !important;
}

/* The RECORD year column carries an explicit flex-basis, which core pins with
   flex-grow:0 — but flex-shrink still defaults to 1, so a row with long text
   squeezes its year column narrower than the rest and the description column
   starts at a different x on every row. Pinning shrink is what actually makes
   the table read as a table. */
.wp-block-column.dossier-record-yearcol {
	flex-shrink: 0;
}

/* ---------------------------------------------------------------------------
   Root spacing and the footer seam
   ------------------------------------------------------------------------ */

/* The root blockGap is a real value (24px) so that a page an editor builds
   from scratch has sensible breathing room between blocks by default. It used
   to be 0, which did close the gap above the footer but at the cost of every
   new page rendering with its sections touching.

   WordPress applies the root gap as a top margin on each direct child of
   .wp-site-blocks, which is what put a stray band of space above the footer.
   Core writes that rule inside :where(), so it carries zero specificity and a
   plain class selector overrides it without !important. Zeroing it here on the
   header and footer template parts keeps the seam tight while leaving the gap
   working everywhere it is actually wanted. */
.wp-site-blocks > header.wp-block-template-part,
.wp-site-blocks > footer.wp-block-template-part {
	margin-block-start: 0;
}

/* ---------------------------------------------------------------------------
   Card rows
   ------------------------------------------------------------------------ */

/* Cards in a row must match height regardless of how much copy each carries,
   or a row where only some cards end in a button renders visibly ragged. The
   columns block already stretches its columns; it is the card inside that
   shrinks to its content, so the card is what needs the full height. */
.wp-block-column > .wp-block-group.is-style-aspire-card {
	height: 100%;
}

/* ---------------------------------------------------------------------------
   Text on the Bathsheba Blue band
   ------------------------------------------------------------------------ */

/* #009ddf is a shapes-only colour. The eyebrow inherits deep-blue, which on
   this ground measures 2.18:1 — a clear AA failure that no palette check
   caught, because both colours are individually fine against white. Anything
   set on this background takes ink instead. */
.wp-block-group.has-bathsheba-blue-background-color :where(h1, h2, h3, h4, h5, h6, p) {
	color: var(--wp--preset--color--ink);
}

/* ---------------------------------------------------------------------------
   Funder cards — dropped-in logos
   ------------------------------------------------------------------------ */

/* A funder card ships with a name and no logo, because the client has given
   permission to display exactly one funder and we hold no artwork. An editor
   adds the logo as an ordinary Image block inside the card; this sizes whatever
   they upload so a tall crest and a wide wordmark sit at the same visual weight
   without anybody opening an image editor.

   object-fit is CONTAIN, not cover. A photograph may be cropped to fill a
   shape; a logo may not — cropping someone's mark is the kind of thing that
   gets a permission withdrawn. width:auto lets a wide logo stay wide and a
   square one stay square, inside the same 56px height. */
.fn-card img {
	max-height: 56px;
	width: auto;
	max-width: 100%;
	object-fit: contain;
}

/* A fixed 56px band for the logo, whatever shape it is. Without it each card
   is as tall as its own artwork, so a wide wordmark and a tall crest push their
   funder names to different heights and the row reads as misaligned rather than
   as a set. */
.fn-card figure {
	margin: 0;
	height: 56px;
	display: flex;
	align-items: center;
}

/* ---------------------------------------------------------------------------
   Section rhythm
   ------------------------------------------------------------------------ */

/* A full-width section owns its vertical space through PADDING, and nothing is
   added between sections on top of that.
   
   Measured, the site had between 0 and 32px of extra margin landing on some
   sections and not others — the root block gap reaching whichever ones did not
   set a margin of their own, plus a couple that did. So two identical-looking
   bands could sit 192px apart in one place and 224px in another for no reason
   a reader could see. With this, the distance between any two sections is
   exactly their two paddings, everywhere.

   !important is needed because some patterns set the margin inline, and an
   inline style cannot be beaten any other way. It is scoped to sections that
   are direct children of the content wrapper, so nothing inside a section is
   affected. */
.entry-content > .alignfull {
	margin-block: 0 !important;
}

/* ---------------------------------------------------------------------------
   Board of directors — avatar placeholders
   ------------------------------------------------------------------------ */

/* A circle carrying the director's INITIALS, not a generic person silhouette.

   Initials are real information taken from the name beside them, so the circle
   is doing something rather than standing in for a photograph that does not
   exist. A silhouette icon on seven cards reads as seven missing images and
   invites the question "when are the photos coming?"; initials read as a
   deliberate treatment that happens to also work once headshots arrive — an
   editor drops an Image block in place of the circle, one director at a time,
   and the section does not look half-finished in the meantime.

   Deep Blue on Pale Blue measures 4.91:1, clear of the 4.5:1 needed at this
   size. Bathsheba Blue would not be — it is a shapes-only colour. */
.bd-avatar {
	width: 56px;
	height: 56px;
	border-radius: 999px;
	background-color: var(--wp--preset--color--pale-blue);
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 56px;
	/* Clips a dropped-in headshot to the circle. The rules further down describe
	   this as doing the clipping and, for one revision, did not exist — the
	   comment was written and the declaration was not. A photo's square corners
	   sat outside the circle. */
	overflow: hidden;
}

.bd-avatar p {
	color: var(--wp--preset--color--deep-blue);
	font-family: var(--wp--preset--font-family--display);
	font-weight: 600;
	font-size: 0.9375rem;
	letter-spacing: 0.02em;
	line-height: 1;
	margin: 0;
}

/* Dropping a headshot in.

   The whole point of the initials circle is that it can be replaced ONE
   director at a time without the other six looking unfinished, so the swap has
   to be something an editor can do in the block editor with no help: select the
   circle, add an Image block inside it, upload. These rules do the rest.

   The photograph is cropped to the circle by object-fit rather than asking
   anyone to crop a square before uploading — a portrait or a landscape snap
   both come out as a centred circular crop. overflow:hidden on the track is
   what actually clips it; without it the image corners sit outside the circle.

   :has() hides the initials once a real photo is in place, so an editor does
   not have to remember to delete the text as a separate step. Where :has() is
   not supported the image simply covers the letters, because it fills the
   circle — the fallback is invisible rather than broken. */
.bd-avatar img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	border-radius: 999px;
}

.bd-avatar:has(img) p {
	display: none;
}

/* The Image block wraps its <img> in a <figure> that would otherwise sit at its
   natural size inside the flex circle. */
.bd-avatar .wp-block-image,
.bd-avatar figure {
	width: 100%;
	height: 100%;
	margin: 0;
}

/* ---------------------------------------------------------------------------
   Journey rail — the Incubator page's ARRIVE / BUILD / LEAVE STRONGER steps
   ------------------------------------------------------------------------ */

/* Each step is a two-column block: a narrow column holding the numbered disc,
   and a wide one holding the content. The connecting line is drawn as a
   BACKGROUND on the narrow column, not as an absolutely-positioned pseudo
   element on the step.

   That choice is about Gutenberg, not about CSS. Absolute positioning inside a
   block means an editor who drags a step, adds one, or deletes one gets a rail
   that no longer lines up with anything, with no way to see why. A background
   on a real column is drawn by the column itself: steps can be reordered,
   duplicated or removed and the rail simply follows.

   Only steps that are NOT last draw the line, so it runs from the first disc
   to the last and stops there rather than trailing off the end. */
.tl-step:not(:last-child) > .wp-block-columns > .wp-block-column:first-child {
	background-image: linear-gradient(var(--wp--preset--color--pale-blue), var(--wp--preset--color--pale-blue));
	background-repeat: no-repeat;
	background-position: 19px top;
	background-size: 2px 100%;
}

/* The disc paints over the top of the line, which is what makes the line look
   like it starts below each number instead of running through it. It needs an
   opaque background of its own for that, which every .tl-dot-* gives it. */
.tl-dot {
	width: 40px;
	height: 40px;
	border-radius: 999px;
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 40px;
}

/* The numeral is INK on all three discs, not white. The design shows white,
   and measured against these three grounds white is 3.05:1 on Bathsheba Blue,
   2.15:1 on Sunset Orange and 1.73:1 on Garrison Green. At 13px that needs
   4.5:1, so all three fail and two fail badly. Ink gives 4.99 / 7.09 / 8.78.
   The disc still reads as blue, orange and green, which is the whole job the
   colour is doing here — the number just has to be readable on it. */
.tl-dot p {
	color: var(--wp--preset--color--ink);
	font-family: var(--wp--preset--font-family--display);
	font-weight: 600;
	font-size: 0.8125rem;
	line-height: 1;
	margin: 0;
}

/* The three step colours, in the approved design's order. These are brand hues
   used as SHAPES — a filled disc — which is the one use the design system
   permits for Bathsheba Blue and Garrison Green. */
.tl-dot-1 { background-color: var(--wp--preset--color--bathsheba-blue); }
.tl-dot-2 { background-color: var(--wp--preset--color--sunset-orange); }
.tl-dot-3 { background-color: var(--wp--preset--color--garrison-green); }

/* Stacked, the narrow column becomes full width and the rail would draw a
   2px line down the middle of the page. */
@media (max-width: 781px) {
	.tl-step > .wp-block-columns > .wp-block-column:first-child {
		background-image: none;
	}
}

/* ---------------------------------------------------------------------------
   Documents / reporting table
   ------------------------------------------------------------------------ */

/* The approved design draws "Download" as plain blue text with no underline.
   Theme-wide, links ARE underlined, and that is the right default: an
   underline is what marks a link inside a sentence, where colour alone is not
   enough. This column is the exception the rule allows — "Download" sits alone
   in its own column of a table, under no prose, doing nothing else. The
   underline comes back on hover and on keyboard focus, so the affordance is
   still there for anyone looking for it. */
.doc-row a {
	text-decoration: none;
}

.doc-row a:hover,
.doc-row a:focus {
	text-decoration: underline;
}

/* Below 782px the columns block stacks to one column per row, which turns each
   document into four stacked lines. Two of those lines are right-aligned for
   the table layout and read as stray text once stacked, so pull the whole row
   left and tighten it into a block. */
@media (max-width: 781px) {
	.doc-row .has-text-align-right {
		text-align: left;
	}
}

/* ---------------------------------------------------------------------------
   Value-breakdown chart fills
   ------------------------------------------------------------------------ */

/* Six categorical fills for the "Where the value comes from" bars, in fixed
   slot order 1..6 top to bottom — never cycled, never reassigned by rank. The
   ROWS were later reordered by value (largest first); the slots did not move,
   so the validated adjacency below is unchanged and only the Standard named in
   each comment changed. Keep it that way: reorder rows freely, leave the hexes
   where they are.

   These are re-stepped from the brand hues rather than taken from it raw. The
   raw palette does not survive inspection as a six-way categorical set:
   Bathsheba Blue and Sea Turquoise sit far too close to NORMAL vision, which no
   reader can separate, and Sunset Orange against Garrison Green collapses under
   protanopia.

   Validated as ADJACENT pairs, which is the rule for bars: worst adjacent pair
   is Sunset Orange against the darkened green at deltaE 11.0 protan / 21.3
   normal, both clear. It does NOT clear an ALL-PAIRS check (green against the
   rust is deltaE 5.4 deutan), and that is a deliberate, tested limit rather
   than an oversight: an exhaustive search over the sRGB gamut found NO six
   colours that clear all-pairs at 15/8 while keeping Bathsheba Blue, Sunset
   Orange and the turquoise re-step. Six categories is past what colour alone
   can carry. The relief the validator requires is present — every bar has its
   own text label and value sitting beside it — and it is also why two fills are
   allowed under 3:1 against the page.

   Slot 1 was #0086bd (DS Hover Blue) until it was caught reading as the same
   colour as Bathsheba Blue in slot 3 — deltaE 7.5 to normal vision, i.e. two
   bars in one chart that nobody can tell apart, which makes the colour coding
   look like a mistake. Replaced with an indigo at deltaE 25.3 from it.

   Re-validate before changing any hex:
     validate_palette.py "#4b3f9e,#a8582b,#009ddf,#6d8f00,#efa117,#0f9a86" */
.vb-fill-1 { background-color: #4b3f9e; }   /* Governance & Legal Compliance      — indigo, not in the DS */
.vb-fill-2 { background-color: #a8582b; }   /* Financial Management               — re-step, not in the DS */
.vb-fill-3 { background-color: #009ddf; }   /* Business, Strategic & Impact Plan. — DS Bathsheba Blue */
.vb-fill-4 { background-color: #6d8f00; }   /* Resource Mobilisation & Proposals  — Garrison Green, darkened */
.vb-fill-5 { background-color: #efa117; }   /* Human Resources                    — DS Sunset Orange */
.vb-fill-6 { background-color: #0f9a86; }   /* Branding & Communications          — Sea Turquoise, re-stepped */

/* Track and fill, shared mechanics.

   TWO bars in this theme are built this way: the six value-breakdown bars
   (.vb-*) and the progress bar on the Impact page (.pb-*). What they share is
   the STRUCTURE — a track that clips, a fill anchored to the left edge — and
   that is all that belongs in a shared rule.

   Their SHAPES are deliberately different, and an earlier version of this file
   got that wrong by giving both the same 999px pill:

     - a value-breakdown bar is a 14px pill with a pill-shaped fill floating
       inside it, which is what the approved design shows for a chart row;
     - the progress bar is a 52px rounded rectangle at 6px, filled from the left
       with a SQUARE inner edge — measured off the design, where the fill's
       right edge is pixel-straight down all 52 rows and the outer corners come
       in about 6px.

   A pill reads as a token, a discrete thing. A rounded rectangle filling up
   reads as a vessel with a level in it, which is what a progress bar is. They
   are different jobs; making them look alike was the mistake. */
.vb-track,
.pb-track {
	background-color: var(--wp--preset--color--sand);
	overflow: hidden;
}

.vb-fill,
.pb-fill {
	height: 100%;
	/* WordPress's constrained layout sets margin-left/right to auto on every
	   child, with !important, which centres the fill in its track — so a 10% bar
	   floats in the middle instead of growing from the left and the whole chart
	   is unreadable. Anchor it to the start. */
	margin-left: 0 !important;
	margin-right: auto !important;
	transition: width 200ms ease-out;
}

/* ---- value-breakdown: a pill, with a pill inside it ---------------------- */
.vb-track {
	height: 14px;
	border-radius: 999px;
}

.vb-fill {
	border-radius: 999px;
}

/* ---- progress: one rounded rectangle, filled from the left --------------- */
/* 52px is the old two-column build's 26px+26px padding, preserved so nothing
   else on the Impact page shifts. */
.pb-track {
	height: 52px;
	border-radius: 6px;
}

/* No radius of its own: the fill's left corners are rounded by the track
   clipping it, and its right edge stays square wherever it happens to stop.
   Rounding it here would round that inner edge too and put a visible notch in
   the middle of the bar. */
.pb-fill {
	border-radius: 0;
	background-color: var(--wp--preset--color--bathsheba-blue);
}

/* ---- the same bars, on the editor canvas --------------------------------

   The fill is an empty group block: a coloured rectangle with nothing inside
   it, which is right for the front end and is exactly what the editor handles
   worst. An empty group is drawn as a block APPENDER — a placeholder outline
   with its own height and no background — so the bars appear on the canvas as
   hollow outlines and an editor reasonably concludes the section is broken.

   These rules put the shape back. They are scoped to .editor-styles-wrapper so
   they cannot touch the front end, and they are in this file rather than a
   separate editor stylesheet because add_editor_style() already loads it (see
   aspire_lb_setup() in functions.php) and one file cannot drift from itself. */
.editor-styles-wrapper .vb-track,
.editor-styles-wrapper .vb-fill {
	min-height: 14px;
}

.editor-styles-wrapper .pb-track,
.editor-styles-wrapper .pb-fill {
	min-height: 52px;
}

.editor-styles-wrapper .vb-fill,
.editor-styles-wrapper .pb-fill {
	/* Gutenberg pads an empty group so its appender is clickable; that padding
	   makes a 14px bar 40-odd px tall on the canvas and nowhere else. */
	padding: 0 !important;
}

/* The appender itself: an editor should not be invited to put blocks inside a
   bar. Hiding it also stops it forcing the height back open. */
.editor-styles-wrapper .vb-fill .block-list-appender,
.editor-styles-wrapper .vb-fill .block-editor-button-block-appender,
.editor-styles-wrapper .vb-fill .block-editor-default-block-appender,
.editor-styles-wrapper .pb-fill .block-list-appender,
.editor-styles-wrapper .pb-fill .block-editor-button-block-appender,
.editor-styles-wrapper .pb-fill .block-editor-default-block-appender {
	display: none !important;
}

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

/* Each bar's caption is a flex row — Standard on the left, "400 hrs · BBD
   200,000" on the right. On a phone that row is wider than the screen for the
   longer Standard names, so flex wraps it, and it wraps PER ROW: three captions
   break onto two lines and three do not, which gives the chart a ragged,
   half-broken rhythm exactly where it needs to look deliberate. Below 600px
   every caption stacks instead, so all six behave the same way. */
@media (max-width: 600px) {
	.vb-row > .is-layout-flex {
		flex-direction: column;
		/* The block writes align-items:center as an INLINE style (its
		   verticalAlignment attribute), which is what centres the label and
		   amount against each other on a wide screen and is right there. Once
		   the row becomes a column that same declaration centres them
		   horizontally, leaving every caption floating above a bar that starts
		   hard left. An inline style can only be beaten by !important. */
		align-items: flex-start !important;
	}
}

/* ---------------------------------------------------------------------------
   THE SPACING DIAL — "Spacing: Compact" and "Spacing: Generous"
   ---------------------------------------------------------------------------
   Two block styles on core/group, registered in functions.php, that retune a
   whole section's rhythm in one choice.

   These deliberately REDEFINE the spacing presets on the section element rather
   than overriding individual properties. Section padding and most internal gaps
   are written as inline styles in the pattern markup — `padding-top:
   var(--wp--preset--spacing--90)` — and an inline style beats any class rule,
   so a conventional override would need !important on every one of them and
   would still miss the gaps it did not know about.

   Redefining the variable instead means the inline styles stay exactly as they
   are and simply resolve to a different number, and because custom properties
   inherit, everything nested inside follows: the section padding, the gap
   between cards, the gap between a heading and its paragraph. One choice, the
   whole ladder, still in proportion.

   (This is the same inheritance behaviour that was a BUG in the render harness,
   where a child container's gap shadowed its parent's. Here it is the point.)

   Each style is the scale shifted one rung:

       preset        default    Compact     Generous
       spacing|40      16px       12px        24px
       spacing|50      24px       16px        32px
       spacing|60      32px       24px        48px
       spacing|70      48px       32px        64px
       spacing|80      64px       48px        96px
       spacing|90      96px       64px       144px

   Compact is every step one down the scale, Generous one up. The top of
   Generous has no rung above it, so 96 goes to 144 — the same 1.5x the rest of
   that column happens to be.

   Do not add a third variant without re-reading tools/gen_patterns.py: the
   relationships are named there (TIGHT / CLOSE / STEP / APART) and the whole
   point is that they stay in proportion to each other.
   --------------------------------------------------------------------------- */
.wp-block-group.is-style-aspire-rhythm-compact {
	--wp--preset--spacing--40: 12px;
	--wp--preset--spacing--50: 16px;
	--wp--preset--spacing--60: 24px;
	--wp--preset--spacing--70: 32px;
	--wp--preset--spacing--80: 48px;
	--wp--preset--spacing--90: 64px;
}

.wp-block-group.is-style-aspire-rhythm-generous {
	--wp--preset--spacing--40: 24px;
	--wp--preset--spacing--50: 32px;
	--wp--preset--spacing--60: 48px;
	--wp--preset--spacing--70: 64px;
	--wp--preset--spacing--80: 96px;
	--wp--preset--spacing--90: 144px;
}

/* Testimonials — the <cite> is for machines, not readers.

   Each testimonial shows its speaker in a proper block beneath the quote:
   portrait circle, name, role, relationship to ASPIRE. The <cite> repeats the
   name and role and is hidden, because showing both would print the attribution
   twice.

   It is hidden rather than deleted for two reasons. A <blockquote> with no
   <cite> is worse markup — the attribution stops being machine-readable, which
   matters on a page whose argument is that ASPIRE can be checked. And
   tools/audit.php reads every <cite> in the theme and fails the build if a named
   quote is not on its approved list; that check is what stopped invented
   testimony being attributed to two real Barbadians, and removing the element
   would quietly switch it off for this pattern.

   clip-path over display:none so it stays in the accessibility tree. */
.wp-block-quote.is-style-plain cite {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

/* Testimonial cards — speakers pinned to the bottom.

   The three cards are grid items, so they already stretch to a common height.
   Their CONTENTS did not: each speaker block sat directly under its own quote,
   so with quotes of 70, 35 and 45 words the three attributions landed at three
   different heights with a pool of empty card beneath the short ones. It read
   as two unfinished cards rather than one tidy row.

   Pushing the speaker down with margin-top:auto lines all three up on the same
   baseline and puts the leftover space where it belongs — between the quote and
   its attribution, which is a gap that is meant to be there. */
.wp-block-group.ts-card-outer {
	display: flex;
	flex-direction: column;
}

.wp-block-group.ts-card {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
}

.wp-block-group.ts-card > .bd-person {
	/* auto pushes the speaker to the bottom of the card; the padding is the
	   MINIMUM gap, for the card whose quote is long enough to leave no slack.
	   This must not be a margin-top in the pattern markup: that is an inline
	   style, it beats this rule, and `auto` never gets a chance to do its job. */
	margin-top: auto;
	padding-top: var(--wp--preset--spacing--70);
}
