/* Parnex SSM — operations console.
   Calm, dense, high-contrast. Severity is always carried by a glyph and a text label
   as well as by colour. */

:root {
  color-scheme: light dark;

  --bg:            #f6f7f9;
  --surface:       #ffffff;
  --surface-sunk:  #f1f3f6;
  --border:        #d7dbe2;
  --border-strong: #b7bec9;

  --text:          #171a1f;
  --text-muted:    #5b6472;
  --text-inverse:  #ffffff;

  --accent:        #1f5fbf;
  --accent-dark:   #17488f;

  --healthy:       #1c7a4a;
  --healthy-bg:    #e6f4ec;
  --info:          #2b6cb0;
  --info-bg:       #e7f0f9;
  --warning:       #8a5800;
  --warning-bg:    #fdf1dc;
  --critical:      #b0231f;
  --critical-bg:   #fbe9e8;
  --offline:       #4a5160;
  --offline-bg:    #eceef2;
  --unknown:       #5b6472;
  --unknown-bg:    #f0f1f4;

  --radius:   6px;
  --radius-s: 4px;
  --shadow:   0 1px 2px rgba(16, 24, 40, .06), 0 1px 3px rgba(16, 24, 40, .10);

  --space-0: 2px;
  --space-1: 4px;  --space-2: 8px;  --space-3: 12px;
  --space-4: 16px; --space-5: 24px; --space-6: 32px; --space-7: 48px;

  /* Operations density. A monitoring console is read, not browsed: rows are scanned
     in bulk and the useful comparison is between rows, so vertical rhythm is tight. */
  --row-h:   28px;
  --spark-h: 24px;

  /* Chart series identity, deliberately NOT the severity ramp above. A red line must
     mean "this is the write series", never "this is bad" — severity colour is reserved
     for severity. Chosen to stay distinguishable under deuteranopia and protanopia;
     dash patterns in dashboard.js carry the same distinction without colour at all. */
  --series-1: #5191e6;
  --series-2: #bf6210;
  --series-3: #0d7567;
  --series-4: #7d30a4;
  --series-5: #573f0f;
  --series-6: #561942;

  /* One measure for a form column and anything that has to line up with it. */
  --form-width: 520px;

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    /* Lifted for dark surfaces; the light values fall below 3:1 against --surface. */
    --series-1: #1e6acf;
    --series-2: #c76610;
    --series-3: #13a894;
    --series-4: #ca9be2;
    --series-5: #e7c277;
    --series-6: #f5dced;

    --bg:            #12151a;
    --surface:       #1a1e25;
    --surface-sunk:  #161a20;
    --border:        #2b313b;
    --border-strong: #3b434f;

    --text:          #e8eaee;
    --text-muted:    #9aa3b2;

    --accent:        #6aa3f0;
    --accent-dark:   #8dbcf7;

    --healthy:       #5fd39a;  --healthy-bg:  #14301f;
    --info:          #7cb3ec;  --info-bg:     #16253a;
    --warning:       #e6b45c;  --warning-bg:  #33270f;
    --critical:      #f08a84;  --critical-bg: #3a1917;
    --offline:       #9aa3b2;  --offline-bg:  #22262e;
    --unknown:       #9aa3b2;  --unknown-bg:  #20242b;

    --shadow: 0 1px 2px rgba(0, 0, 0, .4);
  }
}

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.5;
  /* Tabular figures everywhere. Proportional digits change width as a value updates,
     which makes a column of readings shuffle sideways while being read. */
  font-variant-numeric: tabular-nums;
  color: var(--text);
  background: var(--bg);
  -webkit-text-size-adjust: 100%;
}

h1, h2, h3 { margin: 0; font-weight: 600; line-height: 1.25; letter-spacing: -0.01em; }
h1 { font-size: 20px; }
h2 { font-size: 16px; }
h3 { font-size: 14px; }
p  { margin: 0 0 var(--space-3); }
p:last-child { margin-bottom: 0; }
code { font-family: var(--mono); font-size: 0.92em; }

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--accent-dark); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-s);
}

