/*
 * Crane MFI Annual Reports — project stylesheet.
 *
 * Loaded after the parent's style-main.css (see functions.php), so rules here
 * win against the parent reset.
 */

/* ==========================================================================
   Footer
   ==========================================================================

   These rules reproduce the WPBakery footer that `template-parts/footer-type.php`
   replaced. Every number is a measurement taken from the old footer as it
   rendered on 2026-09-01, at viewport widths 1440, 1200, 992, 768 and 375. The
   measurements are written next to the rules that hit them, because the only
   way to know this file is still correct is to be able to check it against the
   thing it copies.

   The old footer at 1440px, measured from the top of the <footer> element:

     y=0        1px separator row. The painted hairline sits at y=1, because
                WPBakery's .vc_sep_line is 1px tall inside a 1px box and is
                pushed down 1px by `position:relative; top:1px`.
     y=1..25    24px of space (a vc_empty_space element).
     y=25       Three columns, 50% / 25% / 25%, gutter 15px each side.
                  logo    x=15    300 x 106.23
                  address x=735   heading 330 x 25.19, then 24px, then
                                  two lines at 32.4px each
                  phone   x=1095  the same
                Row height 113.97, set by the text columns, not the logo.
     y=138.97   24px of space.
     Total height 162.97.

   Below 768px the columns stack, in source order, with no space between them,
   and the total height is 383.17.

   Nothing here may rely on a rule from js_composer.min.css. That is the point
   of the exercise: WPBakery has to be removable. The classes carried over from
   the old markup — .footer, .crane-container, .footer-menu-sub-header,
   .footer-site-address — are styled by Crane or by the theme-options stylesheet,
   never by WPBakery, which was checked rule by rule through the CSSOM rather
   than assumed.
*/

/*
 * The hairline. Copied from WPBakery's own geometry rather than simplified to a
 * border on the container, because `top: 1px` inside a 1px box is what puts the
 * line one pixel below the top edge of the footer. A plain border-top would sit
 * a pixel higher.
 */
.crane-mfi-footer__rule {
	height: 1px;
}

.crane-mfi-footer__rule-line {
	display: block;
	position: relative;
	top: 1px;
	width: 100%;
	height: 1px;
	border-top: 1px solid #e4e4e4;
}

/*
 * The 24px above and below the columns were two separate spacer elements in the
 * old footer. Padding on the row is the same picture with four fewer elements.
 *
 * The negative margins undo .crane-container's 15px padding so that the column
 * gutters, not the container, set where the content starts. That is the Crane
 * and Bootstrap row convention, and it is why the content lines up at x=15
 * rather than x=30.
 */
.crane-mfi-footer__cols {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	margin-right: -15px;
	margin-left: -15px;
	padding-top: 24px;
	padding-bottom: 24px;
}

.crane-mfi-footer__col {
	position: relative;
	width: 100%;
	min-height: 1px;
	padding-right: 15px;
	padding-left: 15px;
}

/*
 * 768px is WPBakery's `sm` breakpoint, so this is where vc_col-sm-6 and
 * vc_col-sm-3 used to take effect. Below it the columns were full width.
 */
@media (min-width: 768px) {

	.crane-mfi-footer__col--logo {
		width: 50%;
	}

	.crane-mfi-footer__col--address,
	.crane-mfi-footer__col--phone {
		width: 25%;
	}
}

/*
 * `display: block` matters. The old markup got the same result from
 * `.wpb_single_image img { vertical-align: top }`, which is a WPBakery rule and
 * therefore not available here. Left inline, the image would sit on a text
 * baseline and add a descender's worth of height below it — about 5px at this
 * line height — which shows up as a taller footer on narrow screens where the
 * logo sets the height of its column.
 *
 * The width is set per image on the element, from the Logo width field. Height
 * stays automatic so the aspect ratio decides it: the logo is an SVG with a
 * 284.62 x 100.8 viewBox, which is what makes 300px wide come out 106.23 tall.
 */
.crane-mfi-footer__logo {
	display: block;
	max-width: 100%;
	height: auto;
}

/*
 * `display: block` for the same reason as the image, and `fit-content` so the
 * link box stays the size of the logo. An `inline-block` link would put the
 * descender space back; a plain block link would make the whole left half of
 * the footer clickable, which is a behavior change and not wanted.
 */
.crane-mfi-footer__logo-link {
	display: block;
	width: -moz-fit-content;
	width: fit-content;
}

/* ==========================================================================
   Header
   ==========================================================================

   These rules reproduce the Groovy Menu header that `template-parts/header-bar.php`
   replaced. Every number is a measurement taken from the old header as it
   rendered on 2026-09-02, at viewport widths 1440, 1200, 992, 768 and 375, in
   three states each: at rest, scrolled, and with the menu open. That capture is
   committed as `tests/header-baseline.json`; the comparison is
   `tests/header-geometry.js`.

   The old header at 1440px:

     bar        1440 x 100, white, 1px solid #e4e4e4 along the bottom.
                `position: fixed`, and the page content deliberately runs
                underneath it — the 2022 hero starts at y=80 and the first text
                on the page is at y=360. So there is no spacer, and adding one
                would push every report down by 100px.
     container  max-width 1200, 15px padding each side. At 1440 that puts the
                logo at x=135 and the right edge of the search at x=1305.
     logo       height 75, width automatic. The file is an SVG with a 2.8236
                aspect ratio, so 75 tall comes out 211.77 wide.
     links      Cabin 16px/600, line-height 25, uppercase, #222222, 30px apart,
                the group right-aligned. Centred in the bar: (100-25)/2 = 37.5.
     scrolled   The bar becomes 50 tall and the logo 47, on any scroll at all —
                measured, not assumed: at scrollY 1 it was already animating and
                it had settled by scrollY 10.
     dropdown   230 wide, white, opening at the bottom edge of the bar. Rows are
                46.39 tall: 12px padding, 22.4px line, 12px padding. Text is
                Cabin 16px/400, capitalized, #16181b, indented 15px so it lines
                up under the parent label.

   Below 1024px — Groovy Menu's own breakpoint, taken from
   `@media (max-width: 1023px)` in its generated preset stylesheet — the bar is
   70 tall, the logo 44, and the links move into a 250px drawer at the right.

   Five differences from the old header are deliberate. They are listed here
   because the geometry test reports every one of them, and without this note
   the next person to run it will read them as regressions.

     1. The current-page color is no longer #abc88e, which measures 1.84:1
        against white against a required 4.5:1 (finding B2). See
        --crane-mfi-nav-current.
     2. The current page is underlined as well as colored. Color alone was the
        only signal, which fails WCAG 1.4.1 whatever the ratio. The one place
        the underline is suppressed is the front page, where the top-level
        links all point at the front page and so are all marked current at
        once — see the note on `body.home` beside the rule itself.
     3. The bar is one box rather than two. Groovy Menu drew the rule on a
        101px-tall element and the white ground on a separate 100px one behind
        it; this is a single element with a background and a border.
     4. The caret and the search icon are inline SVGs, not FontAwesome and
        icon-font glyphs. That is what lets the FontAwesome and three icon-font
        stylesheets leave the page entirely.
     5. The mobile drawer's items sit 16.79px higher than they did, because the
        old first item carried a stray Groovy Menu icon value that rendered as
        visible text reading "#Presidents-Note" above the item's real label.
        Removing it moves everything below it up. The burger also stays in the
        bar and turns into a close control in place, rather than the drawer
        carrying a second, separate close button a few pixels away.
   ========================================================================== */

