/* =============================================================
   DSBN PATTERN LIBRARY (v2)  —  token-based, Bootstrap-free
   -------------------------------------------------------------
   Styles for the v2 block patterns in /patterns/v2/*.php.
   Every value derives from css/design-tokens.css so the whole
   library re-themes per site. All components are responsive.
   ============================================================= */

/* ---------- Global base ----------------------------------- */
body {
	font-family: var(--dsbn-font-body);
	font-size: var(--dsbn-fs-body);
	line-height: var(--dsbn-lh-body);
	color: var(--dsbn-color-body);
}

/* ---------- Shared layout primitives ---------------------- */
.dsbn-section {
	padding-block: var(--dsbn-section-pad);
	padding-inline: var(--dsbn-gutter);
}

.dsbn-section+.dsbn-section {
	margin-top: 0;
}

/* Two adjacent PLAIN (no background) sections would otherwise stack
   bottom-pad + top-pad into a doubled gap. Drop the second one's top
   padding so plain sections "fold" together like collapsed margins —
   while any section with a background (modifier class, palette class,
   or custom inline color) keeps its full padding, since a colored band
   needs its own breathing room above its content. Margins can't be used
   for this instead: backgrounds don't paint margin, and margin
   collapsing breaks inside flex/grid parents.
   Scoped to real page content (.pg-contents) + the editor canvas —
   template-rendered sections (homepage etc.) have hand-tuned spacing and
   bespoke background classes this heuristic can't see (e.g. the Who We
   Are gradient), so they must keep their own rhythm untouched. */
:where(.pg-contents, .editor-styles-wrapper) .dsbn-section:not([class*="dsbn-section--"]):not([class*="-background-color"]):not([style*="background"])+.dsbn-section:not([class*="dsbn-section--"]):not([class*="-background-color"]):not([style*="background"]) {
	padding-top: 0;
}

.dsbn-section--compact {
	padding-block: clamp(2rem, 4vw, 3rem);
}

.dsbn-section--spacious {
	padding-block: clamp(4rem, 8vw, 7rem);
}

.dsbn-section--white {
	background: #fff;
}

.dsbn-section--tint {
	background: var(--dsbn-surface-blue-soft);
}

.dsbn-section--cream {
	background: var(--dsbn-surface-cream);
}

.dsbn-section--gray {
	background: var(--dsbn-surface-gray);
}

.dsbn-section--alt {
	background: var(--dsbn-color-surface-alt);
}

.dsbn-section.has-dsbn-blue-background-color,
.dsbn-section.has-dsbn-accessible-blue-background-color,
.dsbn-section.has-dsbn-ink-background-color {
	color: #fff;
}

.dsbn-section.has-dsbn-blue-background-color :where(.dsbn-eyebrow, .dsbn-heading, .dsbn-body, .dsbn-section-header__title),
.dsbn-section.has-dsbn-accessible-blue-background-color :where(.dsbn-eyebrow, .dsbn-heading, .dsbn-body, .dsbn-section-header__title),
.dsbn-section.has-dsbn-ink-background-color :where(.dsbn-eyebrow, .dsbn-heading, .dsbn-body, .dsbn-section-header__title) {
	color: #fff;
}

/* The "Enclosed" media-row variant floats a light card on top of the
   section background (its own background, not the section's), so text
   inside it must stay dark even when the surrounding section is dark.
   Reset at the container level (not just heading/body) so any text
   inside the card inherits the normal dark color by default. */
.dsbn-section.has-dsbn-blue-background-color .dsbn-media-row--enclosed,
.dsbn-section.has-dsbn-accessible-blue-background-color .dsbn-media-row--enclosed,
.dsbn-section.has-dsbn-ink-background-color .dsbn-media-row--enclosed {
	color: var(--dsbn-color-body);
}

.dsbn-section.has-dsbn-blue-background-color .dsbn-media-row--enclosed :where(.dsbn-heading, .dsbn-section-header__title),
.dsbn-section.has-dsbn-accessible-blue-background-color .dsbn-media-row--enclosed :where(.dsbn-heading, .dsbn-section-header__title),
.dsbn-section.has-dsbn-ink-background-color .dsbn-media-row--enclosed :where(.dsbn-heading, .dsbn-section-header__title) {
	color: var(--dsbn-color-ink);
}

.dsbn-section.has-dsbn-blue-background-color .dsbn-media-row--enclosed .dsbn-body,
.dsbn-section.has-dsbn-accessible-blue-background-color .dsbn-media-row--enclosed .dsbn-body,
.dsbn-section.has-dsbn-ink-background-color .dsbn-media-row--enclosed .dsbn-body {
	color: var(--dsbn-color-body);
}

.dsbn-section.has-dsbn-blue-background-color .dsbn-media-row--enclosed .dsbn-eyebrow,
.dsbn-section.has-dsbn-accessible-blue-background-color .dsbn-media-row--enclosed .dsbn-eyebrow,
.dsbn-section.has-dsbn-ink-background-color .dsbn-media-row--enclosed .dsbn-eyebrow {
	color: var(--dsbn-color-eyebrow);
}

.dsbn-container {
	width: 100%;
	max-width: var(--dsbn-shell);
	margin-inline: auto;
	container-type: inline-size;
}

/* Native WordPress block alignment (the Wide/Full width toolbar buttons —
   theme support added via add_theme_support('align-wide') in
   functions.php) had no CSS support at all in patterns' .dsbn-container
   context before this — only page.php's .dsbn-inside-content handled it.
   Without it, WordPress core's own default .alignfull rule applies instead
   (width:100vw via a negative-viewport-margin breakout) — that assumes the
   block sits alone in normal flow, so when the block is actually one item
   inside a card-row's CSS grid, it has no idea and blows straight past the
   other cards in the row.
   Normal flow: a real edge-to-edge breakout, matching WP core's own
   alignfull convention. */
.dsbn-container .alignfull {
	width: 100vw;
	max-width: 100vw;
	margin-left: calc(50% - 50vw);
	margin-right: calc(50% - 50vw);
}

.dsbn-container .alignwide {
	width: 100%;
	max-width: var(--dsbn-shell-wide);
	margin-left: auto;
	margin-right: auto;
}

/* Inside a card-row/grid pattern there's no sensible way for one card to
   "break out" past its siblings without wrecking the row, so full/wide
   here just means "fill this grid cell flush" instead of trying (and
   failing) to escape to the viewport edge. Same container list already
   used for the inner-container mirror-rule above, so any pattern that
   list already covers gets this for free too. */
:where(.dsbn-card-row, .dsbn-news-card-row, .dsbn-story-card-row, .dsbn-hub-hero, .dsbn-media-row, .dsbn-video-card--half, .dsbn-card-carousel__track, .dsbn-icon-cards, .dsbn-carousel-tabs__panel) :where(.alignfull, .alignwide) {
	width: 100%;
	max-width: 100%;
	margin-left: 0;
	margin-right: 0;
}

.dsbn-section-intro {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0.35rem;
	margin-bottom: clamp(1.25rem, 3vw, 2rem);
}

.dsbn-section-intro .dsbn-heading {
	margin: 0;
}

/* ---------- Shared text primitives ------------------------ */
.dsbn-eyebrow {
	display: inline-block;
	/* Pull the eyebrow visually into the heading below it so the two read as one
	   unit. The measured box gap was only 12px, but the OPTICAL gap was much
	   larger for two reasons, and both are fixed here rather than by retuning
	   containers — the 12px comes from WordPress's own flex layout on
	   .wp-block-group__inner-container (the majority of eyebrow parents), which
	   the theme doesn't own.
	   1. line-height: the eyebrow inherited --dsbn-lh-body (1.6), so a 20px
	      single-line uppercase label sat in a 32px line box — ~6px of dead space
	      under glyphs that have no descenders to use it. --dsbn-lh-heading (1.2)
	      gives 24px and still leaves room if an eyebrow wraps to two lines.
	   2. margin-bottom: in a flex container, an item's margin adds to the gap,
	      so -0.25rem trims the effective 12px gap to 8px (and the hub hero's
	      16px to 12px) without touching any container rule. */
	margin: 0 0 -0.25rem;
	font-family: var(--dsbn-font-body);
	font-size: var(--dsbn-fs-eyebrow);
	font-weight: var(--dsbn-fw-semibold);
	line-height: var(--dsbn-lh-heading);
	letter-spacing: normal;
	text-transform: uppercase;
	color: var(--dsbn-color-eyebrow);
}

.dsbn-heading {
	margin: 0 0 1rem;
	font-family: var(--dsbn-font-heading);
	font-size: var(--dsbn-fs-section);
	font-weight: var(--dsbn-fw-body);
	line-height: var(--dsbn-lh-heading);
	color: var(--dsbn-color-ink);
	text-wrap: balance;
}

.dsbn-body {
	margin: 0 0 1.5rem;
	font-family: var(--dsbn-font-body);
	font-size: var(--dsbn-fs-body);
	font-weight: var(--dsbn-fw-body);
	line-height: var(--dsbn-lh-body);
	color: var(--dsbn-color-body);
}

/* Hub-hero intro uses medium weight per spec. */
.dsbn-hub-hero .dsbn-body {
	font-weight: var(--dsbn-fw-medium);
}

/* ---------- Buttons --------------------------------------- */
/* Work both as a plain anchor (homepage / carousel markup):
       <a class="dsbn-btn dsbn-btn--primary">…</a>
   and as an editable core Button block:
       <div class="wp-block-buttons dsbn-btn-row">
         <div class="wp-block-button dsbn-btn dsbn-btn--primary">
           <a class="wp-block-button__link">…</a> */
.dsbn-btn-row {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
	margin: 0;
}

.dsbn-btn,
.wp-block-button.dsbn-btn>.wp-block-button__link,
.wp-block-button[class*="is-style-dsbn-"]>.wp-block-button__link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.4rem;
	padding: 0.9rem 1.75rem;
	border: 2px solid transparent;
	border-radius: var(--dsbn-radius-btn);
	font-family: var(--dsbn-font-body);
	font-size: 1.1875rem;
	font-weight: var(--dsbn-fw-medium);
	line-height: 1;
	text-decoration: none;
	background: transparent;
	cursor: pointer;
	box-shadow: none;
	transition: background 260ms var(--dsbn-ease), color 260ms var(--dsbn-ease), border-color 260ms var(--dsbn-ease), transform 260ms var(--dsbn-ease);
}

.dsbn-btn:hover,
.wp-block-button.dsbn-btn>.wp-block-button__link:hover,
.wp-block-button[class*="is-style-dsbn-"]>.wp-block-button__link:hover {
	transform: translateY(-1px);
}

.dsbn-btn:focus-visible,
.wp-block-button.dsbn-btn>.wp-block-button__link:focus-visible,
.wp-block-button[class*="is-style-dsbn-"]>.wp-block-button__link:focus-visible,
.dsbn-carousel-tabs__tab:focus-visible,
.dsbn-card-carousel__control:focus-visible,
.dsbn-card-carousel__dot:focus-visible,
.dsbn-icon-card summary:focus-visible,
.dsbn-icon-card--static:focus-visible,
.dsbn-hub-hero__nav-label:focus-visible,
.dsbn-hub-hero__nav a:focus-visible,
.dsbn-video-modal__close:focus-visible {
	outline: 3px solid var(--dsbn-color-accent-blue);
	outline-offset: 4px;
}

.dsbn-card__link .wp-block-button__link:focus-visible,
.dsbn-news-card__link .wp-block-button__link:focus-visible,
.dsbn-image-link-card__link .wp-block-button__link:focus-visible,
.dsbn-card-carousel__link .wp-block-button__link:focus-visible {
	outline: 3px solid var(--dsbn-color-accent-blue);
	outline-offset: -6px;
	box-shadow: inset 0 0 0 3px #fff;
}

/* The core Button block wraps the link in a div that shares the
   .dsbn-btn classes — neutralise that wrapper so only the inner
   link is styled (avoids a doubled padding/border box). */
.wp-block-button.dsbn-btn,
.wp-block-button[class*="is-style-dsbn-"] {
	display: inline-flex;
	padding: 0;
	border: 0;
	background: transparent;
}

.dsbn-btn__icon {
	font-size: 1.15em;
	line-height: 1;
}

/* Optional trailing chevron / leading play icon — keeps the
   button label fully editable while preserving the design icon.
   Anchor rules are scoped to `a` so the core button WRAPPER div
   (which shares the same classes) is not styled twice. */
a.dsbn-btn--arrow::after,
.wp-block-button.dsbn-btn--arrow>.wp-block-button__link::after,
.wp-block-button[class*="is-style-dsbn-"]>.wp-block-button__link::after {
	content: "";
	width: 1.1em;
	height: 1.1em;
	background-color: currentColor;
	-webkit-mask: var(--dsbn-icon-chevron) center / contain no-repeat;
	mask: var(--dsbn-icon-chevron) center / contain no-repeat;
}

/* Leading chevron, mirrored to point left — used for "previous" /
   "back" navigation (e.g. the single-post prev/next nav). */
a.dsbn-btn--arrow-left::before,
.wp-block-button.dsbn-btn--arrow-left>.wp-block-button__link::before {
	content: "";
	width: 1.1em;
	height: 1.1em;
	background-color: currentColor;
	-webkit-mask: var(--dsbn-icon-chevron) center / contain no-repeat;
	mask: var(--dsbn-icon-chevron) center / contain no-repeat;
	transform: scaleX(-1);
}

a.dsbn-btn--play::before,
.wp-block-button.dsbn-btn--play>.wp-block-button__link::before {
	content: "play_circle";
	font-family: "Material Symbols Outlined";
	font-size: 1.2em;
	line-height: 1;
}

/* Trailing download icon — drop-in swap for .dsbn-btn--arrow when the
   button's action is a file download rather than "go to a page". */
a.dsbn-btn--download::after,
.wp-block-button.dsbn-btn--download>.wp-block-button__link::after {
	content: "download";
	font-family: "Material Symbols Outlined";
	font-size: 1.2em;
	line-height: 1;
}

a.dsbn-btn--primary,
.wp-block-button.dsbn-btn--primary>.wp-block-button__link,
.wp-block-button.is-style-dsbn-primary>.wp-block-button__link {
	background: var(--dsbn-btn-main);
	color: #fff;
}

a.dsbn-btn--primary:hover,
.wp-block-button.dsbn-btn--primary>.wp-block-button__link:hover,
.wp-block-button.is-style-dsbn-primary>.wp-block-button__link:hover {
	background: var(--dsbn-color-primary);
	color: #fff;
}

a.dsbn-btn--secondary,
a.dsbn-btn--alt,
.wp-block-button.dsbn-btn--secondary>.wp-block-button__link,
.wp-block-button.dsbn-btn--alt>.wp-block-button__link,
.wp-block-button.is-style-dsbn-secondary>.wp-block-button__link {
	background: var(--dsbn-btn-alt);
	color: #fff;
}

a.dsbn-btn--secondary:hover,
a.dsbn-btn--alt:hover,
.wp-block-button.dsbn-btn--secondary>.wp-block-button__link:hover,
.wp-block-button.dsbn-btn--alt>.wp-block-button__link:hover,
.wp-block-button.is-style-dsbn-secondary>.wp-block-button__link:hover {
	background: var(--dsbn-btn-main);
	color: #fff;
}

a.dsbn-btn--ghost,
.wp-block-button.dsbn-btn--ghost>.wp-block-button__link,
.wp-block-button.is-style-dsbn-ghost>.wp-block-button__link {
	background: transparent;
	border-color: var(--dsbn-color-line);
	color: var(--dsbn-color-ink);
}

a.dsbn-btn--ghost:hover,
.wp-block-button.dsbn-btn--ghost>.wp-block-button__link:hover,
.wp-block-button.is-style-dsbn-ghost>.wp-block-button__link:hover {
	/* Was --dsbn-btn-main (a brighter blue) — every other interactive hover
	   in the system (primary/secondary buttons, .dsbn-cta-link) converges on
	   the DARKER --dsbn-color-primary instead; ghost was the one component
	   trending lighter on hover instead of following that convention. */
	background: color-mix(in srgb, var(--dsbn-color-primary) 8%, transparent);
	border-color: var(--dsbn-color-primary);
	color: var(--dsbn-color-primary);
}

