/*
Theme Name: CIFE
Author: CIFE
Description: Custom block theme for the Council for Independent Education.
Requires at least: 6.7
Tested up to: 6.9
Requires PHP: 7.2
Version: 0.1.25
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: cife-theme
Tags: full-site-editing, block-patterns, block-styles, wide-blocks, accessibility-ready, style-variations
*/

/* ---------------------------------------------------------------------------
   Layout rhythm
   WordPress inserts margin-block-start: var(--wp--style--block-gap) between the
   template's top-level sections (header part, main, footer part) — a gap that
   exists even when no markup asks for it. Zero it so sections butt edge-to-edge
   and own their vertical rhythm via padding.
--------------------------------------------------------------------------- */
.wp-site-blocks > * + * {
	margin-block-start: 0;
}

/* Inside a page, WordPress applies that same flow gap between every top-level
   block. On paper ground it reads as rhythm, but between two blocks that both
   carry a background - the mist enquiry panel meeting the ink closing CTA, say
   - it reads as a pale seam that looks like a mistake rather than spacing. Those
   bands butt edge-to-edge; sections separated by transparent ground keep the
   gap. */
.wp-block-post-content > .wp-block-group.has-background + .wp-block-group.has-background {
	margin-block-start: 0;
}

/* With that gap gone, main carries its own vertical padding so templates this
   theme does not author (WooCommerce shop, product, cart…) still clear the
   header and footer. A descendant selector, not a child one: WooCommerce wraps
   the single-product main in an extra group. Templates built from full-bleed
   sections opt out with is-flush and let the sections own the rhythm. */
.wp-site-blocks main {
	padding-block: var(--wp--preset--spacing--60) var(--wp--preset--spacing--70);
}
.wp-site-blocks main.is-flush {
	padding-block: 0;
}

/* Section bands marked alignfull escape the constrained content column and
   span the viewport, while their own constrained layout keeps the inner
   content aligned to the page container. */
.wp-site-blocks main .wp-block-group.alignfull {
	width: 100vw;
	max-width: 100vw;
	margin-left: calc(50% - 50vw);
	margin-right: calc(50% - 50vw);
}
html,
body {
	overflow-x: clip;
}

/* ---------------------------------------------------------------------------
   Editorial devices
--------------------------------------------------------------------------- */
.is-style-kicker {
	margin-block-end: 0.75rem;
	color: var(--wp--preset--color--primary);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}
.wp-block-image.is-style-hero {
	margin-block-end: 0;
}
.wp-block-image.is-style-hero img {
	width: 100%;
	aspect-ratio: 3 / 2;
	object-fit: cover;
	border-radius: var(--wp--preset--border-radius--medium);
	box-shadow: 0 2px 8px rgba(22, 35, 63, 0.06), 0 30px 60px -30px rgba(22, 35, 63, 0.35);
}

/* ---------------------------------------------------------------------------
   Typography detail
--------------------------------------------------------------------------- */
h1,
h2,
h3 {
	text-wrap: balance;
}
p,
li {
	text-wrap: pretty;
}
h1 + p,
h2 + p,
h3 + p {
	margin-block-start: 0.75rem;
}

/* Content links read as links without shouting. Button links opt out. */
.wp-block-group :where(p, li) a:not(.wp-element-button) {
	text-underline-offset: 0.18em;
	text-decoration-thickness: from-font;
}

/* On ink bands the default (primary) link colour is illegible; use the off-white. */
:where(.has-ink-background-color) :where(p, li) a:not(.wp-element-button) {
	color: var(--wp--preset--color--on-ink);
}

/* Light-on-dark type reads optically thinner (and blooms more) than dark-on-
   light, so thicken the strokes on ink bands: headings 600 -> 700, body 400 ->
   450. We also deliberately do NOT set -webkit-font-smoothing: antialiased on
   ink bands, which would thin the text further. */
.wp-block-group.has-ink-background-color :where(h1, h2, h3, h4, h5, h6) {
	font-weight: 700;
}
.wp-block-group.has-ink-background-color :where(p, li, blockquote):not(.wp-block-site-title) {
	font-weight: 450;
}

/* Header brand wordmark: the logo is the client's SVG, which carries a viewBox
   but no intrinsic width, and WordPress's own site-logo sizing cannot help
   because wp_attachment_is_image() excludes svg, so wp_get_attachment_image_src()
   returns false and the block emits the image with no dimensions at all. A bare
   inline SVG therefore collapses to 0 inside the header's flex row. Size it here.

   The size preserves the brand lockup's own proportions, measured by pixel
   analysis of the brand's lockup files (cife-logo .png, cife-logo-large .png):
   the tagline is 1.44 x the wordmark's width, i.e. wordmark = 0.694 x tagline
   width. The header tagline renders 147.3px wide at 15.96px, so the wordmark is
   102px wide and, from the artwork's own 1733:1082 ratio, 64px tall.
   If the tagline's size ever changes, scale this with it or the ratio breaks. */
.wp-block-site-logo img.custom-logo {
	width: 102px;
	height: auto;
}

@media (max-width: 600px) {
	/* Mobile tagline renders 138.5px wide, so 0.694 x that = 96px. */
	.wp-block-site-logo img.custom-logo {
		width: 96px;
	}
}

/* Dark-band depth: a faint plum gradient (instead of a flat fill). Lightened so
   the base plum (#3f3043) is the darkest stop; off-white stays AAA (8.71:1 on
   the lightest stop). The brand-orange rule is not part of this any more: it
   lives on the header's bottom edge (Header and navigation section), and ink
   bands carry no edge of their own. */
.wp-block-group.has-ink-background-color {
	background-image: linear-gradient(160deg, #4E3D56 0%, #46364E 55%, #3f3043 100%);
}

/* Breadcrumb trail: inline ordered list, separators drawn in CSS. */
nav[aria-label="Breadcrumb"] ol {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
}
nav[aria-label="Breadcrumb"] li + li::before {
	content: "·";
	margin-inline: 0.5em;
}

/* Reading measure: long-form templates (article, news, post, profile,
   page-hero, page-course, page) declare a 43rem content column (~90 characters
   at the body size, counting spaces) in their block layout. Grids, cards, media
   and the top-level / hub / landing pages keep the 1080px site content width.
   Change the measure in those templates' group/post-content layout. Use rem,
   not em: WordPress applies contentSize as a max-width on each child, so em
   would resolve against each heading's own (large) font-size. */

/* ---------------------------------------------------------------------------
   Buttons
--------------------------------------------------------------------------- */
.wp-element-button,
.wp-block-button__link {
	transition: background-color 0.18s ease, color 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
}
.wp-block-button.is-style-outline .wp-block-button__link:hover {
	background: var(--wp--preset--color--primary);
	border-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--paper);
}
/* The chooser's course filter (mu-plugins/cife-chooser.php): the chip that is the active filter takes
the solid button. That is not a new treatment — it is the one an outline chip already has on
hover — so the filtered state reads in the page's own vocabulary and the chips stay one set of
nine. Keyed to `aria-current`, not a bare class: the state is announced as well as shown, and
the only chips that ever set it to `true` are these. */
.wp-block-button.is-style-outline .wp-block-button__link[aria-current="true"],
.wp-block-button.is-style-outline .wp-block-button__link[aria-current="true"]:hover {
	background: var(--wp--preset--color--primary);
	border-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--paper);
}

