/* Component styles for heroes, section blocks, cards and the contact form. */

/* Page hero */
.page-hero { padding-block: clamp(48px, 7vw, 104px) clamp(32px, 5vw, 72px); }
.page-hero-inner { display: grid; gap: var(--space-7); align-items: end; }
.page-hero .display { max-width: 16ch; margin-bottom: 0; }
/* The Privacy Statement's effective date, sitting directly under the H1. */
.page-hero-date { font-size: var(--step--1); color: var(--color-muted); margin: var(--space-4) 0 0; }
.page-hero-media { margin: 0; border-radius: var(--radius-lg); overflow: hidden; aspect-ratio: 4 / 3; background: var(--color-sand); }
.page-hero-media img, .page-hero-media picture { width: 100%; height: 100%; object-fit: cover; }
@media (min-width: 900px) {
  .page-hero.has-media .page-hero-inner { grid-template-columns: 1.1fr 0.9fr; }
}

/* Home hero */
.hero-home { position: relative; overflow: hidden; display: flex; align-items: center; min-height: 78vh; padding-block: clamp(96px, 16vw, 160px) clamp(56px, 8vw, 96px); }
.hero-home-media { position: absolute; inset: 0; z-index: 0; overflow: hidden; }
.hero-home-media .parallax { position: absolute; inset: -8% 0; }
.hero-home-media picture, .hero-home-media img { width: 100%; height: 100%; object-fit: cover; }
.hero-home-media img { object-position: 60% 40%; }
/* Scrim. Below 900px the copy fills the hero from about a fifth to about
   four fifths of its height, so the wash stays strong through that whole band
   and only opens up above the eyebrow. Measured in Chrome, the earlier stops
   left the gold eyebrow at 1.14:1 and the H1 at 1.77:1 over the bright leaves
   at the top of the photograph. */
.hero-home::before {
  content: "";
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(to top, rgba(9, 53, 32, 0.92) 0%, rgba(9, 53, 32, 0.88) 84%, rgba(9, 53, 32, 0.3) 100%);
}
.hero-home::after {
  content: "";
  position: absolute; inset: 0 0 auto 0; height: 180px; z-index: 2; pointer-events: none;
  background: linear-gradient(to bottom, rgba(9, 53, 32, 0.55), transparent);
}
.hero-home-inner { position: relative; z-index: 3; }
.hero-home .eyebrow { color: var(--color-gold); }
.hero-home .display { color: var(--color-on-dark); max-width: 17ch; font-size: clamp(2.6rem, 1.6rem + 3.4vw, 4.6rem); }
/* The lead paragraph and the second button sit straight on the photograph, the
   same as the H1 above them, so they take the same on-dark treatment. Without
   it both inherit the page's dark ink and vanish into the scrim. The measure
   keeps the paragraph inside the strong end of the scrim gradient rather than
   running the full container width out into the bare photo, matching the
   measure the cta-band lead already uses. */
.hero-actions { color: var(--color-on-dark); }
.hero-actions p { max-width: 46ch; }
.hero-actions .btn-row { margin-top: var(--space-5); }
.hero-actions .btn-ghost { --btn-fg: var(--color-on-dark); border-color: var(--color-on-dark); }
.hero-actions .btn-ghost:hover { --btn-bg: var(--color-on-dark); --btn-fg: var(--color-forest); }
.hero-home > .pattern-band { position: absolute; inset: auto 0 0 0; z-index: 3; }
@media (min-width: 900px) {
  .hero-home { min-height: min(92vh, 880px); }
  .hero-home-media img { object-position: 80% 50%; }
  /* From 900px the copy is a left column and the wash runs across instead of up,
     so the photograph opens out on the right. The eyebrow, the lead and the
     buttons all end inside the first 45% of the viewport and the wash holds its
     plateau across that whole run. The H1's 17ch measure carries on to about 56%,
     into the falloff, where it is large text and still measured 4.4:1 in Chrome. */
  .hero-home::before {
    background: linear-gradient(to right, rgba(9, 53, 32, 0.92) 0%, rgba(9, 53, 32, 0.88) 45%, rgba(9, 53, 32, 0.2) 75%, transparent 100%);
  }
}
/* The overlay header is fixed and out of flow, so give the hero content room to clear it. */
html.nav-overlay .hero-home { padding-top: calc(var(--header-h) + var(--space-6)); }

.section-title { max-width: 22ch; }
.section-lead { margin-bottom: var(--space-6); }

/* Checklist grid */
.section-checklist { background: var(--color-sand); }
.checklist { list-style: none; margin: var(--space-6) 0 0; padding: 0; display: grid; gap: var(--space-4); grid-template-columns: 1fr; }
.checklist-item { display: flex; gap: var(--space-4); align-items: flex-start; padding: var(--space-5); background: var(--color-cream); border: 1px solid var(--color-line); border-radius: var(--radius-md); line-height: 1.45; transition: transform 0.35s var(--ease-out), box-shadow 0.35s var(--ease-out); }
.checklist-item:hover { transform: translateY(-3px); box-shadow: var(--shadow-card); }
.tick { flex: none; width: 22px; height: 22px; padding: 3px; border-radius: 50%; background: var(--color-forest); color: var(--color-gold); }

