/* ============================================================================
   AI Bridge — application layer
   Shell, panels, data views. One spacing scale (4px), one radius scale, one
   type scale. Chrome stays neutral; colour is reserved for status and for the
   validated categorical/sequential ramps used by the charts.
   ========================================================================== */

:root {
  color-scheme: light;
  --bg: #f4f4f2;
  --surface: #ffffff;
  --surface-2: #f7f7f5;
  --surface-3: #eeeeeb;
  --surface-sunken: #fafaf8;
  --ink: #161614;
  --ink-soft: #3d3d39;
  --muted: #5c5c57;
  --faint: #6e6e68;
  --line: #e4e4de;
  --line-2: #d0d0c8;
  --hairline: rgba(22, 22, 20, .09);
  --accent: #161614;
  --accent-soft: rgba(22, 22, 20, .06);
  --selection: rgba(22, 22, 20, .07);
  --selection-hover: rgba(22, 22, 20, .04);
  --focus-ring: #2a78d6;
  --good: #2c6a4c;
  --good-soft: rgba(44, 106, 76, .11);
  --warn: #85560f;
  --warn-soft: rgba(133, 86, 15, .12);
  --red: #a3352f;
  --red-soft: rgba(163, 53, 47, .1);
  --bad: var(--red);
  --blue: var(--accent);
  --blue-soft: var(--accent-soft);
  --data-1: #2a78d6;
  --data-2: #eb6834;
  --data-3: #1baf7a;
  --data-4: #eda100;
  --data-5: #e87ba4;
  --data-6: #4a3aa7;
  --data-line: #1c5cab;
  --data-line-2: #4d97e2;
  --data-grid: rgba(22, 22, 20, .09);
  --data-axis: #6e6e68;
  --hm-low: #edece8;
  --hm-high: #0d366b;
  --r-xl: 24px;
  --r-lg: 20px;
  --r-md: 14px;
  --r-sm: 10px;
  --r-pill: 999px;
  --ctl-h: 36px;
  --ctl-h-sm: 30px;
  --ctl-h-xs: 26px;
  --shadow: 0 1px 1px rgba(20, 20, 18, .02), 0 4px 14px rgba(20, 20, 18, .035);
  --sidebar-shadow: 0 1px 2px rgba(20, 20, 18, .04), 0 12px 32px rgba(20, 20, 18, .07);
  --shadow-raised: 0 1px 1px rgba(20, 20, 18, .03), 0 16px 40px rgba(20, 20, 18, .09);
  --motion-fast: 110ms;
  --motion-standard: 170ms;
  --motion-enter: 240ms;
  --motion-slow: 460ms;
  --motion-ease: cubic-bezier(.2, .8, .2, 1);
  --motion-ease-standard: cubic-bezier(.4, 0, .2, 1);
  --motion-ease-emphasis: cubic-bezier(.32, .96, .35, 1);
  --motion-distance: 6px;
  --sidebar-w: 244px;
  /* The sidebar floats over the page like a macOS source list, so the shell
     reserves its width plus the gutter on both of its sides. */
  --sidebar-inset: 12px;
  --sidebar-gutter: calc(var(--sidebar-w) + var(--sidebar-inset) * 2);
  --sidebar-radius: 18px;
  --sidebar-surface: rgba(250, 250, 248, .94);
  /* The floating toolbar is translucent while it rests over the page gutter,
     and near-opaque once content starts sliding underneath it — 18% of a
     chart ghosting through a page header reads as a rendering fault. */
  --toolbar-surface: rgba(255, 255, 255, .82);
  --toolbar-surface-stuck: rgba(255, 255, 255, .97);
  --toolbar-top: 16px;
  /* One rhythm for the whole page: panels are separated by --space-panel, and
     everything inside a panel is spaced on the same 4px scale. */
  --space-panel: 14px;
  --space-panel-pad: 22px;
  --space-block: 16px;
}

[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0a0a09;
  --surface: #171716;
  --surface-2: #1f1f1d;
  --surface-3: #2b2b28;
  --surface-sunken: #121211;
  --ink: #f4f4f0;
  --ink-soft: #d6d6cf;
  --muted: #adada6;
  --faint: #98988f;
  --line: #302f2d;
  --line-2: #403f3b;
  --hairline: rgba(255, 255, 255, .08);
  --accent: #f2f2ee;
  --accent-soft: rgba(255, 255, 255, .07);
  --selection: rgba(255, 255, 255, .08);
  --selection-hover: rgba(255, 255, 255, .05);
  --focus-ring: #6da7ec;
  --good: #74c095;
  --good-soft: rgba(116, 192, 149, .15);
  --warn: #dbab63;
  --warn-soft: rgba(219, 171, 99, .15);
  --red: #e88b83;
  --red-soft: rgba(232, 139, 131, .15);
  --data-1: #4b93e8;
  --data-2: #ef7643;
  --data-3: #2cc08c;
  --data-4: #e0a92f;
  --data-5: #ef8bb0;
  --data-6: #9d92f0;
  --data-line: #6fb0ec;
  --data-line-2: #3d7fc9;
  --data-grid: rgba(255, 255, 255, .09);
  --data-axis: #98988f;
  --hm-low: #201f1e;
  --hm-high: #a9cef8;
  --shadow: 0 1px 0 rgba(255, 255, 255, .03) inset, 0 8px 24px rgba(0, 0, 0, .4);
  --sidebar-shadow: 0 1px 0 rgba(255, 255, 255, .03) inset, 0 16px 40px rgba(0, 0, 0, .42);
  --shadow-raised: 0 1px 0 rgba(255, 255, 255, .04) inset, 0 20px 48px rgba(0, 0, 0, .55);
  --sidebar-surface: rgba(19, 19, 18, .94);
  --toolbar-surface: rgba(23, 23, 22, .84);
  --toolbar-surface-stuck: rgba(24, 24, 23, .97);
}

body {
  overflow-x: hidden;
  transition-property: background-color, color;
  transition-duration: var(--motion-standard);
  transition-timing-function: var(--motion-ease-standard);
}

body.sidebar-open,
body.modal-open {
  overflow: hidden;
}

button,
a,
input,
select,
textarea {
  -webkit-tap-highlight-color: transparent;
}

/* ══ shell ═══════════════════════════════════════════════════════════════ */
.admin-shell {
  min-height: 100vh;
}

.admin-workspace {
  min-height: 100vh;
  margin-left: var(--sidebar-gutter);
}

.workspace-main {
  /* The gutter is a variable because the sticky toolbar has to paint a strip
     of page background exactly as wide as the content column behind itself. */
  --page-gutter: 32px;
  display: none;
  max-width: 1440px;
  margin: 0 auto;
  padding: 0 var(--page-gutter) 88px;
}

.workspace-main.on {
  display: block;
}

/* ══ sidebar ═════════════════════════════════════════════════════════════ */
/* A detached, rounded panel floating over the page rather than a full-height
   column welded to the window edge. */
.admin-sidebar {
  position: fixed;
  inset: var(--sidebar-inset) auto var(--sidebar-inset) var(--sidebar-inset);
  z-index: 55;
  display: flex;
  flex-direction: column;
  width: var(--sidebar-w);
  padding: 14px 10px 12px;
  overflow-y: auto;
  overscroll-behavior: contain;
  border: 1px solid var(--hairline);
  border-radius: var(--sidebar-radius);
  background: var(--sidebar-surface);
  box-shadow: var(--sidebar-shadow);
  backdrop-filter: blur(20px) saturate(130%);
  -webkit-backdrop-filter: blur(20px) saturate(130%);
  scrollbar-width: thin;
}

.sidebar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-height: 40px;
  padding: 0 6px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.mark,
[data-theme="dark"] .mark {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  border: 0;
  border-radius: 9px;
  background: var(--ink);
  color: var(--surface);
  box-shadow: none;
}

.mark svg {
  width: 14px;
  height: 14px;
}

.wordmark {
  display: block;
  color: var(--ink);
  font-size: 13.5px;
  font-weight: 650;
  letter-spacing: -.02em;
  line-height: 1.2;
}

.brand .sub {
  display: block;
  margin: 0;
  color: var(--faint);
  font-size: 10.5px;
  text-transform: none;
}

.sidebar-close {
  display: none;
  place-items: center;
  width: 32px;
  height: 32px;
  border: 0;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--muted);
  font-size: 18px;
  cursor: pointer;
}

/* command palette trigger ------------------------------------------------ */
/* The palette is the fastest route to anything on the page, so it gets a
   visible affordance instead of living only behind a shortcut nobody guesses. */
.cmdk-trigger {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  height: var(--ctl-h);
  margin-top: 14px;
  padding: 0 8px 0 11px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--faint);
  font-size: 12.5px;
  text-align: left;
  cursor: pointer;
  transition-property: color, border-color, background-color;
  transition-duration: var(--motion-standard);
  transition-timing-function: var(--motion-ease-standard);
}

.cmdk-trigger:hover {
  border-color: var(--line-2);
  color: var(--muted);
}

.cmdk-trigger .ui-icon {
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
}

.cmdk-trigger span {
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

kbd,
.cmdk-hint {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border: 1px solid var(--line);
  border-radius: 5px;
  background: var(--surface-2);
  color: var(--faint);
  font-family: var(--sans);
  font-size: 10.5px;
  font-weight: 600;
  line-height: 1;
}

body:not(.is-authed) .cmdk-trigger {
  display: none;
}

/* nav ------------------------------------------------------------------- */
.admin-tabs-bar {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 22px 0 0;
  padding: 0;
  border: 0;
  background: transparent;
  overflow: visible;
}

/* The selected pill is a single element that travels between the items, so
   switching sections reads as one continuous move rather than one panel
   switching off and another switching on. */
.nav-indicator {
  position: absolute;
  z-index: 0;
  top: 0;
  left: 0;
  width: var(--nav-w, 0);
  height: var(--nav-h, 0);
  border-radius: var(--r-sm);
  background: var(--selection);
  opacity: 0;
  pointer-events: none;
  transform: translate3d(0, var(--nav-y, 0), 0);
  transition-property: transform, height, width, opacity;
  transition-duration: 300ms;
  transition-timing-function: cubic-bezier(.22, 1, .36, 1);
}

.nav-indicator.is-on {
  opacity: 1;
}

.nav-indicator.is-placing {
  transition: none;
}

.sidebar-section-label {
  margin: 0 8px 8px;
  color: var(--faint);
  font-size: 9.5px;
  font-weight: 650;
  letter-spacing: .11em;
  text-transform: uppercase;
}

.tab-btn {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 20px 1fr;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 38px;
  padding: 8px 12px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--muted);
  font-size: 13px;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  transition-property: color, background-color;
  transition-duration: var(--motion-standard);
  transition-timing-function: var(--motion-ease-standard);
}

/* No edge rail: the panel is detached from the window, so an indicator hung
   off its left side would float in the gutter. The filled pill carries the
   active state on its own, the way a macOS source list does. */
.tab-btn:hover {
  color: var(--ink);
  background: var(--selection-hover);
}

.tab-btn.active {
  color: var(--ink);
  background: var(--selection);
  font-weight: 600;
}

/* Once the travelling pill exists it owns the fill; the painted state above
   stays as the no-script fallback. */
.admin-tabs-bar.has-indicator .tab-btn.active {
  background: transparent;
}

.tab-icon {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  color: var(--faint);
  transition-property: color, transform;
  transition-duration: var(--motion-standard);
  transition-timing-function: var(--motion-ease-emphasis);
}

.tab-btn:hover .tab-icon {
  color: var(--muted);
  transform: scale(1.08);
}

.tab-btn.active .tab-icon {
  color: var(--ink);
}

.tab-btn:active {
  transform: scale(.985);
}

/* system pulse ----------------------------------------------------------- */
/* The nav is four items long and the footer is pinned to the bottom, which left
   the middle of the panel empty on every screen taller than a laptop. It now
   carries the health figures that were otherwise only readable by navigating
   back to Overview — the same three an operator glances at between tasks. */
.sidebar-pulse {
  margin-top: 22px;
  padding: 11px 11px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
}

.sidebar-pulse[hidden] {
  display: none;
}

.pulse-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}

.pulse-head .sidebar-section-label {
  margin: 0;
  padding: 0;
}

.pulse-head .sec-note {
  font-size: 10px;
}

.pulse-list {
  display: grid;
  gap: 7px;
  margin: 0;
}

.pulse-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}

.pulse-row dt {
  color: var(--faint);
  font-size: 11px;
}

.pulse-row dd {
  margin: 0;
  color: var(--ink);
  font-size: 12.5px;
  font-weight: 620;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
}

/* A sparkline is the one thing here that says whether a number is going
   anywhere; it is deliberately unlabelled, since the row above names it. */
.pulse-spark {
  display: block;
  width: 100%;
  height: 26px;
  margin-top: 9px;
  overflow: visible;
}

.pulse-spark path {
  fill: none;
  stroke: var(--data-line);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

.pulse-spark .pulse-spark-area {
  fill: var(--accent-soft);
  stroke: none;
}

/* footer ---------------------------------------------------------------- */
.sidebar-foot {
  display: grid;
  gap: 10px;
  margin-top: auto;
  padding-top: 14px;
}

/* Nothing in the footer has a value before sign-in, so it stays out of the
   way rather than showing a column of em dashes. */
body:not(.is-authed) .sidebar-status,
body:not(.is-authed) .sidebar-pulse,
body:not(.is-authed) .account-copy {
  display: none;
}

.sidebar-status {
  display: grid;
  gap: 5px;
  padding: 10px 11px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
}

.sidebar-status-row {
  display: flex;
  align-items: center;
  gap: 7px;
  color: var(--muted);
  font-size: 11.5px;
  font-weight: 550;
}

.live-dot {
  width: 6px;
  height: 6px;
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--good);
  box-shadow: 0 0 0 3px var(--good-soft);
}

body.is-paused .live-dot {
  background: var(--faint);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.status-txt {
  display: block;
  color: var(--faint);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  line-height: 1.45;
}

.status-txt .when {
  color: var(--muted);
}

.sidebar-account {
  display: grid;
  gap: 8px;
  padding: 10px 4px 0;
  border-top: 1px solid var(--line);
}

.account-copy {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
  color: var(--faint);
  font-size: 11px;
}

.account-copy .who {
  overflow: hidden;
  font-family: var(--mono);
  font-size: 10.5px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sidebar-actions {
  display: flex;
  align-items: center;
  gap: 2px;
}

.sidebar-actions .icon-btn {
  width: 30px;
  height: 30px;
}

/* mobile chrome --------------------------------------------------------- */
.mobile-header {
  display: none;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--hairline);
  border-radius: 0 0 var(--r-md) var(--r-md);
  background: var(--toolbar-surface);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
}

.mobile-menu-btn {
  display: grid;
  align-content: center;
  gap: 4px;
  width: 34px;
  height: 34px;
  padding: 0 8px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface);
  cursor: pointer;
}

.mobile-menu-btn span {
  display: block;
  height: 1.5px;
  border-radius: 2px;
  background: var(--ink);
}

.mobile-brand {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-right: auto;
  color: var(--ink);
  font-size: 13px;
  font-weight: 650;
}

.mobile-brand .mark {
  width: 24px;
  height: 24px;
  border-radius: 7px;
}

.mobile-brand .mark svg {
  width: 12px;
  height: 12px;
}

.sidebar-backdrop {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: none;
  background: rgba(12, 12, 11, .38);
}

