/* ActSmall — minimal, mobile-first, accessible, low-bandwidth */

:root {
  --bg: #f7f5ef;
  --bg-soft: #efece2;
  --ink: #1c2418;
  --ink-soft: #4a5345;
  --rule: #d6d2c2;
  --accent: #355c3a;       /* deep moss green */
  --accent-soft: #5a8a5e;
  --accent-ink: #ffffff;
  --warn-bg: #fff4d6;
  --warn-ink: #6a4b00;
  --warn-rule: #d9b865;
  --danger-bg: #fde4e0;
  --danger-ink: #7a1f12;
  --danger-rule: #c97464;
  --safe-bg: #e6efe2;
  --safe-ink: #1f3a22;
  --max: 64rem;
  --radius: 6px;
  --shadow: 0 1px 0 rgba(0,0,0,0.04), 0 4px 14px rgba(0,0,0,0.05);
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, "Noto Sans", sans-serif;
  font-size: 18px;
  line-height: 1.55;
  color: var(--ink);
  background: var(--bg);
  text-rendering: optimizeLegibility;
}

a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}
a:hover, a:focus { color: #1f3a22; }

h1, h2, h3, h4 {
  font-family: Georgia, "Times New Roman", "Noto Serif", serif;
  line-height: 1.2;
  color: var(--ink);
  margin: 0 0 0.5em;
}
h1 { font-size: 2rem; }
h2 { font-size: 1.5rem; margin-top: 1.6em; }
h3 { font-size: 1.2rem; margin-top: 1.4em; }

p, li { font-size: 1.05rem; }

ul, ol { padding-left: 1.25rem; }
li + li { margin-top: 0.25em; }

img, svg { max-width: 100%; height: auto; }

hr { border: 0; border-top: 1px solid var(--rule); margin: 2rem 0; }

code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  background: var(--bg-soft);
  padding: 1px 4px;
  border-radius: 3px;
  font-size: 0.95em;
}

/* Layout */
.container { width: 100%; max-width: var(--max); margin: 0 auto; padding: 0 1rem; }

/* Header */
.site-header {
  background: var(--bg-soft);
  border-bottom: 1px solid var(--rule);
}
.site-header .container {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 0.5rem 1.25rem;
  padding-top: 0.85rem;
  padding-bottom: 0.85rem;
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  text-decoration: none;
  color: var(--ink);
  font-weight: 700;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 1.25rem;
}
.brand-mark {
  width: 28px; height: 28px;
  display: inline-block;
}

.skip-link {
  position: absolute; left: -9999px; top: auto;
  background: var(--accent); color: #fff; padding: 0.5rem 0.75rem;
  border-radius: var(--radius);
}
.skip-link:focus { left: 1rem; top: 1rem; z-index: 1000; }

/* Nav */
.site-nav {
  margin-left: auto;
}
.site-nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 0.25rem 0.75rem;
}
.site-nav a {
  display: inline-block;
  padding: 0.4rem 0.6rem;
  text-decoration: none;
  color: var(--ink);
  border-radius: var(--radius);
  font-size: 0.98rem;
}
.site-nav a:hover, .site-nav a:focus { background: #e6e3d4; color: var(--ink); }
.site-nav a[aria-current="page"] {
  background: var(--accent);
  color: var(--accent-ink);
}

/* Sitewide safety strip */
.safety-strip {
  position: sticky;
  top: 0;
  z-index: 200;
  background: var(--danger-bg);
  color: var(--danger-ink);
  border-bottom: 2px solid var(--danger-rule);
  font-size: 0.98rem;
  font-weight: 600;
  text-align: center;
  padding: 0.6rem 1rem;
  box-shadow: 0 1px 0 rgba(0,0,0,0.04);
}
.safety-strip a {
  color: var(--danger-ink);
  text-decoration: underline;
}
.safety-strip a:hover, .safety-strip a:focus { color: #4a1308; }

/* Topic strip — the cross-site switcher.

   Lives between the sticky safety strip and the per-topic header. Each
   page on every subdomain renders the strip so visitors can hop to
   sibling topics or back to the apex without having to know the URLs.
   The current topic is identified by `aria-current="page"` and a
   stronger visual pip so assistive tech and visual readers both have
   a clear "you are here" anchor.

   Mobile: the topic list scrolls horizontally with momentum, the home
   anchor stays pinned at the left so people can always get back to
   actsmall.org. We deliberately keep the strip narrow (~36px tall on
   desktop) so it never competes with the actual site header below. */
.topic-strip {
  background: #f0ede1;
  border-bottom: 1px solid var(--rule);
  font-size: 0.88rem;
  color: var(--ink);
}
.topic-strip .container {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding-top: 0.35rem;
  padding-bottom: 0.35rem;
  min-height: 36px;
}
.topic-strip-home {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  text-decoration: none;
  color: var(--ink);
  font-weight: 700;
  padding: 0.25rem 0.5rem 0.25rem 0;
  flex: 0 0 auto;
  border-radius: 4px;
}
.topic-strip-home:hover,
.topic-strip-home:focus-visible {
  background: rgba(0, 0, 0, 0.06);
  outline: none;
}
.topic-strip-logo {
  display: inline-block;
  width: 22px; height: 22px;
  border-radius: 5px;
  background: #1f3b54;
  color: #fff;
  font-size: 0.66rem;
  font-weight: 800;
  text-align: center;
  line-height: 22px;
  letter-spacing: 0;
}
.topic-strip-label {
  font-weight: 700;
  letter-spacing: -0.005em;
}
.topic-strip-label::after {
  content: '/';
  margin: 0 0.1rem 0 0.45rem;
  color: var(--ink-soft);
  font-weight: 400;
}
.topic-strip-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  gap: 0.05rem;
  flex: 1 1 auto;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}
.topic-strip-list::-webkit-scrollbar { height: 0; }
.topic-strip-list li { flex: 0 0 auto; }
.topic-strip-list a {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  color: var(--ink-soft);
  padding: 0.3rem 0.55rem;
  border-radius: 999px;
  font-weight: 600;
  white-space: nowrap;
}
.topic-strip-list a:hover,
.topic-strip-list a:focus-visible {
  background: rgba(0, 0, 0, 0.06);
  color: var(--ink);
  outline: none;
}
.topic-strip-list a[aria-current="page"] {
  background: var(--accent);
  color: var(--accent-ink);
  cursor: default;
}
.topic-strip-list a[aria-current="page"]:hover,
.topic-strip-list a[aria-current="page"]:focus-visible {
  background: var(--accent);
}
@media (max-width: 480px) {
  .topic-strip .container { gap: 0.25rem; }
  .topic-strip-label { display: none; }
  .topic-strip-label::after { display: none; }
}

/* Hero */
.hero {
  padding: 2.25rem 0 1.25rem;
}
.hero h1 {
  font-size: clamp(1.85rem, 4.5vw, 2.6rem);
  margin-bottom: 0.4em;
}
.hero p.lede {
  font-size: 1.15rem;
  color: var(--ink-soft);
  max-width: 44rem;
}

/* Hero with an editorial photograph.
   - On wide screens, the photograph sits to the right of the lede in a
     two-column grid so a 1.5MB PNG never elbows out the text the user
     actually came to read.
   - On phones, the image stacks above the headline, full-bleed inside
     the container, capped to a reasonable height so it never dominates
     the fold. `aspect-ratio` + `object-fit: cover` keeps the composition
     stable across breakpoints. We always preload `decoding="async"`
     `loading="lazy"` on the <img> tag itself (set in markup, not here).
   - The image is *always* decorative — alt="" — because every page
     using it also carries a headline + lede that already convey the
     topic. Adding a non-empty alt would be redundant for screen reader
     users. */
.hero.has-figure .container {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1.4rem;
  align-items: center;
}
@media (min-width: 56rem) {
  .hero.has-figure .container {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    gap: 2rem;
  }
}
.hero-text { min-width: 0; }
.hero-figure {
  margin: 0;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg-soft);
  border: 1px solid var(--rule);
  box-shadow: var(--shadow);
  aspect-ratio: 3 / 2;
  max-height: min(46vh, 360px);
}
@media (min-width: 56rem) {
  .hero-figure {
    aspect-ratio: 3 / 2;
    max-height: 420px;
  }
}
.hero-figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Sections */
.section { padding: 1.25rem 0 2rem; }
.section + .section { border-top: 1px solid var(--rule); }

.grid {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr;
  align-items: stretch;
}
/* Auto-fit grid: cards expand to fill the row instead of staying narrow
   and wrapping titles/buttons. Browsers pick the largest count of columns
   where every card is at least the minmax floor wide. */
@media (min-width: 640px) {
  .grid.cols-2 { grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); }
  .grid.cols-3 { grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr)); }
}

/* Cards */
.card {
  background: #fff;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 1.1rem 1.2rem;
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  height: 100%;
}
.card h3 { margin-top: 0.2em; }
.card p { margin: 0 0 0.75em; }
/* Anchor the final paragraph (usually the action link/button) to the bottom
   so all cards in a row line up nicely regardless of body length. */
.card > p:last-child { margin-top: auto; margin-bottom: 0; }
.card .btn { align-self: flex-start; }

/* Steps */
.steps {
  counter-reset: step;
  list-style: none;
  padding: 0;
  display: grid;
  gap: 0.75rem;
}
.steps > li {
  counter-increment: step;
  position: relative;
  background: #fff;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 0.85rem 1rem 0.85rem 3.6rem;
}
.steps > li::before {
  content: counter(step);
  position: absolute;
  left: 0.75rem;
  top: 0.75rem;
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 700;
  border-radius: 999px;
  width: 2.2rem; height: 2.2rem;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: Georgia, serif;
  font-size: 1.05rem;
}
.steps > li > strong { font-weight: 700; }
.steps > li > p:first-child { margin-top: 0; }
.steps > li > p:last-child { margin-bottom: 0; }