/* Icon badge, the one circular icon chip. Cards, process nodes and the audience
   and status callouts all use it, sized through --badge-size. */
.icon-badge {
  --badge-size: 48px;
  position: relative; z-index: 1; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--badge-size); height: var(--badge-size);
  border-radius: 50%; background: var(--color-sand-2); color: var(--color-forest);
  margin-bottom: var(--space-4);
}
.icon-badge .icon { width: calc(var(--badge-size) / 2); height: calc(var(--badge-size) / 2); }

/* Photo backdrop, a full-bleed photo behind a section with a scrim over it so
   text stays legible. Used by the CTA band and the coming soon card. */
.photo-backdrop { position: absolute; inset: 0; z-index: 0; }
.photo-backdrop picture, .photo-backdrop img { width: 100%; height: 100%; object-fit: cover; }
.scrim { position: absolute; inset: 0; z-index: 1; background: rgba(17, 17, 17, 0.72); }

/* Icon line (contact email, footer contact list) */
.icon-line { display: flex; align-items: center; gap: var(--space-3); }
.icon-line .icon { color: var(--color-forest); }

/* On the Contact page the email and address lines join into one sand card, set
   larger in the heading face so they stand out from the copy around them. */
.contact-copy .icon-line {
  margin: 0; padding: var(--space-4) var(--space-5); gap: var(--space-4);
  background: var(--color-sand); color: var(--color-forest);
  font: 500 var(--step-1)/1.3 var(--font-heading); overflow-wrap: anywhere;
}
.contact-copy .icon-line + .icon-line { border-top: 1px solid var(--color-sand-2); }
.contact-copy :not(.icon-line) + .icon-line { margin-top: var(--space-5); border-radius: var(--radius-md) var(--radius-md) 0 0; }
.contact-copy .icon-line:has(+ :not(.icon-line)) { margin-bottom: var(--space-5); border-radius: 0 0 var(--radius-md) var(--radius-md); }
.contact-copy :not(.icon-line) + .icon-line:has(+ :not(.icon-line)) { border-radius: var(--radius-md); }
.contact-copy .icon-line .icon { width: 1.5rem; height: 1.5rem; }
.contact-copy .icon-line a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: 0.2em; }

/* CTA band */
.cta-band { position: relative; overflow: hidden; background: var(--color-forest); color: var(--color-on-dark); }
.cta-band > .pattern-band { position: relative; z-index: 2; }
.cta-band-inner { position: relative; z-index: 2; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-6); padding-block: clamp(64px, 8vw, 112px); }
.cta-band-copy { flex: 1 1 320px; }
.cta-heading { color: var(--color-on-dark); font-size: var(--step-4); max-width: 18ch; margin: 0; }
.cta-band-body { color: var(--color-on-dark-muted); font-size: var(--step-0); max-width: 46ch; margin: var(--space-3) 0 0; }
.cta-band-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4); }
.cta-band-actions .btn-ghost { --btn-fg: var(--color-on-dark); border-color: var(--color-on-dark); }
.cta-band-actions .btn-ghost:hover { --btn-bg: var(--color-on-dark); --btn-fg: var(--color-forest); }
.btn-lg { font-size: var(--step-0); padding: 1.1em 2em; }

/* Coming soon */
.coming-soon { position: relative; overflow: hidden; }
.coming-soon .container { position: relative; z-index: 2; }
.coming-soon-card { padding: clamp(32px, 5vw, 64px); background: var(--color-sand); border-radius: var(--radius-lg); max-width: 720px; }
.coming-soon-text { font-family: var(--font-heading); font-size: var(--step-2); color: var(--color-forest); }

/* Feature blocks */
.section-features { background: var(--color-sand); }
.features { display: grid; gap: var(--space-5); grid-template-columns: 1fr; margin-top: var(--space-6); }
.feature { padding: clamp(24px, 3vw, 40px); background: var(--color-cream); border-radius: var(--radius-lg); border: 1px solid var(--color-line); transition: transform 0.35s var(--ease-out), box-shadow 0.35s var(--ease-out); }
.feature:hover { transform: translateY(-4px); box-shadow: var(--shadow-card); }
.feature-title { font-size: var(--step-2); }
/* As on the callouts, an icon sits beside the title and the body runs full width below. */
.feature { display: grid; grid-template-columns: auto 1fr; align-items: center; column-gap: var(--space-4); align-content: start; }
.feature > * { grid-column: 1 / -1; margin-block: 0; }
.feature > .icon-badge { grid-column: 1; }
.feature > .icon-badge + .feature-title { grid-column: 2; }
.feature > .feature-body { margin-top: var(--space-4); }
.feature-body > :last-child { margin-bottom: 0; }

