/* ============================================================================
   TGIS Admin — the shared design layer.

   This file introduces NO new colours, type sizes, radii, easings or shadows.
   Every value below resolves to a token from tokens.css. What it does add is a
   DENSITY layer, because an admin console and a timeline are different
   problems: the timeline is one 640px column read at leisure, the console is a
   fourteen-column table scanned for an outlier.

   Three rules this file enforces, all of them things a hostile reviewer checks
   in the first ten seconds:

   1. NUMERALS ARE TABULAR, ALWAYS. Proportional digits in a stacked column
      make the eye do arithmetic it should not have to do. Every numeric cell
      and every metric carries `font-variant-numeric: tabular-nums`.

   2. THE ACCENT IS RATIONED. In the consumer app lime marks anything
      interactive. In a console where everything is interactive that would be
      noise, and "the accent is sprayed rather than earned" is the single most
      common way a dense UI reads as amateur. Here lime means exactly three
      things: the focus ring, the current nav item, and the one primary action
      on a screen. Status meaning is carried by --ok/--warn/--danger/--info.

   3. ONE SPACING RHYTHM. Everything is a multiple of 4px off the --s-* scale.
      There is no 5px, no 7px, no 18px anywhere in this file.
   ========================================================================== */

/* Drawers, dialogs and menus portal to <body>, outside the .adm subtree. They
   still need the density scale and the console's type size, so the variable
   block is carried by both the shell and the portal wrapper while the layout
   below belongs to the shell alone. */
.adm, .adm-portal, .adm-gate {
  /* ---------- density ---------------------------------------------------- */
  --adm-nav-w:      248px;
  --adm-nav-w-sm:   64px;
  --adm-top-h:      52px;
  --adm-row-h:      44px;
  --adm-row-h-cmp:  34px;
  --adm-cell-x:     var(--s-5);   /* 12px — horizontal cell padding */
  --adm-gut:        var(--s-6);   /* 16px — panel gutter */
  --adm-pane:       var(--s-8);   /* 24px — page padding */

  /* Console body type sits one step below the timeline's --t-15. */
  --adm-t-body:     var(--t-13);
  --adm-lh-body:    var(--lh-13);
  --adm-t-label:    var(--t-11);

  color: var(--text-0);
  font-family: var(--font-ui);
  font-size: var(--adm-t-body);
  line-height: var(--adm-lh-body);
}

.adm {
  position: fixed;
  inset: 0;
  z-index: var(--z-content);
  display: grid;
  grid-template-columns: var(--adm-nav-w) minmax(0, 1fr);
  background: var(--bg-0);
  /* The ambient WebGL room is a reading-room affordance. Behind a data table it
     is a distraction and it costs contrast, so the console is opaque. */
  isolation: isolate;
}

.adm[data-density='compact'] { --adm-row-h: var(--adm-row-h-cmp); }

@media (max-width: 1100px) {
  .adm { grid-template-columns: var(--adm-nav-w-sm) minmax(0, 1fr); }
  .adm__navlabel, .adm__navsection { display: none; }
  .adm__navitem { justify-content: center; }
}

/* The console document has no scrolling page — the shell owns the viewport and
   the panes scroll inside it. */
.adm-body { margin: 0; background: var(--bg-0); overflow: hidden; }

/* Toasts. `toast()` is shared with the product but its appearance lives in
   app.css, which the console does not load, so the handful of rules it needs
   are restated under .adm-body. The position is changed on purpose: the
   product centres them at the bottom, which is exactly where the bulk-action
   bar floats, so here they go to the corner. */
.adm-body .toast-root { left: auto; right: var(--s-8); bottom: var(--s-8); transform: none; align-items: flex-end; }
.adm-body .toast {
  display: flex; align-items: center; gap: var(--s-5);
  min-width: 240px; max-width: 420px;
  padding: var(--s-5) var(--s-6);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--bg-3);
  box-shadow: var(--e-3);
  font-size: var(--t-13); font-weight: 500;
  color: var(--text-0);
  pointer-events: auto;
  opacity: 0; transform: translateY(8px);
  transition: opacity var(--d-3) var(--ease-out), transform var(--d-4) var(--ease-spring);
}
.adm-body .toast.is-in { opacity: 1; transform: none; }
.adm-body .toast--success { border-color: var(--line-accent); }
.adm-body .toast--error { border-color: rgba(255, 95, 109, .4); }
.adm-body .toast__msg { flex: 1; }
.adm-body .toast__action { border: 0; background: none; color: var(--accent); font: inherit; font-weight: 700; cursor: pointer; }

/* ================================================================= gate === */

.adm-gate {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  padding: var(--s-8);
  background: var(--bg-0);
}
.adm-gate__card {
  display: grid;
  gap: var(--s-6);
  width: min(360px, 100%);
  padding: var(--s-9);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--bg-1);
  box-shadow: var(--e-3);
}
.adm-gate__mark { color: var(--accent); }
.adm-gate__title {
  margin: 0;
  font-family: var(--font-dis);
  font-size: var(--t-24); line-height: var(--lh-24);
  font-weight: 700; letter-spacing: var(--tracking-tight);
  color: var(--text-0);
}
.adm-gate__body { margin: 0; font-size: var(--t-13); line-height: var(--lh-14); color: var(--text-2); }
.adm-gate__card .adm-btn { height: 36px; }

