/*
Theme Name: EOCPR
Theme URI: https://cancerresearchethiopia.org
Author: Ethiopian Organization for Cancer Prevention and Research
Description: Hand-written bilingual theme for EOCPR. No page builder, no framework, no build step.
Version: 0.7.2
Requires at least: 6.3
Requires PHP: 8.0
Text Domain: eocpr
*/

/* =====================================================================
   EOCPR DESIGN SYSTEM — Direction A, Editorial.

   This file is the whole design system. The class contract it exposes is
   documented in COMPONENTS.md at the theme root; template authors build
   against that file, not against guesswork here.

   CONTENTS
     1.  FONTS          self-hosted @font-face, no CDN, no base64
     2.  TOKENS         colour, surface, type, space, radius, shadow, motion
     3.  CONTRAST       the measured ledger + the forbidden list
     4.  AMHARIC        parallel scale for html[lang^="am"]
     5.  RESET
     6.  BASE           element defaults, links, focus, selection, skip link
     7.  LAYOUT         shell, section, surfaces, soft joins
     8.  FLOW           the prose / breakout grid — the core of this layout
     9.  TEXT UTILITIES eyebrow, lede, muted, measure
     10. HEADER         topbar, masthead, brandmark, nav, mobile nav
     11. BUTTONS
     12. HERO + STATPANEL
     13. CARDS
     14. UNIT ROWS
     15. ARTICLE MASTHEAD, BREADCRUMBS, CONTENTS RAIL
     16. DESIGNED LISTS
     17. KEY-FACT CALLOUTS
     18. STATISTIC BLOCKS
     19. FIGURE FRAMES
     20. QUOTES
     21. ACCORDIONS
     22. TABLES
     23. DEFINITION TILES
     24. STEP SEQUENCES
     25. SOURCE LISTS
     26. CTA BLOCKS
     27. FOOTER
     28. FORMS
     29. FOREIGN OUTPUT   markup this theme does not write (switcher,
                          core pagination, editor-authored figures)
     30. MOTION          reveal layer
     31. RESPONSIVE      mobile-first step-ups
     32. REDUCED MOTION  no exceptions
     33. PRINT
     34. DATA DASHBOARD   template-dashboard.php only. Appended rather than
                          inserted at 29 so that every "see §30", "§31" and
                          "§32" reference already written into this file,
                          into COMPONENTS.md and into the templates keeps
                          pointing at the section it names.
     35. DIRECTION 3      the merged design: icon set, hero plate, word
                          rotator, one-row nav flyouts, mobile <details>
                          panel, the deep-page editorial grid (numbered
                          sticky rail + reading column + breakout tracks),
                          the evidence panel, the figure frame and the
                          light CTA band. Appended for the same reason 34
                          was: every existing §n reference keeps pointing
                          at the section it names.

   THREE DELIBERATE DEPARTURES FROM THE APPROVED PREVIEW
     a. Footer surface darkened from #1A6B45 to forest #0F5132. The preview
        put gold-lum #E8C86A on #1A6B45, measured here at 3.99:1, which fails
        AA for the 13px/700 text it was used on. On #0F5132 the same gold is
        5.75:1. See section 3.
     b. The count-up animation on statistics is gone, in CSS and in JS.
        Statistics render at their final value, always. Animating
        mortality-adjacent numbers reads as gamified.
     c. The brandmark has a real sized relationship to the masthead, a
        responsive step, and a reverse treatment for dark green. See §10.
   ===================================================================== */


/* =====================================================================
   1. FONTS
   Both faces are SIL OFL 1.1 — free forever, no licence fee, no trial.
   The files are real .woff2 in assets/fonts/. No third-party CDN: a health
   site should not be paying for a cross-origin DNS lookup, and it should
   not be handing a reader's IP address to a font host to render a page.
   No base64 either — inlined fonts cannot be cached across pages.

   font-display:swap so text is readable during the download. The two
   400 weights and Source Serif 600 are preloaded from functions.php —
   Source Serif 600 is what every h1–h4 is set in, so it is on the LCP
   path and must not wait for the stylesheet to be parsed first.

   unicode-range keeps these six files out of the download path on Amharic
   pages that carry no Latin text at all.

   SIX FILES, NOT TEN. Four faces were shipped and never earned it:
     Inter 300           — no rule in this file ever asked for it
     Source Serif 300    — no rule in this file ever asked for it
     Source Serif 500    — no rule in this file ever asked for it
     Inter 500           — three rules used it (.nav__list a, .mnav a,
                           .stat__l). Those three now use 400 and 600,
                           which are already on the wire for other reasons,
                           so a whole 24 KB face is no longer downloaded on
                           a first visit to buy one intermediate weight.
   The .woff2 files for all four have been deleted from assets/fonts/.
   ===================================================================== */
/* 0.7.0: the EPIC Field faces. Newsreader (display and headings, optical
   size axis, normal and italic) and Schibsted Grotesk (interface and body),
   both SIL OFL 1.1 and self-hosted, the same files the EPIC and ISPOR sites
   use. Three variable files replace the six static Inter and Source Serif
   weights, so every weight from 400 to 800 costs nothing extra. */
@font-face{
  font-family:'Newsreader';font-style:normal;font-weight:200 800;font-display:swap;
  src:url('assets/fonts/newsreader-latin-opsz-normal.woff2') format('woff2-variations');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Newsreader';font-style:italic;font-weight:200 800;font-display:swap;
  src:url('assets/fonts/newsreader-latin-opsz-italic.woff2') format('woff2-variations');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Schibsted Grotesk';font-style:normal;font-weight:400 900;font-display:swap;
  src:url('assets/fonts/schibsted-grotesk-latin-wght-normal.woff2') format('woff2-variations');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}


/* =====================================================================
   2. TOKENS
   The forest / teal / gold palette is the brand kit's, unchanged. What is
   engineered here is WHICH TOKEN IS ALLOWED WHERE. Every text colour was
   measured against the background it actually sits on; the ratio is stated
   in a comment at the point of use and collected in section 3.

   Two DERIVED shades exist, and only because the brand gold #D4AF37 is
   2.10:1 on white and can never legally be text:
     --gold-ink  #7A6416  darkened gold, legal as text on light surfaces
     --gold-lum  #E8C86A  lightened gold, legal as text on forest
   The brand gold itself stays, restricted to shapes, rules and marks.
   ===================================================================== */
:root{
  /* --- BRAND PALETTE — unchanged from the brand kit ----------------- */
  --forest:#0F5132;
  --teal:#0E8F8A;
  --deep-teal:#0B6B66;
  --gold:#D4AF37;
  --ivory:#FBF7ED;
  --ink:#123222;

  /* --- DERIVED, for contrast only ---------------------------------- */
  --forest-deep:#0B3D26;
  --forest-hover:#0C4429;
  --gold-ink:#7A6416;
  --gold-lum:#E8C86A;
  --gold-hover:#E0BE4C;

  /* --- SURFACE SYSTEM — page / paper / band / card / tint / dark ---- */
  --s-page:#FFFFFF;
  --s-paper:#FCFAF4;      /* softest warm step, used to fade band joins */
  --s-band:#FBF7ED;       /* ivory band */
  --s-band-deep:#F5F1E6;  /* table heads, figure heads, inset wells */
  --s-card:#FFFFFF;
  --s-teal:#E8F2F1;       /* teal tint surface */
  --s-gold:#FAF3DC;       /* gold tint surface */
  --s-inset:#F7F3E8;      /* the evidence panel surface — §35 */
  --s-dark:#0F5132;       /* dark band base */
  --s-footer:#0F5132;     /* CHANGED from the preview's #1A6B45 — see §3 */
  --plate-top:#14603C;    /* the LIGHTEST pixel of the hero plate gradient.
                             Every plate ratio in §3 is stated against this,
                             not against the gradient's dark end. */
  --hair:#E6E2D6;         /* hairline rule */
  --hair-soft:#EFEBE0;    /* softer hairline, inside components */
  --hair-dark:rgba(255,255,255,.16);  /* hairline on dark surfaces */

  /* --- DOMAIN COLOURS — the six areas of the cancer control dashboard ---

     An earlier build carried six domain colours and they were removed,
     correctly: #1B5E8A, #8A4B00, #5B2440 and #3D5A2B were invented at the
     point of use, sat outside this file, and were the only thing on the page
     identifying a domain. Ground rule 2 forbids the first; ground rule 7
     forbids the last.

     They come back here as real tokens, and with the second problem solved
     rather than repeated. THE DOMAIN IS ALWAYS CARRIED BY TEXT — the section
     heading a panel sits under, the filter chip's own label, the chart's
     <title> and <desc>. Colour is the second cue and never the first, so
     everything on the page survives greyscale, forced-colors mode and being
     read aloud.

     That is not a nicety here, it is arithmetic. Six inks all dark enough to
     clear 4.5:1 as text on white are forced into a narrow luminance band: the
     closest pair in this set differs by 1.04:1, which is invisible in
     greyscale. No six-colour set can avoid that and stay legible. A palette
     this size can only ever be a secondary cue, so it is built as one.

     Two inks are the brand's own — prevention reuses --deep-teal, burden
     reuses --forest — because inventing new greens beside them would read as
     an error rather than a system.

     Each ink is paired with a tint for chip and badge surfaces. Every ratio
     below is measured, ink against white card, and ink against its own tint.

       domain     ink        on #FFFFFF   tint       ink on tint
       prevent    #0B6B66      6.35:1     #E8F2F1      5.56:1
       detect     #15507D      8.48:1     #E7F0F7      7.36:1
       treat      #6B2D5C      9.74:1     #F5EAF2      8.32:1
       finance    #7A6416      5.73:1     #FAF3DC      5.17:1
       burden     #0F5132      9.36:1     #E6F0EA      8.03:1
       policy     #8F3A14      7.55:1     #FBEDE5      6.59:1                */
  --dom-prevent:#0B6B66;  --dom-prevent-t:#E8F2F1;
  --dom-detect:#15507D;   --dom-detect-t:#E7F0F7;
  --dom-treat:#6B2D5C;    --dom-treat-t:#F5EAF2;
  --dom-finance:#7A6416;  --dom-finance-t:#FAF3DC;
  --dom-burden:#0F5132;   --dom-burden-t:#E6F0EA;
  --dom-policy:#8F3A14;   --dom-policy-t:#FBEDE5;

  /* The fallback, for a domain added in wp-admin that has no colour of its
     own. It is the body ink, so a new domain is neutral rather than wrong. */
  --dom-none:#123222;     --dom-none-t:#F5F1E6;

  /* CONTROL BORDER — a different job from a hairline, and a different
     rule. WCAG 2.1 SC 1.4.11 requires 3:1 for any visual boundary that is
     the ONLY thing identifying a control: a text input, an outline button,
     a response box. --hair is decoration between blocks and is exempt;
     this is not. Measured on every light surface in the system:
       #828D85 on page      #FFFFFF   3.44:1
       #828D85 on paper     #FCFAF4   3.30:1
       #828D85 on band      #FBF7ED   3.22:1
       #828D85 on gold-tint #FAF3DC   3.10:1
       #828D85 on band-deep #F5F1E6   3.05:1
       #828D85 on teal-tint #E8F2F1   3.02:1
     The worst case still clears 3:1, so the control boundary is legal
     wherever a control can legally be placed. */
  --line-ctl:#828D85;

  /* --- TEXT — ratios against the surface named ---------------------- */
  --text:#123222;         /* 13.95 page · 13.04 band · 12.36 band-deep · 12.23 teal-tint · 12.57 gold-tint */
  --text-mut:#4A5C51;     /*  7.14 page ·  6.67 band ·  6.33 band-deep ·  6.26 teal-tint ·  6.43 gold-tint */
  --heading:#0F5132;      /*  9.36 page ·  8.75 band ·  8.29 band-deep ·  8.20 teal-tint ·  8.43 gold-tint */

  /* --- THE LINK SYSTEM — FOUR COLOURS, AND ONLY FOUR ----------------
     This site shipped NINE link colours: prose teal, prose hover forest,
     nav ink, nav current forest, topbar white, topbar hover gold-lum,
     footer white, footer hover gold-lum, and gold-lum again for links
     inside .sec--dark. Nine colours is not a system, it is nine local
     decisions, and a reader cannot learn which of them means "link".

     There are four now, one per SURFACE CLASS, and every one of them is
     measured against the surface it is actually painted on:

       1  prose      --link       #0B6B66   ALWAYS UNDERLINED. Never colour
                                            alone (WCAG 1.4.1). 6.35 page,
                                            5.93 band, 5.72 inset.
       2  nav        --link-nav   #123222   Position, weight and a tint
                                            carry it, not a rule. 13.95 on
                                            page. Used by the masthead nav,
                                            the flyouts, the mobile panel
                                            and the contents rail — the
                                            rail is navigation, so it takes
                                            the navigation colour rather
                                            than a tenth muted one.
       3  footer     --link-foot  #D5E7DC   7.26 on forest, 9.53 on
                                            forest-deep (the topbar).
       4  on-dark    --link-inv   #FFFFFF   9.36 on forest, 8.43 on the
                                            .sec--dark composite #0E5841,
                                            7.59 on the plate top #14603C.
                                            Underlined, because on a dark
                                            surface white is also the body
                                            text colour.

     --link-hover is NOT a fifth colour. Every hover in this file moves to
     one of the four above or to the surface's own text colour; the token
     is kept only because §6 and three components already name it. */
  --link:#0B6B66;         /*  6.35 page ·  5.93 band ·  5.62 band-deep ·  5.56 teal-tint ·  5.72 gold-tint */
  --link-nav:#123222;     /* 13.95 page */
  --link-foot:#D5E7DC;    /*  7.26 forest ·  9.53 forest-deep */
  --link-inv:#FFFFFF;     /*  9.36 forest ·  8.43 sec--dark composite ·  7.59 plate-top */
  --link-hover:#0F5132;
  /* The first figure on each dark line is the one that governs: .sec--dark
     paints a wash over the forest gradient, so text there sits on the
     COMPOSITE #0E5841, never on the flat token. See §3. */
  --on-dark:#FFFFFF;      /*  8.43 sec--dark ·  9.36 forest · 12.28 forest-deep ·  9.36 footer */
  --on-dark-mut:#C5D8CC;  /*  5.65 sec--dark ·  6.27 forest ·  8.23 forest-deep ·  6.27 footer */
  --on-foot-mut:#D5E7DC;  /*  6.54 sec--dark ·  7.26 footer (was 5.04 on the preview's lighter green) */

  /* --- FOCUS — non-text minimum is 3:1; both clear it comfortably --- */
  --focus:#0B6B66;        /* 6.35:1 against page */
  --focus-dark:#E8C86A;   /* 5.18:1 on the .sec--dark composite · 5.75:1 on flat forest */
  --focus-w:3px;
  --focus-off:3px;

  /* --- TYPE
     Serif is the reading voice. Sans is the interface voice. That split
     is the point: the serif is a decision here, not a default. ------- */
  --serif:'Newsreader',Georgia,'Times New Roman',serif;
  --sans:'Schibsted Grotesk',-apple-system,'Segoe UI',Helvetica,Arial,sans-serif;
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;

  /* THE TYPE SCALE — RESET AGAINST MEASURED DOM VALUES.
     The complaint was not "the headings feel big", it was measured: h1
     rendered at 56px and h2 at 40px on the owner's 2294px screen. The old
     scale above topped out at 84px hero / 61.6px h1 / 44.8px h2, so at
     2294px it was pinned at its maximum and there was no viewport at which
     it was not oversized.

     Every clamp below is LINEAR from 390px to 1600px and then flat, so
     both reported endpoints are exact rather than incidental:

       token        390px    2294px     was (390 / 2294)
       --fs-hero     32px      52px      40.8 /  84
       --fs-h1       30px      44px      34.4 /  61.6
       --fs-h2       24px      34px      27.2 /  44.8
       --fs-h3       18px      22px      19.5 /  25.6
       --fs-lede     19px      23px      18.2 /  23.2
       --fs-body     17px      18px      17   /  18      unchanged

     Arithmetic for the first one, so the rest can be checked the same way:
     52 - 32 = 20px of growth over 1600 - 390 = 1210px of viewport, which
     is 1.653vw; at 390px that vw term contributes 6.45px, so the fixed
     part is 32 - 6.45 = 25.55px = 1.597rem. Flat above 1600px, which is
     why 1600px and 2294px report the same number. */
  --fs-hero:clamp(2.062rem,1.359rem + 2.886vw,3.956rem);   /* 33 → 63.3px  Latin */
  --fs-h1:clamp(2.062rem,1.359rem + 2.886vw,3.956rem);   /* 33 → 63.3px  Latin */
  --fs-h2:clamp(1.562rem,1.163rem + 1.638vw,2.638rem);   /* 25 → 42.2px  Latin */
  --fs-h3:clamp(1.25rem,1.099rem + 0.619vw,1.656rem);   /* 20 → 26.5px  Latin */
  --fs-h4:1rem;                                           /*      16px */
  --fs-lede:clamp(1.1875rem,1.107rem + .331vw,1.4375rem); /* 19 → 23px */
  --fs-body:clamp(1.062rem, 1.039rem + 0.09524vw, 1.125rem);  /* 17 → 18px */
  --fs-sm:clamp(0.9062rem, 0.883rem + 0.09524vw, 0.9688rem);                                       /*      15px */
  --fs-xs:clamp(0.7812rem, 0.758rem + 0.09524vw, 0.8438rem);                                       /*      13px */

  /* THE ARTICLE PAIR IS GONE AS A SEPARATE SCALE.
     --fs-art-h2 was 40px at the top and that is exactly the h2 the owner
     measured and objected to. There is now ONE h2 size on the site, 34px,
     so a section heading on the home page and a subhead inside the reading
     column are the same object at the same size — which is what the merged
     design does. The three tokens are kept, pointed at the single scale,
     because .art/.prose and COMPONENTS.md already name them and an alias
     is cheaper than hunting every reference.
     Article h1 keeps its own step: 44px against the hero's 52px. */
  --fs-art-h1:clamp(2.062rem, 1.359rem + 2.886vw, 3.956rem);   /* 33 → 63.3px  article h1 */
  --fs-art-h2:clamp(1.562rem, 1.163rem + 1.638vw, 2.638rem);   /* 25 → 42.2px  article h2 */
  --fs-art-h3:clamp(1.25rem, 1.099rem + 0.619vw, 1.656rem);   /* 20 → 26.5px  article h3 */

  --lead-body:1.62;
  --lead-tight:1.1;

  /* --- SPACE — one rhythm, used everywhere ------------------------- */
  --s1:.25rem; --s2:.5rem;  --s3:.75rem; --s4:1rem;  --s5:1.5rem;
  --s6:2rem;   --s7:3rem;   --s8:4rem;   --s9:6rem;
  --section:clamp(3.25rem,5.5vw,6rem);  /* vertical rhythm between sections */
  --gutter:clamp(1.15rem,4vw,3.5rem);   /* 18.4px @390 · 56px @2294 */

  /* THE CONTAINER. The complaint, verbatim: "looks like a book or mobile
     version on a computer screen, not screen optimised". It was 78rem —
     1248px — on a 2294px display, so 1046px of the owner's screen was
     margin. The wide screen is the PRIMARY case here, not an edge case.
       --shell      min(1440px,100%)   1440 - 112 gutter = 1328px of content
     --shell-wide is kept as an alias rather than deleted: eleven templates
     carry .shell--wide, five of which this pass is not allowed to edit, and
     a second cap would just reintroduce the two-width problem. Both names
     now resolve to the same container. */
  --shell:min(1680px, 100%);
  --shell-wide:min(1440px,100%);

  /* THE MEASURE. 1ch is Inter 400's zero advance, 0.6309em, read out of
     inter-latin-400-normal.woff2 — so 70ch at 18px is 794.9px, about 88
     characters of running text. Wider than the old 66ch because the body
     face is no longer the serif (see §8) and Inter sets narrower. */
  --measure:68ch;
  --rail:3rem;                          /* the breakout step either side */

  /* --- RADII ------------------------------------------------------- */
  --r-sm:6px; --r:12px; --r-lg:20px; --r-pill:999px;

  /* --- SHADOWS — three steps, tinted with the ink, never neutral --- */
  --sh-1:0 1px 2px rgba(18,50,34,.05),0 2px 8px rgba(18,50,34,.045);
  --sh-2:0 2px 4px rgba(18,50,34,.05),0 12px 28px -8px rgba(18,50,34,.12);
  --sh-3:0 4px 8px rgba(18,50,34,.06),0 28px 56px -16px rgba(18,50,34,.20);
  --sh-nav:0 6px 20px -14px rgba(18,50,34,.5);
  --sh-panel:-20px 0 60px -20px rgba(18,50,34,.4);

  /* --- MOTION — easing and durations are tokens, not literals ------ */
  --ease:cubic-bezier(.22,.61,.36,1);       /* decelerate, the house curve */
  --ease-in-out:cubic-bezier(.65,0,.35,1);
  --dur-1:.18s;   /* state flicks: hover colour, skip link */
  --dur-2:.28s;   /* affordances: underlines, arrows, icons */
  --dur-3:.35s;   /* objects: cards lifting, panels sliding */
  --dur-4:.55s;   /* entrances: the reveal layer */
  --rd:0s;        /* per-element reveal delay, set by [data-d] in §30 */
}

/* Article-scoped type scale. .art wraps the body of every page.php and
   single.php render and .prose is the reading column inside it, so
   redeclaring the two tokens here re-points the h2/h3 rules in §6 without
   touching them and without affecting the landing pages, which have no
   .art wrapper. Values are the approved tobacco.html pair. */
.art,.prose{--fs-h2:var(--fs-art-h2);--fs-h3:var(--fs-art-h3)}


/* =====================================================================
   3. CONTRAST LEDGER
   Every pair below was computed, not estimated. AA needs 4.5:1 for text
   under 18.66px bold / 24px regular, 3:1 above that, 3:1 for non-text.

   ON LIGHT SURFACES                          page    band    band-dp teal-t  gold-t
     --text        #123222                    13.95   13.04   12.36   12.23   12.57
     --text-mut    #4A5C51                     7.14    6.67    6.33    6.26    6.43
     --heading     #0F5132                     9.36    8.75    8.29    8.20    8.43
     --link        #0B6B66                     6.35    5.93    5.62    5.56    5.72
     --gold-ink    #7A6416                     5.73    5.36    5.08    5.03    5.17
     --forest-deep #0B3D26                    12.28   11.48   10.88   10.76   11.07

   ON DARK SURFACES
   READ THIS BEFORE USING THE NUMBERS. A ratio is only meaningful against
   the pixels a reader actually sees. .sec--dark does NOT paint a flat
   --s-dark: it paints a radial wash over a forest-to-forest-deep linear
   gradient (§7). Text there sits on the COMPOSITE, which is lighter than
   the flat token, so every figure below is stated against the composite,
   worst case. The worst case for .sec--dark is the top-left corner, where
   the radial is at full strength (alpha .28) over the lightest end of the
   linear gradient (#0F5132):

       rgba(11,107,102,.28) over #0F5132  =  #0E5841   <- measure on THIS

   The footer paints forest-deep -> forest with no wash, so its worst case
   really is the flat #0F5132. The topbar is flat #0F5132.

                                      sec--dark  forest  forest-deep  footer
                                      composite  #0F5132 #0B3D26      #0F5132
                                      #0E5841
     --on-dark     #FFFFFF               8.43     9.36    12.28        9.36
     --on-dark-mut #C5D8CC               5.65     6.27     8.23        6.27
     --on-foot-mut #D5E7DC               6.54     7.26     9.53        7.26
     --gold-lum    #E8C86A               5.18     5.75     7.55        5.75

   Every pair above clears 4.5:1 on the composite, which is the surface
   that is actually rendered.

   THE WASH DEFECT, AND ITS FIX
   The wash was rgba(14,143,138,.28) — the brand teal. Composited over
   #0F5132 that is #0F624B, and on #0F624B:

       --gold-lum #E8C86A on #0F624B  =  4.4967:1   FAIL (needs 4.5)

   which is what .sec--dark a and .eyebrow--dark were actually rendering
   at, while this ledger claimed 5.75:1 against a flat token that is never
   painted. The wash now uses --deep-teal #0B6B66 at the same .28 alpha:
   the same weight of glow in the same place, but composited from a darker
   colour, so the surface underneath the text is #0E5841 and the same gold
   measures 5.18:1. Nothing else about the section changed.

   CONTROL BOUNDARIES — SC 1.4.11, 3:1 minimum (see --line-ctl in §2)
     --line-ctl #828D85 on #FFFFFF            3.44   form inputs, textarea,
                                                     select, .btn--outline,
                                                     .wpcf7-response-output
     --line-ctl #828D85 on #FBF7ED            3.22   .btn--outline on a band
     --line-ctl #828D85 on #E8F2F1            3.02   worst surface in the set
   Superseded, and why: the inputs were #B9C2BB (1.83:1 on white) and
   .btn--outline was #BFCFC4 (1.62:1 on white, 1.52:1 on a band). In all
   three cases the border is the only visual boundary the control has —
   there is no fill and no shadow — so 1.4.11 applies and all three failed.

   ON GOLD                                    #D4AF37 #E0BE4C(hover)
     --forest-deep #0B3D26                     5.84    6.81
     --ink         #123222                     6.64    7.73

   BUTTON LABELS
     #FFFFFF on --forest        #0F5132        9.36
     #FFFFFF on --forest-hover  #0C4429       11.20
     #0B3D26 on --gold          #D4AF37        5.84
     #0B3D26 on --gold-hover    #E0BE4C        6.81
     #0F5132 on --s-page        #FFFFFF        9.36   (outline button label)

   FOCUS RINGS (non-text, 3:1 minimum)
     --focus      #0B6B66 on #FFFFFF           6.35
     --focus-dark #E8C86A on #0F5132           5.75   topbar, footer
     --focus-dark #E8C86A on #0E5841           5.18   .sec--dark composite

   --- THE FOOTER DEFECT, AND ITS FIX ------------------------------------
   The approved preview set the footer surface to #1A6B45 and put
   --gold-lum #E8C86A on it for .foot__h, which is 13px/700 — NOT large
   text under WCAG, so it needs 4.5:1.

       #E8C86A on #1A6B45  =  3.99:1   FAIL
       #C5D8CC on #1A6B45  =  4.35:1   FAIL for body copy
       #D5E7DC on #1A6B45  =  5.04:1   pass, but with no headroom

   Adopting the fix the preview's own author recommended, the footer is
   darkened to forest #0F5132:

       #E8C86A on #0F5132  =  5.75:1   PASS   <-- the defect is fixed
       #FFFFFF on #0F5132  =  9.36:1   PASS
       #C5D8CC on #0F5132  =  6.27:1   PASS
       #D5E7DC on #0F5132  =  7.26:1   PASS

   Every footer pair now clears AA with headroom. The footer also gains a
   forest-deep-to-forest wash at its top edge (§27) so the dark CTA hands
   over to it without a visible step; text there sits on a background at
   least as dark as #0F5132, so the ratios above are the worst case.

   --- FORBIDDEN COMBINATIONS — each one is a real temptation -----------
     teal   #0E8F8A on forest #0F5132  = 2.37:1   never
     teal   #0E8F8A on white           = 3.95:1   never body copy
     gold   #D4AF37 on white           = 2.10:1   never text, at any size
     gold   #D4AF37 on band  #FBF7ED   = 1.97:1   never text
     gold   #D4AF37 on footer #0F5132  = 4.45:1   large text only, so:
                                                   not button labels, not
                                                   13px headings. Use
                                                   --gold-lum instead.
     gold-lum #E8C86A on white         = 1.63:1   never on a light surface
     gold-ink #7A6416 on forest        = 1.63:1   never on a dark surface
   Use --deep-teal for links, --gold-ink for accents on light, --gold-lum
   for accents on dark, and keep the brand gold for rules and marks.
   check_theme.py enforces the two worst of these mechanically.

   ---------------------------------------------------------------------
   DIRECTION 3 ADDITIONS. Every pair introduced by the merge, computed the
   same way. Two new surfaces are involved:
     --s-inset    #F7F3E8   the evidence panel (§35.6)
     --plate-top  #14603C   the LIGHTEST pixel of the hero plate gradient,
                            which runs #0B3D26 -> #14603C. Every plate
                            ratio is stated against the light end, which
                            is the worst case, not the average.

   THE FOUR LINK COLOURS — and there are only four
                                       page    band    inset   b-deep  teal-t
     1 --link      #0B6B66   prose      6.35    5.93    5.72    5.62    5.56
                                        always underlined; never colour alone
     2 --link-nav  #123222   nav       13.95   13.04   12.58   12.36   12.23
                                        masthead, flyouts, panel, rail
                                       forest  f-deep  plate
     3 --link-foot #D5E7DC   footer     7.26    9.53    5.89
                                        footer, topbar, switcher, plate foot
     4 --link-inv  #FFFFFF   on-dark    9.36   12.28    7.59
                                        also 8.43 on the .sec--dark composite
                                        #0E5841; underlined, because white is
                                        also the body colour on those surfaces
     --link-hover  #0F5132 is the shared hover/current STATE, not a fifth
     resting colour: 9.36 page, 8.97 paper, 8.20 on the teal tint the prose
     hover paints behind the text.

   ON THE INSET SURFACE #F7F3E8 (the evidence panel)
     --text        #123222                   12.58
     --text-mut    #4A5C51                    6.44   dt labels
     --heading     #0F5132                    8.44   .num
     --gold-ink    #7A6416                    5.17   .well__h
     --link        #0B6B66                    5.72   .well__h .ic, non-text

   ON THE PLATE, stated against --plate-top #14603C
     #FFFFFF       .plate__st, links          7.59
     --link-foot   .plate__foot               5.89
     --gold-lum    .plate .eyebrow            4.66   clears AA 4.5 for normal
                                                     text at the LIGHT end;
                                                     7.55 at the dark end
     --on-dark-mut #C5D8CC                    5.08

   ON forest-deep #0B3D26 — the topbar moved onto this surface
     --link-foot   #D5E7DC                    9.53
     #FFFFFF       hover, current language   12.28
     --on-dark-mut #C5D8CC                    8.23
     --gold-lum    #E8C86A  non-text mark     7.55

   COMPONENT MARKS AND SURFACES
     #0F5132 on teal tint  .card__ic .pos__ic .ctaband__ic       8.20
     #FFFFFF on forest     .card__ic on hover                    9.36
     #0B6B66 on white      .unit__ic at rest                      6.35
     #FFFFFF on #0B6B66    .unit__ic on hover                     6.35
     #123222 on paper      .card on hover #FCFAF4                13.37
     #0F5132 on band       .rail current numeral                  8.75
     #7A6416 on band-deep  .figframe__k, caption                  5.08
     #0B6B66 on band-deep  .figframe__k .ic, non-text             5.62
     #0E8F8A on white      .nav current inset rule, non-text      3.95  >=3
     #828D85 on white      .mnav__sum border, SC 1.4.11           3.44  >=3
     #123222 on gold       .btn--gold label                       6.64
     #123222 on #E0BE4C    .btn--gold hover label                 7.73
   ===================================================================== */