/* ---------------------------------------------------------------------------
   Cards (college cards in Query Loops)
--------------------------------------------------------------------------- */
.wp-block-post-template.is-layout-grid {
	--card-gap: clamp(1rem, 2.4vw, 1.75rem);
	gap: var(--card-gap);
}
/* ---------------------------------------------------------------------------
   College cards in the course and location archives
   The chooser page's sizing - the shared college-card pattern, spacing|50 of
   padding, the theme's own grid gap, and now the same content column - wearing
   the panel language from the home and courses grids: the surface tint instead
   of card chrome, no radius, no shadow, no lift, and the brand orange drawn as
   rules in the gutters. The chooser page keeps the card treatment: there a
   college is a door to open, here it is a row in a comparison.
--------------------------------------------------------------------------- */
body.tax-course {
	--panel-rule: 2px;
	--panel-rule-color: var(--wp--preset--color--accent-light);
}
body.tax-course .wp-block-post-template.is-layout-grid > .wp-block-post {
	position: relative;
}
/* The rules are centred in the gutters, and the offset is (gutter + rule) / -2:
   the rule's own width has to be added, not subtracted. (gutter - rule) / -2
   looks right and is not, because it leaves the rule a rule-width right of
   centre. Colour and weight come from the same two dials the panels use.
   Every cell draws both rules and the grid's own `overflow: clip` removes exactly
   the two that fall outside it - the first column's vertical rule and the first
   row's horizontal rule. Nothing depends on a child's index, which is what the
   previous `nth-child` arithmetic did: the editor's Query Loop renders an
   invisible 0х0 duplicate of the first post, so every index shifted by one and a
   row rule landed above the wrong card (D119, D122). Core owns the column count
   - it collapses these grids at 600px - so nothing here is breakpoint-dependent. */
body.tax-course .wp-block-post-template.is-layout-grid {
	overflow: clip;
}
body.tax-course .wp-block-post-template.is-layout-grid > .wp-block-post::before,
body.tax-course .wp-block-post-template.is-layout-grid > .wp-block-post::after {
	--rule-bleed: calc((var(--card-gap) + var(--panel-rule)) / -2);
	content: "";
	display: block;
	position: absolute;
	background-color: var(--panel-rule-color);
}
/* The vertical rule: every cell, centred in the gutter to its left. The first
   column's is clipped away, and at one column every one of them is. */
body.tax-course .wp-block-post-template.is-layout-grid > .wp-block-post::before {
	top: 0;
	bottom: 0;
	left: var(--rule-bleed);
	width: var(--panel-rule);
}
/* The horizontal rule: every cell, centred in the gutter above it. Its width is
   100vw on purpose - the clip trims it to the grid's right edge, so it never
   breaks at a gutter and never needs to know how many columns there are. The
   first row's is clipped away; every later one is the divider between rows. */
body.tax-course .wp-block-post-template.is-layout-grid > .wp-block-post::after {
	top: var(--rule-bleed);
	height: var(--panel-rule);
	left: 0;
	width: 100vw;
}

/* Course route panels: the nine route columns on the courses page and the six
   on the homepage band. The padding is the point: it is what stops the text of
   one column running into the next, which is the failure the panels are there
   to fix.

   The fill is decided by the band the panel sits on, because one fill cannot
   read as a panel in both places. On the white courses page the panel has to be
   a tint - paper there would vanish and leave only the rules. On the tinted
   homepage band it has to be the lighter lift: surface is barely a shade off
   mist, so the cards dissolved into the band and read as loose text (D163).
   Two rules, one token each, and no per-instance colour on any block. */
.wp-block-column.is-style-panel {
	position: relative;
	background-color: var(--wp--preset--color--surface);
	padding: var(--wp--preset--spacing--50);
}

/* A panel on a tinted band is paper: the band supplies the tint, so the panel
   only has to be lighter than it. Keyed on the ancestor band rather than on the
   home page, so a panel placed on any mist band behaves the same way, and the
   courses page - whose panels sit on white - is untouched. */
.has-mist-background-color .wp-block-column.is-style-panel {
	background-color: var(--wp--preset--color--paper);
}

/* Panels on white (the courses page) flow naturally — spacing is the editor
   block gap. Panels on a mist band (the homepage course cards) pin their
   trailing "…course details" link to the bottom edge instead: the panel is a
   flex column and the description paragraph takes the slack, so a row of cards
   whose descriptions wrap differently still lands every footer on one bottom
   line. Scoped to the mist band so the courses-page panels — whose last block
   is a list, not a link — keep their natural flow. */
.has-mist-background-color .wp-block-column.is-style-panel {
	display: flex;
	flex-direction: column;
}

.has-mist-background-color .wp-block-column.is-style-panel > p:not(:last-child) {
	flex: 1 1 auto;
}

/* The grid rules have two dials: weight and colour. 2px matches the trust
   strip's rule weight, 1px recedes to a hairline. `accent` is the brand orange
   the trust strip and the pillar columns use; `accent-light` is the same family
   a step softer, which lets the grid sit behind the content rather than frame
   it. The centred offsets below are derived from the weight, so changing either
   value keeps every rule centred in its gutter. */
.wp-block-columns:has(> .wp-block-column.is-style-panel) {
	--panel-rule: 2px;
	--panel-rule-color: var(--wp--preset--color--accent-light);
}

/* The structure is drawn in the brand accent, matching the hairlines the trust
   strip and the pillar columns already use, rather than with a border on each
   panel. A border per panel can only draw the outside of a cell, and two
   adjacent borders in one gutter read as nothing at all; a rule in the gutter
   belongs to the grid instead of to one of the two cells it separates. */
.wp-block-columns:has(> .wp-block-column.is-style-panel) + .wp-block-columns:has(> .wp-block-column.is-style-panel) {
	position: relative;
	margin-block-start: var(--wp--preset--spacing--50);
}

