/* Custom styles for the DSBN 2026 website */
/* Design tokens now live in css/design-tokens.css (single source of truth). */

/* =============================================================
   BASE TYPOGRAPHY  (design system)
   Routes Bootstrap's own font variables to the DSBN tokens so
   New Spirit / DM Sans apply site-wide without per-element edits.
   ============================================================= */
:root {
	--bs-body-font-family: var(--dsbn-font-body);
	--bs-body-font-size: var(--dsbn-fs-body);
	--bs-body-font-weight: var(--dsbn-fw-body);
	--bs-body-line-height: var(--dsbn-lh-body);
	--bs-body-color: var(--dsbn-color-body);
	--bs-heading-color: var(--dsbn-color-ink);
}

/* Full Bootstrap carried its own universal `*, *::before, *::after { box-sizing:
   border-box; }` reset. Dropping it for the lighter bootstrap-shim.css left the
   theme with NO universal reset — every element defaulted back to content-box,
   so any rule combining a fixed/percentage width or height with padding got
   the padding added ON TOP instead of included within it. That silently broke
   .dsbn-hub-visual-hero__inner (see its own comment) and had already been
   patched around 8 separate times, component by component, across
   style.css/patterns.css before adding it here once, for good. */
*,
*::before,
*::after {
	box-sizing: border-box;
}

/* Reserve the scrollbar gutter at all times so opening a modal
   (which sets overflow: hidden on body) doesn't shift the page
   horizontally when the scrollbar disappears. */
html {
	scrollbar-gutter: stable;
}

h1,
h2,
h3,
h4,
h5,
h6,
.h1,
.h2,
.h3,
.h4,
.h5,
.h6 {
	font-family: var(--dsbn-font-heading);
	line-height: var(--dsbn-lh-heading);
}

.dsbn-logo {
	display: block;
	width: clamp(10.75rem, 13vw, 12rem);
	max-height: none;
}

/* Skip link visibility for keyboard users */
.skip-link {
	position: absolute;
	top: -40px;
	left: 0;
	z-index: 1000;
}

.skip-link:focus,
.skip-link:focus-visible {
	top: 0;
	outline: 2px solid var(--bs-warning);
	outline-offset: 2px;
}

/* Top-Bar styling */
.dsbn-utility-bar {
	position: relative;
	z-index: 40;
	min-height: 2.375rem;
	background: var(--dsbn-color-primary);
	color: #fff;
	font-family: var(--dsbn-font-body);
	font-size: var(--dsbn-fs-nav);
	font-weight: var(--dsbn-fw-medium);
	line-height: 1;
}

.dsbn-utility-bar__inner {
	display: flex;
	flex-wrap: wrap;
	row-gap: 0.4rem;
	align-items: center;
	justify-content: space-between;
	gap: clamp(1rem, 3vw, 2.5rem);
	width: min(100% - clamp(2rem, 8vw, 10rem), var(--dsbn-shell));
	min-height: inherit;
	margin-inline: auto;
}

.dsbn-utility-bar__link,
.dsbn-utility-bar button {
	appearance: none;
	display: inline-flex;
	align-items: center;
	min-height: 2.375rem;
	padding: 0;
	border: 0;
	background: transparent;
	color: inherit;
	font-size: inherit;
	font-weight: inherit;
	line-height: 1;
	text-decoration: none;
	cursor: pointer;
}

.dsbn-utility-bar__link:focus-visible,
.dsbn-utility-bar button:focus-visible {
	outline: 2px solid #fff;
	outline-offset: 2px;
}

.dsbn-utility-bar__actions {
	position: relative;
	display: inline-flex;
	flex-wrap: wrap;
	row-gap: 0.4rem;
	align-items: center;
	/* Widened from clamp(1rem, 1.8vw, 1.75rem) — Quick Links / Select
	   Language / text-size / contrast / Contact Us were sitting visibly
	   cramped together on desktop. */
	gap: clamp(1.5rem, 2.5vw, 2.5rem);
}

.dsbn-utility-bar__link {
	gap: 0.25rem;
}

.dsbn-utility-menu__toggle {
	position: relative;
}

.dsbn-utility-menu__toggle::after {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0.35rem;
	height: 2px;
	background: currentColor;
	content: "";
	transform: scaleX(0);
	transform-origin: center;
	transition: transform var(--dsbn-transition);
}

.dsbn-utility-menu:hover .dsbn-utility-menu__toggle::after,
.dsbn-utility-menu__toggle:focus-visible::after,
.dsbn-utility-menu__toggle[aria-expanded="true"]::after {
	transform: scaleX(1);
}

.dsbn-utility-bar__text-size {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
}

.dsbn-utility-bar__text-size button:first-child {
	font-size: 0.625rem;
}

.dsbn-utility-bar__text-size button[aria-disabled="true"] {
	opacity: 0.7;
	cursor: default;
}

/* Text size control steps (js/scripts.js toggles these on <html>). Rem-based
   sizing throughout the theme means this scales the whole site consistently. */
html.dsbn-text-scale-2 {
	font-size: 110%;
}

html.dsbn-text-scale-3 {
	font-size: 120%;
}

html.dsbn-text-scale-4 {
	font-size: 130%;
}

html.dsbn-text-scale-5 {
	font-size: 140%;
}

/* Google Translate widget overrides - the language picker is our own modal
   (#google_translate_element), so neutralize Google's auto-injected banner/
   tooltip/highlight chrome instead of letting it shift or paint over the page. */
body {
	top: 0 !important;
}

.goog-te-banner-frame.skiptranslate,
.goog-te-balloon-frame,
#goog-gt-tt,
iframe.skiptranslate {
	display: none !important;
}

.goog-text-highlight {
	background: none !important;
	box-shadow: none !important;
}

.dsbn-utility-menu {
	position: relative;
}

.dsbn-utility-menu__panel {
	position: absolute;
	top: 100%;
	right: 0;
	z-index: 60;
	display: grid;
	gap: 0;
	min-width: 15rem;
	margin: 0;
	padding: 0.75rem 0;
	border: 1px solid var(--dsbn-color-line);
	border-radius: 0 0 8px 8px;
	background: var(--dsbn-color-surface);
	box-shadow: 0 18px 40px rgba(0, 35, 71, 0.14);
	list-style: none;
	animation: dsbnUtilityMenuIn 160ms ease-out;
}

@keyframes dsbnUtilityMenuIn {
	from {
		opacity: 0;
		transform: translateY(-0.25rem);
	}

	to {
		opacity: 1;
		transform: translateY(0);
	}
}

.dsbn-utility-menu__panel[hidden] {
	display: none;
}

.dsbn-utility-menu__panel li {
	margin: 0;
	padding: 0;
}

.dsbn-utility-menu__panel a {
	display: block;
	padding: 0.75rem 1.1rem;
	color: var(--dsbn-color-ink);
	font-size: 0.95rem;
	line-height: 1.2;
	text-decoration: none;
	transition: color var(--dsbn-transition);
}

.dsbn-utility-menu__panel a:hover,
.dsbn-utility-menu__panel a:focus-visible {
	color: var(--dsbn-color-primary);
}

.dsbn-utility-bar .material-symbols-outlined {
	font-size: 12px !important;
}

/* High contrast toggle: the only icon-only control in the bar that has to
   carry its whole meaning alone. The dropdown carets share the bar's 12px
   icon size fine because they're secondary to the text label beside them
   ("Quick Links ⌄"), and A/A is self-explanatory by its own letter sizes —
   neither needs to be legible as a standalone symbol. This one does, so it
   overrides back up from the shared 12px. */
.dsbn-utility-bar__high-contrast .material-symbols-outlined {
	font-size: 1.15rem !important;
}

.dsbn-utility-bar__high-contrast {
	position: relative;
}

/* Visual-only hint, not the accessible name — the button's own aria-label
   already names the control for screen readers, and this span is
   aria-hidden so it can never be announced as a second, redundant label.
   It exists purely so a sighted mouse/keyboard user gets the same "what is
   this" answer a screen reader user already has from the aria-label alone. */
.dsbn-utility-bar__tooltip {
	position: absolute;
	top: 100%;
	left: 50%;
	transform: translate(-50%, 0.5rem);
	padding: 0.35rem 0.65rem;
	border-radius: var(--dsbn-radius-sm);
	background: var(--dsbn-color-ink);
	color: #fff;
	font-size: 0.75rem;
	font-weight: var(--dsbn-fw-medium);
	line-height: 1.2;
	white-space: nowrap;
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	transition: opacity var(--dsbn-transition), visibility var(--dsbn-transition);
	z-index: 20;
}

.dsbn-utility-bar__tooltip::before {
	content: "";
	position: absolute;
	bottom: 100%;
	left: 50%;
	transform: translateX(-50%);
	border: 5px solid transparent;
	border-bottom-color: var(--dsbn-color-ink);
}

.dsbn-utility-bar__high-contrast:hover .dsbn-utility-bar__tooltip,
.dsbn-utility-bar__high-contrast:focus-visible .dsbn-utility-bar__tooltip {
	opacity: 1;
	visibility: visible;
}

/* At <=1000px this becomes the rightmost item in a right-aligned row (Quick
   Links hides, Login/Contact move into the hamburger — see the utility-bar
   mobile rules further down), close enough to the viewport edge that
   centering pushes the tooltip past it. `body`'s overflow-x:hidden then
   clips it in place rather than letting the page scroll to reveal it —
   measured: tooltip right edge landing exactly at the 390px viewport
   boundary, "High Contrast" reading as "High Contras". Right-anchor instead
   of centering at the same breakpoint the row itself switches to
   right-aligned; the arrow shifts to match so it still points at the icon
   rather than the middle of a now off-center box. */
@media screen and (max-width: 1000px) {
	.dsbn-utility-bar__tooltip {
		left: auto;
		right: 0;
		transform: translateY(0.5rem);
	}

	.dsbn-utility-bar__tooltip::before {
		left: auto;
		right: 0.95rem;
		transform: none;
	}
}

body.dsbn-modal-open {
	overflow: hidden;
}

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

.dsbn-modal {
	position: fixed;
	inset: 0;
	z-index: 1000;
	/* Flexbox, not grid — tried `display:grid;place-items:safe center` first
	   (the modern, spec-correct way to say "center it, but fall back to
	   start-aligned/scrollable rather than clipping both edges once it
	   doesn't fit"), but Chromium has a real rendering bug where combining
	   `safe center` with `overflow-y:auto` on the SAME grid container breaks
	   centering on the axis that ISN'T even overflowing (verified live: a
	   dialog well within the viewport's width still rendered flush against
	   the left edge instead of centered). The older auto-margin trick below
	   doesn't have that bug and has been reliable across browsers for far
	   longer. */
	display: flex;
	overflow-y: auto;
	/* Just a "never touch the screen edge" gutter. The centering is done by
	   the dialog's auto margins, not by tuning this value. */
	padding: clamp(1.5rem, 4vw, 2rem);
	font-family: var(--dsbn-font-body);
}

.dsbn-modal__backdrop {
	/* fixed, NOT absolute — .dsbn-modal is itself the scroll container
	   (overflow-y:auto above). An absolutely-positioned `inset:0` child
	   sizes to its containing block's PADDING BOX (i.e. one viewport tall),
	   not the scrollable content height, and then scrolls away with the
	   content: measured on a real 800px-tall viewport with 940px of modal
	   content, scrolling to the bottom put the backdrop at top:-140/
	   bottom:660, leaving the last 140px of the screen with no dim layer at
	   all and the live page showing through. Anchoring to the viewport
	   instead keeps it covering the full screen at any scroll position. */
	position: fixed;
	inset: 0;
	background: var(--dsbn-color-backdrop);
	opacity: 0;
	transition: opacity var(--dsbn-transition);
}

.dsbn-modal__dialog {
	position: relative;
	z-index: 1;
	width: min(100%, 34rem);
	/* Auto margins on a flex item center it on BOTH axes when there's room
	   to spare, and cleanly collapse to 0 (start-aligned, fully reachable by
	   scrolling .dsbn-modal above) the moment there isn't — without needing
	   `safe center`. No max-height/overflow-y here anymore either — the
	   dialog just grows to fit whatever content it's given. */
	margin: auto;
	transform: translateY(0.75rem) scale(0.98);
	transition: opacity var(--dsbn-transition), transform var(--dsbn-transition);
	opacity: 0;
}

.dsbn-modal__dialog--wide {
	width: min(100%, 48rem);
}

.dsbn-modal.is-open .dsbn-modal__backdrop {
	opacity: 1;
}

.dsbn-modal.is-open .dsbn-modal__dialog {
	opacity: 1;
	transform: translateY(0) scale(1);
}

.dsbn-modal__content {
	position: relative;
	border-radius: var(--dsbn-radius-sm);
	background: #fff;
	box-shadow: 0 24px 70px rgba(0, 35, 71, 0.24);
}

.dsbn-modal__header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	padding: clamp(1.25rem, 3vw, 1.75rem) clamp(4rem, 8vw, 4.75rem) 0.75rem clamp(1.25rem, 3vw, 2rem);
}

.dsbn-modal__title {
	margin: 0;
	font-family: var(--dsbn-font-heading);
	font-size: clamp(1.45rem, 3vw, 1.85rem);
	font-weight: var(--dsbn-fw-medium);
	line-height: var(--dsbn-lh-tight);
	color: var(--dsbn-color-ink);
}

.dsbn-modal__close {
	appearance: none;
	position: absolute;
	top: 1rem;
	right: 1rem;
	flex: 0 0 auto;
	/* 44px — WCAG 2.5.5/2.5.8 touch-target guideline. Was 2.25rem (36px);
	   used by every .dsbn-modal sitewide (language, search, icon-card
	   modals, the Stories modal), so worth getting right once here. */
	width: 2.75rem;
	height: 2.75rem;
	border: 1px solid var(--dsbn-color-line);
	border-radius: var(--dsbn-radius-pill);
	background: var(--dsbn-color-surface);
	cursor: pointer;
}

.dsbn-modal__close::before,
.dsbn-modal__close::after {
	position: absolute;
	top: 50%;
	left: 50%;
	width: 1rem;
	height: 2px;
	background: var(--dsbn-color-ink);
	content: "";
}

.dsbn-modal__close::before {
	transform: translate(-50%, -50%) rotate(45deg);
}

.dsbn-modal__close::after {
	transform: translate(-50%, -50%) rotate(-45deg);
}

.dsbn-modal__close:hover,
.dsbn-modal__close:focus-visible {
	border-color: var(--dsbn-color-primary);
	outline: 3px solid var(--dsbn-color-accent-blue);
	outline-offset: 2px;
}

/* overflow-wrap: a long unbroken token (a raw URL is the real-world case --
   found live via dsbn-scholarships, whose modal content includes real
   scholarship website links) has no natural break point, so it silently
   pushes past the dialog's own edge instead of wrapping -- narrow enough to
   matter on mobile, where the dialog is close to full viewport width
   already. Scoped to the body generally (not just links) since a long email
   address or reference code in plain text would overflow the exact same
   way. */
.dsbn-modal__body {
	padding: 0.75rem clamp(1.25rem, 3vw, 2rem) clamp(1.5rem, 4vw, 2rem);
	overflow-wrap: anywhere;
}

/* Section headings inside modal content (Amount/Deadline/Criteria in the
   scholarships modal, Priorities/Highlights/Commitments in the Equity
   Action Plan one) -- found live via dsbn-scholarships. This content isn't
   inside .pg-contents, so it never picks up that wrapper's h3-h6 DM Sans/
   semibold content-heading treatment (patterns.css) and instead fell
   through to the sitewide h1-h6 base rule (New Spirit, browser-default
   bold) meant for page-level headings, not in-content sub-headings --
   confirmed live, computing to bold New Spirit with EQUAL margin
   top/bottom (23.94px both), the same "sits equidistant between the
   section before it and its own content, reading as attached to neither"
   issue already fixed elsewhere (FAQ answer headings, card CTA dividers).
   .dsbn-modal__title itself is deliberately unaffected (it's the dialog's
   own top-level heading, styled to match the page's own h1/h2 New Spirit
   treatment on purpose) -- these rules only reach headings inside
   .dsbn-modal__body, never .dsbn-modal__header. */
.dsbn-modal__body :is(h2, h3, h4, h5, h6) {
	margin: 1.75rem 0 0.5rem;
	font-family: var(--dsbn-font-body);
	font-weight: var(--dsbn-fw-semibold);
}

.dsbn-modal__body :is(h2, h3, h4, h5, h6):first-child {
	margin-top: 0;
}

