/* ============================================================
   site.css, nonprofit-layout

   STRUCTURE ONLY. Shared by every client on this layout.
   No hex value, no typeface name, no client word lives here.
   Everything brand shaped is a custom property read from the
   theme file. If a change cannot be made in a theme file it
   belongs to EVERY client using this layout, so think twice.
   ============================================================ */

/* ---------- reset ---------- */

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

/* --ground and --fg exist because --paper and --ink were each doing two
   jobs. --paper was the page background AND the text colour sitting on a
   dark band. --ink was the body text AND the ground of .band--ink. On a
   light theme both readings agree, so nothing showed. On a DARK theme they
   fight, and flipping the values breaks four bands at once. These two names
   carry the page's own ground and text, nothing else. A light theme sets
   them to --paper and --ink and nothing moves. */
body {
  margin: 0;
  background: var(--ground);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.65;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
}

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

a { color: inherit; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  line-height: 1.08;
  letter-spacing: var(--display-tracking);
  margin: 0;
  text-wrap: balance;
}

p { margin: 0; }

/* figure carries a 40px UA margin. It is the single most common reason a
   card image looks inset for no reason. */
figure { margin: 0; }

ul { margin: 0; padding: 0; list-style: none; }

:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- rhythm ---------- */

.wrap {
  width: min(100% - 2.5rem, var(--measure-wide));
  margin-inline: auto;
}

.wrap--tight { width: min(100% - 2.5rem, var(--measure-tight)); }

/* ONE NUMBER SETS THE WHOLE PAGE RHYTHM. Every gap between two sections is
   this value twice, because the band above pays half and the band below pays
   half. The hero's bottom and the footer's top are driven off the same
   token, which is the only way the first gap and the last gap match the
   seven in the middle. Measured, not guessed: before this the hero to give
   gap was 264px, the middle was 224px and the footer was 184px. */
.band { padding-block: var(--band-space); position: relative; }

/* THE BAND THAT FOLLOWS A LOGO ROW NEEDS MORE AIR ABOVE IT THAN THE TOKEN GIVES.
   Every other band on this page ends in TEXT, which carries its own settled
   baseline and descender space, so one --band-space either side reads correct.
   The proof band ends in .partners__list, a row of hard edged images flush to
   the bottom of their boxes, and the founder band opens with a large photo.
   Hard edge against hard edge collapses the gap optically while it measures the
   same. Put this on any band that comes straight after a logo row. */
.band--after-logos { padding-block-start: calc(var(--band-space) * 1.9); }

.band--ink   { background: var(--ink); color: var(--paper); }
.band--deep  { background: var(--ink-deep); color: var(--paper); }
.band--tint  { background: var(--tint); }
.band--paper { background: var(--ground); }

/* THE HOLE. Reads as paper but is transparent, so the fixed .markdrop layer
   shows through it. Every other ground is solid and covers the mark, so
   which bands get this class is what makes the mark appear, disappear and
   appear again on the way down. A COMPOSITION choice, not a colour one.

   NEVER put it on the first band under the header. A giant mark landing
   directly below the lockup reads as a second, broken logo rather than as a
   backdrop. Start it mid page, after at least one solid band. */
.band--open { background: transparent; }

.band--ink a, .band--deep a { color: var(--paper); }

/* A band head is capped at the text measure, so on a wide screen it hugs one
   side and leaves a hole on the other. --head-inline decides which. `0 auto`
   pins it left, `auto` centres it. The eyebrow's flex line has to follow, or
   a centred heading sits under a label that is still ranged left. */
.band__head {
  max-width: var(--measure-text);
  margin-bottom: clamp(2.25rem, 4vw, 3.25rem);
  margin-inline: var(--head-inline);
  text-align: var(--head-align);
}

.band__head .eyebrow { justify-content: var(--head-justify); }

/* The mirrored rule only exists when the eyebrow is centred. Left ranged it
   is capped at 0 and never draws. */
.band__head .eyebrow::before {
  content: "";
  flex: 1;
  height: 1px;
  background: currentColor;
  opacity: 0.35;
  max-width: var(--eyebrow-rule-lead);
}

.band__head .lede { margin-inline: var(--head-inline); }

.eyebrow {
  font-family: var(--font-body);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.9rem;
  display: flex;
  align-items: center;
  gap: 0.7rem;
}

