/**
 * IB4A global foundation.
 *
 * Plain CSS only - no SCSS, no Tailwind, no Bootstrap.
 *
 * The custom properties below are FALLBACKS. Theme Options emits a :root
 * block after this file (see inc/dynamic-css.php) which overrides them, so
 * editing a colour or the container in the admin updates the whole site.
 *
 * Media queries cannot read CSS variables, so the breakpoints are fixed
 * here while the values they select between stay editable.
 */

/* ---------------------------------------------------------------------------
   Tokens (fallbacks - Theme Options wins)
   --------------------------------------------------------------------------- */
:root {
  /* Palette */
  --clr-navy: #202050;
  --clr-teal: #5bc4c4;
  --clr-gold: #f2c53d;
  --clr-off-white: #f5f5f5;
  --clr-white: #ffffff;

  /* Typography */
  --font-display: "Barlow Condensed", sans-serif;
  --font-body: "DM Sans", sans-serif;
  --heading-tracking: 0.04em;
  --heading-line-height: 1.05;

  /* Container */
  --container-max-width: 1440px;
  --container-pad-desktop: 100px;
  --container-pad-tablet: 50px;
  --container-pad-mobile: 20px;

  /* Mobile-first: the base value is the mobile one, stepped up below. */
  --container-padding: var(--container-pad-mobile);

  /* Rhythm */
  /* 80px on mobile to 112px on desktop, matching the design's
     py-20 -> md:py-28 pairing. */
  --section-space: clamp(80px, 8vw, 112px);
  --transition: 0.3s ease;
}

/* Tablet: 768px and up */
@media (min-width: 768px) {
  :root {
    --container-padding: var(--container-pad-tablet);
  }
}

/* Desktop: 992px and up */
@media (min-width: 992px) {
  :root {
    --container-padding: var(--container-pad-desktop);
  }
}

/* ---------------------------------------------------------------------------
   Base
   --------------------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: var(--font-body);
  color: var(--clr-navy);
  background: var(--clr-white);
  overflow-x: hidden;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  font-family: var(--font-display);
  font-weight: 800;
  letter-spacing: var(--heading-tracking);
  line-height: var(--heading-line-height);
  margin: 0 0 0.5em;
}

img {
  max-width: 100%;
  height: auto;
  display: block;
}

a {
  color: inherit;
  transition: color var(--transition);
}

/* ---------------------------------------------------------------------------
   Wrapper / container

   Caps out at --container-max-width (1440px by default) and stays fluid
   below that, keeping its side padding the whole way down. Because
   box-sizing is border-box, the padding sits INSIDE the max-width, so the
   content area is 1440 - (2 x 100) = 1240px on desktop.
   --------------------------------------------------------------------------- */
.wrapper {
  width: 100%;
  max-width: var(--container-max-width);
  margin-inline: auto;
  padding-inline: var(--container-padding);
}

/* Opt-out for sections that must bleed edge to edge while their inner
   content still aligns to the container. */
.wrapper--full {
  max-width: none;
  padding-inline: 0;
}

/* ---------------------------------------------------------------------------
   In-page anchors
   --------------------------------------------------------------------------- */
/*
 * Smooth scrolling for every in-page anchor - the hero Scroll link, and any
 * menu item pointing at a Section ID. Set on html (not on a single link) so
 * behaviour is consistent wherever an anchor is used.
 */
html {
  scroll-behavior: smooth;
}

/*
 * Animated scrolling is a documented vestibular trigger, so honour the OS
 * setting - matching how the hero bounce and image drift are already handled.
 */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

/* ---------------------------------------------------------------------------
   Section rhythm
   --------------------------------------------------------------------------- */
.section {
  padding-block: var(--section-space);
}

/* ---------------------------------------------------------------------------
   Shared text components
   --------------------------------------------------------------------------- */
.sub_sec__heading {
  margin: 0 0 16px;
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.3em;
  color: var(--clr-teal);
  font-size: clamp(0.8125rem, 1vw, 0.875rem);
}

.sec__heading {
  margin: 0 0 30px;
  font-weight: 800;
  /*
   * 36px on small screens rising to 60px. The design pairs text-5xl with
   * md:text-6xl, but a 48px floor reads oversized on a 375px screen, so the
   * floor is lowered and the top of the range is unchanged.
   */
  font-size: clamp(2.25rem, 5.5vw, 3.75rem);
  line-height: 1;
  text-transform: uppercase;
}

.body__text {
  /* The design uses a flat text-base (16px) with leading-relaxed for body
     copy, not a fluid size - a clamp was rendering it at 18px/29.7px. */
  font-size: 1rem;
  line-height: 1.625;
  /* Design body copy is the section's text colour at 80%. color-mix keeps it
     relative to the section, so it works on both light and dark bands. */
  color: color-mix(in srgb, currentColor 80%, transparent);
}

.teal__color {
  color: var(--clr-teal);
}

.gold__color {
  color: var(--clr-gold);
}

/* ---------------------------------------------------------------------------
   Buttons
   --------------------------------------------------------------------------- */
.btn__wrap {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  line-height: 1.25rem;
  font-family: var(--font-body);
  font-weight: 900;
  font-size: 0.875rem;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  text-decoration: none;
  padding: 14px 28px;
  border: 2px solid transparent;
  cursor: pointer;
  transition: background-color var(--transition), color var(--transition),
    border-color var(--transition);
}

/*
 * :visited is declared on the base of every variant because these buttons are
 * anchors - without it a visited link can pick up the browser's own visited
 * colour. It sits BEFORE :hover/:focus-visible so those still win at equal
 * specificity. Only colour/background/border-colour are settable on :visited.
 */
.btn__primary,
.btn__primary:visited {
  background: var(--clr-gold);
  color: var(--clr-navy);
}

.btn__primary:hover,
.btn__primary:focus-visible {
  background: var(--clr-teal);
  color: var(--clr-white);
}

/* Teal fill with navy text is the design's pattern for this button. */
.btn__secondary,
.btn__secondary:visited {
  background: var(--clr-teal);
  color: var(--clr-navy);
}

.btn__secondary:hover,
.btn__secondary:focus-visible {
  background: var(--clr-gold);
  color: var(--clr-navy);
}

.btn__outline,
.btn__outline:visited {
  background: transparent;
  color: currentColor;
  border-color: currentColor;
}

/*
 * Hovers to navy with white text, matching the design (hover:bg-[#202050]
 * hover:text-white) - the same hover treatment the form's submit button uses.
 * This was previously teal, which was wrong.
 */
.btn__outline:hover,
.btn__outline:focus-visible {
  background: var(--clr-navy);
  border-color: var(--clr-navy);
  color: var(--clr-white);
}

/* ---------------------------------------------------------------------------
   Layout utilities
   --------------------------------------------------------------------------- */
.flex {
  display: flex;
}

.f-row {
  flex-direction: row;
}

.f-col {
  flex-direction: column;
}

.f-wrap {
  flex-wrap: wrap;
}

.jc-center {
  justify-content: center;
}

.jc-between {
  justify-content: space-between;
}

.ai-center {
  align-items: center;
}

.ta-center {
  text-align: center;
}

/* ---------------------------------------------------------------------------
   Accessibility
   --------------------------------------------------------------------------- */