/* The 0.5rem bottom margin above only wins on paper -- adjacent margins
   collapse to whichever is LARGER, and the following paragraph's own
   default top margin (~1em, ~18px at this body size) is bigger than the
   heading's 0.5rem (8px), so the heading's own tighter value was being
   silently overridden by the paragraph's margin every time. Confirmed
   live: measured gap was 18px, not the intended 8px. Zeroing the
   following block's own top margin removes the competing value entirely
   instead of fighting the collapse. */
.dsbn-modal__body :is(h2, h3, h4, h5, h6)+ :is(p, ul, ol) {
	margin-top: 0;
}

.dsbn-modal__body :is(h2, h3) {
	font-size: var(--dsbn-fs-body-header);
}

.dsbn-modal__body :is(h4) {
	font-size: 1.375rem;
}

.dsbn-modal__body :is(h5) {
	font-size: 1.25rem;
}

.dsbn-modal__body :is(h6) {
	font-size: 1.125rem;
}

/* Equity Action Plan-style modals (Priorities / Highlights / Commitments —
   multiple heading-led sections in one body) lay out in 2 columns instead
   of one long single-column scroll. Scoped structurally via :has(), to
   whichever modal actually HAS 2+ headings, rather than a class on the
   pattern — this content already lives on real published pages, and
   patterns aren't "synced" blocks, so a class added only to the pattern
   file wouldn't retroactively reach anything already inserted from it
   (also why this checks every heading level, not just the pattern file's
   own H4 — real saved content on the live page turned out to use H3
   instead). Every other modal shape (icon-card-modal-single's plain
   paragraph, no headings at all) never matches and stays single-column.
   break-after/-inside: avoid-column on the heading and its list together
   mean the browser's only valid break point is between one section's list
   and the next section's heading — never mid-list, never orphaning a
   heading alone at a column's bottom. */
.dsbn-modal__body:has(:is(h2, h3, h4, h5, h6) ~ :is(h2, h3, h4, h5, h6)) {
	column-count: 2;
	column-gap: clamp(1.5rem, 3vw, 2.5rem);
}

.dsbn-modal__body:has(:is(h2, h3, h4, h5, h6) ~ :is(h2, h3, h4, h5, h6)) :is(h2, h3, h4, h5, h6) {
	break-after: avoid-column;
}

.dsbn-modal__body:has(:is(h2, h3, h4, h5, h6) ~ :is(h2, h3, h4, h5, h6)) :is(h2, h3, h4, h5, h6),
.dsbn-modal__body:has(:is(h2, h3, h4, h5, h6) ~ :is(h2, h3, h4, h5, h6)) ul,
.dsbn-modal__body:has(:is(h2, h3, h4, h5, h6) ~ :is(h2, h3, h4, h5, h6)) ol,
.dsbn-modal__body:has(:is(h2, h3, h4, h5, h6) ~ :is(h2, h3, h4, h5, h6)) p {
	break-inside: avoid-column;
}

/* A 2-column body needs real width per column or the text just wraps a lot
   and the whole modal ends up tall/scroll-heavy anyway — defeating the
   point. Wider than even .dsbn-modal__dialog--wide (48rem), scoped the same
   structural way (independent of --wide, which header.php's hand-coded
   language/search modals also use and shouldn't be affected by this).
   88rem specifically, not a round guess: measured the real (longest)
   Student Voice modal's rendered height across widths on a typical
   1440x800 laptop viewport — 56rem=993px, 64rem=908px, 72/80rem=793px,
   88rem=735px. 88rem is the first step that actually FITS an 800px-tall
   screen without the overlay needing to scroll at all, which was the
   point of widening it. min(100%, …) still keeps it inside narrower
   screens, where the mobile single-column rule below takes over anyway. */
.dsbn-modal__dialog:has(.dsbn-modal__body :is(h2, h3, h4, h5, h6) ~ :is(h2, h3, h4, h5, h6)) {
	width: min(100%, 88rem);
}

@media screen and (max-width: 768px) {

	/* 2 columns of body text on a phone-width dialog is cramped no matter
	   how the breaks fall — stack back to one column, same as any other
	   modal, rather than trying to preserve the desktop trick at a width it
	   was never meant for. */
	.dsbn-modal__body:has(:is(h2, h3, h4, h5, h6) ~ :is(h2, h3, h4, h5, h6)) {
		column-count: 1;
	}
}

.dsbn-modal__note {
	margin: 0 0 1rem;
	font-size: 0.95rem;
	line-height: var(--dsbn-lh-body);
	color: var(--dsbn-color-muted);
}

.dsbn-modal__note--last {
	margin: 1rem 0 0;
}

.dsbn-search-form__field {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	border: 1px solid var(--dsbn-color-line);
	border-radius: 8px;
	overflow: hidden;
}

.dsbn-search-form__input {
	width: 100%;
	min-height: 3.5rem;
	padding: 0 1rem;
	border: 0;
	font: inherit;
	font-size: 1.05rem;
	color: var(--dsbn-color-ink);
}

.dsbn-search-form__input:focus {
	outline: none;
}

.dsbn-search-form__field:focus-within {
	border-color: var(--dsbn-color-primary);
	box-shadow: 0 0 0 3px rgba(26, 153, 229, 0.22);
}

.dsbn-search-form__submit {
	appearance: none;
	display: grid;
	place-items: center;
	width: 4rem;
	min-height: 3.5rem;
	border: 0;
	background: var(--dsbn-color-primary);
	color: #fff;
	cursor: pointer;
	transition: background var(--dsbn-transition);
}

.dsbn-search-form__submit:hover,
.dsbn-search-form__submit:focus-visible {
	background: var(--dsbn-color-ink);
	outline: none;
}

.dsbn-search-form__submit .material-symbols-outlined {
	font-size: 1.45rem !important;
}

@media screen and (max-width: 768px) {
	.dsbn-utility-bar {
		font-size: .75rem;
	}
}

/* NavBar styling */
.dsbn-site-header {
	position: relative;
	z-index: 30;
	min-height: 7.25rem;
	background: #fff;
}

.dsbn-site-header__inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: clamp(1.25rem, 4vw, 4rem);
	width: min(100% - clamp(2rem, 8vw, 10rem), var(--dsbn-shell));
	min-height: inherit;
	margin-inline: auto;
}

.dsbn-site-header__brand {
	display: inline-flex;
	align-items: center;
	flex: 0 0 auto;
}

/* display:contents on desktop — a no-op layout-wise, so .dsbn-site-header__search's
   own display:none and .dsbn-menu-toggle's own display:none (unchanged, set on
   the buttons themselves) still apply exactly as if this wrapper weren't there.
   At max-width:1000px it becomes a real flex row so the two buttons sit close
   together (mobile icon-cluster convention) while still being pushed to the
   header's right edge via its own margin-left:auto — see that breakpoint. */
.dsbn-site-header__mobile-actions {
	display: contents;
}

/* Hidden on desktop — the primary nav's own icon-only .dsbn-primary-nav__search
   item covers it there. Shown at max-width:1000px (see that breakpoint below)
   so search stays one tap away instead of requiring the whole mobile menu to
   open first. Icon reuses .dsbn-primary-nav__search-icon (same mask/asset as
   desktop's search item) so both render identically. */
.dsbn-site-header__search {
	display: none;
	appearance: none;
	place-items: center;
	width: 2.75rem;
	height: 2.75rem;
	border: 0;
	border-radius: 0;
	background: transparent;
	color: var(--dsbn-color-primary);
	cursor: pointer;
}

.dsbn-site-header__search:focus-visible {
	outline: 3px solid var(--dsbn-color-accent-blue);
	outline-offset: 2px;
}

.dsbn-primary-nav {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	flex: 1 1 auto;
	min-width: 0;
}

.dsbn-primary-nav__list {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: flex-end;
	row-gap: 0.5rem;
	gap: clamp(1.25rem, 2vw, 2.75rem);
	margin: 0;
	padding: 0;
	list-style: none;
}

.dsbn-primary-nav__item {
	position: static;
	display: flex;
	align-items: center;
	gap: 0.15rem;
	min-height: 7.25rem;
	margin: 0;
	padding: 0;
	list-style: none;
	font-family: var(--dsbn-font-body);
	font-weight: var(--dsbn-fw-bold);
	/* Trimmed from clamp(0.95rem, 0.92vw, 1.0625rem) — closer to Apple HIG
	   tab-bar (~13px) / Material nav-item (~14px) label sizes. */
	font-size: clamp(0.85rem, 0.85vw, 0.9375rem);
	line-height: 1;
	text-transform: uppercase;
}

.dsbn-primary-nav__link {
	appearance: none;
	position: relative;
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	min-height: 2.75rem;
	padding: 0;
	border: 0;
	background: transparent;
	color: var(--dsbn-color-primary);
	font: inherit;
	line-height: 1.2;
	text-transform: inherit;
	text-decoration: none;
	cursor: pointer;
	overflow-wrap: anywhere;
	transition: color var(--dsbn-transition);
}

.dsbn-primary-nav__submenu-toggle {
	appearance: none;
	display: inline-grid;
	place-items: center;
	width: 1.35rem;
	height: 2.75rem;
	padding: 0;
	border: 0;
	background: transparent;
	color: var(--dsbn-color-primary);
	cursor: pointer;
}

.dsbn-primary-nav__link::after {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0.35rem;
	height: 3px;
	background: currentColor;
	content: "";
	transform: scaleX(0);
	transform-origin: center;
	transition: transform var(--dsbn-transition);
}

.dsbn-primary-nav__link:hover::after,
.dsbn-primary-nav__link:focus-visible::after,
.dsbn-primary-nav__item.is-open>.dsbn-primary-nav__link::after {
	transform: scaleX(1);
}

.dsbn-primary-nav__submenu-toggle .material-symbols-outlined {
	font-size: 1rem;
	line-height: 1;
	transition: transform var(--dsbn-transition);
}

.dsbn-primary-nav__item.is-open .dsbn-primary-nav__submenu-toggle .material-symbols-outlined {
	transform: rotate(180deg);
}

.dsbn-primary-nav__submenu-toggle:focus-visible {
	outline: 3px solid var(--dsbn-color-accent-blue);
	outline-offset: 3px;
}

.dsbn-primary-nav__search {
	justify-content: center;
	width: 1.875rem;
	height: 1.875rem;
	min-height: 1.875rem;
}

.dsbn-primary-nav__search::after {
	display: none;
}

.dsbn-primary-nav__search img {
	display: block;
	width: 1.5rem;
	height: 1.5rem;
	object-fit: contain;
}

.dsbn-primary-nav__search-icon {
	display: block;
	width: 1.5rem;
	height: 1.5rem;
	background: var(--dsbn-color-primary);
	-webkit-mask: var(--dsbn-icon-search) center / contain no-repeat;
	mask: var(--dsbn-icon-search) center / contain no-repeat;
}

/* Screen-reader-only on desktop, where the search nav item is icon-only;
   unclipped in the mobile menu (below ~1000px) so the word "Search" shows
   next to the icon. */
.dsbn-primary-nav__search-label {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
}

/* Student & Staff Login / Contact Us: only shown inside the hamburger menu
   below ~1000px (see max-width:1000px block) — the utility bar carries them
   on desktop instead. */
.dsbn-primary-nav__item--utility {
	display: none;
}

.dsbn-megamenu {
	position: absolute;
	top: 100%;
	left: 0;
	right: 0;
	z-index: 50;
	border-top: 1px solid var(--dsbn-color-line);
	border-bottom: 1px solid var(--dsbn-color-line);
	background: #fff;
	box-shadow: 0 20px 45px rgba(0, 35, 71, 0.1);
	animation: dsbnMegamenuIn 160ms ease-out;
}

@keyframes dsbnMegamenuIn {
	from {
		opacity: 0;
		transform: translateY(-0.35rem);
	}

	to {
		opacity: 1;
		transform: translateY(0);
	}
}

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

.dsbn-megamenu__inner {
	display: grid;
	grid-template-columns: minmax(14rem, 20rem) minmax(0, 1fr);
	gap: clamp(1.25rem, 2.5vw, 2.5rem);
	width: min(100% - clamp(2rem, 8vw, 10rem), var(--dsbn-shell));
	margin-inline: auto;
	padding-block: clamp(1.75rem, 3vw, 2.75rem);
}

/* Desktop keeps a distinct heading font (its own column, see grid above).
   Mobile overrides font-family + border-bottom further down to render as
   a plain depth-1 submenu link instead (shares color/border/hover with
   .dsbn-megamenu__link and the bold weight with
   .dsbn-megamenu__item--depth-1 links). */
.dsbn-megamenu__heading {
	align-self: start;
	max-width: 100%;
	font-family: var(--dsbn-font-heading);
	font-size: 1.0625rem;
	line-height: 1.35;
	white-space: normal;
	overflow-wrap: anywhere;
}

/* CSS multi-column, not grid: a grid row's height is set by its tallest
   cell, and items WITH a nested .dsbn-megamenu__sublist (grandchild list)
   can be far taller than plain ones — tried grid first, but that meant
   every short item in a row got stretched to match its tallest neighbor,
   leaving large dead gaps (worse than the misalignment it was meant to
   fix). Multi-column flows each column independently by its own content
   height, so short items stay short regardless of what's next to them —
   the standard technique for compact lists of uneven-height items. 4
   columns (not 3) so the tallest single column stays shorter overall. */
.dsbn-megamenu__links {
	display: block;
	column-count: 4;
	column-gap: clamp(1.5rem, 3vw, 3rem);
	margin: 0;
	padding: 0;
	list-style: none;
}

.dsbn-megamenu__item {
	margin: 0;
	padding: 0 0 clamp(0.5rem, 1vw, 0.85rem);
	break-inside: avoid;
	page-break-inside: avoid;
	font-size: 1.0625rem;
	font-weight: var(--dsbn-fw-medium);
	line-height: 1.35;
	text-transform: none;
}

/* Transparent border (not "none") so hover/focus can reveal the same 1px
   line without a layout shift — matches depth-2 sub-items, which already
   have no permanent underline of their own. */
.dsbn-megamenu__link,
.dsbn-megamenu__heading {
	display: block;
	padding: 0.4rem 0;
	border-bottom: 1px solid transparent;
	color: #111;
	text-decoration: none;
	transition: color var(--dsbn-transition), border-color var(--dsbn-transition);
}

/* Two separate rules, not a shared selector list: .dsbn-megamenu__heading is
   never actually a descendant of .dsbn-megamenu__item--depth-1 (it's a
   standalone sibling link in .dsbn-megamenu__inner, see functions.php) — it
   should always be bold unconditionally, not conditionally on that
   ancestor. Written as one list before, which worked by coincidence but
   read as if it were scoped. */
.dsbn-megamenu__item--depth-1>.dsbn-megamenu__link {
	font-weight: var(--dsbn-fw-bold);
}

.dsbn-megamenu__heading {
	font-weight: var(--dsbn-fw-bold);
}

.dsbn-megamenu__sublist {
	display: block;
	margin: 0;
	padding: 0.25rem 0 0;
	list-style: none;
}

.dsbn-megamenu__sublist .dsbn-megamenu__item {
	padding-bottom: 0;
	font-size: 0.95rem;
	font-weight: var(--dsbn-fw-medium);
}

.dsbn-megamenu__sublist .dsbn-megamenu__link {
	position: relative;
	padding: 0.35rem 0;
	border-bottom: 0;
	color: #333;
}

.dsbn-megamenu__link:hover,
.dsbn-megamenu__link:focus-visible,
.dsbn-megamenu__heading:hover,
.dsbn-megamenu__heading:focus-visible {
	border-bottom-color: var(--dsbn-color-primary);
	color: var(--dsbn-color-primary);
}

.dsbn-menu-toggle {
	display: none;
	appearance: none;
	position: relative;
	/* 44px — WCAG 2.5.5/2.5.8 touch-target guideline. Was 2rem (32px); this
	   is the primary way to open the whole mobile nav, worth getting
	   right. The bars are centered via transform, so this doesn't shift
	   their position, just gives the button more surrounding tap area. */
	width: 2.75rem;
	height: 2.75rem;
	place-items: center;
	border: 0;
	border-radius: 0;
	background: transparent;
	cursor: pointer;
}

.dsbn-menu-toggle__bar {
	position: absolute;
	left: 50%;
	display: block;
	width: 1.35rem;
	height: 2px;
	background: var(--dsbn-color-primary);
	transform: translateX(-50%);
	transition: opacity var(--dsbn-transition), transform var(--dsbn-transition);
}

.dsbn-menu-toggle__bar:nth-child(1) {
	transform: translate(-50%, -0.42rem);
}

.dsbn-menu-toggle__bar:nth-child(2) {
	transform: translateX(-50%);
}

.dsbn-menu-toggle__bar:nth-child(3) {
	transform: translate(-50%, 0.42rem);
}