a.dsbn-btn--white,
a.dsbn-btn--light,
a.dsbn-btn--on-dark,
.wp-block-button.dsbn-btn--white>.wp-block-button__link,
.wp-block-button.dsbn-btn--on-dark>.wp-block-button__link,
.wp-block-button.dsbn-btn--light>.wp-block-button__link,
.wp-block-button.is-style-dsbn-white>.wp-block-button__link {
	background: #fff;
	color: var(--dsbn-btn-main);
}

a.dsbn-btn--white:hover,
a.dsbn-btn--light:hover,
a.dsbn-btn--on-dark:hover,
.wp-block-button.dsbn-btn--white>.wp-block-button__link:hover,
.wp-block-button.dsbn-btn--on-dark>.wp-block-button__link:hover,
.wp-block-button.dsbn-btn--light>.wp-block-button__link:hover,
.wp-block-button.is-style-dsbn-white>.wp-block-button__link:hover {
	background: #fff;
	color: var(--dsbn-color-primary);
}

a.dsbn-btn--ghost-white,
a.dsbn-btn--light-ghost,
a.dsbn-btn--white-outline,
.wp-block-button.dsbn-btn--ghost-white>.wp-block-button__link,
.wp-block-button.dsbn-btn--white-outline>.wp-block-button__link,
.wp-block-button.dsbn-btn--light-ghost>.wp-block-button__link,
.wp-block-button.is-style-dsbn-ghost-white>.wp-block-button__link {
	background: transparent;
	border-color: #fff;
	color: #fff;
}

a.dsbn-btn--ghost-white:hover,
a.dsbn-btn--light-ghost:hover,
a.dsbn-btn--white-outline:hover,
.wp-block-button.dsbn-btn--ghost-white>.wp-block-button__link:hover,
.wp-block-button.dsbn-btn--white-outline>.wp-block-button__link:hover,
.wp-block-button.dsbn-btn--light-ghost>.wp-block-button__link:hover,
.wp-block-button.is-style-dsbn-ghost-white>.wp-block-button__link:hover {
	background: #fff;
	border-color: #fff;
	color: var(--dsbn-btn-main);
}

/* Full video-card play control — white rounded square with a dark play
   triangle, followed by a white text label (transparent button box). */
a.dsbn-btn--play-full,
.wp-block-button.dsbn-btn--play-full>.wp-block-button__link {
	background: transparent;
	color: #fff;
	gap: 0.85rem;
	padding: 0;
	border: 0;
}

a.dsbn-btn--play-full::before,
.wp-block-button.dsbn-btn--play-full>.wp-block-button__link::before {
	content: "";
	width: 4.5rem;
	height: auto;
	aspect-ratio: 109.378 / 77.717;
	flex-shrink: 0;
	background: url("/wp-content/themes/dsbn/images/icons/youtube.svg") center / contain no-repeat;
	transition: transform 260ms var(--dsbn-ease);
}

a.dsbn-btn--play-full:hover,
.wp-block-button.dsbn-btn--play-full>.wp-block-button__link:hover {
	color: #fff;
	text-decoration: underline;
	text-decoration-thickness: 2px;
	text-underline-offset: 0.25em;
}

a.dsbn-btn--play-full:hover::before,
.wp-block-button.dsbn-btn--play-full>.wp-block-button__link:hover::before {
	transform: scale(1.06);
}

/* Translucent "glass" pill — sits on top of a photo/video thumbnail.
   White play-circle icon + label + trailing chevron on a blurred dark
   backing so it stays legible over any image. */
a.dsbn-btn--watch,
.wp-block-button.dsbn-btn--watch>.wp-block-button__link {
	gap: 0.75rem;
	padding: 0.5rem 1.5rem 0.5rem 0.5rem;
	background: rgba(6, 33, 62, 0.45);
	backdrop-filter: blur(6px);
	-webkit-backdrop-filter: blur(6px);
	color: #fff;
}

a.dsbn-btn--watch:hover,
.wp-block-button.dsbn-btn--watch>.wp-block-button__link:hover {
	background: rgba(6, 33, 62, 0.78);
}

a.dsbn-btn--watch::before,
.wp-block-button.dsbn-btn--watch>.wp-block-button__link::before {
	content: "";
	width: 2.5rem;
	height: 2.5rem;
	flex-shrink: 0;
	background: var(--dsbn-icon-play-circle-white) center / contain no-repeat;
}

/* Download PDF button — wraps a core/file block. Editors attach the real
   PDF via the block's own native "Drag file, or Upload" placeholder (click
   the block, choose/upload a PDF) — no custom upload UI needed. */
.wp-block-file.dsbn-pdf-button {
	display: flex;
	align-items: center;
	gap: 1rem;
	flex-wrap: wrap;
	padding: 1rem 1.25rem;
	border: 1px solid var(--dsbn-color-line);
	border-radius: var(--dsbn-radius-md);
	background: var(--dsbn-color-surface);
}

.wp-block-file.dsbn-pdf-button::before {
	content: "";
	width: 2rem;
	height: 2rem;
	flex-shrink: 0;
	background: var(--dsbn-color-primary);
	-webkit-mask: var(--dsbn-icon-document) center / contain no-repeat;
	mask: var(--dsbn-icon-document) center / contain no-repeat;
}

/* Skip the generic document icon when the actual PDF is already shown via
   the inline preview embed — showing both is redundant. Front end saves the
   preview as .wp-block-file__embed; the block editor's own live canvas
   renders it as .wp-block-file__preview instead — check both. */
.wp-block-file.dsbn-pdf-button:has(.wp-block-file__embed, .wp-block-file__preview)::before {
	display: none;
}

/* Equal padding on every side when the preview is showing, so the outer
   card's rounded corners and the preview's own rounded corners share the
   same inset and visually line up (the default 1rem/1.25rem split is fine
   without a preview, but reads uneven once there's a full-width image
   directly inside that padding). */
.wp-block-file.dsbn-pdf-button:has(.wp-block-file__embed, .wp-block-file__preview) {
	padding: 1.25rem;
}

/* When "Show inline embed" is on (see download-pdf-button-with-preview.php), the
   <object> preview renders as an extra direct child of the same flex row —
   force it onto its own full-width line above the icon/filename/button so it
   doesn't get squeezed into the row layout meant for those three items. */
.wp-block-file.dsbn-pdf-button .wp-block-file__embed,
.wp-block-file.dsbn-pdf-button .wp-block-file__preview {
	width: 100%;
	border: 1px solid var(--dsbn-color-line);
	border-radius: var(--dsbn-radius-md);
}

.wp-block-file.dsbn-pdf-button a:first-of-type {
	margin-right: auto;
	font-family: var(--dsbn-font-body);
	font-weight: var(--dsbn-fw-medium);
	color: var(--dsbn-color-ink);
	text-decoration: none;
}

.wp-block-file.dsbn-pdf-button .wp-block-file__button {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	padding: 0.6rem 1.25rem;
	border-radius: var(--dsbn-radius-pill);
	background: var(--dsbn-color-primary);
	color: #fff;
	font-family: var(--dsbn-font-body);
	font-weight: var(--dsbn-fw-medium);
	text-decoration: none;
	transition: background var(--dsbn-transition);
}

.wp-block-file.dsbn-pdf-button .wp-block-file__button:hover {
	background: var(--dsbn-color-primary-dark, var(--dsbn-color-primary));
}

/* =============================================================
   HUB HERO
   ============================================================= */
.dsbn-hub-hero {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 320px);
	gap: clamp(1.5rem, 4vw, 3rem);
	align-items: start;
}

.dsbn-hub-hero--content-only {
	display: block;
}

.dsbn-hub-hero--content-only .dsbn-hub-hero__main {
	max-width: 54rem;
}

.dsbn-hub-hero__heading,
.dsbn-heading--hub {
	font-family: var(--dsbn-font-heading);
	/* Sits deliberately between --dsbn-fs-banner (60px ceiling, used by the
	   hub visual-hero title and inside-page hero titles) and --dsbn-fs-hub
	   (110px ceiling, flagged as "massive" for this exact heading before) —
	   this intro heading is meant to read as a bigger visual moment than a
	   plain title, just not at the full hub-display scale, which overwhelmed
	   real editor copy once it ran past a couple of words.

	   Ceiling lowered 5.625rem -> 4.5rem (90 -> 72px): at 90px the /about/
	   heading ("Welcome to the District School Board of Niagara!") still ran
	   to THREE lines / 297px tall on a 1440 desktop — the same "overwhelmed
	   by real editor copy" failure this comment describes, just at a higher
	   threshold. Floor raised 2.5 -> 2.75rem to preserve today's 44px phone
	   size exactly, so this is a desktop/tablet-only reduction.

	   This single clamp now covers ALL widths. There used to be a ≤768px
	   "scale-down" override using 10vw, but 10vw is LARGER than this rule's
	   6.5vw, so it scaled the heading UP as the screen narrowed: 50px at
	   769px jumped to 61.4px at 768px (measured). One monotonic clamp cannot
	   do that. */
	font-size: clamp(2.75rem, 6.5vw, 4.5rem);
	font-weight: var(--dsbn-fw-body);
	line-height: var(--dsbn-lh-tight);
	color: var(--dsbn-color-ink);
	margin: 0.5rem 0 1.25rem;
}

.dsbn-hub-hero__nav {
	border: 1px solid var(--dsbn-hub-nav-border);
	border-radius: 26px;
	padding: 1.5rem;
	background: var(--dsbn-hub-nav-bg);
}

.dsbn-hub-hero__nav-label {
	display: flex;
	align-items: center;
	justify-content: space-between;
	width: 100%;
	padding: 0 0.25rem 0.75rem;
	margin-bottom: 1rem;
	border: 0;
	border-bottom: 1px solid var(--dsbn-color-line);
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: #5c6673;
	background: transparent;
	text-align: left;
}

.dsbn-hub-hero__nav-label::after {
	content: "";
	display: none;
	width: 1rem;
	height: 1rem;
	background-color: currentColor;
	-webkit-mask: var(--dsbn-icon-chevron) center / contain no-repeat;
	mask: var(--dsbn-icon-chevron) center / contain no-repeat;
	transform: rotate(90deg);
	transition: transform var(--dsbn-transition);
}

.dsbn-hub-hero__nav-list {
	list-style: none;
	margin: 1rem 0 0;
	padding: 0;
}

.dsbn-hub-hero__nav-list li {
	margin: 0;
}

.dsbn-hub-hero__nav-icon {
	width: 1rem;
	height: 1rem;
	object-fit: contain;
	opacity: 0.7;
}

.dsbn-hub-hero__nav a {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	padding: 0.7rem 0.75rem;
	border-radius: var(--dsbn-radius-nav-link);
	color: var(--dsbn-color-body);
	font-size: var(--dsbn-fs-body);
	font-weight: var(--dsbn-fw-medium);
	text-decoration: none;
	transition: background var(--dsbn-transition), color var(--dsbn-transition);
}

.dsbn-hub-hero__nav a:hover,
.dsbn-hub-hero__nav a.is-active,
.dsbn-hub-hero__nav [aria-current="page"] {
	background: var(--dsbn-hub-nav-active);
	color: var(--dsbn-color-ink);
	font-weight: var(--dsbn-fw-bold);
}

@media (max-width: 1024px) {
	.dsbn-hub-hero {
		grid-template-columns: 1fr;
	}

	.dsbn-hub-hero__nav {
		padding: 1.25rem;
	}

	.dsbn-hub-hero__nav-label {
		padding: 0;
		margin-bottom: 0;
		border-bottom: 0;
		cursor: pointer;
	}

	/* .dsbn-inside-nav's own label rule (outside this media query) has
	   higher specificity (2 classes) than the generic reset just above, so
	   it was winning even on mobile and keeping its desktop padding-bottom/
	   margin-bottom on the COLLAPSED toggle — leaving a chunk of dead
	   clickable-looking space under the title with nothing visibly below
	   it until expanded. Match that specificity here to actually reset it. */
	.dsbn-inside-nav .dsbn-hub-hero__nav-label {
		padding: 0;
		margin-bottom: 0;
		cursor: pointer;
	}

	.dsbn-hub-hero__nav-label::after {
		display: block;
	}

	.dsbn-hub-hero__nav.is-open .dsbn-hub-hero__nav-label::after {
		transform: rotate(-90deg);
	}

	.dsbn-hub-hero__nav-list,
	.dsbn-hub-hero__nav .wp-block-list {
		overflow: hidden;
		max-height: 0;
		margin-top: 0;
		transition: max-height 0.3s ease, margin-top 0.3s ease;
	}

	.dsbn-hub-hero__nav.is-open .dsbn-hub-hero__nav-list,
	.dsbn-hub-hero__nav.is-open .wp-block-list {
		max-height: 32rem;
		margin-top: 1rem;
	}
}

/* =============================================================
   HOME QUICK MENU
   ============================================================= */
.dsbn-section--home-menu {
	padding-block: clamp(1.5rem, 4vw, 2.5rem);
}

.dsbn-home-menu {
	position: relative;
	box-sizing: border-box;
	display: grid;
	grid-template-columns: repeat(6, minmax(0, 1fr));
	align-items: stretch;
	width: 100%;
	margin-inline: auto;
	padding: 2rem 2.5rem;
	border: 1px solid #D9DDE2;
	border-radius: 26px;
	background: #fff;
	box-shadow: 0 8px 24px rgba(0, 0, 0, 0.14);
	overflow: hidden;
	--dsbn-home-menu-glow-x: calc(2.5rem + (100% - 5rem) * 0.08333);
	--dsbn-home-menu-glow-tint: 26, 109, 219;
	--dsbn-home-menu-glow-opacity: 0;
}

.dsbn-home-menu::before {
	position: absolute;
	inset: auto 0 0;
	height: 13rem;
	background: radial-gradient(ellipse 14rem 13rem at var(--dsbn-home-menu-glow-x) 100%, rgba(var(--dsbn-home-menu-glow-tint), 0.22) 0%, rgba(var(--dsbn-home-menu-glow-tint), 0.12) 50%, rgba(var(--dsbn-home-menu-glow-tint), 0) 82%);
	content: "";
	opacity: var(--dsbn-home-menu-glow-opacity);
	pointer-events: none;
	transition: opacity var(--dsbn-transition), background var(--dsbn-transition);
}

.dsbn-home-menu__item {
	position: relative;
	z-index: 1;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 0.75rem;
	min-height: clamp(7rem, 9vw, 8rem);
	padding: 1rem 0.75rem;
	border-radius: 14px;
	font-family: var(--dsbn-font-body);
	font-size: 1.5rem;
	font-weight: var(--dsbn-fw-light, 300);
	line-height: 1.2;
	text-align: center;
	text-decoration: none;
	color: var(--dsbn-color-body);
	background: transparent;
	transition: background var(--dsbn-transition), color var(--dsbn-transition), transform var(--dsbn-transition);
	--dsbn-home-menu-tint: 26, 109, 219;
	--dsbn-home-menu-color: #1a6ddb;
	--dsbn-home-menu-filter: invert(42%) sepia(92%) saturate(1847%) hue-rotate(198deg) brightness(89%) contrast(92%);
}

.dsbn-home-menu__item:hover,
.dsbn-home-menu__item:focus-within {
	background: transparent;
	color: var(--dsbn-home-menu-color);
	transform: translateY(-2px);
}

/* Per-item hover colours. :focus-within (rather than :focus-visible) so this still
   triggers when the item is a wrapper div whose inner label link receives focus
   (block-editor markup), as well as when the item itself is the focused anchor
   (front-page.php's hand-rolled markup). */
.dsbn-home-menu:has(.dsbn-home-menu__item:nth-child(1):is(:hover, :focus-within)) {
	--dsbn-home-menu-glow-x: calc(2.5rem + (100% - 5rem) * 0.08333);
	--dsbn-home-menu-glow-tint: 20, 167, 255;
	--dsbn-home-menu-glow-opacity: 1;
}

