/*
 * TIA Yukon — supplemental styles.
 *
 * Only what theme.json and /styles cannot express. Every rule here should have a
 * reason it is not a token. Reference preset custom properties, never raw hex, so
 * a token change in theme.json propagates.
 */

/* --------------------------------------------------------------------------
 * Focus
 * Core's default focus ring disappears on dark surfaces. Use a two-tone ring so
 * it stays visible on white, tint, linen, dark and brand alike.
 * ----------------------------------------------------------------------- */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
	outline: 2px solid var(--wp--preset--color--pink-500);
	outline-offset: 2px;
	border-radius: 2px;
}

/* Two ways a surface can go dark, and both need the ring flipped.
 *
 * A section style variation emits `is-style-section-brand--13` plus its own
 * background declaration — it never sets `has-pink-500-background-color`. Keying
 * the inversion off the preset class alone meant it matched nothing on any
 * section, so a focus ring on the brand surface was drawn pink-500 on pink-500:
 * 1.00:1, invisible. The `[class*=]` form is what the rest of this file already
 * uses to reach section styles, because of that numeric suffix.
 *
 * The preset classes stay for the case they do cover: a group where an editor
 * picked the background by hand from the colour control. */
[class*="is-style-section-dark"] :where(a, button, input, select, textarea, [tabindex]):focus-visible,
[class*="is-style-section-brand"] :where(a, button, input, select, textarea, [tabindex]):focus-visible,
.has-blue-950-background-color :where(a, button, input, select, textarea, [tabindex]):focus-visible,
.has-pink-500-background-color :where(a, button, input, select, textarea, [tabindex]):focus-visible {
	outline-color: var(--wp--preset--color--white);
}

/* A card with its own light surface sitting on a dark or brand section is the
   exception to the exception: the ring is drawn around the card, against the
   section behind it, so it needs to stay pink. */
[class*="is-style-section-dark"] .tiay-card[class*="-background-color"] :where(a, button):focus-visible,
[class*="is-style-section-brand"] .tiay-card[class*="-background-color"] :where(a, button):focus-visible {
	outline-color: var(--wp--preset--color--pink-500);
}

/* ...and back to white again when the card is dark rather than light.

   The exception above assumes a card with a background colour is a LIGHT card
   sitting on a dark section — usually true, and not true of the Boost Your
   Business streams, which are blue-800 cards on a dark section. There the
   exception restores a pink-500 ring against blue-800: 2.60:1, under the 3:1
   WCAG 1.4.11 asks of a focus indicator.

   The same assumption put a pink-700 link on those cards at 1.70:1, fixed
   further down this file. One assumption, two failures, and the ring is the one
   nobody sees until they navigate by keyboard.

       blue-600   pink ring 1.83:1   white ring  8.56:1
       blue-800   pink ring 2.60:1   white ring 12.16:1
       blue-950   pink ring 3.64:1   white ring 17.00:1

   blue-950 passes on 3:1 and is included anyway: a focus ring that changes
   colour depending on which dark card it lands in is harder to recognise than
   one that does not. */
[class*="is-style-section-"]
	.tiay-card:is(
		.has-blue-400-background-color,
		.has-blue-600-background-color,
		.has-blue-800-background-color,
		.has-blue-950-background-color,
		.has-pink-500-background-color,
		.has-pink-700-background-color,
		.has-stone-700-background-color,
		.has-stone-900-background-color
	)
	:where(a, button):focus-visible {
	outline-color: var(--wp--preset--color--white);
}

/* --------------------------------------------------------------------------
 * Skip link
 *
 * Finding 12: functional and correctly placed, but wearing core's grey — #eee
 * on #444 — which belongs to no palette on this site. The first thing a
 * keyboard user sees should not look like a browser default.
 *
 * Only the focus state is touched. Core's hidden state works and is not worth
 * reimplementing.
 *
 * The `body` prefix is deliberate. Core prints these rules in an inline <style>
 * whose selector is `.skip-link.screen-reader-text:focus` — (0,3,0), the same
 * weight a matching rule here would carry. Today that inline block happens to
 * sit above tiay.css in the head, so an equal-specificity rule would win on
 * order alone. Relying on that is how four other rules in this file came to
 * exist and do nothing. `body` makes it (0,3,1) and the outcome stops depending
 * on where WordPress decides to print its stylesheet.
 *
 * white on blue-950 is 17.00:1; the pink-500 ring lands on the white header
 * behind it at 4.67:1, clear of the 3:1 asked of a focus indicator.
 * ----------------------------------------------------------------------- */
body .skip-link.screen-reader-text:focus {
	top: var(--wp--preset--spacing--20);
	left: var(--wp--preset--spacing--20);
	padding: 0.9rem 1.25rem;
	border-radius: var(--wp--custom--radius--button);
	background-color: var(--wp--preset--color--blue-950);
	color: var(--wp--preset--color--white);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 700;
	line-height: 1;
	text-decoration: none;
	outline: 2px solid var(--wp--preset--color--pink-500);
	outline-offset: 2px;
}

/* --------------------------------------------------------------------------
 * Links
 *
 * No underlines anywhere, in any state.
 *
 * That leaves colour as the only thing separating an inline link from the copy
 * around it, and the palette does not have the 3:1 separation WCAG 1.4.1 asks
 * for — pink-700 against stone-900 is 2.44:1, and on the brand surface a white
 * link on white text is 1.00:1. So prose links carry weight as a non-colour
 * cue. Navigation, footer and card links do not need it: they sit in their own
 * blocks rather than mid-sentence, so there is no body copy to be confused with.
 * ----------------------------------------------------------------------- */
:where(a):not(.wp-element-button) {
	text-decoration: none;
}

.wp-block-post-content :where(p, li, td) a:not(.wp-element-button),
.wp-block-post-content :where(p, li, td) a:not(.wp-element-button):hover {
	font-weight: 700;
}

/* --------------------------------------------------------------------------
 * Section content width
 *
 * Sections are full-bleed for their background colour, but their content sits
 * in a column capped at the wide size and centred — the same column the header
 * and footer use. Without this, section content is viewport-width minus the
 * fixed gutter, so it matches the header at 1440 by coincidence and grows
 * wider than it on any larger screen.
 *
 * Text is left-aligned within that column, which is what the comps show.
 * Centring is opt-in per section with .tiay-center, for the stat and facts
 * bands, jump links, funder notes and a few editorial moments.
 *
 * This redefines the custom property core's own layout rule already reads,
 * rather than declaring a competing max-width.
 *
 * It used to do the latter, at `[class*="is-style-section-"].is-layout-
 * constrained > :where(...)`. That is specificity (0,2,0) against core's
 * (0,1,0), so it beat not only core's default but also the per-block rule core
 * emits when an editor sets a width in the sidebar — silently. The control
 * moved, the markup updated, the page did not change. Sections were stuck at
 * the wide size, and switching a section to the Default style was the only way
 * to get the control back, which then dropped the content to the narrow measure
 * with the card grid still wide beside it.
 *
 * Core's rule is `max-width: var(--wp--style--global--content-size)`. Setting
 * that property on the section makes core's own rule resolve to the wide size,
 * so the default is unchanged — and a block that sets its own width still emits
 * a literal max-width at equal specificity but later in the cascade, which now
 * wins, as it should. The margin rule is gone with it: core already sets
 * `margin: auto !important` in the same rule this now feeds.
 *
 * Fourth time this shape of bug has been found in this file. A rule that
 * plainly exists and has no effect is nearly always specificity or emission
 * order — and the fix is usually to feed core's rule rather than outrank it.
 *
 * The second selector is why a band does not have to be styled to be laid out.
 * What makes a section need the wide column is being FULL-BLEED, not having a
 * background colour — a full-width group whose content sits at the 720px prose
 * measure in a 1600px viewport looks broken whether or not it is coloured in.
 * Keying only off the style variation meant picking "Default" on a section
 * dropped its heading and buttons to 720 while the card grid beside them stayed
 * at 1280, because a Query Loop carries alignwide and takes a different path.
 *
 * A group that is NOT full-bleed keeps the prose measure, which is the whole
 * point of contentSize: an article body stays at 720 and is not touched here.
 * ----------------------------------------------------------------------- */
[class*="is-style-section-"],
.wp-block-group.alignfull.is-layout-constrained {
	--wp--style--global--content-size: var(--wp--style--global--wide-size);
}

/* The Cover block's inner container is a flow layout, so it takes the full
   padded width rather than the shared column. Without this the hero starts at
   the gutter while everything else starts at the column edge — 180px adrift at
   1800px wide. */
.tiay-hero > .wp-block-cover__inner-container {
	inline-size: 100%;
	max-width: var(--wp--style--global--wide-size);
	margin-inline: auto;
}

/* --------------------------------------------------------------------------
 * The Fair Exchange Rate figure in the footer band
 *
 * The band is a space-between flex row that already wraps: the text block on
 * the left, the PDF button on the right. The figure is a third child, and where
 * it sits is a decision about what "centred" is allowed to mean.
 *
 * BY DEFAULT IT TAKES ITS OWN ROW. flex-basis:100% forces a line break before
 * it, so it spans the band and its centred text is centred in the band exactly.
 * That is the only arrangement that is truly centred at every width.
 *
 * Inline between the two only above 1100px, where there is room for all three.
 * Two things were measured before settling on that:
 *
 *   1280   inline works, but the figure lands 7px left of the band's centre.
 *          space-between gives the middle item the space LEFT OVER, so it is
 *          centred between its neighbours rather than in the band, and the
 *          error is half their difference: (196 - 183) / 2 = 6.5. Invisible.
 *
 *    768   inline fails. The band wraps to [text][figure] / [button] and the
 *          figure centres in the right-hand remainder — 99px off, and visibly
 *          not centred. This is the case the breakpoint exists for.
 *
 * 1100px is not a new number: it is one of the five widths this theme's buttons
 * are already verified at (375 / 768 / 1100 / 1440 / 1920).
 *
 * min-inline-size:0 because a flex item's default min-width is auto, which
 * refuses to shrink below its content — without it the figure pushes the button
 * off the row before the wrap point is reached.
 * ----------------------------------------------------------------------- */
.tiay-footer__resource > .tiay-footer__rate-block {
	flex: 1 1 100%;
	min-inline-size: 0;
}

.tiay-footer__rate,
.tiay-footer__rate-source {
	margin-block: 0;
}

/* Tabular figures so the digits sit on a consistent grid. This is a number
   that changes monthly and is read as data, not as prose. */
.tiay-footer__rate {
	font-variant-numeric: tabular-nums;
}

/* The Bank of Canada link sits INSIDE a sentence, and colour alone is not enough
   to mark it. WCAG 1.4.1 is Level A, and axe-core flags this as `serious`.

   MEASURED on the live footer: the link is pink-700 rgb(157,43,92), the sentence
   around it is stone-700 rgb(68,64,60), and the two differ by only 1.44:1. The
   accepted threshold for colour as the sole cue is 3:1, so this misses by a wide
   margin — and for anyone who cannot separate those hues there is no cue at all,
   since the link carried no underline, no border and no weight change.

   Underline rather than a heavier weight or a darker pink: a weight change is
   itself easy to miss at x-small, and any colour answer just moves the same
   problem. This is the one cue that does not depend on seeing colour.

   Note this is a link in a BLOCK OF TEXT. Standalone links elsewhere in the
   footer are exempt from the rule — their position and grouping do the work —
   which is why this is scoped to the source line rather than applied to footer
   links generally.

   Introduced 21 Aug 2026 with the Fair Exchange Rate strip, after the 20 Aug
   axe-core run, which is why a previously clean site had 36 violations.

   `.tiay-footer` is repeated in the selector on purpose. `.tiay-footer a` further
   down this file sets `text-decoration: none`, and at one class plus one element
   the two selectors have IDENTICAL specificity — so the later rule simply won and
   the underline never appeared. The first attempt at this fix looked correct in
   the file and changed nothing on the page. Two classes settles it regardless of
   which rule moves where later. */
.tiay-footer .tiay-footer__rate-source a {
	text-decoration: underline;
	text-underline-offset: 0.15em;
}

/* The source is stone-700, not the stone-500 a footnote would normally take:
   stone-500 on this blue-50 band is 4.41:1, which misses AA for normal text by
   a hair. stone-700 is 9.45:1 and matches the "Updated" line it sits opposite. */