.eyebrow::after {
  content: "";
  flex: 1;
  height: 1px;
  background: currentColor;
  opacity: 0.35;
  max-width: 4.5rem;
}

.hero .eyebrow, .band--ink .eyebrow, .band--deep .eyebrow { color: var(--accent-on-dark); }

h1 { font-size: clamp(2.5rem, 6.4vw, 4.4rem); }
h2 { font-size: clamp(1.95rem, 4.2vw, 3rem); }
h3 { font-size: clamp(1.15rem, 1.9vw, 1.4rem); line-height: 1.2; }

.lede {
  font-size: clamp(1.05rem, 1.6vw, 1.25rem);
  line-height: 1.6;
  color: var(--ink-soft);
  margin-top: 1.15rem;
  max-width: var(--measure-text);
}

.band--ink .lede, .band--deep .lede { color: var(--paper-soft); }

/* ---------- the mark backdrop ---------- */

/* THE MARK DOES NOT MOVE. One FIXED layer pinned to the viewport, the page
   scrolls over it. Content slides, the mark holds still, so it reads as
   sitting behind the building rather than printed on a band. A repeating
   background or a parallax offset would both cost a scroll listener and
   neither looks like this.

   See .band--open for which bands let it through, and for the one place it
   must never be allowed to show.

   aria-hidden and pointer-events because it carries no information and must
   never eat a click. The mark is announced once, in the header lockup. */
.markdrop {
  position: fixed;
  inset: 0;
  z-index: -1;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  pointer-events: none;
}

.markdrop img {
  width: min(var(--markdrop-vw), var(--markdrop-cap));
  max-width: none;
  opacity: var(--markdrop-opacity);
}

/* A theme that does not want the effect sets --markdrop-opacity to 0. */
@media print { .markdrop { display: none; } }

/* ---------- buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  font-family: var(--font-body);
  font-size: 0.9375rem;
  font-weight: 650;
  letter-spacing: 0.01em;
  padding: 0.95rem 1.7rem;
  border-radius: var(--radius-btn);
  border: 2px solid transparent;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.16s ease, background-color 0.16s ease, border-color 0.16s ease, color 0.16s ease;
}

.btn:hover { transform: translateY(-2px); }

.btn--primary {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: var(--accent);
  box-shadow: var(--shadow-btn);
}

.btn--primary:hover { background: var(--accent-bright); border-color: var(--accent-bright); }

/* A theme whose accent is dark has no working primary button on a dark band.
   These two properties let the theme name a second fill for exactly that case.
   A theme that does not care sets them equal to the accent and nothing moves. */
.site-header .btn--primary,
.hero .btn--primary,
.band--ink .btn--primary,
.band--deep .btn--primary {
  background: var(--btn-on-dark-bg);
  border-color: var(--btn-on-dark-bg);
  color: var(--btn-on-dark-ink);
}

.site-header .btn--primary:hover,
.hero .btn--primary:hover,
.band--ink .btn--primary:hover,
.band--deep .btn--primary:hover {
  background: var(--btn-on-dark-hover);
  border-color: var(--btn-on-dark-hover);
}

.btn--ghost { background: transparent; border-color: var(--rule-strong); color: inherit; }

.btn--ghost:hover { border-color: var(--accent); color: var(--accent); }

.band--ink .btn--ghost, .band--deep .btn--ghost { border-color: var(--rule-on-dark); }

.band--ink .btn--ghost:hover, .band--deep .btn--ghost:hover {
  border-color: var(--accent-on-dark);
  color: var(--accent-on-dark);
}

.btn--lg { padding: 1.1rem 2.1rem; font-size: 1rem; }

.btn-row { display: flex; flex-wrap: wrap; gap: 0.85rem; margin-top: 2rem; }

/* A band's own button row follows the band head. The hero keeps its own
   alignment, which is why this is scoped to .band and not to .btn-row. */
.band > .wrap > .btn-row { justify-content: var(--head-justify); }