.dsbn-menu-toggle[aria-expanded="true"] .dsbn-menu-toggle__bar:nth-child(1) {
	transform: translateX(-50%) rotate(45deg);
}

.dsbn-menu-toggle[aria-expanded="true"] .dsbn-menu-toggle__bar:nth-child(2) {
	opacity: 0;
	transform: translateX(-50%) scaleX(0.2);
}

.dsbn-menu-toggle[aria-expanded="true"] .dsbn-menu-toggle__bar:nth-child(3) {
	transform: translateX(-50%) rotate(-45deg);
}

/* Compact desktop nav — keeps the full horizontal menu (no hamburger) down
   to common small-laptop widths (~1024px) by tightening the logo, gutters,
   gaps and type size just enough for all items to fit on one line. Below
   this tier there's no longer enough room even at these tightened sizes,
   so the mobile hamburger menu (next breakpoint) takes over instead. */
@media screen and (min-width: 1001px) and (max-width: 1300px) {
	.dsbn-site-header__inner {
		width: min(100% - 1.5rem, var(--dsbn-shell));
		gap: 1rem;
	}

	.dsbn-logo {
		width: 9rem;
	}

	.dsbn-primary-nav__list {
		gap: 0.75rem;
	}

	.dsbn-primary-nav__item {
		font-size: 0.85rem;
	}

	.dsbn-primary-nav__link {
		gap: 0.25rem;
	}

	.dsbn-primary-nav__submenu-toggle {
		width: 1.1rem;
	}
}

/* Desktop-only megamenu overrides. On desktop the top-nav link itself
   already navigates to the page on click (see js/scripts.js — the click
   is only intercepted to toggle the panel on mobile), so the duplicate
   .dsbn-megamenu__heading link inside the panel serves no purpose here and
   is hidden; the heading column collapses so .dsbn-megamenu__links takes
   the full width. Mobile keeps the heading (its only way to reach the
   parent page there) and its own grid-template-columns override further
   down, so this block is scoped to not touch mobile at all.
   Also caps the panel's height to the viewport: .dsbn-megamenu is
   position:absolute with no height limit of its own, so a top-level item
   with several children that each have their own sub-children could render
   taller than the viewport with nothing to scroll it. 6rem mirrors the
   same "viewport minus header" estimate already used for the mobile
   nav panel's own scroll cap below. */
@media screen and (min-width: 1001px) {
	.dsbn-megamenu {
		max-height: calc(100vh - 6rem);
		overflow-y: auto;
	}

	.dsbn-megamenu__heading {
		display: none;
	}

	.dsbn-megamenu__inner {
		grid-template-columns: 1fr;
	}
}

@media screen and (max-width: 1000px) {
	.dsbn-site-header {
		min-height: 6rem;
	}

	.dsbn-menu-toggle {
		display: grid;
	}

	.dsbn-site-header__search {
		display: grid;
	}

	.dsbn-site-header__mobile-actions {
		display: flex;
		align-items: center;
		/* Tight, matching how iOS/Material group an icon cluster in a
		   compact header rather than spacing them across the row. */
		gap: 0.35rem;
		margin-left: auto;
	}

	/* Student & Staff Login and Contact Us move into the hamburger menu
	   itself (see .dsbn-primary-nav__item--utility below) once the utility
	   bar no longer has room to lay them out alongside the other controls. */
	.dsbn-utility-bar__login,
	.dsbn-utility-bar__contact {
		display: none;
	}

	.dsbn-utility-bar__inner {
		justify-content: flex-end;
	}

	.dsbn-primary-nav {
		position: absolute;
		top: 100%;
		left: 0;
		right: 0;
		display: none;
		max-height: calc(100vh - 6rem);
		overflow-x: hidden;
		overflow-y: auto;
		background: #fff;
		border-top: 1px solid var(--dsbn-color-line);
		box-shadow: 0 18px 36px rgba(0, 35, 71, 0.12);
		scrollbar-width: none;
		-webkit-overflow-scrolling: touch;
	}

	.dsbn-primary-nav::-webkit-scrollbar {
		width: 0;
		height: 0;
	}

	.dsbn-primary-nav.is-open {
		display: block;
	}

	.dsbn-primary-nav__list {
		display: grid;
		/* The base (desktop) rule sets justify-content:flex-end for the flex
		   layout there, but that same declaration also applies to grid layout
		   (align/justify-content isn't reset by this override) — with no
		   explicit grid-template-columns the single implicit column sized to
		   its own content width, then got pushed flush-right by flex-end,
		   leaving a large empty gap on the left. Setting an explicit 1fr
		   column (and resetting justify-content) makes the column/each item
		   fill the full width every time, regardless of that inherited value. */
		grid-template-columns: 1fr;
		justify-content: normal;
		gap: 0;
		width: 100%;
		margin-inline: auto;
		padding: 0;
		white-space: normal;
	}

	.dsbn-primary-nav__item {
		display: grid;
		grid-template-columns: minmax(0, 1fr) 3.25rem;
		align-items: stretch;
		gap: 0;
		min-height: 0;
		/* Grid items default to min-width:auto (content-based), so a wide
		   megamenu row spanning both columns (grid-column:1/-1 below) could
		   otherwise force this item — and the shared 1fr list column with
		   it — wider than the viewport, causing horizontal scroll only
		   while a submenu is open. */
		min-width: 0;
		/* Trimmed from 1.125rem (18px) — still a comfortable touch-target
		   row, just closer to native mobile list-item text sizes. */
		font-size: 1rem;
	}

	/* Redundant with the header's own persistent search icon
	   (.dsbn-site-header__mobile-actions), which replaces it at this same
	   breakpoint — the list version would just be a second, buried way to
	   do the same thing. Must come after the .dsbn-primary-nav__item rule
	   above (same specificity, source order decides). */
	.dsbn-primary-nav__item--search {
		display: none;
	}

	.dsbn-primary-nav__link {
		width: 100%;
		min-height: 3.5rem;
		padding-left: 1rem;
		border-bottom: 0;
	}

	.dsbn-primary-nav__submenu-toggle {
		width: 100%;
		height: 3.5rem;
		border-bottom: 0;
	}

	.dsbn-primary-nav__link::after {
		display: none;
	}

	.dsbn-primary-nav__item--search .dsbn-primary-nav__link {
		justify-content: flex-start;
	}

	.dsbn-primary-nav__search-label {
		position: static;
		width: auto;
		height: auto;
		margin: 0;
		padding: 0;
		overflow: visible;
		clip: auto;
		white-space: normal;
	}

	/* Bold + uppercase like every other item in the mobile list (the
	   border-top divider two rules below is enough to signal these are a
	   separate utility group — a different font-weight/case on top of that
	   read as visually broken, not intentional). */
	.dsbn-primary-nav__item--utility {
		display: grid;
	}

	.dsbn-primary-nav__item:not(.dsbn-primary-nav__item--utility)+.dsbn-primary-nav__item--utility {
		border-top: 1px solid var(--dsbn-color-line);
	}

	.dsbn-megamenu {
		grid-column: 1 / -1;
		position: static;
		min-width: 0;
		border: 0;
		background: #fff;
		box-shadow: none;
		animation: none;
	}

	.dsbn-megamenu__inner {
		grid-template-columns: 1fr;
		gap: 0;
		width: 100%;
		padding: 0 1rem 1.5rem;
	}

	.dsbn-megamenu__links {
		column-count: 1;
	}

	.dsbn-megamenu__item,
	.dsbn-megamenu__heading {
		font-size: 1rem;
	}

	.dsbn-megamenu__item {
		padding-bottom: 0.85rem;
	}

	.dsbn-megamenu__link,
	.dsbn-megamenu__heading {
		padding-block: 0.85rem;
	}

	/* Shares the plain depth-1 link's sizing/weight, but keeps a permanent
	   (not hover-only) underline so it still reads as the distinct
	   "go to this page" row above the rest of the list. */
	.dsbn-megamenu__heading {
		font-family: var(--dsbn-font-body);
		border-bottom-color: var(--dsbn-color-line);
		/* Not wrapped in an .dsbn-megamenu__item <li> like every other row,
		   so it's missing that li's own 0.85rem padding-bottom on top of
		   the 0.85rem it already gets from .dsbn-megamenu__link's
		   padding-block — without matching that combined 1.7rem total, the
		   gap before the first real link breaks the rhythm of every other
		   item-to-item gap in the list. Split across padding-bottom (above
		   the underline) and margin-bottom (below it, on top of the next
		   link's own 0.85rem built-in top padding) so the line sits centred
		   in that 1.7rem gap instead of jammed right against the item below
		   it: 1.275rem + (0.425rem + 0.85rem) = 1.275rem on each side. */
		padding-bottom: 1.275rem;
		margin-bottom: 0.425rem;
	}

	.dsbn-megamenu__sublist {
		padding-top: 0.25rem;
	}

	.dsbn-megamenu__sublist .dsbn-megamenu__item {
		font-size: 0.95rem;
	}

	.dsbn-megamenu__sublist .dsbn-megamenu__link {
		/* 0.65rem padding + this row's own 0.95rem/1.35 line-height worked
		   out to ~41px total tap height — just under the 44px touch-target
		   guideline (WCAG 2.5.5 / Apple HIG / Material Design). Depth-1
		   .dsbn-megamenu__link above is already ~49px, fine as-is. */
		padding-block: 0.85rem;
	}
}

@media screen and (max-width: 768px) {
	.dsbn-logo {
		width: clamp(7rem, 30vw, 8.25rem);
	}

	.dsbn-site-header {
		min-height: 4.25rem;
	}

	.dsbn-primary-nav {
		max-height: calc(100vh - 4.25rem);
	}

	.dsbn-utility-bar__inner {
		align-items: center;
		flex-direction: row;
		gap: 0.75rem;
		width: min(100% - 2rem, var(--dsbn-shell));
		padding-block: 0.25rem;
	}

	.dsbn-utility-menu {
		display: none;
	}

	.dsbn-utility-bar__actions {
		display: flex;
		align-items: center;
		/* Right-aligned rather than centered: once Login/Contact move into
		   the hamburger menu (<=1000px) and Quick Links hides (below),
		   this row is down to just Select Language / text size / high
		   contrast — three compact controls that read as a stray cluster
		   with big empty gutters on both sides when centered in an
		   otherwise-empty bar; right-aligned matches the usual convention
		   of grouping utility/accessibility icons in one corner. */
		justify-content: flex-end;
		flex: 1 1 auto;
		/* Tight — the two real accessibility controls (text size, high
		   contrast) should read as one cluster, not spaced out like
		   unrelated buttons. Select Language keeps its own separation from
		   that cluster via margin-right below instead of sharing this gap,
		   since it's a language/localization control, not an accessibility
		   one. */
		gap: 0.5rem;
		min-width: 0;
	}

	.dsbn-utility-bar__actions> :first-child {
		margin-right: 1rem;
	}

	.dsbn-utility-bar__link,
	.dsbn-utility-bar button {
		justify-content: center;
		width: auto;
		/* 44px — WCAG 2.5.5 / Apple HIG / Material Design's touch-target
		   guideline. Was 1.75rem (28px), noticeably cramped for a row of
		   tap targets. */
		min-height: 2.75rem;
		white-space: nowrap;
	}

	.dsbn-utility-bar__text-size {
		flex: 0 0 auto;
		min-height: 2.75rem;
	}

	/* The A/A buttons inherit 44px min-height from the generic
	   `.dsbn-utility-bar button` rule above, but that rule's own
	   `padding: 0` (base, non-mobile rule) left their clickable WIDTH at
	   just the glyph itself — well under the 44px WCAG 2.5.5 / Apple HIG /
	   Material touch-target guideline in that dimension, even though
	   height was already fixed in the earlier 44px sweep. */
	.dsbn-utility-bar__text-size button {
		min-width: 2.75rem;
	}

	/* Both buttons keep their full 44px tap zone, but center the glyph
	   toward the shared inner edge instead of the box's own middle — with
	   no visible button chrome, centering each glyph independently reads
	   as the A/A pair sitting far apart, even though the boxes themselves
	   are touching. */
	.dsbn-utility-bar__text-size button:first-child {
		justify-content: flex-end;
	}

	.dsbn-utility-bar__text-size button:last-child {
		justify-content: flex-start;
	}
}

.submenu-indicator {
	flex-shrink: 0;
	font-size: 1.25rem;
	font-weight: 600;
	line-height: 1;
}

/* SubPage Nav styling */
.subpage-nav .nav-link {
	font-family: var(--dsbn-font-body);
	color: var(--dsbn-color-ink);
	font-size: 1.13rem;
	font-weight: 600;
	padding: 0.5rem !important;
}

.subpage-nav .subpage-nav-row {
	display: flex;
	align-items: center;
	gap: 0.4rem;
}

.subpage-nav .subpage-nav-row .nav-link {
	flex: 1 1 auto;
}

/* Inside page template */
.dsbn-inside-page {
	--dsbn-inside-hero-color: var(--dsbn-color-primary);
	background: #fff;
}

.dsbn-inside-hero {
	position: relative;
	isolation: isolate;
	overflow: hidden;
	/* Was clamp(11rem, 22vw, 15rem). .dsbn-inside-hero__inner inherits this as
	   its own min-height and vertically centers the title within it — since
	   the title is much shorter than the box, the __inner padding-block below
	   has NO visible effect until content actually exceeds this min-height
	   (padding just gets absorbed into the centered gap). To actually add
	   visible breathing room around the title, the box itself needs to grow. */
	min-height: clamp(12rem, 24vw, 17rem);
	background: var(--dsbn-inside-hero-color);
}

.dsbn-inside-hero__media {
	position: absolute;
	inset: 0;
	z-index: -2;
	background-image: var(--dsbn-inside-hero-image);
	background-size: cover;
	background-position: center;
}

.dsbn-inside-hero::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background: linear-gradient(90deg,
			var(--dsbn-inside-hero-color) 0%,
			color-mix(in srgb, var(--dsbn-inside-hero-color) 85%, transparent) 30%,
			transparent 65%);
}

@media screen and (max-width: 600px) {

	/* Narrow hero = narrow photo real-estate — the same 30%/65% stops used on
	   desktop only leave a sliver of clear image on the far right, which read
	   fine there but wasn't "almost all blue" like intended for mobile. Pushed
	   both stops further right so the solid/near-solid color covers most of
	   the box, with just a thin hint of the photo peeking through the edge. */
	.dsbn-inside-hero::after {
		background: linear-gradient(90deg,
				var(--dsbn-inside-hero-color) 0%,
				color-mix(in srgb, var(--dsbn-inside-hero-color) 90%, transparent) 70%,
				transparent 92%);
	}
}

.dsbn-inside-hero__inner,
.dsbn-inside-layout {
	/* Uses the same --dsbn-gutter token as .dsbn-section's padding-inline
	   (patterns.css) so inside-page content gets the exact same side gutter,
	   pixel-for-pixel, as homepage sections at every viewport width — one
	   shared source of truth instead of two separately-tuned clamp()s. */
	width: min(calc(100% - (var(--dsbn-gutter) * 2)), var(--dsbn-shell));
	margin-inline: auto;
}

.dsbn-inside-breadcrumb {
	/* Normal flow — it's the first child of .dsbn-inside-hero__inner in
	   source order (verified: all 9 templates that render a breadcrumb nest
	   it there), so this just stacks it above the title, and __inner's
	   justify-content:center (below) centers the two together as one group.
	   A previous version pulled this out with position:absolute so the title
	   alone would center on its own, but that fixed top offset collided with
	   the title on mobile once a longer title wrapped to 2-3 lines within the
	   hero's fixed min-height floor — simpler to let both sit in flow.

	   Deliberately NOT in the shared width rule above: that rule subtracts a
	   --dsbn-gutter and re-centers, which is correct for __inner itself but
	   applied the gutter a SECOND time to the breadcrumb nested inside it —
	   making it narrower than, and indented from, the title it's supposed to
	   line up with. __inner's own width/centering is all it needs. */
	margin-bottom: 0.5rem;
}

.dsbn-inside-hero__inner {
	display: flex;
	min-height: inherit;
	flex-direction: column;
	justify-content: center;
	/* Slightly bigger than before (was clamp(1.5rem,4vw,2.5rem)) so the title
	   has a bit more breathing room above/below within the hero band. */
	padding-block: clamp(2rem, 5vw, 3.25rem);
}