:root {

	/*
	 * The bar's heights, as custom properties because three separate things need
	 * them: the bar, the logo inside it, and `scroll-padding-top` below.
	 * Restating the numbers in those three places is how they drift apart.
	 */
	--crane-mfi-header-h: 100px;
	--crane-mfi-header-h-compact: 50px;
	--crane-mfi-logo-h: 75px;
	--crane-mfi-logo-h-compact: 47px;

	--crane-mfi-header-bg: #ffffff;
	--crane-mfi-header-rule: #e4e4e4;

	--crane-mfi-nav-color: #222222;
	--crane-mfi-dropdown-color: #16181b;
	--crane-mfi-drawer-color: #5a5a5a;
	--crane-mfi-burger: #686868;

	/*
	 * The current-page green.
	 *
	 * The old value was #abc88e, which measures **1.84:1** against white where
	 * WCAG 1.4.3 requires 4.5:1 for text this size. It was the worst contrast
	 * failure on the site, and it was on the navigation of every page.
	 *
	 * #577934 is the same hue — both are 90° — darkened until it passes:
	 * relative luminance 0.1596, so 1.05 / (0.1596 + 0.05) = **5.01:1**. The
	 * headroom over 4.5 is deliberate, because antialiasing thins the strokes of
	 * 16px uppercase type and the measured figure is for solid color.
	 *
	 * **This is a brand color, so the final value is the client's to choose.**
	 * The site audit says the palette is a decision for them rather than a code
	 * change, and this is a value that passes rather than a value anybody has
	 * approved. Changing it means changing this one line.
	 */
	--crane-mfi-nav-current: #577934;
}

/*
 * Anchor links and focus both land under the fixed bar without this.
 *
 * The compact height is the right number, not the resting one: the bar is only
 * 100px tall at the very top of the page, and by the time any anchor jump or
 * focus scroll happens the page has scrolled and the bar is 50. The 8px is
 * breathing room so the target does not sit flush against the rule.
 *
 * This is what answers WCAG 2.2 SC 2.4.11 Focus Not Obscured (Minimum), which
 * restoring the focus indicators would otherwise have walked straight into:
 * `scroll-padding-top` applies to the browser's own scroll-into-view, so tabbing
 * back up a page now stops the focused element below the bar rather than behind
 * it. It fixes the section links at the same time — `#Grants`, `#Financials` and
 * the rest have always landed with their first 100px hidden.
 */
html {
	scroll-padding-top: calc( var( --crane-mfi-header-h-compact ) + 8px );
}

/* --------------------------------------------------------------------------
   Focus indicators, site-wide
   --------------------------------------------------------------------------

   Finding B1: the site had no visible focus indicator anywhere. The cause is a
   Meyer-style reset in the parent — `themes/crane/assets/css/style-main.css:7262`
   sets `outline: 0` on a selector list that includes `summary` and `details` —
   and nothing restores one on focus. Counted in the browser across every loaded
   stylesheet, 35 rules strip an outline and 2 restore one, and both of the two
   belong to the charts plugin.

   This is what made the client report that the 2022 accordions "weren't
   focusable". They were, and a real Enter press opened them. Nothing on screen
   said so.

   Three decisions:

   `:focus-visible`, not `:focus`, so a mouse click on a button does not leave a
   ring behind it. The browser decides, and it gets it right for keyboard, for
   assistive technology, and for text fields where a ring is wanted on click too.

   `:where()` around the element list, so the whole selector weighs the same as a
   bare `:focus-visible` and anything more specific written later can override it
   without a fight.

   `!important`, because loading last is not enough on its own:
   `.wpb_accordion_section .wpb_accordion_header a:focus` in WPBakery is (0,3,1)
   and would win. Checked before reaching for it — only 3 of the 35 use
   `!important` themselves (`.mfp-wrap`, and two wpDataTables font selects), and
   none of the three touches page content, so nothing fights back. That count
   came with a control: the same scan found 23 `display: … !important` rules, so
   it was reading priorities correctly rather than simply finding nothing.
   -------------------------------------------------------------------------- */

:where( a, button, input, select, textarea, summary, details, [tabindex], [contenteditable="true"] ):focus-visible {

	/*
	 * A dark ring with a white one just outside it. The site puts focusable
	 * things on white, on the teal #80c1c3 hero, and on the orange #f06b34
	 * accordion headers, and no single color is visible against all three. The
	 * pair always shows one edge or the other.
	 */
	outline: 3px solid #16181b !important;
	outline-offset: 2px !important;
	box-shadow: 0 0 0 5px rgba( 255, 255, 255, 0.95 ) !important;
}

/*
 * There is deliberately no `position` or `z-index` here, and the rule that used
 * to set them was a bug.
 *
 * It read `:where( a, button, summary ):focus-visible { position: relative;
 * z-index: 1 }`, justified as giving the outline somewhere to be drawn when an
 * ancestor has `overflow: hidden`. **That justification was wrong.** An
 * ancestor's `overflow: hidden` clips a `position: relative` descendant exactly
 * as it clips a static one; only taking the element out of that ancestor's clip
 * chain would help, which `relative` does not do. So the rule bought nothing.
 *
 * What it cost was real. It is (0,1,0) and loads after the parent theme, so it
 * beat every positioned control on the site *while that control was focused*.
 * The scroll-to-top button is the live case: Crane sets `.crane-top` to
 * `position: fixed; z-index: 99` (`themes/crane/assets/css/style-main.css:11000`),
 * and focusing it recomputed to `position: relative`, which moved it from
 * x=1358 to **x=-27** — off the left edge of the viewport. A keyboard user
 * reached the button and it vanished.
 *
 * An outline needs neither property. If a specific control ever paints its ring
 * underneath a neighbour, raise that one control rather than every control on
 * the site.
 */

/*
 * Windows High Contrast and any other forced-colors mode.
 *
 * The `!important` above is aimed at 35 third-party rules that strip outlines,
 * but it does not know when to stop: it would also override a rule that sets
 * the outline to a *system* color, and hard-coding #16181b in a mode whose whole
 * purpose is to let the reader choose the colors is the opposite of the point.
 *
 * That is not hypothetical. `plugins/mfi-charts/assets/css/mfi-charts.css:265`
 * already does this correctly for the chart's data-table toggle, inside its own
 * `forced-colors: active` block — and the rule above, being `!important` and
 * loading later, would have beaten it.
 *
 * `Highlight` is a system color, so the reader's own theme picks it. The
 * box-shadow goes because forced-colors drops shadows anyway, and leaving it in
 * only invites the question of why it is there.
 */
@media ( forced-colors: active ) {

	:where( a, button, input, select, textarea, summary, details, [tabindex], [contenteditable="true"] ):focus-visible {
		outline: 3px solid Highlight !important;
		outline-offset: 2px !important;
		box-shadow: none !important;
	}
}

/* --------------------------------------------------------------------------
   Skip link
   --------------------------------------------------------------------------

   It targets `<main id="crane-mfi-main">`, which this theme's header.php and
   footer.php exist to provide. The site had no `<main>` at all before, so there
   was nothing for a skip link to skip to.

   Moved off screen until focused rather than `display: none`, because a hidden
   element cannot take focus, and a skip link that cannot take focus is not a
   skip link.
   -------------------------------------------------------------------------- */

.crane-mfi-skip-link {
	position: absolute;
	top: 0;
	left: 0;
	z-index: 100000;
	padding: 12px 20px;
	background: #ffffff;
	color: #16181b;
	font-family: Cabin, sans-serif;
	font-size: 16px;
	font-weight: 600;
	text-decoration: underline;

	/*
	 * Moved up rather than sideways. `left: -9999px` puts it outside the inline
	 * box in a right-to-left context; a vertical translate does not, and the
	 * focused state is a plain reset.
	 */
	transform: translateY( -200% );
}

