/* NAV BREAKPOINT — SINGLE SOURCE OF TRUTH: the literal in the `@media (max-width: 991px)` block below. Media queries cannot read custom properties, so that block publishes `--nav-drawer: 1` and nav-mobile.js reads the flag instead of repeating the number; `--nav-breakpoint` is the same value in a form JS and tests can cross-check. */
:root {
  --nav-breakpoint: 991px;
  --nav-drawer: 0;
}

body.admin-bar {
  --wp-admin-bar-offset: 32px;
}

body.admin-bar .site-header {
  top: var(--wp-admin-bar-offset);
}

body.nav-open,
body.nav-open-fixed {
  overflow: hidden;
}

/* Fixed rather than sticky, with its height reserved as body padding: a sticky bar keeps its slot in the flow, so the compact-on-scroll state would pull every following section up the instant the class landed. --header-h is the RESTING height, and header-compact.js overwrites the placeholder with the measured one. */
.site-header {
  /* THE BAR'S OWN TOKEN API — a project restyles the header by rewriting these lines, and the structure (header.php, nav.js, nav-mobile.js) stays locked. They were once var() fallbacks, which made the fallback the real value and left the token gate unable to see the colour at all. */
  --header-bg: rgba(var(--white-rgb), 0.96);
  --header-border: rgba(var(--ink-rgb), 0.08);
  --header-utility-color: var(--ink);
  --header-logo-color: var(--ink);
  --header-logo-width: 12rem;
  --header-link-color: var(--ink);
  --header-link-active: var(--brand);
  --header-dropdown-bg: var(--white);
  --header-dropdown-border: rgba(var(--ink-rgb), 0.08);
  --header-dropdown-link: var(--ink);
  --header-dropdown-hover-bg: rgba(var(--brand-rgb), 0.08);
  --header-toggle-color: var(--ink);
  --header-social-color: var(--header-link-color);
  --header-social-hover: var(--header-link-active);
  --header-social-size: 1.375rem;
  --header-social-hit: 2.5rem;
  --header-social-gap: 0;
  --header-social-offset: 0.625rem;
  --header-compact-shadow: 0 4px 18px rgba(var(--ink-rgb), 0.09);
  --header-compact-pad: 0.4rem;
  --header-compact-logo-scale: 0.75;
  /* The drawer panel is the brand colour with white type on it, and --header-mobile-link-active is a separate name so a restyle can hold >= 4.5:1 without touching the resting link colour. */
  --header-mobile-bg: var(--brand);
  --header-mobile-link: var(--white);
  --header-mobile-link-active: var(--header-mobile-link);
  --header-mobile-close: var(--header-mobile-link);
  --header-mobile-divider: rgba(var(--white-rgb), 0.12);
  --header-mobile-social-divider: rgba(var(--white-rgb), 0.28);
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000;
  background: var(--header-bg);
  border-bottom: 1px solid var(--header-border);
  backdrop-filter: blur(12px);
  /* Naming the bar lifts it out of the page-wide crossfade into its own transition group, so a same-origin navigation paints it continuously. */
  view-transition-name: site-header;
}

/* The header is normally byte-identical on both documents, so there is nothing to crossfade — anything else reads as a flicker on a fixed element. */
::view-transition-old(site-header),
::view-transition-new(site-header) {
  animation: none;
  mix-blend-mode: normal;
}

/* `html body`, not `body`: WordPress core's global-styles-inline-css emits `body{padding:0}`
   (theme.json), and WHERE it prints moved once already — before the theme sheets on one build,
   after them on the next. At (0,0,1) this rule won or lost by print order, and page bundles grew
   their own clearance to survive the losing case; when the order flipped back, every interior page
   cleared the header twice (operator, 2026-09-13). (0,0,2) wins in both orders, so this is the ONLY
   clearance a theme built on this base may carry — never a page root, never a section. */
html body {
  padding-top: var(--header-h);
}

/* Anchor targets have to clear the fixed bar, or every #hash link lands with its heading hidden underneath the header. */
html {
  scroll-padding-top: var(--header-h);
}

.site-header.scrolled {
  box-shadow: 0 12px 30px rgba(15, 23, 42, 0.08);
}

.site-header__inner {
  display: grid;
  grid-template-columns: minmax(0, max-content) 1fr;
  grid-template-areas:
    "logo utility"
    "logo nav";
  align-items: center;
  column-gap: clamp(1.5rem, 3vw, 2.5rem);
  row-gap: 0.75rem;
  padding-block: 1rem;
}

