/* =============================================================
   Page compositions — layouts that belong to a single page
   ============================================================= */

/* ---------- Home hero ------------------------------------------- */
.hero {
  position: relative;
  overflow: hidden;
  background: var(--brand-primary);
  padding-block: clamp(3rem, 2rem + 5vw, 5rem) clamp(2.5rem, 1.5rem + 5vw, 4rem);
  min-height: clamp(380px, 46vw, 480px);
  display: flex; align-items: center;
}
.hero__slide {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease);
}
.hero__slide.is-active { opacity: 1; }
/* Photographs whose subject sits away from the centre: `cover` on a wide
   hero would otherwise crop to empty sky or roofing. */
.hero__slide[src$="photo-dairy-cow-feeding.jpg"] { object-position: 50% 96%; }
/* The animals sit at the far left of this frame, behind the headline. Over-
   widening the slide crops the empty hillside on the right and carries them
   across into the clear half; `overflow: hidden` on .hero trims the excess. */
.hero__slide[src$="photo-dairy-cows-fodder.jpg"] {
  width: 140%; max-width: none;   /* the reset caps images at 100% */
  object-position: 50% 45%;       /* keeps the farmer, trims the hooves */
}
.hero__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(90deg, rgba(20, 4, 6, 0.88) 0%, rgba(20, 4, 6, 0.62) 42%, rgba(20, 4, 6, 0.22) 78%);
}
@media (max-width: 48rem) {
  .hero__scrim { background: linear-gradient(180deg, rgba(20, 4, 6, 0.72) 0%, rgba(20, 4, 6, 0.88) 100%); }
}
.hero__content { position: relative; width: 100%; }
.hero__eyebrow {
  display: inline-block;
  padding: 5px var(--space-3);
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.16);
  color: var(--brand-accent);
  font-size: var(--step--1); font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  margin-bottom: var(--space-5);
}
.hero__title {
  font-family: var(--font-display); font-weight: 600;
  font-size: var(--step-7); line-height: 1.08;
  color: #fff; max-width: 20ch;
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.35);
  text-wrap: balance;
}
.hero__lede {
  font-size: var(--step-2); line-height: 1.6;
  color: rgba(255, 255, 255, 0.92);
  max-width: 56ch; margin-top: var(--space-5);
}
.hero__actions { display: flex; gap: var(--space-3); margin-top: var(--space-7); flex-wrap: wrap; }
.hero__dots { display: flex; gap: 7px; margin-top: var(--space-7); }
.hero__dot {
  width: 14px; height: 10px; padding: 3px 0;
  background-clip: content-box; background-color: rgba(255, 255, 255, 0.45);
  border-radius: var(--radius-pill);
  transition: width var(--dur-base) var(--ease), background-color var(--dur-base) var(--ease);
}
.hero__dot[aria-selected="true"] { width: 28px; background-color: var(--brand-accent); }

/* Stat strip rides up over the hero on wide screens. */
.hero-stats { position: relative; margin-top: calc(-1 * var(--space-8)); }
@media (max-width: 48rem) { .hero-stats { margin-top: var(--space-6); } }
/* Six abreast, fixed rather than auto-fitted: the cards are portrait now and
   auto-fit let the row reflow to five-and-one at intermediate widths. The
   gutter is the reference's own 0.058 of a card, which at this width is
   var(--space-3). */
.hero-stats .grid--200 {
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: var(--space-3);
}
/* Three, then two. Six portrait cards need about 170px each to hold a
   nine-digit figure; below that the row folds rather than squeezing. */
@media (max-width: 64rem) {
  .hero-stats .grid--200 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    max-width: 46rem; margin-inline: auto;
  }
}
/* On phones the six headline figures sit two abreast rather than in one
   long column; the figure steps down one size so it still fits its tile. */
@media (max-width: 40rem) {
  .hero-stats .grid--200 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hero-stats .stat__body { padding: var(--space-4) var(--space-3) var(--space-3); }
  .hero-stats .stat__icon,
  .hero-stats .stat__icon svg { width: 38px; height: 38px; }
  .hero-stats .stat__icon { margin-bottom: var(--space-4); }
  /* The figure scales with the viewport so it fits a half-width tile; it is
     never allowed to break between digits. */
  .hero-stats .stat__value { font-size: clamp(1.25rem, 6.2vw, var(--step-5)); }
  .hero-stats .stat__tag { min-height: 4rem; margin: 0 var(--space-2) var(--space-2); }
}

/* ---------- About ------------------------------------------------ */
/* The page is laid out after udbl.co.ug's own About pages, at the client's
   direction (2026-09-20). The proportions are measured off the reference
   screenshot rather than judged by eye. It is a 2000px-wide capture of a
   1271px viewport, so each figure below is the measurement divided by that
   viewport width, carried here as a vw:

     band height   412px → 0.206 of the window
     title size     77px → 0.0385
     mark height   164px → 0.082   (0.40 of the band)
     side inset    228px → 0.114   ⇒ a measure 0.772 of the window

   What is borrowed from the reference's gradient is its shape, not its
   hue: flat for the first fifth, ramping to seven tenths, flat again. The
   reference's two indigos are 21 points of lightness apart, which on this
   portal's maroon would land in a pink no white text could sit on, so the
   ramp runs #6E020A → #A81421 — 12.4:1 and 7.5:1 against white. */
.about-page {
  /* The reference's content is 0.772 of its window; 1180px gives 0.775 of
     a 1440px one. Only the measure narrows — the bands are outside the
     shell and stay full-bleed, as they do there. */
  --shell-max: 1180px;
  --surface-page: #FFFFFF;
  /* The portal's own page plane, which on this white page is a band tint. */
  --about-tint: #F4F3EF;
  background: var(--surface-page);
  /* The site footer carries a top margin, which on a white page shows as a
     strip of the site's beige plane between the two. The page absorbs it:
     grows by that much, pulls the footer back up the same amount. */
  padding-bottom: calc(var(--space-9) + var(--space-7));
  margin-bottom: calc(-1 * var(--space-7));
}

/* The title band: the page's name, its claim and its calls to action on a
   gradient, with no photograph behind them. */
.page-band {
  background: linear-gradient(90deg, #6E020A 0%, #6E020A 20%, #A81421 70%, #A81421 100%);
  color: var(--ink-inverse);
}
.page-band__inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-7);
  min-height: clamp(13.75rem, 20.6vw, 19.5rem);
  /* space-8 here pushed the content past the min-height and the band grew
     to 0.219 of the window; at space-7 the copy fits inside it and the band
     measures 296px on a 1440px one — 0.2056, against the reference's
     0.206, with the mark at 0.399 of its height against 0.40. */
  padding-block: var(--space-7);
}
/* A rem measure, not a `ch` one: `ch` here resolves against this block's
   own 14px body size, which squeezed the 54px title into a third of the
   band and broke it over two lines. */
.page-band__copy { max-width: 40rem; }
.page-band__eyebrow {
  color: var(--brand-accent);
  font-size: var(--step--1); font-weight: 800;
  letter-spacing: 0.08em; text-transform: uppercase;
}
.page-band__title {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(2.125rem, 1.1rem + 3.85vw, 3.4rem);
  line-height: 1.05; text-wrap: balance; margin-top: var(--space-3);
}
.page-band__lede {
  font-size: var(--step-2); line-height: 1.6; max-width: 32rem;
  color: rgba(255, 255, 255, 0.9); margin-top: var(--space-4); text-wrap: pretty;
}
.page-band__actions { display: flex; gap: var(--space-3); flex-wrap: wrap; margin-top: var(--space-6); }
/* The mark is the band's one ornament, as it is in the reference: a single
   line drawing at four tenths of the band's height, with no chip or disc
   behind it. icons.js draws at 1.7 in a 24 box for a 24px tile; past 100px
   that stroke reads as a slab, so this one is thinned to hold the weight
   the reference's mark has. */
.page-band__mark { flex: 0 0 auto; color: rgba(255, 255, 255, 0.95); }
.page-band__mark svg {
  width: clamp(4.5rem, 8.2vw, 7.5rem); height: clamp(4.5rem, 8.2vw, 7.5rem);
  stroke-width: 1.15;
}
/* Below this the copy fills the band and the mark would crowd it. */
@media (max-width: 52rem) { .page-band__mark { display: none; } }
/* The page's maroon focus ring would vanish on the band. */
.page-band :focus-visible { outline-color: var(--brand-accent); }

/* Every block below the mandate band keeps one rhythm. */
.about-section { padding-block: var(--space-9) 0; }
.about-section--last { padding-block: var(--space-9) 0; }
.about-section > .eyebrow + .about-h2 { margin-top: var(--space-2); }
.about-sub {
  margin-top: var(--space-3); font-size: var(--step-1);
  color: var(--ink-secondary); max-width: 62ch;
}

/* Section headings take the brand colour, as the reference's do. */
.about-h2 {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(1.5rem, 1.05rem + 1.4vw, 2.125rem);
  line-height: 1.2; color: var(--brand-primary); text-wrap: balance;
}

/* The scale, directly under the band so the figures anchor the page before
   any prose asks to be read. */
.about-scale { padding-top: var(--space-7); }
.about-scale .about-facts { margin-top: 0; }

/* "What Pillar 3 is": prose beside the one photograph, the way the
   reference opens with "Who we are". */
.about-intro { display: grid; gap: var(--space-7); align-items: start; padding-block: var(--space-9) 0; }
@media (min-width: 60rem) { .about-intro { grid-template-columns: 1.15fr 1fr; gap: var(--space-9); } }
.about-prose {
  font-size: var(--step-2); line-height: 1.75; max-width: 62ch;
  margin-top: var(--space-5); text-wrap: pretty;
}
/* The four services the guidelines name: a ruled row, not four cards, so
   the section stays one block of reading. */
.about-services {
  display: grid; margin-top: var(--space-8);
  border-top: 1px solid var(--line-strong);
}
@media (min-width: 40rem) {
  .about-services { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--space-7); }
}
@media (min-width: 64rem) {
  .about-services { grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: var(--space-6); }
}
.about-services > li { padding-block: var(--space-4); border-bottom: 1px solid var(--line-strong); }
.about-services__name { display: block; font-weight: 800; font-size: var(--step-1); }
.about-services__text {
  display: block; margin-top: 2px; font-size: var(--step-0);
  line-height: 1.55; color: var(--ink-secondary);
}
.about-intro__figure { margin: 0; }
.about-intro__caption { font-size: var(--step--1); color: var(--ink-secondary); margin-top: var(--space-3); }

/* The mandate, set as a statement on the page's one photographic moment.
   It used to be folded into a disclosure below the fold; the reference
   gives its mandate, vision and mission a section each, and this is the
   one piece of the page that is issued text rather than ours. */
.about-mandate {
  position: relative; overflow: hidden;
  background: var(--brand-primary-ink); color: var(--ink-inverse);
  margin-top: var(--space-9);
  padding-block: clamp(2.75rem, 2rem + 3.4vw, 5rem);
}
.about-mandate__photo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.about-mandate__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(90deg, rgba(84, 3, 10, 0.96) 0%, rgba(84, 3, 10, 0.9) 50%, rgba(84, 3, 10, 0.72) 100%);
}
.about-mandate__content { position: relative; }
.about-mandate__eyebrow {
  color: var(--brand-accent);
  font-size: var(--step--1); font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase;
}
.about-mandate__title {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(1.75rem, 1.2rem + 2.4vw, 2.75rem);
  line-height: 1.1; text-wrap: balance; max-width: 20ch; margin-top: var(--space-3);
}
.about-mandate__quote {
  margin-top: var(--space-6); padding-left: var(--space-6);
  border-left: 3px solid var(--brand-accent);
  font-family: var(--font-display); font-size: clamp(1rem, 0.85rem + 0.6vw, 1.375rem);
  line-height: 1.7; color: rgba(255, 255, 255, 0.94); max-width: 62ch; text-wrap: pretty;
}
.about-mandate__cite { margin-top: var(--space-5); font-size: var(--step-0); color: rgba(255, 255, 255, 0.8); }
.about-mandate__cite a { color: var(--brand-accent); font-weight: 700; }
.about-mandate :focus-visible { outline-color: var(--brand-accent); }

/* The six focus areas. The reference sets its high impact goals as a row
   of oversized numerals over the text, each under a rule; the guidelines
   number these i to vi, so those are the numerals used. */
