/* =========================================================================
   Lions 301-C

   This file may ONLY alias tokens declared in theme.json. It must never
   contain a hex colour, a font stack, or a raw spacing value. If a value is
   missing, add it to theme.json first and alias it here.

   Sections:
     1. Token aliases
     2. Reset and base
     3. Layout primitives and bands
     4. Section rhythm by adjacency
     5. Components
     6. Responsive
   ========================================================================= */

/* ---------- 1. Token aliases ------------------------------------------- */

:root {
  /* Colour */
  --c-brand:       var(--wp--preset--color--brand);
  --c-brand-deep:  var(--wp--preset--color--brand-deep);
  --c-gold:        var(--wp--preset--color--gold);
  --c-gold-ink:    var(--wp--preset--color--gold-ink);
  --c-ink:         var(--wp--preset--color--ink);
  --c-ink-deep:    var(--wp--preset--color--ink-deep);
  --c-body:        var(--wp--preset--color--body);
  --c-muted:       var(--wp--preset--color--muted);
  --c-on-brand:    var(--wp--preset--color--on-brand);
  --c-steel:       var(--wp--preset--color--steel);
  --c-canvas:      var(--wp--preset--color--canvas);
  --c-tint:        var(--wp--preset--color--tint);
  --c-tint-warm:   var(--wp--preset--color--tint-warm);
  --c-line:        var(--wp--preset--color--line);
  --c-line-soft:   var(--wp--preset--color--line-soft);
  --c-line-blue:   var(--wp--preset--color--line-blue);
  --c-line-deep:   var(--wp--preset--color--line-deep);

  /* Type */
  --f-sans:  var(--wp--preset--font-family--sans);
  --f-serif: var(--wp--preset--font-family--serif);

  --t-micro:      var(--wp--preset--font-size--micro);
  --t-xs:         var(--wp--preset--font-size--xs);
  --t-sm:         var(--wp--preset--font-size--sm);
  --t-base:       var(--wp--preset--font-size--base);
  --t-md:         var(--wp--preset--font-size--md);
  --t-lg:         var(--wp--preset--font-size--lg);
  --t-xl:         var(--wp--preset--font-size--xl);
  --t-2xl:        var(--wp--preset--font-size--2-xl);
  --t-stat:       var(--wp--preset--font-size--stat);
  --t-display-sm: var(--wp--preset--font-size--display-sm);
  --t-display-md: var(--wp--preset--font-size--display-md);
  --t-display-lg: var(--wp--preset--font-size--display-lg);
  --t-display-xl: var(--wp--preset--font-size--display-xl);

  /* Spacing: the only vertical and horizontal steps allowed anywhere */
  --s-1: var(--wp--preset--spacing--1);
  --s-2: var(--wp--preset--spacing--2);
  --s-3: var(--wp--preset--spacing--3);
  --s-4: var(--wp--preset--spacing--4);
  --s-5: var(--wp--preset--spacing--5);
  --s-6: var(--wp--preset--spacing--6);
  --s-7: var(--wp--preset--spacing--7);

  /* Measure, leading, tracking */
  --m-prose:  var(--wp--custom--measure--prose);
  --m-narrow: var(--wp--custom--measure--narrow);
  --m-tight:  var(--wp--custom--measure--tight);
  --m-media:  var(--wp--custom--measure--media);
  --m-card:   var(--wp--custom--measure--card);
  --m-section-narrow: var(--wp--custom--measure--section-narrow);

  --lh-flat:    var(--wp--custom--leading--flat);
  --lh-tight:   var(--wp--custom--leading--tight);
  --lh-snug:    var(--wp--custom--leading--snug);
  --lh-heading: var(--wp--custom--leading--heading);
  --lh-normal:  var(--wp--custom--leading--normal);
  --lh-relaxed: var(--wp--custom--leading--relaxed);

  --tr-wide:    var(--wp--custom--tracking--wide);
  --tr-eyebrow: var(--wp--custom--tracking--eyebrow);
  --tr-widest:  var(--wp--custom--tracking--widest);
  --tr-tightest: var(--wp--custom--tracking--tightest);
  --tr-label: var(--wp--custom--tracking--label);

  /* Shape, depth */
  --r-sm:   var(--wp--custom--radius--sm);
  --r-xs:      var(--wp--custom--radius--xs);
  --r-md:   var(--wp--custom--radius--md);
  --r-lg:   var(--wp--custom--radius--lg);
  --r-pill: var(--wp--custom--radius--pill);

  --sh-card:   var(--wp--custom--shadow--card);
  --sh-raised: var(--wp--custom--shadow--raised);
  --sh-deep:   var(--wp--custom--shadow--deep);
  --sh-glyph:  var(--wp--custom--shadow--glyph);

  --scrim-soft:   var(--wp--custom--scrim--soft);
  --scrim-strong: var(--wp--custom--scrim--strong);
  --scrim-deep:   var(--wp--custom--scrim--deep);
  --scrim-none:   var(--wp--custom--scrim--none);
  --scrim-faint:  var(--wp--custom--scrim--faint);
  --scrim-hero-1: var(--wp--custom--scrim--hero-start);
  --scrim-hero-2: var(--wp--custom--scrim--hero-mid);
  --scrim-hero-3: var(--wp--custom--scrim--hero-end);
  --scrim-duo-navy:   var(--wp--custom--scrim--duo-navy);
  --scrim-duo-indigo: var(--wp--custom--scrim--duo-indigo);
  --scrim-duo-plum:   var(--wp--custom--scrim--duo-plum);
  --c-plum:           var(--wp--preset--color--plum);

  --hair-on-brand:      var(--wp--custom--hairline--on-brand);
  --hair-on-brand-soft: var(--wp--custom--hairline--on-brand-soft);
  --c-on-brand-bright:  var(--wp--custom--on-brand-bright);

  /* Structural sizes */
  --z-logo:        var(--wp--custom--size--logo);
  --z-logo-sm:     var(--wp--custom--size--logo-sm);
  --z-logo-foot:   var(--wp--custom--size--logo-footer);
  --z-icon:        var(--wp--custom--size--icon);
  --z-icon-sm:     var(--wp--custom--size--icon-sm);
  --z-gallery-row: var(--wp--custom--size--gallery-row);
  --z-marquee:     var(--wp--custom--size--marquee-logo);
  --z-date:        var(--wp--custom--size--date-chip);
  --z-event-card:  var(--wp--custom--size--event-card);
  --z-officer:      var(--wp--custom--size--officer);
  --z-officer-lead: var(--wp--custom--size--officer-lead);
  --z-officer-lead-card: var(--wp--custom--size--officer-lead-card);
  --z-officer-row: var(--wp--custom--size--officer-row);
  --z-tap: var(--wp--custom--size--tap);
  --z-control: var(--wp--custom--size--control);
  --z-bar: var(--wp--custom--size--bar);
  --z-bars: var(--wp--custom--size--bars);
  --z-lead-mark: var(--wp--custom--size--lead-mark);
  --z-lead-watermark: var(--wp--custom--size--lead-watermark);
  --scrim-card-foot: var(--wp--custom--scrim--card-foot);
  --scrim-card-mid:  var(--wp--custom--scrim--card-mid);
  --wm-lci: url("../img/lci-emblem.png");
  --z-officer-card:var(--wp--custom--size--officer-card);
  --z-stat-card:   var(--wp--custom--size--stat-card);
  --z-area-card:   var(--wp--custom--size--area-card);
  --z-photo-card:  var(--wp--custom--size--photo-card);
  --z-area-thumb:  var(--wp--custom--size--area-thumb);
  --z-cause-card:  var(--wp--custom--size--cause-card);
  --z-mark-wm:     var(--wp--custom--size--mark-watermark);
  --z-card-blur:   var(--wp--custom--size--card-blur);
  --z-hero-blur:   var(--wp--custom--size--hero-blur);
  --z-pin:         var(--wp--custom--size--pin);
  --z-pin-sm:      var(--wp--custom--size--pin-sm);
  --z-club-mark:   var(--wp--custom--size--club-mark);
  --z-club-col:    var(--wp--custom--size--club-col);
  --z-club-label:  var(--wp--custom--size--club-label);
  --z-club-field:  var(--wp--custom--size--club-field);
  --z-chev:        var(--wp--custom--size--chev);
  --z-submenu:     var(--wp--custom--size--submenu);
  --z-drawer:      var(--wp--custom--size--drawer);
  --z-cal:         var(--wp--custom--size--cal);
  --z-event-media: var(--wp--custom--size--event-media);
  --z-hair:        var(--wp--custom--size--hairline);
  --z-hero:        var(--wp--custom--size--hero);
  --z-news-row:    var(--wp--custom--size--news-block);
  --z-news-half:   var(--wp--custom--size--news-row);
  --z-portrait:    var(--wp--custom--size--portrait);
  --z-rule:        var(--wp--custom--size--rule);
  --z-pillar:      var(--wp--custom--size--pillar);
  --z-play:        var(--wp--custom--size--play);
  --z-play-arrow:  var(--wp--custom--size--play-arrow);
  --z-circ-col:    var(--wp--custom--size--circ-col);
  --z-share-menu:  var(--wp--custom--size--share-menu);
  --z-reader-bar:  var(--wp--custom--size--reader-bar);
  --z-circ-thumb:  var(--wp--custom--size--circ-thumb);
  --z-lion-404:    var(--wp--custom--size--lion-404);
  --z-lion-404-sm: var(--wp--custom--size--lion-404-sm);

  --gutter: var(--wp--custom--gutter);
}

/* ---------- 2. Reset and base ------------------------------------------ */

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

/* [hidden] must beat any later display rule. Without this a component that
   declares its own display (a .btn, a flex grid item) keeps painting while
   marked hidden, and every JS filter on the site silently does nothing. */
[hidden] { display: none !important; }

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

body {
  margin: 0;
  font-family: var(--f-sans);
  font-size: var(--t-md);
  line-height: var(--lh-normal);
  color: var(--c-ink);
  background: var(--c-canvas);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6 {
  margin: 0;
  font-family: var(--f-serif);
  line-height: var(--lh-heading);
  color: var(--c-ink);
}

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

a { color: var(--c-brand); text-decoration: none; }
a:hover { color: var(--c-gold-ink); }

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

:where(a, button, [tabindex]):focus-visible {
  outline: var(--z-hair) solid var(--c-gold-ink);
  outline-offset: var(--s-1);
}

.screen-reader-text {
  position: absolute;
  width: var(--z-hair);
  height: var(--z-hair);
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link {
  position: absolute;
  left: var(--s-1);
  top: var(--s-1);
  z-index: 100;
  padding: var(--s-1) var(--s-3);
  background: var(--c-canvas);
  border-radius: var(--r-sm);
  transform: translateY(-200%);
}
.skip-link:focus { transform: none; }

/* ---------- 3. Layout primitives and bands ----------------------------- */

.inner {
  max-width: var(--wp--style--global--content-size);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* Two capped tracks inside the 1600px shell leave a dead gap between them.
   Sections built that way get a narrower shell instead of a wider gap. */
.inner.is-narrow { max-width: var(--m-section-narrow); }

/* A band owns its background. A section owns its rhythm. */
.band { background: var(--c-canvas); }
.band-canvas { background: var(--c-canvas); }
.band-tint   { background: var(--c-tint); }
.band-brand  { background: var(--c-brand); color: var(--c-canvas); }
.band-ink    { background: var(--c-ink-deep); color: var(--c-on-brand); }

.band-brand h1, .band-brand h2, .band-brand h3 { color: var(--c-canvas); }
.band-ink   h1, .band-ink   h2, .band-ink   h3 { color: var(--c-canvas); }

/* Default interior rhythm for every band. */
.band > .inner {
  padding-block: var(--s-7);
}

/* ---------- 4. Section rhythm by adjacency ------------------------------

   Collapse the seam ONLY where two neighbouring bands paint the SAME
   background, because there is then no visible line between them and their
   two paddings would read as one oversized gap.

   Wherever the background CHANGES, both sides keep their own interior
   padding. Each needs room away from the edge between them. Near-white is
   still a visible edge: canvas against tint draws a line, so it does not
   collapse.
   ----------------------------------------------------------------------- */

:is(.band-canvas) + :is(.band-canvas) > .inner,
:is(.band-tint)   + :is(.band-tint)   > .inner,
:is(.band-brand)  + :is(.band-brand)  > .inner,
:is(.band-ink)    + :is(.band-ink)    > .inner {
  padding-block-start: 0;
}

/* `.band.is-tight > .inner` is (0,2,1), and so is the collapse rule above it,
   so a tight band following a band of the same colour kept its 80px and the
   seam measured 180px instead of 100. Naming both classes settles it, which is
   the honest fix: the rule that needs to win is written to win. */
:is(.band-canvas) + :is(.band-canvas).is-tight > .inner,
:is(.band-tint)   + :is(.band-tint).is-tight   > .inner,
:is(.band-brand)  + :is(.band-brand).is-tight  > .inner,
:is(.band-ink)    + :is(.band-ink).is-tight    > .inner {
  padding-block-start: 0;
}

/* First band under the header needs no extra lift, the hero supplies it. */
.band.is-flush > .inner { padding-block-start: 0; }
.band.is-tight > .inner { padding-block: var(--s-6); }

/* ---------- 5. Components ---------------------------------------------- */

/* 5.1 Eyebrow, the small tracked label above a heading */
.eyebrow {
  font-family: var(--f-sans);
  font-size: var(--t-sm);
  font-weight: 700;
  letter-spacing: var(--tr-widest);
  text-transform: uppercase;
  color: var(--c-brand);
  margin-block-end: var(--s-2);
}
.band-brand .eyebrow, .band-ink .eyebrow { color: var(--c-gold); }

.section-head { max-width: var(--m-prose); }
.section-head p:not(.eyebrow) {
  margin-block-start: var(--s-3);
  color: var(--c-body);
  font-size: var(--t-lg);
  line-height: var(--lh-relaxed);
  max-width: var(--m-narrow);
}
.band-brand .section-head p:not(.eyebrow) { color: var(--c-on-brand); }
/* band-ink only restyled its headings, so the paragraph kept --c-body and
   measured 2.3:1 against the dark field. */
.band-ink .section-head p:not(.eyebrow) { color: var(--c-on-brand); }


/* 5.2 Buttons */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  padding: var(--s-2) var(--s-4);
  border-radius: var(--r-pill);
  font-family: var(--f-sans);
  font-size: var(--t-base);
  font-weight: 700;
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  border: var(--z-hair) solid transparent;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease;
}
.btn-primary { background: var(--c-gold); color: var(--c-brand-deep); }
/* The hover state turns the button white. On a canvas band that left a button
   with no edge at all: the label floated and the shape disappeared. It keeps
   its outline now, so hovering changes the button rather than removing it. */
.btn-primary:hover {
  background: var(--c-canvas);
  color: var(--c-brand-deep);
  border-color: var(--c-brand-deep);
}
.btn-ghost { border-color: var(--c-line-blue); color: var(--c-brand); }
.btn-ghost:hover { border-color: var(--c-brand); color: var(--c-brand-deep); }
.btn-on-dark { border-color: var(--hair-on-brand); color: var(--c-canvas); }
.btn-on-dark:hover { background: var(--c-canvas); color: var(--c-brand-deep); }

.link-arrow {
  font-weight: 700;
  font-size: var(--t-base);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
}
.link-arrow::after { content: " \2192"; }

/* 5.3 Utility bar and site header */
.topbar { background: var(--c-brand-deep); color: var(--c-line-blue); font-size: var(--t-xs); }
.topbar > .inner { display: flex; justify-content: flex-end; gap: var(--s-3); padding-block: var(--s-1); flex-wrap: wrap; }
.topbar a { color: var(--c-line-blue); }
.topbar a:hover { color: var(--c-gold); }
/* An icon-only link is a small target by definition, so it gets the tap floor
   rather than the line height of the words beside it. */
.topbar a.is-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: var(--z-tap);
  min-block-size: var(--z-tap);
  margin-block: calc(var(--s-1) * -1);
}
.topbar a.is-icon svg { display: block; }
a.has-icon {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
}
a.has-icon svg { flex: none; }

/* Site header */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--c-canvas);
  border-block-end: var(--z-hair) solid var(--c-line);
}
.site-header > .inner {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding-block: var(--s-2);
  flex-wrap: wrap;
}
.site-header .brand { display: flex; align-items: center; gap: var(--s-2); }
.site-header .brand img { height: var(--z-logo); width: auto; }
.site-header .brand .lci { height: var(--z-logo-sm); }

