/* ==========================================================================
   NWPA — site.css
   Henry (Web Dev), 2026-08-06.

   Authored from Eleanor's design system, round 3
   (Dev Notes/Design/NWPA_Design_System.md). Every value below traces to a
   token or a measurement in that document; the cascade, the structure and the
   behaviour are mine.

   Order:
     1  Fonts
     2  Tokens
     3  Reset and base
     4  Typography
     5  Layout primitives
     6  Header, navigation, drawer
     7  Hero
     8  Page header
     9  Cards
    10  Rows (documents, newsletters, clubs, links)
    11  Officers
    12  Buttons and links
    13  Prose
    14  Footer
    15  Reduced motion
    16  Print
   ========================================================================== */


/* 1  Fonts -----------------------------------------------------------------
   Self-hosted, subset to Latin plus the Welsh diacritics. No CDN, at runtime
   or at build time. Five files, weights 400 and 600 only (design §3.2).       */

@font-face {
  font-family: "Cormorant Garamond";
  src: url("../fonts/cormorant-garamond-600.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Cormorant Garamond";
  src: url("../fonts/cormorant-garamond-600-italic.woff2") format("woff2");
  font-weight: 600;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Proza Libre";
  src: url("../fonts/proza-libre-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Proza Libre";
  src: url("../fonts/proza-libre-400-italic.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Proza Libre";
  src: url("../fonts/proza-libre-600.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

/* Cormorant sets optically small; Georgia at the same pixel size renders
   noticeably larger, so the swap jumps. Size-adjust the fallback to ~90%
   (design §3.2 — a starting measurement, tuned by eye against a rendered h1). */
@font-face {
  font-family: "Georgia fallback";
  src: local("Georgia"), local("Times New Roman");
  size-adjust: 90%;
  font-display: swap;
}


/* 2  Tokens ---------------------------------------------------------------- */

:root {
  /* Colour — three chromatic colours plus neutrals (design §3.1) */
  --c-maroon:        #6E1A16;
  --c-red:           #B03A22;
  --c-red-hover:     #8E2C19;
  --c-slate:         #1F4E5F;
  --c-slate-hover:   #163A47;

  --surface:         #FDFCFA;
  --surface-band:    #F4F1EC;
  --surface-deep:    #15333D;

  --ink:             #1F1D1B;
  --ink-muted:       #5D5854;
  --border:          #DCD5CD;
  --border-strong:   #8B8177;

  --on-deep:         #E9E4DD;
  --on-deep-muted:   #AFC0C7;
  --on-deep-link:    #F0A793;

  /* Hero scrim (design §3.5, §4.2d) — warm near-black, NOT the slate */
  --scrim-ink:       #1F1D1B;
  --scrim-alpha:     0.20;
  --scrim-plateau:   80%;
  --scrim-ease:      1.5;
  /* Footer band — same ink, DIFFERENT geometry: bottom-anchored in pixels,
     because the band's crop window varies from 49% of the frame at 1440 to
     75% in the mobile file, and a percentage ramp would reach into the sun.
     Do not substitute --scrim-alpha (design §3.5, §4.11e). */
  --band-scrim-alpha:   0.66;
  --band-scrim-plateau: 112px;
  --band-scrim-ramp:    160px;
  --band-scrim-ease:    2.5;

  /* Type */
  --font-display: "Cormorant Garamond", "Georgia fallback", Georgia, "Times New Roman", serif;
  --font-body:    "Proza Libre", Helvetica, Arial, sans-serif;

  /* Type scale — mobile column (design §3.2). Restepped at 600 and 1024. */
  --t-hero-h1:      30px;   --lh-hero-h1:   1.18;
  --t-page-h1:      28px;   --lh-page-h1:   1.18;
  --t-h2:           23px;   --lh-h2:        1.25;
  --t-h3:           20px;   --lh-h3:        1.30;
  --t-card-title:   20px;   --lh-card-title:1.30;
  --t-lead:         19px;   --lh-lead:      1.55;
  --t-body:         18px;   --lh-body:      1.60;
  --t-body-sm:      16px;   --lh-body-sm:   1.55;
  --t-meta:         14px;
  --t-eyebrow:      12px;
  --t-nav:          17px;
  --t-button:       15px;
  --t-credit:       12px;
  --t-cy:           12px;
  --t-footer:       15px;
  --t-footer-head:  12px;

  /* Spacing — 4px base, 8px rhythm (design §3.3) */
  --sp-1: 4px;   --sp-2: 8px;   --sp-3: 12px;  --sp-4: 16px;  --sp-5: 24px;
  --sp-6: 32px;  --sp-7: 48px;  --sp-8: 64px;  --sp-9: 96px;  --sp-10: 128px;

  /* Thumbnail to kicker, DG's call on the render (2026-08-06), superseding
     §4.4's --sp-4. It is ON the 4px base but OFF the 8px rhythm and has no
     token, so it is named here rather than left as a bare number in the card
     rules. Raised with Ada. */
  --card-media-gap: 20px;

  /* Measure and containers (design §3.2) */
  --measure:          68ch;
  --measure-narrow:   52ch;
  --measure-hero:     460px;
  --container-prose:  700px;
  --container:        1200px;
  --container-wide:   1440px;
  --gutter:           var(--sp-4);

  /* Radii, borders, motion (design §3.5) */
  --radius:            0;
  --radius-img:        2px;
  --border-width:      1px;
  --border-width-accent: 2px;
  --focus-width:       3px;
  --focus-offset:      2px;
  --transition:        160ms ease-out;
  --transition-slow:   240ms ease-out;
  --parallax-max:      64px;
  --tap-min:           44px;

  --header-height:     66px;   /* 64 + 2px rule, below 1080px */
  --header-height-min: 66px;
}

@media (min-width: 600px) {
  :root {
    --gutter: var(--sp-5);
    --t-hero-h1: 32px;  --lh-hero-h1: 1.14;   /* round 5: 36px measures 2.80:1 */
    --t-page-h1: 36px;  --lh-page-h1: 1.14;
    --t-h2: 26px;       --lh-h2: 1.22;
    --t-h3: 21px;
    --t-card-title: 21px;
    --t-lead: 20px;
    --lh-body: 1.65;
  }
}

@media (min-width: 900px) {
  :root { --gutter: var(--sp-6); }
}

@media (min-width: 1024px) {
  :root {
    --t-page-h1: 44px;  --lh-page-h1: 1.10;
    --t-h2: 30px;       --lh-h2: 1.20;
    --t-h3: 22px;       --lh-h3: 1.28;
    --t-card-title: 22px; --lh-card-title: 1.28;
    --t-lead: 21px;
    --t-meta: 15px;
    --t-eyebrow: 13px;
    --t-credit: 13px;
    --t-footer: 16px;
  }
}

/* The horizontal header engages at 1080px, not 900 — seven items plus a
   bilingual lockup do not fit below it (design §4.1a shows the arithmetic). */
@media (min-width: 1080px) {
  :root {
    /* Round 4: 44px, not 56px. At 56px the association's full name wraps to
       three lines in a 460px measure and the copy block grows to 322px, whose
       top edge lands in the brightest cloud in the frame. §4.2d. */
    --t-hero-h1: 44px;  --lh-hero-h1: 1.10;
    --t-nav: 13px;
    --header-height: 74px;      /* 72 + 2px rule */
    --header-height-min: 56px;  /* collapsed: 54 + 2px rule */
  }
}

@media (min-width: 1280px) {
  :root { --t-nav: 14px; }
}


/* 3  Reset and base -------------------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  /* Keep a focused element clear of the sticky header when tabbing (§6.3). */
  scroll-padding-top: calc(var(--header-height-min) + var(--sp-4));
}

body {
  margin: 0;
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
}

img, svg { max-width: 100%; }
img { height: auto; border: 0; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--c-maroon);
  margin: 0;
}

p, ul, ol, dl { margin: 0; }

a { color: var(--c-red); }

/* Focus is never removed and never traded for hover (design §4, §6.3). */
:focus-visible {
  outline: var(--focus-width) solid var(--c-red);
  outline-offset: var(--focus-offset);
}
/* The deep footer is the only reversed field on the site, so it is the only
   place the ring changes colour. The drawer is --surface, i.e. light — a coral
   ring there would measure 2.6:1 and be worse than the red. */
.site-footer :focus-visible { outline-color: var(--on-deep-link); }

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

.skip-link {
  position: absolute;
  left: var(--sp-4);
  top: var(--sp-4);
  z-index: 100;
  transform: translateY(-200%);
  background: var(--c-red);
  color: #fff;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--t-button);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  padding: var(--sp-4) var(--sp-6);
  min-height: var(--tap-min);
}
.skip-link:focus { transform: translateY(0); }

.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }


/* 4  Typography ------------------------------------------------------------ */

.page-header__title { font-size: var(--t-page-h1); line-height: var(--lh-page-h1); }
h2, .section-heading { font-size: var(--t-h2); line-height: var(--lh-h2); }
h3 { font-size: var(--t-h3); line-height: var(--lh-h3); }

.page-header__title,
.hero__headline { letter-spacing: 0; }

@media (min-width: 1024px) {
  .page-header__title, .hero__headline { letter-spacing: -0.005em; }
}

.empty {
  font-size: var(--t-body);
  color: var(--ink-muted);
  margin: var(--sp-5) 0;
}


/* 5  Layout primitives ----------------------------------------------------- */

.site-main { display: block; }

.site-main > * ,
.site-header__inner,
.site-footer__inner {
  margin-inline: auto;
  padding-inline: var(--gutter);
  max-width: calc(var(--container) + (var(--gutter) * 2));
}

/* Full-bleed elements opt out of the container. */
.hero, .band {
  max-width: none;
  padding-inline: 0;
}

.band {
  background: var(--surface-band);
  padding-block: var(--sp-8);
  margin-block: var(--sp-8);
}
.band > * {
  margin-inline: auto;
  padding-inline: var(--gutter);
  max-width: calc(var(--container) + (var(--gutter) * 2));
}

@media (min-width: 1200px) {
  .band { padding-block: var(--sp-9); margin-block: var(--sp-9); }
}

/* The section marker — the one decorative element in the system (design §4.3),
   and the group rule (§4.8). Not a border on a heading: a rule of its own so
   the spacing above and below it is controllable. */
.rule {
  width: 40px;
  height: var(--border-width-accent);
  background: var(--c-red);
  margin: var(--sp-4) 0;
}
@media (min-width: 600px) { .rule { width: 56px; } }
.rule--short { width: 40px; }
.rule--hair {
  width: 24px;
  height: 1px;
  background: var(--border);
}

.section-heading { margin-bottom: 0; }

.section-more {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-5);
  margin-top: var(--sp-7);
}

.archive-note {
  font-size: var(--t-body-sm);
  color: var(--ink-muted);
  /* 2026-09-28: block margins only -- the shorthand zeroed the container's
     auto inline margins, pinning the note to the viewport's left edge. */
  margin-block: var(--sp-5) var(--sp-8);
}

/* An outbound marker that is not a font glyph: Proza Libre carries no arrow
   glyphs, so an inline SVG is the only way to keep it in the type colour and
   on the baseline at every size. */
/* The word space in front of this glyph is a &nbsp; in the markup, which is
   what stops it being widowed onto a line of its own — so it carries no left
   margin of its own. */
.ext {
  width: 0.85em;
  height: 0.85em;
  margin-left: 0;
  fill: var(--c-slate);
  vertical-align: baseline;
}


/* 6  Header, navigation, drawer -------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--surface);            /* opaque, always (design §4.1) */
  border-bottom: var(--border-width-accent) solid var(--c-maroon);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  min-height: calc(var(--header-height) - var(--border-width-accent));
}

