/* ==========================================================================
   K-BIAN — Shared inner-page components

   The design-language primitives every page after the home page follows (see
   CLAUDE.md's Design language section): the section-heading pattern, the
   full-bleed hero, the image band. Sections 0-3 were moved out of home.css
   verbatim when /about, /programmes and /kakamega-forest were built, so the
   home page and every inner page share one definition rather than three
   copies drifting apart. Sections 4 onward are new components those three
   pages introduced, kept here rather than duplicated per page file because
   later pages will need the same breadcrumb, badge, avatar and accordion
   treatment.

   Mobile-first. Every colour comes from tokens.css.
   ========================================================================== */

/* ==========================================================================
   0. Shared section-heading pattern — CLAUDE.md's Page composition standard,
      rule 2, exact and non-negotiable:

        eyebrow -> 16px -> h2 -> 12px -> deck -> 24px -> gold rule -> 40px -> content

      The deck sits BETWEEN the h2 and the gold rule — not after it. A bare
      h2 sitting directly on a paragraph, with no deck, is banned; write a
      real deck (one specific sentence) for every section on every page.
   ========================================================================== */

.section-eyebrow {
    display: block;
    font-family: var(--kb-font-heading);
    font-size: var(--fs-eyebrow);
    font-weight: var(--kb-weight-bold);
    text-transform: uppercase;
    letter-spacing: var(--kb-tracking-caps);
    color: var(--kb-green-600);
    margin-block-end: 1rem; /* 16px, exact per spec */
}

.section-title {
    margin-block-end: 0.75rem; /* 12px to the deck, exact per spec */
}

/* The deck: 21px, one specific sentence, max 60ch. */
.section-deck {
    max-width: 60ch;
    margin-block-end: 1.5rem; /* 24px to the gold rule, exact per spec */
    font-size: 1.3125rem; /* 21px */
    line-height: var(--lh-lead);
    color: var(--kb-green-700);
}

/* The gold rule sits after the deck now, as its own element rather than a
   heading pseudo-element, since it no longer sits flush under the h2. */
.section-rule {
    display: block;
    width: 2.875rem; /* 46px */
    height: 3px;
    margin-block-end: 2.5rem; /* 40px to the section's real content */
    background-color: var(--kb-rule);
    border-radius: var(--kb-radius-pill);
}

/* A section header with no deck (e.g. Vision and Mission, which the client
   asked to have its deck removed as not relevant) would otherwise sit the
   rule only 12px under the h2 — the margin meant for h2-to-deck, not
   h2-to-rule. Widen the gap when the rule directly follows the title. */
.section-title + .section-rule {
    margin-block-start: 1.5rem; /* 24px, matching the deck-to-rule gap */
}

/* Kept as an alias for older markup that still expects the lead directly
   under the h2 with no deck/rule pair (e.g. a card's own internal heading,
   not a full section header) — same size as the deck. */
.section-lead {
    max-width: 60ch;
    font-size: 1.3125rem;
    line-height: var(--lh-lead);
    color: var(--kb-green-700);
}

/* A section header sitting on a dark band needs the same classes, just
   re-coloured for the dark surface — see .page-section--dark below. */
.page-section--dark .section-eyebrow {
    color: var(--kb-gold-400);
}

.page-section--dark .section-deck,
.page-section--dark .section-lead {
    color: var(--kb-cream);
    opacity: 0.85;
}

/* ==========================================================================
   1. Hero — full-bleed photo, dark scrim, light text
   ========================================================================== */

.hero {
    position: relative;
    display: flex;
    align-items: flex-end;
    min-height: 80vh;
    overflow: hidden;
}

.hero__image {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Dark on the text side, breathing room for the photo on the other —
   deliberately not a flat top-to-bottom fade. Built from --kb-green-900-rgb
   rather than a literal rgba(42,48,24,...): same colour, but it stays tied
   to the one file that owns it. */
.hero__scrim {
    position: absolute;
    inset: 0;
    background: linear-gradient(
        105deg,
        rgb(var(--kb-green-900-rgb) / 0.94),
        rgb(var(--kb-green-900-rgb) / 0.72) 52%,
        rgb(var(--kb-green-900-rgb) / 0.25)
    );
}

.hero__content {
    position: relative;
    z-index: var(--kb-z-raised);
    padding-block: var(--kb-space-2xl) var(--kb-space-3xl);
}

.hero__eyebrow {
    display: block;
    font-family: var(--kb-font-heading);
    font-size: var(--fs-eyebrow);
    font-weight: var(--kb-weight-bold);
    text-transform: uppercase;
    letter-spacing: var(--kb-tracking-caps);
    color: var(--kb-gold-400);
    margin-block-end: var(--kb-space-sm);
}

.hero__title {
    max-width: 20ch;
    color: var(--kb-white);
}

.hero__title mark {
    background: none;
    color: var(--kb-gold-400);
}

.hero__lede {
    max-width: 46ch;
    margin-block-start: var(--kb-space-sm);
    font-size: var(--fs-lead);
    line-height: var(--lh-lead);
    color: var(--kb-cream);
}

/* Inner-page hero intro paragraph — per the Page composition standard's
   Hero pattern (rule 5): 20px, max 62ch, wider than the home hero's 46ch
   sub-line because inner pages don't also carry two CTA buttons directly
   beneath it. */
.hero__intro {
    max-width: 62ch;
    margin-block-start: var(--kb-space-sm);
    font-size: 1.25rem; /* 20px */
    line-height: var(--lh-lead);
    color: var(--kb-cream);
}

.hero__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--kb-space-sm);
    margin-block-start: var(--kb-space-lg);
}

/* Photo credit, bottom-right of the hero — per the Hero pattern rule. */
.hero__credit {
    position: absolute;
    inset-block-end: var(--kb-space-sm);
    inset-inline-end: var(--kb-gutter);
    z-index: var(--kb-z-raised);
    font-size: var(--fs-small);
    color: var(--kb-cream);
    opacity: 0.6;
}