/* ---------- header ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 60;
  background: var(--header-bg);
  border-bottom: 1px solid var(--rule-on-dark);
  backdrop-filter: saturate(140%) blur(10px);
}

.site-header__inner {
  width: min(100% - 2.5rem, var(--measure-wide));
  margin-inline: auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem;
  min-height: var(--header-h);
}

.lockup {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  text-decoration: none;
  color: var(--paper);
}

.lockup__mark { width: var(--mark-size); height: var(--mark-size); object-fit: contain; }

.lockup__name {
  display: block;
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  font-size: 1.0625rem;
  line-height: 1.05;
  letter-spacing: var(--display-tracking);
}

.lockup__sub {
  display: block;
  font-size: 0.6875rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--paper-faint);
  margin-top: 0.28rem;
}

.site-nav { display: flex; align-items: center; gap: 1.9rem; }

.site-nav a {
  color: var(--paper-soft);
  text-decoration: none;
  font-size: 0.9375rem;
  font-weight: 500;
  transition: color 0.16s ease;
}

.site-nav a:hover { color: var(--accent-on-dark); }

/* ---- The programmes menu in the header ----
   Hover opens it on a pointer, tap opens it on a touch screen (site.js). The
   ::before is a bridge across the gap between the label and the panel: without
   it the pointer leaves the group on the way down and the menu shuts under the
   cursor. On the narrow layout it stops being a panel and just indents. */
.nav-group { position: relative; display: flex; align-items: center; }
.nav-group__btn {
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: var(--paper-soft);
  font: inherit;
  font-size: 0.9375rem;
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  transition: color 0.16s ease;
}
.nav-group__btn:hover,
.nav-group[data-open="true"] .nav-group__btn { color: var(--accent-on-dark); }
.nav-group__cav { font-size: 0.7em; line-height: 1; transition: transform 0.16s ease; }
.nav-group[data-open="true"] .nav-group__cav { transform: rotate(180deg); }
.nav-group__menu {
  position: absolute;
  top: calc(100% + 0.9rem);
  left: -1.1rem;
  display: none;
  flex-direction: column;
  min-width: 15.5rem;
  background: var(--ink-deep);
  border: 1px solid var(--rule-on-dark);
  border-radius: var(--radius-card);
  padding: 0.45rem 0;
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.45);
  z-index: 60;
}
.nav-group__menu::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -0.95rem;
  height: 0.95rem;
}
.nav-group:hover .nav-group__menu,
.nav-group[data-open="true"] .nav-group__menu { display: flex; }
.nav-group__menu a { padding: 0.62rem 1.1rem; font-size: 0.9375rem; }
.nav-group__menu a:hover { background: #ffffff0d; }

.site-header .btn { padding: 0.7rem 1.35rem; font-size: 0.875rem; }

.nav-toggle {
  display: none;
  background: none;
  border: 1px solid var(--rule-on-dark);
  border-radius: var(--radius-btn);
  color: var(--paper);
  padding: 0.55rem 0.85rem;
  font-size: 0.8125rem;
  font-weight: 600;
  cursor: pointer;
}

/* ---------- hero ---------- */

.hero { position: relative; background: var(--ink-deep); color: var(--paper); overflow: hidden; }

/* The hero art is usually a photograph, so the default is cover. A theme can
   hand it a LOGO instead, and a logo run through cover gets cropped to a
   meaningless slab, so the fit, the side it stages to and its inset are all
   theme decisions. The mask is what fades its near edge into the ground so
   the headline never has to fight it. */
.hero__media {
  position: absolute;
  inset: 0;
  padding: var(--hero-media-inset);
  -webkit-mask-image: var(--hero-media-mask);
  mask-image: var(--hero-media-mask);
}

.hero__media img {
  width: 100%;
  height: 100%;
  object-fit: var(--hero-media-fit);
  object-position: var(--hero-media-pos);
}

.hero__scrim { position: absolute; inset: 0; background: var(--hero-scrim); }

.hero__inner {
  position: relative;
  width: min(100% - 2.5rem, var(--measure-wide));
  margin-inline: auto;
  padding-block: var(--hero-space-top) var(--band-space);
  max-width: none;
}

.hero__copy { max-width: 46rem; }

.hero h1 { margin-top: 0.4rem; }

.hero .lede { color: var(--paper-soft); font-size: clamp(1.1rem, 1.8vw, 1.35rem); max-width: 38rem; }

.hero__note {
  margin-top: 1.6rem;
  font-size: 0.875rem;
  color: var(--paper-faint);
  display: flex;
  align-items: center;
  gap: 0.55rem;
}

.hero__note::before {
  content: "";
  width: 1.75rem;
  height: 1px;
  background: var(--accent-on-dark);
  flex: none;
}

/* ---------- pull quote band ---------- */

.pull { display: grid; gap: clamp(2rem, 4vw, 3.5rem); grid-template-columns: 1.15fr 1fr; align-items: center; }

.pull__quote {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  font-size: clamp(1.5rem, 3vw, 2.25rem);
  line-height: 1.24;
  letter-spacing: var(--display-tracking);
  text-wrap: balance;
}

.pull__mark {
  display: block;
  font-family: var(--font-display);
  font-size: 3.5rem;
  line-height: 0.6;
  color: var(--accent);
  margin-bottom: 0.6rem;
}

.pull__attrib {
  margin-top: 1.4rem;
  font-size: 0.875rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.pull__body p + p { margin-top: 1.1rem; }

/* ---------- give tiers ---------- */

.tiers {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13.5rem, 1fr));
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: var(--radius-card);
  overflow: hidden;
}