/* -- lockup -- */
.lockup {
  display: flex;
  align-items: center;
  min-width: 0;              /* let the Welsh name wrap instead of overflowing */
  gap: var(--sp-4);
  text-decoration: none;
  color: inherit;
  padding-block: var(--sp-2);
}
.lockup__mark {
  flex: none;
  width: 36px;
  height: 36px;
  color: var(--c-maroon);
  transition: width var(--transition-slow), height var(--transition-slow);
}
.lockup__names { display: block; min-width: 0; }
.lockup__en {
  display: block;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 15px;
  line-height: 1.2;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--c-maroon);
}
.lockup__en--full { display: none; }
.lockup__cy {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  font-style: italic;
  font-size: var(--t-cy);
  line-height: 1.2;
  color: var(--ink-muted);
}

/* -- burger -- */
.burger {
  display: none;
  flex: none;
  align-items: center;
  gap: var(--sp-2);
  min-width: var(--tap-min);
  min-height: var(--tap-min);
  padding: var(--sp-2);
  background: none;
  border: 0;
  cursor: pointer;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--t-button);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--c-maroon);
}
.js .burger { display: inline-flex; }
.burger__bars,
.burger__bars::before,
.burger__bars::after {
  display: block;
  width: 22px;
  height: 2px;
  background: currentColor;
}
.burger__bars { position: relative; }
.burger__bars::before,
.burger__bars::after { content: ""; position: absolute; left: 0; }
.burger__bars::before { top: -6px; }
.burger__bars::after  { top: 6px; }

/* -- navigation, below 1080px --

   Without JavaScript the burger is not rendered and the nav is a plain
   stacked list under the header: everything stays reachable. With
   JavaScript it becomes the full-screen drawer Eleanor specified. */
.site-nav__head { display: none; }

.site-nav__list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.site-nav__item { position: relative; }

.site-nav__link,
.site-subnav__link {
  display: flex;
  align-items: center;
  min-height: 56px;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--t-nav);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
  border-bottom: var(--border-width) solid var(--border);
  border-left: 3px solid transparent;
  padding-inline: var(--sp-4);
  transition: color var(--transition), background-color var(--transition);
}
.site-subnav__link {
  min-height: 48px;
  font-size: 15px;
  color: var(--ink-muted);
  margin-left: var(--sp-6);
  padding-inline: var(--sp-4);
}
.site-nav__link:hover,
.site-subnav__link:hover,
.site-nav__link:focus-visible,
.site-subnav__link:focus-visible {
  background: var(--surface-band);
  color: var(--c-maroon);
  border-left-color: var(--c-red);
}
.site-subnav { list-style: none; margin: 0; padding: 0; }

/* The caret is a desktop affordance only — in the drawer the children are
   always visible, so there is nothing to expand (design §4.1, drawer). */
.site-nav__caret { display: none; }