.site-nav {
  display: flex;
  gap: var(--s-4);
  margin-inline-start: auto;
  font-size: var(--t-base);
  font-weight: 500;
  flex-wrap: wrap;
  align-items: center;
}
.site-nav-list {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  flex-wrap: wrap;
}
.site-nav a { color: var(--c-ink); }
.site-nav a:hover { color: var(--c-brand); }

/* 5.4 Hero */
/* Hero geometry follows the mockup: a capped-height photo, a 100deg scrim
   that clears the right side, and copy held to a 640px measure. */
.hero { position: relative; background: var(--c-brand-deep); color: var(--c-canvas); }
/* z-index here is load bearing: without it .media makes no stacking context,
   so the scrim's z-index competes with .inner and paints over the copy. */
.hero .media { position: absolute; inset: 0; overflow: hidden; z-index: 0; }
.hero .media img { width: 100%; height: 100%; object-fit: cover; }
/* Duotone wash: navy where the copy sits, through indigo, to plum on the open
   side. The brand kit specifies #4B115C and the site had never used it.
   The mockup's original 0.72/0.35/0.05 ramp measured 3.12:1 behind the
   paragraph and 2.26:1 behind the eyebrow, both below WCAG AA, so the dark end
   of this gradient still has to carry the copy. */
.hero .media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg, var(--scrim-duo-navy) 0%, var(--scrim-duo-indigo) 46%, var(--scrim-duo-plum) 100%);
}
/* A second pass under the wash, so the photograph reads as one toned image
   rather than a picture with a colour sheet laid over it. */
.hero .media::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(105deg, var(--c-brand-deep) 0%, var(--c-plum) 100%);
  mix-blend-mode: color;
  opacity: 0.42;
}
.hero .media::after { z-index: 2; }
.hero > .inner {
  position: relative;
  min-height: var(--z-hero);
  display: flex;
  align-items: center;
  padding-block: var(--s-6);
}
.hero-copy { max-width: var(--m-tight); }
.hero h1 {
  font-size: var(--t-display-xl);
  line-height: var(--lh-tight);
  font-weight: 600;
  color: var(--c-canvas);
  margin-block: var(--s-3);
}
.hero .eyebrow { color: var(--c-gold); }
.hero p:not(.eyebrow) {
  font-size: var(--t-lg);
  line-height: var(--lh-normal);
  color: var(--c-tint-warm);
}
.hero .actions { display: flex; gap: var(--s-2); flex-wrap: wrap; margin-block-start: var(--s-5); }

/* 5.5 Pledge band: three full-bleed panels, blue / photo / gold.
   Not bordered cards. The panels butt together inside one rounded, clipped
   wrapper, so no gaps and no internal borders. */
/* The three panels are full bleed, so the band had no bottom padding at all and
   the next section's eyebrow sat straight under the gold panel with nothing
   between them. The band still starts tight; it just stops properly. */
.pledge > .inner { padding-block: var(--s-5) var(--s-6); }
.pledge-band {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  border-radius: var(--r-lg);
  overflow: hidden;
}
.pledge-panel {
  padding: var(--s-5);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--s-4);
  min-height: 0;
}
.pledge-panel p {
  font-family: var(--f-serif);
  font-size: var(--t-2xl);
  line-height: var(--lh-snug);
}
.pledge-blue { background: var(--c-brand); color: var(--c-canvas); }
.pledge-gold { background: var(--c-gold); color: var(--c-ink); }
.pledge-blue .btn { background: var(--c-gold); color: var(--c-brand-deep); align-self: flex-start; }
.pledge-gold .btn { background: var(--c-brand); color: var(--c-canvas); align-self: flex-start; }
.pledge-photo { position: relative; background: var(--c-tint); }
.pledge-photo img { width: 100%; height: 100%; object-fit: cover; }

/* 5.6 Section heads.
   The mockup centres the causes, news and gallery heads on a narrow measure,
   and left-aligns the story and events heads. Two variants, not one. */
.section-head.is-centered {
  max-width: var(--m-prose);
  margin-inline: auto;
  text-align: center;
}
.section-head.is-centered p { margin-inline: auto; }
.section-head.is-centered h2 { font-size: var(--t-display-lg); }
.section-head h2 { font-size: var(--t-display-md); }

/* 5.7 Causes: four across, each an outlined card with a round icon. */
.causes-grid {
  display: grid;
  /* Four across. A 40em/640px minimum can only ever fit two tracks here. */
  grid-template-columns: repeat(auto-fit, minmax(min(var(--m-card), 100%), 1fr));
  gap: var(--s-2);
  margin-block-start: var(--s-5);
}
.cause {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--s-2);
  padding: var(--s-4) var(--s-3);
  border: var(--z-hair) solid var(--c-line);
  border-radius: var(--r-md);
  background: var(--c-canvas);
}
.cause .icon {
  width: var(--z-icon);
  height: var(--z-icon);
  aspect-ratio: 1 / 1;
  border-radius: var(--r-pill);
  background: var(--c-tint);
  display: grid;
  place-items: center;
  overflow: hidden;
}
.cause .icon img { width: 100%; height: 100%; object-fit: cover; }
.cause h3 { font-family: var(--f-sans); font-size: var(--t-xl); font-weight: 700; letter-spacing: var(--tr-tightest); }
.more {
  font-size: var(--t-sm);
  font-weight: 700;
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  color: var(--c-brand);
}
.more:hover { color: var(--c-brand-deep); }
.band-brand .more, .band-ink .more { color: var(--c-gold); }

/* 5.8 Story: copy and portrait held close on a narrow shell, with an offset
   gold block behind the portrait so the column has weight without more size. */
.story-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--z-portrait);
  gap: var(--s-5);
  align-items: center;
}
.story-grid .prose p:not(.eyebrow) {
  color: var(--c-body);
  font-size: var(--t-md);
  line-height: var(--lh-relaxed);
  max-width: var(--m-narrow);
}

.story-quote {
  margin-block-start: var(--s-4);
  padding: var(--s-3) var(--s-4);
  background: var(--c-tint);
  border-inline-start: var(--z-rule) solid var(--c-gold);
  border-radius: 0 var(--r-md) var(--r-md) 0;
}
.story-quote blockquote {
  margin: 0;
  font-family: var(--f-serif);
  font-size: var(--t-xl);
  line-height: var(--lh-snug);
  color: var(--c-brand-deep);
}
.story-quote .quote-gloss {
  margin-block-start: var(--s-1);
  font-size: var(--t-sm);
  font-style: italic;
  color: var(--c-muted);
}
.story-quote cite {
  display: block;
  margin-block-start: var(--s-2);
  padding-block-start: var(--s-2);
  border-block-start: var(--z-hair) solid var(--c-line);
  font-style: normal;
  font-size: var(--t-sm);
  font-weight: 700;
  color: var(--c-ink);
}
.story-quote cite span { display: block; font-weight: 400; color: var(--c-muted); }

.story-media { position: relative; }
.story-media::before {
  content: "";
  position: absolute;
  inset-block-end: calc(var(--s-3) * -1);
  inset-inline-end: calc(var(--s-3) * -1);
  width: 62%;
  height: 62%;
  /* Blue, not gold: the Governor's portrait is shot on a gold ground, so a
     gold block behind it disappears. */
  background: var(--c-brand);
  border-radius: var(--r-lg);
}
.story-media img {
  position: relative;
  width: 100%;
  height: auto;
  border-radius: var(--r-lg);
  /* height:auto is required: WordPress emits width/height attributes and a
     non-auto height makes the browser ignore aspect-ratio entirely. */
  aspect-ratio: 4 / 5;
  object-fit: cover;
  object-position: center top;
}

/* 5.9 Pillars: four photo cards, copy laid over the image.
   Each card owns a scrim so the text is legible whatever the photo does. */
.pillars-head {
  max-width: var(--m-prose);
  margin-inline: auto;
  text-align: center;
  font-family: var(--f-serif);
  font-size: var(--t-2xl);
  line-height: var(--lh-snug);
  color: var(--c-canvas);
}
.pillars-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(var(--m-tight), 100%), 1fr));
  gap: var(--s-2);
  margin-block-start: var(--s-5);
}
.pillar {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-md);
  min-height: var(--z-pillar);
  display: flex;
}
.pillar img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.pillar::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, var(--scrim-deep) 0%, var(--scrim-strong) 45%, var(--scrim-none) 100%);
}
.pillar .body {
  position: relative;
  z-index: 1;
  margin-block-start: auto;
  padding: var(--s-4);
  color: var(--c-canvas);
}
.pillar h3 {
  font-family: var(--f-serif);
  font-size: var(--t-display-sm);
  font-weight: 700;
  color: var(--c-canvas);
  margin-block-end: var(--s-1);
}
.pillar p {
  font-size: var(--t-sm);
  line-height: var(--lh-normal);
  color: var(--c-tint-warm);
}

/* 5.10 News: one wide feature, one standard card, and a stacked
   quote / call-to-action column. */
.news-grid {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  /* Two fixed rows. Left to themselves the cards grow to their content and
     the block ran more than twice the mockup's height. */
  grid-template-rows: repeat(2, var(--z-news-half));
  align-items: stretch;
  gap: var(--s-2);
  margin-block-start: var(--s-5);
}
.news-feature { grid-row: span 2; position: relative; overflow: hidden; border-radius: var(--r-md); display: block; }

/* A post with no featured image must still look deliberate. Without this the
   scrim gradient renders over white and the card reads as broken. */
.news-feature.is-textonly { background: var(--c-brand); display: flex; }
.news-feature.is-textonly::after { display: none; }
.news-feature.is-textonly .body { position: relative; margin-block-start: auto; background: none; }
.news-card.is-textonly .body { margin-block: auto; }
.news-feature img { width: 100%; height: 100%; object-fit: cover; }
/* The scrim covers the whole card, not just the text box. A gradient confined
   to the body measured 1.07:1 over a bright poster image: the headline was
   effectively invisible. This is the same ramp the pillar cards use. */
.news-feature::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, var(--scrim-deep) 0%, var(--scrim-strong) 45%, var(--scrim-none) 100%);
}
.news-feature .body {
  position: absolute;
  z-index: 1;
  inset-inline: 0;
  inset-block-end: 0;
  padding: var(--s-6) var(--s-4) var(--s-4);
  color: var(--c-canvas);
}
.news-feature h3 { color: var(--c-canvas); font-size: var(--t-2xl); }
.news-feature p { color: var(--c-tint-warm); font-size: var(--t-sm); margin-block-start: var(--s-1); }

.news-card {
  background: var(--c-tint);
  border-radius: var(--r-md);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.news-card--tall { grid-row: span 2; }
.news-card--tall .thumb { width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; flex: none; }
.news-card--compact { justify-content: center; }
.news-card--compact .body { padding: var(--s-4) var(--s-3); }
.news-card--compact h3 { font-size: var(--t-lg); }
.news-card--tall.is-textonly { justify-content: center; }
.news-card .body { padding: var(--s-3); display: flex; flex-direction: column; gap: var(--s-1); }
.news-card h3 {
  font-family: var(--f-sans);
  font-size: var(--t-lg);
  letter-spacing: var(--tr-tightest);
  line-height: var(--lh-snug);
}
.news-card p {
  color: var(--c-body);
  font-size: var(--t-sm);
  line-height: var(--lh-normal);
  /* Clamp the excerpt so a long one cannot push the card past its row. */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.news-card .body { min-height: 0; overflow: hidden; }

.news-meta {
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: var(--tr-eyebrow);
  text-transform: uppercase;
  /* steel is the dark-field tone and measures 3.81 on a light card */
  color: var(--c-muted);
}
.news-feature .news-meta { color: var(--c-gold); }

.news-quote, .news-more {
  border-radius: var(--r-md);
  padding: var(--s-4);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--s-2);
}
.news-quote { background: var(--c-brand); color: var(--c-canvas); }
.news-quote blockquote { margin: 0; font-family: var(--f-serif); font-size: var(--t-xl); line-height: var(--lh-snug); }
.news-quote .note { font-size: var(--t-xs); letter-spacing: var(--tr-widest); text-transform: uppercase; color: var(--c-gold); }
.news-more { background: var(--c-gold); color: var(--c-ink); }
.news-more p { font-family: var(--f-serif); font-size: var(--t-xl); line-height: var(--lh-snug); }
.news-more .link-arrow { color: var(--c-brand-deep); }

/* 5.11 Events: head left, cards right, on the tint band. */
.events-grid {
  display: grid;
  /* Two across: head left, cards right. A 42em minimum leaves no room for the
     second track once the gutter and gap are taken out. */
  grid-template-columns: repeat(auto-fit, minmax(min(var(--m-narrow), 100%), 1fr));
  gap: var(--s-5);
  align-items: start;
}
.events-list { display: grid; gap: var(--s-2); }
.event {
  display: grid;
  grid-template-columns: var(--z-date) minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-md);
  background: var(--c-canvas);
  box-shadow: var(--sh-card);
}
.event .date {
  text-align: center;
  border-radius: var(--r-sm);
  background: var(--c-brand);
  color: var(--c-canvas);
  padding: var(--s-1);
}
.event .date .d { display: block; font-family: var(--f-serif); font-size: var(--t-xl); font-weight: 700; line-height: var(--lh-flat); }
.event .date .m { display: block; font-size: var(--t-micro); letter-spacing: var(--tr-eyebrow); text-transform: uppercase; }
/* balance keeps a two-line event title from orphaning its last word, which
   happens often here because the titles are the district's own wording. */
.event h3 {
  font-size: var(--t-md);
  font-weight: 700;
  font-family: var(--f-sans);
  text-wrap: balance;
}
.event .where { color: var(--c-muted); font-size: var(--t-sm); }
.events-empty { color: var(--c-muted); }

/* 5.11b Feature video: poster first, nothing loads until the viewer asks.
   preload="none" keeps it off the critical path so it cannot gate LCP. */
.video-block {
  margin-block-start: var(--s-5);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--c-ink-deep);
  box-shadow: var(--sh-raised);
}
.video-block video {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: var(--c-ink-deep);
}
.video-facade {
  position: relative;
  display: block;
  cursor: pointer;
  aspect-ratio: 16 / 9;
}
.video-facade img { width: 100%; height: 100%; object-fit: cover; }
.video-facade::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--scrim-soft);
  transition: background .2s ease;
}
.video-facade:hover::after,
.video-facade:focus-visible::after { background: var(--scrim-strong); }
.video-play {
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 50%;
  transform: translate(-50%, -50%);
  z-index: 1;
  width: var(--z-play);
  height: var(--z-play);
  border-radius: var(--r-pill);
  background: var(--c-gold);
  display: grid;
  place-items: center;
}
.video-play::before {
  content: "";
  border-inline-start: var(--z-play-arrow) solid var(--c-brand-deep);
  border-block: calc(var(--z-play-arrow) * 0.6) solid transparent;
  margin-inline-start: calc(var(--z-play-arrow) * 0.3);
}
.video-facade.is-playing { aspect-ratio: 16 / 9; cursor: default; }
.video-facade.is-playing::after, .video-facade.is-playing .video-play { display: none; }
.video-facade iframe { width: 100%; height: 100%; border: 0; display: block; }

.video-caption {
  margin-block-start: var(--s-2);
  font-size: var(--t-sm);
  color: var(--c-muted);
  text-align: center;
}

/* 5.12 Gallery: four across, tight mosaic. */
.gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(var(--m-card), 100%), 1fr));
  grid-auto-rows: var(--z-gallery-row);
  gap: var(--s-1);
  margin-block-start: var(--s-5);
}
.gallery-grid figure { margin: 0; display: block; overflow: hidden; border-radius: var(--r-sm); }
.gallery-grid img { width: 100%; height: 100%; object-fit: cover; }
.gallery-grid .span-2 { grid-column: span 2; }