.crane-mfi-skip-link:focus {
	transform: translateY( 0 );
}

@media ( prefers-reduced-motion: no-preference ) {

	.crane-mfi-skip-link {
		transition: transform 0.15s ease-out;
	}
}

/* --------------------------------------------------------------------------
   The bar
   -------------------------------------------------------------------------- */

/*
 * The `<header>` itself contributes no height, exactly as Groovy Menu's did
 * (`header.gm-navbar` measured 1440x0). The bar inside it is what is fixed, and
 * the page content passes underneath.
 */
.crane-mfi-header {
	position: relative;
	z-index: 9999;
}

.crane-mfi-header__bar {
	position: fixed;
	top: 0;
	right: 0;
	left: 0;
	background: var( --crane-mfi-header-bg );

	/*
	 * One element with a background and a border, where the old header used two
	 * stacked ones. See difference 3 in the note at the top of this section.
	 */
	border-bottom: 1px solid var( --crane-mfi-header-rule );
}

.crane-mfi-header__inner {
	box-sizing: border-box;
	max-width: 1200px;
	margin: 0 auto;
	padding: 0 15px;
	height: var( --crane-mfi-header-h );
	display: flex;
	align-items: center;
}

@media ( prefers-reduced-motion: no-preference ) {

	.crane-mfi-header__inner,
	.crane-mfi-header__logo-img {
		transition: height 0.2s ease-out;
	}
}

.crane-mfi-header.is-compact .crane-mfi-header__inner {
	height: var( --crane-mfi-header-h-compact );
}

/* --------------------------------------------------------------------------
   Logo
   -------------------------------------------------------------------------- */

.crane-mfi-header__logo {
	flex: 0 0 auto;
}

/*
 * `display: block` and a `fit-content` width, for the reason recorded on the
 * footer logo: an inline image sits on a text baseline and adds a descender's
 * worth of height below it, and a block-level link would make the whole left
 * half of the bar clickable.
 */
.crane-mfi-header__logo-link {
	display: block;
	width: -moz-fit-content;
	width: fit-content;
}

/*
 * Sized by height, with the width left to the aspect ratio. That is how the old
 * header behaved, and it is the only way to size an SVG whose attachment
 * metadata carries no dimensions — the reason Groovy Menu served this same file
 * as `width="1" height="1"`.
 */
.crane-mfi-header__logo-img {
	display: block;
	height: var( --crane-mfi-logo-h );
	width: auto;
	max-width: 100%;
}

.crane-mfi-header.is-compact .crane-mfi-header__logo-img {
	height: var( --crane-mfi-logo-h-compact );
}

.crane-mfi-header__logo-text {
	display: block;
	font-family: Cabin, sans-serif;
	font-size: 20px;
	font-weight: 600;
	color: var( --crane-mfi-nav-color );
}

/* --------------------------------------------------------------------------
   The menu group
   --------------------------------------------------------------------------

   Right-aligned, which is what puts the first link at x=470.52 at 1440 rather
   than immediately after the logo: the group is pushed to the right edge of the
   container and the items fall where they fall.
   -------------------------------------------------------------------------- */

.crane-mfi-header__menu {
	margin-left: auto;
	display: flex;
	align-items: center;
}

.crane-mfi-nav__list {
	display: flex;
	align-items: stretch;
	gap: 30px;
	margin: 0;
	padding: 0;
	list-style: none;
	height: var( --crane-mfi-header-h );
}

.crane-mfi-header.is-compact .crane-mfi-nav__list {
	height: var( --crane-mfi-header-h-compact );
}

.crane-mfi-nav__item {
	position: relative;
	display: flex;
	align-items: center;
	margin: 0;
}

/*
 * The link and the toggle fill the height of the bar, so the pointer target is
 * the whole 100px rather than the 25px the text occupies. The text stays where
 * it was: a 25px line box centred in a 100px box lands at y=37.5, which is the
 * measurement.
 */
.crane-mfi-nav__link,
.crane-mfi-nav__toggle {
	display: flex;
	align-items: center;
	gap: 5px;
	height: 100%;
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
	font-family: Cabin, sans-serif;
	font-size: 16px;
	font-weight: 600;
	line-height: 25px;
	letter-spacing: normal;
	text-transform: uppercase;
	text-decoration: none;
	color: var( --crane-mfi-nav-color );
	cursor: pointer;
}

.crane-mfi-nav__link:hover,
.crane-mfi-nav__toggle:hover,
.crane-mfi-nav__link:focus,
.crane-mfi-nav__toggle:focus {
	color: var( --crane-mfi-nav-current );
}

/*
 * `inline-block`, not `block`, so the label is only as wide as its text.
 *
 * It matters because the current-page underline is drawn on this element. As a
 * block it filled its container, which in the dropdown meant a 200px underline
 * under a 137px label — a rule across the whole panel rather than under the
 * words. In the bar the difference was invisible, because there the label is a
 * flex item and was already shrinking to its content.
 */
.crane-mfi-nav__label {
	display: inline-block;
}

/*
 * The current page, and the page whose dropdown the current page is in.
 *
 * The underline is the part that is not in the old design, and it is there
 * because WCAG 1.4.1 does not allow color to be the only visual signal. It is
 * drawn with a pseudo-element rather than `text-decoration`, so that turning it
 * on cannot change the height of the line box and move every other item.
 */
.crane-mfi-nav__item.current-menu-item > .crane-mfi-nav__link,
.crane-mfi-nav__item.current_page_item > .crane-mfi-nav__link,
.crane-mfi-nav__item.current-menu-ancestor > .crane-mfi-nav__link,
.crane-mfi-nav__item.current-menu-ancestor > .crane-mfi-nav__toggle,
.crane-mfi-nav__item.current-menu-parent > .crane-mfi-nav__link,
.crane-mfi-nav__item.current-menu-parent > .crane-mfi-nav__toggle {
	color: var( --crane-mfi-nav-current );
}

.crane-mfi-nav__item.current-menu-item > .crane-mfi-nav__link .crane-mfi-nav__label,
.crane-mfi-nav__item.current_page_item > .crane-mfi-nav__link .crane-mfi-nav__label,
.crane-mfi-nav__item.current-menu-ancestor > .crane-mfi-nav__link .crane-mfi-nav__label,
.crane-mfi-nav__item.current-menu-ancestor > .crane-mfi-nav__toggle .crane-mfi-nav__label,
.crane-mfi-nav__item.current-menu-parent > .crane-mfi-nav__link .crane-mfi-nav__label,
.crane-mfi-nav__item.current-menu-parent > .crane-mfi-nav__toggle .crane-mfi-nav__label {
	position: relative;
}

.crane-mfi-nav__item.current-menu-item > .crane-mfi-nav__link .crane-mfi-nav__label::after,
.crane-mfi-nav__item.current_page_item > .crane-mfi-nav__link .crane-mfi-nav__label::after,
.crane-mfi-nav__item.current-menu-ancestor > .crane-mfi-nav__link .crane-mfi-nav__label::after,
.crane-mfi-nav__item.current-menu-ancestor > .crane-mfi-nav__toggle .crane-mfi-nav__label::after,
.crane-mfi-nav__item.current-menu-parent > .crane-mfi-nav__link .crane-mfi-nav__label::after,
.crane-mfi-nav__item.current-menu-parent > .crane-mfi-nav__toggle .crane-mfi-nav__label::after {
	content: "";
	position: absolute;
	right: 0;
	bottom: -2px;
	left: 0;
	height: 2px;
	background: currentColor;
}

