/* Greyton Conservation Society — components and layout.
   Built on assets/css/tokens.css. Every value comes from a token. */

/* ══ Layout primitives ═══════════════════════════════════════════════════ */
.wrap{width:100%;max-width:var(--width-content);margin-inline:auto;padding-inline:var(--gutter-page)}
.wrap--narrow{max-width:var(--width-narrow)}
/* Chrome — masthead, drawer and footer — runs near full-bleed so the wordmark,
   nav and footer columns sit close to the screen edges on wide displays.
   Reading content keeps the capped --width-content measure. */
.wrap--wide{max-width:none}
@media (min-width:900px){.wrap{padding-inline:var(--gutter-page-lg)}}
/* Content opens up on large displays so the page doesn't read as a narrow
   column under edge-to-edge chrome. Prose keeps its own 64ch measure, so
   line length for reading is unaffected by these steps. */
@media (min-width:1500px){:root{--width-content:1360px}}
@media (min-width:1900px){:root{--width-content:1520px}}

.section{padding-block:var(--section-y)}
.section--tight{padding-block:var(--section-y-tight)}
.section--sage{background:var(--surface-sage)}
.section--sunken{background:var(--surface-sunken)}
.section--brand{background:var(--surface-brand);color:var(--text-on-brand)}
.section--brand-deep{background:var(--surface-brand-deep);color:var(--text-on-brand)}
.section--brand h1,.section--brand h2,.section--brand h3,
.section--brand-deep h1,.section--brand-deep h2,.section--brand-deep h3{color:var(--text-on-brand)}

.stack{display:flex;flex-direction:column;gap:var(--space-6)}
.stack--lg{gap:var(--space-9)}
.grid{display:grid;gap:var(--space-8)}
@media (min-width:720px){
  .grid--2{grid-template-columns:repeat(2,1fr)}
  .grid--3{grid-template-columns:repeat(2,1fr)}
  .grid--4{grid-template-columns:repeat(2,1fr)}
}
@media (min-width:980px){
  .grid--3{grid-template-columns:repeat(3,1fr)}
  .grid--4{grid-template-columns:repeat(4,1fr)}
}

.skip-link{position:absolute;left:var(--space-6);top:calc(var(--space-6) * -6);z-index:100;
  background:var(--surface-card);color:var(--text-heading);border:none;border-radius:var(--radius-sm);
  padding:var(--space-5) var(--space-7);box-shadow:var(--shadow-md);font:var(--type-label);
  display:inline-flex;align-items:center;min-height:var(--hit-min);
  transition:top var(--dur-fast) var(--ease-out)}
.skip-link:focus{top:var(--space-6)}

/* ══ Type helpers ════════════════════════════════════════════════════════ */
.eyebrow{display:flex;align-items:center;gap:var(--space-5);
  font:var(--type-eyebrow);letter-spacing:var(--tracking-eyebrow);text-transform:uppercase;
  color:var(--text-muted);margin:0}
.eyebrow::before{content:"";width:18px;height:var(--border-thin);background:currentColor;flex:none}
.eyebrow--center{justify-content:center}
/* The three-word tagline must not break after a pipe — drop a step instead */
@media (max-width:520px){
  .eyebrow{font-size:var(--text-2xs);letter-spacing:var(--tracking-wide)}
  .eyebrow::before{width:12px}
}
.on-dark .eyebrow,.section--brand .eyebrow,.section--brand-deep .eyebrow{color:var(--kloof-300)}

.lede{font:var(--type-lede);color:var(--text-muted);max-width:var(--measure-prose)}
.section--brand .lede,.section--brand-deep .lede,.on-dark .lede{color:var(--kloof-200)}
.h1{font:var(--type-h1)}
.h2{font:var(--type-h2)}
.h3{font:var(--type-h3)}
.small{font:var(--type-small);color:var(--text-muted)}
.data{font:var(--type-data);letter-spacing:var(--tracking-normal)}
.muted{color:var(--text-muted)}

.prose{max-width:var(--measure-prose);display:flex;flex-direction:column;gap:var(--space-6)}
.prose h2{font:var(--type-h2);margin-top:var(--space-6)}
.prose h3{font:var(--type-h3);margin-top:var(--space-5)}
.prose ul,.prose ol{margin:0;padding-left:var(--space-8);display:flex;flex-direction:column;gap:var(--space-4)}
.prose li::marker{color:var(--kloof-400)}
.prose--lg{font-size:var(--text-md)}

.section-heading{display:flex;flex-direction:column;gap:var(--space-5);max-width:var(--width-narrow)}
.section-heading--center{align-items:center;text-align:center;margin-inline:auto}

/* ══ Rules ═══════════════════════════════════════════════════════════════ */
.rule{border:0;height:var(--border-thin);background:var(--border-hairline);margin:0}
.rule--lei{height:var(--rule-lei);background:var(--lei-300);width:56px}

/* ══ Buttons ═════════════════════════════════════════════════════════════ */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-4);
  min-height:var(--control-md);padding:0 var(--space-7);border-radius:var(--radius-sm);
  font:var(--type-label);letter-spacing:var(--tracking-eyebrow);text-transform:uppercase;
  border:var(--border-thin) solid transparent;cursor:pointer;white-space:nowrap;
  transition:var(--transition-control),transform var(--dur-instant) var(--ease-out)}
.btn:hover{border-bottom-color:transparent}
.btn:active{transform:translateY(1px)}
.btn--lg{min-height:var(--control-lg);padding-inline:var(--space-9)}
.btn--sm{min-height:var(--control-sm);padding-inline:var(--space-6)}

.btn--primary{background:var(--kloof-700);color:var(--stone-050);border-color:var(--kloof-700)}
.btn--primary:hover{background:var(--kloof-800);border-color:var(--kloof-800);color:var(--stone-050)}

/* Deep ochre, not the mid tone: at ochre-500 the fill sits only 2.79:1 against
   the cream page, under the 3:1 a control needs to read as a control. ochre-700
   gives 5.25:1 against paper and 5.53:1 for the white label. (White on ochre-500
   would have been 2.93:1 — the one combination to avoid.) */
