@charset "UTF-8";
/* ==========================================================================
   SERTOMA CLUB OF [CITY]
   style.css — single stylesheet, Elementor-mappable

   TABLE OF CONTENTS
   --------------------------------------------------------------------------
   01  VARIABLES ............ design tokens  → Elementor Global Colors / Fonts
   02  RESET ................ normalise      → not rebuilt (Elementor/theme)
   03  TYPOGRAPHY ........... base type      → Elementor Global Fonts
   04  LAYOUT ............... container/grid → Elementor Containers
   05  COMPONENTS ........... reusable       → Elementor Global Widgets
   06  SECTIONS ............. per-section    → Elementor per-container Custom CSS
                              (added in Steps 4–6, one fenced block per section)
   07  UTILITIES ............ helpers        → Elementor Custom CSS / classes
   08  RESPONSIVE ........... only what can't live inline

   BREAKPOINTS — desktop-first, matching Elementor's default tabs exactly.
   --------------------------------------------------------------------------
     Desktop        (base, no query)            Elementor tab: Desktop
     max-width: 1366px                          Elementor tab: Laptop        *
     max-width: 1024px                          Elementor tab: Tablet
     max-width:  880px                          Elementor tab: Mobile Extra  *
     max-width:  767px                          Elementor tab: Mobile

     * Laptop and Mobile Extra are OFF by default in Elementor.
       Enable: Site Settings → Layout → Breakpoints → Additional Breakpoints.

   NAMING — the rule that makes sections deletable
   --------------------------------------------------------------------------
     .s-*   section    may ONLY appear inside its own §06 fenced block
     .c-*   component  may appear anywhere
     .u-*   utility    may appear anywhere
     .is-*  state      toggled by JS
     .has-* state      toggled by JS on an ancestor

   See docs/DESIGN-SYSTEM.md for the full token contract.
   ========================================================================== */


/* ==========================================================================
   01  VARIABLES
   --------------------------------------------------------------------------
   → ELEMENTOR: paste this entire :root block into
     Site Settings → Custom CSS
     so every container's Custom CSS can reference var(--sr-*).
     The colours/fonts are ALSO registered as Global Colors / Global Fonts —
     see docs/DESIGN-SYSTEM.md §3 and §4 for the slot assignments.
   ========================================================================== */

:root {

  /* --- COLOUR · Navy — trust, stability, heritage ------------------------ */
  --sr-navy-900:      #0C2440;  /* footer, deepest band                     */
  --sr-navy-700:      #14385F;  /* ★ BRAND     → Elementor System: Primary  */
  --sr-navy-500:      #2A5B8F;  /* hover, secondary surface                 */
  --sr-navy-200:      #B9CCE1;  /* borders on dark            (non-text)    */
  --sr-navy-50:       #EEF2F7;  /* tint fill, meeting tag     (background)  */

  /* --- COLOUR · Ember — warmth, action ---------------------------------- */
  --sr-ember-800:     #8F2C22;  /* ⚠ red TEXT under 24px goes here  7.2:1   */
  --sr-ember-600:     #C43D30;  /* ★ CTA FILL  → Elementor System: Secondary*/
  --sr-ember-400:     #E0705F;  /* hover, decorative          (non-text)    */
  --sr-ember-50:      #FCEEEC;  /* error tint                 (background)  */

  /* --- COLOUR · Gold — optimism, energy --------------------------------- */
  --sr-gold-500:      #F2A93B;  /* ★ ACCENT    → Elementor System: Accent   */
                                /* ⚠ 2.1:1 on white — DARK BACKGROUNDS ONLY */
  --sr-gold-700:      #7A5200;  /* fundraiser tag text              7.8:1   */
  --sr-gold-100:      #FDF0D9;  /* fundraiser tag fill                      */

  /* --- COLOUR · Teal — the hearing-health signature ---------------------- */
  --sr-teal-700:      #155E56;  /* service tag text                 7.1:1   */
  --sr-teal-500:      #1F7A72;  /* mission icon                     4.9:1   */
  --sr-teal-50:       #E3F2EF;  /* service tag fill                         */

  /* --- COLOUR · Neutral & surface --------------------------------------- */
  --sr-white:         #FFFFFF;
  --sr-canvas:        #F7F5F1;  /* ★ warm off-white — default page bg       */
  --sr-cool-50:       #EEF2F7;  /* = navy-50                                */
  --sr-border:        #E7E2DA;  /* hairline, card border                    */
  --sr-border-strong: #D3CDC3;  /* input border, divider                    */
  --sr-ink:           #1A2230;  /* ★ BODY      → Elementor System: Text     */
  --sr-ink-muted:     #4A5568;  /* meta, caption                    8.3:1   */
  --sr-ink-subtle:    #6B7688;  /* ⚠ THE FLOOR. No gray lighter.    4.8:1   */
  --sr-ink-inverse:   #FFFFFF;  /* text on navy                             */

  /* --- COLOUR · Semantic ------------------------------------------------- */
  --sr-success:       #1E7A4B;  --sr-success-text: #16603A;  --sr-success-bg: #E4F3EB;
  --sr-warning:       #B36B00;  --sr-warning-text: #7A5200;  --sr-warning-bg: #FDF0D9;
  --sr-error:         #B3261E;  --sr-error-text:   #8F2C22;  --sr-error-bg:   #FCEEEC;
  --sr-info:          #2A5B8F;  --sr-info-text:    #14385F;  --sr-info-bg:    #EEF2F7;

  /* --- TYPOGRAPHY · families -------------------------------------------- */
  /* Metric-matched fallbacks — minimises font-swap layout shift (CLS).      */
  --sr-font-heading: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont,
                     'Segoe UI', Roboto, Arial, sans-serif;
  --sr-font-body:    'Inter', -apple-system, BlinkMacSystemFont,
                     'Segoe UI', Roboto, Arial, sans-serif;
  --sr-font-quote:   'Fraunces', Georgia, 'Times New Roman', serif;

  /* --- TYPOGRAPHY · scale (Desktop) ------------------------------------- */
  /* Per-breakpoint overrides live in §08. No clamp() — Elementor's          */
  /* Typography control takes a number per device tab, not an expression.    */
  --sr-fs-display:   64px;
  --sr-fs-h1:        48px;
  --sr-fs-h2:        38px;
  --sr-fs-h3:        26px;
  --sr-fs-h4:        20px;
  --sr-fs-body-lg:   19px;
  --sr-fs-body:      17px;   /* ⚠ 17, not 16. Fixed at every breakpoint.    */
  --sr-fs-body-sm:   15px;
  --sr-fs-caption:   13px;
  --sr-fs-eyebrow:   13px;
  --sr-fs-button:    16px;
  --sr-fs-stat:      60px;
  --sr-fs-quote:     28px;

  /* --- TYPOGRAPHY · weight / leading / tracking -------------------------- */
  --sr-fw-regular:   400;
  --sr-fw-semibold:  600;
  --sr-fw-bold:      700;

  --sr-lh-tight:     1.05;
  --sr-lh-heading:   1.2;
  --sr-lh-snug:      1.4;
  --sr-lh-body:      1.7;   /* ★ exceeds WCAG 1.4.12's 1.5 with headroom    */
  --sr-lh-flat:      1;

  --sr-ls-tightest:  -0.03em;
  --sr-ls-tighter:   -0.02em;
  --sr-ls-tight:     -0.01em;
  --sr-ls-normal:    0;
  --sr-ls-wide:      0.01em;
  --sr-ls-widest:    0.1em;   /* eyebrow only */

  --sr-measure:      68ch;    /* 65–75 characters */

  /* --- SPACING · 4px base ------------------------------------------------ */
  --sr-space-1:       4px;
  --sr-space-2:       8px;
  --sr-space-3:      12px;
  --sr-space-4:      16px;
  --sr-space-5:      20px;
  --sr-space-6:      24px;
  --sr-space-8:      32px;
  --sr-space-10:     40px;
  --sr-space-12:     48px;
  --sr-space-16:     64px;
  --sr-space-20:     80px;
  --sr-space-24:     96px;
  --sr-space-32:    128px;

  /* --- SPACING · applied (Desktop) --------------------------------------- */
  /* ⚠ Elementor has NO global spacing token. These are the literal numbers  */
  /*   typed into Advanced → Padding. See docs/DESIGN-SYSTEM.md §5.1.        */
  --sr-section-y:    var(--sr-space-24);  /* 96 → 88 → 80 → 72 → 64          */
  --sr-gutter:       var(--sr-space-12);  /* 48 → 48 → 40 → 24 → 24          */
  --sr-gap-grid:     var(--sr-space-8);   /* 32 → 32 → 24 → 16 → 16          */
  --sr-gap-gallery:  var(--sr-space-4);   /* 16 → 16 → 12 →  8 →  8          */
  --sr-card-pad:     var(--sr-space-8);   /* 32 → mobile 20                  */

  /* --- LAYOUT ------------------------------------------------------------ */
  --sr-container:        1120px;  /* ★ Site Settings → Content Width         */
  --sr-container-narrow:  720px;
  --sr-container-wide:   1280px;
  --sr-header-h:           88px;  /* → 68px scrolled                         */
  --sr-header-h-scrolled:  68px;

  /* --- RADIUS ------------------------------------------------------------ */
  --sr-radius-sm:      6px;   /* tags, chips              */
  --sr-radius-md:      8px;   /* ★ buttons, inputs        */
  --sr-radius-lg:     12px;   /* gallery tiles            */
  --sr-radius-xl:     16px;   /* ★ content cards          */
  --sr-radius-2xl:    24px;   /* meeting card, features   */
  --sr-radius-full:  9999px;  /* avatars, pills           */

  /* --- SHADOW · navy-tinted, never pure black ---------------------------- */
  --sr-shadow-xs:    0 1px  2px rgba(12, 36, 64, .05);
  --sr-shadow-sm:    0 2px  8px rgba(12, 36, 64, .06);
  --sr-shadow-md:    0 8px 24px rgba(12, 36, 64, .10);
  --sr-shadow-lg:    0 16px 40px rgba(12, 36, 64, .14);
  --sr-shadow-xl:    0 24px 64px rgba(12, 36, 64, .20);
  --sr-shadow-focus: 0 0 0 3px rgba(242, 169, 59, .5);

  /* --- FOCUS · one ring, every context ----------------------------------- */
  /* Gold is 6.4:1 on navy AND 3.1:1 on white — the only palette colour      */
  /* visible against both. One colour = zero exceptions to remember.         */
  --sr-focus-width:  3px;
  --sr-focus-color:  var(--sr-gold-500);
  --sr-focus-offset: 2px;

  /* --- MOTION ------------------------------------------------------------ */
  --sr-ease:         cubic-bezier(.4, 0, .2, 1);
  --sr-dur-fast:     150ms;
  --sr-dur:          200ms;
  --sr-dur-slow:     240ms;
  --sr-dur-reveal:   400ms;
  --sr-reveal-y:     12px;

  /* --- Z-INDEX · named scale, prevents the 99999 arms race ---------------- */
  --sr-z-base:      1;
  --sr-z-sticky:  100;
  --sr-z-drawer:  200;
  --sr-z-lightbox:300;
  --sr-z-skip:    400;  /* must outrank everything */
}


/* ==========================================================================
   02  RESET
   --------------------------------------------------------------------------
   → ELEMENTOR: NOT rebuilt. Elementor + the parent theme supply their own
     normalise. This exists so the prototype renders identically in isolation.
   ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* ★ WCAG 2.2 §2.4.11 Focus Not Obscured — stops the sticky header
     covering the element a keyboard user just tabbed to. */
  scroll-padding-top: calc(var(--sr-header-h) + var(--sr-space-4));
}