.screen-reader-text {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/*
 * Focus ring.
 *
 * Deliberately NOT written with :where(). That pseudo-class contributes zero
 * specificity, so the rule was only (0,1,0) and the parent theme's own
 * `a:focus { outline: thin dotted }` at (0,1,1) beat it - every link on the
 * site was showing a 1px dotted ring instead of this one. Listing the
 * elements directly makes each selector (0,1,1), and loading after the parent
 * stylesheet it wins.
 *
 * The plain :focus reset comes first so a mouse click does not leave a ring;
 * :focus-visible then restores it for keyboard users.
 */
a:focus,
button:focus,
input:focus,
select:focus,
textarea:focus,
summary:focus {
  outline: none;
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible {
  outline: 3px solid var(--clr-teal);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
   Animations (from the design system)
   --------------------------------------------------------------------------- */
@keyframes slideUp {
  from {
    opacity: 0;
    transform: translateY(40px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.animate-slide-up {
  animation: slideUp 0.8s ease-out forwards;
}

.animate-fade-in {
  animation: fadeIn 0.6s ease-out forwards;
}

.teal-hover {
  position: relative;
}

.teal-hover::after {
  content: "";
  position: absolute;
  bottom: -2px;
  left: 0;
  width: 0;
  height: 2px;
  background: var(--clr-teal);
  transition: width var(--transition);
}

.teal-hover:hover::after,
.teal-hover:focus-visible::after {
  width: 100%;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ===========================================================================
   SITE HEADER

   Nav switches to the drawer below 992px, matching the project's desktop
   breakpoint (and assets/js/header.js). The design's own source switched at
   768px, but the tablet band is a distinct 50px-padding band here and four
   links plus a CTA are cramped at 768.
   =========================================================================== */
:root {
  --header-h: 64px;
  --header-logo-h: 40px;
}

.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  transition: background-color var(--transition), box-shadow var(--transition);
}

.site-header--solid,
.site-header.is-scrolled {
  background-color: var(--clr-navy);
}

.site-header.is-scrolled {
  box-shadow: 0 2px 20px rgba(0, 0, 0, 0.3);
}

.site-header--transparent:not(.is-scrolled) {
  background-color: transparent;
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: var(--header-h);
  gap: 24px;
}

/* Solid header is fixed, so inner pages need to clear it. The homepage
   deliberately does not - the header floats over the hero. */
body:not(.home) #primary {
  padding-top: var(--header-h);
}

/* --- Brand ---------------------------------------------------------------- */
.site-header__logo {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}

.site-header__logo-img {
  height: var(--header-logo-h);
  width: auto;
  object-fit: contain;
}

.site-header__logo-img--sticky {
  display: none;
}

.site-header.is-scrolled .site-header__logo-img--sticky {
  display: block;
}

.site-header.is-scrolled
  .site-header__logo-img--sticky
  ~ .site-header__logo-img--default,
.site-header.is-scrolled
  .site-header__logo-img--default:has(~ .site-header__logo-img--sticky) {
  display: none;
}

.site-header__title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.5rem;
  text-transform: uppercase;
  color: var(--clr-white);
}

/* --- Desktop nav --------------------------------------------------------- */
.site-nav {
  display: none;
}

.site-nav__menu {
  display: flex;
  align-items: center;
  gap: 32px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-nav__menu a {
  position: relative;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.875rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  text-decoration: none;
  color: var(--clr-white);
}

.site-nav__menu a::after {
  content: "";
  position: absolute;
  bottom: -4px;
  left: 0;
  width: 0;
  height: 2px;
  background: var(--clr-teal);
  transition: width var(--transition);
}

.site-nav__menu a:hover,
.site-nav__menu a:focus-visible {
  color: var(--clr-teal);
}

.site-nav__menu a:hover::after,
.site-nav__menu a:focus-visible::after {
  width: 100%;
}

/*
 * No focus ring on the nav links. Safe to drop here because focus is still
 * clearly signalled by the two rules above - the link turns teal and the teal
 * underline sweeps in - so keyboard users keep a visible indicator rather
 * than losing it entirely.
 */
.site-nav__menu a:focus,
.site-nav__menu a:focus-visible {
  outline: none;
}

.site-nav__menu .current-menu-item > a,
.site-nav__menu .current_page_item > a {
  color: var(--clr-teal);
}

.site-nav {
  align-items: center;
  gap: 32px;
}

.site-nav__cta .btn {
  padding: 8px 20px;
}

/* --- Hamburger ----------------------------------------------------------- */
.site-header__toggle {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  width: 44px;
  height: 44px;
  padding: 10px;
  margin-right: -10px;
  background: none;
  border: 0;
  cursor: pointer;
}

.site-header__toggle-bar {
  display: block;
  width: 24px;
  height: 2px;
  background: var(--clr-white);
  transition: transform var(--transition), opacity var(--transition);
}

.site-header.is-drawer-open .site-header__toggle-bar:nth-child(1) {
  transform: translateY(8px) rotate(45deg);
}

.site-header.is-drawer-open .site-header__toggle-bar:nth-child(2) {
  opacity: 0;
}

.site-header.is-drawer-open .site-header__toggle-bar:nth-child(3) {
  transform: translateY(-8px) rotate(-45deg);
}

/* --- Drawer -------------------------------------------------------------- */
.site-drawer {
  background: var(--clr-navy);
  border-top: 1px solid rgba(91, 196, 196, 0.3);
  max-height: 0;
  overflow: hidden;
  transition: max-height var(--transition);
}

.site-header.is-drawer-open .site-drawer {
  max-height: 80vh;
  overflow-y: auto;
}

.site-drawer__inner {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding-block: 20px;
}

.site-drawer__menu {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-drawer__menu a {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.5rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  text-decoration: none;
  color: var(--clr-white);
}

.site-drawer__menu a:hover,
.site-drawer__menu a:focus-visible,
.site-drawer__menu .current-menu-item > a {
  color: var(--clr-teal);
}

.site-drawer__cta .btn {
  align-self: flex-start;
  font-size: 1.125rem;
  padding: 12px 20px;
}

/* --- Desktop switch ------------------------------------------------------ */
@media (min-width: 992px) {
  .site-nav {
    display: flex;
  }

  .site-header__toggle,
  .site-drawer {
    display: none;
  }
}

/* ===========================================================================
   SITE FOOTER

   Three columns from 768px up (a content grid, unrelated to the nav's 992px
   switch). Stacks to one column below that.
   =========================================================================== */
:root {
  --footer-logo-h: 56px;
}

.site-footer {
  background: var(--clr-navy);
  color: var(--clr-white);
}

.site-footer__inner {
  padding-block: 56px;
}

.site-footer__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 40px;
}

@media (min-width: 768px) {
  .site-footer__grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* --- Brand column -------------------------------------------------------- */
.site-footer__logo {
  display: inline-flex;
  margin-bottom: 20px;
  text-decoration: none;
}

.site-footer__logo-img {
  height: var(--footer-logo-h);
  width: auto;
  object-fit: contain;
}

.site-footer__tagline {
  margin: 0 0 16px;
  color: rgba(255, 255, 255, 0.7);
  font-size: 0.9375rem;
  line-height: 1.6;
}

.site-footer__email,
.site-footer__phone {
  display: table;
  color: var(--clr-teal);
  font-weight: 500;
  font-size: 0.875rem;
  /* tracking-wide in the design is 0.025em. */
  letter-spacing: 0.025em;
  text-transform: uppercase;
  text-decoration: none;
  word-break: break-word;
}

.site-footer__phone {
  margin-top: 6px;
  text-transform: none;
}

.site-footer__email:hover,
.site-footer__email:focus-visible,
.site-footer__phone:hover,
.site-footer__phone:focus-visible {
  color: var(--clr-gold);
}

/* --- Column headings ----------------------------------------------------- */
.site-footer__heading {
  margin: 0 0 16px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.875rem;
  text-transform: uppercase;
  /* tracking-widest in the design is 0.1em, not 0.15em. */
  letter-spacing: 0.1em;
  color: var(--clr-teal);
}

/* --- Social -------------------------------------------------------------- */
.social {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 24px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.social__item {
  display: flex;
  align-items: center;
}

/* Vertical rule between icons, matching the design's separators. */
.social__item:not(:last-child)::after {
  content: "";
  width: 1px;
  height: 16px;
  margin-left: 24px;
  background: rgba(91, 196, 196, 0.4);
}

.social__link {
  display: inline-flex;
  align-items: center;
  color: var(--clr-white);
  text-decoration: none;
}

.social__link:hover,
.social__link:focus-visible {
  color: var(--clr-gold);
}

.social__icon {
  width: 20px;
  height: 20px;
  display: block;
}

.social__label {
  font-size: 0.8125rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

/* --- Footer nav ---------------------------------------------------------- */
.site-footer__menu {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-footer__menu a {
  color: rgba(255, 255, 255, 0.7);
  font-size: 0.875rem;
  font-weight: 500;
  text-decoration: none;
}

.site-footer__menu a:hover,
.site-footer__menu a:focus-visible,
.site-footer__menu .current-menu-item > a {
  color: var(--clr-teal);
}

/* --- Legal --------------------------------------------------------------- */
.site-footer__legal {
  margin-top: 40px;
  padding-top: 32px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  align-items: center;gap: 20px;
}

.site-footer__disclaimer {
  display: inline-block;
  margin: 0;
  padding: 12px 20px;
  border: 2px solid rgba(91, 196, 196, 0.4);
  background: rgba(91, 196, 196, 0.05);
  color: rgba(255, 255, 255, 0.6);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  line-height: 1.5;
}

.site-footer__copyright {
  margin: 0px 0 0;
  color: rgba(255, 255, 255, 0.5);
  font-size: 0.8125rem;
}
.site-footer__copyright a {color: rgba(255, 255, 255, 0.7);} 
.site-footer__copyright a:hover {color: var(--clr-teal);}

@media screen and (max-width: 1279px) {
    .site-footer__legal {justify-content: center;text-align: center;}
}

/* ===========================================================================
   FLEXIBLE-CONTENT SECTION BASE

   Consumes the CSS custom properties set by section-open.php, so background,
   overlay, text colour and spacing are handled once for every layout.
   =========================================================================== */
.section {
  position: relative;
  padding-block: var(--section-space);
  /*
   * The header is position:fixed, so an anchor jump would otherwise park the
   * target's first 64px underneath it. Offsetting by the same token the header
   * sizes itself with keeps the two in step if that value ever changes.
   */
  scroll-margin-top: var(--header-h);
}

.section.spacing-none {
  padding-block: 0;
}

/* Flat 80px - the design's py-20 with no desktop step-up, used by the
   donate band. */
.section.spacing-small {
  padding-block: 80px;
}

.section.spacing-large {
  padding-block: clamp(80px, 10vw, 160px);
}

.section.has-bg-color {
  background-color: var(--sec-bg);
}

.section.has-bg-image {
  background-image: var(--sec-bg-image);
  background-size: cover;
  background-position: center;
}

.section.has-text-color {
  color: var(--sec-text);
}

.section.has-overlay::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--sec-overlay);
  z-index: 0;
  pointer-events: none;
}

/*
 * Superseded by the :not(.section__bg-video) version in the RESTORED BLOCKS
 * section at the foot of this file. Left in place without the video would
 * re-break background video: this selector also matches the <video> and
 * outranks .section__bg-video, stacking it above the content.
 */

.section__bg-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}

.section.align-center {
  text-align: center;
}

.section.align-right {
  text-align: right;
}

/* Larger button variant used by hero-scale calls to action. */
.btn--lg {
  padding: 16px 32px;
  font-size: 0.875rem;
}

.btn__outline-light,
.btn__outline-light:visited {
  background: transparent;
  color: var(--clr-gold);
  border-color: var(--clr-gold);
}

.btn__outline-light:hover,
.btn__outline-light:focus-visible {
  background: var(--clr-gold);
  color: var(--clr-navy);
}

/* ---------------------------------------------------------------------------
   Scroll reveal

   Mirrors the design's in-view animation. Elements start hidden and animate
   once when they enter the viewport; assets/js/reveal.js adds .is-visible.
   With JS unavailable the .no-js fallback keeps everything visible.
   --------------------------------------------------------------------------- */
/*
 * Hidden ONLY when JavaScript is available to reveal it again. A tiny inline
 * script in wp_head sets .js-reveal on <html> before first paint, so there is
 * no flash, and with JS disabled or broken the content stays visible instead
 * of being permanently invisible.
 */
.js-reveal .reveal {
  opacity: 0;
}

/*
 * opacity:1 is declared OUTRIGHT and not left to the animation's `forwards`
 * fill. Relying on the animation meant that anywhere the animation did not
 * run - reduced-motion, an animation suppressed by the OS, a cancelled
 * animation - the element stayed at opacity 0 forever. That shipped: on a
 * phone with Reduce Motion enabled EVERY revealed element on the site was
 * permanently invisible while backgrounds and chrome painted normally.
 * Same specificity as `.js-reveal .reveal` (0,2,0) and later in the file, so
 * this wins.
 */
.reveal.is-visible {
  opacity: 1;
  animation: slideUp 0.8s ease-out both;
  animation-delay: var(--reveal-delay, 0s);
}

.no-js .reveal,
.reveal.reveal--static {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  /*
   * `.js-reveal .reveal`, not a bare `.reveal`: the bare selector is (0,1,0)
   * and LOST to the (0,2,0) `.js-reveal .reveal { opacity: 0 }` above, so this
   * reduced-motion fallback silently did nothing and reduced-motion visitors
   * saw a site with no content in it.
   */
  .js-reveal .reveal {
    opacity: 1;
  }

  .reveal.is-visible {
    animation: none;
  }
}

/* ===========================================================================
   LAYOUT: HERO (SPLIT)
   =========================================================================== */
@keyframes heroZoomOut {
  from {
    transform: scale(1.15);
  }
  to {
    transform: scale(1);
  }
}

@keyframes heroBounce {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(8px);
  }
}

.section--hero-split {
  display: flex;
  min-height: 100vh;
  min-height: 100svh;
  padding-block: 0;
  overflow: hidden;
  background-color: var(--clr-navy);
  color: var(--clr-white);
}

/*
 * The background image is moved onto its own layer so it can be constrained
 * to the text column at desktop, matching the design, instead of stretching
 * behind the side image where it would be cropped differently.
 */
.section--hero-split.has-bg-image {
  background-image: none;
}

.section--hero-split.has-bg-image::after {
  content: "";
  position: absolute;
  inset-block: 0;
  left: 0;
  width: 100%;
  background-image: var(--sec-bg-image);
  background-size: cover;
  background-position: center;
  z-index: 0;
}

.hero__accent-bar {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 6px;
  background: var(--clr-teal);
  z-index: 3;
}

.hero__content {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 100%;
  min-height: 100vh;
  min-height: 100svh;
  /*
   * Uses the project's global container padding (100 / 50 / 20), not the
   * design's own smaller inset. The headline below is sized in cqw against
   * this column, so it shrinks to fit automatically rather than clipping.
   */
  padding-inline: var(--container-padding);
  padding-block: 96px 64px;
  /*
   * Makes the headline below scale against THIS column rather than the
   * viewport. Sized in vw it overflowed, because the column is 40% of the
   * viewport minus its padding - not a linear fraction of it.
   */
  container-type: inline-size;
}

.hero__name {
  margin: 0 0 4px;
  font-family: var(--font-display);
  font-weight: 600;
  /* Viewport-based below the desktop breakpoint; container units resume at
     992px where the column really becomes a 40% slice. */
  font-size: clamp(1.5rem, 6vw, 4.5rem);
  font-size: clamp(2rem, 4vw, 4.5rem);
  line-height: 1;
  text-transform: uppercase;
  color: var(--clr-white);
  white-space: nowrap;
}

.hero__headline {
  margin: 0 0 40px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(4rem, 6.5vw, 10rem);
  line-height: 0.9;
  letter-spacing: var(--heading-tracking);
  text-transform: uppercase;
  color: var(--clr-white);
}

.hero__buttons {
  flex-direction: column;
  align-items: flex-start;
}

.hero__scroll {
  position: absolute;
  bottom: 32px;
  /*
   * Centred with auto margins, NOT left:50% + translateX(-50%). The bounce
   * animation below animates `transform`, which replaced the centring
   * translate outright and shifted this 29px to the right.
   */
  left: 0;
  right: 0;
  width: fit-content;
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  z-index: 3;
  animation: heroBounce 2s ease-in-out infinite;
}

/*
 * With a Scroll Link Target set, .hero__scroll renders as an <a>. It keeps the
 * identical box (the flex rules above apply to either element); these only
 * strip the default link treatment and add interaction states.
 */
.hero__scroll--link {
  text-decoration: none;
  color: inherit;
  cursor: pointer;
}

.hero__scroll--link:hover .hero__scroll-line,
.hero__scroll--link:focus-visible .hero__scroll-line {
  background: var(--clr-teal);
}

.hero__scroll--link:hover .hero__scroll-label,
.hero__scroll--link:focus-visible .hero__scroll-label {
  color: var(--clr-teal);
}

.hero__scroll--link:focus-visible {
  outline: 2px solid var(--clr-teal);
  outline-offset: 6px;
  border-radius: 2px;
}

.hero__scroll-line {
  width: 1px;
  height: 40px;
  background: rgba(91, 196, 196, 0.6);
  transition: background-color var(--transition);
}

.hero__scroll-label {
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  color: rgba(91, 196, 196, 0.6);
}
.hero__media {
	position: relative;
	z-index: 1;
}
@media (min-width: 640px) {
  .hero__buttons {
    flex-direction: row;
    align-items: center;
  }
}

@media (min-width: 992px) {
  .section--hero-split.has-bg-image::after {
    width: 40%;
  }

  /* Container sizing, now that the column is a real 40% slice. */
  .hero__name {
    font-size: clamp(1.75rem, 11cqw, 4.5rem);
  }
  .hero__content {
    width: 40%;
    flex: 0 0 40%;
  }
.hero__content {
  padding-right: 30px;
}
  .hero__media {
    display: block;
    position: relative;
    width: 60%;
    flex: 0 0 60%;
    overflow: hidden;
  }

  /*
   * Absolutely positioned on purpose. The collage is portrait (2371x2560), so
   * as a normal flex child its intrinsic aspect ratio dictated the row height
   * and pushed the hero 235px past the viewport. Taking it out of flow lets
   * the text column's min-height govern, and object-fit crops the photo.
   */
  .hero__media-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    animation: heroZoomOut 1.6s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
  }

  /* Keeps the fixed header legible over light areas of the photograph. */
  .hero__media-scrim {
    position: absolute;
    inset-inline: 0;
    top: 0;
    height: 128px;
    background: linear-gradient(to bottom, rgba(32, 32, 80, 0.7), transparent);
    pointer-events: none;
  }
}
@media (max-width: 1650px) {
  .hero__headline {
    font-size: clamp(4rem, 6.1vw, 10rem);
  }
}
@media (max-width: 1439px) {
  .hero__headline {
    font-size: clamp(4rem, 5.6vw, 10rem);
  }
}
@media (max-width: 1279px) {
  .hero__headline {
    font-size: clamp(2.8rem, 4vw, 10rem);
  }
}
@media (max-width: 1199px) {
  /* Tighten the primary nav so the menu and the Donate button stop competing
     for room before the mobile breakpoint takes over at 991px. */
  .site-nav__menu {
    gap: 20px;
  }
}
@media (max-width: 991px) {
  .hero__headline {
    font-size: clamp(4rem, 6.5vw, 10rem);
  }

  /*
   * Below the desktop breakpoint the hero sizes to its own content instead of
   * filling the viewport. Both rules are needed: the section and the text
   * column each carry their own min-height: 100svh, so unsetting only the
   * section would leave the inner column still forcing a full-height hero.
   */
  .section--hero-split,
  .hero__content {
    min-height: 0;
  }
  .section--hero-split {flex-direction: column;}
  .hero__headline br {display: none;}

  /*
   * Room for the scroll indicator. It is position:absolute, so it takes no
   * space in flow - at full-viewport height there was slack beneath the
   * buttons to absorb it, but against an auto-height hero it landed on top of
   * them (measured 31px of overlap at 480px).
   *
   * 128px = its own 66px height + the 32px it sits off the bottom + ~30px of
   * clearance, so the buttons stop clear of it rather than just touching.
   */
  .hero__content {
    padding-bottom: 50px;
  }

  /*
   * The signup heading's hard line break ("Stay / Involved") is there to shape
   * the two-column desktop layout. Once the columns go full width it just
   * wastes a line, so the break is dropped and the heading sets naturally.
   * The newline that follows the <br> in the source collapses to a space, so
   * the words stay separated.
   */
  .signup__heading br {
    display: none;
  }

}
@media (prefers-reduced-motion: reduce) {
  .hero__scroll {
    animation: none;
  }

  .hero__media-img {
    animation: none;
  }
}

/* ===========================================================================
   LAYOUT: CONTENT + MEDIA

   Shared by the About pattern (cropped portrait + accents) and the district
   pattern (uncropped image + tag pills over a tinted background image).
   =========================================================================== */
.content-media__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 48px;
  align-items: start;
}

.content-media__body > *:first-child {
  margin-top: 0;
}

.content-media__body > *:last-child {
  margin-bottom: 0;
}

.content-media__body p + p {
  margin-top: 20px;
}

.content-media__buttons {
  margin-top: 32px;
}

/* --- Tag pills ----------------------------------------------------------- */
.content-media__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin: 32px 0 0;
  padding: 0;
  list-style: none;
}

.content-media__tag {
  background: var(--clr-navy);
  color: var(--clr-white);
  font-weight: 700;
  font-size: 0.75rem;
  text-transform: uppercase;
  /* tracking-widest in the design is 0.1em. */
  letter-spacing: 0.1em;
  padding: 8px 12px;
}

/* --- Media --------------------------------------------------------------- */
.content-media__frame {
  position: relative;
}

.content-media__img {
  position: relative;
  z-index: 1;
  display: block;
  width: 100%;
}

.content-media__frame--portrait .content-media__img,
.content-media__frame--square .content-media__img,
.content-media__frame--landscape .content-media__img {
  height: 100%;
  object-fit: cover;
  object-position: top;
}

.content-media__frame--portrait {
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: var(--clr-off-white);
}

.content-media__frame--square {
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background: var(--clr-off-white);
}

.content-media__frame--landscape {
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--clr-off-white);
}

.content-media__frame--natural .content-media__img {
  height: auto;
  object-fit: contain;
}

/* Slow settle from a slight zoom, matching the design's in-view transform. */
.content-media__media .content-media__img {
  transform: scale(1.12);
  transition: transform 1.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

.content-media__media.is-visible .content-media__img {
  transform: scale(1);
}

.content-media__frame--natural .content-media__img,
.content-media__frame--natural.is-visible .content-media__img {
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .content-media__media .content-media__img {
    transform: none;
    transition: none;
  }
}

/* --- Decorative accents -------------------------------------------------- */
.content-media__accent {
  position: absolute;
  z-index: 0;
  display: block;
}

.content-media__accent--block {
  right: -16px;
  bottom: -16px;
  width: 96px;
  height: 96px;
  background: var(--clr-teal);
}

.content-media__accent--outline {
  top: -16px;
  left: -16px;
  width: 64px;
  height: 64px;
  border: 2px solid var(--clr-gold);
}

/* The accents sit outside the frame, so it must not clip them. */
.content-media__frame.has-accents {
  overflow: visible;
}

.content-media__frame--portrait.has-accents .content-media__img,
.content-media__frame--square.has-accents .content-media__img,
.content-media__frame--landscape.has-accents .content-media__img {
  /* Restore the crop that overflow:visible would otherwise lose. */
  position: absolute;
  inset: 0;
  height: 100%;
}

/* --- Two-column at desktop ---------------------------------------------- */
@media (min-width: 992px) {
  .content-media__grid {
    grid-template-columns: 1fr 1fr;
    gap: 80px;
  }

  /* Reorder rather than reordering the markup, so the text stays first in
     the DOM for screen readers and mobile stacking. */
  .content-media__grid--image-left .content-media__text {
    order: 2;
  }

  .content-media__grid--image-left .content-media__media {
    order: 1;
  }
}

/* ===========================================================================
   LAYOUT: CONTENT + EMBED PANEL
   =========================================================================== */
.content-embed__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 48px;
  align-items: center;
}

.content-embed__bar {
  display: block;
  width: 48px;
  height: 4px;
  margin-bottom: 24px;
  background: var(--clr-gold);
}

.content-embed__heading {
  line-height: 1.1;
  color: inherit;
}

/* --- Word-by-word reveal ------------------------------------------------- */
.word-reveal span {
  display: inline-block;
}

.js-reveal .word-reveal span {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity 0.5s ease, transform 0.5s ease;
  transition-delay: var(--word-delay, 0s);
}

.word-reveal.is-visible span {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .js-reveal .word-reveal span {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* --- Panel --------------------------------------------------------------- */
.content-embed__panel {
  width: 100%;
}

.content-embed__embed {
  max-width: 28rem;
}

.content-embed__grid--panel-right .content-embed__embed,
.content-embed__grid--panel-right .content-embed__placeholder {
  margin-inline-start: auto;
}

/* Responsive iframes from pasted provider embeds. */
.content-embed__embed iframe,
.content-embed__embed img,
.content-embed__embed video {
  max-width: 100%;
}

/*
 * Editor-only notice shown while an embed is still outstanding. Deliberately
 * plain - it is scaffolding, not design.
 */
.content-embed__placeholder {
  max-width: 28rem;
  padding: 32px;
  border: 2px dashed rgba(91, 196, 196, 0.6);
  background: rgba(91, 196, 196, 0.06);
}

.content-embed__placeholder-title {
  margin: 0 0 8px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.125rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--clr-teal);
}

.content-embed__placeholder-note {
  margin: 0;
  font-size: 0.8125rem;
  line-height: 1.6;
  color: inherit;
  opacity: 0.75;
}

@media (min-width: 992px) {
  .content-embed__grid {
    grid-template-columns: 1fr 1fr;
  }

  .content-embed__grid--panel-left .content-embed__text {
    order: 2;
  }

  .content-embed__grid--panel-left .content-embed__panel {
    order: 1;
  }

  .content-embed__grid--panel-left .content-embed__embed,
  .content-embed__grid--panel-left .content-embed__placeholder {
    margin-inline-start: 0;
    margin-inline-end: auto;
  }
}

/* ===========================================================================
   SHARED SECTION REFINEMENTS
   =========================================================================== */

/*
 * The eyebrow stays TEAL by default, which is what the design uses almost
 * everywhere - including on sections whose body text is navy or white.
 *
 * It only turns navy on the teal-tinted bands (the district and crossroads
 * sections), where teal-on-teal would be invisible. That is opted into per
 * section with the eyebrow-navy Custom CSS Class rather than derived from the
 * section's text colour: an earlier "inherit the text colour" rule looked
 * right on the district band but silently turned the Stay Involved and page
 * hero eyebrows navy/white when the design wants them teal.
 */
.section.eyebrow-navy .sub_sec__heading {
  color: var(--clr-navy);
}

/*
 * Opt-in larger section heading, applied through the section's Custom CSS
 * Class field. The district heading is text-7xl (72px) in the design where
 * every other section is text-6xl (60px), so this avoids adding a whole
 * field for a single case.
 */
.section.heading-xl .sec__heading {
  /* 40px small screens up to the design's text-7xl (72px). */
  font-size: clamp(2.5rem, 6vw, 4.5rem);
}

/* ===========================================================================
   LAYOUT: MEDIA FEATURE
   =========================================================================== */
.media-feature {
  margin-inline: auto;
}

.media-feature--narrow {
  max-width: 64rem;
}

.media-feature--default {
  max-width: 72rem;
}

.media-feature--wide {
  max-width: none;
}

.media-feature__head {
  margin-bottom: 40px;
}

.media-feature .sub_sec__heading {
  margin-bottom: 12px;
}

.media-feature__heading {
  margin-bottom: 0;
}

.media-feature__frame {
  position: relative;
  overflow: hidden;
}

.media-feature__frame.is-framed {
  border: 4px solid var(--clr-teal);
}

/* Pasted provider embeds size themselves to the frame. */
.media-feature__embed img,
.media-feature__embed video,
.media-feature__img,
.media-feature__video {
  display: block;
  width: 100%;
  height: auto;
  max-width: 100%;
}

/*
 * Provider iframes carry hardcoded width/height attributes, and height:auto
 * does NOT override them - the Flickr player rendered 417x572 (ratio 0.73)
 * instead of 16:9, i.e. squashed into a tall box. Giving the wrapper the
 * aspect ratio and letting the iframe fill it absolutely fixes that at every
 * width. Scoped with :has(iframe) so a plain image embed is unaffected.
 */
.media-feature__embed:has(iframe),
.content-embed__embed:has(iframe) {
  position: relative;
  aspect-ratio: var(--embed-ratio, 16 / 9);
}

.media-feature__embed:has(iframe) iframe,
.content-embed__embed:has(iframe) iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  border: 0;
}

.media-feature__embed a {
  display: block;
}

/* ===========================================================================
   LAYOUT: SIGNUP / FORM
   =========================================================================== */
.section--signup-form {
  border-top: 4px solid var(--clr-teal);
}

.signup__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 48px;
}

