/* =================================================================
   Donum Foundation
   One stylesheet. No framework, no reset library, no webfont.

   Black and white, and nothing else (spec 12, brand/BRAND.md). The
   wordmark takes its colour from the text around it, which is why the
   whole palette is a greyscale: there is no brand colour for it to
   fight with.

   WRITTEN IN LOGICAL PROPERTIES. padding-inline, margin-inline,
   inset-inline-start, border-inline-start. Arabic is in the language
   table from day one (spec 3), and `left`/`right` is the thing that is
   cheap to get right now and a week of work to unpick later.
   ================================================================= */

/* ---------- Tokens ----------

   Light lives here as plain values. Dark overrides them further down,
   under `prefers-color-scheme: dark` and again under
   `[data-theme="dark"]`. Two blocks, on purpose: see the note on the
   dark block for what the clever one-liner actually does on a phone.
   ---------------------------------------------------------------- */
:root {
  /* No webfont. One HTTP request the people this site is for do not
     have to pay for on a metered connection (spec 3). */
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Helvetica, Arial, sans-serif;

  /* Both schemes are allowed here; the switch narrows it to one. */
  color-scheme: light dark;

  /* Three levels of ink, and every one of them clears 4.5:1 on every
     ground it is used on, in both modes. Checked, not eyeballed. */
  --ink: #131314;
  --ink-2: #55555c;
  --ink-3: #6a6a72;
  --paper: #ffffff;
  --paper-2: #f4f4f5;
  --hair: rgba(0, 0, 0, .14);
  --hair-soft: rgba(0, 0, 0, .06);

  --nav-h: 56px;
  --pill: 980px;

  /* ---------- Motion ----------
     Two curves and four durations, and everything uses them. --ease
     decelerates hard, for things arriving. --ease-soft is even, for a
     colour or a shadow, where a dramatic curve reads as a twitch.
     Duration is chosen by how far the thing travels: a colour in
     dur-1, a small element in dur-2, a panel crossing the screen in
     dur-3, and dur-4 for the one or two things that should feel
     deliberate. */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-soft: cubic-bezier(0.25, 0.1, 0.25, 1);
  --dur-1: .18s;
  --dur-2: .28s;
  --dur-3: .42s;
  --dur-4: .6s;

  --container: 1024px;
  --container-wide: 1220px;
  --gutter: 22px;
  /* Red for errors, and nothing else (Joel, 14 October 2026, D-373; spec 12). */
  --danger: #b3261e;
  /* Royal blue for a team title, the site's own accent (Joel, 17 October 2026, R-131, D-387):
     6.5 to 1 on white here, 9 to 1 on black in dark mode, and a blue that the common
     kinds of colour blindness still see as blue. Never the only signal: each says what it is.
     No longer the verified tick's own colour (below): item 7 of the handles/seal/titles
     spec, 18 October 2026, D-408, moved the tick to its own gold, so the two marks read as
     two separate things rather than one colour doing both jobs. */
  --verified: #2f55d4;
  /* Gold for the verified seal alone (D-408): a deep amber here, 5.9 to 1 on white; a
     brighter gold in dark mode, 13.3 to 1 on black (both checked against the real
     backgrounds, not assumed). The check mark inside is drawn in the page's own paper
     colour, which already contrasts with gold in both directions. */
  --seal: #8a5a00; --seal-mark: #ffffff;
}

/* The switch writes one of these onto <html>. Nothing else changes. */
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

/* ---------- Section grounds ----------
   Pages alternate grounds for rhythm. In dark mode the rhythm is kept
   but the whole range shifts down, so a "dark" section is still a
   change of ground rather than a light panel in a dark page.
   ---------------------------------------------------------------- */
.theme-light { --danger: #b3261e; --verified: #2f55d4; --seal: #8a5a00; --seal-mark: #ffffff; --bg: #ffffff; --fg: #131314; --fg-2: #6a6a72; --line: rgba(0,0,0,.08); --card: #ffffff; --card-line: rgba(0,0,0,.12); }
.theme-muted { --danger: #b3261e; --verified: #2f55d4; --seal: #8a5a00; --seal-mark: #ffffff; --bg: #f4f4f5; --fg: #131314; --fg-2: #6a6a72; --line: rgba(0,0,0,.10); --card: #ffffff; --card-line: rgba(0,0,0,.09); }
.theme-dark  { --danger: #ff8a80; --verified: #8aa6ff; --seal: #ffc531; --seal-mark: #131316; --bg: #000000; --fg: #f5f5f7; --fg-2: #a6a6ad; --line: rgba(255,255,255,.16); --card: #131316; --card-line: rgba(255,255,255,.12); }

/* ══════════════════════════════════════════════════════════════════
   DARK

   Plain overrides, deliberately NOT `light-dark()`.

   A custom property accepts any value and the browser does not
   validate it at parse time, so writing `--ink: #131314;` followed by
   `--ink: light-dark(…);` does not leave a fallback behind: the second
   declaration always wins and stores a function an older browser
   cannot resolve. Every `color: var(--ink)` then becomes invalid at
   computed-value time, which for an inherited property means INHERIT,
   not fall back. On older WebKit that is white text on white.

   So: no function, two triggers, works everywhere.
   ══════════════════════════════════════════════════════════════════ */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ink: #f5f5f7;
    --ink-2: #a6a6ad;
    --ink-3: #8e8e96;
    --paper: #000000;
    --paper-2: #0c0c0d;
    --hair: rgba(255,255,255,.18);
    --hair-soft: rgba(255,255,255,.09);
    --danger: #ff8a80; --verified: #8aa6ff; --seal: #ffc531; --seal-mark: #131316;
  }
  :root:not([data-theme="light"]) .theme-light { --danger: #ff8a80; --verified: #8aa6ff; --seal: #ffc531; --seal-mark: #131316; --bg: #000000; --fg: #f5f5f7; --fg-2: #a6a6ad; --line: rgba(255,255,255,.12); --card: #121214; --card-line: rgba(255,255,255,.12); }
  :root:not([data-theme="light"]) .theme-muted { --danger: #ff8a80; --verified: #8aa6ff; --seal: #ffc531; --seal-mark: #131316; --bg: #0c0c0d; --fg: #f5f5f7; --fg-2: #a6a6ad; --line: rgba(255,255,255,.12); --card: #161618; --card-line: rgba(255,255,255,.11); }
  :root:not([data-theme="light"]) .theme-dark  { --danger: #ff8a80; --verified: #8aa6ff; --seal: #ffc531; --seal-mark: #131316; --bg: #161617; --fg: #f5f5f7; --fg-2: #a6a6ad; --line: rgba(255,255,255,.16); --card: #1f1f22; --card-line: rgba(255,255,255,.12); }
}

:root[data-theme="dark"] {
  --ink: #f5f5f7;
  --ink-2: #a6a6ad;
  --ink-3: #8e8e96;
  --paper: #000000;
  --paper-2: #0c0c0d;
  --hair: rgba(255,255,255,.18);
  --hair-soft: rgba(255,255,255,.09);
  --danger: #ff8a80; --verified: #8aa6ff; --seal: #ffc531; --seal-mark: #131316;
}
:root[data-theme="dark"] .theme-light { --danger: #ff8a80; --verified: #8aa6ff; --seal: #ffc531; --seal-mark: #131316; --bg: #000000; --fg: #f5f5f7; --fg-2: #a6a6ad; --line: rgba(255,255,255,.12); --card: #121214; --card-line: rgba(255,255,255,.12); }
:root[data-theme="dark"] .theme-muted { --danger: #ff8a80; --verified: #8aa6ff; --seal: #ffc531; --seal-mark: #131316; --bg: #0c0c0d; --fg: #f5f5f7; --fg-2: #a6a6ad; --line: rgba(255,255,255,.12); --card: #161618; --card-line: rgba(255,255,255,.11); }
:root[data-theme="dark"] .theme-dark  { --danger: #ff8a80; --verified: #8aa6ff; --seal: #ffc531; --seal-mark: #131316; --bg: #161617; --fg: #f5f5f7; --fg-2: #a6a6ad; --line: rgba(255,255,255,.16); --card: #1f1f22; --card-line: rgba(255,255,255,.12); }

/* The cross-fade on a deliberate tap. theme.js sets data-switching for
   ~420ms, comfortably past this, so the fade is never cut off. It is
   NOT set on the first call, before paint: there is nothing to fade
   from, and animating it would fade the site up from blank on every
   single load. */
:root[data-switching] * {
  transition: background-color var(--dur-2) var(--ease-soft),
              color var(--dur-2) var(--ease-soft),
              border-color var(--dur-2) var(--ease-soft) !important;
}
@media (prefers-reduced-motion: reduce) {
  :root[data-switching] * { transition: none !important; }
}

/* ---------- Base ---------- */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.47;
  letter-spacing: -0.011em;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img, svg { max-width: 100%; }
[hidden] { display: none !important; }

/* No brand colour means links cannot be "the blue ones". They are the
   underlined ones, which is what a link was before colour, and which
   survives being printed, photocopied and read by somebody who cannot
   separate the hues. */
a { color: inherit; text-decoration: underline; text-underline-offset: 0.18em; text-decoration-thickness: from-font; }
@media (hover: hover) and (pointer: fine) {
  a:hover { text-decoration-thickness: 2px; }
}

h1, h2, h3, h4 { margin: 0; font-weight: 600; letter-spacing: -0.018em; line-height: 1.08; }
p { margin: 0; }
ul, ol { margin: 0; padding: 0; }

::selection { background: var(--ink); color: var(--paper); }

/* The focus ring takes the ground's foreground, so it is dark on a
   light section and light on a dark one. `currentColor` alone would
   be wrong on a filled button, where the text is the INVERSE of the
   page the ring is drawn on. */
:focus-visible {
  outline: 3px solid var(--fg, var(--ink));
  outline-offset: 3px;
  border-radius: 4px;
}

.u-visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

.skip-link {
  position: absolute; top: -60px; inset-inline-start: 12px; z-index: 100;
  background: var(--paper); color: var(--ink); padding: 10px 16px;
  border-radius: 10px; border: 1px solid var(--hair);
  text-decoration: none;
  transition: top var(--dur-1) var(--ease);
}
.skip-link:focus { top: calc(var(--nav-h) + 8px); }

/* ══════════════════════════════════════════════════════════════════
   THE BAR. Two things, at every width: the wordmark and the menu.
   ══════════════════════════════════════════════════════════════════ */
.sitehead {
  position: sticky; top: 0; z-index: 60;
  /* Solid, and deliberately not frosted. A translucent bar with a
     backdrop filter takes its colour from whatever is passing
     underneath, and the wordmark is drawn in currentColor: it would
     sit on a moving grey wash instead of on paper. */
  background: var(--paper);
  color: var(--ink);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur-2) var(--ease-soft);
}
.sitehead.is-scrolled { border-bottom-color: var(--hair); }

.sitehead__inner {
  max-width: var(--container-wide);
  margin: 0 auto;
  padding-inline: var(--gutter);
  height: var(--nav-h);
  display: flex; align-items: center; gap: 16px;
}

/* ── THE WORDMARK IS THE THEME SWITCH ─────────────────────────────
 *
 * A real <button>, because it does something. It is not a link home:
 * home is the first row of the drawer and it is in the footer too.
 *
 * SIZE IS NOT A MATTER OF TASTE HERE. BRAND.md sets a floor of 96px
 * wide, below which the underline and the F go too thin to read. 104
 * is that floor plus a little air. The height follows from the art's
 * 3.41:1 and is never set alongside the width, because setting both
 * is how a wordmark gets stretched.
 * ───────────────────────────────────────────────────────────────── */
.sitehead__logo {
  flex: none;
  margin: 0;
  /* Clear space, BRAND.md: at least the thickness of the underline on
     every side before anything else. The underline is ~11% of the
     art's height, so at 30px tall that is ~3.4px; 8 is comfortably
     past it and gives the tap target its height. */
  padding: 8px;
  margin-inline-start: -8px;
  background: none; border: 0; cursor: pointer;
  color: var(--ink);
  display: inline-flex; align-items: center;
  border-radius: 8px;
  -webkit-tap-highlight-color: transparent;
  transition: opacity var(--dur-1) var(--ease-soft);
}
.sitehead__logo .wordmark {
  /* Width only. Never both.

     The lockup reads "Donum Foundation" and is 7.01:1, so the floor that
     keeps the underline and the F from going thin is 198px, not the 96px
     that applied to the short mark. 198 plus the 44px menu button plus the
     gutters is 286 of a 320px screen, which is the narrowest phone worth
     designing for and the reason this does not go any smaller. */
  width: 198px;
  height: auto;
  display: block;
  transition: transform var(--dur-3) var(--ease);
}
@media (min-width: 460px) { .sitehead__logo .wordmark { width: 228px; } }

/* The full name stays at every width the bar can hold it, which is every
   phone worth designing for. What gives instead is the BAR's own padding,
   not the wordmark: at 340px and below the bar tightens to a 12px gutter,
   which buys the 20px the lockup needs beside two 44px controls. The page's
   content keeps the full gutter; only the bar tightens.

   Measured, not assumed. The first version of this cropped back to the short
   mark below 379px, a threshold picked without checking where the overflow
   actually started, and it fired on a 375px iPhone, which is most of them. */
@media (max-width: 340px) {
  .sitehead__inner { padding-inline: 12px; gap: 10px; }
  .sitehead__logo { margin-inline-start: -6px; padding-inline: 6px; }
}
@media (hover: hover) and (pointer: fine) {
  .sitehead__logo:hover { opacity: .6; }
}
.sitehead__logo:active .wordmark { transform: scale(.94); }
@media (prefers-reduced-motion: reduce) {
  .sitehead__logo:active .wordmark { transform: none; }
}

.sitehead__menu {
  margin-inline-start: auto;
  width: 44px; height: 44px; padding: 0; flex: none;
  background: none; border: 0; cursor: pointer; color: var(--ink);
  display: grid; place-items: center; border-radius: 10px;
  -webkit-tap-highlight-color: transparent;
  transition: background var(--dur-1) var(--ease-soft);
}
@media (hover: hover) and (pointer: fine) {
  .sitehead__menu:hover { background: var(--hair-soft); }
}
.sitehead__menu:active { background: var(--hair); }

/* How many things are new in My account (R-143): on the menu button and on
   the My account row. Filled in by site.js and hidden while it is nought, so
   a page served from a cache never shows anybody's count. The colours are
   the ink and the paper reversed, so it reads in both themes, and the number
   is the message: nothing depends on telling one colour from another. */
.count-badge {
  display: inline-grid; place-items: center;
  min-width: 20px; height: 20px; padding: 0 6px; border-radius: 10px;
  background: var(--ink); color: var(--paper);
  font-size: 12px; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums;
  margin-inline-start: 8px;
}
.count-badge[hidden] { display: none; }
.sitehead__menu { position: relative; }
.count-badge--corner { position: absolute; top: 2px; inset-inline-end: 0; margin: 0; min-width: 18px; height: 18px; font-size: 11px; padding: 0 5px; }

/* Three bars that become a cross while the drawer is open. CSS rather
   than SVG because they have to come apart, but 16 units wide and 1.7
   thick like every icon, so they carry the same weight. */
.bars { display: block; position: relative; width: 18px; height: 12.4px; }
.bars i {
  position: absolute; inset-inline-start: 0; width: 18px; height: 1.8px; border-radius: 1px;
  background: currentColor;
  transition: transform var(--dur-3) var(--ease), opacity var(--dur-1) var(--ease-soft),
              top var(--dur-1) var(--ease);
}
.bars i:nth-child(1) { top: 0; }
.bars i:nth-child(2) { top: 5.3px; }
.bars i:nth-child(3) { top: 10.6px; }
/* Into a cross: the outer two slide to the middle, then turn. The
   middle one shrinks towards its centre rather than fading, so it
   reads as absorbed into the other two instead of blinking out. */
.sitehead__menu[aria-expanded="true"] .bars i:nth-child(1) { top: 5.3px; transform: rotate(45deg); }
.sitehead__menu[aria-expanded="true"] .bars i:nth-child(2) { opacity: 0; transform: scaleX(.2); }
.sitehead__menu[aria-expanded="true"] .bars i:nth-child(3) { top: 5.3px; transform: rotate(-45deg); }

/* ══════════════════════════════════════════════════════════════════
   THE DRAWER, in from the inline start.
   ══════════════════════════════════════════════════════════════════ */
.drawer { position: fixed; inset: 0; z-index: 80; }
.drawer[hidden] { display: none !important; }

.drawer__scrim {
  position: absolute; inset: 0;
  background: var(--paper);
  opacity: 0; transition: opacity var(--dur-2) var(--ease-soft);
}
.drawer.is-open .drawer__scrim { opacity: 1; }

.drawer__panel {
  position: absolute; inset-block: 0; inset-inline: 0 auto;
  width: min(430px, 92vw);
  display: flex; flex-direction: column;
  background: var(--paper);
  transform: translateX(-100%);
  transition: transform var(--dur-3) var(--ease);
  padding-top: env(safe-area-inset-top, 0px);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  overscroll-behavior: contain;
}
[dir="rtl"] .drawer__panel { transform: translateX(100%); }
.drawer.is-open .drawer__panel { transform: none; }

.drawer__head {
  flex: none; height: var(--nav-h);
  display: flex; align-items: center; justify-content: space-between;
  padding-inline: var(--gutter) 12px;
  border-bottom: 1px solid var(--hair-soft);
}
.drawer__brand {
  font-size: 15px; font-weight: 600; letter-spacing: -0.015em; color: var(--ink);
}
.drawer__close {
  width: 40px; height: 40px; padding: 0;
  background: none; border: 0; cursor: pointer; color: var(--ink-2);
  display: grid; place-items: center; border-radius: 10px;
  transition: background var(--dur-1) var(--ease-soft), color var(--dur-1) var(--ease-soft);
}
@media (hover: hover) and (pointer: fine) {
  .drawer__close:hover { background: var(--hair-soft); color: var(--ink); }
}
.drawer__close svg { width: 20px; height: 20px; }

.drawer__nav {
  flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: 18px var(--gutter) 40px;
}

/* ---------- The way back, and the way to help ----------
   First in the panel, above the labels for everything they are not,
   and shaped like rows rather than lines of text so they read as
   somewhere to go. */
.drawer__top { display: grid; gap: 10px; margin-bottom: 26px; }
.drawer__home {
  display: flex; align-items: center; gap: 12px;
  padding: 13px 14px;
  border-radius: 14px;
  background: var(--hair-soft);
  color: var(--ink); text-decoration: none;
  font-size: 17px; font-weight: 600; letter-spacing: -0.015em;
  transition: background var(--dur-1) var(--ease-soft);
}
/* The space before the groups is the block's own (.drawer__top), so it sits
   under whichever row is last: My account, or Donate from the day donations
   open (R-57). Every two rows are the same 10px apart. */
@media (hover: hover) and (pointer: fine) {
  .drawer__home:hover { background: var(--hair); }
}
.drawer__home-icon { display: grid; place-items: center; color: var(--ink-2); }
.drawer__home-icon svg { width: 21px; height: 21px; display: block; }
.drawer__home-label { flex: 1; }
.drawer__home .drawer__go { font-size: 22px; color: var(--ink-3); }
/* On the page itself it is where you already are, so it says so and
   stops pretending to be a way somewhere. */
.drawer__home.is-current { background: none; border: 1px solid var(--hair); color: var(--ink-2); }
.drawer__home.is-current .drawer__go { display: none; }
.drawer__home.is-current .drawer__home-label::after {
  content: "You are here"; margin-inline-start: 9px;
  font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--ink-3);
}

.drawer__label {
  font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--ink-3); margin-bottom: 8px;
}
.drawer__label--also { margin-top: 26px; }
.drawer__list, .drawer__also { list-style: none; margin: 0 0 22px; padding: 0; }
.drawer__also { margin-bottom: 0; }

/* Each row arrives a beat after the one above it: what the drawer as
   a whole is doing, repeated down the list. */
.drawer__item {
  opacity: 0; transform: translateX(-14px);
  transition: opacity var(--dur-3) var(--ease), transform var(--dur-3) var(--ease);
  transition-delay: calc(90ms + var(--i, 0) * 26ms);
}
[dir="rtl"] .drawer__item { transform: translateX(14px); }
.drawer.is-open .drawer__item { opacity: 1; transform: none; }
.drawer__label { transition: opacity var(--dur-3) var(--ease); }
@media (prefers-reduced-motion: reduce) {
  .drawer__item { opacity: 1; transform: none; transition: none; }
}

.drawer__link {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas: "name go" "line go";
  align-items: center;
  gap: 0 12px;
  padding: 11px 12px 13px;
  margin-inline: -12px;
  border-radius: 14px;
  color: var(--ink); text-decoration: none;
  transition: background var(--dur-1) var(--ease-soft);
}
@media (hover: hover) and (pointer: fine) {
  .drawer__link:hover { background: var(--hair-soft); }
}
.drawer__link:active { background: var(--hair); }
.drawer__name { grid-area: name; font-size: 21px; font-weight: 600; letter-spacing: -0.02em; line-height: 1.16; }
.drawer__line { grid-area: line; font-size: 13px; line-height: 1.38; color: var(--ink-2); margin-top: 4px; }
.drawer__go {
  grid-area: go;
  font-size: 22px; color: var(--ink-3);
  transition: transform var(--dur-2) var(--ease);
}
[dir="rtl"] .drawer__go { transform: scaleX(-1); }
@media (hover: hover) and (pointer: fine) {
  .drawer__link:hover .drawer__go { transform: translateX(3px); }
  [dir="rtl"] .drawer__link:hover .drawer__go { transform: scaleX(-1) translateX(3px); }
}
.drawer__link.is-current { background: var(--hair-soft); }
.drawer__link.is-current .drawer__name { text-decoration: underline; text-underline-offset: 0.18em; }

.drawer__also-link {
  display: flex; align-items: center; justify-content: space-between;
  padding: 11px 12px; margin-inline: -12px; border-radius: 12px;
  color: var(--ink-2); text-decoration: none; font-size: 15px;
  transition: background var(--dur-1) var(--ease-soft), color var(--dur-1) var(--ease-soft);
}
@media (hover: hover) and (pointer: fine) {
  .drawer__also-link:hover { background: var(--hair-soft); color: var(--ink); }
}
.drawer__also-link span { color: var(--ink-3); font-size: 20px; }
[dir="rtl"] .drawer__also-link span { transform: scaleX(-1); display: inline-block; }

body.is-locked { overflow: hidden; }

/* ---------- Layout ---------- */
.container { max-width: var(--container); margin: 0 auto; padding-inline: var(--gutter); }
.container--wide { max-width: var(--container-wide); }

.section { background: var(--bg); color: var(--fg); }
.section--pad-lg { padding-block: clamp(72px, 10vw, 128px); }
.section--pad-md { padding-block: clamp(56px, 8vw, 96px); }
.section--pad-sm { padding-block: clamp(28px, 4vw, 44px); }

.section__head { max-width: 760px; margin-bottom: clamp(36px, 5vw, 64px); }
.section__head--center { margin-inline: auto; text-align: center; }
.section__head--start { margin-inline: 0; }
.section__head:last-child { margin-bottom: 0; }

/* ---------- Type ---------- */
.headline {
  font-size: clamp(31px, 4.6vw, 54px);
  line-height: 1.08; letter-spacing: -0.02em; font-weight: 600;
  text-wrap: balance;
}
.headline--xl {
  font-size: clamp(37px, 6.1vw, 72px);
  line-height: 1.05; letter-spacing: -0.024em;
}
.subhead {
  margin-top: clamp(14px, 2vw, 22px);
  font-size: clamp(19px, 2.1vw, 26px);
  line-height: 1.3; letter-spacing: -0.005em; font-weight: 400;
  color: var(--fg-2, var(--ink-2));
  text-wrap: pretty;
}
.lead {
  margin-top: 18px;
  font-size: clamp(17px, 1.6vw, 20px);
  line-height: 1.45;
  color: var(--fg-2, var(--ink-2));
  text-wrap: pretty;
}
.kicker { margin: 0 0 12px; font-size: clamp(17px, 1.8vw, 20px); font-weight: 600; color: var(--fg-2, var(--ink-2)); }
.eyebrow {
  margin: 0 0 14px;
  font-size: 12px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
  color: var(--fg-2, var(--ink-2));
}

strong { font-weight: 600; }

/* ---------- Actions ---------- */
.actions { margin-top: clamp(20px, 3vw, 30px); display: flex; flex-wrap: wrap; align-items: center; gap: 14px 28px; }
.section__head--center .actions, .hero .actions { justify-content: center; }

.chevron-link {
  display: inline-flex; align-items: baseline; gap: 4px;
  font-size: clamp(17px, 1.5vw, 20px);
  text-decoration: underline; text-underline-offset: 0.18em;
}
.chevron-link span { font-size: 1.05em; transition: transform var(--dur-2) var(--ease); display: inline-block; text-decoration: none; }
[dir="rtl"] .chevron-link span { transform: scaleX(-1); }
@media (hover: hover) and (pointer: fine) {
  .chevron-link:hover span { transform: translateX(3px); }
  [dir="rtl"] .chevron-link:hover span { transform: scaleX(-1) translateX(3px); }
}

.pill {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: 8px 23px;
  border-radius: var(--pill);
  font-size: 17px; line-height: 1.24; letter-spacing: -0.01em;
  text-decoration: none;
  border: 1px solid transparent;
  transition: background var(--dur-1) var(--ease-soft), color var(--dur-1) var(--ease-soft),
              border-color var(--dur-1) var(--ease-soft);
}
.pill--filled { background: var(--fg, var(--ink)); color: var(--bg, var(--paper)); }
.pill--outline { border-color: var(--fg, var(--ink)); color: var(--fg, var(--ink)); }
@media (hover: hover) and (pointer: fine) {
  .pill:hover { text-decoration: none; }
  .pill--filled:hover { opacity: .82; }
  .pill--outline:hover { background: var(--fg, var(--ink)); color: var(--bg, var(--paper)); }
}

/* ---------- Hero ---------- */
.hero {
  background: var(--bg); color: var(--fg);
  padding-block: clamp(64px, 11vw, 132px) clamp(52px, 8vw, 96px);
  text-align: center;
}
.hero .container { max-width: 1040px; }
.hero--sm { padding-block: clamp(48px, 7vw, 80px) clamp(36px, 5vw, 60px); }
/* A light section straight after a small light heading starts at once: the
   heading's own bottom padding is the gap. The two paddings together stood
   92px apart on a phone (Joel, 11 October 2026: "Why is there this space").
   A muted section keeps its padding, inside its own band of colour. */
.hero--sm.theme-light + .section.theme-light { padding-block-start: 0; }
.hero .subhead { max-width: 720px; margin-inline: auto; }

/* ---------- Reveal ----------

   THE DEFAULT IS VISIBLE. The hidden state is scoped to `:root.js`, a
   class site.js adds as its very first statement and drops again if it
   throws. Blocked, failed to parse, errored on line one, or running on
   something that dislikes a feature it uses, the content is simply
   there, unanimated.

   This is also what makes spec 3's "reading pages must work with
   JavaScript disabled" true for free, rather than true in theory. */
.reveal { transition: opacity var(--dur-4) var(--ease), transform var(--dur-4) var(--ease); }
:root.js .reveal {
  opacity: 0; transform: translateY(20px);
  transition-delay: calc(var(--i, 0) * 60ms);
}
:root.js .reveal.is-in, :root.js .reveal.is-static { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  :root.js .reveal { opacity: 1 !important; transform: none !important; transition: none !important; }
}

/* ---------- The rules, and anything else numbered ---------- */
.ruleset { list-style: none; counter-reset: rule; display: grid; gap: clamp(26px, 4vw, 44px); }
.ruleset--compact { gap: clamp(20px, 3vw, 30px); }
.ruleset__item {
  counter-increment: rule;
  display: grid; grid-template-columns: auto 1fr; gap: 4px 18px;
  grid-template-areas: "num title" "num line";
}
.ruleset__item::before {
  content: counter(rule);
  grid-area: num;
  font-size: clamp(15px, 1.4vw, 17px); font-weight: 600;
  color: var(--fg-2);
  padding-top: .35em;
  font-variant-numeric: tabular-nums;
}
.ruleset__title { grid-area: title; font-size: clamp(21px, 2.2vw, 28px); letter-spacing: -0.02em; }
.ruleset__line { grid-area: line; margin-top: 8px; font-size: clamp(16px, 1.4vw, 18px); line-height: 1.5; color: var(--fg-2); }

/* ---------- Cards ---------- */
.cards { list-style: none; display: grid; gap: clamp(18px, 2.4vw, 26px); }
.cards--2 { grid-template-columns: repeat(2, 1fr); }
.cards--3 { grid-template-columns: repeat(3, 1fr); }
.card {
  background: var(--card);
  border: 1px solid var(--card-line);
  border-radius: 18px;
  padding: clamp(20px, 2.4vw, 28px);
}
.card__eyebrow { font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--fg-2); margin-bottom: 10px; }
.card__title { font-size: clamp(19px, 1.9vw, 23px); letter-spacing: -0.018em; }
.card__title a { text-decoration: none; }
/* The whole card is the target, but only the title is the link, so the
   accessible name stays the title rather than every word in the card. */
.card__title a::after { content: ""; position: absolute; inset: 0; }
.card { position: relative; }
@media (hover: hover) and (pointer: fine) {
  .card:hover { border-color: var(--fg-2); }
  .card:hover .card__title a { text-decoration: underline; }
}
.card__line { margin-top: 10px; font-size: 15px; line-height: 1.5; color: var(--fg-2); }
/* A planned project's label (Batch 9, R-87): words, never a colour alone. */
.card__label { display: inline-block; margin-bottom: 10px; padding: 3px 10px; border: 1px solid var(--card-line); border-radius: 999px; font-size: 12px; font-weight: 600; }
/* Open chances in groups ("Nakivale", "Donum Centre"), Batch 9. */
.chances__group { font-size: clamp(22px, 2.4vw, 28px); letter-spacing: -0.02em; margin: 0 0 18px; }
.cards + .chances__group { margin-top: 40px; }
.card__meta { margin-top: 14px; font-size: 13px; color: var(--fg-2); }
/* The way back (Joel, 11 October 2026): at the top of a page reached by a
   link on another page of this site, shown by the script. */
.back { padding-block: 14px 0; }
.back[hidden] { display: none; }
/* Joel, 11 October 2026 ("Why is there this space"): while Back is shown, the
   page's heading sits close under it, as the heading's own top padding had
   stood empty under Back. */
.back:not([hidden]) + .hero,
.back:not([hidden]) + #page-slot > .hero:first-child { padding-block-start: 12px; }
.back__link { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; font-weight: 600; text-decoration: none; color: var(--fg, var(--ink)); }
.back__link span[aria-hidden] { font-size: 22px; line-height: 1; }
@media (hover: hover) and (pointer: fine) { .back__link:hover { text-decoration: underline; } }

/* "Give to this project", kept in the bottom right corner while a chance's
   page is read (Joel, 11 October 2026). Under the bar, the menu and search.
   The script moves it away while the page's own button or the footer is on
   the screen, and it can never be reached while it is away. */
.give-float {
  position: fixed;
  inset-inline-end: max(16px, env(safe-area-inset-right));
  inset-block-end: max(16px, env(safe-area-inset-bottom));
  z-index: 50;
  box-shadow: 0 8px 28px rgba(0, 0, 0, .22);
  transition: opacity var(--dur-2, 200ms) var(--ease-soft, ease), transform var(--dur-2, 200ms) var(--ease-soft, ease),
              visibility 0s linear 0s;
}
.give-float.is-away {
  opacity: 0; transform: translateY(14px); visibility: hidden; pointer-events: none;
  transition: opacity var(--dur-2, 200ms) var(--ease-soft, ease), transform var(--dur-2, 200ms) var(--ease-soft, ease),
              visibility 0s linear var(--dur-2, 200ms);
}
@media (prefers-reduced-motion: reduce) { .give-float, .give-float.is-away { transition: none; } }
@media print { .give-float { display: none; } }

/* "On this page", the way back to the list (D-364): in the same corner as
   "Give to this project", above it when both are on the page so neither
   covers the other on a narrow phone, and in its place once that one moves
   away. The script shows it once the list is above the screen, and moves it
   away while the list or the footer is on the screen. */
.toc-return {
  position: fixed;
  inset-inline-end: max(16px, env(safe-area-inset-right));
  inset-block-end: max(16px, env(safe-area-inset-bottom));
  z-index: 50;
  gap: 6px; padding-inline: 18px;
  background: var(--bg, var(--paper));
  box-shadow: 0 8px 28px rgba(0, 0, 0, .18);
  transition: opacity var(--dur-2, 200ms) var(--ease-soft, ease), transform var(--dur-2, 200ms) var(--ease-soft, ease),
              inset-block-end var(--dur-2, 200ms) var(--ease-soft, ease), visibility 0s linear 0s;
}
.toc-return[hidden] { display: none; }
.give-float ~ .toc-return { inset-block-end: calc(max(16px, env(safe-area-inset-bottom)) + 56px); }
.give-float.is-away ~ .toc-return { inset-block-end: max(16px, env(safe-area-inset-bottom)); }
.toc-return.is-away {
  opacity: 0; transform: translateY(14px); visibility: hidden; pointer-events: none;
  transition: opacity var(--dur-2, 200ms) var(--ease-soft, ease), transform var(--dur-2, 200ms) var(--ease-soft, ease),
              visibility 0s linear var(--dur-2, 200ms);
}
@media (prefers-reduced-motion: reduce) { .toc-return, .toc-return.is-away { transition: none; } }
@media print { .toc-return { display: none; } }

/* Donate and Read more (Joel, 11 October 2026), above the card's own link,
   which covers the card, so each is its own target. */
.card__actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 18px; position: relative; z-index: 1; }
.card__actions .pill { flex: 1 1 auto; }
.card--chance .actions { position: relative; z-index: 1; }
@media (max-width: 860px) { .cards--3 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .cards--2, .cards--3 { grid-template-columns: 1fr; } }

/* ---------- Statistics ----------
   Non-negotiable 12: the source and the date are part of the figure,
   not a footnote under it, so they are inside the same box and they
   are never styled away to nothing. */
.stats { list-style: none; display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: clamp(22px, 3vw, 40px); }
.stat__value { font-size: clamp(34px, 4.4vw, 52px); font-weight: 600; letter-spacing: -0.025em; line-height: 1.04; }
.stat__label { margin-top: 10px; font-size: 16px; line-height: 1.45; color: var(--fg-2); }
.stat__source { margin-top: 10px; font-size: 12px; line-height: 1.5; color: var(--fg-2); }
.stat__source a { color: inherit; }

/* ---------- The honest empty state ---------- */
.empty {
  border: 1px dashed var(--card-line);
  border-radius: 18px;
  padding: clamp(28px, 4vw, 44px);
  text-align: center;
}
.empty__text { color: var(--fg-2); max-width: 46ch; margin-inline: auto; }
.empty .actions { justify-content: center; }

/* ---------- The line every story carries ---------- */
.gift-line {
  margin-top: clamp(28px, 4vw, 44px);
  padding-top: clamp(20px, 3vw, 28px);
  border-top: 1px solid var(--line);
  font-size: clamp(17px, 1.6vw, 20px); font-weight: 600;
}

/* ---------- Prose, for the pages written in Markdown ---------- */
.prose { max-width: 68ch; margin-inline: auto; font-size: clamp(17px, 1.5vw, 19px); line-height: 1.62; }
.prose > * + * { margin-top: 1.15em; }
.prose h2 { font-size: clamp(24px, 2.6vw, 32px); margin-top: 1.9em; letter-spacing: -0.02em; }
.prose h3 { font-size: clamp(19px, 2vw, 23px); margin-top: 1.7em; }
.prose ul, .prose ol { padding-inline-start: 1.3em; display: grid; gap: .5em; }
.prose li { line-height: 1.55; }
.prose blockquote {
  margin-inline: 0; padding-inline-start: 1.1em;
  border-inline-start: 3px solid var(--line);
  color: var(--fg-2);
}
.prose hr { border: 0; border-top: 1px solid var(--line); margin-block: 2.2em; }

/* ---------- Private preview banner (spec 2) ----------
   It is a statement of fact about the site, not decoration, so it sits
   above everything and says the same thing on every page. It goes away
   on its own when SITE_PUBLIC is switched on. */
.private-note {
  background: var(--ink); color: var(--paper);
  font-size: 13px; line-height: 1.45;
  padding-block: 9px;
}
.private-note b { font-weight: 600; }

/* ---------- Footer ---------- */
.footer { background: var(--paper-2); color: var(--ink-2); padding-block: 44px 30px; font-size: 13px; line-height: 1.55; }
.footer__note { max-width: 78ch; padding-bottom: 22px; border-bottom: 1px solid var(--hair); color: var(--ink-3); }
.footer__cols { display: grid; grid-template-columns: repeat(3, 1fr); gap: 26px; padding-block: 28px; }
.footer__col-title { font-size: 13px; font-weight: 600; color: var(--ink); margin-bottom: 10px; }
.footer__col ul { list-style: none; display: grid; gap: 9px; }
.footer__col a { color: var(--ink-2); text-decoration: none; }
@media (hover: hover) and (pointer: fine) {
  .footer__col a:hover { color: var(--ink); text-decoration: underline; }
}
.footer__bar { padding-top: 20px; border-top: 1px solid var(--hair); color: var(--ink-3); }
.footer__copy { margin-bottom: 8px; }
.footer__registration { margin-bottom: 8px; }
.footer__theme { margin-bottom: 8px; }
.footer__legal { display: flex; flex-wrap: wrap; align-items: center; row-gap: 4px; }
.footer__legal a { color: var(--ink-3); white-space: nowrap; text-decoration: none; }
@media (hover: hover) and (pointer: fine) {
  .footer__legal a:hover { color: var(--ink); text-decoration: underline; }
}
/* ::after on every link but the last, NOT ::before on every link but
   the first. The generated box lives inside its own anchor either way,
   so a divider can never be separated from the link it belongs to,
   which on a phone is the difference between a second line reading
   "Terms | Donation policy" and one reading "| Terms | Donation
   policy" with an orphan slash in front. */
.footer__legal a:not(:last-child)::after {
  content: "|";
  margin-inline: 10px;
  color: var(--hair);
  pointer-events: none;
  display: inline-block;
  text-decoration: none;
}
@media (max-width: 700px) { .footer__cols { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 420px) { .footer__cols { grid-template-columns: 1fr; } }

/* ---------- 200% text size (spec 3, WCAG 2.1 AA) ----------
   Nothing above uses a fixed height for anything that holds text, and
   the bar is the one exception, so it is the one thing that needs to
   be told to grow. */
@media (max-width: 500px) {
  .sitehead__inner { gap: 8px; }
}

/* ---------- Sample content (spec 2) ----------
   Visible, on the page, not a note in the HTML. Somebody reading a preview on
   a phone has to be able to tell at a glance that a story is composed rather
   than somebody's actual life. It goes away when the sample data is purged,
   and the launch check refuses to pass while any of it remains. */
.sample-mark {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 10px;
  margin-bottom: clamp(22px, 3vw, 32px);
  padding: 12px 16px;
  border: 1px dashed var(--card-line);
  border-radius: 12px;
  font-size: 13px; line-height: 1.5; color: var(--fg-2);
}
.sample-mark__tag {
  flex: none;
  background: var(--fg); color: var(--bg);
  font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  padding: 3px 8px; border-radius: 999px;
}

/* ---------- The story filter, as a dropdown ----------
   A native <details>, so it opens and closes with no JavaScript, and every
   option inside is a real link somebody can share. */
.shockmenu {
  margin-bottom: clamp(24px, 3vw, 34px);
  border: 1px solid var(--card-line);
  border-radius: 14px;
  background: var(--card);
}
.shockmenu__summary {
  /* The label sits above the value rather than beside it. Side by side, a
     long option like "A visa, permit or asylum claim lost or refused" has
     nowhere to go on a phone and wraps into the label. */
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 2px 12px;
  padding: 13px 18px;
  cursor: pointer;
  list-style: none;
  border-radius: 14px;
}
.shockmenu__summary::-webkit-details-marker { display: none; }
.shockmenu__summary::after {
  content: "";
  grid-column: 2; grid-row: 1 / span 2;
  flex: none;
  width: 9px; height: 9px;
  border-right: 2px solid var(--fg-2);
  border-bottom: 2px solid var(--fg-2);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform var(--dur-2) var(--ease);
}
.shockmenu[open] .shockmenu__summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.shockmenu__label {
  grid-column: 1;
  font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--fg-2);
}
.shockmenu__value {
  grid-column: 1;
  font-size: 17px; font-weight: 600; letter-spacing: -0.018em; line-height: 1.25;
}
.shockmenu__panel {
  border-top: 1px solid var(--line);
  padding: 8px 18px 18px;
  max-height: 60vh; overflow-y: auto; overscroll-behavior: contain;
}
.shockmenu__group { margin-top: 18px; }
.shockmenu__grouplabel {
  font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--fg-2); margin-bottom: 6px;
}
.shockmenu__list { list-style: none; display: grid; gap: 1px; }
.shockmenu__link, .shockmenu__none {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  padding: 10px 12px; margin-inline: -12px; border-radius: 10px;
  font-size: 16px; text-decoration: none; color: var(--fg);
  transition: background var(--dur-1) var(--ease-soft);
}
@media (hover: hover) and (pointer: fine) {
  .shockmenu__link:hover { background: var(--line); text-decoration: none; }
}
.shockmenu__link.is-current { background: var(--line); font-weight: 600; }
/* Listed, but nothing under it yet. Shown rather than hidden: somebody
   scanning for what happened to them should find it here even when it is
   empty. */
.shockmenu__none { color: var(--fg-2); opacity: .55; }
.shockmenu__count {
  flex: none;
  font-size: 12px; font-variant-numeric: tabular-nums; color: var(--fg-2);
}

/* ---------- Progress on a chance ---------- */
.progress { margin-top: 16px; }
.progress__bar {
  display: block; width: 100%; height: 8px;
  appearance: none; -webkit-appearance: none; border: 0; border-radius: 999px;
  background: var(--line); color: var(--fg); overflow: hidden;
}
.progress__bar::-webkit-progress-bar { background: var(--line); border-radius: 999px; }
.progress__bar::-webkit-progress-value { background: var(--fg); border-radius: 999px; }
.progress__bar::-moz-progress-bar { background: var(--fg); border-radius: 999px; }
.progress__text { margin-top: 9px; font-size: 13px; color: var(--fg-2); }
.progress__text strong { color: var(--fg); }

/* ---------- A story, read ---------- */
.map-template { max-width: 68ch; margin-inline: auto; }
.map-template__q + .map-template__q { margin-top: clamp(34px, 5vw, 56px); }
.map-template__title {
  font-size: clamp(19px, 2vw, 24px); letter-spacing: -0.018em;
  color: var(--fg-2);
}
.map-template__body {
  margin-top: 14px;
  font-size: clamp(17px, 1.6vw, 20px); line-height: 1.62;
  white-space: pre-line;
}
/* A lesson (25 October 2026, part 2): what life taught, drawn large as the story's opening line. */
.map-template__q--lesson .map-template__title { font-size: 15px; letter-spacing: 0; }
.map-template__lesson {
  margin-top: 10px;
  font-size: clamp(24px, 3.2vw, 36px); line-height: 1.3; letter-spacing: -0.02em; font-weight: 600;
  white-space: pre-line;
}
.story-foot { max-width: 68ch; margin-inline: auto; }
.story-foot__note { margin-top: 18px; font-size: 14px; color: var(--fg-2); }

/* ---------- Comments ---------- */
.comments { list-style: none; max-width: 68ch; margin-inline: auto; display: grid; gap: 18px; }
/* Where "back to the comments" and a new comment land (D-430), clear of the bar. */
.comments__region, .comments__region .comment, .comments__region #comment-form, .comments__region #reactions {
  scroll-margin-top: calc(var(--nav-h) + 16px);
}
.comment {
  background: var(--card); border: 1px solid var(--card-line);
  border-radius: 16px; padding: 18px 20px;
}
.comment__who { font-size: 13px; font-weight: 600; color: var(--fg-2); }
/* The verified tick and a team title (R-131, R-134, D-387). The tick is a plain
   circle and check drawn here, not anybody's badge. */