.goal-grid { display: grid; gap: var(--space-6); margin-top: var(--space-7); }
@media (min-width: 40rem) { .goal-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 64rem) { .goal-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.goal { border-top: 2px solid var(--brand-primary); padding-top: var(--space-4); }
.goal__num {
  display: block; font-family: var(--font-display); font-weight: 700;
  font-size: clamp(1.75rem, 1.3rem + 1.5vw, 2.5rem); line-height: 1;
  color: var(--brand-primary);
}
.goal__text { margin-top: var(--space-3); font-size: var(--step-2); line-height: 1.6; text-wrap: pretty; }

/* The seven pillars, on a tinted band of their own. Each takes the colour
   it is given as a top rule; the third — this site's subject — is filled,
   so the reader can see at a glance which one they are reading about. */
.about-pillars { background: var(--about-tint); margin-top: var(--space-9); }
.about-pillars .about-section { padding-block: var(--space-9); }
.pillar-row { display: grid; gap: var(--space-4); margin-top: var(--space-7); }
@media (min-width: 40rem) { .pillar-row { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 64rem) { .pillar-row { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
/* Block, not flex: the numeral, the name and the note stack. The seven
   used to be `.grid--260 > li`, which is flexed for the cards it is meant
   for, and the note ended up alongside the name rather than under it. */
.pillar-tile {
  display: block;
  background: var(--surface-raised);
  border: 1px solid var(--line-hairline);
  border-top: 4px solid var(--pillar-color, var(--line-strong));
  border-radius: var(--radius-md);
  padding: var(--space-4);
}
.pillar-tile__num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--pillar-color, var(--ink-muted)); color: var(--ink-inverse);
  font-size: var(--step-0); font-weight: 800;
}
.pillar-tile__name {
  margin-top: var(--space-3); font-weight: 800; font-size: var(--step-1);
  line-height: 1.35; text-wrap: balance;
}
.pillar-tile__desc {
  margin-top: var(--space-2); font-size: var(--step--1);
  line-height: 1.55; color: var(--ink-secondary);
}
.pillar-tile.is-current {
  background: var(--brand-primary); border-color: var(--brand-primary);
  border-top-color: var(--brand-accent); color: var(--ink-inverse);
}
.pillar-tile.is-current .pillar-tile__num { background: var(--brand-accent); color: var(--brand-black); }
.pillar-tile.is-current .pillar-tile__desc { color: rgba(255, 255, 255, 0.88); }
.pillar-tile__here {
  display: inline-block; margin-top: var(--space-3);
  font-size: var(--step--1); font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--brand-accent);
}

/* The scale of the pillar: four figures in one hairline-ruled row, two by
   two on phones. Rules, not cards: these figures frame the page rather
   than compete with it. */
.about-facts {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  margin-top: var(--space-8);
  border-top: 1px solid var(--line-strong); border-bottom: 1px solid var(--line-strong);
}
@media (min-width: 48rem) { .about-facts { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.about-fact { padding: var(--space-5) var(--space-5) var(--space-5) 0; }
.about-fact + .about-fact { border-left: 1px solid var(--line-strong); padding-left: var(--space-5); }
@media (max-width: 47.99rem) {
  .about-fact { padding-right: var(--space-4); }
  .about-fact + .about-fact { padding-left: var(--space-4); }
  .about-fact:nth-child(3) { border-left: 0; padding-left: 0; }
  .about-fact:nth-child(-n + 2) { border-bottom: 1px solid var(--line-strong); }
}
/* The figure scales with the viewport so "UGX 3.788Tn" stays on one line
   in a quarter column; it never breaks inside the amount. */
.about-fact__value {
  font-family: var(--font-display); font-weight: 700; line-height: 1;
  font-size: clamp(1.375rem, 2.6vw, var(--step-6)); white-space: nowrap;
  font-variant-numeric: tabular-nums; color: var(--brand-primary);
}
.about-fact__label { font-size: var(--step-1); font-weight: 800; margin-top: var(--space-3); }
.about-fact__note { font-size: var(--step--1); color: var(--ink-secondary); margin-top: 2px; }

/* A field photograph under a maroon scrim, white copy, a ruled row of
   points and a folded quote beneath. This began on About; that page now
   sets its own statement band (`.about-mandate` above), and these classes
   are what "Why repayment matters" on #/loan-terms is built from. */
.about-band {
  position: relative; overflow: hidden;
  background: var(--brand-primary-ink); color: var(--ink-inverse);
  padding-block: clamp(2.5rem, 2rem + 3vw, 4.5rem);
}
.about-band__photo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.about-band__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(90deg, rgba(84, 3, 10, 0.95) 0%, rgba(84, 3, 10, 0.88) 55%, rgba(84, 3, 10, 0.74) 100%);
}
.about-band__content { position: relative; }
.about-band__head { display: grid; gap: var(--space-5); align-items: end; }
@media (min-width: 60rem) { .about-band__head { grid-template-columns: 1.1fr 1fr; gap: var(--space-9); } }
.about-band__eyebrow {
  color: var(--brand-accent);
  font-size: var(--step--1); font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase;
}
.about-band__title {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(1.75rem, 1.2rem + 2.4vw, 2.75rem); line-height: 1.1;
  text-wrap: balance; max-width: 18ch; margin-top: var(--space-3);
}
.about-band__lede { font-size: var(--step-1); line-height: 1.65; color: rgba(255, 255, 255, 0.9); max-width: 52ch; }
.about-band__services {
  display: grid; gap: var(--space-5) var(--space-6);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin-top: var(--space-7);
}
@media (min-width: 60rem) { .about-band__services { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.about-band__services > li { border-top: 2px solid var(--brand-accent); padding-top: var(--space-4); }
.about-band__service-name { display: block; font-family: var(--font-display); font-weight: 600; font-size: var(--step-3); }
.about-band__service-text { display: block; margin-top: var(--space-2); font-size: var(--step-0); line-height: 1.55; color: rgba(255, 255, 255, 0.85); }
.about-band__quote { margin-top: var(--space-7); font-size: var(--step-0); }
.about-band__quote summary { cursor: pointer; font-weight: 700; color: var(--brand-accent); width: fit-content; }
.about-band__quote summary:hover { text-decoration: underline; }
.about-band__quote blockquote {
  margin-top: var(--space-4); padding-left: var(--space-5);
  border-left: 2px solid rgba(255, 255, 255, 0.4);
  font-family: var(--font-display); font-size: var(--step-2); line-height: 1.7;
  color: rgba(255, 255, 255, 0.92); max-width: 68ch; text-wrap: pretty;
}
/* The page's maroon focus ring would vanish on the maroon band. */
.about-band :focus-visible { outline-color: var(--brand-accent); }

.prose-serif {
  font-family: var(--font-display);
  font-size: var(--step-2); line-height: 1.75;
  text-wrap: pretty; max-width: 68ch;
}

/* The six focus areas, numbered as the guidelines number them, in two
   ruled columns. */
.focus-list { display: grid; column-gap: var(--space-9); border-top: 1px solid var(--line-strong); }
@media (min-width: 52rem) { .focus-list { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.focus-list > li {
  display: flex; gap: var(--space-4); align-items: baseline;
  padding-block: var(--space-5); border-bottom: 1px solid var(--line-strong);
}
.focus-list__num {
  font-family: var(--font-display); font-weight: 700; font-size: var(--step-4);
  color: var(--brand-primary); width: 2.25rem; flex-shrink: 0;
}
.focus-list__text { font-size: var(--step-2); line-height: 1.55; text-wrap: pretty; }

/* The six components in a fixed three by two, so no card is left alone on
   a row; each card's story link sits on the same baseline. */
.comp-grid { display: grid; gap: var(--space-4); }
@media (min-width: 40rem) { .comp-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 64rem) { .comp-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.comp-grid > li { display: flex; }
.comp-card { display: flex; flex-direction: column; flex: 1; }
.comp-card__body { display: flex; flex-direction: column; flex: 1; gap: var(--space-3); }
.comp-card__title { font-weight: 800; font-size: var(--step-3); line-height: 1.35; text-wrap: balance; }
.comp-card__blurb { font-size: var(--step-0); line-height: 1.55; color: var(--ink-secondary); }
.comp-card__more { margin-top: auto; padding-top: var(--space-2); }

/* ---------- How a PRF loan works ---------------------------------- */
/* The page ran on a page-scoped dark navy plane from 2026-09-14 (taken
   from a dashboard screenshot) until 2026-09-20, when the client asked
   for the background to change: it now sits on the site's ordinary
   warm-neutral plane like every other page, and `.loan-page` is a plain
   scope with no plane of its own. What it keeps from the dark version is
   the one thing worth keeping — the four terms as small cards with a
   coloured top bar (below) — now drawn the way every other card on a
   light plane is, with a hairline and a shadow rather than
   white-against-navy doing the lifting.

   Nothing here redefines ink or line tokens any more: on the site plane
   the defaults are already right, so the reset block that forced white
   boxes back to dark ink, and the gold overrides that kept the rule
   numbers and the details summary legible on navy, are both gone. Those
   elements are back to brand maroon by inheritance. */

/* The four terms borrow the About page's ruled fact row; here they
   become small white cards with a coloured top bar per term, supplied
   by pages/loans.js via the --tile-accent custom property. */
/* The gap beneath the tiles used to come from the shell that followed them;
   inside the rail they and the first section are siblings, so the row
   carries it. */
.loan-facts { margin-top: 0; margin-bottom: var(--space-8); border-top: 0; border-bottom: 0; gap: var(--space-4); }
.loan-page .about-fact {
  background: var(--surface-raised); border-radius: var(--radius-xl);
  padding: var(--space-5); box-shadow: var(--shadow-2);
  border: 1px solid var(--line-hairline);
  border-top: 4px solid var(--tile-accent, var(--brand-accent));
}
/* The ruled-row rules the About page sets on adjacent facts (a dividing
   left border, a bottom border on the first two when they wrap) would
   double up on a card that already has four sides, so each is restated
   as the card's own hairline rather than switched off. */
.loan-page .about-fact + .about-fact { border-left: 1px solid var(--line-hairline); padding-left: var(--space-5); }
@media (max-width: 47.99rem) {
  .loan-page .about-fact:nth-child(3) { border-left: 1px solid var(--line-hairline); padding-left: var(--space-5); }
  .loan-page .about-fact:nth-child(-n + 2) { border-bottom: 1px solid var(--line-hairline); }
}

/* The plan: the three years as cards beside the worked example. */
.loan-plan { display: grid; gap: var(--space-5); align-items: start; }
@media (min-width: 62rem) { .loan-plan { grid-template-columns: minmax(0, 1.6fr) minmax(280px, 1fr); } }
.loan-timeline { display: grid; gap: var(--space-4); }
@media (min-width: 40rem) { .loan-timeline { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.loan-year {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-5); border-radius: var(--radius-xl);
  background: var(--surface-raised); border: 1px solid var(--line-hairline); box-shadow: var(--shadow-1);
  border-top: 5px solid var(--line-strong);
}
.loan-year--repay { border-top-color: var(--brand-accent); }
.loan-year__span { font-size: var(--step--1); font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-secondary); }
.loan-year__title { font-family: var(--font-display); font-weight: 600; font-size: var(--step-3); }
.loan-year__text { font-size: var(--step-0); line-height: 1.55; color: var(--ink-secondary); }

/* The worked example sits beside the three year cards, so it is inset
   rather than raised: the page's sunken tint marks it as a read-out of
   the years rather than a fourth card in the row. The total was gold
   while the plane was navy; on a light panel gold runs about 1.6:1
   against the tint, so it takes the brand maroon the tile figures above
   already use. */
.loan-example {
  background: var(--surface-sunken);
  border: 1px solid var(--line-hairline);
  border-radius: var(--radius-xl); padding: var(--space-5);
}
.loan-example__row {
  display: flex; justify-content: space-between; gap: var(--space-4); align-items: baseline;
  padding-block: var(--space-3); font-size: var(--step-0); color: var(--ink-secondary);
}
.loan-example__row + .loan-example__row { border-top: 1px solid var(--line-strong); }
.loan-example__row b { color: var(--ink-primary); }
.loan-example__total { font-size: var(--step-1); font-weight: 700; color: var(--ink-primary); }
.loan-example__total b { font-family: var(--font-display); font-size: var(--step-4); color: var(--brand-primary); }

/* The rules reuse the focus-area list, with a bold title line above each. */
.focus-list__title { display: block; font-weight: 800; margin-bottom: 4px; }
.focus-list--rules .focus-list__text { font-size: var(--step-1); }

.why-grid { display: grid; gap: var(--space-5) var(--space-6); }
@media (min-width: 40rem) { .why-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.why-grid > li { border-top: 2px solid var(--brand-accent); padding-top: var(--space-4); }
.why-grid__title { display: block; font-family: var(--font-display); font-weight: 600; font-size: var(--step-3); }
.why-grid__text { display: block; margin-top: var(--space-2); font-size: var(--step-0); line-height: 1.55; color: var(--ink-secondary); }

/* Inside the maroon band the why-grid takes white type and the repeat-loan
   panel floats as the one light object. */
.loan-band__grid { display: grid; gap: var(--space-6); align-items: start; margin-top: var(--space-7); }
@media (min-width: 60rem) { .loan-band__grid { grid-template-columns: minmax(0, 1.5fr) minmax(280px, 1fr); gap: var(--space-9); } }
.loan-band .why-grid__title { color: var(--ink-inverse); }
.loan-band .why-grid__text { color: rgba(255, 255, 255, 0.85); }
.loan-band .panel { border: 0; box-shadow: var(--shadow-4); }
/* The band sets white ink on itself, and a white panel inside it inherits
   that already-resolved literal -- so its heading and its kv values turn
   white on white. Anything with a colour of its own (the .meta line, the
   kv terms) survives, which is why the labels showed and the values did
   not. Re-anchoring `color` on the panel puts every plain-text child back
   to page ink. (The loan page's old dark scope did this for every white
   box on the page and happened to cover this one too; it went with the
   navy on 2026-09-20, so the band now carries its own fix.) */
.about-band .panel { color: var(--ink-primary); }

/* Key/value rows: the repeat-loan terms. */
.kv__row {
  display: grid; grid-template-columns: minmax(6.5rem, 8rem) 1fr; gap: var(--space-3);
  padding-block: var(--space-3); border-top: 1px solid var(--line-soft); font-size: var(--step-0);
}
.kv__row:first-child { border-top: 0; padding-top: 0; }
.kv__row dt { font-size: 0.66rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-secondary); padding-top: 3px; }
.kv__row dd { line-height: 1.5; }

/* Who does what: a ruled list. */
.roles > li { padding-block: var(--space-4); border-top: 1px solid var(--line-strong); }
.roles > li:last-child { border-bottom: 1px solid var(--line-strong); }
.roles__who { display: block; font-weight: 800; font-size: var(--step-1); }
.roles__what { display: block; margin-top: 3px; font-size: var(--step-0); line-height: 1.55; color: var(--ink-secondary); }

/* The arrears timeline marks each step with its day rather than a number. */
.flow-step__when {
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  min-width: 5.25rem; padding: 4px var(--space-3); border-radius: var(--radius-pill);
  background: var(--brand-primary); color: var(--ink-inverse);
  font-size: var(--step--1); font-weight: 800; white-space: nowrap;
}

.loan-details > summary { cursor: pointer; width: fit-content; font-weight: 800; font-size: var(--step-1); color: var(--brand-primary); }
.loan-details > summary:hover { text-decoration: underline; }

/* ---------- Component cards -------------------------------------- */
.comp-badge {
  width: 26px; height: 26px; border-radius: var(--radius-md);
  display: flex; align-items: center; justify-content: center;
  color: var(--ink-inverse); font-weight: 800; font-size: var(--step-0);
  flex-shrink: 0;
}

/* ---------- District map ----------------------------------------- */
.district-group__head {
  display: flex; justify-content: space-between; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
}
.district-group__name { color: var(--ink-inverse); font-weight: 800; font-size: var(--step-0); }
.district-group__region {
  color: rgba(255, 255, 255, 0.9); font-size: 0.66rem; font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase;
}
.district-list { padding: var(--space-4); display: flex; flex-direction: column; gap: 6px; }
.district-row {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  background: var(--surface-hover);
  width: 100%; text-align: left; color: inherit;
}
.district-row:hover { background: var(--surface-sunken); text-decoration: none; }
.district-row__dot { width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; }
.district-row__name { flex: 1; font-size: var(--step-0); font-weight: 700; }
.district-row__value { font-size: var(--step-0); font-weight: 800; font-variant-numeric: tabular-nums; }

/* ---------- Systems ---------------------------------------------- */
.system-card__head {
  padding: var(--space-4) var(--space-5);
  min-height: 92px;
  display: flex; justify-content: space-between; align-items: center; gap: var(--space-4);
}
.system-card__name { color: var(--ink-inverse); font-weight: 800; font-size: var(--step-2); }
.system-card__owner { color: rgba(255, 255, 255, 0.88); font-size: var(--step--1); margin-top: 2px; }
/* A partner's mark closes the header. The thin white ring keeps its own
   brand orange distinct from the deeper surface it sits on. */
.system-card__mark {
  width: 56px; height: 56px; border-radius: 10px; flex-shrink: 0;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.85);
}
.system-card__label {
  font-size: 0.66rem; font-weight: 800; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--ink-secondary);
}

.flow-step { display: flex; gap: var(--space-4); align-items: flex-start; }
.flow-step__num {
  width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0;
  background: var(--brand-primary); color: var(--ink-inverse);
  display: flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: var(--step-0);
}
.flow-step + .flow-step { margin-top: var(--space-4); }

.callout {
  background: var(--brand-primary);
  color: var(--ink-inverse);
  border-radius: var(--radius-xl);
  padding: var(--space-6);
  display: flex; justify-content: space-between; align-items: center;
  gap: var(--space-5); flex-wrap: wrap;
}
.callout__title { font-family: var(--font-display); font-size: var(--step-4); font-weight: 600; }
.callout__text { font-size: var(--step-0); color: rgba(255, 255, 255, 0.88); margin-top: var(--space-2); max-width: 60ch; }

/* WENDI media callout: the field photograph beside the message, stacked
   photo-over-text on phones. Painted in the partner's deep orange so the
   white copy clears 5:1 (see --brand-wendi-deep). */
.callout--wendi {
  background: var(--brand-wendi-deep);
  padding: 0;
  display: grid; grid-template-columns: minmax(0, 1fr);
  align-items: stretch; gap: 0;
  min-height: 260px;
  overflow: hidden;
}
@media (min-width: 52rem) { .callout--wendi { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); } }
.callout__media { position: relative; min-height: 220px; }
.callout__media img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: 58% 40%;
}
.callout__body { padding: var(--space-6); display: flex; flex-direction: column; justify-content: center; }
.callout__lockup { display: flex; align-items: center; gap: var(--space-3); }
.callout__mark {
  width: 44px; height: 44px; border-radius: 10px; flex-shrink: 0;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.85);
}
.callout__action { margin-top: var(--space-5); }

/* ---------- Stories ---------------------------------------------- */
/* Home: three stories as rows beside the field video, so the column sits
   level with the player instead of running past it. */
.story-row { align-items: center; }
.story-row .media-frame { width: 148px; flex-shrink: 0; }
.story-row .tag { font-size: 0.625rem; }
/* The beneficiary's own words, cut at two lines; the full quote is on the
   story itself. */
.story-row__quote {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden;
  margin-top: var(--space-2);
  font-family: var(--font-display); font-size: var(--step-0); line-height: 1.5;
  color: var(--ink-primary); text-wrap: pretty;
}
/* Narrow text column on phones: a third line lets a sentence finish. */
@media (max-width: 40rem) { .story-row__quote { -webkit-line-clamp: 3; } }

.story-card__quote {
  font-size: var(--step-0); line-height: 1.65;
  margin-top: var(--space-3); text-wrap: pretty;
}

/* A narrative set as paragraphs, spaced rather than indented. Shared by the
   SACCO profile's "About this SACCO" and by a story, which steps it up a
   size of its own -- see .story-body--feature further down. */
.story-body { font-size: var(--step-1); }
.story-body > p + p { margin-top: var(--space-4); }
.stat-pair { display: flex; gap: var(--space-6); flex-wrap: wrap; }
.stat-pair__value { font-weight: 800; font-size: var(--step-1); }
.stat-pair__label { font-size: 0.625rem; color: var(--ink-secondary); }
.card__footer {
  margin-top: var(--space-4); padding-top: var(--space-3);
  border-top: 1px solid var(--line-soft);
}

/* ---------- Field updates -----------------------------------------------------
 *
 * All that is left of the Impact Wall: two rules for the strip of recent
 * field updates that Home and News each carry. The board that collected
 * them is gone — every source it aggregated has a page of its own.
 * ------------------------------------------------------------------------- */

.wall-item__location { font-size: var(--step--1); font-weight: 800; color: var(--brand-primary); }
.wall-item__time { font-size: var(--step--1); color: var(--ink-muted); white-space: nowrap; }

/* ---------- Events ------------------------------------------------ */
.events { max-width: 1100px; margin-inline: auto; }
.event { display: flex; gap: var(--space-5); align-items: center; flex-wrap: wrap; padding: var(--space-5); }
.event__date { text-align: center; flex-shrink: 0; width: 62px; }
.event__day {
  font-family: var(--font-display); font-size: var(--step-5); font-weight: 800;
  color: var(--brand-primary); line-height: 1;
}
.event__month {
  font-size: 0.66rem; font-weight: 800; color: var(--ink-secondary);
  text-transform: uppercase; letter-spacing: 0.08em;
}
.event__body { flex: 1 1 240px; border-left: 1px solid var(--line-soft); padding-left: var(--space-5); }

/* ---------- Utility rows -------------------------------------------- */
.inline { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.between { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-3); flex-wrap: wrap; }
.note {
  display: inline-block;
  padding: var(--space-3) var(--space-4);
  background: var(--surface-wash);
  border-radius: var(--radius-md);
  font-size: var(--step-0); color: var(--ink-secondary);
}
.note b { color: var(--ink-primary); }
.source-line { font-size: var(--step--1); color: var(--ink-secondary); margin-top: var(--space-3); }

/* ---------- Videos ------------------------------------------------- */
.channel-card { padding: var(--space-5); }
.channel-card__name { font-family: var(--font-display); font-weight: 600; font-size: var(--step-4); margin-top: var(--space-2); }
.channel-card__name .muted { font-family: var(--font-ui); font-size: var(--step-0); font-weight: 600; }
.channel-card .source-line { margin-top: var(--space-4); }
.video-description {
  margin-top: var(--space-4);
  font-size: var(--step-1); line-height: 1.7; color: var(--ink-secondary);
  white-space: pre-line; max-width: 72ch;
}
@media print { .yt-lite__button { display: none; } }

/* ---------- Home: the repayment map summary --------------------------
   The map replaces what used to be eighteen sub-region cards: one figure
   carrying the same national picture in roughly a quarter of the height.
   The full explorer (search, sub-region list, detail panel) stays on
   #/repayment — this is the teaser, so it links there rather than holding
   state of its own. */
.home-map { display: grid; gap: var(--space-5); align-items: stretch; }
@media (min-width: 62rem) {
  .home-map { grid-template-columns: minmax(0, 1.2fr) minmax(260px, 1fr); }
}

.home-map__figure {
  margin: 0;
  display: flex; flex-direction: column;
  background: var(--surface-raised);
  border: 1px solid var(--line-hairline);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-2);
  padding: var(--space-4) var(--space-4) var(--space-3);
}
/* Height-led rather than width-led: the drawing is slightly taller than it
   is wide, so sizing by height is what keeps this section from towering
   over the rest of the page. The auto block margin centres it when the
   column runs taller than the drawing. */
.home-map__figure .repay-map__svg {
  height: clamp(260px, 40vw, 540px);
  width: auto;
  max-width: 100%;
  margin-inline: auto;
  margin-block: auto;
}
/* Stacked on narrower screens the figure has the full width to itself, so
   the drawing is sized by width there instead — height-led sizing would
   strand it in the middle of a very wide card. */
@media (max-width: 61.99rem) {
  .home-map__figure .repay-map__svg { width: min(100%, 560px); height: auto; }
}

.home-map__caption {
  display: flex; justify-content: space-between; align-items: center;
  gap: var(--space-3) var(--space-5); flex-wrap: wrap;
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--line-soft);
}