/* A shorter hero for inner pages that follow with a breadcrumb trail —
   80vh of photo before any body copy reads as too much once the page also
   has a breadcrumb and isn't the home page's first impression. */
.hero--inner {
    min-height: 52vh;
}

/* ==========================================================================
   1b. Key facts sit straight below an inner-page hero, so the page's key
       numbers are visible before the reader scrolls past it — see
       .key-facts in components.css.
   ========================================================================== */

/* ==========================================================================
   2. Full-bleed image band — breaks out of the container between sections
   ========================================================================== */

/* Capped at 460px so no single full-bleed image band ever takes over a
   section, regardless of viewport width — object-fit crops the rest. */
.image-band {
    position: relative;
    height: clamp(17.5rem, 32vw, 26rem); /* 280px -> 416px */
    max-height: 28.75rem; /* 460px */
    overflow: hidden;
}

.image-band img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
}

/* A corner scrim, not a flat wash: guarantees a dark reading zone behind the
   caption regardless of what the photo happens to show there, rather than
   hoping a single bottom-to-top fade lands somewhere dark. */
.image-band__scrim {
    position: absolute;
    inset: 0;
    background:
        linear-gradient(100deg, rgb(var(--kb-green-900-rgb) / 0.88) 0%, rgb(var(--kb-green-900-rgb) / 0.4) 38%, rgb(var(--kb-green-900-rgb) / 0) 62%),
        linear-gradient(0deg, rgb(var(--kb-green-900-rgb) / 0.5) 0%, rgb(var(--kb-green-900-rgb) / 0) 55%);
}

.image-band__content {
    position: absolute;
    inset-block-end: var(--kb-space-xl);
    inset-inline-start: var(--kb-gutter);
    inset-inline-end: var(--kb-gutter);
    max-width: 26rem;
}

.image-band__eyebrow {
    display: block;
    font-family: var(--kb-font-heading);
    font-size: var(--fs-eyebrow);
    font-weight: var(--kb-weight-bold);
    text-transform: uppercase;
    letter-spacing: var(--kb-tracking-caps);
    color: var(--kb-gold-400);
    margin-block-end: var(--kb-space-2xs);
}

.image-band__caption {
    font-family: var(--kb-font-heading);
    font-size: var(--fs-h3);
    font-weight: var(--kb-weight-semibold);
    line-height: var(--lh-h3);
    color: var(--kb-white);
    text-shadow: 0 2px 12px rgb(var(--kb-green-900-rgb) / 0.85);
}

/* ==========================================================================
   3. Page section rhythm and surface — CLAUDE.md's Rule 3 padding floor,
      and the four alternating surfaces Rule 1 requires. Cream needs no
      class (it is the page background); white, band and dark are below.
      A full-bleed photograph with scrim is the fifth surface — use .hero
      or .image-band for that, not a .page-section variant.
   ========================================================================== */

.page-section {
    padding-block: clamp(4.5rem, 9vw, 7.5rem); /* 72px -> 120px, the floor */
}

.page-section--white {
    background-color: var(--kb-surface);
}

.page-section--band {
    background-color: var(--kb-bg-band);
}

/* Dark band: green-800, distinct from the green-900 hero/footer so the page
   doesn't read as "the same dark" everywhere. Light text throughout — every
   plain-text element needs an explicit override since base.css's defaults
   assume the cream/white surfaces. */
.page-section--dark {
    background-color: var(--kb-green-800);
    color: var(--kb-text-on-deep);
}

.page-section--dark h2,
.page-section--dark h3,
.page-section--dark h4 {
    color: var(--kb-text-on-deep);
}

/* --kb-link (green-700) is illegible on a dark band — reuse the same
   cream already proven for text on --kb-green-900 in the header/footer;
   green-800 is lighter still, so contrast only improves. */
.page-section--dark a:not(.btn) {
    color: var(--kb-text-on-deep);
}

/* ==========================================================================
   4. Breadcrumbs
   ========================================================================== */

.breadcrumbs {
    padding-block: var(--kb-space-sm);
    font-size: var(--fs-small);
}

.breadcrumbs__list {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--kb-space-2xs);
}

.breadcrumbs__list li {
    display: flex;
    align-items: center;
    gap: var(--kb-space-2xs);
}

.breadcrumbs__list li:not(:last-child)::after {
    content: "/";
    color: var(--kb-border);
}

.breadcrumbs a {
    color: var(--kb-text-muted);
}

.breadcrumbs [aria-current="page"] {
    color: var(--kb-text);
    font-weight: var(--kb-weight-medium);
}

/* Sitting directly on the dark hero scrim rather than the cream page bg. */
.breadcrumbs--on-dark {
    color: var(--kb-cream);
}

.breadcrumbs--on-dark a {
    color: var(--kb-cream);
    opacity: 0.75;
}

.breadcrumbs--on-dark a:hover {
    opacity: 1;
}

.breadcrumbs--on-dark [aria-current="page"] {
    color: var(--kb-white);
    opacity: 1;
}

.breadcrumbs--on-dark .breadcrumbs__list li:not(:last-child)::after {
    color: rgb(var(--kb-ink-rgb) / 0.3);
}

/* ==========================================================================
   5. Programme cards and status badge

      Moved out of home.css: the /programmes index uses the identical card,
      and the detail page reuses just the badge — see CLAUDE.md's P07
      carry-forward note, "give it the same badge treatment as the home
      page cards."
   ========================================================================== */

.programme-cards {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--kb-space-lg);
    margin-block-start: var(--kb-space-xl);
}

/* Flex columns inside the grid, so every card in a row is the same height
   and "Learn more" always sits on the same line regardless of copy length. */
.programme-card {
    display: flex;
}