.site-nav__foot {
  padding: var(--sp-5) var(--sp-4);
  color: var(--ink-muted);
  font-size: var(--t-body-sm);
}
.site-nav__foot p { margin-bottom: var(--sp-2); }

/* Drawer, JS only */
.js .site-nav {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: var(--surface);
  overflow-y: auto;
  transform: translateX(100%);
  visibility: hidden;
  /* Visibility is stepped, not eased. On CLOSE it is held until the slide has
     finished; on OPEN it flips immediately, so the drawer is genuinely visible
     the instant the class lands and can therefore take focus. A hidden element
     refuses focus, and the focus trap depends on focus being inside. */
  transition: transform var(--transition-slow), visibility 0s linear 240ms;
}
.js .site-nav.is-open {
  transform: translateX(0);
  visibility: visible;
  transition: transform var(--transition-slow), visibility 0s linear 0s;
}
.js .site-nav__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-4);
  border-bottom: var(--border-width) solid var(--border);
}
.site-nav__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-style: italic;
  color: var(--ink-muted);
}
.drawer-close {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: var(--tap-min);
  min-height: var(--tap-min);
  background: none;
  border: 0;
  cursor: pointer;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--t-button);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--c-maroon);
}
.drawer-close__x {
  position: relative;
  width: 22px;
  height: 22px;
}
.drawer-close__x::before,
.drawer-close__x::after {
  content: "";
  position: absolute;
  top: 10px; left: 0;
  width: 22px; height: 2px;
  background: currentColor;
}
.drawer-close__x::before { transform: rotate(45deg); }
.drawer-close__x::after  { transform: rotate(-45deg); }

body.drawer-open { overflow: hidden; }

/* -- navigation, 1080px and up: one row, seven items, flush right -- */
@media (min-width: 1080px) {
  .js .burger { display: none; }

  .js .site-nav,
  .site-nav {
    position: static;
    transform: none;
    visibility: visible;
    background: none;
    overflow: visible;
  }
  .site-nav__head, .site-nav__foot { display: none !important; }

  .site-nav__list {
    display: flex;
    align-items: center;
    gap: 20px;
  }

  .site-nav__link {
    min-height: var(--tap-min);
    border: 0;
    padding-inline: 0;
    position: relative;
    white-space: nowrap;
  }
  /* Hover/active underline sits 10px below the baseline and does not move the
     text — a pseudo-element, never a border on the link box. */
  .site-nav__link::after {
    content: "";
    position: absolute;
    left: 0; right: 0;
    bottom: calc(50% - 0.5em - 10px);
    height: var(--border-width-accent);
    background: var(--c-red);
    opacity: 0;
    transition: opacity var(--transition);
  }
  .site-nav__link:hover { color: var(--c-maroon); background: none; border-left-color: transparent; }
  .site-nav__link:hover::after { opacity: 1; }

  /* Current page. About also carries the marker when a child page is current,
     otherwise two of the seven pages show no location at all (design §4.1). */
  .page-home    .site-nav__link[data-page="home"],
  .page-news    .site-nav__link[data-page="news"],
  .page-event   .site-nav__link[data-page="events"],
  .page-events  .site-nav__link[data-page="events"],
  .page-about   .site-nav__link[data-page="about"],
  .page-officers .site-nav__link[data-page="about"],
  .page-documents .site-nav__link[data-page="about"],
  .page-clubs   .site-nav__link[data-page="clubs"],
  .page-links   .site-nav__link[data-page="links"],
  .page-contact .site-nav__link[data-page="contact"] { color: var(--c-maroon); }

  .page-home    .site-nav__link[data-page="home"]::after,
  .page-news    .site-nav__link[data-page="news"]::after,
  .page-event   .site-nav__link[data-page="events"]::after,
  .page-events  .site-nav__link[data-page="events"]::after,
  .page-about   .site-nav__link[data-page="about"]::after,
  .page-officers .site-nav__link[data-page="about"]::after,
  .page-documents .site-nav__link[data-page="about"]::after,
  .page-clubs   .site-nav__link[data-page="clubs"]::after,
  .page-links   .site-nav__link[data-page="links"]::after,
  .page-contact .site-nav__link[data-page="contact"]::after { opacity: 1; }

  /* About sub-menu */
  .site-nav__item--parent { display: flex; align-items: center; }
  .site-nav__caret {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    min-height: var(--tap-min);
    margin-left: var(--sp-2);
    padding: 0;
    background: none;
    border: 0;
    cursor: pointer;
    color: var(--c-maroon);
  }
  .site-nav__caret::before {
    content: "";
    width: 10px; height: 6px;
    background: currentColor;
    clip-path: polygon(0 0, 100% 0, 50% 100%);
  }

  .site-subnav {
    position: absolute;
    top: 100%;
    left: 0;
    min-width: 200px;
    background: var(--surface);
    border: var(--border-width) solid var(--border);
    border-top: var(--border-width-accent) solid var(--c-maroon);
    display: none;
  }
  .site-nav__item--parent:hover > .site-subnav,
  .site-nav__item--parent:focus-within > .site-subnav,
  .site-nav__caret[aria-expanded="true"] + .site-subnav { display: block; }

  .site-subnav__link {
    min-height: var(--tap-min);
    margin-left: 0;
    font-size: var(--t-nav);
    color: var(--ink);
    border-bottom: 0;
    padding-inline: var(--sp-5);
  }

  /* Lockup: full English name from 1280px, NWPA below it (design §4.1). */
  .lockup { gap: var(--sp-4); }
  .lockup__mark { width: 36px; height: 36px; }
  .lockup__cy { font-size: 13px; }

  .site-header__inner { gap: 40px; }
}

@media (min-width: 1280px) {
  .lockup__mark { width: 40px; height: 40px; }
  .lockup__en--full { display: block; }
  .lockup__en--short { display: none; }
  /* 2026-09-28: Welsh line set to the width of the English one above it
     (~383px), mostly by size and a little by tracking. Only here, where the
     full English name shows; the compact state hides this line anyway. */
  .lockup__cy { font-size: 22px; line-height: 1.1; letter-spacing: 0.075em; }
  .site-nav__list { gap: var(--sp-5); }
  .site-header__inner { gap: 56px; }
}

/* Collapsed header, past 120px of scroll. A reduction, not a restructure:
   the row was already one row, so only the lockup narrows. */
@media (min-width: 1080px) {
  .site-header {
    transition: none;
  }
  .site-header__inner { transition: min-height var(--transition-slow); }
  .site-header.is-scrolled .site-header__inner {
    min-height: calc(var(--header-height-min) - var(--border-width-accent));
  }
  .site-header.is-scrolled .lockup__mark { width: 32px; height: 32px; }
  .site-header.is-scrolled .lockup__cy { display: none; }
  .site-header.is-scrolled .lockup__en--full { display: none; }
  .site-header.is-scrolled .lockup__en--short { display: block; }
}


/* 7  Hero ------------------------------------------------------------------
   Measured against D Griff — Sunrise in Nant Peris (2400x1188), design §4.2.
   Type bottom-left; scrim rises from the bottom; the top 46% is untouched.   */

.hero {
  position: relative;
  overflow: hidden;
  background: var(--surface-deep);
  /* Round 4: the mobile hero grows to carry a two-line 30px headline and the
     button, with the standfirst moved out below it. */
  height: clamp(540px, 66vh, 620px);
}

