/* ============================================
   barrievotes.ca — shared styles

   Design intent: read as a public utility, not a campaign. High contrast,
   generous line length limits, one accent used only for wayfinding, and no
   colour that codes partisan. Light and dark both first-class.

   Sections:
     1. Tokens
     2. Reset + base
     3. Layout
     4. Header + nav
     5. Breadcrumbs
     6. Stub pages
     7. Section indexes
     8. Home
     9. Footer
    10. Utilities
   ============================================ */

/* ── 1. Tokens ───────────────────────────────────────────────────────────── */
:root {
    /* Accent: a slate teal. Chosen to sit clear of federal and provincial
       party palettes — red, true blue, orange, and green all carry meaning
       on a ballot-adjacent site. */
    --accent:        #0b6b6b;
    --accent-hover:  #085252;
    --accent-soft:   #e3f2f1;

    --ink:           #14181b;
    --ink-2:         #3d474e;
    --ink-3:         #626d75;

    --bg:            #ffffff;
    --bg-2:          #f5f7f8;
    --bg-3:          #eceff1;

    --line:          #d6dbde;
    --line-strong:   #b3bbc0;

    /* Status hues. Distinct in both themes, and distinguishable without
       relying on colour alone — every status also carries a text label. */
    --st-live:       #0b6b6b;
    --st-live-bg:    #e3f2f1;
    --st-progress:   #1f5f9e;
    --st-progress-bg:#e5eff8;
    --st-waiting:    #8a5a00;
    --st-waiting-bg: #fbf0d9;
    --st-blocked:    #5b5266;
    --st-blocked-bg: #efecf3;

    /* Seventh categorical chart hue — the six status colours run out on the
       budget-split and renewal-gap stacks, and wrapping into an accent
       variant made the last segment read as the first. */
    --chart-7:       #a1583c;
    /* Eighth categorical hue — the career timelines give each office CLASS
       (councillor, mayor, trustee, MP, MPP) a fixed colour, which needs one
       more hue than the status set provides. */
    --chart-8:       #9c5a86;

    --radius:        6px;
    --wrap:          72rem;
    --measure:       38rem;   /* comfortable line length for body copy */

    --shadow: 0 1px 2px rgba(20, 24, 27, .06), 0 2px 8px rgba(20, 24, 27, .04);
}

@media (prefers-color-scheme: dark) {
    :root {
        --accent:        #4fc4bd;
        --accent-hover:  #7ad8d2;
        --accent-soft:   #10312f;

        --ink:           #eef2f4;
        --ink-2:         #b9c3c9;
        --ink-3:         #8b979e;

        --bg:            #0e1214;
        --bg-2:          #161c1f;
        --bg-3:          #1e262a;

        --line:          #2b3438;
        --line-strong:   #3f4b51;

        --st-live:       #4fc4bd;
        --st-live-bg:    #10312f;
        --st-progress:   #7fb3e8;
        --st-progress-bg:#152633;
        --st-waiting:    #e0b354;
        --st-waiting-bg: #302713;
        --st-blocked:    #b6a8c9;
        --st-blocked-bg: #241f2b;

        --shadow: none;
    }
}

/* ── 2. Reset + base ─────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

html {
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

body {
    margin: 0;
    background: var(--bg);
    color: var(--ink);
    font-family: var(--font-text);
    font-size: 1.0625rem;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

h1, h2, h3, h4 { line-height: 1.25; margin: 0 0 .5em; font-weight: 650; letter-spacing: -.01em; }
h1 { font-size: clamp(1.75rem, 1.3rem + 2vw, 2.5rem); }
h2 { font-size: clamp(1.3rem, 1.1rem + 1vw, 1.6rem); }
h3 { font-size: 1.125rem; }

p  { margin: 0 0 1rem; }
ul, ol { margin: 0 0 1rem; padding-left: 1.25rem; }

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: .15em; }
a:hover { color: var(--accent-hover); }

:focus-visible {
    outline: 3px solid var(--accent);
    outline-offset: 2px;
    border-radius: 2px;
}

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

.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    background: var(--accent);
    color: #fff;
    padding: .65rem 1rem;
    z-index: 100;
}
.skip-link:focus { left: 0; }

/* ── 3. Layout ───────────────────────────────────────────────────────────── */
.wrap {
    width: 100%;
    max-width: var(--wrap);
    margin-inline: auto;
    padding-inline: 1.25rem;
}