.programme-card__link {
    display: flex;
    flex-direction: column;
    width: 100%;
    background-color: var(--kb-surface);
    border-radius: var(--kb-radius-lg);
    box-shadow: var(--kb-shadow-sm);
    overflow: hidden;
    color: inherit;
    text-decoration: none;
    transition: transform 200ms var(--kb-ease-out), box-shadow 200ms var(--kb-ease-out);
}

.programme-card__link:hover {
    box-shadow: var(--kb-shadow-xl);
    transform: translateY(-3px);
}

.programme-card__image {
    width: 100%;
    height: 12.5rem; /* 200px */
    object-fit: cover;
}

.programme-card__body {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    padding: var(--kb-space-lg);
}

/* Honest, small — K-BIAN is ten months old and most programmes are designed
   rather than running. See CLAUDE.md: never soften this into looking like
   an achievement. */
.programme-card__status {
    display: inline-block;
    align-self: flex-start;
    margin-block-end: var(--kb-space-2xs);
    padding: 0.125rem 0.5rem;
    border-radius: var(--kb-radius-pill);
    font-size: var(--fs-eyebrow);
    font-weight: var(--kb-weight-bold);
    text-transform: uppercase;
    letter-spacing: var(--kb-tracking-caps);
}

.programme-card__status--active {
    background-color: var(--kb-green-100);
    color: var(--kb-green-700);
}

.programme-card__status--in_development {
    background-color: transparent;
    border: var(--kb-border-thin) solid var(--kb-border);
    color: var(--kb-text-muted);
}

.programme-card__title {
    font-size: var(--fs-h3);
    font-weight: var(--kb-weight-semibold);
}

.programme-card__summary {
    margin-block-start: var(--kb-space-2xs);
    color: var(--kb-text-muted);
}

.programme-card__cta {
    display: inline-block;
    margin-block-start: auto;
    padding-block-start: var(--kb-space-md);
    font-weight: var(--kb-weight-semibold);
    color: var(--kb-primary-text);
}