/* =====================================================================
   4. AMHARIC — parallel scale
   Ethiopic runs taller, has no case distinction, and sets a wider glyph
   for the same nominal size, so it needs more leading, no tracking games,
   and a narrower character-count measure to hold the same optical width.

   UNTESTED. No Amharic content exists on the site yet. These are hooks
   placed now so that when Amharic copy arrives the layout does not have to
   be re-argued from scratch. Everything in this block should be checked
   against real Ethiopic copy before launch; the measure in particular is a
   reasoned estimate, not an observation.
   ===================================================================== */
html[lang^="am"]{
  --serif:'Noto Serif Ethiopic','Newsreader',Georgia,serif;
  --sans:'Noto Sans Ethiopic','Schibsted Grotesk',-apple-system,'Segoe UI',sans-serif;

  /* Ethiopic needs air between lines far more than Latin does. */
  --lead-body:1.95;
  --lead-tight:1.42;

  /* One step down at the top of the scale. Re-derived against the reset
     Latin scale above rather than left at the old 84px-era numbers:
       Ethiopic hero  29 → 46px   (Latin 32 → 52)
       Ethiopic h1    27 → 39px   (Latin 30 → 44)
       Ethiopic h2    22 → 30px   (Latin 24 → 34) */
  --fs-hero:clamp(1.812rem,1.186rem + 2.571vw,3.5rem);   /* 29 → 56px  Ethiopic */
  --fs-h1:clamp(1.812rem,1.186rem + 2.571vw,3.5rem);   /* 29 → 56px  Ethiopic */
  --fs-h2:clamp(1.375rem,1.027rem + 1.429vw,2.312rem);   /* 22 → 37px  Ethiopic */
  --fs-art-h1:var(--fs-h1);

  /* ~70 Latin ch is ~57 Ethiopic ch at comparable optical width. */
  --measure:57ch;
}
/* Ethiopic has no upper case, and letter-spacing an abugida damages it. */
html[lang^="am"] .eyebrow,
html[lang^="am"] .foot__h,
html[lang^="am"] .rail__h,
html[lang^="am"] .well__h,
html[lang^="am"] .well dt,
html[lang^="am"] .figframe__k,
html[lang^="am"] .toc__hd,
html[lang^="am"] .statpanel__hd,
html[lang^="am"] .figframe__hd span:first-child,
html[lang^="am"] .unit__abbr,
html[lang^="am"] .card__idx,
html[lang^="am"] .brandmark__l2,
html[lang^="am"] thead th{
  text-transform:none;
  letter-spacing:0;
}
/* Negative tracking closes Ethiopic counters. Headings set at 0. */
html[lang^="am"] h1,
html[lang^="am"] h2,
html[lang^="am"] h3,
html[lang^="am"] h4,
html[lang^="am"] .stat__n,
html[lang^="am"] .unit__k,
html[lang^="am"] blockquote{letter-spacing:0}
/* Ethiopic word-breaking is poor in most engines; balance hurts more than
   it helps, and tight leading on a hero is unreadable. */
html[lang^="am"] .hero h1{line-height:1.28;text-wrap:pretty}
html[lang^="am"] .stat__n{line-height:1.2}


/* =====================================================================
   5. RESET
   ===================================================================== */
*,*::before,*::after{box-sizing:border-box}
body,h1,h2,h3,h4,h5,h6,p,figure,blockquote,ul,ol,dl,dd,dt,fieldset{margin:0}
ul[class],ol[class]{list-style:none;padding:0}
img,svg,video{display:block;max-width:100%}
img{height:auto}
button,input,select,textarea{font:inherit;color:inherit}
fieldset{border:0;padding:0;min-width:0}
html{-webkit-text-size-adjust:100%}


/* =====================================================================
   6. BASE
   ===================================================================== */
body{
  font-family:var(--sans);
  font-size:var(--fs-body);
  line-height:var(--lead-body);
  color:var(--text);                 /* #123222 on #FFFFFF = 13.95:1 */
  background:var(--s-page);
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}
h1,h2,h3,h4{
  font-family:var(--serif);
  color:var(--heading);              /* #0F5132 on #FFFFFF = 9.36:1 */
  line-height:var(--lead-tight);
  font-weight:600;
  text-wrap:balance;
}
h1{font-size:var(--fs-h1);letter-spacing:-.022em}
h2{font-size:var(--fs-h2);letter-spacing:-.018em}
h3{font-size:var(--fs-h3);letter-spacing:-.012em;line-height:1.2}
h4{font-size:var(--fs-h4);letter-spacing:-.005em;line-height:1.3}
h5,h6{font-family:var(--sans);font-weight:700;font-size:var(--fs-sm);color:var(--heading);line-height:1.4}

/* LINK 1 — PROSE. The default for every anchor that is not inside a
   navigation surface. Underlined ALWAYS: colour is never the only cue
   (WCAG 1.4.1), and the underline is what tells a reader it is a link
   before they have learned the palette. */
a{color:var(--link);text-underline-offset:.18em;text-decoration-thickness:1px}
a:not([class]),.prose a,.flow a,.art a,.entry-content a,
p a,li a,dd a,td a,.crumbs a{
  text-decoration-line:underline;
  text-decoration-color:rgba(11,107,102,.45);
}
/* The four surfaces that are NOT prose opt out here, by name, so that the
   rule above can stay a blanket. Each one gets its colour in its own
   section: nav §10, rail §35, card §13, footer §27. */
:root .toc a,:root .rail a,:root .card,:root .nav__top,:root .sub a,
:root .mnav__grp a,:root .foot a,:root .topbar a,:root .btn{text-decoration-line:none}
/* Prose hover: the underline goes to full strength and a teal tint block
   appears behind the text, so the change is not carried by colour alone
   for a reader who cannot separate #0B6B66 from #0F5132. */
.prose a:hover,.flow a:hover,p a:hover,li a:hover,dd a:hover,td a:hover,a:not([class]):hover{
  color:var(--link-hover);                      /* #0F5132 on #E8F2F1 = 8.20:1 */
  text-decoration-color:currentColor;
  background:var(--s-teal);box-shadow:0 0 0 2px var(--s-teal);border-radius:2px;
}
a:hover{color:var(--link-hover)}    /* #0F5132 on #FFFFFF = 9.36:1 */

/* Focus is visible everywhere, and switches to the light gold on any dark
   surface so it never disappears into forest green. */
:focus-visible{outline:var(--focus-w) solid var(--focus);outline-offset:var(--focus-off);border-radius:2px}
.on-dark :focus-visible,
.sec--dark :focus-visible,
.plate :focus-visible,
.foot :focus-visible,
.topbar :focus-visible{outline-color:var(--focus-dark)}   /* #E8C86A: 5.18:1 on the
                                                             .sec--dark composite,
                                                             5.75:1 on flat forest */