.dsbn-inside-hero__title {
	/* Was a tight 14ch (forced even short-ish titles to wrap early). Widened
	   to half the hero's own inner width so long titles get real room before
	   wrapping, instead of an arbitrary character count. */
	max-width: 50%;
	margin: 0;
	text-wrap: balance;
	font-family: var(--dsbn-font-heading);
	/* Bumped from --dsbn-fs-section to --dsbn-fs-banner (36-60px) so this
	   template's main title reads clearly larger than an in-page h1/h2
	   (both now also --dsbn-fs-section, see the .pg-contents rules above) —
	   same convention as the hub template's .dsbn-hub-visual-hero__title. */
	font-size: var(--dsbn-fs-banner);
	/* Semibold to match .dsbn-hub-visual-hero__title and the slideshow's
	   .dsbn-slideshow-title__main — all three "main hero title" components
	   now share the same weight, not just the same size token. */
	font-weight: var(--dsbn-fw-semibold);
	line-height: var(--dsbn-lh-tight);
	color: #fff;
}

.dsbn-inside-hero__title--wide {
	max-width: 22ch;
}

/* Applied via dsbn_get_inside_hero_title_class() when the real title text is
   long — 50% still wraps a long title more than necessary, so give it more
   room. Comes after --wide in source order so it wins if a template ever
   carries both classes on the same title. */
.dsbn-inside-hero__title--long {
	max-width: 75%;
}

/* Applied alongside --long for genuinely long titles (full-sentence news
   headlines especially) — extra wrap room alone still rendered these at
   4+ lines of full hero size. Steps down to --dsbn-fs-section, the same
   token the other (smaller) inside-page hero titles already use, rather
   than a one-off size. Comes after --long so it wins the font-size tie. */
.dsbn-inside-hero__title--xlong {
	font-size: var(--dsbn-fs-section);
}

.dsbn-inside-breadcrumb {
	font-family: var(--dsbn-font-body);
	font-size: 0.8125rem;
	font-weight: var(--dsbn-fw-medium);
	color: rgba(255, 255, 255, 0.85);
}

.dsbn-inside-breadcrumb ol {
	display: flex;
	flex-wrap: wrap;
	gap: 0.35rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.dsbn-inside-breadcrumb li:not(:last-child)::after {
	content: ">";
	margin-left: 0.35rem;
	color: rgba(255, 255, 255, 0.7);
}

.dsbn-inside-breadcrumb a {
	color: inherit;
	text-decoration: none;
}

.dsbn-inside-breadcrumb a:hover {
	text-decoration: underline;
	text-underline-offset: 0.2em;
}

@media screen and (max-width: 600px) {

	/* Collapse the trail to just the immediate parent on phones. The full
	   4-level trail wrapped to ~3 lines inside the hero, crowding the title
	   it sits above; "‹ Parent" is one line and is the affordance that
	   actually gets used at this size (go up one level).

	   dsbn_render_inside_page_breadcrumbs() always emits Home first and the
	   current page last (aria-current="page"), so the immediate parent is
	   reliably :nth-last-child(2) — and on a top-level page, where there are
	   no ancestors between them, that resolves to "Home", which is still the
	   correct parent. There are always >= 2 items, so this never selects
	   nothing and blanks the breadcrumb out.

	   Hiding the intermediate crumbs with display:none takes them out of the
	   accessibility tree too, which is the intent — this is a collapsed
	   breadcrumb, not a visually-hidden one; the parent link remains as the
	   real "up" control, and the trail is still complete on wider screens.

	   Must come AFTER the `li:not(:last-child)::after` separator rule above:
	   both land on identical specificity (0,2,2), so source order is what
	   lets `content: none` actually suppress the trailing ">" here. */
	.dsbn-inside-breadcrumb li {
		display: none;
	}

	.dsbn-inside-breadcrumb li:nth-last-child(2) {
		display: block;
	}

	.dsbn-inside-breadcrumb li:nth-last-child(2)::after {
		content: none;
	}

	.dsbn-inside-breadcrumb li:nth-last-child(2)::before {
		content: "\2039";
		margin-right: 0.35rem;
		color: rgba(255, 255, 255, 0.7);
	}
}

.dsbn-inside-layout {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(18rem, 22.5rem);
	gap: clamp(2rem, 6vw, 5rem);
	align-items: start;
	padding-block: clamp(2.5rem, 6vw, 4.5rem) clamp(4rem, 8vw, 7rem);
}

.dsbn-inside-content {
	min-width: 0;
	width: 100%;
	font-family: var(--dsbn-font-body);
	font-size: var(--dsbn-fs-body);
	line-height: var(--dsbn-lh-body);
	color: var(--dsbn-color-body);
}

.dsbn-inside-content :where(.alignwide, .alignfull, .wp-block-cover, .wp-block-columns, .wp-block-group, .wp-block-image, img) {
	max-width: 100%;
}

.dsbn-inside-content :where(img) {
	height: auto;
}

.dsbn-inside-content .offset-feature-image {
	width: min(100%, 400px);
}

.dsbn-inside-content> :first-child {
	margin-top: 0;
}

.dsbn-inside-content h2,
.dsbn-inside-content h3,
.dsbn-inside-content h4 {
	color: var(--dsbn-color-ink);
}

.dsbn-inside-content a:not(.dsbn-btn) {
	color: var(--dsbn-color-primary);
	font-weight: var(--dsbn-fw-bold);
}

.dsbn-entry-intro {
	margin-bottom: clamp(1.5rem, 4vw, 2.5rem);
}

.dsbn-entry-meta {
	display: flex;
	flex-wrap: wrap;
	gap: 0.35rem 0.8rem;
	margin-bottom: clamp(1.5rem, 4vw, 2.5rem);
	font-family: var(--dsbn-font-body);
	/* Matches the article body's own size/color (--dsbn-fs-body/-color-body)
	   rather than the old one-off small-muted-gray combo, which wasn't tied
	   to anything else in the type scale. Kept at medium weight (already had
	   it) so the date still reads as a label, not the first line of body
	   copy. */
	font-size: var(--dsbn-fs-body);
	font-weight: var(--dsbn-fw-medium);
	color: var(--dsbn-color-body);
}

.dsbn-news-card .dsbn-eyebrow {
	margin-bottom: 0.35rem;
}

.dsbn-entry-empty {
	padding: clamp(1.5rem, 4vw, 2.25rem);
	border: 1px solid rgba(0, 75, 152, 0.18);
	border-radius: 32px;
	background: var(--dsbn-surface-blue-soft);
	font-family: var(--dsbn-font-body);
	font-size: 1.0625rem;
	color: var(--dsbn-color-body);
	box-shadow: 0 12px 30px rgba(6, 33, 62, 0.06);
}

/* Any table in real page content — a Table block OR a hand-authored
   <table> from a Custom HTML/Classic block (e.g. pasted from Google Docs,
   which is the only way to get real lists inside table cells; Gutenberg's
   Table block cells are plain RichText, they can't hold a List block).
   Kept intentionally simple so any table reads as part of the design
   system: body font, a light header band, hairline row borders,
   comfortable padding. Scoped to real page content (.dsbn-inside-content)
   plus the editor canvas (.editor-styles-wrapper) so it looks the same
   while editing. Specificity (0,2,0) intentionally beats WordPress core's
   own .wp-block-table cell rules.
   .wp-block-table and (legacy Google-Docs-paste) .table-responsive both
   get their own overflow-x rule below — a Table block always has the
   former wrapper div, a hand-authored table only scrolls on narrow
   screens if its markup happens to include the latter. */
.dsbn-inside-content .wp-block-table,
.dsbn-inside-content .table-responsive,
.editor-styles-wrapper .wp-block-table,
.editor-styles-wrapper .table-responsive {
	overflow-x: auto;
}

.dsbn-inside-content table,
.editor-styles-wrapper table {
	width: 100%;
	border-collapse: collapse;
	margin-block: clamp(1.5rem, 3vw, 2rem);
	font-family: var(--dsbn-font-body);
	font-size: 1rem;
	line-height: var(--dsbn-lh-body);
	color: var(--dsbn-color-body);
}

.dsbn-inside-content th,
.dsbn-inside-content td,
.editor-styles-wrapper th,
.editor-styles-wrapper td {
	padding: 0.75rem 1rem;
	text-align: left;
	vertical-align: top;
	border: 1px solid var(--dsbn-color-line);
}

.dsbn-inside-content th,
.editor-styles-wrapper th {
	background: var(--dsbn-surface-gray);
	color: var(--dsbn-color-ink);
	font-weight: var(--dsbn-fw-semibold);
}

/* A Custom HTML block previews its rendered output inside a SECOND,
   sandboxed iframe (Gutenberg's <SandBox>, `sandbox="allow-scripts
   allow-presentation"` — deliberate isolation so pasted HTML can't touch
   the parent editor). This stylesheet does get inlined into that sandbox's
   own <head>, but its <body> is bare — no .dsbn-inside-content or
   .editor-styles-wrapper to hook into, just <body><div><table>. Unscoped
   fallback so a table styles correctly there too. Lower specificity (0,1,0)
   than the rules above, so it only fills the gap rather than overriding
   anything; safe unscoped because style.css never loads anywhere else a
   bare <table> would plausibly appear (not enqueued in wp-admin chrome). */
table {
	width: 100%;
	border-collapse: collapse;
	margin-block: clamp(1.5rem, 3vw, 2rem);
	font-family: var(--dsbn-font-body);
	font-size: 1rem;
	line-height: var(--dsbn-lh-body);
	color: var(--dsbn-color-body);
}

th,
td {
	padding: 0.75rem 1rem;
	text-align: left;
	vertical-align: top;
	border: 1px solid var(--dsbn-color-line);
}

th {
	background: var(--dsbn-surface-gray);
	color: var(--dsbn-color-ink);
	font-weight: var(--dsbn-fw-semibold);
}

/* Lists nested inside a table cell (only possible via hand-authored
   markup, see above) — browser-default <ul> spacing (40px indent, 1em
   margin) reads too heavy inside an already-padded td. Tightened, not
   removed, so it still reads as a list. */
.dsbn-inside-content td ul,
.dsbn-inside-content td ol,
.editor-styles-wrapper td ul,
.editor-styles-wrapper td ol,
td ul,
td ol {
	margin: 0.5rem 0;
	padding-left: 1.25rem;
}

.dsbn-inside-content td p,
.editor-styles-wrapper td p,
td p {
	margin: 0 0 0.5rem;
}

.dsbn-inside-content td p:last-child,
.editor-styles-wrapper td p:last-child,
td p:last-child {
	margin-bottom: 0;
}

.dsbn-inside-content .navigation.pagination {
	margin-top: clamp(2rem, 5vw, 3rem);
	font-family: var(--dsbn-font-body);
}

.dsbn-inside-content .navigation.pagination .screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.dsbn-inside-content .nav-links {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
}

.dsbn-inside-content .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 2.75rem;
	min-height: 2.75rem;
	padding: 0.55rem 0.85rem;
	border: 1px solid var(--dsbn-color-line);
	border-radius: var(--dsbn-radius-sm);
	background: #fff;
	color: var(--dsbn-color-primary);
	font-size: 1rem;
	font-weight: var(--dsbn-fw-bold);
	line-height: 1;
	text-decoration: none;
	transition: background var(--dsbn-transition), border-color var(--dsbn-transition), color var(--dsbn-transition), transform var(--dsbn-transition);
}

.dsbn-inside-content a.page-numbers:hover,
.dsbn-inside-content a.page-numbers:focus-visible {
	border-color: var(--dsbn-color-primary);
	background: var(--dsbn-surface-blue-soft);
	color: var(--dsbn-color-primary);
	transform: translateY(-1px);
}

.dsbn-inside-content a.page-numbers:focus-visible {
	outline: 3px solid var(--dsbn-color-accent-blue);
	outline-offset: 3px;
}

.dsbn-inside-content .page-numbers.current {
	border-color: var(--dsbn-color-primary);
	background: var(--dsbn-color-primary);
	color: #fff;
}

.dsbn-inside-content .page-numbers.dots {
	min-width: auto;
	border-color: transparent;
	background: transparent;
	color: var(--dsbn-color-muted);
}

.dsbn-inside-content .page-numbers.prev,
.dsbn-inside-content .page-numbers.next {
	gap: 0.35rem;
	padding-inline: 1rem;
	min-width: auto;
}

.dsbn-post-navigation {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	gap: 1rem;
	padding-top: 2rem;
	border-top: 1px solid rgba(0, 75, 152, 0.18);
}

.dsbn-post-navigation>div:last-child {
	margin-left: auto;
}

.dsbn-inside-sidebar {
	position: sticky;
	top: 1.5rem;
}

.dsbn-inside-sidebar:empty {
	display: none;
}

.dsbn-inside-layout:has(.dsbn-inside-sidebar:empty) {
	grid-template-columns: minmax(0, 1fr);
}

.dsbn-inside-layout--no-sidebar {
	grid-template-columns: minmax(0, 1fr);
}

.dsbn-inside-layout--no-sidebar .dsbn-inside-content {
	max-width: none;
	width: 100%;
}

.dsbn-hub-visual-hero {
	position: relative;
	isolation: isolate;
	overflow: hidden;
	/* Same fixed height as the homepage slideshow (.carousel-item), with the
	   same tablet/mobile step-down breakpoints, so hub-hero and homepage-hero
	   feel like the same component at every width. */
	height: 625px;
	background: var(--dsbn-inside-hero-color);
	/* Neutral dark scrim used when a colour overlay toggle is off (see the
	   overlay rules below) — ink-tinted rather than pure black, biased left
	   where the hero text sits, so the bare photo still keeps legible text. */
	--dsbn-hub-hero-scrim: linear-gradient(90deg,
			rgba(6, 33, 62, 0.72) 0%,
			rgba(6, 33, 62, 0.45) 45%,
			rgba(6, 33, 62, 0.2) 100%);
}

@media screen and (max-width: 991px) {
	.dsbn-hub-visual-hero {
		height: clamp(19rem, 56vw, 31.125rem);
	}
}

@media screen and (max-width: 768px) {
	.dsbn-hub-visual-hero {
		height: clamp(24rem, calc(90svh - 8.5rem), 41rem);
	}
}

.dsbn-hub-visual-hero__media {
	position: absolute;
	inset: 0;
	z-index: -2;
	background-image: var(--dsbn-inside-hero-image);
	background-size: cover;
	background-position: center;
}

/* Optional mobile-only override photo (dsbn_hub_hero_mobile_image), sat on
   top of the regular Featured Image .dsbn-hub-visual-hero__media above via
   a higher z-index, and only shown from the hub hero's own tablet/mobile
   breakpoint down — desktop always keeps the regular photo. */
.dsbn-hub-visual-hero__media--mobile {
	display: none;
}

@media screen and (max-width: 768px) {
	.dsbn-hub-visual-hero__media--mobile {
		display: block;
		z-index: -1;
		background-image: var(--dsbn-inside-hero-image-mobile);
	}
}

.dsbn-hub-visual-hero::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 0;
	/* Figma spec: linear-gradient(284deg, #015DA800 0%, #04508E 100%) — still
	   driven by --dsbn-inside-hero-color (customizable per-page color picker)
	   rather than a hardcoded hex. The darkest tone is only a very thin far-left
	   edge, and the wash is kept tighter so it does not flood the subject area. */
	background: linear-gradient(284deg,
			transparent 52%,
			var(--dsbn-inside-hero-color) 86%,
			color-mix(in srgb, var(--dsbn-inside-hero-color) 65%, black) 98%,
			color-mix(in srgb, var(--dsbn-inside-hero-color) 65%, black) 100%);
	pointer-events: none;
}

/* Overlay toggles (dsbn_hub_hero_overlay_desktop / _mobile). "Off" swaps the
   brand-colour wash for the neutral dark scrim so hero text stays legible on
   the bare photo. Split by width so each breakpoint's toggle is independent:
   the desktop-off rule is gated min-width:769px so it never leaks onto mobile,
   and the whole mobile overlay (colour wash, its optional per-page mobile
   colour override, or the scrim) lives in the max-width:768px block. Each
   rule matches the base ::after specificity (0-1-1) and wins on source order,
   so it must stay AFTER the base rule above. */
@media screen and (min-width: 769px) {
	.dsbn-hub-visual-hero--no-overlay-desktop::after {
		background: var(--dsbn-hub-hero-scrim);
	}
}

@media screen and (max-width: 768px) {
	.dsbn-hub-visual-hero::after {
		background: linear-gradient(284deg,
				transparent 52%,
				var(--dsbn-inside-hero-color-mobile, var(--dsbn-inside-hero-color)) 86%,
				color-mix(in srgb, var(--dsbn-inside-hero-color-mobile, var(--dsbn-inside-hero-color)) 65%, black) 98%,
				color-mix(in srgb, var(--dsbn-inside-hero-color-mobile, var(--dsbn-inside-hero-color)) 65%, black) 100%);
	}

	.dsbn-hub-visual-hero--no-overlay-mobile::after {
		background: var(--dsbn-hub-hero-scrim);
	}
}

