/* ============================================================================
   29-admin-analytics.css — the revolutionized admin Overview dashboard,
   Health/diagnostics view, enriched Users table and per-user detail drawer.
   Everything is theme-aware through the shared --adm-* tokens (dark + light).
   Charts are inline SVG / CSS bars, so there are no external asset requests.
   ============================================================================ */

/* ---------- loading + generic empties ---------- */
.adm-ov-loading{
  padding:60px 20px; text-align:center; color:var(--adm-muted);
  font-size:16px; font-weight:600; letter-spacing:.2px;
}
.adm-empty-mini{
  padding:18px; text-align:center; color:var(--adm-muted);
  font-size:14.5px; border:1px dashed var(--adm-border); border-radius:12px;
  background:rgba(255,255,255,.015);
}

/* ---------- pending-payments alert ---------- */
.adm-ov-alert{
  display:flex; align-items:center; gap:12px; text-decoration:none;
  margin-bottom:18px; padding:13px 16px; border-radius:14px;
  color:var(--adm-text); font-size:16px; font-weight:600;
  background:linear-gradient(100deg, rgba(251,191,36,.16), rgba(255,138,91,.10));
  border:1px solid rgba(251,191,36,.35);
  transition:transform .15s ease, box-shadow .15s ease;
}
.adm-ov-alert:hover{ transform:translateY(-1px); box-shadow:0 8px 24px -12px rgba(251,191,36,.5); }
.adm-ov-alert-ico{ font-size:20px; }
.adm-ov-alert b{ color:var(--adm-accent-2); }
.adm-ov-alert-go{ margin-left:auto; color:var(--adm-accent-2); font-weight:700; font-size:15px; }

/* ---------- hero KPI cards ---------- */
.adm-hero-grid{
  display:grid; grid-template-columns:repeat(4, 1fr); gap:14px; margin-bottom:16px;
}
.adm-hero-card{
  position:relative; overflow:hidden; border-radius:16px;
  background:
    radial-gradient(120% 80% at 100% 0%, rgba(255,138,91,.10), transparent 55%),
    var(--adm-card);
  border:1px solid var(--adm-border);
  padding:16px 16px 0; min-height:150px; display:flex; flex-direction:column;
  animation:admFade .28s ease both;
}
.adm-hero-card::before{
  content:""; position:absolute; inset:0 0 auto 0; height:3px;
  background:linear-gradient(90deg, var(--adm-accent), var(--adm-accent-2));
  opacity:.85;
}
.adm-hero-top{ display:flex; align-items:center; gap:8px; }
.adm-hero-ico{
  width:30px; height:30px; display:grid; place-items:center; font-size:16px;
  border-radius:8px; background:rgba(255,255,255,.06); border:1px solid var(--adm-border);
}
.adm-hero-label{ font-size:14px; font-weight:700; color:var(--adm-muted); text-transform:uppercase; letter-spacing:.6px; }
.adm-hero-num{
  font-size:32px; font-weight:800; color:var(--adm-text); margin:10px 0 6px;
  line-height:1; font-variant-numeric:tabular-nums; letter-spacing:-.5px;
}
.adm-hero-num small{ font-size:15px; font-weight:700; color:var(--adm-muted); letter-spacing:0; }
.adm-hero-foot{ display:flex; flex-wrap:wrap; gap:6px; margin-bottom:10px; }
.adm-hero-spark{ margin:auto -16px 0; line-height:0; }
.adm-hero-stack{
  display:flex; height:8px; border-radius:5px; overflow:hidden; gap:2px;
  margin:2px 0 12px; background:var(--adm-border);
}
.adm-hero-stack span{ display:block; border-radius:3px; }

/* status chips */
.adm-chip{
  display:inline-flex; align-items:center; gap:4px; font-size:13.5px; font-weight:700;
  padding:3px 8px; border-radius:999px; color:var(--adm-muted);
  background:rgba(255,255,255,.05); border:1px solid var(--adm-border); white-space:nowrap;
}
.adm-chip.up{   color:var(--adm-success); background:rgba(52,211,153,.12); border-color:rgba(52,211,153,.28); }
.adm-chip.down{ color:var(--adm-danger);  background:rgba(248,113,134,.12); border-color:rgba(248,113,134,.28); }
.adm-chip.flat{ color:var(--adm-muted); }

/* ---------- panel grid ---------- */
/* stretch, not start: two panels sharing a row are one card, and letting the
   shorter one stop early left a ragged step down the middle of the dashboard. */
.adm-ov-grid{
  display:grid; grid-template-columns:1fr 1fr; gap:14px; margin-bottom:14px;
  align-items:stretch;
}
.adm-ov-panel{
  border-radius:16px; background:var(--adm-card); border:1px solid var(--adm-border);
  padding:16px 18px; animation:admFade .28s ease both;
  display:flex; flex-direction:column; min-width:0;
}
.adm-ov-panel-body{ flex:1; min-width:0; }
.adm-ov-panel-head{ margin-bottom:14px; }
.adm-ov-panel-title{ font-size:16.5px; font-weight:800; color:var(--adm-text); letter-spacing:-.2px; }
.adm-ov-panel-sub{ font-size:14px; color:var(--adm-muted); margin-top:2px; }
.adm-ov-panel-foot{ margin-top:14px; padding-top:12px; border-top:1px solid var(--adm-border); }

/* ---------- charts ---------- */
.adm-chart-box{
  height:150px; display:flex; align-items:flex-end;
  border-radius:10px; padding:6px 4px 0;
  /* Four 36px bands under the 6px top pad exactly fills the 150px box, so the
     last gridline lands on the baseline. At 37px the grid did not divide the
     height and the bottom band was sliced, which read as a rendering fault. */
  background:
    linear-gradient(var(--adm-border) 1px, transparent 1px) 0 6px/100% 36px;
  background-color:rgba(255,255,255,.012);
}
.adm-chart-box.sm{ height:114px; }
.adm-chart-box svg{ display:block; }
.adm-spark{ display:block; }
.adm-spark-empty{
  width:100%; border-radius:8px; opacity:.5;
  background:repeating-linear-gradient(90deg, var(--adm-border) 0 1px, transparent 1px 7px);
}
.adm-chart-axis{
  display:flex; justify-content:space-between; margin-top:6px;
  font-size:12.5px; color:var(--adm-muted); font-variant-numeric:tabular-nums;
}

/* Bar charts as boxes rather than SVG rects — see cssBars(). Radii and gaps land
   on whole pixels at any panel width, and each column can grow in. */
.adm-bars{ display:flex; align-items:flex-end; gap:3px; width:100%; height:100%; }
.adm-bars.dense{ gap:1px; }
.adm-bar-col{ flex:1 1 0; min-width:0; display:flex; align-items:flex-end; height:100%; }
.adm-bar{
  display:block; width:100%; height:var(--h, 0);
  border-radius:3px 3px 1px 1px; background:var(--bar, var(--adm-accent));
  animation:admGrowH .55s cubic-bezier(.22,1,.36,1) both;
  animation-delay:calc(var(--i, 0) * .012s);
}
/* An all-zero series used to render as a full-height slab of empty gridlines
   with a date axis beneath it, which reads as broken rather than as "nothing
   happened yet". */
.adm-chart-empty{
  height:150px; display:grid; place-items:center; text-align:center;
  padding:0 18px; border-radius:10px; border:1px dashed var(--adm-border);
  background:rgba(255,255,255,.015); color:var(--adm-muted); font-size:14.5px;
}
.adm-chart-empty.sm{ height:114px; }

/* ---------- small metric row (panel footer) ---------- */
/* A grid, not a wrapping flex row: with flex the cells were as wide as their own
   text, so no two figures in a panel lined up and the footers of two panels side
   by side agreed on nothing. */