.tier {
  background: var(--card-bg);
  padding: clamp(1.6rem, 2.6vw, 2.15rem);
  text-align: var(--card-align);
}

.tier__amount {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  font-size: clamp(1.9rem, 3.4vw, 2.6rem);
  line-height: 1;
  letter-spacing: var(--display-tracking);
  color: var(--accent-deep);
}

.tier__label { margin-top: 0.85rem; font-size: 1rem; line-height: 1.45; color: var(--ink-soft); }

.tiers-note {
  margin-top: 1.5rem;
  font-size: 0.875rem;
  color: var(--ink-faint);
  max-width: var(--measure-text);
  margin-inline: var(--head-inline);
  text-align: var(--head-align);
}

/* ---------- programs ---------- */

/* Five cards on a six column grid. Three spanning two, then two
   spanning three, so the last row fills instead of orphaning a
   card at the end of a row of four. auto-fit cannot do this and
   the 4 + 1 it produces reads like a mistake. */
.cards { display: grid; grid-template-columns: repeat(6, 1fr); gap: 1.25rem; }

.cards > :nth-child(-n+3) { grid-column: span 2; }
.cards > :nth-child(n+4)  { grid-column: span 3; }

@media (max-width: 64rem) {
  .cards { grid-template-columns: 1fr; }
  .cards > :nth-child(-n+3), .cards > :nth-child(n+4) { grid-column: auto; }
}

.card {
  background: var(--card-bg);
  border: 1px solid var(--rule);
  border-radius: var(--radius-card);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: border-color 0.16s ease, transform 0.16s ease;
}

/* Optional image slot. A card without one still works, the body just
   sits at the top of the box. Delete the figure, change nothing else. */
.card__media { aspect-ratio: 16 / 10; background: var(--tint); }

.card__media img { width: 100%; height: 100%; object-fit: cover; }

/* --card-align and --card-items move together. text-align handles the type,
   align-items handles the flex children, and a card centred on one but not
   the other looks like a bug rather than a choice. */
.card__body {
  padding: clamp(1.5rem, 2.4vw, 2rem);
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  flex: 1;
  text-align: var(--card-align);
  align-items: var(--card-items);
}

.card:hover { border-color: var(--accent); transform: translateY(-3px); }

.card__idx {
  font-family: var(--font-body);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  color: var(--accent);
}

.card p { color: var(--ink-soft); font-size: 0.9875rem; }

/* ---------- the numbered flow, three steps ---------- */

.flow { display: grid; grid-template-columns: 1fr auto 1fr auto 1fr; align-items: start; gap: 1.5rem; }

.step {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  text-align: var(--card-align);
  align-items: var(--card-items);
}

.step__n {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  font-size: 1rem;
  letter-spacing: 0.06em;
  color: var(--accent-on-dark);
}

.step p { color: var(--paper-soft); font-size: 0.9875rem; }

.flow__chev {
  align-self: center;
  color: var(--rule-on-dark);
  font-size: 1.35rem;
  line-height: 1;
  padding-top: 0.4rem;
  user-select: none;
}

/* ---------- proof ---------- */

/* NO BOX. A 1px grid gap over a rule colour draws a table, and a table is
   the one thing a proof band must not look like: it reads as data somebody
   compiled rather than as three things that happened. Open columns with a
   single hairline between them, and no fill, so the backdrop mark runs
   straight through. */
.facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: 0;
}