.dsbn-hub-visual-hero__inner,
.dsbn-hub-page__layout {
	/* Same shared --dsbn-gutter/--dsbn-shell tokens as .dsbn-inside-hero__inner
	   / .dsbn-inside-layout and .dsbn-section — this formula previously used
	   its own standalone clamp() and drifted out of sync with the rest of the
	   site's side gutter. */
	width: min(calc(100% - (var(--dsbn-gutter) * 2)), var(--dsbn-shell));
	margin-inline: auto;
}

/* Unlike the top intro+sidebar row above, .dsbn-hub-page__full sits OUTSIDE
   that grid as its own full-bleed area (no sidebar to share width with) —
   left genuinely full width (100%, no shell cap) so any .dsbn-section
   inserted as page content here can stretch its background edge-to-edge,
   the same as on front-page.php/page.php. Its .dsbn-section children
   provide their own padding-inline gutter + .dsbn-container shell-centering,
   exactly like every other full-bleed template. */
.dsbn-hub-page__full {
	width: 100%;
}

.dsbn-hub-visual-hero__inner {
	position: relative;
	z-index: 1;
	display: flex;
	/* Parent now sets a fixed `height` (not `min-height`), so this needs to
	   match that via height:100% rather than min-height:inherit (inheriting
	   an unset min-height was a no-op, leaving the title/description
	   top-aligned instead of vertically centered). */
	height: 100%;
	/* No global box-sizing:border-box reset is loaded (bootstrap.css itself
	   isn't enqueued) — the few explicit border-box declarations that do
	   exist are scoped to individual components (e.g. .emergency-notification
	   below). Without this, height:100%
	   plus padding-block below added the padding ON TOP of that 100%,
	   overflowing the parent's fixed/clamped height and pushing content
	   outside the hero, clipped by its overflow:hidden. */
	box-sizing: border-box;
	flex-direction: column;
	justify-content: center;
	padding-block: clamp(2rem, 6vw, 4rem);
}

.dsbn-hub-visual-hero__title {
	max-width: 12ch;
	margin: 0;
	text-wrap: balance;
	font-family: var(--dsbn-font-heading);
	/* --dsbn-fs-hub's 110px ceiling was too large for a photo hero (that token
	   is meant for the big in-content hub-hero display heading, not this
	   banner-style title). --dsbn-fs-banner matches the homepage slideshow's
	   own title scale (fixed 3.75rem/60px past ~1000px viewport width) while
	   still giving a bigger mobile floor (2.25rem/36px) than the old
	   --dsbn-fs-section (2rem/32px). */
	font-size: var(--dsbn-fs-banner);
	font-weight: var(--dsbn-fw-semibold);
	line-height: var(--dsbn-lh-tight);
	color: #fff;
}

.dsbn-hub-visual-hero__description {
	max-width: 28rem;
	margin: 0.75rem 0 0;
	font-family: var(--dsbn-font-body);
	/* Caps at --dsbn-fs-banner-sub ("Banner Subheadings — DM Sans 30", matches
	   the requested 30pt/DM Sans/medium spec) on desktop/tablet, but scales
	   down on narrow phones instead of staying fixed at 30px — at 30px it read
	   almost as big as the title once the title's own mobile floor kicked in. */
	font-size: clamp(1.125rem, 4vw, var(--dsbn-fs-banner-sub));
	font-weight: var(--dsbn-fw-medium);
	/* --dsbn-lh-body (1.6) is tuned for running paragraph copy, not a large
	   1-2 line hero subtitle — at 30px that's 48px between lines, looking
	   loose/gappy. --dsbn-lh-heading (1.2) reads tighter/correct at this size. */
	line-height: var(--dsbn-lh-heading);
	color: #fff;
}

/* Optional hero call-to-action row. `align-self` matters: .dsbn-btn-row is a
   flex item of the column above, whose default align-items:stretch would
   otherwise widen it to the full shell — harmless for the buttons themselves
   (they're inline-flex) but it makes the row a full-width target sitting over
   the photo. Sized to its own content instead. Top margin is larger than the
   description's 0.75rem so the buttons read as a separate action, not as a
   third line of the sentence above them.
   `.dsbn-hub-visual-hero__actions` alone, at equal 0-1-0 specificity to
   patterns.css's own `.dsbn-btn-row { margin: 0; }` (loaded after this
   file), silently lost the margin-top to source order — patterns.css always
   wins ties. Compounding the two classes into one selector isn't just
   belt-and-suspenders: at 0-2-0 it now actually beats that rule regardless
   of load order. */
.dsbn-btn-row.dsbn-hub-visual-hero__actions {
	align-self: flex-start;
	margin-top: clamp(1.25rem, 3vw, 2rem);
}

.dsbn-hub-page__layout {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(18rem, 22.5rem);
	gap: clamp(2rem, 6vw, 5rem);
	align-items: start;
	/* Was an asymmetric clamp() pair (2.5-4.5rem top, 4-7rem bottom) —
	   noticeably more space below the intro/sidebar row than above it, and
	   both ends larger than every .dsbn-section's own padding-block
	   elsewhere on the site. Same --dsbn-section-pad token as everything
	   else, applied symmetrically. */
	padding-block: var(--dsbn-section-pad);
}

.dsbn-hub-page .dsbn-inside-content {
	max-width: none;
}

.dsbn-hub-page .dsbn-inside-content> :first-child {
	margin-top: 0;
}

.dsbn-hub-page .dsbn-inside-sidebar {
	position: sticky;
	top: 1.5rem;
}

.dsbn-hub-page .dsbn-inside-sidebar:empty {
	display: none;
}

.dsbn-hub-page__layout:has(.dsbn-inside-sidebar:empty) {
	grid-template-columns: minmax(0, 1fr);
}

/* Hub page with neither an intro nor page content: only the section-nav
   sidebar is left, so the empty main column would otherwise reserve half the
   row. Collapse to just the sidebar column (kept on the right where it always
   sits). Higher specificity than the :empty rule above so an empty sidebar
   here collapses the whole row rather than reappearing as a 1fr column. */
.dsbn-hub-page__layout--no-intro {
	grid-template-columns: minmax(18rem, 22.5rem);
	justify-content: end;
}

.dsbn-hub-page__layout--no-intro:has(.dsbn-inside-sidebar:empty) {
	display: none;
}

.dsbn-hub-page__full {
	padding-block: 0 clamp(4rem, 8vw, 7rem);
}

/* Same "last full-bleed background section eats the layout's own bottom
   padding" trick the with-sidebar/no-sidebar inside-page templates already
   have — a colored last section otherwise gets an oversized blank gap
   between its own bottom edge and the footer. This was documented (2026-07-29
   phase-plan) as already added, but the actual rule was never committed —
   only checked here now. Also broader than a plain .has-background check
   would have been: real content uses both WP's native background-color
   picker (.has-background) AND the DSBN section presets (patterns.css'
   .dsbn-section--white/tint/cream/gray/alt) — a page ending in a preset
   class alone (no native background set) would otherwise still show the
   bug the fix was meant to close.

   The second selector exists because Gutenberg routinely leaves an EMPTY
   trailing paragraph in saved content (press Enter at the end of a page and
   you get one). It renders at zero height, so it's invisible — but it is the
   real last element child, and `:last-child` is structural, not visual, so it
   silently stopped this rule matching and the gap came back. Tolerate exactly
   that one case rather than relying on editors to notice and delete it. */
.dsbn-hub-page__full:has(>.dsbn-section:last-child:is(.has-background, .dsbn-section--white, .dsbn-section--tint, .dsbn-section--cream, .dsbn-section--gray, .dsbn-section--alt)),
.dsbn-hub-page__full:has(>.dsbn-section:is(.has-background, .dsbn-section--white, .dsbn-section--tint, .dsbn-section--cream, .dsbn-section--gray, .dsbn-section--alt)+p:empty:last-child) {
	padding-bottom: 0;
}

/* ...and the paragraph itself still carried its own 18px margins into the
   gap even once the padding above was collapsed. Zero height, no text, no
   reason to occupy space. Kept to the trailing one specifically — an empty
   paragraph in the middle of content is at least plausibly deliberate
   spacing, while a trailing one is just editor residue. */
.dsbn-hub-page__full>p:empty:last-child,
.dsbn-inside-content>p:empty:last-child {
	display: none;
}

.dsbn-hub-page__full> :first-child {
	margin-top: 0;
}

/* No negative-margin cancellation here (removed) — .dsbn-hub-page__layout's
   own bottom padding above is now the real, visible gap between the top
   intro/sidebar row and whatever renders below it. */

.dsbn-hub-hero__nav.dsbn-inside-nav {
	border-radius: 8px;
	padding: 1.25rem;
}

.dsbn-inside-nav .dsbn-hub-hero__nav-label {
	padding: 0 0.15rem 0.7rem;
	margin-bottom: 0.75rem;
	font-size: 0.75rem;
	letter-spacing: 0.08em;
	cursor: default;
}

.dsbn-inside-nav .dsbn-hub-hero__nav-list {
	margin-top: 0.75rem;
}

.dsbn-inside-nav .dsbn-hub-hero__nav-icon {
	width: 0.9rem;
	height: 0.9rem;
}

.dsbn-hub-hero__nav.dsbn-inside-nav a {
	gap: 0.65rem;
	padding: 0.6rem 0.65rem;
	font-size: 1rem;
	line-height: 1.3;
}

@media (max-width: 1024px) {

	.dsbn-inside-layout,
	.dsbn-hub-page__layout {
		grid-template-columns: 1fr;
	}

	.dsbn-inside-sidebar {
		position: static;
		order: -1;
	}
}

.subpage-nav .subpage-toggle {
	text-decoration: none !important;
	min-width: 0.75rem;
	margin-left: auto;
	/* .btn-link's real background/border rules were trimmed out of
	   bootstrap-shim.css when it was reduced to only its still-genuinely-
	   used pieces, leaving this a plain unstyled <button> — browsers paint
	   a visible light-grey default background behind the +/- indicator
	   without this. */
	background: none;
	border: none;
}

.subpage-nav .subpage-toggle:hover,
.subpage-nav .subpage-toggle:focus {
	text-decoration: none !important;
}

.subpage-nav .subpage-toggle .submenu-indicator {
	font-weight: 700;
	color: var(--bs-primary);
	line-height: 1;
}

.subpage-nav .subpage-nav-item {
	margin-bottom: 0.15rem;
}

.subpage-nav .subpage-nav-children {
	background-color: var(--bs-white);
	border-radius: 0.375rem;
	margin: 0.15rem 0 0.35rem;
	padding: 0.3rem 0.4rem;
}

.subpage-nav .nav-link.nav-depth-1 {
	padding-left: 0.5rem !important;
}

.subpage-nav .nav-link.nav-depth-2 {
	padding-left: 1.25rem !important;
}

.subpage-nav .nav-link.nav-depth-3 {
	padding-left: 2rem !important;
}

.subpage-nav .nav-link.nav-depth-4,
.subpage-nav .nav-link.nav-depth-5,
.subpage-nav .nav-link.nav-depth-6 {
	padding-left: 2.75rem !important;
}

.subpage-nav .nav-link.active {
	position: relative;
	padding-left: 0.5rem !important;
	font-weight: bold;
	color: var(--bs-primary) !important;
}

.subpage-nav .nav-link.nav-depth-2.active {
	padding-left: 1.25rem !important;
}

.subpage-nav .nav-link.nav-depth-2.active::before {
	left: 0rem !important;
}

.subpage-nav .nav-link.nav-depth-3.active {
	padding-left: 2rem !important;
}

.subpage-nav .nav-link.nav-depth-4.active,
.subpage-nav .nav-link.nav-depth-5.active,
.subpage-nav .nav-link.nav-depth-6.active {
	padding-left: 2.75rem !important;
}


.subpage-nav .nav-link.active::before {
	content: "";
	position: absolute;
	left: -0.5rem;
	top: 50%;
	width: 0.5rem;
	height: 0.5rem;
	background-color: var(--bs-primary);
	border-radius: 50%;
	transform: translateY(-50%);
}

/* FAQ collapse toggle icon rotation */
.faq-collapse .btn .faq-collapse-toggle-icon {
	display: inline-block;
	flex: 0 0 auto;
	transition: transform 0.25s ease;
	transform: rotate(0deg);
	transform-origin: center;
}

.faq-collapse .btn[aria-expanded="true"] .faq-collapse-toggle-icon {
	transform: rotate(0deg);
}

.faq-collapse .btn[aria-expanded="false"] .faq-collapse-toggle-icon {
	transform: rotate(180deg);
}

/* Close buttons in dropdowns */
.close-dropdown {
	border: none !important;
	background: transparent !important;
	padding: 0.25rem 0 !important;
	margin-left: 1rem;
	text-decoration: none !important;
	cursor: pointer;
}

.close-dropdown:hover,
.close-dropdown:focus {
	background: transparent !important;
	color: var(--bs-light) !important;
}

.close-dropdown:focus {
	outline: 2px solid var(--accent);
	outline-offset: 2px;
}

/* Font size controls */
.btn-link {
	color: inherit;
	text-decoration: none;
	border: none;
	padding: 0;
	font-size: inherit;
}

.btn-link:hover,
.btn-link:focus {
	text-decoration: underline;
}

.btn-link:focus {
	outline: 2px solid var(--accent);
	outline-offset: 2px;
}

/* Carousel styling */

/* Base carousel structure (formerly provided by Bootstrap's Carousel CSS —
   ported here now that bootstrap.css is removed; the vanilla-JS carousel
   engine in the DSBN Slideshow plugin drives the same .active class /
   data-bs-* attribute names for minimal markup + selector churn). Slides
   are stacked (position:absolute, inset:0) and cross-fade via opacity
   rather than reproducing Bootstrap's horizontal slide-transform, which
   keeps the implementation small per the removal plan. */
.carousel {
	position: relative;
}

.carousel-inner {
	position: relative;
	width: 100%;
	min-height: 625px;
	overflow: hidden;
}

.carousel-item {
	position: absolute;
	inset: 0;
	display: block;
	opacity: 0;
	visibility: hidden;
	z-index: 0;
	backface-visibility: hidden;
	/* visibility isn't itself fade-able, so without a delay it snaps to
	   hidden the instant .active is removed — before opacity finishes
	   fading out — which briefly exposes the bare background behind both
	   slides (the flash on slide change). Delaying it by the full fade
	   duration keeps the outgoing slide rendered until it's fully
	   transparent, so the two opacities genuinely cross-fade. */
	transition: opacity 0.6s ease-in-out, visibility 0s linear 0.6s;
}

.carousel-item.active {
	opacity: 1;
	visibility: visible;
	z-index: 1;
	transition: opacity 0.6s ease-in-out, visibility 0s linear 0s;
}

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

.carousel-control-prev,
.carousel-control-next {
	position: absolute;
	inset-block: 0;
	z-index: 3;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 15%;
	padding: 0;
	color: #fff;
	text-align: center;
	background: none;
	border: 0;
	opacity: 0.5;
	transition: opacity 0.15s ease;
}

.carousel-control-prev:hover,
.carousel-control-prev:focus,
.carousel-control-next:hover,
.carousel-control-next:focus {
	color: #fff;
	text-decoration: none;
	outline: 0;
	opacity: 0.9;
}

.carousel-control-prev {
	left: 0;
}

.carousel-control-next {
	right: 0;
}

.carousel-control-prev-icon,
.carousel-control-next-icon {
	display: inline-block;
	width: 2rem;
	height: 2rem;
	background-repeat: no-repeat;
	background-position: 50%;
	background-size: 100% 100%;
}

.carousel-control-prev-icon {
	background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0'/%3e%3c/svg%3e");
}

.carousel-control-next-icon {
	background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708'/%3e%3c/svg%3e");
}

.carousel-indicators {
	position: absolute;
	right: 0;
	bottom: 0;
	left: 0;
	z-index: 3;
	display: flex;
	justify-content: center;
	padding: 0;
	margin-right: 15%;
	margin-bottom: 1rem;
	margin-left: 15%;
}

.carousel-indicators [data-bs-target] {
	box-sizing: content-box;
	flex: 0 1 auto;
	width: 30px;
	height: 3px;
	padding: 0;
	margin-right: 3px;
	margin-left: 3px;
	text-indent: -999px;
	cursor: pointer;
	background-color: #fff;
	background-clip: padding-box;
	border: 0;
	border-top: 10px solid transparent;
	border-bottom: 10px solid transparent;
	opacity: 0.5;
	transition: opacity 0.6s ease;
}