/* Horizontal rule between rows, centred in the row gutter. */
.wp-block-columns:has(> .wp-block-column.is-style-panel) + .wp-block-columns:has(> .wp-block-column.is-style-panel)::before {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	top: calc((var(--wp--preset--spacing--50) + var(--panel-rule)) / -2);
	height: var(--panel-rule);
	background-color: var(--panel-rule-color);
}

/* Vertical rule between columns, centred in the column gutter. Only above the
   width where core stops stacking columns, since stacked columns need the
   horizontal form instead. */
@media (min-width: 782px) {
	.wp-block-column.is-style-panel + .wp-block-column.is-style-panel::before {
		content: "";
		position: absolute;
		top: 0;
		bottom: 0;
		left: calc((var(--wp--preset--spacing--50) + var(--panel-rule)) / -2);
		width: var(--panel-rule);
		background-color: var(--panel-rule-color);
	}
}

/* Below that width the same rule turns horizontal, so stacked cells are still
   separated by the grid rather than by tint alone. */
@media (max-width: 781px) {
	.wp-block-column.is-style-panel + .wp-block-column.is-style-panel::before {
		content: "";
		position: absolute;
		left: 0;
		right: 0;
		top: calc((var(--wp--preset--spacing--50) + var(--panel-rule)) / -2);
		height: var(--panel-rule);
		background-color: var(--panel-rule-color);
	}
}

/* ---------------------------------------------------------------------------
   College profiles
--------------------------------------------------------------------------- */
/* The breadcrumb trail is the profile's first strip; main runs flush so the
   full-bleed hero can begin immediately below it, which leaves the trail to
   own its own breathing room. */
.single-college .wp-site-blocks main.is-flush > .wp-block-group:first-child {
	padding-block: var(--wp--preset--spacing--50) var(--wp--preset--spacing--40);
}

/* That strip and the hero meet flush: the flow block-gap would otherwise open
   a pale stripe between the trail and the top of the band. The trail is
   transparent, so this cannot be written as a background-band rule; the hero
   carries its own `profile-hero` class instead (D88, superseding the
   ink-scoped selector the hero needed while it was plum). */
.single-college main.is-flush > .wp-block-group.profile-hero {
	margin-block-start: 0;
}

/* Above the college name the location line reads as a tracked label rather
   than a stray link (post-terms has no colour support of its own). Profile
   heroes have been mist since D88, which is the only surface this now applies
   to. */
.has-mist-background-color .wp-block-post-terms {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}
/* Profile heroes have been mist since D88, so the label keeps its treatment in
   slate there (7.8:1 on mist) instead of light-on-plum. */
.has-mist-background-color .wp-block-post-terms {
	color: var(--wp--preset--color--slate);
}
.has-mist-background-color .wp-block-post-terms a {
	color: inherit;
	text-decoration: none;
}
.has-mist-background-color .wp-block-post-terms a:hover {
	text-decoration: underline;
}

/* Course chips (the D8 terms on a profile) — a native post-terms style. */
.is-style-chips a {
	display: inline-block;
	margin: 0 0.4rem 0.4rem 0;
	padding: 0.35rem 0.85rem;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: 999px;
	background: var(--wp--preset--color--mist);
	color: var(--wp--preset--color--slate);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	text-decoration: none;
	transition: border-color 0.18s ease, background-color 0.18s ease, color 0.18s ease;
}
.is-style-chips a:hover {
	border-color: var(--wp--preset--color--primary);
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--primary);
}

/* Migrated profile bodies put the facts (principal, address, map, social) in a
   narrow sidebar column beside the narrative. The template widens the body to
   60rem so the narrative column lands near the site reading measure; a profile
   whose body is flat prose instead (the house format) keeps the long-form
   measure, because its prose is a direct child of the body rather than nested
   inside the columns. On phones the columns stack, and the narrative should
   come first — which is what the migrated "mlrg-reverse-mobile" class was for. */
.single-college .wp-block-post-content > :where(p, h2, h3, h4, ul, ol, blockquote) {
	max-width: 43rem;
}
.single-college .wp-block-post-content .mlrg-reverse-mobile {
	align-items: flex-start;
}
@media (max-width: 781px) {
	.single-college .wp-block-post-content .mlrg-reverse-mobile {
		flex-direction: column-reverse;
	}
}

/* ---------------------------------------------------------------------------
   Header and navigation
--------------------------------------------------------------------------- */
/* The orange rule under the menu is NOT here on purpose. It is a border block
   attribute on the header group in parts/header.html, which is what makes it
   appear in the editor's Border panel and stay editable there. A stylesheet
   rule would render in the canvas but be invisible to every control - and would
   silently fight the attribute if an editor changed it.
   Current value in the file: border.bottom = 4px accent (D87; it was 2px between
   D82 and D87). The footer's mirror rule - border.top = 4px accent on the footer
   group in parts/footer.html (D85/D87) - works the same way. Keep both values in
   those files: editing either one in the Site Editor saves a custom template
   part that then shadows the file (D83/D84).
   The trust strip in patterns/trust-strip.php is a separate device and keeps its
   own inline 2px accent rules top and bottom. */
/* The tagline carries the brand orange as part of the logo lockup (chosen
   treatment) but in the LIGHT value: accent #DD7E12 is only 3.32:1 against the
   top of the ink gradient, under AA for small text, while accent-light #EFA24C
   is 4.68:1 there and 5.80:1 at the foot of the band. The old 0.7 muting is what
   originally muddied it against the ink. */
header.wp-block-group .wp-block-site-tagline {
	opacity: 1;
}

/* Header CTA stacks vertically on narrow screens so the
   button and phone link never squeeze beside the branding. */
@media (max-width: 640px) {
	.is-style-header-cta {
		flex-direction: column;
		align-items: stretch;
	}
}

