/* ==========================================================================
   BAWUMIA NATION — DESIGN SYSTEM
   --------------------------------------------------------------------------
   The palette is taken from the logo, because the logo already solved it:
   Ghana's flag beside the movement's blue. Nothing here is invented.

     BLUE   the brand. Structure, links, the platform's voice.
     GOLD   the call to action, and only that. Spending it anywhere else
            makes the one button that matters stop shouting.
     GREEN  progress, verification, work that is finished.
     RED    destructive and urgent. Never decorative.
     INK    type, and the dark blocks the page rests between.

   Blue and gold is also the reason this reads young rather than municipal.
   High-chroma complements at full strength, on generous white, with rounded
   surfaces and soft blue-cast shadow: the visual language a nineteen-year-old
   already uses every day. The alternative -- muted institutional greys with a
   red accent -- reads as something their uncle would be asked to fill in.

   Structure is unchanged from the Vox Populi template: full-bleed sections
   alternating down the page on a 136px rhythm, an eyebrow and rule above each
   headline, pill actions, a dark footer.

   Still hand-written rather than generated by a utility framework, for the
   same reason as before: the primary user is on an Android handset, on
   intermittent mobile data, in Ghana. One cached stylesheet, no build step,
   no JavaScript required to render a page.

   Contents
     1.  Tokens
     1b. Webfonts
     2.  Reset and base
     3.  Layout
     4.  Typography
     5.  Buttons
     6.  Forms
     7.  Cards and surfaces
     8.  Badges, pills, chips
     9.  Alerts
     10. Stats and data display
     11. Tables
     12. Navigation
     13. Feed and content
     14. Progress and score
     15. Empty, error and loading states
     16. Utilities
     17. Print
     18. Site chrome and marketing sections
   ========================================================================== */

/* 1. TOKENS ============================================================== */

:root {
    /* --- Palette --------------------------------------------------------

       Blue and red are sampled from the logo itself. The badge is the brand,
       so the interface follows it rather than the other way round -- and the
       hero artwork was re-rendered onto this same blue, so the mark, the
       header and the photograph are one colour rather than three that nearly
       match, which is the kind of thing nobody can name but everybody sees.
    */
    --bn-blue-900: #03015C;
    --bn-blue-800: #050185;
    --bn-blue-700: #0601A1;
    --bn-blue-600: #0802B8;  /* the brand, straight off the badge */
    --bn-blue-500: #2A20D4;
    --bn-blue-400: #5A4EE8;
    --bn-blue-200: #C3BEF8;
    --bn-blue-100: #E0DDFC;
    --bn-blue-50: #F2F1FE;

    --bn-gold-700: #8A6400;
    --bn-gold-600: #A87C00;
    --bn-gold-500: #FFC400;  /* the call to action */
    --bn-gold-400: #FFD447;
    --bn-gold-100: #FFF3D1;

    --bn-green-700: #046B41;
    --bn-green-600: #00844B;
    --bn-green-500: #00A05B;
    --bn-green-100: #DEF5EA;

    /* The badge's red. It appears in the mark itself, so it earns a place in
       the interface -- on the rule above a headline, and on anything
       destructive. It is not the action colour: red on this much blue
       vibrates at button size, which is what gold is for. */
    --bn-red-700: #96040E;
    --bn-red-600: #BE0511;
    --bn-red-500: #DE0614;  /* straight off the badge */
    --bn-red-100: #FCE0E3;

    /* Ink is blue-black, not neutral black. Against a blue brand a true
       neutral looks accidental; this looks chosen. */
    --bn-ink: #0E1422;
    --bn-ink-800: #151D30;
    --bn-ink-700: #1E2942;
    --bn-ink-soft: #47506B;
    --bn-muted: #6B7490;

    --bn-line: #E2E7F2;
    --bn-line-soft: #EEF1F8;
    --bn-surface: #FFFFFF;
    --bn-mist: #F4F6FB;      /* the alternating light section */
    --bn-canvas: #F4F6FB;
    --bn-canvas-warm: #FAFBFE;

    /* Semantic */
    --bn-primary: var(--bn-blue-600);
    --bn-primary-hover: var(--bn-blue-700);
    --bn-accent: var(--bn-gold-500);
    --bn-success: var(--bn-green-500);
    --bn-danger: var(--bn-red-500);
    --bn-warning: var(--bn-gold-600);

    /* --- Legacy aliases --------------------------------------------------

       The names ninety views were written against. They finally mean what
       they say -- blue is blue and gold is gold -- so these are a courtesy to
       the markup rather than a translation layer.
    */
    --bn-navy-900: var(--bn-ink);
    --bn-navy-800: var(--bn-ink-800);
    --bn-navy-700: var(--bn-ink-700);
    --bn-crimson-500: var(--bn-red-500);
    --bn-crimson-600: var(--bn-red-600);
    --bn-crimson-700: var(--bn-red-700);
    --bn-crimson-400: var(--bn-red-500);
    --bn-crimson-100: var(--bn-red-100);
    --bn-crimson-50: #FFF5F6;
    --bn-black-900: var(--bn-ink);
    --bn-black-800: var(--bn-ink-800);
    --bn-black-700: var(--bn-ink-700);
    --bn-black-600: #27334F;
    --bn-steel-600: var(--bn-blue-700);
    --bn-steel-100: var(--bn-blue-100);
    --bn-amber-600: var(--bn-gold-600);
    --bn-amber-500: var(--bn-gold-500);
    --bn-amber-100: var(--bn-gold-100);

    /* Spacing — 4px base */
    --sp-1: 0.25rem;
    --sp-2: 0.5rem;
    --sp-3: 0.75rem;
    --sp-4: 1rem;
    --sp-5: 1.25rem;
    --sp-6: 1.5rem;
    --sp-8: 2rem;
    --sp-10: 2.5rem;
    --sp-12: 3rem;
    --sp-16: 4rem;

    /* The template breathes: 136px between full-bleed sections on desktop. */
    --section-pad: 3.5rem;
    --section-pad-sm: 2.5rem;

    /* --- Radius ---------------------------------------------------------

       The single change that moves this design a decade forward. The template
       squares everything off, which reads as newsprint; every surface a young
       person touches all day is rounded. Actions stay fully pill.
    */
    --r-sm: 8px;
    --r-md: 12px;
    --r-lg: 18px;
    --r-xl: 26px;
    --r-full: 999px;

    /* Shadow is blue-cast, never grey. Grey shadow on a coloured interface
       looks like dirt under the card. */
    --sh-sm: 0 1px 2px rgba(8, 40, 120, 0.06);
    --sh-md: 0 6px 22px rgba(8, 40, 120, 0.10);
    --sh-lg: 0 18px 48px rgba(8, 40, 120, 0.16);

    /* Type scale */
    --fs-xs: 0.75rem;
    --fs-sm: 0.8125rem;
    --fs-base: 1rem;
    --fs-md: 1.0625rem;
    --fs-lg: 1.1875rem;
    --fs-xl: 1.5rem;
    --fs-2xl: 1.875rem;
    --fs-3xl: 2.5rem;
    --fs-4xl: 3.25rem;

    --lh-tight: 1.1;
    --lh-snug: 1.35;
    --lh-normal: 1.6;
    --lh-loose: 1.8;

    /* Letter-spacing on the small uppercase labels the template leans on. */
    --ls-caps: 0.14em;

    /*
      Work Sans for headlines, Roboto for text. Work Sans at 600 is the
      closest widely available companion to the heavy condensed face in the
      logo -- it does not imitate it, which would look like a bad copy, but it
      sits beside it without arguing.
    */
    --font-display: "Work Sans", -apple-system, BlinkMacSystemFont, "Segoe UI",
        Arial, "Noto Sans", sans-serif;
    --font-sans: "Roboto", -apple-system, BlinkMacSystemFont, "Segoe UI",
        "Helvetica Neue", Arial, "Noto Sans", sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

    --nav-height: 60px;
    --header-height: 64px;
    --content-max: 1200px;

}

