/* ---------------------------------------------------------------------------
 * Self-hosted variable fonts — Inter (UI text) and JetBrains Mono (numbers/
 * data: KPI values, masked keys, timestamps). Previously the stylesheet
 * declared 'Inter' without ever shipping it, so every browser silently fell
 * back to its own default OS font. These are real font files vendored into
 * app/static/fonts (same self-host-everything approach already used for
 * Chart.js — SIL OFL / Apache-2.0, both freely redistributable).
 * ------------------------------------------------------------------------ */
@font-face {
  font-family: 'Inter';
  src: url('/static/fonts/inter-var.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url('/static/fonts/jetbrains-mono-var.woff2') format('woff2');
  font-weight: 100 800;
  font-style: normal;
  font-display: swap;
}

/* ---------------------------------------------------------------------------
 * Color tokens — deep navy-blue theme. Same variable names used throughout
 * every template (nothing downstream needs to change), only the values are
 * refined: neutrals now carry a deliberate blue hue instead of flat grey,
 * and the accent deepened to a richer indigo-blue to stay legible against
 * the darker ground. Semantic colors (green/red/yellow) stay strictly
 * reserved for real success/warning/failure states, never decorative.
 * ------------------------------------------------------------------------ */
:root {
  --bg: #060911;
  --bg-elevated: #0a0f1e;
  --bg-card: #0e1526;
  --border: #1f2a48;
  --border-soft: #141c33;
  --text: #e8ecf7;
  --text-muted: #8791ab;
  --text-faint: #505a76;
  --accent: #5f7fff;
  --accent-soft: rgba(95, 127, 255, 0.16);
  --green: #32c99a;
  --red: #f0546a;
  --yellow: #f0b64a;
  --purple: #8f9bfa;
  --orange: #f2954a;
}

body { background: var(--bg); color: var(--text); font-family: 'Inter', -apple-system, 'Segoe UI Variable', 'Segoe UI', system-ui, sans-serif; }

/* No global reset previously existed, so every <a> — including ones styled
   as buttons (.btn-primary/.btn-secondary) — fell back to the browser's
   default underline. This is the one line that fixes it everywhere at
   once. .hover\:underline (below) still adds it back intentionally on
   hover for plain text links, since that rule's specificity/order wins. */
a { text-decoration: none; }

.card { background: var(--bg-card); border: 1px solid var(--border); border-radius: 14px; }
.card-elevated { background: var(--bg-elevated); border: 1px solid var(--border); border-radius: 14px; }

.sidebar-link { color: var(--text-muted); border-radius: 10px; transition: all .15s ease; }
.sidebar-link:hover { background: var(--border-soft); color: var(--text); }
.sidebar-link.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }

.badge { border-radius: 999px; padding: 2px 10px; font-size: 12px; font-weight: 600; }
.badge-healthy { background: rgba(50,201,154,.15); color: var(--green); }
.badge-warning { background: rgba(240,182,74,.15); color: var(--yellow); }
.badge-critical { background: rgba(240,84,106,.15); color: var(--red); }
.badge-neutral { background: rgba(139,147,167,.15); color: var(--text-muted); }
.badge-info { background: rgba(95,127,255,.15); color: var(--accent); }

.btn-primary { background: var(--accent); color: #060911; border-radius: 10px; font-weight: 600; }
.btn-primary:hover { filter: brightness(1.08); }
.btn-secondary { background: var(--bg-elevated); color: var(--text); border: 1px solid var(--border); border-radius: 10px; }
.btn-secondary:hover { background: var(--border-soft); }
.btn-danger { background: rgba(240,84,106,.12); color: var(--red); border-radius: 10px; }
.btn-send { background: rgba(50,201,154,.12); color: var(--green); border: 1px solid rgba(50,201,154,.4); border-radius: 10px; font-weight: 600; }
.btn-send:hover { background: rgba(50,201,154,.2); }

/* Day-of-week pill picker (Custom Schedule) — a real checkbox visually
 * hidden, its sibling label styled as the pill; the :checked selector
 * drives the selected look, so it needs zero JS to toggle. */
.day-pill-input { position: absolute; opacity: 0; width: 0; height: 0; }
.day-pill-label {
  width: 2.3rem; height: 2.3rem; border-radius: 9px; display: flex; align-items: center; justify-content: center;
  font-size: .72rem; font-weight: 600; background: var(--bg-elevated); border: 1px solid var(--border);
  color: var(--text-faint); cursor: pointer; user-select: none;
}
.day-pill-label:has(.day-pill-input:checked) { background: var(--accent); border-color: var(--accent); color: #060911; }
.day-pill-label:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }

input, select, textarea {
  background: var(--bg-elevated); border: 1px solid var(--border); color: var(--text); border-radius: 10px;
}
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--accent); }