.signup__text {
  /* Lets the oversized heading below scale against this column rather than
     the viewport - the same overflow trap the hero hit. */
  container-type: inline-size;
}

.signup__heading {
  margin: 0 0 24px;
  font-family: var(--font-display);
  font-weight: 800;
  /*
   * Viewport-based on purpose, matching the design. Unlike the hero - whose
   * 40% column made vw sizing overflow - this column is generous relative to
   * its longest word, and cqw under-sized it badly (113px vs the intended
   * 160px) because the container caps at 1440 so the column stops growing.
   */
  /*
   * Capped at 8.75rem (140px) rather than the design's 10rem. At 10rem the
   * word "Involved" measures 634px inside a 580px column and overflows - the
   * design has the same problem and hides it with overflow:hidden, which
   * clips the word. 140px is the largest size that fits with slack for a
   * different font-loading state.
   */
  /* Floor lowered from 4rem: 64px was oversized on a 375px screen. Now 40px
     on mobile, unchanged at the top of the range. */
  font-size: clamp(2.5rem, 8.5vw, 8.75rem);
  line-height: 0.9;
  letter-spacing: var(--heading-tracking);
  text-transform: uppercase;
  color: inherit;
}

.signup__description {
  margin: 0 0 32px;
  /* The design uses navy/70 here, slightly lighter than body copy's /80.
     .body__text already applies /80, so this trims it the rest of the way. */
  opacity: 0.875;
}