.carousel-indicators .active {
	opacity: 1;
}

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

	.carousel-control-prev,
	.carousel-control-next,
	.carousel-indicators [data-bs-target] {
		transition: none;
	}
}

.carousel-title {
	position: absolute;
	top: 50%;
	/* Uses --dsbn-carousel-edge-zone (design-tokens.css) — the SAME value
	   the prev/next arrow icons center themselves within below, so the title
	   always starts exactly where the arrow's zone ends, not from an
	   independently-computed guess. Falls back to the normal shell-centering
	   math once the viewport exceeds the shell width, same as before. */
	left: max(var(--dsbn-carousel-edge-zone), (100% - var(--dsbn-shell)) / 2);
	transform: translateY(-50%);
	max-width: var(--dsbn-carousel-title-max);
	color: white;
	font-size: 3rem;
	line-height: normal;
}

@media screen and (max-width: 768px) {
	.carousel-title {
		/* Matches --dsbn-fs-banner (same token/floor .dsbn-hub-visual-hero__title
		   uses) instead of an unrelated hardcoded 2rem, so the homepage slideshow
		   title reads at the same size as the hub hero title on mobile. Applies
		   to every layout — only the position rule below needs excluding. */
		font-size: var(--dsbn-fs-banner);
	}

	/* Position/width only actually applies to overlay-left (the default) and
	   image-only — overlay-center/bottom-banner/color-center each set their
	   own continuously-responsive position via clamp()/calc() (see their own
	   rules further down), not tied to this breakpoint at all, and don't need
	   arrow-clearance values tuned specifically for overlay-left. Before this
	   was one unscoped `.carousel-title` rule that those three layouts'
	   higher-specificity two-class selectors happened to always beat — worked,
	   but by accident of source order/specificity, not because the exclusion
	   was deliberate. Excluding them explicitly here means a future edit to
	   this position rule can't silently stop affecting them without anyone
	   noticing. */
	.carousel-item:not(.carousel-item--layout-overlay-center):not(.carousel-item--layout-bottom-banner):not(.carousel-item--layout-color-center) .carousel-title {
		top: 50%;
		/* The prev/next arrow buttons are width: clamp(4rem, 7vw, 6.5rem)
		   (see .carousel-control-prev/-next below) — at every viewport in
		   this <=768px range, 7vw is smaller than the 4rem floor, so the
		   buttons are a flat 4rem (64px) wide the whole time. left:3rem
		   (48px) used to start the title 16px INSIDE that zone, overlapping
		   the arrow. Clearing the full 4rem button plus a small gap fixes
		   the overlap on both edges (max-width leaves the same 4.5rem clear
		   on the right for the next-arrow zone). */
		left: 4.5rem;
		max-width: calc(100% - 9rem);
	}

}

.carousel-control-prev,
.carousel-control-next {
	width: clamp(4rem, 7vw, 6.5rem) !important;
}

.carousel-item {
	max-height: 625px;
}

#main-content>.carousel {
	overflow: hidden;
	width: 100%;
	max-width: none;
	margin-inline: 0;
}

#main-content>.carousel .carousel-item {
	/* Stays position:absolute (from the base .carousel-item rule above) so
	   slides stack for the cross-fade transition instead of each pushing
	   .carousel-inner's height in normal flow. */
	max-height: none;
}

#main-content>.carousel .carousel-item>img {
	/* >img not the descendant form — that'd also stretch image-left/-right's own nested, differently-sized <img>. */
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
}

#main-content>.carousel .carousel-item::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	/* A slight dark tint confined to the left, where the title sits, so the
	   image reads clean and bright across its right half. */
	background: linear-gradient(90deg, rgba(0, 20, 40, 0.45) 0%, rgba(0, 20, 40, 0.18) 30%, rgba(0, 0, 0, 0) 55%);
	pointer-events: none;
}

/* Individual pale photos can opt into a deeper scrim without changing the
   balanced default used by the rest of the overlay-left slides. */
#main-content>.carousel .carousel-item--overlay-strong::before {
	background: linear-gradient(90deg, rgba(0, 20, 40, 0.62) 0%, rgba(0, 20, 40, 0.32) 35%, rgba(0, 0, 0, 0) 60%);
}

#main-content>.carousel .carousel-title {
	z-index: 2;
}

#main-content>.carousel .carousel-indicators {
	z-index: 4;
	bottom: clamp(1rem, 3vw, 2rem);
	gap: 0.6rem;
	margin-bottom: 0;
}

#main-content>.carousel .carousel-indicators [data-bs-target] {
	width: 0.75rem;
	height: 0.75rem;
	border: 2px solid #fff;
	border-radius: var(--dsbn-radius-pill);
	background: transparent;
	opacity: 1;
	transition: width 180ms ease, background-color 180ms ease;
}

#main-content>.carousel .carousel-indicators .active {
	width: 2.25rem;
	background: #fff;
}

#main-content>.carousel .carousel-control-prev,
#main-content>.carousel .carousel-control-next {
	z-index: 4;
	opacity: 1;
}

#main-content>.carousel .carousel-control-prev {
	justify-content: flex-start;
	/* Centers the icon within --dsbn-carousel-edge-zone (the same zone
	   .carousel-title starts right after) — (zone - icon width) / 2. */
	padding-left: calc((var(--dsbn-carousel-edge-zone) - 2.5rem) / 2);
}

#main-content>.carousel .carousel-control-next {
	justify-content: flex-end;
	padding-right: calc((var(--dsbn-carousel-edge-zone) - 2.5rem) / 2);
}

@media screen and (max-width: 768px) {

	#main-content>.carousel .carousel-indicators {
		bottom: 0.85rem;
	}
}

@media screen and (max-width: 991px) {

	#main-content>.carousel,
	#main-content>.carousel .carousel-inner,
	#main-content>.carousel .carousel-item,
	#main-content>.carousel .carousel-item>img {
		height: clamp(19rem, min(56vw, calc(100svh - 15rem)), 31.125rem);
	}
}

@media screen and (max-width: 768px) {

	#main-content>.carousel,
	#main-content>.carousel .carousel-inner,
	#main-content>.carousel .carousel-item,
	#main-content>.carousel .carousel-item>img {
		height: clamp(24rem, calc(90svh - 8.5rem), 41rem);
	}
}

@media screen and (min-width: 992px) {

	#main-content>.carousel,
	#main-content>.carousel .carousel-inner,
	#main-content>.carousel .carousel-item,
	#main-content>.carousel .carousel-item>img {
		height: clamp(26rem, calc(100svh - 15rem), 39.0625rem);
	}
}

.carousel-title .dsbn-slideshow-copy {
	/* align-items:flex-start — default stretch was forcing overlay-left's button to full width. */
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0.75rem;
	color: var(--bs-white);
}

.carousel-title .dsbn-slideshow-copy>* {
	margin: 0;
}

/* :not(.dsbn-btn) — forcing white here made dsbn-btn--white render white-on-white. */
.carousel-title .dsbn-slideshow-copy>*:not(.dsbn-btn) {
	color: var(--bs-white) !important;
}

.carousel-title .dsbn-slideshow-title {
	margin: 0;
	color: var(--bs-white);
	font-family: var(--dsbn-font-heading);
	/* Was a hardcoded 3.75rem + a SEPARATE hardcoded 1.5rem override below
	   at max-width:768px — the mobile value never matched the hub hero
	   title's size/token. --dsbn-fs-banner (same token .dsbn-hub-visual-hero__title
	   uses) already clamps down to a 2.25rem/36px floor on narrow screens on
	   its own, so no extra breakpoint override is needed at all. */
	font-size: var(--dsbn-fs-banner);
	font-weight: 400;
	line-height: 1.05;
	/* Balances line lengths to avoid a lone short "orphan" word left dangling
	   on its own line whenever the text wraps naturally (balance over pretty:
	   actually equalizes line breaks instead of a soft heuristic, and pretty
	   has no Safari support). Does not affect author-inserted <br> line
	   breaks, which are removed separately on narrow screens below. */
	text-wrap: balance;
}

.carousel-title .dsbn-slideshow-title__intro,
.carousel-title .dsbn-slideshow-title__main {
	display: block;
	font-family: inherit;
	font-size: inherit;
	line-height: inherit;
}

.carousel-title .dsbn-slideshow-title__intro {
	font-weight: 400;
}

.carousel-title .dsbn-slideshow-title__main {
	font-weight: 600;
}

@media screen and (max-width: 600px) {

	/* Even with the widened mobile column, "District School Board" alone
	   still needs ~400px at --dsbn-fs-banner — more than a 390px phone's
	   FULL width, arrows included. Rather than an arbitrary one-off shrink,
	   step down to --dsbn-fs-section (2rem/32px floor) here — the SAME token
	   the other (non-hub) inside-page hero titles already use (.dsbn-inside-hero__title,
	   e.g. Board Action Plan) — so the slideshow title matches that existing
	   size/scale on phones instead of introducing a third one-off value.
	   Still bigger than the old flat 1.5rem/24px, and dropping the author's
	   manual <br> (which forced "Board" to end its own line right before
	   "Of Niagara") lets the whole phrase reflow as one naturally-wrapping
	   run so text-wrap:balance (above) can pick a balanced break instead of
	   fighting an author break that no longer fits.
	   (The literal space now authored right after the <br> in the markup —
	   see front-page.php / the slideshow plugin — is what keeps "Board" and
	   "Of" from merging into "BoardOf" once the <br> itself is hidden.) */
	.carousel-title .dsbn-slideshow-title,
	.carousel-title .dsbn-slideshow-kicker,
	.carousel-title .dsbn-slideshow-heading {
		font-size: var(--dsbn-fs-section);
	}

	.carousel-title .dsbn-slideshow-title__main br {
		display: none;
	}
}

.carousel-title .dsbn-slideshow-kicker {
	font-family: var(--dsbn-font-heading);
	font-size: var(--dsbn-fs-banner);
	font-weight: 400;
	line-height: 1.05;
}

.carousel-title .dsbn-slideshow-heading {
	font-family: var(--dsbn-font-heading);
	font-size: var(--dsbn-fs-banner);
	font-weight: 600;
	line-height: 1.05;
}

/* ---------------------------------------------------------------
   Slide layout variants (dsbn-slideshow plugin "Layout" field).
   overlay-left is today's existing default treatment (the rules
   above, unmodified) and needs no override here. Written without a
   live browser check — verify/tune once real slides exist. */

/* overlay-center: same content block as overlay-left, centered with
   a full-width scrim instead of a left-anchored one. */
#main-content>.carousel .carousel-item--layout-overlay-center::before {
	background: linear-gradient(180deg, rgba(0, 20, 40, 0.5) 0%, rgba(0, 20, 40, 0.2) 45%, rgba(0, 20, 40, 0.45) 100%);
}

.carousel-item--layout-overlay-center .carousel-title {
	left: 50%;
	right: auto;
	transform: translate(-50%, -50%);
	text-align: center;
	max-width: var(--dsbn-carousel-title-max);
}

.carousel-item--layout-overlay-center .dsbn-slideshow-copy {
	display: flex;
	flex-direction: column;
	align-items: center;
}

/* image-only: render() never outputs .carousel-title for this layout at
   all, so the only thing left to disable is the scrim — no text needs
   contrast against the photo. */
#main-content>.carousel .carousel-item--layout-image-only::before {
	display: none;
}

/* bottom-banner: a translucent color strip anchored to the bottom of the
   photo, letting the image show through behind the text, instead of a
   solid bar that pushes the photo up above it. The photo keeps its normal
   full-slide sizing (no flex/order tricks needed) — only .carousel-title's
   own position changes, from vertically-centered to bottom-anchored. */
#main-content>.carousel .carousel-item--layout-bottom-banner::before {
	display: none;
}

.carousel-item--layout-bottom-banner .carousel-title {
	top: auto;
	bottom: 0;
	left: 0;
	right: 0;
	transform: none;
	max-width: none;
	width: 100%;
	/* border-box so the horizontal edge-zone padding is drawn INSIDE the
	   100% width — without it, width:100% + padding overflows the carousel
	   (~184px past the right edge at desktop), which the carousel's
	   overflow:hidden clips, silently pushing the "centered" text off-centre. */
	box-sizing: border-box;
	/* Translucent --dsbn-color-ink (the design system's darker navy) so the
	   photo shows through behind the text instead of a fully solid bar. */
	background: rgba(6, 33, 62, 0.72);
	/* Extra bottom padding clears the carousel indicator dots, which are
	   positioned at the carousel's bottom-centre (shared across all slides,
	   so they can't move per-layout) and would otherwise sit on top of the
	   banner text — with the padding they land in the empty navy area below it. */
	padding: clamp(1rem, 3vw, 2rem) var(--dsbn-carousel-edge-zone) clamp(3.5rem, 5vw, 4.5rem);
	text-align: center;
}

.carousel-item--layout-bottom-banner .dsbn-slideshow-copy {
	display: flex;
	flex-direction: column;
	align-items: center;
}

/* image-left / image-right: a two-column split — featured image in one
   column, kicker/heading/subtitle/button in the other, on a background
   color or image (set inline via PHP) instead of a full-bleed photo. Its
   own independent type treatment rather than reusing .carousel-title/
   .dsbn-slideshow-copy — those assume a dark photo behind white text via
   !important, which would be illegible against this layout's typically
   light default background color. */
#main-content>.carousel .carousel-item--layout-image-left::before,
#main-content>.carousel .carousel-item--layout-image-right::before {
	display: none;
}

.carousel-item--layout-image-left,
.carousel-item--layout-image-right {
	display: flex;
	align-items: center;
	background-color: var(--dsbn-color-surface);
}

.dsbn-slideshow-split__overlay {
	position: absolute;
	inset: 0;
	z-index: 1;
	background: rgba(6, 33, 62, 0.55);
	pointer-events: none;
}

.dsbn-slideshow-split {
	position: relative;
	z-index: 2;
	display: grid;
	grid-template-columns: 1fr 1fr;
	align-items: center;
	gap: clamp(2rem, 5vw, 4rem);
	width: 100%;
	max-width: var(--dsbn-shell);
	margin-inline: auto;
	padding-inline: var(--dsbn-carousel-edge-zone);
}

/* Markup order is always media-then-body (image-left needs no override) —
   image-right pushes the media item after the body instead. */
.carousel-item--layout-image-right .dsbn-slideshow-split__media {
	order: 1;
}

.dsbn-slideshow-split__media img {
	display: block;
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border-radius: 24px;
}

.dsbn-slideshow-split__body {
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
	color: var(--dsbn-color-ink);
}

/* Only the overlay variant (background image + the overlay checkbox) is
   dark enough to need white text — a plain background color defaults
   light, so ink stays the readable choice there. */
.dsbn-slideshow-split__overlay~.dsbn-slideshow-split .dsbn-slideshow-split__body {
	color: #fff;
}

.dsbn-slideshow-split__body .dsbn-slideshow-title {
	margin: 0;
	color: inherit;
	font-family: var(--dsbn-font-heading);
	font-size: var(--dsbn-fs-banner);
	font-weight: 400;
	line-height: 1.05;
}

.dsbn-slideshow-split__body .dsbn-slideshow-title__intro {
	display: block;
	font-weight: 400;
}

.dsbn-slideshow-split__body .dsbn-slideshow-title__main {
	display: block;
	font-weight: 600;
}

/* DM Sans/semibold like .dsbn-card__title (site's de facto h3) — serif-on-serif with the title read as too little contrast. */
.dsbn-slideshow-subheading {
	margin: 0;
	color: inherit;
	font-family: var(--dsbn-font-body);
	font-size: var(--dsbn-fs-body-header);
	font-weight: var(--dsbn-fw-semibold);
	line-height: var(--dsbn-lh-heading);
}

.dsbn-slideshow-subtitle {
	/* No top margin — title's own line-height already reads as more space than the gap needs. */
	margin-block: 0 var(--dsbn-space-xs);
	color: inherit;
	font-family: var(--dsbn-font-body);
	font-size: var(--dsbn-fs-body);
	opacity: 0.85;
}

/* Reasserted at higher specificity — the >* margin:0 reset above would otherwise win. */
.carousel-title .dsbn-slideshow-copy .dsbn-slideshow-subtitle {
	margin-block: 0 var(--dsbn-space-xs);
}

@media screen and (max-width: 768px) {
	.dsbn-slideshow-split {
		grid-template-columns: 1fr;
		gap: 1.25rem;
		padding-block: clamp(2rem, 6vw, 3rem);
	}

	.carousel-item--layout-image-right .dsbn-slideshow-split__media {
		order: 0;
	}

	.dsbn-slideshow-split__media img {
		aspect-ratio: 16 / 9;
	}

	.dsbn-slideshow-split__body .dsbn-slideshow-title {
		font-size: var(--dsbn-fs-banner);
	}
}