@media (min-width: 40em) { /* 640px */
    .programme-cards {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (min-width: 64em) { /* 1024px */
    .programme-cards {
        grid-template-columns: repeat(3, 1fr);
    }
}

@media (prefers-reduced-motion: reduce) {
    .programme-card__link:hover {
        transform: none;
    }
}

/* ==========================================================================
   6. Page body — the wrapper around a `pages.body` HTML blob (about,
      kakamega-forest and, eventually, the other database-driven pages).
      Deliberately not the generic `.prose` utility in base.css: that caps
      the WHOLE element's max-width, which would also squeeze the full-width
      tables, the value cards and the split-block below down to one narrow
      column. Only flowing text gets the measure cap; structural children
      (table, the split-block/value-cards divs) render at full container
      width.
   ========================================================================== */

.page-body > p,
.page-body > ul,
.page-body > ol {
    max-width: var(--kb-measure);
}

/* ==========================================================================
   6b. Prose reading column — the other half of the "68ch never sits alone
       in a wide container" rule (CLAUDE.md). For a short, genuinely
       text-only block that keeps the wide .container on its siblings (card
       grids, bank panels): narrows itself to a single centred reading
       column instead, so the container stays full width for everything
       else in the section while the prose doesn't sit stranded on one side.
   --------------------------------------------------------------------------
   SUPERSEDES `.prose--columns` (removed, July 2026). That version used CSS
   `columns: 2` to split the same content into two flowing newspaper
   columns. It looked right with evenly-sized paragraphs and broke with
   real content every time: the column-balancing algorithm decides where to
   break based on total content height, not paragraph count, so two or
   three uneven paragraphs routinely ended up split one-per-column with
   mismatched top edges, or with a trailing heading (e.g. get-involved's
   "What your gift funds") stranded alone in an otherwise-empty second
   column. Found three times independently (about's objectives, kakamega-
   forest's wildlife section, get-involved's CFA section) — a single
   reading column has no balancing step, so it cannot reproduce the bug.
   Do not reintroduce `columns: 2` on flowing prose for this reason.
   ========================================================================== */

.prose--reading {
    max-width: var(--kb-container-reading);
    margin-inline: auto;
}

/* Real table treatment per CLAUDE.md's Rule 4: a solid green-800 header
   row (light text), alternating row tint, generous cell padding, the total
   row emphasised rather than just underlined. */
.page-body table {
    width: 100%;
    border-collapse: collapse;
    overflow: hidden;
    font-size: var(--fs-small);
    border-radius: var(--kb-radius-md);
    box-shadow: var(--kb-shadow-sm);
}

.page-body caption {
    padding-block-end: var(--kb-space-sm);
    text-align: start;
    font-size: var(--fs-h3);
    font-family: var(--kb-font-heading);
    font-weight: var(--kb-weight-semibold);
    color: var(--kb-text-heading);
}

.page-body th,
.page-body td {
    padding: var(--kb-space-sm) var(--kb-space-md);
    text-align: start;
}

.page-body thead th {
    background-color: var(--kb-green-800);
    color: var(--kb-text-on-deep);
    font-size: var(--fs-eyebrow);
    text-transform: uppercase;
    letter-spacing: var(--kb-tracking-caps);
}

.page-body tbody tr:nth-child(odd) {
    background-color: var(--kb-bg-band);
}

.page-body tbody tr:nth-child(even) {
    background-color: var(--kb-surface);
}

.page-body tbody th[scope="row"] {
    font-weight: var(--kb-weight-medium);
    color: var(--kb-text-heading);
}

/* The total row: its own solid fill rather than a border, so it reads as
   the answer the table has been building to. */
.page-body tbody tr:last-child {
    background-color: var(--kb-primary);
}

.page-body tbody tr:last-child th,
.page-body tbody tr:last-child td {
    color: var(--kb-text-on-brand);
    font-weight: var(--kb-weight-bold);
}

.page-body .lede {
    font-size: var(--fs-lead);
    line-height: var(--lh-lead);
    color: var(--kb-text-heading);
}

/* ==========================================================================
   7. Asymmetric two-column block — media pinned at 46%, content flexible
      (1fr) beside it. The media column is always the smaller of the two
      regardless of .split-block--reverse: --reverse only reorders which
      side it visually sits on (via :first-child { order: 2 } below), never
      which track gets which width. That is what lets the sticky rule below
      target .split-block__media alone and be correct in both directions.
   ========================================================================== */

.split-block {
    display: grid;
    gap: var(--kb-space-xl); /* 48px */
}

@media (min-width: 56.25em) { /* 900px */
    .split-block {
        grid-template-columns: 46% 1fr;
        align-items: start;
    }

    .split-block--reverse > :first-child {
        order: 2;
    }
}

.split-block__panel {
    padding: var(--kb-space-lg);
    background-color: var(--kb-surface);
    border-radius: var(--kb-radius-lg);
    box-shadow: var(--kb-shadow-sm);
}

.split-block__panel h2,
.split-block__panel h3 {
    margin-block-start: 0;
}

/* The image half of a split-block, bleeding past the container edge — same
   construction as the home page's .kakamega-teaser__media, generalised so
   About's "Who we are" and "Where we work" can use it too (Rule 5:
   asymmetry, image breaking past the container). */
.split-block__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: var(--kb-radius-lg);
}

@media (min-width: 56.25em) { /* 900px */
    .split-block__media {
        margin-inline-start: calc(var(--kb-gutter) * -1);
        /* Pins while the longer content column scrolls past, releasing once
           the two columns' bottoms align — CSS alone, no JS. Capped so a
           short page can never leave the image jammed against the viewport
           bottom, and never taller than the space actually below the
           header. Read the CRITICAL note in CLAUDE.md before touching this:
           it silently does nothing if any ancestor gets overflow or a
           transform added later. */
        position: sticky;
        inset-block-start: calc(var(--kb-header-h) + 1.5rem); /* +24px */
        max-height: calc(100vh - var(--kb-header-h) - 3rem); /* -48px */
    }

    .split-block--reverse .split-block__media {
        margin-inline-start: 0;
        margin-inline-end: calc(var(--kb-gutter) * -1);
    }

    .split-block__media img {
        border-radius: 0;
        max-height: inherit;
    }
}

@media (max-width: 56.1875em) { /* just below 900px: columns have already
                                    stacked via the grid rule above, but
                                    make the release explicit rather than
                                    relying on the sticky rule simply not
                                    having been applied */
    .split-block__media {
        position: static;
    }
}

/* ==========================================================================
   7b. Pull-quotes — Vision and Mission on the dark band. Large, quiet, one
       per column; the gold rule between them is the column gap border, not
       a decorative rule element, so it only appears once the layout is
       actually two columns.
   ========================================================================== */

.pull-quotes {
    display: grid;
    gap: var(--kb-space-xl);
}

@media (min-width: 56em) { /* 896px */
    .pull-quotes {
        grid-template-columns: 1fr 1fr;
    }

    .pull-quotes .pull-quote:first-child {
        padding-inline-end: var(--kb-space-xl);
        border-inline-end: var(--kb-border-thin) solid rgb(var(--kb-ink-rgb) / 0.3);
    }

    .pull-quotes .pull-quote:last-child {
        padding-inline-start: var(--kb-space-xl);
    }
}

.pull-quote {
    margin: 0;
    border: none;
    padding: 0;
}

/* Reduced one step down the scale, August 2026 client review ("the fonts
   are too large") — was clamp(1.625rem, ..., 1.875rem) (26-30px). Still
   reads as a pull-quote (well above --fs-lead's 19px body-adjacent size),
   just no longer the largest text on the page outside the hero/h2 scale. */
.pull-quote p {
    font-family: var(--kb-font-heading);
    font-size: clamp(1.375rem, 1.2rem + 0.8vw, 1.5rem); /* 22 -> 24px */
    font-weight: var(--kb-weight-semibold);
    line-height: var(--lh-h3);
    color: var(--kb-text-on-deep);
}

/* Title sits ON TOP of the quote now (August 2026 client review — DOM order
   in PagesSeeder's vision-mission block is <cite> then <p>), so its margin
   is margin-block-end, not -start. */
.pull-quote cite {
    display: block;
    margin-block-end: var(--kb-space-sm);
    font-size: var(--fs-small);
    font-style: normal;
    font-weight: var(--kb-weight-semibold);
    text-transform: uppercase;
    letter-spacing: var(--kb-tracking-caps);
    color: var(--kb-gold-400);
}

/* ==========================================================================
   8. Value cards — the four core values
   ========================================================================== */

/* Gap and padding are the Rule 3 floors (28px / 32px) exactly, not the
   nearest token — --kb-space-md (24px) was under the floor, which is what
   made these read as touching. */
.value-cards {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.75rem; /* 28px */
    margin-block-start: var(--kb-space-xl);
}

.value-card {
    padding: 2rem; /* 32px */
    background-color: var(--kb-surface);
    border-radius: var(--kb-radius-lg);
    box-shadow: var(--kb-shadow-sm);
}

.value-card__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    margin-block-end: var(--kb-space-sm);
    border-radius: var(--kb-radius-md);
    background-color: var(--kb-bg-band);
    color: var(--kb-primary-text);
}

.value-card dt {
    font-family: var(--kb-font-heading);
    font-size: var(--fs-h3);
    font-weight: var(--kb-weight-semibold);
    color: var(--kb-text-heading);
}

.value-card dd {
    margin-block-start: var(--kb-space-2xs);
    color: var(--kb-text-muted);
}