/*
 * On the front page the top-level items keep the green and lose the underline.
 *
 * The menu was changed so that the four top-level links are section anchors on
 * the front page — `/#Grants`, `/#Financials` and the rest. Core strips the
 * fragment before it compares a custom link against the request
 * (`_wp_menu_item_classes_by_context()` builds `$raw_item_url` by cutting at the
 * `#`), so on the front page every one of the four matches `home_url()` and all
 * four are stamped `current-menu-item current_page_item` at once. Measured: four
 * green labels, each with a painted 2px rule under it.
 *
 * Four "you are here" markers is not a current-page indicator, it is four of
 * them, and the underline is what makes that read as a fault rather than as
 * emphasis.
 *
 * This does not put back the WCAG 1.4.1 problem the underline was added to fix.
 * That rule is about color being the *only* carrier of information, and in this
 * state the marking carries no information to lose: the items are uniform, so
 * there is no "which one" for a user who cannot see the green to be denied.
 * `aria-current="page"` is still on each link either way, so the programmatic
 * signal is untouched. Everywhere else — the report pages, and any top-level
 * item that is genuinely a page of its own — the underline is still drawn,
 * because there it does distinguish one item from four others.
 *
 * Scoped to `--lvl-0` and to the two "this item is itself the current page"
 * classes on purpose. `current-menu-ancestor` is deliberately not included: an
 * ancestor marker on the front page would mean something different from this
 * and should not be swallowed by the same rule.
 *
 * Specificity: (0,5,2) against the (0,4,1) of the block above, so it wins on
 * weight and not only on order.
 */
body.home .crane-mfi-nav__item--lvl-0.current-menu-item > .crane-mfi-nav__link .crane-mfi-nav__label::after,
body.home .crane-mfi-nav__item--lvl-0.current_page_item > .crane-mfi-nav__link .crane-mfi-nav__label::after,
body.home .crane-mfi-nav__item--lvl-0.current-menu-item > .crane-mfi-nav__toggle .crane-mfi-nav__label::after,
body.home .crane-mfi-nav__item--lvl-0.current_page_item > .crane-mfi-nav__toggle .crane-mfi-nav__label::after {
	content: none;
}

/*
 * 20.56 x 16, which is the box FontAwesome's `fa-fw` caret occupied, not the
 * size of the mark. The mark itself stays 16x16 and centred, because the SVG
 * keeps its own 16x16 viewBox and the default `preserveAspectRatio` fits it to
 * the height.
 *
 * Reproducing the box rather than only the mark is what keeps the rest of the
 * bar where it was. The links are right-aligned as a group, so every pixel this
 * is narrower than the glyph it replaces pushes all five of them to the right:
 * with the caret at a plain 16px and the search at its natural 17px, the whole
 * navigation sat 32.56px too far right — 4.56 from here and 28 from the search.
 */
.crane-mfi-nav__caret {
	display: block;
	flex: 0 0 auto;
	width: 20.56px;
	height: 16px;
}

@media ( prefers-reduced-motion: no-preference ) {

	.crane-mfi-nav__caret {
		transition: transform 0.15s ease-out;
	}
}

.crane-mfi-nav__toggle[aria-expanded="true"] .crane-mfi-nav__caret {
	transform: rotate( 180deg );
}

/* --------------------------------------------------------------------------
   The dropdown
   --------------------------------------------------------------------------

   Closed with `display: none`, driven off the button's own `aria-expanded`.
   Tying the two together in the selector is what makes it impossible for the
   attribute and the picture to disagree: there is no separate class that could
   be set without the other, and the server renders the closed state, so the
   panel is shut before any script runs.
   -------------------------------------------------------------------------- */

.crane-mfi-nav__submenu {
	position: absolute;
	top: 100%;

	/*
	 * -15px, so the dropdown's own 15px of padding puts its text at the same x
	 * as the parent label above it. Measured: parent label at 1045.44, dropdown
	 * box at 1030.44.
	 */
	left: -15px;
	z-index: 10;
	box-sizing: border-box;
	width: 230px;
	margin: 0;
	padding: 0;
	list-style: none;
	background: var( --crane-mfi-header-bg );
	box-shadow: 0 2px 6px rgba( 0, 0, 0, 0.12 );
}

.crane-mfi-nav__toggle[aria-expanded="false"] + .crane-mfi-nav__submenu {
	display: none;
}

.crane-mfi-nav__item--lvl-1 {
	display: block;
}

/*
 * 12 + 22.4 + 12 = 46.4, against a measured row height of 46.39.
 */
.crane-mfi-nav__item--lvl-1 > .crane-mfi-nav__link {
	display: block;
	height: auto;
	padding: 12px 15px;
	font-size: 16px;
	font-weight: 400;
	line-height: 22.4px;
	text-transform: capitalize;
	color: var( --crane-mfi-dropdown-color );
}

.crane-mfi-nav__item--lvl-1 > .crane-mfi-nav__link:hover,
.crane-mfi-nav__item--lvl-1 > .crane-mfi-nav__link:focus {
	color: var( --crane-mfi-nav-current );
}

/* --------------------------------------------------------------------------
   Search
   -------------------------------------------------------------------------- */

.crane-mfi-header__actions {
	display: flex;
	align-items: center;

	/*
	 * 15px from the caret of the last menu item. Measured: caret ends at 1245,
	 * the search icon starts at 1260.
	 */
	margin-left: 15px;
}

.crane-mfi-header__search-toggle {
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
	font-family: Cabin, sans-serif;
	font-size: 11px;
	font-weight: 400;
	line-height: 19.8px;
	color: var( --crane-mfi-nav-color );
	cursor: pointer;
}

.crane-mfi-header__search-toggle:hover,
.crane-mfi-header__search-toggle:focus {
	color: var( --crane-mfi-nav-current );
}

/*
 * The word "Search" is hidden on the bar and shown in the drawer, which is
 * where the old header put it. It is clipped rather than `display: none`, so it
 * is still the button's accessible name at every width — the icon is
 * `aria-hidden`, so without this the control would have no name at all on
 * desktop, which is the same defect as the logo.
 */
@media ( min-width: 1024px ) {

	/*
	 * 45px wide, which is the box Groovy Menu's icon-font magnifier occupied.
	 * See the note on .crane-mfi-nav__caret: the group is right-aligned, so the
	 * width of this box sets where the whole navigation starts.
	 */
	.crane-mfi-header__search-toggle {
		width: 45px;
		justify-content: center;
	}

	.crane-mfi-header__search-label {
		position: absolute;
		width: 1px;
		height: 1px;
		margin: -1px;
		padding: 0;
		overflow: hidden;
		clip: rect( 0, 0, 0, 0 );
		clip-path: inset( 50% );
		white-space: nowrap;
		border: 0;
	}
}

.crane-mfi-search {
	position: fixed;
	inset: 0;
	z-index: 100000;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgba( 255, 255, 255, 0.98 );
}

/*
 * `[hidden]` is only `display: none` at the browser's default specificity, and
 * the `display: flex` above beats it. Without this the dialog would be visible
 * whenever the stylesheet loaded, which is the exact failure the `hidden`
 * attribute was chosen to avoid.
 */
.crane-mfi-search[hidden] {
	display: none;
}

.crane-mfi-search__inner {
	position: relative;
	box-sizing: border-box;
	width: 100%;
	max-width: 640px;
	padding: 0 20px;
	text-align: center;
}