/* 5.12b Supporters: full-bleed marquee on the tint band. */
/* The supporters strip runs edge to edge in the mockup, so its inner wrapper
   drops the gutter and only the label keeps it. */
.supporters { text-align: center; }
.supporters > .inner { padding-inline: 0; }
.supporters .title { padding-inline: var(--gutter); }
.supporters .title {
  font-size: var(--t-sm);
  font-weight: 700;
  letter-spacing: var(--tr-widest);
  text-transform: uppercase;
  color: var(--c-muted);
}
.marquee { overflow: hidden; margin-block-start: var(--s-4); }
.marquee ul { display: flex; align-items: center; gap: var(--s-2); width: max-content; }
.marquee img { height: var(--z-marquee); width: auto; object-fit: contain; }
@media (prefers-reduced-motion: no-preference) {
  .marquee ul { animation: marquee 40s linear infinite; }
}
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* 5.13 Footer */
.site-footer { font-size: var(--t-sm); }
.site-footer > .inner { padding-block: var(--s-6); }
.footer-grid {
  display: grid;
  /* Four across. A 40em first track plus 40em minimums wrapped the columns
     onto a second row and nearly doubled the footer height. */
  grid-template-columns: repeat(auto-fit, minmax(min(var(--m-card), 100%), 1fr));
  gap: var(--s-4);
}
.site-footer .brand img { height: var(--z-logo-foot); width: auto; }
.site-footer .tagline { margin-block-start: var(--s-3); color: var(--c-on-brand); line-height: var(--lh-relaxed); max-width: var(--m-narrow); }
.site-footer h2 {
  font-family: var(--f-sans);
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: var(--tr-widest);
  text-transform: uppercase;
  color: var(--c-canvas);
  margin-block-end: var(--s-3);
}
.site-footer li + li { margin-block-start: var(--s-1); }
.site-footer a { color: var(--c-on-brand); }
.site-footer a:hover { color: var(--c-gold); }
.footer-legal {
  margin-block-start: var(--s-5);
  padding-block-start: var(--s-4);
  border-block-start: var(--z-hair) solid var(--hair-on-brand-soft);
  /* steel is shared with light-background meta text, where lightening it would
     fail instead. On the dark footer this needs the on-brand tone: 4.28 -> 11.3 */
  color: var(--c-on-brand);
  font-size: var(--t-xs);
  line-height: var(--lh-relaxed);
}

/* ---------- 6. Responsive ---------------------------------------------- */

@media (max-width: 60em) {
  :root { --gutter: var(--s-4); }

  .band > .inner { padding-block: var(--s-6); }
  .band.is-tight > .inner { padding-block: var(--s-5); }

  .story-grid { grid-template-columns: minmax(0, 1fr); gap: var(--s-5); }
  .story-media { max-width: var(--z-portrait); }
  .pledge-band { grid-template-columns: minmax(0, 1fr); }
  /* The two fixed 290px rows are for the three-column desktop layout. Left in
     place here they combine with aspect-ratio below to compute a width of
     290 * 16/9 = 516px, which overflows a phone by 156px. */
  .news-grid { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto; }
  .news-feature, .news-card { grid-row: auto; }
  .news-feature { aspect-ratio: 16 / 9; }
  .event { grid-template-columns: var(--z-date) minmax(0, 1fr); }
  .event .details { grid-column: 1 / -1; }
  .gallery-grid .span-2 { grid-column: span 1; }
}

@media (max-width: 40em) {
  .site-header > .inner { gap: var(--s-2); }
  /* the two lockups side by side run 3px past a 390px viewport at full size */
  .site-header .brand img { height: var(--z-logo-sm); }
  .site-nav { gap: var(--s-3); font-size: var(--t-sm); width: 100%; margin-inline-start: 0; }
  .hero .actions .btn { width: 100%; justify-content: center; }
}


/* 5.14 Events archive.
   Two lists on one page, upcoming then past, so the grid has to read the same
   in a band of four and a band of fifty. The date chip sits on the cover rather
   than beside the title, which keeps the card's text column full width. */
.event-cards,
.post-grid {
  display: grid;
  /* min() keeps the 320px floor from overflowing a phone, where the column has
     less than 320px to work with once the gutter is taken out. */
  grid-template-columns: repeat(auto-fill, minmax(min(var(--z-event-card), 100%), 1fr));
  gap: var(--s-4);
}
.event-card,
.post-card {
  display: flex;
  flex-direction: column;
  background: var(--c-canvas);
  border-radius: var(--r-md);
  box-shadow: var(--sh-card);
  overflow: hidden;
}
.band-tint .event-card { box-shadow: var(--sh-raised); }
.event-card__media,
.post-card__media {
  position: relative;
  display: block;
  aspect-ratio: 1200 / 630;
  background: var(--c-brand);
}
.event-card__media img,
.post-card__media img {
  /* Absolute, not height:100%. A percentage height inside a box sized only by
     aspect-ratio is a cyclic dependency, so the image's intrinsic height wins
     and stretches the card: a square photo produced a 428x428 slot in a 16/9
     frame. Taking the image out of flow lets aspect-ratio decide the box. */
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.event-card__body,
.post-card__body {
  padding: var(--s-3) var(--s-4) var(--s-4);
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
}
/* Sans, like every other card headline on the site. The serif is for display
   sizes; at 18px above a letterspaced label it read as a second design. */
.event-card__body h3 {
  font-family: var(--f-sans);
  font-size: var(--t-lg);
  font-weight: 700;
  letter-spacing: var(--tr-tightest);
  line-height: var(--lh-snug);
  text-wrap: balance;
}
.event-card__body h3 a { color: inherit; text-decoration: none; }
.event-card__body h3 a:hover { color: var(--c-brand); text-decoration: underline; }
.event-card__when { font-weight: 600; color: var(--c-body); font-size: var(--t-sm); }
.event-card__where { color: var(--c-muted); font-size: var(--t-sm); }

/* 5.15 Single event. The facts column carries the page when there is no body
   copy, which is the normal case for a calendar entry. */
.event-single__when {
  font-family: var(--f-serif);
  font-size: var(--t-lg);
  color: var(--c-gold);
  margin-block-start: var(--s-2);
}
/* The cover is the heading band's photograph now, not a figure floating in the
   body with the right half of the page empty beside it, so .event-single__media
   is gone rather than left behind unused. */
/* An event cover has its own type baked in: the kind, the day, the month. Used
   sharp behind the heading it prints SERVICE and 10 Oct 2026 twice on the same
   screen, once in the page's type and once in the picture's. Blurred, the cover
   becomes the field of colour and motif it was designed as, and only the page's
   own words are readable. */
.event-single .band-photo > .media img {
  filter: blur(var(--z-hero-blur));
  transform: scale(1.08);
}
.event-single__flag {
  margin-block-start: var(--s-2);
  display: inline-flex;
  align-items: center;
  padding: var(--s-1) var(--s-3);
  border-radius: var(--r-pill);
  background: var(--hair-on-brand);
  color: var(--c-canvas);
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
}
.event-single__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-block-start: var(--s-3);
}
.event-single__actions .btn { flex: 1 1 auto; justify-content: center; }
.event-single__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 22em);
  gap: var(--s-5);
  align-items: start;
}
.event-single__body { max-width: var(--m-prose); }
.event-single__note { color: var(--c-body); font-size: var(--t-md); line-height: var(--lh-relaxed); }
.event-single__facts {
  background: var(--c-tint);
  border: var(--z-hair) solid var(--c-line);
  border-radius: var(--r-md);
  padding: var(--s-4);
}
.event-single__facts dt {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: var(--tr-eyebrow);
  text-transform: uppercase;
  color: var(--c-muted);
}
.event-single__facts dd {
  /* the UA stylesheet indents dd by 40px, which reads as a broken alignment */
  margin-inline-start: 0;
  margin-block: var(--s-1) var(--s-3);
  color: var(--c-ink);
  font-weight: 600;
}
.event-single__facts dd:last-of-type { margin-block-end: var(--s-3); }
.event-single__facts dd a { color: var(--c-brand); }
.event-single__facts dd a:hover { color: var(--c-brand-deep); }

@media (max-width: 54em) {
  .event-single__grid { grid-template-columns: minmax(0, 1fr); }
}


/* 5.16 Events archive filters.
   The form is the state: the server renders it filtered, and the script only
   re-applies the same rules, so this has to read correctly before any JS runs
   and after the submit button is hidden. */
.event-filters {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  padding: var(--s-4);
  border: var(--z-hair) solid var(--c-line);
  border-radius: var(--r-md);
  background: var(--c-tint);
  margin-block-end: var(--s-4);
}
.event-filters__row {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--s-3);
}
.event-filters__field { display: flex; flex-direction: column; gap: var(--s-1); }
.event-filters label,
.event-filters legend {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: var(--tr-eyebrow);
  text-transform: uppercase;
  color: var(--c-muted);
}
.event-filters input[type="search"],
.event-filters select {
  inline-size: 100%;
  padding: var(--s-2) var(--s-3);
  font: inherit;
  font-size: var(--t-base);
  color: var(--c-ink);
  background: var(--c-canvas);
  border: var(--z-hair) solid var(--c-line-blue);
  border-radius: var(--r-sm);
}
.event-filters input[type="search"]:focus-visible,
.event-filters select:focus-visible {
  outline: var(--z-rule) solid var(--c-brand);
  outline-offset: var(--z-hair);
}
.event-filters__when {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
  border: 0;
  padding: 0;
  margin: 0;
}
.event-filters__when legend { float: left; padding-inline-end: var(--s-3); }
.event-filters__radio { display: flex; align-items: center; gap: var(--s-1); }
.event-filters__radio label {
  font-size: var(--t-sm);
  font-weight: 600;
  letter-spacing: normal;
  text-transform: none;
  color: var(--c-ink);
  cursor: pointer;
}
.event-filters__actions { display: flex; align-items: center; gap: var(--s-4); flex-wrap: wrap; }
.event-count {
  color: var(--c-muted);
  font-size: var(--t-sm);
  font-weight: 600;
  margin-block-end: var(--s-3);
}
.event-empty {
  color: var(--c-body);
  font-size: var(--t-md);
  padding-block: var(--s-5);
}
.event-cards__item { display: flex; }
.event-cards__item > .event-card { inline-size: 100%; }

@media (max-width: 54em) {
  .event-filters__row { grid-template-columns: minmax(0, 1fr); }
  /* the floated legend drags the first radio up onto its line */
  .event-filters__when legend {
    float: none;
    inline-size: 100%;
    padding-inline-end: 0;
    margin-block-end: var(--s-1);
  }
}

/* The kind on a homepage event row is a way into the archive's filters. */
.event .event-kind { font-size: var(--t-micro); margin-block-end: var(--s-1); }
.event .event-kind a { color: var(--c-brand); text-decoration: none; }
.event .event-kind a:hover { text-decoration: underline; }

/* News archive: same card as an event, with the headline one level up because
   these are h2 in a list of stories rather than h3 inside a section. */
.post-card__body h2 {
  font-family: var(--f-sans);
  font-size: var(--t-lg);
  font-weight: 700;
  letter-spacing: var(--tr-tightest);
  line-height: var(--lh-snug);
  text-wrap: balance;
}
.post-card__body h2 a { color: inherit; text-decoration: none; }
.post-card__body h2 a:hover { color: var(--c-brand); text-decoration: underline; }
.post-card__excerpt { color: var(--c-muted); font-size: var(--t-sm); line-height: var(--lh-relaxed); }

/* The district posts square and portrait artwork far more often than landscape
   photographs: of ten cards on page one, five were square and two portrait
   against a 16:9 box. Cover cropped a square to its middle third, which keeps
   the headline and loses the date and the venue, and those are the whole point
   of an announcement. So the picture is contained and never cropped, and the
   space beside it is filled by a blurred copy of the same file. */
.post-card__media { overflow: hidden; }
/* Scoped to .post-card__media, not written as a bare class. `.post-card__media
   img` above is (0,1,1) and sets object-fit: cover, so a lone `.post-card__shot`
   at (0,1,0) loses on specificity no matter where it sits in the file, and the
   contain never takes effect. */
.post-card__media .post-card__blur,
.post-card__media .post-card__shot {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  display: block;
}
.post-card__media .post-card__blur {
  object-fit: cover;
  filter: blur(var(--z-card-blur)) saturate(0.85) brightness(0.62);
  /* scaled past the edges so the blur has nothing to feather against */
  transform: scale(1.2);
}
.post-card__media .post-card__shot {
  object-fit: contain;
  object-position: center;
}

/* Eleven published posts have no featured image. Leaving the media box out for
   those made their cards two thirds the height of the rest and the grid filled
   with holes, so a post without a photograph gets the district mark on the
   brand gradient instead: deliberate rather than missing. */
.post-card__mark {
  position: absolute;
  inset: 0;
  display: block;
  /* pitched at the same value as the blurred fields beside it, so a card
     without a photograph sits in the grid instead of jumping out of it */
  background:
    linear-gradient(var(--scrim-soft), var(--scrim-soft)),
    linear-gradient(140deg, var(--c-brand) 0%, var(--c-brand-deep) 100%);
}
/* held back to a watermark: at full strength two of these on one screen pull
   the eye away from the cards that do have a photograph */
.post-card__mark::after {
  content: "";
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 50%;
  inline-size: var(--z-mark-wm);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  background: var(--wm-lci) center / contain no-repeat;
  opacity: 0.22;
}

/* Filter chips. Plain links, so each view has its own URL and the filter works
   with scripting off. */
.chip-nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-block-start: var(--s-4);
}
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  min-block-size: var(--z-tap);
  padding: var(--s-1) var(--s-3);
  border-radius: var(--r-pill);
  background: var(--hair-on-brand);
  color: var(--c-canvas);
  font-size: var(--t-sm);
  font-weight: 600;
  text-decoration: none;
}
.chip:hover { background: var(--c-gold); color: var(--c-ink-deep); }
.chip.is-on { background: var(--c-gold); color: var(--c-ink-deep); }
.chip__count {
  font-size: var(--t-micro);
  font-weight: 700;
  opacity: 0.7;
}
.post-card__media { aspect-ratio: 16 / 9; }
.pagination { margin-block-start: var(--s-5); display: flex; justify-content: center; }
.pagination .nav-links { display: flex; gap: var(--s-2); flex-wrap: wrap; align-items: center; }
.pagination a, .pagination span {
  padding: var(--s-1) var(--s-3);
  border-radius: var(--r-sm);
  border: var(--z-hair) solid var(--c-line);
  color: var(--c-brand);
  text-decoration: none;
  font-weight: 600;
}
.pagination .current { background: var(--c-brand); color: var(--c-canvas); border-color: var(--c-brand); }


/* 5.17 Article and page prose.
   There was no .entry rule at all, so every post and page rendered at the full
   1344px container: paragraphs ran edge to edge with no spacing and headings
   had no rhythm. Everything here is measure-first. */