@media (min-width: 40em) { /* 640px */
    .value-cards {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (min-width: 64em) { /* 1024px */
    .value-cards {
        grid-template-columns: repeat(4, 1fr);
    }
}

/* ==========================================================================
   8b. Objectives — large gold numerals beside each item, not a browser
       default <ol>. Decorative-only per the gold rule in CLAUDE.md (the
       numeral carries no meaning a screen reader needs beyond the list
       order it already announces), so it is a ::before generated from the
       li's own ordinal via CSS counters, not printed text.
   ========================================================================== */

.objectives-list {
    list-style: none;
    counter-reset: objective;
    display: grid;
    gap: 0;
    margin-block-start: var(--kb-space-xl);
}

.objectives-list li {
    display: grid;
    grid-template-columns: 3rem 1fr;
    gap: var(--kb-space-md);
    align-items: start;
    max-width: var(--kb-measure);
}

.objectives-list li + li {
    padding-block-start: var(--kb-space-lg);
    border-block-start: 1px solid var(--kb-green-100);
}

/* Green-600, not gold: gold is reserved exclusively for donate actions
   (CLAUDE.md, hard rule) and gold-400 specifically is decoration-only and
   may never carry text — a 48px numeral sitting on the WHITE band below
   would also fail even the 3:1 large-text threshold there (it clears only
   2.2:1 on cream, and white is no better). Green-600 is the primary brand
   fill/mark colour, exactly what a decorative numeral-as-mark calls for. */
.objectives-list li::before {
    counter-increment: objective;
    content: counter(objective);
    font-family: var(--kb-font-heading);
    font-size: 3rem; /* 48px, per spec */
    font-weight: var(--kb-weight-bold);
    line-height: 1;
    color: var(--kb-green-600);
}

/* ==========================================================================
   8c. Where we work — two bullets and a captioned photo pair, replacing the
       old reserves table (August 2026 client review — no hectare total or
       table anywhere on the site any more, see CLAUDE.md).
   ========================================================================== */

.where-we-work-list {
    list-style: none;
    display: grid;
    gap: var(--kb-space-sm);
    margin: 0 0 var(--kb-space-xl);
    padding: 0;
    font-family: var(--kb-font-heading);
    font-size: var(--fs-h3);
    font-weight: var(--kb-weight-semibold);
    color: var(--kb-text-heading);
}

.where-we-work-list li {
    padding-inline-start: var(--kb-space-lg);
    position: relative;
}

.where-we-work-list li::before {
    content: '';
    position: absolute;
    inset-inline-start: 0;
    top: 0.55em;
    width: 0.55rem;
    height: 0.55rem;
    border-radius: var(--kb-radius-circle);
    background-color: var(--kb-green-600);
}

.where-we-work-photos {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.75rem; /* 28px, Rule 4 floor */
}

/* Flex column + a fixed-height figcaption keeps both photos levelled with
   each other regardless of caption length — the mining photo's figcaption
   carries an extra credit line the forest photo's doesn't, which without a
   fixed height left the two frames sitting at different heights. */
.where-we-work-photos__item {
    display: flex;
    flex-direction: column;
}

.where-we-work-photos__item figcaption {
    min-height: 2.8rem;
}

.where-we-work-photos__item picture {
    display: block;
    aspect-ratio: 4 / 3;
    overflow: hidden;
    border-radius: var(--kb-radius-lg);
}

.where-we-work-photos__item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.where-we-work-photos__caption {
    display: block;
    margin-block-start: var(--kb-space-xs);
    font-style: italic;
    font-size: var(--fs-small);
    color: var(--kb-text-muted);
}

.where-we-work-photos__credit {
    display: block;
    font-size: var(--fs-small);
    opacity: 0.6;
}

@media (min-width: 40em) { /* 640px */
    .where-we-work-photos {
        grid-template-columns: repeat(2, 1fr);
    }
}

/* ==========================================================================
   9. People grid — board and leadership
   ========================================================================== */

.people-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--kb-space-lg);
    margin-block-start: var(--kb-space-xl);
}

.person-card {
    display: flex;
    flex-direction: column;
    padding: var(--kb-space-lg);
    background-color: var(--kb-surface);
    border-radius: var(--kb-radius-lg);
    box-shadow: var(--kb-shadow-sm);
}

.person-card__photo {
    width: 6rem;
    height: 6rem;
    border-radius: var(--kb-radius-circle);
    object-fit: cover;
    margin-block-end: var(--kb-space-sm);
}

/* Initials avatar, shown whenever team_members.photo is null — never a
   broken image. Same 6rem circle as a real photo so the grid never jumps
   depending on which rows have one. */
.avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 6rem;
    height: 6rem;
    border-radius: var(--kb-radius-circle);
    margin-block-end: var(--kb-space-sm);
    background-color: var(--kb-primary);
    color: var(--kb-text-on-brand);
    font-family: var(--kb-font-heading);
    font-size: var(--fs-h3);
    font-weight: var(--kb-weight-semibold);
}

.person-card__name {
    font-size: var(--fs-h3);
    font-weight: var(--kb-weight-semibold);
}

.person-card__role {
    margin-block-start: var(--kb-space-3xs);
    font-size: var(--fs-small);
    font-weight: var(--kb-weight-medium);
    color: var(--kb-accent);
    text-transform: uppercase;
    letter-spacing: var(--kb-tracking-caps);
}

.person-card__summary {
    margin-block-start: var(--kb-space-sm);
    color: var(--kb-text-muted);
}

.person-card__bio {
    margin-block-start: var(--kb-space-sm);
    color: var(--kb-text-muted);
}

/* The expand control is a real <button> driving a native <details>, or the
   <details>/<summary> pair alone — both work with JS disabled. Style the
   marker away and use our own, since the default triangle/arrow is
   inconsistent across browsers and does not take a hover/focus state. */
.person-card__toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--kb-space-3xs);
    margin-block-start: var(--kb-space-sm);
    font-size: var(--fs-small);
    font-weight: var(--kb-weight-semibold);
    color: var(--kb-primary-text);
    cursor: pointer;
    list-style: none;
}

.person-card__toggle::-webkit-details-marker {
    display: none;
}

