/* =============================================================================
   TG LokOS Dashboard — V3 stylesheet

   Every token below is a verbatim value from the V3 Figma library ("TG LokOS
   Dashboard / Tokens"). Two things in here are accessibility-critical and were
   audited against WCAG — they must NOT be "tidied", re-hued or merged:

     1. The completion ramp (--tg-band-1..5) runs red (worst) to green (best).
        It is the ONLY channel that encodes completion. Do not swap in a
        categorical/rainbow ramp, do not reorder it, and do not reuse a band
        colour to mean anything other than "this much complete".
        Two hues only, red to green, with no amber step: red, soft red, pale
        red, green, deep green. The turn happens between bands 3 and 4, which is
        where the ramp changes hue rather than passing through a third colour.
        Band 3 stays clearly PINK (chroma 45) and must never drift to a neutral
        tint - that is the fill --tg-muted-bg uses for "no data", and the two
        would be indistinguishable on the map. Hue carries the order, so a
        colour-blind reader cannot rank it by colour alone; every band, card and
        legend also prints its percentage, and the number is the value. Text
        contrast must never slip: all five bands sit at >= 5.2 against their
        --tg-band-N-ink in both themes. Re-hue a step and recompute it.
     2. Bands 4 and 5 are dark enough that near-black text fails contrast on
        them, so every text node sitting on a band-4/5 fill is #ffffff. That is
        carried by --tg-band-ink and applied wherever a band is a fill: map
        paths, heatmap cells and dots, drill cards, legend swatches.

   Dark theme follows the same mechanism public/styles.css uses, so an explicit
   [data-theme="light"] still beats the OS preference.
   ========================================================================== */

/* ---------------------------------------------------------------- tokens */
.tg {
  /* surfaces & ink */
  --tg-canvas: #f5f5f4;
  --tg-surface: #ffffff;
  --tg-subtle: #fafaf9;
  --tg-muted-bg: #efeeec;
  --tg-text-primary: #1c1917;
  --tg-text-secondary: #57534e;
  /* darkened from the V3 #78716c: that value is 4.40:1 on the canvas and fails outright on
     the pastel KPI surfaces, and this token carries every caption and chip label. */
  --tg-text-tertiary: #66605c;
  --tg-border: #e7e5e4;
  --tg-border-strong: #d6d3d1;
  --tg-action: #2563eb;
  --tg-on-primary: #ffffff;
  --tg-focus: #2563eb;

  /* Completion ramp — five steps, cream -> terracotta -> slate -> navy, taken verbatim from the
     V3 library (Color/completion/1..5). It is the ONLY channel that encodes completion.

     Each step carries its own ink and its own bar-track wash, because which one is readable
     flips partway along the ramp AND flips again in dark mode: in light, steps 1-3 are pale and
     take near-black while 4-5 are dark and take white; in dark the ramp inverts, so 1-3 are
     near-black grounds taking light ink and 4-5 are pale blues taking dark ink. Measured, not
     guessed - the worst pairing on this list is 4.77:1. */
  --tg-band-1: #d4706d;
  --tg-band-2: #e79c94;
  --tg-band-3: #f5cdc8;
  --tg-band-4: #5cb582;
  --tg-band-5: #1c7042;
  --tg-band-1-ink: #1c1917;  --tg-band-1-track: rgba(0, 0, 0, 0.16);
  --tg-band-2-ink: #1c1917;  --tg-band-2-track: rgba(0, 0, 0, 0.16);
  --tg-band-3-ink: #1c1917;  --tg-band-3-track: rgba(0, 0, 0, 0.16);
  --tg-band-4-ink: #1c1917;  --tg-band-4-track: rgba(0, 0, 0, 0.16);
  --tg-band-5-ink: #ffffff;  --tg-band-5-track: rgba(255, 255, 255, 0.30);
  --tg-band-lo-track: rgba(0, 0, 0, 0.14);
  --tg-band-hi-track: rgba(255, 255, 255, 0.30);

  /* category tiles — surface / ink pairs, fixed order */
  --tg-violet-s: #e4d7f5;   --tg-violet-i: #6b3fa8;
  --tg-teal-s: #cdeded;     --tg-teal-i: #0c6767;
  --tg-blue-s: #cfe4f3;     --tg-blue-i: #195c8c;
  --tg-amber-s: #fbe8b0;    --tg-amber-i: #7d570a;
  --tg-magenta-s: #f5d9e8;  --tg-magenta-i: #9c1f68;
  --tg-orange-s: #fbddbf;   --tg-orange-i: #8f4516;
  --tg-green-s: #dcedc8;    --tg-green-i: #3e6324;

  /* status — never a series colour */
  --tg-success: #15803d;
  --tg-warning: #b45309;
  --tg-danger: #b91c1c;
  --tg-info: #2563eb;
  --tg-neutral: #78716c;

  /* space */
  --tg-s1: 4px;  --tg-s2: 8px;  --tg-s3: 12px; --tg-s4: 16px;
  --tg-s5: 24px; --tg-s6: 32px; --tg-s7: 40px; --tg-s8: 48px;

  /* radius & lines */
  --tg-r-sm: 4px; --tg-r-md: 6px; --tg-r-lg: 8px; --tg-r-xl: 12px; --tg-r-full: 999px;
  --tg-hair: 1px;
  --tg-strong: 2px;

  /* type */
  --tg-sans: "Inter", system-ui, -apple-system, "Segoe UI", "Noto Sans Telugu", sans-serif;
  --tg-mono: "JetBrains Mono", ui-monospace, "Cascadia Code", "Segoe UI Mono", Consolas, monospace;
  --tg-t-display: 30px;
  --tg-t-page: 22px;
  --tg-t-section: 16px;
  --tg-t-card: 14px;
  --tg-t-body: 14px;
  --tg-t-small: 13px;
  --tg-t-label: 12px;
  --tg-t-th: 11px;
  --tg-t-metric: 26px;
  --tg-t-metric-sm: 20px;
  --tg-t-caption: 11px;

  /* controls */
  --tg-control: 36px;
  --tg-touch: 44px;
  --tg-detail-w: 520px;
  --tg-shell: 1440px;

  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .tg {
    color-scheme: dark;
    --tg-canvas: #141312;
    --tg-surface: #221f1d;
    --tg-subtle: #1a1917;
    --tg-muted-bg: #2a2724;
    --tg-text-primary: #edeae6;
    --tg-text-secondary: #b8b1a9;
    /* lightened from #8a837c: clears 4.5:1 on every dark ground, incl. tinted row highlights */
    --tg-text-tertiary: #989088;
    --tg-border: #3a3633;
    --tg-border-strong: #8a837c;
    /* #408cff, a step up from the V3 blue/500 #3b82f6. As a FILL that value is fine, but it also
       carries text links, where it is 4.04-4.45:1 on the dark surfaces - just under. #408cff
       clears 4.5:1 as text and improves the dark ink on the button fill to 5.67:1. */
    --tg-action: #408cff;
    /* Near-black on the accent in dark mode, which is what the V3 token says:
       action/on-primary maps to stone/00 in Light and night/950 in Dark. White on the dark
       accent #3b82f6 is only 3.68:1; #141312 gives 5.05:1. */
    --tg-on-primary: #141312;
    --tg-focus: #408cff;
    --tg-band-1: #8f3a36;
    --tg-band-2: #c47268;
    --tg-band-3: #d99b93;
    --tg-band-4: #7fd3a0;
    --tg-band-5: #b9e8cd;
    /* the ramp inverts here: 1-3 are near-black grounds, 4-5 are pale blues */
    --tg-band-1-ink: #edeae6;  --tg-band-1-track: rgba(255, 255, 255, 0.18);
    --tg-band-2-ink: #141312;  --tg-band-2-track: rgba(0, 0, 0, 0.20);
    --tg-band-3-ink: #141312;  --tg-band-3-track: rgba(0, 0, 0, 0.20);
    --tg-band-4-ink: #141312;  --tg-band-4-track: rgba(0, 0, 0, 0.20);
    --tg-band-5-ink: #141312;  --tg-band-5-track: rgba(0, 0, 0, 0.20);
    --tg-band-lo-track: rgba(255, 255, 255, 0.16);
    --tg-band-hi-track: rgba(0, 0, 0, 0.20);
    /* Status hues for dark mode. Without these the light values are inherited and every one of
       them fails on a dark ground - #b91c1c danger scored 2.53:1 on the surface. Values are the
       V3 dark tokens, except danger: #ef4444 measures 3.95:1, so it is lightened one step to
       #ff4c4c (4.52:1) which is the smallest change that clears 4.5. */
    --tg-success: #22c55e;
    --tg-warning: #f59e0b;
    --tg-serious: #f97316;
    --tg-danger: #ff4c4c;
    --tg-info: #408cff;
    --tg-neutral: #989088;
    --tg-violet-s: #241539;   --tg-violet-i: #bfa3e8;
    --tg-teal-s: #062b2b;     --tg-teal-i: #84d2d2;
    --tg-blue-s: #0e2739;     --tg-blue-i: #93c4e4;
    --tg-amber-s: #332404;    --tg-amber-i: #e5c05c;
    --tg-magenta-s: #3a0f27;  --tg-magenta-i: #e8a8c8;
    --tg-orange-s: #3a1e0b;   --tg-orange-i: #f0b980;
    --tg-green-s: #1b2a10;    --tg-green-i: #a9d183;
  }
}