/* Numbered cards */
.section-numbered { background: var(--color-sand); }
.numbered-cards { list-style: none; margin: var(--space-6) 0 0; padding: 0; display: grid; gap: var(--space-5); grid-template-columns: 1fr; }
.numbered-card { position: relative; padding: clamp(28px, 3vw, 40px); background: var(--color-cream); border-radius: var(--radius-lg); overflow: hidden; transition: transform 0.35s var(--ease-out), box-shadow 0.35s var(--ease-out); }
.numbered-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-card); }
.card-label { font-size: var(--step--1); font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--color-muted); margin-bottom: var(--space-2); }
.card-title { font-size: var(--step-2); }
.card-body > :last-child { margin-bottom: 0; }

/* Program cards */
.section-programs { background: var(--color-sand); }
.section-programs-cream { background: var(--color-cream); }
/* With no hero photo the cards follow straight on from the page heading, as one section. */
.page-hero + .section-programs-cream { padding-top: 0; }
/* On the cream section the cards turn sand, as News & Resources cards do, and their icon
   badges turn cream so they still stand out from the card. */
.section-programs-cream .program-card { background: var(--color-sand); border-color: var(--color-sand-2); }
.section-programs-cream .program-card .icon-badge { background: var(--color-cream); }
.program-cards { display: grid; gap: var(--space-5); grid-template-columns: 1fr; }
/* One card surface for the three grids that use it, so a change to the surface
   reaches all of them instead of leaving one behind on the old look. */
.program-card, .opportunity-card, .resource-card { display: flex; flex-direction: column; padding: clamp(28px, 3vw, 40px); background: var(--color-cream); border-radius: var(--radius-lg); border: 1px solid var(--color-line); transition: transform 0.35s var(--ease-out), box-shadow 0.35s var(--ease-out), border-color 0.35s; }
.program-card:hover, .opportunity-card:hover, .resource-card:hover { transform: translateY(-6px); box-shadow: var(--shadow-card); border-color: var(--color-gold); }
.program-title { font-size: var(--step-2); }
.program-desc { color: var(--color-muted); flex: 1; }
.program-links { list-style: none; margin: var(--space-5) 0 0; padding: var(--space-4) 0 0; border-top: 1px solid var(--color-line); }
.program-links li { margin: 0; }
.program-link { display: flex; justify-content: space-between; gap: var(--space-3); padding: 10px 0; font-weight: 700; text-decoration: none; line-height: 1.35; }
.program-link svg { flex: none; width: 18px; transition: transform 0.35s var(--ease-out); }
.program-link:hover svg { transform: translateX(5px); }
.program-note { padding: 10px 0; color: var(--color-muted); font-size: var(--step--1); }
/* A note under a program link qualifies that link, so it sits close beneath it. */
.program-links li + .program-note { padding-top: 0; }

/* Opportunity cards (home only). Shares the .program-card look above (a
   distinct .opportunity-card class keeps them out of the built site's
   `.program-card` counts, which several tests use to assert exactly the
   four real programme cards). The cards are a carousel rather than a card
   grid, a single row that scrolls and snaps card by card. */
.section-opportunities { background: var(--color-forest); color: var(--color-on-dark); }
.section-opportunities .section-title { color: var(--color-on-dark); }
.carousel-header { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--space-4) var(--space-5); }
.carousel-header .section-title { margin-bottom: 0; }
.carousel-controls { display: flex; gap: var(--space-3); margin-left: auto; }
.carousel-btn { display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; padding: 0; border-radius: 50%; border: 1.5px solid var(--color-cream); background: transparent; color: var(--color-cream); cursor: pointer; transition: background-color 0.2s, color 0.2s, opacity 0.2s; }
.carousel-btn[hidden] { display: none; }
.carousel-btn .icon { width: 22px; height: 22px; }
.carousel-btn:hover:not(:disabled) { background: var(--color-cream); color: var(--color-forest); }
.carousel-btn:disabled { opacity: 0.4; cursor: default; }
/* The scroller clips both axes, so the padding gives the card hover lift and its
   shadow room, and the matching negative margin keeps the cards on the container
   edges. scroll-padding-inline lines each snapped card up with that edge. */
.carousel-track { display: flex; gap: var(--space-5); overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; scroll-padding-inline: var(--space-4); padding: var(--space-3) var(--space-4) var(--space-6); margin: var(--space-5) calc(-1 * var(--space-4)) calc(-1 * var(--space-6)); scrollbar-width: none; }
.carousel-track::-webkit-scrollbar { display: none; }
.carousel-track > * { flex: 0 0 auto; width: 85%; scroll-snap-align: start; }
.carousel-track:focus-visible, .carousel-btn:focus-visible { outline: 3px solid var(--color-gold); outline-offset: 3px; box-shadow: none; }
@media (min-width: 640px) {
  .carousel-track > * { width: calc((100% - var(--space-5)) / 2); }
}
@media (min-width: 1100px) {
  .carousel-track > * { width: calc((100% - 2 * var(--space-5)) / 3); }
}
/* The cards are cream inside a forest section, so they reset the inherited
   near-white text. Without this, anything added to a card later that does not
   set its own colour would render light on light. */
.opportunity-card { color: var(--color-ink); }
.opportunity-card .program-title a { color: var(--color-forest); text-decoration: none; }
.opportunity-card .program-title a:hover { color: var(--color-forest-deep); text-decoration-thickness: 2px; }
.opportunity-card .status-pill { margin: 0 0 var(--space-4); }
.opportunity-audience { flex: 1; color: var(--color-muted); margin: 0 0 var(--space-5); }
.opportunity-card .btn-row { margin-top: 0; }

