/* =============================================================
   Components — the portal's reusable design-system parts
   ============================================================= */

/* ---------- Navigation ---------------------------------------- */
.site-nav {
  position: sticky; top: 0; z-index: 80;
  background: var(--surface-raised);
  border-bottom: 1px solid var(--line-hairline);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
}
.site-nav__inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-4);
  min-height: var(--nav-height);
  padding-block: var(--space-3);
}
.brand { display: flex; align-items: center; gap: var(--space-3); color: inherit; }
.brand:hover { text-decoration: none; }
.brand__mark {
  height: 40px; width: auto; object-fit: contain;
  background: #fff; border-radius: var(--radius-sm); padding: 4px 8px;
  border: 1px solid var(--line-soft);
}
.brand__name { display: block; font-weight: 800; font-size: var(--step-1); letter-spacing: 0.01em; line-height: 1.2; }
.brand__sub {
  display: block;
  color: var(--brand-primary); font-size: 0.66rem; font-weight: 700;
  letter-spacing: 0.09em; text-transform: uppercase; margin-top: 2px;
}

.nav-toggle {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line-strong); border-radius: var(--radius-md);
  font-size: var(--step-0); font-weight: 700;
}
@media (min-width: 66rem) { .nav-toggle { display: none; } }

.nav-menu { display: flex; align-items: center; gap: 2px; flex-wrap: wrap; }
@media (max-width: 65.99rem) {
  .nav-menu {
    display: none;
    position: absolute; left: 0; right: 0; top: 100%;
    flex-direction: column; align-items: stretch; gap: var(--space-1);
    background: var(--surface-raised);
    border-bottom: 1px solid var(--line-hairline);
    box-shadow: var(--shadow-4);
    padding: var(--space-3) var(--shell-pad) var(--space-5);
    max-height: calc(100dvh - var(--nav-height));
    overflow-y: auto;
  }
  .nav-menu[data-open="true"] { display: flex; }
}

.nav-group { position: relative; }
.nav-link {
  display: flex; align-items: center; gap: var(--space-2);
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  font-size: var(--step-0); font-weight: 700;
  color: var(--brand-black);
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.nav-link:hover { background: var(--surface-sunken); text-decoration: none; }
.nav-link[aria-expanded="true"] { background: var(--surface-sunken); }
.nav-link[aria-current="page"],
.nav-link.is-active { background: var(--brand-primary); color: var(--ink-inverse); }
.nav-link__caret { font-size: 0.6rem; opacity: 0.7; transition: transform var(--dur-fast) var(--ease); }
.nav-link[aria-expanded="true"] .nav-link__caret { transform: rotate(180deg); }

.nav-submenu {
  min-width: 254px;
  background: var(--surface-raised);
  border: 1px solid var(--line-hairline);
  border-radius: var(--radius-lg);
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.16);
  padding: var(--space-1);
  z-index: 90;
}
@media (min-width: 66rem) {
  .nav-submenu { position: absolute; top: calc(100% + 6px); left: 0; }
}
@media (max-width: 65.99rem) {
  .nav-submenu { margin: var(--space-1) 0 var(--space-2) var(--space-4); box-shadow: none; }
}
.nav-submenu[hidden] { display: none; }
.nav-subitem {
  display: block; width: 100%; text-align: left;
  padding: var(--space-3); border-radius: var(--radius-md);
  font-size: var(--step-0); font-weight: 600; color: var(--brand-black);
}
.nav-subitem:hover { background: var(--surface-sunken); text-decoration: none; }
.nav-subitem[aria-current="page"] {
  background: var(--brand-primary-wash); color: var(--brand-primary); font-weight: 800;
}

/* ---------- Buttons -------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-md);
  font-size: var(--step-1); font-weight: 700;
  transition: transform var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease);
  white-space: nowrap;
}
.btn:hover { text-decoration: none; transform: translateY(-1px); }
.btn:active { transform: none; }
.btn--primary { background: var(--brand-primary); color: var(--ink-inverse); }
.btn--primary:hover { background: var(--brand-primary-ink); }
.btn--accent { background: var(--brand-accent); color: var(--brand-black); font-weight: 800; }
.btn--accent:hover { background: #edc40d; }
.btn--ghost-light { border: 1.5px solid rgba(255, 255, 255, 0.6); color: #fff; }
.btn--ghost-light:hover { background: rgba(255, 255, 255, 0.12); }
.btn--quiet {
  border: 1px solid var(--line-strong); background: var(--surface-raised);
  color: var(--ink-primary); font-weight: 700;
}
.btn--quiet:hover { background: var(--surface-hover); }
.btn--sm { padding: var(--space-2) var(--space-4); font-size: var(--step-0); }

.link-more {
  font-size: var(--step-0); font-weight: 700; color: var(--brand-primary);
  display: inline-flex; align-items: center; gap: 4px;
}
.link-more::after { content: "\2192"; transition: transform var(--dur-fast) var(--ease); }
.link-more:hover::after { transform: translateX(3px); }

/* ---------- Cards ---------------------------------------------- */
.card {
  background: var(--surface-raised);
  border: 1px solid var(--line-hairline);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-2);
  overflow: hidden;
}
.card__body { padding: var(--space-5); }
.card__rule { height: 6px; }
.card--interactive {
  cursor: pointer; text-align: left; width: 100%; display: block; color: inherit;
  transition: transform var(--dur-base) var(--ease), box-shadow var(--dur-base) var(--ease);
}
.card--interactive:hover { transform: translateY(-3px); box-shadow: var(--shadow-4); text-decoration: none; }