.hero__media { position: absolute; inset: 0; }

.hero__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Mobile crop window x 23.3-62.0% (design §4.2b). The crop is on width
     only — the full height of the frame is kept at every breakpoint. */
  object-position: 38% center;
}

.hero__scrim {
  position: absolute;
  inset: 0;
  /* Round 4. DG saw the ONSET, not the depth: round 3 moved alpha 0 to 0.55
     inside 14 per cent of hero height, which measures 1.05-1.32 sRGB levels
     per pixel over ground at V 168-222, and reads as a contour.

     This starts at the frame's top edge at alpha zero with zero slope, so
     there is no interior line whose beginning can be seen, then rises on
     a = 0.20 x (y / 0.80) ^ 1.5 to a 0.20 plateau at four-fifths height.
     Curve shape and plateau point are Eleanor's round 5; the plateau depth is
     DG's call (2026-08-06) — he wants the photograph, not the insurance.

     ONE gradient, not a stack: a stack reintroduces the slope discontinuity
     this exists to remove. Stops spaced by EQUAL ALPHA rather than
     equal distance, so they crowd where the curve bends hardest — a browser
     interpolates linearly between whatever stops it is given, and four stops
     would reproduce the round-3 problem in miniature at each joint.
     Regenerated from the round-5 curve, not edited from round 4's. */
  background: linear-gradient(
    to bottom,
    rgba(31, 29, 27, 0.000) 0.00%,
    rgba(31, 29, 27, 0.003) 5.00%,
    rgba(31, 29, 27, 0.009) 10.00%,
    rgba(31, 29, 27, 0.011) 11.65%,
    rgba(31, 29, 27, 0.016) 15.00%,
    rgba(31, 29, 27, 0.022) 18.49%,
    rgba(31, 29, 27, 0.025) 20.00%,
    rgba(31, 29, 27, 0.033) 24.23%,
    rgba(31, 29, 27, 0.035) 25.00%,
    rgba(31, 29, 27, 0.044) 29.35%,
    rgba(31, 29, 27, 0.046) 30.00%,
    rgba(31, 29, 27, 0.056) 34.06%,
    rgba(31, 29, 27, 0.058) 35.00%,
    rgba(31, 29, 27, 0.067) 38.46%,
    rgba(31, 29, 27, 0.071) 40.00%,
    rgba(31, 29, 27, 0.078) 42.62%,
    rgba(31, 29, 27, 0.084) 45.00%,
    rgba(31, 29, 27, 0.089) 46.59%,
    rgba(31, 29, 27, 0.099) 50.00%,
    rgba(31, 29, 27, 0.100) 50.40%,
    rgba(31, 29, 27, 0.111) 54.06%,
    rgba(31, 29, 27, 0.114) 55.00%,
    rgba(31, 29, 27, 0.122) 57.61%,
    rgba(31, 29, 27, 0.130) 60.00%,
    rgba(31, 29, 27, 0.133) 61.05%,
    rgba(31, 29, 27, 0.144) 64.40%,
    rgba(31, 29, 27, 0.146) 65.00%,
    rgba(31, 29, 27, 0.156) 67.66%,
    rgba(31, 29, 27, 0.164) 70.00%,
    rgba(31, 29, 27, 0.167) 70.84%,
    rgba(31, 29, 27, 0.178) 73.96%,
    rgba(31, 29, 27, 0.182) 75.00%,
    rgba(31, 29, 27, 0.189) 77.01%,
    rgba(31, 29, 27, 0.200) 80.00%,
    rgba(31, 29, 27, 0.200) 100%
  );



}

.hero__inner {
  position: absolute;
  inset: 0;
  margin-inline: auto;
  padding-inline: var(--gutter);
  max-width: calc(var(--container) + (var(--gutter) * 2));
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding-bottom: var(--sp-6);
}

.hero__headline {
  color: #fff;
  font-size: var(--t-hero-h1);
  line-height: var(--lh-hero-h1);
  max-width: 328px;                 /* wraps "North Wales Photographic / Association" */
  text-wrap: balance;
}

/* The standfirst is not over the photograph at mobile — §4.2c. */
.hero__standfirst { display: none; }

.hero__lead { margin-top: var(--sp-3); }
.hero__actions .btn { width: 100%; }

.hero__credit {
  margin-top: var(--sp-3);
  text-align: right;
  font-size: var(--t-credit);
  letter-spacing: 0.02em;
  color: #FFFFFF;                   /* solid, not 82% — round 4, §4.2e */
}

/* Mobile hero foot block: the standfirst, off the picture, on --surface where
   its contrast is 6.85:1 by hex value rather than by measurement. */
.hero-foot {
  background: var(--surface);
  padding: var(--sp-5) var(--gutter);
}
.hero-foot__standfirst {
  font-size: 16px;
  line-height: 1.60;
  color: var(--ink-muted);
  max-width: var(--measure-narrow);
}

@media (min-width: 600px) {
  .hero { height: max(62vh, 460px); }
  .hero__img { object-position: 42% center; }
  .hero__inner { padding-bottom: var(--sp-7); }
  .hero__headline { max-width: 480px; }

  .hero-foot { display: none; }
  .hero__standfirst {
    display: block;
    font-size: 16px;
    line-height: 1.60;
    color: #FFFFFF;
    max-width: 600px;
    margin: 0;
  }
  /* Round 5, at DG's instruction: the CTA moves BELOW the standfirst and left-
     aligns with the text. Round 4 put it beside to save 76px of block height;
     that saving is now deliberately spent, and §4.2d prices what it bought. */
  .hero__lead { margin-top: var(--sp-4); }
  .hero__actions { margin-top: var(--sp-5); }
  .hero__actions .btn { width: auto; min-width: 160px; }

  /* The button's lower border and the credit's descender line share one edge,
     the hero's bottom padding. align-items: end puts both boxes' bottoms on
     it; the 13px credit's baseline then sits ~3px above the button's border,
     which is what §4.2c means by aligning the bottoms and not the baselines. */
  .hero__inner {
    display: grid;
    grid-template-columns: minmax(0, auto) 1fr;
    align-content: end;
    align-items: end;
    column-gap: var(--sp-8);
  }
  .hero__credit { margin-top: 0; align-self: end; justify-self: end; }
}

@media (min-width: 1080px) {
  /* The whole 2:1 frame, uncropped. */
  .hero { height: clamp(520px, 50vw, 720px); }
  .hero__img { object-position: center center; }
  .hero__inner { padding-bottom: 56px; }
  .hero__headline { max-width: var(--measure-hero); }
  .hero__standfirst { max-width: 560px; }
}

/* Parallax, >=1080px only, and only when motion is welcome.
   Rest position: image top flush with the hero top, 80px of overshoot, so a
   64px upward travel can never open a gap (design §6.1). The scrim, the copy
   and the credit do not move — only the photograph slides beneath them. */
@media (min-width: 1080px) {
  .js.parallax-on .hero__img {
    height: calc(100% + 80px);
    will-change: transform;
  }
}


/* 8  Page header (interior pages) — design §4.3 ---------------------------- */

.page-header {
  padding-top: var(--sp-7);
  padding-bottom: var(--sp-6);
}
.page-header__eyebrow {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--t-eyebrow);
  line-height: 1.3;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--c-slate);
  margin-bottom: var(--sp-3);
}
.page-header__date, .page-header__kind { letter-spacing: 0.02em; }
.page-header__sep { margin-inline: 0.4em; }