/* The summary sits level with the map rather than stopping short of it:
   the panel fills the row height and the sourcing line falls to the foot. */
.home-map__aside { display: flex; }
.home-map__aside .panel__body { flex: 1; display: flex; flex-direction: column; }
.home-map__aside .stack > li { list-style: none; }
.home-map__aside .source-line { margin-top: auto; padding-top: var(--space-5); }

/* =============================================================
   Dashboard
   -------------------------------------------------------------
   Panels are paired wide-with-narrow and each pair is its own
   grid row, so a tall panel never leaves its neighbour with a
   column of dead white beneath it — which is what the single
   auto-fit grid used to do here.
   ============================================================= */

.dash .page-title {
  font-family: var(--font-ui); font-weight: 800;
  letter-spacing: -0.02em; font-size: var(--step-5);
}
.dash .panel__title { font-size: var(--step-2); letter-spacing: -0.01em; }

.dash__head {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: var(--space-4); flex-wrap: wrap;
  margin-bottom: var(--space-3);
}
.dash__head .lede { margin-top: var(--space-2); }

/* The export menu: one button, three formats. It is a <details>, so the
   open/close state, the keyboard handling and the focus order are the
   element's own; pages.css only has to make the summary look like the
   button it replaced and hang a panel under it. */
.export { position: relative; }
.export__toggle {
  list-style: none; cursor: pointer; user-select: none;
}
.export__toggle::-webkit-details-marker { display: none; }
.export__toggle::after {
  content: "▾"; font-size: 0.85em; margin-left: 2px;
  transition: transform var(--dur-fast) var(--ease);
}
.export[open] .export__toggle { background: var(--brand-primary-ink); }
.export[open] .export__toggle::after { transform: rotate(180deg); }

.export__menu {
  position: absolute; z-index: 40; right: 0; top: calc(100% + 6px);
  display: grid; gap: 2px;
  width: max-content; max-width: min(320px, calc(100vw - 2 * var(--space-5)));
  padding: var(--space-2);
  background: var(--surface-raised);
  border: 1px solid var(--line-strong); border-radius: var(--radius-md);
  box-shadow: var(--shadow-4);
}
.export__item {
  display: grid; gap: 1px; justify-items: start; text-align: left;
  width: 100%; padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm); color: var(--ink-primary);
}
.export__item:hover, .export__item:focus-visible { background: var(--brand-primary-wash); }
.export__item b { font-size: var(--step-1); }
.export__item span { font-size: var(--step--1); color: var(--ink-secondary); }

/* On a phone the head stacks, and a panel pinned to the right edge of a
   full-width button is a panel half off the screen. */
@media (max-width: 560px) {
  .export, .export__toggle { width: 100%; }
  .export__menu { right: auto; left: 0; width: 100%; max-width: none; }
}

.dash .prov-key {
  padding: var(--space-3) 0;
  border-block: 1px solid var(--line-hairline);
}

/* The period strip gets its own row above the dropdowns, the way the
   month strip does in the reference console. Sharing a row with them
   meant that at 1280px it wrapped underneath and left an L-shaped gap. */
.dash__toolbar {
  display: grid; gap: var(--space-4);
  margin: var(--space-5) 0 var(--space-6);
  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);
}
.dash__periods {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--line-hairline);
}
.dash__selects {
  display: flex; flex-wrap: wrap; align-items: flex-end;
  gap: var(--space-4); flex: 1 1 520px;
}
.dash__selects .field { flex: 1 1 170px; }
/* The Reset button is a button, not a field: it keeps its own width
   rather than stretching to an equal share of the row. */
.dash__selects .field--action { flex: 0 0 auto; }

/* Three across, two down. Six across is what the page had before the
   rail took 232px off the width: at 188px a tile has to set 3,768,000 in
   34px type inside 32px of padding, and the figure runs to both edges.
   Three gives each tile the proportions the reference cards have. */
.dash__kpis {
  display: grid; gap: var(--space-4);
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-bottom: var(--space-6);
}

.dash__row {
  display: grid; gap: var(--space-4);
  align-items: start;
  margin-bottom: var(--space-4);
}
.dash__row--wide-narrow { grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr); }
.dash__panel { margin-bottom: var(--space-4); }

.dash .panel { border-radius: var(--radius-2xl); border: 1px solid var(--line-hairline); box-shadow: var(--shadow-1); }
.dash .panel__body { padding: var(--space-6); }
.dash__plot { margin-top: var(--space-5); }

/* Marks a panel that keeps reporting the country while a sub-region
   filter is on, so its figures are not read as the sub-region's. */
.dash__scope {
  display: inline-block; margin-left: 4px;
  padding: 1px var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--surface-wash);
  font-size: var(--step--1); font-weight: 700; color: var(--ink-secondary);
}
.dash__shares { display: flex; flex-direction: column; gap: var(--space-4); margin-top: var(--space-5); }

/* The provenance note that closes a panel: pushed to the foot so the
   panels in a row line their notes up rather than floating them. */
.dash__foot {
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
  margin-top: var(--space-5); padding-top: var(--space-3);
  border-top: 1px solid var(--line-soft);
  font-size: var(--step--1); color: var(--ink-muted);
}
.dash__foot .link-more { font-size: var(--step--1); margin-left: auto; }