main {
    flex: 1 0 auto;
    width: 100%;
    max-width: var(--wrap);
    margin-inline: auto;
    padding: 1.5rem 1.25rem 4rem;
}

/* Anything wide scrolls inside itself so the page body never scrolls
   sideways on a phone. */
.scroll-x {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* ── 4. Header + nav ─────────────────────────────────────────────────────── */
.site-head {
    border-bottom: 1px solid var(--line);
    background: var(--bg);
    position: sticky;
    top: 0;
    z-index: 20;
}
.site-head .wrap {
    display: flex;
    align-items: center;
    gap: 1rem;
    min-height: 4rem;
    flex-wrap: wrap;
}

.brand {
    display: flex;
    align-items: center;
    gap: .6rem;
    text-decoration: none;
    color: var(--ink);
    margin-right: auto;
    padding: .5rem 0;
    /* Pin the first header row's height. The wrap's 4rem minimum is
       distributed by align-content across flex LINES, so when the mobile nav
       opens onto a second line the brand row loses its stretched share and
       everything shifts up a couple of pixels. A fixed-height tallest item
       keeps the row identical whether the menu is open or not. */
    min-height: 4rem;
}
.brand-mark { line-height: 0; }
.brand-mark img { display: block; width: 28px; height: 28px; }
.brand-text { display: flex; flex-direction: column; }
.brand-name { font-weight: 700; font-size: 1.0625rem; letter-spacing: -.015em; }
.brand-sub  { font-size: .75rem; color: var(--ink-3); letter-spacing: .01em; }

.nav-toggle {
    display: flex;
    align-items: center;
    gap: .5rem;
    background: none;
    border: 1px solid var(--line-strong);
    border-radius: var(--radius);
    color: var(--ink);
    font: inherit;
    font-size: .9rem;
    padding: .45rem .7rem;
    cursor: pointer;
}
.nav-toggle-bars { display: inline-flex; flex-direction: column; gap: 3px; }
.nav-toggle-bars span {
    display: block; width: 16px; height: 2px;
    background: currentColor; border-radius: 1px;
}

.primary-nav { display: none; width: 100%; }
.primary-nav.is-open { display: block; }
.primary-nav ul {
    list-style: none;
    margin: 0 0 .75rem;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .125rem;
}
.primary-nav a {
    display: block;
    padding: .6rem .5rem;
    text-decoration: none;
    color: var(--ink-2);
    border-radius: var(--radius);
    font-weight: 550;
}
.primary-nav a:hover { background: var(--bg-2); color: var(--ink); }
.primary-nav a.is-current { color: var(--accent); background: var(--accent-soft); }

@media (min-width: 48rem) {
    .nav-toggle { display: none; }
    .primary-nav { display: block; width: auto; }
    .primary-nav ul { flex-direction: row; gap: .25rem; margin-bottom: 0; }
    .primary-nav a { padding: .5rem .75rem; }
}

/* ── 5. Breadcrumbs ──────────────────────────────────────────────────────── */
.crumbs { margin-bottom: 1.5rem; font-size: .875rem; }
.crumbs ol {
    list-style: none; margin: 0; padding: 0;
    display: flex; flex-wrap: wrap; gap: .35rem;
}
.crumbs li + li::before { content: "›"; color: var(--ink-3); margin-right: .35rem; }
.crumbs a { color: var(--ink-3); }
.crumbs a:hover { color: var(--accent); }
.crumbs [aria-current] { color: var(--ink-2); }

/* ── 6. Stub pages ───────────────────────────────────────────────────────── */
.stub { max-width: 44rem; }

.stub-flag {
    display: inline-block;
    margin: 0 0 1rem;
    padding: .3rem .6rem;
    border-radius: 100px;
    font-size: .75rem;
    font-weight: 650;
    letter-spacing: .02em;
    text-transform: uppercase;
}
.stub-flag[data-status="live"]                            { color: var(--st-live);     background: var(--st-live-bg); }
.stub-flag[data-status="in-progress"]                     { color: var(--st-progress); background: var(--st-progress-bg); }
.stub-flag[data-status="awaiting-source"]                 { color: var(--st-waiting);  background: var(--st-waiting-bg); }
.stub-flag[data-status="blocked-until-nominations-close"],
.stub-flag[data-status="blocked-until-election-day"]      { color: var(--st-blocked);  background: var(--st-blocked-bg); }

.stub-lede {
    font-size: 1.1875rem;
    line-height: 1.55;
    color: var(--ink-2);
    max-width: var(--measure);
}

.stub-body { margin-top: 2rem; }

.stub-facts {
    margin: 0 0 1.5rem;
    border-top: 1px solid var(--line);
}
.stub-facts > div {
    display: grid;
    gap: .2rem;
    padding: 1rem 0;
    border-bottom: 1px solid var(--line);
}
.stub-facts dt {
    font-size: .75rem;
    font-weight: 650;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--ink-3);
}
.stub-facts dd { margin: 0; color: var(--ink-2); max-width: var(--measure); }