/* Sized and aligned to the capital letters of the name beside it (item 7,
   D-408), so it reads as one size next to a byline's larger text and a
   comment's smaller one, rather than one fixed pixel size everywhere. */
.verified { display: inline-flex; vertical-align: baseline; margin-inline-start: 4px; color: var(--seal); }
.verified svg { width: 0.78em; height: 0.78em; display: block; }
.team-title { display: inline-block; margin-inline-start: 6px; padding: 0 8px; border: 1px solid var(--verified); border-radius: 999px; font-size: 12px; font-weight: 600; line-height: 1.6; color: var(--verified); }
.comment__body { margin-top: 8px; line-height: 1.55; }
.comments__empty { color: var(--fg-2); text-align: center; }

/* ---------- A chance ---------- */
.chance {
  display: grid; grid-template-columns: 1.4fr 1fr; gap: clamp(28px, 5vw, 56px);
  align-items: start;
}
@media (max-width: 820px) { .chance { grid-template-columns: 1fr; } }
.chance__title { font-size: clamp(21px, 2.2vw, 27px); letter-spacing: -0.02em; }
.chance__body { margin-top: 12px; line-height: 1.55; color: var(--fg-2); }
.chance__fund {
  background: var(--card); border: 1px solid var(--card-line);
  border-radius: 18px; padding: clamp(20px, 2.4vw, 26px);
}
.chance__closed { margin-top: 16px; font-size: 14px; color: var(--fg-2); }
.chance__concern { margin-top: 20px; font-size: 14px; color: var(--fg-2); }
.chance__concern a { color: inherit; }

.itemised { width: 100%; margin-top: 24px; border-collapse: collapse; font-size: 15px; }
.itemised caption {
  text-align: start; font-size: 12px; font-weight: 600;
  letter-spacing: .07em; text-transform: uppercase; color: var(--fg-2);
  padding-bottom: 10px;
}
.itemised th, .itemised td { padding: 11px 0; border-bottom: 1px solid var(--line); text-align: start; font-weight: 400; }
.itemised td { text-align: end; font-variant-numeric: tabular-nums; white-space: nowrap; }
.itemised tfoot th, .itemised tfoot td { font-weight: 600; border-bottom: 0; }

/* ---------- Dedications ---------- */
.dedications { max-width: 68ch; margin: clamp(36px, 5vw, 56px) auto 0; }
.dedications__title { font-size: clamp(19px, 2vw, 23px); letter-spacing: -0.018em; }
.dedication {
  margin: 18px 0 0; padding-inline-start: 1.1em;
  border-inline-start: 3px solid var(--line);
}
.dedication__line { font-size: clamp(17px, 1.6vw, 20px); line-height: 1.5; }
.dedication__who { margin-top: 7px; font-size: 14px; color: var(--fg-2); }
.dedications__note { margin-top: 20px; font-size: 14px; color: var(--fg-2); }

/* ---------- Figures ----------
   Donum's own counts, from follow-ups. "Did not hold" sits in the same row as
   the rest, at the same size, because a results page that shrinks its failures
   is not reporting honestly (rule 5). */
.figures {
  list-style: none;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: clamp(22px, 3vw, 36px);
}
.figures--wide { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
.figure__value {
  font-size: clamp(34px, 4.4vw, 52px); font-weight: 600;
  letter-spacing: -0.025em; line-height: 1.04; font-variant-numeric: tabular-nums;
}
.figure__label { margin-top: 8px; font-size: 14px; line-height: 1.4; color: var(--fg-2); }

.breakdown {
  width: 100%; margin-top: clamp(36px, 5vw, 56px);
  border-collapse: collapse; font-size: 15px;
}
.breakdown caption {
  text-align: start; font-size: 12px; font-weight: 600;
  letter-spacing: .07em; text-transform: uppercase; color: var(--fg-2);
  padding-bottom: 12px;
}
.breakdown th, .breakdown td {
  padding: 12px 0; border-bottom: 1px solid var(--line);
  text-align: start; font-weight: 400;
}
.breakdown thead th {
  font-size: 12px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--fg-2);
}
.breakdown td { text-align: end; font-variant-numeric: tabular-nums; }

/* A story card's excerpt is the fifth answer, so it wants room to breathe. */
.card--story .card__line, .card--chance .card__line { font-size: 14px; }

/* ---------- The home page ----------

   One column, read top to bottom. It replaces the `stance` family, whose
   section this page absorbed: Dr. Chekwech Gaudencia's words are now the
   quotation in the middle of the read rather than a band of their own.

   The markup is in `src/home-copy.mjs`, which renders `content/en/home.md`.
   Four kinds of line, and the difference between them is the whole design:
   a display line, a paragraph, Donum's quieter part under an example, and
   the quotation.
   ---------------------------------------------------------------- */
.home { max-width: 64ch; margin-inline: auto; }
.home > * + * { margin-top: 1.15em; }

