/*
 * Operations console — one light theme.
 *
 * Every colour is a token on :root and nothing below the token block names a literal,
 * which is what keeps a palette change to this file's first forty lines.
 *
 * There is no dark theme and no toggle. The console carried both for a while, which
 * meant every new component had to be checked twice and the second check was the one
 * that got skipped — the log stream and the code blocks below are the only dark
 * surfaces left, and they are dark on purpose rather than by theme.
 *
 * Written unminified, unlike the version this replaces. That file was four
 * 6,000-column lines and every change to it was a diff nobody could read.
 */

:root {
  color-scheme: light;

  /* Ground is faintly violet, not neutral grey: white cards need to read as raised,
     and a cool ground does that without the shadow having to get heavy. */
  --bg:          #f2f3f9;
  --bg-2:        #0e1020;      /* the deliberate dark surfaces: log stream, code */
  --surface:     #ffffff;
  --surface-2:   #f7f8fc;
  --surface-3:   #eceef7;
  --line:        #e4e6f1;
  --line-soft:   #eef0f8;

  --ink:         #191b2e;
  --ink-2:       #656a85;
  --ink-3:       #9096b0;
  --ink-on-dark: #ccd2e8;

  --accent:      #5b4ce0;
  --accent-2:    #7b6df0;
  --accent-soft: #ebe8fd;
  --good:        #17a673;
  --good-soft:   #e2f6ee;
  --warn:        #c47f0a;
  --warn-soft:   #fcf1dc;
  --bad:         #e0455c;
  --bad-soft:    #fdeaed;
  --violet:      #a78bfa;
  --cyan:        #22b8cf;

  --radius:      18px;
  --radius-sm:   13px;

  /* Two shadows, both soft and violet-tinted. A neutral black shadow on this ground
     reads as dirt rather than depth. */
  --shadow:      0 1px 2px rgba(24, 27, 56, .04), 0 6px 20px rgba(24, 27, 56, .05);
  --shadow-lg:   0 2px 4px rgba(24, 27, 56, .05), 0 18px 44px rgba(24, 27, 56, .09);

  --mono: ui-monospace, "SF Mono", SFMono-Regular, "JetBrains Mono", Menlo, Consolas, monospace;
  --sans: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

/* ─── Base ─────────────────────────────────────────────────────────────── */

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 13.5px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

button, input, select { font: inherit; color: inherit; }
button { cursor: pointer; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

h1, h2, h3 { margin: 0; letter-spacing: -.02em; }

.hidden { display: none !important; }
.muted  { color: var(--ink-2); }
.faint  { color: var(--ink-3); }
.mono   { font-family: var(--mono); font-size: .92em; }
.num    { font-variant-numeric: tabular-nums; }

.eyebrow {
  color: var(--ink-3);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
}

.empty {
  padding: 34px;
  border: 1px dashed var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--ink-2);
  text-align: center;
  font-size: 12.5px;
}

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb {
  border: 3px solid transparent;
  border-radius: 8px;
  background: #d3d7e8;
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--ink-3); background-clip: content-box; }

/* ─── Sign-in ──────────────────────────────────────────────────────────── */

.auth-shell {
  min-height: 100vh;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(400px, 540px);
  padding: 14px;
  gap: 14px;
  background: var(--bg);
}

/* The one full-bleed brand moment in the product. Deep indigo rather than the page's
   accent so the sign-in reads as a door, and the console behind it as the room. */
.auth-art {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 56px;
  border-radius: 26px;
  color: #fff;
  background:
    radial-gradient(circle at 16% 8%, rgba(167, 139, 250, .55), transparent 46%),
    radial-gradient(circle at 88% 90%, rgba(34, 184, 207, .28), transparent 42%),
    linear-gradient(150deg, #4b3ecf, #2b2178);
}

.auth-art::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, .05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, .05) 1px, transparent 1px);
  background-size: 46px 46px;
  mask-image: linear-gradient(to bottom, #000, transparent 78%);
}