/* The primary nav takes its own row in the header and needs 582.125px of item text
   plus five gaps. That gap is spacing|50 - clamp(1.5rem, 1.25rem + 1vw, 2rem) - so it
   narrows with the viewport, and the row stops fitting once the viewport drops below
   about 802px. Core's own responsive nav only takes over below 600px and it hardcodes
   that breakpoint (no attribute, no CSS variable to move it), so from there to ~802px
   the row simply cannot fit: being flex-wrap: wrap it wraps to two lines rather than
   overflowing. That is what it did at 768px, an iPad-portrait width.

   Tightening the gap only where the row can still fit on one line buys the single line
   back without touching the roomy spacing the nav keeps at every larger width. Both
   bounds are measured, not chosen:
     - 802px  above this the row fits at the full spacing|50 gap, so no override is
              needed: 582.125 + 5 x (1.25rem + 1vw) <= viewport - 80.
     - 722px  below this even a 12px gap cannot fit 582.125px of item text inside the
              header's 40px side padding, so wrapping is unavoidable there and the
              override would only make the two rows look cramped.
   spacing|30 (0.75rem = 12px) rather than spacing|40 (20px): at 768px a 20px gap leaves
   only 6px of slack, which a persistent (non-overlay) scrollbar eats, while 12px leaves
   46px. Recompute both bounds if the nav labels or the nav font-size ever change.

   The selector outranks core's .wp-container-core-navigation-is-layout-* (one class,
   specificity 0,1,0) at 0,2,1, so this wins on specificity rather than on stylesheet
   order - do not shorten it to a single class or it silently stops applying. */
@media (min-width: 722px) and (max-width: 802px) {
	.wp-block-navigation ul.wp-block-navigation__container {
		gap: var(--wp--preset--spacing--30);
	}
}

/* ---------------------------------------------------------------------------
   Imagery (theme.json border styles don't emit for media blocks)
--------------------------------------------------------------------------- */
.wp-block-image img,
.wp-block-post-featured-image img {
	border-radius: var(--wp--preset--border-radius--medium);
}

/* The college profile featured image is a banner, not a full-bleed hero.
   In templates/single-college.html it sits outside any constrained group, so
   unconstrained flow stretched it to the whole viewport - 1040x695 at desktop -
   while the copy beneath it sits in a 60rem column. Match that column and cap
   the height, letting object-fit crop rather than squash the photograph.
   The cap also stops the smaller sources (Bales at 1024x484) being stretched
   well past their native size, which showed as softness at the old width. */
.single-college .wp-block-post-featured-image {
	box-sizing: border-box;
	margin-inline: auto;
	max-width: 60rem;
	/* Match the root padding rather than a spacing preset: the copy column below
	   is inset by styles.spacing.padding in theme.json, so the image lines up
	   with the text and stays lined up if that value is ever retuned. */
	padding-inline: var(--wp--style--root--padding-left) var(--wp--style--root--padding-right);
}

.single-college .wp-block-post-featured-image img {
	width: 100%;
	height: clamp(12rem, 30vw, 24rem);
	object-fit: cover;
}

/* ---------------------------------------------------------------------------
   Stat band (social proof)
--------------------------------------------------------------------------- */
/* Each figure is a cell: an accent hairline, the value set in the heading serif,
   then the label in body copy. Cells stack into a list on phones. */
.wp-block-group.is-style-stat-cell {
	border-top: 1px solid var(--wp--preset--color--accent);
	padding-top: var(--wp--preset--spacing--40);
}

.wp-block-paragraph.is-style-stat-value {
	color: var(--wp--preset--color--ink);
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--xx-large);
	font-weight: 600;
	line-height: 1;
	letter-spacing: -0.01em;
}

.wp-block-paragraph.is-style-stat-label {
	color: var(--wp--preset--color--slate);
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.45;
}

/* The flow block-gap would float the label well below its figure; the pair
   reads as one unit at a tighter step. */
.is-style-stat-value + .is-style-stat-label {
	margin-block-start: 0.4rem;
}

/* ---------------------------------------------------------------------------
   Jump nav (in-page topic pills)

   Hub pages put their articles behind a lot of vertical scroll. A slim strip of
   pill links under the hero lets a reader go straight to the topic they came
   for. It is a functional bar, not a section: no band of its own, no hairline -
   the pills delimit themselves and the paper ground is shared with the band
   below, so the page does not gain another visual seam.
--------------------------------------------------------------------------- */
html {
	scroll-behavior: smooth;
}

/* Pills read as jump targets: a quiet outline at rest, ink fill on hover, so
   they are not mistaken for the accent CTAs on the hero just above.

   The outline is what makes a pill read as a button at all, so it has to be an
   EDGE, not a divider. `line` is the hairline the page draws between things:
   against mist it measures 1.15:1 and against paper 1.31:1 - it is there to be
   barely seen. A control's boundary has to be perceived. `muted` is what the
   form fields already use for theirs (4.98:1 on mist, 5.66:1 on paper), and 3:1
   is the target the focus ring below already argues from. */
.wp-block-button.is-style-pill-link .wp-block-button__link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 2.75rem;
	border: 1px solid var(--wp--preset--color--muted);
	border-radius: 999px;
	background-color: transparent;
	color: var(--wp--preset--color--ink);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	line-height: 1.4;
	padding: 0.5em 1.15em;
	text-decoration: none;
}
.wp-block-button.is-style-pill-link .wp-block-button__link:hover,
.wp-block-button.is-style-pill-link .wp-block-button__link:focus {
	border-color: var(--wp--preset--color--ink);
	background-color: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--paper);
}
/* Keyboard users need the ring back; the ink fill alone is not a focus cue.
   Primary rather than accent: the ring sits outside the pill against the page
   background, where accent measures 2.97:1 - under the 3:1 needed to perceive
   the ring at all. */
.wp-block-button.is-style-pill-link .wp-block-button__link:focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 2px;
}
.is-style-jump-nav-label {
	align-self: center;
	margin-block-start: 0;
	margin-block-end: 0;
	color: var(--wp--preset--color--slate);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

/* D140: the subject directory's four group labels are h3s and keep the label treatment, but a
   heading also takes the serif family and the 1.15 line-height that theme.json sets on the
   heading element — neither of which the label rule above declares, so both would arrive from
   the wrong place. Pinning them to the body's own values keeps the label looking exactly as it
   did as a paragraph. Scoped to the heading so the paragraph instances are untouched. */
.wp-block-heading.is-style-jump-nav-label {
	font-family: var(--wp--preset--font-family--body);
	line-height: 1.65;
}

/* ---------------------------------------------------------------------------
   Forms
--------------------------------------------------------------------------- */
.cife-enquiry input[type="text"],
.cife-enquiry input[type="email"],
.cife-enquiry input[type="tel"],
.cife-enquiry input[type="url"],
.cife-enquiry input[type="number"],
.cife-enquiry input[type="date"],
.cife-enquiry select,
.cife-enquiry textarea,
.wp-block-search__input {
	border: 1px solid var(--wp--preset--color--muted);
	border-radius: var(--wp--preset--border-radius--small);
	padding: 0.6rem 0.75rem;
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--ink);
	/* Controls arrive in the browser's own typography (Arial 13.3px, monospace
	   textarea) - off the site's type scale, and under 16px it is enough for
	   iOS Safari to zoom the page when the field is focused. Match the body
	   face and the body size token (>=17px, so no focus zoom). */
	font-family: inherit;
	font-size: var(--wp--preset--font-size--medium);
	line-height: 1.4;
}
.cife-enquiry input:focus-visible,
.cife-enquiry select:focus-visible,
.cife-enquiry textarea:focus-visible,
.wp-block-search__input:focus-visible {
	border-color: var(--wp--preset--color--primary);
}