.panel {
  background: var(--surface-raised);
  border: 1px solid var(--line-hairline);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-1);
}
.panel__body { padding: var(--space-5); }
.panel__title { font-weight: 800; font-size: var(--step-1); }
.panel__divider { height: 1px; background: var(--line-soft); margin-block: var(--space-5); }

/* ---------- Chips, tags, bands --------------------------------- */
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  border: 1px solid var(--line-strong);
  background: var(--surface-raised);
  font-size: var(--step-0); font-weight: 700; color: var(--brand-black);
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.chip--sm { padding: 5px var(--space-3); font-size: var(--step--1); }
.chip:hover { background: var(--surface-sunken); }
.chip[aria-pressed="true"] {
  background: var(--brand-primary); border-color: var(--brand-primary); color: var(--ink-inverse);
}
.chip-row { display: flex; flex-wrap: wrap; gap: var(--space-2); }

.tag {
  display: inline-flex; align-items: center;
  padding: 2px var(--space-2);
  border-radius: var(--radius-pill);
  font-size: 0.625rem; font-weight: 700; line-height: 1.6;
  background: var(--surface-wash); color: var(--ink-secondary);
}
.tag--solid { color: var(--ink-inverse); }

/* A band chip always carries a glyph AND a word — never colour alone. */
.band {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px var(--space-3);
  border-radius: var(--radius-pill);
  font-size: 0.625rem; font-weight: 800; letter-spacing: 0.02em;
  color: var(--ink-inverse); white-space: nowrap;
}
.band__glyph { font-size: 0.7em; line-height: 1; }
.band--ontrack { background: var(--band-ontrack); }
.band--lagging { background: var(--band-lagging); }
.band--atrisk  { background: var(--band-atrisk); }

.legend { display: flex; flex-wrap: wrap; gap: var(--space-4); align-items: center; }
.legend__item { display: inline-flex; align-items: center; gap: 7px; font-size: var(--step-0); }
.legend__swatch {
  width: 14px; height: 14px; border-radius: 4px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff; font-size: 8px; line-height: 1;
}

/* ---------- Stat tiles -----------------------------------------
   The home strip, rebuilt after the UDB one. Three things change from the
   card it replaces: the unit moves onto its own line so the figure can be
   read at full size rather than wrapping ("UGX 3.788Tn" used to break and
   shrink, which left the largest number on the page reading smallest); the
   label moves from grey 12px under the figure onto a filled bar across the
   foot, where it is the second thing the eye lands on rather than the last;
   and the card turns portrait and centres, losing its 6px colour rule to a
   hairline.

   Proportions are the reference's own, measured off the screenshot rather
   than matched by eye: card height 1.19x its width, gutters 0.058 of the
   card, foot bar 0.238 of the card height, inset 0.063 of the width on both
   sides and the same again beneath it.

   The six hues stay. UDB's strip is one green because its six figures are
   one bank's accounts; ours are six different measures and the hue is how
   the dashboard refers back to them. Nothing rests on hue alone -- every
   card names itself on its own bar. */
.stat {
  display: flex; flex-direction: column;
  background: var(--surface-raised);
  border: 1px solid var(--line-hairline);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-1);
  transition: transform var(--dur-base) var(--ease), box-shadow var(--dur-base) var(--ease);
}
.stat:hover { transform: translateY(-3px); box-shadow: var(--shadow-3); }
/* Grows to fill whatever height the tallest card in the row sets, so the
   foot bars line up across all six however long their labels run. */
.stat__body {
  flex: 1;
  display: flex; flex-direction: column; align-items: center;
  text-align: center;
  padding: var(--space-5) var(--space-4) var(--space-7);
}
/* The pictogram at the size the reference draws it -- about a fifth of the
   card height -- and unchipped: a 34px glyph in a tinted rounded square
   became a 44px line drawing on plain white. icons.js authors these on a
   24 box at 1.7 stroke, which renders 3.1px wide at this size and reads as
   a marker pen, so the weight steps back to 1.3 (2.4px as drawn). */
.stat__icon {
  width: 52px; height: 52px; border-radius: 0; background: none;
  display: flex; align-items: center; justify-content: center;
  margin-bottom: var(--space-6);
}
.stat__icon svg { width: 52px; height: 52px; display: block; stroke-width: 1.2; }
.stat__value {
  font-family: var(--font-display); font-weight: 800; font-size: var(--step-6);
  line-height: 1.05; letter-spacing: -0.01em;
}
/* Only the cards whose figure has a unit carry this; the counts go straight
   from the number to the bar, as the reference's own JOBS card does. */