@media (min-width: 1100px) {
	.tiay-footer__resource > .tiay-footer__rate-block {
		flex-basis: auto;
	}
}

/* On a phone the figure was the only thing in the band not flush left. The text
   block and the button both start at the padding edge; the figure centred inside
   its own full-width row, so it read as misaligned rather than as centred.
   Beating core's .has-text-align-center needs two classes, which is what the
   descendant selector buys. 781px is the theme's existing mobile breakpoint,
   the same one the root padding switches at. */
@media (max-width: 781px) {
	.tiay-footer__rate-block .tiay-footer__rate,
	.tiay-footer__rate-block .tiay-footer__rate-source {
		text-align: start;
	}
}

/* --------------------------------------------------------------------------
 * Hero background video, and the control that makes it permissible
 *
 * The video element itself is core's; everything here is about the toggle.
 *
 * WCAG 2.2.2 Pause, Stop, Hide is LEVEL A: automatically-moving content that
 * runs past five seconds and sits beside other content needs a way to stop it.
 * So this control is not decoration and must not be styled as though it were —
 * it needs a real target size, a visible focus ring, and enough contrast
 * against footage whose brightness changes frame to frame.
 *
 * Placed bottom-right, inside the hero's positioning context. Bottom-LEFT would
 * collide with the hero copy, which is left-aligned at every breakpoint.
 * ----------------------------------------------------------------------- */
.tiay-hero__video-toggle {
	position: absolute;
	inset-block-end: var(--wp--preset--spacing--30);
	inset-inline-end: var(--wp--preset--spacing--30);
	z-index: 2;

	/* 44px, the floor this site holds everything else to. The icon inside is
	   much smaller; the target is not. */
	inline-size: 44px;
	block-size: 44px;

	display: flex;
	align-items: center;
	justify-content: center;

	/* Not a token colour. The button sits on moving footage, so it cannot rely
	   on the section's background the way every other control here can — it
	   carries its own scrim and gets its contrast from that rather than from
	   whatever frame happens to be underneath. */
	background-color: rgba(0, 31, 46, 0.72);
	border: 1px solid rgba(255, 255, 255, 0.6);
	border-radius: 100px;
	color: #fff;
	cursor: pointer;
	padding: 0;
}

.tiay-hero__video-toggle:hover {
	background-color: rgba(0, 31, 46, 0.9);
	border-color: #fff;
}

.tiay-hero__video-toggle:focus-visible {
	outline: 2px solid #fff;
	outline-offset: 2px;
}

/* Pause and play drawn in CSS rather than shipped as an icon: two shapes, no
   request, and they inherit currentColor so the focus and hover states need no
   second asset. */
.tiay-hero__video-toggle-icon {
	display: block;
	inline-size: 14px;
	block-size: 14px;
	background-color: currentColor;
}

.tiay-hero__video-toggle[data-state="playing"] .tiay-hero__video-toggle-icon {
	/* Two bars. */
	clip-path: polygon(0 0, 38% 0, 38% 100%, 0 100%, 0 0, 62% 0, 100% 0, 100% 100%, 62% 100%, 62% 0);
}

.tiay-hero__video-toggle[data-state="paused"] .tiay-hero__video-toggle-icon {
	/* A triangle. */
	clip-path: polygon(6% 0, 100% 50%, 6% 100%);
}

/* The element ships with `hidden` and JavaScript reveals it once the video is
   genuinely playing. display:flex above would otherwise beat the UA's
   [hidden]{display:none}, and the control would appear over a still poster. */
.tiay-hero__video-toggle[hidden] {
	display: none;
}

/* A video that never loads leaves the poster showing, which is the intended
   fallback rather than a degraded one — hero-video.js declines to load on
   reduced-motion, narrow viewports and saveData. object-fit keeps the poster
   framed the same way the video would be. */
.tiay-hero video.wp-block-cover__video-background {
	object-fit: cover;
}

/* --------------------------------------------------------------------------
 * Section stacking
 *
 * Full-bleed sections carry their own background and their own vertical
 * padding, so they are meant to butt directly against each other. The root
 * block gap puts 24px between every top-level block, which on a coloured
 * section reads as a stripe of page background between bands.
 * ----------------------------------------------------------------------- */
.wp-block-post-content > .alignfull,
main.wp-block-group > .alignfull {
	margin-block-start: 0;
}

/* Same block gap applies between the header, main and footer, putting a stripe
   of page background under the header and above the footer. Each of the three
   carries its own padding and border, so they butt together too. */
.wp-site-blocks > * {
	margin-block-start: 0;
}

.tiay-center {
	text-align: center;
}

.tiay-center .wp-block-buttons {
	justify-content: center;
}

/* text-align does not reach flex rows, so an attribution row inside a centred
   card stayed left while the quote above it centred. */
.tiay-center .tiay-card .is-layout-flex {
	justify-content: center;
}

/* --------------------------------------------------------------------------
 * Card grids
 * Grid stretches every cell to the tallest row. Without this, card text
 * vertically centres inside the stretched cell. Text stays top-anchored; a
 * trailing link can still be pushed to the bottom with margin-block-start:auto.
 * ----------------------------------------------------------------------- */
.wp-block-group.is-layout-grid > .wp-block-group,
.wp-block-post-template.is-layout-grid > li {
	align-content: start;
}

/* ...but only where the cross axis is the block axis. WordPress gives every
   flex layout flex-wrap: wrap, which keeps align-content live, and on a COLUMN
   flex card the cross axis is horizontal — so `start` packs the flex line to
   the left rather than to the top. That line is only as wide as its widest
   child, so align-items: center then centres the avatar and the text block
   inside the narrow line instead of inside the card. Board cards sat 28px left
   of centre at 1280 while their text, carrying has-text-align-center, still
   read as centred, which is what made it look like a text-alignment problem.

   Nine of the eleven board cards were affected. The other two happened to hold
   a child wide enough to fill the card, so the row looked ragged rather than
   uniformly shifted.

   Opting out costs no top-anchoring: on a column flex container that comes
   from justify-content, not from align-content. Measured before and after —
   every card top and every avatar top stays where it was.

   Scoped to is-content-justification-center deliberately. 181 of the 183
   elements the rule above matches are vertical, so excluding all of them would
   retire the rule outright. The left- and stretch-justified ones measure
   identically with and without it, but they are left alone regardless: nothing
   is asking them to centre. Only a card that has explicitly asked to be
   centred is being contradicted. */
.wp-block-group.is-layout-grid
	> .wp-block-group.is-vertical.is-content-justification-center {
	align-content: normal;
}

/* No block-size: 100% here. On a grid item that percentage resolves against an
   indefinite track height, so the card stops contributing its real height to
   track sizing and overflows into the row below. Grid and flex items already
   stretch by default, which gives equal-height cards without the side effect. */
.tiay-card {
	border-radius: var(--wp--custom--radius--card);
}

/* A card with its own light background sitting on a dark or brand section
   inherits that section's white text, which renders it invisible — white on
   white. Restore ink colours inside any card that sets its own background.
   Elements carrying an explicit colour class (muted captions, coloured
   eyebrows) are left alone, so intentional colour still wins. */
[class*="is-style-section-"] .tiay-card[class*="-background-color"] {
	color: var(--wp--preset--color--stone-900);
}

[class*="is-style-section-"]
	.tiay-card[class*="-background-color"]
	:is(p, li, strong, em):not([class*="-color"]) {
	color: var(--wp--preset--color--stone-900);
}

[class*="is-style-section-"]
	.tiay-card[class*="-background-color"]
	:is(h1, h2, h3, h4, h5, h6):not([class*="-color"]) {
	color: var(--wp--preset--color--blue-950);
}

[class*="is-style-section-"]
	.tiay-card[class*="-background-color"]
	a:not(.wp-element-button) {
	color: var(--wp--preset--color--pink-700);
}

/* ...unless the card's own background is dark, in which case pink-700 is the
   wrong ink entirely.

   The rules above are written for a LIGHT card on a dark or brand section —
   their comment says so. A dark card on a dark section is the case they do not
   cover, and the Boost Your Business streams are exactly that: blue-800 cards
   carrying inline links. pink-700 on blue-800 measures 1.70:1, against the
   4.5:1 WCAG 1.4.3 asks for. Not marginal — effectively unreadable.

   pink-700 fails on twelve of the palette's eighteen backgrounds, so this is
   not a quirk of one colour:

       blue-200 4.38   blue-300 2.51   blue-400 1.47   blue-600 1.20
       blue-800 1.70   blue-950 2.37   pink-300 3.62   pink-500 1.53
       pink-700 1.00   stone-500 1.49  stone-700 1.44  stone-900 2.44

   White is the answer for the genuinely dark ones — 12.16:1 on blue-800, 17:1
   on blue-950 — and it is already how this theme colours a link on its other
   dark surface, the pink-500 brand band.

   1.4.1 Use of Colour is satisfied the same way it is everywhere else here:
   these links are 700 weight against 400 body copy, which is the non-colour cue
   this theme uses in place of underlines. White also happens to separate from
   the blue-200 body text the card uses, which colour alone did not.

   NOT SOLVED, and worth knowing before someone reaches for one: the mid-tone
   backgrounds. On blue-200, blue-300 and pink-300 neither pink-700 nor white
   clears 4.5:1 — white is 1.63, 2.86 and 1.98. A card on one of those needs a
   colour that is not in the palette yet, so it is a design decision rather than
   a rule. None are in use today. */
[class*="is-style-section-"]
	.tiay-card:is(
		.has-blue-400-background-color,
		.has-blue-600-background-color,
		.has-blue-800-background-color,
		.has-blue-950-background-color,
		.has-pink-500-background-color,
		.has-pink-700-background-color,
		.has-stone-700-background-color,
		.has-stone-900-background-color
	)
	a:not(.wp-element-button) {
	color: var(--wp--preset--color--white);
}

/* --------------------------------------------------------------------------
 * Team avatar — initials underneath, optional headshot on top
 *
 * Equal inline and block size with a 50% radius makes it a true circle —
 * padding alone gives a pill, since two-letter initials are wider than they
 * are tall.
 *
 * The initials are the default state and stay in the page content permanently.
 * A headshot is added by dropping a core/image *inside* this group in the
 * editor; the rules below absolutely position it over the initials and crop it
 * to the circle, so no sizing, cropping or alignment work is needed per card.
 * Delete the image again and the initials are revealed — which is also what
 * happens if the file 404s, so a broken photo degrades to a monogram rather
 * than to a broken-image icon.
 *
 * There is deliberately no `overflow: hidden` here. The photo is already round
 * because the img itself carries border-radius, so clipping the group would be
 * redundant — and tiay.css is loaded into the editor canvas by
 * add_editor_style(), where a clipped 100px circle can swallow the block
 * appender you have to click to add the photo in the first place. Redundant
 * clipping that breaks the one workflow this component exists for is a bad
 * trade.
 *
 * Sizes follow the canonical .pen: board avatar 100px with 28px initials
 * (`F8wT3L`), staff avatar 120px with 40px initials (`t5hDai`). The build
 * shipped 44px, which is too small for a face to be legible and was the real
 * blocker on using headshots at all.
 *
 * padding, border-radius and font-size carry !important because each loses
 * otherwise: the first two to the block editor's own spacing and border
 * controls emitted inline, and font-size to core's preset utility class
 * (`.has-small-font-size`), which core itself emits with !important. This is
 * the one place in this file where outranking core is correct — there is no
 * lower-specificity hook to feed.
 * ----------------------------------------------------------------------- */
.tiay-avatar {
	position: relative;
	inline-size: 100px;
	block-size: 100px;
	flex-shrink: 0;
	padding: 0 !important;
	border-radius: 50% !important;
	align-items: center;
	justify-content: center;
}

.tiay-avatar > p {
	font-size: 28px !important;
}

/* The testimonial attribution avatar, which is a different tier again: PL 08
   draws it at 48px with 15px initials (`qw2Ls`). It needs an explicit rule
   because the base above is the board card's 100px — before the board and
   staff sizes were corrected to the comp, the base was 44px and this card was
   quietly riding on it. Sizes that three different patterns share should be
   named, not inherited by coincidence. */