/* ══ page header ═════════════════════════════════════════════════════════ */
/* A floating toolbar that condenses as the page scrolls: at rest it carries
   the page title and its description, and once content starts passing beneath
   it the description collapses and the title steps down, so the bar shrinks to
   a thin control strip instead of parking a full heading block over the data.

   The sticky element is the dock, not the bar. The dock holds the bar's
   resting height for the whole scroll, so condensing changes nothing in the
   page flow — otherwise every scroll past the threshold would yank the content
   below up by forty pixels, and near the threshold the shorter page could
   push the bar back out of its stuck state and flip it back and forth. */
.page-title-dock {
  position: sticky;
  top: var(--toolbar-top);
  z-index: 30;
  min-height: var(--toolbar-rest-h, auto);
  margin: 16px 0 var(--space-panel);
  pointer-events: none;
}

.page-title {
  position: relative;
  pointer-events: auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px 16px;
  flex-wrap: wrap;
  padding: 14px 16px 14px 22px;
  border: 1px solid var(--hairline);
  border-radius: var(--r-lg);
  background: var(--toolbar-surface);
  box-shadow: var(--shadow);
  backdrop-filter: blur(22px) saturate(160%);
  -webkit-backdrop-filter: blur(22px) saturate(160%);
  transition-property: padding, border-radius, background-color, box-shadow, border-color;
  transition-duration: var(--motion-enter);
  transition-timing-function: var(--motion-ease-standard);
}

/* The bar floats gracefully with backdrop-filter blur */
.page-title::before {
  display: none;
}

/* set by the workspace scroll listener once the bar detaches from the top */
.page-title.is-stuck {
  padding: 10px 14px 10px 18px;
  border-radius: var(--r-md);
  border-color: var(--line);
  background: var(--toolbar-surface-stuck);
  box-shadow: var(--shadow-raised);
}

.page-heading {
  min-width: 0;
}

.page-eyebrow {
  display: none;
}

.page-heading.is-changing {
  animation: page-heading-fade 280ms cubic-bezier(.22, 1, .36, 1) both;
}

@keyframes page-heading-fade {
  0% {
    opacity: 0.2;
    transform: translateY(4px);
    filter: blur(1px);
  }

  100% {
    opacity: 1;
    transform: none;
    filter: blur(0);
  }
}

.page-title h1 {
  margin: 0;
  color: var(--ink);
  font-size: 22px;
  font-weight: 650;
  letter-spacing: -.026em;
  line-height: 1.2;
  outline: none;
  transition: font-size var(--motion-enter) var(--motion-ease-standard);
}

.page-title.is-stuck h1 {
  font-size: 17px;
}

.page-description {
  overflow: hidden;
  max-height: 24px;
  margin: 3px 0 0;
  padding: 0;
  color: var(--faint);
  font-size: 13px;
  line-height: 1.4;
  transition-property: max-height, opacity, margin-top;
  transition-duration: var(--motion-enter);
  transition-timing-function: var(--motion-ease-standard);
}

.page-title.is-stuck .page-description {
  max-height: 0;
  margin-top: 0;
  opacity: 0;
}

.page-title .who {
  display: none;
}

.title-side {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.plan-pills {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.plan-pills .pill {
  background: var(--surface-2);
  border: 1px solid var(--line);
}

/* The subscription pills are context, not a call to action — the page's one
   solid fill belongs to real buttons, so nothing here takes it. */
.plan-pills .pill.solid {
  background: var(--surface-2);
  color: var(--muted);
}

/* control cluster --------------------------------------------------------- */
/* Everything that governs "how fresh is this page" sits in one bordered group
   with hairline separators, instead of three nested pill shapes. */
.toolbar-cluster {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 38px;
  padding: 0 4px 0 3px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--surface);
  transition: border-color var(--motion-standard) var(--motion-ease-standard);
}

.toolbar-cluster:hover {
  border-color: var(--line-2);
}

.cluster-sep {
  flex: 0 0 auto;
  width: 1px;
  height: 18px;
  background: var(--line);
}

/* The freshness readout used to live only in the sidebar footer, three
   hundred pixels away from the control that governs it. */
.live-readout {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-left: 11px;
}

.live-copy {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
}

.live-copy b {
  color: var(--ink);
  font-size: 11.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.live-copy em {
  color: var(--faint);
  font-size: 10px;
  font-style: normal;
  white-space: nowrap;
}

.live-readout .live-dot {
  position: relative;
}

/* A slow expanding ring: enough to say "this page is still listening" without
   becoming a blinking element in the corner of the eye. */
.live-readout .live-dot::after {
  content: "";
  position: absolute;
  inset: -3px;
  border: 1px solid var(--good);
  border-radius: 50%;
  opacity: 0;
  animation: live-pulse 2.8s var(--motion-ease-standard) infinite;
}

body.is-paused .live-readout .live-dot::after {
  animation: none;
}

@keyframes live-pulse {
  0% {
    opacity: .55;
    transform: scale(.75);
  }

  70%,
  100% {
    opacity: 0;
    transform: scale(2.1);
  }
}

.cluster-switch {
  font-size: 12px;
  font-weight: 550;
}

.toolbar-cluster .seg {
  border: 0;
  background: var(--surface-2);
}

.refresh-icon {
  display: grid;
  place-items: center;
  width: var(--ctl-h-sm);
  height: var(--ctl-h-sm);
  border: 0;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--muted);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  transition-property: color, background-color, transform;
  transition-duration: var(--motion-standard);
  transition-timing-function: var(--motion-ease-standard);
}

.refresh-icon:hover {
  color: var(--ink);
  background: var(--surface-3);
}

.refresh-icon .ui-icon {
  width: 15px;
  height: 15px;
}

/* The icon turns for exactly as long as the request is in flight, so the
   control itself reports the fetch rather than a separate spinner. */
body.is-fetching .refresh-icon .ui-icon {
  animation: spin .9s linear infinite;
}

/* ══ load bar ════════════════════════════════════════════════════════════ */
.load-bar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 75;
  height: 2px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--motion-standard) var(--motion-ease-standard);
}

body.is-fetching .load-bar {
  opacity: 1;
}

.load-bar span {
  display: block;
  width: 40%;
  height: 100%;
  border-radius: var(--r-pill);
  background: linear-gradient(90deg, transparent, var(--data-line), transparent);
  animation: load-sweep 1.1s var(--motion-ease-standard) infinite;
}

@keyframes load-sweep {
  from {
    transform: translateX(-100%);
  }

  to {
    transform: translateX(350%);
  }
}

/* ══ command palette ═════════════════════════════════════════════════════ */
.cmdk-veil {
  position: fixed;
  inset: 0;
  z-index: 88;
  display: none;
  justify-content: center;
  /* Anchored high rather than centred: the list grows downward, so the input
     stays under the eye instead of drifting as results change. */
  align-items: flex-start;
  padding: 12vh 20px 20px;
  background: rgba(12, 12, 11, .4);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}

.cmdk-veil.on {
  display: flex;
  animation: veil-in var(--motion-standard) var(--motion-ease-standard) both;
}

.cmdk-veil.is-closing {
  display: flex;
  pointer-events: none;
  animation: veil-out 130ms var(--motion-ease-standard) both;
}

.cmdk {
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 620px;
  max-height: min(64vh, 560px);
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  background: var(--surface);
  box-shadow: var(--shadow-raised);
}

.cmdk-veil.on .cmdk {
  animation: admin-modal-enter var(--motion-enter) var(--motion-ease) both;
}

.cmdk-veil.is-closing .cmdk {
  animation: admin-modal-exit 130ms var(--motion-ease-standard) both;
}

.cmdk-field {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;
  padding: 14px 14px 14px 18px;
  border-bottom: 1px solid var(--line);
}

.cmdk-field .ui-icon {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  color: var(--faint);
}

.cmdk-field input {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  background: none;
  color: var(--ink);
  font-size: 15px;
  outline: none;
}

.cmdk-field input::placeholder {
  color: var(--faint);
}

.cmdk-close {
  flex: 0 0 auto;
  height: 22px;
  padding: 0 9px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface-2);
  color: var(--faint);
  font-size: 10.5px;
  font-weight: 600;
  cursor: pointer;
}

.cmdk-close:hover {
  color: var(--ink);
}

.cmdk-list {
  flex: 1 1 auto;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 8px;
}

.cmdk-group {
  margin: 10px 8px 4px;
  color: var(--faint);
  font-size: 9.5px;
  font-weight: 650;
  letter-spacing: .11em;
  text-transform: uppercase;
}

.cmdk-group:first-child {
  margin-top: 2px;
}

.cmdk-item {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr) auto;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 9px 10px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--ink);
  font-size: 13.5px;
  text-align: left;
  cursor: pointer;
}

.cmdk-item .ui-icon {
  width: 16px;
  height: 16px;
  color: var(--faint);
}

/* Selection follows the keyboard, so hover must not paint a second one —
   pointer movement sets the active index instead. */
.cmdk-item.is-active {
  background: var(--selection);
}

.cmdk-item.is-active .ui-icon {
  color: var(--ink);
}

.cmdk-item-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cmdk-item-label mark {
  background: none;
  color: inherit;
  font-weight: 650;
}

.cmdk-item-hint {
  color: var(--faint);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.cmdk-empty {
  padding: 26px 12px;
  color: var(--faint);
  font-size: 13px;
  text-align: center;
}

.cmdk-foot {
  display: flex;
  align-items: center;
  gap: 16px;
  flex: 0 0 auto;
  padding: 9px 16px;
  border-top: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--faint);
  font-size: 11px;
}

.cmdk-foot span {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.cmdk-foot span:last-child {
  margin-left: auto;
  font-variant-numeric: tabular-nums;
}

/* ══ bulk selection bar ══════════════════════════════════════════════════ */
/* Floats over the page instead of pushing the table down: the selection can be
   made anywhere in a long list and the actions stay in the same place. */
.bulk-bar {
  position: fixed;
  z-index: 60;
  left: calc(50% + var(--sidebar-gutter) / 2);
  bottom: 22px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px 8px 16px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-pill);
  background: var(--surface);
  box-shadow: var(--shadow-raised);
  transform: translateX(-50%);
  animation: bulk-in var(--motion-enter) var(--motion-ease-emphasis) both;
}

.bulk-bar[hidden] {
  display: none;
}

@keyframes bulk-in {
  from {
    opacity: 0;
    transform: translate(-50%, 12px);
  }
}

.bulk-count {
  color: var(--ink);
  font-size: 13px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.bulk-sep {
  width: 1px;
  height: 18px;
  background: var(--line);
}

.kcheck,
.kcheck-head {
  width: 34px;
  padding-right: 0 !important;
}

.kcheck input,
.kcheck-head input {
  width: 15px;
  height: 15px;
  margin: 0;
  accent-color: var(--ink);
  cursor: pointer;
}

.ktbl tbody tr.is-selected td {
  background: var(--selection-hover);
}

#keysTable .ktbl tbody tr.is-selected td:last-child {
  background: var(--selection-hover);
}

/* ══ toasts ══════════════════════════════════════════════════════════════ */
/* Row actions used to succeed in silence: the table simply re-rendered and the
   admin had to infer that the click did anything. */
.toast-stack {
  position: fixed;
  z-index: 85;
  right: 18px;
  bottom: 18px;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
  max-width: min(360px, calc(100vw - 36px));
  pointer-events: none;
}

.toast {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  max-width: 100%;
  padding: 11px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  box-shadow: var(--shadow-raised);
  color: var(--ink);
  font-size: 12.5px;
  line-height: 1.45;
  pointer-events: auto;
  animation: toast-in var(--motion-enter) var(--motion-ease-emphasis) both;
}

.toast.is-leaving {
  animation: toast-out var(--motion-standard) var(--motion-ease-standard) both;
}

.toast-dot {
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  margin-top: 5px;
  border-radius: 50%;
  background: var(--good);
  box-shadow: 0 0 0 3px var(--good-soft);
}

.toast.err .toast-dot {
  background: var(--red);
  box-shadow: 0 0 0 3px var(--red-soft);
}

.toast.warn .toast-dot {
  background: var(--warn);
  box-shadow: 0 0 0 3px var(--warn-soft);
}

.toast.info .toast-dot {
  background: var(--faint);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateY(10px) scale(.97);
  }
}

@keyframes toast-out {
  to {
    opacity: 0;
    transform: translateY(4px) scale(.98);
  }
}

/* ══ panes ═══════════════════════════════════════════════════════════════ */
.view {
  display: none;
}

.view.on {
  display: block;
}

.tab-pane[hidden] {
  display: none !important;
}

.tab-pane {
  display: flex;
  flex-direction: column;
  gap: var(--space-panel);
}

.tab-pane.active:not([hidden]) {
  display: flex;
  animation: admin-pane-glide-in 340ms cubic-bezier(.22, 1, .36, 1) both;
  will-change: opacity, transform, filter;
}

.tab-pane.logs-page.active:not([hidden]),
.tab-pane.analytics-page.active:not([hidden]) {
  display: flex;
}

@keyframes admin-pane-glide-in {
  0% {
    opacity: 0;
    transform: translateY(10px);
    filter: blur(1.5px);
  }

  100% {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0);
  }
}

@keyframes admin-pane-enter {
  from {
    opacity: 0;
    transform: translateY(10px);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes admin-modal-enter {
  from {
    opacity: 0;
    transform: translateY(8px) scale(.99);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

/* ══ cards & panels ══════════════════════════════════════════════════════ */
.card,
.stat {
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  /* Two layers: the drop shadow separates the panel from the page in light,
     the inset edge does the same job in dark, where a shadow on a near-black
     background is invisible. Each token is a no-op in the other theme.
     The fallbacks matter: this sheet is also loaded by the client dashboard,
     which brings its own token set and does not define the pair — without them
     the whole declaration would be invalid and every card would lose its lift. */
  box-shadow: var(--panel-edge, 0 0 0 0 transparent), var(--panel-shadow, var(--shadow));
  transition-property: border-color, box-shadow;
  transition-duration: var(--motion-standard);
  transition-timing-function: var(--motion-ease-standard);
}

/* Panels are large and always visible, so they acknowledge the pointer with a
   border only. Lifting a full-width section on hover would make the page
   twitch as the cursor crosses it. */
.card:hover {
  border-color: var(--line-2);
}

.panel {
  margin: 0;
  padding: 20px var(--space-panel-pad) 22px;
}

/* ── tiles ────────────────────────────────────────────────────────────── */
/* Every inner block on every page — metric, insight, preset, model, provider,
   chart, log summary — is the same component with the same resting surface and
   the same response to the pointer. Before, each page invented its own. */
.metric,
.insight-card,
.preset-card,
.chart-block,
.provider-switch-card,
.hrow,
.routing-template-card,
.model-manager-card,
.log-summary-card,
.analytics-empty,
.provider-key-row,
.cooldown-item {
  transition-property: border-color, box-shadow, transform, background-color;
  transition-duration: var(--motion-standard);
  transition-timing-function: var(--motion-ease-standard);
}

.metric:hover,
.insight-card:hover,
.preset-card:hover,
.chart-block:hover,
.provider-switch-card:hover,
.hrow:hover,
.routing-template-card:hover,
.model-manager-card:hover,
.log-summary-card:hover,
.provider-key-row:hover {
  border-color: var(--line-2);
  box-shadow: var(--shadow);
  transform: translateY(-1px);
}

.flush-panel {
  padding-bottom: 14px;
}

.spaced-panel {
  padding-top: 20px;
}

.sec-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px 20px;
  flex-wrap: wrap;
  margin-bottom: var(--space-block);
}

.sec-head>div {
  min-width: 0;
}

.section-copy,
.models-section-copy,
.logs-section-copy {
  max-width: 62ch;
  margin-top: 4px;
  color: var(--faint);
  font-size: 13px;
  line-height: 1.5;
}

.panel-divider {
  height: 1px;
  margin: 20px 0;
  border: 0;
  background: var(--line);
}

.hm-controls {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.grid2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-panel);
}

.grid3 {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-panel);
}

.grid2>.card,
.grid3>.card {
  min-width: 0;
}

/* ══ readouts ════════════════════════════════════════════════════════════ */
.split {
  display: grid;
  grid-template-columns: minmax(0, 272px) minmax(0, 1fr);
  gap: 28px;
  align-items: center;
}

.readout-lg .eyebrow {
  display: block;
  margin-bottom: 7px;
  color: var(--faint);
  font-size: 12.5px;
  font-weight: 550;
}

.readout-lg .big {
  color: var(--ink);
  font-size: 44px;
  font-weight: 620;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.042em;
  line-height: 1.05;
}

.kpis {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 18px;
  padding-left: 28px;
  border-left: 1px solid var(--line);
}

.kpi .k {
  display: block;
  color: var(--faint);
  font-size: 12px;
  font-weight: 500;
}

.kpi .v {
  display: block;
  margin-top: 4px;
  color: var(--ink);
  font-size: 19px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
}

/* metric tile — the single stat component used across every page --------- */
.metrics {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
}

.metric {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
  padding: 15px 16px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
}

.metric .k {
  color: var(--faint);
  font-size: 12px;
  font-weight: 550;
}

.metric .v {
  color: var(--ink);
  font-size: 22px;
  font-weight: 620;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.03em;
  line-height: 1.15;
  overflow-wrap: anywhere;
}

.metric .v.long {
  font-size: 16px;
  letter-spacing: -.015em;
}

.metric .v small {
  margin-left: 3px;
  color: var(--faint);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0;
}

.metric.good .v {
  color: var(--good);
}

.metric.warn .v {
  color: var(--warn);
}

.metric.danger .v {
  color: var(--red);
}

.metric-sub {
  color: var(--faint);
  font-size: 11.5px;
}

/* Column counts follow the number of tiles each block actually renders, so a
   metric row never ends in an orphan cell. */
#perfMetrics {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

#wowMetrics {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.delta {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  color: var(--good);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
}

