/* ── Theme tokens ──────────────────────────────────────────────────────────
   Dark is the default. `[data-theme="light"]` below is the "Tinted Paper"
   light theme. The `<html>` tag carries `data-theme`, rendered server-side
   from the session (see /set-theme) and resolved client-side when the user
   preference is "system".
   `*-rgb` tokens hold a bare "R,G,B" triplet so a rule can pick its own alpha
   via rgba(var(--brand-rgb), .12) — CSS has no alpha channel override.
   ------------------------------------------------------------------------ */
:root {
  /* surface / structure */
  --surface-bg: #06131a;
  --surface-bg-grid: rgba(89, 239, 208, 0.06);
  --surface-panel: rgba(5, 18, 24, 0.9);
  --surface-raised: #0b2028;
  --surface-sunken: #040d11;
  --surface-overlay: rgba(2, 8, 11, 0.72);
  --surface-grad-1: #051018;
  --surface-grad-2: #09151d;
  --surface-grad-3: #050b10;
  --surface-deep-rgb: 4, 13, 16;
  --tint-rgb: 255, 255, 255;
  --border: rgba(89, 239, 208, 0.28);
  --border-strong: rgba(89, 239, 208, 0.45);
  --shadow-soft: rgba(0, 0, 0, 0.20);
  --shadow-mid: rgba(0, 0, 0, 0.40);
  --shadow-strong: rgba(0, 0, 0, 0.60);

  /* text */
  --text-primary: #d6f7ee;
  --text-primary-rgb: 214, 247, 238;
  --text-muted: #89b7ae;
  --text-muted-rgb: 137, 183, 174;
  --text-faint: #759c93;
  --text-inverse: #08210f;
  --link: #59efd0;
  --link-hover: #8ef5df;

  /* brand — split from status-ok and chart series 1 on purpose; they share a
     value in dark but light theme moves them independently. Do not re-merge. */
  --brand: #59efd0;
  --brand-rgb: 89, 239, 208;
  --emphasis: #a9ff4d;
  --emphasis-rgb: 169, 255, 77;

  /* command safety */
  --cmd-read: #58e7ff;
  --cmd-read-rgb: 88, 231, 255;
  --cmd-read-soft: rgba(88, 231, 255, 0.18);
  --cmd-write: #8cff4f;
  --cmd-write-rgb: 140, 255, 79;
  --cmd-write-soft: rgba(140, 255, 79, 0.18);

  /* status */
  --status-ok: #59efd0;
  --status-ok-rgb: 89, 239, 208;
  --status-ok-bg: rgba(89, 239, 208, 0.12);
  --status-warn: #f0bd55;
  --status-warn-rgb: 240, 189, 85;
  --status-warn-bg: rgba(240, 189, 85, 0.12);
  --status-error: #ff7b72;
  --status-error-rgb: 255, 123, 114;
  --status-error-bg: rgba(255, 123, 114, 0.12);
  --status-info: #58a6ff;
  --status-info-rgb: 88, 166, 255;
  --status-info-bg: rgba(88, 166, 255, 0.12);
  --status-neutral: #8b949e;
  --status-neutral-rgb: 139, 148, 158;
  --status-neutral-bg: rgba(139, 148, 158, 0.12);

  /* traffic direction (IN/OUT) */
  --dir-in: #59efd0;
  --dir-out: #58a6ff;

  /* IP version / protocol */
  --ip-v4: #59efd0;
  --ip-v6: #c08cff;
  --ip-v6-rgb: 192, 140, 255;
  --proto-tcp: #5bd3ff;
  --proto-tcp-rgb: 91, 211, 255;
  --proto-udp: #59efd0;
  --proto-icmp: #e6af3c;

  /* chart chrome */
  --chart-axis: rgba(137, 183, 174, 0.35);
  --chart-grid: rgba(137, 183, 174, 0.12);
  --chart-axis-label: #6a9189;
  /* Cytoscape external-node labels: dim in dark, but on paper a faint ink at
     10px falls under AA — light theme steps it up to --text-muted. */
  --topo-label-dim: var(--text-faint);
  --chart-crosshair: rgba(89, 239, 208, 0.55);
  --chart-tooltip-bg: #0b2028;
  --chart-tooltip-border: rgba(89, 239, 208, 0.28);
  --chart-empty: #3a4f4b;
  --chart-area-from: rgba(89, 239, 208, 0.22);
  --chart-area-to: rgba(89, 239, 208, 0);

  /* categorical scale — indices 1-5 are the deuteranopia/protanopia-safe
     subset (blue, orange, teal, violet, red). Assign in order; never reorder. */
  --cat-1: #58a6ff;
  --cat-2: #f0a24d;
  --cat-3: #59efd0;
  --cat-4: #c08cff;
  --cat-5: #ff7b72;
  --cat-6: #a9ff4d;
  --cat-7: #5bd3ff;
  --cat-8: #ff9ecb;

  --display: 'Rajdhani', system-ui, sans-serif;
  --mono: 'Space Mono', ui-monospace, monospace;

  /* legacy aliases — pre-token rules still reference these (~540 usages) */
  --bg: var(--surface-bg);
  --bg-primary: var(--surface-bg);
  --bg-alt: var(--surface-raised);
  --panel: var(--surface-panel);
  --line: var(--border);
  --text: var(--text-primary);
  --fg: var(--text-primary);
  --muted: var(--text-muted);
  --accent: var(--brand);
  --accent-hot: var(--emphasis);
  --read-accent: var(--cmd-read);
  --read-accent-soft: var(--cmd-read-soft);
  --write-accent: var(--cmd-write);
  --write-accent-soft: var(--cmd-write-soft);
  --error: var(--status-error);
  --warning: var(--status-warn);
  --success: var(--status-ok);

  /* motion - one enter transition for content that arrives (.eg-reveal) */
  --motion-dur: 200ms;
  --motion-ease: cubic-bezier(0.2, 0.8, 0.2, 1);
}

[data-theme="light"] {
  --surface-bg: #eef6f3;
  --surface-bg-grid: rgba(15, 158, 131, 0.05);
  --surface-panel: #ffffff;
  --surface-raised: #f6fbf9;
  --surface-sunken: #e7f2ee;
  --surface-overlay: rgba(13, 36, 32, 0.45);
  --surface-grad-1: #f4faf8;
  --surface-grad-2: #eef6f3;
  --surface-grad-3: #e8f2ee;
  --surface-deep-rgb: 255, 255, 255;
  --tint-rgb: 13, 36, 32;
  --border: rgba(13, 120, 100, 0.22);
  --border-strong: rgba(13, 120, 100, 0.40);
  --shadow-soft: rgba(13, 36, 32, 0.06);
  --shadow-mid: rgba(13, 36, 32, 0.10);
  --shadow-strong: rgba(13, 36, 32, 0.16);

  --text-primary: #0d2420;
  --text-primary-rgb: 13, 36, 32;
  --text-muted: #3e5f58;
  --text-muted-rgb: 62, 95, 88;
  --text-faint: #506c66;
  --text-inverse: #ffffff;
  --link: #0a725e;
  --link-hover: #095c4d;

  --brand: #0a725e;
  --brand-rgb: 10, 114, 94;
  --emphasis: #4a6f11;
  --emphasis-rgb: 74, 111, 17;

  --cmd-read: #0b6b93;
  --cmd-read-rgb: 11, 107, 147;
  --cmd-read-soft: rgba(11, 107, 147, 0.12);
  --cmd-write: #447e1b;
  --cmd-write-rgb: 68, 126, 27;
  --cmd-write-soft: rgba(68, 126, 27, 0.12);

  --status-ok: #0a725e;
  --status-ok-rgb: 10, 114, 94;
  --status-ok-bg: rgba(10, 114, 94, 0.10);
  --status-warn: #805b0d;
  --status-warn-rgb: 128, 91, 13;
  --status-warn-bg: rgba(128, 91, 13, 0.10);
  --status-error: #bb392f;
  --status-error-rgb: 187, 57, 47;
  --status-error-bg: rgba(187, 57, 47, 0.10);
  --status-info: #0f6fae;
  --status-info-rgb: 15, 111, 174;
  --status-info-bg: rgba(15, 111, 174, 0.10);
  --status-neutral: #5c6f6b;
  --status-neutral-rgb: 92, 111, 107;
  --status-neutral-bg: rgba(92, 111, 107, 0.10);

  --dir-in: #0a725e;
  --dir-out: #0f6fae;

  --ip-v4: #0a725e;
  --ip-v6: #7a4fc9;
  --ip-v6-rgb: 122, 79, 201;
  --proto-tcp: #0f6fae;
  --proto-tcp-rgb: 15, 111, 174;
  --proto-udp: #0a725e;
  --proto-icmp: #805b0d;

  --chart-axis: rgba(62, 95, 88, 0.35);
  --chart-grid: rgba(62, 95, 88, 0.14);
  --chart-axis-label: #3e5f58;
  --topo-label-dim: var(--text-muted);
  --chart-crosshair: rgba(10, 114, 94, 0.55);
  --chart-tooltip-bg: #ffffff;
  --chart-tooltip-border: rgba(13, 120, 100, 0.30);
  --chart-empty: #b7c7c2;
  --chart-area-from: rgba(10, 114, 94, 0.16);
  --chart-area-to: rgba(10, 114, 94, 0);

  --cat-1: #0a5f8a;
  --cat-2: #a85d0e;
  --cat-3: #0a725e;
  --cat-4: #7a4fc9;
  --cat-5: #bb392f;
  --cat-6: #557b17;
  --cat-7: #0e7a90;
  --cat-8: #a83e7a;
}


* {
  box-sizing: border-box;
}

body {
  margin: 0;
  min-height: 100vh;
  color: var(--text);
  font-family: "Rajdhani", sans-serif;
  background:
    radial-gradient(circle at top, rgba(var(--brand-rgb),0.15), transparent 30%),
    linear-gradient(180deg, var(--surface-grad-1) 0%, var(--surface-grad-2) 45%, var(--surface-grad-3) 100%);
}

.background-grid {
  position: fixed;
  inset: 0;
  background-image:
    linear-gradient(rgba(var(--brand-rgb),0.06) 1px, transparent 1px),
    linear-gradient(90deg, rgba(var(--brand-rgb),0.06) 1px, transparent 1px);
  background-size: 36px 36px;
  mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.9), transparent);
  pointer-events: none;
}

.shell {
  width: 100%;
  padding: 0 0 48px;
}

.shell-auth {
  min-height: 100vh;
  display: grid;
  place-items: center;
}

/* ── App navbar ── */
.hero {
  position: sticky;
  top: 0;
  z-index: 200;
  margin-bottom: 28px;
  background: rgba(var(--surface-deep-rgb),0.97);
  border-bottom: 1px solid rgba(var(--brand-rgb),0.1);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}

.brand-lockup {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
  flex-shrink: 0;
}

.brand-home-link {
  display: inline-flex;
  align-items: center;
  color: inherit;
  text-decoration: none;
}

.brand-home-link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
}

.brand-logo {
  height: 34px;
  width: auto;
  filter: drop-shadow(0 2px 10px var(--shadow-strong));
}

/* The cream logo is invisible on paper — swap in the dark-ink variant. Same
   artwork, single fill changed, so `content` avoids touching 13 templates. */
[data-theme="light"] .brand-logo {
  content: url("/static/logo-horizontal-ink.svg");
}

[data-theme="light"] .auth-logo {
  content: url("/static/logo-stacked-ink.svg");
}

.auth-brand {
  margin-bottom: 22px;
  align-items: center;
  flex-direction: column;
  gap: 14px;
  text-align: center;
}

.auth-logo {
  height: auto;
  width: clamp(200px, 28vw, 280px);
}

.auth-brand .lede {
  max-width: 430px;
  margin-left: auto;
  margin-right: auto;
}

.auth-footer {
  margin-top: 24px;
  padding-top: 18px;
  border-top: 1px solid rgba(var(--brand-rgb),0.1);
  font-size: 0.8rem;
  color: var(--muted);
  line-height: 1.55;
  text-align: center;
}

.auth-footer p {
  margin: 0 0 6px;
}

.auth-footer a {
  color: var(--accent);
  text-decoration: none;
  font-family: "Space Mono", monospace;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  transition: color 0.15s;
}

.auth-footer a:hover {
  color: var(--text);
  text-decoration: underline;
}

.hero-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 64px;
  gap: 16px;
  padding: 0 20px;
}

.session-box {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
  border: none;
  background: transparent;
  padding: 0;
  min-width: 0;
}

.session-user {
  display: flex;
  flex-direction: column;
  line-height: 1.3;
  padding-right: 10px;
  border-right: 1px solid rgba(var(--brand-rgb),0.14);
}

.session-box strong {
  display: block;
  font-size: 0.88rem;
  margin: 0;
  color: var(--text);
}

.session-box small {
  display: block;
}

.session-box .button-secondary {
  width: auto;
  min-height: 32px;
  margin-top: 0;
  padding: 0 12px;
  font-size: 0.75rem;
  white-space: nowrap;
}

.session-box .session-link-button {
  width: auto;
  min-height: 32px;
  margin-top: 0;
  padding: 0 12px;
  line-height: 30px;
  font-size: 0.75rem;
  white-space: nowrap;
}

.session-box form {
  margin: 0;
}

.eyebrow {
  margin: 0 0 8px;
  color: var(--accent-hot);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-size: 0.85rem;
}

h1,
h2,
p {
  margin: 0;
}

p { text-wrap: pretty; }

h1 {
  font-size: clamp(2.2rem, 6vw, 4.4rem);
  line-height: 0.95;
  text-transform: uppercase;
}

.lede,
.panel-header p,
.field span,
.meta-label,
.status,
small {
  color: var(--muted);
}

.lede {
  margin-top: 12px;
  max-width: 720px;
  font-size: 1.15rem;
}

.panel {
  position: relative;
  margin-top: 18px;
  padding: 22px;
  border: 1px solid var(--line);
  background: linear-gradient(180deg, rgba(var(--surface-deep-rgb),0.92), rgba(var(--surface-deep-rgb),0.92));
  box-shadow: 0 0 0 1px rgba(var(--brand-rgb),0.08), 0 18px 50px var(--shadow-mid);
  overflow: hidden;
}

.panel::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, rgba(var(--brand-rgb),0.08), transparent 35%);
  pointer-events: none;
}

.field-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.field-inline-details {
  padding: 10px 12px;
  border: 1px solid rgba(var(--brand-rgb),0.18);
  background: rgba(var(--surface-deep-rgb),0.72);
}

.field-inline-detail-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin-top: 8px;
}

.field-inline-detail-label {
  display: block;
  margin-bottom: 4px;
  color: var(--muted);
  font-family: "Space Mono", monospace;
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.field-inline-details strong,
.field-inline-details small {
  display: block;
}

.field-inline-details strong {
  color: var(--text);
  font-size: 0.95rem;
}

.field-inline-details small {
  line-height: 1.4;
  word-break: break-word;
}

.field span,
.meta-label {
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.82rem;
}

select,
button,
input,
textarea {
  border: 1px solid rgba(var(--brand-rgb),0.35);
  background: rgba(var(--surface-deep-rgb),0.95);
  color: var(--text);
  font-family: "Space Mono", monospace;
  font-size: 0.95rem;
}

::placeholder { color: var(--text-faint); opacity: 1; }
/* Base for any link without its own color; else the browser blue and purple show. */
a { color: var(--link); }

select {
  min-height: 46px;
  padding: 10px 12px;
}

.command-select-theme.command-theme-read {
  border-color: rgba(var(--cmd-read-rgb),0.45);
  box-shadow: inset 0 0 0 1px rgba(var(--cmd-read-rgb),0.08);
}

.command-select-theme.command-theme-write {
  border-color: rgba(var(--cmd-write-rgb),0.4);
  box-shadow: inset 0 0 0 1px rgba(var(--cmd-write-rgb),0.08);
}

input {
  min-height: 46px;
  padding: 10px 12px;
}

textarea {
  width: 100%;
  min-height: 110px;
  padding: 10px 12px;
  resize: vertical;
}

.device-meta {
  flex: 0 0 100%;
  min-width: 0;
  display: block;
  margin: 0;
  order: 2;
}

/* Command bar: single compact horizontal line instead of vertical card */
.meta-card[data-meta-card="command"] {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 7px 12px;
}
.meta-card[data-meta-card="command"] .meta-label { display: none; }
.meta-card[data-meta-card="command"] strong {
  display: inline;
  margin: 0;
  font-size: 0.9rem;
  white-space: nowrap;
}
.meta-card[data-meta-card="command"] small {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: 0.85rem;
  color: var(--muted);
}

/* A form with one input puts it beside the command bar instead of on a row
   of its own. */
#command-form:has(.dynamic-grid > .field:only-child) .device-meta {
  flex: 1 1 0;
  align-self: flex-end;
}
#command-form:has(.dynamic-grid > .field:only-child) .dynamic-fields {
  flex: 0 0 auto;
}
#command-form:has(.dynamic-grid > .field:only-child) .dynamic-grid {
  grid-template-columns: auto;
}

.meta-card {
  padding: 10px 12px;
  border: 1px solid rgba(var(--emphasis-rgb),0.18);
  background: rgba(var(--surface-deep-rgb),0.78);
}

.meta-card.command-theme-read {
  border-color: var(--read-accent-soft);
  background: linear-gradient(180deg, rgba(var(--cmd-read-rgb),0.06), rgba(var(--surface-deep-rgb),0.78));
}

.meta-card.command-theme-write {
  border-color: var(--write-accent-soft);
  background: linear-gradient(180deg, rgba(var(--cmd-write-rgb),0.06), rgba(var(--surface-deep-rgb),0.78));
}

.meta-card strong,
.meta-card small {
  display: block;
}

.meta-card strong {
  margin: 4px 0 3px;
  font-size: 1rem;
}

.command-type-pill {
  display: inline-block;
  padding: 1px 8px;
  margin-right: 8px;
  border: 1px solid transparent;
  font-family: "Space Mono", monospace;
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.command-type-pill.command-theme-read {
  color: var(--read-accent);
  border-color: rgba(var(--cmd-read-rgb),0.28);
  background: rgba(var(--cmd-read-rgb),0.08);
}

.command-type-pill.command-theme-write {
  color: var(--write-accent);
  border-color: rgba(var(--cmd-write-rgb),0.26);
  background: rgba(var(--cmd-write-rgb),0.08);
}

.action-row {
  flex: 0 0 100%;
  margin-top: 4px;
}

.action-row-inline {
  margin-top: 0;
  margin-bottom: 16px;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.action-row-inline .inline-action-form {
  display: inline-flex;
}

.route-filter-form {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 12px;
  align-items: end;
  margin: 0 0 16px;
}

.command-help {
  flex: 0 0 100%;
  margin-top: 0;
  order: 4;
}
.command-help:empty { display: none; }

.dynamic-fields {
  flex: 1;
  min-width: 0;
  margin-top: 0;
  align-self: center;
  order: 3;
}

/* Full-width controls (multiselect, peer tables, textarea) drop to their own row */
.dynamic-fields:has(.checkbox-list),
.dynamic-fields:has(textarea),
.dynamic-fields:has(.table-wrap) {
  flex: 0 0 100%;
}

.command-plan-live {
  flex: 0 0 100%;
  margin-top: 0;
  order: 5;
}

.command-plan-header {
  margin-bottom: 12px;
}

.command-plan-copy {
  color: var(--muted);
  font-size: 1rem;
}

.loading-panel {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px;
  border: 1px solid rgba(var(--brand-rgb),0.18);
  background: rgba(var(--surface-deep-rgb),0.78);
}

.loading-panel strong,
.loading-panel small {
  display: block;
}

.loading-panel strong {
  color: var(--text);
  margin-bottom: 4px;
}

.dynamic-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
}

.field-wide {
  grid-column: span 2;
}

.field-full {
  grid-column: 1 / -1;
}

.dynamic-row {
  display: flex;
  gap: 14px;
  align-items: flex-end;
  flex-wrap: wrap;
}

.dynamic-row .field {
  flex: 0 0 auto;
}

.dynamic-row .field input[type="text"],
.dynamic-row .field input[type="search"] {
  flex: 1 1 auto;
  width: 100%;
  min-width: 160px;
}

.dynamic-row .field:has(input[type="text"]),
.dynamic-row .field:has(input[type="search"]) {
  flex: 1 1 200px;
}

/* A select sizes to its longest option; in a row it shares the width instead. */
.dynamic-row .field:has(select) {
  flex: 2 1 360px;
  min-width: 0;
}

.dynamic-row .field select {
  width: 100%;
  min-width: 0;
}

.field-submit {
  flex: 0 0 auto;
}

.dynamic-submit-button {
  min-height: 46px;
  padding: 0 20px;
  font-family: "Space Mono", monospace;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  background: var(--accent);
  color: var(--bg-primary);
  border: 1px solid var(--accent);
  cursor: pointer;
  transition: filter 0.15s;
  white-space: nowrap;
}

.dynamic-submit-button:hover {
  filter: brightness(1.12);
}

.hidden {
  display: none !important;
}

.checklist-toolbar {
  display: flex;
  gap: 10px;
  margin-bottom: 10px;
}

.checklist-filters {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 220px);
  gap: 10px;
  margin-bottom: 10px;
}

/* The two filters are search boxes. The magnifier and the placeholder are
   what say so - the label alone read as one more field to fill in. */
.checklist-filter {
  position: relative;
}

.checklist-filter-input {
  min-height: 40px;
  width: 100%;
  padding-left: 34px;
}

.checklist-filter::after {
  content: "";
  position: absolute;
  left: 12px;
  bottom: 13px;
  width: 13px;
  height: 13px;
  border: 1.5px solid var(--muted);
  border-radius: 50%;
  box-shadow: 5px 5px 0 -1.5px var(--muted);
  pointer-events: none;
}

.checkbox-list {
  display: grid;
  gap: 8px;
  max-height: min(62vh, 560px);
  overflow-x: auto;
  overflow-y: auto;
  padding: 0 12px 12px;
  border: 1px solid rgba(var(--brand-rgb),0.18);
  background: rgba(var(--surface-deep-rgb),0.95);
}

.checkbox-table {
  display: grid;
  min-width: 1180px;
}

.checkbox-table-head,
.checkbox-row {
  display: grid;
  grid-template-columns: 34px 170px 240px 90px 120px 110px 100px 210px 210px;
  gap: 0;
}

.checkbox-table-peer-compact {
  min-width: 700px;
}

.checkbox-table-peer-compact .checkbox-table-head,
.checkbox-table-peer-compact .checkbox-row {
  grid-template-columns: 34px minmax(130px, 1fr) minmax(160px, 1.6fr) minmax(80px, .8fr) minmax(90px, .9fr) minmax(90px, .9fr);
}

.checkbox-table-peer-mini {
  min-width: 700px;
}

.checkbox-table-peer-mini .checkbox-table-head,
.checkbox-table-peer-mini .checkbox-row {
  grid-template-columns: 34px minmax(130px, 1fr) minmax(180px, 1.8fr) minmax(80px, .8fr) minmax(110px, 1fr);
}

.checkbox-list-compact {
  max-height: 280px;
}

.checkbox-table-head {
  position: sticky;
  top: 0;
  z-index: 1;
  background: rgba(var(--surface-deep-rgb),0.98);
  color: var(--accent-hot);
  font-family: "Space Mono", monospace;
  font-size: 0.76rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.checkbox-table-head > div {
  padding: 10px 12px;
  border-bottom: 1px solid rgba(var(--brand-rgb),0.18);
}

.checkbox-item {
  border: 1px solid rgba(var(--brand-rgb),0.08);
  background: rgba(var(--brand-rgb),0.03);
  transition: background 140ms ease, border-color 140ms ease, box-shadow 140ms ease, transform 140ms ease;
}

.checkbox-row {
  align-items: stretch;
  cursor: pointer;
}

.checkbox-row > div {
  padding: 7px 12px;
  color: var(--text);
  font-family: "Space Mono", monospace;
  font-size: 0.78rem;
  line-height: 1.35;
  border-bottom: 1px solid rgba(var(--brand-rgb),0.08);
  word-break: break-word;
}

.checkbox-row > .checkbox-cell,
.checkbox-table-head > div:first-child {
  padding-left: 8px;
  padding-right: 8px;
}

.checkbox-row:hover > div {
  background: rgba(var(--brand-rgb),0.04);
}

.checkbox-row.is-selected {
  border-color: rgba(var(--emphasis-rgb),0.24);
  box-shadow: 0 0 0 1px rgba(var(--emphasis-rgb),0.08);
  transform: translateY(-1px);
}

.checkbox-row.is-selected > div {
  background: linear-gradient(180deg, rgba(var(--emphasis-rgb),0.05), rgba(var(--brand-rgb),0.04));
}

.checkbox-row.is-selected > .checkbox-cell {
  box-shadow: inset 3px 0 0 var(--accent-hot);
}

.checkbox-cell {
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  line-height: 0;
}

.checkbox-input {
  position: absolute;
  inset: 0;
  margin: 0;
  cursor: pointer;
  opacity: 0;
}

.checkbox-indicator {
  width: 16px;
  height: 16px;
  border: 1.5px solid var(--muted);
  border-radius: 4px;
  background: transparent;
  display: block;
  position: relative;
  pointer-events: none;
  transition: border-color 140ms ease, box-shadow 140ms ease, background 140ms ease;
}

.checkbox-indicator::after {
  content: "";
  position: absolute;
  left: 4px;
  top: 0;
  width: 5px;
  height: 9px;
  border: solid rgb(var(--surface-deep-rgb));
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
  opacity: 0;
}

.checkbox-row:hover .checkbox-indicator {
  border-color: var(--text-muted);
}

.checkbox-input:focus-visible + .checkbox-indicator {
  box-shadow: 0 0 0 2px rgba(var(--brand-rgb),0.12);
}

.checkbox-input:checked + .checkbox-indicator {
  border-color: var(--accent-hot);
  background: var(--accent-hot);
}

.checkbox-input:checked + .checkbox-indicator::after {
  opacity: 1;
}

.checkbox-empty {
  color: var(--muted);
  font-family: "Space Mono", monospace;
  font-size: 0.9rem;
}

button {
  min-height: 36px;
  padding: 0 18px;
  cursor: pointer;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: 0.78rem;
}

button:disabled {
  cursor: wait;
  opacity: 0.7;
}

.button-secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 36px;
  padding: 0 16px;
  border: 1px solid rgba(var(--brand-rgb),0.35);
  background: transparent;
  color: var(--text);
  font-family: "Space Mono", monospace;
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  margin-top: 0;
  width: auto;
}

.button-secondary:hover {
  border-color: var(--text-muted);
  color: var(--accent);
}

.session-link-button {
  display: block;
  min-height: 36px;
  margin-top: 12px;
  width: 100%;
  padding: 0 18px;
  border: 1px solid rgba(var(--brand-rgb),0.35);
  background: rgba(var(--surface-deep-rgb),0.95);
  color: var(--text);
  font-family: "Space Mono", monospace;
  font-size: 0.8rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-align: center;
  text-decoration: none;
  line-height: 34px;
}

.session-link-button:hover {
  color: var(--accent-hot);
}

.checklist-action {
  margin-top: 0;
  width: auto;
}

.inline-action-form {
  margin: 0;
}

.peer-link-button {
  min-height: 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent);
  font-family: "Space Mono", monospace;
  font-size: 0.84rem;
  letter-spacing: 0;
  text-transform: none;
  text-align: left;
}

.peer-link-button:hover {
  color: var(--accent-hot);
  text-decoration: underline;
}

.peer-action-cell {
  position: relative;
  display: inline-block;
}

.peer-action-toggle {
  display: inline-block;
}

.peer-action-menu {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 40;
  min-width: 190px;
  max-width: min(240px, calc(100vw - 24px));
  padding: 6px;
  border: 1px solid rgba(var(--brand-rgb),0.24);
  background: rgba(var(--surface-deep-rgb),0.98);
  box-shadow: 0 12px 28px var(--shadow-mid);
  display: grid;
  gap: 6px;
}

.peer-action-option {
  width: 100%;
  min-height: 32px;
  padding: 0 10px;
  text-align: left;
  font-size: 0.7rem;
  letter-spacing: 0.08em;
}

.panel-header {
  margin-bottom: 16px;
}

.panel-header h2 {
  font-size: 1.45rem;
  text-transform: uppercase;
}

.summary-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
  margin-bottom: 18px;
}

.summary-card {
  padding: 14px;
  border: 1px solid rgba(var(--brand-rgb),0.24);
  background: rgba(var(--surface-deep-rgb),0.82);
}

.summary-card strong {
  display: block;
  margin-top: 8px;
  font-size: 1.2rem;
}

.summary-card-wide {
  grid-column: span 2;
}

.summary-grid-routing {
  gap: 10px;
  margin-bottom: 14px;
}

.summary-grid-routing-meta {
  grid-template-columns: minmax(220px, 1.2fr) minmax(120px, 0.34fr) minmax(170px, 0.5fr);
}

.summary-grid-routing-stats {
  grid-template-columns: minmax(96px, 0.24fr) minmax(96px, 0.24fr) minmax(360px, 1.52fr);
}

.summary-card-routing {
  padding: 11px 13px;
}

.summary-card-routing strong {
  margin-top: 6px;
  font-size: 1rem;
  line-height: 1.3;
}

.summary-card-routing-command strong {
  font-size: 0.94rem;
  word-break: break-word;
}

.community-change-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
  margin-bottom: 18px;
}

.community-card {
  padding: 14px;
  border: 1px solid rgba(var(--brand-rgb),0.24);
  background: rgba(var(--surface-deep-rgb),0.82);
}

.community-card h3 {
  margin: 10px 0 8px;
  font-size: 1rem;
  color: var(--accent-hot);
  text-transform: uppercase;
}

.table-wrap {
  overflow-x: auto;
  border: 1px solid rgba(var(--brand-rgb),0.18);
  background: rgba(var(--surface-deep-rgb),0.9);
}

.table-filters {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 10px;
  padding: 14px;
  border-bottom: 1px solid rgba(var(--brand-rgb),0.12);
  background: rgba(var(--brand-rgb),0.03);
}

.peer-table-filters {
  grid-template-columns: minmax(180px, 1.45fr) minmax(170px, 0.9fr) minmax(110px, 0.52fr) minmax(160px, 0.9fr) minmax(210px, 1.55fr);
  padding: 8px 10px;
  gap: 8px;
}

/* The text inputs carry their label as placeholder, and the type toggle and
   state select name themselves, so the label row above them is dropped. */
.peer-table-filters .field > span {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}

.peer-table-filters input,
.peer-table-filters select,
.peer-table-filters .type-filter-toggle-group,
.peer-table-filters .type-filter-toggle {
  min-height: 34px;
}

.peer-table-filters input,
.peer-table-filters select {
  padding: 5px 10px;
}

/* Command output: the summary is one compact strip of label + value pairs,
   not a row of cards. A second summary-grid continues the same box. */
#output-content .summary-grid {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 28px;
  margin-bottom: 10px;
  padding: 8px 14px;
  border: 1px solid rgba(var(--brand-rgb),0.18);
  background: rgba(var(--surface-deep-rgb),0.82);
}

#output-content .summary-grid + .summary-grid {
  margin-top: -10px;
  border-top: 0;
}

#output-content .summary-card {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
}

#output-content .summary-card strong {
  display: inline;
  margin: 0;
  font-size: 0.95rem;
  overflow-wrap: anywhere;
}

#output-content .summary-card small {
  display: inline;
  margin-top: 0;
}

.peer-summary-alert {
  color: var(--status-error);
}

/* BGP routing-table lookup: one summary panel (state, matched prefix, best
   path, then the command), then one row per path with the best one marked. */
.rt-summary {
  --rt-state: var(--status-neutral);
  --rt-state-rgb: var(--status-neutral-rgb);
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 12px;
  padding: 12px 16px;
  border: 1px solid rgba(var(--brand-rgb),0.18);
  border-left: 3px solid var(--rt-state);
  background: rgba(var(--surface-deep-rgb),0.82);
}

.rt-state-ok { --rt-state: var(--status-ok); --rt-state-rgb: var(--status-ok-rgb); }
.rt-state-partial { --rt-state: var(--status-warn); --rt-state-rgb: var(--status-warn-rgb); }
.rt-state-down { --rt-state: var(--status-error); --rt-state-rgb: var(--status-error-rgb); }

.rt-summary-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 12px;
}

.rt-state-badge {
  padding: 1px 8px;
  border: 1px solid var(--rt-state);
  color: var(--rt-state);
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.rt-summary-prefix {
  font-family: var(--mono);
  font-size: 1.35rem;
}

.rt-summary-covers,
.rt-summary-meta {
  color: var(--text-muted);
  font-size: 0.85rem;
}

.rt-summary-best {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 24px;
  font-family: var(--mono);
}

.rt-key {
  margin-right: 8px;
  color: var(--text-muted);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.rt-summary-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
}

.rt-summary-meta code {
  color: var(--text-faint);
  font-size: 0.85rem;
  overflow-wrap: anywhere;
}

/* Few columns: fit the result area instead of the 1320px result-table minimum. */
.result-table.rt-table {
  min-width: 0;
}

.rt-table td {
  vertical-align: top;
}

.rt-table .rt-row-best td {
  background: rgba(var(--status-ok-rgb),0.07);
}

.rt-table .rt-row-best td:first-child {
  box-shadow: inset 3px 0 0 var(--status-ok);
}

.rt-table .rt-row-invalid td {
  color: var(--text-muted);
}

.rt-badge-best,
.rt-badge-alt,
.rt-badge-invalid {
  display: inline-block;
  padding: 0 6px;
  border: 1px solid currentColor;
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
}

.rt-badge-best { color: var(--status-ok); }
.rt-badge-alt { color: var(--status-neutral); }
.rt-badge-invalid { color: var(--status-warn); }

.rt-reason,
.rt-more {
  display: block;
  margin-top: 4px;
  color: var(--text-muted);
  font-size: 0.78rem;
}

.rt-row-invalid .rt-reason { color: var(--status-warn); }

.rt-hop,
.rt-path {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.rt-hop span,
.rt-cell-network strong {
  white-space: nowrap;
}

.rt-hop small,
.rt-path-names {
  color: var(--text-muted);
  font-size: 0.8rem;
}

.rt-path-asns {
  overflow-wrap: anywhere;
}

.rt-path-names {
  overflow-wrap: anywhere;
}

.rt-num {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.rt-communities {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  max-width: 28ch;
}

.rt-communities span {
  padding: 0 5px;
  border: 1px solid var(--border);
  font-size: 0.78rem;
  white-space: nowrap;
}

.rt-alt-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
  color: var(--text-muted);
  font-size: 0.85rem;
  cursor: pointer;
}

/* Alternate paths of a longer-prefixes lookup stay hidden until asked for. */
.rt-table .rt-alt { display: none; }
.rt-paths:has(.rt-alt-check:checked) .rt-table .rt-alt { display: table-row; }
.rt-table .rt-alt td { color: var(--text-muted); }

/* Ping / tracert result: verdict in the summary strip, KPIs, then one bar
   per reply (ping) or one row per hop (tracert). Raw output collapses. */
#output-content .tb-verdict {
  padding: 1px 8px;
  border: 1px solid currentColor;
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.tb-state-ok { color: var(--status-ok); }
.tb-state-partial { color: var(--status-warn); }
.tb-state-down { color: var(--status-error); }
.tb-state-unknown { color: var(--status-neutral); }
.tb-faint { color: var(--text-faint); }
.tb-note { margin: 0 0 10px; }

.tb-kpis {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  margin-bottom: 10px;
}

.tb-kpi,
.tb-panel {
  padding: 10px 14px;
  border: 1px solid rgba(var(--brand-rgb),0.18);
  background: rgba(var(--surface-deep-rgb),0.82);
}

.tb-kpi {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.tb-kpi strong {
  font-family: var(--mono);
  font-size: 1.6rem;
  line-height: 1.1;
}

.tb-kpi small {
  color: var(--text-muted);
  font-size: 0.8rem;
}

.tb-panel { margin-bottom: 10px; }

.tb-seq {
  display: flex;
  gap: 8px;
  height: 120px;
  margin-top: 8px;
}

.tb-seq-col {
  display: flex;
  flex: 1 1 0;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  max-width: 72px;
  font-family: var(--mono);
  font-size: 0.78rem;
}

.tb-seq-track {
  display: flex;
  flex: 1;
  align-items: flex-end;
  width: 100%;
  border-bottom: 1px solid var(--chart-axis);
}

.tb-seq-bar {
  width: 100%;
  background: var(--brand);
}

.tb-seq-n { color: var(--text-faint); }
.tb-seq-col.is-lost .tb-seq-val,
.tb-seq-col.is-lost .tb-seq-n { color: var(--status-error); }
.tb-seq-col.is-lost .tb-seq-track { border-bottom: 2px solid var(--status-error); }

.tb-hops {
  margin-top: 8px;
  font-family: var(--mono);
  font-size: 0.82rem;
}

.tb-hop {
  display: grid;
  grid-template-columns: 40px minmax(130px, 1.4fr) minmax(150px, 1.2fr) minmax(120px, 0.5fr) minmax(170px, 0.9fr);
  gap: 12px;
  align-items: center;
  min-height: 26px;
  padding: 3px 6px;
  border-bottom: 1px solid var(--chart-grid);
}

.tb-hop-head {
  color: var(--text-faint);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.tb-hop-n { color: var(--text-muted); text-align: right; white-space: nowrap; }
.tb-hop.is-target { background: var(--status-ok-bg); }
.tb-hop.is-target .tb-hop-n { color: var(--status-ok); }

.tb-hop-stack {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.tb-hop-stack > span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tb-hop-net { color: var(--text-muted); }

.tb-hop-probes {
  display: flex;
  gap: 12px;
}

.tb-hop-rtt {
  display: flex;
  align-items: center;
  gap: 8px;
}

.tb-hop-track {
  flex: 1;
  height: 6px;
  background: var(--chart-grid);
}

.tb-hop-bar {
  display: block;
  height: 100%;
  background: var(--brand);
}

.tb-hop-rtt strong {
  min-width: 60px;
  font-weight: normal;
  text-align: right;
}

@media (max-width: 900px) {
  .tb-kpis { grid-template-columns: 1fr; }
  .tb-hop { grid-template-columns: 28px minmax(0, 1fr) minmax(0, 1fr); }
  .tb-hop-head span:nth-child(n+4),
  .tb-hop-probes,
  .tb-hop-rtt { display: none; }
}

.peer-filter-as input {
  max-width: 12ch;
}

.type-filter-toggle-group {
  display: flex;
  gap: 8px;
  min-height: 46px;
}

/* One segmented control: the buttons share borders instead of floating apart. */
.dynamic-toggle-group {
  display: flex;
  gap: 0;
  min-height: 46px;
  flex-wrap: wrap;
}

.dynamic-toggle-button + .dynamic-toggle-button {
  margin-left: -1px;
}

.dynamic-toggle-button:hover {
  color: var(--text);
  position: relative;
  z-index: 1;
}

.dynamic-toggle-button {
  min-height: 46px;
  padding: 0 16px;
  border: 1px solid rgba(var(--brand-rgb),0.2);
  background: rgba(var(--surface-deep-rgb),0.82);
  color: var(--muted);
  font-family: "Space Mono", monospace;
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  cursor: pointer;
}

.dynamic-toggle-button.is-active {
  position: relative;
  z-index: 2;
  color: var(--accent-hot);
  border-color: rgba(var(--cmd-write-rgb),0.36);
  background: rgba(var(--cmd-write-rgb),0.08);
  box-shadow: inset 0 0 0 1px rgba(var(--cmd-write-rgb),0.12);
}

.type-filter-toggle {
  flex: 1 1 0;
  min-height: 46px;
  padding: 0 14px;
  border: 1px solid rgba(var(--brand-rgb),0.2);
  background: rgba(var(--surface-deep-rgb),0.82);
  color: var(--muted);
  font-family: "Space Mono", monospace;
  font-size: 0.86rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  cursor: pointer;
  transition: border-color 140ms ease, color 140ms ease, background 140ms ease, box-shadow 140ms ease;
}

.type-filter-toggle.is-active {
  color: var(--accent-hot);
  border-color: rgba(var(--cmd-write-rgb),0.36);
  background: rgba(var(--cmd-write-rgb),0.08);
  box-shadow: inset 0 0 0 1px rgba(var(--cmd-write-rgb),0.12);
}

.type-filter-toggle:hover {
  border-color: var(--text-faint);
  color: var(--text);
}

.type-filter-toggle:focus-visible {
  outline: none;
  border-color: var(--text-muted);
  box-shadow: 0 0 0 2px rgba(var(--brand-rgb),0.14);
}

.table-empty {
  padding: 14px;
  color: var(--muted);
  font-family: "Space Mono", monospace;
  font-size: 0.9rem;
}

.result-table {
  width: 100%;
  border-collapse: collapse;
  min-width: 1320px;
  font-family: "Space Mono", monospace;
  font-size: 0.84rem;
}

/* Router ID sits under the peer and the two policies share a column: fits 1440px. */
.peer-result-table {
  min-width: 1100px;
}

.peer-result-table-ipv6 {
  min-width: 1240px;
  font-size: 0.8rem;
}

.peer-result-table-ipv6 th,
.peer-result-table-ipv6 td {
  padding: 9px 10px;
}

.history-table {
  min-width: 1200px;
}
.history-table td:nth-child(1), .history-table td:nth-child(4) { white-space: nowrap; }

.history-toolbar {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 220px 220px;
  gap: 14px;
  margin-bottom: 18px;
}

.history-status-pill {
  display: inline-block;
  min-width: 90px;
  padding: 4px 10px;
  border: 1px solid rgba(var(--brand-rgb),0.22);
  font-family: "Space Mono", monospace;
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-align: center;
}

.history-status-success {
  color: var(--accent-hot);
  border-color: rgba(var(--emphasis-rgb),0.28);
  background: rgba(var(--emphasis-rgb),0.08);
}

.history-status-error {
  color: var(--error);
  border-color: rgba(var(--status-error-rgb),0.3);
  background: rgba(var(--status-error-rgb),0.08);
}

.history-operation-read {
  color: var(--read-accent);
  border-color: rgba(var(--cmd-read-rgb),0.28);
  background: rgba(var(--cmd-read-rgb),0.08);
}

.history-operation-write {
  color: var(--write-accent);
  border-color: rgba(var(--cmd-write-rgb),0.28);
  background: rgba(var(--cmd-write-rgb),0.08);
}

.history-command-details {
  margin-top: 10px;
}

.history-params {
  font-size: 0.75rem;
  color: var(--muted);
  word-break: break-all;
}

.history-command-details summary {
  cursor: pointer;
  color: var(--accent);
  font-family: "Space Mono", monospace;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.history-command-details .terminal {
  margin-top: 10px;
}

.result-table th,
.result-table td {
  padding: 10px 12px;
  border-bottom: 1px solid rgba(var(--brand-rgb),0.12);
  text-align: left;
  vertical-align: top;
}

.result-table th {
  color: var(--accent-hot);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  background: rgba(var(--brand-rgb),0.06);
}

.result-table tr:hover td {
  background: rgba(var(--brand-rgb),0.04);
}

.peer-group-badge {
  display: inline-block;
  margin-top: 6px;
  padding: 2px 8px;
  border: 1px solid rgba(var(--brand-rgb),0.16);
  color: var(--muted);
  background: rgba(var(--brand-rgb),0.05);
  font-family: "Space Mono", monospace;
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.peer-grouped-0 td {
  background: rgba(var(--brand-rgb),0.045);
}

.peer-grouped-1 td {
  background: rgba(var(--cmd-write-rgb),0.045);
}

.peer-grouped-2 td {
  background: rgba(var(--cmd-read-rgb),0.045);
}

.peer-grouped:hover td {
  filter: brightness(1.04);
}

.peer-alert td {
  background: rgba(var(--status-warn-rgb),0.06);
}

.peer-alert td:first-child {
  box-shadow: inset 2px 0 0 rgba(var(--status-error-rgb),0.42);
}

.peer-alert:hover td {
  background: rgba(var(--status-warn-rgb),0.09);
}

.peer-state-alert {
  color: var(--status-warn);
  text-shadow: 0 0 10px rgba(var(--status-warn-rgb),0.12);
}

.metric-cell {
  white-space: nowrap;
}

.nowrap-cell {
  white-space: nowrap;
}

.peer-address-cell,
.peer-type-cell,
.peer-router-id-cell,
.peer-as-cell,
.peer-state-cell,
.peer-uptime-cell {
  white-space: nowrap;
}

.peer-as-meta {
  display: block;
  margin-top: 4px;
  color: var(--muted);
  font-family: "Rajdhani", sans-serif;
  font-size: 0.88rem;
  line-height: 1.1;
  white-space: normal;
}

.peer-description-cell,
.peer-policy-cell {
  overflow-wrap: anywhere;
  word-break: break-word;
}

.peer-result-table-ipv6 .peer-description-cell {
  max-width: 18ch;
}

.peer-result-table-ipv6 .peer-policy-cell {
  max-width: 14ch;
}

.routing-result-table {
  min-width: 1220px;
}

.routing-result-table-ipv6 {
  min-width: 900px;
}

.routing-cell-network,
.routing-cell-prefix,
.routing-cell-next-hop,
.routing-cell-interface,
.routing-cell-from,
.routing-cell-peer-router-id,
.routing-cell-duration,
.routing-cell-med,
.routing-cell-local-pref,
.routing-cell-pref-val,
.routing-cell-status {
  white-space: nowrap;
}

.routing-cell-description,
.routing-cell-attributes,
.routing-cell-path {
  overflow-wrap: anywhere;
  word-break: break-word;
}

.routing-cell-from-combined {
  min-width: 14ch;
}

.route-from-cell {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.route-from-peer {
  white-space: nowrap;
}

.route-from-router-id {
  white-space: nowrap;
  color: var(--muted);
  font-size: 0.82rem;
}

.routing-cell-metrics {
  white-space: nowrap;
}

.route-metrics-cell {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-variant-numeric: tabular-nums;
}

.route-metric-key {
  display: inline-block;
  min-width: 4ch;
  margin-right: 4px;
  color: var(--muted);
  font-size: 0.70rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.as-path-cell {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.as-path-raw {
  overflow-wrap: anywhere;
  word-break: break-word;
}

.as-path-origin {
  color: var(--accent-hot);
}

.as-names-wrap {
  display: inline-block;
}

.as-names-toggle {
  display: block;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  color: var(--accent);
  font-size: 0.72rem;
  font-family: inherit;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.as-names-toggle:hover {
  text-decoration: underline;
}

.as-path-chip-list[hidden] {
  display: none;
}

.as-path-chip-list {
  /* position/top/left set by JS via getBoundingClientRect to escape overflow containers */
  position: fixed;
  z-index: 300;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 8px;
  background: var(--bg-alt);
  border: 1px solid rgba(var(--brand-rgb),0.2);
  min-width: 14rem;
  max-width: 40rem;
}

.as-path-chip {
  display: inline-flex;
  flex-direction: column;
  gap: 2px;
  max-width: 24ch;
  padding: 6px 8px;
  border: 1px solid rgba(var(--brand-rgb),0.16);
  background: rgba(var(--brand-rgb),0.04);
}

.as-path-chip strong {
  color: var(--accent-hot);
  font-size: 0.72rem;
}

.as-path-chip small {
  color: var(--muted);
  font-family: "Rajdhani", sans-serif;
  font-size: 0.82rem;
  line-height: 1.1;
}

.metric-stack {
  display: inline-flex;
  flex-direction: column;
  gap: 4px;
}

.metric-label {
  display: inline-block;
  min-width: 52px;
  margin-right: 8px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.72rem;
}

.metric-value {
  display: inline-block;
}

.status {
  margin-bottom: 12px;
  font-family: "Space Mono", monospace;
}

.status.success {
  color: var(--accent-hot);
}

.status.warning {
  color: var(--status-warn);
}

.status.info {
  color: var(--accent);
}

/* Form hint under a command form: reference text, not a status line. */
.status.info.command-help-text {
  margin: 6px 0 12px;
  color: var(--text-muted);
  font-size: 0.72rem;
  line-height: 1.5;
}

.status.error {
  color: var(--error);
}

.loading-output {
  margin-bottom: 16px;
}

/* The one enter transition of the app, on every page: content fades up
   instead of popping in. CSS restarts an animation whenever an element goes
   from display:none to shown, whatever hid it (.hidden, the hidden attribute,
   style.display, a closed <details>), so a listed element replays it on every
   unhide with no JS. Always-visible containers, and rows a periodic re-render
   recreates (the device panel's interface/peer detail and its Sankey box),
   get .eg-reveal restarted by egReveal() in index.html instead. The exit side
   is egHide() in index.html. Filtered table rows and tooltips stay instant.
   `translate`, not `transform`, so it composes with an element's own transform
   (#eg-loading-pill centering). `backwards` only: nothing stays applied after
   the run, so no stacking context is left behind for dropdowns inside. */
@keyframes eg-reveal { from { opacity: 0; translate: 0 6px; } }
@keyframes eg-fade { from { opacity: 0; } }
.eg-reveal,
/* command form, write plan, loading panel */
.command-plan-live,
#action-row,
.loading-output,
/* device panel, pinned graphs, dashboard loading pill */
.ddp-panel,
.ddp-pinned-strip,
#eg-loading-pill,
/* views: command panes, dashboard tabs, no-device state */
.workspace-pane,
.dash-tab-body,
#ws-empty-state,
/* popover, modal, accordion */
.peer-action-menu,
.dm-dlg,
details[open] > :not(summary),
/* admin: create card, edit row, fields picked by a type or target switch */
.adm-create,
.adm-edit-row,
[data-types],
[data-target-status],
[data-nfy],
[data-incident-only],
[data-vec-list] {
  animation: eg-reveal var(--motion-dur) var(--motion-ease) backwards;
}
/* A full-screen layer only fades: a translate would uncover a strip. */
.dm-bd { animation: eg-fade var(--motion-dur) var(--motion-ease) backwards; }
@media (prefers-reduced-motion: reduce) {
  :root { --motion-dur: 0ms; }
}

#output-content.is-loading {
  opacity: 0.35;
  transition: opacity 120ms ease;
  pointer-events: none;
}

.terminal {
  margin: 0;
  padding: 18px;
  min-height: 320px;
  white-space: pre-wrap;
  word-break: break-word;
  border: 1px solid rgba(var(--brand-rgb),0.18);
  background: var(--surface-sunken);
  color: var(--text-primary);
  font-family: "Space Mono", monospace;
  line-height: 1.5;
}

.terminal-compact {
  min-height: 0;
  padding: 12px;
}

.raw-output {
  margin-top: 18px;
}

.raw-output summary {
  cursor: pointer;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: 12px;
}

.raw-output h3 {
  margin: 14px 0 10px;
  font-size: 0.95rem;
  color: var(--accent-hot);
  font-family: "Space Mono", monospace;
}

.command-plan {
  margin-top: 18px;
}

.command-plan h3 {
  margin: 0 0 10px;
  font-size: 1rem;
  color: var(--accent-hot);
  font-family: "Space Mono", monospace;
}

@keyframes pulse {
  0%,
  100% {
    transform: scale(1);
    opacity: 0.9;
  }
  50% {
    transform: scale(0.88);
    opacity: 0.55;
  }
}
@media (prefers-reduced-motion: reduce) {
  .mit-inc-active, .mit-strip-alert .mit-strip-dot, .csb-badge { animation: none; }
}

.auth-panel {
  width: min(560px, calc(100vw - 24px));
}

.auth-form {
  display: grid;
  gap: 14px;
  margin-top: 20px;
}

.auth-form .action-row {
  display: flex;
  justify-content: center;
}

.auth-form .field span {
  text-align: left;
}

@media (max-width: 900px) {
  .field-grid,
  .device-meta,
  .summary-grid,
  .dynamic-grid,
  .community-change-grid {
    grid-template-columns: 1fr;
  }

  .summary-card-wide {
    grid-column: auto;
  }

  .table-filters {
    grid-template-columns: 1fr;
  }

  .peer-filter-as input {
    max-width: none;
  }

  .history-toolbar {
    grid-template-columns: 1fr;
  }

  .hero-bar {
    height: auto;
    padding: 10px 12px;
    flex-wrap: wrap;
    gap: 10px;
  }

  .session-box {
    flex-wrap: wrap;
    flex-shrink: 1;
    max-width: 100%;
    gap: 8px;
  }

  .field-wide {
    grid-column: auto;
  }

  .shell {
    width: min(100vw - 20px, 1450px);
    margin: 0 auto;
    padding-top: 20px;
  }

  .panel {
    padding: 16px;
  }

  .route-filter-form {
    grid-template-columns: 1fr;
  }

  .field-inline-detail-grid {
    grid-template-columns: 1fr;
    gap: 10px;
  }

  .loading-panel {
    align-items: flex-start;
  }
}

/* ── Site footer ── */
.site-footer {
  margin-top: 32px;
  padding: 12px 0 4px;
  border-top: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-family: "Space Mono", monospace;
  font-size: 0.72rem;
  color: var(--muted);
}

.footer-sep {
  opacity: 0.4;
}

.footer-version {
  color: var(--muted);
  text-decoration: none;
  transition: opacity 0.15s;
}

.footer-version:hover {
  opacity: 0.75;
  text-decoration: underline;
}

.footer-feedback-link {
  color: var(--accent);
  text-decoration: none;
  transition: opacity 0.15s;
}

.footer-feedback-link:hover {
  opacity: 0.75;
  text-decoration: underline;
}

/* ── Changelog page ── */
.changelog-panel {
}

.changelog-panel .panel-header p {
  margin: 6px 0 0;
  font-size: 0.9rem;
  color: var(--muted);
}

.changelog-list {
  display: flex;
  flex-direction: column;
  gap: 0;
  margin-top: 24px;
}

.changelog-entry {
  padding: 20px 0;
  border-bottom: 1px solid var(--line);
}

.changelog-entry:last-child {
  border-bottom: none;
}

.changelog-version-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 10px;
}

.changelog-version {
  font-family: "Space Mono", monospace;
  font-size: 1rem;
  font-weight: 700;
  color: var(--accent);
}

.changelog-tag {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 2px 10px;
  border-radius: 4px;
}

.changelog-tag-current {
  background: rgba(var(--brand-rgb),0.15);
  color: var(--accent);
  border: 1px solid rgba(var(--brand-rgb),0.35);
}

.changelog-items {
  margin: 0;
  padding-left: 20px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  color: var(--text);
  font-size: 0.92rem;
  line-height: 1.5;
}

.changelog-items li {
  color: var(--muted);
}

.changelog-date {
  font-family: "Space Mono", monospace;
  font-size: 0.78rem;
  color: var(--muted);
}

.changelog-rcs {
  margin-top: 14px;
}

.changelog-rcs summary {
  cursor: pointer;
  font-size: 0.8rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.changelog-rc {
  margin: 12px 0 0 14px;
  padding-left: 12px;
  border-left: 1px solid var(--line);
}

.changelog-rc-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
}

.changelog-rc-version {
  font-family: "Space Mono", monospace;
  font-size: 0.82rem;
  color: var(--text);
}

.changelog-rc-items {
  margin-top: 4px;
  padding-left: 0;
  list-style: none;
  font-size: 0.85rem;
}

.changelog-group {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin-right: 6px;
}

.changelog-group-added { color: var(--accent); }
.changelog-group-fixed { color: var(--warning); }

.changelog-series {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 12px;
}

.changelog-series-link {
  font-family: "Space Mono", monospace;
  font-size: 0.8rem;
  padding: 3px 10px;
  border: 1px solid var(--line);
  border-radius: 4px;
  color: var(--muted);
  text-decoration: none;
  transition: color .15s, border-color .15s;
}

.changelog-series-link:hover {
  color: var(--text);
}

.changelog-series-active {
  border-color: var(--accent);
  color: var(--accent);
}

/* ── Feedback form ── */
.feedback-panel {
}

.feedback-panel .panel-header p {
  margin: 6px 0 0;
  font-size: 0.9rem;
  color: var(--muted);
}

.feedback-type-row {
  margin-bottom: 20px;
}

.field-label {
  display: block;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 10px;
}

.feedback-type-options {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}

.feedback-type-option {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}

.feedback-type-option input[type="radio"] {
  display: none;
}

.feedback-type-badge {
  display: inline-block;
  padding: 6px 18px;
  border-radius: 4px;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  border: 1px solid transparent;
  transition: color .15s, border-color .15s, background-color .15s;
  cursor: pointer;
}

.feedback-type-bug {
  border-color: var(--error);
  color: var(--error);
}

.feedback-type-suggestion {
  border-color: var(--accent-hot);
  color: var(--accent-hot);
}

.feedback-type-option input[type="radio"]:checked + .feedback-type-bug {
  background: rgba(var(--status-error-rgb),0.18);
}

.feedback-type-option input[type="radio"]:checked + .feedback-type-suggestion {
  background: rgba(var(--emphasis-rgb),0.18);
}

.feedback-section {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-bottom: 20px;
}

.file-input {
  background: transparent;
  border: 1px dashed var(--line);
  border-radius: 6px;
  padding: 10px 14px;
  color: var(--muted);
  cursor: pointer;
  width: 100%;
}

.file-input:hover {
  border-color: var(--accent);
}

.feedback-sent {
  margin-bottom: 20px;
}

.muted-text {
  color: var(--muted);
}

/* ── Language switcher ── */
.lang-switcher {
  display: flex;
  align-items: center;
  gap: 4px;
}

.lang-sep {
  color: var(--muted);
  opacity: 0.4;
  font-size: 0.7rem;
}

.lang-btn {
  background: transparent;
  border: 1px solid transparent;
  color: var(--muted);
  font-family: "Space Mono", monospace;
  font-size: 0.82rem;
  font-weight: 700;
  line-height: 1;
  min-height: 0;
  padding: 2px 4px;
  border-radius: 3px;
  cursor: pointer;
  letter-spacing: 0.08em;
  transition: color .15s, border-color .15s;
}

.lang-btn:hover {
  border-color: var(--line);
  color: var(--text);
}

.lang-btn.lang-active {
  border-color: var(--accent);
  color: var(--accent);
}

.theme-switcher {
  display: flex;
  align-items: center;
  gap: 2px;
  padding-left: 6px;
  margin-left: 2px;
  border-left: 1px solid var(--line);
}

.theme-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid transparent;
  color: var(--muted);
  line-height: 1;
  min-height: 0;
  padding: 3px;
  border-radius: 3px;
  cursor: pointer;
  transition: color .15s, border-color .15s;
}

.theme-btn svg {
  width: 14px;
  height: 14px;
  display: block;
}

.theme-btn:hover {
  border-color: var(--line);
  color: var(--text);
}

.theme-btn.theme-active {
  border-color: var(--accent);
  color: var(--accent);
}

/* Third-party brand swatches keep their own hue; on a white surface a pale one
   (Cloudflare yellow) needs a neutral ring to stay visible. */
[data-theme="light"] .dash-pie-dot,
[data-theme="light"] .cdn-bc-pill-dot,
[data-theme="light"] .cdn-vs-dot {
  box-shadow: 0 0 0 1px var(--line);
}

/* ── Admin panel ── */
.admin-panel {
  display: flex;
  flex-direction: row;
  padding: 0;        /* sidebar goes edge-to-edge; content has its own padding */
  overflow: visible;
}
/* cmd-sidebar inside admin-panel must stretch to full panel height */
.admin-panel .cmd-sidebar { align-self: stretch; }

.admin-panel .panel-header p {
  margin: 6px 0 0;
  font-size: 0.9rem;
  color: var(--muted);
}

/* Inline create bar (top row above table) */
.admin-create-bar {
  display: flex;
  align-items: flex-end;
  gap: 12px;
  flex-wrap: wrap;
  padding: 14px 16px;
  margin-bottom: 20px;
  border: 1px solid rgba(var(--brand-rgb),0.14);
  background: rgba(var(--surface-deep-rgb),0.65);
}

.admin-create-bar .field {
  flex: 1 1 140px;
  min-width: 0;
  margin: 0;
}

.admin-create-bar .field-narrow {
  flex: 0 1 120px;
}

.admin-create-bar .field span {
  display: block;
  font-size: 0.68rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 4px;
  font-family: "Space Mono", monospace;
}

.admin-create-bar .field input,
.admin-create-bar .field select {
  width: 100%;
  min-width: 0;
}

.admin-create-bar .bar-action {
  flex: 0 0 auto;
  align-self: flex-end;
}

.admin-create-bar .bar-action button {
  margin-top: 0;
}

.admin-section-title {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 14px;
  font-family: "Space Mono", monospace;
}

.admin-user-note {
  font-size: 0.78rem;
  margin: 0 0 14px;
}

.admin-users-table {
  width: 100%;
  min-width: 860px;
  table-layout: fixed;
}

.admin-users-table td {
  vertical-align: middle;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.admin-users-table th:nth-child(1),
.admin-users-table td:nth-child(1) { width: 9%;  }  /* username */

.admin-users-table th:nth-child(2),
.admin-users-table td:nth-child(2) { width: 13%; }  /* company */

.admin-users-table th:nth-child(3),
.admin-users-table td:nth-child(3) { width: 10%; }  /* password */

.admin-users-table th:nth-child(4),
.admin-users-table td:nth-child(4) { width: 9%;  }  /* level */

.admin-users-table th:nth-child(5),
.admin-users-table td:nth-child(5) { width: 8%;  }  /* language */

.admin-users-table th:nth-child(6),
.admin-users-table td:nth-child(6) { width: 8%;  }  /* created */

.admin-users-table th:nth-child(7),
.admin-users-table td:nth-child(7) { width: 10%; }  /* last login */

.admin-users-table th:nth-child(8),
.admin-users-table td:nth-child(8) { width: 19%; }  /* last hit */

/* Actions (9th): fills remaining ~14% */
.admin-users-table th:nth-child(9),
.admin-users-table td:nth-child(9) { overflow: hidden; }

.admin-users-table input,
.admin-users-table select {
  width: 100%;
  min-width: 0;
}

/* Companies table (simpler, fewer columns) */
.admin-companies-table {
  min-width: 0;
  width: 100%;
  table-layout: auto;
}

.admin-companies-table td {
  vertical-align: middle;
}

.admin-companies-table td:nth-child(1) {
  min-width: 200px;
}

.admin-hit-cell small {
  display: block;
  margin-top: 4px;
  color: var(--muted);
  font-size: 0.68rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.admin-user-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
}

.admin-delete-form {
  display: inline;
}

.admin-save-button,
.admin-delete-button {
  width: auto;
  min-height: 34px;
  margin-top: 0;
  padding: 0 12px;
}

.button-danger {
  background: transparent;
  border: 1px solid var(--error);
  color: var(--error);
  font-family: "Rajdhani", sans-serif;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 4px 12px;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color .15s;
}

.button-danger:hover {
  background: rgba(var(--status-error-rgb),0.15);
}

/* ── Admin sticky header ── */
.admin-content {
  flex: 1;
  min-width: 0;
  padding: 22px;
  overflow-y: auto;
}

/* Admin navigation tabs */
.admin-nav {
  display: flex;
  gap: 4px;
  border-bottom: none;
  padding-bottom: 0;
  margin-bottom: 0;
}

.admin-nav-link {
  display: inline-block;
  padding: 10px 18px;
  font-family: "Rajdhani", sans-serif;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color 0.15s, border-color 0.15s;
}

.admin-nav-link:hover {
  color: var(--text);
}

.admin-nav-active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

/* Sub-nav (device tree: List | Register) */
.admin-subnav {
  display: flex;
  align-items: center;
  gap: 0;
  padding: 2px 0 0 36px;
  border-top: 1px solid rgba(var(--brand-rgb),0.08);
}

.admin-subnav-tree {
  font-family: "Space Mono", monospace;
  font-size: 0.68rem;
  color: var(--muted);
  opacity: 0.45;
  padding-right: 10px;
  user-select: none;
}

.admin-subnav-link {
  display: inline-block;
  padding: 6px 14px;
  font-family: "Space Mono", monospace;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--muted);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color 0.15s, border-color 0.15s;
}

.admin-subnav-link:hover {
  color: var(--text);
}

.admin-subnav-active {
  color: var(--accent-hot);
  border-bottom-color: var(--accent-hot);
}

/* Admin layout wider variant for devices page */
.admin-layout-wide {
  flex-direction: column;
}

.admin-layout-wide .admin-create-section {
  max-width: 600px;
}

/* SSH tester inline row */
.ssh-tester-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 4px;
  margin-bottom: 8px;
}

.ssh-test-result {
  font-size: 0.8rem;
  flex: 1;
  min-width: 0;
  word-break: break-word;
}

.ssh-test-ok {
  color: var(--success, var(--status-ok));
}

.ssh-test-fail {
  color: var(--error);
}

/* Command checkboxes in device form */
.command-checkboxes {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 6px;
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: rgba(var(--tint-rgb),0.02);
}

.command-checkboxes .checkbox-item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.85rem;
  cursor: pointer;
}

.command-checkboxes .checkbox-item input[type="checkbox"] {
  width: 14px;
  height: 14px;
  accent-color: var(--accent);
  cursor: pointer;
}

/* Inline checkbox field */
.field-inline {
  flex-direction: row;
  align-items: center;
  gap: 8px;
}

.field-inline input[type="checkbox"] {
  width: 16px;
  height: 16px;
  accent-color: var(--accent);
  cursor: pointer;
  flex-shrink: 0;
}

/* Disabled device row */
.row-disabled td {
  opacity: 0.45;
}

/* Admin toggle button */
.admin-toggle-button {
  width: auto;
  min-height: 28px;
  padding: 0 10px;
  font-size: 0.72rem;
}

/* ── Panel header with action button ── */

.panel-header-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 16px;
}

.panel-header-actions .panel-header {
  margin-bottom: 0;
  flex: 1 1 auto;
  min-width: 0;
}

/* ── Device list ── */

.device-list-toolbar {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 14px;
  margin-bottom: 0;
  border: 1px solid rgba(var(--brand-rgb),0.12);
  border-bottom: none;
  background: rgba(var(--brand-rgb),0.03);
}

.device-filter-bar {
  display: flex;
  align-items: center;
  gap: 10px;
}

.device-filter-bar select {
  min-width: 200px;
}

.device-count-label {
  margin-left: auto;
  font-size: 0.78rem;
}

/* Status dot */
.status-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
}

.status-dot-on  { background: var(--status-ok); }
.status-dot-off { background: var(--status-error); opacity: 0.45; }
.status-dot-warn { background: var(--status-warn); }

/* Device list table — override global min-width */
.device-list-table {
  min-width: 860px;
  table-layout: fixed;
}

.device-list-table td,
.device-list-table th {
  vertical-align: middle;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.device-list-table .col-actions {
  overflow: visible;
  white-space: normal;
}

.device-list-table .col-status   { width: 30px;  text-align: center; }
.device-list-table .col-company  { width: 15%; }
.device-list-table .col-display  { width: 18%; }
.device-list-table .col-name     { width: 14%; }
.device-list-table .col-ip       { width: 15%; }
.device-list-table .col-template { width: 10%; }
.device-list-table .col-cmds     { width: 8%;   text-align: center; }
.device-list-table .col-actions  { width: auto; }

.device-port {
  opacity: 0.5;
  font-size: 0.8em;
}

.device-list-actions {
  display: flex;
  gap: 6px;
  align-items: center;
  white-space: nowrap;
}

/* Shared base for all device row action buttons */
.device-action-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 26px;
  padding: 0 10px;
  font-family: "Space Mono", monospace;
  font-size: 0.66rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  border: 1px solid;
  background: transparent;
  cursor: pointer;
  white-space: nowrap;
  margin-top: 0;
  color: inherit;
}

.device-action-edit {
  border-color: var(--text-faint);
  color: var(--accent);
}

.device-action-edit:hover {
  background: rgba(var(--brand-rgb),0.08);
}

.device-action-enabled {
  border-color: rgba(var(--cmd-write-rgb),0.45);
  color: var(--accent-hot);
}

.device-action-enabled:hover {
  background: rgba(var(--cmd-write-rgb),0.08);
}

.device-action-disabled {
  border-color: rgba(var(--text-muted-rgb),0.3);
  color: var(--muted);
}

.device-action-disabled:hover {
  background: rgba(var(--text-muted-rgb),0.06);
}

.device-action-delete {
  border-color: rgba(var(--status-error-rgb),0.45);
  color: var(--error);
}

.device-action-delete:hover {
  background: rgba(var(--status-error-rgb),0.08);
}

/* Disabled row */
.row-disabled td { opacity: 0.45; }

/* Form page header — h2 inline with cancel button */
.panel-form-title {
  font-size: 1.45rem;
  text-transform: uppercase;
  margin: 0;
  white-space: nowrap;
  flex-shrink: 0;
}

.panel-form-sub {
  margin: 4px 0 18px;
  font-size: 0.9rem;
}

/* ── Device form ── */

.device-form-wrap {
  width: 100%;
}

/* 2-column grid: identity+naming side by side, rest full-width */
.device-form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-top: 10px;
}

/* Sections that should span both columns */
.device-form-section-full {
  grid-column: 1 / -1;
}

.device-form-section {
  padding: 14px 16px;
  border: 1px solid rgba(var(--brand-rgb),0.14);
  background: rgba(var(--surface-deep-rgb),0.65);
}

.device-form-section-label {
  margin: 0 0 12px;
  font-family: "Space Mono", monospace;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}

/* IP + Port 3:1 */
.field-grid-ip {
  display: grid;
  grid-template-columns: 3fr 1fr;
  gap: 12px;
  margin-bottom: 10px;
}

/* SSH connection: IP(3fr) Port(1fr) User(2fr) Pass(2fr) Timeout(1fr) */
.device-form-conn-grid {
  display: grid;
  grid-template-columns: 3fr 1fr 2fr 2fr 1fr;
  gap: 12px;
  margin-bottom: 10px;
}

/* Command checkboxes */
/* Command Read/Write 2-column grid */
.cmd-rw-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  border: 1px solid rgba(var(--brand-rgb),0.12);
}

.cmd-rw-col {
  padding: 14px;
}

.cmd-rw-col:first-child {
  border-right: 1px solid rgba(var(--brand-rgb),0.12);
}

.cmd-col-label {
  font-family: "Space Mono", monospace;
  font-size: 0.68rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  margin: 0 0 10px;
  padding-bottom: 6px;
  border-bottom: 1px solid rgba(var(--brand-rgb),0.1);
}

.cmd-col-label-read  { color: var(--read-accent); }
.cmd-col-label-write { color: var(--write-accent); }

.cmd-col-items {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.cmd-item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.85rem;
  cursor: pointer;
  line-height: 1.3;
}

.cmd-item input[type="checkbox"] {
  width: 14px;
  height: 14px;
  accent-color: var(--accent);
  cursor: pointer;
  flex-shrink: 0;
}

.cmd-type {
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 1px 4px;
  background: rgba(var(--tint-rgb),0.07);
  color: var(--muted);
}

.cmd-type-write { background: rgba(var(--status-warn-rgb),0.15); color: var(--status-warn); }
.cmd-type-read  { background: rgba(var(--status-ok-rgb),0.12);  color: var(--status-ok); }

/* Form footer */
.device-form-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
}

.action-row {
  display: flex;
  gap: 10px;
  align-items: center;
}

/* Primary submit button — green */
.device-form .action-row button[type="submit"] {
  border-color: rgba(var(--cmd-write-rgb),0.6);
  color: var(--accent-hot);
}

.device-form .action-row button[type="submit"]:hover {
  border-color: var(--accent-hot);
  background: rgba(var(--cmd-write-rgb),0.08);
}

/* Remove number input spinners */
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

input[type="number"] {
  -moz-appearance: textfield;
  appearance: textfield;
}

/* Inline checkbox */
.field-inline {
  flex-direction: row;
  align-items: center;
  gap: 8px;
}

.field-inline input[type="checkbox"] {
  width: 16px;
  height: 16px;
  accent-color: var(--accent);
  cursor: pointer;
  flex-shrink: 0;
}

/* SSH tester */
.field-grid-ssh-footer {
  display: flex;
  align-items: flex-end;
  gap: 16px;
  margin-top: 8px;
}

.ssh-tester-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 1 1 auto;
}

.field-ssh-timeout {
  flex: 0 0 160px;
}

.field-ssh-timeout input {
  width: 100%;
}

.ssh-test-result  { font-size: 0.8rem; flex: 1; min-width: 0; word-break: break-word; }
.ssh-test-ok      { color: var(--status-ok); }
.ssh-test-fail    { color: var(--error); }

/* ── Workspace layout (sidebar + split pane) ── */
.workspace {
  display: flex;
  flex-direction: row;
  margin-top: 18px;
  min-height: 640px;
  border: 1px solid var(--line);
  background: linear-gradient(180deg, rgba(var(--surface-deep-rgb),0.92), rgba(var(--surface-deep-rgb),0.92));
  box-shadow: 0 0 0 1px rgba(var(--brand-rgb),0.08), 0 18px 50px var(--shadow-mid);
  overflow: hidden;
}

.cmd-sidebar {
  width: 210px;
  flex-shrink: 0;
  border-right: 1px solid var(--line);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  background: rgba(var(--surface-deep-rgb),0.55);
}

.csb-section { padding: 10px 0 6px; }

/* Device section — heading mirrors the Alerts item exactly (same font/weight/size, no tint) */
.csb-section-device .csb-heading {
  font-family: 'Space Mono', monospace;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--text);
  opacity: 0.7;
  padding: 6px 10px 6px 16px;
}
.csb-section-device .csb-heading:hover { opacity: 1; }
/* Caret dimmed + same glyph font (Rajdhani) as the other sections — the heading
   text is Space Mono to match Alerts, but Space Mono's ▾ renders as a tiny dot. */
.csb-section-device .csb-caret { color: var(--muted); font-family: Rajdhani, sans-serif; }

/* Stats section (Alerts) — plain, no tint */
.csb-section-stats .csb-item.dash-active { opacity: 1; }

/* Flow section — amber/warm tint (same as Alerts) */
.csb-section-flow { background: rgba(var(--status-warn-rgb),0.05); border-left: 2px solid rgba(var(--status-warn-rgb),0.3); }
.csb-section-flow .csb-heading { color: rgba(var(--status-warn-rgb),0.85); }
.csb-section-flow .csb-item:hover { background: rgba(var(--status-warn-rgb),0.10); border-left-color: var(--status-warn); color: var(--status-warn); }
.csb-section-flow .csb-item.dash-active { background: rgba(var(--status-warn-rgb),0.16); border-left-color: var(--status-warn); color: var(--status-warn); opacity: 1; }

/* On paper the amber tint turns muddy tan at the dark-theme alphas — same hue,
   lower alpha, so the section still reads as "flow" without looking stained. */
[data-theme="light"] .csb-section-flow { background: rgba(var(--status-warn-rgb),0.035); }
[data-theme="light"] .csb-section-flow .csb-item:hover { background: rgba(var(--status-warn-rgb),0.07); }
[data-theme="light"] .csb-section-flow .csb-item.dash-active { background: rgba(var(--status-warn-rgb),0.09); }

/* Security section (Scans, Mitigation) - red tint: ISP defense, not a flow view */
.csb-section-security { background: rgba(var(--status-error-rgb),0.05); border-left: 2px solid rgba(var(--status-error-rgb),0.3); }
.csb-section-security .csb-heading { color: rgba(var(--status-error-rgb),0.85); }
.csb-section-security .csb-item:hover { background: rgba(var(--status-error-rgb),0.10); border-left-color: var(--status-error); color: var(--status-error); }
.csb-section-security .csb-item.dash-active { background: rgba(var(--status-error-rgb),0.16); border-left-color: var(--status-error); color: var(--status-error); opacity: 1; }
[data-theme="light"] .csb-section-security { background: rgba(var(--status-error-rgb),0.035); }
[data-theme="light"] .csb-section-security .csb-item:hover { background: rgba(var(--status-error-rgb),0.07); }
[data-theme="light"] .csb-section-security .csb-item.dash-active { background: rgba(var(--status-error-rgb),0.09); }
[data-theme="light"] .csb-section-flow .csb-heading { color: var(--status-warn); }
[data-theme="light"] .csb-section-security .csb-heading { color: var(--status-error); }
[data-theme="light"] .csb-section-analytics .csb-heading { color: var(--ip-v6); }
[data-theme="light"] .csb-section-read .csb-heading { color: var(--status-info); }
[data-theme="light"] .csb-section-write .csb-heading { color: var(--status-ok); }

/* Fixed (non-collapsible) sidebar entry — e.g. Alerts */
.csb-section-fixed { padding: 6px 0; }
.csb-item-fixed { font-weight: 700; letter-spacing: .04em; opacity: 0.9; }

/* Analytics section — purple tint */
.csb-section-analytics { background: rgba(var(--ip-v6-rgb),0.05); border-left: 2px solid rgba(var(--ip-v6-rgb),0.28); }
.csb-section-analytics .csb-heading { color: rgba(var(--ip-v6-rgb),0.85); }
.csb-section-analytics .csb-item:hover { background: rgba(var(--ip-v6-rgb),0.10); border-left-color: var(--ip-v6); color: var(--ip-v6); }
.csb-section-analytics .csb-item.dash-active { background: rgba(var(--ip-v6-rgb),0.16); border-left-color: var(--ip-v6); color: var(--ip-v6); opacity: 1; }

/* Read section — blue tint */
.csb-section-read { background: rgba(var(--status-info-rgb),0.06); border-left: 2px solid rgba(var(--status-info-rgb),0.35); }
.csb-section-read .csb-heading { color: rgba(var(--status-info-rgb),0.85); }
.csb-section-read .csb-item:hover { background: rgba(var(--status-info-rgb),0.12); border-left-color: var(--status-info); color: var(--status-info); }
.csb-section-read .csb-item.active { background: rgba(var(--status-info-rgb),0.18); border-left-color: var(--status-info); color: var(--status-info); }

/* Write section — green tint */
.csb-section-write { background: rgba(var(--status-ok-rgb),0.06); border-left: 2px solid rgba(var(--status-ok-rgb),0.35); }
.csb-section-write .csb-heading { color: rgba(var(--status-ok-rgb),0.85); }
.csb-section-write .csb-item:hover { background: rgba(var(--status-ok-rgb),0.12); border-left-color: var(--status-ok); color: var(--status-ok); }
.csb-section-write .csb-item.active { background: rgba(var(--status-ok-rgb),0.18); border-left-color: var(--status-ok); color: var(--status-ok); }

/* Admin section — teal accent (matches the system/privileged role) */
.csb-section-admin { background: rgba(var(--brand-rgb),0.04); border-left: 2px solid rgba(var(--brand-rgb),0.28); }
.csb-section-admin .csb-heading { color: var(--text-muted); }
.csb-section-admin .csb-item:hover { background: rgba(var(--brand-rgb),0.08); border-left-color: var(--accent); color: var(--accent); opacity: 1; }
.csb-section-admin .csb-item.active { background: rgba(var(--brand-rgb),0.12); border-left-color: var(--accent); color: var(--accent); opacity: 1; }
/* The admin sidebar has no sub-items: per-device pages are tabs on the page
   itself (.dev-tabs), so the nav never changes shape between pages. */

/* Generic stat-item hover (fallback for items not inside a coloured section) */
.csb-item-stat:hover,
.csb-item-stat.dash-active {
  border-left-color: var(--accent);
  color: var(--accent);
  opacity: 1;
  background: rgba(var(--brand-rgb),0.08);
}

/* ── Per-device admin context header ──
   Names the device you are inside and switches to a sibling without a trip
   back to the list. The static admin sidebar deliberately does not name it. */
.dev-ctx {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 0 0 .7rem;
}
.dev-ctx-back {
  font-family: 'Rajdhani', sans-serif; font-size: .78rem; font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); text-decoration: none;
}
.dev-ctx-back:hover { color: var(--accent); }
.dev-ctx-select {
  background: var(--surface-raised); border: 1px solid rgba(var(--brand-rgb),.2);
  border-radius: 4px; color: var(--text);
  font-family: 'Rajdhani', sans-serif; font-size: 1rem; font-weight: 700;
  padding: 3px 10px; outline: none; cursor: pointer; max-width: 24rem;
}
.dev-ctx-select:focus { border-color: var(--text-muted); }
.dev-ctx-meta {
  font-family: 'Space Mono', monospace; font-size: .72rem; color: var(--muted);
}

/* ── Per-device admin tabs (Settings / NetFlow export / Blackhole) ── */
.dev-tabs {
  display: flex; gap: 4px; margin: 0 0 1.2rem;
  border-bottom: 1px solid var(--line); padding-bottom: 8px;
}
.dev-tab {
  font-family: 'Rajdhani', sans-serif; font-size: .8rem; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase;
  padding: 5px 16px; border-radius: 3px 3px 0 0;
  border: 1px solid transparent; border-bottom: none;
  color: var(--muted); text-decoration: none;
  transition: color .15s, border-color .15s, background .15s;
}
.dev-tab:hover { color: var(--text); background: rgba(var(--brand-rgb),0.05); }
.dev-tab.active {
  color: var(--accent); border-color: var(--line);
  background: rgba(var(--brand-rgb),0.08);
}

/* ── Dashboard tabs ── */
.dash-tabs {
  display: flex; gap: 4px; margin-bottom: 1.2rem;
  border-bottom: 1px solid var(--line); padding-bottom: 8px;
}
.dash-tab {
  font-family: inherit; font-size: .78rem; font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase;
  padding: 4px 14px; border-radius: 3px 3px 0 0;
  border: 1px solid transparent; border-bottom: none;
  background: none; color: var(--muted); cursor: pointer;
  transition: color .15s, border-color .15s, background .15s;
}
.dash-tab:hover { color: var(--text); }
.dash-tab.active {
  color: var(--accent); border-color: var(--line);
  background: var(--bg-alt); border-bottom: 1px solid var(--bg-alt);
  margin-bottom: -9px;
}

/* ── Pie chart (SVG donut) ── */
.dash-pie-wrap { display: flex; align-items: center; gap: 1.4rem; flex-wrap: wrap; }
.dash-pie-legend { display: flex; flex-direction: column; gap: .5rem; font-size: .80rem; }
.dash-pie-legend-row { display: flex; align-items: center; gap: .55rem; }
.dash-pie-dot { width: 11px; height: 11px; border-radius: 50%; flex-shrink: 0; }
/* A legend row is one line. The name takes the room the card actually
   has and cuts with an ellipsis only when it runs out, so a wide card
   prints the whole AS name instead of a fixed character budget. */
.dash-pie-legend-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.csb-heading {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 2px 12px 6px;
  font-family: inherit;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--muted);
  background: none;
  border: none;
  cursor: default;
  text-align: left;
}
.csb-collapsible { cursor: pointer; }
.csb-caret { font-size: 9px; transition: transform 0.15s; }
.csb-collapsible[aria-expanded="false"] .csb-caret { transform: rotate(-90deg); }

.csb-sep { height: 1px; background: var(--line); margin: 0 12px; }

.csb-list { display: flex; flex-direction: column; gap: 1px; padding: 2px 0; }
.csb-list.hidden { display: none; }

/* A block with no commands available to the user is hidden with its divider. */
.csb-section.hidden, .csb-sep.hidden { display: none; }

/* Commands of a newly picked device slide in one after the other; the block
   height itself is animated from JS (animateSidebarBlock). */
@keyframes csb-item-in { from { opacity: 0; transform: translateX(-6px); } }
.csb-item-in { animation: csb-item-in var(--motion-dur) var(--motion-ease) backwards; animation-delay: calc(var(--i, 0) * 20ms); }
@media (prefers-reduced-motion: reduce) { .csb-item-in { animation: none; } }

.csb-item {
  display: block;
  width: 100%;
  text-align: left;
  padding: 6px 10px 6px 16px;
  font-family: 'Space Mono', monospace;
  font-size: 11.5px;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--text);
  background: none;
  border: none;
  border-left: 2px solid transparent;
  cursor: pointer;
  opacity: 0.7;
  transition: opacity 0.12s, border-color 0.12s, background 0.12s;
  line-height: 1.35;
  white-space: normal;
  word-break: break-word;
}
.csb-item:hover { opacity: 1; background: rgba(var(--brand-rgb),0.05); }

.csb-item-read:hover,
.csb-item-read.active {
  border-left-color: var(--read-accent);
  color: var(--read-accent);
  opacity: 1;
  background: var(--read-accent-soft);
}
.csb-item-write:hover,
.csb-item-write.active {
  border-left-color: var(--write-accent);
  color: var(--write-accent);
  opacity: 1;
  background: var(--write-accent-soft);
}

.csb-empty-hint {
  display: block;
  padding: 3px 16px;
  font-size: 11px;
  color: var(--muted);
  opacity: 0.4;
}

.csb-history-section {
  flex: 1;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.csb-history-list { flex: 1; overflow-y: auto; }
.csb-history-list .csb-item {
  font-size: 10.5px;
  opacity: 0.55;
  border-left: none;
  padding-left: 14px;
}
.csb-history-list .csb-item:hover { opacity: 0.9; border-left: none; background: rgba(var(--brand-rgb),0.04); }

/* ── Split pane ── */
.workspace-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow: hidden;
}
.workspace-pane { overflow-y: auto; padding: 18px 22px; }
.workspace-pane-input { flex: 0 0 auto; border-bottom: 1px solid var(--line); }
.workspace-pane-output { flex: 1; min-width: 0; }

/* Input pane form: flex-wrap so meta-card + controls sit on same row */
#command-form {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: flex-start;
}
#action-row {
  order: 6;
}

@media (max-width: 900px) {
  /* The sidebar becomes a full-width strip, so the workspace has to stack. A
     100%-wide child inside a row flexbox takes the whole line and collapses
     .workspace-main to zero width — the pane is then off-screen, not narrow. */
  .workspace { flex-direction: column; }
  .cmd-sidebar { width: 100%; border-right: none; border-bottom: 1px solid var(--line); flex-direction: row; flex-wrap: wrap; overflow-x: auto; overflow-y: hidden; max-height: 180px; }
  .workspace-main { flex-direction: column; width: 100%; min-width: 0; }
  .workspace-pane-input { flex: none; border-right: none; border-bottom: 1px solid var(--line); }
  /* Same trap on every /admin page: .admin-panel is a row flexbox holding the
     same .cmd-sidebar, so the 100%-wide strip above pushed .admin-content off
     the right edge instead of stacking under it. */
  .admin-panel { flex-direction: column; }
  .admin-content { width: 100%; min-width: 0; }
}

/* ── Inline dashboard pane ── */
.workspace-pane-dashboard { flex: 1; overflow-y: auto; padding: 22px; }

.dash-toolbar {
  display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; margin-bottom: 1.2rem;
}
.dash-toolbar select {
  font-family: inherit; font-size: .8rem; font-weight: 600;
  letter-spacing: .05em; padding: 5px 14px; border-radius: 3px;
  border: 1px solid var(--line); background: var(--bg-alt);
  color: var(--text); cursor: pointer; transition: border-color .15s, color .15s;
}
.dash-toolbar select:hover { border-color: var(--accent); color: var(--accent); }
.period-btn {
  font-family: inherit; font-size: .8rem; font-weight: 600;
  letter-spacing: .05em; padding: 5px 12px; border-radius: 3px;
  border: 1px solid var(--line); background: var(--bg-alt);
  color: var(--text); cursor: pointer; transition: border-color .15s, color .15s;
}
.period-btn:hover { border-color: var(--accent); color: var(--accent); }
.period-btn.active { border-color: var(--accent); color: var(--accent); background: rgba(var(--brand-rgb),.08); }
.dash-apply-btn { font-family: inherit; font-size: .75rem; padding: 4px 12px; border-radius: 3px; border: 1px solid var(--accent); color: var(--accent); background: rgba(var(--brand-rgb),.08); cursor: pointer; }
.dash-apply-btn:hover { background: rgba(var(--brand-rgb),.18); }
.dash-export-btn { margin-left: auto; }

/* ── Inline horizontal time range (Zabbix-style) ── */
.tp-device-sel {
  font-family: inherit; font-size: .8rem; font-weight: 600;
  letter-spacing: .05em; padding: 5px 14px; border-radius: 3px;
  border: 1px solid var(--line); background: var(--bg-alt);
  color: var(--text); cursor: pointer; transition: border-color .15s, color .15s;
  flex-shrink: 0;
}
.tp-device-sel:hover { border-color: var(--accent); color: var(--accent); }

/* Locked exporter of a customer drill - replaces the device selector */
.fq-pin-chip {
  display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0;
  font-family: 'Space Mono', monospace; font-size: .72rem;
  padding: 4px 8px 4px 10px; border-radius: 3px;
  border: 1px solid rgba(var(--brand-rgb),.35);
  background: rgba(var(--brand-rgb),.08); color: var(--text);
}
.fq-pin-chip-label {
  text-transform: uppercase; letter-spacing: .08em;
  font-size: .66rem; color: var(--text-muted);
}
.fq-pin-chip-x {
  font-family: inherit; font-size: .72rem; line-height: 1;
  border: 0; background: none; color: var(--text-muted);
  cursor: pointer; padding: 2px 3px;
}
.fq-pin-chip-x:hover { color: var(--accent); }

.tp-inline { display: flex; flex-direction: column; flex: 1; min-width: 0; gap: 6px; }

.tp-chip-row {
  display: flex; align-items: center; gap: 3px; flex-wrap: wrap;
}
/* 20 chips wrapped to six rows on a phone and pushed every tab below the
   fold. One row that scrolls sideways instead. */
@media (max-width: 600px) {
  .tp-chip-row {
    flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
    /* Faded edges say there is more on either side */
    mask-image: linear-gradient(to right, transparent, #000 16px, #000 calc(100% - 24px), transparent);
  }
}

.tp-chip {
  font-family: 'Space Mono', monospace; font-size: 10.5px; font-weight: 400;
  letter-spacing: .04em; padding: 4px 9px; border-radius: 3px;
  border: 1px solid transparent;
  background: transparent; color: var(--muted);
  cursor: pointer; white-space: nowrap;
  transition: background .1s, color .1s, border-color .1s;
}
.tp-chip:hover { color: var(--text); background: rgba(var(--brand-rgb),.06); border-color: var(--text-faint); }
.tp-chip.active {
  color: var(--accent); background: rgba(var(--brand-rgb),.1);
  border-color: var(--text-faint); font-weight: 700;
}
.tp-chip-sep { width: 1px; height: 14px; background: var(--line); margin: 0 4px; flex-shrink: 0; }
/* Calendar chips — slightly different font to visually distinguish from numeric presets */
.tp-cal-chip { font-family: inherit; font-size: 10.5px; }
.tp-chip-custom { font-family: inherit; font-size: 10.5px; }
.tp-chip-custom.active { color: var(--accent); }

.tp-custom-inline {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 6px 10px;
  background: rgba(var(--brand-rgb),.03); border: 1px solid rgba(var(--brand-rgb),.12);
  border-radius: 4px;
}
.tp-il-label {
  font-size: .66rem; text-transform: uppercase; letter-spacing: .1em;
  color: var(--muted); white-space: nowrap;
}
.tp-il-input {
  font-family: 'Space Mono', monospace; font-size: 11px;
  background: var(--bg); border: 1px solid rgba(var(--brand-rgb),.2);
  border-radius: 3px; color: var(--text); padding: 4px 8px;
  outline: none; transition: border-color .13s;
  color-scheme: dark;
}
.tp-il-input:focus { border-color: var(--text-muted); }
.tp-il-input::-webkit-calendar-picker-indicator {
  filter: invert(1) brightness(1.4) sepia(1) hue-rotate(120deg) saturate(3);
  opacity: .8; cursor: pointer;
}
.tp-il-input::-webkit-calendar-picker-indicator:hover { opacity: 1; }
.tp-il-apply {
  font-family: inherit; font-size: 11px; font-weight: 600; letter-spacing: .05em;
  padding: 5px 14px; border-radius: 3px;
  border: 1px solid var(--accent); background: rgba(var(--brand-rgb),.1);
  color: var(--accent); cursor: pointer; transition: background .13s;
  white-space: nowrap;
}
.tp-il-apply:hover { background: rgba(var(--brand-rgb),.2); }
.tp-il-cancel {
  background: none; border: none; color: var(--muted); cursor: pointer; font-size: 13px; padding: 2px 4px;
}
.tp-il-cancel:hover { color: var(--text); }

/* Keep old styles for any remaining references (backward compat) */
.time-picker-wrap { position: relative; }
.time-picker-btn { display: none; }   /* hidden — replaced by inline chips */
.time-picker-panel { display: none !important; }

.tp-section-label {
  font-size: .66rem; text-transform: uppercase; letter-spacing: .11em;
  color: var(--muted); padding: 2px 8px 7px; pointer-events: none;
}
.tp-preset {
  font-family: inherit; font-size: .78rem; font-weight: 500; letter-spacing: .02em;
  padding: 5px 10px; border-radius: 3px; border: none;
  background: transparent; color: var(--muted);
  cursor: pointer; text-align: left; transition: background .1s, color .1s; white-space: nowrap;
}
.tp-preset:hover { background: rgba(var(--brand-rgb),.07); color: var(--text); }
.tp-preset.active { color: var(--accent); background: rgba(var(--brand-rgb),.1); font-weight: 600; }
.tp-sep { width: 0; }

.tp-custom {
  display: flex; flex-direction: column; gap: .65rem;
  padding: 10px 14px 14px; min-width: 210px;
}

.tp-field { display: flex; flex-direction: column; gap: .22rem; }

.tp-field-label {
  font-size: .66rem; text-transform: uppercase; letter-spacing: .1em; color: var(--muted);
}

.tp-datetime {
  background: var(--bg); border: 1px solid var(--line); color: var(--text);
  padding: 5px 8px; border-radius: 3px;
  font-family: 'Space Mono', monospace; font-size: .72rem;
  width: 100%; color-scheme: dark;
  transition: border-color .15s;
}
.tp-datetime:focus { outline: none; border-color: var(--accent); }

.tp-apply-btn {
  font-family: inherit; font-size: .78rem; font-weight: 600; letter-spacing: .04em;
  padding: 6px 16px; border-radius: 3px;
  border: 1px solid var(--accent); background: rgba(var(--brand-rgb),.1); color: var(--accent);
  cursor: pointer; margin-top: .2rem; align-self: flex-start;
  transition: background .15s;
}
.tp-apply-btn:hover { background: rgba(var(--brand-rgb),.22); }

.dash-totals { display: flex; gap: 2rem; flex-wrap: wrap; margin-bottom: 1.4rem; }
.dash-total-label { font-size: .68rem; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); display: block; }
.dash-total-val { font-family: 'Space Mono', monospace; font-size: 1.4rem; color: var(--accent); }
/* "vs previous period" line - JS sets the colour per direction. */
.dash-total-delta { display: block; font-size: .75rem; margin-top: .15rem; }

.dash-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.2rem; }
@media (max-width: 900px) { .dash-grid { grid-template-columns: 1fr; } }
.dash-card { background: var(--bg-alt); border: 1px solid var(--line); border-radius: 6px; padding: 1.2rem 1.4rem; }
.dash-card.dash-card-wide { grid-column: 1 / -1; }
/* The last card of an odd run, set by _mitBalance: no blank half row. */
.dash-card.dash-card-fill { grid-column: 1 / -1; }
/* Two short cards stacked in one grid cell, the last one filling the row's height. */
.dash-col { display: flex; flex-direction: column; gap: 1.2rem; min-width: 0; }
.dash-col > .dash-card:last-child { flex: 1; }
.dash-card h3 { font-size: .80rem; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); margin: 0 0 1rem; }

#dash-chart { width: 100%; height: 140px; display: block; overflow: visible; }
.chart-empty { font-size: .78rem; color: var(--muted); text-align: center; padding: 2rem 0; }

.bar-row { display: flex; align-items: center; gap: .5rem; margin-bottom: .45rem; font-size: .74rem; }
.bar-row-click { border-radius: 3px; transition: background .12s; padding: 2px 4px; margin-left: -4px; margin-right: -4px; }
.bar-row-click:hover { background: rgba(var(--tint-rgb),.06); }
.bar-row-click:hover .bar-label { color: var(--read-accent); }

/* Conversations tab: sub-filters, direction balance, sortable log */
.conv-filters { display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; margin-bottom: .9rem; }
.conv-filters .tm-subseg { margin: 0; }
.conv-hint { font-size: .68rem; color: var(--muted); line-height: 1.4; margin-bottom: .6rem; }
/* A full pair label is two "ASxxxxx · Org" strings — give it most of the row
   and keep the bar wide enough to read the split. */
.conv-bal-row { display: grid; grid-template-columns: minmax(200px, 1fr) 2fr 84px; align-items: center;
  gap: .6rem; font-size: .72rem; padding: 3px 4px; margin: 0 -4px; border-radius: 4px;
  cursor: pointer; transition: background .12s; }
.conv-bal-row:hover { background: rgba(var(--tint-rgb),.06); }
.conv-bal-row:hover .conv-bal-label { color: var(--read-accent); }
.conv-bal-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.conv-bal-track { display: flex; height: 10px; border-radius: 3px; overflow: hidden;
  background: rgba(var(--tint-rgb),.06); }
.conv-bal-seg { height: 100%; }
.conv-bal-val { text-align: right; color: var(--muted); font-variant-numeric: tabular-nums; }
.conv-th-sort { cursor: pointer; user-select: none; }
.conv-th-sort:hover { color: var(--read-accent); }

/* Spoofed flow IP samples table */
.spoof-cidr-hint { font-size: .78rem; color: var(--muted); margin-bottom: .6rem; line-height: 1.4; }
.spoof-cidr-hint a { color: var(--link); }
.spoof-samp-wrap { display: flex; flex-direction: column; gap: .05rem; }
.spoof-samp-row { display: grid; grid-template-columns: 150px 150px 1fr 1fr 90px; align-items: center;
  gap: .6rem; font-size: .8rem; padding: 3px 5px; border-radius: 4px; }
.spoof-samp-head { color: var(--muted); font-size: .7rem; text-transform: uppercase; letter-spacing: .04em;
  border-bottom: 1px solid rgba(var(--tint-rgb),.08); padding-bottom: 5px; margin-bottom: 2px; }
.spoof-samp-click { transition: background .12s; }
.spoof-samp-click:hover { background: rgba(var(--tint-rgb),.06); }
/* Scans tab: a source row that narrows the whole tab to itself */
/* !important: the cell is also exp-td-left, which forces the text color and font */
.exp-table tbody td.scan-src-click { font-family: 'Space Mono', monospace !important; font-size: .78rem !important;
  white-space: normal; overflow: visible; text-overflow: clip; max-width: 260px; }
.exp-table tbody td.scan-src-click:hover { color: var(--link) !important; }
.exp-table tbody td.scan-src-selected { color: var(--link) !important; font-weight: 600; }
/* Scans tab: who the source is, under the address */
/* Cells under a left header read left. The AS name and the port list are
   the widest cells by far and pushed Ports and Probes off the panel at
   1440 px: clip both, the full text is the title. */
.exp-table tbody td.scan-l { text-align: left; }
.exp-table tbody td.scan-net { max-width: 180px; overflow: hidden; text-overflow: ellipsis; }
.exp-table tbody td.scan-ports { max-width: 120px; overflow: hidden; text-overflow: ellipsis; }
/* Eleven columns: a two-word header may wrap so the column is as wide as
   its values, not its label. */
.scan-table thead th { white-space: normal; vertical-align: bottom; }
#scan-sources { overflow-x: auto; }
.exp-table tbody td .scan-ptr { font-family: 'Space Mono', monospace; font-size: .68rem; color: var(--muted); font-weight: 400; }
.scan-tag { display: inline-block; white-space: nowrap; font-size: .68rem; color: var(--muted); border: 1px solid var(--border); border-radius: 3px; padding: 0 .3em; margin-left: .3em; font-weight: 400; }
.scan-tag-isps { color: var(--status-warn); border-color: var(--status-warn); }
.scan-active { display: inline-block; width: .5em; height: .5em; border-radius: 50%; background: var(--status-error); margin-right: .4em; vertical-align: middle; }
.spoof-samp-ip { font-family: 'Space Mono', monospace; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.spoof-samp-forged { color: var(--status-error); }
.spoof-samp-click:hover .spoof-samp-forged { color: var(--read-accent); }
.spoof-samp-owner { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.spoof-samp-iface { color: var(--read-accent); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.spoof-samp-dim { color: var(--muted); opacity: .5; }
.spoof-samp-unres { color: var(--status-warn); }
.spoof-samp-click:hover .spoof-samp-unres { color: var(--read-accent); }
.spoof-samp-tag { font-size: 12px; padding: 1px 6px; border-radius: 3px; white-space: nowrap; }
.spoof-samp-tag-unres { color: var(--status-warn); border: 1px solid var(--status-warn); opacity: .8; }
[data-theme="light"] .spoof-samp-tag-unres { opacity: 1; }
.spoof-samp-row .r { text-align: right; }
.bar-label { width: 200px; flex-shrink: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); font-size: .8rem; }
.bar-track { flex: 1; background: rgba(var(--tint-rgb),.05); border-radius: 2px; height: 6px; overflow: hidden; }
.bar-fill { height: 100%; border-radius: 2px; transition: width .4s; }
.bar-val { width: 72px; flex-shrink: 0; text-align: right; color: var(--muted); font-size: .78rem; font-family: 'Space Mono', monospace; }
/* Average rate under the byte total, on bar lists that carry both. Scoped by
   :has() so every other bar list keeps its 72px value column. */
.bar-val:has(.bar-val-rate) { width: 88px; line-height: 1.25; }
.bar-val-rate { display: block; font-size: .72rem; opacity: .6; }
.proto-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 4px; vertical-align: middle; }
.dash-no-data { font-size: .82rem; color: var(--muted); }
/* A tab that never drew and whose read failed shows only the banner. */
.dash-tab-failed > :not(.dash-load-failed) { display: none !important; }
.dash-tab-body > .dash-load-failed { margin: 0 0 12px; }
.chart-legend { display: flex; gap: 1.2rem; margin-top: .5rem; }
.chart-legend-item { display: flex; align-items: center; gap: .35rem; font-size: .78rem; color: var(--muted); }
.chart-legend-swatch { width: 16px; height: 3px; border-radius: 2px; flex-shrink: 0; }
/* Legends drawn by drawLineChart are clickable: click isolates one series,
   clicking the isolated one restores the rest, ctrl/cmd-click toggles one.
   `is-hot` is the entry under the cursor, on the legend or on the line. */
.chart-legend[data-legend="auto"] .chart-legend-item { cursor: pointer; user-select: none; }
.chart-legend-item.is-off { opacity: .4; text-decoration: line-through; }
.chart-legend-item.is-hot { color: var(--text); font-weight: 700; }
.top-table { width: 100%; border-collapse: collapse; font-size: .8rem; }
.top-table thead th { color: var(--muted); text-transform: uppercase; letter-spacing: .06em; font-size: .7rem; padding: .3rem .4rem; border-bottom: 1px solid var(--line); text-align: right; font-weight: 600; }
.top-table thead th:first-child { text-align: left; }
.top-table tbody td { padding: .28rem .4rem; border-bottom: 1px solid rgba(var(--tint-rgb),.03); text-align: right; font-family: 'Space Mono', monospace; font-size: .67rem; color: var(--muted); white-space: nowrap; }
.top-table tbody td:first-child { text-align: left; color: var(--text); font-family: inherit; font-size: .72rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 180px; }
.top-table tbody tr:hover td { background: rgba(var(--tint-rgb),.02); }
.chart-tooltip { position: fixed; z-index: 9999; background: var(--bg-alt); border: 1px solid var(--line); border-radius: 5px; padding: .5rem .7rem; pointer-events: none; font-size: .72rem; white-space: nowrap; box-shadow: 0 4px 16px var(--shadow-strong); }
.ctt-time { color: var(--muted); font-size: .66rem; margin-bottom: .3rem; font-family: 'Space Mono', monospace; }
.ctt-row { display: flex; align-items: center; gap: .4rem; margin-top: .2rem; color: var(--text); }
.ctt-sw { width: 10px; height: 3px; border-radius: 2px; flex-shrink: 0; }
.ctt-val { margin-left: auto; font-family: 'Space Mono', monospace; color: var(--muted); }
.ctt-row.is-hot { font-weight: 700; }
.ctt-row.is-hot .ctt-val { color: var(--text); font-weight: 700; }

/* Live edge marker: pulses on the last complete bucket of a chart that is
   tracking the present. Halo expands and fades, dot breathes. */
@keyframes chart-spark-halo { 0% { r: 2.5; opacity: .5; } 100% { r: 9; opacity: 0; } }
@keyframes chart-spark-dot  { 0%, 100% { opacity: 1; } 50% { opacity: .4; } }
.chart-spark-halo { animation: chart-spark-halo 1.8s ease-out infinite; }
.chart-spark-dot  { animation: chart-spark-dot 1.8s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
  .chart-spark-halo { display: none; }
  .chart-spark-dot  { animation: none; }
}
.cdn-cards-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: .8rem; margin-bottom: 1.2rem; }
@media (max-width: 1000px) { .cdn-cards-grid { grid-template-columns: repeat(2, 1fr); } }
.cdn-provider-card { background: var(--bg-alt); border: 1px solid var(--line); border-left: 3px solid var(--cdn-accent, var(--brand)); border-radius: 6px; padding: 1rem 1.1rem; display: flex; flex-direction: column; align-items: center; gap: .6rem; }
.cdn-logo { width: 130px; height: 44px; object-fit: contain; opacity: .85; filter: brightness(1.1); }
.cdn-logo-placeholder { width: 130px; height: 44px; display: flex; align-items: center; justify-content: center; font-size: .95rem; font-weight: 700; letter-spacing: .05em; }
.cdn-card-donut-wrap { position: relative; display: flex; align-items: center; justify-content: center; }
.cdn-card-donut-center { position: absolute; display: flex; flex-direction: column; align-items: center; pointer-events: none; }
.cdn-card-donut-pct { font-size: 1rem; font-weight: 700; font-family: 'Space Mono', monospace; color: var(--text); }
.cdn-card-donut-lbl { font-size: .66rem; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.cdn-card-legend { width: 100%; display: flex; flex-direction: column; gap: .3rem; }
.cdn-card-legend-row { display: flex; align-items: center; gap: .4rem; font-size: .68rem; color: var(--text); }
.cdn-card-legend-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.cdn-card-legend-val { margin-left: auto; font-family: 'Space Mono', monospace; font-size: .66rem; color: var(--muted); }
.cdn-card-legend-rest { color: var(--muted); }

/* ── Spoofing panel ── */
.spoof-banner {
  display: flex; align-items: center; gap: 1rem;
  padding: .85rem 1.3rem; border-radius: 5px; margin-bottom: 1.4rem;
  border: 1px solid var(--border);
}
.spoof-clean { background: rgba(var(--brand-rgb),.06); border-color: var(--text-faint); }
.spoof-warn  { background: rgba(var(--status-warn-rgb),.06); border-color: rgba(var(--status-warn-rgb),.35); }
.spoof-alert { background: rgba(var(--status-error-rgb),.08); border-color: rgba(var(--status-error-rgb),.4); }

.spoof-banner-icon {
  font-size: 1.3rem; font-weight: 700; flex-shrink: 0;
  width: 2rem; text-align: center;
}
.spoof-clean .spoof-banner-icon { color: var(--accent); }
.spoof-warn  .spoof-banner-icon { color: var(--status-warn); }
.spoof-alert .spoof-banner-icon { color: var(--error); }

.spoof-banner-body { flex: 1; }
.spoof-banner-title { font-size: .9rem; font-weight: 700; letter-spacing: .03em; }
.spoof-clean .spoof-banner-title { color: var(--accent); }
.spoof-warn  .spoof-banner-title { color: var(--status-warn); }
.spoof-alert .spoof-banner-title { color: var(--error); }
.spoof-banner-sub { font-size: .72rem; color: var(--muted); margin-top: .15rem; }

.spoof-banner-badge {
  font-size: .66rem; font-weight: 700; letter-spacing: .1em;
  padding: 3px 10px; border-radius: 2px; flex-shrink: 0;
}
.spoof-clean .spoof-banner-badge { background: rgba(var(--brand-rgb),.15); color: var(--accent); }
.spoof-warn  .spoof-banner-badge { background: rgba(var(--status-warn-rgb),.15); color: var(--status-warn); }
.spoof-alert .spoof-banner-badge { background: rgba(var(--status-error-rgb),.15); color: var(--error); }
[data-theme="light"] .spoof-clean .spoof-banner-badge { background: rgba(var(--brand-rgb),.08); }

.spoof-method {
  display: grid; grid-template-columns: 1fr 1fr; gap: 1.6rem;
}
@media (max-width: 900px) { .spoof-method { grid-template-columns: 1fr; } }
.spoof-method-label {
  display: flex; align-items: center; gap: .5rem;
  font-size: .8rem; font-weight: 700; color: var(--text); margin-bottom: .4rem;
}
.spoof-method-dot {
  width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0;
}
.spoof-method-desc {
  max-width: 60ch; font-size: .8rem; color: var(--muted); line-height: 1.6;
}
.spoof-method-desc code {
  font-family: 'Space Mono', monospace; font-size: .76rem;
  background: rgba(var(--brand-rgb),.08); padding: 1px 5px; border-radius: 2px;
  color: var(--accent);
}

/* ── Mitigation panel ── */
.mit-chips { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: 1.4rem; }
.mit-chip {
  display: inline-flex; align-items: baseline; gap: .45rem;
  padding: 4px 10px; border-radius: 3px;
  border: 1px solid var(--line); background: rgba(var(--tint-rgb),.02);
}
.mit-chip-k { font-size: .66rem; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.mit-chip-v { font-family: 'Space Mono', monospace; font-size: .7rem; color: var(--text); }

.mit-chart { width: 100%; height: 190px; display: block; overflow: visible; }

/* ── Attack simulator (mitigation tab) ──────────────────────────────────────
   A form inside a dash-card, which nothing else in the dashboard does: the
   admin .frm-* inputs are reused for the fields, and only the layout and the
   sandbox marking live here. */
.mit-sim-form {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: .6rem; margin: .7rem 0 .9rem;
}
.mit-sim-f { display: flex; flex-direction: column; gap: 4px; }
.mit-sim-f > span {
  color: var(--muted); font-size: .66rem; text-transform: uppercase; letter-spacing: .04em;
}
.mit-sim-f-wide { grid-column: span 2; }
/* One 150px column fits a phone; span 2 forced a second past the card. */
@media (max-width: 600px) { .mit-sim-f-wide { grid-column: auto; } }
.mit-sim-act { justify-content: flex-end; }
.mit-sim-badge {
  font-family: 'Space Mono', monospace; font-size: .66rem; letter-spacing: .08em;
  border: 1px solid var(--status-warn); color: var(--status-warn);
  border-radius: 3px; padding: 1px 5px; margin-left: .5rem; vertical-align: middle;
}
.mit-sim-verdict {
  border-left: 3px solid var(--line); padding: .55rem .8rem; margin: .2rem 0 .8rem;
  background: var(--surface-2, transparent);
}
.mit-sim-verdict-head { font-size: .85rem; font-weight: 600; }
.mit-sim-verdict-why { font-size: .74rem; color: var(--text); margin-top: 2px; }
.mit-sim-verdict-bits {
  font-family: 'Space Mono', monospace; font-size: .68rem; color: var(--muted); margin-top: 5px;
}
.mit-sim-safe { font-size: .66rem; color: var(--muted); margin-top: 6px; font-style: italic; }
.mit-sim-kinds { margin: .4rem 0 0; padding-left: 1.1rem; font-size: .72rem; }
.mit-sim-legend {
  display: flex; gap: 1rem; flex-wrap: wrap; font-size: .66rem;
  color: var(--muted); margin: .3rem 0 .6rem;
}
.mit-sim-legend i {
  display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin-right: 4px;
}

/* Target column has to hold a full IPv6 address (39 chars in Space Mono), so it
   grows with the card instead of ellipsing every v6 target at 190px. */
.mit-gauge-row {
  display: grid; grid-template-columns: minmax(190px, 360px) minmax(120px, 320px) 1fr 82px 70px;
  align-items: center; gap: .6rem; font-size: .72rem;
  padding: 3px 5px; border-radius: 4px;
}
/* Five fixed columns need ~560px: under that the card scrolls, the page does not */
#mit-live { overflow-x: auto; }
/* A grid item's min-width is its content, so that table widened the whole
   column past a phone screen and the page clipped every card's right edge. */
#dash-tab-mitigation .dash-grid > .dash-card { min-width: 0; }
.mit-gauge-head {
  color: var(--muted); font-size: .66rem; text-transform: uppercase; letter-spacing: .04em;
  border-bottom: 1px solid rgba(var(--tint-rgb),.08); padding-bottom: 5px; margin-bottom: 2px;
}
.mit-gauge-click { cursor: pointer; transition: background .12s; }
.mit-gauge-click:hover { background: rgba(var(--tint-rgb),.06); }
.mit-gauge-click:hover .mit-gauge-ip { color: var(--read-accent); }
.mit-gauge-ip { font-family: 'Space Mono', monospace; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mit-gauge-vec { color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mit-gauge-bar { display: flex; align-items: center; gap: .5rem; }
.mit-gauge-bar .bar-track { flex: 1; display: block; }
.mit-gauge-bar .bar-fill { display: block; }   /* a span is inline: no height, no fill */
.mit-gauge-pct { width: 40px; flex-shrink: 0; text-align: right; font-family: 'Space Mono', monospace; font-size: .68rem; }
/* The current slot as a column of the customer table: the bar needs a
   floor width or the pct eats the track. */
.mit-now { min-width: 130px; }
.mit-r { text-align: right; font-family: 'Space Mono', monospace; font-size: .68rem; color: var(--muted); }
.mit-gauge-head .mit-r { font-family: inherit; font-size: .66rem; }
/* Live target opened on its sources: the rows reuse the gauge grid so the
   share bar and the rate sit under the target's own columns. */
.mit-gauge-row.is-on { background: rgba(var(--tint-rgb),.06); }
.mit-live-src {
  margin: 2px 0 8px 14px; padding: 4px 0 4px 10px;
  border-left: 2px solid var(--brand);
}
.mit-live-src-head { display: flex; justify-content: space-between; gap: .6rem; font-size: .66rem; padding: 0 5px 4px; }
.mit-live-fq { color: var(--read-accent); cursor: pointer; }
.mit-live-fq:hover { text-decoration: underline; }
.mit-live-src-row { font-size: .68rem; }

/* Policy in force: one block per router, three labelled groups side by side. */
.mit-pol-dev + .mit-pol-dev { border-top: 1px solid var(--line); margin-top: .9rem; padding-top: .9rem; }
.mit-pol-name { font-size: .8rem; font-weight: 600; color: var(--text); margin-bottom: .6rem; }
.mit-pol-groups { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1rem 1.8rem; }
.mit-pol-gh {
  font-size: .66rem; text-transform: uppercase; letter-spacing: .06em; color: var(--muted);
  border-bottom: 1px solid rgba(var(--tint-rgb),.08); padding-bottom: 4px; margin-bottom: 6px;
}
.mit-pol-kv { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: .35rem .9rem; margin: 0; font-size: .72rem; }
.mit-pol-kv dt { color: var(--muted); }
.mit-pol-kv dd { margin: 0; font-family: 'Space Mono', monospace; font-size: .7rem; color: var(--text); overflow-wrap: anywhere; }

/* Learning window progress — shown only until the device is arm-eligible. */
.mit-learn {
  display: flex; flex-direction: column; gap: .45rem;
  margin: -.6rem 0 1.4rem; padding: .7rem .9rem; border-radius: 4px;
  border: 1px solid var(--line); background: rgba(var(--tint-rgb),.02);
}
.mit-learn-row { display: grid; grid-template-columns: 170px 1fr 48px; align-items: center; gap: .7rem; }
.mit-learn-label { font-size: .66rem; text-transform: uppercase; letter-spacing: .06em; color: var(--muted);
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mit-learn-row .bar-track { display: block; }
.mit-learn-row .bar-fill { display: block; background: var(--read-accent); }
.mit-learn-pct { text-align: right; font-family: 'Space Mono', monospace; font-size: .68rem; color: var(--text); }

.mit-bar-n { color: var(--muted); }
/* Destinations without reply: name, evidence and senders on three lines, in
   a half-width card, so the label grows past the shared 200px. */
#mit-out-oneway .bar-row { align-items: flex-start; margin-bottom: .7rem; }
#mit-out-oneway .bar-label { width: clamp(180px, 55%, 420px); min-width: 0; flex-shrink: 1; white-space: normal; }
#mit-out-oneway .bar-label > span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#mit-out-oneway .bar-track, #mit-out-oneway .bar-val { margin-top: .4rem; }
.mit-ow-meta { font-size: .68rem; }
/* Both halves of the reflection / no-reply row: long labels ellipsise instead
   of pushing the 1fr track wider than the card. */
.dash-card:has(> #mit-out-oneway) { min-width: 0; }
/* Learned-prefix bars pack prefix + class + IP count into one label; the shared
   200px .bar-label cut every IPv6 prefix on a wide screen. */
#mit-prof-prefixes .bar-label { width: clamp(200px, 30vw, 430px); }
/* p99 rates read "749.3 Mbps" — the shared 64px .bar-val wrapped every one. */
#mit-prof-prefixes .bar-val { width: 82px; }
.mit-pill {
  display: inline-block; font-size: .66rem; padding: 1px 7px;
  border-radius: 3px; border: 1px solid currentColor; white-space: nowrap;
}
/* Evidence packet on an event row. The date is the toggle; the packet
   opens as a second row under it. */
.mit-ev-toggle { cursor: pointer; border-bottom: 1px dotted var(--muted); }
.mit-ev-toggle.mit-ev-open { color: var(--read-accent); }
/* Outranks `.exp-table tbody td`: that rule right-aligns and forbids
   wrapping, which pushed every value off the right edge of the page. */
.exp-table .mit-ev-row > td {
  padding: .5rem .8rem .7rem; text-align: left; white-space: normal;
  background: rgba(var(--tint-rgb),.03);
}
/* width:0 + min-width:100% keeps the packet from setting the table's
   preferred width: without it the three slot items lay out on one line,
   the table grows past the scroll wrapper and the last column is gone. */
.mit-ev-grid {
  display: grid; grid-template-columns: 130px 1fr; gap: .3rem .8rem;
  font-size: .68rem; align-items: baseline; width: 0; min-width: 100%;
}
.mit-ev-k { font-size: .66rem; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.mit-ev-item {
  display: inline-block; margin: 0 .7rem .2rem 0; white-space: nowrap;
  font-family: 'Space Mono', monospace; font-size: .66rem;
}
.mit-ev-none { font-size: .68rem; color: var(--muted); }
@media (max-width: 640px) {
  .mit-ev-grid { grid-template-columns: 1fr; }
  .mit-ev-item { white-space: normal; overflow-wrap: anywhere; }
}
.mit-out-sub {
  font-size: .66rem; text-transform: uppercase; letter-spacing: .06em; color: var(--muted);
  margin: .9rem 0 .4rem;
}
/* Customer table on the sent view: one row per customer, its lines as chips,
   the events nested under the name. A muted row is a customer the operator
   called legit: still listed, dimmed, at the bottom. */
.mit-line {
  display: inline-block; font-family: 'Space Mono', monospace; font-size: .66rem;
  padding: 0 5px; border-radius: 3px; border: 1px solid var(--line); margin: 1px 0;
}
.exp-table tbody td.mit-lines { white-space: normal; }
.mit-ev-nested { margin-top: .4rem; }
/* Incidents: the problem list above both views. An active row carries a
   pulsing red pill; a resolved one reads how long ago it ended, as plain text
   (a bordered .62rem pill at 60% opacity was unreadable). One line per row:
   the customer's lines sit inline after the name. Numeric columns shrink to
   their content so the slack goes to the customer and vector columns. */
.mit-inc-count { margin-left: .5rem; vertical-align: middle; }
.mit-inc-active { color: var(--status-error); animation: pulse 1.6s ease-in-out infinite; }
/* Resolved reads green, active stays red - the NMS convention. */
.mit-inc-done { color: var(--status-ok); white-space: nowrap; }
.mit-inc-table .mit-ev-toggle { font-weight: 600; }
.mit-inc-table tbody td { padding: .26rem .55rem; }
.mit-inc-table th, .mit-inc-table td { width: 1%; }
.mit-inc-table th:nth-child(2), .mit-inc-table td:nth-child(2),
.mit-inc-table th:nth-child(9), .mit-inc-table td:nth-child(9) { width: auto; max-width: none; }
.mit-inc-table td.mit-lines .mit-line { margin-left: .35rem; vertical-align: 1px; }
.mit-inc-table .mit-pill { font-size: .68rem; }
/* Botnet: a sender's newest incidents open under its ranking row, and the
   full history waits behind one button. */
.mit-sender-sub .exp-table tbody td { padding: .22rem .55rem; }
.mit-sender-sub .mit-sender-all { display: inline-block; margin-top: .45rem; }
.mit-hist-toggle { margin-bottom: .6rem; }
/* The signature is the same string the detail page headlines, so it reads in
   the detail's font, not the table's. */
.mit-inc-table td.mit-sig-cell { font-family: var(--font-mono); white-space: nowrap; }
/* A re-scored false positive. Neutral, not a status colour: the incident did
   happen, it just was not an attack. */
.mit-inc-fp { color: var(--text-muted); white-space: nowrap; margin-left: .35rem; }

/* Direction pill. It is a fact about the incident, not its state, so it does
   not pulse and does not use a status colour: sent is amber (our customer is
   the source), received is the read accent (our customer is the target). */
.mit-dir-pill {
  font-size: .72rem; padding: 2px 9px; font-weight: 600;
  letter-spacing: .04em; text-transform: uppercase;
}
.mit-dir-out { color: var(--status-warn); }
.mit-dir-in { color: var(--read-accent); }
.mit-inc-table .mit-dir-pill { font-size: .66rem; padding: 1px 7px; }
/* The head pills were .62rem next to a 1.4rem name and read as decoration. */
.mit-det-head .mit-pill { font-size: .8rem; padding: 3px 11px; }

/* One filter bar for the whole band. It pins under the 64px navbar, because
   every pick is made by clicking a panel below it: at 1440x900 the highlights
   grid is 899px tall, so a chip landing where the bar sits in the flow is off
   screen and reads as nothing happening. */
.mit-fbar { margin: 0 0 1.2rem; }
.mit-fbar-row {
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  padding: .6rem 0;
  background: rgba(var(--surface-deep-rgb),0.97);
  border-bottom: 1px solid var(--line);
}
/* Pinned by `_mitPin`, not by `position: sticky`: the dashboard pane is
   inside two overflow:hidden boxes, which become the scrolling box a sticky
   element is trapped in, and that box never scrolls. */
.mit-fbar.is-pinned .mit-fbar-row {
  position: fixed; top: 65px; z-index: 150;
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  box-shadow: 0 4px 14px var(--shadow-mid);
}
.mit-fbar .tm-badges { margin: 0; }
.mit-fbar .mit-f-chips { margin: 0; flex: 1 1 auto; }
/* The five selects behind one button: they reach a value the panels ranked
   past their cut, which is not the common move and does not earn a row. */
.mit-f-add { position: relative; }
.mit-f-add-btn {
  font: inherit; font-size: 11.5px; padding: 7px 14px; min-height: 0;
  letter-spacing: 0; text-transform: none; cursor: pointer;
  border: 1px solid var(--line); border-radius: 4px;
  background: var(--bg-alt); color: var(--muted);
}
.mit-f-add-btn:hover, .mit-f-add-btn[aria-expanded="true"] {
  border-color: var(--brand); color: var(--accent);
}
.mit-f-pop {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 30;
  display: flex; flex-direction: column; gap: .4rem; padding: .6rem;
  border: 1px solid var(--line); border-radius: 4px;
  background: rgb(var(--surface-deep-rgb));
  box-shadow: 0 6px 20px var(--shadow-mid);
}
.mit-f-pop[hidden] { display: none; }
.mit-f-pop .mit-f-sel { max-width: none; min-width: 15rem; }
.mit-f-lbl {
  font-size: .66rem; text-transform: uppercase; letter-spacing: .08em; color: var(--text-faint);
}
/* A customer login or an AS name can be long, so the select is capped. */
.mit-f-sel {
  font-family: inherit; font-size: 11.5px; padding: 6px 10px; max-width: 13rem;
  border: 1px solid var(--line); border-radius: 4px;
  background: var(--bg-alt); color: var(--text); cursor: pointer;
}
.mit-f-sel:focus { outline: none; border-color: var(--accent); }
/* Twelve columns: the history scrolls sideways before it clips the open link. */
#mit-incidents { overflow-x: auto; }

/* Status strip: the one line the tab exists to say. Colour is the state,
   the chips after it are each router's phase. */
.mit-strip {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  flex-wrap: wrap; padding: .8rem 1.1rem; margin-bottom: 12px; border-radius: 6px;
  border: 1px solid var(--line); background: var(--bg-alt);
}
.mit-strip-main { display: flex; align-items: baseline; gap: .7rem; flex-wrap: wrap; }
.mit-strip-dot { width: 10px; height: 10px; border-radius: 50%; background: currentColor; align-self: center; }
.mit-strip-title { font-family: 'Rajdhani', sans-serif; font-size: 1.25rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
.mit-strip-sub { font-size: .82rem; color: var(--muted); }
.mit-strip-ago { font-family: 'Space Mono', monospace; font-size: .7rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.mit-strip-chips { display: flex; gap: .4rem; flex-wrap: wrap; }
.mit-strip-chip { font-family: 'Space Mono', monospace; font-size: .66rem; padding: 2px 7px; border-radius: 3px; border: 1px solid var(--line); color: var(--muted); }
.mit-strip-quiet { color: var(--status-ok); border-color: rgba(var(--status-ok-rgb),.4); background: rgba(var(--status-ok-rgb),.06); }
.mit-strip-warn  { color: var(--status-warn); border-color: rgba(var(--status-warn-rgb),.4); background: rgba(var(--status-warn-rgb),.06); }
.mit-strip-alert { color: var(--status-error); border-color: rgba(var(--status-error-rgb),.5); background: rgba(var(--status-error-rgb),.08); }
.mit-strip-alert .mit-strip-dot { animation: pulse 1.6s ease-in-out infinite; }
.mit-strip-quiet .mit-strip-title, .mit-strip-warn .mit-strip-title, .mit-strip-alert .mit-strip-title { color: inherit; }

/* One card per open incident. Numbers first, the rest as chips. */
#mit-cards:empty { display: none; }
.mit-card {
  border: 1px solid rgba(var(--status-error-rgb),.45); border-left: 4px solid var(--status-error);
  border-radius: 6px; background: var(--bg-alt); padding: .9rem 1.1rem; margin-bottom: 12px;
}
.mit-card-head { display: flex; align-items: baseline; gap: .7rem; flex-wrap: wrap; margin-bottom: .6rem; }
/* A PPPoE username or a v6 address is one word: break it rather than the card */
.mit-card-who { font-family: 'Space Mono', monospace; font-size: 1.05rem; font-weight: 700; min-width: 0; overflow-wrap: anywhere; }
.mit-card-user { font-family: 'Space Mono', monospace; font-size: .8rem; color: var(--muted); }
.mit-card-dev { font-size: .78rem; color: var(--text-faint); min-width: 0; overflow-wrap: anywhere; }
.mit-card-since { margin-left: auto; font-size: .78rem; color: var(--muted); }
.mit-card-kpis { display: flex; gap: 1.6rem; flex-wrap: wrap; margin-bottom: .6rem; }
.mit-card-kpis > div { display: flex; flex-direction: column; }
.mit-card-kpis b { font-family: 'Space Mono', monospace; font-size: 1.1rem; font-weight: 700; }
.mit-card-kpis small { font-size: .68rem; text-transform: uppercase; letter-spacing: .08em; color: var(--text-faint); }
.mit-card-foot { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
.mit-card-spark { width: 160px; height: 28px; overflow: visible; }
.mit-card-open { margin-left: auto; cursor: pointer; font-family: 'Space Mono', monospace; font-size: .72rem; text-transform: uppercase; letter-spacing: .08em; color: var(--accent); text-decoration: none; }
.mit-card-open:hover { text-decoration: underline; }

/* 30-day strip: one bar per day, count as height, the heaviest day labelled. */
.mit-days-grid { margin-bottom: 1.2rem; }
/* The bands above the filter bar and the history: same gap between two
   grids as inside one. */
#mit-hl, #mit-out-grid, #mit-sent > .dash-grid { margin-bottom: 1.2rem; }
/* Divider inside the links panel: what follows measured the same attack
   from the inside and is not part of the ranking above it. */
.mit-if-split {
  margin: .6rem 0 .3rem; padding-top: .5rem;
  border-top: 1px solid var(--border);
}
.mit-days { width: 100%; height: 150px; display: block; }
.mit-days .mit-days-bar { fill: var(--status-error); opacity: .75; }
.mit-days .mit-days-bar.is-hot { opacity: 1; }
.mit-days .mit-days-zero { fill: var(--line); }
.mit-days text { font-family: 'Space Mono', monospace; font-size: 11px; fill: var(--muted); }
.mit-days .mit-days-lbl { font-size: 12px; font-weight: 700; fill: var(--text); }

/* Attack timeline, above the history table. One bar per incident over the
   window: width is duration, a lane is a row of attacks that never overlapped. */
.mit-tl { width: 100%; display: block; margin: .5rem 0 .25rem; }
.mit-tl .mit-tl-grid { stroke: var(--line); stroke-width: 1; opacity: .5; }
.mit-tl text { font-family: 'Space Mono', monospace; font-size: 11px; fill: var(--muted); }
.mit-tl .mit-tl-bar { fill: var(--read-accent); opacity: .7; cursor: pointer; }
.mit-tl .mit-tl-bar.is-out { fill: var(--status-warn); }
.mit-tl .mit-tl-bar:hover { opacity: 1; }
/* Still running: the right edge is now, not an end. */
.mit-tl .mit-tl-bar.is-live { fill: var(--status-error); opacity: .85; stroke: var(--status-error); stroke-dasharray: 3 2; }
/* Started before the window: the left edge is the axis, not the start. */
.mit-tl .mit-tl-bar.is-clipped { rx: 0; }

/* Incident detail: replaces the list. */
.mit-back { display: inline-block; margin-bottom: .8rem; cursor: pointer; font-family: 'Space Mono', monospace; font-size: .74rem; text-transform: uppercase; letter-spacing: .08em; color: var(--accent); }
.mit-det-head { display: flex; align-items: baseline; gap: .8rem; flex-wrap: wrap; margin-bottom: .8rem; }
.mit-det-head .mit-card-who { font-size: 1.4rem; }
/* The plot goes through the shared `drawLineChart`, which sets its own
   viewBox, height and label fonts - the only thing left here is the box. */
.mit-det-chart { width: 100%; display: block; overflow: visible; }
.mit-det-chart + .chart-legend { margin-top: 10px; }
.mit-det-span { font-weight: 400; color: var(--text-muted); font-family: var(--mono); font-size: .85em; margin-left: 8px; }

/* Timeline: a dot per step on a rail, stamp | title, sentence under the
   title. Red while the attack runs, green when it ends, grey for the action
   the phase allowed. */
.mit-tl { list-style: none; margin: 0; padding: 0; }
.mit-tl li {
  position: relative; display: grid; grid-template-columns: 8.5rem 1fr;
  gap: .1rem .9rem; padding: .3rem 0 .55rem 1.1rem; font-size: .82rem;
}
.mit-tl li::before {
  content: ''; position: absolute; left: 0; top: .62rem; width: 9px; height: 9px;
  border-radius: 50%; background: var(--status-error);
}
.mit-tl li::after {
  content: ''; position: absolute; left: 4px; top: 1.2rem; bottom: -.3rem;
  width: 1px; background: var(--line);
}
.mit-tl li:last-child::after { display: none; }
.mit-tl li.is-ok::before { background: var(--status-ok); }
.mit-tl li.is-muted::before { background: var(--muted); }
.mit-tl li.is-warn::before { background: var(--status-warn); }
.mit-tl time { font-family: 'Space Mono', monospace; font-size: .74rem; color: var(--muted); white-space: nowrap; padding-top: .1rem; }
.mit-tl p { grid-column: 2; margin: 0; font-size: .78rem; line-height: 1.45; color: var(--muted); }
.mit-tl-copy {
  float: right; cursor: pointer; font-family: 'Space Mono', monospace; font-size: .66rem;
  font-weight: 400; text-transform: uppercase; letter-spacing: .08em; color: var(--accent);
}
.mit-tl-copy:hover { text-decoration: underline; }

/* Shared bar cell: a share of the window drawn behind the number, used by the
   address tables, the signature lists and the per-slot table. A bar plus the
   value reads in one pass; the same numbers as prose did not. */
.mit-bar-cell { text-align: right; white-space: nowrap; }
.mit-bar {
  display: inline-block; width: 90px; height: 6px; margin-right: .5rem;
  vertical-align: middle; border-radius: 2px; background: rgba(var(--tint-rgb),.08);
}
.mit-bar > i { display: block; height: 100%; border-radius: 2px; background: var(--status-error); opacity: .7; }
.mit-bar-val { font-family: 'Space Mono', monospace; font-size: .72rem; }
.mit-bar-val small { color: var(--muted); margin-left: .3rem; }
/* Second line under an address or a network: the PTR and the declared type. */
/* `word-break: break-all` split a PTR mid-label ("corbin" / "a.ru"); the
   markup carries a <wbr> after every dot, so it breaks on the labels. */
.mit-sub { display: block; font-size: .66rem; color: var(--muted); overflow-wrap: anywhere; }

/* Signature: one headline, then one 100%-stacked bar per dimension. The
   bars share a left edge and a width, so the dominant share of each reads
   in one pass down the card. */
.mit-sig-head {
  font-family: 'Space Mono', monospace; font-size: 1.6rem; font-weight: 700;
  color: var(--status-error); letter-spacing: .02em; margin-top: .2rem;
}
.mit-sig-sub { font-size: .72rem; line-height: 1.45; color: var(--muted); margin: .15rem 0 0; }
/* Label and legend on one line, the bar full width under them: the 200px
   cap the bar had before read as a bar stopping at 40%. */
.mit-sig-row { margin-top: 1rem; }
.mit-sig-top {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: .6rem 1.2rem; flex-wrap: wrap; margin-bottom: .35rem;
}
.mit-sig-t {
  font-size: .68rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .06em; color: var(--muted);
}
.mit-sig-bar {
  display: flex; height: 12px; border-radius: 3px; overflow: hidden;
  background: rgba(var(--tint-rgb),.08);
}
.mit-sig-bar > i { display: block; height: 100%; background: var(--status-error); }
.mit-sig-legend {
  display: flex; flex-wrap: wrap; justify-content: flex-end; gap: .1rem 1rem;
  font-family: 'Space Mono', monospace; font-size: .72rem; color: var(--text);
}
.mit-sig-key > i {
  display: inline-block; width: 9px; height: 9px; margin-right: .4rem;
  border-radius: 2px; background: var(--status-error); vertical-align: baseline;
}
/* Signature and the per-slot window share one full-width card, side by
   side: both are the evidence of one incident, and in a half-width card
   the 7-column table did not fit. */
.mit-sig-grid { display: grid; grid-template-columns: minmax(280px, 1fr) 2fr; gap: 1.2rem 2.4rem; }
@media (max-width: 1100px) { .mit-sig-grid { grid-template-columns: 1fr; } }
/* min-width: 0 so the 7-column table shrinks to its column instead of
   pushing past the card; past that it scrolls. */
.mit-sig-win { min-width: 0; overflow-x: auto; }
/* The one-address side of an incident (the customer line that sent it, or
   the target that received it) is a line above the other side's table. */
.mit-addr-line {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .4rem 1rem;
  padding: .55rem .8rem; margin-bottom: 1rem;
  border: 1px solid var(--line); border-radius: 4px;
  font-family: 'Space Mono', monospace; font-size: .8rem;
}
.mit-addr-k {
  font-size: .66rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .06em; color: var(--muted); font-family: inherit;
}
.mit-addr-sub { font-size: .7rem; color: var(--muted); }
.mit-addr-line .mit-bar-val { margin-left: auto; }
/* A PTR is the one cell allowed to wrap; the <wbr> after each dot picks the label. */
.exp-table tbody td.mit-ptr { max-width: 260px; font-family: 'Space Mono', monospace !important; font-size: .68rem !important; color: var(--muted) !important; }

/* Sidebar counter on the Mitigation item: open incidents across the scope. */
.csb-badge {
  display: inline-block; margin-left: .5rem; padding: 0 6px; min-width: 1.4em; text-align: center;
  border-radius: 9px; font-size: 10.5px; font-weight: 700; letter-spacing: 0;
  color: #fff; background: var(--status-error); vertical-align: middle;
  animation: pulse 1.6s ease-in-out infinite;
}
/* The rules on the wire next to Security -> Actions: a quiet count, not an alert */
.csb-count { margin-left: .5rem; font-size: 10.5px; font-weight: 700; color: var(--muted); vertical-align: middle; }
/* A failed action waits for the operator; it is not an attack, so it does not pulse */
#csb-act-failed { animation: none; }
.mit-ev-nested .mit-out-sub { margin-top: .6rem; }
.mit-out-sub:first-of-type { margin-top: 0; }
/* Near-miss labels carry who + why, and an IPv6 /128 alone fills the line.
   Two rows instead of one ellipsis that ate the reason. */
#mit-near .bar-label, #mit-hunt .bar-label, #mit-cust .bar-label {
  width: clamp(240px, 32vw, 430px);
  white-space: normal; overflow: visible; text-overflow: clip;
  line-height: 1.25; padding: .15rem 0;
}
#mit-near .bar-label > span, #mit-hunt .bar-label > span,
#mit-cust .bar-label > span { display: block; overflow-wrap: anywhere; }
#mit-near .mit-near-who, #mit-hunt .mit-near-who,
#mit-cust .mit-near-who { font-variant-numeric: tabular-nums; }
/* Under 640px the 240px floor plus the value ran past the card. */
@media (max-width: 640px) {
  #mit-near .bar-label, #mit-hunt .bar-label { width: 60%; flex-shrink: 1; }
}
/* Botnet -> Customers. The half card gives the label a share of the row:
   the 430px clamp left its bars 20px wide at 1440. */
#mit-cust .bar-label { width: 55%; min-width: 0; flex-shrink: 1; }
/* Botnet -> Attacks sent -> C2 candidates: address, one dot per bot, bots
   as a share of the address's reach. Columns come inline from the JS. */
/* contain: the grid card took the rows' 560px as its min width at 390px
   and an ancestor clipped it; now the card fits and .hunt scrolls. */
.hunt { overflow-x: auto; contain: inline-size; }
.hunt-sum { font-size: .72rem; color: var(--muted); margin-bottom: .5rem; }
.hunt-row {
  display: grid; align-items: center; gap: .75rem; min-width: 560px;
  padding: .3rem 4px; border-radius: 3px; font-size: .74rem;
}
.hunt-click { cursor: pointer; transition: background .12s; }
.hunt-click:hover { background: rgba(var(--tint-rgb), .06); }
.hunt-click:hover .hunt-who b { color: var(--read-accent); }
.hunt-who { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hunt-who b { font-weight: 500; font-variant-numeric: tabular-nums; }
.hunt-who > span { color: var(--muted); }
.hunt-chip {
  font-style: normal; font-size: .66rem; color: var(--status-warn);
  border: 1px solid var(--status-warn); border-radius: 3px; padding: 0 .3rem; margin-left: .3rem;
}
.hunt-dots { display: flex; justify-content: flex-end; }
.hunt-dots > * { width: 1rem; flex: none; }
.hunt-dot { display: block; height: .5rem; width: .5rem !important; margin: 0 .25rem; border-radius: 50%;
  border: 1px solid var(--border); }
.hunt-dot.on { background: var(--status-warn); border-color: var(--status-warn); }
.hunt-head { align-items: end; cursor: default; padding-bottom: .4rem; border-bottom: 1px solid var(--border);
  margin-bottom: .2rem; font-size: .66rem; color: var(--muted); }
.hunt-head .hunt-dots > span {
  writing-mode: vertical-rl; transform: rotate(180deg); max-height: 6.5rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; line-height: 1rem;
}
.hunt-head .hunt-share { text-transform: uppercase; letter-spacing: .08em; }
.hunt-bar { height: 6px; border-radius: 3px; background: rgba(var(--tint-rgb), .08); overflow: hidden; }
.hunt-bar > i { display: block; height: 100%; background: var(--status-warn); }
.hunt-share { color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.hunt-share b { color: var(--fg); font-weight: 500; }
.hunt-ago { color: var(--muted); font-size: .68rem; text-align: right; white-space: nowrap; }
.hunt-svc { margin-top: .6rem; }
.hunt-svc > summary { cursor: pointer; font-size: .72rem; color: var(--muted); padding: .3rem 0; }
.hunt-svc > summary > span { opacity: .7; }
.hunt-svc .hunt-row { opacity: .6; }
.hunt-svc .hunt-bar > i, .hunt-svc .hunt-dot.on { background: var(--muted); border-color: var(--muted); }
.mit-bar-head {
  display: flex; justify-content: space-between; gap: 1rem;
  font-size: .66rem; text-transform: uppercase; letter-spacing: .08em; color: var(--muted);
  border-bottom: 1px solid var(--border); padding-bottom: .3rem; margin-bottom: .55rem;
}
.mit-bar-group {
  font-size: .66rem; text-transform: uppercase; letter-spacing: .08em; color: var(--muted);
  margin: .7rem 0 .35rem;
}
.mit-bar-head + .mit-bar-group { margin-top: 0; }
.mit-bar-group > span { font-family: 'Space Mono', monospace; margin-left: .3rem; }
.mit-port { color: var(--muted); font-size: .72rem; margin-left: .35rem; }
.mit-intel-legend {
  display: flex; gap: 1rem; flex-wrap: wrap; margin-top: .8rem; padding-top: .5rem;
  border-top: 1px solid var(--border); font-size: .68rem; color: var(--muted);
}
.mit-intel-legend i { display: inline-block; width: 8px; height: 8px; border-radius: 2px; margin-right: .35rem; vertical-align: middle; }
.mit-hot { color: var(--status-error); white-space: nowrap; }
.mit-new { color: var(--status-warn); font-size: .66rem; text-transform: uppercase; letter-spacing: .05em; }
.mit-fam-chip {
  margin-left: .6rem; padding: 0 .55rem; height: auto; min-height: 0; line-height: 1.5;
  border: 1px solid var(--border); border-radius: 9px;
  background: transparent; color: var(--text); font: inherit; font-size: .68rem;
  letter-spacing: 0; text-transform: none; cursor: pointer; vertical-align: middle;
}
.mit-fam-chip:hover { border-color: var(--read-accent); color: var(--read-accent); }
/* Botnet -> Do Intel head: three segments in one band (_mitRenderHero). */
.bot-hero {
  display: grid; grid-template-columns: minmax(280px, 1.6fr) 1fr 1fr; gap: 0;
  background: var(--bg-alt); border: 1px solid var(--line); border-radius: 6px; margin-bottom: 1.2rem;
}
.bot-hero.bv-intel { grid-template-columns: minmax(280px, 1.6fr) 1fr 1fr 1fr; }
.bot-hero-seg { display: flex; flex-direction: column; gap: .45rem; padding: 1rem 1.4rem; min-width: 0; }
.bot-hero-seg + .bot-hero-seg { border-left: 1px solid var(--line); }
.bot-hero-row { display: flex; align-items: center; gap: 1.1rem; }
.bot-hero .dash-total-val { font-size: 1.9rem; line-height: 1; }
.bot-hero .mit-bar-n { display: flex; flex-direction: column; gap: .1rem; font-size: .74rem; }
/* Exposed services pairs the count with what reflection is, in words,
   before any chart. */
.exp-hero { grid-template-columns: minmax(280px, 1fr) 2fr; }
.exp-intro { margin: 0; max-width: 60ch; font-size: .8rem; line-height: 1.5; color: var(--text); }
@media (max-width: 900px) {
  .bot-hero, .bot-hero.bv-intel { grid-template-columns: 1fr; }
  .bot-hero-seg + .bot-hero-seg { border-left: 0; border-top: 1px solid var(--line); }
}
/* Botnet -> Customers head: the 24 h spark and the top botnets as bars */
.bot-spark { flex: 1; height: 34px; max-width: 220px; }
.bot-spark rect { fill: var(--status-neutral); }
.bot-spark rect.live { fill: none; stroke: var(--status-neutral); stroke-width: .08; stroke-dasharray: .15 .1; vector-effect: non-scaling-stroke; }
.bot-fam-bars { display: flex; flex-direction: column; gap: 3px; }
.bot-fam-bars button {
  display: grid; grid-template-columns: 6.5rem 1fr 2.4rem; align-items: center; gap: .5rem;
  padding: 1px 0; border: 0; background: none; color: var(--text); font: inherit; font-size: .72rem; cursor: pointer; text-align: left;
  min-height: 0; height: auto; line-height: 1.25; text-transform: none; letter-spacing: 0; box-shadow: none;
}
.bot-fam-bars span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bot-fam-bars i { display: block; height: 6px; border-radius: 3px; background: var(--status-error); opacity: .75; }
.bot-fam-bars b { font-weight: 500; text-align: right; color: var(--muted); }
.bot-fam-bars button:hover span, .bot-fam-bars button.on span { color: var(--read-accent); }
.bot-fam-bars button.on i { opacity: 1; }
.bot-days { display: flex; align-items: flex-end; gap: 5px; height: 52px; flex: 1; max-width: 260px; }
.bot-day { flex: 1; height: 100%; display: flex; flex-direction: column; justify-content: flex-end; align-items: stretch; gap: 3px; cursor: help; }
.bot-day > span { font-size: .66rem; text-transform: uppercase; color: var(--muted); text-align: center; line-height: 1; }
.bot-day-col {
  min-height: 2px; background: var(--status-neutral); opacity: .55; border-radius: 2px 2px 0 0;
  display: flex; flex-direction: column; justify-content: flex-end; overflow: hidden;
}
.bot-day-col > i { display: block; background: var(--status-error); }
.bot-day:last-child .bot-day-col { opacity: .9; }
.bot-day:hover .bot-day-col { opacity: 1; }
.bot-split { display: flex; align-items: center; gap: .8rem; font-size: .72rem; color: var(--muted); flex-wrap: wrap; }
.bot-split-bar { flex: 1 1 100%; height: 6px; border-radius: 3px; background: var(--status-neutral); opacity: .8; overflow: hidden; }
.bot-split-bar > i { display: block; height: 100%; background: var(--status-error); }
.bot-ring text { font-family: 'Space Mono', monospace; font-size: 12px; fill: var(--text); }
/* Botnets treemap (_mitLayTree): tiles are placed in px over the box. */
/* The tree fills its card down to the worklist beside it. */
.bot-tree-card { display: flex; flex-direction: column; }
.bot-tree-card > #mit-botnets:not(.dash-no-data) { flex: 1; display: flex; flex-direction: column; }
.bot-tree { position: relative; flex: 1 1 auto; min-height: 360px; }
.bot-tile {
  position: absolute; box-sizing: border-box; border: 2px solid var(--bg-alt); border-left: 3px solid var(--c);
  border-radius: 4px; padding: .45rem .55rem; margin: 0; min-height: 0; height: auto;
  background: color-mix(in srgb, var(--c) calc(var(--a) * 100%), transparent);
  color: var(--text); font: inherit; text-transform: none; letter-spacing: 0; text-align: left;
  display: flex; flex-direction: column; gap: .1rem; overflow: hidden; cursor: pointer;
  transition: opacity .15s, filter .15s;
}
.bot-tile:hover { filter: brightness(1.25); }
.bot-tile-n { font-family: 'Space Mono', monospace; font-size: 1.25rem; line-height: 1.1; }
.bot-tile-name { font-size: .8rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bot-tile-meta { font-size: .66rem; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bot-tile-att { position: absolute; left: 0; bottom: 0; height: 4px; background: var(--status-error); }
.bot-tile.sm { padding: .3rem .4rem; }
.bot-tile.sm .bot-tile-n { font-size: .9rem; }
.bot-tile.sm .bot-tile-meta { display: none; }
.bot-tile.xs > span { display: none; }
.mit-fam-pick .bot-tile:not(.on) { opacity: .35; }
.bot-tile.on { box-shadow: inset 0 0 0 1px var(--c); }
.bot-tree-key { margin-left: auto; }
/* Who to call first (_mitRenderInfected): name, family chips, hours meter. */
.bot-who {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: auto auto; column-gap: 1rem; row-gap: .2rem;
  width: 100%; padding: .4rem .3rem; margin: 0; min-height: 0; height: auto; border: 0; border-radius: 4px;
  border-bottom: 1px solid var(--line); background: none; color: var(--text); font: inherit;
  text-transform: none; letter-spacing: 0; text-align: left; cursor: pointer;
}
.bot-who:hover { background: var(--surface-raised); }
.bot-who-name { font-size: .8rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bot-who-fams { grid-row: 2; display: flex; gap: .3rem; flex-wrap: wrap; }
/* Column names over the rows, as .bot-cl-head on the Customers view. */
.bot-who-head {
  display: flex; justify-content: space-between; gap: 1rem; padding: .3rem .3rem .4rem;
  border-bottom: 1px solid var(--line); font-size: .66rem; text-transform: uppercase; letter-spacing: .08em; color: var(--muted);
}
.bot-who-h { grid-row: 1 / 3; grid-column: 2; display: flex; align-items: center; gap: .5rem; font-family: 'Space Mono', monospace; font-size: .74rem; color: var(--muted); }
.bot-chip {
  font-style: normal; font-size: .66rem; line-height: 1.5; padding: 0 .45rem; border-radius: 8px;
  border: 1px solid var(--line); color: var(--muted); white-space: nowrap;
}
.bot-chip.on { border-color: var(--read-accent); color: var(--read-accent); }
.bot-meter { position: relative; display: inline-block; width: 90px; height: 6px; border-radius: 3px; background: var(--line); overflow: hidden; }
.bot-meter > i { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 3px; }
.bot-meter > .bot-meter-att { background: var(--status-error); }
/* Where the botnet hosts live (_mitRenderC2Hosts): one box per network,
   flowing in columns so a network with many hosts does not stretch a row. */
.bot-as-grid { column-width: 340px; column-gap: 1.2rem; }
.bot-as { break-inside: avoid; margin-bottom: 1rem; border-top: 1px solid var(--line); padding-top: .5rem; }
.bot-as-h { display: flex; align-items: baseline; gap: .5rem; font-size: .74rem; margin-bottom: .25rem; min-width: 0; }
.bot-as-h > b { font-family: 'Space Mono', monospace; font-weight: 400; color: var(--read-accent); }
.bot-as-h > span:nth-child(2) { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1; }
.bot-as-n { color: var(--muted); font-size: .66rem; white-space: nowrap; }
.bot-host {
  display: grid; grid-template-columns: 8px minmax(0, 1.3fr) minmax(0, 1fr) 70px 2.4rem; align-items: center; gap: .55rem;
  width: 100%; padding: .22rem .2rem; margin: 0; min-height: 0; height: auto; border: 0; border-radius: 3px; background: none;
  color: var(--text); font: inherit; font-size: .76rem; text-transform: none; letter-spacing: 0; text-align: left; cursor: pointer;
}
.bot-host:hover { background: var(--surface-raised); }
.bot-host .bot-meter { width: 100%; }
.bot-host-ip { font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bot-host-ip .mit-port { margin-left: .1rem; font-size: .66rem; }
.bot-host-fam { color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bot-host-n { font-family: 'Space Mono', monospace; text-align: right; }
.bot-dot { width: 8px; height: 8px; border-radius: 50%; }
/* Botnet views (botView): only the picked one shows, over the inline display
   the renderers set. An empty card under Attacks sent is noise, so
   it goes too, except the incident history: "no incident" is the answer
   there. Mitigation has no data-bv and keeps every card. */
.bot-views-row { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; margin-bottom: .75rem; }
.bot-views-row .mit-bar-n { cursor: help; }
#mit-main[data-bv]:not([data-bv="intel"]) .bv-intel,
#mit-main[data-bv]:not([data-bv="sent"]) .bv-sent,
#mit-main[data-bv]:not([data-bv="customers"]) .bv-customers,
#mit-main[data-bv]:not([data-bv="quarantine"]) .bv-quarantine,
#mit-main[data-bv]:not([data-bv="campaigns"]) .bv-campaigns,
#mit-main[data-bv] .bv-sent > .dash-card:has(> .dash-no-data):not(:has(> #mit-incidents)) { display: none !important; }
#mit-botnets-h, #mit-intel-h, #mit-c2-hosts-h, #mit-hunt-h, #mit-cust-h { cursor: help; }
/* The Block control on the host rows (_mitBlockCtl), and the blocked badge
   that opens the rule on Security -> Actions (_mitBlockedBadge). The control is a span: the rows are buttons already. With
   it, every row of the C2 hosts card takes one more fixed column, and the
   network boxes get wider so the address keeps its room. */
.bot-as-grid.has-blk { column-width: 400px; }
.bot-host.has-blk { grid-template-columns: 8px minmax(0, 1.3fr) minmax(0, 1fr) 60px 2.4rem 4.6rem; }
.bot-host-blk, .bot-cl-blk { display: flex; justify-content: flex-end; min-width: 0; }
.bot-block-btn, .bot-block-badge {
  display: inline-block; padding: 0 .45rem; border-radius: 8px; font-size: .66rem; line-height: 1.6;
  white-space: nowrap; letter-spacing: 0; text-transform: none;
}
.bot-block-btn { border: 1px solid var(--line); color: var(--muted); cursor: pointer; }
.bot-block-btn:hover, .bot-block-btn:focus-visible {
  border-color: var(--status-error); color: var(--status-error); background: rgba(var(--status-error-rgb), .08); outline: none;
}
.bot-block-badge { border: 1px solid rgba(var(--status-error-rgb), .45); color: var(--status-error); background: rgba(var(--status-error-rgb), .08); }
.bot-block-badge[data-host] { cursor: pointer; }
.bot-block-badge[data-host]:hover, .bot-block-badge[data-host]:focus-visible { background: rgba(var(--status-error-rgb), .2); outline: none; }
.bot-blk-targets { display: flex; align-items: center; gap: .4rem 1.2rem; flex-wrap: wrap; margin-bottom: .8rem; font-size: .72rem; color: var(--muted); }
.bot-blk-tg b { font-weight: 400; color: var(--text); margin-right: .3rem; }
.bot-blk-tg::before { content: ''; display: inline-block; width: 7px; height: 7px; border-radius: 50%; margin-right: .4rem; background: var(--status-warn); vertical-align: middle; }
.bot-blk-tg.ok::before { background: var(--status-ok); }
/* A card's widest line no longer widens the one-column grid past a phone */
#dash-tab-actions .dash-grid > .dash-card { min-width: 0; }
#dash-tab-actions[data-fam="botnet"] #mit-blk-auto-card,
#dash-tab-actions[data-fam="scanner"] #scan-auto-card { grid-column: 1 / -1; }
.bot-blk-targets[hidden] { display: none; }
/* The blocks' band on Actions: three figures in the band Do Intel uses */
.bot-blk-hero { grid-template-columns: 1fr 1fr 1.5fr; margin-bottom: 1rem; }
@media (max-width: 900px) { .bot-blk-hero { grid-template-columns: 1fr; } }
.bot-blk-hero[hidden] { display: none; }
.bot-blk-hero .dash-total-val { display: inline-flex; align-items: center; gap: .5rem; }
.bot-dot.is-ok { background: var(--status-ok); }
.bot-dot.is-err { background: var(--status-error); }
#mit-intel-cont-n { display: inline-flex; align-items: center; gap: .5rem; }
#mit-intel-cont-n .bot-dot { width: 9px; height: 9px; flex: none; }
.mit-strip-alert .mit-strip-sub, .mit-strip-warn .mit-strip-sub { color: inherit; opacity: .85; }
.mit-strip-link { text-decoration: none; color: var(--text); }
.mit-strip-link:hover { border-color: var(--read-accent); color: var(--read-accent); }
/* Hero figures: the effect as a verdict over two before/after dumbbells
   on one scale. Marks in line and muted ink, the customers behind the
   blocks in text ink. */
.bot-hero .bot-did-v { font-size: 1.5rem; }
.bot-did-v.is-ok { color: var(--status-ok); }
.bot-did-v.is-warn { color: var(--status-warn); }
.bot-did-v.is-thin { color: var(--muted); }
.bot-did { display: grid; grid-template-columns: auto minmax(50px, 110px) auto auto; align-items: center; gap: .25rem .6rem; font-size: .74rem; color: var(--muted); }
.bot-did > * { white-space: nowrap; }
.bot-did-n, .bot-did-p { font-family: 'Space Mono', monospace; font-weight: 400; }
.bot-did-p { text-align: right; }
.bot-did > :nth-child(-n+4) { color: var(--text); }
.bot-did-bar { display: block; width: 100%; height: 14px; }
.bot-did-bar line.is-track { stroke: var(--line); stroke-width: 1; }
.bot-did-bar line.is-span { stroke: var(--muted); stroke-width: 2; }
.bot-did-bar circle.is-before { fill: var(--bg-alt); stroke: var(--muted); stroke-width: 1.5; }
.bot-did-bar circle.is-after { fill: var(--muted); }
.bot-did-bar.is-mine line.is-span { stroke: var(--text); }
.bot-did-bar.is-mine circle.is-before { stroke: var(--text); }
.bot-did-bar.is-mine circle.is-after { fill: var(--text); }
.bot-hero-hosts { flex-direction: row !important; flex-wrap: wrap; gap: .2rem .6rem !important; font-family: 'Space Mono', monospace; }
.bot-auto-pill { padding: .15rem .6rem; border: 1px solid var(--border); border-radius: 6px; font-size: .72rem; font-weight: 600; color: var(--muted); }
.bot-auto-pill.is-observe { background: rgba(var(--status-warn-rgb), .16); color: var(--status-warn); border-color: transparent; }
.bot-auto-pill.is-enforce { background: rgba(var(--status-ok-rgb), .16); color: var(--status-ok); border-color: transparent; }
[data-theme="light"] .bot-auto-pill.is-observe { background: rgba(var(--status-warn-rgb), .08); }
[data-theme="light"] .bot-auto-pill.is-enforce { background: rgba(var(--status-ok-rgb), .08); }
.bot-blk-st { display: inline-flex; align-items: center; gap: .4rem; }
/* Botnet -> Campaigns list (_mitRenderCampaigns): the Blocks row grid. */
.bot-camp { --blk-cols: 8rem minmax(0, 1fr) minmax(0, .8fr) minmax(0, 1.6fr) minmax(0, 1fr) 6.5rem; overflow-x: auto; }
.bot-camp .bot-blk-row { min-width: 760px; padding: .6rem .3rem; }
/* Campaigns head: what a campaign is under the count, then three numbers */
.bot-camp-hero { grid-template-columns: minmax(320px, 1.8fr) 1fr 1fr 1fr; }
.bot-camp-intro { margin: .2rem 0 0; font-size: .74rem; line-height: 1.5; color: var(--muted); max-width: 44ch; }
.bot-days.is-dense { gap: 2px; }
.bot-day-col.is-hit { background: var(--status-error); opacity: .8; }
.bot-camp-who { display: flex; flex-wrap: wrap; gap: .3rem; }
.bot-camp-who .bot-chip { color: var(--text); }
/* One group per row: its customers, campaigns meter, then victims and when */
.bot-camp-grp {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; row-gap: .35rem; column-gap: 1rem;
  padding: .6rem .3rem; border-bottom: 1px solid var(--line);
}
.bot-camp-grp > .mit-bar-n { grid-column: 1; font-size: .72rem; }
.bot-camp-empty { display: flex; flex-direction: column; gap: .4rem; font-size: .8rem; }
.bot-camp-empty p { margin: 0; }
.bot-camp-note { margin: .8rem 0 0; font-size: .7rem; color: var(--muted); }
@media (max-width: 900px) { .bot-camp-hero { grid-template-columns: 1fr; } }
.bot-dot.is-warn { background: var(--status-warn); }
.bot-dot.is-dim { background: var(--muted); }
.bot-blk-row {
  display: grid; grid-template-columns: var(--blk-cols); column-gap: 1rem; align-items: center;
  padding: .45rem .3rem; border-bottom: 1px solid var(--line); font-size: .74rem;
}
.bot-blk-row > span { min-width: 0; }
.bot-blk-head { font-size: .66rem; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); padding-top: .2rem; }
.bot-blk-host { display: flex; flex-direction: column; gap: .1rem; }
.bot-blk-host .bot-host-ip { display: flex; align-items: center; gap: .45rem; }
.bot-blk-host .bot-dot { flex: none; }
.bot-blk-host .bot-host-fam { font-size: .68rem; }
.bot-blk-rule { font-family: 'Space Mono', monospace; font-size: .68rem; color: var(--text); overflow-wrap: anywhere; }
.bot-blk-exp { display: flex; flex-direction: column; gap: .1rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.bot-blk-since { color: var(--muted); }
.bot-blk-err #bot-blk-whole-go { margin-left: .5rem; }
.bot-blk-ct { --blk-cols: minmax(0, 2fr) minmax(70px, .6fr) 5.5rem minmax(6.5rem, .9fr) 8.5rem; margin-top: .2rem; }
.bot-blk-ct .bot-blk-exp { text-align: left; }
.bot-blk-ports { display: flex; flex-wrap: wrap; gap: .25rem; }
.bot-blk-ports .mit-port { margin-left: 0; }
.bot-blk-cust { display: flex; flex-direction: column; gap: .1rem; }
.bot-blk-cust small { color: var(--muted); font-size: .66rem; }
.bot-blk-ttl.frm-select { min-height: 0; height: auto; padding: 1px 4px; font-size: .68rem; }
.bot-blk-err { color: var(--status-error); font-size: .72rem; }
.bot-blk-err:empty { display: none; }
@media (max-width: 900px) {
  .bot-blk-ct { --blk-cols: minmax(0, 1fr) minmax(0, 1fr); }
  .bot-blk-head { display: none; }
  .bot-blk-row { row-gap: .35rem; }
  .bot-blk-host, .bot-blk-rule { grid-column: 1 / -1; }
  .bot-as-grid.has-blk { column-width: 300px; }
}
/* The Block dialog: the detail modal's frame, narrower and in the page font */
.dm-dlg.bot-blk-dlg { width: min(560px, 94vw); max-height: 92vh; overflow-y: auto; font-family: inherit; }
.bot-blk-dlg .dm-title { white-space: normal; }
#bot-blk-body { display: flex; flex-direction: column; gap: .7rem; font-size: .8rem; }
#bot-blk-body p { margin: 0; }
.bot-blk-meta { display: flex; align-items: center; gap: .55rem; flex-wrap: wrap; }
.bot-blk-meta b { font-family: 'Space Mono', monospace; font-weight: 400; }
.bot-blk-meta span { color: var(--muted); font-size: .74rem; }
.bot-blk-meta .bot-blk-rule-i { margin-left: auto; font-family: 'Space Mono', monospace; font-size: .68rem; color: var(--muted); }
.bot-blk-intro { color: var(--muted); line-height: 1.5; }
.bot-blk-reach { font-weight: 600; }
.bot-blk-act { display: grid; grid-template-columns: repeat(3, 1fr); gap: .5rem; }
.bot-blk-act-4 { grid-template-columns: repeat(4, 1fr); }
.bot-blk-act-c { display: flex; flex-direction: column; gap: .15rem; padding: .5rem .65rem; border: 1px solid var(--border); border-radius: 6px; min-width: 0; }
.bot-blk-act-c span { color: var(--text-muted); font-size: .7rem; text-transform: uppercase; letter-spacing: .04em; }
.bot-blk-act-c b { font-size: 1.35rem; line-height: 1.1; font-variant-numeric: tabular-nums; }
.bot-blk-act-c:not(.is-live) b { font-size: .82rem; color: var(--muted); line-height: 1.5; }
.bot-blk-act-c small { color: var(--text-muted); font-size: .7rem; min-height: 1em; }
.bot-blk-act-c.is-live { border-color: rgba(var(--status-error-rgb), .55); }
.bot-blk-act-c.is-live b { color: var(--status-error); }
/* Listed ports or whole host: one pressed segment, the rule box follows it */
.bot-blk-mode { display: inline-flex; align-self: flex-start; border: 1px solid var(--border); border-radius: 6px; overflow: hidden; }
.bot-blk-mode button { background: none; border: 0; padding: .3rem .7rem; font: inherit; font-size: .72rem; color: var(--muted); cursor: pointer; }
.bot-blk-mode button + button { border-left: 1px solid var(--border); }
.bot-blk-mode button[aria-pressed="true"] { background: var(--surface-raised); color: var(--text); font-weight: 600; }
#bot-blk-body .bot-blk-rule.is-old { color: var(--muted); border-style: dashed; background: none; }
.bot-blk-hint { color: var(--muted); font-size: .7rem; }
.bot-blk-sum { margin-right: auto; align-self: center; font-size: .72rem; color: var(--muted); font-variant-numeric: tabular-nums; }
@media (max-width: 600px) { .bot-blk-act { grid-template-columns: 1fr; } }
.bot-blk-f { display: flex; flex-direction: column; gap: .3rem; min-width: 0; }
.bot-blk-f .frm-select { width: 100%; }
#bot-blk-body .bot-blk-rule {
  display: block; padding: .5rem .6rem; border: 1px solid var(--line); border-radius: 4px; background: var(--surface-raised);
}
.bot-blk-fields { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: .8rem; }
.bot-blk-btns { display: flex; justify-content: flex-end; gap: .6rem; padding-top: .7rem; border-top: 1px solid var(--line); }
.bot-blk-btns .fq-btn:disabled { opacity: .4; cursor: not-allowed; box-shadow: none; }
@media (max-width: 600px) {
  .bot-blk-fields { grid-template-columns: minmax(0, 1fr); }
}
/* Security -> Exposed services: the action list. One grid row per address
   to close, the volume bar last so the list still reads as a chart. */
.sig-fix-h { cursor: help; }
.sig-row {
  display: grid; grid-template-columns: minmax(150px, 1.2fr) 120px minmax(0, 2fr) 70px minmax(140px, 1fr);
  gap: .8rem; align-items: center; padding: .45rem .3rem; font-size: .76rem;
  border-bottom: 1px solid var(--line); cursor: pointer;
}
.sig-row:hover:not(.sig-hd) { background: rgba(var(--tint-rgb),.04); }
.sig-hd { cursor: default; font-size: .66rem; color: var(--muted); text-transform: uppercase; letter-spacing: .06em; }
.sig-who { display: flex; flex-direction: column; min-width: 0; }
.sig-who > * { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sig-who .mit-bar-n { font-size: .68rem; }
.sig-n { text-align: right; font-family: 'Space Mono', monospace; }
.sig-vol { display: flex; align-items: center; gap: .5rem; }
.sig-vol .bar-fill { display: block; }
.sig-empty { color: var(--status-ok); font-size: .8rem; padding: .4rem 0; }
.sig-act { display: flex; flex-direction: column; gap: .15rem; min-width: 0; }
.sig-act .mit-bar-n { font-size: .68rem; }
/* Grouped by holder: a band per holder (kind badge, name, where it hangs
   off, its services), its addresses indented under it, and one note per
   service in view at the end instead of the same sentence on every row. */
.sig-grp {
  display: grid; grid-template-columns: minmax(150px, 1.2fr) 120px minmax(0, 2fr) 70px minmax(140px, 1fr);
  gap: .15rem .8rem; align-items: center; padding: .55rem .3rem .45rem; font-size: .78rem;
  margin-top: .7rem; border-top: 1px solid var(--border); border-bottom: 1px solid var(--line);
  background: rgba(var(--tint-rgb),.05);
}
/* Row 2 of the band: address count and where the holder hangs off, full
   width and wrapping, so a three-block downstream never truncates. */
.sig-grp .sig-where { grid-column: 1 / -1; white-space: normal; }
.sig-grp .sig-tags { grid-column: 2 / 4; }
.sig-grp .sig-who > b { display: flex; align-items: center; gap: .45rem; min-width: 0; }
.sig-grp .sig-who > b > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sig-kind {
  flex: none; font-size: .66rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--read-accent); border: 1px solid currentColor; border-radius: 3px; padding: .05rem .35rem;
}
.sig-tags { display: flex; flex-wrap: wrap; gap: .2rem .55rem; font-family: 'Space Mono', monospace; font-size: .66rem; }
.sig-svc-tag { display: inline-flex; align-items: center; white-space: nowrap; }
.sig-addr .sig-who:first-child { padding-left: .7rem; }
.sig-notes { display: flex; flex-direction: column; gap: .35rem; margin-top: .9rem; font-size: .74rem; }
.sig-note { display: flex; align-items: center; gap: .7rem; }
.sig-note .sig-svc-tag { flex: none; min-width: 92px; font-family: 'Space Mono', monospace; font-size: .66rem; }
.sig-note .mit-bar-n { font-size: .68rem; }
/* The hero split bar, the chart legend and the by-service card share one
   colour per service with the rows (_sigColors). */
.sig-split { display: flex; flex: 1; max-width: 220px; height: 8px; border-radius: 4px; overflow: hidden; gap: 2px; }
.sig-split > i { display: block; height: 100%; min-width: 2px; }
.sig-tl { display: block; }
.sig-leg { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .5rem; }
.sig-chip, .sig-svc-row {
  display: flex; align-items: center; gap: .45rem; cursor: pointer;
  background: transparent; color: var(--text); font: inherit; font-size: .7rem;
}
.sig-chip { padding: .15rem .55rem; border: 1px solid var(--border); border-radius: 9px; letter-spacing: 0; text-transform: none; }
.sig-chip:hover, .sig-svc-row:hover { border-color: var(--read-accent); background: rgba(var(--tint-rgb),.04); }
.sig-chip.on, .sig-svc-row.on { border-color: var(--read-accent); color: var(--read-accent); }
.sig-chip > i, .sig-svc-row > i, .sig-dot { display: inline-block; width: 8px; height: 8px; border-radius: 2px; flex: none; }
.sig-dot { margin-right: .35rem; vertical-align: middle; }
.sig-svc { display: flex; align-items: center; gap: 1.2rem; }
.sig-donut { flex: none; }
.sig-svc-rows { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: .15rem; }
.sig-svc-row { display: grid; grid-template-columns: 8px minmax(70px, 1fr) 42px minmax(70px, auto) minmax(90px, auto); gap: .6rem; padding: .3rem .4rem; border: 1px solid transparent; border-radius: 6px; }
.sig-svc-row .sig-n { font-size: .72rem; }
.sig-svc-name { font-family: 'Space Mono', monospace; }
.sig-crossing { padding: .3rem .4rem; }
.sig-chart-card .dash-no-data { padding: .4rem 0; }
.sig-ow > summary { cursor: pointer; list-style: none; }
.sig-ow > summary::-webkit-details-marker { display: none; }
.sig-ow > summary h3 { display: inline; }
.sig-ow > summary::after { content: ' +'; color: var(--muted); }
.sig-ow[open] > summary::after { content: ' -'; }
.sig-ow[open] > summary { margin-bottom: .8rem; }
@media (max-width: 900px) {
  .sig-svc { flex-direction: column; align-items: stretch; }
  .sig-svc-row { grid-template-columns: 8px 1fr 42px; }
  .sig-svc-row > .sig-n:nth-child(n+4) { display: none; }
  .sig-row { grid-template-columns: 1fr auto; }
  .sig-hd, .sig-row > .sig-act { display: none; }
  .sig-row > .sig-n { grid-column: 2; grid-row: 1; }
  .sig-row > .sig-vol { grid-column: 1 / -1; }
}
/* Botnet -> Customers: segments and search on one bar. */
.bot-cust-bar { display: flex; align-items: stretch; gap: .8rem; flex-wrap: wrap; margin-bottom: 1rem; }
.bot-cust-bar .tm-badges { margin: 0; }
.bot-cust-bar .mit-cust-q { flex: 1 1 220px; width: auto; margin: 0; }
.bot-seg-n { font-family: 'Space Mono', monospace; opacity: .65; margin-left: .4rem; }
.mit-cust-q { width: 100%; margin-bottom: .6rem; }
.bot-see-all { float: right; }
/* The customer list (_mitRenderCustomers): one template for the head, the
   rows and the open customer's host rows, so every strip sits on the same
   hour axis. The list scrolls under its head. */
.bot-cl {
  --cl-cols: minmax(170px, .95fr) minmax(110px, .7fr) minmax(240px, 3.6fr) 4.4rem 5.6rem;
  max-height: 78vh; overflow-y: auto; margin: 0 -.4rem; padding: 0 .4rem;
}
.bot-cl-head, .bot-cl-row, .bot-cl-host {
  display: grid; grid-template-columns: var(--cl-cols); column-gap: 1rem; align-items: center;
}
.bot-cl-head {
  position: sticky; top: 0; z-index: 2; align-items: end; background: var(--bg-alt);
  padding: .3rem .3rem .4rem; border-bottom: 1px solid var(--line);
  font-size: .66rem; text-transform: uppercase; letter-spacing: .08em; color: var(--muted);
}
.bot-cl-sort {
  margin: 0; padding: 0; min-height: 0; height: auto; border: 0; background: none; color: inherit;
  font: inherit; letter-spacing: inherit; text-transform: inherit; text-align: left; cursor: pointer;
}
.bot-cl-head > .bot-cl-sort:nth-last-child(-n+2) { text-align: right; }
.bot-cl-sort:hover, .bot-cl-sort.on { color: var(--text); }
.bot-cl-sort.on::after { content: ' \2193'; }
.bot-cl-axis { display: flex; flex-direction: column; gap: .25rem; min-width: 0; cursor: help; }
.bot-hist { display: block; width: 100%; height: 46px; }
.bot-hist rect { fill: var(--status-neutral); }
.bot-hist rect.att { fill: var(--status-error); }
.bot-hist g { cursor: pointer; }
.bot-hist rect.hit { fill: transparent; }
.bot-hist g:hover rect:not(.hit), .bot-hist g.on rect:not(.hit) { fill: var(--read-accent); }
.bot-cl-cut { margin: .5rem .3rem 0; }
.bot-cl-cut .mit-fam-chip { margin-left: 0; }
.bot-cl-days { position: relative; height: .75rem; }
.bot-cl-days > span { position: absolute; transform: translateX(-50%); white-space: nowrap; }
.bot-cl .mit-bar-group { margin: .8rem .3rem .3rem; }
.bot-cl-row {
  width: 100%; padding: .34rem .3rem; margin: 0; min-height: 0; height: auto; border: 0; border-radius: 0;
  border-bottom: 1px solid var(--line); background: none; color: var(--text); font: inherit;
  text-transform: none; letter-spacing: 0; text-align: left; cursor: pointer;
}
.bot-cl-row:hover { background: var(--surface-raised); }
.bot-cl-row.att .bot-cl-who > b::before {
  content: ''; display: inline-block; width: 6px; height: 6px; margin-right: .4rem;
  border-radius: 50%; background: var(--status-error); vertical-align: middle;
}
/* Contained: every host it reaches is blocked on a router in scope */
.bot-cl-row.cont .bot-cl-who > b::after {
  content: ''; display: inline-block; width: 6px; height: 6px; margin-left: .4rem;
  border-radius: 50%; background: var(--status-ok); vertical-align: middle;
}
.bot-cl-more { margin: .4rem 0 .6rem .3rem; }
.bot-cl-row .bot-chip-cut { cursor: pointer; }
.bot-cl-row .bot-chip-cut:hover { color: var(--text); }
.bot-cl-row.on { background: var(--surface-raised); box-shadow: inset 3px 0 0 var(--read-accent); border-bottom-color: transparent; }
.bot-cl-row > .bot-who-fams { grid-row: auto; row-gap: .2rem; min-width: 0; }
.bot-cl-who { display: flex; flex-direction: column; gap: .05rem; min-width: 0; }
.bot-cl-who > b { font-weight: 500; font-size: .8rem; overflow-wrap: anywhere; }
.bot-cl-who > .mit-port { margin-left: 0; font-size: .66rem; overflow-wrap: anywhere; }
/* A row's meta (interface description, AS, device) is one line; the row's
   tooltip has it whole */
.bot-cl-row .bot-cl-who > .mit-port { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bot-cl-n, .bot-cl-ago { font-family: 'Space Mono', monospace; font-size: .74rem; text-align: right; white-space: nowrap; }
.bot-cl-ago { color: var(--muted); }
/* One cell per hour (_mitStrip); local midnights cut it in card colour. */
.bot-strip {
  display: block; width: 100%; height: 16px; border-radius: 2px;
  background: color-mix(in srgb, var(--line) 60%, transparent);
}
.bot-strip .c { fill: var(--status-error); }
.bot-strip .p { fill: var(--status-warn); }
.bot-strip-day { stroke: var(--bg-alt); stroke-width: 2px; vector-effect: non-scaling-stroke; }
.bot-hist .bot-strip-day { stroke: var(--line); stroke-width: 1px; }
/* The open customer, under its row. */
.bot-cl-detail {
  padding: .5rem .3rem .7rem; border-bottom: 1px solid var(--line);
  background: color-mix(in srgb, var(--surface-raised) 55%, transparent); box-shadow: inset 3px 0 0 var(--read-accent);
}
.bot-cl-dhead { display: flex; align-items: center; gap: .6rem 1.6rem; flex-wrap: wrap; margin-bottom: .5rem; }
.bot-cl-addrs { flex: 1 1 100%; font-size: .7rem; color: var(--muted); overflow-wrap: anywhere; }
.bot-cust-stats { display: grid; grid-template-columns: repeat(3, auto); gap: 2rem; }
.bot-cust-stats > div { display: flex; flex-direction: column; gap: .15rem; min-width: 0; }
.bot-cust-stats b { font-family: 'Space Mono', monospace; font-weight: 400; font-size: 1rem; }
.bot-cust-acts { display: flex; gap: .5rem; flex-wrap: wrap; margin-left: auto; }
.bot-cust-acts .mit-fam-chip { margin-left: 0; }
/* Quarantine: the Customers card and the control in an outbound incident's
   head. Amber while it only watches, red while its rules drop an attack. */
.mit-quar[hidden] { display: none; }
.mit-quar h3 { margin-bottom: .5rem; }
/* Stacked, not in a dash-grid: the gap the grid gives the other views */
.mit-quar { margin-bottom: 1.2rem; }
/* Empty until the first read lands */
#mit-quar-hero:empty, #mit-quar-eff:empty { display: none; }
.bot-cust-acts > .quar-chip, .bot-cust-acts > .mit-port, .bot-cust-acts > .bot-blk-err { align-self: center; }
.mit-quar-inc { align-self: center; }
.mit-quar-inc:empty { display: none; }
.quar-chip {
  display: inline-block; padding: 0 .5rem; border-radius: 8px; font-size: .66rem; line-height: 1.6; white-space: nowrap;
  font-weight: 400; border: 1px solid rgba(var(--status-warn-rgb), .6); color: var(--text); background: var(--status-warn-bg);
}
.quar-chip.is-drop { border-color: rgba(var(--status-error-rgb), .45); color: var(--status-error); background: rgba(var(--status-error-rgb), .08); }
.quar-end:hover, .quar-end:focus-visible { border-color: var(--status-error); color: var(--status-error); }
.quar-row {
  display: grid; grid-template-columns: minmax(8rem, 1.2fr) minmax(8rem, 1fr) minmax(7rem, .8fr) minmax(9rem, 1.4fr) auto;
  align-items: center; gap: .3rem .9rem; padding: .45rem 0; border-top: 1px solid var(--line); font-size: .78rem;
}
.quar-row:first-child, .quar-warn + .quar-row { border-top: 0; }
.quar-who {
  width: auto; padding: 0; margin: 0; min-height: 0; height: auto; border: 0; background: none; color: var(--text);
  font: inherit; font-weight: 600; text-transform: none; letter-spacing: 0; text-align: left; cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.quar-who:hover, .quar-who:focus-visible { color: var(--read-accent); text-decoration: underline; outline: none; }
.quar-st { display: inline-flex; align-items: center; gap: .4rem; }
.quar-st::before { content: ''; flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--status-warn); }
.quar-row.is-drop .quar-st { color: var(--status-error); }
.quar-row.is-drop .quar-st::before { background: var(--status-error); }
.quar-left { white-space: nowrap; }
.quar-acts { display: flex; gap: .4rem; justify-content: flex-end; align-items: center; }
.quar-acts .mit-fam-chip { margin-left: 0; }
.quar-rules { grid-column: 1 / -1; display: flex; flex-direction: column; gap: .2rem; padding-left: 1rem; }
.quar-rules code { font-family: 'Space Mono', monospace; font-size: .68rem; color: var(--muted); overflow-wrap: anywhere; }
.quar-rules .quar-match { color: var(--text); }
.quar-dsts { display: grid; grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr)); gap: .1rem .8rem; padding-left: 1rem; }
.quar-dsts .is-wide { color: var(--status-error); }
.quar-empty { display: flex; flex-direction: column; gap: .2rem; font-size: .8rem; }
.quar-warn { padding: .35rem .6rem; margin-bottom: .4rem; border-left: 3px solid var(--status-warn); background: var(--status-warn-bg); font-size: .76rem; }
/* Botnet -> Quarantine: the tab's count, the history rows and the
   customer detail that opens under a row (_quarDetPaint) */
.bot-view-n { margin-left: .3rem; font-family: var(--mono); font-size: .85em; color: var(--status-warn); }
.bot-view-n:empty { display: none; }
.quar-row.is-past .quar-st::before { background: var(--status-neutral); }
.quar-row.is-open > .quar-who { color: var(--read-accent); }
.quar-det { grid-column: 1 / -1; display: flex; flex-direction: column; gap: .3rem; margin: .3rem 0 .2rem 1rem;
  padding: .5rem .7rem; border-left: 2px solid var(--line); background: var(--bg-alt); border-radius: 0 6px 6px 0; }
.quar-ep { display: flex; flex-wrap: wrap; gap: .2rem .8rem; align-items: baseline; }
.quar-ep b { font-weight: 600; }
.quar-ep.is-live b { color: var(--status-warn); }
.quar-share { color: var(--muted); font-size: .76rem; line-height: 1.5; }
.quar-how { margin: 0; padding-left: 1.1rem; color: var(--muted); line-height: 1.5; }
.quar-how li + li { margin-top: .2rem; }
@media (max-width: 760px) {
  .quar-row { grid-template-columns: minmax(0, 1fr) auto; }
  .quar-left { grid-column: 2; grid-row: 1; }
  .quar-st, .quar-by, .quar-acts { grid-column: 1 / -1; }
  .quar-acts { justify-content: flex-start; }
}
.bot-cl-host {
  width: 100%; padding: .16rem 0; margin: 0; min-height: 0; height: auto; border: 0; border-radius: 3px; background: none;
  color: var(--text); font: inherit; font-size: .74rem; text-transform: none; letter-spacing: 0; text-align: left; cursor: pointer;
}
.bot-cl-host:hover { background: var(--surface-raised); }
.bot-cl-host .bot-host-ip { display: flex; align-items: center; gap: .45rem; }
.bot-cl-host .bot-dot { flex: none; }
.bot-cl-host .bot-strip { height: 9px; }
@media (max-width: 900px) {
  .bot-cl { --cl-cols: minmax(0, 1fr) 3.4rem 4.8rem; }
  .bot-cl-head > span:nth-child(2), .bot-cl-row > .bot-who-fams, .bot-cl-host > .bot-host-fam { display: none; }
  .bot-cl-head > .bot-cl-axis, .bot-cl-row > .bot-strip, .bot-cl-host > .bot-strip { grid-column: 1 / -1; grid-row: 2; margin-top: .3rem; }
}
/* Sent-attack labels carry a customer or AS name plus its detail; the shared
   200px ellipsis ate the name. Name on the first row, detail under it. The
   destinations card is half width, so its label is a share of the row: a
   viewport clamp there left the bar 20px at 1440. */
#mit-out-dests .bar-label,
#mit-out-senders .bar-label {
  width: clamp(200px, 32vw, 430px); min-width: 0; flex-shrink: 1;
  white-space: normal; overflow: visible; text-overflow: clip;
  line-height: 1.25; padding: .15rem 0;
}
#mit-out-dests .bar-label { width: 55%; }
#mit-out-dests .bar-label > span,
#mit-out-senders .bar-label > span { display: block; overflow-wrap: anywhere; }
/* "357 incidentes" wrapped in the shared 72px value column. */
#mit-out-senders .bar-val { width: 116px; white-space: nowrap; }
.mit-amp-box { display: flex; flex-direction: column; gap: .5rem; }
/* A donut legend row that carries a filter chip: no track to outline, so
   the row carries the mark itself. */
.dash-pie-legend-row.is-on { outline: 1px solid var(--brand); border-radius: 4px; font-weight: 700; }

/* ── Analytics panel ── */
.an-sub { font-size: .66rem; text-transform: none; letter-spacing: 0; color: var(--muted); font-weight: 400; margin-left: .4rem; }
.an-table { width: 100%; border-collapse: collapse; font-size: .72rem; margin-top: .2rem; }
.an-table thead th {
  color: var(--muted); text-transform: uppercase; letter-spacing: .06em;
  font-size: .66rem; padding: .3rem .5rem; border-bottom: 1px solid var(--line);
  text-align: right; font-weight: 600;
}
.an-table thead th.left { text-align: left; }
.an-table tbody td {
  padding: .28rem .5rem; border-bottom: 1px solid rgba(var(--tint-rgb),.03);
  text-align: right; font-family: 'Space Mono', monospace; font-size: .67rem;
  color: var(--muted); white-space: nowrap;
}
.an-table tbody td:first-child { text-align: left; color: var(--text); font-family: inherit; font-size: .72rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 200px; }
.an-table tbody tr:hover td { background: rgba(var(--tint-rgb),.02); }
.an-share { display: flex; align-items: center; gap: .3rem; min-width: 100px; }
.an-share .bar-track { flex: 1; }

.pcf-caret { font-size: 0.7rem; opacity: .5; }

.view-toggle { display: flex; gap: 4px; }
.view-toggle-btn {
  padding: 4px 14px; font-family: inherit; font-size: 0.78rem; font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase; cursor: pointer; border-radius: 3px;
  border: 1px solid var(--line); background: transparent; color: var(--muted);
  transition: background .15s, color .15s;
}
.view-toggle-btn.active {
  background: rgba(var(--brand-rgb),.12); color: var(--accent); border-color: var(--accent);
}

/* Device menu rows: name and IP on one line, the hostname under it only when
   it differs from the name; the selected row is marked like a sidebar item. */
.device-cards { display: flex; flex-direction: column; gap: 1px; }
.device-card {
  display: grid; grid-template-columns: minmax(0,1fr) auto; column-gap: 10px; align-items: baseline;
  width: 100%; min-height: 0; padding: 6px 8px;
  border: none; border-left: 2px solid transparent; border-radius: 0; cursor: pointer;
  background: transparent; color: var(--text); text-align: left; font-family: inherit;
  text-transform: none; letter-spacing: normal;
  transition: border-color .12s, background .12s;
}
.device-card:hover { background: rgba(var(--brand-rgb),.06); }
.device-card.is-selected { border-left-color: var(--accent); background: rgba(var(--brand-rgb),.1); }
.device-card-name { font-weight: 700; font-size: 0.8rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.device-card-ip { font-size: 0.68rem; color: var(--muted); font-family: "Space Mono", monospace; }
.device-card-hostname { grid-column: 1 / -1; font-size: 0.68rem; color: var(--muted); font-family: "Space Mono", monospace; }
/* Responsive */
@media (max-width: 700px) {
  .cmd-rw-grid      { grid-template-columns: 1fr; }
  .cmd-rw-col:first-child { border-right: none; border-bottom: 1px solid rgba(var(--brand-rgb),0.12); }
  .field-grid-ip    { grid-template-columns: 2fr 1fr; }
  .panel-header-actions { flex-wrap: wrap; align-items: flex-start; }
}

/* ── Device health bar ── */
/* One flex row: the events console takes the free width, the stats keep
   theirs. A stat with no data is display:none and the row closes up;
   pinned strips and detail panels wrap below at full width. */
.device-health-bar {
  display: flex; flex-wrap: wrap;
  align-items: stretch;
  background: rgba(var(--surface-deep-rgb),0.97);
  border-top: 1px solid rgba(var(--brand-rgb),0.06);
  border-bottom: 1px solid rgba(var(--brand-rgb),0.14);
  font-family: 'JetBrains Mono', monospace;
  color: var(--muted);
  position: sticky; top: 65px; z-index: 200;
  backdrop-filter: blur(12px);
  box-shadow: 0 2px 12px var(--shadow-mid);
  overflow: visible;
}
.device-health-bar.hidden { display: none; }
/* The bar sticks under the header (.hero-bar 64px + border), not over it:
   the header chip is the one place that names the device and its SSH state.
   Under 900px the header wraps to no fixed height, so the bar covers it. */
.hero:has(+ .device-health-bar:not(.hidden):not(.dh-no-device)) { margin-bottom: 0; }
@media (max-width: 900px) { .device-health-bar { top: 0; } }

/* The console's grow of 999 takes the free width while the stats share its
   row; once they wrap to their own row the stats group is alone and grows
   to the full width. The shadow is the divider in both layouts. */
.device-health-bar > .dh-sec-events { flex: 999 1 340px; }
/* The Events tab shows the full table; the console would repeat it. */
.device-health-bar.dh-events-open > .dh-sec-events { display: none; }
.dh-stats {
  display: flex; flex-wrap: wrap; flex: 1 1 auto; min-width: 0;
  box-shadow: -1px 0 0 rgba(var(--brand-rgb),0.14), 0 -1px 0 rgba(var(--brand-rgb),0.08);
}
.dh-stats > .dh-sec { flex: 1 0 auto; }
.dh-stats > .dh-sec + .dh-sec { border-left: 1px solid rgba(var(--brand-rgb),0.14); }
.dh-stats > .dh-sec-bgp,
.dh-stats > .dh-sec-if { width: 160px; }
.dh-stats > .dh-sec-traffic { width: 210px; }
.dh-stats > .dh-sec-cpu,
.dh-stats > .dh-sec-ram { width: 130px; }
.device-health-bar > .ddp-pinned-strip,
.device-health-bar > .ddp-panel { flex: 0 0 100%; }

/* Graphs collapse toggle — rides on the bottom border, no extra height */
.dh-graphs-toggle {
  position: absolute;
  bottom: -9px; left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; justify-content: center;
  background: rgba(var(--surface-deep-rgb),0.97);
  border: 1px solid rgba(var(--brand-rgb),0.18);
  border-radius: 10px;
  cursor: pointer;
  color: var(--text-faint);
  font-size: 0.66rem;
  width: 40px; height: 14px;
  padding: 0;
  z-index: 201;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.dh-graphs-toggle:hover {
  color: var(--brand);
  border-color: var(--text-muted);
  background: rgba(var(--brand-rgb),0.06);
}
.dh-graphs-toggle .dh-toggle-line { display: none; }
.dh-graphs-toggle .dh-toggle-chevron { transition: transform 0.2s; line-height: 1; }
.dh-graphs-toggle.collapsed .dh-toggle-chevron { transform: rotate(180deg); }

/* No pinned graphs: the toggle would have nothing to collapse, so hide it */
.dh-graphs-toggle.no-pins { display: none; }

/* Collapsed state: hide pinned strips without disrupting .hidden logic */
.ddp-pinned-strip.manually-hidden { display: none !important; }

/* Section base */
.dh-sec {
  display: flex; flex-direction: column;
  justify-content: center;
  padding: 6px 14px;
  gap: 3px;
}

.dh-sec-label {
  font-size: 0.66rem; letter-spacing: 0.12em;
  color: var(--text-muted);
  text-transform: uppercase;
  margin-bottom: 1px;
}

/* Device picker in the header, right of the logo. The hero and the health bar
   are both sticky at z-index 200 and the bar comes later, so an open menu has
   to lift the hero or it drops behind the bar. */
.hdr-device { position: relative; margin-right: auto; min-width: 0; }
.hero:has(.dh-dev-menu:not([hidden])) { z-index: 210; }
.hdr-dev-switch {
  display: flex; align-items: center; gap: 8px; max-width: min(320px, 100%); min-height: 32px; padding: 0 10px;
  background: transparent; border: 1px solid var(--line); border-radius: 4px;
  font-family: inherit; text-align: left; cursor: pointer; text-transform: none; letter-spacing: normal;
  transition: border-color .15s;
}
.hdr-dev-switch:hover, .hdr-dev-switch[aria-expanded="true"] { border-color: var(--accent); }
.hdr-dev-label { font-size: 0.66rem; letter-spacing: 0.12em; color: var(--text-muted); }
.hdr-dev-name {
  min-width: 0; font-size: 0.82rem; font-weight: 700; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hdr-dev-switch .pcf-caret { flex-shrink: 0; }
/* A button sizes to its content, not its box: without the 100% cap above it
   overflows .hdr-device and runs under the session box. Narrow headers give
   the chip room by dropping its label, the user block and logo height. */
.hdr-dev-switch { overflow: hidden; }
@media (max-width: 1150px) {
  .hdr-dev-label, .session-user { display: none; }
  .brand-logo { height: 26px; }
  .hdr-device { min-width: 160px; }
}
.dh-dev-menu {
  position: absolute; top: calc(100% + 4px); left: 0; z-index: 210;
  width: 280px; max-height: 60vh; overflow-y: auto;
  display: flex; flex-direction: column; gap: 4px; padding: 6px;
  background: var(--bg); border: 1px solid var(--line); border-radius: 4px;
  box-shadow: 0 8px 24px var(--shadow-strong);
}
.dh-dev-menu[hidden] { display: none; }
.dh-dev-search { width: 100%; min-height: 0; padding: 5px 8px; font-size: 0.78rem; }
.dh-dev-group {
  padding: 6px 2px 0; font-size: 0.66rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--text-faint);
}
/* Last row of the menu: closing the device is a menu action, not a bar icon */
.dh-dev-clear {
  width: 100%; min-height: 0; margin-top: 2px; padding: 6px 10px 2px;
  background: transparent; border: none; border-top: 1px solid var(--line); border-radius: 0;
  font-family: inherit; font-size: 0.72rem; text-align: left; text-transform: none;
  letter-spacing: normal; color: var(--muted); cursor: pointer; transition: color .15s;
}
.dh-dev-clear:hover { color: var(--text); }
.dh-dev-clear[hidden] { display: none; }
/* No device: no bar; the header picker is the way in */
.device-health-bar.dh-no-device { display: none; }
.dh-vendor-icon {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  object-fit: contain;
  border-radius: 4px;
  opacity: 0.75;
  filter: saturate(0.7) brightness(0.9);
}
/* SSH state on the header chip: color is the state, the tooltip spells it */
.dh-ssh-pill {
  display: inline-flex; align-items: center; gap: 4px; flex-shrink: 0;
  font-size: 0.66rem; font-weight: 700; letter-spacing: .06em;
  padding: 1px 5px;
  border-radius: 4px;
  border: 1px solid rgba(var(--brand-rgb),0.12);
}
.dh-ssh-pill[hidden] { display: none; }
.dh-ssh-pill::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: rgba(var(--brand-rgb),0.2);
}
/* Empty state (no device selected) */
.ws-empty-state {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; min-height: 320px; color: var(--muted); text-align: center;
}
.ws-empty-state[hidden] { display: none; }
.ws-empty-icon { font-size: 2.4rem; opacity: .5; }
.ws-empty-msg { font-size: 0.9rem; letter-spacing: .02em; }
/* No device: hide only the command panes — Flow/Alerts dashboards are device-independent */
.workspace-main.no-device > #wp-input,
.workspace-main.no-device > #wp-output { display: none !important; }
.dh-ssh-err  { color: var(--status-error); }
.dh-ssh-err::before { background: var(--status-error); }
.dh-ssh-warn { color: var(--status-warn); }

/* Count sections */
.dh-counts { display: flex; flex-direction: column; gap: 3px; }
.dh-count-row {
  font-size: 0.84rem; font-weight: 700; line-height: 1.1;
  display: flex; align-items: center; gap: 5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dh-count-row::before { content: "●"; font-size: 0.58rem; flex-shrink: 0; opacity: 0.8; }
.dh-count-row.dh-down::before { content: "●"; opacity: 0.65; }

/* Sparkline sections */
.dh-spark-row {
  display: flex; align-items: center; gap: 5px;
}
/* Replaced arrows ↑↓ with text labels RX/TX */
.dh-lbl {
  font-size: 0.66rem; font-weight: 700; letter-spacing: 0.04em;
  width: 18px; flex-shrink: 0; opacity: 0.75;
}
[data-theme="light"] .dh-lbl { opacity: 1; }
.dh-spark {
  width: 80px; height: 24px; flex: 0 1 80px; min-width: 40px;
  overflow: visible;
}
.dh-spark-val {
  font-size: 0.75rem; font-weight: 600; white-space: nowrap;
  min-width: 42px; text-align: right;
  color: var(--text);
}

/* CPU / RAM / Flow single stat */
.dh-sec-flow { align-items: flex-start; }
.dh-flow-val { font-size: .78rem; font-weight: 600; color: var(--text); font-family: 'Space Mono', monospace; }
.flow-dot {
  width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0;
  background: var(--muted, var(--status-neutral)); transition: background .3s;
}
.flow-dot.active   { background: var(--status-ok); box-shadow: 0 0 6px rgba(var(--status-ok-rgb),0.4); }
.flow-dot.inactive { background: var(--status-error); }
.dh-stat-pct {
  font-size: 0.84rem; font-weight: 700;
  min-width: 34px; text-align: right;
  color: var(--text);
}

/* Color tokens */
.dh-up   { color: var(--status-ok); }
.dh-down { color: var(--status-error); }
.dh-tx   { color: var(--proto-tcp); }
.dh-warn { color: var(--status-warn); }

/* Live dot */
.dh-dot {
  position: absolute; right: 10px; top: 10px;
  width: 5px; height: 5px; border-radius: 50%;
  background: rgba(var(--brand-rgb),0.25);
  transition: background 0.4s;
}
.dh-dot.active { background: var(--status-ok); box-shadow: 0 0 5px rgba(var(--status-ok-rgb),0.5); }

@keyframes dh-flash {
  0%   { background: rgba(var(--brand-rgb),0.2); }
  100% { background: transparent; }
}
.dh-changed {
  animation: dh-flash 1.8s ease-out forwards;
  border-radius: 3px; padding: 0 3px;
}

/* Expandable bar sections */
.dh-expandable {
  cursor: pointer; user-select: none;
  transition: background 0.15s;
  position: relative;
}
.dh-expandable::after {
  content: '';
  position: absolute; bottom: 0; left: 10px; right: 10px;
  height: 2px; border-radius: 1px;
  background: transparent;
  transition: background 0.2s;
}
.dh-expandable:hover { background: rgba(var(--brand-rgb),0.04); }
.dh-expandable:hover::after { background: rgba(var(--brand-rgb),0.25); }
.dh-expandable[aria-expanded="true"] { background: rgba(var(--brand-rgb),0.06); }
.dh-expandable[aria-expanded="true"]::after { background: rgba(var(--status-ok-rgb),0.55); }
.dh-expand-caret {
  font-size: 0.66rem; opacity: 0.55;
  transition: transform 0.2s, opacity 0.2s;
  display: inline-block;
}
.dh-expand-caret.open { transform: scaleY(-1); opacity: 0.85; }

/* ── Drop-down detail panels ──────────────────────────────────────── */
.ddp-panel {
  background: rgba(var(--surface-deep-rgb),0.98);
  border-bottom: 1px solid rgba(var(--brand-rgb),0.08);
  border-top: 1px solid rgba(var(--brand-rgb),0.06);
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.78rem;
  color: var(--muted);
  padding: 10px 18px 14px;
  grid-column: 1 / -1;
}
.ddp-panel.hidden { display: none; }

.ddp-panel-hdr {
  font-size: 0.66rem; letter-spacing: 0.1em;
  color: var(--text-faint); text-transform: uppercase;
  margin-bottom: 10px;
  display: flex; align-items: center; gap: 8px;
}
.ddp-loading   { color: var(--text-faint); }
.ddp-legend    { font-size: 0.66rem; letter-spacing: 0.06em; }

/* Time-range toggle buttons in panel header */
.ddp-time-toggle { display: flex; gap: 2px; margin-left: auto; }
.ddp-tt-btn {
  background: none; border: 1px solid rgba(var(--brand-rgb),0.18);
  color: var(--text-faint); font-family: 'JetBrains Mono', monospace;
  font-size: 0.66rem; padding: 1px 5px; border-radius: 3px; cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
}
.ddp-tt-btn:hover { color: var(--text-muted); border-color: var(--text-faint); }
.ddp-tt-btn.active { color: var(--status-ok); border-color: rgba(var(--status-ok-rgb),0.5); }
.ddp-tt-btn.disabled { opacity: 0.3; cursor: default; }
.ddp-tt-long { color: rgba(var(--proto-tcp-rgb),0.3); border-color: rgba(var(--proto-tcp-rgb),0.15); }
.ddp-tt-long:hover { color: rgba(var(--proto-tcp-rgb),0.65); border-color: rgba(var(--proto-tcp-rgb),0.4); }
.ddp-tt-long.active { color: var(--proto-tcp); border-color: rgba(var(--proto-tcp-rgb),0.5); }
.ddp-tt-sep { width: 1px; background: rgba(var(--brand-rgb),0.15); margin: 1px 3px; align-self: stretch; }
.ddp-detail-loading { padding: 20px 8px; font-size: 0.66rem; color: var(--text-faint); text-align: center; }

/* Event console section */
/* ── Events panel ── */
.dh-sec-events { min-width: 0; }
.dh-sec-events-hdr { display: flex; align-items: center; gap: 8px; }
.dh-sec-events-hdr .dh-sec-label { flex-shrink: 0; }
.dh-ev-ftabs { display: flex; gap: 6px; align-items: center; }
.dh-ev-ftab {
  font-size: 0.66rem; font-family: 'Space Mono', monospace; letter-spacing: .05em;
  color: var(--text-faint); cursor: pointer; user-select: none;
  transition: color .15s;
}
.dh-ev-ftab:hover { color: var(--text-muted); }
.dh-ev-ftab.active { color: var(--brand); border-bottom: 1px solid rgba(var(--brand-rgb),0.6); }
.dh-ev-alerts-link {
  margin-left: auto; background: none; border: none;
  color: var(--text-faint); font-size: 0.66rem; font-family: inherit;
  cursor: pointer; padding: 0; letter-spacing: .04em;
  transition: color 0.15s;
}
.dh-ev-alerts-link:hover { color: var(--brand); }
.dh-console {
  display: flex; flex-direction: column; gap: 0;
  height: 51px; overflow: hidden;
  font-size: 0.66rem; font-family: 'JetBrains Mono', monospace;
}
.dh-console.is-empty { height: auto; overflow: hidden; }
.dh-console-empty { color: var(--text-faint); font-size: 0.66rem; font-style: italic; padding: 2px 0; }
/* Zabbix-style compact row: time | status | type | description */
.dh-ev {
  display: grid; grid-template-columns: 74px 36px 26px 1fr;
  gap: 6px; align-items: center; height: 17px;
  border-bottom: 1px solid rgba(var(--brand-rgb),0.04);
  white-space: nowrap; overflow: hidden;
}
.dh-ev:last-child { border-bottom: none; }
.dh-ev-time  { font-size: 0.66rem; color: var(--text-faint); white-space: nowrap; }
.dh-ev-badge { font-size: 0.66rem; font-weight: 700; letter-spacing: .03em; text-align: center;
               border-radius: 2px; padding: 1px 2px; }
.dh-ev-badge.ok   { color: var(--text-inverse); background: var(--status-ok); }
.dh-ev-badge.prob { color: var(--text-inverse); background: var(--status-error); }
.dh-ev-badge.warn { color: var(--text-inverse); background: var(--status-warn); }
.dh-ev-badge.info { color: var(--text-inverse); background: rgba(var(--brand-rgb),0.6); }
.dh-ev-type  { font-size: 0.66rem; color: var(--text-faint); text-align: center; }
.dh-ev-desc  { overflow: hidden; text-overflow: ellipsis; cursor: default; }
/* level colors */
.dh-ev[data-level="up"]   .dh-ev-icon, .dh-ev[data-level="up"]   .dh-ev-title { color: var(--status-ok); }
.dh-ev[data-level="down"] .dh-ev-icon, .dh-ev[data-level="down"] .dh-ev-title { color: var(--status-error); }
.dh-ev[data-level="warn"] .dh-ev-icon, .dh-ev[data-level="warn"] .dh-ev-title { color: var(--status-warn); }
.dh-ev[data-level="info"] .dh-ev-icon, .dh-ev[data-level="info"] .dh-ev-title { color: var(--text-muted); }
.dh-ev[data-level="error"] .dh-ev-icon, .dh-ev[data-level="error"] .dh-ev-title { color: var(--status-error); }

/* Interface rows */
/* The panel sits inside the sticky health bar: cap it so bar + panel never
   cover most of the viewport */
.ddp-iface-scroll { max-height: min(340px, 42vh); overflow-y: auto; }
.ddp-iface-list   { display: flex; flex-direction: column; gap: 1px; }
.ddp-empty        { color: var(--text-faint); font-size: 0.72rem; }

/* One line per interface: dot, name, spark, RX, TX, pin. The spark and rate
   columns are fixed so they line up down the list and with the BGP groups */
.ddp-iface-row {
  display: grid;
  grid-template-columns: 8px minmax(0,1fr) 160px 84px 84px 18px;
  align-items: center; gap: 10px;
  padding: 3px 6px; border-radius: 3px;
  transition: background 0.15s;
}
.ddp-iface-row:hover     { background: rgba(var(--brand-rgb),0.04); }
.ddp-iface-row.is-pinned { background: rgba(var(--status-ok-rgb),0.04); }
.ddp-iface-row.is-down   { background: rgba(var(--status-error-rgb),0.06); }
.ddp-iface-row .ddp-mini-graph,
.ddp-bgp-group-hdr .ddp-mini-graph { width: 160px; }
.ddp-rate {
  font-family: 'Space Mono', monospace; font-size: 0.72rem;
  text-align: right; white-space: nowrap;
}
@media (max-width: 760px) {
  .ddp-iface-row    { grid-template-columns: 8px minmax(0,1fr) 72px 72px 18px; }
  .ddp-bgp-group-hdr { grid-template-columns: 14px minmax(0,1fr) auto 72px 72px 18px; }
  .ddp-iface-row .ddp-mini-graph,
  .ddp-bgp-group-hdr .ddp-mini-graph { display: none; }
  .ddp-bgp-sub-row  { grid-template-columns: 14px minmax(0,1fr) 88px 64px; padding-right: 6px; }
  .ddp-bgp-routes   { display: none; }
}

.ddp-if-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: currentColor; justify-self: center;
}
.ddp-if-info  { min-width: 0; display: flex; align-items: baseline; gap: 8px; }
.ddp-if-name  {
  font-size: 0.76rem; font-weight: 600; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  display: block; min-width: 0;
}
.ddp-if-sep    { color: var(--text-faint); font-weight: 400; }
.ddp-if-status { font-size: 0.66rem; white-space: nowrap; text-transform: uppercase; letter-spacing: 0.06em; flex-shrink: 0; }

.ddp-mini-graph { display: block; overflow: visible; }

.ddp-pin-btn {
  background: none; border: none; cursor: pointer;
  font-size: 0.72rem; padding: 2px;
  color: var(--text-faint);
  transition: color 0.2s; line-height: 1;
}
.ddp-pin-btn:hover     { color: var(--text-muted); }
.ddp-pin-btn.is-pinned { color: var(--status-ok); }
/* The global button min-height would make every row 36px tall */
.ddp-pin-btn, .ddp-bgp-pin-btn { min-height: 0; height: 18px; }
.ddp-tt-btn, .ddp-dt-btn, .ddp-sankey-toggle, .ddp-detail-close { min-height: 22px; }

/* BGP rows */
.ddp-bgp-scroll { max-height: min(340px, 42vh); overflow-y: auto; }
.ddp-bgp-list   { display: flex; flex-direction: column; gap: 3px; }

/* AS group container */
.ddp-bgp-group { display: flex; flex-direction: column; border-radius: 4px; overflow: hidden; }
.ddp-bgp-group.is-pinned > .ddp-bgp-group-hdr { background: rgba(var(--brand-rgb),0.08); }
.ddp-bgp-group.has-down > .ddp-bgp-group-hdr { background: rgba(var(--status-error-rgb),0.08); }

/* Group header: AS number + name on one line, sessions up, flow spark, RX, TX, pin.
   Same spark and rate columns as .ddp-iface-row */
.ddp-bgp-group-hdr {
  display: grid;
  grid-template-columns: 14px minmax(0,1fr) auto 160px 84px 84px 18px;
  align-items: center; gap: 10px;
  padding: 4px 6px 4px 10px;
  background: rgba(var(--brand-rgb),0.07);
  border-bottom: 1px solid rgba(var(--brand-rgb),0.1);
}
.ddp-bgp-group-as { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.ddp-bgp-group-as-num  { font-size: 0.75rem; color: var(--text-muted); font-weight: 600; white-space: nowrap; }
.ddp-bgp-group-as-name { font-size: 0.68rem; color: var(--text-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ddp-bgp-count { font-size: 0.66rem; color: var(--text-faint); white-space: nowrap; }

/* Pin button (BGP group) */
.ddp-bgp-pin-btn {
  background: none; border: none; cursor: pointer;
  font-size: 0.9rem; line-height: 1; padding: 2px 3px;
  color: var(--text-faint); transition: color 0.15s;
  flex-shrink: 0;
}
.ddp-bgp-pin-btn:hover, .ddp-bgp-pin-btn.is-pinned { color: var(--brand); }

/* Per-peer sub-row inside a group */
/* Peer row: dot, IP + description, state, uptime, prefixes */
.ddp-bgp-sub-row {
  display: grid;
  grid-template-columns: 14px minmax(0,1fr) 96px 72px 110px;
  align-items: center; gap: 10px;
  padding: 2px 34px 2px 28px;
  background: rgba(var(--brand-rgb),0.02);
  border-left: 2px solid rgba(var(--brand-rgb),0.08);
  cursor: pointer;
  transition: background 0.15s;
  min-width: 0;
}
.ddp-bgp-sub-row:hover { background: rgba(var(--brand-rgb),0.05); }
.ddp-bgp-sub-row.is-expanded { background: rgba(var(--brand-rgb),0.06); }
.ddp-bgp-sub-row.is-down { background: rgba(var(--status-error-rgb),0.06); border-left-color: var(--status-error); }
.ddp-bgp-sub-row.is-down .ddp-bgp-state { font-weight: 700; }
.ddp-bgp-peer-cell { display: flex; align-items: baseline; gap: 10px; min-width: 0; }

/* Expanded detail chart area (below a sub-row) */
.ddp-bgp-detail {
  padding: 6px 8px 8px 24px;
  background: rgba(var(--brand-rgb),0.02);
  border-top: 1px solid rgba(var(--brand-rgb),0.06);
}
.ddp-bgp-detail.hidden { display: none; }

.ddp-bgp-dot-wrap {
  position: relative; width: 18px; height: 18px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.ddp-change-ring {
  position: absolute; inset: -3px; border-radius: 50%;
  border: 1.5px solid var(--status-warn);
  animation: ddp-ring-pulse 2s ease-in-out infinite;
}
@keyframes ddp-ring-pulse {
  0%, 100% { opacity: 0.9; transform: scale(1); }
  50%       { opacity: 0.2; transform: scale(1.5); }
}

.ddp-bgp-peer    { font-size: 0.75rem; color: var(--text); font-family: 'Space Mono', monospace; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.ddp-bgp-desc    { font-size: 0.70rem; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.ddp-bgp-state   { font-size: 0.70rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.ddp-bgp-updown  { font-size: 0.68rem; color: var(--text-muted); white-space: nowrap; text-align: right; min-width: 0; }
.ddp-bgp-routes  { font-size: 0.70rem; white-space: nowrap; text-align: right; font-family: 'Space Mono', monospace; }


/* Expanded interface detail chart */
.ddp-iface-detail {
  padding: 6px 6px 8px 24px;
  background: rgba(var(--brand-rgb),0.02);
  border-radius: 0 0 4px 4px;
  border-top: 1px solid rgba(var(--brand-rgb),0.06);
}
.ddp-iface-detail.hidden { display: none; }
.ddp-iface-row.is-expanded { background: rgba(var(--brand-rgb),0.05); border-radius: 4px 4px 0 0; }
.ddp-iface-row { cursor: pointer; }
.ddp-big-graph { display: block; overflow: visible; max-width: 100%; height: auto; }

.ddp-detail-controls {
  display: flex; align-items: center; gap: 4px;
  padding: 6px 8px 4px;
  border-bottom: 1px solid rgba(var(--brand-rgb),0.06);
}
.ddp-dt-btn {
  background: none; border: 1px solid rgba(var(--brand-rgb),0.18); border-radius: 3px;
  color: var(--text-faint); font-size: 0.66rem; font-family: inherit;
  padding: 2px 7px; cursor: pointer; transition: color 0.15s, border-color 0.15s;
  line-height: 1.4;
}
.ddp-dt-btn:hover  { color: var(--text-muted); border-color: var(--text-faint); }
.ddp-dt-btn.active { color: var(--brand); border-color: var(--text-muted); font-weight: 600; }
.ddp-detail-chart { overflow: hidden; transition: opacity 0.18s ease; }
.ddp-bgp-detail .ddp-detail-controls { justify-content: flex-end; }
.ddp-sankey-toggle {
  background: none; border: 1px solid rgba(var(--brand-rgb),0.18); border-radius: 3px;
  color: var(--text-faint); font-size: 0.66rem; font-family: inherit;
  padding: 2px 7px; cursor: pointer; transition: color 0.15s, border-color 0.15s;
  line-height: 1.4; margin-left: auto;
}
.ddp-sankey-toggle:hover  { color: var(--text-muted); border-color: var(--text-faint); }
.ddp-sankey-toggle.active { color: var(--brand); border-color: var(--text-muted); font-weight: 600; }
.ddp-sankey-box { padding: 6px 8px; border-top: 1px solid rgba(var(--brand-rgb),0.06); }
.ddp-sankey-box.hidden { display: none; }
.ddp-sankey-controls { display: flex; gap: 4px; margin-bottom: 4px; }
.ddp-sk-role-btn {
  background: none; border: 1px solid rgba(var(--brand-rgb),0.18); border-radius: 3px;
  color: var(--text-faint); font-size: 0.66rem; font-family: inherit;
  padding: 2px 7px; cursor: pointer; transition: color 0.15s, border-color 0.15s;
}
.ddp-sk-role-btn:hover  { color: var(--text-muted); border-color: var(--text-faint); }
.ddp-sk-role-btn.active { color: var(--brand); border-color: var(--text-muted); font-weight: 600; }
.ddp-sankey-chart svg { display: block; }
.ddp-sankey-sampled { color: var(--text-faint); font-size: 0.66rem; margin-top: 2px; }

@keyframes ddp-now-ping {
  0%   { r: 3;  opacity: 0.7; }
  100% { r: 11; opacity: 0;   }
}
.ddp-now-ping { animation: ddp-now-ping 2.4s ease-out infinite; }
@media (prefers-reduced-motion: reduce) {
  .ddp-change-ring { animation: none; }
  .ddp-now-ping { display: none; }
}
.ddp-detail-nodata {
  padding: 20px 8px;
  font-size: 0.7rem; color: var(--text-faint);
  text-align: center; line-height: 1.8;
}
.ddp-detail-nodata span { font-size: 0.66rem; }

/* Persistent pinned interfaces strip */
.ddp-pinned-strip {
  display: flex; flex-wrap: wrap; gap: 0; align-items: stretch;
  border-top: 1px solid rgba(var(--brand-rgb),0.16);
  background: rgba(var(--surface-deep-rgb),0.5);
  padding: 0;
  font-family: 'JetBrains Mono', monospace;
  grid-column: 1 / -1;
}
.ddp-pinned-strip.hidden { display: none; }
.ddp-pinned-item {
  display: flex; flex-direction: column; gap: 4px;
  flex: 0 0 220px;
  overflow: hidden;
  padding: 8px 14px 8px 12px;
  border-right: 1px solid rgba(var(--brand-rgb),0.1);
  border-left: 3px solid rgba(var(--brand-rgb),0.25);
  cursor: pointer;
  transition: background 0.15s, border-left-color 0.15s;
  margin: 0;
}
.ddp-pinned-item:hover {
  background: rgba(var(--brand-rgb),0.05);
  border-left-color: var(--text-muted);
}
.ddp-pinned-item:hover .ddp-pinned-name,
.ddp-pinned-item:hover .ddp-bgp-group-as-num { color: var(--brand); }
.ddp-pinned-item:last-child { border-right: none; }
.ddp-pinned-name {
  font-size: 0.68rem; color: var(--text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  font-weight: 600; letter-spacing: 0.02em;
}
/* BGP pinned strip: AS number + org name stacked vertically */
.ddp-pinned-bgp-name {
  display: flex; flex-direction: column; gap: 1px;
  min-width: 0;  /* required for text-overflow ellipsis inside flex */
}
.ddp-pinned-bgp-name .ddp-bgp-group-as-num  { font-size: 0.7rem; }
.ddp-pinned-bgp-name .ddp-bgp-group-as-name { font-size: 0.66rem; min-width: 0; }
/* ddp-pinned-graph-row only used for legacy BGP flow mini-graph layout */
.ddp-pinned-graph-row {
  display: flex; align-items: center; gap: 12px;
}
.ddp-pinned-graph-row .ddp-mini-graph { flex: 1 1 0; min-width: 0; width: 0; }
/* Mini-graph inside pinned item (direct child, no wrapper) */
.ddp-pinned-item > .ddp-mini-graph { width: 100%; display: block; margin: 2px 0; }
/* Replaced .ddp-pinned-rates with .ddp-pinned-stats (last/avg/max) */
.ddp-pinned-stats {
  display: flex; flex-direction: column; gap: 2px;
  margin-top: 3px;
}
.ddp-stat-row {
  display: flex; align-items: baseline; gap: 4px;
  font-size: 0.66rem; line-height: 1.25; white-space: nowrap;
}
.ddp-stat-row[hidden] { display: none; }
.ddp-stat-lbl {
  font-size: 0.66rem; font-weight: 700; letter-spacing: 0.05em;
  width: 16px; flex-shrink: 0; opacity: 0.75;
}
.ddp-stat-val {
  font-weight: 700; min-width: 36px;
}
.ddp-stat-meta {
  color: var(--text-faint); font-size: 0.66rem;
}

/* Tooltip stat sub-row (avg/max below the value) */
.ctt-stat-row {
  font-size: 0.66rem; color: var(--text-faint);
  padding: 0 8px 4px 20px; letter-spacing: 0.02em;
}

/* ── Data Explorer ── */
.exp-topbar {
  display: flex; flex-direction: column; gap: .5rem;
  padding: .75rem 1rem; background: var(--surface-sunken);
  border-bottom: 1px solid var(--line);
}
.exp-pills {
  display: flex; gap: .4rem; flex-wrap: wrap;
}
.exp-pill {
  padding: .3rem .9rem; background: transparent;
  border: 1px solid var(--line); border-radius: 20px;
  color: var(--muted); font-family: "Rajdhani", sans-serif;
  font-size: .78rem; font-weight: 600; letter-spacing: .05em;
  cursor: pointer; transition: border-color .15s, color .15s, background .15s;
}
.exp-pill:hover { border-color: var(--accent); color: var(--accent); }
.exp-pill-active {
  border-color: var(--accent); color: var(--accent);
  background: rgba(var(--brand-rgb),.08);
}
.exp-filter-row { display: flex; align-items: center; gap: .5rem; min-height: 30px; }
.exp-filter-group { display: flex; align-items: center; gap: .4rem; }
.exp-input {
  padding: .28rem .6rem; background: var(--surface-sunken);
  border: 1px solid var(--line); border-radius: 3px;
  color: var(--text); font-family: "Space Mono", monospace;
  font-size: .74rem; width: 200px; outline: none;
}
.exp-input:focus { border-color: var(--accent); }
.exp-select {
  padding: .28rem .6rem; background: var(--surface-sunken);
  border: 1px solid var(--line); border-radius: 3px;
  color: var(--text); font-family: "Space Mono", monospace;
  font-size: .74rem; outline: none; cursor: pointer;
}
.exp-select:focus { border-color: var(--accent); }
.exp-apply-btn {
  padding: .28rem .8rem; background: rgba(var(--brand-rgb),.1);
  border: 1px solid var(--accent); border-radius: 3px;
  color: var(--accent); font-family: "Rajdhani", sans-serif;
  font-size: .76rem; font-weight: 700; letter-spacing: .06em;
  cursor: pointer; transition: background .15s;
}
.exp-apply-btn:hover { background: rgba(var(--brand-rgb),.2); }
.exp-clear-val {
  padding: .18rem .5rem; background: transparent;
  border: 1px solid rgba(var(--tint-rgb),.12); border-radius: 3px;
  color: var(--muted); font-size: .8rem; cursor: pointer;
  line-height: 1; transition: color .15s, border-color .15s;
}
.exp-clear-val:hover { color: var(--error); border-color: var(--error); }

/* Protocol pill buttons (replaces native select) */
.exp-proto-pills {
  display: flex; gap: .25rem; flex-wrap: wrap;
}
.exp-proto-pill {
  padding: .22rem .65rem; background: transparent;
  border: 1px solid var(--line); border-radius: 3px;
  color: var(--muted); font-family: "Space Mono", monospace;
  font-size: .72rem; cursor: pointer;
  transition: border-color .15s, color .15s, background .15s;
}
.exp-proto-pill:hover { border-color: var(--accent); color: var(--accent); }
.exp-proto-active {
  border-color: var(--accent); color: var(--accent);
  background: rgba(var(--brand-rgb),.1);
}

/* Active filter tag */
.exp-active-tag {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .2rem .6rem; margin: .3rem 1rem;
  background: rgba(var(--brand-rgb),.08); border: 1px solid rgba(var(--brand-rgb),.3);
  border-radius: 20px; font-size: .75rem; color: var(--accent);
  font-family: "Space Mono", monospace;
}
.exp-tag-x {
  background: transparent; border: none; color: var(--muted);
  font-size: .85rem; cursor: pointer; padding: 0 .1rem;
  line-height: 1; transition: color .15s;
}
.exp-tag-x:hover { color: var(--error); }

/* 2×2 grid */
.exp-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: auto auto;
  gap: 12px;
  padding: 12px;
}
.exp-card-a { grid-column: 1; grid-row: 1; }
.exp-card-b { grid-column: 2; grid-row: 1; }
.exp-card-c { grid-column: 1; grid-row: 2; }
.exp-card-d { grid-column: 2; grid-row: 2; }

.exp-card-title {
  margin: 0 0 .7rem; font-size: .84rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .08em; color: var(--muted);
}

/* Explorer tables */
.exp-table {
  width: 100%; border-collapse: collapse; font-size: .82rem;
}
.exp-table thead th {
  color: var(--muted); text-transform: uppercase; letter-spacing: .05em;
  font-size: .70rem; padding: .38rem .55rem; border-bottom: 1px solid var(--line);
  text-align: right; font-weight: 600; white-space: nowrap;
}
.exp-table thead th.exp-th-left { text-align: left; }
.exp-table thead th.exp-sortable { cursor: pointer; user-select: none; }
.exp-table thead th.exp-sortable:hover { color: var(--accent); }
.exp-arrow { opacity: .3; font-size: .70rem; }
.exp-arrow.exp-arrow-on { opacity: 1; color: var(--accent); }
.exp-table tbody td {
  padding: .38rem .55rem; border-bottom: 1px solid rgba(var(--tint-rgb),.035);
  text-align: right; font-family: 'Space Mono', monospace; font-size: .78rem;
  color: var(--muted); white-space: nowrap;
}
.exp-td-left { text-align: left !important; color: var(--text) !important;
  font-family: inherit !important; font-size: .84rem !important;
  overflow: hidden; text-overflow: ellipsis; max-width: 220px; }
.exp-table tbody tr:hover td { background: rgba(var(--tint-rgb),.025); }
.exp-td-share { min-width: 80px; }
.exp-td-rank { width: 30px; font-size: .70rem; }
.exp-td-bar { width: 150px; padding-right: .2rem; }
.exp-td-pct { width: 52px; color: var(--text); }
.exp-td-big { color: var(--text); font-weight: 700; }
.exp-share-bar { display: block; height: 4px; background: rgba(var(--tint-rgb),.08); border-radius: 2px; }
.exp-share-fill { height: 100%; border-radius: 2px; background: var(--accent); transition: width .3s; }

.exp-dir-badge {
  display: inline-block; margin-left: .4rem; padding: .05rem .35rem;
  background: rgba(var(--brand-rgb),.08); border: 1px solid rgba(var(--brand-rgb),.2);
  border-radius: 3px; font-size: .66rem; color: var(--muted); font-weight: 400;
  letter-spacing: .04em; vertical-align: middle;
}
.exp-pfx-link {
  color: var(--read-accent); cursor: pointer; text-decoration: underline;
  text-decoration-style: dotted; font-family: 'Space Mono', monospace;
}
.exp-pfx-link:hover { color: var(--accent); }
.exp-pfx-row { cursor: pointer; }
.exp-pfx-row:hover td { background: rgba(var(--brand-rgb),.04) !important; }
/* Pie container inside card C (prefix mode) */
#exp-pfx-pie-wrap .dash-pie-wrap {
  padding-top: .4rem; flex-wrap: wrap;
}
.exp-no-data {
  color: var(--muted); font-size: .82rem; text-align: center;
  padding: 1.5rem; opacity: .6;
}

/* ── Prefix multi-section dashboard (exp-pfx-dashboard) ────────────────────── */
/* No own scroll: an inner overflow here puts a second scrollbar next to the
   page one, and the wheel only moves whichever the pointer sits over. */
#exp-pfx-dashboard {
  padding-bottom: 12px;
}
.ep-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  padding: 12px 12px 0;
}
.ep-row-full {
  grid-template-columns: 1fr;
}
.ep-row:last-child {
  padding-bottom: 12px;
}
/* Horizontal bar chart */
.ep-hbar-wrap { padding: .3rem 0; }
.ep-hbar-row {
  display: flex;
  align-items: center;
  gap: .55rem;
  padding: .28rem 0;
  border-bottom: 1px solid rgba(var(--tint-rgb),.035);
}
.ep-hbar-label {
  font-size: .77rem;
  color: var(--text);
  min-width: 140px;
  max-width: 140px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: left;
}
.ep-hbar-track {
  flex: 1;
  height: 12px;
  background: rgba(var(--tint-rgb),.06);
  border-radius: 2px;
}
.ep-hbar-fill {
  height: 100%;
  background: var(--accent);
  border-radius: 2px;
  transition: width .3s;
}
.ep-hbar-val {
  font-size: .74rem;
  color: var(--muted);
  font-family: 'Space Mono', monospace;
  min-width: 78px;
  text-align: right;
}

/* Clickable link cells in prefix dashboard tables */
.ep-link {
  color: var(--read-accent);
  cursor: pointer;
  text-decoration: none;
}
.ep-link:hover { color: var(--accent); text-decoration: underline; text-decoration-thickness: 1px; }
.ep-link.ep-ip { color: var(--read-accent); }   /* monospace IP keeps the link colour */
/* IP address cell */
.ep-ip {
  font-family: 'Space Mono', monospace;
  font-size: .77rem;
  color: var(--text);
}
/* Clickable row highlight */
.ep-clickable-row { cursor: pointer; }
.ep-clickable-row:hover td { background: rgba(var(--brand-rgb),.05) !important; }
/* Sortable header in ep tables */
.ep-sortable { cursor: pointer; user-select: none; }
.ep-sortable:hover { color: var(--accent); }


/* ── Detail chart modal ── */
.dm {
  position: fixed; inset: 0; z-index: 600;
  display: flex; align-items: center; justify-content: center;
}
.dm.hidden { display: none; }
.dm-bd {
  position: absolute; inset: 0;
  background: var(--surface-overlay);
  backdrop-filter: blur(4px);
}
.dm-dlg {
  position: relative; z-index: 1;
  width: min(1320px, 94vw);
  background: rgba(var(--surface-deep-rgb),0.98);
  border: 1px solid rgba(var(--brand-rgb),0.18);
  border-radius: 6px;
  padding: 14px 18px 18px;
  box-shadow: 0 12px 48px var(--shadow-strong);
  font-family: 'JetBrains Mono', monospace;
}
.dm-hdr {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: 10px;
  border-bottom: 1px solid rgba(var(--brand-rgb),0.08);
  padding-bottom: 10px;
}
.dm-title {
  font-size: 0.82rem; font-weight: 600; color: var(--brand);
  flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dm-tabs { display: flex; gap: 3px; }
.dm-close {
  background: none; border: 1px solid rgba(var(--brand-rgb),0.2); border-radius: 4px;
  color: var(--text-faint); font-size: 1rem; width: 26px; height: 26px;
  cursor: pointer; display: flex; align-items: center; justify-content: center;
  transition: color 0.15s, border-color 0.15s; flex-shrink: 0;
}
.dm-close:hover { color: var(--brand); border-color: var(--text-muted); }
.dm-body { min-height: 320px; }
.dm .ddp-detail-close { display: none; }

/* Inline detail close button */
.ddp-detail-close {
  margin-left: auto;
  background: none; border: 1px solid rgba(var(--brand-rgb),0.18); border-radius: 3px;
  color: var(--text-faint); font-size: 0.66rem; font-family: inherit;
  padding: 2px 7px; cursor: pointer; line-height: 1.4;
  transition: color 0.15s, border-color 0.15s;
}
.ddp-detail-close:hover { color: var(--brand); border-color: var(--text-muted); }

/* ── Alerts tab ──────────────────────────────────────── */
.alerts-toolbar { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; margin-bottom: .75rem; }
.alerts-filters { display: flex; gap: 2px; }
.alerts-filter {
  background: none; border: 1px solid transparent; border-radius: 3px;
  color: var(--text-faint); font-family: 'Space Mono', monospace;
  font-size: .66rem; padding: 2px 7px; cursor: pointer; transition: color .15s, border-color .15s;
}
.alerts-filter:hover { color: var(--text-muted); border-color: var(--text-faint); }
.alerts-filter.active { color: var(--brand); border-color: var(--text-faint); }
.alerts-range { margin-left: auto; }
.alerts-table { width: 100%; border-collapse: collapse; font-size: .7rem; font-family: 'JetBrains Mono', monospace; }
.alerts-table th {
  text-align: left; font-size: .66rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-faint); border-bottom: 1px solid rgba(var(--brand-rgb),.1);
  padding: 4px 8px; white-space: nowrap;
}
.alerts-table td { padding: 4px 8px; border-bottom: 1px solid rgba(var(--brand-rgb),.04); vertical-align: top; }
.alerts-table tr:last-child td { border-bottom: none; }
.alerts-table tr:hover td { background: rgba(var(--brand-rgb),.03); }
.alerts-td-time   { white-space: nowrap; color: var(--text-muted); }
.alerts-td-recov  { white-space: nowrap; color: var(--status-ok); }
.alerts-td-dur    { white-space: nowrap; color: var(--text-faint); }
.alerts-td-status .dh-ev-badge { display: inline-block; }
.alerts-td-type   { color: var(--text-faint); }
.alerts-td-event  { color: var(--brand); max-width: 340px; }
.alerts-td-detail { color: var(--text-faint); max-width: 280px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.alerts-empty { text-align: center; color: var(--text-faint); padding: 2rem 0 !important; font-style: italic; }
.alerts-note { margin: .5rem 0 0; font-size: .7rem; color: var(--status-warn); }

/* ── CDN Provider Detail tab ─────────────────────────────── */
.cdnp-selector { display: flex; flex-wrap: wrap; gap: .4rem; margin-bottom: .75rem; }
.cdnp-pill {
  display: flex; align-items: center; gap: .35rem;
  background: rgba(var(--tint-rgb),.04); border: 1px solid rgba(var(--tint-rgb),.1);
  border-radius: 20px; padding: 4px 12px 4px 8px;
  cursor: pointer; font-size: .7rem; color: var(--text-muted);
  transition: color .15s, border-color .15s, background-color .15s;
}
.cdnp-pill:hover { border-color: var(--text-faint); color: var(--brand); }
.cdnp-pill.active { border-color: var(--pill-color, var(--brand)); color: var(--text-primary); background: rgba(var(--brand-rgb),.08); }
.cdnp-pill-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--pill-color, var(--brand)); }
.cdnp-kpis { display: flex; gap: 2rem; flex-wrap: wrap; margin-bottom: .75rem; padding: .6rem 1rem; background: var(--bg-alt); border-radius: 6px; border: 1px solid var(--line); }
.cdnp-kpi { display: flex; flex-direction: column; gap: .15rem; }
.cdnp-kpi-label { font-size: .66rem; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); }
.cdnp-kpi-val { font-size: 1rem; font-weight: 700; font-family: 'Space Mono', monospace; color: var(--text); }
.cdnp-charts { display: grid; grid-template-columns: 1fr 280px; gap: 1rem; margin-bottom: 1rem; }
.cdnp-chart-main { display: flex; flex-direction: column; gap: .4rem; background: var(--bg-alt); border: 1px solid var(--line); border-radius: 6px; padding: .75rem 1rem; }
.cdnp-chart-side { background: var(--bg-alt); border: 1px solid var(--line); border-radius: 6px; padding: .75rem 1rem; display: flex; flex-direction: column; gap: .5rem; }
.cdnp-chart-title { font-size: .66rem; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); }
.cdnp-chart-legend { display: flex; gap: 1.2rem; font-size: .66rem; color: var(--muted); }
.cdnp-legend-item { display: flex; align-items: center; gap: .3rem; }
.cdnp-legend-dot { width: 10px; height: 3px; border-radius: 2px; display: inline-block; }
.cdnp-empty { color: var(--muted); font-size: .75rem; padding: 2rem 0; text-align: center; font-style: italic; }
.cdnp-section { background: var(--bg-alt); border: 1px solid var(--line); border-radius: 6px; padding: .75rem 1rem; display: flex; flex-direction: column; gap: .4rem; margin-bottom: .75rem; }
.cdnp-section-title { font-size: .80rem; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); margin-bottom: .25rem; }
.cdnp-kpi-table { font-size: .7rem; font-family: 'Space Mono',monospace; border-top: 1px solid var(--line); margin-top: .3rem; padding-top: .4rem; }
.cdnp-kpi-hdr, .cdnp-kpi-row { display: grid; grid-template-columns: 100px 1fr 1fr 1fr 1fr; gap: .4rem; padding: 2px 0; }
.cdnp-kpi-hdr { color: var(--muted); font-size: .66rem; text-transform: uppercase; letter-spacing: .05em; }
.cdnp-kpi-label-in  { color: var(--status-ok); }
.cdnp-kpi-label-out { color: var(--text-muted); }
.cdnp-row2 { display: grid; grid-template-columns: 1fr 1fr; gap: .75rem; }
.cdnp-half { margin-bottom: 0; }
.cdnp-donuts { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: .75rem; }
.cdnp-donut-wrap { margin-bottom: 0; min-height: 200px; }

/* ── CDN Filter Pills ────────────────────────────────── */
.cdn-breadcrumb { display: flex; align-items: center; gap: .35rem; margin-bottom: .75rem; flex-wrap: wrap; }

/* Unified pill style — CDN home + provider pills share same base */
.cdn-bc-pill {
  display: inline-flex; align-items: center; gap: .25rem;
  background: none; border: 1px solid rgba(var(--tint-rgb),.1);
  border-radius: 12px; padding: 2px 8px 2px 6px;
  cursor: pointer; font-size: .66rem; color: var(--text-faint);
  font-family: 'Space Mono', monospace; letter-spacing: .03em;
  transition: border-color .15s, color .15s, background .15s; white-space: nowrap;
}
.cdn-bc-pill:hover { border-color: var(--pill-color, var(--brand)); color: var(--text-primary); }
.cdn-bc-pill.cdn-bc-active {
  border-color: var(--pill-color, var(--brand));
  color: var(--text-primary);
  background: rgba(var(--tint-rgb),.05);
}
/* CDN home pill — teal accent */
.cdn-bc-home { --pill-color: var(--brand); }
.cdn-bc-pill-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--pill-color, var(--brand)); flex-shrink: 0; }

/* ── CDN Overview top row — two equal cards ─────────── */
.cdn-overview-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-bottom: 1rem; }

/* Card 1: CDN vs Total — horizontal: donut left, KPI block right */
.cdn-vs-card h3 { margin-bottom: .65rem; }
.cdn-vs-layout { display: flex; align-items: center; gap: 1.6rem; }
.cdn-vs-donut-el { flex-shrink: 0; }
.cdn-vs-kpis { flex: 1; display: flex; flex-direction: column; gap: .55rem; }
.cdn-vs-kpi-row { display: flex; align-items: center; gap: .75rem; }
.cdn-vs-dot { width: 11px; height: 11px; border-radius: 50%; flex-shrink: 0; }
.cdn-vs-dot-gen { background: var(--chart-empty); border: 1px solid rgba(var(--tint-rgb),.2); }
.cdn-vs-kpi-body { display: flex; flex-direction: column; gap: .05rem; }
.cdn-vs-kpi-label { font-size: .68rem; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); }
.cdn-vs-kpi-val { font-size: 1.9rem; font-weight: 700; font-family: 'Space Mono', monospace; color: var(--brand); line-height: 1.1; }
.cdn-vs-kpi-val-gen { color: var(--text); }
.cdn-vs-kpi-pct { font-size: .88rem; font-family: 'Space Mono', monospace; color: var(--muted); }
.cdn-vs-kpi-divider { height: 1px; background: rgba(var(--tint-rgb),.06); margin: .5rem 0; }

/* Card 2: By Provider — donut left, list right; align to top */
.cdn-by-prov-pie { align-items: flex-start; }

/* ── Donut slice hover + tooltip ───────────────────── */
svg path[data-idx], svg circle[data-idx] { cursor: pointer; transition: opacity .12s, filter .12s; }
svg path[data-idx]:hover, svg circle[data-idx]:hover { opacity: 1 !important; filter: brightness(1.18) drop-shadow(0 0 4px currentColor); }

#_donut-tt {
  position: fixed; display: none; pointer-events: none; z-index: 9999;
  align-items: center; gap: .45rem;
  background: rgba(var(--surface-deep-rgb),.97);
  border: 1px solid rgba(var(--brand-rgb),.3);
  border-radius: 5px; padding: 5px 10px;
  box-shadow: 0 4px 16px var(--shadow-strong);
}
.donut-tt-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.donut-tt-label { font-size: .72rem; font-family: inherit; color: var(--text-primary); white-space: nowrap; }
.donut-tt-pct { font-size: .72rem; font-family: 'Space Mono', monospace; color: var(--brand); white-space: nowrap; margin-left: .2rem; }
.donut-tt-bytes { font-size: .68rem; font-family: 'Space Mono', monospace; color: var(--muted); white-space: nowrap; }

/* ════════════════════════════════════════════════════════════
   COOKBOOK ADMIN COMPONENTS  — edgeguard-cookbook.css §§ 5–7
   Class names: setcard, setrow, metricgrid, logtable, pill…
   Only one conflict with existing codebase: cookbook's .field
   is renamed .ck-field here (existing .field is vertical stack).
   ════════════════════════════════════════════════════════════ */

/* ── Typography helpers ───────────────────────────────────── */
.label {
  font-family: var(--display, 'Rajdhani', sans-serif);
  font-size: 10.5px; font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--muted);
}
.h-block {
  font-family: var(--display, 'Rajdhani', sans-serif);
  font-weight: 600; font-size: 13px;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--accent); margin: 0;
}

/* ── Panel head / body ───────────────────────────────────── */
.panel-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid rgba(var(--brand-rgb),.12);
}
.panel-body { padding: 18px; }

/* ── Status pill ─────────────────────────────────────────── */
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: 'Space Mono', monospace; font-size: 12px;
  padding: 3px 10px; border-radius: 999px; border: 1px solid transparent;
}
.pill::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.pill.ok  { color: var(--accent); background: rgba(var(--brand-rgb),.08); border-color: var(--text-faint); }
.pill.warn{ color: var(--status-warn);       background: rgba(var(--status-warn-rgb),.14);  border-color: rgba(var(--status-warn-rgb),.3); }
.pill.err { color: var(--error);  background: rgba(var(--status-error-rgb),.14); border-color: rgba(var(--status-error-rgb),.3); }
.pill.off { color: var(--muted);  border-color: var(--text-faint); }

/* ── Metric grid (read-only KPIs) ────────────────────────── */
.metricgrid {
  display: grid;
  grid-template-columns: repeat(var(--cols, 4), 1fr);
  background: rgba(var(--surface-deep-rgb),.70);
  border: 1px solid rgba(var(--brand-rgb),.12);
  border-radius: 8px; overflow: hidden;
  box-shadow: 0 2px 12px var(--shadow-soft);
}
.metricgrid .metric {
  padding: 20px 22px; border-left: 1px solid rgba(var(--brand-rgb),.12);
}
.metricgrid .metric:first-child { border-left: none; }
.metricgrid .metric .label { margin-bottom: 14px; }
.metricgrid .metric .val {
  font-family: 'Space Mono', monospace; font-size: 30px; font-weight: 500;
  color: var(--accent); line-height: 1; letter-spacing: -.01em; white-space: nowrap;
}
.metricgrid .metric .val.muted { color: var(--muted); }
.metricgrid .metric .val .unit { font-size: 18px; color: var(--muted); margin-left: 4px; }
.metricgrid .metric .rule { height: 1px; background: rgba(var(--brand-rgb),.12); margin: 16px 0 12px; }
.metricgrid .metric .sub { font-family: 'Space Mono', monospace; font-size: 11px; color: var(--muted); }

/* ── Stat list ───────────────────────────────────────────── */
.statlist .statrow {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 18px; border-top: 1px solid rgba(var(--brand-rgb),.12);
}
.statlist .statrow:first-child { border-top: none; }
.statlist .statrow .k b  { display: block; color: var(--text-primary); font-size: 13px; font-weight: 600; }
.statlist .statrow .k b a { color: inherit; }
.statlist .statrow .k span{ color: var(--muted); font-size: 11.5px; }
.statlist .statrow .v  { font-family: 'Space Mono', monospace; font-size: 15px; color: var(--text); }

/* ── KPI row ─────────────────────────────────────────────── */
.kpirow { display: grid; grid-template-columns: repeat(4, 1fr); border-bottom: 1px solid rgba(var(--brand-rgb),.12); }
.kpi { padding: 18px 20px; border-left: 1px solid rgba(var(--brand-rgb),.12); text-align: left; }
.kpi:first-child { border-left: none; }
.kpi .big { font-family: 'Space Mono', monospace; font-size: 26px; line-height: 1; }
.kpi .big.ok      { color: var(--accent); }
.kpi .big.err     { color: var(--error); }
.kpi .big.neutral { color: var(--text-primary); }
.kpi .label { margin-top: 8px; }

/* ── Log / audit table ───────────────────────────────────── */
.logtable { width: 100%; border-collapse: collapse; font-family: 'Space Mono', monospace; font-size: 12.5px; }
.logtable th {
  text-align: left; padding: 12px 18px;
  border-bottom: 1px solid rgba(var(--brand-rgb),.12);
  font-family: 'Rajdhani', sans-serif; font-size: 10.5px;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--muted); font-weight: 500;
}
.logtable td { padding: 13px 18px; border-bottom: 1px solid rgba(var(--brand-rgb),.06); color: var(--muted); }
.logtable tr:last-child td { border-bottom: none; }
.logtable tr:hover td { background: rgba(var(--tint-rgb),.015); }
.logtable td.t { color: var(--text); }
.logtable .st { font-family: 'Rajdhani', sans-serif; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; }
.logtable .st.ok  { color: var(--accent); }
.logtable .st.err { color: var(--error); }

/* ── Segmented control ───────────────────────────────────── */
.segmented {
  display: inline-flex; border: 1px solid rgba(var(--brand-rgb),.12); border-radius: 6px; overflow: hidden;
}
.segmented button {
  background: transparent; border: none; border-left: 1px solid rgba(var(--brand-rgb),.12);
  color: var(--muted); font-family: 'Space Mono', monospace; font-size: 11px;
  padding: 6px 12px; cursor: pointer;
}
.segmented button:first-child { border-left: none; }
.segmented button.on { background: rgba(var(--brand-rgb),.08); color: var(--accent); }
.segmented button:hover:not(.on) { color: var(--text); }

/* ── Settings card ───────────────────────────────────────── */
.setcard {
  background: rgba(var(--surface-deep-rgb),.70);
  border: 1px solid rgba(var(--brand-rgb),.12);
  border-radius: 8px; overflow: hidden;
  box-shadow: 0 2px 12px var(--shadow-soft);
}
.setcard > .panel-head { background: rgba(var(--brand-rgb),.04); padding: 10px 18px; }
.setcard > .panel-body { padding: 14px 18px; }
/* Per-device pages: cards stop at a reading width instead of the whole screen. */

/* ── Setting row ─────────────────────────────────────────── */
.setrow {
  display: grid; grid-template-columns: 1fr auto;
  align-items: center; gap: 24px;
  padding: 18px 20px; border-top: 1px solid rgba(var(--brand-rgb),.06);
}
.setrow:first-child { border-top: none; }
.setrow .meta b { display: block; color: var(--text-primary); font-size: 14px; font-weight: 600; margin-bottom: 3px; }
.setrow .meta p { margin: 0; color: var(--muted); font-size: 12.5px; line-height: 1.5; max-width: 560px; }
.setrow .control { display: flex; align-items: center; gap: 12px; justify-self: end; }
.setrow .state { font-family: 'Space Mono', monospace; font-size: 11px; color: var(--muted); }
.setrow.is-dirty { box-shadow: inset 2px 0 0 var(--status-warn); }

/* ── Toggle ──────────────────────────────────────────────── */
.toggle {
  position: relative; width: 42px; height: 23px; border-radius: 999px;
  border: 1px solid rgba(var(--brand-rgb),.12); background: var(--surface-raised);
  cursor: pointer; transition: .18s; flex: none;
  appearance: none; -webkit-appearance: none;
}
.toggle::after {
  content: ""; position: absolute; top: 2px; left: 2px;
  width: 17px; height: 17px; border-radius: 50%;
  background: var(--muted); transition: .18s;
}
.toggle:checked { background: rgba(var(--brand-rgb),.08); border-color: var(--text-faint); }
.toggle:checked::after { left: 21px; background: var(--accent); }

/* ── Duration input ──────────────────────────────────────── */
.duration {
  display: inline-flex; align-items: stretch;
  border: 1px solid rgba(var(--brand-rgb),.12); border-radius: 6px;
  background: var(--surface-raised); overflow: hidden;
}
.duration input {
  width: 54px; background: transparent; border: none; color: var(--text);
  font-family: 'Space Mono', monospace; font-size: 13px;
  text-align: right; padding: 7px 8px; outline: none;
}
.duration input:focus { color: var(--accent); }
.duration .unit {
  display: flex; align-items: center; border-left: 1px solid rgba(var(--brand-rgb),.12);
  color: var(--muted); font-family: 'Space Mono', monospace; font-size: 12px;
  padding: 0 10px; background: var(--surface-raised);
}
.duration select {
  background: var(--surface-raised); border: none; border-left: 1px solid rgba(var(--brand-rgb),.12);
  color: var(--muted); font-family: 'Space Mono', monospace; font-size: 12px;
  padding: 0 6px; outline: none; cursor: pointer;
}

/* ── Inline field (input box) ────────────────────────────── */
.ck-field {
  display: inline-flex; align-items: center;
  border: 1px solid rgba(var(--brand-rgb),.12); border-radius: 6px;
  background: var(--surface-raised); overflow: hidden;
}
.ck-field input {
  background: transparent; border: none; color: var(--text);
  font-family: 'Space Mono', monospace; font-size: 13px;
  padding: 7px 10px; outline: none; min-width: 120px;
}
.ck-field input:focus { color: var(--accent); }
.ck-field .suffix { color: var(--muted); font-family: 'Space Mono', monospace; font-size: 12px; padding: 0 10px 0 0; }

/* ── Select ──────────────────────────────────────────────── */
.ck-select {
  background: var(--surface-raised); border: 1px solid rgba(var(--brand-rgb),.12);
  border-radius: 6px; color: var(--text);
  font-family: 'Space Mono', monospace; font-size: 13px;
  padding: 7px 28px 7px 10px; cursor: pointer; outline: none;
  appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6'><path d='M1 1l4 4 4-4' stroke='%237e8c87' stroke-width='1.5' fill='none'/></svg>");
  background-repeat: no-repeat; background-position: right 10px center;
}
.ck-select:focus { border-color: var(--text-faint); }

/* ── Setting table (retention / compression) ─────────────── */
.settable { width: 100%; border-collapse: collapse; }
.settable th {
  text-align: left; padding: 10px 16px;
  border-bottom: 1px solid rgba(var(--brand-rgb),.12);
  font-family: 'Rajdhani', sans-serif; font-size: 10.5px;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--muted); font-weight: 500;
}
.settable th.r, .settable td.r { text-align: right; }
.settable th.c, .settable td.c { text-align: center; }
.settable td { padding: 14px 16px; border-bottom: 1px solid rgba(var(--brand-rgb),.06); font-size: 13px; }
.settable tr:last-child td { border-bottom: none; }
.settable .src b   { color: var(--text-primary); font-size: 13px; }
.settable .src span{ display: block; color: var(--muted); font-size: 11px; }
.settable .size { font-family: 'Space Mono', monospace; color: var(--read-accent); }

/* ── Usage bar (in settings context) ────────────────────── */
.usebar { display: grid; grid-template-columns: 120px 1fr 72px; align-items: center; gap: 14px; padding: 9px 18px; }
.usebar .nm  { font-size: 12.5px; color: var(--muted); }
.usebar .track { height: 6px; background: var(--surface-sunken); border-radius: 999px; overflow: hidden; }
.usebar .track i { display: block; height: 100%; background: linear-gradient(90deg, var(--read-accent), rgba(var(--status-info-rgb),.5)); }
.usebar .track i.agg { background: rgba(var(--brand-rgb),.5); }
.usebar .amt { font-family: 'Space Mono', monospace; font-size: 12px; color: var(--read-accent); text-align: right; }

/* ── Save bar ────────────────────────────────────────────── */
.savebar {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 12px 18px; border-top: 1px solid rgba(var(--brand-rgb),.12);
  background: var(--surface-raised); border-radius: 0 0 8px 8px;
}
.savebar .msg { display: flex; align-items: center; gap: 9px; font-size: 12.5px; color: var(--muted); }
.savebar .msg::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--muted); }
.savebar.dirty .msg { color: var(--status-warn); }
.savebar.dirty .msg::before { background: var(--status-warn); }
.savebar.saved .msg { color: var(--accent); }
.savebar.saved .msg::before { background: var(--accent); }
.savebar .acts { display: flex; gap: 10px; }

/* ── Buttons ─────────────────────────────────────────────── */
.btn {
  font-family: 'Rajdhani', sans-serif; font-size: 11.5px;
  letter-spacing: .1em; text-transform: uppercase;
  padding: 8px 18px; border-radius: 6px; cursor: pointer;
  border: 1px solid transparent; transition: .15s; text-decoration: none;
}
.btn:disabled { opacity: .4; cursor: not-allowed; }
.btn-primary { background: var(--emphasis); color: var(--text-inverse); font-weight: 600; border-color: var(--emphasis); }
.btn-primary:not(:disabled):hover { box-shadow: 0 0 0 1px var(--emphasis), 0 0 18px rgba(var(--brand-rgb),.25); }
.btn-link { background: transparent; color: var(--muted); border-color: transparent; }
.btn-link:not(:disabled):hover { color: var(--text); }
.btn-ghost-sm {
  background: transparent; border: 1px solid rgba(var(--brand-rgb),.2);
  color: var(--muted); font-family: 'Space Mono', monospace; font-size: 11px;
  padding: 5px 12px; border-radius: 4px; cursor: pointer; transition: .12s;
  text-transform: uppercase; text-decoration: none; display: inline-flex; align-items: center;
}
.btn-ghost-sm:hover { color: var(--accent); border-color: var(--text-muted); }

/* ── Callout note ────────────────────────────────────────── */
.ck-note {
  border: 1px solid rgba(var(--brand-rgb),.12); border-left: 2px solid var(--accent);
  background: rgba(var(--brand-rgb),.08); padding: 12px 16px; border-radius: 6px;
  font-size: 13px; color: var(--text); margin: 16px 0;
}
.ck-note.warn { border-left-color: var(--status-warn); background: rgba(var(--status-warn-rgb),.14); }

/* The blackhole settings form runs mode → thresholds → BGP → upstreams →
   learned classes, so a submit button at its end is off-screen from every field
   above it and reads as "there is no save button". Pin it to the viewport for
   as long as the form is on screen. */
/* `.admin-content` is `overflow-y: auto`, which makes it the nearest scrollport
   even though it never scrolls (the page does) — a sticky child inside it can
   therefore never stick. Opt this page out so the save bar pins to the viewport. */
.admin-content-sticky { overflow-y: visible; }
.bh-save-bar {
  position: sticky; bottom: 0; z-index: 5;
  display: flex; align-items: center; gap: 14px;
  margin-bottom: 1.4rem; padding: 12px 16px;
  border: 1px solid rgba(var(--brand-rgb),.16); border-radius: 8px;
  background: rgba(var(--surface-deep-rgb),.94);
  box-shadow: 0 -6px 18px rgba(var(--surface-deep-rgb),.55);
}
.bh-save-note { font-family: 'Space Mono', monospace; font-size: 11px; color: var(--muted); }

/* Generated text (letter, router config, notes) is reference material, not
   something to scroll past on every visit — collapsed by default. */
.bh-fold {
  border: 1px solid rgba(var(--brand-rgb),.12); border-radius: 8px;
  background: rgba(var(--surface-deep-rgb),.5); margin-bottom: 1rem;
}
.bh-fold > summary {
  cursor: pointer; list-style: none; padding: 12px 16px;
  font-family: 'Rajdhani', sans-serif; font-size: 1rem; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; color: var(--accent);
}
.bh-fold > summary::-webkit-details-marker { display: none; }
.bh-fold > summary::before { content: '▸ '; }
.bh-fold[open] > summary::before { content: '▾ '; }
.bh-fold-body { padding: 0 16px 16px; }
/* Counts and timestamps inside a fold summary: the operator decides whether to
   open it from these, so they sit next to the title, not inside the body. */
.fold-meta, .fold-count {
  font-family: 'Space Mono', monospace; font-size: 10.5px; font-weight: 400;
  letter-spacing: .04em; text-transform: none; margin-left: 8px;
}
.fold-meta { color: var(--muted); }
.fold-count { color: var(--status-warn); }

/* Long prose explaining a card (why, formula, scope) sits behind one line;
   the fields stay first and the text is one click away. */
.ck-why { margin-top: .9rem; }
.ck-why > summary {
  cursor: pointer; list-style: none; display: inline-block;
  font-family: 'Space Mono', monospace; font-size: 10.5px;
  letter-spacing: .08em; text-transform: uppercase; color: var(--muted);
}
.ck-why > summary::-webkit-details-marker { display: none; }
.ck-why > summary::before { content: '? '; color: var(--accent); }
.ck-why > summary:hover { color: var(--accent); }
.ck-why[open] > summary { margin-bottom: .5rem; }
.ck-why .ck-note { margin: 0 0 .6rem; }
.ck-why .ck-note:last-child { margin-bottom: 0; }

/* Inline hint under a form field (mitigation settings). */
.bh-hint {
  display: block; margin-top: 4px;
  font-family: 'Space Mono', monospace; font-size: 10.5px;
  color: var(--muted); line-height: 1.45;
}

/* Field help on hover: a "?" after the label, text in data-hint.
   .bh-hint stays for state messages (value read from the router, fallback in effect). */
.hint-i {
  display: inline-block; position: relative; margin-left: 6px;
  width: 14px; height: 14px; border-radius: 50%;
  border: 1px solid var(--muted); color: var(--muted);
  font: 500 9px/12px 'Space Mono', monospace; text-align: center;
  letter-spacing: 0; text-transform: none; vertical-align: middle;
  cursor: help; outline: none;
}
.hint-i:hover, .hint-i:focus { border-color: var(--brand); color: var(--brand); }
.hint-i::after {
  content: attr(data-hint);
  position: absolute; left: 0; top: calc(100% + 6px); z-index: 30;
  width: max-content; max-width: 320px; padding: 8px 10px;
  border: 1px solid var(--border); border-radius: 6px;
  background: var(--surface-raised); color: var(--text-primary);
  box-shadow: 0 6px 20px rgba(0, 0, 0, .25);
  font: 10.5px/1.45 'Space Mono', monospace;
  letter-spacing: 0; text-transform: none; text-align: left; white-space: normal;
  opacity: 0; pointer-events: none; transition: opacity .12s;
}
.hint-i:hover::after, .hint-i:focus::after { opacity: 1; }

/* Subheading between the tables of the autodiscovery panel. */
.bh-sub {
  margin: 14px 0 6px;
  font-family: 'Space Mono', monospace; font-size: 10.5px;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--brand);
}

/* Addresses EdgeGuard derives and always spares — read-only, so chips not inputs. */
.bh-prot { display: flex; flex-wrap: wrap; gap: 6px; }
.bh-prot-chip {
  padding: 3px 8px; border-radius: 4px;
  border: 1px solid rgba(var(--brand-rgb),.22); background: rgba(var(--brand-rgb),.07);
  font-family: 'Space Mono', monospace; font-size: 11px; color: var(--accent);
}

/* Candidates for the never-blackhole list. Cards in a responsive grid, not
   rows in a 172px scroll box: the earlier version showed three of ~40 entries
   at a time, which is unreadable for a list you decide from. Full width and
   auto-fill means the whole set is on screen at any window size. */
.bh-suggest {
  display: grid; gap: 6px;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}
.bh-suggest-row {
  display: grid; grid-template-columns: 16px minmax(0, 1fr);
  align-items: center; gap: 4px 10px;
  padding: 8px 10px; cursor: pointer;
  border: 1px solid rgba(var(--brand-rgb),.12); border-radius: 5px;
  background: var(--surface-raised);
}
.bh-suggest-row:hover { border-color: var(--text-faint); background: rgba(var(--brand-rgb),.05); }
.bh-suggest-row:has(input:checked) { border-color: var(--text-faint); background: rgba(var(--brand-rgb),.06); }
.bh-suggest-row:has(input:disabled) { cursor: default; opacity: .6; }
.bh-suggest-ip {
  font-family: 'Space Mono', monospace; font-size: 12px; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bh-suggest-meta {
  grid-column: 2; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-family: 'Space Mono', monospace;
}
.bh-suggest-kind {
  padding: 1px 6px; border-radius: 3px; font-size: 10.5px;
  letter-spacing: .04em; text-transform: uppercase;
  border: 1px solid rgba(var(--brand-rgb),.22); background: rgba(var(--brand-rgb),.08);
  color: var(--accent);
}
.bh-suggest-detail { font-size: 10.5px; color: var(--muted); }

/* The default browser checkbox is a light-theme square on a dark form.
   min-height/padding are reset because the global `input` rule sets 46px and
   10px 12px, which turned this into a tall pill. */
.bh-ck {
  appearance: none; -webkit-appearance: none;
  width: 16px; height: 16px; min-height: 0; padding: 0; margin: 0;
  border: 1px solid rgba(var(--brand-rgb),.35); border-radius: 3px;
  background: var(--surface-sunken); cursor: inherit; position: relative;
}
.bh-ck:checked { background: rgba(var(--brand-rgb),.9); border-color: var(--brand); }
.bh-ck:checked::after {
  content: ''; position: absolute; left: 4px; top: 1px;
  width: 5px; height: 9px; border: solid var(--text-inverse);
  border-width: 0 2px 2px 0; transform: rotate(40deg);
}

/* Address-space classes. The class is the blocking group (FastNetMon's CIDR
   group), so its floors live on the card and its prefixes below them. */
.bh-class-grid {
  display: grid; gap: 10px;
  /* 400px is what fits a /48 prefix + IP count + class chip + the override
     select without ellipsing the prefix, which is the row's identifier. */
  grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
}
.bh-class-card {
  border: 1px solid rgba(var(--brand-rgb),.14); border-radius: 6px;
  background: rgba(var(--surface-deep-rgb),.55); padding: 12px 14px;
}
.bh-class-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.bh-class-badge {
  font-family: 'Rajdhani', sans-serif; font-size: .95rem; font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase; color: var(--accent);
}
.bh-class-stats { font-family: 'Space Mono', monospace; font-size: 10.5px; color: var(--muted); }
.bh-class-floors { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 10px 0 12px; }
.bh-class-floor { display: flex; flex-direction: column; gap: 3px; }
.bh-class-floor > span {
  font-family: 'Space Mono', monospace; font-size: 10.5px;
  letter-spacing: .04em; text-transform: uppercase; color: var(--muted);
}
.bh-class-pfx { display: flex; flex-direction: column; gap: 5px; }
.bh-class-pfx-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto auto 128px;
  align-items: center; gap: 8px;
  padding-top: 5px; border-top: 1px solid rgba(var(--brand-rgb),.08);
}
.bh-class-pfx-name {
  font-family: 'Space Mono', monospace; font-size: 11.5px; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bh-class-pfx-ips { font-family: 'Space Mono', monospace; font-size: 10.5px; color: var(--muted); }
/* Always in the DOM so every row keeps the same five grid columns; only a
   forced prefix has text in it. */
.bh-class-pfx-learned:empty { border-color: transparent; padding: 0; }
.bh-class-pfx-learned {
  padding: 1px 5px; border-radius: 3px;
  font-family: 'Space Mono', monospace; font-size: 10.5px;
  letter-spacing: .03em; text-transform: uppercase;
  border: 1px solid rgba(var(--brand-rgb),.16); color: var(--muted);
}
/* The floor we derived for this prefix from its own traffic. Accented, because
   it is the number in force - not a suggestion sitting next to the real one. */
.bh-class-pfx-reco {
  font-family: 'Space Mono', monospace; font-size: 10.5px;
  color: var(--accent); white-space: nowrap;
}
/* Learned reference under a class card's two floor inputs. */
.bh-reco {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin: -6px 0 12px;
}
.bh-reco-badge {
  padding: 1px 5px; border-radius: 3px;
  font-family: 'Space Mono', monospace; font-size: 10.5px;
  letter-spacing: .04em; text-transform: uppercase;
  border: 1px solid rgba(var(--brand-rgb),.28); color: var(--accent);
}
.bh-reco-val { font-family: 'Space Mono', monospace; font-size: 10.5px; color: var(--text); }
.bh-reco-stats { font-family: 'Space Mono', monospace; font-size: 10.5px; color: var(--muted); }

/* One row per prefix, so the 46px global input height has to go or the card
   turns into a column of buttons. */
.bh-class-pfx-row .frm-input { padding: 4px 6px; min-height: 30px; font-size: 10.5px; }
.bh-class-floor .frm-input { min-height: 34px; padding: 6px 10px; }

/* ── Admin form fields inside a .setcard ──────────────────
   Shared by every admin form (device settings, NetFlow export, blackhole).
   Lived inline in admin_devices_form.html until a second page needed it. */
.frm-input, .frm-select {
  background: var(--surface-raised); border: 1px solid rgba(var(--brand-rgb),.15);
  border-radius: 4px; color: var(--text);
  font-family: 'Space Mono', monospace; font-size: 12.5px;
  padding: 5px 10px; outline: none;
  /* The global `input { min-height: 46px }` rule would make every field a
     slab; an admin field is 32px, a textarea is as tall as its rows. */
  min-height: 32px;
}
textarea.frm-input { min-height: 0; line-height: 1.45; }
/* Fixed-width values (ports, timeouts, floors) do not need a 400px box. */
.frm-cell input[type="number"].frm-input { max-width: 150px; }
.frm-select { cursor: pointer; }
.frm-input:focus, .frm-select:focus { border-color: var(--text-faint); }
.frm-input[disabled] { opacity: .5; cursor: not-allowed; }

/* Columns are capped, not `1fr`: on a 2300px screen an IP field stretched to
   1300px and read as a mistake. A cell is at most 440px, the grid sits left. */
.frm-grid { display: grid; gap: 12px 18px; padding: 12px 20px; }
.frm-grid-2 { grid-template-columns: repeat(auto-fill, minmax(280px, 440px)); }
.frm-grid-3 { grid-template-columns: repeat(auto-fill, minmax(200px, 300px)); }
@media (max-width: 640px) { .frm-grid-2, .frm-grid-3 { grid-template-columns: 1fr; } }
.frm-row { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 440px)); gap: 12px 18px; padding: 0 20px 12px; }
@media (max-width: 640px) { .frm-row { grid-template-columns: 1fr; } }
.frm-cell { display: flex; flex-direction: column; gap: 4px; }
.frm-cell .label { margin-bottom: 0; }
.frm-cell input, .frm-cell select, .frm-cell textarea { width: 100%; }

.test-row { display: flex; align-items: center; gap: 10px; padding: 0 20px 14px; }
.test-result { font-family: 'Space Mono', monospace; font-size: 12px; color: var(--muted); }
.test-result.ok  { color: var(--accent); }
.test-result.err { color: var(--error); }

/* ── Admin content tint ──────────────────────────────────── */
.admin-content { background: rgba(var(--surface-deep-rgb),.35); }

/* ── Section spacing ─────────────────────────────────────── */
.ck-section { margin-bottom: 2rem; }
.ck-section-hd {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; margin-bottom: 14px; flex-wrap: wrap;
}
.ck-section-hd h3 {
  font-family: 'Rajdhani', sans-serif; font-weight: 700; font-size: 20px;
  margin: 0; color: var(--text-primary); line-height: 1.15;
}
.ck-section-hd .desc { color: var(--muted); font-size: 13px; }

/* ══════════════════════════════════════════════════════════════════
   Flow Query tab — all scoped to .fq-* to avoid global collisions
   ══════════════════════════════════════════════════════════════════ */

/* Filter section */
.fq-filter-row { padding: 14px 16px 0; }
.fq-section-label {
  font-family: 'Rajdhani', sans-serif; font-weight: 700; font-size: 13px;
  letter-spacing: .12em; text-transform: uppercase; color: var(--accent);
}
.fq-hint { font-family: 'Space Mono', monospace; font-size: 10.5px; color: var(--warning); }
.fq-panel {
  border: 1px solid rgba(var(--brand-rgb),.2); border-radius: 7px;
  background: linear-gradient(180deg,rgba(var(--brand-rgb),.02),transparent), rgba(var(--surface-deep-rgb),.8);
  padding: 16px 20px 12px;
}
.fq-form {
  display: grid;
  grid-template-columns: auto minmax(200px,1fr) auto minmax(200px,1fr);
  gap: 12px 18px; align-items: center;
}
@media (max-width: 860px) { .fq-form { grid-template-columns: auto 1fr; } }

.fq-flabel {
  justify-self: end; text-align: right;
  font-family: 'Space Mono', monospace; font-size: 10.5px; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; color: var(--muted);
  display: flex; align-items: center; gap: 6px;
}
.fq-flabel.fq-origem { color: var(--cmd-read); }
.fq-flabel.fq-destino { color: var(--accent); }
.fq-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.fq-dot-src { background: var(--cmd-read); box-shadow: 0 0 6px var(--cmd-read); }
.fq-dot-dst { background: var(--accent); box-shadow: 0 0 6px var(--accent); }

.fq-fctrl { display: flex; align-items: center; gap: 7px; min-width: 0; position: relative; }
.fq-sep { color: var(--muted); font-family: 'Space Mono', monospace; font-size: 12px; }

/* Swap source ↔ destination — straddles the gap between the two input rows */
.fq-swap {
  position: absolute; right: 4px; top: calc(100% + 6px);
  transform: translateY(-50%); z-index: 4;
  width: 26px; height: 26px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg); border: 1px solid rgba(var(--brand-rgb),.35);
  color: var(--accent); cursor: pointer; font-size: 15px; line-height: 1;
  box-shadow: 0 0 0 3px rgba(var(--surface-deep-rgb),.85);
  transition: background .13s, transform .13s, box-shadow .13s;
}
.fq-swap:hover { background: rgba(var(--brand-rgb),.18); transform: translateY(-50%) scale(1.12); }
.fq-swap:active { transform: translateY(-50%) scale(.95); }

.fq-inp {
  background: var(--bg); border: 1px solid rgba(var(--brand-rgb),.15);
  border-radius: 5px; color: var(--text);
  font-family: 'Space Mono', monospace; font-size: 11.5px;
  padding: 6px 9px; outline: none; transition: .13s; height: 32px;
}
.fq-inp::placeholder { color: var(--text-faint); }
.fq-inp:focus { border-color: var(--text-faint); background: rgba(var(--surface-deep-rgb),.9); }
.fq-inp-as   { width: 80px; flex-shrink: 0; }
.fq-inp-addr { flex: 1; min-width: 110px; }
.fq-inp-port { width: 64px; flex-shrink: 0; }

.fq-seg {
  display: inline-flex; border: 1px solid rgba(var(--brand-rgb),.15);
  border-radius: 5px; overflow: hidden; background: var(--bg);
}
.fq-seg button {
  background: transparent; border: none; border-left: 1px solid rgba(var(--brand-rgb),.1);
  color: var(--muted); font-family: 'Space Mono', monospace; font-size: 10.5px;
  padding: 6px 11px; cursor: pointer; transition: .12s; white-space: nowrap;
}
.fq-seg button:first-child { border-left: none; }
.fq-seg button:hover:not(.on) { color: var(--text); }
.fq-seg button.on { background: rgba(var(--brand-rgb),.1); color: var(--accent); }

/* Top Metrics sub-tab badges + per-block layout */
.tm-badges { display: flex; margin: 0 0 1rem; }
.tm-badges button { font-size: 11.5px; padding: 7px 16px; }
.tm-subseg { margin: 0 0 .85rem; }
.tm-block > .ep-row:first-child { margin-top: 0; }
/* CIDR line charts — one leader group per row, Download|Upload side by side */
#tm-cidr-charts { padding: 12px; display: flex; flex-direction: column; gap: 16px; }
.cidr-leader-title { margin: 0 0 8px; }
.cidr-dir-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;   /* 1 row : 2 cols (Download | Upload) */
  gap: 12px;
}
.cidr-dir-grid .cidr-chart-card { margin: 0; min-width: 0; }
.cidr-dir-title { margin: 0 0 4px; font-size: .8rem; color: var(--muted, var(--status-neutral)); font-weight: 600; }
/* Many subnet lines → wrap legend to multiple rows instead of overflowing */
#tm-cidr-charts .chart-legend { flex-wrap: wrap; gap: .35rem .9rem; }
.cidr-donut-row { grid-template-columns: repeat(3, 1fr); }
.cidr-asn { font-size: .78em; color: var(--read-accent, var(--brand)); font-weight: 400; opacity: .85; }
/* Leader-title ASN: prominent chip so "AS268168 · FAST PROVEDOR…" reads clearly */
.cidr-leader-title .cidr-asn {
  opacity: 1;
  font-size: .8em;
  font-weight: 500;
  color: var(--read-accent, var(--brand));
  background: rgba(var(--brand-rgb),.12);
  border: 1px solid rgba(var(--brand-rgb),.25);
  padding: 1px 8px;
  border-radius: 5px;
  letter-spacing: .02em;
  text-transform: none;
  vertical-align: middle;
}
/* Row: tudão chart (3 cols) + leaders tree (2 cols) */
.cidr-top-grid { grid-template-columns: 3fr 2fr; }
@media (max-width: 1100px) { .cidr-top-grid { grid-template-columns: 1fr; } }
/* Leaders CIDR tree/folder */
.cidr-tree { font-size: .82rem; }
.cidr-tree-head, .cidr-tree-row {
  display: grid;
  grid-template-columns: 1fr 5.2em 5.2em 5.6em;
  gap: .4rem; align-items: center;
  padding: 3px 4px;
}
.cidr-tree-head { color: var(--status-neutral); border-bottom: 1px solid rgba(var(--tint-rgb),.06); margin-bottom: 2px; }
.cidr-tree-head .ctr-v, .cidr-tree-row .ctr-v { text-align: right; font-variant-numeric: tabular-nums; }
.cidr-tree-row.cidr-tree-child { background: rgba(var(--tint-rgb),.015); }
.cidr-tree-row .ctr-name { display: flex; align-items: center; gap: .35rem; padding-left: calc(var(--depth,0) * 1.2rem); min-width: 0; flex-wrap: nowrap; overflow: hidden; }
.cidr-tree-row .ctr-name .ep-link { flex-shrink: 0; }
.cidr-tree-row .cidr-asn { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.cidr-tree-row .ctr-tot { color: var(--text-primary); }
.ctr-chev { cursor: pointer; width: 1rem; text-align: center; color: var(--read-accent,var(--brand)); user-select: none; flex-shrink: 0; }
.ctr-nochev { width: 1rem; flex-shrink: 0; display: inline-block; }
.cidr-tree .ep-link { cursor: pointer; }
.cidr-tree .ep-link:hover { text-decoration: underline; }
/* Donut legend as aligned IP | AS | Org columns */
.asn-donut-legend.donut-cols { font-size: .72rem; }
.asn-donut-legend.donut-cols .leg-label.leg-cols {
  display: grid;
  grid-template-columns: 18ch 8ch minmax(0, 1fr);
  gap: .45rem; align-items: baseline;
}
.donut-cols .lc-ip  { color: var(--read-accent,var(--brand)); }
.donut-cols .lc-as  { color: var(--text-muted); opacity: .9; }
.donut-cols .lc-org { color: rgba(var(--status-neutral-rgb),.85); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
/* Ranked share bars - replaced the share donuts. Bar length ranks the item
   against the leader; the % column carries share of the total. The label sits
   on the bar so no legend lookup is needed. */
.share-bars { display: flex; flex-direction: column; gap: 3px; width: 100%; }
.dash-pie-wrap > .share-bars, .dash-pie-wrap > .sb-foot { flex: 1 1 100%; }
.sb-row { display: flex; align-items: center; gap: .5rem; font-size: .8rem; }
.sb-track {
  position: relative; flex: 1 1 auto; min-width: 0; height: 20px;
  display: flex; align-items: center; border-radius: 3px;
  background: rgba(var(--tint-rgb), .07); overflow: hidden;
}
.sb-fill { position: absolute; left: 0; top: 0; bottom: 0; opacity: .5; border-radius: 3px; transition: opacity .1s; }
.sb-row:hover .sb-fill { opacity: .85; }
.sb-name {
  position: relative; padding: 0 .45rem; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--text-primary);
}
.sb-cols { display: grid; grid-template-columns: 18ch 8ch minmax(0, 1fr); gap: .45rem; align-items: center; width: 100%; }
.sb-cols .lc-ip  { color: var(--read-accent, var(--brand)); }
.sb-cols .lc-as  { color: var(--text-muted); opacity: .9; }
/* The org name never fits beside the prefix and the ASN inside a bar - it
   clipped to a single letter. The row title carries the full text. */
.sb-cols .lc-org { display: none; }
.sb-cols { grid-template-columns: minmax(0, 18ch) minmax(0, 1fr); }
.sb-pct, .sb-val {
  flex: 0 0 auto; text-align: right; font-family: 'Space Mono', monospace;
  font-size: .76rem; color: var(--muted);
}
.sb-pct { width: 52px; }
.sb-val { width: 92px; }
.sb-foot { margin-top: .55rem; font-size: .76rem; color: var(--text-faint); }

.dash-pie-legend-row { border-radius: 4px; transition: background .1s; }
.dash-pie-legend-row.leg-hi { background: rgba(var(--tint-rgb),.06); }
/* Donut hover: the slice under the cursor bolds its legend row, and the
   other slices fade, the same reading a line chart's legend gives. */
.dash-pie-legend-val { margin-left: auto; font-family: 'Space Mono', monospace; font-size: .66rem; color: var(--muted); white-space: nowrap; }
.dash-pie-legend-row { cursor: default; padding: .1rem .25rem; }
.dash-pie-legend-row.is-hot { background: rgba(var(--tint-rgb),.06); font-weight: 700; color: var(--text); }
.dash-pie-legend-row.is-hot .dash-pie-legend-val { color: var(--text); font-weight: 700; }
.cdn-vs-kpi-row.is-hot { font-weight: 700; }
svg path[data-idx].is-dim, svg circle[data-idx].is-dim { opacity: .3; }
.tm-block .cidr-chart-card .chart-legend { flex-wrap: wrap; gap: .35rem .9rem; }
@media (max-width: 1000px) { .cidr-donut-row { grid-template-columns: 1fr; } }
@media (max-width: 860px) { .cidr-dir-grid { grid-template-columns: 1fr; } }
/* Overview strip inside the IP block — align with .ep-row's 12px side padding */
.tm-ov-totals { padding: 0 12px; margin-bottom: .6rem; }
/* 3-card overview row: Traffic-over-time (2fr) | IPv4-vs-IPv6 timeline (2fr) | share donut (1fr) */
.tm-ov-grid { grid-template-columns: 2fr 2fr 1fr; }
.tm-ov-grid .dash-pie-wrap { flex-direction: column; align-items: center; gap: .6rem; }
@media (max-width: 1100px) { .tm-ov-grid { grid-template-columns: 1fr; } }
/* Interface cell: name (bright) + alias/description (accent, readable) */
.if-name  { color: var(--text); }
.if-alias { color: var(--accent); margin-left: .55ch; }

/* Share donut: chart on top, legend below */
.asn-donut-chart { display: flex; justify-content: center; margin: .4rem 0 .9rem; }
.asn-donut-legend { display: flex; flex-direction: column; gap: .12rem; }
.asn-donut-legend .dash-pie-legend-row { display: flex; align-items: center; gap: .5rem; font-size: .72rem; }
.asn-donut-legend .leg-label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.asn-donut-legend .leg-pct,
.asn-donut-legend .leg-bytes { flex: 0 0 auto; text-align: right; font-family: 'Space Mono', monospace; font-size: .66rem; color: var(--muted); }
.asn-donut-legend .leg-pct { width: 46px; }
.asn-donut-legend .leg-bytes { width: 82px; }

/* Concentration panel: one 100% bar cut into rank bands. Deliberately short —
   it sits beside a full-height donut and must not stretch the grid row. */
.cb-bar {
  display: flex; height: 26px; border-radius: 5px; overflow: hidden;
  background: rgba(var(--tint-rgb),.04); margin: .3rem 0 .7rem;
}
.cb-seg { height: 100%; transition: filter .12s; }
.cb-seg:hover { filter: brightness(1.25); }
.cb-legend { display: flex; flex-wrap: wrap; gap: .3rem 1.1rem; font-size: .78rem; color: var(--muted); }
.cb-leg { display: inline-flex; align-items: center; gap: 6px; }
.cb-leg i { width: 9px; height: 9px; border-radius: 2px; flex: none; }
.cb-leg b { color: var(--text); font-family: 'Space Mono', monospace; font-weight: 600; }
.cc-insight { margin-top: .7rem; font-size: .78rem; color: var(--muted); }

/* Compact variant: the same bands as a strip beside a card title, so a 10-row
   table no longer sits next to a card that is mostly white space. */
.ep-card-head {
  display: flex; align-items: flex-start; gap: 2rem;
  padding-bottom: .85rem; margin-bottom: .3rem; border-bottom: 1px solid var(--line);
}
.ep-card-head .exp-card-title { margin: 0; flex: 0 0 auto; }
.ep-conc-strip { flex: 1 1 auto; min-width: 0; }
/* Window total and top-5 peak, between the title and the concentration bands.
   Smaller than .dash-totals: this is a card head, not the page's opening KPI. */
.tm-head-kpi { display: flex; gap: 1.5rem; flex: 0 0 auto; }
.tm-head-kpi .dash-total-val { font-size: 1.1rem; }
/* The sub-tab chart lives in the same card as its table, above it. */
.tm-card-chart { margin: .9rem 0 0; padding-bottom: .9rem; border-bottom: 1px solid var(--line); }
.tm-card-chart .chart-legend { flex-wrap: wrap; gap: .35rem .9rem; margin-top: .4rem; }
.tm-card-chart + .exp-table { margin-top: .9rem; }
.cc-cap {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: .66rem; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted); margin-bottom: .32rem;
}
.cc-cap b {
  font-family: 'Space Mono', monospace; font-size: .72rem; color: var(--text);
  letter-spacing: 0; text-transform: none; font-weight: 700;
}
.cb-bar-slim { height: 10px; border-radius: 3px; margin: 0; }
.cb-legend-tight { margin-top: .38rem; font-size: .66rem; }
.cb-legend-tight .cb-leg i { width: 8px; height: 8px; }

/* IX Members - concentration panel. Donut and pareto share the top row; the
   three risk cards and the member chips stack under it. */
.ixm-sub {
  display: flex; flex-wrap: wrap; align-items: center; gap: .4rem 1.2rem;
  font-size: .72rem; color: var(--text-muted); margin: -.35rem 0 1.1rem;
}
.ixm-meta { display: flex; flex-wrap: wrap; gap: 1rem; }
.ixm-meta-item { display: inline-flex; align-items: baseline; gap: .35rem; }
.ixm-meta-item i {
  font-style: normal; text-transform: uppercase; letter-spacing: .08em;
  font-size: .66rem; color: var(--text-faint);
}
.ixm-meta-item b { font-family: var(--mono); font-weight: 700; color: var(--text-primary); }

.ixm-top { display: flex; gap: 2rem; align-items: flex-start; flex-wrap: wrap; }
.ixm-donut { display: flex; gap: 1.2rem; align-items: center; flex: 0 0 auto; }
.ixm-donut-big { font-family: var(--mono); font-size: 26px; font-weight: 700; fill: var(--text-primary); }
.ixm-donut-cap {
  font-family: var(--mono); font-size: 10.5px; fill: var(--text-faint);
  text-transform: uppercase; letter-spacing: .06em;
}
.ixm-legend { width: 300px; }
.ixm-leg-row { display: flex; align-items: center; gap: .55rem; height: 24px; }
.ixm-leg-row i { width: 10px; height: 10px; border-radius: 2px; flex: 0 0 auto; opacity: .85; }
.ixm-leg-row > span:first-of-type {
  font-family: var(--display); font-size: 13px; color: var(--text-primary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ixm-leg-pct { margin-left: auto; font-family: var(--mono); font-size: 11.5px; font-weight: 700; flex: 0 0 auto; }
.ixm-leg-val { font-family: var(--mono); font-size: 10.5px; color: var(--text-faint); width: 74px; text-align: right; flex: 0 0 auto; }
.ixm-leg-dim > span { color: var(--text-muted); }
.ixm-leg-row.is-hot { background: rgba(var(--tint-rgb),.06); font-weight: 700; }
.ixm-leg-row.is-hot .ixm-leg-val { color: var(--text-primary); }

.ixm-pareto { flex: 1 1 420px; min-width: 0; }
.ixm-pareto svg { width: 100%; height: auto; display: block; }
.ixm-pareto-head { display: flex; align-items: center; gap: 1rem; margin-bottom: .4rem; }
.ixm-axis-title, .ixm-axis-foot {
  font-size: .66rem; text-transform: uppercase; letter-spacing: .09em; color: var(--text-faint);
}
.ixm-axis-foot { text-align: center; margin-top: .3rem; }
.ixm-roles { display: flex; flex-wrap: wrap; gap: .8rem; margin-left: auto; }
.ixm-roles span { display: inline-flex; align-items: center; gap: .3rem; font-size: .66rem; color: var(--text-muted); }
.ixm-roles i { width: 7px; height: 7px; border-radius: 50%; }
.ixm-grid { stroke: var(--chart-grid); stroke-width: 1; }
.ixm-axis { stroke: var(--chart-axis); stroke-width: 1; }
.ixm-curve { fill: none; stroke: var(--brand); stroke-width: 2; }
.ixm-curve-tail { stroke-dasharray: 4 4; opacity: .55; }
.ixm-tick { font-family: var(--mono); font-size: 10.5px; fill: var(--text-faint); }
.ixm-mark { fill: var(--surface-raised); stroke: var(--brand); stroke-width: 1.6; }
.ixm-mark-label { font-family: var(--mono); font-size: 10.5px; fill: var(--brand); }
.ixm-bar { transition: opacity .12s; }
.ixm-bar.is-hot { opacity: 1; }
.ixm-hit { cursor: crosshair; }
.ixm-readout {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .4rem .9rem;
  margin-top: .55rem; padding-top: .55rem; border-top: 1px solid var(--line);
  min-height: 20px;
}
.ixm-ro-rank { font-family: var(--mono); font-size: 11px; font-weight: 700; color: var(--text-faint); }
.ixm-ro-dot { width: 8px; height: 8px; border-radius: 50%; align-self: center; flex: 0 0 auto; }
.ixm-ro-name {
  font-family: var(--display); font-size: 13px; font-weight: 600; color: var(--text-primary);
  max-width: 340px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ixm-ro-as { font-family: var(--mono); font-size: 10.5px; color: var(--text-muted); }
.ixm-ro-item { display: inline-flex; align-items: baseline; gap: .3rem; margin-left: auto; }
.ixm-ro-item + .ixm-ro-item { margin-left: 0; }
.ixm-ro-item i {
  font-style: normal; text-transform: uppercase; letter-spacing: .08em;
  font-size: .66rem; color: var(--text-faint);
}
.ixm-ro-item b { font-family: var(--mono); font-size: 11.5px; font-weight: 700; color: var(--text-primary); }
.ixm-guide { stroke: var(--text-muted); stroke-width: 1; stroke-dasharray: 3 3; opacity: .6; }
.ixm-cursor { stroke: var(--surface-raised); stroke-width: 1.6; }

.ixm-cards { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 1.6rem; }
.ixm-card {
  flex: 1 1 260px; border: 1px solid var(--line); border-radius: 5px;
  padding: 14px 16px; background: var(--surface-sunken);
}
.ixm-card-label { font-size: .66rem; text-transform: uppercase; letter-spacing: .09em; color: var(--text-faint); }
.ixm-card-nums { display: flex; align-items: baseline; gap: 10px; margin: 8px 0 6px; }
.ixm-card-big { font-family: var(--mono); font-size: 1.5rem; font-weight: 700; color: var(--text-primary); }
.ixm-card-pct { font-family: var(--mono); font-size: 1rem; font-weight: 700; }
.ixm-card-note { font-size: .7rem; line-height: 1.45; color: var(--text-muted); }

.ixm-chips {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin-top: 1.5rem; padding-top: 1.1rem; border-top: 1px solid var(--line);
}
.ixm-chip {
  display: inline-flex; align-items: center; gap: 7px;
  border: 1px solid rgba(var(--tint-rgb),.08); border-radius: 3px;
  padding: 3px 9px; background: var(--surface-sunken);
}
.ixm-chip i { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; }
.ixm-chip span { font-family: var(--display); font-size: 12px; color: var(--text-primary); }
.ixm-chip b { font-family: var(--mono); font-size: 10.5px; font-weight: 400; color: var(--text-faint); }
.ixm-chip-rest { font-family: var(--mono); font-size: 10.5px; color: var(--text-faint); }
.ixm-chip.is-hot { border-color: rgba(var(--brand-rgb),.45); background: rgba(var(--brand-rgb),.08); }

.fq-actions {
  display: flex; justify-content: center; gap: 10px;
  margin-top: 14px; padding-top: 14px;
  border-top: 1px solid rgba(var(--brand-rgb),.08);
}
.fq-btn {
  font-family: 'Rajdhani', sans-serif; font-weight: 600; font-size: 12px;
  letter-spacing: .07em; text-transform: uppercase;
  padding: 8px 22px; border-radius: 5px; cursor: pointer;
  border: 1px solid rgba(var(--brand-rgb),.25); background: transparent;
  color: var(--muted); transition: .13s;
}
.fq-btn:hover { color: var(--text); border-color: var(--text-muted); }
.fq-btn-primary {
  background: var(--emphasis); color: var(--text-inverse); border-color: transparent; font-weight: 700;
}
.fq-btn-primary:hover { background: var(--emphasis); box-shadow: 0 0 14px rgba(var(--emphasis-rgb),.3); color: var(--text-inverse); }

/* Insights strip */
.fq-insights {
  display: grid; grid-template-columns: repeat(6,1fr);
  border-top: 1px solid rgba(var(--brand-rgb),.08); margin-top: 12px;
}
@media (max-width: 860px) { .fq-insights { grid-template-columns: repeat(3,1fr); } }
.fq-kpi {
  padding: 12px 16px;
  border-right: 1px solid rgba(var(--brand-rgb),.06);
}
.fq-kpi:last-child { border-right: none; }
.fq-kpi-label {
  font-family: 'Space Mono', monospace; font-size: 10.5px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 6px;
}
.fq-kpi-val {
  font-family: 'Space Mono', monospace; font-size: 22px; color: var(--accent); line-height: 1;
}
.fq-kpi-val .fq-u { font-size: 12px; color: var(--muted); margin-left: 2px; }
.fq-info   { color: var(--cmd-read) !important; }
.fq-warn   { color: var(--warning) !important; }
.fq-neutral{ color: var(--text-primary) !important; }
.fq-up     { color: var(--accent); }
.fq-dn     { color: var(--error); }
.fq-kpi-sub { font-family: 'Space Mono', monospace; font-size: 10.5px; color: var(--muted); margin-top: 5px; }

/* Result header + view switcher */
.fq-result-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 12px 16px 8px; flex-wrap: wrap;
}
.fq-result-title {
  font-family: 'Rajdhani', sans-serif; font-weight: 600; font-size: 15px; color: var(--text-primary);
}
.fq-vswitch {
  display: inline-flex; background: rgba(var(--surface-deep-rgb),.8);
  border: 1px solid rgba(var(--brand-rgb),.15); border-radius: 5px; overflow: hidden;
}
.fq-vswitch button {
  display: flex; align-items: center; gap: 6px;
  background: transparent; border: none; border-left: 1px solid rgba(var(--brand-rgb),.1);
  color: var(--muted); font-family: 'Rajdhani', sans-serif; font-weight: 600;
  font-size: 11px; letter-spacing: .04em; padding: 7px 13px; cursor: pointer; transition: .13s;
}
.fq-vswitch button:first-child { border-left: none; }
.fq-vswitch button:hover:not(.on) { color: var(--text); background: rgba(var(--tint-rgb),.02); }
.fq-vswitch button.on { background: rgba(var(--brand-rgb),.1); color: var(--accent); }

/* Stage states */
.fq-empty-state {
  text-align: center; padding: 3rem 1rem; color: var(--muted);
}
.fq-empty-icon { font-size: 2.5rem; opacity: .25; margin-bottom: .75rem; }
.fq-empty-msg  { font-size: .82rem; }
.fq-error-banner {
  margin: .75rem 16px; padding: .65rem 1rem;
  background: rgba(var(--status-error-rgb),.08); border: 1px solid rgba(var(--status-error-rgb),.4);
  border-radius: 5px; font-size: .8rem; color: var(--error);
}

/* Table view */
.fq-table-wrap { display: flex; gap: 16px; padding: 0 16px 16px; }
.fq-table {
  width: 100%; border-collapse: collapse;
  font-family: 'Space Mono', monospace; font-size: 11.5px;
}
.fq-table th {
  text-align: left; padding: 9px 10px; border-bottom: 1px solid rgba(var(--brand-rgb),.12);
  font-family: 'Rajdhani', sans-serif; font-size: 10.5px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted); font-weight: 500; cursor: pointer;
  white-space: nowrap; user-select: none;
}
.fq-table th:hover { color: var(--text); }
.fq-table th.r, .fq-table td.r { text-align: right; }
.fq-table td {
  padding: 9px 10px; border-bottom: 1px solid rgba(var(--brand-rgb),.04); color: var(--muted);
}
.fq-table tbody tr.fq-tr:hover td { background: rgba(var(--brand-rgb),.05); cursor: pointer; }
.fq-td-src  { color: var(--cmd-read); }
.fq-cell-sub {
  display: block; font-size: 10.5px; color: var(--muted);
  font-weight: 400; margin-top: 2px; letter-spacing: .01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 320px;
}
.fq-drill {
  display: inline-block; width: 0; overflow: hidden; opacity: 0;
  color: var(--accent); font-size: 12px; vertical-align: baseline;
  transition: opacity .12s, width .12s, margin .12s;
}
.fq-table tbody tr.fq-tr:hover .fq-drill { opacity: 1; width: 14px; margin-right: 2px; }
.fq-td-dst  { color: var(--text); }
.fq-td-bytes{ color: var(--accent); }
.fq-bar-wrap {
  display: inline-block; width: 56px; height: 5px;
  background: rgba(var(--brand-rgb),.08); border-radius: 999px; overflow: hidden;
  vertical-align: middle; margin-right: 6px;
}
.fq-bar-fill { height: 100%; background: linear-gradient(90deg,var(--accent),rgba(var(--brand-rgb),.4)); }
.fq-raw-row { display: none; }
.fq-raw-row.open { display: table-row; }
.fq-raw-cell { padding: 8px 12px 12px 12px !important; }
.fq-raw-block {
  font-family: 'Space Mono', monospace; font-size: 10.5px; color: var(--muted);
  background: rgba(var(--surface-deep-rgb),.9); border: 1px solid rgba(var(--brand-rgb),.1);
  border-radius: 5px; padding: 10px 14px; line-height: 1.9; white-space: pre-wrap;
}
.fq-raw-k { color: var(--cmd-read); }
.fq-raw-v { color: var(--text); }
.fq-expand-btn { background: none; border: none; color: var(--muted); cursor: pointer; font-size: 11px; padding: 0 4px; }
.fq-expand-btn:hover { color: var(--accent); }

/* Direction badge (table) */
.fq-dir-badge {
  display: inline-block; font-family: 'Space Mono', monospace; font-size: 10.5px;
  font-weight: 600; padding: 2px 6px; border-radius: 3px; white-space: nowrap;
  letter-spacing: .02em;
}
.fq-dir-dl      { color: var(--brand); background: rgba(var(--brand-rgb),.12); }
.fq-dir-ul      { color: var(--cmd-read); background: rgba(var(--cmd-read-rgb),.12); }
.fq-dir-onnet   { color: var(--muted); background: rgba(var(--tint-rgb),.05); }
.fq-dir-transit { color: rgba(var(--status-neutral-rgb),.6); background: transparent; }

/* Peers view: balance bar (download share vs upload share + total width) */
.fq-bal {
  display: flex; height: 7px; width: 100%; max-width: 160px;
  border-radius: 999px; overflow: hidden; background: rgba(var(--tint-rgb),.05);
}
.fq-bal-dl { background: var(--brand); }
.fq-bal-ul { background: var(--cmd-read); }
.fq-bal-w  { height: 2px; margin-top: 3px; background: rgba(var(--brand-rgb),.25); border-radius: 999px; max-width: 160px; }
.fq-peers-table { width: 100%; }

/* Share-of-total column (Partners view) */
.fq-share { display: flex; align-items: center; gap: 9px; }
.fq-share-pct {
  font-family: 'Space Mono', monospace; font-size: 11px; color: var(--accent);
  min-width: 44px; text-align: right; flex-shrink: 0;
}
.fq-share-track {
  flex: 1; max-width: 140px; height: 6px; border-radius: 999px;
  background: rgba(var(--tint-rgb),.05); overflow: hidden;
}
.fq-share-fill { display: block; height: 100%; background: linear-gradient(90deg, var(--accent), rgba(var(--brand-rgb),.4)); }

/* Peers view dimension toggle */
.fq-peers-dim { display: flex; gap: 2px; margin-bottom: 10px; }
.fq-peers-dim button {
  font-family: 'Space Mono', monospace; font-size: 10.5px; font-weight: 600;
  padding: 5px 12px; border: 1px solid rgba(var(--brand-rgb),.18); background: transparent;
  color: var(--muted); cursor: pointer; transition: color .12s, border-color .12s, background-color .12s;
}
.fq-peers-dim button:first-child { border-radius: 4px 0 0 4px; }
.fq-peers-dim button:last-child  { border-radius: 0 4px 4px 0; border-left: none; }
.fq-peers-dim button.on { color: var(--accent); background: rgba(var(--brand-rgb),.12); border-color: var(--text-faint); }

/* Peer / Uplink selector (filter panel) */
.fq-peer-select {
  width: 100%; max-width: 320px; cursor: pointer; color-scheme: dark;
  appearance: none; -webkit-appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%),
                    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - 14px) center, calc(100% - 9px) center;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat;
  padding-right: 26px;
}
.fq-peer-select option { background: var(--bg); color: var(--text); }
/* Interface select shares its row with the In/Out/Any seg control, so it can't claim 100% width like the standalone Peer select */
#fq-iface-sel { width: auto; max-width: 220px; flex: 1; min-width: 110px; }
.fq-donut-empty { font-family: 'Space Mono', monospace; font-size: 10.5px; color: var(--muted); text-align: center; padding: 30px 8px; }

/* kind chip (uplink rows) */
.fq-kind-chip {
  display: inline-block; font-size: 10.5px; font-weight: 600; padding: 1px 5px;
  border-radius: 3px; margin-left: 6px; vertical-align: middle; letter-spacing: .03em;
}
.fq-kind-onnet { color: var(--muted);  background: rgba(var(--tint-rgb),.06); }
.fq-kind-peer  { color: var(--brand); background: rgba(var(--brand-rgb),.12); }
.fq-kind-ix    { color: var(--status-warn); background: rgba(var(--status-warn-rgb),.12); }

/* Donut panel */
.fq-donut-panel {
  width: 320px; flex-shrink: 0;
  border: 1px solid rgba(var(--brand-rgb),.1); border-radius: 7px;
  padding: 14px 16px; background: rgba(var(--surface-deep-rgb),.5);
}
.fq-donut-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; gap: 8px; }
.fq-donut-head .fq-panel-head { margin-bottom: 0; }
.fq-donut-toggle { display: flex; gap: 2px; flex-shrink: 0; }
.fq-donut-toggle button {
  font-family: 'Space Mono', monospace; font-size: 10.5px; font-weight: 600;
  padding: 3px 7px; border: 1px solid rgba(var(--brand-rgb),.18); background: transparent;
  color: var(--muted); cursor: pointer; border-radius: 3px; transition: color .12s, border-color .12s, background-color .12s; white-space: nowrap;
}
.fq-donut-toggle button.on { color: var(--accent); background: rgba(var(--brand-rgb),.12); border-color: var(--text-faint); }
.fq-panel-head {
  font-family: 'Rajdhani', sans-serif; font-size: 11px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--accent); margin-bottom: 10px;
}
#fq-donut-svg { display: block; margin: 0 auto 10px; }
.fq-donut-legend { font-family: 'Space Mono', monospace; font-size: 12px; }
.fq-dl-row { display: flex; align-items: flex-start; gap: 9px; padding: 7px 0; border-bottom: 1px solid rgba(var(--brand-rgb),.06); }
.fq-dl-row:last-child { border-bottom: none; }
.fq-dl-dot { margin-top: 4px; }
.fq-dl-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
.fq-dl-name { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.fq-dl-asn  { font-size: 13px; color: var(--text); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fq-dl-org  { font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fq-dl-pct  { color: var(--accent); font-size: 13px; font-weight: 600; min-width: 46px; text-align: right; flex-shrink: 0; align-self: center; }

/* Sankey view */
.fq-sankey-svg { display: block; height: 340px; }

/* Timeline view */
#fq-timeline-svg-rate, #fq-timeline-svg-vol { display: block; height: 160px; width: 100%; }
.fq-timeline-legend { flex-wrap: wrap; gap: 6px 12px; padding: 6px 4px 4px; margin-top: 0; }
.fq-tl-grid { display: grid; grid-template-columns: 1fr 1px 1fr; gap: 18px; align-items: start; }
.fq-tl-cell { min-width: 0; }
.fq-tl-divider { width: 1px; background: rgba(var(--brand-rgb),.12); align-self: stretch; }
.fq-tl-title {
  font-family: 'Rajdhani', sans-serif; font-size: 11px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--accent); margin-bottom: 8px;
}
@media (max-width: 860px) {
  .fq-tl-grid { grid-template-columns: 1fr; }
  .fq-tl-divider { display: none; }
}

/* Cards view */
.fq-cards { display: grid; grid-template-columns: repeat(auto-fill,minmax(260px,1fr)); gap: 10px; padding: 0 16px 16px; }
.fq-card {
  background: rgba(var(--surface-deep-rgb),.8); border: 1px solid rgba(var(--brand-rgb),.1);
  border-radius: 7px; padding: 13px; transition: .13s;
}
.fq-card:hover { border-color: var(--text-faint); }
.fq-card-pair { display: flex; align-items: center; gap: 7px; margin-bottom: 10px; font-family: 'Space Mono', monospace; font-size: 11px; }
.fq-card-src { color: var(--cmd-read); } .fq-card-dst { color: var(--accent); }
.fq-card-sub { display: block; font-size: 10.5px; color: var(--muted); margin-top: 1px; }
.fq-card-body { display: flex; align-items: center; gap: 12px; }
.fq-card-nums { flex: 1; }
.fq-card-big { font-family: 'Space Mono', monospace; font-size: 19px; color: var(--accent); line-height: 1; }
.fq-card-big .fq-u { font-size: 11px; color: var(--muted); }
.fq-card-ln { font-family: 'Space Mono', monospace; font-size: 10.5px; color: var(--muted); margin-top: 4px; }
.fq-card-foot {
  display: flex; justify-content: space-between; align-items: center;
  margin-top: 10px; padding-top: 8px; border-top: 1px solid rgba(var(--brand-rgb),.06);
  font-family: 'Space Mono', monospace; font-size: 10.5px; color: var(--muted);
}

/* Peering (Networks & Uplinks) screen */
.peer-insight { font-size: .78rem; color: var(--muted); margin: .35rem 0 .6rem; }
.peer-badge {
  display: inline-block; font-size: .66rem; font-weight: 600; padding: 1px 6px;
  border-radius: 3px; margin-left: 4px; vertical-align: middle; letter-spacing: .02em;
}
.peer-badge-cdn     { background: rgba(var(--cmd-read-rgb),.15);  color: var(--cmd-read); }
.peer-badge-ix      { background: rgba(var(--status-ok-rgb),.15);  color: var(--status-ok); }
.peer-badge-transit { background: rgba(var(--status-warn-rgb),.15);  color: var(--status-warn); }
.peer-badge-cust    { background: rgba(var(--ip-v6-rgb),.15); color: var(--ip-v6); }

/* Auto/Manual switch on a floor field. The checkbox is .bh-ck, not a raw one:
   the global `input` rule (min-height 46px, padding 10px 12px) turns a bare
   checkbox into a big white slab — the same trap .bh-ck was written for. */
.bh-field-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; margin-bottom: 4px;
}
.bh-field-head .label { margin: 0; }
/* .bh-ck sets a 16px width, which a flex item is still free to shrink below. */
.bh-auto-tog .bh-ck { flex: 0 0 16px; }
.bh-auto-tog {
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  white-space: nowrap;
  font-family: 'Space Mono', monospace; font-size: 10.5px;
  letter-spacing: .04em; text-transform: uppercase; color: var(--muted);
}
/* Label and switch share row 1, the input spans the full width on row 2, so a
   narrow class card does not put the checkbox on a line of its own. */
.bh-class-floor {
  display: grid; grid-template-columns: 1fr auto; gap: 3px 6px; align-items: center;
}
.bh-class-floor > span { grid-column: 1; }
.bh-class-floor > .bh-auto-ck { grid-column: 2; grid-row: 1; }
.bh-class-floor > .frm-input { grid-column: 1 / -1; }

/* ── Subscribers (BRAS) dashboard ─────────────────────── */
/* Drill-down header: back button, the line being inspected, and the identity
   slot that stays empty until an operator asks for it. */
.cdnp-head { display: flex; align-items: center; gap: .75rem; flex-wrap: wrap; margin-bottom: .75rem; }
.cdnp-title { font-family: 'Space Mono', monospace; font-size: .95rem; font-weight: 700; color: var(--text); }
.cdnp-ident { font-size: .72rem; color: var(--muted); }

/* KPI strip: label, number, bar. The sentences that used to sit under each
   number said in words what the cards below say in a chart, so the tiles gave
   that room back to the number itself. The bars stayed: they carry a ratio
   (lines against sessions online, attributed bytes against the device's) with
   no words at all. */
.subs-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: .6rem; margin-bottom: .9rem; }
.subs-kpi { display: flex; flex-direction: column; gap: .3rem; padding: .95rem 1rem; background: var(--surface-raised); border: 1px solid var(--border); border-radius: 6px; }
.subs-kpi-label { font-size: .66rem; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); }
.subs-kpi-val { font-family: 'Space Mono', monospace; font-size: 1.7rem; font-weight: 700; color: var(--text); line-height: 1.05; }
.subs-kpi-foot { display: flex; flex-direction: column; gap: .22rem; margin-top: auto; padding-top: .35rem; }
.subs-kpi-track { height: 3px; background: rgba(var(--tint-rgb),.08); border-radius: 2px; overflow: hidden; }
.subs-kpi-fill { display: block; height: 100%; width: 0; background: var(--brand); }
.subs-kpi-fill-alt { background: var(--status-info); }

@media (max-width: 900px) {
  .subs-kpis { grid-template-columns: repeat(2, 1fr); }
}

/* Concentration as a Lorenz curve against the equality diagonal: the ten-band
   list this replaced held the same numbers but never showed their shape. */
.subs-conc-svg { width: 100%; height: 210px; display: block; }
.subs-conc-hit { fill: transparent; cursor: crosshair; }
/* The crosshair every subscriber chart draws: one dot per series, on the
   instant under the cursor. */
.subs-cursor-dot { fill: var(--brand); stroke: var(--panel); stroke-width: 1.5; }
.subs-cursor-dot.is-cust { fill: var(--status-warn); }
.subs-cursor-dot.is-v6 { fill: var(--ip-v6); }
/* Bar rows answer on hover, so they have to look hoverable. */
.subs-hoverable { cursor: crosshair; border-radius: 3px; transition: background .12s ease; }
.subs-hoverable:hover { background: rgba(var(--tint-rgb),.07); }
.subs-hist-col.subs-hoverable:hover { background: rgba(var(--ip-v6-rgb),.12); }
.subs-conc-cursor-line { stroke: var(--text-faint); stroke-width: 1; }
.subs-conc-cursor-dot { fill: var(--brand); stroke: var(--panel); stroke-width: 1.5; }
.subs-conc-grid { stroke: var(--chart-grid); stroke-width: 1; }
.subs-conc-axis { fill: var(--text-faint); font-size: 12px; font-family: 'Space Mono', monospace; }
.subs-conc-eq { stroke: var(--text-faint); stroke-width: 1; stroke-dasharray: 4 3; opacity: .7; }
.subs-conc-area { fill: rgba(var(--brand-rgb),.14); stroke: none; }
.subs-conc-line { fill: none; stroke: var(--brand); stroke-width: 2; }
.subs-conc-mark { stroke: var(--status-warn); stroke-width: 1; stroke-dasharray: 3 2; }
.subs-conc-dot { fill: var(--status-warn); }
.subs-conc-x { display: flex; justify-content: space-between; font-size: .78rem; color: var(--text-faint); margin-top: -.2rem; }

/* Three numbers a curve cannot be read off precisely, spelled out under it. */
.subs-callouts { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .6rem; }
#subs-avg-fam .subs-note { flex: 1 0 100%; margin-top: .25rem; }
.subs-callout { flex: 1; display: flex; flex-direction: column; gap: .1rem; padding: .4rem .5rem; background: rgba(var(--tint-rgb),.04); border-left: 2px solid var(--brand); border-radius: 3px; }
.subs-callout-val { font-family: 'Space Mono', monospace; font-size: .98rem; font-weight: 700; color: var(--text); }
.subs-callout-label { font-size: .74rem; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
/* Title and its statistics on one baseline: the percentiles belong to the
   card's heading, not to a row inside it. */
.subs-card-head { display: flex; align-items: baseline; gap: .75rem; flex-wrap: wrap; }
.subs-card-head h3 { margin: 0; flex: 0 0 auto; }
.subs-card-head .subs-note { margin: 0 0 0 auto; }

.subs-note { font-size: .78rem; color: var(--text-faint); margin-top: .55rem; line-height: 1.45; }

/* Horizontal bar rows: a label, a track and a value. Shared by the consumption
   bands and the IPv6 funnel. */
.subs-dist-row { display: flex; align-items: center; gap: .55rem; padding: .28rem 0; }
.subs-dist-label { flex: 0 0 4.6rem; font-size: .78rem; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.subs-dist-track { flex: 1; height: 10px; background: rgba(var(--tint-rgb),.06); border-radius: 5px; overflow: hidden; }
.subs-dist-fill { display: block; height: 100%; background: var(--brand); opacity: .75; }
.subs-dist-fill-top { background: var(--status-warn); opacity: .9; }
.subs-dist-val { flex: 0 0 4.6rem; text-align: right; font-family: 'Space Mono', monospace; font-size: .84rem; color: var(--text); }

/* The bands are ranges ("50 – 100 GB") and the value is a head-count, so the
   row is not the percentile row .subs-dist-* was sized for. */
#subs-dist .subs-dist-label { flex: 0 0 6.4rem; text-align: right; text-transform: none; letter-spacing: 0; font-size: .8rem; }
#subs-dist .subs-dist-val { flex: 0 0 3.8rem; }

/* The legend dot shared by every card that needs one: movers, VLANs, families. */
.subs-pop-dot { width: 8px; height: 8px; border-radius: 2px; flex: 0 0 auto; background: var(--muted); }
.subs-pop-dot.is-measured { background: var(--brand); }
.subs-pop-dot.is-up { background: var(--status-warn); }
.subs-pop-dot.is-new { background: var(--ip-v6); }

/* Movers: risers and lines that were silent before are the same question, so
   they share one card and one bar scale, distinguished by the badge. */
.subs-mover { display: flex; align-items: center; gap: .5rem; padding: .25rem 0; cursor: pointer; }
.subs-mover:hover .subs-mover-sub { color: var(--brand); }
.subs-mover-badge { flex: 0 0 auto; min-width: 2.6rem; text-align: center; font-family: 'Space Mono', monospace; font-size: .66rem; padding: .1rem .3rem; border-radius: 3px; }
.subs-mover-badge.is-up { background: rgba(var(--status-warn-rgb),.18); color: var(--status-warn); }
.subs-mover-badge.is-new { background: rgba(var(--ip-v6-rgb),.18); color: var(--ip-v6); }
.subs-mover-sub { flex: 0 0 auto; font-family: 'Space Mono', monospace; font-size: .72rem; color: var(--text); }
.subs-mover-track { flex: 1; height: 6px; background: rgba(var(--tint-rgb),.06); border-radius: 3px; overflow: hidden; }
.subs-mover-fill { display: block; height: 100%; background: var(--status-warn); opacity: .8; }
.subs-mover-fill.is-new { background: var(--ip-v6); }
.subs-mover-val { flex: 0 0 4rem; text-align: right; font-family: 'Space Mono', monospace; font-size: .7rem; color: var(--muted); }
.subs-mover-legend { display: flex; gap: 1rem; flex-wrap: wrap; margin-top: .6rem; font-size: .66rem; color: var(--text-faint); }
.subs-mover-legend span { display: flex; align-items: center; gap: .3rem; }

/* The ranking table absorbed the old "heaviest lines" bar chart - the share
   column is that chart, on the rows it was duplicating. */
/* Lookup screen: the search and its results are a column that STAYS while a
   customer is open beside it. As a dropdown over the ranking, every pick tore
   the list down and the next customer meant typing the query again. */
.subs-lookup { display: grid; grid-template-columns: 20rem minmax(0, 1fr); gap: 1rem; align-items: start; }
.subs-lookup-side { position: sticky; top: .5rem; }
.subs-lookup-main { min-width: 0; }
.subs-search-inp { width: 100%; padding: .45rem .6rem; font-size: .72rem; color: var(--text); background: rgba(var(--tint-rgb),.04); border: 1px solid var(--border); border-radius: 4px; }
.subs-search-inp:focus { outline: none; border-color: var(--brand); }
/* The tree is the panel's body: it fills the column instead of leaving it
   empty until something is typed, and scrolls inside its own height so the
   customer open beside it never moves. */
.subs-tree { margin-top: .4rem; max-height: calc(100vh - 16rem); min-height: 12rem; overflow-y: auto; background: var(--panel); border: 1px solid var(--border); border-radius: 4px; }
.subs-tree-dev { border-bottom: 1px solid var(--border); }
.subs-tree-dev:last-child { border-bottom: none; }
.subs-tree-node { display: flex; align-items: center; gap: .4rem; width: 100%; padding: .4rem .6rem; cursor: pointer; text-align: left; background: rgba(var(--tint-rgb),.04); border: none; color: var(--text); font-family: inherit; font-size: .68rem; text-transform: uppercase; letter-spacing: .04em; }
.subs-tree-node:hover { background: rgba(var(--brand-rgb),.08); }
/* The three levels are told apart by indent and weight, not by a rule between
   them: a customer sits under a concentrator, which sits under a BNG. */
.subs-tree-node.is-group { padding-left: 1.3rem; background: none; font-size: .66rem; color: var(--muted); text-transform: none; letter-spacing: 0; font-family: 'Space Mono', monospace; }
.subs-tree-group { border-top: 1px solid var(--border); }
.subs-tree-group:first-child { border-top: none; }
.subs-tree-chev { flex: 0 0 auto; color: var(--text-faint); transition: transform .12s ease; }
.subs-tree-node.is-open .subs-tree-chev { transform: rotate(90deg); color: var(--brand); }
.subs-tree-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.subs-tree-count { flex: 0 0 auto; font-family: 'Space Mono', monospace; font-size: .66rem; color: var(--text-faint); text-transform: none; }
.subs-tree-row { display: flex; flex-direction: column; gap: .1rem; padding: .34rem .6rem .34rem 2.9rem; cursor: pointer; border-bottom: 1px solid var(--border); border-left: 2px solid transparent; }
.subs-tree-row:last-child { border-bottom: none; }
.subs-tree-row:hover { background: rgba(var(--brand-rgb),.08); }
.subs-tree-row.is-open { border-left-color: var(--brand); background: rgba(var(--brand-rgb),.1); }
.subs-tree-more { width: 100%; padding: .34rem .6rem .34rem 2.9rem; cursor: pointer; background: none; border: none; border-top: 1px solid var(--border); color: var(--brand); font-family: inherit; font-size: .66rem; text-transform: uppercase; letter-spacing: .04em; }
.subs-tree-more:hover { background: rgba(var(--brand-rgb),.08); }
@media (max-width: 1100px) {
  .subs-lookup { grid-template-columns: 1fr; }
  .subs-lookup-side { position: static; }
}

#subs-detail .dash-grid { align-items: start; }

/* Back out of one customer. An arrow glyph is not on the keyboard and renders
   differently per font; the chevron is drawn, so it cannot go missing. */
.subs-back-btn { display: inline-flex; align-items: center; gap: .35rem; }
.subs-search-name { font-size: .72rem; color: var(--text); }
.subs-search-keys { font-size: .66rem; color: var(--muted); font-family: 'Space Mono', monospace; }
.subs-search-meta { font-size: .66rem; color: var(--text-faint); }
.subs-search-empty { padding: .45rem .6rem; font-size: .66rem; color: var(--text-faint); }

/* Destination host list: the address leads, the reverse DNS name or ASN
   trails it in the same row without competing for the eye. The default 200px
   .bar-label ellipsises an IPv6 address before its reverse DNS name even
   starts, so both panels get the wider label the prefix lists use. The label
   keeps flex-shrink so one long address does not push the card's min-content
   past the grid track and clip the full-width cards. */
.subs-dst-meta { color: var(--text-faint); }
#subs-d-dst .bar-label,
#subs-d-peers .bar-label { width: clamp(200px, 32vw, 460px); min-width: 0; flex-shrink: 1; }
#subs-detail .dash-grid > .dash-card { min-width: 0; }
/* Scans: "AS197769 - holder name" overflowed the shared 200px label. Same
   widening as the subscriber lists. */
#scan-top-asns .bar-label { width: clamp(200px, 32vw, 460px); min-width: 0; flex-shrink: 1; }
.dash-card:has(> #scan-top-asns) { min-width: 0; }

.subs-tbl-head { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; margin-bottom: .5rem; }
.subs-tbl-scope { font-size: .66rem; color: var(--text-faint); font-family: 'Space Mono', monospace; }
.subs-filter { margin-left: auto; width: 13rem; padding: .28rem .5rem; font-size: .68rem; color: var(--text); background: rgba(var(--tint-rgb),.04); border: 1px solid var(--border); border-radius: 4px; }
.subs-filter:focus { outline: none; border-color: var(--brand); }
.subs-th-rank, .subs-td-rank { width: 2.2rem; text-align: right; color: var(--text-faint); font-family: 'Space Mono', monospace; }
.subs-th-share { width: 8rem; }
.subs-td-share { display: flex; align-items: center; gap: .4rem; }
.subs-share-track { flex: 1; height: 6px; background: rgba(var(--tint-rgb),.06); border-radius: 3px; overflow: hidden; }
.subs-share-fill { display: block; height: 100%; background: var(--brand); opacity: .7; }
.subs-share-val { flex: 0 0 2.8rem; text-align: right; font-family: 'Space Mono', monospace; font-size: .66rem; color: var(--muted); }

/* One line against the rest, on the same log axis as the fleet distribution:
   "412 of 2,008" does not say how far from the median a line is. */
.subs-vs-axis { position: relative; height: 46px; margin: .8rem 0 .2rem; }
.subs-vs-track { position: absolute; left: 0; right: 0; top: 8px; height: 4px; border-radius: 2px; background: linear-gradient(90deg, rgba(var(--tint-rgb),.06), rgba(var(--brand-rgb),.35)); }
.subs-vs-tick { position: absolute; top: 0; transform: translateX(-50%); }
.subs-vs-tick::before { content: ''; display: block; width: 2px; height: 20px; margin: 0 auto; background: var(--muted); }
.subs-vs-tick-label { display: block; margin-top: .2rem; font-size: .66rem; color: var(--muted); white-space: nowrap; transform: translateX(-50%); margin-left: 50%; }
.subs-vs-tick.is-mine::before { width: 3px; height: 26px; background: var(--brand); }
.subs-vs-tick.is-mine .subs-vs-tick-label { color: var(--brand); font-weight: 700; }
.subs-vs-tick.is-p99::before { background: var(--status-warn); }

/* Ranking rows are clickable; make that visible without a hover-only cue. */
.subs-row-click { cursor: pointer; }
.subs-row-click:hover td { background: rgba(var(--tint-rgb),.05); }

/* ── One subscriber, one line ──────────────────────────────────────────────
   A dual-stack customer holds a delegated IPv6 prefix and a CGNAT IPv4
   address, exported by two different routers. Everything below exists so the
   dashboard shows that as ONE row with two facets, not as two subscribers. */

/* Identity cell: the customer first, the key that represents them second. */
.subs-line { display: flex; flex-direction: column; gap: .1rem; min-width: 0; }
.subs-line-name { font-size: .8rem; color: var(--text); overflow: hidden; text-overflow: ellipsis; }
.subs-line-key { font-family: 'Space Mono', monospace; font-size: .72rem; color: var(--text-faint); overflow: hidden; text-overflow: ellipsis; }
.subs-line-key.is-unidentified { font-family: inherit; font-style: italic; opacity: .8; }

/* Which families the line actually holds - the badge, and the split inside
   the share bar, answer the same question at two zoom levels. */
.subs-stack {
  display: inline-block; font-family: 'Space Mono', monospace; font-size: .66rem;
  padding: .1rem .35rem; border-radius: 3px; letter-spacing: .03em;
  background: rgba(var(--tint-rgb),.08); color: var(--muted);
}
.subs-stack.is-dual { background: rgba(var(--brand-rgb),.16); color: var(--brand); }
[data-theme="light"] .subs-stack.is-dual { background: rgba(var(--brand-rgb),.08); }
.subs-stack.is-v4 { background: rgba(var(--tint-rgb),.1); color: var(--ip-v4); }
.subs-stack.is-v6 { background: rgba(var(--ip-v6-rgb),.16); color: var(--ip-v6); }
.subs-th-stack, .subs-td-stack { width: 3.4rem; text-align: center; }

.subs-share-fill.is-split { display: flex; background: none; opacity: 1; }
.subs-share-v4 { display: block; height: 100%; background: var(--ip-v4); opacity: .75; }
.subs-share-v6 { display: block; height: 100%; background: var(--ip-v6); opacity: .75; }
.subs-share-legend { display: flex; align-items: center; gap: .3rem 1rem; flex-wrap: wrap; margin-top: .45rem; font-size: .66rem; color: var(--text-faint); }
.subs-share-legend span { display: flex; align-items: center; gap: .3rem; }
.subs-share-legend-note { color: var(--text-faint); }
.subs-pop-dot.is-dual { background: var(--brand); }
.subs-pop-dot.is-v4 { background: var(--ip-v4); }
.subs-pop-dot.is-v6 { background: var(--ip-v6); }

/* Address families as a donut: three shares of one population is the one
   shape a pie reads well. Drawn by the dashboard's shared donut renderer, so
   it carries the same hover tooltip as the CDN and conversation pies. */
.subs-pie-donut { flex: 0 0 auto; gap: 0; }
.subs-pie-pct { font-family: 'Space Mono', monospace; font-size: .66rem; color: var(--text-faint); margin-left: .2rem; }

/* Where the base physically sits. Two bars per row on one scale each: how
   many lines the VLAN authenticated, and how much they moved. The inner
   segment of the first is the part of that VLAN flow actually measured. */
.subs-vlan-row { display: grid; grid-template-columns: minmax(6rem, 12rem) minmax(4rem, 1fr) 3.4rem minmax(4rem, 1fr) 4.4rem 4.4rem; align-items: center; gap: .5rem; padding: .3rem 0; }
.subs-vlan-row.is-server { grid-template-columns: minmax(6rem, 1fr) minmax(4rem, 1fr) 3.4rem 4.4rem; }
.subs-vlan-label { display: flex; flex-direction: column; gap: .05rem; font-family: 'Space Mono', monospace; font-size: .78rem; color: var(--text); min-width: 0; }
.subs-vlan-meta { font-family: inherit; font-size: .7rem; color: var(--text-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.subs-vlan-track { height: 9px; background: rgba(var(--tint-rgb),.06); border-radius: 5px; overflow: hidden; }
.subs-vlan-fill { display: block; height: 100%; background: var(--brand); opacity: .55; }
.subs-vlan-fill.is-traffic { background: var(--ip-v6); opacity: .6; }
.subs-vlan-active { display: block; height: 100%; background: var(--brand); opacity: 1; }
.subs-vlan-lines { text-align: right; font-family: 'Space Mono', monospace; font-size: .78rem; color: var(--text); }
.subs-vlan-bytes, .subs-vlan-per { text-align: right; font-family: 'Space Mono', monospace; font-size: .74rem; color: var(--muted); }
.subs-vlan-per { color: var(--text-faint); }
.subs-vlan-legend { display: flex; gap: 1rem; flex-wrap: wrap; margin-top: .7rem; font-size: .72rem; color: var(--text-faint); }
.subs-vlan-legend span { display: flex; align-items: center; gap: .3rem; }
@media (max-width: 900px) {
  /* Bars go before numbers on a narrow card, and the column count follows
     them: a grid with more children than tracks wraps into a second row. */
  .subs-vlan-row { grid-template-columns: minmax(5rem, 1fr) 3.2rem 4.2rem 4.2rem; }
  .subs-vlan-row.is-server { grid-template-columns: minmax(5rem, 1fr) 3.2rem 4.2rem; }
  .subs-vlan-row .subs-vlan-track { display: none; }
}

/* Numbers the operator must not read as complete. */
.subs-warns { display: flex; flex-direction: column; gap: .35rem; margin-top: .6rem; }
.subs-warn {
  font-size: .76rem; line-height: 1.5; color: var(--muted);
  border-left: 2px solid var(--status-warn); padding: .35rem .6rem;
  background: rgba(var(--status-warn-rgb),.06); border-radius: 3px;
}
.subs-warn.is-danger { border-left-color: var(--status-error); background: rgba(var(--status-error-rgb),.06); }
.subs-warn.is-note { border-left-color: rgba(var(--tint-rgb),.25); background: rgba(var(--tint-rgb),.04); }
.subs-warn-link { color: var(--brand); text-decoration: underline; }

/* Drill-down header: every key the line folds, so the operator can see that
   the prefix and the CGNAT address are one customer. */
.subs-d-stack { flex: 0 0 auto; }
.subs-d-keys { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; margin-bottom: .7rem; }
.subs-d-keys-label { font-size: .66rem; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.subs-key {
  font-family: 'Space Mono', monospace; font-size: .66rem; color: var(--text);
  padding: .12rem .4rem; border: 1px solid var(--border); border-radius: 3px;
  background: rgba(var(--tint-rgb),.04);
}

/* Narrow workspaces drop columns rather than scroll sideways: the average
   rates go first, since the totals next to them say the same thing. */
@media (max-width: 1200px) {
  .subs-tbl .subs-col-avg { display: none; }
}
@media (max-width: 980px) {
  .subs-th-share { width: 5.5rem; }
  .subs-share-val { flex: 0 0 2.4rem; }
}

/* A KPI whose caveat is a sentence, not a bar: coverage read as a score bar
   invited "we are failing 47%", when a router carrying transit can never
   attribute all of its traffic to customers. */
.subs-kpi-note { font-size: .78rem; line-height: 1.4; color: var(--text-faint); }
/* Counts inside a note line on the authenticated card: the number carries
   the meaning, the label after it is faint like the rest of the note. */
.subs-kpi-note b { font-family: 'Space Mono', monospace; font-weight: 600; color: var(--text); }

/* Connected customers against the load they put on the network: two units on
   one time axis, so the head-count rides its own right-hand scale. */
.subs-hero-svg { width: 100%; height: 230px; display: block; }
.subs-hero-svg, .subs-percust-svg, .subs-spark-svg { cursor: crosshair; }
.subs-hero-area { fill: rgba(var(--brand-rgb),.13); stroke: none; }
.subs-hero-line { fill: none; stroke: var(--brand); stroke-width: 1.8; }
.subs-hero-cust { fill: none; stroke: var(--status-warn); stroke-width: 1.6; stroke-dasharray: 5 3; }
.subs-hero-partial { opacity: .3; stroke-dasharray: 3 3; }
.subs-hero-axis-r { fill: var(--status-warn); font-size: 10.5px; font-family: 'Space Mono', monospace; text-anchor: start; }
.subs-legend-dashed { border-bottom: 2px dashed var(--status-warn); }

/* Sub-chart under the hero: the same window divided by the head-count. */
.subs-sub-block { margin-top: .7rem; border-top: 1px solid var(--border); padding-top: .5rem; }
.subs-sub-title { display: block; font-size: .66rem; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); margin-bottom: .25rem; }
.subs-percust-svg { width: 100%; height: 70px; display: block; }
.subs-spark-svg { width: 100%; height: 64px; display: block; }
.subs-spark-area { fill: rgba(var(--brand-rgb),.12); stroke: none; }
.subs-spark-line { fill: none; stroke: var(--brand); stroke-width: 1.6; }
.subs-spark-line.is-v6 { stroke: var(--ip-v6); }
.subs-spark-area.is-v6 { fill: rgba(var(--ip-v6-rgb),.12); }

/* IPv6 in the base: deployment, consumption and who still forces IPv4. */
.subs-v6-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); gap: 1rem 1.4rem; }
/* The funnel labels are whole sentences ("3,597 with a delegated prefix"),
   not the 4.2rem bucket names .subs-dist-label was sized for. */
#subs-v6-funnel .subs-dist-label { flex: 1 1 auto; text-transform: none; letter-spacing: 0; font-size: .74rem; }
#subs-v6-funnel .subs-dist-track { flex: 0 0 6rem; }
#subs-v6-funnel .subs-dist-val { flex: 0 0 3rem; }
.subs-v6-cell { min-width: 0; }
.subs-v6-cons-row { display: flex; align-items: center; gap: .55rem; padding: .3rem 0; }
.subs-v6-bar { flex: 1; display: flex; height: 10px; border-radius: 5px; overflow: hidden; background: rgba(var(--tint-rgb),.06); }
.subs-v6-seg { display: block; height: 100%; }
.subs-v6-seg.is-v6 { background: var(--ip-v6); opacity: .8; }
.subs-v6-seg.is-v4 { background: var(--ip-v4); opacity: .6; }
.subs-dist-fill.is-v6 { background: var(--ip-v6); opacity: .8; }
.subs-dist-fill.is-warn { background: var(--status-warn); opacity: .85; }

/* Per-customer IPv6 share as a histogram: an average hides a base split
   between customers that never touch v6 and customers almost fully on it. */
.subs-hist { display: flex; align-items: flex-end; gap: 2px; height: 74px; }
.subs-hist-col { flex: 1; display: flex; align-items: flex-end; height: 100%; background: rgba(var(--tint-rgb),.04); border-radius: 2px 2px 0 0; }
.subs-hist-fill { display: block; width: 100%; background: var(--ip-v6); opacity: .75; border-radius: 2px 2px 0 0; }
.subs-hist-x { display: flex; justify-content: space-between; font-size: .66rem; color: var(--text-faint); margin-top: .25rem; }

.subs-v6-asn-head { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; margin-bottom: .5rem; }
.subs-v6-asns { display: grid; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); gap: .5rem; }
.subs-v6-asn-card { display: flex; flex-direction: column; gap: .22rem; padding: .45rem .55rem; background: rgba(var(--tint-rgb),.04); border-left: 2px solid var(--ip-v4); border-radius: 3px; }
.subs-v6-asn-name { font-size: .74rem; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.subs-v6-asn-pct { font-family: 'Space Mono', monospace; font-size: .72rem; color: var(--muted); }
.subs-v6-asn-pct.is-low { color: var(--status-warn); }
.subs-v6-asn-track { height: 5px; background: rgba(var(--tint-rgb),.08); border-radius: 3px; overflow: hidden; }
.subs-v6-asn-fill { display: block; height: 100%; background: var(--ip-v6); opacity: .8; }
.subs-v6-asn-bytes { font-family: 'Space Mono', monospace; font-size: .68rem; color: var(--text-faint); }

/* Outliers absorbed the movers card: five kinds on one bar scale. */
.subs-mover-badge.is-gone { background: rgba(var(--text-muted-rgb),.2); color: var(--muted); }
.subs-mover-badge.is-upload { background: rgba(var(--status-info-rgb),.18); color: var(--status-info); }
.subs-mover-badge.is-lostv6 { background: rgba(var(--status-error-rgb),.16); color: var(--status-error); }
[data-theme="light"] .subs-mover-badge.is-up { background: rgba(var(--status-warn-rgb),.08); }
[data-theme="light"] .subs-mover-badge.is-new { background: rgba(var(--ip-v6-rgb),.08); }
[data-theme="light"] .subs-mover-badge.is-upload { background: rgba(var(--status-info-rgb),.08); }
[data-theme="light"] .subs-mover-badge.is-lostv6 { background: rgba(var(--status-error-rgb),.08); }
.subs-mover-fill.is-gone { background: rgba(var(--text-muted-rgb),.5); }
.subs-mover-fill.is-upload { background: var(--status-info); }
.subs-mover-fill.is-lostv6 { background: var(--status-error); }
.subs-pop-dot.is-gone { background: rgba(var(--text-muted-rgb),.5); }
.subs-pop-dot.is-upload { background: var(--status-info); }
.subs-pop-dot.is-lostv6 { background: var(--status-error); }

/* Where the base is: VLAN customer counts carry their IPv6 adoption. Four
   columns here, not the six of the full VLANs screen - the overview card
   answers "how many and how much IPv6", not the traffic breakdown. */
.subs-where .subs-vlan-row { grid-template-columns: minmax(6rem, 12rem) minmax(4rem, 1fr) 4.4rem 3.4rem; }
.subs-vlan-v6 { text-align: right; font-family: 'Space Mono', monospace; font-size: .78rem; color: var(--ip-v6); }
.subs-vlan-v6.is-low { color: var(--status-warn); }
@media (max-width: 900px) {
  /* The bar is hidden on a narrow card, so the track count drops with it. */
  .subs-where .subs-vlan-row { grid-template-columns: minmax(5rem, 1fr) 4.2rem 3.4rem; }
}

/* PPPoE servers tab. Every panel reads one payload in bits per second, so the
   rules here are layout only - no colour carries meaning that the numbers do
   not already carry. */
.subs-pp-grid { align-items: start; }
.subs-pp-card { display: flex; flex-direction: column; }

/* KPI strip: six cells on one row, wrapping to three on a narrow card. */
.subs-pp-kpi { display: grid; grid-template-columns: repeat(6, 1fr); gap: .9rem; margin-top: .2rem; }
.subs-pp-kpi-cell { display: flex; flex-direction: column; gap: .15rem; min-width: 0; }
.subs-pp-kpi-val { font-family: 'Space Mono', monospace; font-size: 1.28rem; line-height: 1.15; color: var(--text); }
.subs-pp-kpi-val.is-hot { color: var(--brand); }
.subs-pp-kpi-label { font-size: .72rem; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.subs-pp-kpi-sub { font-size: .68rem; color: var(--text-faint); }
.subs-pp-source { margin-top: .8rem; font-size: .68rem; color: var(--text-faint); }

/* Donut: outer ring is the interfaces, inner ring the servers they sit on. */
.subs-pp-donut { position: relative; display: flex; justify-content: center; }
.subs-pp-donut-svg { width: 100%; max-width: 300px; height: auto; display: block; }
.subs-pp-donut-center { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  display: flex; flex-direction: column; align-items: center; gap: .1rem; pointer-events: none; text-align: center; }
.subs-pp-donut-big { font-family: 'Space Mono', monospace; font-size: 1.15rem; color: var(--text); }
.subs-pp-donut-cap { font-size: .66rem; color: var(--text-faint); }
/* Legend columns are sized to their content, not stretched: a 1fr name column
   pushed the rate and the head count to the far edge of a wide card, and the
   operator had to sweep the whole row to pair a name with its numbers. */
.subs-pp-legend { margin-top: .8rem; display: flex; flex-direction: column; gap: .1rem; }
.subs-pp-leg-row { display: grid; grid-template-columns: 10px minmax(6rem, max-content) 5.6rem 5.6rem 7rem;
  gap: .6rem; align-items: center; font-size: .74rem; padding: .16rem .3rem;
  border-radius: 4px; cursor: default; }
.subs-pp-leg-row.is-hot { background: rgba(var(--tint-rgb),.06); }
.subs-pp-leg-dot { width: 10px; height: 10px; border-radius: 2px; }
.subs-pp-leg-name { font-family: 'Space Mono', monospace; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.subs-pp-leg-val { font-family: 'Space Mono', monospace; text-align: right; color: var(--text); }
.subs-pp-leg-val, .subs-pp-leg-cust, .subs-pp-leg-per { white-space: nowrap; }
.subs-pp-leg-cust, .subs-pp-leg-per { font-family: 'Space Mono', monospace; text-align: right; }
.subs-pp-leg-cust { color: var(--text); }
.subs-pp-leg-per { color: var(--text-faint); }
.subs-pp-note { margin-top: .7rem; font-size: .68rem; color: var(--text-faint); }

.subs-pp-stack-svg { width: 100%; height: 160px; display: block; cursor: crosshair; }
.subs-pp-foot { display: flex; flex-wrap: wrap; gap: 1rem; margin-top: .7rem; font-size: .7rem; color: var(--muted); }
.subs-pp-foot-val { font-family: 'Space Mono', monospace; color: var(--text); }

/* Growth: three plots, one 14-day axis, side by side at full card width. */
.subs-pp-growth { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.2rem; }
.subs-pp-plot { display: flex; flex-direction: column; min-width: 0; }
.subs-pp-plot-head { display: flex; justify-content: space-between; align-items: baseline; gap: .5rem; }
.subs-pp-plot-title { font-size: .74rem; color: var(--text); }
.subs-pp-plot-unit { font-size: .66rem; color: var(--text-faint); }
.subs-pp-plot-svg { width: 100%; display: block; margin-top: .3rem; cursor: crosshair; }
.subs-pp-plot-foot { display: flex; justify-content: space-between; align-items: baseline;
  gap: .4rem; font-family: 'Space Mono', monospace; font-size: .68rem; color: var(--text-faint); }
.subs-pp-plot-delta { color: var(--status-ok); }
.subs-pp-plot-delta.is-down { color: var(--status-warn); }

/* Lens: sort chips, then one interface per row at full card width. */
.subs-pp-chips { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; margin-bottom: .8rem; }
.subs-pp-chip-label { font-size: .7rem; color: var(--muted); margin-right: .2rem; }
.subs-pp-chip { font: inherit; font-size: .72rem; padding: .2rem .6rem; border-radius: 999px;
  border: 1px solid var(--border); background: transparent; color: var(--muted); cursor: pointer; }
.subs-pp-chip:hover { color: var(--text); border-color: var(--brand); }
.subs-pp-chip.on { background: rgba(var(--tint-rgb),.1); border-color: var(--brand); color: var(--text); }
.subs-pp-chip-count { margin-left: auto; font-size: .68rem; color: var(--text-faint); }
.subs-pp-cols { display: grid; grid-template-columns: 1fr; row-gap: .3rem; }
.subs-pp-row { display: grid;
  grid-template-columns: 28px 132px minmax(6rem, 1.2fr) 2fr 78px 76px 56px 44px;
  gap: .6rem; align-items: center; font-size: .78rem; min-width: 0; }
.subs-pp-row:not(.is-head):hover { background: rgba(var(--tint-rgb),.05); }
.subs-pp-row.is-head { font-size: .66rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted); border-bottom: 1px solid var(--border); padding-bottom: .25rem; margin-bottom: .2rem; }
.subs-pp-row .ta-r { text-align: right; }
.subs-pp-i { font-family: 'Space Mono', monospace; font-size: .66rem; color: var(--text-faint); text-align: right; }
.subs-pp-if { font-family: 'Space Mono', monospace; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.subs-pp-desc { color: var(--text-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.subs-pp-track { height: 9px; background: rgba(var(--tint-rgb),.06); border-radius: 3px; overflow: hidden; }
.subs-pp-fill { display: block; height: 100%; background: var(--brand); opacity: .75; }
.subs-pp-perval { font-family: 'Space Mono', monospace; text-align: right; color: var(--text); }
.subs-pp-down { font-family: 'Space Mono', monospace; text-align: right; color: var(--text); }
.subs-pp-auth { font-family: 'Space Mono', monospace; text-align: right; color: var(--text-faint); }
.subs-pp-v6 { font-family: 'Space Mono', monospace; text-align: right; color: var(--ip-v6); }
.subs-pp-v6.is-low { color: var(--status-warn); }

@media (max-width: 1100px) {
  .subs-pp-kpi { grid-template-columns: repeat(3, 1fr); row-gap: 1rem; }
  .subs-pp-growth { grid-template-columns: 1fr; }
}
@media (max-width: 900px) {
  .subs-pp-kpi { grid-template-columns: repeat(2, 1fr); }
  .subs-pp-row { grid-template-columns: 24px 1fr 78px 76px 56px 44px; }
  .subs-pp-row .subs-pp-desc, .subs-pp-row .subs-pp-track { display: none; }
  /* The header cells carry no class, so they drop by position or the header
     stops lining up with the rows under it. */
  .subs-pp-row.is-head > span:nth-child(3),
  .subs-pp-row.is-head > span:nth-child(4) { display: none; }
  /* The name column stays a name column: at this width it is the head count
     that has to survive, so the per-customer rate goes instead. */
  .subs-pp-leg-row { grid-template-columns: 10px 1fr 5.4rem 5.4rem; }
  .subs-pp-leg-per { display: none; }
}

/* This window against the same customer in the one before it. */
.subs-habit { font-family: 'Space Mono', monospace; font-size: .66rem; }
.subs-habit.is-up { color: var(--status-warn); }
.subs-habit.is-down { color: var(--status-info); }
.subs-habit.is-flat { color: var(--text-faint); }
.subs-habit.is-new { color: var(--ip-v6); }
.subs-col-habit { width: 4rem; text-align: right; }
@media (max-width: 1200px) {
  .subs-tbl .subs-col-habit { display: none; }
}

/* Loading mascot: one penguin, three scenes (static/mascot.js injects the
   SVG). ssh = typing on a laptop wired to a router, fish = fishing packets
   out of a data stream, run = chasing a packet along the wire. .egm-long is
   set past 12 s: sweat drop, the message says it is still working. */
.eg-mascot {
  --egm-body: #27314a;
  --egm-rim: rgba(var(--brand-rgb), 0.35);
  --egm-belly: #f3f6fa;
  --egm-ink: #131a28;
  --egm-beak: #f4a340;
  --egm-cheek: #ff8fa3;
  --egm-ice: #e3f3f7;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 10px 0;
}
[data-theme="light"] .eg-mascot { --egm-rim: transparent; --egm-ice: #d5ebf0; }
.eg-mascot svg { width: 160px; height: 90px; overflow: visible; flex: 0 0 auto; }
.eg-mascot-mini { padding: 0; gap: 4px; }
.eg-mascot-mini svg { width: 80px; height: 45px; }
.eg-mascot-row { flex-direction: row; gap: 10px; }
.eg-mascot-panel { justify-content: center; }
.eg-mascot strong { color: var(--text); }

/* Penguin parts */
.egm-body { fill: var(--egm-body); stroke: var(--egm-rim); stroke-width: 1; }
.egm-belly { fill: var(--egm-belly); }
.egm-pupil { fill: var(--egm-ink); }
.egm-glint { fill: #fff; }
.egm-cheek { fill: var(--egm-cheek); opacity: 0.45; }
.egm-beak { fill: var(--egm-beak); stroke: var(--egm-beak); stroke-width: 1.2; stroke-linejoin: round; }
.egm-scarf { fill: var(--accent); }
.egm-flipper { fill: var(--egm-ink); opacity: 0.85; }
.egm-foot { fill: var(--egm-beak); }
.egm-sweat { fill: #7cc8ff; opacity: 0; }
.egm-eye, .egm-flipper, .egm-foot, .egm-scarf-tail, .egm-peng, .egm-sweat,
.egm-fish, .egm-bobber, .egm-chase, .egm-code { transform-box: fill-box; }
.egm-eye { transform-origin: center; animation: egm-blink 3.6s infinite; }
.egm-scarf-tail { transform-origin: 90% 0%; animation: egm-flutter 0.9s ease-in-out infinite; }
.egm-long .egm-sweat { animation: egm-drip 1.4s ease-in infinite; }

/* Shared scenery */
.egm-track { stroke: rgba(var(--brand-rgb), 0.25); stroke-width: 2; stroke-linecap: round; }
.egm-packets, .egm-wire-flow {
  stroke: var(--accent-hot);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-dasharray: 3 14;
  fill: none;
  animation: egm-flow 0.9s linear infinite;
}

/* run: waddle toward the packet */
.egm-scene-run .egm-peng { transform-origin: 50% 100%; animation: egm-bob 0.45s ease-in-out infinite; }
.egm-scene-run .egm-flipper { transform-origin: 80% 10%; animation: egm-wag 0.45s ease-in-out infinite; }
.egm-scene-run .egm-foot-a { animation: egm-step 0.45s ease-in-out infinite; }
.egm-scene-run .egm-foot-b { animation: egm-step 0.45s ease-in-out infinite reverse; }
.egm-speed line {
  stroke: rgba(var(--brand-rgb), 0.45);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-dasharray: 8 12;
  animation: egm-flow 0.6s linear infinite;
}
.egm-chase rect { fill: var(--accent-hot); }
.egm-chase path { fill: none; stroke: var(--egm-body); stroke-width: 1.3; stroke-linejoin: round; }
.egm-chase { transform-origin: 50% 100%; animation: egm-hop 0.9s ease-in-out infinite; }

/* fish: packets swim by, the bobber bites now and then */
.egm-water { fill: rgba(var(--brand-rgb), 0.07); }
.egm-wave {
  fill: none;
  stroke: rgba(var(--brand-rgb), 0.5);
  stroke-width: 1.5;
  stroke-dasharray: 6 4;
  animation: egm-flow 1.8s linear infinite;
}
.egm-ice { fill: var(--egm-ice); stroke: rgba(var(--brand-rgb), 0.35); stroke-width: 1; }
.egm-scene-fish .egm-peng { transform-origin: 50% 100%; animation: egm-sway 3s ease-in-out infinite; }
.egm-rod { stroke: #8a6a45; stroke-width: 2; stroke-linecap: round; }
.egm-line { stroke: rgba(var(--brand-rgb), 0.55); stroke-width: 0.8; }
.egm-bobber circle { fill: #fff; stroke: var(--egm-ink); stroke-width: 0.6; }
.egm-bobber path { fill: var(--accent-hot); }
.egm-bobber { animation: egm-bite 4s ease-in-out infinite; }
.egm-fish path { fill: var(--accent); }
.egm-fish-a { animation: egm-swim 3.4s linear infinite; }
.egm-fish-b { animation: egm-swim 4.6s linear infinite 1.7s; opacity: 0; }
.egm-fish-b path { fill: var(--accent-hot); }

/* ssh: typing, the router answers */
.egm-scene-ssh .egm-peng { transform-origin: 50% 100%; animation: egm-nod 0.9s ease-in-out infinite; }
.egm-scene-ssh .egm-flipper { transform-origin: 80% 10%; animation: egm-tap 0.3s ease-in-out infinite; }
.egm-screen { fill: rgba(var(--surface-deep-rgb), 0.95); stroke: rgba(var(--brand-rgb), 0.55); stroke-width: 1.2; }
.egm-prompt { fill: none; stroke: var(--accent-hot); stroke-width: 1.2; stroke-linecap: round; stroke-linejoin: round; }
.egm-code { fill: var(--accent); transform-origin: 0% 50%; animation: egm-typing 2.6s steps(6) infinite; }
.egm-code-2 { animation-delay: 0.4s; opacity: 0.7; }
.egm-code-3 { animation-delay: 0.8s; opacity: 0.5; }
.egm-cursor { fill: var(--accent-hot); animation: egm-cursor 0.8s steps(1) infinite; }
.egm-kbd { fill: rgba(var(--brand-rgb), 0.25); stroke: rgba(var(--brand-rgb), 0.55); stroke-width: 1; stroke-linejoin: round; }
.egm-wire { fill: none; stroke: rgba(var(--brand-rgb), 0.3); stroke-width: 2; }
.egm-wire-flow { stroke-width: 2.4; stroke-dasharray: 2 7; }
.egm-antenna { stroke: rgba(var(--brand-rgb), 0.55); stroke-width: 1.6; stroke-linecap: round; }
.egm-router { fill: var(--bg-alt); stroke: rgba(var(--brand-rgb), 0.55); stroke-width: 1.2; }
.egm-led { fill: var(--status-ok); animation: egm-led 1.2s steps(1) infinite; }
.egm-led-2 { animation-delay: 0.4s; }
.egm-led-3 { animation-delay: 0.8s; fill: var(--accent-hot); }

.egm-msg {
  color: var(--muted);
  font-size: 0.85rem;
  min-height: 1.2em;
  text-align: center;
  transition: opacity 0.3s;
}
.egm-msg.egm-fade { opacity: 0; }
.egm-long .egm-msg { color: var(--text); }
.egm-pct {
  color: var(--text-faint);
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
  min-width: 2.6em;
  text-align: center;
}
#eg-loading-pill {
  position: fixed;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 900;
  padding: 6px 14px;
  border: 1px solid rgba(var(--brand-rgb), 0.25);
  background: rgba(var(--surface-deep-rgb), 0.92);
  border-radius: 12px;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.25);
}
#eg-loading-pill.hidden { display: none; }
#eg-loading-pill .egm-msg { font-size: 0.8rem; white-space: nowrap; }
.ddp-empty .eg-mascot, .dh-console-empty .eg-mascot, .ddp-detail-loading .eg-mascot { margin: 0 auto; }

@keyframes egm-flow { to { stroke-dashoffset: 17; } }
@keyframes egm-bob {
  0%, 100% { transform: translateY(0) rotate(-2deg); }
  50% { transform: translateY(-3px) rotate(2deg); }
}
@keyframes egm-step {
  0%, 100% { transform: translate(-2px, 0); }
  50% { transform: translate(2px, -1.5px); }
}
@keyframes egm-wag {
  0%, 100% { transform: rotate(-10deg); }
  50% { transform: rotate(14deg); }
}
@keyframes egm-flutter {
  0%, 100% { transform: rotate(0deg); }
  50% { transform: rotate(14deg); }
}
@keyframes egm-blink {
  0%, 92%, 100% { transform: scaleY(1); }
  95% { transform: scaleY(0.1); }
}
@keyframes egm-drip {
  0% { opacity: 0; transform: translateY(0); }
  20% { opacity: 1; }
  100% { opacity: 0; transform: translateY(8px); }
}
@keyframes egm-hop {
  0%, 100% { transform: translateY(0) scaleY(1); }
  40% { transform: translateY(-7px) scaleY(1.05); }
  80% { transform: translateY(0) scaleY(0.9); }
}
@keyframes egm-sway {
  0%, 100% { transform: rotate(-1.5deg); }
  50% { transform: rotate(1.5deg); }
}
@keyframes egm-bite {
  0%, 60%, 100% { transform: translateY(0); }
  30% { transform: translateY(1.2px); }
  72% { transform: translateY(4px); }
  82% { transform: translateY(-1px); }
}
@keyframes egm-swim {
  0% { transform: translateX(150px); opacity: 0; }
  12% { opacity: 1; }
  85% { opacity: 1; }
  100% { transform: translateX(66px); opacity: 0; }
}
@keyframes egm-nod {
  0%, 100% { transform: rotate(0deg); }
  50% { transform: rotate(2.5deg); }
}
@keyframes egm-tap {
  0%, 100% { transform: rotate(-6deg); }
  50% { transform: rotate(12deg); }
}
@keyframes egm-typing {
  0% { transform: scaleX(0); }
  70%, 100% { transform: scaleX(1); }
}
@keyframes egm-cursor { 50% { opacity: 0; } }
@keyframes egm-led { 50% { opacity: 0.25; } }
@media (prefers-reduced-motion: reduce) {
  .eg-mascot *, .eg-mascot .egm-sweat { animation: none !important; }
  .egm-long .egm-sweat { opacity: 1; }
}

/* ── Admin CRUD pages (users, companies, incident actions) ──────────
   One pattern for the three list pages: a header row with a "+ New" button,
   a create card that is hidden until asked for, a read-only table, and an
   edit card that opens under the row being edited. Type-specific fields carry
   `data-types` and static/admin.js hides the ones the selected type does not
   use. The old per-page `.create-bar` / inline-edit markup is gone. */
.admin-content [hidden] { display: none !important; }

.adm-create { margin-bottom: 18px; }
.adm-count { font-family: 'Space Mono', monospace; font-size: 11px; color: var(--muted); }
.ck-section-hd .adm-hd-right { display: flex; align-items: center; gap: 14px; margin-left: auto; }

.frm-textarea {
  background: var(--surface-raised); border: 1px solid rgba(var(--brand-rgb),.15);
  border-radius: 4px; color: var(--text);
  font-family: 'Space Mono', monospace; font-size: 12px; line-height: 1.45;
  padding: 6px 10px; outline: none; resize: vertical; min-height: 64px;
}
.frm-textarea:focus { border-color: var(--text-faint); }
.frm-hint { font-family: 'Space Mono', monospace; font-size: 10.5px; color: var(--text-faint); line-height: 1.4; }
.frm-check { display: flex; align-items: center; gap: 8px; min-height: 34px; font-size: 13px; color: var(--text); cursor: pointer; }
.frm-check input[type="checkbox"] { width: 15px; height: 15px; min-height: 0; padding: 0; margin: 0; accent-color: var(--accent); }
.frm-checks { display: flex; flex-direction: column; gap: 2px; }
.frm-checks .frm-check { min-height: 26px; }
.frm-inline { display: flex; align-items: center; gap: 8px; }
.frm-inline .frm-input, .frm-cell .frm-inline .frm-input { width: 90px; }
.frm-inline .unit { font-family: 'Space Mono', monospace; font-size: 11px; color: var(--muted); }
.frm-cell .frm-input, .frm-cell .frm-select, .frm-cell .frm-textarea { width: 100%; }

/* Condition rows on Incident Actions: label left, toggles right. A toggle is
   a checkbox inside a pill so the whole pill is the click target, and the
   count seen in the stats window sits next to its label. */
.frm-rows { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: 14px 18px; align-items: start; padding: 14px 20px; }
.frm-rows > .label { margin: 0; padding-top: 8px; }
@media (max-width: 640px) { .frm-rows { grid-template-columns: 1fr; gap: 6px; } }
.frm-pills { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.frm-pills + .frm-hint { display: block; margin-top: 6px; }
.frm-pills > .frm-hint { margin-left: 10px; }
.frm-pill {
  display: inline-flex; align-items: center; gap: 8px; min-height: 30px; padding: 4px 10px;
  border: 1px solid rgba(var(--brand-rgb),.18); border-radius: 4px; background: var(--surface-raised);
  color: var(--text); font-size: 13px; cursor: pointer; user-select: none;
}
.frm-pill:hover { border-color: var(--text-faint); }
.frm-pill input[type="checkbox"], .frm-pill input[type="radio"] { width: 14px; height: 14px; min-height: 0; padding: 0; margin: 0; accent-color: var(--accent); }
.frm-pill:has(input:checked) { border-color: rgba(var(--brand-rgb),.55); background: rgba(var(--brand-rgb),.12); }
.frm-pill:has(input:focus-visible) { outline: 1px solid var(--accent); outline-offset: 1px; }
.frm-pill .n { font-family: 'Space Mono', monospace; font-size: 10.5px; color: var(--text-faint); }
.frm-pill.idle:not(:has(input:checked)) { color: var(--muted); }
.frm-pills + .frm-pills { margin-top: 8px; }
.frm-rows:not([hidden]) ~ .frm-rows, [data-types] > .frm-rows:first-child { padding-top: 0; }
/* Incident Actions: action types grouped by what they touch, a fixed
   condition read as a sentence, sized fields, the live match count. */
.frm-groups { display: flex; flex-wrap: wrap; gap: 8px 28px; }
.frm-group > .frm-hint { display: block; margin-bottom: 4px; text-transform: uppercase; letter-spacing: .06em; }
.frm-groups + .frm-hint { display: block; margin-top: 6px; }
.frm-hint.frm-warn { color: var(--warning); white-space: pre-line; }
.frm-pill:has(input:disabled) { opacity: .45; cursor: not-allowed; }
.frm-fixed { display: block; padding-top: 7px; font-size: 13px; color: var(--text); }
.frm-top { align-items: flex-start; }
.frm-stack { display: flex; flex-direction: column; gap: 4px; }
.frm-w { width: 100%; max-width: 300px; }
.frm-w-sm { width: 100%; max-width: 160px; }
.frm-w-lg { width: 100%; max-width: 606px; }
.panel-head [data-match] { color: var(--text); margin: 0 auto 0 16px; }
.frm-stack .frm-textarea { width: 300px; }
.panel-head [data-match].none { color: var(--warning); }
.frm-pill:has(input:disabled) { cursor: default; }
/* Readiness of the router a route action targets; admin.js shows the one picked. */
.frm-status { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 4px; }
.frm-grid-4 { grid-template-columns: repeat(auto-fill, minmax(200px, 270px)); }
@media (max-width: 900px) { .frm-grid-4 { grid-template-columns: 1fr 1fr; } }
.frm-span-2 { grid-column: span 2; }
.frm-span-all { grid-column: 1 / -1; }
/* An open create card has its own submit; the header "New" would be a
   second button with the same name. */
.ck-section:has(> .adm-create:not([hidden])) > .ck-section-hd [data-toggle],
.adm-create:not([hidden]) + .setcard:has(> .adm-empty) { display: none; }
.frm-footer { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 20px; border-top: 1px solid rgba(var(--brand-rgb),.08); }
.frm-footer .left { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text); }
.frm-footer .left input[type="checkbox"] { accent-color: var(--accent); }
.frm-footer .right { display: flex; gap: 10px; margin-left: auto; }

/* Rows */
.logtable td.adm-actions { text-align: right; white-space: nowrap; }
.adm-row-actions { display: inline-flex; gap: 6px; }
.btn-danger-sm { color: var(--error) !important; border-color: rgba(var(--status-error-rgb),.3) !important; }
.btn-danger-sm:hover { border-color: var(--error) !important; }
tr.adm-editing td { background: rgba(var(--brand-rgb),.06) !important; border-bottom-color: transparent; }
.adm-edit-row > td { padding: 0 !important; background: rgba(var(--brand-rgb),.03); }
.adm-edit-row .setcard { border: 0; border-radius: 0; box-shadow: none; background: transparent; }
.adm-edit-row .frm-footer { border-top-color: rgba(var(--brand-rgb),.12); }
.adm-empty { padding: 2rem 1.4rem; color: var(--muted); font-size: .9rem; text-align: center; }
.adm-trunc { display: inline-block; max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }
.adm-yes { color: var(--accent); }
.adm-no { color: var(--text-faint); }
.adm-sub { display: block; font-size: 10.5px; color: var(--text-faint); margin-top: 2px; }
.adm-pill {
  display: inline-block; padding: 2px 8px; border-radius: 4px;
  font-family: 'Rajdhani', sans-serif; font-size: 11px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase;
  border: 1px solid rgba(var(--brand-rgb),.2); color: var(--muted);
}
.adm-pill.on { color: var(--accent); border-color: rgba(var(--brand-rgb),.4); }

/* Incident action type badges (also on the run log) */
.type-badge {
  display: inline-block; padding: 2px 8px; border-radius: 4px;
  font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px;
  color: #fff; background: #6c757d; white-space: nowrap;
}
.type-badge.discord    { background: #5865F2; }
.type-badge.telegram    { background: #26A5E4; }
.type-badge.webhook     { background: #6c757d; }
.type-badge.email       { background: #28a745; }
.type-badge.ssh_command { background: #fd7e14; }
.type-badge.bgp_route_announce { background: #e83e8c; }
.type-badge.flowspec    { background: #6f42c1; }
.type-badge.push        { background: #17a2b8; }
.type-badge.botnet_block  { background: #c82333; }
.type-badge.scanner_block { background: #a71d5d; }
.type-badge.customer_quarantine { background: #8a4b08; }
.act-ok { color: var(--success, #2ecc71); }
.act-fail { color: var(--error, #e74c3c); }
.act-ok small, .act-fail small { color: var(--muted); font-size: .66rem; }

/* /admin/status background tasks: 20 loops in two columns instead of one tall list. */
.statlist-tasks { display: grid; grid-template-columns: 1fr 1fr; column-gap: 2.5rem; }
.statlist-tasks .statrow { padding: 7px 0; gap: 12px; }
.statlist-tasks .statrow:nth-child(2) { border-top: none; }
.statlist-tasks .statrow .k b { font-size: 12.5px; }
.statlist-tasks .statrow .v { font-size: 12px; white-space: nowrap; }

/* Admin shell: the sidebar runs the full viewport height, the page header is
   one pattern (title + one-line subtitle left, count + primary action right). */
.admin-panel { min-height: calc(100vh - 212px); }
.csb-admin .csb-section { padding: 12px 0 8px; }
.csb-admin .csb-heading { padding: 0 12px 6px 16px; }
.adm-page-hd { margin-bottom: 1rem; align-items: center; }
.adm-page-hd h3 { font-size: 22px; }
.adm-page-hd .sub { font-size: 12.5px; color: var(--muted); margin: 3px 0 0; }


/* A link at 90% of its nominal speed while an attack crossed it is the
   answer to "which link did we saturate", so it stops being muted text. */
.mit-bar-sat { color: var(--error); font-weight: 600; }

/* The customer name is the whole answer in the volume panel, and a PPPoE
   login is longer than the 18ch a prefix needs. It takes the room; the rate
   and duration column shrinks to its text. */
#mit-hl-volume .sb-cols, #mit-out-dests .sb-cols { grid-template-columns: minmax(0, 1fr) auto; }
#mit-hl-volume .lc-ip, #mit-out-dests .lc-ip {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
  color: var(--text-primary); font-weight: 600;
}
/* A login read as a tint on a tint: the accent colour sat on a filled bar.
   The text is the content here, so the fill drops back to a background and
   stays there on hover. */
#mit-hl-volume .lc-as, #mit-out-dests .lc-as { color: var(--text-primary); opacity: .7; }
#mit-hl-volume .sb-fill, #mit-hl-volume .sb-row:hover .sb-fill,
#mit-out-dests .sb-fill, #mit-out-dests .sb-row:hover .sb-fill { opacity: .3; }

/* A share bar that filters the table below says so on hover. */
.sb-row-click { cursor: pointer; }
.sb-row-click:hover .sb-track { outline: 1px solid rgba(var(--tint-rgb), .45); }
/* The row whose filter is currently on. */
.sb-row.is-on .sb-track, .bar-row.is-on .bar-track {
  outline: 1px solid var(--brand);
}
/* A value its facet did not pick, while that facet has a pick: faded, and
   still clickable, since a click adds it to the pick. */
.bar-row.is-off, .sb-row.is-off, .dash-pie-legend-row.is-off { opacity: .45; }
svg path[data-idx].is-off { opacity: .3; }
svg path[data-idx].is-on.is-dim, svg circle[data-idx].is-on.is-dim { opacity: 1; }
/* A row that no surviving incident produced. The bar keeps its length: the
   panel still measures the whole window, it only stops claiming relevance. */

/* A panel that reads flow and not detections says so under its title, so a
   click that drills is not mistaken for a click that filters. */

/* Active filters. Each chip removes its own value; the last one clears every
   facet at once. */
.mit-f-chips { margin: .7rem 0 1rem; }
/* A chip is a button, and the base button rule uppercases its text and pads
   it to 36px. A customer login is not uppercase, so the value opts out. */
.mit-chip-x, .mit-chip-clear {
  font: inherit; cursor: pointer; min-height: 0; letter-spacing: 0;
  transition: border-color .12s, background .12s;
}
.mit-chip-x .mit-chip-v { text-transform: none; letter-spacing: 0; }
.mit-chip-x:hover, .mit-chip-clear:hover {
  border-color: var(--brand); background: rgba(var(--tint-rgb),.07);
}
.mit-chip-rm { font-size: .7rem; color: var(--muted); line-height: 1; }
.mit-chip-x:hover .mit-chip-rm { color: var(--error); }
.mit-chip-clear {
  font-size: .68rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted);
}

/* Amplifier drill-down: the panel swaps the donut for one service's
   destinations, so it needs a header with a way back. */

/* Mitigation received/sent views: folded settings cards, sender ranking */
.mit-fold > summary { cursor: pointer; list-style: none; }
.mit-fold > summary::-webkit-details-marker { display: none; }
.mit-fold > summary h3 { display: inline; margin: 0; }
.mit-fold > summary::before { content: '\25B8'; color: var(--muted); margin-right: .4rem; }
.mit-fold[open] > summary::before { content: '\25BE'; }
.mit-fold[open] > summary { margin-bottom: .6rem; }
.mit-kpi-win { color: var(--muted); font-weight: 400; text-transform: none; }
/* A window the period selector does not move stands out, like a Grafana override. */
.mit-kpi-win[data-win="fixed"] { color: var(--accent); cursor: help; }
.mit-note { display: block; margin-top: .5rem; font-size: .74rem; }
.mit-row-spark { width: 120px; height: 22px; overflow: visible; vertical-align: middle; }
.mit-dot-active {
  display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  background: var(--status-error); margin-right: .4rem; vertical-align: middle;
}
.mit-trend { font-size: .7rem; color: var(--muted); margin-left: .3rem; white-space: nowrap; }
.mit-trend-up { color: var(--status-error); }
.mit-trend-down { color: var(--status-ok); }
.mit-sender-intel { cursor: pointer; white-space: nowrap; border-bottom: 1px dotted var(--muted); }
.mit-pat {
  font-family: 'Space Mono', monospace; font-size: .66rem; white-space: nowrap;
  border: 1px solid var(--line); color: var(--muted); border-radius: 3px; padding: 1px 5px;
}
.mit-pat-allday { border-color: var(--status-warn); color: var(--status-warn); }

/* ── Command workspace: dashboard language ──
   READ/WRITE forms and results share the surfaces of the Flow, Security and
   Mitigation tabs (var(--line), var(--bg-alt), 6px radius, muted uppercase
   titles, 34px controls). The command type is a quiet chip; only WRITE keeps
   a colour. Scoped to the two workspace panes so admin pages keep theirs. */
#wp-input .meta-card[data-meta-card="command"] {
  padding: 2px 0 4px;
  border: 0;
  background: none;
  gap: 10px;
}
#wp-input .meta-card[data-meta-card="command"] strong {
  font-family: "Rajdhani", sans-serif;
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: .02em;
}
#wp-input .meta-card[data-meta-card="command"] small { font-size: .82rem; }
#wp-input .command-type-pill {
  padding: 1px 7px;
  border-radius: 3px;
  border-color: var(--line);
  background: none;
  color: var(--muted);
  font-size: .66rem;
}
#wp-input .command-type-pill.command-theme-write {
  color: var(--write-accent);
  border-color: rgba(var(--cmd-write-rgb),.4);
}

#wp-input .field { gap: 5px; }
#wp-input .field span,
#wp-input .meta-label {
  font-size: .68rem;
  color: var(--muted);
}
#wp-input input,
#wp-input select,
#wp-input textarea {
  min-height: 34px;
  padding: 5px 10px;
  border: 1px solid var(--line);
  border-radius: 3px;
  background: var(--bg-alt);
  font-size: .85rem;
  box-shadow: none;
}
#wp-input textarea { min-height: 84px; }
#wp-input input:focus,
#wp-input select:focus,
#wp-input textarea:focus { outline: none; border-color: var(--accent); }
#wp-input input::placeholder,
#wp-input textarea::placeholder { color: var(--text-faint); }
#wp-input .checklist-filter-input { padding-left: 30px; }
#wp-input .checklist-filter::after { left: 10px; bottom: 10px; }

/* Segmented toggles: the active segment is the accent, never the write green. */
#wp-input .dynamic-toggle-group,
#wp-input .dynamic-toggle-button,
#output-content .type-filter-toggle { min-height: 34px; }
#wp-input .dynamic-toggle-button,
#output-content .type-filter-toggle {
  padding: 0 12px;
  border-color: var(--line);
  background: var(--bg-alt);
  font-family: inherit;
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .06em;
}
#wp-input .dynamic-toggle-button:first-child,
#output-content .type-filter-toggle:first-child { border-radius: 3px 0 0 3px; }
#wp-input .dynamic-toggle-button:last-child,
#output-content .type-filter-toggle:last-child { border-radius: 0 3px 3px 0; }
#wp-input .dynamic-toggle-button.is-active,
#output-content .type-filter-toggle.is-active {
  color: var(--accent);
  border-color: rgba(var(--brand-rgb),.45);
  background: rgba(var(--brand-rgb),.1);
  box-shadow: none;
}

/* Buttons: the outlined accent button of the dashboard toolbars. */
#wp-input #submit-button,
#wp-input .dynamic-submit-button {
  min-height: 34px;
  padding: 0 16px;
  border: 1px solid var(--accent);
  border-radius: 3px;
  background: rgba(var(--brand-rgb),.1);
  color: var(--accent);
  font-family: inherit;
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .04em;
  transition: background .15s;
}
#wp-input #submit-button:hover,
#wp-input .dynamic-submit-button:hover { background: rgba(var(--brand-rgb),.22); filter: none; }
#wp-input #submit-button:disabled { opacity: .4; cursor: not-allowed; }
#wp-input .checklist-action {
  min-height: 30px;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: 3px;
  color: var(--muted);
  font-family: inherit;
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .06em;
}
#wp-input .checklist-action:hover { color: var(--accent); border-color: var(--accent); }

/* Surfaces: one card style for the inline detail, the peer picker, the
   loading panels, the summary strip, tables and KPIs. */
#wp-input .field-inline-details,
#wp-input .checkbox-list,
#wp-input .table-wrap,
#wp-input .loading-panel,
#wp-output .loading-panel,
#output-content .summary-grid,
#output-content .table-wrap,
#output-content .tb-kpi,
#output-content .tb-panel {
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--bg-alt);
}
#output-content .summary-grid:has(+ .summary-grid) { border-radius: 6px 6px 0 0; }
#output-content .summary-grid + .summary-grid { border-radius: 0 0 6px 6px; }
#output-content .table-wrap .table-filters {
  border-bottom-color: var(--line);
  background: none;
}
#output-content .table-wrap input,
#output-content .table-wrap select {
  min-height: 34px;
  padding: 5px 10px;
  border: 1px solid var(--line);
  border-radius: 3px;
  background: var(--bg);
  font-size: .85rem;
}
#output-content .result-table th,
#wp-input .result-table th,
#wp-input .checkbox-table-head {
  color: var(--muted);
  font-size: .68rem;
  background: var(--bg-alt);
}
#output-content .result-table th,
#output-content .result-table td,
#wp-input .result-table th,
#wp-input .result-table td { border-bottom-color: var(--line); }
#wp-input .result-table th { background: none; }
#output-content .rt-summary { border-color: var(--line); border-left-color: var(--rt-state); border-radius: 6px; background: var(--bg-alt); }
#output-content .tb-verdict { border-radius: 3px; }

/* Code blocks keep the sunken tone, lose the 320px floor and the tint. */
#wp-output .terminal,
#wp-input .terminal {
  min-height: 0;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 6px;
  font-size: .84rem;
}
#output-content .terminal-empty {
  padding: 2rem 0;
  border: 0;
  background: none;
  color: var(--muted);
  font-family: inherit;
  font-size: .78rem;
  text-align: center;
}
#output-content .raw-output summary {
  color: var(--muted);
  font-size: .72rem;
  font-weight: 600;
}
#output-content .raw-output summary:hover { color: var(--accent); }
#wp-output .status { font-size: .82rem; }

/* Live command plan (write commands): a card with the plan as its body. */
#wp-input .command-plan-live {
  padding: .8rem 1rem;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--bg-alt);
}
#wp-input .command-plan-header { margin-bottom: 6px; }
#wp-input .command-plan-copy { margin: 2px 0 0; font-size: .82rem; }
#wp-input .command-plan-live .status { margin-bottom: 8px; font-size: .78rem; }
#wp-input .command-plan-live .terminal { padding: 10px 12px; }

/* Security -> Actions (_actRender): the rules on the wire, each family's
   switch and the log, one place. Green applied, yellow would have, red
   failed; every other outcome stays in muted ink. */
.bot-hero.act-hero { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) {
  .bot-hero.act-hero { grid-template-columns: repeat(2, 1fr); }
  .act-hero .bot-hero-seg:nth-child(2) { border-top: 0; }
  .act-hero .bot-hero-seg:nth-child(even) { border-left: 1px solid var(--line); }
}
.act-hero .bot-hero-row { flex-wrap: wrap; }
.act-v-ok { color: var(--status-ok); }
.act-v-warn { color: var(--status-warn); }
.act-v-err { color: var(--status-error); }
.act-modes { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; margin-bottom: 1.2rem; }
.act-modes[hidden] { display: none; }
.act-modes-l { font-size: .68rem; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); margin-right: .3rem; }
.act-mode { display: inline-flex; align-items: center; gap: .35rem; padding: .25rem .6rem; border: 1px solid var(--line); border-radius: 6px; background: var(--bg-alt); font-size: .76rem; }
.act-mode b { font-weight: 600; }
.act-mode.is-none { color: var(--muted); }
.act-mode-link {
  width: auto; min-height: 0; height: auto; margin: 0; color: var(--text); font: inherit; font-size: .76rem;
  text-transform: none; letter-spacing: 0; cursor: pointer;
}
.act-mode-link:hover, .act-mode-link:focus-visible { border-color: var(--read-accent); outline: none; }
.act-tbl-wrap { overflow-x: auto; }
/* About 15 rules on screen, the rest scrolls under a header that stays */
@media (min-width: 901px) {
  .act-tbl-wrap { max-height: 34rem; overflow-y: auto; }
  .act-tbl thead th { position: sticky; top: 0; z-index: 1; background: var(--bg-alt); }
}
.act-tbl { width: 100%; border-collapse: collapse; font-size: .8rem; }
.act-tbl th { color: var(--muted); text-transform: uppercase; letter-spacing: .05em; font-size: .68rem; font-weight: 600; text-align: left; padding: .38rem .55rem; border-bottom: 1px solid var(--line); white-space: nowrap; }
.act-tbl td { padding: .3rem .55rem; border-bottom: 1px solid var(--border); vertical-align: middle; }
.act-tbl td:last-child { text-align: right; white-space: nowrap; }
/* Withdraw rests quiet and wakes on hover or focus, as on Botnet -> Blocks */
.act-tbl td:last-child .mit-fam-chip { opacity: .7; transition: opacity .12s; }
.act-tbl tr:hover td:last-child .mit-fam-chip, .act-tbl td:last-child .mit-fam-chip:focus { opacity: 1; }
.act-mono { font-family: 'Space Mono', monospace; font-size: .76rem; }
.act-dim { color: var(--muted); }
.act-fam { display: inline-block; padding: .05rem .45rem; border: 1px solid var(--border); border-radius: 4px; font-size: .68rem; white-space: nowrap; color: var(--text); }
.act-log-hd { display: flex; align-items: baseline; justify-content: space-between; gap: .8rem; flex-wrap: wrap; }
.act-filters { display: flex; align-items: center; gap: .35rem; flex-wrap: wrap; }
.act-chip { padding: .15rem .6rem; border: 1px solid var(--border); border-radius: 9px; background: transparent; color: var(--muted); font: inherit; font-size: .7rem; cursor: pointer; }
.act-chip:hover { border-color: var(--read-accent); color: var(--read-accent); }
.act-chip.is-on { border-color: var(--read-accent); color: var(--text); background: var(--bg-alt); }
.act-chip-sep { width: 1px; height: 1rem; background: var(--line); margin: 0 .2rem; }
.act-log-r { display: grid; grid-template-columns: 7.5rem 8px 6.5rem 7.5rem minmax(0, 1fr); align-items: center; gap: .6rem; padding: .32rem 0; border-bottom: 1px solid var(--border); font-size: .78rem; }
.act-log-r:last-child { border-bottom: 0; }
.act-log-r.is-applied .act-out { color: var(--status-ok); }
.act-log-r.is-would .act-out { color: var(--status-warn); }
.act-log-r.is-failed .act-out { color: var(--status-error); }
.act-log-r .act-out { color: var(--muted); }
.act-log-d { overflow-wrap: anywhere; }
.act-log-r .act-fam { justify-self: start; }
@media (max-width: 700px) {
  .act-log-r { grid-template-columns: auto 8px auto auto; }
  .act-log-d { grid-column: 1 / -1; }
}
/* The botnet blocks' band follows the family filter: off on any other
   family. !important: the hero shows and hides with the hidden attribute. */
#dash-tab-actions[data-fam="rtbh"] .act-blk,
#dash-tab-actions[data-fam="flowspec"] .act-blk,
#dash-tab-actions[data-fam="scanner"] .act-blk-bot { display: none !important; }
.act-goto { margin: 0 0 .75rem; }
.act-goto[hidden] { display: none; }
.act-fams { margin: -.6rem 0 1rem; }
/* The view switch over the family filter: two levels, the view first */
.act-views { margin-bottom: .8rem; }
.act-views + .act-fams { margin-top: 0; }
.act-fams:empty { display: none; }
.act-tbl .act-as { display: inline-block; vertical-align: bottom; max-width: 18rem; margin-left: .5rem; font-size: .7rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.act-log-more { padding-top: .5rem; font-size: .72rem; }
/* One colour per family: the timeline's bars, its legend and the tag's edge */
.act-c-botnet { fill: var(--cmd-read); background: var(--cmd-read); }
.act-c-scanner { fill: var(--emphasis); background: var(--emphasis); }
.act-c-flowspec { fill: var(--status-info); background: var(--status-info); }
.act-c-rtbh { fill: var(--status-neutral); background: var(--status-neutral); }
.act-c-quarantine { fill: var(--status-warn); background: var(--status-warn); }
.act-fam-botnet { border-color: rgba(var(--cmd-read-rgb), .6); }
.act-fam-scanner { border-color: rgba(var(--emphasis-rgb), .6); }
.act-fam-flowspec { border-color: rgba(var(--status-info-rgb), .6); }
.act-fam-rtbh { border-color: rgba(var(--status-neutral-rgb), .6); }
.act-fam-quarantine { border-color: rgba(var(--status-warn-rgb), .6); }
/* Timeline (_actRenderTl): applied above the line, removed below, failed on top */
.act-tl { display: block; width: 100%; height: 140px; }
.act-tl-axis { stroke: var(--chart-axis); stroke-width: 1; }
.act-tl .act-tl-dn { opacity: .5; }
.act-tl-fail { fill: var(--status-error); }
.act-tl-hit { fill: transparent; stroke: none; }
.act-tl-hit:hover { fill: rgba(var(--tint-rgb), .06); }
.act-tl-hit.is-live { stroke: var(--chart-crosshair); stroke-width: 1; stroke-dasharray: 3 3; }
.act-tl-x { display: flex; justify-content: space-between; font-size: .68rem; margin-top: .25rem; }
.act-tl-hint { font-size: .7rem; margin-top: .35rem; }
.act-tl-legend { display: flex; gap: .8rem; flex-wrap: wrap; font-size: .72rem; color: var(--muted); }
.act-tl-key { display: inline-flex; align-items: center; gap: .3rem; }
.act-tl-sw { display: inline-block; width: 10px; height: 10px; border-radius: 2px; }
.act-tl-sw-fail { background: var(--status-error); height: 4px; }
/* Table tools: search, bulk withdraw, refresh switch */
.act-tools { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.act-q { min-width: 14rem; padding: .3rem .6rem; border: 1px solid var(--border); border-radius: 6px; background: var(--bg-alt); color: var(--text); font: inherit; font-size: .78rem; }
.act-q:focus { outline: none; border-color: var(--read-accent); }
.act-q::placeholder { color: var(--text-faint); }
.act-autorf { display: inline-flex; align-items: center; gap: .3rem; font-size: .72rem; color: var(--muted); cursor: pointer; }
.act-ago { font-size: .7rem; }
#act-bulk[hidden] { display: none; }
#act-bulk-err { margin: .3rem 0; }
.act-th { padding: 0; border: 0; background: none; color: inherit; font: inherit; letter-spacing: inherit; text-transform: inherit; cursor: pointer; }
.act-th:hover { color: var(--read-accent); }
.act-th.is-asc::after { content: " \25B4"; }
.act-th.is-desc::after { content: " \25BE"; }
.act-sel-c { width: 1.6rem; }
.act-tbl td.act-sel-c, .act-tbl th.act-sel-c { padding-right: 0; }
/* The page-wide `input { min-height: 46px }` made each row 64 px tall */
.act-tbl .act-sel-c input { width: 14px; height: 14px; min-height: 0; margin: 0; padding: 0; vertical-align: middle; }
.act-row { cursor: pointer; }
.act-row:hover td { background: rgba(var(--tint-rgb), .03); }
.act-row.is-open td { background: var(--bg-alt); border-bottom-color: transparent; }
/* Customers and TTL: a thin bar under the figure */
.act-bar { display: inline-block; vertical-align: middle; width: 4.5rem; height: 4px; margin-left: .5rem; border-radius: 2px; background: rgba(var(--tint-rgb), .08); overflow: hidden; }
.act-bar i { display: block; height: 100%; background: var(--read-accent); }
.act-ttl i { background: var(--status-ok); }
.act-ttl.is-low i { background: var(--status-warn); }
/* Row detail (_actDetail) */
.act-det-tr td { background: var(--bg-alt); }
.act-det { padding: .4rem .2rem .6rem; }
.act-facts { display: grid; grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); gap: .5rem 1rem; margin: 0 0 .6rem; }
.act-facts dt { font-size: .66rem; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.act-facts dd { margin: .1rem 0 0; font-size: .8rem; overflow-wrap: anywhere; }
.act-det-h { font-size: .66rem; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); margin: .6rem 0 .3rem; }
.act-det-bars { display: block; max-width: 100%; height: 36px; }
.act-det-bars rect { fill: var(--read-accent); }
.act-det-links { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; margin-top: .6rem; }
.act-blk-since { display: flex; flex-direction: column; align-items: flex-start; gap: .25rem; font-size: .76rem; }
.act-chip.is-hot { color: var(--status-error); border-color: rgba(var(--status-error-rgb), .45); }
.act-tbl tr.act-det-tr td:last-child { text-align: left; white-space: normal; }
/* Under 900 px the table becomes one card per rule */
@media (max-width: 900px) {
  .act-q { min-width: 0; flex: 1 1 100%; }
  .act-tbl thead { display: none; }
  .act-tbl, .act-tbl tbody, .act-tbl tr, .act-tbl td { display: block; width: 100%; }
  .act-tbl tr.act-row { position: relative; padding: .6rem .7rem; margin-bottom: .5rem; border: 1px solid var(--border); border-radius: 8px; }
  .act-tbl tr.act-row.is-open { margin-bottom: 0; border-radius: 8px 8px 0 0; }
  .act-tbl tr.act-row td { display: flex; justify-content: space-between; align-items: baseline; gap: .8rem; padding: .2rem 0; border: 0; text-align: right; }
  .act-tbl tr.act-row td::before { content: attr(data-label); color: var(--muted); font-size: .66rem; text-transform: uppercase; letter-spacing: .05em; text-align: left; }
  .act-tbl tr.act-row td.act-target { display: block; text-align: left; padding-right: 2rem; }
  .act-tbl tr.act-row td.act-target::before { content: none; }
  .act-tbl tr.act-row td.act-target .act-as { display: block; max-width: 100%; margin-left: 0; }
  .act-tbl tr.act-row td.act-sel-c { position: absolute; top: .6rem; right: .7rem; width: auto; padding: 0; }
  .act-tbl tr.act-row td.act-sel-c::before, .act-tbl tr.act-row td.act-wd::before { content: none; }
  .act-tbl tr.act-row td.act-sel-c + td { padding-right: 2rem; }
  .act-tbl tr.act-row td.act-wd { justify-content: flex-end; }
  .act-tbl tr.act-row td.act-wd:empty { display: none; }
  .act-tbl td:last-child .mit-fam-chip { opacity: 1; }
  .act-tbl tr.act-row td .act-bar { margin-left: auto; width: 6rem; }
  .act-tbl tr.act-row td:has(.act-bar) { flex-wrap: wrap; }
  .act-tbl tr.act-det-tr { margin-bottom: .5rem; border: 1px solid var(--border); border-top: 0; border-radius: 0 0 8px 8px; }
  .act-tbl tr.act-det-tr td { padding: .4rem .7rem; }
}

/* ==========================================================================
   Per-device admin pages (Overview and Settings tabs)
   Rules that used to live inline in the six per-device templates.
   ========================================================================== */
.dev-sec { display: flex; flex-wrap: wrap; gap: .4rem; margin: 0 0 1.2rem; }
.dev-sec-link {
  font-family: 'Space Mono', monospace; font-size: .7rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); text-decoration: none; padding: .3rem .7rem; border-radius: 999px;
  border: 1px solid rgba(var(--brand-rgb),.15);
}
.dev-sec-link:hover { color: var(--accent); border-color: var(--text-muted); }
.dev-sec-body { display: block; scroll-margin-top: 16px; margin-bottom: 1.6rem; }
.dev-sec-body + .dev-sec-body { border-top: 1px solid rgba(var(--brand-rgb),.09); padding-top: 1.2rem; }
.ov-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 1rem; align-items: start; }
.ov-grid > .ck-section { min-width: 0; }
@media (max-width: 1100px) { .ov-grid { grid-template-columns: 1fr; } }

/* Device record form */
.form-cards { display: flex; flex-direction: column; gap: 1rem; }
.setrow .control input,
.setrow .control select { font-size: 13px; }
.form-cards .cmd-rw-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 440px)); gap: 1rem 18px; padding: 12px 20px; border: 0; }
#cmd-col-read, #cmd-col-write { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 0 12px; }
.cmd-col-hd { font-family: 'Rajdhani', sans-serif; font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase; margin-bottom: 8px; }
.cmd-col-hd.read  { color: var(--read-accent); }
.cmd-col-hd.write { color: var(--write-accent); }
.cmd-item { display: flex; align-items: center; gap: 6px; padding: 4px 0; font-size: 13px; cursor: pointer; color: var(--text); }
.cmd-item input[type="checkbox"] { width: 15px; height: 15px; min-height: 0; padding: 0; margin: 0; accent-color: var(--accent); }

/* Generated command blocks and their copy button */
.cmd-block { position: relative; margin-bottom: 1rem; }
.cmd-label { font-size: .72rem; color: var(--muted); margin-bottom: .35rem; display: block; }
.cmd-code {
  background: var(--surface-sunken);
  border: 1px solid var(--border); border-radius: 4px;
  padding: .75rem 1rem; padding-right: 4.5rem; font-family: 'Space Mono', monospace;
  font-size: .78rem; color: var(--text-primary); white-space: pre;
  overflow-x: auto; line-height: 1.65;
}
.copy-btn {
  position: absolute; top: 8px; right: 8px;
  padding: 3px 10px; font-family: inherit; font-size: .68rem; font-weight: 600;
  letter-spacing: .05em; cursor: pointer; border-radius: 3px;
  border: 1px solid rgba(var(--brand-rgb),.2); background: rgba(var(--surface-deep-rgb),.9);
  color: var(--muted); transition: color .15s, border-color .15s;
}
.cmd-label + .copy-btn { top: 28px; }
.copy-btn:hover, .copy-btn.copied { color: var(--accent); border-color: var(--text-muted); }
.setup-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
@media (max-width: 800px) { .setup-grid { grid-template-columns: 1fr; } }
.cmd-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; }
/* Half-width columns clip long config lines behind a scrollbar, so wrap
   them. Copy still ships the original text - it reads textContent. */
.cmd-grid .cmd-code { white-space: pre-wrap; }
@media (max-width: 1100px) { .cmd-grid { grid-template-columns: 1fr; } }

/* Live status rows and key-value strips */
.flow-status-row { display: flex; align-items: center; gap: .75rem; font-size: .85rem; }
.flow-kv { display: flex; gap: 1.5rem; flex-wrap: wrap; margin-top: .5rem; }
.flow-kv-item { font-size: .78rem; }
.flow-kv-key { color: var(--muted); font-size: .7rem; display: block; }
.flow-kv-val { font-family: 'Space Mono', monospace; color: var(--text); }
.bh-kv { display: flex; gap: 1.5rem; flex-wrap: wrap; }
.bh-kv-key { color: var(--muted); font-size: .7rem; display: block; }
.bh-kv-val { font-family: 'Space Mono', monospace; color: var(--text); font-size: .78rem; }
.peer-table { width: 100%; border-collapse: collapse; font-size: .74rem; margin-top: .6rem; }
.peer-table th { text-align: left; color: var(--muted); font-weight: 500; padding: .25rem .4rem; border-bottom: 1px solid rgba(var(--brand-rgb),.1); font-size: .68rem; text-transform: uppercase; letter-spacing: .06em; }
.peer-table td { padding: .22rem .4rem; border-bottom: 1px solid rgba(var(--brand-rgb),.05); font-family: 'Space Mono', monospace; color: var(--text); }
.peer-table tr:last-child td { border-bottom: none; }

/* Exporter form: sampling per family and direction, labelled field groups */
.sampling-rate-grid { display: grid; grid-template-columns: 1fr 1fr; gap: .4rem .8rem; }
.sampling-rate-cell { display: block; font-size: .7rem; color: var(--muted); }
.sampling-rate-cell code { display: block; margin-bottom: .15rem; }
/* Settings sub-tabs: one section shown at a time, the script sets `hidden`. */
.dev-sec-link.active { color: var(--accent); border-color: var(--accent); background: rgba(var(--brand-rgb),.08); }
/* Advanced drawer inside a card: a rule and one summary line, no box, so the
   essential fields above and the Save below it stay in view. */
.dev-adv { margin: 0; border: 0; border-top: 1px solid rgba(var(--brand-rgb),.09); border-radius: 0; background: transparent; }
.setcard > .dev-adv:first-child { border-top: 0; }
.dev-adv > summary { padding: 10px 20px; font-size: .78rem; color: var(--muted); }
.dev-adv > summary:hover, .dev-adv[open] > summary { color: var(--accent); }
.dev-adv > .bh-fold-body { padding: 0 0 6px; }
.dev-adv .cmd-rw-grid { margin-top: 4px; }

/* Readiness table */
.rd-summary { display: flex; gap: .6rem; flex-wrap: wrap; margin: .6rem 0 1rem; }
.rd-table { width: 100%; border-collapse: collapse; font-size: .8rem; }
.rd-table th { text-align: left; color: var(--muted); font-weight: 500; padding: .4rem .6rem; border-bottom: 1px solid rgba(var(--brand-rgb),.1); font-size: .68rem; text-transform: uppercase; letter-spacing: .06em; }
.rd-table td { padding: .5rem .6rem; border-bottom: 1px solid rgba(var(--brand-rgb),.05); vertical-align: top; }
.rd-table tr:last-child td { border-bottom: none; }
.rd-table tr.na td { color: var(--muted); }
.rd-evidence { color: var(--text); line-height: 1.4; }
.rd-items { margin: .3rem 0 0; padding-left: 1rem; font-family: 'Space Mono', monospace; font-size: .72rem; color: var(--muted); }
.rd-fix summary { font-size: .68rem; color: var(--muted); cursor: pointer; margin-top: .35rem; }
.rd-fix pre { white-space: pre-wrap; font-family: 'Space Mono', monospace; font-size: .7rem; margin: .25rem 0 0; background: var(--surface-sunken); border: 1px solid var(--border); border-radius: 4px; padding: .5rem .7rem; }
.rd-fix .lbl { font-size: .66rem; color: var(--muted); margin-top: .3rem; }
.ov-grid > .ck-section:nth-child(3):last-child { grid-column: 1 / -1; }