@media (min-width: 900px) {
    :root {
        --section-pad: 8.5rem;
        --section-pad-sm: 5rem;
    }
}

/* 1b. WEBFONTS =========================================================== */

/*
   Work Sans and Roboto, served from this origin rather than a font CDN.

   Two reasons, and both matter here. The content security policy allows no
   third-party origins at all, and relaxing it so a page can render its
   headlines would be a poor trade. And a request to a CDN on a Ghanaian
   mobile connection is a fresh DNS lookup, TLS handshake and round trip
   before a single letter is painted -- from this origin the connection is
   already open.

   Both are VARIABLE fonts, so one 40-50KB file per family covers every weight
   from 100 to 900. The subset is latin only: 93KB for the pair.

   font-display: swap means text paints immediately in the system fallback and
   reflows once. On a slow link a visible page that reflows beats a blank one.
*/

@font-face {
    font-family: "Work Sans";
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("../fonts/work-sans-latin-variable.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
        U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
        U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: "Roboto";
    font-style: normal;
    font-weight: 100 900;
    font-stretch: 100%;
    font-display: swap;
    src: url("../fonts/roboto-latin-variable.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
        U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
        U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* 2. RESET AND BASE ====================================================== */

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

* {
    margin: 0;
}

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

body {
    font-family: var(--font-sans);
    font-size: var(--fs-base);
    line-height: var(--lh-normal);
    color: var(--bn-ink);
    background: var(--bn-canvas);
    -webkit-font-smoothing: antialiased;
    min-height: 100vh;
}

/* Marketing pages run full-bleed colour blocks edge to edge. */
body.is-marketing {
    background: var(--bn-surface);
}

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

button,
input,
select,
textarea {
    font: inherit;
    color: inherit;
}

a {
    color: var(--bn-blue-600);
    text-decoration: none;
}

a:hover {
    text-decoration: underline;
}

/*
   Focus is always visible. Keyboard users are not second-class here.

   The ring changes colour with the ground it sits on, because no single
   colour in this palette clears WCAG's 3:1 for a focus indicator against all
   of them. Measured:

     blue on white  7.5:1     gold on white  1.6:1   <- unusable
     blue on gold   5.2:1     gold on blue   4.7:1
     blue on ink    1.9:1     gold on ink   11.5:1

   So: blue by default, gold anywhere the ground is dark or brand blue.
*/
:focus-visible {
    outline: 3px solid var(--bn-blue-600);
    outline-offset: 3px;
}

.hero :focus-visible,
.topbar :focus-visible,
.site-topbar :focus-visible,
.site-footer :focus-visible,
.section--dark :focus-visible,
.next-action :focus-visible {
    outline-color: var(--bn-gold-500);
}

/* Respect a member who has asked the OS for less motion. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

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

.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 999;
    padding: var(--sp-3) var(--sp-4);
    background: var(--bn-navy-800);
    color: #fff;
    border-radius: 0 0 var(--r-md) 0;
}

.skip-link:focus {
    left: 0;
}

/* 3. LAYOUT ============================================================== */

.shell {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

.container {
    width: 100%;
    max-width: var(--content-max);
    margin-inline: auto;
    padding-inline: var(--sp-4);
}

.container-narrow {
    max-width: 640px;
}

.container-wide {
    max-width: 1400px;
}

.main {
    flex: 1;
    padding-block: var(--sp-5) calc(var(--nav-height) + var(--sp-8));
}

@media (min-width: 900px) {
    .main {
        padding-bottom: var(--sp-12);
    }
}

.stack {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
}

.stack-sm { gap: var(--sp-2); }
.stack-lg { gap: var(--sp-6); }
.stack-xl { gap: var(--sp-8); }

.row {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
}

.row-between {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
}

.row-wrap {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
    align-items: center;
}

.grid {
    display: grid;
    gap: var(--sp-4);
}

.grid-2 { grid-template-columns: 1fr; }
.grid-3 { grid-template-columns: 1fr; }
.grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

@media (min-width: 640px) {
    .grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 960px) {
    .grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.split {
    display: grid;
    gap: var(--sp-6);
    grid-template-columns: 1fr;
}

@media (min-width: 1000px) {
    .split {
        grid-template-columns: minmax(0, 1fr) 320px;
    }

    .split-wide {
        grid-template-columns: 280px minmax(0, 1fr);
    }
}

/* 4. TYPOGRAPHY ========================================================== */

h1, h2, h3, h4 {
    font-family: var(--font-display);
    line-height: var(--lh-tight);
    font-weight: 600;
    letter-spacing: normal;
    color: var(--bn-ink);
}

h1 { font-size: var(--fs-2xl); }
h2 { font-size: var(--fs-xl); }
h3 { font-size: var(--fs-lg); }
h4 { font-size: var(--fs-md); }

@media (min-width: 768px) {
    h1 { font-size: var(--fs-3xl); }
}

.display {
    font-family: var(--font-display);
    font-size: var(--fs-3xl);
    line-height: 1;
    font-weight: 600;
    letter-spacing: normal;
}

@media (min-width: 768px) {
    .display { font-size: var(--fs-4xl); }
}

.lede {
    font-size: var(--fs-md);
    line-height: var(--lh-loose);
    color: var(--bn-ink-soft);
}

.muted { color: var(--bn-muted); }
.small { font-size: var(--fs-sm); }
.tiny { font-size: var(--fs-xs); }
.bold { font-weight: 650; }
.mono { font-family: var(--font-mono); font-size: 0.9em; letter-spacing: 0.02em; }

/*
   The template's "superheadline": a short line sitting above the headline,
   under a short rule. It is the single most recognisable typographic move in
   the design, so it is a real component rather than a colour tweak.
*/
.eyebrow {
    display: block;
    font-family: var(--font-display);
    font-size: var(--fs-sm);
    font-weight: 600;
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    color: var(--bn-blue-600);
}

.eyebrow::before {
    content: "";
    display: block;
    width: 44px;
    height: 3px;
    margin-bottom: var(--sp-3);
    background: currentColor;
}

.eyebrow-plain::before { display: none; }

.section-title {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-3);
    margin-bottom: var(--sp-4);
}

.section-title h2 {
    font-size: var(--fs-xl);
}

/* Truncation for names and titles that must not break a card's layout. */
.truncate {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.clamp-2 {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.clamp-3 {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* 5. BUTTONS ============================================================= */

/*
   Pill-shaped, and the label is set in small capitals with wide tracking --
   the template's single most distinctive control. The tracking is what makes
   a 12px label read as deliberate rather than merely small.
*/
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    padding: var(--sp-3) var(--sp-6);
    /* 44px minimum: a thumb on a bus, not a mouse on a desk. */
    min-height: 46px;
    border: 2px solid transparent;
    border-radius: var(--r-full);
    font-size: var(--fs-sm);
    font-weight: 600;
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    cursor: pointer;
    text-align: center;
    text-decoration: none;
    transition: background-color 0.18s ease, border-color 0.18s ease, color 0.18s ease;
    background: var(--bn-primary);
    color: #fff;
}

.btn:hover {
    background: var(--bn-primary-hover);
    border-color: var(--bn-primary-hover);
    color: #fff;
    text-decoration: none;
}

.btn:disabled,
.btn[aria-disabled="true"] {
    opacity: 0.5;
    cursor: not-allowed;
}

/*
   Gold, with ink type on it. This is the join-the-movement button and the
   only thing on any screen allowed to be gold, which is exactly why the eye
   finds it before anything else. Ink on gold measures 11:1, so the loudest
   control on the page is also the most legible one.
*/
.btn-accent {
    background: var(--bn-gold-500);
    border-color: var(--bn-gold-500);
    color: var(--bn-ink);
}

.btn-accent:hover {
    background: var(--bn-gold-400);
    border-color: var(--bn-gold-400);
    color: var(--bn-ink);
}

.btn-success { background: var(--bn-success); border-color: var(--bn-success); }
.btn-success:hover { background: var(--bn-green-600); border-color: var(--bn-green-600); }

.btn-danger { background: var(--bn-danger); border-color: var(--bn-danger); }
.btn-danger:hover { background: var(--bn-red-700); border-color: var(--bn-red-700); }

.btn-outline {
    background: transparent;
    border-color: var(--bn-ink);
    color: var(--bn-ink);
}

.btn-outline:hover {
    background: var(--bn-ink);
    border-color: var(--bn-ink);
    color: #fff;
}

.btn-ghost {
    background: transparent;
    border-color: transparent;
    color: var(--bn-blue-600);
    padding-inline: var(--sp-4);
}

.btn-ghost:hover {
    background: var(--bn-blue-50);
    border-color: transparent;
    color: var(--bn-red-600);
}

/* On a dark section, the outline flips to white. */
.on-dark .btn-outline,
.section--dark .btn-outline {
    border-color: #fff;
    color: #fff;
}

.on-dark .btn-outline:hover,
.section--dark .btn-outline:hover {
    background: #fff;
    color: var(--bn-ink);
}

/* Gold holds up on ink without changing, so it does not. */
.on-dark .btn-accent,
.section--dark .btn-accent {
    background: var(--bn-gold-500);
    border-color: var(--bn-gold-500);
    color: var(--bn-ink);
}

.on-dark .btn-accent:hover,
.section--dark .btn-accent:hover {
    background: #fff;
    border-color: #fff;
    color: var(--bn-ink);
}

/* On the gold strip, ink is the only thing that can be louder. */
.section--accent .btn,
.section--accent .btn-accent {
    background: var(--bn-ink);
    border-color: var(--bn-ink);
    color: #fff;
}

.section--accent .btn:hover,
.section--accent .btn-accent:hover {
    background: var(--bn-blue-600);
    border-color: var(--bn-blue-600);
    color: #fff;
}

.section--accent .btn-outline {
    background: transparent;
    border-color: var(--bn-ink);
    color: var(--bn-ink);
}

.section--accent .btn-outline:hover {
    background: var(--bn-ink);
    border-color: var(--bn-ink);
    color: #fff;
}

.btn-sm {
    min-height: 38px;
    padding: var(--sp-2) var(--sp-4);
    font-size: var(--fs-xs);
    letter-spacing: 0.1em;
}

.btn-lg {
    min-height: 60px;
    font-size: var(--fs-base);
    padding-inline: var(--sp-8);
}

.btn-block {
    display: flex;
    width: 100%;
}

/*
   Provider sign-in buttons. Google is visually first and largest.
   These keep sentence case: "CONTINUE WITH GOOGLE" shouts at somebody who is
   only trying to sign in, and the provider names are proper nouns.
*/
.btn-provider {
    background: #fff;
    color: var(--bn-ink);
    border: 2px solid var(--bn-line);
    justify-content: flex-start;
    padding-inline: var(--sp-5);
    font-size: var(--fs-base);
    font-weight: 600;
    text-transform: none;
    letter-spacing: normal;
    gap: var(--sp-3);
}

.btn-provider:hover {
    background: var(--bn-mist);
    border-color: var(--bn-ink);
    color: var(--bn-ink);
}

.btn-provider .provider-icon {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
}

.btn-provider-primary {
    border-color: var(--bn-blue-600);
    border-width: 2px;
    min-height: 56px;
    font-size: var(--fs-md);
}

.btn-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
}

/* 6. FORMS =============================================================== */

.field {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    margin-bottom: var(--sp-4);
}

.field label,
.label {
    font-size: var(--fs-sm);
    font-weight: 650;
    color: var(--bn-ink-soft);
}

.required-mark {
    color: var(--bn-danger);
    margin-left: 2px;
}

.input,
.select,
.textarea {
    width: 100%;
    padding: var(--sp-3);
    min-height: 46px;
    border: 1.5px solid var(--bn-line);
    border-radius: var(--r-md);
    background: var(--bn-surface);
    /* 16px prevents iOS Safari zooming the viewport on focus. */
    font-size: 16px;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

@media (min-width: 640px) {
    .input,
    .select,
    .textarea {
        font-size: var(--fs-base);
    }
}

/*
   Suppressing the outline here is only acceptable because the border replaces
   it. The border must therefore carry the contrast on its own: blue-600
   against white is 7.5:1, where the old blue-400 was 3.4:1 and the pale halo
   behind it was 1.2:1 -- which is to say, decorative.
*/
.input:focus,
.select:focus,
.textarea:focus {
    border-color: var(--bn-blue-600);
    box-shadow: 0 0 0 3px rgba(8, 67, 215, 0.18);
    outline: none;
}

.input[aria-invalid="true"],
.select[aria-invalid="true"],
.textarea[aria-invalid="true"] {
    border-color: var(--bn-danger);
}

.input:disabled,
.select:disabled,
.textarea:disabled {
    background: var(--bn-line-soft);
    color: var(--bn-muted);
    cursor: not-allowed;
}

.textarea {
    min-height: 110px;
    resize: vertical;
    line-height: var(--lh-normal);
}

.select {
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23667085' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right var(--sp-3) center;
    padding-right: var(--sp-8);
}

.hint {
    font-size: var(--fs-sm);
    color: var(--bn-muted);
}

.error-text {
    font-size: var(--fs-sm);
    color: var(--bn-red-600);
    font-weight: 550;
}

.field-error {
    display: block;
    margin-top: var(--sp-1);
}

.checkbox-row,
.radio-row {
    display: flex;
    align-items: flex-start;
    gap: var(--sp-3);
    padding: var(--sp-3);
    border: 1.5px solid var(--bn-line);
    border-radius: var(--r-md);
    cursor: pointer;
    background: var(--bn-surface);
    transition: border-color 0.12s ease, background-color 0.12s ease;
}

.checkbox-row:hover,
.radio-row:hover {
    border-color: var(--bn-blue-400);
    background: var(--bn-blue-50);
}

.checkbox-row input,
.radio-row input {
    width: 20px;
    height: 20px;
    margin-top: 2px;
    accent-color: var(--bn-primary);
    flex-shrink: 0;
}

.checkbox-row:has(input:checked),
.radio-row:has(input:checked) {
    border-color: var(--bn-primary);
    background: var(--bn-blue-50);
}

.choice-grid {
    display: grid;
    gap: var(--sp-2);
    grid-template-columns: 1fr;
}

@media (min-width: 640px) {
    .choice-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

.choice-label {
    font-weight: 600;
    color: var(--bn-ink);
    display: block;
}

.choice-desc {
    font-size: var(--fs-sm);
    color: var(--bn-muted);
}

.char-count {
    font-size: var(--fs-xs);
    color: var(--bn-muted);
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.char-count.over {
    color: var(--bn-danger);
    font-weight: 700;
}

.divider-text {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    color: var(--bn-muted);
    font-size: var(--fs-sm);
    margin-block: var(--sp-5);
}

.divider-text::before,
.divider-text::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--bn-line);
}

/* Segmented control for tab-like filters */
.segmented {
    display: inline-flex;
    padding: 3px;
    background: var(--bn-line-soft);
    border-radius: var(--r-full);
    gap: 2px;
    overflow-x: auto;
    max-width: 100%;
}

.segmented a,
.segmented button {
    padding: var(--sp-2) var(--sp-4);
    border-radius: var(--r-full);
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--bn-ink-soft);
    border: none;
    background: transparent;
    cursor: pointer;
    white-space: nowrap;
    text-decoration: none;
}

.segmented a.is-active,
.segmented button.is-active {
    background: var(--bn-surface);
    color: var(--bn-navy-800);
    box-shadow: var(--sh-sm);
}

/* 7. CARDS AND SURFACES ================================================== */

/*
   Squared, flat, hairline border. The template gets its depth from full-bleed
   colour blocks, not from rounding and shadowing every box on the page.
*/
.card {
    background: var(--bn-surface);
    border: 1px solid var(--bn-line);
    border-radius: var(--r-lg);
    padding: var(--sp-6);
    transition: border-color 0.18s ease, box-shadow 0.18s ease;
}

.card-tight { padding: var(--sp-4); }
.card-flush { padding: 0; overflow: hidden; }

.card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
    padding-bottom: var(--sp-3);
    margin-bottom: var(--sp-4);
    border-bottom: 1px solid var(--bn-line-soft);
}

.card-header h2,
.card-header h3 {
    font-size: var(--fs-lg);
}

.card-link {
    display: block;
    color: inherit;
}

.card-link:hover {
    text-decoration: none;
    border-color: var(--bn-blue-400);
    box-shadow: var(--sh-md);
    transform: translateY(-2px);
}

/*
   The hero card: the single most important thing on the dashboard, and the
   one place in the app that borrows the marketing hero's treatment -- the
   brand blue, with gold on the action and a gold edge down the left.
*/
.next-action {
    position: relative;
    background: var(--bn-blue-600);
    color: #fff;
    border: none;
    border-left: 6px solid var(--bn-gold-500);
    border-radius: var(--r-xl);
    padding: var(--sp-8) var(--sp-6);
    overflow: hidden;
    box-shadow: var(--sh-md);
}

.next-action::after {
    /* One gold wash in the corner: identity without clutter. */
    content: "";
    position: absolute;
    top: -80px;
    right: -80px;
    width: 260px;
    height: 260px;
    background: radial-gradient(circle, rgba(255, 196, 0, 0.30) 0%, transparent 70%);
    pointer-events: none;
}

.next-action h2,
.next-action h3 {
    color: #fff;
}

.next-action .eyebrow {
    color: var(--bn-gold-400);
}

.next-action p {
    color: rgba(255, 255, 255, 0.86);
}

.next-action .btn {
    background: var(--bn-gold-500);
    border-color: var(--bn-gold-500);
    color: var(--bn-ink);
    position: relative;
    z-index: 1;
}

.next-action .btn:hover {
    background: #fff;
    border-color: #fff;
    color: var(--bn-ink);
}

.next-action.is-critical {
    background: var(--bn-red-600);
    border-left-color: var(--bn-gold-500);
}

.next-action.is-overdue {
    background: var(--bn-gold-600);
    border-left-color: var(--bn-ink);
}

.panel {
    background: var(--bn-surface);
    border: 1px solid var(--bn-line);
    border-radius: var(--r-lg);
    overflow: hidden;
}

.panel-head {
    padding: var(--sp-4) var(--sp-5);
    border-bottom: 1px solid var(--bn-line-soft);
    background: var(--bn-canvas-warm);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
}

.panel-body { padding: var(--sp-5); }
.panel-body-flush { padding: 0; }

.list {
    list-style: none;
    padding: 0;
    margin: 0;
}

.list-item {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-4) var(--sp-5);
    border-bottom: 1px solid var(--bn-line-soft);
    color: inherit;
}

.list-item:last-child { border-bottom: none; }

a.list-item:hover {
    background: var(--bn-blue-50);
    text-decoration: none;
}

.list-item-main {
    flex: 1;
    min-width: 0;
}

.list-item-title {
    font-weight: 600;
    color: var(--bn-navy-800);
}

.list-item-meta {
    font-size: var(--fs-sm);
    color: var(--bn-muted);
}

/* 8. BADGES, PILLS, CHIPS ================================================ */

.badge {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    padding: 3px var(--sp-2);
    border-radius: var(--r-full);
    font-size: var(--fs-xs);
    font-weight: 700;
    letter-spacing: 0.02em;
    background: var(--bn-line-soft);
    color: var(--bn-ink-soft);
    white-space: nowrap;
}

.badge-primary { background: var(--bn-blue-100); color: var(--bn-navy-700); }
.badge-accent { background: var(--bn-gold-100); color: var(--bn-gold-600); }
.badge-success { background: var(--bn-green-100); color: var(--bn-green-600); }
.badge-danger { background: var(--bn-red-100); color: var(--bn-red-600); }
.badge-official {
    background: var(--bn-navy-800);
    color: var(--bn-gold-400);
}

.chip {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    padding: var(--sp-1) var(--sp-3);
    border-radius: var(--r-full);
    border: 1px solid var(--bn-line);
    background: var(--bn-surface);
    font-size: var(--fs-sm);
    color: var(--bn-ink-soft);
    text-decoration: none;
}

a.chip:hover {
    border-color: var(--bn-blue-400);
    background: var(--bn-blue-50);
    text-decoration: none;
}

.chip.is-active {
    background: var(--bn-navy-800);
    color: #fff;
    border-color: var(--bn-navy-800);
}

/* Avatar */
.avatar {
    width: 40px;
    height: 40px;
    border-radius: var(--r-full);
    background: var(--bn-blue-100);
    color: var(--bn-navy-700);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: var(--fs-sm);
    flex-shrink: 0;
    overflow: hidden;
    text-transform: uppercase;
}

.avatar img { width: 100%; height: 100%; object-fit: cover; }
.avatar-sm { width: 32px; height: 32px; font-size: var(--fs-xs); }
.avatar-lg { width: 64px; height: 64px; font-size: var(--fs-lg); }
.avatar-xl { width: 96px; height: 96px; font-size: var(--fs-2xl); }

/* 9. ALERTS ============================================================== */

.alert {
    display: flex;
    gap: var(--sp-3);
    padding: var(--sp-4);
    border-radius: var(--r-md);
    border: 1px solid;
    font-size: var(--fs-base);
    margin-bottom: var(--sp-4);
}

.alert-info {
    background: var(--bn-blue-50);
    border-color: var(--bn-blue-100);
    color: var(--bn-navy-700);
}

.alert-success {
    background: var(--bn-green-100);
    border-color: #B7E2D2;
    color: var(--bn-green-600);
}

.alert-warning {
    background: var(--bn-gold-100);
    border-color: #F5DFAE;
    color: #7A5205;
}

.alert-danger {
    background: var(--bn-red-100);
    border-color: #F3C4BF;
    color: var(--bn-red-600);
}

.alert-title {
    font-weight: 700;
    display: block;
    margin-bottom: 2px;
}

/*
   Development banner: shown whenever a message was written to the log
   instead of actually being delivered. It must be impossible to mistake a
   simulated send for a real one.
*/
.dev-banner {
    background: repeating-linear-gradient(
        45deg, #2B2B2B, #2B2B2B 12px, #383838 12px, #383838 24px);
    color: #FFD87A;
    padding: var(--sp-3) var(--sp-4);
    font-size: var(--fs-sm);
    font-family: var(--font-mono);
    border-radius: var(--r-md);
    margin-bottom: var(--sp-4);
}

.dev-banner strong { color: #fff; }

.dev-code {
    display: inline-block;
    font-size: var(--fs-xl);
    letter-spacing: 0.35em;
    font-weight: 700;
    color: #fff;
    padding: var(--sp-1) var(--sp-2);
}

/* 10. STATS AND DATA DISPLAY ============================================= */

.stat-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sp-3);
}

@media (min-width: 768px) {
    .stat-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .stat-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.stat {
    background: var(--bn-surface);
    border: 1px solid var(--bn-line);
    border-radius: var(--r-md);
    padding: var(--sp-4);
}

.stat-value {
    font-size: var(--fs-2xl);
    font-weight: 750;
    color: var(--bn-navy-800);
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
}

.stat-label {
    font-size: var(--fs-sm);
    color: var(--bn-muted);
    margin-top: 2px;
}

.stat-delta {
    font-size: var(--fs-xs);
    font-weight: 650;
    margin-top: var(--sp-1);
}

.stat-delta.up { color: var(--bn-green-500); }
.stat-delta.down { color: var(--bn-red-500); }

/* Funnel: registered > verified > volunteer > active > organizer */
.funnel {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}

.funnel-step {
    display: grid;
    grid-template-columns: 130px 1fr auto;
    align-items: center;
    gap: var(--sp-3);
    font-size: var(--fs-sm);
}

.funnel-bar {
    height: 26px;
    border-radius: var(--r-sm);
    background: var(--bn-line-soft);
    overflow: hidden;
}

.funnel-fill {
    height: 100%;
    background: linear-gradient(90deg, var(--bn-blue-600), var(--bn-blue-400));
    border-radius: var(--r-sm);
    min-width: 2px;
}

.funnel-step:nth-child(2) .funnel-fill { background: linear-gradient(90deg, var(--bn-blue-500), var(--bn-blue-400)); }
.funnel-step:nth-child(3) .funnel-fill { background: linear-gradient(90deg, var(--bn-green-600), var(--bn-green-500)); }
.funnel-step:nth-child(4) .funnel-fill { background: linear-gradient(90deg, var(--bn-gold-600), var(--bn-gold-500)); }
.funnel-step:nth-child(5) .funnel-fill { background: linear-gradient(90deg, var(--bn-navy-800), var(--bn-navy-700)); }

.funnel-count {
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    color: var(--bn-navy-800);
    min-width: 52px;
    text-align: right;
}

/* Simple bar chart, rendered server-side. No charting library, no JS. */
.bar-chart {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}

.bar-row {
    display: grid;
    grid-template-columns: minmax(90px, 1fr) 2fr auto;
    gap: var(--sp-3);
    align-items: center;
    font-size: var(--fs-sm);
}

.bar-track {
    height: 10px;
    background: var(--bn-line-soft);
    border-radius: var(--r-full);
    overflow: hidden;
}

.bar-fill {
    height: 100%;
    background: var(--bn-blue-500);
    border-radius: var(--r-full);
}

/* 11. TABLES ============================================================= */

.table-wrap {
    overflow-x: auto;
    border: 1px solid var(--bn-line);
    border-radius: var(--r-lg);
    background: var(--bn-surface);
    -webkit-overflow-scrolling: touch;
}

table.data {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--fs-sm);
    min-width: 560px;
}

table.data th {
    text-align: left;
    padding: var(--sp-3) var(--sp-4);
    background: var(--bn-canvas-warm);
    border-bottom: 1px solid var(--bn-line);
    font-weight: 700;
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--bn-muted);
    white-space: nowrap;
}

table.data td {
    padding: var(--sp-3) var(--sp-4);
    border-bottom: 1px solid var(--bn-line-soft);
    vertical-align: middle;
}

table.data tbody tr:last-child td { border-bottom: none; }
table.data tbody tr:hover { background: var(--bn-blue-50); }

table.data .num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* 12. NAVIGATION ========================================================= */

.topbar {
    position: sticky;
    top: 0;
    z-index: 40;
    background: var(--bn-navy-800);
    color: #fff;
    height: var(--header-height);
    display: flex;
    align-items: center;
}

.topbar .container {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
}

.brand {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-3);
    color: #fff;
    font-family: var(--font-display);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    font-size: var(--fs-base);
}

.brand:hover { text-decoration: none; }

.brand-mark {
    width: 34px;
    height: 34px;
    border-radius: 0;
    background: var(--bn-blue-600);
    color: #fff;
    display: grid;
    place-items: center;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: var(--fs-sm);
    letter-spacing: 0.02em;
    flex-shrink: 0;
}

.topbar-actions {
    display: flex;
    align-items: center;
    gap: var(--sp-1);
}

.icon-btn {
    position: relative;
    width: 40px;
    height: 40px;
    display: grid;
    place-items: center;
    border-radius: var(--r-full);
    color: rgba(255, 255, 255, 0.9);
    background: transparent;
    border: none;
    cursor: pointer;
}

.icon-btn:hover {
    background: rgba(255, 255, 255, 0.12);
    text-decoration: none;
}

.notification-dot {
    position: absolute;
    top: 6px;
    right: 6px;
    min-width: 17px;
    height: 17px;
    padding-inline: 4px;
    border-radius: var(--r-full);
    /* Gold, not red: an unread count is an invitation, not an emergency, and
       red is reserved here for things that destroy or block. */
    background: var(--bn-gold-500);
    color: var(--bn-ink);
    font-size: 10px;
    font-weight: 800;
    display: grid;
    place-items: center;
    line-height: 1;
}

/* Bottom tab bar — the primary navigation on a phone. */
.tabbar {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 50;
    height: var(--nav-height);
    background: var(--bn-surface);
    border-top: 1px solid var(--bn-line);
    display: flex;
    padding-bottom: env(safe-area-inset-bottom);
}

.tabbar a {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    font-size: 10px;
    font-weight: 650;
    color: var(--bn-muted);
    text-decoration: none;
    padding-top: 6px;
}

.tabbar a.is-active {
    color: var(--bn-primary);
}

.tabbar a.is-active .tab-icon {
    background: var(--bn-blue-50);
}

.tab-icon {
    width: 28px;
    height: 24px;
    display: grid;
    place-items: center;
    border-radius: var(--r-full);
}

@media (min-width: 900px) {
    .tabbar { display: none; }
}

/* Desktop sidebar */
.sidenav {
    display: none;
}

@media (min-width: 900px) {
    .sidenav {
        display: block;
        position: sticky;
        top: calc(var(--header-height) + var(--sp-5));
        align-self: start;
    }

    .sidenav a {
        display: flex;
        align-items: center;
        gap: var(--sp-3);
        padding: var(--sp-3) var(--sp-4);
        border-radius: var(--r-md);
        color: var(--bn-ink-soft);
        font-weight: 600;
        font-size: var(--fs-base);
        margin-bottom: 2px;
    }

    .sidenav a:hover {
        background: var(--bn-blue-50);
        color: var(--bn-navy-800);
        text-decoration: none;
    }

    .sidenav a.is-active {
        background: var(--bn-navy-800);
        color: #fff;
    }

    .sidenav-group {
        margin-top: var(--sp-5);
        padding: 0 var(--sp-4) var(--sp-2);
    }
}

.breadcrumb {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
    font-size: var(--fs-sm);
    color: var(--bn-muted);
    margin-bottom: var(--sp-4);
    align-items: center;
}

.breadcrumb a { color: var(--bn-muted); }
.breadcrumb .sep { opacity: 0.5; }

.pager {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    margin-top: var(--sp-6);
}

/* 13. FEED AND CONTENT =================================================== */

.post {
    background: var(--bn-surface);
    border: 1px solid var(--bn-line);
    border-radius: var(--r-lg);
    padding: var(--sp-4);
}

.post.is-official {
    border-color: var(--bn-line);
    border-left: 4px solid var(--bn-gold-500);
    background: linear-gradient(180deg, var(--bn-gold-100) 0%, var(--bn-surface) 40px);
}

.post-head {
    display: flex;
    gap: var(--sp-3);
    align-items: flex-start;
    margin-bottom: var(--sp-3);
}

.post-author {
    font-weight: 650;
    color: var(--bn-navy-800);
}

.post-meta {
    font-size: var(--fs-xs);
    color: var(--bn-muted);
}

.post-body {
    line-height: var(--lh-normal);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.post-actions {
    display: flex;
    gap: var(--sp-1);
    margin-top: var(--sp-3);
    padding-top: var(--sp-3);
    border-top: 1px solid var(--bn-line-soft);
}

.post-action {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    padding: var(--sp-2) var(--sp-3);
    border-radius: var(--r-md);
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--bn-muted);
    background: none;
    border: none;
    cursor: pointer;
}

.post-action:hover {
    background: var(--bn-blue-50);
    color: var(--bn-primary);
    text-decoration: none;
}

.post-action.is-on {
    color: var(--bn-primary);
}

/* Content asset tile */
.asset {
    border: 1px solid var(--bn-line);
    border-radius: var(--r-lg);
    overflow: hidden;
    background: var(--bn-surface);
    display: flex;
    flex-direction: column;
}

.asset-thumb {
    aspect-ratio: 16 / 9;
    background: linear-gradient(135deg, var(--bn-navy-800), var(--bn-blue-600));
    display: grid;
    place-items: center;
    color: var(--bn-gold-400);
    font-size: var(--fs-2xl);
}

.asset-body {
    padding: var(--sp-4);
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}

.share-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: var(--sp-2);
}