/* Boot indicator. A ring rather than a full-page splash: the console is behind
   one request, and a splash screen for 80ms reads as slower than nothing. */
.adm-gate__spin {
  width: 22px; height: 22px;
  border: 2px solid var(--line-strong);
  border-top-color: var(--accent);
  border-radius: var(--r-pill);
  animation: adm-spin var(--d-5) linear infinite;
}
@keyframes adm-spin { to { transform: rotate(360deg); } }

/* ============================================================ navigation === */

.adm__nav {
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--bg-1);
  border-right: 1px solid var(--line);
}

.adm__brand {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  height: var(--adm-top-h);
  padding: 0 var(--adm-gut);
  border-bottom: 1px solid var(--line);
  flex: none;
  text-decoration: none;
}
/* Sized by width, height auto. The lockup is one artwork at roughly 4.7:1, so
   constraining the height instead would leave the width to the intrinsic ratio
   and the wordmark would run past the 248px rail. 132px leaves room for the
   caption inside the 216px the gutters allow. */
.adm__brandlockup { width: 132px; height: auto; flex: none; }
.adm__brandmark { width: 26px; height: 26px; flex: none; display: none; }
/* A caption, not a second wordmark. The lockup is the brand; "Console" only says
   which surface of it this is, so it sits back in weight and colour rather than
   competing with the artwork it follows. */
.adm__brandtext {
  font-family: var(--font-dis);
  font-size: var(--t-12);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  color: var(--text-2);
  white-space: nowrap;
}

/* The collapsed rail: 64px holds the rooster and nothing else. */
@media (max-width: 1100px) {
  .adm__brand { justify-content: center; padding: 0; gap: 0; }
  .adm__brandlockup, .adm__brandtext { display: none; }
  .adm__brandmark { display: block; }
}

.adm__navscroll { flex: 1; min-height: 0; overflow-y: auto; padding: var(--s-5) var(--s-4) var(--s-8); }

.adm__navsection {
  padding: var(--s-6) var(--s-4) var(--s-3);
  font-size: var(--adm-t-label);
  line-height: var(--lh-11);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-3);
}
.adm__navsection:first-child { padding-top: var(--s-2); }