/* Photo carousel (Our Programs). Without JavaScript it is a row that scrolls and snaps
   photo by photo. photo-carousel.js adds .is-ready, and the slides then stack in one
   grid cell and move by their --pos, so three show with the middle one in focus. Every
   photo is shown whole, never cropped, with its own corners rounded. It fits inside a
   row of one height (a 4:3 box at the slide's width) and is centred there, so the
   captions line up whatever shape the photo is. --w is the focused photo's width, --s how far the side photos
   shrink and --g the gap between them, all in the carousel's own width. */
.section-photos .section-title { text-align: center; margin-inline: auto; margin-bottom: var(--space-7); }
.photo-carousel { position: relative; container-type: inline-size; --w: 72cqw; --s: 0.85; --g: 3cqw; }
.photo-track { display: flex; gap: var(--space-5); overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; scrollbar-width: none; }
.photo-track::-webkit-scrollbar { display: none; }
/* WordPress puts the <img> straight in the <figure> and the static site wraps it in a
   <picture>, so the picture steps aside and the image is the grid item either way. */
.photo-slide { flex: 0 0 var(--w); display: grid; grid-template-rows: calc(var(--w) * 0.75) auto; margin: 0; scroll-snap-align: center; }
.photo-slide picture { display: contents; }
.photo-slide img { display: block; align-self: center; justify-self: center; width: auto; height: auto; max-width: 100%; max-height: 100%; border-radius: var(--radius-md); -webkit-user-drag: none; }
.photo-slide figcaption { margin-top: var(--space-3); text-align: center; font-size: var(--step--1); line-height: 1.4; color: var(--color-muted); }
.photo-carousel.is-ready .photo-track { display: grid; overflow: clip; scroll-snap-type: none; touch-action: pan-y; user-select: none; }
.photo-carousel.is-ready .photo-slide { --scale: var(--s); grid-area: 1 / 1; justify-self: center; width: var(--w); transform: translateX(calc(var(--pos, 0) * (var(--w) * (1 + var(--s)) / 2 + var(--g)))) scale(var(--scale)); transition: transform 0.6s var(--ease-out), opacity 0.6s var(--ease-out), visibility 0.6s; }
.photo-carousel.is-ready .photo-slide[data-state="current"] { --scale: 1; opacity: 1; z-index: 1; }
.photo-carousel.is-ready .photo-slide[data-state="current"] figcaption { color: var(--color-ink); font-weight: 500; }
.photo-carousel.is-ready .photo-slide[data-state="side"] { opacity: 0.55; cursor: pointer; }
.photo-carousel.is-ready .photo-slide[data-state="side"]:hover { opacity: 0.8; }
/* On a phone the side photos are only a sliver, so their captions would be cut off. */
.photo-carousel.is-ready .photo-slide[data-state="side"] figcaption { visibility: hidden; }
.photo-carousel.is-ready .photo-slide[data-state="off"] { opacity: 0; visibility: hidden; pointer-events: none; }
/* The shared round button is drawn for the forest opportunities band, so on the cream
   section it turns forest. It sits over the middle of the photo frames, not the captions. */
.photo-btn { border-color: var(--color-forest); color: var(--color-forest); background: var(--color-cream); }
.photo-btn:hover:not(:disabled) { background: var(--color-forest); color: var(--color-cream); }
.photo-btn:focus-visible { box-shadow: 0 0 0 3px var(--color-forest); }
.photo-carousel.is-ready .photo-btn { position: absolute; z-index: 2; top: calc(var(--w) * 0.375); translate: 0 -50%; }
.photo-prev { left: var(--space-2); }
.photo-next { right: var(--space-2); }
@media (min-width: 700px) {
  /* Wide enough that the side photos reach the container edges, lining up with the
     content above. 50 + w/2 + g + s * w comes to 99.5% of the width. */
  .photo-carousel { --w: 37.5cqw; --s: 0.78; --g: 1.5cqw; }
  .photo-carousel.is-ready .photo-slide[data-state="side"] figcaption { visibility: visible; }
  .photo-prev { left: 0; }
  .photo-next { right: 0; }
}
@media (min-width: 1280px) {
  /* The page gutter is 64px from here, so the buttons step out of the container into
     it and leave the photos clear. Below this they overlap the side photos' edges. */
  .photo-prev { left: calc(-1 * (44px + var(--space-4))); }
  .photo-next { right: calc(-1 * (44px + var(--space-4))); }
}
@media (prefers-reduced-motion: reduce) {
  .photo-carousel.is-ready .photo-slide { transition: none; }
}

/* Program status pills, on the opportunity cards. Open registration is a filled
   forest pill, a program still in development an outlined gold one. */