/* --- Enquiry form (Contact Form 7) ------------------------------------------
   CF7 owns the form and its behaviour; the theme owns how it looks. CF7's own
   stylesheet is switched off in inc/enquiry-form.php, so everything the form
   needs is here. The field rules above already apply, because the CF7 form
   template is wrapped in .cife-enquiry exactly like the form it replaced —
   that is what keeps the styling unchanged. */
.cife-enquiry form p {
	margin-bottom: 1rem;
}
.cife-enquiry label {
	display: block;
	font-weight: 600;
	margin-bottom: 0.25rem;
}
.cife-enquiry input[type="text"],
.cife-enquiry input[type="email"],
.cife-enquiry input[type="tel"],
.cife-enquiry input[type="url"],
.cife-enquiry input[type="number"],
.cife-enquiry input[type="date"],
.cife-enquiry select,
.cife-enquiry textarea {
	width: 100%;
	max-width: 32rem;
	/* The fields are padded, so the border box must own the width - with the
	   default content-box, padding + border pushed the inputs and the textarea
	   past the form's right edge on phones. (select is border-box by default,
	   which is why only the others overflowed.) */
	box-sizing: border-box;
}
/* Choice fields — checkbox and radio. CF7 renders these as a group of
   <span class="wpcf7-list-item"> wrappers, each holding the control plus a
   <span class="wpcf7-list-item-label"> for the option text. There is no <label>
   anywhere in an option, so the label rule above does not reach it; the group's
   own label, authored in the form, is the only label there is. CF7's stylesheet is
   off here, so its layout has to be replaced rather than inherited: CF7 spaces its
   items with whitespace pseudo-elements and a leading 1em margin, whereas this uses
   a real gap and no leading margin, so the first option sits flush with the field
   column exactly like every other control. */
.cife-enquiry .wpcf7-list-item {
	display: inline-block;
	margin: 0 1.25rem 0.25rem 0;
}
.cife-enquiry .wpcf7-list-item input[type="checkbox"],
.cife-enquiry .wpcf7-list-item input[type="radio"] {
	width: 1.15rem;
	height: 1.15rem;
	margin: 0 0.45rem 0 0;
	vertical-align: -0.25em;
	/* Native controls, so the palette has to be handed to the browser. */
	accent-color: var(--wp--preset--color--primary);
}
/* The acceptance field — CF7's consent checkbox — is the one option that wraps its
   control in a real <label>, which is also why it is the one option whose text is
   clickable and which has an accessible name. That is an *option* label, not a field
   label, so the block/bold rule further up has to be undone for it: otherwise the
   consent sentence drops onto its own line in bold, underneath its own checkbox.
   Measured before this rule existed: display block, weight 600, margin-bottom 4px,
   cursor default where the whole sentence is a click target. */
.cife-enquiry .wpcf7-list-item label {
	display: inline;
	font-weight: 400;
	margin: 0;
	cursor: pointer;
}
/* The plain checkbox and radio options are themselves <label class="wpcf7-list-item">
   after the markup rewrite in inc/enquiry-form.php (D147), so the field-label rule above
   would set each option's text in bold — an option is not a field label. Only these two
   properties are corrected: the item's own layout still comes from the .wpcf7-list-item
   rule further up, which must keep its inline-block display. */
.cife-enquiry label.wpcf7-list-item {
	font-weight: 400;
	cursor: pointer;
}

/* A border colour is invisible on a native checkbox, so the invalid state that the
   theme marks on every other control is an outline here. */
.cife-enquiry .wpcf7-list-item input.wpcf7-not-valid {
	outline: 2px solid #b32d2e;
	outline-offset: 2px;
}

/* File upload. A native file input arrives as an OS-grey button, off the site's
   palette and type scale, and it is the one control the grouped rules above cannot
   reach, because it is not a text field. The wrapper takes the same treatment as the
   other controls and the button is re-dressed with ::file-selector-button. Browsers
   without that pseudo-element (Safari before 14.1) keep the native button — a
   fallback, not a break. Focus needs nothing here: the input:focus-visible rule above
   is already type-agnostic. */
.cife-enquiry input[type="file"] {
	width: 100%;
	max-width: 32rem;
	box-sizing: border-box;
	border: 1px solid var(--wp--preset--color--muted);
	border-radius: var(--wp--preset--border-radius--small);
	padding: 0.4rem 0.5rem;
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--ink);
	font-family: inherit;
	font-size: var(--wp--preset--font-size--medium);
	line-height: 1.4;
	cursor: pointer;
}
.cife-enquiry input[type="file"]::file-selector-button {
	font-family: inherit;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	color: var(--wp--preset--color--primary);
	background: transparent;
	border: 1px solid var(--wp--preset--color--primary);
	border-radius: var(--wp--preset--border-radius--small);
	padding: 0.35rem 0.8rem;
	margin-right: 0.75rem;
	cursor: pointer;
}
.cife-enquiry input[type="file"]::file-selector-button:hover {
	background: var(--wp--preset--color--mist);
}

.cife-enquiry__call {
	display: block;
	margin-top: 0.25rem;
}
.cife-enquiry__more {
	margin-bottom: 1rem;
}
.cife-enquiry__more summary {
	cursor: pointer;
	font-weight: 600;
}

/* Form-level notices. CF7's response output takes the same shape as the
   error notice the block renders when it is misconfigured.

   Scoped to .wpcf7 rather than .cife-enquiry (D142): CF7 prints its response output as a
   *sibling* of the .cife-enquiry wrapper, never a child of it, so the .cife-enquiry
   selector could never match — this styling was written, documented and dead, which is why
   a failed submit showed the message as bare body text butted against the submit button.
   CF7's hidden fieldset is scoped the same way, for the same reason. */