.tiay-avatar.is-xs {
	inline-size: 48px;
	block-size: 48px;
}

.tiay-avatar.is-xs > p {
	font-size: 15px !important;
}

/* Staff cards are single-column and carry a bio, so the comp gives them a
   larger circle than the four-up board grid.
   `is-lg` rather than a BEM `--lg`: this class is written into a block comment
   attribute, and a double hyphen is illegal inside an HTML comment. WordPress
   escapes each hyphen to its JSON unicode form in the attribute on save, so
   hand-written BEM here silently diverges from what the editor would produce
   and churns the diff the first time anyone opens the page. `is-` also matches
   the convention core already uses around it. */
.tiay-avatar.is-lg {
	inline-size: 120px;
	block-size: 120px;
}

.tiay-avatar.is-lg > p {
	font-size: 40px !important;
}

/* The headshot layer. `inset: 0` fills the circle regardless of the image's
   own aspect ratio; object-fit crops rather than distorts. The figure's
   default block margin has to go or the image sits low in the circle. */
.tiay-avatar .wp-block-image {
	position: absolute;
	inset: 0;
	margin: 0;
}

.tiay-avatar .wp-block-image img {
	inline-size: 100%;
	block-size: 100%;
	object-fit: cover;
	border-radius: 50%;
}

/* The staff card puts its circle beside the name rather than above it, so on a
   phone the 120px version leaves about 130px for a name and a job title —
   "Manager, Labour Market Programming" wrapped to four lines. The board cards
   are unaffected: their circle sits above the name and has the full card width
   either side of it. 600px matches the breakpoint already used further down
   this file. */
@media (max-width: 600px) {
	.tiay-avatar.is-lg {
		inline-size: 84px;
		block-size: 84px;
	}

	.tiay-avatar.is-lg > p {
		font-size: 28px !important;
	}
}

/* Pushes an element to the foot of a stretched card — testimonial attributions,
   card arrow links — so they line up across a row regardless of how much copy
   sits above them.
   The block layout stylesheet sets margin-block-start on every flex child and
   is emitted after this file, so this needs both the extra specificity and the
   !important to land. */
.tiay-card > .tiay-card__spacer {
	margin-block-start: auto !important;
}

/* --------------------------------------------------------------------------
 * Why every button carries a border
 *
 * theme.json gives `elements.button` a 1px solid transparent border, and the
 * outline variations change nothing but its colour. So the solid and the
 * outline button are the same construction — same padding, same border box —
 * and the only difference between them is which colours are painted. There is
 * no arithmetic keeping them equal and so nothing to keep in sync: change the
 * padding once and both move together.
 *
 * The obvious alternative is to compensate — leave the solid button unbordered
 * and pad the outline 1px tighter to make room for its border. That lands on
 * the same pixels today, but the equality is implicit: nothing enforces it, and
 * one edit to the solid button's padding breaks it silently. Do not go back to
 * it.
 *
 * The border is 1px rather than 2px because of what it sits on. Measured
 * against the hero scrim (#001F2E) a white edge is 17:1 where the primary's
 * pink-500 fill is 3.64:1 — the secondary's boundary was drawn at nearly five
 * times the contrast of the primary's, so it bloomed and read as the larger,
 * louder button even at identical height. Halving the ink halves the bloom
 * without costing legibility: white stays white, and 1.4.11 sets no minimum
 * border thickness.
 *
 * A transparent border also earns its keep in forced-colors mode, where it is
 * painted in a system colour and gives the solid button a boundary it would
 * otherwise lack.
 * ----------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
 * Outline button interactive states
 *
 * The outline variations declare :hover, :focus and :active in their own JSON,
 * and WordPress silently drops them — a block style variation for core/button
 * emits base styles only. What is left is theme.json's global button hover,
 * which the variation then beats anyway: its base `background-color:
 * transparent` is emitted in block-style-variation-styles-inline-css, after
 * global-styles, at equal specificity. So the hover background never paints and
 * the button looks inert.
 *
 * Third time this shape of bug has appeared here — the invisible focus ring and
 * the overlay submenus were the same story. When a rule that plainly exists has
 * no effect, compare specificity AND emission order before rewriting it.
 *
 * These sit above the surface safeguard below on purpose: that block overrides
 * outline-light on dark and brand sections at the same specificity, and needs
 * to win on source order.
 * ----------------------------------------------------------------------- */
[class*="is-style-outline-dark"] .wp-block-button__link:hover,
[class*="is-style-outline-dark"] .wp-block-button__link:focus-visible {
	background-color: var(--wp--preset--color--white);
	color: var(--wp--preset--color--blue-950);
}

[class*="is-style-outline-light"] .wp-block-button__link:hover,
[class*="is-style-outline-light"] .wp-block-button__link:focus-visible {
	background-color: var(--wp--preset--color--pink-700);
	color: var(--wp--preset--color--white);
}

/* --------------------------------------------------------------------------
 * Outline button safeguard
 *
 * The light outline style is pink-700 on transparent, which is designed for
 * white, tint and linen surfaces. Dropped on a dark or brand section it becomes
 * pink-700 on blue-950 — around 1.5:1, effectively unreadable. Patterns can be
 * placed on any surface by an editor, so flip it rather than rely on everyone
 * remembering to pick the right variant.
 * ----------------------------------------------------------------------- */
[class*="is-style-section-dark"] .is-style-outline-light .wp-block-button__link,
[class*="is-style-section-brand"] .is-style-outline-light .wp-block-button__link {
	color: var(--wp--preset--color--white);
	border-color: var(--wp--preset--color--white);
}

[class*="is-style-section-dark"] .is-style-outline-light .wp-block-button__link:hover,
[class*="is-style-section-dark"] .is-style-outline-light .wp-block-button__link:focus-visible,
[class*="is-style-section-brand"] .is-style-outline-light .wp-block-button__link:hover,
[class*="is-style-section-brand"] .is-style-outline-light .wp-block-button__link:focus-visible {
	background-color: var(--wp--preset--color--white);
	color: var(--wp--preset--color--blue-950);
}

/* --------------------------------------------------------------------------
 * Muted text safeguard
 *
 * Same shape as the outline button above, and found the same way — by measuring
 * rather than by reading the palette. stone-500 is the theme's muted text: the
 * caption colour in the light section styles, and the colour the document-list
 * pattern gives its "· PDF, 0.0 MB" metadata line.
 *
 * It is safe on exactly one of the three light surfaces:
 *
 *   white   #FFFFFF   4.80:1   passes, but only by 0.30
 *   linen   #F5F1EC   4.27:1   FAILS 1.4.3
 *   tint    #EEF7FA   4.41:1   FAILS 1.4.3
 *
 * AA wants 4.5:1 for normal text, and document-list sets its metadata at small
 * (14px/400), so the large-text allowance does not apply. The caption binding is
 * fixed at source in styles/sections/section-linen.json and section-tint.json.
 * This block covers the other half: a pattern that carries stone-500 as an
 * explicit block colour, which a section style cannot reach, dropped by an
 * editor onto a surface where it does not hold.
 *
 * stone-700 rather than a new stone-600, because the palette has no 600 and
 * adding one to buy a smaller visual step would put a second muted grey in the
 * system for every future editor to choose wrongly between.
 *
 * !important is not a shortcut here, it is the only thing that works. Core
 * writes its preset colour classes as
 *
 *   .has-stone-500-color { color: var(--wp--preset--color--stone-500) !important }
 *
 * so no amount of specificity beats it. Verified: without this the rule loses
 * and the text stays at 4.27:1.
 * ----------------------------------------------------------------------- */
[class*="is-style-section-linen"] .has-stone-500-color,
[class*="is-style-section-tint"] .has-stone-500-color {
	color: var(--wp--preset--color--stone-700) !important;
}

/* --------------------------------------------------------------------------
 * Header
 * ----------------------------------------------------------------------- */
.tiay-header__logo img {
	display: block;
	block-size: auto;
}

.tiay-header .wp-block-navigation {
	font-weight: 600;
}

.tiay-header .wp-block-navigation .wp-block-navigation-item__content {
	text-decoration: none;
}

.tiay-header .wp-block-navigation .wp-block-navigation-item__content:hover {
	color: var(--wp--preset--color--pink-700);
	text-decoration: none;
}

/* --------------------------------------------------------------------------
 * Header search
 *
 * The core search block in button-only mode expands its field inline, which
 * widens the header row and forces the nav to wrap the moment it opens. The
 * field is lifted out of flow and dropped below the header instead, so opening
 * it never moves anything.
 * ----------------------------------------------------------------------- */
.tiay-header {
	position: relative;
}

.tiay-header__search .wp-block-search__button {
	background: transparent;
	border: 0;
	color: var(--wp--preset--color--blue-950);
	padding: 0.5rem;
}

.tiay-header__search .wp-block-search__inside-wrapper {
	position: static;
}

/* Scoped to the OPEN state, and that scoping is load-bearing.
 *
 * This decoration used to apply in both states, which meant the field kept its
 * 26rem width when collapsed and had to be hidden outright — the rule below
 * used to be `display: none`. That silently broke the search for anyone not
 * using a mouse.
 *
 * Core expands the field and then calls .focus() on it, in that order, in the
 * same handler:
 *
 *     ctx.isSearchInputVisible = true;
 *     ref.parentElement.querySelector( 'input' ).focus();
 *
 * The class change is applied on the next render, so at the moment .focus()
 * runs the element still carries the collapsed styling. Core's own collapse is
 * `width: 0` — zero-width but rendered, so focus lands. `display: none` is not
 * focusable, so the call did nothing: the field opened and focus stayed on the
 * button, which by then had relabelled itself "Submit Search". A keyboard user
 * had to Shift+Tab back to the field they had just asked for, with nothing
 * announcing it had appeared.
 *
 * Leaving the collapsed state to core keeps the element rendered and the focus
 * call working. Nothing here needs to hide it: core zeroes the width, the
 * inline paddings and the side borders with !important, inside a wrapper it
 * sets to overflow: hidden.
 * ----------------------------------------------------------------------- */
.tiay-header__search:not(.wp-block-search__searchfield-hidden) .wp-block-search__input {
	position: absolute;
	inset-block-start: calc(100% + 0.5rem);
	inset-inline-end: 0;
	z-index: 30;
	inline-size: min(26rem, calc(100vw - 3rem));
	max-inline-size: none;
	padding: 0.85rem 1.15rem;
	border: 1px solid var(--wp--preset--color--stone-300);
	border-radius: var(--wp--custom--radius--pill);
	background-color: var(--wp--preset--color--white);
	box-shadow: 0 14px 34px rgb(0 31 46 / 16%);
}

/* The contact link sits in a paragraph, so its inline-flex anchor was baseline
   aligned inside the line box and rode 3.8px above the search icon. Making the
   paragraph a flex container and zeroing its line box centres the two. */
.tiay-header__contact {
	display: flex;
	align-items: center;
	margin-block: 0;
	line-height: 0;
}

.tiay-header__contact a {
	display: flex;
	align-items: center;
	justify-content: center;
	inline-size: 40px;
	block-size: 40px;
	color: var(--wp--preset--color--blue-950);
	text-decoration: none;
}

.tiay-header__contact svg,
.tiay-header__search .wp-block-search__button svg {
	display: block;
	inline-size: 24px;
	block-size: 24px;
}

/* Phosphor draws to the edge of its 256 viewBox — 81% of the box — where core's
   search glyph is 14.6 units inside a 24 box, 61%. At a matching box size the
   icon would read a third larger. 18px puts the drawn shape at 14.6px, level
   with the search glyph and with the envelope this replaced, which was drawn at
   15 for the same reason. Both are filled paths with no stroke, so they read as
   one family; that is why Phosphor regular was chosen over a stroked set. */
.tiay-header__contact svg {
	inline-size: 18px;
	block-size: 18px;
}

/* --------------------------------------------------------------------------
 * Header submenus
 * ----------------------------------------------------------------------- */
.tiay-header .wp-block-navigation__submenu-container {
	min-inline-size: 15rem;
	margin-block-start: 0.75rem;
	padding-block: 0.5rem;
	border: 1px solid var(--wp--preset--color--stone-300);
	border-radius: var(--wp--custom--radius--card);
	background-color: var(--wp--preset--color--white);
	box-shadow: 0 14px 34px rgb(0 31 46 / 14%);
}