body {
  margin: 0;
  background: var(--sr-canvas);
  color: var(--sr-ink);
  font-family: var(--sr-font-body);
  font-size: var(--sr-fs-body);
  font-weight: var(--sr-fw-regular);
  line-height: var(--sr-lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd { margin: 0; }
ul[class], ol[class] { list-style: none; margin: 0; padding: 0; }

img, picture, video, canvas, svg {
  display: block;
  max-width: 100%;
  height: auto;
}

/* Inline body links keep their underline — removing it is both an SEO and a
   WCAG 1.4.1 failure (colour cannot be the only distinguishing signal). */
a { color: inherit; }
a:not([class]) {
  color: var(--sr-navy-700);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

button, input, select, textarea {
  font: inherit;
  color: inherit;
  margin: 0;
}
button { background: none; border: 0; padding: 0; cursor: pointer; }

table { border-collapse: collapse; }

[hidden] { display: none !important; }

/* --- FOCUS · the one ring ------------------------------------------------ */
/* :focus-visible only — keyboard users get the ring, mouse users don't get
   one after clicking. `outline: none` without a compliant replacement is a
   BUILD ERROR: it is the #1 cause of a11y failure on otherwise good sites. */
:focus-visible {
  outline: var(--sr-focus-width) solid var(--sr-focus-color);
  outline-offset: var(--sr-focus-offset);
  border-radius: var(--sr-radius-sm);
}
:focus:not(:focus-visible) { outline: none; }

/* --- MOTION · honour the user's OS setting ------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

::selection { background: var(--sr-gold-500); color: var(--sr-navy-900); }


/* ==========================================================================
   03  TYPOGRAPHY
   --------------------------------------------------------------------------
   → ELEMENTOR: each rule below = one Global Font.
     Site Settings → Global Fonts. See docs/DESIGN-SYSTEM.md §4.3.
   ========================================================================== */

h1, h2, h3, h4,
.c-h1, .c-h2, .c-h3, .c-h4 {
  font-family: var(--sr-font-heading);
  color: var(--sr-navy-700);
  text-wrap: balance;          /* progressive enhancement — ignored if unsupported */
}

h1, .c-h1 {
  font-size: var(--sr-fs-h1);
  font-weight: var(--sr-fw-bold);
  line-height: var(--sr-lh-tight);
  letter-spacing: var(--sr-ls-tighter);
}
h2, .c-h2 {
  font-size: var(--sr-fs-h2);
  font-weight: var(--sr-fw-bold);
  line-height: var(--sr-lh-heading);
  letter-spacing: var(--sr-ls-tighter);
}
h3, .c-h3 {
  font-size: var(--sr-fs-h3);
  font-weight: var(--sr-fw-semibold);
  line-height: 1.3;
  letter-spacing: var(--sr-ls-tight);
}
h4, .c-h4 {
  font-size: var(--sr-fs-h4);
  font-weight: var(--sr-fw-semibold);
  line-height: var(--sr-lh-snug);
}

/* Display — hero H1 only. Global Font: "Display". */
.c-display {
  font-family: var(--sr-font-heading);
  font-size: var(--sr-fs-display);
  font-weight: var(--sr-fw-bold);
  line-height: var(--sr-lh-tight);
  letter-spacing: var(--sr-ls-tightest);
  text-wrap: balance;
}

/* Body. Never justified, never centred as a paragraph — the ragged left
   edge of centred copy destroys scanning. Centred HEADINGS are fine. */
p { max-width: var(--sr-measure); text-wrap: pretty; }
p + p { margin-top: 1em; }

.c-body-lg { font-size: var(--sr-fs-body-lg); line-height: var(--sr-lh-body); }
.c-body-sm { font-size: var(--sr-fs-body-sm); line-height: 1.6; }
.c-caption { font-size: var(--sr-fs-caption); line-height: 1.5; color: var(--sr-ink-muted); }
.c-muted   { color: var(--sr-ink-muted); }

/* Eyebrow — the ONLY place uppercase is permitted. Never uppercase a sentence.
   Global Font: "Eyebrow". */
.c-eyebrow {
  font-family: var(--sr-font-body);
  font-size: var(--sr-fs-eyebrow);
  font-weight: var(--sr-fw-semibold);
  line-height: var(--sr-lh-snug);
  letter-spacing: var(--sr-ls-widest);
  text-transform: uppercase;
  color: var(--sr-ember-800);   /* ⚠ ember-800, NOT ember-600 — 13px is small text */
  margin: 0 0 var(--sr-space-3);
  display: block;
}

/* --- ON-DARK · navy band context ----------------------------------------- */
.u-on-dark,
.u-on-dark h1, .u-on-dark h2, .u-on-dark h3, .u-on-dark h4,
.u-on-dark .c-display { color: var(--sr-ink-inverse); }
.u-on-dark .c-eyebrow { color: var(--sr-gold-500); }  /* ✓ 6.4:1 on navy */
.u-on-dark .c-muted   { color: var(--sr-navy-200); }


/* ==========================================================================
   04  LAYOUT
   --------------------------------------------------------------------------
   → ELEMENTOR: .l-section = a Container (Full Width).
                .l-container = its child Container (Boxed, 1120).
                .l-grid = a Container, flex-direction: row.
     This is the ONLY nesting the design uses: Section > Container > Widgets.
   ========================================================================== */

/* --- Section — the outer full-bleed band --------------------------------- */
.l-section {
  padding-block: var(--sr-section-y);
  position: relative;
}
.l-section--flush      { padding-block: 0; }
.l-section--tight      { padding-block: var(--sr-space-16); }
.l-section--navy       { background: var(--sr-navy-700); }
.l-section--navy-deep  { background: var(--sr-navy-900); }
.l-section--canvas     { background: var(--sr-canvas); }
.l-section--white      { background: var(--sr-white); }
.l-section--cool       { background: var(--sr-cool-50); }

/* --- Container — the boxed inner ------------------------------------------ */
.l-container {
  width: 100%;
  max-width: var(--sr-container);
  margin-inline: auto;
  padding-inline: var(--sr-gutter);
}
.l-container--narrow { max-width: var(--sr-container-narrow); }
.l-container--wide   { max-width: var(--sr-container-wide); }
.l-container--full   { max-width: none; padding-inline: 0; }

/* --- Grid ---------------------------------------------------------------- */
.l-grid {
  display: grid;
  gap: var(--sr-gap-grid);
}
/* ⚠ minmax(0, 1fr) — NEVER a bare 1fr.
   `1fr` is shorthand for minmax(AUTO, 1fr): the track refuses to shrink below
   its content's intrinsic width. One long word or number then (a) steals width
   from its siblings so the columns render UNEQUAL, and (b) pushes the grid past
   the container so the whole PAGE scrolls sideways. minmax(0,1fr) forces truly
   equal, shrinkable tracks. Both failures were caught by measurement in Step 4;
   neither is visible by eye until the content gets long. */
.l-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.l-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.l-grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.l-grid--5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }

/* Asymmetric 7/5 — the split that makes this read "modern nonprofit"
   rather than "2014 Bootstrap". Reversible for alternating sections. */
.l-grid--split {
  grid-template-columns: 7fr 5fr;
  gap: var(--sr-space-16);
  align-items: center;
}
.l-grid--split-reverse { direction: rtl; }
.l-grid--split-reverse > * { direction: ltr; }

/* --- Stack — vertical rhythm without margin collapse --------------------- */
.l-stack { display: flex; flex-direction: column; gap: var(--sr-space-6); }
.l-stack--sm  { gap: var(--sr-space-3); }
.l-stack--lg  { gap: var(--sr-space-10); }

/* --- Cluster — inline group that wraps ----------------------------------- */
.l-cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sr-space-4);
}


/* ==========================================================================
   05  COMPONENTS
   --------------------------------------------------------------------------
   → ELEMENTOR: each .c-* block = one reusable widget or Global Widget.
     These are deliberately OUTSIDE the §06 section fences because they are
     global in both systems. A section may USE a component; it may never
     restyle one.
   ========================================================================== */

/* --------------------------------------------------------------------------
   5.1  BUTTON                                    → Elementor: Button widget
   --------------------------------------------------------------------------
   HTML CONTRACT
     <a class="c-btn c-btn--primary" href="#">Visit a Meeting
       <svg class="c-icon" aria-hidden="true"><use href="#i-arrow-right"></use></svg>
     </a>

   LABEL RULES — verb-led, outcome-stated.
     ✓ Visit a Meeting · See Our Impact · Add to Calendar
     ✗ Learn More (about what?) · Click Here · Submit · Read More
   -------------------------------------------------------------------------- */

.c-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sr-space-2);
  min-height: 44px;                 /* ★ WCAG 2.2 §2.5.8 requires 24×24. We hold
                                       44 on every variant — see --sm and
                                       --tertiary below, which are the two that
                                       normally leak under the limit. */
  padding: var(--sr-space-3) var(--sr-space-6);
  border-radius: var(--sr-radius-md);
  font-family: var(--sr-font-body);
  font-size: var(--sr-fs-button);
  font-weight: var(--sr-fw-semibold);
  line-height: var(--sr-lh-flat);
  letter-spacing: var(--sr-ls-wide);
  text-decoration: none;
  white-space: nowrap;
  border: 1px solid transparent;
  transition: background-color var(--sr-dur) var(--sr-ease),
              border-color     var(--sr-dur) var(--sr-ease),
              color            var(--sr-dur) var(--sr-ease),
              transform        var(--sr-dur) var(--sr-ease),
              box-shadow       var(--sr-dur) var(--sr-ease);
}
/* --sm is visually smaller but keeps a 44px hit area — the box grows, the
   text doesn't move. Density is a look; 44px is a requirement. */
.c-btn--sm { min-height: 44px; padding: var(--sr-space-2) var(--sr-space-4); font-size: var(--sr-fs-body-sm); }
.c-btn--lg { min-height: 52px; padding: var(--sr-space-4) var(--sr-space-8); }
.c-btn--block { display: flex; width: 100%; }

/* Primary — the ONLY red at this scale on the page. Scarcity is what makes
   a CTA colour function. White on ember-600 = 5.1:1 ✓ */
.c-btn--primary {
  background: var(--sr-ember-600);
  color: var(--sr-white);
}
.c-btn--secondary {
  background: transparent;
  color: var(--sr-navy-700);
  border-color: var(--sr-navy-700);
}
.c-btn--tertiary {
  /* ⚠ NOT min-height:auto. These are standalone card CTAs, not links inside a
     sentence, so WCAG 2.2 §2.5.8's inline-target exception does NOT apply.
     inline-flex + align-items:center means the hit area grows to 44px while
     the text stays optically where it was. */
  min-height: 44px;
  padding: 0;
  background: none;
  color: var(--sr-navy-700);
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: 4px;
  /* ⚠ Overrides .c-btn's white-space:nowrap. nowrap is right for a solid
     button (it stops an ugly two-line pill) and WRONG here: a tertiary link
     is a sentence, and a long label like "Learn about our hearing work"
     refuses to wrap, forces its card wider than the viewport, and breaks
     WCAG 1.4.10 Reflow at 320px. Found by measurement, not by eye. */
  white-space: normal;
  text-align: left;
}
/* On-dark variants — for use inside .l-section--navy */
.c-btn--on-dark {
  background: transparent;
  color: var(--sr-white);
  border-color: rgba(255, 255, 255, .5);
}
.c-btn--tertiary.c-btn--on-dark { border: 0; color: var(--sr-gold-500); }

@media (hover: hover) and (pointer: fine) {
  .c-btn--primary:hover   { background: #A9342A; transform: translateY(-1px); box-shadow: var(--sr-shadow-md); }
  .c-btn--secondary:hover { background: var(--sr-navy-700); color: var(--sr-white); }
  .c-btn--tertiary:hover  { text-decoration-color: currentColor; }
  .c-btn--on-dark:hover   { background: rgba(255, 255, 255, .12); border-color: var(--sr-white); }
  .c-btn--tertiary:hover .c-icon { transform: translateX(3px); }
}
.c-btn:active { transform: translateY(0); }
.c-btn[aria-disabled="true"], .c-btn:disabled {
  opacity: .5; pointer-events: none;
}
.c-btn .c-icon { transition: transform var(--sr-dur) var(--sr-ease); }


/* --------------------------------------------------------------------------
   5.2  ICON                                        → Elementor: Icon widget
   --------------------------------------------------------------------------
   HTML CONTRACT — decorative (label already says it):
     <svg class="c-icon" aria-hidden="true"><use href="#i-clock"></use></svg>
   HTML CONTRACT — the icon IS the control:
     <button class="c-icon-btn" aria-label="Close">
       <svg class="c-icon c-icon--24" aria-hidden="true"><use href="#i-x"></use></svg>
     </button>

   RULE: always pair an icon with a text label. Icons clarify; they do not
   communicate alone. Icon-only navigation is banned.
   -------------------------------------------------------------------------- */

.c-icon {
  width: 20px; height: 20px;          /* default */
  flex: 0 0 auto;
  stroke: currentColor;               /* Lucide = stroke-based, inherits colour */
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  fill: none;
}
.c-icon--16 { width: 16px; height: 16px; }
.c-icon--24 { width: 24px; height: 24px; stroke-width: 2; }
.c-icon--32 { width: 32px; height: 32px; stroke-width: 2; }
.c-icon--48 { width: 48px; height: 48px; stroke-width: 2; }

/* Icon-only control — 44px hit area regardless of glyph size. */
.c-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px; height: 44px;
  border-radius: var(--sr-radius-md);
  color: var(--sr-navy-700);
  transition: background-color var(--sr-dur) var(--sr-ease);
}
@media (hover: hover) and (pointer: fine) {
  .c-icon-btn:hover { background: var(--sr-navy-50); }
}

/* Icon in a tinted circle — the program-pillar treatment. */
.c-icon-circle {
  display: grid;
  place-items: center;
  width: 96px; height: 96px;
  border-radius: var(--sr-radius-full);
  background: var(--sr-navy-50);
  color: var(--sr-navy-700);
}