.btn--accent{background:var(--ochre-700);color:var(--white);border-color:var(--ochre-700)}
.btn--accent:hover{background:color-mix(in oklab,var(--ochre-700) 86%,var(--ink-900));
  border-color:color-mix(in oklab,var(--ochre-700) 86%,var(--ink-900));color:var(--white)}

.btn--secondary{background:transparent;color:var(--kloof-700);border-color:var(--border-strong)}
.btn--secondary:hover{background:var(--kloof-050);border-color:var(--kloof-400);color:var(--kloof-800)}

.btn--ghost{background:transparent;color:var(--kloof-700);border-color:transparent}
.btn--ghost:hover{background:var(--kloof-050);color:var(--kloof-800)}

.btn--on-dark{background:transparent;color:var(--stone-050);border-color:var(--border-on-brand)}
.btn--on-dark:hover{background:rgba(251,249,243,.12);border-color:var(--stone-050);color:var(--stone-050)}

.btn .icon{width:18px;height:18px;flex:none;transition:transform var(--dur-fast) var(--ease-out)}
.btn:hover .icon--arrow{transform:translateX(3px)}

/* Inline text link with a nudging arrow */
.arrow-link{display:inline-flex;align-items:center;gap:var(--space-4);
  font:var(--type-label);letter-spacing:var(--tracking-eyebrow);text-transform:uppercase;
  color:var(--kloof-700);border-bottom:none}
.arrow-link .icon{width:18px;height:18px;transition:transform var(--dur-fast) var(--ease-out)}
/* These are the primary way into a card, but the text alone is only ~18px tall.
   Give them a proper target where the pointer is a fingertip. */
@media (pointer:coarse),(max-width:900px){
  .arrow-link{min-height:var(--hit-min);align-items:center}
}
.arrow-link:hover{color:var(--kloof-800)}
.arrow-link:hover .icon{transform:translateX(3px)}
/* .card--brand is a green card that can sit inside a light section, so it must
   flip the link colour on its own — without this the link renders kloof-700 on
   kloof-700 and is literally invisible. */
.on-dark .arrow-link,.section--brand .arrow-link,
.section--brand-deep .arrow-link,.card--brand .arrow-link{color:var(--kloof-200)}
.on-dark .arrow-link:hover,.section--brand .arrow-link:hover,
.card--brand .arrow-link:hover{color:var(--stone-050)}

/* ══ Icons ═══════════════════════════════════════════════════════════════ */
.icon{display:inline-block;width:20px;height:20px;stroke:currentColor;stroke-width:1.5;
  fill:none;stroke-linecap:round;stroke-linejoin:round;vertical-align:middle}
.icon-tile{width:40px;height:40px;border-radius:var(--radius-sm);display:grid;place-items:center;flex:none;
  background:color-mix(in oklab,var(--tone,var(--prog-nature)) 14%,transparent);color:var(--tone,var(--prog-nature))}
.icon-tile .icon{width:22px;height:22px}

/* ══ Tags & badges ═══════════════════════════════════════════════════════ */
/* align-self keeps the pill hugging its text inside a stretching flex column */
.tag{display:inline-flex;align-items:center;align-self:flex-start;gap:var(--space-3);
  padding:var(--space-3) var(--space-5);border-radius:var(--radius-pill);
  font:var(--type-label);letter-spacing:var(--tracking-wide);text-transform:uppercase;
  background:color-mix(in oklab,var(--tone,var(--prog-nature)) 12%,transparent);
  color:color-mix(in oklab,var(--tone,var(--prog-nature)) 78%,var(--ink-900));
  border:none;white-space:nowrap}
.tag--nature{--tone:var(--prog-nature)}
.tag--heritage{--tone:var(--prog-heritage)}
.tag--water{--tone:var(--prog-water)}
.tag--wildlife{--tone:var(--prog-wildlife)}
.tag--community{--tone:var(--prog-community)}

.badge{display:inline-flex;align-items:center;align-self:flex-start;padding:var(--space-2) var(--space-4);
  border-radius:var(--radius-xs);font:var(--type-label);text-transform:uppercase;
  letter-spacing:var(--tracking-wide)}
.badge--easy{background:var(--success-soft);color:var(--kloof-700)}
.badge--moderate{background:var(--warning-soft);color:var(--ochre-700)}
.badge--strenuous{background:var(--danger-soft);color:var(--clay-700)}

/* ══ Cards ═══════════════════════════════════════════════════════════════ */
.card{background:var(--surface-card);border:var(--border-thin) solid var(--border-hairline);
  border-radius:var(--radius-sm);box-shadow:var(--shadow-sm);overflow:hidden;
  display:flex;flex-direction:column}
.card__body{padding:var(--space-8);display:flex;flex-direction:column;gap:var(--space-5);flex:1}
.card--sage{background:var(--surface-sage)}
.card--sunken{background:var(--surface-sunken)}
.card--brand{background:var(--surface-brand);color:var(--text-on-brand);border-color:var(--border-on-brand)}
.card--brand h3{color:var(--text-on-brand)}
.card--link{transition:var(--transition-surface),border-color var(--dur-base) var(--ease-out)}
.card--link:hover{transform:translateY(-2px);box-shadow:var(--shadow-md);border-color:var(--kloof-300)}

.card__media{position:relative;overflow:hidden;background:var(--surface-sunken)}
.card__media img{width:100%;height:100%;object-fit:cover;
  transition:transform var(--dur-slow) var(--ease-drift)}
.card--link:hover .card__media img{transform:scale(1.03)}
.ratio-16-10{aspect-ratio:16/10}
.ratio-4-3{aspect-ratio:4/3}
.ratio-1-1{aspect-ratio:1/1}
.ratio-16-9{aspect-ratio:16/9}

/* Programme card — colour-coded rule at the top of the body */
.prog-card .card__body{gap:var(--space-6)}
.prog-card__head{display:flex;align-items:center;gap:var(--space-5)}

/* ══ Masthead ════════════════════════════════════════════════════════════ */
/* The masthead is a band in normal flow, not an overlay: the photograph starts
   beneath it on a clean edge. Sticky keeps it with you down the page, where the
   veil and blur let content pass under it. */
:root{--masthead-h:92px}
@media (min-width:1200px){:root{--masthead-h:104px}}