@media (min-width: 40rem) {
    .stub-facts > div { grid-template-columns: 12rem 1fr; gap: 1.5rem; align-items: start; }
}

.stub-promise {
    background: var(--bg-2);
    border-left: 3px solid var(--accent);
    padding: 1rem 1.15rem;
    border-radius: 0 var(--radius) var(--radius) 0;
    color: var(--ink-2);
    font-size: .9375rem;
    margin: 0;
}

.stub-siblings { margin-top: 3rem; padding-top: 1.5rem; border-top: 1px solid var(--line); }
.stub-siblings h2 { font-size: .8125rem; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-3); }
.stub-siblings ul {
    list-style: none; padding: 0; margin: 0;
    display: flex; flex-wrap: wrap; gap: .5rem 1rem;
}
.stub-siblings li { display: flex; align-items: center; gap: .4rem; }

.pill {
    display: inline-block;
    white-space: nowrap;
    font-size: .6875rem; font-weight: 650; text-transform: uppercase;
    letter-spacing: .03em; padding: .1rem .4rem; border-radius: 3px;
}
.pill-live { color: var(--st-live); background: var(--st-live-bg); }

/* ── 7. Section indexes ──────────────────────────────────────────────────── */
.section-head { max-width: var(--measure); margin-bottom: 2.5rem; }
.section-lede { font-size: 1.1875rem; line-height: 1.55; color: var(--ink-2); }

.group-head {
    font-size: .8125rem;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--ink-3);
    margin: 2.5rem 0 1rem;
    padding-bottom: .5rem;
    border-bottom: 1px solid var(--line);
}
.group-head:first-of-type { margin-top: 0; }