::selection{background:#D9EAE1;color:var(--ink)}          /* #123222 on #D9EAE1 = 11.17:1 */

code,kbd,samp{font-family:var(--mono);font-size:.9em}
/* Indicator codes such as TOBACCO_MPOWER_O2_MEDICATIONAVAILABILITY are one
   unbroken word wider than a phone column; let them wrap inside prose. */
.prose code,.prose kbd,.prose samp{overflow-wrap:anywhere}

/* Skip link — off-screen until focused, then a real target at the top. */
.skip{
  position:absolute;left:var(--s4);top:-100px;z-index:200;
  background:var(--forest);color:#fff;                    /* #FFFFFF on #0F5132 = 9.36:1 */
  padding:.85rem 1.25rem;border-radius:0 0 var(--r-sm) var(--r-sm);
  font-weight:600;font-size:var(--fs-sm);text-decoration:none;
  transition:top var(--dur-1) var(--ease);
}
.skip:focus{top:0;color:#fff}

/* Screen-reader-only text. Used by .eocpr-newtab and WP core. */
.screen-reader-text,.visually-hidden,.eocpr-newtab{
  position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
}

/* Outbound source links open in a new tab. The arrow is decoration; the
   announcement comes from the .eocpr-newtab span that
   eocpr_annotate_new_tab_links() appends. */
.prose a[target="_blank"]::after,
.flow a[target="_blank"]::after,
.entry-content a[target="_blank"]::after{
  content:"\2197";font-size:.78em;line-height:1;display:inline-block;
  margin-inline-start:.18em;transform:translateY(-.15em);
  color:var(--deep-teal);text-decoration:none;                /* #0B6B66 on #FFFFFF = 6.35:1 */
}


/* =====================================================================
   7. LAYOUT — shell, sections, surfaces, soft joins
   ===================================================================== */
/* THE CONTAINER. Padding-inline, not a subtracted width: the gutter is
   then part of the box rather than a margin computed against it, so a
   full-bleed child can reach the viewport edge by cancelling the padding
   instead of by re-deriving the arithmetic. Content width at 2294px is
   1440 - 2 x 56 = 1328px. */
.shell{width:var(--shell);margin-inline:auto;padding-inline:var(--gutter)}
/* Kept, and deliberately a no-op: both tokens resolve to the same cap now.
   See the --shell note in §2 — five of the eleven templates carrying this
   class are not editable in this pass. */
.shell--wide{--shell:var(--shell-wide)}

.sec{padding-block:var(--section);position:relative}

/* No hard colour joins anywhere. Each band fades in and out of the page
   white over ~10% of its own height, so the page reads as one sheet of
   paper that gets warmer in places rather than as stacked coloured bars. */
.sec--band{
  background:linear-gradient(180deg,
    var(--s-page) 0%, var(--s-paper) 5%, var(--s-band) 14%,
    var(--s-band) 86%, var(--s-paper) 95%, var(--s-page) 100%);
}
/* The wash is --deep-teal #0B6B66, NOT the brand teal #0E8F8A. This is a
   contrast decision, not a colour preference. The wash is painted over the
   forest end of the linear gradient, so what a reader's text sits on is
   the COMPOSITE, never the flat --s-dark token:
     rgba(14,143,138,.28) over #0F5132 = #0F624B — gold-lum 4.4967:1  FAIL
     rgba(11,107,102,.28) over #0F5132 = #0E5841 — gold-lum 5.18:1    PASS
   Same alpha, same position, same size of glow; a darker source colour, so
   the composite stays dark enough for the gold to be legal on it. §3
   states every dark-surface ratio against #0E5841 for this reason. */
.sec--dark{
  background:
    radial-gradient(120% 90% at 12% 0%,rgba(11,107,102,.28) 0%,rgba(11,107,102,0) 58%),
    linear-gradient(170deg,var(--s-dark) 0%,var(--forest-deep) 100%);
  color:var(--on-dark);              /* #FFFFFF on #0E5841 composite = 8.43:1 */
}
/* THE LEAD-IN WASH IS GONE, and its removal is one of the four measured
   footer fixes. It painted a 32–64px transparent-to-#FCFAF4 strip in the
   margin ABOVE every .sec--dark. On the front page the only .sec--dark was
   the membership CTA sitting directly on the footer, so what a reader saw
   at the foot of the page was: a strip of empty warm grey, a green band,
   and then a second green band — which is exactly the complaint. The CTA
   is a light band now (.ctaband, §35) and there is one dark band per page,
   the footer. Nothing replaces this rule. */
.sec--dark h1,.sec--dark h2,.sec--dark h3,.sec--dark h4{color:var(--on-dark)}
.sec--dark p{color:var(--on-dark-mut)}   /* #C5D8CC on #0E5841 composite = 5.65:1 */
/* LINK 4 — INVERTED-ON-DARK. Was --gold-lum, which was the site's NINTH
   link colour and existed only here. It is white now, underlined, which is
   the same treatment the footer and the plate use — one rule for "a link
   on a dark surface" instead of three.

   :not(.btn) is load-bearing, not tidiness. `.sec--dark a` is (0,1,1) and
   `.btn--gold` is (0,1,0), so without it this rule WINS over the button's
   own label colour on the one gold button the site has. A button carries
   its own surface and therefore its own label colour. */
.sec--dark a:not(.btn){
  color:var(--link-inv);text-decoration-line:underline;   /* #FFFFFF on #0E5841 composite = 8.43:1 */
  text-decoration-color:rgba(255,255,255,.5);
}
.sec--dark a:not(.btn):hover{color:var(--link-inv);text-decoration-color:currentColor;background:none;box-shadow:none}

/* Section head — an eyebrow, a heading and at most one paragraph.
   66ch, not 34rem: the heading and its standfirst are read as running
   text, and the measure that governs running text is --measure's basis. */
.sechead{max-width:66ch;margin-bottom:var(--s7)}
.sechead h2{margin-top:.6rem}
/* :not(.eyebrow) so a section eyebrow keeps its own --gold-ink (5.73:1)
   instead of being overridden by this more specific selector. */
.sechead p:not(.eyebrow){margin-top:var(--s4);color:var(--text-mut);max-width:64ch}   /* 7.14:1 */
.sechead--wide{max-width:66ch}

/* The gold rule — brand colour as a MARK, never as a flat band. */
.rule{width:3.25rem;height:3px;background:var(--gold);border-radius:2px}

/* The asymmetric split: a sticky-feeling section head beside its content. */
.split{display:grid;gap:var(--s6)}


/* =====================================================================
   8. FLOW — the prose / breakout grid
   THIS IS THE CORE OF THE APPROVED LAYOUT. The reading column stays at a
   comfortable measure. Figures, callouts, quotes, tables, statistics and
   step sequences break out beyond it into the `wide` or `full` tracks.

     grid-column:text  (default)  the reading measure
     grid-column:wide  (.wide)    measure + one rail either side
     grid-column:full  (.full)    the entire container

   The rails are real columns, not margins, so a breakout element is
   centred on the same axis as the prose rather than nudged off it.

   TRACK ARITHMETIC AT 2294px, from the real Inter advance widths — this
   is the merged design's, re-derived against this theme's container:
     shell inner        1440 - 112 gutter            = 1328.0px
     rail column                                        260.0
     column gap                                          48.0
     flow container                                    1020.0
       text column   min(100%, 70ch) at 18px Inter   =  794.9   (~88 chars)
       inner gutters 2 x 3rem                        =   96.0
       outer tracks  2 x (1020 - 794.9 - 96)/2       =   64.5 each
     so: text 794.9  ->  .wide 890.9  ->  .full 1020.0

   At 390px every track outside the text column is minmax(0,...) and
   collapses to zero, so each object is full width and NO column is ever
   left empty — which was the other thing wrong with the earlier editorial
   build the owner saw.
   ===================================================================== */
.flow,.prose{
  display:grid;
  grid-template-columns:
    [full-start] minmax(0,1fr)
    [wide-start] minmax(0,var(--rail))
    [text-start] min(100%,var(--measure))
    [text-end]   minmax(0,var(--rail))
    [wide-end]   minmax(0,1fr)
    [full-end];
}
.flow > *,.prose > *{grid-column:text}
.flow > .wide,.prose > .wide,
.prose > .alignwide{grid-column:wide}
.flow > .full,.prose > .full,
.prose > .alignfull{grid-column:full}

/* Vertical rhythm inside the flow. Set on the flow, not on the elements,
   so a component dropped into it does not have to know its neighbours. */
.flow > * + *,.prose > * + *{margin-top:var(--s5)}
.flow > h2,.prose > h2{margin-top:var(--s8);scroll-margin-top:6rem}
.flow > h2 + *,.prose > h2 + *{margin-top:var(--s5)}
.flow > h3,.prose > h3{margin-top:var(--s6)}
.flow > h3 + *,.prose > h3 + *{margin-top:var(--s4)}
.flow > .wide,.flow > .full,
.prose > .wide,.prose > .full,
.prose > .alignwide,.prose > .alignfull{margin-top:var(--s7)}
.flow > :first-child,.prose > :first-child{margin-top:0}

/* BODY COPY IS INTER, NOT THE SERIF, AND THAT IS THE PORT.
   The earlier editorial direction set running text in Source Serif 4. The
   merged design drops it and keeps the serif for headings only. The reason
   is the audience, not taste: most of these readers are on a low-DPI
   Android screen, where a 400-weight text serif at 17px loses its thin
   strokes to the pixel grid. Source Serif 4 600 still carries every h1–h4,
   so the face the owner named is still the voice of the page.
   Removing the declaration is enough — body inherits --sans from §6. */
.flow p,.prose p{font-size:var(--fs-body);line-height:1.7}
.flow p a,.prose p a{font-weight:600}
.flow > ul:not([class]),.flow > ol:not([class]),
.prose > ul:not([class]),.prose > ol:not([class]){
  padding-left:1.35rem;display:grid;gap:var(--s2);
}
.flow > ul:not([class]){list-style:disc}
.flow > ol:not([class]){list-style:decimal}
.prose > ul:not([class]){list-style:disc}
.prose > ol:not([class]){list-style:decimal}
.flow hr,.prose hr{height:1px;background:var(--hair);border:0;margin-block:var(--s7)}


/* =====================================================================
   9. TEXT UTILITIES
   ===================================================================== */
/* The eyebrow leads with an ICON now rather than a gold dash — the dash
   was a ::before, so it could not be given a meaning, and the merged
   design puts a 24-grid outline mark there instead (§35). --gold-ink
   rather than --link, so an eyebrow can never be mistaken for a link. */
.eyebrow{
  font-family:var(--sans);font-size:var(--fs-xs);font-weight:600;
  letter-spacing:.10em;text-transform:uppercase;
  color:var(--gold-ink);             /* #7A6416 on #FFFFFF = 5.73:1 */
  display:flex;align-items:center;gap:.5rem;max-width:none;
}
.eyebrow .ic{color:var(--deep-teal)}    /* #0B6B66 on #FFFFFF = 6.35:1, non-text 3:1 floor cleared */
/* Templates that carry no icon keep a mark, so the eyebrow never starts
   flush with nothing. :not(:has(.ic)) rather than a modifier class,
   because five of the templates using .eyebrow are not editable here. */
.eyebrow:not(:has(.ic))::before{content:"";width:1.6rem;height:2px;background:var(--gold);flex:none}
/* 5.18:1 on the .sec--dark composite #0E5841, 5.75:1 on the flat forest of
   the footer and topbar. The composite is the worst case — see §3. */
.eyebrow--dark{color:var(--gold-lum)}

.lede{font-size:var(--fs-lede);line-height:1.5;color:var(--text-mut);font-weight:400;max-width:60ch}
.muted{color:var(--text-mut)}            /* #4A5C51 on #FFFFFF = 7.14:1 */
.measure{max-width:var(--measure)}
.center{text-align:center}
.stack > * + *{margin-top:var(--s4)}
.stack-6 > * + *{margin-top:var(--s5)}


/* =====================================================================
   10. HEADER — topbar, masthead, brandmark, nav, mobile nav
   ===================================================================== */
/* The topbar sits on forest-DEEP, so it reads as a distinct strip above
   the masthead rather than as the same green as the footer. Links here are
   LINK 3, the footer colour — a topbar and a footer are the same kind of
   surface and they now share one rule. */
.topbar{background:var(--forest-deep);color:var(--link-foot);font-size:var(--fs-xs)}
.topbar__in{display:flex;flex-wrap:wrap;gap:.35rem 1.25rem;align-items:center;justify-content:space-between;min-height:2.25rem}
/* min-height 44px on the anchor, not padding alone. The phone number is
   the one control a reader may tap in a hurry; inline-flex + align-items
   keeps the label optically centred in the taller box. */
.topbar a{
  color:var(--link-foot);text-decoration:none;padding:.6rem 0;     /* #D5E7DC on #0B3D26 = 9.53:1 */
  display:inline-flex;align-items:center;gap:.5rem;min-height:44px;
}
.topbar a:hover{color:var(--link-inv);text-decoration:underline}   /* #FFFFFF on #0B3D26 = 12.28:1 */
.topbar__util{display:flex;gap:.9rem;align-items:center;flex-wrap:wrap}
.topbar__loc{display:flex;align-items:center;gap:.5rem;color:var(--link-foot)}   /* 9.53:1 */
.topbar__note{font-size:.75rem;color:var(--on-dark-mut)}           /* #C5D8CC on #0B3D26 = 8.23:1 */
.topbar .ic{color:var(--gold-lum);width:1em;height:1em}            /* #E8C86A on #0B3D26 = 7.55:1, non-text */
.topbar a[aria-current]{font-weight:600;color:var(--link-inv)}     /* 12.28:1 */

/* Language switcher. Real links, so both languages are shareable. */
.lang{display:flex;gap:.55rem;align-items:center}
.lang a{padding:.6rem .2rem;min-height:44px;display:inline-flex;align-items:center}
.lang [aria-current]{color:var(--link-inv);font-weight:600}                                 /* #FFFFFF on #0B3D26 = 12.28:1 */

.masthead{
  position:sticky;top:0;z-index:60;background:rgba(255,255,255,.94);
  backdrop-filter:saturate(1.4) blur(10px);
  border-bottom:1px solid transparent;
  transition:border-color var(--dur-2) var(--ease),box-shadow var(--dur-2) var(--ease);
}
.masthead.is-stuck,.masthead.is-scrolled{border-bottom-color:var(--hair);box-shadow:var(--sh-nav)}
.masthead__in{display:flex;align-items:center;gap:var(--s5);min-height:68px;position:relative}

/* --- BRANDMARK ---------------------------------------------------------
   THE LOGO DECISION, and why.

   brand-kit/06_Vector/logo-english.svg is 80 KB of TRACED OUTLINES — the
   wordmark is paths, not type. Inlining it costs more than the rest of the
   document, it cannot be selected or searched, it cannot be recoloured per
   part, and the -reverse variant bakes its own #0F5132 rectangle into the
   artwork so it cannot sit on any other surface.

   CHOSEN: symbol-compact.svg (2.2 KB, four paths) inlined, with the
   wordmark set in LIVE TYPE beside it.
     - 2.2 KB inline beats an 80 KB request or an 80 KB inline, and beats a
       sprite too: at one mark per page a sprite's extra request and
       <use> indirection buy nothing.
     - live type stays crisp at every size, is selectable and searchable,
       reflows, and swaps to Amharic with no new asset and no second file.
     - the reverse treatment is then a class, not a different file: the
       symbol's four fills are named (.bm-forest/.bm-teal/.bm-dteal/
       .bm-gold) so .brandmark--rev can lighten them for dark green.
   TRADE-OFF, stated: the wordmark is then Source Serif 4 + Inter rather
   than the brand's traced logotype. They are close but not identical. Where
   the officially traced lockup is required — print, partner co-branding,
   press kits — use .brandmark--asset, which serves the real SVG as an
   EXTERNAL file so the browser caches it once across the whole site.

   SIZING: the symbol is sized in explicit relation to the masthead —
   38px at 360px wide, stepping to 52px on desktop — and the wordmark is
   set in ems OF the symbol, so the lockup scales as one object and never
   re-proportions itself.
   --------------------------------------------------------------------- */
.brandmark{
  --sym:clamp(2.375rem,1.6rem + 2.1vw,3.25rem);   /* 38px → 52px */
  display:flex;align-items:center;gap:clamp(.6rem,.9vw,.85rem);
  text-decoration:none;color:var(--forest);flex:none;
  padding:.4rem .4rem .4rem 0;border-radius:var(--r-sm);
}
.brandmark__sym{width:auto;height:var(--sym);flex:none;transition:transform var(--dur-4) var(--ease)}
.brandmark:hover .brandmark__sym{transform:translateY(-1px) scale(1.03)}
.brandmark__words{display:grid;gap:.12em;font-size:var(--sym)}
.brandmark__l1{
  font-family:var(--serif);font-size:.335em;font-weight:600;line-height:1.06;
  letter-spacing:-.014em;color:var(--forest);white-space:nowrap;   /* #0F5132 on #FFFFFF = 9.36:1 */
}
.brandmark__l2{
  font-family:var(--sans);font-size:.185em;font-weight:600;line-height:1;
  letter-spacing:.19em;text-transform:uppercase;
  color:var(--text-mut);white-space:nowrap;                        /* #4A5C51 on #FFFFFF = 7.14:1 */
}
/* Reverse treatment — works on forest, forest-deep and the footer. */
.brandmark--rev{color:#fff}
.brandmark--rev .brandmark__l1{color:#fff}                         /* #FFFFFF on #0F5132 = 9.36:1 */
.brandmark--rev .brandmark__l2{color:var(--on-foot-mut)}           /* #D5E7DC on #0F5132 = 7.26:1 */
.brandmark--rev .bm-forest{fill:#FBF7ED}
.brandmark--rev .bm-teal{fill:#5FC9C2}
.brandmark--rev .bm-dteal{fill:#3FA8A2}
/* Single-colour treatment, for print and for one-ink contexts. */
.brandmark--mono .bm-forest,.brandmark--mono .bm-teal,
.brandmark--mono .bm-dteal,.brandmark--mono .bm-gold{fill:currentColor}

/* The traced-asset escape hatch. External file, never inlined. */
.brandmark--asset{display:inline-block;padding:0}
.brandmark--asset img,.brandmark--asset svg{height:var(--sym);width:auto}

/* --- THE NAV — ONE ROW, SIX TOP-LEVEL ITEMS -------------------------
   The complaint, measured: at 2294px the bar carried NINE items and wrapped
   to two rows. It wrapped because .nav__list had flex-wrap:wrap, which is
   not a layout — it is a way of not deciding. The fix is the information
   architecture, not the wrapping:

     About cancer   > Reduce your risk · Early detection · Diagnosed
     Our research   > Behavioural (BRET) · Health services (CHSR) ·
                      Tobacco control (TCR)
     Insights
     Advocacy
     Professionals
     About          > Get involved · Support · Contact · News

   Children open on :hover AND on :focus-within, so the flyouts work with
   JavaScript off and are reachable by keyboard with no script and no
   aria-expanded to keep in sync.

   FIT AT 2294px. Every advance below was SUMMED FROM THE GLYPH METRICS in
   assets/fonts/inter-latin-600-normal.woff2, not estimated
   (shell inner 1440 - 112 gutter = 1328.0px available):
     brandmark   44.7 symbol + 11.2 gap + 228.5 wordmark      284.4
     gap                                                       24.0
     nav list    466.2 labels (97.8 About cancer, 94.9 Our
                 research, 57.6 Insights, 73.1 Advocacy,
                 99.0 Professionals, 43.9 About)
                 + 32.4 three chevrons (only three items have
                 children) + 105.6 padding + 8.0 gaps         612.2
     gap                                                       24.0
     CTA button  135.2 label + 36.8 padding + 2 border         174.0
     ---------------------------------------------------------------
     required                                                1118.6
     available                                               1328.0
     slack                                                    209.4  -> ONE ROW

   Below 69em the six items no longer fit honestly, and the bar becomes the
   <details> panel below rather than wrapping to a second row. There is no
   flex-wrap anywhere in this block: if something ever stops fitting it
   overflows visibly and gets fixed, instead of silently growing a row. */
/* The single navigation landmark. It holds both renderings of the menu —
   the bar and the <details> panel — and CSS guarantees exactly one of them
   is displayed at any width (§31). margin-left:auto lives here rather than
   on either child, so the two cannot disagree about their alignment. */
.nav__wrap{display:flex;align-items:center;margin-left:auto;min-width:0}
.nav{display:none;align-items:center;gap:var(--s5)}
.nav__list{display:flex;align-items:center;gap:.1rem;list-style:none;margin:0;padding:0}
.nav__list > li{position:relative}

/* LINK 2 — NAV. Position, weight and a tint carry it; no rule, no gold
   underline sliding in. 48px minimum height is kept from the old bar. */
.nav__top,.nav__list > li > a{
  display:flex;align-items:center;gap:.28rem;padding:.55rem .55rem;min-height:48px;
  border-radius:var(--r-sm);font-size:.9375rem;font-weight:600;letter-spacing:.005em;
  color:var(--link-nav);text-decoration:none;white-space:nowrap;   /* #123222 on #FFFFFF = 13.95:1 */
}
.nav__top:hover,.nav__list > li > a:hover,
.nav__list > li:focus-within > .nav__top{background:var(--s-teal)}  /* #123222 on #E8F2F1 = 12.23:1 */
.nav__top .ic{width:.72em;height:.72em;stroke-width:2.2;color:var(--deep-teal)}
.nav__list > li.is-cur > .nav__top,
.nav__list > li.current-menu-item > a,
.nav__list > li > a[aria-current]{box-shadow:inset 0 -2px 0 var(--teal)}  /* #0E8F8A on #FFFFFF = 3.95:1, non-text, clears 3:1 */

/* THE FLYOUT. opacity + visibility, not display:none, so the transition in
   §30 has something to move; visibility:hidden keeps it out of the tab
   order while closed. This is the ONLY opacity:0 in the file that is not
   inside the §30 motion gate, and it is safe because nothing but :hover
   and :focus-within is needed to open it — no script is involved. */
.sub{
  position:absolute;top:calc(100% + .3rem);left:-.35rem;min-width:16.5rem;
  background:var(--s-page);border:1px solid var(--hair);border-radius:var(--r);
  box-shadow:var(--sh-2);padding:.4rem;opacity:0;visibility:hidden;
  transform:translateY(-5px);z-index:5;
}
.nav__list > li:hover > .sub,
.nav__list > li:focus-within > .sub{opacity:1;visibility:visible;transform:none}
/* The last two flyouts open right-aligned so neither can push the page
   sideways and produce a horizontal scrollbar at the shell edge. */
.nav__list > li:nth-last-child(-n+2) > .sub{left:auto;right:-.35rem}
.sub a{
  display:flex;align-items:center;gap:.55rem;padding:.5rem .6rem;min-height:44px;
  border-radius:var(--r-sm);font-size:.9375rem;
  color:var(--link-nav);text-decoration:none;                      /* 13.95:1 */
}
.sub a:hover{background:var(--s-teal)}                             /* 12.23:1 */
.sub a[aria-current]{background:var(--s-teal);box-shadow:inset 2px 0 0 var(--teal)}
.sub .ic{width:1.05em;height:1.05em;color:var(--deep-teal)}        /* 6.35:1 */

/* Between 69em and 82em the six items fit but the membership button does
   not. It is WITHHELD there rather than allowed to wrap the row; it is
   still in the mobile panel, in the footer and in the homepage section. */
.nav > .btn,.masthead__cta{display:none}

/* --- THE MOBILE MENU — a <details>, so it opens with JavaScript off ---
   This replaces the old #navtoggle + #mnav + #scrim trio, which was a
   fixed slide-in panel whose open state existed only in JavaScript. With
   the script blocked there was NO navigation on a phone at all — the
   fallback for that was 40 lines of html:not(.js) overrides in §31 that
   rebuilt a second, different menu. A <details> needs none of it: one
   markup path, one code path, open and close in the browser. */
.mnav{position:relative}
.mnav__sum{
  display:flex;align-items:center;gap:.5rem;list-style:none;cursor:pointer;
  padding:.55rem .8rem;min-height:48px;border:1px solid var(--line-ctl);
  border-radius:var(--r-sm);font-size:.9375rem;font-weight:600;
  color:var(--link-nav);                    /* label 13.95:1 · border #828D85 = 3.44:1, SC 1.4.11 */
}
.mnav__sum::-webkit-details-marker{display:none}
.mnav[open] .mnav__sum{background:var(--s-teal);border-color:var(--deep-teal)}
.mnav__panel{
  position:absolute;left:auto;right:calc(var(--gutter) * -1);
  width:min(92vw,26rem);top:calc(100% + .6rem);
  background:var(--s-page);border:1px solid var(--hair);border-radius:var(--r);
  box-shadow:var(--sh-2);padding:var(--s4) var(--s5) var(--s6);
  max-height:76vh;overflow:auto;z-index:70;
}
.mnav__grp{padding:.5rem 0;border-bottom:1px solid var(--hair-soft)}
.mnav__grp > a{
  display:flex;align-items:center;gap:.6rem;min-height:48px;
  font-size:1.0625rem;font-weight:600;
  color:var(--link-nav);text-decoration:none;padding:.35rem 0;     /* 13.95:1 */
}
.mnav__grp > a .ic{color:var(--deep-teal)}
.mnav__grp ul{display:flex;flex-wrap:wrap;gap:.35rem .45rem;padding:.2rem 0 .35rem 2rem;list-style:none;margin:0}
.mnav__grp ul a{
  display:flex;align-items:center;min-height:44px;padding:.35rem .55rem;
  border-radius:var(--r-sm);background:var(--s-band);font-size:.9375rem;
  color:var(--link-nav);text-decoration:none;                      /* #123222 on #FBF7ED = 13.04:1 */
}
.mnav__grp ul a:hover{background:var(--s-teal)}                    /* 12.23:1 */
.mnav .btn{margin-top:var(--s5);width:100%}


/* =====================================================================
   11. BUTTONS — 48px minimum touch target throughout
   ===================================================================== */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:.55rem;
  min-height:48px;padding:.8rem 1.4rem;border-radius:var(--r-pill);
  border:1.5px solid transparent;
  font-family:var(--sans);font-size:var(--fs-sm);font-weight:600;letter-spacing:.005em;
  text-decoration:none;cursor:pointer;text-align:center;
  transition:background-color var(--dur-1) var(--ease),
             box-shadow var(--dur-2) var(--ease),color var(--dur-1) var(--ease),
             border-color var(--dur-1) var(--ease);
}
/* TONE, NOT LIFT. The -2px hover translate is gone from every button, card
   and tile in this file. A control that moves under the pointer is harder
   to hit, not easier, and on a touch screen the lift only ever fires after
   the tap has already landed. Each hover below changes SURFACE instead. */
.btn--primary{background:var(--forest);color:#fff;box-shadow:var(--sh-1)}       /* #FFFFFF on #0F5132 = 9.36:1 */
.btn--primary:hover{background:var(--forest-hover);color:#fff;box-shadow:var(--sh-2)} /* #FFFFFF on #0C4429 = 11.20:1 */
/* The border is the ONLY thing that identifies this control — transparent
   fill, no shadow — so SC 1.4.11 applies to it and it must be 3:1. It was
   #BFCFC4: 1.62:1 on white and 1.52:1 on a band. Now --line-ctl #828D85:
   3.44:1 on white, 3.22:1 on a band. */
.btn--outline{background:transparent;color:var(--forest);border-color:var(--line-ctl)}  /* label #0F5132 on #FFFFFF = 9.36:1 */
.btn--outline:hover{border-color:var(--forest);background:var(--s-band);color:var(--forest)} /* #0F5132 on #FBF7ED = 8.75:1 */
/* Gold button: forest #0F5132 on gold is only 4.45:1 and fails AA at this
   size, so the label uses the deeper forest. Measured, not assumed. */
.btn--gold{background:var(--gold);color:var(--forest-deep)}                     /* #0B3D26 on #D4AF37 = 5.84:1 */
.btn--gold:hover{background:var(--gold-hover);color:var(--forest-deep)}         /* #0B3D26 on #E0BE4C = 6.81:1 */
/* Ghost sits only on a dark surface. The border carries the affordance. */
.btn--ghost{background:rgba(255,255,255,.08);color:#fff;border-color:rgba(255,255,255,.45)}
.btn--ghost:hover{background:rgba(255,255,255,.16);color:#fff;border-color:#fff}
.btn--block{width:100%}
.btn__ar{transition:transform var(--dur-2) var(--ease);flex:none}
.btn:hover .btn__ar{transform:translateX(3px)}
.btn[disabled],.btn[aria-disabled="true"]{opacity:.55;cursor:not-allowed;transform:none}


/* =====================================================================
   12. HERO + STATISTIC PANEL — asymmetric, not a stacked band
   ===================================================================== */
/* The wash is painted as a background on .hero itself rather than as a
   z-index:-1 pseudo-element. The old ::before sat on a negative stacking
   layer, which meant it painted BEHIND an opaque body background on any
   engine that gave <body> one — so on some renders the hero had no wash at
   all and on others it bled outside the section. A background does neither
   and costs one fewer box. */
.hero{
  position:relative;overflow:clip;
  padding-block:clamp(2.5rem,4.2vw,4.5rem) clamp(3rem,5vw,5.5rem);
  background:
    radial-gradient(58rem 34rem at 88% -14%,rgba(14,143,138,.075),transparent 62%),
    radial-gradient(46rem 30rem at -8% 6%,rgba(212,175,55,.065),transparent 60%),
    var(--s-page);
  border-bottom:1px solid var(--hair);
}
/* TWO TRACKS AGAIN, AND THIS TIME THE SECOND ONE IS FILLED.
   The previous pass collapsed this to one column because the second track
   was empty: the approved preview had a statistic panel there and there
   was no approved copy for one. The merged design fills it with .plate
   (§35) — a finished object made of one approved sentence, the brandmark
   as a watermark and a gradient, needing no statistic and no photograph.
   So the wide screen is composed ACROSS rather than down, which is the
   owner's "not screen optimised" complaint, and no track is left empty. */
.hero__grid{display:grid;gap:clamp(2rem,3.5vw,3.5rem)}
.hero h1,.hero__h{font-size:var(--fs-hero);letter-spacing:-.021em;line-height:var(--lead-tight);margin-top:.85rem;max-width:24ch}
.hero .lede,.hero__lede{margin-top:var(--s5);max-width:54ch}
.hero__acts{display:flex;flex-wrap:wrap;gap:.75rem;margin-top:var(--s6);max-width:none}
/* A row of plain facts under the fold line. Each item is an approved
   string with a decorative mark; nothing here is a claim or a count. */
.hero__meta{
  display:flex;flex-wrap:wrap;gap:.6rem 2rem;margin-top:var(--s6);
  padding-top:var(--s5);border-top:1px solid var(--hair);max-width:none;
}
.hero__meta span{display:flex;align-items:center;gap:.5rem;font-size:var(--fs-sm);color:var(--text-mut)}  /* 7.14:1 */
.hero__meta .ic{color:var(--deep-teal)}                                                                  /* 6.35:1 */

/* The statistic panel — an elevated surface offset from the hero column.
   NOTE: there is no count-up. The number in the markup is the number the
   reader sees, from first paint, always. */
.statpanel{
  background:var(--s-card);border-radius:var(--r-lg);box-shadow:var(--sh-3);
  padding:clamp(1.5rem,3vw,2.25rem);position:relative;
  border-top:4px solid var(--gold);
}
.statpanel__hd{
  font-family:var(--sans);font-size:var(--fs-xs);font-weight:600;letter-spacing:.13em;
  text-transform:uppercase;color:var(--text-mut);              /* #4A5C51 on #FFFFFF = 7.14:1 */
}
.statlist{display:grid;gap:var(--s5);margin-top:var(--s5);list-style:none;padding:0}
.statpanel__foot{
  margin-top:var(--s5);padding-top:var(--s4);border-top:1px solid var(--hair-soft);
  font-size:var(--fs-xs);color:var(--text-mut);                /* #4A5C51 on #FFFFFF = 7.14:1 */
}
.statpanel__foot a{font-weight:600}


/* =====================================================================
   13. CARDS
   ===================================================================== */
.cards{display:grid;gap:var(--s5)}
/* A hairline and a surface, not a shadow. The old card was a floating
   white box on a white page held up by a shadow; on a phone screen in
   daylight the shadow is invisible and the card had no edge at all. */
.card{
  position:relative;background:var(--s-card);border:1px solid var(--hair);border-radius:var(--r);
  padding:var(--s6) var(--s5) var(--s5);
  display:flex;flex-direction:column;gap:.65rem;
  text-decoration:none;color:var(--text);
}
/* Whole-card hit area when the card itself is the link. */
a.card::after{content:"";position:absolute;inset:0;border-radius:var(--r)}
/* TONE, NOT LIFT — no transform, no shadow change. */
a.card:hover{background:var(--s-paper);border-color:#D8D2C0}    /* #123222 on #FCFAF4 = 13.37:1 */
.card__ic{
  display:grid;place-items:center;width:2.9rem;height:2.9rem;flex:none;border-radius:10px;
  background:var(--s-teal);color:var(--forest);margin-bottom:.3rem;   /* #0F5132 on #E8F2F1 = 8.20:1 */
}
.card__ic .ic{width:1.55rem;height:1.55rem;stroke-width:1.6}
a.card:hover .card__ic{background:var(--forest);color:var(--link-inv)}  /* #FFFFFF on #0F5132 = 9.36:1 */
.card__b{min-width:0}
.cards--row .card{flex-direction:row;align-items:flex-start;gap:var(--s4);padding:var(--s5)}
.cards--row .card__ic{margin-bottom:0}
.cards--row .card__b h3{margin-bottom:.4rem}
.card__idx{
  font-family:var(--sans);font-size:var(--fs-xs);font-weight:700;letter-spacing:.1em;
  color:var(--gold-ink);   /* #7A6416 on #FFFFFF = 5.73:1 · on teal tint #E8F2F1 = 5.03:1 */
}
.card h3{color:var(--forest)}
/* A card heading is sometimes legitimately an h2 (news cards; child-nav
   cards on a page whose body has no h2). Correct heading order must not
   change the visual size, so h2 inside a card is set at the h3 step. */
.card h2{color:var(--forest)}
.card h2{font-size:var(--fs-h3)}
                                  /* #0F5132 on #FFFFFF = 9.36:1 */
.card p{color:var(--text-mut);font-size:var(--fs-sm);line-height:1.55;max-width:none}  /* #4A5C51 on #FFFFFF = 7.14:1 */

/* The source line under a homepage claim, added 0.5.3. Until then the
   homepage carried no citation at all while every page behind it linked
   everything — the one page a funder, a journalist or a ministry official
   skims was the one page with nothing to check.

   It is set smaller than the claim and in the muted ink on purpose: this is
   provenance, and §4 of the working brief puts provenance where a reader can
   skip it. The claim is the thing being read; the source is the thing being
   available.

   NO NEW CONTRAST LEDGER ENTRY IS NEEDED. Both colours are already measured
   in §3 against this exact surface — the risk cards sit on .sec, which is
   page white:
       --text-mut  #4A5C51  on  #FFFFFF  =  7.14:1
       --link      #0B6B66  on  #FFFFFF  =  6.35:1
   Underlined as well as coloured, so the link is not carried by colour
   alone. */
.card__src{
  margin-top:.55rem;font-size:var(--fs-xs);line-height:1.5;
  color:var(--text-mut);max-width:none;
}
.card__src a{color:var(--link);text-decoration:underline;text-underline-offset:.15em}
.card__src a:hover{color:var(--link-hover)}                       /* #0F5132 on #FFFFFF = 9.36:1 */

/* Not a link and never focusable — it sits inside a card that IS the link,
   so it carries aria-hidden in every template that renders it. */
.card__go{
  display:flex;align-items:center;gap:.4rem;font-size:var(--fs-sm);font-weight:600;
  color:var(--deep-teal);margin-top:auto;padding-top:var(--s4);   /* #0B6B66 on #FFFFFF = 6.35:1 */
}
.card__go .ic{width:1.15rem;height:1.15rem}
.card:hover .card__go{color:var(--forest)}                        /* #0F5132 on #FCFAF4 = 8.97:1 */
.card__go svg{transition:transform var(--dur-2) var(--ease)}
.card:hover .card__go svg,a.card:hover .card__go .ic{transform:translateX(4px)}
.card--feature{background:linear-gradient(160deg,var(--s-teal),#FFFFFF 72%)}
.card--feature h3{font-size:clamp(1.5rem,1.2rem + 1.2vw,2rem)}
.card--flat{box-shadow:none;border:0;background:transparent;padding:0}


/* =====================================================================
   14. UNIT ROWS — an editorial list, not three boxes in a row
   ===================================================================== */
.units{display:grid;margin-top:var(--s6);border-top:1px solid var(--hair);list-style:none;padding:0}
.unit{
  display:grid;gap:.4rem 1.15rem;padding:var(--s5) .75rem;
  border-bottom:1px solid var(--hair);position:relative;
}
.unit:hover{background:var(--s-page)}
/* The row mark. An outline icon on a bordered tile, filling to deep teal
   on hover — tone, not lift, and the same grammar as .card__ic. */
.unit__ic{
  display:grid;place-items:center;width:2.5rem;height:2.5rem;flex:none;border-radius:9px;
  background:var(--s-page);border:1px solid var(--hair);color:var(--deep-teal);   /* 6.35:1 */
}
.unit:hover .unit__ic{background:var(--deep-teal);color:var(--link-inv);border-color:var(--deep-teal)}
                                                                 /* #FFFFFF on #0B6B66 = 6.35:1 */
/* Re-scaled against the reset type scale. At its old clamp this numeral
   topped out at 48px, which was under the old 44.8px h2 but is now larger
   than the 34px h2 beside it — a row number would have been shouting over
   the row's own title. 24 -> 32px keeps it a mark, which is what it is. */
.unit__k{
  font-family:var(--serif);font-size:clamp(1.5rem,1.24rem + .66vw,2rem);line-height:1;
  font-weight:600;color:var(--gold-ink);letter-spacing:-.02em;  /* #7A6416 on band #FBF7ED = 5.36:1 */
  font-variant-numeric:tabular-nums;
}
.unit__abbr{
  display:inline-block;font-family:var(--sans);font-size:var(--fs-xs);font-weight:700;
  letter-spacing:.12em;padding:.3rem .6rem;border-radius:var(--r-sm);
  background:var(--s-teal);color:var(--link);                   /* #0B6B66 on #E8F2F1 = 5.56:1 */
}
.unit p{color:var(--text-mut);max-width:74ch}                   /* #4A5C51 on #FBF7ED = 6.67:1 */


/* =====================================================================
   15. ARTICLE MASTHEAD, BREADCRUMBS, CONTENTS RAIL
   ===================================================================== */
/* Same change as the hero: the wash is a background, not a z-index:-1
   pseudo-element that can paint behind an opaque body. */
.artmast{
  padding-block:clamp(1.5rem,3vw,2.25rem) var(--s6);position:relative;overflow:clip;
  border-bottom:1px solid var(--hair);
  background:radial-gradient(46rem 28rem at 88% -20%,rgba(14,143,138,.06),transparent 62%),var(--s-page);
}
.artmast h1{font-size:var(--fs-art-h1);margin-top:.7rem;max-width:20ch;letter-spacing:-.021em;line-height:var(--lead-tight)}
/* Sans, like every other run of body copy on the site now — see §8. */
.standfirst{
  font-size:var(--fs-lede);line-height:1.5;
  color:var(--text-mut);margin-top:var(--s5);max-width:78ch;    /* #4A5C51 on #FFFFFF = 7.14:1 */
}
.artmeta{
  display:flex;flex-wrap:wrap;gap:var(--s2) var(--s5);margin-top:var(--s6);padding-top:var(--s4);
  border-top:1px solid var(--hair);font-size:var(--fs-xs);color:var(--text-mut);  /* 7.14:1 */
}
.artmeta strong{color:var(--text);font-weight:600}

.crumbs__nav{display:block}
.crumbs{
  display:flex;flex-wrap:wrap;gap:.4rem;align-items:center;list-style:none;padding:0;
  font-size:var(--fs-xs);color:var(--text-mut);padding-block:var(--s2);   /* #4A5C51 on #FFFFFF = 7.14:1 */
}
.crumbs li{display:flex;align-items:center;gap:.4rem}
.crumbs li::after{content:"/";color:#8B968D}    /* separator, decorative — 3.07:1 on white */
.crumbs li:last-child::after{content:""}
/* 44px, the COMPONENTS.md §1 floor for a dense inline list. Padding alone
   gave 13px x 1.68 + 2 x .5rem = 37.84px. 44 rather than 48 here because
   the crumb trail is a dense inline row and 48 pushes the article h1 down
   a visible step on a phone for no gain. */
/* LINK 1 — prose. A breadcrumb is a run of inline links inside a sentence
   of a trail, not a navigation bar, so it takes the prose colour and the
   prose underline rather than becoming a tenth local decision. */
.crumbs a{
  color:var(--link);padding:.5rem 0;                            /* #0B6B66 on #FFFFFF = 6.35:1 */
  display:inline-flex;align-items:center;min-height:44px;
}
.crumbs a:hover{color:var(--link-hover)}
.crumbs [aria-current]{color:var(--text)}       /* #123222 on #FFFFFF = 13.95:1 */
.crumbs .ic{width:.85em;height:.85em;color:var(--line-ctl)}     /* #828D85 = 3.44:1, decorative separator */

/* Contents rail. A real <details> on mobile so it cannot eat the first
   screen; forced open, sticky and marker-less from 1024px up. */
.art{padding-bottom:var(--section)}
.art__grid{display:grid;gap:var(--s6)}
.toc{position:relative}
.toc__hd{
  font-size:var(--fs-xs);font-weight:700;letter-spacing:.13em;text-transform:uppercase;
  color:var(--text-mut);margin-bottom:var(--s3);              /* #4A5C51 on #FFFFFF = 7.14:1 */
}
.toc ol{counter-reset:t;display:grid;list-style:none;padding:0;margin:0}
.toc li{counter-increment:t}
/* LINK 2 — nav. This block used --text-mut for the link and --forest for
   its hover and current states, which were the sixth and seventh link
   colours on the site. A contents rail IS navigation, so it takes the
   navigation colour; the hierarchy is carried by the rule on its left
   edge and by the gold numeral, not by dimming the text. Matches .rail in
   §35.5, which is the same object under its current name. */
.toc a{
  display:flex;gap:.7rem;align-items:baseline;padding:.6rem .5rem .6rem .7rem;min-height:44px;
  font-size:var(--fs-sm);line-height:1.4;color:var(--link-nav);text-decoration:none;   /* 13.95:1 */
  border-left:2px solid var(--hair);
  transition:border-color var(--dur-2) var(--ease),color var(--dur-2) var(--ease),
             background-color var(--dur-2) var(--ease);
}
.toc a::before{
  content:counter(t,decimal-leading-zero);font-size:var(--fs-xs);font-weight:700;
  color:var(--gold-ink);flex:none;font-variant-numeric:tabular-nums;   /* #7A6416 on #FFFFFF = 5.73:1 */
}
.toc a:hover{border-left-color:var(--gold);background:var(--s-band)}                    /* #123222 on #FBF7ED = 13.04:1 */
.toc a[aria-current]{font-weight:600;border-left-color:var(--forest);background:var(--s-band)}
.toc a[aria-current]::before{color:var(--forest)}                                       /* #0F5132 on #FBF7ED = 8.75:1 */
.toc__m{display:block}
.toc__m > summary{
  list-style:none;cursor:pointer;min-height:48px;display:flex;align-items:center;
  justify-content:space-between;gap:var(--s3);padding:.85rem 1rem;
  background:var(--s-band);border:1px solid var(--hair);border-radius:var(--r-sm);
  font-size:var(--fs-sm);font-weight:600;color:var(--forest);     /* #0F5132 on #FBF7ED = 8.75:1 */
}
.toc__m > summary::-webkit-details-marker{display:none}
.toc__m > summary::after{
  content:"";width:.6rem;height:.6rem;border-right:2px solid currentColor;border-bottom:2px solid currentColor;
  transform:rotate(45deg) translate(-2px,-2px);transition:transform var(--dur-2) var(--ease);flex:none;
}
.toc__m[open] > summary::after{transform:rotate(-135deg) translate(-2px,-2px)}
.toc__m .toc{margin-top:var(--s4)}
.toc__wrap{min-width:0}


/* ---------------------------------------------------------------------
   15.4 REVIEW FURNITURE — the block at the foot of a health page

   Added 1 September 2026. Rendered by page.php only when a review date is
   actually stored, so it is invisible on every page until a named reviewer
   exists. See the comment in page.php for why that is the intended state
   rather than an unfinished one.

   It is set as a quiet footer rather than a callout. This is provenance: the
   reader who wants it goes looking, and the reader who does not should not have
   it competing with the last thing the page had to say. §4 of the working brief
   puts provenance where it can be skipped.

   COLOURS ARE ALL FROM THE MEASURED SET IN §3, on the page-white surface the
   article sits on. No new ledger entries:
       --text      #123222  on #FFFFFF  = 13.95:1   the values
       --text-mut  #4A5C51  on #FFFFFF  =  7.14:1   the labels and the note
       --link      #0B6B66  on #FFFFFF  =  6.35:1   the corrections link
       --gold-ink  #7A6416  on #FFFFFF  =  5.73:1   the overdue marker
   The overdue marker is a word, not a colour — "— overdue" in text. The tint is
   the second cue, never the first, which is the same rule the dashboard applies
   to a stale figure. --------------------------------------------------- */
.revfoot{
  margin-top:var(--s7);padding-top:var(--s5);
  border-top:1px solid var(--hair);
}
.revfoot__h{
  font-family:var(--sans);font-size:var(--fs-xs);font-weight:700;
  letter-spacing:.1em;text-transform:uppercase;
  color:var(--text-mut);margin:0 0 var(--s4);            /* 7.14:1 */
}
.revfoot__l{
  display:grid;gap:var(--s3) var(--s6);margin:0;
  grid-template-columns:1fr;
}
@media (min-width:44em){
  .revfoot__l{grid-template-columns:repeat(auto-fit,minmax(13rem,max-content))}
}
.revfoot__l dt{
  font-size:var(--fs-xs);color:var(--text-mut);margin:0 0 .15rem;  /* 7.14:1 */
}
.revfoot__l dd{
  font-size:var(--fs-sm);color:var(--text);margin:0;font-weight:600;  /* 13.95:1 */
}
.revfoot__od{color:var(--gold-ink);font-weight:700}       /* #7A6416 on #FFFFFF = 5.73:1 */
.revfoot__n{
  margin:var(--s4) 0 0;font-size:var(--fs-xs);line-height:1.55;
  color:var(--text-mut);max-width:60ch;                   /* 7.14:1 */
}
.revfoot__n a{color:var(--link);text-decoration:underline;text-underline-offset:.15em}
.revfoot__n a:hover{color:var(--link-hover)}              /* #0F5132 on #FFFFFF = 9.36:1 */


/* =====================================================================
   16. DESIGNED LIST MARKERS — never a browser disc
   ===================================================================== */
.dlist{display:grid;gap:var(--s4);list-style:none;padding:0}
.dlist li{position:relative;padding-left:1.9rem;font-family:var(--serif);line-height:var(--lead-body)}
.dlist li::before{
  content:"";position:absolute;left:0;top:.62em;width:.7rem;height:.7rem;border-radius:2px;
  background:var(--gold);transform:rotate(45deg);
}
/* Tick variant, for things that are done or true. */
.dlist--check li::before{
  width:.85rem;height:.5rem;border-left:2.5px solid var(--deep-teal);border-bottom:2.5px solid var(--deep-teal);
  background:none;border-radius:0;transform:rotate(-45deg);top:.5em;
}
/* Inline variant, for a set of short terms that belong together. */
.dlist--inline{display:flex;flex-wrap:wrap;gap:var(--s2) var(--s4)}
.dlist--inline li{padding-left:1.25rem;font-family:var(--sans);font-size:var(--fs-sm);color:var(--text)}
.dlist--inline li::before{width:.45rem;height:.45rem;top:.62em;background:var(--deep-teal)}


/* =====================================================================
   17. KEY-FACT CALLOUTS
   ===================================================================== */
.kfacts{display:grid;gap:var(--s4)}
.kfact{
  background:var(--s-card);border-radius:var(--r);padding:clamp(1.25rem,2.4vw,1.75rem);
  box-shadow:var(--sh-1);border-left:4px solid var(--gold);
  display:grid;gap:var(--s3);align-content:start;
  transition:box-shadow var(--dur-3) var(--ease),transform var(--dur-3) var(--ease);
}
.kfact:hover{box-shadow:var(--sh-2);transform:translateY(-2px)}
.kfact h3{
  font-size:1.1rem;letter-spacing:0;font-family:var(--sans);font-weight:700;
  color:var(--forest);line-height:1.35;                          /* #0F5132 on #FFFFFF = 9.36:1 */
}
.kfact p{font-family:var(--serif);font-size:var(--fs-sm);line-height:1.62;color:var(--text)}  /* 13.95:1 */
.kfact--teal{border-left-color:var(--deep-teal);background:linear-gradient(150deg,var(--s-teal),#fff 62%)}


/* =====================================================================
   18. STATISTIC BLOCKS
   NO COUNT-UP. The value in the markup is the value on screen from first
   paint. These numbers describe mortality; animating them gamifies them.
   ===================================================================== */
.stats{
  display:grid;gap:var(--s5);background:var(--s-card);border-radius:var(--r-lg);
  padding:clamp(1.5rem,3vw,2.25rem);box-shadow:var(--sh-2);border-top:4px solid var(--gold);
}
.stat{display:grid;gap:.35rem}
.stat__n{
  font-family:var(--serif);font-weight:700;line-height:.92;
  color:var(--forest);                                           /* #0F5132 on #FFFFFF = 9.36:1 */
  font-size:clamp(2.5rem,1.6rem + 3.4vw,3.5rem);letter-spacing:-.03em;font-variant-numeric:tabular-nums;
}
.stat__n em{font-style:normal;font-size:.5em;font-weight:600;letter-spacing:-.01em}
.stat__l{font-size:var(--fs-sm);color:var(--text);font-weight:600;line-height:1.45}   /* 13.95:1 —
   600 rather than the preview's 500: Inter 500 is no longer shipped (§1) and this is a
   label, so it takes the label weight already used by .statpanel__hd rather than
   dropping to body weight and merging with .stat__src underneath it. */
.stat__src{font-size:var(--fs-xs);color:var(--text-mut);line-height:1.45}             /*  7.14:1 */
/* Inside the hero panel the statistics stack with a rule between them. */
.statlist .stat + .stat{padding-top:var(--s5);border-top:1px solid var(--hair-soft)}


/* =====================================================================
   19. FIGURE FRAMES
   ===================================================================== */
.figframe{background:var(--s-card);border-radius:var(--r-lg);box-shadow:var(--sh-2);overflow:hidden}
.figframe__hd{
  padding:clamp(1rem,2vw,1.35rem) clamp(1.1rem,2.4vw,1.75rem);
  background:var(--s-band-deep);border-bottom:1px solid var(--hair);
  display:flex;flex-wrap:wrap;gap:.4rem var(--s4);align-items:baseline;justify-content:space-between;
}
.figframe__hd span:first-child{
  font-size:var(--fs-xs);font-weight:700;letter-spacing:.12em;text-transform:uppercase;
  color:var(--gold-ink);                                         /* #7A6416 on #F5F1E6 = 5.08:1 */
}
.figframe__hd span:last-child{font-size:var(--fs-xs);color:var(--text-mut)}   /* #4A5C51 on #F5F1E6 = 6.33:1 */
.figframe__plot{padding:clamp(.75rem,2vw,1.5rem)}
.figframe__plot svg{width:100%;height:auto}
/* A matplotlib export carries inline font-family attributes; re-set its
   type in the site face. !important is required to beat those attributes. */
.figframe__plot svg text{font-family:'Schibsted Grotesk',-apple-system,'Segoe UI',Helvetica,Arial,sans-serif !important}
.figframe figcaption{
  padding:clamp(1rem,2.2vw,1.5rem) clamp(1.1rem,2.4vw,1.75rem);
  border-top:1px solid var(--hair);background:var(--s-paper);
  font-size:var(--fs-sm);line-height:1.6;color:var(--text-mut);  /* #4A5C51 on #FCFAF4 = 6.84:1 */
}
.figframe figcaption b,.figframe figcaption strong{color:var(--text);font-weight:600}
.figframe figcaption code{
  font-family:var(--mono);font-size:.9em;background:var(--s-band-deep);
  padding:.1em .35em;border-radius:3px;color:var(--text);        /* #123222 on #F5F1E6 = 12.36:1 */
}
/* Forced-colors mode would flatten a data figure to two colours. */
@media (forced-colors:active){.figframe__plot svg{forced-color-adjust:none}}


/* =====================================================================
   20. QUOTES — break the column, and no quotation-mark clip art
   ===================================================================== */
.quote,.pull{
  border-top:3px solid var(--gold);
  padding-block:clamp(1.5rem,3vw,2.25rem) 0;position:relative;
}
.pull{border-bottom:1px solid var(--hair);padding-bottom:clamp(1.5rem,3vw,2.25rem)}
.quote blockquote,.pull blockquote{
  font-family:var(--serif);font-size:clamp(1.4rem,1.1rem + 1.6vw,2.15rem);
  line-height:1.28;letter-spacing:-.018em;
  color:var(--forest);font-weight:400;text-wrap:balance;         /* #0F5132 on #FFFFFF = 9.36:1 */
}
.pull blockquote{font-size:clamp(1.35rem,1.05rem + 1.5vw,2.05rem)}
.quote figcaption,.pull figcaption{margin-top:var(--s4);font-size:var(--fs-sm);color:var(--text-mut)}  /* 7.14:1 */
.quote figcaption strong,.pull figcaption strong{color:var(--text);font-weight:600}


/* =====================================================================
   21. ACCORDIONS
   The height transition is driven from JS (§ assets/js/eocpr.js) because
   height:auto cannot be animated. Without JS the panel still opens and
   closes correctly — hidden is toggled first, animation second.
   ===================================================================== */
.acc{display:grid;border-top:1px solid var(--hair)}
.acc__item{border-bottom:1px solid var(--hair)}
.acc__btn{
  display:flex;width:100%;gap:var(--s4);align-items:center;justify-content:space-between;
  min-height:56px;padding:1rem .25rem;background:none;border:0;cursor:pointer;text-align:left;
  font-family:var(--serif);font-size:var(--fs-h3);line-height:1.25;letter-spacing:-.01em;
  color:var(--forest);font-weight:600;                           /* #0F5132 on #FFFFFF = 9.36:1 */
  transition:color var(--dur-1) var(--ease);
}
.acc__btn:hover{color:var(--link)}                               /* #0B6B66 on #FFFFFF = 6.35:1 */
.acc__ic{
  flex:none;width:1.9rem;height:1.9rem;border-radius:50%;border:1.5px solid var(--hair);
  display:grid;place-items:center;position:relative;
  transition:background-color var(--dur-2) var(--ease),border-color var(--dur-2) var(--ease);
}
.acc__ic::before,.acc__ic::after{content:"";position:absolute;background:currentColor;border-radius:2px}
.acc__ic::before{width:.75rem;height:2px}
.acc__ic::after{width:2px;height:.75rem;transition:transform var(--dur-3) var(--ease)}
.acc__btn:hover .acc__ic{border-color:var(--gold);background:var(--s-gold)}
.acc__btn[aria-expanded="true"] .acc__ic::after{transform:scaleY(0)}
.acc__body{overflow:hidden;transition:height var(--dur-3) var(--ease)}
.acc__body > div{padding:0 .25rem 1.5rem}
.acc__body p{font-family:var(--serif);font-size:var(--fs-sm);line-height:1.65;color:var(--text)}  /* 13.95:1 */
.acc__body p + p{margin-top:var(--s4)}
.acc__body code{font-family:var(--mono);font-size:.9em;background:var(--s-band-deep);
  padding:.1em .35em;border-radius:3px;color:var(--text)}         /* #123222 on #F5F1E6 = 12.36:1 */


/* =====================================================================
   22. TABLES
   The wrapper scrolls horizontally on a phone. It carries tabindex and a
   role so the overflow is reachable by KEYBOARD, not by mouse-drag only.
   ===================================================================== */
.tblwrap{
  overflow-x:auto;border-radius:var(--r);box-shadow:var(--sh-1);
  background:var(--s-card);-webkit-overflow-scrolling:touch;
}
.tblwrap table{border-collapse:collapse;width:100%;min-width:32rem;font-size:var(--fs-sm)}
.tblwrap caption{
  text-align:left;padding:clamp(1rem,2vw,1.35rem) clamp(1rem,2.2vw,1.5rem) .75rem;
  font-size:var(--fs-xs);color:var(--text-mut);line-height:1.5;   /* #4A5C51 on #FFFFFF = 7.14:1 */
}
.tblwrap thead th{
  background:var(--s-band-deep);color:var(--text);font-weight:700;font-size:var(--fs-xs);
  letter-spacing:.06em;text-transform:uppercase;text-align:left;
  padding:.85rem clamp(.75rem,1.8vw,1.25rem);border-bottom:2px solid var(--hair);  /* #123222 on #F5F1E6 = 12.36:1 */
}
.tblwrap tbody th{text-align:left;font-weight:600;color:var(--text)}
.tblwrap tbody th,.tblwrap tbody td{
  padding:.85rem clamp(.75rem,1.8vw,1.25rem);border-bottom:1px solid var(--hair-soft);vertical-align:top;
}
.tblwrap tbody tr:last-child th,.tblwrap tbody tr:last-child td{border-bottom:0}
.tblwrap tbody tr:hover{background:var(--s-paper)}
.tbl__note{
  padding:clamp(.85rem,2vw,1.2rem) clamp(1rem,2.2vw,1.5rem);background:var(--s-paper);
  border-top:1px solid var(--hair);font-size:var(--fs-xs);color:var(--text-mut);line-height:1.55;
}
/* A score value with a dot. The dot is decoration — the number is printed
   beside it, so colour is never the only carrier of meaning. */
.score{display:inline-flex;align-items:center;gap:.45rem;font-variant-numeric:tabular-nums;font-weight:700;color:var(--text)}
.score i{width:.55rem;height:.55rem;border-radius:50%;background:var(--gold);flex:none}
.score--part i{background:#C9CFC9}


/* =====================================================================
   23. DEFINITION TILES
   ===================================================================== */
.deftiles{display:grid;gap:var(--s3)}
.deftile{
  background:var(--s-band);border-radius:var(--r);padding:clamp(1.1rem,2.2vw,1.5rem);
  display:grid;gap:.5rem;align-content:start;border-bottom:3px solid transparent;
  transition:border-color var(--dur-3) var(--ease),background-color var(--dur-3) var(--ease);
}
.deftile:hover{border-bottom-color:var(--gold);background:var(--s-gold)}
.deftile dt{
  font-family:var(--sans);font-size:var(--fs-sm);font-weight:700;
  color:var(--forest);letter-spacing:.01em;                      /* #0F5132 on #FBF7ED = 8.75:1 · on #FAF3DC = 8.43:1 */
}
.deftile dd{
  font-family:var(--serif);font-size:var(--fs-sm);line-height:1.6;
  color:var(--text-mut);margin:0;                                /* #4A5C51 on #FBF7ED = 6.67:1 · on #FAF3DC = 6.43:1 */
}


/* =====================================================================
   24. STEP SEQUENCES
   ===================================================================== */
.steps{counter-reset:s;display:grid;gap:var(--s4);list-style:none;padding:0}
.stepitem{
  counter-increment:s;position:relative;background:var(--s-card);border-radius:var(--r);
  box-shadow:var(--sh-1);
  padding:clamp(1.2rem,2.4vw,1.6rem) clamp(1.2rem,2.4vw,1.6rem) clamp(1.2rem,2.4vw,1.6rem) 4.25rem;
  transition:transform var(--dur-3) var(--ease),box-shadow var(--dur-3) var(--ease);
}
.stepitem:hover{transform:translateY(-2px);box-shadow:var(--sh-2)}
.stepitem::before{
  content:counter(s,decimal-leading-zero);position:absolute;left:1.2rem;top:1.15rem;
  width:2.3rem;height:2.3rem;border-radius:50%;display:grid;place-items:center;
  background:var(--forest);color:#fff;                           /* #FFFFFF on #0F5132 = 9.36:1 */
  font-family:var(--sans);font-size:.8125rem;font-weight:700;font-variant-numeric:tabular-nums;
}
.stepitem h3{
  font-family:var(--sans);font-size:1.02rem;font-weight:700;line-height:1.4;
  letter-spacing:0;color:var(--forest);                          /* #0F5132 on #FFFFFF = 9.36:1 */
}
.stepitem p{font-family:var(--serif);font-size:var(--fs-sm);line-height:1.62;color:var(--text);margin-top:.5rem}


/* =====================================================================
   25. SOURCE LISTS
   ===================================================================== */
.srclist{display:grid;gap:var(--s3);counter-reset:r;list-style:none;padding:0}
.srcitem{
  counter-increment:r;display:grid;grid-template-columns:2.25rem minmax(0,1fr);gap:var(--s3);
  padding-block:var(--s3);border-bottom:1px solid var(--hair-soft);font-size:var(--fs-sm);line-height:1.55;
}
.srcitem::before{
  content:counter(r);font-family:var(--sans);font-size:var(--fs-xs);font-weight:700;
  color:var(--gold-ink);padding-top:.2em;                        /* #7A6416 on #FFFFFF = 5.73:1 */
}
.srcitem a{font-weight:600;word-break:break-word}
.srcitem span{display:block;color:var(--text-mut);font-size:var(--fs-xs);margin-top:.2rem}  /* 7.14:1 */


/* =====================================================================
   26. CTA BLOCKS
   ===================================================================== */
.cta{display:grid;gap:var(--s5);align-items:center}
.cta h2{color:var(--on-dark)}                                    /* .cta only ever sits inside
                                                                    .sec--dark, so the surface is
                                                                    the composite: #FFFFFF on
                                                                    #0E5841 = 8.43:1 */
.cta__acts{display:flex;flex-wrap:wrap;gap:var(--s3)}
.cta__rule{width:3.5rem;height:3px;background:var(--gold);border-radius:2px}


/* =====================================================================
   27. FOOTER — ONE RESTRAINED BAND

   MEASURED. The footer rendered at 408px in TWO green bands with an empty
   grey region above them. All three came from this file:
     - the empty grey strip was .sec--dark::before, the lead-in wash above
       the membership CTA. Deleted in §7.
     - the first green band was the CTA itself, .sec--dark. It is a light
       band now, .ctaband in §35, so there is exactly ONE dark band per
       page and it is this one.
     - the 408px was this block: --s8/--s6 block padding (64 + 32), a
       --s7 margin and a --s5 pad above the base row (48 + 24), and every
       footer link inflated to a 44px tap target with .65rem of padding on
       each side, which alone added 4 x ~19px to the tallest column.

   THE NEW BOX MODEL, computed at 2294px from the real Inter metrics
   (shell inner 1328px; four columns 1.75fr 1fr 1fr 1.2fr with a 32px gap,
   so brand 435.6 | About 248.9 | Engage 248.9 | Contact 298.7):

     padding-top                                          40.0
     tallest column — brand                              144.7
       symbol 2.6rem wide, viewBox 100x93                  38.7
       gap to paragraph                                    16.0
       description: 1344.0px of Inter 400 at 15px set
       in a 435.6px column = 4 lines at 22.5               90.0
     margin above the base rule                            28.0
     base: 1px rule + 20 padding + 13px x 1.6 line         41.8
     padding-bottom                                        28.0
     ---------------------------------------------------------
     TOTAL                                                282.5px

   If that description wraps to five lines the total is 305.0px, still
   100px inside the 408px it replaces. For reference the other columns are
   About / Engage 143.6px each (15.6 heading + 12.8 margin + 4 links at
   24.3 + 3 gaps at 6) and Contact 85.0px, so the brand column governs.

   TAP TARGETS. The links are 24.3px tall, not 44px. WCAG 2.1 has no
   minimum target size at AA — 2.5.5 Target Size is AAA — and WCAG 2.2 AA
   adds 2.5.8 at 24 x 24 CSS px, which 24.3px clears. The one control here
   a reader may need in a hurry, the telephone number, is NOT relying on
   that: it keeps a 44px box of its own below.
   ===================================================================== */
.foot{
  background:var(--s-footer);                                    /* flat. No gradient: the
                                                                    band above it is light now,
                                                                    so there is no step to hide */
  color:var(--link-foot);                                        /* #D5E7DC on #0F5132 = 7.26:1 */
  padding:40px 0 28px;margin-top:0;
}
.foot__cols{display:grid;gap:var(--s6)}
.foot p{color:var(--on-dark-mut);font-size:var(--fs-sm);line-height:1.5;max-width:48ch;margin-top:16px}
                                                                 /* #C5D8CC on #0F5132 = 6.27:1 */
.foot__h{
  font-family:var(--sans);font-size:var(--fs-xs);letter-spacing:.10em;text-transform:uppercase;
  color:var(--gold-lum);font-weight:600;line-height:1.2;margin-bottom:.8rem;
}                                                                /* #E8C86A on #0F5132 = 5.75:1 */
.foot ul{display:grid;gap:.375rem;list-style:none;padding:0;margin:0;font-size:var(--fs-sm);line-height:24.3px}
/* LINK 3 — FOOTER. */
.foot a{color:var(--link-foot);text-decoration:none;font-size:var(--fs-sm)}   /* 7.26:1 */
.foot li a,.foot__ch a{display:inline-flex;align-items:center;gap:.5rem;line-height:24.3px;min-height:24px}
/* The telephone number keeps a full 44px box. It is the one control in
   this footer a reader might reach for under pressure, and it is the
   reason the old blanket 44px rule existed at all — so the exception is
   kept and the blanket is dropped. */
.foot a[href^="tel:"]{min-height:44px;padding-block:.6rem}
.foot a:hover{color:var(--link-inv);text-decoration:underline;text-underline-offset:.18em}   /* #FFFFFF on #0F5132 = 9.36:1 */
.foot__ch{display:grid;gap:.5rem;font-size:var(--fs-sm)}
.foot__ch span{display:flex;align-items:center;gap:.5rem;color:var(--on-dark-mut);line-height:24.3px}  /* 6.27:1 */
.foot__ch .ic{color:var(--gold-lum);width:1.05em;height:1.05em}  /* #E8C86A on #0F5132 = 5.75:1, non-text */
.foot__rule{height:2px;width:2.5rem;background:var(--gold);margin-top:var(--s3)}
.foot__base{
  margin-top:28px;padding:20px 0 0;border-top:1px solid var(--hair-dark);
  display:flex;flex-wrap:wrap;gap:.5rem 1.25rem;justify-content:space-between;align-items:center;
  font-size:var(--fs-xs);line-height:1.6;color:var(--on-dark-mut);   /* #C5D8CC on #0F5132 = 6.27:1 */
}
.foot__base a{font-size:var(--fs-xs);min-height:24px;display:inline-flex;align-items:center}
.foot__base nav,.foot__legal{display:flex;flex-wrap:wrap;gap:.35rem .7rem;align-items:center}
.foot__sep{color:rgba(255,255,255,.35)}   /* decorative middot, never the only cue */


/* =====================================================================
   28. FORMS
   Scoped to BOTH the Contact Form 7 output and the theme's fallback form,
   so an unconfigured form still renders as part of the site rather than as
   raw browser defaults. eocpr_form_fallback() emits .eocpr-form.
   ===================================================================== */
.wpcf7-form label,.eocpr-form label{
  display:block;font-size:var(--fs-sm);font-weight:600;margin-bottom:.3rem;
  color:var(--forest);                                           /* #0F5132 on #FFFFFF = 9.36:1 */
}
.wpcf7-form input[type=text],.wpcf7-form input[type=email],.wpcf7-form input[type=tel],
.wpcf7-form input[type=search],.wpcf7-form textarea,.wpcf7-form select,
.eocpr-form input[type=text],.eocpr-form input[type=email],.eocpr-form input[type=tel],
.eocpr-form input[type=search],.eocpr-form textarea,.eocpr-form select{
  width:100%;min-height:48px;padding:.7rem .85rem;border:1px solid var(--line-ctl);
  border-radius:var(--r-sm);background:#fff;margin-bottom:var(--s4);font-size:1rem;
  color:var(--text);                     /* text #123222 on #FFFFFF = 13.95:1 */
}                                        /* border --line-ctl #828D85 on #FFFFFF = 3.44:1
                                            (was #B9C2BB = 1.83:1, an SC 1.4.11 failure:
                                            an unfilled input's border is the only thing
                                            that says a control is there at all) */
.wpcf7-form textarea,.eocpr-form textarea{min-height:8rem}
.wpcf7-form input:focus-visible,.eocpr-form input:focus-visible,
.wpcf7-form textarea:focus-visible,.eocpr-form textarea:focus-visible{border-color:var(--forest)}
.wpcf7-form input[type=submit],.eocpr-form button{
  min-height:48px;background:var(--forest);color:#fff;border:0;padding:.8rem 1.4rem;
  border-radius:var(--r-pill);font-size:var(--fs-sm);font-weight:600;cursor:pointer;  /* 9.36:1 */
  transition:background-color var(--dur-1) var(--ease);
}
.wpcf7-form input[type=submit]:hover,
.eocpr-form button:not([disabled]):hover{background:var(--forest-hover)}   /* #FFFFFF on #0C4429 = 11.20:1 */
.eocpr-form button[disabled]{opacity:.55;cursor:not-allowed}
.eocpr-form__note{font-size:var(--fs-xs);color:var(--text-mut);margin-top:.5rem;max-width:52ch}  /* 7.14:1 */

/* Checkbox and radio groups — the membership form uses a multi-select list.
   Without this the items inherit the block label rule above and stack one
   per line at full width, which reads as ten separate questions. */
.wpcf7-form .wpcf7-checkbox,.wpcf7-form .wpcf7-radio,.eocpr-form .eocpr-choices{
  display:flex;flex-wrap:wrap;gap:.4rem 1.25rem;margin-bottom:var(--s4);
}
.wpcf7-form .wpcf7-list-item,.eocpr-form .eocpr-choices label{margin:0}
.wpcf7-form .wpcf7-list-item label,.eocpr-form .eocpr-choices label{
  display:flex;align-items:flex-start;gap:.45rem;font-weight:400;color:var(--text);
  font-size:var(--fs-sm);margin-bottom:0;cursor:pointer;min-height:44px;
}
.wpcf7-form input[type=checkbox],.wpcf7-form input[type=radio]{margin-top:.25rem;flex:0 0 auto;width:1.15rem;height:1.15rem}

/* Required-field marker and validation. CF7 renders these itself; unstyled
   they are red-on-white at default size and fail contrast against our palette. */
.wpcf7-form .wpcf7-not-valid-tip{color:#A32020;font-size:var(--fs-xs);margin:-.7rem 0 1rem}  /* #A32020 on #FFFFFF = 7.54:1 */
.wpcf7-form .wpcf7-not-valid{border-color:#A32020}
.wpcf7-form .wpcf7-response-output{                             /* border 3.44:1 on #FFFFFF —
                                                                   was #B9C2BB = 1.83:1, and
                                                                   the border is the whole
                                                                   box in the neutral state */
  margin:var(--s5) 0 0;padding:.85rem 1rem;border:1px solid var(--line-ctl);
  border-radius:var(--r-sm);font-size:var(--fs-sm);background:#fff;
}
.wpcf7-form.sent .wpcf7-response-output{border-color:var(--forest);background:#DFF0EF;color:var(--forest)}  /* #0F5132 on #DFF0EF = 7.96:1 */
.wpcf7-form.invalid .wpcf7-response-output,
.wpcf7-form.failed .wpcf7-response-output{border-color:#A32020;color:#A32020}
.wpcf7-spinner{margin-inline-start:.6rem}


/* =====================================================================
   29. OUTPUT THIS THEME DOES NOT WRITE
   Three sources of markup that no template in this theme emits and that
   therefore cannot be styled by class contract: the language switcher in
   inc/eocpr-language.php, WordPress core's pagination, and figure markup
   pasted into article content by an editor.

   WHAT USED TO BE HERE, AND WHY IT IS NOT
   This was 102 lines of LEGACY ALIASES — .container, .section,
   .section--band, .section--dark and its four descendants, .skip-link,
   .topbar__inner, .site-header, .site-header__inner, .site-brand,
   .header-cta, `.nav > .container`, .grid, .grid--2/3/4, .card__link,
   .unit--teal, .unit--gold, .site-footer and its seven descendants,
   .footer-rule and .hr — kept so that "pre-redesign templates" could be
   migrated one at a time.

   Every template has since been migrated. Scanning every class="..."
   attribute in every *.php file in the theme, inc/ and template-parts/
   produces not one of those names. They styled nothing, on any page, in
   any state, and were carried into a launch build as dead weight. Deleted.

   THREE GROUPS SURVIVED THE CULL, and are not aliases:
     .lang-switch     inc/eocpr-language.php:111 prints it. It is the
                      topbar language switcher on every single page.
     .page-numbers    WordPress core prints it — index.php:56 calls
     .nav-links       the_posts_pagination(). Deleting these would leave
                      the archive pager as unstyled browser defaults.
     .eocpr-figure    the inline-SVG figure component documented in
     wp-block-image   COMPONENTS.md for article body content, which is
                      authored in the editor, not in a template. No PHP
                      file emits it and none is expected to.
   ===================================================================== */

/* Language switcher — emitted by inc/eocpr-language.php, not by a template. */
.lang-switch{display:flex;gap:.55rem;align-items:center}
/* LINK 3 — footer/topbar. These were the eighth and ninth link colours on
   the site: white for the inactive language and gold-lum for the active
   one, decided locally here because this markup is printed by
   inc/eocpr-language.php rather than by a template. They are the same two
   colours the rest of the topbar uses now, so the switcher stops being a
   special case. The active language is marked by WEIGHT and by
   aria-current as well as by colour. */
.lang-switch a{color:var(--link-foot);text-decoration:none;padding:.6rem .2rem;min-height:44px;display:inline-flex;align-items:center}
                                                                            /* #D5E7DC on #0B3D26 = 9.53:1 */
.lang-switch a[aria-current="true"]{color:var(--link-inv);font-weight:600}  /* #FFFFFF on #0B3D26 = 12.28:1 */

/* ---------------------------------------------------------------------
   DATA FIGURES — .eocpr-figure

   Three things were wrong and are fixed here.

   1. THE FIGURE IS NOT A CARD. It used to render as a white panel floating
      on the page's off-white. It has no background, no border, no radius and
      no shadow of its own, and the SVGs it holds are transparent — no
      facecolor, no background <path>, verified by
      content/figures/_verify_responsive.py check 4. Whatever surface the
      figure is dropped on shows through, and every ink in the chart was
      measured against ALL FOUR light surfaces, not just page white:

        role                         hex       page  paper   band  band-deep
        title, bars, value labels    #0F5132   9.36   8.97   8.75   8.29
        headings, ticks, subtitle    #4A5C51   7.14   6.84   6.67   6.33
        in-chart notes               #5A6B60   5.67   5.43   5.30   5.02
        target caption, female bar   #7A641C   5.73   5.49   5.35   5.07
        "no national figure ..."     #3D4A42   9.31   8.92   8.70   8.25

      Worst case 5.02:1, against a 4.5:1 requirement. The graphical objects
      (#0F5132 and #7A641C fills) need 3:1 and clear it on every surface.
      The pale comparator fill #C9D6CE is 1.50:1 and would fail alone; it
      carries a #4A5C51 outline (6.33:1 worst case) and a hatch, and every
      bar prints its own value, so nothing rests on the fill.

   2. TWO VARIANTS, ONE SWAP. The chart was rebuilt at phone dimensions,
      which on a desktop content column reads as a mobile layout. Both a
      landscape and a portrait SVG now ship inline and one is switched off
      at 700px. It costs ~9KB of markup per figure (~2KB gzipped, the text
      is text) and it is the only way both screens get a chart drawn for
      their shape.

   3. THE CAPTION IS ONE LINE. The long source note moves into a <details>
      that works with no JavaScript.
   --------------------------------------------------------------------- */
.eocpr-figure{
  display:block;width:100%;margin-block:var(--s6);
  background:none;border:0;border-radius:0;box-shadow:none;padding:0;
}
.eocpr-figure svg{
  width:100%;height:auto;display:block;
  font-family:var(--sans);        /* the SVG carries size/weight/style only */
}
/* The swap. Portrait is the default, so the narrow case needs no query.

   WHY 768px AND NOT 700px. The brief said "around 700px", and 700 is where
   the landscape artwork is DESIGNED to sit. But the breakpoint is on the
   VIEWPORT and the floor is on the CHART, and those are not the same number:
   the article column measured on the live site steps
     viewport   320  360  414  576  768  992+
     column     267  307  361  510  690  820
   At a 700px viewport the column is still 510px, and the landscape chart
   drawn there renders its smallest type at 9.6 x 510/504 = 9.71 CSS px —
   worse than the portrait chart it replaced. 768px is the first step where
   the column (690px) is wide enough for the landscape artwork: 9.6 x
   690/504 = 13.14 CSS px, over the 13.0 floor, rising to 15.6px at 992px.
   Measured, not guessed. */
.eocpr-fig--wide{display:none}
@media (min-width:768px){
  .eocpr-fig--wide{display:block}
  .eocpr-fig--tall{display:none}
}
.eocpr-figure figcaption,figure.wp-block-image figcaption{
  margin-top:.6rem;font-size:var(--fs-sm);line-height:1.55;color:var(--text-mut);   /* 7.14:1 */
}
.eocpr-figure figcaption code{font-size:.92em;word-break:break-word}

/* The sourcing. It used to be 6.9pt burned into the chart raster, then a
   second stacked paragraph taller than the chart itself. Nothing has been
   deleted — every word is still here, one click away, selectable, and
   reachable by a screen reader.
   NOT display:flex. Chrome and Safari drop the disclosure triangle the
   moment a <summary> stops being display:list-item, which leaves a control
   with no affordance at all — the same trap documented at .dash__data
   below. min-height plus padding gets the target without touching display. */
/* THE FIGURE DATA TABLE, added 1 September 2026.

   The four editorial charts had role="img", a <title> and a substantive <desc>
   and no table of the values. The dashboard panels have both, and the August
   audit recorded the gap. A description read aloud is a sentence; a table is
   navigable — you can move cell by cell, compare two rows and go back. They are
   not substitutes for one another.

   .figtbl carries NO colours and NO type of its own on purpose. It is a marker
   on a <details> that is already .figsrc, and the table inside it is already
   .tblwrap — two components that exist and whose contrast is already measured in
   §3. A new visual treatment here would be a third way of drawing a table on a
   site that already has one.

   The only thing it adds is a ceiling. The hepatitis B series is 26 rows, one
   per year from 2000, and a disclosure that pushes the rest of the page two
   screens down is a worse reading experience than one that scrolls inside
   itself. .tblwrap already scrolls horizontally; this lets it scroll vertically
   too, and only when it needs to. */
.figtbl .tblwrap{max-height:22rem;overflow-y:auto}
.figtbl .tblwrap table{min-width:0}

.figsrc{display:block;margin-top:.15rem}
.figsrc > summary{
  min-height:44px;padding:.7rem 0;cursor:pointer;list-style-position:inside;
  font-size:var(--fs-xs);font-weight:600;color:var(--link);      /* #0B6B66 on #FFFFFF = 6.35:1 */
}                                                                /* #0B6B66 on #FBF7ED = 5.93:1 */
.figsrc > summary:hover{color:var(--link-hover)}                 /* #0F5132 on #FFFFFF = 9.36:1 */
.figsrc[open] > summary{color:var(--link-hover)}                 /* #0F5132 on #FFFFFF = 9.36:1 */
.figsrc[open] > div{
  font-size:var(--fs-xs);line-height:1.6;color:var(--text-mut);  /* #4A5C51 on #FFFFFF = 7.14:1 */
  padding-bottom:var(--s2);                                      /* #4A5C51 on #FBF7ED = 6.67:1 */
}
@media (forced-colors:active){.eocpr-figure svg{forced-color-adjust:none}}
/* Paper gets the sources open and both variants collapsed to the portrait
   one, which is the shape that fits a printed column. */
@media print{
  .figsrc > div{
    display:block !important;
    font-size:var(--fs-xs);line-height:1.6;color:var(--text-mut);   /* 7.14:1 */
  }
  .figsrc > summary{display:none}
  .eocpr-fig--wide{display:none}
  .eocpr-fig--tall{display:block}
}

/* WordPress pagination — the_posts_pagination() in index.php */
.nav-links,.page-numbers{display:flex;flex-wrap:wrap;gap:var(--s2);list-style:none;padding:0}
a.page-numbers,span.page-numbers{
  display:inline-flex;align-items:center;justify-content:center;min-width:48px;min-height:48px;
  padding:.5rem .8rem;border-radius:var(--r-sm);text-decoration:none;
  border:1px solid var(--hair);color:var(--link);                            /* #0B6B66 on #FFFFFF = 6.35:1 */
}
span.page-numbers.current{background:var(--forest);color:#fff;border-color:var(--forest)}  /* 9.36:1 */


/* =====================================================================
   30. MOTION — the reveal layer

   THE HIDING RULE IS GATED ON html.js AND NOTHING ELSE MAY UNGATE IT.
   `opacity:0` here is only safe if something is guaranteed to come along
   and add .is-in. Ungated, this rule was a single point of failure for the
   entire site: .is-in is added by assets/js/eocpr.js alone, so a 404 on
   that file, a corporate proxy stripping it, a CSP, an extension, or one
   thrown exception left the homepage as a header, a footer and twelve
   invisible blocks of white space — the hero included.

   Three independent things now have to fail before a reader sees nothing:

     1. html.js — functions.php prints an inline script at wp_head
        priority 1 that adds the class. No script running at all (JS
        disabled, blocked, unsupported) means no class, means this rule
        never matches, means every [data-reveal] block renders normally.
     2. <noscript> — functions.php also prints a <noscript><style> that
        forces opacity back to 1. Belt for the braces above: it covers the
        case where the class is somehow present but scripting is off.
     3. the watchdog — the same inline script starts a 2.5s timer and
        REMOVES html.js unless eocpr.js has set html.eocpr-ready. That is
        the case the first two do not catch: scripting is on, the inline
        script ran, and then eocpr.js 404d or threw. The page un-hides
        itself instead of staying blank.

   The hero is additionally not gated on any of this: front-page.php no
   longer marks it data-reveal at all, so the LCP element is painted by the
   first style pass under every one of these conditions.

   Everything here is switched off wholesale in §32. Reveal uses the
   standalone `translate` property, not `transform`, so a component's own
   hover transform composes with it instead of being cancelled by it. With
   IntersectionObserver missing, or motion reduced, eocpr.js adds .is-in to
   everything immediately.
   ===================================================================== */
/* ONE CODE PATH FOR REDUCED MOTION AND FOR NO JAVASCRIPT.
   The whole motion layer is now inside prefers-reduced-motion:
   no-preference AND still gated on html.js. That makes the two failure
   modes the SAME path rather than two paths that have to agree:

     JavaScript off   -> no html.js class      -> nothing hidden, nothing moves
     reduced motion   -> the query is false    -> nothing hidden, nothing moves

   Previously the hiding rule was gated on html.js only and §32 undid it
   afterwards with !important. That worked, but it meant a reader who asked
   for reduced motion still had content hidden for the length of one style
   recalculation, and it meant the two rules could drift apart. Now there
   is nothing to undo: under reduced motion this block never matches.
   §32 stays as a hard stop for anything added later.

   The three guards in functions.php are untouched and still required —
   html.js, the <noscript><style>, and the load watchdog that strips html.js
   if eocpr.js never sets html.eocpr-ready.

   `translate`, not `transform`, so a component's own hover transform
   composes with the reveal instead of being cancelled by it. */
@media (prefers-reduced-motion:no-preference){
  html.js [data-reveal]{opacity:0;translate:0 12px}
  html.js [data-reveal].is-in{
    opacity:1;translate:0 0;
    transition:opacity var(--dur-4) var(--ease) var(--rd),translate var(--dur-4) var(--ease) var(--rd);
  }
  [data-d="1"]{--rd:.07s} [data-d="2"]{--rd:.14s} [data-d="3"]{--rd:.21s}
  [data-d="4"]{--rd:.28s} [data-d="5"]{--rd:.35s} [data-d="6"]{--rd:.42s}

  /* THE CHART DRAW-IN.

     pathLength="1" on the polyline — set in eocpr_dash_plot() — normalises
     every series to a length of 1 whatever its real geometry, so these four
     rules draw all fifteen charts on the page. Measuring each line in
     JavaScript instead would mean a chart whose script had not run yet showed
     a line hidden behind a dash pattern cut for a different line.

     WHAT MOVES IS THE LINE. WHAT IS READABLE NEVER MOVES. Every point's value
     is printed as text beside it, repeated in the SVG <desc>, and repeated
     again in the real table underneath. The animation is the last thing a
     reader needs and the first thing to go: it is inside this query, so it
     never runs for reduced motion, and gated on html.js, so it never runs
     without the reveal script. In both cases the chart is simply drawn.

     The points and their labels fade in at 55% of the line's duration, so the
     numbers arrive as the line reaches them rather than all at the end. */
  html.js .dash__ind .dash__line{stroke-dasharray:1;stroke-dashoffset:1}
  html.js .dash__ind.is-in .dash__line{
    stroke-dashoffset:0;
    transition:stroke-dashoffset calc(var(--dur-4) * 1.6) var(--ease) var(--rd);
  }
  html.js .dash__ind .dash__pt,
  html.js .dash__ind .dash__ptv{opacity:0}
  html.js .dash__ind.is-in .dash__pt,
  html.js .dash__ind.is-in .dash__ptv{
    opacity:1;
    transition:opacity var(--dur-3) var(--ease) calc(var(--rd) + var(--dur-4) * .88);
  }

  /* The comparator bars grow from the left, staggered just behind the line.

     scaleX, not width. Each bar's width is an inline style written by
     eocpr_dash_compare() — `<i style="width:41.2%">` — and an inline style
     beats a stylesheet rule, so animating width here would silently do
     nothing. The rounded corner belongs to the track, which clips, so nothing
     is distorted by the scale. */
  html.js .dash__ind .dash__bar-t i{transform:scaleX(0);transform-origin:left center}
  html.js .dash__ind.is-in .dash__bar-t i{
    transform:scaleX(1);
    transition:transform calc(var(--dur-4) * 1.2) var(--ease) calc(var(--rd) + .1s);
  }

  /* Every hover in the system is a TONE change, so one transition list
     covers all of them. Nothing here moves an object; the two transform
     transitions are a 3px arrow nudge and the flyout's 5px settle. */
  .masthead,.card,.card__ic,.unit,.unit__ic,.btn,.sub,.nav__top,.foot a,.sub a,
  .brieflink,.rail a,.toc a,.topbar a,.mnav__sum,.mnav__grp ul a,.crumbs a,
  p a,li a,dd a,td a{
    transition:background-color var(--dur-1) var(--ease),color var(--dur-1) var(--ease),
      border-color var(--dur-1) var(--ease),box-shadow var(--dur-1) var(--ease),
      opacity var(--dur-2) var(--ease),transform var(--dur-2) var(--ease),
      visibility var(--dur-2) var(--ease);
  }
  .btn__ar,.card__go .ic,.card__go svg{transition:transform var(--dur-2) var(--ease)}

  /* The hero word rotator's cross-fade. No bounce, no slide-in from the
     side: opacity plus a quarter-em rise, which is a fade with a direction
     rather than a movement. Width is reserved by .rot__sizer (§35), so
     nothing around it reflows as the word changes. */
  .rot__w{transition:opacity .35s var(--ease),transform .35s var(--ease)}
  .rot.is-out .rot__w{opacity:0;transform:translateY(-.28em)}

  html{scroll-behavior:smooth}
}


/* =====================================================================
   31. RESPONSIVE — mobile-first. Everything above is the phone layout;
   these are the step-ups. 360px is the design target, not an afterthought.
   ===================================================================== */

/* THE html:not(.js) NAVIGATION FALLBACK IS GONE, AND THAT IS AN IMPROVEMENT
   — 40 lines of it. It existed because the mobile menu's open state lived
   only in JavaScript: .nav__list was display:none, the panel was
   visibility:hidden until a script added .is-open, and a phone with the
   script blocked had NO navigation at all. So the fallback rebuilt a
   second, different, stacked menu for that case.

   The menu is a <details> now (§10). The browser opens and closes it with
   no script, at every breakpoint, in one markup path. There is nothing
   left to fall back FROM, so there is nothing to fall back TO. #navtoggle,
   #scrim, #mnavclose and .navtoggle no longer exist in header.php either.

   What must stay true, and is checked below: the six-item list and the
   <details> summary are never both visible, and never both hidden. */

@media (min-width:560px){
  .cards--3,.cards--4{grid-template-columns:repeat(2,1fr)}
}
@media (min-width:44em){
  .cards--row{grid-template-columns:1fr}
  .well dl{grid-template-columns:repeat(2,minmax(0,1fr))}
  .foot__cols{grid-template-columns:1fr 1fr}
}
@media (min-width:600px){
  .kfacts,.deftiles{grid-template-columns:repeat(2,1fr)}
  .stats{grid-template-columns:repeat(3,1fr);gap:var(--s6)}
  .stats .stat + .stat{border-left:1px solid var(--hair-soft);padding-left:var(--s6)}
}
@media (min-width:700px){
  .cards--stagger{grid-template-columns:repeat(2,1fr)}
  .cards--stagger > :first-child{grid-column:span 2}
}
/* 62em — the wide screen starts being used ACROSS rather than down. This
   is the breakpoint that answers "looks like a book or mobile version on a
   computer screen": the hero gains its plate, the risk section puts its
   cards beside each other, and the footer resolves to four columns. */
@media (min-width:62em){
  .hero__grid{grid-template-columns:minmax(0,1.04fr) minmax(0,.96fr);align-items:stretch}
  .cards--4{grid-template-columns:repeat(4,1fr)}
  .cards--3{grid-template-columns:repeat(3,1fr)}
  .cards--row{grid-template-columns:repeat(2,minmax(0,1fr))}
  /* inside the asymmetric split the pillar cards stay 2 x 2 */
  .split .cards--4{grid-template-columns:repeat(2,1fr)}
  .split{grid-template-columns:minmax(0,22rem) minmax(0,1fr);gap:clamp(2rem,5vw,5rem);align-items:start}
  /* `auto`, not a fixed 2.5rem: this row is rendered TWO ways. front-page.php
     puts a 2.5rem .unit__ic in the first cell; archive-eocpr_position.php —
     which this pass may not edit — puts a .unit__k numeral there. `auto`
     sizes the track to whichever is wider and keeps every row aligned. */
  .unit{grid-template-columns:auto minmax(0,24rem) minmax(0,1fr);align-items:start}
  .cta{grid-template-columns:minmax(0,1fr) auto;gap:var(--s7)}
  .ctaband__in{grid-template-columns:minmax(0,1fr) auto;gap:var(--s8)}
  .riskgrid{grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr);gap:var(--s7);align-items:start}
  .riskgrid .cards{gap:var(--s4)}
  .foot__cols{grid-template-columns:1.75fr 1fr 1fr 1.2fr;gap:var(--s6)}
  .well dl{grid-template-columns:repeat(3,minmax(0,1fr))}
  .deftiles{grid-template-columns:repeat(3,1fr)}
  .statpanel{margin-top:1.5rem}
  /* margin, not transform — a transform here would be cancelled by the
     card's own hover transform */
  .cards--offset > :nth-child(even){margin-top:2rem}
}

/* 69em — the six-item bar first fits honestly. Above it the <details>
   panel is removed and the row is shown; below it the reverse. The two are
   never both present and never both absent. See the fit arithmetic in §10. */
@media (min-width:69em){
  .nav{display:flex}
  .mnav{display:none}
  .masthead__in{min-height:4.75rem}
  .brandmark{--sym:2.6rem}
}

/* 78em — the contents rail earns its own column and becomes sticky. */
@media (min-width:78em){
  .cards--stagger{grid-template-columns:repeat(3,1fr)}
  .cards--stagger > :first-child{grid-column:span 1;grid-row:span 2}
  .artgrid,.art__grid{grid-template-columns:260px minmax(0,1fr);gap:var(--s7);align-items:start}
  /* the rail sticks; the grid parent is tall, so it has room to travel */
  .rail,.toc__m{position:sticky;top:6.75rem;align-self:start;max-height:calc(100vh - 9rem);overflow:auto;padding-right:.25rem}
  .rail__m{border:0;padding:0}
  .rail__m > summary,.toc__m > summary{display:none}
  .toc__m .toc{margin-top:0}
  .kfacts--3{grid-template-columns:repeat(3,1fr)}
}

/* 82em — the membership button rejoins the bar. Below this the six items
   fit and the button does not, so it is withheld rather than wrapped. */
@media (min-width:82em){
  .nav > .btn,.masthead__cta{display:inline-flex}
}

/* 88em — the outer track of the editorial grid first measures >=48px, so
   the position numeral has somewhere honest to sit. Below this it is
   simply not drawn rather than being crushed against the text column. */
@media (min-width:88em){
  .pos__n{display:block}
}

/* --- SMALL PHONE ------------------------------------------------------
   At 360px the full horizontal lockup plus a menu button does not fit at a
   legible wordmark size. The mark stands alone; the accessible name on the
   link still carries the full organisation name, and the footer keeps the
   complete lockup where there is room for it. */
@media (max-width:479px){
  .masthead .brandmark{--sym:2.35rem}
  .masthead .brandmark__words{display:none}
  .masthead__in{gap:var(--s3);min-height:64px}
  .mnav__sum{padding:.55rem .7rem}
  .topbar__in{font-size:.75rem}
  /* the step number moves above the text rather than squeezing it */
  .stepitem{padding:3.5rem 1.15rem 1.25rem}
  .stepitem::before{top:1.15rem;left:1.15rem}
}


/* =====================================================================
   32. REDUCED MOTION — nothing animates. Not quite the same claim.

   WHAT IS TRUE: every transition, animation and smooth scroll is reduced
   to zero duration, and revealed content is shown at full opacity
   immediately. Nothing on the site moves. assets/js/eocpr.js reads the
   same media query independently and never starts an animation, so a JS
   failure cannot leave motion running and a CSS failure cannot either.
   Belt and braces, deliberately.

   WHAT THIS COMMENT USED TO CLAIM, WRONGLY: that "every transform" is
   removed. It is not, and it should not be — a transform is geometry, and
   only its ANIMATION is motion. The four hover-lift transforms are removed
   outright below because their whole purpose was the movement. Eight
   others are left in place and simply snap between states at zero
   duration, which is the correct behaviour:

     1. .prose a[target=_blank]::after  translateY  — optical alignment of
                                                     the outbound arrow;
                                                     static, never animated
     2. .nav__list a::after             scaleX      — underline, snaps in
     3. .navtoggle i (x2)               translate/rotate — bars snap to an X
     4. .btn:active                     translateY(0) — already a no-op
     5. .toc__m > summary::after        rotate      — chevron snaps over
     6. .dlist / list markers           rotate      — static diamond shape
     7. .acc__btn .acc__ic::after       scaleY      — plus snaps to minus
     8. .mnav / .mnav.is-open           translateX  — panel snaps open

   Removing those would not reduce motion; it would break the affordance
   and leave a reader unable to tell an open panel from a closed one.

   NOT HERE ANY MORE: this block used to also set
   `.cards--offset > :nth-child(even){margin-top:0}`. That is a layout
   change, not a motion change. prefers-reduced-motion is a request about
   movement, and answering it by silently re-flowing the page into a
   different composition is out of scope for the query.
   ===================================================================== */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    animation-delay:0ms !important;
    transition-duration:.001ms !important;
    transition-delay:0ms !important;
    scroll-behavior:auto !important;
  }
  html{scroll-behavior:auto !important}
  [data-reveal]{opacity:1 !important;translate:none !important;transform:none !important}
  .card:hover,.btn:hover,.kfact:hover,.stepitem:hover{transform:none}
  .brandmark:hover .brandmark__sym{transform:none}
  .btn:hover .btn__ar,.card:hover .card__go svg,a.card:hover .card__go .ic{transform:none}
  .acc__body{transition:none}
  /* The rotator holds whichever word is on screen. The sentence around it
     is complete either way, so stopping the swap costs the reader nothing.
     eocpr.js reads the same query and never starts the timer, so this is
     belt for those braces, not the only stop. */
  .rot.is-out .rot__w{opacity:1 !important;transform:none !important}
}


/* =====================================================================
   33. PRINT — the citations must survive paper
   ===================================================================== */
@media print{
  .topbar,.masthead,.nav,.mnav,.scrim,.toc,.toc__m,
  .sec--dark,.foot,.skip{display:none}
  .flow > .wide,.flow > .full,.prose > .wide,.prose > .full{grid-column:text}
  .acc__body{display:block !important;height:auto !important}
  .acc__body[hidden]{display:block !important}
  .tblwrap{overflow:visible;box-shadow:none}
  .card,.kfact,.stepitem,.stats,.figframe{box-shadow:none;border:1px solid #999}
  a[href^="http"]::after{content:" (" attr(href) ")";font-size:.8em;word-break:break-all}
}

/* Below 1024px the <summary> already carries this label word for word, so the
   heading would appear twice when the disclosure is open. Visually hidden, not
   removed — aria-labelledby="toc-hd" still names the nav from it. */
@media (max-width:1023.98px){
  .toc__wrap .toc__hd{
    position:absolute;width:1px;height:1px;overflow:hidden;
    clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;
  }
}


/* =====================================================================
   34. DATA DASHBOARD — template-dashboard.php

   WHAT THIS REPLACES. dashboard/dashboard.css declared its own :root block
   with its own eleven variables — --forest, --teal, --deep, --gold, --ivory,
   --ink, --muted, --rule, --page and two font stacks — duplicating this file
   under different names, and a separate six-colour domain palette lived in
   dashboard.js. Four of those six (#1B5E8A #8A4B00 #5B2440 #3D5A2B) existed
   in no brand document. That is a second colour system, which COMPONENTS.md
   ground rule 2 forbids, and it would have drifted from this one the first
   time either was touched. NOTHING BELOW DECLARES A COLOUR. Every value is a
   token from §2, and the domain a figure belongs to is now carried by the
   section heading it sits under — text, which survives greyscale, forced
   colours and a screen reader.

   CONTRAST — every pair this section introduces, measured, not estimated.

     TEXT                                                          ratio
     --forest    #0F5132  on  --s-card    #FFFFFF   .dash__ind h3   9.36:1
     --forest    #0F5132  on  --s-card    #FFFFFF   .dash__val      9.36:1
     --text      #123222  on  --s-card    #FFFFFF   .dash__note    13.95:1
     --text-mut  #4A5C51  on  --s-card    #FFFFFF   .dash__meta     7.14:1
     --text-mut  #4A5C51  on  --s-card    #FFFFFF   .dash__cmp-h    7.14:1
     --text-mut  #4A5C51  on  --s-card    #FFFFFF   .dash__ptv      7.14:1
     --text-mut  #4A5C51  on  --s-card    #FFFFFF   .dash__tick     7.14:1
     --text-mut  #4A5C51  on  --s-paper   #FCFAF4   .dash__src      6.84:1
     --link      #0B6B66  on  --s-paper   #FCFAF4   .dash__src a    6.08:1
     --link      #0B6B66  on  --s-card    #FFFFFF   .dash__data     6.35:1
     --link      #0B6B66  on  --s-teal    #E8F2F1   badge, live     5.56:1
     --gold-ink  #7A6416  on  --s-gold    #FAF3DC   badge, evidence 5.17:1
     --gold-ink  #7A6416  on  --s-card    #FFFFFF   .dash__tlabel   5.73:1
     --text      #123222  on  --s-card    #FFFFFF   .dash__chip     13.95:1
     --on-dark   #FFFFFF  on  --forest    #0F5132   chip, pressed    9.36:1
     --text      #123222  on  --s-band    #FBF7ED   .dash__status  13.04:1
     --text      #123222  on  --s-gold    #FAF3DC   status, warn   12.57:1
     --forest    #0F5132  on  --s-paper   #FCFAF4   .dash__lead-v   8.94:1
     --text      #123222  on  --s-paper   #FCFAF4   .dash__lead-l  13.32:1
     --text-mut  #4A5C51  on  --s-paper   #FCFAF4   .dash__lead-m   6.84:1
     --text-mut  #4A5C51  on  --s-band    #FBF7ED   .dash__sources  6.67:1
     --forest    #0F5132  on  --s-band    #FBF7ED   .dash__method h2 8.75:1
     --text      #123222  on  --s-band    #FBF7ED   .dash__method p 13.04:1
     --text      #123222  on  --s-card    #FFFFFF   .dash__bar-n   13.95:1

     NON-TEXT — WCAG 1.4.11 needs 3:1 for a control boundary or for a
     graphical object a reader must see to understand the content.
     --line-ctl  #828D85  on  --s-card    #FFFFFF   chip border     3.44:1
     --line-ctl  #828D85  on  --s-card    #FFFFFF   .dash__axis     3.44:1
     --line-ctl  #828D85  on  --s-band-deep #F5F1E6 comparison bar  3.05:1
     --deep-teal #0B6B66  on  --s-card    #FFFFFF   .dash__line     6.35:1
     --deep-teal #0B6B66  on  --s-band-deep #F5F1E6 Ethiopia bar    5.62:1
     --gold-ink  #7A6416  on  --s-card    #FFFFFF   .dash__target   5.73:1

     THE TARGET LINE IS --gold-ink, NOT --gold. The brand gold #D4AF37 is
     2.10:1 on white. A dashed line a reader has to see in order to read the
     chart is a graphical object under 1.4.11 and 2.10:1 fails it outright,
     so the target rule is drawn in the darkened gold at 5.73:1. The target
     value is ALSO printed as text in .dash__meta and again in the <desc>, so
     colour is not the only thing carrying it either way.

     --hair #E6E2D6 is 1.30:1 on white and is used for .dash__grid. That is
     deliberate and it is legal: the gridlines are decoration. Every value is
     printed beside its own point, restated in the SVG <desc> and restated
     again in the <table> below the chart, so no reader has to measure a
     point against a gridline to obtain a number.

   MOTION. Nothing in this section has a transition or an animation. Figures
   on a page about cancer mortality do not move, and §32 therefore has
   nothing here to switch off — prefers-reduced-motion is satisfied by there
   being no motion in the first place rather than by a query that removes it.
   ===================================================================== */

.dash{padding-top:var(--s7)}

/* THE HEADLINE BAND — the four figures that answer "how big is this, and how
   much of it are we catching", before any filter or control.

   It replaces the live/evidence key that used to open the page. A key asks a
   reader to learn a rule before they have seen a number; these are the numbers.
   Nothing here holds a value of its own — each tile names one indicator already
   in the set below and prints the same resolved figure, so the band and the
   panel cannot disagree.

   No cards, no boxes. Hairline rules between columns, which is how a broadsheet
   sets a summary table and is quieter than four more bordered tiles above a
   page of bordered tiles. */
.dash__lead{
  display:grid;gap:0;margin:0 0 var(--s6);
  border-block:1px solid var(--hair);
  grid-template-columns:1fr;
}
.dash__lead-i{
  padding:var(--s4) 0;
  display:flex;flex-direction:column;gap:.15rem;
}
.dash__lead-i + .dash__lead-i{border-top:1px solid var(--hair-soft)}
/* The headline figure takes its own domain's ink, which is the first place a
   reader meets the colour — before the chips, before the section rules. The
   label under it says which domain in words. */
.dash__lead-v{
  margin:0;font-family:var(--serif);font-weight:700;line-height:1;
  font-size:clamp(2rem,1.4rem + 2.2vw,3.1rem);
  color:var(--dom);font-variant-numeric:tabular-nums;             /* 5.73:1 worst case */
}
.dash__lead-u{font-size:.45em;font-weight:600;margin-left:.08em}
.dash__lead-l{
  margin:0;font-size:var(--fs-sm);font-weight:600;color:var(--text);  /* 13.95:1 */
}
.dash__lead-m{margin:0;font-size:var(--fs-xs);color:var(--text-mut)}  /* 7.14:1 */
.dash__lead-i a{color:inherit;text-decoration:none}
.dash__lead-i a:hover .dash__lead-l,
.dash__lead-i a:focus-visible .dash__lead-l{text-decoration:underline}

/* THE SUMMARY BAND DOES NOT ANIMATE, AND THAT IS THE SECOND DECISION HERE.

   1 September 2026, first attempt. The count-up on the four headline figures had
   to go — it tweened the digits, so the band spent 700ms asserting figures
   nobody published: "20,533 estimated new cancer cases, 2024" where the value is
   79,239. The reasoning is in the header of assets/js/eocpr-dashboard.js and it
   still stands.

   The replacement was a fade-and-rise on the tile: hide with opacity 0, let an
   IntersectionObserver add .is-shown. Correct in principle, wrong here, and it
   shipped before anyone looked at the page.

   THE SUMMARY BAND IS ABOVE THE FOLD. Hiding it means the dashboard's first
   painted frame is an empty rule with a gap under it, and the numbers arrive
   only once a deferred script has run and an observer has fired. That is a
   visible flash of nothing at the top of the page — and §35 of this file
   already records the same lesson, which is why the LCP element is deliberately
   not marked data-reveal.

   It also reintroduced the failure the three-layer defence exists to prevent: a
   script that loads, sets html.js, then throws before revealLeads() leaves the
   band permanently invisible. Reveal-on-scroll is for content BELOW the fold,
   where nothing is hidden that a reader was already looking at.

   So there is no rule here. The band paints with its correct values in the first
   frame and never moves. The charts still draw in and the comparator bars still
   grow, further down the page, where a reveal costs nothing.

   Motion that risks showing a reader nothing is not better than no motion, on a
   page whose job is to show numbers. */

/* Two up, then four. The rules between tiles are drawn by the tile itself, so
   the pattern is stated once per breakpoint and never as an override of the
   breakpoint below it: every rule is reset to 0 at the top of each block and
   then set on the tiles that need it. */
@media (min-width:34em){
  .dash__lead{grid-template-columns:repeat(2,minmax(0,1fr));column-gap:var(--s6)}
  .dash__lead-i{border-top:0}
  .dash__lead-i:nth-child(n+3){border-top:1px solid var(--hair-soft)}
  .dash__lead-i:nth-child(even){border-left:1px solid var(--hair-soft);padding-left:var(--s6)}
}
@media (min-width:62em){
  .dash__lead{grid-template-columns:repeat(4,minmax(0,1fr));column-gap:var(--s5)}
  .dash__lead-i{border-top:0;border-left:0;padding-left:0}
  .dash__lead-i + .dash__lead-i{border-left:1px solid var(--hair-soft);padding-left:var(--s5)}
}

/* The live region. Collapsed while empty so it occupies nothing and reads as
   nothing, but present in the DOM from first paint — a region injected at the
   same moment as its text is not announced by most screen readers. */
.dash__status{
  margin:var(--s4) 0 0;padding:.7rem 1rem;border-radius:var(--r-sm);
  background:var(--s-band);border-left:3px solid var(--line-ctl);
  font-size:var(--fs-sm);color:var(--text);                      /* #123222 on #FBF7ED = 13.04:1 */
}
.dash__status:empty{display:none}
.dash__status--warn{background:var(--s-gold);border-left-color:var(--gold-ink)}  /* #123222 on #FAF3DC = 12.57:1 */

/* Controls. Hidden in the markup, revealed by the script — a filter that
   cannot filter is worse than no filter. */
.dash__controls{
  display:flex;flex-wrap:wrap;gap:var(--s3);align-items:center;
  margin-top:var(--s5);padding-bottom:var(--s4);border-bottom:1px solid var(--hair);
}
.dash__controls[hidden]{display:none}
.dash__filters{display:flex;flex-wrap:wrap;gap:var(--s2)}
.dash__chip,.dash__export,.dash__refresh{
  font-family:var(--sans);font-size:var(--fs-sm);line-height:1.2;
  min-height:48px;padding:.5rem 1.05rem;border-radius:var(--r-pill);cursor:pointer;
  background:var(--s-card);color:var(--text);                    /* #123222 on #FFFFFF = 13.95:1 */
  border:1px solid var(--line-ctl);                              /* #828D85 on #FFFFFF = 3.44:1 — 1.4.11 */
  display:inline-flex;align-items:center;
}
.dash__export{border-radius:var(--r-sm);margin-left:auto}
/* The refresh control sits with the export, before it, and is only rendered
   for an editor — see the note in template-dashboard.php. It takes the same
   shape as the export rather than a shape of its own, because it is the same
   kind of thing: an action on the whole set, not a filter within it. */
.dash__refresh{border-radius:var(--r-sm);margin-left:auto}
.dash__refresh + .dash__export{margin-left:var(--s2)}
.dash__refresh[disabled]{opacity:.55;cursor:progress}
.dash__chip:hover,.dash__export:hover,.dash__refresh:not([disabled]):hover{background:var(--s-band)}

/* A filter chip carries its domain's colour as a disc before the label, so the
   colour a reader learns on the chip is the colour they then see on the section
   rule and the chart. The label is still the label; the disc is aria-hidden by
   virtue of being a pseudo-element and carries nothing of its own.

   Not on the All chip: it has no domain, so it falls through to --dom-none,
   which is the body ink — a near-black dot there would read as a seventh
   domain rather than as the absence of one. */
.dash__chip[data-filter]:not([data-filter="all"])::before{
  content:"";width:.6rem;height:.6rem;border-radius:50%;flex:none;
  margin-right:.5rem;background:var(--dom);
}

/* Pressed, the chip fills with its own domain ink. Every one of the six clears
   4.5:1 against --on-dark; the weakest is finance at 5.73:1. Weight changes as
   well as colour, and aria-pressed carries the state for anyone not seeing
   either. */
.dash__chip[aria-pressed="true"]{
  background:var(--dom);color:var(--on-dark);border-color:var(--dom);font-weight:600;
}
.dash__chip[aria-pressed="true"]::before{background:var(--on-dark)}

/* One card per indicator. Single column on a phone, two from 900px: the
   chart is 420 units wide and below about 600px of rendered width its tick
   labels start to collide. */
/* ---------------------------------------------------------------------
   DOMAIN COLOUR, BOUND ONCE.

   Every element that needs a domain colour is inside a [data-domain] section
   or carries one itself, so the ink and its tint are resolved here, once per
   domain, into two local custom properties. Everything downstream reads
   var(--dom) and var(--dom-t) and never names a colour.

   The consequence worth having: adding a seventh domain is one pair of lines
   in §2 and one pair here, and nothing else in the file changes. A domain the
   owner creates in wp-admin with no colour of its own falls through to
   --dom-none, which is the body ink — neutral, not broken.                */
.dash__dom,.dash__ind,.dash__chip,.dash__lead-i{--dom:var(--dom-none);--dom-t:var(--dom-none-t)}
[data-domain="prevent"],.dash__chip[data-filter="prevent"]{--dom:var(--dom-prevent);--dom-t:var(--dom-prevent-t)}
[data-domain="detect"], .dash__chip[data-filter="detect"] {--dom:var(--dom-detect); --dom-t:var(--dom-detect-t)}
[data-domain="treat"],  .dash__chip[data-filter="treat"]  {--dom:var(--dom-treat);  --dom-t:var(--dom-treat-t)}
[data-domain="finance"],.dash__chip[data-filter="finance"]{--dom:var(--dom-finance);--dom-t:var(--dom-finance-t)}
[data-domain="burden"], .dash__chip[data-filter="burden"] {--dom:var(--dom-burden); --dom-t:var(--dom-burden-t)}
[data-domain="policy"], .dash__chip[data-filter="policy"] {--dom:var(--dom-policy); --dom-t:var(--dom-policy-t)}

.dash__dom{margin-top:var(--s8)}
.dash__dom[hidden]{display:none}

/* The section heading is the primary carrier of the domain — it is text, it is
   read aloud, it survives greyscale. The rule under it is the colour, and it
   is 3px so it reads as a deliberate mark rather than a border that failed. */
.dash__dom > h2{
  color:var(--dom);                                  /* 5.73:1 worst case, finance */
  padding-bottom:var(--s2);border-bottom:3px solid var(--dom);
}
.dash__grid{display:grid;gap:var(--s5);margin-top:var(--s5)}

/* The card takes its domain on the top edge only. Six fully coloured borders
   on one screen would be six competing frames; a 3px cap groups the cards
   under their heading without shouting. It is declared after the neutral
   border on purpose — border-top has to win, and specificity is equal. */
.dash__ind{
  position:relative;background:var(--s-card);border:1px solid var(--hair);
  border-top:3px solid var(--dom);
  border-radius:var(--r);padding:clamp(1.1rem,2.4vw,1.6rem);
  display:flex;flex-direction:column;gap:var(--s3);
}
.dash__ind h3{margin:0;color:var(--heading)}                      /* #0F5132 on #FFFFFF = 9.36:1 */

/* HOW THE FIGURE GOT HERE. Text first, colour second.

   It used to be absolutely positioned in the top right corner, which forced
   7rem of permanent padding onto every card heading to stop the two colliding —
   a reserved gap that stayed there whether or not the title needed the room. It
   also could not survive the badge text growing, and it has just grown: "Live"
   and "Evidence" became "Auto-updated" and "Published evidence" because the
   short words claimed things the site cannot claim.

   In normal flow above the heading it takes the width it needs, wraps if it has
   to, and the heading gets the whole card back. */
.dash__badge{
  align-self:flex-start;margin:0;
  font-size:var(--fs-xs);font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  padding:.2rem .55rem;border-radius:var(--r-sm);
}
.dash__badge--live{background:var(--s-teal);color:var(--link)}        /* #0B6B66 on #E8F2F1 = 5.56:1 */
.dash__badge--evid{background:var(--s-gold);color:var(--gold-ink)}    /* #7A6416 on #FAF3DC = 5.17:1 */

.dash__val{
  margin:0;font-family:var(--serif);font-weight:600;line-height:1.02;
  font-size:clamp(2.1rem,1.5rem + 2.4vw,3.1rem);
  color:var(--heading);                                          /* #0F5132 on #FFFFFF = 9.36:1 */
}
.dash__val--txt{font-size:clamp(1.35rem,1.1rem + .9vw,1.7rem);line-height:1.2}
.dash__u{font-size:.5em;font-weight:600;margin-left:.06em}
.dash__val--txt .dash__u{font-size:.8em}
.dash__meta{margin:0;font-size:var(--fs-xs);color:var(--text-mut)}    /* #4A5C51 on #FFFFFF = 7.14:1 */
.dash__note{
  margin:0;font-family:var(--serif);font-size:var(--fs-sm);line-height:1.6;
  color:var(--text);                                             /* #123222 on #FFFFFF = 13.95:1 */
}
.dash__note--thin{font-size:var(--fs-xs);color:var(--text-mut)}       /* 7.14:1 */

/* The chart. Inline SVG, no library, no CDN. */
.dash__plot:empty{display:none}
.dash__svg{width:100%;height:auto;display:block}
.dash__gridline{stroke:var(--hair);stroke-width:1}                /* decoration — see the note above */
.dash__axis{stroke:var(--line-ctl);stroke-width:1}                /* 3.44:1 */
/* The series takes the domain ink. Worst case in the set is finance at 5.73:1
   against the card, well past the 3:1 SC 1.4.11 needs for a graphic. */
.dash__line{fill:none;stroke:var(--dom);stroke-width:2;stroke-linejoin:round;stroke-linecap:round}
.dash__pt{fill:var(--dom)}

/* The chart draw-in lives in §30, inside prefers-reduced-motion:no-preference
   and gated on html.js, because that is the one code path the whole motion
   layer uses. Putting it here instead would have made a second path that has
   to agree with the first, which is the exact failure §30 was rewritten to
   remove. Search for dash__line in §30. */
.dash__target{stroke:var(--gold-ink);stroke-width:1.5;stroke-dasharray:5 4}  /* 5.73:1 */
.dash__tlabel{fill:var(--gold-ink);font-family:var(--sans);font-size:10px;font-weight:600}  /* 5.73:1 */
.dash__tick{fill:var(--text-mut);font-family:var(--sans);font-size:10px}     /* 7.14:1 */
.dash__ptv{fill:var(--text-mut);font-family:var(--sans);font-size:10px;font-weight:600}     /* 7.14:1 */
@media (forced-colors:active){.dash__svg{forced-color-adjust:none}}

/* Comparison rows. The bar is decoration and is aria-hidden; the country and
   the number are printed on every row, so nothing depends on seeing it. */
.dash__cmp{border-top:1px solid var(--hair-soft);padding-top:var(--s3)}
.dash__cmp-h{margin:0 0 var(--s2);font-size:var(--fs-xs);color:var(--text-mut)}  /* 7.14:1 */
.dash__bars{list-style:none;margin:0;padding:0;display:grid;gap:.35rem}
.dash__bar{
  display:grid;grid-template-columns:5.5rem 1fr 3.5rem;gap:var(--s3);align-items:center;
  font-size:var(--fs-xs);color:var(--text);                      /* #123222 on #FFFFFF = 13.95:1 */
}
.dash__bar--self .dash__bar-n,.dash__bar--self .dash__bar-v{font-weight:700}
.dash__bar-v{text-align:right;font-variant-numeric:tabular-nums}
.dash__bar-t{display:block;height:9px;border-radius:3px;background:var(--s-band-deep);overflow:hidden}
.dash__bar-t i{display:block;height:100%;background:var(--line-ctl)}          /* #828D85 on #F5F1E6 = 3.05:1 */
/* Ethiopia's own bar takes the domain ink; the comparators stay neutral grey,
   so which bar is the subject is carried by weight and colour together and by
   the row label, which is text. */
.dash__bar--self .dash__bar-t i{background:var(--dom)}                        /* 5.17:1 worst case */

/* The text alternative. A real table, in a disclosure so it does not double
   the length of the page, but always in the markup and never behind JS. */
/* NOT display:flex. Chrome and Safari drop the disclosure triangle the moment
   a <summary> stops being display:list-item, which leaves a control with no
   affordance at all. min-height plus padding gets the 48px target without
   touching display. */
.dash__data > summary{
  min-height:48px;padding:.8rem 0;cursor:pointer;list-style-position:inside;
  font-size:var(--fs-sm);font-weight:600;color:var(--link);      /* #0B6B66 on #FFFFFF = 6.35:1 */
}
.dash__data .tblwrap{margin-top:var(--s2)}
.dash__data .tblwrap table{min-width:0}

.dash__src{
  margin:0;padding-top:var(--s3);border-top:1px solid var(--hair-soft);
  font-size:var(--fs-xs);line-height:1.55;color:var(--text-mut); /* #4A5C51 on #FFFFFF = 7.14:1 */
}
.dash__src code{font-family:var(--mono);font-size:.92em;word-break:break-word}
/* Flagged when the feed could not be reached. The flag is a text status in
   #dash-status as well; this is the visual echo, not the message. */
.dash__ind--stale{border-color:var(--line-ctl)}

.dash__method{
  margin-top:var(--s8);background:var(--s-band);border-radius:var(--r);
  padding:clamp(1.25rem,3vw,2rem);
}
.dash__method h2{margin:0 0 var(--s3);color:var(--heading)}       /* #0F5132 on #FBF7ED = 8.75:1 */
.dash__method p{
  font-family:var(--serif);font-size:var(--fs-sm);line-height:1.65;
  color:var(--text);max-width:var(--measure);                    /* #123222 on #FBF7ED = 13.04:1 */
}
.dash__method p + p{margin-top:var(--s4)}
.dash__method .dash__sources{font-size:var(--fs-xs);color:var(--text-mut)}  /* #4A5C51 on #FBF7ED = 6.67:1 */

/* The method note reads as prose, so its paragraphs keep --measure. On a wide
   screen a single 68ch column inside a 1680px band left roughly 770px of empty
   cream to its right — the emptiest thing on the page sitting under the
   densest. Two columns at 82em fill the band and each paragraph keeps a
   readable measure; the source lines stay full width underneath, because they
   are a list and not prose. */
@media (min-width:82em){
  .dash__method{
    display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
    column-gap:clamp(2rem,4vw,3.5rem);row-gap:var(--s4);
    align-items:start;
  }
  .dash__method h2{grid-column:1 / -1;margin-bottom:0}
  .dash__method p + p{margin-top:0}
  .dash__method .dash__sources{grid-column:1 / -1;max-width:none}
  .dash__method .dash__sources + .dash__sources{margin-top:calc(var(--s3) * -1)}
}

/* THE GRID.

   Two columns used to be the widest this ever went, on a page constrained to
   1440px. At 1440 that gave a card about 650px wide holding a number, a note of
   twenty words and a chart 200px tall — a card with more air in it than
   content, and on a 2294px screen the whole page sat in the middle 1440 with
   839px of empty paper either side.

   The page now uses the full shell and the grid goes to three at 82em. A
   three-up card lands around 520px, which is the width the sparkline and the
   comparator bars were drawn for. */
@media (min-width:56.25em){
  .dash__grid{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (min-width:82em){
  .dash__grid{grid-template-columns:repeat(3,minmax(0,1fr))}
}

/* Print. §33 already strips the site chrome. The dashboard's own controls do
   nothing on paper, and the data tables have to survive it — a printed page
   of charts with the numbers locked inside a closed disclosure is exactly the
   failure §33 exists to prevent. Best effort: not every engine honours a
   forced-open <details>, which is why the SVG <desc> and the printed value on
   every point are the guarantee and this is the convenience. */
@media print{
  .dash__controls,.dash__status{display:none}
  .dash__data > summary{display:none}
  .dash__data,.dash__data > *{display:block}
  .dash__ind{break-inside:avoid;border:1px solid #999}
}


/* =====================================================================
   35. DIRECTION 3 — THE MERGE

   The owner chose design-v2/3-merged. Its base is 2-alive — the fonts,
   the motion grammar, the icon set, the word rotator, the hero plate, the
   six-item nav and the short footer. From the earlier A-editorial
   direction it takes ONLY three things: the deep-page editorial grid
   (numbered sticky rail + reading column + objects that break out to
   wider tracks), the figure frame, and colour restraint.

   COLOUR RESTRAINT, stated as a rule rather than a mood: brand colour
   appears as rules, marks, numerals and small surfaces. Gold is never
   text — --gold-ink is its text form. There is exactly ONE dark band per
   page and it is the footer; the hero plate is a dark OBJECT, not a band.

   This section is appended rather than woven in, so every "§7", "§30",
   "§31" reference already written into this file, into COMPONENTS.md and
   into the six templates this pass is not allowed to edit still points at
   the section it names.
   ===================================================================== */

/* --- 35.1 ICONS -------------------------------------------------------
   ONE outline set: 24-unit grid, 1.75 stroke, round caps and joins,
   currentColor. Inline SVG, so an icon inherits the colour of whatever it
   sits in and there is no second request and no icon font.

   The set is defined once per document as <symbol>s inside a hidden
   <svg class="icons">, printed by eocpr_icon_sprite() at wp_body_open, and
   referenced with <use href="#i-name">. Decorative icons carry
   aria-hidden="true" and focusable="false" — the second attribute is not
   redundant, IE-era engines and some Android WebViews still put an <svg>
   in the tab order without it.

   An icon that carries MEANING is never left to do it alone: it sits
   inside an element that already has an accessible name.
   --------------------------------------------------------------------- */
.icons{position:absolute;width:0;height:0;overflow:hidden}
.ic{
  width:1.25em;height:1.25em;flex:none;fill:none;stroke:currentColor;
  stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round;
}

/* --- 35.2 THE HERO PLATE, AND THE PHOTO SLOT --------------------------
   There is no photograph library in this repository, so the hero does not
   pretend one exists and does not borrow stock. The plate is a FINISHED
   object: a gradient, the brand mark as a watermark at 8.5% opacity, and
   one sentence of approved copy set in the display face.

   It is also the drop-in slot. Replace .plate__art with
   <img class="plate__img" ...> and every surrounding grid, type and
   contrast rule is unchanged, because .plate__in already sits on its own
   scrim rather than on the raw image.

   CONTRAST. The gradient runs #0B3D26 -> #14603C, so every ratio below is
   stated against --plate-top #14603C, the LIGHTEST pixel any plate text
   can land on. That is the worst case, not the average.
   --------------------------------------------------------------------- */
.plate{
  position:relative;overflow:hidden;border-radius:var(--r-lg);
  background:linear-gradient(152deg,var(--forest-deep) 8%,var(--plate-top) 96%);
  color:var(--on-dark);padding:clamp(1.6rem,3vw,2.6rem);
  min-height:clamp(19rem,30vw,27rem);display:flex;
}
.plate__art{position:absolute;inset:0;pointer-events:none}
.plate__img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.plate__art .brandmark__sym{position:absolute;right:-9%;bottom:-18%;width:74%;height:auto;opacity:.085}
.plate__art::after{
  content:"";position:absolute;inset:0;
  background:radial-gradient(30rem 22rem at 16% 6%,rgba(14,143,138,.30),transparent 64%);
}
.plate__in{
  position:relative;display:flex;flex-direction:column;gap:var(--s5);
  justify-content:space-between;width:100%;
}
.plate .eyebrow{color:var(--gold-lum)}          /* #E8C86A on #14603C = 4.66:1. Stated against the
                                                   LIGHTEST pixel of the plate gradient, which is the
                                                   worst case; it clears AA 4.5:1 for normal text
                                                   there, and 7.55:1 at the dark end. */
.plate .eyebrow .ic{color:var(--gold-lum)}
.plate .rule{background:var(--gold)}
.plate__st{
  font-family:var(--serif);font-weight:600;line-height:1.16;letter-spacing:-.02em;
  font-size:clamp(1.5rem,1.05rem + 1.35vw,2.25rem);
  color:var(--on-dark);max-width:16ch;                              /* #FFFFFF on #14603C = 7.59:1 */
}
.plate__foot{
  display:flex;align-items:center;gap:.55rem;font-size:var(--fs-sm);
  color:var(--link-foot);max-width:none;                            /* #D5E7DC on #14603C = 5.89:1 */
}
.plate__foot .ic{color:var(--gold-lum)}                             /* 4.66:1, non-text mark */

/* Source line on the plate, added 0.5.3 alongside .card__src. Same reasoning,
   different surface. Reuses the two pairs already measured for the plate in
   §3 against --plate-top #14603C, the LIGHTEST pixel of the plate gradient
   and therefore the worst case for light text:
       --link-foot #D5E7DC  on  #14603C  =  5.89:1   (the line)
       --link-inv  #FFFFFF  on  #14603C  =  7.59:1   (the link, below)
   No new ledger entry. The link itself inherits .plate a:not(.btn) on the
   next rule, which already carries the underline. */
.plate__src{
  font-size:var(--fs-xs);line-height:1.5;color:var(--link-foot);max-width:none;
  margin-top:.6rem;
}

.plate a:not(.btn){color:var(--link-inv);text-decoration:underline} /* #FFFFFF on #14603C = 7.59:1 */
.bm--ghost path{fill:var(--link-inv)}

/* --- 35.3 THE HERO WORD ROTATOR ---------------------------------------
   The owner asked for this one specifically. Four properties, all of them
   load-bearing:

   1. THE SENTENCE IS COMPLETE IN THE HTML. .rot__w ships with the first
      word already in it, inside a full sentence, so with JavaScript off
      the headline reads correctly and permanently. Nothing is assembled
      by script.

   2. WIDTH IS RESERVED, SO NOTHING REFLOWS. .rot__sizer stacks EVERY
      candidate word in the same grid cell and is visibility:hidden, so the
      inline-grid is permanently as wide as the longest word — 378.0px for
      "early detection" at 52px in Source Serif 4 600, summed from that
      file's own advance widths (against equity 160.6, prevention 279.0,
      research 220.3, treatment 251.0). The line never re-wraps mid-swap.

   3. CROSS-FADE, NO BOUNCE. The transition is in §30: opacity plus a
      -0.28em rise over 350ms on the house ease. No spring, no overshoot,
      no horizontal slide.

   4. NO aria-live, DELIBERATELY. A live region would re-announce the
      headline every 3.2 seconds, forever, to a screen-reader user who is
      trying to read the rest of the page. The sentence is announced once,
      as written, which is what a reader needs.

   Under prefers-reduced-motion the swap never starts (eocpr.js reads the
   query) and §32 pins the word visible regardless.
   --------------------------------------------------------------------- */
.rot{display:inline-grid;vertical-align:baseline;color:var(--deep-teal)}  /* #0B6B66 on #FFFFFF = 6.35:1 */
.rot__sizer,.rot__w{grid-area:1/1}
.rot__sizer{visibility:hidden;display:grid;pointer-events:none}
.rot__sizer > span{grid-area:1/1}

/* --- 35.4 THE RISK GRID -----------------------------------------------
   Stacked on a phone, side by side from 62em (see §31). This is the
   direct answer to "the texts are vertically ... looks like book or
   mobile version on a computer screen". --------------------------------- */
.riskgrid{display:grid;gap:var(--s6)}

/* --- 35.5 THE DEEP-PAGE EDITORIAL GRID --------------------------------
   Three parts: a numbered sticky contents rail, a reading column at
   --measure, and a wider track that evidence panels, figures, tables and
   quotes break out to. The track arithmetic is in §8; this is the object
   layer that sits on it.

   .artgrid / .rail are the merged design's names and are what
   COMPONENTS.md documents. .art__grid / .toc are the older names, still
   defined in §15 and §31, because templates this pass may not edit use
   them. Both resolve to the same two-column layout at 78em.
   --------------------------------------------------------------------- */
.artgrid{display:grid;gap:var(--s7);margin-top:var(--s7)}

/* (a) THE RAIL — numbered, ruled, sticky. Links here are LINK 2, the
   navigation colour: the rail is navigation, and giving it a muted colour
   of its own is how a site ends up with nine link colours. */
.rail{font-size:var(--fs-sm)}
/* Hidden while the <summary> is on screen, shown when the summary is not —
   they carry the SAME approved label, and printing it twice would read as
   a stutter. It stays in the DOM either way because it is the rail
   landmark's accessible name (aria-labelledby in page.php), and an
   accessible name is computed from text whether or not it is displayed. */
.rail__h{
  display:none;
  font-family:var(--sans);font-size:var(--fs-xs);font-weight:600;
  letter-spacing:.12em;text-transform:uppercase;color:var(--gold-ink);   /* #7A6416 on #FFFFFF = 5.73:1 */
  padding-bottom:var(--s3);border-bottom:1px solid var(--hair);
}
@media (min-width:78em){.rail__h{display:block}}
.rail ol{counter-reset:r;margin-top:var(--s4);display:grid;gap:.1rem;list-style:none;padding:0}
.rail li{counter-increment:r}
.rail a{
  display:grid;grid-template-columns:1.9rem 1fr;gap:.4rem;padding:.5rem .55rem;min-height:44px;
  color:var(--link-nav);text-decoration:none;line-height:1.35;           /* #123222 on #FFFFFF = 13.95:1 */
  border-left:2px solid var(--hair);align-items:baseline;
}
.rail a::before{
  content:counter(r,decimal-leading-zero);font-family:var(--mono);
  font-size:.75rem;font-weight:600;color:var(--gold-ink);padding-top:.1rem;   /* 5.73:1 */
  font-variant-numeric:tabular-nums;
}
.rail a:hover{background:var(--s-band);border-left-color:var(--gold)}        /* #123222 on #FBF7ED = 13.04:1 */
.rail a:hover span{text-decoration:underline;text-underline-offset:.18em}
/* Both spellings: .is-here is the design's, [aria-current] is what
   assets/js/eocpr.js sets and what a screen reader actually reads. */
.rail a.is-here,.rail a[aria-current]{background:var(--s-band);border-left-color:var(--forest);font-weight:600}
.rail a.is-here::before,.rail a[aria-current]::before{color:var(--forest)}   /* #0F5132 on #FBF7ED = 8.75:1 */
.rail__m{border:1px solid var(--hair);border-radius:var(--r);padding:.2rem .9rem .6rem}
.rail__m > summary{
  list-style:none;cursor:pointer;display:flex;align-items:center;gap:.5rem;min-height:48px;
  padding:.8rem 0;font-weight:600;color:var(--link-nav);                     /* 13.95:1 */
}
.rail__m > summary::-webkit-details-marker{display:none}
.rail__m > summary .ic{color:var(--deep-teal)}                              /* 6.35:1 */

/* (b) THE FLOW — the named-line grid for a page of numbered positions.
   No column here can be empty: the outer tracks are minmax(0,1fr) and
   collapse to zero when the viewport cannot pay for them. */
.positions{display:grid;gap:0}
.pos{
  display:grid;padding-top:var(--s8);margin-top:var(--s8);
  border-top:1px solid var(--hair);scroll-margin-top:7rem;
  grid-template-columns:
    [full-start] minmax(0,1fr)
    [wide-start] minmax(0,3rem)
    [text-start] min(100%,var(--measure))
    [text-end]   minmax(0,3rem)
    [wide-end]   minmax(0,1fr)
    [full-end];
}
.pos:first-child{border-top:0;padding-top:0;margin-top:0}
.pos > *{grid-column:text}
.pos > .wide{grid-column:wide}
.pos > .full{grid-column:full}
.pos > * + *{margin-top:var(--s5)}
.pos > .pos__n + .pos__head{margin-top:0}
.pos > .wide,.pos > .full{margin-top:var(--s6)}
.pos__head{display:flex;align-items:flex-start;gap:var(--s4)}
.pos__ic{
  display:grid;place-items:center;width:2.75rem;height:2.75rem;flex:none;
  border-radius:10px;background:var(--s-teal);color:var(--forest);       /* #0F5132 on #E8F2F1 = 8.20:1 */
}
.pos__ic .ic{width:1.5rem;height:1.5rem;stroke-width:1.6}
.pos h2{max-width:24ch}
.pos p{line-height:1.7}
.pos p + p{margin-top:var(--s4)}
/* The position numeral, hung in the outer track. It ties the rail to the
   page and it is the reason that track is never merely empty margin.
   Drawn only from 88em — see §31. */
.pos__n{
  display:none;grid-row:1;grid-column:full-start/text-start;justify-self:start;
  font-family:var(--mono);font-size:.8125rem;font-weight:600;letter-spacing:.06em;
  color:var(--gold-ink);padding-top:.85rem;                              /* 5.73:1 */
  font-variant-numeric:tabular-nums;
}
/* A link to a full document, treated as an object rather than as prose. */
.brieflink{
  display:inline-flex;align-items:center;gap:.45rem;min-height:44px;
  padding:.6rem .85rem;border:1px solid var(--hair);border-radius:var(--r-sm);
  background:var(--s-band);color:var(--link);font-size:var(--fs-sm);font-weight:600;
  text-decoration:underline;text-underline-offset:.18em;justify-self:start;   /* #0B6B66 on #FBF7ED = 5.93:1 */
}
.brieflink:hover,.pos .brieflink:hover{background:var(--s-teal);border-color:var(--deep-teal);box-shadow:none}
/* The outbound mark, inline. Never the only signal that a link leaves the
   site: eocpr_annotate_new_tab_links() appends the spoken equivalent. */
.ext{
  width:.78em;height:.78em;stroke-width:2.4;display:inline-block;
  vertical-align:-.02em;margin-left:.2em;color:var(--deep-teal);          /* 6.35:1, non-text */
}

/* --- 35.6 THE EVIDENCE PANEL ------------------------------------------
   A distinct visual OBJECT from the argument around it. The position is
   editorial — serif heading, prose column, prose links. The evidence is a
   panel — sans-serif labels, tabular numerals, an inset surface and a gold
   left rule. A reader can tell at a glance which is which, which is the
   whole point of the thing.
   --------------------------------------------------------------------- */
.well{background:var(--s-inset);border-left:3px solid var(--gold);padding:var(--s5) var(--s6)}
.well__h{
  display:flex;align-items:center;gap:.5rem;font-size:var(--fs-xs);
  font-weight:600;letter-spacing:.12em;text-transform:uppercase;
  color:var(--gold-ink);                                                 /* #7A6416 on #F7F3E8 = 5.17:1 */
}
.well__h .ic{color:var(--deep-teal)}                                     /* #0B6B66 on #F7F3E8 = 5.72:1 */
.well dl{margin-top:var(--s5);display:grid;gap:var(--s5) var(--s6)}
.well dt{
  font-size:var(--fs-xs);font-weight:600;letter-spacing:.07em;
  text-transform:uppercase;color:var(--text-mut);                        /* #4A5C51 on #F7F3E8 = 6.44:1 */
}
.well dd{margin-top:.35rem;font-size:var(--fs-sm);color:var(--text);line-height:1.5}  /* 12.58:1 */
.well .num{
  display:block;font-family:var(--serif);font-size:1.75rem;font-weight:600;
  line-height:1.1;letter-spacing:-.02em;color:var(--heading);            /* #0F5132 on #F7F3E8 = 8.44:1 */
  font-variant-numeric:tabular-nums;
}
.well .num--sm{font-size:1.25rem}

/* --- 35.7 THE FIGURE FRAME — a frame, not a card ----------------------
   The owner's note: "see how bad the figure isnt integrated in the colour
   of the background". So the plot area has NO fill of its own — the
   transparent SVG sits directly on whatever surface the section is using.
   What remains is a hairline, a small header strip and a caption rule.

   The caption is CONTENT, not a footnote: one line at reading size in
   --text, with the long source note folded into a <details> under it.
   The owner again: "i really dont want that boring busy many txt caption
   a one liner please".

   These rules OVERRIDE §19 for frames that carry .figframe__k. §19 keeps
   its white card for the templates this pass may not edit; a frame is
   opted into the flat treatment by using the new header classes.
   --------------------------------------------------------------------- */
.figframe:has(.figframe__k){border:1px solid var(--hair);border-radius:var(--r);background:none;box-shadow:none}
.figframe__hd:has(.figframe__k){
  display:flex;flex-wrap:wrap;gap:.4rem var(--s4);align-items:baseline;justify-content:space-between;
  padding:.8rem clamp(1rem,2vw,1.4rem);background:var(--s-band-deep);
  border-bottom:1px solid var(--hair);border-radius:calc(var(--r) - 1px) calc(var(--r) - 1px) 0 0;
}
.figframe__k{
  display:flex;align-items:center;gap:.5rem;font-size:var(--fs-xs);
  font-weight:600;letter-spacing:.12em;text-transform:uppercase;
  color:var(--gold-ink);                                                 /* #7A6416 on #F5F1E6 = 5.08:1 */
}
.figframe__k .ic{width:1em;height:1em;color:var(--deep-teal)}            /* #0B6B66 on #F5F1E6 = 5.62:1 */
.figframe__y{font-size:var(--fs-xs);color:var(--text-mut);font-variant-numeric:tabular-nums}  /* 6.33:1 */
.figframe:has(.figframe__k) .figframe__plot{padding:clamp(.9rem,1.8vw,1.4rem);background:none}
.figframe:has(.figframe__k) figcaption{
  padding:clamp(.9rem,1.8vw,1.25rem) clamp(1rem,2vw,1.4rem);
  border-top:1px solid var(--hair);background:none;
  font-size:var(--fs-sm);line-height:1.55;color:var(--text);             /* #123222 on #FFFFFF = 13.95:1 */
}
.eocpr-fig{width:100%;height:auto;display:block}
.eocpr-fig text{font-family:var(--sans)}
/* The portrait figure variant, swapped in CSS. No script, no reflow, and
   the two are never both in the layout. */
.eocpr-fig--tall{display:none}
@media (max-width:767.98px){
  .eocpr-fig--wide{display:none}
  .eocpr-fig--tall{display:block}
}
/* The long source note, folded. Open by default in print — see §33. */
.figsrc{margin-top:.6rem}
.figsrc > summary{
  cursor:pointer;display:inline-flex;align-items:center;gap:.4rem;min-height:44px;
  font-size:var(--fs-xs);font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--link);list-style:none;text-decoration:underline;text-underline-offset:.18em;  /* 6.35:1 */
}
.figsrc > summary::-webkit-details-marker{display:none}
.figsrc > summary::before{
  content:"";width:.5rem;height:.5rem;flex:none;
  border-right:2px solid currentColor;border-bottom:2px solid currentColor;
  transform:rotate(45deg) translateY(-2px);
}
.figsrc[open] > summary::before{transform:rotate(-135deg) translateY(-1px)}
.figsrc > div{margin-top:.6rem;font-size:var(--fs-xs);line-height:1.6;color:var(--text-mut);max-width:88ch}  /* 7.14:1 */

/* --- 35.8 EVIDENCE TABLE ROWS -----------------------------------------
   Two row states for a table that compares a measurement to a benchmark.
   Neither is carried by colour alone: the total row also gains weight and
   a rule, the benchmark row also gains a left rule and a surface change.
   --------------------------------------------------------------------- */
tbody tr.is-total th,tbody tr.is-total td{
  font-weight:600;color:var(--heading);border-top:2px solid var(--hair);border-bottom:0;   /* 9.36:1 */
}
tbody tr.is-bench th,tbody tr.is-bench td{
  background:var(--s-inset);box-shadow:inset 3px 0 0 var(--gold);color:var(--text);        /* 12.58:1 */
}

/* --- 35.9 THE CTA BAND ------------------------------------------------
   A LIGHT band with a gold top rule, NOT a fifth green slab and NOT the
   dark .sec--dark block this replaced on the front page. The colour
   restraint is the point, and it is also the footer fix: there is exactly
   one dark band on the page now, and it is the footer.

   .ctaband is a NEW class rather than a change to .cta. template-parts/
   cta.php still renders the dark .sec--dark .cta block and is used by six
   templates this pass may not edit; repurposing .cta would have silently
   restyled all of them.
   --------------------------------------------------------------------- */
.ctaband{border-top:3px solid var(--gold);background:var(--s-band)}
.ctaband__in{display:grid;gap:var(--s6);align-items:center}
.ctaband__ic{
  display:grid;place-items:center;width:3rem;height:3rem;border-radius:11px;
  background:var(--s-teal);color:var(--forest);margin-bottom:var(--s5);   /* #0F5132 on #E8F2F1 = 8.20:1 */
}
.ctaband__ic .ic{width:1.6rem;height:1.6rem;stroke-width:1.6}
.ctaband h2{margin-top:.6rem}
.ctaband p:not(.eyebrow){margin-top:var(--s4);color:var(--text-mut);max-width:44rem}  /* #4A5C51 on #FBF7ED = 6.67:1 */

/* --- 35.10 PRINT ADDITIONS -------------------------------------------- */
@media print{
  .topbar,.masthead,.mnav,.rail,.hero__acts,.foot__base nav,.foot__legal,.pos__n,.plate__art{display:none}
  .plate{background:none;color:#000;border:1px solid #999}
  .plate__st,.plate__foot{color:#000}
  .figsrc > div{display:block}
  .ctaband{border-top:1px solid #999;background:none}
}

/* =====================================================================
   36. GROUPED NAVIGATION — tab, then sub-tab
   ---------------------------------------------------------------------
   The previous panel put every child of a section into one flat column.
   With "About cancer" carrying sixteen pages that is a wall, and it is
   what the client rejected: "I want it similar to the institutional
   design where it was tab then subtabs then subtabs, not all in one."

   So a top-level tab opens a panel of TITLED GROUPS. A visitor scanning
   About cancer sees four headings and reads only the column they want.
   Group headings that have their own landing page are links; the rest are
   plain <p>. Neither is a heading element — this is inside <nav>, and
   h-levels here would corrupt the document outline.

   Opens on :hover AND :focus-within, so it works with JavaScript off and
   needs no aria-expanded to keep in sync with anything.
   ===================================================================== */
.sub{
  display:grid; gap:var(--s5) var(--s7);
  grid-template-columns:repeat(auto-fit,minmax(13.5rem,1fr));
  padding:var(--s6);
}
/* Column count comes from a data attribute, not a class built with printf:
   a dynamic class name is invisible to check_theme.py's class audit, which
   is the only thing stopping a template shipping a class that does not
   exist in this file. */
.sub[data-cols="1"]{grid-template-columns:minmax(15rem,20rem)}
.sub[data-cols="2"]{grid-template-columns:repeat(2,minmax(13.5rem,17rem))}
.sub[data-cols="3"]{grid-template-columns:repeat(3,minmax(12.5rem,16rem))}
.sub[data-cols="4"]{grid-template-columns:repeat(4,minmax(12rem,15rem))}

.sub__g{min-width:0}
.sub__h{
  display:block; margin:0 0 var(--s3);
  font-family:var(--sans); font-size:var(--fs-xs); font-weight:600;
  letter-spacing:.09em; text-transform:uppercase;
  color:var(--gold-ink);                     /* #7A6416 on #FFFFFF = 5.73:1 */
  text-decoration-line:none;
}
a.sub__h:hover{color:var(--forest); text-decoration-line:underline} /* 9.36:1 */
.sub__l{list-style:none; margin:0; padding:0; display:grid; gap:2px}
.sub__l a{
  display:block; padding:.42rem .5rem; margin-inline-start:-.5rem;
  border-radius:var(--r-sm);
  font-size:var(--fs-sm); line-height:1.35;
  color:var(--link-nav);                     /* #123222 on #FFFFFF = 13.95:1 */
  text-decoration-line:none;
}
.sub__l a:hover{background:var(--s-teal); color:var(--forest)}   /* 8.20:1 */
.sub__l a[aria-current]{color:var(--forest); font-weight:600}

/* ---- the same grouping on a phone, one section at a time -------------
   Each top-level item is its own nested <details>, so the panel opens
   showing six things rather than sixty. Browser-driven: no script, so a
   phone with JS blocked still has the whole navigation. */
.mnav__sec{border-bottom:1px solid var(--hair)}
.mnav__sec:last-of-type{border-bottom:0}
.mnav__top{
  display:flex; align-items:center; gap:var(--s3);
  min-height:52px; padding:var(--s3) 0;
  font-family:var(--sans); font-size:var(--fs-body); font-weight:600;
  color:var(--link-nav); text-decoration-line:none; cursor:pointer;
  list-style:none;
}
.mnav__top::-webkit-details-marker{display:none}
.mnav__chev{margin-inline-start:auto; transition:rotate var(--dur-2) var(--ease)}
.mnav__sec[open] > .mnav__top .mnav__chev{rotate:180deg}
.mnav__body{padding:0 0 var(--s4) var(--s6)}
.mnav__all{
  display:inline-block; min-height:44px; padding:.5rem 0;
  font-size:var(--fs-sm); font-weight:600; color:var(--link);  /* 6.35:1 */
}
.mnav__grp{margin-top:var(--s4)}
.mnav__h{
  margin:0 0 var(--s2); font-family:var(--sans);
  font-size:var(--fs-xs); font-weight:600; letter-spacing:.09em;
  text-transform:uppercase; color:var(--gold-ink);            /* 5.73:1 */
  text-decoration-line:none;
}
.mnav__grp ul{list-style:none; margin:0; padding:0}
.mnav__grp li a{
  display:block; min-height:44px; padding:.55rem 0;
  font-size:var(--fs-sm); color:var(--link-nav);              /* 13.95:1 */
  text-decoration-line:none;
}
.mnav__grp li a[aria-current]{color:var(--forest); font-weight:600}

/* =====================================================================
   37. THE WORDMARK STAYS ON A PHONE
   ---------------------------------------------------------------------
   §31 hid .brandmark__words below 480px, so a phone showed the symbol and
   nothing else — the client's "logo text is not visible on the phone
   version". There is room: the nav collapses to a single button, so the
   masthead has the whole row. Shrink the lockup instead of amputating it.
   ===================================================================== */
@media (max-width:479.98px){
  .masthead .brandmark__words{display:block}
  .masthead .brandmark{--sym:2rem; gap:.5rem}
  .masthead .brandmark__l1{font-size:.9375rem; letter-spacing:-.005em}
  .masthead .brandmark__l2{font-size:.625rem; letter-spacing:.16em}
  /* The label is redundant next to a universally understood icon at this
     width, and dropping it is what buys the wordmark its room. It is
     VISUALLY hidden, not removed, so the summary keeps its accessible
     name — display:none here would leave a control announced as nothing. */
  .mnav__sum .mnav__lbl{
    position:absolute;width:1px;height:1px;overflow:hidden;
    clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;
  }
}

/* =====================================================================
   38. PERSON CARD
   ---------------------------------------------------------------------
   A portrait frame that is the same shape whether or not a photograph
   exists, so a row of people never goes ragged and nothing has to be
   redesigned the day the first real portrait arrives.

   With no photograph the frame carries the person's INITIALS on a brand
   tint. Deliberately not a grey silhouette: an outline of a generic head
   reads as a missing person, and two of these people have asked not to be
   pictured. Initials read as a considered mark instead of an absence.
   ===================================================================== */
.pcard{display:flex;flex-direction:column;gap:var(--s3)}

.pcard__fig{
  width:5.5rem;height:5.5rem;border-radius:50%;overflow:hidden;
  display:grid;place-items:center;flex:0 0 auto;
  background:var(--s-teal);                       /* #E8F2F1 */
  border:1px solid var(--hair);
}
.pcard__img{width:100%;height:100%;object-fit:cover;display:block}
.pcard__ini{
  font-family:var(--serif);font-weight:600;
  font-size:1.75rem;line-height:1;letter-spacing:.01em;
  color:var(--forest);                            /* #0F5132 on #E8F2F1 = 8.20:1 */
}

/* The filing detail, after the bio and quiet. It is not the headline. */
.pcard__tags{
  display:flex;flex-wrap:wrap;gap:.3rem;
  margin-top:auto;padding-top:var(--s2);
}
.pcard__tag{
  display:inline-block;padding:.15rem .5rem;border-radius:var(--r-pill);
  background:var(--s-band);                       /* #FBF7ED */
  border:1px solid var(--hair);
  font-family:var(--sans);font-size:var(--fs-xs);line-height:1.5;
  color:var(--text-mut);                          /* #4A5C51 on #FBF7ED = 6.67:1 */
  white-space:nowrap;
}

/* From two columns up, the portrait sits beside the name rather than above
   it — the card reads as a person, not as a headshot with a caption. */
@media (min-width:40em){
  .pcard{display:grid;grid-template-columns:5.5rem 1fr;gap:var(--s3) var(--s4);align-items:start}
  .pcard__fig{grid-row:span 2}
  .pcard > :not(.pcard__fig){grid-column:2}
}


/* =====================================================================
   39. FIELD — THE EPIC DESIGN IN CPR – ETHIOPIA'S COLOURS (0.7.0)

   Daniel's brief, 29 October 2026: revise the site to be on par with the
   EPIC Health Systems site, as was done for ISPOR Ethiopia. This section is
   that layer: the EPIC "Field" header with mega panels, the Field hero,
   figures band, tabbed explorer, row lists, tiles, dark membership band,
   page heads and footer, set in EPIC's faces (Newsreader and Schibsted
   Grotesk, §1).

   THE COLOURS ARE NOT NEW. Every pair below reuses a token from §2 and is
   measured here the same way §3 measures its own:
     #0B6B66 deep teal on #FFFFFF 6.35 · on #FBF7ED 5.93 · on #FCFAF4 6.08
     #7A6416 gold-ink  on #FFFFFF 5.73 · on #FBF7ED 5.36   (eyebrows)
     #4A5C51 text-mut  on #FFFFFF 7.14 · on #FBF7ED 6.67
     #FFFFFF on #0B3D26 forest-deep 12.28 · #D3DCD8 on #0B3D26 8.77
     #E8C86A gold-lum  on #0B3D26 7.55 · on #0F5132 5.75
     #FFFFFF on #0F5132 9.36 · #D4E0DA on #0F5132 6.90
     #0B3D26 on #D4AF37 gold 5.84 (gold buttons, unchanged from §11)
     #123222 on #E8F2F1 teal tint 12.23
   Appended rather than inserted, for the same reason §34 and §35 were:
   every "§n" reference already written elsewhere keeps its meaning.
   ===================================================================== */
:root{
  --shell:min(1440px,100%);
  --f-r:16px;--f-r-lg:22px;
  --f-shadow:0 30px 60px rgba(11,61,38,.10);
  --f-shadow-sm:0 18px 40px rgba(11,61,38,.08);
}
h1,h2,h3,h4{font-weight:500}
.art h2,.prose h2,.art h3,.prose h3{font-weight:500}
strong,b{font-weight:600}

/* 39.1 Shared pieces ------------------------------------------------------ */
.feyebrow{display:block;margin:0;font-family:var(--sans);font-size:var(--fs-xs);line-height:1.3;font-weight:600;letter-spacing:.16em;text-transform:uppercase;color:var(--gold-ink)}  /* 5.73:1 */
.fh2{font-family:var(--serif);font-weight:500;font-size:var(--fs-h2);line-height:1.08;letter-spacing:-.016em;color:var(--heading);margin:.6rem 0 0;max-width:22ch}
.fbtns{display:flex;flex-wrap:wrap;gap:.75rem;align-items:center;margin:0}
.flink{display:inline-flex;align-items:center;gap:.5rem;font-weight:600;font-size:var(--fs-sm);color:var(--deep-teal);text-decoration:none}   /* 6.35:1 */
.flink .ic{width:1.05em;height:1.05em;transition:transform var(--dur-2) var(--ease)}
.flink:hover{color:var(--forest);text-decoration:underline;text-underline-offset:.2em}
.flink:hover .ic{transform:translateX(3px)}
.btn--ghostw{background:transparent;color:#fff;border:1.5px solid rgba(255,255,255,.55)}   /* #FFFFFF on #0B3D26 = 12.28:1 */
.btn--ghostw:hover{background:rgba(255,255,255,.12);color:#fff}
.fsec{padding:clamp(4.5rem,3rem + 4vw,6.5rem) 0}
.fsec--soft{background:var(--s-band)}
.fsec + .fsec:not(.fsec--soft){border-top:1px solid var(--hair-soft)}
.fheads{display:flex;justify-content:space-between;align-items:flex-end;gap:2rem;flex-wrap:wrap;margin-bottom:clamp(2rem,1.4rem + 1.6vw,3rem)}

/* 39.2 Top bar and masthead ---------------------------------------------- */
.topbar{background:var(--s-paper);color:var(--text-mut);border-bottom:1px solid var(--hair-soft)}
.topbar__in{min-height:2.6rem}
.topbar__loc{gap:1.4rem;color:var(--text-mut);flex-wrap:wrap}
.topbar__loc > span,.topbar a{display:inline-flex;align-items:center;gap:.45rem;color:var(--text-mut)}   /* 7.14:1 on #FCFAF4 */
.topbar a:hover{color:var(--forest)}
.topbar .ic{color:var(--deep-teal)}
.topbar a[aria-current]{color:var(--forest)}
.topbar :focus-visible{outline-color:var(--deep-teal)}
@media (max-width:47.99em){.topbar a.topbar__mail{display:none}}
.masthead{background:rgba(255,255,255,.97);border-bottom:1px solid var(--hair)}
.admin-bar .masthead{top:32px}
@media (max-width:782px){.admin-bar .masthead{top:0}}
.masthead__in{min-height:84px;gap:1rem}
.nav{gap:0;height:84px;align-items:stretch}
.fnav{display:flex;align-items:stretch;list-style:none;margin:0;padding:0;height:100%}
.fnav__i{display:flex;align-items:stretch}
.fnav__t{display:flex;align-items:center;gap:.35rem;padding:0 .8rem;font-size:var(--fs-sm);font-weight:500;color:var(--text);text-decoration:none;white-space:nowrap;border-bottom:2.5px solid transparent;margin-bottom:-1px;transition:color var(--dur-2) var(--ease),border-color var(--dur-2) var(--ease)}
.fnav__chev{width:.9em;height:.9em;color:var(--text-mut);transition:transform var(--dur-2) var(--ease)}
.fnav__i:hover .fnav__t,.fnav__i:focus-within .fnav__t,.fnav__i.is-cur .fnav__t{color:var(--forest);border-bottom-color:var(--gold)}
.fnav__i:hover .fnav__chev,.fnav__i:focus-within .fnav__chev{transform:rotate(180deg)}
.mega{position:absolute;left:var(--gutter);right:var(--gutter);top:100%;z-index:70;background:#fff;border:1px solid var(--hair);border-top:0;border-radius:0 0 var(--f-r-lg) var(--f-r-lg);box-shadow:0 34px 70px rgba(11,61,38,.14);padding:1.9rem 2.1rem 2.1rem;opacity:0;visibility:hidden;transform:translateY(-8px);transition:opacity .22s,transform .22s,visibility .22s}
.fnav__i:hover .mega,.fnav__i:focus-within .mega{opacity:1;visibility:visible;transform:none}
.mega.is-closed{opacity:0!important;visibility:hidden!important}
.mega__grid{display:grid;grid-template-columns:repeat(var(--cols,2),minmax(0,1fr)) minmax(0,1.15fr);gap:1.75rem}
.mega__h{display:flex;align-items:center;gap:.6rem;margin:0 0 .7rem;padding-bottom:.7rem;border-bottom:1px solid var(--hair-soft);font-size:.78rem;font-weight:600;letter-spacing:.13em;text-transform:uppercase;color:var(--gold-ink);text-decoration:none}   /* 5.73:1 */
a.mega__h:hover{color:var(--forest)}
.mega__ic{width:30px;height:30px;border-radius:9px;background:var(--s-teal);color:var(--deep-teal);display:flex;align-items:center;justify-content:center;flex:none}
.mega__ic .ic{width:17px;height:17px}
.mega__l{list-style:none;margin:0;padding:0;display:grid;gap:.1rem}
.mega__l a{display:block;padding:.45rem .6rem;margin:0 -.6rem;border-radius:10px;font-size:var(--fs-sm);line-height:1.35;color:var(--text);text-decoration:none;transition:background var(--dur-2) var(--ease),color var(--dur-2) var(--ease)}   /* 13.95:1 */
.mega__l a:hover{background:var(--s-teal);color:var(--forest)}   /* 8.20:1 */
.mega__l a[aria-current]{color:var(--forest);font-weight:600}
.mega__f{position:relative;isolation:isolate;overflow:hidden;display:flex;flex-direction:column;justify-content:flex-end;gap:.5rem;min-height:100%;padding:1.5rem;border-radius:var(--f-r);background:var(--forest-deep);color:#fff;text-decoration:none}
.mega__f::before{content:"";position:absolute;inset:0;z-index:-1;background:radial-gradient(circle,rgba(232,200,106,.22) 1.4px,transparent 1.6px) 0 0/18px 18px;-webkit-mask-image:linear-gradient(160deg,#000 0%,transparent 70%);mask-image:linear-gradient(160deg,#000 0%,transparent 70%)}
.mega__fk{font-size:.78rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--gold-lum)}   /* 7.55:1 */
.mega__ft{font-family:var(--serif);font-size:1.35rem;line-height:1.25;color:#fff}   /* 12.28:1 */
.mega__fd{font-size:var(--fs-sm);line-height:1.5;color:#D3DCD8}   /* 8.77:1 */
.mega__fgo{display:inline-flex;margin-top:.3rem;color:var(--gold-lum)}
.mega__fgo .ic{width:1.2em;height:1.2em;transition:transform var(--dur-2) var(--ease)}
.mega__f:hover .mega__fgo .ic{transform:translateX(4px)}
.mega__f:focus-visible{outline-color:var(--gold)}
.msrch{position:relative;flex:none}
.msrch > summary{list-style:none;cursor:pointer;width:44px;height:44px;border-radius:999px;border:1px solid var(--hair);display:flex;align-items:center;justify-content:center;color:var(--forest)}
.msrch > summary::-webkit-details-marker{display:none}
.msrch > summary:hover,.msrch[open] > summary{border-color:var(--deep-teal);background:var(--s-teal)}
.msrch > summary .ic{width:18px;height:18px}
.msrch form{position:absolute;right:0;top:calc(100% + 12px);z-index:75;width:min(420px,86vw);display:flex;gap:.5rem;padding:.6rem;background:#fff;border:1px solid var(--hair);border-radius:var(--f-r);box-shadow:var(--f-shadow)}
.msrch input{flex:1;min-width:0;border:1px solid var(--line-ctl);border-radius:999px;padding:.7rem 1.1rem;font-size:var(--fs-sm);color:var(--text)}
.msrch .btn{min-height:44px;padding:.6rem 1.1rem}
.mast__join{display:none;flex:none}
@media (min-width:69em){.nav__wrap{order:0}}
@media (min-width:82em){.mast__join{display:inline-flex}}
@media (max-width:68.99em){.msrch{margin-left:auto}.nav__wrap{margin-left:.5rem}}
@media (max-width:47.99em){.msrch{display:none}.nav__wrap{margin-left:auto}}
.mnav__srch{display:flex;gap:.5rem;margin-top:var(--s5)}
.mnav__srch input{flex:1;min-width:0;border:1px solid var(--line-ctl);border-radius:999px;padding:.7rem 1rem;font-size:var(--fs-sm)}
@media (min-width:48em){.mnav__srch{display:none}}

/* 39.3 Hero ---------------------------------------------------------------- */
.fhero{position:relative;overflow:hidden;background:linear-gradient(180deg,#fff 0%,var(--s-paper) 55%,var(--s-band) 100%);border-bottom:1px solid var(--hair)}
.fhero__dots{position:absolute;inset:0;pointer-events:none;background:radial-gradient(circle,rgba(14,143,138,.16) 1.6px,transparent 1.8px) 0 0/22px 22px;-webkit-mask-image:radial-gradient(ellipse 70% 90% at 92% 10%,#000 0%,transparent 70%);mask-image:radial-gradient(ellipse 70% 90% at 92% 10%,#000 0%,transparent 70%)}
.fhero__grid{position:relative;display:grid;gap:clamp(2.5rem,1rem + 4vw,4.5rem);align-items:center;padding-top:clamp(3.5rem,2rem + 5vw,6.5rem);padding-bottom:clamp(4rem,2rem + 5vw,7rem)}
@media (min-width:62em){.fhero__grid{grid-template-columns:minmax(0,1.2fr) minmax(0,.8fr)}}
.fhero__h{margin:.9rem 0 0;font-family:var(--serif);font-weight:500;font-size:var(--fs-hero);line-height:1.04;letter-spacing:-.022em;color:var(--heading);max-width:15ch}
.fhero__h .rot__w,.fhero__h .rot__sizer{font-style:italic;color:var(--deep-teal)}   /* 6.35:1, large text */
.fhero__lede{margin:1.6rem 0 2.2rem;font-size:var(--fs-lede);line-height:1.5;color:var(--text);max-width:36em}
.fhero__meta{display:flex;flex-wrap:wrap;gap:.6rem 1.6rem;margin:2.2rem 0 0;padding-top:1.4rem;border-top:1px solid var(--hair);font-size:var(--fs-sm);color:var(--text-mut)}
.fhero__meta span{display:inline-flex;align-items:center;gap:.45rem}
.fhero__meta .ic{color:var(--deep-teal)}
.fcard{position:relative;background:#fff;border:1px solid var(--hair);border-radius:var(--f-r-lg);box-shadow:var(--f-shadow);padding:clamp(1.5rem,1.1rem + 1vw,2.1rem)}
.fcard__k{display:flex;align-items:center;gap:.6rem;margin:0;font-size:var(--fs-xs);font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--gold-ink)}
.fcard__dot{width:8px;height:8px;border-radius:50%;background:var(--gold);box-shadow:0 0 0 4px rgba(212,175,55,.22)}
.fcard__t{margin:1rem 0 .8rem;font-family:var(--serif);font-size:clamp(1.5rem,1.2rem + 1vw,2rem);line-height:1.2;color:var(--heading)}
.fcard__src{margin:0 0 1.2rem;font-size:var(--fs-xs);line-height:1.5;color:var(--text-mut)}
.fcard__src a{color:var(--deep-teal)}

/* 39.4 Figures band ------------------------------------------------------- */
.fstats{background:var(--s-teal);padding:clamp(2.75rem,2rem + 2vw,3.75rem) 0;border-bottom:1px solid var(--hair-soft)}
.fstats__head{display:flex;justify-content:space-between;align-items:baseline;gap:1rem;flex-wrap:wrap;margin-bottom:1.6rem}
.fstats__head .feyebrow{color:var(--forest)}   /* 8.20:1 on #E8F2F1 */
.fstats__grid{display:grid;gap:1.75rem}
@media (min-width:40em){.fstats__grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (min-width:75em){.fstats__grid{grid-template-columns:repeat(4,minmax(0,1fr))}}
.fstat{border-left:2px solid var(--gold);padding:.15rem 0 .15rem 1.25rem}
.fstat p{margin:0}
.fstat__v{font-family:var(--serif);font-size:clamp(2.2rem,1.7rem + 1.6vw,3.2rem);line-height:1;letter-spacing:-.02em;color:var(--heading)}   /* 8.20:1 */
.fstat__u{font-size:.55em;margin-left:.08em}
.fstat__l{margin-top:.7rem!important;font-size:var(--fs-sm);font-weight:600;color:var(--text)}   /* 12.23:1 */
.fstat__n{margin-top:.4rem!important;font-size:var(--fs-xs);line-height:1.5;color:var(--text-mut)}   /* 6.26:1 */
.fstat__s{margin-top:.45rem!important;font-size:var(--fs-xs);line-height:1.5;color:var(--text-mut)}
.fstat__s p{margin:.2rem 0 0}
.fstat__src{font-size:var(--fs-xs)}
.fstat__s a,.fstat__src a{color:var(--forest)}

/* 39.5 Explorer (tabs) ------------------------------------------------------ */
.fx{display:grid;gap:1.75rem;align-items:stretch}
@media (min-width:62em){.fx.is-tabbed{grid-template-columns:minmax(0,.8fr) minmax(0,1.2fr)}}
.fx__list{display:none;flex-direction:column;gap:.6rem}
.fx.is-tabbed .fx__list{display:flex}
.fx__b{display:grid;grid-template-columns:44px minmax(0,1fr) 20px;gap:.9rem;align-items:center;width:100%;text-align:left;padding:1rem 1.15rem;border-radius:var(--f-r);border:1px solid var(--hair);background:#fff;color:var(--text);font:inherit;font-size:var(--fs-body);font-weight:500;cursor:pointer;transition:background var(--dur-2) var(--ease),border-color var(--dur-2) var(--ease),color var(--dur-2) var(--ease)}
.fx__ic{width:44px;height:44px;border-radius:12px;background:var(--s-teal);color:var(--deep-teal);display:flex;align-items:center;justify-content:center}
.fx__ar{color:var(--text-mut);transition:transform var(--dur-2) var(--ease)}
.fx__b:hover{border-color:var(--deep-teal)}
.fx__b.on{background:var(--forest-deep);border-color:var(--forest-deep);color:#fff}   /* 12.28:1 */
.fx__b.on .fx__ic{background:rgba(232,200,106,.16);color:var(--gold-lum)}
.fx__b.on .fx__ar{color:#fff;transform:translateX(3px)}
.fx__b:focus-visible{outline:3px solid var(--deep-teal);outline-offset:3px}
.fx__p{position:relative;isolation:isolate;overflow:hidden;display:flex;flex-direction:column;border-radius:var(--f-r-lg);background:var(--forest-deep);color:#fff;padding:clamp(1.75rem,1.2rem + 2vw,2.75rem)}
.fx.is-tabbed .fx__p{display:none}
.fx.is-tabbed .fx__p.on{display:flex}
.fx__p::before{content:"";position:absolute;inset:0;z-index:-1;background:radial-gradient(circle,rgba(232,200,106,.18) 1.6px,transparent 1.8px) 0 0/22px 22px;-webkit-mask-image:radial-gradient(ellipse 80% 80% at 100% 0%,#000 0%,transparent 70%);mask-image:radial-gradient(ellipse 80% 80% at 100% 0%,#000 0%,transparent 70%)}
.fx__pic{width:56px;height:56px;border-radius:16px;background:rgba(232,200,106,.16);color:var(--gold-lum);display:flex;align-items:center;justify-content:center;margin-bottom:1.6rem}
.fx__pic .ic{width:26px;height:26px}
.fx__p h3{font-family:var(--serif);font-weight:500;font-size:var(--fs-h2);line-height:1.12;color:#fff;margin:0}
.fx__p > p{margin:1rem 0 0;font-size:var(--fs-lede);line-height:1.55;color:#D3DCD8;max-width:34em}   /* 8.77:1 */
.fx__chips{list-style:none;display:flex;flex-wrap:wrap;gap:.5rem;margin:1.6rem 0 2rem;padding:0}
.fx__chips a{display:inline-flex;min-height:36px;align-items:center;padding:.35rem .8rem;border-radius:999px;background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.18);font-size:var(--fs-xs);color:#fff;text-decoration:none}   /* #FFFFFF on ~#1B4A35 > 10:1 */
.fx__chips a:hover{background:rgba(255,255,255,.18)}
.fx__p .btn{margin-top:auto;align-self:flex-start}
.fx__p :focus-visible{outline-color:var(--gold-lum)}
.fx:not(.is-tabbed) .fx__p + .fx__p{margin-top:0}

/* 39.6 Rows and tiles ---------------------------------------------------- */
.frows{list-style:none;margin:0;padding:0;border-top:1px solid var(--hair)}
.frows > li{border-bottom:1px solid var(--hair)}
.frow{display:grid;grid-template-columns:48px minmax(0,1fr) 44px;gap:1.25rem;align-items:center;padding:1.4rem .3rem;color:var(--text);text-decoration:none;transition:background var(--dur-2) var(--ease)}
.frow:hover{background:rgba(255,255,255,.7)}
.fsec:not(.fsec--soft) .frow:hover{background:var(--s-paper)}
.frow__ic{width:48px;height:48px;border-radius:14px;background:#fff;border:1px solid var(--hair);color:var(--deep-teal);display:flex;align-items:center;justify-content:center}
.frow__b{display:grid;gap:.3rem}
.frow__t{font-family:var(--serif);font-size:clamp(1.2rem,1.05rem + .5vw,1.45rem);line-height:1.25;color:var(--heading)}   /* 9.36:1 */
.frow__d{font-size:var(--fs-sm);line-height:1.55;color:var(--text-mut)}   /* 7.14 / 6.67:1 */
.frow__go{width:44px;height:44px;border-radius:50%;border:1px solid var(--hair);background:#fff;display:flex;align-items:center;justify-content:center;color:var(--deep-teal);transition:background var(--dur-2) var(--ease),color var(--dur-2) var(--ease),border-color var(--dur-2) var(--ease)}
.frow:hover .frow__go{background:var(--forest);border-color:var(--forest);color:#fff}
.frow:hover .frow__t{text-decoration:underline;text-underline-offset:.15em;text-decoration-thickness:1px}
@media (max-width:39.99em){.frow{grid-template-columns:minmax(0,1fr) 40px}.frow__ic{display:none}}
.ftiles{display:grid;gap:1.25rem}
@media (min-width:48em){.ftiles{grid-template-columns:repeat(3,minmax(0,1fr))}}
.ftile{display:flex;flex-direction:column;gap:.75rem;background:#fff;border:1px solid var(--hair);border-radius:var(--f-r-lg);padding:clamp(1.4rem,1.1rem + .8vw,1.9rem);transition:border-color var(--dur-2) var(--ease),box-shadow var(--dur-2) var(--ease),transform var(--dur-2) var(--ease)}
.ftile:hover{border-color:#C9D9D4;box-shadow:var(--f-shadow-sm)}
.ftile__ic{width:46px;height:46px;border-radius:12px;background:var(--s-teal);color:var(--deep-teal);display:flex;align-items:center;justify-content:center}
.ftile h3{margin:.2rem 0 0;font-family:var(--serif);font-size:var(--fs-h3);line-height:1.25}
.ftile h3 a{color:var(--heading);text-decoration:none}
.ftile h3 a:hover{text-decoration:underline;text-underline-offset:.15em}
.ftile > p{margin:0;font-size:var(--fs-sm);line-height:1.6;color:var(--text)}
.ftile__src{margin:auto 0 0!important;padding-top:.6rem;font-size:var(--fs-xs);line-height:1.5;color:var(--text-mut)}
.ftile__src a{color:var(--deep-teal)}

/* 39.7 Membership band ---------------------------------------------------- */
.fcta{position:relative;isolation:isolate;overflow:hidden;background:var(--forest-deep);color:#fff}
.fcta::before{content:"";position:absolute;inset:0;z-index:-1;background:radial-gradient(circle,rgba(232,200,106,.16) 1.6px,transparent 1.8px) 0 0/22px 22px;-webkit-mask-image:radial-gradient(ellipse 60% 100% at 100% 50%,#000 0%,transparent 75%);mask-image:radial-gradient(ellipse 60% 100% at 100% 50%,#000 0%,transparent 75%)}
.fcta__in{display:grid;gap:2rem;align-items:center;padding-top:clamp(3.5rem,2.5rem + 3vw,5.5rem);padding-bottom:clamp(3.5rem,2.5rem + 3vw,5.5rem)}
@media (min-width:62em){.fcta__in{grid-template-columns:minmax(0,1.3fr) auto;gap:3rem}}
.fcta .feyebrow{color:var(--gold-lum)}   /* 7.55:1 */
.fcta .fh2{color:#fff}
.fcta p:not(.feyebrow):not(.fbtns){color:#D3DCD8;font-size:var(--fs-lede);line-height:1.5;margin:1rem 0 0;max-width:36em}   /* 8.77:1 */
.fcta .fbtns{margin:0}
.fcta :focus-visible{outline-color:var(--gold-lum)}

/* 39.8 Page heads (page.php, template-parts/article-masthead.php) ---------- */
.artmast{position:relative;overflow:hidden;background:linear-gradient(180deg,var(--s-band) 0%,#fff 100%);border-bottom:1px solid var(--hair);padding-top:clamp(2.25rem,1.6rem + 2vw,3.5rem);padding-bottom:clamp(2.5rem,1.8rem + 2.4vw,4rem)}
.artmast::before{content:"";position:absolute;inset:0;pointer-events:none;background:radial-gradient(circle,rgba(14,143,138,.13) 1.6px,transparent 1.8px) 0 0/22px 22px;-webkit-mask-image:radial-gradient(ellipse 55% 90% at 96% 0%,#000 0%,transparent 70%);mask-image:radial-gradient(ellipse 55% 90% at 96% 0%,#000 0%,transparent 70%)}
.artmast > .shell{position:relative}
.artmast h1{font-family:var(--serif);font-weight:500;letter-spacing:-.02em;line-height:1.06;max-width:22ch}
.artmast .eyebrow{font-weight:600;letter-spacing:.16em;color:var(--gold-ink)}
.artmast .crumbs{margin-bottom:1.4rem}

/* 39.9 Footer --------------------------------------------------------------- */
.foot__cols{display:grid;gap:2.5rem}
@media (min-width:48em){.foot__cols{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}}
@media (min-width:75em){.foot__cols{grid-template-columns:minmax(0,1.25fr) minmax(0,3.2fr) minmax(0,1fr)}}
.foot__nav{display:grid;gap:2rem}
@media (min-width:36em){.foot__nav{grid-template-columns:repeat(3,minmax(0,1fr))}}
.foot p,.foot__ch span{color:#D4E0DA}   /* 6.90:1 on #0F5132 */
.foot a{color:#D4E0DA}
.foot a:hover{color:#fff}
.foot__h a{color:inherit;text-decoration:none}   /* the heading's own gold-lum, 5.75:1 */
.foot__h a:hover{color:#fff;text-decoration:underline;text-underline-offset:.18em}
.foot__ch .ic{color:var(--gold-lum)}

/* 39.10 Figure swap fix ----------------------------------------------------
   LIVE DEFECT FOUND 29 October 2026: on all six chart pages both drawings of
   each chart were shown, on every screen. `.eocpr-figure svg{display:block}`
   (specificity 0,1,1) outranked `.eocpr-fig--tall{display:none}` (0,1,0),
   so the portrait chart sat under the landscape one on a desktop and the
   landscape one under the portrait one on a phone. Raised here so the swap
   wins at both widths, and in print. */
.eocpr-figure svg.eocpr-fig--tall{display:none}
@media (max-width:767.98px){
  .eocpr-figure svg.eocpr-fig--wide{display:none}
  .eocpr-figure svg.eocpr-fig--tall{display:block}
}
@media print{
  .eocpr-figure svg.eocpr-fig--wide{display:none}
  .eocpr-figure svg.eocpr-fig--tall{display:block}
  .mega,.msrch,.fhero__dots,.fcta{display:none}
}

@media (prefers-reduced-motion:reduce){
  .mega{transition:none;transform:none}
}
/* Phones: the menu button must never be pushed off the edge. Measured at
   390px: brandmark 324px + 16px gap + 43px button = 383px against 353px of
   shell, so the button overflowed by 18px before 0.7.0 as well. */
.nav__wrap{flex:none}
.masthead .brandmark{min-width:0}
@media (max-width:479.98px){
  /* Newsreader sets wider than Source Serif did: 15px measured 276px. */
  .masthead .brandmark__l1{font-size:.84rem}
}
/* The phone menu panel hangs from the masthead row, not from the button, so
   it can never extend past the right edge of the screen (it did by 15px). */
.mnav{position:static}
.mnav__panel{right:var(--gutter);left:auto;width:min(calc(100vw - 2 * var(--gutter)),26rem);top:100%}

/* 39.11 The health-page template blocks, styled where they already are --
   CLAUDE.md §5 names Key facts and What you can do as required blocks on
   every health page, and §8 P1 #6 records that nothing emitted a treatment
   for them. These rules give both the Field callout treatment by matching
   the heading the converter already writes (id="key-facts",
   id="what-you-can-do", from page.php's id pass), so not one page of
   content changes and the live content hashes stay valid. */
.prose > h2[id^="key-facts"] + ul:not([class]){
  list-style:none;padding:clamp(1.25rem,1rem + .8vw,1.75rem) clamp(1.25rem,1rem + .8vw,1.9rem);
  background:var(--s-teal);border-left:3px solid var(--gold);border-radius:0 var(--f-r) var(--f-r) 0;gap:.85rem;
}
.prose > h2[id^="key-facts"] + ul:not([class]) > li{position:relative;padding-left:1.35rem;color:var(--text)}   /* 12.23:1 */
.prose > h2[id^="key-facts"] + ul:not([class]) > li::before{content:"";position:absolute;left:0;top:.62em;width:.5rem;height:.5rem;border-radius:2px;background:var(--deep-teal)}
.prose > h2[id^="key-facts"] + ul a{color:var(--forest)}   /* 8.20:1 on the teal tint */
.prose > h2[id^="what-you-can-do"] + ul:not([class]),
.prose > h2[id^="what-you-can-do"] + ol:not([class]){list-style:none;padding:0;gap:.7rem}
.prose > h2[id^="what-you-can-do"] + ul:not([class]) > li,
.prose > h2[id^="what-you-can-do"] + ol:not([class]) > li{
  position:relative;padding:1rem 1.15rem 1rem 3.1rem;background:#fff;border:1px solid var(--hair);border-radius:var(--f-r);
}
.prose > h2[id^="what-you-can-do"] + ul:not([class]) > li::before,
.prose > h2[id^="what-you-can-do"] + ol:not([class]) > li::before{
  content:"";position:absolute;left:1rem;top:1.1rem;width:1.4rem;height:1.4rem;border-radius:50%;
  background:var(--s-teal) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230B6B66' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12l5 5 9-10'/%3E%3C/svg%3E") center/.8rem no-repeat;
}
@media print{
  .prose > h2[id^="key-facts"] + ul:not([class]){background:none;border-left-color:#000}
}
.foot__h a{font-size:inherit}
.mega__g,.foot__brand,.foot__contact{min-width:0}
@media (max-width:479.98px){
  .masthead .brandmark__l1,.masthead .brandmark__l2{display:block}
}
@media (max-width:400px){
  /* A 390px phone with a classic scrollbar has 371px; the lockup must still
     leave the menu button on screen. */
  .masthead .brandmark{--sym:1.8rem;gap:.4rem}
  .masthead .brandmark__l1{font-size:.76rem}
  .masthead .brandmark__l2{font-size:.56rem}
  .masthead__in{gap:.5rem}
}
@media (max-width:359.98px){
  /* 320px: the name takes two lines rather than pushing the menu off screen. */
  .masthead .brandmark__l1{white-space:normal;font-size:.8rem;line-height:1.1;max-width:9.5em}
  .masthead .brandmark__l2{margin-top:.2em}
}