/* --------------------------------------------------------------------------
   5.3  TAG / PILL                              → Elementor: Text Editor + CSS
   --------------------------------------------------------------------------
   HTML CONTRACT
     <span class="c-tag c-tag--fundraiser">Fundraiser</span>

   Category colour is the ONLY other place these hues appear. Every pair below
   is verified ≥ 4.5:1. Never use the fill colour as text.
   -------------------------------------------------------------------------- */

.c-tag {
  display: inline-flex;
  align-items: center;
  gap: var(--sr-space-1);
  padding: var(--sr-space-1) var(--sr-space-3);
  border-radius: var(--sr-radius-sm);
  font-size: var(--sr-fs-caption);
  font-weight: var(--sr-fw-semibold);
  line-height: var(--sr-lh-snug);
  letter-spacing: var(--sr-ls-wide);
  text-transform: uppercase;
  white-space: nowrap;
}
.c-tag--meeting    { background: var(--sr-navy-50);  color: var(--sr-navy-700); }  /*  8.4:1 */
.c-tag--fundraiser { background: var(--sr-gold-100); color: var(--sr-gold-700); }  /*  7.1:1 */
.c-tag--board      { background: #F1F0EE;            color: var(--sr-ink-muted); } /*  7.9:1 */
.c-tag--service    { background: var(--sr-teal-50);  color: var(--sr-teal-700); }  /*  6.6:1 */
.c-tag--muted      { background: var(--sr-canvas);   color: var(--sr-ink-muted); }


/* --------------------------------------------------------------------------
   5.4  SECTION HEADER            → Elementor: Global Widget (~20 instances)
   --------------------------------------------------------------------------
   HTML CONTRACT
     <header class="c-section-header">
       <span class="c-eyebrow">What We Do</span>
       <h2>Three ways we show up.</h2>
       <p class="c-body-lg">Optional supporting line.</p>
     </header>
   -------------------------------------------------------------------------- */

.c-section-header {
  margin-bottom: var(--sr-space-16);
  max-width: 720px;
}
.c-section-header > h2 + p,
.c-section-header > .c-h2 + p { margin-top: var(--sr-space-4); }

.c-section-header--center {
  margin-inline: auto;
  text-align: center;
}
.c-section-header--center p { margin-inline: auto; }

/* Header with a trailing CTA on the same line (desktop only). */
.c-section-header--split {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--sr-space-8);
  max-width: none;
}
.c-section-header--split > div { max-width: 720px; }


/* --------------------------------------------------------------------------
   5.5  MEDIA                              → Elementor: Image widget
   --------------------------------------------------------------------------
   HTML CONTRACT — prototype (no image yet):
     <figure class="c-media c-media--3x2" data-placeholder="mission/tuesday-lunch.webp"></figure>

   HTML CONTRACT — with a real image (placeholder auto-hides beneath it):
     <figure class="c-media c-media--3x2" data-placeholder="mission/tuesday-lunch.webp">
       <img src="assets/images/mission/tuesday-lunch.webp"
            alt="Club members talking over lunch at the community centre"
            width="800" height="533" loading="lazy" decoding="async">
     </figure>

   ★ The placeholder is a real design decision, not a stub. Phase 1 argued
     hard against stock photography; a navy block naming the required file is
     honest about what's missing, and IMAGE_GUIDE.md tells the client what to
     shoot for each slot. Dropping in the <img> covers it — zero CSS change.
   -------------------------------------------------------------------------- */

.c-media {
  position: relative;
  overflow: hidden;
  border-radius: var(--sr-radius-xl);
  background: var(--sr-navy-700);
  margin: 0;
}
.c-media > img {
  position: relative;
  z-index: var(--sr-z-base);
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The placeholder label. */
.c-media::after {
  content: attr(data-placeholder);
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  padding: var(--sr-space-4);
  font-family: ui-monospace, 'SF Mono', 'Cascadia Mono', Menlo, monospace;
  font-size: var(--sr-fs-caption);
  line-height: 1.6;
  text-align: center;
  color: var(--sr-navy-200);
  background-image:
    repeating-linear-gradient(45deg,
      rgba(255, 255, 255, .03) 0 12px,
      transparent 12px 24px);
}

/* Once a real photo is in, the placeholder label must not sit behind a
   transparent PNG or peek through a letterboxed image. */
.c-media:has(> img)::after { content: none; }

/* Aspect ratios — no fixed heights, anywhere. */
.c-media--16x9 { aspect-ratio: 16 / 9; }
.c-media--3x2  { aspect-ratio: 3 / 2; }
.c-media--4x5  { aspect-ratio: 4 / 5; }
.c-media--1x1  { aspect-ratio: 1 / 1; }
.c-media--flat { border-radius: 0; }


/* --------------------------------------------------------------------------
   5.6  CARD (base)                        → Elementor: Container + widgets
   --------------------------------------------------------------------------
   HTML CONTRACT
     <article class="c-card"> … </article>

   Elevation encodes interactivity: if it lifts, it's clickable. Static
   content is bordered, not shadowed. Shadows carry meaning.
   -------------------------------------------------------------------------- */

.c-card {
  display: flex;
  flex-direction: column;
  background: var(--sr-white);
  border: 1px solid var(--sr-border);
  border-radius: var(--sr-radius-xl);
  box-shadow: var(--sr-shadow-sm);
  padding: var(--sr-card-pad);
  transition: transform var(--sr-dur) var(--sr-ease),
              box-shadow var(--sr-dur) var(--sr-ease),
              border-color var(--sr-dur) var(--sr-ease);
}
.c-card--flush { padding: 0; overflow: hidden; }
.c-card--navy  { background: var(--sr-navy-700); border-color: transparent; }

@media (hover: hover) and (pointer: fine) {
  .c-card--interactive:hover {
    transform: translateY(-4px);
    box-shadow: var(--sr-shadow-md);
    border-color: rgba(20, 56, 95, .3);
  }
}


/* --------------------------------------------------------------------------
   5.7  FEATURE CARD                        → Elementor: Icon Box widget
   --------------------------------------------------------------------------
   HTML CONTRACT
     <article class="c-card c-card--interactive c-feature-card">
       <span class="c-icon-circle"><svg class="c-icon c-icon--48" aria-hidden="true">
         <use href="#i-ear"></use></svg></span>
       <h3>Hearing Health</h3>
       <p class="c-body-sm">…</p>
       <a class="c-btn c-btn--tertiary" href="#">Learn about our hearing work
         <svg class="c-icon c-icon--16" aria-hidden="true"><use href="#i-chevron-right"></use></svg></a>
     </article>
   -------------------------------------------------------------------------- */

.c-feature-card { gap: var(--sr-space-5); align-items: flex-start; }
.c-feature-card p { flex: 1; color: var(--sr-ink-muted); }


/* --------------------------------------------------------------------------
   5.8  STAT                              → Elementor: Counter widget
   --------------------------------------------------------------------------
   HTML CONTRACT
     <div class="c-stat">
       <span class="c-stat__value" data-count-to="127000" data-count-prefix="$">$127,000</span>
       <span class="c-stat__label">raised for local causes since 2015</span>
     </div>

   ★ The final value is IN THE DOM. The count-up is presentational only —
     a screen reader announces "$127,000", never "$3… $47,000… $91,000".
   ⚠ Gold on navy = 6.4:1 ✓. Gold on white = 2.1:1 ✗ — which is exactly why
     the Impact band is navy. A colour constraint driving a layout decision.
   -------------------------------------------------------------------------- */

.c-stat { text-align: center; }
.c-stat__value {
  display: block;
  font-family: var(--sr-font-heading);
  font-size: var(--sr-fs-stat);
  font-weight: var(--sr-fw-bold);
  line-height: var(--sr-lh-flat);
  letter-spacing: var(--sr-ls-tighter);
  color: var(--sr-gold-500);
  font-variant-numeric: tabular-nums;   /* stops width jitter while counting */
}
.c-stat__label {
  display: block;
  margin-top: var(--sr-space-3);
  font-size: var(--sr-fs-caption);
  font-weight: var(--sr-fw-semibold);
  letter-spacing: var(--sr-ls-widest);
  text-transform: uppercase;
  line-height: var(--sr-lh-snug);
  color: rgba(255, 255, 255, .8);
}


/* --------------------------------------------------------------------------
   5.9  MEETING RIBBON             → Elementor: Global Widget ★ THE SPINE
   --------------------------------------------------------------------------
   HTML CONTRACT
     <div class="c-ribbon">
       <span class="c-ribbon__item"><svg class="c-icon" aria-hidden="true">
         <use href="#i-clock"></use></svg>Tuesdays, 12:00pm</span>
       <span class="c-ribbon__item"><svg class="c-icon" aria-hidden="true">
         <use href="#i-map-pin"></use></svg>Riverside Community Center</span>
       <span class="c-ribbon__note">Guests always welcome</span>
     </div>

   ★ ONE data source, FOUR renderings: hero (glass), events (card), footer
     (compact), mobile drawer. It is the site's most-wanted fact, and it is
     TRUE even if nobody logs in for six months.
     → In WordPress this becomes ONE ACF Options field. Diane edits the
       meeting time once; four places update. She never knows there were four.
   -------------------------------------------------------------------------- */

.c-ribbon {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sr-space-3) var(--sr-space-6);
  padding: var(--sr-space-4) var(--sr-space-6);
  border-radius: var(--sr-radius-md);
  font-size: var(--sr-fs-body-sm);
  font-weight: var(--sr-fw-semibold);
}
.c-ribbon__item { display: inline-flex; align-items: center; gap: var(--sr-space-2); }
.c-ribbon__note {
  font-weight: var(--sr-fw-regular);
  font-style: italic;
  opacity: .85;
}

/* Rendering 1 — hero. Frosted glass over the hero photograph. */
.c-ribbon--glass {
  background: rgba(12, 36, 64, .55);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, .18);
  color: var(--sr-white);
}
/* Rendering 2 — events page card. */
.c-ribbon--card {
  background: var(--sr-white);
  border: 1px solid var(--sr-border);
  box-shadow: var(--sr-shadow-sm);
  color: var(--sr-ink);
}
/* Rendering 3 — footer / drawer. Compact, stacked. */
.c-ribbon--compact {
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sr-space-2);
  padding: 0;
  color: inherit;
}


/* --------------------------------------------------------------------------
   5.10  EVENT CARD                → Elementor: Loop Item ★ 4 CONTEXTS
   --------------------------------------------------------------------------
   HTML CONTRACT
     <article class="c-event-card">
       <time class="c-event-card__date" datetime="2026-08-14">
         <span class="c-event-card__month">Aug</span>
         <span class="c-event-card__day">14</span>
         <span class="c-event-card__weekday">Thu</span>
       </time>
       <div class="c-event-card__body">
         <span class="c-tag c-tag--fundraiser">Fundraiser</span>
         <h3 class="c-event-card__title">Pancake Breakfast for Hearing</h3>
         <p class="c-event-card__meta">…</p>
         <p class="c-body-sm c-muted">…</p>
       </div>
       <div class="c-event-card__action"> … </div>
     </article>

   ★ Used on: Home §06, Events (upcoming), Events (past, muted), Join.
     ONE component, four contexts. This is the return on designing
     components before pages.
   ★ The DATE CHIP is the hero of the card — the eye scans dates, not titles.
   -------------------------------------------------------------------------- */

.c-event-card {
  display: grid;
  grid-template-columns: 88px 1fr auto;
  gap: var(--sr-space-6);
  align-items: center;
  background: var(--sr-white);
  border: 1px solid var(--sr-border);
  border-radius: var(--sr-radius-xl);
  box-shadow: var(--sr-shadow-sm);
  padding: var(--sr-space-5);
  transition: box-shadow var(--sr-dur) var(--sr-ease),
              border-color var(--sr-dur) var(--sr-ease);
}
@media (hover: hover) and (pointer: fine) {
  .c-event-card:hover {
    box-shadow: var(--sr-shadow-md);
    border-color: rgba(20, 56, 95, .3);
  }
}

.c-event-card__date {
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 2px;
  width: 88px;
  padding: var(--sr-space-3) var(--sr-space-2);
  border-radius: var(--sr-radius-lg);
  background: var(--sr-navy-700);
  color: var(--sr-white);
}
.c-event-card__month {
  font-size: var(--sr-fs-caption);
  font-weight: var(--sr-fw-semibold);
  letter-spacing: var(--sr-ls-widest);
  text-transform: uppercase;
  line-height: var(--sr-lh-flat);
}
.c-event-card__day {
  font-family: var(--sr-font-heading);
  font-size: 32px;
  font-weight: var(--sr-fw-bold);
  line-height: 1.1;
}
.c-event-card__weekday {
  font-size: 11px;
  font-weight: var(--sr-fw-semibold);
  text-transform: uppercase;
  letter-spacing: var(--sr-ls-wide);
  line-height: var(--sr-lh-flat);
  opacity: .7;
}