.dsbn-home-menu:has(.dsbn-home-menu__item:nth-child(2):is(:hover, :focus-within)) {
	--dsbn-home-menu-glow-x: calc(2.5rem + (100% - 5rem) * 0.25);
	--dsbn-home-menu-glow-tint: 177, 247, 81;
	--dsbn-home-menu-glow-opacity: 1;
}

.dsbn-home-menu:has(.dsbn-home-menu__item:nth-child(3):is(:hover, :focus-within)) {
	--dsbn-home-menu-glow-x: calc(2.5rem + (100% - 5rem) * 0.41667);
	--dsbn-home-menu-glow-tint: 255, 199, 70;
	--dsbn-home-menu-glow-opacity: 1;
}

.dsbn-home-menu:has(.dsbn-home-menu__item:nth-child(4):is(:hover, :focus-within)) {
	--dsbn-home-menu-glow-x: calc(2.5rem + (100% - 5rem) * 0.58333);
	--dsbn-home-menu-glow-tint: 210, 125, 229;
	--dsbn-home-menu-glow-opacity: 1;
}

.dsbn-home-menu:has(.dsbn-home-menu__item:nth-child(5):is(:hover, :focus-within)) {
	--dsbn-home-menu-glow-x: calc(2.5rem + (100% - 5rem) * 0.75);
	--dsbn-home-menu-glow-tint: 250, 179, 109;
	--dsbn-home-menu-glow-opacity: 1;
}

.dsbn-home-menu:has(.dsbn-home-menu__item:nth-child(6):is(:hover, :focus-within)) {
	--dsbn-home-menu-glow-x: calc(2.5rem + (100% - 5rem) * 0.91667);
	--dsbn-home-menu-glow-tint: 212, 43, 80;
	--dsbn-home-menu-glow-opacity: 1;
}

.dsbn-home-menu__item:nth-child(1) {
	--dsbn-home-menu-tint: 26, 109, 219;
	--dsbn-home-menu-color: #1a6ddb;
	--dsbn-home-menu-filter: invert(42%) sepia(92%) saturate(1847%) hue-rotate(198deg) brightness(89%) contrast(92%);
}

.dsbn-home-menu__item:nth-child(2) {
	--dsbn-home-menu-tint: 26, 140, 69;
	--dsbn-home-menu-color: #1a8c45;
	--dsbn-home-menu-filter: invert(40%) sepia(85%) saturate(514%) hue-rotate(91deg) brightness(90%) contrast(87%);
}

.dsbn-home-menu__item:nth-child(3) {
	--dsbn-home-menu-tint: 184, 134, 11;
	--dsbn-home-menu-color: #b8860b;
	--dsbn-home-menu-filter: invert(54%) sepia(88%) saturate(736%) hue-rotate(5deg) brightness(92%) contrast(91%);
}

.dsbn-home-menu__item:nth-child(4) {
	--dsbn-home-menu-tint: 123, 45, 191;
	--dsbn-home-menu-color: #7b2dbf;
	--dsbn-home-menu-filter: invert(24%) sepia(76%) saturate(1966%) hue-rotate(263deg) brightness(86%) contrast(89%);
}

.dsbn-home-menu__item:nth-child(5) {
	--dsbn-home-menu-tint: 212, 98, 10;
	--dsbn-home-menu-color: #d4620a;
	--dsbn-home-menu-filter: invert(44%) sepia(94%) saturate(1354%) hue-rotate(7deg) brightness(92%) contrast(92%);
}

.dsbn-home-menu__item:nth-child(6) {
	--dsbn-home-menu-tint: 212, 43, 80;
	--dsbn-home-menu-color: #d42b50;
	--dsbn-home-menu-filter: invert(31%) sepia(90%) saturate(1690%) hue-rotate(325deg) brightness(91%) contrast(88%);
}

.dsbn-home-menu__icon,
.dsbn-home-menu__icon img {
	display: block;
	width: 3rem;
	height: 3rem;
	object-fit: contain;
	filter: grayscale(1);
	opacity: 0.72;
	transition: filter var(--dsbn-transition), opacity var(--dsbn-transition);
}

/* The block-editor Image block wraps <img> in a <figure> — reset the figure's
   own margin so it doesn't add spacing the original hand-rolled <img> didn't have. */
.dsbn-home-menu__icon {
	margin: 0;
}

.dsbn-home-menu__item:hover .dsbn-home-menu__icon,
.dsbn-home-menu__item:focus-within .dsbn-home-menu__icon,
.dsbn-home-menu__item:hover .dsbn-home-menu__icon img,
.dsbn-home-menu__item:focus-within .dsbn-home-menu__icon img {
	filter: var(--dsbn-home-menu-filter);
	opacity: 1;
}

/* Label link (block-editor markup: <p class="dsbn-home-menu__label"><a>...</a></p>).
   The anchor is stretched to cover the whole item so the entire card stays
   clickable/hoverable, matching the original single <a class="dsbn-home-menu__item">
   used by front-page.php's hand-rolled markup. */
.dsbn-home-menu__label {
	margin: 0;
}

.dsbn-home-menu__label a {
	color: inherit;
	text-decoration: inherit;
}

.dsbn-home-menu__label a::after {
	content: "";
	position: absolute;
	inset: 0;
}

@media (max-width: 768px) {
	.dsbn-home-menu {
		grid-template-columns: repeat(3, minmax(0, 1fr));
		gap: 0.35rem;
		padding: 0.75rem;
		border-radius: 20px;
	}

	.dsbn-home-menu:has(.dsbn-home-menu__item:nth-child(1):is(:hover, :focus-within)),
	.dsbn-home-menu:has(.dsbn-home-menu__item:nth-child(4):is(:hover, :focus-within)) {
		--dsbn-home-menu-glow-x: calc(0.75rem + (100% - 1.5rem) * 0.16667);
	}

	.dsbn-home-menu:has(.dsbn-home-menu__item:nth-child(2):is(:hover, :focus-within)),
	.dsbn-home-menu:has(.dsbn-home-menu__item:nth-child(5):is(:hover, :focus-within)) {
		--dsbn-home-menu-glow-x: calc(0.75rem + (100% - 1.5rem) * 0.5);
	}

	.dsbn-home-menu:has(.dsbn-home-menu__item:nth-child(3):is(:hover, :focus-within)),
	.dsbn-home-menu:has(.dsbn-home-menu__item:nth-child(6):is(:hover, :focus-within)) {
		--dsbn-home-menu-glow-x: calc(0.75rem + (100% - 1.5rem) * 0.83333);
	}

	.dsbn-home-menu__item {
		min-height: 4.5rem;
		font-size: 0.8125rem;
	}
}

@media (max-width: 480px) {
	.dsbn-home-menu {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.dsbn-home-menu:has(.dsbn-home-menu__item:nth-child(odd):is(:hover, :focus-within)) {
		--dsbn-home-menu-glow-x: calc(0.75rem + (100% - 1.5rem) * 0.25);
	}

	.dsbn-home-menu:has(.dsbn-home-menu__item:nth-child(even):is(:hover, :focus-within)) {
		--dsbn-home-menu-glow-x: calc(0.75rem + (100% - 1.5rem) * 0.75);
	}
}

/* =============================================================
   CARD ROWS  (outline + fill)
   ============================================================= */
.dsbn-card-row {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: clamp(1rem, 2.5vw, 1.75rem);
}

@media (max-width: 768px) {
	.dsbn-card-row:not(.dsbn-card-row-container .dsbn-card-row) {
		grid-template-columns: 1fr;
	}
}

.dsbn-card-row--four {
	grid-template-columns: repeat(4, minmax(0, 1fr));
}

.dsbn-card {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
	padding: 1.75rem 1.75rem 3rem;
	border-radius: 46px;
	background: var(--dsbn-color-surface);
	min-height: 100%;
	transition: transform var(--dsbn-transition), box-shadow var(--dsbn-transition);
}

.dsbn-card:has(.dsbn-card__link .wp-block-button__link:is([href]):not([href="#"]):not([href=""])):hover,
.dsbn-card:has(.dsbn-card__link .wp-block-button__link:is([href]):not([href="#"]):not([href=""])):focus-within,
.dsbn-card:has(.dsbn-cta-link a:is([href]):not([href="#"]):not([href=""])):hover,
.dsbn-card:has(.dsbn-cta-link a:is([href]):not([href="#"]):not([href=""])):focus-within {
	transform: translateY(-4px);
	box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
}

a.dsbn-card,
.dsbn-card[href] {
	cursor: pointer;
	text-decoration: none;
	color: inherit;
}

.dsbn-card__title {
	margin: 0;
	font-family: var(--dsbn-font-body);
	font-size: var(--dsbn-fs-body-header);
	font-weight: var(--dsbn-fw-bold);
	line-height: var(--dsbn-lh-heading);
	color: var(--dsbn-color-ink);
	text-wrap: balance;
}

.dsbn-card__text {
	margin: 0;
	font-family: var(--dsbn-font-body);
	font-size: var(--dsbn-fs-body);
	font-weight: var(--dsbn-fw-medium);
	line-height: var(--dsbn-lh-body);
	color: var(--dsbn-color-body);
}

/* Shared "CTA" footer — hairline divider + visible ghost text link with a
   chevron. Used by the Icon Card (CTA) and Info Card (CTA) patterns; sits
   as a flex item inside any flex-column card (.dsbn-icon-card--static,
   .dsbn-card) and pushes itself to the bottom via margin-top:auto. */
.dsbn-cta-link {
	margin: auto 0 0;
	padding-top: 1.25rem;
	border-top: 1px solid var(--dsbn-color-line);
}

.dsbn-cta-link a {
	display: inline-flex;
	align-items: center;
	gap: 0.3rem;
	font-weight: var(--dsbn-fw-bold);
	color: var(--dsbn-btn-main);
	text-decoration: none;
}

.dsbn-cta-link a:hover {
	color: var(--dsbn-color-primary);
}

/* No chevron here, deliberately: in this design system the chevron is the
   affordance for cards whose link has NO visible text (fill/outline, news,
   image-link, carousel — their anchor is transparent and stretched over the
   whole card, so the chevron is the only thing marking it as clickable).
   This card already says "Learn more" in words, so a chevron would be a
   second, redundant marker for the same link. */

/* Stretched-link trick (classic Bootstrap technique): an invisible ::before
   covering the whole card via the nearest positioned ancestor (.dsbn-card /
   .dsbn-icon-card, both position:relative), so the entire card is clickable
   once linked — not just this text row — while the anchor's own visible
   text stays exactly where it is. */
.dsbn-cta-link a:is([href]):not([href="#"]):not([href=""])::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 2;
}

.dsbn-card__actions {
	position: static;
	margin: 0;
}

.dsbn-card__link {
	position: static;
}

.dsbn-card__link .wp-block-button__link {
	position: absolute;
	inset: -1px;
	z-index: 2;
	display: block;
	width: auto;
	height: auto;
	padding: 0;
	border: 0;
	border-radius: inherit;
	background: transparent;
	color: transparent;
	font-size: 0;
}

/* No real page picked yet (js/card-link-picker.js + PHP
   dsbn_resolve_card_page_link() manage this class) — the card ships with
   this button by default, so without gating on it a brand-new/duplicated
   card would look and behave clickable while still pointing at "#". */
.dsbn-card__link .wp-block-button__link:not([href]),
.dsbn-card__link .wp-block-button__link[href="#"],
.dsbn-card__link .wp-block-button__link[href=""] {
	pointer-events: none;
}

.dsbn-card__link .wp-block-button__link:is([href]):not([href="#"]):not([href=""])::after {
	position: absolute;
	right: 1.5rem;
	bottom: 1.25rem;
	display: block;
	width: 1.75rem;
	height: 1.75rem;
	background: #808080;
	content: "";
	-webkit-mask: var(--dsbn-icon-chevron) center / contain no-repeat;
	mask: var(--dsbn-icon-chevron) center / contain no-repeat;
	transition: transform var(--dsbn-transition), background var(--dsbn-transition);
}

.dsbn-card:hover .dsbn-card__link .wp-block-button__link:is([href]):not([href="#"]):not([href=""])::after,
.dsbn-card:focus-within .dsbn-card__link .wp-block-button__link:is([href]):not([href="#"]):not([href=""])::after {
	background: #808080;
	transform: translateX(4px);
}

/* Outline variant — thin hairline + gradient eyebrow border that
   follows the card's rounded corners at a uniform 8 px thickness,
   then cuts off with a hard horizontal edge below the curve. */
.dsbn-card--outline {
	position: relative;
	border: 1px solid var(--dsbn-color-card-border);
	border-radius: 46px;
	padding-top: 4.5rem;
}