/* Boxes */
.box {
  border: 1px solid var(--rule);
  border-left: 5px solid var(--accent);
  background: #fff;
  padding: 0.85rem 1rem;
  border-radius: var(--radius);
  margin: 1rem 0;
}
.box.warn {
  background: var(--warn-bg);
  color: var(--warn-ink);
  border-color: var(--warn-rule);
  border-left-color: #b88a1a;
}
.box.danger {
  background: var(--danger-bg);
  color: var(--danger-ink);
  border-color: var(--danger-rule);
  border-left-color: #a83d2c;
}
.box.safe {
  background: var(--safe-bg);
  color: var(--safe-ink);
  border-color: #b5c8ad;
  border-left-color: var(--accent);
}
.box h3 { margin-top: 0; }
.box p:last-child, .box ul:last-child, .box ol:last-child { margin-bottom: 0; }

/* Collapsible callout (used on /submit-action/ and /submit-peer/ for the
   "Read this first" warn boxes). On narrow viewports the body folds
   behind its title so it doesn't push the form off-screen on phones;
   from 640px up it renders as a static panel (no caret, no pointer)
   identical in appearance to a plain .box.warn.

   The HTML ships with the `open` attribute, so no-JS / no-CSS users
   always see the content. The desktop media query re-asserts that
   open state visually in case the visitor toggled the panel closed
   on a small viewport and then enlarged the window. */
details.box-collapsible {
  padding: 0;
}
details.box-collapsible > summary {
  cursor: pointer;
  list-style: none;
  font-size: 1.05rem;
  font-weight: 700;
  padding: 0.7rem 1rem;
  margin: 0;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  border-radius: var(--radius);
}
details.box-collapsible > summary::-webkit-details-marker,
details.box-collapsible > summary::marker {
  display: none;
}
details.box-collapsible > summary::after {
  content: "\25BE"; /* ▾ */
  margin-left: auto;
  font-size: 0.85em;
  opacity: 0.7;
  transition: transform 0.15s ease;
}
details.box-collapsible[open] > summary::after { transform: rotate(180deg); }
details.box-collapsible[open] > summary { padding-bottom: 0.4rem; }
details.box-collapsible > *:not(summary) {
  padding: 0 1rem 0.85rem;
  margin: 0;
}

@media (min-width: 640px) {
  details.box-collapsible > summary {
    cursor: default;
    pointer-events: none;
  }
  details.box-collapsible > summary::after { display: none; }
  /* If the visitor closed the panel on a narrow viewport and then
     resized larger, force-show the body anyway. The UA stylesheet
     hides it with display:none on non-summary children when [open]
     is absent — overriding that here is enough. */
  details.box-collapsible:not([open]) > *:not(summary) {
    display: block !important;
  }
}