.cife-enquiry__notice,
.wpcf7 .wpcf7-response-output {
	border-left: 4px solid;
	padding: 0.75rem 1rem;
}
.cife-enquiry__notice--error,
.wpcf7 .wpcf7-response-output {
	border-color: #b32d2e;
	background: #fdf0f0;
}
.wpcf7 .wpcf7-response-output {
	/* CF7's default is 2em 0.5em 1em, which sits oddly in the band. */
	margin: 1rem 0 0;
}
/* The success state keys off the FORM, not off the output. CF7 puts its status class on the
   <form> (contact-form.php:689-690 maps the mail_sent status to `sent` — the same class CF7's
   own stylesheet reads) and never on the output: form_response_output() builds exactly
   `wpcf7-response-output` and appends nothing to it. So the old .wpcf7-mail-sent-ok selector
   could never match, and a successful submission fell through to the red error treatment
   above — a "Thank you" in a red box. Same bug class as D142, and the same lesson: check the
   class CF7 actually renders. The descendant relationship this relies on is the one already
   proven to work by the `form.init` rule below. */
.wpcf7 form.sent .wpcf7-response-output {
	border-color: var(--wp--preset--color--primary);
	background: transparent;
}

/* A spam block is not the visitor's mistake, so it reads differently from a validation error
   rather than identically to one. CF7's own colour for the state is #f56e28 (D144, stakeholder
   choice from the audit in D143); the tint is the theme's error tint — H 0°, S 76%, L 97% —
   rebuilt at that orange's own hue (H 20.5°), so the two notices stay one family instead of
   being an orange rule over a pink box. The site's `spam` message already reads
   "Something looked automated about that submission…", so the shape is the only thing that
   needed changing. */
.wpcf7 form.spam .wpcf7-response-output {
	border-color: #f56e28;
	background: #fdf5f0;
}

/* CF7 paints nothing here until it has something to say, and hides the markup in these
   states. Its own stylesheet is off here, so without this the notice above would render
   empty on every page load — a red left border and a tint with nothing inside it. The
   states are CF7's, reproduced: a fresh page load is `init`, a failed submit is `invalid`,
   and `invalid` is deliberately absent from this list. */
.wpcf7 form.init .wpcf7-response-output,
.wpcf7 form.resetting .wpcf7-response-output,
.wpcf7 form.submitting .wpcf7-response-output {
	display: none;
}

/* Per-field validation. CF7 marks the input itself and adds a tip below it. */
.cife-enquiry .wpcf7-not-valid {
	border-color: #b32d2e;
}
.cife-enquiry .wpcf7-not-valid-tip {
	display: block;
	margin-top: 0.25rem;
	color: #b32d2e;
	font-size: var(--wp--preset--font-size--small);
}

/* Spam honeypot: off-screen, never display:none, so bots still fill it. */
.cife-hp {
	position: absolute;
	left: -9999px;
	top: auto;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

/* CF7 wraps its own hidden inputs (form id, version, unit tag, posted-data hash) in a
   <fieldset> it emits *before* the form body, so the fieldset sits outside .cife-enquiry
   and has to be scoped to .wpcf7 instead. A fieldset paints a default border even when it
   holds nothing but hidden inputs, so without this it shows as an empty frame — CF7's own
   stylesheet normally hides it, and that stylesheet is off here. */
.wpcf7 .hidden-fields-container,
.wpcf7 .wpcf7-spinner {
	display: none;
}

/* CF7's accessible live region. It holds the "Please check the highlighted fields and try
   again." status line plus a bulleted "This field is required." for every failed field.
   CF7's own stylesheet is off here, and it shipped the only rule that keeps this off-screen,
   so without it a failed submit prints those sentences at the top of the form — the same
   words each field already shows underneath itself. The region must stay in the DOM: it is
   the aria-live announcement screen readers depend on, so hide it visually and never
   display:none. Like CF7's hidden fieldset above, it sits outside .cife-enquiry, so it is
   scoped to .wpcf7. Declarations are CF7's own, reproduced rather than reinvented. */
.wpcf7 .screen-reader-response {
	position: absolute;
	overflow: hidden;
	clip: rect(1px, 1px, 1px, 1px);
	clip-path: inset(50%);
	height: 1px;
	width: 1px;
	margin: -1px;
	padding: 0;
	border: 0;
	word-wrap: normal !important;
	word-break: normal !important;
}

/* CF7 submits with an <input type="submit">, not a button block, so core never names it
   `wp-element-button` and the treatment in `theme.json` (`styles.elements.button` -
   background, radius, padding, size, hover) could not reach it. `inc/enquiry-form.php`
   names it now (D255), so those values come from the same place every other button's do,
   plus the shared transition at the top of this file.

   Only what is specific to an <input> is left here: a form control inherits no font, and
   the UA gives it a border and its own cursor. **The treatment that used to be spelled out
   here is gone rather than re-tuned** - that duplicate is exactly what let this button sit
   at 8px / 18px while every other button on the site moved to 10px / 16px. One source, and
   it is the one the design system owns. `scripts/cf7-audit.php` asserts the pairing, so if
   CF7 ever stops rendering an input of this shape the failure is named rather than seen. */
.cife-enquiry input[type="submit"],
.cife-enquiry .wpcf7-submit {
	border: 0;
	font-family: inherit;
	cursor: pointer;
}
.cife-enquiry input[type="submit"]:focus-visible,
.cife-enquiry .wpcf7-submit:focus-visible {
	outline: 2px solid var(--wp--preset--color--accent);
	outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
   The excerpt "read more" field, in the editor
   core/post-excerpt always offers an author a "more text" field and offers no
   attribute to switch it off (block-library.js renders it unconditionally), so
   the theme hides the blank field instead. Two homes, one problem (D126): the
   hero bands, and the college cards, whose copies live in page content as
   ordinary blocks an author can click into and type a stray "read more" into by
   accident. The theme never uses it: every
   excerpt here is a curated summary, and patterns/college-card.php opts out in
   markup with moreText:"" (D111).
   WordPress 7.1 renders the field's placeholder as an inner
   <span data-rich-text-placeholder>, so the field itself is never :empty and it
   is the placeholder that has to be matched. That attribute exists only while
   the field is blank, and only in the editor - rendered HTML never carries it -
   so a filled link and every front-end page are untouched. The :empty pair
   covers versions that hang the attribute on the field itself.
   The archive and index query loops
   keep the field, because a list of teasers may legitimately want one.
   :is() rather than a second comma-list keeps one specificity (0,2,0), so adding
   the cards cannot reorder anything against core's own display rule.
--------------------------------------------------------------------------- */
:is(.has-mist-background-color, .cife-college-panel) .wp-block-post-excerpt__more-link > [data-rich-text-placeholder],
:is(.has-mist-background-color, .cife-college-panel) .wp-block-post-excerpt__more-text:has(> .wp-block-post-excerpt__more-link > [data-rich-text-placeholder]),
:is(.has-mist-background-color, .cife-college-panel) .wp-block-post-excerpt__more-link:empty,
:is(.has-mist-background-color, .cife-college-panel) .wp-block-post-excerpt__more-text:has(> .wp-block-post-excerpt__more-link:empty) {
	display: none;
}

/* ---------------------------------------------------------------------------
   Accessibility
--------------------------------------------------------------------------- */
:focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 2px;
}
/* The primary ring is invisible on ink; switch to paper there. */
:where(.has-ink-background-color) :focus-visible,
header.wp-block-group :focus-visible {
	outline-color: var(--wp--preset--color--paper);
}
.skip-link.screen-reader-text:focus {
	position: fixed;
	top: 0.5rem;
	left: 0.5rem;
	z-index: 100000;
	padding: 0.75rem 1rem;
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--ink);
	border-radius: var(--wp--preset--border-radius--small);
}