.person-card__toggle-icon {
    transition: transform var(--kb-duration-base) var(--kb-ease-out);
}

details[open] > .person-card__toggle .person-card__toggle-icon {
    transform: rotate(180deg);
}

@media (min-width: 40em) { /* 640px */
    .people-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (min-width: 64em) { /* 1024px */
    .people-grid {
        grid-template-columns: repeat(3, 1fr);
    }
}

/* ==========================================================================
   10. Accordion — Exceptional Resource Values, built on native
       <details>/<summary> so it works with JavaScript disabled.
   ========================================================================== */

.accordion {
    margin-block-start: var(--kb-space-xl);
    border-block-start: var(--kb-border-thin) solid var(--kb-border-subtle);
}

.accordion__item {
    border-block-end: var(--kb-border-thin) solid var(--kb-border-subtle);
}

.accordion__summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--kb-space-sm);
    padding-block: var(--kb-space-md);
    font-family: var(--kb-font-heading);
    font-size: var(--fs-h3);
    font-weight: var(--kb-weight-semibold);
    color: var(--kb-text-heading);
    cursor: pointer;
    list-style: none;
}

.accordion__summary::-webkit-details-marker {
    display: none;
}

.accordion__icon {
    flex-shrink: 0;
    transition: transform var(--kb-duration-base) var(--kb-ease-out);
}

details[open] > .accordion__summary .accordion__icon {
    transform: rotate(45deg);
}

.accordion__panel {
    padding-block-end: var(--kb-space-lg);
}

.accordion__panel ul {
    display: grid;
    gap: var(--kb-space-sm);
}

.accordion__panel li {
    padding-inline-start: var(--kb-space-md);
    border-inline-start: var(--kb-border-medium) solid var(--kb-accent-decor);
    color: var(--kb-text-muted);
}

/* ==========================================================================
   11. Photo strip — a horizontally scrollable filmstrip. Each image keeps
       its native aspect ratio at a fixed display height rather than being
       force-cropped: several source compositions (three colobus spread
       along a branch, a bee-eater pair) lose their subject under a uniform
       crop.
   ========================================================================== */

.photo-strip {
    display: flex;
    gap: var(--kb-space-sm);
    margin-block-start: var(--kb-space-xl);
    padding-block-end: var(--kb-space-2xs); /* room for the focus ring */
    overflow-x: auto;
    scroll-snap-type: x proximity;
}

.photo-strip__item {
    flex-shrink: 0;
    scroll-snap-align: start;
}

.photo-strip__item img {
    height: 13.75rem; /* 220px */
    width: auto;
    border-radius: var(--kb-radius-md);
}

.photo-strip figcaption {
    margin-block-start: var(--kb-space-2xs);
    max-width: 13.75rem;
    font-size: var(--fs-small);
    color: var(--kb-text-muted);
}

/* --kb-text-muted (green-700) is tuned for light surfaces and is nearly
   invisible on a dark band — same reasoning as .page-section--dark's other
   text overrides above. */
.page-section--dark .photo-strip figcaption {
    color: var(--kb-cream);
    opacity: 0.75;
}

.photo-strip__cta {
    margin-block-start: var(--kb-space-lg);
}

/* ==========================================================================
   12. CTA box — donate / related-content prompts on inner pages
   ========================================================================== */

.cta-box {
    margin-block-start: var(--kb-space-2xl);
    padding: var(--kb-space-lg);
    background-color: var(--kb-bg-band);
    border-radius: var(--kb-radius-lg);
    text-align: center;
}

.cta-box p {
    max-width: 52ch;
    margin-inline: auto;
    color: var(--kb-text-muted);
}

/* A full-bleed dark CTA band closing out a page — no card, no radius, no
   top margin of its own (the section wrapper's own padding does that job)
   since this variant IS the section, not a box floating inside a cream
   one. */
.cta-box--dark {
    margin-block-start: 0;
    padding: 0;
    background-color: transparent;
    border-radius: 0;
}

.cta-box--dark h2 {
    color: var(--kb-text-on-deep);
}

.cta-box--dark p {
    color: var(--kb-cream);
    opacity: 0.85;
}

.cta-box .btn {
    margin-block-start: var(--kb-space-md);
}

/* ==========================================================================
   13. Figures inline in the page body — the threats/pressures documentary
       photos on /kakamega-forest
   ========================================================================== */

.page-body figure.inline-figure {
    max-width: var(--kb-container-sm);
    margin-block: var(--kb-space-lg);
}

.page-body figure.inline-figure img {
    width: 100%;
    border-radius: var(--kb-radius-lg);
}

.page-body figure.inline-figure figcaption {
    margin-block-start: var(--kb-space-2xs);
    font-size: var(--fs-small);
    color: var(--kb-text-muted);
}

@media (prefers-reduced-motion: reduce) {
    .photo-strip {
        scroll-behavior: auto;
    }
}

/* ==========================================================================
   15. Full-width image with caption and credit — Page composition
       standard rule 7. Distinct from .image-band: that one overlays text
       on the photo for a hero-like moment; this one breaks the container
       at 16:9 and puts the caption and credit in plain type directly
       beneath, for a documentary photograph that needs to be read, not
       just felt.
   ========================================================================== */

.full-image {
    margin-block: var(--kb-space-xl);
}

/* Capped at 460px, same rule as .image-band — a 16:9 frame at full
   container width alone would run to 675px and dominate the page, which is
   exactly what happened with the logging photo on kakamega-forest. */
.full-image__frame {
    height: clamp(17.5rem, 32vw, 28.75rem); /* 280px -> 460px */
    max-height: 28.75rem; /* 460px */
    overflow: hidden;
}

.full-image__frame img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
}

.full-image figcaption {
    max-width: var(--kb-container);
    margin-inline: auto;
    padding-inline: var(--kb-gutter);
    padding-block-start: var(--kb-space-sm);
}