.status-pill { display: inline-flex; align-self: flex-start; align-items: center; gap: var(--space-2); padding: 6px 14px; border-radius: 999px; font-size: var(--step--1); font-weight: 700; line-height: 1.3; }
.status-pill-icon { display: inline-flex; flex: none; }
.status-pill-icon .icon { width: 18px; height: 18px; }
.status-pill-open, .status-pill-staff, .status-pill-board { background: var(--color-forest); color: var(--color-cream); border: 1.5px solid var(--color-forest); }
.status-pill-developing { background: transparent; border: 1.5px solid var(--color-gold); color: var(--color-ink); }

/* Resource cards, the external items on Community News and Resources. The card
   surface itself is the shared one above. Each card carries one third-party
   destination, so the link sits on its own footer row with the new-tab icon, and a
   dated item wears a gold frame and an ember date line instead of a decorative
   strip. A page of these sections alternates sand and cream so a long run of cards
   does not read as one flat colour, and on a cream section the cards take the sand
   surface so they stay a distinct shape. */
.section-resources-sand { background: var(--color-sand); }
.section-resources-cream { background: var(--color-cream); }
.section-resources-cream .resource-card { background: var(--color-sand); border-color: var(--color-sand-2); }
.resource-section-head { display: flex; align-items: center; gap: var(--space-4); margin-bottom: var(--space-6); }
.resource-section-head .icon-badge { margin-bottom: 0; }
.resource-section-head .section-title { margin-bottom: 0; }
.resource-cards { display: grid; gap: var(--space-5); grid-template-columns: 1fr; }
.resource-title { font-size: var(--step-1); margin-bottom: var(--space-3); }
.resource-meta { font-size: var(--step--1); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-muted); margin: 0 0 var(--space-4); }
.resource-body { color: var(--color-muted); flex: 1; }
.resource-body > :last-child { margin-bottom: 0; }
.resource-link-row { margin: var(--space-5) 0 0; padding-top: var(--space-4); border-top: 1px solid var(--color-line); }
.resource-link { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); font-weight: 700; line-height: 1.35; text-decoration: none; }
.resource-link-label { text-decoration: underline; text-underline-offset: 0.18em; text-decoration-thickness: 1px; }
.resource-link:hover .resource-link-label { text-decoration-thickness: 2px; }
.resource-link-icon { flex: none; transition: transform 0.35s var(--ease-out); }
.resource-link:hover .resource-link-icon { transform: translate(2px, -2px); }
.resource-card.is-deadline { border-color: var(--color-gold); border-width: 2px; }
.resource-deadline { display: flex; align-items: flex-start; gap: var(--space-2); font-weight: 700; color: var(--color-ember); margin: 0 0 var(--space-4); }
.resource-deadline .icon { flex: none; margin-top: 0.2em; }

/* Section nav, the labelled list of a page's own sections. The links are plain
   anchors onto real ids, so they work with JavaScript off. It is a shallow sand
   band, so it carries the page's alternating rhythm on rather than adding a third
   cream section to the top of it, and the band is the list's container, which is
   why the list itself takes no frame of its own. Its title is an H2 so the nav
   keeps a name and a place in the page outline, styled down to the eyebrow size,
   which is what the statement band does with its own heading. */
.section-nav { padding-block: var(--space-6); background: var(--color-sand); }
/* The nav belongs to the intro above it, so it sits close under it rather than a
   full section apart. A browser without :has() simply leaves the usual section gap. */
.section-prose:has(+ .section-nav) { padding-bottom: var(--space-6); }
/* The jump nav is a row of links, not prose, so it takes the container width rather
   than the 68ch prose measure. Capping it at the measure pushed the fourth link,
   "Seniors’ health and safety", onto a second row by itself. The list still wraps,
   so narrow viewports break the row instead of overflowing it. */
.jump-nav { max-width: none; }
.jump-nav-title { font-family: var(--font-body); font-weight: 700; font-size: var(--step--1); letter-spacing: 0.14em; text-transform: uppercase; color: var(--color-muted); margin-bottom: var(--space-3); }
.jump-nav ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-5); }
.jump-nav li { margin: 0; }

/* Media split (image on one side, prose content on the other) */
.media-split-inner { display: grid; gap: var(--space-6); }
.media-split-media { margin: 0; border-radius: var(--radius-lg); overflow: hidden; aspect-ratio: 4 / 3; background: var(--color-sand); }
.media-split-media img, .media-split-media picture { width: 100%; height: 100%; object-fit: cover; }
/* A portrait source photo keeps a tall frame at every width, so the default
   landscape crop never cuts its subject off on a narrow screen. */
.media-split-portrait .media-split-media { aspect-ratio: 3 / 4; }
.media-split-sand { background: var(--color-sand); }
.media-split-sand .media-split-media { background: var(--color-sand-2); }
.media-split-sub + .media-split-sub { margin-top: var(--space-6); padding-top: var(--space-6); border-top: 1px solid var(--color-line); }
.media-split-sub-title { margin-bottom: 0.5em; }
.media-split-content .icon-list { list-style: none; margin: var(--space-5) 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-3); }
.media-split-content .icon-list li::marker { content: none; }
.icon-list-item { display: flex; align-items: flex-start; gap: var(--space-3); }
.icon-list-item .icon-list-icon { color: var(--color-forest); margin-top: 0.15em; }
@media (min-width: 900px) {
  .media-split-inner { grid-template-columns: 1fr 1fr; align-items: start; gap: var(--space-8); }
  .media-split-media { aspect-ratio: 4 / 5; position: sticky; top: calc(var(--header-h) + var(--space-6)); }
  .media-split-portrait .media-split-media { aspect-ratio: 3 / 4; }
  /* The photo stays at the top and sticks while long copy scrolls, and short copy sits centred beside it. */
  .media-split-content { align-self: center; }
  .media-split-right .media-split-media { order: 2; }
  .media-split-right .media-split-content { order: 1; }
}