.card-list {
    list-style: none; padding: 0; margin: 0 0 1rem;
    display: grid; gap: 1rem;
    grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
}
.card {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 1.15rem;
    background: var(--bg);
    display: flex;
    flex-direction: column;
    gap: .35rem;
}
.card:hover { border-color: var(--line-strong); box-shadow: var(--shadow); }
.card h3 { margin: 0; font-size: 1.0625rem; }
.card h3 a { text-decoration: none; }
.card h3 a:hover { text-decoration: underline; }
.card p { margin: 0; font-size: .9rem; color: var(--ink-2); }
.card-status {
    margin-top: auto !important;
    padding-top: .5rem;
    font-size: .75rem !important;
    font-weight: 600;
}
.card-status[data-status="live"]                            { color: var(--st-live) !important; }
.card-status[data-status="in-progress"]                     { color: var(--st-progress) !important; }
.card-status[data-status="awaiting-source"]                 { color: var(--st-waiting) !important; }
.card-status[data-status="blocked-until-nominations-close"],
.card-status[data-status="blocked-until-election-day"]      { color: var(--st-blocked) !important; }

/* ── 8. Home ─────────────────────────────────────────────────────────────── */
.hero { max-width: 42rem; margin-bottom: 1rem; }
.hero h1 { margin-bottom: .5rem; }
.hero-lede { font-size: 1.25rem; line-height: 1.5; color: var(--ink-2); }

.notice {
    border: 1px solid var(--line);
    border-left: 3px solid var(--st-waiting);
    background: var(--bg-2);
    border-radius: 0 var(--radius) var(--radius) 0;
    padding: 1rem 1.15rem;
    margin: 2rem 0;
    max-width: 42rem;
}
.notice h2 { font-size: 1rem; margin-bottom: .35rem; }
.notice p:last-child { margin-bottom: 0; }

.pillars {
    list-style: none; padding: 0; margin: 2.5rem 0 0;
    display: grid; gap: 1.25rem;
    grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
}
.pillar {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 1.6rem 1.5rem;
    display: flex;
    flex-direction: column;
    gap: .4rem;
}
.pillar h2 { font-size: 1.3rem; margin-bottom: 0; }
.pillar h2 a { text-decoration: none; }
.pillar h2 a:hover { text-decoration: underline; }
.pillar p { margin: 0; font-size: .9375rem; color: var(--ink-2); }
/* The live figure on each card — what is behind the door, before the click. */
.pillar p.pillar-stat {
    margin-top: auto;
    padding-top: .6rem;
    font-weight: 650;
    color: var(--accent);
    font-variant-numeric: tabular-nums;
}

/* ── 9. Footer ───────────────────────────────────────────────────────────── */
.site-foot {
    flex-shrink: 0;
    border-top: 1px solid var(--line);
    background: var(--bg-2);
    padding: 2.5rem 0 2rem;
    font-size: .875rem;
}
.foot-cols {
    display: grid;
    gap: 1.75rem;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    margin-bottom: 2rem;
}
.foot-col h2 { font-size: .8125rem; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-3); margin-bottom: .6rem; }
.foot-col h2 a { color: inherit; text-decoration: none; }
.foot-col h2 a:hover { color: var(--accent); }
.foot-col ul { list-style: none; padding: 0; margin: 0; display: grid; gap: .3rem; }
.foot-col a { color: var(--ink-2); text-decoration: none; }
.foot-col a:hover { color: var(--accent); text-decoration: underline; }

.foot-meta { border-top: 1px solid var(--line); padding-top: 1.5rem; }
.foot-mission { color: var(--ink-3); max-width: 48rem; font-size: .8125rem; line-height: 1.55; }
.foot-build { color: var(--ink-3); font-size: .8125rem; margin: 0; display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; }
.foot-build a { color: var(--ink-2); }
.foot-build .sep { color: var(--line-strong); }
.build-status { font-variant-numeric: tabular-nums; }

/* ── 10. Utilities ───────────────────────────────────────────────────────── */
.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;
}
.measure { max-width: var(--measure); }
/* The About page is disclosure prose, not data commentary: it reads better
   in longer lines than the narrow measure the data pages use. */
.about-page .measure { max-width: 54rem; }

/* ── 11. Candidates ──────────────────────────────────────────────────────── */

/* Provenance banner. Appears on every candidate view. The list is a moving
   target until nominations close, so the date and the uncertified status are
   part of the content, not a disclaimer tucked at the bottom. */