.delta.down {
  color: var(--red);
}

.delta.flat {
  color: var(--faint);
}

.delta i {
  font-style: normal;
}

.delta span {
  color: var(--faint);
}

/* stat (client dashboard) ----------------------------------------------- */
.stat {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  padding: 18px 20px;
}

.stat .label {
  color: var(--faint);
  font-size: 12px;
  font-weight: 550;
}

.stat .val {
  color: var(--ink);
  font-size: 26px;
  font-weight: 620;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.035em;
  overflow-wrap: anywhere;
}

.stat .val.long {
  font-size: 19px;
}

.stat.danger .val {
  color: var(--red);
}

.stat .sub {
  color: var(--faint);
  font-size: 12px;
}

/* ══ bars & rankings ═════════════════════════════════════════════════════ */
.bar-track {
  height: 6px;
  border-radius: var(--r-pill);
  background: var(--surface-3);
  overflow: hidden;
}

.bar-fill {
  display: block;
  height: 100%;
  border-radius: var(--r-pill);
  background: var(--data-line);
  width: var(--meter-value, 100%);
}

/* Entrance animations are scoped to `.is-fresh`, a class the renderer holds on
   a pane for about a second the first time it is filled. A live dashboard
   repaints itself every minute; replaying every meter, ring and line on each
   of those repaints would turn a quiet page into a slot machine.

   A keyframe list with only a `from` resolves its end state from the element's
   own computed width, so one rule animates every meter on the page whether its
   target arrives as a custom property or as an inline width. */
.tab-pane.is-fresh .bar-fill {
  animation: meter-grow var(--motion-slow) var(--motion-ease) both;
}

@keyframes meter-grow {
  from {
    width: 0;
  }
}

.bar-fill.soft {
  background: var(--data-line-2);
}

.bar-fill.warn {
  background: var(--warn);
}

.bar-fill.bad {
  background: var(--red);
}

.rank {
  display: flex;
  flex-direction: column;
}

.rank-row {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr);
  gap: 14px;
  padding: 13px 0;
  border-bottom: 1px solid var(--line);
}

.rank-row:last-child {
  border-bottom: 0;
  padding-bottom: 2px;
}

.rank-row .no {
  padding-top: 2px;
  color: var(--faint);
  font-family: var(--mono);
  font-size: 11px;
}

.rank-row .top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  font-size: 13px;
}

.rank-row .nm {
  overflow: hidden;
  color: var(--ink);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rank-row .amt {
  color: var(--muted);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.rank-row .amt b {
  color: var(--ink);
  font-weight: 600;
}

.rank-row .bar-track {
  margin-top: 8px;
}

.rank-row .meta {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-top: 6px;
  color: var(--faint);
  font-family: var(--mono);
  font-size: 10.5px;
}

/* dual (p50/p95, error rate) -------------------------------------------- */
.dual {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.dual .d-row .top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  font-size: 13px;
}

.dual .d-row .top .nm {
  overflow: hidden;
  color: var(--ink);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.dual .d-row .lab {
  color: var(--faint);
  font-family: var(--mono);
  font-size: 10.5px;
  white-space: nowrap;
}

.dual .d-line {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr);
  align-items: center;
  gap: 8px;
  margin-top: 6px;
}

.err-lab {
  color: var(--muted);
}

/* quota rows ------------------------------------------------------------ */
.quota-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.quota-rows {
  display: flex;
  flex-direction: column;
}

.qrow {
  display: grid;
  grid-template-columns: minmax(0, 190px) minmax(0, 1fr) auto 58px;
  align-items: center;
  gap: 16px;
  padding: 11px 8px;
  margin: 0 -8px;
  border-radius: var(--r-sm);
  transition: background-color var(--motion-fast) var(--motion-ease-standard);
}

.qrow:hover {
  background: var(--selection-hover);
}

.qrow+.qrow {
  box-shadow: 0 -1px 0 var(--line);
}

.qrow .ql {
  overflow: hidden;
  color: var(--ink);
  font-size: 13.5px;
  font-weight: 500;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.qrow .qt {
  display: block;
  height: 8px;
  border-radius: var(--r-pill);
  background: var(--surface-3);
  overflow: hidden;
}

.qrow .qf {
  display: block;
  height: 100%;
  border-radius: var(--r-pill);
  background: var(--data-line);
}

.tab-pane.is-fresh .qrow .qf {
  animation: meter-grow var(--motion-slow) var(--motion-ease) both;
}

.qrow[data-tone="warn"] .qf {
  background: var(--warn);
}

.qrow[data-tone="bad"] .qf {
  background: var(--red);
}

.qrow[data-tone="unlimited"] .qf {
  background: repeating-linear-gradient(90deg, var(--line-2) 0 4px, transparent 4px 8px);
}

.qrow .qv {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  color: var(--muted);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.qrow .qv b {
  color: var(--ink);
  font-weight: 600;
}

.qrow .qv i {
  font-style: normal;
}

/* The share is the row's headline number, so it gets its own aligned column
   instead of trailing the raw counts. */
.qrow .qpct {
  color: var(--ink);
  font-size: 12.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.qrow[data-tone="warn"] .qpct {
  color: var(--warn);
}

.qrow[data-tone="bad"] .qpct {
  color: var(--red);
}

.qrow[data-tone="unlimited"] .qpct {
  color: var(--faint);
  font-weight: 500;
}

/* reveal control for collapsed lists ------------------------------------- */
.list-more {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  align-self: center;
  height: var(--ctl-h-sm);
  margin-top: 4px;
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--surface-2);
  color: var(--muted);
  font: inherit;
  font-size: 12px;
  font-weight: 550;
  cursor: pointer;
  transition-property: color, background-color, border-color;
  transition-duration: var(--motion-standard);
  transition-timing-function: var(--motion-ease-standard);
}

.list-more:hover {
  border-color: var(--line-2);
  background: var(--surface-3);
  color: var(--ink);
}

.list-more-chevron {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform var(--motion-standard) var(--motion-ease-standard);
}

.list-more[aria-expanded="true"] .list-more-chevron {
  transform: rotate(180deg);
}

.rank .list-more {
  display: flex;
  width: fit-content;
  margin: 10px auto 2px;
}

/* ══ insights ════════════════════════════════════════════════════════════ */
/* 248px rather than 280px: at the common desktop width the wider track fits
   three cards and stranded the fourth alone on its own row. */
.insights-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(248px, 1fr));
  gap: 12px;
}

.insight-card {
  display: grid;
  gap: 6px;
  padding: 15px 16px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
}

.insight-icon {
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--faint);
}

.insight-card.danger .insight-icon {
  background: var(--red);
  box-shadow: 0 0 0 3px var(--red-soft);
}

.insight-card.warning .insight-icon {
  background: var(--warn);
  box-shadow: 0 0 0 3px var(--warn-soft);
}

.insight-card.success .insight-icon {
  background: var(--good);
  box-shadow: 0 0 0 3px var(--good-soft);
}

.insight-card.danger {
  border-color: color-mix(in srgb, var(--red) 34%, var(--line));
  background: var(--red-soft);
}

.insight-card.warning {
  border-color: color-mix(in srgb, var(--warn) 30%, var(--line));
  background: var(--warn-soft);
}

.insight-head {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  min-width: 0;
}

/* Four signals fit across a desktop row, which leaves each title about fifteen
   characters on one line — so the title wraps rather than ellipsing away the
   thing the card is actually reporting. The cards are grid siblings and share
   a height anyway, so the extra line costs nothing once one card needs it. */
.insight-head b {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
  color: var(--ink);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.35;
}

.insight-head .insight-icon {
  margin-top: 5px;
}

.insight-tag {
  margin-top: 2px;
  margin-left: auto;
  padding: 1px 7px;
  border-radius: var(--r-pill);
  background: var(--surface-3);
  color: var(--muted);
  font-size: 9.5px;
  font-weight: 650;
  letter-spacing: .06em;
  text-transform: uppercase;
  white-space: nowrap;
}

.insight-card.danger .insight-tag {
  background: color-mix(in srgb, var(--red) 18%, transparent);
  color: var(--red);
}

.insight-card.warning .insight-tag {
  background: color-mix(in srgb, var(--warn) 18%, transparent);
  color: var(--warn);
}

.insight-card.success .insight-tag {
  background: var(--good-soft);
  color: var(--good);
}

.insight-body {
  color: var(--muted);
  font-size: 12.5px;
  line-height: 1.5;
}

/* ══ charts — shared ═════════════════════════════════════════════════════ */
.chart-grid,
.daily-grid line,
.trend-grid line {
  stroke: var(--data-grid);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

.axis-label,
.chart-axis-label,
.daily-grid text,
.trend-grid text {
  fill: var(--data-axis);
  font-family: var(--sans);
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
}

.daily-plot-label {
  fill: var(--muted);
  font-size: 9.5px;
  font-weight: 650;
  letter-spacing: .09em;
}

/* Each plot carries its own mark in its own title, so "which series is this"
   is answered inside the plot rather than in the caption below the figure. */
.daily-legend-line {
  stroke: var(--data-line);
  stroke-width: 2.5;
  stroke-linecap: round;
}

.daily-legend-bar {
  fill: var(--data-line-2);
}

.chart-legend {
  display: flex;
  align-items: center;
  gap: 14px;
  color: var(--muted);
  font-size: 11.5px;
}

.chart-legend span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

/* The caption keys repeat the marks used in the plots — a rule for the line
   series, a block for the column series — so the legend and the chart cannot
   drift apart. */
.chart-key {
  display: inline-block;
  width: 11px;
  height: 3px;
  border-radius: 2px;
  background: var(--data-line);
}

.chart-key.request {
  width: 8px;
  height: 10px;
  border-radius: 2px;
  background: var(--data-line-2);
}

.chart-foot {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
  color: var(--faint);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
}

.chart-foot b {
  color: var(--ink);
  font-weight: 600;
}

/* daily usage — stacked small multiples, one scale per plot -------------- */
.daily-chart {
  margin: 0;
}

.daily-chart-stage {
  width: 100%;
}

#dailyChart {
  display: block;
  width: 100%;
  overflow: visible;
}

.daily-axis-left {
  fill: var(--data-axis);
}

.daily-band {
  fill: var(--surface-2);
}

.daily-series {
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

/* The series carry pathLength="1", so one dash rule draws any of them left to
   right regardless of how many days the period holds. */
.tab-pane.is-fresh .daily-series[pathLength],
.tab-pane.is-fresh .trend-line[pathLength] {
  stroke-dasharray: 1;
  animation: series-draw 900ms var(--motion-ease-standard) both;
}

@keyframes series-draw {
  from {
    stroke-dashoffset: 1;
  }

  to {
    stroke-dashoffset: 0;
  }
}

.daily-token-line {
  stroke: var(--data-line);
}

/* Columns, not a second line: requests are a count per day, and a bar reads its
   own value where a line only reads its slope. */
.daily-request-bar {
  transition: opacity var(--motion-fast) var(--motion-ease-standard);
}

.daily-request-bar.is-selected {
  fill: var(--data-line);
}

.daily-request-bars:hover .daily-request-bar {
  opacity: .55;
}

.daily-request-bars .daily-request-bar.is-selected {
  opacity: 1;
}

.tab-pane.is-fresh .daily-request-bars {
  animation: daily-bars-in var(--motion-slow) var(--motion-ease-standard) both;
  transform-origin: center bottom;
}

@keyframes daily-bars-in {
  from {
    opacity: 0;
    transform: scaleY(.4);
  }
}

/* Saturdays and Sundays, shaded behind both plots. The weekly rhythm is the
   first thing an operator checks a usage curve against. */
.daily-weekend {
  fill: var(--data-band, rgba(128, 128, 128, .05));
}

.daily-hit {
  cursor: pointer;
  outline: none;
}

.daily-hit-area {
  fill: transparent;
}

.daily-crosshair {
  stroke: var(--ink);
  stroke-width: 1;
  stroke-dasharray: 2 3;
  opacity: 0;
}

.daily-token-dot {
  opacity: 0;
  fill: var(--data-line);
  stroke: var(--surface);
  stroke-width: 2;
}

.daily-hit:hover .daily-crosshair,
.daily-hit.selected .daily-crosshair {
  opacity: .45;
}

.daily-hit:hover .daily-token-dot,
.daily-hit.selected .daily-token-dot {
  opacity: 1;
}

.daily-hit:focus-visible .daily-hit-area {
  fill: var(--selection-hover);
}

.daily-chart-caption {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px 20px;
  flex-wrap: wrap;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}

.daily-selection {
  display: flex;
  align-items: baseline;
  gap: 14px;
  flex-wrap: wrap;
  color: var(--faint);
  font-size: 12px;
}

.daily-selection time {
  color: var(--ink);
  font-weight: 600;
}

.daily-selection b {
  color: var(--ink);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* failure-rate trend ----------------------------------------------------- */
.trend-stage {
  width: 100%;
}

#recentErrChart {
  display: block;
  width: 100%;
}

.trend-line {
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

/* The line takes the tone of the window's own average, so a 0.4% failure rate
   is not painted the same red as a 40% one. */
.trend-line.trend-good {
  stroke: var(--good);
}

.trend-line.trend-warn {
  stroke: var(--warn);
}

.trend-line.trend-bad {
  stroke: var(--red);
}

.trend-dot {
  fill: var(--surface);
  stroke: currentColor;
  stroke-width: 1.8;
  color: var(--good);
}

.trend-dot.has-error {
  fill: var(--red);
  stroke: var(--surface);
  stroke-width: 1.6;
  color: var(--red);
}

/* The window average, drawn across the plot. It is a reference, not a series:
   dashed, unlabelled on the axis, and always below the curve in the stack. */
.trend-mean line {
  stroke: var(--faint);
  stroke-width: 1;
  stroke-dasharray: 5 4;
  vector-effect: non-scaling-stroke;
  opacity: .8;
}

/* The label is painted over whatever the curve happens to be doing beneath it,
   so it carries a halo of the block's own surface rather than being positioned
   around data whose shape is not known until it is drawn. */
.trend-mean text {
  fill: var(--faint);
  font-family: var(--sans);
  font-size: 10.5px;
  font-weight: 550;
  font-variant-numeric: tabular-nums;
  paint-order: stroke;
  stroke: var(--surface-2);
  stroke-width: 3.5px;
  stroke-linejoin: round;
}

.trend-hit {
  fill: transparent;
  cursor: crosshair;
}

/* donut ------------------------------------------------------------------ */
.donut-layout {
  display: grid;
  grid-template-columns: 148px minmax(0, 1fr);
  align-items: center;
  gap: 20px;
}

.donut-stage {
  position: relative;
  width: 148px;
  height: 148px;
}

.donut-stage svg {
  display: block;
  width: 100%;
  height: 100%;
}

.donut-slice {
  stroke: var(--surface);
  stroke-width: 2;
  transform-origin: 60px 60px;
  transition: opacity var(--motion-fast) var(--motion-ease-standard);
}

.tab-pane.is-fresh .donut-slice {
  animation: donut-in var(--motion-enter) var(--motion-ease-emphasis) both;
}

@keyframes donut-in {
  from {
    opacity: 0;
    transform: scale(.86);
  }
}

.donut-slice.is-muted {
  opacity: .28;
}

.donut-center {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  text-align: center;
  pointer-events: none;
}

.donut-center b {
  display: block;
  color: var(--ink);
  font-size: 21px;
  font-weight: 620;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.03em;
}

.donut-center span {
  display: block;
  max-width: 92px;
  color: var(--faint);
  font-size: 11px;
  line-height: 1.3;
  overflow-wrap: anywhere;
}

/* A slice name is longer than the word it replaces, so the readout tightens
   rather than pushing itself outside the ring. */
.donut-center.is-detail b {
  font-size: 18px;
}

.donut-center.is-detail span {
  font-size: 10px;
}

.donut-slice {
  cursor: default;
}

.donut-legend {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.donut-legend-row {
  display: grid;
  grid-template-columns: 10px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  padding: 6px 7px;
  border-radius: var(--r-sm);
  font-size: 12.5px;
  transition: background-color var(--motion-fast) var(--motion-ease-standard);
}

.donut-legend-row.is-active {
  background: var(--selection-hover);
}

.donut-swatch {
  width: 10px;
  height: 10px;
  border-radius: 3px;
}

.donut-legend-name {
  overflow: hidden;
  color: var(--ink);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.donut-legend-val {
  display: inline-flex;
  align-items: baseline;
  gap: 7px;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}

.donut-legend-val b {
  color: var(--ink);
  font-weight: 600;
}

.donut-legend-val em {
  font-style: normal;
  font-size: 11px;
}

/* chart blocks ----------------------------------------------------------- */
.chart-block {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
  padding: 17px 18px 18px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
}

.chart-block-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}

.chart-block-title {
  color: var(--ink);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -.01em;
}

.chart-block-note {
  color: var(--faint);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

/* The trend spans two donut columns: a line needs horizontal room to be read
   as a shape, and both donuts stay square next to it. */
.reliability-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
  margin-top: var(--space-block);
}

.reliability-grid #recentErrChartWrap {
  grid-column: 1 / -1;
}

.reliability-metrics {
  margin-top: 0;
}

/* Sample window: a segmented control over the eight real sample sizes. A
   slider implied a continuum that does not exist here — every stop is a
   discrete count — and made the middle values hard to land on. */
.sample-control {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.sample-label {
  color: var(--faint);
  font-size: 12px;
  font-weight: 550;
  white-space: nowrap;
}

.sample-control .seg {
  flex-wrap: wrap;
  justify-content: center;
}

.sample-control .sec-note {
  min-width: 13ch;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* A step wider than the recorded history still works — it just returns
   everything — so it is dimmed rather than disabled. */
.seg button.is-beyond:not(.active) {
  color: var(--faint);
  opacity: .62;
}

/* ══ heatmap ═════════════════════════════════════════════════════════════ */
.heatmap-figure {
  margin: 0;
}

.heatmap-wrap {
  padding-bottom: 4px;
  overflow-x: auto;
  overscroll-behavior-inline: contain;
}

#heatmap {
  display: block;
  margin: 0 auto;
}

#heatmap[aria-busy="true"] {
  opacity: .5;
}

.hm-cell {
  cursor: pointer;
  outline: none;
}

.hm-cell rect {
  transition: opacity var(--motion-fast) var(--motion-ease-standard);
}

/* Cells carry their grid index, so the map fills in as a sweep across the week
   instead of appearing all at once. */
.tab-pane.is-fresh .hm-cell rect {
  transform-box: fill-box;
  transform-origin: center;
  animation: hm-cell-in 260ms var(--motion-ease-emphasis) both;
  animation-delay: calc(var(--i, 0) * 2.2ms);
}

@keyframes hm-cell-in {
  from {
    opacity: 0;
    transform: scale(.55);
  }
}

.hm-cell.is-empty rect {
  opacity: .85;
}

.hm-cell:hover rect,
.hm-cell.selected rect {
  stroke: var(--ink);
  stroke-width: 1.5;
}

.hm-cell:focus-visible rect {
  stroke: var(--ink);
  stroke-width: 2;
}

.hm-rule {
  stroke: var(--data-grid);
  stroke-width: 1;
}

.hm-scale line {
  stroke: var(--data-grid);
}

.hm-scale text,
.hm-hour,
.hm-day,
.hm-month {
  fill: var(--faint);
  font-family: var(--sans);
  font-size: 10px;
  font-variant-numeric: tabular-nums;
}

.hm-day {
  fill: var(--muted);
  font-size: 10.5px;
}

.hm-day.is-weekend {
  fill: var(--faint);
}

.hm-month {
  fill: var(--muted);
  font-size: 10.5px;
  font-weight: 600;
}

.hm-date-number {
  fill: var(--muted);
  font-family: var(--sans);
  font-size: 9.5px;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}

.hm-date-number.on-dark {
  fill: #fff;
}

[data-theme="dark"] .hm-date-number.on-dark {
  fill: #101010;
}

.heatmap-figure figcaption {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px 20px;
  flex-wrap: wrap;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}

.hm-selection {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  color: var(--faint);
  font-size: 12px;
}

.hm-selection b {
  color: var(--ink);
  font-weight: 600;
}

.hm-selection strong {
  color: var(--ink);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.hm-caption-side {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  margin-left: auto;
}

.legend,
.hm-legend {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--faint);
  font-size: 11px;
}

.hm-legend .scale {
  display: inline-flex;
  gap: 2px;
}

.hm-legend .scale i {
  display: block;
  width: 13px;
  height: 9px;
}

.hm-legend .scale i:first-child {
  border-radius: 3px 0 0 3px;
}

.hm-legend .scale i:last-child {
  border-radius: 0 3px 3px 0;
}

.hm-foot {
  color: var(--faint);
  font-size: 11.5px;
}

.hm-foot b {
  color: var(--muted);
  font-weight: 600;
}

/* ══ tables ══════════════════════════════════════════════════════════════ */
.kfilter-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

.kfilter-group {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.ksearch {
  flex: 1 1 260px;
}

.ktable-wrap {
  margin: 0 -20px;
  padding: 0 20px;
  overflow-x: auto;
  overscroll-behavior-inline: contain;
}

/* Row actions were the first thing to fall off the right edge of a scrolling
   table, which is exactly backwards: they are the reason the row is there.
   Pinning the column keeps Top up / Edit / Block / Revoke reachable at any
   width, and the shadow says the rest of the row continues underneath. */
#keysTable .ktbl th:last-child,
#keysTable .ktbl td:last-child {
  position: sticky;
  right: 0;
  z-index: 2;
  background: var(--surface);
  box-shadow: -12px 0 12px -12px rgba(0, 0, 0, .22);
}

#keysTable .ktbl tbody tr:hover td:last-child {
  background: var(--surface-2);
}

#keysTable .ktbl thead th:last-child {
  z-index: 3;
}

table.ktbl {
  width: 100%;
  min-width: 860px;
  border-collapse: collapse;
  font-size: 13px;
}

.kaccess .ksub {
  display: block;
  max-width: 150px;
  overflow: hidden;
  margin-top: 4px;
  text-overflow: ellipsis;
}

.ktbl thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 8px 12px;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}