/* Dropdown text lines up with the parent item's text.
 *
 * Core right-aligns submenus in a right-justified nav, so the panel hung to the
 * left of its parent with the two labels 145px apart. Left-aligning the panel is
 * not enough on its own: the text then sits inset by the panel's 1px border plus
 * the 1rem item padding, so the panel is pulled back by exactly that much and
 * the two labels share an edge.
 *
 * Core's rule is `.wp-block-navigation.items-justified-right
 * .wp-block-navigation__container .has-child .wp-block-navigation__submenu-container`
 * — four classes. This has to carry at least as many to win, which is why the
 * justification class is repeated here rather than reaching for !important. */
.tiay-header .wp-block-navigation.items-justified-right
	.wp-block-navigation__container
	.has-child
	.wp-block-navigation__submenu-container {
	inset-inline-start: calc(-1rem + 1px);
	inset-inline-end: auto;
}

/* The offset above opens a dead strip between the nav item and its dropdown;
   crossing it with the mouse would close the menu, because core closes on the
   list item's pointerleave and an absolutely positioned panel does not extend
   its box. This bridges the gap so the pointer never leaves the item.
   The extra 4px deliberately overlaps into the item rather than abutting it: an
   exactly-abutting bridge can leave a sub-pixel sliver at fractional device
   pixel ratios, and a slowly moving pointer is precisely what lands in it. */
.tiay-header .wp-block-navigation__submenu-container::before {
	content: "";
	position: absolute;
	inset-inline: 0;
	inset-block-end: 100%;
	block-size: calc(0.75rem + 4px);
}

.tiay-header .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
	padding-block: 0.5rem;
	padding-inline: 1rem;
	font-weight: 500;
}

.tiay-header
	.wp-block-navigation__submenu-container
	.wp-block-navigation-item__content:hover {
	color: var(--wp--preset--color--pink-700);
	text-decoration: none;
}

/* The submenu chevrons render at 8.4px square with no padding, which is a poor
   pointer target however well it scores. MEASURED in the browser at 1280px:
   8.4 x 8.4, 4px from its own parent link, and as little as 10px from the next
   nav item.

   It is not a WCAG 2.5.8 failure. That criterion allows an undersized target
   when a 24px circle centred on it clears every neighbouring target's circle,
   and these sit 34-50px apart centre to centre, so they pass on the spacing
   exception. This is about the hand, not the audit: 8px is small enough to miss.

   The hit area is expanded with a pseudo-element rather than padding, because
   the button already carries `margin-left: 3.5px` and is `box-sizing:
   border-box` with no explicit width. Padding would grow the box and shift the
   row; an absolutely positioned ::after cannot affect layout at all, so nothing
   moves by a pixel.

   -8px on every side. MEASURED result by probing elementFromPoint outward from
   the centre: the effective target goes from 8.4 x 8.4 to 20 x 25, roughly a
   sevenfold increase in area, 71px2 to 500px2.

   Not the full 24 wide, and that is deliberate. The left edge caps at 7px out
   because the parent link's own label span wins the paint order below x=376.
   Forcing past it would need a z-index that puts this button on top of a real
   navigation link, and buying the last 4px on the right instead would overlap
   the NEXT nav item, which has only 10px of clearance on Insights, News and
   Events. Overlapping a neighbouring target to satisfy a target-size number
   makes the bar worse, not better. 20 x 25 without touching a neighbour is the
   honest maximum here.

   Safe at mobile without a media query: the overlay's copies are already
   `display: none` further down this file, and a pseudo-element on a
   display:none element renders nothing. Were that rule ever dropped, this would
   need a breakpoint guard, or it would put a 16px invisible target over the
   overlay's top-level links. */
.tiay-header .wp-block-navigation-submenu__toggle {
	position: relative;
}

.tiay-header .wp-block-navigation-submenu__toggle::after {
	content: "";
	position: absolute;
	inset: -8px;
}

/* The CTA label must never break mid-word. Without this it renders as
   "Beco me a mem ber" once the row gets tight. */
.tiay-header__cta .wp-block-button__link {
	white-space: nowrap;
}

/* Collapse the inline nav to the overlay well before core's own breakpoint.
   Seven top-level items carrying submenu chevrons need roughly 1120px next to
   the logo and the utility cluster; below that the row overflowed and pushed
   the whole page into horizontal scroll. The utilities stay visible down to the
   mobile breakpoint, so the CTA is not lost on tablets. */
@media (max-width: 1120px) {
	.tiay-header .wp-block-navigation__responsive-container:not(.is-menu-open) {
		display: none;
	}

	/* The toggle is the only route to navigation once the inline menu collapses,
	   and core draws it as a bare 24px icon — the WCAG 2.2 minimum exactly, with
	   nothing to spare. Grown to a 44px target. The negative margin keeps the
	   icon optically on the content edge rather than pushing the row 10px in.
	   `display` has to stay inside this media query: core hides the button above
	   600px at equal specificity, and this stylesheet is emitted after core's,
	   so an unscoped rule here would win and show it on desktop. */
	.tiay-header .wp-block-navigation__responsive-container-open {
		display: flex;
		align-items: center;
		justify-content: center;
		inline-size: 44px;
		block-size: 44px;
		margin-inline-end: -10px;
	}

	.tiay-header__cta .wp-block-button__link {
		padding-inline: 1rem;
	}

	.tiay-header__right {
		gap: 1rem;
	}
}

.tiay-header__logo {
	flex-shrink: 0;
}

@media (max-width: 781px) {
	/* The 80px gutter is a 1440 measurement. Applied at phone widths it eats
	   160px of a 375px screen, which collapsed the header logo to zero width
	   and pushed the CTA off-screen. Overriding the root padding custom
	   properties fixes the gutter everywhere at once, including the negative
	   margins alignfull sections use to break out of it. */
	body {
		--wp--style--root--padding-right: var(--wp--preset--spacing--30);
		--wp--style--root--padding-left: var(--wp--preset--spacing--30);
	}

	/* The utility cluster is desktop-only — search, contact and the CTA all repeat
	   inside the navigation overlay. The extra .tiay-header is needed to beat
	   the block layout class, which is emitted after this stylesheet. */
	.tiay-header .tiay-header__utilities {
		display: none;
	}

	/* 188px of a 375px screen is most of the header. */
	.tiay-header__logo img {
		width: 132px;
	}

	/* The Cover block writes the 80px gutter as an inline style, so the root
	   padding override above cannot reach it. */
	.tiay-hero {
		padding-inline: var(--wp--preset--spacing--30) !important;
	}

	/* Section vertical rhythm is drawn for 1440; it reads as dead space on a
	   phone. Pull the largest steps back a little. */
	[class*="is-style-section-"] {
		padding-top: var(--wp--preset--spacing--60) !important;
		padding-bottom: var(--wp--preset--spacing--60) !important;
	}
}

/* --------------------------------------------------------------------------
 * Navigation overlay (PL A3)
 * The overlay template part supplies its own surface, so core's default overlay
 * background is suppressed by the disable-default-overlay class WordPress adds.
 * ----------------------------------------------------------------------- */
.tiay-overlay {
	min-block-size: 100vh;
}

.tiay-overlay__nav .wp-block-navigation-item__content {
	font-weight: 800;
	text-decoration: none;
	color: var(--wp--preset--color--blue-950);
}

/* The overlay lists the seven sections only. Expanding every submenu made it a
   26-item scroll on a phone and 34 stops for a keyboard; each section landing
   page carries its own children, so the second level is reachable one tap in.
   `display: none` rather than a visual hide, so the links leave the tab order
   too.
   Two consequences worth keeping together: the disclosure toggle has nothing
   left to disclose and would render as a stray chevron under each parent, and
   the submenu block still carries `submenuVisibility: always`, which is what
   keeps core from positioning these as floating dropdown panels. If the second
   level is ever wanted back as tap-to-expand, changing that attribute alone is
   not enough — core's `open-always` class is what makes the container static,
   and dropping it brings back the absolutely positioned dropdown.

   The `.has-child` in the selector is load-bearing. Core sets `display: flex`
   at `.wp-block-navigation .has-child .wp-block-navigation__submenu-container`,
   three classes; a two-class selector here loses on specificity — not source
   order — and the submenus stay open with nothing to show the rule exists. */
.tiay-overlay__nav .has-child .wp-block-navigation__submenu-container,
.tiay-overlay__nav .wp-block-navigation-submenu__toggle {
	display: none !important;
}

/* --------------------------------------------------------------------------
 * News category filter
 *
 * core/categories renders a <ul> of links. Laid out as a wrapping chip row it
 * reads as a filter without becoming one in code: every chip stays a real link
 * to a real archive, so it works with scripts off and each filtered view keeps
 * its own shareable URL.
 *
 * The active chip is marked twice over — `current-cat` for the eye, and
 * aria-current in the markup for everything else. Colour alone would fail
 * WCAG 1.4.1, so the active state also inverts, which survives greyscale.
 * ----------------------------------------------------------------------- */
.tiay-filter {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.tiay-filter li {
	margin: 0;
}

.tiay-filter a {
	/* 44px minimum, matching every other interactive target on the site — the
	   social icons and the file links are built to the same floor. Centred
	   rather than padded to height so the chip keeps its proportions when the
	   label wraps on a narrow screen. */
	display: flex;
	align-items: center;
	/* border-box, or the padding is added ON TOP of the minimum and a 44px
	   floor renders as a 59px chip. */
	box-sizing: border-box;
	min-block-size: 44px;
	padding: 0.4rem 0.9rem;
	border: 1px solid var(--wp--preset--color--stone-300);
	border-radius: var(--wp--custom--radius--pill, 100px);
	background-color: var(--wp--preset--color--white);
	color: var(--wp--preset--color--blue-950);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 600;
	line-height: 1.4;
	text-decoration: none;
	white-space: nowrap;
}

.tiay-filter a:hover,
.tiay-filter a:focus-visible {
	border-color: var(--wp--preset--color--blue-950);
	text-decoration: none;
}

/* Inverted, not just tinted: the active filter has to survive greyscale. */
.tiay-filter .current-cat > a {
	border-color: var(--wp--preset--color--blue-950);
	background-color: var(--wp--preset--color--blue-950);
	color: var(--wp--preset--color--white);
}

/* The count core appends sits inside the anchor; mute it rather than hide it,
   since "how many are in here" is useful before you commit to the click. */
.tiay-filter a .post-count {
	opacity: 0.6;
}

/* Below the wrap point the strip scrolls sideways instead of stacking.
 *
 * Nine chips are 1126px wide — three viewports at 375px — so wrapping cost
 * 200px of vertical space before the first card. This costs 44px.
 *
 * The affordance is the PEEK, not a gradient: the strip is padded so a chip is
 * visibly cut at the right edge, which reads as "there is more" in a way a fade
 * does not — people read fades as decoration. It is the same strip every news
 * app uses for exactly this, which is most of why it works.
 *
 * The scrollbar is hidden but the strip is not inert: swipe, trackpad and
 * shift-scroll all work, and Tab still reaches every chip because browsers
 * scroll a focused element into view. assets/js/news-filter.js centres the
 * ACTIVE chip on load, which is the one thing scrolling alone cannot do.
 */
@media (max-width: 781px) {
	.tiay-filter {
		flex-wrap: nowrap;
		overflow-x: auto;
		/* Room for the cut-off chip to be visibly cut rather than flush. */
		padding-inline-end: 2.5rem;
		/* Firefox, then WebKit — the bar itself adds nothing here and costs
		   height on a 44px strip. */
		scrollbar-width: none;
		-ms-overflow-style: none;
	}

	.tiay-filter::-webkit-scrollbar {
		display: none;
	}

	/*
	 * No scroll-snap here, deliberately.
	 *
	 * `scroll-snap-align: start` pulled the strip to the nearest chip boundary
	 * and overrode the script's attempt to bring the active chip into view: on
	 * the Industry updates archive it snapped back to the previous chip's edge,
	 * leaving the active one jammed against the right edge with 154px of empty
	 * space to its left. Snapping is polish; showing which filter is applied is
	 * not, and when they conflict the filter wins. Free scrolling reads fine on
	 * a strip of short chips — snapping earns its place on full-width carousels,
	 * not here.
	 */
}

/* --------------------------------------------------------------------------
 * Footer
 * The funder band is borderless and aligned to the content edge — no card, no
 * rule, no centring.
 * ----------------------------------------------------------------------- */
.tiay-footer__top {
	align-items: start;
}

/* The brand column carries the address block, so it needs more room than the
   two link columns. */
.tiay-footer__brand {
	grid-column: span 2;
	max-inline-size: 30rem;
}

@media (max-width: 781px) {
	.tiay-footer__brand {
		grid-column: auto;
	}
}

.tiay-footer__colophon {
	inline-size: 100%;
}

/* The two footer link columns are lists inside `<nav>` — accessibility review,
   finding 9. A screen reader now announces "list, 7 items" instead of seven
   unrelated paragraphs, and the columns show up as named landmarks.

   The markup changed; the design did not. These rules restore exactly what the
   paragraph stack looked like: no marker, no indent, and the same blockGap
   between rows that the flex column was already applying. */
.tiay-footer__links {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--10);
}