.provenance {
    border: 1px solid var(--line);
    border-left: 3px solid var(--st-waiting);
    background: var(--bg-2);
    border-radius: 0 var(--radius) var(--radius) 0;
    padding: 1rem 1.15rem;
    margin: 0 0 2.5rem;
    max-width: 46rem;
}
.provenance-lead { margin-bottom: .5rem; }
.provenance-src  { margin: 0; font-size: .875rem; color: var(--ink-3); }
.provenance-src a { color: var(--ink-2); }

/* Jump nav — ward numbers abbreviated so 12 targets fit on a phone. */
.jump {
    display: flex; flex-wrap: wrap; gap: .4rem;
    margin: 0 0 2.5rem;
}
.jump a {
    display: inline-block;
    padding: .3rem .6rem;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    font-size: .8125rem;
    text-decoration: none;
    color: var(--ink-2);
}
.jump a:hover { border-color: var(--accent); color: var(--accent); }

.race { margin: 0 0 2.5rem; scroll-margin-top: 5rem; }
.race h2 {
    display: flex; align-items: baseline; gap: .6rem;
    padding-bottom: .5rem;
    border-bottom: 1px solid var(--line);
}
.race-count {
    font-size: .8125rem; font-weight: 600;
    color: var(--ink-3);
    font-variant-numeric: tabular-nums;
}
.race-note {
    font-size: .875rem;
    color: var(--st-waiting);
    margin: .75rem 0 0;
}

.board { margin: 0 0 2.5rem; }
.board h3 { display: flex; flex-wrap: wrap; align-items: baseline; gap: .5rem; margin-bottom: .25rem; }
.board-kind {
    font-size: .75rem; font-weight: 600; text-transform: uppercase;
    letter-spacing: .04em; color: var(--ink-3);
    background: var(--bg-3); padding: .1rem .4rem; border-radius: 3px;
}
.board h4 {
    font-size: .8125rem; text-transform: uppercase; letter-spacing: .05em;
    color: var(--ink-3); margin: 1.25rem 0 .5rem;
}

.cand-list {
    list-style: none; padding: 0; margin: 1rem 0 0;
    display: grid; gap: .75rem;
    grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
}
.cand {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: .9rem 1rem;
}
.cand-name { font-weight: 650; margin: 0 0 .15rem; display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; }
.cand-filed { font-size: .75rem; color: var(--ink-3); margin: 0 0 .5rem; }
.cand-links { list-style: none; padding: 0; margin: 0; display: grid; gap: .15rem; font-size: .8125rem; }
.cand-links a { word-break: break-word; }
.cand-social { color: var(--ink-3); }

/* A withdrawal stays on the page. Removing the name would make it look like
   the person was never there, and the record is the point. */
.cand-withdrawn { opacity: .6; }
.cand-withdrawn .cand-name { text-decoration: line-through; text-decoration-thickness: 1px; }
.pill-withdrawn { color: var(--st-blocked); background: var(--st-blocked-bg); text-decoration: none; }

/* Incumbency. Two distinct states, because the ward redraw makes a single
   "Incumbent" badge inaccurate: someone can sit on council today and be running
   in a differently-numbered ward. The detail line carries the qualification —
   a badge alone would imply a seat continuity the boundary change broke. */
.pill-incumbent { color: var(--st-progress); background: var(--st-progress-bg); }
.cand-incumbent { border-color: var(--st-progress); }
.cand-incumbent-note {
    font-size: .75rem;
    color: var(--st-progress);
    margin: 0 0 .35rem;
}

/* Acclamation warning. Deliberately prominent: a race with one candidate is on
   track to be decided without anyone voting, and that is precisely the thing a
   reader would never learn from a bare list of names. */
