/* 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
   callout 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); }

/* 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); }
.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); }
.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); }

/* 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 grid is its own class so three cards can
   settle into one row on desktop. Programme cards pair up instead, which is
   decided by max_per_row=2 in sections.py rather than by any cap here. */
.section-opportunities { background: var(--color-forest); color: var(--color-on-dark); }
.section-opportunities .section-title { color: var(--color-on-dark); }
.opportunity-cards { display: grid; gap: var(--space-5); grid-template-columns: 1fr; margin-top: var(--space-6); }
/* 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-status { font-size: var(--step--1); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-muted); margin: 0 0 var(--space-3); }
.opportunity-audience { flex: 1; color: var(--color-muted); margin: 0 0 var(--space-5); }
.opportunity-card .btn-row { margin-top: 0; }

/* 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-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) */
.callout-card { padding: clamp(28px, 4vw, 40px); border-radius: var(--radius-lg); }
.callout-icon { display: inline-flex; align-items: center; justify-content: center; margin-bottom: var(--space-4); color: var(--color-forest); }
.callout-title { margin-bottom: 0.5em; }
.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); }
.callout-status .callout-icon { width: 40px; height: 40px; color: var(--color-gold); }

/* 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; }

/* 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-narrow { max-width: 280px; }
.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; }

/* 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.

   Opportunity cards run on that same three-step schedule. They used to go three
   across from 720px, which put each of them at 214px at 768px, well under the
   254px floor, on the most prominent new section of the home page.

   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, .opportunity-cards { grid-template-columns: repeat(12, 1fr); }
  .checklist > *, .features > *, .values-grid-list > *, .opportunity-cards > * { --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 > *, .opportunity-cards > * { --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 > *, .opportunity-cards > * { --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)); }
}