[data-theme="dark"] .tg {
  color-scheme: dark;
  --tg-canvas: #141312;
  --tg-surface: #221f1d;
  --tg-subtle: #1a1917;
  --tg-muted-bg: #2a2724;
  --tg-text-primary: #edeae6;
  --tg-text-secondary: #b8b1a9;
  /* lightened from #8a837c: clears 4.5:1 on every dark ground, incl. tinted row highlights */
  --tg-text-tertiary: #989088;
  --tg-border: #3a3633;
  --tg-border-strong: #8a837c;
  /* #408cff, a step up from the V3 blue/500 #3b82f6. As a FILL that value is fine, but it also
     carries text links, where it is 4.04-4.45:1 on the dark surfaces - just under. #408cff
     clears 4.5:1 as text and improves the dark ink on the button fill to 5.67:1. */
  --tg-action: #408cff;
  /* see the note above: white on the dark accent is 3.68:1 */
  --tg-on-primary: #141312;
  --tg-focus: #408cff;
  --tg-band-1: #8f3a36;
  --tg-band-2: #c47268;
  --tg-band-3: #d99b93;
  --tg-band-4: #7fd3a0;
  --tg-band-5: #b9e8cd;
  --tg-band-1-ink: #edeae6;  --tg-band-1-track: rgba(255, 255, 255, 0.18);
  --tg-band-2-ink: #141312;  --tg-band-2-track: rgba(0, 0, 0, 0.20);
  --tg-band-3-ink: #141312;  --tg-band-3-track: rgba(0, 0, 0, 0.20);
  --tg-band-4-ink: #141312;  --tg-band-4-track: rgba(0, 0, 0, 0.20);
  --tg-band-5-ink: #141312;  --tg-band-5-track: rgba(0, 0, 0, 0.20);
  --tg-band-lo-track: rgba(255, 255, 255, 0.16);
  --tg-band-hi-track: rgba(0, 0, 0, 0.20);
  /* Status hues for dark mode. Without these the light values are inherited and every one of
     them fails on a dark ground - #b91c1c danger scored 2.53:1 on the surface. Values are the
     V3 dark tokens, except danger: #ef4444 measures 3.95:1, so it is lightened one step to
     #ff4c4c (4.52:1) which is the smallest change that clears 4.5. */
  --tg-success: #22c55e;
  --tg-warning: #f59e0b;
  --tg-serious: #f97316;
  --tg-danger: #ff4c4c;
  --tg-info: #408cff;
  --tg-neutral: #989088;
  --tg-violet-s: #241539;   --tg-violet-i: #bfa3e8;
  --tg-teal-s: #062b2b;     --tg-teal-i: #84d2d2;
  --tg-blue-s: #0e2739;     --tg-blue-i: #93c4e4;
  --tg-amber-s: #332404;    --tg-amber-i: #e5c05c;
  --tg-magenta-s: #3a0f27;  --tg-magenta-i: #e8a8c8;
  --tg-orange-s: #3a1e0b;   --tg-orange-i: #f0b980;
  --tg-green-s: #1b2a10;    --tg-green-i: #a9d183;
}

/* ------------------------------------------------------- band assignment
   One place decides fill, ink and track for a band. Bands 4-5 take white ink:
   near-black text does not clear 4.5:1 on them. Do not change these pairings. */
.tg [data-band="1"] { --tg-band: var(--tg-band-1); --tg-band-ink: var(--tg-band-1-ink); --tg-band-track: var(--tg-band-1-track); }
.tg [data-band="2"] { --tg-band: var(--tg-band-2); --tg-band-ink: var(--tg-band-2-ink); --tg-band-track: var(--tg-band-2-track); }
.tg [data-band="3"] { --tg-band: var(--tg-band-3); --tg-band-ink: var(--tg-band-3-ink); --tg-band-track: var(--tg-band-3-track); }
.tg [data-band="4"] { --tg-band: var(--tg-band-4); --tg-band-ink: var(--tg-band-4-ink); --tg-band-track: var(--tg-band-4-track); }
.tg [data-band="5"] { --tg-band: var(--tg-band-5); --tg-band-ink: var(--tg-band-5-ink); --tg-band-track: var(--tg-band-5-track); }
.tg [data-band="0"],
.tg [data-band="na"],
.tg [data-band=""] { --tg-band: var(--tg-muted-bg); --tg-band-ink: var(--tg-text-tertiary); --tg-band-track: var(--tg-band-lo-track); }

/* ------------------------------------------------------ category assignment
   data-cat carries the Figma colour name. The nth-child rules underneath are a
   fallback so the seven tiles keep the library's fixed order even if a tile
   ships without the attribute — order is part of the design, not decoration. */
.tg [data-cat="violet"]  { --tg-cat-s: var(--tg-violet-s);  --tg-cat-i: var(--tg-violet-i); }
.tg [data-cat="teal"]    { --tg-cat-s: var(--tg-teal-s);    --tg-cat-i: var(--tg-teal-i); }
.tg [data-cat="blue"]    { --tg-cat-s: var(--tg-blue-s);    --tg-cat-i: var(--tg-blue-i); }
.tg [data-cat="amber"]   { --tg-cat-s: var(--tg-amber-s);   --tg-cat-i: var(--tg-amber-i); }
.tg [data-cat="magenta"] { --tg-cat-s: var(--tg-magenta-s); --tg-cat-i: var(--tg-magenta-i); }
.tg [data-cat="orange"]  { --tg-cat-s: var(--tg-orange-s);  --tg-cat-i: var(--tg-orange-i); }
.tg [data-cat="green"]   { --tg-cat-s: var(--tg-green-s);   --tg-cat-i: var(--tg-green-i); }

.tg-tiles > :nth-child(7n + 1), .tg-kpis > :nth-child(7n + 1) { --tg-cat-s: var(--tg-violet-s);  --tg-cat-i: var(--tg-violet-i); }
.tg-tiles > :nth-child(7n + 2), .tg-kpis > :nth-child(7n + 2) { --tg-cat-s: var(--tg-teal-s);    --tg-cat-i: var(--tg-teal-i); }
.tg-tiles > :nth-child(7n + 3), .tg-kpis > :nth-child(7n + 3) { --tg-cat-s: var(--tg-blue-s);    --tg-cat-i: var(--tg-blue-i); }
.tg-tiles > :nth-child(7n + 4), .tg-kpis > :nth-child(7n + 4) { --tg-cat-s: var(--tg-amber-s);   --tg-cat-i: var(--tg-amber-i); }
.tg-tiles > :nth-child(7n + 5), .tg-kpis > :nth-child(7n + 5) { --tg-cat-s: var(--tg-magenta-s); --tg-cat-i: var(--tg-magenta-i); }
.tg-tiles > :nth-child(7n + 6), .tg-kpis > :nth-child(7n + 6) { --tg-cat-s: var(--tg-orange-s);  --tg-cat-i: var(--tg-orange-i); }
.tg-tiles > :nth-child(7n + 7), .tg-kpis > :nth-child(7n + 7) { --tg-cat-s: var(--tg-green-s);   --tg-cat-i: var(--tg-green-i); }
/* an explicit attribute always wins over the positional fallback */
.tg-tiles > [data-cat="violet"],  .tg-kpis > [data-cat="violet"]  { --tg-cat-s: var(--tg-violet-s);  --tg-cat-i: var(--tg-violet-i); }
.tg-tiles > [data-cat="teal"],    .tg-kpis > [data-cat="teal"]    { --tg-cat-s: var(--tg-teal-s);    --tg-cat-i: var(--tg-teal-i); }
.tg-tiles > [data-cat="blue"],    .tg-kpis > [data-cat="blue"]    { --tg-cat-s: var(--tg-blue-s);    --tg-cat-i: var(--tg-blue-i); }
.tg-tiles > [data-cat="amber"],   .tg-kpis > [data-cat="amber"]   { --tg-cat-s: var(--tg-amber-s);   --tg-cat-i: var(--tg-amber-i); }
.tg-tiles > [data-cat="magenta"], .tg-kpis > [data-cat="magenta"] { --tg-cat-s: var(--tg-magenta-s); --tg-cat-i: var(--tg-magenta-i); }
.tg-tiles > [data-cat="orange"],  .tg-kpis > [data-cat="orange"]  { --tg-cat-s: var(--tg-orange-s);  --tg-cat-i: var(--tg-orange-i); }
.tg-tiles > [data-cat="green"],   .tg-kpis > [data-cat="green"]   { --tg-cat-s: var(--tg-green-s);   --tg-cat-i: var(--tg-green-i); }

/* ---------------------------------------------------------------- shell */
/* The app shell pads `main`, but the identity strip, masthead and footer are
   full-bleed bands. Pull back by exactly the shell padding at each breakpoint
   rather than using 100vw, which would run under the sidebar rail. */