/* The veil has to do two jobs at once: stay see-through enough that the fynbos
   reads through it, and quiet the photograph enough that 14px uppercase stays
   crisp. The heavy blur does most of the second job — it removes the detail
   behind the letterforms while keeping the image's colour and light — so the
   tint can stay comparatively light. */
.masthead{position:sticky;inset-block-start:0;z-index:50;
  background:rgba(251,249,243,.82);
  backdrop-filter:saturate(.85) brightness(1.06) blur(26px);
  -webkit-backdrop-filter:saturate(.85) brightness(1.06) blur(26px);
  border-bottom:var(--border-thin) solid rgba(21,24,15,.12);
  transition:background-color var(--dur-base) var(--ease-out),
             box-shadow var(--dur-base) var(--ease-out)}
.masthead__inner{display:flex;align-items:center;justify-content:space-between;
  gap:var(--space-8);min-height:var(--masthead-h)}
/* Buy back horizontal room where it is scarcest: the gutters and the two gaps
   between logo, wordmark and button account for ~88px of a 360px screen. */
@media (max-width:560px){
  .masthead .wrap,.masthead__inner{padding-inline:var(--space-6)}
  .masthead__inner{gap:var(--space-6)}
  .wordmark{gap:var(--space-5)}
}

/* On a phone the bar takes a far larger share of the screen, so it is thinned
   right down over the hero — there is no small nav type to protect there, only
   the wordmark and the menu button. It still firms up once scrolled. */
@media (max-width:1023px){
  .masthead:not(.is-veiled){background:rgba(251,249,243,.60)}
}

/* Once the page has moved under it the bar firms up: body copy passing beneath
   needs more cover than a photograph does. */
/* Solid once scrolled. At 82% the hero copy passing underneath stayed
   faintly visible through the bar and read as text cut in half. */
.masthead.is-veiled{background:var(--paper);box-shadow:var(--shadow-md)}

/* Without backdrop-filter the veil alone must hide what passes beneath it */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .masthead{background:rgba(251,249,243,.88)}
  .masthead.is-veiled{background:var(--paper)}
}

/* Must be allowed to shrink: the masthead is fixed, so anything it pushes past
   the right edge is clipped silently rather than producing a scrollbar. */
.wordmark{display:flex;align-items:center;gap:var(--space-6);border-bottom:none;
  flex:0 1 auto;min-width:0}
.wordmark__logo{width:68px;height:68px;border-radius:var(--radius-pill);flex:none;
  background:var(--paper);border:var(--border-thin) solid var(--border-hairline);
  padding:var(--space-1);transition:var(--transition-control)}
/* The roundel is the distinctive part of the brand, so it holds its size on a
   phone rather than shrinking with everything else. */
@media (max-width:520px){.wordmark__logo{width:62px;height:62px}}
@media (max-width:380px){.wordmark__logo{width:54px;height:54px}}
.wordmark__text{display:flex;flex-direction:column;gap:var(--space-1);min-width:0}
.wordmark__name{font:var(--weight-regular) var(--text-lg)/1.1 var(--font-display);
  color:var(--text-heading);letter-spacing:var(--tracking-tight);transition:color var(--dur-base) var(--ease-out)}
.wordmark__tag{font:var(--type-eyebrow);font-size:var(--text-xs);
  letter-spacing:var(--tracking-eyebrow);text-transform:uppercase;color:var(--text-muted);
  transition:color var(--dur-base) var(--ease-out)}
/* Desktop keeps one continuous line, so the two spans just sit inline. */
.wordmark__lead,.wordmark__rest{font:inherit;letter-spacing:inherit;color:inherit}

/* On a phone the name is set as a two line lockup, "Greyton Conservation" over
   "Society". Both lines share one size and face so it reads as a single
   wordmark that has wrapped, rather than two different pieces of text. The
   size follows the viewport so the longer first line always fits. */
@media (max-width:640px){
  .wordmark__name:not(.wordmark__name--flat){display:flex;flex-direction:column;
    gap:0;min-width:0}
  .wordmark__name:not(.wordmark__name--flat) .wordmark__lead,
  .wordmark__name:not(.wordmark__name--flat) .wordmark__rest{
    font:var(--weight-regular) clamp(15px,4.7vw,23px)/1.14 var(--font-display);
    letter-spacing:var(--tracking-tight);color:var(--text-heading);
    text-transform:none}
}
/* Above phone widths the name must stay on one line — a wrapping wordmark
   silently doubles or triples the height of the fixed masthead. */
@media (min-width:641px){
  .wordmark__name{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
}
@media (max-width:520px){.wordmark__tag{display:none}}

.nav{display:none}
.nav__list{display:flex;align-items:center;gap:var(--space-2);list-style:none;margin:0;padding:0}
.nav__link{display:inline-flex;align-items:center;min-height:var(--control-lg);
  padding:0 var(--space-6);border-radius:var(--radius-sm);border-bottom:none;
  font:var(--type-label);font-size:var(--text-sm);
  letter-spacing:var(--tracking-eyebrow);text-transform:uppercase;
  color:var(--text-heading);position:relative;white-space:nowrap;
  transition:var(--transition-control)}
.nav__link:hover{background:color-mix(in oklab,var(--kloof-500) 12%,transparent);color:var(--kloof-800)}
.nav__link[aria-current="page"]::after{content:"";position:absolute;left:var(--space-5);right:var(--space-5);
  bottom:var(--space-3);height:var(--border-thick);background:var(--ochre-500);border-radius:var(--radius-pill)}
.masthead__actions{display:none;align-items:center;gap:var(--space-5)}
.masthead__actions .btn{min-height:var(--control-lg);padding-inline:var(--space-8)}
/* Between the nav appearing and full width, everything steps down a notch so
   the society's name is never truncated and the tagline never wraps. */
@media (min-width:1400px) and (max-width:1579px){
  .wordmark__name{font-size:var(--text-md)}
  .wordmark__tag{display:none}
  .nav__list{gap:var(--space-1)}
  .nav__link{font-size:var(--text-xs);padding-inline:var(--space-4)}
  .nav__link[aria-current="page"]::after{left:var(--space-3);right:var(--space-3)}
  .masthead__actions .btn{font-size:var(--text-2xs);padding-inline:var(--space-6)}
}
}
/* The masthead is fixed, so in-page anchors must clear it when jumped to */
main [id]{scroll-margin-top:124px}
@media (min-width:1400px){
  .nav{display:block}
  .masthead__actions{display:flex}
}