table.data-table th { color: var(--text-faint); font-size: 12px; text-transform: uppercase; letter-spacing: .03em; text-align: left; padding: 10px 14px; border-bottom: 1px solid var(--border); }
table.data-table td { padding: 12px 14px; border-bottom: 1px solid var(--border-soft); font-size: 14px; }
table.data-table tr:hover td { background: var(--border-soft); }

.masked-key { font-family: 'JetBrains Mono', ui-monospace, monospace; letter-spacing: .02em; }
.mono { font-family: 'JetBrains Mono', ui-monospace, monospace; font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------------------
 * Utility layer (hand-authored subset of Tailwind CSS utility classes).
 *
 * This app previously loaded Tailwind's "Play CDN" JIT compiler at runtime
 * (<script src="https://cdnjs.../tailwind.min.js">) to generate these classes
 * in-browser. Tailwind's own docs mark that CDN build "not intended for
 * production" — it silently produces an unstyled page (exactly what these
 * classes look like without CSS) whenever a client can't reach cdnjs
 * (corporate proxy, ad blocker, offline, strict CSP). This block replaces
 * that runtime dependency with the exact set of utility classes the
 * templates actually use, self-hosted here — no external request, no JS
 * compile step, works identically every time.
 * ------------------------------------------------------------------------ */

*, ::before, ::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

.block { display: block; }
.inline { display: inline; }
.inline-block { display: inline-block; }
.flex { display: flex; }
.inline-flex { display: inline-flex; }
.grid { display: grid; }
.hidden { display: none; }

.flex-1 { flex: 1 1 0%; }
.flex-col { flex-direction: column; }
.flex-wrap { flex-wrap: wrap; }
.shrink-0 { flex-shrink: 0; }
.items-center { align-items: center; }
.items-start { align-items: flex-start; }
.items-end { align-items: flex-end; }
.justify-between { justify-content: space-between; }
.justify-center { justify-content: center; }

.grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); }
.grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.col-span-3 { grid-column: span 3 / span 3; }

.gap-2 { gap: .5rem; }
.gap-3 { gap: .75rem; }
.gap-4 { gap: 1rem; }
.gap-6 { gap: 1.5rem; }
.space-y-1 > * + * { margin-top: .25rem; }
.space-y-2 > * + * { margin-top: .5rem; }
.space-y-3 > * + * { margin-top: .75rem; }
.space-y-4 > * + * { margin-top: 1rem; }

.m-3 { margin: .75rem; }
.mb-1 { margin-bottom: .25rem; }
.mb-2 { margin-bottom: .5rem; }
.mb-3 { margin-bottom: .75rem; }
.mb-4 { margin-bottom: 1rem; }
.mb-6 { margin-bottom: 1.5rem; }
.mt-1 { margin-top: .25rem; }
.mt-2 { margin-top: .5rem; }
.mt-3 { margin-top: .75rem; }
.mt-4 { margin-top: 1rem; }
.mt-5 { margin-top: 1.25rem; }
.mt-6 { margin-top: 1.5rem; }

.p-3 { padding: .75rem; }
.p-4 { padding: 1rem; }
.p-5 { padding: 1.25rem; }
.p-6 { padding: 1.5rem; }
.p-8 { padding: 2rem; }
.px-2 { padding-left: .5rem; padding-right: .5rem; }
.px-3 { padding-left: .75rem; padding-right: .75rem; }
.px-4 { padding-left: 1rem; padding-right: 1rem; }
.px-5 { padding-left: 1.25rem; padding-right: 1.25rem; }
.px-6 { padding-left: 1.5rem; padding-right: 1.5rem; }
.py-1 { padding-top: .25rem; padding-bottom: .25rem; }
.py-2 { padding-top: .5rem; padding-bottom: .5rem; }
.py-3 { padding-top: .75rem; padding-bottom: .75rem; }
.py-4 { padding-top: 1rem; padding-bottom: 1rem; }
.py-5 { padding-top: 1.25rem; padding-bottom: 1.25rem; }
.py-6 { padding-top: 1.5rem; padding-bottom: 1.5rem; }
.py-10 { padding-top: 2.5rem; padding-bottom: 2.5rem; }