.adm__navitem {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--s-5);
  width: 100%;
  height: 34px;
  padding: 0 var(--s-4);
  border: 0;
  border-radius: var(--r-xs);
  background: transparent;
  color: var(--text-1);
  font: inherit;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  transition: background var(--d-2) var(--ease-out), color var(--d-2) var(--ease-out);
}
.adm__navitem:hover { background: var(--bg-2); color: var(--text-0); }
.adm__navitem.is-active { background: var(--bg-3); color: var(--text-0); }
/* The only place a persistent lime mark is earned: where you currently are. */
.adm__navitem.is-active::before {
  content: '';
  position: absolute;
  left: calc(var(--s-4) * -1);
  top: 50%;
  transform: translateY(-50%);
  width: 2px;
  height: 16px;
  border-radius: var(--r-pill);
  background: var(--accent);
}
.adm__navitem svg { flex: none; opacity: .82; }
.adm__navitem.is-active svg { opacity: 1; }
.adm__navlabel { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Queue depth. Neutral until it is actually a problem — a permanently red
   badge trains people to ignore red. */
.adm__navcount {
  flex: none;
  min-width: 20px;
  padding: 0 var(--s-2);
  border-radius: var(--r-pill);
  background: var(--bg-4);
  color: var(--text-2);
  font-size: var(--adm-t-label);
  line-height: 16px;
  font-weight: 600;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.adm__navcount[data-tone='warn']   { background: var(--amber-dim);  color: var(--warn); }
.adm__navcount[data-tone='danger'] { background: var(--danger-dim); color: var(--danger); }

.adm__navfoot {
  flex: none;
  padding: var(--s-4);
  border-top: 1px solid var(--line);
}

/* Signed-in staff member. Role is stated in words, never by colour alone. */
.adm__who { display: flex; align-items: center; gap: var(--s-4); padding: var(--s-3) var(--s-4); border-radius: var(--r-xs); }
.adm__who:hover { background: var(--bg-2); }
.adm__whotext { min-width: 0; flex: 1; }
.adm__whoname {
  display: block; font-size: var(--t-12); line-height: var(--lh-12); font-weight: 600;
  color: var(--text-0); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.adm__whorole { display: block; font-size: var(--adm-t-label); line-height: var(--lh-11); color: var(--text-2); }

/* ================================================================= main === */

.adm__main { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.adm__page { display: flex; flex-direction: column; flex: 1; min-height: 0; min-width: 0; }

.adm__top {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--s-5);
  height: var(--adm-top-h);
  padding: 0 var(--adm-pane);
  border-bottom: 1px solid var(--line);
  background: var(--bg-1);
}
.adm__title {
  font-family: var(--font-dis);
  font-size: var(--t-15);
  line-height: var(--lh-15);
  font-weight: 700;
  letter-spacing: var(--tracking-tight);
  color: var(--text-0);
}
.adm__crumb { display: flex; align-items: center; gap: var(--s-3); min-width: 0; }
.adm__crumb a { color: var(--text-2); text-decoration: none; }
.adm__crumb a:hover { color: var(--text-0); }
.adm__crumbsep { color: var(--text-3); }
.adm__topspacer { flex: 1; }

.adm__body { flex: 1; min-height: 0; overflow-y: auto; padding: var(--adm-pane); }
.adm__body[data-flush='1'] { padding: 0; }

/* `fill` hands the height to the page's content instead of scrolling the page.
   A table page wants this: the toolbar and the column headers stay fixed and
   only the rows move. Without it the header scrolls away and a 400-row queue
   becomes unreadable halfway down. */
.adm__body[data-fill='1'] { display: flex; flex-direction: column; overflow: hidden; }
.adm__body[data-fill='1'] > * { min-height: 0; }
.adm__body[data-fill='1'] > .adm-panel { flex: 1; }

.adm-stackv { display: grid; gap: var(--adm-gut); align-content: start; }

/* ================================================================ panel === */

.adm-panel {
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--bevel);
  overflow: hidden;
}
.adm-panel__head {
  display: flex;
  align-items: center;
  gap: var(--s-5);
  padding: var(--s-5) var(--adm-gut);
  border-bottom: 1px solid var(--line);
}
.adm-panel__title {
  font-size: var(--t-13);
  line-height: var(--lh-13);
  font-weight: 600;
  color: var(--text-0);
  letter-spacing: var(--tracking-tight);
}
.adm-panel__sub { font-size: var(--t-12); line-height: var(--lh-12); color: var(--text-2); }
.adm-panel__spacer { flex: 1; }
.adm-panel__body { padding: var(--adm-gut); }
.adm-panel__body[data-flush='1'] { padding: 0; }

/* A table panel is a column: fixed toolbar, fixed header, scrolling rows. */
.adm-panel--table { display: flex; flex-direction: column; min-height: 0; }
.adm-panel--table > .adm-panel__body { flex: 1; min-height: 0; display: flex; flex-direction: column; }

.adm-grid { display: grid; gap: var(--adm-gut); }
.adm-grid[data-cols='2'] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.adm-grid[data-cols='3'] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.adm-grid[data-cols='4'] { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1400px) { .adm-grid[data-cols='4'] { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 1100px) {
  .adm-grid[data-cols='2'], .adm-grid[data-cols='3'] { grid-template-columns: minmax(0, 1fr); }
}

/* ================================================================= stat === */

.adm-stat { display: flex; flex-direction: column; gap: var(--s-3); padding: var(--s-6) var(--adm-gut); }
.adm-stat__label {
  font-size: var(--adm-t-label);
  line-height: var(--lh-11);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-2);
}
.adm-stat__row { display: flex; align-items: baseline; gap: var(--s-4); }
.adm-stat__value {
  font-family: var(--font-dis);
  font-size: var(--t-31);
  line-height: var(--lh-31);
  font-weight: 700;
  letter-spacing: var(--tracking-display);
  color: var(--text-0);
  font-variant-numeric: tabular-nums;
}
.adm-stat__unit { font-size: var(--t-14); color: var(--text-2); font-weight: 500; }
.adm-stat__foot { display: flex; align-items: center; gap: var(--s-3); }

/* Delta. The arrow is not decorative — it is the only glyph, and direction
   plus colour must agree. "Up" is not automatically good, so tone is passed
   in by the caller rather than derived from the sign. */
.adm-delta {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--t-12);
  line-height: var(--lh-12);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text-2);
}
.adm-delta[data-tone='up']   { color: var(--ok); }
.adm-delta[data-tone='down'] { color: var(--danger); }
.adm-delta[data-tone='flat'] { color: var(--text-2); }
.adm-delta__since { color: var(--text-3); font-weight: 500; }

/* ================================================================ table === */

/* The wrap is the scroll container in both axes. That is what makes the sticky
   header actually stick: a header inside a container that never scrolls
   vertically is sticky in name only. */
.adm-table__wrap { flex: 1; min-height: 0; width: 100%; overflow: auto; scrollbar-gutter: stable; }
.adm-table__wrap:focus { outline: none; }
/* Fixed, so the `<colgroup>` widths are law rather than a suggestion.
   Under `auto` a browser sizes columns to their content, which means one long
   post excerpt widens its column until the table is 1,972px inside an 851px
   panel and the last four columns are off the edge — and `text-overflow` never
   fires, because the cell it is clipping against grew to fit. Every cell that
   holds free text already asks for `.adm-table__cellclip`; this is the line
   that lets it work. Columns without a declared width share what is left. */
.adm-table { width: 100%; table-layout: fixed; border-collapse: separate; border-spacing: 0; }