.nav-toggle{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-4);
  min-height:var(--control-lg);padding:0 var(--space-6);background:transparent;cursor:pointer;
  border:var(--border-thin) solid var(--border-strong);border-radius:var(--radius-sm);
  color:var(--text-heading);font:var(--type-label);letter-spacing:var(--tracking-eyebrow);
  text-transform:uppercase;transition:var(--transition-control);flex:none}
@media (max-width:520px){
  .nav-toggle{padding:0 var(--space-5);gap:var(--space-3);font-size:var(--text-2xs)}
}
/* Under ~400px the masthead simply runs out of room: the descriptor needs about
   164px and only ~128px is left once padding, logo, gaps and a labelled button
   have taken their share. Dropping the word "Menu" returns ~42px — more than
   any amount of type-shrinking would — and aria-label keeps the button named. */
@media (max-width:400px){
  .nav-toggle__label{
    position:absolute;width:1px;height:1px;margin:-1px;padding:0;
    overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
  .nav-toggle{padding:0;width:var(--control-lg);justify-content:center;gap:0}
  .nav-toggle .icon{width:22px;height:22px}
}
@media (min-width:1400px){.nav-toggle{display:none}}

/* Mobile drawer */
.drawer{position:fixed;inset:0;z-index:60;background:var(--surface-brand-deep);
  color:var(--text-on-brand);display:flex;flex-direction:column;
  padding:var(--space-8) var(--gutter-page) var(--space-11);
  opacity:0;visibility:hidden;transform:translateY(-8px);
  transition:opacity var(--dur-base) var(--ease-out),transform var(--dur-base) var(--ease-out),visibility var(--dur-base)}
.drawer.is-open{opacity:1;visibility:visible;transform:none}
.drawer__head{display:flex;align-items:center;justify-content:space-between;min-height:76px;margin-bottom:var(--space-9)}
.drawer__close{background:transparent;border:var(--border-thin) solid var(--border-on-brand);
  border-radius:var(--radius-sm);color:var(--stone-050);min-height:var(--control-md);
  padding:0 var(--space-6);cursor:pointer;font:var(--type-label);
  letter-spacing:var(--tracking-eyebrow);text-transform:uppercase}
.drawer__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column}
.drawer__link{display:block;padding:var(--space-6) 0;border-bottom:var(--border-thin) solid var(--border-on-brand);
  color:var(--stone-050);font:var(--weight-regular) var(--text-xl)/1.2 var(--font-display);
  letter-spacing:var(--tracking-tight)}
.drawer__link:hover{color:var(--ochre-300)}
.drawer__foot{margin-top:var(--space-10);display:flex;flex-direction:column;gap:var(--space-6)}
/* A bare link here would inherit the global link green, which is meant for the
   paper background — on the drawer's near-black panel that measured 1.86:1. */
.drawer__foot a:not(.btn){color:var(--kloof-200);
  border-bottom-color:rgba(251,249,243,.30)}
.drawer__foot a:not(.btn):hover{color:var(--stone-050);border-bottom-color:currentColor}

/* ══ Hero ════════════════════════════════════════════════════════════════ */
/* Deliberately short of the viewport: with the masthead band above it, the top
   of the stat band stays visible on first load so the page reads as continuing. */
/* Runs up behind the translucent masthead so the photograph reads through it,
   and stops short of the viewport so the stat band stays above the fold. */
.hero{position:relative;margin-top:calc(-1 * var(--masthead-h));
  min-height:clamp(520px,82svh,980px);display:flex;align-items:flex-end;
  overflow:hidden;background:var(--kloof-900);isolation:isolate}
.hero__media{position:absolute;inset:0;z-index:-2;overflow:hidden;will-change:transform}
/* Overscanned past the frame top and bottom so the parallax shift can never
   drag a bare edge into view. */
.hero__media img{position:absolute;left:0;top:-8%;width:100%;height:116%;
  object-fit:cover}
/* Two scrims. The vertical one is the house gradient; the horizontal one darkens
   only the column the copy occupies, because the eyebrow and headline sit over
   the brightest part of the fynbos (measured 1.8:1 without it). The right-hand
   side stays clear so the photograph still carries the frame. */
/* Kept as light as the text will allow: the vertical wash barely touches the top
   of the frame so the fynbos stays bright, and the horizontal one darkens only
   the column the copy sits in. Values are set by measurement, not by eye — see
   the contrast notes on .hero__eyebrow. */
.hero::after{content:"";position:absolute;inset:0;z-index:-1;background:
  linear-gradient(90deg,rgba(16,30,22,.74) 0%,rgba(16,30,22,.56) 34%,
                        rgba(16,30,22,.30) 56%,rgba(16,30,22,0) 82%),
  linear-gradient(180deg,rgba(16,30,22,.16) 0%,rgba(16,30,22,.10) 28%,
                         rgba(16,30,22,.28) 62%,rgba(16,30,22,.68) 100%)}
/* The hero runs up behind the masthead, so its top padding must clear the bar —
   otherwise on a short viewport the bottom-aligned copy overflows upward and
   the eyebrow ends up sliding under the header. */
.hero__inner{width:100%;color:var(--stone-050);
  padding-block:calc(var(--masthead-h) + var(--space-8)) var(--space-13)}
/* Line breaks in the headline are authored as .reveal-line spans, so the
   container only needs to be wide enough not to re-wrap them. */
.hero__content{max-width:min(100%,780px)}
/* Near-white, not the light green: at 12px over a photograph kloof-200's own
   luminance caps it near 2:1 however hard the scrim works. inline-flex keeps
   the box to the text so it cannot stray over the bright right-hand side. */
.hero__eyebrow{color:var(--stone-050);margin-bottom:var(--space-7);
  display:inline-flex;text-shadow:0 1px 2px rgba(16,30,22,.55)}
/* The shadow is for the handful of bright blooms the type crosses; the scrim
   does the bulk of the work. */
.hero__title{font:var(--type-hero);color:var(--stone-050);letter-spacing:var(--tracking-tight);
  margin-bottom:var(--space-7);text-shadow:0 2px 12px rgba(16,30,22,.42);
  /* Scale down on narrow screens so the authored line breaks still hold */
  font-size:clamp(var(--text-2xl),8.2vw,var(--text-4xl))}