.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; left: -9999px; top: var(--space-2);
  background: var(--surface); padding: var(--space-2) var(--space-4);
  border: 1px solid var(--border); border-radius: var(--radius); z-index: 100;
}
.skip-link:focus { left: var(--space-4); }

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

/* ---------- top bar ---------- */
.topbar {
  display: flex; align-items: center; gap: var(--space-5);
  padding: 0 var(--space-5); height: 52px;
  background: var(--surface); border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 20;
}
.topbar__brand { display: flex; align-items: center; }
/* The lockup already carries the product name, so the bar does not repeat it as text.
   Only the height is ours to pick; the artwork supplies the width. 36px is the floor —
   the tagline stops resolving below roughly that and reads as a smudge, and the mark
   descends to the tagline's baseline, so it cannot be cropped away to buy height. */
.topbar__logo { display: block; height: 36px; width: auto; }
.topbar__nav { display: flex; gap: var(--space-1); margin-right: auto; }
/* The overflow disclosure is a nav item like any other, so it shares the selector
   rather than being restyled to look similar and drifting later. */
.topbar__nav a,
.topbar__nav > .topbar__more > summary {
  display: inline-flex; align-items: center;
  padding: var(--space-2) var(--space-3); border-radius: var(--radius-s);
  color: var(--text-muted); text-decoration: none; font-weight: 500;
  font-size: inherit; font-family: inherit; line-height: inherit;
  white-space: nowrap;
}
.topbar__nav a:hover,
.topbar__nav > .topbar__more > summary:hover { background: var(--surface-sunk); color: var(--text); }
.topbar__nav a[aria-current="page"],
.topbar__nav > .topbar__more[open] > summary,
.topbar__nav > .topbar__more--active > summary {
  color: var(--text); background: var(--surface-sunk);
}
.topbar__nav a[aria-current="page"],
.topbar__nav > .topbar__more--active > summary {
  box-shadow: inset 0 -2px 0 var(--accent);
}
/* Keyboard focus must stay visible on the summary, which has no default ring here. */
.topbar__nav > .topbar__more > summary:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
.topbar__account { display: flex; align-items: center; gap: var(--space-3); }
.topbar__user { display: flex; flex-direction: column; text-decoration: none; color: var(--text); line-height: 1.2; }
.topbar__user-role { font-size: 11px; color: var(--text-muted); }
.topbar__logout { margin: 0; }

/* ---------- layout ---------- */
.main { max-width: 1440px; margin: 0 auto; padding: var(--space-5); }
.footer {
  max-width: 1440px; margin: 0 auto; padding: var(--space-4) var(--space-5) var(--space-6);
  display: flex; flex-wrap: wrap; gap: var(--space-2);
  color: var(--text-muted); font-size: 12px;
}

.page-head {
  display: flex; flex-wrap: wrap; gap: var(--space-4);
  align-items: flex-start; justify-content: space-between;
  margin-bottom: var(--space-5);
}
.page-head__meta { color: var(--text-muted); font-size: 13px; margin: var(--space-1) 0 0; }
.page-head__status { text-align: right; }
.page-head__freshness { font-size: 12px; color: var(--text-muted); margin: var(--space-2) 0 0; max-width: 44ch; }

.section-heading {
  font-size: 12px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-muted); margin: var(--space-6) 0 var(--space-3);
}
.section-heading:first-of-type { margin-top: 0; }

.split { display: grid; gap: var(--space-4); grid-template-columns: repeat(auto-fit, minmax(420px, 1fr)); }
.row { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; }

/* ---------- cards & panels ---------- */
.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow);
  padding: var(--space-4); margin-bottom: var(--space-4);
}
.card--narrow { max-width: 560px; }
.card--danger { border-color: color-mix(in srgb, var(--critical) 40%, var(--border)); }
.card__head { margin-bottom: var(--space-4); }
.card__note { font-size: 12px; color: var(--text-muted); margin: var(--space-1) 0 0; max-width: 68ch; }