/* The cife mark used to stand in for a missing photograph, so the grid kept its rhythm where a college
   had none — a production concern: six of the colleges there had no photograph. Every college in this
   build has one (D104), so the stand-in was never doing anything, and the stakeholder asked for it to be
   removed (D132). Nothing takes its place, and nothing moves when a college has no image: the photograph
   slot's 3:2 shape comes from the block's own aspect-ratio, and the card simply has no photograph. */

/* ---------------------------------------------------------------------------
   College listing: the course-route panel language
   Adopted from the chooser mock-up, 16-09-26. The brief names
   /courses-at-cife-colleges/ as the style anchor, and its grid is the site's own
   orange-line device: flat surface panels with no chrome, divided by 2px
   accent-light rules drawn in the gutters rather than by a border on each cell -
   a border can only outline a panel, sits off-centre in the gutter, and two
   adjacent borders in one gutter read as nothing at all. Same two dials
   (--panel-rule, --panel-rule-color) and the same offsets as the route panels,
   so the college grid and the route grid read as one system. What this adds is
   the flush photograph, the cife-mark stand-in for the six colleges that have no
   photograph, and the gutters this grid's own count needs. Column count is
   explicit rather than auto-fill because the rules are drawn against it: three
   up, two in the middle, one - a list - below 620px. The panel frame and the
   stack's 7/6/6 spacing come from the pattern's own block attributes, not from
   here.
--------------------------------------------------------------------------- */
.cife-college-grid {
	--panel-rule: 2px;
	--panel-rule-color: var(--wp--preset--color--accent-light);
}

/* The route panels' gutter, not the card grid's tighter one: both grids should
   divide at the same rhythm, and the rule offsets below are derived from it.
   `grid-auto-rows: 1fr` evens the row heights out: without it each row is only as tall as
   its own tallest card, so the grid reads as strips of different heights with a different
   foot line in each. This way the tallest profile in the grid sets every card's height. */
.cife-college-grid .wp-block-post-template.is-layout-grid {
	gap: var(--wp--preset--spacing--50);
	grid-auto-rows: 1fr;
}

.cife-college-panel {
	/* A column, so the text block can take the height left under the photograph and the
	   card's action can sit at its foot. */
	display: flex;
	flex-direction: column;
	height: 100%;
	/* The photograph sits flush to the panel's top edge, so the panel's corners
	   clip it or a rounded image shows through square ones. */
	overflow: hidden;
	background-color: var(--wp--preset--color--surface);
}

.cife-college-panel .wp-block-post-featured-image img {
	border-radius: 0;
}

/* The panel is a directory entry, not the profile. At three columns the prose ran
   to seven or eight lines and two thirds of the panel, so it is set a step down:
   the name and the course list lead, and the excerpt is the quiet closing line,
   whole, including its "ask cife" sentence. */
.cife-college-panel .wp-block-post-excerpt {
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.6;
}

/* The card's action, at its foot. It is `core/read-more`, not a Button block: inside a
   Query Loop a Button cannot take the current post's permalink (the URL attribute is not
   bindable), while read-more links to the post it renders in. The anchor itself carries
   `.wp-block-read-more` — there is no wrapper element — and the theme already dresses that
   class as a plain centred link for article cards, so this rule is panel-scoped and has to
   override it. Dressed to match the theme's `elements.button`: primary, paper text, 10px
   radius, 600, at small size, with more clearance than the stack's 6px step, so the action
   does not read as the last line of the text run. */
.cife-college-panel a.wp-block-read-more {
	display: inline-block;
	/* Centred on the panel's axis like the name, and shrunk to its label rather than stretching
	   to the column — the column is a flex container and would otherwise stretch every child. */
	align-self: center;
	/* The card's foot, not wherever the copy happens to end — see the column rule below. */
	margin-block-start: auto;
	text-align: start;
	background-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--paper);
	/* A step below the page's buttons: small label, tight frame, still 600 weight. */
	padding: 0.5rem 1rem;
	border-radius: 10px;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	text-decoration: none;
}

/* A boxed action wants a straight row of feet, not one button per copy length. The text block
   takes the leftover height under the photograph, the action takes the leftover height above
   itself, and every button in a row lands on the same line. `auto` replaces the 6px flow step
   on that one block, so the excerpt carries a 12px margin-bottom to keep the floor. The
   `margin-inline: 0` undoes the auto side margins core's constrained layout gives its children:
   inside a flex column those centre every line instead of leaving it flush. */
.cife-college-panel > .wp-block-group {
	display: flex;
	flex-direction: column;
	flex: 1;
}

/* Every line in the panel is full width, so nothing sits where it does by accident. Core's
   constrained layout gives these children `margin-left/right: auto` *with* `!important`, and
   inside a flex column auto margins absorb the free space before alignment runs: the box
   shrink-wraps and centres, while its lines still start at the box's left edge. That was the
   tell — a one-line name looked centred while a two- or three-line one read as flush left beside
   it, which is what "some of the names aren't centered" pointed at. Zeroing these margins and
   centring the name's text puts every name on the same axis; the action joins it with
   `align-self: center` instead. */
.cife-college-panel > .wp-block-group > :where(.wp-block-post-title, .wp-block-post-terms, .wp-block-post-excerpt, a.wp-block-read-more) {
	margin-inline: 0 !important;
}

.cife-college-panel .wp-block-post-title {
	text-align: center;
}

.cife-college-panel .wp-block-post-excerpt {
	margin-block-end: 0.75rem;
}

.cife-college-panel a.wp-block-read-more:hover {
	background-color: var(--wp--preset--color--primary-deep);
	color: var(--wp--preset--color--paper);
}