#view-voa { padding: 0; }
.tg {
  margin: -24px -24px -32px;
  font: var(--tg-t-body) / 1.45 var(--tg-sans);
  color: var(--tg-text-primary);
  background: var(--tg-canvas);
  min-height: 100%;
  max-width: none;
  -webkit-text-size-adjust: 100%;
}
.tg *, .tg *::before, .tg *::after { box-sizing: border-box; }
.tg p, .tg h2, .tg h3, .tg ol, .tg ul { margin: 0; }
.tg ol, .tg ul { padding: 0; list-style: none; }
.tg i, .tg em { font-style: normal; }
/* Wrapped in :where() so the resets carry ZERO specificity. Written as `.tg button` they score
   (0,1,1) and silently beat every single-class component rule - `.tg-tile` at (0,1,0) lost its
   category fill to `background: none` here, which is not a cascade order problem and cannot be
   fixed by moving the block. Keep the :where(). */
:where(.tg button) { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
:where(.tg select) { font: inherit; color: inherit; }
:where(.tg a) { color: var(--tg-action); text-decoration: none; }
:where(.tg a):hover { text-decoration: underline; }
.tg [hidden] { display: none !important; }

.tg :where(a, button, select, input, summary, [tabindex]):focus-visible {
  outline: var(--tg-strong) solid var(--tg-focus);
  outline-offset: 2px;
  border-radius: var(--tg-r-sm);
}

@media (prefers-reduced-motion: reduce) {
  .tg *, .tg *::before, .tg *::after {
    animation: none !important;
    transition: none !important;
  }
}

/* ------------------------------------------------------------- gov strip */
/* The national identity strip is dark ground in BOTH themes: it is a
   government-of-India band with a fixed appearance, not a themed surface. */
.tg-gov {
  height: 34px;
  display: flex;
  align-items: center;
  gap: var(--tg-s4);
  padding: 0 var(--tg-s5);
  background: #1c1917;
  color: #f5f5f4;
  font-size: var(--tg-t-th);
  line-height: 1;
}
.tg-gov-id { display: flex; align-items: center; gap: var(--tg-s2); min-width: 0; white-space: nowrap; flex: 1 1 auto; }
.tg-gov-id span { font-size: var(--tg-t-th); color: #e7e5e4; }
.tg-gov-id i { color: #78716c; margin: 0 2px; }
/* the build-freshness stamp sits at the right end of the dark identity strip; its bold value needs
   a light colour to read there, and it pushes to the far edge on a wide screen */
.tg-gov-id .tg-fresh { margin-left: auto; color: #d6d3d1; }
.tg-gov-id .tg-fresh b { color: #ffffff; }
.tg-emblem {
  width: 18px; height: 18px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--tg-r-sm);
  background: rgba(255, 255, 255, 0.10);
  font-size: 10px; overflow: hidden;
}
.tg-emblem img, .tg-emblem svg { width: 100%; height: 100%; object-fit: contain; display: block; }

.tg-gov-util { margin-left: auto; display: flex; align-items: center; gap: var(--tg-s2); white-space: nowrap; }
.tg-util,
.tg-textsize button,
.tg-lang button {
  display: inline-flex; align-items: center; justify-content: center;
  height: 22px; padding: 0 var(--tg-s2);
  border-radius: var(--tg-r-full);
  color: #e7e5e4; font-size: var(--tg-t-th); line-height: 1;
  background: transparent;
}
.tg-util:hover, .tg-textsize button:hover, .tg-lang button:hover {
  text-decoration: underline; color: #ffffff; background: rgba(255, 255, 255, 0.10);
}
.tg-textsize, .tg-lang { display: inline-flex; align-items: center; gap: 2px; }
.tg-textsize { margin-left: var(--tg-s2); }
.tg-textsize button { min-width: 24px; font-weight: 600; }
.tg-lang button { min-width: 30px; }
.tg-textsize button.active, .tg-lang button.active {
  background: rgba(255, 255, 255, 0.20); color: #ffffff; font-weight: 600;
}
.tg-gov :where(a, button):focus-visible { outline-color: #ffffff; }

/* --------------------------------------------------------------- masthead */
.tg-mast {
  position: relative;
  height: 72px;
  display: flex; align-items: center; gap: var(--tg-s3);
  padding: 0 var(--tg-s5);
  background: var(--tg-surface);
  border-bottom: var(--tg-hair) solid var(--tg-border);
}
.tg-mark {
  width: 40px; height: 40px; flex: none;
  display: grid; place-items: center;
  border-radius: var(--tg-r-lg);
  background: var(--tg-action); color: var(--tg-on-primary);
  font-weight: 700; font-size: var(--tg-t-card); letter-spacing: 0.02em;
}
/* emblem + title are one home link; they stay on one row (the emblem never sits above the title)
   and clicking anywhere on them returns to the top of the tree */
.tg-mast-home {
  display: inline-flex; align-items: center; gap: var(--tg-s3);
  min-width: 0; flex: 0 1 auto;
  text-decoration: none; color: inherit; border-radius: var(--tg-r-lg);
}
.tg-mast-home:hover .tg-product { text-decoration: underline; }
.tg-mast-home:focus-visible { outline: 2px solid var(--tg-action); outline-offset: 3px; }
.tg-mast-title { min-width: 0; }
.tg-product { font-size: var(--tg-t-page); line-height: 1.2; font-weight: 600; letter-spacing: -0.01em; }
.tg-context { margin-top: 2px; font-size: var(--tg-t-label); color: var(--tg-text-secondary); }
.tg-mast-rule { width: 1px; height: 32px; flex: none; background: var(--tg-border); margin: 0 var(--tg-s1); }
.tg-fresh { font-size: var(--tg-t-small); color: var(--tg-text-secondary); white-space: nowrap; }
.tg-fresh b { color: var(--tg-text-primary); font-weight: 600; }
.tg-mast > .tg-fresh { margin-right: auto; }

.tg-btn {
  height: var(--tg-control); padding: 0 var(--tg-s3);
  display: inline-flex; align-items: center; gap: var(--tg-s2);
  border: var(--tg-hair) solid var(--tg-border-strong); border-radius: var(--tg-r-md);
  background: var(--tg-surface); color: var(--tg-text-primary);
  font-size: var(--tg-t-small); font-weight: 500; white-space: nowrap;
  transition: background .12s ease, border-color .12s ease;
}
.tg-btn:hover { background: var(--tg-muted-bg); border-color: var(--tg-text-tertiary); text-decoration: none; }
.tg-btn.primary { background: var(--tg-action); border-color: var(--tg-action); color: var(--tg-on-primary); font-weight: 600; }
.tg-btn.primary:hover { background: var(--tg-action); filter: brightness(1.08); }
.tg-btn:disabled { opacity: .45; cursor: not-allowed; }

.tg-account {
  height: var(--tg-control); padding: 0 var(--tg-s2);
  display: inline-flex; align-items: center; gap: var(--tg-s2);
  border-radius: var(--tg-r-md);
  font-size: var(--tg-t-small); color: var(--tg-text-primary); white-space: nowrap;
}
.tg-account:hover { background: var(--tg-muted-bg); }
.tg-avatar {
  width: 24px; height: 24px; flex: none;
  display: grid; place-items: center; border-radius: var(--tg-r-full);
  background: var(--tg-muted-bg); color: var(--tg-text-secondary);
  font-size: var(--tg-t-th); font-weight: 700;
}
.tg-menu {
  position: absolute; top: 62px; right: var(--tg-s5); z-index: 40;
  min-width: 220px; padding: var(--tg-s1);
  display: flex; flex-direction: column;
  background: var(--tg-surface);
  border: var(--tg-hair) solid var(--tg-border); border-radius: var(--tg-r-lg);
  box-shadow: 0 12px 32px rgba(28, 25, 23, 0.16);
}
.tg-menu[hidden] { display: none; }
.tg-menu a, .tg-menu button {
  display: flex; align-items: center; gap: var(--tg-s2);
  width: 100%; min-height: var(--tg-control); padding: 0 var(--tg-s3);
  border-radius: var(--tg-r-md);
  color: var(--tg-text-primary); font-size: var(--tg-t-small); text-align: left;
}
.tg-menu a:hover, .tg-menu button:hover { background: var(--tg-muted-bg); text-decoration: none; }
.tg-menu hr { border: 0; border-top: var(--tg-hair) solid var(--tg-border); margin: var(--tg-s1) 0; }

/* the public dashboard is anonymous: no account menu, no sign-out, no admin tools */
body.tg-public .tg-account-wrap { display: none; }

/* ------------------------------------------------------------------ main */
.tg-main {
  max-width: var(--tg-shell);
  margin: 0 auto;
  padding: var(--tg-s5);
  display: flex; flex-direction: column; gap: var(--tg-s5);
  min-width: 0;
}

/* ------------------------------------------------------------ scope chain */
.tg-chain { display: flex; align-items: flex-end; flex-wrap: wrap; gap: var(--tg-s2); }
.tg-chain-label {
  font-size: var(--tg-t-th); font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--tg-text-tertiary); padding-bottom: 10px; margin-right: var(--tg-s1);
}
.tg-step { display: flex; flex-direction: column; gap: var(--tg-s1); min-width: 0; }
.tg-step > span {
  font-size: var(--tg-t-th); font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--tg-text-tertiary);
}
.tg-step select {
  width: 189px; height: var(--tg-control); padding: 0 var(--tg-s2);
  border: var(--tg-hair) solid var(--tg-border-strong); border-radius: var(--tg-r-md);
  background: var(--tg-surface); color: var(--tg-text-primary);
  font-size: var(--tg-t-small); max-width: 100%;
}
.tg-step.disabled select, .tg-step select:disabled {
  opacity: .5; color: var(--tg-text-tertiary); background: var(--tg-muted-bg); cursor: not-allowed;
}
.tg-sep { color: var(--tg-text-tertiary); padding-bottom: 10px; font-size: var(--tg-t-body); }
.tg-chain-reset {
  height: var(--tg-control); padding: 0 var(--tg-s3);
  border-radius: var(--tg-r-md);
  color: var(--tg-action); font-size: var(--tg-t-small); font-weight: 600;
  margin-left: var(--tg-s1);
}
.tg-chain-reset:hover { text-decoration: underline; }

/* ------------------------------------------------------------ breadcrumb */
.tg-crumb {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--tg-s1) var(--tg-s2);
  font-size: var(--tg-t-small); color: var(--tg-text-secondary);
}
.tg-crumb a { color: var(--tg-action); }
.tg-crumb > span { color: var(--tg-text-secondary); }
.tg-crumb i { color: var(--tg-text-tertiary); }
.tg-crumb > span:last-of-type { color: var(--tg-text-primary); font-weight: 600; }
.tg-crumb-change {
  display: none;
  height: 28px; padding: 0 var(--tg-s3); margin-left: auto;
  border: var(--tg-hair) solid var(--tg-border-strong); border-radius: var(--tg-r-full);
  background: var(--tg-surface); color: var(--tg-action);
  font-size: var(--tg-t-label); font-weight: 600;
}

/* ----------------------------------------------------------------- tiles */
.tg-tiles { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--tg-s3); }
.tg-tile {
  display: flex; flex-direction: column; align-items: stretch; gap: var(--tg-s2);
  min-height: 120px; padding: 14px;
  border-radius: var(--tg-r-xl);
  background: var(--tg-cat-s, var(--tg-muted-bg));
  color: var(--tg-text-primary);
  text-align: left;
  cursor: default;
  transition: transform .14s ease, box-shadow .14s ease, opacity .14s ease;
}
.tg-tile-head { display: flex; align-items: flex-start; gap: var(--tg-s2); }
.tg-tile-name {
  font-size: var(--tg-t-label); font-weight: 600; line-height: 1.3;
  color: var(--tg-cat-i, var(--tg-text-primary));
}
.tg-tile-head .tg-chip { margin-left: auto; }
.tg-tile-val { display: flex; align-items: baseline; gap: var(--tg-s1); margin-top: auto; min-width: 0; }
.tg-tile-val b {
  font-size: var(--tg-t-metric); line-height: 1.1; font-weight: 700;
  color: var(--tg-cat-i, var(--tg-text-primary)); font-variant-numeric: tabular-nums;
}
.tg-tile-val i { font-size: var(--tg-t-small); color: var(--tg-text-secondary); }
.tg-tile-val em {
  margin-left: auto; font-size: var(--tg-t-small); font-weight: 600;
  color: var(--tg-text-secondary); font-variant-numeric: tabular-nums;
}
.tg-tile-val.em { font-size: var(--tg-t-metric); font-weight: 700; line-height: 1.1; color: var(--tg-cat-i, var(--tg-text-primary)); }
.tg-tile-sub { font-size: var(--tg-t-label); color: var(--tg-text-secondary); line-height: 1.35; }
.tg-tile .tg-bar > i { background: var(--tg-cat-i, var(--tg-action)); }

.tg-tile.live { cursor: pointer; }
.tg-tile.live:hover { transform: translateY(-2px); box-shadow: 0 6px 18px rgba(28, 25, 23, 0.14); }
.tg-tile.live:focus-visible { outline: var(--tg-strong) solid var(--tg-focus); outline-offset: 2px; }
.tg-tile.soon { cursor: default; filter: saturate(.5); }
/* box-shadow, not outline, so the selected ring and the focus ring can coexist */
.tg-tile.selected { box-shadow: inset 0 0 0 var(--tg-strong) var(--tg-cat-i, var(--tg-action)); }
.tg-tile.dim { opacity: .45; }

/* --------------------------------------------------------- progress bars */
.tg-bar {
  height: 6px; border-radius: var(--tg-r-full);
  background: var(--tg-surface); overflow: hidden; flex: none;
}
.tg-bar > i {
  display: block; height: 100%; width: 0; border-radius: var(--tg-r-full);
  background: var(--tg-action);
  transition: width .15s ease;
}
.tg-bar > i[data-band] { background: var(--tg-band); }

/* ---------------------------------------------------------------- columns */
.tg-cols { display: grid; grid-template-columns: minmax(0, 1fr) var(--tg-detail-w); gap: var(--tg-s4); align-items: start; }
/* a member is a leaf - nothing sits beneath it - so the locator/heatmap column is dropped and the
   record detail spans the full width, instead of sitting beside an empty "nothing to chart" panel */
#tg-root[data-level="member"] .tg-cols { grid-template-columns: minmax(0, 1fr); }
#tg-root[data-level="member"] #tg-panel { display: none; }
.tg-panel, .tg-detail, .tg-drill-side {
  background: var(--tg-surface);
  border: var(--tg-hair) solid var(--tg-border);
  border-radius: var(--tg-r-xl);
  min-width: 0;
  overflow: hidden;
}

/* ------------------------------------------------------------- map panel */
.tg-panel-head {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--tg-s2) var(--tg-s3);
  padding: var(--tg-s3) var(--tg-s4);
  border-bottom: var(--tg-hair) solid var(--tg-border);
}
.tg-panel-title { font-size: var(--tg-t-section); font-weight: 600; line-height: 1.3; }
.tg-panel-sub { font-size: var(--tg-t-small); color: var(--tg-text-tertiary); }
.tg-seg {
  margin-left: auto;
  display: inline-flex; align-items: center;
  border: var(--tg-hair) solid var(--tg-border-strong);
  border-radius: var(--tg-r-full);
  overflow: hidden;
  background: var(--tg-surface);
}
.tg-seg button {
  height: 30px; padding: 0 var(--tg-s3);
  font-size: var(--tg-t-label); font-weight: 500; color: var(--tg-text-secondary);
  white-space: nowrap;
}
.tg-seg button + button { border-left: var(--tg-hair) solid var(--tg-border); }
.tg-seg button:hover { background: var(--tg-muted-bg); color: var(--tg-text-primary); }
.tg-seg button.active { background: var(--tg-action); color: var(--tg-on-primary); font-weight: 600; }
.tg-seg button:focus-visible { outline-offset: -2px; }