.page-header__standfirst {
  font-size: var(--t-lead);
  line-height: var(--lh-lead);
  color: var(--ink-muted);
  max-width: var(--measure-narrow);
}
.page-header__standfirst p { margin-bottom: var(--sp-4); }
.page-header__standfirst p:last-child { margin-bottom: 0; }

@media (min-width: 1024px) {
  .page-header { padding-top: var(--sp-9); padding-bottom: var(--sp-8); }
}


/* 9  Cards — design §4.4 ---------------------------------------------------
   One component, two layout variants. The whole card is one link.            */

.card-grid {
  display: grid;
  /* Round 4: column gutter 32 -> 48px, DG's "+50%". Row gap unchanged. */
  gap: var(--sp-8) var(--sp-7);
  margin-top: var(--sp-6);
}
@media (min-width: 600px) { .card-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px) { .card-grid { grid-template-columns: repeat(3, 1fr); } }

/* Design §4.4: a mixed row of thumbed and un-thumbed cards aligns on the
   KICKER baseline, not the top of the card — and an un-thumbed card still
   shows no placeholder, no grey box, no icon. Both at once means the
   thumbnail must be a row track SHARED across the row, which the un-thumbed
   card simply leaves empty. Subgrid carries the track down through the card
   and its link wrapper. Where subgrid is unsupported the cards top-align,
   which is the previous behaviour — a degradation, not a break. */
@media (min-width: 600px) {
  .card-grid { grid-template-rows: auto auto; }
  .card-grid .card,
  .card-grid .card__link {
    grid-row: span 2;
    display: grid;
    grid-template-rows: subgrid;
    /* A subgrid inherits the parent's row-gap BETWEEN its tracks, so the 64px
       that separates one row of cards from the next was also opening up INSIDE
       every card, between the thumbnail and the kicker — 80px against §4.4's
       intended 16px. That was a defect in my subgrid work, not a design value.
       Zeroed here, so the intra-card gap is the media's margin alone and is the
       same at every breakpoint; --sp-8 goes on doing its real job between rows
       of cards. */
    row-gap: 0;
  }
  /* The body must sit in the second track even when there is no media. */
  .card-grid .card__body { grid-row: 2; }
}
/* Homepage panel (DG, 2026-09-28): 1-3 items keep the grid above. At four
   (the generator's maximum) all four show: stacked on phones, 2x2 from 600px
   to 1199px, four narrower columns from 1200px. */
@media (min-width: 900px) and (max-width: 1199px) {
  .card-grid--4 { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1200px) {
  .card-grid--4 { grid-template-columns: repeat(4, 1fr); }
}

.card-list { display: block; }

.card__link {
  display: block;
  text-decoration: none;
  color: inherit;
}

/* Thumbnail to kicker — 20px, DG's figure, chosen on the render after the
   80px he first saw turned out to be a subgrid defect rather than a design
   value. Applies to the vertical card variant at every breakpoint and on both
   index pages; §4.4 documents no mobile variation. The horizontal variant at
   >=900px sets this to 0 and uses its flex column gap instead. */
.card__media { display: block; margin-bottom: var(--card-media-gap); }
.card-grid .card__media { flex: none; }
.card__img {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 2;      /* fixed, so a mixed set never breaks the grid */
  object-fit: cover;
  border-radius: var(--radius-img);
  border: var(--border-width) solid var(--border-strong);
  transition: filter var(--transition);
}

.card__body { display: block; }

.card__kicker {
  display: block;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--t-meta);
  line-height: 1.4;
  letter-spacing: 0.02em;
  color: var(--c-slate);
}
.card__sep { margin-inline: 0.35em; }

.card__title {
  display: block;
  margin: var(--sp-2) 0 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--t-card-title);
  line-height: var(--lh-card-title);
  color: var(--ink);
  transition: color var(--transition);
}

.card__teaser {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  margin-top: var(--sp-3);
  font-size: var(--t-body-sm);
  line-height: var(--lh-body-sm);
  color: var(--ink-muted);
}
@media (min-width: 1024px) { .card__teaser { -webkit-line-clamp: 3; } }

.card__venue,
.card__note {
  display: block;
  margin-top: var(--sp-2);
  font-size: var(--t-meta);
  color: var(--ink-muted);
}

/* States. Nothing moves, lifts, scales or gains a shadow. */
.card__link:hover .card__title { color: var(--c-maroon); }
.card__link:hover .card__img { filter: brightness(1.04); }
.card__link:active .card__title { color: var(--c-red-hover); }

/* Horizontal variant on index pages, >=900px (design §4.4, §5.2). */
@media (min-width: 900px) {
  .card-list .card__link {
    display: flex;
    align-items: flex-start;
    gap: var(--sp-6);
  }
  /* No thumbnail: the text column runs full width. The row does not indent to
     a phantom thumbnail (design §4.4). Flex gives that for free — no :has(). */
  .card-list .card__media {
    flex: 0 0 200px;
    margin-bottom: 0;
  }
  .card-list .card__body {
    flex: 1 1 auto;
    min-width: 0;
    max-width: var(--measure-narrow);
  }
}
@media (min-width: 600px) and (max-width: 899px) {
  .card-list .card__media { max-width: 320px; }
}

/* Vertical stacking below 900px on index pages */
.card-list .card { padding-block: var(--sp-6); border-bottom: var(--border-width) solid var(--border); }
.card-list .card:last-child { border-bottom: 0; }

.month-group + .month-group { margin-top: var(--sp-8); }
.month-group { margin-top: var(--sp-8); }


/* 10  Rows — documents, newsletters, clubs, links (design §4.5, §4.7-4.9) --- */

.rows { display: block; margin-top: var(--sp-5); }

.row { border-bottom: var(--border-width) solid var(--border); }
.rows > .row:last-child { border-bottom: 0; }

.row__link-whole,
.row--club > .row__main {
  text-decoration: none;
  color: inherit;
}

.row__link-whole {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  min-height: 72px;
  padding-block: var(--sp-4);
  transition: background-color var(--transition);
}
.row__link-whole:hover { background: var(--surface-band); }
.row__link-whole:hover .row__title { color: var(--c-maroon); }
.row__link-whole:active .row__title { color: var(--c-red-hover); }

.row__main { flex: 1 1 auto; min-width: 0; }
.row__aside { flex: none; text-align: right; }

.row__title {
  display: block;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--t-body);
  color: var(--ink);
  transition: color var(--transition);
}
.row__sub,
.row__meta {
  display: block;
  margin-top: var(--sp-1);
  font-size: var(--t-meta);
  color: var(--ink-muted);
}

/* A drawn document mark, not an icon set: a rectangle with a folded corner
   and the letters PDF (design §4.5). */
.doc-glyph {
  flex: none;
  position: relative;
  display: block;
  width: 32px;
  height: 40px;
  color: var(--c-slate);
  transition: color var(--transition);
}
.doc-glyph svg { display: block; width: 32px; height: 40px; }
.doc-glyph__label {
  position: absolute;
  left: 0; right: 0; bottom: 7px;
  text-align: center;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 9px;
  letter-spacing: 0.06em;
  color: currentColor;
}
.row__link-whole:hover .doc-glyph { color: var(--c-maroon); }