.ktbl td {
  padding: 10px 10px;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  background: transparent;
  vertical-align: middle;
}

.ktbl tbody tr:last-child td {
  border-bottom: 0;
}

.ktbl tbody tr {
  transition: background-color var(--motion-fast) var(--motion-ease-standard);
}

.ktbl tbody tr:hover td {
  background: var(--surface-2);
}

.kname b {
  display: block;
  color: var(--ink);
  font-weight: 600;
}

.kname .pref {
  display: block;
  margin-top: 1px;
  color: var(--faint);
  font-family: var(--mono);
  font-size: 10.5px;
}

.kbal b {
  color: var(--ink);
  font-weight: 600;
}

.kbal .lim {
  color: var(--faint);
  font-size: 11.5px;
}

.ksub {
  display: block;
  margin-top: 1px;
  color: var(--faint);
  font-size: 10.5px;
  white-space: nowrap;
}

.knum {
  color: var(--ink);
  font-family: var(--mono);
  font-size: 12px;
}

.kacts {
  display: flex;
  gap: 4px;
  justify-content: flex-end;
  flex-wrap: nowrap;
}

.kacts-head {
  text-align: right;
}

.kacts button {
  appearance: none;
  height: var(--ctl-h-xs);
  padding: 0 9px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--muted);
  font-size: 11.5px;
  font-weight: 550;
  white-space: nowrap;
  cursor: pointer;
  transition-property: color, background-color, border-color;
  transition-duration: var(--motion-standard);
  transition-timing-function: var(--motion-ease-standard);
}

.kacts button:hover {
  color: var(--ink);
  background: var(--surface-2);
}

/* Row actions repeat once per row, so none of them takes the page's primary
   fill — emphasis is carried by a solid border instead. */
.kacts button.accent {
  border-color: var(--ink);
  color: var(--ink);
}

.kacts button.accent:hover {
  background: var(--ink);
  color: var(--surface);
}

.kacts button.danger {
  color: var(--red);
}

.kacts button.danger:hover {
  background: var(--red-soft);
  border-color: transparent;
}

.kacts button[disabled] {
  opacity: .4;
  cursor: not-allowed;
}

/* overflow trigger ------------------------------------------------------- */
.kacts button.kacts-more {
  display: grid;
  place-items: center;
  width: var(--ctl-h-xs);
  padding: 0;
  border-color: transparent;
  background: transparent;
  color: var(--faint);
}

.kacts button.kacts-more svg {
  width: 16px;
  height: 16px;
  fill: currentColor;
}

.kacts button.kacts-more:hover,
.kacts button.kacts-more[aria-expanded="true"] {
  border-color: var(--line-2);
  background: var(--surface-2);
  color: var(--ink);
}

/* row overflow menu ------------------------------------------------------ */
/* Anchored to the trigger in viewport coordinates rather than nested in the
   row: the key table scrolls horizontally, and a menu inside it would be cut
   off by exactly the overflow that makes the table usable. */
.row-menu {
  position: fixed;
  z-index: 85;
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 186px;
  padding: 6px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  box-shadow: var(--shadow-raised);
  animation: row-menu-in var(--motion-fast) var(--motion-ease-standard) both;
}

.row-menu[hidden] {
  display: none;
}

@keyframes row-menu-in {
  from {
    opacity: 0;
    transform: translateY(-4px);
  }
}

.row-menu-title {
  overflow: hidden;
  padding: 5px 9px 7px;
  color: var(--faint);
  font-size: 10.5px;
  font-weight: 650;
  letter-spacing: .05em;
  text-overflow: ellipsis;
  text-transform: uppercase;
  white-space: nowrap;
}

.row-menu button {
  appearance: none;
  display: flex;
  align-items: center;
  width: 100%;
  height: 32px;
  padding: 0 9px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--ink-soft);
  font-size: 13px;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  transition-property: color, background-color;
  transition-duration: var(--motion-fast);
  transition-timing-function: var(--motion-ease-standard);
}

.row-menu button:hover:not([disabled]),
.row-menu button:focus-visible:not([disabled]) {
  background: var(--selection);
  color: var(--ink);
}

.row-menu button.is-danger {
  color: var(--red);
}

.row-menu button.is-danger:hover:not([disabled]),
.row-menu button.is-danger:focus-visible:not([disabled]) {
  background: var(--red-soft);
  color: var(--red);
}

.row-menu button[disabled] {
  opacity: .4;
  cursor: not-allowed;
}

/* The destructive item is separated rather than merely tinted: colour alone is
   not a barrier for anyone who cannot see it. */
.row-menu-sep {
  height: 1px;
  margin: 5px 4px;
  background: var(--line);
}

/* ══ key presets ═════════════════════════════════════════════════════════ */
.presets-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 10px;
}

.preset-card {
  display: flex;
  flex-direction: column;
  gap: 11px;
  padding: 16px 17px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
}

.preset-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
}

.preset-card-title {
  color: var(--ink);
  font-size: 13.5px;
  font-weight: 600;
}

.preset-card-actions {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 4px;
}

.preset-card-edit {
  flex: 0 0 auto;
  height: 22px;
  padding: 0 8px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--muted);
  font-size: 11.5px;
  font-weight: 550;
  line-height: 1;
  cursor: pointer;
  transition-property: color, background-color, border-color;
  transition-duration: var(--motion-fast);
  transition-timing-function: var(--motion-ease-standard);
}

.preset-card-edit:hover {
  color: var(--ink);
  border-color: var(--ink);
  background: var(--surface-2);
}

.preset-card-del {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--faint);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  transition-property: color, background-color;
  transition-duration: var(--motion-fast);
  transition-timing-function: var(--motion-ease-standard);
}

.preset-card-del:hover {
  color: var(--red);
  background: var(--red-soft);
}

.preset-card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-bottom: auto;
}

.preset-tag {
  padding: 2px 8px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--muted);
  font-size: 11px;
  font-weight: 500;
  white-space: nowrap;
}

.preset-batch-controls {
  display: grid;
  grid-template-columns: 88px minmax(0, 1fr);
  align-items: end;
  gap: 8px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
}

.preset-quantity {
  display: grid;
  gap: 4px;
  color: var(--faint);
  font-size: 11px;
  font-weight: 550;
}

.preset-quantity input {
  width: 100%;
  height: var(--ctl-h-sm);
  padding: 0 8px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--ink);
  font-family: var(--mono);
  font-size: 12.5px;
  outline: none;
}

.preset-quantity input:focus {
  border-color: var(--ink);
}

.preset-gen-btn {
  width: 100%;
}

.preset-card-error {
  color: var(--red);
  font-size: 11.5px;
}

