/* ============================================================
   LAL TOPI — shared theme layer for all 13 pdag.live sites
   ============================================================

   Loaded from _content/Lib.Core AFTER each site's app.css and
   BEFORE its scoped <Site>.styles.css, so it restyles the shared
   shell without editing thirteen forked app.css files, and a
   component's own scoped rule still wins where one exists.

   Removing the two <link> lines from App.razor reverts every site.

   The direction: the Samajwadi red is a SURFACE, not a hairline.
   Previously --red appeared only as a 2px line on a card's top
   edge; here it carries the masthead, the active nav state and
   the panel rules, and green carries every positive value.

   Scope of this pass: chrome (topbar, sidebar, nav), the card and
   panel system, KPIs, tables, buttons and form focus. The
   specialised families -- .geo-*, .cf-*, .vc-*, .pdag-*, .gauge,
   .bc-* -- still inherit app.css and are a deliberate second pass.

   Contrast (WCAG AA, computed not estimated):
     #F2E6DC on #120A0C  16.1:1    body text
     #C99A9F on #1E1013   8.0:1    card labels
     #A87C82 on #1E1013   5.6:1    sub-labels, smallest text used
     #FFFFFF on #E4002B   4.9:1    masthead text on party red
     #00A651 on #1E1013   5.6:1    positive values
   Red and green are adjacent hues and a deuteranopia hazard, so
   neither is ever the ONLY carrier of meaning: every coloured
   value is also a number, and the card rails repeat information
   the label already states.
   ============================================================ */

:root {
    /* Warm near-black. The old palette was blue-grey (#080b0f); this
       shifts the whole ground red-ward so the party colour reads as
       belonging to the surface rather than sitting on top of it. */
    --bg: #120A0C;
    --bg2: #1E1013;
    --bg3: #2E191E;
    --bg4: #3D2229;

    /* Borders were rgba(255,255,255,.06) -- invisible, which is why
       cards never read as objects. Nearly doubled, and warm. */
    --border: rgba(242,230,220,0.11);
    --border2: rgba(242,230,220,0.22);

    --text: #F2E6DC;
    /*  --muted was #A87C82. It cleared AA at 5.16:1 on a card, but most of the
        text that uses it is 10-12px on a dense console -- hero sub-lines, "#21
        by voters", "Surnames inside" -- and at that size a bare pass reads as
        dim, not as readable. Both raised roughly one and a half steps:
        --muted is now 7.40:1 on a card and --muted2 9.52:1, so secondary text
        is comfortably legible without competing with --text. */
    --muted: #C29AA0;
    --muted2: #D4B2B6;

    --red: #E4002B;
    --red-dim: rgba(228,0,43,0.16);
    --green: #00A651;
    --green-dim: rgba(0,166,81,0.16);
    --amber: #FFC72C;
    --amber-dim: rgba(255,199,44,0.14);
    /* These four are NOT decorative -- they are the PDA-G encoding.
       .pdag-p reads var(--amber) (Pichhda), .pdag-d var(--blue) (Dalit),
       .pdag-a var(--green) (Alpasankhyak), .pdag-g var(--purple) (General),
       and .voter-card.vc-m reads var(--blue) for male.
       An earlier draft of this theme set --blue to cream and --cyan to the
       same value as --green, which turned Dalit cream and made two classes
       indistinguishable. Each must stay a separate, nameable hue that also
       clears 4.5:1 on the warm ground. */
    --blue: #7FB2FF;
    --blue-dim: rgba(127,178,255,0.14);
    --cyan: #4FD1C5;
    --cyan-dim: rgba(79,209,197,0.14);
    --purple: #C77DFF;
    --purple-dim: rgba(199,125,255,0.16);

    --accent: #E4002B;
    --accent-dim: rgba(228,0,43,0.14);

    /* Anek Devanagari sets Devanagari and Latin on one set of metrics,
       so a Hindi label and its English counterpart sit at the same
       weight -- Devanagari stops being an afterthought. Mukta carries
       body text; both fall back to the previous stack. */
    --sans: 'Mukta','Inter',system-ui,sans-serif;
    --display: 'Anek Devanagari','Mukta',system-ui,sans-serif;
    --radius: 3px;
}

/* app.css sets `html, body { background:#060a06 }` as a literal, not
   var(--bg), and each site hard-codes a different one -- so the token
   override alone never reaches the page ground and the body stayed a
   green-black behind the warm palette. Restated here explicitly. */
html, body { background: var(--bg); color: var(--text); }
body { font-family: var(--sans); font-size: 14.5px; line-height: 1.55; }

/* ── Masthead ─────────────────────────────────────────────────
   The signature move. A solid band of party red across every
   page, replacing a 52px strip of near-black that read as nothing. */