.doc-group { margin-top: var(--sp-8); }

/* Only Insurance collapses. Every group ships the same markup with <details
   open>; CSS hides the control everywhere it is not wanted and site.js closes
   Insurance alone, so a no-JS reader sees all four groups expanded. */
.doc-reveal > summary { list-style: none; }
.doc-reveal > summary::-webkit-details-marker { display: none; }
.doc-reveal__summary {
  display: none;
  align-items: center;
  min-height: var(--tap-min);
  margin-bottom: var(--sp-3);
  cursor: pointer;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--t-button);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--c-red);
}
.doc-group--insurance .doc-reveal__summary { display: flex; }
.doc-reveal__summary:hover { color: var(--c-red-hover); text-decoration: underline; }
.doc-reveal__hide { display: none; }
.doc-reveal[open] > .doc-reveal__summary .doc-reveal__show { display: none; }
.doc-reveal[open] > .doc-reveal__summary .doc-reveal__hide { display: inline; }
.doc-group__note {
  margin-top: var(--sp-4);
  font-size: var(--t-body-sm);
  color: var(--ink-muted);
  max-width: var(--measure-narrow);
}

/* Club rows: only the website link is clickable; the row leads nowhere. */
.row--club { padding-block: var(--sp-5); }
.row--club { display: block; }
/* A full club URL is a single unbreakable token up to ~55 characters, which
   overflows a 320px screen. It must be allowed to break until the generator
   can supply a bare domain (design §4.7). The glyph leads the address rather
   than trailing it, so nothing can be widowed by the wrap. */
.row__link a {
  color: var(--c-red);
  font-weight: 600;
  font-size: 15px;
  overflow-wrap: anywhere;
}
.row__link .ext { margin-right: 0.35em; }

@media (min-width: 600px) {
  .row--club {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-5);
    min-height: 72px;
  }
}

.reveal { margin-top: var(--sp-8); }
.reveal__summary {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-min);
  cursor: pointer;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--t-button);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--c-red);
}
.reveal__summary:hover { color: var(--c-red-hover); text-decoration: underline; }
.reveal__body { margin-top: var(--sp-5); }


/* 11  Officers — design §4.6 -----------------------------------------------
   No card, no border, no background. Space separates them.                   */

.officer-grid {
  display: grid;
  gap: var(--sp-8) var(--sp-6);
  margin-top: var(--sp-6);
}
@media (min-width: 600px)  { .officer-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1200px) { .officer-grid { grid-template-columns: repeat(3, 1fr); } }

.officer__role {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--t-eyebrow);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--c-slate);
}
.officer__name {
  margin-top: var(--sp-2);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--t-card-title);
  line-height: var(--lh-card-title);
  color: var(--ink);
}
.officer__club {
  margin-top: var(--sp-3);
  font-size: var(--t-body-sm);
  color: var(--ink-muted);
  max-width: 40ch;
}
.officer .rule--hair { margin: var(--sp-4) 0 var(--sp-3); }
.officer__contact a {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 15px;
  color: var(--c-red);
  text-decoration: none;
}
.officer__contact a:hover { color: var(--c-red-hover); text-decoration: underline; }


/* 12  Buttons and links — design §4.10 -------------------------------------
   Four kinds specified; the ghost is unused at launch and is not written.    */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-width: 160px;
  min-height: 52px;
  padding: var(--sp-4) var(--sp-6);
  border: 0;
  border-radius: var(--radius);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--t-button);
  /* The body's 1.65 line-height was making a 52px button 57px tall (§4.10). */
  line-height: 1.2;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--transition), color var(--transition);
}
.btn--primary { background: var(--c-red); color: #fff; }
.btn--primary:hover { background: var(--c-red-hover); }
.btn--primary:active { background: var(--c-red-hover); transform: translateY(1px); }

.btn--secondary {
  background: transparent;
  color: var(--c-maroon);
  box-shadow: inset 0 0 0 var(--border-width-accent) var(--c-maroon);
}
.btn--secondary:hover { background: var(--c-maroon); color: #fff; }

/* Reversed primary — the deep field only. --c-red measures 2.21:1 against
   --surface-deep, so a red button there has no discernible edge and fails
   1.4.11 as a control. This passes as text AND as a control at 6.77:1. */
/* Reversed primary (design §4.10). Scoped to .site-footer THROUGHOUT, because
   `.site-footer a` is (0,2,0) and was winning the label colour off an
   unscoped `.btn--reversed` — which put --on-deep on the coral at 1.56:1.
   Every state below is footer-scoped for that reason; do not unscope one. */
.site-footer .btn--reversed {
  background: var(--on-deep-link);
  color: var(--surface-deep);
  min-width: 220px;
  text-decoration: none;
}
/* Hover is a white ground with the label unchanged — 14.6:1. The footer's
   link rules add an underline and recolour on hover; both are refused here. */
.site-footer .btn--reversed:hover {
  background: #FFFFFF;
  color: var(--surface-deep);
  text-decoration: none;
}
.site-footer .btn--reversed:active {
  background: var(--on-deep-link);
  color: var(--surface-deep);
  transform: translateY(1px);
}
/* The standard --on-deep-link ring is invisible against a button of the same
   colour, so this one takes a white ring. */
.site-footer .btn--reversed:focus-visible { outline-color: #FFFFFF; }

@media (max-width: 479px) { .btn { width: 100%; } }

/* Tertiary — in-flow links, "view all", back-links. The chevron sits outside
   the label and does not animate. */
.link-more,
.link-back {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--tap-min);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--t-button);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--c-red);
  transition: color var(--transition);
}
.link-more:hover,
.link-back:hover { color: var(--c-red-hover); text-decoration: underline; }

.item__back { margin-block: var(--sp-8); }


/* 13  Prose — design §4.12 ------------------------------------------------- */

.prose {
  max-width: var(--container-prose);
  font-size: var(--t-body);
  line-height: var(--lh-body);
}
.prose > * + * { margin-top: var(--sp-5); }
.prose h2 { margin-top: var(--sp-7); }
.prose h3 { margin-top: var(--sp-6); }
.prose h2 + *, .prose h3 + * { margin-top: var(--sp-4); }
.prose ul, .prose ol { padding-left: var(--sp-5); }
.prose li + li { margin-top: var(--sp-3); }

.prose a {
  color: var(--c-red);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}
.prose a:hover {
  color: var(--c-red-hover);
  text-decoration-thickness: 2px;
}

@media (min-width: 1024px) {
  .prose h2 { margin-top: var(--sp-8); }
}

.prose-cta { margin-block: var(--sp-7); }

/* prose.html serves both About and Contact, so the two page-specific blocks
   below it are gated on the body class rather than on a template branch. */
.page-about   .page-contact-only,
.page-contact .page-about-only { display: none; }

.figure { margin: var(--sp-7) 0; }
.figure__img {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border-radius: var(--radius-img);
  border: var(--border-width) solid var(--border-strong);
}
.figure__credit {
  margin-top: var(--sp-2);
  font-size: var(--t-credit);
  letter-spacing: 0.02em;
  color: var(--ink-muted);
}

.item__body { margin-top: var(--sp-7); }

/* 2026-09-28: side image (image_layout: side). A grid, not a float: text in
   the left column at its normal measure, the image in its own right-hand
   column of about a third, never wrapped round. Below 768px it stacks, image
   first (source order). */