.signup__benefits {
  display: flex;
  flex-direction: column;
  gap: 20px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.benefit {
  display: flex;
  align-items: center;
  gap: 16px;
}

.benefit__icon-wrap {
  flex: 0 0 auto;
  display: inline-flex;
  color: var(--clr-teal);
}

.benefit__icon {
  display: block;
  width: 40px;
  height: 40px;
}

.benefit__label {
  font-family: var(--font-display);
  font-weight: 700;
  /* Was a fixed 1.25rem. 16px mobile to the design's text-xl (20px). */
  font-size: clamp(1rem, 2.2vw, 1.25rem);
  text-transform: uppercase;
  /* tracking-wide in the design is 0.025em. */
  letter-spacing: 0.025em;
}

.signup__panel {
  background: var(--clr-white);
  border: 2px solid var(--clr-teal);
  padding: 32px;
  color: var(--clr-navy);
}

/* ---------------------------------------------------------------------------
   Gravity Forms, styled to the design

   The design's inputs use a 40%-opacity teal border that goes solid on
   focus, and the submit is TEAL with navy text (not gold).
   --------------------------------------------------------------------------- */
.signup__panel .gform_wrapper form,
.signup__panel .gform_wrapper .gform_fields {
  margin: 0;
}

.signup__panel .gform_wrapper .gform_fields {
  row-gap: 16px;
  column-gap: 16px;
}

.signup__panel .gform_wrapper .gfield_label {
  /* The design shows placeholders only. */
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.signup__panel .gform_wrapper input[type="text"],
.signup__panel .gform_wrapper input[type="email"],
.signup__panel .gform_wrapper input[type="tel"],
.signup__panel .gform_wrapper input[type="number"],
.signup__panel .gform_wrapper textarea,
.signup__panel .gform_wrapper select {
  width: 100%;
  border: 2px solid rgba(91, 196, 196, 0.4);
  background: var(--clr-white);
  padding: 12px 16px;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.875rem;
  color: var(--clr-navy);
  transition: border-color var(--transition);
}

.signup__panel .gform_wrapper ::placeholder {
  color: #9ca3af;
  opacity: 1;
}

.signup__panel .gform_wrapper input:focus,
.signup__panel .gform_wrapper textarea:focus,
.signup__panel .gform_wrapper select:focus {
  outline: none;
  border-color: var(--clr-teal);
}

/* Consent checkbox: small control beside fine print. */
.signup__panel .gform_wrapper .ib4a-consent .gfield_checkbox {
  margin: 0;
}

.signup__panel .gform_wrapper .ib4a-consent .gchoice {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}

.signup__panel .gform_wrapper .ib4a-consent input[type="checkbox"] {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  margin-top: 3px;
  accent-color: var(--clr-teal);
  cursor: pointer;
  /* Forced: Gravity Forms' Orbital theme sets its own control radius through
     the --gf-ctrl-radius cascade, which beats this selector on origin. */
  border-radius: 3px !important;
}

.signup__panel .gform_wrapper .ib4a-consent label {
  font-size: 0.75rem;
  line-height: 1.625;
  font-weight: 400;
  color: color-mix(in srgb, var(--clr-navy) 60%, transparent);
  cursor: pointer;
  /* The row is a flex pair with its own gap, so Gravity Forms' default label
     indent would double the space beside the checkbox. */
  margin-left: 0;
}

.signup__panel .gform_wrapper .gform_footer {
  margin: 24px 0 0;
  padding: 0;
}

/*
 * Gravity Forms ships its "Orbital" theme framework, which injects its own
 * design tokens (a #204ce5 blue primary) and whose button rules out-rank a
 * plain class selector - the submit rendered blue, weight 500, 99px wide.
 * Two things are needed: re-point GF's tokens at the brand palette so its own
 * components follow it, and match the framework's specificity on the button.
 */
.signup__panel .gform_wrapper.gform-theme,
.signup__panel .gform_wrapper.gform-theme[data-form-theme] {
  --gf-color-primary: #5bc4c4;
  --gf-color-primary-rgb: 91, 196, 196;
  --gf-color-primary-contrast: #202050;
  --gf-color-primary-contrast-rgb: 32, 32, 80;
  --gf-color-primary-darker: #202050;
  --gf-color-primary-lighter: #5bc4c4;
  --gf-color-in-ctrl-primary: #5bc4c4;
  --gf-color-in-ctrl-primary-contrast: #202050;
  --gf-radius: 0;
  --gf-ctrl-btn-bg-color-primary: #5bc4c4;
  --gf-ctrl-btn-color-primary: #202050;
  --gf-ctrl-btn-bg-color-hover-primary: #202050;
  --gf-ctrl-btn-color-hover-primary: #ffffff;
  --gf-ctrl-btn-border-color-primary: #5bc4c4;
  --gf-ctrl-btn-font-size: 14px;
}

.signup__panel .gform_wrapper .gform_footer {
  display: block;
  width: 100%;
}

.signup__panel .gform_wrapper.gform-theme .gform_footer .gform_button,
.signup__panel .gform_wrapper .gform_footer input[type="submit"],
.signup__panel .gform_wrapper .gform_footer button[type="submit"] {
  background: var(--clr-teal);
  color: var(--clr-navy);
  border: 0;
  font-family: var(--font-body);
  font-size: 0.875rem;
  line-height: 1.2;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  cursor: pointer;
  transition: background-color var(--transition), color var(--transition);
  /*
   * These three are forced. The Orbital framework resolves width, padding and
   * font-weight through its own --gf-ctrl-btn-* cascade, which beat a
   * higher-specificity selector (0,5,0 vs 0,4,0) - the button rendered 99px
   * wide at weight 500 with no padding. Same justified override as the
   * border-radius reset: narrowly scoped to this plugin's control.
   */
  width: 100% !important;
  padding: 16px 24px !important;
  font-weight: 900 !important;
  /*
   * Uppercase and tracking need forcing for the same reason: declared without
   * !important above, they computed as none/normal because Orbital's own
   * --gf-ctrl-btn-* cascade won.
   */
  text-transform: uppercase !important;
  letter-spacing: 0.1em !important;
}

.signup__panel .gform_wrapper.gform-theme .gform_footer .gform_button:hover,
.signup__panel .gform_wrapper .gform_footer input[type="submit"]:hover,
.signup__panel .gform_wrapper.gform-theme .gform_footer .gform_button:focus-visible,
.signup__panel .gform_wrapper .gform_footer input[type="submit"]:focus-visible {
  background: var(--clr-navy);
  color: var(--clr-white);
}

/*
 * The '"*" indicates required fields' legend Gravity Forms prints above the
 * fields. Hidden by request - the design has no such line.
 *
 * Only the sentence goes: the asterisk itself stays (styled teal just below)
 * and Gravity Forms still sets aria-required on the inputs, so required
 * fields are still marked visually and still announced as required.
 */
.signup__panel .gform_wrapper .gform_required_legend {
  display: none;
}

/* Validation and confirmation messages in the brand palette. */
.signup__panel .gform_wrapper .gfield_required {
  color: var(--clr-teal);
}

.signup__panel .gform_wrapper .gfield_validation_message,
.signup__panel .gform_wrapper .validation_message {
  background: none;
  border: 0;
  padding: 4px 0 0;
  font-size: 0.75rem;
  color: #b3261e;
}

.signup__panel .gform_confirmation_message {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.5rem;
  text-transform: uppercase;
  color: var(--clr-navy);
}

@media (min-width: 992px) {
  .signup__grid {
    grid-template-columns: 1fr 1fr;
    gap: 80px;
  }

  .signup__grid--form-left .signup__text {
    order: 2;
  }

  .signup__grid--form-left .signup__form {
    order: 1;
  }
}

/* ===========================================================================
   LAYOUT: PAGE HERO (inner pages)
   =========================================================================== */
.section--page-hero {
  position: relative;
  overflow: hidden;
  /*
   * The design's pt-32 (128px) exists to clear the fixed header. Inner pages
   * already get 64px of clearance on #primary, so 64px here sums to the
   * design's 128px without double-counting.
   */
  padding-block: 64px 80px;
}

/* Oversized decorative word bleeding off the right edge. */
.page-hero__watermark {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  z-index: 0;
  font-family: var(--font-display);
  font-weight: 900;
  font-size: 25vw;
  line-height: 1;
  text-transform: uppercase;
  white-space: nowrap;
  color: rgba(255, 255, 255, 0.1);
  pointer-events: none;
  user-select: none;
}

.page-hero__inner {
  position: relative;
  z-index: 1;
}

.page-hero__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 48px;
  align-items: center;
}

.page-hero__text {
  /* Sizes the heading against this column, not the viewport - the same
     overflow trap the home hero hit. */
  container-type: inline-size;
}

.page-hero__heading {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 800;
  /*
   * Small screens are sized off the VIEWPORT, capped at the design's
   * text-6xl (60px). Container units are wrong here: on mobile the column is
   * nearly full width, so 21cqw resolved to 89px - far past the design - while
   * on desktop the same value is correct because the column is half as wide.
   * The desktop override below restores container sizing.
   */
  font-size: clamp(2.5rem, 10vw, 3.75rem);
  line-height: 1;
  letter-spacing: var(--heading-tracking);
  text-transform: uppercase;
  color: inherit;
}

/*
 * The page-hero headings carry hard line breaks ("Endorsed / by the / People")
 * that shape the heading against the desktop two-column hero. On a narrow
 * screen those forced breaks just stack the words into a tall thin column, so
 * the heading is allowed to wrap naturally instead. The newline following each
 * <br> in the source collapses to a space, so words stay separated.
 *
 * Placed here rather than in the shared max-width: 991px block near the top of
 * the file: that block precedes .page-hero__heading, and a media query adds no
 * specificity, so the later rule above would win on source order.
 */
@media (max-width: 991px) {
  .page-hero__heading br {
    display: none;
  }
  .section--page-hero:has(.page-hero__media--bg) {
    	flex-direction: column-reverse;
    	display: flex;
    }
}

.page-hero__bar {
  display: block;
  width: 96px;
  height: 4px;
  margin-top: 24px;
  background: var(--clr-gold);
}

@media (min-width: 992px) {
  .page-hero__grid {
    grid-template-columns: 1fr 1fr;
  }

  /* Two-column from here, so container sizing is meaningful again and the
     heading can scale up to the design's md:text-9xl (128px). */
  .page-hero__heading {
    font-size: clamp(3.75rem, 21cqw, 8rem);
  }

  .page-hero__media {
    display: flex;
    justify-content: flex-end;
  }

  .page-hero__img {
    max-height: 520px;
    width: auto;
    object-fit: contain;
  }
}

/* ===========================================================================
   BUTTON: TEAL OUTLINE
   Teal border with navy text, filling teal on hover (the gallery CTA).
   =========================================================================== */
.btn__outline-teal,
.btn__outline-teal:visited {
  background: transparent;
  color: var(--clr-navy);
  border-color: var(--clr-teal);
}

.btn__outline-teal:hover,
.btn__outline-teal:focus-visible {
  background: var(--clr-teal);
  color: var(--clr-white);
  border-color: var(--clr-teal);
}

/* ===========================================================================
   LAYOUT: LETTER / LONG-FORM CONTENT
   =========================================================================== */
.letter__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 48px;
}

.letter__aside-head {
  margin-bottom: 32px;
  padding-left: 24px;
  border-left: 4px solid var(--clr-teal);
}

.letter__aside-heading {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 800;
  /* 24px small screens up to the design's md:text-4xl (36px). */
  font-size: clamp(1.5rem, 2.5vw, 2.25rem);
  line-height: 1.1;
  letter-spacing: var(--heading-tracking);
  text-transform: uppercase;
  color: inherit;
}

.letter__quote {
  margin: 0;
  padding: 24px;
  border: 2px solid var(--clr-gold);
  /* Sizes the quote against the box it lives in, not the viewport. */
  container-type: inline-size;
}

.letter__quote-text {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 900;
  /*
   * Viewport-based while the layout is a single column, capped at 28px on a
   * phone. Container-based sizing takes over at 992px (see below), where the
   * aside becomes a narrow 4:8 track and vw sizing overflowed the box.
   * Neither unit works alone: the box is 272px on mobile and only 349px at
   * 1920, so cqw cannot express the design's 28px -> 60px jump.
   */
  font-size: clamp(1.75rem, 4.5vw, 3.75rem);
  line-height: 1;
  /* No tracking on the pull quote. Stated explicitly rather than dropping the
     declaration, so it cannot pick up --heading-tracking by inheritance. */
  letter-spacing: normal;
  text-transform: uppercase;
  color: inherit;
  /* Last-resort guard: a single long word can never breach the border. */
  overflow-wrap: break-word;
}

/*
 * The letter body runs at 20px in the design, larger than standard body copy -
 * but it was a fixed 1.25rem, so it never reduced on small screens. Now 16px
 * on mobile rising to the design's 20px.
 */
.letter__text {
  font-size: clamp(1rem, 2.2vw, 1.25rem);
  line-height: 1.625;
  color: color-mix(in srgb, currentColor 80%, transparent);
}

.letter__text > *:first-child {
  margin-top: 0;
}

.letter__text p + p {
  margin-top: 24px;
}

.letter__signoff {
  margin-top: 24px;
  padding-top: 24px;
  border-top: 1px solid rgba(91, 196, 196, 0.3);
}

.letter__signoff-label {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1rem, 1.4vw, 1.125rem);
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

.letter__signoff-name {
  margin: 8px 0 0;
  font-family: var(--font-display);
  font-weight: 900;
  /* Was a fixed 2.25rem that never reduced. 28px mobile to 36px desktop. */
  font-size: clamp(1.75rem, 3vw, 2.25rem);
  line-height: 1;
  text-transform: uppercase;
}

@media (min-width: 992px) {
  /*
   * Two tracks in a 4:8 ratio rather than a 12-column grid. Same proportion
   * as the design's col-span-4 / col-span-8, but a 12-column grid with a
   * uniform 48px gap spends ELEVEN gaps (528px) inside the container - at
   * 1024px that starved the aside to ~242px and the pull quote broke out of
   * its box. One gap instead keeps the columns usable.
   */
  .letter__grid {
    grid-template-columns: 4fr 8fr;
    gap: 48px;
  }

  /* Now that the aside is a narrow track, the quote tracks its own box so it
     can never breach the border at the tighter desktop widths. */
  .letter__quote-text {
    font-size: clamp(1.5rem, 20cqw, 3.75rem);
  }

  /* Holds the pull quote in view while the letter scrolls past. */
  .letter__aside-inner.is-sticky {
    position: sticky;
    top: 96px;
  }
}

/* ===========================================================================
   LAYOUT: ROADMAP / STOPS

   One markup tree for both breakpoints. Below 768px the stops are a plain
   stacked list; from 768px up the spine, dots and connectors appear as
   decorative pseudo-elements and the cards alternate sides. Reading order is
   identical either way.
   =========================================================================== */
.roadmap__intro {
  max-width: 42rem;
  margin-bottom: 64px;
}

.roadmap {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 32px;
}