.crane-mfi-search__close {
	position: absolute;
	top: -80px;
	right: 20px;
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
	color: var( --crane-mfi-drawer-color );
	cursor: pointer;
}

.crane-mfi-search__title {
	margin: 0 0 24px;
	font-family: Cabin, sans-serif;
	font-size: 20px;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var( --crane-mfi-dropdown-color );
}

.crane-mfi-search__label {
	display: block;
	margin-bottom: 8px;
	font-family: Cabin, sans-serif;
	font-size: 14px;
	color: var( --crane-mfi-dropdown-color );
	text-align: left;
}

.crane-mfi-search__row {
	display: flex;
	gap: 8px;
}

.crane-mfi-search__input {
	flex: 1 1 auto;
	box-sizing: border-box;
	min-width: 0;
	padding: 12px 14px;
	border: 1px solid var( --crane-mfi-drawer-color );
	background: #ffffff;
	font-family: Cabin, sans-serif;
	font-size: 16px;
	color: var( --crane-mfi-dropdown-color );
}

.crane-mfi-search__submit {
	flex: 0 0 auto;
	padding: 12px 20px;
	border: 1px solid var( --crane-mfi-dropdown-color );
	background: var( --crane-mfi-dropdown-color );
	font-family: Cabin, sans-serif;
	font-size: 14px;
	font-weight: 600;
	text-transform: uppercase;
	color: #ffffff;
	cursor: pointer;
}

/* --------------------------------------------------------------------------
   The burger and the drawer
   --------------------------------------------------------------------------

   Hidden above 1024px, which is Groovy Menu's own breakpoint rather than a
   number picked here.
   -------------------------------------------------------------------------- */

.crane-mfi-header__burger {
	display: none;
}

@media ( max-width: 1023px ) {

	:root {
		--crane-mfi-header-h: 70px;
		--crane-mfi-header-h-compact: 70px;
		--crane-mfi-logo-h: 44px;
		--crane-mfi-logo-h-compact: 44px;
	}

	/*
	 * Above the drawer, so the same control that opens it also closes it. The
	 * old header hid this button under the drawer and put a second, separate
	 * close button a few pixels away inside it; one control that reports its own
	 * state in `aria-expanded` is both simpler and truthful.
	 */
	/*
	 * `margin-left: auto` and nothing else on the right, so the bars stop at the
	 * container's content edge — 15px in from the viewport, the same inset the
	 * logo has on the left.
	 *
	 * This rule used to carry `margin-right: -15px` to cancel the container's
	 * padding, described as putting the bars "flush against the container edge".
	 * That cancelled the wrong 15px. The measurement recorded beside it —
	 * the old burger running **x=336 to x=360** in a 375px viewport — is the
	 * container's *content* edge, and 360 is 15px inside the viewport, not at
	 * it. Read off `tests/header-baseline-groovy.json` (2022 / 375 / rest) to
	 * confirm rather than from the comment: one 24x3 bar at x=336, right edge
	 * 360. The negative margin moved ours to x=351..375, hard against the screen
	 * edge, which is what the client reported.
	 *
	 * So the fix is to remove the cancellation, not to add padding on top of it.
	 * Adding padding would have left the button's own box overhanging the
	 * container and only moved the bars back by eye.
	 */
	/*
	 * The padding is the tap target, and it grows left and vertically only.
	 *
	 * The painted icon is 24x19 — three 3px bars with two 5px gaps — so the
	 * control was smaller than the 24x24 of WCAG 2.2 SC 2.5.8. That is **not** a
	 * failure here: 2.5.8 exempts an undersized target whose 24px-diameter
	 * circle does not intersect another target's, and measured at 375, 768 and
	 * 1023px, drawer closed and open, the nearest approach is 18.2px (to the
	 * first drawer link). It passes on the exception. This padding is therefore
	 * an ergonomics improvement, not a conformance fix — do not record it as
	 * one.
	 *
	 * 20px on the left takes the box to 44 wide, the figure Apple and Google
	 * both give for a touch target. Nothing else lives to the left until the
	 * logo ends at x=139, so it is free space.
	 *
	 * **8px block, and not the 22 that 44 square would need.** The drawer's
	 * first link sits 13.5px below the icon, and this button carries
	 * `z-index: 2` so that it stays above the open drawer — so a box tall enough
	 * to reach it would not look wrong, it would silently take taps aimed at
	 * "President's Note". 8px gives a 44x35 target with 5.5px still clear.
	 * Re-measure that clearance before increasing this.
	 *
	 * No padding on the right, and so no negative margin to cancel it: the bars
	 * must stay at the container's content edge, which is what the rule above
	 * exists to do. The asymmetry is also the right way round for a thumb
	 * reaching the top corner of a phone, which falls short and inward, never
	 * past the screen edge.
	 */
	.crane-mfi-header__burger {
		position: relative;
		z-index: 2;
		display: flex;
		align-items: center;
		margin: 0 0 0 auto;
		padding: 8px 0 8px 20px;
		border: 0;
		background: none;
		cursor: pointer;
	}

	.crane-mfi-header__burger-box {
		display: flex;
		flex-direction: column;
		gap: 5px;
		width: 24px;
	}

	.crane-mfi-header__burger-bar {
		display: block;
		width: 24px;
		height: 3px;
		background: var( --crane-mfi-burger );
	}

	/*
	 * Real elements rather than `::before` and `::after` on one bar, so each can
	 * be transformed on its own and the open state is a clean cross instead of
	 * the two overlapping 19.09px bars the old one produced.
	 */
	.crane-mfi-header__burger[aria-expanded="true"] .crane-mfi-header__burger-bar:nth-child( 1 ) {
		transform: translateY( 8px ) rotate( 45deg );
	}

	.crane-mfi-header__burger[aria-expanded="true"] .crane-mfi-header__burger-bar:nth-child( 2 ) {
		opacity: 0;
	}

	.crane-mfi-header__burger[aria-expanded="true"] .crane-mfi-header__burger-bar:nth-child( 3 ) {
		transform: translateY( -8px ) rotate( -45deg );
	}

	@media ( prefers-reduced-motion: no-preference ) {

		.crane-mfi-header__burger-bar {
			transition: transform 0.2s ease-out, opacity 0.2s ease-out;
		}
	}

	/*
	 * The logo goes while the drawer is open, which is what the old header did:
	 * its mobile `open` capture contains no logo image at all. Left visible, the
	 * 250px drawer cuts across it at x=125 in a 375px viewport and the wordmark
	 * reads as clipped rather than as deliberately behind something.
	 *
	 * `visibility` rather than `opacity`, so the home link leaves the tab order
	 * with the picture. A link that cannot be seen but can still be tabbed to is
	 * the same defect as a dropdown that is invisible but focusable.
	 */
	.crane-mfi-header.is-drawer-open .crane-mfi-header__logo {
		visibility: hidden;
	}

	.crane-mfi-header__menu {
		position: fixed;
		top: 0;
		right: 0;
		bottom: 0;
		z-index: 1;
		box-sizing: border-box;
		width: 250px;
		margin: 0;

		/*
		 * 58px above the first item, which is where the old drawer's own close
		 * control sat. Measured: the first drawer row opened at y=58.39.
		 */
		padding: 58px 15px 24px;
		overflow-y: auto;
		background: var( --crane-mfi-header-bg );
		transform: translateX( 100% );
		visibility: hidden;

		/*
		 * A column, so the search can be pushed to the bottom of the drawer with
		 * `margin-top: auto` below. That is where the old drawer put it — the
		 * measured search icon sat at y=803.81 in a 900px viewport, well below
		 * the last menu item.
		 */
		display: flex;
		flex-direction: column;
	}

	@media ( prefers-reduced-motion: no-preference ) {

		.crane-mfi-header__menu {
			transition: transform 0.25s ease-out, visibility 0.25s;
		}
	}

	.crane-mfi-header.is-drawer-open .crane-mfi-header__menu {
		transform: translateX( 0 );
		visibility: visible;
	}

	.crane-mfi-nav__list {
		display: block;
		height: auto;
	}

	.crane-mfi-nav__item {
		display: block;
	}

	/*
	 * 9 + 16.8 + 9 + 1 = 35.8, against a measured drawer row height of 35.8.
	 */
	.crane-mfi-nav__link,
	.crane-mfi-nav__toggle {
		box-sizing: border-box;
		display: flex;
		justify-content: space-between;
		width: 100%;
		height: auto;
		padding: 9px 0;
		border-bottom: 1px dotted var( --crane-mfi-drawer-color );
		font-size: 12px;
		font-weight: 700;
		line-height: 16.8px;
		text-align: left;
		color: var( --crane-mfi-drawer-color );
	}

	.crane-mfi-nav__submenu {
		position: static;
		width: auto;
		padding-left: 15px;
		box-shadow: none;
	}

	/*
	 * 9 + 15.4 + 9 + 1 = 34.4, against a measured second-level row height of
	 * 34.39.
	 */
	.crane-mfi-nav__item--lvl-1 > .crane-mfi-nav__link {
		display: block;
		padding: 9px 0;
		font-size: 11px;
		font-weight: 700;
		line-height: 15.4px;
		text-transform: uppercase;
		color: var( --crane-mfi-drawer-color );
	}

	.crane-mfi-header__actions {
		margin: auto 0 0;
		padding-top: 24px;
		justify-content: flex-start;
	}

	.crane-mfi-header__search-toggle {
		flex-direction: column;
		gap: 6px;
		color: var( --crane-mfi-drawer-color );
	}
}