.panel { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: var(--space-6); }
.panel--centered { max-width: 640px; margin: var(--space-7) auto; text-align: center; }
.error__code { font-size: 40px; font-weight: 700; color: var(--text-muted); margin: 0; line-height: 1; }

.empty { color: var(--text-muted); text-align: center; padding: var(--space-5); margin: 0; }

/* ---------- notices ---------- */
.notice {
  display: flex; gap: var(--space-3); align-items: flex-start;
  padding: var(--space-3) var(--space-4); border-radius: var(--radius);
  border: 1px solid var(--border); margin-bottom: var(--space-4);
}
.notice__glyph {
  flex: 0 0 auto; width: 18px; height: 18px; border-radius: 50%;
  display: grid; place-items: center; font-size: 11px; font-weight: 700;
  background: currentColor; color: var(--surface);
}
.notice--success { background: var(--healthy-bg);  border-color: var(--healthy);  color: var(--healthy); }
.notice--info    { background: var(--info-bg);     border-color: var(--info);     color: var(--info); }
.notice--warning { background: var(--warning-bg);  border-color: var(--warning);  color: var(--warning); }
.notice--error   { background: var(--critical-bg); border-color: var(--critical); color: var(--critical); }
.notice > span:not(.notice__glyph), .notice > div { color: var(--text); }

/* ---------- severity pills ---------- */
.pill {
  display: inline-flex; align-items: center; gap: var(--space-1);
  padding: 2px var(--space-2); border-radius: 100px;
  font-size: 11px; font-weight: 600; white-space: nowrap;
  border: 1px solid transparent;
}
.pill__glyph { font-size: 10px; line-height: 1; }
.pill--healthy  { background: var(--healthy-bg);  color: var(--healthy);  border-color: color-mix(in srgb, var(--healthy) 30%, transparent); }
.pill--info     { background: var(--info-bg);     color: var(--info);     border-color: color-mix(in srgb, var(--info) 30%, transparent); }
.pill--warning  { background: var(--warning-bg);  color: var(--warning);  border-color: color-mix(in srgb, var(--warning) 35%, transparent); }
.pill--critical { background: var(--critical-bg); color: var(--critical); border-color: color-mix(in srgb, var(--critical) 35%, transparent); }
.pill--offline  { background: var(--offline-bg);  color: var(--offline);  border-color: color-mix(in srgb, var(--offline) 30%, transparent); }
.pill--unknown  { background: var(--unknown-bg);  color: var(--unknown);  border-color: color-mix(in srgb, var(--unknown) 30%, transparent); }

/* ---------- toolbar ---------- */
.toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4);
  padding: var(--space-3) var(--space-4); margin-bottom: var(--space-4);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
}
.toolbar__group { display: flex; align-items: center; gap: var(--space-2); }
.toolbar__label, .toolbar label { font-size: 12px; color: var(--text-muted); font-weight: 500; }
/* Pushes a destructive action to the far end of a toolbar: same bar, deliberate
   distance from the primary button next to it. */
.toolbar__end { margin-left: auto; }
.toolbar__resolution { margin: 0 0 0 auto; font-size: 12px; color: var(--text-muted); font-variant-numeric: tabular-nums; }

.chip {
  padding: 3px var(--space-3); border-radius: 100px; font-size: 12px;
  text-decoration: none; color: var(--text-muted);
  border: 1px solid var(--border);
}
.chip:hover { border-color: var(--border-strong); color: var(--text); }
.chip--active { background: var(--accent); border-color: var(--accent); color: var(--text-inverse); font-weight: 600; }
.chip--active:hover { color: var(--text-inverse); }