.dsbn-card--outline::before {
	content: "";
	position: absolute;
	inset: -1px;
	border-radius: inherit;
	padding: 10px;
	background: var(--dsbn-eyebrow-blue);
	-webkit-mask:
		linear-gradient(#fff 0 0) content-box,
		linear-gradient(#fff 0 0);
	-webkit-mask-composite: xor;
	mask:
		linear-gradient(#fff 0 0) content-box,
		linear-gradient(#fff 0 0);
	mask-composite: exclude;
	clip-path: inset(0 0 calc(100% - 46px) 0);
	pointer-events: none;
}

.dsbn-card--outline.is-accent-1::before {
	background: var(--dsbn-eyebrow-purple);
}

.dsbn-card--outline.is-accent-2::before {
	background: var(--dsbn-eyebrow-pink);
}

.dsbn-card--outline.is-accent-3::before {
	background: var(--dsbn-eyebrow-blue);
}

.dsbn-card--outline.is-accent-orange::before {
	background: var(--dsbn-eyebrow-orange);
}

.dsbn-card--outline.is-accent-dark-pink::before {
	background: var(--dsbn-eyebrow-dark-pink);
}

.dsbn-card--outline.is-accent-red::before {
	background: var(--dsbn-eyebrow-red);
}

.dsbn-card--outline.is-accent-light-purple::before {
	background: var(--dsbn-eyebrow-light-purple);
}

.dsbn-card--outline.is-accent-light-pink::before {
	background: var(--dsbn-eyebrow-light-pink);
}

.dsbn-card--outline.is-accent-yellow::before {
	background: var(--dsbn-eyebrow-yellow);
}

.dsbn-card--outline.is-accent-light-blue::before {
	background: var(--dsbn-eyebrow-light-blue);
}

.dsbn-card--outline.is-accent-light-green::before {
	background: var(--dsbn-eyebrow-light-green);
}

.dsbn-card--outline.is-accent-green::before {
	background: var(--dsbn-eyebrow-green);
}

.dsbn-card--outline.is-accent-dark-green::before {
	background: var(--dsbn-eyebrow-dark-green);
}



/* Fill variant — gradient header band (heading on white text) sitting
   over a white body that holds the description + a grey chevron.
   The gradient only covers the TOP of the card, not the whole card. */
.dsbn-card--fill {
	padding: 0;
	gap: 0;
	overflow: hidden;
	border-radius: 46px;
	box-shadow: var(--dsbn-shadow-card);
}

.dsbn-card--fill .dsbn-card__head {
	display: flex;
	align-items: flex-end;
	min-height: 175px;
	padding: 1.5rem 1.75rem;
}

.dsbn-card--fill.is-grad-1 .dsbn-card__head {
	background: var(--dsbn-grad-1);
}

.dsbn-card--fill.is-grad-2 .dsbn-card__head {
	background: var(--dsbn-grad-2);
}

.dsbn-card--fill.is-grad-3 .dsbn-card__head {
	background: var(--dsbn-grad-3);
}

.dsbn-card--fill.is-grad-purple .dsbn-card__head {
	background: var(--dsbn-grad-purple);
}

.dsbn-card--fill.is-grad-pink .dsbn-card__head {
	background: var(--dsbn-grad-pink);
}

.dsbn-card--fill.is-grad-blue .dsbn-card__head {
	background: var(--dsbn-grad-blue);
}

.dsbn-card--fill.is-grad-light-purple .dsbn-card__head {
	background: var(--dsbn-grad-light-purple);
}

.dsbn-card--fill.is-grad-light-pink .dsbn-card__head {
	background: var(--dsbn-grad-light-pink);
}

.dsbn-card--fill.is-grad-yellow .dsbn-card__head {
	background: var(--dsbn-grad-yellow);
}

.dsbn-card--fill.is-grad-light-blue .dsbn-card__head {
	background: var(--dsbn-grad-light-blue);
}

.dsbn-card--fill .dsbn-card__title {
	color: #fff;
}

.dsbn-card--fill .dsbn-card__body {
	position: static;
	flex: 1;
	background: var(--dsbn-color-surface);
	padding: 1.5rem 1.75rem 2.75rem;
}

.dsbn-card--fill .dsbn-card__body::after {
	display: none;
}

@media (max-width: 768px) {
	.dsbn-card-row {
		grid-template-columns: 1fr;
	}
}

/* Latest news cards — section heading, see-all action and linked text cards. */
.dsbn-section-header {
	display: flex;
	align-items: center;
	gap: clamp(1rem, 3vw, 2.5rem);
	margin-bottom: 1.75rem;
}

.dsbn-section-header__title {
	margin: 0;
	font-family: var(--dsbn-font-heading);
	/* Was a hand-copied clone of --dsbn-fs-section's value. Once .dsbn-heading
	   gained a mobile step-down and the token's ceiling changed, this copy
	   silently diverged — the homepage rendered "Latest News" (this component)
	   at 32px next to "From across the DSBN" (.dsbn-heading) at 28px. Point at
	   the token so the two section-header components can't drift again. */
	font-size: var(--dsbn-fs-section);
	font-weight: var(--dsbn-fw-body);
	line-height: 1.1;
	color: var(--dsbn-color-ink);
	text-wrap: balance;
}

.dsbn-section-header__actions {
	margin: 0;
}

.dsbn-news-card-row {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: clamp(1.5rem, 3vw, 3.25rem);
}

.dsbn-news-card {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: 0.85rem;
	min-height: 11.25rem;
	padding: 1.75rem 4rem 2.5rem 2rem;
	border: 1px solid var(--dsbn-color-card-border);
	border-radius: 32px;
	background: var(--dsbn-color-surface);
	transition: transform var(--dsbn-transition), box-shadow var(--dsbn-transition);
}

.dsbn-news-card:has(.dsbn-news-card__link .wp-block-button__link:is([href]):not([href="#"]):not([href=""])):hover,
.dsbn-news-card:has(.dsbn-news-card__link .wp-block-button__link:is([href]):not([href="#"]):not([href=""])):focus-within {
	transform: translateY(-4px);
	box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
}

.dsbn-news-card__title {
	margin: 0;
	font-family: var(--dsbn-font-body);
	font-size: var(--dsbn-fs-body-header);
	font-weight: var(--dsbn-fw-bold);
	line-height: 1.08;
	color: var(--dsbn-color-ink);
	text-wrap: balance;
}

.dsbn-news-card__text {
	margin: 0;
	font-family: var(--dsbn-font-body);
	font-size: 1rem;
	font-weight: var(--dsbn-fw-medium);
	line-height: 1.55;
	color: var(--dsbn-color-body);
}

.dsbn-news-card__actions,
.dsbn-news-card__link {
	position: static;
	margin: 0;
}

.dsbn-news-card__link .wp-block-button__link {
	position: absolute;
	inset: -1px;
	z-index: 2;
	display: block;
	width: auto;
	height: auto;
	padding: 0;
	border: 0;
	border-radius: inherit;
	background: transparent;
	color: transparent;
	font-size: 0;
}

/* See .dsbn-card__link's matching rule above for why. */
.dsbn-news-card__link .wp-block-button__link:not([href]),
.dsbn-news-card__link .wp-block-button__link[href="#"],
.dsbn-news-card__link .wp-block-button__link[href=""] {
	pointer-events: none;
}

.dsbn-news-card__link .wp-block-button__link:is([href]):not([href="#"]):not([href=""])::after {
	position: absolute;
	right: 1.75rem;
	bottom: 1.55rem;
	display: block;
	width: 1.5rem;
	height: 1.5rem;
	background: #b3b3b3;
	content: "";
	-webkit-mask: var(--dsbn-icon-chevron) center / contain no-repeat;
	mask: var(--dsbn-icon-chevron) center / contain no-repeat;
	transition: transform var(--dsbn-transition), background var(--dsbn-transition);
}

.dsbn-news-card:hover .dsbn-news-card__link .wp-block-button__link:is([href]):not([href="#"]):not([href=""])::after,
.dsbn-news-card:focus-within .dsbn-news-card__link .wp-block-button__link:is([href]):not([href="#"]):not([href=""])::after {
	background: #808080;
	transform: translateX(4px);
}

@media (max-width: 1024px) {
	.dsbn-news-card-row {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 1.5rem;
	}
}

@media (max-width: 640px) {
	.dsbn-section-header {
		align-items: flex-start;
		flex-direction: column;
	}

	.dsbn-news-card-row {
		grid-template-columns: 1fr;
	}

	.dsbn-news-card {
		min-height: 11rem;
		padding: 1.5rem 3.5rem 2.75rem 1.5rem;
		border-radius: 28px;
	}
}

/* Image link card — rounded card with a customizable top image. */
.dsbn-image-link-card {
	position: relative;
	display: flex;
	flex-direction: column;
	max-width: 540px;
	min-height: 100%;
	padding: 0;
	gap: 0;
	border: 1px solid var(--dsbn-color-card-border);
	border-radius: 46px;
	background: var(--dsbn-color-surface);
	overflow: hidden;
	transition: transform var(--dsbn-transition), box-shadow var(--dsbn-transition);
}

.dsbn-image-link-card:has(.dsbn-image-link-card__link .wp-block-button__link:is([href]):not([href="#"]):not([href=""])):hover,
.dsbn-image-link-card:has(.dsbn-image-link-card__link .wp-block-button__link:is([href]):not([href="#"]):not([href=""])):focus-within {
	transform: translateY(-4px);
	box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
}

.dsbn-image-link-card__media {
	width: 100%;
	margin: 0;
}

.dsbn-image-link-card__media img {
	display: block;
	width: 100%;
	aspect-ratio: 2.35 / 1;
	object-fit: cover;
}

.dsbn-image-link-card__body {
	position: static;
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: 0.75rem;
	padding: 2rem 4.5rem 3.25rem 2.5rem;
}

.dsbn-image-link-card__title {
	margin: 0;
	font-family: var(--dsbn-font-body);
	font-size: var(--dsbn-fs-body-header);
	font-weight: var(--dsbn-fw-bold);
	line-height: var(--dsbn-lh-heading);
	color: var(--dsbn-color-ink);
	text-wrap: balance;
}

.dsbn-image-link-card__text {
	margin: 0;
	font-family: var(--dsbn-font-body);
	font-size: var(--dsbn-fs-body);
	font-weight: var(--dsbn-fw-medium);
	line-height: var(--dsbn-lh-body);
	color: var(--dsbn-color-body);
}

.dsbn-image-link-card__actions {
	position: static;
	margin: 0;
}

.dsbn-image-link-card__link {
	position: static;
}

.dsbn-image-link-card__link .wp-block-button__link {
	position: absolute;
	inset: -1px;
	z-index: 2;
	display: block;
	width: auto;
	height: auto;
	padding: 0;
	border: 0;
	border-radius: inherit;
	background: transparent;
	color: transparent;
	font-size: 0;
}

/* See .dsbn-card__link's matching rule above for why. */
.dsbn-image-link-card__link .wp-block-button__link:not([href]),
.dsbn-image-link-card__link .wp-block-button__link[href="#"],
.dsbn-image-link-card__link .wp-block-button__link[href=""] {
	pointer-events: none;
}

.dsbn-image-link-card__link .wp-block-button__link:is([href]):not([href="#"]):not([href=""])::after {
	position: absolute;
	right: 2rem;
	bottom: 1.75rem;
	display: block;
	width: 1.6rem;
	height: 1.6rem;
	background: var(--dsbn-color-ink);
	content: "";
	-webkit-mask: var(--dsbn-icon-chevron) center / contain no-repeat;
	mask: var(--dsbn-icon-chevron) center / contain no-repeat;
	transition: transform var(--dsbn-transition), background var(--dsbn-transition);
}

.dsbn-image-link-card:hover .dsbn-image-link-card__link .wp-block-button__link:is([href]):not([href="#"]):not([href=""])::after,
.dsbn-image-link-card:focus-within .dsbn-image-link-card__link .wp-block-button__link:is([href]):not([href="#"]):not([href=""])::after {
	background: var(--dsbn-color-ink);
	transform: translateX(4px);
}

@media (max-width: 768px) {
	.dsbn-image-link-card {
		max-width: none;
		border-radius: 32px;
	}

	.dsbn-image-link-card__media img {
		aspect-ratio: 1.8 / 1;
	}

	.dsbn-image-link-card__body {
		padding: 1.5rem 3.75rem 2.75rem 1.5rem;
	}

	.dsbn-image-link-card__actions {
		margin: 0;
	}

	.dsbn-image-link-card__link .wp-block-button__link::after {
		right: 1.25rem;
		bottom: 1.25rem;
	}
}

/* =============================================================
   VIDEO CARD  (half image + full image)
   ============================================================= */
.dsbn-video-card {
	border-radius: 46px;
	overflow: hidden;
}

/* Half-image: text left, image right */
.dsbn-video-card--half {
	display: grid;
	grid-template-columns: 1fr 1fr;
	background: var(--dsbn-video-half-bg);
}

.dsbn-video-card--half .dsbn-video-card__body {
	padding: clamp(1.5rem, 4vw, 3rem);
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 0.75rem;
}

.dsbn-video-card__media {
	position: relative;
	min-height: 240px;
	background-size: cover;
	background-position: center;
}

.dsbn-video-card__title {
	margin: 0;
	font-family: var(--dsbn-font-heading);
	font-size: var(--dsbn-fs-section);
	font-weight: var(--dsbn-fw-body);
	color: var(--dsbn-color-ink);
	text-wrap: balance;
}

/* Half card sits on a light-blue wash — heading uses brand blue. */
.dsbn-video-card--half .dsbn-video-card__title {
	color: var(--dsbn-color-eyebrow);
}

.dsbn-video-card .dsbn-eyebrow {
	font-weight: var(--dsbn-fw-semibold);
}

/* Full-image: editable Cover block, gradient overlay + overlaid text */
.dsbn-video-card--full {
	min-height: 580px;
	color: #fff;
}

.dsbn-video-card--full .wp-block-cover__inner-container {
	width: 100%;
}

.dsbn-video-card--full .dsbn-video-card__body {
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
	padding: clamp(1.5rem, 4vw, 3rem);
	width: 100%;
}

.dsbn-video-card--full .dsbn-video-card__title,
.dsbn-video-card--full .dsbn-eyebrow,
.dsbn-video-card--full .dsbn-body {
	color: #fff;
}

@media (max-width: 768px) {
	.dsbn-video-card--half {
		grid-template-columns: 1fr;
	}

	.dsbn-video-card--half .dsbn-video-card__media {
		order: -1;
		min-height: 200px;
	}
}

/* =============================================================
   CAROUSEL  (tabbed video series)
   ============================================================= */
.dsbn-carousel-tabs__tablist {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	border-bottom: 1px solid var(--dsbn-color-line);
	margin-bottom: 1.5rem;
}

.dsbn-carousel-tabs__tab {
	appearance: none;
	background: none;
	border: 0;
	border-bottom: 3px solid transparent;
	padding: 0.75rem 1rem;
	font-family: var(--dsbn-font-body);
	font-size: var(--dsbn-fs-body);
	font-weight: var(--dsbn-fw-bold);
	color: var(--dsbn-color-body);
	cursor: pointer;
	transition: color var(--dsbn-transition), border-color var(--dsbn-transition);
}

.dsbn-carousel-tabs__tab[aria-selected="true"] {
	color: var(--dsbn-color-primary);
	border-bottom-color: var(--dsbn-color-accent-blue);
}

.dsbn-carousel-tabs__panel[hidden] {
	display: none;
}

.dsbn-carousel-tabs__panel {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: clamp(1.5rem, 4vw, 3rem);
	align-items: center;
}

.dsbn-carousel-tabs__media {
	aspect-ratio: 16 / 9;
	border-radius: var(--dsbn-radius-md);
	background: var(--dsbn-color-surface-alt);
	background-size: cover;
	background-position: center;
}

/* Editable thumbnail (wp:image renders a <figure>). */
.dsbn-carousel-tabs__media.wp-block-image {
	margin: 0;
	overflow: hidden;
}

.dsbn-carousel-tabs__media.wp-block-image img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	border-radius: var(--dsbn-radius-md);
}

.dsbn-carousel-tabs__body {
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
}

/* Text-only variant (no media column) — used by the generic "Carousel Tabs
   (Text)" pattern. Same tab-building/switching JS as the video variant
   (dsbn-patterns.js only looks for .dsbn-carousel-tabs__panel), just a
   single full-width column instead of the media+body grid — same "no
   image" convention as .dsbn-media-row--no-image (fills the container,
   no artificial width cap). */
.dsbn-carousel-tabs__panel.dsbn-carousel-tabs__panel--text {
	grid-template-columns: 1fr;
}

@media (max-width: 768px) {
	.dsbn-carousel-tabs__panel {
		grid-template-columns: 1fr;
	}
}

/* =============================================================
   CARD CAROUSEL
   ============================================================= */
.dsbn-section--card-carousel {
	overflow: hidden;
	background: var(--dsbn-color-surface-alt);
}

.dsbn-card-carousel {
	--dsbn-card-carousel-gap: clamp(1.25rem, 2.5vw, 2rem);
	--dsbn-card-carousel-card: clamp(20rem, 30vw, 27.25rem);
	--dsbn-card-carousel-visible: 3;
	position: relative;
	width: 100vw;
	margin-left: calc(50% - 50vw);
	max-width: none;
}

.dsbn-card-carousel::before,
.dsbn-card-carousel::after {
	display: none;
}

.dsbn-card-carousel__controls {
	display: flex;
	justify-content: flex-end;
	gap: 0.75rem;
	width: 100%;
	/* border-box so the right-inset padding below eats into the 100% width
	   instead of adding to it — this theme has no universal box-sizing
	   reset, so without this the box rendered 100% + padding-right wide,
	   pushing the right-justified arrows past the true right edge. */
	box-sizing: border-box;
	/* Matches .dsbn-card-carousel__track's own right-inset formula exactly
	   (below) so the arrows' right edge lines up with the last visible
	   card's right edge. The old `width: min(100% - 2rem, var(--dsbn-shell))`
	   centered this row against the shared page shell width, which has no
	   relation to where the visible N-card group actually centers itself
	   inside the full-bleed (100vw) track — the two edges rarely matched. */
	padding-right: max(1rem, calc((100vw - ((var(--dsbn-card-carousel-card) * var(--dsbn-card-carousel-visible)) + (var(--dsbn-card-carousel-gap) * (var(--dsbn-card-carousel-visible) - 1)))) / 2));
	margin: 0 0 1.5rem;
}

.dsbn-card-carousel__control {
	appearance: none;
	display: grid;
	place-items: center;
	/* 44px — WCAG 2.5.5/2.5.8 touch-target guideline. Was 2.5rem (40px);
	   shared by the "Programs and supports" carousel arrows and the
	   Stories modal's prev/next buttons. */
	width: 2.75rem;
	height: 2.75rem;
	border: 1px solid var(--dsbn-color-line);
	border-radius: 999px;
	background: var(--dsbn-color-surface);
	cursor: pointer;
	transition: background var(--dsbn-transition), transform var(--dsbn-transition), opacity var(--dsbn-transition);
}

.dsbn-card-carousel__control::before {
	display: block;
	width: 1.25rem;
	height: 1.25rem;
	background: var(--dsbn-color-ink);
	content: "";
	-webkit-mask: var(--dsbn-icon-chevron) center / contain no-repeat;
	mask: var(--dsbn-icon-chevron) center / contain no-repeat;
}

.dsbn-card-carousel__control--prev::before {
	transform: rotate(180deg);
}

.dsbn-card-carousel__control:hover,
.dsbn-card-carousel__control:focus-visible {
	background: var(--dsbn-color-surface-alt);
	transform: translateY(-2px);
}

.dsbn-card-carousel__control:disabled {
	cursor: default;
	opacity: 0.35;
	transform: none;
}

.dsbn-card-carousel__viewport {
	width: 100%;
	overflow-x: auto;
	overflow-y: hidden;
	scroll-behavior: smooth;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	-webkit-overflow-scrolling: touch;
}

.dsbn-card-carousel.is-animating .dsbn-card-carousel__viewport {
	scroll-snap-type: none;
	/* The JS arrow-click tween (dsbn-patterns.js) already eases scrollLeft
	   itself frame-by-frame — with the base rule's `scroll-behavior: smooth`
	   still active, the browser ALSO tries to smoothly animate to every one
	   of those per-frame values, fighting the JS's own easing and producing
	   a stuttery, stair-stepped motion instead of one fluid scroll. */
	scroll-behavior: auto;
}

.dsbn-card-carousel.is-animating .dsbn-card-carousel__track {
	pointer-events: none;
}

.dsbn-card-carousel__viewport::-webkit-scrollbar {
	display: none;
}

.dsbn-card-carousel__track {
	display: flex;
	align-items: stretch;
	gap: var(--dsbn-card-carousel-gap);
	width: max-content;
	min-width: 100%;
	padding: 0 max(1rem, calc((100vw - ((var(--dsbn-card-carousel-card) * var(--dsbn-card-carousel-visible)) + (var(--dsbn-card-carousel-gap) * (var(--dsbn-card-carousel-visible) - 1)))) / 2)) 1rem;
}

.dsbn-card-carousel__item {
	position: relative;
	display: flex;
	flex: 0 0 var(--dsbn-card-carousel-card);
	flex-direction: column;
	padding: 0;
	gap: 0;
	border: 1px solid var(--dsbn-color-card-border);
	border-radius: 32px;
	background: var(--dsbn-color-surface);
	overflow: hidden;
	scroll-snap-align: center;
	transition: filter var(--dsbn-transition), opacity var(--dsbn-transition), transform var(--dsbn-transition), box-shadow var(--dsbn-transition);
}

.dsbn-card-carousel__item.is-outside-blurred {
	filter: blur(2px);
	opacity: 0.62;
	pointer-events: none;
}

.dsbn-card-carousel:not(.is-animating) .dsbn-card-carousel__item:has(.dsbn-card-carousel__link .wp-block-button__link:is([href]):not([href="#"]):not([href=""])):hover,
.dsbn-card-carousel:not(.is-animating) .dsbn-card-carousel__item:has(.dsbn-card-carousel__link .wp-block-button__link:is([href]):not([href="#"]):not([href=""])):focus-within {
	transform: translateY(-4px);
	box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
}

.dsbn-card-carousel__media {
	width: 100%;
	margin: 0;
}

.dsbn-card-carousel__media img {
	display: block;
	width: 100%;
	aspect-ratio: 1.78 / 1;
	object-fit: cover;
}

.dsbn-card-carousel__body {
	position: static;
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: 0.85rem;
	padding: 2rem 2rem 2.5rem;
}

.dsbn-card-carousel__eyebrow {
	margin: 0;
	font-family: var(--dsbn-font-body);
	font-size: 0.875rem;
	font-weight: var(--dsbn-fw-bold);
	line-height: 1.2;
	text-transform: uppercase;
	color: var(--dsbn-color-eyebrow);
}

.dsbn-card-carousel__title {
	margin: 0;
	font-family: var(--dsbn-font-body);
	font-size: var(--dsbn-fs-body-header);
	font-weight: var(--dsbn-fw-bold);
	line-height: var(--dsbn-lh-heading);
	color: var(--dsbn-color-ink);
	text-wrap: balance;
}

.dsbn-card-carousel__text {
	margin: 0;
	font-family: var(--dsbn-font-body);
	font-size: 1rem;
	font-weight: var(--dsbn-fw-medium);
	line-height: 1.6;
	color: var(--dsbn-color-body);
}

.dsbn-card-carousel__actions,
.dsbn-card-carousel__link {
	position: static;
	margin: 0;
}

.dsbn-card-carousel__link .wp-block-button__link {
	position: absolute;
	inset: -1px;
	z-index: 2;
	display: block;
	width: auto;
	height: auto;
	padding: 0;
	border: 0;
	border-radius: inherit;
	background: transparent;
	color: transparent;
	font-size: 0;
}

/* See .dsbn-card__link's matching rule above for why. */
.dsbn-card-carousel__link .wp-block-button__link:not([href]),
.dsbn-card-carousel__link .wp-block-button__link[href="#"],
.dsbn-card-carousel__link .wp-block-button__link[href=""] {
	pointer-events: none;
}

.dsbn-card-carousel__link .wp-block-button__link:is([href]):not([href="#"]):not([href=""])::after {
	position: absolute;
	right: 2rem;
	bottom: 1.75rem;
	display: block;
	width: 1.5rem;
	height: 1.5rem;
	background: var(--dsbn-color-ink);
	content: "";
	-webkit-mask: var(--dsbn-icon-chevron) center / contain no-repeat;
	mask: var(--dsbn-icon-chevron) center / contain no-repeat;
	transition: transform var(--dsbn-transition);
}

.dsbn-card-carousel:not(.is-animating) .dsbn-card-carousel__item:hover .dsbn-card-carousel__link .wp-block-button__link:is([href]):not([href="#"]):not([href=""])::after,
.dsbn-card-carousel:not(.is-animating) .dsbn-card-carousel__item:focus-within .dsbn-card-carousel__link .wp-block-button__link:is([href]):not([href="#"]):not([href=""])::after {
	transform: translateX(4px);
}

.dsbn-card-carousel__dots {
	display: flex;
	justify-content: center;
	gap: 0.5rem;
	margin-top: 1.25rem;
}

.dsbn-card-carousel__dot {
	appearance: none;
	width: 0.625rem;
	height: 0.625rem;
	padding: 0;
	border: 0;
	border-radius: 999px;
	background: #b8bec8;
	cursor: pointer;
	transition: background var(--dsbn-transition), transform var(--dsbn-transition), width var(--dsbn-transition);
}

.dsbn-card-carousel__dot[aria-current="true"] {
	width: 1.5rem;
	background: var(--dsbn-color-primary);
}

@media (max-width: 1100px) {
	.dsbn-card-carousel {
		--dsbn-card-carousel-card: min(34vw, 22rem);
		--dsbn-card-carousel-visible: 2;
	}

	.dsbn-card-carousel__viewport {
		scroll-snap-type: none;
	}
}

@media (max-width: 640px) {
	.dsbn-card-carousel {
		--dsbn-card-carousel-card: min(82vw, 24rem);
		--dsbn-card-carousel-visible: 1;
	}

	.dsbn-card-carousel__viewport {
		scroll-snap-type: x mandatory;
	}

	.dsbn-card-carousel::before,
	.dsbn-card-carousel::after {
		display: none;
	}

	.dsbn-card-carousel__controls {
		margin-bottom: 1rem;
	}

	.dsbn-card-carousel__track {
		padding-inline: max(1rem, calc((100vw - var(--dsbn-card-carousel-card)) / 2));
	}
}

@media (max-width: 520px) {
	.dsbn-card-carousel {
		--dsbn-card-carousel-gap: 0.75rem;
	}

	.dsbn-card-carousel__controls {
		justify-content: center;
		/* Base rule's right-inset only makes sense paired with flex-end —
		   centered arrows shouldn't be skewed left by leftover padding. */
		padding-right: 0;
	}

	.dsbn-card-carousel__body {
		padding: 1.5rem 1.5rem 2.75rem;
	}

	.dsbn-card-carousel__link .wp-block-button__link::after {
		right: 1.5rem;
		bottom: 1.25rem;
	}
}

@media (max-width: 340px) {
	.dsbn-card-carousel {
		--dsbn-card-carousel-card: calc(100vw - 2rem);
	}

	.dsbn-card-carousel__item.is-outside-blurred {
		filter: none;
		opacity: 0;
	}
}

@media (prefers-reduced-motion: reduce) {

	.dsbn-btn,
	.wp-block-button.dsbn-btn>.wp-block-button__link,
	.dsbn-home-menu::before,
	.dsbn-home-menu__item,
	.dsbn-home-menu__icon,
	.dsbn-card,
	.dsbn-card__link .wp-block-button__link::after,
	.dsbn-news-card,
	.dsbn-news-card__link .wp-block-button__link::after,
	.dsbn-image-link-card,
	.dsbn-image-link-card__link .wp-block-button__link::after,
	.dsbn-carousel-tabs__tab,
	.dsbn-card-carousel__control,
	.dsbn-card-carousel__item,
	.dsbn-card-carousel__link .wp-block-button__link::after,
	.dsbn-card-carousel__dot,
	.dsbn-faq__item,
	.dsbn-faq__item summary::after,
	.dsbn-icon-card,
	.dsbn-icon-card summary::after,
	.dsbn-icon-card--static,
	.dsbn-video-modal__close {
		transition-duration: 0.01ms;
	}

	.dsbn-card-carousel__viewport {
		scroll-behavior: auto;
	}
}

/* =============================================================
   MEDIA ROW  (image left / right / none / enclosed)
   ============================================================= */
.dsbn-media-row {
	display: grid;
	grid-template-columns: 2fr 1fr;
	gap: clamp(1.5rem, 4vw, 3rem);
	align-items: center;
}

.dsbn-media-row__body {
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
}

.dsbn-media-row__media img {
	display: block;
	max-width: 100%;
	height: auto;
	margin-inline: auto;
	border-radius: 46px;
}

/* image-right keeps source order; image-left flips media first */
.dsbn-media-row--image-left {
	grid-template-columns: 1fr 2fr;
}

.dsbn-media-row--image-left .dsbn-media-row__media {
	order: -1;
}

/* No-image: single centred column */
.dsbn-media-row--no-image {
	grid-template-columns: 1fr;
}

/* Enclosed: wrap the row in a card */
.dsbn-media-row--enclosed {
	grid-template-columns: 3fr 1fr;
	padding: clamp(1.5rem, 4vw, 2.5rem);
	border-radius: 46px;
	border: 1px solid #D5D5D5;
	background: var(--dsbn-color-surface);
}

/* Enclosed + image-left needs the column ratio mirrored (text stays the wide 3fr track) */
.dsbn-media-row--enclosed.dsbn-media-row--image-left {
	grid-template-columns: 1fr 3fr;
}

/* Enclosed + no-image: single centred column with the card chrome, no media column ratio */
.dsbn-media-row--enclosed.dsbn-media-row--no-image {
	grid-template-columns: 1fr;
}

/* Enclosed "bleed": the image fills the card edge-to-edge instead of sitting inside
   the card's padding. Padding moves onto the text column only; the container clips
   the image's outer corners to its own 46px radius via overflow:hidden. */
.dsbn-media-row--enclosed.dsbn-media-row--bleed {
	align-items: stretch;
	padding: 0;
	overflow: hidden;
}

.dsbn-media-row--enclosed.dsbn-media-row--bleed .dsbn-media-row__body {
	padding: clamp(1.5rem, 4vw, 2.5rem);
}

.dsbn-media-row--enclosed.dsbn-media-row--bleed .dsbn-media-row__media {
	align-self: stretch;
	height: 100%;
}

.dsbn-media-row--enclosed.dsbn-media-row--bleed .dsbn-media-row__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	border-radius: 0;
}

/* Container query (not a viewport media query): responds to the actual
   rendered width of the nearest `.dsbn-container` ancestor, not the
   viewport. This matters because a media row can end up narrow even on a
   "desktop" viewport — e.g. the sub-page-with-nav template's sidebar grid
   squeezes the content column well below 768px while the browser viewport
   is still 1400px+. A viewport media query would never fire there, leaving
   the 2-column grid intact with an unreasonably narrow text column (and,
   for the bleed variant, an image stretched to match an inflated text-driven
   row height). Container queries fix this regardless of viewport size. */
@container (max-width: 768px) {
	.dsbn-media-row {
		grid-template-columns: 1fr;
	}

	/* Higher-specificity ratio rule .dsbn-media-row--enclosed.dsbn-media-row--image-left
	   (1fr 3fr, defined above for desktop) would otherwise beat the single-column collapse
	   above at equal specificity — re-assert 1fr here so mobile always stacks to one column. */
	.dsbn-media-row--enclosed.dsbn-media-row--image-left {
		grid-template-columns: 1fr;
	}

	.dsbn-media-row--image-left .dsbn-media-row__media {
		order: -1;
	}

	.dsbn-media-row--enclosed.dsbn-media-row--bleed .dsbn-media-row__media {
		height: 260px;
	}
}

/* =============================================================
   FAQ ACCORDION  (native <details>, zero-JS)
   ============================================================= */
.dsbn-faq {
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
}

/* Click anywhere on the item toggles it (js/dsbn-patterns.js initFaqItem),
   not just the summary/question row — cursor should read that way too. */
.dsbn-faq__item {
	box-sizing: border-box;
	border: 1px solid var(--dsbn-color-card-border);
	border-radius: 26px;
	background: var(--dsbn-color-surface);
	cursor: pointer;
	transition: box-shadow var(--dsbn-transition);
}

.dsbn-faq__item[open] {
	box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06);
}

.dsbn-faq__item summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	padding: 1.5rem 1.75rem;
	font-family: var(--dsbn-font-body);
	/* Was a hardcoded 1.875rem (30px) — which is exactly --dsbn-fs-body-header's
	   max, so the intent was "body header size", but typing the value meant it
	   never got the token's fluid behaviour and it sat flat at 30px from
	   1440px all the way down to 769px, then a ≤768px override dropped it 28%
	   in a single pixel to 21.6px.

	   Still too large even fixed: on a real long question ("What is the DSBN
	   doing to support and keep students with prevalent medical conditions
	   safe?") 30px wrapped to two lines and made a plain-looking FAQ list feel
	   heavy stacked. Dropped to its own smaller clamp (24px max, well below
	   --dsbn-fs-body-header), now --dsbn-fs-body-header-sm, and to semibold
	   (matching the weight h3/card titles use elsewhere) rather than bold —
	   together that's enough for the same question to fit on one line.
	   Verified against the live page: this is what actually fixed it, not
	   weight alone (bold -> semibold at the old 30px still wrapped to two
	   lines; the size had to come down). */
	font-size: var(--dsbn-fs-body-header-sm);
	font-weight: var(--dsbn-fw-semibold);
	color: var(--dsbn-color-ink);
	cursor: pointer;
	list-style: none;
}