.roadmap__stops {
  width: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.roadmap__stop {
  position: relative;
}

.roadmap__card {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: flex-start;
  gap: 16px;
  padding: 24px;
  background: var(--clr-navy);
  color: var(--clr-white);
}

/*
 * Mobile: centre the icon against the copy.
 *
 * The card pins its 40px icon to the top, which reads fine on desktop where
 * the stops alternate either side of the road. Stacked on mobile the copy runs
 * 2-4 lines, leaving the icon's centre up to 32px above the text's centre and
 * looking detached from it.
 *
 * Deliberately placed HERE rather than in the shared max-width: 991px block
 * further up the file: that block precedes the .roadmap__card rule above, and
 * since a media query adds no specificity of its own, the later base rule
 * would win on source order and the override would silently do nothing.
 */
@media (max-width: 991px) {
  .roadmap__card {
    align-items: center;
  }
}

.roadmap__icon {
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  display: block;
}

.roadmap__text {
  margin: 0;
  /* Was a fixed 1.25rem. 16px mobile to the design's 20px. */
  font-size: clamp(1rem, 2.2vw, 1.25rem);
  line-height: 1.625;
  font-weight: 500;
}

/*
 * The design sets these two at text-[20px] like the roadmap cards, not the
 * standard 16px body size, so they override .body__text - reducing on mobile
 * the same way.
 */
.roadmap__intro,
.roadmap__closing {
  font-size: clamp(1rem, 2.2vw, 1.25rem);
}

.roadmap__start {
  display: none;
}

.roadmap__end {
  position: relative;
  z-index: 1;
  padding: 16px 32px;
  background: var(--clr-gold);
  text-align: center;
}

.roadmap__end-label {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 900;
  /* 28px small screens up to the design's md:text-6xl (60px). */
  font-size: clamp(1.75rem, 4.5vw, 3.75rem);
  line-height: 1;
  /* No tracking. Stated explicitly rather than dropping the declaration, so
     it cannot pick up --heading-tracking by inheritance. */
  letter-spacing: normal;
  text-transform: uppercase;
  color: var(--clr-navy);
}

.roadmap__closing {
  max-width: 48rem;
  margin: 64px auto 0;
  text-align: center;
}

/*
 * The alternating road layout starts at the project's desktop breakpoint
 * (992px), not the design's own md: (768px). Below 992 everything else is a
 * single column, and a two-sided road in that band would be inconsistent.
 */
@media (min-width: 992px) {
  .roadmap {
    gap: 60px;
  }

  /* The road spine. */
  /*
   * The single full-height rule was replaced by .roadmap__seg (see RESTORED
   * BLOCKS at the foot of this file), which draws the road as separate bars in
   * the gaps between cards, as the design does. Leaving this in would paint a
   * continuous navy line straight through every card row on top of them.
   */

  .roadmap__stops {
    gap: 60px;
  }

  .roadmap__stop {
    display: flex;
  }

  /* Odd stops sit left of the spine, even stops right - as in the design. */
  .roadmap__stop:nth-child(odd) {
    justify-content: flex-end;
    padding-right: 52%;
  }

  .roadmap__stop:nth-child(even) {
    justify-content: flex-start;
    padding-left: 52%;
  }

  /* Dot on the spine. */
  .roadmap__stop::before {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: 24px;
    height: 24px;
    margin: -12px 0 0 -12px;
    background: var(--clr-gold);
    border: 4px solid var(--clr-navy);
    box-sizing: border-box;
    z-index: 2;
  }

  /* Connector from the spine to the card. */
  .roadmap__stop::after {
    content: "";
    position: absolute;
    top: 50%;
    width: 48px;
    height: 2px;
    margin-top: -1px;
    background: var(--clr-navy);
    z-index: 1;
  }

  .roadmap__stop:nth-child(odd)::after {
    right: 50%;
  }

  .roadmap__stop:nth-child(even)::after {
    left: 50%;
  }

  .roadmap__card {
    max-width: 20rem;
    flex-direction: column;
    gap: 12px;
  }

  /* Start marker: gold square with a navy pip. */
  .roadmap__start {
    position: relative;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    background: var(--clr-gold);
    border: 4px solid var(--clr-navy);
    box-sizing: border-box;
  }

  .roadmap__start::after {
    content: "";
    width: 8px;
    height: 8px;
    background: var(--clr-navy);
  }
}

/* ===========================================================================
   LAYOUT: GALLERY / EMBED
   =========================================================================== */
.gallery__heading {
  margin-bottom: 48px;
}

/* Masonry via CSS columns, as in the design. */
.gallery__grid {
  columns: 2;
  column-gap: 12px;
}

.gallery-item {
  margin-bottom: 12px;
  overflow: hidden;
  display: block;
  break-inside: avoid;
}

.gallery__img,
.gallery-item img {
  display: block;
  width: 100%;
  object-fit: cover;
}

/* Greyscale settling into colour on hover, per the design. */
.gallery-item img {
  filter: grayscale(100%);
  transition: filter 0.45s ease, transform 0.45s ease;
}

.gallery-item:hover img,
.gallery-item:focus-within img {
  filter: grayscale(0%);
  transform: scale(1.04);
}

.gallery__embed iframe {
  width: 100%;
  border: 0;
}

.gallery__buttons {
  justify-content: center;
  margin-top: 40px;
}

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

  .gallery-item:hover img,
  .gallery-item:focus-within img {
    transform: none;
  }
}

@media (min-width: 768px) {
  .gallery__grid {
    columns: 3;
  }
}

@media (min-width: 992px) {
  .gallery__grid {
    columns: 4;
  }
}

/* ===========================================================================
   BUTTON: DARK
   Navy fill with white text, going gold on hover (the split-feature CTA).
   =========================================================================== */
.btn__dark,
.btn__dark:visited {
  background: var(--clr-navy);
  color: var(--clr-white);
}

.btn__dark:hover,
.btn__dark:focus-visible {
  background: var(--clr-gold);
  color: var(--clr-navy);
}

/* ===========================================================================
   PAGE HERO: GRID OVERLAY AND SLIDESHOW
   =========================================================================== */
.page-hero__grid-overlay {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  opacity: 0.05;
  pointer-events: none;
}

.page-hero__grid-overlay i {
  border-right: 1px solid var(--clr-white);
}

/*
 * Unlike the single side image - which the design hides on small screens -
 * the slideshow is part of the content on every width, so it opts back in.
 */
.page-hero__slideshow {
  display: block;
  position: relative;
  height: 20rem;
  overflow: hidden;
}

.page-hero__slides {
  position: absolute;
  inset: 0;
}

.page-hero__slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 1s ease;
}

.page-hero__slide.is-active {
  opacity: 1;
}

.page-hero__slide-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

.page-hero__dots {
  position: absolute;
  bottom: 12px;
  left: 0;
  right: 0;
  width: fit-content;
  margin-inline: auto;
  display: flex;
  gap: 8px;
  z-index: 2;
}

.page-hero__dot {
  width: 8px;
  height: 8px;
  padding: 0;
  border: 0;
  background: rgba(255, 255, 255, 0.6);
  cursor: pointer;
  transition: width var(--transition), background-color var(--transition);
}

.page-hero__dot.is-active {
  width: 20px;
  background: var(--clr-gold);
}

@media (min-width: 992px) {
  .page-hero__slideshow {
    height: 26.25rem;
  }
}

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

/* ===========================================================================
   LAYOUT: FLIP CARDS

   Hairline grid gaps over a light background reproduce the design's 1px
   dividers. Flips on hover (pointer devices only), on tap/click, and on
   Enter/Space - see assets/js/interactions.js.
   =========================================================================== */
.flip-cards {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1px;
  background: #e5e7eb;
}

.flip-card {
  position: relative;
  min-height: 22rem;
  perspective: 1200px;
  cursor: pointer;
}

.flip-card--static {
  cursor: default;
}

.flip-card__inner {
  position: relative;
  width: 100%;
  min-height: inherit;
  transform-style: preserve-3d;
  transition: transform 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

/* Hover flip only where there is a real pointer - on touch it would stick. */
@media (hover: hover) {
  .flip-card:not(.flip-card--static):hover .flip-card__inner {
    transform: rotateY(180deg);
  }
}

.flip-card.is-flipped .flip-card__inner {
  transform: rotateY(180deg);
}

.flip-card__face {
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding: 32px;
  min-height: 22rem;
  backface-visibility: hidden;
}

/*
 * The front face stays in flow so it sets the card's height; the back is
 * layered over it. Without this the absolutely-positioned faces would
 * collapse the card to nothing.
 */
.flip-card__face--front {
  position: relative;
  background: var(--clr-white);
  color: var(--clr-navy);
}

.flip-card__face--back {
  position: absolute;
  inset: 0;
  transform: rotateY(180deg);
  background: var(--card-accent, var(--clr-teal));
  color: var(--clr-white);
  overflow-y: auto;
}

.flip-card__icon {
  width: 40px;
  height: 40px;
  display: block;
  color: var(--card-accent, var(--clr-teal));
}

.flip-card__headline {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.25rem, 2vw, 1.5rem);
  line-height: 1.1;
  letter-spacing: var(--heading-tracking);
  text-transform: uppercase;
}

.flip-card__headline--back {
  color: var(--clr-white);
}

.flip-card__rule {
  display: block;
  /*
   * flex: 0 0 auto is load-bearing, not decoration. The faces are flex columns
   * and the back is a fixed-height box that scrolls, so on the card with the
   * longest back copy this 2px rule was being shrunk to 0 and vanishing while
   * it rendered fine on every shorter card.
   */
  flex: 0 0 auto;
  width: 32px;
  height: 2px;
  background: var(--clr-gold);
}

.flip-card__text {
  margin: 0;
  font-size: clamp(1rem, 2.2vw, 1.25rem);
  line-height: 1.625;
  color: rgba(255, 255, 255, 0.9);
}

.flip-card:focus-visible {
  outline: 3px solid var(--clr-teal);
  outline-offset: 2px;
}

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