/* The slogan, and the page's only heading.

   Deliberately the quieter of the first two lines. "A gift for another
   chance" is what this organisation is called, and a page needs one heading
   that names it: but the first thing a reader should MEET is "Every life is a
   journey", so the display line under this one is the larger. The outline and
   the reading order are both still right, which is why this is a type
   decision and not a markup one. */
.home__slogan {
  font-size: clamp(16px, 1.5vw, 18px);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.005em;
  color: var(--fg-2);
}
.home > .home__slogan + .home__display { margin-top: clamp(12px, 1.6vw, 18px); }

/* A display line. Read only these and the argument is still whole, which is
   what earns them the size. Still a <p>: seventeen headings would make the
   heading list useless to somebody navigating by it. */
.home > .home__display, .home__chapter > .home__display {
  margin-top: clamp(40px, 5.5vw, 76px);
  font-size: clamp(25px, 3.3vw, 40px);
  font-weight: 600;
  line-height: 1.14;
  letter-spacing: -0.022em;
  text-wrap: balance;
}

/* A REAL heading, for a page in these conventions that has sections. `/about/`
   has two; the home page has none and should not gain any, for the reason on
   the display line above.

   Set SMALLER than a display line and above it in the outline, which is the
   same deliberate disagreement between type size and markup that the slogan
   makes: the display lines are the argument and carry the size, the headings
   are the map and carry the structure. A screen reader gets the map; an eye
   gets the argument. */
.home__h2 {
  margin-top: clamp(48px, 6vw, 84px);
  margin-bottom: clamp(6px, 1vw, 12px);
  font-size: clamp(13px, 1.1vw, 15px);
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--fg-2, var(--ink-2));
}
.home__h2 + .home__display { margin-top: clamp(10px, 1.4vw, 16px); }

/* The reading. Paragraphs are short here on purpose: a one-line paragraph is
   a beat, and the rhythm of them is the voice of the page. */
.home__p {
  font-size: clamp(17px, 1.5vw, 19px);
  line-height: 1.62;
  text-wrap: pretty;
}

/* Donum's own part in the example above it: "We pay the fee. Everything after
   it is his." Quieter, and pulled up against the paragraph it belongs to,
   because the example is the point and this is the footnote to it. */
.home > .home__quiet, .home__chapter > .home__quiet {
  margin-top: .55em;
  font-size: clamp(15px, 1.3vw, 17px);
  line-height: 1.55;
  color: var(--fg-2);
  text-wrap: pretty;
}

/* The quotation. A change of ground rather than a change of size, so it reads
   as somebody else speaking. No attribution under it: the paragraph above it
   names her, in the sentence that introduces her, which is where a reader is
   already looking. */
.home > .home__quote, .home__chapter > .home__quote {
  margin-top: clamp(32px, 4vw, 52px);
  margin-inline: 0;
  padding: clamp(24px, 3.4vw, 40px) clamp(20px, 3vw, 36px);
  border-radius: 18px;
  background: var(--paper-2);
  border: 1px solid var(--hair-soft);
}
.home__quote p {
  font-size: clamp(17px, 1.5vw, 19px);
  line-height: 1.6;
  text-wrap: pretty;
}
.home__quote p + p { margin-top: .95em; }
/* Her first line is the aphorism the rest of it explains, so it carries. */
.home__quote p:first-child {
  font-size: clamp(20px, 2.1vw, 25px);
  line-height: 1.28;
  letter-spacing: -0.015em;
}
.home__quote strong { font-weight: 600; }

/* Links, where they fall in the reading. Two on consecutive lines are one
   choice offered twice, so they sit on one row and wrap together. */
.home > .home__links, .home__chapter > .home__links {
  margin-top: clamp(20px, 2.6vw, 30px);
  display: flex;
  flex-wrap: wrap;
  gap: 12px 26px;
}

/* A figure's source (non-negotiable 12), beside the sentence that uses it.
   Small, because a source is a receipt and not a claim: it has to be there,
   it does not have to be loud. */
.home > .home__source, .home__chapter > .home__source {
  margin-top: .7em;
  font-size: 13px;
  line-height: 1.5;
  color: var(--fg-2);
}
.home__source a { color: inherit; }
/* The rule is the separator, drawn rather than typed: a punctuation mark here
   would be read out as one by a screen reader. */
.home__asof {
  margin-inline-start: .6em;
  padding-inline-start: .6em;
  border-inline-start: 1px solid var(--line);
  white-space: nowrap;
}

/* ---------- The chaptered home page (25 October 2026, parts 6 to 9) ----------

   Behind HOME_CHAPTERS_OPEN. Black and white only (the progress colours stay
   in the challenge), drawn from the page's own text, readable without a
   script, and 360 pixels wide with nothing scrolling sideways but the bar.
   ---------------------------------------------------------------- */

/* Ruling C: the slogan is the largest line on the page, larger than every
   display line; the description sits under it, and the tagline under that,
   smaller and quieter. */
.home--chapters > .home__slogan--largest {
  font-size: clamp(36px, 6vw, 64px);
  line-height: 1.04;
  letter-spacing: -0.03em;
  color: var(--fg);
  text-wrap: balance;
}
.home--chapters .home__display { font-size: clamp(23px, 3vw, 34px); }
.home__lead { font-size: clamp(19px, 1.9vw, 23px); line-height: 1.45; text-wrap: pretty; }
.home__tagline { font-size: clamp(15px, 1.3vw, 17px); color: var(--fg-2); }

/* The chapter bar: one line of names, no numbers, scrolling sideways on its
   own; it scrolls up with the page and then holds under the site's bar. */
.home-bar {
  position: sticky; top: var(--nav-h); z-index: 40;
  margin-inline: calc(-1 * var(--gutter, 16px));
  padding: 8px var(--gutter, 16px);
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}
.home-bar__list {
  display: flex; gap: 8px; margin: 0; padding: 0; list-style: none;
  overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.home-bar__list::-webkit-scrollbar { display: none; }
.home-bar__link {
  display: inline-flex; align-items: center; min-height: 36px; padding: 4px 14px;
  border-radius: var(--pill); border: 1px solid transparent;
  white-space: nowrap; color: var(--fg); text-decoration: none; font-size: 15px;
}
.home-bar__link--passed { border-color: var(--fg); }
.home-bar__link[aria-current="true"] { background: var(--fg); color: var(--bg); border-color: var(--fg); }

/* A chapter: a jump to it leaves room for both bars above it. */
.home__chapter { scroll-margin-top: calc(var(--nav-h) + 64px); }
.home__chapter > * + * { margin-top: 1.15em; }
.home__chapter > .home__display { margin-top: clamp(40px, 5.5vw, 76px); }
.home > .home__chapter { margin-top: clamp(40px, 5vw, 64px); }

/* Every link, a bold, filled button, one per line (ruling E). */
.home__buttons { display: grid; gap: 10px; justify-items: start; }
.home__buttons p { margin: 0; max-width: 100%; }
.home__button { font-weight: 700; white-space: normal; text-align: center; max-width: 100%; }

/* 8.1: the question, in a large box with a heavy left edge. */
.home__question {
  padding: clamp(18px, 3vw, 28px) clamp(18px, 3vw, 32px);
  border: 1px solid var(--fg); border-left-width: 8px;
  font-size: clamp(22px, 2.8vw, 32px); font-weight: 600; line-height: 1.22; letter-spacing: -0.015em;
  text-wrap: balance;
}

/* 8.2: the Next Step field. */
.home__field { padding: 16px; border: 1px solid var(--fg); border-radius: 14px; }

/* 8.3: "Why me?" turning to "Why not me?". Closed, the front and a hint;
   open, the back and its line. A <details>: the same without a script. */
.home-flip { border: 1px solid var(--fg); border-radius: 18px; padding: clamp(18px, 3vw, 28px); }
.home-flip__summary { cursor: pointer; list-style: none; display: grid; gap: 6px; }
.home-flip__summary::-webkit-details-marker { display: none; }
.home-flip__front, .home-flip__back { font-size: clamp(28px, 4vw, 44px); font-weight: 700; letter-spacing: -0.025em; line-height: 1.1; }
.home-flip__hint { font-size: 14px; color: var(--fg-2); }
.home-flip__back { display: none; }
.home-flip[open] .home-flip__front, .home-flip[open] .home-flip__hint { display: none; }
.home-flip[open] .home-flip__back { display: block; }
.home-flip__line { margin-top: 10px; font-size: clamp(17px, 1.5vw, 19px); }

/* 8.4: the five boxes, numbered, joined by short lines, Donum's filled. */
.home-flow { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.home-flow__box {
  position: relative; display: grid; grid-template-columns: auto 1fr; column-gap: 12px; row-gap: 2px;
  padding: 14px 16px; border: 1px solid var(--fg); border-radius: 14px; background: var(--bg); color: var(--fg);
}
.home-flow__box + .home-flow__box { margin-top: 22px; }
.home-flow__box + .home-flow__box::before {
  content: ''; position: absolute; left: 30px; top: -23px; width: 0; height: 22px; border-left: 2px solid var(--fg);
}
.home-flow__box--filled { background: var(--fg); color: var(--bg); }
.home-flow__n { grid-row: span 2; font-weight: 700; font-size: 20px; min-width: 1.4em; }
.home-flow__title { font-weight: 700; }
.home-flow__line { font-size: 15px; line-height: 1.45; }

/* 8.5: the key, and the chains of rounded labels joined by arrows. */
.home-key__title { font-weight: 600; }
.home-key__list { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.home-chip {
  display: inline-flex; align-items: center; min-height: 32px; padding: 4px 12px;
  border: 1.5px solid var(--fg); border-radius: var(--pill); font-size: 15px; line-height: 1.3; color: var(--fg); background: var(--bg);
}
.home-chip--filled { background: var(--fg); color: var(--bg); }
.home-chain { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.home-chain__arrow { font-weight: 700; color: var(--fg); }

/* 8.6: the community path, a vertical list joined by a line, the last point filled. */
.home-path { list-style: none; margin: 0; padding: 0 0 0 4px; }
.home-path__point { position: relative; padding: 0 0 18px 30px; }
.home-path__point::before {
  content: ''; position: absolute; left: 0; top: .3em; width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid var(--fg); background: var(--bg);
}
.home-path__point:not(:last-child)::after {
  content: ''; position: absolute; left: 8px; top: calc(.3em + 16px); bottom: 0; border-left: 2px solid var(--fg);
}
.home-path__point--filled { font-weight: 700; }
.home-path__point--filled::before { background: var(--fg); }

/* Paragraphs folded under a summary. */
.home-fold__summary { cursor: pointer; font-weight: 700; min-height: 44px; display: flex; align-items: center; }
.home-fold > .home__p { margin-top: 1em; }

/* "Show other examples" under the challenge's examples (ruling G). */
.ns-examples__more { margin: 8px 0 0; }

/* ---------- Members in the admin (25 October 2026, part 10) ---------- */
.admin-member__handle { user-select: all; -webkit-user-select: all; font-weight: 600; }
.admin-member__copy { margin: 4px 0 0; }
.admin-member__acts { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-start; margin-top: 8px; }
.admin-member__act { flex-basis: 100%; }
.admin-member__act > summary { list-style: none; cursor: pointer; display: inline-flex; }
.admin-member__act > summary::-webkit-details-marker { display: none; }
.admin-members__search { margin-bottom: 12px; }
.admin-find-handle { margin: -6px 0 12px; font-size: 14px; }

/* ---------- A published outcome ----------

   One person's outcome, published because they asked for it to be (spec 9.4).
   Drawn as a card in a list, and every one of them the SAME card: a chance
   that did not hold gets the same ground, the same type and the same space as
   one that held. There is no `outcome--held` and there must never be one. A
   stylesheet that makes the good news larger has made an editorial decision
   the page is not admitting to.
   ---------------------------------------------------------------- */
.outcomes { list-style: none; display: grid; gap: clamp(16px, 2.2vw, 24px); max-width: 68ch; }
.outcomes--one { max-width: 44rem; }

.outcome {
  display: grid;
  gap: 12px;
  padding: clamp(18px, 2.4vw, 26px);
  border: 1px solid var(--card-line, var(--hair));
  border-radius: 16px;
  background: var(--card, var(--paper));
}
.outcome__head { display: flex; align-items: center; gap: 12px; }
/* The outcome, not the person: this is a record of how a gift went. */
.outcome__what { font-size: clamp(18px, 1.8vw, 21px); font-weight: 650; letter-spacing: -0.02em; }
.outcome__who { margin-top: 2px; font-size: 13px; color: var(--fg-2); }
.outcome__gift { font-size: 15px; line-height: 1.5; color: var(--fg-2); }
.outcome__note { margin: 0; padding-inline-start: 1.1em; border-inline-start: 3px solid var(--line); }
.outcome__note p { font-size: clamp(16px, 1.4vw, 18px); line-height: 1.6; }
.outcome__category { font-size: 12px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--fg-2); }

/* ---------- The bar's tools ---------- */
.sitehead__tools { margin-inline-start: auto; display: flex; align-items: center; gap: 2px; }

.sitehead__tool {
  width: 44px; height: 44px; padding: 0; flex: none;
  background: none; border: 0; cursor: pointer; color: var(--ink);
  display: grid; place-items: center; border-radius: 10px;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
  transition: background var(--dur-1) var(--ease-soft);
}
@media (hover: hover) and (pointer: fine) {
  .sitehead__tool:hover { background: var(--hair-soft); text-decoration: none; }
}
.sitehead__tool:active { background: var(--hair); }
.sitehead__tool svg { width: 23px; height: 23px; display: block; }

/* ---------- Search ----------
   Hidden until JavaScript opens it. Without JavaScript the bar's search link
   goes to /search/, which is a real page listing everything. */
.search { position: fixed; inset: 0; z-index: 90; }
.search[hidden] { display: none !important; }
.search__scrim {
  position: absolute; inset: 0; background: var(--paper);
  opacity: 0; transition: opacity var(--dur-2) var(--ease-soft);
}
.search.is-open .search__scrim { opacity: 1; }

.search__panel {
  position: absolute; inset-inline: 0; top: 0; bottom: 0;
  display: flex; flex-direction: column;
  background: var(--paper);
  transform: translateY(-12px); opacity: 0;
  transition: transform var(--dur-2) var(--ease), opacity var(--dur-2) var(--ease-soft);
  padding-top: env(safe-area-inset-top, 0px);
  overscroll-behavior: contain;
}
.search.is-open .search__panel { transform: none; opacity: 1; }

.search__bar {
  flex: none; display: flex; align-items: center; gap: 10px;
  min-height: var(--nav-h);
  padding-inline: var(--gutter) 12px;
  border-bottom: 1px solid var(--hair-soft);
}
.search__bar-icon { display: grid; place-items: center; color: var(--ink-3); flex: none; }
.search__bar-icon svg { width: 21px; height: 21px; display: block; }
.search__input {
  flex: 1; min-width: 0;
  border: 0; background: none; color: var(--ink);
  font: inherit; font-size: 17px; padding: 14px 0;
  -webkit-appearance: none; appearance: none;
}
.search__input:focus { outline: none; }
.search__input::placeholder { color: var(--ink-3); }
.search__cancel {
  flex: none; background: none; border: 0; cursor: pointer;
  color: var(--ink-2); font: inherit; font-size: 15px; padding: 10px 8px;
  border-radius: 8px;
}
@media (hover: hover) and (pointer: fine) { .search__cancel:hover { color: var(--ink); } }

.search__body { flex: 1; overflow-y: auto; padding: 20px var(--gutter) 40px; }
.search__label {
  font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--ink-3); margin-bottom: 12px;
}
.search__chips { list-style: none; display: grid; gap: 6px; }
.search__chip {
  display: flex; align-items: center; justify-content: space-between;
  padding: 13px 14px; margin-inline: -14px; border-radius: 12px;
  color: var(--ink); text-decoration: none; font-size: 17px;
  transition: background var(--dur-1) var(--ease-soft);
}
.search__chip span { color: var(--ink-3); font-size: 20px; }
@media (hover: hover) and (pointer: fine) {
  .search__chip:hover { background: var(--hair-soft); text-decoration: none; }
}

.search__results { display: grid; gap: 4px; }
.search__hit {
  display: grid; gap: 2px;
  padding: 13px 14px; margin-inline: -14px; border-radius: 12px;
  color: var(--ink); text-decoration: none;
  transition: background var(--dur-1) var(--ease-soft);
}
@media (hover: hover) and (pointer: fine) {
  .search__hit:hover { background: var(--hair-soft); text-decoration: none; }
}
.search__hit-kind {
  font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-3);
}
.search__hit-title { font-size: 17px; font-weight: 600; letter-spacing: -0.015em; }
.search__hit-line { font-size: 13px; line-height: 1.4; color: var(--ink-2); }
.search__empty { color: var(--ink-2); font-size: 15px; }

@media (min-width: 700px) {
  .search__panel {
    inset-inline: 50%; top: 10vh; bottom: auto;
    width: min(620px, 92vw); transform: translate(-50%, -12px);
    max-height: 70vh; border-radius: 18px;
    border: 1px solid var(--hair);
    box-shadow: 0 30px 80px rgba(0,0,0,.18);
  }
  .search.is-open .search__panel { transform: translate(-50%, 0); }
  .search__scrim { background: rgba(0,0,0,.35); }
}

/* ---------- The /search/ box and its results page (D-365) ---------- */
.search-page { max-width: 68ch; margin-inline: auto; display: grid; gap: 20px; }
.search-form__row { display: flex; gap: 10px; align-items: stretch; }
.search-form__input { flex: 1 1 auto; min-width: 0; }
.search-form .pill { flex: none; border: 0; cursor: pointer; font: inherit; }
.search-page__lead { margin: 0; }
.search__results--page { list-style: none; margin: 0; padding: 0; }
.search__results--page .search__hit { margin-inline: 0; }

/* ---------- The /search/ directory, for when JavaScript is off ---------- */
.directory { display: grid; gap: clamp(32px, 4vw, 48px); max-width: 68ch; margin-inline: auto; }
.directory__title {
  font-size: 12px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--fg-2); margin-bottom: 14px;
}
.directory__list { list-style: none; display: grid; gap: 12px; }
.directory__item { display: grid; gap: 2px; }
.directory__item a { font-size: 17px; }
.directory__line { font-size: 13px; color: var(--fg-2); }

/* ---------- Forms ----------

   One form on the site so far, and it is the one somebody fills in
   when they are in trouble. So: generous targets, a real focus ring,
   and no cleverness that could make a field hard to find.

   Inputs are 16px on purpose. Anything smaller and iOS Safari zooms
   the page the moment the field takes focus, which on a long form
   leaves somebody scrolled sideways and hunting for the next box.

   Written in logical properties, like the rest of this file, so the
   whole thing mirrors when Arabic arrives.
   ---------------------------------------------------------------- */
.form-wrap { max-width: 44rem; margin-inline: auto; }

.form { display: grid; gap: 26px; }

.field { display: grid; gap: 6px; border: 0; padding: 0; margin: 0; min-inline-size: 0; }
/* A fieldset with a visible legend is laid out as a block, never a grid or
   a flex box. Safari on iPhone sizes the legend of a grid fieldset to its
   narrowest width before the page settles, one word to a line (Joel's
   phone, 2 October 2026; floating the legend, D-253, fixed it only after the
   page was laid out again, D-256). A block fieldset is the case every
   browser has drawn the same way from the start; its children are spaced by
   margins instead of a grid gap. */
fieldset.field, fieldset.give__to, fieldset.give__chances, fieldset.partner-fieldset { display: block; }
fieldset.field > * + * { margin-top: 6px; }
fieldset.give__to > * + *, fieldset.give__chances > * + * { margin-top: 10px; }
fieldset.partner-fieldset > * + * { margin-top: 18px; }
fieldset > legend { padding: 0; }

.field__label {
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--fg);
  padding: 0;
}
.field__optional { font-weight: 400; color: var(--fg-2); font-size: 14px; }

.field__hint { font-size: 14px; line-height: 1.5; color: var(--fg-2); margin: 0; }
/* No surprise cuts (part 2a): what is left, or how many too many. */
.field__count { font-size: 14px; line-height: 1.5; color: var(--fg-2); margin: 0; font-variant-numeric: tabular-nums; }
.field__count--over { color: var(--danger); font-weight: 600; }

.field__input {
  font: inherit;
  font-size: 16px;
  line-height: 1.5;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 12px 14px;
  inline-size: 100%;
  -webkit-appearance: none;
  appearance: none;
  transition: border-color var(--dur-1) var(--ease-soft),
    box-shadow var(--dur-1) var(--ease-soft);
}
textarea.field__input { resize: vertical; min-block-size: 8lh; }

/* A select needs its own arrow once appearance is stripped. Drawn as
   a background SVG in currentColor's place rather than an image file,
   so it follows the theme without a second asset. */
select.field__input {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%236a6a72' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 12px 8px;
  padding-inline-end: 38px;
}
[dir="rtl"] select.field__input { background-position: left 14px center; }

.field__input:focus-visible {
  outline: none;
  border-color: var(--fg);
  box-shadow: 0 0 0 3px var(--hair);
}

.field--error .field__input { border-color: var(--danger); border-width: 2px; }

/* An error is red (Joel, 14 October 2026, D-373: "error messages should
   show in red not black"), the one colour beside black and white (spec 12),
   used for nothing else. It is still not colour-only: the weight of the
   border, the bar beside the message and the words themselves mark it too,
   for anybody who cannot separate red from grey. --danger is a darker red
   on a light ground and a lighter one on a dark ground, each well past
   4.5:1 against it. */
.field__error {
  font-size: 14px;
  line-height: 1.5;
  font-weight: 600;
  color: var(--danger);
  margin: 0;
  padding-inline-start: 10px;
  border-inline-start: 3px solid var(--danger);
}

.radios { display: grid; gap: 8px; }
.radio, .checkbox {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 16px;
  line-height: 1.5;
  cursor: pointer;
  /* A whole-line target. Tapping the words should work, not just the
     11px circle, and on a phone that is most of the difference
     between a form that is pleasant and one that is a fight. */
  padding: 8px 10px;
  margin-inline: -10px;
  border-radius: 10px;
  transition: background var(--dur-1) var(--ease-soft);
}
.radio:active, .checkbox:active { background: var(--hair-soft); }
.radio input, .checkbox input {
  inline-size: 20px;
  block-size: 20px;
  margin: 2px 0 0;
  flex: none;
  accent-color: var(--fg);
}
.checkbox span { font-size: 15px; line-height: 1.55; color: var(--fg-2); }

/* ── A member's picture, or the letter standing in for one ─────────────────
   Most people never upload anything, so the letter is the common case and is
   built to look deliberate rather than like a gap. Greyscale, like the rest
   of the site: BRAND.md allows no colour, so it is the hairline and the
   surface that make it a shape. */
.avatar { flex: none; }
.avatar--photo {
  border-radius: 50%;
  object-fit: cover;
  background: var(--hair-soft);
}
.avatar--letter {
  --avatar-size: 48px;
  inline-size: var(--avatar-size);
  block-size: var(--avatar-size);
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--hair);
  background: var(--hair-soft);
  color: var(--fg-2);
  font-size: calc(var(--avatar-size) * 0.42);
  font-weight: 600;
  line-height: 1;
  user-select: none;
}

.form__submit { justify-self: start; border: 0; cursor: pointer; font: inherit; }
.form__foot { font-size: 13px; color: var(--fg-2); margin: 0; }

.form-summary {
  border: 2px solid var(--danger);
  border-radius: 14px;
  padding: 16px 18px;
  margin-block-end: 26px;
}
.form-summary:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--hair); }
.form-summary__title { font-weight: 700; margin: 0 0 8px; font-size: 16px; color: var(--danger); }
.form-summary__list { margin: 0; padding-inline-start: 20px; display: grid; gap: 4px; }
.form-summary__list { color: var(--danger); }
.form-summary__list a { font-size: 15px; color: var(--danger); }

.form-done {
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: clamp(20px, 4vw, 30px);
  display: grid;
  gap: 10px;
}
.form-done:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--hair); }
.form-done__title { font-size: 20px; font-weight: 650; letter-spacing: -0.02em; margin: 0; }
.form-done__line { margin: 0; color: var(--fg-2); line-height: 1.6; }
.form-done__ref { margin: 6px 0 0; font-size: 13px; color: var(--fg-2); }
.form-done__ref code { font-size: 12px; }

/* Crisis resources, and the honest empty state that stands in for
   them until every entry has been checked by hand. */