.share-btn {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    padding: var(--sp-3);
    border: 1px solid var(--bn-line);
    border-radius: var(--r-md);
    background: var(--bn-surface);
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--bn-ink);
    cursor: pointer;
    text-align: left;
}

.share-btn:hover {
    border-color: var(--bn-blue-400);
    background: var(--bn-blue-50);
    text-decoration: none;
}

.share-note {
    font-size: var(--fs-xs);
    color: var(--bn-muted);
    grid-column: 1 / -1;
}

/* 14. PROGRESS AND SCORE ================================================= */

.progress {
    height: 8px;
    background: var(--bn-line-soft);
    border-radius: var(--r-full);
    overflow: hidden;
}

.progress-bar {
    height: 100%;
    background: var(--bn-green-500);
    border-radius: var(--r-full);
    transition: width 0.3s ease;
}

.progress-lg { height: 12px; }

.score-ring {
    --score: 0;
    width: 96px;
    height: 96px;
    border-radius: var(--r-full);
    display: grid;
    place-items: center;
    background: conic-gradient(
        var(--bn-gold-500) calc(var(--score) * 1%),
        var(--bn-line-soft) 0);
    flex-shrink: 0;
}

.score-ring-inner {
    width: 76px;
    height: 76px;
    border-radius: var(--r-full);
    background: var(--bn-surface);
    display: grid;
    place-items: center;
    text-align: center;
    line-height: 1.1;
}