/* The canvas is a fixed box and the drawing fits inside it.
   Telangana's outline is portrait (a 551x579 viewBox) while this column is wide, so `width:100%`
   with `height:auto` scaled the map to about 1,400px tall on a 1900px monitor - every label blown
   up with it. Bounding the canvas and letting preserveAspectRatio letterbox the drawing keeps the
   map the same readable size at every window width. */
.tg-canvas {
  position: relative;
  height: clamp(520px, 68vh, 880px);
  padding: var(--tg-s4);
  max-width: 100%;
}
.tg-map, .tg-dot, .tg-sq { width: 100%; height: 100%; display: block; }
/* the choropleth is wrapped so its callouts can be positioned against it; without a height here
   the SVG's `height:100%` has an auto-height parent to resolve against and falls back to its
   intrinsic aspect ratio, which is the over-zoom all over again */
.tg-mapwrap { position: relative; height: 100%; }
.tg-map { overflow: visible; }
.tg-map path {
  stroke: var(--tg-surface);
  stroke-width: 1;
  cursor: pointer;
  fill: var(--tg-muted-bg);
}
.tg-map path[data-band] { fill: var(--tg-band); }
/* A transform (even a null one) puts the path in its own stacking context, so
   its 2px stroke paints over its neighbours instead of half under them — SVG
   children otherwise honour document order only. */
.tg-map path:hover,
.tg-map path.on {
  stroke: var(--tg-text-primary);
  stroke-width: 2;
  transform: translate(0);
}
.tg-map path:focus-visible { outline: none; stroke: var(--tg-focus); stroke-width: 3; transform: translate(0); }
/* Hyderabad and anything that did not match a boundary: present but not a data
   value, so it takes the neutral ground and is not clickable. */
.tg-map path.na, .tg-map path.na[data-band] {
  fill: var(--tg-muted-bg);
  cursor: default;
  opacity: .8;
}
.tg-map path.na:hover { stroke: var(--tg-surface); stroke-width: 1; transform: none; }

/* Paint-order puts the halo stroke *behind* the glyph, so a label stays legible
   on a band-5 fill without a box behind it. */
.tg-map-label, .tg-sq text, .tg-dot text {
  font-size: 10px;
  text-anchor: middle;
  pointer-events: none;
  fill: var(--tg-text-primary);
  stroke: var(--tg-surface);
  stroke-width: 2px;
  stroke-linejoin: round;
  paint-order: stroke fill;
  font-family: var(--tg-sans);
}

.tg-callout, .tg-source {
  position: absolute; bottom: var(--tg-s4);
  max-width: 46%;
  padding: var(--tg-s1) var(--tg-s2);
  font-size: var(--tg-t-caption); line-height: 1.4;
  color: var(--tg-text-secondary);
  background: color-mix(in srgb, var(--tg-surface) 88%, transparent);
  border: var(--tg-hair) solid var(--tg-border);
  border-radius: var(--tg-r-md);
}
.tg-callout { left: var(--tg-s4); }
.tg-source { right: var(--tg-s4); text-align: right; }