.hero__lede{font:var(--type-lede);color:var(--stone-050);max-width:46ch;
  margin-bottom:var(--space-9);text-shadow:0 1px 8px rgba(16,30,22,.45)}
.hero__actions{display:flex;flex-wrap:wrap;gap:var(--space-5)}
/* On a phone the two buttons wrap to their own lines anyway; matching their
   width stops the ragged edge, and the tighter lede keeps the hero from
   growing past the fold on a short viewport. */
@media (max-width:560px){
  .hero__lede{font-size:var(--text-base);margin-bottom:var(--space-8)}
  .hero__actions{flex-direction:column;align-items:stretch;gap:var(--space-5)}
  .hero__actions .btn{width:100%}
}
/* A phone with the browser chrome showing has very little height to spend, so
   give the hero back some of its footer padding to keep the stat band in view. */
@media (max-height:700px){
  .hero__inner{padding-bottom:var(--space-11)}
  .hero__lede{margin-bottom:var(--space-7)}
}
.hero__credit{position:absolute;right:var(--gutter-page);bottom:var(--space-6);z-index:2;
  font:var(--type-small);font-size:var(--text-2xs);color:rgba(251,249,243,.55);
  letter-spacing:var(--tracking-wide);text-transform:uppercase}

/* Masked line reveal — each line sits in its own clipping box. The box clips
   vertically only; the padding keeps descenders and italic overhang inside it. */
.reveal-line{display:block;overflow:hidden;padding-bottom:.14em;margin-bottom:-.14em}
.reveal-line > span{display:block}

.hero__scroll{position:absolute;left:50%;bottom:var(--space-7);z-index:2;transform:translateX(-50%);
  display:flex;flex-direction:column;align-items:center;gap:var(--space-4);
  color:rgba(251,249,243,.7);border-bottom:none;
  font:var(--type-eyebrow);letter-spacing:var(--tracking-eyebrow);text-transform:uppercase}
.hero__scroll:hover{color:var(--stone-050)}
.hero__scroll .icon{width:18px;height:18px;animation:nudge 2.4s var(--ease-in-out) infinite}
@keyframes nudge{0%,100%{transform:translateY(0);opacity:.7}50%{transform:translateY(4px);opacity:1}}
@media (max-width:720px){.hero__scroll{display:none}}

@media (min-width:900px){
  .hero__title{font-size:var(--text-5xl)}
  .hero__inner{padding-block:calc(var(--masthead-h) + var(--space-10)) var(--space-14)}
}

/* Compact hero for interior pages */
.page-hero{position:relative;min-height:66svh;display:flex;align-items:flex-end;
  overflow:hidden;background:var(--kloof-900);isolation:isolate}
.page-hero__media{position:absolute;inset:0;z-index:-2;overflow:hidden}
/* Only a little overscan: the parallax travel is small, and every extra
   percent here is zoom the reader did not ask for. */
.page-hero__media{will-change:transform}
.page-hero__media img{position:absolute;left:0;top:-3%;width:100%;height:106%;object-fit:cover}

/* ── Hero slides ─────────────────────────────────────────────────────────
   Three photographs stacked in the same frame. Only the first is visible
   until main.js starts the crossfade, so with no JS, or with reduced motion
   asked for, the header is simply one still picture. */
.masonry{columns:3 300px;column-gap:var(--space-6)}
.masonry figure{break-inside:avoid;margin:0 0 var(--space-6)}
.masonry a{display:block;border-radius:var(--radius-md)}
.masonry img{width:100%;height:auto;display:block;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);transition:box-shadow var(--duration-quick) var(--ease-out)}
.masonry a:hover img{box-shadow:var(--shadow-md)}
.masonry figcaption{font-size:var(--text-xs);color:var(--text-faint);padding-top:var(--space-2)}
.card__body>.btn[data-dialog]{align-self:flex-start}
.notes-dialog{border:0;padding:0;margin:auto;width:min(720px,calc(100vw - var(--space-8)));max-height:min(88svh,900px);
  background:var(--surface-card);color:var(--text-body);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);overflow:hidden}
.notes-dialog::backdrop{background:rgba(16,30,22,.58)}
.notes-dialog__inner{max-height:min(88svh,900px);overflow:auto;overscroll-behavior:contain;padding:var(--space-9) var(--space-9) var(--space-10);display:flex;flex-direction:column;gap:var(--space-6)}
.notes-dialog__head{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-6)}
.notes-dialog__head .h2{max-width:20ch}
.notes-dialog__close{flex:none;width:var(--hit-min);height:var(--hit-min);display:grid;place-items:center;border-radius:var(--radius-pill);
  border:var(--border-thin) solid var(--border-strong);background:transparent;color:var(--text-heading);cursor:pointer;transition:var(--transition-control)}
.notes-dialog__close:hover{background:color-mix(in oklab,var(--kloof-500) 12%,transparent)}
.notes-dialog__close .icon{width:20px;height:20px}
.notes-dialog__meta{border-top:var(--border-thin) solid var(--border-subtle);border-bottom:var(--border-thin) solid var(--border-subtle);padding-block:var(--space-5)}
.notes-dialog__body p+p{margin-top:var(--space-5)}
.notes-dialog__body .lede{margin-bottom:var(--space-2)}
.notes-dialog__foot{padding-top:var(--space-2)}
@media (max-width:640px){.notes-dialog__inner{padding:var(--space-7) var(--space-6) var(--space-8)}}
@media (prefers-reduced-motion:no-preference){
  .notes-dialog[open]{animation:dialog-in .34s var(--ease-out)}
  .notes-dialog[open]::backdrop{animation:backdrop-in .34s var(--ease-out)}
}
@keyframes dialog-in{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
@keyframes backdrop-in{from{opacity:0}to{opacity:1}}
/* Without JavaScript the notes simply appear in the card, as plain content */
html:not(.js-ready) .notes-dialog{display:block;position:static;width:auto;max-height:none;box-shadow:none;border-radius:0;background:transparent;overflow:visible}
html:not(.js-ready) .notes-dialog__inner{max-height:none;padding:0}
html:not(.js-ready) .notes-dialog__close,html:not(.js-ready) .btn[data-dialog]{display:none}
.video-stage{background:radial-gradient(120% 90% at 72% 50%,color-mix(in oklab,var(--kloof-700) 55%,var(--kloof-900)),var(--kloof-900) 70%)}
.video-stage__inner{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:var(--space-11);align-items:center}
.video-stage__copy{gap:var(--space-5);max-width:var(--measure-prose)}
.video-card{margin:0;justify-self:end}
.video-card video{display:block;height:clamp(440px,74svh,760px);width:auto;max-width:100%;aspect-ratio:478/850;
  border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);background:var(--ink-900)}