.c-event-card__body { display: flex; flex-direction: column; gap: var(--sr-space-2); align-items: flex-start; }
.c-event-card__title { font-size: var(--sr-fs-h4); }
.c-event-card__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sr-space-2) var(--sr-space-4);
  font-size: var(--sr-fs-body-sm);
  color: var(--sr-ink-muted);
  max-width: none;
}
.c-event-card__meta span { display: inline-flex; align-items: center; gap: var(--sr-space-1); }

/* Context: past events — muted, no CTA. Kept because a visible history is
   the recency proof a sponsor checks. Never deleted. */
.c-event-card--past { box-shadow: none; background: transparent; }
.c-event-card--past .c-event-card__date { opacity: .6; }


/* --------------------------------------------------------------------------
   5.11  GALLERY ITEM               → Elementor: Gallery widget
   --------------------------------------------------------------------------
   HTML CONTRACT
     <li>
       <button class="c-gallery-item" type="button"
               data-lightbox-index="0"
               data-full="assets/images/gallery/pancake-01.webp"
               data-caption="Members serving pancakes at Fire Station #2, August 2026">
         <figure class="c-media c-media--4x5 c-media--flat" data-placeholder="gallery/pancake-01.webp"></figure>
         <span class="c-gallery-item__caption">Pancake Breakfast · Aug 2026</span>
         <svg class="c-icon c-icon--24 c-gallery-item__expand" aria-hidden="true">
           <use href="#i-maximize"></use></svg>
       </button>
     </li>

   ★ A real <button> in DOM order — not a div with onclick. That single
     decision prevents ~60% of typical a11y defects here.
   -------------------------------------------------------------------------- */

.c-gallery-item {
  position: relative;
  display: block;
  width: 100%;
  overflow: hidden;
  border-radius: var(--sr-radius-lg);
  background: var(--sr-navy-700);
  cursor: zoom-in;
}
.c-gallery-item .c-media { transition: transform var(--sr-dur-slow) var(--sr-ease); }

/* Overlay + caption + expand icon — hidden until hover/focus. */
.c-gallery-item::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top,
              rgba(12, 36, 64, .75) 0%,
              rgba(12, 36, 64, .35) 45%,
              rgba(12, 36, 64, 0) 100%);
  opacity: 0;
  transition: opacity var(--sr-dur-slow) var(--sr-ease);
  z-index: 2;
}
.c-gallery-item__caption,
.c-gallery-item__expand {
  position: absolute;
  z-index: 3;
  opacity: 0;
  transition: opacity var(--sr-dur-slow) var(--sr-ease),
              transform var(--sr-dur-slow) var(--sr-ease);
  color: var(--sr-white);
}
.c-gallery-item__caption {
  left: var(--sr-space-4);
  right: var(--sr-space-4);
  bottom: var(--sr-space-4);
  transform: translateY(8px);
  font-size: var(--sr-fs-body-sm);
  font-weight: var(--sr-fw-semibold);
  line-height: 1.4;
  text-align: left;
}
.c-gallery-item__expand { top: var(--sr-space-4); right: var(--sr-space-4); }

/* ⚠ Guarded. Unguarded hover on touch produces a sticky state after a tap —
   the classic mobile bug. Focus-within gives keyboard users the same reveal. */
@media (hover: hover) and (pointer: fine) {
  .c-gallery-item:hover .c-media { transform: scale(1.05); }
  .c-gallery-item:hover::after,
  .c-gallery-item:hover .c-gallery-item__caption,
  .c-gallery-item:hover .c-gallery-item__expand { opacity: 1; }
  .c-gallery-item:hover .c-gallery-item__caption { transform: translateY(0); }
}
.c-gallery-item:focus-visible::after,
.c-gallery-item:focus-visible .c-gallery-item__caption,
.c-gallery-item:focus-visible .c-gallery-item__expand { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .c-gallery-item:hover .c-media { transform: none; }
}


/* --------------------------------------------------------------------------
   5.12  LIGHTBOX                 → Elementor: built into Gallery widget
   --------------------------------------------------------------------------
   HTML CONTRACT — one per gallery page, driven by assets/js/gallery.js
     <div class="c-lightbox" id="lightbox" role="dialog" aria-modal="true"
          aria-label="Photo viewer" hidden> … </div>

   ★ Focus is TRAPPED inside, and on close returns to the ORIGINATING TILE —
     not the page top. Without that, a keyboard user is dumped at the top of
     a 42-photo grid every single time.
   -------------------------------------------------------------------------- */

.c-lightbox {
  position: fixed;
  inset: 0;
  z-index: var(--sr-z-lightbox);
  display: grid;
  grid-template-rows: auto 1fr auto;
  background: rgba(12, 36, 64, .92);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  opacity: 0;
  transition: opacity var(--sr-dur) var(--sr-ease);
}
.c-lightbox.is-open { opacity: 1; }

.c-lightbox__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sr-space-4);
  padding: var(--sr-space-4) var(--sr-space-6);
  color: var(--sr-white);
}
.c-lightbox__counter {
  font-size: var(--sr-fs-body-sm);
  font-weight: var(--sr-fw-semibold);
  font-variant-numeric: tabular-nums;
}
.c-lightbox__stage {
  display: grid;
  place-items: center;
  padding-inline: var(--sr-space-16);
  min-height: 0;
}

/* ⚠ This figure is NOT .c-media, on purpose: that component forces
   object-fit:cover, and a lightbox that crops the photo you opened to see in
   full is worse than no lightbox. It carries its own placeholder instead. */
.c-lightbox__figure {
  position: relative;
  display: grid;
  place-items: center;
  width: min(90vw, 960px);
  aspect-ratio: 3 / 2;
  margin: 0;
  border-radius: var(--sr-radius-md);
  background: rgba(255, 255, 255, .04);
  border: 1px dashed rgba(255, 255, 255, .22);
}
.c-lightbox__figure::after {
  content: attr(data-placeholder);
  font-family: ui-monospace, 'SF Mono', Menlo, monospace;
  font-size: var(--sr-fs-caption);
  color: var(--sr-navy-200);
  text-align: center;
  padding: var(--sr-space-4);
}
/* Once a real photo is in, the frame gets out of the way entirely. */
.c-lightbox__figure:has(img:not([hidden])) {
  aspect-ratio: auto;
  width: auto;
  background: none;
  border: 0;
}
.c-lightbox__figure:has(img:not([hidden]))::after { content: none; }

.c-lightbox__img {
  max-width: 90vw;
  max-height: 85vh;
  width: auto;
  height: auto;
  object-fit: contain;       /* ★ contain, never cover */
  border-radius: var(--sr-radius-md);
  transform: scale(.96);
  transition: transform var(--sr-dur-slow) var(--sr-ease);
}
.c-lightbox.is-open .c-lightbox__img { transform: scale(1); }

.c-lightbox__caption {
  padding: var(--sr-space-4) var(--sr-space-6) var(--sr-space-8);
  text-align: center;
  font-size: var(--sr-fs-body-sm);
  color: rgba(255, 255, 255, .85);
}
.c-lightbox__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 48px; height: 48px;
  display: grid;
  place-items: center;
  border-radius: var(--sr-radius-full);
  background: rgba(255, 255, 255, .1);
  color: var(--sr-white);
  transition: background-color var(--sr-dur) var(--sr-ease);
}
.c-lightbox__nav--prev { left: var(--sr-space-4); }
.c-lightbox__nav--next { right: var(--sr-space-4); }
.c-lightbox__close { color: var(--sr-white); }
@media (hover: hover) and (pointer: fine) {
  .c-lightbox__nav:hover { background: rgba(255, 255, 255, .22); }
}

/* Body scroll lock while open — set by JS. */
.has-lightbox-open { overflow: hidden; }


/* --------------------------------------------------------------------------
   5.13  TESTIMONIAL                    → Elementor: Testimonial widget
   --------------------------------------------------------------------------
   HTML CONTRACT
     <figure class="c-testimonial">
       <blockquote class="c-testimonial__quote">…</blockquote>
       <figcaption class="c-testimonial__by">
         <span class="c-avatar" data-placeholder="people/ellen.webp"></span>
         <span><strong>Ellen Marsh</strong><span class="c-caption">Member since 2019</span></span>
       </figcaption>
     </figure>

   ★ Fraunces appears HERE AND NOWHERE ELSE. That restriction is precisely
     why it lands. Loaded only on index.html.
   ★ Never auto-rotates — WCAG 2.2.2 satisfied by design, not by adding
     pause controls to a carousel nobody reads.
   -------------------------------------------------------------------------- */

.c-testimonial { text-align: center; }
.c-testimonial__quote {
  font-family: var(--sr-font-quote);
  font-size: var(--sr-fs-quote);
  font-style: italic;
  font-weight: var(--sr-fw-regular);
  line-height: var(--sr-lh-heading);
  letter-spacing: var(--sr-ls-tight);
  color: var(--sr-navy-700);
  margin: 0;
  text-wrap: pretty;
}
.c-testimonial__by {
  display: inline-flex;
  align-items: center;
  gap: var(--sr-space-4);
  margin-top: var(--sr-space-8);
  text-align: left;
}
.c-testimonial__by strong { display: block; font-weight: var(--sr-fw-semibold); }

.c-avatar {
  display: block;
  width: 64px; height: 64px;
  flex: 0 0 auto;
  border-radius: var(--sr-radius-full);
  overflow: hidden;
  background: var(--sr-navy-700);
  position: relative;
}
.c-avatar > img { width: 100%; height: 100%; object-fit: cover; }
.c-avatar--sm { width: 40px; height: 40px; }
/* Initials, used where there is no photograph. Deliberate: a stock portrait
   attached to a name would read as a real person endorsing the club. */
.c-avatar--initials {
  display: grid;
  place-items: center;
  background: var(--sr-navy-50);
  color: var(--sr-navy-700);
  font-family: var(--sr-font-heading);
  font-size: 22px;
  font-weight: var(--sr-fw-bold);
  letter-spacing: var(--sr-ls-wide);
}
.c-avatar--lg { width: 96px; height: 96px; }


/* --------------------------------------------------------------------------
   5.14  SPONSOR                         → Elementor: Image Box / Image
   --------------------------------------------------------------------------
   HTML CONTRACT
     <li><a class="c-sponsor" href="#" aria-label="Alvarado Heating & Air">
       <span class="c-sponsor__mark" data-placeholder="sponsors/alvarado.svg"></span>
     </a></li>

   Greyscale at rest → full colour on hover. Keeps the row calm and stops
   twelve competing logos from shouting over the section header.
   -------------------------------------------------------------------------- */

.c-sponsor {
  display: grid;
  place-items: center;
  padding: var(--sr-space-5);
  border-radius: var(--sr-radius-lg);
  background: var(--sr-white);
  border: 1px solid var(--sr-border);
  min-height: 96px;
  transition: border-color var(--sr-dur) var(--sr-ease),
              box-shadow var(--sr-dur) var(--sr-ease);
}
.c-sponsor__mark {
  display: block;
  width: 100%;
  height: 40px;
  object-fit: contain;
  filter: grayscale(1);
  opacity: .65;
  transition: filter var(--sr-dur) var(--sr-ease), opacity var(--sr-dur) var(--sr-ease);
}
@media (hover: hover) and (pointer: fine) {
  .c-sponsor:hover { border-color: var(--sr-navy-200); box-shadow: var(--sr-shadow-sm); }
  .c-sponsor:hover .c-sponsor__mark { filter: grayscale(0); opacity: 1; }
}


/* --------------------------------------------------------------------------
   5.15  FORM                              → Elementor: Form widget (Pro)
   --------------------------------------------------------------------------
   HTML CONTRACT
     <div class="c-field">
       <label class="c-field__label" for="name">Name <span class="c-field__req">(required)</span></label>
       <input class="c-field__input" id="name" name="name" type="text"
              autocomplete="name" required aria-describedby="name-hint">
       <p class="c-field__hint" id="name-hint">…</p>
     </div>

   ★ VISIBLE LABELS, ALWAYS. Never placeholder-as-label — placeholders vanish
     on input, fail contrast, and break autofill. The single most common form
     defect on the web.
   ★ Required is marked TWICE: the asterisk AND the word. Never colour alone.
   ★ NO CAPTCHA — WCAG 2.2 §3.3.8. A honeypot + timestamp is invisible,
     accessible, and enough for the spam a club site attracts.
   -------------------------------------------------------------------------- */

.c-field { display: flex; flex-direction: column; gap: var(--sr-space-2); }
.c-field__label {
  font-size: var(--sr-fs-body-sm);
  font-weight: var(--sr-fw-semibold);
  color: var(--sr-ink);
}
.c-field__req { font-weight: var(--sr-fw-regular); color: var(--sr-ink-muted); }