.adm-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  height: 32px;
  padding: 0 var(--adm-cell-x);
  background: var(--bg-2);
  border-bottom: 1px solid var(--line);
  font-size: var(--adm-t-label);
  line-height: var(--lh-11);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-2);
  text-align: left;
  white-space: nowrap;
  user-select: none;
}
.adm-table thead th[data-align='right']  { text-align: right; }
.adm-table thead th[data-align='center'] { text-align: center; }

.adm-table__sort {
  display: inline-flex; align-items: center; gap: var(--s-2);
  border: 0; background: none; padding: 0; margin: 0;
  font: inherit; letter-spacing: inherit; text-transform: inherit; color: inherit;
  cursor: pointer;
}
.adm-table__sort:hover { color: var(--text-0); }
.adm-table__sortglyph {
  display: inline-flex;
  transition: opacity var(--d-2) var(--ease-out), transform var(--d-2) var(--ease-out);
  opacity: 0;
}
.adm-table__sort:hover .adm-table__sortglyph { opacity: .5; }
.adm-table__sort.is-sorted { color: var(--text-0); }
.adm-table__sort.is-sorted .adm-table__sortglyph { opacity: 1; }

.adm-table tbody td {
  height: var(--adm-row-h);
  padding: 0 var(--adm-cell-x);
  border-bottom: 1px solid var(--line-soft);
  color: var(--text-1);
  vertical-align: middle;
}
.adm-table tbody td[data-align='right']  { text-align: right; }
.adm-table tbody td[data-align='center'] { text-align: center; }
/* Every number in the console aligns on its digits. */
.adm-table td[data-kind='num'],
.adm-table td[data-kind='time'] { font-variant-numeric: tabular-nums; }
.adm-table td[data-kind='id'] {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  color: var(--text-2);
}
.adm-table td[data-kind='strong'] { color: var(--text-0); font-weight: 500; }

.adm-table tbody tr { transition: background var(--d-1) var(--ease-out); }
.adm-table tbody tr:hover { background: var(--bg-2); }
.adm-table tbody tr.is-selected { background: var(--accent-dim); }
.adm-table tbody tr.is-open { background: var(--bg-3); }
.adm-table tbody tr[data-muted='1'] td { color: var(--text-3); }

.adm-table__cellclip { display: block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Checkbox column keeps a fixed optical width so headers never shift. */
.adm-table__check { width: 36px; padding-left: var(--adm-gut) !important; }

/* ============================================================ checkbox === */

.adm-check {
  appearance: none;
  width: 15px; height: 15px;
  margin: 0;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-xs);
  background: var(--bg-3);
  display: grid; place-content: center;
  cursor: pointer;
  transition: background var(--d-1) var(--ease-out), border-color var(--d-1) var(--ease-out);
}
.adm-check:hover { border-color: var(--text-3); }
.adm-check:checked, .adm-check:indeterminate { background: var(--accent); border-color: var(--accent); }
.adm-check:checked::after {
  content: '';
  width: 9px; height: 5px;
  border-left: 2px solid var(--accent-ink);
  border-bottom: 2px solid var(--accent-ink);
  transform: rotate(-45deg) translate(1px, -1px);
}
.adm-check:indeterminate::after {
  content: ''; width: 8px; height: 2px; background: var(--accent-ink); border-radius: var(--r-pill);
}

/* ================================================================= pill === */

/* Status is spelled out. Colour reinforces the word, it never replaces it —
   a reviewer testing for colour-blind safety looks for exactly this. */
.adm-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  height: 20px;
  padding: 0 var(--s-4);
  border-radius: var(--r-pill);
  background: var(--bg-3);
  color: var(--text-1);
  font-size: var(--adm-t-label);
  line-height: 1;
  font-weight: 600;
  letter-spacing: .01em;
  white-space: nowrap;
}
.adm-pill::before {
  content: '';
  width: 5px; height: 5px;
  border-radius: var(--r-pill);
  background: currentColor;
  flex: none;
  opacity: .9;
}
.adm-pill[data-tone='ok']      { background: rgba(74, 222, 139, .13); color: var(--ok); }
.adm-pill[data-tone='warn']    { background: var(--amber-dim);        color: var(--warn); }
.adm-pill[data-tone='danger']  { background: var(--danger-dim);       color: var(--danger); }
.adm-pill[data-tone='info']    { background: rgba(88, 182, 255, .13); color: var(--info); }
.adm-pill[data-tone='violet']  { background: var(--violet-dim);       color: var(--violet-400); }
.adm-pill[data-tone='neutral'] { background: var(--bg-3);             color: var(--text-2); }
.adm-pill[data-plain='1']::before { display: none; }

/* ============================================================== toolbar === */

.adm-toolbar {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-5) var(--adm-gut);
  border-bottom: 1px solid var(--line);
  background: var(--bg-1);
}
.adm-toolbar__spacer { flex: 1; }

