﻿/* ============================================================
   DataCenter — shell stylesheet
   Served to all 32 state hosts as _content/DataCenter.Shared/app.css.
   ------------------------------------------------------------
   Ported from PDAProject/Web/DatacenterWeb/wwwroot/app.css, which was itself
   site.css + dc.css + the Blazor defaults merged.

   NOTHING HERE IS STATE-SPECIFIC. The 32 subdomains share one stylesheet and
   one layout; the only thing that differs per site is the text MainLayout
   reads out of StateContext.
   ============================================================ */

/*  Page-level vocabulary, extracted from the inline <style> blocks that ~220
    pages carried. Imported rather than <link>ed because App.razor is shared by
    all 32 hosts and is owned by another area of the port -- this file is the
    only hook the stylesheets have into the document.

    In the reference the two sheets fought: 35 selectors were defined in both,
    and datacenter-shared.css won every one of them purely by loading second.
    Each is resolved to a single definition now, folded into whichever file it
    belongs in, so load order no longer decides anything and the @import may sit
    first without changing how a page renders. If a later agent adds an explicit
    <link> for the page sheet in App.razor, drop this line. */
@import url("css/datacenter-shared.css");

/* ── CSS Custom Properties ──
   Legacy VoterDataCenter theme (datacenter.votersir.site / src/PdaDataCenter
   app.css), inlined here. Same variable names as the previous "SP Red+Green"
   palette, so the ~220 existing pages pick up the legacy look without markup
   changes. --cyan is a true cyan again (it was aliased to green). */
:root {
    --bg: #080b0f; --bg2: #0e1117; --bg3: #161b24; --bg4: #1e2533;
    --border: rgba(255,255,255,0.06); --border2: rgba(255,255,255,0.12);
    --text: #e2e8f0; --muted: #64748b; --muted2: #94a3b8;
    --green: #00A651; --green-dim: rgba(0,166,81,0.15);
    --red: #E4002B; --red-dim: rgba(228,0,43,0.15);
    --amber: #f59e0b; --amber-dim: rgba(245,158,11,0.12);
    --blue: #3b82f6; --blue-dim: rgba(59,130,246,0.12);
    --cyan: #00A651; --cyan-dim: rgba(0,166,81,0.12);
    --purple: #a855f7; --purple-dim: rgba(168,85,247,0.15);
    --orange: #f97316;
    --accent: #00A651; --accent-dim: rgba(0,166,81,0.12);
    --mono: 'JetBrains Mono',monospace;
    --sans: 'Inter',system-ui,sans-serif;
    --radius: 6px;

    /*  The sidebar sticks under the topbar, so both heights come off one number.
        The reference hardcoded 52px here and 54px in the page sheet's sidebar
        override, which left a 2px strip of page showing above the rail. */
    --topbar-h: 52px;

    /*  .pw-eye (password reveal, bottom of this file) styles its focus ring and
        active state with --login-accent, which nothing ever defined -- so both
        declarations were dropped as invalid and the reveal button had no focus
        ring at all. It is the login card's accent. */
    --login-accent: #22e3c3;
}

/* ── Reset & Base ── */
* { box-sizing: border-box; }
html, body { margin:0; padding:0; background:var(--bg); color:var(--text); font-family:var(--sans); font-size:14px; line-height:1.6; }
h1, h2, h3 { margin:0 0 8px; }
h2 { font-size:20px; }
h3 { font-size:16px; }
a { color:var(--cyan); text-decoration:none !important; }
a:hover { text-decoration:none !important; }

