/* ============================================================================
   main.css — 360° Impact Portfolio
   ----------------------------------------------------------------------------
   The single stylesheet for every public page. Loaded by
   /templates/head_tags_v2.php, so a page never carries its own copy of a
   component and two pages can never drift apart.

   The wheel lives in /assets/css/i360.css and the token-gated client report in
   /assets/css/client_report.css. Both are loaded separately, because both are
   shared with the assessor viewer and neither belongs to the public site alone.

   Rules, from CLAUDE.md §23:
     - Every colour is a named token. The only exception is SDG decorative hex
       (swatch, 17-colour stripe, .pbar segments, project badges, domain keys),
       which reproduces the official UN goal colours in fixed order.
     - 400-500 is the default weight. 600 for UI labels, eyebrows and stat
       figures. 700 only where a component already used it.
     - The lightest background is var(--paper). Never pure white.

   Anything added here must also be added to styleguide.html, which loads this
   file rather than repeating it.

   v2.5 · 2026-09 · the last Tailwind removed. §66 adds .site-header__inner,
   .site-header__cta and the grouped drawer (.site-header__mobile and its
   parts), plus type for .nav-dd__btn, which had been borrowing Tailwind's
   `text-sm text-ink-muted` and fell back to browser button defaults whenever
   the CDN was blocked. .site-header__nav link rules rescoped to `>` direct
   children so .nav-dd__panel links keep their own size and colour. Toggle
   border dropped for parity with the header that shipped. With this, no page
   loads a utility framework and the tokens have one home: the CDN config in
   head_tags_v2.php had been a second, drifting copy of --ink-faint and
   --sdg-energy-dk.
   v2.4a · 2026-09 · contrast pass. --ink-faint darkened to #62676c (was
   #7a7f84, 3.21:1 on sand). Climate green kept as a fill but swapped to
   --sdg-climate-dk wherever it carried informational small text: the eyebrow,
   .t-micro and the twelve mono micro-labels that share that role. .commit
   given its dark-ground colours (it was documented "on navy" at 1.3:1) and
   .process given the list reset its <ol> always needed. --sdg-energy-dk
   darkened to #855a00 (3.77:1 on sand); .ev__tick, .goals__n and .hero__meta
   moved off SDG hues as type. Dark-ground rules added for .stats, .link,
   .figures, .closer and .list. Light panels sitting on a dark ground keep ink
   type (the :is() list below §26 in CLAUDE.md) — and the few elements that set
   their own dark ground *inside* such a panel (.rec__result, .closer--plate,
   .callout--absolute) get paper type back at matching specificity.
   All 33 bare `1fr` grid tracks became minmax(0, 1fr).
   v2.4 · 2026-09 · page and document components, §53-§65: .pagenav,
   .nextpage, .doc/.toc, .seq, .rec, .marks, .explorer, .callout, .table,
   .stats, .form, .skip-link and the focus ring, .sheet--stack/--page. Plus
   the navy and green ground modifiers with the .on-dark hook, .btn--light,
   .faq--stack, .bands--cards, .closer--plate, .groups__toolbar, .verdict-key
   and .hero--dark. Eight new tokens: four --paper-tint-*, --paper-dim,
   --paper-faint, --rule-dark, --header-h. Nothing existing changes behaviour.
   v2.3 · 2026-09 · card roles (.card--absolute/method/caution/yes/no), card
   parts (__cap, __eyebrow, __body, __tally) and the tab treatment
   (.cards--tab). Plain .card is unchanged.
   v2.2 · 2026-09 · area accordion (.groups) and criteria key (.gkey) for
   the twenty criteria on /methodology.php, replacing the three-column .faq
   there. .faq itself is unchanged.
   v2.1 · 2026-09 · editorial type scale — serif restored to h2/h3 per
   CLAUDE.md §2, headings up ~25-35%, body 17px, lead 20px capped at 52ch,
   serif at 400 on dark grounds.
   v2.0 · 2026-09 · promoted from the homepage build
   ============================================================================ */

/* ============================================================
   Design tokens
   ============================================================ */
:root {
  --font-serif: 'IBM Plex Serif', Cambria, 'Times New Roman', Georgia, serif;
  --font-sans:  'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono:  'IBM Plex Mono', 'SF Mono', Menlo, Consolas, monospace;

  /* SDG core palette */
  --sdg-climate:     #3F7E44;
  --sdg-climate-dk:  #2D5A30;
  --sdg-partner:     #19486A;
  --sdg-partner-dk:  #102F46;
  --sdg-energy:      #FCC30B;
  --sdg-energy-dk:   #855a00;   /* amber legible as text on every ground.
                                   #9a6a00 measured 3.77:1 on sand. */
  --sdg-energy-soft: rgba(252, 195, 11, 0.35);
  --sdg-climate-soft: rgba(63, 126, 68, 0.12);   /* v2.4 — .field focus ring */
  --sdg-water:       #26BDE2;

  /* Extended SDG palette — for graphic blocks and swatch motifs */
  --sdg-poverty:    #E5243B;   /* SDG  1 */
  --sdg-poverty-dk: #A8182D;
  --sdg-hunger:    #DDA63A;   /* SDG  2 */
  --sdg-health:    #4C9F38;   /* SDG  3 */
  --sdg-education: #C5192D;   /* SDG  4 */
  --sdg-gender:    #FF3A21;   /* SDG  5 */
  --sdg-growth:    #A21942;   /* SDG  8 */
  --sdg-industry:  #FD6925;   /* SDG  9 */
  --sdg-equality:  #DD1367;   /* SDG 10 */
  --sdg-cities:    #FD9D24;   /* SDG 11 */
  --sdg-consume:   #BF8B2E;   /* SDG 12 */
  --sdg-ocean:     #0A97D9;   /* SDG 14 */
  --sdg-life:      #56C02B;   /* SDG 15 */
  --sdg-peace:     #00689D;   /* SDG 16 */

  /* Ink & paper */
  --ink:        #14171a;
  --ink-muted:  #3a3f44;
  --ink-faint:  #62676c;   /* v2.4 — was #7a7f84, which measured 3.21:1 on sand */
  --ink-ghost:  #c8c4ba;

  --paper:      #faf8f3;
  --paper-warm:  #ebe5d5;   /* sand  — process and service */
  --paper-slate: #e6ecef;   /* slate — measurement and method */
  --paper-cool:  #f4f3ee;

  --rule:       #d8d4ca;
  --rule-soft:  #e8e5dd;

  /* Tweakable CTA background — default deep climate green */
  --cta-bg: #1f4a23;

  /* v2.4 — tinted grounds for .callout and .form__success. Mixed from
     --paper, not from white, so they sit on the page rather than glow on it. */
  --paper-tint-climate: #eff4ee;
  --paper-tint-energy:  #fbf6e8;
  --paper-tint-partner: #eceff3;
  --paper-tint-poverty: #f8eeef;

  /* v2.4 — ink and rule on dark grounds. One value each, so a dark band is
     legible at the same level everywhere. 0.72 is the floor that keeps 14px
     sans above WCAG AA on --sdg-partner-dk. */
  --paper-dim:   rgba(250, 248, 243, 0.72);
  --paper-faint: rgba(250, 248, 243, 0.60);   /* Must clear every dark ground, not
                                                 just navy. On --cta-bg green 0.52
                                                 measured 3.85:1; 0.60 gives 4.58
                                                 there and 5.67 on navy. */
  --rule-dark:   rgba(250, 248, 243, 0.16);

  /* v2.4 — header height. .pagenav, the .toc, the mobile drawer and
     scroll-padding all anchor to this one number. */
  --header-h: 64px;
}

/* ============================================================
   Base reset
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; }
html { font-size: 16px; scroll-behavior: smooth;
       scroll-padding-top: calc(var(--header-h) + 3.5rem); }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
  font-feature-settings: 'kern', 'liga', 'calt';
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ============================================================
   Type roles
   ============================================================ */
/* ------------------------------------------------------------
   v2.1 · 2026-09 — editorial scale.
     - Serif carries display through h3. Sans resumes at h4, where the mono
       label directly above it is close enough that serif would compete.
     - Display, h1 and h2 are fluid. The minima hold an h2 at 32.8px on a
       phone, so a section heading still reads as one.
     - Body is 17px and lead 20px. The headings grew, so the copy grew with
       them; never raise the headings again without raising these.
     - .t-lead caps at 52ch. At 20px a 64ch standfirst runs too long beside a
       serif head in .section__head--split. Use .t-lead--wide to opt out.
   ------------------------------------------------------------ */
.t-display { font-family: var(--font-serif); font-size: clamp(3rem, 8.4vw, 5.4rem); font-weight: 500; line-height: 1.0; letter-spacing: -0.028em; color: var(--ink); margin: 0; overflow-wrap: break-word; }
.t-h1      { font-family: var(--font-serif); font-size: clamp(2.6rem, 5.2vw, 3.5rem); font-weight: 500; line-height: 1.06; letter-spacing: -0.025em; color: var(--ink); margin: 0; }
.t-h2      { font-family: var(--font-serif); font-size: clamp(2.05rem, 3.9vw, 2.7rem); font-weight: 500; line-height: 1.12; letter-spacing: -0.022em; color: var(--ink); margin: 0; }
.t-h3      { font-family: var(--font-serif); font-size: 1.75rem; font-weight: 500; line-height: 1.22; letter-spacing: -0.016em; color: var(--ink); margin: 0; }
.t-h4      { font-family: var(--font-sans); font-size: 1.25rem; font-weight: 500; line-height: 1.35; letter-spacing: -0.005em; color: var(--ink); margin: 0; }
.t-lead    { font-family: var(--font-sans); font-size: 1.25rem; font-weight: 400; line-height: 1.55; letter-spacing: -0.005em; color: var(--ink-muted); margin: 0; max-width: 52ch; }
.t-lead--wide { max-width: none; }
.t-body    { font-family: var(--font-sans); font-size: 1.0625rem; font-weight: 400; line-height: 1.65; color: var(--ink-muted); margin: 0; }
.t-body strong { font-weight: 500; color: var(--ink); }
.t-quote   { font-family: var(--font-serif); font-style: italic; font-weight: 500; font-size: 1.15rem; line-height: 1.5; color: var(--ink); margin: 0; }
.t-caption { font-family: var(--font-sans); font-size: 0.82rem; line-height: 1.55; color: var(--ink-faint); margin: 0; }
.t-micro   { font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.18em; text-transform: uppercase; font-weight: 500; color: var(--sdg-climate-dk); }
.max-w-prose { max-width: 64ch; }
.max-w-lead  { max-width: 52ch; }

/* Optical compensation. Light serif on a dark ground gains apparent weight,
   so display through h3 drop to 400 inside the dark bands. Sans and mono are
   left alone — the effect only shows at size, in a face with fine serifs. */
.integrity .t-display, .integrity .t-h1, .integrity .t-h2, .integrity .t-h3,
.cta .t-display, .cta .t-h1, .cta .t-h2, .cta .t-h3 { font-weight: 400; }

/* ============================================================
   Eyebrow
   ============================================================ */
.eyebrow {
  display: flex; align-items: center; gap: 0.7rem;
  font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.18em;
  text-transform: uppercase; font-weight: 500; color: var(--sdg-climate-dk);
  margin: 0 0 1rem 0; flex-wrap: wrap;
}
.eyebrow--partner { color: var(--sdg-partner); }
.eyebrow--paper   { color: var(--paper); }
.eyebrow__rule    { width: 28px; height: 1px; background: currentColor; flex-shrink: 0; }
.eyebrow__sep     { color: var(--ink-ghost); font-weight: 400; }
.eyebrow--paper .eyebrow__sep { color: rgba(255,255,255,0.4); }
.eyebrow__chip {
  padding: 2px 8px; background: var(--sdg-climate); color: var(--paper);
  border-radius: 2px; font-size: 0.62rem; letter-spacing: 0.10em; margin-left: 0.4rem;
}
.eyebrow--partner .eyebrow__chip { background: var(--sdg-partner); }
.eyebrow--paper   .eyebrow__chip { background: var(--sdg-energy); color: var(--ink); }

/* ============================================================
   SDG swatch block — 5-color motif used in eyebrows
   ============================================================ */
.swatch {
  display: inline-flex; flex-shrink: 0; height: 14px;
  border: 1px solid rgba(0,0,0,0.08);
}
.swatch span      { width: 14px; height: 100%; display: block; }
.swatch--lg       { height: 20px; }
.swatch--lg span  { width: 20px; }
.swatch--xl       { height: 28px; }
.swatch--xl span  { width: 28px; }
.eyebrow--paper .swatch { border-color: rgba(255,255,255,0.18); }

/* SDG rainbow stripe — full 17-color edge-to-edge ribbon */
.stripe      { display: flex; height: 6px; width: 100%; }
.stripe span { flex: 1; height: 100%; }
.stripe--tall { height: 10px; }

/* ============================================================
   Marker highlight
   ============================================================ */
.hl {
  background-image: linear-gradient(transparent 62%, var(--sdg-energy-soft) 62%, var(--sdg-energy-soft) 92%, transparent 92%);
  padding: 0 0.05em;
}

/* ============================================================
   Buttons
   ============================================================ */
.btn {
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0.8rem 1.4rem;
  font-family: var(--font-sans); font-size: 0.875rem; font-weight: 500;
  letter-spacing: 0.02em; border-radius: 2px; text-decoration: none;
  transition: background 120ms, color 120ms, border-color 120ms;
  cursor: pointer; border: 1px solid transparent;
}
.btn--primary   { background: var(--sdg-climate); color: var(--paper); }
.btn--primary:hover { background: var(--sdg-climate-dk); }
.btn--secondary { background: transparent; color: var(--ink); border-color: var(--rule); }
.btn--secondary:hover { border-color: var(--ink); }
.btn--ghost     { background: transparent; color: var(--paper); border-color: rgba(255,255,255,0.3); }
.btn--ghost:hover { border-color: var(--paper); }
/* v2.4 — the solid counterpart to --ghost on a dark ground. Ghost is an
   outline and reads as the secondary action; light is a fill and reads as the
   primary one. A dark band that needs both weights takes one of each. */
.btn--light     { background: var(--paper); color: var(--sdg-partner-dk); }
.btn--light:hover { background: var(--paper-cool); }
.btn .arr { transition: transform 200ms; }
.btn:hover .arr { transform: translateX(3px); }

.link {
  color: var(--sdg-partner); text-decoration: underline;
  text-decoration-thickness: 1px; text-underline-offset: 3px;
}
.link:hover { text-decoration-thickness: 2px; }
/* Partner blue measured 1.43:1 on navy. A link on a dark ground takes paper and
   keeps the underline as the thing that marks it as a link. */
.on-dark .link, .section--navy .link, .section--green .link,
.integrity .link, .cta .link { color: var(--paper); }

/* ============================================================
   Layout
   ----------------------------------------------------------------
   Every grid track is minmax(0, 1fr), never a bare 1fr. A bare 1fr
   is minmax(auto, 1fr), so one unbreakable string — a registry id,
   a table with a min-width, a long mono label — widens the whole
   grid and the page scrolls sideways on a phone. Measured at 1109px
   on a 390px viewport before this was fixed.
   ============================================================ */
.container { max-width: 1240px; margin: 0 auto; padding: 0 2rem; }
@media (max-width: 700px) { .container { padding: 0 1.25rem; } }

/* ============================================================
   Hero
   ============================================================ */