/* The social icons sit in the brand column, under the address, phone and email.
   They are a contact channel, so they belong with the other ways to reach TIA
   Yukon rather than beside the copyright.

   36px glyphs with 6px padding give a 48px square tap target, past the 44px
   floor in WCAG 2.5.8 with room to spare.

   This replaces an earlier rule that grew a 16px glyph to a 44px target with
   14px of padding and then pulled the padding back out again with negative
   margins, so the colophon row did not grow. That rule was scoped to
   `.tiay-footer__colophon` and stopped matching the moment the block moved —
   left in place it would have silently collapsed the targets to 36px. At this
   size the padding is small enough not to need cancelling.

   THE PADDING IS NO LONGER SCOPED TO THE FOOTER, for the same reason. A second
   social block went onto the Arctic Collaboration page on 21 August and landed
   at 36px, because `is-style-logos-only` zeroes the padding in core and the 6px
   that fixed it only ever matched inside `.tiay-footer__social`. The tap target
   is an accessibility floor, not a footer detail, so it now applies wherever
   this component is used. Gap and margin stay scoped — those are layout. */
.tiay-footer__social {
	gap: 0.25rem;
}

.tiay-footer__social .wp-block-social-link {
	margin-block: 0;
}

.wp-block-social-links.is-style-logos-only .wp-block-social-link-anchor {
	padding: 6px;
}

.tiay-footer a {
	text-decoration: none;
}

.tiay-footer a:hover {
	text-decoration: underline;
}

.tiay-footer__funder-logo img {
	display: block;
	block-size: auto;
}

/* --------------------------------------------------------------------------
 * Hero
 *
 * Three layers, bottom to top:
 *   1. a solid dark ground on the Cover itself — the fallback when no
 *      background image is set, and what keeps white hero text legible
 *   2. the image, which Cover renders as its own <img> element
 *   3. the scrim, applied to Cover's dim overlay span
 *
 * The ground matters because the scrim is semi-transparent: without it, a hero
 * with no image renders the gradient over nothing and washes out.
 *
 * Cover only paints a background-image onto the overlay span in parallax or
 * repeated mode. These heroes use neither, so the scrim never hides the image.
 * ----------------------------------------------------------------------- */
.tiay-hero {
	background-color: var(--wp--preset--color--blue-950);
}

.tiay-hero .wp-block-cover__background {
	background: var(--wp--custom--gradient--hero-scrim);
	opacity: 1;
}

/* --------------------------------------------------------------------------
 * Post feed
 *
 * The category renders as a chip, borrowing the annotated link card's chip
 * language so tags read the same way everywhere on the site.
 *
 * Colours are surface-aware. The date was previously pinned to stone-500 in the
 * block markup, which is 4.80:1 on white but only 3.54:1 on the dark homepage
 * section — an AA failure. The hardcoded colour is gone; these rules set it per
 * surface instead.
 * ----------------------------------------------------------------------- */
.wp-block-post-terms {
	display: block;
}

.wp-block-post-terms a,
.wp-block-post-terms .wp-block-post-terms__separator + a {
	display: inline-block;
	padding: 0.3rem 0.6rem;
	border-radius: var(--wp--custom--radius--pill);
	background-color: var(--wp--preset--color--pink-100);
	color: var(--wp--preset--color--pink-700);
	font-size: 0.6875rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	line-height: 1;
	text-transform: uppercase;
	text-decoration: none;
}

.wp-block-post-terms a:hover,
.wp-block-post-terms a:focus-visible {
	background-color: var(--wp--preset--color--pink-700);
	color: var(--wp--preset--color--white);
}

/* The separator is redundant once each term is a chip. */
.wp-block-post-terms .wp-block-post-terms__separator {
	font-size: 0;
	margin-inline: 0.25rem;
}

.wp-block-post-date {
	color: var(--wp--preset--color--stone-500);
}

/* The chip goes pink on the dark card. It was blue-200, which read as a second
   cyan next to the date rather than as the brand accent. pink-300 keeps the
   light-chip-on-dark-card structure and only changes the hue: 8.60:1 for the
   text, and 6.15:1 for the pill against the card, so the shape stays defined. */
[class*="is-style-section-dark"] .wp-block-post-terms a {
	background-color: var(--wp--preset--color--pink-300);
	color: var(--wp--preset--color--blue-950);
}

[class*="is-style-section-dark"] .wp-block-post-terms a:hover,
[class*="is-style-section-dark"] .wp-block-post-terms a:focus-visible {
	background-color: var(--wp--preset--color--pink-100);
	color: var(--wp--preset--color--blue-950);
}

[class*="is-style-section-dark"] .wp-block-post-date {
	color: var(--wp--preset--color--blue-200);
}

/* --------------------------------------------------------------------------
 * Post cards
 *
 * The card carries a surface on EVERY section, not only on dark. It used to be
 * a dark-section exception, so on white, tint, linen and brand the cards were
 * bare text in a grid: no surface, no padding, nothing marking where one post
 * ended and the next began.
 *
 * That was a contrast bug as much as a layout one. Text sitting straight on a
 * section inherits that section's colours, and the date stayed pinned at
 * stone-500 wherever it landed — 4.41:1 on tint and 4.27:1 on linen, both under
 * AA, and 1.03:1 on brand, which is pink on pink and the same invisibility the
 * focus ring had. The excerpt inherited white and vanished there too.
 *
 * Giving every card a surface settles the measurement, not just the look. That
 * is the reasoning the annotated link card already records: a card whose
 * background never shifts has contrast that can be checked once. There are two
 * surfaces here rather than the link card's one, because the comp draws a dark
 * card on the dark section and that is worth keeping — so both get checked:
 *
 *   white card   stone-900 ink, date 4.80:1, chip 5.95:1
 *   blue-800     white ink,     date 7.44:1, chip 8.60:1
 * ----------------------------------------------------------------------- */
.wp-block-post-template > li {
	background-color: var(--wp--preset--color--white);
	border: 1px solid var(--wp--preset--color--stone-300);
	border-radius: var(--wp--custom--radius--card);
	overflow: hidden;
	padding-block-end: var(--wp--preset--spacing--30);
	/* The card states its own ink, so a dark or brand section's white text
	   cannot leak in and leave the excerpt white on white. */
	color: var(--wp--preset--color--stone-900);
	transition: border-color 120ms ease, transform 120ms ease;
}

/* The image runs to the card edge; everything else is inset. */
.wp-block-post-template > li > *:not(.wp-block-post-featured-image) {
	padding-inline: var(--wp--preset--spacing--30);
}

.wp-block-post-template > li > .wp-block-post-featured-image {
	margin-block-end: var(--wp--preset--spacing--20);
}

/* No rule here squaring off the image corners.
 *
 * There used to be one, `border-radius: 0`, and it never once applied: the
 * block writes its border radius as an inline style on the img, and inline
 * beats a stylesheet. It read as a guard and was not one. The radius is gone
 * from the block attributes instead — in the three templates, in the feed
 * pattern, and in the two pages that carry their own Query Loop.
 *
 * The card's own overflow:hidden still rounds the top two corners to the card,
 * which is what the comp shows. The bottom two are mid-card and stay square. */

/* A card with no featured image should not start flush against its own edge. */
.wp-block-post-template > li > *:first-child:not(.wp-block-post-featured-image) {
	margin-block-start: var(--wp--preset--spacing--30);
}

/* The comp's dark card. Its border is transparent rather than absent so the
   hover state below has something to colour in without shifting the layout. */
[class*="is-style-section-dark"] .wp-block-post-template > li {
	background-color: var(--wp--preset--color--blue-800);
	border-color: transparent;
	color: var(--wp--preset--color--white);
}

/* --------------------------------------------------------------------------
 * Post cards: whole-card click target
 *
 * The card carried two links to the same post — the featured image and the
 * title — with the same destination and the same accessible name. Screen
 * readers announced each card twice; keyboard users tabbed through it twice.
 *
 * The fix is NOT an anchor wrapped around the card. Two reasons it cannot be:
 * the post-template gives no element to wrap without a render_block filter,
 * and an anchor around the card takes its accessible name from everything
 * inside it — category, title, excerpt and date run together, which is the
 * 241-character name we just finished removing from the link cards. The
 * category chip is also a real link to a different destination, and an anchor
 * cannot contain another anchor.
 *
 * So: the image drops its link (isLink:false in the templates) and the title's
 * anchor stretches a transparent ::after across the card. One link per card,
 * named by the title alone, clickable across the full card face.
 *
 * Trade-off: the overlay sits above the excerpt, so dragging to select that
 * text starts a link drag instead. Accepted — these are teaser cards, and the
 * full text is one click away.
 * ----------------------------------------------------------------------- */
.wp-block-post-template > li {
	position: relative;
}

.wp-block-post-template > li .wp-block-post-title a::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
}

/* The category chip goes to the archive, not the post, so it stays a separate
   link — which means lifting it back above the overlay to stay clickable. */
.wp-block-post-template > li .wp-block-post-terms {
	position: relative;
	z-index: 2;
}

/* Hover moves the card's border, not the title's colour.
 *
 * The first attempt at this shifted the title to pink-700 on light surfaces and
 * blue-200 on dark, which does nothing on either: the title is a link, so it is
 * ALREADY those exact colours at rest — theme.json sets elements.link per
 * section. The rule matched, applied, and changed no pixel. Reading a hover cue
 * off a colour the element already has is a mistake that looks correct in the
 * stylesheet and is invisible in the browser.
 *
 * Now that the card has a border on every surface, the affordance is the one
 * the annotated link card already uses — border to pink-500, a 2px lift — so
 * both card families answer the pointer the same way. It works regardless of
 * what colour the title happens to be. */
.wp-block-post-template > li:hover {
	border-color: var(--wp--preset--color--pink-500);
	transform: translateY(-2px);
}

@media (prefers-reduced-motion: reduce) {
	.wp-block-post-template > li {
		transition: none;
	}

	.wp-block-post-template > li:hover {
		transform: none;
	}
}

/* With the anchor stretched over the card, a ring around the title text alone
   would understate the target. Draw it around the card and suppress the
   title's own. :has() keeps this off the card when the chip is the thing
   focused — that link gets its own ring, from the chip rules above. */
.wp-block-post-template > li:has(.wp-block-post-title a:focus-visible) {
	outline: 2px solid var(--wp--preset--color--pink-500);
	outline-offset: 2px;
	border-radius: var(--wp--custom--radius--card);
}

.wp-block-post-template > li .wp-block-post-title a:focus-visible {
	outline: none;
}

[class*="is-style-section-dark"]
	.wp-block-post-template
	> li:has(.wp-block-post-title a:focus-visible),
[class*="is-style-section-brand"]
	.wp-block-post-template
	> li:has(.wp-block-post-title a:focus-visible) {
	outline-color: var(--wp--preset--color--white);
}

/* --------------------------------------------------------------------------
 * Link posts
 *
 * A news card that points at another site. The arrow matches the annotated
 * link card's convention — ↗ leaves the site, → stays on it — so the two card
 * families read as one system. It is aria-hidden; the accessible cue is the
 * visually hidden "(opens in a new tab)" beside it, added in inc/link-posts.php.
 *
 * The separator before the source is drawn here rather than written into the
 * markup, so a card whose source is empty cannot render a stray middot.
 * ----------------------------------------------------------------------- */