.entry {
  max-inline-size: var(--m-prose);
  color: var(--c-body);
  font-size: var(--t-md);
  line-height: var(--lh-relaxed);
}
.entry > * + * { margin-block-start: var(--s-3); }
.entry h2 {
  font-size: var(--t-2xl);
  line-height: var(--lh-heading);
  color: var(--c-ink);
  margin-block-start: var(--s-5);
  text-wrap: balance;
}
.entry h3 {
  font-size: var(--t-lg);
  line-height: var(--lh-heading);
  color: var(--c-ink);
  margin-block-start: var(--s-4);
  font-family: var(--f-sans);
  font-weight: 700;
}
.entry h4 {
  font-size: var(--t-md);
  line-height: var(--lh-heading);
  color: var(--c-ink);
  margin-block-start: var(--s-4);
  font-family: var(--f-sans);
  font-weight: 700;
}
.entry h5,
.entry h6 {
  font-size: var(--t-sm);
  line-height: var(--lh-heading);
  color: var(--c-brand);
  margin-block-start: var(--s-3);
  font-family: var(--f-sans);
  font-weight: 700;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
}
.entry h2 + p, .entry h3 + p,
.entry h4 + p, .entry h5 + p, .entry h6 + p { margin-block-start: var(--s-2); }
.entry a { color: var(--c-brand); text-underline-offset: 0.12em; }
.entry a:hover { color: var(--c-brand-deep); }
.entry strong { color: var(--c-ink); }
.entry ul, .entry ol { padding-inline-start: var(--s-4); }
.entry li + li { margin-block-start: var(--s-1); }
.entry img,
.entry figure img { max-inline-size: 100%; block-size: auto; border-radius: var(--r-md); }
.entry figure { margin-block: var(--s-4); }
.entry figcaption { color: var(--c-muted); font-size: var(--t-sm); margin-block-start: var(--s-1); }
.entry blockquote {
  margin-block: var(--s-4);
  padding-inline-start: var(--s-4);
  border-inline-start: var(--z-rule) solid var(--c-gold);
  color: var(--c-ink);
  font-family: var(--f-serif);
  font-size: var(--t-lg);
  line-height: var(--lh-snug);
}
.entry hr { border: 0; border-block-start: var(--z-hair) solid var(--c-line); margin-block: var(--s-5); }

.page-article__media,
.post-article__media {
  max-inline-size: var(--m-section-narrow);
  border-radius: var(--r-lg);
  overflow: hidden;
  margin-block-end: var(--s-5);
  box-shadow: var(--sh-raised);
}
.page-article__media img,
.post-article__media img { inline-size: 100%; block-size: auto; display: block; }

.post-article__nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
  align-items: center;
  margin-block-start: var(--s-6);
  padding-block-start: var(--s-4);
  border-block-start: var(--z-hair) solid var(--c-line);
}
.post-article__nav .btn { margin-inline-start: auto; }

/* 5.18 Officers.
   Sixty-three people, so the card has to stay quiet: portrait, role, name,
   club. Officers without a photograph get a monogram in the same slot, which
   keeps every row the same height instead of leaving holes in the grid. */
.officer-jump {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-block-start: var(--s-4);
}
.officer-jump a {
  padding: var(--s-1) var(--s-3);
  border-radius: var(--r-pill);
  background: var(--hair-on-brand);
  color: var(--c-canvas);
  font-size: var(--t-sm);
  font-weight: 600;
  text-decoration: none;
}
.officer-jump a:hover { background: var(--c-gold); color: var(--c-ink-deep); }

.officer-grid {
  list-style: none;
  padding: 0;
  margin-block-start: var(--s-4);
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(var(--z-officer-card), 100%), 1fr));
  gap: var(--s-4);
}
.officer {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}
/* A quiet lift on hover: these are people, not products, so the card should
   acknowledge the pointer without performing. */
.officer__portrait {
  transition: transform 160ms ease, box-shadow 160ms ease;
}
.officer:hover .officer__portrait {
  transform: translateY(calc(var(--s-1) * -0.4));
  box-shadow: var(--sh-raised);
}
@media (prefers-reduced-motion: reduce) {
  .officer__portrait { transition: none; }
  .officer:hover .officer__portrait { transform: none; }
}
.officer__portrait {
  /* 4:5, a little taller than square, so the vest reads at directory size too.
     The leadership tier goes further at 3:4. */
  inline-size: 100%;
  block-size: auto;
  aspect-ratio: 4 / 5;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--c-tint-warm);
  display: block;
  position: relative;
}
.officer__portrait img {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: center top;
  display: block;
}
.officer__portrait--monogram {
  display: grid;
  place-items: center;
  background: linear-gradient(140deg, var(--c-brand) 0%, var(--c-brand-deep) 100%);
  color: var(--c-gold);
  font-family: var(--f-serif);
  font-size: var(--t-2xl);
  font-weight: 700;
  letter-spacing: var(--tr-wide);
  position: relative;
  overflow: hidden;
}
/* Same held-back emblem as the leadership card, so a missing photograph looks
   the same wherever it appears. */
.officer__portrait--monogram::before {
  content: "";
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 50%;
  inline-size: var(--z-lead-watermark);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  background: var(--wm-lci) center / contain no-repeat;
  opacity: 0.09;
}
.officer__portrait--monogram > * { position: relative; z-index: 1; }
.officer__body { display: flex; flex-direction: column; gap: var(--s-1); }
.officer__role {
  /* Gold reads as gold on navy and as mud on white, so the label here is the
     brand blue. Tracking drops from 0.14em to 0.05em: at eyebrow width a
     three-word role was wrapping on the letterspacing alone. */
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--c-brand);
  line-height: var(--lh-snug);
  min-block-size: calc(var(--t-micro) * var(--lh-snug) * 2);
}
.officer__name {
  /* Sans, like every other card on the site. The serif is for display headings;
     at 18px beside a letterspaced label it read as a different design. */
  font-family: var(--f-sans);
  font-size: var(--t-md);
  font-weight: 700;
  color: var(--c-ink);
  line-height: var(--lh-snug);
  letter-spacing: var(--tr-tightest);
}
.officer__note, .officer__club { color: var(--c-muted); font-size: var(--t-sm); line-height: var(--lh-snug); }
.officer__note { font-style: italic; }


/* 5.19 The Governor's team, as cards.
   The portrait is the card rather than sitting above a caption: a numbered
   corner, the district mark, and the name set across the foot, with the surname
   carrying the weight. Same idea as a sports card, which is what the district
   asked for, but in navy and gold rather than red. */
.officers-lead .officer-grid--lead {
  grid-template-columns: repeat(auto-fit, minmax(min(var(--z-officer-lead-card), 100%), 1fr));
  gap: var(--s-4);
  margin-block-start: var(--s-4);
}
.officer-grid--lead .officer { display: block; }

.lead-card {
  position: relative;
  display: block;
  aspect-ratio: 2 / 3;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--c-brand-deep);
  box-shadow: var(--sh-deep);
  isolation: isolate;
}
.lead-card__media { position: absolute; inset: 0; display: block; }
.lead-card__media img {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  display: block;
}
/* the copy sits on the lower third, so that is where the card has to darken */
.lead-card::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  /* The darkening was reaching the chins. It stops lower and lighter now, and
     the name keeps its own contrast from --sh-glyph rather than taking it from
     the picture: a shadow darkens behind the letters, a scrim darkens a face. */
  background: linear-gradient(to top, var(--scrim-card-foot) 14%, var(--scrim-card-mid) 38%, var(--scrim-none) 54%);
  pointer-events: none;
}

.lead-card__mark,
.lead-card__bottom { position: absolute; z-index: 2; }

/* The whole bottom stack is one flow container pinned to the foot of the card.
   Positioning the name, the role and the bar as separate absolute siblings made
   a two-line role climb over the surname and a two-line club name fall out of
   the card. In flow they simply stack. */
.lead-card__bottom {
  inset-inline: 0;
  inset-block-end: 0;
  display: flex;
  flex-direction: column;
}
.lead-card__foot {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  padding: 0 var(--s-3) var(--s-3);
  text-align: center;
}

.lead-card__mark {
  inset-block-start: 0;
  inset-inline-end: var(--s-3);
  inline-size: var(--z-lead-mark);
  display: grid;
  place-items: center;
  padding-block: var(--s-2);
  background: var(--c-gold);
  border-end-start-radius: var(--r-sm);
  border-end-end-radius: var(--r-sm);
}
.lead-card__mark img { inline-size: 70%; block-size: auto; display: block; }

.lead-card__name { display: flex; flex-direction: column; gap: var(--s-1); }
.lead-card__foot .lead-card__name,
.lead-card__foot .lead-card__role { text-shadow: var(--sh-glyph); }
.lead-card__given {
  font-size: var(--t-sm);
  font-weight: 600;
  letter-spacing: var(--tr-widest);
  text-transform: uppercase;
  color: var(--c-canvas);
}
.lead-card__family {
  font-size: var(--t-2xl);
  font-weight: 800;
  line-height: var(--lh-flat);
  letter-spacing: var(--tr-tightest);
  text-transform: uppercase;
  color: var(--c-canvas);
  text-wrap: balance;
}
.lead-card__role {
  font-size: var(--t-micro);
  line-height: var(--lh-snug);
  color: var(--c-gold);
  font-weight: 600;
  /* a two-line floor: without it a one-line role sat the name 40px lower than
     the card beside it, and four cards in a row had four name heights */
  min-block-size: calc(var(--t-micro) * var(--lh-snug) * 2);
}
.lead-card__bar {
  padding: var(--s-2) var(--s-3);
  text-align: center;
  background: var(--c-gold);
  color: var(--c-ink-deep);
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  /* club names run to one or two lines, which made the gold band 50px deep on
     one card and 71px on the next. Floor it at two. */
  display: grid;
  place-items: center;
  min-block-size: calc(var(--t-micro) * var(--lh-normal) * 2 + var(--s-2) * 2);
}

/* No photograph yet: initials over the Lions emblem, held back far enough that
   it reads as a watermark rather than a logo someone forgot to remove. */
.lead-card__monogram {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: linear-gradient(140deg, var(--c-brand) 0%, var(--c-brand-deep) 100%);
  color: var(--c-gold);
  font-family: var(--f-serif);
  font-size: var(--t-display-md);
  font-weight: 700;
  letter-spacing: var(--tr-wide);
}
.lead-card__monogram::before {
  content: "";
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 50%;
  inline-size: var(--z-lead-watermark);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  background: var(--wm-lci) center / contain no-repeat;
  opacity: 0.09;
}

.officer--dg .lead-card { box-shadow: 0 0 0 var(--z-rule) var(--c-gold), var(--sh-deep); }

/* 5.20 The two-frame portrait.
   Every officer was photographed twice: on pink in the Lions vest, and on
   yellow without it. Where both frames exist the yellow one lies underneath and
   is wiped in on hover, which is a small joke the district will recognise
   because they stood for both shots on the same afternoon.

   The wipe is a clip-path on the top frame rather than a cross-fade, so the two
   never blend into a ghost of each other mid-transition. Keyboard users get it
   too: the card's link is not focusable here, so focus-within covers the case
   where one is added later. */
.officer__portrait--swap .officer__alt,
.lead-card__media--swap .officer__alt {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: center top;
  display: block;
  z-index: 0;
}
.officer__portrait--swap > img:not(.officer__alt),
.lead-card__media--swap > img:not(.officer__alt) {
  z-index: 1;
  opacity: 1;
  /* A dissolve, not a wipe. A hard wipe line cut across his hair halfway
     through, and the two frames are different poses, so a clean edge between
     them reads as a glitch where a dissolve reads as a change of costume. */
  transition: opacity 320ms ease, transform 420ms cubic-bezier(0.4, 0, 0.2, 1);
}
.officer:hover .officer__portrait--swap > img:not(.officer__alt),
.officer:focus-within .officer__portrait--swap > img:not(.officer__alt),
.officer:hover .lead-card__media--swap > img:not(.officer__alt),
.officer:focus-within .lead-card__media--swap > img:not(.officer__alt) {
  opacity: 0;
}
/* Both frames drift in very slightly, which sells the swap as one motion. */
.officer__portrait--swap img { transition: transform 420ms cubic-bezier(0.4, 0, 0.2, 1); }
.officer:hover .officer__portrait--swap img,
.officer:focus-within .officer__portrait--swap img { transform: scale(1.03); }

@media (prefers-reduced-motion: reduce) {
  .officer__portrait--swap img { transition: none; }
  .officer:hover .officer__portrait--swap img,
  .officer:focus-within .officer__portrait--swap img { transform: none; }
}


/* 5.21 Photographic page heading.
   Same duotone as the homepage hero so the two read as one system: navy where
   the copy sits, through indigo, to plum on the open side. The z-index on
   .media is load bearing here for the same reason it is on the hero, otherwise
   the scrim competes with .inner and paints over the heading. */
.band-photo { position: relative; overflow: hidden; }
.band-photo > .media {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
}
.band-photo > .media img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  /* the group sits low in the frame */
  object-position: center 62%;
  display: block;
}
.band-photo > .media::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(105deg, var(--c-brand-deep) 0%, var(--c-plum) 100%);
  mix-blend-mode: color;
  opacity: 0.42;
}
.band-photo > .media::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  background: linear-gradient(105deg, var(--scrim-duo-navy) 0%, var(--scrim-duo-indigo) 52%, var(--scrim-duo-plum) 100%);
}
.band-photo > .inner { position: relative; }


/* 5.22 Touch targets.
   Measured on an iPhone 13: the filter radios were 13x13, the jump pills 39px
   tall and the inline arrow links 23px. A 44px target is the floor at which a
   link is reliably hittable, and it matters more than usual here because most
   of this district's visitors are older. */
.event-filters input[type="radio"],
.event-filters input[type="checkbox"] {
  inline-size: var(--z-control);
  block-size: var(--z-control);
  accent-color: var(--c-brand);
}
.event-filters__radio {
  min-block-size: var(--z-tap);
  gap: var(--s-2);
}
/* the credit line was a 15px-tall target on every page of the site */
.footer-legal a {
  display: inline-block;
  padding-block: var(--s-2);
}
.officer-jump a {
  min-block-size: var(--z-tap);
  display: inline-flex;
  align-items: center;
}

@media (max-width: 40em) {
  .link-arrow,
  .news-more a,
  .post-article__nav .link-arrow {
    min-block-size: var(--z-tap);
    display: inline-flex;
    align-items: center;
  }
  /* the label is the target too, not just the control */
  .event-filters__radio label { min-block-size: var(--z-tap); display: inline-flex; align-items: center; }
}


/* 5.23 Mobile chrome.
   The header was costing roughly 300px before any content: a two-row utility
   bar, a logo row, a nav that wrapped onto two lines and a full-width Donate
   button. This reduces it to one row, and moves the nav behind a button. */
.nav-toggle {
  display: none;
  align-items: center;
  gap: var(--s-2);
  min-block-size: var(--z-tap);
  padding-inline: var(--s-3);
  border: var(--z-hair) solid var(--c-line-blue);
  border-radius: var(--r-pill);
  background: var(--c-canvas);
  color: var(--c-ink);
  font: inherit;
  font-size: var(--t-sm);
  font-weight: 700;
  cursor: pointer;
}
.nav-toggle__bars,
.nav-toggle__bars::before,
.nav-toggle__bars::after {
  display: block;
  inline-size: var(--z-bars);
  block-size: var(--z-bar);
  background: var(--c-brand);
  border-radius: var(--r-sm);
}
.nav-toggle__bars { position: relative; }
.nav-toggle__bars::before,
.nav-toggle__bars::after { content: ""; position: absolute; inset-inline-start: 0; }
.nav-toggle__bars::before { inset-block-start: calc(var(--s-1) * -0.75); }
.nav-toggle__bars::after { inset-block-start: calc(var(--s-1) * 0.75); }
.header-cta { display: none; }