/* ---------- KPI grid ---------- */
.kpi-grid { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.kpi {
  background: var(--surface); border: 1px solid var(--border);
  border-left: 3px solid var(--border-strong);
  border-radius: var(--radius); padding: var(--space-3) var(--space-4); box-shadow: var(--shadow);
}
.kpi--healthy  { border-left-color: var(--healthy); }
.kpi--info     { border-left-color: var(--info); }
.kpi--warning  { border-left-color: var(--warning); }
.kpi--critical { border-left-color: var(--critical); }
.kpi--offline  { border-left-color: var(--offline); }
.kpi--unknown  { border-left-color: var(--unknown); }
.kpi__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.kpi__label { font-size: 12px; color: var(--text-muted); font-weight: 500; }
.kpi__value {
  font-size: 26px; font-weight: 600; letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums; margin: var(--space-2) 0 0;
}
.kpi__context, .kpi__freshness { font-size: 11px; color: var(--text-muted); margin: var(--space-1) 0 0; }

/* ---------- charts ---------- */
.chart-grid { display: grid; gap: var(--space-4); grid-template-columns: repeat(auto-fit, minmax(460px, 1fr)); }
.chart-card { margin-bottom: 0; display: flex; flex-direction: column; }
.chart-card__canvas { position: relative; height: 220px; margin-bottom: var(--space-3); }
.chart-card__canvas canvas { width: 100% !important; height: 100% !important; }
.chart-card__state {
  position: absolute; inset: 0; display: grid; place-items: center;
  font-size: 12px; color: var(--text-muted); background: var(--surface); margin: 0;
}
.chart-card__state[hidden] { display: none; }
.chart-card__summary { width: 100%; border-collapse: collapse; font-size: 12px; }
.chart-card__summary th, .chart-card__summary td {
  padding: var(--space-1) var(--space-2); text-align: right;
  border-top: 1px solid var(--border); font-variant-numeric: tabular-nums;
}
.chart-card__summary th:first-child, .chart-card__summary td:first-child { text-align: left; font-weight: 500; }
.chart-card__summary thead th { color: var(--text-muted); font-weight: 500; border-top: 0; }

/* ---------- tables ---------- */
.table-scroll { overflow-x: auto; }
.table { width: 100%; border-collapse: collapse; font-size: 13px; }
.table th, .table td {
  padding: var(--space-2) var(--space-3); text-align: left;
  border-bottom: 1px solid var(--border); vertical-align: middle;
}
.table thead th {
  font-size: 11px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--text-muted); font-weight: 600; white-space: nowrap;
  border-bottom: 1px solid var(--border-strong);
}
.table tbody tr:last-child th, .table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: var(--surface-sunk); }
.table--dense th, .table--dense td { padding: var(--space-1) var(--space-2); font-size: 12px; }
.stack { display: flex; flex-direction: column; line-height: 1.35; }
.stack .muted { font-size: 12px; font-weight: 400; }

.meter { position: relative; min-width: 110px; height: 18px; background: var(--surface-sunk); border-radius: var(--radius-s); overflow: hidden; }
.meter__bar { position: absolute; inset: 0 auto 0 0; width: 0; border-radius: var(--radius-s); }
.meter__bar--healthy  { background: color-mix(in srgb, var(--healthy) 35%, transparent); }
.meter__bar--info     { background: color-mix(in srgb, var(--info) 35%, transparent); }
.meter__bar--warning  { background: color-mix(in srgb, var(--warning) 45%, transparent); }
.meter__bar--critical { background: color-mix(in srgb, var(--critical) 45%, transparent); }
.meter__bar--unknown, .meter__bar--offline { background: var(--border); }
.meter__text {
  position: relative; display: block; text-align: center; line-height: 18px;
  font-size: 11px; font-variant-numeric: tabular-nums; font-weight: 600;
}

.tag {
  display: inline-block; padding: 1px var(--space-2); margin: 1px;
  background: var(--surface-sunk); border-radius: var(--radius-s);
  font-size: 11px; font-family: var(--mono); color: var(--text-muted);
}
.audit__context { max-width: 320px; }

/* ---------- forms ---------- */
.form { max-width: var(--form-width); }
/* A form and its action bar are one column even though they are two elements. The
   bar has to sit outside the <form> wherever it carries a destructive action, since
   that needs a POST of its own and HTML forbids nesting forms — without this the bar
   would ignore the form's measure and run the full width of the page. */