.acclaim-warn {
    border: 1px solid var(--st-waiting);
    border-left-width: 3px;
    background: var(--st-waiting-bg);
    border-radius: 0 var(--radius) var(--radius) 0;
    padding: .9rem 1.1rem;
    margin: 1rem 0 0;
    max-width: 46rem;
    font-size: .9375rem;
}
.acclaim-head {
    font-weight: 650;
    color: var(--st-waiting);
    margin: 0 0 .35rem;
}
.acclaim-warn p { margin: 0 0 .5rem; }
.acclaim-warn p:last-child { margin-bottom: 0; }
.acclaim-src { font-size: .8125rem; color: var(--ink-3); }

/* Inline acclamation flag: sits INSIDE the candidate list, directly above the
   one candidate it concerns, so the warning and the name read as one unit. */
.acclaim-flag {
    border: 1px solid var(--st-waiting);
    border-left-width: 3px;
    background: var(--st-waiting-bg);
    border-radius: 0 var(--radius) var(--radius) 0;
    padding: .7rem .95rem;
    font-size: .875rem;
    list-style: none;
}
.acclaim-flag .acclaim-head { margin: 0 0 .25rem; }
.acclaim-flag p { margin: 0; max-width: var(--measure); }

/* ── 12. Content pages ───────────────────────────────────────────────────── */
.data-page h2 { margin-top: 2.5rem; }
.data-page h2:first-of-type { margin-top: 2rem; }

blockquote.quotes {
    margin: 1.25rem 0;
    padding: .25rem 0 .25rem 1.15rem;
    border-left: 3px solid var(--line-strong);
    max-width: var(--measure);
}
blockquote.quotes p { color: var(--ink-2); font-style: italic; }
blockquote.quotes p:last-child { margin-bottom: 0; }
blockquote.quotes strong { font-style: normal; color: var(--ink); }

/* Numbered walkthroughs. Counter rather than <ol> markers so the number can
   sit beside a heading. */
.steps { list-style: none; counter-reset: step; padding: 0; margin: 2rem 0; max-width: 46rem; }
.steps > li {
    counter-increment: step;
    position: relative;
    padding: 0 0 1.5rem 3rem;
    border-left: 2px solid var(--line);
    margin-left: 1rem;
}
.steps > li:last-child { border-left-color: transparent; padding-bottom: 0; }
.steps > li::before {
    content: counter(step);
    position: absolute; left: -1.05rem; top: 0;
    width: 2rem; height: 2rem;
    display: grid; place-items: center;
    background: var(--accent); color: #fff;
    border-radius: 50%;
    font-size: .875rem; font-weight: 700;
    font-variant-numeric: tabular-nums;
}
@media (prefers-color-scheme: dark) { .steps > li::before { color: var(--bg); } }
.steps h2 { font-size: 1.125rem; margin: .15rem 0 .4rem; }
.steps p { margin-bottom: .6rem; }
.steps p:last-child { margin-bottom: 0; }
.steps .note, p.note {
    font-size: .875rem; color: var(--ink-3);
    border-left: 2px solid var(--line); padding-left: .75rem;
}

/* Headline figures. Tabular so a row of them lines up. */
.stat-row {
    list-style: none; padding: 0;
    margin: 0 0 1.5rem;
    display: grid; gap: 1rem;
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    max-width: 46rem;
}
.stat-row li {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: .9rem 1rem;
}
.stat-value {
    display: block;
    font-size: 1.75rem; font-weight: 700; line-height: 1.1;
    letter-spacing: -.02em;
    color: var(--accent);
}
.stat-label { display: block; font-size: .8125rem; color: var(--ink-3); margin-top: .2rem; }

/* A caution that belongs beside the data, not in a footnote. */
.warn-note {
    border: 1px solid var(--st-waiting);
    border-left-width: 3px;
    background: var(--st-waiting-bg);
    border-radius: 0 var(--radius) var(--radius) 0;
    padding: .9rem 1.1rem;
    margin: 1.5rem 0;
    max-width: 46rem;
    font-size: .9375rem;
}
.warn-note p:last-child { margin-bottom: 0; }