/* ---- The sub-region table ---- */
.dash__table { min-width: 820px; }
.dash__table th[scope="row"] { font-weight: 700; }
.dash__table tbody tr.is-selected { background: var(--brand-primary-wash); }
.dash__dot {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  margin-right: 7px; vertical-align: 1px;
}
.dash__region {
  display: block; margin-left: 15px;
  font-size: var(--step--1); font-weight: 600; color: var(--ink-muted);
}
.dash__inline { display: flex; align-items: center; gap: var(--space-3); }
.dash__inline-track {
  flex: 1; min-width: 46px; height: 6px;
  background: var(--viz-track); border-radius: var(--radius-pill);
}
.dash__inline-fill { display: block; height: 100%; border-radius: var(--radius-pill); }

/* ---- Administrative levels ---- */
.dash__levels { display: flex; flex-direction: column; margin-top: var(--space-5); }
.dash__levels--row {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-5); margin-top: var(--space-4);
}
.dash__levels--row .dash__level {
  grid-template-columns: 1fr; border-bottom: 0;
  padding: var(--space-4) var(--space-5);
  background: var(--surface-sunken); border-radius: var(--radius-md);
}
.dash__levels--row .dash__level-count { grid-row: auto; font-size: var(--step-6); }
.dash__levels-note {
  display: flex; align-items: center; gap: 7px;
  font-size: var(--step--1); color: var(--ink-muted);
}
.dash__level {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: baseline;
  gap: 2px var(--space-3);
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--line-soft);
}
.dash__level:last-child { border-bottom: 0; }
.dash__level-count {
  grid-row: span 2;
  font-family: var(--font-ui); font-weight: 800; font-size: var(--step-3);
  min-width: 4.5ch;
}
.dash__level-label { font-size: var(--step-0); font-weight: 700; }
.dash__level-avg { font-size: var(--step--1); color: var(--ink-secondary); }


@media (max-width: 900px) {
  .dash__row--wide-narrow { grid-template-columns: minmax(0, 1fr); }
  .dash__levels--row { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); }
  .dash__levels-note { display: none; }
}
@media (max-width: 560px) {
  .dash__kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); }
  .dash__kpis .kpi__value { font-size: var(--step-5); }
  .dash__toolbar { padding: var(--space-4); }
  .dash .panel__body { padding: var(--space-4); }
  .dash__selects .field { flex: 1 1 100%; }
  .stack-key__item { grid-template-columns: 12px 1fr auto; }
  .stack-key__pct { grid-column: 2 / -1; text-align: left; }
}

/* =============================================================
   Section shell — the dark rail
   -------------------------------------------------------------
   Taken from the reference consoles: the section's own list down
   the side with the current entry marked, one block of context at
   the foot. The site's top navigation is untouched.

   Three sections run inside it — the Results console, whose rail
   lists its pages; the Stories archive, whose rail lists the six
   pillar components with the number of stories behind each; and
   Documents, whose rail lists its three shelves with the number of
   papers on each. Hence `.rail` rather than `.dash-rail`: it
   belongs to none of them.
   ============================================================= */

.rail-shell {
  display: grid;
  grid-template-columns: 232px minmax(0, 1fr);
  gap: var(--space-6);
  align-items: start;
}