.form-stack { max-width: var(--form-width); }
.form-stack > .form { max-width: none; }
.field { margin-bottom: var(--space-4); }
.field label { display: block; font-size: 13px; font-weight: 500; margin-bottom: var(--space-1); }
.field__help { font-size: 12px; color: var(--text-muted); margin: var(--space-1) 0 0; }
.field--check { display: flex; align-items: flex-start; gap: var(--space-2); }
/* Two numbers that are only meaningful together — a threshold and its window, a
   failure count and a recovery count. Side by side so the pair reads as one
   setting; stacked at the same 640px breakpoint the rest of the sheet uses, where
   two number inputs side by side stop being legible. */
.field--pair { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
.field--pair > span { display: block; }
@media (max-width: 640px) { .field--pair { grid-template-columns: 1fr; } }
.field--check label { margin: 0; font-weight: 400; }

input[type="text"], input[type="email"], input[type="password"], input[type="search"],
input[type="number"], select {
  width: 100%; padding: var(--space-2) var(--space-3);
  font: inherit; color: var(--text);
  background: var(--surface); border: 1px solid var(--border-strong);
  border-radius: var(--radius-s);
}
.toolbar input, .toolbar select { width: auto; min-width: 160px; }
input:focus, select:focus { border-color: var(--accent); }
.input--code { font-family: var(--mono); font-size: 20px; letter-spacing: .3em; text-align: center; }

.fieldset { border: 1px solid var(--border); border-radius: var(--radius); padding: var(--space-3); margin: 0 0 var(--space-4); }
.fieldset legend { font-size: 12px; font-weight: 600; color: var(--text-muted); padding: 0 var(--space-2); }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-4); font: inherit; font-weight: 500;
  color: var(--text); background: var(--surface);
  border: 1px solid var(--border-strong); border-radius: var(--radius-s);
  cursor: pointer; text-decoration: none;
}
.btn:hover { background: var(--surface-sunk); color: var(--text); }
.btn--primary { background: var(--accent); border-color: var(--accent); color: var(--text-inverse); }
.btn--primary:hover { background: var(--accent-dark); border-color: var(--accent-dark); color: var(--text-inverse); }
.btn--danger { background: var(--critical); border-color: var(--critical); color: #fff; }
.btn--danger:hover { filter: brightness(.92); color: #fff; }
.btn--quiet { background: transparent; border-color: transparent; color: var(--text-muted); }
.btn--quiet:hover { background: var(--surface-sunk); color: var(--text); }
.btn--block { width: 100%; }

.pagination { display: flex; align-items: center; gap: var(--space-3); justify-content: center; padding: var(--space-4) 0; }
.pagination__status { font-size: 12px; color: var(--text-muted); }

/* ---------- auth ---------- */
.auth { display: grid; place-items: center; min-height: 100vh; padding: var(--space-5); }
.auth__card {
  width: 100%; max-width: 400px; padding: var(--space-6);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow);
}
.auth--wide .auth__card { max-width: 640px; }
.auth__title { margin-bottom: var(--space-1); }
.auth__subtitle { color: var(--text-muted); font-size: 13px; margin-bottom: var(--space-5); }
.auth__hint { font-size: 12px; color: var(--text-muted); margin-top: var(--space-4); }
.auth__recovery { margin-top: var(--space-5); border-top: 1px solid var(--border); padding-top: var(--space-4); }
.auth__recovery summary { cursor: pointer; font-size: 13px; color: var(--accent); }
.auth__cancel { margin-top: var(--space-4); text-align: center; }

.steps { margin: 0; padding-left: var(--space-5); }
.steps > li { margin-bottom: var(--space-5); }
.steps h2 { font-size: 14px; margin-bottom: var(--space-2); }
.steps--compact > li { margin-bottom: var(--space-2); }

.secret {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3);
  padding: var(--space-3); margin-bottom: var(--space-3);
  background: var(--surface-sunk); border: 1px solid var(--border); border-radius: var(--radius);
}
.secret__label { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--text-muted); }
.secret__value { font-family: var(--mono); font-size: 15px; letter-spacing: .08em; word-break: break-all; }