/* theme.json gives every post title a 0.4rem bottom margin, and that margin is
   added to the layout's block gap — so the name had 26.4px of air under it against
   20px under the course list. Nothing in a panel's stack should be further from
   the name than from the line below it. The margin goes; the group's block gap is
   spacing|30 (12px), which is then the same distance above and below the course
   list, and tighter than the 20px it was. */
.cife-college-panel .wp-block-post-title {
	margin-bottom: 0;
}

.cife-college-grid .wp-block-post {
	position: relative;
}

/* Both rules are drawn by EVERY cell, and the grid clips whatever falls outside its own
   box. That removes exactly two of them: the vertical rule of the first column and the
   horizontal rule of the first row, which both sit one gutter outside the grid. Nothing
   here counts children.

   D119 replaced an `nth-child` scheme that drew the rules on selected cells and stretched
   them across the gutters. Index arithmetic assumed the grid's children were only cards,
   and in the block editor they are not: the editor's Query Loop renders an invisible 0×0
   duplicate of the first post, which shifted every index by one and put the rule belonging
   to the second row above the first row's third card. Drawing on every cell is index-free,
   so a placeholder, a spinner or an appender in the editor cannot move a rule again — and
   the column counts below are the only breakpoint-dependent part left. */
.cife-college-grid .wp-block-post-template.is-layout-grid {
	overflow: clip;
}

.cife-college-grid .wp-block-post::before,
.cife-college-grid .wp-block-post::after {
	content: "";
	display: block;
	position: absolute;
	background-color: var(--panel-rule-color);
}

/* The vertical rule: every cell, centred in the gutter to its left. The first
   column's is clipped away. */
.cife-college-grid .wp-block-post::before {
	top: 0;
	bottom: 0;
	left: calc((var(--wp--preset--spacing--50) + var(--panel-rule)) / -2);
	width: var(--panel-rule);
}

/* The horizontal rule: every cell, centred in the gutter above it. Its width is
   100vw on purpose — the clip trims it to the grid's right edge, so it never breaks
   at a gutter and never needs to know how many columns there are. The first row's is
   clipped away. */
.cife-college-grid .wp-block-post::after {
	top: calc((var(--wp--preset--spacing--50) + var(--panel-rule)) / -2);
	height: var(--panel-rule);
	left: 0;
	width: 100vw;
}

/* Column counts. The rules need to know nothing about them. */
@media (min-width: 1024px) {
	.cife-college-grid .wp-block-post-template.is-layout-grid {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

/* Two columns in the middle. */
@media (min-width: 620px) and (max-width: 1023px) {
	.cife-college-grid .wp-block-post-template.is-layout-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/* One column: the same grid stacked, which is what the route panels do on a phone.
   The horizontal rule becomes the divider between cards; the vertical one has nothing
   left to divide and is clipped. */
@media (max-width: 619px) {
	.cife-college-grid .wp-block-post-template.is-layout-grid {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* ---------------------------------------------------------------------------
   Easter course comparison table
   The comparison table borrows the courses-page "cards and lines" language:
   flat surface panels, no chrome, and the structure drawn as 2px accent-light
   rules in the gutters instead of grey cell borders. Column proportions live
   on the header row (the row that drives column widths under table-layout:
   fixed). Scoped via the block's className so the three-column fees table,
   which wants equal thirds, is left alone.
--------------------------------------------------------------------------- */
.wp-block-table.easter-course-table {
	--panel-rule: 2px;
	--panel-rule-color: var(--wp--preset--color--accent-light);
}

/* Drop the default grey borders (core draws 1px currentColor on cells;
   theme.json draws a 1px line border on the table). */
.wp-block-table.easter-course-table table,
.wp-block-table.easter-course-table th,
.wp-block-table.easter-course-table td {
	border: none;
}

/* Breathing room in every cell, top-aligned so short "Avg Class size" values
   don't sink to the bottom of tall description cells. */
.wp-block-table.easter-course-table th,
.wp-block-table.easter-course-table td {
	padding: var(--wp--preset--spacing--40);
	vertical-align: top;
}

/* Column proportions (drive the fixed-layout widths). */
.wp-block-table.easter-course-table th:nth-child(1) { width: 40%; }
.wp-block-table.easter-course-table th:nth-child(2) { width: 10%; }
.wp-block-table.easter-course-table th:nth-child(3) { width: 25%; }
.wp-block-table.easter-course-table th:nth-child(4) { width: 25%; }

/* Header band: a surface panel capped with the brand accent rule. The
   accent line is drawn on the cells below; core's table styles also paint a
   3px solid currentColor border under the thead, which reads as a second,
   darker (slate) line over the accent — suppress it. */
.wp-block-table.easter-course-table thead {
	border-bottom: none;
}
.wp-block-table.easter-course-table thead th {
	background-color: var(--wp--preset--color--surface);
	border-top: var(--panel-rule) solid var(--panel-rule-color);
	border-bottom: var(--panel-rule) solid var(--wp--preset--color--accent);
}

/* Each college's name band reads as a surface panel header. */
.wp-block-table.easter-course-table tbody tr:has(td[colspan]) td {
	background-color: var(--wp--preset--color--surface);
}

/* The college name (first cell of the band) is that row's title. */
.wp-block-table.easter-course-table tbody tr:has(td[colspan]) td:first-child {
	font-weight: 600;
}

/* An accent-light rule between college blocks. */
.wp-block-table.easter-course-table tbody tr:has(td[colspan]):not(:first-child) td {
	border-top: var(--panel-rule) solid var(--panel-rule-color);
}

/* An accent-light rule between a college's name band and its detail row, and
   a bottom frame line under the last row. */
.wp-block-table.easter-course-table tbody tr:not(:has(td[colspan])) td {
	border-top: var(--panel-rule) solid var(--panel-rule-color);
}
.wp-block-table.easter-course-table tbody tr:last-child td {
	border-bottom: var(--panel-rule) solid var(--panel-rule-color);
}

/* Vertical rules between columns, matching the grid. The college name bands
   span two columns with a colspan, so the 1|2 and 3|4 rules pause there and
   resume in the header and detail rows; the 2|3 rule runs the whole height. */
.wp-block-table.easter-course-table th + th,
.wp-block-table.easter-course-table td + td {
	border-left: var(--panel-rule) solid var(--panel-rule-color);
}

/* ---------------------------------------------------------------------------
   Responsive
--------------------------------------------------------------------------- */
@media (max-width: 782px) {
	.wp-site-blocks main {
		padding-block: var(--wp--preset--spacing--50) var(--wp--preset--spacing--60);
	}
}

@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}
	.is-style-header-cta,
	.wp-element-button,
	.wp-block-button__link {
		transition: none;
	}
}