.c-field__input,
.c-field__textarea {
  width: 100%;
  min-height: 44px;
  padding: var(--sr-space-3) var(--sr-space-4);
  background: var(--sr-white);
  border: 1px solid var(--sr-border-strong);
  border-radius: var(--sr-radius-md);
  box-shadow: var(--sr-shadow-xs);
  font-size: var(--sr-fs-body);
  color: var(--sr-ink);
  transition: border-color var(--sr-dur) var(--sr-ease),
              box-shadow var(--sr-dur) var(--sr-ease);
}
.c-field__textarea { min-height: 132px; resize: vertical; }
.c-field__input::placeholder,
.c-field__textarea::placeholder { color: var(--sr-ink-subtle); }
.c-field__input:focus-visible,
.c-field__textarea:focus-visible {
  border-color: var(--sr-navy-700);
  outline: var(--sr-focus-width) solid var(--sr-focus-color);
  outline-offset: 1px;
}
.c-field__hint { font-size: var(--sr-fs-caption); color: var(--sr-ink-muted); max-width: none; }
.c-field__input[aria-invalid="true"],
.c-field__textarea[aria-invalid="true"] { border-color: var(--sr-error); }
.c-field__error {
  display: flex;
  align-items: center;
  gap: var(--sr-space-1);
  font-size: var(--sr-fs-caption);
  font-weight: var(--sr-fw-semibold);
  color: var(--sr-error-text);
}

/* Honeypot — visually gone, still in the tab order for nobody, off for AT. */
.c-field--honey {
  position: absolute;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}


/* --------------------------------------------------------------------------
   5.16  NEWSLETTER                        → Elementor: Form widget (Pro)
   --------------------------------------------------------------------------
   HTML CONTRACT
     <form class="c-newsletter" action="#" method="post">
       <label class="c-field__label" for="nl-email">Email address</label>
       <div class="c-newsletter__row">
         <input class="c-field__input" id="nl-email" type="email"
                autocomplete="email" placeholder="you@example.com" required>
         <button class="c-btn c-btn--primary" type="submit">Sign up</button>
       </div>
     </form>

   Phase 1 Part 17: the #1 Phase-2 recommendation. The slot is reserved in
   the footer at launch so adding it later is a drop-in, not a redesign.
   -------------------------------------------------------------------------- */

.c-newsletter { display: flex; flex-direction: column; gap: var(--sr-space-2); }
.c-newsletter__row { display: flex; gap: var(--sr-space-2); }
.c-newsletter__row .c-field__input { flex: 1; min-width: 0; }


/* --------------------------------------------------------------------------
   5.17  EMPTY STATE       → Elementor: Container ★ A CONVERSION SURFACE
   --------------------------------------------------------------------------
   HTML CONTRACT
     <div class="c-empty">
       <svg class="c-icon c-icon--48" aria-hidden="true"><use href="#i-calendar"></use></svg>
       <h3>We're between events right now — but we still meet every Tuesday.</h3>
       <p>…</p>
       <a class="c-btn c-btn--primary" href="#">Get Directions</a>
     </div>

   ★ THE MOST STRATEGICALLY IMPORTANT COMPONENT ON THE SITE.
     It must NEVER say "No events found." That sentence tells a first-time
     visitor the club is dead, and he leaves forever. An empty state is a
     conversion opportunity, not an error message — it converts a content
     gap into a meeting invitation. This is Phase 1's decay constraint,
     made concrete.
   -------------------------------------------------------------------------- */

.c-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sr-space-5);
  max-width: 560px;
  margin-inline: auto;
  padding: var(--sr-space-16) var(--sr-space-6);
  text-align: center;
  background: var(--sr-white);
  border: 1px dashed var(--sr-border-strong);
  border-radius: var(--sr-radius-2xl);
}
.c-empty > .c-icon { color: var(--sr-navy-200); }
/* h2 OR h3 — the correct LEVEL depends on whether the host section has a
   header of its own; the size is set with .c-h3. Both are styled here so the
   component works at either level without the author fighting it. */
.c-empty h2, .c-empty h3 { text-wrap: balance; }
.c-empty p { color: var(--sr-ink-muted); }


/* --------------------------------------------------------------------------
   5.18  ALERT                              → Elementor: Alert widget
   --------------------------------------------------------------------------
   HTML CONTRACT
     <div class="c-alert c-alert--success" role="status">
       <svg class="c-icon" aria-hidden="true"><use href="#i-check-circle"></use></svg>
       <p>Thanks — we'll be in touch within a couple of days.</p>
     </div>

   ★ Never colour alone (WCAG 1.4.1). Every alert carries an icon AND a label.
   -------------------------------------------------------------------------- */

.c-alert {
  display: flex;
  align-items: flex-start;
  gap: var(--sr-space-3);
  padding: var(--sr-space-4) var(--sr-space-5);
  border-radius: var(--sr-radius-md);
  border: 1px solid transparent;
  font-size: var(--sr-fs-body-sm);
}
.c-alert p { max-width: none; }
.c-alert--success { background: var(--sr-success-bg); border-color: var(--sr-success); color: var(--sr-success-text); }
.c-alert--warning { background: var(--sr-warning-bg); border-color: var(--sr-warning); color: var(--sr-warning-text); }
.c-alert--error   { background: var(--sr-error-bg);   border-color: var(--sr-error);   color: var(--sr-error-text); }
.c-alert--info    { background: var(--sr-info-bg);    border-color: var(--sr-info);    color: var(--sr-info-text); }


/* ==========================================================================
   06  SECTIONS
   --------------------------------------------------------------------------
   ★ THE CUT LINES.

   Each section's CSS is a self-contained, comment-fenced block. Every
   selector is namespaced .s-<section>__* and touches NOTHING outside its
   own fence. Delete the fence → delete the section → nothing else moves.

   → ELEMENTOR: the block between two banners pastes directly into that
     Saved Template's container → Advanced → Custom CSS. The fences are not
     tidiness; they are literally where you cut.

   Populated in Step 4 (Home), Step 5 (Events), Step 6 (Gallery).
   ========================================================================== */


/* ──────────────────────────────────────────────────────────────────────────
   HEADER                                    → Theme Builder → Header (global)
   Transparent over the hero, solid on scroll, hides on scroll-down and
   returns on scroll-up. Hide-on-scroll is right here because the site is
   scroll-heavy and the nav carries the primary CTA: it must be one gesture
   away at all times without permanently eating 68px of a 375px screen.
   ────────────────────────────────────────────────────────────────────────── */

.s-header {
  position: fixed;
  inset: 0 0 auto;
  z-index: var(--sr-z-sticky);
  height: var(--sr-header-h);
  background: transparent;
  transition: height var(--sr-dur) var(--sr-ease),
              background-color var(--sr-dur) var(--sr-ease),
              box-shadow var(--sr-dur) var(--sr-ease),
              transform var(--sr-dur-slow) var(--sr-ease);
}
.s-header__bar {
  display: flex;
  align-items: center;
  gap: var(--sr-space-8);
  height: 100%;
}

/* State: scrolled past 80px. */
.s-header.is-scrolled {
  height: var(--sr-header-h-scrolled);
  background: var(--sr-white);
  box-shadow: var(--sr-shadow-md);
}
/* State: scrolling down — return the viewport to the content. */
.s-header.is-hidden { transform: translateY(-100%); }

/* The client's mark, in two variants that crossfade with the header.
   --light: white artwork + gold club name, for the transparent-over-hero state.
   --dark:  navy artwork, for the solid-white scrolled state.
   ⚠ Both are the SAME artwork, so the crossfade has no positional shift. The
     --light variant deliberately has NO white pill behind the gold club name:
     gold on white is 2.1:1, gold on navy is ~6:1. See docs/DESIGN-SYSTEM.md §2.4. */
.s-header__logo {
  position: relative;
  display: inline-flex;
  align-items: center;
  margin-right: auto;
  text-decoration: none;
}
.s-header__logo-img {
  display: block;
  height: 56px;
  width: auto;
  transition: height var(--sr-dur) var(--sr-ease), opacity var(--sr-dur) var(--sr-ease);
}
.s-header__logo-img--dark {
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  opacity: 0;
}
.s-header.is-scrolled .s-header__logo-img { height: 44px; }
.s-header.is-scrolled .s-header__logo-img--light { opacity: 0; }
.s-header.is-scrolled .s-header__logo-img--dark { opacity: 1; }

/* 4 links + 1 button. That is the entire nav. No dropdowns — zero. Dropdowns
   are hover-dependent, fail on touch, and signal depth we don't have. */
.s-header__list { display: flex; align-items: center; gap: var(--sr-space-8); }
.s-header__link {
  position: relative;
  font-size: var(--sr-fs-body-sm);
  font-weight: var(--sr-fw-semibold);
  text-decoration: none;
  color: var(--sr-white);
  padding-block: var(--sr-space-2);
  transition: color var(--sr-dur) var(--sr-ease);
}
.s-header__link::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 2px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--sr-dur) var(--sr-ease);
}
@media (hover: hover) and (pointer: fine) {
  .s-header__link:hover::after { transform: scaleX(1); }
}
.s-header__link[aria-current="page"]::after { transform: scaleX(1); }
.s-header.is-scrolled .s-header__link { color: var(--sr-navy-700); }

.s-header__toggle { display: none; color: var(--sr-white); }
.s-header.is-scrolled .s-header__toggle { color: var(--sr-navy-700); }

/* Tablet ↓ — the header goes SOLID from pixel one and never transparent.
   Contrast over an unpredictable photo is not a risk worth taking on the
   device where most first-time visitors arrive. */
@media (max-width: 1024px) {
  .s-header {
    height: var(--sr-header-h-scrolled);
    background: var(--sr-white);
    box-shadow: var(--sr-shadow-sm);
  }
  /* Header is solid white from pixel one here, so the navy mark is the only
     correct one — pin it and drop the crossfade entirely. */
  .s-header__logo-img { height: 44px; }
  .s-header__logo-img--light { opacity: 0; }
  .s-header__logo-img--dark  { opacity: 1; }
  .s-header__toggle { display: inline-flex; color: var(--sr-navy-700); }
  .s-header__nav,
  .s-header__cta { display: none; }
}
@media (max-width: 767px) {
  .s-header__logo-img { height: 38px; }
}
/* HEADER END */


/* ──────────────────────────────────────────────────────────────────────────
   MOBILE DRAWER                             → Theme Builder → Header (global)
   Full-screen overlay, not a slide-in panel. Focus trapped; Esc closes; focus
   returns to the trigger. 56px tap heights.
   ────────────────────────────────────────────────────────────────────────── */

.s-drawer {
  position: fixed;
  inset: 0;
  z-index: var(--sr-z-drawer);
  display: flex;
  flex-direction: column;
  background: var(--sr-white);
  opacity: 0;
  transform: scale(.98);
  transition: opacity var(--sr-dur-slow) var(--sr-ease),
              transform var(--sr-dur-slow) var(--sr-ease);
}
.s-drawer.is-open { opacity: 1; transform: scale(1); }

.s-drawer__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--sr-header-h-scrolled);
  flex: 0 0 auto;
}
.s-drawer__logo-img {
  display: block;
  height: 44px;
  width: auto;   /* navy mark — the drawer is white */
}

.s-drawer__nav {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--sr-space-6);
  padding-block: var(--sr-space-8) var(--sr-space-12);
  overflow-y: auto;
}
.s-drawer__list { display: flex; flex-direction: column; }
.s-drawer__list a {
  display: flex;
  align-items: center;
  min-height: 56px;
  font-family: var(--sr-font-heading);
  font-size: 32px;
  font-weight: var(--sr-fw-bold);
  letter-spacing: var(--sr-ls-tighter);
  color: var(--sr-navy-700);
  text-decoration: none;
}
.s-drawer__cta { margin-top: var(--sr-space-2); }

.s-drawer__ribbon {
  padding-top: var(--sr-space-6);
  border-top: 1px solid var(--sr-border);
  color: var(--sr-ink-muted);
  font-size: var(--sr-fs-body-sm);
}
.s-drawer__ribbon a { color: inherit; }

.s-drawer__social { display: flex; gap: var(--sr-space-5); margin-top: auto; color: var(--sr-navy-700); }
/* MOBILE DRAWER END */


/* ──────────────────────────────────────────────────────────────────────────
   HERO — HOME                                → Saved Template: "Hero — Home"
   85vh, NOT 100vh: the 15% content peek defeats the "is there more?"
   hesitation. Mobile is min-height + auto-grow — never viewport-locked, so
   the layout survives a 200% text-spacing override (WCAG 1.4.12).
   ────────────────────────────────────────────────────────────────────────── */

.s-hero {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 85vh;
  padding-block: calc(var(--sr-header-h) + var(--sr-space-10)) var(--sr-space-16);
  overflow: hidden;
}
.s-hero__media { position: absolute; inset: 0; z-index: 0; }

/* The scrim. A GUARANTEED gradient, not a hope — it holds 4.5:1 on the text
   regardless of what photograph lands behind it. A pseudo-element, so no
   meaningless div. */
.s-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(105deg,
              rgba(12, 36, 64, .88) 0%,
              rgba(12, 36, 64, .70) 45%,
              rgba(12, 36, 64, .28) 100%);
}