.codes { list-style: none; padding: 0; margin: var(--space-4) 0; display: grid; gap: var(--space-2); grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.codes code {
  display: block; padding: var(--space-2); text-align: center;
  background: var(--surface-sunk); border: 1px solid var(--border); border-radius: var(--radius-s);
  font-size: 14px; letter-spacing: .05em;
}

.kv { display: grid; grid-template-columns: max-content 1fr; gap: var(--space-1) var(--space-4); margin: 0 0 var(--space-4); font-size: 13px; }
.kv dt { color: var(--text-muted); }
.kv dd { margin: 0; }
.kv--inline { margin-bottom: var(--space-3); }

/* ---------- section sub-navigation ---------- */
.subnav { display: flex; flex-wrap: wrap; gap: var(--space-1); margin: 0 0 var(--space-4);
          border-bottom: 1px solid var(--border); }
.subnav__link { padding: var(--space-2) var(--space-3); font-size: 13px; text-decoration: none;
                color: var(--text-muted); border-bottom: 2px solid transparent; margin-bottom: -1px; }
.subnav__link:hover { color: var(--text); }
/* The active tab carries a weight and a rule, not only a colour. */
.subnav__link--active { color: var(--text); font-weight: 600; border-bottom-color: var(--accent); }

/* ---------- alert summary counters ---------- */
/* Severity is carried by the glyph and the label as well as the colour, so the tint
   here is reinforcement rather than the only signal. */
.stat-row { display: flex; flex-wrap: wrap; gap: var(--space-3); list-style: none; padding: 0; margin: 0 0 var(--space-4); }
.stat { display: flex; flex-direction: column; gap: 2px; min-width: 96px; padding: var(--space-3) var(--space-4);
        border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-sunk); }
.stat__value { font-size: 24px; font-weight: 600; line-height: 1.1; font-variant-numeric: tabular-nums; }
.stat__label { font-size: 12px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.stat--critical { border-color: var(--critical); background: var(--critical-bg); }
.stat--critical .stat__value { color: var(--critical); }
.stat--warning { border-color: var(--warning); background: var(--warning-bg); }
.stat--warning .stat__value { color: var(--warning); }

/* ---------- responsive ---------- */

/* ---------------------------------------------------------------- triage bar
   Rendered only when something is wrong, so its presence is itself the signal.
   A permanent "all clear" strip becomes furniture and stops being read. */
.triage {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas: "glyph title" "glyph items";
  gap: 0 var(--space-3);
  align-items: start;
  margin-bottom: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border-strong);
  border-left-width: 4px;
  border-radius: var(--radius);
  background: var(--surface);
}
.triage--critical { border-left-color: var(--critical); background: var(--critical-bg); }
.triage--warning  { border-left-color: var(--warning);  background: var(--warning-bg); }
.triage--offline  { border-left-color: var(--offline);  background: var(--offline-bg); }
.triage--unknown  { border-left-color: var(--unknown);  background: var(--unknown-bg); }
.triage__glyph { grid-area: glyph; font-size: 18px; line-height: 1.4; }
.triage--critical .triage__glyph { color: var(--critical); }
.triage--warning  .triage__glyph { color: var(--warning); }
.triage__title { grid-area: title; margin: 0; font-size: 14px; font-weight: 600; }
.triage__items {
  grid-area: items;
  display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4);
  margin: var(--space-1) 0 0; padding: 0; list-style: none;
}
.triage__items li::before { content: "·"; margin-right: var(--space-2); color: var(--text-muted); }
.triage__items li:first-child::before { content: none; }

/* ------------------------------------------------------------- vitals strip
   Replaces the KPI card grid. Compact enough that eight subsystems fit one row
   on a desktop, so the comparison between them is a glance rather than a scroll. */
.vitals {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--space-2);
  margin: 0 0 var(--space-5); padding: 0;
  list-style: none;
}
.vital {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0 var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border);
  border-top: 3px solid var(--border-strong);
  border-radius: var(--radius-s);
  background: var(--surface);
}
.vital--healthy  { border-top-color: var(--healthy); }
.vital--info     { border-top-color: var(--info); }
.vital--warning  { border-top-color: var(--warning); }
.vital--critical { border-top-color: var(--critical); }
.vital--offline  { border-top-color: var(--offline); }
.vital--unknown  { border-top-color: var(--unknown); }