/* Buttons */
.btn {
  display: inline-block;
  background: var(--accent);
  color: var(--accent-ink);
  padding: 0.6rem 1rem;
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  text-decoration: none;
  font-weight: 600;
  cursor: pointer;
  font-size: 1rem;
}
.btn:hover, .btn:focus { background: #284a2e; color: #fff; }
.btn.secondary {
  background: transparent; color: var(--accent);
}
.btn.secondary:hover { background: #e6efe2; }
.btn-row { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-top: 0.5rem; }

/* Tables */
table {
  width: 100%; border-collapse: collapse; margin: 1rem 0;
  background: #fff; border: 1px solid var(--rule);
}
th, td { padding: 0.55rem 0.7rem; border-bottom: 1px solid var(--rule); text-align: left; vertical-align: top; }
th { background: var(--bg-soft); font-weight: 600; }

/* Diagrams (CSS layered trench) */
.trench {
  display: grid;
  gap: 0;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
  margin: 1rem 0;
  background: #fff;
}
.trench .layer {
  padding: 0.8rem 1rem;
  font-weight: 600;
  border-bottom: 1px solid var(--rule);
  display: flex; justify-content: space-between; align-items: center;
}
.trench .layer:last-child { border-bottom: 0; }
.trench .layer .note { font-weight: 400; color: var(--ink-soft); font-size: 0.95rem; }
.layer-leaves { background: #f1ead2; color: #5b4a17; }
.layer-myco   { background: #d9c8a4; color: #4d3d18; }
.layer-sand   { background: #e9dfb6; color: #5b4d18; }
.layer-gravel { background: #c9c4b3; color: #3a3527; }

/* Flow diagram (horizontal arrows) */
.flow {
  display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: stretch;
  margin: 1rem 0;
}
.flow .node {
  background: #fff; border: 1px solid var(--rule); border-radius: var(--radius);
  padding: 0.6rem 0.85rem; flex: 1 1 8rem; min-width: 7rem;
  text-align: center; font-weight: 600; font-size: 0.95rem;
  box-shadow: var(--shadow);
}
.flow .arrow {
  align-self: center; color: var(--accent-soft); font-weight: 700;
  padding: 0 0.1rem;
}

/* Checklists */
.checklist { list-style: none; padding: 0; margin: 0.5rem 0 1.25rem; }
.checklist li {
  display: flex; align-items: flex-start; gap: 0.6rem;
  padding: 0.45rem 0;
  border-bottom: 1px dashed var(--rule);
}
.checklist li::before {
  content: "";
  display: inline-block;
  width: 1.1rem; height: 1.1rem;
  border: 2px solid var(--ink-soft);
  border-radius: 3px;
  margin-top: 0.2rem;
  flex-shrink: 0;
}

/* Footer */
.site-footer {
  background: var(--bg-soft);
  border-top: 1px solid var(--rule);
  margin-top: 3rem;
  padding: 1.5rem 0 2rem;
  font-size: 0.95rem;
  color: var(--ink-soft);
}
.site-footer .safety-line {
  background: var(--warn-bg);
  color: var(--warn-ink);
  border: 1px solid var(--warn-rule);
  padding: 0.65rem 0.85rem;
  border-radius: var(--radius);
  margin-bottom: 0.9rem;
}
.site-footer p { margin: 0.35rem 0; }

/* Cross-site policy nav in the footer. Same row of small chips on every
   topic page so a visitor on any subdomain is one click away from the
   single source of truth on contribute/methodology/privacy/terms — and
   the contribute link is the one we want visitors to take, because it
   converts attention to data. */
.site-footer .footer-policy {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.1rem;
  margin: 0.7rem 0 0.4rem;
  font-size: 0.92rem;
}
.site-footer .footer-policy a {
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  padding: 0.1rem 0;
}
.site-footer .footer-policy a:hover,
.site-footer .footer-policy a:focus-visible {
  border-bottom-color: var(--accent);
  outline: none;
}
.site-footer .footer-policy a strong {
  font-weight: 700;
}

/* Utility */
.muted { color: var(--ink-soft); }
.center { text-align: center; }
.no-print { /* default */ }

/* Print */
@media print {
  :root { --bg: #fff; --bg-soft: #fff; }
  body { font-size: 12pt; color: #000; background: #fff; }
  .site-header, .site-nav, .site-footer .nav-row, .no-print, .skip-link { display: none !important; }
  .safety-strip { border-bottom: 1px solid #000; background: #fff; color: #000; }
  .container { max-width: 100%; padding: 0; }
  a { color: #000; text-decoration: underline; }
  .card, .box, .steps > li, .flow .node {
    box-shadow: none;
    border: 1px solid #555;
    background: #fff !important;
    color: #000 !important;
    page-break-inside: avoid;
  }
  h1, h2, h3 { page-break-after: avoid; }
  .checklist li { page-break-inside: avoid; }
  .site-footer { background: #fff; border-top: 1px solid #000; }
  .site-footer .safety-line { border: 1px solid #000; background: #fff; color: #000; }
}

/* Reduced motion respect */
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* ===== Water Quality Portal (map page) ===== */
.hero.compact { padding: 1rem 0 0.5rem; }
.hero.compact h1 { margin: 0 0 .25rem; font-size: clamp(1.4rem, 1.1rem + 1.4vw, 2rem); }
.hero.compact .lede { font-size: 1.02rem; margin: 0; max-width: 56rem; }

/* The toolbar collapses by default — search is the only thing visible
   without a click. Indicator + layer fieldsets live behind the Options
   disclosure so the map is the focal element on first paint. */
.map-toolbar {
  display: grid;
  gap: 0.55rem 0.75rem;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  margin: 0 0 0.75rem;
  padding: 0.55rem 0.7rem;
  background: var(--bg-soft);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}
.map-toolbar .toolbar-toggle {
  white-space: nowrap;
}
.toolbar-options {
  grid-column: 1 / -1;
  display: grid;
  gap: 0.6rem 1rem;
  grid-template-columns: minmax(14rem, 1fr) minmax(14rem, 1fr);
  padding: 0.6rem 0;
  border-top: 1px dashed var(--rule);
  margin-top: 0.25rem;
}
.toolbar-options[hidden] { display: none; }
@media (max-width: 800px) {
  .toolbar-options { grid-template-columns: 1fr; }
}
.map-toolbar fieldset {
  border: 0;
  margin: 0;
  padding: 0;
}
.map-toolbar legend {
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
  margin: 0 0 0.25rem;
  padding: 0;
}
.map-search { display: flex; }
.map-search input {
  flex: 1;
  padding: 0.6rem 0.75rem;
  font: inherit;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: #fff;
  color: var(--ink);
}
.map-search input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.map-indicator > div, .map-layers {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
  font-size: 0.95rem;
  color: var(--ink);
}
.map-indicator label, .map-layers label {
  display: inline-flex;
  gap: 0.35rem;
  align-items: center;
  cursor: pointer;
}

/* ----- Map + overlays ----- */
.map-stage {
  display: grid;
  gap: 1rem;
  grid-template-columns: minmax(0, 1fr);
  margin: 0 0 1rem;
}
@media (min-width: 64rem) {
  .map-stage { grid-template-columns: minmax(0, 1.6fr) minmax(20rem, 1fr); }
}
.map-wrap {
  margin: 0;
  min-width: 0;
}
/* map-canvas wraps the map element + its absolutely-positioned overlays
   (time picker, legend, etc.). It is the positioning context, NOT
   .map-wrap, because .map-wrap also contains the button row and hint
   paragraph in flow — anchoring overlays to .map-wrap would let the
   legend land on top of those controls. */
.map-canvas {
  position: relative;
  min-width: 0;
}
.map {
  width: 100%;
  height: clamp(420px, 72vh, 780px);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}
body.add-mode .map .maplibregl-canvas { cursor: crosshair !important; }

/* Generic overlay container for things that float on top of the map. The
   map is the hero; everything else (legend, time/scenario chips) sits over
   it in semi-transparent panels with a hide affordance so the user can
   reclaim screen space when they want to. */
.map-overlay {
  position: absolute;
  z-index: 5;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  background: rgba(255, 255, 255, 0.95);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 0.55rem 0.7rem;
  box-shadow: var(--shadow);
  font-size: 0.85rem;
  max-width: min(20rem, calc(100% - 1.2rem));
}
.map-overlay--top-left    { top: 0.6rem; left: 0.6rem; }
.map-overlay--bottom-left { bottom: 0.6rem; left: 0.6rem; }
/* MapLibre's bottom-left attribution control (OpenStreetMap, WHO/UNICEF JMP,
   etc.) sits flush at the bottom edge of the map. Pin the legend overlay
   up by one attribution-row's worth so its toggle button never covers a
   source citation when expanded or collapsed. The data source line is
   the most important thing on the map — it has to stay readable. */
#legend-overlay.map-overlay--bottom-left { bottom: 2.1rem; }

/* Time/scenario chip group rendered over the map. Compact, tap-friendly. */
.time-row, .scenario-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.overlay-label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ink-soft);
}
.time-chips {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0.2rem;
  background: #fff;
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 0.15rem;
}
.time-chips button {
  appearance: none;
  background: transparent;
  border: 0;
  color: var(--ink);
  font-size: 0.82rem;
  font-weight: 600;
  padding: 0.25rem 0.7rem;
  border-radius: 999px;
  cursor: pointer;
  line-height: 1.1;
}
.time-chips button:hover { background: var(--bg-soft); }
.time-chips button[aria-pressed="true"] {
  background: var(--accent);
  color: #fff;
}
.time-chips button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.overlay-disclaimer {
  margin: 0;
  max-width: 22rem;
  line-height: 1.35;
}
.overlay-disclaimer a { color: var(--accent); text-decoration: underline; }

/* Legend overlay — shares the .map-overlay shell. Has its own toggle so it
   can be hidden on small screens where it competes with the map. */
.legend-toggle {
  align-self: flex-end;
  appearance: none;
  background: transparent;
  border: 0;
  color: var(--accent);
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  padding: 0.05rem 0.3rem;
  border-radius: 4px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.legend-toggle:hover { background: var(--bg-soft); }
.legend-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
#legend-overlay.is-collapsed { padding: 0.25rem 0.4rem; }
#legend-overlay.is-collapsed .map-legend { display: none; }
#legend-overlay.is-collapsed .legend-toggle { align-self: center; }

.map-legend {
  font-size: 0.85rem;
  max-width: 18rem;
}
.legend-title { font-weight: 600; margin: 0 0 0.3rem; }
.legend-bar {
  display: flex;
  height: 0.7rem;
  border-radius: 999px;
  overflow: hidden;
  border: 1px solid var(--rule);
}
.legend-bar .swatch { flex: 1; display: block; }
.legend-axis {
  display: flex;
  justify-content: space-between;
  font-size: 0.75rem;
  color: var(--ink-soft);
  margin-top: 0.2rem;
}
.legend-source { margin-top: 0.3rem; }

/* Buttons used to be position:absolute over the bottom-left of the map, but
   .map-wrap also contains the .map-hint paragraph in flow — so the wrap grew
   to include the hint and the absolute buttons ended up pinned on top of the
   hint text. Putting them in normal flow below the map fixes the overlap and
   gives a much larger tap target on phones. */
.map-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0.6rem 0 0;
}
.map-actions .btn { box-shadow: var(--shadow); }

.btn.small { padding: 0.35rem 0.7rem; font-size: 0.9rem; }
.btn.ghost {
  background: transparent;
  color: var(--danger-ink);
  border: 1px solid var(--danger-rule);
}
.btn.ghost:hover { background: var(--danger-bg); }
.btn[aria-pressed="true"] {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  background: var(--accent);
  color: var(--accent-ink);
}

.map-hint {
  margin: 0.55rem 0 0;
  font-size: 0.85rem;
  color: var(--ink-soft);
  line-height: 1.4;
}

/* ----- Side panels ----- */
.map-side {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
  margin: 0.5rem 0 0;
}
.map-card {
  background: var(--bg-soft);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 0.9rem 1rem;
  display: flex;
  flex-direction: column;
}
.map-card h2 {
  margin: 0 0 .25rem;
  font-size: 1.05rem;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.map-card .muted { font-size: 0.85rem; margin-top: 0; }
.map-card .badge { background: var(--rule); }

/* "Act now" sidebar — make it visually the front door of the side rail */
.map-card--act {
  background: linear-gradient(180deg, #f1f7e8 0%, #ffffff 60%);
  border-color: #cfe0a8;
}
.map-card--act > h2 {
  color: var(--ink);
}

.action-list {
  list-style: none;
  margin: 0.4rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}
.action-list.inline {
  margin-top: 0.4rem;
  padding: 0.6rem 0.8rem;
  background: #f5fbe9;
  border: 1px solid #cfe0a8;
  border-radius: var(--radius);
}
.action-item {
  padding: 0.55rem 0.7rem;
  background: #ffffff;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  font-size: 0.9rem;
}
.action-item p { margin: 0.25rem 0 0; }
.action-item .action-links {
  margin-top: 0.35rem;
  word-break: break-word;
}
.action-verb {
  display: inline-block;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 0.05rem 0.45rem;
  border-radius: 4px;
  margin-right: 0.4rem;
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 700;
  vertical-align: 1px;
}
.action-item.action-donate    .action-verb { background: #b14d4d; color: #fff; }
.action-item.action-volunteer .action-verb { background: #2f6f3a; color: #fff; }
.action-item.action-build     .action-verb { background: #3a5b8c; color: #fff; }
.action-item.action-conserve  .action-verb { background: #5c7a30; color: #fff; }
.action-item.action-report    .action-verb { background: #806015; color: #fff; }
.action-item.action-advocate  .action-verb { background: #6c3f8a; color: #fff; }
.action-item.action-learn     .action-verb { background: #6a6a6a; color: #fff; }

/* Small country/region chip beside a regional link, e.g. "[US]", "[EU]". The
   catalog orders global references first and then regional ones; the chip is
   what tells a non-US, non-EU visitor at a glance which links apply to them
   without forcing them to read every label. Global links are intentionally
   not chipped so they stay visually clean. */
.action-region {
  display: inline-block;
  margin-left: 0.3rem;
  padding: 0 0.35rem;
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  border-radius: 3px;
  background: rgba(0, 0, 0, 0.07);
  color: var(--muted);
  vertical-align: 1px;
}
@media (prefers-color-scheme: dark) {
  .action-region { background: rgba(255, 255, 255, 0.1); }
}

/* "unverified today" marker on action links. The curator probes every
   URL daily; if a probe gets a soft block (Cloudflare WAF, 403, network
   error) we still keep the link — the maintainer vetted it — but tell
   the visitor we couldn't independently re-confirm it today. The
   marker is deliberately quiet (warn-tinted, not red) because the
   most common failure mode is a working site behind aggressive bot
   protection, not a dead URL. */
/* Footnote under primary donate/advocate CTAs — signals, vetting, methodology. */
.primary-cta-trust {
  margin: 0.55rem 0 0;
  padding-top: 0.5rem;
  border-top: 1px dashed var(--rule);
  line-height: 1.45;
}
.primary-cta-trust a { color: var(--accent); }

.link-unverified {
  display: inline-block;
  margin-left: 0.25rem;
  padding: 0 0.4rem;
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border-radius: 3px;
  background: var(--warn-bg);
  color: var(--warn-ink);
  border: 1px solid var(--warn-rule);
  vertical-align: 1px;
  cursor: help;
}

/* ===== Primary call-to-action block =====
   Sits at the very top of the country card so the single highest-leverage
   thing a visitor can do is the first thing they see, ahead of statistics
   or technique recommendations. The colour band is verb-coloured so the
   eye picks up "this is a donation moment" / "this is a conserve moment"
   without parsing words. */
.primary-cta {
  margin: 0.5rem 0 0.9rem;
  padding: 0.75rem 0.95rem 0.85rem;
  border-radius: var(--radius);
  background: linear-gradient(180deg, #faf6e9 0%, #ffffff 70%);
  border: 1px solid #e0d9bd;
  box-shadow: var(--shadow);
}
.primary-cta-h {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
  flex-wrap: wrap;
  font-size: 1.02rem;
  margin-bottom: 0.2rem;
  line-height: 1.3;
}
.primary-cta-h strong {
  font-family: Georgia, "Times New Roman", "Noto Serif", serif;
  font-size: 1.05rem;
  font-weight: 700;
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
}
.primary-pip {
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  background: #1c2418;
  color: #fff;
  padding: 0.15rem 0.55rem;
  border-radius: 4px;
  white-space: nowrap;
}
.primary-cta-sub {
  margin: 0.35rem 0 0.5rem;
  font-size: 0.92rem;
  line-height: 1.45;
  color: var(--ink);
}
.primary-cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  align-items: stretch;
  margin-top: 0.5rem;
}
.primary-cta-btn {
  flex: 1 1 auto;
  min-width: 0;
  text-align: center;
  background: var(--accent);
  color: #fff;
  border: 1px solid var(--accent);
  padding: 0.55rem 0.9rem;
  border-radius: 5px;
  font-weight: 700;
  font-size: 0.95rem;
  text-decoration: none;
  line-height: 1.25;
  word-break: break-word;
}
.primary-cta-btn:hover, .primary-cta-btn:focus {
  background: #284a2e;
  color: #fff;
  outline: 2px solid #fff;
  outline-offset: 2px;
}
.primary-cta-secondary {
  flex: 0 1 auto;
  background: rgba(0, 0, 0, 0.04);
  color: var(--ink);
  border: 1px solid var(--rule);
  padding: 0.4rem 0.7rem;
  border-radius: 5px;
  font-size: 0.86rem;
  font-weight: 600;
  text-decoration: none;
  line-height: 1.25;
  word-break: break-word;
}
.primary-cta-secondary:hover, .primary-cta-secondary:focus {
  background: rgba(0, 0, 0, 0.08);
  color: var(--ink);
}
.primary-cta-tertiary {
  margin: 0.35rem 0 0;
  font-size: 0.82rem;
}
.primary-cta-followups {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin: 0.55rem 0 0;
  padding: 0.5rem 0 0;
  border-top: 1px dashed var(--rule);
  align-items: center;
}
.primary-cta-followup {
  appearance: none;
  background: transparent;
  border: 1px solid var(--rule);
  color: var(--ink);
  padding: 0.25rem 0.6rem;
  font-size: 0.78rem;
  font-weight: 600;
  border-radius: 999px;
  cursor: pointer;
  line-height: 1.2;
}
.primary-cta-followup:hover { background: var(--bg-soft); }
.primary-cta-followup:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.primary-cta-followup.is-on,
.primary-cta-followup[disabled] {
  background: var(--safe-bg);
  color: var(--safe-ink);
  border-color: #b5c8ad;
  cursor: default;
}
.primary-cta-confirm {
  flex: 1 1 100%;
  min-height: 1.1rem;
  font-size: 0.78rem;
  color: var(--ink-soft);
  opacity: 0;
  transition: opacity 0.2s ease;
}
.primary-cta-confirm.is-on { opacity: 1; }

/* Verb-coloured variants. The chrome stays the same; only the primary
   action button shifts colour so the user reads the verb at a glance. */
.primary-cta--donate { border-color: #e3b9a8; background: linear-gradient(180deg, #fff4f0 0%, #ffffff 70%); }
.primary-cta--donate .primary-pip { background: #b14d4d; }
.primary-cta--donate .primary-cta-btn { background: #b14d4d; border-color: #b14d4d; }
.primary-cta--donate .primary-cta-btn:hover, .primary-cta--donate .primary-cta-btn:focus { background: #913a3a; }

.primary-cta--volunteer { border-color: #b5c8ad; background: linear-gradient(180deg, #eff5ea 0%, #ffffff 70%); }
.primary-cta--volunteer .primary-pip { background: #2f6f3a; }
.primary-cta--volunteer .primary-cta-btn { background: #2f6f3a; border-color: #2f6f3a; }
.primary-cta--volunteer .primary-cta-btn:hover, .primary-cta--volunteer .primary-cta-btn:focus { background: #235228; }

.primary-cta--conserve { border-color: #c5d29a; background: linear-gradient(180deg, #f3f7e6 0%, #ffffff 70%); }
.primary-cta--conserve .primary-pip { background: #5c7a30; }
.primary-cta--conserve .primary-cta-btn { background: #5c7a30; border-color: #5c7a30; }
.primary-cta--conserve .primary-cta-btn:hover, .primary-cta--conserve .primary-cta-btn:focus { background: #475d24; }

.primary-cta--advocate { border-color: #cdb8d9; background: linear-gradient(180deg, #f5eef9 0%, #ffffff 70%); }
.primary-cta--advocate .primary-pip { background: #6c3f8a; }
.primary-cta--advocate .primary-cta-btn { background: #6c3f8a; border-color: #6c3f8a; }
.primary-cta--advocate .primary-cta-btn:hover, .primary-cta--advocate .primary-cta-btn:focus { background: #532f6b; }

.primary-cta--share { border-color: #b9c9d8; background: linear-gradient(180deg, #eef3f8 0%, #ffffff 70%); }
.primary-cta--share .primary-pip { background: #3a5b8c; }
.primary-cta--share .primary-cta-btn { background: #3a5b8c; border-color: #3a5b8c; }
.primary-cta--share .primary-cta-btn:hover, .primary-cta--share .primary-cta-btn:focus { background: #2c466d; }

/* "More techniques" disclosure under the top-3 ranked list. Calmer than the
   primary list so it doesn't compete for attention; clear summary gesture. */
.tech-rank-more { margin-top: 0.3rem; }
.tech-rank-more > summary {
  cursor: pointer;
  padding: 0.4rem 0;
  font-weight: 600;
  border-top: 1px dashed var(--rule);
}
.tech-rank-more[open] > summary { color: var(--accent); }

/* Personal action log sidebar — only renders when the user has logged at
   least one entry. Matches the soft sidebar palette so it doesn't shout. */
.map-card--log {
  background: linear-gradient(180deg, #f1ecf6 0%, #ffffff 60%);
  border-color: #cdb8d9;
}
.pledge-item {
  display: block;
}
.pledge-status {
  display: inline-block;
  width: 1.3rem;
  text-align: center;
  font-weight: 700;
  margin-right: 0.15rem;
}
.pledge-status--done    { color: #2f6f3a; }
.pledge-status--pending { color: #806015; }
.pledge-meta { margin-top: 0.15rem; }
.pledge-remove { color: var(--ink-soft); }
.pledge-remove:hover { color: var(--danger-ink); }

/* Top-of-card urgent appeals strip — the headline donate block. Heavier visual
   weight than the sidebar version because this is the *single* most-actionable
   thing on the page when a country has live operations. */
.urgent-appeals {
  margin: 0.5rem 0 0.9rem;
  padding: 0.7rem 0.9rem 0.85rem;
  background: linear-gradient(180deg, #b14d4d 0%, #ad4848 100%);
  border-radius: var(--radius);
  color: #fff;
}
.urgent-appeals .urgent-appeals-h {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  flex-wrap: wrap;
  font-size: 1rem;
  margin-bottom: 0.2rem;
}
.urgent-appeals .urgent-appeals-h strong { font-weight: 700; }
.urgent-pip {
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  background: #fff;
  color: #7a2f1a;
  padding: 0.1rem 0.5rem;
  border-radius: 4px;
}
.urgent-appeals .muted, .urgent-appeals .muted.small { color: #fbe4dc; }
.urgent-appeals a { color: #fff; text-decoration: underline; }
.urgent-appeals .appeal-list { margin-top: 0.35rem; }
.urgent-appeals .appeal-item {
  background: #fff;
  border-color: #c9b3aa;
  color: var(--ink);
}
.urgent-appeals .appeal-item .muted, .urgent-appeals .appeal-item .muted.small { color: #6a6a6a; }

/* Soft variant — shown when a country has no live IFRC operation. We still
   surface a donate path (chronic-need WASH operators) so the user's "I want
   to help here" intent never hits a blank wall. The colour is calmer than the
   emergency red so the visual hierarchy reads "important, but not urgent". */
.urgent-appeals.urgent-appeals--soft {
  background: linear-gradient(180deg, #3b6c5e 0%, #345f54 100%);
}
.urgent-appeals.urgent-appeals--soft .urgent-pip.soft {
  background: #fff;
  color: #234c41;
}
.urgent-appeals.urgent-appeals--soft .muted,
.urgent-appeals.urgent-appeals--soft .muted.small { color: #d6ebe3; }
.urgent-appeals .btn.donate.secondary {
  background: rgba(255,255,255,0.12);
  color: #fff;
  border-color: rgba(255,255,255,0.4);
}

/* Recommendation card heading — keeps the title and the share button on the
   same row at desktop widths, then stacks gracefully on narrow panels. */
.recommend-h {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
  flex-wrap: wrap;
  margin-bottom: 0.1rem;
}
.recommend-h h2 { margin: 0; flex: 1 1 auto; }
.share-link {
  font-size: 0.85rem;
  color: var(--accent);
  white-space: nowrap;
}
.share-link[disabled] { color: var(--ink-soft); cursor: default; }

/* Live IFRC emergency appeals — surfaced when there's a real, named, currently
   running operation a donor's money would actually go to. The red ribbon is
   intentional: it's the universal "donate to disaster relief" colour. */
.action-appeals {
  margin: 0.4rem 0 0.8rem;
  padding: 0.65rem 0.8rem;
  background: linear-gradient(180deg, #fff4f0 0%, #ffffff 70%);
  border: 1px solid #e3b9a8;
  border-radius: var(--radius);
}
.action-appeals .appeals-h {
  margin: 0 0 0.3rem;
  font-size: 1rem;
  color: #7a2f1a;
}
.appeal-list {
  list-style: none;
  margin: 0.3rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.appeal-item {
  padding: 0.55rem 0.7rem;
  background: #ffffff;
  border: 1px solid #e6c6b4;
  border-radius: var(--radius);
  font-size: 0.9rem;
}
.appeal-item strong { display: block; margin-top: 0.05rem; }
.appeal-dtype {
  display: inline-block;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 0.05rem 0.45rem;
  border-radius: 4px;
  background: #b14d4d;
  color: #fff;
  font-weight: 700;
  vertical-align: 1px;
}
.appeal-links { margin: 0.45rem 0 0; overflow-wrap: anywhere; }
/* Block-level button that fills the card width on narrow side panels — donor
   intent is the single most-actionable thing on the country card so the CTA
   gets full prominence. Bigger tap target on phones too. */
.btn.donate {
  display: inline-block;
  background: #b14d4d;
  color: #fff;
  padding: 0.45rem 0.85rem;
  border-radius: 5px;
  font-weight: 700;
  text-decoration: none;
  font-size: 0.9rem;
  line-height: 1.2;
}
.btn.donate:hover, .btn.donate:focus {
  background: #913a3a;
  color: #fff;
  text-decoration: none;
  outline: 2px solid #fff;
  outline-offset: 2px;
}
.appeals-footer-link { margin-top: 0.5rem !important; }
.appeals-footer-link a { color: #fff; text-decoration: underline; font-weight: 600; }
.action-appeals .appeals-footer-link a { color: #7a2f1a; }
.appeal-item strong {
  display: block;
  margin: 0.1rem 0 0.05rem;
  line-height: 1.3;
  overflow-wrap: anywhere;
}
.appeal-item .muted, .appeal-item .muted.small { line-height: 1.35; }

.recommend-action-h { margin-top: 0.8rem; }

ol.ranked, ul.ranked {
  list-style: none;
  margin: 0.6rem 0 0;
  padding: 0;
  max-height: 22rem;
  overflow-y: auto;
}
ol.ranked li, ul.ranked li {
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--rule);
  display: block;
}
ol.ranked li:last-child, ul.ranked li:last-child { border-bottom: 0; }

.link-button {
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: var(--accent);
  text-align: left;
  cursor: pointer;
  text-decoration: underline;
}
.link-button:hover { color: var(--ink); }

.badge {
  display: inline-block;
  margin-left: 0.35rem;
  padding: 0.05rem 0.5rem;
  border-radius: 999px;
  background: var(--rule);
  color: var(--ink);
  font-size: 0.78rem;
  font-weight: 600;
  vertical-align: 0.05em;
}
.small { font-size: 0.85rem; }

.poi-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 0.7rem;
  padding-top: 0.7rem;
  border-top: 1px solid var(--rule);
}

/* ----- Map popup styling ----- */
.maplibregl-popup-content {
  padding: 0.7rem 0.85rem;
  border-radius: var(--radius);
  font-family: inherit;
}
.maplibregl-ctrl button { background-color: #ffffff; }
.map-popup { font-size: 0.93rem; }
.map-popup p { margin: 0.4rem 0; }
.map-popup .popup-actions { margin-top: 0.4rem; }
.map-popup .popup-data {
  margin: 0.45rem 0;
  border-collapse: collapse;
  width: 100%;
  font-size: 0.88rem;
}
.map-popup .popup-data th {
  text-align: left;
  font-weight: 500;
  color: var(--ink-soft);
  padding: 0.15rem 0.4rem 0.15rem 0;
  vertical-align: top;
}
.map-popup .popup-data td {
  padding: 0.15rem 0;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.map-popup .popup-data tr.row-active th,
.map-popup .popup-data tr.row-active td {
  font-weight: 600;
  color: var(--ink);
}

/* GDACS / disaster map popup — suggested techniques (visible wrapped copy; no browser title tooltip) */
.maplibregl-popup.actsmall-popup-disaster .maplibregl-popup-content {
  padding: 0.65rem 0.75rem;
}
.map-popup.map-popup--disaster .popup-tech-heading {
  margin: 0.55rem 0 0.35rem;
  font-size: 0.88rem;
  line-height: 1.35;
}
.map-popup.map-popup--disaster .popup-actions--footer {
  margin-top: 0.65rem;
  margin-bottom: 0;
}
.map-popup.map-popup--disaster ul.popup-tech-cards {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}
.map-popup.map-popup--disaster .popup-tech-card {
  margin: 0;
  padding: 0.45rem 0.5rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--bg-soft);
}
.map-popup.map-popup--disaster .popup-tech-card-btn {
  display: block;
  width: 100%;
  box-sizing: border-box;
  margin: 0;
  padding: 0.4rem 0.55rem;
  border: none;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-ink);
  font: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  text-align: left;
  line-height: 1.3;
  cursor: pointer;
  overflow-wrap: anywhere;
  word-wrap: break-word;
}
.map-popup.map-popup--disaster .popup-tech-card-btn:hover,
.map-popup.map-popup--disaster .popup-tech-card-btn:focus-visible {
  filter: brightness(0.97);
  outline: 2px solid var(--rule);
  outline-offset: 2px;
}
.map-popup.map-popup--disaster .popup-tech-card-desc {
  margin: 0.4rem 0 0;
  padding: 0;
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--ink-soft);
  overflow-wrap: anywhere;
  word-wrap: break-word;
}

/* ----- POI form inside popup ----- */
.poi-form { display: flex; flex-direction: column; gap: 0.45rem; min-width: 16rem; }
.poi-form label { display: flex; flex-direction: column; font-size: 0.85rem; gap: 0.2rem; }
.poi-form label span { font-weight: 600; color: var(--ink-soft); }
.poi-form input, .poi-form select, .poi-form textarea {
  font: inherit;
  padding: 0.4rem 0.5rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: #fff;
  color: var(--ink);
  width: 100%;
  box-sizing: border-box;
}
.poi-form textarea { resize: vertical; min-height: 3.5rem; }
.poi-form-row { display: flex; gap: 0.4rem; }

/* ----- Help disclosure ----- */
.map-help {
  margin: 1rem 0 0;
  background: var(--bg-soft);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 0.5rem 0.9rem;
}
.map-help summary {
  cursor: pointer;
  font-weight: 600;
  padding: 0.4rem 0;
}
.map-help ul { margin: 0.3rem 0 0.6rem 1rem; }

.map-attribution { margin: 0.75rem 0 0; }
.map-attribution p { margin: 0.25rem 0; }

/* ----- Data status line ----- */
.data-status {
  margin: 0.4rem 0 0.7rem;
  padding: 0.35rem 0.6rem;
  background: var(--bg-soft);
  border: 1px dashed var(--rule);
  border-radius: var(--radius);
  display: inline-block;
}

/* ----- Recommendation card (right side of map) ----- */
.recommend-card {
  background: var(--bg-soft);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 1rem 1.15rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  min-width: 0;
  max-height: clamp(420px, 72vh, 780px);
  overflow-y: auto;
}
.recommend-card h2 {
  margin: 0 0 .25rem;
  font-size: 1.1rem;
}
.recommend-card h3 {
  margin: 0.6rem 0 0.3rem;
  font-size: 0.98rem;
}
/* Trust-line disclosure for multi-polygon countries (USA's Hawaii / Alaska,
   France's Corsica, Indonesia's 13 island groups, etc.). Surfaced by
   site-shared/js/map-click.js whenever the visitor clicked a country whose
   boundary geometry has more than one disjoint polygon. The point is to
   tell the visitor — out loud, in the same panel as the figures — that
   the data is country-level and may not describe the specific island or
   territory they clicked. We style it as a soft, indented note (not a
   warning, not a hero) so it sits beside the data without screaming. */
.region-disclosure {
  margin: 0.05rem 0 0.55rem;
  padding: 0.45rem 0.7rem;
  background: #fff;
  border: 1px dashed var(--rule);
  border-left: 3px solid var(--accent-soft, var(--accent));
  border-radius: var(--radius);
  line-height: 1.45;
}
/* Stacked label-over-value rows. The previous grid layout (max-content 1fr)
   pinned the dt to its own widest text ("Water-withdrawal stress (SDG 6.4.2)")
   which left almost no room for values like "Democratic Republic of the Congo"
   on a 320px-wide side panel — they wrapped mid-word into "Democrati c". A
   stacked layout lets each value flow across the full card width. The dt is
   visually demoted to a small uppercase tag, which also reads better as the
   eye scans down a long stat list. */
.recommend-stats {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  margin: 0.3rem 0;
  padding: 0.55rem 0.75rem;
  background: #ffffff;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  font-size: 0.88rem;
}
.recommend-stats > div { display: block; }
.recommend-stats dt {
  color: var(--ink-soft);
  font-weight: 600;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin: 0 0 0.05rem;
}
.recommend-stats dd {
  margin: 0;
  font-weight: 600;
  overflow-wrap: anywhere; /* break only when truly necessary, not mid-word */
  hyphens: auto;
  line-height: 1.35;
}

/* National-context citation — surfaces what the country-mean indicator
   colouring can't show: latest annual food-insecurity figure (food),
   sub-national plumbing / Indigenous water-access gaps (water), or
   wildfire-smoke / failing-grade county counts (air). Visually set apart
   from the live-data stat block to make the cadence difference (annual
   survey vs. live monitoring) self-evident. Render is symmetric across
   topics — schemas differ but the visual shape is the same. */
.domestic-stat {
  margin: 0.6rem 0 0.3rem;
  padding: 0.65rem 0.85rem 0.7rem;
  background: var(--bg-soft);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
}
.domestic-stat h3 {
  margin: 0 0 0.25rem;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
  font-weight: 700;
}
.domestic-stat .domestic-headline {
  margin: 0.15rem 0 0.3rem;
  font-size: 1.02rem;
  line-height: 1.35;
}
.domestic-stat .domestic-headline strong {
  font-size: 1.25rem;
  font-family: Georgia, "Times New Roman", "Noto Serif", serif;
}
.domestic-stat p { margin: 0.15rem 0; }
.domestic-stat .small { font-size: 0.78rem; }
.domestic-stat a { word-break: break-word; }
/* Compact facts list inside the National-context block (water/air).
   Tighter than the food schema's domestic-headline because these are
   often two short rows like "131M Americans — counties with failing
   AQ grade (ALA)" rather than a single big number. */
.domestic-stat .domestic-facts {
  list-style: none;
  margin: 0.25rem 0 0.4rem;
  padding: 0;
}
.domestic-stat .domestic-facts li {
  margin: 0.15rem 0;
  font-size: 0.92rem;
  line-height: 1.35;
}
.domestic-stat .domestic-facts strong {
  font-family: Georgia, "Times New Roman", "Noto Serif", serif;
  font-size: 1.05rem;
}
/* Data-gap variant of the National-context block: rendered when the
   selected country has no live indicator value AND no editor-vetted
   national-context entry. The visitor still gets a one-click action,
   pointed at the open-data effort for whichever topic they're on, and
   the colour difference signals "this is a gap, not a verdict on the
   country" (the country isn't being painted as worse than its
   neighbours; the data simply isn't there yet). Same layout as the
   default block so the two never visually compete. */
.domestic-stat.data-gap {
  border-left-color: var(--ink-soft);
  background: var(--bg);
}
.domestic-stat.data-gap h3 { color: var(--ink); }

/* Trajectory pill — shows the now → future delta for the active indicator on
   the country card. Uses warm/cool/calm colours mapped to the direction so
   the eye picks up "getting worse" without parsing the number. */
.trajectory {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  margin: 0.25rem 0 0.5rem;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 700;
  background: #f4ede0;
  color: #6c4a1f;
  border: 1px solid #e2cfa6;
}
.trajectory.is-worse  { background: #f8e0db; color: #7a2c1d; border-color: #e8b9af; }
.trajectory.is-stable { background: #eef2ec; color: #4a5b48; border-color: #c8d2c5; }
.trajectory.is-better { background: #e2efe5; color: #2c5a39; border-color: #b6d2bd; }
.trajectory .trajectory-arrow { font-size: 0.95em; }

/* Future-mode chip on the recommend card — companion to the trajectory pill,
   makes it obvious you're not looking at "today" any more. */
.future-mode-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.18rem 0.55rem;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background: #2d4a8a;
  color: #fff;
  margin-left: 0.4rem;
}
.usecase-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin: 0.2rem 0 0.4rem;
}
.chip {
  display: inline-block;
  padding: 0.1rem 0.55rem;
  background: var(--accent);
  color: var(--accent-ink);
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}

ol.tech-rank {
  list-style: none;
  margin: 0.3rem 0 0;
  padding: 0;
  counter-reset: tech;
}
ol.tech-rank li {
  position: relative;
  padding: 0.55rem 0 0.55rem 2rem;
  border-bottom: 1px solid var(--rule);
  counter-increment: tech;
}
ol.tech-rank li:last-child { border-bottom: 0; }
ol.tech-rank li::before {
  content: counter(tech);
  position: absolute;
  left: 0;
  top: 0.55rem;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-ink);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.8rem;
  font-weight: 700;
}
.match-tags {
  margin-top: 0.2rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}
.tag {
  display: inline-block;
  padding: 0.05rem 0.4rem;
  background: var(--safe-bg);
  color: var(--safe-ink);
  border-radius: 4px;
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.badge.ghost {
  background: transparent;
  border: 1px solid var(--rule);
}

/* ----- Alert chips (live conditions for the clicked country) ----- */
.alert-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin: 0.4rem 0 0.6rem;
}
.alert-chip {
  display: inline-block;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  background: var(--warn-bg);
  color: var(--warn-ink);
  border: 1px solid rgba(0, 0, 0, 0.06);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

/* ----- Technique catalog grid ----- */
.tech-grid {
  display: grid;
  gap: 0.6rem;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  margin: 0.6rem 0;
}
.tech-card {
  text-align: left;
  background: #ffffff;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 0.7rem 0.8rem;
  font: inherit;
  color: inherit;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.tech-card:hover, .tech-card:focus {
  border-color: var(--accent);
  box-shadow: var(--shadow);
  outline: none;
}
.tech-card-name {
  font-weight: 700;
  font-size: 1rem;
  font-family: Georgia, "Times New Roman", "Noto Serif", serif;
}
.tech-card-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}
.tech-card .badge {
  margin-left: 0;
}

/* ----- Technique detail sheet (overlay) ----- */
.tech-sheet-overlay {
  position: fixed;
  inset: 0;
  background: rgba(28, 36, 24, 0.55);
  display: none;
  align-items: flex-start;
  justify-content: center;
  padding: 2rem 1rem;
  z-index: 50;
  overflow-y: auto;
}
.tech-sheet-overlay.open { display: flex; }
.tech-sheet {
  background: #ffffff;
  border-radius: var(--radius);
  max-width: 36rem;
  width: 100%;
  padding: 1.2rem 1.4rem 1.4rem;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
}
.tech-sheet h3 {
  margin: 0 0 .25rem;
  font-size: 1.4rem;
}
.tech-sheet h4 {
  margin: 1rem 0 .35rem;
  font-size: 1.05rem;
}
.tech-meta {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.25rem 0.7rem;
  margin: 0.7rem 0;
  font-size: 0.92rem;
}
.tech-meta > div { display: contents; }
.tech-meta dt {
  color: var(--ink-soft);
  font-weight: 500;
}
.tech-meta dd { margin: 0; font-weight: 600; }
.tech-sources { padding-left: 1.1rem; margin: 0.3rem 0 0.6rem; }
.tech-sources li { margin: 0.15rem 0; }

/* ----- Freshness bar ----- */
.freshness-bar {
  margin: 0.4rem 0 0.7rem;
  padding: 0.5rem 0.7rem;
  background: var(--bg-soft);
  border: 1px dashed var(--rule);
  border-radius: var(--radius);
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}
.freshness-bar p { margin: 0; }
.freshness-bar .trust-line {
  margin-top: 0.2rem;
  padding-top: 0.3rem;
  border-top: 1px dotted var(--rule);
  font-style: italic;
}
.freshness-bar .trust-line:empty {
  display: none;
}
.freshness-bar .trust-line a { color: var(--accent); }

/* ----- Time-window chips on disaster card ----- */
.time-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  margin: 0.4rem 0;
}
.time-chips button {
  appearance: none;
  background: #ffffff;
  border: 1px solid var(--rule);
  color: var(--ink);
  font: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  padding: 0.18rem 0.55rem;
  border-radius: 999px;
  cursor: pointer;
}
.time-chips button:hover { border-color: var(--accent); }
.time-chips button[aria-pressed="true"] {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: var(--accent);
}

/* ----- Recency badge (used inline next to event names) ----- */
.recency {
  display: inline-block;
  padding: 0.05rem 0.45rem;
  border-radius: 4px;
  background: var(--bg-soft);
  color: var(--ink-soft);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  vertical-align: 0.05em;
  margin-left: 0.3rem;
}
.recency.recent {
  background: #fde4e0;
  color: #7a1f12;
  animation: recent-pulse 1.6s ease-in-out infinite;
}
@keyframes recent-pulse {
  0%,100% { box-shadow: 0 0 0 0 rgba(122,31,18,0.0); }
  50%     { box-shadow: 0 0 0 4px rgba(122,31,18,0.18); }
}

/* Make the action chips inside disaster popups feel clickable */
.map-popup .usecase-chips .chip { cursor: pointer; border: 0; text-decoration: none; }
.map-popup .usecase-chips .chip:hover { filter: brightness(0.92); }

/* ----- USGS gauge popup ----- */
.usgs-readings {
  width: 100%;
  border-collapse: collapse;
  margin: 0.4rem 0 0.2rem;
  font-size: 0.85rem;
}
.usgs-readings th,
.usgs-readings td {
  text-align: left;
  padding: 0.18rem 0.45rem 0.18rem 0;
  border-bottom: 1px solid var(--border-soft, #eee);
  vertical-align: top;
}
.usgs-readings th { font-weight: 600; color: var(--ink-soft); width: 38%; }
.badge.usgs-ok      { background: #e3f1e6; color: #1f5b32; }
.badge.usgs-watch   { background: #fbf2d3; color: #806208; }
.badge.usgs-concern { background: #fde4e0; color: #7a1f12; }
.badge.alert-red    { background: #fde4e0; color: #7a1f12; }
.badge.alert-orange { background: #fbf2d3; color: #806208; }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0);
  white-space: nowrap; border: 0;
}

@media print {
  .map-wrap, .map-toolbar, .map-side, .map-attribution, .map-help { display: none; }
}

/* ========================================================================
   Primer / library pages (the "teaching wing", currently used by site-forest).
   These styles intentionally sit on top of the existing shared vocabulary
   (.section, .container, .lede, .muted, .tag) so any topic that wants a
   library namespace can opt in just by mirroring the markup.
   ======================================================================== */

.primer { display: block; }

.primer-head {
  background: var(--bg-soft);
  border-bottom: 1px solid var(--rule);
  padding: 1.5rem 0 1.25rem;
}
.primer-kicker {
  font-size: 0.85rem;
  color: var(--ink-soft);
  margin: 0 0 0.4rem;
  letter-spacing: 0.02em;
}
.primer-kicker a { text-decoration: none; }
.primer-kicker a:hover, .primer-kicker a:focus { text-decoration: underline; }
.primer-head h1 {
  margin: 0 0 0.5rem;
  font-size: 2.1rem;
  line-height: 1.15;
}
.primer-head .lede {
  font-size: 1.15rem;
  line-height: 1.45;
  font-style: italic;
  color: var(--ink);
  max-width: 44rem;
  margin: 0 0 1.1rem;
}
.primer-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.4rem;
  margin: 0;
  font-size: 0.85rem;
  color: var(--ink-soft);
}
.primer-meta > div { margin: 0; }
.primer-meta dt {
  display: inline;
  font-weight: 600;
  color: var(--ink-soft);
}
.primer-meta dt::after { content: ":\00a0"; }
.primer-meta dd {
  display: inline;
  margin: 0;
}

.container.narrow { max-width: 44rem; }
.container.narrow > p { margin: 0 0 1.05em; line-height: 1.6; }
.container.narrow > h2 {
  margin-top: 2.2rem;
  font-size: 1.45rem;
}
.container.narrow > h3 {
  margin-top: 1.6rem;
  margin-bottom: 0.4rem;
  font-size: 1.1rem;
  color: var(--accent);
}
.container.narrow sup a {
  text-decoration: none;
  font-size: 0.78em;
  padding: 0 1px;
}
.container.narrow sup a:hover,
.container.narrow sup a:focus { text-decoration: underline; }

.primer-figure {
  margin: 1.6rem 0 2rem;
  background: var(--bg-soft);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 0.75rem;
}
.primer-figure svg {
  display: block;
  width: 100%;
  height: auto;
  background: #f7f5ef;
  border-radius: 3px;
}
.primer-figure figcaption {
  font-size: 0.92rem;
  color: var(--ink-soft);
  line-height: 1.45;
  margin-top: 0.6rem;
  padding: 0 0.4rem;
}
.primer-figure figcaption strong { color: var(--ink); }
.figure-disclosure {
  display: block;
  margin-top: 0.4rem;
  font-size: 0.78rem;
  font-style: italic;
  color: var(--ink-soft);
  letter-spacing: 0.02em;
}

.primer-sources {
  background: var(--bg-soft);
  border-top: 1px solid var(--rule);
}
.primer-sources h2 { margin-top: 0.4rem; font-size: 1.25rem; }
.sources {
  padding-left: 1.4rem;
  margin: 0.6rem 0 0.4rem;
}
.sources li {
  margin: 0.45rem 0;
  font-size: 0.95rem;
  line-height: 1.5;
}
.sources li em { font-style: italic; }

.primer-disclosure { font-size: 0.93rem; }
.primer-disclosure h2 { font-size: 1.1rem; margin-top: 0.4rem; }
.primer-disclosure p { margin: 0.3rem 0; line-height: 1.5; }
.primer-disclosure strong { color: var(--ink); }

.primer-nav {
  padding: 1rem 0 2rem;
  border-top: 1px solid var(--rule);
}
.primer-nav p { margin: 0; }

.primer-list {
  list-style: none;
  padding: 0;
  margin: 0;
}
.primer-list > li {
  border-top: 1px solid var(--rule);
  padding: 0.4rem 0 0.6rem;
}
.primer-list > li:first-child { border-top: 0; }
.primer-list h3 {
  font-family: Georgia, "Times New Roman", serif;
  font-size: 1.15rem;
  margin: 0 0 0.25rem;
}
.primer-list h3 a { text-decoration: none; }
.primer-list h3 a:hover, .primer-list h3 a:focus { text-decoration: underline; }
.primer-list p { margin: 0; }

.tag-pending {
  background: var(--warn-bg);
  color: var(--warn-ink);
}
.tag-library {
  background: #e2e6d6;
  color: #3a4a26;
}

@media (min-width: 40em) {
  .primer-head h1 { font-size: 2.4rem; }
}

/* ===== Mobile / notch / tap targets (topic sites + maps) ===== */
.container {
  padding-left: max(1rem, env(safe-area-inset-left));
  padding-right: max(1rem, env(safe-area-inset-right));
}
@media (max-width: 640px) {
  .site-nav ul {
    gap: 0.35rem 0.75rem;
    justify-content: flex-end;
  }
  .site-nav a {
    padding: 0.62rem 0.72rem;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    box-sizing: border-box;
  }
  .map-toolbar {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.45rem;
  }
  .map-toolbar .toolbar-toggle {
    justify-self: start;
  }
}
@media (max-width: 520px) {
  .map {
    height: clamp(280px, min(58vh, 520px), 85vh);
  }
  .map-actions .btn {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding-left: 1rem;
    padding-right: 1rem;
  }
  .time-chips button {
    min-height: 36px;
    padding: 0.35rem 0.75rem;
  }
}

/* ----------------------------------------------------------------
   Mobile map-click coachmark + recommend-card peek

   The single biggest mobile UX gap on every topic was that visitors
   tap the map, the recommender card updates *below* the map, and
   nothing in the viewport changes — so they think the tap did
   nothing. Two fixes:

   1. A pulsing "Tap any country" coachmark overlay that sits at the
      bottom-center of the map until the first selection happens
      (or for 8 seconds, whichever is sooner). Pointer-events: none
      so it never blocks a real tap. Markup is injected by
      map-coachmark.js (shared across topics) so individual map.js
      files don't need to grow.

   2. A bottom-sheet "peek" behaviour: when the visitor taps a
      country on a small viewport, the page smooth-scrolls the
      recommender card into view. JS-side; this is the matching
      CSS hooks. The recommender card carries a tag-style "Live"
      pip on mobile so it reads as "here's the action that just
      arrived" rather than as a continuation of the page.

   Reduced-motion users get the coachmark in static (non-pulsing)
   form via `prefers-reduced-motion`.
   ---------------------------------------------------------------- */

.map-coachmark {
  position: absolute;
  z-index: 10;
  left: 50%;
  bottom: 1rem;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  background: rgba(20, 20, 20, 0.86);
  color: #fff;
  font-size: 0.92rem;
  font-weight: 600;
  letter-spacing: 0.005em;
  padding: 0.55rem 0.95rem;
  border-radius: 999px;
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.18),
    0 8px 24px rgba(0, 0, 0, 0.22);
  pointer-events: none;
  white-space: nowrap;
  animation: actsmall-coachmark-pulse 1.8s ease-in-out 0.4s 4 both;
}
.map-coachmark::before {
  content: '👆';
  font-size: 1.05rem;
  line-height: 1;
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.4));
}
.map-coachmark.is-dismissed {
  animation: actsmall-coachmark-fade 0.45s ease-out forwards;
}
@keyframes actsmall-coachmark-pulse {
  0%   { transform: translateX(-50%) translateY(0); opacity: 0.92; }
  50%  { transform: translateX(-50%) translateY(-6px); opacity: 1; }
  100% { transform: translateX(-50%) translateY(0); opacity: 0.92; }
}
@keyframes actsmall-coachmark-fade {
  to { opacity: 0; transform: translateX(-50%) translateY(8px); }
}
@media (prefers-reduced-motion: reduce) {
  .map-coachmark {
    animation: none;
  }
}
/* On larger screens the recommender card is already visible next to
   the map, so the coachmark would be noise. Hide it on desktop. */
@media (min-width: 64rem) {
  .map-coachmark { display: none; }
}

/* Sticky "peek" on the recommender card after a country is picked on
   mobile. JS adds the `.is-active` class once a country has been
   selected; CSS gives it a thin accent border + a small visible badge
   so the user can tell the card just got new content. The active
   border softly fades after a few seconds via the `is-fresh` class. */
@media (max-width: 63.99rem) {
  .recommend-card {
    scroll-margin-top: 5rem;
  }
  .recommend-card.is-active {
    border-color: var(--accent);
    border-width: 1px;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent),
                var(--shadow);
    transition: border-color 0.3s ease, box-shadow 0.3s ease;
  }
  .recommend-card.is-active.is-fresh::after {
    content: 'Just picked';
    position: absolute;
    top: -0.7rem;
    right: 0.9rem;
    background: var(--accent);
    color: var(--accent-ink, #fff);
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    padding: 0.18rem 0.55rem;
    border-radius: 999px;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18);
    animation: actsmall-fresh-fade 4.5s ease 0s 1 forwards;
  }
  .recommend-card { position: relative; }
}
@keyframes actsmall-fresh-fade {
  0%   { opacity: 1; }
  70%  { opacity: 1; }
  100% { opacity: 0; }
}

/* ----------------------------------------------------------------
   Mobile bottom sheet — tap country → primary CTA in view

   On viewports under 64rem the recommender becomes a fixed bottom
   sheet once a country is picked. The primary-cta block is rendered
   first by every topic's map.js, so the peek height (~38vh) lands
   the main action button within one thumb-reach. Expand for stats,
   technique lists, and follow-ups. Idle placeholder copy is hidden
   so the map keeps maximum height before the first tap.
   ---------------------------------------------------------------- */
@media (max-width: 63.99rem) {
  .map-stage {
    position: relative;
  }
  .map-page .hero.compact {
    padding: 0.65rem 0 0.35rem;
  }
  .map-page .hero.compact .lede {
    font-size: 0.95rem;
    line-height: 1.4;
  }
  .map-page .section[style*="padding-top:0"],
  .map-page .section:first-of-type {
    padding-top: 0;
  }

  /* Reserve space so the fixed sheet does not cover map controls */
  .map-stage.has-sheet .map-wrap {
    margin-bottom: 0.25rem;
  }
  .recommend-card-spacer {
    display: block;
    height: 0;
    transition: height 0.25s ease;
    pointer-events: none;
  }
  .map-stage.has-sheet .recommend-card-spacer {
    height: min(38vh, 300px);
  }
  .map-stage.has-sheet.is-sheet-expanded .recommend-card-spacer {
    height: min(72vh, 560px);
  }

  .recommend-card:not(.is-active) {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }

  .recommend-card.is-active.is-sheet .sheet-handle {
    display: flex;
  }

  .recommend-card.is-active.is-sheet {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 180;
    margin: 0;
    max-width: none;
    max-height: min(38vh, 320px);
    border-radius: var(--radius) var(--radius) 0 0;
    border-bottom: 0;
    padding:
      0.35rem 1rem max(0.85rem, env(safe-area-inset-bottom)) 1.15rem;
    box-shadow:
      0 -4px 24px rgba(0, 0, 0, 0.12),
      0 0 0 1px var(--rule);
    transition: max-height 0.28s ease, box-shadow 0.2s ease;
    -webkit-overflow-scrolling: touch;
    scroll-margin-top: 0;
  }
  .recommend-card.is-active.is-sheet.is-sheet-expanded {
    max-height: min(88vh, 720px);
  }

  .sheet-handle {
    display: none;
    flex-direction: column;
    align-items: center;
    gap: 0.2rem;
    width: 100%;
    margin: 0 0 0.35rem;
    padding: 0.35rem 0.5rem 0.15rem;
    appearance: none;
    background: transparent;
    border: 0;
    cursor: pointer;
    color: var(--ink-soft);
    font: inherit;
    flex-shrink: 0;
  }
  .sheet-handle:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--radius);
  }
  .sheet-handle-bar {
    display: block;
    width: 2.5rem;
    height: 0.28rem;
    border-radius: 999px;
    background: var(--rule);
  }
  .sheet-handle-label {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--ink-soft);
  }
  .sheet-handle-action {
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--ink);
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .recommend-card.is-sheet-expanded .sheet-handle-action::after {
    content: ' · tap to collapse';
    font-weight: 500;
    color: var(--ink-soft);
    font-size: 0.78rem;
  }

  .recommend-card.is-sheet-peek .primary-cta {
    margin-top: 0;
  }
  .recommend-card.is-sheet-peek .primary-cta-btn {
    min-height: 48px;
    font-size: 1rem;
  }
  .recommend-card.is-sheet-peek .primary-cta-followup {
    min-height: 44px;
    padding: 0.45rem 0.75rem;
    font-size: 0.88rem;
  }

  .map-side {
    grid-template-columns: minmax(0, 1fr);
  }
  .map-card--act {
    order: -1;
  }
  .map-explore-details {
    border: 1px solid var(--rule);
    border-radius: var(--radius);
    background: var(--bg-soft);
    overflow: hidden;
  }
  .map-explore-details > summary.map-explore-summary {
    padding: 0.85rem 1rem;
    font-weight: 700;
    font-size: 0.95rem;
    cursor: pointer;
    list-style: none;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    min-height: 48px;
    box-sizing: border-box;
  }
  .map-explore-details > summary.map-explore-summary::-webkit-details-marker {
    display: none;
  }
  .map-explore-details > summary.map-explore-summary::after {
    content: '▾';
    font-size: 0.85rem;
    color: var(--ink-soft);
    transition: transform 0.2s ease;
  }
  .map-explore-details[open] > summary.map-explore-summary::after {
    transform: rotate(180deg);
  }
  .map-explore-inner {
    display: grid;
    gap: 1rem;
    padding: 0 1rem 1rem;
  }
  .map-explore-inner > .map-card {
    margin: 0;
  }
}

@media (max-width: 640px) {
  .hero .btn-row {
    flex-direction: column;
    width: 100%;
  }
  .hero .btn-row .btn {
    flex: 1 1 auto;
    width: 100%;
    justify-content: center;
    min-height: 48px;
    text-align: center;
  }
  .primary-cta-btn,
  .primary-cta-secondary {
    min-height: 48px;
    font-size: 1rem;
  }
  .primary-cta-followup {
    min-height: 44px;
    padding: 0.4rem 0.8rem;
  }
}

/* ========================================================================
   Apex /today/ card. Rendered into <div id="today-card"> by today.js
   after fetching /data/today.json. Lives directly inside .section >
   .container so the page chrome stays consistent with the rest of
   the apex secondary pages.
   ======================================================================== */
.today-card {
  padding: 1.5rem;
  border: 1px solid var(--rule);
  border-radius: 8px;
  background: var(--bg-soft, transparent);
}
.today-card[data-state="loading"] { padding: 1rem 1.25rem; }
.today-meta { margin: 0 0 0.3rem; }
.today-title { margin: 0 0 0.6rem; }
.today-summary { margin: 0 0 0.9rem; font-size: 1.05rem; }
.today-action { margin: 0 0 1rem; }
.today-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin: 0 0 1.1rem;
}
.today-foot { margin: 0; }

/* ========================================================================
   Apex /country/<iso3>/ page. Rendered into <main id="main"> by
   country.js after fetching /data/by-country/<iso3>.json. A 7-card
   grid, one per topic, with a deep link to that topic's map.
   ======================================================================== */
.country-stage {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
  gap: 1rem;
  margin: 1.2rem 0 2rem;
}
.country-topic {
  padding: 1rem 1.1rem;
  border: 1px solid var(--rule);
  border-radius: 8px;
  background: var(--bg-soft, transparent);
}
.country-topic h3 { margin: 0 0 0.4rem; font-size: 1.05rem; }
.country-topic .country-topic-value {
  font-size: 1.4rem;
  font-weight: 600;
  margin: 0 0 0.3rem;
}
.country-topic .country-topic-indicator {
  margin: 0 0 0.8rem;
  font-size: 0.85rem;
  color: var(--ink-soft);
}
.country-topic .country-topic-summary {
  margin: 0 0 0.9rem;
  font-size: 0.95rem;
}
.country-topic .country-topic-link {
  display: inline-block;
  font-weight: 500;
}
.country-topic[data-empty="true"] {
  opacity: 0.7;
}
.country-topic[data-empty="true"] .country-topic-value { color: var(--ink-soft); }
.country-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 1rem;
  margin: 0 0 0.6rem;
}
.country-head h1 { margin: 0; }
.country-head .country-iso { color: var(--ink-soft); font-weight: 500; }

/* ========================================================================
   Contribute-page context banner. Rendered only when /contribute/ is
   visited with `?topic=<id>` (and optionally `?country=<ISO3>`) in the
   URL — e.g. after a click from a recommender card's data-gap lane.
   ======================================================================== */
.contribute-context {
  margin: 0.6rem 0 0;
  padding: 0.5rem 0.75rem;
  border-left: 3px solid var(--accent, currentColor);
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  border-radius: 0 4px 4px 0;
}
.contribute-context a {
  color: inherit;
  font-weight: 500;
}

/* ========================================================================
   Cross-topic "this country across the rest of ActSmall" row.
   Injected inside .recommend-card by site-shared/js/other-topics.js on
   every successful country pick. Lives at the bottom of the card, after
   the existing footer paragraph, so the recommender's primary content
   (headline action, universal actions, source links) reads first.
   The row visually echoes the topic strip at the top of the page so a
   visitor recognises it as a cross-site control, not a topic-local one.
   ======================================================================== */
.other-topics-row {
  margin-top: 1.1rem;
  padding-top: 0.85rem;
  border-top: 1px dashed var(--rule);
}
.other-topics-lede {
  margin: 0 0 0.45rem;
}
.other-topics-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.other-topics-list li { margin: 0; }
.other-topics-list a {
  display: inline-block;
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  border: 1px solid var(--rule);
  background: var(--bg-soft, transparent);
  color: var(--ink, inherit);
  font-size: 0.85rem;
  font-weight: 500;
  text-decoration: none;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.other-topics-list a:hover,
.other-topics-list a:focus-visible {
  border-color: var(--accent, currentColor);
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}
@media (max-width: 30rem) {
  .other-topics-list a { font-size: 0.8rem; padding: 0.26rem 0.6rem; }
}

/* ========================================================================
   ActSmall * moments banner (BEGIN — owned by site-shared/js/moments.js)
   ------------------------------------------------------------------------
   A small attention-moment banner rendered at the top of each topic
   home (e.g. "World Bee Day. Plant a square metre of native pollinator
   forage this week.") when today falls inside one of the windows in
   site-shared/data/moments.json for the page's topic. The mount point
   is a single `<div data-actsmall-moment hidden>` placed near the top
   of the hero; the renderer un-hides it only when a match exists.

   Visual posture:
     - Quiet, accent-tinted card, not a banner-ad. Single CTA. No close
       button (refreshing the page is enough; nothing is stored).
     - No animation. No reliance on JS hover state. Dark-mode safe via
       the same `prefers-color-scheme` block as the rest of main.css.
     - Inside the hero container, this banner sits above the headline
       row; outside the hero container it sits where the author dropped
       the mount div.
   ======================================================================== */
[data-actsmall-moment][hidden] { display: none !important; }
[data-actsmall-moment] { display: block; margin: 0 0 1rem; }
.actsmall-moment {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  padding: 0.65rem 0.85rem;
  border: 1px solid var(--rule);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius, 6px);
  background: color-mix(in srgb, var(--accent) 6%, var(--bg-soft));
  color: var(--ink);
  font-size: 0.95rem;
  line-height: 1.4;
}
.actsmall-moment-icon {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.4rem;
  height: 1.4rem;
  margin-top: 0.05rem;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-ink, #fff);
  font-weight: 700;
  font-size: 0.85rem;
}
.actsmall-moment-body {
  flex: 1 1 auto;
  min-width: 0;
}
.actsmall-moment-text {
  margin: 0;
  font-weight: 500;
}
.actsmall-moment-cta {
  display: inline-block;
  margin-top: 0.3rem;
  font-weight: 600;
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.actsmall-moment-cta:hover,
.actsmall-moment-cta:focus-visible {
  text-decoration-thickness: 2px;
}
@media (max-width: 30rem) {
  .actsmall-moment { font-size: 0.9rem; padding: 0.55rem 0.7rem; }
  .actsmall-moment-icon { width: 1.2rem; height: 1.2rem; font-size: 0.75rem; }
}
@media (prefers-color-scheme: dark) {
  .actsmall-moment {
    background: color-mix(in srgb, var(--accent) 18%, transparent);
    border-color: color-mix(in srgb, var(--rule) 60%, transparent);
  }
}
/* ActSmall * moments banner (END) ====================================== */