@media (max-width: 60em) {
  /* Utility links are all repeated in the footer, so on a phone the strip is
     just cost. */
  .topbar { display: none; }

  .site-header > .inner { flex-wrap: nowrap; align-items: center; gap: var(--s-2); }
  .nav-toggle { display: inline-flex; margin-inline-start: auto; }
  .header-cta { display: inline-flex; }
  .nav-cta { display: none; }

  /* A drawer, not a dropdown.
     The panel pushed the page down and dropped it again, which on a long menu
     reads as the page jumping. It slides in from the edge over a dimmed page
     instead: the page stays where it was, and the menu is clearly a layer on
     top of it rather than part of it.
     Only collapses once the script can reopen it. */
  body.has-nav-toggle .site-nav {
    position: fixed;
    inset-block: 0;
    inset-inline-end: 0;
    inline-size: min(var(--z-drawer), 86vw);
    max-inline-size: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: var(--s-5) var(--s-4) var(--s-6);
    background: var(--c-canvas);
    box-shadow: var(--sh-deep);
    z-index: 60;
    overflow-y: auto;
    overscroll-behavior: contain;
    transform: translateX(100%);
    visibility: hidden;
    transition:
      transform 320ms cubic-bezier(0.22, 1, 0.36, 1),
      visibility 320ms;
  }
  body.has-nav-toggle .site-nav.is-open { transform: none; visibility: visible; }

  /* The dimmed page behind it. A button, so it is a real target for a tap and
     for a screen reader, and the script owns its label. */
  .nav-scrim {
    position: fixed;
    inset: 0;
    /* Below the header, not above it.
       .site-header is position: relative with z-index 50, which makes a
       stacking context, so the drawer's z-index 60 is capped inside it and the
       whole header stack competes at 50. A scrim at 50 then painted over the
       drawer and greyed the menu out. It sits under the header instead. */
    z-index: 40;
    border: 0;
    padding: 0;
    background: var(--scrim-strong);
    opacity: 0;
    visibility: hidden;
    transition: opacity 320ms ease, visibility 320ms;
    cursor: pointer;
  }
  body.nav-open .nav-scrim { opacity: 1; visibility: visible; }
  /* the page must not scroll under an open drawer */
  body.nav-open { overflow: hidden; }

  /* Each row arrives a beat after the one above it. Cheap, and it makes the
     drawer feel like it opened rather than appeared. */
  body.has-nav-toggle .site-nav .site-nav-list > li {
    opacity: 0;
    transform: translateX(var(--s-3));
    transition: opacity 260ms ease, transform 260ms cubic-bezier(0.22, 1, 0.36, 1);
  }
  body.has-nav-toggle .site-nav.is-open .site-nav-list > li { opacity: 1; transform: none; }
  body.has-nav-toggle .site-nav.is-open .site-nav-list > li:nth-child(1) { transition-delay: 60ms; }
  body.has-nav-toggle .site-nav.is-open .site-nav-list > li:nth-child(2) { transition-delay: 100ms; }
  body.has-nav-toggle .site-nav.is-open .site-nav-list > li:nth-child(3) { transition-delay: 140ms; }
  body.has-nav-toggle .site-nav.is-open .site-nav-list > li:nth-child(4) { transition-delay: 180ms; }
  body.has-nav-toggle .site-nav.is-open .site-nav-list > li:nth-child(5) { transition-delay: 220ms; }
  body.has-nav-toggle .site-nav.is-open .site-nav-list > li:nth-child(6) { transition-delay: 260ms; }

  @media (prefers-reduced-motion: reduce) {
    body.has-nav-toggle .site-nav,
    .nav-scrim,
    body.has-nav-toggle .site-nav .site-nav-list > li { transition: none; }
    body.has-nav-toggle .site-nav .site-nav-list > li { opacity: 1; transform: none; }
  }

  /* The bars become a cross while the drawer is open. */
  body.nav-open .nav-toggle__bars { background: transparent; }
  body.nav-open .nav-toggle__bars::before { inset-block-start: 0; transform: rotate(45deg); }
  body.nav-open .nav-toggle__bars::after { inset-block-start: 0; transform: rotate(-45deg); }
  .nav-toggle__bars::before,
  .nav-toggle__bars::after { transition: transform 240ms ease, inset-block-start 240ms ease; }
  .nav-toggle { position: relative; z-index: 70; }
  .site-header { position: relative; }
  /* the links live in .site-nav-list, so that is the flex container to turn */
  body.has-nav-toggle .site-nav .site-nav-list {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    inline-size: 100%;
  }
  body.has-nav-toggle .site-nav .site-nav-list a {
    min-block-size: var(--z-tap);
    display: flex;
    align-items: center;
    font-size: var(--t-md);
    border-block-end: var(--z-hair) solid var(--c-line-soft);
  }
  body.has-nav-toggle .site-nav .site-nav-list li:last-child a { border-block-end: 0; }
  /* the header already carries Donate on this width */
  body.has-nav-toggle .site-nav .nav-cta { display: none; }

  /* The lockup is two marks side by side. On a phone the district mark alone
     is the recognisable one and leaves room for Donate and the menu. */
  .site-header .brand .lci { display: none; }
  .site-header .brand { flex: none; }
  .header-cta { flex: none; padding-inline: var(--s-3); font-size: var(--t-sm); }
}

/* 5.24 Footer columns fold on a phone.
   Four stacked lists ran most of a screen on their own. details/summary keeps
   it native: the markup ships open, and the script closes it only on narrow
   screens where it can also reopen it. */
.footer-col > summary {
  list-style: none;
  cursor: default;
}
.footer-col > summary::-webkit-details-marker { display: none; }
.footer-col > summary h2 { display: inline; margin: 0; }

@media (max-width: 40em) {
  .footer-col > summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    min-block-size: var(--z-tap);
    cursor: pointer;
    border-block-end: var(--z-hair) solid var(--hair-on-brand-soft);
  }
  .footer-col > summary::after {
    content: "+";
    font-size: var(--t-lg);
    font-weight: 700;
    color: var(--c-gold);
    line-height: var(--lh-flat);
  }
  .footer-col[open] > summary::after { content: "\2212"; }
  .footer-col > ul { padding-block: var(--s-2); }
  .footer-grid > .footer-col + .footer-col { margin-block-start: var(--s-1); }
  .site-footer li a { min-block-size: var(--z-tap); display: flex; align-items: center; }
}


/* 5.25 Whole-card targets.
   A card title was a 25px tall target on a phone. Padding the link would only
   push the layout around, so the title's pseudo-element is stretched over the
   card instead: the whole card becomes the tap target, which is what people
   already assume. The media anchor below it is decorative and aria-hidden. */
.event-card,
.post-card { position: relative; }
.event-card__body h3 a::after,
.post-card__body h2 a::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
}
.event-card__media,
.post-card__media { z-index: 0; }

@media (max-width: 40em) {
  .more,
  .event .event-kind a {
    min-block-size: var(--z-tap);
    display: inline-flex;
    align-items: center;
  }
}


/* 5.26 The directory as a list on a phone.
   Sixty-three portrait cards stacked one per row ran to 26,800px, about
   sixty-eight screens. A row with the photograph beside the name reads faster
   and keeps the type large. The Governor's team keeps its card. */
@media (max-width: 40em) {
  .officer-grid:not(.officer-grid--lead) {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s-3);
  }
  .officer-grid:not(.officer-grid--lead) .officer {
    flex-direction: row;
    align-items: center;
    gap: var(--s-3);
  }
  .officer-grid:not(.officer-grid--lead) .officer__portrait {
    inline-size: var(--z-officer-row);
    max-inline-size: none;
    flex: none;
  }
  .officer-grid:not(.officer-grid--lead) .officer__body { min-inline-size: 0; }
  /* the two-line floor aligns a grid; in a list it only adds gaps */
  .officer-grid:not(.officer-grid--lead) .officer__role { min-block-size: 0; }
}


/* 5.27 Aligning the directory cards.
   The role is the only variable line, and it runs from one to four lines
   depending on the office and the width, which left names up to 37px out of
   step across a row. A fixed floor would have to reserve four lines on every
   card to be safe, which is a lot of dead space under "District Diabetes
   Chairperson".

   Subgrid solves it properly: the card adopts the grid's rows, so the portrait,
   role, name and club of every card in a row share the same four tracks and
   line up whatever the role does. A fifth, empty track carries the separation
   between rows of cards, because the grid's own row-gap is doing the tighter
   spacing inside each card.

   Mobile is excluded: there the directory is a single-column list where there
   is nothing to align against. The two-line floor above stays as the fallback
   for anything without subgrid. */
@media (min-width: 40.0625em) {
  @supports (grid-template-rows: subgrid) {
    .officer-grid:not(.officer-grid--lead) {
      grid-auto-rows: auto;
      row-gap: var(--s-1);
      column-gap: var(--s-4);
    }
    /* A subgrid uses its parent's gutters unless it sets its own, so `gap: 0`
       here closed every gap inside the card: the name sat flush on the role and
       the role flush on the photograph. Letting the 8px row-gap through gives
       the card its line spacing back. */
    .officer-grid:not(.officer-grid--lead) .officer {
      display: grid;
      grid-template-rows: subgrid;
      grid-row: span 5;
    }
    /* the photograph wants more air under it than the lines want between them */
    .officer-grid:not(.officer-grid--lead) .officer__portrait {
      margin-block-end: var(--s-1);
    }
    /* 8px + 14px + 8px, so cards sit one --s-4 apart, matching the gutter */
    .officer-grid:not(.officer-grid--lead) .officer::after {
      content: "";
      display: block;
      min-block-size: var(--s-2);
    }
    .officer-grid:not(.officer-grid--lead) .officer__body {
      display: grid;
      grid-template-rows: subgrid;
      grid-row: span 3;
    }
    /* subgrid is doing the aligning now, so the floor only adds a gap */
    .officer-grid:not(.officer-grid--lead) .officer__role { min-block-size: 0; }
  }
}


/* 5.28 About page.
   Same structural language as the Officers page: a photographic heading band,
   then alternating canvas and tint bands, each a section-head over a grid. The
   two pages are the district's front doors and should not read as two
   different websites, so everything here uses the tokens already in play and
   adds no new type sizes or colours. */

/* The four counts. A number this size is the one place display type earns its
   keep on an internal page, and it is the fastest answer to "how big is this
   district". */
.stat-strip {
  list-style: none;
  padding: 0;
  margin-block-start: var(--s-5);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(var(--z-stat-card), 100%), 1fr));
  gap: var(--s-3);
}
.stat {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  padding: var(--s-4) var(--s-3);
  border-radius: var(--r-md);
  background: var(--c-tint);
  border-block-start: var(--z-rule) solid var(--c-gold);
}
.band-tint .stat { background: var(--c-canvas); }
.stat__value {
  font-family: var(--f-serif);
  font-size: var(--t-stat);
  font-weight: 700;
  line-height: var(--lh-flat);
  color: var(--c-brand);
  letter-spacing: var(--tr-tightest);
}
.stat__label {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--c-muted);
  line-height: var(--lh-snug);
}

/* Copy beside an image. Two columns on a laptop, stacked on a phone, and the
   reverse modifier flips the order on the wide layout only, so the reading
   order on a phone is always copy first. */
.split {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: var(--s-5);
  align-items: center;
}
.split--even { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: start; }
.split__media {
  margin: 0;
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--sh-deep);
}
.split__media img { inline-size: 100%; block-size: auto; display: block; }
.split__action { margin-block-start: var(--s-4); }

.pull-quote {
  margin: var(--s-4) 0 0;
  padding-inline-start: var(--s-4);
  border-inline-start: var(--z-rule) solid var(--c-gold);
}
.pull-quote blockquote {
  margin: 0;
  font-family: var(--f-serif);
  font-size: var(--t-xl);
  line-height: var(--lh-snug);
  color: var(--c-canvas);
}
.pull-quote figcaption {
  margin-block-start: var(--s-2);
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--c-gold);
}

/* The five regions. Same card rhythm as an officer card: a small tracked label,
   then the name, then the quiet line. */
.area-grid {
  list-style: none;
  padding: 0;
  margin-block-start: var(--s-5);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(var(--z-area-card), 100%), 1fr));
  gap: var(--s-3);
  align-items: stretch;
}

/* Three points beside a statement, separated by a hairline rather than boxed.
   The gold rule is the only ornament and it grows on hover, which is enough
   movement for a list that is not a set of links. */
.point-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
}
.point {
  position: relative;
  padding: var(--s-4) 0 var(--s-4) var(--s-4);
}
.point + .point { border-block-start: var(--z-hair) solid var(--c-line); }
.point::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: var(--s-4);
  inline-size: var(--z-rule);
  block-size: var(--s-3);
  border-radius: var(--r-pill);
  background: var(--c-gold);
  transition: block-size 260ms cubic-bezier(0.4, 0, 0.2, 1);
}
.point:hover::before { block-size: calc(100% - var(--s-5)); }
@media (prefers-reduced-motion: reduce) {
  .point::before { transition: none; }
  .point:hover::before { block-size: var(--s-3); }
}
.point__title {
  font-family: var(--f-sans);
  font-size: var(--t-lg);
  font-weight: 700;
  letter-spacing: var(--tr-tightest);
  line-height: var(--lh-snug);
  color: var(--c-ink);
}
.point__copy {
  margin: var(--s-1) 0 0;
  color: var(--c-body);
  font-size: var(--t-base);
  line-height: var(--lh-relaxed);
}

/* A region card carries a photograph taken in that region, so the picture is
   the top of the card and the copy sits under it. Text alone made this the
   flattest band on the page. */
.area {
  display: flex;
  flex-direction: column;
  border-radius: var(--r-md);
  background: var(--c-canvas);
  border: var(--z-hair) solid var(--c-line);
  overflow: hidden;
}
.band-canvas .area { background: var(--c-tint); }
.area__media {
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--c-brand-deep);
}
.area__media img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  display: block;
  transition: transform 320ms cubic-bezier(0.4, 0, 0.2, 1);
}
.area:hover .area__media img { transform: scale(1.05); }
@media (prefers-reduced-motion: reduce) {
  .area__media img { transition: none; }
  .area:hover .area__media img { transform: none; }
}
.area__body {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  padding: var(--s-3);
}
.area__zones {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--c-brand);
  line-height: var(--lh-snug);
}
.area__name {
  font-size: var(--t-lg);
  font-weight: 700;
  color: var(--c-ink);
  line-height: var(--lh-snug);
  letter-spacing: var(--tr-tightest);
  order: -1;
}
/* The card is the target. One anchor, stretched over it, so there is one thing
   in the tab order rather than a link on the name and a dead photograph. */
.area { position: relative; }
.area__name a { color: inherit; text-decoration: none; }
.area__name a::after { content: ""; position: absolute; inset: 0; z-index: 1; }
.area:hover .area__name a { color: var(--c-brand); text-decoration: underline; }
.area__name a:focus-visible { outline: none; }
.area:focus-within { outline: var(--z-rule) solid var(--c-gold); outline-offset: var(--s-1); }
.section-foot--pair { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4); }
.area__note {
  color: var(--c-muted);
  font-size: var(--t-sm);
  line-height: var(--lh-snug);
  margin: 0;
}

/* We Serve. Two words, the oldest thing on the page, so they get room. */
.motto {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--s-2);
  padding: var(--s-5) var(--s-4);
  border-radius: var(--r-lg);
  background: var(--c-canvas);
  box-shadow: var(--sh-raised);
}
.motto__mark { inline-size: var(--z-icon); block-size: auto; display: block; }
.motto__text {
  margin: 0;
  font-family: var(--f-serif);
  font-size: var(--t-display-sm);
  font-weight: 700;
  line-height: var(--lh-flat);
  color: var(--c-brand);
}
.motto__note {
  margin: 0;
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--c-muted);
}

.section-foot { margin-block-start: var(--s-4); }
.actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-block-start: var(--s-5);
}
.actions.is-centered { justify-content: center; }

@media (max-width: 52em) {
  .split { grid-template-columns: minmax(0, 1fr); gap: var(--s-4); }
  .split--reverse .split__copy { order: -1; }
}

@media (max-width: 40em) {
  .stat-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-2); }
  .stat { padding: var(--s-3) var(--s-2); }
  .area-grid { grid-template-columns: minmax(0, 1fr); gap: var(--s-2); }
  .point-list { margin-block-start: var(--s-3); }
  .point { padding-block: var(--s-3); }
  .area { flex-direction: row; align-items: stretch; }
  .area__media { inline-size: var(--z-area-thumb); flex: none; aspect-ratio: auto; }
  .area__body { min-inline-size: 0; justify-content: center; }
  .actions .btn { inline-size: 100%; justify-content: center; }
}

/* The district's own photographs. Four across on a laptop, two on a phone, all
   on the same 3:2 so the mosaic reads as one block rather than eight pictures.
   The source frames are 414px because that is what the district's Facebook page
   serves, so they are never asked to fill more than a quarter of the width. */
.photo-grid {
  list-style: none;
  padding: 0;
  margin-block-start: var(--s-5);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(var(--z-photo-card), 100%), 1fr));
  gap: var(--s-2);
}
.photo {
  margin: 0;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--c-brand-deep);
  aspect-ratio: 3 / 2;
}
.photo img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  display: block;
  transition: transform 320ms cubic-bezier(0.4, 0, 0.2, 1);
}
.photo:hover img { transform: scale(1.04); }
@media (prefers-reduced-motion: reduce) {
  .photo img { transition: none; }
  .photo:hover img { transform: none; }
}