.stat__unit {
  display: block; margin-top: var(--space-1);
  font-weight: 700; font-size: var(--step-2); line-height: 1.2;
}
/* The label, on a bar filled in the card's hue. White caps on that fill is
   small text, so it answers to the 4.5:1 of WCAG 1.4.3 rather than the 3:1
   the old icon chip got away with -- see --kpi-*-fill in tokens.css, where
   orange and green step down to clear it. The height is fixed rather than
   fitted: a one-line label and a two-line label have to produce the same
   bar or the row goes ragged, so the text centres in a set box. */
.stat__tag {
  display: flex; align-items: center; justify-content: center;
  min-height: 3.75rem;
  margin: 0 var(--space-3) var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--ink-inverse);
  font-size: var(--step--1); font-weight: 700;
  letter-spacing: 0.04em; text-transform: uppercase;
  line-height: 1.25; text-align: center;
  text-wrap: balance;
}

/* ---------- KPI tiles -------------------------------------------
   A headline figure, what it counts, and one supporting fact that
   belongs to it. The figure is set in the UI sans rather than the
   display serif: at 34px a serif numeral reads as decoration on an
   analytical page, and these sit six across. Proportional figures,
   not tabular — tabular gives every digit the width of a zero, which
   leaves a number like 3,718 looking loose at this size. */
.kpi {
  display: flex; flex-direction: column;
  background: var(--surface-raised);
  border: 1px solid var(--line-hairline);
  border-radius: var(--radius-2xl);
  padding: var(--space-5);
  box-shadow: var(--shadow-1);
  transition: transform var(--dur-base) var(--ease), box-shadow var(--dur-base) var(--ease);
}
.kpi:hover { transform: translateY(-2px); box-shadow: var(--shadow-3); }
.kpi__top {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-2); margin-bottom: var(--space-3);
}
/* A filled disc in the tile's accent, white pictogram on it — the
   reference consoles' signature. The glyph is a graphic, not text, so
   the bar is the 3:1 of WCAG 1.4.11: white clears it on all six accents
   (red 7.4, violet 5.5, teal 5.0, blue 4.9, green 4.4, orange 3.3). The
   figure and the label beside it stay in ink, where the text bar
   applies. */
.kpi__icon {
  width: 38px; height: 38px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--ink-inverse);
}
.kpi__icon svg { width: 19px; height: 19px; display: block; }
.kpi__value {
  font-family: var(--font-ui); font-weight: 800; font-size: var(--step-6);
  line-height: 1.05; letter-spacing: -0.02em; color: var(--ink-primary);
}
.kpi__label {
  font-size: var(--step--1); font-weight: 700; color: var(--ink-secondary);
  margin-top: var(--space-1);
}
.kpi__meter { margin-top: var(--space-3); }
/* The note follows its label rather than being pinned to the card foot:
   only two of the six tiles carry a meter, and bottom-aligning the notes
   opened a gap in the four that do not. Slack sits at the card bottom
   now, where it reads as padding. */
.kpi__note {
  margin-top: var(--space-4);
  font-size: var(--step--1); color: var(--ink-muted); line-height: 1.45;
}

/* ---------- Charts --------------------------------------------- */
.chart { display: flex; flex-direction: column; gap: var(--space-3); }
.chart__caption { font-size: var(--step--1); color: var(--ink-secondary); }