.rail {
  position: sticky;
  top: calc(var(--nav-height) + var(--space-4));
  background: var(--surface-dark);
  border-radius: var(--radius-2xl);
  padding: var(--space-5);
  color: var(--ink-inverse);
}
.rail__eyebrow {
  font-size: 0.6rem; font-weight: 800; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--brand-accent);
}
.rail__list { margin-top: var(--space-4); display: flex; flex-direction: column; gap: 2px; }
.rail__link {
  display: block; padding: var(--space-3);
  border-radius: var(--radius-md);
  color: rgba(255, 255, 255, 0.72);
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.rail__link:hover { background: rgba(255, 255, 255, 0.07); color: #fff; text-decoration: none; }
/* `--rail-on` is set per entry where the section has a colour of its own to
   mark the current one with — the component colours on the archive. Where it
   is not set the fallback is the brand red the Results rail has always used. */
.rail__link.is-current { background: var(--rail-on, var(--brand-primary)); color: #fff; }
.rail__label {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2);
  font-size: var(--step-0); font-weight: 700;
}
/* The count sits at the right of the label, quiet until the entry is the
   current one. It is the number of stories behind a component, so it says
   which strands of the pillar have been written up and which have not. */
.rail__count { font-size: var(--step--1); font-weight: 700; opacity: 0.6; }
.rail__link.is-current .rail__count { opacity: 0.85; }
/* Two lines, then an ellipsis: four of the six component titles are a full
   sentence long, and a rail is 232px wide. */
.rail__note {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden;
  font-size: var(--step--1); line-height: 1.35; opacity: 0.66; margin-top: 2px;
}
.rail__foot {
  margin-top: var(--space-6); padding-top: var(--space-4);
  border-top: 1px solid rgba(255, 255, 255, 0.14);
}
.rail__value { font-size: var(--step-1); font-weight: 800; margin-top: 2px; }
.rail__source {
  font-size: var(--step--1); color: rgba(255, 255, 255, 0.55);
  margin-top: var(--space-1); line-height: 1.45;
}

/* =============================================================
   Donut
   ============================================================= */

.donut {
  display: grid;
  grid-template-columns: 246px minmax(0, 1fr);
  gap: var(--space-7);
  align-items: center;
}
.donut__ring { position: relative; }
.donut__ring svg { display: block; width: 100%; height: auto; }
.donut__centre {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; pointer-events: none;
}
.donut__total {
  font-family: var(--font-ui); font-weight: 800; font-size: var(--step-3);
  letter-spacing: -0.02em; line-height: 1.1;
}
.donut__caption { font-size: var(--step--1); color: var(--ink-secondary); margin-top: 2px; }
.donut__key { margin-top: 0; }

@media (max-width: 720px) {
  .donut { grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
  .donut__ring { max-width: 200px; margin-inline: auto; }
}


/* The rail lies down above the content once there is no room for a
   232px column beside it. These override the base grid above, so they
   have to come after it in the file.

   Lying down, an entry is a chip: label and count on one line, the note
   dropped. On the archive that is the component chip row this rail replaced
   on wide screens, which is the right shape for a phone and was only ever
   the wrong one for a 1440px page with a column of empty margin beside it. */
@media (max-width: 1080px) {
  .rail-shell { grid-template-columns: minmax(0, 1fr); }
  .rail { position: static; padding: var(--space-4); }
  .rail__list { flex-direction: row; flex-wrap: wrap; margin-top: var(--space-3); }
  .rail__link { padding: var(--space-2) var(--space-4); }
  .rail__note, .rail__foot { display: none; }
}


/* ---- SACCO profile --------------------------------------------------------
   The leaderboard's Read more opens a page about one SACCO, laid out the
   way a profile is: a colour band, the SACCO's mark overlapping it, the
   name and the place beside the mark, its figures in a rail down the side.

   The mark is a logo where one has been filed and the parish's initials
   where one has not, so the shape of the page does not change with the
   data -- there is no empty circle and no stand-in photograph. */

/* The plane is white and the band is the reference's own teal, both taken
   off the image with a colour picker rather than matched by eye: the band
   averages #20706F across the reference (--profile-band), and every pixel
   of the page behind it is #FFFFFF. The dark edge visible in the second
   copy of that reference is the screenshot's own frame -- eight pixels of
   it, and #262626 on one side against #000000 on the other -- not a plane
   the page ever had.

   The band is held inside the shell with its top corners rounded, at the
   client's instruction, rather than run to the window's edges the way the
   reference does. `--surface-page` is redefined on this wrapper alone, a
   page-scoped override; nothing outside this page moves. */
.sacco-page {
  --surface-page: #FFFFFF;
  background: var(--surface-page);
  /* The site footer carries a top margin, which on a white page shows as a
     strip of the site's beige plane between the two. The page absorbs it:
     grows by that much, pulls the footer back up the same amount. */
  padding-bottom: calc(var(--space-9) + var(--space-7));
  margin-bottom: calc(-1 * var(--space-7));
}
.sacco-page__crumb { padding-block: var(--space-4); }

/* The band's height and the mark's overlap are proportions read off the
   reference, not numbers invented here: there the band is 41px against a
   145px mark -- a little over a quarter of it -- and the mark's white ring
   stops 7px short of the top edge rather than touching it, leaving a thin
   line of the band above the circle. */
.profile-band { height: 40px; background: var(--profile-band); }
/* The band is wider than the column beneath it: it runs to the window's
   edges while the content keeps the shell's margin, so the mark and the
   name begin inside the colour rather than flush with it. At the
   reference's own width that margin computes to 28px against its 27px, so
   the shell's padding is the whole of it and this rule adds nothing. */
.profile-body { padding: 0; }
.profile__head {
  display: flex; align-items: flex-end; flex-wrap: wrap;
  gap: var(--space-5); padding-bottom: var(--space-6);
}
.profile__mark {
  width: 140px; height: 140px; border-radius: 50%; flex-shrink: 0;
  margin-top: -36px; object-fit: cover;
  border: 5px solid var(--surface-raised);
  background: var(--surface-sunken);
}
.profile__mark--initials {
  display: flex; align-items: center; justify-content: center;
  background: var(--profile-mark);
  font-family: var(--font-display); font-weight: 800;
  font-size: var(--step-6); letter-spacing: 0.02em; color: var(--ink-inverse);
}
.profile__ident { flex: 1 1 15rem; min-width: 0; padding-top: var(--space-4); }
.profile__actions {
  display: flex; align-items: center; gap: var(--space-4);
  margin-left: auto; padding-top: var(--space-4);
}
.profile__rank { display: flex; align-items: center; gap: var(--space-3); }
.profile__rank-note { font-size: var(--step--1); color: var(--ink-secondary); line-height: 1.3; }

/* Each tab is an address, so they are links with an underline that marks
   the current one -- not buttons holding state the URL cannot see. */
.profile-tabs {
  display: flex; flex-wrap: wrap; gap: var(--space-5);
  margin-top: var(--space-5); border-bottom: 1px solid var(--line-strong);
}
.profile-tab {
  padding: var(--space-3) 0; margin-bottom: -1px;
  font-weight: 700; font-size: var(--step-1); color: var(--ink-secondary);
  border-bottom: 3px solid transparent;
}
.profile-tab:hover { color: var(--ink-primary); text-decoration: none; }
.profile-tab.is-current { color: var(--brand-primary); border-bottom-color: var(--brand-primary); }
.profile-tab__count {
  display: inline-block; min-width: 20px; padding: 0 6px; margin-left: 4px;
  border-radius: var(--radius-pill); background: var(--surface-wash);
  font-size: var(--step--1); color: var(--ink-secondary); text-align: center;
}

/* An insight is computed from the leaderboard beside it, never asserted,
   so every card carries the derived marker in its corner. */
.insight {
  position: relative; padding: var(--space-5);
  background: var(--surface-raised);
  border: 1px solid var(--line-hairline);
  border-radius: var(--radius-lg);
}
.insight__icon {
  display: inline-flex; width: 32px; height: 32px; border-radius: 9px;
  align-items: center; justify-content: center;
  background: var(--brand-primary-wash); color: var(--brand-primary);
}
.insight__icon svg { width: 18px; height: 18px; display: block; }
.insight__title { font-weight: 800; font-size: var(--step-1); margin-top: var(--space-3); }
.insight__note { font-size: var(--step--1); color: var(--ink-secondary); margin-top: var(--space-2); }
.insight__prov { position: absolute; top: var(--space-5); right: var(--space-5); }

/* The record itself. A row with no value is not drawn, so the list is
   always as long as the SACCO's return and no longer. */
.facts { margin-top: var(--space-4); }
.facts__row {
  display: grid; grid-template-columns: minmax(0, 12rem) minmax(0, 1fr);
  gap: var(--space-4); padding: var(--space-3) 0;
  border-bottom: 1px solid var(--line-soft);
}
.facts__row:last-child { border-bottom: 0; }
.facts__term { font-size: var(--step-0); font-weight: 600; color: var(--ink-secondary); }
.facts__value { font-size: var(--step-1); font-weight: 700; }
@media (max-width: 560px) {
  .facts__row { grid-template-columns: minmax(0, 1fr); gap: 2px; }
}

/* The next few meeting dates, counted forward from today. */
.meet-dates { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-2); }
.meet-date {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: var(--space-3) var(--space-2);
  background: var(--surface-raised);
  border: 1px solid var(--line-strong); border-radius: var(--radius-md);
}
.meet-date__dow {
  font-size: var(--step--1); font-weight: 700; letter-spacing: 0.04em;
  color: var(--ink-secondary);
}
.meet-date__day {
  font-family: var(--font-display); font-weight: 800;
  font-size: var(--step-3); line-height: 1;
}
.meet-date__mon { font-size: var(--step--1); color: var(--ink-secondary); }

.stack-tight > * + * { margin-top: var(--space-3); }

/* Back to the list this record came from, filter and all. */
.link-back { font-size: var(--step-0); font-weight: 700; color: var(--ink-secondary); }
.link-back::before { content: "\2190"; margin-right: 6px; }
.link-back:hover { color: var(--brand-primary); }

/* A link that inherits the type around it: a SACCO's name on a leaderboard
   card is a heading first and a link second. */
.plain-link { color: inherit; }
.plain-link:hover { color: var(--brand-primary); }
.row--link { text-decoration: none; }

/* On a phone the header stacks: the mark keeps its overlap of the band and
   the name sits beneath it. Left as a row, the short mark aligned to the
   bottom of a title that had wrapped to three lines, which read as the
   circle having slipped down the page. */
@media (max-width: 720px) {
  .profile__head {
    flex-direction: column; align-items: flex-start;
    gap: var(--space-3); padding-bottom: var(--space-5);
  }
  .profile__mark { width: 104px; height: 104px; margin-top: -36px; }
  /* The 15rem flex-basis is a width in the row layout and would become a
     240px height here, opening a gap under the name. */
  .profile__ident { flex: 0 0 auto; padding-top: 0; }
  .profile__actions { margin-left: 0; padding-top: var(--space-2); }
}

/* ---- The reference's own look, duplicated ---------------------------------
   The client asked for the example reproduced, not interpreted, so this page
   takes the reference's type and accent rather than the portal's. Every value
   below is sampled from that image, not chosen:

     ink        near-black; the darkest pixels in its headings are #0B–#17
     accent     its own teal -- since replaced by the logo's, see below
     cards      a 1px #E4E4E4 hairline, square-ish corners, and no shadow
                at all -- the reference lifts nothing off the page

   It is all scoped to `.sacco-page` and all of it rides on tokens, so the
   portal's serif display face and its maroon simply do not reach this page
   while every other page keeps them. Deleting this block restores the house
   style with no other edit.

   Worth saying plainly: this page no longer looks like the rest of the site.
   That is the instruction, not an accident. */
.sacco-page {
  --font-display: var(--font-ui);
  --ink-primary: #0F1115;
  --ink-secondary: #4A5257;
  --ink-muted: #737B80;
  /* The reference's whole page is 1071px across. On the portal's 1440px
     shell the same content spread to fill a wide screen and read as a much
     larger page than the example, whatever the type was doing. The band
     stays full-bleed -- it sits outside the shell -- so only the measure
     narrows, which is what the reference does too. */
  --shell-max: 1080px;
  /* The accent is the PDM logo's teal, not the reference's: #1F8B85 taken
     off assets/pdm-logo.png and stepped down until it carries text. The
     logo ink itself is only 4.13:1 on white, which fails AA for body-sized
     type, so links and the current tab take it at 78% (#186C68, 6.17:1)
     and the hover at 66% (#145C58, 7.80:1). Same hue, readable. */
  --brand-primary: #186C68;
  --brand-primary-ink: #145C58;
  /* The wash behind the small icons is the maroon's tint site-wide, which
     on this page put pink chips under teal glyphs. This is the logo teal
     at a 90% tint. */
  --brand-primary-wash: #E9F3F3;
  /* The share meters are drawn with this token from sacco.js. */
  --kpi-teal: #186C68;
  /* The enterprise mix is a single-series bar chart, so its hue carries no
     distinction between categories and can follow the page; the validated
     adjacent-pair work in README § Design system is about the categorical
     palettes, which this page does not use. The logo teal at 78% clears
     6.17:1 on white, well past the 3:1 a graphic needs. */
  --viz-series: #186C68;
  --line-hairline: #E4E4E4;
  --line-soft: #EDEDED;
  --line-strong: #E4E4E4;
  --focus-ring: 0 0 0 3px rgba(13, 102, 96, 0.28);
}
/* The display face carried the weight; the UI face has to be asked for it. */
.sacco-page .display,
.sacco-page .page-title,
.sacco-page .section-title { font-weight: 700; letter-spacing: -0.01em; }
.sacco-page .card,
.sacco-page .panel {
  border-radius: var(--radius-lg);
  box-shadow: none;
}
/* The call to action is brighter than the accent, the way the reference's
   is against its band: the logo teal at 85%, where white text on it still
   clears 5.41:1. */
.sacco-page .btn--primary { background: #1A7671; }
.sacco-page .btn--primary:hover { background: #186C68; }
/* Its tab counter is a filled dark pill, not the portal's grey one. */
.sacco-page .profile-tab__count {
  background: #1C2024; color: #FFFFFF; font-weight: 700;
}

/* The heading scale is the other way round in the reference, and this was
   what kept the page from reading like it however close the colours got:
   the headings down the left column are SMALLER than the portal's (cap
   height ~12px against the section title's 22px, so about 17px), and the
   headings on the rail cards are LARGER (cap ~14px, about 19px). The
   portal's own scale had those two the wrong way about, 22 against 14, so
   the left column shouted and the rail whispered. */
.sacco-page .section-title { font-size: 1.0625rem; font-weight: 700; }
.sacco-page .panel__title { font-size: var(--step-3); font-weight: 700; }

/* Built like a National Dashboard KPI card, because that is the page this
   one is asked to sit beside: the pictogram in a solid filled circle with
   a white glyph on its own line, the title under it, the note under that.

   It was laid out as a row before, with the icon beside the title. That
   only held while a title was short enough to fit: "Savings above the
   listed median" wrapped and pushed itself under the circle, so no two
   cards in the grid started their text at the same height. A stack cannot
   go ragged that way, and it is what the dashboard does anyway.

   The dashboard gives each card its own hue out of six. The logo holds
   two, so these alternate between them -- the same family of tiles, and
   the hue carries nothing either way, since every card states its own
   title directly beneath the circle. */
.sacco-page .insight {
  display: block;
  /* The provenance mark sits in the top-right corner: the text stops short
     of it rather than running underneath. */
  padding: var(--space-5) var(--space-8) var(--space-5) var(--space-5);
}
.sacco-page .insight__icon {
  width: 34px; height: 34px; border-radius: 50%;
  color: var(--ink-inverse);
}
.sacco-page .insight__icon svg { width: 17px; height: 17px; }
.sacco-page .insight:nth-child(odd) .insight__icon { background: #1F8B85; }
.sacco-page .insight:nth-child(even) .insight__icon { background: #1B8A4F; }
.sacco-page .insight__title {
  margin-top: var(--space-4); font-size: var(--step-1);
  color: var(--brand-primary);
}
.sacco-page .insight__note { margin-top: var(--space-2); }
.sacco-page .insight__prov { top: var(--space-5); right: var(--space-5); }
/* The reference fits two of these side by side in a column this wide -- its
   cards are about 235px. The portal's 260px floor made them break to one
   per row at the same width, which read as a much heavier page. */
.sacco-page .grid--260 {
  grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr));
}

/* The channel between the two columns is about a tenth of the content width
   in the reference and a fixed 32px here, which is most of what was left of
   the difference in how crowded the two pages feel. */
.sacco-page .split { gap: clamp(var(--space-7), 6vw, 5rem); }

/* The reference's headline pair, wearing the dashboard's tile: the figure
   at a size you read before the label, the label small and grey beneath
   it, and the icon in a solid filled circle with a white glyph -- the same
   38px `.kpi__icon` treatment the National Dashboard uses, so the two
   pages read as one site. Two abreast on the rail, and one above the other
   once the rail is too narrow to hold a currency figure on one line. */
.sacco-stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: var(--space-4); margin-top: var(--space-5);
}
.sacco-stat { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
.sacco-stat__icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 50%; flex-shrink: 0;
  color: var(--ink-inverse);
}
.sacco-stat__icon svg { width: 19px; height: 19px; display: block; }
/* The two fills are the logo's own two inks -- its teal for the membership
   figure, its green for the money -- each taken as deep as it needs to go
   for a white pictogram to clear 4:1 on it. The teal is the ink itself at
   4.13:1; the green needs 85% to reach 4.39:1. The hues are decorative:
   each tile sits beside its own written label. */
.sacco-stat__icon--people { background: #1F8B85; }
.sacco-stat__icon--money  { background: #1B8A4F; }
.sacco-stat__value {
  display: block; font-size: var(--step-2); font-weight: 800; line-height: 1.15;
}
.sacco-stat__label {
  display: block; font-size: var(--step--1); color: var(--ink-secondary);
  margin-top: 2px;
}

/* ---------- Home, layout B ----------------------------------------------------
 *
 * The four rules layout B needs beyond what layout A already styles: the
 * quick-link cards, a leaderboard row that is a link to the SACCO profile,
 * a field update that can carry a thumbnail, and the calendar strip that
 * closes the page.
 * ------------------------------------------------------------------------- */

.quick-card { display: flex; gap: var(--space-4); align-items: flex-start; }
.quick-card__icon { width: 26px; height: 26px; flex-shrink: 0; display: block; }
.quick-card__icon svg { width: 100%; height: 100%; display: block; }
.quick-card__title { display: block; font-weight: 800; font-size: var(--step-1); line-height: 1.3; }
.quick-card__note { display: block; margin-top: 4px; line-height: 1.5; }

/* The ranked list is a navigation list here, so the whole row is the target
   and the padding belongs to the link rather than to the item around it. */
.ranklist__row--link { padding: 0; }
.ranklist__row--link > a {
  display: flex; align-items: center; gap: var(--space-3); width: 100%;
  padding: var(--space-3) var(--space-3); border-radius: var(--radius-md); color: inherit;
}
.ranklist__row--link > a:hover { background: var(--surface-hover); text-decoration: none; }

.wall-row { display: flex; gap: var(--space-4); align-items: center; padding: var(--space-4); }
.wall-row .media-frame { width: 84px; flex-shrink: 0; }

.next-up { padding: var(--space-4); }
.next-up__row {
  display: flex; gap: var(--space-4); align-items: center;
  padding-top: var(--space-3); margin-top: var(--space-3);
  border-top: 1px solid var(--line-soft);
}
.next-up__date {
  width: 58px; flex-shrink: 0; font-weight: 800; font-size: var(--step--1);
  color: var(--brand-primary); text-transform: uppercase; letter-spacing: 0.04em;
}

/* On a phone the ranked list's single-line name and its figures fight for
   34rem of row: the name loses and every SACCO reads "Nsangi Parish P…".
   Both are allowed to wrap instead, which costs a line and keeps the name. */
@media (max-width: 560px) {
  .ranklist__row--link .ranklist__name { white-space: normal; }
  .ranklist__row--link .ranklist__figures { max-width: 42%; }
  .ranklist__row--link .ranklist__note { white-space: normal; text-align: right; line-height: 1.35; }
}

/* A story published before its photograph arrived. Stated in a line rather
   than reserving the full picture height for something that is not there —
   see the note beside `awaitingPhoto` in pages/beneficiaries.js. */
.story-await {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  padding: var(--space-3) var(--space-4);
  background: var(--surface-wash);
  border-bottom: 1px solid var(--line-soft);
  font-size: var(--step--1); color: var(--ink-muted);
}
.story-await__icon { width: 15px; height: 15px; display: block; flex-shrink: 0; }
.story-await__icon svg { width: 100%; height: 100%; display: block; }

/* The year on a calendar entry, shown only where a bare day and month
   would be ambiguous — an event that has rolled into next year. */
.event__year { font-size: 0.66rem; font-weight: 800; color: var(--ink-muted); letter-spacing: 0.04em; }

/* ---------- Onward links ------------------------------------------------------
 *
 * Several pages ended with nowhere to go: the reader finished PDMIS / FIS /
 * WENDI, the training centres, the results map or the loan terms and the
 * only route onward was back up to the menu. This is the strip that closes
 * those pages — two or three named destinations, not a second navigation.
 * ------------------------------------------------------------------------- */

.onward {
  margin-top: var(--space-8); padding-top: var(--space-5);
  border-top: 1px solid var(--line-soft);
}
.onward__label {
  font-size: var(--step--1); font-weight: 800; color: var(--ink-secondary);
  text-transform: uppercase; letter-spacing: 0.08em;
}
.onward__list {
  display: grid; gap: var(--space-4); margin-top: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
}
.onward__link {
  display: block; height: 100%; padding: var(--space-4) var(--space-5);
  background: var(--surface-raised); border: 1px solid var(--line-hairline);
  border-radius: var(--radius-lg); color: inherit;
  transition: border-color var(--dur-base) var(--ease), transform var(--dur-base) var(--ease);
}
.onward__link:hover {
  border-color: var(--brand-primary); transform: translateY(-2px); text-decoration: none;
}
.onward__title {
  display: block; font-weight: 800; font-size: var(--step-0); color: var(--brand-primary);
}
.onward__title::after { content: " →"; }
.onward__note {
  display: block; margin-top: 3px; font-size: var(--step--1);
  color: var(--ink-secondary); line-height: 1.45;
}

/* ---------- The Stories of Change archive, and one story ----------------------
 *
 * The archive stopped being a gallery of everything published and became a
 * directory that is read a page at a time (see pages/beneficiaries.js and
 * api/src/stories.js). Three things it needs that a gallery did not: a way
 * to say it is fetching, a row of districts to move between, and a pager.
 *
 * A story left the dialog it used to open in and took a page of its own, so
 * the rules that set a narrative — the column width, the pull-quote, the
 * facts beneath it — live here rather than inside `.dialog`.
 * --------------------------------------------------------------------------- */

/* Shown only by the two pages that fetch. A line of text, not a spinner:
   the wait is a query on the same host, and a spinner for 40ms reads as a
   fault rather than as progress. */
.loading {
  padding: var(--space-6) 0;
  font-size: var(--step-0); color: var(--ink-muted);
}

/* ---- District facets ---- */

.facets {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2) var(--space-3);
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--line-soft);
}
.facets__label {
  flex-shrink: 0;
  font-size: 0.625rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink-secondary);
}
.facets__chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }

/* The chips are anchors here, not buttons: each district is an address, so
   it can be opened in a new tab and sent to somebody. `.chip` carries
   aria-pressed styling for the button form; `is-on` is the same state for
   the link form. */
.facets .chip { padding: 5px var(--space-3); font-size: var(--step--1); }
.facets .chip:hover { text-decoration: none; }
.facets .chip.is-on {
  background: var(--brand-primary); border-color: var(--brand-primary); color: var(--ink-inverse);
}
.chip__count { font-weight: 800; opacity: 0.66; }

.facets__note {
  flex-basis: 100%;
  font-size: var(--step--1); color: var(--ink-muted);
}

/* ---- Pager ---- */

.pager {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: var(--space-3);
  margin-top: var(--space-7);
  padding-top: var(--space-5);
  border-top: 1px solid var(--line-soft);
}
.pager__step {
  font-weight: 800; font-size: var(--step-0); color: var(--brand-primary);
}
.pager__step.is-off { color: var(--ink-muted); opacity: 0.5; }
.pager__numbers { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.pager__no {
  min-width: 34px; height: 34px; padding: 0 6px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-md);
  font-size: var(--step--1); font-weight: 700; color: var(--ink-secondary);
}
.pager__no:hover { background: var(--surface-sunken); text-decoration: none; }
.pager__no.is-current {
  background: var(--brand-primary); color: var(--ink-inverse);
}
.pager__gap { color: var(--ink-muted); padding: 0 2px; }

/* On a phone the page numbers are the part that wraps badly, so the two
   steps take the row and the numbers centre beneath them. */
@media (max-width: 34rem) {
  .pager { justify-content: center; }
  .pager__numbers { order: 3; flex-basis: 100%; justify-content: center; }
}

/* ---- "Photographed only" ---- */

.field--check { display: flex; align-items: flex-end; }
.check {
  display: inline-flex; align-items: center; gap: 8px;
  padding-bottom: 9px;
  font-size: var(--step--1); font-weight: 700; color: var(--ink-secondary);
  cursor: pointer;
}
.check input { width: 16px; height: 16px; accent-color: var(--brand-primary); }

/* ---- The card's note that there is more behind it ---- */

.story-card__more {
  display: block; margin-top: var(--space-3);
  font-size: var(--step--1); font-weight: 800; color: var(--brand-primary);
}

/* ---- One story ---------------------------------------------------------------
 *
 * Redrawn on 2026-09-20 from a reference the client sent: a charity's
 * landing page, whose opener is a dark card with the photograph filling one
 * side of it, a strip of icon-and-label facts directly beneath, and a
 * generous radius on everything.
 *
 * Borrowed: that composition, and — after the client saw it in the footer's
 * navy and said the colour did not depict success and change — the
 * reference's deep green ground too. Ours is --surface-story: the PDM green
 * of the logo's D, which the sequential ramp is already built on because
 * green reads as growth in this palette. Not borrowed: the voice. The
 * reference's two call-to-action buttons have no honest equivalent on a page
 * that reports how public money was spent, and the accent on the green is
 * the flag gold that marks a section on every dark surface in this portal.
 *
 * Wider than the 880px this page used to hold, because the opener is a
 * two-column card now. The narrative keeps the measure — .prose-serif caps
 * it at 68ch, which is what makes it readable — so what got wider is the
 * page around it, not the line.
 */

.story-page { max-width: 1120px; margin-inline: auto; }
.story-page__crumb { margin-bottom: var(--space-4); }

/* ---- The opener ---- */

.story-hero {
  display: grid;
  grid-template-columns: minmax(0, 1.06fr) minmax(0, 1fr);
  background: var(--surface-story);
  border-radius: var(--radius-2xl);
  /* The photograph runs to the card's edge, so the card clips it to the
     corner rather than the image carrying a radius of its own. */
  overflow: hidden;
  box-shadow: var(--shadow-3);
}
/* Nine stories in eleven are published before their photograph arrives.
   With none there is no second column to fill, so the text takes the whole
   card and the absence is stated in a line — the same answer the archive's
   cards give, rather than half a card of grey.

   It is a banner rather than a card then: shallower, and the headline keeps
   a measure instead of running the full width. A title set across 1,000px
   of dark is not a headline, it is a stripe. */
.story-hero--unillustrated { grid-template-columns: minmax(0, 1fr); }
.story-hero--unillustrated .story-hero__text { padding-block: var(--space-7); }
.story-hero--unillustrated .story-hero__title { max-width: 26ch; }

.story-hero__text {
  align-self: center;
  padding: clamp(var(--space-6), 3vw, var(--space-8));
}
.story-hero__eyebrow {
  font-size: 0.6rem; font-weight: 800; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--brand-accent);
}
.story-hero__title {
  margin-top: var(--space-4);
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(1.75rem, 1.1rem + 1.9vw, 2.5rem); line-height: 1.12;
  color: #fff; text-wrap: balance;
}
/* The household's own sentence, and on most stories the whole of what was
   written down.

   The rule beside it took the component's own colour while the panel was
   navy. It cannot now the panel is green: component D — savings and credit,
   and the component most of the archive sits under — is #1F8A4C against a
   ground of #0E5F30, which is 1.8:1 and therefore no rule at all. The gold
   holds against the green at 5.3:1 whichever component the story belongs
   to. The component still has its colour on this page; it has it on the
   lettered disc in the record below, which sits on white, where all six
   read. */