.h-2 { height: .5rem; }
.h-2\.5 { height: .625rem; }
.w-2\.5 { width: .625rem; }
.w-60 { width: 15rem; }
.w-full { width: 100%; }
.min-w-0 { min-width: 0px; }
.min-h-screen { min-height: 100vh; }
.max-w-sm { max-width: 24rem; }
.max-w-md { max-width: 28rem; }
.max-w-lg { max-width: 32rem; }
.max-w-xl { max-width: 36rem; }

.border-b { border-bottom: 1px solid var(--border); }
.border-r { border-right: 1px solid var(--border); }
.rounded-full { border-radius: 9999px; }
.rounded-lg { border-radius: .5rem; }
.overflow-hidden { overflow: hidden; }
.overflow-x-auto { overflow-x: auto; }

.text-xs { font-size: .75rem; line-height: 1rem; }
.text-sm { font-size: .875rem; line-height: 1.25rem; }
.text-lg { font-size: 1.125rem; line-height: 1.75rem; }
.text-xl { font-size: 1.25rem; line-height: 1.75rem; }
.text-2xl { font-size: 1.5rem; line-height: 2rem; }
.text-3xl { font-size: 1.875rem; line-height: 2.25rem; }
.text-center { text-align: center; }
.font-normal { font-weight: 400; }
.font-medium { font-weight: 500; }
.font-semibold { font-weight: 600; }
.font-bold { font-weight: 700; }
.tracking-tight { letter-spacing: -.025em; }

.transition { transition-property: color, background-color, border-color, opacity, filter, box-shadow, transform; transition-duration: .15s; transition-timing-function: ease; }
.hover\:opacity-90:hover { opacity: .9; }
.hover\:underline:hover { text-decoration: underline; }

@media (min-width: 768px) {
  .md\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .md\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .md\:grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (min-width: 1024px) {
  .lg\:col-span-2 { grid-column: span 2 / span 2; }
  .lg\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .lg\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .lg\:grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .lg\:grid-cols-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  /* Settings page: fixed-width sticky quick-nav + flexible content column. */
  .lg\:grid-cols-settings { grid-template-columns: 190px 1fr; }
  .lg\:flex { display: flex; }
}

/* ---------------------------------------------------------------------------
 * Enterprise Edition restyle additions (header, collapsible sidebar,
 * dashboard sparklines/KPI cards). Additive only — extends the tokens
 * above, no second design system.
 * ------------------------------------------------------------------------ */

.sidebar { width: var(--sidebar-width, 15rem); transition: width .15s ease; }
html.sidebar-collapsed .sidebar { --sidebar-width: 4.5rem; }
html.sidebar-collapsed .sidebar-label,
html.sidebar-collapsed .sidebar-group-label,
html.sidebar-collapsed .sidebar-footer-card { display: none; }
html.sidebar-collapsed .sidebar-link { justify-content: center; }

.sidebar-backdrop { display: none; }
.header-compact-show { display: none; }

/* Mobile: the sidebar has no room to sit beside the page content like it
 * does on desktop, so below 768px it becomes a fixed, full-height drawer —
 * hidden off-screen by default, slid into view with the header's hamburger
 * button. Deliberately ignores the desktop-only collapsed/expanded state
 * above (`--sidebar-width`) so a stale "collapsed" preference saved from a
 * previous desktop session never leaves a phone visitor stuck with an
 * icon-only, unreadable drawer. */
@media (max-width: 767px) {
  .sidebar {
    position: fixed; top: 0; left: 0; height: 100vh; z-index: 60;
    width: 15rem !important;
    transform: translateX(-100%);
    box-shadow: 0 0 40px rgba(0,0,0,.45);
  }
  html.sidebar-mobile-open .sidebar { transform: translateX(0); }

  html.sidebar-mobile-open .sidebar-backdrop {
    display: block; position: fixed; inset: 0; background: rgba(3,5,11,.6); z-index: 55;
  }

  /* Declutter the header so it fits a phone screen without wrapping or
   * overflowing — search and the project switcher move out of the way
   * (still reachable once the drawer's open, nothing is removed from the
   * app, just hidden from this cramped row); the signed-in user's name/role
   * text collapses to just the avatar, and Sign out becomes an icon. */
  .header-compact-hide { display: none !important; }
  .header-compact-show { display: inline-flex; }
  header { padding-left: 1rem !important; padding-right: 1rem !important; }
  main { padding: 1rem !important; }
}

.sidebar-group-label {
  font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-faint); padding: 0 .75rem; margin-top: 1.25rem; margin-bottom: .375rem;
}
.sidebar-group-label:first-of-type { margin-top: .5rem; }