.notice {
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: clamp(18px, 3.5vw, 26px);
  display: grid;
  gap: 10px;
  max-inline-size: 60ch;
}
.notice p { margin: 0; line-height: 1.6; color: var(--fg-2); }
.notice p strong { color: var(--fg); }
/* A refusal shown as a notice is an error, so it is red too (D-373). */
.notice--error { color: var(--danger); border-color: var(--danger); font-weight: 600; }
/* Under "Donate" while no way to pay is open (Joel, 11 October 2026). */
.give__setup { margin: 0 0 28px; }

.resources { list-style: none; margin: 0; padding: 0; display: grid; gap: 18px; max-inline-size: 60ch; }
.resource { display: grid; gap: 3px; padding-block-end: 18px; border-block-end: 1px solid var(--hair-soft); }
.resource:last-child { border-block-end: 0; padding-block-end: 0; }
.resource__name { font-weight: 650; margin: 0; }
.resource__what, .resource__hours { margin: 0; font-size: 14px; color: var(--fg-2); }
.resource__contact { margin: 0; font-size: 16px; }

/* ---------- A chance page ----------

   Rendered per request by the Worker, from the same components every
   static page uses. The amount raised moves while somebody is reading,
   which is the whole reason this page is not a file.
   ---------------------------------------------------------------- */
.chance { display: grid; gap: 26px; max-inline-size: 42rem; }

.chance__gift { display: grid; gap: 6px; }
.chance__gift-text { font-size: clamp(18px, 2.4vw, 21px); line-height: 1.5; margin: 0; }

.chance__status { font-size: 15px; font-weight: 600; margin: 0; }
.chance__partner { font-size: 14px; color: var(--fg-2); margin: 0; }

/* What every chance page says about itself (spec 9.2, R-30): who checked
   it and when, who delivers it, where the price comes from. A description
   list, so each answer is read out with its question. */
.chance__facts { display: grid; gap: 14px; margin: 18px 0 0; }
.chance__fact { display: grid; gap: 2px; }
.chance__fact dt {
  font-size: 12px; font-weight: 600; letter-spacing: .07em;
  text-transform: uppercase; color: var(--fg-2);
}
.chance__fact dd { margin: 0; font-size: 15px; line-height: 1.45; }
.chance__words {
  margin: 8px 0 0; padding-inline-start: 1.1em;
  border-inline-start: 3px solid var(--line);
  font-size: clamp(17px, 1.6vw, 20px); line-height: 1.5;
}
/* Every change to the budget after approval, oldest first (R-24). */
.chance__revisions { list-style: none; padding: 0; margin: 0; display: grid; gap: 18px; max-inline-size: 42rem; }
.chance__revision { display: grid; gap: 4px; padding-block-end: 16px; border-bottom: 1px solid var(--line); }
.chance__revision-when { font-size: 13px; font-weight: 600; color: var(--fg-2); margin: 0; }
.chance__revision-total { font-size: 15px; font-variant-numeric: tabular-nums; margin: 0; }

/* Step 6 turns this into a button. Until then it says so, because a
   button that looks like it takes money and does not is worse than no
   button: somebody presses it, nothing happens, and they conclude the
   whole thing is broken rather than unfinished. */
.chance__soon {
  font-size: 14px;
  color: var(--fg-2);
  margin: 0;
  padding-inline-start: 12px;
  border-inline-start: 2px solid var(--hair);
}

/* ---------- Giving ----------

   Two steps: the form, then a screen that says exactly where the
   money goes before anything is charged. Spec 9.3 requires the
   second one, and it is also what makes the flow work with no
   JavaScript at all.
   ---------------------------------------------------------------- */
/* The Donate form (Part 5.2). "Give once" or "Give monthly" are two radios
   drawn as a switch of two: nothing is drawn again for the choice (Joel, 11
   October 2026). The amounts are radios in a grid of three across, the one
   chosen filled. */
.give__for { margin: 0; font-size: 17px; line-height: 1.5; }
.give__switch {
  display: flex;
  gap: 6px;
  margin: 0;
  padding: 4px;
  min-width: 0;
  border: 1px solid var(--line);
  border-radius: 999px;
}
.give__option {
  position: relative;
  cursor: pointer;
  flex: 1 1 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 44px;
  padding: 8px 12px;
  border-radius: 999px;
  color: var(--fg);
  font-weight: 600;
  text-decoration: none;
}
.give__option input { position: absolute; opacity: 0; inset: 0; margin: 0; cursor: pointer; }
.give__option.is-current, .give__option:has(input:checked) { background: var(--fg); color: var(--bg); }
.give__option:not(:has(input:checked)) { background: none; color: var(--fg); }
.give__option:has(input:focus-visible) { box-shadow: 0 0 0 3px var(--hair); }
.give__heart { width: 18px; height: 18px; flex: none; }

.give__amounts { border: 0; margin: 0; padding: 0; min-width: 0; display: grid; gap: 12px; }
.give__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.give__amount { position: relative; display: block; cursor: pointer; }
.give__amount input { position: absolute; opacity: 0; inset: 0; margin: 0; cursor: pointer; }
.give__amount > span {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 8px 6px;
  border: 1px solid var(--line);
  border-radius: 12px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  text-align: center;
}
.give__amount input:checked + span { background: var(--fg); color: var(--bg); border-color: var(--fg); }
.give__amount input:focus-visible + span { box-shadow: 0 0 0 3px var(--hair); }
.give__other[hidden] { display: none; }

.give__submit { min-height: 52px; }
/* Exact words with the script ("Give USD 50 once"), certain ones without
   ("Give once"): see give-form.mjs. */
.give__say--exact { display: none; }
:root.js .give__say--exact { display: inline; }
:root.js .give__say--plain { display: none; }
/* Without the script, the button says the choice made above it, and only it. */
.give:has(input[name="frequency"][value="monthly"]:checked) .give__say--once,
.give:has(input[name="frequency"][value="once"]:checked) .give__say--monthly { display: none; }
.give:not(:has(input[name="frequency"]:checked)) .give__say--monthly { display: none; }
.give__more { margin: 0; text-align: center; }
/* Where the gift goes (Batch 8.6): the general fund and an open chance,
   side by side, the same size, weight and style, so neither reads as the
   lesser choice. One above the other on a phone. */
.give__to { border: 0; margin: 0; padding: 0; min-width: 0; display: grid; gap: 10px; }
.give__dests { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); gap: 10px; }
.give__dest {
  position: relative;
  display: grid;
  align-content: start;
  gap: 6px;
  padding: 14px 16px 14px 46px;
  border: 1px solid var(--line);
  border-radius: 14px;
  cursor: pointer;
}
.give__dest input { position: absolute; left: 16px; top: 17px; width: 18px; height: 18px; margin: 0; accent-color: var(--fg); }
.give__dest:has(input:checked) { border-color: var(--fg); box-shadow: inset 0 0 0 1px var(--fg); }
.give__dest:has(input:disabled) { cursor: default; color: var(--fg-2); }
.give__dest:has(input:focus-visible) { box-shadow: 0 0 0 3px var(--hair); }
.give__dest-name { font-weight: 650; font-size: 17px; }
.give__dest-line { color: var(--fg-2); font-size: 15px; line-height: 1.45; }
.give__places[hidden], .give__dest-line[hidden],
.give__for[hidden], .give__switch[hidden], .give__chances[hidden], .give__search[hidden],
.give__chance[hidden], .give__chance-none[hidden] { display: none; }
.give__change { margin-left: 6px; font-weight: 600; white-space: nowrap; }
.give__notice { margin: 0; padding: 10px 14px; border-left: 3px solid var(--fg); font-size: 15px; }
/* The open chances: a compact list that scrolls, never a page of cards. */
.give__chances { border: 0; margin: 0; padding: 0; min-width: 0; display: grid; gap: 10px; }
.give__search { display: grid; gap: 6px; }
.give__chance-list {
  list-style: none;
  margin: 0;
  padding: 0;
  max-height: 22rem;
  overflow-y: auto;
  border: 1px solid var(--line);
  border-radius: 14px;
}
.give__chance { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 8px 12px; padding: 12px 14px; }
.give__chance + .give__chance { border-top: 1px solid var(--line); }
/* The radio sits in its own column beside every line of text, however many there are (a sample has
   three). Placed by hand, never by auto-placement: an unplaced third line once fell into the radio's
   column, widened it, and left the name a few letters wide (D-257). */
.give__chance-pick { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 2px 10px; align-items: start; cursor: pointer; min-width: 0; }
.give__chance-pick input { grid-column: 1; grid-row: 1 / span 3; margin-top: 4px; accent-color: var(--fg); }
.give__chance-pick > :not(input) { grid-column: 2; }
/* On a phone the line is too narrow to share: "About this chance" goes under the words. */
@media (max-width: 560px) {
  .give__chance { grid-template-columns: minmax(0, 1fr); }
  .give__chance-about { justify-self: start; margin-left: 31px; }
}
.give__chance-name { font-weight: 600; overflow-wrap: anywhere; }
.give__chance-need { color: var(--fg-2); font-size: 14px; font-variant-numeric: tabular-nums; }
.give__chance-about { font-size: 14px; font-weight: 600; white-space: nowrap; }
.give__chance-none { margin: 0; color: var(--fg-2); }
.give__for-need { display: block; margin-top: 4px; color: var(--fg-2); font-size: 14px; font-weight: 400; font-variant-numeric: tabular-nums; }
/* "About this chance": a dialog beside the list on a wide screen, a sheet
   from the bottom on a phone. Escape closes it (the browser's own). */
.give-panel {
  width: min(28rem, 100vw);
  max-height: 100dvh;
  margin: 0 0 0 auto;
  height: 100dvh;
  padding: 0;
  border: 0;
  border-left: 1px solid var(--line);
  background: var(--bg);
  color: var(--fg);
}
.give-panel::backdrop { background: rgb(0 0 0 / 0.35); }
.give-panel__body { display: grid; gap: 12px; padding: 22px clamp(16px, 4vw, 26px) 28px; }
.give-panel__title { font-size: 21px; letter-spacing: -0.01em; margin: 0; }
.give-panel__actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0 0; }
@media (max-width: 640px) {
  .give-panel {
    width: 100vw;
    max-width: 100vw;
    height: auto;
    max-height: 85dvh;
    margin: auto 0 0;
    border-left: 0;
    border-top: 1px solid var(--line);
    border-radius: 18px 18px 0 0;
    overflow-y: auto;
  }
}
.chance__kicker { margin: 0; color: var(--fg-2); font-size: 14px; }
.chance__need { margin: 0; line-height: 1.5; }
.chance__total, .chance__still { margin: 0; font-weight: 600; font-variant-numeric: tabular-nums; }

/* Your gift (Batch 8.7): the summary just above the button, and what
   follows "Prepare the email". Lines with nothing in them are hidden. */
.give__pay-none { margin: 0 0 6px; padding: 10px 14px; border-left: 3px solid var(--fg); font-size: 15px; line-height: 1.5; }
.give__summary { border: 1px solid var(--line); border-radius: 14px; padding: 14px clamp(14px, 3vw, 20px); display: grid; gap: 10px; }
.give__summary-title { margin: 0; font-size: 17px; }
.give__summary-line { margin: 0; font-size: 17px; font-weight: 650; line-height: 1.45; overflow-wrap: anywhere; }
.give__summary-line[hidden] { display: none; }
.give__summary-list { margin: 0; display: grid; gap: 8px; }
.give__summary-row { display: grid; grid-template-columns: minmax(7rem, 11rem) 1fr; gap: 2px 12px; }
.give__summary-row[hidden] { display: none; }
.give__summary-row dt { color: var(--fg-2); font-size: 14px; }
.give__summary-row dd { margin: 0; overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }
@media (max-width: 420px) { .give__summary-row { grid-template-columns: 1fr; } }
.give__prepared { display: grid; gap: 10px; }
/* A gift list (Issue 2): the panel the script fills under the form, and its
   "Add another gift". Hidden until there is something in it. */
.give-list { border: 1px solid var(--line); border-radius: 14px; padding: 14px clamp(14px, 3vw, 20px); display: grid; gap: 10px; margin-top: 18px; }
.give-list[hidden], .give-list [hidden], .give-list__add[hidden] { display: none; }
.give-list__title { margin: 0; font-size: 17px; }
.give-list__status { margin: 0; line-height: 1.5; }
.give-list__status:empty { display: none; }
.give-list__lines { margin: 0; padding-inline-start: 1.4em; display: grid; gap: 10px; }
.give-list__line { line-height: 1.45; }
.give-list__what { display: block; overflow-wrap: anywhere; }
.give-list__moves { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
.give-list__totals { margin: 0; display: grid; gap: 8px; }
.give-list__totals div { display: grid; grid-template-columns: minmax(7rem, 1fr) auto; gap: 2px 12px; }
.give-list__totals dt { color: var(--fg-2); font-size: 14px; }
.give-list__totals dd { margin: 0; font-weight: 650; font-variant-numeric: tabular-nums; }
@media (max-width: 420px) { .give-list__totals div { grid-template-columns: 1fr; } }
.give-list__note { margin: 0; color: var(--fg-2); font-size: 14px; line-height: 1.5; }
.give-list__actions { margin: 0; }
.give-list__add { display: grid; gap: 6px; margin: 0 0 12px; }
.give-list__add--after { margin: 14px 0 0; }
.give-list__hint { color: var(--fg-2); font-size: 14px; line-height: 1.5; }
.give__prepared-line { margin: 0; line-height: 1.5; }
.give__prepared-line[hidden], .give__prepared [hidden] { display: none; }
.give__email { width: 100%; min-height: 14rem; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 14px; line-height: 1.45; }
/* "View email" (Joel, 11 October 2026): a button the size of "Prepare the
   email", just above it, opening a box to read, type in and copy. Both run
   the width of the form, so they are the same size whatever their words. */
.email-view { display: grid; gap: 12px; }
.email-view[hidden], .email-view__panel[hidden] { display: none; }
.email-view__panel { display: grid; gap: 10px; }
.email-view__button { justify-self: stretch; width: 100%; }
.email-view + .form__submit { justify-self: stretch; width: 100%; }
.give .email-view__button { min-height: 52px; }
.give__copied { margin-left: 8px; color: var(--fg-2); font-size: 14px; }

/* Who receives a gift (Batch 7.5), under "You're giving to". */
.give__received { margin: 0; color: var(--fg-2); font-size: 15px; }
/* How would you like to pay? (Batch 7.4): a way not open yet says so under
   itself, once chosen. */
.give__pay { margin: 0; }
.give__pay-note { margin: 0 0 4px; padding: 10px 14px; border-left: 3px solid var(--line); color: var(--fg-2); font-size: 15px; }
.give__pay-note[hidden] { display: none; }
.give__pay-note a { display: inline-block; margin-top: 4px; font-weight: 600; }
/* Batch 9.8: what Donum receives by each way, a way arranged by email, and about how much. */
.give__pay-receives { display: block; color: var(--fg-2); font-size: 14px; line-height: 1.4; }
.give__pay-email { color: var(--fg-2); font-size: 14px; }
.give__pay-email::before { content: "· "; }
.give__pay-about { margin: 8px 0 0; padding: 10px 14px; border-left: 3px solid var(--line); font-size: 15px; line-height: 1.5; }
/* Batch 11.4: the way chosen as one clear line, and "Other ways to pay"
   under it, which opens the whole list. */
.give__pay .radio[hidden] { display: none; }
/* "What would you like to give?" (Joel, 11 October 2026): money first, and
   every other way one tap away, as the ways to pay are. Without the script
   every choice shows, and the stylesheet shows the chosen one's panel in
   place of the money form. */
.give__kinds .radio[hidden] { display: none; }
.give__kind-line { display: block; margin-top: 2px; font-size: 14px; line-height: 1.45; color: var(--fg-2); }
.give__money { display: contents; }
.give__money[hidden] { display: none; }
.give__kind-panel { display: none; gap: 14px; }
.give__kind-panel[hidden] { display: none !important; }
.give:has(input[name="give_kind"]:not([value="money"]):checked) .give__money { display: none; }
.give:has(input[name="give_kind"][value="things"]:checked) [data-give-kind-panel="things"],
.give:has(input[name="give_kind"][value="time"]:checked) [data-give-kind-panel="time"],
.give:has(input[name="give_kind"][value="story"]:checked) [data-give-kind-panel="story"],
.give:has(input[name="give_kind"][value="promise"]:checked) [data-give-kind-panel="promise"],
.give:has(input[name="give_kind"][value="partner"]:checked) [data-give-kind-panel="partner"] { display: grid; }
.give__kind-links { list-style: none; margin: 0; padding: 0; display: grid; }
.give__kind-links li { padding: 12px 0; border-bottom: 1px solid var(--line); }
.give__kind-link { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; text-decoration: none; color: var(--fg); min-height: 32px; }
.give__kind-link span[aria-hidden] { font-size: 20px; line-height: 1; color: var(--fg-2); }
.give__kind-link-line { display: block; font-size: 14px; line-height: 1.45; color: var(--fg-2); }
.give__things { border: 1px solid var(--line); border-radius: 12px; padding: 0 14px; }
.give__things summary { cursor: pointer; padding: 14px 0; font-weight: 600; }
.give__things[open] summary { border-bottom: 1px solid var(--line); }
.give__things .give__kind-links li:last-child { border-bottom: 0; }
.give__kind-more { margin: 0; }
.give__offer { margin: 0; padding-inline-start: 1.1em; display: grid; gap: 6px; line-height: 1.5; }
.give__pay .radios.is-one .radio { border: 1px solid var(--fg); border-radius: 12px; padding: 12px 14px; }
.give__pay-more { margin: 10px 0 0; }
/* "Other ways to pay" (Joel, 11 October 2026: "bolden other ways to pay so
   that people don't bypass it for lack of visibility"): the ink's own outline
   and bold words, with a mark that turns while the list is open. */
.give__more { gap: 10px; border-width: 2px; cursor: pointer; font: inherit; font-weight: 700; background: transparent; }
.give__more-mark { width: 12px; height: 8px; flex: none; transition: transform var(--dur-1) var(--ease-soft); }
.give__more[aria-expanded="true"] .give__more-mark { transform: rotate(180deg); }
/* "How to pay" (Batch 11.5): after the review step, for a way with no
   checkout, what to send, the way's details and the reference. */
.how-to-pay { display: grid; gap: 10px; }
/* The Philanthropy Partners form (Batch 11.7), inside the page's prose. */
.partner-form { display: grid; gap: 12px; margin: 28px 0; padding: 18px clamp(14px, 3vw, 22px); border: 1px solid var(--line); border-radius: 14px; }
.partner-form > h2 { margin: 0; }
.partner-form > p { margin: 0; }
.partner-form__form { display: grid; gap: 20px; }
.partner-form__form label, .partner-form__form legend { font-size: 16px; }
.how-to-pay .ways__details { margin: 0; }
.give__pay-more[hidden] { display: none; }
.give__pay-about[hidden] { display: none; }

.dedicate {
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 14px clamp(14px, 3vw, 20px);
  display: grid;
  gap: 16px;
}
.dedicate__head { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.dedicate__label { display: inline-flex; align-items: center; gap: 10px; font-weight: 600; cursor: pointer; }
.dedicate__label input { width: 20px; height: 20px; margin: 0; }
.dedicate__fields { display: grid; gap: 18px; }
.dedicate__fields[hidden] { display: none; }

/* A (?) that shows one sentence. A <details>, so it opens without the
   script, and its words are read in full by a screen reader. */
.tip > summary { list-style: none; }
.tip > summary::-webkit-details-marker { display: none; }
.tip__button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: 1px solid var(--line);
  border-radius: 50%;
  font-weight: 700;
  font-size: 14px;
  cursor: pointer;
}
.tip__button:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--hair); }
.tip__text { margin: 10px 0 0; flex-basis: 100%; font-size: 14px; color: var(--fg-2); line-height: 1.55; }
.tip[open] { flex-basis: 100%; }

/* "See the amounts in your currency" (R-58, Part 5.3): under each amount, a
   line in the visitor's own currency; below the amounts, the list. */
.give__amount > .give__about {
  display: block;
  min-height: 0;
  padding: 4px 2px 0;
  border: 0;
  border-radius: 0;
  font-weight: 400;
  font-size: 12px;
  color: var(--fg-2);
}
.give__amount > .give__about:empty { display: none; }

/* The currency box beside an amount (Batch 11.1; R-109, R-110): joined to
   the amount's left like a telephone's country code. Closed it shows only the
   code, with a border and a down mark, so it reads as something to tap. One
   component for every form that takes money. */
.money-box { display: grid; gap: 6px; min-width: 0; }
.money-box__row { display: flex; align-items: stretch; min-width: 0; }
.money-box__row > .money-box__amount { flex: 1 1 auto; min-width: 0; border-start-start-radius: 0; border-end-start-radius: 0; }
/* The box people type an amount in, drawn bold so nobody has to find it
   (Joel, 11 October 2026: "too faint and it's not obvious until someone taps
   in other"): the ink's own two-pixel outline round the currency and the
   amount as one box, as "Other ways to pay" has, and grey words in it while
   it is empty. An error is marked by a heavier border still, the bar beside
   the message and the words (see .field__error). */
.money-box__row > .money-box__amount,
.money-box__row > .money-box__currency,
.money-box__row .money-box__button { border: 2px solid var(--fg); }
.money-box__row > .money-box__amount { border-inline-start-width: 1px; border-inline-start-color: var(--line); }
.money-box__row > .money-box__currency,
.money-box__row .money-box__button { border-inline-end: 0; }
.money-box__amount::placeholder { color: var(--fg-2); opacity: 1; }
.field--error .money-box__row > .money-box__amount,
.field--error .money-box__row > .money-box__currency,
.field--error .money-box__row .money-box__button { border-width: 3px; border-color: var(--danger); }
.field--error .money-box__row > .money-box__amount { border-inline-start-width: 1px; }
.money-box__currency,
.money-box__button {
  font: inherit;
  font-size: 16px;
  font-weight: 650;
  color: var(--fg);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-inline-end: 0;
  border-radius: 12px 0 0 12px;
  min-height: 50px;
}
.money-box__currency { flex: 0 1 auto; max-width: 48%; padding: 0 10px; }
.money-box__pick { position: relative; display: flex; flex: none; }
.money-box__button { display: inline-flex; align-items: center; gap: 8px; padding: 0 12px 0 14px; cursor: pointer; }
.money-box__currency:focus-visible, .money-box__button:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--hair); }
.money-box__mark { width: 12px; height: 8px; flex: none; }
.money-box__button[aria-expanded="true"] .money-box__mark { transform: rotate(180deg); }
.money-box__panel {
  position: absolute;
  z-index: 30;
  inset-block-start: calc(100% + 6px);
  inset-inline-start: 0;
  inline-size: min(22rem, calc(100vw - 32px));
  display: grid;
  gap: 6px;
  padding: 8px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 10px 30px var(--hair-soft);
}
.money-box__panel[hidden] { display: none; }
.money-box__list { list-style: none; margin: 0; padding: 0; max-block-size: 16rem; overflow-y: auto; }
.money-box__option, .money-box__none { padding: 9px 10px; border-radius: 8px; line-height: 1.4; }
.money-box__option { cursor: pointer; }
.money-box__option.is-active { background: var(--hair-soft); }
.money-box__option[aria-selected="true"] { font-weight: 650; }
.money-box__none { color: var(--fg-2); }
.money-box__about { margin: 0; font-size: 15px; line-height: 1.5; }
.money-box__about[hidden] { display: none; }
.money-box__hint { margin: 0; font-size: 14px; color: var(--fg-2); line-height: 1.5; }
.convert { display: grid; gap: 10px; }
.convert__row { display: flex; gap: 8px; align-items: stretch; }
.convert__select { flex: 1 1 auto; min-width: 0; }
.convert__find[hidden] { display: none; }
:root.js .convert__show { display: none; }
.convert__note, .convert__source { margin: 0; font-size: 13px; color: var(--fg-2); line-height: 1.55; }
.dedicate__intro { margin: 0; font-weight: 600; }

/* Ways to pay (Part 5.3, R-49): each way, its details, and in the preview
   whether it is switched on. */
.ways-page { display: grid; gap: 4px; }
.ways { list-style: none; margin: 0 0 8px; padding: 0; display: grid; gap: 14px; }
.ways__intro { margin: 0 0 18px; }
.ways__way { line-height: 1.6; }
.ways__receives { color: var(--fg-2); }
.ways__heading { margin: 32px 0 12px; font-size: 21px; font-weight: 650; letter-spacing: -0.01em; }
.ways__details { margin: 8px 0 0; display: grid; gap: 4px; }
.ways__detail { display: flex; flex-wrap: wrap; gap: 6px; }
.ways__detail dt { color: var(--fg-2); }
.ways__detail dt::after { content: ':'; }
.ways__detail dd { margin: 0; }
.ways__missing { font-style: italic; color: var(--fg-2); }
.ways__state {
  display: inline-block;
  margin-inline-start: 6px;
  padding: 1px 8px;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  color: var(--fg-2);
}
.ways__state--on { border-color: var(--fg); color: var(--fg); }
.report { display: grid; gap: 18px; }
.report-done { display: grid; gap: 10px; }
.report-done__ref { font-variant-numeric: tabular-nums; letter-spacing: 0.04em; }
.report-done__line { margin: 0; }

