/* ==========================================================================
   TN-METER — the one shared proportional-bar surface (admin + user + public)
   --------------------------------------------------------------------------
   Q-UIUX E1. Eight stylesheets defined the same track/fill pair before this
   file existed, and every one of them re-decided the same five questions
   (height, radius, track colour, tone mapping, how the width gets in):

     1. `.tool-health-card__progress` / `__progress-fill` +
        `--healthy` / `--warning` / `--critical`
        (`pages/admin-runtime-diagnostics.css`) — 8px, `border-radius: 999px`.
     2. `.email-kpi__meter` / `__meter-fill` (`admin-email-overview.css`) —
        4px, and the only fork that solved the width problem: a 21-step
        `[data-width="0|5|…|100"]` ladder, because
        `EmailAdminViewContractTests` bans `style=` in that view outright.
     3. `.email-senders-meter` / `__fill` + `.is-tight` / `.is-exhausted`
        (`admin-email-senders.css`) — 4px, `max-width: 9rem`, built in JS.
     4. `.auth-password-strength__track` / `__bar` (`components/auth.css`) —
        4px, `border-radius: 2px`, and a track coloured `--tn-border-subtle`
        rather than the inset surface every other fork used.
     5. `.exec-mon-confidence-bar` / `__fill` / `__fill--blue`
        (`pages/admin-execution-monitoring.css`) — 64px × 4px, and **raw
        literals**: `rgb(24 24 27)`, `rgb(16 185 129)`, `rgb(59 130 246)`,
        which the eleven selectable admin themes cannot re-point.
     6. `.loader-progress-bar` / `-fill` (`components/admin-shell-layout.css`)
        — 2px, and **zero call sites** in the entire repo. Dead on arrival.
     7. `.loader-progress-bar` / `-fill` again
        (`tool-public-new/css/new-tool-public-page.css`) — the same two class
        names a second time, also with zero call sites, this time animated by
        private `loaderProgressAnim` / `loaderShimmer` keyframes over a
        hard-coded three-stop blue gradient. Two independent copies of a dead
        widget is what a missing shared component costs even when nobody is
        looking at it.
     8. Ten hand-written Tailwind-utility bars across six admin views
        (`AgenticRuns/Details`, `EeatContent/Index` ×4, `EeatContent/Authors`,
        `SocialDistribution/Analytics` ×2, `SocialDistribution/CampaignDetails`)
        which had no vocabulary at all — `h-2 rounded-full bg-[…] overflow-hidden`
        repeated inline, with the width AND the tone token interpolated into a
        `style` attribute. `CampaignDetails` had been broken by that pattern for
        as long as it existed: its width was `@(bar.Value > 0 ? 100 : 0)%`, so
        every non-zero engagement metric drew a full bar.

   One name, one prefix. `tn-` because a meter is shared vocabulary like
   `tn-empty` / `tn-toast`, not admin-owned: naming fork 1 `tool-health-card__*`
   and fork 4 `auth-*` is exactly why the public auth surface and the admin
   panel ended up with two 4px bars that disagreed about their track colour.

   ── Delivery ────────────────────────────────────────────────────────────
   Three links, because this repo has three CSS entry paths and the auth shell
   uses none of them:
     • `entry-points/admin-site.css` — served unbundled, no rebuild step.
     • `public-site.entry.css` → `public-site.bundle.css` (`npm run
       build:public-css`; also listed in `scripts/css-bundles.mjs` so the
       freshness guard hashes this file).
     • `Views/Shared/_AuthLayout.cshtml` links it directly — that layout links
       neither entry point, and `Views/Auth/Register.cshtml` is a call site.

   ── The width seam ──────────────────────────────────────────────────────
   `--tn-meter-value` is an unhinted custom property holding a bare number
   0-100; the fill turns it into a width with `calc(… * 1%)`. That is the
   established idiom in this codebase for a data-driven value (`--stagger`,
   `--legal-progress`, `--tn-console-h`), and it is what lets a live module
   write ONE property instead of two style declarations:

       meter.style.setProperty('--tn-meter-value', pct);   // was .style.width

   Two modules do exactly that on every tick — `admin/agentic-run-details.js`
   over its SSE stream and `auth-password-strength.js` on every keystroke —
   and both used to write `style.background` alongside it from a JS-side tone
   table. Tone is a class now (`is-success` … see below), so neither module
   can put a colour the themes do not know about on screen.

   ── The tone seam ───────────────────────────────────────────────────────
   Tone sets `--tn-meter-color` on the ROOT, and the fill reads it. Root, not
   fill, so a caller holding one element reference can change both the value
   and the tone; and a custom property rather than a `background` declaration
   so `--labelled` can key its text colour off the same switch.
   ========================================================================== */