.fact {
  display: flex;
  flex-direction: column;
  padding: clamp(0.5rem, 1.5vw, 1rem) clamp(1.5rem, 3vw, 2.75rem);
  text-align: var(--card-align);
  border-inline-start: 1px solid var(--rule);
}

/* The first column in each row has nothing to its left to divide it from. */
.fact:first-child { border-inline-start: 0; }

@media (max-width: 62rem) {
  .fact { border-inline-start: 0; border-block-start: 1px solid var(--rule); padding-block: 1.75rem; }
  .fact:first-child { border-block-start: 0; padding-block-start: 0; }
}

/* --fg, not --ink. --ink is a BAND GROUND on this layout, so on a dark theme
   a number painted with it lands near black on near black and disappears.
   This is the same double booking --ground and --fg were split out to fix,
   and the proof band was the last place still reading the wrong one. */
.fact__n {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  font-size: clamp(2.6rem, 5.4vw, 4rem);
  line-height: 0.95;
  letter-spacing: -0.03em;
  color: var(--fg);
}

.fact__l {
  margin-top: 0.9rem;
  font-size: 1rem;
  line-height: 1.5;
  color: var(--ink-soft);
  /* Pushes every source line to the bottom of its column, so three labels of
     different lengths still leave the sources on one line across the row. */
  flex: 1;
}

/* The source is the point of the band, not a footnote, but it must never
   compete with the number. Small, spaced, and lifted off the label by its
   own rule so it reads as a citation. */
.fact__src {
  margin-top: 1.1rem;
  padding-top: 0.85rem;
  border-top: 1px solid var(--rule);
  font-size: 0.75rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* The sponsor row is a second block inside the proof band, so it gets HALF
   the page rhythm. A full band space here would read as a section break and
   the row would look orphaned from the numbers it belongs to. */
.partners { margin-top: calc(var(--band-space) * 0.6); }

.partners__label {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 1.25rem;
  text-align: var(--head-align);
}

.partners__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: var(--head-justify);
  gap: clamp(1.75rem, 4vw, 3.25rem);
}

/* No chip, no box. A partner row is marks sitting on the page. The height
   is the only thing held constant, because logos arrive at every aspect
   ratio and matching their WIDTHS makes the wide ones tiny. */
.partners__list li { display: flex; align-items: center; }

.partners__list img {
  height: var(--partner-h);
  width: auto;
  max-width: 15rem;
  object-fit: contain;
  /* An SVG with no intrinsic pixel size collapses to a token square when
     only its height is set. Naming a minimum width lets a wide mark stay
     wide and a round one stay round. */
  min-width: var(--partner-h);
  filter: var(--partner-filter);
  opacity: var(--partner-opacity);
  transition: opacity 0.16s ease;
}

.partners__list li:hover img { opacity: 1; }

/* ---------- founder ---------- */

/* THE PHOTO IS SIZED BY THE TEXT, NOT BY A RATIO. A fixed 4/5 portrait next to a
   centre aligned text column overhung it by 67px at the top AND 67px at the bottom
   at 1440, so neither edge lined up with anything and the block read lopsided. The
   ratio is dropped on desktop and the media stretches to the grid row instead, so
   its top sits on the eyebrow and its bottom sits on the signature no matter how
   long the copy runs. The mobile override below puts a ratio back once the columns
   stack, because there is no text column left to measure against. */
.founder { display: grid; grid-template-columns: 0.85fr 1.15fr; gap: clamp(2rem, 5vw, 4rem); align-items: stretch; }

.founder__media { border-radius: var(--radius-card); overflow: hidden; background: var(--tint); }

.founder__media img { width: 100%; height: 100%; object-fit: cover; }

.founder__body p + p { margin-top: 1.1rem; }

.founder__body p { color: var(--ink-soft); }

.founder__quote {
  margin-top: 1.75rem;
  padding-left: 1.35rem;
  border-left: 3px solid var(--accent);
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  font-size: clamp(1.15rem, 2vw, 1.5rem);
  line-height: 1.3;
  letter-spacing: var(--display-tracking);
  color: var(--ink);
}

.founder__sig { margin-top: 1.5rem; font-size: 0.875rem; letter-spacing: 0.09em; text-transform: uppercase; color: var(--ink-faint); }

/* ---------- closing call ---------- */

.close { text-align: center; max-width: var(--measure-text); margin-inline: auto; }

.close .lede { margin-inline: auto; }

.close .btn-row { justify-content: center; }