/* Statement (closing full-width band) */
.section-statement { background: var(--color-sand); }
.statement-inner { padding-block: var(--section-pad); text-align: center; }
.statement-inner .icon.statement-quote { width: 40px; height: 40px; color: var(--color-gold-deep); margin-inline: auto; }
/* An authored heading, styled as an eyebrow. The heading resets keep the look identical to the paragraph it replaced. */
.statement-eyebrow { font-family: var(--font-body); font-size: var(--step--1); font-weight: 700; line-height: inherit; letter-spacing: 0.14em; text-transform: uppercase; font-variation-settings: normal; color: var(--color-forest); margin: var(--space-4) 0 0; }
.statement-body { max-width: 60ch; margin-inline: auto; text-align: center; font-family: var(--font-heading); font-size: var(--step-2); line-height: 1.35; color: var(--color-forest); }
.statement-body p { margin-bottom: 1em; }
.statement-body > :last-child { margin-bottom: 0; }
.statement-body .btn-row { justify-content: center; }
.statement-forest-deep { background: var(--color-forest-deep); }
.statement-forest-deep .statement-body { color: var(--color-on-dark); }
.statement-forest-deep .statement-eyebrow { color: var(--color-gold); }
.statement-forest-deep .icon.statement-quote { color: var(--color-gold); }

/* Split intro (heading left, body and buttons right) */
.section-split-intro { position: relative; overflow: hidden; background: var(--color-sand); }
.split-intro-accent {
  display: none; position: absolute; top: 0; right: 0; bottom: 0; width: 16px;
  background: url("../img/pattern-band.svg") repeat-y left top / 48px 24px;
  opacity: 0.9; pointer-events: none;
}
.split-intro-inner { position: relative; z-index: 1; display: grid; gap: var(--space-6); }
.split-intro-heading { font-size: var(--step-4); max-width: 14ch; margin: 0; }
.split-intro-body > :last-child { margin-bottom: 0; }
@media (min-width: 900px) {
  .split-intro-inner { grid-template-columns: 1fr 1fr; align-items: start; gap: var(--space-8); }
  .split-intro-accent { display: block; }
}

/* Values grid (balanced icon-card grid, no lone widow) */
.values-grid-sand { background: var(--color-sand); }
.values-grid-list { list-style: none; margin: var(--space-6) 0 0; padding: 0; display: grid; gap: var(--space-5); grid-template-columns: 1fr; }
.value-grid-card { padding: clamp(24px, 3vw, 32px); background: var(--color-cream); border: 1px solid var(--color-line); border-radius: var(--radius-lg); text-align: center; transition: transform 0.35s var(--ease-out), box-shadow 0.35s var(--ease-out); }
.value-grid-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-card); }
.value-grid-card .icon-badge { margin-inline: auto; }
.value-grid-text { font-family: var(--font-heading); font-size: var(--step-1); color: var(--color-forest); margin: 0; }

/* Process steps (connected sequence, no numbers) */
.process-steps { list-style: none; margin: var(--space-7) 0 0; padding: 0; position: relative; display: flex; flex-direction: column; gap: var(--space-6); }
.process-steps::before { content: ""; position: absolute; left: 23px; top: 0; bottom: 0; width: 2px; background: var(--color-line); }
.process-step { position: relative; display: flex; gap: var(--space-4); align-items: flex-start; }
/* The node sits on the connector line, and the step's own gap spaces the text. */
.process-node { margin-bottom: 0; }
.process-text { margin: 0; padding-top: 10px; }
@media (min-width: 900px) {
  .process-steps { flex-direction: row; gap: var(--space-5); }
  .process-steps::before { left: 24px; right: 24px; top: 23px; bottom: auto; width: auto; height: 2px; }
  .process-step { flex: 1; flex-direction: column; align-items: center; text-align: center; }
  .process-text { padding-top: 0; margin-top: var(--space-4); }
}

/* Callout (audience, note, status variants) */
/* Callouts in a row read as one group of cards, so they sit a card gap apart
   rather than a full section apart. */