.full-image__caption {
    display: block;
    font-style: italic;
    color: var(--kb-text-heading);
}

.full-image__credit {
    display: block;
    margin-block-start: var(--kb-space-3xs);
    font-size: var(--fs-small);
    color: var(--kb-text-muted);
    opacity: 0.6;
}

/* ==========================================================================
   16. Inline CTA panel — Page composition standard rule 8. Mid-article,
       breaking the flow: photo left (40%), dark green-800 panel right.
       Two per long page (donate, volunteer) — never the same CTA twice.
   ========================================================================== */

.cta-panel {
    display: grid;
    grid-template-columns: 1fr;
    margin-block: var(--kb-space-2xl);
    border-radius: var(--kb-radius-lg);
    overflow: hidden;
    box-shadow: var(--kb-shadow-md);
}

.cta-panel__media img {
    width: 100%;
    height: 100%;
    min-height: 14rem;
    object-fit: cover;
}

.cta-panel__body {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: var(--kb-space-xl);
    background-color: var(--kb-green-800);
    color: var(--kb-text-on-deep);
}

.cta-panel__eyebrow {
    display: block;
    margin-block-end: var(--kb-space-2xs);
    font-family: var(--kb-font-heading);
    font-size: var(--fs-eyebrow);
    font-weight: var(--kb-weight-bold);
    text-transform: uppercase;
    letter-spacing: var(--kb-tracking-caps);
    color: var(--kb-gold-400);
}

.cta-panel__body h2 {
    color: var(--kb-text-on-deep);
}

.cta-panel__body p {
    margin-block-start: var(--kb-space-2xs);
    max-width: 42ch;
    color: var(--kb-cream);
    opacity: 0.85;
}

.cta-panel__body .btn {
    margin-block-start: var(--kb-space-md);
    align-self: flex-start;
}

@media (min-width: 56em) { /* 896px */
    .cta-panel {
        grid-template-columns: 2fr 3fr; /* photo 40% / panel 60% */
    }

    .cta-panel--reverse {
        grid-template-columns: 3fr 2fr;
    }

    .cta-panel--reverse .cta-panel__media {
        order: 2;
    }
}

/* ==========================================================================
   17. Species cards — Page composition standard rule 9. A horizontally
       scrollable row, same construction as .photo-strip but each card
       carries its own heading and copy rather than just a caption.
   ========================================================================== */

.species-cards {
    display: flex;
    gap: 1.75rem; /* 28px, the card-gap floor */
    margin-block-start: var(--kb-space-xl);
    padding-block-end: var(--kb-space-2xs); /* room for the focus ring */
    overflow-x: auto;
    scroll-snap-type: x proximity;
}

.species-card {
    flex-shrink: 0;
    width: 15.5rem;
    scroll-snap-align: start;
    background-color: var(--kb-surface);
    border-radius: var(--kb-radius-lg);
    box-shadow: var(--kb-shadow-sm);
    overflow: hidden;
}

.species-card img {
    width: 100%;
    height: 11rem;
    object-fit: cover;
}

.species-card__body {
    padding: var(--kb-space-md);
}

.species-card__name {
    font-size: var(--fs-h3);
    font-weight: var(--kb-weight-semibold);
}

.species-card__body p {
    margin-block-start: var(--kb-space-2xs);
    color: var(--kb-text-muted);
    font-size: var(--fs-small);
}

/* ==========================================================================
   18. Programme detail sidebar — 62/38 two-column, right column sticky.
       The alternative to .container--reading where a section keeps the
       wide container: the remaining space carries the status badge, key
       facts (where a programme has real ones — see CLAUDE.md's "Facts and
       honesty"), and the donate CTA, so the prose column is never sitting
       alone. Stacks below 900px.
   ========================================================================== */

.programme-detail {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--kb-space-2xl);
    align-items: start;
}

.programme-detail__body {
    min-width: 0; /* grid item default is auto, which prevents long words/URLs from wrapping */
}

.programme-detail__sidebar {
    display: flex;
    flex-direction: column;
    gap: var(--kb-space-lg);
}

.sidebar-panel {
    padding: var(--kb-space-lg);
    background-color: var(--kb-surface);
    border-radius: var(--kb-radius-lg);
    box-shadow: var(--kb-shadow-sm);
}

.sidebar-panel__heading {
    font-family: var(--kb-font-heading);
    font-size: var(--fs-h3);
    font-weight: var(--kb-weight-semibold);
    color: var(--kb-text-heading);
    margin-block-end: var(--kb-space-sm);
}

.sidebar-facts {
    display: flex;
    flex-direction: column;
    gap: var(--kb-space-md);
}

.sidebar-facts__value {
    display: block;
    font-family: var(--kb-font-heading);
    font-size: 1.5rem; /* 24px */
    font-weight: var(--kb-weight-bold);
    color: var(--kb-green-600);
    font-variant-numeric: tabular-nums;
}

.sidebar-facts__label {
    display: block;
    margin-block-start: 0.125rem;
    font-size: var(--fs-small);
    color: var(--kb-text-muted);
}

.sidebar-panel--cta {
    background-color: var(--kb-green-800);
    color: var(--kb-text-on-deep);
}

.sidebar-panel--cta h2 {
    color: var(--kb-text-on-deep);
}

.sidebar-panel--cta p {
    margin-block-start: var(--kb-space-2xs);
    font-size: var(--fs-small);
    color: var(--kb-cream);
    opacity: 0.85;
}

.sidebar-panel--cta .btn {
    margin-block-start: var(--kb-space-md);
}

@media (min-width: 56.25em) { /* 900px */
    .programme-detail {
        grid-template-columns: 62fr 38fr;
    }

    .programme-detail__sidebar {
        position: sticky;
        inset-block-start: calc(var(--kb-header-h) + 1.5rem); /* +24px */
        max-height: calc(100vh - var(--kb-header-h) - 3rem); /* -48px */
        overflow-y: auto;
    }
}