/* A document link says so where the arrow would go.
 *
 * Outlined rather than filled: the filled pill is the category chip's
 * treatment, and two filled pills on one card compete. Muted, because this is
 * a qualifier on the headline, not a label for it.
 *
 * It carries the size when the file is ours to measure — the one fact worth
 * having before clicking on a phone. `white-space: nowrap` because "PDF · 240
 * KB" wrapping mid-marker reads as two separate things. */
/* The document mark sits in the card's date line, after the source:
 *
 *     16 August 2026 · CBC · PDF · 140 KB
 *
 * It began beside the headline as an outlined pill, which was too heavy at
 * x-large and crowded the title. Here it is one more fact on a line that is
 * already small and muted, so it needs no border and no size of its own — it
 * inherits the line's. The separator matches the source's, drawn in CSS so a
 * card with no source does not render a stray middot.
 *
 * Uppercase and tracked to read as a label rather than as more prose, since
 * "PDF" beside a source name would otherwise look like part of it. */
.tiay-doc-marker {
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	white-space: nowrap;
}

.tiay-doc-marker::before {
	content: "·";
	margin-inline: 0.4em;
	font-weight: 400;
	/* Decorative, and read aloud as "middle dot" by some screen readers. */
	speak: never;
}


.tiay-link-post__arrow {
	display: inline-block;
	margin-inline-start: 0.25em;
	/* Nudged against the cap height: the glyph sits high in its em box and
	   reads as floating above the last word without this. */
	transform: translateY(0.06em);
	font-size: 0.8em;
	line-height: 1;
}

.tiay-link-post__source::before {
	content: "·";
	margin-inline: 0.4em;
	/* Decorative, and read aloud as "middle dot" by some screen readers. */
	speak: never;
}

/* --------------------------------------------------------------------------
 * Testimonial scroller
 *
 * Eight member quotes, about three visible, scrolled horizontally. The client
 * supplied eight and the homepage showed three; a carousel keeps the section
 * the height PL 08 draws while putting the other five one gesture away.
 *
 * No JavaScript, and nothing hidden. All eight cards are in the DOM in source
 * order, so a screen reader reads all eight in sequence and there is no
 * "slide 4 of 8" bookkeeping, no live region, and no focus management. That is
 * the whole reason for scroll-snap over a scripted carousel — the accessible
 * version is the default rather than something bolted on, and the build rule
 * against custom blocks (PL 00) holds.
 *
 * The block is a flex group with flexWrap nowrap, which core already emits as
 * `display:flex; flex-wrap:nowrap`. Only the scrolling is added here — feeding
 * core's rule rather than outranking it, per the note in the section-width
 * block above.
 *
 * Card width is the affordance. min(22rem, 78%) shows three across the wide
 * column with the fourth peeking, and one-and-a-bit on a phone, so it is
 * visibly scrollable without an arrow control that would need JavaScript.
 *
 * Keyboard reachability is NOT here — a scroll container has to be focusable
 * for WCAG 2.1.1, and Safari does not do that on its own. tabindex, role and
 * the accessible name come from tiay_quote_scroller_a11y() in functions.php,
 * because core/group drops attributes it does not know about.
 * ----------------------------------------------------------------------- */
.tiay-quote-scroller {
	overflow-x: auto;
	overflow-y: hidden;
	scroll-snap-type: x mandatory;

	/* Full-bleed track, content-aligned first card.
	 *
	 * The block is alignfull so cards run off both edges rather than stopping
	 * at the wide column — that is what makes it read as a track with more in
	 * it, and it is why no arrow control is needed.
	 *
	 * But a naive alignfull would start the first card hard against the
	 * viewport edge, out of line with the heading above it. This padding walks
	 * to where the heading starts: first the root padding, which gets from the
	 * viewport edge to the section's padded area, then half the slack between
	 * that area and the wide column, which is what centres the heading inside
	 * it. Card one lands directly under the "T", and cards still bleed right.
	 *
	 * The first version was max(rootPadding, (100% - wideSize) / 2) and was
	 * only right at about 1440px, by coincidence. A percentage in padding
	 * resolves against the CONTAINING BLOCK, not the element's own width — and
	 * this element is full-bleed while its containing block is the padded
	 * section, 160px narrower. At 1920 that put the card at 240 and the heading
	 * at 320. The two terms are added rather than max()'d for the same reason:
	 * they are consecutive steps, not alternatives.
	 *
	 * scroll-padding matches, or a snapped card would align to the viewport
	 * edge instead of the content column and the whole thing would sit one
	 * gutter out of true after the first swipe. */
	padding-inline: calc(
		var(--wp--style--root--padding-left) +
		max(0px, (100% - var(--wp--style--global--wide-size)) / 2)
	);
	scroll-padding-inline: calc(
		var(--wp--style--root--padding-left) +
		max(0px, (100% - var(--wp--style--global--wide-size)) / 2)
	);

	/* Room for the focus ring, which the theme draws 2px outside the box. */
	padding-block-end: var(--wp--preset--spacing--20);

	/* Stop a trackpad swipe past the last card from chaining to the page and
	   triggering the browser's back gesture. */
	overscroll-behavior-inline: contain;
}

.tiay-quote-scroller > * {
	flex: 0 0 min(22rem, 78%);
	scroll-snap-align: start;
}

/* --------------------------------------------------------------------------
 * Scroller controls
 *
 * Two mutually exclusive treatments, chosen by what the browser can do.
 *
 * Where CSS carousel controls are supported, the track gets real arrow buttons
 * and a row of position dots and the scrollbar is hidden. These are generated
 * by the browser from ::scroll-button() — actual focusable buttons that scroll
 * the track and disable themselves at each end, with no JavaScript, no custom
 * block, and nothing added to the DOM. Verified: clicking the right arrow
 * moves the track 1128px, three cards.
 *
 * There are no position dots, and that is a decision rather than an omission.
 * ::scroll-marker is per item, so eight cards give eight dots — but with three
 * and a bit visible, the last three can never reach the leading edge: the card
 * pitch is 376px and card six would need to scroll to 1880 against a maximum
 * of 1704. Those three dots all resolve to the same end position and appear
 * dead when clicked. Paging dots would need markers grouped per screenful,
 * which the spec does not express, so the honest control set is the arrows,
 * whose disabled states say the same thing truthfully.
 *
 * Everywhere else, the styled scrollbar stays exactly as it was. That fallback
 * is the point of the @supports split rather than a nicety — hiding the
 * scrollbar unconditionally would leave a desktop mouse user in a browser
 * without these pseudo-elements no visible way to move the track at all. The
 * bleeding card says there is more; it does not say how to get there.
 *
 * Support was Chromium-first and could only be confirmed in Chromium from
 * here, so which branch a given visitor gets is genuinely unknown. Both are
 * complete on their own, which is what makes that acceptable.
 *
 * No auto-advance, deliberately. Anything that moves on its own for more than
 * five seconds needs a pause control under WCAG 2.2.2, and a carousel that
 * moves while you are reading a quote is worse than one that waits.
 * ----------------------------------------------------------------------- */
@supports not selector(::scroll-button(right)) {
	.tiay-quote-scroller {
		scrollbar-width: thin;
	}

	.tiay-quote-scroller::-webkit-scrollbar {
		block-size: 8px;
	}

	.tiay-quote-scroller::-webkit-scrollbar-thumb {
		border-radius: 4px;
		background-color: var(--wp--preset--color--blue-200);
	}
}

@supports selector(::scroll-button(right)) {
	.tiay-quote-scroller {
		scrollbar-width: none;
		/* Arrow navigation jumps a card at a time; gliding makes the jump
		   readable as movement rather than a cut. The reduced-motion block
		   below turns this off. */
		scroll-behavior: smooth;
	}

	.tiay-quote-scroller::-webkit-scrollbar {
		display: none;
	}

	/* Left in normal flow, deliberately.
	 *
	 * These were anchor-positioned against the track — first above it beside
	 * the heading, then below it beside the dots. Both floated over content
	 * rather than occupying space, so both collided: on the heading at 375px,
	 * on the cards at 820px, and finally on the cards' bottom edge at every
	 * width, which left them technically clickable and practically not.
	 *
	 * In flow they take their own band between the heading and the track and
	 * cannot overlap anything, at any width, because the track is pushed down
	 * by exactly their height. They land at the content column's left edge —
	 * the track's own padding puts them there — so they line up under the
	 * heading. No anchor positioning, no breakpoint, no tuning.
	 * ----------------------------------------------------------------------- */
	.tiay-quote-scroller::scroll-button(*) {
		inline-size: 44px;
		block-size: 44px;
		margin-block-end: var(--wp--preset--spacing--20);
		border: 1px solid var(--wp--preset--color--blue-100);
		border-radius: 50%;
		background-color: var(--wp--preset--color--white);
		color: var(--wp--preset--color--blue-950);
		font-size: 1.25rem;
		line-height: 1;
		cursor: pointer;
	}

	/* The buttons are laid out against the section's padded box, not the
	   track's own padding box, so they start at the root padding and ignore the
	   inline padding that pushes the cards in to the wide column. At 1440 those
	   happen to be the same 80px and the arrows looked aligned; at 1920 the
	   heading and cards sit at 320 and the arrows stayed at 80. This adds the
	   centring half back, on the first button so the pair moves together. */
	.tiay-quote-scroller::scroll-button(left) {
		margin-inline-start: max(
			0px,
			calc((100% - var(--wp--style--global--wide-size)) / 2)
		);
	}

	.tiay-quote-scroller::scroll-button(right) {
		margin-inline-start: 0.5rem;
	}

	.tiay-quote-scroller::scroll-button(*):disabled {
		opacity: 0.35;
		cursor: default;
	}

	.tiay-quote-scroller::scroll-button(*):hover:not(:disabled) {
		border-color: var(--wp--preset--color--pink-500);
		color: var(--wp--preset--color--pink-700);
	}

	/* The content is the accessible name: the text after the slash is what a
	   screen reader announces, the glyph is what is drawn. */
	.tiay-quote-scroller::scroll-button(left) {
		content: "\2190" / "Previous testimonials";
	}

	.tiay-quote-scroller::scroll-button(right) {
		content: "\2192" / "Next testimonials";
	}
}

/* A snapped scroller and reduced motion do not fight, but the smooth scroll a
   browser applies on keyboard paging does. */
@media (prefers-reduced-motion: reduce) {
	.tiay-quote-scroller {
		scroll-behavior: auto;
	}
}

/* --------------------------------------------------------------------------
 * Testimonial quote mark
 *
 * PL 08 opens each card with a 44px pink-500 double-quote above the quote.
 * That used to be a core/paragraph holding the character with aria-hidden on
 * it — which core/paragraph cannot emit from save(), so the block invalidated
 * the first time an editor opened the card, and the accessibility intent went
 * with it. Drawn here instead: no element, nothing to hide, and one less block
 * for an editor to select by accident and type into.
 *
 * `speak: never` for the same reason as the middot above.
 * ----------------------------------------------------------------------- */
.tiay-quote::before {
	content: "\275D";
	display: block;
	margin-block-end: var(--wp--preset--spacing--20);
	color: var(--wp--preset--color--pink-500);
	font-size: 44px;
	font-weight: 800;
	line-height: 0.8;
	speak: never;
}

/* --------------------------------------------------------------------------
 * Care for the Arctic — icon badges and responsibility cards
 *
 * The 80px circle holding a 44px icon is the "decorative large" tier the icon
 * README names, and Care for the Arctic is the page it names it for. The size
 * lives here rather than in the block markup so the two numbers stay together
 * and an editor cannot drift them apart.
 *
 * The badge and the card icon both inherit currentColor, which is the whole
 * reason these are inline SVG and not PNG: the badge sits on a brand circle and
 * the card icon on white, and one file serves both.
 * ----------------------------------------------------------------------- */
.tiay-icon-badge {
	display: flex;
	align-items: center;
	justify-content: center;
	inline-size: 80px;
	block-size: 80px;
	/* Never let the grid squeeze the circle into an oval. */
	flex: 0 0 auto;
	border-radius: 50%;
	background-color: var(--wp--preset--color--pink-500);
	color: var(--wp--preset--color--white);
}