.adm-search {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  height: 30px;
  min-width: 220px;
  padding: 0 var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r-xs);
  background: var(--bg-2);
  color: var(--text-2);
  transition: border-color var(--d-2) var(--ease-out);
}
.adm-search:focus-within { border-color: var(--line-strong); }
.adm-search input {
  flex: 1; min-width: 0;
  border: 0; background: none; outline: none;
  font: inherit; color: var(--text-0);
}
.adm-search input::placeholder { color: var(--text-3); }
.adm-search kbd {
  flex: none;
  padding: 1px var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-xs);
  background: var(--bg-3);
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-3);
}

/* Facet chip. `is-on` is a border+text change, not a lime fill — filters are
   frequently multi-selected and a row of lime chips would dominate the page. */
.adm-facet {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  height: 30px;
  padding: 0 var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r-xs);
  background: var(--bg-2);
  color: var(--text-1);
  font: inherit;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--d-2) var(--ease-out), border-color var(--d-2) var(--ease-out), color var(--d-2) var(--ease-out);
}
.adm-facet:hover { background: var(--bg-3); color: var(--text-0); }
.adm-facet.is-on { border-color: var(--line-strong); background: var(--bg-4); color: var(--text-0); }
.adm-facet[data-size='sm'] { height: 24px; padding: 0 var(--s-4); font-size: var(--t-12); font-weight: 500; }
.adm-facet__count { color: var(--text-3); font-variant-numeric: tabular-nums; font-weight: 600; }
.adm-facet svg { opacity: .6; }

/* ============================================================== buttons === */

.adm-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-3);
  height: 30px;
  padding: 0 var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r-xs);
  background: var(--bg-2);
  color: var(--text-0);
  font: inherit;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--d-1) var(--ease-out), border-color var(--d-1) var(--ease-out), opacity var(--d-1) var(--ease-out);
}
.adm-btn:hover { background: var(--bg-3); }
.adm-btn:active { background: var(--bg-4); }
.adm-btn[disabled] { opacity: .45; cursor: not-allowed; }
.adm-btn svg { opacity: .85; }

/* Exactly one of these per screen. */
.adm-btn[data-variant='primary'] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}
.adm-btn[data-variant='primary']:hover  { background: var(--accent-hover); border-color: var(--accent-hover); }
.adm-btn[data-variant='primary']:active { background: var(--accent-press); border-color: var(--accent-press); }
.adm-btn[data-variant='primary'] svg { opacity: 1; }

.adm-btn[data-variant='danger'] { color: var(--danger); border-color: var(--danger-dim); background: var(--danger-dim); }
.adm-btn[data-variant='danger']:hover { background: rgba(255, 95, 109, .22); }

.adm-btn[data-variant='ghost'] { background: transparent; border-color: transparent; color: var(--text-1); }
.adm-btn[data-variant='ghost']:hover { background: var(--bg-2); color: var(--text-0); }

.adm-btn[data-size='sm'] { height: 24px; padding: 0 var(--s-4); font-size: var(--t-12); }
.adm-iconbtn {
  display: inline-grid; place-content: center;
  width: 30px; height: 30px;
  border: 1px solid transparent; border-radius: var(--r-xs);
  background: transparent; color: var(--text-2);
  cursor: pointer;
  transition: background var(--d-1) var(--ease-out), color var(--d-1) var(--ease-out);
}
.adm-iconbtn:hover:not(:disabled) { background: var(--bg-3); color: var(--text-0); }
/* Dimmer than the .45 the kit's other disabled controls use: this one has no
   label to fall back on, so the icon has to read as inert on its own, and it
   must not answer a hover it will not honour. */
.adm-iconbtn:disabled { opacity: .3; cursor: not-allowed; }

/* ============================================================ bulk bar === */

/* Floats over the table rather than pushing it — a bar that reflows 200 rows
   when you tick one checkbox is disorienting. */
.adm-bulk {
  position: sticky;
  bottom: var(--adm-gut);
  z-index: var(--z-sticky);
  display: flex;
  align-items: center;
  gap: var(--s-5);
  width: fit-content;
  margin: 0 auto;
  padding: var(--s-4) var(--s-5);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--glass-strong);
  backdrop-filter: blur(12px);
  box-shadow: var(--e-3);
  animation: adm-rise var(--d-3) var(--ease-out);
}
@keyframes adm-rise { from { opacity: 0; transform: translateY(6px); } }
.adm-bulk__count { font-weight: 600; color: var(--text-0); font-variant-numeric: tabular-nums; }
.adm-bulk__rule { width: 1px; height: 18px; background: var(--line); }

/* ============================================================== drawer === */