.s-hero__body {
  position: relative;
  z-index: 2;
  max-width: 720px;
  margin-right: auto;
  margin-left: 0;
  padding-left: var(--sr-gutter);
}
.s-hero__eyebrow { color: var(--sr-gold-500); }          /* 6.4:1 on navy ✓ */
.s-hero__title   { color: var(--sr-white); }
.s-hero__sub     { color: rgba(255, 255, 255, .88); margin-top: var(--sr-space-5); max-width: 60ch; }
.s-hero__actions { margin-top: var(--sr-space-8); }
.s-hero__ribbon  { margin-top: var(--sr-space-8); width: fit-content; }

.s-hero__cue {
  position: absolute;
  left: 50%;
  bottom: var(--sr-space-8);
  z-index: 2;
  transform: translateX(-50%);
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  color: rgba(255, 255, 255, .7);
  transition: opacity var(--sr-dur) var(--sr-ease), color var(--sr-dur) var(--sr-ease);
  animation: s-hero-cue 2.4s var(--sr-ease) infinite;
}
@keyframes s-hero-cue {
  0%, 100% { transform: translate(-50%, 0); }
  50%      { transform: translate(-50%, 6px); }
}
@media (hover: hover) and (pointer: fine) { .s-hero__cue:hover { color: var(--sr-white); } }
.s-hero.is-scrolled-past .s-hero__cue { opacity: 0; pointer-events: none; }

@media (max-width: 1024px) {
  .s-hero {
    min-height: 0;
    padding-block: calc(var(--sr-header-h-scrolled) + var(--sr-space-16)) var(--sr-space-20);
  }
  .s-hero::after {
    background: linear-gradient(to top,
                rgba(12, 36, 64, .90) 0%,
                rgba(12, 36, 64, .72) 60%,
                rgba(12, 36, 64, .55) 100%);
  }
  .s-hero__cue { display: none; }
}
@media (max-width: 880px) {
  .s-hero__ribbon { width: 100%; }
  .s-hero__actions .c-btn { flex: 1 1 auto; }
}
/* HERO END */


/* ──────────────────────────────────────────────────────────────────────────
   MISSION                                       → Saved Template: "Mission"
   ────────────────────────────────────────────────────────────────────────── */

.s-mission__media {
  /* Bleeds past the container's right edge. The overflow is what stops this
     reading as a plain two-column block. */
  margin-right: calc(var(--sr-gutter) * -1);
}
@media (max-width: 1024px) {
  .s-mission__media { margin-right: 0; order: -1; }  /* photo first — people read faces before copy */
}
/* MISSION END */


/* ──────────────────────────────────────────────────────────────────────────
   ABOUT — HOME                              → Saved Template: "About — Home"
   ────────────────────────────────────────────────────────────────────────── */

.s-about__media { margin-left: calc(var(--sr-gutter) * -1); }

.s-about__facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sr-space-10);
  padding-top: var(--sr-space-6);
  border-top: 1px solid var(--sr-border);
}
.s-about__facts li { display: flex; flex-direction: column; gap: 2px; }
.s-about__facts strong {
  font-family: var(--sr-font-heading);
  font-size: var(--sr-fs-h3);
  font-weight: var(--sr-fw-bold);
  color: var(--sr-navy-700);
  line-height: 1.1;
}
.s-about__facts span {
  font-size: var(--sr-fs-caption);
  font-weight: var(--sr-fw-semibold);
  letter-spacing: var(--sr-ls-widest);
  text-transform: uppercase;
  color: var(--sr-ink-muted);
}

@media (max-width: 1024px) {
  .s-about__media { margin-left: 0; order: -1; }
}
@media (max-width: 767px) {
  .s-about__facts { gap: var(--sr-space-6); }
}
/* ABOUT END */


/* ──────────────────────────────────────────────────────────────────────────
   COMMUNITY IMPACT                     → Saved Template: "Community Impact"
   ────────────────────────────────────────────────────────────────────────── */

.s-impact__icon--teal  { background: var(--sr-teal-50);  color: var(--sr-teal-700); }
.s-impact__icon--ember { background: var(--sr-ember-50); color: var(--sr-ember-800); }
.s-impact__icon--gold  { background: var(--sr-gold-100); color: var(--sr-gold-700); }
/* COMMUNITY IMPACT END */


/* ──────────────────────────────────────────────────────────────────────────
   STATISTICS BAND                        → Saved Template: "Statistics Band"
   A rhythm break — the visual exhale that separates "what we do" from
   "proof we do it".
   ────────────────────────────────────────────────────────────────────────── */

/* ⚠ Selectors here are doubled (.s-stats .s-stats__grid = 0,2,0) on purpose.
   §08 RESPONSIVE loads AFTER §06, so a plain .s-stats__grid (0,1,0) LOSES to
   §08's .l-grid--4{1fr} at the same specificity. A section must be able to
   override a global utility from inside its own fence — that's the whole
   contract. Doubling is the fix that keeps the fence self-contained. */
.s-stats .s-stats__grid { align-items: start; }
.s-stats__note {
  margin: var(--sr-space-12) auto 0;
  text-align: center;
  font-size: var(--sr-fs-body-sm);
  font-style: italic;
  color: var(--sr-navy-200);
}
/* ⚠ minmax(0, 1fr), NOT 1fr. Plain `1fr` means minmax(AUTO, 1fr): the column
   refuses to shrink below its content, so a long value ("$127,000") pushes the
   grid past the viewport and the whole PAGE scrolls sideways. minmax(0,...)
   lets the track shrink. This is the guard that stops a future stat string
   from silently breaking the layout. */
@media (max-width: 1024px) {
  .s-stats .s-stats__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sr-space-12) var(--sr-space-8);
  }
}
@media (max-width: 767px) {
  /* ★ Stays 2×2 — four stacked numbers read as a list, not a scoreboard.
     This is the rule §08's .l-grid--4{1fr} was silently killing.
     ⚠ Stat drops to 32px here, NOT Phase 1's 44px. At 375px a 2-up track is
     ~155px and "$127,000" at 44px needs ~200px. Phase 1 sized the scale
     against a 3-digit stat and never tested it against the longest real
     string. 2×2 at 32px beats 1×4 at 44px: the scoreboard read survives,
     which was the actual intent behind the number. */
  .s-stats .s-stats__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sr-space-10) var(--sr-space-4);
  }
  .s-stats .c-stat__value { font-size: 32px; }
  .s-stats__note { margin-top: var(--sr-space-8); }
}
/* STATISTICS BAND END */


/* ──────────────────────────────────────────────────────────────────────────
   EVENTS PREVIEW                          → Saved Template: "Events Preview"
   → WORDPRESS: Loop Grid on the Event CPT, order by start date ASC, limit 3.
   ────────────────────────────────────────────────────────────────────────── */

.s-events__list { gap: var(--sr-space-4); }
/* EVENTS PREVIEW END */


/* ──────────────────────────────────────────────────────────────────────────
   GALLERY TEASER                          → Saved Template: "Gallery Teaser"
   ⚠ Not in the Step 4 brief — restored from Phase 1 §07. Delete this fence
     and its HTML block to remove. Nothing else moves.
   Asymmetric mosaic: one 2×2 lead + four singles.
   ────────────────────────────────────────────────────────────────────────── */

.s-teaser__mosaic {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--sr-gap-gallery);
}
.s-teaser__cell { aspect-ratio: 1 / 1; }
.s-teaser__cell--lead { grid-column: span 2; grid-row: span 2; }
.s-teaser__link {
  display: block;
  height: 100%;
  overflow: hidden;
  border-radius: var(--sr-radius-lg);
}
.s-teaser__link .c-media {
  height: 100%;
  transition: transform var(--sr-dur-slow) var(--sr-ease);
}
@media (hover: hover) and (pointer: fine) {
  .s-teaser__link:hover .c-media { transform: scale(1.05); }
}
@media (prefers-reduced-motion: reduce) {
  .s-teaser__link:hover .c-media { transform: none; }
}

@media (max-width: 767px) {
  .s-teaser__mosaic { grid-template-columns: repeat(2, 1fr); }
  /* Drop the 5th tile — an orphan single under a 2×2 lead reads as a mistake. */
  .s-teaser__cell:nth-child(5) { display: none; }
}
/* GALLERY TEASER END */


/* ──────────────────────────────────────────────────────────────────────────
   TESTIMONIAL                                → Saved Template: "Testimonial"
   Generous whitespace is the point — this is a beat to absorb, not to read.
   ────────────────────────────────────────────────────────────────────────── */

.s-voices { padding-block: var(--sr-space-32); }
@media (max-width: 1024px) { .s-voices { padding-block: var(--sr-space-24); } }
@media (max-width: 767px)  { .s-voices { padding-block: var(--sr-space-16); } }
/* TESTIMONIAL END */


/* ──────────────────────────────────────────────────────────────────────────
   VOLUNTEER CTA                     → Saved Template: "Ways to Get Involved"
   ────────────────────────────────────────────────────────────────────────── */

.s-volunteer__card { gap: var(--sr-space-5); align-items: flex-start; }
.s-volunteer__card p { flex: 1; }
.s-volunteer__card--lead { box-shadow: var(--sr-shadow-lg); }
.s-volunteer__card--lead p { color: var(--sr-navy-200); }

.s-volunteer__icon {
  width: 64px; height: 64px;
  background: rgba(255, 255, 255, .12);
  color: var(--sr-gold-500);
}
.s-volunteer__icon--light { background: var(--sr-navy-50); color: var(--sr-navy-700); }
/* VOLUNTEER CTA END */


/* ──────────────────────────────────────────────────────────────────────────
   SPONSORS                                      → Saved Template: "Sponsors"
   ────────────────────────────────────────────────────────────────────────── */

.s-sponsors__grid { align-items: stretch; }
.s-sponsors__grid > li { display: flex; }
.s-sponsors__grid .c-sponsor { flex: 1; }
.s-sponsors__cta { margin-top: var(--sr-space-10); text-align: center; }
/* SPONSORS END */


/* ──────────────────────────────────────────────────────────────────────────
   PAGE HERO — COMPACT              → Saved Template: "Page Hero — Compact"
   Used by events.html and gallery.html. 40vh, not 85vh: a sub-page hero
   ORIENTS, it doesn't sell. Burning 85vh here would push the actual content
   below the fold, which is the one thing these pages exist to prevent.
   ────────────────────────────────────────────────────────────────────────── */

.s-pagehero {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: 40vh;
  padding-block: calc(var(--sr-header-h) + var(--sr-space-16)) var(--sr-space-16);
  overflow: hidden;
}
.s-pagehero__media { position: absolute; inset: 0; z-index: 0; }
.s-pagehero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(105deg,
              rgba(12, 36, 64, .90) 0%,
              rgba(12, 36, 64, .74) 50%,
              rgba(12, 36, 64, .38) 100%);
}
.s-pagehero__body { position: relative; z-index: 2; max-width: 720px; }
.s-pagehero__eyebrow { color: var(--sr-gold-500); }
.s-pagehero__title {
  font-family: var(--sr-font-heading);
  font-size: var(--sr-fs-h1);
  font-weight: var(--sr-fw-bold);
  line-height: var(--sr-lh-tight);
  letter-spacing: var(--sr-ls-tighter);
  color: var(--sr-white);
}
.s-pagehero__sub { color: rgba(255, 255, 255, .86); margin-top: var(--sr-space-4); max-width: 56ch; }

@media (max-width: 1024px) {
  .s-pagehero {
    min-height: 0;
    padding-block: calc(var(--sr-header-h-scrolled) + var(--sr-space-12)) var(--sr-space-12);
  }
  .s-pagehero::after {
    background: linear-gradient(to top, rgba(12,36,64,.92) 0%, rgba(12,36,64,.74) 70%, rgba(12,36,64,.6) 100%);
  }
}
/* PAGE HERO — COMPACT END */


/* ──────────────────────────────────────────────────────────────────────────
   UPCOMING EVENTS                       → Saved Template: "Upcoming Events"
   ────────────────────────────────────────────────────────────────────────── */

.s-upcoming__filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sr-space-2);
  margin-bottom: var(--sr-space-8);
}
.s-upcoming__filter {
  min-height: 44px;                    /* ★ WCAG 2.2 §2.5.8 */
  padding: var(--sr-space-2) var(--sr-space-5);
  border: 1px solid var(--sr-border-strong);
  border-radius: var(--sr-radius-full);
  background: var(--sr-white);
  font-size: var(--sr-fs-body-sm);
  font-weight: var(--sr-fw-semibold);
  color: var(--sr-ink-muted);
  transition: background-color var(--sr-dur) var(--sr-ease),
              border-color var(--sr-dur) var(--sr-ease),
              color var(--sr-dur) var(--sr-ease);
}
@media (hover: hover) and (pointer: fine) {
  .s-upcoming__filter:hover { border-color: var(--sr-navy-700); color: var(--sr-navy-700); }
}
/* Selected state is carried by aria-selected, not a class — the accessible
   state and the visual state cannot drift apart if they're the same attribute. */