/* Horizontal ranked bars: one series, magnitude, direct-labelled. */
.bars { display: flex; flex-direction: column; gap: var(--space-3); }
.bar__row { display: block; width: 100%; text-align: left; }
.bar__head {
  display: flex; justify-content: space-between; gap: var(--space-3);
  font-size: var(--step-0); margin-bottom: 4px;
}
.bar__value { font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.bar__track { height: 9px; background: var(--viz-track); border-radius: var(--radius-pill); overflow: hidden; }
.bar__fill {
  height: 100%; border-radius: var(--radius-pill);
  background: var(--viz-series);
  transition: width var(--dur-slow) var(--ease);
}
.bar__row:hover .bar__track { outline: 2px solid var(--line-strong); outline-offset: 2px; }

/* Columns: one series over time. Equal columns on a fixed plot height,
   each bar rising from the baseline with a 4px rounded top and a 2px gap
   to its neighbour; a recessive grid behind, the axis labels beneath, and
   direct labels only where the page asks for them (the peak, the latest).
   A hatched bar is a value the source gave only approximately. */
.cols {
  --cols-h: 220px;
  position: relative;
  display: grid; grid-template-columns: repeat(var(--cols, 12), minmax(0, 1fr));
  gap: 2px; align-items: end;
  padding: 1.6rem 0 1.8rem;
}
.cols__grid {
  position: absolute; left: 0; right: 0; top: 1.6rem; height: var(--cols-h);
  display: flex; flex-direction: column; justify-content: space-between; pointer-events: none;
}
.cols__grid > span { display: block; border-top: 1px solid var(--viz-grid); }
.cols__grid > span:last-child { border-top-color: var(--viz-axis); }
.col { position: relative; height: var(--cols-h); display: flex; align-items: flex-end; justify-content: center; }
.col__bar {
  display: block; width: 100%; max-width: 44px; height: var(--h, 0%); min-height: 2px;
  background: var(--col-color, var(--viz-series)); border-radius: 4px 4px 0 0;
}
.col--approx .col__bar {
  background: repeating-linear-gradient(135deg,
    var(--col-color, var(--viz-series)) 0 3px,
    color-mix(in srgb, var(--col-color, var(--viz-series)) 30%, #fff) 3px 6px);
}
.col__value {
  position: absolute; left: 50%; bottom: calc(var(--h, 0%) + 5px); transform: translateX(-50%);
  font-size: var(--step--1); font-weight: 700; white-space: nowrap; color: var(--ink-primary);
}
.col__axis {
  position: absolute; left: 50%; top: 100%; transform: translateX(-50%);
  margin-top: 7px; font-size: var(--step--1); color: var(--viz-label); white-space: nowrap;
}
/* A label centred on an edge column would spill past the plot; the first
   two and last two columns anchor theirs to the plot edge instead. */
.col:nth-child(2) .col__value, .col:nth-child(3) .col__value { left: 0; transform: none; }
.col:nth-last-child(-n + 2) .col__value { left: auto; right: 0; transform: none; }
/* Seventeen month labels do not fit a narrow plot: keep every third. The
   grid overlay is child one, so the first column is child two. */
@media (max-width: 60rem) { .col:not(:nth-child(3n + 2)) .col__axis { visibility: hidden; } }

.meter { height: 14px; background: var(--viz-track); border-radius: var(--radius-pill); overflow: hidden; }
.meter__fill { height: 100%; border-radius: var(--radius-pill); }
.meter--sm { height: 7px; }

/* Proportional mosaic — sequential fill, hairline ring keeps the
   lightest blocks legible against the white card. */
.mosaic { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.mosaic__block {
  flex: var(--grow, 1) 1 clamp(130px, 14vw, 170px);
  min-height: 150px;
  border-radius: var(--radius-lg);
  border: 1px solid rgba(27, 27, 27, 0.12);
  padding: var(--space-4);
  display: flex; flex-direction: column; justify-content: space-between; gap: var(--space-3);
  text-align: left;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
  transition: transform var(--dur-base) var(--ease), box-shadow var(--dur-base) var(--ease);
}
.mosaic__block:hover { transform: translateY(-2px); box-shadow: var(--shadow-3); text-decoration: none; }
.mosaic__name { font-size: var(--step-1); font-weight: 800; }
.mosaic__value { font-size: var(--step-4); font-weight: 800; font-variant-numeric: tabular-nums; }

.ramp-legend { display: flex; align-items: center; gap: var(--space-2); }
.ramp-legend__bar {
  width: 120px; height: 10px; border-radius: var(--radius-pill);
  background: linear-gradient(90deg, var(--seq-1), var(--seq-4), var(--seq-7));
  border: 1px solid rgba(27, 27, 27, 0.12);
}

/* ---------- Tables --------------------------------------------- */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table { width: 100%; border-collapse: collapse; font-size: var(--step-0); min-width: 720px; }
.table caption { text-align: left; padding: var(--space-4) var(--space-5) 0; font-size: var(--step--1); color: var(--ink-secondary); }
.table th, .table td { padding: var(--space-3) var(--space-5); text-align: left; }
.table thead th {
  background: var(--surface-sunken);
  font-size: 0.66rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--ink-secondary); white-space: nowrap;
}
.table tbody tr { border-bottom: 1px solid var(--line-soft); }
.table tbody tr:hover { background: var(--surface-hover); }
.table td.num { font-variant-numeric: tabular-nums; white-space: nowrap; }
.table__sort {
  display: inline-flex; align-items: center; gap: 4px; font: inherit;
  color: inherit; text-transform: inherit; letter-spacing: inherit;
}
.table__sort::after { content: "\2195"; opacity: 0.4; font-size: 0.9em; }
.table th[aria-sort="ascending"] .table__sort::after { content: "\2191"; opacity: 1; }
.table th[aria-sort="descending"] .table__sort::after { content: "\2193"; opacity: 1; }

.list-rows > * + * { border-top: 1px solid var(--line-soft); }
.row {
  display: flex; align-items: center; gap: var(--space-4);
  padding: var(--space-4) var(--space-5); width: 100%; text-align: left; color: inherit;
}
.row:hover { background: var(--surface-hover); text-decoration: none; }

.rank {
  width: 34px; height: 34px; border-radius: 10px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-weight: 800; font-size: var(--step-1);
  color: var(--ink-inverse);
}

/* ---------- Form controls --------------------------------------- */
.field { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.field__label {
  font-size: 0.68rem; font-weight: 800; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--ink-secondary);
}
.control {
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-raised);
  font-size: var(--step-0);
  min-height: 38px;
}
.control:hover { border-color: var(--ink-muted); }
.control:focus-visible { border-color: var(--brand-primary); box-shadow: var(--focus-ring); outline: none; }

.filter-bar {
  display: flex; flex-wrap: wrap; gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  background: var(--surface-raised);
  border: 1px solid var(--line-hairline);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-1);
  align-items: flex-end;
}
.filter-bar .field--grow { flex: 1 1 200px; }
.field--action { justify-content: flex-end; }

/* ---------- Media ----------------------------------------------- */
.media-frame { background: var(--surface-wash); overflow: hidden; position: relative; }
.media-frame img { width: 100%; height: 100%; object-fit: cover; }
.media-frame--empty::after {
  content: attr(data-placeholder);
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  padding: var(--space-3); text-align: center;
  font-size: var(--step--1); color: var(--ink-muted);
}

/* ---------- Dialog ---------------------------------------------- */
.dialog-backdrop {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(15, 8, 9, 0.58);
  display: flex; align-items: center; justify-content: center;
  padding: var(--space-5);
  animation: fadeUp var(--dur-base) var(--ease);
}
.dialog {
  background: var(--surface-raised);
  border-radius: var(--radius-2xl);
  box-shadow: var(--shadow-5);
  width: min(640px, 100%);
  max-height: min(85dvh, 900px);
  overflow: auto;
  padding: var(--space-6);
}
.dialog__head { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--space-4); }
.dialog__close {
  width: 34px; height: 34px; border-radius: var(--radius-md); flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--step-2); color: var(--ink-secondary);
}
.dialog__close:hover { background: var(--surface-sunken); }