.hero {
  padding: 5rem 0 4.5rem;
  border-bottom: 1px solid var(--rule);
  position: relative;
}
.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: 4rem;
  align-items: end;
}
@media (max-width: 1000px) {
  .hero__grid { grid-template-columns: minmax(0, 1fr); gap: 2.5rem; }
}
.hero__display { max-width: 18ch; }
.hero__lead    { margin-top: 1.5rem; max-width: 52ch; }
.hero__ctas    { margin-top: 2rem; display: flex; gap: 0.8rem; flex-wrap: wrap; }
.hero__meta {
  margin-top: 2.5rem;
  display: flex; gap: 2.5rem; flex-wrap: wrap;
  padding-top: 1.5rem; border-top: 1px solid var(--rule);
}
.hero__meta-item { display: flex; flex-direction: column; gap: 0.3rem; min-width: 0; }
.hero__meta-key {
  font-family: var(--font-mono); font-size: 0.62rem;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-faint); font-weight: 500;
}
.hero__meta-val {
  font-family: var(--font-serif); font-size: 1.5rem; color: var(--ink); font-weight: 500; letter-spacing: -0.015em;
}
.hero__meta-val .mono { font-family: var(--font-mono); font-weight: 400; color: var(--sdg-partner); font-size: 0.85rem; }
.hero__meta-item:nth-child(1) .hero__meta-val { color: var(--sdg-climate); }
.hero__meta-item:nth-child(2) .hero__meta-val { color: var(--sdg-energy-dk); }   /* #FCC30B measured 1.53:1 as a figure on paper */

/* Hero side panel — contribution claim */
.hero__claim {
  background: var(--paper-warm);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--sdg-climate);
  padding: 2rem 2rem 1.75rem 2.25rem;
  position: relative;
}
.hero__claim::before {
  content: '"'; position: absolute; top: 0.3rem; left: 0.7rem;
  font-family: var(--font-serif); font-size: 4rem; line-height: 1;
  color: var(--sdg-climate); opacity: 0.25; font-weight: 500;
}
.hero__claim-label {
  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.18em;
  text-transform: uppercase; font-weight: 500; color: var(--sdg-climate-dk);
  margin-bottom: 0.7rem; display: flex; align-items: center; gap: 0.6rem;
}
.hero__claim-label::after {
  content: ''; flex: 1; height: 1px; background: var(--sdg-climate); opacity: 0.25;
}
.hero__claim-text {
  font-family: var(--font-serif); font-style: italic; font-weight: 500;
  font-size: 1.18rem; line-height: 1.5; color: var(--ink); margin: 0;
}
.hero__claim-foot {
  margin-top: 1.25rem; padding-top: 1rem; border-top: 1px solid var(--rule);
  display: flex; justify-content: space-between; align-items: baseline;
  font-family: var(--font-mono); font-size: 0.7rem; color: var(--ink-faint); letter-spacing: 0.04em;
}
.hero__claim-foot .ref { color: var(--sdg-partner); }

/* ============================================================
   Trustbar
   ============================================================ */
.trust {
  padding: 1.6rem 0;
  background: var(--ink);
  border-bottom: none;
}
.trust__inner {
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  align-items: center; gap: 2.5rem;
  max-width: 1240px; margin: 0 auto; padding: 0 2rem;
}
@media (max-width: 800px) { .trust__inner { grid-template-columns: minmax(0, 1fr); gap: 0.8rem; } }
.trust__label {
  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.18em;
  text-transform: uppercase; font-weight: 500; color: rgba(250, 248, 243, 0.5);
}
.trust__list  { display: flex; gap: 2.2rem; flex-wrap: wrap; align-items: center; font-family: var(--font-sans); font-size: 0.9rem; color: rgba(250, 248, 243, 0.78); }
.trust__item  { display: flex; align-items: baseline; gap: 0.5rem; }
.trust__item-name { font-weight: 500; color: var(--ink); }
.trust__item-id   { font-family: var(--font-mono); font-size: 0.72rem; color: var(--sdg-partner); letter-spacing: 0.04em; }

/* ============================================================
   Sections
   ============================================================ */
.section         { padding: 5.5rem 0; border-bottom: 1px solid var(--rule); }
.section--warm   { background: var(--paper-warm); }
.section__head   { margin-bottom: 3rem; max-width: 64ch; }
.section__head .t-h2 { margin-top: 0.4rem; }
.section__desc   { margin-top: 1rem; }

/* ============================================================
   Why BVCM — drop-cap + sidenotes
   ============================================================ */
.why__grid { display: grid; grid-template-columns: minmax(0, 1fr) 280px; gap: 4rem; align-items: start; }
@media (max-width: 1000px) { .why__grid { grid-template-columns: minmax(0, 1fr); gap: 2rem; } }
.why__main { min-width: 0; max-width: 64ch; }
.why__lead-p { margin-bottom: 1.25rem; }
.why__lead-p::first-letter {
  float: left;
  font-family: var(--font-serif); font-size: 4.2em; line-height: 0.88; font-weight: 500;
  color: var(--sdg-climate); padding: 0.05em 0.1em 0 0;
}
.margin-note             { padding-left: 1rem; margin-bottom: 1.75rem; border-left: 2px solid var(--sdg-climate); }
.margin-note--partner    { border-left-color: var(--sdg-partner); }
.margin-note__label {
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.16em;
  text-transform: uppercase; font-weight: 500; color: var(--sdg-climate-dk); margin-bottom: 0.35rem;
}
.margin-note--partner .margin-note__label { color: var(--sdg-partner); }
.margin-note__text {
  font-family: var(--font-sans); font-size: 0.78rem; font-style: italic;
  line-height: 1.55; color: var(--ink-muted); margin: 0;
}
.margin-note__text strong { font-style: normal; font-weight: 500; color: var(--ink); }

/* ============================================================
   Process steps
   ============================================================ */
.process {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0;
  margin-top: 1rem; border-top: 1px solid var(--rule); border-left: 1px solid var(--rule);
  /* v2.4 fix — the markup is <ol role="list"> for accessibility, but the list
     style was never reset, so the default 1. 2. 3. 4. markers rendered outside
     each grid cell. role="list" restores the semantics Safari drops when
     list-style is none, which is why both are needed. */
  list-style: none; margin-left: 0; margin-right: 0; padding: 0;
}
@media (max-width: 900px) { .process { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .process { grid-template-columns: minmax(0, 1fr); } }
.process__step {
  padding: 1.75rem 1.5rem 2rem;
  border-right: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
  background: var(--paper); position: relative;
}
.process__num   { font-family: var(--font-mono); font-size: 0.72rem; color: var(--sdg-climate-dk); letter-spacing: 0.16em; font-weight: 500; margin-bottom: 0.8rem; }
.process__title { margin-bottom: 0.6rem; }
.process__text  { font-family: var(--font-sans); font-size: 0.9rem; line-height: 1.6; color: var(--ink-muted); margin: 0; }

/* ============================================================
   Portfolio composition
   ============================================================ */
.composition { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); gap: 3rem; align-items: start; }
@media (max-width: 1000px) { .composition { grid-template-columns: minmax(0, 1fr); } }

/* Data block */
.data       { border: 1px solid var(--rule); background: var(--paper); box-shadow: 0 1px 0 rgba(0,0,0,0.02); }
.data__head {
  padding: 0.95rem 1.25rem; border-bottom: 1px solid var(--rule); background: var(--paper-warm);
  display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; flex-wrap: wrap;
}
.data__title { font-family: var(--font-sans); font-size: 0.95rem; font-weight: 500; color: var(--ink); }
.data__id    { font-family: var(--font-mono); font-size: 0.72rem; color: var(--ink-faint); letter-spacing: 0.04em; }
.data__row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  padding: 0.7rem 1.25rem; border-bottom: 1px solid var(--rule-soft); align-items: center; gap: 1rem;
}
.data__row:last-child { border-bottom: none; }
.data__key {
  font-family: var(--font-sans); font-size: 0.88rem; color: var(--ink-muted);
  display: flex; align-items: center; gap: 0.5rem;
}
.data__key::before { content: ''; width: 4px; height: 4px; background: var(--sdg-climate); border-radius: 50%; opacity: 0.6; }
.data__val {
  font-family: var(--font-sans); font-size: 0.92rem;
  color: var(--ink); font-weight: 500; text-align: right; font-variant-numeric: tabular-nums;
}
.data__sparkline { display: inline-flex; align-items: center; gap: 0.7rem; }
.data__sparkline svg { width: 70px; height: 20px; display: block; }
.data__trend { font-family: var(--font-mono); font-size: 0.72rem; color: var(--sdg-climate-dk); font-weight: 500; }
.data__foot {
  padding: 0.85rem 1.25rem; background: var(--paper-cool); border-top: 1px solid var(--rule);
  font-family: var(--font-mono); font-size: 0.7rem; color: var(--ink-faint); letter-spacing: 0.04em;
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem;
}

/* Portfolio composition bar */
.pbar         { margin-top: 1.5rem; }
.pbar__track  { display: flex; height: 14px; border-radius: 1px; overflow: hidden; border: 1px solid var(--rule); }
.pbar__seg    { transition: filter 120ms; }
.pbar__seg:hover { filter: brightness(0.92); }
.pbar__legend { margin-top: 0.9rem; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.5rem 1.5rem; font-family: var(--font-sans); font-size: 0.82rem; }
.pbar__leg    { display: flex; align-items: baseline; gap: 0.5rem; color: var(--ink-muted); }
.pbar__dot    { width: 10px; height: 10px; flex-shrink: 0; transform: translateY(1px); }
.pbar__name   { color: var(--ink); font-weight: 500; }
.pbar__pct    { margin-left: auto; font-family: var(--font-mono); color: var(--ink-faint); }

/* ============================================================
   Project cards
   ============================================================ */
.projects { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.5rem; margin-top: 2.5rem; }
@media (max-width: 1000px) { .projects { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width:  640px) { .projects { grid-template-columns: minmax(0, 1fr); } }
/* v2.4 — minmax(0,1fr) above: a plain 1fr track is minmax(auto,1fr), so a long
   registry id inside .proj__id pushed the whole grid wider than the phone. */
.proj {
  background: var(--paper); border: 1px solid var(--rule);
  display: flex; flex-direction: column; min-height: 360px;
  transition: border-color 120ms, transform 200ms;
}
.proj:hover { border-color: var(--ink); }
.proj__header {
  padding: 1.25rem 1.25rem 1rem; border-bottom: 1px solid var(--rule-soft);
  display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem;
}
.proj__sdg {
  width: 32px; height: 32px; flex-shrink: 0; color: var(--paper);
  font-family: var(--font-sans); font-size: 0.85rem; font-weight: 500;
  display: flex; align-items: center; justify-content: center; border-radius: 1px;
}
.proj__sdg--13 { background: var(--sdg-climate); }
.proj__sdg--7  { background: var(--sdg-energy); color: var(--ink); }
.proj__sdg--6  { background: var(--sdg-water); color: var(--ink); }
.proj__id      { font-family: var(--font-mono); font-size: 0.7rem; color: var(--ink-faint); letter-spacing: 0.04em; text-align: right; }
.proj__id strong { color: var(--sdg-partner); font-weight: 500; }
.proj__body    { padding: 1rem 1.25rem; flex: 1; display: flex; flex-direction: column; }
.proj__title   { font-family: var(--font-serif); font-size: 1.45rem; font-weight: 500; line-height: 1.24; letter-spacing: -0.016em; color: var(--ink); margin: 0 0 0.5rem; }
.proj__loc     { font-family: var(--font-sans); font-size: 0.85rem; color: var(--ink-muted); margin: 0 0 1rem; }
.proj__desc    { font-family: var(--font-sans); font-size: 0.88rem; line-height: 1.55; color: var(--ink-muted); margin: 0 0 1.25rem; flex: 1; }
.proj__stats   { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.6rem 1rem; padding-top: 1rem; border-top: 1px solid var(--rule-soft); }
.proj__stat-key { font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-faint); font-weight: 500; }
.proj__stat-val { font-family: var(--font-sans); font-size: 0.95rem; font-weight: 500; color: var(--ink); margin-top: 2px; font-variant-numeric: tabular-nums; }
.proj__foot {
  padding: 0.85rem 1.25rem; border-top: 1px solid var(--rule-soft); background: var(--paper-cool);
  display: flex; justify-content: space-between; align-items: center;
}
.proj__status {
  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--sdg-climate-dk); font-weight: 500;
  display: flex; align-items: center; gap: 0.5rem;
}
.proj__status::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--sdg-climate); }
.proj__view { font-family: var(--font-sans); font-size: 0.82rem; color: var(--sdg-partner); text-decoration: none; font-weight: 500; }
.proj__view:hover { text-decoration: underline; }

/* ============================================================
   Integrity dark band
   ============================================================ */
.integrity {
  background: var(--sdg-partner-dk); color: var(--paper); padding: 5.5rem 0; border-bottom: 1px solid var(--rule);
}
.integrity__grid { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 4rem; align-items: start; }
@media (max-width: 1000px) { .integrity__grid { grid-template-columns: minmax(0, 1fr); gap: 2.5rem; } }
.integrity .t-h2   { color: var(--paper); }
.integrity .t-lead { color: rgba(250, 248, 243, 0.78); }
.integrity__pillars { display: grid; gap: 1.25rem; }
.pillar {
  border-top: 1px solid rgba(250, 248, 243, 0.14); padding-top: 1.25rem;
  display: grid; grid-template-columns: 110px minmax(0, 1fr); gap: 1.5rem; align-items: start;
}
@media (max-width: 600px) { .pillar { grid-template-columns: minmax(0, 1fr); gap: 0.5rem; } }
.pillar__id    { font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--sdg-energy); font-weight: 500; padding-top: 4px; }
.pillar__title { font-family: var(--font-serif); font-size: 1.25rem; font-weight: 400; line-height: 1.3; letter-spacing: -0.012em; color: var(--paper); margin: 0 0 0.4rem; }
.pillar__text  { font-family: var(--font-sans); font-size: 0.92rem; line-height: 1.6; color: rgba(250, 248, 243, 0.7); margin: 0; }

/* ============================================================
   Pricing tiers
   ============================================================ */
.tiers { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.5rem; margin-top: 2.5rem; }
@media (max-width: 900px) { .tiers { grid-template-columns: minmax(0, 1fr); } }
.tier {
  background: var(--paper); border: 1px solid var(--rule);
  padding: 2rem 1.75rem; display: flex; flex-direction: column; position: relative;
}
.tier--gold { border-color: var(--sdg-climate); box-shadow: 0 0 0 1px var(--sdg-climate); }
.tier__name {
  font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.18em;
  text-transform: uppercase; font-weight: 500; color: var(--sdg-climate-dk); margin-bottom: 1.2rem;
  display: flex; align-items: center; gap: 0.6rem;
}
.tier__name::after { content: ''; flex: 1; height: 1px; background: var(--rule); }
.tier__pop {
  position: absolute; top: -0.7rem; right: 1rem;
  background: var(--sdg-climate); color: var(--paper);
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.16em;
  text-transform: uppercase; font-weight: 500; padding: 3px 9px; border-radius: 1px;
}
.tier__price      { font-family: var(--font-serif); font-size: 2.7rem; font-weight: 500; line-height: 1; letter-spacing: -0.02em; color: var(--ink); margin: 0; }
.tier__price-unit { font-family: var(--font-sans); font-size: 0.85rem; color: var(--ink-faint); margin-top: 0.35rem; }
.tier__desc       { font-family: var(--font-sans); font-size: 0.92rem; line-height: 1.55; color: var(--ink-muted); margin: 1.25rem 0 1.5rem; padding-top: 1.25rem; border-top: 1px solid var(--rule-soft); }
.tier__list       { list-style: none; padding: 0; margin: 0 0 1.75rem; flex: 1; }
.tier__list li    { font-family: var(--font-sans); font-size: 0.88rem; line-height: 1.5; color: var(--ink-muted); padding: 0.55rem 0 0.55rem 1.4rem; border-bottom: 1px dashed var(--rule-soft); position: relative; }
.tier__list li:last-child { border-bottom: none; }
.tier__list li::before { content: '+'; position: absolute; left: 0; top: 0.55rem; font-family: var(--font-mono); font-size: 0.85rem; color: var(--sdg-climate); font-weight: 500; }

/* ============================================================
   Testimonial
   ============================================================ */