.close__legal { margin-top: 2.25rem; font-size: 0.8125rem; color: var(--paper-faint); line-height: 1.6; }

/* ---------- footer ---------- */

.site-footer { background: var(--ink-deep); color: var(--paper-soft); padding-block: var(--band-space) 2rem; }

.footer-grid { display: grid; grid-template-columns: 1.6fr 1fr 1fr; gap: clamp(2rem, 4vw, 3.5rem); }

/* THE FOOTER RUNS EVEN COLUMNS WHEN THE BRAND BLOCK IS DROPPED. The default
   `1.6fr 1fr 1fr` exists to give the name and blurb room. Take that column out
   and the wide track becomes a hole on the left. Set 2026-08-29 on the OCF
   footer, which runs Find us, Contact us and Follow with nothing in front. */
.footer-grid--even { grid-template-columns: 1fr 1fr 1fr; }

/* EVERY COLUMN IS CENTRED ON ITS OWN TRACK. This replaces a left, centre,
   right arrangement from earlier the same day, which squared the block edges
   with the legal row beneath but left each heading sitting off to the side of
   the thing it names. Seth 2026-08-29: "center the words above the icons and
   the email and any of the other words in any of the other columns". Centring
   inside the track puts Follow over its own marks and Contact us over its own
   address, and the columns still balance because the tracks are even. The
   reset lives in the existing narrow query, NOT in a min-width twin: a
   `min-width: 62.0625rem` pair leaves a dead band at fractional viewport
   widths where neither rule applies. Same breakpoint, one direction, no gap. */
.footer-grid--even > * { text-align: center; }

/* THE FOLLOW COLUMN IS A ROW OF BRAND MARKS, centred under its own heading.
   Scoped to the even footer because the default footer still runs its social
   row flush right against a wide brand column. Set 2026-08-29. */
.social-row { display: flex; align-items: center; gap: 0.7rem; justify-content: flex-end; }
.footer-grid--even .social-row { justify-content: center; }

/* THE MARKS ARE FULL BRAND COLOUR, SO THEY CARRY NO RING. A grey ring around a
   blue disc and a gradient disc reads as a border someone forgot to remove.
   The svg IS the button, sized to the old ring so the row keeps its rhythm. */
.social-ico {
  display: inline-flex;
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 999px;
  transition: transform 0.16s ease, opacity 0.16s ease;
}

.social-ico svg { width: 100%; height: 100%; display: block; border-radius: 999px; }

.social-ico:hover { transform: translateY(-2px); }

.social-ico:focus-visible { outline: 2px solid var(--accent-on-dark); outline-offset: 3px; }

/* The footer button rides a 0.8125rem base line, so the full size button is far
   too heavy next to two 2.6rem marks. */
.btn--sm { padding: 0.7rem 1.35rem; font-size: 0.875rem; }

.footer-grid h3 {
  font-family: var(--font-body);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--paper-faint);
  margin-bottom: 1rem;
}

.footer-grid p, .footer-grid li { font-size: 0.9375rem; line-height: 1.7; }

.footer-grid li a { text-decoration: none; color: var(--paper-soft); }

.footer-grid li a:hover { color: var(--accent-on-dark); }

.footer-blurb { color: var(--paper-faint); max-width: 26rem; margin-top: 1rem; }

/* THE WHOLE CARD IS THE HIT AREA. The link sits on the heading and this layer
   stretches it over the card, so a click anywhere on the pad opens the page
   while the accessibility tree still holds exactly one link named by the
   heading. Set 2026-08-29 on Seth's ask, replacing a "Give to this" line under
   the copy which he did not want. The card needs `position: relative` for the
   layer to have something to fill, and the whole card lifts on hover so it
   reads as pressable rather than as a panel with a link buried in it. */
.card:has(.card__hit) { position: relative; cursor: pointer; }

.card__hit { color: inherit; text-decoration: none; }

.card__hit::after { content: ""; position: absolute; inset: 0;
  border-radius: var(--radius-card); }

.card:has(.card__hit):hover { border-color: var(--rule-strong); }

.card:has(.card__hit):hover .card__hit { color: var(--accent-on-dark); }

/* The stretched layer takes the focus ring, so it has to draw one itself. */
.card__hit:focus-visible { outline: none; }

.card__hit:focus-visible::after { outline: 3px solid var(--accent); outline-offset: 3px; }