.table-note {
    font-size: .875rem; color: var(--ink-3);
    max-width: var(--measure); margin: -.25rem 0 2rem;
}

/* Results table styling lives in assets/data-tables.css — it loads after this
   file, so table rules there win cleanly instead of relying on selector weight. */

/* ── 13. Profiles and race context ───────────────────────────────────────── */
.profile h2 { margin-top: 2.5rem; }
.profile h3 { margin-top: 2rem; font-size: 1rem; color: var(--ink-2); }
.profile-links { font-size: .9375rem; margin-bottom: .75rem; }

/* The context block sits between the candidate list and the page footer, so it
   needs a visible boundary without competing with the h1. */
.race-context {
    margin-top: 3rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--line);
}
.context-head {
    font-size: .8125rem;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--ink-3);
    margin-bottom: 1rem;
}

/* Previous/next navigation between election pages. */
.year-nav {
    display: flex; flex-wrap: wrap; gap: 1rem;
    align-items: center; justify-content: space-between;
    margin-top: 3rem; padding-top: 1.5rem;
    border-top: 1px solid var(--line);
    font-size: .9375rem;
}
.year-nav .year-index { color: var(--ink-3); }

/* ── 14. Ward lookup ─────────────────────────────────────────────────────── */
/* Plain server-rendered form — no JavaScript. Someone may be loading this on a
   bad connection outside a voting location. */
.ward-form {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--bg-2);
    padding: 1.25rem;
    margin: 0 0 2rem;
    max-width: 42rem;
}
.ward-form label { display: block; font-weight: 650; margin-bottom: .5rem; }
.ward-form-row { display: flex; flex-wrap: wrap; gap: .6rem; }
.ward-form input[type="text"] {
    flex: 1 1 16rem;
    min-width: 0;
    font: inherit;
    padding: .6rem .75rem;
    border: 1px solid var(--line-strong);
    border-radius: var(--radius);
    background: var(--bg);
    color: var(--ink);
}
.ward-form button {
    font: inherit; font-weight: 650;
    padding: .6rem 1.1rem;
    border: 0; border-radius: var(--radius);
    background: var(--accent); color: #fff;
    cursor: pointer;
}
@media (prefers-color-scheme: dark) { .ward-form button { color: var(--bg); } }
.ward-form button:hover { background: var(--accent-hover); }
.ward-form-note { font-size: .8125rem; color: var(--ink-3); margin: .75rem 0 0; }

/* Everything on the lookup page shares the form's column width — the page
   otherwise mixes 38/42/46rem text with full-width tables, which reads as
   three different pages stacked. */
.ward-page .table-wrap,
.ward-page .card-list,
.ward-page .warn-note,
.ward-page .notice,
.ward-page .stat-row { max-width: 42rem; }

/* The answer. Large because it is the single thing the visitor came for. */
.ward-result {
    border: 1px solid var(--accent);
    border-left-width: 3px;
    border-radius: 0 var(--radius) var(--radius) 0;
    background: var(--accent-soft);
    padding: 1.25rem;
    margin: 0 0 1.5rem;
    max-width: 42rem;
}
.ward-result-lead { margin: 0; font-size: .9375rem; color: var(--ink-2); }
.ward-result-ward {
    margin: .1rem 0;
    font-size: clamp(2rem, 1.4rem + 3vw, 2.75rem);
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -.02em;
    color: var(--accent);
}
.ward-result-sub { margin: 0; font-size: .875rem; color: var(--ink-3); }

/* When two sections share a footer column (Charts above About), space the
   second heading off the first list. */
.foot-col ul + h2 { margin-top: 1.1rem; }
/* Column one carries three shelves; give them room to read as three. */
.foot-col-stacked ul + h2 { margin-top: 2rem; }