#main-content>.carousel .carousel-item--layout-color-center::before {
	display: none;
}

.carousel-item--layout-color-center {
	display: flex;
	align-items: center;
	background-color: var(--dsbn-color-surface);
}

.carousel-item--layout-color-center .carousel-title {
	position: relative;
	top: auto;
	left: auto;
	right: auto;
	transform: none;
	width: 100%;
	max-width: var(--dsbn-carousel-title-max);
	margin-inline: auto;
	text-align: center;
}

.carousel-item--layout-color-center .dsbn-slideshow-copy {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.75rem;
}

.carousel-item--layout-color-center .dsbn-slideshow-copy,
.carousel-item--layout-color-center .dsbn-slideshow-copy>*:not(.dsbn-btn) {
	/* :not(.dsbn-btn) — forcing ink here made the button render dark-on-blue instead of white-on-blue. */
	color: var(--dsbn-color-ink) !important;
}

/* Per-slide text-color override (dsbn-slideshow "Text color" field). 'auto'
   keeps each layout's default treatment above; light/dark force the choice
   so an editor can, e.g., run white text on a dark Color Background slide.
   Every per-layout default here is !important, so these must be too, and
   they're placed after all of them so an equal-specificity tie resolves in
   the override's favour on source order. The split layouts' own text reads
   color:inherit from .dsbn-slideshow-split__body, so recolouring the body
   is enough there; the overlay layouts colour each copy child directly. */
.carousel-item--text-light .dsbn-slideshow-copy,
.carousel-item--text-light .dsbn-slideshow-copy>*:not(.dsbn-btn),
.carousel-item--text-light .dsbn-slideshow-split__body {
	color: var(--bs-white) !important;
}

.carousel-item--text-dark .dsbn-slideshow-copy,
.carousel-item--text-dark .dsbn-slideshow-copy>*:not(.dsbn-btn),
.carousel-item--text-dark .dsbn-slideshow-split__body {
	color: var(--dsbn-color-ink) !important;
}

.carousel-control-prev-icon,
.carousel-control-next-icon {
	border-radius: 50%;
}

/* Footer styling */
.dsbn-site-footer {
	--dsbn-footer-tagline-size: var(--dsbn-fs-section);
	--dsbn-footer-social-heading-size: 1.5625rem;
	background: linear-gradient(1deg, var(--dsbn-color-primary) 0%, var(--dsbn-color-secondary) 100%);
	color: var(--dsbn-color-footer-text);
}

.dsbn-site-footer__inner {
	/* Same shared --dsbn-gutter/--dsbn-shell tokens as section/inside-page
	   content so the footer's edges line up with the content above it —
	   previously used its own standalone clamp() and sat ~8px off from the
	   content shell at common viewport widths. */
	width: min(calc(100% - (var(--dsbn-gutter) * 2)), var(--dsbn-shell));
	margin-inline: auto;
	padding-block: clamp(3rem, 6vw, 4.75rem) clamp(4rem, 7vw, 6rem);
}

.dsbn-site-footer__tagline {
	margin: 0 0 clamp(2rem, 4vw, 3rem);
	font-family: var(--dsbn-font-heading);
	font-size: var(--dsbn-footer-tagline-size);
	font-weight: var(--dsbn-fw-body);
	line-height: 1;
	text-align: center;
	text-wrap: balance;
}

.dsbn-site-footer__grid {
	display: grid;
	grid-template-columns: minmax(24rem, 1.6fr) minmax(9rem, 0.8fr) minmax(9rem, 0.8fr) minmax(12rem, 0.9fr);
	gap: clamp(2rem, 5vw, 5rem);
	align-items: start;
}

.dsbn-site-footer__brand {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: 2rem;
	align-items: start;
}

.dsbn-site-footer__logo-link {
	display: inline-flex;
	width: 7.5rem;
}

.dsbn-site-footer__logo {
	display: block;
	width: 100%;
	height: auto;
}

.dsbn-site-footer__address {
	display: flex;
	flex-direction: column;
	gap: 0.25rem;
	margin: 0;
	font-style: normal;
	font-family: var(--dsbn-font-body);
	font-size: 1rem;
	font-weight: var(--dsbn-fw-body);
	line-height: 1.45;
}

.dsbn-site-footer__address strong,
.dsbn-site-footer__heading {
	margin: 0 0 0.6rem;
	font-family: var(--dsbn-font-body);
	font-size: 1rem;
	font-weight: var(--dsbn-fw-bold);
	line-height: 1.35;
	color: inherit;
	text-transform: none;
}

.dsbn-site-footer__address strong {
	text-transform: uppercase;
}

.dsbn-site-footer a {
	color: inherit;
	text-decoration: none;
}

.dsbn-site-footer a:hover {
	text-decoration: underline;
	text-underline-offset: 0.2em;
}

.dsbn-site-footer a:focus-visible {
	outline: 3px solid #fff;
	outline-offset: 4px;
}

.dsbn-site-footer__nav ul {
	display: flex;
	flex-direction: column;
	gap: 0.45rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.dsbn-site-footer__nav a {
	font-family: var(--dsbn-font-body);
	font-size: 1rem;
	font-weight: var(--dsbn-fw-body);
	line-height: 1.45;
}

.dsbn-site-footer__connect {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 2.5rem;
}

.dsbn-site-footer__contact {
	align-self: flex-start;
}

.dsbn-site-footer__social-heading {
	margin: 0 0 0.6rem;
	font-family: var(--dsbn-font-heading);
	font-size: var(--dsbn-footer-social-heading-size);
	font-weight: var(--dsbn-fw-body);
	line-height: 1.1;
}

.dsbn-site-footer__social-list {
	display: flex;
	gap: 0.75rem;
	align-items: center;
}

.dsbn-site-footer__social-list a {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1.55rem;
	height: 1.55rem;
}

.dsbn-site-footer__social-list img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: contain;
}

/* Every other social icon is a raster PNG with a white circle already
   baked into the image; youtube.svg is just the flat white play-button
   glyph with no backing shape, so it stood out unstyled against the
   footer. Give it the same white-circle treatment here instead, using
   the icon as a mask (same technique as --dsbn-icon-phone etc. in
   design-tokens.css) so it can be recolored — its own fill is white,
   which would otherwise be invisible on a white circle. */
.dsbn-site-footer__social-list-youtube {
	background: #fff;
	border-radius: var(--dsbn-radius-pill);
}

.dsbn-site-footer__social-list-youtube::before {
	content: "";
	display: block;
	width: 62%;
	height: 62%;
	background-color: var(--dsbn-color-primary);
	-webkit-mask: url("../images/icons/youtube.svg") center / contain no-repeat;
	mask: url("../images/icons/youtube.svg") center / contain no-repeat;
}

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

	.dsbn-site-footer__brand {
		grid-column: 1 / -1;
	}
}

@media (max-width: 640px) {
	.dsbn-site-footer__inner {
		width: min(100% - 2rem, 34rem);
	}

	.dsbn-site-footer__tagline {
		text-align: left;
	}

	.dsbn-site-footer__grid,
	.dsbn-site-footer__brand {
		grid-template-columns: 1fr;
	}

	.dsbn-site-footer__brand {
		gap: 1.25rem;
	}

	.dsbn-site-footer__connect {
		gap: 1.75rem;
	}
}

/* Background - text color for dark blue */
.bg-dark-blue {
	--bs-bg-opacity: 1;
	background: var(--bs-dark-blue) !important;
}

.text-dark-blue {
	--bs-text-opacity: 1;
	color: var(--bs-dark-blue) !important;
}

.pt {
	font-family: var(--dsbn-font-heading) !important;
}

.int {
	font-family: var(--dsbn-font-body) !important;
}

/* Icons */
.contact-icon {
	max-width: 1.5rem;
}

/* Buttons */
.btn-dsbn {
	background-color: var(--bs-white);
	background-image: url("../images/icons/arrow_blue_right.png");
	background-repeat: no-repeat;
	background-position: right 0.7rem center;
	background-size: 1.5rem;
	color: var(--bs-dark-blue);
	border-radius: 25px !important;
	padding: 0.3rem 2.7rem 0.4rem 0.7rem !important;
	border: 2px solid var(--bs-primary);
	min-width: 10rem;
	text-align: left !important;
}

@media screen and (max-width: 768px) {
	.btn-dsbn {
		min-width: 8rem;
	}
}

.btn-dsbn:hover {
	background-color: var(--bs-warning);
	border: 2px solid var(--bs-primary);
}

.btn-dsbn-noback {
	background-image: url("../images/icons/arrow_white_right.png");
	background-repeat: no-repeat;
	background-position: right 0.7rem center;
	background-size: 1.5rem;
	border-radius: 25px !important;
	padding: 0.3rem 2.7rem 0.4rem 0.7rem !important;
	border: 2px solid var(--bs-white);
	color: var(--bs-white);
	text-align: left !important;
}

.btn-dsbn-noback:hover {
	border: 2px solid var(--bs-warning);
}

.btn-round {
	border-radius: 25px !important;
}



/************************************* PATTERNS STYLES *************************************/

/* Superintendent Pattern styling */
.superintendent-schools-table {
	width: 100%;
	border-collapse: collapse;
	margin-top: 1rem;
	font-size: 0.875rem;
}

.superintendent-schools-table td {
	vertical-align: top;
}

.superintendent-schools-table ul {
	padding-left: 1rem;
	margin: 0;
}

/* Trustee Pattern styling */
.trustee-card .card-body {
	padding: 0.5rem;
}

.trustee-image-sm {
	max-width: 140px;
	margin-bottom: 1rem;
}

.trustee-image-lg {
	max-width: 210px;
	margin-bottom: 1rem;
	padding-left: 1rem;
	/* Not sure why */
}

.dsbn-highlight-card-content {
	align-items: center;
	display: flex;
	flex-direction: column;
	justify-content: flex-start;
	text-align: center;
	min-height: 300px;
}

.dsbn-highlight-card-content figure.dsbn-highlight-card-image {
	align-self: center;
	margin: 0 auto 1rem;
	width: 140px;
}

.dsbn-highlight-card-content .dsbn-highlight-card-image img {
	aspect-ratio: 1 / 1;
	border-radius: 50%;
	display: block;
	object-fit: cover;
	width: 100%;
}

/* Publications Pattern styling */
.publication-card .card-body {
	min-height: 6rem;
	padding-bottom: 0;
}

.publication-thumb {
	max-width: 320px;
}

/* Meetings Pattern styling */
.meetings-card {
	max-width: 320px;
	overflow: hidden;
}

.meetings-card figure.wp-block-image,
.meetings-card .wp-block-image {
	margin: 0 !important;
}

.meetings-card .wp-block-image img {
	display: block;
	width: 100%;
}

.meetings-card .card-body {
	min-height: 5rem;
	padding-bottom: 0;
}

.meetings-card a {
	color: var(--bs-white) !important;
}

/* Testimonial Pattern styling */
.testimonial-container {
	background-color: #ede8f1;
	border-radius: 10px;
	gap: 10rem;
	outline: none;
	padding: 1.5rem 2rem;
}

.testimonial-quote-wrapper {
	align-items: center;
	flex: 0 1 auto;
	gap: 1rem;
	justify-content: flex-start;
}

.testimonial-quote-mark {
	align-self: flex-start;
	margin: 0;
	width: 12%;
}

.testimonial-quote-mark img {
	display: block;
	height: auto;
	width: 100%;
}

.testimonial-text {
	font-size: 1.5rem;
	line-height: 1.35;
	margin: 0;
	max-width: 35ch;
}

.testimonial-id-wrapper {
	align-items: center;
	flex: 0 0 auto;
	gap: 1rem;
	min-width: 320px;
}

.testimonial-id-info {
	font-size: 1.5rem;
}

.testimonial-profilepic {
	margin: 0;
	width: 150px;
}

.testimonial-profilepic img {
	aspect-ratio: 1 / 1;
	border: 1px solid #969696;
	border-radius: 50%;
	display: block;
	object-fit: cover;
	width: 100%;
}

.testimonial-id-info p {
	margin: 0;
}

.testimonial-name {
	font-weight: 700;
}

@media screen and (max-width: 900px) {
	.testimonial-container {
		flex-direction: column;
		gap: 1.5rem;
		padding: 1.5rem;
	}

	.testimonial-id-wrapper {
		min-width: 0;
		width: 100%;
	}
}

/* Real-content headings default to the heading font. :where() keeps this
   at class-only specificity (0-1-0) so ANY design-system component rule
   (.dsbn-card__title, .dsbn-icon-card__title, ...) can override it just by
   existing — the old plain h1..h6 list (0-1-1) silently beat every
   single-class component font and forced New Spirit onto pattern headings
   that were designed to use the body font. */
.pg-contents :where(h1, h2, h3, h4, h5, h6) {
	font-family: var(--dsbn-font-heading);
	line-height: var(--dsbn-lh-heading);
	/* Avoids a lone word stranded on its own final line at large sizes (e.g.
	   "If You Are Concerned About a Child or / Youth"). balance (not pretty)
	   for Safari support — pretty is Chromium/Firefox-only and was a no-op
	   there, so the orphan it's meant to fix kept showing up. */
	text-wrap: balance;
	/* Bootstrap's element-level h1..h6 rule (margin-top:0; margin-bottom:.5rem)
	   has specificity 0-0-1 — lower than this 0-1-0 :where() rule, but this
	   rule previously never set margin at all, so Bootstrap's value was still
	   the only one in play. Set our own so Bootstrap's rule no longer has
	   anything left to contribute. `.dsbn-inside-content>:first-child` (and
	   the hub equivalent) already zero out the very first block's top
	   margin, so this doesn't add unwanted space above a heading that opens
	   the content area. */
	margin: 2rem 0 1rem;
}

.pg-contents :where(h1, h2, h3, h4, h5, h6):first-child {
	margin-top: 0;
}

/* Content heading SIZES. Without these, the vendored bootstrap.css element
   defaults win (this copy was customized ages ago with an inflated scale —
   h1 3.8rem / h2 3.1rem, far larger than stock Bootstrap) and plain
   wp-block-heading h2s rendered at ~50px. Token-based scale instead. Same
   :where() trick: any component class (patterns.css loads later) overrides
   these freely.
   h1/h2 are both sized + weighted to match .dsbn-heading (--dsbn-fs-section /
   --dsbn-fw-body) exactly — h2 is the level editors actually reach for as
   "the" section heading inside body content, and it looked jarring sitting
   next to a pattern's eyebrow+heading (.dsbn-heading) at a fraction of the
   size with a heavier default browser weight. h1 rarely appears in real
   content (the page title is template-rendered separately) but is kept at
   the same size for consistency. h3..h6 step down one level from the
   previous scale to keep a clear hierarchy under the now-larger h2. */
.pg-contents :where(h1, h2) {
	font-size: var(--dsbn-fs-section);
	font-weight: var(--dsbn-fw-body);
}

.pg-contents :where(h3) {
	/* DM Sans (not New Spirit) at the same size as an in-card title
	   (--dsbn-fs-body-header) — New Spirit read too heavy as a body
	   sub-heading. Weight dropped from bold to semibold: h2 above it is
	   regular (--dsbn-fw-body), so a fully bold h3 read heavier than its
	   own parent heading — semibold keeps it distinguishable without
	   outweighing h2. */
	font-family: var(--dsbn-font-body);
	font-size: var(--dsbn-fs-body-header);
	font-weight: var(--dsbn-fw-semibold);
}

/* h4..h6 repeat h3's font-family for the same reason h3 sets it, and
   because they can't inherit it: the sitewide h1-h6 base rule targets
   these elements directly with New Spirit, which beats inheriting from
   any ancestor no matter the specificity. Without it a sub-heading
   BELOW a sans h3 flipped back to the serif display face — the two
   levels then differed by typeface rather than by weight/size, reading
   as unrelated rather than as one step down. */
.pg-contents :where(h4) {
	font-family: var(--dsbn-font-body);
	font-size: 1.375rem;
	font-weight: var(--dsbn-fw-semibold);
}

.pg-contents :where(h5) {
	font-family: var(--dsbn-font-body);
	font-size: 1.25rem;
	font-weight: var(--dsbn-fw-semibold);
}

.pg-contents :where(h6) {
	font-family: var(--dsbn-font-body);
	font-size: 1.125rem;
	font-weight: var(--dsbn-fw-semibold);
}