.quote-block { max-width: 60ch; margin: 0 auto; padding: 0 1rem; text-align: left; }
.quote-block .t-quote { font-size: 2rem; line-height: 1.35; color: var(--ink); font-style: normal; font-weight: 400; letter-spacing: -0.012em; }
.quote-block__attr { margin-top: 2rem; padding-top: 1.25rem; border-top: 1px solid var(--rule); display: flex; justify-content: space-between; align-items: baseline; flex-wrap: wrap; gap: 0.75rem; }
.quote-block__name { font-family: var(--font-sans); font-size: 0.95rem; font-weight: 500; color: var(--ink); }
.quote-block__role { font-family: var(--font-sans); font-size: 0.85rem; color: var(--ink-muted); }
.quote-block__ref  { font-family: var(--font-mono); font-size: 0.7rem; color: var(--sdg-partner); letter-spacing: 0.04em; }

/* ============================================================
   CTA band
   ============================================================ */
.cta { background: var(--cta-bg); color: var(--paper); padding: 5rem 0; }
.cta__inner { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: 3rem; align-items: start; }
@media (max-width: 900px) { .cta__inner { grid-template-columns: minmax(0, 1fr); gap: 1.5rem; } }
.cta .t-h1 { color: var(--paper); }
.cta .t-h1 .hl {
  color: var(--paper);
  background-image: linear-gradient(transparent 62%, rgba(252,195,11,0.45) 62%, rgba(252,195,11,0.45) 92%, transparent 92%);
}
.cta__desc { font-family: var(--font-sans); font-size: 1.125rem; line-height: 1.6; color: rgba(250, 248, 243, 0.7); margin: 1rem 0 0; }

/* Contact form inside CTA */
/* The right column of a CTA. It carries either the scoping form with a
   secondary route beneath it, or two buttons on a page whose job is to send
   the reader to the form. Direct children only, so the form's own submit
   button keeps the width rule set on .cta-form. */
.cta__actions        { display: flex; flex-direction: column; align-items: stretch; gap: 1rem; }
.cta__actions > .btn { width: 100%; justify-content: center; }

/* Visually hidden, still announced. Used for the labels on the scoping form,
   where a placeholder alone would leave a screen-reader user with an unlabelled
   field and would vanish for everyone the moment they started typing. */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
           overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }

.cta-form { display: flex; flex-direction: column; gap: 0.7rem; }
.cta-form__row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0.7rem; }
@media (max-width: 600px) { .cta-form__row { grid-template-columns: minmax(0, 1fr); } }
.cta-form input,
.cta-form select {
  width: 100%; padding: 0.7rem 1rem;
  font-family: var(--font-sans); font-size: 0.88rem; font-weight: 400;
  background: rgba(255,255,255,0.08);
  border: 1px solid rgba(255,255,255,0.22);
  color: var(--paper); border-radius: 2px; outline: none;
  transition: border-color 150ms, background 150ms;
  appearance: none; -webkit-appearance: none;
}
.cta-form input::placeholder { color: rgba(250,248,243,0.45); }
.cta-form input:focus,
.cta-form select:focus { border-color: rgba(255,255,255,0.55); background: rgba(255,255,255,0.13); }
.cta-form select { cursor: pointer; color: rgba(250,248,243,0.85); }
.cta-form select option { background: var(--cta-bg); color: var(--paper); }
.cta-form__note { font-family: var(--font-mono); font-size: 0.68rem; color: var(--paper-faint); letter-spacing: 0.04em; margin-top: 0.1rem; }
.cta-form .btn--primary { width: 100%; justify-content: center; margin-top: 0.2rem; }
.cta-form__alt { font-family: var(--font-sans); font-size: 0.82rem; color: var(--paper-faint); text-align: center; margin-top: 0.5rem; }
.cta-form__alt a { color: var(--paper-dim); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 2px; }
.cta-form__alt a:hover { color: var(--paper); }
.cta-form__alert {
  padding: 0.75rem 1rem; border-radius: 2px;
  font-family: var(--font-sans); font-size: 0.88rem; line-height: 1.5;
}
.cta-form__alert--success { background: rgba(63,126,68,0.35); border: 1px solid rgba(63,126,68,0.55); color: var(--paper); }
.cta-form__alert--error   { background: rgba(229,36,59,0.25); border: 1px solid rgba(229,36,59,0.45); color: var(--paper); }

/* ============================================================
   Site header (sticky nav)
   ============================================================ */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: rgba(250,248,243,0.92);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--rule-soft);
}
.site-header__brand {
  font-family: var(--font-serif); font-size: 1.05rem;
  font-weight: 500; color: var(--ink); text-decoration: none;
}

/* ============================================================
   Footer
   ============================================================ */