.adm-drawer {
  position: fixed;
  inset: 0 0 0 auto;
  z-index: var(--z-modal);
  width: min(560px, 100vw);
  display: flex;
  flex-direction: column;
  background: var(--bg-1);
  border-left: 1px solid var(--line-strong);
  box-shadow: var(--e-4);
  animation: adm-slide var(--d-3) var(--ease-out);
}
@keyframes adm-slide { from { transform: translateX(16px); opacity: 0; } }
.adm-drawer__scrim {
  position: fixed; inset: 0; z-index: calc(var(--z-modal) - 1);
  background: var(--scrim);
  animation: adm-fade var(--d-2) var(--ease-out);
}
@keyframes adm-fade { from { opacity: 0; } }
.adm-drawer__head {
  flex: none;
  display: flex; align-items: center; gap: var(--s-5);
  padding: var(--s-5) var(--adm-gut);
  border-bottom: 1px solid var(--line);
}
.adm-drawer__title {
  flex: 1; min-width: 0;
  font-family: var(--font-dis);
  font-size: var(--t-15); line-height: var(--lh-15);
  font-weight: 700; letter-spacing: var(--tracking-tight);
  color: var(--text-0);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.adm-drawer__sub {
  margin-top: 1px;
  font-size: var(--t-12); line-height: var(--lh-12);
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.adm-drawer:focus { outline: none; }
.adm-drawer[data-busy='1'] .adm-drawer__body { opacity: .5; pointer-events: none; }
.adm-drawer__body { flex: 1; min-height: 0; overflow-y: auto; padding: var(--adm-gut); }
.adm-drawer__foot {
  flex: none;
  display: flex; align-items: center; gap: var(--s-4);
  padding: var(--s-5) var(--adm-gut);
  border-top: 1px solid var(--line);
  background: var(--bg-2);
}

/* ============================================================== dialog === */

/* Confirmation. Narrow on purpose — a wide confirm dialog encourages a wall of
   text, and the one thing that must be read here is the sentence naming what
   is about to happen and to whom. */
/* The dialog layer sits above the drawer layer, not beside it. A confirm that
   dims the page but leaves an open drawer at full brightness reads as though
   the drawer is still live — the one moment where that misread is expensive. */
.adm-dialog__scrim {
  position: fixed; inset: 0;
  z-index: calc(var(--z-modal) + 1);
  background: var(--scrim);
  animation: adm-fade var(--d-2) var(--ease-out);
}
.adm-dialog {
  position: fixed;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  z-index: calc(var(--z-modal) + 2);
  width: min(440px, calc(100vw - var(--s-8)));
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  background: var(--bg-1);
  box-shadow: var(--e-4);
  animation: adm-pop var(--d-3) var(--ease-spring);
}
@keyframes adm-pop { from { opacity: 0; transform: translate(-50%, -46%) scale(.97); } }
.adm-dialog__head { padding: var(--adm-gut) var(--adm-gut) 0; }
.adm-dialog__title {
  font-family: var(--font-dis);
  font-size: var(--t-17); line-height: var(--lh-17);
  font-weight: 700; letter-spacing: var(--tracking-tight);
  color: var(--text-0);
}
.adm-dialog__body { padding: var(--s-4) var(--adm-gut) var(--adm-gut); display: grid; gap: var(--s-5); }
.adm-dialog__body p { font-size: var(--t-13); line-height: var(--lh-14); color: var(--text-1); margin: 0; }
.adm-dialog__foot {
  display: flex; align-items: center; justify-content: flex-end; gap: var(--s-4);
  padding: var(--s-5) var(--adm-gut);
  border-top: 1px solid var(--line);
  background: var(--bg-2);
  border-radius: 0 0 var(--r-lg) var(--r-lg);
}
.adm-dialog__foot .adm-dialog__spacer { flex: 1; }

/* =============================================================== field === */

.adm-field { display: grid; gap: var(--s-3); }
.adm-field__label {
  font-size: var(--adm-t-label);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-2);
}
.adm-field__hint { font-size: var(--t-11); color: var(--text-3); line-height: var(--lh-12); }
.adm-input, .adm-select, .adm-textarea {
  width: 100%;
  padding: var(--s-4) var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r-xs);
  background: var(--bg-2);
  color: var(--text-0);
  font: inherit;
  outline: none;
  transition: border-color var(--d-2) var(--ease-out);
}
.adm-input:hover, .adm-select:hover, .adm-textarea:hover { border-color: var(--line-strong); }
.adm-input::placeholder, .adm-textarea::placeholder { color: var(--text-3); }
.adm-textarea { min-height: 76px; resize: vertical; line-height: var(--lh-14); }
.adm-select {
  appearance: none;
  padding-right: var(--s-9);
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 17px) 13px, calc(100% - 12px) 13px;
  background-size: 5px 5px;
  background-repeat: no-repeat;
  cursor: pointer;
}
.adm-select option { background: var(--bg-2); color: var(--text-0); }

/* ================================================================== kv === */

.adm-kv { display: grid; grid-template-columns: minmax(96px, auto) minmax(0, 1fr); gap: var(--s-3) var(--s-6); }
.adm-kv__k { font-size: var(--t-12); line-height: var(--lh-14); color: var(--text-2); }
.adm-kv__v { font-size: var(--t-13); line-height: var(--lh-14); color: var(--text-0); min-width: 0; overflow-wrap: anywhere; }
.adm-kv__v[data-kind='num'] { font-variant-numeric: tabular-nums; }
.adm-kv__v[data-kind='id']  { font-family: var(--font-mono); font-size: var(--t-11); color: var(--text-1); }

/* ============================================================ timeline === */