.story-hero__quote {
  margin-top: var(--space-6);
  padding-left: var(--space-5);
  border-left: 3px solid var(--brand-accent);
  font-family: var(--font-display); font-size: var(--step-2); line-height: 1.6;
  color: rgba(255, 255, 255, 0.88); max-width: 46ch; text-wrap: pretty;
}
/* Both of the quiet lines on this panel are white at 0.7 rather than the
   0.55-ish the rail and the footer use for theirs. The green ground is a
   good deal lighter than the navy those sit on — 0.085 against 0.018 in
   relative luminance — so white dimmed that far came out at 3.8:1 on it,
   under what AA asks of text this small. */
/* The foot of the card: the byline at one end, and where there is no
   photograph the line that says so at the other. On a card that has its
   picture the byline is the only child and sits where it always did. */
.story-hero__foot {
  display: flex; flex-wrap: wrap; align-items: baseline;
  justify-content: space-between; gap: var(--space-3) var(--space-5);
  margin-top: var(--space-6);
}
.story-hero__byline {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2);
  font-size: var(--step-0); color: rgba(255, 255, 255, 0.7);
}
.story-hero__name { font-weight: 800; color: #fff; }
/* The separator belongs to the pair, not to either half: written into the
   markup it would survive the line breaking between them. */
.story-hero__name::after {
  content: "·"; margin-left: var(--space-2); color: rgba(255, 255, 255, 0.35);
}
.story-hero__await {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: var(--step--1); color: rgba(255, 255, 255, 0.7);
}

.story-hero__media {
  position: relative;
  min-height: 280px;
  background: rgba(255, 255, 255, 0.06);
}
.story-hero__media img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
}

/* Below this the second column is too narrow to be a photograph, so the
   card stacks and the picture leads, the way it does on a card in the
   archive. */
@media (max-width: 60rem) {
  .story-hero { grid-template-columns: minmax(0, 1fr); }
  .story-hero__media { order: -1; min-height: 0; height: clamp(200px, 52vw, 320px); }
}

/* ---- The record ----
   What was borrowed, under which strand of the pillar, and when it was
   published: the three facts a reader scans rather than reads. They were
   three columns of plain text under a rule. */

.story-record {
  display: flex; flex-wrap: wrap;
  margin-top: var(--space-6);
  background: var(--surface-raised);
  border: 1px solid var(--line-hairline);
  border-radius: var(--radius-2xl);
  overflow: hidden;
}
.story-record__item {
  flex: 1 1 13rem;
  display: flex; align-items: center; gap: var(--space-4);
  padding: var(--space-5);
  border-left: 1px solid var(--line-soft);
}
.story-record__item:first-child { border-left: 0; }
.story-record__icon {
  flex-shrink: 0;
  width: 40px; height: 40px; border-radius: var(--radius-lg);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface-sunken); color: var(--brand-primary);
}
.story-record__icon svg { width: 21px; height: 21px; display: block; }
/* The component's letter on a disc of its own colour — the colour that
   tints it in the archive's rail and on every card that carries it. This is
   the one place in the portal where a component hue carries text: at
   --step-3 and 800 the letter is large text by WCAG's definition, where the
   floor is 3:1, and the weakest of the six — component B's goldenrod — is
   3.25:1 against white. Nothing smaller is set on these colours. */
.story-record__icon--letter {
  background: var(--story-on, var(--brand-primary));
  color: #fff;
  font-family: var(--font-display); font-size: var(--step-3); font-weight: 800;
  line-height: 1;
}
.story-record dt {
  font-size: 0.625rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--ink-secondary);
}
.story-record dd {
  font-size: var(--step-2); font-weight: 800; margin-top: 3px; text-wrap: pretty;
}
.story-record .meter { margin-top: var(--space-2); }

/* One under another once three of them no longer fit across the page: the
   divider moves with them, from the left edge to the top. */
@media (max-width: 48rem) {
  .story-record__item {
    flex-basis: 100%;
    border-left: 0; border-top: 1px solid var(--line-soft);
  }
  .story-record__item:first-child { border-top: 0; }
}

/* ---- The narrative ----
   Two of the eleven published stories have one. It is the reason this is a
   page and not a card, so it is set a step above the .story-body the SACCO
   profile shares with it, and its opening paragraph a step above that. */

/* Centred under the full-width opener and the record. The measure is the
   same 68ch it has always been; what changed is that the page around it is
   1120px now, and a column of prose pinned to the left of that leaves a
   third of the page empty beside it. */
.story-narrative {
  max-width: 68ch; margin-inline: auto;
  margin-top: var(--space-8);
}
.story-narrative .eyebrow { display: block; margin-bottom: var(--space-4); }
.story-body--feature { font-size: var(--step-2); }
.story-body--feature > p:first-child { font-size: var(--step-3); line-height: 1.6; }

.story-article__consent { margin-top: var(--space-6); }

/* ---- Previous / next --------------------------------------------------------
 *
 * The point of a page over a dialog: a reader who has finished can go on
 * rather than only go back.
 */

.story-nav {
  display: grid; gap: var(--space-4);
  grid-template-columns: 1fr 1fr;
  margin-top: var(--space-7);
}
.story-nav__link {
  display: block; padding: var(--space-5) var(--space-6);
  background: var(--surface-raised); border: 1px solid var(--line-hairline);
  border-radius: var(--radius-2xl); color: inherit;
  transition: border-color var(--dur-base) var(--ease), transform var(--dur-base) var(--ease);
}
.story-nav__link:hover {
  border-color: var(--brand-primary); transform: translateY(-2px); text-decoration: none;
}
.story-nav__link--next { text-align: right; }
.story-nav__dir {
  display: block; font-size: var(--step--1); font-weight: 800; color: var(--brand-primary);
}
.story-nav__title {
  display: block; margin-top: 4px;
  font-family: var(--font-display); font-size: var(--step-1); font-weight: 800;
  line-height: 1.3; text-wrap: pretty;
}

@media (max-width: 40rem) {
  .story-nav { grid-template-columns: 1fr; }
  .story-nav__link--next { text-align: left; }
}

/* Printing a story is printing the narrative and the facts. The crumb, the
   two neighbours and the onward strip are already .no-print; what is left is
   the opener, which on paper is a headline, a quotation and a photograph
   rather than a dark card — a page-wide block of ink most office printers
   would put down as grey mud. */