.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.25rem; height: 2.25rem; border-radius: 10px; color: var(--text-muted);
  background: transparent; border: 1px solid transparent; cursor: pointer;
}
.icon-btn:hover { background: var(--border-soft); color: var(--text); }

.avatar-circle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.25rem; height: 2.25rem; border-radius: 9999px;
  background: var(--accent-soft); color: var(--accent); font-weight: 700; font-size: 13px;
}

/* Native <dialog> popup (e.g. Create User) — real modal in front of the
   page, dimmed backdrop, no page navigation. The browser centers it and
   handles Escape-to-close natively; only the visual styling is ours. */
dialog.modal-dialog {
  background: var(--bg-card); color: var(--text); border: 1px solid var(--border);
  border-radius: 14px; padding: 1.5rem; width: 380px; max-width: 90vw;
}
dialog.modal-dialog::backdrop { background: rgba(3, 5, 11, 0.72); }

.notif-dot {
  position: absolute; top: -2px; right: -2px; min-width: 16px; height: 16px; padding: 0 3px;
  border-radius: 9999px; background: var(--red); color: #fff; font-size: 10px; font-weight: 700;
  display: flex; align-items: center; justify-content: center; line-height: 1;
}

.sparkline { display: block; width: 100%; height: 32px; }

#search-results {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 30;
  max-height: 360px; overflow-y: auto;
}
#search-results a { display: block; }
#search-results a:hover { background: var(--border-soft); }

/* ---------------------------------------------------------------------------
 * Login page — centered card over a real photo background. Scoped to
 * .login-* classes only — no change to any other page's styling.
 * ------------------------------------------------------------------------ */

.login-page {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  position: relative; padding: 2rem;
  background-image: url('/static/images/login-bg.jpg');
  background-size: cover; background-position: center;
}
.login-page::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, rgba(4,6,9,.62), rgba(4,6,9,.8));
}

.login-logo-badge {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.75rem; height: 2.75rem; border-radius: 12px; background: var(--accent);
  color: #060911; font-weight: 800; font-size: 13px; letter-spacing: .02em;
}

.login-card {
  position: relative; z-index: 1; width: 100%; max-width: 24rem;
  background: rgba(14,21,38,.86); backdrop-filter: blur(10px);
  border: 1px solid rgba(255,255,255,.08); box-shadow: 0 25px 60px -15px rgba(0,0,0,.6);
}
.login-lock-badge {
  display: flex; align-items: center; justify-content: center;
  width: 3.5rem; height: 3.5rem; border-radius: 9999px; background: var(--accent);
  color: #fff; font-size: 22px;
}

.field-icon-input { position: relative; }
.field-icon-input .field-icon {
  position: absolute; left: .75rem; top: 50%; transform: translateY(-50%);
  color: var(--text-faint); font-size: 14px; pointer-events: none;
}
.field-icon-input input { padding-left: 2.25rem; }
.password-field .password-toggle {
  position: absolute; right: .6rem; top: 50%; transform: translateY(-50%);
  background: none; border: none; color: var(--text-faint); cursor: pointer;
  font-size: 14px; padding: .25rem; line-height: 1;
}
.password-field .password-toggle:hover { color: var(--text); }

/* Plain text-styled <button> — resets default browser button chrome
   (padding/border/background) so a <button> used purely for its color
   (e.g. table row actions like Disable/Delete) renders as a plain link,
   not a bezeled box. */
.btn-text { background: none; border: none; padding: 0; cursor: pointer; font: inherit; }
.btn-text:hover { text-decoration: underline; }