.adm-tl { display: grid; gap: 0; }
.adm-tl__item { position: relative; display: grid; grid-template-columns: 20px minmax(0, 1fr); gap: var(--s-5); padding-bottom: var(--s-6); }
.adm-tl__item:last-child { padding-bottom: 0; }
.adm-tl__rail { position: relative; display: flex; justify-content: center; padding-top: 4px; }
.adm-tl__dot {
  width: 7px; height: 7px; border-radius: var(--r-pill);
  background: var(--text-3); flex: none; z-index: 1;
  box-shadow: 0 0 0 3px var(--bg-1);
}
.adm-tl__dot[data-tone='ok']     { background: var(--ok); }
.adm-tl__dot[data-tone='warn']   { background: var(--warn); }
.adm-tl__dot[data-tone='danger'] { background: var(--danger); }
.adm-tl__item:not(:last-child) .adm-tl__rail::after {
  content: ''; position: absolute; top: 12px; bottom: calc(var(--s-6) * -1);
  width: 1px; background: var(--line);
}
.adm-tl__head { display: flex; align-items: baseline; gap: var(--s-4); flex-wrap: wrap; }
.adm-tl__what { font-size: var(--t-13); line-height: var(--lh-13); color: var(--text-0); font-weight: 500; }
.adm-tl__when { font-size: var(--t-11); line-height: var(--lh-11); color: var(--text-3); font-variant-numeric: tabular-nums; }
.adm-tl__detail { margin-top: var(--s-2); font-size: var(--t-12); line-height: var(--lh-14); color: var(--text-2); }

/* =============================================================== chart === */

.adm-chart { display: block; width: 100%; overflow: visible; }
.adm-chart__grid line { stroke: var(--line-soft); stroke-width: 1; shape-rendering: crispEdges; }
.adm-chart__axis text {
  fill: var(--text-3);
  font-family: var(--font-ui);
  font-size: 10px;
  font-variant-numeric: tabular-nums;
}
.adm-chart__line { fill: none; stroke: var(--accent); stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
/* The fill is set inline per instance — each chart mints its own gradient id so
   two charts on one page cannot collide. */
.adm-chart__area { opacity: .7; }
.adm-chart__bar  { fill: var(--bg-4); transition: fill var(--d-1) var(--ease-out); }
.adm-chart__bar:hover { fill: var(--text-3); }
.adm-chart__dot  { fill: var(--accent); stroke: var(--bg-1); stroke-width: 2; }
.adm-chart__cross { stroke: var(--line-strong); stroke-width: 1; stroke-dasharray: 2 3; }
.adm-spark { display: block; overflow: visible; }

/* Tooltip. Positioned by the chart, never wider than its content, and it flips
   sides before it would leave the panel. */
.adm-chart__tip {
  position: absolute;
  z-index: var(--z-sticky);
  min-width: 108px;
  padding: var(--s-4) var(--s-5);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-xs);
  background: var(--glass-strong);
  backdrop-filter: blur(10px);
  box-shadow: var(--e-3);
  pointer-events: none;
}
.adm-chart__tipwhen {
  margin-bottom: var(--s-3);
  font-size: var(--adm-t-label);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
.adm-chart__tiprow { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-6); }
.adm-chart__tipkey { font-size: var(--t-12); color: var(--text-2); }
.adm-chart__tipval { font-size: var(--t-13); font-weight: 600; color: var(--text-0); font-variant-numeric: tabular-nums; }

/* ================================================================= bars === */

.adm-bars { display: grid; gap: var(--s-3); }
.adm-bars__row {
  display: grid;
  grid-template-columns: minmax(72px, 168px) minmax(0, 1fr) minmax(40px, auto);
  align-items: center;
  gap: var(--s-5);
  height: 26px;
}
.adm-bars__label { font-size: var(--t-12); color: var(--text-1); }
.adm-bars__track { height: 8px; border-radius: var(--r-pill); background: var(--bg-3); overflow: hidden; }
.adm-bars__fill {
  display: block; height: 100%;
  border-radius: var(--r-pill);
  background: var(--text-3);
  transition: width var(--d-4) var(--ease-out);
}
.adm-bars__value { font-size: var(--t-12); font-weight: 600; color: var(--text-0); text-align: right; }

/* Bars and stack segments share one tone map. */
.adm-bars__fill[data-tone='accent'],  .adm-stack__seg[data-tone='accent'],  .adm-stack__keyitem i[data-tone='accent']  { background: var(--accent); }
.adm-bars__fill[data-tone='ok'],      .adm-stack__seg[data-tone='ok'],      .adm-stack__keyitem i[data-tone='ok']      { background: var(--ok); }
.adm-bars__fill[data-tone='warn'],    .adm-stack__seg[data-tone='warn'],    .adm-stack__keyitem i[data-tone='warn']    { background: var(--warn); }
.adm-bars__fill[data-tone='danger'],  .adm-stack__seg[data-tone='danger'],  .adm-stack__keyitem i[data-tone='danger']  { background: var(--danger); }
.adm-bars__fill[data-tone='info'],    .adm-stack__seg[data-tone='info'],    .adm-stack__keyitem i[data-tone='info']    { background: var(--info); }
.adm-bars__fill[data-tone='violet'],  .adm-stack__seg[data-tone='violet'],  .adm-stack__keyitem i[data-tone='violet']  { background: var(--violet-400); }
.adm-bars__fill[data-tone='neutral'], .adm-stack__seg[data-tone='neutral'], .adm-stack__keyitem i[data-tone='neutral'] { background: var(--text-3); }