@media (max-width: 40em) {
  .photo-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-1); }
}

/* 5.29 Ways We Serve.
   Eight causes, so the card has to stay quiet and the icon has to do the
   recognising. The old page ran one enormous icon per cause down a single
   column and came to 8,292px, most of it white space. */
.cause-grid {
  list-style: none;
  padding: 0;
  margin-block-start: var(--s-5);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(var(--z-cause-card), 100%), 1fr));
  gap: var(--s-3);
}
.cause-card {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding: var(--s-4) var(--s-3);
  border-radius: var(--r-md);
  background: var(--c-canvas);
  border: var(--z-hair) solid var(--c-line);
  transition: transform 200ms ease, box-shadow 200ms ease;
}
.cause-card:hover { transform: translateY(calc(var(--s-1) * -0.4)); box-shadow: var(--sh-raised); }
@media (prefers-reduced-motion: reduce) {
  .cause-card { transition: none; }
  .cause-card:hover { transform: none; }
}
.cause-card__icon {
  inline-size: var(--z-icon);
  block-size: var(--z-icon);
  aspect-ratio: 1;
  border-radius: var(--r-pill);
  background: var(--c-tint);
  display: grid;
  place-items: center;
  overflow: hidden;
}
.cause-card__icon img { inline-size: 100%; block-size: 100%; object-fit: cover; display: block; }
.cause-card__title {
  font-family: var(--f-sans);
  font-size: var(--t-lg);
  font-weight: 700;
  letter-spacing: var(--tr-tightest);
  line-height: var(--lh-snug);
  color: var(--c-ink);
}
.cause-card__copy {
  margin: 0;
  color: var(--c-body);
  font-size: var(--t-base);
  line-height: var(--lh-relaxed);
}

/* Three district-wide pushes, in order, on the dark band. The date leads
   because the question people bring to this section is when, not what. */
.week-list {
  list-style: none;
  padding: 0;
  margin-block-start: var(--s-5);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(var(--z-area-card), 100%), 1fr));
  gap: var(--s-4);
  counter-reset: none;
}
.week {
  padding-block-start: var(--s-3);
  border-block-start: var(--z-rule) solid var(--c-gold);
}
.week__when {
  display: block;
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--c-gold);
  line-height: var(--lh-snug);
}
.week__title {
  margin-block-start: var(--s-1);
  font-family: var(--f-serif);
  font-size: var(--t-2xl);
  font-weight: 700;
  line-height: var(--lh-tight);
  color: var(--c-canvas);
}
.week__copy {
  margin: var(--s-1) 0 0;
  color: var(--c-on-brand);
  font-size: var(--t-base);
  line-height: var(--lh-relaxed);
}

/* The stat strip carries three tall numbers here rather than four short ones,
   so it stacks in one column beside the copy instead of running across. */
.stat-strip--tall { grid-template-columns: minmax(0, 1fr); margin-block-start: 0; gap: var(--s-2); }
.stat-strip--tall .stat { display: grid; grid-template-columns: auto 1fr; align-items: baseline; gap: var(--s-3); }

@media (max-width: 40em) {
  .cause-grid { grid-template-columns: minmax(0, 1fr); gap: var(--s-2); }
  .week-list { grid-template-columns: minmax(0, 1fr); gap: var(--s-3); }
}

/* 5.30 Aligning the news cards.
   Same problem the officer directory had and the same fix: the category label
   runs to one or two lines depending on its name, so without subgrid the
   headline of each card in a row starts at a different height. */
@media (min-width: 40.0625em) {
  @supports (grid-template-rows: subgrid) {
    .post-grid { grid-auto-rows: auto; }
    .post-card { display: grid; grid-template-rows: subgrid; grid-row: span 4; }
    .post-card__body {
      display: grid;
      grid-template-rows: subgrid;
      grid-row: span 3;
      gap: var(--s-1);
    }
  }
}

/* 5.31 Contact.
   Three ways in, then what to put in the subject line. No form: the mail plugin
   on this install is deactivated, so a form would accept a message and drop it,
   which is worse than an address that works. */
.channel-grid,
.route-grid {
  list-style: none;
  padding: 0;
  margin-block-start: var(--s-5);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(var(--z-cause-card), 100%), 1fr));
  gap: var(--s-3);
}
.channel {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  padding: var(--s-4) var(--s-3);
  border-radius: var(--r-md);
  background: var(--c-tint);
  border-block-start: var(--z-rule) solid var(--c-gold);
}
.channel__icon {
  display: inline-grid;
  place-items: center;
  inline-size: var(--z-control);
  block-size: var(--z-control);
  color: var(--c-brand);
  flex: none;
}
.channel__icon svg { inline-size: 100%; block-size: auto; display: block; }
.channel__label {
  display: flex;
  align-items: center;
  gap: var(--s-1);
  min-block-size: var(--z-control);
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--c-brand);
  line-height: var(--lh-snug);
}
.channel__value {
  font-family: var(--f-sans);
  font-size: var(--t-lg);
  font-weight: 700;
  letter-spacing: var(--tr-tightest);
  line-height: var(--lh-snug);
  color: var(--c-ink);
  text-decoration: none;
  /* the whole card is the target; the address is just where it is written */
  position: static;
}
.channel { position: relative; }
.channel__value::after { content: ""; position: absolute; inset: 0; }
.channel:hover .channel__value { color: var(--c-brand); text-decoration: underline; }
.channel__note {
  color: var(--c-muted);
  font-size: var(--t-sm);
  line-height: var(--lh-snug);
  margin-block-start: var(--s-1);
}

.route {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  padding: var(--s-4) var(--s-3);
  border-radius: var(--r-md);
  background: var(--c-canvas);
  border: var(--z-hair) solid var(--c-line);
}
.route__title {
  font-family: var(--f-sans);
  font-size: var(--t-lg);
  font-weight: 700;
  letter-spacing: var(--tr-tightest);
  line-height: var(--lh-snug);
  color: var(--c-ink);
}
.route__copy {
  margin: 0;
  color: var(--c-body);
  font-size: var(--t-base);
  line-height: var(--lh-relaxed);
}

@media (max-width: 40em) {
  .channel-grid,
  .route-grid { grid-template-columns: minmax(0, 1fr); gap: var(--s-2); }
}

/* 5.32 The club map.
   An inline SVG of Northern Luzon with a pin per region, and a panel that
   swaps to that region's clubs. The switching is six radio inputs and CSS,
   with no script at all: every pin is a label, so it is keyboard reachable and
   it works with JavaScript off. */
.clubmap {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: var(--s-5);
  align-items: start;
  margin-block-start: var(--s-5);
}
.clubmap__state {
  position: absolute;
  inline-size: var(--z-hair);
  block-size: var(--z-hair);
  overflow: hidden;
  clip-path: inset(50%);
}
.clubmap__figure {
  position: relative;
  border-radius: var(--r-lg);
  background: var(--c-tint);
  padding: var(--s-3);
}
.clubmap__svg { inline-size: 100%; block-size: auto; display: block; }
.clubmap__land path {
  fill: var(--c-line-blue);
  stroke: var(--c-canvas);
  stroke-width: 1;
  stroke-linejoin: round;
  transition: fill 200ms ease;
}
.clubmap__figure:hover .clubmap__land path { fill: var(--c-line-deep); }

/* A pin is a point, and the label is the tap target centred on it.
   The first version put translate(-50%, -50%) on a label that contained the dot
   AND the name plate, so the pair was centred on the coordinate and every dot
   sat left of its city by half the plate's width. Baguio-Cordillera has the
   longest name and landed 108px out, in the South China Sea.
   The label is a --z-tap square now: symmetric, so the transform is right, it
   is the 44px target on its own, and the dot inside it can be any size. */
.clubmap__plot { position: relative; }
.clubmap__pin {
  position: absolute;
  transform: translate(-50%, -50%);
  inline-size: var(--z-tap);
  block-size: var(--z-tap);
  display: grid;
  place-items: center;
  cursor: pointer;
  z-index: 1;
}
.clubmap__dot {
  display: grid;
  place-items: center;
  inline-size: var(--z-pin);
  block-size: var(--z-pin);
  border-radius: var(--r-pill);
  background: var(--c-brand);
  color: var(--c-canvas);
  font-size: var(--t-micro);
  font-weight: 700;
  box-shadow: 0 0 0 var(--z-rule) var(--c-canvas), var(--sh-raised);
  transition: transform 200ms cubic-bezier(0.4, 0, 0.2, 1), background-color 200ms ease;
}
.clubmap__pin:hover .clubmap__dot { transform: scale(1.12); background: var(--c-brand-deep); }
/* Three of the five seats are within 60km of each other on the west coast, so
   the tags overlapped at rest and the map read as a pile of boxes. The dot and
   its count are always there; the name arrives on hover, on focus, and on the
   region being shown, which is when you actually want to read it. */
.clubmap__tag {
  display: flex;
  flex-direction: column;
  padding: var(--s-1) var(--s-2);
  border-radius: var(--r-sm);
  background: var(--c-canvas);
  box-shadow: var(--sh-raised);
  white-space: nowrap;
  position: absolute;
  inset-inline-start: calc(100% + var(--s-1));
  opacity: 0;
  transform: translateX(calc(var(--s-1) * -0.5));
  transition: opacity 180ms ease, transform 180ms ease;
  pointer-events: none;
}
.clubmap__pin:hover .clubmap__tag { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .clubmap__tag { transition: none; }
}
.clubmap__region {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--c-brand);
  line-height: var(--lh-snug);
}
.clubmap__seat { font-size: var(--t-micro); color: var(--c-muted); line-height: var(--lh-snug); }

/* The pin for the region on show gets the gold, so the map and the panel always
   agree about where you are. */
#rg-baguio-cordillera:checked ~ .clubmap__figure .clubmap__pin[data-region="baguio-cordillera"] .clubmap__dot,
#rg-cagayan:checked           ~ .clubmap__figure .clubmap__pin[data-region="cagayan"] .clubmap__dot,
#rg-pangasinan:checked        ~ .clubmap__figure .clubmap__pin[data-region="pangasinan"] .clubmap__dot,
#rg-ilocos:checked            ~ .clubmap__figure .clubmap__pin[data-region="ilocos"] .clubmap__dot,
#rg-la-union:checked          ~ .clubmap__figure .clubmap__pin[data-region="la-union"] .clubmap__dot {
  background: var(--c-gold);
  color: var(--c-ink-deep);
  transform: scale(1.18);
}
#rg-baguio-cordillera:checked ~ .clubmap__figure .clubmap__pin[data-region="baguio-cordillera"],
#rg-cagayan:checked           ~ .clubmap__figure .clubmap__pin[data-region="cagayan"],
#rg-pangasinan:checked        ~ .clubmap__figure .clubmap__pin[data-region="pangasinan"],
#rg-ilocos:checked            ~ .clubmap__figure .clubmap__pin[data-region="ilocos"],
#rg-la-union:checked          ~ .clubmap__figure .clubmap__pin[data-region="la-union"] { z-index: 2; }
#rg-baguio-cordillera:checked ~ .clubmap__figure .clubmap__pin[data-region="baguio-cordillera"] .clubmap__tag,
#rg-cagayan:checked           ~ .clubmap__figure .clubmap__pin[data-region="cagayan"] .clubmap__tag,
#rg-pangasinan:checked        ~ .clubmap__figure .clubmap__pin[data-region="pangasinan"] .clubmap__tag,
#rg-ilocos:checked            ~ .clubmap__figure .clubmap__pin[data-region="ilocos"] .clubmap__tag,
#rg-la-union:checked          ~ .clubmap__figure .clubmap__pin[data-region="la-union"] .clubmap__tag {
  opacity: 1;
  transform: none;
}
/* focus has to be visible on the label, because the input it drives is hidden */
.clubmap__state:focus-visible ~ .clubmap__figure .clubmap__pin .clubmap__dot,
.clubmap__state:focus-visible ~ .clubmap__panel .region-list__btn { outline: var(--z-rule) solid var(--c-gold); outline-offset: var(--s-1); }

/* The map sticks and the list scrolls, not the other way round. A region can
   hold 22 clubs, so the panel is the long thing on the page, and scrolling it
   inside its own box would hide the page's own scrollbar behaviour and trap a
   trackpad. */
.clubmap__figure { position: sticky; inset-block-start: var(--s-3); }
.clubmap__panel {
  border-radius: var(--r-lg);
  background: var(--c-canvas);
  border: var(--z-hair) solid var(--c-line);
  padding: var(--s-4);
}
.band-canvas .clubmap__panel { background: var(--c-tint); }
.clubmap__pane { display: none; }
#rg-all:checked               ~ .clubmap__panel .clubmap__pane[data-region="all"],
#rg-baguio-cordillera:checked ~ .clubmap__panel .clubmap__pane[data-region="baguio-cordillera"],
#rg-cagayan:checked           ~ .clubmap__panel .clubmap__pane[data-region="cagayan"],
#rg-pangasinan:checked        ~ .clubmap__panel .clubmap__pane[data-region="pangasinan"],
#rg-ilocos:checked            ~ .clubmap__panel .clubmap__pane[data-region="ilocos"],
#rg-la-union:checked          ~ .clubmap__panel .clubmap__pane[data-region="la-union"] { display: block; }

.clubmap__lead { margin: 0 0 var(--s-3); color: var(--c-body); font-size: var(--t-base); }
.clubmap__note { margin: var(--s-3) 0 0; color: var(--c-muted); font-size: var(--t-sm); line-height: var(--lh-snug); }
.clubmap__panehead {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s-2);
  padding-block-end: var(--s-3);
  border-block-end: var(--z-hair) solid var(--c-line);
}
.clubmap__panehead h3 {
  font-family: var(--f-sans);
  font-size: var(--t-xl);
  font-weight: 700;
  letter-spacing: var(--tr-tightest);
  color: var(--c-ink);
}
.clubmap__panehead p { margin: 0; color: var(--c-muted); font-size: var(--t-sm); }
.clubmap__back {
  margin-inline-start: auto;
  cursor: pointer;
  min-block-size: var(--z-tap);
  display: inline-flex;
  align-items: center;
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--c-brand);
}
.clubmap__back:hover { color: var(--c-brand-deep); text-decoration: underline; }

.region-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: var(--s-1); }
.region-list__btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2);
  min-block-size: var(--z-tap);
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-md);
  background: var(--c-canvas);
  border: var(--z-hair) solid var(--c-line);
  cursor: pointer;
}
.band-canvas .region-list__btn { background: var(--c-canvas); }
.region-list__btn:hover { border-color: var(--c-brand); }
.region-list__name { font-weight: 700; color: var(--c-ink); }
.region-list__count { font-size: var(--t-sm); color: var(--c-muted); }

/* A club row: mark, name, where it sits, then its president, secretary and
   treasurer. Same shape in the panel and in the full roll. */
.club-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; }
.club { display: flex; gap: var(--s-3); padding-block: var(--s-3); }
.club + .club { border-block-start: var(--z-hair) solid var(--c-line); }
.club__mark {
  flex: none;
  display: grid;
  place-items: center;
  inline-size: var(--z-club-mark);
  block-size: var(--z-club-mark);
  border-radius: var(--r-md);
  background: linear-gradient(140deg, var(--c-brand) 0%, var(--c-brand-deep) 100%);
  color: var(--c-gold);
  font-family: var(--f-serif);
  font-weight: 700;
  font-size: var(--t-base);
  letter-spacing: var(--tr-tightest);
}
/* A club that has sent its crest shows it where the initials would be. Same
   box, so a list of clubs stays a list whichever a club has. */