.tn-meter {
    --tn-meter-color: var(--tn-accent-primary);
    --tn-meter-track: var(--tn-surface-inset);
    --tn-meter-height: 8px;

    display: block;
    width: 100%;
    height: var(--tn-meter-height);
    overflow: hidden;
    border-radius: var(--tn-radius-pill);
    background: var(--tn-meter-track);
}

/* `calc(var(…) * 1%)` and not `width: var(--tn-meter-value)`: keeping the
   property a bare number means a JS caller passes `62`, not `'62%'`, so a
   missing unit cannot silently zero the bar. The `0` fallback is what an
   un-set meter renders as — empty, never full. */
.tn-meter__fill {
    display: block;
    width: calc(var(--tn-meter-value, 0) * 1%);
    max-width: 100%;
    height: 100%;
    border-radius: inherit;
    background: var(--tn-meter-color);
    transition: width 300ms cubic-bezier(0.4, 0, 0.2, 1);
}

/* ── Tones ─────────────────────────────────────────────────────────────────
   Five, because that is what the eight forks between them expressed:
   accent (default), success, warning, error, info. `exec-mon`'s emerald and
   blue literals map onto `success` and `info`; `auth-password-strength`'s
   four-step Weak/Fair/Good/Strong table maps onto error/warning/info/success.

   `is-*` and not `--*`: three of the four toggles are made from JS, where
   `classList.toggle('is-tight')` reads as state and a BEM modifier reads as a
   different component. The retired `.is-tight` / `.is-exhausted` pair is the
   precedent. */
.tn-meter.is-accent {
    --tn-meter-color: var(--tn-accent-primary);
}

.tn-meter.is-success {
    --tn-meter-color: var(--tn-success);
}

.tn-meter.is-warning {
    --tn-meter-color: var(--tn-warning);
}

.tn-meter.is-error {
    --tn-meter-color: var(--tn-error);
}

.tn-meter.is-info {
    --tn-meter-color: var(--tn-info);
}

/* ── Sizes ─────────────────────────────────────────────────────────────────
   Only the three the forks actually used. 4px was the majority (four of the
   eight), but 8px is the majority of *call sites* once the ten hand-written
   bars are counted, so 8px is the default and 4px is the modifier. */
.tn-meter--sm {
    --tn-meter-height: 4px;
}

.tn-meter--lg {
    --tn-meter-height: 24px;
}

/* Sits on a text line inside a table cell next to the numeric "sent / limit"
   pair, so it must not eat the whole column. Was `email-senders-meter`'s
   `max-width: 9rem` + `margin-top: 3px`. */
.tn-meter--inline {
    display: inline-block;
    width: 9rem;
    max-width: 100%;
    margin-top: 3px;
    vertical-align: middle;
}

/* The confidence bar under a recommendation: 4rem, which is the 64px
   `exec-mon-confidence-bar` shipped. */
.tn-meter--mini {
    width: 4rem;
    margin-top: var(--tn-space-1);
}

/* ── Labelled ──────────────────────────────────────────────────────────────
   One call site today (`SocialDistribution/Analytics`'s indexation rate), and
   the reason `<tn-meter>` is a tag helper rather than a partial: the label is
   caller-authored markup living INSIDE the fill, right-aligned against its
   leading edge, which a Razor partial cannot take as a slot.

   `--tn-text-inverse` rather than `--tn-color-paper`: the fill is a theme
   colour, so the text on it has to flip with the theme too — a hard-coded
   paper white went unreadable on the light-teal fill of the soft themes. */
.tn-meter--labelled {
    --tn-meter-height: 24px;
}

.tn-meter--labelled .tn-meter__fill {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding-right: var(--tn-space-2);
    overflow: hidden;
    color: var(--tn-text-inverse);
    font-size: var(--tn-font-size-xs);
    font-weight: 600;
    white-space: nowrap;
}

/* Author-origin `display: block` beats the UA sheet's `[hidden]`, the same
   trap `tn-empty` documents. No live call site toggles a meter this way yet;
   the rule is here so the first one that does gets the behaviour it expects
   rather than a bar that stays on screen. */
.tn-meter[hidden] {
    display: none;
}

@media (prefers-reduced-motion: reduce) {
    .tn-meter__fill {
        transition: none;
    }
}