.score-number {
    font-size: var(--fs-xl);
    font-weight: 800;
    color: var(--bn-navy-800);
    font-variant-numeric: tabular-nums;
}

.score-band {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bn-muted);
}

.band-strong { color: var(--bn-green-500); }
.band-steady { color: var(--bn-blue-500); }
.band-building { color: var(--bn-gold-600); }
.band-weak { color: #C77700; }
.band-needsintervention { color: var(--bn-red-500); }

/* Election countdown */
.countdown {
    display: flex;
    gap: var(--sp-3);
}

.countdown-unit {
    background: var(--bn-navy-800);
    color: #fff;
    border-radius: var(--r-md);
    padding: var(--sp-3) var(--sp-4);
    text-align: center;
    min-width: 64px;
}

.countdown-num {
    font-size: var(--fs-xl);
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

.countdown-label {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--bn-gold-400);
    margin-top: 3px;
}

/* 15. EMPTY, ERROR AND LOADING STATES ==================================== */

.empty {
    text-align: center;
    padding: var(--sp-10) var(--sp-5);
    color: var(--bn-muted);
}

.empty-icon {
    font-size: 40px;
    margin-bottom: var(--sp-3);
    opacity: 0.65;
}

.empty h3 {
    color: var(--bn-ink-soft);
    margin-bottom: var(--sp-2);
}

.empty p {
    max-width: 42ch;
    margin-inline: auto;
    margin-bottom: var(--sp-4);
}

.offline-note {
    display: none;
    background: var(--bn-navy-800);
    color: var(--bn-gold-400);
    text-align: center;
    padding: var(--sp-2);
    font-size: var(--fs-sm);
    font-weight: 600;
}

body.is-offline .offline-note { display: block; }

.skeleton {
    background: linear-gradient(
        90deg, var(--bn-line-soft) 25%, #F6F7F9 50%, var(--bn-line-soft) 75%);
    background-size: 200% 100%;
    animation: skeleton-shimmer 1.4s ease-in-out infinite;
    border-radius: var(--r-sm);
}

@keyframes skeleton-shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

.skeleton-line { height: 12px; margin-bottom: var(--sp-2); }
.skeleton-line.short { width: 40%; }
.skeleton-line.medium { width: 70%; }

.error-page {
    text-align: center;
    padding: var(--sp-16) var(--sp-5);
    max-width: 520px;
    margin-inline: auto;
}

.error-code {
    font-size: var(--fs-4xl);
    font-weight: 800;
    color: var(--bn-line);
    line-height: 1;
}

/* 16. UTILITIES ========================================================== */

.mt-0 { margin-top: 0; }
.mt-2 { margin-top: var(--sp-2); }
.mt-3 { margin-top: var(--sp-3); }
.mt-4 { margin-top: var(--sp-4); }
.mt-6 { margin-top: var(--sp-6); }
.mt-8 { margin-top: var(--sp-8); }
.mb-2 { margin-bottom: var(--sp-2); }
.mb-3 { margin-bottom: var(--sp-3); }
.mb-4 { margin-bottom: var(--sp-4); }
.mb-6 { margin-bottom: var(--sp-6); }

.text-center { text-align: center; }
.text-right { text-align: right; }
.flex-1 { flex: 1; min-width: 0; }
.w-full { width: 100%; }
.hide { display: none; }

@media (max-width: 639px) {
    .hide-mobile { display: none; }
}

@media (min-width: 900px) {
    .hide-desktop { display: none; }
}

.sticky-actions {
    position: sticky;
    bottom: calc(var(--nav-height) + var(--sp-2));
    background: var(--bn-surface);
    border: 1px solid var(--bn-line);
    border-radius: var(--r-lg);
    padding: var(--sp-3);
    box-shadow: var(--sh-lg);
    z-index: 20;
}

@media (min-width: 900px) {
    .sticky-actions { bottom: var(--sp-4); }
}

/* 17. PRINT ============================================================== */

@media print {
    .topbar,
    .tabbar,
    .sidenav,
    .post-actions,
    .sticky-actions,
    .btn {
        display: none !important;
    }

    body {
        background: #fff;
    }

    .card,
    .panel {
        border: 1px solid #ccc;
        box-shadow: none;
        break-inside: avoid;
    }
}

/* Certificates are meant to be printed. */
.certificate {
    border: 3px double var(--bn-navy-800);
    padding: var(--sp-10);
    text-align: center;
    background: var(--bn-canvas-warm);
    border-radius: var(--r-md);
}

.certificate .serial {
    font-family: var(--font-mono);
    letter-spacing: 0.12em;
    color: var(--bn-muted);
}

/* 18. SITE CHROME AND MARKETING SECTIONS ================================= */

/*
   Everything below dresses the pages a visitor sees before they sign in, and
   it is where the template's language actually lives:

     - full-bleed sections alternating white / mist / near-black, 136px apart
     - a headline block of eyebrow + rule + big Work Sans headline
     - pill actions, squared everything else
     - a dark top strip above a white header, and a dark footer below

   The signed-in application reuses the tokens but keeps its own denser
   layout: a section rhythm built for reading does not suit a work queue.
*/

/* --- Sections ---------------------------------------------------------- */

.section {
    padding-block: var(--section-pad);
    background: var(--bn-surface);
    color: var(--bn-ink);
}

.section-sm { padding-block: var(--section-pad-sm); }

.section--mist {
    background: var(--bn-mist);
}

.section--dark {
    background: var(--bn-ink-800);
    color: rgba(255, 255, 255, 0.82);
}

/* The one full-bleed gold block on the page, immediately above the footer.
   After ink, white and blue, it lands as a burst of daylight -- which is
   exactly the moment to ask somebody to join. */
.section--accent {
    background: var(--bn-gold-500);
    color: var(--bn-ink);
}

.section--dark h1,
.section--dark h2,
.section--dark h3,
.section--dark h4 {
    color: #fff;
}

.section--accent h1,
.section--accent h2,
.section--accent h3,
.section--accent h4 {
    color: var(--bn-ink);
}

.section--dark .muted { color: rgba(255, 255, 255, 0.62); }
.section--accent .muted { color: rgba(14, 20, 34, 0.72); }
.section--dark .eyebrow { color: var(--bn-gold-500); }
.section--accent .eyebrow { color: var(--bn-ink); }
.section--dark a:not(.btn) { color: #fff; }
.section--accent a:not(.btn) { color: var(--bn-ink); }
.section--dark .lede { color: rgba(255, 255, 255, 0.78); }

/* Cards sitting on a dark section invert rather than punching a hole in it. */
.section--dark .card {
    background: var(--bn-ink-700);
    border-color: rgba(255, 255, 255, 0.12);
    color: rgba(255, 255, 255, 0.82);
}

.section--dark .card-link:hover { border-color: var(--bn-blue-600); }

/* --- Headline block ---------------------------------------------------- */

.headline {
    max-width: 46rem;
}

.headline .eyebrow { margin-bottom: var(--sp-4); }

.headline h1,
.headline h2 {
    font-size: var(--fs-2xl);
    line-height: 1.1;
}

.headline p {
    margin-top: var(--sp-5);
    font-size: var(--fs-md);
    line-height: var(--lh-loose);
    color: var(--bn-ink-soft);
}

.section--dark .headline p { color: rgba(255, 255, 255, 0.7); }

.headline-center {
    margin-inline: auto;
    text-align: center;
}

.headline-center .eyebrow::before { margin-inline: auto; }

@media (min-width: 768px) {
    .headline h1,
    .headline h2 { font-size: var(--fs-3xl); }
}

/* --- Hero -------------------------------------------------------------- */

/*
   The hero carries the campaign artwork: the elephant assembled out of
   people, on the party's blue.

   The artwork was re-rendered onto the badge's blue, #0802B8, so the mark,
   the header and the photograph are one colour. It is repeated here as a
   background-colour so any crop, any aspect ratio and the moment before the
   image loads all land on the same blue rather than on a grey hole.

   Gold carries the action here, as it does everywhere else. On this much
   saturated blue it is the only accent that does not either disappear or
   vibrate.
*/
.hero {
    position: relative;
    display: flex;
    align-items: center;
    min-height: clamp(30rem, 76vh, 46rem);
    background-color: #0802B8;
    background-repeat: no-repeat;
    background-position: center;
    background-size: cover;
    color: #fff;
    padding-block: calc(var(--section-pad) * 0.75);
    overflow: hidden;

    /* Plain url() first, for anything that cannot parse image-set(). */
    background-image: url("../img/hero-elephant.jpg");
    background-image: -webkit-image-set(
        url("../img/hero-elephant.webp") type("image/webp"),
        url("../img/hero-elephant.jpg") type("image/jpeg"));
    background-image: image-set(
        url("../img/hero-elephant.webp") type("image/webp"),
        url("../img/hero-elephant.jpg") type("image/jpeg"));
}

/* A phone gets the 900px file: a third of the bytes, and no visible difference
   at that size. */
@media (max-width: 899px) {
    .hero {
        background-image: url("../img/hero-elephant.jpg");
        background-image: -webkit-image-set(
            url("../img/hero-elephant-900.webp") type("image/webp"),
            url("../img/hero-elephant.jpg") type("image/jpeg"));
        background-image: image-set(
            url("../img/hero-elephant-900.webp") type("image/webp"),
            url("../img/hero-elephant.jpg") type("image/jpeg"));
        background-position: 72% center;
    }
}

/*
   A scrim from the left. The artwork's field is dark enough to carry white
   type on its own, but the crowd drifts across it at some crop ratios, and a
   headline is not something to leave to the aspect ratio of the viewport.
*/
.hero::before {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(
        100deg,
        rgba(3, 20, 74, 0.88) 0%,
        rgba(4, 26, 96, 0.66) 34%,
        rgba(6, 40, 150, 0.16) 62%,
        rgba(8, 67, 215, 0) 82%);
    pointer-events: none;
}

@media (max-width: 899px) {
    .hero::before {
        background: linear-gradient(
            180deg,
            rgba(3, 20, 74, 0.42) 0%,
            rgba(3, 20, 74, 0.72) 46%,
            rgba(3, 20, 74, 0.92) 100%);
    }
}

.hero > .container { position: relative; z-index: 1; width: 100%; }

/*
   Narrower than a normal headline block, for two reasons: it keeps the type
   inside the strong end of the scrim rather than drifting over the elephant's
   face, and it breaks the slogan onto three lines -- which is how the artwork
   set it in the first place.
*/
.hero .headline { max-width: 33rem; }

.hero h1 {
    font-size: clamp(2.25rem, 6.4vw, 3.75rem);
    line-height: 1;
    color: #fff;
    text-wrap: balance;
}

.hero .eyebrow { color: var(--bn-gold-500); }
.hero .eyebrow::before { background: var(--bn-gold-500); }

.hero p {
    color: rgba(255, 255, 255, 0.86);
    font-size: var(--fs-md);
    line-height: var(--lh-loose);
    max-width: 42ch;
    text-shadow: 0 1px 12px rgba(3, 20, 74, 0.5);
}

.hero .btn {
    background: var(--bn-gold-500);
    border-color: var(--bn-gold-500);
    color: var(--bn-ink);
    box-shadow: 0 10px 30px rgba(4, 20, 70, 0.35);
}

.hero .btn:hover {
    background: #fff;
    border-color: #fff;
    color: var(--bn-ink);
}

.hero .btn-outline {
    background: transparent;
    border-color: rgba(255, 255, 255, 0.8);
    color: #fff;
    box-shadow: none;
}

.hero .btn-outline:hover {
    background: #fff;
    border-color: #fff;
    color: var(--bn-blue-700);
}

/* --- Counters ---------------------------------------------------------- */

.counter-row {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sp-8) var(--sp-4);
}

@media (min-width: 768px) {
    .counter-row { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.counter-value {
    font-family: var(--font-display);
    font-size: clamp(2.25rem, 6vw, 3.25rem);
    font-weight: 600;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    color: var(--bn-blue-600);
}

.section--dark .counter-value,
.hero .counter-value { color: #fff; }

.counter-label {
    margin-top: var(--sp-3);
    font-size: var(--fs-sm);
    font-weight: 600;
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    color: var(--bn-muted);
}

.hero .counter-label,
.section--dark .counter-label { color: rgba(255, 255, 255, 0.6); }

.counter-value + .counter-label::before {
    content: "";
    display: block;
    width: 28px;
    height: 2px;
    margin-bottom: var(--sp-3);
    background: var(--bn-blue-600);
}

.hero .counter-value + .counter-label::before { background: #fff; }

/* --- Service block: icon, title, text ---------------------------------- */

.service {
    display: flex;
    gap: var(--sp-4);
    align-items: flex-start;
}

.service-icon {
    flex-shrink: 0;
    width: 56px;
    height: 56px;
    display: grid;
    place-items: center;
    border: 2px solid var(--bn-blue-600);
    border-radius: var(--r-full);
    color: var(--bn-blue-600);
}

.section--dark .service-icon,
.site-footer .service-icon {
    border-color: rgba(255, 255, 255, 0.35);
    color: #fff;
}

.service-title {
    font-family: var(--font-display);
    font-size: var(--fs-sm);
    font-weight: 600;
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    color: var(--bn-ink);
}

.section--dark .service-title { color: #fff; }

.service-text {
    margin-top: var(--sp-2);
    color: var(--bn-ink-soft);
    line-height: var(--lh-loose);
}

.section--dark .service-text,
.site-footer .service-text { color: rgba(255, 255, 255, 0.68); }

/* Stacked variant, for a grid of three or four reasons to join. */
.service-stack {
    display: block;
    padding: var(--sp-8) var(--sp-6);
    background: var(--bn-surface);
    border: 1px solid var(--bn-line);
    border-radius: var(--r-lg);
    box-shadow: var(--sh-sm);
    height: 100%;
    transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
}

/* A small lift on hover. Not decoration: it is the affordance that tells
   somebody raised on apps that a surface is a thing they can act on. */
.service-stack:hover {
    transform: translateY(-3px);
    box-shadow: var(--sh-md);
    border-color: var(--bn-blue-200);
}

.service-stack .service-icon { margin-bottom: var(--sp-5); }

.service-stack h3 { font-size: var(--fs-lg); }

/* --- Numbered steps ---------------------------------------------------- */

.step-num {
    font-family: var(--font-display);
    font-size: var(--fs-3xl);
    font-weight: 600;
    line-height: 1;
    color: var(--bn-line);
}

.section--dark .step-num { color: rgba(255, 255, 255, 0.22); }

/* --- Issue bars: the template's "Top Issues" block --------------------- */

.issue {
    padding-block: var(--sp-4);
    border-bottom: 1px solid var(--bn-line);
}

.section--dark .issue { border-bottom-color: rgba(255, 255, 255, 0.12); }

.issue-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-4);
    margin-bottom: var(--sp-3);
}

.issue-name {
    font-family: var(--font-display);
    font-size: var(--fs-md);
    font-weight: 600;
}

.issue-value {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: var(--bn-blue-400);
}

.issue-track {
    height: 6px;
    background: var(--bn-line);
    border-radius: var(--r-full);
    overflow: hidden;
}

.section--dark .issue-track { background: rgba(255, 255, 255, 0.14); }

.issue-fill {
    height: 100%;
    background: var(--bn-blue-600);
    border-radius: var(--r-full);
}

/* Blue on ink is barely a bar. Gold is, and it ties the measure to the action
   colour: this is what the movement is spending its effort on. */
.section--dark .issue-fill { background: var(--bn-gold-500); }
.section--dark .issue-value { color: var(--bn-gold-500); }

/* --- Site header ------------------------------------------------------- */

.site-topbar {
    background: var(--bn-ink-800);
    color: rgba(255, 255, 255, 0.7);
    font-size: var(--fs-sm);
}

.site-topbar .container {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    flex-wrap: wrap;
    min-height: 46px;
    padding-block: var(--sp-2);
}

.site-topbar a { color: rgba(255, 255, 255, 0.7); }
.site-topbar a:hover { color: #fff; text-decoration: none; }

.site-topbar strong {
    color: #fff;
    font-weight: 600;
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    font-size: var(--fs-xs);
}

.site-header {
    position: sticky;
    top: 0;
    z-index: 40;
    background: var(--bn-surface);
    border-bottom: 1px solid var(--bn-line);
}

.site-header .container {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    min-height: 76px;
}

/*
   The logo is a circular badge, and its own ring already reads BAWUMIA
   NATION. That lettering is legible at about 80px and not below, so at header
   size the badge works as a mark and the name is set beside it as live text.
   Printing the words twice would be redundant; printing them once, illegibly,
   would be worse.

   Two files rather than one filtered: the badge as drawn for light grounds,
   and one with the blue lifted to white for dark ones. `filter: invert()`
   would take the red with it and turn it cyan.
*/
.site-brand {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-3);
    flex-shrink: 0;
    color: var(--bn-ink);
    font-family: var(--font-display);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    line-height: 1.05;
}

.site-brand:hover { text-decoration: none; color: var(--bn-ink); }

.site-logo {
    display: block;
    width: 38px;
    height: 38px;
    flex-shrink: 0;
}

/* The name, set in two stacked lines so it occupies the badge's height
   instead of running the header wide on a handset. */
.site-wordmark {
    display: none;
    font-size: var(--fs-sm);
}

.site-wordmark span { display: block; }

.site-wordmark span:last-child { color: var(--bn-blue-600); }

/* 360px, not 420: the badge plus the name plus the join button plus the menu
   measure about 280px, so the brand name still fits on the narrowest handset
   anyone actually carries. Hiding it there would drop the movement's name from
   the screen most members use. */
@media (min-width: 360px) {
    .site-wordmark { display: block; }
}

@media (min-width: 640px) {
    .site-logo { width: 46px; height: 46px; }
    .site-wordmark { font-size: var(--fs-base); }
}

/* On a dark ground the name flips; the badge swaps file rather than colour. */
.topbar .site-brand,
.site-footer .site-brand { color: #fff; }

.topbar .site-brand:hover,
.site-footer .site-brand:hover { color: #fff; }

.topbar .site-wordmark span:last-child,
.site-footer .site-wordmark span:last-child { color: var(--bn-blue-200); }

/* The app header is denser than the marketing one. */
.topbar .site-logo { width: 32px; height: 32px; }

.site-nav {
    display: none;
    align-items: center;
    gap: var(--sp-1);
}

@media (min-width: 900px) {
    .site-nav { display: flex; }
}

.site-nav a {
    display: block;
    padding: var(--sp-3) var(--sp-4);
    font-family: var(--font-display);
    font-size: var(--fs-sm);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--bn-ink);
}

.site-nav a:hover,
.site-nav a.is-active {
    color: var(--bn-blue-600);
    text-decoration: none;
}

.site-header-actions {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
}

/*
   The mobile menu is a <details> element, so it opens and closes without a
   line of JavaScript. That matters more than usual here: the policy forbids
   third-party script, and a handset that has not finished executing our own
   should still be able to reach the navigation.
*/
.site-menu > summary {
    display: grid;
    place-items: center;
    width: 46px;
    height: 46px;
    cursor: pointer;
    color: var(--bn-ink);
    list-style: none;
}

.site-menu > summary::-webkit-details-marker { display: none; }

.site-menu[open] > summary { color: var(--bn-blue-600); }

.site-menu-panel {
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    background: var(--bn-surface);
    border-bottom: 1px solid var(--bn-line);
    border-radius: 0 0 var(--r-lg) var(--r-lg);
    box-shadow: var(--sh-md);
    padding: var(--sp-3) 0;
}

.site-menu-panel a {
    display: block;
    padding: var(--sp-4) var(--sp-5);
    font-family: var(--font-display);
    font-size: var(--fs-sm);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--bn-ink);
    border-bottom: 1px solid var(--bn-line-soft);
}

.site-menu-panel a:last-child { border-bottom: none; }

.site-menu-panel a:hover {
    color: var(--bn-blue-600);
    text-decoration: none;
}

@media (min-width: 900px) {
    .site-menu { display: none; }
}

/* --- Site footer ------------------------------------------------------- */

.site-footer {
    background: var(--bn-ink-800);
    color: rgba(255, 255, 255, 0.62);
}

.site-footer-main { padding-block: var(--section-pad-sm); }

.site-footer h2,
.site-footer h3,
.site-footer .service-title { color: #fff; }

.site-footer a { color: rgba(255, 255, 255, 0.62); }
.site-footer a:hover { color: #fff; }

.site-footer-bottom {
    border-top: 1px solid rgba(255, 255, 255, 0.12);
    padding-block: var(--sp-6);
}

.site-footer-bottom .container {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    flex-wrap: wrap;
}

.site-footer-nav {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-5);
    font-family: var(--font-display);
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
}

/* --- Call-to-action strip ---------------------------------------------- */

.cta-strip .container {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-6);
    flex-wrap: wrap;
}

.cta-strip h2 {
    font-size: var(--fs-xl);
    margin: 0;
}

@media (min-width: 768px) {
    .cta-strip h2 { font-size: var(--fs-2xl); }
}

/* --- Split with a media panel ------------------------------------------ */

.feature-split {
    display: grid;
    gap: var(--sp-8);
    align-items: center;
}

@media (min-width: 900px) {
    .feature-split { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-16); }
}