/* --------------------------------------------------------------------------
   The close control on the search panel
   --------------------------------------------------------------------------

   Crane sets `button:hover, button:focus { color: #fff }`
   (`themes/crane/assets/css/style-main.css:11639`) at specificity (0,1,1).
   `.crane-mfi-search__close` is (0,1,0), so the parent wins on hover however
   late this file loads — and the panel's ground is
   `rgba( 255, 255, 255, 0.98 )`. Both the ring and the cross of the close icon
   are stroked with `currentColor`, so the whole control resolves to white on
   white and disappears under the pointer.

   Measured under a real hover rather than inferred: computed `color`,
   `circle` stroke and `path` stroke were all `rgb( 255, 255, 255 )` against a
   `rgba( 255, 255, 255, 0.98 )` panel — **1.0:1**, where WCAG 1.4.11 requires
   3:1 for a control's visual boundary.

   Keyboard focus alone was **not** affected: the control kept `#5a5a5a` and
   took the site-wide focus ring. So this is a pointer-only fault, and the ring
   is not what fixes it.

   The two sibling controls in this header — `.crane-mfi-nav__toggle` and
   `.crane-mfi-header__search-toggle` — already carry their own `:hover, :focus`
   color rules for exactly this reason, which is why neither of them was
   reported. This control was the only one missing that pair. The fix is to
   match them rather than to reach for `!important`.

   **The selector below wins outright, and it does not depend on load order.**
   An earlier version of this note said it ties with the parent at (0,1,1) and
   wins on source order. That was wrong. A pseudo-class counts in the *class*
   column, so `.crane-mfi-search__close:hover` is **(0,2,0)** against the
   parent's `button:hover` at (0,1,1) — two class-column entries beat one, and
   the element column is never reached. The rule would win even if `child.css`
   loaded first.

   Worth keeping the distinction, because it changes what is safe to do next: a
   rule that only wins on order is fragile against an enqueue change, and this
   one is not. The dependency on `crane-style-main` is still needed for other
   rules in this file — see the header of `functions.php` — just not for this
   one.

   `--crane-mfi-dropdown-color` is #16181b, which is 16.1:1 on the panel — a
   darkening on hover, the same direction the nav links move.
   -------------------------------------------------------------------------- */

.crane-mfi-search__close:hover,
.crane-mfi-search__close:focus {
	color: var( --crane-mfi-dropdown-color );
}

/* --------------------------------------------------------------------------
   Templates whose content starts at the top of the document
   --------------------------------------------------------------------------

   The bar is `position: fixed` and the annual reports deliberately run under
   it — the 2022 hero starts at y=80 — so there is no spacer, and adding one
   would push every report down 100px. That is recorded in the header section
   above and it is still the right call for the reports.

   It is the wrong call everywhere else. Crane's `search.php` and `404.php` open
   straight into a text heading with no hero behind it, so the first thing on
   the page is drawn underneath an opaque white bar.

   Measured at 1440x900, scrollY 0, bar 100.67px tall, by hit-testing rather
   than by comparing numbers:

     search results   `<h1>Search results: 2021</h1>` at y=80.
                      `document.elementFromPoint()` over it returned
                      `DIV.crane-mfi-header__bar`.
     404              `.crane-404__header` at y=60, hit-test returned
                      `DIV.crane-mfi-header__inner`.

   The resting height is the right number here, not the compact one. The bar
   only shrinks to 50px once the page has scrolled, and these templates are
   obscured at the top of the document, which is exactly where it is 100px.
   `--crane-mfi-header-h` already becomes 70px under 1024px in `:root`, so one
   `var()` covers both widths and there is no second number to keep in step.

   The list is positive rather than `body:not( .page )` on purpose. Every report
   and every report sub-page is a `page`, and an inverse rule would silently
   start offsetting any future template that is not one.
   -------------------------------------------------------------------------- */

body.search main.crane-content,
body.error404 main.crane-content,
body.blog main.crane-content,
body.archive main.crane-content,
body.single main.crane-content {
	padding-top: var( --crane-mfi-header-h );
}


/* --------------------------------------------------------------------------
   The financial-statements download link
   --------------------------------------------------------------------------

   The PDF of the financial statements is invisible on the reports that offer
   one. Not low contrast — **1.0:1**, white text on the white page.

   Measured, with the accordion forced open so the link had a real box: on the
   2022 report `MFI-2022-Financials` renders 123x16px with computed
   `color: rgb(255, 255, 255)` and an effective background of
   `rgb(255, 255, 255)`. The same on 2023 with `MFI-2023-Financials`. The link
   works and is clickable; there is simply nothing to see.

   ## Where the white comes from

   Not from the parent stylesheet, and not from anything in this repository.
   It is `a { color: #ffffff }` inside `crane-style-main-inline-css`, which
   Crane generates from the saved **theme options** — the link typography
   setting. It is specificity (0,0,1), the weakest a rule can be, so anything
   more specific beats it.

   That is why this shows up in exactly one place. Every other link on the
   reports is a `.wp-block-button`, which supplies its own colored background,
   and white on that button is correct and deliberate. `.wp-block-file` is the
   one block that puts a link on the bare page and adds no color of its own, so
   it inherits the global white and vanishes.

   ## Why the fix is here and not in the theme options

   Changing the option would mean reactivating Grooni Theme Addons to reach the
   Redux screen, and the value lives in each environment's own database — so it
   would have to be done again on dev, staging and production, and it would be
   lost on any install that gets a fresh copy. It would also change every link
   on the site, including the buttons where white is right.

   A rule here deploys with the theme, applies everywhere at once, and touches
   only the block that is broken.

   `#3a3a3a` is the site's own body text color, read off `main p` rather than
   chosen — 10.6:1 on white. The underline is not decoration: color alone
   cannot be the only thing marking a link (WCAG 1.4.1), and these sit inside
   running text.

   ## `.wp-block-file__button` must be excluded, and this was learned the hard
   way

   The block contains **two** links: the filename, and a "Download" button
   beside it. The first version of this rule matched both, and it broke the
   second one — the button carries its own dark ground of `rgb(50, 55, 60)`,
   where white text measures about 11:1. Darkening it took the button from
   correct to **1.06:1**, which is worse than the fault being fixed.

   It was missed at first because the measurement was taken on the 2022 report,
   where that button happens to render with a zero-width box and so was skipped
   by the scan. It has a real box on 2023. The lesson is the one this project
   keeps relearning: a selector aimed at a block needs checking against every
   element the block draws, not the one that was visibly wrong.
   -------------------------------------------------------------------------- */