/* --------------------------------------------------------------------------
 * Feature card icon
 *
 * PL 11 draws a 52px pink circle holding a 24px white icon, and in the comp the
 * circle is layout (`FRFl6`) with the icon a separate object inside it. It is
 * built the same way here: the circle is this figure, the icon is the image.
 *
 * That matters for who can add an icon. A version of this baked the circle into
 * the PNGs, which meant a seventeenth icon had to be composited onto a pink
 * circle at the right size before it could be used — a job for whoever has the
 * toolchain, not for the client. Drawn here, any icon image dropped into the
 * block works, and pink-500 stays a theme.json token that a rebrand propagates
 * to.
 *
 * The figure is the badge rather than a wrapping Group, so the whole thing is
 * one block: click it and Replace, with nothing to select into. Two earlier
 * attempts put the icon in a container the editor could not reach.
 *
 * The filter is what lets any image work. The shipped PNGs are blue-950 rather
 * than white, so their media-library thumbnails are visible — sixteen white
 * icons on transparent are sixteen blank squares in the picker, which is worse
 * than no picker. brightness(0) flattens any colour to black and preserves
 * alpha; invert(1) turns that white. So the file can be whatever is legible in
 * the library and still land white on the badge.
 * ----------------------------------------------------------------------- */
.tiay-feature-icon {
	display: flex;
	align-items: center;
	justify-content: center;
	inline-size: 52px;
	block-size: 52px;
	flex: 0 0 auto;
	margin: 0;
	border-radius: 50%;
	background-color: var(--wp--preset--color--pink-500);
}

.tiay-feature-icon img {
	inline-size: 24px;
	block-size: 24px;
	object-fit: contain;
	filter: brightness(0) invert(1);
}

.tiay-reality .wp-block-heading {
	margin-block-end: 0;
}

/* The framework diagram is a square infographic with type baked into it, so it
 * is capped rather than allowed to fill the wide column — past about 720px the
 * drawing is bigger than it needs to be and the section stops reading as one
 * idea. Centred, because unlike the prose it is a figure, not a column.
 *
 * Centring is done on the figure, not with margin-inline:auto on the image.
 * The auto margin resolved to zero and left the diagram hard against the left
 * edge of a 1280px figure: core's own image rules already govern the img box,
 * and an auto margin cannot centre inside a parent that is not sizing to it.
 *
 * The cap is min(720px, 100%) and BOTH halves are load-bearing. A bare
 * max-inline-size: 720px replaces core's max-width:100% rather than adding to
 * it, so the image stops being bound by its container at all. That was hidden
 * for as long as the block was alignwide, because core gives an aligned image
 * width:100% and the two constraints together came out right. Un-align it and
 * the image renders a flat 720px inside a 375px phone, overflowing the document
 * by 172px -- horizontal scrolling on a page, which is WCAG 1.4.10 Reflow. */
.tiay-framework-diagram {
	display: flex;
	flex-direction: column;
	align-items: center;
}

.tiay-framework-diagram img {
	max-inline-size: min(720px, 100%);
	block-size: auto;
}

.tiay-responsibility__icon {
	display: flex;
	color: var(--wp--preset--color--blue-950);
}

/* The number, the icon and the title are one stack; the comp spaces the number
   away from the icon rather than from the card edge. */
.tiay-responsibility .tiay-eyebrow {
	margin-block-end: var(--wp--preset--spacing--10);
}

/* --------------------------------------------------------------------------
 * Jump links — "On this page"
 *
 * Sampled from the Who's Who artboard (hjJgT / fbwgn), which draws these as
 * pills rather than the plain text links the build had:
 *
 *   band     blue-50      label   blue-950 on white, 17.00:1
 *   pill     white        arrow   pink-500 on white, 4.67:1
 *   border   blue-200     eyebrow blue-600 on blue-50, 7.87:1
 *
 * One deliberate departure. The comp's blue-200 border is 1.50:1 against the
 * blue-50 band, and the white pill is barely lighter than the band it sits on,
 * so at low vision the pills dissolve and the row reads as loose text. The
 * border is blue-400 here, 4.47:1, clearing the 3:1 WCAG 1.4.11 asks of the
 * boundary that identifies a control.
 *
 * blue-300 was the obvious smaller step and does not work: 2.63:1, still under
 * the floor. Two steps darker than the comp is more than I would like, but the
 * palette has nothing between, and a boundary that cannot be seen is not a
 * boundary.
 *
 * The list is unstyled back to a row: it exists for structure, not for bullets.
 * ----------------------------------------------------------------------- */
.tiay-jump__links {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--20);
	margin: 0;
	padding: 0;
	list-style: none;
}

.tiay-jump__links li {
	margin: 0;
}

.tiay-jump__links a {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.6rem 1.1rem;
	border: 1px solid var(--wp--preset--color--blue-400);
	border-radius: var(--wp--custom--radius--pill);
	background-color: var(--wp--preset--color--white);
	color: var(--wp--preset--color--blue-950);
	font-size: var(--wp--preset--font-size--small);
	text-decoration: none;
	transition: border-color 120ms ease, background-color 120ms ease;
}

/* Decorative: the link text already says where it goes, and "downwards arrow"
   read aloud after every label is noise. Drawn in CSS so an editor rewriting a
   label cannot delete it, and so it never lands inside the link's name. */
.tiay-jump__links a::after {
	content: "\2193";
	color: var(--wp--preset--color--pink-500);
	font-size: 1.1em;
	line-height: 1;
	speak: never;
}

.tiay-jump__links a:hover,
.tiay-jump__links a:focus-visible {
	border-color: var(--wp--preset--color--pink-500);
	background-color: var(--wp--preset--color--pink-50);
}

/* The eyebrow is the row's label, so it sits on the band rather than in a pill
   and takes the comp's blue-600 instead of the sitewide eyebrow pink. */
.tiay-jump__label {
	margin-block: 0;
	color: var(--wp--preset--color--blue-600);
}

/* On a narrow screen the row becomes a column, and a pill that stretches to
   the full width stops reading as a pill. */
@media (max-width: 600px) {
	.tiay-jump__links {
		gap: 0.5rem;
	}

	.tiay-jump__links a {
		width: auto;
	}
}

/* --------------------------------------------------------------------------
 * Program facts band (PL 15)
 *
 * A row of facts distributed across the content column, each one left-aligned
 * in its own 260px measure. The comp's alignItems:center is cross-axis on a
 * horizontal row — it centres the facts vertically against each other, it does
 * not centre their text.
 *
 * Label and value sizes are taken from the artboard rather than the type scale:
 * 11px at 2px tracking is smaller and tighter than the x-small preset.
 * ----------------------------------------------------------------------- */
.tiay-fact {
	max-inline-size: 260px;
}

.tiay-fact__label {
	margin: 0;
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 2px;
	text-transform: uppercase;
	color: var(--wp--preset--color--pink-700);
}

.tiay-fact__value {
	margin: 0;
	font-size: 1rem;
	line-height: 1.3;
	font-weight: 700;
	color: var(--wp--preset--color--blue-950);
}

/* On a dark section the pink label drops to 1.9:1, so both lines invert. */
[class*="is-style-section-dark"] .tiay-fact__label {
	color: var(--wp--preset--color--blue-200);
}

[class*="is-style-section-dark"] .tiay-fact__value {
	color: var(--wp--preset--color--white);
}

/* --------------------------------------------------------------------------
 * File / document rows
 *
 * Core's File block is a bare link plus a button. Styled here to match the
 * document rows used elsewhere: a bordered card, the file name and its type and
 * size on the left, the download action on the right.
 * ----------------------------------------------------------------------- */
.tiay-doc-list .wp-block-file {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--20);
	padding: var(--wp--preset--spacing--30);
	border: 1px solid var(--wp--preset--color--stone-300);
	border-radius: var(--wp--custom--radius--card);
	background-color: var(--wp--preset--color--white);
}

.tiay-doc-list .wp-block-file > a:not(.wp-block-file__button) {
	flex: 1 1 60%;
	font-weight: 700;
	color: var(--wp--preset--color--blue-950);
}

.tiay-doc-list .wp-block-file > a:not(.wp-block-file__button):hover {
	color: var(--wp--preset--color--pink-700);
}

/* Derived from the attachment by tiay_file_block_meta(), so it cannot go stale
   when a file is replaced. */
.tiay-file__meta {
	flex: 1 1 100%;
	order: 3;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--stone-700);
}

.tiay-doc-list .wp-block-file__button {
	order: 2;
	background-color: var(--wp--preset--color--blue-950);
	color: var(--wp--preset--color--white);
	border-radius: var(--wp--custom--radius--button);
	padding: 0.7rem 1.4rem;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 700;
}

.tiay-doc-list .wp-block-file__button:hover,
.tiay-doc-list .wp-block-file__button:focus-visible {
	background-color: var(--wp--preset--color--pink-700);
	color: var(--wp--preset--color--white);
}

/* --------------------------------------------------------------------------
 * Embedded map
 * ----------------------------------------------------------------------- */
/* Border is blue-100 rather than the stone-300 used on cards, and the panel is
   460 tall — both per the Contact artboard, where the map sits beside a column
   of address detail and is meant to read as a tinted panel rather than a card. */
.tiay-map {
	overflow: hidden;
	border: 1px solid var(--wp--preset--color--blue-100);
	border-radius: var(--wp--custom--radius--card);
	background-color: var(--wp--preset--color--blue-50);
}

.tiay-map iframe {
	display: block;
	inline-size: 100%;
	block-size: 460px;
	border: 0;
}

@media (max-width: 781px) {
	.tiay-map iframe {
		block-size: 300px;
	}
}

/* The form card sits on a centred brand section, but fields and their labels
   read badly centred, and a form stretched to the full 1280 column is far wider
   than it needs to be. The width needs !important to clear the section-width
   rule above, which itself matches core's weight. */
.tiay-form-card {
	text-align: start;
	max-width: 46rem !important;
}

/* --------------------------------------------------------------------------
 * Mailchimp embed
 *
 * Mailchimp's classic embed ships no stylesheet of its own, so without this the
 * form renders in browser defaults: Arial 13.3px, a 2px inset border, square
 * corners, and 21px-tall controls on a page whose every other target is built
 * to a 44px floor. Measured before writing this, on the newsletter page.
 *
 * Nothing here is invented. The field surface is blue-50 inside a blue-100
 * hairline at 12px, which is the inset-card recipe the artboards use for
 * fairExchange and fundedBy; the submit button restates elements.button from
 * theme.json exactly, because the embed emits `input[type=submit]` and core's
 * button styles only reach `.wp-element-button`.
 *
 * Scoped to #mc_embed_signup throughout. Mailchimp owns this markup and can
 * change it; keeping the whole block behind one id means a future embed that
 * does not match simply falls back to unstyled rather than half-styled.
 * ----------------------------------------------------------------------- */
#mc_embed_signup {
	/* 46rem is not a new number: it is .tiay-form-card's cap above, which is the
	   theme's existing answer to "a form stretched to the full 1280 column is far
	   wider than it needs to be". Matching it means the form is the same width
	   whether or not the card carries that class — and if the card does carry it,
	   the fields simply fill the card, which is what the artboards draw. */
	max-inline-size: 46rem;
	font-family: inherit;
}

#mc_embed_signup form {
	padding: 0;
}

#mc_embed_signup .indicates-required {
	margin-block-end: var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--stone-700);
	text-align: start;
}

#mc_embed_signup .asterisk {
	color: var(--wp--preset--color--pink-700);
}

#mc_embed_signup .mc-field-group {
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
	margin-block-end: var(--wp--preset--spacing--20);
	padding: 0;
	width: auto;
}

#mc_embed_signup .mc-field-group label {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	color: var(--wp--preset--color--stone-900);
}

#mc_embed_signup .mc-field-group input,
#mc_embed_signup .mc-field-group textarea {
	/* 1rem, not the theme's small: anything under 16px makes iOS zoom the page
	   on focus, and the zoom does not reverse on blur. */
	font-family: inherit;
	font-size: 1rem;
	line-height: 1.4;
	color: var(--wp--preset--color--stone-900);
	background-color: var(--wp--preset--color--blue-50);
	border: 1px solid var(--wp--preset--color--blue-100);
	border-radius: 8px;
	/* Padding, not a fixed height, so the control still grows if the browser
	   text size is raised. 0.75rem + 1rem line + 0.75rem clears the 44px floor
	   the social icons and file links are already built to. */
	padding: 0.75rem 1rem;
	inline-size: 100%;
	box-sizing: border-box;
}