@media print {
  .story-page { max-width: none; }
  .story-hero {
    display: block;
    background: none; box-shadow: none; border-radius: 0;
  }
  .story-hero__text { padding: 0 0 var(--space-5); }
  .story-hero__title, .story-hero__quote, .story-hero__name { color: #000; }
  .story-hero__eyebrow, .story-hero__byline { color: #555; }
  .story-hero__quote { border-left-color: #000; }
  .story-hero__media { height: 220px; min-height: 0; }
  .story-record { break-inside: avoid; }
}

/* Cards in the archive grid fill their row rather than each finding its own
   height. It shows up here more than elsewhere because a story waiting for
   its photograph is 160px shorter than one that has it, so a mixed row was
   visibly ragged. */
.grid--260 > li { display: flex; }
.grid--260 > li > .card { flex: 1; display: flex; flex-direction: column; }
.grid--260 > li > .card > .card__body { flex: 1; }

/* ---------- Home: the video band -----------------------------------
   The film no longer shares its row with the story rows, and a 16:9
   frame across the whole shell is 770px tall — taller than the map
   above it. Held to a reading width and centred under its own head. */
.video-band { max-width: min(100%, 52rem); margin-inline: auto; }

/* =============================================================
   Home layout C — the finder-led composition
   ============================================================= */

/* ---------- The finder ------------------------------------------
   The card straddles the hero's lower edge, exactly as the stat strip
   does in layouts A and B. Only one of them can hold that overlap, so
   where the finder is carried the figures drop into normal flow below
   it (.finder-stats). */
.finder-shell { position: relative; z-index: 1; margin-top: calc(-1 * var(--space-8)); }
@media (max-width: 48rem) { .finder-shell { margin-top: var(--space-5); } }

.finder {
  background: var(--surface-raised);
  border: 1px solid var(--line-hairline);
  border-radius: var(--radius-2xl);
  box-shadow: var(--shadow-4);
  padding: var(--space-5) var(--space-6) var(--space-5);
}
.finder__heading {
  font-family: var(--font-display); font-weight: 600;
  font-size: var(--step-3); line-height: 1.25;
  margin-bottom: var(--space-4);
}
.finder__fields { display: grid; gap: var(--space-4); align-items: end; }
@media (min-width: 46rem) {
  .finder__fields { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1.4fr) auto; }
}
.finder__field { min-width: 0; }
.finder__go { width: 100%; justify-content: center; }
@media (min-width: 46rem) { .finder__go { width: auto; } }
.finder__note {
  margin-top: var(--space-4); padding-top: var(--space-4);
  border-top: 1px solid var(--line-soft);
  font-size: var(--step--1); line-height: 1.55; color: var(--ink-secondary);
  max-width: 96ch;
}

/* Layout D's variant: the reference's search bar carries no heading of its
   own, so the accessible name stays and the text steps out of the way. */
.finder--wide .finder__heading {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
.finder--wide { padding-block: var(--space-4); }

/* Where the finder holds the overlap, the figures sit in ordinary flow. */
.finder-stats .hero-stats { margin-top: var(--space-7); }

/* ---------- The component row ------------------------------------ */
.comp-row { display: grid; gap: var(--space-3); }
@media (min-width: 34rem) { .comp-row { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 52rem) { .comp-row { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 76rem) { .comp-row { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
.comp-row > li { display: flex; }

.comp-chip {
  flex: 1; display: flex; align-items: center; gap: var(--space-3);
  min-width: 0; padding: var(--space-3) var(--space-4);
  background: var(--surface-raised);
  border: 1px solid var(--line-hairline);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
  color: inherit;
  transition: transform var(--dur-base) var(--ease), box-shadow var(--dur-base) var(--ease);
}
.comp-chip:hover { transform: translateY(-2px); box-shadow: var(--shadow-3); text-decoration: none; }
.comp-chip__letter {
  flex: none; width: 34px; height: 34px; border-radius: var(--radius-md);
  display: grid; place-items: center;
  color: var(--ink-inverse); font-weight: 800; font-size: var(--step-2);
}
.comp-chip__body { min-width: 0; }
.comp-chip__name {
  display: block; font-weight: 800; font-size: var(--step-0); line-height: 1.3;
  text-wrap: pretty;
}
.comp-chip__note { display: block; margin-top: 2px; font-size: var(--step--1); color: var(--ink-secondary); }

/* ---------- What the pillar delivers ------------------------------ */
.deliver {
  background: var(--surface-sunken);
  border-radius: var(--radius-2xl);
  padding: var(--space-7) var(--space-6);
}
.deliver__head { max-width: 62ch; margin-bottom: var(--space-6); }
.deliver__head .lede { margin-top: var(--space-2); }
.deliver__grid { display: grid; gap: var(--space-5) var(--space-6); }
@media (min-width: 40rem) { .deliver__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 64rem) { .deliver__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.deliver__item { border-top: 2px solid var(--brand-accent); }
.deliver__link { display: block; padding-top: var(--space-4); color: inherit; }
.deliver__link:hover { text-decoration: none; }
.deliver__link:hover .deliver__name { text-decoration: underline; }
.deliver__icon { display: block; width: 28px; height: 28px; margin-bottom: var(--space-3); }
.deliver__icon svg { width: 100%; height: 100%; display: block; }
.deliver__name {
  display: block; font-family: var(--font-display); font-weight: 600; font-size: var(--step-3);
}
.deliver__text {
  display: block; margin-top: var(--space-2);
  font-size: var(--step-0); line-height: 1.55; color: var(--ink-secondary);
}

/* =============================================================
   Home layout D — the reference layout, transposed
   Every selector here is prefixed hv- and is used by pages/home-d.js
   alone, so the four compositions cannot interfere with one another.
   ============================================================= */

/* ---------- The utility bar --------------------------------------- */
.hv-top {
  background: var(--surface-dark);
  color: rgba(255, 255, 255, 0.82);
  font-size: var(--step--1);
}
.hv-top__inner {
  display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-5);
  align-items: center; justify-content: space-between;
  padding-block: var(--space-2);
}
.hv-top__facts { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-5); }
.hv-top__fact { display: inline-flex; align-items: center; gap: var(--space-2); }
.hv-top__fact + .hv-top__fact::before {
  content: ""; width: 3px; height: 3px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.4); margin-right: var(--space-3);
}
.hv-top__follow { display: inline-flex; align-items: center; gap: var(--space-3); }
.hv-top__follow a {
  display: inline-flex; align-items: center; gap: 6px;
  color: #fff; text-decoration: none; font-weight: 700;
}
.hv-top__follow a:hover { text-decoration: underline; }
.hv-top__follow svg { color: #FF0033; }

/* ---------- The hero ----------------------------------------------
   Copy on the left, the photographs in a frame on the right — the
   reference's arrangement. The slides, the dots and the caption are the
   hooks home.js's `mount` already drives. */
.hv-hero {
  background: linear-gradient(160deg, var(--brand-primary-wash) 0%, var(--surface-page) 62%);
  padding-block: clamp(2rem, 1rem + 4vw, 3.5rem) clamp(3rem, 2rem + 5vw, 4.5rem);
}
.hv-hero__inner { display: grid; gap: var(--space-7); align-items: center; }
@media (min-width: 62rem) {
  .hv-hero__inner { grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); gap: var(--space-9); }
}
.hv-hero__copy { min-width: 0; }
.hv-hero__title {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(1.9rem, 1.2rem + 3vw, 3rem); line-height: 1.1;
  text-wrap: balance;
}
.hv-hero__title-accent { color: var(--brand-primary); }
.hv-hero__lede {
  margin-top: var(--space-4);
  font-size: var(--step-2); line-height: 1.6;
  color: var(--ink-secondary); max-width: 46ch;
}
.hv-hero__actions { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-top: var(--space-6); }

/* The reference's avatar stack and its line of social proof, counting
   published stories instead. */
.hv-proof {
  display: inline-flex; align-items: center; gap: var(--space-4);
  margin-top: var(--space-7); color: inherit;
}
.hv-proof:hover { text-decoration: none; }
.hv-proof:hover .hv-proof__text { text-decoration: underline; }
.hv-proof__faces { display: inline-flex; }
.hv-proof__faces img,
.hv-proof__more {
  width: 36px; height: 36px; border-radius: 50%;
  border: 2px solid var(--surface-page); object-fit: cover;
}
.hv-proof__faces img + img,
.hv-proof__more { margin-left: -12px; }
.hv-proof__more {
  display: grid; place-items: center;
  background: var(--brand-primary); color: var(--ink-inverse);
  font-weight: 800; font-size: var(--step-1);
}
.hv-proof__text { font-size: var(--step-0); color: var(--ink-secondary); max-width: 34ch; line-height: 1.45; }

.hv-hero__media {
  position: relative; overflow: hidden;
  height: clamp(300px, 40vw, 440px);
  border-radius: var(--radius-2xl);
  box-shadow: var(--shadow-4);
  background: var(--surface-wash);
}
.hv-hero__slide {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transition: opacity var(--dur-slow) var(--ease);
}
.hv-hero__slide.is-active { opacity: 1; }
/* The scrim the caption and the dots sit on. */
.hv-hero__media::after {
  content: ""; position: absolute; inset: auto 0 0 0; height: 46%;
  background: linear-gradient(180deg, rgba(20, 4, 6, 0) 0%, rgba(20, 4, 6, 0.78) 100%);
  pointer-events: none;
}

/* The reference floats the listing price here; this is the one figure the
   programme is measured by. */
.hv-hero__card {
  position: absolute; top: var(--space-5); left: var(--space-5); z-index: 1;
  display: flex; align-items: center; gap: var(--space-3);
  max-width: min(17rem, calc(100% - 2 * var(--space-5)));
  padding: var(--space-3) var(--space-4);
  background: var(--surface-raised);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-4);
}
.hv-hero__card-icon {
  flex: none; width: 38px; height: 38px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--brand-primary-wash); color: var(--brand-primary);
}
.hv-hero__card-icon svg { width: 21px; height: 21px; display: block; }
.hv-hero__card-label {
  display: block; font-size: 0.66rem; font-weight: 800;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-secondary);
}
.hv-hero__card-value {
  display: block; font-family: var(--font-display); font-weight: 800;
  font-size: var(--step-4); line-height: 1.1; color: var(--brand-primary);
}
.hv-hero__card-note { display: block; font-size: var(--step--1); color: var(--ink-secondary); }

.hv-hero__caption {
  position: absolute; z-index: 1;
  left: var(--space-5); right: calc(var(--space-5) + 84px); bottom: var(--space-5);
  color: rgba(255, 255, 255, 0.94);
  font-size: var(--step--1); line-height: 1.45;
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.4);
}
.hv-hero__cap { display: none; }
.hv-hero__cap.is-active { display: block; }
.hv-hero__dots {
  position: absolute; z-index: 1;
  right: var(--space-5); bottom: calc(var(--space-5) + 3px);
  display: flex; gap: 7px;
}
@media (max-width: 40rem) {
  .hv-hero__caption { right: var(--space-5); bottom: calc(var(--space-5) + 22px); }
  .hv-hero__dots { bottom: var(--space-4); }
}

/* ---------- The search card --------------------------------------- */
.hv-search-shell { position: relative; z-index: 2; margin-top: calc(-1 * var(--space-8)); }
@media (max-width: 62rem) { .hv-search-shell { margin-top: var(--space-5); } }

/* ---------- The counted chip row ---------------------------------- */
.hv-types { display: grid; gap: var(--space-3); }
@media (min-width: 34rem) { .hv-types { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 52rem) { .hv-types { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 76rem) { .hv-types { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
.hv-types > li { display: flex; }
.hv-type {
  flex: 1; display: flex; align-items: center; gap: var(--space-3);
  min-width: 0; padding: var(--space-4);
  background: var(--surface-raised);
  border: 1px solid var(--line-hairline);
  border-radius: var(--radius-lg);
  color: inherit;
  transition: transform var(--dur-base) var(--ease), box-shadow var(--dur-base) var(--ease);
}
.hv-type:hover { transform: translateY(-2px); box-shadow: var(--shadow-3); text-decoration: none; }
.hv-type__letter {
  flex: none; width: 38px; height: 38px; border-radius: var(--radius-md);
  display: grid; place-items: center;
  color: var(--ink-inverse); font-weight: 800; font-size: var(--step-3);
}
.hv-type__body { min-width: 0; }
.hv-type__name { display: block; font-weight: 800; font-size: var(--step-0); line-height: 1.3; text-wrap: pretty; }
.hv-type__count { display: block; margin-top: 2px; font-size: var(--step--1); color: var(--ink-secondary); }

/* ---------- The card rails ----------------------------------------
   Ordinary overflow scrollers: they swipe on a phone and take the
   keyboard anywhere. The arrows are a second way to do what the
   scrollbar already does, and pages/home.js hides one whenever its
   track has nothing left to scroll.

   Shared, not layout D's: the served home page carries the story rail
   too, which is why these are not hv- prefixed like the bands below. */
.card-rail { position: relative; }
.card-rail__track {
  display: flex; gap: var(--space-4);
  overflow-x: auto; scroll-snap-type: x proximity;
  padding-block: var(--space-1) var(--space-4);
  -webkit-overflow-scrolling: touch;
}
.card-rail__track > li { scroll-snap-align: start; flex: 0 0 clamp(236px, 74vw, 272px); }
/* The wide rail holds three cards, not five: where the row has room for
   all three they share it, as the reference does, and where it has not
   they scroll like any other rail. */
.card-rail__track--wide > li { flex: 1 1 268px; min-width: min(268px, 82vw); }
.card-rail__arrow {
  position: absolute; top: 40%; right: calc(-1 * var(--space-3));
  width: 40px; height: 40px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--surface-raised); color: var(--ink-primary);
  border: 1px solid var(--line-hairline); box-shadow: var(--shadow-3);
  font-size: var(--step-4); line-height: 1;
}
.card-rail__arrow:hover { background: var(--surface-hover); }
.card-rail--quiet .card-rail__arrow { display: none; }
.card-rail__arrows { display: inline-flex; gap: var(--space-2); }
/* The arrows set [hidden] on themselves when their rail has no overflow;
   display:grid on .card-rail__arrow would otherwise win over it. */
.card-rail__arrow[hidden] { display: none; }
.card-rail__arrow--sm {
  position: static; width: 34px; height: 34px; font-size: var(--step-2);
  box-shadow: var(--shadow-1);
}
@media (max-width: 52rem) { .card-rail > .card-rail__arrow { display: none; } }

/* ---------- The story card that rides the rail --------------------
   Drawn for layout D as the transposition of the reference's property
   card — a corner badge, the photograph, the title, the place, the loan
   in the brand colour and a three-fact foot — and kept when the served
   home page took the rail on. */
.rail-card {
  background: var(--surface-raised);
  border: 1px solid var(--line-hairline);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-1);
  overflow: hidden;
  transition: transform var(--dur-base) var(--ease), box-shadow var(--dur-base) var(--ease);
}
.rail-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-4); }
.rail-card > a { display: block; color: inherit; }
.rail-card > a:hover { text-decoration: none; }
.rail-card__media { position: relative; display: block; }
.rail-card__badge {
  position: absolute; top: var(--space-3); left: var(--space-3);
  padding: 4px var(--space-3); border-radius: var(--radius-pill);
  color: var(--ink-inverse); font-size: 0.625rem; font-weight: 800;
  letter-spacing: 0.04em;
}
.rail-card__body { display: block; padding: var(--space-4); }
.rail-card__title {
  display: block; font-family: var(--font-display); font-weight: 600;
  font-size: var(--step-2); line-height: 1.3; text-wrap: pretty;
}
.rail-card__place { display: block; margin-top: 4px; font-size: var(--step--1); color: var(--ink-secondary); }
.rail-card__price {
  display: block; margin-top: var(--space-3);
  font-weight: 800; font-size: var(--step-3); color: var(--brand-primary);
}
.rail-card__price-unit { font-size: var(--step--1); font-weight: 700; color: var(--ink-secondary); }
.rail-card__facts {
  display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4);
  margin-top: var(--space-3); padding-top: var(--space-3);
  border-top: 1px solid var(--line-soft);
  font-size: var(--step--1); color: var(--ink-secondary);
}
.rail-card__fact { display: inline-flex; align-items: center; min-width: 0; }