.vital__label   { grid-column: 1 / -1; font-size: 12px; color: var(--text-muted); }
.vital__value   { font-size: 20px; font-weight: 600; line-height: 1.2; }
.vital__state   { justify-self: end; align-self: center; display: flex; align-items: center; gap: var(--space-1); font-size: 11px; }
.vital__glyph   { font-size: 12px; }
.vital--healthy  .vital__glyph, .vital--healthy  .vital__severity { color: var(--healthy); }
.vital--info     .vital__glyph, .vital--info     .vital__severity { color: var(--info); }
.vital--warning  .vital__glyph, .vital--warning  .vital__severity { color: var(--warning); }
.vital--critical .vital__glyph, .vital--critical .vital__severity { color: var(--critical); }
.vital--offline  .vital__glyph, .vital--offline  .vital__severity { color: var(--offline); }
.vital--unknown  .vital__glyph, .vital--unknown  .vital__severity { color: var(--unknown); }
.vital__context { grid-column: 1 / -1; font-size: 11px; color: var(--text-muted); }
/* Height is reserved so the row does not jump when the sparkline finishes loading. */
.vital__spark   { grid-column: 1 / -1; display: block; position: relative;
                  width: 100%; height: var(--spark-h); margin-top: var(--space-1); }
/* Same containment as .chart-card__canvas, and required for the same reason: a
   responsive Chart.js canvas fills its parent, so the parent must be the thing
   with the height. Without this the sparkline grew its own cell without bound. */
.vital__spark canvas { display: block; width: 100% !important; height: 100% !important; }

/* -------------------------------------------------------------- custom range */
.range-custom { position: relative; display: inline-block; }
.range-custom > summary { cursor: pointer; list-style: none; }
.range-custom > summary::-webkit-details-marker { display: none; }
.range-custom__form {
  position: absolute; z-index: 40; top: calc(100% + var(--space-1)); left: 0;
  display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: flex-end;
  padding: var(--space-3);
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  background: var(--surface); box-shadow: var(--shadow);
}
.range-custom__field { display: flex; flex-direction: column; gap: var(--space-1); }
.range-custom__field label { font-size: 11px; color: var(--text-muted); }
.range-custom__error {
  position: absolute; z-index: 40; top: calc(100% + var(--space-1)); left: 0;
  margin: 0; max-width: 32ch; color: var(--warning);
}

/* --------------------------------------------------------- availability band
   Discrete segments, not a line. Uptime is a state over time, and a line drawn
   between 100 and 0 implies values in between that were never observed. */
.availability__figure { display: flex; align-items: center; gap: var(--space-3); margin: 0 0 var(--space-2); }
.availability__value  { font-size: 22px; font-weight: 600; }
.availability__band {
  display: flex; gap: 1px; margin: 0 0 var(--space-2); padding: 0;
  list-style: none; height: 20px; border-radius: var(--radius-s); overflow: hidden;
}
.availability__seg { flex: 1 1 auto; min-width: 2px; }
.availability__seg--up    { background: var(--healthy); }
.availability__seg--down  { background: var(--critical); }
.availability__seg--error { background: var(--unknown); }
.availability__note { margin: 0; font-size: 12px; color: var(--text-muted); }

/* ------------------------------------------------------------- dense tables */
.table--dense th, .table--dense td { padding-top: var(--space-1); padding-bottom: var(--space-1); height: var(--row-h); }

/* --------------------------------------------------------------- navigation */
/* The nav scrolls horizontally below 900px; without an edge fade nothing says so. */
.topbar__nav { scrollbar-width: thin; }
.topbar__more { position: relative; display: flex; align-items: center; }
.topbar__more > summary { cursor: pointer; list-style: none; }
.topbar__more > summary::-webkit-details-marker { display: none; }
.topbar__more-menu {
  position: absolute; z-index: 100; right: 0; top: calc(100% + var(--space-1));
  display: flex; flex-direction: column; min-width: 160px;
  padding: var(--space-1);
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  background: var(--surface); box-shadow: var(--shadow);
}