/* ---------- Toast ------------------------------------------------ */
.toast {
  position: fixed; bottom: var(--space-5); right: var(--space-5); z-index: 200;
  background: var(--brand-black); color: var(--ink-inverse);
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-md);
  font-size: var(--step-0); font-weight: 600;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.25);
  animation: fadeUp var(--dur-base) var(--ease);
  max-width: min(360px, calc(100vw - 2 * var(--space-5)));
}

/* ---------- Empty state ------------------------------------------ */
.empty {
  padding: var(--space-8) var(--space-5);
  text-align: center;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-xl);
  background: var(--surface-raised);
}
.empty__title { font-weight: 800; font-size: var(--step-2); }

/* ---------- Footer ------------------------------------------------ */
.site-footer {
  background: var(--surface-dark);
  color: rgba(255, 255, 255, 0.85);
  padding-block: var(--space-8) var(--space-5);
  margin-top: var(--space-7);
  font-size: var(--step-0);
}
.site-footer a { color: rgba(255, 255, 255, 0.9); text-decoration: underline; }
.site-footer__grid { display: grid; gap: var(--space-7); }
@media (min-width: 52rem) { .site-footer__grid { grid-template-columns: 1.2fr 1fr 1fr; } }
.site-footer__title {
  color: var(--brand-accent); font-weight: 700; font-size: var(--step--1);
  letter-spacing: 0.06em; text-transform: uppercase; margin-bottom: var(--space-3);
}
.site-footer__list { line-height: 2; }
.site-footer__base {
  margin-top: var(--space-6); padding-top: var(--space-4);
  border-top: 1px solid rgba(255, 255, 255, 0.15);
  font-size: var(--step--1); color: rgba(255, 255, 255, 0.6);
  display: flex; justify-content: space-between; gap: var(--space-4); flex-wrap: wrap;
}

/* ---------- Live indicator ---------------------------------------- */
.live-dot {
  width: 9px; height: 9px; border-radius: 50%; background: #D21034;
  animation: pulseDot 1.6s infinite; flex-shrink: 0;
}

/* ---------- Partner brand marks ----------------------------------- */
/* A brand mark may stand in for a stat tile's glyph: same slot, same
   radius, nothing painted behind it. */
.stat__icon--image { display: block; object-fit: cover; padding: 0; }