/* With no `utility` menu the first grid row collapses to 0 but its row-gap survives, so the bar carries ~12px of phantom space and the logo centres half a gap above the nav's axis. header.php marks the wrapper and the grid drops to one row. Declared before the drawer breakpoint so the mobile grid still wins. */
.site-header__inner--no-utility {
  grid-template-areas: "logo nav";
  row-gap: 0;
  align-items: center;
}

.site-header__top {
  grid-area: utility;
  display: flex;
  justify-content: flex-end;
}

.site-header__utility-menu {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 1rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-header__utility-menu a {
  color: var(--header-utility-color);
  font-family: var(--sans);
  font-size: 0.95rem;
}

.site-header__middle {
  grid-area: logo;
  display: flex;
  align-items: center;
  gap: 1rem;
}

.site-header__logo {
  display: inline-flex;
  align-items: center;
  color: var(--header-logo-color);
}

.site-header__logo img {
  width: min(100%, var(--header-logo-width));
  height: auto;
}

.site-header__logo-text {
  font-family: var(--sans);
  font-size: clamp(1.125rem, 2vw, 1.5rem);
  font-weight: 700;
}

.site-header__nav {
  grid-area: nav;
  display: flex;
  justify-content: flex-end;
  width: 100%;
}

.site-nav,
.site-nav .sub-menu {
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(1rem, 2.2vw, 1.75rem);
}

.site-nav li {
  position: relative;
}

.site-nav a {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding-block: 0.35rem;
  font-family: var(--sans);
  font-size: 1rem;
  color: var(--header-link-color);
}

.site-nav > .menu-item-has-children > a::after {
  content: "";
  width: 0.5rem;
  height: 0.5rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg) translateY(-1px);
}

.site-nav .current-menu-item > a,
.site-nav .current-menu-ancestor > a,
.site-nav a:hover,
.site-nav a:focus-visible {
  color: var(--header-link-active);
}

.site-nav .sub-menu {
  position: absolute;
  top: calc(100% + 0.875rem);
  left: 0;
  min-width: 15rem;
  display: grid;
  gap: 0.125rem;
  padding: 0.75rem;
  background: var(--header-dropdown-bg);
  border: 1px solid var(--header-dropdown-border);
  border-radius: var(--radius-lg);
  box-shadow: 0 18px 48px rgba(15, 23, 42, 0.14);
  opacity: 0;
  visibility: hidden;
  transform: translateY(0.5rem);
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s ease;
}

.site-nav li:hover > .sub-menu,
.site-nav li:focus-within > .sub-menu {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  pointer-events: auto;
}

.site-nav .sub-menu a {
  justify-content: space-between;
  padding: 0.75rem 0.875rem;
  border-radius: var(--radius);
  color: var(--header-dropdown-link);
}

.site-nav .sub-menu a:hover,
.site-nav .sub-menu a:focus-visible {
  background: var(--header-dropdown-hover-bg);
}

/* Bare symbol, no chrome — and it is also the drawer's close control, so `flex: 0 0 auto` keeps the header's flex row from squeezing the 3rem box. */
.site-header__toggle {
  display: none;
  flex: 0 0 auto;
  width: 3rem;
  height: 3rem;
  margin-left: auto;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  color: var(--header-toggle-color);
  cursor: pointer;
}

.site-header__toggle span {
  display: block;
  width: 1.125rem;
  height: 2px;
  margin: 0.25rem auto;
  background: currentColor;
  /* Paced just ahead of the 380ms drawer slide so the X has landed by the time the panel finishes; at 200ms it snapped shut mid-travel. */
  transition: transform 300ms ease-out, opacity 300ms ease-out;
}

/* Convergence distance comes from the bar metrics, not from taste: 2px + 2 x 0.25rem margin = a 10px pitch, and a 6px translate stops short and reads as a ">". Keep these in step with the bar height and margin. */
.site-header__toggle.is-active span:nth-child(1) {
  transform: translateY(10px) rotate(45deg);
}

.site-header__toggle.is-active span:nth-child(2) {
  opacity: 0;
}

.site-header__toggle.is-active span:nth-child(3) {
  transform: translateY(-10px) rotate(-45deg);
}

/* The toggle sits above the drawer, which is painted --header-mobile-bg, so bars in the resting colour can end up invisible against it. */
body.nav-open .site-header__toggle span,
.site-header__toggle.is-active span {
  background: var(--header-mobile-close);
}

.site-header__toggle.is-active {
  color: var(--header-mobile-close);
}