.wp-block-file a:not( .wp-block-file__button ) {
	color: #3a3a3a;
	text-decoration: underline;
}

/* --------------------------------------------------------------------------
   The approved brand palette
   --------------------------------------------------------------------------

   The client chose new values for three brand colors on 2026-09-16, from the
   options in `private/reports/mfi-color-decisions.html`. All three are Option A
   — the same hue deepened until white text on it clears 4.5:1 — and the
   navigation green was kept as it is, so it is not in this block.

     teal          #80c1c3 -> #3b7c7e   white on it 4.81:1
     orange        #f06b34 -> #c9450f   white on it 4.84:1
     button green  #7c9469 -> #657855   white on it 4.80:1

   ## Why this is CSS and not a change to the stored values

   It is an explicit decision, taken on 2026-09-16: **the database is not to be
   touched.** The same reasoning as the `.wp-block-file` rule above applies and
   then some — every value lives in a per-environment database, so changing them
   at source means repeating the work on local, dev, staging and production, and
   none of it travels with a deploy. A rule here deploys with the theme and
   applies to every install at once.

   What that costs is recorded rather than glossed: the stored values do not
   change, so the block editor's color picker still offers the old hex. A
   section built later will be the old color again unless somebody overrides it
   here too. `private/deploy-checklist.md` carries the full account.

   ## Why `!important`, and why these selectors

   Every occurrence in the page content is a block-editor custom color written
   as an inline style, and an inline style beats any selector — so `!important`
   is the only instrument that reaches it. The declarations were read out of the
   database rather than guessed: **63 declarations across 61 `style` attributes**
   on the published pages, all lowercase, no space after the colon, using
   exactly two properties — `color` (40) and `background-color` (23).

   ## The substring trap, and the anchor that closes it

   An attribute selector matches a *substring*, and `background-color:#80c1c3`
   **contains** `color:#80c1c3`. So the obvious `[style*="color:#80c1c3"]` also
   matches every element that merely sets a background, and repaints its text.

   The first version of this block answered that with
   `:not([style*="background-color:#80c1c3"])`, which is correct for the text
   rule, and then added a compound rule for elements setting both halves:
   `[style*="color:#X"][style*="background-color:#X"]`. **That compound is the
   very bug the `:not()` existed to prevent.** Because the second string implies
   the first, the whole selector collapses to the background-only case — so it
   painted the label the same color as the button. Measured before the fix: 12
   controls at **1.00:1**, six staff buttons on the 2021 report, four "Read
   Here" and the PDF link on 2023, and one link on Chapter 4, every one of them
   declaring `color:#ffffff` inline and losing it to the `!important`. A rule
   written to fix a contrast failure had created a worse one.

   The anchor is what actually discriminates. A real `color` declaration is
   either first in the attribute or preceded by `;`, and `;background-color:`
   can never contain `;color:`. Counted on the live content: **38** of the 40
   are first, **2** are preceded by `;`, and **0** attributes have leading
   whitespace — so both forms are needed and `^=` is safe to use.

   With the anchor there is no need for `:not()` and no need for a compound
   rule: an element setting both gets both declarations from the two ordinary
   rules, which is what the pair of separators on Our People 2025 needs.

   Only the color properties are set. The lesson from the focus-outline rule
   further down this file is that a rule reaching broadly must declare narrowly;
   these carry no positioning, no layout, nothing but the color that changed.
   -------------------------------------------------------------------------- */

/* The teal. */
[style^="color:#80c1c3"],
[style*=";color:#80c1c3"] {
	color: #3b7c7e !important;
}

[style*="background-color:#80c1c3"] {
	background-color: #3b7c7e !important;
}

/* The orange. */
[style^="color:#f06b34"],
[style*=";color:#f06b34"] {
	color: #c9450f !important;
}

[style*="background-color:#f06b34"] {
	background-color: #c9450f !important;
}

/* The button green. */
[style^="color:#7c9469"],
[style*=";color:#7c9469"] {
	color: #657855 !important;
}

[style*="background-color:#7c9469"] {
	background-color: #657855 !important;
}

/*
 * The three rules that are not inline, and are not in any file either.
 *
 * These live in the Additional CSS post (id 182), which WordPress prints in
 * `wp_head` at priority 101 — after every enqueued stylesheet, so this file
 * cannot beat them on source order however late it is enqueued. `!important`
 * is what settles it, since none of the three uses `!important` itself.
 *
 * The accordion rule is the most consequential value in the whole set: it is
 * every accordion header on the 2021, 2022 and 2023 reports, which is the
 * failure B2 singled out at 3.06:1.
 */
.grants-accordion .gb-accordion-title {
	background-color: #c9450f !important;
}

.blue-links > a:hover,
.blue-links > a:visited {
	color: #3b7c7e !important;
}

/*
 * The one link whose color is not an inline style at all.
 *
 * A block that sets a *link* color does not get an inline style. WordPress
 * writes a rule into the page instead, keyed by a class it derives from the
 * block's own attributes — here `.wp-elements-<hash> a:where(:not(.wp-element-button))`
 * — so there is no `style="…"` for an attribute selector to match. It is the
 * "A Note From our President & CEO" link on the 2025 report.
 *
 * **The hash has to be named explicitly, and that is a liability worth stating.**
 * The obvious general form, `[class*="wp-elements-"] a`, cannot be used: the
 * same mechanism carries at least five other colors on these pages — #222222,
 * #323b2a, #3d5967, #636261 and more, counted off the live stylesheets — and a
 * selector keyed on the mechanism rather than the color would repaint all of
 * them.
 *
 * The hash is derived from the block's attributes, so **editing that block's
 * colors in wp-admin changes the hash and this rule silently stops applying.**
 * Nothing will report it. If the "A Note From our President" link goes back to
 * the old green, this is why.
 */
.wp-elements-03ab03d537c2059a1252e2297617bb54 a:where( :not( .wp-element-button ) ) {
	color: #657855 !important;
}

/*
 * The chart colors are deliberately NOT changed here, and the reason is not
 * that they were missed.
 *
 * `.mfi-chart__swatch` writes `background:#80c1c3` — the shorthand, which the
 * selectors above do not match because they look for `background-color:`. Adding
 * a shorthand rule would repaint the legend swatch and nothing else, because the
 * pie slice beside it is an SVG `fill` taken from the block's saved data. The
 * legend and the chart would then disagree about what teal means.
 *
 * The chart palette is also already solved on its own terms: the block measures
 * each slice and chooses dark or light label ink per slice, so the teal there is
 * not a contrast failure the way the heading teal was. Repainting it would
 * invalidate a decision the block made about #80c1c3, for a color it would no
 * longer be using.
 *
 * Changing the chart palette means changing the block data, which is a separate
 * job and a database one. See `private/deploy-checklist.md`.
 */