.preset-card-error:empty {
  display: none;
}

.preset-empty {
  grid-column: 1 / -1;
}

/* ══ models & health ═════════════════════════════════════════════════════ */
.models-summary-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px 16px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}

.models-health-controls {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.models-control-notes {
  display: flex;
  gap: 6px 18px;
  flex-wrap: wrap;
  margin-bottom: 14px;
  color: var(--faint);
  font-size: 11.5px;
}

/* System status ribbon — one bar, four states.
   This block replaced four boxed counters that occupied a full panel row to
   report four small integers. The bar carries the same four numbers plus the
   proportion between them, and the headline says which of them is the reason
   to keep reading. */
.health-kpis {
  display: block;
  padding: 0;
  border: 0;
}

.status-ribbon {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px 16px 15px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
}

.status-ribbon-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px 16px;
  flex-wrap: wrap;
}

.status-ribbon-headline {
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: -.012em;
}

.status-ribbon-bar {
  display: flex;
  gap: 2px;
  height: 10px;
  border-radius: var(--r-pill);
  overflow: hidden;
  background: var(--surface-3);
}

.status-ribbon-seg {
  width: var(--share, 0%);
  border-radius: var(--r-pill);
  transition: width var(--motion-slow) var(--motion-ease);
}

.status-ribbon-seg.status-up {
  background: var(--good);
}

.status-ribbon-seg.status-degraded {
  background: var(--warn);
}

.status-ribbon-seg.status-down {
  background: var(--red);
}

.status-ribbon-seg.status-disabled {
  background: var(--line-2);
}

.status-ribbon-legend {
  display: flex;
  gap: 8px 20px;
  flex-wrap: wrap;
}

.status-ribbon-item {
  display: inline-flex;
  align-items: baseline;
  gap: 7px;
  color: var(--faint);
  font-size: 12.5px;
}

.status-ribbon-item i {
  align-self: center;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--line-2);
}

.status-ribbon-item.status-up i {
  background: var(--good);
}

.status-ribbon-item.status-degraded i {
  background: var(--warn);
}

.status-ribbon-item.status-down i {
  background: var(--red);
}

.status-ribbon-item b {
  color: var(--ink);
  font-size: 15px;
  font-weight: 620;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
}

.status-ribbon-item em {
  font-style: normal;
}

/* A state with nothing in it is still listed — the absence is the news — but it
   recedes so the eye lands on the states that have members. */
.status-ribbon-item.is-zero {
  opacity: .5;
}

.status-ribbon-item.is-zero b {
  color: var(--faint);
}

.active-cooldowns-panel {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}

.active-cooldowns-panel[hidden] {
  display: none;
}

.cooldowns-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
}

.active-cooldowns-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 8px;
}

.cooldown-item {
  display: grid;
  grid-template-columns: 8px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--warn-soft);
}

.cooldown-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--warn);
}

.cooldown-copy {
  display: grid;
  min-width: 0;
}

.cooldown-kind {
  color: var(--faint);
  font-size: 9.5px;
  font-weight: 650;
  letter-spacing: .07em;
  text-transform: uppercase;
}

.cooldown-copy b {
  overflow: hidden;
  color: var(--ink);
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 500;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cooldown-time {
  color: var(--warn);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* provider switches ------------------------------------------------------ */
.provider-switches-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 10px;
}

.provider-switch-card {
  display: grid;
  grid-template-columns: 8px minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  padding: 14px 15px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
}

.provider-global-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--good);
  box-shadow: 0 0 0 3px var(--good-soft);
}

.provider-switch-card.is-disabled .provider-global-dot {
  background: var(--faint);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.provider-switch-copy {
  display: grid;
  gap: 2px;
  min-width: 0;
}

.provider-switch-copy b {
  color: var(--ink);
  font-size: 13.5px;
  font-weight: 600;
}

.provider-switch-copy span {
  color: var(--faint);
  font-size: 11.5px;
  line-height: 1.4;
}

.provider-global-state {
  display: none;
}

/* credential disclosure -------------------------------------------------- */
.provider-credential-disclosure {
  margin-top: 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
  overflow: hidden;
}

.provider-credential-disclosure>summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 13px 15px;
  cursor: pointer;
  list-style: none;
}

.provider-credential-disclosure>summary::-webkit-details-marker {
  display: none;
}

.provider-credential-summary-copy {
  display: grid;
  gap: 1px;
  min-width: 0;
}

.provider-form-kicker {
  color: var(--faint);
  font-size: 9.5px;
  font-weight: 650;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.provider-credential-summary-copy b {
  color: var(--ink);
  font-size: 13px;
  font-weight: 600;
}

.provider-credential-summary-copy>span:last-child {
  color: var(--faint);
  font-size: 11.5px;
}

.provider-credential-chevron {
  flex: 0 0 auto;
  width: 9px;
  height: 9px;
  border-right: 1.6px solid var(--faint);
  border-bottom: 1.6px solid var(--faint);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform var(--motion-standard) var(--motion-ease-standard);
}

.provider-credential-disclosure[open] {
  background: var(--surface);
}

.provider-credential-disclosure[open] .provider-credential-chevron {
  transform: rotate(225deg) translate(-2px, -2px);
}

.provider-credential-content {
  padding: 0 15px 15px;
  border-top: 1px solid var(--line);
}

.credential-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding: 13px 0;
}

.credential-panel-head p {
  color: var(--faint);
  font-size: 12px;
}

.credential-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  background: var(--good-soft);
  color: var(--good);
  font-size: 11px;
  font-weight: 550;
}

.credential-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

.provider-key-form {
  display: grid;
  grid-template-columns: minmax(220px, 2fr) minmax(130px, 1fr) 92px auto;
  align-items: end;
  gap: 10px;
}

.provider-key-form .field {
  min-width: 0;
  margin: 0;
}

.key-format {
  color: var(--faint);
  font-size: 10.5px;
  font-weight: 550;
}

.key-format.good {
  color: var(--good);
}

.key-format.warn {
  color: var(--warn);
}

.key-format.bad {
  color: var(--red);
}

.secret-input-wrap {
  position: relative;
}

.secret-input-wrap input {
  padding-right: 60px !important;
  font-family: var(--mono);
  font-size: 12.5px !important;
}

.secret-toggle {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  height: 24px;
  padding: 0 9px;
  border: 0;
  border-radius: var(--r-pill);
  background: var(--surface-3);
  color: var(--muted);
  font-size: 11px;
  font-weight: 550;
  cursor: pointer;
}

.secret-toggle:hover {
  color: var(--ink);
}

.provider-form-note {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-top: 12px;
  color: var(--faint);
  font-size: 11.5px;
  line-height: 1.5;
}

.note-mark {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 15px;
  height: 15px;
  margin-top: 1px;
  border-radius: 50%;
  background: var(--surface-3);
  color: var(--muted);
  font-size: 9.5px;
  font-weight: 700;
  font-style: normal;
}

.provider-credentials-list {
  display: grid;
  gap: 6px;
  margin-top: 12px;
}

.provider-key-row {
  display: grid;
  grid-template-columns: 8px auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 11px;
  padding: 9px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface-2);
}

.key-state-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--faint);
}

.key-state-dot.ready {
  background: var(--good);
  box-shadow: 0 0 0 3px var(--good-soft);
}

.key-state-dot.cooling {
  background: var(--warn);
  box-shadow: 0 0 0 3px var(--warn-soft);
}

.key-state-dot.disabled {
  opacity: .5;
}

.provider-key-main {
  min-width: 0;
}

.provider-key-main b {
  display: block;
  color: var(--ink);
  font-size: 12.5px;
  font-weight: 600;
}

.provider-key-main b em {
  margin-left: 6px;
  color: var(--faint);
  font-family: var(--mono);
  font-size: 10.5px;
  font-style: normal;
  font-weight: 400;
}

.provider-key-meta {
  display: block;
  overflow: hidden;
  color: var(--faint);
  font-size: 11px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.provider-empty {
  margin-top: 12px;
}

/* model health cards ----------------------------------------------------- */
#modelHealthBars {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 10px;
}

.hrow {
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: 14px 15px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
}

.hrow.is-disabled {
  opacity: .62;
}

.hrow-alert {
  border-color: color-mix(in srgb, var(--red) 40%, var(--line));
  background: var(--red-soft);
}

.hrow.health-degraded.hrow-alert {
  border-color: color-mix(in srgb, var(--warn) 40%, var(--line));
  background: var(--warn-soft);
}

.hrow-top {
  display: grid;
  grid-template-columns: 8px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
}

.health-status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--faint);
}

.health-status-dot.up {
  background: var(--good);
  box-shadow: 0 0 0 3px var(--good-soft);
}

.health-status-dot.degraded {
  background: var(--warn);
  box-shadow: 0 0 0 3px var(--warn-soft);
}

.health-status-dot.down {
  background: var(--red);
  box-shadow: 0 0 0 3px var(--red-soft);
}

.hrow-name {
  display: grid;
  gap: 1px;
  min-width: 0;
}

.hrow-name b {
  overflow: hidden;
  color: var(--ink);
  font-size: 13.5px;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.hrow-route {
  overflow: hidden;
  color: var(--faint);
  font-family: var(--mono);
  font-size: 10.5px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.hrow-actions {
  display: flex;
  align-items: center;
}

.hrow-signals {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.hrow-meta {
  color: var(--faint);
  font-size: 11px;
  line-height: 1.45;
}

.health-reason {
  display: block;
  padding: 7px 10px;
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--muted);
  font-size: 11.5px;
  line-height: 1.45;
}

.hrow-bars {
  display: grid;
  gap: 9px;
  margin-top: auto;
}

.health-meter {
  display: grid;
  gap: 5px;
}

.health-meter-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  color: var(--faint);
  font-size: 10.5px;
}

.health-meter-head b {
  color: var(--muted);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* routing templates ------------------------------------------------------ */
.routing-template-grid {
  display: grid;
  /* Wide enough for a provider name plus its model chain; min() keeps a single
     card from overflowing a viewport narrower than the track. */
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 340px), 1fr));
  /* Each card ends where its chain ends: stretching a one-route template to
     match a three-route neighbour left a large empty well under it. */
  align-items: start;
  gap: 12px;
}

.routing-template-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 15px 16px 13px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
  transition: border-color var(--motion-standard) var(--motion-ease-standard);
}

.routing-template-card:hover {
  border-color: var(--line-2);
}

.routing-template-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px 12px;
  flex-wrap: wrap;
}

.routing-template-name {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.routing-template-name b {
  overflow: hidden;
  color: var(--ink);
  font-size: 13.5px;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.routing-template-name .badge {
  flex: 0 0 auto;
}

.routing-template-count {
  flex: 0 0 auto;
  color: var(--faint);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.routing-template-chain {
  display: grid;
  gap: 5px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.routing-template-chain li {
  display: grid;
  grid-template-columns: 16px minmax(0, 1fr);
  align-items: start;
  gap: 10px;
  overflow: hidden;
  padding: 8px 11px;
  border-radius: var(--r-sm);
  background: var(--surface);
}

.route-step {
  color: var(--faint);
  font-family: var(--mono);
  font-size: 10px;
  font-variant-numeric: tabular-nums;
  line-height: 1.7;
  text-align: right;
}

.route-detail {
  display: grid;
  gap: 1px;
  min-width: 0;
}

.route-detail b {
  color: var(--ink);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.45;
}

/* The chain can list several fallback ids: it wraps to two lines and then
   ellipsizes inside the card instead of running past its edge. */
.route-detail span {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  color: var(--faint);
  font-family: var(--mono);
  font-size: 10.5px;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.routing-template-card .kacts {
  justify-content: flex-start;
  flex-wrap: wrap;
  gap: 6px;
  padding-top: 11px;
  border-top: 1px solid var(--line);
}

/* route editor ----------------------------------------------------------- */
.routing-template-routes {
  display: grid;
  gap: 6px;
  margin-bottom: 10px;
}

.template-route-row {
  position: relative;
  display: grid;
  grid-template-columns: 22px 24px minmax(0, 1fr) minmax(0, 1.2fr) auto auto auto;
  align-items: center;
  gap: 6px;
  padding: 7px 8px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface-2);
}

.template-route-row.is-dragging {
  opacity: .45;
  border-color: var(--line-2);
}

.template-route-row.drag-over-before::before,
.template-route-row.drag-over-after::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 2px;
  border-radius: 2px;
  background: var(--ink);
}

.template-route-row.drag-over-before::before {
  top: -4px;
}

.template-route-row.drag-over-after::after {
  bottom: -4px;
}

.template-route-row .kselect,
.template-route-row input {
  height: var(--ctl-h-sm);
  min-width: 0;
  padding: 0 10px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  background-color: var(--surface);
  color: var(--ink);
  font-size: 12.5px;
  outline: none;
}

.template-route-row .kselect {
  padding-right: 28px;
}

.template-route-row button {
  width: var(--ctl-h-sm);
  height: var(--ctl-h-sm);
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--muted);
  cursor: pointer;
}

.template-route-row button:hover:not([disabled]) {
  color: var(--ink);
  background: var(--surface-2);
}

.template-route-row button[disabled] {
  opacity: .35;
  cursor: not-allowed;
}

/* The handle is the only place a drag can start, so it gets a real target and
   a visible hover rather than two faint glyphs. */
.template-drag {
  display: grid;
  place-items: center;
  height: 26px;
  border-radius: 7px;
  color: var(--faint);
  font-size: 11px;
  letter-spacing: -2px;
  cursor: grab;
  transition-property: color, background-color;
  transition-duration: var(--motion-standard);
  transition-timing-function: var(--motion-ease-standard);
}

.template-drag:hover {
  color: var(--muted);
  background: var(--surface);
}

.template-drag:active {
  cursor: grabbing;
}

.template-route-position {
  color: var(--faint);
  font-family: var(--mono);
  font-size: 10.5px;
}

/* model catalog ---------------------------------------------------------- */
.model-manager-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 10px;
}

.model-manager-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px 15px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
}

.model-manager-card.is-disabled {
  opacity: .62;
}