@media (min-width: 768px) {
  .flip-cards {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 992px) {
  .flip-cards--cols-3 {
    grid-template-columns: repeat(3, 1fr);
  }

  .flip-cards--cols-4 {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* ===========================================================================
   LAYOUT: SPLIT FEATURE
   =========================================================================== */
.split-feature {
  display: grid;
  grid-template-columns: 1fr;
}

.split-feature__media {
  position: relative;
  overflow: hidden;
  min-height: 20rem;
}

.split-feature__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

.split-feature__img.has-zoom {
  animation: heroZoom 10s ease-out forwards;
}

.split-feature__panel {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 48px;
  background: var(--panel-bg, var(--clr-teal));
  color: var(--clr-navy);
}

.split-feature__bar {
  display: block;
  width: 48px;
  height: 4px;
  margin-bottom: 24px;
  background: var(--clr-gold);
}

.split-feature__heading {
  margin: 0 0 24px;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2rem, 4vw, 3rem);
  line-height: 1.1;
  letter-spacing: var(--heading-tracking);
  text-transform: uppercase;
}

.split-feature__text {
  margin-bottom: 32px;
  font-size: clamp(1rem, 2.2vw, 1.25rem);
  line-height: 1.625;
  color: color-mix(in srgb, currentColor 80%, transparent);
}

.split-feature__text > *:first-child {
  margin-top: 0;
}

.split-feature__text > *:last-child {
  margin-bottom: 0;
}

.split-feature__buttons {
  margin: 0;
}

@media (prefers-reduced-motion: reduce) {
  .split-feature__img.has-zoom {
    animation: none;
  }
}

@media (min-width: 992px) {
  .split-feature {
    grid-template-columns: 1fr 1fr;
    align-items: stretch;
  }

  .split-feature__panel {
    padding: 64px;
  }

  /* Reorder visually only, so the text stays first in the DOM. */
  .split-feature--image-right .split-feature__media {
    order: 2;
  }
}

/* ===========================================================================
   LAYOUT: LOGO WALL
   One list of organisation logos, shown either as a grid of boxes with the
   name beneath each, or as rows that drift sideways. Both presentations come
   from the design and take the same fields, so they share one layout.
   =========================================================================== */
.logo-wall__head {
  margin-bottom: 56px;
}

.logo-wall__heading {
  margin-bottom: 0;
}

/* --- Shared: the logo mark itself --------------------------------------- */
.logo-wall__mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}

/*
 * Some organisations supply artwork that is white or very light on a
 * transparent background. On our white tile that is invisible, so the row
 * carries the organisation's own brand colour and we lay the mark on it.
 */
.logo-wall__mark.has-backdrop {
  padding: 8px 10px;
  background: var(--logo-bg);
}

.logo-wall__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* Listed before its artwork arrived - set the name instead, as the design does. */
.logo-wall__fallback {
  font-family: var(--font-display);
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1.25;
  color: var(--clr-navy);
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.025em;
}

/* --- Grid presentation --------------------------------------------------- */
.logo-wall--grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  /* Row gap only: the name sits below each tile, so rows need more breathing
     room than columns to keep a name visually tied to its own logo. */
  gap: 20px 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.logo-wall__item {
  display: flex;
  flex-direction: column;
  margin: 0;
}

.logo-wall__box {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 16 / 9;
  padding: 12px;
  overflow: hidden;
  background: color-mix(in srgb, var(--clr-teal) 5%, transparent);
  border: 1px solid color-mix(in srgb, var(--clr-teal) 30%, transparent);
  transition: background-color 0.2s ease, border-color 0.2s ease;
}

a.logo-wall__box:hover,
a.logo-wall__box:focus-visible,
.logo-wall__item:hover .logo-wall__box {
  background: color-mix(in srgb, var(--clr-teal) 10%, transparent);
  border-color: var(--clr-teal);
}

.logo-wall__name {
  margin: 8px 0 0;
  padding-inline: 4px;
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1.25;
  color: var(--clr-navy);
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.025em;
}

/*
 * Progressive disclosure. The extras are hidden ONLY when JavaScript is
 * present to bring them back - same contract as .reveal - so with JS off or
 * broken every logo is on the page rather than permanently unreachable.
 */
.js-reveal .logo-wall--grid[data-initial]:not(.is-expanded) .logo-wall__item.is-extra {
  display: none;
}

.logo-wall__more {
  display: none;
  justify-content: center;
  margin-top: 40px;
}

.js-reveal .logo-wall__more {
  display: flex;
}

.logo-wall__more.is-done {
  display: none;
}

/* --- Marquee presentation ------------------------------------------------ */
.logo-wall--marquee {
  display: flex;
  flex-direction: column;
  gap: 12px;
  overflow: hidden;
}

.logo-wall__row {
  overflow: hidden;
}

.logo-wall__track {
  display: flex;
  width: max-content;
  animation: logoWallDrift var(--marquee-speed, 35s) linear infinite;
}

.logo-wall__row.is-reverse .logo-wall__track {
  animation-direction: reverse;
}

/*
 * The row is printed twice, so translating a full 50% lands exactly where it
 * started and the loop is seamless.
 */
@keyframes logoWallDrift {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}

.logo-wall__track:hover,
.logo-wall__track:focus-within {
  animation-play-state: paused;
}

.logo-wall__set {
  display: flex;
}

.logo-wall__cell {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  min-width: 192px;
  height: 80px;
  margin-inline: 6px;
  padding: 16px 20px;
  background: var(--clr-white);
  border: 1px solid color-mix(in srgb, var(--clr-navy) 20%, transparent);
}

.logo-wall__cell .logo-wall__img {
  width: auto;
  max-width: 100%;
  max-height: 48px;
}

.logo-wall__cell .logo-wall__fallback {
  white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  /*
   * Sideways drift is decorative motion, so it stops. The rows then need to
   * scroll by hand, which is why the overflow becomes scrollable rather than
   * clipping the logos that were off-screen.
   */
  .logo-wall__track {
    animation: none;
  }

  .logo-wall__row {
    overflow-x: auto;
  }

  .logo-wall__set + .logo-wall__set {
    display: none;
  }
}

@media (min-width: 768px) {
  .logo-wall--grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (min-width: 992px) {
  .logo-wall--grid.logo-wall--cols-3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .logo-wall--grid.logo-wall--cols-4 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .logo-wall--grid.logo-wall--cols-5 {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

/* ===========================================================================
   LAYOUT: PEOPLE GRID
   Square photos under one colour wash, so a set of press shots from many
   sources reads as a single coalition rather than a scrapbook.
   =========================================================================== */
.people-grid__head {
  margin-bottom: 56px;
}

.people-grid__heading {
  margin-bottom: 0;
}

.people-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.people-grid__item {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin: 0;
}

.people-grid__figure {
  position: relative;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background: color-mix(in srgb, var(--clr-navy) 35%, transparent);
}

.people-grid__photo {
  display: block;
  width: 100%;
  height: 100%;
  /* Cropped from the top, so a head near the top of the frame stays in shot. */
  object-fit: cover;
  object-position: top center;
}

.people-grid__wash {
  position: absolute;
  inset: 0;
  background: var(--wash);
  mix-blend-mode: multiply;
}

.people-grid__name {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 800;
  line-height: 1.15;
  text-transform: uppercase;
  letter-spacing: 0.025em;
}

.people-grid__title {
  margin: -5px 0 0;
  font-size: 0.75rem;
  font-weight: 500;
  line-height: 1.25;
  color: var(--clr-teal);
}

@media (min-width: 640px) {
  .people-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (min-width: 768px) {
  .people-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 24px;
  }
}

@media (min-width: 992px) {
  /*
   * One step below the chosen count here and the full count at 1280, matching
   * the design's lg:5 / xl:6 pair without hardcoding either number.
   */
  .people-grid--cols-5 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .people-grid--cols-6 {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

@media (min-width: 1280px) {
  .people-grid--cols-4 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .people-grid--cols-5 {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }

  .people-grid--cols-6 {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }
}

/* ===========================================================================
   LAYOUT: SCROLLING NAME LIST
   Heading and intro beside a panel of names that scrolls inside its own
   height, so a roster of forty does not push the page down.
   =========================================================================== */
.scroll-list {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 48px;
  align-items: start;
}

.scroll-list__heading {
  margin-bottom: 0;
}

.scroll-list__text {
  margin: 24px 0 0;
  font-size: 1.0625rem;
  line-height: 1.625;
  color: color-mix(in srgb, var(--clr-navy) 70%, transparent);
}

.scroll-list__panel {
  background: var(--clr-white);
  border: 2px solid var(--clr-teal);
}

.scroll-list__items {
  height: var(--panel-height, 480px);
  margin: 0;
  padding: 0;
  overflow-y: auto;
  list-style: none;
  scrollbar-width: thin;
  scrollbar-color: var(--clr-teal) #e8e8e8;
}

.scroll-list__items::-webkit-scrollbar {
  width: 8px;
}

.scroll-list__items::-webkit-scrollbar-track {
  background: #e8e8e8;
}

.scroll-list__items::-webkit-scrollbar-thumb {
  background: var(--clr-teal);
}

.scroll-list__item {
  display: flex;
  flex-direction: column;
  padding: 16px 24px;
  transition: background-color 0.15s ease;
}

.scroll-list__item + .scroll-list__item {
  border-top: 1px solid color-mix(in srgb, var(--clr-teal) 20%, transparent);
}

.scroll-list__item:hover {
  background: color-mix(in srgb, var(--clr-teal) 5%, transparent);
}

.scroll-list__name {
  font-family: var(--font-display);
  font-size: 1.0625rem;
  font-weight: 800;
  line-height: 1.15;
  color: var(--clr-navy);
  text-transform: uppercase;
  letter-spacing: 0.025em;
}

.scroll-list__title {
  margin-top: 2px;
  font-size: 0.9375rem;
  font-weight: 500;
  line-height: 1.3;
  color: var(--clr-teal);
}

@media (min-width: 992px) {
  .scroll-list {
    grid-template-columns: 2fr 3fr;
  }

  /* Reorder visually only, so the heading stays first in the DOM. */
  .scroll-list--panel-left .scroll-list__intro {
    order: 2;
  }

  .scroll-list__text,
  .scroll-list__name {
    font-size: 1.25rem;
  }

  .scroll-list__title {
    font-size: 1rem;
  }
}

/* ===========================================================================
   BUTTON: GOLD, NAVY ON HOVER
   Distinct from .btn__primary, which hovers to teal. On a teal panel that
   hover would make the button vanish into its own background, so this variant
   darkens to navy instead - the design's behaviour for the donate CTA.
   =========================================================================== */
.btn__gold-navy,
.btn__gold-navy:visited {
  background: var(--clr-gold);
  color: var(--clr-navy);
  border-color: var(--clr-gold);
}

.btn__gold-navy:hover,
.btn__gold-navy:focus-visible {
  background: var(--clr-navy);
  /* White on hover, per the Endorsements donate-button request. */
  color: var(--clr-white);
  border-color: var(--clr-navy);
}

/* ===========================================================================
   PAGE HERO: FAINTER WATERMARK
   The About hero's watermark is 10% white at 25vw; the Endorsements hero's is
   5% at 20vw, because its word is longer and sits behind a three-line
   headline. An opt-in modifier rather than a change to the shared default, so
   the pages already signed off keep exactly the watermark they were approved
   with. Applied through the section's own Extra Class field.
   =========================================================================== */
.section.watermark-faint .page-hero__watermark {
  font-size: 20vw;
  color: rgba(255, 255, 255, 0.05);
}

/* ===========================================================================
   FLIP CARDS - CORRECTIONS
   Three fixes, all from looking at the rendered page:

   1. The grey that appeared mid-flip was this grid's own divider colour. The
      card sat on it with a transparent background, so while the inner face
      was edge-on there was nothing opaque in front of it. Giving the card
      itself an opaque white background hides the divider behind it without
      losing the dividers between cards.

   2. The 1px gap over this grid's background is what draws the hairline
      dividers, exactly as the design does it - so there is a line BETWEEN
      boxes and none around the outside. A 1px padding here would close that
      ring if an outer border is ever wanted; it is deliberately not set.

   3. The description now lives on the front, so the body text needs a colour
      per face - navy at 70% on white, white at 90% on the accent - instead of
      one rule written for the back alone.
   =========================================================================== */
.flip-card {
  /*
   * Opaque, so whatever sits behind the grid never shows through a card that
   * is part-way through its rotation. Kept after the grid's own background was
   * removed - it is what stops a section background or image appearing through
   * a card at the moment its face is edge-on.
   */
  background: var(--clr-white);
}

.flip-card__face--front {
  justify-content: flex-start;
}

.flip-card__text--front {
  color: color-mix(in srgb, var(--clr-navy) 70%, transparent);
}

.flip-card__text--back {
  color: rgba(255, 255, 255, 0.9);
}

/*
 * The back face can hold more copy than the front, so it scrolls inside the
 * card rather than being clipped. Momentum scrolling on touch, and a thin
 * gold thumb so it is visible against the accent colour.
 */
.flip-card__face--back {
  scrollbar-width: thin;
  scrollbar-color: var(--clr-gold) transparent;
}

.flip-card__face--back::-webkit-scrollbar {
  width: 6px;
}

.flip-card__face--back::-webkit-scrollbar-thumb {
  background: var(--clr-gold);
}


/* ===========================================================================
   RESTORED BLOCKS (merge, 2026-09-08)

   These rules existed in the working stylesheet but were absent from the
   uploaded copy, which left several layouts unstyled on live pages. They are
   appended here rather than spliced back into their original positions so the
   merge is reviewable in one place; every selector below is unique to this
   block, so cascade order is not load-bearing.
   =========================================================================== */

/*
 * Button icons. These were being emitted with no size at all: the inline SVGs
 * carry a viewBox but no width/height attributes, and nothing in the
 * stylesheet sized .btn__icon, so the Load More chevron was rendering about
 * 4px wide - present in the markup, invisible on the page. 16px is the
 * design's w-4 h-4.
 */
.btn__icon {
  flex: 0 0 auto;
  display: block;
  width: 16px;
  height: 16px;
}

/*
 * An uploaded icon (ib4a_the_button's Icon field) is arbitrary artwork rather
 * than a 24x24 glyph, so it keeps its own proportions and is capped instead of
 * being squashed into a square.
 */
img.btn__icon {
  width: auto;
  height: auto;
  max-width: 24px;
  max-height: 20px;
}

/*
 * Optional rule across the top of a section, opted into through the shared
 * Custom CSS Class field rather than a new setting - the design uses it once,
 * on Take Action's Stay Involved band, and draws it as a border rather than a
 * separate element.
 */
.section.has-top-rule {
  border-top: 4px solid var(--clr-teal);
}

/*
 * Lift real content above the overlay and any background video.
 *
 * The :not() is load-bearing. Without it this selector also matches the
 * background <video> itself and outranks .section__bg-video, which turned the
 * video into an in-flow element stacked ABOVE the content instead of a
 * backdrop behind it.
 */
.section.has-overlay > *:not(.section__bg-video),
.section.has-bg-video > *:not(.section__bg-video) {
  position: relative;
  z-index: 1;
}

/*
 * Content Alignment.
 *
 * align-left needs a real declaration rather than relying on the inherited
 * default: without it, switching a section from Center back to Left only
 * works while nothing above it sets text-align, so the option would quietly
 * stop working the first time a layout defaults to centred.
 */
.section.align-left {
  text-align: left;
}

/*
 * text-align cannot move a flex child, and .btn__wrap is a flex row, so the
 * setting has to be restated for button rows - otherwise centring a section
 * moves its copy while the buttons stay pinned left.
 */
.section.align-center .btn__wrap {
  justify-content: center;
}

.section.align-right .btn__wrap {
  justify-content: flex-end;
}

/* Load More: the design's px-8 py-4 against the shared .btn default. */
.logo-wall__more-btn {
  padding: 16px 32px;
}

/*
 * Road segments. The design's road is NOT one continuous rule - it is a series
 * of short bars that sit in the GAPS between the start marker, each stop and
 * the end cap, with no line crossing a card row. Each segment is a child of
 * the element BELOW its gap and is pulled up into it, so the count follows the
 * number of stops automatically. Desktop only, like the rest of the road.
 */
.roadmap__seg {
  display: none;
}

/*
 * Large heading. The design uses this split at two scales: the Plan page's
 * "Learn More" band is text-4xl/md:text-5xl (the 48px default above), while
 * the donate band is text-5xl/md:text-7xl - 72px at desktop. Opt-in, so the
 * existing Plan section keeps the size it was designed at.
 */
.split-feature--heading-lg .split-feature__heading {
  font-size: clamp(3rem, 5.2vw, 4.5rem);
  line-height: 1.25;
}

/*
 * Background media treatment. Instead of taking its own column, the image sits
 * behind the copy and fills half the section (the design's absolutely
 * positioned right-hand district map). The img element is kept rather than
 * swapping to a CSS background so srcset/sizes and the alt text survive.
 */
.split-feature--media-bg {
  grid-template-columns: 1fr;
}

/*
 * Deliberately NOT position:relative. The design fills the right half of the
 * full-bleed SECTION, not of the 1240px .wrapper the layout sits in, so the
 * media is left to resolve against .section (which is position:relative)
 * instead. .wrapper is unpositioned, so it does not intercept.
 *
 * In this mode the coloured band is the section's own Background Color rather
 * than --panel-bg, because the panel no longer occupies a half to tint.
 *
 * Caveat: adding an Overlay to this section would make .wrapper positioned
 * (via .section.has-overlay > *) and pull the artwork back to wrapper width.
 */
.split-feature--media-bg .split-feature__media {
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  width: 50%;
  min-height: 0;
  z-index: 0;
  pointer-events: none;
}

.split-feature--media-bg.split-feature--image-left .split-feature__media {
  right: auto;
  left: 0;
}

.split-feature--media-bg .split-feature__img {
  object-position: left center;
}

.split-feature--media-bg.split-feature--image-left .split-feature__img {
  object-position: right center;
}

/*
 * The copy sits above the artwork and keeps the design's max-w-xl measure.
 * Padding drops to zero because in this mode the coloured area is the whole
 * section, whose vertical rhythm already comes from .section's padding-block
 * and whose side padding comes from .wrapper - the panel's own 48/64px is the
 * inset of the coloured HALF and would double up here.
 */
.split-feature--media-bg .split-feature__panel {
  position: relative;
  z-index: 1;
  max-width: 36rem;
  padding: 0;
  background: transparent;
}

@media (min-width: 992px) {
  /*
   * Background treatment: the artwork fills the right half of the FULL-BLEED
   * section rather than a column inside the 1240px wrapper. The element is a
   * direct child of .section (see page-hero.php) so it resolves against the
   * section, and .page-hero__inner's own z-index:1 keeps the copy above it.
   */
  .page-hero__media--bg {
    display: block;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 50%;
    z-index: 0;
    pointer-events: none;
  }

  .page-hero__media--bg .page-hero__img {
    width: 100%;
    height: 100%;
    max-height: none;
    object-fit: cover;
    object-position: center;
  }

  /* The design's min-h-[560px]. Desktop only: below 992px the artwork is
     hidden, so enforcing it there would leave a tall empty band. */
  .section--page-hero.has-hero-media-bg {
    min-height: 560px;
    display: flex;
    flex-direction: column;
    justify-content: center;
  }

  /* One column, and the copy is held to its half so it never runs over the
     artwork now that the two overlap. */
  .has-hero-media-bg .page-hero__grid {
    grid-template-columns: 1fr;
  }

  .has-hero-media-bg .page-hero__text {
    max-width: 50%;
  }

  /*
   * The road, drawn segment by segment. Every gap here measures exactly 60px
   * (.roadmap and .roadmap__stops both use gap: 60px), so a segment pulled up
   * 60px from the top of the element below it fills its gap precisely and
   * stops at the card edge - reproducing the design's broken road instead of
   * the single full-height rule this replaced.
   */
  .roadmap__seg {
    display: block;
    position: absolute;
    left: 50%;
    top: -60px;
    width: 4px;
    height: 60px;
    margin-left: -2px;
    background: var(--clr-navy);
    z-index: 0;
  }

  /*
   * Background mode stays a single column. These two rules are required, not
   * redundant: the .split-feature rules above match at the same specificity
   * and come later in the file, so without them the two-column grid and the
   * 64px panel padding would both win here.
   */
  .split-feature--media-bg {
    grid-template-columns: 1fr;
  }

  .split-feature--media-bg .split-feature__panel {
    padding: 0;
  }
}

/* ===========================================================================
   LAYOUT: RICH TEXT
   The one section carrying ordinary editor prose. Everything the WordPress
   editor can emit is given a style here, because until now the theme only
   styled paragraphs - a pasted policy full of headings, lists and links would
   have fallen back to browser defaults and looked nothing like the site.
   =========================================================================== */
.rich-text__heading {
  margin-bottom: 32px;
}

.rich-text__body {
  font-size: 1rem;
  line-height: 1.7;
  color: color-mix(in srgb, currentColor 80%, transparent);
}

/* Collapse the outer margins so the block's own spacing controls the edges. */
.rich-text__body > *:first-child {
  margin-top: 0;
}

.rich-text__body > *:last-child {
  margin-bottom: 0;
}

.rich-text__body p {
  margin: 0 0 20px;
}

/*
 * Editor headings step down from the section heading. They are display-face
 * and uppercase like every other heading on the site, just smaller, so a
 * policy still reads as this site rather than a generic document.
 */
.rich-text__body h2,
.rich-text__body h3,
.rich-text__body h4,
.rich-text__body h5,
.rich-text__body h6 {
  margin: 40px 0 16px;
  font-family: var(--font-display);
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: var(--heading-tracking);
  text-transform: uppercase;
  /* Headings sit at full strength against the 80% body copy. */
  color: currentColor;
}

.rich-text__body h2 {
  font-size: clamp(1.5rem, 3vw, 2rem);
}

.rich-text__body h3 {
  font-size: clamp(1.25rem, 2.4vw, 1.5rem);
}

.rich-text__body h4,
.rich-text__body h5,
.rich-text__body h6 {
  font-size: 1.125rem;
}

.rich-text__body ul,
.rich-text__body ol {
  margin: 0 0 20px;
  padding-left: 1.25rem;
}

.rich-text__body li {
  margin-bottom: 8px;
}

.rich-text__body li > ul,
.rich-text__body li > ol {
  margin: 8px 0 0;
}

.rich-text__body a {
  color: currentColor;
  text-decoration: underline;
  text-underline-offset: 0.15em;
  text-decoration-thickness: 2px;
  transition: color var(--transition);
}

.rich-text__body a:hover,
.rich-text__body a:focus-visible {
  color: var(--clr-teal);
}

.rich-text__body strong,
.rich-text__body b {
  font-weight: 700;
  color: currentColor;
}

.rich-text__body blockquote {
  margin: 32px 0;
  padding-left: 24px;
  border-left: 4px solid var(--clr-teal);
  font-style: normal;
}

.rich-text__body hr {
  margin: 40px 0;
  border: 0;
  border-top: 2px solid color-mix(in srgb, currentColor 20%, transparent);
}

.rich-text__body img {
  margin: 24px 0;
}

.rich-text__body figure {
  margin: 24px 0;
}

.rich-text__body figcaption {
  margin-top: 8px;
  font-size: 0.875rem;
  color: color-mix(in srgb, currentColor 65%, transparent);
}

/* A table can be wider than the measure, so it scrolls in its own right
   rather than pushing the page sideways. */
.rich-text__body table {
  display: block;
  width: 100%;
  margin: 0 0 24px;
  overflow-x: auto;
  border-collapse: collapse;
}

.rich-text__body th,
.rich-text__body td {
  padding: 12px 16px;
  border: 1px solid color-mix(in srgb, currentColor 20%, transparent);
  text-align: left;
}

.rich-text__body th {
  font-family: var(--font-display);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.rich-text__body code,
.rich-text__body pre {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.9375rem;
}

.rich-text__body pre {
  margin: 0 0 24px;
  padding: 16px;
  overflow-x: auto;
  background: color-mix(in srgb, currentColor 8%, transparent);
}

/* ===========================================================================
   LAYOUT: QUOTE FEATURE
   A pull quote beside a portrait. The section's gold ground and its type
   pattern come from the shared section settings, so nothing here paints a
   background - only the quote, the watermark and the image furniture.
   =========================================================================== */
.quote-feature {
  display: grid;
  grid-template-columns: 1fr;
  align-items: stretch;
}

/*
 * The watermark quote mark. It hangs off the top-left corner of the section,
 * which is why the section clips it - see .section--quote-feature below. It is
 * decorative and must never be selectable or hit-testable.
 */
.quote-feature__mark {
  position: absolute;
  /*
   * The design's own -top-8 / -left-4. Given as pixels rather than em because
   * the font-size here is a 448px clamp - an em offset scaled with it and
   * pushed the glyph four times further out of the section than intended.
   */
  top: -32px;
  left: -16px;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(16rem, 30vw, 28rem);
  line-height: 1;
  color: color-mix(in srgb, var(--clr-navy) 10%, transparent);
  pointer-events: none;
  user-select: none;
  z-index: 0;
}

.section--quote-feature {
  overflow: hidden;
}

.quote-feature__body {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-block: 40px;
}

.quote-feature__eyebrow {
  margin: 0 0 24px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.875rem;
  line-height: 1.2;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--clr-navy) 60%, transparent);
}

.quote-feature__quote {
  margin: 0 0 32px;
}

.quote-feature__quote p {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 900;
  /* The design's clamp(2rem, 3.5vw, 3rem) - 32px on small screens up to 48px. */
  font-size: clamp(2rem, 3.5vw, 3rem);
  line-height: 0.95;
  letter-spacing: var(--heading-tracking);
  text-transform: uppercase;
  color: var(--clr-navy);
}

/*
 * The rule draws itself in as the block reveals. It starts at zero width and
 * is grown by the .is-visible class reveal.js adds, so the animation shares
 * the same trigger as every other reveal on the site rather than needing its
 * own observer.
 */
.quote-feature__rule {
  display: block;
  width: 0;
  height: 4px;
  background: var(--clr-navy);
  transition: width 1s ease-out;
}

.quote-feature__body.is-visible .quote-feature__rule {
  width: 80px;
}

.quote-feature__name {
  margin: 24px 0 0;
  font-family: var(--font-display);
  font-weight: 900;
  font-size: 1.25rem;
  line-height: 1.2;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--clr-navy);
}

.quote-feature__title {
  margin: 4px 0 0;
  font-family: var(--font-body);
  font-size: 0.875rem;
  line-height: 1.4;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--clr-navy) 70%, transparent);
}

.quote-feature__media {
  position: relative;
  z-index: 1;
  margin: 0;
  min-height: 20rem;
  overflow: hidden;
}

.quote-feature__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* object-top: the design keeps faces in frame as the box gets shorter. */
  object-position: center top;
  transform: scale(1.1);
  transition: transform 1.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

.quote-feature__media.is-visible .quote-feature__img {
  transform: scale(1);
}

/* Diagonal accent cut out of the image's top-left corner. */
.quote-feature__slice {
  position: absolute;
  inset: 0;
  background: var(--clr-teal);
  clip-path: polygon(0 0, 30px 0, 0 60px);
  z-index: 2;
  pointer-events: none;
}

.quote-feature__caption {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 2;
  padding: 12px 24px;
  background: var(--clr-navy);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 0.875rem;
  line-height: 1.3;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--clr-gold);
}

@media (prefers-reduced-motion: reduce) {
  .quote-feature__rule,
  .quote-feature__img {
    transition: none;
  }

  .quote-feature__img {
    transform: none;
  }
}

@media (min-width: 992px) {
  .quote-feature {
    grid-template-columns: 1fr 1fr;
    min-height: 20rem;
  }

  .quote-feature__body {
    padding-block: 56px;
    padding-right: 64px;
  }

  /* Image on the left flips the padding and reorders visually only, so the
     quote stays first in the DOM and therefore first for screen readers. */
  .quote-feature--image-left .quote-feature__media {
    order: -1;
  }

  .quote-feature--image-left .quote-feature__body {
    padding-right: 0;
    padding-left: 64px;
  }

  .quote-feature__media {
    min-height: 26.25rem;
  }
}

/*
 * Mobile: cap the portrait's WIDTH.
 *
 * The image is width:100% with an auto height, so it takes its intrinsic
 * portrait aspect - at full column width that drew it 480px tall, over half
 * the section. Capping the width scales the whole picture down proportionally
 * rather than cropping it, so nothing is cut off the frame.
 *
 * min-height is reset because the frame no longer needs a floor once its
 * height simply follows the narrower width.
 *
 * Placed after the min-width: 992px block above so it is not overridden: a
 * media query carries no specificity of its own, only source order.
 */
@media (max-width: 991px) {
  .quote-feature__media {
    max-width: 15rem;
    min-height: 0;
  }
}

/* ===========================================================================
   REVEAL: FROM THE LEFT

   The design does not reveal every heading the same way. Most rise from below
   (slideUp), but four section headings enter horizontally from the left -
   design-source keyframe `slideRight`, translateX(-40px) -> 0 over 0.7s:
   Home's "Isaac Bryan Is A Leading Voice...", "One of the Most Diverse..."
   and "Stay Involved", plus Take Action's "Stay Involved".

   Only the HEADING moves sideways in the design; the eyebrow above it and the
   body copy below it both keep slideUp, which is why this is a modifier on
   the heading rather than a change to .reveal itself.
   =========================================================================== */
@keyframes slideInLeft {
  from {
    opacity: 0;
    transform: translateX(-40px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

/*
 * Same specificity as `.reveal.is-visible` (0,2,0), so this only wins by
 * coming later in the file - it must stay below that rule.
 *
 * `both`, NOT `forwards`, and the reason is the trap: the `animation`
 * shorthand RESETS animation-fill-mode, so this rule silently overwrote the
 * `both` set on `.reveal.is-visible` above. With `forwards` the fill does not
 * cover the animation-delay window, so an element with `opacity: 1` declared
 * sat fully visible for its delay, snapped to the keyframe's opacity 0, then
 * faded in - a visible flicker. Measured on four headings before this was
 * corrected: opacity held 1.000 for ~145ms then dropped to 0.024 in one
 * frame. Any future animation shorthand on a .reveal variant must use `both`
 * for the same reason.
 */
.reveal--left.is-visible {
  animation: slideInLeft 0.7s ease-out both;
  animation-delay: var(--reveal-delay, 0s);
}

@media (prefers-reduced-motion: reduce) {
  .reveal--left.is-visible {
    animation: none;
  }
}

/* ===========================================================================
   COLUMN ALIGNMENT (shared Section Setting)

   How the two columns line up against each other when one is shorter. Set
   once in Section Settings and applied here to every two-column layout, so
   the option behaves the same wherever it is used.

   Specificity is 0,3,0 (.section.cols-x .grid), which clears both the base
   grid rules (0,1,0) and their desktop overrides - media queries add no
   specificity of their own, so a plain rule here still wins inside them.
   Left outside any breakpoint deliberately: below the desktop breakpoint
   these grids collapse to one column, where align-items is inert anyway.
   =========================================================================== */
.section.cols-top .content-media__grid,
.section.cols-top .split-feature,
.section.cols-top .quote-feature,
.section.cols-top .signup__grid,
.section.cols-top .scroll-list {
  align-items: start;
}

.section.cols-center .content-media__grid,
.section.cols-center .split-feature,
.section.cols-center .quote-feature,
.section.cols-center .signup__grid,
.section.cols-center .scroll-list {
  align-items: center;
}

.section.cols-bottom .content-media__grid,
.section.cols-bottom .split-feature,
.section.cols-bottom .quote-feature,
.section.cols-bottom .signup__grid,
.section.cols-bottom .scroll-list {
  align-items: end;
}

/*
 * Stretch is offered explicitly because it is the default on most of these
 * layouts but NOT on Content + Media (which the design sets to start), so
 * without it there would be no way to opt that one layout into full-height
 * columns.
 */
.section.cols-stretch .content-media__grid,
.section.cols-stretch .split-feature,
.section.cols-stretch .quote-feature,
.section.cols-stretch .signup__grid,
.section.cols-stretch .scroll-list {
  align-items: stretch;
}

/* ==========================================================================
   Photo Collage
   Shared component: framed photos arranged either as a slightly rotated,
   overlapping fan (--scatter, the 55th District wall) or as a rigid square
   grid (--grid, the About hero). One tree, a display switch, as with the
   roadmap and logo wall. Frame colour comes in via --collage-frame so the
   two variants share every other rule.
   ========================================================================== */
.photo-collage {
  display: grid;
  grid-template-columns: 1fr 1fr;
  margin: 0;
  padding: 0;
  list-style: none;
}

.photo-collage--frame-white {
  --collage-frame: #fff;
}

.photo-collage--frame-gold {
  --collage-frame: var(--clr-gold);
}

.photo-collage__item {
  margin: 0;
}

.photo-collage__frame {
  position: relative;
  margin: 0;
}

/*
 * Deliberately NOT .content-media__img: that selector carries a
 * transform: scale(1.12) settle which escapes its overflow:visible frame,
 * and these tiles must not inherit it.
 */
.photo-collage__img {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
}

/* --- Scatter: polaroid frames, fanned ------------------------------------- */
.photo-collage--scatter {
  gap: 14px;
  width: 100%;
  max-width: 640px;
}

.photo-collage--scatter .photo-collage__frame {
  padding: clamp(6px, 1.2%, 10px) clamp(6px, 1.2%, 10px) clamp(22px, 7%, 34px);
  border-radius: 2px;
  background: var(--collage-frame);
  box-shadow: 0 10px 24px rgba(32, 32, 80, 0.18);
}

/* Rows two and three ride up slightly so the tiles just clip each other. */
.photo-collage--scatter .photo-collage__item:nth-child(n + 3) {
  margin-top: -22px;
}

/* Ascending stack order, so each later tile sits over the earlier one. */
.photo-collage--scatter .photo-collage__item {
  position: relative;
}

.photo-collage--scatter .photo-collage__item:nth-child(1) {
  z-index: 1;
}

.photo-collage--scatter .photo-collage__item:nth-child(2) {
  z-index: 2;
}

.photo-collage--scatter .photo-collage__item:nth-child(3) {
  z-index: 3;
}

.photo-collage--scatter .photo-collage__item:nth-child(4) {
  z-index: 4;
}

.photo-collage--scatter .photo-collage__item:nth-child(5) {
  z-index: 5;
}

/* The fifth tile centres beneath the two above it. */
.photo-collage--scatter .photo-collage__item:nth-child(5) {
  grid-column: 1 / -1;
  justify-self: center;
  width: 50%;
}

.photo-collage--scatter .photo-collage__item:nth-child(1) .photo-collage__frame {
  transform: rotate(-5deg);
}

.photo-collage--scatter .photo-collage__item:nth-child(2) .photo-collage__frame {
  transform: rotate(4deg);
}

.photo-collage--scatter .photo-collage__item:nth-child(3) .photo-collage__frame {
  transform: rotate(-3deg);
}

.photo-collage--scatter .photo-collage__item:nth-child(4) .photo-collage__frame {
  transform: rotate(5deg);
}

.photo-collage--scatter .photo-collage__item:nth-child(5) .photo-collage__frame {
  transform: rotate(-2deg);
}

/* --- Grid: square, rigid, bordered --------------------------------------- */
.photo-collage--grid {
  gap: 14px;
  width: 100%;
  max-width: 560px;
}

.photo-collage--grid .photo-collage__frame {
  border: 6px solid var(--collage-frame);
}

/* --- Responsive ----------------------------------------------------------- */
/*
 * Below the 992px desktop breakpoint the scatter fan calms down: half the
 * rotation and half the overlap, so the rotated corners stay inside the
 * wrapper's padding. Two columns are kept all the way down to 480px.
 */
@media (max-width: 991px) {
  .photo-collage--scatter .photo-collage__item:nth-child(n + 3) {
    margin-top: -12px;
  }

  .photo-collage--scatter .photo-collage__item:nth-child(1) .photo-collage__frame {
    transform: rotate(-2.5deg);
  }

  .photo-collage--scatter .photo-collage__item:nth-child(2) .photo-collage__frame {
    transform: rotate(2deg);
  }

  .photo-collage--scatter .photo-collage__item:nth-child(3) .photo-collage__frame {
    transform: rotate(-1.5deg);
  }

  .photo-collage--scatter .photo-collage__item:nth-child(4) .photo-collage__frame {
    transform: rotate(2.5deg);
  }

  .photo-collage--scatter .photo-collage__item:nth-child(5) .photo-collage__frame {
    transform: rotate(-1deg);
  }
}

/* ===========================================================================
   404: PAGE NOT FOUND

   Reuses the Page Hero language - navy band, faint column grid, oversized
   watermark, gold accent bar - rather than inventing a treatment for a page
   nobody means to visit. The only differences are forced by the content:

   - There is no side image to balance, so the copy is ONE column capped at a
     readable measure instead of stretched across the full 1240px.
   - A desktop min-height keeps the navy band from reading as a thin strip
     above the footer; it lands within ~40px of the About hero's 704px.
   =========================================================================== */
.section--error-404 {
  display: flex;
  align-items: center;
}

.section--error-404 .page-hero__inner {
  width: 100%;
}

/*
 * container-type mirrors .page-hero__text: the heading's desktop clamp is
 * measured against THIS column, not the viewport, so capping the column
 * also caps the heading.
 */
.error-404__text {
  container-type: inline-size;
  max-width: 760px;
}

.error-404__lede {
  margin: 28px 0 0;
  max-width: 46ch;
}

.error-404__actions {
  margin-top: 36px;
}

.error-404__explore {
  margin-top: 48px;
}

.error-404__links {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 28px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.error-404__links a {
  display: inline-block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.125rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  text-decoration: none;
  border-bottom: 2px solid transparent;
  padding-bottom: 2px;
  transition: color var(--transition), border-color var(--transition);
}

/* The site's standard teal underline hover. */
.error-404__links a:hover,
.error-404__links a:focus-visible {
  color: var(--clr-teal);
  border-bottom-color: var(--clr-teal);
}

/*
 * The watermark is an error code, not a word. Three characters at the page
 * heroes' flat 25vw sit well short of the right edge and read as a small
 * label rather than a backdrop, so this one gets its own curve - and a
 * maximum, which 25vw lacks, so it stops growing on very wide screens.
 *
 * Single-class specificity like .page-hero__watermark, so it wins on source
 * order alone; it must stay after that rule.
 */
.error-404__watermark {
  font-size: clamp(7rem, 30vw, 24rem);
}

@media (min-width: 992px) {
  .section--error-404 {
    min-height: 560px;
  }
}

/* ===========================================================================
   MAILCHIMP OPT-IN FORM INSIDE THE SIGNUP PANEL

   The Stay Involved sections (home #stay-involved, take-action
   #stay-involved) now carry the campaign's Mailchimp embed instead of
   Gravity Form 1. .signup__panel above already paints the white ground, the
   2px teal keyline and the 32px padding, so nothing here repeats them - this
   block only styles the form itself, reusing the SAME values as the Gravity
   Forms rules it replaces so the panel is visually unchanged.

   The client's snippet ships its own classic-061523.css plus an inline
   <style>; both were left out of what was pasted in. That sheet forces
   Helvetica/Arial on a white 14px form and would fight the brand type ramp,
   and its inline block is malformed at source ("background:#fff; false;"
   and "width: px;").
   =========================================================================== */
.signup__panel #mc_embed_signup {
  background: none;
  font-family: var(--font-body);
  color: var(--clr-navy);
}

/* Mailchimp always emits an empty <h2>; the section has its own heading. */
.signup__panel #mc_embed_signup h2:empty {
  display: none;
}

/*
 * '* indicates required' is hidden for the same reason the Gravity Forms
 * gform_required_legend was: the design has no such line. The asterisk itself
 * stays - it sits inside the Email label - and the input keeps its required
 * attribute, so the field is still marked and still announced.
 */
.signup__panel #mc_embed_signup .indicates-required {
  display: none;
}

.signup__panel #mc_embed_signup .mc-field-group {
  margin: 0 0 16px;
}

/*
 * Gravity Forms hid its labels because that design shows placeholders only.
 * The Mailchimp snippet carries labels and NO placeholders, so the same
 * treatment would leave four unlabelled boxes. Labels stay visible and are
 * styled as small caps instead.
 */
.signup__panel #mc_embed_signup label {
  display: block;
  margin: 0 0 6px;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--clr-navy);
}