.site-footer { background: var(--paper-warm); padding: 0 0 2rem; }
.site-footer__top { display: grid; grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr)); gap: 2.5rem; padding-bottom: 2.5rem; border-bottom: 1px solid var(--rule); }
@media (max-width: 900px) { .site-footer__top { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .site-footer__top { grid-template-columns: minmax(0, 1fr); } }
.site-footer__brand-name  { font-family: var(--font-serif); font-size: 1.15rem; font-weight: 500; color: var(--ink); }
.site-footer__about       { font-family: var(--font-sans); font-size: 0.9rem; line-height: 1.55; color: var(--ink-muted); margin: 0; max-width: 36ch; }
.site-footer__col-title   { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.18em; text-transform: uppercase; font-weight: 500; color: var(--ink-faint); margin: 0 0 1rem; }
.site-footer__list        { list-style: none; padding: 0; margin: 0; }
.site-footer__list li     { margin-bottom: 0.55rem; }
.site-footer__list a      { font-family: var(--font-sans); font-size: 0.9rem; color: var(--ink-muted); text-decoration: none; }
.site-footer__list a:hover { color: var(--ink); }
.site-footer__bottom { margin-top: 2rem; display: flex; justify-content: space-between; flex-wrap: wrap; gap: 1rem; font-family: var(--font-mono); font-size: 0.7rem; color: var(--ink-faint); letter-spacing: 0.04em; }
.site-footer__bottom a      { color: var(--ink-faint); text-decoration: none; }
.site-footer__bottom a:hover { color: var(--ink); }

/* ============================================================
   Tweaks panel — staff design tool, not a site component
   No MVP page mounts this. Its palette sits deliberately outside
   the token system, because the panel floats over the design
   rather than forming part of it. Remove once internal tooling
   is confirmed not to use it.
   ============================================================ */
.twk-panel {
  position: fixed; right: 20px; bottom: 20px; z-index: 9999;
  width: 296px; background: rgba(250,248,243,0.94); color: #14171a;
  backdrop-filter: blur(20px) saturate(160%); -webkit-backdrop-filter: blur(20px) saturate(160%);
  border: 1px solid rgba(0,0,0,0.08); border-radius: 12px;
  box-shadow: 0 12px 48px rgba(0,0,0,0.16);
  font-family: 'IBM Plex Sans', system-ui, sans-serif; font-size: 12px;
  overflow: hidden; display: none;
}
.twk-panel.is-open { display: block; }
.twk-hd { display: flex; align-items: center; justify-content: space-between; padding: 12px 12px 12px 16px; border-bottom: 1px solid rgba(0,0,0,0.06); }
.twk-hd b { font-family: 'IBM Plex Mono', monospace; font-size: 10px; letter-spacing: 0.18em; text-transform: uppercase; font-weight: 500; }
.twk-x { appearance: none; border: 0; background: transparent; padding: 0; width: 22px; height: 22px; border-radius: 6px; cursor: pointer; color: rgba(0,0,0,0.5); font-size: 16px; line-height: 1; }
.twk-x:hover { background: rgba(0,0,0,0.06); color: #14171a; }
.twk-body { padding: 14px 16px 16px; display: flex; flex-direction: column; gap: 16px; max-height: calc(100vh - 140px); overflow-y: auto; }
.twk-sec-label { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: 0.16em; text-transform: uppercase; font-weight: 500; color: rgba(0,0,0,0.55); margin-bottom: 8px; }
.twk-row { display: flex; flex-direction: column; gap: 8px; }
.twk-swatches { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 8px; }
.twk-sw { appearance: none; border: 0; padding: 0; cursor: pointer; aspect-ratio: 1/1; border-radius: 6px; border: 2px solid transparent; transition: transform 120ms, border-color 120ms; position: relative; }
.twk-sw:hover { transform: scale(1.06); }
.twk-sw.is-active { border-color: #14171a; }
.twk-sw.is-active::after { content: ''; position: absolute; inset: 4px; border: 1.5px solid rgba(255,255,255,0.85); border-radius: 3px; }
.twk-name { font-family: 'IBM Plex Sans', sans-serif; font-size: 11px; color: rgba(0,0,0,0.7); font-weight: 500; display: flex; justify-content: space-between; align-items: baseline; }
.twk-name .twk-val { font-family: 'IBM Plex Mono', monospace; font-size: 10px; color: rgba(0,0,0,0.45); letter-spacing: 0.04em; }
.twk-toggle { display: flex; align-items: center; justify-content: space-between; padding: 6px 0; }
.twk-switch { appearance: none; border: 0; padding: 0; cursor: pointer; width: 32px; height: 18px; border-radius: 999px; background: rgba(0,0,0,0.18); position: relative; transition: background 120ms; }
.twk-switch::after { content: ''; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,0.2); transition: transform 160ms; }
.twk-switch.is-on { background: #3F7E44; }
.twk-switch.is-on::after { transform: translateX(14px); }
/* ============================================================
   Background rhythm
   Grounds are assigned by what a section does, not by simple
   alternation:

     paper   the argument          requirements · screen · claims · evidence · FAQ
     ink     the measured facts    metrics ribbon under the hero
     sand    process and service   curation · existing holdings
     slate   measurement + method  360° Impact · transparency
     navy    the two absolutes     integrity vs impact · cost
     green   the ask               CTA

   Two rules hold it together. No two adjacent sections share a
   ground, and the two mid-tones are drawn from opposite
   temperatures — sand is warm, slate is cool — so they never
   read as the same colour when they land near each other.
   Anything sitting ON a ground (cards, chips, the proof block)
   takes paper, so it always lifts off it.
   ============================================================ */
.section--slate              { background: var(--paper-slate); }
.section--slate .card        { background: var(--paper); }
.section--slate .faq__item   { background: var(--paper); }
.section--slate .chip        { background: var(--paper); }
.section--slate .proof       { background: var(--paper); }
.section--slate .hero__claim { background: var(--paper); }
.section--slate .claimtabs   { background: var(--sdg-partner-dk); }

/* ============================================================
   Content components
   Cards, lists, expandable questions, closing lines, claim tabs
   and the Impact Band table.
   ============================================================ */
.cards        { display: grid; gap: 1.25rem; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.cards--wide  { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.cards--stack { grid-template-columns: minmax(0, 1fr); }
/* Claim panel reused outside the hero — same alternation as .card */
.cards--2up   { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 860px) { .cards--2up { grid-template-columns: minmax(0, 1fr); } }
.section--warm .hero__claim { background: var(--paper); }
/* Cards sit on the opposite paper step from their section: warm on plain
   sections, plain on warm sections. Border stays --rule in both. */
.card         { background: var(--paper-warm); border: 1px solid var(--rule); padding: 1.75rem; transition: border-color 120ms; }
.section--warm .card { background: var(--paper); }
.card:hover   { border-color: var(--ink); }
.card--compact { padding: 1.1rem 1.25rem; }
.card__title  { margin: 0 0 0.6rem; }
.card__text   { margin: 0; }
.card__key    { display: inline-block; margin-right: 0.55rem; vertical-align: 0.02em; }

/* ------------------------------------------------------------
   Card roles and the tab treatment · v2.3
   A role says what a card states; the colour follows the role,
   never the card's position, so a colour means the same thing
   wherever it lands.
     .card--absolute  a position the method never moves on   navy
     .card--method    how the method works                   partner blue
     .card--caution   the conservative default, the gap      energy yellow
     .card--yes       what passes, or what can be done       climate green
     .card--no        what fails, or what cannot be done     poverty red
   Yes and no match the verdict colours (meets green, fail red)
   on purpose, and are only for a card stating one side of a
   pass/fail or can/cannot contrast.
     --role       ground for the tab label (dark enough for small type)
     --role-edge  the brighter version, for the top edge
     --role-on    type set on --role
   ------------------------------------------------------------ */
.card--absolute { --role: var(--sdg-partner-dk); --role-edge: var(--sdg-partner-dk); --role-on: var(--paper); }
.card--method   { --role: var(--sdg-partner);    --role-edge: var(--sdg-partner);    --role-on: var(--paper); }
.card--caution  { --role: var(--sdg-energy);     --role-edge: var(--sdg-energy);     --role-on: var(--ink);   }
.card--yes      { --role: var(--sdg-climate-dk); --role-edge: var(--sdg-climate);    --role-on: var(--paper); }
.card--no       { --role: var(--sdg-poverty-dk); --role-edge: var(--sdg-poverty);    --role-on: var(--paper); }

/* Card parts. .card__cap holds label and title; .card__body holds
   the rest, so a pair of cards can line their bodies up. */
.card__cap      { display: block; }
.card__body > :first-child { margin-top: 0; }
.card__eyebrow  { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem; margin: 0 0 0.9rem;
                  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.16em; line-height: 1.3;
                  text-transform: uppercase; font-weight: 500; color: var(--ink-faint); }
/* A criterion code keeps its case, so it matches the evidence pack. */
.card__eyebrow code { font-family: var(--font-mono); font-size: 1.12em; letter-spacing: 0.02em; text-transform: none; }
.card__title code { font-family: var(--font-mono); font-size: 0.8em; font-weight: 500; color: var(--sdg-partner); }

/* Verdict tally: counts the card's own text already states, set so
   they read at a glance. Uses the existing .verdict badge. */
.card__tally    { list-style: none; margin: 0 0 1.15rem; padding: 0.75rem 0; display: flex; flex-wrap: wrap;
                  gap: 0.5rem 1.5rem; border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule); }
.card__tally li { display: flex; align-items: baseline; gap: 0.5rem; }
.card__tally b  { font-family: var(--font-serif); font-size: 1.4rem; font-weight: 500; line-height: 1; color: var(--ink); }

/* Tab. A file-divider tab in the role colour carries the label and
   sits on a matching top edge. Each card spans two row tracks and
   takes them as a subgrid, so the bodies of cards in the same row
   start on the same line however long a title runs.
   Row spacing lives on the cards, not the grid: a subgrid would
   otherwise absorb the grid's gap between a cap and its body. The
   container's negative bottom margin returns the last row's. */
.cards--tab       { row-gap: 0; margin-bottom: -1.25rem; }
.cards--tab .card { position: relative; display: grid; grid-row: span 2; grid-template-rows: subgrid;
                    row-gap: 0; align-content: start;
                    margin: 1.75rem 0 1.25rem; padding: 1.8rem 1.9rem 1.9rem;
                    border-top: 3px solid var(--role-edge, var(--ink)); }
.cards--tab .card:hover { border-color: var(--ink); border-top-color: var(--role-edge, var(--ink)); }
.cards--tab .card__eyebrow { position: absolute; left: -1px; bottom: calc(100% + 3px); margin: 0;
                    padding: 0.5rem 0.9rem 0.45rem; border-radius: 2px 2px 0 0;
                    background: var(--role, var(--ink)); color: var(--role-on, var(--paper)); }
.cards--tab .card__eyebrow .deflist__tier { background: var(--paper); color: var(--ink); }
.cards--tab .card__title { font-size: 1.5rem; line-height: 1.25; margin-bottom: 0.8rem; }

.list         { list-style: none; padding: 0; margin: 0; }
.list li      { font-family: var(--font-sans); font-size: 0.95rem; line-height: 1.6; color: var(--ink-muted);
                padding: 0.7rem 0 0.7rem 1.5rem; border-bottom: 1px dashed var(--rule-soft); position: relative; }
.list li:last-child { border-bottom: none; }
.list li::before { content: '\2713'; position: absolute; left: 0; top: 0.66rem;
                font-family: var(--font-sans); font-size: 0.92rem; color: var(--sdg-climate); font-weight: 500; }
.list strong  { color: var(--ink); font-weight: 500; }

.faq          { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); align-items: start; }
.faq__item    { background: var(--paper-warm); border: 1px solid var(--rule); }
.section--warm .faq__item { background: var(--paper); }
.faq__q       { font-family: var(--font-sans); font-size: 1.0625rem; font-weight: 500; color: var(--ink);
                padding: 1.15rem 1.4rem; cursor: pointer; list-style: none;
                display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; }
.faq__q::-webkit-details-marker { display: none; }
.faq__q::after { content: '+'; font-family: var(--font-mono); font-size: 0.95rem; color: var(--sdg-climate); }
.faq__item[open] .faq__q::after { content: '\2212'; }
.faq__a       { margin: 0; padding: 0 1.4rem 1.35rem; }

/* v2.4 — single-column accordion. The card grid stays right for four short
   questions; a long list reads better stacked, with the rules doing the
   separating instead of nine boxes. */
.faq--stack   { display: block; border-top: 1px solid var(--rule); }
.faq--stack .faq__item { background: none; border: 0; border-bottom: 1px solid var(--rule); }
.section--warm .faq--stack .faq__item,
.section--slate .faq--stack .faq__item { background: none; }
.faq--stack .faq__q { padding: 1.2rem 0.2rem; }
.faq--stack .faq__a { max-width: 76ch; padding: 0 0.2rem 1.4rem; }

.closer       { margin-top: 2rem; font-family: var(--font-serif); font-size: 1.35rem; line-height: 1.4;
                font-weight: 500; color: var(--ink); letter-spacing: -0.01em; }
.integrity .closer { color: var(--paper); }
/* v2.4 — the same pull line on a plate rather than bare on the ground, for
   the closing statement of a section that has been making a case. Navy for an
   absolute, green for the ask. Never more than one per section. */
.closer--plate { margin-top: 1rem; padding: 1.2rem 1.4rem; background: var(--sdg-partner-dk);
                 color: var(--paper); font-weight: 400; text-align: center; }
.closer--plate.closer--ask { background: var(--cta-bg); }

.cta__list    { list-style: none; padding: 0; margin: 1.35rem 0 0; }
.cta__list li { font-family: var(--font-sans); font-size: 0.9rem; line-height: 1.55;
                color: rgba(250,248,243,0.7); padding: 0.3rem 0 0.3rem 1.3rem; position: relative; }
.cta__list li::before { content: '\2713'; position: absolute; left: 0; font-family: var(--font-sans); color: var(--sdg-energy); }

/* Hero runs headline and buttons left, explanatory prose right, so the
   columns align at the top rather than the foot (.hero__grid ships end). */
.hero__grid   { align-items: start; }   /* 7fr / 5fr comes from the design system */
.hero__side   { padding-top: 0.4rem; }
.hero__body   { margin: 1.15rem 0 0; max-width: 62ch; }
.hero__side .hero__body:first-child { margin-top: 0; }

/* Provisional badge — uses the new --sdg-energy-dk token, since #FCC30B
   does not meet contrast as text on paper. */
.badge        { display: inline-block; margin-left: 0.5rem; padding: 0.18em 0.5em;
                font-family: var(--font-mono); font-size: 0.6rem; letter-spacing: 0.12em;
                text-transform: uppercase; vertical-align: 0.18em; border: 1px solid currentColor; }
.badge--provisional { color: var(--sdg-energy-dk); }

.list--split  { columns: 2; column-gap: 3.5rem; }
.list--split li { break-inside: avoid; -webkit-column-break-inside: avoid; }
.list--split li:last-child { border-bottom: 1px dashed var(--rule-soft); }
@media (max-width: 860px) { .list--split { columns: 1; } }

.list--tight  { margin-top: 1rem; border-top: 1px dashed var(--rule-soft); }
.list--tight li { font-size: 0.9rem; padding-top: 0.6rem; padding-bottom: 0.6rem; }

/* Reversed claim panel — the four cards above it are all paper, so the
   sample claim drops out on the navy already used by the .integrity bands.
   Green accents do not carry on navy, so the label goes to paper and the
   rule, accent border and reference move to amber. */
.claimtabs               { background: var(--sdg-partner-dk); border-color: var(--sdg-partner-dk);
                           border-left-color: var(--sdg-energy); }
.section--warm .claimtabs { background: var(--sdg-partner-dk); }
.claimtabs::before       { color: var(--paper); opacity: 0.16; }
.claimtabs .hero__claim-label       { color: var(--paper); }
.claimtabs .hero__claim-label::after { background: var(--paper); opacity: 0.22; }
.claimtabs .hero__claim-text        { color: var(--paper); }
.claimtabs .hero__claim-foot        { color: rgba(250, 248, 243, 0.62);
                                      border-top-color: rgba(250, 248, 243, 0.18); }
.claimtabs .hero__claim-foot .ref   { color: var(--sdg-energy); }

/* Claim panel tabs — panes share one grid cell so the panel keeps the
   height of the tallest claim and the switch crossfades in place. */
.claimtabs__tabs  { display: flex; flex-wrap: wrap; gap: 0.35rem; margin: 0 0 1rem; }
.claimtabs__tab   { font-family: var(--font-mono); font-size: 0.6rem; letter-spacing: 0.1em;
                    text-transform: uppercase; color: rgba(250, 248, 243, 0.6); background: transparent;
                    border: 1px solid rgba(250, 248, 243, 0.28); padding: 0.4em 0.7em; cursor: pointer;
                    transition: color 160ms, border-color 160ms, background 160ms; }
.claimtabs__tab:hover { color: var(--paper); border-color: rgba(250, 248, 243, 0.55); }
.claimtabs__tab.is-active { color: var(--sdg-partner-dk); background: var(--paper); border-color: var(--paper); }
.claimtabs__tab:focus-visible { outline: 2px solid var(--sdg-energy); outline-offset: 2px; }
.claimtabs__panes { display: grid; }
.claimtabs__pane  { grid-area: 1 / 1; opacity: 0; transform: translateY(6px);
                    transition: opacity 260ms ease, transform 260ms ease; pointer-events: none; }
.claimtabs__pane.is-active { opacity: 1; transform: none; pointer-events: auto; }
.claimtabs__pane[hidden] { display: block; }
@media (prefers-reduced-motion: reduce) { .claimtabs__pane { transition: none; } }

.bands        { margin: 1.75rem 0 0.9rem; border-top: 1px solid var(--rule); }
.bands__row   { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem;
                padding: 0.7rem 0; border-bottom: 1px dashed var(--rule-soft); }
.bands dt     { font-family: var(--font-serif); font-size: 1.0625rem; font-weight: 500; color: var(--ink); }
.bands dd     { margin: 0; font-family: var(--font-mono); font-size: 0.85rem; color: var(--ink-muted); }

/* v2.4 — the four bands as cards with a coloured top rail, where the section
   has room for them. The rail colour is positional, like .groups: it names
   nothing and ranks nothing, and the band title carries the meaning. Still
   published with the working-values caveat. */
.bands--cards { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
                gap: 1px; margin: 1.75rem 0 0.9rem; background: var(--rule);
                border: 1px solid var(--rule); }
.bands--cards .bands__row { display: block; padding: 1.3rem; background: var(--paper);
                border-bottom: 0; border-top: 8px solid var(--band, var(--rule)); }
.bands--cards .bands__row:nth-child(1) { --band: var(--ink-faint); }
.bands--cards .bands__row:nth-child(2) { --band: var(--sdg-partner); }
.bands--cards .bands__row:nth-child(3) { --band: var(--sdg-climate); }
.bands--cards .bands__row:nth-child(4) { --band: var(--sdg-climate-dk); }
.bands--cards dd { margin-bottom: 1.6rem; font-size: 1.9rem; font-family: var(--font-serif);
                font-weight: 500; letter-spacing: -0.04em; line-height: 1; color: var(--band); }
.bands--cards dt { font-size: 1.35rem; }
.bands--cards dt .bands__note { display: block; margin-top: 0.5rem;
                font-family: var(--font-sans); font-size: 0.82rem; font-weight: 400;
                line-height: 1.55; color: var(--ink-muted); }
@media (max-width: 900px) { .bands--cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .bands--cards { grid-template-columns: minmax(0, 1fr); } }

.wheel__caption { margin-top: 1rem; }

/* ============================================================
   Page furniture and evidence components
   The lighter hero, the metrics ribbon, split section heads, and
   the components that carry the method: chip lists, standard
   chips, paired definitions, counted screen cards, the proof
   block, deliverable ticks, the commitments row and reveal.
   ============================================================ */

/* Hero — the headline column and the wheel column carry equal weight,
   so the 7/5 split of the standard hero is squared up here. */
.hero--lite .hero__grid { grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); align-items: center; gap: 3.5rem; }
@media (max-width: 1000px) { .hero--lite .hero__grid { grid-template-columns: minmax(0, 1fr); gap: 2.75rem; } }
.hero--lite .hero__display { max-width: 16ch; }
.hero--lite .hero__side { padding-top: 0; }

/* The six-step specification line. One statement, six beats — set as a
   list so it wraps as units rather than as a run of prose. */
.hero__spec { margin: 1.75rem 0 0; max-width: 52ch;
              font-family: var(--font-sans); font-size: 1.1rem; line-height: 1.6;
              letter-spacing: -0.005em; color: var(--ink-muted); }
.hero__spec b { font-weight: 600; color: var(--sdg-climate); }

/* ── Hero wheel ──────────────────────────────────────────────────────
   The site mark, stepping through its six domains and naming the goals
   inside each. Structure only: no sector here carries a score, so the
   radius is constant and only opacity moves. */
.hw { position: relative; width: 100%; max-width: 360px; margin: 0 auto; }
.hw__svg { display: block; width: 100%; height: auto; overflow: visible; }
.hw__sec { cursor: pointer; opacity: 0.2; transform-origin: 225px 225px;
           transition: opacity .55s ease, transform .55s ease; outline: none; }
.hw__sec.is-on { opacity: 1; transform: scale(1.035); }
.hw__sec:focus-visible { opacity: 1; }
.hw__mark { font-family: var(--font-serif); font-weight: 700; letter-spacing: -0.02em; fill: var(--ink); pointer-events: none; }
.hw__mark--num { font-size: 50px; }
.hw__mark--den { font-family: var(--font-mono); font-size: 12px; font-weight: 400; letter-spacing: 0.12em; fill: var(--ink-faint); }

/* Caption block is a fixed height: the goal count varies by domain and a
   jumping hero is worse than a little white space. */
.hw__cap { max-width: 400px; margin: 1.5rem auto 0; padding-top: 1.25rem;
           border-top: 1px solid var(--rule); min-height: 178px; }
.hw__cap-id  { font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.18em;
               text-transform: uppercase; color: var(--ink-faint); margin: 0 0 0.35rem; }
.hw__cap-ttl { font-family: var(--font-serif); font-size: 1.55rem; font-weight: 500;
               letter-spacing: -0.015em; color: var(--ink); margin: 0 0 0.9rem; }
.hw__goals   { display: flex; flex-direction: column; gap: 0.4rem; }
.hw__goal    { display: flex; align-items: center; gap: 0.65rem;
               font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.35; color: var(--ink-muted);
               opacity: 0; transform: translateY(4px); animation: hwIn .45s ease forwards; }
.hw__goal b  { flex: none; width: 26px; height: 26px; display: flex; align-items: center; justify-content: center;
               font-family: var(--font-mono); font-size: 0.72rem; font-weight: 500; }
@keyframes hwIn { to { opacity: 1; transform: none; } }
.hw + .hw__cap { margin-top: 1.5rem; }
@media (max-width: 1000px) { .hw__cap { min-height: 0; } }
@media (prefers-reduced-motion: reduce) {
  .hw__sec  { transition: none; opacity: 1; }
  .hw__goal { animation: none; opacity: 1; transform: none; }
}

/* ── Specification strip ─────────────────────────────────────────── */
.trust__list { gap: 1.2rem 2rem; }
.trust__item { align-items: baseline; gap: 0.6rem; }
.trust__num  { font-family: var(--font-serif); font-size: 1.6rem; font-weight: 500;
               line-height: 1; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.trust__item:nth-child(1) .trust__num { color: var(--sdg-energy); }
.trust__item:nth-child(2) .trust__num { color: var(--sdg-water); }
.trust__item:nth-child(3) .trust__num { color: var(--sdg-life); }
.trust__item:nth-child(4) .trust__num { color: var(--sdg-cities); }
.trust__item:nth-child(5) .trust__num { color: var(--sdg-gender); }

/* ── The two specification decisions ─────────────────────────────── */

/* The dark bands set .t-lead margins to zero via .t-lead itself; the head
   needs air between the heading and the standfirst. */
.integrity .t-h2 + .t-lead { margin-top: 1rem; }

/* Inline verdict and criterion codes, where the evidence-pack tokens
   appear in prose. */
.t-body code, .card__text code { font-family: var(--font-mono); font-size: 0.86em; color: var(--sdg-partner); }

/* ============================================================
   v14 — split section heads, requirement cards, definitions,
   screening summary, evidence grid, commitments, reveal
   ============================================================ */

/* Heading left, standfirst right. Applied wherever a section has both,
   so the eye gets a consistent two-beat opening. */
.section__head--split { max-width: none; display: grid;
                        grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
                        gap: 2rem 4rem; align-items: end; }
.section__head--split > *:last-child { padding-bottom: 0.2rem; }
@media (max-width: 900px) {
  .section__head--split { grid-template-columns: minmax(0, 1fr); gap: 1.25rem; align-items: start; }
}
.integrity .section__head { margin-bottom: 3rem; }
.integrity .section__head .t-h2 { color: var(--paper); }

/* Requirement cards */
.req__id   { font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.16em;
             text-transform: uppercase; color: var(--sdg-climate-dk); font-weight: 500; margin: 0 0 0.9rem; }
.req .bands { margin-top: 1.5rem; }
.req__link { margin-top: 1.25rem; }

/* Claim categories — a stacked set of rows rather than free-floating pills,
   so they read as a closed list of four. */
.chiplist { list-style: none; margin: 1.5rem 0 0; padding: 0; display: grid; gap: 0.5rem; }
.chiplist li { font-family: var(--font-sans); font-size: 0.92rem; line-height: 1.45; color: var(--ink);
               background: var(--paper-warm); border: 1px solid var(--rule);
               border-left: 3px solid var(--rule); padding: 0.6rem 0.85rem; }
.section--warm .chiplist li,
.section--slate .chiplist li { background: var(--paper); }
.chiplist li:nth-child(1) { border-left-color: var(--sdg-poverty); }
.chiplist li:nth-child(2) { border-left-color: var(--sdg-energy); }
.chiplist li:nth-child(3) { border-left-color: var(--sdg-climate); }
.chiplist li:nth-child(4) { border-left-color: var(--sdg-partner); }
.chiplist__note { display: block; font-family: var(--font-mono); font-size: 0.66rem;
                  letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-faint); margin-top: 0.25rem; }

/* Framework chips in a section head */
.chips { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1.25rem; }
.chip  { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.08em;
         color: var(--sdg-partner); background: var(--paper-warm);
         border: 1px solid var(--rule); padding: 0.35rem 0.6rem; }
.section--warm .chip { background: var(--paper); }

/* Integrity / impact definitions, on navy */
.defs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.5rem; }
@media (max-width: 820px) { .defs { grid-template-columns: minmax(0, 1fr); } }
.def { border: 1px solid rgba(250, 248, 243, 0.16); padding: 2rem; background: rgba(250, 248, 243, 0.03);
       display: flex; flex-direction: column; }
.def__tag   { font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.16em; text-transform: uppercase;
              color: var(--sdg-energy); font-weight: 500; margin: 0 0 0.9rem; }
.def__title { font-family: var(--font-serif); font-size: 1.6rem; font-weight: 400; line-height: 1.22;
              letter-spacing: -0.016em; color: var(--paper); margin: 0 0 0.8rem; }
.def__text  { font-family: var(--font-sans); font-size: 0.98rem; line-height: 1.65;
              color: rgba(250, 248, 243, 0.72); margin: 0; }
/* Pushed to the foot of the card so the rule lines up across both. */
.def__rule  { font-family: var(--font-serif); font-size: 1.02rem; line-height: 1.5; color: var(--paper);
              margin: 1.5rem 0 0; padding-top: 1.25rem; border-top: 1px solid rgba(250, 248, 243, 0.18);
              margin-top: auto; }

/* Screening summary — three cards with a large count */
.screen { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.5rem; }
@media (max-width: 900px) { .screen { grid-template-columns: minmax(0, 1fr); } }
.screen__card  { border-top: 3px solid var(--rule); padding-top: 1.5rem; }
.screen__card:nth-child(1) { border-top-color: var(--sdg-poverty); }
.screen__card:nth-child(2) { border-top-color: var(--sdg-energy); }
.screen__card:nth-child(3) { border-top-color: var(--sdg-climate); }
/* Bottom-aligned in a fixed box so the three headings sit on one line. */
.screen__count { font-family: var(--font-serif); font-size: 3.2rem; line-height: 0.9; font-weight: 500;
                 letter-spacing: -0.03em; color: var(--ink); margin: 0 0 0.9rem; font-variant-numeric: tabular-nums;
                 display: flex; align-items: flex-end; min-height: 2.9rem; }
.screen__count--word { font-size: 2.4rem; }
.screen__title { margin: 0 0 0.6rem; }
.screen__text  { font-size: 0.95rem; }

/* Exclusion rate */
.proof { margin-top: 3.5rem; padding: 2.25rem 2.5rem; background: var(--paper-warm); border: 1px solid var(--rule);
         display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 2.5rem; align-items: center; }
.section--warm .proof { background: var(--paper); }
@media (max-width: 760px) { .proof { grid-template-columns: minmax(0, 1fr); gap: 1.25rem; padding: 1.75rem; } }
.proof__stat  { font-family: var(--font-serif); font-size: clamp(3rem, 7vw, 4.25rem); line-height: 0.85;
                font-weight: 500; letter-spacing: -0.03em; color: var(--sdg-education); margin: 0; }
.proof__text  { max-width: 68ch; }
.proof__links { display: flex; flex-wrap: wrap; gap: 1.5rem; margin-top: 1rem; }
.proof__links .arr { display: inline-block; transition: transform 200ms; }
.proof__links a:hover .arr { transform: translateX(3px); }

/* Evidence pack */
.ev { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.75rem 3rem; }
@media (max-width: 980px) { .ev { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px)  { .ev { grid-template-columns: minmax(0, 1fr); } }
.ev__item  { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0.9rem; align-items: start;
             padding-top: 1.1rem; border-top: 1px solid var(--rule); }
.ev__tick  { font-size: 0.95rem; line-height: 1.5; color: var(--sdg-climate-dk); }
.ev__title { margin: 0 0 0.35rem; }
.ev__text  { font-size: 0.92rem; line-height: 1.55; }

/* Commitments row, on navy */
.commit { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 2rem; }
@media (max-width: 1000px) { .commit { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.75rem; } }
@media (max-width: 560px)  { .commit { grid-template-columns: minmax(0, 1fr); } }
.commit__item { border-top: 1px solid var(--rule); padding-top: 1rem; }
.commit__item b    { display: block; font-family: var(--font-sans); font-size: 1rem; font-weight: 500;
                     color: var(--ink); margin-bottom: 0.4rem; }
.commit__item span { font-family: var(--font-sans); font-size: 0.9rem; line-height: 1.55;
                     color: var(--ink-muted); }
/* v2.4 fix — .commit is documented "on navy" but carried ink colours, so on the
   ground it was written for it rendered at 1.3:1. These are the dark-ground
   values; the light ones above stay, because the styleguide demos it on paper. */
.on-dark .commit__item, .section--navy .commit__item,
.section--green .commit__item, .integrity .commit__item, .cta .commit__item {
                     border-top-color: var(--rule-dark); }
.on-dark .commit__item b, .section--navy .commit__item b,
.section--green .commit__item b, .integrity .commit__item b, .cta .commit__item b {
                     color: var(--paper); }
.on-dark .commit__item span, .section--navy .commit__item span,
.section--green .commit__item span, .integrity .commit__item span, .cta .commit__item span {
                     color: var(--paper-dim); }

/* The same gap on .closer and .list: .integrity already had a rule, the new
   ground modifiers did not. */
.section--navy .closer, .section--green .closer, .on-dark .closer { color: var(--paper); }
.on-dark .list li, .section--navy .list li, .section--green .list li { color: var(--paper-dim);
                     border-bottom-color: var(--rule-dark); }
.on-dark .list strong, .section--navy .list strong, .section--green .list strong { color: var(--paper); }
.on-dark .list li::before, .section--navy .list li::before,
.section--green .list li::before { color: var(--sdg-energy); }

/* Reveal on scroll. The hidden state is applied only once the script has
   run, so the page is fully readable if JavaScript never arrives. */
.has-reveal .reveal { opacity: 0; transform: translateY(16px);
                      transition: opacity 700ms cubic-bezier(.22,.61,.36,1), transform 700ms cubic-bezier(.22,.61,.36,1); }
.has-reveal .reveal.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .has-reveal .reveal { opacity: 1; transform: none; transition: none; }
}


/* ============================================================
   Definition list
   A term and its explanation, numbered by default. Carries the
   exclusion gates, the criterion questions inside each group,
   and the Tier 1 set.

   The term may be a plain name or the mono token that appears
   in the evidence pack, so a reader can match a line on the
   site to the same line on their own screen. --2col halves a
   long set; --plain drops the numbering where the order is not
   the point.
   ============================================================ */
.deflist          { list-style: none; margin: 1.75rem 0 0; padding: 0; display: grid;
                    counter-reset: deflist; }
.deflist--2col    { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 3.5rem; }
@media (max-width: 860px) { .deflist--2col { grid-template-columns: minmax(0, 1fr); } }

.deflist li       { display: grid; grid-template-columns: 2.4rem minmax(0, 1fr); gap: 0.9rem;
                    align-items: start; padding: 1rem 0;
                    border-bottom: 1px dashed var(--rule-soft); }
.deflist li::before { counter-increment: deflist;
                    content: counter(deflist, decimal-leading-zero);
                    font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.08em;
                    font-weight: 500; color: var(--sdg-climate-dk); padding-top: 0.28rem; }
.deflist--plain li          { grid-template-columns: minmax(0, 1fr); }
.deflist--plain li::before  { content: none; }

.deflist__term    { font-family: var(--font-sans); font-size: 1rem; font-weight: 500;
                    color: var(--ink); margin: 0 0 0.3rem;
                    display: flex; align-items: baseline; gap: 0.55rem; flex-wrap: wrap; }
.deflist__term code { font-family: var(--font-mono); font-size: 0.92em; font-weight: 500;
                    color: var(--sdg-partner); }
.deflist__text    { font-family: var(--font-sans); font-size: 0.92rem; line-height: 1.6;
                    color: var(--ink-muted); margin: 0; }

/* Tier 1 is a stricter passing verdict, not a heavier weight. The mark is
   flat ink so it reads as a label rather than a score. */
.deflist__tier    { font-family: var(--font-mono); font-size: 0.55rem; letter-spacing: 0.14em;
                    text-transform: uppercase; font-weight: 600; color: var(--paper);
                    background: var(--ink); padding: 0.16rem 0.42rem; }

/* Inside an expandable group the list follows the summary directly. */
.faq__a .deflist  { margin-top: 0.4rem; }
.deflist__note    { font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.6;
                    color: var(--ink-faint); margin: 1.1rem 0 0; max-width: 74ch; }

/* ============================================================
   Area accordion and criteria key
   The twenty criteria in their six areas, on /methodology.php.
   One full-width panel per area, each carrying its area colour
   on a left rail that thickens when open. Native details and
   summary, as .faq, so every criterion is in the page for search
   and print whether its area is open or not. Inside sits the
   unchanged .deflist .deflist--plain, set --2col.

   Area colours follow position: the five swatch colours in
   swatch order, then navy for the sixth, set by data-area on the
   item and on each key block. They name nothing and rank
   nothing; the area title carries the meaning. Colour appears
   as a rail or a block, never as a round dot, because the dot
   belongs to .verdict and a green dot beside a criterion would
   read as "meets". Colour is never used as text here: energy
   yellow and water cyan do not hold contrast on paper.

   The key above the accordion is twenty equal blocks, one per
   criterion. Equal on purpose: blocks sized by area would read
   as weighting, and the method has none.

   Built for the slate ground (and sand). The panels are paper,
   so on a plain paper section they would not lift.
   ============================================================ */
.groups__item[data-area="1"], .gkey__cell[data-area="1"] { --area: var(--sdg-poverty); }
.groups__item[data-area="2"], .gkey__cell[data-area="2"] { --area: var(--sdg-energy); }
.groups__item[data-area="3"], .gkey__cell[data-area="3"] { --area: var(--sdg-climate); }
.groups__item[data-area="4"], .gkey__cell[data-area="4"] { --area: var(--sdg-water); }
.groups__item[data-area="5"], .gkey__cell[data-area="5"] { --area: var(--sdg-partner); }
.groups__item[data-area="6"], .gkey__cell[data-area="6"] { --area: var(--sdg-partner-dk); }

/* Accordion */
.groups         { display: grid; gap: 0.625rem; }
.groups__item   { background: var(--paper); border: 1px solid var(--rule); border-left: 0;
                  box-shadow: inset 6px 0 0 var(--area, var(--rule)); scroll-margin-top: 6rem;
                  transition: box-shadow 240ms cubic-bezier(.22,.61,.36,1), border-color 160ms; }
.groups__item:not([open]):hover { border-color: var(--ink); }
.groups__item[open] { box-shadow: inset 10px 0 0 var(--area, var(--rule)); }

.groups__head   { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center;
                  gap: 0.75rem 2rem; padding: 1.4rem 1.5rem 1.4rem 2.5rem; list-style: none; cursor: pointer; }
.groups__head::-webkit-details-marker { display: none; }
.groups__head::marker { content: ''; }
.groups__head:focus-visible { outline: 2px solid var(--sdg-partner); outline-offset: 3px; }
.groups__item[open] > .groups__head { border-bottom: 1px solid var(--rule-soft); }

.groups__title  { display: block; font-family: var(--font-serif); font-size: 1.375rem; font-weight: 500;
                  line-height: 1.25; letter-spacing: -0.012em; color: var(--ink); }
.groups__meta   { display: flex; align-items: center; justify-content: flex-end; gap: 0.75rem; flex-wrap: wrap; }
.groups__count  { font-family: var(--font-mono); font-size: 0.78rem; color: var(--ink-muted); white-space: nowrap; }
.groups__meta .deflist__tier { white-space: nowrap; }

/* The control: a drawn plus that loses its upright when open. */
.groups__ctl    { position: relative; flex: none; width: 2.25rem; height: 2.25rem;
                  border: 1px solid var(--rule); transition: border-color 160ms; }
.groups__ctl::before,
.groups__ctl::after { content: ''; position: absolute; left: 50%; top: 50%; width: 0.8rem; height: 1.5px;
                  margin: -0.75px 0 0 -0.4rem; background: var(--sdg-climate);
                  transition: transform 220ms cubic-bezier(.22,.61,.36,1); }
.groups__ctl::after { transform: rotate(90deg); }
.groups__item[open] > .groups__head .groups__ctl::after { transform: rotate(0deg); }
.groups__head:hover .groups__ctl { border-color: var(--ink); }

.groups__body   { padding: 0.25rem 1.5rem 1.9rem 2.5rem; }
.groups__body .deflist { margin-top: 0; }
.groups__body .deflist li:last-child { border-bottom: 0; }
.groups__body .deflist--2col li:nth-last-child(2):nth-child(odd) { border-bottom: 0; }
.groups__item[open] > .groups__body { animation: groups-open 260ms cubic-bezier(.22,.61,.36,1); }
@keyframes groups-open { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

@media (max-width: 700px) {
  .groups__head { grid-template-columns: minmax(0, 1fr) auto; padding: 1.2rem 1.25rem 1.2rem 1.75rem; }
  .groups__meta { grid-column: 1; grid-row: 2; justify-content: flex-start; }
  .groups__ctl  { grid-column: 2; grid-row: 1 / span 2; align-self: start; }
  .groups__body { padding: 0.25rem 1.25rem 1.5rem 1.75rem; }
}
@media (prefers-reduced-motion: reduce) {
  .groups__item, .groups__ctl, .groups__ctl::before, .groups__ctl::after { transition: none; }
  .groups__item[open] > .groups__body { animation: none; }
}

/* Key. The block grid and the label grid share twenty columns
   and one gap, so every block is the same width and each label
   sits exactly under its run. A label spans its run with an
   inline grid-column: span n, where n is the area's count. */
.gkey           { margin: 0 0 2.25rem; }
.gkey__cells,
.gkey__labels   { display: grid; grid-template-columns: repeat(20, minmax(0, 1fr)); column-gap: 3px; }
.gkey__cell     { position: relative; height: 18px; background: var(--area, var(--rule)); }
.gkey__cell.is-t1::after { content: ''; position: absolute; left: 0; right: 0; bottom: -8px; height: 3px;
                  background: var(--ink); }
.gkey__labels   { list-style: none; margin: 1.1rem 0 0; padding: 0; }
.gkey__labels li { min-width: 0; border-left: 1px solid var(--ink-ghost); padding: 0.15rem 0 0 0.55rem; }
.gkey__labels a { display: block; font-family: var(--font-sans); font-size: 0.85rem; font-weight: 500;
                  line-height: 1.35; color: var(--ink); text-decoration: none; overflow-wrap: anywhere; }
.gkey__labels a:hover { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
.gkey__labels a:focus-visible { outline: 2px solid var(--sdg-partner); outline-offset: 2px; }
.gkey__n        { display: block; margin-top: 0.15rem; font-family: var(--font-mono); font-size: 0.7rem;
                  font-weight: 400; color: var(--ink-faint); }
.gkey__caption  { margin-top: 1rem; max-width: 64ch; }
@media (max-width: 760px) { .gkey__labels { display: none; } }

/* ============================================================
   Figures table
   Worked arithmetic the reader is meant to check: the portfolio
   weighting, the scoring ladder, the price build-up. Numerals
   are mono and right aligned so a column compares down the page.
   It scrolls rather than wraps on a narrow screen, because a
   reflowed calculation is no longer a calculation.
   ============================================================ */
.figures            { margin-top: 1.75rem; overflow-x: auto; }
.figures table      { width: 100%; border-collapse: collapse; min-width: 34rem; }
.figures th         { text-align: left; font-family: var(--font-mono); font-size: 0.58rem;
                      letter-spacing: 0.16em; text-transform: uppercase; font-weight: 500;
                      color: var(--ink-faint); padding: 0 1.25rem 0.65rem 0;
                      border-bottom: 1px solid var(--rule); }
.figures td         { padding: 0.85rem 1.25rem 0.85rem 0; border-bottom: 1px solid var(--rule-soft);
                      font-family: var(--font-sans); font-size: 0.95rem; line-height: 1.5;
                      color: var(--ink); vertical-align: top; }
.figures th:last-child, .figures td:last-child { padding-right: 0; }
.figures .num       { text-align: right; font-family: var(--font-mono); font-size: 0.88rem;
                      white-space: nowrap; }
.figures tbody tr:last-child td { border-bottom: none; }
.figures tfoot td   { border-top: 1px solid var(--ink); border-bottom: none;
                      font-weight: 600; padding-top: 0.95rem; }
.on-dark .figures th, .section--navy .figures th, .integrity .figures th { color: var(--paper-faint); }
.on-dark .figures td, .section--navy .figures td, .integrity .figures td {
                    color: var(--paper-dim); border-bottom-color: var(--rule-dark); }
.on-dark .figures .num, .section--navy .figures .num, .integrity .figures .num { color: var(--paper); }
.on-dark .figures tfoot td, .section--navy .figures tfoot td, .integrity .figures tfoot td {
                    color: var(--paper); border-top-color: var(--paper-faint); }
.on-dark .figures caption, .section--navy .figures caption, .integrity .figures caption { color: var(--paper-faint); }
.figures caption    { caption-side: bottom; text-align: left; margin-top: 1rem;
                      font-family: var(--font-sans); font-size: 0.82rem; line-height: 1.6;
                      color: var(--ink-faint); max-width: 74ch; }

/* ============================================================
   Document sheet
   A facsimile of a page from the delivered evidence pack. It is
   a frame rather than a screenshot: the contents are live markup
   built from site components, so a sample on the website and the
   thing it describes cannot silently drift apart.

   Every sheet carries a label saying what it is and a note saying
   what the delivered pack holds that the sample does not. A
   facsimile that implies completeness is a worse lie than no
   facsimile at all.
   ============================================================ */
.sheet          { background: var(--paper); border: 1px solid var(--rule);
                  box-shadow: 0 18px 40px rgba(20, 23, 26, 0.07); }
.sheet__bar     { display: flex; justify-content: space-between; align-items: baseline;
                  gap: 1rem; flex-wrap: wrap;
                  padding: 0.75rem 1.5rem; border-bottom: 1px solid var(--rule);
                  background: var(--paper-cool);
                  font-family: var(--font-mono); font-size: 0.58rem; letter-spacing: 0.16em;
                  text-transform: uppercase; color: var(--ink-faint); }
.sheet__body    { padding: 2rem 1.5rem 2.25rem; }
@media (min-width: 720px) { .sheet__body { padding: 2.5rem 2.5rem 2.75rem; } }
.sheet__title   { font-family: var(--font-serif); font-size: 1.5rem; line-height: 1.2;
                  letter-spacing: -0.015em; color: var(--ink); margin: 0 0 0.4rem; }
.sheet__meta    { font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.14em;
                  text-transform: uppercase; color: var(--ink-faint); margin: 0 0 1.5rem;
                  padding-bottom: 1.25rem; border-bottom: 1px solid var(--rule-soft); }
.sheet__note    { font-family: var(--font-sans); font-size: 0.82rem; line-height: 1.6;
                  color: var(--ink-faint); margin: 1.25rem 0 0; max-width: 74ch; }
.sheet__note strong { color: var(--ink-muted); }
.sheet .figures { margin-top: 0; }

/* ============================================================
   Verdict badge
   The four criterion verdicts, in the same colours the delivered
   pack uses, so a reader moving between the two is not learning
   a second vocabulary. The word is always present: the dot
   supports it and never carries the meaning alone.
   ============================================================ */
.verdict           { display: inline-flex; align-items: center; gap: 0.42rem;
                     font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.12em;
                     text-transform: uppercase; font-weight: 500; white-space: nowrap;
                     color: var(--ink); }
.verdict::before   { content: ''; width: 7px; height: 7px; border-radius: 50%; flex: none;
                     background: var(--ink-faint); }
.verdict--meets::before { background: var(--sdg-climate); }
.verdict--gap::before   { background: var(--sdg-energy); }
.verdict--fail::before  { background: var(--sdg-poverty); }
.verdict--na::before    { background: var(--ink-ghost); }

/* ============================================================
   Navigation dropdowns
   Promoted out of nav.php so the header is markup only.
   ============================================================ */
.nav-dd { position: relative; }
.nav-dd__btn {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  padding: .5rem .75rem;
  background: none;
  border: 0;
  cursor: pointer;
  line-height: 1;
  transition: color .3s;
}
.nav-dd__caret { font-size: .7em; transition: transform .25s; }
.nav-dd[aria-open="true"] .nav-dd__caret { transform: rotate(180deg); }

.nav-dd__panel {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  min-width: 240px;
  background: var(--paper);
  border: 1px solid var(--rule-soft);
  border-radius: 10px;
  box-shadow: 0 12px 32px rgba(20, 23, 26, .12);
  padding: .5rem;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity .2s, transform .2s, visibility .2s;
  z-index: 50;
}
.nav-dd[aria-open="true"] .nav-dd__panel {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.nav-dd__panel ul { list-style: none; margin: 0; padding: 0; }
.nav-dd__panel a {
  display: block;
  padding: .5rem .75rem;
  border-radius: 6px;
  font-size: .9rem;
  color: var(--ink-muted);
  text-decoration: none;
  transition: background .2s, color .3s;
}
.nav-dd__panel a:hover { background: var(--paper-slate); }

/* SDG colour hover cycle, matching mobile */
.nav-dd__panel li:nth-child(5n+1) a:hover { color: var(--sdg-poverty); }
.nav-dd__panel li:nth-child(5n+2) a:hover { color: var(--sdg-cities); }
.nav-dd__panel li:nth-child(5n+3) a:hover { color: var(--sdg-life); }
.nav-dd__panel li:nth-child(5n+4) a:hover { color: var(--sdg-water); }
.nav-dd__panel li:nth-child(5n+5) a:hover { color: var(--sdg-peace); }

/* ============================================================================
   v2.4 · 2026-09 — page and document components, §53–§65
   ----------------------------------------------------------------------------
   Promoted from the ten /preview pages. Each one replaces a shape that the
   preview built two or more times under two or more names. Built in the
   system's own geometry: square, flat, token-only, on the .t-* scale.

   Settled with the additions review, 14 Sep 2026:
     - §4 stands as written. The swatch eyebrow opens a public section; the
       document-scale label inside one page is .doc__kicker (§55).
     - Standing rule 9 is narrowed: the homepage process grid has four steps.
       Other counted sequences use .seq (§56), which is not fixed at four.
     - §18 stands. The footer is --paper-warm with the 17-colour stripe.
     - Round marks stay reserved for status. Every new connector, number box
       and arrow below is square; the one round mark added is .rec__status.
   ============================================================================ */

/* ============================================================
   Dark and green grounds
   The system could reach a dark ground only by being the
   .integrity band, and a green one only by being the .cta. Both
   are now plain ground modifiers, with .on-dark as the shared
   hook anything sitting on them inherits from.

   Scoped to the new selectors on purpose: .integrity and .cta
   keep the rules they already had, so no published page moves.
   ============================================================ */
.section--navy  { background: var(--sdg-partner-dk); border-bottom-color: var(--rule-dark); }
.section--green { background: var(--cta-bg); border-bottom: 0; }

.on-dark, .section--navy, .section--green { color: var(--paper); }
.on-dark .t-h2, .on-dark .t-h3,
.section--navy .t-h2, .section--navy .t-h3,
.section--green .t-h2, .section--green .t-h3 { color: var(--paper); font-weight: 400; }
.on-dark .t-h4, .section--navy .t-h4, .section--green .t-h4 { color: var(--paper); }
.on-dark .t-body, .on-dark .t-lead,
.section--navy .t-body, .section--navy .t-lead,
.section--green .t-body, .section--green .t-lead { color: var(--paper-dim); }
.on-dark .t-caption, .section--navy .t-caption, .section--green .t-caption { color: var(--paper-faint); }

/* ============================================================
   §53 · Page navigation
   A sticky second bar under the header carrying anchors to the
   sections of a long page. Scrolls sideways rather than wrapping,
   so a ten-section method page keeps one row on a phone. Sand
   ground, so it separates from both the header above and a plain
   section below. Maximum ten links: beyond that it is a contents
   list (§55), not a nav.
   ============================================================ */
.pagenav        { position: sticky; top: var(--header-h); z-index: 40;
                  background: var(--paper-warm); border-bottom: 1px solid var(--rule); }
.pagenav__row   { display: flex; gap: 1.75rem; overflow-x: auto; scrollbar-width: none; }
.pagenav__row::-webkit-scrollbar { display: none; }
.pagenav a      { flex: 0 0 auto; padding: 0.85rem 0; border-bottom: 2px solid transparent;
                  font-family: var(--font-sans); font-size: 0.8rem; font-weight: 500;
                  color: var(--ink-muted); text-decoration: none; white-space: nowrap;
                  transition: color 120ms, border-color 120ms; }
.pagenav a:hover,
.pagenav a[aria-current="true"] { color: var(--sdg-climate-dk); border-bottom-color: var(--sdg-climate-dk); }

/* ============================================================
   §54 · Next page
   The continuity link at the foot of a content page, above the
   CTA. One per page, always last before the CTA. The title is the
   next page's argument, not its menu label.
   ============================================================ */
.nextpage       { padding: 2.5rem 0; border-bottom: 1px solid var(--rule); }
.nextpage--band { padding: 3.5rem 0; background: var(--sdg-partner-dk); border-bottom: 0; color: var(--paper); }
.nextpage__link  { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2rem;
                   align-items: center; padding: 2.25rem; background: var(--paper);
                   border: 1px solid var(--rule); text-decoration: none;
                   transition: border-color 140ms; }
.nextpage__link:hover { border-color: var(--sdg-climate); }
.nextpage__label { display: block; margin-bottom: 0.5rem; font-family: var(--font-mono);
                   font-size: 0.68rem; letter-spacing: 0.18em; text-transform: uppercase;
                   color: var(--ink-faint); }
.nextpage__title { margin: 0; max-width: 26ch; font-family: var(--font-serif);
                   font-size: 1.75rem; font-weight: 500; line-height: 1.15; color: var(--ink); }
.nextpage__arrow { display: grid; place-items: center; width: 54px; height: 54px;
                   border: 1px solid var(--rule); color: var(--sdg-climate); font-size: 1.3rem;
                   transition: transform 160ms, background 160ms, color 160ms, border-color 160ms; }
.nextpage__link:hover .nextpage__arrow { transform: translateX(4px); background: var(--sdg-climate);
                   color: var(--paper); border-color: var(--sdg-climate); }
.nextpage--band .nextpage__link  { background: transparent; border-color: var(--rule-dark); }
.nextpage--band .nextpage__link:hover { border-color: var(--sdg-energy); }
.nextpage--band .nextpage__label { color: var(--sdg-energy); }
.nextpage--band .nextpage__title { color: var(--paper); font-weight: 400; }
.nextpage--band .nextpage__arrow { border-color: var(--rule-dark); color: var(--paper); }
.nextpage--band .nextpage__link:hover .nextpage__arrow { background: var(--sdg-energy);
                   color: var(--ink); border-color: var(--sdg-energy); }

/* ============================================================
   §55 · Long-form document and contents
   Privacy, terms, and any numbered policy or method document.
   Sticky contents left, numbered sections right.

   .doc__kicker is the document-scale eyebrow, settled 14 Sep: a
   page carries one swatch eyebrow at the top per §4, and the
   sections inside it take the kicker. Twelve five-colour swatches
   down a privacy notice would read as decoration, not structure.

   Body copy caps at 74ch here rather than 64. A clause reads worse
   broken into short lines than a marketing paragraph does.
   ============================================================ */
.doc__grid      { display: grid; grid-template-columns: 240px minmax(0, 1fr);
                  gap: 4.5rem; align-items: start; }
.toc            { position: sticky; top: calc(var(--header-h) + 3rem); padding: 1.35rem 0;
                  border-top: 3px solid var(--sdg-partner-dk); border-bottom: 1px solid var(--rule); }
.toc__title     { margin: 0 0 0.8rem; font-family: var(--font-mono); font-size: 0.7rem;
                  letter-spacing: 0.18em; text-transform: uppercase; font-weight: 500;
                  color: var(--ink-faint); }
.toc__list      { list-style: none; margin: 0; padding: 0; }
.toc__list a    { display: grid; grid-template-columns: 26px minmax(0, 1fr); gap: 0.4rem;
                  padding: 0.42rem 0; font-family: var(--font-sans); font-size: 0.82rem;
                  color: var(--ink-muted); text-decoration: none; }
.toc__list a:hover { color: var(--sdg-climate); }
.toc__n         { font-family: var(--font-mono); font-size: 0.67rem; color: var(--ink-faint); }
.doc__section   { padding-bottom: 3.5rem; margin-bottom: 3.5rem;
                  border-bottom: 1px solid var(--rule); scroll-margin-top: 6rem; }
.doc__section:last-child { padding-bottom: 0; margin-bottom: 0; border-bottom: 0; }
.doc__kicker    { display: block; margin-bottom: 0.75rem; font-family: var(--font-mono);
                  font-size: 0.72rem; letter-spacing: 0.18em; text-transform: uppercase;
                  font-weight: 500; color: var(--sdg-climate-dk); }
.doc__section .t-h3   { margin: 1.7rem 0 0.45rem; }
.doc__section .t-body { max-width: 74ch; margin-bottom: 1rem; }
.doc__section .t-body:last-child { margin-bottom: 0; }

/* ============================================================
   §56 · Numbered sequence
   One component for every counted set. Replaces sixteen spellings
   across the preview. .process keeps the homepage's four steps;
   everything else — ten gates, five market rules, three evidence
   stages — is .seq, which counts what it actually has.

   The number is climate green on paper and energy yellow on dark,
   matching .pillar__id: energy is the only warm accent permitted
   on a dark ground. The flow connector is square, because the
   round mark belongs to status.
   ============================================================ */
.seq            { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
                  border-top: 1px solid var(--rule); border-left: 1px solid var(--rule);
                  list-style: none; margin: 0; padding: 0; }
.seq--2         { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.seq--3         { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.seq--5         { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.seq__step      { position: relative; padding: 1.6rem 1.4rem;
                  border-right: 1px solid var(--rule); border-bottom: 1px solid var(--rule); }
.seq__n         { display: block; margin-bottom: 2.5rem; font-family: var(--font-mono);
                  font-size: 0.72rem; letter-spacing: 0.18em; text-transform: uppercase;
                  color: var(--sdg-climate-dk); }
.seq__title     { margin: 0 0 0.5rem; font-family: var(--font-serif); font-size: 1.35rem;
                  font-weight: 500; line-height: 1.15; color: var(--ink); }
.seq__text      { margin: 0; font-family: var(--font-sans); font-size: 0.9rem;
                  line-height: 1.6; color: var(--ink-muted); }
.seq--flow .seq__step:not(:last-child)::after {
                  content: '\2192'; position: absolute; z-index: 2; top: 50%; right: -17px;
                  display: grid; place-items: center; width: 34px; height: 34px;
                  transform: translateY(-50%); background: var(--sdg-climate);
                  color: var(--paper); font-size: 0.9rem; }
.seq--rows      { grid-template-columns: minmax(0, 1fr); border-left: 0; }
.seq--rows .seq__step { display: grid; grid-template-columns: 46px minmax(0, 1fr); gap: 1rem;
                  padding: 1.15rem 0; border-right: 0; }
.seq--rows .seq__n     { margin-bottom: 0; }
.seq--rows .seq__title { font-family: var(--font-sans); font-size: 1rem; font-weight: 500; }
.on-dark .seq, .section--navy .seq, .section--green .seq {
                  border-top-color: var(--rule-dark); border-left-color: var(--rule-dark); }
.on-dark .seq__step, .section--navy .seq__step, .section--green .seq__step {
                  border-right-color: var(--rule-dark); border-bottom-color: var(--rule-dark); }
.on-dark .seq__n, .section--navy .seq__n, .section--green .seq__n { color: var(--sdg-energy); }
.on-dark .seq__title, .section--navy .seq__title, .section--green .seq__title {
                  color: var(--paper); font-weight: 400; }
.on-dark .seq__text, .section--navy .seq__text, .section--green .seq__text { color: var(--paper-dim); }

/* ============================================================
   §57 · Record panel
   A label-and-status header, dashed key/value rows, a result line.
   The quote, the holdings summary, the registry record and the
   inherited assurance position are all this.

   The status dot is round on purpose — this is the canonical
   status mark the round-dot rule is reserved for. There is no
   red status: a record showing a failure should not be on the
   page. The result plate is navy or quiet; never green, which
   here would read as a pass verdict.
   ============================================================ */
.rec            { padding: 2rem; background: var(--paper); border: 1px solid var(--rule); }
.rec__top       { display: flex; justify-content: space-between; gap: 1rem; align-items: baseline;
                  padding-bottom: 1rem; margin-bottom: 1.4rem; border-bottom: 1px solid var(--rule); }
.rec__label     { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.14em;
                  text-transform: uppercase; color: var(--ink-faint); }
.rec__status    { display: inline-flex; align-items: center; gap: 0.45rem;
                  font-family: var(--font-sans); font-size: 0.78rem; font-weight: 600;
                  color: var(--sdg-climate-dk); }
.rec__status::before { content: ''; width: 7px; height: 7px; border-radius: 50%; flex: none;
                  background: var(--sdg-climate); }
.rec__status--pending { color: var(--sdg-energy-dk); }
.rec__status--pending::before { background: var(--sdg-energy); }
.rec__row       { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 1rem;
                  padding: 0.75rem 0; border-bottom: 1px dashed var(--rule);
                  font-family: var(--font-sans); font-size: 0.85rem; }
.rec__row > :first-child { color: var(--ink-faint); }
.rec__row > :last-child  { color: var(--ink); font-weight: 600; text-align: right; }
.rec__result    { margin: 1rem 0 0; padding: 0.95rem; background: var(--sdg-partner-dk);
                  color: var(--paper); font-family: var(--font-serif); font-size: 1.05rem;
                  text-align: center; }
.rec__result--quiet { background: var(--paper-warm); color: var(--ink-muted);
                  font-family: var(--font-sans); font-size: 0.85rem; }
.rec__note      { margin: 1rem 0 0; font-family: var(--font-sans); font-size: 0.8rem;
                  color: var(--ink-faint); }

/* ============================================================
   §58 · Marked list
   One list with a boxed mark in the gutter, in four roles.
   .list keeps its inline tick for running copy; .marks is for a
   list where the mark means something — included, out of scope,
   excluded.

   The mark is aria-hidden and the meaning lives in the <strong>.
   A reader hearing "tick" and "dash" learns nothing, which is
   Standing rule "colour alone never conveys meaning" applied to
   shape as well.
   ============================================================ */
.marks          { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.85rem; }
.marks li       { display: grid; grid-template-columns: 26px minmax(0, 1fr); gap: 0.75rem;
                  align-items: start; font-family: var(--font-sans); font-size: 0.9rem;
                  line-height: 1.6; color: var(--ink-muted); }
.marks strong   { display: block; color: var(--ink); font-weight: 500; }
.marks__m       { display: grid; place-items: center; width: 22px; height: 22px;
                  border: 1px solid var(--rule); font-size: 0.72rem; font-weight: 600;
                  color: var(--sdg-climate-dk); }
.marks--dash  .marks__m { color: var(--sdg-partner); }
.marks--cross .marks__m { color: var(--sdg-poverty); }
.marks--plain .marks__m { border: 0; width: auto; height: auto; justify-self: start; }
.marks--2up     { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.85rem 2.5rem; }
.on-dark .marks li, .section--navy .marks li, .section--green .marks li { color: var(--paper-dim); }
.on-dark .marks strong, .section--navy .marks strong, .section--green .marks strong { color: var(--paper); }
.on-dark .marks__m, .section--navy .marks__m, .section--green .marks__m {
                  border-color: var(--rule-dark); color: var(--sdg-energy); }
.on-dark .marks--dash .marks__m, .section--navy .marks--dash .marks__m { color: var(--sdg-water); }

/* ============================================================
   §59 · Explorer
   A vertical tab rail and a content panel — the full-page sibling
   of .claimtabs, which only works inside .hero__claim.

   Use it only where the panes are alternatives: one claim
   category, one domain, one record type. Never for a sequence the
   reader should see in full, because a hidden pane is not in the
   print view and is weaker for search. Sequences use .seq (§56);
   questions use .faq (§44).
   ============================================================ */
.explorer       { display: grid; grid-template-columns: minmax(240px, 0.68fr) minmax(0, 1.32fr);
                  gap: 4rem; align-items: start; }
.explorer__tabs { display: grid; border-top: 1px solid var(--rule); }
.explorer__tab  { display: grid; grid-template-columns: 32px minmax(0, 1fr) auto; gap: 0.8rem;
                  align-items: center; width: 100%; min-height: 64px; padding: 0.8rem 0.25rem;
                  border: 0; border-bottom: 1px solid var(--rule); background: transparent;
                  color: var(--ink-faint); text-align: left; cursor: pointer; font: inherit;
                  transition: color 140ms, padding-left 140ms; }
.explorer__tab:hover,
.explorer__tab[aria-selected="true"] { color: var(--ink); padding-left: 0.6rem; }
.explorer__n    { display: grid; place-items: center; width: 30px; height: 30px;
                  border: 1px solid currentColor; font-family: var(--font-mono); font-size: 0.65rem; }
.explorer__tab[aria-selected="true"] .explorer__n { background: var(--sdg-climate);
                  color: var(--paper); border-color: var(--sdg-climate); }
.explorer__name { font-family: var(--font-sans); font-size: 0.95rem; font-weight: 500; line-height: 1.25; }
.explorer__meta { font-family: var(--font-mono); font-size: 0.6rem; letter-spacing: 0.08em;
                  text-transform: uppercase; }
.explorer__panel{ padding: 2.5rem; background: var(--paper); border: 1px solid var(--rule); }
.explorer__panel[hidden] { display: none; }
.explorer__head { display: flex; justify-content: space-between; gap: 2rem; align-items: flex-start;
                  padding-bottom: 1.5rem; margin-bottom: 1.5rem; border-bottom: 1px solid var(--rule); }
.explorer__badge{ flex: 0 0 auto; padding: 0.35rem 0.65rem; background: var(--paper-warm);
                  border: 1px solid var(--rule); font-family: var(--font-mono); font-size: 0.65rem;
                  letter-spacing: 0.05em; text-transform: uppercase; color: var(--ink-muted);
                  white-space: nowrap; }
.on-dark .explorer__tabs, .section--navy .explorer__tabs { border-top-color: var(--rule-dark); }
.on-dark .explorer__tab, .section--navy .explorer__tab {
                  color: var(--paper-faint); border-bottom-color: var(--rule-dark); }
.on-dark .explorer__tab:hover, .on-dark .explorer__tab[aria-selected="true"],
.section--navy .explorer__tab:hover, .section--navy .explorer__tab[aria-selected="true"] { color: var(--paper); }
.on-dark .explorer__tab[aria-selected="true"] .explorer__n,
.section--navy .explorer__tab[aria-selected="true"] .explorer__n {
                  background: var(--sdg-energy); color: var(--ink); border-color: var(--sdg-energy); }

/* SDG goal cards — the standard body of a domain panel. Decorative SDG hex
   per §1, set through --goal on the element. */
.goals          { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.65rem; }
.goals__card    { padding: 1rem; background: var(--paper-warm);
                  border-top: 4px solid var(--goal, var(--rule)); }
.goals__n       { display: block; margin-bottom: 1.2rem; font-family: var(--font-serif);
                  font-size: 2rem; font-weight: 500; line-height: 1; color: var(--ink);
                  /* The goal colour is the top rail. It is not the numeral:
                     SDG 7 yellow measured 1.74:1 as 32px type on sand, and
                     §52 already says colour is a rail or a block, never text. */ }
.goals__name    { display: block; font-family: var(--font-sans); font-size: 0.84rem;
                  font-weight: 500; line-height: 1.3; color: var(--ink); }

/* ============================================================
   §60 · Callout
   The in-flow emphasis block. .margin-note is a margin column and
   .closer is a serif pull line; this is the one that sits inside
   prose.

   The five roles are the five card roles from §36, so the site has
   one role vocabulary rather than two. Role is chosen by what the
   callout says, never by where it sits. Green and red appear only
   as the two sides of a can/cannot contrast. Energy is a rail and
   a tint, never type — where energy must be read as text, that is
   --sdg-energy-dk. One --absolute per page at most.
   ============================================================ */
.callout        { margin-top: 1.5rem; padding: 1.3rem 1.5rem;
                  border-left: 4px solid var(--sdg-climate); background: var(--paper-tint-climate); }
.callout__title { display: block; margin-bottom: 0.3rem; font-family: var(--font-sans);
                  font-size: 1rem; font-weight: 500; color: var(--ink); }
.callout p      { margin: 0; font-family: var(--font-sans); font-size: 0.9rem;
                  line-height: 1.6; color: var(--ink-muted); }
.callout--method   { border-left-color: var(--sdg-partner); background: var(--paper-tint-partner); }
.callout--caution  { border-left-color: var(--sdg-energy);  background: var(--paper-tint-energy); }
.callout--no       { border-left-color: var(--sdg-poverty); background: var(--paper-tint-poverty); }
.callout--absolute { border-left-color: var(--sdg-energy);  background: var(--sdg-partner-dk); }
.callout--absolute .callout__title { color: var(--paper); }
.callout--absolute p { color: var(--paper-dim); }

/* ============================================================
   §61 · Data table
   Categorical data — retention periods, lawful bases, domain
   weightings. .figures stays for worked arithmetic the reader is
   meant to check. Both share the .num numeral treatment.

   Always inside .table__wrap: a table is the one thing permitted
   to scroll sideways, and it does so inside its own box rather
   than pushing the page.
   ============================================================ */
.table__wrap    { overflow-x: auto; }
.table          { width: 100%; border-collapse: collapse; border: 1px solid var(--rule);
                  background: var(--paper); font-family: var(--font-sans); }
.table caption  { padding-bottom: 0.9rem; text-align: left; font-family: var(--font-mono);
                  font-size: 0.68rem; letter-spacing: 0.16em; text-transform: uppercase;
                  color: var(--ink-faint); }
.table th, .table td { padding: 1rem 1.1rem; border-bottom: 1px solid var(--rule);
                  text-align: left; vertical-align: top; }
.table th       { background: var(--paper-warm); font-family: var(--font-mono); font-size: 0.66rem;
                  font-weight: 500; letter-spacing: 0.09em; text-transform: uppercase;
                  color: var(--ink-faint); }
.table td       { font-size: 0.88rem; line-height: 1.6; color: var(--ink-muted); }
.table td:first-child { color: var(--ink); font-weight: 500; }
.table tr:last-child td { border-bottom: 0; }
.table .num     { text-align: right; font-family: var(--font-mono); }
.on-dark .table, .section--navy .table { background: transparent; border-color: var(--rule-dark); }
.on-dark .table th, .section--navy .table th { background: transparent; color: var(--paper-faint);
                  border-bottom-color: var(--rule-dark); }
.on-dark .table td, .section--navy .table td { color: var(--paper-dim);
                  border-bottom-color: var(--rule-dark); }
.on-dark .table td:first-child, .section--navy .table td:first-child { color: var(--paper); }

/* ============================================================
   §62 · Stat grid
   Two to four large figures. .proof stays the single statistic,
   one per page; this is the row. At most one --lead cell.

   Figures are serif 500, not 600: §2 puts serif display at
   400–500, and a 3.4rem numeral at 600 shouts. Unless a brief
   says otherwise the figures are the §25 metrics ribbon —
   17 SDGs · 360 scale · 10 gates · 20 criteria · 6 domains.
   ============================================================ */
.stats          { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
                  border-top: 1px solid var(--rule); border-left: 1px solid var(--rule); }
.stats--2       { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.stats--3       { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.stats__item    { padding: 1.6rem 1.5rem; border-right: 1px solid var(--rule);
                  border-bottom: 1px solid var(--rule); }
.stats__val     { display: block; margin-bottom: 1.6rem; font-family: var(--font-serif);
                  font-size: clamp(2.6rem, 5vw, 3.4rem); font-weight: 500;
                  letter-spacing: -0.04em; line-height: 0.9; color: var(--sdg-climate); }
.stats__key     { display: block; font-family: var(--font-sans); font-size: 0.95rem;
                  font-weight: 500; line-height: 1.3; color: var(--ink); }
.stats__note    { display: block; margin-top: 0.35rem; font-family: var(--font-sans);
                  font-size: 0.78rem; color: var(--ink-faint); }
/* On a dark ground the non-lead cells need the dark ink scale; only --lead
   carried it before, so the other cells measured 1.3:1. */
.on-dark .stats, .section--navy .stats, .section--green .stats, .integrity .stats {
                  border-top-color: var(--rule-dark); border-left-color: var(--rule-dark); }
.on-dark .stats__item, .section--navy .stats__item, .section--green .stats__item, .integrity .stats__item {
                  border-right-color: var(--rule-dark); border-bottom-color: var(--rule-dark); }
.on-dark .stats__val, .section--navy .stats__val, .section--green .stats__val, .integrity .stats__val {
                  color: var(--sdg-energy); }
.on-dark .stats__key, .section--navy .stats__key, .section--green .stats__key, .integrity .stats__key {
                  color: var(--paper); }
.on-dark .stats__note, .section--navy .stats__note, .section--green .stats__note, .integrity .stats__note {
                  color: var(--paper-faint); }
.stats__item--lead { background: var(--sdg-partner-dk); }
.stats__item--lead .stats__val  { color: var(--sdg-energy); }
.stats__item--lead .stats__key  { color: var(--paper); }
.stats__item--lead .stats__note { color: var(--paper-faint); }

/* ============================================================
   §63 · Form
   The page-level enquiry form, in numbered sections. .cta-form
   stays the compact dark one inside the CTA band.

   Every input has a real <label for>. A placeholder is a hint,
   never a label. Optional is marked in the label and required is
   not, so the unmarked state is the common one. Inputs sit on
   --paper-cool and lift to --paper on focus: that is how a field
   shows it is active without an elevation the system does not use.
   ============================================================ */
.form           { padding: 2.5rem; background: var(--paper); border: 1px solid var(--rule); }
.form__section + .form__section { margin-top: 2.5rem; padding-top: 2.5rem;
                  border-top: 1px solid var(--rule); }
.form__head     { display: grid; grid-template-columns: 38px minmax(0, 1fr); gap: 0.9rem;
                  margin-bottom: 1.5rem; }
.form__n        { display: grid; place-items: center; width: 34px; height: 34px;
                  background: var(--sdg-partner-dk); color: var(--paper);
                  font-family: var(--font-mono); font-size: 0.72rem; }
.form__grid     { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.2rem; }
.field          { display: flex; flex-direction: column; gap: 0.45rem; min-width: 0; }
.field--full    { grid-column: 1 / -1; }
.field label    { font-family: var(--font-sans); font-size: 0.82rem; font-weight: 500;
                  color: var(--ink-muted); }
.field label span { color: var(--ink-faint); font-weight: 400; }
.field input, .field select, .field textarea {
                  width: 100%; min-height: 50px; padding: 0.78rem 0.9rem;
                  border: 1px solid var(--rule); border-radius: 2px;
                  background: var(--paper-cool); color: var(--ink);
                  font-family: var(--font-sans); font-size: 0.95rem;
                  transition: border-color 140ms, background 140ms, box-shadow 140ms; }
.field textarea { min-height: 132px; resize: vertical; }
.field input:hover, .field select:hover, .field textarea:hover { border-color: var(--ink-faint); }
.field input:focus, .field select:focus, .field textarea:focus {
                  outline: none; border-color: var(--sdg-climate); background: var(--paper);
                  box-shadow: 0 0 0 3px var(--sdg-climate-soft); }
.field__hint    { margin: 0; font-family: var(--font-sans); font-size: 0.78rem; color: var(--ink-faint); }
.form__foot     { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 1.25rem;
                  align-items: center; margin-top: 2rem; }
.form__success  { display: none; margin-top: 1.5rem; padding: 1rem 1.2rem;
                  border-left: 4px solid var(--sdg-climate); background: var(--paper-tint-climate);
                  font-family: var(--font-sans); font-weight: 500; color: var(--sdg-climate-dk); }
.form__success.is-in { display: block; }

/* ============================================================
   §64 · Skip link, focus ring and mobile drawer
   Three things every preview page had and main.css did not.

   The focus ring is energy yellow because a ring is a graphic mark
   on any ground, and yellow is the one accent that shows on paper,
   sand, slate, navy and green alike. Set through :where() so it
   never outranks a component's own focus style.
   ============================================================ */
.skip-link      { position: fixed; top: 0.75rem; left: 0.75rem; z-index: 200;
                  transform: translateY(-250%); padding: 0.7rem 1.1rem;
                  background: var(--ink); color: var(--paper); font-family: var(--font-sans);
                  font-size: 0.85rem; text-decoration: none; border-radius: 2px;
                  transition: transform 140ms; }
.skip-link:focus { transform: translateY(0); }

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
                  outline: 3px solid var(--sdg-energy); outline-offset: 2px; }

/* The desktop nav itself. v1 built this with Tailwind utilities on the
   element (`hidden lg:flex`), which is why §22 claimed no custom nav CSS was
   needed. The v2 pages carry no Tailwind, so it lives here. */
.site-header__nav { display: flex; align-items: center; gap: 1.4rem; }
/* Direct children only. A .nav-dd__panel link lives inside this nav and keeps
   its own size and colour — an unscoped descendant selector here overrode it,
   because both compute to (0,1,1) and this rule sits later in the file. */
.site-header__nav > a { font-family: var(--font-sans); font-size: 0.875rem; font-weight: 500;
                  color: var(--ink-muted); text-decoration: none; transition: color 120ms; }
.site-header__nav > a:hover,
.site-header__nav > a[aria-current="page"] { color: var(--sdg-climate-dk); }
.site-header__nav > a.btn,
.site-header__nav > a.btn:hover { color: var(--paper); }

.site-header__toggle { display: none; width: 44px; height: 44px; border: 0;
                  background: transparent; cursor: pointer; padding: 0; }
.site-header__toggle span { display: block; width: 20px; height: 1.5px; margin: 4px auto;
                  background: var(--ink); }
body.is-locked  { overflow: hidden; }
@media (max-width: 900px) {
  .site-header__toggle { display: block; }
  /* Flat shape (v2 pages): the nav element *is* the drawer. */
  .site-header__nav { position: fixed; inset: var(--header-h) 0 auto; display: none;
                  padding: 1.2rem 1.25rem 1.6rem; background: var(--paper);
                  border-bottom: 1px solid var(--rule); }
  .site-header__nav.is-open { display: grid; gap: 0.35rem; }
  .site-header__nav > a { padding: 0.7rem 0.25rem; font-size: 1rem; }
}

/* ============================================================
   §66 · Header layout and the grouped drawer
   ----------------------------------------------------------------------------
   The last Tailwind in the codebase lived in templates/nav.php: the flex row,
   the show/hide breakpoints, and an arbitrary-variant block that coloured the
   mobile links through the SDG cycle. All of it is here now, so the pages load
   no utility framework and the tokens have one home.

   Two drawer shapes are supported and they are not interchangeable:
     .site-header__nav.is-open    flat link row that becomes its own drawer
     .site-header__mobile.is-open grouped panel with headed lists (the site)
   A header uses one or the other. The grouped shape is what the live pages
   ship, because the nav has more entries than a flat row reads well at.
   ============================================================ */
.site-header__inner {
  height: var(--header-h);
  display: flex; align-items: center; justify-content: space-between;
}
.site-header__cta { display: flex; }

/* The dropdown trigger. It had no type of its own — it borrowed Tailwind's
   `text-sm text-ink-muted`, which is why it fell back to browser button
   defaults the moment the CDN was blocked. */
.nav-dd__btn {
  font-family: var(--font-sans); font-size: 0.875rem; font-weight: 500;
  color: var(--ink-muted); text-decoration: none;
}
.nav-dd__btn:hover,
.nav-dd__btn[aria-current="page"] { color: var(--sdg-climate-dk); }

/* Hamburger. Carries either three <span> bars or a pair of SVG icons; the
   .site-header__toggle span rule in §64 only applies if bars are present. */
.site-header__toggle {
  align-items: center; justify-content: center;
  margin-right: -0.5rem; color: var(--ink);
}
.site-header__toggle svg { width: 24px; height: 24px; }
.site-header__toggle [hidden] { display: none; }

/* Grouped drawer */
.site-header__mobile {
  display: none; background: var(--paper);
  border-top: 1px solid var(--rule-soft);
  overflow-y: auto; max-height: calc(100vh - var(--header-h) - 16px);
}
.site-header__mobile.is-open { display: block; }
.site-header__mobile-inner { padding: 1.5rem; display: flex; flex-direction: column; gap: 1.5rem; }
.site-header__mobile-title {
  font-family: var(--font-sans); font-size: 1.125rem; font-weight: 500; color: var(--ink);
  margin: 0 0 0.5rem; padding-bottom: 0.5rem; border-bottom: 1px solid var(--rule-soft);
}
.site-header__mobile ul { list-style: none; margin: 0; padding: 0; }
.site-header__mobile li a {
  display: block; padding: 0.5rem 0;
  font-family: var(--font-sans); font-size: 1rem; color: var(--ink-muted);
  text-decoration: none; transition: color 300ms, text-shadow 300ms;
}
.site-header__mobile li a:hover { text-shadow: 0 0 1px currentColor; }
.site-header__mobile li a[aria-current="page"] { color: var(--ink); }
/* Same five-step SDG cycle as .nav-dd__panel, so a link keeps its colour
   whichever menu the visitor opens it from. */
.site-header__mobile li:nth-child(5n+1) a:hover { color: var(--sdg-poverty); }
.site-header__mobile li:nth-child(5n+2) a:hover { color: var(--sdg-cities); }
.site-header__mobile li:nth-child(5n+3) a:hover { color: var(--sdg-life); }
.site-header__mobile li:nth-child(5n+4) a:hover { color: var(--sdg-water); }
.site-header__mobile li:nth-child(5n+5) a:hover { color: var(--sdg-peace); }
.site-header__mobile .btn { width: 100%; justify-content: center; margin-top: 0.5rem; }

@media (max-width: 900px) {
  .site-header__cta { display: none; }
  .site-header__toggle { display: inline-flex; }
}
@media (min-width: 901px) {
  .site-header__mobile { display: none; }
}

/* ============================================================
   §65 · Sheet stack and facsimile page
   Two modifiers on .sheet. The leaves separate by paper step, not
   by elevation. Back leaves are aria-hidden and carry no text.

   A facsimile always carries a --caution callout saying it is
   illustrative. A specimen that could be mistaken for a real
   record is the one thing this component must not do.
   ============================================================ */
.sheet--stack   { position: relative; width: min(100%, 430px); min-height: 430px; margin-inline: auto; }
.sheet--stack > .sheet__leaf { position: absolute; width: 82%; min-height: 370px; padding: 1.9rem;
                  background: var(--paper); border: 1px solid var(--rule); }
.sheet--stack > .sheet__leaf--back   { top: 14px; right: 0; transform: rotate(4deg);
                  background: var(--paper-warm); }
.sheet--stack > .sheet__leaf--middle { top: 26px; left: 7%; transform: rotate(-2.5deg);
                  background: var(--paper-cool); }
.sheet--stack > .sheet__leaf--front  { top: 0; left: 2%; z-index: 3; display: flex;
                  flex-direction: column; background: var(--sdg-partner-dk);
                  border-color: var(--sdg-partner-dk); }
.sheet__mark    { width: 48px; height: 5px; margin-bottom: 3rem;
                  background: linear-gradient(90deg, var(--sdg-climate) 0 50%, var(--sdg-energy) 50%); }
.sheet__type    { font-family: var(--font-mono); font-size: 0.65rem; letter-spacing: 0.16em;
                  text-transform: uppercase; color: var(--sdg-energy); }
.sheet__ttl     { max-width: 10ch; margin: 0.7rem 0 1rem; font-family: var(--font-serif);
                  font-size: 2.1rem; font-weight: 400; line-height: 0.98; color: var(--paper); }
.sheet__sub     { margin: 0; font-family: var(--font-sans); font-size: 0.8rem; color: var(--paper-faint); }
.sheet__foot    { margin-top: auto; padding-top: 2rem; border-top: 1px solid var(--rule-dark);
                  display: grid; gap: 0.55rem; }
.sheet__foot span { font-family: var(--font-sans); font-size: 0.78rem; color: var(--paper-dim); }
.sheet__foot b  { color: var(--sdg-energy); font-weight: 500; margin-right: 0.5rem; }

.sheet--page    { padding: 2.5rem; }
.sheet--page .sheet__bar { padding: 0 0 1rem; margin-bottom: 2rem;
                  border-bottom: 3px solid var(--sdg-partner-dk); }
.sheet__brand   { font-family: var(--font-serif); font-size: 1rem; font-weight: 500; color: var(--ink); }
.sheet__id      { font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.06em;
                  text-transform: uppercase; color: var(--ink-faint); text-align: right; }
.fields         { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
                  border-top: 1px solid var(--rule); border-left: 1px solid var(--rule); }
.fields__item   { padding: 1rem; border-right: 1px solid var(--rule);
                  border-bottom: 1px solid var(--rule); }
.fields__key    { display: block; margin-bottom: 0.8rem; font-family: var(--font-mono);
                  font-size: 0.6rem; letter-spacing: 0.07em; text-transform: uppercase;
                  color: var(--ink-faint); }
.fields__val    { display: block; font-family: var(--font-sans); font-size: 0.86rem;
                  font-weight: 600; color: var(--ink); }
.fields__blank  { display: block; height: 7px; margin-top: 0.55rem; background: var(--rule-soft); }
.fields__blank--short { width: 58%; }

/* ============================================================
   v2.4 fold-ins to published components
   Additive only. Nothing existing changes behaviour.
   ============================================================ */
/* Expand-all / collapse-all above .groups. Twenty criteria in six areas
   needs it; the control itself reuses .btn--secondary sizing. */
/* ============================================================
   Light panels inside a dark section
   A component that sets its own light background sits inside a
   dark section perfectly happily until the dark-ground type rules
   reach its children — at which point its text is paper on paper.
   Measured at 1:1 on the impact-scoring explorer before this
   existed. Any component added later that sets a --paper* ground
   belongs in this list.
   ============================================================ */
:is(.on-dark, .section--navy, .section--green, .integrity, .cta)
  :is(.explorer__panel, .card, .rec, .form, .proof, .sheet, .hero__claim,
      .callout:not(.callout--absolute), .goals__card, .verdict-key__item) {
  color: var(--ink);
}
:is(.on-dark, .section--navy, .section--green, .integrity, .cta)
  :is(.explorer__panel, .card, .rec, .form, .proof, .sheet, .hero__claim,
      .callout:not(.callout--absolute), .goals__card, .verdict-key__item)
  :is(.t-display, .t-h1, .t-h2, .t-h3, .t-h4) { color: var(--ink); font-weight: 500; }
:is(.on-dark, .section--navy, .section--green, .integrity, .cta)
  :is(.explorer__panel, .card, .rec, .form, .proof, .sheet, .hero__claim,
      .callout:not(.callout--absolute), .goals__card, .verdict-key__item)
  :is(.t-body, .t-lead, p) { color: var(--ink-muted); }
/* ...except elements that set their own DARK ground inside that light panel.
   The bare `p` above caught .rec__result and turned it ink-on-navy.

   These selectors deliberately carry the same three-class depth as the rule
   above, and sit after it, so they win the cascade. A two-class version was
   written first and lost silently — the audit is what caught it. */
:is(.on-dark, .section--navy, .section--green, .integrity, .cta)
  :is(.explorer__panel, .card, .rec, .form, .proof, .sheet, .hero__claim)
  :is(.rec__result, .closer--plate, .callout--absolute .callout__title) { color: var(--paper); }
:is(.on-dark, .section--navy, .section--green, .integrity, .cta)
  :is(.explorer__panel, .card, .rec, .form, .proof, .sheet, .hero__claim)
  .callout--absolute p { color: var(--paper-dim); }
/* And the same elements sitting directly on the dark ground, not in a panel. */
:is(.on-dark, .section--navy, .section--green, .integrity, .cta)
  :is(.rec__result, .closer--plate) { color: var(--paper); }
:is(.on-dark, .section--navy, .section--green, .integrity, .cta)
  :is(.explorer__panel, .card, .rec, .form, .proof, .sheet, .hero__claim,
      .callout:not(.callout--absolute), .goals__card, .verdict-key__item)
  .t-caption { color: var(--ink-faint); }

/* Worked arithmetic, shown as the reader would check it. Sits under a
   .figures table and states the calculation the table's rows produce. Mono,
   because the alignment of the operators is the point. */
.formula        { margin: 1rem 0 0; padding: 1rem 1.1rem; background: var(--paper-warm);
                  font-family: var(--font-mono); font-size: 0.82rem; line-height: 1.7;
                  color: var(--ink); overflow-x: auto; }
.on-dark .formula, .section--navy .formula, .integrity .formula {
                  background: rgba(250, 248, 243, 0.06); color: var(--paper); }

/* The closing line of a card, set off by a rule. The preview pages wanted it
   on the floor cards and the boundary cards: a card that has made an argument
   and then states the rule that follows from it. Purely additive — no existing
   card carries this class, so nothing published moves. */
.card__rule     { margin: 1.5rem 0 0; padding-top: 1rem; border-top: 1px solid var(--rule);
                  font-family: var(--font-sans); font-size: 0.95rem; font-weight: 500;
                  color: var(--ink); }
.on-dark .card__rule, .section--navy .card__rule, .section--green .card__rule,
.integrity .card__rule, .cta .card__rule { border-top-color: var(--rule-dark); color: var(--paper); }

.groups__toolbar { display: flex; align-items: center; justify-content: space-between;
                  gap: 1rem; margin-bottom: 1rem; }
.groups__toolbar p { margin: 0; font-family: var(--font-sans); font-size: 0.82rem;
                  color: var(--ink-faint); }
.groups__all    { padding: 0.45rem 0.7rem; border: 1px solid var(--rule); background: var(--paper);
                  color: var(--ink-muted); font-family: var(--font-sans); font-size: 0.78rem;
                  font-weight: 500; cursor: pointer; }
.groups__all:hover { border-color: var(--ink); color: var(--ink); }

/* The four-up legend explaining what each verdict means. The badges already
   exist; the key did not. */
.verdict-key    { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
                  border: 1px solid var(--rule); }
.verdict-key__item { padding: 1.25rem; border-right: 1px solid var(--rule); background: var(--paper); }
.verdict-key__item:last-child { border-right: 0; }
.verdict-key__item .verdict { margin-bottom: 1.2rem; }
.verdict-key__item p { margin: 0; font-family: var(--font-sans); font-size: 0.84rem;
                  line-height: 1.6; color: var(--ink-muted); }

/* Dark hero, for the utility pages where a light hero has nothing to carry.
   No gradient: the ground is flat, as everywhere else. */
.hero--dark     { background: var(--sdg-partner-dk); border-bottom-color: var(--rule-dark); }
.hero--dark .t-display, .hero--dark .t-h1 { color: var(--paper); font-weight: 400; }
.hero--dark .t-lead, .hero--dark .hero__lead, .hero--dark .hero__body { color: var(--paper-dim); }

/* ============================================================
   v2.4 responsive
   ============================================================ */
@media (max-width: 1000px) {
  .doc__grid     { grid-template-columns: minmax(0, 1fr); gap: 2.5rem; }
  .toc           { position: static; }
  .explorer      { grid-template-columns: minmax(0, 1fr); gap: 2rem; }
  .explorer__tabs { grid-template-columns: repeat(2, minmax(0, 1fr)); border-left: 1px solid var(--rule); }
  .explorer__tab { border-right: 1px solid var(--rule); padding-inline: 0.8rem; }
  .seq, .seq--5  { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .seq--flow .seq__step::after { display: none; }
  .stats         { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .verdict-key   { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .verdict-key__item:nth-child(2) { border-right: 0; }
  .verdict-key__item:nth-child(-n+2) { border-bottom: 1px solid var(--rule); }
}
@media (max-width: 700px) {
  .seq, .seq--2, .seq--3, .seq--5, .stats, .stats--2, .stats--3, .verdict-key,
  .form__grid, .fields, .marks--2up, .goals, .explorer__tabs { grid-template-columns: minmax(0, 1fr); }
  .verdict-key__item { border-right: 0; border-bottom: 1px solid var(--rule); }
  .nextpage__link, .form__foot, .rec__row { grid-template-columns: minmax(0, 1fr); }
  .nextpage__arrow { justify-self: start; }
  .rec__row > :last-child { text-align: left; }
  .form, .explorer__panel { padding: 1.5rem; }
  .sheet--page .sheet__bar { display: grid; gap: 0.35rem; }
  .sheet__id { text-align: left; }
}