.oauth-btn {
  display: flex; align-items: center; justify-content: center; gap: .4rem;
  padding: .55rem .5rem; border-radius: 10px; border: 1px solid var(--border);
  background: var(--bg-elevated); color: var(--text); font-size: 13px; font-weight: 600;
  text-decoration: none;
}
.oauth-btn:hover { background: var(--border-soft); }

.login-divider { display: flex; align-items: center; gap: .75rem; color: var(--text-faint); font-size: 12px; }
.login-divider::before, .login-divider::after { content: ""; flex: 1; height: 1px; background: var(--border); }

/* ---------------------------------------------------------------------------
 * Icon system — replaces the emoji used throughout the app (sidebar, header,
 * KPI cards) with a self-hosted SVG sprite (see _icon_sprite.html), one
 * consistent 1.75px stroke weight instead of inconsistent emoji glyphs.
 * ------------------------------------------------------------------------ */
svg.icon { width: 1em; height: 1em; flex: none; stroke: currentColor; fill: none; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
.icon-chip {
  width: 1.85rem; height: 1.85rem; border-radius: 7px; display: flex; align-items: center; justify-content: center; flex: none;
}
.icon-chip svg { width: 15px; height: 15px; }
.icon-chip.blue { background: var(--accent-soft); color: var(--accent); }
.icon-chip.green { background: rgba(50, 201, 154, .14); color: var(--green); }
.icon-chip.red { background: rgba(240, 84, 106, .14); color: var(--red); }
.icon-chip.amber { background: rgba(240, 182, 74, .14); color: var(--yellow); }

/* ---------------------------------------------------------------------------
 * KPI cards — refined hierarchy: label + icon chip on top, big tabular
 * number, trend/context line below. Same .card shell, additive modifier.
 * ------------------------------------------------------------------------ */
.kpi-card { display: flex; flex-direction: column; gap: .65rem; }
.kpi-card .kpi-top { display: flex; align-items: center; justify-content: space-between; }
.kpi-card .kpi-label { font-size: 12px; color: var(--text-muted); font-weight: 550; }
.kpi-card .kpi-value { font-size: 26px; font-weight: 650; letter-spacing: -.02em; }

/* Whole-card link (an <a> wrapping the entire .card, not just the icon) —
   the full box is the click target, not just the small symbol. Text/color
   reset since a bare <a> would otherwise underline and re-tint everything
   inside it; the icon-chip glows and the card lifts on hover/focus so the
   whole box reads as a real, clickable button. */
a.card-link { display: flex; color: inherit; text-decoration: none; cursor: pointer;
  transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease; }
a.card-link:hover, a.card-link:focus-visible {
  border-color: var(--accent); transform: translateY(-2px);
  box-shadow: 0 10px 24px -14px rgba(95,127,255,.45);
}
a.card-link:hover .icon-chip, a.card-link:focus-visible .icon-chip,
a.balance-banner:hover .balance-icon, a.balance-banner:focus-visible .balance-icon {
  transform: scale(1.08);
}
a.card-link:hover .icon-chip.blue, a.card-link:focus-visible .icon-chip.blue,
a.balance-banner:hover .balance-icon, a.balance-banner:focus-visible .balance-icon {
  box-shadow: 0 0 0 5px rgba(95,127,255,.16), 0 0 18px 3px rgba(95,127,255,.65);
}
a.card-link:hover .icon-chip.amber, a.card-link:focus-visible .icon-chip.amber {
  box-shadow: 0 0 0 5px rgba(240,182,74,.16), 0 0 18px 3px rgba(240,182,74,.65);
}
.icon-chip { transition: transform .15s ease, box-shadow .15s ease; }

/* Balance banner — the single most important real number, surfaced first. */
.balance-banner {
  display: flex; align-items: center; justify-content: space-between; gap: 1.5rem; flex-wrap: wrap;
  background: linear-gradient(115deg, var(--bg-card) 0%, var(--bg-card) 55%, rgba(95,127,255,.1) 100%);
  border: 1px solid var(--border-soft); border-radius: 14px; padding: 1.25rem 1.5rem;
  position: relative; overflow: hidden;
}
a.balance-banner { color: inherit; text-decoration: none; cursor: pointer;
  transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease; }
a.balance-banner:hover, a.balance-banner:focus-visible {
  border-color: var(--accent); transform: translateY(-2px);
  box-shadow: 0 10px 24px -14px rgba(95,127,255,.45);
}
.balance-banner::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(340px 160px at 100% 0%, rgba(95,127,255,.18), transparent 70%);
}
.balance-main { display: flex; align-items: center; gap: 1rem; position: relative; }
.balance-icon {
  width: 2.9rem; height: 2.9rem; border-radius: 11px; background: var(--accent-soft); color: var(--accent);
  display: flex; align-items: center; justify-content: center; flex: none;
  transition: transform .15s ease, box-shadow .15s ease;
}
.balance-icon svg { width: 20px; height: 20px; }
.balance-label { font-size: 12px; color: var(--text-muted); font-weight: 600; display: flex; align-items: center; gap: .4rem; }
.balance-value { font-size: 32px; font-weight: 700; letter-spacing: -.02em; line-height: 1.1; margin-top: .15rem; }
.balance-source { font-size: 11px; color: var(--text-faint); margin-top: .25rem; }
.balance-breakdown { display: flex; gap: 1.75rem; position: relative; flex-wrap: wrap; }
.bd-cell { min-width: 6.5rem; }
.bd-label { font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-faint); font-weight: 650; }
.bd-value { font-size: 16px; font-weight: 650; margin-top: .2rem; }
.bd-bar-wrap { margin-top: .35rem; }
.bd-bar-track { height: 6px; width: 6.5rem; border-radius: 99px; background: var(--border-soft); overflow: hidden; }
.bd-bar-fill { height: 100%; border-radius: 99px; background: var(--accent); }
.live-dot { width: 6px; height: 6px; border-radius: 99px; background: var(--green); box-shadow: 0 0 0 3px rgba(50,201,154,.16); display: inline-block; }