.dsbn-faq__item summary::-webkit-details-marker {
	display: none;
}

.dsbn-faq__item summary::after {
	content: "";
	flex-shrink: 0;
	width: 1.4rem;
	height: 1.4rem;
	background-color: var(--dsbn-color-ink);
	-webkit-mask: var(--dsbn-icon-plus) center / contain no-repeat;
	mask: var(--dsbn-icon-plus) center / contain no-repeat;
	transition: transform 0.3s ease, background-color 0.3s ease;
}

.dsbn-faq__item[open] summary::after {
	-webkit-mask-image: var(--dsbn-icon-minus);
	mask-image: var(--dsbn-icon-minus);
	background-color: #4B6EBC;
	transform: rotate(180deg);
}

/* Smooth expand animation for FAQ + icon cards — height driven by JS */
.dsbn-faq__item.is-sliding,
.dsbn-icon-card__expand.is-sliding {
	overflow: hidden;
	transition: height 0.32s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

/* =============================================================
   EXPANDABLE ICON CARDS  (native <details>, zero-JS)
   ============================================================= */
.dsbn-icon-cards {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: clamp(1rem, 2.5vw, 1.5rem);
	/* start (not the grid default stretch) so an opened <details> card
	   (Expandable variant) grows on its own without forcing every other
	   still-closed card in the row to stretch and match its height. */
	align-items: start;
}

/* Static/CTA cards (.dsbn-icon-card--static, not <details>) have no such
   independent-height reason — a 2-line heading in one card next to 1-line
   headings in its siblings otherwise leaves them visibly shorter. Scoped
   via :has() so pure Expandable rows (no --static cards) keep the
   behavior above untouched. */
.dsbn-icon-cards:has(.dsbn-icon-card--static) {
	align-items: stretch;
}

/* 4-across variant (the 4/6 Card Row - Icon patterns) — same base rule,
   just a different desktop column count; the 900px/560px collapse below
   still applies since it targets .dsbn-icon-cards generically. */
.dsbn-icon-cards--four {
	grid-template-columns: repeat(4, minmax(0, 1fr));
}

.dsbn-icon-card {
	position: relative;
	box-sizing: border-box;
	border: 1px solid var(--dsbn-color-line);
	border-radius: 46px;
	background: var(--dsbn-color-surface);
	padding: 1.75rem;
	transition: box-shadow var(--dsbn-transition), transform var(--dsbn-transition);
}

/* Expandable variant: a Group card (like --static) wrapping a nested
   <details> (.dsbn-icon-card__expand) for the toggle + body. Structured this
   way so the icon can be a real Image block the editor's DSBN Icon /
   Background pickers attach to — a core/details summary is stored as
   rich-text and can't hold an image block, which is why the icon used to be
   uneditable inline markup on expandable cards. */
.dsbn-icon-card--expandable {
	display: flex;
	flex-direction: column;
	gap: 1rem;
}

.dsbn-icon-card:has(.dsbn-icon-card__expand[open]) {
	box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06);
}