/* A builder's mark set in the footer line. Sized in `em` so it rides the
   line it sits on rather than a fixed pixel height, which is the only way it
   stays put when the base line resizes. */
.built-by {
  display: inline-block;
  height: 1.05em;
  width: auto;
  vertical-align: -0.2em;
  margin-inline-start: 0.4rem;
  opacity: 0.8;
}

.site-footer__base {
  margin-top: clamp(2.5rem, 4vw, 3.5rem);
  padding-top: 1.6rem;
  border-top: 1px solid var(--rule-on-dark);
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.5rem;
  justify-content: space-between;
  font-size: 0.8125rem;
  color: var(--paper-faint);
}

/* ---------- narrow ---------- */

@media (max-width: 62rem) {
  .pull { grid-template-columns: 1fr; }
  .founder { grid-template-columns: 1fr; }
  .founder__media { aspect-ratio: 16 / 10; max-height: 22rem; }
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .footer-grid--even > * { text-align: left; }
  .social-row, .footer-grid--even .social-row { justify-content: flex-start; }
  .flow { grid-template-columns: 1fr; gap: 1.75rem; }
  .flow__chev { display: none; }
}

@media (max-width: 48rem) {
  .site-nav {
    display: none;
    position: absolute;
    top: var(--header-h);
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    background: var(--ink-deep);
    border-bottom: 1px solid var(--rule-on-dark);
    padding: 0.5rem 1.25rem 1.25rem;
  }
  .site-nav[data-open="true"] { display: flex; }
  .site-nav a { padding: 0.85rem 0; width: 100%; border-bottom: 1px solid var(--rule-on-dark); }
  .nav-group { display: block; width: 100%; }
  .nav-group__btn {
    width: 100%;
    padding: 0.85rem 0;
    justify-content: space-between;
    border-bottom: 1px solid var(--rule-on-dark);
  }
  .nav-group__menu {
    position: static;
    min-width: 0;
    background: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    padding: 0 0 0 0.9rem;
  }
  .nav-group__menu::before { display: none; }
  .nav-group:hover .nav-group__menu { display: none; }
  .nav-group[data-open="true"] .nav-group__menu { display: flex; }
  .nav-group__menu a { padding: 0.72rem 0; }
  .nav-toggle { display: block; }
  .site-header .btn { display: none; }
  .footer-grid { grid-template-columns: 1fr; }
  .btn-row .btn { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition-duration: 0.01ms !important; }
  .btn:hover, .card:hover { transform: none; }
}

/* ---------- the capture band under the hero ----------
   Seth 2026-08-29 asked for the shape elyisius.com uses under its opening
   screen, and on his call WITHOUT the label and note column beside it, so the
   fields take the whole width. It is a BAND, not a card: a boxed panel inside
   a hero reads as a second page laid on the first, which is why it runs edge
   to edge with the wrap inside it and takes its own ground and a top rule.
   Only builds that fill HERO_CAPTURE get one, the slot is empty everywhere
   else and the whole element never renders. */
.hero__capture { background: var(--tint); border-top: 1px solid var(--rule); }

.capture {
  width: min(100% - 2.5rem, var(--measure-wide));
  margin-inline: auto;
  padding-block: clamp(1.15rem, 2.4vw, 1.7rem);
}

/* THE LINE ABOVE THE FIELDS IS THE REASON TO FILL THEM. Set above the label
   size so it reads as the band's own heading and not as a fourth label. */
.capture__ask {
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 2.2vw, 1.6rem);
  color: var(--paper);
  margin-bottom: clamp(0.75rem, 1.6vw, 1.1rem);
}

/* Three even fields and a button that sizes to its own word. */
.capture__form {
  display: grid;
  gap: 0.75rem 1rem;
  grid-template-columns: repeat(3, minmax(0, 1fr)) auto;
  align-items: end;
}

.capture__form label { display: grid; gap: 0.35rem; }
.capture__form label span { font-size: 0.8125rem; font-weight: 600; color: var(--paper); }

/* 16px on the field itself, never smaller: iOS Safari zooms the whole page on
   focus for anything under 16px, and a hero that jumps on first tap reads as
   broken. min-height carries the 44px tap target. The message box starts at
   one row so the band stays a single line, and grows as it is typed into. */