/* Explanatory notes under the card instead of over the map.

   .tg-callout above is absolutely positioned for the in-map case, which is fine for one short
   line but put the GHMC paragraph on top of three districts. Inside this container it returns to
   normal flow and takes the full width, so the text wraps under the legend where it can be read
   without hiding the thing it is explaining. */
.tg-panel-notes {
  display: flex; flex-direction: column; gap: var(--tg-s2);
  padding: var(--tg-s3) var(--tg-s4) var(--tg-s4);
  border-top: var(--tg-hair) solid var(--tg-border);
}
.tg-panel-notes .tg-callout,
.tg-panel-notes .tg-source {
  position: static; inset: auto; max-width: none; text-align: left;
  border-left: 3px solid var(--tg-border);
  background: color-mix(in srgb, var(--tg-surface) 94%, transparent);
}
.tg-panel-notes .tg-callout.warn { border-left-color: var(--tg-warning, var(--tg-border)); }

/* The same voice as .tg-callout but in normal flow - the callout above is absolutely positioned
   for the map panel, and reusing it inside the card list would tear the layout apart. */
.tg-inline-note {
  margin: 0 0 var(--tg-s3);
  padding: var(--tg-s2) var(--tg-s3);
  font-size: var(--tg-t-caption); line-height: 1.45;
  color: var(--tg-text-secondary);
  background: color-mix(in srgb, var(--tg-surface) 88%, transparent);
  border: var(--tg-hair) solid var(--tg-border);
  border-left: 3px solid var(--tg-border-strong, var(--tg-border));
  border-radius: var(--tg-r-md);
}
.tg-inline-note b { color: var(--tg-text-primary); font-weight: 650; }

/* a zero denominator: no CBO of this type exists here, which is not the same as 0% */
.tg-card-kpi b.none { opacity: .55; font-weight: 600; }

/* ------------------------------------------------------------ heat modes */
.tg-dot circle[data-band] { fill: var(--tg-band); cursor: pointer; stroke: var(--tg-surface); stroke-width: 1; }
.tg-dot circle:hover { stroke: var(--tg-text-primary); stroke-width: 2; transform: translate(0); }
.tg-dot line { stroke: var(--tg-border); stroke-width: 1; }
.tg-sq rect[data-band] { fill: var(--tg-band); stroke: var(--tg-surface); stroke-width: 1; cursor: pointer; }
.tg-sq rect:hover { stroke: var(--tg-text-primary); stroke-width: 2; transform: translate(0); }
.tg-sq text { fill: var(--tg-text-primary); }
/* JS marks labels whose cell is too small to hold them */
.tg-sq text.tiny, .tg-dot text.tiny { display: none; }

.tg[data-mode="map"] .tg-dot, .tg[data-mode="map"] .tg-sq { display: none; }
.tg[data-mode="dot"] .tg-map, .tg[data-mode="dot"] .tg-sq { display: none; }
.tg[data-mode="square"] .tg-map, .tg[data-mode="square"] .tg-dot { display: none; }

/* ---------------------------------------------------------------- legend */
.tg-legend {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--tg-s3) var(--tg-s5);
  padding: var(--tg-s3) var(--tg-s4);
  border-top: var(--tg-hair) solid var(--tg-border);
  background: var(--tg-subtle);
  font-size: var(--tg-t-caption);
  color: var(--tg-text-secondary);
}
.tg-ramp { display: flex; align-items: center; gap: var(--tg-s2); flex-wrap: wrap; }
.tg-ramp-steps { display: inline-flex; gap: 2px; }
.tg-ramp-steps i {
  width: 28px; height: 12px; display: block;
  border-radius: 2px;
  background: var(--tg-band, var(--tg-muted-bg));
}
.tg-ramp-ends { display: inline-flex; gap: var(--tg-s2); font-size: var(--tg-t-caption); }
.tg-ramp-ends b { font-weight: 600; color: var(--tg-text-secondary); font-variant-numeric: tabular-nums; }
.tg-sizekey { display: flex; align-items: center; gap: var(--tg-s2); margin-left: auto; font-size: var(--tg-t-caption); }
.tg-sizekey i, .tg-sizekey b {
  display: inline-block; border-radius: var(--tg-r-full);
  background: var(--tg-border-strong); flex: none;
}
.tg-sizekey i:nth-of-type(1), .tg-sizekey b:nth-of-type(1) { width: 6px; height: 6px; }
.tg-sizekey i:nth-of-type(2), .tg-sizekey b:nth-of-type(2) { width: 10px; height: 10px; }
.tg-sizekey i:nth-of-type(3), .tg-sizekey b:nth-of-type(3) { width: 14px; height: 14px; }
.tg-sizekey svg { overflow: visible; }
.tg-sizekey circle { fill: var(--tg-border-strong); }

/* ----------------------------------------------------------- drill cards */
.tg-drill { display: flex; flex-direction: column; gap: var(--tg-s3); }
.tg-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--tg-s3); }
/* cards on the left, the selected type's exception list on the right; it stays in view while the grid scrolls */
.tg-drill-body { display: grid; grid-template-columns: minmax(0, 1fr) var(--tg-detail-w); gap: var(--tg-s4); align-items: start; }
.tg-drill-side { position: sticky; top: var(--tg-s3); min-width: 0; max-height: calc(100vh - 2 * var(--tg-s3)); overflow: auto; }
.tg-drill-side .tg-worst-sum { margin-bottom: var(--tg-s2); }
.tg-card {
  display: flex; flex-direction: column; gap: var(--tg-s2);
  padding: var(--tg-s3);
  border-radius: var(--tg-r-xl);
  background: var(--tg-band, var(--tg-muted-bg));
  /* every text node in the card rides on the band fill, so it inherits the
     band's ink — white on bands 4 and 5 */
  color: var(--tg-band-ink, var(--tg-text-primary));
  text-decoration: none;
  transition: transform .14s ease, box-shadow .14s ease;
}
.tg-card:hover { text-decoration: none; transform: translateY(-2px); box-shadow: 0 6px 18px rgba(28, 25, 23, 0.16); }
.tg-card-head { display: flex; align-items: baseline; gap: var(--tg-s2); min-width: 0; }
.tg-card-name {
  font-size: var(--tg-t-card); font-weight: 600; line-height: 1.3;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tg-card-code { font-family: var(--tg-mono); font-size: var(--tg-t-th); opacity: .7; white-space: nowrap; }
.tg-card-kpi { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--tg-s1) var(--tg-s2); }
.tg-card-kpi-name {
  flex: 1 1 100%;
  font-size: var(--tg-t-th); text-transform: uppercase; letter-spacing: 0.04em;
  opacity: .85;
}
.tg-card-kpi b { font-size: var(--tg-t-metric-sm); font-weight: 700; line-height: 1.15; font-variant-numeric: tabular-nums; }
.tg-card-kpi i { font-size: var(--tg-t-label); opacity: .85; }
.tg-card-kpi em { margin-left: auto; font-size: var(--tg-t-label); font-weight: 600; font-variant-numeric: tabular-nums; }
.tg-card-kpi .tg-bar { flex: 1 1 100%; background: var(--tg-band-track, var(--tg-band-lo-track)); }
.tg-card-kpi .tg-bar > i { background: currentColor; opacity: .9; }
.tg-card-kpi.txn .tg-bar > i { opacity: .65; }

/* --------------------------------------------------------- detail panels */
.tg-detail { display: flex; flex-direction: column; }
.tg-dpanel { min-width: 0; }
.tg-dpanel + .tg-dpanel { border-top: var(--tg-hair) solid var(--tg-border); }
.tg-dpanel-head {
  display: flex; align-items: baseline; gap: var(--tg-s2);
  padding: var(--tg-s3) var(--tg-s4);
  border-bottom: var(--tg-hair) solid var(--tg-border);
}
.tg-dpanel-head h3 { font-size: var(--tg-t-card); font-weight: 600; line-height: 1.3; }
.tg-note { font-size: var(--tg-t-label); color: var(--tg-text-tertiary); margin-left: auto; text-align: right; }
.tg-dpanel-body { padding: var(--tg-s4); display: flex; flex-direction: column; gap: var(--tg-s3); }

/* A panel that folds. The month table is detail, not a headline, so it opens on demand; `details`
   carries the keyboard and screen-reader behaviour for free. Closed, the head's bottom border
   would be a line under nothing, so it is dropped. */
details.tg-fold > summary {
  cursor: pointer; list-style: none;
  -webkit-tap-highlight-color: transparent;
}
details.tg-fold > summary::-webkit-details-marker { display: none; }
details.tg-fold > summary::after {
  content: ''; flex: 0 0 auto;
  width: 7px; height: 7px; margin-left: var(--tg-s2); align-self: center;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translate(-1px, -1px);
  transition: transform .15s ease; opacity: .5;
}
details.tg-fold[open] > summary::after { transform: rotate(-135deg) translate(-1px, -1px); }
details.tg-fold > summary:hover::after { opacity: .9; }
details.tg-fold:not([open]) > summary { border-bottom: 0; }

/* The ten-worst lists. A ranked list, so an ordered list - the number carries meaning and a
   screen reader should read it. */