.s-upcoming__filter[aria-selected="true"] {
  background: var(--sr-navy-700);
  border-color: var(--sr-navy-700);
  color: var(--sr-white);
}
.s-upcoming__list { gap: var(--sr-space-4); }
.s-upcoming__empty { margin-top: var(--sr-space-4); }
/* UPCOMING EVENTS END */


/* ──────────────────────────────────────────────────────────────────────────
   MEETING SCHEDULE                    → Saved Template: "Meeting Schedule"
   ★ THE SPINE, fullest rendering. Static content — true even if nobody logs
     in for six months.
   ────────────────────────────────────────────────────────────────────────── */

.s-schedule__grid {
  display: grid;
  grid-template-columns: 7fr 5fr;
  gap: var(--sr-space-12);
  align-items: start;
}
.s-schedule__card {
  /* Overrides .c-ribbon's row flex — this rendering is a full card. */
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sr-space-5);
  padding: var(--sr-space-8);
  border-radius: var(--sr-radius-2xl);
  box-shadow: var(--sr-shadow-lg);
  font-size: var(--sr-fs-body);
  font-weight: var(--sr-fw-regular);
}
.s-schedule__label {
  font-size: var(--sr-fs-caption);
  font-weight: var(--sr-fw-semibold);
  letter-spacing: var(--sr-ls-widest);
  text-transform: uppercase;
  color: var(--sr-ember-800);
}
.s-schedule__when {
  font-family: var(--sr-font-heading);
  font-size: var(--sr-fs-h2);
  font-weight: var(--sr-fw-bold);
  line-height: 1.1;
  letter-spacing: var(--sr-ls-tighter);
  color: var(--sr-navy-700);
}
.s-schedule__when span {
  display: block;
  font-family: var(--sr-font-body);
  font-size: var(--sr-fs-body-lg);
  font-weight: var(--sr-fw-semibold);
  letter-spacing: 0;
  color: var(--sr-ink-muted);
  margin-top: var(--sr-space-1);
}
.s-schedule__facts {
  display: flex;
  flex-direction: column;
  gap: var(--sr-space-4);
  padding-top: var(--sr-space-5);
  border-top: 1px solid var(--sr-border);
  width: 100%;
}
.s-schedule__facts li {
  display: grid;
  grid-template-columns: 20px 1fr;
  gap: var(--sr-space-3);
  align-items: start;
  font-size: var(--sr-fs-body-sm);
  line-height: 1.6;
}
.s-schedule__facts .c-icon { color: var(--sr-teal-500); margin-top: 3px; }
.s-schedule__aside {
  display: flex;
  flex-direction: column;
  gap: var(--sr-space-4);
  padding: var(--sr-space-8);
  background: var(--sr-canvas);
  border-radius: var(--sr-radius-xl);
}

@media (max-width: 1024px) {
  .s-schedule__grid { grid-template-columns: 1fr; gap: var(--sr-space-8); }
}
@media (max-width: 767px) {
  .s-schedule__card,
  .s-schedule__aside { padding: var(--sr-space-5); }
  .s-schedule__card .c-btn { width: 100%; }
}
/* MEETING SCHEDULE END */


/* ──────────────────────────────────────────────────────────────────────────
   BOARD MEETINGS                          → Saved Template: "Board Meetings"
   Deliberately the QUIETEST section on the page. Internal business is a
   transparency signal, not a draw — giving it visual weight would be a
   mistake. No imagery, no CTA, muted palette.
   ────────────────────────────────────────────────────────────────────────── */

.s-board__inner {
  display: grid;
  grid-template-columns: 6fr 6fr;
  gap: var(--sr-space-12);
  align-items: center;
  padding: var(--sr-space-8);
  background: var(--sr-white);
  border: 1px solid var(--sr-border);
  border-radius: var(--sr-radius-xl);
}
.s-board__intro { display: flex; flex-direction: column; gap: var(--sr-space-3); align-items: flex-start; }
.s-board__dates { display: flex; flex-direction: column; }
.s-board__dates li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sr-space-4);
  padding: var(--sr-space-4) 0;
  border-bottom: 1px solid var(--sr-border);
  font-size: var(--sr-fs-body-sm);
}
.s-board__dates li:first-child { border-top: 1px solid var(--sr-border); }
.s-board__dates time { font-weight: var(--sr-fw-semibold); color: var(--sr-navy-700); white-space: nowrap; }
.s-board__dates span { color: var(--sr-ink-muted); text-align: right; }

@media (max-width: 1024px) {
  .s-board__inner { grid-template-columns: 1fr; gap: var(--sr-space-8); }
}
@media (max-width: 767px) {
  .s-board__inner { padding: var(--sr-space-5); }
}
/* BOARD MEETINGS END */


/* ──────────────────────────────────────────────────────────────────────────
   FUNDRAISING                                → Saved Template: "Fundraising"
   Evergreen, not dated — so it does NOT duplicate the dated fundraiser cards
   in Upcoming Events. Different question, different answer.
   ────────────────────────────────────────────────────────────────────────── */

.s-fund__card { overflow: hidden; }
.s-fund__body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sr-space-3);
  padding: var(--sr-space-6);
  flex: 1;
}
.s-fund__body p { flex: 1; }
.s-fund__raised {
  flex: 0 0 auto;
  width: 100%;
  margin-top: var(--sr-space-2);
  padding-top: var(--sr-space-4);
  border-top: 1px solid var(--sr-border);
  font-size: var(--sr-fs-body-sm);
  color: var(--sr-ink-muted);
}
.s-fund__raised strong {
  font-family: var(--sr-font-heading);
  font-size: var(--sr-fs-h4);
  font-weight: var(--sr-fw-bold);
  color: var(--sr-teal-700);            /* 7.1:1 ✓ — money reads as growth, not alarm */
}
/* FUNDRAISING END */


/* ──────────────────────────────────────────────────────────────────────────
   CALENDAR PREVIEW                      → Saved Template: "Calendar Preview"
   ⚠ SECONDARY BY DESIGN. The list above stays canonical: a 45px cell cannot
     hold "Pancake Breakfast for Hearing, 7–11am, Fire Station #2". This is a
     glanceable index + the subscribe CTA, and nothing more.
   Real <table> — a month IS tabular data. Gives screen readers row/column
   semantics for free, which a div grid would have to fake with ARIA.
   ────────────────────────────────────────────────────────────────────────── */

.s-cal__grid {
  display: grid;
  grid-template-columns: 5fr 4fr;
  gap: var(--sr-space-12);
  align-items: start;
}
.s-cal__month {
  padding: var(--sr-space-6);
  background: var(--sr-white);
  border: 1px solid var(--sr-border);
  border-radius: var(--sr-radius-xl);
  box-shadow: var(--sr-shadow-sm);
}
.s-cal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--sr-space-4);
}
.s-cal__nav { display: flex; gap: var(--sr-space-1); }
.s-cal__nav button[disabled] { opacity: .35; pointer-events: none; }

.s-cal__table { width: 100%; table-layout: fixed; }
.s-cal__table th {
  padding-bottom: var(--sr-space-3);
  font-size: var(--sr-fs-caption);
  font-weight: var(--sr-fw-semibold);
  letter-spacing: var(--sr-ls-wide);
  color: var(--sr-ink-subtle);
}
.s-cal__table th abbr { text-decoration: none; }
.s-cal__table td { padding: 2px; text-align: center; }

/* ⚠ TAP TARGET NOTE — the one place on the site under 44px, measured at 38px
   on a 375px screen. Seven columns in a ~295px card caps out at ~42px; 44 is
   geometrically impossible without horizontal scroll, which would be a worse
   failure (WCAG 1.4.10).
   It is still CONFORMANT: 2.5.8 AA requires 24×24, and the "equivalent
   control" exception applies cleanly — every dotted day links to an event card
   in the list above, and those are 44px+. The list is the accessible path;
   this is the glanceable index. Documented rather than quietly ignored. */
.s-cal__day {
  position: relative;
  display: grid;
  place-items: center;
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: var(--sr-radius-md);
  font-size: var(--sr-fs-body-sm);
  font-variant-numeric: tabular-nums;
  color: var(--sr-ink-muted);
  text-decoration: none;
}
/* Days WITH an event: filled, navy, and a real link into the list above.
   The dot alone would be colour-only information (WCAG 1.4.1) — the weight
   change and the visually-hidden event name carry it too. */
.s-cal__day--event {
  background: var(--sr-navy-50);
  color: var(--sr-navy-700);
  font-weight: var(--sr-fw-bold);
  transition: background-color var(--sr-dur) var(--sr-ease), color var(--sr-dur) var(--sr-ease);
}
.s-cal__day--event::after {
  content: "";
  position: absolute;
  bottom: 5px;
  width: 5px; height: 5px;
  border-radius: var(--sr-radius-full);
  background: var(--sr-navy-500);
}
.s-cal__day--fundraiser { background: var(--sr-gold-100); color: var(--sr-gold-700); }
.s-cal__day--fundraiser::after { background: var(--sr-gold-700); }
.s-cal__day--board { background: #F1F0EE; color: var(--sr-ink-muted); }
.s-cal__day--board::after { background: var(--sr-ink-subtle); }
@media (hover: hover) and (pointer: fine) {
  .s-cal__day--event:hover { background: var(--sr-navy-700); color: var(--sr-white); }
  .s-cal__day--event:hover::after { background: var(--sr-white); }
}

.s-cal__legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sr-space-4);
  margin-top: var(--sr-space-5);
  padding-top: var(--sr-space-4);
  border-top: 1px solid var(--sr-border);
}
.s-cal__key {
  display: inline-flex;
  align-items: center;
  gap: var(--sr-space-2);
  font-size: var(--sr-fs-caption);
  color: var(--sr-ink-muted);
}
.s-cal__key::before {
  content: "";
  width: 10px; height: 10px;
  border-radius: var(--sr-radius-full);
}
.s-cal__key--meeting::before    { background: var(--sr-navy-500); }
.s-cal__key--fundraiser::before { background: var(--sr-gold-700); }
.s-cal__key--board::before      { background: var(--sr-ink-subtle); }

.s-cal__subscribe { display: flex; flex-direction: column; gap: var(--sr-space-4); }
.s-cal__links { display: flex; flex-direction: column; gap: var(--sr-space-3); margin-top: var(--sr-space-2); }
.s-cal__links .c-btn--block { justify-content: flex-start; gap: var(--sr-space-3); }

@media (max-width: 1024px) {
  .s-cal__grid { grid-template-columns: 1fr; gap: var(--sr-space-8); }
  .s-cal__month { max-width: 480px; }
}
@media (max-width: 767px) {
  .s-cal__month { padding: var(--sr-space-4); }
  .s-cal__day { font-size: var(--sr-fs-caption); }
}
/* CALENDAR PREVIEW END */


/* ──────────────────────────────────────────────────────────────────────────
   GALLERY GRID                              → Saved Template: "Gallery Grid"

   ★ MASONRY VIA CSS MULTI-COLUMN. Three options were on the table:

     1. grid-template-rows: masonry — still not stable in 2026. Rejected.
     2. CSS Grid with fixed aspect ratios — correct source order, but it CROPS.
        Phase 1: "the volunteer will upload phone photos in mixed orientations,
        and forced 1:1 crops will decapitate people — routinely, invisibly, and
        permanently." The grid must survive its maintainer. Rejected.
     3. CSS multi-column — preserves native ratios, zero JS, universal support,
        AND it is exactly how Elementor's Gallery widget does masonry, so it
        maps 1:1. Chosen.

   The usual objection to columns is that content flows DOWN column 1 before
   column 2, so source order ≠ left-to-right reading order. That is fine here
   and is in fact an ACCESSIBILITY WIN: visual order and DOM/tab order both run
   down the columns, so they agree. A JS-balanced masonry would break that.
   ────────────────────────────────────────────────────────────────────────── */

.s-gallery__grid {
  column-count: 3;
  column-gap: var(--sr-gap-gallery);
}
.s-gallery__cell {
  /* All three: Safari and older Firefox still want the legacy properties, and
     a tile torn across a column break looks like a rendering bug. */
  -webkit-column-break-inside: avoid;
     page-break-inside: avoid;
          break-inside: avoid;
  margin-bottom: var(--sr-gap-gallery);
}

.s-gallery__more {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sr-space-4);
  margin-top: var(--sr-space-12);
}
.s-gallery__count {
  font-size: var(--sr-fs-body-sm);
  color: var(--sr-ink-muted);
  max-width: none;
}
.s-gallery__empty { margin-top: var(--sr-space-4); }

/* Tablet ↓ — 2 columns. */
@media (max-width: 1024px) {
  .s-gallery__grid { column-count: 2; }
}
/* ★ Mobile — STAYS 2 columns, NOT 1. Photo-scanning is the primary behaviour
   here: 2-up shows 6+ photos per screen instead of 2, and a single column
   reads as a slideshow you're trapped in. This is why the gallery does NOT
   opt into §08's generic 1-col collapse. */