/* The whole card is the click target (js/dsbn-patterns.js
   initExpandableIconCard), not just the summary text, so the pointer
   cursor should read that way everywhere on the card. */
.dsbn-icon-card--expandable {
	cursor: pointer;
}

.dsbn-icon-card__expand summary {
	cursor: pointer;
	list-style: none;
}

.dsbn-icon-card__expand summary::-webkit-details-marker {
	display: none;
}

/* Toggle button — top-right circle (+ / ×). Drawn on the CARD itself (not
   the summary) so it's reliably positioned to the card's own corner: the
   card group is position:relative, whereas the nested details/summary /
   their block wrappers can create their own containing block and drag an
   absolutely-positioned summary::after down to the bottom. pointer-events
   are off so it never blocks selecting the icon; the summary/title stays
   the toggle target. State flips via :has() when the details is open. */
.dsbn-icon-card--expandable::after {
	content: "";
	position: absolute;
	top: 1.5rem;
	right: 1.5rem;
	width: 2rem;
	height: 2rem;
	border-radius: 50%;
	border: 1.5px solid #D8D8D8;
	background-color: transparent;
	background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 5v14M5 12h14' fill='none' stroke='%23D8D8D8' stroke-width='2.2' stroke-linecap='round'/></svg>");
	background-size: 1rem;
	background-repeat: no-repeat;
	background-position: center;
	pointer-events: none;
	transition: border-color 0.3s ease, background-color 0.3s ease, transform 0.3s ease;
}

.dsbn-icon-card--expandable:has(.dsbn-icon-card__expand[open])::after {
	border-color: #4B6EBC;
	background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6 6l12 12M18 6L6 18' fill='none' stroke='%234B6EBC' stroke-width='2' stroke-linecap='round'/></svg>");
	transform: rotate(90deg);
}

.dsbn-icon-card__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 3.75rem;
	height: 3.75rem;
	margin: 0;
	flex-shrink: 0;
	border-radius: 21px;
	background: var(--dsbn-surface-blue-soft);
	/* Dark by default; each gradient below overrides it with a shade of its
	   own hue. Drives the masked ::before below. */
	--dsbn-icon-color: #06213E;
}

/* DSBN icon-background gradient set (the "DSBN Icon Background" picker's
   options). Each also sets --dsbn-icon-color: a saturated mid-shade of the
   gradient's own hue, which colors the masked icon. Class names, gradient
   values, and icon colors must stay in sync with the swatch previews in
   js/icon-card-picker.js. */