/* ---------- "Why choose us" ---------------------------------------- */
.hv-why {
  background: var(--surface-sunken);
  border-radius: var(--radius-2xl);
  padding: var(--space-7) var(--space-6);
}
.hv-why__grid { display: grid; gap: var(--space-5) var(--space-4); margin-top: var(--space-6); }
@media (min-width: 40rem) { .hv-why__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 64rem) { .hv-why__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.hv-why__item { min-width: 0; }
.hv-why__item + .hv-why__item { border-left: 1px solid var(--line-strong); padding-left: var(--space-5); }
@media (max-width: 63.99rem) { .hv-why__item + .hv-why__item { border-left: 0; padding-left: 0; } }
.hv-why__item > a { display: flex; gap: var(--space-4); align-items: flex-start; color: inherit; }
.hv-why__item > a:hover { text-decoration: none; }
.hv-why__item > a:hover .hv-why__name { text-decoration: underline; }
.hv-why__icon {
  flex: none; width: 46px; height: 46px; border-radius: 50%;
  display: grid; place-items: center;
  border: 1.5px solid var(--brand-primary); color: var(--brand-primary);
  background: var(--surface-raised);
}
.hv-why__icon svg { width: 22px; height: 22px; display: block; }
.hv-why__name { display: block; font-weight: 800; font-size: var(--step-1); }
.hv-why__text {
  display: block; margin-top: 4px;
  font-size: var(--step-0); line-height: 1.5; color: var(--ink-secondary);
}

/* ---------- The SACCO cards (the reference's testimonials) --------- */
.hv-voice {
  display: flex;
  background: var(--surface-raised);
  border: 1px solid var(--line-hairline);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-1);
  transition: transform var(--dur-base) var(--ease), box-shadow var(--dur-base) var(--ease);
}
.hv-voice:hover { transform: translateY(-2px); box-shadow: var(--shadow-3); }
.hv-voice > a {
  flex: 1; display: flex; flex-direction: column; justify-content: space-between;
  gap: var(--space-4); padding: var(--space-5); color: inherit;
}
.hv-voice > a:hover { text-decoration: none; }
.hv-voice__quote-mark { display: block; width: 24px; height: 24px; color: var(--brand-accent-ink); }
.hv-voice__quote-mark svg { width: 100%; height: 100%; display: block; }
.hv-voice__quote {
  display: block; font-size: var(--step-1); line-height: 1.6; text-wrap: pretty;
}
.hv-voice__foot { display: flex; align-items: center; gap: var(--space-3); }
.hv-voice__mark {
  flex: none; width: 40px; height: 40px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--profile-mark); color: var(--ink-inverse);
  font-weight: 800; font-size: var(--step-1);
}
.hv-voice__who { flex: 1; min-width: 0; }
.hv-voice__name { display: block; font-weight: 800; font-size: var(--step-0); line-height: 1.3; }
.hv-voice__place { display: block; font-size: var(--step--1); color: var(--ink-secondary); }
.hv-voice__figure { flex: none; text-align: right; }
.hv-voice__figure b { display: block; font-size: var(--step-2); }
.hv-voice__figure-label { display: block; font-size: var(--step--1); color: var(--ink-secondary); }

/* ---------- The closing band (the reference's newsletter) ---------- */
.hv-cta {
  display: grid; gap: var(--space-5); align-items: center;
  background: var(--surface-dark); color: var(--ink-inverse);
  border-radius: var(--radius-2xl); overflow: hidden;
  padding: var(--space-6);
  margin-bottom: var(--space-8);
}
@media (min-width: 52rem) {
  .hv-cta { grid-template-columns: 220px minmax(0, 1fr) auto; gap: var(--space-7); padding: 0 var(--space-7) 0 0; }
}
.hv-cta__media {
  width: 100%; height: 160px; object-fit: cover;
  border-radius: var(--radius-lg);
}
@media (min-width: 52rem) { .hv-cta__media { height: 190px; border-radius: 0; } }
.hv-cta__body { min-width: 0; }
.hv-cta__title {
  font-family: var(--font-display); font-weight: 600;
  font-size: var(--step-4); line-height: 1.25; text-wrap: balance;
}
.hv-cta__text {
  margin-top: var(--space-3);
  font-size: var(--step-0); line-height: 1.6;
  color: rgba(255, 255, 255, 0.82); max-width: 70ch;
}
.hv-cta__actions { display: flex; flex-wrap: wrap; gap: var(--space-3); }
.hv-cta :focus-visible { outline-color: var(--brand-accent); }

/* A news item's region disc in Central gold takes dark ink. */
.story-record__icon--dark { color: var(--ink-primary); }

/* =====================================================================
   Latest News, as a magazine front (news.js). Redrawn on 2026-09-24 from
   a news-magazine template the client sent. Kickers and chips are the
   item's region in its logo colour; the banner and follow tiles use the
   portal's own brand colours, never a region's.
   ===================================================================== */

/* Trending bar */
.nx-ticker {
  display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap;
  margin-top: var(--space-5);
  padding: 10px var(--space-4);
  background: var(--surface-dark); color: rgba(255, 255, 255, 0.9);
  border-radius: var(--radius-lg);
  font-size: var(--step--1);
}
.nx-ticker__label {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 3px 10px; border-radius: var(--radius-pill);
  background: var(--brand-primary); color: #fff;
  font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; font-size: 0.6875rem;
}
.nx-ticker__label .live-dot { background: #fff; }
.nx-ticker__text { flex: 1 1 18rem; min-width: 0; font-weight: 600; }
.nx-ticker__when { color: rgba(255, 255, 255, 0.6); white-space: nowrap; }
.nx-ticker__follow { color: var(--brand-accent); font-weight: 700; text-decoration: none; white-space: nowrap; }
.nx-ticker__follow:hover { text-decoration: underline; }

/* Title and filter on one row */
.nx-head { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--space-4) var(--space-6); flex-wrap: wrap; }
.nx-head .page-head { margin-bottom: 0; }
.nx-filter { display: flex; gap: var(--space-3); align-items: flex-end; flex-wrap: wrap; }
.nx-filter .field { margin: 0; }

/* Shared bits */
.nx-chip {
  display: inline-block; align-self: flex-start;
  padding: 3px 9px; border-radius: var(--radius-sm, 4px);
  font-size: 0.6875rem; font-weight: 800; letter-spacing: 0.05em; text-transform: uppercase;
}
.nx-kicker {
  display: block; font-size: 0.6875rem; font-weight: 800;
  letter-spacing: 0.06em; text-transform: uppercase;
}
.nx-meta {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  font-size: var(--step--1); color: var(--ink-muted);
}
.nx-meta__date { display: inline-flex; align-items: center; gap: 4px; }
.nx-meta__date svg { width: 13px; height: 13px; }

/* Strip of four, round thumbnails */
.nx-strip {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-5);
  padding: var(--space-5); margin-top: var(--space-5);
  background: var(--surface-raised); border: 1px solid var(--line-hairline);
  border-radius: var(--radius-xl);
}
.nx-strip__item { display: flex; gap: var(--space-3); align-items: center; min-width: 0; }
.nx-strip__thumb {
  flex: none; width: 68px; height: 68px; border-radius: 50%; object-fit: cover;
  box-shadow: 0 0 0 3px var(--surface-raised), 0 0 0 4px var(--line-hairline);
}
.nx-strip__thumb--empty {
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-size: var(--step-3); font-weight: 800;
}
.nx-strip__body { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.nx-strip__title {
  font-weight: 700; font-size: var(--step--1); line-height: 1.35; color: var(--ink-primary);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

/* Lead item and the three beside it */
.nx-lead { display: grid; grid-template-columns: 1.45fr 1fr; gap: var(--space-5); }
.nx-hero {
  position: relative; display: flex; align-items: flex-end;
  min-height: 460px; overflow: hidden; border-radius: var(--radius-xl);
  background: var(--surface-dark); color: #fff; text-decoration: none;
}
.nx-hero img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  transition: transform 600ms var(--ease);
}
.nx-hero:hover img { transform: scale(1.03); }
.nx-hero::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,0) 35%, rgba(0,0,0,0.78) 100%);
}
.nx-hero__body {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; gap: var(--space-3);
  padding: var(--space-6);
}
.nx-hero__title {
  font-family: var(--font-ui); font-weight: 800; font-size: clamp(1.6rem, 3vw, 2.5rem);
  line-height: 1.12; letter-spacing: -0.01em; text-wrap: balance;
}
.nx-hero__title--sm { font-size: var(--step-3); }
.nx-hero__place { font-size: var(--step-0); color: rgba(255, 255, 255, 0.9); }
.nx-hero .nx-meta { color: rgba(255, 255, 255, 0.85); }

.nx-side { display: grid; grid-template-rows: repeat(3, 1fr); gap: var(--space-4); }
.nx-side__item {
  display: grid; grid-template-columns: 42% 1fr; height: 100%; min-height: 140px;
  background: var(--surface-raised); border: 1px solid var(--line-hairline);
  border-radius: var(--radius-lg); overflow: hidden;
  color: inherit; text-decoration: none;
  transition: box-shadow var(--dur-base) var(--ease), transform var(--dur-base) var(--ease);
}
.nx-side__item:hover { box-shadow: var(--shadow-2); transform: translateY(-2px); }
.nx-side__item .media-frame { height: 100% !important; }
.nx-side__body { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-4); justify-content: center; }
.nx-side__title { font-weight: 800; font-size: var(--step-1); line-height: 1.3; }

/* Banner */
.nx-banner {
  position: relative; display: flex; align-items: center; gap: var(--space-6); flex-wrap: wrap;
  padding: var(--space-5) var(--space-6) var(--space-5) 0;
  border-radius: var(--radius-xl); overflow: hidden;
  background: linear-gradient(100deg, var(--brand-primary-ink) 0%, var(--brand-primary) 55%, #B0121F 100%);
  color: #fff; text-decoration: none;
}
.nx-banner::before {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; 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%);
}
.nx-banner__photo {
  width: 230px; align-self: stretch; margin: calc(-1 * var(--space-5)) 0;
  object-fit: cover; clip-path: polygon(0 0, 100% 0, 82% 100%, 0 100%);
}
.nx-banner__text { display: flex; flex-direction: column; gap: 4px; flex: 1 1 16rem; }
.nx-banner__eyebrow { font-size: 0.6875rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--brand-accent); }
.nx-banner__title { font-family: var(--font-display); font-size: var(--step-4); font-weight: 700; line-height: 1.1; }
.nx-banner__sub { color: rgba(255, 255, 255, 0.85); }
.nx-banner__figure { display: flex; flex-direction: column; }
.nx-banner__num { font-size: var(--step-5); font-weight: 800; line-height: 1; }
.nx-banner__unit { font-size: var(--step--1); color: rgba(255, 255, 255, 0.8); }
.nx-banner__cta {
  padding: 12px 22px; border-radius: var(--radius-md);
  background: var(--brand-accent); color: var(--ink-primary); font-weight: 800;
}
.nx-banner:hover .nx-banner__cta { filter: brightness(1.05); }

/* Four-up */
.nx-four { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-5); }
.nx-card { display: flex; flex-direction: column; gap: var(--space-2); color: inherit; text-decoration: none; }
.nx-card .media-frame { margin-bottom: var(--space-2); overflow: hidden; }
.nx-card .media-frame img { transition: transform 500ms var(--ease); }
.nx-card:hover .media-frame img { transform: scale(1.04); }
.nx-card__title { font-weight: 800; font-size: var(--step-1); line-height: 1.3; }
.nx-card:hover .nx-card__title { color: var(--brand-primary); }

/* What's new, tabbed, and the follow tiles */
.nx-bottom { display: grid; grid-template-columns: minmax(0, 2.2fr) minmax(0, 1fr); gap: var(--space-6); }
.nx-tabs-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); flex-wrap: wrap; margin-bottom: var(--space-4); }
.nx-tabs { display: flex; gap: 4px; padding: 4px; background: var(--surface-raised); border: 1px solid var(--line-hairline); border-radius: var(--radius-md); }
.nx-tab {
  padding: 6px 14px; border: 0; border-radius: var(--radius-sm, 4px); cursor: pointer;
  background: transparent; font: inherit; font-size: var(--step--1); font-weight: 700; color: var(--ink-secondary);
}
.nx-tab:hover { color: var(--ink-primary); }
.nx-tab[aria-selected="true"] { background: var(--tab); color: var(--tab-ink); }
.nx-panel { display: grid; grid-template-columns: 1.15fr 1fr; gap: var(--space-5); }
.nx-hero--panel { min-height: 320px; }
.nx-numbered { display: flex; flex-direction: column; gap: var(--space-4); align-self: center; }
.nx-numbered__item { display: grid; grid-template-columns: 22px 96px 1fr; gap: var(--space-3); align-items: center; color: inherit; text-decoration: none; }
.nx-numbered__no { font-weight: 800; font-size: var(--step-2); }
.nx-numbered__title { display: block; font-weight: 800; font-size: var(--step-0); line-height: 1.35; margin-bottom: 4px; }
.nx-numbered__item:hover .nx-numbered__title { color: var(--brand-primary); }

.nx-follow { display: flex; flex-direction: column; gap: var(--space-3); margin-top: var(--space-4); }
.nx-follow__tile {
  display: flex; align-items: center; gap: var(--space-4);
  padding: var(--space-3) var(--space-4); border-radius: var(--radius-md);
  color: #fff; text-decoration: none;
  transition: transform var(--dur-base) var(--ease), filter var(--dur-base) var(--ease);
}
.nx-follow__tile:hover { transform: translateX(3px); filter: brightness(1.08); }
.nx-follow__tile b { display: block; font-size: var(--step-0); }
.nx-follow__tile span span { display: block; font-size: var(--step--1); opacity: 0.85; }
.nx-follow__icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 50%; background: rgba(255, 255, 255, 0.16);
}
.nx-follow__icon svg { width: 19px; height: 19px; }
.nx-follow__tile--youtube { background: linear-gradient(90deg, var(--brand-primary-ink), var(--brand-primary)); }
.nx-follow__tile--videos  { background: linear-gradient(90deg, #151A24, var(--surface-dark)); }
.nx-follow__tile--stories { background: linear-gradient(90deg, #0A4A25, var(--surface-story)); }
.nx-follow__tile--events  { background: linear-gradient(90deg, var(--brand-wendi-deep), var(--brand-wendi)); }

@media (max-width: 64rem) {
  .nx-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .nx-lead, .nx-bottom { grid-template-columns: 1fr; }
  .nx-four { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 40rem) {
  .nx-strip, .nx-four, .nx-panel { grid-template-columns: 1fr; }
  .nx-hero { min-height: 340px; }
  .nx-side__item { grid-template-columns: 38% 1fr; }
  .nx-banner { padding: 0 var(--space-5) var(--space-5); }
  .nx-banner__photo { width: calc(100% + 2 * var(--space-5)); height: 150px; margin: 0 calc(-1 * var(--space-5)); clip-path: none; }
  .nx-ticker__when { white-space: normal; }
}
@media print { .nx-hero img, .nx-banner__photo { display: none; } }
.nx-panel[hidden] { display: none; }
.nx .nx-head { margin-top: var(--space-6); }
.nx .nx-head { margin-bottom: var(--space-5); }