.model-manager-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.model-card-kicker {
  display: block;
  color: var(--faint);
  font-size: 9.5px;
  font-weight: 650;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.model-manager-head h3 {
  overflow: hidden;
  color: var(--ink);
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.model-manager-details {
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(0, 1fr);
  gap: 10px 16px;
  margin-bottom: auto;
}

.model-card-label {
  display: block;
  margin-bottom: 5px;
  color: var(--faint);
  font-size: 10.5px;
  font-weight: 600;
}

.model-alias-list {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.model-alias-chip {
  padding: 2px 7px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 10.5px;
}

.model-alias-more {
  color: var(--faint);
  font-size: 10.5px;
}

.model-manager-actions {
  justify-content: flex-start;
  padding-top: 10px;
  border-top: 1px solid var(--line);
}

/* ══ logs ════════════════════════════════════════════════════════════════ */
.logs-panel-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px 16px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

.logs-panel-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.log-overview {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
  margin-bottom: 14px;
}

.log-summary-card {
  display: grid;
  align-content: start;
  gap: 3px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
}

.log-summary-label {
  color: var(--faint);
  font-size: 11.5px;
  font-weight: 550;
}

.log-summary-value {
  color: var(--ink);
  font-size: 21px;
  font-weight: 620;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.03em;
  line-height: 1.15;
}

.log-summary-card.is-good .log-summary-value {
  color: var(--good);
}

.log-summary-card.is-warning .log-summary-value {
  color: var(--warn);
}

.log-summary-card.is-critical .log-summary-value {
  color: var(--red);
}

.log-summary-context {
  color: var(--faint);
  font-size: 11px;
}

/* log table -------------------------------------------------------------- */
.logs-table-scroll {
  overflow-x: auto;
  overscroll-behavior-inline: contain;
}

.logtbl {
  min-width: 1060px;
  table-layout: fixed;
}

.logtbl th:nth-child(1),
.logtbl td:nth-child(1) {
  width: 108px;
}

.logtbl th:nth-child(2),
.logtbl td:nth-child(2) {
  width: 148px;
}

.logtbl th:nth-child(3),
.logtbl td:nth-child(3) {
  width: 150px;
}

.logtbl th:nth-child(4),
.logtbl td:nth-child(4) {
  width: 108px;
}

.logtbl th:nth-child(5),
.logtbl td:nth-child(5) {
  width: 176px;
}

.logtbl th:nth-child(6),
.logtbl td:nth-child(6) {
  width: 106px;
}

.logtbl th:nth-child(7),
.logtbl td:nth-child(7) {
  width: 74px;
  text-align: right;
}

/* Wide enough for "in 1.0k out 1.1k" on one line: at 96px the in/out split
   wrapped its labels away from their values. */
.logtbl th:nth-child(8),
.logtbl td:nth-child(8) {
  width: 116px;
}

.logtbl th:nth-child(9),
.logtbl td:nth-child(9) {
  width: 118px;
}

/* Client identity is carried by the badge dot and a barely-there row wash;
   the strong left edge is reserved for request status so colour never lies. */
.log-summary-row td {
  border-bottom: 1px solid var(--line);
  background: color-mix(in srgb, hsl(var(--client-hue, 0) 45% 52%) 3%, var(--surface));
  cursor: pointer;
  transition: background-color var(--motion-fast) var(--motion-ease-standard);
}

.log-summary-row:hover td,
.log-summary-row:focus-visible td {
  background: color-mix(in srgb, hsl(var(--client-hue, 0) 45% 52%) 7%, var(--surface));
}

.log-summary-row.expanded td {
  background: color-mix(in srgb, hsl(var(--client-hue, 0) 45% 52%) 8%, var(--surface));
  border-bottom-color: transparent;
}

.log-summary-row td:first-child {
  box-shadow: inset 2px 0 0 transparent;
}

.log-summary-row.has-error td:first-child {
  box-shadow: inset 2px 0 0 var(--red);
}

.log-summary-row.has-error td {
  background: var(--red-soft);
}

.log-summary-row.has-error:hover td {
  background: color-mix(in srgb, var(--red) 14%, var(--surface));
}

[data-theme="dark"] .log-summary-row td {
  background: color-mix(in srgb, hsl(var(--client-hue, 0) 40% 60%) 4%, var(--surface));
}

[data-theme="dark"] .log-summary-row.expanded td {
  background: color-mix(in srgb, hsl(var(--client-hue, 0) 40% 60%) 10%, var(--surface));
}

[data-theme="dark"] .log-summary-row.has-error td {
  background: var(--red-soft);
}

.log-summary-row:focus-visible {
  outline: none;
}

.log-time-cell {
  font-size: 12px;
}

.log-time-wrap {
  display: grid;
  grid-template-columns: 14px minmax(0, 1fr);
  align-items: center;
  gap: 7px;
}

.log-expand-chevron {
  width: 7px;
  height: 7px;
  border-right: 1.6px solid var(--faint);
  border-bottom: 1.6px solid var(--faint);
  transform: rotate(-45deg) translate(-1px, -1px);
  transition: transform var(--motion-standard) var(--motion-ease-standard);
}

.log-summary-row.expanded .log-expand-chevron {
  border-color: var(--ink);
  transform: rotate(45deg) translate(-1px, -1px);
}

.time-clock {
  color: var(--ink);
  font-weight: 600;
}

.time-ago {
  margin-top: 1px;
  color: var(--faint);
  font-size: 10.5px;
}

.log-key-badge {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}

.log-key-badge b {
  overflow: hidden;
  color: var(--ink);
  font-size: 12.5px;
  font-weight: 550;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.log-key-icon {
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: hsl(var(--client-hue, 0) 46% 46%);
}

[data-theme="dark"] .log-key-icon {
  background: hsl(var(--client-hue, 0) 44% 64%);
}

.col-model b {
  color: var(--ink);
  font-weight: 550;
}

.log-route {
  text-transform: capitalize;
}

.log-attempt-count {
  display: block;
  margin-top: 3px;
  color: var(--faint);
  font-size: 10px;
  white-space: nowrap;
}

.log-provider-cell {
  display: grid;
  gap: 1px;
  min-width: 0;
}

.log-provider-slug {
  overflow: hidden;
  color: var(--muted);
  font-size: 11.5px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.log-provider-model {
  overflow: hidden;
  color: var(--faint);
  font-size: 10.5px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.log-status-pill {
  font-variant-numeric: tabular-nums;
}

.log-status-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--good);
}

.log-status-pill.warn .log-status-dot {
  background: var(--warn);
}

.log-status-pill.bad .log-status-dot {
  background: var(--red);
}

.latency-slow {
  color: var(--warn) !important;
  font-weight: 600;
}

.log-tok-box {
  display: grid;
  gap: 1px;
  font-variant-numeric: tabular-nums;
}

.tok-total {
  color: var(--ink);
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
}

.tok-split {
  display: flex;
  gap: 7px;
  color: var(--faint);
  font-family: var(--mono);
  font-size: 10px;
  white-space: nowrap;
}

.log-req-cell {
  color: var(--faint);
  font-size: 11px;
}

/* expanded routing trace ------------------------------------------------- */
.log-route-detail {
  display: none;
}

.log-route-detail.open {
  display: table-row;
}

.log-route-detail.open>td {
  padding: 0 12px 14px;
  border-bottom: 1px solid var(--line);
  background: color-mix(in srgb, hsl(var(--client-hue, 0) 45% 52%) 4%, var(--surface));
}

[data-theme="dark"] .log-route-detail.open>td {
  background: color-mix(in srgb, hsl(var(--client-hue, 0) 40% 60%) 6%, var(--surface));
}

.route-trace {
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
}

.route-trace-summary {
  display: flex;
  align-items: center;
  gap: 10px 16px;
  flex-wrap: wrap;
  margin-bottom: 14px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line);
  color: var(--faint);
  font-size: 11px;
}

.route-trace-summary>div {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.route-trace-summary>div span {
  font-size: 9.5px;
  font-weight: 650;
  letter-spacing: .07em;
  text-transform: uppercase;
}

.route-trace-summary b {
  color: var(--ink);
  font-size: 12.5px;
  font-weight: 600;
}

.route-trace-summary code {
  overflow: hidden;
  padding: 3px 8px;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 10.5px;
  text-overflow: ellipsis;
}

.trace-copy {
  height: var(--ctl-h-xs);
  padding: 0 10px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--muted);
  font-size: 11px;
  font-weight: 550;
  cursor: pointer;
  transition-property: color, background-color;
  transition-duration: var(--motion-standard);
  transition-timing-function: var(--motion-ease-standard);
}

.trace-copy:hover {
  color: var(--ink);
  background: var(--surface-2);
}

.route-trace-summary>span:last-child {
  margin-left: auto;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

.route-trace-tree {
  display: flex;
  flex-direction: column;
}

.route-trace-step {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr);
  gap: 10px;
}

.route-trace-rail {
  position: relative;
  display: flex;
  justify-content: center;
}

.route-trace-index {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border: 1px solid var(--line-2);
  border-radius: 50%;
  background: var(--surface);
  color: var(--faint);
  font-family: var(--mono);
  font-size: 10px;
}

.route-trace-step.success .route-trace-index {
  border-color: color-mix(in srgb, var(--good) 50%, transparent);
  background: var(--good-soft);
  color: var(--good);
}

.route-trace-step.failed .route-trace-index {
  border-color: color-mix(in srgb, var(--red) 50%, transparent);
  background: var(--red-soft);
  color: var(--red);
}

.route-trace-step.rate-limited .route-trace-index,
.route-trace-step.timeout .route-trace-index {
  border-color: color-mix(in srgb, var(--warn) 50%, transparent);
  background: var(--warn-soft);
  color: var(--warn);
}

.route-trace-line {
  position: absolute;
  top: 24px;
  bottom: -10px;
  width: 1px;
  background: var(--line-2);
}

.route-trace-card {
  min-width: 0;
  margin-bottom: 10px;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface-2);
}

.route-trace-step:last-child .route-trace-card {
  margin-bottom: 0;
}

.route-trace-head,
.route-trace-provider,
.route-trace-meta {
  display: flex;
  align-items: center;
  gap: 9px;
  flex-wrap: wrap;
  min-width: 0;
}

.route-trace-head {
  color: var(--faint);
  font-family: var(--mono);
  font-size: 10.5px;
}

.route-trace-head time {
  color: var(--muted);
}

.route-trace-head b {
  color: var(--ink);
  font-weight: 600;
}

.route-trace-state {
  padding: 2px 7px;
  border-radius: var(--r-pill);
  background: var(--surface-3);
  color: var(--muted);
  font-family: var(--sans);
  font-size: 9.5px;
  font-weight: 650;
  letter-spacing: .05em;
  text-transform: uppercase;
}

.route-trace-state.success {
  background: var(--good-soft);
  color: var(--good);
}

.route-trace-state.failed {
  background: var(--red-soft);
  color: var(--red);
}

.route-trace-state.rate-limited,
.route-trace-state.timeout {
  background: var(--warn-soft);
  color: var(--warn);
}

.route-trace-provider {
  margin-top: 8px;
}

.route-trace-provider .pill {
  flex: 0 0 auto;
  padding: 1px 7px;
  font-size: 10px;
  text-transform: capitalize;
}

.route-trace-provider strong {
  min-width: 0;
  color: var(--ink);
  font-family: var(--mono);
  font-size: 12px;
  overflow-wrap: anywhere;
}

.route-trace-provider em {
  margin-left: auto;
  color: var(--faint);
  font-family: var(--mono);
  font-size: 10.5px;
  font-style: normal;
  white-space: nowrap;
}

.route-trace-meta {
  margin-top: 7px;
  color: var(--faint);
  font-family: var(--mono);
  font-size: 10.5px;
}

.route-trace-error {
  margin-top: 8px;
  padding: 7px 10px;
  border-radius: var(--r-sm);
  background: var(--red-soft);
  color: var(--red);
  font-family: var(--mono);
  font-size: 10.5px;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.route-retry-label {
  display: inline-block;
  margin-top: 8px;
  color: var(--warn);
  font-size: 10.5px;
  font-weight: 550;
}

.logs-paginator {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}

.logs-page-txt {
  color: var(--faint);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}

/* client analytics ------------------------------------------------------- */
.analytics-container {
  display: grid;
  gap: 14px;
}

.analytics-metrics {
  grid-template-columns: repeat(5, minmax(0, 1fr));
}

.analytics-status-title {
  margin-bottom: 8px;
}

.analytics-block {
  display: grid;
  gap: 8px;
}

.analytics-status-bar {
  display: flex;
  gap: 2px;
  height: 12px;
  border-radius: var(--r-pill);
  overflow: hidden;
}

.analytics-status-bar>span {
  width: var(--value, 0%);
  min-width: 0;
  background: var(--good);
}

.tab-pane.is-fresh .analytics-status-bar>span {
  animation: meter-grow var(--motion-slow) var(--motion-ease) both;
}

.analytics-status-bar .warn {
  background: var(--warn);
}

.analytics-status-bar .bad {
  background: var(--red);
}

.analytics-legend {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  color: var(--muted);
  font-size: 11.5px;
}

.analytics-legend span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.analytics-legend i {
  width: 8px;
  height: 8px;
  border-radius: 2px;
  background: var(--good);
}

.analytics-legend .warn i {
  background: var(--warn);
}

.analytics-legend .bad i {
  background: var(--red);
}

.analytics-empty {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
  color: var(--faint);
  font-size: 12.5px;
}

.economics-hero-card {
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: 20px;
  padding: 20px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  position: relative;
  overflow: hidden;
}

.economics-hero-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 4px;
  height: 100%;
  background: var(--accent);
}

.economics-hero-main .sec-label {
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
}

.economics-hero-big {
  font-size: 34px;
  font-weight: 700;
  letter-spacing: -0.03em;
  color: var(--ink);
  line-height: 1.1;
  margin: 6px 0 4px;
  font-variant-numeric: tabular-nums;
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.economics-hero-big .unit {
  font-size: 14px;
  font-weight: 500;
  color: var(--muted);
  letter-spacing: 0;
}

.economics-hero-sub {
  font-size: 12px;
  color: var(--muted);
}

.economics-horizons {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  align-content: center;
}

.economics-horizon-item {
  padding: 10px 12px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  text-align: center;
  transition: transform 0.15s ease, border-color 0.15s ease;
}

.economics-horizon-item.is-current {
  border-color: var(--accent);
  background: var(--surface-2);
}

.economics-horizon-label {
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  color: var(--muted);
  letter-spacing: 0.04em;
}

.economics-horizon-val {
  font-size: 14px;
  font-weight: 700;
  color: var(--ink);
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}

.economics-horizon-vol {
  font-size: 10px;
  color: var(--faint);
}

.rate-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 7px;
  border-radius: var(--r-pill);
  font-size: 11px;
  font-weight: 600;
  background: var(--surface-2);
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.rate-badge.green {
  background: rgba(16, 185, 129, 0.12);
  color: var(--good);
}

.rank-rate {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.analytics-details-toggle-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  margin-top: 4px;
}

.analytics-details-controls {
  display: flex;
  align-items: center;
  gap: 10px;
}

.analytics-details-label {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.analytics-filter-select {
  padding: 4px 8px;
  font-size: 12px;
  height: 28px;
}

.analytics-details-container {
  display: grid;
  gap: 14px;
  margin-top: 6px;
}

.analytics-details-container[hidden] {
  display: none !important;
}

.analytics-models-grid {
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: 14px;
}

.analytics-models-grid .card {
  padding: 14px 16px;
}

@media (max-width: 900px) {
  .analytics-models-grid {
    grid-template-columns: 1fr;
  }
  .analytics-details-toggle-bar {
    flex-direction: column;
    align-items: stretch;
  }
}

@media (max-width: 900px) {
  .economics-hero-card {
    grid-template-columns: 1fr;
  }
  .economics-horizons {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* ══ auth ════════════════════════════════════════════════════════════════ */
.auth-stage {
  display: grid;
  place-items: center;
  min-height: 100vh;
  padding: 32px 24px;
}

.auth-stage.hide {
  display: none !important;
}

.auth-card {
  width: 100%;
  max-width: 420px;
  padding: 30px 32px 26px;
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  background: var(--surface);
  box-shadow: var(--shadow-raised);
}

.auth-enter {
  animation: admin-modal-enter var(--motion-enter) var(--motion-ease) both;
}

.auth-mark {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  margin-bottom: 18px;
  border-radius: 12px;
  background: var(--ink);
  color: var(--surface);
}

.auth-mark svg {
  width: 19px;
  height: 19px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.auth-card .page-eyebrow {
  display: block;
  margin-bottom: 6px;
  color: var(--faint);
  font-size: 10px;
  font-weight: 650;
  letter-spacing: .1em;
  text-transform: uppercase;
}

.auth-card h1 {
  color: var(--ink);
  font-size: 22px;
  font-weight: 650;
  letter-spacing: -.025em;
}

.auth-intro {
  margin-top: 6px;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.55;
}

.auth-label {
  display: block;
  margin: 20px 0 7px;
  color: var(--ink);
  font-size: 12.5px;
  font-weight: 550;
}

.auth-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px;
}

.auth-secret {
  position: relative;
  min-width: 0;
}

.auth-secret input {
  width: 100%;
  height: var(--ctl-h);
  padding: 0 62px 0 12px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--ink);
  font-size: 13.5px;
  outline: none;
  transition-property: border-color, box-shadow;
  transition-duration: var(--motion-standard);
  transition-timing-function: var(--motion-ease-standard);
}

.auth-secret input:focus {
  border-color: var(--ink);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.auth-secret button {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  height: 24px;
  padding: 0 9px;
  border: 0;
  border-radius: var(--r-pill);
  background: var(--surface-3);
  color: var(--muted);
  font-size: 11px;
  font-weight: 550;
  cursor: pointer;
}

.auth-security {
  margin-top: 14px;
  color: var(--faint);
  font-size: 11.5px;
  line-height: 1.5;
}

.auth-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 12px;
  color: var(--muted);
  font-size: 12.5px;
}

.auth-meta .who {
  color: var(--ink);
  font-family: var(--mono);
  font-size: 12px;
}

.fresh {
  color: var(--faint);
  font-size: 11.5px;
}

/* ══ modal enter ═════════════════════════════════════════════════════════ */
.modal-veil.on .modal {
  animation: admin-modal-enter var(--motion-enter) var(--motion-ease) both;
}

.modal {
  border-radius: var(--r-xl);
}

/* ══ responsive ══════════════════════════════════════════════════════════ */
@media (max-width: 1180px) {
  .analytics-metrics {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (max-width: 940px) {
  .reliability-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .sample-control {
    justify-content: flex-start;
  }

  .sample-control .sec-note {
    text-align: left;
  }
}

@media (max-width: 1080px) {
  .grid3 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .grid3>.card:last-child {
    grid-column: span 2;
  }

  .split {
    grid-template-columns: minmax(0, 1fr);
    gap: 16px;
  }

  .kpis {
    padding-left: 0;
    padding-top: 16px;
    border-left: 0;
    border-top: 1px solid var(--line);
  }

  .provider-key-form {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }

  .provider-key-form .provider-secret {
    grid-column: 1 / -1;
  }

  .provider-key-form .provider-submit {
    grid-column: 1 / -1;
  }
}

@media (max-width: 900px) {
  .admin-sidebar {
    /* The panel is inset from the edge, so it has to travel its own width
       plus the gutter to clear the viewport completely. */
    transform: translateX(calc(-100% - var(--sidebar-inset) - 6px));
    transition: transform var(--motion-enter) var(--motion-ease);
  }

  body.sidebar-open .admin-sidebar {
    transform: none;
    box-shadow: var(--shadow-raised);
  }

  body.sidebar-open .sidebar-backdrop {
    display: block;
  }

  .sidebar-close {
    display: grid;
  }

  .admin-workspace {
    margin-left: 0;
  }

  .mobile-header {
    display: flex;
    position: sticky;
    top: 0;
    z-index: 40;
  }

  .workspace-main {
    --page-gutter: 18px;
    padding: 0 var(--page-gutter) 64px;
  }

  /* The mobile header already pins the brand and the refresh action to the top
     of the viewport; a second sticky bar under it would eat a third of a phone
     screen, so the page heading scrolls away with the content. */
  .page-title-dock {
    position: static;
    min-height: 0;
    margin: 16px 0;
  }

  /* No sidebar gutter to offset against once the sidebar floats out. */
  .bulk-bar {
    left: 50%;
    max-width: calc(100vw - 24px);
    flex-wrap: wrap;
    justify-content: center;
    border-radius: var(--r-md);
  }

  .page-title,
  .page-title.is-stuck {
    padding: 15px 15px 15px 18px;
    border-radius: var(--r-md);
    box-shadow: var(--shadow);
    background: var(--surface);
  }

  .page-title.is-stuck h1 {
    font-size: 22px;
  }

  /* The description wraps to two or three lines at this width, so the collapse
     cap that keeps the desktop bar to one line has to come off entirely. */
  .page-description,
  .page-title.is-stuck .page-description {
    max-height: none;
    margin-top: 3px;
    opacity: 1;
  }

  .page-title::before {
    display: none;
  }

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

  .grid3>.card:last-child {
    grid-column: auto;
  }

  .metrics,
  .log-overview,
  .kpis {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .analytics-metrics {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .template-route-row {
    grid-template-columns: 22px 24px minmax(0, 1fr) auto auto auto;
  }

  .template-route-row [data-route-model] {
    grid-column: 3 / -1;
  }
}

@media (max-width: 620px) {
  :root {
    --space-panel: 14px;
    --space-panel-pad: 16px;
  }

  .workspace-main {
    --page-gutter: 16px;
  }

  .panel {
    padding: 16px;
  }

  .ktable-wrap {
    margin: 0 -16px;
    padding: 0 16px;
  }

  .page-title h1,
  .page-title.is-stuck h1 {
    font-size: 19px;
  }

  .readout-lg .big {
    font-size: 34px;
  }

  /* On a phone the cluster is the widest thing in the header, so it stops
     pretending to be a compact pill and becomes a two-by-two block: freshness
     and the auto switch above, the interval stops and the manual refresh
     below, each column aligned to the same edge. */
  .toolbar-cluster {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 10px;
    width: 100%;
    height: auto;
    padding: 10px;
    border-radius: var(--r-md);
  }

  .live-readout {
    padding-left: 4px;
  }

  .toolbar-cluster .cluster-sep {
    display: none;
  }

  .toolbar-cluster .cluster-switch,
  .toolbar-cluster .refresh-icon {
    justify-self: end;
  }

  .toolbar-cluster .seg {
    justify-content: space-between;
  }

  .title-side {
    width: 100%;
  }

  .plan-pills {
    order: 2;
  }

  .metrics,
  .log-overview,
  .kpis,
  .analytics-metrics {
    grid-template-columns: minmax(0, 1fr);
  }

  /* Name and share stay on one line; the bar and the raw counts drop below
     it rather than each row collapsing into four stacked fragments. */
  .qrow {
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 4px 10px;
    padding: 12px 8px;
  }

  .qrow .qt {
    grid-column: 1 / -1;
    order: 3;
    margin-top: 4px;
  }

  .qrow .qv {
    grid-column: 1 / -1;
    order: 4;
  }

  /* The ring and its legend only stack once they genuinely stop fitting side
     by side — full-width chart blocks above this width keep both in one row. */
  .donut-layout {
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
  }

  .donut-legend {
    width: 100%;
  }

  .preset-batch-controls {
    grid-template-columns: 76px minmax(0, 1fr);
  }
}


/* ══ density ═══════════════════════════════════════════════════════════════
   One switch, two settings. `cozy` is the layout the console was drawn at;
   `compact` tightens the same components so a long key table or a page of
   requests fits a laptop without the scroll. Only spacing and control heights
   move — no label drops below 10.5px and no hit target below 26px, so the
   compact layout stays as usable as the comfortable one. */
[data-density="compact"] {
  --space-panel: 12px;
  --space-panel-pad: 16px;
  --space-block: 12px;
  --ctl-h: 32px;
  --ctl-h-sm: 27px;
}

[data-density="compact"] .panel {
  padding: 14px var(--space-panel-pad) 16px;
}

[data-density="compact"] .ktbl td {
  padding: 6px 10px;
}

[data-density="compact"] .ktbl thead th {
  padding: 6px 10px;
}

[data-density="compact"] .qrow {
  padding: 7px 8px;
}

[data-density="compact"] .metric,
[data-density="compact"] .kpi,
[data-density="compact"] .log-summary-card {
  padding: 10px 12px;
}

[data-density="compact"] .sec-head {
  margin-bottom: 12px;
}

/* Compact drops the prose that explains a panel, never a line that carries a
   figure — #periodNote states the date range the hero numbers cover, so it
   stays whatever the density. */
[data-density="compact"] .section-copy:not(#periodNote),
[data-density="compact"] .models-section-copy,
[data-density="compact"] .logs-section-copy {
  display: none;
}

/* The icon says which way the switch goes: the inner rules only exist in the
   comfortable state, and disappear once the layout is already tight. */
[data-density="compact"] #densityBtn .density-row-inner {
  opacity: 0;
}

#densityBtn .density-row-inner {
  opacity: .45;
  transition: opacity var(--motion-standard) var(--motion-ease-standard);
}

/* ══ key table: name opens the profile ═════════════════════════════════════ */
.kname-btn {
  display: block;
  width: 100%;
  padding: 2px 6px;
  margin: -2px -6px;
  border: 0;
  border-radius: var(--r-sm);
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background-color var(--motion-fast) var(--motion-ease-standard);
}

.kname-btn:hover {
  background: var(--selection);
}

.kname-btn:hover b {
  text-decoration: underline;
  text-underline-offset: 2px;
}

.kname-btn:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 1px;
}

/* ══ consumption pace ══════════════════════════════════════════════════════
   A percentage says how far a key has come; this says how long it has left.
   Tone tracks urgency rather than magnitude — under three days is the window
   in which somebody actually has to act. */
.qrunway {
  justify-self: end;
  padding: 3px 9px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  color: var(--muted);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: -.005em;
  white-space: nowrap;
}

.qrunway[data-tone="ok"] {
  border-color: transparent;
  background: var(--good-soft);
  color: var(--good);
}

.qrunway[data-tone="warn"] {
  border-color: transparent;
  background: var(--warn-soft);
  color: var(--warn);
}

.qrunway[data-tone="bad"] {
  border-color: transparent;
  background: var(--red-soft);
  color: var(--red);
}

.qrow:has(.qrunway) {
  grid-template-columns: minmax(0, 170px) minmax(0, 1fr) auto 52px auto;
}

/* ══ client key drawer ═════════════════════════════════════════════════════
   A side panel rather than a centred dialog: it is a reading surface tied to
   the row behind it, and the table stays visible so the context of "which key
   am I looking at" never leaves the screen. */
.drawer-veil {
  align-items: stretch;
  justify-content: flex-end;
  padding: 0;
}

.drawer-panel {
  display: flex;
  flex-direction: column;
  width: min(560px, 100%);
  max-width: none;
  max-height: 100vh;
  height: 100vh;
  border: 0;
  border-left: 1px solid var(--line);
  border-radius: 0;
  overflow: hidden;
}

.modal-veil.on .drawer-panel {
  animation: admin-drawer-enter var(--motion-enter) var(--motion-ease) both;
}

.modal-veil.is-closing .drawer-panel {
  animation: admin-drawer-exit 150ms var(--motion-ease-standard) both;
}

@keyframes admin-drawer-enter {
  from {
    transform: translateX(24px);
    opacity: 0;
  }
}

@keyframes admin-drawer-exit {
  to {
    transform: translateX(20px);
    opacity: 0;
  }
}

.drawer-panel .drawer-head {
  padding: 18px 22px 14px;
}

.drawer-heading h3 {
  margin-top: 2px;
  font-size: 18px;
  letter-spacing: -.02em;
}

.drawer-panel .drawer-body {
  flex: 1 1 auto;
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  gap: var(--space-block);
  padding: 16px 22px 22px;
}

.drawer-panel .drawer-foot {
  position: static;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: flex-start;
}

.profile-loading {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 32px 0;
  color: var(--muted);
  font-size: 12.5px;
}

.profile-chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}

.profile-chip {
  max-width: 100%;
  overflow: hidden;
  padding: 3px 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  color: var(--muted);
  font-size: 11px;
  font-weight: 500;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.profile-block {
  padding: 14px 16px 16px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-sunken);
}

.profile-block-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
}

.profile-block-head h4 {
  margin: 0;
  color: var(--ink);
  font-size: 11px;
  font-weight: 650;
  letter-spacing: .07em;
  text-transform: uppercase;
}

.profile-balance-figure {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 6px;
}

.profile-balance-figure b {
  color: var(--ink);
  font-size: 30px;
  font-weight: 600;
  letter-spacing: -.03em;
  line-height: 1;
}

.profile-balance-figure span {
  color: var(--faint);
  font-size: 12px;
}

.profile-note {
  margin: 10px 0 0;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.55;
}

.profile-note b {
  color: var(--ink);
  font-weight: 600;
}

/* A 30-day trace with no axis on purpose: the question it answers is "steady,
   spiking, or stopped", and the exact figures sit in the row beneath it. */
.profile-spark svg {
  display: block;
  width: 100%;
  height: 92px;
}

.profile-spark-area {
  fill: var(--data-line);
  opacity: .12;
}

.profile-spark-line {
  fill: none;
  stroke: var(--data-line);
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}

.profile-spark-peak {
  fill: var(--data-line);
}

.profile-spark figcaption {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 8px;
  color: var(--faint);
  font-size: 10.5px;
}

.profile-spark-peak-note {
  color: var(--muted);
  font-weight: 600;
}

.profile-metrics {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

/* ══ key profile ═══════════════════════════════════════════════════════════
   One content block, two hosts. Stacked in the drawer, which is a column; two
   up in the search-result panel, which has a page's width to work with. */
.profile {
  display: grid;
  gap: var(--space-block);
  align-items: start;
}

.profile.is-wide {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

/* Rows that read across the whole profile rather than beside a neighbour. */
.profile.is-wide .profile-chips,
.profile.is-wide .profile-metrics,
.profile.is-wide .profile-logs {
  grid-column: 1 / -1;
}

.profile-log-list {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.profile-log-row {
  display: grid;
  grid-template-columns: minmax(0, 108px) minmax(0, 1fr) auto minmax(0, 62px) minmax(0, 74px);
  align-items: center;
  gap: 10px;
  padding: 7px 8px;
  margin: 0 -8px;
  border-radius: var(--r-sm);
  font-size: 12px;
}

.profile-log-row:hover {
  background: var(--surface-2);
}

.profile-log-time {
  color: var(--faint);
  font-family: var(--mono);
  font-size: 10.5px;
  white-space: nowrap;
}

.profile-log-model {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.profile-log-model b {
  overflow: hidden;
  color: var(--ink);
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.profile-log-model span {
  overflow: hidden;
  color: var(--faint);
  font-family: var(--mono);
  font-size: 10px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.profile-log-status {
  justify-self: start;
  font-family: var(--mono);
  font-size: 10.5px;
}

.profile-log-num {
  color: var(--muted);
  font-family: var(--mono);
  font-size: 11px;
  text-align: right;
  white-space: nowrap;
}

.profile-log-num b {
  color: var(--ink);
  font-weight: 600;
}

.profile-log-all {
  align-self: start;
  margin-top: 10px;
}

/* ══ resolved search result ════════════════════════════════════════════════
   A query that names exactly one client stops being a filter and becomes an
   answer: the profile opens under the box it was typed into, so the balance,
   the pace, the recent requests and every action are one glance away. */
.key-match-panel {
  margin: 4px 0 var(--space-block);
}

.key-match-panel[hidden] {
  display: none;
}

.key-match {
  padding: 16px 18px 18px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-md);
  background: var(--surface-2);
  animation: admin-pane-enter var(--motion-enter) var(--motion-ease) both;
}

.key-match-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: var(--space-block);
}

.key-match-eyebrow {
  display: block;
  color: var(--faint);
  font-size: 10px;
  font-weight: 650;
  letter-spacing: .09em;
  text-transform: uppercase;
}

.key-match-id h3 {
  margin: 3px 0 1px;
  color: var(--ink);
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -.02em;
}

.key-match-id p {
  margin: 0;
  color: var(--faint);
  font-family: var(--mono);
  font-size: 11.5px;
}

.key-match-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* The blocks inside the panel already sit on --surface-2, so they lift onto
   the card surface rather than sinking into it the way they do in the drawer. */
.key-match .profile-block {
  border-color: var(--line);
  background: var(--surface);
}

@media (max-width: 900px) {
  .profile.is-wide {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 620px) {
  .profile-log-row {
    grid-template-columns: minmax(0, 1fr) auto auto;
    gap: 4px 10px;
  }

  .profile-log-time {
    grid-column: 1 / -1;
    order: -1;
  }
}

.profile-block .analytics-rank {
  margin-top: 0;
}

@media (max-width: 620px) {
  .drawer-panel {
    width: 100%;
    border-left: 0;
  }

  .profile-metrics {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .qrow:has(.qrunway) {
    grid-template-columns: minmax(0, 1fr) auto;
  }
}

/* ══ live tail ═════════════════════════════════════════════════════════════
   The section refresh runs on a 30s–5m cadence, far too slow to watch traffic
   arrive. The tail is a second, faster poll scoped to this table alone, and
   the rows it brings in say so for one beat before settling. */
.logs-live-switch {
  flex: 0 0 auto;
}

body.is-tailing .logs-live-switch {
  color: var(--ink);
}

.log-summary-row.is-new td {
  animation: log-row-arrive 1.6s var(--motion-ease-standard) both;
}

@keyframes log-row-arrive {
  0% {
    background: var(--good-soft);
    box-shadow: inset 2px 0 0 var(--good);
  }

  60% {
    background: var(--good-soft);
    box-shadow: inset 2px 0 0 var(--good);
  }

  100% {
    background: transparent;
    box-shadow: none;
  }
}

/* ══ shortcut reference ════════════════════════════════════════════════════ */
.shortcut-groups {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.shortcut-group h4 {
  margin: 0 0 8px;
  color: var(--faint);
  font-size: 10.5px;
  font-weight: 650;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.shortcut-group dl {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.shortcut-row {
  display: grid;
  grid-template-columns: 116px minmax(0, 1fr);
  align-items: center;
  gap: 12px;
  padding: 7px 8px;
  margin: 0 -8px;
  border-radius: var(--r-sm);
}

.shortcut-row:hover {
  background: var(--surface-2);
}

.shortcut-row dt {
  display: flex;
  align-items: center;
  gap: 4px;
}

.shortcut-row dd {
  margin: 0;
  color: var(--muted);
  font-size: 12.5px;
}

.shortcut-then {
  color: var(--faint);
  font-size: 10px;
}

/* The floating page header overlays whatever a jump scrolls to, so a panel
   that can be scrolled into view reserves its own clearance beneath it. */
.logs-request-panel {
  scroll-margin-top: 104px;
}

@media (prefers-reduced-motion: reduce) {

  .modal-veil.on .drawer-panel,
  .modal-veil.is-closing .drawer-panel,
  .log-summary-row.is-new td {
    animation: none;
  }
}

/* ---- full request transcripts ----
   A stored body is reference material, not a figure to scan: it gets the
   monospace column, its own scroll box, and no colour of its own, so an
   expanded row still reads as one routing trace with an appendix. */
.log-payload {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px dashed var(--line);
}

.log-payload-note {
  font-size: 11.5px;
  color: var(--faint);
}

.log-payload-body {
  margin-top: 12px;
}

.conversation-explorer {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 16px;
  padding: 16px;
  border-radius: var(--r-md);
  background-color: var(--surface-sunken);
  border: 1px solid var(--line);
  max-height: 650px;
  overflow-y: auto;
  scroll-behavior: smooth;
}

.payload-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
  flex-wrap: wrap;
}

.payload-toolbar .payload-summary {
  margin-bottom: 0;
}

.payload-view-toggle {
  font-size: 11px;
}

.payload-view-toggle.active {
  background: var(--accent);
  color: var(--bg);
}

.conversation-explorer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 4px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--faint);
}

.msg-bubble {
  padding: 12px 16px;
  border-radius: 14px;
  max-width: 85%;
  font-size: 13px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-wrap: break-word;
  font-family: inherit;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
}

/* User message: Modern accent blue, crisp white text in both light & dark modes */
.msg-bubble.role-user {
  align-self: flex-end;
  background-color: #2563eb;
  color: #ffffff;
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-bottom-right-radius: 4px;
}

[data-theme="dark"] .msg-bubble.role-user {
  background-color: #1d4ed8;
  color: #f8fafc;
  border: 1px solid rgba(255, 255, 255, 0.12);
}

/* Assistant message: Clean elevated surface with theme ink text */
.msg-bubble.role-assistant {
  align-self: flex-start;
  background-color: var(--surface);
  border: 1px solid var(--line);
  color: var(--ink);
  border-bottom-left-radius: 4px;
}

[data-theme="dark"] .msg-bubble.role-assistant {
  background-color: var(--surface-2);
  border-color: var(--line-2);
}

.msg-bubble.role-assistant.role-error {
  border-color: var(--red);
  background-color: var(--red-soft);
  color: var(--red);
}

/* System message: Centered, subtle dashed separator */
.msg-bubble.role-system {
  align-self: center;
  max-width: 95%;
  background-color: transparent;
  color: var(--muted);
  font-size: 12px;
  text-align: center;
  border-bottom: 1px dashed var(--line);
  padding: 8px 12px;
  border-radius: 0;
  box-shadow: none;
}

.system-prompt-details {
  text-align: left;
  width: 100%;
}

.system-prompt-details summary {
  cursor: pointer;
  color: var(--faint);
  font-weight: 500;
  text-align: center;
  user-select: none;
  font-size: 11.5px;
  transition: color var(--motion-fast);
}

.system-prompt-details summary:hover {
  color: var(--ink);
}

.msg-system-content {
  margin-top: 8px;
  padding: 10px 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  max-height: 250px;
  overflow-y: auto;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--ink-soft);
  white-space: pre-wrap;
  text-align: left;
}

[data-theme="dark"] .msg-system-content {
  background: var(--surface-2);
  border-color: var(--line-2);
}

/* Thought process / Reasoning block inside assistant bubbles */
.msg-reasoning {
  margin-bottom: 10px;
  font-size: 11.5px;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  border: 1px dashed var(--line-2);
  padding: 8px 12px;
}

[data-theme="dark"] .msg-reasoning {
  background: var(--surface-3);
  border-color: var(--line);
}

.msg-reasoning details summary {
  cursor: pointer;
  color: var(--faint);
  font-weight: 500;
  user-select: none;
  transition: color var(--motion-fast);
}

.msg-reasoning details summary:hover {
  color: var(--ink);
}

.msg-thought-body {
  margin-top: 6px;
  color: var(--muted);
  font-style: italic;
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.45;
}

/* Tool call badges */
.msg-tool-calls {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}

.msg-tool-pill {
  font-size: 11px;
  font-family: var(--mono);
  padding: 3px 10px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--ink-soft);
}

[data-theme="dark"] .msg-tool-pill {
  background: var(--surface-3);
  border-color: var(--line-2);
  color: var(--ink);
}

/* Collapsible message bubbles (Show more / Show less) */
.msg-collapsible {
  display: flex;
  flex-direction: column;
  position: relative;
  width: 100%;
}

.msg-collapsible-body {
  position: relative;
  width: 100%;
}

.msg-collapsible.is-collapsed .msg-collapsible-body {
  max-height: 160px;
  overflow: hidden;
}

.msg-collapsible.is-collapsed .msg-collapsible-fade {
  display: block;
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 56px;
  pointer-events: none;
}

.msg-bubble.role-user .msg-collapsible.is-collapsed .msg-collapsible-fade {
  background: linear-gradient(to bottom, rgba(37, 99, 235, 0), rgba(37, 99, 235, 0.95) 75%, #2563eb);
}

[data-theme="dark"] .msg-bubble.role-user .msg-collapsible.is-collapsed .msg-collapsible-fade {
  background: linear-gradient(to bottom, rgba(29, 78, 216, 0), rgba(29, 78, 216, 0.95) 75%, #1d4ed8);
}

.msg-bubble.role-assistant .msg-collapsible.is-collapsed .msg-collapsible-fade {
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.95) 75%, var(--surface));
}

[data-theme="dark"] .msg-bubble.role-assistant .msg-collapsible.is-collapsed .msg-collapsible-fade {
  background: linear-gradient(to bottom, rgba(31, 31, 29, 0), rgba(31, 31, 29, 0.95) 75%, var(--surface-2));
}

.msg-collapsible.is-expanded .msg-collapsible-fade {
  display: none;
}

.msg-collapsible-actions {
  display: flex;
  align-items: center;
  margin-top: 10px;
}

.msg-bubble.role-user .msg-collapsible-actions {
  justify-content: flex-end;
}

.msg-bubble.role-assistant .msg-collapsible-actions {
  justify-content: flex-start;
}

.msg-collapsible-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 12px;
  font-size: 11.5px;
  font-weight: 500;
  line-height: 1.2;
  border-radius: var(--r-pill);
  cursor: pointer;
  background: var(--surface-3);
  border: 1px solid var(--line-2);
  color: var(--ink);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
  transition: background-color var(--motion-fast), color var(--motion-fast), border-color var(--motion-fast), transform var(--motion-fast);
  user-select: none;
}

.msg-collapsible-btn:hover {
  background: var(--line);
  color: var(--ink);
}

.msg-bubble.role-user .msg-collapsible-btn {
  background: rgba(255, 255, 255, 0.22);
  border: 1px solid rgba(255, 255, 255, 0.4);
  color: #ffffff;
  backdrop-filter: blur(4px);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
}

.msg-bubble.role-user .msg-collapsible-btn:hover {
  background: rgba(255, 255, 255, 0.35);
  border-color: rgba(255, 255, 255, 0.6);
  color: #ffffff;
}

.msg-expand-icon {
  transition: transform var(--motion-standard) var(--motion-ease);
}

.msg-collapsible.is-expanded .msg-expand-icon {
  transform: rotate(180deg);
}

.payload-summary {
  display: flex;
  align-items: center;
  gap: 8px 14px;
  flex-wrap: wrap;
  font-size: 11.5px;
  color: var(--muted);
  margin-bottom: 10px;
}

.payload-headers {
  display: grid;
  gap: 2px;
  margin-bottom: 12px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface);
}

.payload-header-row {
  display: grid;
  grid-template-columns: minmax(120px, 220px) 1fr;
  gap: 12px;
  font-size: 10.5px;
  line-height: 1.7;
}

.payload-header-row span:first-child {
  color: var(--faint);
}

.payload-header-row span:last-child {
  overflow-wrap: anywhere;
  color: var(--muted);
}

.payload-block + .payload-block {
  margin-top: 12px;
}

.payload-block-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 6px;
  font-size: 11.5px;
}

.payload-meta {
  color: var(--faint);
}

.payload-block-head .btn {
  margin-left: auto;
}

.payload-clip {
  font-size: 10.5px;
  color: var(--warn, #B9691F);
  margin-bottom: 6px;
}

.payload-pre {
  margin: 0;
  max-height: 340px;
  overflow: auto;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface);
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.6;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  tab-size: 2;
}

/* ---- broadcast console ---- */
.broadcast-form {
  display: grid;
  gap: 14px;
  margin-top: 4px;
}

.broadcast-switches {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
  min-height: 34px;
}

/* `.field label` is the form-row label rule and outranks `.switch`, so a switch
   placed inside a field collapses to a block: the track stops being a flex item,
   goes back to `inline`, drops its 34px, and leaves the knob floating over the
   caption. The component's own layout is restored here rather than by weakening
   the field rule every other form in the console depends on. */
.broadcast-switches .switch {
  display: inline-flex;
  margin-bottom: 0;
  color: var(--muted);
  font-weight: 400;
}

.broadcast-form-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.broadcast-form-actions .sec-note {
  color: var(--red);
}

.broadcast-composer-panel {
  scroll-margin-top: 104px;
}

.broadcast-row {
  display: flex;
  align-items: flex-start;
  gap: 18px;
  padding: 14px 0;
  border-bottom: 1px solid var(--line);
}

.broadcast-row:last-child {
  border-bottom: 0;
  padding-bottom: 2px;
}

.broadcast-row-main {
  flex: 1;
  min-width: 0;
}

.broadcast-row-head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 7px;
}

.broadcast-row-title {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -.01em;
}

.broadcast-row-body {
  margin: 6px 0 0;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--muted);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.broadcast-row-meta {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 8px;
  font-size: 11px;
  color: var(--faint);
}

.broadcast-row-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  justify-content: flex-end;
  flex: none;
}

/* Severity reads on the level pill alone. The row keeps the neutral chrome of
   every other list on the page, because an operator scanning ten announcements
   is looking for one label, not for ten differently coloured cards. */
.pill.broadcast-level.info {
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 35%, var(--line));
}

.pill.broadcast-level.success {
  color: var(--good);
  border-color: color-mix(in srgb, var(--good) 35%, var(--line));
}

.pill.broadcast-level.warning {
  color: var(--warn, #B9691F);
  border-color: color-mix(in srgb, var(--warn, #B9691F) 35%, var(--line));
}

.pill.broadcast-level.critical {
  color: var(--red);
  border-color: color-mix(in srgb, var(--red) 35%, var(--line));
}

@media (max-width: 720px) {
  .broadcast-row {
    flex-direction: column;
    gap: 10px;
  }

  .broadcast-row-actions {
    justify-content: flex-start;
  }
}

/* ---- broadcast: poll editor and what came back ---- */
.broadcast-options {
  display: grid;
  gap: 8px;
  margin-bottom: 10px;
}

.broadcast-option-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.broadcast-option-index {
  width: 20px;
  text-align: center;
  font-size: 11px;
  color: var(--faint);
  flex: none;
}

.broadcast-option-input {
  flex: 1;
  min-width: 0;
}

.broadcast-poll-field .optional {
  font-weight: 400;
}

.broadcast-responses {
  margin-top: 12px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface);
  display: grid;
  gap: 12px;
}

.broadcast-ack-stat {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 12px;
}

.broadcast-stat-figure {
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
}

.broadcast-stat-figure i,
.broadcast-poll-count i {
  font-style: normal;
  font-weight: 400;
  font-size: 11px;
  color: var(--faint);
  margin-left: 5px;
}

/* One bar style for both the Done count and every poll row: they answer the
   same question — what share of the people asked have replied — and drawing
   them differently would imply they do not. */
.broadcast-stat-bar {
  height: 6px;
  border-radius: 999px;
  background: var(--surface-3, var(--line));
  overflow: hidden;
  min-width: 60px;
}

.broadcast-stat-bar>span {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--accent);
}

.broadcast-stat-label {
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
}

.broadcast-poll-results {
  display: grid;
  gap: 7px;
}

.broadcast-poll-row {
  display: grid;
  grid-template-columns: minmax(90px, 190px) 1fr auto;
  align-items: center;
  gap: 12px;
}

.broadcast-poll-option {
  font-size: 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.broadcast-poll-count {
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

.auth-remember {
  margin: 4px 0 14px;
}

@media (max-width: 720px) {

  .broadcast-ack-stat,
  .broadcast-poll-row {
    grid-template-columns: 1fr auto;
  }

  .broadcast-ack-stat .broadcast-stat-bar,
  .broadcast-poll-row .broadcast-stat-bar {
    grid-column: 1 / -1;
  }
}