.dsbn-icon-card__icon.is-icon-grad-rose {
	background: linear-gradient(180deg, #FAE8E9 0%, #F7AEB2 100%);
	--dsbn-icon-color: #D85F86;
}

.dsbn-icon-card__icon.is-icon-grad-green {
	background: linear-gradient(180deg, #E8FAEC 0%, #ABEBAB 100%);
	--dsbn-icon-color: #3FA062;
}

.dsbn-icon-card__icon.is-icon-grad-blue {
	background: linear-gradient(151deg, #E7F2FC 0%, #BCD3FF 100%);
	--dsbn-icon-color: #4A7CD1;
}

.dsbn-icon-card__icon.is-icon-grad-yellow {
	background: linear-gradient(180deg, #FFFDE0 0%, #FCF2A5 100%);
	--dsbn-icon-color: #C99A24;
}

.dsbn-icon-card__icon.is-icon-grad-lavender {
	background: linear-gradient(151deg, #F8E7FC 0%, #E5BCFF 100%);
	--dsbn-icon-color: #A063D4;
}

.dsbn-icon-card__icon.is-icon-grad-orange {
	background: linear-gradient(180deg, #FFF0DB 0%, #F7C796 100%);
	--dsbn-icon-color: #E37E33;
}

.dsbn-icon-card__icon.is-icon-grad-sky {
	background: linear-gradient(180deg, #E8EFFA 0%, #AEDEF7 100%);
	--dsbn-icon-color: #3E9FD6;
}

.dsbn-icon-card__icon.is-icon-grad-violet {
	background: linear-gradient(180deg, #F4DBFF 0%, #DD96F7 100%);
	--dsbn-icon-color: #B94FD6;
}

/* The icon renders as a CSS mask, not the raw <img> — the real <img> stays
   in the DOM (hidden) so it remains a proper Image block for the editor's
   DSBN Icon picker. The ::before is filled with --dsbn-icon-color (dark by
   default, a shade of the gradient when one is chosen); its shape comes
   from a per-icon mask-image generated in functions.php
   (dsbn_icon_card_mask_css(), keyed by the figure's is-cardicon-<slug>
   class). Works because the mask uses each SVG's alpha silhouette, ignoring
   its own baked-in color entirely. The <img> is hidden three ways
   (display + visibility + zero size) so no editor/core image rule can
   re-show the raw coloured SVG on top of the mask, and the ::before is
   absolutely centred so it never depends on the figure staying flex. */
.dsbn-icon-card__icon {
	position: relative;
}

.dsbn-icon-card__icon img {
	display: none !important;
	visibility: hidden;
	width: 0;
	height: 0;
}

.dsbn-icon-card__icon::before {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	width: 1.75rem;
	height: 1.75rem;
	background-color: var(--dsbn-icon-color);
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
}

.dsbn-icon-card__title {
	margin: 0;
	font-family: var(--dsbn-font-body);
	font-size: var(--dsbn-fs-body-header);
	font-weight: var(--dsbn-fw-bold);
	line-height: var(--dsbn-lh-heading);
	color: var(--dsbn-color-ink);
	text-wrap: balance;
}

.pg-contents .dsbn-section :where(.dsbn-heading, .dsbn-card__title, .dsbn-news-card__title, .dsbn-image-link-card__title, .dsbn-card-carousel__title, .dsbn-faq__question, .dsbn-icon-card__title, .dsbn-hub-hero__title) {
	font-family: inherit;
}

.pg-contents .dsbn-section .dsbn-heading,
.pg-contents .dsbn-section .dsbn-hub-hero__title {
	font-family: var(--dsbn-font-heading);
}

.pg-contents .dsbn-section :where(.dsbn-card__title, .dsbn-news-card__title, .dsbn-image-link-card__title, .dsbn-card-carousel__title, .dsbn-faq__question, .dsbn-icon-card__title) {
	font-family: var(--dsbn-font-body);
}

/* Real content pages (page.php, page-hub.php, landing-page.php, the
   sub-page templates) already give `.pg-contents` its own horizontal
   gutter via the enclosing `.dsbn-inside-layout`/sidebar grid — a
   `.dsbn-section` inserted as page content doesn't need its own
   padding-inline on top of that (it was double-guttering the content,
   squeezing patterns like Image Left Enclosed - Bleed narrower than
   intended). The homepage and any other bare, non-`.pg-contents` usage
   of `.dsbn-section` keeps its own padding-inline as normal. Only applies
   to sections with NO background of their own — see the
   `.dsbn-section.has-background` breakout below, which needs its own
   padding-inline back (a colored section can't rely on the layout's
   gutter once it's broken out past it). */
.pg-contents .dsbn-section:not(.has-background) {
	padding-inline: 0;
}

/* A colored/gradient section is still confined to the shell-width content
   column on these templates, unlike the homepage where `.dsbn-section`'s
   parent already IS the full viewport — it reads as a color-filled box
   sitting inside the page rather than a true full-bleed band. Break it out
   to the real viewport edge (same negative-margin technique as
   `.dsbn-container .alignfull` above), then give it back its own
   padding-inline since it's no longer inside the layout's gutter — the
   inner `.dsbn-container` still re-centers the actual content to shell
   width, so this only changes how far the BACKGROUND color reaches.
   Scoped to single-column layouts only (no-sidebar templates, and
   with-sidebar templates whose sidebar happens to be empty) — a full-bleed
   band would run behind/past the sidebar column on templates that still
   have one, which reads as broken rather than intentional. */
.dsbn-inside-layout--no-sidebar .pg-contents .dsbn-section.has-background,
.dsbn-inside-layout:has(.dsbn-inside-sidebar:empty) .pg-contents .dsbn-section.has-background {
	width: 100vw;
	max-width: 100vw;
	margin-left: calc(50% - 50vw);
	margin-right: calc(50% - 50vw);
	padding-inline: var(--dsbn-gutter);
}

/* .dsbn-hub-page__full is .pg-contents too, but (unlike the sidebar-narrowed
   templates the rule above targets) it's genuinely full-bleed — restore its
   sections' normal side gutter so content doesn't touch the screen edges. */
.dsbn-hub-page__full.pg-contents .dsbn-section {
	padding-inline: var(--dsbn-gutter);
}

/* Editors commonly place a heading or intro paragraph directly in a
   section, as a sibling to the .dsbn-container that wraps the section's
   actual row (e.g. a heading above an icon-cards row, or an intro
   paragraph above a Carousel Tabs pattern) — same convention used
   throughout .pg-contents pages. On the sidebar-narrowed sub-page
   templates this looks fine because the OUTER .dsbn-inside-layout already
   caps to --dsbn-shell, so .dsbn-container's own max-width never binds —
   sibling and row end up the same width either way. .dsbn-hub-page__full
   has no such outer cap: .dsbn-container is the FIRST place width gets
   constrained, so it centers itself narrower than an uncapped sibling,
   which just sits at the section's own edge — visibly misaligned from the
   row below it. Give the sibling the same shell-width cap + centering so
   the two line up. */
.dsbn-hub-page__full.pg-contents .dsbn-section > .wp-block-group__inner-container > .wp-block-heading,
.dsbn-hub-page__full.pg-contents .dsbn-section > .wp-block-group__inner-container > p {
	max-width: var(--dsbn-shell);
	margin-inline: auto;
	margin-bottom: clamp(1.5rem, 4vw, 2.5rem);
}

/* The sidebar (.dsbn-inside-sidebar) and the content column start at the
   exact same grid row top — but the first .dsbn-section's own top padding
   (--dsbn-section-pad) then pushes its actual heading/text down well
   below that shared top edge, while the sidebar box's content starts
   right at the top with much less padding of its own, making the two
   columns look misaligned even though they're structurally even. Drop
   just the FIRST section's top padding on with-sidebar templates so its
   content lines up with where the sidebar starts. Excludes single-column
   layouts (no sidebar to align with) — there this was zeroing a
   full-bleed background section's own top padding too, leaving its
   heading with no breathing room from the color's top edge. */
.dsbn-inside-layout:not(.dsbn-inside-layout--no-sidebar):not(:has(.dsbn-inside-sidebar:empty))>.dsbn-inside-content>.dsbn-section:first-child,
.dsbn-hub-page__layout>.dsbn-inside-content>.dsbn-section:first-child {
	padding-top: 0;
}

/* If the very first/last piece of page content is a full-bleed colored
   section (the breakout above), the layout's own top/bottom padding just
   leaves an awkward gap between it and the hero/footer — collapse that
   side so the color sits flush against them instead. Only meaningful on
   the same single-column contexts the breakout itself applies to. */
.dsbn-inside-layout--no-sidebar:has(>.dsbn-inside-content>.dsbn-section.has-background:first-child),
.dsbn-inside-layout:has(.dsbn-inside-sidebar:empty):has(>.dsbn-inside-content>.dsbn-section.has-background:first-child) {
	padding-top: 0;
}

.dsbn-inside-layout--no-sidebar:has(>.dsbn-inside-content>.dsbn-section.has-background:last-child),
.dsbn-inside-layout:has(.dsbn-inside-sidebar:empty):has(>.dsbn-inside-content>.dsbn-section.has-background:last-child) {
	padding-bottom: 0;
}

/* Static (non-expandable) icon cards — linked, no toggle */
.dsbn-icon-card--static {
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
	text-decoration: none;
	color: inherit;
	cursor: default;
	transition: transform var(--dsbn-transition), box-shadow var(--dsbn-transition);
}

a.dsbn-icon-card--static {
	cursor: pointer;
}

a.dsbn-icon-card--static:hover {
	transform: translateY(-4px);
	box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
}

/* A linked icon card is whole-card clickable (see .dsbn-cta-link's stretched
   ::before), so it needs the same hover affordance every other linked card
   family already has. Gated on has-dsbn-link for the same reason they are —
   an unlinked card shouldn't imply it's clickable. */
.dsbn-icon-card:has(.dsbn-cta-link a:is([href]):not([href="#"]):not([href=""])):hover,
.dsbn-icon-card:has(.dsbn-cta-link a:is([href]):not([href="#"]):not([href=""])):focus-within {
	transform: translateY(-4px);
	box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
}

.dsbn-icon-card__desc {
	margin: 0;
	font-size: var(--dsbn-fs-body);
	font-weight: var(--dsbn-fw-medium);
	line-height: var(--dsbn-lh-body);
	color: var(--dsbn-color-body);
}

/* Separator line between summary and body. The line spans the full card
   width while the text stays aligned with the rest of the card — drawn as an
   absolutely-positioned ::before that bleeds out by the card's own padding,
   NOT the older negative-margin + matching-padding trick. The block editor
   zeroes margins on blocks (`.block-editor-block-list__block`), which killed
   the negative half of that pair and left the padding behind as a visible
   ~20px indent on the expanded content — this version has no margin for the
   editor to reset, so it renders identically in both places. */
.dsbn-icon-card__body {
	position: relative;
	padding-top: 3rem;
	margin-top: 0;
	font-size: var(--dsbn-fs-body);
	font-weight: var(--dsbn-fw-medium);
	line-height: var(--dsbn-lh-body);
	color: var(--dsbn-color-body);
}

.dsbn-icon-card__body::before {
	content: "";
	position: absolute;
	top: 1.75rem;
	/* Matches .dsbn-icon-card's own padding so the line reaches both card
	   edges (overridden alongside that padding at the 768px breakpoint). */
	left: -1.75rem;
	right: -1.75rem;
	height: 1px;
	background: var(--dsbn-color-line);
}

.dsbn-icon-card__body a {
	display: flex;
	align-items: center;
	gap: 0.3rem;
	width: fit-content;
	margin-top: 1rem;
	font-weight: var(--dsbn-fw-bold);
	color: var(--dsbn-btn-main);
	text-decoration: none;
}

/* No chevron — see .dsbn-cta-link above. This link says "Learn More" in
   words, and in this design system the chevron only stands in for a link
   that has no visible text of its own. */

/* An expandable card's "Learn More" is inline rich text inside the body
   paragraph, not a separate block that "Remove link" can delete — so on the
   published page it hides itself when there's no destination, rather than
   showing a CTA that goes nowhere. Plenty of these cards legitimately have
   no link at all.
   css/editor.css deliberately overrides this back to visible-but-dimmed in
   the editor: the text has to stay selectable there, or an editor can
   neither reword it nor paste in an external URL — which would leave the
   page picker as the only way to link one of these cards. */
.dsbn-icon-card__body a:not([href]),
.dsbn-icon-card__body a[href="#"],
.dsbn-icon-card__body a[href=""] {
	display: none;
}

@media (max-width: 900px) {
	.dsbn-icon-cards {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 560px) {
	.dsbn-icon-cards {
		grid-template-columns: 1fr;
	}
}

/* =============================================================
   CORE-BLOCK NORMALIZATION
   These patterns are built from editable core blocks
   (group / heading / paragraph / image / buttons / details).
   Core blocks add their own wrapper classes and default
   margins — neutralise them so our flex/grid `gap` controls
   spacing, then restyle as needed.
   ============================================================= */

/* Let our component `gap` own the vertical rhythm. */
.dsbn-hub-hero>*,
.dsbn-hub-hero__main>*,
.dsbn-hub-hero__nav>*,
.dsbn-card>*,
.dsbn-card__head>*,
.dsbn-card__body>*,
.dsbn-media-row__body>*,
.dsbn-video-card__body>*,
.dsbn-faq>*,
.dsbn-faq__item>* {
	margin-top: 0;
	margin-bottom: 0;
}

/* Core group keeps its child layout but we drive the box. */
.dsbn-hub-hero.wp-block-group,
.dsbn-hub-hero__main.wp-block-group,
.dsbn-card.wp-block-group,
.dsbn-card__head.wp-block-group,
.dsbn-card__body.wp-block-group,
.dsbn-card-row.wp-block-group,
.dsbn-media-row.wp-block-group,
.dsbn-media-row__body.wp-block-group,
.dsbn-faq.wp-block-group {
	margin: 0;
}

/* Editable images (wp:image renders a <figure>). */
.dsbn-media-row__media.wp-block-image,
.dsbn-video-card__media.wp-block-image {
	margin: 0;
}

.dsbn-media-row__media.wp-block-image img {
	display: block;
	max-width: 100%;
	height: auto;
	margin-inline: auto;
	border-radius: var(--dsbn-radius-md);
}

.dsbn-video-card__media.wp-block-image {
	height: 100%;
}

.dsbn-video-card__media.wp-block-image img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Decorative card arrow (replaces the old .dsbn-arrow element so
   the card body stays fully editable as core blocks). */
.dsbn-card::after {
	content: none;
	position: absolute;
	right: 1.5rem;
	bottom: 1.25rem;
	width: 1.75rem;
	height: 1.75rem;
	background-color: #808080;
	-webkit-mask: var(--dsbn-icon-chevron) center / contain no-repeat;
	mask: var(--dsbn-icon-chevron) center / contain no-repeat;
}

.dsbn-card--fill::after {
	display: none;
}

/* Play badge for the half video card — removed per design. */

.dsbn-faq__item> :not(summary) {
	padding: 0 1.25rem 1.25rem;
	font-size: var(--dsbn-fs-body);
	line-height: var(--dsbn-lh-body);
	color: var(--dsbn-color-body);
}

/* The reset above sets the same 1.25rem left padding on every answer
   child, including a List block — which zeroes out its normal indent
   and leaves the bullets flush with the paragraph text above them.
   Add it back so list items read as indented, not flush with the card. */
.dsbn-faq__item .wp-block-list {
	padding-left: 3rem;
}

/* Hub hero main column stacks its editable blocks. */
.dsbn-hub-hero__main {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 1rem;
}

/* Hub hero side nav as an editable core list. */
.dsbn-hub-hero__nav .wp-block-list {
	list-style: none;
	margin: 1rem 0 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
}

.dsbn-hub-hero__nav .wp-block-list li {
	margin: 0;
}

/* Classic themes can render Group block children inside a front-end
   .wp-block-group__inner-container. Mirror component layout onto that wrapper
   so grids/flex gaps survive after WordPress renders the saved blocks. */
:where(.dsbn-card-row, .dsbn-news-card-row, .dsbn-hub-hero, .dsbn-media-row, .dsbn-video-card--half, .dsbn-icon-cards, .dsbn-carousel-tabs__panel)>.wp-block-group__inner-container {
	display: grid;
	grid-column: 1 / -1;
	width: 100%;
}

.dsbn-carousel-tabs__panel>.wp-block-group__inner-container {
	grid-template-columns: 1fr 1fr;
	gap: clamp(1.5rem, 4vw, 3rem);
	align-items: center;
}

.dsbn-carousel-tabs__panel.dsbn-carousel-tabs__panel--text>.wp-block-group__inner-container {
	grid-template-columns: 1fr;
	max-width: 44rem;
}

.dsbn-card-row>.wp-block-group__inner-container {
	/* Column count responds to the row's ACTUAL available width via a
	   container query (.dsbn-container, its containing ancestor, already
	   declares container-type: inline-size), not viewport width. Measured
	   across a real sidebar+card-row page from 768px to 1600px viewport:
	   3 static columns stayed cramped (titles wrapping 3-4 lines) all the
	   way up to ~1500px viewport whenever a fixed-width sidebar shared the
	   row, while the exact same 3 columns looked fine at a NARROWER
	   viewport once the sidebar had stacked away — viewport width alone
	   can't tell those two cases apart, container width can. */
	grid-template-columns: 1fr;
	gap: clamp(1rem, 2.5vw, 1.75rem);
}

@container (min-width: 700px) {
	.dsbn-card-row>.wp-block-group__inner-container {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@container (min-width: 1100px) {
	.dsbn-card-row>.wp-block-group__inner-container {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

.dsbn-card-row--four>.wp-block-group__inner-container {
	grid-template-columns: repeat(4, minmax(0, 1fr));
}

.dsbn-news-card-row>.wp-block-group__inner-container {
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: clamp(1.5rem, 3vw, 3.25rem);
}

.dsbn-icon-cards>.wp-block-group__inner-container {
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: clamp(1rem, 2.5vw, 1.5rem);
	align-items: start;
}

.dsbn-hub-hero>.wp-block-group__inner-container {
	grid-template-columns: minmax(0, 1fr) minmax(0, 320px);
	gap: clamp(1.5rem, 4vw, 3rem);
	align-items: start;
}

.dsbn-video-card--half>.wp-block-group__inner-container {
	grid-template-columns: 1fr 1fr;
}

.dsbn-media-row>.wp-block-group__inner-container {
	grid-template-columns: 2fr 1fr;
	gap: clamp(1.5rem, 4vw, 3rem);
	align-items: center;
}

.dsbn-media-row--image-left>.wp-block-group__inner-container {
	grid-template-columns: 1fr 2fr;
}

.dsbn-media-row--no-image>.wp-block-group__inner-container {
	grid-template-columns: 1fr;
}

.dsbn-media-row--enclosed>.wp-block-group__inner-container {
	grid-template-columns: 3fr 1fr;
}

.dsbn-staff-card__row>.wp-block-group__inner-container {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
	gap: clamp(1.25rem, 3vw, 2rem);
	align-items: start;
}

/* Enclosed + image-left needs the column ratio mirrored here too (text stays
   the wide 3fr track) — classic-theme rendering makes this inner-container
   the real grid parent, not `.dsbn-media-row` itself, so this combo needs
   its own rule rather than relying on the single-class rules above (equal
   specificity, so whichever is declared last would otherwise win). */
.dsbn-media-row--enclosed.dsbn-media-row--image-left>.wp-block-group__inner-container {
	grid-template-columns: 1fr 3fr;
}

/* Enclosed + no-image needs the same combo treatment: single centred column,
   no media ratio — same equal-specificity cascade issue as the image-left
   combo above. */
.dsbn-media-row--enclosed.dsbn-media-row--no-image>.wp-block-group__inner-container {
	grid-template-columns: 1fr;
}

.dsbn-section-header>.wp-block-group__inner-container {
	display: flex;
	align-items: center;
	gap: clamp(1rem, 3vw, 2.5rem);
	width: 100%;
}

:where(.dsbn-card, .dsbn-card__head, .dsbn-card__body, .dsbn-hub-hero__main, .dsbn-media-row__body, .dsbn-video-card__body, .dsbn-faq, .dsbn-image-link-card, .dsbn-image-link-card__body, .dsbn-card-carousel__item, .dsbn-card-carousel__body, .dsbn-icon-card, .dsbn-carousel-tabs__body)>.wp-block-group__inner-container {
	display: flex;
	flex-direction: column;
	gap: inherit;
	width: 100%;
}

/* Trustee card mirror: when WP wraps the card's children in an
   inner-container, THAT wrapper becomes the flex parent — so the card's own
   align-items:center (and the photo's margin:0 auto, which editor.css zeroes
   out) never reaches the children. Recentre at the wrapper level. */
.dsbn-trustee-card>.wp-block-group__inner-container {
	align-items: center;
}

.dsbn-card--fill>.wp-block-group__inner-container,
.dsbn-image-link-card>.wp-block-group__inner-container,
.dsbn-card-carousel__item>.wp-block-group__inner-container {
	flex: 1;
}

.dsbn-card-carousel__viewport>.wp-block-group__inner-container {
	width: 100%;
	overflow: visible;
}

.dsbn-card-carousel__track>.wp-block-group__inner-container {
	display: flex;
	align-items: stretch;
	gap: var(--dsbn-card-carousel-gap);
	width: max-content;
	min-width: 100%;
	padding: 0 max(1rem, calc((100vw - ((var(--dsbn-card-carousel-card) * var(--dsbn-card-carousel-visible)) + (var(--dsbn-card-carousel-gap) * (var(--dsbn-card-carousel-visible) - 1)))) / 2)) 1rem;
}

:where(.dsbn-card-row, .dsbn-news-card-row, .dsbn-hub-hero, .dsbn-media-row, .dsbn-video-card--half, .dsbn-card-carousel__track, .dsbn-icon-cards, .dsbn-carousel-tabs__panel)>.wp-block-group__inner-container>.wp-block-group,
:where(.dsbn-card-row, .dsbn-news-card-row, .dsbn-hub-hero, .dsbn-media-row, .dsbn-video-card--half, .dsbn-card-carousel__track, .dsbn-icon-cards, .dsbn-carousel-tabs__panel)>.wp-block-group__inner-container>.wp-block-image {
	width: 100%;
	max-width: none;
	margin: 0;
}

@media (max-width: 1024px) {
	.dsbn-news-card-row>.wp-block-group__inner-container {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 1.5rem;
	}

	.dsbn-icon-cards>.wp-block-group__inner-container {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 768px) {

	.dsbn-card-row--four>.wp-block-group__inner-container,
	.dsbn-hub-hero>.wp-block-group__inner-container,
	.dsbn-video-card--half>.wp-block-group__inner-container,
	.dsbn-carousel-tabs__panel>.wp-block-group__inner-container {
		grid-template-columns: 1fr;
	}

	.dsbn-section-header>.wp-block-group__inner-container {
		align-items: flex-start;
		flex-direction: column;
	}
}

/* Media-row inner-container mirrors collapse via container query, not
   viewport media query — see the `.dsbn-media-row` @container rule above
   for why (classic-theme with-nav templates can squeeze this well under
   768px on an otherwise-desktop viewport). */
@container (max-width: 768px) {

	.dsbn-media-row>.wp-block-group__inner-container,
	.dsbn-media-row--image-left>.wp-block-group__inner-container,
	.dsbn-media-row--enclosed>.wp-block-group__inner-container,
	.dsbn-media-row--enclosed.dsbn-media-row--image-left>.wp-block-group__inner-container,
	.dsbn-staff-card__row>.wp-block-group__inner-container {
		grid-template-columns: 1fr;
	}
}

@media (max-width: 640px) {

	.dsbn-news-card-row>.wp-block-group__inner-container,
	.dsbn-icon-cards>.wp-block-group__inner-container {
		grid-template-columns: 1fr;
	}
}

/* Gutenberg wraps inner Group blocks in editor-only containers. Mirror the
   front-end layout onto those wrappers so pattern previews do not collapse
   into a single vertical column while editing. */
.editor-styles-wrapper :where(.dsbn-card-row, .dsbn-news-card-row, .dsbn-hub-hero, .dsbn-media-row, .dsbn-video-card--half, .dsbn-icon-cards, .dsbn-staff-card__row)>.block-editor-inner-blocks {
	width: 100%;
}

.editor-styles-wrapper :where(.dsbn-card-row, .dsbn-news-card-row, .dsbn-hub-hero, .dsbn-media-row, .dsbn-video-card--half, .dsbn-icon-cards, .dsbn-staff-card__row)>.block-editor-inner-blocks>.block-editor-block-list__layout {
	display: grid;
	width: 100%;
}

.editor-styles-wrapper .dsbn-card-row>.block-editor-inner-blocks>.block-editor-block-list__layout {
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: clamp(1rem, 2.5vw, 1.75rem);
}

.editor-styles-wrapper .dsbn-card-row--four>.block-editor-inner-blocks>.block-editor-block-list__layout {
	grid-template-columns: repeat(4, minmax(0, 1fr));
}

.editor-styles-wrapper .dsbn-news-card-row>.block-editor-inner-blocks>.block-editor-block-list__layout {
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: clamp(1.5rem, 3vw, 3.25rem);
}

.editor-styles-wrapper .dsbn-icon-cards>.block-editor-inner-blocks>.block-editor-block-list__layout {
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: clamp(1rem, 2.5vw, 1.5rem);
	align-items: start;
}

.editor-styles-wrapper .dsbn-hub-hero>.block-editor-inner-blocks>.block-editor-block-list__layout {
	grid-template-columns: minmax(0, 1fr) minmax(0, 320px);
	gap: clamp(1.5rem, 4vw, 3rem);
	align-items: start;
}

.editor-styles-wrapper .dsbn-video-card--half>.block-editor-inner-blocks>.block-editor-block-list__layout {
	grid-template-columns: 1fr 1fr;
}

.editor-styles-wrapper .dsbn-media-row>.block-editor-inner-blocks>.block-editor-block-list__layout {
	grid-template-columns: 2fr 1fr;
	gap: clamp(1.5rem, 4vw, 3rem);
	align-items: center;
}

.editor-styles-wrapper .dsbn-media-row--image-left>.block-editor-inner-blocks>.block-editor-block-list__layout {
	grid-template-columns: 1fr 2fr;
}

.editor-styles-wrapper .dsbn-media-row--no-image>.block-editor-inner-blocks>.block-editor-block-list__layout {
	grid-template-columns: 1fr;
}

.editor-styles-wrapper .dsbn-media-row--enclosed>.block-editor-inner-blocks>.block-editor-block-list__layout {
	grid-template-columns: 3fr 1fr;
}

.editor-styles-wrapper .dsbn-staff-card__row>.block-editor-inner-blocks>.block-editor-block-list__layout {
	grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
	gap: clamp(1.25rem, 3vw, 2rem);
	align-items: start;
}

.editor-styles-wrapper :where(.dsbn-card-row, .dsbn-news-card-row, .dsbn-hub-hero, .dsbn-media-row, .dsbn-video-card--half, .dsbn-icon-cards)>.block-editor-inner-blocks>.block-editor-block-list__layout>.wp-block {
	width: 100%;
	max-width: none;
	margin: 0;
}

.editor-styles-wrapper :where(.dsbn-card, .dsbn-card__head, .dsbn-card__body, .dsbn-hub-hero__main, .dsbn-media-row__body, .dsbn-video-card__body, .dsbn-faq, .dsbn-icon-card)>.block-editor-inner-blocks>.block-editor-block-list__layout {
	display: flex;
	flex-direction: column;
	gap: inherit;
	width: 100%;
}

.editor-styles-wrapper :where(.dsbn-card, .dsbn-card__head, .dsbn-card__body, .dsbn-hub-hero__main, .dsbn-media-row__body, .dsbn-video-card__body, .dsbn-faq, .dsbn-icon-card)>.block-editor-inner-blocks>.block-editor-block-list__layout>.wp-block {
	width: 100%;
	max-width: none;
	margin: 0;
}

@media (max-width: 1024px) {
	.editor-styles-wrapper .dsbn-news-card-row>.block-editor-inner-blocks>.block-editor-block-list__layout {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 1.5rem;
	}

	.editor-styles-wrapper .dsbn-icon-cards>.block-editor-inner-blocks>.block-editor-block-list__layout {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 768px) {

	.editor-styles-wrapper .dsbn-card-row>.block-editor-inner-blocks>.block-editor-block-list__layout,
	.editor-styles-wrapper .dsbn-card-row--four>.block-editor-inner-blocks>.block-editor-block-list__layout,
	.editor-styles-wrapper .dsbn-hub-hero>.block-editor-inner-blocks>.block-editor-block-list__layout,
	.editor-styles-wrapper .dsbn-video-card--half>.block-editor-inner-blocks>.block-editor-block-list__layout,
	.editor-styles-wrapper .dsbn-media-row>.block-editor-inner-blocks>.block-editor-block-list__layout,
	.editor-styles-wrapper .dsbn-media-row--image-left>.block-editor-inner-blocks>.block-editor-block-list__layout,
	.editor-styles-wrapper .dsbn-media-row--enclosed>.block-editor-inner-blocks>.block-editor-block-list__layout {
		grid-template-columns: 1fr;
	}
}

@media (max-width: 640px) {

	.editor-styles-wrapper .dsbn-news-card-row>.block-editor-inner-blocks>.block-editor-block-list__layout,
	.editor-styles-wrapper .dsbn-icon-cards>.block-editor-inner-blocks>.block-editor-block-list__layout {
		grid-template-columns: 1fr;
	}
}

/* =============================================================
   VIDEO MODAL
   ============================================================= */
.dsbn-video-modal {
	display: none;
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	background-color: rgba(0, 0, 0, 0.7);
	z-index: 9999;
	overflow: auto;
}

.dsbn-video-modal.is-open {
	display: block;
}

.dsbn-video-modal__content {
	display: flex;
	justify-content: center;
	align-items: center;
	height: 100%;
}

.dsbn-video-modal__close {
	position: fixed;
	top: 1rem;
	right: 1rem;
	width: 2.75rem;
	height: 2.75rem;
	border: 0;
	border-radius: 50%;
	background: rgba(0, 0, 0, 0.5) url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6 6l12 12M18 6L6 18' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round'/></svg>") center / 1.25rem no-repeat;
	cursor: pointer;
	z-index: 10000;
	transition: background-color var(--dsbn-transition);
}

.dsbn-video-modal__close:hover {
	background-color: var(--dsbn-color-accent-blue);
}

.dsbn-video-modal__video {
	position: relative;
	aspect-ratio: 16 / 9;
	width: 90%;
	max-width: 960px;
}

.dsbn-video-modal__video iframe {
	border: none;
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
}

/* =============================================================
   STAFF CONTACT CARD  (e.g. Superintendent directory listing)
   -------------------------------------------------------------
   A "person" card: name/title + contact details on the left,
   a grouped list (e.g. assigned schools) in a soft panel on the
   right. The schools list reflows via CSS columns (not a fixed
   table), and the two-column row collapses to a single stacked
   column on mobile so nothing gets squeezed unreadable.
   ============================================================= */
.dsbn-staff-card {
	container-type: inline-size;
	padding: clamp(1.5rem, 3vw, 2.25rem);
	margin-block: clamp(1.5rem, 3vw, 2rem);
	border-radius: var(--dsbn-radius-lg);
	background: var(--dsbn-color-surface);
	/* --dsbn-shadow-soft is offset well below the box (14px), so its blur
	   barely reaches the top edge. Use a near-symmetric shadow instead (small
	   offset, large blur) so the card reads as "lifted" on every side. */
	box-shadow: 0 4px 32px rgba(18, 35, 61, 0.16);
}

/* Same convention as .dsbn-section+.dsbn-section: space above/below is
   symmetric (margin-block) so the card looks consistent wherever it lands,
   but two stacked cards don't get a doubled gap between them. */
.dsbn-staff-card+.dsbn-staff-card {
	margin-top: 0;
}

.dsbn-staff-card__name {
	margin: 0 0 0.25rem;
	font-family: var(--dsbn-font-body);
	font-size: var(--dsbn-fs-body-header);
	font-weight: var(--dsbn-fw-bold);
	line-height: var(--dsbn-lh-heading);
	color: var(--dsbn-color-ink);
}

.dsbn-staff-card__title {
	margin: 0 0 1.25rem;
	font-family: var(--dsbn-font-body);
	font-size: 1rem;
	font-weight: var(--dsbn-fw-medium);
	color: var(--dsbn-color-body);
}

/* Classic-theme rendering (the_content()) wraps this block's children in an
   extra .wp-block-group__inner-container div — the real grid then belongs
   on THAT wrapper (see the mirror rule below), not here too. Applying grid
   to both levels would turn the lone inner-container child into a grid item
   that only fills the outer grid's first track, squeezing the real 2-column
   content (and the schools list inside it) into a fraction of the width.
   The :has() guard only makes this element a grid itself when no such
   wrapper is present (e.g. full-site-editing/template contexts). */
.dsbn-staff-card__row:not(:has(> .wp-block-group__inner-container)) {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
	gap: clamp(1.25rem, 3vw, 2rem);
	align-items: start;
}

.dsbn-staff-card__note {
	margin: 0;
	font-size: 0.95rem;
	color: var(--dsbn-color-body);
}

.dsbn-staff-card__contact-list {
	display: flex;
	flex-direction: column;
	gap: 0.6rem;
	margin: 0.75rem 0 0;
	padding: 0;
	list-style: none;
}

.dsbn-staff-card__contact-list li {
	position: relative;
	padding-left: 1.6rem;
	font-size: 0.95rem;
}

.dsbn-staff-card__contact-list li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.1em;
	width: 1.1rem;
	height: 1.1rem;
	background-color: var(--dsbn-color-primary);
}

/* Icon is chosen by content, not position: an item containing a link
   (the "Email" item always links) gets the mail icon, plain-text items
   (the "Ext. ..." item) get the phone icon. This means either line can
   be deleted in the editor — e.g. to leave only the email contact —
   without the remaining item inheriting the wrong icon. */
.dsbn-staff-card__contact-list li:not(:has(a))::before {
	-webkit-mask: var(--dsbn-icon-phone) center / contain no-repeat;
	mask: var(--dsbn-icon-phone) center / contain no-repeat;
}

.dsbn-staff-card__contact-list li:has(a)::before {
	-webkit-mask: var(--dsbn-icon-mail) center / contain no-repeat;
	mask: var(--dsbn-icon-mail) center / contain no-repeat;
}

.dsbn-staff-card__contact-list a {
	color: var(--dsbn-btn-main);
	font-weight: var(--dsbn-fw-semibold);
	text-decoration: underline;
}

.dsbn-staff-card__schools {
	padding: 1.25rem 1.5rem;
	border-radius: var(--dsbn-radius-md);
	/* --dsbn-surface-gray (#F7F7F7) reads as white next to the card's own
	   white background — use a touch more depth so the panel is clearly a
	   distinct grey block, not just untinted white. */
	background: var(--dsbn-color-surface-alt);
}

.dsbn-staff-card__schools-title {
	margin: 0 0 0.75rem;
	font-family: var(--dsbn-font-body);
	font-size: 1.2rem;
	font-weight: var(--dsbn-fw-bold);
	color: var(--dsbn-color-ink);
}

/* CSS columns (not a fixed-column table) so the list reflows to fit
   whatever width the panel actually has, instead of relying on the
   content being hand-split into a fixed number of <td> buckets. */
.dsbn-staff-card__schools-list {
	columns: 3;
	column-gap: 1.75rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.dsbn-staff-card__schools-list li {
	position: relative;
	margin-bottom: 0.65rem;
	padding-left: 1.15rem;
	font-size: var(--dsbn-fs-body);
	line-height: var(--dsbn-lh-body);
	color: var(--dsbn-color-body);
	break-inside: avoid;
}

.dsbn-staff-card__schools-list li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.6em;
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background: var(--dsbn-color-primary);
}

/* ---- Variant: multiple contacts / school groups under one person (e.g.
   separate Elementary + Secondary administrative assistants and school
   lists) — see patterns/v2/staff-contact-card-two-admins.php. Reuses every
   class above (.dsbn-staff-card__note, __contact-list, __schools-list);
   these rules just add the repeatable "group" wrapper + category label. */
.dsbn-staff-card__group-label {
	margin: 0 0 0.35rem;
	font-family: var(--dsbn-font-body);
	font-size: 1rem;
	font-weight: var(--dsbn-fw-bold);
	color: var(--dsbn-color-ink);
}

.dsbn-staff-card__contact-group {
	margin-top: 1.25rem;
}

.dsbn-staff-card__schools-group+.dsbn-staff-card__schools-group {
	margin-top: 1.5rem;
}

@container (max-width: 900px) {
	.dsbn-staff-card__schools-list {
		columns: 2;
	}
}

@container (max-width: 768px) {
	.dsbn-staff-card__row {
		grid-template-columns: 1fr;
	}
}

@container (max-width: 480px) {
	.dsbn-staff-card__schools-list {
		columns: 1;
	}
}

/* =============================================================
   TRUSTEE CARD  (photo, name, role/region, Contact button)
   -------------------------------------------------------------
   Extends .dsbn-card (padding/radius/background/hover already
   defined there) with a centred, photo-led layout. Drop it inside
   a Card Row (.dsbn-card-row) for the 3-up grid — that grid
   already collapses to a single column at 768px.
   ============================================================= */
.dsbn-trustee-card {
	align-items: center;
	padding: clamp(1.75rem, 4vw, 2.25rem) clamp(1.25rem, 3vw, 1.5rem);
	border: 1px solid var(--dsbn-color-card-border);
	border-radius: var(--dsbn-radius-lg);
	text-align: center;
	box-shadow: 0 4px 32px rgba(18, 35, 61, 0.12);
}

.dsbn-trustee-card:hover {
	transform: translateY(-4px);
}

.dsbn-trustee-card__photo {
	width: 130px;
	height: 130px;
	margin: 0 auto;
	border-radius: 50%;
	overflow: hidden;
	background: var(--dsbn-color-surface-alt);
}

.dsbn-trustee-card__photo img {
	display: block;
	width: 100%;
	height: 100%;
	border-radius: 50%;
	object-fit: cover;
}

.dsbn-trustee-card__name {
	margin: 0;
	font-family: var(--dsbn-font-body);
	font-size: var(--dsbn-fs-body-header);
	font-weight: var(--dsbn-fw-bold);
	line-height: var(--dsbn-lh-heading);
	color: var(--dsbn-color-ink);
}

/* Role (e.g. "Chair") and region sit on their own lines within ONE
   paragraph (a <br> between them), not as separate flex children —
   that keeps them close together instead of picking up .dsbn-card's
   inter-child gap between the two lines. Muted body color (not the
   eyebrow/link blue) so it reads as supporting text, doesn't look
   clickable, and doesn't compete with the Contact button below. */
.dsbn-trustee-card__meta {
	margin: 0;
	font-family: var(--dsbn-font-body);
	font-size: 1rem;
	font-weight: var(--dsbn-fw-medium);
	line-height: 1.5;
	color: var(--dsbn-color-body);
}

.dsbn-trustee-card__actions {
	display: flex;
	justify-content: center;
	width: 100%;
	margin-top: auto;
	padding-top: 0.5rem;
}

/* =============================================================
   MOBILE POLISH  (≤ 768 px)
   ============================================================= */
@media (max-width: 768px) {

	/* --- Typography scale-down ----------------------------- */

	/* .dsbn-hub-hero__heading / .dsbn-heading--hub deliberately have NO
	   step-down here — their base clamp already scales monotonically across
	   every width. The rule that used to live here (10vw) was larger than the
	   base rule's 6.5vw and made the heading grow as the viewport shrank. */

	/* .dsbn-heading deliberately has NO step-down here. Because the max of a
	   clamp(1.75rem, 6vw, var(--dsbn-fs-section)) is itself a clamp that floors
	   at 2rem, such a rule can only ever pull the size BELOW 32px, never above
	   — so it did nothing between 534px and 768px and then dropped .dsbn-heading
	   to 28px on phones while a plain editor h2 (which has no such rule) stayed
	   at the token's 32px floor. That inverted the intended relationship: the
	   typed heading rendered LARGER than the design-system section heading it
	   is meant to match. Both now track --dsbn-fs-section alone and agree at
	   every width. */

	.dsbn-video-card__title {
		font-size: clamp(1.75rem, 6vw, var(--dsbn-fs-section));
	}

	.dsbn-faq__item summary {
		/* font-size intentionally not overridden — its own clamp() already
		   scales down here. The old 1.35rem cliff-dropped 30px -> 21.6px in
		   one pixel at this breakpoint. Padding still tightens on small screens. */
		padding: 1.25rem 1.5rem;
	}

	.dsbn-faq__item> :not(summary) {
		padding: 0 1.25rem 1rem;
	}

	/* --- Section spacing ---------------------------------- */
	.dsbn-section {
		padding-block: clamp(2rem, 6vw, var(--dsbn-section-pad));
	}

	/* --- Border-radius tighten ----------------------------- */
	.dsbn-card,
	.dsbn-card--outline,
	.dsbn-card--fill,
	.dsbn-video-card,
	.dsbn-media-row--enclosed,
	.dsbn-media-row__media img {
		border-radius: 28px;
	}

	.dsbn-card--outline::before {
		border-radius: 28px;
	}

	.dsbn-hub-hero__nav,
	.dsbn-faq__item,
	.dsbn-icon-card {
		border-radius: 20px;
	}

	/* --- Card spacing ------------------------------------- */
	.dsbn-card {
		padding: 1.25rem 1.25rem 2.75rem;
	}

	.dsbn-card--outline {
		padding-top: 3rem;
	}

	.dsbn-card--fill {
		padding: 0;
	}

	.dsbn-card--fill .dsbn-card__head {
		min-height: 120px;
		padding: 1.25rem;
	}

	.dsbn-card--fill .dsbn-card__body {
		padding: 1.25rem 1.25rem 2.75rem;
	}

	.dsbn-icon-card {
		padding: 1.25rem;
	}

	/* --- Icon card separator fix --------------------------
	   Card padding drops to 1.25rem here, so the divider's bleed has to
	   match. See the base rule for why this is a pseudo-element rather
	   than negative margins. */
	.dsbn-icon-card__body::before {
		left: -1.25rem;
		right: -1.25rem;
	}

	/* --- Carousel tabs 2x2 -------------------------------- */
	.dsbn-carousel-tabs__tablist {
		display: grid;
		grid-template-columns: 1fr 1fr;
		gap: 0;
		border-bottom: none;
	}

	.dsbn-carousel-tabs__tab {
		border-bottom: 3px solid transparent;
		text-align: center;
		padding: 0.6rem 0.5rem;
		font-size: 0.9rem;
	}

	/* --- Buttons full-width ------------------------------- */
	.dsbn-hub-hero .dsbn-btn-row {
		flex-direction: column;
	}

	.dsbn-hub-hero .dsbn-btn,
	.dsbn-hub-hero .wp-block-button.dsbn-btn>.wp-block-button__link {
		width: 100%;
		justify-content: center;
	}

	/* --- Video card full height reduce -------------------- */
	.dsbn-video-card--full {
		min-height: 400px;
	}

	/* --- Enclosed card image radius ----------------------- */
	.dsbn-media-row--enclosed {
		padding: 1.25rem;
	}

	/* --- Hub hero mobile accordion ------------------------ */
	.dsbn-hub-hero__nav:not(.is-open) .dsbn-hub-hero__nav-list,
	.dsbn-hub-hero__nav:not(.is-open) .wp-block-list {
		margin-top: 0;
	}
}