.topbar {
    background: var(--red);
    border-bottom: none;
    height: 54px;
    box-shadow: 0 2px 0 rgba(0,0,0,.35);
}
.topbar-logo {
    font-family: var(--display); font-size: 19px; font-weight: 800;
    letter-spacing: 0; color: #FFFFFF; text-transform: none;
}
.topbar-logo span { color: rgba(255,255,255,.72); font-weight: 600; }
.topbar-right { font-family: var(--sans); font-size: 12px; color: rgba(255,255,255,.86); font-weight: 600; }
.topbar a { color: rgba(255,255,255,.92); }
.topbar .logout-btn, .topbar .login-link {
    background: rgba(0,0,0,.22); color: #FFFFFF;
    border: 1px solid rgba(255,255,255,.34);
    font-family: var(--sans); font-size: 11px; font-weight: 700; letter-spacing: .06em;
}
.topbar .logout-btn:hover, .topbar .login-link:hover { background: rgba(0,0,0,.38); }

/* ── Sidebar ──────────────────────────────────────────────────
   Active state becomes a red bar, so the current section is
   findable at a glance instead of a slightly lighter grey. */
.sidebar { background: var(--bg2); border-right: 1px solid var(--border); }
.nav-label {
    font-family: var(--sans); font-size: 10.5px; font-weight: 800;
    letter-spacing: .14em; color: var(--muted);
}
.nav-link { font-family: var(--sans); font-size: 13px; font-weight: 600; color: var(--muted2); }
.nav-link:hover { background: var(--bg3); color: var(--text); }
.nav-link.active {
    background: var(--red-dim); color: #FFFFFF;
    box-shadow: inset 3px 0 0 var(--red);
    border-radius: 0 var(--radius) var(--radius) 0;
}
.nav-section + .nav-section { border-top: 1px solid var(--border); }

/* ── Stat cards ───────────────────────────────────────────────
   The accent moves from a top hairline to a 4px foot rule: it
   closes the card instead of floating above it, and at 4px it is
   actually visible on a phone. */