.signup__panel #mc_embed_signup .asterisk {
  color: var(--clr-teal);
}

.signup__panel #mc_embed_signup input[type="email"],
.signup__panel #mc_embed_signup input[type="text"],
.signup__panel #mc_embed_signup input[type="tel"] {
  width: 100%;
  border: 2px solid rgba(91, 196, 196, 0.4);
  background: var(--clr-white);
  padding: 12px 16px;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.875rem;
  color: var(--clr-navy);
  transition: border-color var(--transition);
}

.signup__panel #mc_embed_signup input:focus {
  outline: none;
  border-color: var(--clr-teal);
}

.signup__panel #mc_embed_signup input[type="submit"] {
  width: 100%;
  margin-top: 24px;
  background: var(--clr-teal);
  color: var(--clr-navy);
  border: 0;
  padding: 16px 24px;
  font-family: var(--font-body);
  font-weight: 900;
  font-size: 0.875rem;
  line-height: 1.2;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  cursor: pointer;
  transition: background-color var(--transition), color var(--transition);
}

.signup__panel #mc_embed_signup input[type="submit"]:hover,
.signup__panel #mc_embed_signup input[type="submit"]:focus-visible {
  background: var(--clr-navy);
  color: var(--clr-white);
}

/* Inline validation mc-validate.js writes into the field group. */
.signup__panel #mc_embed_signup div.mce_inline_error {
  margin: 4px 0 0;
  padding: 0;
  background: none;
  font-size: 0.75rem;
  font-weight: 500;
  color: #b3261e;
}