.adm-metric-row{ display:grid; grid-template-columns:repeat(auto-fit, minmax(84px, 1fr)); gap:14px 16px; }
.adm-metric{ display:flex; flex-direction:column; gap:3px; min-width:0; }
.adm-metric-label{
  font-size:13px; color:var(--adm-muted); text-transform:uppercase; letter-spacing:.5px;
  font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.adm-metric-num{
  font-size:18px; font-weight:800; color:var(--adm-text);
  font-variant-numeric:tabular-nums; letter-spacing:-.2px;
}

/* ---------- share table (CEFR levels, revenue by plan, adjustments) ---------- */
.adm-sr{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip-path:inset(50%); white-space:nowrap; border:0;
}
.adm-tbl-slot{ margin-top:14px; }
.adm-tbl-slot.grow{ flex:1 1 190px; min-width:180px; margin-top:0; }
.adm-tbl-wrap{ overflow-x:auto; }
.adm-tbl{ width:100%; border-collapse:collapse; font-size:14.5px; }
.adm-tbl th, .adm-tbl td{ padding:7px 12px 7px 0; text-align:left; vertical-align:middle; }
.adm-tbl td:last-child, .adm-tbl th:last-child{ padding-right:0; }
.adm-tbl thead th{
  padding-top:0; padding-bottom:7px; font-size:12.5px; font-weight:700;
  text-transform:uppercase; letter-spacing:.5px; color:var(--adm-muted);
  border-bottom:1px solid var(--adm-border);
}
.adm-tbl tbody tr{ animation:admFade .3s ease both; animation-delay:calc(var(--i, 0) * .04s); }
.adm-tbl tbody tr + tr th, .adm-tbl tbody tr + tr td{ border-top:1px solid var(--adm-border); }
.adm-tbl tbody th{ font-weight:600; color:var(--adm-text); }
.adm-tbl-dot{ display:inline-block; width:9px; height:9px; border-radius:3px; margin-right:8px; vertical-align:middle; }
.adm-tbl-name{ vertical-align:middle; }
.adm-tbl .num{ text-align:right; white-space:nowrap; font-variant-numeric:tabular-nums; }
.adm-tbl .pct{ width:1%; color:var(--adm-muted); }
.adm-tbl .bar{ width:72px; }
/* Beside a donut the bar column is the ring said twice, and the ~84px it costs
   is exactly what makes "B1 · Intermediate" wrap onto a second line and stand
   one row taller than its neighbours. */
.adm-donut-row .adm-tbl .bar{ display:none; }
.adm-donut-row .adm-tbl .adm-tbl-name{ white-space:nowrap; }
.adm-tbl .bar i{
  display:block; height:6px; border-radius:3px; width:var(--w, 0);
  animation:admGrowW .6s cubic-bezier(.22,1,.36,1) both;
  animation-delay:calc(var(--i, 0) * .05s);
}
/* The total row is the point of the table: it lets a reader check that the parts
   add up instead of taking the headline on trust. */
.adm-tbl tfoot th, .adm-tbl tfoot td{
  padding-top:9px; border-top:1px solid var(--adm-border);
  font-weight:800; color:var(--adm-text);
}
.adm-tbl tfoot .pct{ color:var(--adm-muted); font-weight:700; }

/* ---------- donut + legend ---------- */
.adm-donut-row{ display:flex; align-items:center; gap:20px; flex-wrap:wrap; }
.adm-donut-wrap{ position:relative; flex:none; }
/* The old `transition:stroke-dasharray` here never once fired: every arc is born
   with its final dasharray already set, and a transition needs a value to change
   FROM. Sweeping each arc in from zero has to be a keyframe. */
.adm-donut-seg{
  stroke-dasharray:var(--dash) var(--gap);
  animation:admDonutDraw .75s cubic-bezier(.22,1,.36,1) both;
  animation-delay:calc(var(--i, 0) * .1s);
}
.adm-donut-center{
  position:absolute; inset:0; display:flex; flex-direction:column;
  align-items:center; justify-content:center; text-align:center; pointer-events:none;
}
.adm-donut-center b{ font-size:26px; font-weight:800; color:var(--adm-text); font-variant-numeric:tabular-nums; line-height:1; }
.adm-donut-center span{ font-size:13px; color:var(--adm-muted); margin-top:2px; }
.adm-donut-empty{ padding:30px 10px; color:var(--adm-muted); font-size:14.5px; text-align:center; width:100%; }
.adm-legend{ display:flex; flex-direction:column; gap:8px; flex:1; min-width:120px; }
.adm-legend-item{ display:flex; align-items:center; gap:8px; font-size:14.5px; color:var(--adm-muted); }
.adm-legend-dot{ width:10px; height:10px; border-radius:3px; flex:none; }
.adm-legend-label{ flex:1; color:var(--adm-text); font-weight:600; }
.adm-legend-item b{ color:var(--adm-text); font-variant-numeric:tabular-nums; }
.adm-legend-pct{ min-width:36px; text-align:right; color:var(--adm-muted); font-variant-numeric:tabular-nums; }

/* ---------- band histogram ---------- */
.adm-hist{ display:flex; align-items:flex-end; gap:6px; height:164px; padding-top:4px; }
.adm-hist-col{ flex:1; display:flex; flex-direction:column; align-items:center; gap:5px; height:100%; min-width:0; }
.adm-hist-n{
  font-size:11.5px; min-height:12px; font-weight:700;
  color:var(--adm-muted); font-variant-numeric:tabular-nums;
}
.adm-hist-bar-wrap{ flex:1; width:100%; display:flex; align-items:flex-end; }
.adm-hist-bar{
  width:100%; border-radius:5px 5px 2px 2px; height:var(--h, 0);
  background:linear-gradient(180deg, var(--adm-accent), var(--adm-accent-2));
  animation:admGrowH .6s cubic-bezier(.22,1,.36,1) both;
  animation-delay:calc(var(--i, 0) * .04s);
}
.adm-hist-x{ font-size:12.5px; color:var(--adm-muted); font-weight:600; font-variant-numeric:tabular-nums; }

/* ---------- funnel ---------- */
/* Now that panels sharing a row match heights, the three funnel rows have to
   spread through whatever height the taller neighbour sets, or they huddle at
   the top of a mostly empty card. */
.adm-funnel{ display:flex; flex-direction:column; justify-content:space-evenly; gap:16px; padding:6px 0; height:100%; min-height:150px; }
.adm-funnel-row{ display:grid; grid-template-columns:1fr 46px; grid-template-areas:"meta conv" "track conv"; gap:2px 10px; align-items:center; }
.adm-funnel-meta{ grid-area:meta; display:flex; justify-content:space-between; align-items:flex-start; gap:10px; font-size:15px; color:var(--adm-text); }
.adm-funnel-meta b{ font-variant-numeric:tabular-nums; text-align:right; }
.adm-funnel-meta b small{ display:block; font-size:12px; font-weight:600; color:var(--adm-muted); margin-top:1px; }
.adm-funnel-track{ grid-area:track; height:12px; border-radius:7px; background:rgba(255,255,255,.05); overflow:hidden; }
/* Same story as the donut arcs: the fill mounts at its final width, so the
   transition that used to live here could never run. */
.adm-funnel-fill{
  height:100%; border-radius:7px; width:var(--w, 0);
  animation:admGrowW .7s cubic-bezier(.22,1,.36,1) both;
  animation-delay:calc(var(--i, 0) * .1s);
}
.adm-funnel-conv{ grid-area:conv; font-size:14px; font-weight:700; color:var(--adm-muted); text-align:right; font-variant-numeric:tabular-nums; }

/* ---------- leaderboards ---------- */
.adm-lead-cols{ display:grid; grid-template-columns:1fr 1fr; gap:22px; }
.adm-lead-h{ font-size:14px; font-weight:700; color:var(--adm-muted); margin-bottom:10px; text-transform:uppercase; letter-spacing:.5px; }
.adm-lead{ display:flex; flex-direction:column; gap:9px; }
.adm-lead-row{ display:flex; align-items:center; gap:9px; font-size:14.5px; }
.adm-lead-rank{ width:18px; height:18px; flex:none; display:grid; place-items:center; font-size:12.5px; font-weight:800; color:var(--adm-muted); background:rgba(255,255,255,.05); border-radius:6px; }
.adm-lead-title{ flex:1; color:var(--adm-text); font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.adm-lead-band{ font-size:13px; font-weight:800; color:var(--adm-success); background:rgba(52,211,153,.12); padding:1px 6px; border-radius:6px; flex:none; }
.adm-lead-band.money{ color:var(--adm-accent-2); background:rgba(251,191,36,.12); }
.adm-lead-attempts{ font-size:13.5px; color:var(--adm-muted); font-weight:700; font-variant-numeric:tabular-nums; flex:none; min-width:30px; text-align:right; }
.adm-lead-bar{ width:56px; height:5px; border-radius:3px; background:rgba(255,255,255,.06); overflow:hidden; flex:none; }
.adm-lead-bar span{ display:block; height:100%; border-radius:3px; background:var(--adm-accent); }

/* ---------- content library tiles ---------- */
/* 120px, not 88px: at panel width the smaller track gave four columns for six
   tiles, so the second row was half-empty. Three and three sits square. */
.adm-lib-grid{ display:grid; grid-template-columns:repeat(auto-fit, minmax(120px,1fr)); gap:10px; }
.adm-lib-tile{
  display:flex; flex-direction:column; align-items:center; gap:3px;
  padding:14px 8px; border-radius:12px; background:rgba(255,255,255,.02);
  border:1px solid var(--adm-border); text-align:center;
}
.adm-lib-ico{ font-size:19px; }
.adm-lib-num{ font-size:21px; font-weight:800; color:var(--adm-text); font-variant-numeric:tabular-nums; }
.adm-lib-label{ font-size:13px; color:var(--adm-muted); font-weight:600; }

/* ==================== GIVEN AWAY (free grants) ==================== */
/* Visually separate from the revenue tiles on purpose: nothing in this panel is
   money, and it sits on a screen where everything else is. */
.adm-comp-grid{ display:grid; grid-template-columns:repeat(auto-fit, minmax(120px,1fr)); gap:10px; }
.adm-comp-list{ margin-top:14px; border-top:1px solid var(--adm-border); }
.adm-comp-row{
  display:flex; align-items:baseline; gap:10px;
  padding:9px 0; border-bottom:1px solid var(--adm-border);
}
.adm-comp-row:last-child{ border-bottom:0; }
.adm-comp-who{ flex:1; min-width:0; display:flex; align-items:baseline; gap:7px; flex-wrap:wrap; }
.adm-comp-who b{ font-size:14.5px; font-weight:700; color:var(--adm-text); }
.adm-comp-who span{ font-size:13px; color:var(--adm-muted); }
.adm-comp-who em{ font-size:13px; color:var(--adm-muted); font-style:italic; opacity:.85; }
.adm-comp-len{
  flex:none; font-size:13px; font-weight:750; padding:2px 9px; border-radius:7px;
  color:var(--adm-accent-2); background:rgba(251,191,36,.12); font-variant-numeric:tabular-nums;
}
.adm-comp-at{ flex:none; font-size:12.5px; color:var(--adm-muted); font-variant-numeric:tabular-nums; }

/* ============================ HEALTH ============================ */
/* Severity is carried on three tokens reused by every element below, so a
   finding, a filter pill and a table row all read as the same colour without
   each one restating the rgba(). */
.adm-health{
  --h-crit:#f87186; --h-crit-bg:rgba(248,113,134,.13); --h-crit-bd:rgba(248,113,134,.34);
  --h-warn:#fbbf24; --h-warn-bg:rgba(251,191,36,.12);  --h-warn-bd:rgba(251,191,36,.32);
  --h-ok:#34d399;   --h-ok-bg:rgba(52,211,153,.11);    --h-ok-bd:rgba(52,211,153,.28);
}

/* ---- verdict hero ---- */
.adm-hhero{
  position:relative; overflow:hidden; border-radius:18px; padding:20px 22px;
  border:1px solid var(--adm-border); background:var(--adm-card); margin-bottom:16px;
}
/* The status wash lives on a pseudo-element so the hero's own background stays
   a plain token — a gradient on the element itself would have to be restated in
   all three states. */
.adm-hhero::before{
  content:''; position:absolute; inset:0; pointer-events:none;
  background:radial-gradient(120% 160% at 0% 0%, var(--wash, transparent) 0%, transparent 60%);
}
.adm-hhero.crit{ border-color:var(--h-crit-bd); --wash:var(--h-crit-bg); }
.adm-hhero.warn{ border-color:var(--h-warn-bd); --wash:var(--h-warn-bg); }
.adm-hhero.ok  { border-color:var(--h-ok-bd);   --wash:var(--h-ok-bg); }
.adm-hhero-main{ position:relative; display:flex; align-items:center; gap:15px; }
.adm-hhero-badge{
  flex:none; width:46px; height:46px; border-radius:14px; display:grid; place-items:center;
  font-size:23px; background:var(--adm-card-hi); border:1px solid var(--adm-border);
}
.adm-hhero.crit .adm-hhero-badge{ color:var(--h-crit); background:var(--h-crit-bg); border-color:var(--h-crit-bd); }
.adm-hhero.warn .adm-hhero-badge{ color:var(--h-warn); background:var(--h-warn-bg); border-color:var(--h-warn-bd); }
.adm-hhero.ok   .adm-hhero-badge{ color:var(--h-ok);   background:var(--h-ok-bg);   border-color:var(--h-ok-bd); }
.adm-hhero-text{ flex:1; min-width:0; }
.adm-hhero-text h3{ margin:0; font-size:20px; font-weight:800; color:var(--adm-text); letter-spacing:-.3px; }
.adm-hhero-text p{ margin:3px 0 0; font-size:14.5px; color:var(--adm-muted); line-height:1.45; }
.adm-hscan{
  flex:none; display:inline-flex; align-items:center; gap:7px; cursor:pointer;
  padding:9px 15px; border-radius:11px; font-size:14px; font-weight:700;
  border:1px solid var(--adm-border); background:var(--adm-card-hi); color:var(--adm-text);
  transition:border-color .16s, background .16s, transform .16s;
}
.adm-hscan:hover{ border-color:var(--adm-border-hi); transform:translateY(-1px); }
.adm-hscan:active{ transform:translateY(0); }

.adm-hchips{
  position:relative; display:flex; flex-wrap:wrap; gap:8px;
  margin-top:16px; padding-top:15px; border-top:1px solid var(--adm-border);
}
.adm-hchip{
  display:inline-flex; align-items:center; gap:7px; padding:7px 12px; border-radius:10px;
  background:var(--adm-card-hi); border:1px solid var(--adm-border); color:var(--adm-muted);
}
.adm-hchip-v{ font-size:14.5px; font-weight:800; color:var(--adm-text); font-variant-numeric:tabular-nums; }
.adm-hchip-l{ font-size:13px; font-weight:600; }
.adm-hchip.good{ color:var(--h-ok); border-color:var(--h-ok-bd); }
.adm-hchip.mid { color:var(--h-warn); border-color:var(--h-warn-bd); }
.adm-hchip.bad { color:var(--h-crit); border-color:var(--h-crit-bd); }

/* ---- severity filters (the counters ARE the filter) ---- */
.adm-hfilters{ display:flex; gap:10px; flex-wrap:wrap; margin-bottom:12px; }
.adm-hfilter{
  flex:1; min-width:130px; display:flex; align-items:center; gap:11px; cursor:pointer; text-align:left;
  padding:13px 17px; border-radius:14px; border:1px solid var(--adm-border); background:var(--adm-card);
  transition:border-color .16s, background .16s, transform .16s;
}
.adm-hfilter:hover{ border-color:var(--adm-border-hi); transform:translateY(-1px); }
.adm-hfilter b{ font-size:26px; font-weight:800; font-variant-numeric:tabular-nums; color:var(--adm-text); }
.adm-hfilter span{ font-size:14px; color:var(--adm-muted); font-weight:600; }
.adm-hfilter.crit b{ color:var(--h-crit); }
.adm-hfilter.warn b{ color:var(--h-warn); }
.adm-hfilter.ok   b{ color:var(--h-ok); }
.adm-hfilter.on{ background:var(--adm-card-hi); border-color:var(--adm-border-hi); }
.adm-hfilter.crit.on{ border-color:var(--h-crit-bd); background:var(--h-crit-bg); }
.adm-hfilter.warn.on{ border-color:var(--h-warn-bd); background:var(--h-warn-bg); }
.adm-hfilter.ok.on  { border-color:var(--h-ok-bd);   background:var(--h-ok-bg); }

.adm-hcats{ display:flex; gap:7px; flex-wrap:wrap; margin-bottom:14px; }
.adm-hcat{
  cursor:pointer; padding:6px 12px; border-radius:999px; font-size:13.5px; font-weight:650;
  border:1px solid var(--adm-border); background:transparent; color:var(--adm-muted);
  transition:color .15s, border-color .15s, background .15s;
}
.adm-hcat:hover{ color:var(--adm-text); border-color:var(--adm-border-hi); }
.adm-hcat.on{ color:var(--adm-text); background:var(--adm-card-hi); border-color:var(--adm-border-hi); }

/* ---- finding cards ---- */
.adm-hlist{ display:flex; flex-direction:column; gap:9px; }
.adm-hc{
  border-radius:14px; border:1px solid var(--adm-border); background:var(--adm-card); overflow:hidden;
  /* The hidden start state lives in the keyframes, not on the element: an
     element that starts at opacity:0 in its own rule is invisible forever if
     the animation never runs. `backwards` applies frame 0 during the delay. */
  animation:admHFade .34s ease both;
  animation-delay:calc(var(--i, 0) * 28ms);
}
/* Once settled, re-rendering for a filter click must not replay the entrance. */
.adm-health.is-settled .adm-hc{ animation:none; }
@keyframes admHFade{ from{ opacity:0; transform:translateY(7px); } to{ opacity:1; transform:none; } }
.adm-hc.crit{ border-color:var(--h-crit-bd); }
.adm-hc.warn{ border-color:var(--h-warn-bd); }
.adm-hc-head{
  width:100%; display:flex; align-items:center; gap:12px; cursor:pointer; text-align:left;
  padding:14px 16px; background:transparent; border:0; color:inherit;
  transition:background .15s;
}
.adm-hc-head:hover:not([disabled]){ background:var(--adm-card-hi); }
.adm-hc-head[disabled]{ cursor:default; }
.adm-hc-ico{
  flex:none; width:28px; height:28px; border-radius:9px; display:grid; place-items:center; font-size:15px;
}
.adm-hc.crit .adm-hc-ico{ color:var(--h-crit); background:var(--h-crit-bg); }
.adm-hc.warn .adm-hc-ico{ color:var(--h-warn); background:var(--h-warn-bg); }
.adm-hc.ok   .adm-hc-ico{ color:var(--h-ok);   background:var(--h-ok-bg); }
.adm-hc-text{ flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; }
.adm-hc-text b{ font-size:15.5px; font-weight:700; color:var(--adm-text); }
.adm-hc-text > span{ font-size:14px; color:var(--adm-muted); line-height:1.45; }
.adm-hc-metric{
  flex:none; font-size:13px; font-weight:750; padding:3px 9px; border-radius:8px;
  background:var(--adm-card-hi); color:var(--adm-text); font-variant-numeric:tabular-nums;
}
.adm-hc-cat{ flex:none; font-size:12.5px; font-weight:600; color:var(--adm-muted); opacity:.75; }
.adm-hc-chev{ flex:none; color:var(--adm-muted); display:grid; place-items:center; transition:transform .2s; }
.adm-hc.open .adm-hc-chev{ transform:rotate(180deg); }

/* Height animation needs a definite end value, so the body is a grid row that
   goes 0fr → 1fr rather than max-height guesswork.
   The 0fr track collapses ONE child — .adm-hc-inner must stay the only one, or
   every extra child gets an implicit auto row and shows while the card is shut. */
.adm-hc-body{
  display:grid; grid-template-rows:0fr; transition:grid-template-rows .26s ease;
  border-top:1px solid transparent;
}
.adm-hc.open .adm-hc-body{ grid-template-rows:1fr; border-top-color:var(--adm-border); }
.adm-hc-inner{ overflow:hidden; padding:0 16px; transition:padding .26s ease; }
.adm-hc.open .adm-hc-inner{ padding:14px 16px; }

.adm-hrow{ display:flex; gap:11px; padding:0 0 11px; }
.adm-hrow:last-child{ padding-bottom:0; }
.adm-hrow-k{
  flex:none; width:104px; font-size:12.5px; font-weight:750; text-transform:uppercase;
  letter-spacing:.05em; color:var(--adm-muted); padding-top:2px;
}
.adm-hrow p{ margin:0; font-size:14.5px; line-height:1.55; color:var(--adm-text); }
.adm-hrow.why  .adm-hrow-k{ color:var(--h-warn); }
.adm-hrow.fix  .adm-hrow-k{ color:var(--h-ok); }
.adm-hrow code, .adm-hitem code{
  font-family:ui-monospace, SFMono-Regular, Menlo, monospace; font-size:13px;
  background:var(--adm-card-hi); padding:1px 6px; border-radius:6px; color:var(--adm-text);
  word-break:break-all;
}

/* ---- offending rows ---- */
.adm-hitems{ margin-top:4px; border-top:1px solid var(--adm-border); padding-top:11px; }
.adm-hitem{
  display:flex; align-items:baseline; gap:9px; flex-wrap:wrap;
  padding:8px 0; border-bottom:1px solid var(--adm-border);
}
.adm-hitem:last-child{ border-bottom:0; }
.adm-hitem-main{ flex:1; min-width:0; display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; }
.adm-hitem-main b{ font-size:14px; font-weight:700; color:var(--adm-text); }
.adm-hitem-main span{ font-size:13px; color:var(--adm-muted); }
.adm-hitem-n{
  flex:none; font-size:13px; font-weight:800; color:var(--h-crit);
  background:var(--h-crit-bg); padding:2px 8px; border-radius:7px; font-variant-numeric:tabular-nums;
}
.adm-hitem-at{ flex:none; font-size:12.5px; color:var(--adm-muted); }
.adm-hcode{
  flex-basis:100%; margin:5px 0 0; padding:8px 11px; border-radius:8px; overflow-x:auto;
  background:var(--adm-card-hi); font-family:ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size:12.5px; color:var(--adm-text);
}
.adm-htb{ flex-basis:100%; margin-top:6px; }
.adm-htb summary{
  cursor:pointer; font-size:13px; font-weight:650; color:var(--adm-muted);
  list-style:none; display:inline-flex; align-items:center; gap:5px;
}
.adm-htb summary::before{ content:'▸'; transition:transform .15s; display:inline-block; }
.adm-htb[open] summary::before{ transform:rotate(90deg); }
.adm-htb summary:hover{ color:var(--adm-text); }
.adm-htb pre{
  margin:7px 0 0; padding:11px 13px; border-radius:9px; overflow-x:auto; max-height:320px; overflow-y:auto;
  background:#0b0d12; border:1px solid var(--adm-border);
  font-family:ui-monospace, SFMono-Regular, Menlo, monospace; font-size:12px; line-height:1.6;
  color:#e6b9c2; white-space:pre;
}
.adm-hmore{ padding-top:9px; font-size:13px; color:var(--adm-muted); font-style:italic; }

.adm-hempty{
  display:flex; align-items:center; gap:9px; justify-content:center; padding:34px 16px;
  border-radius:14px; border:1px dashed var(--adm-border); color:var(--adm-muted); font-size:14.5px;
}
.adm-hacts{ display:flex; justify-content:flex-end; margin-top:12px; }

/* ---- endpoint table ---- */
/* The wrapper scrolls, not the page: a wide table must never make the whole
   admin shell scroll sideways. */
.adm-htable-wrap{ overflow-x:auto; }
.adm-htable{ width:100%; border-collapse:collapse; font-size:13.5px; }
.adm-htable th{
  text-align:left; padding:7px 10px; font-size:12px; font-weight:750; text-transform:uppercase;
  letter-spacing:.05em; color:var(--adm-muted); border-bottom:1px solid var(--adm-border); white-space:nowrap;
}
.adm-htable td{
  padding:8px 10px; border-bottom:1px solid var(--adm-border); color:var(--adm-text);
  font-variant-numeric:tabular-nums; white-space:nowrap;
}
.adm-htable td:first-child{ white-space:normal; }
.adm-htable tr:last-child td{ border-bottom:0; }
.adm-htable td.w{ color:var(--h-warn); font-weight:750; }
.adm-htable td.c{ color:var(--h-crit); font-weight:800; }
.adm-htable tr.bad{ background:var(--h-crit-bg); }
.adm-htable tr.mid{ background:var(--h-warn-bg); }

@media (max-width:760px){
  .adm-hhero-main{ flex-wrap:wrap; }
  .adm-hscan{ order:3; width:100%; justify-content:center; }
  .adm-hc-cat, .adm-hc-metric{ display:none; }
  .adm-hrow{ flex-direction:column; gap:3px; }
  .adm-hrow-k{ width:auto; }
  .adm-hfilter{ min-width:calc(50% - 5px); }
}

/* ============================ USERS ============================ */
.adm-users-toolbar{ display:flex; gap:8px; flex-wrap:wrap; margin-bottom:14px; }
.adm-seg-btn{
  display:inline-flex; align-items:center; gap:6px; padding:7px 13px; border-radius:10px;
  font-size:14.5px; font-weight:600; cursor:pointer; color:var(--adm-muted);
  background:var(--adm-card); border:1px solid var(--adm-border); transition:all .14s ease;
}
.adm-seg-btn span{
  font-size:13px; font-weight:800; padding:0 6px; border-radius:6px;
  background:rgba(255,255,255,.06); color:var(--adm-text); font-variant-numeric:tabular-nums;
}
.adm-seg-btn:hover{ color:var(--adm-text); border-color:var(--adm-border-hi); }
.adm-seg-btn.active{ color:#fff; background:linear-gradient(90deg, var(--adm-accent), var(--adm-accent-2)); border-color:transparent; }
.adm-seg-btn.active span{ background:rgba(0,0,0,.18); color:#fff; }

.adm-users-scroll{ overflow-x:auto; border-radius:14px; border:1px solid var(--adm-border); }
.adm-users-table.enriched{ width:100%; border-collapse:collapse; font-size:15px; min-width:720px; }
.adm-users-table.enriched thead th{
  text-align:left; padding:11px 14px; font-size:13px; text-transform:uppercase; letter-spacing:.5px;
  color:var(--adm-muted); font-weight:700; background:rgba(255,255,255,.02); border-bottom:1px solid var(--adm-border);
}
.adm-users-table.enriched thead th.num{ text-align:right; }
.adm-users-table.enriched tbody td{ padding:11px 14px; border-bottom:1px solid var(--adm-border); color:var(--adm-text); vertical-align:middle; }
.adm-users-table.enriched tbody tr{ cursor:pointer; transition:background .12s ease; }
.adm-users-table.enriched tbody tr:hover{ background:rgba(255,138,91,.06); }
.adm-users-table.enriched tbody tr:last-child td{ border-bottom:0; }
.adm-users-table.enriched td.mono{ font-family:ui-monospace, SFMono-Regular, Menlo, 'Native Emoji', monospace; font-size:14px; color:var(--adm-muted); }
.adm-users-table.enriched td.num{ text-align:right; font-variant-numeric:tabular-nums; }
.adm-users-table.enriched .muted{ color:var(--adm-muted); }
.adm-users-table.enriched .adm-u-go{ color:var(--adm-muted); font-size:20px; text-align:center; width:20px; }
.adm-u-dot{ display:inline-block; width:8px; height:8px; border-radius:50%; margin-right:8px; vertical-align:middle; }
.adm-u-dot.on{ background:var(--adm-success); box-shadow:0 0 0 3px rgba(52,211,153,.16); }
.adm-u-dot.off{ background:var(--adm-muted); opacity:.5; }
.adm-u-chip{ display:inline-block; font-size:13px; font-weight:700; padding:2px 8px; border-radius:999px; }
.adm-u-chip.prem{ color:var(--adm-accent-2); background:rgba(251,191,36,.14); border:1px solid rgba(251,191,36,.3); }
.adm-u-chip.free{ color:var(--adm-muted); background:rgba(255,255,255,.05); border:1px solid var(--adm-border); }
/* Ended membership — same slate as the roster's .adm-ur-chip.ended, so the
   drawer and the row it opened from tell one story. */
.adm-u-chip.ended{ color:#cbd5e1; background:rgba(148,163,184,.14); border:1px solid rgba(148,163,184,.32); }
:root[data-theme="light"] .adm-u-chip.ended{ color:#475569; background:rgba(100,116,139,.13); border-color:rgba(100,116,139,.3); }
.adm-tab-badge.is-crit{ background:var(--adm-danger) !important; color:#fff !important; }

/* ============================ USER DETAIL DRAWER ============================ */
.adm-drawer-backdrop{
  position:fixed; inset:0; z-index:1200; background:rgba(6,7,11,.55);
  backdrop-filter:blur(3px); opacity:0; pointer-events:none; transition:opacity .2s ease;
  display:flex; justify-content:flex-end;
}
.adm-drawer-backdrop.open{ opacity:1; pointer-events:auto; }
.adm-drawer{
  width:min(440px, 94vw); height:100%; overflow-y:auto; background:var(--adm-panel);
  border-left:1px solid var(--adm-border); box-shadow:-24px 0 60px -20px rgba(0,0,0,.6);
  transform:translateX(40px); opacity:.4; transition:transform .26s cubic-bezier(.22,1,.36,1), opacity .26s ease;
}
.adm-drawer-backdrop.open .adm-drawer{ transform:translateX(0); opacity:1; }
.adm-drawer-loading{ padding:60px 24px; text-align:center; color:var(--adm-muted); font-weight:600; }
.adm-drawer-head{
  position:sticky; top:0; z-index:2; display:flex; align-items:center; gap:12px;
  padding:18px 20px; background:var(--adm-panel); border-bottom:1px solid var(--adm-border);
}
.adm-drawer-id{ display:flex; align-items:center; gap:12px; flex:1; min-width:0; }
.adm-drawer-avatar{
  width:46px; height:46px; flex:none; border-radius:12px; display:grid; place-items:center;
  font-size:20px; font-weight:800; color:#fff;
  background:linear-gradient(135deg, var(--adm-accent), var(--adm-accent-2));
}
.adm-drawer-name{ font-size:17px; font-weight:800; color:var(--adm-text); }
.adm-drawer-sub{ font-size:14px; color:var(--adm-muted); margin-top:1px; }
.adm-drawer-close{
  flex:none; width:36px; height:36px; border-radius:9px; cursor:pointer; font-size:16px;
  color:var(--adm-muted); background:transparent; border:1px solid var(--adm-border); transition:all .14s ease;
}
.adm-drawer-close:hover{ color:var(--adm-danger); border-color:rgba(248,113,134,.4); }
.adm-drawer-body{ padding:18px 20px 28px; }
.adm-drawer-tags{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-bottom:16px; }
.adm-drawer-dim{ font-size:14px; color:var(--adm-muted); }

.adm-drawer-eng{ margin-bottom:16px; }
.adm-drawer-eng-top{ display:flex; justify-content:space-between; font-size:14.5px; color:var(--adm-muted); font-weight:600; margin-bottom:6px; }
.adm-drawer-eng-top b{ color:var(--adm-text); font-variant-numeric:tabular-nums; }
.adm-drawer-eng-track{ height:9px; border-radius:6px; background:rgba(255,255,255,.06); overflow:hidden; }
.adm-drawer-eng-track div{ height:100%; border-radius:6px; transition:width .6s cubic-bezier(.22,1,.36,1); }

.adm-dstat-grid{ display:grid; grid-template-columns:repeat(4,1fr); gap:9px; margin-bottom:12px; }
.adm-dstat{
  display:flex; flex-direction:column; align-items:center; gap:3px; padding:12px 6px;
  border-radius:11px; background:var(--adm-card); border:1px solid var(--adm-border);
}
.adm-dstat-num{ font-size:20px; font-weight:800; color:var(--adm-text); font-variant-numeric:tabular-nums; line-height:1; }
.adm-dstat-label{ font-size:12.5px; color:var(--adm-muted); text-transform:uppercase; letter-spacing:.4px; font-weight:600; text-align:center; }
.adm-dstat.hi .adm-dstat-num{ color:var(--adm-success); }

.adm-drawer-section{ margin-top:18px; }
.adm-drawer-section-h{ font-size:14px; font-weight:800; color:var(--adm-muted); text-transform:uppercase; letter-spacing:.6px; margin-bottom:9px; }
.adm-dtest{ display:flex; align-items:center; gap:8px; padding:9px 0; border-top:1px solid var(--adm-border); font-size:14.5px; }
.adm-dtest:first-of-type{ border-top:0; }
.adm-dtest-title{ flex:1; color:var(--adm-text); font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.adm-dtest-mode{ font-size:12px; color:var(--adm-muted); text-transform:uppercase; letter-spacing:.3px; }
.adm-dtest-att{ font-size:13.5px; color:var(--adm-muted); font-weight:700; font-variant-numeric:tabular-nums; }
.adm-dtest-band{ font-size:13px; font-weight:800; color:var(--adm-muted); background:rgba(255,255,255,.05); padding:2px 7px; border-radius:6px; flex:none; }
.adm-dtest-band.hi{ color:var(--adm-success); background:rgba(52,211,153,.12); }
.adm-dpay{ display:flex; align-items:center; gap:9px; padding:9px 0; border-top:1px solid var(--adm-border); font-size:14.5px; }
.adm-dpay:first-of-type{ border-top:0; }
.adm-dpay span:first-child{ flex:1; color:var(--adm-text); font-weight:600; }
.adm-dpay b{ font-variant-numeric:tabular-nums; color:var(--adm-text); }
.adm-drawer-meta{ margin-top:18px; font-size:13.5px; color:var(--adm-muted); line-height:1.5; }
.adm-drawer-actions{ margin-top:16px; display:flex; gap:10px; }
.adm-drawer-actions .adm-action{ flex:1; justify-content:center; }

/* ============================ REVENUE ============================ */
.adm-rev-hero{ display:grid; grid-template-columns:repeat(5,1fr); gap:12px; margin-bottom:16px; align-items:stretch; }
.adm-rev-tile{
  position:relative; overflow:hidden; border-radius:14px; padding:16px 16px 14px;
  background:var(--adm-card); border:1px solid var(--adm-border);
  display:flex; flex-direction:column;
  animation:admFade .28s ease both; animation-delay:calc(var(--i, 0) * .05s);
}
.adm-rev-tile.accent{
  background:radial-gradient(120% 90% at 100% 0%, rgba(52,211,153,.14), transparent 55%), var(--adm-card);
  border-color:rgba(52,211,153,.32);
}
.adm-rev-tile.grand{
  background:linear-gradient(135deg, rgba(255,138,91,.14), rgba(251,191,36,.10)), var(--adm-card);
  border-color:rgba(251,191,36,.34);
}
.adm-rev-label{ font-size:13px; font-weight:700; color:var(--adm-muted); text-transform:uppercase; letter-spacing:.5px; }
.adm-rev-num{ font-size:25px; font-weight:800; color:var(--adm-text); margin:8px 0 3px; line-height:1; font-variant-numeric:tabular-nums; letter-spacing:-.4px; }
.adm-rev-num small{ font-size:13px; font-weight:700; color:var(--adm-muted); letter-spacing:0; }
.adm-rev-full{ font-size:13.5px; color:var(--adm-muted); font-variant-numeric:tabular-nums; }
.adm-rev-note{
  margin-top:auto; padding-top:8px; font-size:12.5px; line-height:1.35;
  color:var(--adm-muted); font-variant-numeric:tabular-nums;
}
.adm-rev-tile.grand .adm-rev-num{ color:var(--adm-accent-2); }

/* monthly revenue bars (labelled, 12 columns) */
.adm-mbars{ display:flex; align-items:flex-end; gap:6px; height:170px; padding-top:14px; }
.adm-mbar-col{ flex:1; display:flex; flex-direction:column; align-items:center; gap:5px; height:100%; }
.adm-mbar-val{ font-size:11.5px; color:var(--adm-muted); font-weight:700; font-variant-numeric:tabular-nums; min-height:12px; }
.adm-mbar-wrap{ flex:1; width:100%; display:flex; align-items:flex-end; }
.adm-mbar{
  width:100%; border-radius:5px 5px 2px 2px; height:var(--h, 0);
  background:linear-gradient(180deg, var(--adm-success), rgba(52,211,153,.55));
  animation:admGrowH .6s cubic-bezier(.22,1,.36,1) both;
  animation-delay:calc(var(--i, 0) * .045s);
}
.adm-mbar-x{ font-size:12px; color:var(--adm-muted); font-weight:600; }

/* ============================ LIVE / ONLINE NOW ============================
   A console, not a card grid. Three bands stacked above the roster:
     .adm-live-strip     KPIs + the sampled sparkline + the refresh countdown
     .adm-live-where     how the people online divide across the site
     .adm-live-controls  search · tier filter · sort
   Everything above the roster is built ONCE by liveShellHTML(); only the body
   below it is repainted on the five-second poll. That split is load-bearing —
   see the comment on .adm-live-row about what a full repaint would cost. */
.adm-live-dot{ width:11px; height:11px; border-radius:50%; background:var(--adm-success); box-shadow:0 0 0 0 rgba(52,211,153,.6); animation:admPulse 1.8s ease-out infinite; flex:none; }

/* ---- the stat strip ---- */
.adm-live-strip{
  display:grid; grid-template-columns:repeat(3, minmax(0,auto)) minmax(0,1fr) auto;
  align-items:stretch; gap:10px; margin-bottom:12px;
}
.adm-live-kpi{
  display:flex; flex-direction:column; justify-content:center; gap:3px;
  padding:10px 16px; border-radius:12px; min-width:96px;
  background:var(--adm-card); border:1px solid var(--adm-border);
}
.adm-live-kpi-lbl{
  display:flex; align-items:center; gap:6px;
  font-size:12px; font-weight:800; letter-spacing:.7px; text-transform:uppercase;
  color:var(--adm-muted); white-space:nowrap;
}
.adm-live-kpi b{
  font-size:26px; font-weight:800; line-height:1; color:var(--adm-text);
  font-variant-numeric:tabular-nums;
}
.adm-live-kpi.is-now b{ color:var(--adm-success); }

.adm-live-spark{
  display:flex; flex-direction:column; gap:2px; min-width:0;
  padding:9px 14px 4px; border-radius:12px;
  background:var(--adm-card); border:1px solid var(--adm-border);
}
.adm-live-spark-top{
  display:flex; justify-content:space-between; gap:10px;
  font-size:12px; font-weight:700; letter-spacing:.4px; color:var(--adm-muted);
  white-space:nowrap;
}
.adm-live-spark svg{ width:100%; height:44px; display:block; overflow:visible; }
.adm-live-line{ fill:none; stroke:var(--adm-success); stroke-width:1.6; vector-effect:non-scaling-stroke;
                stroke-linejoin:round; stroke-linecap:round; }
.adm-live-area{ fill:color-mix(in oklab, var(--adm-success) 16%, transparent); stroke:none; }

/* refresh countdown + pause, one control */
.adm-live-pause{
  display:flex; align-items:center; gap:9px; padding:0 16px 0 12px;
  border-radius:12px; cursor:pointer; white-space:nowrap;
  font-family:inherit; font-size:14px; font-weight:700; color:var(--adm-text);
  background:var(--adm-card); border:1px solid var(--adm-border);
  transition:background .14s ease, border-color .14s ease;
}
.adm-live-pause:hover{ background:var(--adm-card-hi); border-color:var(--adm-border-hi); }
.adm-live-pause.is-paused{ color:var(--adm-warn, #fbbf24); border-color:color-mix(in oklab, var(--adm-warn, #fbbf24) 45%, transparent); }
.adm-live-tick{ position:relative; width:34px; height:34px; flex:none; display:grid; place-items:center; }
.adm-live-tick svg{ position:absolute; inset:0; width:100%; height:100%; transform:none; }
.adm-live-tick-tr{ fill:none; stroke:var(--adm-border); stroke-width:3; }
.adm-live-tick-arc{ fill:none; stroke:var(--adm-success); stroke-width:3; stroke-linecap:round; }
.adm-live-pause.is-paused .adm-live-tick-arc{ stroke:var(--adm-warn, #fbbf24); }
.adm-live-tick i{
  position:relative; font-style:normal; font-size:12.5px; font-weight:800;
  color:var(--adm-muted); font-variant-numeric:tabular-nums;
}

/* ---- where they are ---- */
.adm-live-where{
  display:grid; grid-template-columns:repeat(auto-fit, minmax(120px,1fr));
  gap:8px; margin-bottom:12px;
}
.adm-live-where:empty{ display:none; }      /* no rule, no gap, when nobody is on */
/* --ca is the accent everything below reads. The inline style carries both the
   dark value and its light twin; only this pair of rules decides which is live,
   because an inline `--c` could never be overridden from a stylesheet. */
.adm-live-wcell,
.adm-live-row{ --ca:var(--c); }
:root[data-theme="light"] .adm-live-wcell,
:root[data-theme="light"] .adm-live-row{ --ca:var(--cl); }

.adm-live-wcell{
  padding:8px 11px 9px; border-radius:11px;
  background:var(--adm-card); border:1px solid var(--adm-border);
}
.adm-live-wtop{
  display:flex; align-items:baseline; justify-content:space-between; gap:8px;
  font-size:13.5px; font-weight:700; color:var(--adm-text); white-space:nowrap;
}
.adm-live-wtop span{ overflow:hidden; text-overflow:ellipsis; }
.adm-live-wtop b{ font-size:16px; font-weight:800; color:rgb(var(--ca)); font-variant-numeric:tabular-nums; }
.adm-live-wbar{ height:4px; margin-top:6px; border-radius:99px; background:var(--adm-border); overflow:hidden; }
.adm-live-wbar i{ display:block; height:100%; border-radius:99px; background:rgb(var(--ca)); }

/* ---- controls ---- */
.adm-live-controls{ display:flex; align-items:center; gap:9px; flex-wrap:wrap; margin-bottom:12px; }
.adm-live-search{
  position:relative; display:flex; align-items:center; gap:8px; flex:1 1 260px; min-width:0;
  padding:0 13px; height:42px; border-radius:11px;
  background:var(--adm-card); border:1px solid var(--adm-border);
}
.adm-live-search:focus-within{ border-color:var(--adm-accent); }
.adm-live-search span{ font-size:14px; opacity:.7; flex:none; }
.adm-live-search input{
  flex:1; min-width:0; height:100%; border:0; outline:0; background:none;
  font-family:inherit; font-size:15px; color:var(--adm-text);
}
.adm-live-search input::placeholder{ color:var(--adm-muted); }
.adm-live-search input::-webkit-search-cancel-button{ filter:grayscale(1) opacity(.5); }

.adm-live-chips{ display:flex; gap:6px; flex-wrap:wrap; }
.adm-live-chip{
  display:inline-flex; align-items:center; gap:6px; height:42px; padding:0 13px;
  border-radius:11px; cursor:pointer; font-family:inherit; font-size:14.5px; font-weight:700;
  color:var(--adm-muted); background:var(--adm-card); border:1px solid var(--adm-border);
  transition:color .14s ease, background .14s ease, border-color .14s ease;
}
.adm-live-chip i{
  font-style:normal; font-size:13px; font-weight:800; padding:1px 6px; border-radius:99px;
  background:var(--adm-card-hi); color:var(--adm-muted); font-variant-numeric:tabular-nums;
}
.adm-live-chip:hover{ color:var(--adm-text); border-color:var(--adm-border-hi); }
.adm-live-chip.is-on{
  color:var(--adm-accent); border-color:color-mix(in oklab, var(--adm-accent) 55%, transparent);
  background:color-mix(in oklab, var(--adm-accent) 12%, var(--adm-card));
}
.adm-live-chip.is-on i{ background:color-mix(in oklab, var(--adm-accent) 22%, transparent); color:var(--adm-accent); }
.adm-live-sel{
  height:42px; padding:0 11px; border-radius:11px; cursor:pointer;
  font-family:inherit; font-size:14.5px; font-weight:700; color:var(--adm-text);
  background:var(--adm-card); border:1px solid var(--adm-border);
}

.adm-live-foot{ margin:9px 2px 0; font-size:13px; color:var(--adm-muted); }
.adm-live-foot b{ color:var(--adm-text); font-variant-numeric:tabular-nums; }
/* One bordered list, hairline-separated, rather than a grid of free-floating
   cards. Two people used to render as two boxes stranded in the top-left of an
   otherwise empty page; a list with a header reads as a complete object at any
   length, and the columns let you scan "who is on what" straight down. */
.adm-live-list{
  border:1px solid var(--adm-border); border-radius:14px; overflow:hidden;
  background:var(--adm-card);
}

/* The header and every row share this template — change one, change both, or
   the columns stop lining up. */
.adm-live-cols,
.adm-live-row{
  display:grid; align-items:center;
  grid-template-columns:minmax(0,2.2fr) minmax(0,2.4fr) minmax(0,1.5fr) 132px 104px;
  gap:14px; padding:11px 16px;
}
.adm-live-cols{
  font-size:12.5px; font-weight:800; letter-spacing:.8px; text-transform:uppercase;
  color:var(--adm-muted); padding-top:10px; padding-bottom:10px;
  background:var(--adm-card-hi); border-bottom:1px solid var(--adm-border);
}
.adm-live-cols span:nth-child(4){ text-align:center; }
.adm-live-cols span:nth-child(5){ text-align:right; }

/* Deliberately NO entrance animation. renderLive() reassigns the whole list's
   innerHTML on a 5-second poll, so every row node is destroyed and rebuilt each
   time — a fade-and-rise would not read as an entrance, it would read as the
   table flickering every five seconds, forever. */
.adm-live-row{
  cursor:pointer; border-top:1px solid var(--adm-border);
  transition:background .14s ease;
}
/* Adjacent-sibling, NOT :first-of-type — the header is a <div> too, so it is
   the first of that type and no row ever matched, leaving a doubled 2px rule
   under the header. Still matches on mobile, where the header is display:none
   but remains in the DOM. */
.adm-live-cols + .adm-live-row{ border-top:0; }
.adm-live-row:hover{ background:var(--adm-card-hi); }
/* No translate on hover: rows sit against their neighbours, so lifting one
   shears the hairlines above and below it. */

.adm-live-who{ display:flex; align-items:center; gap:11px; min-width:0; }
.adm-live-av{
  position:relative; flex:none; width:42px; height:42px; border-radius:11px; display:grid; place-items:center;
  font-size:17px; font-weight:800; color:#fff; background:linear-gradient(135deg, var(--adm-accent), var(--adm-accent-2));
}
.adm-live-ring{
  position:absolute; right:-2px; bottom:-2px; width:12px; height:12px; border-radius:50%;
  background:var(--adm-success); border:2px solid var(--adm-card); animation:admPulse 1.8s ease-out infinite;
}
.adm-live-id{ min-width:0; }
.adm-live-name{ font-size:15.5px; font-weight:700; color:var(--adm-text); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* `.badge` is styled nowhere in the app, so the admin marker rendered as the
   bare word welded to the end of the name — "Abdulloh Admin Admin". Give it a
   chip here rather than inventing a global .badge that would land on whatever
   else happens to use the class. */
.adm-live-name .badge{
  display:inline-block; vertical-align:1px; margin-left:6px; padding:1px 7px;
  border-radius:99px; font-size:11.5px; font-weight:800; letter-spacing:.6px;
  text-transform:uppercase; color:var(--adm-accent);
  background:color-mix(in oklab, var(--adm-accent) 16%, transparent);
  border:1px solid color-mix(in oklab, var(--adm-accent) 38%, transparent);
}
.adm-live-sub2{ font-size:13.5px; font-weight:500; color:var(--adm-muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* The section badge is derived from `route`, the activity line from the label
   the client sent. Two lines because they answer different questions: WHICH
   part of the site, and WHAT exactly — and the section is the one you scan. */
.adm-live-act{ min-width:0; display:flex; flex-direction:column; gap:2px; }
.adm-live-sec{
  align-self:flex-start; padding:1px 8px; border-radius:99px;
  font-size:12.5px; font-weight:800; letter-spacing:.3px; white-space:nowrap;
  color:rgb(var(--ca)); background:rgba(var(--ca), .13);
  border:1px solid rgba(var(--ca), .3);
}
.adm-live-act-t{
  font-size:14.5px; color:var(--adm-text); font-weight:600;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.adm-live-dev{
  font-size:13.5px; color:var(--adm-muted); font-weight:600; min-width:0;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.adm-live-tier{ text-align:center; }
.adm-live-ago{ font-size:13.5px; color:var(--adm-muted); font-variant-numeric:tabular-nums; text-align:right; }

/* Narrow: the four columns become two rows inside the same box — the header
   stops meaning anything once the cells no longer sit under it, so it goes. */
@media (max-width:1080px){
  /* Device is the first thing to go: it is context, not the answer to "who is
     on what", and it is still one click away in the user drawer. */
  .adm-live-cols,
  .adm-live-row{ grid-template-columns:minmax(0,2.2fr) minmax(0,2.6fr) 132px 104px; }
  .adm-live-dev{ display:none; }
  .adm-live-cols span:nth-child(3){ display:none; }
}
@media (max-width:920px){
  .adm-live-strip{ grid-template-columns:repeat(3, minmax(0,1fr)); }
  .adm-live-spark{ grid-column:1 / -1; order:1; }
  .adm-live-pause{ grid-column:1 / -1; order:2; justify-content:center; padding:9px 16px; }
}
@media (max-width:820px){
  .adm-live-cols{ display:none; }
  .adm-live-row{
    grid-template-columns:minmax(0,1fr) auto;
    grid-template-areas:"who tier" "act ago";
    gap:4px 12px; padding:12px 14px;
  }
  .adm-live-who{ grid-area:who; }
  .adm-live-tier{ grid-area:tier; text-align:right; }
  .adm-live-act{ grid-area:act; padding-left:49px; }   /* clears the 38px avatar + its gap */
  .adm-live-ago{ grid-area:ago; align-self:end; }
  .adm-live-search{ flex-basis:100%; }
}
@media (max-width:560px){
  .adm-live-strip{ grid-template-columns:repeat(3, minmax(0,1fr)); gap:8px; }
  .adm-live-kpi{ min-width:0; padding:9px 10px; }
  .adm-live-kpi b{ font-size:21px; }
  .adm-live-kpi-lbl{ font-size:11px; letter-spacing:.4px; }
  .adm-live-where{ grid-template-columns:repeat(auto-fit, minmax(104px,1fr)); }
  .adm-live-chips{ width:100%; }
  .adm-live-chip{ flex:1 1 0; justify-content:center; padding:0 8px; }
  .adm-live-sel{ width:100%; }
}
.adm-tab-badge.live{ background:var(--adm-success) !important; color:#04150e !important; }

@keyframes admPulse{
  0%   { box-shadow:0 0 0 0 rgba(52,211,153,.55); }
  70%  { box-shadow:0 0 0 7px rgba(52,211,153,0); }
  100% { box-shadow:0 0 0 0 rgba(52,211,153,0); }
}

/* ---------- entrance ---------- */
@keyframes admFade{ from{ opacity:0; transform:translateY(6px); } to{ opacity:1; transform:none; } }
/* Bars, fills and arcs all grow from nothing to the size the markup already
   gave them, so the resting value stays on the element and only the START is
   in the keyframe. Switch the animation off (below) and every chart is still
   drawn at the right size — see the entrance-animation visibility rule. */
@keyframes admGrowH{ from{ height:0; }  to{ height:var(--h, 0); } }
@keyframes admGrowW{ from{ width:0; }   to{ width:var(--w, 0); } }
@keyframes admDonutDraw{
  from{ stroke-dasharray:0 var(--c); }
  to  { stroke-dasharray:var(--dash) var(--gap); }
}

/* Stagger the top rows so the dashboard resolves left-to-right instead of every
   card appearing on the same frame. Index comes from position, not from markup:
   these two rows are fixed-length and threading a counter through the builders
   for four cards would be noise. */
.adm-hero-grid > *:nth-child(2), .adm-rev-hero > *:nth-child(2){ animation-delay:.05s; }
.adm-hero-grid > *:nth-child(3), .adm-rev-hero > *:nth-child(3){ animation-delay:.10s; }
.adm-hero-grid > *:nth-child(4), .adm-rev-hero > *:nth-child(4){ animation-delay:.15s; }
.adm-rev-hero > *:nth-child(5){ animation-delay:.20s; }

/* These roots are rebuilt wholesale on every Refresh and on every poll. Without
   this the entire dashboard replayed its stagger each time, which reads as the
   page flinching rather than as data arriving. First paint only. */
.adm-ov.is-settled .adm-hero-card,
.adm-ov.is-settled .adm-ov-panel,
.adm-ov.is-settled .adm-rev-tile,
.adm-ov.is-settled .adm-bar,
.adm-ov.is-settled .adm-hist-bar,
.adm-ov.is-settled .adm-mbar,
.adm-ov.is-settled .adm-funnel-fill,
.adm-ov.is-settled .adm-donut-seg,
.adm-ov.is-settled .adm-tbl tbody tr,
.adm-ov.is-settled .adm-tbl .bar i{ animation:none; }

/* ---------- responsive ---------- */
@media (max-width: 1000px){
  .adm-hero-grid{ grid-template-columns:repeat(2,1fr); }
  .adm-ov-grid{ grid-template-columns:1fr; }
  .adm-lead-cols{ grid-template-columns:1fr; gap:16px; }
  .adm-rev-hero{ grid-template-columns:repeat(3,1fr); }
}
@media (max-width: 700px){
  /* Below this the donut and its table are each too narrow to read side by
     side, so the ring goes on top and the table takes the full width. */
  .adm-donut-row{ flex-direction:column; align-items:stretch; gap:14px; }
  .adm-donut-wrap{ align-self:center; }
  .adm-tbl-slot.grow{ min-width:0; }
}
@media (max-width: 560px){
  .adm-hero-grid{ grid-template-columns:1fr; }
  .adm-dstat-grid{ grid-template-columns:repeat(2,1fr); }
  .adm-hero-num{ font-size:28px; }
  .adm-rev-hero{ grid-template-columns:repeat(2,1fr); }
  .adm-mbar-val{ display:none; }
  .adm-tbl .bar{ display:none; }
  .adm-hist{ height:140px; }
  .adm-hist-n{ display:none; }
}

@media (prefers-reduced-motion: reduce){
  .adm-hero-card, .adm-ov-panel, .adm-rev-tile, .adm-bar, .adm-hist-bar, .adm-mbar,
  .adm-funnel-fill, .adm-donut-seg, .adm-tbl tbody tr, .adm-tbl .bar i,
  .adm-live-dot, .adm-ur-pres{ animation:none !important; }
  .adm-ov-alert{ transition:none; }
}

/* ---------- light-theme nudges ---------- */
:root[data-theme="light"] .adm-chart-box{ background-color:rgba(30,40,80,.02); }
:root[data-theme="light"] .adm-chart-empty{ background:rgba(30,40,80,.02); }
:root[data-theme="light"] .adm-hero-stack,
:root[data-theme="light"] .adm-funnel-track,
:root[data-theme="light"] .adm-lead-bar,
:root[data-theme="light"] .adm-drawer-eng-track{ background:rgba(30,40,80,.08); }
:root[data-theme="light"] .adm-seg-btn span,
:root[data-theme="light"] .adm-lib-tile,
:root[data-theme="light"] .adm-lead-rank{ background:rgba(30,40,80,.05); }
:root[data-theme="light"] .adm-drawer-backdrop{ background:rgba(30,40,80,.28); }
:root[data-theme="light"] .adm-users-table.enriched tbody tr:hover{ background:rgba(255,138,91,.08); }

/* Access note in the per-user drawer — why this account has the tier it has. */
.adm-drawer-note{
  margin-top:12px; padding:10px 12px; border-radius:11px;
  font-size:14.5px; line-height:1.5; color:var(--adm-text);
  background:rgba(251,191,36,.08); border:1px solid rgba(251,191,36,.26);
}
.adm-drawer-note span{
  display:block; font-size:11.5px; font-weight:800; letter-spacing:.5px;
  text-transform:uppercase; color:var(--adm-accent-2); margin-bottom:4px;
}
.adm-drawer-note i{ display:block; font-style:normal; margin-top:4px; font-size:13px; color:var(--adm-muted); }
:root[data-theme="light"] .adm-drawer-note{ background:rgba(251,191,36,.13); }