#mc_embed_signup .mc-field-group input::placeholder,
#mc_embed_signup .mc-field-group textarea::placeholder {
	color: var(--wp--preset--color--stone-700);
}

#mc_embed_signup .mc-field-group input:hover,
#mc_embed_signup .mc-field-group textarea:hover {
	border-color: var(--wp--preset--color--blue-200);
}

/* The long-answer field.
 *
 * A taller <input> would be a lie: it looks like it takes a paragraph, but the
 * text runs off sideways on one line and never wraps. So the markup uses a
 * <textarea> and this sizes it.
 *
 * min-block-size rather than rows, so the floor holds whatever the browser's
 * default row height is, and resize:vertical so someone with more to say can
 * pull it open — but not sideways, which would break the grid column.
 *
 * The real ceiling is not visual. MMERGE6 is a Mailchimp *text* merge field,
 * capped at 255 bytes, and Mailchimp clips silently past that. maxlength on the
 * element is what turns that into an honest limit the person can see coming. */
#mc_embed_signup .mc-field-group textarea {
	min-block-size: 7.5rem;
	resize: vertical;
}

/* Two-up for the name pair from 600px, matching the artboards' first row.
   Keyed to the fields by id rather than nth-child: Mailchimp reorders these
   when the audience's merge fields change, and a positional selector would
   silently pair the wrong two. */
@media (min-width: 600px) {
	#mc_embed_signup #mc_embed_signup_scroll {
		display: grid;
		grid-template-columns: 1fr 1fr;
		column-gap: var(--wp--preset--spacing--20);
	}

	#mc_embed_signup #mc_embed_signup_scroll > *:not(.mc-field-group:has(#mce-FNAME)):not(.mc-field-group:has(#mce-LNAME)) {
		grid-column: 1 / -1;
	}
}

/* The consent line, sitting between the last field and the button.
 *
 * CASL wants express consent to name what is being sent and by whom, and every
 * message to carry a way out. This is the "names what is being sent" half, put
 * where the person reads it before they act rather than under the button after.
 *
 * stone-700, not stone-500: it sits on the white card, so stone-500 would pass
 * at 4.80 — but consent copy is the last thing that should be styled as though
 * it were fine print, and the muted-text safeguard above already darkens this
 * token on two of the three light surfaces. */
#mc_embed_signup .tiay-form-consent {
	margin: 0 0 var(--wp--preset--spacing--20);
	max-inline-size: 34rem;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.5;
	color: var(--wp--preset--color--stone-700);
}

/* Response messages. These carry role="alert" and role="status" in the markup,
   which is what actually announces them; this is only their appearance. */
#mc_embed_signup #mce-responses {
	padding: 0;
	width: auto;
	margin: 0;
}

#mc_embed_signup .response {
	margin: 0 0 var(--wp--preset--spacing--20);
	padding: 0.75rem 1rem;
	border-radius: 8px;
	font-size: var(--wp--preset--font-size--small);
}

#mc_embed_signup #mce-error-response {
	background-color: var(--wp--preset--color--pink-50);
	border: 1px solid var(--wp--preset--color--pink-300);
	color: var(--wp--preset--color--pink-700);
}

#mc_embed_signup #mce-success-response {
	background-color: var(--wp--preset--color--blue-50);
	border: 1px solid var(--wp--preset--color--blue-200);
	color: var(--wp--preset--color--blue-600);
}

/* Field-level validation text Mailchimp writes on failed submit. */
#mc_embed_signup div.mce_inline_error {
	margin: 0.35rem 0 0;
	padding: 0;
	background: none;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	color: var(--wp--preset--color--pink-700);
}

#mc_embed_signup input.mce_inline_error {
	border-color: var(--wp--preset--color--pink-500);
}

/* elements.button from theme.json, restated. The embed emits a bare
   input[type=submit], which core's .wp-element-button rules never reach. The
   1px transparent border is not decoration — it is the shared box every button
   variation on this site carries so the outline styles cost no extra pixels. */
#mc_embed_signup #mc-embedded-subscribe {
	display: inline-block;
	inline-size: auto;
	height: auto;
	margin: 0;
	font-family: inherit;
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 700;
	line-height: 1.2;
	color: var(--wp--preset--color--white);
	background-color: var(--wp--preset--color--pink-500);
	border: 1px solid transparent;
	border-radius: 8px;
	padding: 0.9375rem 2.1875rem;
	cursor: pointer;
	transition: background-color 120ms ease;
}

#mc_embed_signup #mc-embedded-subscribe:hover,
#mc_embed_signup #mc-embedded-subscribe:focus,
#mc_embed_signup #mc-embedded-subscribe:active {
	background-color: var(--wp--preset--color--pink-700);
	color: var(--wp--preset--color--white);
}

@media (prefers-reduced-motion: reduce) {
	#mc_embed_signup #mc-embedded-subscribe {
		transition: none;
	}
}

/* --------------------------------------------------------------------------
 * Eyebrow
 * Used above section headings. A heading level is chosen for structure; this is
 * the visual treatment applied to it.
 * ----------------------------------------------------------------------- */
/* The comp draws the section eyebrow in brand pink. The build never set a
 * colour on it, so it inherited the section's body colour — white on dark
 * grounds, near-black on light ones. The pink was lost by omission, not by
 * decision.
 *
 * It cannot be the artboards' pink-500 everywhere: on blue-950 that is 3.64:1
 * at 14px and fails AA. That finding is already recorded in the accessibility
 * review, for the Contact hero, where the answer was blue-200. Per surface
 * instead, so the eyebrow stays pink wherever pink can be read:
 *
 *   light grounds   pink-700   7.16:1 on white, 6.59:1 on tint
 *   dark grounds    pink-300   8.60:1 on blue-950
 *   brand ground    white      4.67:1, and the comp draws it white there
 *
 * pink-300 rather than blue-200 because it answers the contrast without
 * changing the hue, which is the thing the design was asking for. Same
 * reasoning as the news card chip.
 *
 * An eyebrow that sets its own colour still wins: core emits .has-*-color with
 * !important, so the hero's blue-200 and the numbered responsibility cards are
 * untouched by these three rules. */
.tiay-eyebrow {
	text-transform: uppercase;
	letter-spacing: 0.16em;
	font-weight: 700;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--pink-700);
}

[class*="is-style-section-dark"] .tiay-eyebrow {
	color: var(--wp--preset--color--pink-300);
}

[class*="is-style-section-brand"] .tiay-eyebrow {
	color: var(--wp--preset--color--white);
}

/* A generic .tiay-pill rule lived here and was never used — the annotated link
   card carries its own chip styles, scoped to the block. Removed rather than
   left as a second, competing definition of the same idea. */

/* --------------------------------------------------------------------------
 * Hero photo credit
 *
 * Bottom-right, in the corner the hero's left-aligned text leaves empty. Sized
 * and coloured as metadata rather than content: this is an obligation to the
 * photographer, not something the page is asking anyone to read.
 *
 * blue-200 is safe against any photograph, not just the ones in use today. The
 * scrim's last stop is rgba(0,31,46,0.93), so the bottom edge composites to
 * rgb(18,47,61) even under a pure white image — blue-200 measures 8.56:1 there
 * and 10.40:1 over a dark frame. Nothing an editor uploads can break it.
 *
 * THE VIDEO TOGGLE LIVES IN THIS CORNER TOO. It is dormant while the heroes are
 * stills, and the filter that draws it is deliberately kept so any future video
 * hero inherits its WCAG 2.2.2 pause control. The moment one returns, a credit
 * at the same inset would sit underneath a 44px button — so the credit steps
 * aside when a toggle is present rather than waiting to be discovered by
 * whoever switches video back on.
 * ----------------------------------------------------------------------- */
.tiay-hero__credit {
	position: absolute;
	inset-block-end: var(--wp--preset--spacing--30);
	inset-inline-end: var(--wp--preset--spacing--30);
	z-index: 2;
	margin-block: 0;

	font-size: var(--wp--preset--font-size--x-small);
	line-height: 1.3;
	color: var(--wp--preset--color--blue-200);
	text-align: end;
}

/* inline-block plus 5px block padding takes the target from 15px to 25px high.
   A 15px-high link passes 2.5.8 only on the spacing exception — nothing else is
   near it — and leaning on an exception when ten pixels of padding removes the
   need is not worth it. The padding is invisible: the line is anchored to the
   hero's bottom inset, so the text shifts up by five pixels and nothing else
   moves. It also gives the focus ring something to sit around. */
.tiay-hero__credit a {
	color: inherit;
	display: inline-block;
	padding-block: 5px;
}

.tiay-hero__credit a:hover,
.tiay-hero__credit a:focus-visible {
	color: var(--wp--preset--color--white);
}

/* 24px inset + 44px control + 12px breathing room. */
.tiay-hero:has(.tiay-hero__video-toggle) .tiay-hero__credit {
	inset-inline-end: calc(var(--wp--preset--spacing--30) + 56px);
}

/* The hero is a cover, not a section style, so the white-ring rule further up
   this file does not reach it. A pink-500 ring on the scrim measures exactly
   3.00:1 over a white photograph — on the 1.4.11 threshold with no margin, and
   dependent on the image, which is not a guarantee worth relying on. */
.tiay-hero :where(a, button):focus-visible {
	outline-color: var(--wp--preset--color--white);
}

/* --------------------------------------------------------------------------
 * Fair Exchange Rate — the printable sheet
 *
 * This page replaces a PDF that a script on a developer's Mac used to render
 * through headless Chrome. Members post it at the till, so it has to survive a
 * browser's Print dialogue as cleanly as the PDF did — which is the entire job
 * of the print block at the bottom of this section.
 *
 * The figures are injected by inc/fair-exchange-rate.php, derived from the one
 * rate in the "Fair Exchange Rate" synced pattern. Nothing here is authored by
 * hand, so nothing here can disagree with the footer.
 *
 * ONE PRINTED PAGE is the constraint everything below serves. The sheet is
 * reprinted weekly, and a business that has to reprint two pages a week will
 * stop reprinting. Anything addressed to the business rather than to the
 * visitor — how to take part, the print button itself — is marked
 * `tiay-fer-noprint` and stays on screen.
 * ----------------------------------------------------------------------- */

.tiay-fer__headline {
	font-size: clamp(1.9rem, 1.1rem + 3.4vw, 3.4rem);
	font-weight: 800;
	line-height: 1.1;
	margin-block: 0 0.25rem;
	color: var(--wp--preset--color--blue-950);
	font-variant-numeric: tabular-nums;
	text-wrap: balance;
}

.tiay-fer__set {
	margin-block: 0;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--stone-700);
}

.tiay-fer__tables {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
	gap: var(--wp--preset--spacing--30);
	margin-block-start: var(--wp--preset--spacing--20);
}

.tiay-fer__table {
	width: 100%;
	border-collapse: collapse;
	font-variant-numeric: tabular-nums;
}

.tiay-fer__table th {
	text-align: start;
	font-size: var(--wp--preset--font-size--x-small);
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--wp--preset--color--stone-700);
	border-block-end: 2px solid var(--wp--preset--color--blue-950);
	padding-block: 0.35rem;
}

.tiay-fer__table td {
	padding-block: 0.35rem;
	border-block-end: 1px solid var(--wp--preset--color--blue-50);
}

/* The instruction to print is the one thing on the page that must not print. */
@media print {
	.tiay-fer-noprint,
	.tiay-fer-staff,
	body:has(.tiay-fer-sheet) .tiay-header,
	body:has(.tiay-fer-sheet) .tiay-footer,
	body:has(.tiay-fer-sheet) .tiay-nav-overlay {
		display: none !important;
	}

	/* Section tints are a screen device. On a shop's printer a full-page wash of
	   colour is somebody else's ink cartridge, so both sections print on white. */
	.tiay-fer-sheet,
	.tiay-fer-staff {
		padding-block: 0 !important;
		background: transparent !important;
	}

	.tiay-fer__tables,
	.tiay-fer__table tr {
		break-inside: avoid;
		page-break-inside: avoid;
	}
}