.give-test {
  margin: 0;
  font-size: 13px;
  color: var(--fg-2);
  padding-inline-start: 12px;
  border-inline-start: 2px solid var(--fg);
}

.confirm { gap: 18px; }
.confirm__amount {
  font-size: clamp(34px, 8vw, 46px);
  font-weight: 700;
  letter-spacing: -0.04em;
  margin: 0;
  font-variant-numeric: tabular-nums;
}
.confirm__where { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.confirm__where li {
  padding-inline-start: 14px;
  border-inline-start: 2px solid var(--line);
  line-height: 1.5;
}
.confirm__dedication, .confirm__recurring { margin: 0; color: var(--fg-2); line-height: 1.55; }
.confirm__actions { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.confirm__actions .pill { border: 0; cursor: pointer; font: inherit; }
/* A second button: plainly a button, in the text's own colour with a clear edge (D-542). It was grey text in a
   hairline, which read as a disabled box or a label. */
.pill--quiet {
  background: transparent;
  color: var(--fg);
  border: 1.5px solid var(--fg-2) !important;
}

/* The sandbox payment step. Only ever reachable while giving is off. */
.sandbox {
  border: 2px solid var(--fg);
  border-radius: 14px;
  padding: clamp(20px, 4vw, 28px);
  display: grid;
  gap: 10px;
}
.sandbox__title { margin: 2px 0 0; font-size: 20px; font-weight: 650; letter-spacing: -0.02em; }
.sandbox__line { margin: 0; color: var(--fg-2); line-height: 1.6; }
.sandbox__actions { display: flex; flex-wrap: wrap; gap: 10px; margin-block-start: 8px; }
.sandbox__actions .pill { border: 0; cursor: pointer; font: inherit; }

/* ---------- Results ----------

   Held and did not hold in the same type, on purpose. A page that
   sets its good number large and its bad number small is doing
   marketing and calling it transparency (rule 5).
   ---------------------------------------------------------------- */
.figures {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: clamp(20px, 4vw, 32px);
  /* 140px, not 160: at 375px the gutters leave about 335px, and 160 means
     two columns need 340. One figure per row put "held" and "did not hold"
     on separate screens, which is exactly the comparison this page exists
     to make. */
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
}
.figure { display: grid; gap: 2px; }
.figure__n {
  font-size: clamp(34px, 7vw, 48px);
  font-weight: 700;
  letter-spacing: -0.045em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.figure__label { font-size: 14px; color: var(--fg-2); line-height: 1.4; }

/* The second row is the shape of the programme rather than its
   outcome, so it is quieter without being hidden. */
.figures--quiet .figure__n { font-size: clamp(24px, 5vw, 32px); }

.table-wrap { overflow-x: auto; }
.table { border-collapse: collapse; inline-size: 100%; min-inline-size: 22rem; }
.table th, .table td {
  text-align: start;
  padding: 11px 14px 11px 0;
  border-block-end: 1px solid var(--hair-soft);
  font-size: 15px;
}
.table thead th {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--fg-2);
  font-weight: 600;
}
.table td { font-variant-numeric: tabular-nums; }
.table tbody th { font-weight: 600; }
.table-note {
  margin: 14px 0 0;
  font-size: 13.5px;
  color: var(--fg-2);
  line-height: 1.55;
  padding-inline-start: 12px;
  border-inline-start: 2px solid var(--line);
  max-inline-size: 52ch;
}
.sample-mark { margin: 0; font-size: 13px; color: var(--fg-2); }

/* ---------- The account screen ----------
   Worker-rendered and never cached, so none of this appears in dist/. It was
   written without styles and shipped that way: the class-family check in
   apps/web/check.mjs now reads the source modules as well as the built pages,
   which is how it was found. */
.account-head {
  display: flex; align-items: center; gap: 16px;
  padding-bottom: 20px; border-bottom: 1px solid var(--line);
}
.account-head__mark { flex: none; }
.account-head__handle { font-size: 21px; font-weight: 600; letter-spacing: -0.02em; }
.account-head__note { font-size: 14px; color: var(--fg-2); margin-top: 2px; }

/* My account's menu (D-428): the panel icon at the upper left of every
   signed-in /account/ page. It opens the site's own drawer. Beside it, the
   member's name and seal; the bar stays fixed under the site's bar (D-432). */
.account-bar {
  position: sticky; top: var(--nav-h); z-index: 50;
  background: var(--paper);
  border-bottom: 1px solid var(--hair-soft);
}
.account-bar__row { display: flex; align-items: center; gap: 6px; min-height: 52px; }
.account-bar__who {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 17px; font-weight: 600; letter-spacing: -0.015em;
  color: var(--ink); text-decoration: none;
}
.account-bar__open {
  width: 40px; height: 40px; margin-inline-start: -8px;
  display: grid; place-items: center; border-radius: 10px;
  color: var(--ink-2);
  transition: background var(--dur-1) var(--ease-soft), color var(--dur-1) var(--ease-soft);
}
@media (hover: hover) and (pointer: fine) {
  .account-bar__open:hover { background: var(--hair-soft); color: var(--ink); }
}
.account-bar__open svg { width: 22px; height: 22px; }
/* Under the bar (D-436), the page's first section starts close, as it did inside <main>. */
body:has(> .account-bar) main > .section:first-of-type,
body:has(> .account-bar) main > .back + .section { padding-top: 20px; }
/* A number beside a row of the menu (D-434): what waits inside it. */
.drawer__count { margin-inline-start: 8px; align-self: center; }
.drawer__link:has(.drawer__count:not([hidden])) { grid-template-columns: auto 1fr auto; grid-template-areas: "name count go"; }
.drawer__link .drawer__count { grid-area: count; justify-self: start; }
/* What needs you and Notifications on My account (D-434): each a button that opens and closes. */
.account-fold { border-bottom: 1px solid var(--hair-soft); }
.account-fold > summary { list-style: none; cursor: pointer; }
.account-fold > summary::-webkit-details-marker { display: none; }
.account-fold__head { display: flex; align-items: center; gap: 10px; padding: 18px 0; }
.account-fold__title { font-size: 20px; font-weight: 600; letter-spacing: -0.015em; color: var(--ink); }
.account-fold__go { margin-inline-start: auto; color: var(--ink-2); font-size: 22px; transition: transform var(--dur-1) var(--ease-soft); }
.account-fold[open] .account-fold__go { transform: rotate(90deg); }
.account-fold__body { padding-bottom: 18px; }
/* A row of the menu that opens a short list (D-429): Account settings, each console. */
.drawer__group > summary { list-style: none; cursor: pointer; }
.drawer__group > summary::-webkit-details-marker { display: none; }
.drawer__group > summary .drawer__go { transition: transform var(--dur-1) var(--ease-soft); }
.drawer__group[open] > summary .drawer__go { transform: rotate(90deg); }
.drawer__sublist { list-style: none; margin: 2px 0 10px; padding: 0 0 0 14px; display: grid; gap: 2px; }
.drawer__sublink {
  display: block; padding: 9px 12px; border-radius: 12px;
  font-size: 17px; color: var(--ink); text-decoration: none;
}
@media (hover: hover) and (pointer: fine) {
  .drawer__sublink:hover { background: var(--hair-soft); }
}
.drawer__sublink[aria-current="page"] { background: var(--hair-soft); text-decoration: underline; text-underline-offset: 0.18em; }
/* The tabs at the top of a group's pages (D-429): one row, scrolled sideways on a phone. */
.account-tabs {
  display: flex; gap: 6px; overflow-x: auto; -webkit-overflow-scrolling: touch;
  padding-top: 12px; padding-bottom: 4px; scrollbar-width: none;
}
.account-tabs::-webkit-scrollbar { display: none; }
.account-tabs__tab {
  flex: none; padding: 8px 14px; border-radius: 999px;
  font-size: 15px; color: var(--ink-2); text-decoration: none; white-space: nowrap;
  border: 1px solid var(--hair);
}
.account-tabs__tab.is-current { color: var(--paper); background: var(--ink); border-color: var(--ink); }
.account-tabs + .section { padding-top: 12px; }
.account-links { list-style: none; display: grid; gap: 10px; margin-top: 24px; }
.account-links a { font-size: 17px; }

.account-data { margin-top: 32px; display: grid; gap: 10px; }
.account-data h2 { font-size: 19px; font-weight: 600; letter-spacing: -0.02em; }
.account-data p { color: var(--fg-2); line-height: 1.55; }
.account-data a { color: var(--fg); }
.account-data__delete { font-size: 14px; }

/* What needs you (Part 4.15, R-35): first on the page, and plain, because
   everything in it is somewhere to go. */
.account-needs {
  display: grid; gap: 10px;
  padding-bottom: 24px; margin-bottom: 24px; border-bottom: 1px solid var(--line);
}
.account-needs__title { font-size: 19px; font-weight: 600; letter-spacing: -0.02em; }
.account-needs__list { list-style: none; display: grid; gap: 10px; }
.account-needs__list a { font-size: 17px; color: var(--fg); }
.account-needs__none { color: var(--fg-2); line-height: 1.55; }

/* The decisions made about a member's comments (Part 4.15). */
.account-decisions { list-style: none; display: grid; gap: 28px; }
.account-decisions__one { display: grid; gap: 10px; line-height: 1.55; }
.account-decisions__one a { color: var(--fg); }
.account-decisions__title { font-size: 17px; font-weight: 600; margin: 0; }
.account-decisions__label { font-size: 13px; font-weight: 600; color: var(--fg-2); }
.account-decisions__quote { margin: 0; padding-inline-start: 14px; border-inline-start: 2px solid var(--line); color: var(--fg-2); }

/* ---------- Comments: writing one ----------
   The list itself is further up, under "Comments". This is the part a member
   uses: the box, the reply banner, the report form and the three reactions. */
.comment-form { max-width: 68ch; margin: 24px auto 0; display: grid; gap: 14px; }
.comment-form__replying {
  font-size: 14px; color: var(--fg-2);
  padding: 10px 14px; border: 1px solid var(--line); border-radius: 12px;
}
.comment__head { display: flex; align-items: center; gap: 10px; }
.comment__when { font-size: 13px; color: var(--fg-2); margin-inline-start: auto; }
.comment__tools { display: flex; gap: 16px; margin-top: 10px; }
.comment__tool { font-size: 14px; }
.comment__tool--quiet { color: var(--fg-2); }
.comments--replies {
  margin-top: 14px; margin-inline-start: 18px;
  padding-inline-start: 14px; border-inline-start: 1px solid var(--line);
  gap: 12px;
}

.reactions { max-width: 68ch; margin: 28px auto 0; display: grid; gap: 10px; }
.reactions__label { font-size: 14px; color: var(--fg-2); }
.reactions__row { display: flex; flex-wrap: wrap; gap: 10px; }
.reactions__row .pill { cursor: pointer; font: inherit; }

/* ---------- Writing a story, and deciding what happens to it ----------
   All Worker-rendered, under /account/stories/. The approval screen is where
   non-negotiable 9 is actually exercised, so the text an author is approving
   has to read like the story it is about to become, not like a form. */
.story-form { display: grid; gap: 22px; }
/* "Whose story is this?" reveals a section (Part 4.11). Without JavaScript
   both sections show, each under the answer it belongs to. */
.story-form__when {
  border: 0; border-inline-start: 2px solid var(--line); margin: 0;
  padding: 2px 0 2px 16px; min-inline-size: 0; display: grid; gap: 18px;
}
.story-form__when[hidden], .story-form [data-when-alive][hidden] { display: none; }
.story-form__when-legend { font-size: 15px; font-weight: 600; color: var(--fg-2); padding: 0; margin-bottom: 4px; }
.story-form__note {
  font-size: 14px; color: var(--fg-2); line-height: 1.55;
  padding: 12px 14px; border: 1px solid var(--line); border-radius: 12px;
}

.story-list { list-style: none; display: grid; gap: 14px; margin-bottom: 28px; }
.story-list__item {
  background: var(--card); border: 1px solid var(--card-line);
  border-radius: 16px; padding: 18px 20px;
}
.story-list__status {
  font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--fg-2);
}
.story-list__title { margin-top: 6px; font-size: 21px; letter-spacing: -0.02em; }
.story-list__next { margin-top: 8px; font-size: 14px; color: var(--fg-2); line-height: 1.55; }

/* What an editor changed, and what it said before. Side by side on a wide
   screen, stacked on a phone, which is where Joel reads everything. */
.story-changes {
  margin-top: 24px; padding: 18px 20px;
  border: 2px solid var(--fg); border-radius: 16px;
}
.story-changes__title { font-size: 19px; letter-spacing: -0.02em; }
.story-changes__why { margin-top: 6px; font-size: 14px; color: var(--fg-2); }
.story-changes__one { margin-top: 18px; }
.story-changes__label {
  font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--fg-2);
}
.story-changes__was, .story-changes__now { margin-top: 6px; line-height: 1.55; }
.story-changes__was { color: var(--fg-2); text-decoration: line-through; }
.story-changes__was span, .story-changes__now span {
  display: inline-block; min-width: 42px;
  font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  text-decoration: none; color: var(--fg-2);
}

.story-read { margin-top: 28px; display: grid; gap: 26px; }
.story-read__title { font-size: 19px; letter-spacing: -0.02em; }
.story-read__body { margin-top: 8px; line-height: 1.65; white-space: pre-wrap; }

.story-actions { margin-top: 32px; display: grid; gap: 16px; }
.story-actions__note { margin-top: 6px; font-size: 13px; color: var(--fg-2); line-height: 1.5; }

/* ---------- The partner portal ----------
   Worker-rendered, never cached, and read by caseworkers on a phone between
   appointments. Short labels, no persuasion, and the cost lines laid out so a
   thumb can reach both halves of a row. */
.partner-who {
  font-size: 19px; font-weight: 600; letter-spacing: -0.02em;
  padding-bottom: 16px; border-bottom: 1px solid var(--line);
}
.partner-section { margin-top: 32px; font-size: 19px; letter-spacing: -0.02em; }

.partner-owed {
  margin-top: 20px; padding: 16px 18px;
  border: 2px solid var(--fg); border-radius: 16px;
}
.partner-owed__title { font-size: 16px; font-weight: 600; }
.partner-owed__list { list-style: none; margin-top: 10px; display: grid; gap: 8px; font-size: 15px; }

.partner-list { list-style: none; margin-top: 14px; display: grid; gap: 14px; }
.partner-list__item {
  background: var(--card); border: 1px solid var(--card-line);
  border-radius: 16px; padding: 16px 18px;
}
.partner-list__status {
  font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--fg-2);
}
.partner-list__title { margin-top: 6px; font-size: 19px; letter-spacing: -0.02em; }
.partner-list__line { margin-top: 6px; font-size: 14px; color: var(--fg-2); line-height: 1.5; }
.partner-list__amount { margin-top: 8px; font-size: 15px; font-weight: 600; }

.partner-form { display: grid; gap: 26px; }
.partner-form__note, .partner-form__consent {
  font-size: 14px; color: var(--fg-2); line-height: 1.55;
}
.partner-form__consent {
  padding: 12px 14px; border: 1px solid var(--line); border-radius: 12px;
}
.partner-fieldset { border: 0; padding: 0; margin: 0; min-inline-size: 0; display: grid; gap: 18px; }
.partner-fieldset__legend { font-size: 19px; font-weight: 600; letter-spacing: -0.02em; }
.partner-fieldset__note { font-size: 14px; color: var(--fg-2); line-height: 1.55; }

/* One row per thing being paid for. Two columns on a wide screen, stacked on
   a phone, where every one of these is actually filled in. */
.partner-items { display: grid; gap: 10px; }
.partner-items__row { display: grid; grid-template-columns: 1fr 140px; gap: 10px; }
@media (max-width: 560px) { .partner-items__row { grid-template-columns: 1fr; } }
.partner-items__what, .partner-items__amount { display: grid; gap: 4px; }
.partner-items__what span, .partner-items__amount span {
  font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--fg-2);
}

.partner-note {
  margin-top: 18px; padding: 16px 18px;
  border: 2px solid var(--fg); border-radius: 16px;
}
.partner-note__title { font-size: 16px; font-weight: 600; margin-bottom: 6px; }

.partner-read { margin-top: 24px; display: grid; gap: 14px; }
.partner-read dt {
  font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--fg-2);
}
.partner-read dd { margin-top: 4px; line-height: 1.55; }

.partner-withdrawn {
  margin-top: 24px; padding: 14px 16px;
  border: 1px solid var(--line); border-radius: 12px;
  font-size: 14px; color: var(--fg-2); line-height: 1.55;
}

/* ---------- Volunteering and mentoring ----------
   Worker-rendered under /account/. The one thing every screen here has to
   keep saying is that matching happens by email through the foundation, so
   the notes are part of the layout rather than an afterthought under it. */
.volunteer-heading {
  margin-top: 36px; font-size: 19px; letter-spacing: -0.02em;
  padding-bottom: 10px; border-bottom: 1px solid var(--line);
}
.volunteer-form { display: grid; gap: 22px; }
.volunteer-form__note, .mentor-offer__note, .mentor-offer__what {
  font-size: 14px; color: var(--fg-2); line-height: 1.55;
}
.volunteer-form__note, .mentor-offer__note {
  padding: 12px 14px; border: 1px solid var(--line); border-radius: 12px;
}

.volunteer-list { list-style: none; margin-top: 16px; display: grid; gap: 14px; }
.volunteer-list__item {
  background: var(--card); border: 1px solid var(--card-line);
  border-radius: 16px; padding: 16px 18px;
}
.volunteer-list__status {
  font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--fg-2);
}
.volunteer-list__title { margin-top: 6px; font-size: 19px; letter-spacing: -0.02em; }
.volunteer-list__body { margin-top: 8px; line-height: 1.55; }
.volunteer-list__note { margin-top: 8px; font-size: 14px; color: var(--fg-2); line-height: 1.55; }

/* Yes and no side by side, both reachable with a thumb, neither the louder
   of the two. A no here is a complete answer. */
.volunteer-answer { margin-top: 14px; display: flex; flex-wrap: wrap; gap: 10px; }
.volunteer-answer .pill { cursor: pointer; font: inherit; }

.mentor-offer {
  margin-top: 28px; display: grid; gap: 14px;
  padding: 18px 20px; border: 1px solid var(--line); border-radius: 16px;
}

/* ---------- The admin ----------
   Joel runs this foundation from a phone. Not "also on a phone": that is the
   only device. So everything below is one column, every action is a full
   width button a thumb reaches, and nothing needs a hover, a right click or a
   second window. There are no tables: a table with eight columns is not a
   small table on a phone, it is an unusable one. */
.admin-back { font-size: 14px; margin-bottom: 14px; }
.admin-who { font-size: 14px; color: var(--fg-2); margin-bottom: 18px; }
.admin-heading {
  margin-top: 36px; font-size: 19px; letter-spacing: -0.02em;
  padding-bottom: 10px; border-bottom: 1px solid var(--line);
}
.admin-links { list-style: none; margin-top: 14px; display: grid; gap: 12px; font-size: 17px; }

/* The dashboard. Every number is a thing to do, so every number is a link,
   and one with work behind it is drawn heavier than one without. */
.admin-counts { list-style: none; display: grid; gap: 12px; }
.admin-count {
  background: var(--card); border: 1px solid var(--card-line);
  border-radius: 16px; padding: 16px 18px;
}
.admin-count--due { border-color: var(--fg); border-width: 2px; }
.admin-count--off { opacity: .65; }
.admin-count__link {
  display: flex; align-items: baseline; gap: 14px;
  text-decoration: none; color: var(--fg); min-height: 44px;
}
.admin-count__n {
  font-size: 32px; font-weight: 600; letter-spacing: -0.03em;
  min-width: 1.4em; font-variant-numeric: tabular-nums;
}
.admin-count__label { font-size: 17px; line-height: 1.3; }
.admin-count__note { margin-top: 6px; font-size: 13px; color: var(--fg-2); line-height: 1.5; }

/* Every queue looks the same, whatever it holds. Somebody moving between six
   of them on a phone should not be relearning a layout each time. */
.admin-queue { list-style: none; display: grid; gap: 12px; }
.admin-queue__item {
  background: var(--card); border: 1px solid var(--card-line);
  border-radius: 16px; padding: 16px 18px;
}
.admin-queue__status {
  font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--fg-2);
}
.admin-queue__title { margin-top: 6px; font-size: 18px; letter-spacing: -0.02em; line-height: 1.35; }
.admin-queue__line { margin-top: 6px; font-size: 14px; color: var(--fg-2); }
.admin-queue__lines { margin: 6px 0 0; padding-inline-start: 1.4em; font-size: 14px; line-height: 1.5; display: grid; gap: 4px; }
.admin-queue__when { margin-top: 6px; font-size: 13px; color: var(--fg-2); }
/* A drafted email (R-145): never sent by the system, so it sits apart from
   the forms that do send something, with its own light border. */
.admin-queue__draft {
  margin-top: 10px; padding: 12px 14px; border: 1px dashed var(--card-line);
  border-radius: 12px; display: grid; gap: 8px;
}
.admin-empty { color: var(--fg-2); line-height: 1.55; }

/* One switch, one form, one button. A screen where six move together is a
   screen where somebody turns on the wrong one while turning on the right
   one, and one of these makes the site public. */
.admin-switches { list-style: none; display: grid; gap: 14px; }
.admin-switch {
  background: var(--card); border: 1px solid var(--card-line);
  border-radius: 16px; padding: 16px 18px; display: grid; gap: 8px;
}
.admin-switch__name {
  font-size: 13px; font-weight: 600; letter-spacing: .04em;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.admin-switch__state { font-size: 21px; font-weight: 600; letter-spacing: -0.02em; }
.admin-switch__what { font-size: 14px; color: var(--fg-2); line-height: 1.55; }
/* A switch that is out of step, read by nothing, or not checked everywhere
   is drawn heavier, as a dashboard count with work behind it is (D-345). */
.admin-switch--due { border-color: var(--fg); border-width: 2px; }
.admin-switch__where { font-size: 14px; line-height: 1.5; }
.admin-switch__verdict { font-size: 15px; font-weight: 600; line-height: 1.5; }
.admin-switch__how { font-size: 14px; color: var(--fg-2); line-height: 1.55; }

.admin-copy { margin-top: 24px; display: grid; gap: 16px; }
.admin-copy .field__input { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 14px; }
.admin-copy__note { font-size: 13px; color: var(--fg-2); line-height: 1.55; }
.admin-preview {
  margin-top: 14px; padding: 18px 20px;
  border: 1px solid var(--line); border-radius: 16px;
}

/* ---------- The admin's review screens ----------
   What the machine found is never the verdict, so the findings are drawn as a
   worklist beside the text and not as a banner over it. Nothing here is
   coloured to push a decision: black and white is the whole palette, and the
   two buttons on a held comment are deliberately the same weight. */
.admin-findings {
  margin-top: 20px; padding: 16px 18px;
  border: 1px solid var(--line); border-radius: 16px;
}
.admin-findings__title { font-size: 16px; font-weight: 600; }
.admin-findings__note { margin-top: 6px; font-size: 13px; color: var(--fg-2); line-height: 1.55; }
.admin-findings__list { list-style: none; margin-top: 14px; display: grid; gap: 14px; }
.admin-finding { padding-inline-start: 12px; border-inline-start: 2px solid var(--line); }
.admin-finding__kind {
  font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--fg-2);
}
.admin-finding__span { margin-top: 4px; font-weight: 600; line-height: 1.5; }
.admin-finding__why, .admin-finding__suggestion {
  margin-top: 4px; font-size: 14px; color: var(--fg-2); line-height: 1.55;
}

/* A publishing checklist (spec 9.6). One item per line, ticked by a named
   person. A ticked item stays on the screen with when it was ticked: the
   record of who checked what is the point of the list. */
.admin-checklist { list-style: none; margin-top: 14px; display: grid; gap: 10px; }
.admin-checklist__item {
  background: var(--card); border: 1px solid var(--card-line);
  border-radius: 16px; padding: 14px 16px; display: grid; gap: 8px;
}
.admin-checklist__item--done { background: transparent; border-color: var(--line); }
.admin-checklist__label { line-height: 1.5; }
.admin-checklist__who { font-size: 13px; color: var(--fg-2); line-height: 1.5; }