/* ==========================================================================
   19. Get-involved page: donation tier cards, CFA cards, bank panel.
   ========================================================================== */

.bank-panel {
    margin-block: var(--kb-space-xl);
    padding: var(--kb-space-lg);
    background-color: var(--kb-bg-band); /* green-100 */
    border-radius: var(--kb-radius-lg);
}

.bank-panel h3 {
    margin-block-end: var(--kb-space-md);
}

/* Account name, bank/branch and SWIFT are shared by all three currency
   accounts, so they're shown once here rather than repeated on every card
   below — see the seeder/view docblocks. */
.bank-panel__shared {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--kb-space-md);
    margin-block-end: var(--kb-space-lg);
    padding-block-end: var(--kb-space-lg);
    border-block-end: 1px solid rgb(155 165 127 / 0.28); /* green-400 */
}

.bank-panel__shared dt {
    font-size: var(--fs-small);
    color: var(--kb-text-muted);
}

.bank-panel__shared dd {
    margin-inline-start: 0;
    font-weight: var(--kb-weight-semibold);
    color: var(--kb-text-heading);
}

.bank-panel__swift {
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.04em;
}

@media (min-width: 40em) { /* 640px */
    .bank-panel__shared {
        grid-template-columns: repeat(3, 1fr);
    }
}

/* Three currency cards, equal prominence — KES, USD and EUR side by side,
   not KES first with the others an afterthought. See CLAUDE.md: confirmed
   foreign-currency accounts are a real signal to international funders for
   a young organisation. */
.bank-account-cards {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.75rem; /* 28px, the card-gap floor */
}

@media (min-width: 40em) { /* 640px */
    .bank-account-cards {
        grid-template-columns: repeat(3, 1fr);
    }
}

.bank-account-card {
    display: flex;
    flex-direction: column;
    gap: var(--kb-space-3xs);
    padding: var(--kb-space-lg);
    background-color: var(--kb-surface);
    border-radius: var(--kb-radius-lg);
    box-shadow: var(--kb-shadow-sm);
}

.bank-account-card__currency {
    font-family: var(--kb-font-heading);
    font-weight: var(--kb-weight-bold);
    font-size: var(--fs-h3);
    color: var(--kb-green-600);
}

.bank-account-card__label {
    font-size: var(--fs-small);
    color: var(--kb-text-muted);
}

.bank-account-card__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--kb-space-sm);
    margin-block-start: var(--kb-space-sm);
    padding-block-start: var(--kb-space-sm);
    border-block-start: 1px solid rgb(155 165 127 / 0.28); /* green-400 */
}

/* Tabular-nums + a monospace stack, per spec, so the digits are easy to
   read and to copy correctly by eye as a fallback to the copy button. */
.bank-account-card__number {
    font-family: ui-monospace, 'SFMono-Regular', Menlo, Consolas, monospace;
    font-variant-numeric: tabular-nums;
    font-size: 1.0625rem; /* 17px */
    font-weight: var(--kb-weight-semibold);
    color: var(--kb-text-heading);
    letter-spacing: 0.02em;
}

.bank-account-card__copy {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    flex-shrink: 0;
    padding: 0.375rem 0.625rem;
    font-size: var(--fs-small);
    font-weight: var(--kb-weight-semibold);
    color: var(--kb-green-700);
    background: none;
    border: 1px solid var(--kb-green-400);
    border-radius: var(--kb-radius-pill);
    cursor: pointer;
    transition: background-color var(--kb-duration-base) var(--kb-ease-out);
}

.bank-account-card__copy:hover,
.bank-account-card__copy:focus-visible {
    background-color: var(--kb-bg-band);
}

.bank-account-card__copy--done {
    color: var(--kb-white);
    background-color: var(--kb-green-600);
    border-color: var(--kb-green-600);
}

.tiers-heading {
    margin-block-end: var(--kb-space-md);
}

.tier-cards {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.75rem; /* 28px, the card-gap floor */
}

.tier-card {
    display: flex;
    flex-direction: column;
    gap: var(--kb-space-2xs);
    padding: 2rem; /* 32px, the card-padding floor */
    background-color: var(--kb-surface);
    border-radius: var(--kb-radius-lg);
    box-shadow: var(--kb-shadow-sm);
    text-align: center;
}

.tier-card__amount {
    font-family: var(--kb-font-heading);
    font-weight: var(--kb-weight-bold);
    font-size: clamp(1.75rem, 3vw, 2.25rem);
    color: var(--kb-green-600);
}

.tier-card__label {
    margin-block-start: var(--kb-space-sm);
    font-weight: var(--kb-weight-semibold);
    color: var(--kb-text-heading);
}

.tier-card__sub {
    margin-block-start: var(--kb-space-3xs);
    font-size: var(--fs-small);
    color: var(--kb-text-muted);
}

.tier-card .btn {
    margin-block-start: auto; /* pins to the card bottom regardless of how much copy sits above it */
    align-self: center;
}

@media (min-width: 40em) { /* 640px */
    .tier-cards {
        grid-template-columns: repeat(3, 1fr);
    }
}

.cfa-cards {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.75rem; /* 28px */
    margin-block-end: var(--kb-space-xl);
}

.cfa-card {
    padding: 1.5rem;
    background-color: var(--kb-surface);
    border-radius: var(--kb-radius-lg);
    box-shadow: var(--kb-shadow-sm);
}

.cfa-card__name {
    font-family: var(--kb-font-heading);
    font-weight: var(--kb-weight-semibold);
    color: var(--kb-text-heading);
}

.cfa-card__forest {
    margin-block-start: var(--kb-space-3xs);
    color: var(--kb-text-muted);
    font-size: var(--fs-small);
}

@media (min-width: 40em) { /* 640px */
    .cfa-cards {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (min-width: 64em) { /* 1024px */
    .cfa-cards {
        grid-template-columns: repeat(4, 1fr);
    }
}