/* --------------------------------------------------------------------------
   When the script is not there
   --------------------------------------------------------------------------

   Everything above assumes `header.js` runs. This is what happens when it does
   not.

   It matters more here than it looks. The four earlier annual reports live
   *only* in this dropdown — checked directly across all 26 published pages,
   which found 2024, 2023, 2022 and 2021 linked from nothing else, against a
   control showing 4 of those 26 pages do contain a `page_id=` link. So a
   dropdown with no script to open it does not merely degrade the navigation; it
   puts four of the site's five reports out of reach.

   ## This block must be last in the file, and that is not a style preference

   The first version of it sat *before* the `max-width: 1023px` block. Media
   queries add no specificity, so at equal specificity the later rule wins, and
   every declaration here that also appears down there was silently beaten.
   Measured at 375px with scripting off: `.crane-mfi-header__menu` kept
   `position: fixed`, `transform: translateX(100%)` and `visibility: hidden`,
   the burger painted as `flex/visible` and did nothing, and **0 of the 4 report
   links were reachable**. The block existed, was correct in isolation, and did
   nothing at all on a phone.

   So it goes at the end of the file. Anything added after it is above it in the
   cascade and will beat it in exactly the same silent way.

   ## Two triggers, and the difference between them

   `scripting: none` matches when scripting is switched off. It does **not**
   match when scripting is on and the script merely failed to arrive — that is
   still `scripting: enabled` as far as the browser is concerned.

   `.crane-mfi-header--no-script` covers the case that can be detected on the
   server: `crane_mfi_header_script_available()` finds no `header.js` on disk,
   so the theme knows there will be no behavior and says so in the markup. That
   is the realistic partial-deploy failure, given this repository deploys each
   directory as its own rsync step.

   Neither covers a script that exists on the server and fails in transit. That
   is not detectable from CSS or from PHP, and the documentation does not claim
   it is.

   ## Why the whole header goes static

   The obvious fallback — open the dropdown in place — does not work, and the
   measurement says why. At 1440px the submenu is a flex item of a 100px-tall
   `align-items: center` row, so a 186px panel is centred on a 100px box and
   starts at **y=-43**: its first link sits above the top of the viewport with
   3px showing. Keeping the fixed bar means keeping that.

   So with no script the header stops being a fixed bar and becomes an ordinary
   block at the top of the document, with the menu as a plain nested list. The
   page content moves down instead of sliding underneath. It looks different
   from the designed header, which is the correct trade: this is the state where
   nothing can open, and every link being visible and reachable beats every link
   being in the right place.

   The toggle button is hidden rather than the panel merely being opened. A
   control reading `aria-expanded="false"` above a panel that is visibly open
   would be a worse lie than the closed panel it replaced.
   -------------------------------------------------------------------------- */

@media ( scripting: none ) {

	.crane-mfi-header__bar {
		position: static;
	}

	.crane-mfi-header__inner {
		height: auto;
		flex-wrap: wrap;
		padding-top: 12px;
		padding-bottom: 12px;
	}

	/*
	 * The logo is hidden behind the open drawer at narrow widths by a rule in
	 * the mobile block. There is no drawer here, so that must not apply.
	 */
	.crane-mfi-header__logo {
		visibility: visible;
	}

	.crane-mfi-header__burger,
	.crane-mfi-header__search-toggle,
	.crane-mfi-nav__toggle {
		display: none;
	}

	.crane-mfi-header__menu {
		position: static;
		width: 100%;
		height: auto;
		margin: 0;
		padding: 0;
		overflow: visible;
		transform: none;
		visibility: visible;
		display: block;
	}

	.crane-mfi-nav__list {
		display: block;
		height: auto;
	}

	.crane-mfi-nav__item {
		display: block;
	}

	.crane-mfi-nav__link {
		display: block;
		height: auto;
		padding: 9px 0;
	}

	.crane-mfi-nav__submenu,
	.crane-mfi-nav__toggle[aria-expanded="false"] + .crane-mfi-nav__submenu {
		display: block;
		position: static;
		width: auto;
		padding-left: 20px;
		box-shadow: none;
	}

	.crane-mfi-nav__item--lvl-1 > .crane-mfi-nav__link {
		padding: 9px 0;
	}
}

/*
 * The same fallback, for the case PHP can see: no `header.js` on disk. Written
 * out rather than folded into the selector list above, because `scripting: none`
 * is not understood by every browser this may meet, and a browser that cannot
 * parse the media query would throw away the whole rule if the two shared one.
 */
.crane-mfi-header--no-script .crane-mfi-header__bar {
	position: static;
}

.crane-mfi-header--no-script .crane-mfi-header__inner {
	height: auto;
	flex-wrap: wrap;
	padding-top: 12px;
	padding-bottom: 12px;
}

.crane-mfi-header--no-script .crane-mfi-header__logo {
	visibility: visible;
}

.crane-mfi-header--no-script .crane-mfi-header__burger,
.crane-mfi-header--no-script .crane-mfi-header__search-toggle,
.crane-mfi-header--no-script .crane-mfi-nav__toggle {
	display: none;
}

.crane-mfi-header--no-script .crane-mfi-header__menu {
	position: static;
	width: 100%;
	height: auto;
	margin: 0;
	padding: 0;
	overflow: visible;
	transform: none;
	visibility: visible;
	display: block;
}

.crane-mfi-header--no-script .crane-mfi-nav__list {
	display: block;
	height: auto;
}

.crane-mfi-header--no-script .crane-mfi-nav__item {
	display: block;
}

.crane-mfi-header--no-script .crane-mfi-nav__link {
	display: block;
	height: auto;
	padding: 9px 0;
}

.crane-mfi-header--no-script .crane-mfi-nav__submenu,
.crane-mfi-header--no-script .crane-mfi-nav__toggle[aria-expanded="false"] + .crane-mfi-nav__submenu {
	display: block;
	position: static;
	width: auto;
	padding-left: 20px;
	box-shadow: none;
}

.crane-mfi-header--no-script .crane-mfi-nav__item--lvl-1 > .crane-mfi-nav__link {
	padding: 9px 0;
}

/*
 * The top offset must come off in both no-script states.
 *
 * `body.search main.crane-content` above is (0,2,2). A reset written as plain
 * `main.crane-content { padding-top: 0 }` is (0,1,1) and loses to it, media
 * query or not — media queries add no specificity, which is the same trap this
 * whole section carries a warning about. So the reset repeats the selector list
 * to tie at (0,2,2) and wins on order, being later in the file.
 *
 * The class-based trigger cannot use a descendant combinator: the class is on
 * the `<header>` element (`template-parts/header-bar.php:58`), and `<main>` is
 * its *sibling* under `<body>`, not its child. `~` is what reaches it, and it
 * lands at (0,2,2) too.
 *
 * Both are needed because the offset exists only to clear a *fixed* bar, and in
 * both of these states the bar is `position: static` and takes its own space in
 * the flow. Leaving the padding on would open a 100px hole under a header that
 * is already pushing the content down.
 */
@media ( scripting: none ) {

	body.search main.crane-content,
	body.error404 main.crane-content,
	body.blog main.crane-content,
	body.archive main.crane-content,
	body.single main.crane-content {
		padding-top: 0;
	}
}

.crane-mfi-header--no-script ~ main.crane-content {
	padding-top: 0;
}