/* Chrome controls ring on keyboard focus only: a tap must never leave a box around the burger or the X. */
.site-header__toggle:focus:not(:focus-visible) {
  outline: 0;
  box-shadow: none;
}

.site-header__toggle:focus-visible {
  outline: 2px solid var(--form-focus-border);
  outline-offset: 2px;
}

/* The drawer-only "Overview" row nav-mobile.js injects so the parent page stays reachable; desktop dropdowns never show it. */
.site-nav .sub-menu > .site-header__overview-item {
  display: none;
}

/* Header social icons, rendered inside .site-header__nav by header.php so they ride the mobile drawer. A 22px mark centred in a >=40px hit area: social glyphs are smaller than the pointer-target minimum, so the box is padded out rather than the art. */
.site-header__social {
  display: flex;
  align-items: center;
  margin-left: var(--header-social-offset);
}

.site-header__social-menu {
  display: flex;
  align-items: center;
  gap: var(--header-social-gap);
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-header__social-menu a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--header-social-hit);
  height: var(--header-social-hit);
  padding: 0;
  /* The glyph is the only thing carrying meaning (the label is sr-only text), so this colour has to clear 4.5:1 against the header background. */
  color: var(--header-social-color);
}

.site-header__social-menu .cnm-icon {
  font-size: var(--header-social-size); /* 22px */
  transition: color 150ms ease-out, transform 150ms ease-out;
}

.site-header__social-menu a:hover .cnm-icon,
.site-header__social-menu a:focus-visible .cnm-icon {
  color: var(--header-social-hover);
  transform: translateY(-1px);
}

/* --------------------------------------------------------------------------- Compact-on-scroll header. assets/js/header-compact.js adds .site-header--compact past a small scroll threshold and owns nothing else; every visual is here. The bar tightens by spending its own vertical padding and the logo scales from its LEFT edge, so the wordmark shrinks toward the corner it is anchored to instead of drifting inward. The logo keeps its full box while scaled, which is what lets the padding do the height reduction on its own. Safe because .site-header is fixed and its resting height is reserved as body padding-top (top of this file) — the bar can change height without moving anything below it. ------------------------------------------------------------------------- */
.site-header,
.site-header__inner,
.site-header__logo {
  transition: padding 300ms ease-out, box-shadow 300ms ease-out, transform 300ms ease-out;
}

.site-header__logo {
  transform-origin: left center;
}

.site-header--compact {
  box-shadow: var(--header-compact-shadow);
}

.site-header--compact .site-header__inner {
  padding-block: var(--header-compact-pad);
}

.site-header--compact .site-header__logo {
  transform: scale(var(--header-compact-logo-scale));
}

/* One-frame flag from header-compact.js: a page that loads already scrolled starts compact with no entrance animation. */
.site-header--no-transition,
.site-header--no-transition .site-header__inner,
.site-header--no-transition .site-header__logo {
  transition: none;
}