/* ------------------------------------------------------------- breadcrumbs */
.breadcrumb { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: 0 0 var(--space-3); padding: 0; list-style: none; font-size: 12px; }
.breadcrumb li + li::before { content: "›"; margin-right: var(--space-2); color: var(--text-muted); }

@media (max-width: 900px) {
  .topbar { flex-wrap: wrap; height: auto; padding: var(--space-3) var(--space-4); gap: var(--space-3); }
  .topbar__nav { order: 3; width: 100%; overflow-x: auto; }
  .main { padding: var(--space-4) var(--space-3); }
  .split, .chart-grid { grid-template-columns: 1fr; }
  .vitals { grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); }
  /* A popover anchored to a chip runs off a narrow screen; in the flow it cannot. */
  .range-custom { position: static; }
  .range-custom__form, .range-custom__error { position: static; max-width: none; }
  .range-custom__form { margin-top: var(--space-2); }
  /* A fade at the trailing edge, so a nav that scrolls looks like one. The spacer
     keeps the last link clear of the fade rather than under it. Masking degrades to
     "no fade" where unsupported, which is the previous behaviour, not a broken one. */
  .topbar__nav {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent);
            mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent);
  }
  .topbar__nav::after { content: ""; flex: 0 0 var(--space-5); }
  .stat { flex: 1 1 40%; min-width: 0; }
  .chart-card__canvas { height: 200px; }
  .toolbar__resolution { margin-left: 0; width: 100%; }
  .page-head__status { text-align: left; }
}

@media print {
  .topbar, .toolbar, .btn, .skip-link { display: none !important; }
  /* The footer stays, because the ownership line is inside it. Its screen-only parts
     are hidden instead of the whole bar: display:none on the parent would take the
     notice with it, and nothing a child declares can undo that. */
  .footer > :not(.copyright) { display: none !important; }
  .footer {
    margin-top: 1rem; padding: 0.5rem 0 0;
    border-top: 1px solid #999; color: #000; font-size: 8pt;
  }
  body { background: #fff; }
  .card, .kpi { box-shadow: none; border-color: #999; break-inside: avoid; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ------------------------------------------------------------------ services
   The findings list: one row per thing that is wrong, with the severity pill on
   the left so the column of glyphs can be scanned without reading the sentences.
   Deliberately not a table — these rows are of unequal height by nature, because
   a service can carry more than one finding at once. */
.card--warning { border-color: color-mix(in srgb, var(--warning) 40%, var(--border)); }

.findings { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--space-2); }
.finding {
  display: grid;
  grid-template-columns: minmax(9rem, auto) 1fr;
  gap: 0 var(--space-3);
  align-items: start;
  padding: var(--space-2) 0;
  border-top: 1px solid var(--border);
}
.finding:first-child { border-top: 0; padding-top: 0; }
.finding__state { grid-column: 1; }
.finding__body  { grid-column: 2; min-width: 0; }
.finding__notes {
  margin: var(--space-1) 0 0; padding: 0; list-style: none;
  font-size: 12px; color: var(--text-muted); max-width: 78ch;
}
.finding__notes li + li { margin-top: 2px; }

/* A value that disagrees with what was configured. Never colour alone: every use
   sits beside the literal word ("disabled", "Never"), and the surrounding row
   carries a severity pill that states the same thing in text. */
.is-wrong { color: var(--warning); font-weight: 600; }

.card__filter { display: flex; align-items: center; gap: var(--space-2); font-size: 12px; }
.card__filter label { color: var(--text-muted); }

/* The unit picker. A datalist rather than a <select>: a host reports several
   hundred units, and typing "ngin" beats scrolling past 500 options — while the
   list still means the value came from what the host published. */
.unit-picker { display: grid; gap: var(--space-1); }
.unit-picker__count { font-size: 12px; color: var(--text-muted); }

@media (max-width: 640px) {
  .finding { grid-template-columns: 1fr; gap: var(--space-1); }
  .finding__state, .finding__body { grid-column: 1; }
}
