:root {
  --bg: #07090a;
  --panel: #0f1315;
  --panel-2: #141a1d;
  --panel-3: #1a2226;
  --border: #1e2629;
  --border-soft: #171d20;
  --text: #e7eef1;
  --text-dim: #9daab1;
  --muted: #6d7d85;
  --green: #2fe08a;
  --green-2: #17b86b;
  --green-glow: rgba(47, 224, 138, 0.14);
  --red: #ff5064;
  --red-glow: rgba(255, 80, 100, 0.14);
  --amber: #ffb545;
  --blue: #4fb8f7;
  --purple: #a97bff;
  --radius: 12px;
  --radius-sm: 8px;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body { height: 100%; }

body {
  background:
    radial-gradient(1200px 600px at 78% -10%, rgba(47, 224, 138, 0.06), transparent 60%),
    radial-gradient(900px 500px at 8% 110%, rgba(79, 184, 247, 0.045), transparent 60%),
    var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 13px;
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}

::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #232c30; border-radius: 8px; }
::-webkit-scrollbar-thumb:hover { background: #2e393e; }

button { font-family: inherit; color: inherit; border: none; background: none; cursor: pointer; }
input, select { font-family: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }

.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.up { color: var(--green); }
.down { color: var(--red); }
.dim { color: var(--muted); }

/* ── shell ─────────────────────────────────────────── */
.app {
  display: grid;
  grid-template-columns: 236px 1fr;
  height: 100vh;
}

.sidebar {
  background: linear-gradient(180deg, #0d1113, #0a0d0f);
  border-right: 1px solid var(--border-soft);
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  padding: 14px 12px 20px;
}

/* An anchor, not a heading. Clicking the logo goes to your dashboard, which is
   what every other product on the web has trained people to expect. *Which*
   dashboard depends on the account type, so ui.js owns the href — see
   landingFor(). */
.brand {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 4px 6px 16px;
  color: inherit;
  text-decoration: none;
  border-radius: 10px;
  transition: opacity 120ms ease;
}
a.brand:hover { opacity: 0.85; }
a.brand:hover .brand-mark { box-shadow: 0 0 22px rgba(47, 224, 138, 0.55); }
/* Keyboard users need to see where they are. The sidebar already has 12px of
   side padding, so the ring has room and nothing shifts. */
a.brand:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }

.brand-mark {
  width: 30px; height: 30px;
  display: grid; place-items: center;
  border-radius: 9px;
  background: linear-gradient(145deg, var(--green), #0d8a52);
  box-shadow: 0 0 18px rgba(47, 224, 138, 0.35);
}
.brand-mark svg { width: 17px; height: 17px; }
.brand-name { font-size: 15px; font-weight: 800; letter-spacing: 0.06em; }
.brand-name span { color: var(--green); }
.brand-sub { font-size: 8.5px; letter-spacing: 0.18em; color: var(--muted); text-transform: uppercase; }

.node-card {
  background: linear-gradient(150deg, #16211c, #101617);
  border: 1px solid #24352c;
  border-radius: var(--radius);
  padding: 11px 12px;
  margin-bottom: 12px;
  position: relative;
  overflow: hidden;
}
.node-card::after {
  content: "";
  position: absolute; inset: 0;
  background: radial-gradient(120px 60px at 90% 0%, var(--green-glow), transparent 70%);
  pointer-events: none;
}
.node-card-top { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.node-icon {
  width: 26px; height: 26px; border-radius: 7px;
  display: grid; place-items: center;
  background: #0e1512; border: 1px solid #244032;
}
.node-icon svg { width: 13px; height: 13px; color: var(--green); }
.node-label { font-size: 11px; font-weight: 700; letter-spacing: 0.02em; }
.node-delta { font-size: 10px; color: var(--green); font-weight: 600; }
.node-value { font-family: var(--mono); font-size: 19px; font-weight: 600; letter-spacing: -0.01em; }
.node-value small { font-size: 10px; color: var(--muted); font-weight: 500; margin-left: 3px; }

.search {
  display: flex; align-items: center; gap: 8px;
  background: #0c1012;
  border: 1px solid var(--border);
  border-radius: 9px;
  padding: 8px 10px;
  margin-bottom: 14px;
}
.search svg { width: 13px; height: 13px; color: var(--muted); flex-shrink: 0; }
.search input {
  background: none; border: none; outline: none;
  font-size: 12px; width: 100%; color: var(--text);
}
.search input::placeholder { color: var(--muted); }

.nav-group { margin-bottom: 3px; }
.nav-item {
  display: flex; align-items: center; gap: 10px;
  width: 100%;
  padding: 8px 10px;
  border-radius: 8px;
  font-size: 12.5px;
  color: var(--text-dim);
  transition: background 0.14s, color 0.14s;
}
.nav-item:hover { background: #131a1d; color: var(--text); }
.nav-item svg { width: 14px; height: 14px; flex-shrink: 0; opacity: 0.8; }
.nav-item .chev { margin-left: auto; width: 11px; height: 11px; transition: transform 0.18s; }
.nav-item.open .chev { transform: rotate(180deg); }
.nav-item.active {
  background: linear-gradient(90deg, rgba(47, 224, 138, 0.14), rgba(47, 224, 138, 0.03));
  color: var(--green);
  border: 1px solid rgba(47, 224, 138, 0.25);
  padding: 7px 9px;
}
.nav-item.active svg { opacity: 1; }

.nav-sub { padding: 2px 0 6px 12px; display: none; }
.nav-sub.open { display: block; }
.nav-sub a {
  display: flex; align-items: center; gap: 9px;
  padding: 6px 10px; border-radius: 7px;
  font-size: 12px; color: var(--muted);
}
.nav-sub a:hover { color: var(--text); background: #121819; }
.nav-sub a.is-active { color: var(--green); }
.nav-sub svg { width: 12px; height: 12px; }

.nav-divider { height: 1px; background: var(--border-soft); margin: 10px 4px; }
.nav-label {
  font-size: 9px; letter-spacing: 0.16em; text-transform: uppercase;
  color: #4d5a60; padding: 10px 10px 6px; font-weight: 700;
}

/* ── main ──────────────────────────────────────────── */
.main { display: flex; flex-direction: column; overflow: hidden; }

.topbar {
  height: 54px;
  border-bottom: 1px solid var(--border-soft);
  display: flex; align-items: center; gap: 14px;
  padding: 0 18px;
  flex-shrink: 0;
  background: rgba(10, 13, 15, 0.7);
  backdrop-filter: blur(8px);
}
.topbar h1 { font-size: 14px; font-weight: 650; letter-spacing: -0.01em; }
.topbar .crumb { color: var(--muted); font-size: 12px; }
.topbar-right { margin-left: auto; display: flex; align-items: center; gap: 9px; }

.pill {
  display: inline-flex; align-items: center; gap: 6px;
  height: 28px; padding: 0 11px;
  border: 1px solid var(--border);
  border-radius: 20px;
  font-size: 11.5px; color: var(--text-dim);
  background: #0e1214;
  transition: border-color 0.15s, color 0.15s;
}
.pill:hover { border-color: #2c3a3f; color: var(--text); }
.pill svg { width: 12px; height: 12px; }
.pill.live { border-color: rgba(47, 224, 138, 0.3); color: var(--green); background: rgba(47, 224, 138, 0.07); }

.dot { width: 6px; height: 6px; border-radius: 50%; background: var(--green); }
.dot.pulse { animation: pulse 1.6s infinite; }
@keyframes pulse {
  0%, 100% { opacity: 1; box-shadow: 0 0 0 0 rgba(47, 224, 138, 0.5); }
  50% { opacity: 0.55; box-shadow: 0 0 0 5px rgba(47, 224, 138, 0); }
}

.btn {
  height: 30px; padding: 0 14px;
  border-radius: 8px; font-size: 12px; font-weight: 600;
  display: inline-flex; align-items: center; gap: 7px;
  transition: filter 0.15s, background 0.15s;
}
.btn-ghost { border: 1px solid var(--border); color: var(--text-dim); }
.btn-ghost:hover { border-color: #2c3a3f; color: var(--text); }
.btn-primary { background: linear-gradient(180deg, var(--green), var(--green-2)); color: #04180e; }
.btn-primary:hover { filter: brightness(1.08); }

.avatar {
  width: 30px; height: 30px; border-radius: 9px;
  background: linear-gradient(145deg, #23303a, #16202a);
  border: 1px solid var(--border);
  display: grid; place-items: center;
  font-size: 11px; font-weight: 700; color: var(--text-dim);
}

.content { flex: 1; overflow-y: auto; padding: 14px 18px 24px; }

.grid-top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 332px;
  gap: 14px;
  margin-bottom: 14px;
}

/* ── panels ────────────────────────────────────────── */
.panel {
  background: var(--panel);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
}
.panel-head {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border-soft);
}
.panel-title { font-size: 12.5px; font-weight: 650; }
.panel-head .right { margin-left: auto; display: flex; align-items: center; gap: 6px; }

/* ── main chart ────────────────────────────────────── */
.chart-panel { display: flex; flex-direction: column; min-height: 430px; }
.chart-head { padding: 13px 15px 8px; }
.chart-id { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.asset-badge {
  display: flex; align-items: center; gap: 8px;
  padding: 5px 11px 5px 6px;
  background: #131a1d; border: 1px solid var(--border);
  border-radius: 22px;
}
.asset-badge .ico {
  width: 21px; height: 21px; border-radius: 50%;
  background: linear-gradient(145deg, #1f2b31, #131a1e);
  display: grid; place-items: center;
}
.asset-badge .ico svg { width: 11px; height: 11px; color: var(--green); }
.asset-badge b { font-size: 13px; letter-spacing: 0.02em; }
.asset-badge svg.chev { width: 11px; height: 11px; color: var(--muted); }

.headline {
  font-family: var(--mono);
  font-size: 25px; font-weight: 600; letter-spacing: -0.02em;
  color: var(--green);
  display: flex; align-items: baseline; gap: 7px;
}
.headline .unit { font-size: 12px; color: var(--text-dim); font-family: var(--sans); font-weight: 500; }
.headline.alarm { color: var(--red); }

.chart-meta {
  display: flex; gap: 18px; flex-wrap: wrap;
  padding: 8px 0 2px;
  font-size: 10.5px; color: var(--muted);
}
.chart-meta b { color: var(--text-dim); font-weight: 600; }
.chart-meta .k { font-family: var(--mono); }

.chart-tools { margin-left: auto; display: flex; align-items: center; gap: 5px; }
.tool {
  width: 27px; height: 27px; border-radius: 7px;
  border: 1px solid var(--border-soft);
  display: grid; place-items: center;
  color: var(--muted);
  transition: background 0.14s, color 0.14s;
}
.tool:hover { background: #161d20; color: var(--text); }
.tool svg { width: 13px; height: 13px; }

.seg { display: flex; gap: 3px; background: #0d1113; border: 1px solid var(--border-soft); border-radius: 8px; padding: 3px; }
.seg button {
  padding: 4px 9px; border-radius: 6px;
  font-size: 11px; font-weight: 600; color: var(--muted);
  transition: background 0.14s, color 0.14s;
}
.seg button:hover { color: var(--text-dim); }
.seg button.on { background: #1c2529; color: var(--text); }

.chart-body { flex: 1; position: relative; padding: 4px 8px 0; min-height: 250px; }
.chart-body canvas { width: 100% !important; }

.chart-legend {
  display: flex; gap: 16px; padding: 6px 15px 10px;
  font-size: 10.5px; color: var(--muted);
}
.chart-legend i { width: 8px; height: 8px; border-radius: 2px; display: inline-block; margin-right: 6px; }

.chart-nodes {
  display: flex; gap: 4px; overflow-x: auto;
  padding: 8px 12px 11px;
  border-top: 1px solid var(--border-soft);
  scrollbar-width: none;
}
.chart-nodes::-webkit-scrollbar { display: none; }
.node-chip {
  flex-shrink: 0;
  display: flex; align-items: center; gap: 7px;
  padding: 5px 10px; border-radius: 7px;
  font-size: 10.5px; color: var(--muted);
  border: 1px solid transparent;
  white-space: nowrap;
  transition: background 0.14s, color 0.14s;
}
.node-chip:hover { background: #141a1d; color: var(--text-dim); }
.node-chip.on { background: #141d1a; border-color: rgba(47, 224, 138, 0.22); color: var(--text); }
.node-chip .v { font-family: var(--mono); }

/* ── console (right rail) ──────────────────────────── */
.console { display: flex; flex-direction: column; }
.console-tabs {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 4px; padding: 6px;
  background: #0c1012;
  border-bottom: 1px solid var(--border-soft);
  border-radius: var(--radius) var(--radius) 0 0;
}
.console-tabs button {
  padding: 8px; border-radius: 8px;
  font-size: 12px; font-weight: 600; color: var(--muted);
}
.console-tabs button.on { background: var(--panel-3); color: var(--text); }
.console-body { padding: 13px; display: flex; flex-direction: column; gap: 13px; }

.field-label {
  font-size: 9px; letter-spacing: 0.15em; text-transform: uppercase;
  color: var(--muted); font-weight: 700; margin-bottom: 6px;
}

.verdict { display: grid; grid-template-columns: 1fr 1fr; gap: 7px; }
.verdict button {
  height: 42px; border-radius: 9px;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  font-size: 12.5px; font-weight: 800; letter-spacing: 0.06em;
  transition: filter 0.15s, opacity 0.15s;
}
.verdict svg { width: 15px; height: 15px; }
.v-threat { background: linear-gradient(180deg, #ff5f57, #d63c4e); color: #2a0207; opacity: 0.32; }
.v-clear { background: linear-gradient(180deg, var(--green), var(--green-2)); color: #04180e; opacity: 0.32; }
.v-threat.on, .v-clear.on { opacity: 1; }
.v-threat.on { box-shadow: 0 0 22px rgba(255, 80, 100, 0.3); }
.v-clear.on { box-shadow: 0 0 22px rgba(47, 224, 138, 0.24); }

.input-row {
  display: flex; align-items: center; gap: 8px;
  background: #0c1012; border: 1px solid var(--border);
  border-radius: 9px; padding: 9px 10px;
}
.input-row .lead {
  width: 19px; height: 19px; border-radius: 50%;
  background: #1b2429; display: grid; place-items: center;
  font-size: 9px; color: var(--green); flex-shrink: 0;
}
.input-row input {
  background: none; border: none; outline: none; width: 100%;
  font-family: var(--mono); font-size: 13px;
}
.input-row .stepper { display: flex; gap: 4px; margin-left: auto; }
.input-row .stepper button {
  padding: 3px 8px; border-radius: 6px;
  background: #171f23; font-size: 10.5px; color: var(--text-dim); font-family: var(--mono);
}
.input-row .stepper button:hover { background: #202b30; }

.dual { display: grid; grid-template-columns: 1fr 1.15fr; gap: 9px; align-items: end; }
.big-metric {
  font-family: var(--mono);
  font-size: 26px; font-weight: 600; letter-spacing: -0.02em;
  line-height: 1.05;
}
.big-metric.risk-low { color: var(--green); }
.big-metric.risk-med { color: var(--amber); }
.big-metric.risk-high { color: var(--red); }

.slider-wrap { padding-top: 2px; }
.slider {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 5px; border-radius: 4px; outline: none;
  background: linear-gradient(90deg, var(--green) 0%, #b6e04a 35%, var(--amber) 65%, var(--red) 100%);
}
.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 15px; height: 15px; border-radius: 50%;
  background: #fff; cursor: pointer;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.12);
}
.slider::-moz-range-thumb {
  width: 15px; height: 15px; border-radius: 50%;
  background: #fff; border: none; cursor: pointer;
}
.slider-scale {
  display: flex; justify-content: space-between;
  font-size: 9.5px; color: var(--muted); margin-top: 7px;
}

.checks { display: flex; gap: 16px; }
.check { display: flex; align-items: center; gap: 7px; font-size: 11.5px; color: var(--text-dim); cursor: pointer; }
.check input { display: none; }
.check .box {
  width: 14px; height: 14px; border-radius: 4px;
  border: 1px solid #2c3a3f; display: grid; place-items: center;
  transition: background 0.14s, border-color 0.14s;
}
.check .box svg { width: 9px; height: 9px; opacity: 0; color: #04180e; }
.check input:checked + .box { background: var(--green); border-color: var(--green); }
.check input:checked + .box svg { opacity: 1; }

.action-btn {
  width: 100%; height: 42px; border-radius: 9px;
  background: linear-gradient(180deg, var(--green), var(--green-2));
  color: #04180e; font-size: 13px; font-weight: 800; letter-spacing: 0.03em;
  transition: filter 0.15s;
}
.action-btn:hover { filter: brightness(1.08); }
.action-btn:active { filter: brightness(0.94); }
.action-btn.armed { background: linear-gradient(180deg, #ff5f57, #d63c4e); color: #2a0207; }

.console-foot {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 13px;
  border-top: 1px solid var(--border-soft);
  font-size: 10.5px; color: var(--muted);
}

/* ── stat strip + mini charts ──────────────────────── */
.stat-strip {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 10px;
  margin-bottom: 14px;
}
.stat {
  background: var(--panel);
  border: 1px solid var(--border-soft);
  border-radius: 10px;
  padding: 11px 13px;
}
.stat .k { font-size: 9.5px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); font-weight: 700; }
.stat .v { font-family: var(--mono); font-size: 19px; font-weight: 600; margin-top: 6px; letter-spacing: -0.01em; }
.stat .d { font-size: 10.5px; margin-top: 3px; }

.mini-grid {
  display: grid;
  grid-template-columns: 1.15fr 1fr 1.15fr;
  gap: 14px;
  margin-bottom: 14px;
}

.split { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 1100px) { .split { grid-template-columns: 1fr; } }
.mini-body { padding: 12px 14px; height: 186px; position: relative; }

/* ── table ─────────────────────────────────────────── */
.table-tabs {
  display: flex; align-items: center; gap: 2px;
  padding: 8px 10px 0;
  border-bottom: 1px solid var(--border-soft);
}
.table-tabs button {
  padding: 9px 14px;
  font-size: 12px; font-weight: 600; color: var(--muted);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color 0.14s;
}
.table-tabs button:hover { color: var(--text-dim); }
.table-tabs button.on { color: var(--text); border-bottom-color: var(--green); }
.table-tabs .right { margin-left: auto; display: flex; gap: 6px; padding-bottom: 7px; }

.table-scroll { overflow-x: auto; max-height: 420px; overflow-y: auto; }
table { width: 100%; border-collapse: collapse; white-space: nowrap; }
thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--panel);
  text-align: left;
  font-size: 9px; letter-spacing: 0.13em; text-transform: uppercase;
  color: var(--muted); font-weight: 700;
  padding: 11px 12px 9px;
  border-bottom: 1px solid var(--border-soft);
}
tbody td {
  padding: 9px 12px;
  font-size: 11.5px;
  border-bottom: 1px solid #12181a;
  color: var(--text-dim);
}
tbody tr { transition: background 0.14s; }
tbody tr:hover { background: #12181a; }
tbody tr.flash { animation: rowflash 1.1s ease-out; }
@keyframes rowflash {
  0% { background: rgba(47, 224, 138, 0.13); }
  100% { background: transparent; }
}
tbody tr.flash-alert { animation: rowflashred 1.4s ease-out; }
@keyframes rowflashred {
  0% { background: rgba(255, 80, 100, 0.16); }
  100% { background: transparent; }
}

.flow-cell { display: flex; align-items: center; gap: 8px; }
.flow-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.flow-name { color: var(--text); font-weight: 600; font-size: 11.5px; }

/* A line of evidence under the cell it belongs to. Wraps rather than truncating
   with an ellipsis: it exists to be read, and a sentence cut off at "34
   connections held open against 10.0.0.7:443, averag…" has thrown away the
   half that says whether this is an attack. */
.cell-sub {
  font-family: var(--sans); font-size: 10.5px; line-height: 1.5;
  color: var(--muted); margin-top: 3px; max-width: 340px;
  white-space: normal; font-weight: 400; letter-spacing: 0;
}

.tag {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 8px; border-radius: 5px;
  font-size: 10px; font-weight: 700; letter-spacing: 0.04em;
}
.tag-benign { background: rgba(47, 224, 138, 0.11); color: var(--green); }
.tag-ddos { background: rgba(255, 80, 100, 0.12); color: var(--red); }
.tag-dos { background: rgba(255, 181, 69, 0.12); color: var(--amber); }
.tag-scan { background: rgba(169, 123, 255, 0.13); color: var(--purple); }
.tag-brute { background: rgba(79, 184, 247, 0.12); color: var(--blue); }
/* Marks a control that is present and saves, but whose effect is not wired up
   yet. Better to say so on the control itself than to let an operator configure
   it and assume something is listening. */
.tag-pending {
  background: rgba(255, 181, 69, 0.12); color: var(--amber);
  text-transform: uppercase; vertical-align: middle; margin-left: 6px;
}

.conf-bar {
  display: flex; align-items: center; gap: 8px;
}
.conf-track { width: 46px; height: 4px; border-radius: 3px; background: #1c2427; overflow: hidden; }
.conf-fill { height: 100%; border-radius: 3px; }

.row-btn {
  padding: 4px 10px; border-radius: 6px;
  font-size: 10px; font-weight: 700; letter-spacing: 0.04em;
  border: 1px solid rgba(47, 224, 138, 0.28);
  background: rgba(47, 224, 138, 0.09);
  color: var(--green);
  transition: background 0.14s;
}
.row-btn:hover { background: rgba(47, 224, 138, 0.18); }
.row-btn.danger { border-color: rgba(255, 80, 100, 0.3); background: rgba(255, 80, 100, 0.09); color: var(--red); }
.row-btn.danger:hover { background: rgba(255, 80, 100, 0.18); }
.row-btn.ghost { border-color: var(--border); background: transparent; color: var(--muted); }
.row-btn.ghost:hover { color: var(--text-dim); background: #171f22; }
.row-actions { display: flex; gap: 6px; justify-content: flex-end; }

.empty-state { padding: 44px; text-align: center; color: var(--muted); font-size: 12px; }

/* ── secondary pages ───────────────────────────────── */
.page { max-width: 1080px; }
.page-grid { display: grid; grid-template-columns: 300px minmax(0, 1fr); gap: 14px; }

.profile-card { padding: 20px; text-align: center; }
.profile-avatar {
  width: 72px; height: 72px; border-radius: 20px;
  margin: 0 auto 12px;
  background: linear-gradient(145deg, var(--green), #0d8a52);
  display: grid; place-items: center;
  font-size: 25px; font-weight: 800; color: #04180e;
  box-shadow: 0 0 26px rgba(47, 224, 138, 0.25);
}
.profile-name { font-size: 16px; font-weight: 700; }
.profile-role { font-size: 11.5px; color: var(--muted); margin-top: 3px; }
.profile-badges { display: flex; gap: 6px; justify-content: center; margin-top: 12px; flex-wrap: wrap; }

.kv-list { padding: 4px 0; }
.kv {
  display: flex; align-items: center; justify-content: space-between;
  padding: 11px 15px;
  border-bottom: 1px solid var(--border-soft);
  font-size: 12px;
}
.kv:last-child { border-bottom: none; }
.kv .k { color: var(--muted); }
.kv .v { font-weight: 600; }

.setting-row {
  display: flex; align-items: center; gap: 16px;
  padding: 14px 15px;
  border-bottom: 1px solid var(--border-soft);
}
.setting-row:last-child { border-bottom: none; }
.setting-info { flex: 1; min-width: 0; }
.setting-info .t { font-size: 12.5px; font-weight: 600; }
.setting-info .d { font-size: 11px; color: var(--muted); margin-top: 3px; line-height: 1.5; }
.setting-control { flex-shrink: 0; }

.toggle { position: relative; width: 38px; height: 21px; cursor: pointer; }
.toggle input { display: none; }
.toggle .track {
  position: absolute; inset: 0;
  background: #232c30; border-radius: 20px;
  transition: background 0.18s;
}
.toggle .knob {
  position: absolute; top: 3px; left: 3px;
  width: 15px; height: 15px; border-radius: 50%;
  background: #7d8b93;
  transition: transform 0.18s, background 0.18s;
}
.toggle input:checked ~ .track { background: rgba(47, 224, 138, 0.28); }
.toggle input:checked ~ .knob { transform: translateX(17px); background: var(--green); }

.txt-input, .sel-input {
  background: #0c1012;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 11px;
  font-size: 12px;
  outline: none;
  min-width: 190px;
  transition: border-color 0.15s;
}
.txt-input:focus, .sel-input:focus { border-color: rgba(47, 224, 138, 0.4); }
.sel-input { cursor: pointer; }
.txt-input.wide { width: 100%; }

.notice {
  display: flex; gap: 11px;
  padding: 12px 14px; border-radius: 10px;
  background: rgba(79, 184, 247, 0.06);
  border: 1px solid rgba(79, 184, 247, 0.18);
  font-size: 11.5px; color: var(--text-dim); line-height: 1.6;
  margin-bottom: 14px;
}
.notice svg { width: 15px; height: 15px; color: var(--blue); flex-shrink: 0; margin-top: 1px; }
.notice code { font-family: var(--mono); color: var(--green); font-size: 11px; }

.toast {
  position: fixed; bottom: 22px; right: 22px; z-index: 90;
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  font-size: 12px;
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.5);
  transform: translateY(80px);
  opacity: 0;
  transition: transform 0.28s cubic-bezier(.2,.8,.3,1), opacity 0.28s;
}
.toast.show { transform: translateY(0); opacity: 1; }
.toast svg { width: 15px; height: 15px; color: var(--green); }
.toast.err { border-color: rgba(255, 80, 100, 0.35); }
.toast.err svg { color: var(--red); }

/* ── fatal banner ──────────────────────────────────────
   Shown when the API cannot be reached. Deliberately loud and non-dismissable:
   a security dashboard that quietly shows stale data is worse than one that
   shows nothing. */
.fatal-bar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center; gap: 10px;
  padding: 9px 16px;
  background: linear-gradient(180deg, #3a1119, #2a0d13);
  border-bottom: 1px solid rgba(255, 80, 100, 0.4);
  color: #ffb3bd; font-size: 12px; font-weight: 600;
}
.fatal-bar svg { color: var(--red); flex-shrink: 0; }

/* ── auth pages ────────────────────────────────────────── */
body.auth { overflow: auto; display: grid; place-items: center; min-height: 100vh; padding: 30px 18px; }
.auth-card {
  width: 100%; max-width: 408px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 28px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5);
}
.auth-brand { display: flex; align-items: center; gap: 10px; margin-bottom: 22px; }
.auth-title { font-size: 19px; font-weight: 700; letter-spacing: -0.01em; }
.auth-sub { font-size: 12px; color: var(--muted); margin-top: 5px; line-height: 1.6; }
.auth-form { display: flex; flex-direction: column; gap: 13px; margin-top: 20px; }
/* Each signup step is a wrapper inside the form, so it has to repeat the column
   layout — otherwise the form's stretch stops at the wrapper and the buttons
   inside shrink to fit their own text. The :not([hidden]) is load-bearing: an
   author `display` here outranks the browser's own rule for [hidden], so
   without it every step renders at once. */
.auth-form [data-step]:not([hidden]) { display: flex; flex-direction: column; gap: 13px; }
.field { display: flex; flex-direction: column; gap: 6px; }
.field label { font-size: 11px; font-weight: 600; color: var(--text-dim); }
.field input, .field select {
  background: #0c1012; border: 1px solid var(--border);
  border-radius: 9px; padding: 10px 12px; font-size: 13px; outline: none;
  transition: border-color 0.15s;
}
.field input:focus, .field select:focus { border-color: rgba(47, 224, 138, 0.45); }
.field .hint { font-size: 10.5px; color: var(--muted); line-height: 1.5; }
.auth-btn {
  height: 42px; border-radius: 10px; margin-top: 4px;
  background: linear-gradient(180deg, var(--green), var(--green-2));
  color: #04180e; font-size: 13.5px; font-weight: 700;
  transition: filter 0.15s;
}
.auth-btn:hover { filter: brightness(1.08); }
.auth-btn[disabled] { opacity: 0.55; cursor: not-allowed; }
.auth-alt { margin-top: 18px; text-align: center; font-size: 12px; color: var(--muted); }

.org-type-picker { display: flex; flex-direction: column; gap: 8px; }
.org-type-opt {
  display: flex; flex-direction: column; gap: 2px; text-align: left;
  background: #0c1012; border: 1px solid var(--border); border-radius: 9px;
  padding: 10px 12px; cursor: pointer; transition: border-color 0.15s, background 0.15s;
}
.org-type-opt:hover { border-color: rgba(47, 224, 138, 0.3); }
.org-type-opt.selected { border-color: rgba(47, 224, 138, 0.55); background: var(--green-glow); }
.org-type-opt .t { font-size: 12.5px; font-weight: 600; }
.org-type-opt.selected .t { color: var(--green); }
.org-type-opt .d { font-size: 10.5px; color: var(--muted); line-height: 1.5; }
.auth-alt a { color: var(--green); font-weight: 600; }
.form-error {
  display: none;
  padding: 10px 12px; border-radius: 9px;
  background: rgba(255, 80, 100, 0.08);
  border: 1px solid rgba(255, 80, 100, 0.28);
  color: #ffb3bd; font-size: 11.5px; line-height: 1.55;
}
.form-error.show { display: block; }

.auth-back {
  height: 34px; border-radius: 9px; background: transparent;
  color: var(--muted); font-size: 12px; font-weight: 600;
  transition: color 0.15s;
}
.auth-back:hover { color: var(--text); }

.step-dots { display: flex; gap: 6px; justify-content: center; margin-bottom: 4px; }
.step-dots i {
  width: 22px; height: 3px; border-radius: 2px;
  background: var(--border); transition: background 0.2s;
}
.step-dots i.on { background: var(--green); }
.step-dots i.done { background: rgba(47, 224, 138, 0.4); }

.field label .opt {
  font-weight: 500; color: var(--muted); text-transform: none; letter-spacing: 0;
}

/* Terminal state for a join request: the form is replaced rather than left
   on screen, because there is nothing further to submit. */
.auth-done {
  padding: 14px; border-radius: 10px; margin-top: 20px;
  background: var(--green-glow);
  border: 1px solid rgba(47, 224, 138, 0.3);
  font-size: 12.5px; line-height: 1.6;
}
.auth-done .t { font-weight: 700; color: var(--green); margin-bottom: 4px; }

/* ── generic page furniture ────────────────────────────── */
.page-head {
  display: flex; align-items: center; gap: 12px;
  margin-bottom: 14px; flex-wrap: wrap;
}
.page-head .page-title { font-size: 15px; font-weight: 700; }
.page-head .right { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.section-note { font-size: 11px; color: var(--muted); line-height: 1.6; padding: 12px 15px; }

/* Device configuration the operator pastes into a router. `white-space: pre`
   without wrapping is deliberate — these are CLI lines, and a soft-wrapped
   command copied out of the browser arrives at the device broken across two
   lines. Horizontal scroll is the lesser evil. */
.snippet {
  font-family: var(--mono); font-size: 11.5px; line-height: 1.75;
  white-space: pre; overflow-x: auto;
  background: #0a0e10; border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm);
  padding: 13px 15px; margin: 0 15px 13px;
  color: var(--text-dim);
}
.snippet .cmt { color: var(--muted); }

.chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px; border-radius: 20px;
  font-size: 10px; font-weight: 700; letter-spacing: 0.05em;
  border: 1px solid var(--border); color: var(--text-dim); background: #10171a;
}
.chip.ok { border-color: rgba(47, 224, 138, 0.3); color: var(--green); background: rgba(47, 224, 138, 0.08); }
.chip.warn { border-color: rgba(255, 181, 69, 0.3); color: var(--amber); background: rgba(255, 181, 69, 0.08); }
.chip.bad { border-color: rgba(255, 80, 100, 0.3); color: var(--red); background: rgba(255, 80, 100, 0.08); }
.chip.info { border-color: rgba(79, 184, 247, 0.3); color: var(--blue); background: rgba(79, 184, 247, 0.08); }

.sev-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; flex-shrink: 0; }

.node-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
.node-tile {
  background: var(--panel); border: 1px solid var(--border-soft);
  border-radius: var(--radius); padding: 14px 15px;
}
.node-tile .top { display: flex; align-items: center; gap: 9px; margin-bottom: 11px; }
.node-tile .name { font-size: 13px; font-weight: 700; }
.node-tile .desc { font-size: 11px; color: var(--muted); margin-top: 2px; }
.node-tile .figs { display: flex; gap: 18px; margin-top: 12px; }
.node-tile .fig .k { font-size: 9px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); font-weight: 700; }
.node-tile .fig .v { font-family: var(--mono); font-size: 17px; margin-top: 4px; }

/* The tile itself is a <button> that selects the node, so its manage controls
   cannot live inside it — a button nested in a button is invalid HTML and
   screen readers disagree about which one they are announcing. They sit as
   siblings instead, positioned over the tile's top-right corner, which is why
   the wrapper establishes a containing block. */
.node-tile-wrap { position: relative; }
.node-actions { position: absolute; top: 11px; right: 12px; display: flex; gap: 4px; }
/* Reserved so the status chip cannot slide underneath the controls on a narrow
   tile. Applied only when the controls are actually drawn, so a viewer — who
   gets neither — keeps the full width for the chip. */
.node-tile.has-actions .top { padding-right: 56px; }
.node-act {
  width: 24px; height: 24px; border-radius: 6px;
  display: grid; place-items: center;
  background: #0c1012; border: 1px solid var(--border-soft);
  color: var(--muted); cursor: pointer;
  /* Dimmed rather than hidden-until-hover. A control that only appears on hover
     is undiscoverable by anyone who does not happen to hover, and unreachable
     on a touchscreen. */
  opacity: 0.55; transition: opacity 0.15s, color 0.15s, border-color 0.15s;
}
.node-act:hover { opacity: 1; color: var(--text); border-color: var(--border); }
.node-act:focus-visible { opacity: 1; outline: 2px solid var(--green); outline-offset: 1px; }
.node-act.danger:hover { color: var(--red); border-color: rgba(255, 107, 107, 0.4); }
.node-act svg { width: 12px; height: 12px; }

.bar-track { height: 5px; border-radius: 3px; background: #1c2427; overflow: hidden; margin-top: 11px; }
.bar-fill { height: 100%; border-radius: 3px; background: var(--green); transition: width 0.4s; }

/* ── modal ─────────────────────────────────────────────── */
.modal-back {
  position: fixed; inset: 0; z-index: 120;
  background: rgba(3, 5, 6, 0.72);
  backdrop-filter: blur(3px);
  display: none; place-items: center; padding: 20px;
}
.modal-back.show { display: grid; }
.modal {
  width: 100%; max-width: 430px;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 14px; box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
}
.modal-head {
  display: flex; align-items: center; gap: 10px;
  padding: 15px 17px; border-bottom: 1px solid var(--border-soft);
}
.modal-head .t { font-size: 13.5px; font-weight: 700; }
.modal-head .x { margin-left: auto; color: var(--muted); display: grid; place-items: center; }
.modal-head .x:hover { color: var(--text); }
.modal-body { padding: 17px; display: flex; flex-direction: column; gap: 13px; }
.modal-foot {
  display: flex; justify-content: flex-end; gap: 8px;
  padding: 13px 17px; border-top: 1px solid var(--border-soft);
}
.btn-danger { background: linear-gradient(180deg, #ff5f57, #d63c4e); color: #2a0207; }
.btn-danger:hover { filter: brightness(1.08); }

/* ── filter popover ────────────────────────────────────── */
.popover {
  position: absolute; z-index: 60;
  background: var(--panel-2); border: 1px solid var(--border);
  border-radius: 10px; padding: 10px;
  box-shadow: 0 14px 36px rgba(0, 0, 0, 0.5);
  display: flex; flex-direction: column; gap: 9px;
  min-width: 178px;
}
.popover .ph {
  font-size: 9px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--muted); font-weight: 700;
}

/* ── report layout ─────────────────────────────────────── */
.report-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 12px; margin-bottom: 14px; }
.matrix { width: auto; border-collapse: collapse; }
.matrix td, .matrix th { padding: 8px 13px; font-size: 11.5px; text-align: center; border: 1px solid var(--border-soft); }
.matrix th { color: var(--muted); font-size: 9.5px; letter-spacing: 0.1em; text-transform: uppercase; }
.matrix td.hit { color: var(--green); font-weight: 700; }
.matrix td.miss { color: var(--red); font-weight: 700; }

/* ── consumer home ─────────────────────────────────────── */
/* Same panels, same borders, same type scale as the enterprise pages — the
   difference is how much is on screen and what the words are, not a second
   visual language. */
.home-hero {
  display: flex; align-items: center; gap: 20px;
  padding: 26px 28px; margin-bottom: 14px;
  border-radius: var(--radius);
  background: var(--panel); border: 1px solid var(--border-soft);
}
.home-hero .ring {
  width: 62px; height: 62px; border-radius: 50%; flex-shrink: 0;
  display: grid; place-items: center;
  border: 2px solid var(--border);
  color: var(--muted);
}
.home-hero .ring svg { width: 28px; height: 28px; }
.home-hero .verdict-line { font-size: 21px; font-weight: 700; letter-spacing: -0.015em; }
.home-hero .verdict-why { font-size: 12.5px; color: var(--text-dim); margin-top: 6px; line-height: 1.6; }
.home-hero.is-ok { border-color: rgba(47, 224, 138, 0.28); background: linear-gradient(180deg, var(--green-glow), transparent 70%), var(--panel); }
.home-hero.is-ok .ring { border-color: rgba(47, 224, 138, 0.5); color: var(--green); }
.home-hero.is-ok .verdict-line { color: var(--green); }
.home-hero.is-warn { border-color: rgba(255, 181, 69, 0.3); background: linear-gradient(180deg, rgba(255, 181, 69, 0.1), transparent 70%), var(--panel); }
.home-hero.is-warn .ring { border-color: rgba(255, 181, 69, 0.5); color: var(--amber); }
.home-hero.is-warn .verdict-line { color: var(--amber); }
.home-hero.is-bad { border-color: rgba(255, 80, 100, 0.32); background: linear-gradient(180deg, var(--red-glow), transparent 70%), var(--panel); }
.home-hero.is-bad .ring { border-color: rgba(255, 80, 100, 0.5); color: var(--red); }
.home-hero.is-bad .verdict-line { color: var(--red); }

.home-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 14px; }
/* Plainer than .stat: a word-first label and a number that does not shout, so
   the card reads as a sentence rather than as an instrument. */
.home-stats .stat .k { letter-spacing: 0.06em; text-transform: none; font-size: 11px; }
.home-stats .stat .v { font-family: var(--sans); font-size: 22px; font-weight: 700; }

.plain-list { padding: 4px 0; }
.plain-row { padding: 12px 15px; border-bottom: 1px solid var(--border-soft); }
.plain-row:last-child { border-bottom: none; }
.plain-row .line { display: flex; align-items: center; gap: 10px; }
.plain-row .what { font-size: 12.5px; font-weight: 600; }
.plain-row .when { font-size: 11px; color: var(--muted); margin-left: auto; white-space: nowrap; }
.plain-row .sub { font-size: 11.5px; color: var(--text-dim); margin-top: 4px; line-height: 1.55; }
/* Detail on demand: the technical read is present for anyone who wants it,
   but never the first thing on screen. */
.disclose {
  font-size: 11px; color: var(--muted); font-weight: 600; margin-top: 7px;
  display: inline-flex; align-items: center; gap: 5px;
}
.disclose:hover { color: var(--text-dim); }
.disclose svg { width: 11px; height: 11px; transition: transform 0.15s; }
.disclose.open svg { transform: rotate(180deg); }
.plain-detail {
  display: none; margin-top: 9px; padding: 10px 12px;
  border-radius: 8px; background: #0c1012; border: 1px solid var(--border-soft);
  font-family: var(--mono); font-size: 11px; color: var(--text-dim);
  line-height: 1.7;
}
.plain-detail.show { display: block; }
.plain-detail b { color: var(--muted); font-weight: 500; }

/* Alerts folded into the device or day they belong to. Sans-serif on purpose
   even though it sits inside the monospace detail panel: these rows are prose
   the reader is meant to skim, not field values they are meant to compare. */
.mini-list { margin-top: 10px; border-top: 1px solid var(--border-soft); padding-top: 8px; }
.mini-row {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 0; font-family: var(--sans); font-size: 11.5px;
}
.mini-row .what { color: var(--text); font-weight: 600; }
.mini-row .dim { color: var(--muted); font-size: 11px; }
.mini-row .chip, .mini-row .btn { margin-left: auto; flex-shrink: 0; }
.btn-sm { height: 24px; padding: 0 10px; font-size: 11px; border-radius: 7px; }
/* Disclosure and the block button share a line. The disclosure keeps its own
   top margin from .disclose, so align on the baseline rather than stretching. */
.row-actions { display: flex; align-items: center; gap: 12px; }
.row-actions .disclose { margin-right: 0; }

@media (max-width: 1280px) {
  .grid-top { grid-template-columns: minmax(0, 1fr); }
  .stat-strip { grid-template-columns: repeat(3, 1fr); }
  .mini-grid { grid-template-columns: 1fr; }
}
@media (max-width: 900px) {
  .app { grid-template-columns: 1fr; }
  .sidebar { display: none; }
  .stat-strip { grid-template-columns: repeat(2, 1fr); }
  .page-grid { grid-template-columns: 1fr; }
  .home-stats { grid-template-columns: 1fr; }
  .home-hero { flex-direction: column; align-items: flex-start; gap: 14px; }
}