/* ---------------------------------------------------------------------------
 * Provider table (API Keys overview — "Option A" layout). Reuses .card,
 * .badge-*, .data-table conventions already established elsewhere.
 * ------------------------------------------------------------------------ */
.prov-id { display: flex; align-items: center; gap: .65rem; }
.prov-icon { width: 2rem; height: 2rem; border-radius: 8px; display: flex; align-items: center; justify-content: center; flex: none; }
.prov-icon svg { width: 15px; height: 15px; }
.prov-icon.blue { background: var(--accent-soft); color: var(--accent); }
.prov-icon.green { background: rgba(50, 201, 154, .14); color: var(--green); }
.prov-icon.purple { background: rgba(167, 139, 250, .16); color: var(--purple); }
.prov-icon.amber { background: rgba(240, 182, 74, .14); color: var(--yellow); }
.prov-name { font-weight: 600; font-size: 13px; }
.util-track { width: 4.5rem; height: 5px; border-radius: 99px; background: var(--border-soft); overflow: hidden; display: inline-block; vertical-align: middle; margin-right: .4rem; }
.util-fill { height: 100%; background: var(--accent); border-radius: 99px; }
table.data-table tr:hover td .prov-icon { filter: brightness(1.1); }

/* ---------------------------------------------------------------------------
 * Key health (Usage Overview) — color-coded by real % balance remaining,
 * sorted worst-first server-side. Colors: green >=50%, amber 20-49%,
 * red <20%, gray = no balance data available for this key.
 * ------------------------------------------------------------------------ */
.health-row { position: relative; overflow: hidden; }
.health-row::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; }
.health-row.tier-green::before { background: var(--green); }
.health-row.tier-amber::before { background: var(--yellow); }
.health-row.tier-red::before { background: var(--red); }
.health-row.tier-gray::before { background: var(--border); }
.gauge-track { width: 5rem; height: 8px; border-radius: 99px; background: var(--border-soft); overflow: hidden; display: inline-block; vertical-align: middle; }
.gauge-fill { height: 100%; border-radius: 99px; }
.gauge-fill.tier-green { background: var(--green); }
.gauge-fill.tier-amber { background: var(--yellow); }
.gauge-fill.tier-red { background: var(--red); }
.gauge-fill.tier-gray { background: var(--border); }
.gauge-pct.tier-green { color: var(--green); }
.gauge-pct.tier-amber { color: var(--yellow); }
.gauge-pct.tier-red { color: var(--red); }
.gauge-pct.tier-gray { color: var(--text-faint); }