/* Somebody else's words, kept visibly somebody else's. */
.admin-quote {
  margin-top: 20px; padding: 16px 18px;
  background: var(--card); border: 1px solid var(--card-line); border-radius: 16px;
  line-height: 1.6; white-space: pre-wrap;
}

/* On the one screen that shows a message written by somebody in trouble. */
.admin-private {
  margin-top: 18px; padding: 14px 16px;
  border: 2px solid var(--fg); border-radius: 14px;
  font-size: 14px; line-height: 1.55;
}

/* ---------- Community Notes ----------
   Opened from one comment, replacing the comment box rather than sitting
   beside it: three forms on a phone, two of them about a comment somebody has
   scrolled past, is three forms nobody fills in. Helpful and not helpful are
   the same weight, because a note is not a downvote and a screen that makes
   one of them louder has decided. */
.notes { max-width: 68ch; margin: 24px auto 0; display: grid; gap: 16px; }
.notes__about { font-size: 14px; color: var(--fg-2); }
.notes__what {
  font-size: 14px; line-height: 1.6;
  padding: 14px 16px; border: 1px solid var(--line); border-radius: 12px;
}
.notes__closed {
  font-size: 14px; color: var(--fg-2); line-height: 1.55;
  padding: 12px 14px; border: 1px solid var(--line); border-radius: 12px;
}
.notes__list { list-style: none; display: grid; gap: 12px; }
.notes__rate { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px; }
.notes__rate .pill { cursor: pointer; font: inherit; }

.note {
  background: var(--card); border: 1px solid var(--card-line);
  border-radius: 16px; padding: 14px 16px;
}
.note__who { font-size: 13px; font-weight: 600; color: var(--fg-2); }
.note__body { margin-top: 6px; line-height: 1.55; }
.note__where { margin-top: 8px; font-size: 13px; color: var(--fg-2); line-height: 1.5; }
.note__mine { margin-top: 8px; font-size: 13px; color: var(--fg-2); }

/* Sanctioning an account, folded away under the comment's own decision.
   The two questions are genuinely different: whether this comment stays up,
   and whether this account keeps the ability to post. A screen that offers
   both as one action turns every removal into a punishment. */
.admin-sanction {
  margin-top: 28px; padding: 14px 16px;
  border: 1px solid var(--line); border-radius: 16px;
}
.admin-sanction__open { cursor: pointer; font-size: 16px; font-weight: 600; min-height: 44px; display: flex; align-items: center; }
.admin-sanction__note { margin-top: 6px; font-size: 13px; color: var(--fg-2); line-height: 1.55; }
.admin-sanction .form { margin-top: 16px; display: grid; gap: 16px; }

/* Deleting something of your own (Part 5.7): closed until opened, and a box to tick. */
.account-heading { margin-top: 40px; margin-bottom: 16px; font-size: 20px; font-weight: 600; }
.account-delete { margin-top: 8px; }
.account-delete__open { cursor: pointer; font-size: 14px; font-weight: 600; min-height: 44px; display: flex; align-items: center; color: var(--fg-2); }
.account-delete__note { font-size: 13px; color: var(--fg-2); line-height: 1.55; }
.account-delete .form { margin-top: 8px; display: grid; gap: 12px; }

/* ---------- A donor's own giving ---------- */
.giving { list-style: none; display: grid; gap: 12px; }
.giving__item {
  background: var(--card); border: 1px solid var(--card-line);
  border-radius: 16px; padding: 16px 18px;
}
.giving__status {
  font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--fg-2);
}
.giving__amount { margin-top: 6px; font-size: 24px; font-weight: 600; letter-spacing: -0.02em; }
.giving__where { margin-top: 4px; line-height: 1.5; }
.giving__when { margin-top: 6px; font-size: 13px; color: var(--fg-2); }
.giving__note { margin-top: 20px; font-size: 14px; color: var(--fg-2); line-height: 1.55; }
/* Part 5.2: monthly gifts above the list of every gift, and a receipt for
   each one that went through. */
.giving__heading { margin: 28px 0 12px; font-size: 19px; font-weight: 650; letter-spacing: -0.01em; }
.giving__question { border: 1px solid var(--line); border-radius: 14px; padding: 4px clamp(14px, 3vw, 20px) 16px; margin-bottom: 18px; }
.giving__receipt { margin-top: 8px; font-size: 14px; }
.giving__refund { margin-top: 8px; font-size: 14px; color: var(--ink-2); }
.giving__item .form--inline { margin-top: 12px; }

/* A translation beside the English it came from. Stacked on a phone, which is
   the only place this actually gets read: the risk is a draft that put back
   what the English left out, and you cannot see that reading one alone. */
.translate-pair {
  padding: 16px 18px; border: 1px solid var(--line); border-radius: 16px;
  display: grid; gap: 12px;
}
.translate-pair__label {
  font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--fg-2);
}
.translate-pair__english { line-height: 1.6; color: var(--fg-2); }

/* ---------- The private preview strip ----------
   Above the header, on every page, until SITE_PUBLIC goes on. Somebody shown
   this site today is looking at sample stories about invented people, and the
   three things hiding it from strangers all talk to machines. This is the one
   that talks to the person you deliberately let in. */
.private-strip {
  background: var(--fg);
  color: var(--bg);
  padding: 10px 0;
}
.private-strip__text {
  max-width: var(--container, 1200px);
  margin-inline: auto;
  padding-inline: 16px;
  font-size: 13px;
  line-height: 1.5;
}
.private-strip__badge {
  display: inline-block;
  margin-inline-end: 8px;
  padding: 2px 8px;
  border: 1px solid currentColor;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* ---------- Tabs ----------

   Used by Donum Foundation Philanthropy Partners. Two states matter and they
   are NOT the same state:

     Built, no JavaScript. `.tabs` is a row of anchor links and both
     `.tabs__panel`s are on the screen, one under the other. The rules below
     therefore have to look right with every panel visible, which is why a
     panel carries a rule of its own rather than relying on being the only one.

     Upgraded. site.js hides all but one panel with the `hidden` attribute and
     marks the chosen tab `aria-selected="true"`. `.is-current` is set in both
     states, by the build for the first tab and by the script thereafter, so
     the selected look is one rule rather than two that can disagree.           */
.tabs { margin-bottom: clamp(20px, 3vw, 30px); }
.tabs__list {
  display: flex; flex-wrap: wrap; gap: 8px;
  margin: 0; padding: 0; list-style: none;
  border-bottom: 1px solid var(--line);
}
.tabs__item { margin: 0; }
.tabs__tab {
  display: inline-block;
  padding: 10px 16px;
  font-size: clamp(15px, 1.3vw, 17px);
  font-weight: 600;
  color: var(--fg-2, var(--ink-2));
  text-decoration: none;
  border-bottom: 2px solid transparent;
  /* A tab that is 2px taller when selected shifts the row. The border is
     always there and only its colour changes. */
  margin-bottom: -1px;
}
@media (hover: hover) and (pointer: fine) {
  .tabs__tab:hover { color: var(--fg); text-decoration: none; }
}
.tabs__tab.is-current, .tabs__tab[aria-selected="true"] {
  color: var(--fg);
  border-bottom-color: var(--fg);
}
.tabs__panel { margin-bottom: clamp(28px, 4vw, 44px); }
.tabs__panel:last-child { margin-bottom: 0; }
.tabs__panel:focus-visible { outline: 2px solid var(--fg); outline-offset: 6px; }
/* Once one panel is showing at a time, the space under it is the section's. */
:root.js .tabs__panel { margin-bottom: 0; }

/* ---------- A community chance's stages and photos (Part 5.15) ---------- */
.chance__stages { margin: 0 0 20px; padding-left: 1.3em; line-height: 1.6; }
.chance__stages li { margin-bottom: 8px; }
.chance__photos {
  margin: 0; padding: 0; list-style: none;
  display: grid; gap: 16px; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
}
.chance__photos img { display: block; width: 100%; height: auto; border-radius: 10px; }
.chance__photos figure { margin: 0; }
.chance__photos figcaption { margin-top: 6px; font-size: 14px; color: var(--fg-2, var(--ink-2)); }
.chance__note { margin-top: 12px; font-size: 14px; color: var(--fg-2, var(--ink-2)); }

/* ---------- The Donum Chance Pledge (Part 5.12) ----------

   A pledge is set as a document: its first line the title, its second the
   subtitle, every other line kept where it breaks. A blank in the form is a
   small box inside the sentence, so the promise is read while it is filled
   in; the preview under it is the same words with what was typed.           */
.pledge {
  margin-block: clamp(18px, 3vw, 28px);
  padding: clamp(18px, 3vw, 28px);
  border: 1px solid var(--card-line);
  border-radius: 14px;
  background: var(--bg);
}
.pledge__title {
  margin: 0;
  font-size: 13px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
}
.pledge__subtitle { margin: 6px 0 18px; font-size: clamp(20px, 2.2vw, 26px); line-height: 1.25; }
.pledge__line { margin: 0 0 14px; line-height: 1.6; text-wrap: pretty; }
.pledge__line:last-child { margin-bottom: 0; }
.pledge__box {
  display: inline-block;
  min-width: 10ch; max-width: 100%;
  margin: 2px 0;
  padding: 2px 8px;
  border: 1px solid var(--card-line);
  border-radius: 6px;
  font: inherit;
  color: var(--fg);
  background: var(--bg);
}
.pledge__box:focus-visible { outline: 2px solid var(--fg); outline-offset: 2px; }
.pledge__box--error { border-color: var(--danger); }
.pledge__fill { font-weight: 600; }
.pledge__preview { margin-top: clamp(18px, 3vw, 28px); }
.pledge__label, .pledge__by {
  margin: 0; font-size: 13px; font-weight: 600; color: var(--fg-2, var(--ink-2));
}
.pledge__safety {
  margin: 0 0 16px; padding: 12px 16px;
  border-left: 3px solid var(--fg);
  font-size: 15px;
}
.pledge__make { margin: 0 0 18px; }
.pledge__choose { margin-bottom: 8px; }
.pledge__hint { margin: 0; font-size: 15px; color: var(--fg-2, var(--ink-2)); }
.pledge__change { margin-bottom: 18px; }
.pledge__shared { margin: 0; padding: 0; list-style: none; }
.pledge__card { margin-bottom: clamp(18px, 3vw, 28px); }

/* ---------- Your Ancestor Record (Part 5.13) ----------

   A page to keep. Printed, it is the record alone: the bar, the menu, the
   footer and every control are hidden.                                      */
.record {
  margin-block: clamp(18px, 3vw, 28px);
  padding: clamp(18px, 3vw, 28px);
  border: 1px solid var(--card-line);
  border-radius: 14px;
}
.record__person { margin: 0 0 12px; font-size: clamp(22px, 2.4vw, 28px); }
.record__label {
  margin: 18px 0 6px;
  font-size: 13px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--fg-2, var(--ink-2));
}
.record__truths { margin: 0; padding-left: 1.3em; }
.record__line { margin: 0; line-height: 1.6; }
.record__sentence { margin: 20px 0 0; font-size: clamp(18px, 2vw, 22px); font-weight: 600; }
.record__actions { margin-top: 16px; }
@media print {
  .sitehead, .footer, .drawer, .search, .skip-link, .record__actions, .notice { display: none !important; }
  .record { border: 0; padding: 0; }
}

/* ---------- The Donum Thank You Challenge (Part 5.14) ----------

   Three lines, set as what somebody said: the first a little larger, the
   name under them. No card shadow: a thank-you is not a product.            */
.thanks { margin: 0; }
.thanks__lines { margin: 0; padding: 0 0 0 16px; border-left: 3px solid var(--fg); }
.thanks__line { margin: 0 0 6px; line-height: 1.5; text-wrap: pretty; }
.thanks__line--first { font-size: clamp(18px, 2vw, 21px); font-weight: 600; }
.thanks__by { margin: 10px 0 0 19px; font-size: 14px; color: var(--fg-2, var(--ink-2)); }
.thanks-list { margin: 0; padding: 0; list-style: none; }
.thanks-list__item { padding-block: clamp(16px, 2.4vw, 24px); border-top: 1px solid var(--line); }
.thanks-list__item:first-child { border-top: 0; padding-top: 0; }

/* ---------- The Journal ----------

   Donum writing, rather than a member's story, so it is deliberately not a
   `.card`: no box, no shadow, just a rule between entries. A list of what an
   organisation has said reads as a list; the same list in boxes reads as
   products.                                                                   */
.journal { margin: 0; padding: 0; list-style: none; }
.journal__item {
  padding-block: clamp(22px, 3vw, 30px);
  border-top: 1px solid var(--line);
}
.journal__item:first-child { border-top: 0; padding-top: 0; }
.journal__meta {
  margin: 0 0 8px;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 12px;
  font-size: 13px;
  color: var(--fg-2, var(--ink-2));
}
.journal__kind {
  font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
}
.journal__title { margin: 0; font-size: clamp(21px, 2.2vw, 27px); line-height: 1.22; }
.journal__summary { margin: 8px 0 0; color: var(--fg-2, var(--ink-2)); text-wrap: pretty; }
.journal__author { margin: 8px 0 0; font-size: 14px; color: var(--fg-2, var(--ink-2)); }
/* A post's byline, set as a newspaper sets it (D-433): "By" and the name in
   bold with its seal, the role in plain words, the day, then a rule. */
.byline { max-width: 68ch; margin: 0 auto 28px; padding-bottom: 18px; border-bottom: 1px solid var(--hair); }
.byline__who { font-size: 17px; line-height: 1.45; color: var(--ink); }
.byline__name { font-weight: 600; }
.byline__follow { margin-top: 6px; font-size: 15px; }
/* "Follow" beside a handle (R-157), filled after load by site.js */
.follow-slot { font-size: 15px; margin-inline-start: 6px; }
.follow-slot__link { font-weight: 600; }
/* Follow this writer, and the hiring list (the core team batch, A5, A7) */
.follow__state { font-weight: 600; margin-bottom: 8px; }
.byline__when { margin-top: 6px; font-size: 15px; color: var(--fg-2, var(--ink-2)); }

/* The filters. Paths, not query strings, so these are ordinary links and work
   with this stylesheet's job done and nothing else running. */
.journal__filter {
  display: flex; flex-wrap: wrap; gap: 8px;
  margin-bottom: clamp(22px, 3vw, 30px);
}
.journal__chip {
  padding: 7px 15px;
  border: 1px solid var(--card-line);
  border-radius: 999px;
  font-size: 15px;
  font-weight: 600;
  color: var(--fg-2, var(--ink-2));
  text-decoration: none;
}
@media (hover: hover) and (pointer: fine) {
  .journal__chip:hover { color: var(--fg); border-color: var(--fg); text-decoration: none; }
}
.journal__chip.is-current {
  color: var(--bg); background: var(--fg); border-color: var(--fg);
}

/* The Thank You Wall (Part 5.20): its filters are links, like the Journal's,
   and "Show more" is the next page, so nothing here needs the script. */
.thanks-wall__filter { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 clamp(20px, 3vw, 28px); }
.thanks-wall__chip {
  display: inline-flex; align-items: center; min-height: 44px;
  padding: 7px 15px; border: 1px solid var(--card-line); border-radius: 999px;
  font-size: 15px; font-weight: 600; color: var(--fg-2, var(--ink-2)); text-decoration: none;
}
@media (hover: hover) and (pointer: fine) {
  .thanks-wall__chip:hover { color: var(--fg); border-color: var(--fg); text-decoration: none; }
}
.thanks-wall__chip.is-current { color: var(--bg); background: var(--fg); border-color: var(--fg); }
.thanks-wall__more { margin: clamp(20px, 3vw, 28px) 0 0; }
.thanks__line--first a { color: inherit; }