.adm-stack { display: grid; gap: var(--s-5); }
.adm-stack__bar { display: flex; height: 10px; border-radius: var(--r-pill); background: var(--bg-3); overflow: hidden; }
.adm-stack__seg { height: 100%; transition: width var(--d-4) var(--ease-out); }
.adm-stack__seg + .adm-stack__seg { box-shadow: inset 1px 0 0 var(--bg-1); }
.adm-stack__key { display: flex; flex-wrap: wrap; gap: var(--s-3) var(--s-6); }
.adm-stack__keyitem { display: inline-flex; align-items: center; gap: var(--s-3); font-size: var(--t-12); color: var(--text-2); }
.adm-stack__keyitem i { width: 8px; height: 8px; border-radius: 2px; flex: none; }
.adm-stack__keyitem b { color: var(--text-0); font-weight: 600; font-variant-numeric: tabular-nums; }
.adm-spark path { fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }

/* ================================================================ misc === */

.adm-empty {
  display: grid; place-items: center; gap: var(--s-5);
  padding: var(--s-12) var(--s-8);
  text-align: center;
}
.adm-empty svg { color: var(--text-3); }
.adm-empty__title { font-size: var(--t-14); font-weight: 600; color: var(--text-1); }
.adm-empty__body { font-size: var(--t-13); color: var(--text-2); max-width: 40ch; line-height: var(--lh-14); }

.adm-skel {
  background: linear-gradient(90deg, var(--bg-2) 25%, var(--bg-3) 50%, var(--bg-2) 75%);
  background-size: 200% 100%;
  border-radius: var(--r-xs);
  animation: adm-shimmer var(--d-6) linear infinite;
}
@keyframes adm-shimmer { to { background-position: -200% 0; } }

.adm-note {
  display: flex; gap: var(--s-4);
  padding: var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r-xs);
  background: var(--bg-2);
  font-size: var(--t-12);
  line-height: var(--lh-14);
  color: var(--text-1);
}
.adm-note[data-tone='warn']   { border-color: rgba(255, 207, 77, .28); background: var(--amber-dim); }
.adm-note[data-tone='danger'] { border-color: rgba(255, 95, 109, .3);  background: var(--danger-dim); }
.adm-note svg { flex: none; margin-top: 1px; }

/* One focus treatment for the entire console. */
.adm :focus-visible,
.adm-portal :focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  border-radius: var(--r-xs);
}

/* ============================================================== cells === */

.adm-facets { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; }

/* Avatar() is shared with the product, but its stylesheet is app.css and the
   console does not load app.css. Rather than pull in the whole consumer
   component library for one circle, the four rules it actually needs are
   restated here. The live ring and the presence dot are consumer affordances
   and have no place in a moderation table, so they are not restated. */
.adm .avatar, .adm-portal .avatar {
  position: relative; display: block; flex: none;
  width: var(--av); height: var(--av);
  border-radius: var(--r-pill);
  background: linear-gradient(160deg, var(--bg-3), var(--bg-1));
  overflow: hidden;
  box-shadow: inset 0 0 0 1px var(--ink-4);
}
.adm .avatar__img, .adm-portal .avatar__img { width: 100%; height: 100%; object-fit: cover; }

.adm-user { display: flex; align-items: center; gap: var(--s-4); min-width: 0; }
.adm-user__text { min-width: 0; display: grid; }
.adm-user__name { font-size: var(--t-13); line-height: var(--lh-12); font-weight: 500; color: var(--text-0); }
.adm-user__handle { font-size: var(--t-11); line-height: var(--lh-11); color: var(--text-3); }

/* Ids are copy targets, not decoration — the confirmation is the point. */
.adm-id {
  border: 0; padding: 0; background: none;
  font-family: var(--font-mono); font-size: var(--t-11);
  color: var(--text-2); cursor: copy;
  transition: color var(--d-1) var(--ease-out);
}
.adm-id:hover { color: var(--text-0); }
.adm-id[data-copied='1'] { color: var(--ok); }
.adm-id[data-copied='1']::after { content: ' copied'; font-size: 10px; }

.adm-mono { font-family: var(--font-mono); font-size: var(--t-11); color: var(--text-2); }
.adm-num  { font-variant-numeric: tabular-nums; }
.adm-clip { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The console's motion is all entrance and feedback — none of it carries
   meaning, so all of it can go. The shimmer is the exception worth keeping in
   spirit but not in motion: it becomes a flat block rather than disappearing,
   so the loading state is still legible. */
@media (prefers-reduced-motion: reduce) {
  .adm *, .adm-portal * {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }
  .adm-skel { background: var(--bg-2); }
}