@media (max-width:900px){
  .video-stage__inner{grid-template-columns:1fr;gap:var(--space-8)}
  .video-card{justify-self:center}
  .video-card video{height:auto;width:min(100%,380px)}
}
.route-grid{display:grid;gap:var(--space-8)}
.route-grid__aside img{width:100%;height:auto;display:block}
@media (min-width:1024px){
.route-grid{grid-template-columns:minmax(0,1fr) minmax(0,.58fr);align-items:start;gap:var(--space-10)}
.route-grid__aside{position:sticky;top:calc(var(--masthead-h) + var(--space-6))}
}
.match-card{background:var(--kloof-900);color:var(--kloof-100);border-radius:var(--radius-lg);padding:var(--space-9) var(--space-8);display:flex;flex-direction:column;justify-content:center;gap:var(--space-5);box-shadow:var(--shadow-md)}
.match-card__eyebrow{color:var(--ochre-300)}
.match-card__eyebrow::before{background:var(--ochre-300)}
.match-card__big{font-family:var(--font-display);font-weight:500;font-size:clamp(2.1rem,3.4vw,3rem);line-height:1.08;letter-spacing:-0.01em;color:var(--stone-050);max-width:14ch}
.match-card__body{color:var(--kloof-100);max-width:44ch}
.snapscan-row{display:flex;align-items:center;gap:var(--space-6);flex-wrap:wrap}
.snapscan{display:block;flex:0 0 auto;width:min(168px,40vw);border-radius:var(--radius-md);transition:box-shadow var(--duration-quick) var(--ease-out)}
.snapscan img{display:block;width:100%;height:auto;border-radius:var(--radius-md);box-shadow:var(--shadow-sm)}
.snapscan:hover img{box-shadow:var(--shadow-md)}
.snapscan-row>div{flex:1 1 24ch}
.page-hero__media picture,.hero__media picture{display:contents}
.hero-slide{opacity:0}
.hero-slide.is-current{opacity:1}
@media (prefers-reduced-motion:reduce){
  .hero-slide:not(.is-current){display:none}
}

/* Arrows for stepping through the hero photographs. Injected by main.js only
   when slides exist, so they never appear as dead controls. Kept off phones,
   where the 24px gutter would put them on top of the headline. */
.hero-arrow{position:absolute;top:50%;translate:0 -50%;z-index:2;
  width:var(--hit-min);height:var(--hit-min);border-radius:var(--radius-pill);
  display:none;place-items:center;cursor:pointer;padding:0;
  background:rgba(16,30,22,.26);border:var(--border-thin) solid rgba(251,249,243,.32);
  color:var(--stone-050);opacity:.5;
  transition:var(--transition-control),opacity var(--dur-base) var(--ease-out)}
.hero-arrow:hover{opacity:1;background:rgba(16,30,22,.5);border-color:rgba(251,249,243,.75);color:var(--stone-050)}
.hero-arrow:active{translate:0 calc(-50% + 1px)}
.hero-arrow .icon{width:20px;height:20px}
.hero-arrow--prev{left:var(--space-3)}
.hero-arrow--prev .icon{transform:rotate(180deg)}
.hero-arrow--next{right:var(--space-3)}
@media (min-width:900px){.hero-arrow{display:grid}}
.page-hero::after{content:"";position:absolute;inset:0;z-index:-1;background:var(--scrim-hero)}
.page-hero__inner{width:100%;padding-block:var(--space-12) var(--space-11);color:var(--stone-050)}
.page-hero__title{font:var(--type-h1);color:var(--stone-050);margin-block:var(--space-6) var(--space-6);
  max-width:min(100%,820px);font-size:clamp(var(--text-xl),7vw,var(--text-3xl))}
.page-hero__lede{font:var(--type-lede);color:var(--kloof-100);max-width:52ch}
@media (min-width:900px){.page-hero__title{font-size:var(--text-4xl)}}

/* ══ Stat band ═══════════════════════════════════════════════════════════ */
.statband{display:grid;gap:var(--space-9);grid-template-columns:repeat(2,1fr)}
@media (min-width:900px){.statband{grid-template-columns:repeat(4,1fr);gap:var(--space-10)}}
.stat{display:flex;flex-direction:column;gap:var(--space-4)}
.stat__value{font:var(--weight-light) var(--text-2xl)/var(--leading-tight) var(--font-display);
  color:var(--text-heading);letter-spacing:var(--tracking-tight);font-variant-numeric:tabular-nums}
.section--brand .stat__value,.section--brand-deep .stat__value,.on-dark .stat__value{color:var(--stone-050)}
.stat__label{font:var(--type-eyebrow);letter-spacing:var(--tracking-eyebrow);
  text-transform:uppercase;color:var(--text-muted)}
.section--brand .stat__label,.section--brand-deep .stat__label,.on-dark .stat__label{color:var(--kloof-300)}
.stat__note{font:var(--type-small);color:var(--text-faint)}
.section--brand .stat__note,.on-dark .stat__note{color:var(--kloof-300)}
@media (min-width:900px){.stat__value{font-size:var(--text-3xl)}}

/* ══ Split feature (text + image) ════════════════════════════════════════ */
.split{display:grid;gap:var(--space-10);align-items:center}
.split--top{align-items:start}
@media (min-width:900px){
  .split{grid-template-columns:1fr 1fr;gap:var(--space-12)}
  .split--wide-media{grid-template-columns:5fr 7fr}
  .split--reverse .split__media{order:2}
}
.split__media{border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-md);
  background:var(--surface-sunken)}