.section-callout:has(+ .section-callout) { padding-bottom: var(--space-6); }
/* The icon sits beside the title on one row and the body runs full width below. */
.callout-card { display: grid; grid-template-columns: auto 1fr; align-items: center; column-gap: var(--space-4); padding: clamp(28px, 4vw, 40px); border-radius: var(--radius-lg); }
.callout-card > * { grid-column: 1 / -1; margin-block: 0; }
.callout-card > .callout-icon { grid-column: 1; }
.callout-card > .callout-icon + .callout-title { grid-column: 2; }
.callout-card > .callout-body { margin-top: var(--space-4); }
.callout-icon { display: inline-flex; align-items: center; justify-content: center; color: var(--color-forest); }
.callout-title { margin-bottom: 0; }
.callout-body > :last-child { margin-bottom: 0; }
.callout-audience { background: var(--color-sand); }
.callout-audience .callout-icon { --badge-size: 56px; }
.callout-audience .callout-body { font-size: var(--step-1); }
/* Note carries the program and service boundary statements, so it reads at body size
   on its own sand surface rather than as a footnote on the cream section behind it. */
.callout-note { background: var(--color-sand); border: 1px solid var(--color-line); }
.callout-note .callout-icon { width: 28px; height: 28px; }
.callout-note .callout-body { font-size: var(--step-0); color: var(--color-muted); }
.callout-status { background: var(--color-forest); color: var(--color-on-dark); }
.callout-status .callout-title { color: var(--color-on-dark); }
/* The status badge matches the audience one in size, as a faint cream disc on the forest. */
.callout-status .callout-icon { --badge-size: 56px; background: rgba(251, 247, 239, 0.12); color: var(--color-gold); }
/* Register runs the full width of the card, under the description. */
.callout-status .callout-body > .btn-row > * { flex: 1; justify-content: center; }

/* Highlight (full-width forest band inside the page flow) */
.section-highlight { background: var(--color-forest); color: var(--color-on-dark); }
/* The closing cta-band is forest too, so a page that ends on a highlight asks for
   the deeper forest and the two bands stay apart. */
.highlight-forest-deep { background: var(--color-forest-deep); }
.highlight-inner { padding-block: var(--section-pad); text-align: center; }
.highlight-icon { margin-inline: auto; }
.highlight-heading { color: var(--color-on-dark); max-width: 22ch; margin-inline: auto; }
.highlight-body { max-width: 52ch; margin-inline: auto; font-size: var(--step-1); color: var(--color-on-dark-muted); }
.highlight-body > :last-child { margin-bottom: 0; }
/* The body is centred, so its buttons are too, and a ghost button turns light on the forest. */
.highlight-body .btn-row { justify-content: center; }
.highlight-forest .btn-ghost, .highlight-forest-deep .btn-ghost { --btn-fg: var(--color-on-dark); border-color: var(--color-on-dark); }
.highlight-forest .btn-ghost:hover, .highlight-forest-deep .btn-ghost:hover { --btn-bg: var(--color-on-dark); --btn-fg: var(--color-forest); }

/* Table of contents layout for long prose pages, turned on with the toc front matter key */
.toc-mobile { margin-bottom: var(--space-6); border: 1px solid var(--color-line); border-radius: var(--radius-md); padding: var(--space-4) var(--space-5); }
.toc-mobile summary { cursor: pointer; font-weight: 700; color: var(--color-forest); }
.toc-mobile nav ul { list-style: none; margin: var(--space-4) 0 0; padding: 0; }
.toc-mobile nav li { margin-bottom: var(--space-2); }
.toc-sidebar { display: none; }
@media (min-width: 1024px) {
  .toc-mobile { display: none; }
  .toc-container { display: grid; grid-template-columns: 240px 1fr; gap: var(--space-8); align-items: start; }
  .toc-sidebar { display: block; position: sticky; top: calc(var(--header-h) + var(--space-6)); }
  .toc-sidebar-title { font-weight: 700; font-size: var(--step--1); letter-spacing: 0.14em; text-transform: uppercase; color: var(--color-muted); margin-bottom: var(--space-4); }
  .toc-sidebar ul { list-style: none; margin: 0; padding: 0; }
  .toc-sidebar li { margin-bottom: var(--space-2); }
  .toc-sidebar a { display: block; padding: 8px 0 8px var(--space-4); color: var(--color-ink); text-decoration: none; border-left: 2px solid var(--color-line); }
  .toc-sidebar a:hover { color: var(--color-forest); border-left-color: var(--color-forest); font-weight: 700; }
}

/* Contact form */
.contact-layout { display: grid; gap: clamp(32px, 5vw, 72px); align-items: start; }
.contact-form { margin-top: 0; padding: clamp(24px, 4vw, 48px); background: var(--color-sand); border-radius: var(--radius-lg); }
.form-grid { display: grid; gap: var(--space-5); grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr)); }
.field { display: flex; flex-direction: column; gap: var(--space-2); margin: 0 0 var(--space-5); border: 0; padding: 0; min-width: 0; }
.field label, .field legend { font-weight: 700; font-size: var(--step--1); color: var(--color-ink); }
.req { color: var(--color-ember); }
.field input, .field textarea { font: inherit; padding: 14px 16px; border: 1.5px solid var(--color-muted); border-radius: var(--radius-md); background: var(--color-cream); color: var(--color-ink); transition: border-color 0.2s, box-shadow 0.2s; }
.field input:focus, .field textarea:focus { outline: none; border-color: var(--color-forest); box-shadow: 0 0 0 2px var(--color-forest), 0 0 0 5px var(--color-gold); }
.field [aria-invalid="true"] { border-color: var(--color-ember); }
.checks { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); margin-top: var(--space-3); }
.check { display: flex; gap: var(--space-3); align-items: flex-start; font-weight: 500 !important; cursor: pointer; }
.check input { width: 20px; height: 20px; margin-top: 3px; accent-color: var(--color-forest); flex: none; }
.form-privacy { font-size: var(--step--1); color: var(--color-muted); }
.form-status { font-weight: 700; color: var(--color-forest); min-height: 1.5em; }