.club__mark--crest,
.club-row__mark--crest {
  background: none;
  object-fit: contain;
  border-radius: 0;
}
.club__body { display: flex; flex-direction: column; gap: var(--s-1); min-inline-size: 0; }
.club__name {
  font-family: var(--f-sans);
  font-size: var(--t-md);
  font-weight: 700;
  letter-spacing: var(--tr-tightest);
  line-height: var(--lh-snug);
  color: var(--c-ink);
}
.club__where {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--c-brand);
  line-height: var(--lh-snug);
}
.club__people { display: flex; flex-wrap: wrap; gap: var(--s-1) var(--s-3); margin-block-start: var(--s-1); }
.club__person { display: flex; flex-direction: column; }
.club__role {
  font-size: var(--t-micro);
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--c-muted);
  line-height: var(--lh-snug);
}
.club__who { font-size: var(--t-sm); color: var(--c-body); line-height: var(--lh-snug); }

/* 5.33 The full roll.
   This was 77 cards in three columns, each with the three officers in a
   wrapping flex row. Two of them fitted on a line in one card and three in the
   next, so no column lined up with any other and card heights ran 144px to
   190px. Nothing could be read down a column, which is the only way anyone
   reads a roster. It is a table now, because it is tabular. */
.club-filters {
  margin-block-start: var(--s-5);
  padding: var(--s-3);
  border-radius: var(--r-md);
  background: var(--c-canvas);
  border: var(--z-hair) solid var(--c-line);
}
.club-filters__row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  align-items: end;
}
.club-filters__field { margin: 0; display: flex; flex-direction: column; gap: var(--s-1); min-inline-size: 0; }
.club-filters__field--grow { flex: 1 1 var(--z-club-col); }
.club-filters label {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--c-brand);
}
.club-filters input,
.club-filters select {
  min-block-size: var(--z-tap);
  padding: var(--s-1) var(--s-2);
  border-radius: var(--r-sm);
  border: var(--z-hair) solid var(--c-line-blue);
  background: var(--c-canvas);
  color: var(--c-ink);
  font-family: var(--f-sans);
  font-size: var(--t-base);
}
.club-filters input:focus-visible,
.club-filters select:focus-visible { outline: var(--z-rule) solid var(--c-gold); outline-offset: var(--s-1); }
.club-filters__go { margin: 0; display: flex; align-items: center; gap: var(--s-3); }
.club-filters__clear {
  display: inline-flex;
  align-items: center;
  min-block-size: var(--z-tap);
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--c-brand);
}
/* the submit is the no-script path; once site.js is filtering live it is noise */
.club-filters.is-live .club-filters__go .btn { display: none; }

.club-count { margin-block: var(--s-3) 0; color: var(--c-muted); font-size: var(--t-sm); }
.club-count strong { color: var(--c-ink); }

.club-table__scroll { margin-block-start: var(--s-3); }
.club-table {
  inline-size: 100%;
  border-collapse: collapse;
  background: var(--c-canvas);
  border-radius: var(--r-md);
  overflow: hidden;
  box-shadow: var(--sh-card);
}
.club-table th,
.club-table td {
  text-align: start;
  padding: var(--s-2) var(--s-3);
  vertical-align: middle;
  border-block-start: var(--z-hair) solid var(--c-line);
}
.club-table thead th {
  border-block-start: 0;
  background: var(--c-brand);
  color: var(--c-canvas);
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  position: sticky;
  inset-block-start: 0;
  z-index: 1;
}
.club-table tbody tr:hover { background: var(--c-tint); }
/* Auto layout gave the club column 470px and then wrapped "Baguio-Cordillera"
   onto two lines next to it. Fixed shares, and the two short columns never wrap. */
@media (min-width: 60.0625em) {
  .club-table { table-layout: fixed; }
  .club-table thead th:nth-child(1) { inline-size: 26%; }
  .club-table thead th:nth-child(2) { inline-size: 14%; }
  .club-table thead th:nth-child(3) { inline-size: 6%; }
  .club-table thead th:nth-child(4),
  .club-table thead th:nth-child(5),
  .club-table thead th:nth-child(6) { inline-size: 18%; }
  .club-table td:nth-of-type(1),
  .club-table td:nth-of-type(2) { white-space: nowrap; }
}
.club-table tbody th {
  font-weight: 400;
  display: flex;
  align-items: center;
  gap: var(--s-2);
}
.club-row__mark {
  flex: none;
  display: grid;
  place-items: center;
  inline-size: var(--z-control);
  block-size: var(--z-control);
  border-radius: var(--r-sm);
  background: linear-gradient(140deg, var(--c-brand) 0%, var(--c-brand-deep) 100%);
  color: var(--c-gold);
  font-family: var(--f-serif);
  font-weight: 700;
  font-size: var(--t-micro);
}
.club-row__name { font-weight: 700; color: var(--c-ink); }
.club-row__flag {
  flex: none;
  padding: 0 var(--s-1);
  border-radius: var(--r-pill);
  background: var(--c-gold);
  color: var(--c-ink-deep);
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
}
.club-table td { color: var(--c-body); font-size: var(--t-sm); }
.club-empty { margin-block-start: var(--s-4); color: var(--c-muted); }

/* On a phone a six-column table is a horizontal scrollbar nobody finds, so each
   row becomes a card and every cell carries its own column heading. */
@media (max-width: 60em) {
  .club-table thead { position: absolute; inline-size: var(--z-hair); block-size: var(--z-hair); overflow: hidden; clip-path: inset(50%); }
  .club-table,
  .club-table tbody,
  .club-table tr,
  .club-table th,
  .club-table td { display: block; }
  .club-table { box-shadow: none; background: none; }
  .club-table tbody tr {
    background: var(--c-canvas);
    border-radius: var(--r-md);
    box-shadow: var(--sh-card);
    padding: var(--s-3);
    margin-block-end: var(--s-2);
  }
  .club-table tbody tr:hover { background: var(--c-canvas); }
  .club-table th,
  .club-table td { border-block-start: 0; padding: 0; }
  .club-table tbody th { margin-block-end: var(--s-2); }
  .club-table td {
    display: grid;
    grid-template-columns: var(--z-club-label) minmax(0, 1fr);
    gap: var(--s-2);
    padding-block: var(--s-1);
  }
  /* 77 cards of six rows each ran the page to 27,000px. A club with no
     secretary does not need a line saying so. */
  .club-table td[data-empty] { display: none; }
  .club-table tbody tr { padding: var(--s-2) var(--s-3); }
  .club-table td::before {
    content: attr(data-label);
    font-size: var(--t-micro);
    font-weight: 700;
    letter-spacing: var(--tr-label);
    text-transform: uppercase;
    color: var(--c-muted);
    line-height: var(--lh-snug);
  }
  .club-filters__field--grow { flex-basis: 100%; }
  .club-filters__field { flex: 1 1 var(--z-club-col); }
}
@media (max-width: 40em) {
  /* four stacked fields is most of a screen before a single club appears, so
     the three selects pair up */
  .club-filters__field { flex: 1 1 var(--z-club-field); }
  .club-filters__row { gap: var(--s-2); }
}

@media (max-width: 60em) {
  .clubmap { grid-template-columns: minmax(0, 1fr); }
  .clubmap__figure { position: static; max-inline-size: var(--m-tight); margin-inline: auto; }
}
@media (max-width: 40em) {
  .clubmap__tag { display: none; }
  .club__people { gap: var(--s-1) var(--s-2); }
  /* The map is 290px wide on a phone and a 44px dot covers a whole province.
     The dot shrinks, the label stays 44px, so the target does not. */
  .clubmap__pin { --z-pin: var(--z-pin-sm); }
  .clubmap__figure { padding: var(--s-2); }
  .clubmap { gap: var(--s-4); }
}

/* 5.33 District Bulletin Board.

   Thirty-two scans of A4 paper. The design problem is that a page of type,
   shrunk to card size, is texture rather than information: it says "an official
   document" and nothing else. So the card carries a real crop of the top of the
   sheet, made at build time by scripts/build-circulars.py, which is the part
   that identifies it (letterhead, date, number, TO and SUBJECT), and the title,
   date and summary beneath it are set type that can actually be read and
   searched. The scan is the evidence; the text is the index. */

.gate {
  display: flex;
  align-items: center;
  min-block-size: var(--z-hero);
}
.gate > .inner { inline-size: 100%; }
.gate__panel {
  max-inline-size: var(--m-tight);
  margin-inline: auto;
  text-align: center;
}
.gate__lock {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--z-icon);
  block-size: var(--z-icon);
  margin-block-end: var(--s-3);
  border-radius: var(--r-pill);
  background: var(--hair-on-brand);
  color: var(--c-gold);
}
.gate__panel .eyebrow { justify-content: center; }
.gate__copy {
  margin-block-start: var(--s-3);
  color: var(--c-on-brand);
  font-size: var(--t-lg);
  line-height: var(--lh-relaxed);
}
.gate__form { margin-block-start: var(--s-5); text-align: start; }
.gate__label {
  display: block;
  margin-block-end: var(--s-1);
  color: var(--c-gold);
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: var(--tr-eyebrow);
  text-transform: uppercase;
}
.gate__row { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.gate__row input {
  flex: 1 1 var(--m-card);
  min-inline-size: 0;
  min-block-size: var(--z-tap);
  padding: var(--s-2) var(--s-3);
  font: inherit;
  font-size: var(--t-md);
  color: var(--c-ink);
  background: var(--c-canvas);
  border: var(--z-hair) solid var(--c-line-blue);
  border-radius: var(--r-sm);
}
.gate__row input:focus-visible {
  outline: var(--z-rule) solid var(--c-gold);
  outline-offset: var(--z-hair);
}
.gate__hint {
  margin-block-start: var(--s-3);
  color: var(--c-on-brand);
  font-size: var(--t-sm);
  text-align: start;
}
.gate__hint a { color: var(--c-gold); text-decoration: underline; }

/* The standing reminder that this is not a public page. */
.board__flag {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  margin-block-start: var(--s-4);
  padding: var(--s-1) var(--s-3);
  border-radius: var(--r-pill);
  background: var(--hair-on-brand);
  color: var(--c-gold);
  font-size: var(--t-sm);
  font-weight: 700;
}
.board__flag span { display: inline-flex; }
.board__flag svg { inline-size: var(--z-icon-sm); block-size: var(--z-icon-sm); }

/* Filters. Hidden in the markup and revealed by the script, so with scripting
   off the board is the full list rather than a row of dead buttons. */
.board-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
  margin-block: var(--s-5) var(--s-4);
  padding-block-end: var(--s-3);
  border-block-end: var(--z-hair) solid var(--c-line);
}
.board-filters__search { position: relative; flex: 1 1 var(--m-media); min-inline-size: 0; }
.board-filters__icon {
  position: absolute;
  inset-block: 0;
  inset-inline-start: var(--s-2);
  display: flex;
  align-items: center;
  color: var(--c-steel);
  pointer-events: none;
}
.board-filters input[type="search"] {
  inline-size: 100%;
  min-block-size: var(--z-tap);
  padding: var(--s-2) var(--s-3) var(--s-2) var(--s-5);
  font: inherit;
  font-size: var(--t-base);
  color: var(--c-ink);
  background: var(--c-canvas);
  border: var(--z-hair) solid var(--c-line-blue);
  border-radius: var(--r-pill);
}
.board-filters input[type="search"]:focus-visible {
  outline: var(--z-rule) solid var(--c-brand);
  outline-offset: var(--z-hair);
}
.chips { display: flex; flex-wrap: wrap; gap: var(--s-1); }

/* The shared .chip is drawn for a dark band. On the tint it needs an edge, or
   a white pill on near-white reads as nothing at all. */
.chips .chip {
  border: var(--z-hair) solid var(--c-line-blue);
  background: var(--c-canvas);
  color: var(--c-brand);
  cursor: pointer;
  font-family: inherit;
}
.chips .chip:hover,
.chips .chip.is-on {
  border-color: var(--c-brand);
  background: var(--c-brand);
  color: var(--c-canvas);
}
.board-filters__count {
  margin-inline-start: auto;
  color: var(--c-muted);
  font-size: var(--t-sm);
  font-weight: 600;
}
.board-empty {
  padding-block: var(--s-5);
  color: var(--c-body);
  font-size: var(--t-md);
  text-align: center;
}
.board-empty .more {
  display: inline;
  margin-inline-start: var(--s-1);
  border: 0;
  background: none;
  font: inherit;
  cursor: pointer;
}

/* The grid. */
.circ-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(var(--z-circ-col), 100%), 1fr));
  gap: var(--s-4);
}
.circ {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--c-canvas);
  border: var(--z-hair) solid var(--c-line);
  border-radius: var(--r-md);
  overflow: hidden;
  box-shadow: var(--sh-card);
  transition: box-shadow 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
}
.circ:hover {
  border-color: var(--c-line-blue);
  box-shadow: var(--sh-raised);
  transform: translateY(calc(var(--s-1) * -0.25));
}

/* The button is the whole card's target: a 44px control in the corner of a
   card people will tap anywhere on is a target that tests fine and fails in
   the hand. */
.circ__open {
  position: static;
  display: block;
  inline-size: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
  text-align: start;
  font: inherit;
}
.circ__open::after { content: ""; position: absolute; inset: 0; z-index: 1; }
.circ__open:focus-visible { outline: 0; }
.circ__open:focus-visible::after {
  outline: var(--z-rule) solid var(--c-gold-ink);
  outline-offset: calc(var(--s-1) * -0.25);
  border-radius: var(--r-md);
}
.circ__sheet {
  display: block;
  position: relative;
  aspect-ratio: 620 / 368;
  overflow: hidden;
  background: var(--c-tint);
  border-block-end: var(--z-hair) solid var(--c-line);
}
.circ__sheet img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: top center;
}
.circ__no,
.circ__tag {
  position: absolute;
  z-index: 2;
  inset-block-start: var(--s-2);
  padding: calc(var(--s-1) * 0.5) var(--s-2);
  border-radius: var(--r-pill);
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: var(--tr-label);
}
.circ__no {
  inset-inline-start: var(--s-2);
  background: var(--c-brand-deep);
  color: var(--c-canvas);
}
.circ__tag {
  inset-inline-end: var(--s-2);
  background: var(--c-gold);
  color: var(--c-brand-deep);
  text-transform: uppercase;
}
.circ__body {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  flex: 1;
  padding: var(--s-3);
}
.circ__date {
  color: var(--c-brand);
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
}
.circ__title {
  font-family: var(--f-sans);
  font-size: var(--t-lg);
  font-weight: 700;
  line-height: var(--lh-snug);
  color: var(--c-ink);
}
.circ__summary {
  color: var(--c-body);
  font-size: var(--t-sm);
  line-height: var(--lh-relaxed);
}
.circ__note {
  padding-inline-start: var(--s-2);
  border-inline-start: var(--z-rule) solid var(--c-gold);
  color: var(--c-muted);
  font-size: var(--t-micro);
  font-weight: 600;
}
.circ__meta {
  display: flex;
  flex-wrap: wrap;
  gap: calc(var(--s-1) * 0.5) var(--s-2);
  margin-block-start: auto;
  padding-block-start: var(--s-2);
  border-block-start: var(--z-hair) solid var(--c-line);
  color: var(--c-muted);
  font-size: var(--t-micro);
}
.circ__meta span + span { padding-inline-start: var(--s-2); border-inline-start: var(--z-hair) solid var(--c-line); }