.tg-worst { list-style: none; counter-reset: worst; display: flex; flex-direction: column; gap: 2px; }
.tg-worst > li {
  counter-increment: worst;
  display: flex; align-items: baseline; gap: var(--tg-s2);
  padding: 5px 0; min-width: 0;
  border-bottom: var(--tg-hair) solid var(--tg-border);
}
.tg-worst > li:last-child { border-bottom: 0; }
.tg-worst > li::before {
  content: counter(worst);
  flex: 0 0 1.4em; text-align: right;
  font-size: var(--tg-t-label); font-variant-numeric: tabular-nums;
  color: var(--tg-text-tertiary);
}
.tg-worst-name {
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--tg-t-label); color: var(--tg-text-primary); text-decoration: none;
}
a.tg-worst-name:hover { text-decoration: underline; }
.tg-worst-id { margin-left: 6px; font-family: var(--tg-mono); font-size: var(--tg-t-caption); color: var(--tg-text-tertiary); }
.tg-worst > li.tg-worst-off .tg-worst-name { color: var(--tg-text-tertiary); }
.tg-worst .tg-chip { flex: none; }
.tg-worst-sum { margin: 0 0 4px; font-size: var(--tg-t-caption); color: var(--tg-text-tertiary); }
.tg-worst-none { margin: 4px 0; font-size: var(--tg-t-label); color: var(--tg-text-tertiary); }
.tg-worst-more { display: block; margin: 8px 0 2px; font-size: var(--tg-t-caption); }
.tg-worst > li.click { cursor: pointer; border-radius: var(--tg-r-sm); }
.tg-worst > li.click:hover, .tg-worst > li.click:focus-visible { background: var(--tg-muted-bg); outline: none; }
/* the records behind one exception row, in a popup */
dialog.tg-modal {
  border: 0; padding: 0; margin: auto;
  width: min(760px, calc(100vw - 32px)); max-height: min(86vh, 920px);
  background: var(--tg-surface); color: var(--tg-text-primary);
  border-radius: var(--tg-r-xl); box-shadow: 0 24px 64px rgba(20, 16, 12, .32);
}
dialog.tg-modal[open] { display: flex; flex-direction: column; }
dialog.tg-modal::backdrop { background: rgba(20, 16, 12, .45); }
.tg-modal-head { display: flex; align-items: flex-start; gap: var(--tg-s3); padding: var(--tg-s4) var(--tg-s4) var(--tg-s3); border-bottom: var(--tg-hair) solid var(--tg-border); }
.tg-modal-title { min-width: 0; flex: 1 1 auto; }
.tg-modal-title h3 { margin: 0; font-size: var(--tg-t-card); font-weight: 600; line-height: 1.3; }
.tg-modal-title .tg-worst-sum { margin: 4px 0 0; }
.tg-modal-close { flex: none; }
.tg-modal-body { padding: var(--tg-s2) var(--tg-s4); overflow: auto; min-height: 120px; }
.tg-modal-foot { display: flex; align-items: center; justify-content: space-between; gap: var(--tg-s3); padding: var(--tg-s3) var(--tg-s4); border-top: var(--tg-hair) solid var(--tg-border); }
.tg-rec { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.tg-rec > li {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: auto auto; column-gap: var(--tg-s2);
  padding: 6px 0; border-bottom: var(--tg-hair) solid var(--tg-border); min-width: 0;
}
.tg-rec > li:last-child { border-bottom: 0; }
.tg-rec-name { font-size: var(--tg-t-label); color: var(--tg-text-primary); text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tg-rec-name:hover { text-decoration: underline; }
.tg-rec > li > .tg-worst-id { grid-column: 1; margin-left: 0; }
.tg-rec-place { grid-column: 1; font-size: var(--tg-t-caption); color: var(--tg-text-tertiary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tg-rec-metric { grid-column: 2; grid-row: 1 / span 3; align-self: center; display: flex; flex-direction: column; align-items: flex-end; gap: 2px; white-space: nowrap; }
.tg-rec-count { display: flex; align-items: baseline; gap: 4px; }
.tg-rec-count b { font-size: var(--tg-t-label); font-weight: 700; font-variant-numeric: tabular-nums; }
.tg-rec-count i { font-size: var(--tg-t-caption); font-style: normal; color: var(--tg-text-tertiary); }
.tg-rec-block, .tg-rec-ok { font-size: var(--tg-t-caption); font-style: normal; }
.tg-rec-block { color: var(--tg-danger); font-weight: 600; }
.tg-rec-ok { color: var(--tg-text-tertiary); }
.tg-worst-val { flex: 0 0 auto; display: flex; align-items: baseline; gap: 5px; }
.tg-worst-val b { font-size: var(--tg-t-label); font-weight: 700; font-variant-numeric: tabular-nums; }
.tg-worst-val i { font-size: var(--tg-t-caption); font-style: normal; color: var(--tg-text-tertiary); }
details.tg-fold > summary:focus-visible {
  outline: 2px solid var(--tg-focus, currentColor); outline-offset: -2px;
}

.tg-kpis { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--tg-s3) var(--tg-s4); }
.tg-kpi { display: flex; flex-direction: column; gap: var(--tg-s1); min-width: 0; }
.tg-kpi-name { font-size: var(--tg-t-label); font-weight: 600; color: var(--tg-cat-i, var(--tg-text-secondary)); }
.tg-kpi-val { display: flex; align-items: baseline; gap: var(--tg-s1); }
.tg-kpi-val b { font-size: var(--tg-t-metric-sm); font-weight: 700; line-height: 1.15; font-variant-numeric: tabular-nums; }
.tg-kpi-val i { font-size: var(--tg-t-small); color: var(--tg-text-secondary); }
.tg-kpi .tg-bar { background: var(--tg-muted-bg); }
.tg-kpi .tg-bar > i { background: var(--tg-cat-i, var(--tg-action)); }
.tg-kpi-pct { text-align: right; font-size: var(--tg-t-small); font-weight: 600; font-variant-numeric: tabular-nums; }

.tg-rank { display: flex; flex-direction: column; gap: var(--tg-s1); }
.tg-rank li {
  display: flex; align-items: center; gap: var(--tg-s2);
  padding: var(--tg-s1) var(--tg-s1);
  border-radius: var(--tg-r-md);
  font-size: var(--tg-t-small);
}
.tg-rank-n {
  width: 18px; height: 18px; flex: none;
  display: grid; place-items: center;
  border-radius: var(--tg-r-full);
  background: var(--tg-subtle); border: var(--tg-hair) solid var(--tg-border);
  font-size: var(--tg-t-th); color: var(--tg-text-secondary); font-variant-numeric: tabular-nums;
}
.tg-rank-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tg-rank .tg-bar { width: 80px; flex: none; background: var(--tg-muted-bg); }
.tg-rank-val { width: 52px; flex: none; text-align: right; font-size: var(--tg-t-small); font-weight: 600; font-variant-numeric: tabular-nums; }
.tg-rank li.click { cursor: pointer; }
.tg-rank li.click:hover { background: var(--tg-muted-bg); }

/* ---------------------------------------------------------------- chips */
.tg-chip {
  display: inline-flex; align-items: center; gap: var(--tg-s1);
  padding: 1px var(--tg-s2);
  border: var(--tg-hair) solid var(--tg-border);
  border-radius: var(--tg-r-full);
  background: var(--tg-surface);
  font-size: var(--tg-t-th); line-height: 1.6; white-space: nowrap;
  color: var(--tg-text-secondary);
}
.tg-chip.soon {
  text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600;
  /* on a category surface the neutral grey is 3.65-3.88:1; the tile's own ink clears 5.3+ */
  color: var(--tg-cat-i, var(--tg-neutral));
  background: color-mix(in srgb, var(--tg-surface) 55%, transparent);
  border-color: color-mix(in srgb, var(--tg-cat-i, var(--tg-neutral)) 30%, var(--tg-surface));
}
.tg-chip.good {
  color: var(--tg-success);
  background: color-mix(in srgb, var(--tg-success) 10%, var(--tg-surface));
  border-color: color-mix(in srgb, var(--tg-success) 30%, var(--tg-surface));
}
.tg-chip.warn {
  color: var(--tg-warning);
  background: color-mix(in srgb, var(--tg-warning) 10%, var(--tg-surface));
  border-color: color-mix(in srgb, var(--tg-warning) 30%, var(--tg-surface));
}
.tg-chip.bad {
  color: var(--tg-danger);
  background: color-mix(in srgb, var(--tg-danger) 10%, var(--tg-surface));
  border-color: color-mix(in srgb, var(--tg-danger) 30%, var(--tg-surface));
}

/* ---------------------------------------------------------------- states */
.tg-empty, .tg-loading, .tg-error {
  display: flex; align-items: center; justify-content: center;
  gap: var(--tg-s2);
  min-height: 120px; padding: var(--tg-s5);
  text-align: center; font-size: var(--tg-t-small);
  color: var(--tg-text-tertiary);
}
.tg-error { color: var(--tg-danger); }
.tg-skel {
  height: 12px; border-radius: var(--tg-r-md);
  background: linear-gradient(90deg, var(--tg-muted-bg) 25%, var(--tg-subtle) 37%, var(--tg-muted-bg) 63%);
  background-size: 400% 100%;
  animation: tg-shimmer 1.4s ease-in-out infinite;
}
@keyframes tg-shimmer { from { background-position: 100% 50%; } to { background-position: 0 50%; } }
@media (prefers-reduced-motion: reduce) {
  .tg-skel { animation: none; background: var(--tg-muted-bg); }
}

/* ---------------------------------------------------------------- footer */
.tg-foot {
  border-top: var(--tg-hair) solid var(--tg-border);
  background: var(--tg-subtle);
  padding: var(--tg-s4) var(--tg-s5) var(--tg-s5);
  font-size: var(--tg-t-label); line-height: 1.6;
  color: var(--tg-text-secondary);
  text-align: center;
}
.tg-foot p { max-width: var(--tg-shell); margin: 0 auto; }
.tg-foot p + p { margin-top: var(--tg-s1); color: var(--tg-text-tertiary); }
.tg-foot a { color: var(--tg-text-secondary); text-decoration: underline; }
.tg-foot a:hover { color: var(--tg-text-primary); }

/* ==========================================================================
   RESPONSIVE — 768-1279: columns stack, tiles 4+3, chain on two rows
   ========================================================================== */
@media (max-width: 1279px) {
  .tg { margin: -24px -20px -72px; }
  .tg-cols { grid-template-columns: minmax(0, 1fr); }
  .tg-drill-body { grid-template-columns: minmax(0, 1fr); }
  .tg-drill-side { position: static; }
  .tg-detail { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tg-dpanel + .tg-dpanel { border-top: 0; }
  .tg-dpanel { border-top: var(--tg-hair) solid var(--tg-border); }
  .tg-dpanel:nth-child(-n + 2) { border-top: 0; }
  .tg-dpanel:nth-child(odd) { border-right: var(--tg-hair) solid var(--tg-border); }
}

@media (max-width: 1279px) and (min-width: 768px) {
  /* 12 columns: four tiles of 3 on the first row, three tiles of 4 on the second */
  .tg-tiles { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .tg-tile:nth-child(-n + 4) { grid-column: span 3; }
  .tg-tile:nth-child(n + 5) { grid-column: span 4; }
}

@media (max-width: 1023px) {
  .tg-step { flex: 1 1 180px; }
  .tg-step select { width: 100%; }
  .tg-canvas { min-height: 480px; }
}

@media (max-width: 833px) {
  .tg-chain { row-gap: var(--tg-s3); }
  .tg-chain-label { flex: 1 1 100%; padding-bottom: 0; }
}

/* ==========================================================================
   RESPONSIVE — <768: one column, breadcrumb instead of the chain
   ========================================================================== */
@media (max-width: 767px) {
  .tg { margin: -16px -16px calc(-80px - env(safe-area-inset-bottom, 0px)); }
  .tg-main { padding: var(--tg-s4); gap: var(--tg-s4); }

  /* The strip scrolls sideways as one row rather than stacking into three
     lines; it also grows past 34px because its controls take a 44px target. */
  .tg-gov {
    height: auto; min-height: 34px;
    padding: var(--tg-s1) var(--tg-s4);
    overflow-x: auto; overflow-y: hidden;
    flex-wrap: nowrap; scrollbar-width: none;
  }
  .tg-gov::-webkit-scrollbar { display: none; }
  .tg-gov-id, .tg-gov-util { flex: none; }
  .tg-gov-util { margin-left: var(--tg-s4); }

  .tg-mast { height: auto; flex-wrap: wrap; gap: var(--tg-s2); padding: var(--tg-s3) var(--tg-s4); }
  .tg-mast-rule { display: none; }
  .tg-product { font-size: var(--tg-t-section); }
  .tg-mast > .tg-fresh { margin-right: 0; flex: 1 1 100%; }
  .tg-menu { right: var(--tg-s4); left: var(--tg-s4); top: auto; }

  /* the scope dropdowns stay available on a phone: they wrap two-per-row with full-width selects,
     the "›" separators drop (rows wrap, so they would float oddly), and the breadcrumb's redundant
     "Change" button is hidden since the dropdowns now do that job */
  .tg-chain { display: flex; flex-wrap: wrap; row-gap: var(--tg-s2); column-gap: var(--tg-s2); align-items: flex-end; }
  .tg-chain .tg-sep { display: none; }
  .tg-chain-label { display: none; }
  .tg-step { flex: 1 1 42%; min-width: 0; }
  .tg-step select { width: 100%; }
  .tg-chain-reset { margin-left: auto; }
  .tg-crumb-change { display: none; }

  .tg-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tg-tile, .tg-tile:nth-child(-n + 4), .tg-tile:nth-child(n + 5) { grid-column: auto; }
  .tg-tile-val b, .tg-tile-val.em { font-size: var(--tg-t-metric-sm); }

  .tg-detail { grid-template-columns: minmax(0, 1fr); }
  .tg-dpanel:nth-child(odd) { border-right: 0; }
  .tg-dpanel:nth-child(2) { border-top: var(--tg-hair) solid var(--tg-border); }

  .tg-canvas { min-height: 440px; padding: var(--tg-s3); }
  /* Names and values ARE shown on the map and heatmap here: the builders enlarge the SVG type to
     survive the ~0.4x phone down-scale and thin the label count so they do not collide, and a cell
     too small to hold the larger type drops its own label. Only the (unused) dot-burst hub stays off. */
  .tg-dot-hublabel { display: none; }
  .tg-callout, .tg-source { position: static; max-width: none; text-align: left; margin-top: var(--tg-s2); }

  .tg-cards { grid-template-columns: minmax(0, 1fr); }

  /* ranked rows go to two lines: name, then bar + value */
  .tg-rank li { flex-wrap: wrap; row-gap: var(--tg-s1); padding: var(--tg-s2) var(--tg-s1); }
  .tg-rank-name { flex: 1 1 auto; white-space: normal; }
  .tg-rank .tg-bar { flex: 1 1 auto; width: auto; margin-left: 26px; }
  .tg-rank-val { width: auto; min-width: 52px; }

  .tg-legend { gap: var(--tg-s2) var(--tg-s4); padding: var(--tg-s3) var(--tg-s4); }
  .tg-sizekey { margin-left: 0; }
  .tg-foot { padding: var(--tg-s4); }

  /* touch targets */
  .tg-btn, .tg-account, .tg-chain-reset, .tg-crumb-change,
  .tg-seg button, .tg-menu a, .tg-menu button,
  .tg-util, .tg-textsize button, .tg-lang button {
    min-height: var(--tg-touch);
  }
  .tg-textsize button, .tg-lang button, .tg-util { min-width: 40px; border-radius: var(--tg-r-lg); }
  .tg-seg { border-radius: var(--tg-r-lg); }
  .tg-step select { height: var(--tg-touch); }

  /* nothing may push the page sideways */
  .tg, .tg-main, .tg-cols, .tg-panel, .tg-detail, .tg-canvas { max-width: 100%; }
  .tg-canvas { overflow-x: auto; }
}

/* ---------------------------------------------------------------- 1600+ */
@media (min-width: 1600px) {
  .tg { margin-left: -44px; margin-right: -44px; }
}

/* ----------------------------------------------------------------- print */
@media print {
  .tg-gov, .tg-seg, .tg-chain-reset, .tg-account, .tg-menu { display: none !important; }
  .tg { margin: 0; background: #ffffff; }
  .tg-panel, .tg-detail, .tg-card, .tg-tile { break-inside: avoid; }
}


/* ---- the app shell, while the dashboard is open -----------------------------------------
   The V3 product has no sidebar, rail or tab bar: the scope chain IS the navigation and it
   doubles as the breadcrumb. `tg-solo` is set by the router while #voa is the open route;
   `tg-only` is set for the VOA role, which has no other view to go back to. Both hide the
   shell, and both must therefore also collapse the shell's grid column and page padding -
   otherwise the government strip would start 232px in from the left edge.
   ---------------------------------------------------------------------------------------- */

body.tg-solo .sidebar,
body.tg-solo .tabbar,
body.tg-solo .mobilebar,
body.tg-only .sidebar,
body.tg-only .tabbar,
body.tg-only .mobilebar { display: none !important; }

body.tg-solo .app,
body.tg-only .app { grid-template-columns: minmax(0, 1fr) !important; }

/* the shell's own <main>, NOT the dashboard's <main class="tg-main"> - an unscoped `main`
   selector here zeroes the dashboard's 24px gutter and clips the scope chain off the left edge */
body.tg-solo .app > main,
body.tg-only .app > main { padding: 0 !important; max-width: none !important; gap: 0 !important; }

body.tg-solo #view-voa,
body.tg-only #view-voa { padding: 0 !important; gap: 0 !important; }

/* The full-bleed negative margins above exist to escape main's padding; with that padding gone
   they would instead pull the dashboard off the edge. The TOP margin matters as much as the
   sides - left at -24px it lifts the page above the viewport and shears the 34px government
   strip down to a 10px sliver. */
body.tg-solo .tg,
body.tg-only .tg { margin: 0 !important; width: 100% !important; }

/* the account dropdown anchors to its own wrapper, not to the whole masthead */
.tg-account-wrap { position: relative; display: inline-flex; }

/* the transient status line the government-strip utilities and Help write into */
.tg-toast {
  position: fixed; left: 50%; bottom: 24px; transform: translate(-50%, 12px);
  max-width: min(560px, calc(100vw - 32px));
  padding: 10px 14px; border-radius: var(--tg-radius-lg, 8px);
  background: var(--tg-text-primary); color: var(--tg-surface);
  font-size: 13px; line-height: 1.45; box-shadow: 0 6px 24px rgba(0, 0, 0, .28);
  opacity: 0; pointer-events: none; transition: opacity .18s ease, transform .18s ease;
  z-index: 60;
}
.tg-toast.on { opacity: 1; transform: translate(-50%, 0); }

/* High contrast, from the government strip's own control */
.tg.tg-hc { --tg-text-secondary: var(--tg-text-primary); --tg-text-tertiary: var(--tg-text-primary); --tg-border: var(--tg-text-primary); }
.tg.tg-hc .tg-panel,
.tg.tg-hc .tg-detail,
.tg.tg-hc .tg-tile { border-width: 2px; }

/* key/value list in the CLF / VO / SHG detail panel */
.tg-kv { display: grid; grid-template-columns: 120px minmax(0, 1fr); gap: 6px 12px; margin: 0; }
.tg-kv dt { color: var(--tg-text-tertiary); font-size: 12px; }
.tg-kv dd { margin: 0; font-size: 13px; color: var(--tg-text-primary); }
.tg-kv dd.mono { font-family: var(--tg-mono, ui-monospace, monospace); font-size: 12px; }

/* the full exception list on an entity */
.tg-exc { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.tg-exc li {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 8px; align-items: baseline;
  padding: 7px 8px; border: 1px solid var(--tg-border); border-radius: var(--tg-radius-md, 6px);
  background: var(--tg-subtle); font-size: 13px;
}
.tg-exc li.blocks { border-color: var(--tg-danger, #b91c1c); background: color-mix(in srgb, var(--tg-danger, #b91c1c) 6%, var(--tg-surface)); }
.tg-exc-id { font-family: var(--tg-mono, ui-monospace, monospace); font-size: 11px; color: var(--tg-text-tertiary); }
.tg-exc-label { min-width: 0; }

.tg-btn.block { display: block; width: 100%; text-align: center; text-decoration: none; line-height: 34px; }

.tg-drill-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 12px; }

/* The name is what the reader is looking for, so it takes the whole first line; the code and any
   "N blocking" chip wrap beneath it. Sharing one row crushed SHG names down to "GAA…".
   The code sits directly under the name at the left margin - pushed to the right it read as a
   column of its own rather than as the name's code. The chip keeps the right-hand side. */
.tg-card-head { flex-wrap: wrap; row-gap: 2px; }
.tg-card-head .tg-card-name { flex: 1 1 100%; }
.tg-card-head .tg-chip { margin-left: auto; }
.tg-crumb-exit, .tg-crumb-change { margin-left: 8px; }

@media (max-width: 767px) {
  body.tg-solo main, body.tg-only main { padding-bottom: 0 !important; }
}


/* Skip link. The V3 identity strip carries one identity line and the language switcher and
   nothing else, so this is present for keyboard users but only paints when focused. */
.tg-skip {
  position: absolute; left: -9999px; top: 0;
  padding: 8px 14px; border-radius: 0 0 var(--tg-r-md, 6px) 0;
  /* --tg-on-primary, not #fff: in dark mode the accent lightens and white drops to 3.27:1 */
  background: var(--tg-action); color: var(--tg-on-primary, #fff); font-size: 13px; font-weight: 600;
  text-decoration: none; z-index: 80;
}
.tg-skip:focus-visible, .tg-skip:focus { left: 0; outline: 2px solid var(--tg-focus); outline-offset: -4px; }


/* ---- full-width layout ---------------------------------------------------------------
   The V3 frames are drawn at a 1440 viewport, which is a canvas size, not a maximum. Capping
   the shell there frames a wide monitor in empty margins, so --tg-shell is released and the
   gutter grows with the breakpoint instead. The detail panel keeps its fixed 520.
   -------------------------------------------------------------------------------------- */
.tg .tg-main { max-width: none; }
.tg .tg-foot p { max-width: none; }
@media (min-width: 1600px) {
  .tg .tg-main { padding-left: var(--tg-s6); padding-right: var(--tg-s6); }
  .tg .tg-gov, .tg .tg-mast, .tg .tg-foot { padding-left: var(--tg-s6); padding-right: var(--tg-s6); }
}
@media (min-width: 2000px) {
  .tg .tg-main { padding-left: var(--tg-s7); padding-right: var(--tg-s7); }
  .tg .tg-gov, .tg .tg-mast, .tg .tg-foot { padding-left: var(--tg-s7); padding-right: var(--tg-s7); }
}


/* ---- mandal markers ------------------------------------------------------------------
   The district view drills below the published boundary layer. Mandals have no polygons, so
   they are drawn as points at their observed median coordinate - deliberately circles, so no
   one reads them as borders. Sizes are set inline in viewBox units so zoom does not change
   their apparent size.
   -------------------------------------------------------------------------------------- */
.tg-map-neighbour { fill: var(--tg-muted-bg); stroke: var(--tg-surface); stroke-width: 1; opacity: .55; }
.tg-map-here { fill: var(--tg-subtle); stroke: var(--tg-text-secondary); stroke-width: 1.4; }
/* The district view zooms the viewBox, and `.tg-map` is overflow:visible so a state-level label
   can sit outside the box. Zoomed in, that lets the map paint over the panel header, so this one
   clips. */
.tg-map-mandal { overflow: hidden; }
/* below district the polygon is only a bearing, not a container */
.tg-map-edge { fill: none; stroke: var(--tg-border-strong); stroke-width: .8; stroke-dasharray: 3 3; }
.tg-mandal {
  fill: var(--tg-band, var(--tg-muted-bg));
  stroke: var(--tg-surface); stroke-width: 1; cursor: pointer;
  transition: stroke-width .12s ease;
}
.tg-mandal:hover, .tg-mandal:focus-visible {
  stroke: var(--tg-text-primary); stroke-width: 2; outline: none;
}
.tg-mandal-label {
  fill: var(--tg-text-primary); text-anchor: middle; pointer-events: none;
  paint-order: stroke; stroke: var(--tg-surface); stroke-width: 2px; stroke-linejoin: round;
}
@media (max-width: 767px) { .tg-mandal-label { display: none; } }


/* A chip on a drill card sits on a band fill, not on the page. Left transparent it inherits that
   band and a status colour lands at 1.78:1 on it, so inside a card a chip carries its own solid
   surface and the status hue goes back to being text on a plain ground. */
.tg-card .tg-chip {
  background: var(--tg-surface);
  border-color: var(--tg-border);
}
.tg-card .tg-chip.bad { color: var(--tg-danger); }
.tg-card .tg-chip.good { color: var(--tg-success); }
.tg-card .tg-chip.warn { color: var(--tg-warning); }


/* map canvas, small screens: a full-height box on a phone pushes everything below it off the
   fold, so each tier gets its own ceiling - raised with the desktop one, in proportion */
@media (max-width: 767px) {
  .tg-canvas { height: clamp(340px, 54vh, 500px); padding: var(--tg-s3); }
}
@media (min-width: 768px) and (max-width: 1279px) {
  .tg-canvas { height: clamp(440px, 58vh, 680px); }
}


/* ---- regular meetings, month by month -------------------------------------------------
   A compact year-at-a-glance table inside the 520px detail panel: month, then one column per
   CBO type that actually has figures. The bar carries the shape, the number carries the value.
   ---------------------------------------------------------------------------------------- */
.tg-months { width: 100%; border-collapse: collapse; font-size: var(--tg-t-small); }
.tg-months th {
  text-align: right; font-size: var(--tg-t-th); font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--tg-text-tertiary);
  padding: 0 0 6px; border-bottom: 1px solid var(--tg-border);
}
.tg-months th.mth, .tg-months td.mth { text-align: left; }
.tg-months td {
  padding: 5px 0; border-bottom: 1px solid var(--tg-border);
  color: var(--tg-text-primary); vertical-align: middle;
}
.tg-months tbody tr:last-child td { border-bottom: 0; }
.tg-months td.mth { white-space: nowrap; padding-right: var(--tg-s3); }
.tg-months td.num { text-align: right; padding-left: var(--tg-s3); }
/* a month the export defines but nobody has reached yet - present, but plainly not a result */
.tg-months tr.none td { color: var(--tg-text-tertiary); }
.tg-months tr.none .tg-mbar > i { background: var(--tg-border-strong); }
.tg-mbar {
  display: inline-block; vertical-align: middle; width: 56px; height: 5px;
  border-radius: var(--tg-r-full); background: var(--tg-muted-bg); overflow: hidden;
  margin-right: var(--tg-s2);
}
.tg-mbar > i { display: block; height: 100%; background: var(--tg-action); border-radius: inherit; }
.tg-mpct { display: inline-block; min-width: 46px; text-align: right; font-variant-numeric: tabular-nums; }
@media (max-width: 767px) { .tg-mbar { width: 40px; } }

/* District choropleth: the mandal-cell outline sits above the cells, non-interactive.
   The selector must out-specify `.tg-map path` (0,1,1) or that rule's grey fill wins and the
   outline paints a grey blob over every cell - hence `.tg-map path.tg-map-fence-outline` (0,2,1). */
.tg-map path.tg-map-fence-outline { fill: none; stroke: var(--tg-text-secondary); stroke-width: 1.2; cursor: default; pointer-events: none; }