.item__split { margin-top: var(--sp-7); }
.item__split .item__body { margin-top: 0; }
.figure--side { margin: 0 0 var(--sp-6); }
@media (min-width: 768px) {
  .item__split {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    column-gap: var(--sp-7);
    align-items: start;
  }
  .item__split .item__body { grid-column: 1; grid-row: 1; }
  .figure--side { grid-column: 2; grid-row: 1; margin: 0.35em 0 0; }
}

.meta-box {
  margin-top: var(--sp-8);
  max-width: var(--container-prose);
  background: var(--surface-band);
  border-left: 3px solid var(--c-slate);
  padding: var(--sp-5);
}
.meta-box__heading { font-size: var(--t-h3); }
.meta-box__list { margin-top: var(--sp-4); }
.meta-box__row { display: block; }
.meta-box__row + .meta-box__row { margin-top: var(--sp-3); }
.meta-box dt {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--t-meta);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--c-slate);
}
.meta-box dd { margin: var(--sp-1) 0 0; font-size: var(--t-body); }

/* Homepage intro — design §5.1: prose in seven columns, the benefits list in
   five, at desktop.

   INTRO and BENEFITS are separate values, so each column is a SINGLE grid item
   containing its own normal flow. The two columns therefore share no row
   tracks and neither can strand the other — which is what went wrong when one
   block of markup had to be split by element type. */
.home-intro { margin-block: var(--sp-8); }

.home-intro__prose > * + * { margin-top: var(--sp-5); }
.home-intro__prose > p { max-width: var(--measure); }
/* The standfirst that left the hero (§4.2c). */
.home-intro__prose > p:first-child {
  font-size: var(--t-lead);
  line-height: var(--lh-lead);
  color: var(--ink-muted);
  max-width: var(--measure-narrow);
}

/* Round 4 separation: 48px stacked below 600, 64px stacked 600-1199,
   96px horizontal at 1200+. DG: "a big fan of plenty of white space." */
.home-benefits { margin-top: var(--sp-7); }
@media (min-width: 600px) { .home-benefits { margin-top: var(--sp-8); } }
.home-benefits h2 { font-size: var(--t-h2); line-height: var(--lh-h2); }
.home-benefits ul {
  list-style: none;
  margin-top: var(--sp-5);
  padding-left: 0;
}
.home-benefits li + li { margin-top: var(--sp-5); }
/* The marker is a 12 x 2px rule, not a bullet and not an icon (design §5.5). */
.home-benefits li::before {
  content: "";
  display: block;
  width: 12px;
  height: 2px;
  background: var(--c-red);
  margin-bottom: var(--sp-3);
}
/* Lead phrase over its explanation, so the list can be scanned by label alone. */
.home-benefits li strong {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 20px;
  line-height: 1.3;
  color: var(--ink);
  margin-bottom: var(--sp-1);
}
.home-benefits li {
  font-size: var(--t-body-sm);
  line-height: var(--lh-body-sm);
  color: var(--ink-muted);
}

/* Design §5.1 puts the intro prose in seven columns and the benefits list in
   five at desktop. That layout has been withdrawn, and the reason is worth
   recording because it is not a preference.

   The generator supplies the whole block as ONE value, so both columns are
   siblings in a single grid and therefore SHARE ROW TRACKS. The paragraphs and
   the list have unequal child counts (5 and 2 here), so whatever is pinned
   into the short column either strands itself on a later row — the ~230px
   void Ada measured — or, once pinned adjacent, grows a shared row and opens
   the same void in the other column instead. Spanning the surplus rows trades
   it for ~1.2m of row-gap. There is no arrangement of a single grid that
   avoids all three: two independent columns need two containers.

   Restoring it is one placeholder — a BENEFITS value separate from INTRO —
   and nothing else moves. Raised with Ada; single column until then, which is
   correct at every width and for any shape of copy DG writes. */
@media (min-width: 1200px) {
  .home-intro { margin-block: var(--sp-9); }
  /* Two tracks in 7:5 proportion with a REAL 96px gap between them — not
     twelve columns whose seventh gap happens to be wider, which would set the
     internal column rhythm fighting the division (Eleanor's note, §5.1). */
  .home-intro__inner {
    display: grid;
    grid-template-columns: 7fr 5fr;
    column-gap: var(--sp-9);
    align-items: start;
  }
  .home-intro__prose { grid-column: 1; grid-row: 1; }
  .home-benefits     { grid-column: 2; grid-row: 1; margin-top: 0; }
}


/* 14  Footer — design §4.11 ------------------------------------------------
   The full-bleed photograph band is specified but not built: the image
   library holds no second file above 1385px wide, and the generator supplies
   no footer-image value. Both raised with Ada.                               */

.site-footer {
  background: var(--surface-deep);
  color: var(--on-deep);
  margin-top: var(--sp-9);
  font-size: var(--t-footer);
}
/* A full-bleed band that ends the page meets the footer directly: two blocks
   of colour with a stripe of body background between them reads as a fault
   rather than as breathing room. The negative margin cancels the footer's own
   top margin exactly, through the usual collapse, so every other page keeps
   its --sp-9 of air. Hanging the space off the last section instead does not
   work: a page whose last child is display:none (prose.html emits one) would
   put its spacing on a box that is not there. */
.site-main > .band:last-child { margin-bottom: calc(-1 * var(--sp-9)); }
/* Padding belongs to the field, not the footer: the photographic band is a
   sibling of the field and runs full bleed to the bottom of the page. */
.site-footer__inner { padding-block: var(--sp-8); }
@media (min-width: 1024px) { .site-footer__inner { padding-block: var(--sp-9); } }

.site-footer a {
  color: var(--on-deep);
  text-decoration: none;
}
.site-footer a:hover { color: var(--on-deep-link); text-decoration: underline; }

/* Three blocks: identity, navigation, archive. No divider, no bottom line —
   both withdrawn in round 4; the bottom line's contents are on the band. */
.footer-columns { display: grid; gap: var(--sp-8); }
@media (min-width: 600px) and (max-width: 899px) {
  .footer-columns { grid-template-columns: 1fr 1fr; }
  .footer-identity { grid-column: 1 / -1; }
}
@media (min-width: 900px)  { .footer-columns { grid-template-columns: 4fr 4fr 4fr; gap: var(--sp-8); } }
@media (min-width: 1080px) { .footer-columns { gap: var(--sp-9); } }

.footer-identity__mark {
  display: block;
  width: 40px; height: 40px;
  /* 2026-09-28: white in the footer only, via fill on this <use> instance;
     the header mark is unaffected. */
  color: #fff;
  fill: currentColor;
  margin-bottom: var(--sp-4);
}
.footer-identity__en {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 16px;
}
.footer-identity__cy {
  font-family: var(--font-display);
  font-weight: 600;
  font-style: italic;
  /* 2026-09-28: sized (with a touch of tracking) to the width of the English
     line above it (~311px at 16px), same method as the header lockup. Fits the
     360px floor; wraps with the English line in narrow three-column widths. */
  font-size: 21px;
  line-height: 1.2;
  letter-spacing: 0.005em;
  color: var(--on-deep-muted);
}
.footer-identity__note {
  margin-top: var(--sp-3);
  font-size: 15px;
  color: var(--on-deep-muted);
}