/* The Turnstile spam check, between the last field and the Submit button.
   Turnstile renders its own widget into this box and will not draw it narrower than
   300px, which is wider than the inside of the sand form card on a small phone. Under
   400px the widget is scaled down from its top left corner, so it stays inside the
   card and the page keeps its single column instead of gaining a sideways scroll. */
.form-check { margin-top: var(--space-6); --turnstile-scale: 0.78; }
.form-check .cf-turnstile { transform: scale(var(--turnstile-scale)); transform-origin: left top; }
.form-check .form-privacy { margin-top: var(--space-3); }
@media (min-width: 400px) { .form-check { --turnstile-scale: 1; } }
/* The shared button rule takes pointer events away from anything marked aria-disabled,
   which inside this form would leave a visitor clicking Submit with nothing happening
   and nothing said. The button stays clickable here so the submit handler in form.js
   can answer that the spam check is still outstanding. */
.contact-form .btn[aria-disabled="true"] { pointer-events: auto; cursor: not-allowed; }

/* Registration forms. One column, since the forms are long and read top to bottom. */
.registration-layout { max-width: 820px; }
.registration-copy { margin-bottom: var(--space-6); }
.form-section + .form-section { margin-top: var(--space-7); }
.form-section-title { font-size: var(--step-2); margin: 0 0 var(--space-4); }
.field-help { margin: 0; font-size: var(--step--1); color: var(--color-muted); }
.field-single .field-help { margin-left: calc(20px + var(--space-3)); }
.form-note { margin: 0 0 var(--space-5); }

/* Card grids, which never leave a dead column or a widow.
   Every card grid fills each of its rows. A grid is one column on phones, and
   above its own breakpoint its track becomes twelve columns while each card
   declares the share of a row it takes. A short row stretches across the full
   width, so no row is left with empty columns and no card is left alone on a
   row it does not fill. The shares are computed by _grid_rows in sections.py,
   which is the one place row sizes are decided.

   Widths. Phones stay one column. The grids that open out widen in three steps,
   and each step is where the arithmetic first allows it. Two across from 640px.
   Three across from 900px, where a third of an 810px container is 254px, the
   width the user reviewed and accepted; at 899px the same row would be 253.7px,
   so 900px is the first width that clears it. The full declared spans from
   1280px, because a count that leads with a row of four puts a card at a quarter
   of the track, which is 212px at 1024px and 270px at 1280px.

   The rest keep the widths they already had, 720px for programme and numbered
   cards and 900px for the longer resource cards. Both of those pair up two
   across.

   A grid that pairs up has one card left over at an odd count. From 900px that
   card joins the two before it in a row of three, the same width the wider grids
   go three across at. Below 900px three abreast is too narrow, so between 720px
   and 899px the odd card stretches across its row instead, which is the one place
   a card is still alone on a row.

   --card-span, --card-span-md and --card-span-sm are what a card declares, one
   per step. --card-grid-span is the one the grid is using at the current width,
   which is why it is set inside the media queries and read by the single rule
   above them. */
.card-grid > * { grid-column: span var(--card-grid-span, 1); }

@media (min-width: 640px) {
  .checklist, .features, .values-grid-list { grid-template-columns: repeat(12, 1fr); }
  .checklist > *, .features > *, .values-grid-list > * { --card-grid-span: var(--card-span-sm, 12); }
}

@media (min-width: 720px) {
  .program-cards, .numbered-cards { grid-template-columns: repeat(12, 1fr); }
  /* An odd card stretches across its row here, and only a grid that has one
     declares the second span, so the rest fall through to their halves. */
  .program-cards > *, .numbered-cards > * { --card-grid-span: var(--card-span-sm, var(--card-span, 12)); }
}

@media (min-width: 900px) {
  .checklist > *, .features > *, .values-grid-list > * { --card-grid-span: var(--card-span-md, 12); }
  /* The declared span, where an odd row is three across rather than one stretched card. */
  .program-cards > *, .numbered-cards > * { --card-grid-span: var(--card-span, 12); }
  .resource-cards { grid-template-columns: repeat(12, 1fr); }
  .resource-cards > * { --card-grid-span: var(--card-span, 12); }
}

@media (min-width: 1280px) {
  .checklist > *, .features > *, .values-grid-list > * { --card-grid-span: var(--card-span, 12); }
}

.page-hero + .section-form { padding-top: 0; }
@media (min-width: 900px) {
  .contact-layout { grid-template-columns: 1fr 1fr; }
  .contact-copy { position: sticky; top: calc(var(--header-h) + var(--space-6)); }
}
