/* almon — minimal, dark, clean. */
:root {
  --bg:        #0e1116;
  --bg-2:      #161b22;
  --bg-3:      #1b222d;
  --border:    #2a3340;
  --text:      #e6edf3;
  --muted:     #8b949e;
  --accent:    #58e1c4;
  --accent-2:  #7ee9d4;
  --warn:      #f0b94e;
  --alert:     #f06464;
  --ok:        #58e1c4;
  --link:      #6ec1ff;
  --shadow:    0 6px 24px rgba(0,0,0,0.4);
}
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
body {
  background: var(--bg);
  color: var(--text);
  font: 14px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}
.hidden { display: none !important; }
.muted { color: var(--muted); }
.small { font-size: 12px; }

/* --- Login --- */
.login {
  height: 100%;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(1200px 600px at 30% 20%, #182530 0%, var(--bg) 60%);
}
.login .card { width: 320px; }
.login .brand { display: flex; align-items: center; gap: 10px; }
.login h1 { margin: 0; font-size: 24px; letter-spacing: 0.5px; }
.login input {
  width: 100%; padding: 10px 12px; margin-top: 10px;
  background: var(--bg-3); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px;
}
.login input:focus { outline: 2px solid var(--accent); }
.login button {
  width: 100%; padding: 10px; margin-top: 14px;
  background: var(--accent); color: #001f1a;
  border: 0; border-radius: 8px; font-weight: 600;
  cursor: pointer;
}
.login button:hover { background: var(--accent-2); }
.err { color: var(--alert); margin-top: 12px; min-height: 18px; }

/* --- App shell --- */
.app {
  height: 100%;
  display: grid;
  grid-template-columns: 220px 1fr;
}
.sidebar {
  background: var(--bg-2);
  border-right: 1px solid var(--border);
  display: flex; flex-direction: column;
  padding: 20px 14px;
  gap: 18px;
}
.sidebar .brand { display: flex; align-items: center; gap: 10px; font-weight: 600; font-size: 18px; }
.sidebar nav { display: flex; flex-direction: column; gap: 2px; }
.sidebar nav a {
  color: var(--text); text-decoration: none;
  padding: 8px 10px; border-radius: 6px;
  display: flex; justify-content: space-between; align-items: center;
}
.sidebar nav a:hover { background: var(--bg-3); }
.sidebar nav a.active { background: var(--bg-3); color: var(--accent); }
.sidebar .footer { margin-top: auto; display: flex; flex-direction: column; gap: 4px; }
.sidebar .pill {
  background: var(--accent); color: #001f1a;
  font-weight: 700; font-size: 11px;
  padding: 1px 6px; border-radius: 999px;
}
/* Sidebar Alerts badge: warning (amber) and alert (red) tones so a
 * glance at the nav tells the operator something needs attention.
 * `.pill.warn` is overridden by `.pill.alert` via load order — JS
 * sets whichever class applies, with alert winning when both
 * conditions are true. The accent default is kept for non-alert
 * counters like "pending agents". */
.sidebar .pill.warn  { background: var(--warn);  color: #2a1c00; }
.sidebar .pill.alert { background: var(--alert); color: #2a0606; }
/* Subtle pulse for the red variant — draws the eye to a real
 * incident without being annoying enough that operators learn to
 * ignore it (no flashing/blinking). */
@keyframes almon-alert-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(240,100,100,0); }
  50%      { box-shadow: 0 0 0 4px rgba(240,100,100,0.18); }
}
.sidebar .pill.alert {
  animation: almon-alert-pulse 1.6s ease-in-out infinite;
}
.link { background: none; border: 0; color: var(--link); cursor: pointer; padding: 0; text-align: left; font-size: inherit; }
.link:hover { text-decoration: underline; }

main {
  padding: 24px 28px;
  overflow-y: auto;
  height: 100vh;
}
header {
  display: flex; align-items: center; gap: 12px;
  margin-bottom: 16px;
}
header h2 { margin: 0; font-size: 22px; }
header .back { color: var(--link); text-decoration: none; }
header .back:hover { text-decoration: underline; }

/* --- Card / list / table --- */
.card {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 18px 20px;
  margin-bottom: 18px;
  box-shadow: var(--shadow);
}
.card h3 { margin: 0 0 12px; font-size: 14px; letter-spacing: 0.4px; text-transform: uppercase; color: var(--muted); }

table { width: 100%; border-collapse: collapse; }
thead th {
  font-weight: 600; text-align: left; font-size: 12px;
  text-transform: uppercase; color: var(--muted);
  border-bottom: 1px solid var(--border);
  padding: 8px 10px;
}
tbody td {
  padding: 10px; border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
tbody tr:hover { background: rgba(255,255,255,0.02); }
tbody tr:last-child td { border-bottom: 0; }

.row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.row input, .row button, .row select {
  padding: 8px 10px; background: var(--bg-3); color: var(--text);
  border: 1px solid var(--border); border-radius: 6px;
}
.row button {
  background: var(--accent); color: #001f1a; cursor: pointer; border: 0; font-weight: 600;
}
.row button.secondary { background: transparent; color: var(--text); border: 1px solid var(--border); font-weight: 400; }
.row button.danger { background: transparent; color: var(--alert); border: 1px solid var(--alert); font-weight: 400; }
.row button:hover { filter: brightness(1.05); }
.check { display: inline-flex; gap: 6px; align-items: center; color: var(--muted); }

input, select, textarea, button { font: inherit; }
button { cursor: pointer; }

/* --- Form controls: theme baseline ------------------------------ */
/*
 * Bare <button>, <input>, <select> elements get the dark-theme look
 * by default so headers (Alerts, Services), modal forms and any
 * dynamically-injected control don't render as bright-white system
 * widgets against the dark UI. Specific contexts override:
 *   - `.login`           — wider, accent-coloured submit
 *   - `.row`             — same look but in form rows inside cards
 *   - `.link`            — text-only buttons that look like links
 *   - `.chart-expand`    — tiny "⤢" toggles on chart labels
 *   - `.env-filter`      — selects in headers (legacy class, still works)
 *   - `button.secondary.small` — compact secondary in card heads
 * All of those have higher specificity than the bare-element rules,
 * so existing styling is preserved.
 *
 * Checkbox / radio are intentionally NOT restyled here — browser
 * native rendering is fine for them on a dark surface and a custom
 * checkbox would be a lot more CSS than it's worth.
 */
input[type="text"],
input[type="password"],
input[type="number"],
input[type="email"],
input[type="search"],
input:not([type]),
select,
textarea {
  padding: 8px 10px;
  background: var(--bg-3);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
}
input[type="text"]:focus,
input[type="password"]:focus,
input[type="number"]:focus,
input[type="email"]:focus,
input[type="search"]:focus,
input:not([type]):focus,
select:focus,
textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
}
input::placeholder, textarea::placeholder { color: var(--muted); }

button {
  padding: 8px 12px;
  background: var(--accent);
  color: #001f1a;
  border: 0;
  border-radius: 6px;
  font-weight: 600;
}
button:hover:not(:disabled) { filter: brightness(1.05); }
button:disabled { opacity: 0.45; cursor: not-allowed; filter: none; }

/* Variant: secondary — outlined, theme-neutral. Works wherever a
 * <button class="secondary"> appears (header, modal, anywhere).
 * The earlier `.row button.secondary` rule still applies inside
 * form rows; the look matches so the cascade is harmless. */
button.secondary {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
  font-weight: 400;
}
button.secondary:hover:not(:disabled) {
  background: var(--bg-3);
  border-color: var(--accent);
  color: var(--accent);
  filter: none;
}

/* Variant: danger — outlined red for destructive actions
 * (Wipe history, Delete, etc). */
button.danger {
  background: transparent;
  color: var(--alert);
  border: 1px solid var(--alert);
  font-weight: 400;
}
button.danger:hover:not(:disabled) {
  background: rgba(240,100,100,0.08);
  filter: none;
}

/* Header form controls: keep them at a sensible compact width so a
 * search input in `<header>` doesn't stretch to fill the bar like
 * inputs inside `.row` do. Selects already had this via
 * `.env-filter`; this rule covers bare ones (e.g. al-range) and the
 * services search input. */
header input[type="text"],
header input[type="search"],
header input:not([type]),
header select {
  padding: 6px 8px;
  min-width: 160px;
  max-width: 320px;
}

/* --- Dashboard grid --- */
.grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 14px;
}
.agent-card {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 14px 16px;
  display: flex; flex-direction: column; gap: 10px;
  cursor: pointer;
}
.agent-card:hover { border-color: var(--accent); }
.agent-card .row1 { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.agent-card .row1 strong { font-size: 15px; }
.agent-card .meta { color: var(--muted); font-size: 12px; }
.agent-card .charts { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 6px; }
.agent-card .chart-mini { height: 36px; }
.agent-card .stat { font-size: 11px; color: var(--muted); text-align: center; }

/* --- Status pills --- */
.status-pill {
  display: inline-block; padding: 2px 8px; border-radius: 999px;
  font-size: 11px; font-weight: 600; text-transform: uppercase;
  background: var(--bg-3); color: var(--muted);
}
.status-pill.online { background: rgba(88, 225, 196, 0.15); color: var(--ok); }
.status-pill.offline { background: rgba(240, 100, 100, 0.15); color: var(--alert); }
.status-pill.warning { background: rgba(240, 185, 78, 0.15); color: var(--warn); }
.status-pill.alert { background: rgba(240, 100, 100, 0.18); color: var(--alert); }
.status-pill.pending { background: rgba(110, 193, 255, 0.15); color: var(--link); }
.status-pill.rejected { background: rgba(255,255,255,0.05); color: var(--muted); }

/* Kind pill — sits next to the level pill on the alerts page. The
   level (warning/alert) tells you "how loud", the kind tells you
   "what fired" so an operator scanning the table can tell offline
   from clock-skew at a glance. */
.kind-pill {
  display: inline-block; padding: 2px 8px; border-radius: 999px;
  font-size: 10px; font-weight: 600; letter-spacing: 0.02em;
  background: rgba(255,255,255,0.04); color: var(--muted);
  border: 1px solid var(--border);
}
.kind-pill.kind-clock_skew { color: var(--link); border-color: rgba(110,193,255,0.4); }
.kind-pill.kind-offline { color: var(--muted); }
/* Service-kind pills. We don't pretend to know every kind in advance
   (we'll add MySQL / Postgres / JMX detectors later) so the default
   styling above is fine for unknown kinds; the explicit overrides
   below give the ones we do know a distinguishable hue. */
.kind-pill.kind-lvm    { color: #b89bff; border-color: rgba(184,155,255,0.4); }
.kind-pill.kind-mdraid { color: #f0b94e; border-color: rgba(240,185,78,0.4); }
.kind-pill.kind-zfs    { color: #58e1c4; border-color: rgba(88,225,196,0.4); }
.kind-pill.kind-mysql  { color: #ff8db1; border-color: rgba(255,141,177,0.4); }
.kind-pill.kind-docker { color: #6ec1ff; border-color: rgba(110,193,255,0.4); }
/* Generic styling for every "kind-rule_NN" pill — the underscore-
 * separated suffix is a dynamic rule id (we replace ':' with '_' in
 * the class name to keep the CSS selector valid). */
.kind-pill[class*="kind-rule_"] { color: #c2b3ff; border-color: rgba(194,179,255,0.4); }
.kind-pill.kind-stale  { color: var(--warn); border-color: rgba(240,185,78,0.4); }
.kind-pill.kind-oom        { color: #ff7878; border-color: rgba(255,120,120,0.45); background: rgba(255,120,120,0.08); }
.kind-pill.kind-mce        { color: #ff7878; border-color: rgba(255,120,120,0.45); background: rgba(255,120,120,0.08); }
.kind-pill.kind-io_error   { color: #ff9a5a; border-color: rgba(255,154,90,0.45); background: rgba(255,154,90,0.08); }
.kind-pill.kind-fs_error   { color: #ff9a5a; border-color: rgba(255,154,90,0.45); background: rgba(255,154,90,0.08); }
.kind-pill.kind-ata_error  { color: var(--warn); border-color: rgba(240,185,78,0.4); }

/* install-cmd renders copy-pasteable shell / SQL snippets inside the
   service edit modal's "How to give almon read-only access" block.
   Distinct from <pre> default so it visually reads as an instruction
   box rather than a fatal error trace. */
pre.install-cmd {
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
  margin: 6px 0;
  white-space: pre;
  overflow-x: auto;
  font-size: 12px;
}

/* MySQL service-card visualisations. The goal here is at-a-glance
   readable: stat cards on the top row, a stacked bar for buffer
   pool occupancy, a donut for query mix. We deliberately avoid
   anything fancier than inline SVG so the asset stays small (one
   <pre> dump-the-counters block remains as a "raw" details fallback). */
.mysql-head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.mysql-flavor { display: inline-flex; align-items: center; gap: 8px; }
.mysql-endpoint { font-family: var(--mono, monospace); }

.mysql-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 8px;
  margin-bottom: 12px;
}
.mysql-stat {
  background: rgba(255,255,255,0.03);
  border: 1px solid var(--border);
  border-left: 3px solid rgba(126, 233, 212, 0.5);
  border-radius: 6px;
  padding: 8px 10px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  position: relative;
  min-height: 70px;
}
.mysql-stat-warning { border-left-color: var(--warn); }
.mysql-stat-alert   { border-left-color: var(--alert); }
.mysql-stat-label {
  font-size: 11px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.mysql-stat-value { font-size: 22px; font-weight: 600; }
.mysql-stat-sub { margin-top: 2px; }
.mysql-stat .mysql-spark {
  position: absolute;
  right: 6px;
  bottom: 6px;
  color: rgba(126, 233, 212, 0.7);
  pointer-events: none;
}
.mysql-stat .mysql-bar2 {
  height: 4px;
  background: rgba(255,255,255,0.05);
  border-radius: 2px;
  margin-top: 6px;
  overflow: hidden;
}
.mysql-stat .mysql-bar2 .seg {
  height: 100%;
  background: rgba(126, 233, 212, 0.7);
}

.mysql-section { margin: 12px 0; }
.mysql-section h5 {
  margin: 0 0 6px 0;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}

.mysql-stack {
  display: flex;
  width: 100%;
  height: 14px;
  background: rgba(255,255,255,0.05);
  border-radius: 3px;
  overflow: hidden;
}
.mysql-stack .seg { height: 100%; }
.mysql-stack .seg-data  { background: #7ee9d4; }
.mysql-stack .seg-dirty { background: #f0b94e; }
.mysql-stack .seg-free  { background: rgba(255,255,255,0.10); }
.mysql-legend {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 6px;
  font-size: 11px;
  color: var(--muted);
}
.mysql-legend i.dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-right: 5px;
  vertical-align: 1px;
}
.mysql-legend i.dot-data  { background: #7ee9d4; }
.mysql-legend i.dot-dirty { background: #f0b94e; }
.mysql-legend i.dot-free  { background: rgba(255,255,255,0.30); }

.mysql-mix-grid {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 16px;
  align-items: center;
}
.mysql-donut-wrap { display: flex; justify-content: center; align-items: center; }
.mysql-mix-row {
  display: grid;
  grid-template-columns: 14px 70px 1fr 40px 70px;
  align-items: center;
  gap: 8px;
  padding: 3px 0;
  font-size: 12px;
}
.mysql-mix-row .dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
}
.mysql-mix-name { font-weight: 500; }
.mysql-mix-bar {
  height: 6px;
  background: rgba(255,255,255,0.05);
  border-radius: 3px;
  overflow: hidden;
  position: relative;
}
.mysql-mix-bar > span {
  display: block;
  height: 100%;
  border-radius: 3px;
}
.mysql-mix-pct { text-align: right; font-variant-numeric: tabular-nums; }

@media (max-width: 640px) {
  .mysql-mix-grid { grid-template-columns: 1fr; }
  .mysql-donut-wrap { order: -1; }
}

/* kind-config groups kind-specific fields (today MySQL credentials)
   inside the service edit modal so they read as a distinct unit
   rather than four loose inputs jammed under "State". */
fieldset.kind-config {
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 10px 12px;
  margin-top: 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
fieldset.kind-config legend {
  padding: 0 6px;
  font-size: 12px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
fieldset.kind-config details summary { cursor: pointer; }

/* Docker snapshot dashboard. Mirrors the mdraid/zfs/mysql visual
 * vocabulary so an operator scanning the host page reads "all
 * service cards look the same shape" instead of "this one's
 * different".
 *
 *   .docker-head   — version, socket, OS one-liner
 *   .docker-stats  — running/stopped/total/images stat cards
 *   .docker-table  — collapsible per-container table
 */
.docker-head {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-bottom: 10px;
}
.docker-sock { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; color: var(--muted); }
.docker-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(90px, 1fr));
  gap: 8px;
  margin-bottom: 12px;
}
.docker-stat {
  background: var(--bg-3);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 10px;
  text-align: center;
}
.docker-stat-num {
  font-size: 22px; font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
}
.docker-stat-lbl {
  font-size: 11px; text-transform: uppercase;
  letter-spacing: 0.05em; color: var(--muted);
}
.docker-containers summary { cursor: pointer; color: var(--muted); margin-bottom: 6px; }
.docker-table { width: 100%; }
.docker-table td, .docker-table th { padding: 4px 8px; }

/* System-logs (per-agent tail) view. Fixed-height with scroll so the
 * page layout doesn't reflow as new lines arrive every minute, and a
 * dim mono font that matches `pre`/`code` elsewhere. */
.log-view {
  background: #07120f;
  border: 1px solid var(--border);
  border-radius: 6px;
  color: #d6e4df;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  line-height: 1.4;
  max-height: 480px;
  min-height: 200px;
  margin: 0;
  overflow: auto;
  padding: 8px 10px;
  white-space: pre-wrap;
  word-break: break-word;
}
.log-view .muted { opacity: 0.6; }

/* ============================================================
   Monitors / Explorer / Dashboards
   ============================================================ */

/* Explorer legend: chips with a stroke swatch + name + last value.
 * Long lists are scrollable so 50 hosts don't push the chart out
 * of view. */
.explorer-legend {
  display: flex; flex-wrap: wrap; gap: 8px 12px; margin-top: 10px;
  padding-top: 10px; border-top: 1px solid var(--border);
  max-height: 200px; overflow-y: auto;
}
.legend-count { flex-basis: 100%; margin-bottom: 4px; }
.legend-item {
  display: inline-flex; align-items: center; gap: 6px; font-size: 13px;
  padding: 2px 6px; border-radius: 4px; background: var(--bg-3, rgba(255,255,255,0.04));
}
.legend-swatch {
  display: inline-block; width: 12px; height: 12px;
  border-radius: 2px;
}

/* Widget head controls (edit / resize / move / remove). Keep them
 * small so the title gets the visual weight; reveal on hover so a
 * busy dashboard with 20 widgets doesn't look like a button farm. */
.widget-head .widget-size {
  margin-left: 6px; padding: 1px 6px;
  background: rgba(255,255,255,0.05);
  border-radius: 4px;
}
.widget-head .link {
  opacity: 0.4; transition: opacity 0.15s;
}
.widget-card:hover .widget-head .link { opacity: 1; }

/* Disabled action buttons (when dashboard is locked) get a subtle
 * dim+no-pointer treatment so the operator immediately sees the
 * controls are present but currently inert. */
button[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
}

/* Settings → Database panel
 *
 * Compact stats grid + sortable-ish table. Numeric column is
 * tabular-numeric + right aligned so 17 vs 17,000,000 align. */
.db-summary {
  display: flex; flex-wrap: wrap; gap: 16px;
  margin: 8px 0 12px;
  padding: 10px 12px;
  background: rgba(255,255,255,0.03);
  border-radius: 6px;
}
.db-summary-num {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-size: 16px;
  color: var(--accent);
}
.db-table {
  width: 100%;
  font-size: 13px;
  margin-top: 4px;
  border-collapse: collapse;
}
.db-table th, .db-table td {
  padding: 4px 8px;
  border-bottom: 1px solid var(--border);
}
.db-table .num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.db-table tbody tr:hover { background: rgba(255,255,255,0.03); }

.db-job {
  display: flex; flex-direction: column; gap: 8px;
  margin: 8px 0;
  padding: 10px 12px;
  border-left: 3px solid var(--accent);
  background: rgba(94,224,197,0.08);
  border-radius: 4px;
}
.db-job-head {
  display: flex; align-items: center; gap: 10px;
}
.db-job-name { flex: 1; font-size: 14px; }
.db-job-bar-wrap {
  height: 8px;
  background: rgba(255,255,255,0.08);
  border-radius: 4px;
  overflow: hidden;
}
.db-job-bar {
  height: 100%;
  background: var(--accent);
  border-radius: 4px;
  transition: width 0.4s ease;
  min-width: 0;
}
.db-job-bar.indeterminate {
  transition: none;
  animation: db-bar-slide 1.4s ease-in-out infinite;
}
@keyframes db-bar-slide {
  0%   { margin-left: 0; }
  50%  { margin-left: 60%; }
  100% { margin-left: 0; }
}
.db-job-detail { font-style: italic; opacity: 0.85; }
.db-job-spinner {
  width: 12px; height: 12px;
  border: 2px solid var(--accent);
  border-top-color: transparent;
  border-radius: 50%;
  animation: db-spin 0.9s linear infinite;
  display: inline-block;
  flex-shrink: 0;
}
.db-job-spinner.hidden { display: none; }
@keyframes db-spin {
  to { transform: rotate(360deg); }
}

/* Inline status pill used in the DB summary to surface the
 * auto_vacuum mode. Green = incremental reclaim is available;
 * orange = legacy DB needs a one-time full VACUUM before
 * non-blocking reclaim works. */
.db-pill {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 500;
}
.db-pill.ok    { background: rgba(94,224,197,0.16);  color: var(--accent); }
.db-pill.warn  { background: rgba(255,176,46,0.16);  color: #ffb02e; }

/* Dashboard grid uses a 12-column layout; widgets pick how many
 * columns they span via grid-column: span N. Mobile-friendly:
 * collapses to one column under 720px. */
.dashboard-grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 12px;
}
@media (max-width: 720px) {
  .dashboard-grid { grid-template-columns: 1fr; }
  .widget-card { grid-column: span 1 !important; }
}
.widget-card {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px;
  min-height: 160px;
  display: flex; flex-direction: column;
  grid-column: span 6;
}
.widget-head {
  display: flex; align-items: center; gap: 8px;
  margin-bottom: 8px;
}
.widget-body { flex: 1; min-height: 0; }
.widget-chart { min-height: 180px; }
.widget-stat {
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; height: 100%;
}
.widget-stat-num {
  font-size: 36px; font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
}
.widget-text {
  font-size: 14px; color: var(--text); line-height: 1.45;
}

/* Modal forms (monitor, dashboard, widget) reuse `.modal` from the
 * pop-out chart but want a narrower default card so the form rows
 * stay compact. */
.modal.dynamic-modal .modal-card {
  max-width: 640px;
}
.modal.dynamic-modal .row {
  display: flex; align-items: center; gap: 8px; margin: 6px 0;
}
.modal.dynamic-modal .row > label {
  min-width: 130px; color: var(--muted); font-size: 13px;
}
.modal.dynamic-modal input[type="text"],
.modal.dynamic-modal input[type="number"],
.modal.dynamic-modal select,
.modal.dynamic-modal textarea {
  flex: 1;
}

/* Per-row state colouring inside RAID / ZFS member tables: any device
   row whose snapshot says "this disk is sick" gets a red tint so a
   degraded array stands out at a glance without needing the operator
   to read state strings. svc-bad on a kv-row strong tag does the same
   for the headline summary line. */
.svc-bad,
tr.svc-bad td,
tr.svc-bad td code { color: var(--alert); }
strong.svc-bad     { color: var(--alert); }

/* Service-state pills reuse status-pill chrome but add specific tones
   so "unconfigured" reads as something to do, "configured" as fine,
   and "ignored" as muted. */
.status-pill.svc-state-discovered { background: rgba(110, 193, 255, 0.15); color: var(--link); }
.status-pill.svc-state-configured { background: rgba(88, 225, 196, 0.15); color: var(--ok); }
.status-pill.svc-state-ignored    { background: rgba(255,255,255,0.04); color: var(--muted); }

/* Outdated agent version: orange-on-dark to match the warning palette
   so the agents table at-a-glance shows which hosts still need to
   self-update (or have failed to). The row gets a subtle background
   tint; the version string itself is the loud part. */
tr.row-version-old td { background: rgba(240, 185, 78, 0.06); }
.version-old {
  color: var(--warn);
  font-weight: 600;
  border-bottom: 1px dotted rgba(240, 185, 78, 0.5);
  cursor: help;
}

/* API key column on the environments page. The masked dots use a
   monospace font so toggling reveal->hide doesn't reflow the row. */
code.api-key { font-family: var(--mono, monospace); padding: 2px 6px; background: rgba(255,255,255,0.04); border-radius: 4px; }
button.small { padding: 2px 8px; font-size: 0.85em; }

/* Services panel inside the agent-detail page. Each card is one
   discovered instance. */
.services-list { display: flex; flex-direction: column; gap: 10px; }
.service-card {
  background: var(--bg-3); border: 1px solid var(--border);
  border-radius: 8px; padding: 10px 12px;
}
.service-head {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-bottom: 8px;
}
.service-head .spacer { flex: 1; }
.service-body details {
  margin-top: 6px; font-size: 13px;
}
.service-body details summary {
  cursor: pointer; color: var(--muted); padding: 4px 0;
}
.service-body .kv-row {
  display: grid; grid-template-columns: repeat(5, auto 1fr); gap: 4px 12px;
  font-size: 13px; align-items: baseline;
}
.service-body .kv-row .muted { font-size: 11px; }
.services-sub { width: 100%; margin-top: 6px; font-size: 12px; }
.services-sub th { text-align: left; color: var(--muted); font-weight: 500; padding: 4px 6px; }
.services-sub td { padding: 4px 6px; border-top: 1px solid var(--border); }

/* Services page — keep the table dense; the row-stale class dims
   instances the agent hasn't reported lately so the operator can see
   "we used to monitor this, but the host stopped reporting it". */
#services-table tr.row-stale td { opacity: 0.55; }

.list { display: flex; flex-direction: column; gap: 8px; }
.list .item {
  display: flex; justify-content: space-between; align-items: center;
  background: var(--bg-3); border: 1px solid var(--border);
  border-radius: 8px; padding: 10px 12px;
}

/* --- Detail page --- */
.charts-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.chart-box label { display: block; font-size: 12px; color: var(--muted); margin-bottom: 4px; }
.chart { height: 110px; background: var(--bg-3); border-radius: 8px; }
.kv { display: grid; grid-template-columns: max-content 1fr; gap: 6px 16px; margin: 0; }
.kv dt { color: var(--muted); }
.kv dd { margin: 0; }

pre {
  background: var(--bg-3); border: 1px solid var(--border);
  border-radius: 8px; padding: 12px; overflow-x: auto;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
}
code {
  background: var(--bg-3); padding: 2px 6px; border-radius: 4px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
}

.banner {
  position: fixed; bottom: 16px; right: 16px;
  background: var(--alert); color: #fff;
  padding: 8px 14px; border-radius: 8px;
  box-shadow: var(--shadow);
}

a { color: var(--link); }

.spacer { flex: 1; }
.env-filter {
  background: var(--bg-3); color: var(--text);
  border: 1px solid var(--border); border-radius: 6px;
  padding: 6px 8px; font: inherit;
}
.tag {
  display: inline-block;
  padding: 1px 7px; border-radius: 999px;
  background: var(--bg-3); color: var(--muted);
  border: 1px solid var(--border);
  font-size: 11px; margin-right: 4px;
}
.cat-io  { background: rgba(240,100,100,0.15); color: var(--alert); }
.cat-ata { background: rgba(240,185,78,0.15);  color: var(--warn); }
.cat-fs  { background: rgba(240,100,100,0.15); color: var(--alert); }
.cat-oom { background: rgba(110,193,255,0.15); color: var(--link); }
.cat-mce { background: rgba(240,100,100,0.15); color: var(--alert); }

/* --- Server clock in sidebar footer --- */
.server-clock {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.2px;
}

/* --- Card head: keep h3 inline with controls (range selector, etc) --- */
.card-head {
  display: flex; align-items: center; gap: 8px;
  margin-bottom: 8px;
}
.card-head h3 { margin: 0; }
button.secondary.small {
  background: transparent; color: var(--text);
  border: 1px solid var(--border); border-radius: 6px;
  padding: 5px 10px; font-size: 12px;
}

/* --- Charts: visible cursor on hover, slightly bigger area --- */
.chart { height: 150px; }

/* --- Chart-box label: expand button sits right-aligned --- */
.chart-box label {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 12px; color: var(--muted); margin-bottom: 4px;
}
.chart-expand {
  background: transparent; color: var(--muted);
  border: 1px solid var(--border); border-radius: 4px;
  padding: 0 6px; font-size: 11px; line-height: 18px;
  cursor: pointer;
}
.chart-expand:hover { color: var(--accent); border-color: var(--accent); }

/* --- Pop-out chart modal --- */
.modal {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(0, 0, 0, 0.7);
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
}
.modal-card {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow);
  width: 95vw; max-width: 1400px;
  display: flex; flex-direction: column;
  padding: 18px 20px;
}
.modal-head {
  display: flex; align-items: center; gap: 12px;
  border-bottom: 1px solid var(--border);
  padding-bottom: 10px; margin-bottom: 10px;
}
.modal-head h3 { margin: 0; font-size: 16px; }
.modal-hint { margin: 0 0 12px; }
.chart-large {
  height: 70vh; min-height: 360px;
  background: var(--bg-3); border-radius: 8px;
}