.footer-heading {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--t-footer-head);
  line-height: 1.3;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--on-deep-muted);
  margin-bottom: var(--sp-4);
}

/* One list, folded into two sub-columns at >=900px — one heading over both. */
.footer-nav__list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.footer-nav__list a {
  display: flex;
  align-items: center;
  min-height: var(--tap-min);
  font-size: 16px;
}
@media (min-width: 900px) {
  /* 2026-09-28: CSS columns, not a fixed 4-row grid, so the split balances
     itself to the number of links (3 + 2 interim, 4 + 3 full site). */
  .footer-nav__list {
    columns: 2;
    column-gap: var(--sp-6);
  }
  .footer-nav__list li { break-inside: avoid; }
}

.footer-archive__text {
  font-size: 15px;
  line-height: 1.6;
  color: var(--on-deep-muted);
  max-width: 40ch;
  margin-bottom: var(--sp-5);
}

/* -- the photographic band (design §4.11d-g, round 4) --

   Heights are FIXED PIXELS, not vh: with object-fit: cover the crop window is
   a function of the box's aspect ratio, so a vh-driven band would re-crop the
   picture on every phone and every browser-chrome state. */
.footer-band {
  position: relative;
  height: 320px;            /* mobile */
  overflow: hidden;
}
.footer-band__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Mobile takes a dedicated 720x640 crop, so the framing is baked in. */
  object-position: center center;
}

/* Bottom-anchored in pixels. The shape is the INVERSE of the hero's and
   deliberately so: the hero eases in slowly from the top because its ramp
   crosses bright cloud; the band eases out slowly at the top because its ramp
   crosses mist that brightens as it rises. Flat where the picture is light,
   steep only in the last 40px above the plateau where the marram is already
   black. a = 0.66 x (1 - t) ^ 2.5. Nothing sits in the ramp — white there
   falls to 1.02:1 at mobile. */
.footer-band__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to top,
    rgba(31, 29, 27, 0.660) 0px,
    rgba(31, 29, 27, 0.660) 96px,
    rgba(31, 29, 27, 0.613) 100px,
    rgba(31, 29, 27, 0.566) 104px,
    rgba(31, 29, 27, 0.519) 108px,
    rgba(31, 29, 27, 0.471) 112px,
    rgba(31, 29, 27, 0.424) 117px,
    rgba(31, 29, 27, 0.377) 122px,
    rgba(31, 29, 27, 0.330) 127px,
    rgba(31, 29, 27, 0.283) 133px,
    rgba(31, 29, 27, 0.236) 139px,
    rgba(31, 29, 27, 0.189) 146px,
    rgba(31, 29, 27, 0.141) 155px,
    rgba(31, 29, 27, 0.094) 165px,
    rgba(31, 29, 27, 0.047) 179px,
    rgba(31, 29, 27, 0.000) 224px
  );
}

/* The three closing marks, all inside the 112px plateau, all solid white.
   Read left to right: who built it, who owns it, who took the photograph. */
.footer-band__strip {
  position: absolute;
  left: 0; right: 0;
  bottom: var(--sp-5);
  margin-inline: auto;
  padding-inline: var(--gutter);
  max-width: calc(var(--container) + (var(--gutter) * 2));
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  row-gap: var(--sp-2);
  color: #FFFFFF;
}

.footer-dji {
  display: inline-block;
  opacity: 0.70;                       /* round 4: was 0.35 on the flat field */
  transition: opacity 150ms ease-out, transform 150ms ease-out;
}
.footer-dji:hover,
.footer-dji:focus-visible { opacity: 1; transform: translateY(-1px); }
.footer-dji img {
  display: block;
  width: 84px;
  height: auto;
  /* The raster is a baked mid-grey (#808080) on transparency and cannot take
     currentColor the way a vector would. This flattens it to white; the
     opacity above does the rest. Delete when the vector lands. */
  filter: brightness(0) invert(1);
}

.footer-copyright {
  font-size: 14px;
  text-align: right;
}
.footer-copyright--long { display: none; }

.footer-band__credit {
  grid-column: 1 / -1;
  text-align: right;
  font-size: var(--t-credit);
  letter-spacing: 0.02em;
}

@media (min-width: 600px) {
  .footer-band { height: 340px; }                       /* tablet, round 4 */
  .footer-band__img { object-position: center 78%; }
  .footer-band__scrim {
    background: linear-gradient(
      to top,
      rgba(31, 29, 27, 0.660) 0px,
    rgba(31, 29, 27, 0.660) 112px,
    rgba(31, 29, 27, 0.613) 117px,
    rgba(31, 29, 27, 0.566) 122px,
    rgba(31, 29, 27, 0.519) 127px,
    rgba(31, 29, 27, 0.471) 132px,
    rgba(31, 29, 27, 0.424) 138px,
    rgba(31, 29, 27, 0.377) 144px,
    rgba(31, 29, 27, 0.330) 151px,
    rgba(31, 29, 27, 0.283) 158px,
    rgba(31, 29, 27, 0.236) 166px,
    rgba(31, 29, 27, 0.189) 175px,
    rgba(31, 29, 27, 0.141) 186px,
    rgba(31, 29, 27, 0.094) 199px,
    rgba(31, 29, 27, 0.047) 216px,
    rgba(31, 29, 27, 0.000) 272px
    );
  }
  .footer-band__strip {
    bottom: var(--sp-6);
    grid-template-columns: auto auto 1fr;
    column-gap: var(--sp-6);
    row-gap: 0;
  }
  .footer-dji img { width: 96px; }
  .footer-copyright { text-align: left; }
  .footer-band__credit { grid-column: auto; }
}

@media (min-width: 900px) {
  .footer-band { height: 420px; }                       /* desktop */
  .footer-band__strip { column-gap: var(--sp-7); }
  .footer-copyright--long { display: block; }
  .footer-copyright--short { display: none; }
}

/* 15  Reduced motion -------------------------------------------------------
   Parallax is off — not reduced, off — at every width. The static hero is the
   primary rendering and shows the whole photograph uncropped (design §6.1).  */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .js .site-nav {
    transition: opacity 100ms linear, visibility 0s linear 100ms;
    transform: none;
    opacity: 0;
  }
  .js .site-nav.is-open {
    opacity: 1;
    transition: opacity 100ms linear, visibility 0s linear 0s;
  }
  .js.parallax-on .hero__img { height: 100%; transform: none !important; }
  .footer-dji a:hover,
  .footer-dji a:focus-visible { transform: none; }
}


/* 16  Print — Officers, Documents and Contact (spec §8a, §8c) --------------- */

@media print {
  .site-header, .site-footer, .footer-band, .hero-foot, .skip-link, .hero, .sprite,
  .section-more, .archive-note, .link-more, .link-back { display: none !important; }

  body { background: #fff; color: #000; font-size: 11pt; line-height: 1.4; }
  h1, h2, h3 { color: #000; }
  .rule { background: #000; }

  a { color: #000; text-decoration: none; }
  .row__link-whole { min-height: 0; }

  .officer-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12pt 18pt; }

  /* The page's own address, so a printed sheet can be found again. */
  .site-main::after {
    content: "North Wales Photographic Association — nwpa.co.uk";
    display: block;
    margin-top: 18pt;
    padding-top: 6pt;
    border-top: 1pt solid #000;
    font-size: 9pt;
  }
}