.capture__form input {
  font: inherit;
  font-size: 1rem;
  color: var(--paper);
  background: #ffffff0f;
  border: 1px solid var(--rule);
  border-radius: var(--radius-btn);
  padding: 0.75rem 0.9rem;
  /* ONE PINNED HEIGHT so every box in the row measures the same and the labels
     above them sit on one line. */
  height: 3rem;
  min-height: 44px;
  width: 100%;
}


.capture__form input:focus-visible {
  outline: 2px solid var(--accent-on-dark);
  outline-offset: 2px;
  border-color: var(--accent-on-dark);
}

.capture__form .btn { min-height: 44px; white-space: nowrap; }
.capture__form .btn[disabled] { opacity: 0.6; cursor: default; }

.capture__status { grid-column: 1 / -1; font-size: 0.875rem; color: var(--paper-soft); }
.capture__status:empty { display: none; }

/* The honeypot is for a robot's eyes only. Off canvas rather than display
   none, because some bots skip anything that is not rendered. */
.capture__honey { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }

.capture__done { text-align: center; }
.capture__done .capture__label {
  font-size: 0.8125rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--accent-on-dark);
}
.capture__done .capture__note { margin-top: 0.5rem; color: var(--paper-soft); }

@media (max-width: 62rem) {
  .capture__form { grid-template-columns: 1fr 1fr; }
  .capture__form .btn { grid-column: 1 / -1; justify-self: stretch; }
}

@media (max-width: 40rem) {
  .capture__form { grid-template-columns: 1fr; }
}

/* THE CARD SAYS WHAT THE CLICK DOES. Plain text, never a link: the card holds
   exactly one anchor, on its heading, with an invisible layer stretched over
   the whole card. It picks up the accent on hover with the rest of the card so
   it reads as part of the same target and not as a second thing to aim at. */
.card__cta {
  margin-top: 0.85rem;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-on-dark);
}

.card:hover .card__cta { color: var(--accent-bright); }

/* Supporters band, the backers page. One column so a name and what they did
   never split across a gutter, which is what an orphan card looks like here.
   Rules between, not boxes: a card grid of eight reads as a pricing table. */
.backers { max-width: var(--measure-text); margin: 2rem auto 0; }
.backer { padding: 1.35rem 0; border-top: 1px solid rgba(255,255,255,.12); }
.backer:first-child { border-top: 0; padding-top: .5rem; }
.backer__name { margin: 0 0 .4rem; font-size: 1.06rem; line-height: 1.3; }
.backer__what { margin: 0; }

/* The one readable line under the partner logos, and the door into the
   backers page. Centred on the row it belongs to, not flush left. */
.partners__more { margin: 1.25rem 0 0; text-align: center; font-size: .95rem; }

/* A page with no banner is not holding a gap for one. */
.prog-hero--nobanner { padding-top: 2.5rem; }
.prog-hero--nobanner .prog-hero__head { margin-top: 0; }

/* Names with no published detail. A plain list, never dressed up as a claim. */
.backers-also { max-width: var(--measure-text); margin: 2.25rem auto 0;
  padding-top: 1.5rem; border-top: 1px solid rgba(255,255,255,.12); }
.backers-also h3 { margin: 0 0 .6rem; font-size: .82rem; letter-spacing: .09em;
  text-transform: uppercase; opacity: .72; }
.backers-also ul { margin: 0; padding: 0; list-style: none; }
.backers-also li { padding: .3rem 0; }

/* Areas we serve. ONE quiet line across the footer of the five programme
   pages, never a column. As a column it wrapped under Find us and became a
   seven item vertical stack, which reads as a link farm. Across, it reads as
   a place list, which is what it is. Centred to match footer-grid--even. */
.footer-areas { margin-top: 2.25rem; padding-top: 1.5rem;
  border-top: 1px solid rgba(255,255,255,.09); text-align: center; }
.footer-areas__label { display: block; font-size: .72rem; letter-spacing: .1em;
  text-transform: uppercase; opacity: .55; margin-bottom: .55rem; }
.footer-areas__list { display: flex; flex-wrap: wrap; justify-content: center;
  gap: .35rem 0; font-size: .875rem; }
.footer-areas__list a { text-decoration: none; opacity: .78; padding: 0 .7rem; }
.footer-areas__list a + a { border-left: 1px solid rgba(255,255,255,.16); }
.footer-areas__list a:hover { opacity: 1; text-decoration: underline; }