/* ── Blazor framework styles ── */
.content { padding-top:1.1rem; }
h1:focus { outline:none; }
.valid.modified:not([type=checkbox]) { outline:1px solid #26b050; }
.invalid { outline:1px solid #e50000; }
.validation-message { color:#e50000; }
.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem; color: white;
}
.blazor-error-boundary::after { content: "An error has occurred."; }
.darker-border-checkbox.form-check-input { border-color: #929292; }
.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder { color: var(--bs-secondary-color); text-align: end; }
.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder { text-align: start; }

/* ── Topbar (legacy VoterDataCenter shell) ── */
.topbar { background:var(--bg2); border-bottom:1px solid var(--border); height:var(--topbar-h); display:flex; align-items:center; padding:0 24px; gap:32px; position:sticky; top:0; z-index:200; }
.topbar-logo { font-family:var(--mono); font-size:12px; font-weight:700; letter-spacing:.15em; color:var(--green); text-transform:uppercase; white-space:nowrap; }
.topbar-logo span { color:var(--muted); font-weight:400; }
.topbar-right { margin-left:auto; display:flex; align-items:center; gap:16px; font-family:var(--mono); font-size:11px; color:var(--muted); }
.topbar-right form { margin:0; }
.topbar a { color:var(--muted2); text-decoration:none; }
.topbar .logout-btn, .topbar .login-link { display:inline-block; padding:5px 13px; background:var(--bg3); color:var(--muted2); border:1px solid var(--border2); border-radius:var(--radius); font-family:var(--mono); font-size:10px; font-weight:600; letter-spacing:.06em; text-transform:uppercase; text-decoration:none; cursor:pointer; transition:all .15s; }
.topbar .logout-btn:hover, .topbar .login-link:hover { background:var(--red-dim); color:var(--red); border-color:var(--red); }

.live-dot { width:7px; height:7px; border-radius:50%; background:var(--green); box-shadow:0 0 0 3px var(--green-dim); animation:pulse 2s infinite; }
@keyframes pulse { 0%,100% { opacity:1 } 50% { opacity:.4 } }

/* ── Layout: sidebar + main ── */
.layout { display:flex; min-height:calc(100vh - var(--topbar-h)); }

.sidebar { width:225px; min-width:225px; background:var(--bg2); border-right:1px solid var(--border); padding:14px 0 40px; position:sticky; top:var(--topbar-h); height:calc(100vh - var(--topbar-h)); overflow-y:auto; }
.sidebar::-webkit-scrollbar { width:8px; }
.sidebar::-webkit-scrollbar-thumb { background:var(--bg4); border-radius:4px; }

/* Sections collapse with <details>/<summary> — no JS, works under static SSR. */
.nav-section { padding:0 10px; margin-bottom:6px; }
/*  Type scale. The reference ran a 13-step scale -- 9, 9.5, 10, 10.5, 11, 11.5,
    12, 12.5, 13, 14, 15, 18, 26 -- with 39 declarations below 11px, where an
    uppercase label stops being read and becomes texture. The page sheet fixed the
    worst offenders by restating them at the end of the file; the sizes are applied
    at the declaration site here instead. */
.nav-label { font-family:var(--mono); font-size:16px; font-weight:700; letter-spacing:.08em; color:var(--muted); text-transform:uppercase; padding:10px 8px; margin-bottom:2px; cursor:pointer; list-style:none; display:flex; align-items:center; gap:6px; border-radius:var(--radius); user-select:none; }
.nav-label::-webkit-details-marker { display:none; }
.nav-label::before { content:"\25B8"; font-size:11px; opacity:.6; transition:transform .15s; }
.nav-section[open] > .nav-label::before { transform:rotate(90deg); }
.nav-label:hover { background:var(--bg3); }
.nav-section + .nav-section { border-top:1px solid var(--border); padding-top:4px; }

.nav-link { display:flex; align-items:center; gap:9px; padding:6px 10px; border-radius:var(--radius); color:var(--muted2); text-decoration:none; font-size:13px; font-weight:500; transition:all .15s; }
.nav-link:hover { background:var(--bg3); color:var(--text); text-decoration:none; }
.nav-link.active { background:var(--green-dim); color:var(--green); }
.nav-link .icon { width:15px; text-align:center; font-size:12px; flex-shrink:0; }

.nav-divider { height:1px; background:var(--border); margin:8px 10px; }

/* ── Main content ── */
/*  overflow-x lives on .main, NOT on .layout. Any overflow other than visible on
    an ancestor makes that ancestor the scroll container, and the sidebar's
    position:sticky would then stick to it rather than to the viewport -- which is
    what stopped the rail holding while the page scrolled. auto rather than hidden
    so a wide table scrolls inside the console instead of being clipped. */
.main { flex:1; min-width:0; padding:22px 26px 60px; overflow-x:auto; }
.main--plain { max-width:700px; margin:0 auto; padding:16px; }

/*  The reference collapsed to a phone layout under 900px -- .layout went to a
    column and the rail dropped to a full-width static block -- and then the page
    sheet, loading afterwards, restated the desktop values to undo it at every
    width. Only the undo survives here.

    This is an analyst console driven on laptops, wall displays and tablets in
    landscape, and the collapsed variant loses the 21-section rail that is the
    only way to reach 100+ screens. The trade is a horizontal scrollbar below
    ~900px instead of a reflow, which is the right failure for a dense console:
    the layout stays the one people know rather than rearranging under them. */

/* ── Page header ── */
.page-header { display:flex; align-items:flex-start; justify-content:space-between; margin-bottom:24px; gap:16px; }
.page-title { font-family:var(--mono); font-size:17px; font-weight:700; color:var(--text); }
.page-subtitle { font-size:13px; color:var(--muted); margin-top:3px; }
.page-actions { display:flex; gap:8px; align-items:center; flex-shrink:0; flex-wrap:wrap; }

/* ── Section header ── */
.section-hdr { font-family:var(--mono); font-size:9px; letter-spacing:.18em; color:var(--muted); text-transform:uppercase; border-bottom:1px solid var(--border); padding-bottom:7px; margin-bottom:14px; }

/* ── Stat cards ── */
.cards-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(165px,1fr)); gap:10px; margin-bottom:24px; }
.col-span-2 { grid-column:span 2; }
.cards-grid-8 { display:grid; grid-template-columns:repeat(8,minmax(0,1fr)); gap:10px; margin-bottom:24px; }
.cards-grid-7 { display:grid; grid-template-columns:repeat(7,minmax(0,1fr)); gap:10px; margin-bottom:24px; }
@media(max-width:700px){ .cards-grid-8,.cards-grid-7{grid-template-columns:repeat(2,minmax(0,1fr))} }

.stat-card { background:var(--bg2); border:1px solid var(--border); border-radius:var(--radius); padding:14px 16px; position:relative; overflow:hidden; }
.stat-card.c-green  { border-top:2px solid var(--green); }
.stat-card.c-red    { border-top:2px solid var(--red); }
.stat-card.c-amber  { border-top:2px solid var(--amber); }
.stat-card.c-blue   { border-top:2px solid var(--blue); }
.stat-card.c-cyan   { border-top:2px solid var(--cyan); }
.stat-card.c-purple { border-top:2px solid var(--purple); }
.stat-card.c-gray   { border-top:2px solid #374151; }

.card-label { font-family:var(--mono); font-size:11.5px; letter-spacing:.12em; color:var(--muted); text-transform:uppercase; margin-bottom:8px; }
.card-value { font-family:var(--mono); font-size:24px; font-weight:700; line-height:1; margin-bottom:5px; }
.c-green  .card-value { color:var(--green); }
.c-red    .card-value { color:var(--red); }
.c-amber  .card-value { color:var(--amber); }
.c-blue   .card-value { color:var(--blue); }
.c-cyan   .card-value { color:var(--cyan); }
.c-purple .card-value { color:var(--purple); }
.c-gray   .card-value { color:#9ca3af; }
.card-sub { font-family:var(--mono); font-size:11.5px; color:var(--muted); }

/* ── Progress bar ── */
.progress-box { background:var(--bg2); border:1px solid var(--border); border-radius:var(--radius); padding:18px 22px; margin-bottom:24px; }
.progress-top { display:flex; justify-content:space-between; align-items:baseline; margin-bottom:10px; }
.progress-pct { font-family:var(--mono); font-size:18px; font-weight:700; color:var(--green); }
.progress-meta { font-family:var(--mono); font-size:10px; color:var(--muted); }
.prog-track { height:8px; background:var(--bg4); border-radius:4px; overflow:hidden; display:flex; gap:1px; }
.prog-seg { height:100%; border-radius:3px; transition:width .5s ease; }
.seg-done { background:var(--green); } .seg-fail { background:var(--red); } .seg-nf { background:#374151; } .seg-ip { background:var(--amber); }
.prog-legend { display:flex; flex-wrap:wrap; gap:14px; margin-top:8px; }
.leg { display:flex; align-items:center; gap:5px; font-family:var(--mono); font-size:11.5px; color:var(--muted); }
.leg-dot { width:7px; height:7px; border-radius:2px; flex-shrink:0; }

/* ── Two-column layout ── */
.two-col { display:grid; grid-template-columns:1fr 1fr; gap:18px; margin-bottom:24px; }
@media(max-width:1050px){ .two-col{grid-template-columns:1fr} }

/* ── Tables ── */
/*  overflow-x:auto, not the reference's overflow:hidden -- a table wider than the
    panel was clipped with no way to reach the far columns. overflow-y stays hidden
    so the rounded corners still clip the header row. */
.table-wrap { background:var(--bg2); border:1px solid var(--border); border-radius:var(--radius); overflow-x:auto; overflow-y:hidden; -webkit-overflow-scrolling:touch; margin-bottom:24px; }
.data-table { width:100%; border-collapse:collapse; font-size:12px; }
.data-table th { background:var(--bg3); color:var(--muted); font-family:var(--mono); font-size:9px; letter-spacing:.1em; text-transform:uppercase; padding:8px 12px; text-align:left; border-bottom:1px solid var(--border); white-space:nowrap; }
.data-table td { padding:8px 12px; border-bottom:1px solid var(--border); color:var(--muted2); font-family:var(--mono); font-size:11px; }
.data-table tr:last-child td { border-bottom:none; }
.data-table tr:hover td { background:var(--bg3); }
.data-table a { color:var(--cyan); text-decoration:none; }
.data-table a:hover { text-decoration:underline; }
.data-table th.sortable { cursor:pointer; }
.data-table th.sortable:hover { color:var(--text); }

/* ── Bar chart (CSS only) ── */
.bar-chart { display:flex; flex-direction:column; gap:8px; }
.bar-row { display:flex; align-items:center; gap:10px; font-family:var(--mono); font-size:10px; }
.bar-label { width:80px; flex-shrink:0; font-family:var(--mono); font-size:11.5px; color:var(--muted2); text-align:right; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.bar-track { flex:1; height:18px; background:var(--bg4); border-radius:3px; overflow:hidden; position:relative; }
.bar-fill { height:100%; border-radius:3px; transition:width .4s ease; display:flex; align-items:center; justify-content:flex-end; padding-right:6px; font-size:9px; font-weight:700; }
.bar-value { width:60px; flex-shrink:0; font-family:var(--mono); font-size:11.5px; font-weight:600; color:var(--text); text-align:right; }
.bar { background:var(--green); }

/* ── PDA-G palette ── */
.pdag-p { color:var(--amber); } .pdag-d { color:var(--blue); } .pdag-a { color:var(--green); } .pdag-g { color:var(--purple); }
.bg-pdag-p { background:var(--amber); } .bg-pdag-d { background:var(--blue); } .bg-pdag-a { background:var(--green); } .bg-pdag-g { background:var(--purple); }
.pdag-tile { display:flex; flex-direction:column; align-items:center; justify-content:center; }
.pdag-letter { font-size:40px; font-weight:800; font-family:var(--sans); line-height:1; margin-bottom:4px; }
.pdag-p .pdag-letter { color:var(--amber); }
.pdag-d .pdag-letter { color:var(--blue); }
.pdag-a .pdag-letter { color:var(--green); }
.pdag-g .pdag-letter { color:var(--purple); }

/* ── Badges ── */
.badge { display:inline-block; font-family:var(--mono); font-size:8px; font-weight:700; letter-spacing:.06em; padding:2px 5px; border-radius:3px; }
.badge-done    { background:var(--green-dim); color:var(--green); }
.badge-failed  { background:var(--red-dim); color:var(--red); }
.badge-ip      { background:var(--amber-dim); color:var(--amber); }
.badge-pending { background:var(--bg4); color:var(--muted); }

/* ── Buttons ── */
.btn { display:inline-block; padding:10px 20px; background:var(--bg3); border:1px solid var(--border2); color:var(--text); font-family:var(--mono); font-size:11px; border-radius:var(--radius); text-decoration:none; cursor:pointer; }
.btn:active, .btn:hover { background:var(--bg4); }
.page-actions .btn { font-size:10px; padding:5px 12px; white-space:nowrap; }
.page-actions .btn-green { background:var(--green-dim); color:var(--green); border-color:var(--green); }
/*  Two definitions collided in the reference: a green chip here and a black-text
    badge in the page sheet that loaded after it, so what shipped was black text on
    a dark-green ground. The box model is the badge's, the colours the chip's. A
    page that paints its own .pill background sets the text colour with it. */
.pill { display:inline-block; padding:2px 8px; border-radius:4px; font-family:var(--mono); font-size:10px; font-weight:700; background:var(--green-dim); color:var(--green); }

/* Bootstrap overrides for dark theme */
.btn-primary { background-color:var(--green); border-color:var(--green); color:#fff; }
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus { box-shadow:0 0 0 0.1rem rgba(255,255,255,.1), 0 0 0 0.25rem rgba(76,175,80,.4); }

/* ── Cards ── */
.card { background:var(--bg2); border:1px solid var(--border); color:var(--text); border-radius:8px; padding:16px; margin-bottom:12px; box-shadow:0 1px 4px rgba(0,0,0,.18); }

/* ── Forms ── */
input[type=text], input[type=password], input[type=email], input[type=number], textarea, select {
    width:100%; box-sizing:border-box; padding:10px 12px; font-size:14px; font-family:var(--sans);
    background:var(--bg3); color:var(--text); border:1px solid var(--border2); border-radius:var(--radius); outline:none; transition:border-color .15s, box-shadow .15s;
}
input:focus, textarea:focus, select:focus { border-color:var(--cyan); box-shadow:0 0 0 2px rgba(6,182,212,.15); }
textarea { min-height:60px; resize:vertical; }
select { cursor:pointer; appearance:none; -webkit-appearance:none;
    background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 14 14'><path d='M3 5 L7 9 L11 5' stroke='%2394a3b8' stroke-width='2' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>");
    background-repeat:no-repeat; background-position:right 12px center; padding-right:34px;
}
.form-row { margin-bottom:14px; }
.form-row label { display:block; font-family:var(--mono); font-size:11px; font-weight:600; color:var(--muted2); letter-spacing:.06em; text-transform:uppercase; margin-bottom:5px; }

.edit-actions { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.btn-save { background:var(--green)!important; color:#fff!important; border-color:var(--green)!important; font-weight:700; padding:10px 28px!important; font-size:13px!important; }
.btn-save:hover { opacity:.9; }
.btn-cancel { background:var(--bg3)!important; color:var(--muted2)!important; border:1px solid var(--border2)!important; padding:10px 22px!important; font-size:13px!important; }
.btn-cancel:hover { background:var(--bg4)!important; color:var(--text)!important; }

/* ── Status messages ── */
.err { color:var(--red); font-weight:600; }
.ok  { color:var(--green); font-weight:600; }
.err-text { color:var(--red)!important; font-size:10px; }

/* ── Voter cards ── */
.voter-card { background:linear-gradient(135deg,#0e180e,#152215); border:1px solid rgba(76,175,80,0.10); border-radius:10px; margin-bottom:8px; overflow:hidden; border-left:3px solid var(--green); box-shadow:0 2px 12px rgba(0,0,0,.35); transition:transform .15s,box-shadow .15s; }
.voter-card:hover { transform:translateY(-1px); box-shadow:0 4px 20px rgba(0,0,0,.45); }
.voter-card a { color:var(--cyan); text-decoration:none; }
.voter-card a:active { text-decoration:underline; }
.voter-card.vc-m { border-left-color:var(--blue); box-shadow:0 2px 12px rgba(0,0,0,.35),inset 0 0 0 1px rgba(96,165,250,.06); }
.voter-card.vc-f { border-left-color:#ec4899; box-shadow:0 2px 12px rgba(0,0,0,.35),inset 0 0 0 1px rgba(236,72,153,.06); }

.vc-layout { display:flex; align-items:stretch; }
.vc-srno { display:flex; align-items:center; justify-content:center; min-width:46px; padding:0 4px; font-family:var(--mono); font-size:15px; font-weight:800; color:var(--muted2); background:rgba(255,255,255,.03); border-right:1px solid rgba(148,163,184,0.08); flex-shrink:0; }
.vc-content { flex:1; min-width:0; padding:12px 14px; }

.vc-row1 { display:flex; align-items:flex-start; gap:8px; margin-bottom:4px; }
.vc-name { flex:1; min-width:0; font-size:15px; font-weight:700; color:#fff; line-height:1.35; }
.vc-en { font-size:12px; font-weight:400; color:var(--muted2); }
.vc-edit { flex-shrink:0; padding:4px 12px; border-radius:6px; background:rgba(239,68,68,.10); border:1px solid rgba(239,68,68,.25); color:var(--red); text-decoration:none; font-family:var(--mono); font-size:10px; font-weight:700; white-space:nowrap; transition:all .15s; letter-spacing:.03em; }
.vc-edit:hover { background:rgba(239,68,68,.20); border-color:var(--red); box-shadow:0 0 8px rgba(239,68,68,.2); }

.vc-row2 { display:flex; align-items:center; gap:8px; margin-bottom:5px; font-size:12px; }
.vc-sur { color:var(--muted2); font-weight:500; }
.vc-vid { font-family:var(--mono); font-size:10px; color:var(--green); letter-spacing:.03em; padding:2px 7px; background:rgba(76,175,80,.10); border:1px solid rgba(76,175,80,.15); border-radius:4px; font-weight:600; }

.vc-row3 { display:flex; flex-wrap:wrap; gap:0; font-family:var(--mono); font-size:11px; color:var(--muted2); line-height:1.3; }
.vc-row3 span { white-space:nowrap; }
.vc-row3 span::after { content:"\00b7"; margin:0 5px; color:var(--muted); opacity:.4; }
.vc-row3 span:last-child::after { display:none; }
.vc-row3 .vc-ph { color:var(--green); }
.vc-row3 .vc-pty { color:var(--blue); font-weight:700; }

/* ── Tile grid ── */
.tile-grid { display:grid; grid-template-columns:repeat(3,1fr); gap:14px; padding:16px; }
.tile { display:block; background:var(--bg2); border:1px solid var(--border); border-radius:10px; padding:14px 10px; text-align:center; text-decoration:none; color:var(--text); box-shadow:0 2px 8px rgba(0,0,0,.25); transition:transform .15s,box-shadow .15s,border-color .15s; }
.tile:active { transform:scale(0.97); }
.tile:hover { border-color:var(--border2); transform:translateY(-1px); box-shadow:0 4px 20px rgba(0,0,0,.35); }
.tile img { width:80px; height:80px; object-fit:contain; }
.tile h5 { margin:8px 0 0; font-size:14px; font-weight:600; color:var(--muted2); }

/* ── Picker bar ── */
.pdc-picker { display:grid; grid-template-columns:auto 1fr; gap:10px; align-items:center; width:100%; margin:14px 0 22px; }
@media(max-width:600px){ .pdc-picker{grid-template-columns:1fr} }
.pdc-picker-lbl { font-family:var(--mono); font-size:11px; color:var(--muted2); text-transform:uppercase; letter-spacing:.14em; font-weight:700; }
.pdc-picker-sel {
    appearance:none; -webkit-appearance:none; cursor:pointer; width:100%; max-width:420px;
    background-color:var(--bg3);
    background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 14 14'><path d='M3 5 L7 9 L11 5' stroke='%2394a3b8' stroke-width='2' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>");
    background-repeat:no-repeat; background-position:right 12px center;
    color:var(--text); border:1px solid var(--border2); border-radius:8px;
    padding:9px 34px 9px 12px; font-family:var(--mono); font-size:13px; font-weight:500;
}
.pdc-picker-sel:focus { outline:none; border-color:#22e3c3; box-shadow:0 0 0 2px rgba(34,227,195,.18); }
.pdc-picker-sel option { background:var(--bg2); color:var(--text); }

/* ── Geo bar: area picker + level tabs (PDAOverview) ──
   Static SSR — the picker is a plain <form method="get">, the tabs are links.
   The select carries its own chevron so it matches the dark shell in every
   browser (the native one renders light on Windows). */
.geo-bar { display:flex; flex-wrap:wrap; gap:10px; align-items:center; margin:14px 0 22px; }
.geo-pick { display:flex; align-items:center; gap:8px; background:var(--bg2); border:1px solid var(--border); border-radius:10px; padding:6px 6px 6px 12px; min-width:0; }
.geo-pick-lbl { font-family:var(--mono); font-size:9.5px; letter-spacing:.16em; text-transform:uppercase; color:var(--muted); font-weight:700; white-space:nowrap; }
.geo-bar select, .geo-pick-sel {
    appearance:none; -webkit-appearance:none; cursor:pointer;
    max-width:min(440px,60vw); text-overflow:ellipsis;
    background-color:var(--bg3);
    background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 14 14'><path d='M3 5 L7 9 L11 5' stroke='%2394a3b8' stroke-width='2' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>");
    background-repeat:no-repeat; background-position:right 11px center;
    color:var(--text); border:1px solid var(--border2); border-radius:8px;
    padding:8px 32px 8px 12px; font-family:var(--mono); font-size:13px; font-weight:500;
    transition:border-color .15s, box-shadow .15s;
}
.geo-pick-sel option { background:var(--bg2); color:var(--text); }
.geo-pick-sel:hover:not(:disabled) { border-color:var(--muted); }
.geo-pick-sel:focus-visible { outline:none; border-color:var(--cyan); box-shadow:0 0 0 2px var(--cyan-dim); }
.geo-pick-sel:disabled { cursor:default; opacity:.75; }
/* State level has nothing to pick — the select is a label, not a control. */
.geo-pick--static { opacity:.85; }
.geo-go { background:var(--bg4); color:var(--muted2); border:1px solid var(--border2); border-radius:8px; padding:8px 13px; font-family:var(--mono); font-size:10px; font-weight:700; letter-spacing:.1em; text-transform:uppercase; cursor:pointer; transition:all .15s; }
.geo-go:hover { background:var(--cyan-dim); color:var(--cyan); border-color:var(--cyan); }
.geo-go:focus-visible { outline:2px solid var(--cyan); outline-offset:1px; }

.geo-tabs { display:flex; flex-wrap:wrap; gap:6px; margin-left:auto; }
.geo-tab { font-family:var(--mono); font-size:11px; font-weight:600; padding:8px 13px; border-radius:8px; border:1px solid var(--border2); color:var(--muted2); text-decoration:none; transition:all .15s; }
.geo-tab:hover { background:var(--bg3); color:var(--text); border-color:var(--muted); text-decoration:none; }
.geo-tab.on { background:var(--cyan-dim); color:var(--cyan); border-color:var(--cyan); }
.geo-tab:focus-visible { outline:2px solid var(--cyan); outline-offset:2px; }
@media(max-width:760px){ .geo-tabs { margin-left:0; width:100%; } .geo-pick { width:100%; } .geo-pick-sel { flex:1; max-width:none; } }

/* ── Booth Picker ── */
.bp-bar { display:flex; align-items:center; gap:10px; padding:10px 14px; margin:0 0 12px; background:linear-gradient(135deg,#0e180e,#152215); border:1px solid rgba(76,175,80,0.10); border-radius:var(--radius); flex-wrap:wrap; }
.bp-lbl { font-family:var(--mono); font-size:10px; font-weight:600; color:var(--muted); text-transform:uppercase; letter-spacing:.08em; white-space:nowrap; }
.bp-sel { flex:1; min-width:140px; padding:8px 30px 8px 10px; font-family:var(--mono); font-size:12px; background:var(--bg3); color:var(--text); border:1px solid var(--border2); border-radius:var(--radius); outline:none; appearance:none; -webkit-appearance:none; cursor:pointer; background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 14 14'><path d='M3 5 L7 9 L11 5' stroke='%2394a3b8' stroke-width='2' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>"); background-repeat:no-repeat; background-position:right 10px center; }
.bp-sel:focus { border-color:var(--cyan); box-shadow:0 0 0 2px rgba(6,182,212,.15); }

/* ── Search box ── */
.search-box { background:var(--bg3); border:1px solid var(--border2); color:var(--text); font-family:var(--mono); font-size:12px; padding:7px 12px; border-radius:var(--radius); outline:none; width:260px; }
.search-box:focus { border-color:var(--cyan); }

/* ── Filter bar ── */
.filter-header { font-family:var(--mono); font-size:15px; font-weight:700; color:var(--text); padding:14px 0 4px; letter-spacing:.02em; }
.filter-bar { display:flex; align-items:center; gap:10px; padding:10px 14px; margin:6px 0 10px; background:linear-gradient(135deg,#0e180e,#152215); border:1px solid rgba(76,175,80,0.10); border-radius:var(--radius); flex-wrap:wrap; box-shadow:0 2px 10px rgba(0,0,0,.3); }
.filter-bar label { font-family:var(--mono); font-size:10px; font-weight:600; color:var(--muted); text-transform:uppercase; letter-spacing:.08em; white-space:nowrap; }
.filter-bar select, .filter-bar input[type=text] { flex:1; min-width:120px; padding:9px 12px; font-family:var(--mono); font-size:13px; background:var(--bg3); color:var(--text); border:1px solid var(--border2); border-radius:var(--radius); outline:none; transition:border-color .15s,box-shadow .15s; appearance:none; -webkit-appearance:none; }
.filter-bar select { background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 14 14'><path d='M3 5 L7 9 L11 5' stroke='%2394a3b8' stroke-width='2' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>"); background-repeat:no-repeat; background-position:right 10px center; padding-right:30px; cursor:pointer; }
.filter-bar select:focus, .filter-bar input[type=text]:focus { border-color:var(--cyan); box-shadow:0 0 0 2px rgba(6,182,212,.15); }
.filter-bar .btn { background:var(--green); color:#fff; border:none; padding:9px 18px; font-family:var(--mono); font-size:11px; font-weight:700; border-radius:var(--radius); cursor:pointer; letter-spacing:.04em; text-transform:uppercase; transition:opacity .15s; }
.filter-bar .btn:hover { opacity:.85; }
.filter-results-count { font-family:var(--mono); font-size:11.5px; color:var(--muted2); padding:4px 0 8px; letter-spacing:.02em; }

/* ── Letter picker ── */
.letter-picker { display:flex; flex-wrap:wrap; gap:4px; padding:8px 16px; }
.letter-picker a { padding:4px 8px; background:var(--bg3); color:var(--muted2); border:1px solid var(--border); text-decoration:none; border-radius:4px; font-size:12px; }
.letter-picker a.active { background:var(--red); color:#fff; border-color:var(--red); font-weight:700; }

/* ── Surname Cloud ── */
.surname-cloud { display:flex; flex-wrap:wrap; gap:6px 10px; align-items:baseline; padding:14px; margin:8px 0 12px; background:linear-gradient(135deg,#0e180e,#152215); border:1px solid rgba(76,175,80,0.10); border-radius:var(--radius); line-height:1.6; box-shadow:0 2px 10px rgba(0,0,0,.3); }
.sc-tag { text-decoration:none; color:var(--muted2); font-family:var(--sans); transition:color .15s; white-space:nowrap; }
.sc-tag:hover { color:var(--accent); }
.sc-tag.sc-active { color:var(--accent); font-weight:700; }
.sc-tag .sc-cnt { font-size:inherit; color:var(--muted); font-family:var(--mono); font-weight:400; }

/* ── Pager ── */
/*  .pager was defined three times across the two sheets -- twice here, once in the
    page sheet -- for two different pagers: a row of .pager-btn links, and a
    prev/next pair of <button>s with a count between them. One definition carries
    both now; the <button> skin comes from the page sheet's version, which used the
    theme tokens rather than hardcoded hexes. */
.pager { display:flex; flex-wrap:wrap; align-items:center; justify-content:center; gap:10px; padding:14px 0; margin:12px 0; font-family:var(--mono); font-size:12px; color:var(--muted2); }
.pager button { background:var(--bg3); border:1px solid var(--border); color:var(--text); padding:5px 12px; border-radius:6px; font-family:var(--mono); font-size:11px; cursor:pointer; }
.pager button:disabled { opacity:.4; cursor:default; }
.pager button:not(:disabled):hover { background:var(--cyan); color:#000; }
.pager-btn { display:inline-flex; align-items:center; justify-content:center; min-width:36px; height:36px; padding:0 10px; border-radius:var(--radius); font-size:13px; font-weight:600; color:var(--text); background:var(--bg2); border:1px solid var(--border); text-decoration:none; cursor:pointer; transition:background .15s,border-color .15s; }
.pager-btn:hover { background:var(--bg3); border-color:var(--border2); }
.pager-btn.active { background:var(--red); color:#fff; border-color:var(--red); }
.pager-btn.disabled { opacity:.35; cursor:default; pointer-events:none; }
.pager-dots { display:inline-flex; align-items:center; padding:0 4px; color:var(--muted); }

/* ── Back link ── */
.back-link { display:inline-block; margin-top:16px; font-family:var(--mono); font-size:12px; color:var(--cyan); text-decoration:none; padding:6px 0; }
.back-link:hover { text-decoration:underline; }

/* ── Text helpers ── */
.text-muted  { color:var(--muted); }
.text-muted2 { color:var(--muted2); }
.text-green  { color:var(--green); }
.text-red    { color:var(--red); }
.text-amber  { color:var(--amber); }
.text-blue   { color:var(--blue); }
.text-cyan   { color:var(--cyan); }
.text-purple { color:var(--purple); }
.mono { font-family:var(--mono); }
.mb24 { margin-bottom:24px; }

/* ── Stat grid ── */
.stat-grid > div { color:var(--muted2); }

/* ── Login page ── */
.login-body { background:linear-gradient(135deg, #0d1117 0%, #1a1f2e 50%, #0d1117 100%) fixed; min-height:100vh; color:#fff; }
.login-body .main { padding:24px 18px; max-width:460px; margin:0 auto; padding-top:5vh; }
.login-body img { box-shadow:0 10px 30px rgba(0,0,0,.45), 0 0 0 1px rgba(255,255,255,.06); }
.login-body .card { background:rgba(22,27,34,.85); backdrop-filter:blur(10px); border:1px solid rgba(255,255,255,.08); border-radius:16px; padding:28px 24px; box-shadow:0 20px 50px rgba(0,0,0,.4); color:#fff; }
.login-body .card h2 { font-family:var(--mono); font-size:32px; font-weight:800; margin:0 0 6px; letter-spacing:.04em; text-transform:uppercase; background:linear-gradient(90deg, #22e3c3, #a855f7); -webkit-background-clip:text; background-clip:text; -webkit-text-fill-color:transparent; }
.login-body .card .subtitle { font-size:12px; letter-spacing:.18em; text-transform:uppercase; color:#94a3b8; margin-bottom:24px; font-weight:600; }
.login-body .form-row { margin-bottom:16px; }
.login-body .form-row label { color:#94a3b8; font-size:11px; letter-spacing:.14em; }
.login-body .form-row input[type="text"], .login-body .form-row input[type="password"] { padding:12px 14px; background:rgba(13,17,23,.6); border:1px solid rgba(255,255,255,.12); border-radius:10px; color:#fff; font-size:15px; }
.login-body .form-row input[type="text"]:focus, .login-body .form-row input[type="password"]:focus { border-color:#22e3c3; box-shadow:0 0 0 3px rgba(34,227,195,.15); background:rgba(13,17,23,.85); }
.login-body .btn { width:100%; padding:13px 20px; background:linear-gradient(135deg, #22e3c3, #06b6d4); color:#0d1117; border:none; border-radius:10px; font-weight:800; font-size:15px; letter-spacing:.08em; text-transform:uppercase; text-align:center; box-shadow:0 6px 20px rgba(34,227,195,.25); }
.login-body .btn:hover { transform:translateY(-1px); box-shadow:0 10px 28px rgba(34,227,195,.4); }
.login-body .err { display:block; margin-top:14px; padding:10px 14px; background:rgba(239,68,68,.12); border:1px solid rgba(239,68,68,.3); border-radius:8px; color:#fca5a5; font-size:13px; }
@media (max-width: 480px) { .login-body .card h2 { font-size:26px; } .login-body .main { padding-top:2vh; } }

/*  A second, cruder copy of .voter-card / .vc-name / .pager sat here in the
    reference and, loading later, overrode the styled versions above with flat
    panels and hardcoded hexes. Only the classes that had no counterpart survive,
    re-themed onto the tokens. The .layer-assembly block that preceded them
    belonged to the sibling AssemblyWeb app and is not ported. */
.vc-head { display:flex; justify-content:space-between; font-size:12px; color:var(--muted2); margin-bottom:4px; }
.vc-hname { font-size:13px; color:var(--muted2); margin-top:2px; }
.vc-detail { display:flex; gap:12px; font-size:12px; color:var(--muted); margin-top:6px; }
.vc-tag { display:inline-block; font-size:11px; background:rgba(255,255,255,.06); border-radius:4px; padding:2px 8px; margin-top:6px; color:var(--muted2); }
.pager .pager-info { font-size:13px; color:var(--muted2); }
.booth-picker select { width:100%; padding:8px 12px; background:var(--bg2); border:1px solid var(--border2); border-radius:8px; color:var(--text); font-size:14px; }

/* ============================================================
   Command Center (home) — lifted from legacy Default.aspx <style>.
   Meters/bars/chips are pure CSS: no Chart.js, no CDN, no scripts.
   ============================================================ */
.dash-hero { background:linear-gradient(135deg,#0e1117,#161b24); border:1px solid var(--border2); border-radius:14px; padding:26px 28px; margin-bottom:18px; }
.dash-hero .h-title { font-family:var(--mono); font-size:24px; font-weight:700; color:var(--text); }
.dash-hero .h-verdict { font-size:16px; color:var(--green); margin:8px 0 18px; font-weight:600; }

.pda-tiles { display:grid; grid-template-columns:repeat(6,1fr); gap:14px; margin:14px 0; }
@media(max-width:1100px) { .pda-tiles { grid-template-columns:repeat(3,1fr); } }
@media(max-width:620px)  { .pda-tiles { grid-template-columns:repeat(2,1fr); } }
.pda-tile { border-radius:10px; padding:22px 14px; text-align:center; color:#fff; box-shadow:0 2px 10px rgba(0,0,0,.4); }
.pda-tile .t-label { font-size:12px; font-weight:600; opacity:.95; }
.pda-tile .t-val { font-family:var(--mono); font-size:30px; font-weight:700; margin-top:8px; line-height:1; }
.pda-tile .t-sub { font-size:10px; opacity:.85; margin-top:5px; }
.pt-total { background:#1f7ae0; } .pt-p { background:#2e8b57; } .pt-d { background:#d23b3b; }
.pt-a { background:#1aa3a3; } .pt-g { background:#7a3fb0; } .pt-c { background:#f0902a; }

.gauges { display:grid; grid-template-columns:repeat(6,1fr); gap:16px; }
@media(max-width:1100px) { .gauges { grid-template-columns:repeat(3,1fr); } }
.gauge .g-top { display:flex; justify-content:space-between; font-size:11px; color:var(--muted); margin-bottom:5px; }
.gauge .g-val { font-family:var(--mono); font-size:19px; font-weight:700; color:var(--text); }
.gauge .g-track { height:8px; background:var(--bg4); border-radius:4px; overflow:hidden; }
.gauge .g-fill { height:100%; border-radius:4px; }

.sec { margin:30px 0 8px; display:flex; align-items:center; gap:12px; }
.sec h3 { font-family:var(--mono); font-size:14px; letter-spacing:.12em; text-transform:uppercase; color:var(--text); margin:0; }
.sec .line { flex:1; height:1px; background:var(--border); }
.sec a { font-size:11px; color:var(--cyan); text-decoration:none; }

.grid2 { display:grid; grid-template-columns:1fr 1fr; gap:18px; }
.grid3 { display:grid; grid-template-columns:1fr 1fr 1fr; gap:18px; }
@media(max-width:1000px) { .grid2, .grid3 { grid-template-columns:1fr; } }

.panel { background:var(--bg2); border:1px solid var(--border); border-radius:12px; padding:16px 18px; }
.panel h4 { font-family:var(--mono); font-size:11px; letter-spacing:.14em; text-transform:uppercase; color:var(--muted2); margin-bottom:14px; border-bottom:1px solid var(--border); padding-bottom:8px; }

.kpi-row { display:grid; grid-template-columns:repeat(auto-fill,minmax(120px,1fr)); gap:10px; }
.kpi { background:var(--bg3); border:1px solid var(--border); border-radius:8px; padding:12px; text-align:center; }
.kpi .k-l { font-size:11.5px; color:var(--muted); text-transform:uppercase; letter-spacing:.08em; }
.kpi .k-v { font-family:var(--mono); font-size:20px; font-weight:700; color:var(--text); margin-top:5px; }
.kpi .k-v.k-na { color:var(--muted); }

.cloud span { display:inline-block; margin:3px 9px 3px 0; white-space:nowrap; }

/* Cast-of-the-day surname chips (Devanagari) */
.sn-chip { font-family:var(--mono); background:var(--bg3); border:1px solid var(--border); border-radius:6px; padding:4px 9px; font-size:11px; }

/* Top-casts-per-bucket rows */
.bkt-row { display:flex; align-items:baseline; gap:8px; padding:5px 0; border-bottom:1px solid var(--border); font-family:var(--mono); font-size:12px; }
.bkt-row:last-child { border-bottom:none; }
.bkt-row a { color:var(--text); text-decoration:none; flex:1; }
.bkt-row a:hover { color:var(--cyan); }

/* ============================================================
   PDA Overview (Geo PDA) — hero KPIs, chart grid, datapoint grid
   Shared by /pdaoverview/{state,district,parliamentary,assembly,booth}.
   These class names are used only by those pages plus the GeoHero /
   GeoCharts components, so nothing else in the app is re-themed.
   ============================================================ */

/* ── Hero band ── */
.geo-hero { background:linear-gradient(160deg,#0f1825 0%,#0a1117 100%); border:1px solid var(--border2); border-radius:14px; padding:20px 22px; margin:0 0 22px; }
.geo-hero-top { display:flex; flex-wrap:wrap; align-items:baseline; gap:14px; margin-bottom:16px; border-bottom:1px solid var(--border); padding-bottom:14px; }
.geo-hero-name { font-family:var(--mono); font-size:21px; font-weight:800; color:#fff; margin:0; letter-spacing:-.01em; }
.geo-hero-level { font-family:var(--mono); font-size:10px; letter-spacing:.16em; text-transform:uppercase; color:var(--muted2); }
.geo-hero-total { margin-left:auto; font-family:var(--mono); font-size:11px; color:var(--muted); }
.geo-hero-total b { font-size:14px; font-weight:700; color:var(--cyan); margin-right:5px; }

/* Six headline cards on ONE row — the legacy layout, with breakpoints that
   step down 6 → 3 → 2 instead of collapsing straight to a 2-wide stack. */
.geo-kpis { display:grid; grid-template-columns:repeat(6,minmax(0,1fr)); gap:10px; }
@media(max-width:1180px){ .geo-kpis { grid-template-columns:repeat(3,minmax(0,1fr)); } }
@media(max-width:620px){ .geo-kpis { grid-template-columns:repeat(2,minmax(0,1fr)); } }

.geo-kpi { position:relative; overflow:hidden; border-radius:10px; padding:14px 12px 13px; text-align:center; color:#fff; box-shadow:0 2px 10px rgba(0,0,0,.32); transition:transform .15s, box-shadow .15s; }
.geo-kpi::before { content:""; position:absolute; inset:0 0 auto; height:1px; background:rgba(255,255,255,.28); }
.geo-kpi:hover { transform:translateY(-2px); box-shadow:0 6px 18px rgba(0,0,0,.45); }
.geo-kpi .k-label { font-size:11px; font-weight:600; opacity:.92; letter-spacing:.02em; }
.geo-kpi .k-value { font-family:var(--mono); font-size:22px; font-weight:800; margin-top:6px; line-height:1.1; word-break:break-word; }
.geo-kpi .k-sub { font-size:10px; opacity:.85; margin-top:5px; }
.geo-kpi .k-bar { height:3px; border-radius:2px; background:rgba(0,0,0,.28); margin:8px 2px 0; overflow:hidden; }
.geo-kpi .k-bar span { display:block; height:100%; background:rgba(255,255,255,.72); border-radius:2px; }
.geo-kpi.is-na .k-value { opacity:.55; }
.geo-kpi.k-total  { background:#1f7ae0; }
.geo-kpi.k-male   { background:#3b82f6; }
.geo-kpi.k-female { background:#d23b3b; }
.geo-kpi.k-hindu  { background:#f59e0b; }
.geo-kpi.k-muslim { background:#10b981; }
.geo-kpi.k-age    { background:#a855f7; }

/* ── Secondary chips ── */
.geo-chips { display:flex; flex-wrap:wrap; gap:8px; margin-top:16px; }
.geo-chip { background:var(--bg3); border:1px solid var(--border); border-radius:7px; padding:6px 11px; font-family:var(--mono); font-size:11px; color:var(--muted2); transition:border-color .15s; }
.geo-chip:hover { border-color:var(--border2); }
.geo-chip b { color:var(--text); margin-left:7px; font-weight:700; }
.geo-chip i { font-style:normal; font-size:9.5px; color:var(--muted); margin-left:5px; }
.geo-chip.is-na b { color:var(--muted); }
.geo-chip b.hi-amber { color:var(--amber); }
.geo-chip b.hi-green { color:var(--green); }

/* ── Section header ── */
.sechdr { display:flex; flex-wrap:wrap; align-items:baseline; gap:12px; font-family:var(--mono); font-size:13px; font-weight:600; letter-spacing:.14em; text-transform:uppercase; color:#bfeee6; margin:30px 0 14px; border-bottom:1px solid var(--border); padding-bottom:8px; }
.sechdr-note { margin-left:auto; font-size:11.5px; font-weight:400; letter-spacing:.06em; text-transform:none; color:var(--muted); }

/* ── Chart grid: THREE columns, stepping 3 → 2 → 1 ── */
.gcharts { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:14px; align-items:start; }
@media(max-width:1100px){ .gcharts { grid-template-columns:repeat(2,minmax(0,1fr)); } }
@media(max-width:680px){ .gcharts { grid-template-columns:minmax(0,1fr); } }
/* Nothing rendered means Chart.js never ran — say so instead of showing a void. */
.gcharts:empty::after { content:"Charts could not be drawn — chart.umd.min.js did not load."; display:block; font-family:var(--mono); font-size:11px; color:var(--muted); background:var(--bg2); border:1px dashed var(--border2); border-radius:12px; padding:22px; text-align:center; }

.gcard { background:var(--bg2); border:1px solid var(--border); border-radius:12px; padding:14px; min-width:0; transition:border-color .15s, box-shadow .15s; }
.gcard:hover { border-color:var(--border2); box-shadow:0 4px 16px rgba(0,0,0,.30); }
.gcard-head { display:flex; align-items:baseline; gap:8px; margin-bottom:10px; }
.gcard h4 { flex:1; min-width:0; font-family:var(--mono); font-size:11px; font-weight:700; letter-spacing:.09em; text-transform:uppercase; color:var(--muted2); margin:0; }
/*  11.5px, not the 13px the page sheet's type-scale block gave it: .gcard-sub is
    a caption on the same line as an 11px uppercase h4, and 13px made the caption
    the larger of the two. Same reasoning for .tlh-sub further down. */
.gcard-sub { font-family:var(--mono); font-size:11.5px; color:var(--muted); white-space:nowrap; }
.gcard-canvas { position:relative; height:230px; }
/* Horizontal bars (Top-25 castes, surname leaderboards) need width and height,
   so they take the full row rather than being squeezed into a third. */
.gcard--wide { grid-column:1 / -1; }
.gcard--wide .gcard-canvas { height:clamp(300px,38vh,430px); }
.gcard--failed { border-color:var(--red); }

/* ── Dense datapoint grid ── */
.kpis { display:grid; grid-template-columns:repeat(auto-fill,minmax(196px,1fr)); gap:8px; }
.kpi2 { background:var(--bg3); border:1px solid var(--border); border-radius:8px; padding:9px 11px; transition:border-color .15s, background .15s; }
.kpi2:hover { background:var(--bg4); border-color:var(--border2); }
.kpi2 .k { font-size:9.5px; color:var(--muted); text-transform:uppercase; letter-spacing:.07em; }
.kpi2 .v { font-family:var(--mono); font-size:14px; font-weight:700; color:var(--text); margin-top:3px; word-break:break-word; }
/* Genuinely absent in source — never a substituted number. */
.kpi2--na .v { color:var(--muted); font-weight:500; }

/* ── PDA Cast sections (inlined Controls/PdaCastSections.ascx) ──
   The port flattened every grid here to 1–2 columns; these restore the
   legacy 6 / 4 / 3 column rhythm with the same breakpoints. */
.pdacs-wrap { margin-top:34px; }
.pdacs-wrap .pdag-sec { margin:0 0 18px; }
.pdacs-wrap .pdag-h { font-family:var(--mono); font-size:26px; font-weight:800; display:flex; flex-wrap:wrap; align-items:center; gap:14px; padding:4px 0 14px; margin:0 0 22px; border-bottom:4px solid var(--border2); }
.pdacs-wrap .pdag-h .bdg { font-size:14px; font-weight:800; color:#04130f; border-radius:8px; padding:5px 13px; }
.pdacs-wrap .pdag-h small { font-size:13px; font-weight:500; color:var(--muted); }
.pdacs-wrap .gap-rule { height:3px; background:linear-gradient(90deg,transparent,var(--border2) 30%,var(--border2) 70%,transparent); margin:46px 0 48px; border-radius:2px; }
.pdacs-wrap .pda-tiles { display:grid; grid-template-columns:repeat(6,minmax(0,1fr)); gap:14px; margin:8px 0 18px; }
@media(max-width:1100px){ .pdacs-wrap .pda-tiles { grid-template-columns:repeat(3,minmax(0,1fr)); } }
@media(max-width:620px){ .pdacs-wrap .pda-tiles { grid-template-columns:repeat(2,minmax(0,1fr)); } }
.pdacs-wrap .pda-tiles.t4 { grid-template-columns:repeat(4,minmax(0,1fr)); }
@media(max-width:1100px){ .pdacs-wrap .pda-tiles.t4 { grid-template-columns:repeat(2,minmax(0,1fr)); } }
.pdacs-wrap .pda-tile { border-radius:10px; padding:20px 14px; text-align:center; color:#fff; box-shadow:0 2px 8px rgba(0,0,0,.35); transition:transform .15s, box-shadow .15s; }
.pdacs-wrap .pda-tile:hover { transform:translateY(-2px); box-shadow:0 6px 18px rgba(0,0,0,.45); }
.pdacs-wrap .pda-tile .t-label { font-size:12.5px; font-weight:600; opacity:.95; }
.pdacs-wrap .pda-tile .t-val { font-family:var(--mono); font-size:26px; font-weight:700; margin-top:9px; line-height:1.05; word-break:break-word; }
.pdacs-wrap .pda-tile .t-sub { font-size:11px; opacity:.85; margin-top:6px; }
.pdacs-wrap .pt-total { background:#1f7ae0; } .pdacs-wrap .pt-p { background:#2e8b57; } .pdacs-wrap .pt-d { background:#d23b3b; }
.pdacs-wrap .pt-a { background:#1aa3a3; } .pdacs-wrap .pt-g { background:#7a3fb0; } .pdacs-wrap .pt-asd { background:#f0902a; }
.pdacs-wrap .bk-charts { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:16px; margin:6px 0 14px; }
@media(max-width:1100px){ .pdacs-wrap .bk-charts { grid-template-columns:repeat(2,minmax(0,1fr)); } }
@media(max-width:760px){ .pdacs-wrap .bk-charts { grid-template-columns:minmax(0,1fr); } }
.pdacs-wrap .chart-box { background:var(--bg2); border:1px solid var(--border); border-radius:10px; padding:16px; min-width:0; transition:border-color .15s; }
.pdacs-wrap .chart-box:hover { border-color:var(--border2); }
.pdacs-wrap .chart-box h4 { font-size:11px; color:var(--muted2); margin-bottom:10px; text-align:center; font-weight:700; text-transform:uppercase; letter-spacing:.09em; font-family:var(--mono); }
.pdacs-wrap .chart-box.wide { grid-column:1 / -1; }
.pdacs-wrap .chart-box canvas { max-height:230px; }
.pdacs-wrap .chart-box.wide canvas { max-height:210px; }
.pdacs-wrap .glance { background:var(--bg2); border:1px solid var(--border); border-radius:10px; padding:18px 20px; margin:8px 0 18px; }
.pdacs-wrap .glance .verdict { font-size:15px; font-weight:600; color:var(--text); margin-bottom:14px; line-height:1.5; }
.pdacs-wrap .gauges { display:grid; grid-template-columns:repeat(6,minmax(0,1fr)); gap:16px; }
@media(max-width:1100px){ .pdacs-wrap .gauges { grid-template-columns:repeat(3,minmax(0,1fr)); } }
@media(max-width:620px){ .pdacs-wrap .gauges { grid-template-columns:repeat(2,minmax(0,1fr)); } }
.pdacs-wrap .gauge .g-top { display:flex; justify-content:space-between; font-size:11px; color:var(--muted); margin-bottom:5px; gap:8px; }
.pdacs-wrap .gauge .g-val { font-family:var(--mono); font-size:18px; font-weight:700; color:var(--text); }
.pdacs-wrap .gauge .g-track { height:8px; background:var(--bg4); border-radius:4px; overflow:hidden; }
.pdacs-wrap .gauge .g-fill { height:100%; border-radius:4px; }
.pdacs-wrap .bsub { font-size:11px; color:var(--muted); font-family:var(--mono); margin:18px 0 8px; text-transform:uppercase; letter-spacing:.12em; }
.pdacs-wrap .pdacs-banner { font-family:var(--mono); font-size:12px; letter-spacing:.18em; text-transform:uppercase; color:#bfeee6; margin:8px 0 22px; border-top:1px solid var(--border); border-bottom:1px solid var(--border); padding:14px 0; text-align:center; }
.pdacs-wrap .cast-card { background:var(--bg2); border:1px solid var(--border); border-radius:10px; padding:12px 16px; margin:0 0 10px; transition:border-color .15s, transform .15s; }
.pdacs-wrap .cast-card:hover { border-color:var(--border2); transform:translateX(2px); }
.pdacs-wrap .cast-head { display:flex; flex-wrap:wrap; align-items:baseline; gap:14px; margin-bottom:8px; }
.pdacs-wrap .cast-head .rk { font-family:var(--mono); font-size:11px; color:var(--muted); }
.pdacs-wrap .cast-head a { font-size:15px; font-weight:700; color:var(--text); text-decoration:none; }
.pdacs-wrap .cast-head a:hover { color:var(--cyan); text-decoration:none; }
.pdacs-wrap .cast-head .rel { font-family:var(--mono); font-size:11px; color:var(--muted2); }
.pdacs-wrap .cast-head .cnt { margin-left:auto; font-family:var(--mono); font-size:14px; font-weight:700; }
.pdacs-wrap .cast-head .shr { font-family:var(--mono); font-size:10px; color:var(--muted); }
.pdacs-wrap .cast-track { height:5px; background:var(--bg4); border-radius:3px; overflow:hidden; margin-bottom:10px; }
.pdacs-wrap .cast-track span { display:block; height:100%; }
.pdacs-wrap .sn-label { font-family:var(--mono); font-size:10px; letter-spacing:.1em; text-transform:uppercase; color:var(--muted); margin-bottom:6px; }
.pdacs-wrap .sn-list { display:flex; flex-wrap:wrap; gap:6px; }
.pdacs-wrap .sn-tag { position:relative; overflow:hidden; background:var(--bg3); border:1px solid var(--border); border-radius:6px; padding:4px 9px; font-family:var(--mono); font-size:11px; color:var(--text); }
.pdacs-wrap .sn-tag em { position:absolute; left:0; bottom:0; height:2px; }
.pdacs-wrap .sn-tag u { text-decoration:none; color:var(--muted2); margin-left:5px; }

/* ============================================================
   SHARED PAGE VOCABULARY
   ------------------------------------------------------------
   These class families were previously duplicated verbatim inside
   individual page <style> blocks — .cf-* in 30 pages, .ov-kpi* in 14,
   .section-card in 18 — each page carrying its own slightly drifted
   copy. They are promoted here once so every page renders the same
   system, and the duplicates were deleted from the pages.

   Cascade note: a page <style> block sits in <body>, i.e. AFTER this
   stylesheet, so any page that still needs a local variant keeps it
   and still wins. Nothing here can override a deliberate page rule.

   No CSS custom property is (re)defined in this file section — the
   tokens in :root at the top are shared with ~220 pages and other
   projects and must stay exactly as they are.
   ============================================================ */

/* ── .cf-* : the analytics page vocabulary (hero / bar / kpi / sec / tbl) ── */

.cf-hero { background:linear-gradient(135deg,rgba(34,227,195,.10),rgba(168,85,247,.05)); border:1px solid var(--border); border-radius:14px; padding:22px 24px; margin-bottom:14px; }
.cf-hero h1 { font-family:var(--mono); font-size:30px; font-weight:900; color:#22e3c3; line-height:1; margin:0; }
.cf-hero .sub { font-family:var(--mono); font-size:11.5px; letter-spacing:.14em; text-transform:uppercase; color:var(--muted2); margin-top:6px; }
.cf-hero .pill { display:inline-block; background:rgba(34,227,195,.12); border:1px solid rgba(34,227,195,.35); border-radius:999px; color:#22e3c3; font-family:var(--mono); font-size:10.5px; font-weight:800; letter-spacing:.1em; text-transform:uppercase; padding:3px 10px; margin-bottom:8px; }
@media(max-width:680px){ .cf-hero { padding:18px 16px; } .cf-hero h1 { font-size:26px; } }

.cf-bar { display:flex; flex-wrap:wrap; align-items:center; gap:10px; background:var(--bg2); border:1px solid var(--border); border-radius:12px; padding:14px 16px; margin:14px 0; }
.cf-bar label { font-family:var(--mono); font-size:10.5px; font-weight:700; letter-spacing:.16em; text-transform:uppercase; color:var(--muted); margin-right:6px; }
.cf-bar select { appearance:none; -webkit-appearance:none; background:var(--bg3); 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 d='M1 1l5 5 5-5' stroke='%2322e3c3' stroke-width='2' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); background-repeat:no-repeat; background-position:right 12px center; border:1px solid var(--border2); border-radius:8px; color:var(--text); font-family:var(--mono); font-size:13px; font-weight:600; min-width:200px; padding:9px 32px 9px 12px; }
.cf-bar select:focus { outline:none; border-color:#22e3c3; box-shadow:0 0 0 3px rgba(34,227,195,.18); }
.cf-bar select:hover { border-color:var(--muted); }

.cf-kpi { display:grid; grid-template-columns:repeat(auto-fit,minmax(120px,1fr)); gap:10px; margin:14px 0; }
.cf-kpi .k { background:var(--bg2); border:1px solid var(--border); border-radius:10px; padding:11px 13px; border-left:3px solid var(--ac,#22e3c3); }
.cf-kpi .k { transition:background .15s; }
.cf-kpi .k:hover { background:var(--bg3); }
.cf-kpi .k .lbl { font-family:var(--mono); font-size:9.5px; font-weight:700; letter-spacing:.14em; text-transform:uppercase; color:var(--muted); }
.cf-kpi .k .val { font-family:var(--mono); font-size:18px; font-weight:800; color:var(--text); line-height:1.1; margin-top:4px; }
.cf-kpi .k .sub { font-family:var(--mono); font-size:9.5px; color:var(--muted2); margin-top:3px; }

.cf-sec { background:var(--bg2); border:1px solid var(--border); border-radius:12px; padding:16px 18px; margin-bottom:14px; }
.cf-sec h3 { font-family:var(--mono); font-size:12px; font-weight:800; letter-spacing:.16em; text-transform:uppercase; color:#bfeee6; border-bottom:1px solid var(--border); padding-bottom:8px; margin:0 0 12px; }

.cf-tbl { width:100%; border-collapse:collapse; font-family:var(--mono); font-size:11.5px; }
.cf-tbl th { background:var(--bg3); color:var(--muted); font-size:9.5px; font-weight:700; letter-spacing:.14em; text-transform:uppercase; text-align:left; padding:7px 8px; border-bottom:1px solid var(--border); }
.cf-tbl td { color:var(--text); padding:6px 8px; border-bottom:1px solid rgba(255,255,255,.04); }
.cf-tbl tr:hover td { background:rgba(255,255,255,.02); }
.cf-tbl .num { text-align:right; font-variant-numeric:tabular-nums; }

.cf-bar2 { display:inline-block; width:100%; max-width:120px; height:6px; background:rgba(255,255,255,.06); border-radius:3px; overflow:hidden; vertical-align:middle; }
.cf-bar2 i { display:block; height:100%; background:linear-gradient(90deg,#22e3c3,#06b6d4); }

.cf-2col { display:grid; grid-template-columns:1fr 1fr; gap:14px; margin-bottom:14px; }
@media(max-width:900px){ .cf-2col { grid-template-columns:1fr; } }

.cf-chart { position:relative; height:240px; }

.cf-pyr { display:grid; grid-template-columns:1fr 80px 1fr; align-items:center; gap:6px; margin:8px 0; }
.cf-pyr .lbl { font-family:var(--mono); font-size:11px; font-weight:700; color:var(--muted2); text-align:center; }
.cf-pyr .bM { display:flex; align-items:center; justify-content:flex-end; }
.cf-pyr .bF { display:flex; align-items:center; justify-content:flex-start; }
.cf-pyr .bM i { display:block; height:18px; background:linear-gradient(90deg,#1d4ed8,#3b82f6); border-radius:3px 0 0 3px; }
.cf-pyr .bF i { display:block; height:18px; background:linear-gradient(90deg,#ec4899,#be185d); border-radius:0 3px 3px 0; }
.cf-pyr .val { font-family:var(--mono); font-size:11px; color:var(--text); min-width:50px; }
.cf-pyr .valM { color:#7bb6ff; text-align:right; }
.cf-pyr .valF { color:#ffb3d9; text-align:left; }

.cf-gauge { display:flex; flex-direction:column; align-items:center; gap:4px; background:var(--bg3); border:1px solid var(--border); border-radius:10px; padding:14px; }
.cf-gauge .num { font-family:var(--mono); font-size:22px; font-weight:900; color:var(--text); line-height:1; }
.cf-gauge .lbl { font-family:var(--mono); font-size:9.5px; letter-spacing:.14em; text-transform:uppercase; color:var(--muted); text-align:center; }
.cf-gauge.green .num { color:#22c55e; }
.cf-gauge.amber .num { color:#fde047; }
.cf-gauge.red   .num { color:#ef4444; }
.cf-gauge.cyan  .num { color:#22e3c3; }

.cf-pill { display:inline-block; background:rgba(34,227,195,.1); border:1px solid rgba(34,227,195,.25); border-radius:999px; color:#22e3c3; font-family:var(--mono); font-size:10px; font-weight:700; padding:3px 8px; margin-right:4px; }
.cf-pill.amber  { background:rgba(253,224,71,.1); border-color:rgba(253,224,71,.25); color:#fde047; }
.cf-pill.purple { background:rgba(168,85,247,.1); border-color:rgba(168,85,247,.25); color:#a78bfa; }

.cf-cards { display:grid; grid-template-columns:repeat(auto-fit,minmax(180px,1fr)); gap:8px; margin-top:8px; }

/* ── .ov-kpi* : overview KPI tiles ── */
.ov-kpi-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(170px,1fr)); gap:14px; margin:18px 0; }
.ov-kpi { background:var(--bg2); border:1px solid var(--border); border-radius:12px; padding:18px; }
.ov-kpi { transition:border-color .15s; }
.ov-kpi:hover { border-color:var(--border2); }
.ov-kpi .l { font-family:var(--mono); font-size:10px; letter-spacing:.12em; text-transform:uppercase; color:var(--muted2); }
.ov-kpi .v { font-family:var(--mono); font-size:24px; font-weight:700; color:var(--text); line-height:1.1; margin-top:6px; }
.ov-kpi.k-blue   .v { color:#06b6d4; }
.ov-kpi.k-amber  .v { color:#f59e0b; }
.ov-kpi.k-red    .v { color:#f43f5e; }
.ov-kpi.k-orange .v { color:#fb923c; }
.ov-kpi.k-purple .v { color:#a855f7; }
.ov-kpi.k-green  .v { color:#10b981; }
.ov-kpi.k-cyan   .v { color:#22e3c3; }
@media(max-width:600px){
    .ov-kpi-grid { grid-template-columns:repeat(auto-fit,minmax(130px,1fr)); }
    .ov-kpi .v { font-size:18px; }
}

/* ── .section-card : the generic titled panel ── */
.section-card { background:var(--bg2); border:1px solid var(--border); border-radius:12px; padding:18px 20px; margin-bottom:18px; }
.section-card .sh { font-family:var(--mono); font-size:12px; letter-spacing:.14em; text-transform:uppercase; color:var(--muted2); border-bottom:1px solid var(--border); padding-bottom:8px; margin-bottom:14px; }

/* ── .charts-grid : two-up chart panels (16 pages; 5 had no rule at all) ── */
.charts-grid { display:grid; grid-template-columns:1fr 1fr; gap:18px; margin-bottom:18px; }
@media(max-width:900px){ .charts-grid { grid-template-columns:1fr; } }

/* ── .svc-hero* : service banner on the hub pages ──
   Used by 5 hub pages and defined by none of them, so these rendered as
   unstyled text. --hero is the accent; each modifier sets it. */
.svc-hero {
    --hero:#22e3c3;
    background:linear-gradient(135deg, color-mix(in srgb, var(--hero) 12%, transparent) 0%, color-mix(in srgb, var(--hero) 3%, transparent) 55%, transparent 100%), var(--bg2);
    border:1px solid color-mix(in srgb, var(--hero) 28%, var(--border2));
    border-radius:18px; padding:20px 22px; margin:12px 0 0;
    box-shadow:0 2px 10px rgba(0,0,0,.25);
}
.svc-hero--sir   { --hero:#3b82f6; }
.svc-hero--caste { --hero:#f59e0b; }
.svc-hero--demo  { --hero:#a855f7; }
.svc-hero--em    { --hero:#10b981; }
.svc-hero__head { display:flex; align-items:center; gap:14px; }
/* The Bootstrap Icons webfont is not vendored in this project, so the <i>
   elements are empty; collapse them rather than reserving a blank gutter. */
.svc-hero__icon { font-size:32px; color:var(--hero); line-height:1; }
.svc-hero__icon:empty { display:none; }
.svc-hero__title { font-family:var(--mono); font-size:19px; font-weight:800; color:var(--text); margin:0; line-height:1.2; }
.svc-hero__sub { font-size:12px; color:var(--muted2); margin:3px 0 0; font-weight:500; letter-spacing:.02em; }
.svc-hero-divider { display:flex; align-items:center; gap:10px; margin:18px 0 6px; }
.svc-hero-divider__line { flex:1; height:1px; background:linear-gradient(90deg,transparent,var(--border2),transparent); }
.svc-hero-divider__dot { width:5px; height:5px; border-radius:50%; background:var(--border2); flex:none; }

/* ── .tlh* : timeline page header (7 pages used it, 1 defined it) ── */
.tlh { margin-top:12px; padding:18px 16px 14px; background:linear-gradient(145deg, color-mix(in srgb, var(--hero) 8%, transparent), transparent); border:1px solid color-mix(in srgb, var(--hero) 30%, var(--border)); border-radius:18px; }
.tlh-head { display:flex; align-items:center; gap:12px; margin-bottom:12px; }
.tlh-ico { font-size:32px; color:var(--hero); line-height:1; }
.tlh-ico:empty { display:none; }
.tlh-title { font-size:17px; font-weight:800; color:var(--text); margin:0; }
.tlh-sub { font-size:11.5px; color:var(--muted); margin:2px 0 0; font-weight:500; }
.tlh-nav { display:flex; flex-wrap:wrap; gap:6px; }
.tlh-chip { display:inline-flex; align-items:center; gap:5px; padding:6px 12px; border-radius:20px; font-size:11px; font-weight:700; color:var(--c); background:color-mix(in srgb, var(--c) 10%, transparent); border:1px solid color-mix(in srgb, var(--c) 25%, transparent); text-decoration:none; transition:background .15s; }
.tlh-chip:hover { background:color-mix(in srgb, var(--c) 18%, transparent); text-decoration:none; }
.tlh-chip i { font-size:13px; }

/* ── generic chips ── */
.chips { display:flex; flex-wrap:wrap; gap:8px; }
.chip { display:inline-block; background:var(--bg3); border:1px solid var(--border); border-radius:7px; color:var(--muted2); font-family:var(--mono); font-size:11.5px; padding:6px 11px; }
a.chip { text-decoration:none; transition:border-color .15s, color .15s; }
a.chip:hover { border-color:var(--border2); color:var(--text); text-decoration:none; }

/* ── numeric table cells ──
   .num is used on 65 pages but only styled inside .cf-tbl on 51 of them. */
.num { text-align:right; font-variant-numeric:tabular-nums; }

/* ── explicit card-row counts ──
   .cards-grid keeps auto-fill: the pages that use it carry anywhere from 4
   to 12 cards, and a fixed count would either squash or strand them. The
   min track is raised so cards stop shrinking to unreadable widths, and the
   numbered modifiers below give a fixed rhythm where a page wants one
   (joining the pre-existing .cards-grid-7 / -8). */
.cards-grid-2, .cards-grid-3, .cards-grid-4, .cards-grid-5, .cards-grid-6 { display:grid; gap:10px; margin-bottom:24px; }
.cards-grid-2 { grid-template-columns:repeat(2,minmax(0,1fr)); }
.cards-grid-3 { grid-template-columns:repeat(3,minmax(0,1fr)); }
.cards-grid-4 { grid-template-columns:repeat(4,minmax(0,1fr)); }
.cards-grid-5 { grid-template-columns:repeat(5,minmax(0,1fr)); }
.cards-grid-6 { grid-template-columns:repeat(6,minmax(0,1fr)); }
@media(max-width:1100px){
    .cards-grid-4, .cards-grid-5, .cards-grid-6 { grid-template-columns:repeat(3,minmax(0,1fr)); }
}
@media(max-width:680px){
    .cards-grid-3, .cards-grid-4, .cards-grid-5, .cards-grid-6 { grid-template-columns:repeat(2,minmax(0,1fr)); }
}

/* ── --vc-* aliases ──
   50 references across the pages point at a --vc-* palette that was never
   defined anywhere in this project, so those declarations were dropped by the
   browser as invalid. These are ALIASES onto the existing tokens above — no
   token declared earlier in this file is redefined, so nothing is re-themed. */
:root {
    --vc-bg-surface: var(--bg2);
    --vc-border:     var(--border);
    --vc-text-high:  var(--text);
    --vc-text-muted: var(--muted);
    --vc-primary:    var(--green);
    --vc-danger:     var(--red);
}

/* ── LoadingSpinner component (Components/Shared/LoadingSpinner.razor) ──
   Rendered by nearly every page while data loads and previously carried no
   styling at all — a bare unstyled div. */
.vc-loading { display:flex; flex-direction:column; align-items:center; justify-content:center; gap:12px; padding:38px 16px; }
.vc-loading--fullpage { min-height:52vh; }
.vc-loading__ring { width:30px; height:30px; border-radius:50%; border:3px solid var(--border2); border-top-color:var(--green); animation:vc-spin .8s linear infinite; }
.vc-loading__text { font-family:var(--mono); font-size:11px; letter-spacing:.14em; text-transform:uppercase; color:var(--muted); }
@keyframes vc-spin { to { transform:rotate(360deg); } }
@media (prefers-reduced-motion:reduce) {
    .vc-loading__ring { animation-duration:2.4s; }
}

/* ── .vc-card : generic surface used by the PDA-G pages ── */
.vc-card { background:var(--bg2); border:1px solid var(--border); border-radius:10px; }

/* ── .cv-pick : the geo picker form on the Overview pages ── */
.cv-pick { display:flex; flex-wrap:wrap; align-items:center; gap:10px; background:var(--bg2); border:1px solid var(--border); border-radius:12px; padding:12px 14px; margin:14px 0 20px; }
.cv-pick label { font-family:var(--mono); font-size:10px; font-weight:700; letter-spacing:.14em; text-transform:uppercase; color:var(--muted); }
.cv-pick select, .cv-pick input { background:var(--bg3); color:var(--text); border:1px solid var(--border2); border-radius:8px; padding:8px 12px; font-family:var(--mono); font-size:13px; }
.cv-pick select:focus, .cv-pick input:focus { outline:none; border-color:var(--cyan); box-shadow:0 0 0 2px var(--cyan-dim); }

/* ── .tl-count : row-count caption on the Timeline pages ── */
.tl-count { font-family:var(--mono); font-size:11px; letter-spacing:.1em; text-transform:uppercase; color:var(--muted); margin:10px 0 14px; }

/* ── .su-tbl : surname table (Community/Occupation/Booth) ── */
.su-tbl { width:100%; border-collapse:collapse; font-family:var(--mono); font-size:12px; }
.su-tbl th { background:var(--bg3); color:var(--muted); font-size:9.5px; font-weight:700; letter-spacing:.14em; text-transform:uppercase; text-align:left; padding:7px 8px; border-bottom:1px solid var(--border); }
.su-tbl td { color:var(--text); padding:6px 8px; border-bottom:1px solid rgba(255,255,255,.04); }
.su-tbl tr:hover td { background:rgba(255,255,255,.02); }

/* ── Bootstrap Icons ──
   ~40 pages render <i class="bi bi-*"> but the bootstrap-icons webfont is not
   vendored in this project and no CDN is permitted, so those glyphs cannot be
   drawn. Collapse the empty elements so they do not leave a blank gutter or a
   stray inline box next to headings. */
i.bi:empty, span.bi:empty { display:none; }

/* ── Wide content must scroll inside itself, never the page ── */
.table-scroll, .scroll-x { overflow-x:auto; }

/* .cd-row — Cast Drill leaderboard row. Its grid is applied inline on the
   element; this only adds the hover affordance the link row was missing. */
.cd-row { transition:background .15s; }
.cd-row:hover { background:var(--bg3); }

/* ── Dropdown affordance ──
   Every <select> gets a visible chevron. Without it a select styled to match the
   surrounding inputs is indistinguishable from a text box, so nothing tells the
   user it opens a list -- which is exactly how the Category and Occupation
   fields on the voter form read.

   appearance:none removes the platform arrow (which is drawn light-on-light and
   effectively invisible in a dark WebView on Android), and the chevron is a data
   URI so it still renders with no network in the field. Padding on the right
   keeps a long option from running underneath it. */
select,
.vr-f select,
select.inp,
select.form-select {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 4.5 6 8l3.5-3.5' stroke='%23cbd5e1' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-size: 12px;
    padding-right: 30px;
}

/* The native popup inherits the page, not the control, so option colours are set
   explicitly or they come out unreadable on a dark theme. */
select option { background: #142014; color: #e6f0e6; }

/* A multi-select or a sized list is not a dropdown and must not claim to be. */
select[multiple],
select[size]:not([size="1"]) {
    background-image: none;
    padding-right: 10px;
}

/* ════════════════════════════════════════════════════════════════════════
   HERO HEADERS  (each card declares a plain background before the color-mix
   one: a color-mix fallback, since an unsupported value voids the whole
   declaration and would leave the card transparent)
   ────────────────────────────────────────────────────────────────────────
   Every page title becomes a card, and it is done HERE rather than in the
   227 .razor files that render one. They all already share .page-header,
   so restyling the class reaches every page at once -- including the sixty
   that go through <VotersHeader> -- with no markup to get wrong and one
   place to tune afterwards.

   The existing per-family accent is kept, not replaced: --ph-accent is
   already green for /voters, cyan for /booth and purple for AI, and it now
   drives the rail, the wash and the glow together so a page still announces
   which family it belongs to.
   ════════════════════════════════════════════════════════════════════════ */

.page-header {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    flex-wrap: wrap;

    padding: 15px 17px 15px 19px;
    margin-bottom: 20px;
    border-radius: 0 12px 12px 0;

    border: 1px solid rgba(255, 255, 255, .075);
    border-left: 0;

    /*  A wash angled off the family accent, at low enough alpha that the card
        reads as lit from the rail rather than tinted a colour. The second
        layer is the flat panel underneath it. */
    background: var(--bg2, #121a12);
    background:
        linear-gradient(105deg,
            color-mix(in srgb, var(--ph-accent, var(--green)) 13%, transparent) 0%,
            color-mix(in srgb, var(--ph-accent, var(--green)) 4%, transparent) 40%,
            transparent 74%),
        var(--bg2, #121a12);

    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .035),
        0 6px 18px rgba(0, 0, 0, .28);
}

/*  The rail was a 3px bar floated inside the old flat header; as a card edge it
    runs the full height and carries a soft bloom so it looks lit rather than
    drawn on. */
.page-header::before {
    content: "";
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 3px;
    border-radius: 0;
    background: var(--ph-accent, var(--green));
    box-shadow: 0 0 12px -1px var(--ph-accent, var(--green));
}

.page-title {
    font-family: inherit;
    font-size: 22px;
    font-weight: 800;
    letter-spacing: -.012em;
    line-height: 1.16;
    color: var(--text);
    text-wrap: balance;
}

/*  Subtitle as an uppercase mono eyebrow: it is almost always a location or a
    count -- "Booth 101 · AC 100" -- which is reference data, not prose, and
    reads faster spaced out than set as a sentence. */
.page-subtitle,
.page-header .page-sub {
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: .11em;
    text-transform: uppercase;
    color: var(--muted2, var(--muted));
    margin-top: 5px;
}

.page-hd { align-items: center; gap: 13px; }

.page-icon,
.page-icon-svg {
    opacity: 1;
    margin-top: 0;
    filter: drop-shadow(0 2px 5px rgba(0, 0, 0, .45));
}

.page-actions { align-self: center; }

@media (max-width: 560px) {
    .page-header { padding: 13px 13px 13px 15px; border-radius: 0 10px 10px 0; }
    .page-title  { font-size: 19px; }
    /*  Stays an eyebrow at every width: the page sheet's type-scale block bumped
        .page-subtitle to 13px as collateral of grouping it with its own earlier
        13px definition, which undid the deliberate 11px uppercase mono treatment
        below. 11px is already at the floor, so only the sub-11px value moved. */
    .page-subtitle, .page-header .page-sub { font-size: 11px; letter-spacing: .09em; }
}

/* ── Dashboard hero (Home) ────────────────────────────────────────────────
   Home names a place rather than a page, so it keeps its centred layout and
   gets the same card treatment around it. */
.bv-hero {
    position: relative;
    text-align: center;
    padding: 26px 18px 22px;
    margin: 0 0 22px;
    border-radius: 14px;
    border: 1px solid rgba(255, 255, 255, .075);
    background: var(--bg2, #121a12);
    background:
        radial-gradient(120% 130% at 50% -25%,
            color-mix(in srgb, var(--accent, #f59e0b) 15%, transparent) 0%,
            transparent 62%),
        var(--bg2, #121a12);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .04),
        0 8px 26px rgba(0, 0, 0, .32);
    overflow: hidden;
}

/*  A hairline across the top, brightest at the centre, so the card has a lip
    to catch the eye without a heavy border. */
.bv-hero::before {
    content: "";
    position: absolute;
    left: 12%; right: 12%; top: 0;
    height: 1px;
    background: linear-gradient(90deg,
        transparent,
        var(--accent, #f59e0b) 50%,
        transparent);
    opacity: .55;
}

.bv-hero h1 {
    font-size: clamp(19px, 5.2vw, 25px);
    font-weight: 800;
    letter-spacing: -.015em;
    line-height: 1.2;
    margin: 0;
    text-wrap: balance;
}

.bv-hero-sub {
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: .11em;
    text-transform: uppercase;
    color: var(--muted2, var(--muted));
    margin: 9px 0 0;
}

/* ── Section headers ──
   The same rail idea one level down, so a section reads as belonging to the
   page above it rather than as another unrelated band. */
.section-hdr {
    position: relative;
    padding-left: 11px;
    margin-top: 22px;
}

.section-hdr::before {
    content: "";
    position: absolute;
    left: 0; top: 50%;
    width: 3px; height: 13px;
    transform: translateY(-50%);
    border-radius: 2px;
    background: var(--accent, #f59e0b);
    opacity: .8;
}

/* ── Splitters ────────────────────────────────────────────────────────────
   One divider treatment, reached three ways so no page needs new markup to
   get it: the .split utility, any bare <hr> (there are eleven across the
   apps and none of them were styled -- they rendered as the browser's grey
   default inset line on a dark page), and the footer back-link, which is the
   same "end of content" moment on 65 pages.

   A rule that fades at both ends reads as a divider; one that runs edge to
   edge reads as a border and implies the thing below is a different region.
   The diamond marks the centre so the line has a reason to be there. */

.split,
hr {
    position: relative;
    height: 1px;
    border: 0;
    margin: 20px 0 22px;
    background: linear-gradient(90deg,
        transparent,
        rgba(255, 255, 255, .13) 18%,
        rgba(255, 255, 255, .13) 82%,
        transparent);
    overflow: visible;
}

.split::after,
hr::after {
    content: "";
    position: absolute;
    left: 50%; top: 50%;
    width: 7px; height: 7px;
    transform: translate(-50%, -50%) rotate(45deg);
    background: var(--accent, #f59e0b);
    box-shadow: 0 0 0 4px var(--bg, #0a120a), 0 0 10px rgba(245, 158, 11, .45);
}

/*  A plain rule, for places where the diamond would be one mark too many. */
.split-plain::after, hr.plain::after { display: none; }

/*  End-of-page back link. The divider is drawn above the link rather than
    added as an element, so all 65 pages that already render one pick it up
    without being touched. Width is capped so it stays a divider and does not
    become a full-bleed border on a wide screen. */
.back-link {
    position: relative;
    display: inline-block;
    margin-top: 30px;
}

.back-link::before {
    content: "";
    position: absolute;
    left: 50%; top: -17px;
    transform: translateX(-50%);
    width: min(340px, 66vw);
    height: 1px;
    background: linear-gradient(90deg,
        transparent,
        rgba(255, 255, 255, .12) 22%,
        rgba(255, 255, 255, .12) 78%,
        transparent);
}

/* ── Analysis hero (compact variant) ──
   Home and Analysis were the same centred card carrying the same @GeoName and
   subtitles two words apart, so switching tabs looked like nothing had
   happened. Home names a PLACE and is the front door, so it keeps the tall
   centred treatment. Analysis is a working screen, so it gets a shorter
   left-aligned band with an eyebrow: different silhouette, and it gives back
   the vertical space to the charts that are the actual content. */
.bv-hero.hero-work {
    text-align: left;
    padding: 14px 16px 14px 18px;
    border-radius: 0 12px 12px 0;
    background: var(--bg2, #121a12);
    background:
        linear-gradient(100deg,
            color-mix(in srgb, var(--purple, #a855f7) 13%, transparent) 0%,
            color-mix(in srgb, var(--purple, #a855f7) 4%, transparent) 42%,
            transparent 76%),
        var(--bg2, #121a12);
}

/*  Rail instead of the top hairline, so the two heroes do not even share an
    edge treatment. */
.bv-hero.hero-work::before {
    left: 0; right: auto; top: 0; bottom: 0;
    width: 3px; height: auto;
    background: var(--purple, #a855f7);
    box-shadow: 0 0 12px -1px var(--purple, #a855f7);
    opacity: 1;
}

.bv-hero.hero-work .hero-eyebrow {
    display: block;
    font-family: var(--mono);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--purple, #a855f7);
    margin: 0 0 5px;
}

.bv-hero.hero-work h1 {
    font-size: clamp(16px, 4.2vw, 19px);
    line-height: 1.25;
    text-wrap: balance;
}

.bv-hero.hero-work .bv-hero-sub {
    margin-top: 6px;
    letter-spacing: .09em;
}

/* ── Centred page header ──
   For a hub screen whose header names the place rather than labelling a list.
   Same card, same family rail, stacked and centred so it reads as an opening
   rather than a row of controls. */
.page-header.ph-center {
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 10px;
    padding: 17px 16px 16px;
}

.page-header.ph-center > div { width: 100%; }
.page-header.ph-center .page-actions { align-self: center; }

/*  The rail would sit off to one side of centred text, so a centred header
    takes the hairline the dashboard hero uses instead. */
.page-header.ph-center::before {
    left: 12%; right: 12%; top: 0; bottom: auto;
    width: auto; height: 1px;
    background: linear-gradient(90deg, transparent,
        var(--ph-accent, var(--green)) 50%, transparent);
    box-shadow: none;
    opacity: .6;
}

.page-header.ph-center { border-left: 1px solid rgba(255,255,255,.075); border-radius: 12px; }

/* ── Centred hero background ──
   A plain panel under centred text looked empty, so the card gets three
   layers, all pure CSS so nothing has to load in the field:

     1. a soft dome of the family accent rising from the top edge,
     2. a fine diagonal weave at very low alpha for texture,
     3. the flat panel underneath.

   The weave is 1px lines on a 7px repeat -- close enough to read as a surface
   rather than as stripes, and it sits under the text at 2.5% so it never
   competes with it. */
.page-header.ph-center {
    background: var(--bg2, #121a12);
    background:
        radial-gradient(125% 150% at 50% -30%,
            color-mix(in srgb, var(--ph-accent, var(--green)) 20%, transparent) 0%,
            color-mix(in srgb, var(--ph-accent, var(--green)) 5%, transparent) 38%,
            transparent 66%),
        repeating-linear-gradient(135deg,
            rgba(255, 255, 255, .025) 0px,
            rgba(255, 255, 255, .025) 1px,
            transparent 1px,
            transparent 7px),
        var(--bg2, #121a12);
    overflow: hidden;
}

/*  A faint bloom behind the title, so the centre of the card is the brightest
    point and the eye lands on the name first. */
.page-header.ph-center .page-title {
    position: relative;
    text-shadow: 0 0 26px color-mix(in srgb, var(--ph-accent, var(--green)) 32%, transparent);
}

/*  Corner ticks: two short rules at the lower corners that stop the textured
    panel from ending abruptly. */
.page-header.ph-center::after {
    content: "";
    position: absolute;
    left: 18%; right: 18%; bottom: 0;
    height: 1px;
    background: linear-gradient(90deg, transparent,
        color-mix(in srgb, var(--ph-accent, var(--green)) 45%, transparent) 50%,
        transparent);
    opacity: .5;
}

/*  first-thing tightening: <main> pads 16px all round, which suits a page that
    opens with text but leaves a visible band above a card meant to sit just
    under the top bar. */
main.main > .comms-row:first-child,
main.main > .page-header:first-child,
main.main > .bv-hero:first-child { margin-top: -6px; }
/* ── Booth combobox ──
   A text input bound to a <datalist>: type a number or part of the name and the
   browser narrows the suggestions. Replaces a <select> that listed ~440 booths
   with no way in but scrolling.

   Sized and coloured to match the selects beside it so the filter bar still
   reads as one row of controls, and given the same chevron so it is obviously
   a list and not a free-text field. */
.bc-input {
    min-width: 210px;
    flex: 1 1 210px;
    padding: 7px 28px 7px 11px;
    border-radius: 8px;
    border: 1px solid rgba(255, 255, 255, .14);
    background-color: rgba(255, 255, 255, .05);
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 4.5 6 8l3.5-3.5' stroke='%23cbd5e1' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 9px center;
    background-size: 12px;
    color: var(--text);
    font-family: inherit;
    font-size: 13px;
}

.bc-input::placeholder { color: var(--muted2, var(--muted)); opacity: .75; }
.bc-input:focus { outline: none; border-color: var(--accent); }

/*  Typed text that does not resolve to a booth yet. Not an error -- it is what
    a half-finished word looks like -- so it warns rather than shouts, and the
    previously chosen booth is still what would submit. */
.bc-input.bc-bad { border-color: var(--amber, #f59e0b); }

/*  Chromium draws its own dropdown arrow inside a datalist input on some
    builds; ours is already in the background. */
.bc-input::-webkit-calendar-picker-indicator { opacity: 0; }

@media (max-width: 480px) {
    .bc-input { min-width: 0; width: 100%; flex-basis: 100%; }
}

/* ── Booth combobox dropdown ──
   Drawn here rather than by a native <datalist>. On Android the WebView renders
   datalist suggestions as an unstyled list that floats over the page, ignores
   the theme and clips every booth name mid-word -- the number and the name
   arrive as one truncated string. This list is ordinary markup, so it is
   themed, scrollable, and can show the number and the name as two things. */
.bc-host { position: relative; display: inline-flex; flex: 1 1 240px; min-width: 0; }

.bc-list {
    position: absolute; left: 0; right: 0; top: calc(100% + 4px);
    z-index: 60;
    max-height: min(52vh, 340px);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    background: var(--bg2, #121a12);
    border: 1px solid rgba(255, 255, 255, .14);
    border-radius: 10px;
    box-shadow: 0 12px 34px rgba(0, 0, 0, .55);
    padding: 4px;
}

.bc-item {
    display: flex; align-items: baseline; gap: 9px;
    padding: 9px 10px;
    border-radius: 7px;
    cursor: pointer;
    line-height: 1.25;
}

.bc-item + .bc-item { border-top: 1px solid rgba(255, 255, 255, .05); }
.bc-item:hover, .bc-item.bc-on { background: rgba(255, 255, 255, .07); }

/*  The number is the thing being submitted, so it is fixed-width and leads;
    the name wraps to a second line rather than being cut, which is the whole
    complaint about the native list. */
.bc-n {
    font-family: var(--mono); font-size: 12.5px; font-weight: 700;
    color: var(--accent); flex: 0 0 auto; min-width: 30px;
}
.bc-t { font-size: 13px; color: var(--text); overflow-wrap: anywhere; }

.bc-none { padding: 12px 10px; font-size: 13px; color: var(--muted2, var(--muted)); }

@media (max-width: 480px) {
    .bc-list { max-height: 46vh; }
    .bc-item { padding: 11px 10px; }   /* a comfortable touch target */
}

/* ── password reveal ── */
.pw-wrap { position:relative; display:block; }
/*  Room for the eye so a long password does not run under it. */
.pw-input { padding-right:46px; }
.pw-eye { position:absolute; top:50%; right:6px; transform:translateY(-50%); width:36px; height:36px; display:flex; align-items:center; justify-content:center; padding:0; background:transparent; border:none; border-radius:8px; color:var(--muted); cursor:pointer; transition:color .15s, background .15s; }
.pw-eye:hover { color:var(--text); background:rgba(255,255,255,.06); }
.pw-eye:focus-visible { outline:2px solid var(--login-accent); outline-offset:-2px; }
.pw-eye svg { width:19px; height:19px; fill:currentColor; }
/*  Only one glyph shows at a time: open eye while hidden, struck-through while
    visible, so the icon reports the current state rather than the action. */
.pw-eye .pw-off { display:none; }
.pw-eye.on { color:var(--login-accent); }
.pw-eye.on .pw-on { display:none; }
.pw-eye.on .pw-off { display:block; }

/*  Sidebar filter box — added by js/navmenu.js, styled here so it matches the
    rail rather than carrying inline styles. Sticky so it stays reachable while
    the 21-section rail scrolls beneath it. */
.nav-filter{position:sticky;top:0;z-index:2;padding:8px 10px;background:var(--bg2,#0f1720);
    border-bottom:1px solid var(--border,rgba(255,255,255,.08))}
.nav-filter input{width:100%;box-sizing:border-box;padding:7px 10px;font-size:12.5px;
    font-family:var(--mono,ui-monospace,monospace);color:var(--text,#e2e8f0);
    background:var(--bg3,rgba(255,255,255,.05));border:1px solid var(--border,rgba(255,255,255,.12));
    border-radius:7px;outline:none}
.nav-filter input:focus{border-color:var(--cyan,#06b6d4)}
.nav-filter input::placeholder{color:var(--muted,#64748b)}

/* ══════════════════════════════════════════════════════════════════════════
   Brand mark, rail collapse, and the section controls at the foot of the rail.
   Appended after the shell rules above so these win without !important.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── brand ── */
/*  A link, so it needs the reset .topbar a would otherwise impose on it. */
.topbar-logo { display:flex; align-items:center; gap:10px; text-decoration:none; }
.topbar a.topbar-logo { color:var(--text-hi); }
.topbar-logo:hover { text-decoration:none; }

/*  Amber, not the green accent: green is reserved for live/active/positive, and
    a permanent green fixture makes it mean less everywhere it is a signal. The
    fill is a 14%-alpha wash rather than a solid block -- "not green bg" applies
    to the mark as a whole, which should read as an outlined glyph, not a chip. */
.brand-mark { width:26px; height:26px; flex-shrink:0; overflow:visible; }
.brand-mark rect { fill:var(--amber-dim); stroke:var(--amber); stroke-width:1.5; }
.brand-mark text {
    fill:var(--amber); font-family:var(--mono); font-size:13px; font-weight:700;
    letter-spacing:.04em; text-anchor:middle;
}
.topbar-logo:hover .brand-mark rect { fill:var(--amber); stroke:var(--amber); }
.topbar-logo:hover .brand-mark text { fill:var(--bg); }
.brand-mark rect, .brand-mark text { transition:fill .15s, stroke .15s; }

.brand-text { font-family:var(--mono); font-size:12px; font-weight:400; letter-spacing:.15em;
    text-transform:uppercase; color:var(--muted); white-space:nowrap; }
.brand-text b { color:var(--text-hi); font-weight:700; }

/* ── rail: collapse control ── */
/*  Sits inside .nav-filter (navmenu.js moves it there), so it is not sticky itself --
    the filter row already is, and two sticky elements at top:0 covered each other. */
.nav-filter { display:flex; align-items:center; gap:8px; }
.nav-filter input { flex:1; min-width:0; }
.rail-collapse { flex-shrink:0; display:flex; align-items:center; justify-content:center;
    width:30px; height:30px; padding:0; background:var(--bg3); border:1px solid var(--border);
    border-radius:var(--radius); cursor:pointer; transition:all .15s; }
.rail-collapse:hover { background:var(--bg4); border-color:var(--border2); }
.rail-collapse-icon { display:block; width:13px; height:11px; border-left:2px solid var(--muted);
    border-right:2px solid var(--muted); position:relative; transition:border-color .15s; }
.rail-collapse-icon::before { content:""; position:absolute; inset:4px 3px auto 3px; height:2px;
    background:var(--muted); transition:background .15s; }
.rail-collapse:hover .rail-collapse-icon { border-color:var(--text-hi); }
.rail-collapse:hover .rail-collapse-icon::before { background:var(--text-hi); }

/* ── rail: collapsed state ──
   Driven by a class on <body> rather than the rail, because .main's width is a
   sibling concern: collapsing the rail has to give the content the space back. */
body.rail-collapsed .sidebar { width:52px; min-width:52px; }
body.rail-collapsed .sidebar .nav-filter input,
body.rail-collapsed .sidebar .rail-foot,
body.rail-collapsed .sidebar .nav-label,
/*  The link's label is a bare TEXT NODE beside the icon span, not an element, so no
    child selector can reach it -- `> :not(.icon)` hid nothing and the collapsed rail
    rendered every label wrapped over three lines. Zeroing the font on the link and
    restoring it on the icon is the only selector-reachable way to drop a text node. */
body.rail-collapsed .sidebar .nav-link { font-size:0; }
/*  Every section shows its links while collapsed: with the headings hidden there
    is nothing left to expand, and an icon rail that hides most of its icons is
    just a narrow empty column. */
body.rail-collapsed .sidebar .nav-section > .nav-link { display:flex; }
body.rail-collapsed .sidebar .nav-link { justify-content:center; padding:8px 0; gap:0; }
body.rail-collapsed .sidebar .nav-link .icon { width:auto; font-size:15px; line-height:1; }
body.rail-collapsed .sidebar .nav-filter { justify-content:center; padding:8px 0; }
body.rail-collapsed .rail-collapse-icon { transform:rotate(180deg); }

/*  The label rides along on hover so a collapsed rail is still navigable without
    expanding it. position:fixed escapes the rail's overflow-y:auto clip. */
body.rail-collapsed .sidebar .nav-link { position:relative; }
/*  top comes from --row-y, set by navmenu.js on hover: a fixed element with `top:auto`
    falls back to its static position, which put the label a couple of rows below the
    icon it belonged to. */
body.rail-collapsed .sidebar .nav-link::after {
    content:attr(data-label); position:fixed; left:56px; top:var(--row-y, 0); z-index:300;
    transform:translateY(-50%);
    padding:5px 10px; background:var(--bg4); color:var(--text-hi);
    border:1px solid var(--border2); border-radius:var(--radius);
    font-family:var(--mono); font-size:11.5px; letter-spacing:.04em; white-space:nowrap;
    line-height:1.2;
    opacity:0; pointer-events:none; transition:opacity .12s;
}
body.rail-collapsed .sidebar .nav-link:hover::after { opacity:1; }

/* ── rail: hover and active ── */
/*  The active link keeps the green fill AND gains a left rule, so it is still
    findable at a glance once a dozen sections are open. The hover slide is 2px:
    enough to feel responsive, not enough to reflow the column. */
.nav-link { position:relative; }
.nav-link:hover { transform:translateX(2px); }
.nav-link.active { box-shadow:inset 2px 0 0 0 var(--green); font-weight:600; }
.nav-link.active:hover { transform:none; }
.nav-label:hover { color:var(--text-hi); }
body.rail-collapsed .nav-link:hover { transform:none; }

/* ── rail: foot controls ── */
.rail-foot { display:flex; gap:6px; margin:10px 10px 0; padding-top:10px;
    border-top:1px solid var(--border); }
.rail-all { flex:1; padding:6px 4px; background:var(--bg3); color:var(--muted);
    border:1px solid var(--border); border-radius:var(--radius); cursor:pointer;
    font-family:var(--mono); font-size:9.5px; font-weight:600; letter-spacing:.1em;
    text-transform:uppercase; transition:all .15s; }
.rail-all:hover { background:var(--bg4); color:var(--text-hi); border-color:var(--border2); }