.auth-message { position: relative; z-index: 1; }
.auth-message h1 {
  margin: 0 0 18px;
  font-size: clamp(34px, 4.6vw, 58px);
  line-height: 1.04;
  letter-spacing: -.045em;
}
.auth-message p { max-width: 470px; margin: 0; color: #c8c6ef; font-size: 15.5px; line-height: 1.65; }

.auth-points { position: relative; z-index: 1; display: flex; flex-wrap: wrap; gap: 22px; color: #b3b0e4; font-size: 12px; }
.auth-points span::before {
  content: "";
  display: inline-block;
  width: 6px; height: 6px;
  margin-right: 8px;
  border-radius: 50%;
  background: #6ee7b7;
}

.auth-panel {
  display: grid;
  place-items: center;
  padding: 44px;
  border-radius: 26px;
  background: var(--surface);
  box-shadow: var(--shadow);
}
.login { width: min(100%, 348px); }
.login h2 { margin: 0 0 6px; font-size: 27px; letter-spacing: -.032em; }
.login > p { margin: 0 0 26px; color: var(--ink-2); }
.login .mobile-brand { display: none; margin-bottom: 34px; }
.login-error { min-height: 18px; margin: 12px 0 0; color: var(--bad); font-size: 12px; }

.field { margin-bottom: 14px; }
.field label { display: block; margin-bottom: 6px; color: var(--ink-2); font-size: 11.5px; font-weight: 650; }
.field input, .field select {
  width: 100%;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  transition: border-color .15s, box-shadow .15s, background .15s;
}
.field input:focus, .field select:focus {
  outline: none;
  background: var(--surface);
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.field input::placeholder { color: var(--ink-3); }

/* ─── Brand ────────────────────────────────────────────────────────────── */

.brand {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 17px;
  font-weight: 750;
  letter-spacing: -.03em;
}

/* Swap the mark for the real logo by replacing the .brand-mark element in the markup —
   this rule sizes whatever sits there, initials or an <img>. */
.brand-mark {
  flex: 0 0 34px;
  width: 34px; height: 34px;
  display: grid;
  place-items: center;
  border-radius: 11px;
  background: linear-gradient(140deg, var(--accent), #8b5cf6);
  color: #fff;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: -.02em;
}
.brand-mark svg { width: 66%; height: 66%; color: #fff; }
.brand-mark img { width: 100%; height: 100%; border-radius: inherit; object-fit: contain; }
.auth-art .brand { color: #fff; }
.auth-art .brand-mark { background: rgba(255, 255, 255, .16); backdrop-filter: blur(6px); }

/* ─── Shell ────────────────────────────────────────────────────────────── */

#app { display: none; min-height: 100vh; }

.sidebar {
  position: fixed;
  inset: 0 auto 0 0;
  z-index: 30;
  width: 240px;
  display: flex;
  flex-direction: column;
  padding: 20px 14px;
  background: var(--surface);
  border-right: 1px solid var(--line);
}

.sidebar .brand { padding: 4px 8px 18px; }

.nav { display: flex; flex-direction: column; gap: 3px; margin-top: 6px; overflow-y: auto; }
.nav-group { margin: 18px 10px 7px; color: var(--ink-3); font-size: 9.5px; font-weight: 750; letter-spacing: .13em; text-transform: uppercase; }

.nav button {
  position: relative;
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 9px 12px;
  border: 0;
  border-radius: 11px;
  background: transparent;
  color: var(--ink-2);
  font-size: 12.5px;
  font-weight: 600;
  text-align: left;
  transition: background .15s, color .15s;
}
.nav button:hover { color: var(--ink); background: var(--surface-2); }

/* Active is a tinted pill plus a bar hung off the sidebar's left padding, which is the
   one cue that survives at a glance when several counts are lit at once. */
.nav button.active { color: var(--accent); background: var(--accent-soft); font-weight: 700; }
.nav button.active::before {
  content: "";
  position: absolute;
  left: -14px;
  top: 50%;
  width: 3px; height: 20px;
  transform: translateY(-50%);
  border-radius: 0 3px 3px 0;
  background: var(--accent);
}

.nav .nav-icon { width: 16px; text-align: center; font-size: 13px; opacity: .9; }
.nav .nav-count {
  margin-left: auto;
  padding: 1px 7px;
  border-radius: 99px;
  background: var(--surface-3);
  color: var(--ink-2);
  font-size: 10px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.nav button.active .nav-count { background: #fff; color: var(--accent); }
.nav .nav-count.bad  { background: var(--bad);  color: #fff; }
.nav .nav-count.warn { background: var(--warn); color: #fff; }
.nav .nav-count:empty { display: none; }

/* The dark card at the bottom of the rail, carrying the one status an operator wants
   without navigating: is the server itself all right. */
.sidebar-foot {
  margin-top: auto;
  padding: 14px;
  border-radius: 16px;
  background: linear-gradient(160deg, #221c5c, #12142c);
  color: #fff;
}
.system-mini { display: flex; align-items: center; gap: 9px; font-size: 11.5px; font-weight: 650; }
.system-mini i {
  flex: 0 0 7px;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: #34d399;
  box-shadow: 0 0 0 4px rgba(52, 211, 153, .18);
}
.system-mini.problem i { background: #fb7185; box-shadow: 0 0 0 4px rgba(251, 113, 133, .2); }
.sidebar-foot p { margin: 8px 0 0; color: #a6a6d6; font-size: 10.5px; line-height: 1.5; }

.main { margin-left: 240px; min-width: 0; }

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  height: 70px;
  padding: 0 26px;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  border-bottom: 1px solid var(--line);
  backdrop-filter: blur(14px);
}
/* The title takes what is left and truncates. Without min-width:0 the flex item
   refuses to shrink below its content, so on a narrow screen the heading wrapped to
   four lines and pushed the actions — Sign out included — off the right edge. */
.topbar > div:first-child { min-width: 0; }
.topbar h1, .topbar p { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.topbar h1 { font-size: 18px; }
.topbar p  { margin: 2px 0 0; color: var(--ink-2); font-size: 11.5px; }
.top-actions { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }

/* The signed-in operator, where the reference puts it: far right of the topbar, the
   avatar carrying the identity and the name carrying the role. */
.who {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 6px 5px 5px;
  border: 1px solid var(--line);
  border-radius: 99px;
  background: var(--surface);
}
.who-avatar {
  flex: 0 0 30px;
  width: 30px; height: 30px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: linear-gradient(140deg, var(--accent), #8b5cf6);
  color: #fff;
  font-size: 11px;
  font-weight: 800;
  text-transform: uppercase;
}
.who-name { display: flex; flex-direction: column; line-height: 1.25; }
.who-name b { font-size: 11.5px; }
.who-name > span { color: var(--ink-3); font-size: 9.5px; }

.content { max-width: 1560px; margin: 0 auto; padding: 26px 26px 64px; }

.view { display: none; }
.view.active { display: block; animation: fade .2s ease-out; }
@keyframes fade { from { opacity: 0; transform: translateY(4px); } }

.mobile-menu { display: none; }

/* ─── Controls ─────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-height: 36px;
  padding: 8px 14px;
  border: 1px solid var(--line);
  border-radius: 11px;
  background: var(--surface);
  color: var(--ink);
  font-size: 12px;
  font-weight: 650;
  white-space: nowrap;
  transition: background .15s, border-color .15s, color .15s, box-shadow .15s;
}
.btn:hover { background: var(--surface-2); border-color: #d5d9ea; }
.btn:disabled { opacity: .5; cursor: default; }

.btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; box-shadow: 0 6px 16px rgba(91, 76, 224, .28); }
.btn-primary:hover { background: var(--accent-2); border-color: var(--accent-2); }
.btn-secondary { background: var(--accent-soft); border-color: transparent; color: var(--accent); }
.btn-secondary:hover { background: #e0dbfb; border-color: transparent; }
.btn-danger { color: var(--bad); }
.btn-danger:hover { background: var(--bad-soft); border-color: color-mix(in srgb, var(--bad) 35%, var(--line)); }
.btn-small { min-height: 30px; padding: 5px 11px; border-radius: 9px; font-size: 11px; }
.btn.on { background: var(--accent-soft); border-color: transparent; color: var(--accent); }

.icon { font-size: 14px; line-height: 1; }
.spin { display: inline-block; animation: spin .8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

.seg { display: inline-flex; padding: 3px; border: 1px solid var(--line); border-radius: 11px; background: var(--surface-2); }
.seg button {
  padding: 5px 12px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--ink-2);
  font-size: 11.5px;
  font-weight: 650;
}
.seg button.active { background: var(--surface); color: var(--accent); box-shadow: var(--shadow); }

.search {
  min-width: 200px;
  padding: 8px 13px;
  border: 1px solid var(--line);
  border-radius: 11px;
  background: var(--surface);
  font-size: 12px;
}
.search:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }

/* ─── Badges ───────────────────────────────────────────────────────────── */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 99px;
  font-size: 10.5px;
  font-weight: 700;
  white-space: nowrap;
}
.badge::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
.badge-good    { background: var(--good-soft); color: var(--good); }
.badge-bad     { background: var(--bad-soft);  color: var(--bad); }
.badge-warn    { background: var(--warn-soft); color: var(--warn); }
.badge-neutral { background: var(--surface-3); color: var(--ink-2); }
.badge-plain::before { display: none; }

/* ─── Panels ───────────────────────────────────────────────────────────── */

.panel {
  min-width: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
}

.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 17px 20px;
  border-bottom: 1px solid var(--line-soft);
}
.panel-head h2 { font-size: 14px; }
.panel-head p  { margin: 3px 0 0; color: var(--ink-2); font-size: 11px; }
.panel-tools { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.panel-body { padding: 20px; }
.panel + .panel, .section-space { margin-top: 18px; }

.grid-2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 18px; }
.grid-2-wide { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1.6fr); gap: 18px; }

/* ─── Status banner ────────────────────────────────────────────────────── */

.status-banner {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  margin-bottom: 18px;
  padding: 20px 22px;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: linear-gradient(100deg, var(--good-soft), var(--surface) 66%);
  box-shadow: var(--shadow);
}
.status-banner::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 4px;
  background: var(--good);
}
.status-banner.problem { background: linear-gradient(100deg, var(--bad-soft), var(--surface) 66%); }
.status-banner.problem::before { background: var(--bad); }

.status-main { display: flex; align-items: center; gap: 15px; min-width: 0; }
.status-icon {
  flex: 0 0 44px;
  width: 44px; height: 44px;
  display: grid;
  place-items: center;
  border-radius: 14px;
  background: var(--good);
  color: #fff;
  font-size: 17px;
  font-weight: 800;
}
.problem .status-icon { background: var(--bad); }
.status-copy h2 { margin-bottom: 4px; font-size: 15px; }
.status-copy p  { margin: 0; color: var(--ink-2); font-size: 12px; }
.status-time { white-space: nowrap; color: var(--ink-3); font-size: 11px; }

/* ─── KPI tiles ────────────────────────────────────────────────────────── */

.stats-grid { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 12px; margin-bottom: 18px; }

.stat-card {
  padding: 17px 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
  transition: transform .15s, box-shadow .15s;
}
.stat-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }
/* Two lines of room whether the label needs them or not, so "Lifetime tracked"
   wrapping does not drop its figure below the five figures beside it. */
.stat-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; min-height: 30px; }
.stat-label { color: var(--ink-3); font-size: 10px; font-weight: 750; letter-spacing: .08em; text-transform: uppercase; }
.stat-icon {
  flex: 0 0 28px;
  width: 28px; height: 28px;
  display: grid;
  place-items: center;
  border-radius: 9px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 11px;
  font-weight: 800;
}
.stat-card.tone-bad  .stat-icon { background: var(--bad-soft);  color: var(--bad); }
.stat-card.tone-warn .stat-icon { background: var(--warn-soft); color: var(--warn); }
.stat-card.tone-good .stat-icon { background: var(--good-soft); color: var(--good); }
.stat-value { margin: 12px 0 3px; font-size: 28px; font-weight: 750; letter-spacing: -.045em; font-variant-numeric: tabular-nums; }
.stat-note  { color: var(--ink-3); font-size: 10.5px; }

/* One filled tile, and it is the headline figure — the reference's own trick, and the
   reason it works there is that exactly one tile is filled. In flight is this
   console's headline: it is always present, always the first tile, and never carries
   a tone of its own. */
.stat-card:first-child {
  border-color: transparent;
  background: linear-gradient(150deg, #6d5cf0, #4a3ac9);
  color: #fff;
  box-shadow: 0 8px 24px rgba(91, 76, 224, .3);
}
.stat-card:first-child .stat-label,
.stat-card:first-child .stat-note { color: rgba(255, 255, 255, .8); }
.stat-card:first-child .stat-icon { background: rgba(255, 255, 255, .2); color: #fff; }

/* A tile in trouble stays white and turns its own figure red, rather than filling.
   Two or three tiles can go bad at once — carriers broken, lookups failing, phones
   quiet — and three filled tiles is a wall of colour that ranks nothing. */
.stat-card.tone-bad { border-color: color-mix(in srgb, var(--bad) 40%, var(--line)); }
.stat-card.tone-bad .stat-value { color: var(--bad); }
.stat-card.tone-warn .stat-value { color: var(--warn); }

/* ─── Charts ───────────────────────────────────────────────────────────── */

.workload { display: grid; grid-template-columns: 178px 1fr; align-items: center; gap: 24px; }
.donut-wrap { display: grid; place-items: center; }
.donut {
  position: relative;
  width: 164px; height: 164px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: conic-gradient(var(--accent) 0 var(--active-angle), #ddd9f7 var(--active-angle) 360deg);
}
.donut::after { content: ""; position: absolute; inset: 19px; border-radius: 50%; background: var(--surface); }
.donut-center { position: relative; z-index: 1; text-align: center; }
.donut-center b { display: block; font-size: 26px; font-weight: 750; letter-spacing: -.04em; font-variant-numeric: tabular-nums; }
.donut-center span { color: var(--ink-3); font-size: 10px; }

.legend { display: grid; gap: 13px; }
.legend-row { display: grid; grid-template-columns: 9px 1fr auto; align-items: center; gap: 10px; font-size: 12px; }
.legend-row i { width: 9px; height: 9px; border-radius: 3px; }
.legend-row strong { font-variant-numeric: tabular-nums; }
.legend-note { padding-top: 13px; border-top: 1px solid var(--line-soft); color: var(--ink-3); font-size: 10.5px; line-height: 1.5; }

.bars { display: grid; gap: 12px; }
.bar-row { display: grid; grid-template-columns: minmax(90px, 160px) 1fr 52px; align-items: center; gap: 12px; }
.bar-label { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: 11.5px; font-weight: 600; }
.bar-track { height: 9px; border-radius: 99px; background: var(--surface-3); overflow: hidden; }
.bar-fill { height: 100%; min-width: 4px; border-radius: 99px; background: linear-gradient(90deg, var(--accent), #8b5cf6); }
.bar-value { text-align: right; font-size: 11.5px; font-weight: 700; font-variant-numeric: tabular-nums; }

.chart-foot { display: flex; gap: 24px; margin-top: 18px; padding-top: 15px; border-top: 1px solid var(--line-soft); color: var(--ink-3); font-size: 10px; }
.chart-foot b { display: block; color: var(--ink); font-size: 15px; font-variant-numeric: tabular-nums; }

/* Stacked status ribbon */
.ribbon { display: flex; height: 14px; border-radius: 99px; overflow: hidden; background: var(--surface-3); }
.ribbon i { display: block; height: 100%; }
.ribbon-key { display: flex; flex-wrap: wrap; gap: 8px 18px; margin-top: 15px; }
.ribbon-key span { display: inline-flex; align-items: center; gap: 7px; color: var(--ink-2); font-size: 11px; }
.ribbon-key i { width: 8px; height: 8px; border-radius: 3px; }
.ribbon-key b { color: var(--ink); font-variant-numeric: tabular-nums; }

/* ─── Tables ───────────────────────────────────────────────────────────── */

.table-wrap { overflow: auto; border: 1px solid var(--line); border-radius: var(--radius-sm); }
table { width: 100%; border-collapse: collapse; font-size: 12px; }
thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 10px 13px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--line);
  color: var(--ink-3);
  font-size: 9.5px;
  font-weight: 750;
  letter-spacing: .07em;
  text-transform: uppercase;
  text-align: left;
  white-space: nowrap;
}
td { padding: 10px 13px; border-top: 1px solid var(--line-soft); white-space: nowrap; }
tbody tr:hover td { background: var(--surface-2); }
td.wrap { white-space: normal; min-width: 240px; overflow-wrap: anywhere; }
/*
 * One carrier error can be a few hundred characters of JSON. Unclamped it made a
 * single row eleven lines tall, in a table that routinely holds hundreds of rows —
 * the full text is on the cell's title.
 *
 * The clamp is on a div INSIDE the cell rather than on the cell, because clamping
 * needs `display: -webkit-box`, and setting that on a <td> replaces its
 * `display: table-cell`. Chrome currently keeps the row intact anyway — measured, it
 * is a pixel off the wrapped version — but a cell that is no longer a table cell is
 * not something to rely on across engines when a wrapper div costs nothing.
 */
.err-cell {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
  max-width: 360px;
}
td.right, th.right { text-align: right; font-variant-numeric: tabular-nums; }

.status-pill {
  display: inline-flex;
  padding: 3px 9px;
  border-radius: 99px;
  background: var(--surface-3);
  color: var(--ink-2);
  font-size: 10px;
  font-weight: 700;
}
.status-pill.DELIVERED { background: var(--good-soft); color: var(--good); }
.status-pill.IN_TRANSIT, .status-pill.PICKED_UP { background: var(--accent-soft); color: var(--accent); }
.status-pill.OUT_FOR_DELIVERY, .status-pill.DELAYED, .status-pill.HELD, .status-pill.UNDELIVERED { background: var(--warn-soft); color: var(--warn); }
.status-pill.ERROR, .status-pill.NOT_FOUND, .status-pill.UNKNOWN { background: var(--bad-soft); color: var(--bad); }

/* ─── Carrier cards ────────────────────────────────────────────────────── */

.carrier-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(292px, 1fr)); gap: 12px; }

.carrier-card {
  padding: 16px 17px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  transition: border-color .15s, box-shadow .15s;
}
.carrier-card:hover { box-shadow: var(--shadow); }
.carrier-card.broken { border-color: color-mix(in srgb, var(--bad) 45%, var(--line)); background: linear-gradient(180deg, var(--bad-soft), var(--surface) 40%); }
.carrier-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.carrier-name { font-size: 12.5px; font-weight: 700; }
/*
 * A carrier error is whatever the carrier said, and carriers say things like a JSON
 * body with a siteKey in it or a signed URL — hundreds of characters with no space to
 * break on. `overflow-wrap: anywhere` is the rule that makes those break at all;
 * without it the longest token sets the card's minimum width, the grid column cannot
 * shrink to it, and the text runs out of the card and across the page.
 *
 * Clamped to three lines because the full text is not the card's job — it is on the
 * title attribute, and on the Copy error button beside it.
 */
.carrier-meta {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
  overflow-wrap: anywhere;
  margin: 9px 0 11px;
  min-height: 28px;
  color: var(--ink-2);
  font-size: 10.5px;
  line-height: 1.45;
}
.carrier-copy { margin-bottom: 11px; color: var(--bad); }
.carrier-copy:hover { background: var(--bad-soft); border-color: color-mix(in srgb, var(--bad) 35%, var(--line)); }
.carrier-foot { display: flex; justify-content: space-between; gap: 8px; margin-top: 9px; color: var(--ink-3); font-size: 10px; }

/*
 * 24h column chart. One column per hour, stacked ok/error/blocked/throttled.
 *
 * The <i> is the track and is always full height, lit or not. The <span> inside it is
 * the bar. Drawing the track for every hour is what gives a sparse carrier a shape —
 * two lit hours read against twenty-two unlit ones, rather than as two marks adrift.
 */
.hours { display: flex; align-items: flex-end; gap: 2px; height: 46px; }
.hours i {
  flex: 1;
  min-width: 2px;
  height: 100%;
  display: flex;
  flex-direction: column-reverse;
  border-radius: 3px;
  overflow: hidden;
  background: var(--surface-3);
}
.hours i > span { display: flex; flex-direction: column-reverse; width: 100%; border-radius: 3px 3px 0 0; overflow: hidden; }
.hours i u { display: block; width: 100%; }
.hours u.ok      { background: var(--good); }
.hours u.err     { background: var(--bad); }
.hours u.blocked { background: #8b5cf6; }
.hours u.quota   { background: var(--warn); }
.hours-axis { display: flex; justify-content: space-between; margin-top: 6px; color: var(--ink-3); font-size: 9.5px; }

/* ─── Service card ─────────────────────────────────────────────────────── */

.service-card {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 15px;
  padding: 17px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}
.service-logo {
  width: 42px; height: 42px;
  display: grid;
  place-items: center;
  border-radius: 13px;
  background: linear-gradient(140deg, #8b5cf6, var(--accent));
  color: #fff;
  font-weight: 800;
}
.service-copy b { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; font-size: 12.5px; }
.service-copy p { margin: 0; color: var(--ink-2); font-size: 10.5px; line-height: 1.5; }
.service-stat { text-align: right; }
.service-stat strong { display: block; font-size: 20px; font-weight: 750; font-variant-numeric: tabular-nums; }
.service-stat span { color: var(--ink-3); font-size: 9.5px; text-transform: uppercase; letter-spacing: .06em; }

/* ─── Clients ──────────────────────────────────────────────────────────── */

.client-list { display: grid; gap: 12px; }
.client-card {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  overflow: hidden;
  transition: border-color .15s, box-shadow .15s;
}
.client-card:hover { box-shadow: var(--shadow); }

/* A revoked client is dimmed rather than hidden — it still holds shipment history, and
   an operator looking for "where did Acme go" needs to find it here, greyed, with the
   way back on it. Opacity alone would take the Restore button down with it. */
.client-card.revoked { background: var(--surface-2); border-style: dashed; }
.client-card.revoked .company-avatar { background: var(--surface-3); color: var(--ink-3); }
.client-card.revoked .company-name b,
.client-card.revoked .client-metric b { color: var(--ink-2); }

.client-main {
  display: grid;
  grid-template-columns: minmax(210px, 1.2fr) minmax(180px, .85fr) minmax(230px, 1fr) auto;
  align-items: center;
  gap: 16px;
  padding: 16px 17px;
}
.company { display: flex; align-items: center; gap: 12px; min-width: 0; }
.company-avatar {
  flex: 0 0 40px;
  width: 40px; height: 40px;
  display: grid;
  place-items: center;
  border-radius: 13px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 13px;
  font-weight: 800;
}
.company-name { min-width: 0; }
.company-name b { display: block; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: 13px; }
.company-name span { display: block; margin-top: 2px; color: var(--ink-3); font-size: 10px; }

.key-row { display: flex; align-items: center; gap: 6px; margin-top: 7px; }
.key-row code {
  padding: 2px 7px;
  border-radius: 6px;
  background: var(--surface-3);
  color: var(--ink-2);
  font-family: var(--mono);
  font-size: 9.5px;
}

.phone-state { display: flex; align-items: center; gap: 10px; }
.phone-icon {
  flex: 0 0 32px;
  width: 32px; height: 32px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  background: var(--good-soft);
  color: var(--good);
  font-size: 14px;
}
.phone-state.quiet .phone-icon, .phone-state.never .phone-icon { background: var(--warn-soft); color: var(--warn); }
.phone-state.disabled .phone-icon { background: var(--surface-3); color: var(--ink-3); }
.phone-copy b { display: block; font-size: 11.5px; }
.phone-copy span { display: block; margin-top: 3px; color: var(--ink-3); font-size: 9.5px; }
/* The build line carries a badge, and `.phone-copy b` above would blow it up to a
   full-width block. Sized down to sit inside the 9.5px line it shares. */
.phone-copy b.badge { display: inline-flex; font-size: 9px; padding: 2px 7px; }

.client-metrics { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.client-metric { padding-left: 12px; border-left: 2px solid var(--line-soft); }
.client-metric b { display: block; font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; }
.client-metric span { display: block; margin-top: 2px; color: var(--ink-3); font-size: 9.5px; }
.client-actions { display: flex; justify-content: flex-end; gap: 6px; flex-wrap: wrap; }

.awb-panel { display: none; padding: 0 17px 17px; }
.awb-panel.open { display: block; }

/* ─── Budget / capacity ────────────────────────────────────────────────── */

.budget-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(242px, 1fr)); gap: 11px; }
.budget-card { padding: 14px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface-2); }
/* Carrier name on one line, the scope wrapping under it if it must. Letting both wrap
   broke "Blue Dart" across two lines beside a scope that had room to spare. */
.budget-title { display: flex; justify-content: space-between; gap: 10px; font-size: 11px; font-weight: 700; }
.budget-title span:first-child { white-space: nowrap; }
.budget-title span:last-child { text-align: right; color: var(--ink-3); font-weight: 600; }
.budget-bar { height: 7px; margin-top: 10px; border-radius: 99px; background: var(--surface-3); overflow: hidden; }
.budget-bar i { display: block; height: 100%; border-radius: 99px; background: var(--accent); }

.cap-device { padding: 16px 0; border-top: 1px solid var(--line-soft); }
.cap-device:first-child { padding-top: 0; border-top: 0; }
.cap-dev-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 11px; }
.cap-dev-name { font-size: 12.5px; font-weight: 700; }
.cap-dev-sub { color: var(--ink-3); font-size: 10.5px; }
.cap-rows { display: grid; gap: 8px; }
.cap-row { display: grid; grid-template-columns: minmax(96px, 1.1fr) minmax(60px, 2fr) minmax(112px, 1.1fr); align-items: center; gap: 12px; font-size: 10.5px; }
.cap-carrier { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-weight: 650; }
.cap-carrier i { display: block; margin-top: 1px; color: var(--ink-3); font-size: 9.5px; font-style: normal; font-weight: 600; }
.cap-bar { height: 7px; border-radius: 99px; background: var(--surface-3); overflow: hidden; }
.cap-bar i { display: block; height: 100%; border-radius: 99px; background: var(--accent); }
.cap-bar i.warn { background: var(--warn); }
.cap-bar i.crit { background: var(--bad); }
.cap-fig { text-align: right; white-space: nowrap; font-weight: 700; font-variant-numeric: tabular-nums; }
.cap-fig i { display: block; margin-top: 1px; color: var(--ink-3); font-size: 9.5px; font-style: normal; font-weight: 600; }
.cap-tag {
  display: inline-block;
  margin-left: 5px;
  padding: 2px 6px;
  border-radius: 99px;
  background: var(--warn-soft);
  color: var(--warn);
  font-size: 8.5px;
  font-weight: 750;
}

/* ─── Errors ───────────────────────────────────────────────────────────── */

.sig-list { display: grid; gap: 10px; }
.sig-row {
  display: grid;
  grid-template-columns: 54px 1fr auto;
  align-items: center;
  gap: 13px;
  padding: 13px 15px;
  border: 1px solid var(--line);
  border-left: 3px solid var(--bad);
  border-radius: var(--radius-sm);
  background: var(--surface);
}
.sig-row:hover { box-shadow: var(--shadow); }
.sig-count { font-size: 20px; font-weight: 750; color: var(--bad); font-variant-numeric: tabular-nums; }
.sig-msg { min-width: 0; font-family: var(--mono); font-size: 11.5px; line-height: 1.45; word-break: break-word; }
.sig-where { margin-top: 5px; color: var(--ink-3); font-family: var(--sans); font-size: 10.5px; }
.sig-when { color: var(--ink-3); font-size: 10.5px; white-space: nowrap; }

/* ─── Logs ─────────────────────────────────────────────────────────────── */

.log-toolbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* Deliberately dark, in a light console. A log is read as a stream rather than a
   document, and the dark ground is what stops 700 monospace lines from glaring. */
.log-stream {
  max-height: min(62vh, 700px);
  overflow: auto;
  border: 1px solid #1c1f3a;
  border-radius: var(--radius-sm);
  background: var(--bg-2);
  font-family: var(--mono);
  font-size: 11.5px;
  line-height: 1.6;
}
.log-line {
  display: grid;
  grid-template-columns: 78px 52px 1fr;
  gap: 12px;
  padding: 3px 13px;
  border-left: 2px solid transparent;
  color: var(--ink-on-dark);
}
.log-line:hover { background: rgba(255, 255, 255, .04); }
.log-line.warn  { border-left-color: #f2b23c; }
.log-line.error { border-left-color: #fb7185; background: rgba(251, 113, 133, .08); }
.log-time  { color: #6b7099; }
.log-level { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; }
.log-line.info  .log-level { color: #6b7099; }
.log-line.warn  .log-level { color: #f2b23c; }
.log-line.error .log-level { color: #fb7185; }
.log-msg { word-break: break-word; white-space: pre-wrap; }
.log-msg mark { background: #f2b23c; color: #1a1206; border-radius: 3px; }
.log-tag { color: #4dd4e8; }

/* ─── Alerts / operators / misc ────────────────────────────────────────── */

.alert-list { display: grid; gap: 7px; max-height: 62vh; overflow: auto; }
.alert-row {
  display: grid;
  grid-template-columns: 84px 1fr auto;
  align-items: baseline;
  gap: 13px;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  font-size: 11.5px;
}
.alert-kind {
  padding: 3px 7px;
  border-radius: 99px;
  background: var(--surface-3);
  color: var(--ink-2);
  font-size: 8.5px;
  font-weight: 750;
  letter-spacing: .05em;
  text-align: center;
  text-transform: uppercase;
}
.alert-kind.carrier, .alert-kind.blocked, .alert-kind.disk { background: var(--bad-soft); color: var(--bad); }
.alert-kind.gemini, .alert-kind.backlog { background: var(--warn-soft); color: var(--warn); }
.alert-kind.recovery { background: var(--good-soft); color: var(--good); }
.alert-row > span { min-width: 0; overflow-wrap: anywhere; }
.alert-when { white-space: nowrap; color: var(--ink-3); font-size: 10.5px; }

.op-list { display: grid; gap: 8px; margin-bottom: 14px; }
.op-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface-2);
  font-size: 11.5px;
}
.op-row span { color: var(--ink-3); font-size: 10px; }

.form-row { display: grid; grid-template-columns: 1fr 1fr auto; gap: 10px; align-items: end; }
.form-row .field { margin: 0; }
.form-message { min-height: 16px; margin: 11px 0 0; color: var(--ink-2); font-size: 11px; }

.dev-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: 10px; margin-bottom: 14px; }
.dev-fact { padding: 12px 14px; border: 1px solid var(--line); border-radius: 13px; background: var(--surface-2); }
.dev-fact b { display: block; font-size: 12.5px; }
.dev-fact span { display: block; margin-top: 3px; color: var(--ink-3); font-size: 9px; letter-spacing: .06em; text-transform: uppercase; }
.dev-fact.warn { border-color: color-mix(in srgb, var(--warn) 45%, var(--line)); background: var(--warn-soft); }
.dev-fact.warn b { color: var(--warn); }

.run-bar { display: flex; align-items: flex-end; gap: 3px; height: 38px; margin: 4px 0 10px; }
.run-bar i { flex: 1; min-width: 2px; padding: 0; border: 0; border-radius: 3px 3px 0 0; background: var(--accent); }
.run-bar i.nosuccess { background: var(--warn); }
.run-bar i.none { background: var(--surface-3); }
.spark-note { display: flex; justify-content: space-between; color: var(--ink-3); font-size: 9.5px; }

.backlog-list { display: grid; gap: 9px; }
.backlog-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 13px 14px;
  border: 1px solid color-mix(in srgb, var(--warn) 40%, var(--line));
  border-radius: 13px;
  background: var(--warn-soft);
  font-size: 11.5px;
  overflow-wrap: anywhere;
}

.setup-content { color: var(--ink-2); font-size: 12.5px; line-height: 1.75; }
.setup-content code { padding: 2px 6px; border-radius: 6px; background: var(--surface-3); color: var(--ink); font-family: var(--mono); font-size: 11px; }
.setup-content pre {
  padding: 15px;
  overflow: auto;
  border-radius: var(--radius-sm);
  background: var(--bg-2);
  color: var(--ink-on-dark);
  font-family: var(--mono);
  font-size: 11.5px;
  line-height: 1.65;
}
.setup-content pre code { padding: 0; background: none; color: inherit; font-size: inherit; }

/* ─── Responsive ───────────────────────────────────────────────────────── */

@media (max-width: 1400px) {
  .stats-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 1180px) {
  .grid-2, .grid-2-wide { grid-template-columns: 1fr; }
  .client-main { grid-template-columns: 1fr 1fr; }
  .client-actions { justify-content: flex-start; }
}

@media (max-width: 860px) {
  .sidebar { transform: translateX(-100%); transition: transform .2s; box-shadow: var(--shadow-lg); }
  .sidebar.open { transform: none; }
  .main { margin-left: 0; }
  .mobile-menu { display: inline-flex; }
  .topbar { padding: 0 16px; }
  .content { padding: 20px 16px 48px; }
  .auth-shell { grid-template-columns: 1fr; padding: 0; gap: 0; }
  .auth-art { display: none; }
  .auth-panel { min-height: 100vh; padding: 26px; border-radius: 0; box-shadow: none; }
  .login .mobile-brand { display: flex; }
  .workload { grid-template-columns: 1fr; }
  .status-time { display: none; }
}

@media (max-width: 980px) {
  .who-name { display: none; }
}

@media (max-width: 620px) {
  .stats-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 9px; }
  .topbar .btn .label { display: none; }
  /* The chip sheds its frame and avatar here and is just the Sign out button — the
     one part of it that does something. */
  .who { padding: 0; border: 0; background: none; }
  .who-avatar { display: none; }
  /* Heading over tools, rather than a heading squeezed into a column beside them. */
  .panel-head { flex-wrap: wrap; }
  .panel-head > div:first-child { flex: 1 0 100%; }
  .search { min-width: 0; width: 100%; }
  .client-main { grid-template-columns: 1fr; }
  .form-row { grid-template-columns: 1fr; }
  .log-line { grid-template-columns: 62px 1fr; }
  .log-line .log-level { display: none; }
  .sig-row { grid-template-columns: 44px 1fr; }
  .sig-when { display: none; }
}