/* White button for use on a partner-coloured surface. */
.btn--light { background: #fff; color: var(--ink-primary); }
.btn--light:hover { background: #FFF6F1; }

/* ---------- Video (lite YouTube embed) ------------------------------
   The thumbnail and a play button stand in for the player; the iframe is
   created only when play is pressed (app.js → 'play-video'). */
.yt-lite {
  position: relative;
  aspect-ratio: 16 / 9;
  width: 100%;
  background: #0d0d0d;
  border-radius: var(--radius-xl);
  overflow: hidden;
  box-shadow: var(--shadow-3);
}
.yt-lite__poster {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  opacity: 0.94;
  transition: transform var(--dur-slow) var(--ease), opacity var(--dur-base) var(--ease);
}
.yt-lite__button {
  position: absolute; inset: 0; width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0) 55%, rgba(0, 0, 0, 0.45) 100%);
  cursor: pointer;
}
.yt-lite__button:hover .yt-lite__play { transform: scale(1.07); background: var(--brand-primary-ink); }
.yt-lite__button:hover ~ .yt-lite__poster,
.yt-lite:hover .yt-lite__poster { transform: scale(1.03); opacity: 1; }
.yt-lite__button:focus-visible { outline: 3px solid var(--brand-accent); outline-offset: -3px; border-radius: var(--radius-xl); }
.yt-lite__play {
  width: 72px; height: 50px; border-radius: 14px;
  display: flex; align-items: center; justify-content: center;
  background: var(--brand-primary); color: #fff;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  transition: transform var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.yt-lite__play svg { margin-left: 3px; }
.yt-lite__frame { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

.video-card__thumb {
  display: block; position: relative;
  aspect-ratio: 16 / 9; background: #0d0d0d; overflow: hidden;
}
.video-card__thumb img { width: 100%; height: 100%; object-fit: cover; }
.video-card__badge {
  position: absolute; right: var(--space-3); bottom: var(--space-3);
  width: 30px; height: 30px; border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, 0.72); color: #fff;
}
.video-card__badge svg { margin-left: 1px; }
.video-card[aria-current="true"] { outline: 2px solid var(--brand-primary); outline-offset: 0; }
.video-card[aria-current="true"] .video-card__badge { background: var(--brand-primary); }

.site-footer__social { margin-top: var(--space-4); }
.site-footer__social a {
  display: inline-flex; align-items: center; gap: var(--space-2);
  text-decoration: none; font-weight: 700; color: #fff;
}
.site-footer__social a:hover span { text-decoration: underline; }
.site-footer__social svg { color: #FF0033; flex-shrink: 0; }

/* ---------- Repayment map (real geography, Uganda-Locale boundaries) ---
   Interaction state (hover, selection, sub-region highlight, the
   repayment/region toggle) is local to results.js's mount(), not the
   query string — see the comment above the `repayment` page export. */
.repay-map { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(260px, 1fr); gap: var(--space-5); align-items: start; margin-top: var(--space-2); }
@media (max-width: 62rem) { .repay-map { grid-template-columns: 1fr; } }

.repay-map__panel { background: var(--surface-raised); border: 1px solid var(--line-hairline); border-radius: var(--radius-xl); box-shadow: var(--shadow-2); overflow: hidden; }
.repay-map__controls { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); flex-wrap: wrap; padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--line-hairline); }
.repay-map__controls .field { min-width: 180px; }

.repay-map__stage { padding: var(--space-3) clamp(4px, 1.5vw, var(--space-5)) 0; }
.repay-map__svg { display: block; width: 100%; height: auto; }
.repay-map__district {
  stroke: var(--surface-raised); stroke-width: 0.6; cursor: pointer;
  transition: filter var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease), stroke-width var(--dur-fast) var(--ease);
}
.repay-map__district:hover { filter: brightness(1.12); stroke-width: 1.4; }
.repay-map__district.is-selected,
.repay-map__district.is-highlight { stroke: var(--ink-primary); stroke-width: 1.8; }
.repay-map__district.is-match { stroke: var(--ink-primary); stroke-width: 1.6; }
.repay-map__district.is-dim { opacity: 0.22; }
.repay-map__region-outline { fill: none; stroke: var(--ink-primary); stroke-opacity: 0.28; stroke-width: 1.2; pointer-events: none; }

.repay-map__side { display: flex; flex-direction: column; }
.repay-map__side .row.is-active { background: var(--brand-primary-wash); }

/* ---------- The layered results map --------------------------------------
   Two marks, one frame. A rate layer shades the land; a count layer leaves
   it uniform and sizes a circle at each sub-region's centroid, because on
   a real map an area's size is its geography, not its figure. The
   sub-region outline is what holds either reading together — it is
   dissolved out of the district borders at runtime (data/subregion-geo.js),
   so the districts underneath stay hoverable. */
.repay-map__stage--capped { display: flex; justify-content: center; padding-bottom: var(--space-3); }
.repay-map__svg--layered { width: auto; max-width: 100%; max-height: 640px; }

.repay-map__svg--layered .repay-map__district { stroke: var(--surface-raised); stroke-width: 0.45; }
.repay-map__svg--layered .repay-map__district:hover { filter: brightness(1.06); stroke-width: 0.45; }
.repay-map__svg--layered .repay-map__district.is-highlight { stroke: var(--surface-raised); stroke-width: 0.45; }

.map-subregion-outline {
  stroke: var(--ink-primary); stroke-opacity: 0.4; stroke-width: 1.3;
  stroke-linejoin: round; pointer-events: none;
  transition: stroke-opacity var(--dur-fast) var(--ease), stroke-width var(--dur-fast) var(--ease);
}
.map-subregion-outline.is-active { stroke-opacity: 1; stroke-width: 2.4; }

.map-rank-list { max-height: 27rem; overflow-y: auto; }
@media print { .map-rank-list { max-height: none; overflow: visible; } }

/* Each region takes one of the logo's four colours: the circles in full,
   the land beneath them as a pale wash of the same hue. */