/* The replaced shelf: closed by default, because nothing in it is in force. */
.shelf {
  border: var(--z-hair) solid var(--c-line);
  border-radius: var(--r-md);
  background: var(--c-tint);
}
.shelf__head {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  min-block-size: var(--z-tap);
  padding: var(--s-3);
  cursor: pointer;
  list-style: none;
}
.shelf__head::-webkit-details-marker { display: none; }
.shelf__head::after {
  content: "";
  margin-inline-start: auto;
  inline-size: var(--z-control);
  block-size: var(--z-control);
  border-inline-end: var(--z-bar) solid var(--c-brand);
  border-block-end: var(--z-bar) solid var(--c-brand);
  transform: rotate(45deg);
  transition: transform 0.18s ease;
}
.shelf[open] .shelf__head::after { transform: rotate(-135deg); }
.shelf__title { font-weight: 700; color: var(--c-ink); }
.shelf__count {
  min-inline-size: var(--z-control);
  padding: 0 var(--s-1);
  border-radius: var(--r-pill);
  background: var(--c-line-blue);
  color: var(--c-brand-deep);
  font-size: var(--t-micro);
  font-weight: 700;
  text-align: center;
}
.shelf__copy {
  padding: 0 var(--s-3) var(--s-3);
  color: var(--c-body);
  font-size: var(--t-sm);
  line-height: var(--lh-relaxed);
}
.shelf__list { padding: 0 var(--s-3) var(--s-3); }
.shelf__item + .shelf__item { border-block-start: var(--z-hair) solid var(--c-line-deep); }
.shelf__open {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  inline-size: 100%;
  min-block-size: var(--z-tap);
  padding: var(--s-2) 0;
  border: 0;
  background: none;
  cursor: zoom-in;
  text-align: start;
  font: inherit;
}
.shelf__no {
  flex: none;
  padding: calc(var(--s-1) * 0.5) var(--s-2);
  border-radius: var(--r-pill);
  background: var(--c-line-blue);
  color: var(--c-brand-deep);
  font-size: var(--t-micro);
  font-weight: 700;
}
.shelf__body { display: flex; flex-direction: column; gap: calc(var(--s-1) * 0.5); }
.shelf__name { color: var(--c-ink); font-size: var(--t-sm); font-weight: 600; }
.shelf__note { color: var(--c-muted); font-size: var(--t-micro); }
.shelf__date { margin-inline-start: auto; flex: none; color: var(--c-muted); font-size: var(--t-micro); }

/* The reader. */
body.has-reader { overflow: hidden; }
.reader { position: fixed; inset: 0; z-index: 90; background: var(--c-ink); }
.reader__panel {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
}
.reader__bar,
.reader__foot {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex: none;
  min-block-size: var(--z-reader-bar);
  padding: var(--s-1) var(--s-3);
  background: var(--c-ink-deep);
  color: var(--c-canvas);
}
.reader__title { margin-block: calc(var(--s-1) * 0.25); }
.reader__id { min-inline-size: 0; }
.reader__no {
  color: var(--c-gold);
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
}
.reader__title {
  font-family: var(--f-sans);
  font-size: var(--t-lg);
  font-weight: 700;
  line-height: var(--lh-snug);
  color: var(--c-canvas);
}
.reader__date { color: var(--c-on-brand); font-size: var(--t-micro); }
.reader__bar > .iconbtn { margin-inline-start: auto; flex: none; }
.reader__zoom { display: flex; align-items: center; gap: var(--s-1); }
.iconbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--z-tap);
  block-size: var(--z-tap);
  padding: 0;
  border: var(--z-hair) solid var(--hair-on-brand);
  border-radius: var(--r-sm);
  background: none;
  color: var(--c-canvas);
  cursor: pointer;
  font: inherit;
}
.iconbtn:hover { background: var(--hair-on-brand); }
.iconbtn:disabled { opacity: 0.3; cursor: default; }
.iconbtn:disabled:hover { background: none; }
.iconbtn--text { inline-size: auto; padding-inline: var(--s-2); font-size: var(--t-micro); font-weight: 700; }
.iconbtn--close { border-color: var(--c-gold); color: var(--c-gold); }

.reader__stage {
  position: relative;
  flex: 1;
  min-block-size: 0;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  touch-action: none;
  background: var(--c-ink);
}
.reader__sheet {
  max-inline-size: 100%;
  max-block-size: 100%;
  /* The page IS the content: it takes every pixel the stage can give it,
     rather than floating in the middle of a dark field. */
  inline-size: auto;
  block-size: auto;
  transform-origin: center center;
  will-change: transform;
  user-select: none;
  background: var(--c-canvas);
  box-shadow: var(--sh-deep);
}
.reader__sheet.is-zoomed { cursor: grab; }
.reader__stage.is-dragging .reader__sheet { cursor: grabbing; }

.reader__step {
  position: absolute;
  inset-block-start: 50%;
  translate: 0 -50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--z-tap);
  block-size: var(--z-tap);
  border: 0;
  border-radius: var(--r-pill);
  background: var(--scrim-strong);
  color: var(--c-canvas);
  cursor: pointer;
}
.reader__step--prev { inset-inline-start: var(--s-2); }
.reader__step--next { inset-inline-end: var(--s-2); }
.reader__step:disabled { opacity: 0.25; cursor: default; }

.reader__hint {
  position: absolute;
  inset-block-end: var(--s-3);
  inset-inline: 0;
  margin-inline: auto;
  inline-size: fit-content;
  max-inline-size: 90%;
  padding: var(--s-1) var(--s-3);
  border-radius: var(--r-pill);
  background: var(--scrim-strong);
  color: var(--c-canvas);
  font-size: var(--t-micro);
  text-align: center;
  transition: opacity 0.4s ease;
}
.reader__hint.is-gone { opacity: 0; pointer-events: none; }

.reader__pages { color: var(--c-on-brand); font-size: var(--t-micro); font-weight: 700; }
.reader__actions { display: flex; align-items: center; gap: var(--s-2); margin-inline: auto; }
.reader__pages { flex: none; }
.reader__actions .btn { display: inline-flex; align-items: center; gap: var(--s-1); }
.reader__actions .btn-ghost { border-color: var(--hair-on-brand); color: var(--c-canvas); }
.reader__actions .btn-ghost:hover { border-color: var(--c-canvas); color: var(--c-canvas); background: var(--hair-on-brand); }
.reader__flip { display: flex; gap: var(--s-1); }

.sharewrap { position: relative; }
.sharemenu {
  position: absolute;
  inset-block-end: calc(100% + var(--s-1));
  inset-inline-end: 0;
  inline-size: var(--z-share-menu);
  padding: var(--s-2);
  border: var(--z-hair) solid var(--c-line);
  border-radius: var(--r-md);
  background: var(--c-canvas);
  box-shadow: var(--sh-deep);
  z-index: 2;
}
.sharemenu__note {
  padding: 0 var(--s-1) var(--s-2);
  border-block-end: var(--z-hair) solid var(--c-line);
  color: var(--c-muted);
  font-size: var(--t-micro);
  line-height: var(--lh-normal);
}
.sharemenu__list { padding-block-start: var(--s-1); }
.sharemenu__list a,
.sharemenu__list button {
  display: flex;
  align-items: center;
  inline-size: 100%;
  min-block-size: var(--z-tap);
  padding-inline: var(--s-2);
  border: 0;
  border-radius: var(--r-sm);
  background: none;
  color: var(--c-brand);
  cursor: pointer;
  font: inherit;
  font-size: var(--t-sm);
  font-weight: 600;
  text-align: start;
}
.sharemenu__list a:hover,
.sharemenu__list button:hover { background: var(--c-tint); color: var(--c-brand-deep); }

@media (max-width: 60em) {
  .board-filters__count { margin-inline-start: 0; }
}

/* A phone gets the list, not the grid.

   Twenty-nine full-width cards with a sheet preview on top of each ran to
   18,600px, which is the same fault the officer directory had: a layout drawn
   for a wide screen, stacked. The sheet becomes a leading thumbnail, the text
   becomes the card, and the page comes down to roughly a third of that. This
   is the pattern section 5.26 established, applied to documents. */
@media (max-width: 40em) {
  .circ-grid { gap: var(--s-3); }
  .circ { flex-direction: row; align-items: stretch; }
  .circ__open {
    flex: none;
    inline-size: var(--z-circ-thumb);
    cursor: pointer;
  }
  .circ__sheet {
    block-size: 100%;
    aspect-ratio: auto;
    border-block-end: 0;
    border-inline-end: var(--z-hair) solid var(--c-line);
  }
  .circ__no {
    inset-block-start: var(--s-1);
    inset-inline-start: var(--s-1);
  }
  /* Side by side with the number there is no room on that thumbnail, so the
     amended flag sits under it rather than opposite it. */
  .circ__tag {
    inset-inline: var(--s-1) auto;
    inset-block-start: calc(var(--s-4) + var(--s-1));
  }
  .circ__body { padding: var(--s-2) var(--s-3); }
  .circ__title { font-size: var(--t-md); }
  .circ__summary {
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .circ__meta span:last-child { display: none; }

  /* The reader gives the sheet everything it can. One line of chrome at the
     top, two compact rows at the bottom, and no wrapped title pushing the
     page down the screen. */
  .reader__bar { min-block-size: 0; }
  .reader__title {
    font-size: var(--t-base);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .reader__date { display: none; }
  .reader__foot { min-block-size: 0; flex-wrap: wrap; row-gap: var(--s-1); }
  .reader__zoom { order: 1; }
  .reader__pages { order: 2; margin-inline: auto; }
  .reader__flip { order: 3; }
  .reader__actions { order: 4; flex-basis: 100%; margin-inline: 0; }
  .reader__actions .btn { flex: 1; justify-content: center; }
  .sharemenu { inset-inline-end: auto; inset-inline-start: 0; }
}

/* 5.34 Submenus.
   A parent is a link and a disclosure, which is two jobs, so it has two
   controls: the link goes to the section, the button beside it opens the list.
   One element doing both means a keyboard user can reach the page or the
   submenu but never both. */
.site-nav .has-sub { position: relative; }
.nav-parent { display: flex; align-items: center; gap: var(--s-1); }
.nav-sub-toggle {
  /* a button does not inherit the page's font, and the visually hidden label
     inside it was the only Arial on the whole site */
  font: inherit;
  display: grid;
  place-items: center;
  inline-size: var(--z-control);
  block-size: var(--z-control);
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  cursor: pointer;
}
.nav-sub-toggle__chev {
  inline-size: var(--z-chev);
  block-size: var(--z-chev);
  border-inline-end: var(--z-bar) solid currentColor;
  border-block-end: var(--z-bar) solid currentColor;
  transform: rotate(45deg) translate(-25%, -25%);
  transition: transform 180ms ease;
}
.has-sub.is-open > .nav-parent .nav-sub-toggle__chev { transform: rotate(-135deg) translate(-25%, -25%); }

.sub-menu {
  list-style: none;
  margin: 0;
  padding: 0;
}
.sub-menu a { display: block; }

@media (min-width: 60.0625em) {
  .site-nav .sub-menu {
    position: absolute;
    inset-block-start: 100%;
    inset-inline-start: calc(var(--s-3) * -1);
    min-inline-size: var(--z-submenu);
    padding: var(--s-2);
    border-radius: var(--r-md);
    background: var(--c-canvas);
    box-shadow: var(--sh-deep);
    border: var(--z-hair) solid var(--c-line);
    opacity: 0;
    visibility: hidden;
    transform: translateY(calc(var(--s-1) * -0.5));
    transition: opacity 160ms ease, transform 160ms ease, visibility 160ms;
    z-index: 30;
  }
  .site-nav .has-sub:hover > .sub-menu,
  .site-nav .has-sub:focus-within > .sub-menu,
  .site-nav .has-sub.is-open > .sub-menu {
    opacity: 1;
    visibility: visible;
    transform: none;
  }
  .site-nav .sub-menu a {
    padding: var(--s-1) var(--s-2);
    border-radius: var(--r-sm);
    font-size: var(--t-sm);
    color: var(--c-ink);
    white-space: nowrap;
    min-block-size: var(--z-tap);
    display: flex;
    align-items: center;
  }
  .site-nav .sub-menu a:hover { background: var(--c-tint); color: var(--c-brand); }
  /* a gap between the parent and the panel drops the hover halfway across it */
  .site-nav .has-sub::after {
    content: "";
    position: absolute;
    inset-block-start: 100%;
    inset-inline: 0;
    block-size: var(--s-2);
  }
}

@media (max-width: 60em) {
  /* In the drawer the submenu is an indented list under its parent, not a
     floating panel: there is nothing to float over. */
  .site-nav .has-sub { inline-size: 100%; }
  .site-nav .nav-parent { justify-content: space-between; inline-size: 100%; }
  .site-nav .nav-sub-toggle { inline-size: var(--z-tap); block-size: var(--z-tap); }
  .site-nav .sub-menu {
    inline-size: 100%;
    padding-inline-start: var(--s-3);
    border-inline-start: var(--z-hair) solid var(--c-line);
    margin-block-start: var(--s-1);
    display: none;
  }
  .site-nav .has-sub.is-open > .sub-menu { display: block; }
  .site-nav .sub-menu a { padding-block: var(--s-1); min-block-size: var(--z-tap); display: flex; align-items: center; font-size: var(--t-sm); }
}

/* 5.35 Add to calendar, on an event card.
   z-index above the stretched ::after that makes the whole card a link to the
   event, or the card swallows the click and the button never fires. */
.event-card__add { margin-block-start: auto; padding-block-start: var(--s-2); }
.cal-btn {
  position: relative;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  min-block-size: var(--z-tap);
  padding-inline-end: var(--s-2);
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--c-brand);
  text-decoration: none;
}
.cal-btn:hover { color: var(--c-brand-deep); text-decoration: underline; }
/* a calendar drawn in borders: no request, and it takes currentColor */
.cal-btn__icon {
  position: relative;
  flex: none;
  inline-size: var(--z-cal);
  block-size: var(--z-cal);
  border: var(--z-hair) solid currentColor;
  border-radius: var(--r-xs);
}
.cal-btn__icon::before,
.cal-btn__icon::after {
  content: "";
  position: absolute;
  inline-size: var(--z-hair);
  block-size: var(--s-1);
  background: currentColor;
  inset-block-start: calc(var(--s-1) * -0.4);
}
.cal-btn__icon::before { inset-inline-start: 25%; }
.cal-btn__icon::after { inset-inline-end: 25%; }

/* An empty cell in the club table. The em dash is the printer's convention for
   "no value", but the house rule bans the character, and a rule drawn in CSS
   is cleaner anyway: no glyph for a screen reader to announce, and the cell
   carries its own wording for one. */
.is-none {
  display: inline-block;
  inline-size: var(--s-3);
  border-block-end: var(--z-hair) solid var(--c-line-blue);
  vertical-align: middle;
}

/* 5.34 Anthem and Prayer.
   Three recordings stacked, each under its own heading, and the prayer's words
   set as verse. .pull-quote is drawn for a dark band; this is the same
   component on canvas, with the line breaks the prayer is written in. */
.pull-quote--verse {
  max-inline-size: var(--m-prose);
  margin-block-start: var(--s-5);
}
.pull-quote--verse blockquote {
  color: var(--c-ink);
  font-size: var(--t-xl);
  line-height: var(--lh-relaxed);
}

/* 5.35 Not found.
   The whole viewport, blue, with the words on the left and a gold lion on the
   right. The lion is drawn facing right; scaleX(-1) turns it to face the copy,
   because a figure looking off the edge of the page leads the eye with it. Its
   mane runs off the bottom of the band on purpose: cropped, it reads as
   large; whole, it reads as a sticker. */
.lost { display: flex; align-items: center; min-block-size: var(--z-hero); overflow: hidden; }
.lost > .inner { inline-size: 100%; }
.lost__inner {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  align-items: center;
  gap: var(--s-5);
}
.lost__copy { max-inline-size: var(--m-prose); }
.lost__copy h1 { font-size: var(--t-display-xl); }
.lost__lede {
  margin-block-start: var(--s-3);
  color: var(--c-on-brand);
  font-size: var(--t-lg);
  line-height: var(--lh-relaxed);
}
.lost__chips { margin-block-start: var(--s-4); }
.lost__copy .actions { margin-block-start: var(--s-4); }
.lost__figure {
  position: relative;
  align-self: end;
  justify-self: end;
  inline-size: var(--z-lion-404);
  margin-block-end: calc(var(--s-6) * -1);
}
.lost__figure img {
  inline-size: 100%;
  block-size: auto;
  transform: scaleX(-1);
  filter: drop-shadow(0 var(--s-2) var(--s-4) var(--scrim-strong));
}

@media (max-width: 60em) {
  .lost { min-block-size: 0; }
  .lost__inner { grid-template-columns: minmax(0, 1fr); gap: var(--s-4); }
  .lost__figure {
    order: -1;
    justify-self: center;
    align-self: start;
    inline-size: var(--z-lion-404-sm);
    margin-block-end: 0;
  }
}