.split__media img{width:100%;height:100%;object-fit:cover}
.split__body{display:flex;flex-direction:column;gap:var(--space-6);align-items:flex-start}

/* ══ Event rows ══════════════════════════════════════════════════════════ */
.eventlist{display:flex;flex-direction:column;border-top:var(--border-thin) solid var(--border-hairline)}
.event{display:grid;gap:var(--space-5);padding:var(--space-8) var(--space-5);
  border-bottom:var(--border-thin) solid var(--border-hairline);
  transition:background-color var(--dur-fast) var(--ease-out);align-items:center}
.event:hover{background:var(--kloof-050)}
.event__when{display:flex;align-items:center;gap:var(--space-5)}
.event__time{font:var(--type-data);color:var(--text-muted);white-space:nowrap}
.event__title{font:var(--type-h3);color:var(--text-heading)}
.event__desc{font:var(--type-small);color:var(--text-muted)}
@media (min-width:900px){
  .event{grid-template-columns:auto 1fr auto;gap:var(--space-9);padding-inline:var(--space-6)}
}

/* ══ Trail card ══════════════════════════════════════════════════════════ */
.trail__meta{display:flex;flex-wrap:wrap;gap:var(--space-5) var(--space-8);
  padding-top:var(--space-5);border-top:var(--border-thin) solid var(--border-hairline)}
.trail__stat{display:flex;flex-direction:column;gap:var(--space-2)}
.trail__stat dt{font:var(--type-eyebrow);letter-spacing:var(--tracking-eyebrow);
  text-transform:uppercase;color:var(--text-faint)}
.trail__stat dd{margin:0;font:var(--type-data);color:var(--text-body)}

/* ══ Callout ═════════════════════════════════════════════════════════════ */
.callout{display:flex;gap:var(--space-6);padding:var(--space-8);border-radius:var(--radius-sm);
  background:var(--info-soft);align-items:flex-start}
.callout--note{background:var(--surface-sunken)}
.callout--warning{background:var(--warning-soft)}
.callout__icon{color:var(--info);flex:none;margin-top:var(--space-1)}
.callout--note .callout__icon{color:var(--stone-700)}
.callout--warning .callout__icon{color:var(--ochre-700)}
.callout__body{display:flex;flex-direction:column;gap:var(--space-4)}
.callout__title{font:var(--type-h3);font-size:var(--text-base);color:var(--text-heading)}

/* ══ Quote ═══════════════════════════════════════════════════════════════ */
.quote{display:flex;flex-direction:column;gap:var(--space-6);max-width:var(--measure-prose)}
.quote__text{font:var(--weight-light) var(--text-lg)/var(--leading-normal) var(--font-display);
  color:var(--text-heading);letter-spacing:var(--tracking-tight)}
.section--brand .quote__text,.on-dark .quote__text{color:var(--stone-050)}
.quote__cite{font:var(--type-eyebrow);letter-spacing:var(--tracking-eyebrow);
  text-transform:uppercase;color:var(--text-muted);font-style:normal}
@media (min-width:900px){.quote__text{font-size:var(--text-xl)}}

/* ══ Team ════════════════════════════════════════════════════════════════ */
.person__photo{aspect-ratio:1/1;overflow:hidden;border-radius:var(--radius-sm);
  background:var(--surface-sunken);margin-bottom:var(--space-6)}
.person__photo img{width:100%;height:100%;object-fit:cover}
.person__name{font:var(--type-h3);color:var(--text-heading)}
.person__role{font:var(--type-eyebrow);letter-spacing:var(--tracking-eyebrow);
  text-transform:uppercase;color:var(--prog-nature);margin-block:var(--space-3) var(--space-5)}
.person__bio{font:var(--type-small);color:var(--text-muted)}

/* ══ Membership tiers ════════════════════════════════════════════════════ */
.tier{position:relative}
.tier--feature{border-color:var(--kloof-300);box-shadow:var(--shadow-md)}
.tier__price{font:var(--weight-light) var(--text-2xl)/1 var(--font-display);
  color:var(--text-heading);font-variant-numeric:tabular-nums}
.tier__period{font:var(--type-small);color:var(--text-faint)}
.tier__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--space-5);flex:1}
.tier__list li{display:flex;gap:var(--space-5);align-items:flex-start;font:var(--type-small)}
.tier__list .icon{width:18px;height:18px;color:var(--kloof-500);flex:none;margin-top:var(--space-1)}

/* ══ Partner strip ═══════════════════════════════════════════════════════ */
.partners{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--space-6);align-items:center}
@media (min-width:720px){.partners{grid-template-columns:repeat(3,1fr)}}
@media (min-width:980px){.partners{grid-template-columns:repeat(6,1fr)}}
.partner{display:grid;place-items:center;padding:var(--space-7);background:var(--paper-raised);
  border:var(--border-thin) solid var(--border-hairline);border-radius:var(--radius-sm);
  min-height:116px;transition:var(--transition-control)}
.partner:hover{border-color:var(--kloof-300)}
/* Partners we have no logo file for: the name set in the display face, so the
   strip stays even rather than mixing marks with blank tiles. */
.partner--text{text-align:center}
.partner__name{font:var(--weight-regular) var(--text-md)/1.2 var(--font-display);
  color:var(--text-heading);letter-spacing:var(--tracking-tight)}
.partner--text:hover .partner__name{color:var(--kloof-600)}
.partner img{max-height:68px;width:auto;object-fit:contain;
  filter:grayscale(1);opacity:.85;transition:var(--transition-control),filter var(--dur-base) var(--ease-out),opacity var(--dur-base) var(--ease-out)}
.partner:hover img{filter:none;opacity:1}

/* ══ Gallery (rainfall charts, maps) ═════════════════════════════════════ */
.chart-grid{display:grid;gap:var(--space-8);grid-template-columns:1fr}
@media (min-width:720px){.chart-grid{grid-template-columns:repeat(2,1fr)}}
@media (min-width:1100px){.chart-grid{grid-template-columns:repeat(3,1fr)}}
.chart{background:var(--paper-raised);border:var(--border-thin) solid var(--border-hairline);
  border-radius:var(--radius-sm);overflow:hidden;box-shadow:var(--shadow-sm);
  transition:var(--transition-surface)}