@media (max-width: 767px) {
  .s-gallery__grid { column-count: 2; }
}
/* GALLERY GRID END */


/* ──────────────────────────────────────────────────────────────────────────
   PAST EVENTS                                → Saved Template: "Past Events"
   ⚠ Not in the Step 5 brief — restored from Phase 1. It is where auto-archived
     events land, and it is the recency proof a sponsor checks.
   <details>/<summary> — native keyboard support, zero JS, zero bugs. Ships
   collapsed so past never outweighs future.
   ────────────────────────────────────────────────────────────────────────── */

.s-past__wrap {
  border: 1px solid var(--sr-border);
  border-radius: var(--sr-radius-xl);
  background: var(--sr-canvas);
  padding: var(--sr-space-6) var(--sr-space-8);
}
.s-past__summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sr-space-4);
  min-height: 44px;
  cursor: pointer;
  list-style: none;
}
.s-past__summary::-webkit-details-marker { display: none; }
.s-past__summary .c-eyebrow { margin-bottom: var(--sr-space-1); }
.s-past__chevron {
  color: var(--sr-navy-700);
  flex: 0 0 auto;
  transition: transform var(--sr-dur) var(--sr-ease);
}
.s-past__wrap[open] .s-past__chevron { transform: rotate(180deg); }
.s-past__list {
  gap: var(--sr-space-2);
  margin-top: var(--sr-space-6);
  padding-top: var(--sr-space-6);
  border-top: 1px solid var(--sr-border);
}

@media (max-width: 767px) {
  .s-past__wrap { padding: var(--sr-space-5); }
}
/* PAST EVENTS END */


/* ──────────────────────────────────────────────────────────────────────────
   CTA BAND                             → Saved Template: "CTA Band" ★ GLOBAL
   Saved ONCE, reused on all three pages. Sits flush against the footer with
   no gap, so the page bottoms out rather than trailing off.
   ────────────────────────────────────────────────────────────────────────── */

.s-cta {
  text-align: center;
  background-image:
    radial-gradient(circle at 12% 18%, rgba(242, 169, 59, .10) 0, transparent 42%),
    radial-gradient(circle at 88% 82%, rgba(196, 61, 48, .12) 0, transparent 45%);
}
.s-cta__title  { text-wrap: balance; }
.s-cta__sub    { margin: var(--sr-space-5) auto 0; color: rgba(255, 255, 255, .82); }
.s-cta__action { margin-top: var(--sr-space-8); }
.s-cta__ribbon { margin: var(--sr-space-8) auto 0; width: fit-content; justify-content: center; }
.s-cta__human  {
  margin-top: var(--sr-space-8);
  font-size: var(--sr-fs-body-sm);
  color: var(--sr-navy-200);
}
.s-cta__human a { color: var(--sr-gold-500); font-weight: var(--sr-fw-semibold); }

@media (max-width: 880px) {
  .s-cta__ribbon { width: 100%; }
}
/* CTA BAND END */


/* ──────────────────────────────────────────────────────────────────────────
   FOOTER                                    → Theme Builder → Footer (global)
   navy-900 — one step darker than the CTA band, so the page bottoms out.
   ────────────────────────────────────────────────────────────────────────── */

.s-footer {
  background: var(--sr-navy-900);
  color: rgba(255, 255, 255, .78);
  padding-block: var(--sr-space-24) var(--sr-space-8);
  font-size: var(--sr-fs-body-sm);
}
.s-footer a { color: inherit; text-decoration: none; }
@media (hover: hover) and (pointer: fine) {
  .s-footer a:hover { color: var(--sr-white); text-decoration: underline; text-underline-offset: 3px; }
}

.s-footer__grid {
  display: grid;
  grid-template-columns: 1.5fr 1fr 1.4fr 1.4fr;
  gap: var(--sr-space-10);
  padding-bottom: var(--sr-space-16);
  border-bottom: 1px solid rgba(255, 255, 255, .12);
}
.s-footer__col { display: flex; flex-direction: column; gap: var(--sr-space-4); }
.s-footer__col p { max-width: 40ch; }

.s-footer__logo-img {
  display: block;
  height: 68px;
  width: auto;   /* white mark — the footer is navy-900 */
  margin-bottom: var(--sr-space-1);
}

.s-footer__heading {
  font-family: var(--sr-font-body);
  font-size: var(--sr-fs-caption);
  font-weight: var(--sr-fw-semibold);
  letter-spacing: var(--sr-ls-widest);
  text-transform: uppercase;
  color: var(--sr-white);
  margin-bottom: var(--sr-space-1);
}
.s-footer__list { display: flex; flex-direction: column; gap: var(--sr-space-3); }
.s-footer__social { display: flex; gap: var(--sr-space-4); margin-top: auto; color: var(--sr-white); }

.s-footer__ribbon { gap: var(--sr-space-3); }
.s-footer__ribbon .c-icon { color: var(--sr-gold-500); }
.s-footer__nl-label { color: var(--sr-white); }
.s-footer__newsletter { margin-top: var(--sr-space-4); }

/* Alicia's door — quiet on purpose. Findable by someone looking for it,
   not performative to everyone else. */
.s-footer__help a {
  display: inline-flex;
  align-items: center;
  gap: var(--sr-space-2);
  font-weight: var(--sr-fw-semibold);
  color: var(--sr-gold-500);
}

.s-footer__base {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sr-space-4);
  padding-top: var(--sr-space-8);
}
.s-footer__base .c-caption { color: rgba(255, 255, 255, .55); }
.s-footer__base a { text-decoration: underline; text-underline-offset: 3px; }

@media (max-width: 1024px) {
  .s-footer__grid { grid-template-columns: repeat(2, 1fr); gap: var(--sr-space-12) var(--sr-space-10); }
}
@media (max-width: 767px) {
  .s-footer { padding-block: var(--sr-space-16) var(--sr-space-8); }
  .s-footer__grid { grid-template-columns: 1fr; gap: var(--sr-space-10); }
  .s-footer__social { margin-top: var(--sr-space-2); }
  .s-footer__base { flex-direction: column; align-items: flex-start; gap: var(--sr-space-2); }
}
/* FOOTER END */


/* ==========================================================================
   07  UTILITIES
   ========================================================================== */

/* Screen-reader only. */
.u-visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Skip link — the first focusable element on every page. Required. */
.u-skip-link {
  position: absolute;
  top: var(--sr-space-2);
  left: var(--sr-space-2);
  z-index: var(--sr-z-skip);
  padding: var(--sr-space-3) var(--sr-space-5);
  background: var(--sr-navy-700);
  color: var(--sr-white);
  border-radius: var(--sr-radius-md);
  font-weight: var(--sr-fw-semibold);
  text-decoration: none;
  transform: translateY(-150%);
  transition: transform var(--sr-dur) var(--sr-ease);
}
.u-skip-link:focus { transform: translateY(0); }

/* Scroll reveal — PROGRESSIVE ENHANCEMENT.
   Content is visible without JS: the hidden state only applies once the
   inline head script has set .has-js on <html>. JS never gates content. */
:root.has-js .u-reveal {
  opacity: 0;
  transform: translateY(var(--sr-reveal-y));
  transition: opacity var(--sr-dur-reveal) var(--sr-ease),
              transform var(--sr-dur-reveal) var(--sr-ease);
}
:root.has-js .u-reveal.is-visible { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  :root.has-js .u-reveal { opacity: 1; transform: none; transition: none; }
}
/* Stagger — applied to grid children. */
.u-reveal--d1 { transition-delay: 60ms; }
.u-reveal--d2 { transition-delay: 120ms; }
.u-reveal--d3 { transition-delay: 180ms; }

.u-text-center { text-align: center; }
.u-measure     { max-width: var(--sr-measure); }
.u-mt-auto     { margin-top: auto; }
.u-full-bleed  { width: 100%; }
.u-no-scroll   { overflow: hidden; }


/* ==========================================================================
   08  RESPONSIVE
   --------------------------------------------------------------------------
   Desktop-first. Every query below names its Elementor tab.
   Only rules that CANNOT live inline belong here — the type scale and the
   applied spacing tokens. Component/section reflow lives with its component.
   ========================================================================== */

/* --- LAPTOP · Elementor tab: Laptop · ⚠ must be enabled in Site Settings -- */
@media (max-width: 1366px) {
  :root {
    --sr-fs-display: 56px;
    --sr-fs-h1:      44px;
    --sr-fs-h2:      34px;
    --sr-fs-h3:      25px;
    --sr-fs-stat:    54px;
    --sr-fs-quote:   26px;
    --sr-section-y:  88px;
  }
}

/* --- TABLET · Elementor tab: Tablet · ★ THE PRIMARY BREAKPOINT ------------ */
/* Where the site changes character: desktop nav → hamburger, 3-col → 2-col,
   asymmetric splits collapse. Everything else is refinement.               */
@media (max-width: 1024px) {
  :root {
    --sr-fs-display:  46px;
    --sr-fs-h1:       38px;
    --sr-fs-h2:       31px;
    --sr-fs-h3:       23px;
    --sr-fs-h4:       19px;
    --sr-fs-body-lg:  18px;
    --sr-fs-stat:     48px;
    --sr-fs-quote:    24px;
    --sr-section-y:   80px;
    --sr-gutter:      40px;
    --sr-gap-grid:    24px;
    --sr-gap-gallery: 12px;
  }

  .l-grid--3,
  .l-grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .l-grid--5 { grid-template-columns: repeat(3, minmax(0, 1fr)); }

  /* The 7/5 split collapses to a stack. */
  .l-grid--split,
  .l-grid--split-reverse {
    grid-template-columns: 1fr;
    gap: var(--sr-space-10);
    direction: ltr;
  }

  .c-section-header { margin-bottom: var(--sr-space-12); }
  .c-section-header--split { flex-direction: column; align-items: flex-start; }
}

/* --- LARGE MOBILE · Elementor tab: Mobile Extra · ⚠ must be enabled ------- */
@media (max-width: 880px) {
  :root {
    --sr-fs-display:  40px;
    --sr-fs-h1:       35px;
    --sr-fs-h2:       29px;
    --sr-fs-h3:       22px;
    --sr-fs-h4:       18px;
    --sr-fs-body-lg:  17px;
    --sr-fs-eyebrow:  12px;
    --sr-fs-stat:     46px;
    --sr-fs-quote:    23px;
    --sr-section-y:   72px;
    --sr-gutter:      24px;
    --sr-gap-grid:    16px;
    --sr-gap-gallery:  8px;
  }

  /* Event card: the date chip goes horizontal-inline above the title,
     and the action becomes a full-width footer. */
  .c-event-card {
    grid-template-columns: 1fr;
    gap: var(--sr-space-4);
    padding: var(--sr-space-5);
  }
  .c-event-card__date {
    grid-auto-flow: column;
    justify-items: start;
    align-items: baseline;
    gap: var(--sr-space-2);
    width: fit-content;
    padding: var(--sr-space-2) var(--sr-space-3);
  }
  .c-event-card__day { font-size: 22px; }
  .c-event-card__action { width: 100%; }
  .c-event-card__action .c-btn { width: 100%; }

  .c-testimonial__by { flex-direction: column; text-align: center; gap: var(--sr-space-3); }

  /* Lightbox goes full-screen; arrows stay for keyboard/AT, swipe handles touch. */
  .c-lightbox__stage { padding-inline: var(--sr-space-4); }
  .c-lightbox__nav { width: 44px; height: 44px; }
}

/* --- MOBILE · Elementor tab: Mobile -------------------------------------- */
@media (max-width: 767px) {
  :root {
    --sr-fs-display: 38px;
    --sr-fs-h1:      34px;
    --sr-fs-h2:      28px;
    --sr-fs-stat:    44px;
    --sr-fs-quote:   22px;
    --sr-section-y:  64px;
    --sr-card-pad:   var(--sr-space-5);
  }

  .l-grid--2,
  .l-grid--3,
  .l-grid--4 { grid-template-columns: minmax(0, 1fr); }
  .l-grid--5 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* ★ Gallery stays 2-col — NOT 1. Photo-scanning is the primary behaviour
     here; a single column reads as a slideshow you're trapped in. The
     gallery grid opts back in from its own §06 block. */

  .c-icon-circle { width: 72px; height: 72px; }
  .c-icon--48 { width: 36px; height: 36px; }

  .c-newsletter__row { flex-direction: column; }
  .c-newsletter__row .c-btn { width: 100%; }

  .c-empty { padding: var(--sr-space-12) var(--sr-space-5); }
}

/* --- PRINT --------------------------------------------------------------- */
@media print {
  .c-lightbox, .u-skip-link { display: none !important; }
  :root.has-js .u-reveal { opacity: 1 !important; transform: none !important; }
  .c-media::after { content: none; }
}