.repay-map__svg--layered {
  --map-land-central:  #FDF4D2;
  --map-land-eastern:  #FCE3DF;
  --map-land-northern: #DDEFEE;
  --map-land-western:  #DDF1E5;
}
.map-symbol { cursor: pointer; transition: opacity var(--dur-fast) var(--ease); --sym: var(--seq-6); --sym-ink: var(--ink-inverse); }
.map-symbol--central  { --sym: var(--region-central); --sym-ink: var(--ink-primary); }
.map-symbol--eastern  { --sym: var(--region-eastern); }
.map-symbol--northern { --sym: var(--region-northern); }
.map-symbol--western  { --sym: var(--region-western); }
.map-symbol__disc {
  fill: var(--sym); fill-opacity: 0.88; stroke: var(--surface-raised); stroke-width: 1.5;
  transition: fill-opacity var(--dur-fast) var(--ease);
}
.map-symbol:hover .map-symbol__disc { fill-opacity: 1; }
.map-symbol.is-active .map-symbol__disc { fill-opacity: 1; stroke: var(--ink-primary); stroke-width: 2.2; }
.map-symbol.is-dim { opacity: 0.3; }
.map-symbol__nil { fill: var(--map-land); stroke: var(--seq-6); stroke-opacity: 0.6; stroke-width: 1.3; }
.map-symbol--none:hover .map-symbol__nil { stroke-opacity: 1; }

/* ---------- The layer's national figure ---------------------------
   What the layer measures on the left, what it comes to nationally in
   the middle, how it is drawn on the right. The figure keeps its own
   card because it is the headline of the page, not a caption to the
   band beside it; it carries a provenance marker like every other
   figure on the portal, and stays in ink rather than taking the map's
   colour, which belongs to the data. */
.map-summary {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: var(--space-4) var(--space-5);
  margin-top: var(--space-4);
}
.map-summary__desc { flex: 1 1 22rem; margin: 0; }

.map-total {
  display: flex; flex-direction: column; align-items: flex-end; text-align: right;
  margin-left: auto;
  padding: var(--space-4) var(--space-5);
  background: var(--surface-raised);
  border: 1px solid var(--line-hairline);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-1);
}
/* The largest thing on the page, deliberately: the page title is a step
   below it. The map answers where; this answers how much, and how much is
   the programme's whole claim. */
.map-total__value {
  font-family: var(--font-ui); font-weight: 800; font-size: var(--step-6);
  letter-spacing: -0.02em; line-height: 1.05;
}
.map-total__label {
  display: flex; align-items: center; gap: 7px;
  margin-top: 3px;
  font-size: var(--step--1); font-weight: 600; color: var(--ink-secondary);
}
.map-total__leader { margin-top: 2px; font-size: var(--step--1); color: var(--ink-muted); }

@media (max-width: 47.99rem) {
  .map-total { align-items: flex-start; text-align: left; width: 100%; }
}
.map-symbol--none.is-active .map-symbol__nil { stroke: var(--ink-primary); stroke-opacity: 1; stroke-width: 1.8; }
.map-symbol__label {
  font-family: var(--font-ui); font-size: 12px; font-weight: 800;
  pointer-events: none; paint-order: stroke; stroke-width: 4px; stroke-linejoin: round;
}
.map-symbol__label--in { fill: var(--sym-ink); stroke: var(--sym); }
.map-symbol__label--out { fill: var(--ink-primary); stroke: var(--map-land); }

/* Kampala, magnified into the empty south-east of the frame — 0.2% of the
   country's area, and otherwise neither visible nor clickable. */
.map-inset__leader { stroke: var(--ink-muted); stroke-width: 1; stroke-dasharray: 4 3; }
.map-inset__locator { fill: none; stroke: var(--ink-primary); stroke-width: 1.4; }
.map-inset__ground { fill: var(--surface-raised); }
.map-inset__ring { fill: none; stroke: var(--line-strong); stroke-width: 1.6; }
.map-inset__context { fill: var(--surface-wash); stroke: var(--surface-raised); stroke-width: 0.5; }
.map-inset__label { font-family: var(--font-ui); font-size: 15px; font-weight: 700; fill: var(--ink-secondary); }

/* Selected sub-region: its figures across every layer, not only the
   mapped one. */
.map-facts { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3) var(--space-4); margin-top: var(--space-4); }
.map-facts dt { font-size: var(--step--1); color: var(--ink-secondary); }
.map-facts dd { margin: 2px 0 0; font-weight: 800; font-size: var(--step-1); }

/* Nested circles at exactly the size the map draws them, so the reader
   measures against the real thing rather than a key. */
.symbol-legend { display: flex; align-items: center; gap: var(--space-5); flex-wrap: wrap; }
.symbol-legend__figure { flex: none; height: auto; }
.symbol-legend__disc { fill: none; stroke: var(--ink-muted); stroke-width: 1.3; }
.symbol-legend__tick { stroke: var(--line-strong); stroke-width: 1; }
.symbol-legend__key { font-family: var(--font-ui); font-size: 12px; fill: var(--ink-secondary); font-variant-numeric: tabular-nums; }
.symbol-legend__note { max-width: 24ch; }