/* ── People and roles (Batch 6.3) ─────────────────────────────────────────── */
.people { list-style: none; margin: 0 0 24px; padding: 0; display: grid; gap: 16px; }
.people__person { border: 1px solid var(--line); border-radius: 12px; padding: 16px; }
.people__name { margin: 0 0 12px; font-size: 16px; overflow-wrap: anywhere; }
.people__roles { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.people__role { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.people__role-name { flex: 1 1 12em; }
.people__role-state { font-size: 14px; color: var(--fg-2); min-width: 5em; }
.people__role--on .people__role-state { color: var(--fg); font-weight: 600; }

/* Batch 6.9: Listen to stories. The list of recordings, the channels line
   above it, and a story's own player. Every player is preload="none". */
.podcast { list-style: none; margin: 0; padding: 0; display: grid; gap: 20px; }
.podcast__item { padding: 20px; border: 1px solid var(--hair); border-radius: 16px; background: var(--paper); }
.podcast__title { margin: 0 0 6px; font-size: 19px; font-weight: 650; letter-spacing: -0.01em; }
.podcast__meta { margin: 0 0 12px; font-size: 14px; color: var(--ink-2); }
.podcast__player { width: 100%; }
.podcast__channels { margin: 0 0 20px; font-size: 15px; color: var(--ink-2); }
.story-audio { margin: 0 0 28px; }
.story-audio__title { margin: 0 0 10px; font-size: 17px; font-weight: 650; }
.story-audio__player { width: 100%; }

/* ══════════════════════════════════════════════════════════════════
   A LONG LIST, FOUND BY TYPING, AND A CALENDAR FOR EVERY DATE
   (Joel, 30 September 2026.) Both are drawn by static/site.js over a
   plain select or date box, which is what is sent. Black and white
   like everything else (spec 12): the chosen day is ink on paper
   turned over, today is a ring, and nothing leans on colour.
   ══════════════════════════════════════════════════════════════════ */
.picker { position: relative; }
.picker__input { padding-inline-end: 40px; background-image: none; }
.picker::after {
  content: ""; position: absolute; inset-inline-end: 16px; top: 22px;
  inline-size: 8px; block-size: 8px; border: solid var(--fg-2, var(--ink-2));
  border-width: 0 1.6px 1.6px 0; transform: translateY(-50%) rotate(45deg);
  transition: transform var(--dur-2) var(--ease); pointer-events: none;
}
.picker.is-open::after { transform: translateY(-15%) rotate(-135deg); }
.picker__list {
  list-style: none; margin: 6px 0 0; padding: 6px;
  max-block-size: 280px; overflow-y: auto; overscroll-behavior: contain;
  background: var(--card, var(--paper)); color: var(--fg, var(--ink));
  border: 1px solid var(--card-line, var(--hair)); border-radius: 14px;
  box-shadow: 0 18px 40px -18px rgba(0,0,0,.35);
  animation: picker-in var(--dur-2) var(--ease);
}
.picker__option, .picker__none {
  padding: 11px 12px; border-radius: 9px; font-size: 16px; line-height: 1.35; cursor: pointer;
}
.picker__none { color: var(--fg-2, var(--ink-2)); cursor: default; }
.picker__option.is-active { background: var(--hair-soft); }
.picker__option[aria-selected="true"] { font-weight: 600; }
.picker__option[aria-selected="true"]::after { content: " \2713"; }
@keyframes picker-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

.calendar { position: relative; }
.calendar__face {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  text-align: start; cursor: pointer;
}
.calendar__face.is-empty .calendar__words { color: var(--fg-2, var(--ink-2)); }
.calendar__icon { display: inline-flex; transition: transform var(--dur-3) var(--ease); }
.calendar.is-open .calendar__icon { transform: rotate(-8deg) scale(1.08); }
.calendar__face.is-picked { animation: calendar-picked var(--dur-4) var(--ease); }
.calendar.is-wanted .calendar__face { border-color: var(--fg, var(--ink)); border-width: 2px; }
.calendar__panel {
  margin-top: 8px; padding: 14px; max-inline-size: 360px;
  background: var(--card, var(--paper)); color: var(--fg, var(--ink));
  border: 1px solid var(--card-line, var(--hair)); border-radius: 20px;
  box-shadow: 0 24px 60px -24px rgba(0,0,0,.45);
  transform-origin: top left; animation: calendar-open var(--dur-3) var(--ease);
}
.calendar__bar { display: grid; grid-template-columns: 40px 1fr 40px; align-items: center; margin-bottom: 8px; }
.calendar__step, .calendar__title, .calendar__day, .calendar__year, .calendar__quick {
  font: inherit; color: inherit; background: none; border: 0; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.calendar__step {
  inline-size: 40px; block-size: 40px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background var(--dur-1) var(--ease-soft);
}
.calendar__step[hidden] { visibility: hidden; display: inline-flex; }
.calendar__title {
  font-size: 17px; font-weight: 600; letter-spacing: -.01em; padding: 8px 12px; border-radius: 999px;
  justify-self: center; transition: background var(--dur-1) var(--ease-soft);
}
.calendar__step:hover:not(:disabled), .calendar__title:hover,
.calendar__day:hover:not(:disabled):not(.is-chosen), .calendar__year:hover:not(:disabled):not(.is-chosen),
.calendar__quick:hover { background: var(--hair-soft); }
.calendar__step:disabled, .calendar__day:disabled, .calendar__year:disabled { opacity: .28; cursor: default; }
.calendar__stage { overflow: hidden; }
.calendar__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.calendar__grid.is-from-right { animation: calendar-from-right var(--dur-3) var(--ease); }
.calendar__grid.is-from-left { animation: calendar-from-left var(--dur-3) var(--ease); }
.calendar__weekday {
  text-align: center; font-size: 12px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--fg-2, var(--ink-2)); padding: 6px 0;
}
.calendar__day {
  aspect-ratio: 1; min-block-size: 40px; border-radius: 50%; font-size: 15px;
  font-variant-numeric: tabular-nums; position: relative;
  transition: background var(--dur-1) var(--ease-soft), transform var(--dur-1) var(--ease);
}
.calendar__day:active:not(:disabled) { transform: scale(.9); }
.calendar__day.is-today, .calendar__year.is-today { box-shadow: inset 0 0 0 1.5px var(--fg, var(--ink)); }
.calendar__day.is-chosen, .calendar__year.is-chosen {
  background: var(--fg, var(--ink)); color: var(--bg, var(--paper)); font-weight: 600;
  animation: calendar-pop var(--dur-3) var(--ease);
}
.calendar__day:focus-visible, .calendar__year:focus-visible, .calendar__step:focus-visible,
.calendar__title:focus-visible, .calendar__quick:focus-visible {
  outline: 2px solid var(--fg, var(--ink)); outline-offset: 2px;
}
.calendar__years { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.calendar__years.is-rising { animation: calendar-rise var(--dur-3) var(--ease); }
.calendar__year { padding: 14px 0; border-radius: 999px; font-size: 16px; font-variant-numeric: tabular-nums; }
.calendar__foot {
  display: flex; justify-content: space-between; gap: 8px; margin-top: 10px; padding-top: 10px;
  border-top: 1px solid var(--line, var(--hair-soft));
}
.calendar__quick { font-size: 15px; font-weight: 600; padding: 8px 14px; border-radius: 999px; }
.calendar__quick:disabled { opacity: .3; cursor: default; }
@keyframes calendar-open { from { opacity: 0; transform: scale(.96) translateY(-6px); } to { opacity: 1; transform: none; } }
@keyframes calendar-from-right { from { opacity: 0; transform: translateX(28px); } to { opacity: 1; transform: none; } }
@keyframes calendar-from-left { from { opacity: 0; transform: translateX(-28px); } to { opacity: 1; transform: none; } }
@keyframes calendar-rise { from { opacity: 0; transform: translateY(10px) scale(.98); } to { opacity: 1; transform: none; } }
@keyframes calendar-pop { 0% { transform: scale(.7); } 60% { transform: scale(1.08); } 100% { transform: scale(1); } }
@keyframes calendar-picked { 0% { box-shadow: 0 0 0 0 var(--hair); } 40% { box-shadow: 0 0 0 6px var(--hair); } 100% { box-shadow: 0 0 0 0 transparent; } }
@media (prefers-reduced-motion: reduce) {
  .picker__list, .calendar__panel, .calendar__day.is-chosen, .calendar__year.is-chosen { animation: none; }
  .picker::after, .calendar__icon { transition: none; }
}

/* A chance's amounts in the visitor's currency (30 September 2026). */
.chance__convert { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line, var(--hair-soft)); }
.chance__convert[hidden] { display: none; }
.chance__about { margin: 0; font-size: 17px; font-weight: 600; min-height: 1.4em; }

/* ── A planned project's page (Batch 9.3) ─────────────────────────────────
   Every part is a native <details>, so it opens with no JavaScript; its bar
   is the same <progress> the Results page and the chance cards use. */
.project { display: grid; gap: 12px; max-inline-size: 46rem; }
.project__label { justify-self: start; margin: 0; padding: 3px 10px; border: 1px solid var(--card-line); border-radius: 999px; font-size: 12px; font-weight: 600; }
.project__notice { margin: 0; padding: 14px 16px; border: 1px solid var(--line); border-radius: 12px; line-height: 1.5; }
.project__total { margin: 0; font-size: clamp(26px, 3vw, 34px); font-weight: 700; font-variant-numeric: tabular-nums; }
.project__bar { width: 100%; }
.project__parts { list-style: none; padding: 0; margin: 16px 0 0; display: grid; gap: 10px; }
.project__part { border: 1px solid var(--card-line); border-radius: 14px; background: var(--card); }
.project__part-head { display: grid; gap: 6px; padding: 14px 16px; cursor: pointer; list-style: none; }
.project__part-head::-webkit-details-marker { display: none; }
.project__part-title { font-weight: 600; font-size: 17px; }
.project__part-title::after { content: " +"; color: var(--fg-2); }
.project__part[open] .project__part-title::after { content: " \2212"; }
.project__part-figures { font-size: 14px; color: var(--fg-2); font-variant-numeric: tabular-nums; }
.project__units { list-style: none; margin: 0; padding: 0 16px 14px; display: grid; gap: 12px; }
.project__unit { display: grid; gap: 4px; padding-top: 12px; border-top: 1px solid var(--line); }
.project__unit p { margin: 0; }
.project__unit-what { font-weight: 600; }
.project__unit-figures, .project__unit-price { font-size: 14px; font-variant-numeric: tabular-nums; }
.project__unit-basis, .project__unit-early { font-size: 13px; color: var(--fg-2); }
.project__unit-basis span { font-weight: 600; }
.project__give { font-weight: 600; font-size: 14px; }
.project__table-wrap { overflow-x: auto; margin-top: 12px; }
.project__approvals { width: 100%; border-collapse: collapse; font-size: 14px; }
.project__approvals th, .project__approvals td { text-align: start; padding: 9px 8px 9px 0; border-bottom: 1px solid var(--line); vertical-align: top; }
.project__approvals thead th { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-2); }
.project__approvals tbody th { font-weight: 600; }
/* The case on a planned project's page and the plan pages (Batch 9.3, 9.9),
   mirroring the model's presentation: four fact tiles (.v value, .k label,
   .s note with its source), the money strip, "Read more" (details.more, closed
   by default) and one question with its answer (details.qa). The plan pages'
   generated Markdown uses the same class names, so one set of rules serves both. */
.project__subtitle { margin: 12px 0 0; font-size: 17px; font-weight: 600; }
.project__list { margin: 0; padding-inline-start: 1.2em; display: grid; gap: 8px; line-height: 1.55; }
/* When it happens, on a planned project's page (Joel, 11 October 2026): the
   month it opens, then its stages in order, numbered and joined by a line. */
.project__when { font-size: 17px; }
.project__timeline { list-style: none; margin: 4px 0 0; padding: 0; counter-reset: stage; }
.project__timeline li { counter-increment: stage; position: relative; display: grid; grid-template-columns: 28px 1fr; gap: 12px; padding-bottom: 14px; line-height: 1.5; }
.project__timeline li::before { content: counter(stage); display: grid; place-items: center; inline-size: 28px; block-size: 28px; border: 1px solid var(--card-line); border-radius: 50%; background: var(--card); font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
.project__timeline li:not(:last-child)::after { content: ""; position: absolute; inset-inline-start: 14px; inset-block: 28px 0; border-inline-start: 1px solid var(--card-line); }
.project__timeline li > span { padding-top: 3px; }
.project > p { margin: 0; line-height: 1.6; }
.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin: 6px 0; }
.fact { display: flex; flex-direction: column; gap: 2px; min-width: 0; padding: 12px 14px; border: 1px solid var(--card-line); border-radius: 12px; background: var(--card); }
.fact p, .money p { margin: 0; }
.fact .v { font-size: 22px; font-weight: 700; letter-spacing: -.01em; line-height: 1.2; font-variant-numeric: tabular-nums; }
.fact .k { font-size: 13px; font-weight: 600; }
.fact .s { font-size: 12px; line-height: 1.4; color: var(--fg-2); }
.money { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px; margin: 6px 0; overflow: hidden; border: 1px solid var(--line); border-radius: 12px; background: var(--line); }
.money > div { min-width: 0; padding: 10px 12px; background: var(--card); }
.money .k { font-size: 12px; color: var(--fg-2); }
.money .v { font-size: 17px; font-weight: 700; line-height: 1.25; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.money .s { font-size: 12px; line-height: 1.35; color: var(--fg-2); }
@media (max-width: 560px) { .money { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
details.more, details.qa { margin: 4px 0; border: 1px dashed var(--card-line); border-radius: 12px; padding: 2px 14px; }
details.qa { border-style: solid; background: var(--card); }
details.more > summary, details.qa > summary { cursor: pointer; list-style: none; padding: 9px 0; font-weight: 600; }
details.more > summary { font-size: 14px; }
details.more > summary::-webkit-details-marker, details.qa > summary::-webkit-details-marker { display: none; }
details.more > summary::before { content: "+ "; font-weight: 700; }
details.more[open] > summary::before { content: "\2212 "; }
.more__body { display: grid; gap: 10px; padding-bottom: 12px; line-height: 1.6; }
.more__body p { margin: 0; }
.chart { margin: 6px 0; overflow: hidden; border: 1px solid var(--line); border-radius: 12px; }
.chart svg { display: block; width: 100%; height: auto; }
/* The plan pages (Batch 9.9): the list of sections, the tables, footnotes. */
/* "On this page" (D-364), first a plan's (Joel, 11 October 2026: "beautifully
   organized"), now every long page's: one list, a line each, any numbers in
   their own column; two columns where there is room. */
.toc { scroll-margin-top: calc(var(--nav-h) + 12px); }
.toc__list { margin: 12px 0 0; padding: 0; list-style: none; columns: 2 20rem; column-gap: 36px; }
.toc__list li { break-inside: avoid; border-bottom: 1px solid var(--line); }
.toc__list a { display: flex; align-items: baseline; gap: 6px; min-height: 44px; box-sizing: border-box; padding: 11px 0; font-size: 15px; line-height: 1.4; text-decoration: none; color: var(--fg); }
.toc__n { flex: 0 0 2.2em; color: var(--fg-2); font-variant-numeric: tabular-nums; }
@media (hover: hover) and (pointer: fine) { .toc__list a:hover span:last-child { text-decoration: underline; } }
.toc__title { margin: 0; font-size: 15px; font-weight: 600; }
/* A heading a line of the list goes to lands below the bar, not under it. */
.prose h2, .prose h3, .section[id] { scroll-margin-top: calc(var(--nav-h) + 12px); }
/* When a planned project opens, under its name on its card. */
.card__when { margin-top: 8px; font-size: 13px; font-weight: 600; color: var(--fg-2); }
/* "Sort by" on Open chances (Joel, 11 October 2026). */
.chances__sort { display: grid; gap: 8px; max-inline-size: 22rem; margin: 0 0 32px; }
.chances__sort[hidden] { display: none; }
/* "Show" beside "Sort by" (Joel, 11 October 2026): side by side where there
   is room, one above the other on a phone. Over a project's parts, "Show"
   alone, closer to its list. */
.chances__controls { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: 16px; max-inline-size: 46rem; margin: 0 0 32px; }
.chances__controls .chances__sort { max-inline-size: none; margin: 0; }
.chances__controls:not(:has(> :not([hidden]))) { display: none; }
.project .chances__show { margin: 4px 0 4px; }
.chances__none { margin: -16px 0 32px; color: var(--fg-2); }
.project .chances__none { margin: 4px 0; }
.plan { max-width: 46rem; }
.plan h2, .plan h3, .plan h4 { scroll-margin-top: calc(var(--nav-h) + 12px); }
.plan__table { width: 100%; border-collapse: collapse; font-size: 14px; line-height: 1.45; }
.plan__table th, .plan__table td { text-align: start; padding: 8px 10px 8px 0; border-bottom: 1px solid var(--line); vertical-align: top; }
.plan__table thead th { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-2); }
.plan__table .plan__num { text-align: end; white-space: nowrap; font-variant-numeric: tabular-nums; }
.plan__ref { font-size: .72em; line-height: 0; }
.plan__ref a, .plan__back { text-decoration: none; }
.plan__notes { font-size: 14px; color: var(--fg-2); }
/* An amount set in dollars (9.6); static/site.js may add the visitor's own currency after it. */
.amt { font-variant-numeric: tabular-nums; }
/* A planned project's form (Batch 9.4). */
.planned { display: grid; gap: 18px; }
.planned__for { margin: 0; font-weight: 600; }
.planned__for a { margin-inline-start: 8px; font-weight: 400; }
.planned__kinds { border: 0; padding: 0; margin: 0; display: grid; gap: 8px; }
.planned__kind { display: flex; gap: 10px; align-items: flex-start; font-size: 16px; line-height: 1.4; min-height: 44px; }
.planned__kind input { margin-top: 3px; inline-size: 20px; block-size: 20px; flex: none; }
.planned__receives { display: block; font-size: 13px; color: var(--fg-2); }
/* The Philanthropy Partner box (Batch 9.7): on the Donate form and a planned project's form. */
.partner-box { display: grid; gap: 4px; padding: 14px 16px; border: 1px solid var(--line); border-radius: 12px; }
.partner-box__label { display: flex; gap: 10px; align-items: flex-start; font-size: 16px; line-height: 1.4; min-height: 44px; cursor: pointer; }
.partner-box__label input { margin-top: 3px; inline-size: 20px; block-size: 20px; flex: none; }
.partner-box__link { margin: 0 0 0 30px; font-size: 14px; }
.planned select optgroup { font-weight: 600; }
[data-planned-when-money][hidden], [data-planned-when-units][hidden] { display: none; }
.chances__endowment { margin: 0 0 28px; max-inline-size: 42rem; line-height: 1.55; color: var(--fg-2); }
.chances__endowment .chevron-link { display: inline-flex; margin-top: 6px; }
/* The visitor's own currency after an amount (9.6): muted, and never in place of it. */
.amt__about { color: var(--fg-2); font-weight: 400; font-size: .92em; }
.currency { margin: 4px 0 20px; max-inline-size: 26rem; }
.currency .convert__note { margin-top: 6px; font-size: 13px; color: var(--fg-2); }

/* ── The Student Laptop Draw (Batch 10.5) ────────────────────────────────────
   Ticket codes and hashes in a fixed-width face, so a reader can compare them
   character by character; the notice set apart; the list of codes in columns. */
.draw__notice { margin-top: 28px; padding: 16px 18px; border: 1px solid var(--line); border-radius: 14px; }
.draw__notice-title { margin: 0 0 6px; font-size: 16px; font-weight: 600; }
.draw__notice p { margin: 0; font-size: 15px; line-height: 1.5; }
.draw__count { font-weight: 600; }
.draw__code, .draw__hash { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-variant-numeric: tabular-nums; letter-spacing: 0.02em; }
.draw__hash { font-size: 13px; overflow-wrap: anywhere; }
.draw__list { list-style: none; margin: 12px 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 6px 16px; }
.draw__result { margin-top: 16px; padding: 14px 16px; border: 1px solid var(--line); border-radius: 14px; }
.draw__result p { margin: 0; }
.draw__months, .draw__winners { list-style: none; margin: 16px 0 0; padding: 0; display: grid; gap: 12px; }
.draw__month { display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: baseline; }
.draw__status { color: var(--fg-2); font-size: 14px; }
.draw__picks { margin: 12px 0 0; padding-left: 22px; display: grid; gap: 6px; }
.draw__role { font-weight: 600; }
.draw__check { margin-top: 28px; }
.draw__check-result { margin-top: 10px; font-weight: 600; }
.draw__winner { display: grid; gap: 8px; }
.draw__photo { width: 100%; max-width: 420px; height: auto; border-radius: 14px; }
.draw__quote { margin: 8px 0; padding-left: 14px; border-left: 3px solid var(--line); }

/* ---------- Browsing a long list (D-363) ----------
   The filters are a plain form sent by GET, so every view is an address; the
   same grid as the Show and Sort controls on Open chances. "Show more" ends
   every list that is longer than one batch: a tap adds the next batch where
   the reader is, never by itself, because a list that grows as you scroll
   spends a reader's data and hides the footer. */
.filters {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 16px; max-inline-size: 60rem; margin: 0 0 32px; align-items: end;
}
/* "Sort" (Joel, 14 October 2026, D-369): the choices behind one button, so
   the list starts on the first screen of a phone. A <details>: it opens and
   closes without the script, and its own marker is replaced by a chevron. */
.sorter { margin: 0 0 28px; }
.sorter[hidden] { display: none; }
.sorter__button {
  display: inline-flex; align-items: center; gap: 10px;
  min-height: 44px; padding: 8px 20px;
  border: 1px solid var(--line); border-radius: var(--pill);
  font-size: 16px; font-weight: 600; cursor: pointer; list-style: none;
  color: var(--fg, var(--ink));
}
.sorter__button::-webkit-details-marker { display: none; }
.sorter__button::marker { content: ""; }
.sorter__mark {
  inline-size: 8px; block-size: 8px; margin-block-start: -4px;
  border-inline-end: 2px solid currentColor; border-block-end: 2px solid currentColor;
  transform: rotate(45deg); transition: transform var(--dur-1, 150ms) var(--ease-soft, ease);
}
.sorter[open] > .sorter__button .sorter__mark { transform: rotate(-135deg); margin-block-start: 4px; }
.sorter[open] > .sorter__button { border-color: var(--fg, var(--ink)); }
@media (prefers-reduced-motion: reduce) { .sorter__mark { transition: none; } }
.sorter__panel { padding-block-start: 16px; }
.sorter .filters, .sorter .chances__controls { margin-block-end: 0; }
/* A question behind one button (D-371): the Donate form's "What would you
   like to give?" and "Where would you like your gift to go?". The button is
   the question, with the answer chosen now under it; every answer is drawn
   and the one whose radio is checked is shown, one rule per answer, so it is
   right with no script and after the browser puts a choice back. */
.chooser { margin: 0; }
.chooser__button {
  display: grid; grid-template-columns: 1fr auto; align-items: center; column-gap: 12px; row-gap: 2px;
  min-height: 44px; padding: 12px 16px;
  border: 1px solid var(--line); border-radius: 12px;
  cursor: pointer; list-style: none; color: var(--fg, var(--ink));
}
.chooser__button::-webkit-details-marker { display: none; }
.chooser__button::marker { content: ""; }
.chooser__question { grid-column: 1; font-size: 17px; font-weight: 650; line-height: 1.3; }
.chooser__answer { display: none; grid-column: 1; font-size: 15px; line-height: 1.4; color: var(--fg-2); }
.chooser__button .sorter__mark { grid-column: 2; grid-row: 1 / span 2; }
.chooser[open] > .chooser__button { border-color: var(--fg, var(--ink)); }
.chooser[open] > .chooser__button .sorter__mark { transform: rotate(-135deg); margin-block-start: 4px; }
.chooser__panel { display: grid; gap: 10px; padding-block-start: 12px; }
@supports not selector(:has(a)) { .chooser__answer[data-drawn] { display: block; } }
.chooser:has(input[name="give_kind"][value="money"]:checked) [data-answer="money"],
.chooser:has(input[name="give_kind"][value="things"]:checked) [data-answer="things"],
.chooser:has(input[name="give_kind"][value="time"]:checked) [data-answer="time"],
.chooser:has(input[name="give_kind"][value="story"]:checked) [data-answer="story"],
.chooser:has(input[name="give_kind"][value="promise"]:checked) [data-answer="promise"],
.chooser:has(input[name="give_kind"][value="partner"]:checked) [data-answer="partner"],
.chooser:has(input[name="to"][value="general"]:checked) [data-answer="general"],
.chooser:has(input[name="to"][value="chance"]:checked) [data-answer="chance"],
.chooser:has(input[name="to"][value="endowment"]:checked) [data-answer="endowment"] { display: block; }
.filters__field { display: grid; gap: 8px; }
.filters__apply { justify-self: start; }
.filters.is-live .filters__apply { display: none; }
.list-more { display: grid; justify-items: center; gap: 12px; margin-top: 32px; text-align: center; }
.list-more__count { font-size: 14px; color: var(--fg-2); }
.list-more__link[aria-busy="true"] { opacity: .6; pointer-events: none; }
/* Both are drawn as grid and flex, which would show through `hidden` (D-367). */
.list-more[hidden], .list-more__link[hidden] { display: none; }

/* ---------- The card behind a handle (handles spec item 10, D-415) ----------
   A <details>, so it works with no script; the summary keeps the line's own
   look, and the card opens under it, inside the comment, never over it. */
.who-card { display: inline; }
.who-card__name { display: inline; cursor: pointer; list-style: none; }
.who-card__name::-webkit-details-marker { display: none; }
.who-card__name:focus-visible { outline: 2px solid var(--fg); outline-offset: 2px; border-radius: 4px; }
.who-card__body {
  display: grid; gap: 10px; margin-top: 8px; padding: 12px 14px; max-width: 32ch;
  background: var(--card); border: 1px solid var(--card-line); border-radius: 14px;
  font-weight: 400;
}
.who-card__who { font-weight: 600; }
.who-card__close { justify-self: start; cursor: pointer; font: inherit; }

/* ---------- A console's band (account spec item 6, D-420) ----------
   Across the top: which hat, the switch to the others, the way back. */
.console-band {
  display: grid; gap: 6px; margin-bottom: 20px; padding: 12px 16px;
  border: 1px solid var(--card-line); border-radius: 14px; background: var(--card);
}
.console-band__as { font-weight: 600; }
.console-band__switch, .console-band__back { font-size: 14px; }

/* ── Your role (the core team batch, A2) ─────────────────────────────── */
.role-card__opening { color: var(--ink-2); margin-bottom: 8px; }
.role-card { border-top: 1px solid var(--hair-soft); padding-block: 22px; }
.role-card__name { font-size: 22px; font-weight: 600; letter-spacing: -0.015em; margin: 0 0 10px; }
.role-card__head { font-size: 15px; font-weight: 600; color: var(--ink-2); margin: 16px 0 6px; }
.role-card__list { padding-inline-start: 1.2em; display: grid; gap: 6px; margin: 0; list-style: disc; }
.role-card--ask { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.role-card--ask .role-card__line { flex-basis: 100%; }
/* Your weekly report (the core team batch, A4) */
.report__section { border-top: 1px solid var(--hair-soft); padding-block: 18px; }
.report__head { font-size: 18px; font-weight: 600; margin: 14px 0 8px; }
.report__q { font-size: 15px; font-weight: 600; color: var(--ink-2); margin: 14px 0 4px; }
.report__a { margin: 0 0 10px; overflow-wrap: anywhere; }
.report__work, .report__rows { padding-inline-start: 1.2em; display: grid; gap: 6px; margin: 0; list-style: disc; }
.report__row { overflow-wrap: anywhere; }
.report__due, .report__who { color: var(--ink-2); }
.report__status { font-weight: 600; }
.report__form { margin-top: 12px; }
.role-card__line { margin: 6px 0 0; }
.role-card__given { margin: 14px 0 0; color: var(--ink-2); font-size: 15px; }

/* ── Passing work on, the board's list, who answers for each job (the core team batch, B8, B9) ── */
.admin-pass-on { margin: -6px 0 18px; }
.handover-list { display: grid; gap: 14px; margin: 10px 0 28px; padding: 0; list-style: none; }
.handover { border: 1px solid var(--hair-soft); border-radius: 14px; padding: 16px; display: grid; gap: 6px; }
.handover--overdue { border-color: var(--accent, var(--ink-2)); }
.handover__direction { font-size: 13px; font-weight: 600; letter-spacing: .02em; color: var(--ink-2); margin: 0; }
.handover__title { font-weight: 600; margin: 0; }
.handover__line, .handover__note { margin: 0; }
.handover__note { color: var(--ink-2); white-space: pre-line; }
.handover__overdue { font-weight: 600; margin-inline-start: 6px; }
.handover__people { margin: 6px 0 0; padding-inline-start: 1.1em; display: grid; gap: 4px; }
.handover__actions { display: grid; gap: 12px; margin-top: 8px; }
.pick { border: 1px solid var(--hair-soft); border-radius: 12px; padding: 10px 12px; }
.pick__summary { cursor: pointer; font-weight: 600; }
.pick__list { list-style: none; padding: 0; margin: 10px 0 0; display: grid; gap: 8px; }

/* The Donum Endowment's page and card (the core team batch, A6). */
.endowment__card { margin: 0 0 28px; }
.endowment__shares { list-style: none; padding: 0; margin: 0; display: grid; gap: 10px; max-inline-size: 42rem; }
.endowment__share { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 4px 16px; padding-block: 10px; border-bottom: 1px solid var(--hair-soft); }
.endowment__amount { font-variant-numeric: tabular-nums; color: var(--ink-2); }
.endowment__hire { padding-inline-start: 1.4em; display: grid; gap: 6px; margin: 12px 0 0; }
/* The team's budget, admin only (CORE_TEAM_FOLLOW_UP.md, item 2) */
.budget { margin-block: 18px 28px; }
.budget__scroll { overflow-x: auto; max-width: 100%; }
.budget__table { border-collapse: collapse; font-size: 13px; min-width: 100%; }
.budget__table td { border: 1px solid var(--hair-soft); padding: 4px 6px; vertical-align: top; max-width: 28em; overflow-wrap: anywhere; }
.budget__n { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }

/* ---------- The Donum Next Step Challenge (community 0057) ----------
   Drawn only while NEXT_STEP_OPEN is on. A status is a word as well as a
   colour, and no colour reads as a fault: changed and stopped are grey,
   never the danger red, because the four answers are equal ways to finish
   (the spec, 6a). Every colour is a theme token, so light and dark both hold. */
.step-how { padding-left: 1.25em; line-height: 1.6; }
.step-totals { display: grid; gap: 12px; margin: 8px 0 24px; }
.step-totals__show { justify-self: start; }
.js .step-totals__show { display: none; }
.step-totals__figures { display: flex; flex-wrap: wrap; gap: 12px 32px; margin: 0; }
.step-totals__figure dt, .step-numbers__item dt { color: var(--fg-2); font-size: .9rem; }
.step-totals__figure dd { margin: 0; font-size: 2rem; font-weight: 600; }
.step-totals__note, .step-numbers__note { color: var(--fg-2); font-size: .9rem; margin: 0; }
.step-numbers { margin-bottom: 20px; }
.step-numbers__list { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 12px; margin: 0 0 8px; }
.step-numbers__item dd { margin: 0; font-size: 1.4rem; font-weight: 600; }
.step-actions-bar { display: flex; flex-wrap: wrap; gap: 8px; }
.step-views { display: flex; gap: 16px; margin: 16px 0; border-bottom: 1px solid var(--line); }
.step-views__link { padding: 8px 0; color: var(--fg-2); text-decoration: none; border-bottom: 2px solid transparent; }
.step-views__link[aria-current="page"] { color: var(--fg); border-bottom-color: var(--fg); }
.step-lines, .step-action-list { list-style: none; padding: 0; margin: 0 0 16px; }
.step-line, .step-action { padding: 12px 0; border-bottom: 1px solid var(--line); }
.step-line__title { display: block; font-weight: 600; }
.step-line__meta, .step-action__meta { display: block; color: var(--fg-2); font-size: .9rem; margin: 2px 0 0; }
.step-one__title { font-size: 1.25rem; font-weight: 600; margin: 4px 0 12px; overflow-wrap: anywhere; }
.step-status { display: inline-block; margin: 0; padding: 2px 10px; border: 1px solid var(--line); border-radius: var(--pill); font-size: .85rem; }
.step-status--going { border-color: var(--verified); color: var(--verified); }
.step-status--done { border-color: var(--seal); color: var(--seal); }
.step-status--changed { border-style: dashed; color: var(--fg-2); }
.step-status--stopped { border-style: dotted; color: var(--fg-2); }
.step-section { margin-top: 32px; padding-top: 24px; border-top: 1px solid var(--line); }
/* A section's heading sits on its line, not 40px under it (D-542). */
.step-section > .account-heading:first-child, .ns-plan > .account-heading:first-child, .ns-saved > .account-heading:first-child { margin-top: 0; }
.step-share__status { color: var(--fg-2); }
/* Each question with its own room (D-542): until 27 October 2026 this rule set
   4px between them, so a box could not be told from the next question. The
   form's own 26px applies; the button stands apart from the last question. */
.step-form, .step-action-form { gap: 26px; }
.form > .form__submit, .form > .step-more + .form__submit { margin-top: 8px; }
.step-more, .step-add, .step-plan__earlier, .step-plan__change, .step-action__ask, .step-action__change { margin: 12px 0; }
/* A part that opens: a row that looks tappable, with its arrow, never bare text. */
.step-more__summary, .step-action__change > summary, .step-add > summary {
  cursor: pointer; font-weight: 600; padding: 12px 14px; min-height: 44px; box-sizing: border-box;
  border: 1px solid var(--line); border-radius: 12px; list-style-position: inside;
}
.step-more[open] > .step-more__summary { margin-bottom: 16px; }
.step-more[open] { display: grid; gap: 26px; }
.step-more[open] > .step-more__summary, .step-more[open] > .field__hint { margin-bottom: 0; }
.step-times { display: flex; flex-wrap: wrap; gap: 16px; }
/* Starts and Ends side by side, each wide enough to read and tap. Safari on an iPhone draws an empty time box with no
   width of its own, so in a row they shrank to slivers (Joel's phone, 28 October 2026, D-545). */
.step-times > .field { flex: 1 1 8rem; min-width: 0; }
.field__input[type="time"] { box-sizing: border-box; width: 100%; min-width: 7.5rem; min-height: 48px; -webkit-appearance: none; appearance: none; }
.step-plan__when, .step-plan__from { color: var(--fg-2); font-size: .9rem; margin: 4px 0; }
.step-plan__text { white-space: pre-wrap; overflow-wrap: anywhere; }
.step-plan__versions { padding-left: 1.25em; }
.step-action__title { font-weight: 600; margin: 0; overflow-wrap: anywhere; }
.step-action__note { margin: 6px 0 0; overflow-wrap: anywhere; }
.step-sort { display: flex; flex-wrap: wrap; align-items: end; gap: 8px 16px; }
/* From Mag (R-162): what done means in parts, and what got in the way. */
.step-items { list-style: none; padding: 0; margin: 0 0 16px; }
.step-item { display: grid; grid-template-columns: 1fr auto; gap: 2px 12px; align-items: center; padding: 10px 0; border-bottom: 1px solid var(--line); }
.step-item__text { margin: 0; overflow-wrap: anywhere; }
.step-item--ticked .step-item__text::before { content: "\2713\00a0"; color: var(--verified); font-weight: 600; }
.step-item__meta { grid-column: 1; margin: 0; color: var(--fg-2); font-size: .9rem; }
.step-item__form { grid-column: 2; grid-row: 1 / span 2; margin: 0; }
.step-ways { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 8px 16px; margin: 4px 0 8px; }
.step-ways__item dt { color: var(--fg-2); font-size: .9rem; }
.step-ways__item dd { margin: 0; font-size: 1.2rem; font-weight: 600; }
/* What got in the way on the challenge page (R-209): closed under one line; each item, its count and a black bar. */
.step-ways-fold { margin: 12px 0 8px; }
.step-ways-fold__summary { cursor: pointer; font-weight: 600; padding: 8px 0; }
.step-way-list { list-style: none; margin: 8px 0; padding: 0; display: grid; gap: 10px; }
.step-way__name { font-weight: 600; }
.step-way__n { font-variant-numeric: tabular-nums; }
.step-way__bar { display: block; height: 10px; margin-top: 4px; background: var(--fg); min-width: 4px; }
.pledge__from-step { color: var(--fg-2); }

/* The chain (part 4). Without a script, the nested list is what shows. With
   one, the chart shows and the list stays for screen readers, out of sight
   until a keyboard reaches one of its links. The chart scrolls inside its
   own frame, so the page never scrolls sideways, even at 360 pixels. */
.step-chart { display: none; }
.js .step-chart { display: block; max-width: 100%; overflow: auto; -webkit-overflow-scrolling: touch;
  border: 1px solid var(--line); border-radius: 12px; background: var(--card, var(--bg)); touch-action: pan-x pan-y pinch-zoom; }
.step-chart__frame { position: relative; }
.step-chart__lines { position: absolute; inset: 0; fill: none; stroke: var(--fg-2); stroke-width: 1.5; }
.step-chart__box { position: absolute; display: flex; flex-direction: column; justify-content: space-between; gap: 4px;
  box-sizing: border-box; padding: 8px 10px; text-align: left; font: inherit; color: var(--fg);
  background: var(--bg); border: 2px solid var(--line); border-radius: 10px; cursor: pointer; overflow: hidden; }
.step-chart__box--going { border-color: var(--verified); }
.step-chart__box--done { border-color: var(--seal); }
.step-chart__box--changed { border-style: dashed; border-color: var(--fg-2); }
.step-chart__box--stopped { border-style: dotted; border-color: var(--fg-2); }
.step-chart__box--planned { border-color: var(--verified); }
.step-chart__box--not_done { border-style: dotted; border-color: var(--fg-2); }
.step-chart__box--written { cursor: default; border-style: solid; border-color: var(--line); color: var(--fg-2); }
.step-chart__words { font-size: .9rem; line-height: 1.3; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; }
.step-chart__meta { font-size: .78rem; color: var(--fg-2); }
.step-chart__status { font-weight: 600; color: var(--fg); }
.step-chart__panel { max-width: min(92vw, 420px); padding: 16px 18px; border: 1px solid var(--line); border-radius: 12px;
  background: var(--bg); color: var(--fg); }
/* Every panel opened by a tap (`popover`), on a browser without popover (Safari and every iPhone browser before
   iOS 17, 26 October 2026, D-529). Such a browser ignores the attribute and draws every panel open, in the page:
   on the timeline, beside the action, squeezing it to one letter a line. So a panel is closed unless it is open:
   the browser's own (:popover-open, a rule an older browser drops whole), or static/site.js's (.is-open), which
   it lays over the page as the browser would. */
[popover]:not(.is-open) { display: none; }
[popover]:popover-open { display: block; }
[popover].is-open { display: block; position: fixed; inset: 0; margin: auto; width: fit-content; height: fit-content;
  max-width: min(92vw, 420px); max-height: calc(100% - 32px); overflow: auto; z-index: 1000;
  box-shadow: 0 8px 32px rgb(0 0 0 / 0.35); }
.step-chart__panel-title { font-weight: 600; overflow-wrap: anywhere; }
.step-chart__panel-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.step-chain__list { padding-left: 1.25em; line-height: 1.6; }
.step-chain__list .step-chain__list { border-left: 1px solid var(--line); margin-left: 4px; }
.step-chain__meta { color: var(--fg-2); font-size: .9rem; }
.js .step-chain__as-list:not(:focus-within) { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ---------- The Next Step Challenge, round two (NEXT_STEP_SPEC_24_OCTOBER.md, part 7) ----------

   Colours only in the challenge's progress, each always with its word: in a
   label, a dot's panel, or the key above each chain. No red anywhere. Purple
   always means a change of course, for steps and actions alike. Two dark
   blocks, as for every token above: the system's dark, and the switch's. */
:root {
  --ns-done: #1e7a3a; --ns-partly-fill: #cfe8d6; --ns-not: #6a6a72; --ns-other: #6b3fa0;
  --ns-waiting: #a15c00; --ns-planned: #131314; --ns-closed: #6a6a72; --ns-going: #2f55d4;
  --ns-heat-1: #e3f2e7; --ns-heat-2: #b9dfc4; --ns-heat-3: #7cc293; --ns-heat-4: #1e7a3a; --ns-heat-ink: #ffffff;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ns-done: #5cc97f; --ns-partly-fill: #1f4a2c; --ns-not: #a6a6ad; --ns-other: #c4a3f0;
    --ns-waiting: #f0b04a; --ns-planned: #f5f5f7; --ns-closed: #a6a6ad; --ns-going: #8aa6ff;
    --ns-heat-1: #173a22; --ns-heat-2: #1f5a33; --ns-heat-3: #2f8a4e; --ns-heat-4: #5cc97f; --ns-heat-ink: #000000;
  }
}
:root[data-theme="dark"] {
  --ns-done: #5cc97f; --ns-partly-fill: #1f4a2c; --ns-not: #a6a6ad; --ns-other: #c4a3f0;
  --ns-waiting: #f0b04a; --ns-planned: #f5f5f7; --ns-closed: #a6a6ad; --ns-going: #8aa6ff;
  --ns-heat-1: #173a22; --ns-heat-2: #1f5a33; --ns-heat-3: #2f8a4e; --ns-heat-4: #5cc97f; --ns-heat-ink: #000000;
}

/* A step's status: a coloured label with its word. */
.ns-status { display: inline-block; margin: 0 0 4px; padding: 2px 10px; border: 1.5px solid currentColor; border-radius: var(--pill); font-size: .85rem; font-weight: 600; }
.ns-status--small { font-size: .78rem; padding: 0 8px; margin-right: 6px; }
.ns-status--going { color: var(--ns-going); }
.ns-status--done { color: var(--ns-done); }
.ns-status--changed { color: var(--ns-other); }
.ns-status--stopped { color: var(--ns-not); }
.ns-swatch { display: inline-block; width: 12px; height: 12px; border-radius: 3px; vertical-align: -1px; }
.ns-swatch--going { background: var(--ns-going); }
.ns-swatch--done { background: var(--ns-done); }
.ns-swatch--changed { background: var(--ns-other); }
.ns-swatch--stopped { background: var(--ns-not); }

/* An action's dot, by its state. */
.ns-dot { display: inline-block; flex: none; width: 14px; height: 14px; border-radius: 50%; box-sizing: border-box; border: 2px solid transparent; vertical-align: -2px; padding: 0; background: transparent; }
.ns-dot--done { background: var(--ns-done); border-color: var(--ns-done); }
.ns-dot--partly { background: var(--ns-partly-fill); border-color: var(--ns-done); }
.ns-dot--not_done { background: var(--ns-not); border-color: var(--ns-not); }
.ns-dot--other { background: var(--ns-other); border-color: var(--ns-other); }
.ns-dot--waiting { border-color: var(--ns-waiting); border-width: 3px; }
.ns-dot--planned { border-color: var(--ns-planned); border-width: 1.5px; }
.ns-dot--closed { border-color: var(--ns-closed); border-style: dashed; }
.ns-dots { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px; }
.ns-dots .ns-dot { width: 10px; height: 10px; }
.ns-dots__earlier { font-size: .78rem; color: var(--fg-2); margin-right: 2px; }
.ns-dots-line { margin: 8px 0 0; }
.ns-waiting { font-size: .85rem; color: var(--ns-waiting); font-weight: 600; }
.ns-word--waiting { color: var(--ns-waiting); font-weight: 600; }
.ns-word--done, .ns-word--partly { color: var(--ns-done); font-weight: 600; }
.ns-word--other { color: var(--ns-other); font-weight: 600; }
.ns-word--not_done, .ns-word--closed, .ns-word--planned { color: var(--fg-2); font-weight: 600; }

/* The key above each chain and chart. */
.ns-key { margin: 8px 0 12px; font-size: .9rem; }
.ns-key summary { cursor: pointer; color: var(--fg-2); }
.ns-key__list { display: flex; flex-wrap: wrap; gap: 6px 16px; padding: 8px 0 0; margin: 0; list-style: none; }

/* The time bar: blue to today, the same blue once the date has passed. */
.ns-timebar { margin: 8px 0 16px; }
.ns-timebar__bar { display: block; width: 100%; height: 8px; }
.ns-timebar__track { fill: var(--line); }
.ns-timebar__fill { fill: var(--ns-going); }
.ns-timebar__sentence { margin: 6px 0 0; color: var(--fg-2); font-size: .9rem; }

/* Chips: tappable choices, radio buttons drawn as chips. Without a script they are ordinary radios. */
.ns-chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 4px 0 8px; }
/* An answer to tap, not a button that does something (D-542): square corners and a grey ground, where a button
   (.pill) is round, so the two cannot be taken for each other. */
.ns-chip { display: inline-block; padding: 8px 14px; border: 1.5px solid var(--card-line, var(--line)); border-radius: 8px; background: var(--hair-soft, var(--bg)); color: var(--fg); font: inherit; font-size: 15px; text-decoration: none; cursor: pointer; }
.ns-chip[aria-current] { border-color: var(--fg); font-weight: 600; }
.ns-chips .field--radios { margin: 0; border: 0; padding: 0; }
.ns-chips .radios { display: flex; flex-wrap: wrap; gap: 8px; }
.ns-chips .radio { padding: 8px 14px; margin-inline: 0; border: 1.5px solid var(--card-line, var(--line)); border-radius: 8px; background: var(--hair-soft, var(--bg)); cursor: pointer; }
.ns-chips .radio:has(input:checked) { border-color: var(--fg); font-weight: 600; }

/* The challenge page. */
.ns-lead { font-size: clamp(18px, 2.2vw, 22px); font-weight: 600; margin: 0 0 16px; }
.ns-entry { display: grid; gap: 8px; margin: 0 0 24px; }
.ns-entry__go { justify-self: start; }
.ns-examples__title { margin: 8px 0 0; font-weight: 600; }
.ns-examples { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; }
.ns-example { margin: 24px 0; padding: 16px 18px; border: 1px dashed var(--card-line, var(--line)); border-radius: 12px; }
.ns-example__label { margin: 0 0 8px; color: var(--fg-2); font-size: .9rem; }

/* A step in My steps: its label, title, dots and lines, one under another. */
.ns-step { display: grid; gap: 2px; }
.ns-step .ns-status--small { justify-self: start; }
.ns-entry__fallback { margin: 0 0 24px; }
.ns-version__whole { margin: 8px 0; }

/* A step's page. */
.ns-head { margin-bottom: 8px; }
/* Opened by a link to its "#", so its heading is not under the top of the screen. */
.ns-next, .ns-first, .ns-saved { scroll-margin-top: 16px; }
.ns-close { margin: 16px 0 0; }
.ns-back { margin-top: 32px; }
/* A page's title and what is under it, with room between (D-542). */
.section__title + .form-wrap { margin-top: 20px; }
/* What can be done next: buttons in a row, wrapping on a phone, each its own target. */
.ns-do { display: flex; flex-wrap: wrap; gap: 10px; margin: 16px 0 0; }
/* Just saved: what was saved, what comes next, and sharing, in one card at the top (D-542). */
.ns-saved { margin-top: 20px; padding: 18px; border: 2px solid var(--fg); border-radius: 14px; }
.ns-saved__said { margin: 0 0 12px; font-weight: 600; font-size: 17px; }
.ns-saved__step { margin: 0; display: grid; gap: 12px; }
.ns-saved__step dt { font-size: 14px; color: var(--fg-2); }
.ns-saved__step dd { margin: 2px 0 0; overflow-wrap: anywhere; }
.ns-saved__what { margin: 0; }
.ns-saved .step-section { margin-top: 20px; }
.ns-plan { margin-top: 32px; padding: 16px 18px; border: 1px solid var(--card-line, var(--line)); border-radius: 12px; }
.ns-plan__line { margin: 2px 0 8px; color: var(--fg-2); font-size: .9rem; }
.ns-plan__now .step-plan__text { margin: 0 0 4px; }
.ns-plan__list { margin: 0 0 4px; padding-left: 1.25em; }
.ns-plan__change { display: flex; flex-wrap: wrap; gap: 8px; }
.ns-plan__change summary { list-style: none; cursor: pointer; }
.ns-answer { padding: 16px 18px; border: 1.5px solid var(--ns-waiting); border-radius: 12px; }
.ns-answer__what { margin: 0 0 8px; }

/* The timeline: a vertical line of dots in time order. */
.ns-tl { list-style: none; margin: 0 0 16px; padding: 0; position: relative; }
.ns-tl::before { content: ""; position: absolute; left: 6px; top: 8px; bottom: 8px; width: 2px; background: var(--line); }
.ns-tl__item { position: relative; display: flex; gap: 12px; padding: 8px 0; }
.ns-tl__dot { position: relative; margin-top: 3px; cursor: pointer; }
.ns-tl__body { flex: 1; min-width: 0; }
.ns-tl__body p { margin: 0 0 4px; }

/* The chain's boxes, round two's states. */
.step-chart__box--partly { border-color: var(--ns-done); background: var(--ns-partly-fill); }
.step-chart__box--other { border-color: var(--ns-other); }
.step-chart__box--waiting { border-color: var(--ns-waiting); border-width: 3px; }
.step-chart__box--closed { border-style: dashed; border-color: var(--ns-closed); }
.step-chart__box .ns-dots { margin: 2px 0; }

/* Plan history: a sheet with a bar that stays at the top. */
.ns-sheet__bar { position: sticky; top: 0; z-index: 2; display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 0; background: var(--bg); border-bottom: 1px solid var(--line); }
.ns-sheet__title { margin: 0; font-size: 1.2rem; }
.ns-sheet__step { color: var(--fg-2); font-size: .9rem; margin: 10px 0; }
.ns-versions { position: sticky; top: 56px; z-index: 1; background: var(--bg); padding: 6px 0; }
.ns-version { padding: 16px 0; border-bottom: 1px solid var(--line); scroll-margin-top: 110px; }
.ns-now { margin-left: 8px; padding: 1px 8px; border: 1.5px solid var(--ns-going); border-radius: var(--pill); color: var(--ns-going); font-size: .8rem; }
.ns-diff__head { margin: 8px 0 2px; font-weight: 600; }
.ns-diff__head--added { color: var(--ns-done); }
.ns-diff__head--removed { color: var(--ns-not); }
.ns-diff__list { margin: 0; padding-left: 1.25em; }
.ns-diff__list--added { border-left: 3px solid var(--ns-done); }
.ns-diff__list--removed { border-left: 3px dashed var(--ns-not); color: var(--fg-2); }
.ns-version__restore { margin-top: 8px; }
.ns-sheet__end { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 20px; }

/* Patterns: cards, the week grid, the bars. Counts, hours and the calendar only. */
.ns-patterns { display: grid; gap: 16px; }
.ns-patterns__wait { color: var(--fg-2); }
.ns-card { padding: 16px 18px; border: 1px solid var(--card-line, var(--line)); border-radius: 12px; overflow-x: auto; }
.ns-card__open { all: unset; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }
.ns-card__figure { font-size: 1.6rem; font-weight: 600; margin: 4px 0; }
.ns-grid { border-collapse: separate; border-spacing: 3px; font-size: .8rem; }
.ns-grid th { font-weight: 600; color: var(--fg-2); text-align: left; padding: 0 4px 0 0; }
.ns-grid__cell { width: 30px; height: 26px; text-align: center; border-radius: 4px; background: var(--line); }
.ns-grid__cell--1 { background: var(--ns-heat-1); }
.ns-grid__cell--2 { background: var(--ns-heat-2); }
.ns-grid__cell--3 { background: var(--ns-heat-3); }
.ns-grid__cell--4 { background: var(--ns-heat-4); color: var(--ns-heat-ink); }
.ns-weeks { display: flex; align-items: flex-end; gap: 8px; }
.ns-weeks__bar { display: grid; justify-items: center; gap: 2px; padding: 0; border: 0; background: none; color: var(--fg-2); font: inherit; font-size: .72rem; cursor: pointer; }
.ns-weeks__bar svg { width: 22px; height: 60px; }
.ns-fill--done { fill: var(--ns-done); }
.ns-fill--partly { fill: var(--ns-partly-fill); stroke: var(--ns-done); stroke-width: .8; }
.ns-fill--other { fill: var(--ns-other); }
.ns-fill--not_done { fill: var(--ns-not); }
.ns-fill--waiting { fill: var(--ns-waiting); }
.ns-take { display: grid; gap: 6px; margin: 4px 0 8px; }
.ns-take dt { color: var(--fg-2); font-size: .9rem; }
.ns-take dd { margin: 0; display: flex; align-items: center; gap: 8px; }
.ns-take__bar { display: inline-block; height: 10px; border-radius: 5px; background: var(--ns-going); }
.ns-take__bar--took { background: var(--ns-done); }

/* Printing the plan's history: every version unfolded, no menu, no buttons. */
@media print {
  .ns-sheet__close, .ns-sheet__end, .ns-version__restore, .ns-versions, .ns-sheet summary { display: none !important; }
  .ns-sheet__bar, .ns-versions { position: static; }
  .ns-version { break-inside: avoid; }
}

/* ── Save and send (SAVE_AND_SEND_SPEC_24_OCTOBER.md, part 2) ─────────────
   The line where a form's buttons were: what is happening, that it worked
   (green, with a tick), or why it did not (red, with a cross). Every colour
   comes with its words and its icon. Red is the site's own --danger; green
   is --sas-done, each at least 4.5:1 on its background in light and in both
   dark themes (test/save-send.test.mjs measures them). */
:root, .theme-light, .theme-muted { --sas-done: #1e7a3a; }
.theme-dark { --sas-done: #5cc97f; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]),
  :root:not([data-theme="light"]) .theme-light,
  :root:not([data-theme="light"]) .theme-muted,
  :root:not([data-theme="light"]) .theme-dark { --sas-done: #5cc97f; }
}
:root[data-theme="dark"],
:root[data-theme="dark"] .theme-light,
:root[data-theme="dark"] .theme-muted,
:root[data-theme="dark"] .theme-dark { --sas-done: #5cc97f; }

.sas { display: flex; align-items: flex-start; gap: .5rem; margin: .75rem 0; font-weight: 600; line-height: 1.45; }
.sas:focus { outline: 2px solid currentColor; outline-offset: 3px; }
.sas__icon { flex: none; width: 1.25em; height: 1.25em; margin-top: .05em; }
.sas__words { min-width: 0; overflow-wrap: anywhere; }
.sas__words strong { font-weight: 700; }
.sas a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.sas--doing { color: var(--fg); }
.sas--done { color: var(--sas-done); }
.sas--failed { color: var(--danger); }
.sas__spinner {
  flex: none; width: 1.1em; height: 1.1em; margin-top: .1em; border-radius: 50%;
  border: 2px solid currentColor; border-right-color: transparent;
  animation: sas-turn .8s linear infinite;
}
@keyframes sas-turn { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .sas__spinner { animation: none; border-right-color: currentColor; opacity: .6; } }
/* Fields locked while a form sends: the words stay readable. */
form[aria-busy="true"] :disabled { opacity: 1; }

/* ── Find a way to finish this step (FIND_A_WAY_SPEC_24_OCTOBER.md) ──────────
   One screen at a time: the dots, the line that says what is still missing,
   the summary, and the team's pages. Every colour comes with its words. */
.way .form { margin-bottom: 16px; }
.way-step { color: var(--fg-2); margin: 0 0 8px; }
.way-safety { font-weight: 600; margin: 0 0 16px; }
.way-dots { display: flex; gap: 8px; list-style: none; margin: 0 0 16px; padding: 0; }
.way-dots__dot { width: 10px; height: 10px; border-radius: 50%; border: 1.5px solid var(--fg-2); }
.way-dots__dot--done { background: var(--fg-2); }
.way-dots__dot--now { border-color: var(--fg); background: var(--fg); box-shadow: 0 0 0 3px var(--bg), 0 0 0 4.5px var(--fg); }
.way-missing { font-size: 1.15rem; font-weight: 600; margin: 0 0 12px; }
.way-found { font-size: 1.15rem; font-weight: 600; }
.way-summary { border-top: 1px solid var(--line); margin-top: 24px; padding-top: 16px; }
.way-summary__text { white-space: pre-wrap; margin: 0 0 12px; }
.way-ask { border-bottom: 1px solid var(--line); padding: 8px 0; }
.way-how-to-ask, .way-hint, .way-month, .way-context { color: var(--fg-2); }
.way-context { border-left: 3px solid var(--line); padding-left: 12px; }
.way-points { margin: 0 0 12px; padding-left: 20px; }
.way-trust { font-weight: 600; }
.way-answer, .way-entry, .way-worked, .way-connections, .way-needs { margin: 16px 0; }
.way-connect { margin: 0 0 12px; }
.way-begin { margin: 0; }
.way-shared { margin-top: 32px; color: var(--fg-2); }
.link-button { background: none; border: 0; padding: 0; color: inherit; font: inherit; text-decoration: underline; cursor: pointer; }
.money-box__currency--fixed { display: inline-flex; align-items: center; padding: 0 12px; }
.way-chances__list { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 16px; margin: 16px 0; }
.way-chance__figures { margin: 0 0 12px; }
.way-chance__figures dt { color: var(--fg-2); font-size: .9rem; }
.way-chance__figures dd { margin: 0 0 6px; font-weight: 600; }
.way-late { border-left: 4px solid var(--danger); padding-left: 12px; }
.way-late__mark { color: var(--danger); }
/* Screen 1's two parts (R-190): what is sent, without a name, and what only the member sees. */
.way-part { border: 1.5px solid var(--card-line, var(--line)); border-radius: 12px; padding: 12px 16px; margin: 0 0 16px; }
.way-part--mine { border-style: dashed; }
.way-part__title { font-weight: 600; padding: 0 4px; }
.way-part__note { color: var(--fg-2); margin: 4px 0 0; }