.chart:hover{transform:translateY(-2px);box-shadow:var(--shadow-md)}
.chart img{width:100%;height:auto;background:var(--white)}
/* Photograph tiles in a row: fix the ratio so the captions line up even if a
   source image is cropped differently. */
.chart--tile img{aspect-ratio:16/10;height:auto;object-fit:cover}
.chart__label{padding:var(--space-5) var(--space-6);font:var(--type-eyebrow);
  letter-spacing:var(--tracking-eyebrow);text-transform:uppercase;color:var(--text-muted);
  border-top:var(--border-thin) solid var(--border-hairline)}
.chart--wide{grid-column:1/-1}

/* Month by month rainfall sits closed until asked for. Without JavaScript the
   toggle never appears and every chart is simply on the page. */
html.js-ready .rainfall-months{display:none}
html.js-ready .rainfall-months.is-open{display:grid}
html:not(.js-ready) .rainfall-toggle{display:none}
.rainfall-toggle{align-self:flex-start}

/* ══ Forms ═══════════════════════════════════════════════════════════════ */
.form{display:flex;flex-direction:column;gap:var(--space-7);max-width:var(--width-narrow)}
.form__row{display:grid;gap:var(--space-7)}
@media (min-width:720px){.form__row--2{grid-template-columns:repeat(2,1fr)}}
.field{display:flex;flex-direction:column;gap:var(--space-4)}
.field__label{font:var(--type-label);letter-spacing:var(--tracking-wide);
  text-transform:uppercase;color:var(--text-muted)}
.field__hint{font:var(--type-small);color:var(--text-faint)}
.input,.textarea,.select{width:100%;min-height:var(--control-lg);padding:var(--space-5) var(--space-6);
  background:var(--paper-raised);color:var(--text-body);font:var(--type-body);
  border:var(--border-thin) solid var(--border-strong);border-radius:var(--radius-sm);
  transition:var(--transition-control)}
.input:hover,.textarea:hover,.select:hover{border-color:var(--kloof-400)}
.input:focus,.textarea:focus,.select:focus{border-color:var(--kloof-600);box-shadow:var(--shadow-focus);outline:none}
.textarea{min-height:140px;resize:vertical;padding-top:var(--space-6)}
.fieldset{display:flex;flex-direction:column;gap:var(--space-4);border:0;margin:0;padding:0;min-inline-size:0}
.choices{display:flex;flex-direction:column;gap:var(--space-4);list-style:none;margin:0;padding:0}
.choice{display:flex;align-items:center;gap:var(--space-4);min-height:var(--hit-min);cursor:pointer;font:var(--type-body);color:var(--text-body)}
.choice input{flex:none;width:20px;height:20px;margin:0;accent-color:var(--kloof-600);cursor:pointer}
.choice input:focus-visible{outline:var(--border-thick) solid var(--ochre-500);outline-offset:2px}
.choice--stack{align-items:flex-start}
.form__note{font:var(--type-small);color:var(--text-faint)}

/* Dark-surface form (newsletter in the footer). Capped so the input does not
   stretch across a full-bleed footer column on wide displays. */
.form--on-dark{max-width:420px}
.form--on-dark .field__label{color:var(--kloof-300)}
.form--on-dark .input,.form--on-dark .textarea{background:rgba(251,249,243,.06);
  color:var(--stone-050);border-color:var(--border-on-brand)}
.form--on-dark .input::placeholder{color:var(--kloof-300)}
.form--on-dark .input:hover{border-color:var(--kloof-400)}
.form--on-dark .input:focus{border-color:var(--ochre-500)}

/* ══ Footer ══════════════════════════════════════════════════════════════ */
.footer{background:var(--surface-brand-deep);color:var(--kloof-200)}
.footer a{color:var(--kloof-200);border-bottom-color:rgba(251,249,243,.22)}
.footer a:hover{color:var(--stone-050);border-bottom-color:currentColor}
.footer__top{display:grid;gap:var(--space-10);padding-block:var(--section-y-tight)}
@media (min-width:900px){.footer__top{grid-template-columns:2fr 1fr 1fr 2fr;gap:var(--space-11)}}
/* 40ch keeps the three-word tagline on one line rather than breaking it
   after a pipe; the blurb above it is short enough not to run long. */
.footer__brand{display:flex;flex-direction:column;gap:var(--space-6);max-width:40ch}
.footer__logo{width:64px;height:64px;border-radius:var(--radius-pill);background:var(--paper);
  padding:var(--space-2)}
.footer__title{font:var(--type-eyebrow);letter-spacing:var(--tracking-eyebrow);
  text-transform:uppercase;color:var(--kloof-300);margin-bottom:var(--space-6)}
.footer__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--space-5)}
.footer__list a{font:var(--type-small);border-bottom:none}
.footer__list a:hover{border-bottom:1px solid currentColor}
.footer__bottom{display:flex;flex-wrap:wrap;gap:var(--space-6) var(--space-9);
  justify-content:space-between;align-items:center;padding-block:var(--space-8);
  border-top:var(--border-thin) solid var(--border-on-brand);
  font:var(--type-small);color:var(--kloof-300)}
.social{display:flex;gap:var(--space-5)}
.social a{display:grid;place-items:center;width:var(--control-md);height:var(--control-md);
  border:var(--border-thin) solid var(--border-on-brand);border-radius:var(--radius-sm);
  color:var(--kloof-200);transition:var(--transition-control)}
.social a:hover{background:rgba(251,249,243,.1);color:var(--stone-050);border-color:var(--stone-050)}

/* ══ Scroll-reveal defaults ══════════════════════════════════════════════
   Elements start hidden only when JS is running and motion is allowed;
   .js-ready is set by main.js so no-JS visitors see everything. */
html.js-ready [data-reveal]{opacity:0}
/* The hero copy must be hidden from the very first paint, or it renders fully,
   vanishes when GSAP takes over, and fades back in — a visible flash on every
   page change. These match the values the intro animates from. */
html.js-ready .reveal-line > span{transform:translateY(108%)}
html.js-ready [data-hero-fade]{opacity:0}
@media (prefers-reduced-motion:reduce){
  html.js-ready [data-reveal]{opacity:1}
  html.js-ready .reveal-line > span{transform:none}
  html.js-ready [data-hero-fade]{opacity:1}
}