/* ---------- Map tooltip -------------------------------------------------- */
.map-tooltip {
  position: fixed; z-index: 90; pointer-events: none; max-width: 220px;
  background: var(--brand-black); color: var(--ink-inverse); border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4); font-size: var(--step--1);
  box-shadow: var(--shadow-4); opacity: 0; transform: translate(-50%, calc(-100% - 12px));
  transition: opacity var(--dur-fast) var(--ease);
}
.map-tooltip.is-visible { opacity: 1; }
@media print { .map-tooltip { display: none; } }

/* ---------- Provenance markers ----------------------------------
   Which figures are reported and which are not, carried beside each
   one rather than in a single footnote at the foot of the page.
   Shape as well as hue: a filled disc is published, a hollow ring is
   illustrative, a diamond is derived — so the three stay apart in
   grayscale, in print and under any colour vision. */
.prov {
  display: inline-block; width: 9px; height: 9px; flex-shrink: 0;
  border-radius: 50%; vertical-align: 1px;
}
.prov--published    { background: var(--band-ontrack); }
.prov--illustrative { background: transparent; border: 2px solid var(--kpi-orange); }
.prov--derived      { background: var(--kpi-violet); border-radius: 1px; transform: rotate(45deg); }

.prov-key {
  display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-5);
  font-size: var(--step--1); color: var(--ink-secondary);
}
.prov-key__item { display: inline-flex; align-items: center; gap: 7px; }

/* ---------- Part-to-whole --------------------------------------
   One bar, one segment per class. A 2px gap in the page colour does
   the separating — never a stroke, which would add ink that is not
   data. Nothing is labelled inside a segment: an interior segment has
   no free end, and small white text does not clear contrast on all
   four region hues. The key beneath carries every value instead. */
.stack-bar {
  display: flex; gap: 2px; height: 30px;
  border-radius: var(--radius-sm); overflow: hidden;
}
.stack-bar__seg { display: block; height: 100%; min-width: 2px; }
.stack-bar__seg:first-child { border-radius: var(--radius-sm) 0 0 var(--radius-sm); }
.stack-bar__seg:last-child  { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }

.stack-key { margin-top: var(--space-4); }
.stack-key__item {
  display: grid;
  grid-template-columns: 12px 1fr auto auto;
  align-items: center; gap: var(--space-3);
  padding: var(--space-3) 0;
  font-size: var(--step-0);
  border-bottom: 1px solid var(--line-soft);
}
.stack-key__item:last-child { border-bottom: 0; }
.stack-key__swatch { width: 12px; height: 12px; border-radius: 3px; }
.stack-key__label { color: var(--ink-primary); }
.stack-key__value { font-weight: 700; }
.stack-key__pct {
  min-width: 3.5ch; text-align: right;
  color: var(--ink-secondary); font-weight: 700;
}

/* ---------- Ranked list -----------------------------------------
   Position is a numeral first and a colour second, so the order
   survives a monochrome print. */
.ranklist { display: flex; flex-direction: column; }
.ranklist__row {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--line-soft);
}
.ranklist__row:last-child { border-bottom: 0; }
.ranklist__no {
  width: 26px; height: 26px; border-radius: 8px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--step--1); font-weight: 800; color: var(--ink-inverse);
}
.ranklist__body { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.ranklist__name {
  font-size: var(--step-0); font-weight: 700; color: var(--ink-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ranklist__sub { font-size: var(--step--1); color: var(--ink-secondary); }
.ranklist__figures { display: flex; flex-direction: column; align-items: flex-end; flex-shrink: 0; }
.ranklist__value { font-size: var(--step-0); font-weight: 700; }
.ranklist__note { font-size: var(--step--1); color: var(--ink-secondary); }

/* ---------- Region colour, outside the map -------------------------------
   The results map gives each region one of the logo's four colours; a
   SACCO, training centre or sub-region row elsewhere carries the same one,
   always beside the region's name — never colour alone. */
.region-tag {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--step--1); color: var(--ink-secondary);
}
.region-tag--after { margin-left: 8px; }
.region-tag__dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.card--region { border-top: 5px solid var(--region, var(--line-hairline)); }

/* The logo's slash — gold, red, teal, green — as a hairline band under the
   header. Brand, not data: it is the only place these four colours appear
   without meaning a region. */
.site-nav::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 4px;
  background: linear-gradient(90deg,
    var(--logo-gold) 0 25%, var(--logo-red) 25% 50%,
    var(--logo-teal) 50% 75%, var(--logo-green) 75% 100%);
  pointer-events: none;
}
@media print { .site-nav::after { display: none; } }
.wall-row--region { border-left: 5px solid var(--region, var(--line-hairline)); }
/* On a region-coloured row the location reads in ink: brand maroon beside
   the red of Eastern would look like a second region colour. */
.wall-row--region .wall-item__location { color: var(--ink-primary); }