/* Browsers never give <li> its own top/bottom margin by default (only the
   parent <ul>/<ol> gets one) — no rule anywhere in this theme has ever set
   one either, so multi-line list items in real page content (each holding
   a bold lead-in plus a full sentence or two, e.g. Awards & Bursaries' "How
   to get started" steps) ran back-to-back with zero gap, reading as one
   dense block rather than five distinct steps. :where() keeps this at
   .pg-contents' own class-only specificity, same convention as the heading
   rules above, so a component embedded in page content (e.g. .dsbn-faq__item,
   directly below) can still override it. Reuses the same 1.5rem "prose"
   rhythm as the Hub-intro/media-row fixes — a multi-line list item is
   exactly that, not a compact card teaser. */
.pg-contents :where(ul, ol) li+li {
	margin-top: 1.5rem;
}

/* FAQ answers are compact widget content (see the 0.75rem component rhythm
   in patterns.css), not the multi-paragraph prose the rule above targets —
   without this override, a bulleted list inside an answer would jump to
   the much looser 1.5rem prose rhythm and read as disconnected from the
   rest of the answer's tight internal spacing. Originally shipped as a
   hard 0 instead of that 0.75rem tier: looked fine for short one-line
   bullets (e.g. "What materials does my child need to bring to school?")
   but multi-line tips (e.g. "What can I do to prepare my child for their
   first day?", 10 full-sentence items) collapsed into one dense block with
   no break between items — the exact bug the rule above was written to
   fix, just recreated inside FAQ answers. 0.75rem gives real separation
   without reaching all the way to the page-content rhythm. */
.dsbn-faq__item .wp-block-list li+li {
	margin-top: 0.75rem;
}

/* Emergency Notification styling
   Matches the design shared across other DSBN sites using the same
   cdn.dsbn.org feed (images/emergency/notification-*.png are that same
   shared asset set), adapted from a centered floating card (position:
   absolute, fixed top offset tuned to a different site's header height,
   max-width, box-shadow, border-radius) to a full-width in-flow bar —
   the floating version's hardcoded top offset doesn't transfer to this
   theme's own (different, responsively-variable) header height, and a
   floating overlay changes the whole page's reflow around it. Box model
   (box-sizing, shell-width padding-inline) lives here now instead of
   bootstrap-shim.css's old #emergency_notification.alert rule — the
   feed's own markup already carries a real .emergency-notification wrapper,
   so styling that directly no longer needs Bootstrap's .alert/.bg-warning/
   .rounded-0 classes on our own outer #emergency_notification wrapper. */
.emergency-notification {
	box-sizing: border-box;
	padding-block: 2.25rem;
	padding-inline: max(var(--dsbn-gutter), calc((100% - var(--dsbn-shell)) / 2));
	background-color: #bc2e2d;
	color: #FFFFFF;
	font-family: var(--dsbn-font-body);
	font-size: var(--dsbn-fs-body);
	line-height: var(--dsbn-lh-body);
}

.emergency-inner {
	color: #FFFFFF;
}

.emergency-msg {
	background: url("../images/emergency/notification-icon.png") no-repeat 0 0;
	padding-left: 6.25rem;
}

/* font-family explicit here (not left to inherit .emergency-notification's
   DM Sans) because style.css's sitewide h1-h6 base rule targets these
   elements directly with the serif heading font (--dsbn-font-heading) —
   a rule that directly targets an element always wins over inheriting
   from an ancestor, no matter the specificity numbers on either side. */
.emergency-msg h1 {
	color: #FFFFFF;
	font-family: var(--dsbn-font-body);
	font-size: var(--dsbn-fs-body-header);
	font-weight: bold;
	margin: 0;
	padding: 0;
}

/* The feed emits <h2> for the message and stays that way (editing the
   external .aspx feed itself was ruled out) — styled here to read as
   plain body copy instead of a second heading. Browsers default <h2> to
   1.5em of its own inherited context, which read as oversized/bold
   before this reset. Note this is a visual-only fix: a screen reader
   still announces "heading level 2" regardless of what it looks like,
   since the actual tag is unchanged. p/h3 selectors kept alongside in
   case the feed markup ever does change — see the h1 comment above for
   why font-family is repeated rather than left to inherit. */
.emergency-msg h2,
.emergency-msg h3,
.emergency-msg p {
	font-family: var(--dsbn-font-body);
	font-size: inherit;
	font-weight: normal;
	margin: 0.5rem 0 0;
}

.emergency-msg a {
	color: #FFFFFF !important;
	font-size: var(--dsbn-fs-body);
}

.emergency-msg a:hover {
	color: #FFB3B3 !important;
}

.emergency-msg p.emergency-date-posted {
	margin-bottom: 0;
	color: #FF7371 !important;
}

@media screen and (max-width: 768px) {
	.emergency-msg {
		padding-left: 0;
		padding-top: 3.75rem;
		background-position: center top;
		background-size: 3.125rem;
	}
}

/* Landing Page Button Large */

.lrg-button-container {
	align-items: center;
	background-color: var(--dsbn-color-primary-bright);
	border-radius: 10px;
	display: flex;
	justify-content: space-around;
	line-height: 3rem;
	padding: 1.5rem;
}

.lrg-button-container figure {
	margin: 0;
}

.lrg-btn-text {
	color: #fff;
	font-size: 2.5rem;
	font-weight: 700;
}

.lrg-button-container .lrg-btn-arrow {
	align-self: flex-end;
}

/* Full Width Button Pattern */

.full-width-btn-container {
	align-items: center;
	background-color: var(--dsbn-color-primary-bright);
	border: 2px solid #7070704d;
	border-radius: 10px;
	box-shadow: 0 4px 10px rgba(0, 0, 0, 0.16);
	display: flex;
	gap: 1rem;
	overflow: hidden;
	padding: 2rem;
}

.full-width-btn-icon {
	flex: 0 0 20%;
	margin: 0;
	max-width: 20%;
}

.full-width-btn-icon img {
	display: block;
	height: auto;
	margin: 0 auto;
	width: 40%;
}

.full-width-btn-text-wrap {
	flex: 0 0 40%;
	max-width: 40%;
}

.full-width-btn-text {
	font-weight: 700;
}

.full-width-btn-btn {
	flex: 0 0 40%;
	max-width: 40%;
	min-width: 0;
}

.full-width-btn-btn {
	width: 100%;
	max-width: 100%;
}

.full-width-btn-btn .dsbn-generic-button-wrapper {
	box-sizing: border-box;
	max-width: 100%;
	margin: 0 auto;
	width: 80%;
}

/* Landing Page Colour Box styling */
.landing-page-colour-box a {
	text-decoration: none;
}

.landing-page-colour-box h3 {
	font-size: clamp(1.5rem, 1.5vw, 2rem);
	line-height: 1.2;
	font-weight: 700;
}

/* Landing Page Video styling */
.landing-page-video-embed h2 {
	font-size: clamp(2rem, 6vw, 3.3rem);
}


/* Landing Page Button */
.card-body figure {
	margin: 0;
}

.landing-page-btn {
	align-items: flex-end;
	color: var(--dsbn-color-primary-bright);
	display: flex;
	flex-direction: row;
	font-size: 1.5rem;
	font-weight: 700;
	line-height: 1.8rem;
	padding: 1rem;
	min-height: 140px;
}

.landing-page-btn-text {
	margin: 0;
}

img.landing-page-btn-arrow {
	width: 35px;
}

/* Landing Page Header with Background Image */
.landing-page-header-kicker {
	font-size: clamp(1.1rem, 2.4vw, 1.9rem);
	margin-bottom: 0;
	font-weight: 600;
}

.landing-page-header-kicker.purple {
	color: #eda0ff;
}

.landing-page-header-kicker.teal {
	color: #90F2FF;
}

.landing-page-header-kicker.blue {
	color: #2cd1f5;
}

.landing-page-header-title {
	font-size: clamp(2rem, 6vw, 3.8rem);
	line-height: 1.1;
	max-width: 20ch;
}

.landing-page-header-copy {
	font-size: clamp(0.9rem, 2.4vw, 1.5rem);
}

.landing-page-header-button a {
	background-color: #fff;
	border-radius: 18px;
	color: var(--dsbn-color-primary);
	display: inline-block;
	font-size: clamp(1rem, 2.3vw, 2.2rem);
	font-weight: 700;
	line-height: 1.2;
	padding: clamp(0.6rem, 1.2vw, 1rem) clamp(1.25rem, 3.2vw, 4rem);
	text-align: center;
	white-space: normal;
}

@media screen and (max-width: 768px) {
	.landing-page-header-overlay-w-button {
		background-color: #4b2c7c;
	}

	.landing-page-header-overlay-w-button .wp-block-cover__image-background,
	.landing-page-header-overlay-w-button .wp-block-cover__gradient-background {
		display: none;
	}

	.landing-page-header-overlay-w-button .wp-block-group {
		padding: 1rem !important;
	}

	.landing-page-header-button a {
		width: 100%;
	}
}

/* Landing Page Offset Feature styling */
.landing-page-offset-feature-button a {
	background-color: #fff;
	border-radius: 15px;
	color: var(--dsbn-color-primary);
	display: inline-block;
	font-size: clamp(1rem, 1.5vw, 1.5rem);
	font-weight: 700;
	line-height: 1.2;
	padding: clamp(0.6rem, 1.2vw, 1rem) clamp(1.25rem, 3.2vw, 4rem);
	text-align: center;
	white-space: normal;
	box-shadow: var(--bs-box-shadow) !important;
	border: 2px solid #7070704D;
}


/* DSBN Generic Button */
.dsbn-generic-button-wrapper a {
	background-color: #fff;
	border-radius: 12px;
	color: var(--dsbn-color-primary-bright);
	font-size: clamp(1rem, 1.6vw, 1.5rem);
	font-weight: 700;
	display: inline-block;
	line-height: 1.1;
	padding: clamp(0.6rem, 1.2vw, 1rem) clamp(1.25rem, 3.2vw, 2.5rem);
	text-align: center;
	white-space: normal;
	border: 2px solid #7070704D;
	box-shadow: var(--bs-box-shadow) !important;
}

/* Landing Page Offset Feature styling */
.offset-feature-image {
	max-width: 25rem;
	height: auto;
}

@media screen and (max-width: 768px) {
	.offset-feature-image {
		min-width: 225px;
		height: auto;
	}
}

/* Download PDF button */

.pdf-button-container {
	align-items: center;
	background-color: #FFFFFF;
	border-radius: 15px;
	display: flex;
	justify-content: space-between;
	line-height: 3rem;
	padding: 1rem 1.5rem;
}

.pdf-button-container figure {
	margin: 0;
}

.pdf-btn-text {
	color: var(--dsbn-color-primary);
	font-size: clamp(1rem, 1.6vw, 1.5rem);
	font-weight: 700;
	margin: 0;
	text-align: left;
	flex: 1 1 auto;
	padding-left: 1rem;
}

.pdf-btn-text a {
	display: inline-block;
	text-decoration: none;
}

.pdf-btn-icon,
.pdf-btn-arrow {
	flex: 0 0 auto;
}

.pdf-button-container .pdf-btn-arrow {
	align-self: flex-end;
}

/* =============================================================
   HOMEPAGE TEMPLATE GLUE
   Uses existing v2 pattern classes for component styling.
   ============================================================= */
.dsbn-home-template {
	overflow-x: hidden;
	background: #fff;
}

body.home {
	overflow-x: hidden;
}

.dsbn-home-template .dsbn-home-template__quick {
	position: relative;
	z-index: 3;
	margin-top: 0;
	padding-inline: 0;
}

.dsbn-home-template__quick .dsbn-container {
	/* Same unified --dsbn-gutter/--dsbn-shell formula as .dsbn-container
	   elsewhere — this was still on the old pre-unification standalone
	   clamp(), same class of drift already fixed on .dsbn-hub-visual-hero__inner
	   / .dsbn-hub-page__layout earlier. padding-inline:0 stays (the parent
	   .dsbn-home-template__quick section already zeroes its own gutter, and
	   this formula supplies it instead). */
	width: min(calc(100% - (var(--dsbn-gutter) * 2)), var(--dsbn-shell));
	max-width: none;
	padding-inline: 0;
}

.dsbn-section.dsbn-home-template__belong {
	padding-block: var(--dsbn-section-pad) 0;
	background: linear-gradient(0deg, #E2F8FF 0%, #FFFFFF 100%);
}

.dsbn-home-template__belong-inner {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(18rem, 0.72fr);
	align-items: center;
	gap: clamp(2rem, 7vw, 7rem);
}

.dsbn-home-template__belong-copy {
	max-width: 48rem;
	padding-bottom: clamp(3rem, 7vw, 5.5rem);
}

.dsbn-home-template__belong-image {
	display: block;
	width: 100%;
	max-height: 32rem;
	object-fit: contain;
	object-position: bottom center;
}

.dsbn-home-template__image-link-grid,
.dsbn-home-template__story-grid {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: clamp(1.5rem, 3vw, 3.25rem);
}

.dsbn-home-template__image-link-grid {
	max-width: min(72rem, 100%);
}

.dsbn-home-template__image-link-grid .dsbn-image-link-card,
.dsbn-home-template__story-grid .dsbn-image-link-card {
	max-width: none;
}

.dsbn-home-template__fallback-hero {
	position: relative;
	overflow: hidden;
	/* Full-bleed, matching #main-content>.carousel's own treatment — this is
	   the no-slides fallback for the same hero, so it must look identical
	   (edge-to-edge), not capped to the shell/gutter width like an
	   inside-page content column. .carousel-title inside it is a shared,
	   non-scoped rule that already computes its left-offset off "100%" of
	   its positioned ancestor, so making this full width also fixes the
	   title's gutter alignment automatically. */
	width: 100%;
	max-width: none;
}

.dsbn-home-template__fallback-hero img {
	display: block;
	width: 100%;
	height: clamp(24rem, min(36vw, calc(100svh - 15rem)), 42rem);
	object-fit: cover;
}

@media (max-width: 900px) {
	.dsbn-home-template__quick {
		margin-top: 0;
	}

	.dsbn-home-template__belong-inner,
	.dsbn-home-template__image-link-grid,
	.dsbn-home-template__story-grid {
		grid-template-columns: 1fr;
	}

	.dsbn-home-template__belong-copy {
		padding-bottom: 0;
	}

	.dsbn-home-template__belong-image {
		max-height: 22rem;
	}
}

/* Landing Page Tabs */

.lp-tabs-nav {
	--lp-tabs-link-padding-x: clamp(1rem, 1.2vw, 1.5rem);
	--lp-tabs-link-padding-y: clamp(0.2rem, 1.2vw, 0.5rem);
	--lp-tabs-link-color: var(--bs-black);
	--lp-tabs-link-hover-color: #076ED8;
	--lp-tabs-link-active-color: #076ED8;
	--lp-tabs-link-active-bg: var(--bs-body-bg);
	--lp-tabs-border-color: var(--bs-border-color);
	display: flex;
	flex-wrap: wrap;
	padding-left: 0;
	margin-bottom: 0;
	list-style: none;
}

.lp-tabs-border-bottom {
	border-bottom: 1px solid var(--lp-tabs-border-color);
}

.lp-tabs-link {
	display: block;
	padding: var(--lp-tabs-link-padding-y) var(--lp-tabs-link-padding-x);
	color: var(--lp-tabs-link-color);
	text-decoration: none;
	font-size: clamp(1rem, 1.6vw, 2rem);
	font-weight: 700;
	font-family: var(--dsbn-font-body);
	background: none;
	border: 0px solid transparent;
	/*border-top-left-radius: var(--bs-border-radius);
  border-top-right-radius: var(--bs-border-radius);
  */
	margin-bottom: -1px;
	transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out;
}

.lp-tabs-link:hover,
.lp-tabs-link:focus {
	color: var(--lp-tabs-link-hover-color);
	isolation: isolate;
	/*border-color: var(--bs-secondary-bg) var(--bs-secondary-bg) var(--lp-tabs-border-color);*/
}

.lp-tabs-link.active {
	color: var(--lp-tabs-link-active-color);
	border-bottom: 5px solid var(--lp-tabs-link-active-color);
	/*
  background-color: var(--lp-tabs-link-active-bg);
  border-color: var(--lp-tabs-border-color) var(--lp-tabs-border-color) var(--lp-tabs-link-active-bg);
  */
}

.lp-tabs-link:focus-visible {
	outline: 0;
	box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
}

.lp-tabs-link.disabled,
.lp-tabs-link:disabled {
	color: var(--bs-secondary-color);
	pointer-events: none;
	cursor: default;
}

.lp-tabs-content .lp-tabs-pane {
	display: none !important;
}

.lp-tabs-content .lp-tabs-pane.active,
.lp-tabs-content .lp-tabs-pane.show {
	display: block !important;
}