.signup__panel #mc_embed_signup input.mce_inline_error {
  border-color: #b3261e;
}

.signup__panel #mc_embed_signup #mce-responses .response {
  margin: 16px 0 0;
  padding: 0;
  font-size: 0.875rem;
  line-height: 1.6;
}

.signup__panel #mc_embed_signup #mce-error-response {
  color: #b3261e;
}

.signup__panel #mc_embed_signup #mce-success-response {
  color: var(--clr-navy);
  font-weight: 700;
}

/* ===========================================================================
   BENEFIT ROWS AS BUTTONS

   A Stay Involved benefit row with a Link renders as a button instead of
   plain text. Rows without one are untouched - every rule here is scoped to
   .benefit--button, which only the linked branch emits.
   =========================================================================== */

/*
 * The <li> stops being the flex ROW and becomes a flex CONTAINER, so the
 * anchor inside sizes to its own content instead of stretching the full
 * column. Three buttons of differing widths read as a list of links; three
 * full-width bars would compete with the SUBSCRIBE button opposite.
 */
.benefit--button {
  display: flex;
}

.benefit__btn {
  /*
   * .btn is inline-flex with a 10px gap; this keeps the 16px icon/label gap
   * the unlinked rows use so linked and unlinked rows stay visually aligned.
   */
  gap: 16px;
  max-width: 100%;
  padding: 12px 24px;
  text-align: left;
  /*
   * .btn sets white-space: nowrap so short labels never break. These labels
   * are full sentences - "Volunteer With The Campaign" at 1.25rem overflows
   * a 390px screen - so wrapping is re-enabled here only.
   */
  white-space: normal;
}

/*
 * The icon is teal on the plain rows, which sits at roughly 1.6:1 on the gold
 * button. It takes the button's own text colour instead, and follows it
 * through the hover swap.
 */
.benefit--button .benefit__icon-wrap {
  color: inherit;
}

/*
 * .benefit__label carries its own display font, size and tracking, and wins
 * over .btn inside the anchor. That is deliberate - the button keeps the
 * label typography the design already uses for these rows rather than
 * dropping to the 0.875rem/0.15em button ramp.
 */

@media (max-width: 575px) {
  .benefit__btn {
    padding: 12px 18px;
  }

  .benefit--button .benefit__icon {
    width: 32px;
    height: 32px;
  }
}

/*
 * Buttons in the content + embed panel follow the same edge the embed does,
 * so a right-hand panel stays right-aligned on desktop.
 */
.content-embed__buttons {
  max-width: 28rem;
}

.content-embed__grid--panel-right .content-embed__buttons {
  margin-inline-start: auto;justify-content: end;
}

.content-embed__grid--panel-left .content-embed__buttons {
  margin-inline-start: 0;
  margin-inline-end: auto;
}

/* Only needed when a panel carries buttons AND an embed. */
.content-embed__buttons + .content-embed__embed {
  margin-top: 24px;
}
@media (max-width: 991px) {
  .content-embed__grid--panel-right .content-embed__buttons {
    margin-inline-start: 0;justify-content: start;
  }
}