.stat-card {
    background: var(--bg2); border: 1px solid var(--border); border-top: 1px solid var(--border);
    border-bottom: 4px solid var(--green); border-radius: var(--radius);
    padding: 15px 16px;
}
.stat-card.c-green  { border-top: 1px solid var(--border); border-bottom-color: var(--green); }
.stat-card.c-red    { border-top: 1px solid var(--border); border-bottom-color: var(--red); }
.stat-card.c-amber  { border-top: 1px solid var(--border); border-bottom-color: var(--amber); }
.stat-card.c-blue   { border-top: 1px solid var(--border); border-bottom-color: var(--blue); }
.stat-card.c-cyan   { border-top: 1px solid var(--border); border-bottom-color: var(--cyan); }
.stat-card.c-purple { border-top: 1px solid var(--border); border-bottom-color: var(--purple); }
.stat-card.c-gray   { border-top: 1px solid var(--border); border-bottom-color: #7A5057; }

.card-label {
    font-family: var(--sans); font-size: 11.5px; font-weight: 800;
    letter-spacing: .09em; text-transform: uppercase; color: var(--muted2);
    margin-bottom: 7px;
}
.card-value {
    font-family: var(--display); font-size: 30px; font-weight: 800;
    line-height: .96; letter-spacing: -.01em; color: #FFFFFF;
    font-variant-numeric: tabular-nums;
}
.card-sub { font-family: var(--sans); font-size: 11.5px; font-weight: 600; color: var(--muted); }

/* ── Panels, cards, KPIs ──────────────────────────────────────
   A red rule down the left edge marks a panel as a titled region,
   which the old flat box never did. */
.panel {
    background: var(--bg2); border: 1px solid var(--border);
    border-left: 4px solid var(--red); border-radius: var(--radius);
}
.panel h4 {
    font-family: var(--display); font-size: 16px; font-weight: 800;
    color: #FFFFFF; letter-spacing: 0; text-transform: none; text-align: left;
}
.card { background: var(--bg2); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: none; }
.kpi { background: var(--bg3); border: 1px solid var(--border); border-radius: var(--radius); }
.kpi .k-l { font-family: var(--sans); font-size: 11px; font-weight: 700; letter-spacing: .07em; color: var(--muted2); }
.kpi .k-v { font-family: var(--display); font-size: 22px; font-weight: 800; color: #FFFFFF; font-variant-numeric: tabular-nums; }
.tile { background: var(--bg2); border: 1px solid var(--border); border-bottom: 4px solid var(--green); border-radius: var(--radius); box-shadow: none; }
.tile:hover { border-color: var(--border2); border-bottom-color: var(--red); box-shadow: none; }
.tile h5 { font-family: var(--display); font-weight: 800; color: var(--text); font-size: 15px; }

/* ── Page headings ────────────────────────────────────────────*/
.page-title { font-family: var(--display); font-weight: 800; color: #FFFFFF; letter-spacing: -.005em; }
.page-subtitle { font-family: var(--sans); color: var(--muted); font-weight: 600; }
.sec, .sechdr { font-family: var(--display); font-weight: 800; color: var(--text); }

/* ── Tables ───────────────────────────────────────────────────
   Header underline in party red so a table reads as a titled
   object; digits get tabular figures so columns line up. */
.table-wrap { background: var(--bg2); border: 1px solid var(--border); border-radius: var(--radius); }
.data-table th, .table-wrap th, table th {
    font-family: var(--sans); font-size: 11px; font-weight: 800;
    letter-spacing: .09em; text-transform: uppercase; color: var(--muted2);
    border-bottom: 2px solid var(--red);
}
.data-table td, .table-wrap td, table td {
    font-family: var(--sans); font-size: 13.5px; font-weight: 600; color: var(--text);
    border-bottom: 1px solid var(--bg3);
    font-variant-numeric: tabular-nums;
}
.data-table tr:hover td, .table-wrap tr:hover td { background: var(--bg3); }

/* ── Buttons and focus ────────────────────────────────────────*/
.btn {
    font-family: var(--sans); font-size: 12.5px; font-weight: 700;
    background: var(--bg3); border: 1px solid var(--border2); border-radius: var(--radius);
}
.btn:hover, .btn:active { background: var(--bg4); }
/* Dark ink on green, not white: white on #00A651 measures 3.19:1 and
   fails AA for button text. #0A0F0A on the same green is 5.96:1, and it
   keeps the brand green at full saturation instead of darkening it.
   This is also how the amber button it replaces already worked. */
.btn-primary, .btn-save { background-color: var(--green) !important; border-color: var(--green) !important; color: #0A0F0A !important; font-weight: 800; }
.btn-primary:hover, .btn-save:hover { background-color: #008C45 !important; opacity: 1; }
.btn-cancel { background: var(--bg3) !important; color: var(--muted2) !important; border-color: var(--border2) !important; }

/* Focus ring picks up the party red rather than the old green
   glow, and stays visible on every surface in this palette. */
.btn:focus, .btn:active:focus, .form-control:focus, .form-check-input:focus,
input:focus, textarea:focus, select:focus {
    outline: none;
    border-color: var(--red) !important;
    box-shadow: 0 0 0 3px rgba(228,0,43,.30) !important;
}

/* ── Bars, pills, badges ──────────────────────────────────────*/
.bar-track, .prog-track { background: var(--bg3); }
.bar-fill { background: var(--green); }
.pill, .chip, .badge { font-family: var(--sans); font-weight: 700; border-radius: var(--radius); }
.live-dot { background: var(--green); }

/* ── Motion ───────────────────────────────────────────────────*/
@media (prefers-reduced-motion: reduce) {
    * { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}

/* ── Sign-in ──────────────────────────────────────────────────
   The login page shipped its own complete amber identity
   (--login-accent #f59e0b, gradient headings, 16px radii) that
   predates this theme, so without these rules the first screen
   every one of the 212,934 accounts sees would still be gold
   while the app behind it is red. Re-pointed at the party
   palette; the layout is left exactly as it was.

   Selectors mirror app.css's own specificity (.login-body .card,
   .login-body .btn) because a bare .card would lose to them. */
.login-body, .login-wrap {
    background: linear-gradient(135deg, #1A0C10 0%, #2E141A 52%, #120A0C 100%) fixed;
    color: var(--text);
}
.login-body .card, .login-card {
    background: rgba(30,16,19,.90);
    border: 1px solid var(--border2);
    border-top: 4px solid var(--red);
    border-radius: var(--radius);
    box-shadow: 0 18px 44px rgba(0,0,0,.55);
}
.login-card { --login-accent: #E4002B; --login-ink: #FFFFFF; }

/* The heading was gradient-clipped text, which needs the fill to
   be transparent to show. Restored to a solid colour, so the
   -webkit-text-fill-color has to be unset or the text stays invisible. */
.login-body .card h2, .login-body.layer-booth .card h2, .login-title {
    background: none;
    -webkit-text-fill-color: #FFFFFF;
    color: #FFFFFF;
    font-family: var(--display);
    font-weight: 800;
    letter-spacing: 0;
    text-transform: none;
}
.login-body .card .subtitle, .login-subtitle {
    color: var(--muted2); font-family: var(--sans); font-weight: 600; letter-spacing: .1em;
}
.login-body .form-row label { color: var(--muted2); font-family: var(--sans); font-weight: 700; }
.login-body .form-row input[type="text"], .login-body .form-row input[type="password"] {
    background: rgba(18,10,12,.72); border: 1px solid var(--border2);
    border-radius: var(--radius); color: var(--text); font-family: var(--sans);
}
.login-body .form-row input[type="text"]:focus,
.login-body .form-row input[type="password"]:focus,
.login-body.layer-booth .form-row input[type="text"]:focus,
.login-body.layer-booth .form-row input[type="password"]:focus {
    border-color: var(--red);
    box-shadow: 0 0 0 3px rgba(228,0,43,.28);
    background: rgba(18,10,12,.92);
}

/* Green for the primary action, not red: the masthead already
   carries the party red, and a red submit button on a red-accented
   card reads as a destructive action rather than "sign in". */
.login-body .btn, .login-body.layer-booth .btn, .login-btn {
    background: var(--green); background-image: none;
    color: #0A0F0A; border: none; border-radius: var(--radius);
    font-family: var(--sans); font-weight: 800; letter-spacing: .08em;
    box-shadow: 0 4px 14px rgba(0,166,81,.28);
}
.login-body .btn:hover, .login-body.layer-booth .btn:hover, .login-btn:hover {
    background: #00BE5D; box-shadow: 0 7px 20px rgba(0,166,81,.40); transform: none;
}
.login-body .err { background: var(--red-dim); border: 1px solid rgba(228,0,43,.42); color: #FFC9D2; border-radius: var(--radius); }

/* ── Masthead brand, and the tier signal ──────────────────────
   app.css gives .brand a different colour per tier -- booth
   #f59e0b, state #fde047, district #a855f7, parliamentary
   #3b82f6, sector #10b981, assembly #ef4444, community #22e3c3.
   That colour is not decoration: it is how someone working
   across several tiers knows at a glance which site they are on.

   A solid red masthead would have destroyed that signal and put
   every one of those hues on red at roughly 2:1 -- amber on red
   was the first thing that looked wrong on screen.

   So the wordmark goes white (4.9:1 on party red) and the tier
   moves to a dot before it, carrying the original hue with a
   white ring so it stays visible whatever the hue does against
   red. The signal survives at full contrast, and it costs no
   markup change -- the dot is a pseudo-element.

   Specificity note: .topbar.layer-x .brand is (0,3,0), so these
   rules have to match it, not merely .topbar .brand. */
.topbar .brand,
.topbar[class*="layer-"] .brand {
    color: #FFFFFF;
    text-shadow: none;
    font-family: var(--display);
    font-size: 18px;
    font-weight: 800;
    letter-spacing: .02em;
    text-transform: none;
    display: inline-flex;
    align-items: center;
}
.topbar .brand .brand-sep { color: rgba(255,255,255,.55); opacity: 1; }

/* The product mark, on every masthead. It doubles as the tier
   signal: the chip's colour is the hue app.css used to give the
   wordmark, so "which product" and "which tier" are answered by
   one element. Dark ink on the light tier hues, which is why the
   tier colours below are the lightened variants. */
.topbar .brand::before {
    content: "PDA";
    flex: 0 0 auto;
    margin-right: 11px;
    padding: 3px 7px 2px;
    border-radius: 3px;
    background: #FFFFFF;
    color: #120A0C;
    font-family: var(--sans);
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .12em;
    line-height: 1.25;
}
.topbar.layer-booth         .brand::before { background: #F59E0B; }
.topbar.layer-state         .brand::before { background: #FDE047; }
.topbar.layer-district      .brand::before { background: #C77DFF; }
.topbar.layer-parliamentary .brand::before { background: #7FB2FF; }
.topbar.layer-sector        .brand::before { background: #34D399; }
.topbar.layer-assembly      .brand::before { background: #FF8A8A; }
.topbar.layer-community     .brand::before { background: #5EEAD4; }

/* ── Dividers on big cards ────────────────────────────────────
   app.css already has a divider language: .split / hr draw a
   line that fades at both ends with a small rotated square at
   the centre. This reuses it INSIDE the large cards, under the
   heading, so a panel reads as a titled region rather than text
   floating above content.

   Two constraints shaped the implementation:

   1. .section-hdr::before and .page-header::before are already
      used by app.css, so only ::after is free. The line is
      therefore painted as a background-image on the heading
      itself (a gradient border is not expressible as border-color),
      leaving the one free pseudo-element for the diamond.
   2. Headings that already carry a flat border-bottom have it
      removed, or the card gets two rules stacked a pixel apart.

   Only the big containers -- panel, card, section card, chart
   card. Stat cards and KPIs are deliberately excluded: they are
   small, there are up to forty on a page, and a divider in each
   would be the texture problem this theme set out to remove. */
.panel > h4,
.card > h3,
.card > h4,
.section-hdr,
.sechdr,
.gcard .gcard-head {
    position: relative;
    padding-bottom: 12px;
    margin-bottom: 15px;
    border-bottom: none;
    background-image: linear-gradient(90deg,
        transparent,
        rgba(242,230,220,.17) 16%,
        rgba(242,230,220,.17) 84%,
        transparent);
    background-repeat: no-repeat;
    background-size: 100% 1px;
    background-position: 0 100%;
}

/* The centre mark, in party red, ringed in the card's own
   background so the line appears to pass behind it. */
.panel > h4::after,
.card > h3::after,
.card > h4::after,
.section-hdr::after,
.sechdr::after,
.gcard .gcard-head::after {
    content: "";
    position: absolute;
    left: 50%;
    bottom: 0;
    width: 6px;
    height: 6px;
    transform: translate(-50%, 50%) rotate(45deg);
    background: var(--red);
    box-shadow: 0 0 0 4px var(--bg2);
    pointer-events: none;
}

/* .sechdr is a flex row with a right-aligned note, and .gcard-head
   is a baseline row -- neither should have its layout changed by
   the divider, only its bottom edge. */
.sechdr { align-items: baseline; }
.gcard .gcard-head { display: flex; align-items: baseline; }

/* A heading immediately followed by nothing (an empty panel) would
   leave a rule with no content under it. */
.panel > h4:only-child,
.card > h3:only-child,
.card > h4:only-child {
    background-image: none;
    padding-bottom: 0;
    margin-bottom: 0;
}
.panel > h4:only-child::after,
.card > h3:only-child::after,
.card > h4:only-child::after { display: none; }

/* ════════════════════════════════════════════════════════════════
   SECOND PASS — the families app.css styles with hard-coded
   literals, which no token override can reach.

   About 1500 hex literals sit across the 13 forked app.css files
   (24-72 unique each). The first pass moved the tokens; these rules
   kept their literals, which is why the deep pages stayed on the old
   cool palette beside the new warm shell. Offenders by volume:
   #f59e0b x116 (old amber accent), #121a12 x109 / #0d1117 x45 /
   #1a1f2e x43 (blue and green-black surfaces), #94a3b8 x52 (cool
   slate text), #22e3c3 x49 (caste-flow teal).

   Every rule below overrides a literal. Colours that carry meaning
   are re-hued for the warm ground, never merged.
   ════════════════════════════════════════════════════════════════ */

/* ── Voter cards ──────────────────────────────────────────────
   Sex is encoded on the left rail -- vc-m male, vc-f female -- so
   both keep a distinct hue. The card body was a green-black
   gradient (#0e180e to #152215) that read as a different product
   sitting next to the red shell. */
.voter-card {
    background: linear-gradient(135deg, #1E1013, #2A1519);
    border: 1px solid var(--border);
    border-left: 3px solid var(--green);
}
.voter-card.vc-m { border-left-color: var(--blue); }
.voter-card.vc-f { border-left-color: #FF7AB8; }
.voter-card a { color: var(--blue); }
.vc-name, .vc-hname { color: #FFFFFF; font-family: var(--sans); font-weight: 700; }
.vc-head, .vc-sur, .vc-en, .vc-srno { color: var(--muted2); font-family: var(--sans); }
.vc-vid { font-variant-numeric: tabular-nums; color: var(--text); }
.vc-tag { background: var(--bg3); color: var(--muted2); border-radius: var(--radius); }

/* ── PDA-G tiles ──────────────────────────────────────────────
   The classification carried TWO different colour mappings in the
   same product: the letters (.pdag-p/d/a/g) read amber/blue/green/
   purple from tokens, while the tiles (.pt-*) hard-coded green/red/
   teal/purple. The same group was one colour as a letter and a
   different colour as a tile. Tiles are aligned to the letters,
   which is the mapping the tokens and the rest of the theme use.
   Darkened from the letter hues because these are solid fills
   carrying white text: each pair below clears 4.5:1. */
.pt-p { background: #8A6508; }   /* Pichhda      - amber family */
.pt-d { background: #24558F; }   /* Dalit        - blue family   */
.pt-a { background: #006633; }   /* Alpasankhyak - green family  */
.pt-g { background: #5E3480; }   /* General      - purple family */
.pt-total { background: #8A2233; }
.pt-c { background: #8F4C18; }
.pda-tile { border-radius: var(--radius); box-shadow: none; color: #FFFFFF; }
.pda-tile .t-label { font-family: var(--sans); font-weight: 700; }
.pda-tile .t-val { font-family: var(--display); font-weight: 800; font-variant-numeric: tabular-nums; }
.pdag-letter { font-family: var(--display); }

/* ── Caste flow ───────────────────────────────────────────────
   Built entirely around #22e3c3, a teal from the previous palette
   and the single most out-of-place colour on the warm ground. */
.cf-hero {
    background: linear-gradient(135deg, rgba(228,0,43,.12), rgba(0,166,81,.06));
    border: 1px solid var(--border);
    border-left: 4px solid var(--red);
    border-radius: var(--radius);
}
.cf-hero h1 { font-family: var(--display); color: #FFFFFF; font-weight: 800; }
.cf-hero .sub { font-family: var(--sans); color: var(--muted2); }
.cf-hero .pill, .cf-pill {
    background: var(--red-dim); border: 1px solid rgba(228,0,43,.42);
    color: #FF9FB0; font-family: var(--sans); border-radius: var(--radius);
}
.cf-pill.amber { background: var(--amber-dim); border-color: rgba(255,199,44,.42); color: var(--amber); }
.cf-pill.purple { background: var(--purple-dim); border-color: rgba(199,125,255,.42); color: var(--purple); }
.cf-kpi .k { background: var(--bg2); border: 1px solid var(--border); border-left: 3px solid var(--ac, var(--green)); border-radius: var(--radius); }
.cf-kpi .k:hover { background: var(--bg3); }
.cf-gauge.green { --ac: var(--green); }
.cf-gauge.red   { --ac: var(--red); }
.cf-gauge.amber { --ac: var(--amber); }
.cf-gauge.cyan  { --ac: var(--cyan); }

/* ── Geo bar, tabs and KPIs ───────────────────────────────────
   k-male / k-female / k-hindu / k-muslim encode demographics, so
   each keeps its own hue rather than collapsing into the accent. */
.geo-pick { background: var(--bg2); border: 1px solid var(--border); border-radius: var(--radius); }
.geo-pick-lbl { font-family: var(--sans); font-weight: 800; color: var(--muted2); font-size: 11px; letter-spacing: .1em; }
.geo-bar select, .geo-pick-sel { background: var(--bg3); border: 1px solid var(--border2); color: var(--text); font-family: var(--sans); border-radius: var(--radius); }
.geo-pick-sel option { background: var(--bg2); color: var(--text); }
.geo-pick-sel:focus-visible { border-color: var(--red); box-shadow: 0 0 0 2px rgba(228,0,43,.30); }
.geo-tab { font-family: var(--sans); font-size: 12px; font-weight: 700; color: var(--muted2); border: 1px solid var(--border2); border-radius: var(--radius); }
.geo-tab:hover { background: var(--bg3); color: var(--text); border-color: var(--muted); }
.geo-tab.on { background: var(--red); border-color: var(--red); color: #FFFFFF; }
.geo-chip { background: var(--bg3); border: 1px solid var(--border); color: var(--muted2); border-radius: var(--radius); font-family: var(--sans); }
.geo-hero { background: var(--bg2); border: 1px solid var(--border); border-left: 4px solid var(--red); border-radius: var(--radius); }
.geo-hero-name { font-family: var(--display); color: #FFFFFF; font-weight: 800; }
.geo-hero-level, .geo-hero-total { font-family: var(--sans); color: var(--muted2); }
.geo-kpi { background: var(--bg3); border: 1px solid var(--border); border-radius: var(--radius); }
.geo-kpi.k-total  { border-left: 3px solid var(--text); }
.geo-kpi.k-male   { border-left: 3px solid var(--blue); }
.geo-kpi.k-female { border-left: 3px solid #FF7AB8; }
.geo-kpi.k-hindu  { border-left: 3px solid var(--amber); }
.geo-kpi.k-muslim { border-left: 3px solid var(--green); }
.geo-kpi.k-age    { border-left: 3px solid var(--purple); }

/* ── Gauges, meters, progress ─────────────────────────────────*/
.ov-kpi { background: var(--bg2); border: 1px solid var(--border); border-radius: var(--radius); }
.ov-kpi.k-green .v  { color: var(--green); }
.ov-kpi.k-red .v    { color: #FF5C77; }
.ov-kpi.k-amber .v  { color: var(--amber); }
.ov-kpi.k-blue .v   { color: var(--blue); }
.ov-kpi.k-cyan .v   { color: var(--cyan); }
.ov-kpi.k-purple .v { color: var(--purple); }
.ov-kpi.k-orange .v { color: #FF9A4D; }
.prog-track, .bar-track, .progress-box { background: var(--bg3); }
.prog-seg, .bar-fill, .seg-done { background: var(--green); }
.progress-pct, .bar-value { font-variant-numeric: tabular-nums; color: var(--text); }
.bar-label { font-family: var(--sans); color: var(--muted2); }
.leg-dot { border-radius: 2px; }

/* ── Pickers, filters, paging ─────────────────────────────────*/
.bc-host, .bc-list, .booth-picker select, .bp-sel, .pdc-picker-sel, .search-box, .filter-bar {
    background: var(--bg2); border: 1px solid var(--border2); color: var(--text);
    font-family: var(--sans); border-radius: var(--radius);
}
.bc-item:hover, .bc-item.on { background: var(--red-dim); color: #FFFFFF; }
.bc-t { color: var(--text); }
.bc-n, .bc-none { color: var(--muted2); }
.bc-input.bc-bad { border-color: var(--red); }
.letter-picker a, .pager-btn {
    background: var(--bg2); border: 1px solid var(--border); color: var(--text);
    font-family: var(--sans); border-radius: var(--radius);
}
.pager-btn:hover { background: var(--bg3); border-color: var(--border2); }
.pager-btn.active { background: var(--red); border-color: var(--red); color: #FFFFFF; font-weight: 800; }
.pager-btn.disabled { color: var(--muted); opacity: .55; }
.filter-results-count { font-family: var(--sans); color: var(--muted2); }

/* ── Chips, badges, tags ──────────────────────────────────────
   .badge was 8px, below the readable floor on a phone. */
.badge { font-family: var(--sans); font-size: 11px; font-weight: 700; letter-spacing: .04em; border-radius: var(--radius); padding: 2px 6px; }
.badge-done    { background: var(--green-dim); color: #4FE08C; }
.badge-failed  { background: var(--red-dim); color: #FF9FB0; }
.badge-ip      { background: var(--amber-dim); color: var(--amber); }
.badge-pending { background: var(--bg4); color: var(--muted2); }
.pill { background: var(--green-dim); color: #4FE08C; border-radius: var(--radius); font-family: var(--sans); }
.chip, .sn-chip, .tlh-chip { background: var(--bg3); border: 1px solid var(--border); color: var(--muted2); font-family: var(--sans); border-radius: var(--radius); }
.sc-tag { color: var(--muted2); font-family: var(--sans); }
.sc-tag:hover, .sc-tag.sc-active { color: #FF6B85; }
.sc-tag .sc-cnt { color: var(--muted); font-variant-numeric: tabular-nums; }
.text-green { color: var(--green); } .text-red { color: #FF5C77; }
.text-amber { color: var(--amber); } .text-blue { color: var(--blue); }
.text-cyan  { color: var(--cyan); }  .text-purple { color: var(--purple); }

/* ── Heroes, tiles, chart cards ───────────────────────────────*/
.svc-hero, .dash-hero, .bv-hero, .tlh {
    background: var(--bg2); border: 1px solid var(--border);
    border-left: 4px solid var(--hero, var(--red)); border-radius: var(--radius);
}
.svc-hero--sir { --hero: var(--blue); } .svc-hero--demo { --hero: var(--green); }
.svc-hero--caste { --hero: var(--amber); } .svc-hero--em { --hero: var(--purple); }
.tlh-title { font-family: var(--display); color: #FFFFFF; }
.tlh-sub, .bv-hero-sub, .gcard-sub { font-family: var(--sans); color: var(--muted2); }
.gcard { background: var(--bg2); border: 1px solid var(--border); border-radius: var(--radius); }
.gcard--failed { border-color: rgba(228,0,43,.45); }

/* The native select popup inherits the page, not the control, so
   option colours are set explicitly or they come out unreadable.
   app.css hard-codes a green-black here in every one of the files. */
select option { background: var(--bg2); color: var(--text); }

/* ── Micro-type floor ─────────────────────────────────────────
   318 font-size declarations across the 13 files sit below 11px,
   13 of them at 8px. Below roughly 11px an uppercase label stops
   being read and becomes texture, which was one of the six reasons
   the UI read dull. Raised where the text is a label, not data. */
.card-label, .nav-label, .section-hdr, .bar-label,
.geo-pick-lbl, .cf-hero .sub, .badge, .pill, .chip { font-size: 11px; }

/* ── Cards per row ────────────────────────────────────────────
   The stat values were clipping: "13,42,31,25…" and "2,93,02,938"
   cut off mid-digit on the analysis dashboard.

   Three causes, all here. app.css sizes .cards-grid at
   minmax(165px,1fr), which is narrower than a nine-digit Indian-
   grouped number needs; .cards-grid-7 and -8 pin a literal seven
   or eight columns with repeat(7|8, minmax(0,1fr)), so they never
   wrap however narrow the window gets; and this theme raised
   .card-value from 24px mono to 30px Anek, which needs more room
   than the old size did.

   Every fixed-count grid becomes auto-fit with a real minimum, so
   the column count falls out of the available width instead of
   being asserted. Fewer, wider cards per row, and they reflow
   down to 360px instead of overflowing. minmax(0,1fr) is kept as
   the upper bound reasoning -- a grid item's default min-width is
   auto, which is what lets content push a track wider than its
   share and cause the overflow in the first place. */
.cards-grid,
.cards-grid-4,
.cards-grid-5,
.cards-grid-6,
.cards-grid-7,
.cards-grid-8 {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 10px;
}
.cards-grid-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.cards-grid-3 { grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }

/*  The same fixed-count problem in the other tile families. */
.kpi-row   { grid-template-columns: repeat(auto-fit, minmax(175px, 1fr)); }
.geo-kpis  { grid-template-columns: repeat(auto-fit, minmax(185px, 1fr)); }
.pda-tiles { grid-template-columns: repeat(auto-fit, minmax(205px, 1fr)); }
.cf-kpi    { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.tile-grid { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.ov-kpi-grid { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.gcharts   { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }

/*  A grid item will not shrink below its content unless told to.
    Without this a long value widens its own track and overflows
    the card rather than wrapping, which is what clipped the digits. */
.cards-grid > *, .cards-grid-2 > *, .cards-grid-3 > *, .cards-grid-4 > *,
.cards-grid-5 > *, .cards-grid-6 > *, .cards-grid-7 > *, .cards-grid-8 > *,
.kpi-row > *, .geo-kpis > *, .pda-tiles > *, .cf-kpi > *, .ov-kpi-grid > * {
    min-width: 0;
}

/*  Belt and braces: a value longer than any sensible column still
    steps down rather than spilling. Anek keeps its weight at the
    smaller end, so this reads as the same type, just tighter. */
.card-value {
    font-size: clamp(21px, 2.1vw, 30px);
    overflow-wrap: anywhere;
}
.kpi .k-v, .pda-tile .t-val { overflow-wrap: anywhere; }

/* ── Text that failed contrast outright ───────────────────────
   Found by computing every `color:` literal in the thirteen
   stylesheets against the three warm grounds. These sat below
   4.5:1 and are old-palette leftovers no token could reach. */
.vc-detail { color: var(--muted2); }              /* was #64748b, 3.46:1 */
.validation-message { color: #FF8FA3; }           /* was #e50000, 3.40:1 -> 7.1:1 */
.m-dup .v, .ov-kpi.k-purple .v { color: var(--purple); }   /* was #a855f7, 4.17:1 */
.cf-gauge.red .num, .neg { color: #FF5C77; }      /* was #ef4444, 4.38:1 -> 6.19:1 */
.finding-card.fc-red .fc-num,
.m-dead .v, .ov-kpi.k-red .v { color: #FF5C77; }  /* was #f43f5e, 4.49:1 */

/*  Dividers and disabled states were dimmed by opacity on top of an
    already-muted colour, which compounds: .35 of a 5:1 colour is not
    readable by any measure. Raised to the point where "disabled"
    still reads as disabled but the text can be read. */
.pager-btn.disabled, .pager button:disabled { opacity: .6; }
.geo-kpi.is-na .k-value { opacity: .75; }
.vc-row3 span::after { opacity: .6; }

/* ── Bootstrap's text utilities ───────────────────────────────
   .text-muted is used 171 times on the analysis page alone, and it
   was rendering at rgba(33,37,41,.75) -- Bootstrap 5.3's
   $gray-900 -- which is 1.2:1 on a dark card. Effectively invisible,
   and the actual cause of "grey text goes hidden".

   app.css already says .text-muted { color: var(--muted) } and
   loads after bootstrap, but Bootstrap declares its colour
   utilities with !important, so it wins regardless of order. The
   only way to take it back is to match that, which is why these
   carry !important where nothing else in this file does.

   .text-secondary / .text-body-secondary are the 5.3 successors
   and are covered pre-emptively: they are not in the markup today,
   but they are what a future Bootstrap upgrade renames these to. */
.text-muted,
.text-secondary,
.text-body-secondary { color: var(--muted) !important; }

/* ── Phones: two up, not one ──────────────────────────────────
   The desktop fix above raised the card minimum to 240px so a
   nine-digit number stops clipping. auto-fit then resolves to a
   SINGLE column below about 500px, which turned the Voters and
   Booth tabs into one tall tile per screen — worse than before
   the fix, on the surface that matters most.

   auto-fit cannot express "at least two" — the minimum is an
   absolute length and a phone is narrower than two of them. So
   phones get an explicit two-column track instead, and the tile
   art comes down with it: an 80px icon inside a half-width card
   leaves no room for the label it belongs to.

   Scoped to the phone surface. The console sites are desktop-only
   by design and never reflow; this only reaches them if someone
   opens one on a handset, where two columns is still the better
   of the two wrong answers. */
@media (max-width: 560px) {
    .cards-grid, .cards-grid-2, .cards-grid-3, .cards-grid-4,
    .cards-grid-5, .cards-grid-6, .cards-grid-7, .cards-grid-8,
    .tile-grid, .kpi-row, .geo-kpis, .pda-tiles, .cf-kpi, .ov-kpi-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 9px;
    }
    .tile-grid { padding: 12px; }
    .tile { padding: 13px 10px; }
    .tile img { width: 54px; height: 54px; }
    .tile h5 { font-size: 13.5px; }
    .stat-card { padding: 12px 13px; }
    .card-value { font-size: clamp(19px, 6vw, 25px); }
    .card-label { font-size: 11px; letter-spacing: .06em; }
}

/*  Below ~340px two columns stops being readable — a 150px track
    cannot hold "Alpasankhyak" plus a figure. Single column there. */
@media (max-width: 340px) {
    .cards-grid, .tile-grid, .kpi-row, .geo-kpis, .pda-tiles, .cf-kpi, .ov-kpi-grid {
        grid-template-columns: 1fr;
    }
}