/* THE nav breakpoint literal. Keep `--nav-breakpoint` at the top of this file equal to it; nav-mobile.js reads the flag published here, not the number. */
@media (max-width: 991px) {
  :root {
    --nav-drawer: 1;
  }

  .site-header__inner {
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "utility utility"
      "logo logo"
      "nav nav";
  }

  .site-header__top {
    justify-content: flex-start;
  }

  .site-header__middle {
    width: 100%;
    justify-content: space-between;
  }

  .site-header__toggle {
    display: inline-flex;
    flex-direction: column;
    justify-content: center;
    position: relative;
    z-index: 110; /* above the drawer so the X stays clickable */
  }

  .site-header__nav {
    position: fixed;
    top: 0;
    right: -100%;
    width: 80%;
    max-width: 360px;
    height: 100vh;
    background: var(--header-mobile-bg);
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-start;
    padding: 96px 30px 30px;
    /* ease-out, not ease: the panel leaves fast and settles slowly instead of stopping dead at the edge. */
    transition: right 380ms ease-out;
    overflow-y: auto;
    z-index: 105;
    /* The panel is painted --header-mobile-bg, so the desktop link colours — chosen against the page background — routinely fall under 4.5:1 here. Set --header-mobile-bg and the three foreground tokens together. */
    color: var(--header-mobile-link);
  }

  .site-header__nav.is-open {
    right: 0;
  }

  body.nav-open {
    overflow: hidden;
  }

  .site-nav {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    width: 100%;
  }

  .site-nav > li {
    width: 100%;
    border-bottom: 1px solid var(--header-mobile-divider);
  }

  .site-nav > li > a {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 0;
    font-size: 1.125rem;
    color: var(--header-mobile-link);
  }

  /* The current item is marked with a rule, not a hue: the desktop active colour sits on the brand panel and scores ~2:1 there. */
  .site-nav .current-menu-item > a,
  .site-nav .current-menu-ancestor > a,
  .site-nav a:hover,
  .site-nav a:focus-visible {
    color: var(--header-mobile-link-active);
    text-decoration: underline;
    text-underline-offset: 0.25rem;
  }

  /* Pinned to the bottom of the drawer under a hairline rule — the conventional place, and far enough from the nav links not to read as one. */
  .site-header__social {
    width: 100%;
    margin: auto 0 0;
    padding-top: 1.5rem;
    /* Its own name, not the nav divider's: the two carried the SAME token at DIFFERENT weights, and collapsing them would let one silently win. */
    border-top: 1px solid var(--header-mobile-social-divider);
  }

  .site-header__social-menu {
    gap: 0.5rem;
    /* Pull the first hit area back so the glyph aligns with the nav labels' left edge instead of the box's. */
    margin-left: -0.5625rem;
  }

  .site-header__social-menu a {
    color: var(--header-mobile-link);
  }

  .site-header__social-menu a:hover .cnm-icon,
  .site-header__social-menu a:focus-visible .cnm-icon {
    color: var(--header-mobile-link);
    opacity: 0.75;
  }

  /* Sub-menu accordion (inline within drawer) — overrides desktop dropdown styles. Selectors carry 3 classes to beat the desktop sub-menu specificity. */
  .site-header__nav--mobile-accordion .site-nav > .menu-item-has-children > .sub-menu {
    position: static;
    list-style: none;
    margin: 0;
    padding: 0 0 12px 16px;
    min-width: 0;
    background: transparent;
    border: 0;
    box-shadow: none;
    opacity: 1;
    visibility: visible;
    transform: none;
    pointer-events: auto;
    transition: none;
    display: none;
  }

  .site-header__nav--mobile-accordion .site-nav > .menu-item-has-children > .sub-menu::before {
    display: none;
  }

  .site-header__nav--mobile-accordion .site-nav > .menu-item-has-children.is-open > .sub-menu,
  .site-header__nav--mobile-accordion .site-nav > .menu-item-has-children.current-menu-item > .sub-menu,
  .site-header__nav--mobile-accordion .site-nav > .menu-item-has-children.current-menu-ancestor > .sub-menu,
  .site-header__nav--mobile-accordion .site-nav > .menu-item-has-children.current-menu-parent > .sub-menu {
    display: block;
  }

  .site-header__nav--mobile-accordion .site-nav > .menu-item-has-children > .sub-menu li {
    border-bottom: 0;
  }

  .site-header__nav--mobile-accordion .site-nav > .menu-item-has-children > .sub-menu > .site-header__overview-item {
    display: block;
  }

  .site-header__nav--mobile-accordion .site-nav > .menu-item-has-children > .sub-menu a {
    display: block;
    padding: 10px 0;
    font-size: 0.9375rem;
    font-weight: 300;
    color: var(--header-mobile-link);
    text-decoration: none;
    background: transparent;
    opacity: 0.85;
  }

  .site-header__nav--mobile-accordion .site-nav > .menu-item-has-children > .sub-menu a:hover,
  .site-header__nav--mobile-accordion .site-nav > .menu-item-has-children > .sub-menu a:focus-visible {
    opacity: 1;
    background: transparent;
  }
}
/* Reduced motion: nothing in the header animates — not the compact transition, not the drawer slide, not the hamburger's fold into an X. States still change instantly, so every control keeps working. */
@media (prefers-reduced-motion: reduce) {
  .site-header,
  .site-header__inner,
  .site-header__logo,
  .site-header__nav,
  .site-header__toggle span,
  .site-header__social-menu .cnm-icon {
    transition: none;
  }

  .site-header__social-menu a:hover .cnm-icon,
  .site-header__social-menu a:focus-visible .cnm-icon {
    transform: none;
  }
}

/* templates/page-landing.php renders no bar: the one `html body` clearance above is excepted by body class, and --header-h resolves to 0 for everything that reads it. */
html:has(> body.no-site-header) {
  scroll-padding-top: 0;
}

html body.no-site-header {
  --header-h: 0px;
  padding-top: 0;
}

.skip-link {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1000;
  padding: 0.75rem 1rem;
  background: var(--white);
  color: var(--black);
  transform: translateY(-120%);
}

.skip-link:focus,
.skip-link:focus-visible {
  transform: translateY(0);
}
