/* SPDX-License-Identifier: AGPL-3.0-only */
/* Webmonit — dark first, light when chosen or when the system asks;
   one accent; data in monospace; small radii; no library, no font
   download. */
:root {
  --ground: #0d141d; --ground-2: #121b26; --panel: #1a2634; --panel-2: #22303f; --panel-3: #2a3a4c;
  --line: rgba(255,255,255,.10); --line-2: rgba(255,255,255,.18);
  --ink: #f4f7fa; --ink-2: #d5dde6; --mute: #aab5c2;
  --act: #5c98ff; --act-2: #8b6cff; --act-ink: #fff;
  --ok: #6fd39c; --chart: #59d38f; --chart-2: #5c98ff; --warn: #f0c14b; --danger: #ff6b86; --red: #ff5252; --maint: #7fb5ff; --ext: #b79bff; --unknown: #7a8795; --ack: #9aa8c7;
  --orange: #e8944a;
  --field: rgba(0,0,0,.28); --overlay: #1e2b3a; --shadow: 0 10px 34px rgba(0,0,0,.45); --glow: rgba(92,152,255,.28);
  --mono: ui-monospace, "SFMono-Regular", Menlo, Consolas, "Liberation Mono", monospace;
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --r: 10px; --r-s: 7px; --t: .16s ease;
  color-scheme: dark;
}
:root[data-theme="light"] {
  --ground: #eef1f5; --ground-2: #e6eaf0; --panel: #fff; --panel-2: #f1f4f8; --panel-3: #e5eaf1;
  --line: rgba(20,30,45,.10); --line-2: rgba(20,30,45,.20);
  --ink: #121a24; --ink-2: #2f3b49; --mute: #5b6875;
  --act: #2b6fe6; --act-2: #6a4ce6;
  --ok: #1f9d5b; --chart: #12925a; --chart-2: #2b6fe6; --warn: #b8860b; --danger: #d6335a; --red: #d61f1f; --maint: #2b6fe6; --ext: #7a4fd6; --unknown: #8a95a1; --ack: #5b6b8f;
  --orange: #c2691a;
  --field: #fff; --overlay: #fff; --shadow: 0 10px 34px rgba(20,30,45,.16); --glow: rgba(43,111,230,.2);
  color-scheme: light;
}
@media (prefers-color-scheme: light) { :root:not([data-theme="dark"]) {
  --ground: #eef1f5; --ground-2: #e6eaf0; --panel: #fff; --panel-2: #f1f4f8; --panel-3: #e5eaf1;
  --line: rgba(20,30,45,.10); --line-2: rgba(20,30,45,.20);
  --ink: #121a24; --ink-2: #2f3b49; --mute: #5b6875;
  --act: #2b6fe6; --act-2: #6a4ce6;
  --ok: #1f9d5b; --chart: #12925a; --chart-2: #2b6fe6; --warn: #b8860b; --danger: #d6335a; --red: #d61f1f; --maint: #2b6fe6; --ext: #7a4fd6; --unknown: #8a95a1; --ack: #5b6b8f;
  --orange: #c2691a;
  --field: #fff; --overlay: #fff; --shadow: 0 10px 34px rgba(20,30,45,.16); --glow: rgba(43,111,230,.2);
  color-scheme: light;
} }
* { box-sizing: border-box; }
html, body { margin: 0; min-height: 100%; }
body { background: var(--ground); color: var(--ink); font: 14px/1.5 var(--sans); }
a { color: var(--act); text-decoration: none; transition: color var(--t); }
a:hover { color: var(--act-2); }
code, .mono, input, select, textarea, pre { font-family: var(--mono); font-size: 13px; }
h1, h2, h3 { font-weight: 650; letter-spacing: -0.01em; margin: 0 0 .5rem; color: var(--ink); }
h1 { font-size: 21px; display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
h2 { color: var(--ink-2); text-transform: uppercase; letter-spacing: .1em; font-size: 11.5px; margin-top: 1.6rem; font-weight: 700; display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
h2 a { color: var(--ink); text-transform: none; letter-spacing: 0; font-size: 14px; }
h2 .mono, h2 .dim { text-transform: none; letter-spacing: 0; font-weight: 400; }
p { margin: 0 0 .75rem; color: var(--ink-2); }
.dim { color: var(--mute); }
.small { font-size: 12px; }
button, .btn { background: var(--panel-2); color: var(--ink); border: 1px solid var(--line); border-radius: var(--r-s); padding: .42rem .85rem; cursor: pointer; font: inherit; line-height: 1.3; transition: background var(--t), border-color var(--t), transform var(--t); }
button:hover, .btn:hover { background: var(--panel-3); border-color: var(--line-2); transform: translateY(-1px); color: var(--ink); }
button.primary { background: linear-gradient(135deg, var(--act), var(--act-2)); color: #fff; font-weight: 600; border-color: transparent; box-shadow: 0 4px 14px var(--glow); }
button.danger { color: var(--danger); background: color-mix(in srgb, var(--danger) 10%, transparent); border-color: color-mix(in srgb, var(--danger) 25%, transparent); }
button.small, .btn.small { padding: .24rem .6rem; font-size: 12px; }
button.ghost { background: transparent; border-color: transparent; color: var(--ink-2); }
button.on, .chips button.on { background: var(--panel-3); border-color: var(--act); }
button:disabled { opacity: .5; cursor: default; transform: none; }
input, select, textarea { background: var(--field); color: var(--ink); border: 1px solid var(--line-2); border-radius: var(--r-s); padding: .42rem .65rem; }
input:focus, select:focus { border-color: var(--act); box-shadow: 0 0 0 3px var(--glow); outline: none; }
label { color: var(--ink); font-size: 12px; display: block; margin-bottom: .2rem; }
label input, label select { display: block; width: 100%; margin-top: .15rem; }
label.check { display: flex; align-items: center; gap: .45rem; font-size: 13px; }
label.check input { width: auto; }
.hint { color: var(--mute); font-size: 12px; margin: .35rem 0 0; }
.inline { display: inline-flex; gap: .5rem; align-items: flex-end; flex-wrap: wrap; }
.inline label { margin: 0; }
form.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: .6rem; align-items: end; margin-top: .6rem; }
/* A block that belongs to the whole form, not to one column. */
form.grid > .wide, form.grid > fieldset { grid-column: 1 / -1; }
form.grid > button { grid-column: 1 / -1; justify-self: start; }
details.adder summary { list-style: none; display: inline-block; }
details.adder[open] summary { margin-bottom: .4rem; }

/* header */
/* An anchor followed lands under the sticky top bar otherwise: what
   the reader clicked on sits a bar's height too low. */
html { scroll-padding-top: 4rem; }
.top { display: grid; grid-template-columns: auto 1fr auto; gap: 1rem; align-items: center; padding: .55rem 1.2rem; border-bottom: 1px solid var(--line); background: var(--panel); position: sticky; top: 0; z-index: 5; }
.brand { color: var(--ink); font-weight: 700; white-space: nowrap; font-size: 15.5px; display: flex; align-items: center; gap: .45rem; }
.brand .logo { height: 20px; width: auto; display: block; }
.loginlogo { height: 54px; width: auto; display: block; margin: 0 auto .75rem; }
.menu { display: flex; gap: .2rem; flex-wrap: wrap; align-items: center; }
.menu a, .menu .drop > a { color: var(--ink-2); padding: .3rem .7rem; border-radius: var(--r-s); display: inline-block; line-height: 1.4; }
.menu a:hover { background: var(--panel-2); color: var(--ink); }
.menu a.on, .menu .drop.on > a { background: var(--panel-3); color: var(--ink); }
.drop { position: relative; display: inline-flex; align-items: center; }
.drop .panel { display: none; position: absolute; top: 100%; left: 0; background: var(--overlay); border: 1px solid var(--line-2); border-radius: var(--r-s); box-shadow: var(--shadow); padding: .3rem; min-width: 180px; z-index: 10; flex-direction: column; }
.drop:hover .panel, .drop:focus-within .panel, .drop.open .panel { display: flex; }
.drop .panel a { display: block; }
.who { display: flex; gap: .6rem; align-items: center; }
.who form { display: inline; }
.who a.on { color: var(--ink); text-decoration: underline; }
/* theme toggle: auto / dark / light */
.theme { display: none; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: 50%; border: 1px solid var(--line); background: var(--panel-2); color: var(--ink-2); cursor: pointer; padding: 0; }
.js .theme { display: inline-flex; }
.theme:hover { color: var(--ink); border-color: var(--mute); transform: none; }
.theme svg { width: 18px; height: 18px; display: none; }
.theme[data-mode="auto"] .i-auto, .theme[data-mode="dark"] .i-dark, .theme[data-mode="light"] .i-light { display: block; }
.tabs { display: flex; gap: .3rem; margin: .6rem 0; }
.tabs a { padding: .3rem .8rem; border-radius: var(--r-s); border: 1px solid var(--line); color: var(--ink-2); }
.tabs a.on { background: var(--panel-3); color: var(--ink); border-color: var(--act); }
.toolbar { display: flex; gap: .4rem; flex-wrap: wrap; align-items: center; margin-top: .4rem; }
.toolbar .filter { width: 320px; }
.toolbar .short { width: 150px; }
.crumbs { margin: 0 0 .2rem; font-size: 12px; }
.family { display: flex; gap: .4rem; flex-wrap: wrap; margin: .4rem 0 .8rem; }
.pill { display: inline-flex; align-items: center; gap: .4rem; padding: .2rem .6rem; border: 1px solid var(--line); border-radius: 999px; background: var(--panel); color: var(--ink); font-family: var(--mono); font-size: 12.5px; }
.pill:hover { border-color: var(--act); color: var(--ink); }

/* An ultrawide screen would otherwise have a third of it empty on
   each side. The page follows the window up to a width where a table
   still reads, and the activity belt takes the lot. */
main { padding: 1.2rem; max-width: min(2200px, 96vw); margin: 0 auto; }
@media (max-width: 1500px) { main { max-width: 1400px; } }
main.wallpage { max-width: none; padding: 0; }
.flash { background: color-mix(in srgb, var(--warn) 15%, transparent); border: 1px solid color-mix(in srgb, var(--warn) 40%, transparent); padding: .5rem .8rem; border-radius: var(--r-s); margin-bottom: 1rem; }
/* A blind monitor is not a warning about a site: it is the tool
   saying its own answers are worthless (SPEC §5.15). */
.flash.blind { background: color-mix(in srgb, var(--red) 15%, transparent); border-color: color-mix(in srgb, var(--red) 45%, transparent); }
.head { margin-bottom: .6rem; }
.head .actions { display: flex; gap: .4rem; margin-top: .4rem; }
.counts { display: flex; gap: .4rem; flex-wrap: wrap; margin: .3rem 0; }
.filter { margin-top: .4rem; width: 300px; }
.cols { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; }
@media (max-width: 900px) { .cols { grid-template-columns: 1fr; } .top { grid-template-columns: 1fr; } }

/* tags and dots */
.tag { display: inline-block; padding: .08rem .5rem; border-radius: 999px; font-size: 11.5px; font-family: var(--mono); background: var(--panel-3); color: var(--ink-2); border: 1px solid var(--line); vertical-align: middle; }
.tag.ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 40%, transparent); background: color-mix(in srgb, var(--ok) 12%, transparent); }
.tag.down { color: var(--red); border-color: color-mix(in srgb, var(--red) 40%, transparent); background: color-mix(in srgb, var(--red) 14%, transparent); }
.tag.warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, transparent); background: color-mix(in srgb, var(--warn) 12%, transparent); }
.tag.maint { color: var(--maint); border-color: color-mix(in srgb, var(--maint) 40%, transparent); background: color-mix(in srgb, var(--maint) 12%, transparent); }
.tag.mute, .tag.unknown { color: var(--mute); }
.tag.info { color: var(--act); border-color: color-mix(in srgb, var(--act) 40%, transparent); background: color-mix(in srgb, var(--act) 10%, transparent); }
.tag.on { border-color: var(--act); color: var(--ink); }
.tag.critical { color: var(--red); }
.dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; background: var(--unknown); flex: none; }
.dot.big { width: 14px; height: 14px; }
.dot.ok { background: var(--ok); } .dot.down { background: var(--red); box-shadow: 0 0 8px var(--red); } .dot.warn { background: var(--warn); } .dot.maint { background: var(--maint); } .dot.mute { background: var(--mute); opacity: .5; }
.c-down { color: var(--red); } .c-warn { color: var(--warn); } .c-ok { color: var(--ok); }

/* lists */
.hostblock { background: var(--panel); border: 1px solid var(--line); border-radius: var(--r); padding: .5rem 1rem .6rem; margin-bottom: .6rem; contain: layout style; }
.hostblock h2 { margin-top: .2rem; }
.hostblock summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; font-size: 14px; }
.hostblock summary::-webkit-details-marker { display: none; }
.hostblock summary::before { content: "▸"; color: var(--mute); width: .8rem; display: inline-block; transition: transform var(--t); }
.hostblock[open] summary::before { transform: rotate(90deg); }
/* Hovering the card is about to fold/unfold it: the arrow
   answers. */
.hostblock:not(.leaf) summary:hover::before { color: var(--act); transform: scale(1.25); }
.hostblock:not(.leaf)[open] summary:hover::before { transform: rotate(90deg) scale(1.25); }
.hostblock .hostname { font-weight: 650; color: var(--ink); font-family: var(--mono); }
/* The name is a door: say so. A stranger could not tell the hostname
   opens the machine's page. */
.hostblock summary a.hostname { text-decoration: underline dotted 1px; text-decoration-color: var(--mute); text-underline-offset: 3px; }
.hostblock summary a.hostname:hover { color: var(--act); text-decoration-color: var(--act); text-decoration-style: solid; }
/* A block with nothing to unfold carries no arrow and no fold cursor;
   its links keep working. */
.hostblock.leaf summary::before { content: ""; width: .8rem; }
.hostblock.leaf summary { cursor: default; pointer-events: none; }
.hostblock.leaf summary a, .hostblock.leaf summary button, .hostblock.leaf summary .svc { pointer-events: auto; }
.owner { margin: .5rem 0 .2rem 1.2rem; }
.ownerhead { font-size: 11.5px; text-transform: uppercase; letter-spacing: .08em; color: var(--mute); margin-bottom: .15rem; }
.ownerhead a { color: var(--ink-2); }
/* the hosts-and-sites table: one line per site, aligned columns */
table.sites { width: 100%; border-collapse: collapse; font-size: 13px; }
table.sites th { text-align: left; font-size: 10.5px; text-transform: uppercase; letter-spacing: .08em; color: var(--mute); padding: .25rem .5rem; border-bottom: 1px solid var(--line); font-weight: 600; cursor: pointer; user-select: none; white-space: nowrap; }
table.sites th.num, table.sites td.num { text-align: right; }
table.sites th[data-sort].on::after { content: " ▾"; color: var(--act); }
table.sites th[data-sort].on.asc::after { content: " ▴"; }
table.sites td { padding: .18rem .5rem; border-bottom: 1px solid color-mix(in srgb, var(--line) 60%, transparent); white-space: nowrap; vertical-align: middle; }
table.sites tr:last-child td { border-bottom: 0; }
table.sites tr.owner td { padding-top: .5rem; font-size: 10.5px; text-transform: uppercase; letter-spacing: .08em; color: var(--mute); border-bottom: 0; }
table.sites tr.child td.name { padding-left: 1.6rem; }
table.sites td.name a { color: var(--ink); font-family: var(--mono); }
table.sites td.name .dot { margin-right: .4rem; }
table.sites tr:hover td { background: var(--panel-2); }
table.sites tr[hidden] { display: none; }
table.sites td.reason { max-width: 320px; overflow: hidden; text-overflow: ellipsis; color: var(--mute); }
table.sites .elsewhere { color: var(--warn); }
table.sites .fwd { color: var(--ink-2); font-family: var(--mono); font-size: 12px; }
.treebar { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; margin: .3rem 0 .6rem; }
.treebar input[type=search] { width: 300px; }
.treebar .count { color: var(--mute); font-size: 12px; margin-left: auto; }
.cards.compact .card { padding: .4rem .7rem; }
.cards.compact .card .num { font-size: 19px; }
.card.off { opacity: .5; }
.alerts .tl { grid-template-columns: 120px auto 1fr auto; }
.sitegrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: .15rem .8rem; }
.siterow { display: grid; grid-template-columns: 12px 1fr auto auto; gap: .1rem .5rem; align-items: center; padding: .25rem .4rem; border-radius: var(--r-s); color: var(--ink); }
.siterow:hover { background: var(--panel-2); color: var(--ink); }
.siterow .name { font-family: var(--mono); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.siterow .name.sub { color: var(--ink-2); padding-left: .8rem; }
.siterow .st { font-size: 11.5px; color: var(--mute); font-family: var(--mono); }
.siterow .reason { grid-column: 2 / 4; font-size: 11.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.siterow .since { grid-column: 4; font-size: 11.5px; font-family: var(--mono); }
.siterow .reason:empty, .siterow .since:empty { display: none; }
.siterow[hidden] { display: none; }
table.list { width: 100%; border-collapse: collapse; background: var(--panel); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
table.list th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .08em; color: var(--mute); padding: .5rem .7rem; border-bottom: 1px solid var(--line); font-weight: 600; }
table.list td { padding: .42rem .7rem; border-bottom: 1px solid var(--line); vertical-align: top; }
table.list tr:last-child td { border-bottom: 0; }
table.list tr.open td { background: color-mix(in srgb, var(--red) 6%, transparent); }
.res .fam { font-family: var(--mono); font-size: 11px; color: var(--mute); display: inline-block; min-width: 2.2rem; }
.empty { text-align: center; padding: 3rem 1rem; color: var(--mute); }
.empty code { display: inline-block; margin: .2rem .3rem; background: var(--panel-2); padding: .1rem .4rem; border-radius: 4px; }
.tags .tag { margin-left: .2rem; }
details.evidence { background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-s); margin-bottom: .4rem; }
details.evidence summary { padding: .4rem .7rem; cursor: pointer; color: var(--ink-2); }
details.evidence pre { margin: 0; padding: .6rem .8rem; border-top: 1px solid var(--line); white-space: pre-wrap; word-break: break-all; max-height: 400px; overflow: auto; font-size: 12px; }
/* the "acknowledged by" pill on an incident: a box, never a row — a
   site row carries the status class ack too */
.ackbox { background: color-mix(in srgb, var(--ok) 10%, transparent); border: 1px solid color-mix(in srgb, var(--ok) 30%, transparent); padding: .4rem .7rem; border-radius: var(--r-s); display: inline-block; }

/* chart */
/* One window, one header, every chart under it on the same axis. */
.twinhead { display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; margin-top: 1rem; }
.twinhead .chips { display: inline-flex; gap: .3rem; }
.twindow.picked .twinhead { position: sticky; top: 0; z-index: 3; background: var(--ground); padding: .3rem 0; }
.legend .k { cursor: pointer; user-select: none; }
/* The name wears the colour of the thing it names — muted enough to
   stay readable, because a legend is read as text before it is read as
   a colour. */
.mchart .legend .k.m-used { color: var(--mem-used); } .mchart .legend .k.m-buf { color: var(--mem-buf); }
.mchart .legend .k.m-cache { color: var(--mem-cache); } .mchart .legend .k.m-swap { color: var(--mem-swap); }
.mchart .legend .k.m-avail { color: var(--mem-avail); }
.legend .k.total { color: var(--chart); } .legend .k.ttfb { color: var(--act-2); } .legend .k.rtt { color: var(--warn); }
.legend .k.s1 { color: var(--act); } .legend .k.s2 { color: var(--act-2); } .legend .k.s3 { color: var(--warn); }
.legend .k.s4 { color: var(--red); } .legend .k.s5 { color: var(--chart-2); } .legend .k.s6 { color: var(--ok); }
.legend .k.s0 { color: var(--chart); }
.legend .k.off { opacity: .35; text-decoration: line-through; }
.chart { background: var(--panel); border: 1px solid var(--line); border-radius: var(--r); padding: .6rem 1rem .6rem; margin-top: 1rem; }
.chart h2 { margin-top: 0; }
.chart .chips { display: inline-flex; gap: .3rem; margin-left: .3rem; }
.chart .avail { margin-left: auto; text-transform: none; letter-spacing: 0; font-weight: 400; font-family: var(--mono); }
.graphwrap { position: relative; }
.graph { width: 100%; height: 240px; display: block; }
.graph .hover line { stroke: var(--ink); stroke-width: 1; stroke-dasharray: 2 3; vector-effect: non-scaling-stroke; }
.graph .band { fill: color-mix(in srgb, var(--chart) 22%, transparent); stroke: none; }
.tip { position: absolute; pointer-events: none; background: var(--overlay); border: 1px solid var(--line-2); border-radius: var(--r-s); padding: .35rem .55rem; font-size: 12px; font-family: var(--mono); box-shadow: var(--shadow); white-space: nowrap; z-index: 3; color: var(--ink); }
.legend .band::before { background: color-mix(in srgb, var(--act) 35%, transparent); height: 8px; }
.graph .grid line { stroke: var(--line); stroke-width: 1; mix-blend-mode: overlay; opacity: .85; }
.graph .grid line.zero { stroke: var(--line-2); }
.graph .grid text { fill: var(--mute); font-size: 11px; font-family: var(--mono); paint-order: stroke; stroke: var(--panel); stroke-width: 3px; }
.graph path { fill: none; stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.graph circle.total { fill: var(--act); } .graph circle.ttfb { fill: var(--act-2); } .graph circle.rtt { fill: var(--warn); } .graph circle.warm { fill: var(--ok); }
.graph .total { stroke: var(--chart); stroke-width: 2; } .graph .ttfb { stroke: var(--act-2); } .graph .rtt { stroke: var(--warn); stroke-dasharray: 4 3; } .graph .warm { stroke: var(--ok); stroke-width: 2; }
.graph .down { fill: color-mix(in srgb, var(--red) 25%, transparent); }
/* What was last measured, held across a window it did not fall in. */
.graph .lastknown { stroke-dasharray: 3 4; opacity: .7; }
/* A chart whose series are DISCOVERED, not declared — one line per
   kind of check that ran, one per database that exists — needs a
   palette that is not tied to a meaning: s0…s9, cycled. Every one has
   its line, its marker and its legend chip, so a series added tomorrow
   is drawn without touching this file. */
.graph .s0 { stroke: var(--chart); } .graph .s1 { stroke: var(--act); } .graph .s2 { stroke: var(--act-2); }
.graph .s3 { stroke: var(--warn); } .graph .s4 { stroke: var(--red); } .graph .s5 { stroke: var(--chart-2); }
.graph .s6 { stroke: var(--ok); stroke-dasharray: 5 3; } .graph .s7 { stroke: var(--act); stroke-dasharray: 5 3; }
.graph .s8 { stroke: var(--warn); stroke-dasharray: 5 3; } .graph .s9 { stroke: var(--unknown); }
.graph circle.s0 { fill: var(--chart); } .graph circle.s1 { fill: var(--act); } .graph circle.s2 { fill: var(--act-2); }
.graph circle.s3 { fill: var(--warn); } .graph circle.s4 { fill: var(--red); } .graph circle.s5 { fill: var(--chart-2); }
.graph circle.s6 { fill: var(--ok); } .graph circle.s7 { fill: var(--act); }
.graph circle.s8 { fill: var(--warn); } .graph circle.s9 { fill: var(--unknown); }
/* The peak behind the mean: the same colour, barely there. */
.graph path.band { stroke: none; fill: color-mix(in srgb, currentColor 18%, transparent); }
.graph path.band.total { fill: color-mix(in srgb, var(--chart) 18%, transparent); }
.graph path.band.ttfb { fill: color-mix(in srgb, var(--act-2) 18%, transparent); }
.legend { font-size: 11.5px; display: flex; gap: 1rem; margin-top: .3rem; }
.legend .k::before { content: ""; display: inline-block; width: 14px; height: 3px; margin-right: .3rem; vertical-align: middle; background: var(--chart); }
.legend .ttfb::before { background: var(--act-2); } .legend .rtt::before { background: var(--warn); } .legend .warm::before { background: var(--ok); }
.legend .s1::before { background: var(--act); } .legend .s2::before { background: var(--act-2); }
.legend .s3::before { background: var(--warn); } .legend .s4::before { background: var(--red); }
.legend .s5::before { background: var(--chart-2); } .legend .s6::before { background: var(--ok); }
.legend .s7::before { background: var(--act); } .legend .s8::before { background: var(--warn); }
.legend .s9::before { background: var(--unknown); }

/* wall */
.wall { background: var(--ground); padding: 1.2rem 1.5rem; }
/* the bars and the latest changes share the wall's margins; the
   changes sit under it */
.wallside { padding: .6rem 1.5rem 0; }
.wallside.below { padding-top: 0; }
.wallside .treebar { margin: 0 0 .4rem; }
.wallhead { display: flex; align-items: baseline; gap: 1.2rem; margin-bottom: 1rem; }
.wallhead .big { font-size: 34px; font-weight: 700; }
.wallhead .live { margin-left: auto; color: var(--mute); font-size: 12px; }
.wallhead .walltoggle { text-decoration: none; }
.wallhead .walltoggle.on { color: var(--ink); }
.wallhead .live.on { color: var(--ok); }
/* auto-FIT, not auto-fill: with one tile it takes the whole width
   and its rows split into columns inside it, instead of a single
   column down the middle of a wide screen. */
.walltiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(380px, 1fr)); gap: .8rem; align-items: start; }
.tile { background: var(--panel); border: 1px solid var(--line); border-radius: var(--r); padding: .6rem 1rem .8rem; }
.tile h2 { margin-top: .1rem; font-size: 13px; letter-spacing: .04em; }
.tile .siterow { grid-template-columns: 12px 1fr auto; font-size: 15px; }
.tile .siterow .name { font-size: 15px; }
.allwell { text-align: center; font-size: 140px; color: var(--ok); margin-top: 12vh; opacity: .85; }
.login { max-width: 360px; margin: 12vh auto; background: var(--panel); border: 1px solid var(--line); border-radius: var(--r); padding: 1.5rem; }
.login label { margin-bottom: .6rem; }
.login button { width: 100%; margin-top: .4rem; }

/* cards, timeline, modal */
/* Cards line up from the left and keep their size: one card alone
   must not stretch across the page. */
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, max-content)); gap: .6rem; margin: .6rem 0 .4rem; justify-content: start; }
.card { display: flex; flex-direction: column; gap: .05rem; background: var(--panel); border: 1px solid var(--line); border-radius: var(--r); padding: .4rem .7rem; color: var(--ink); border-left-width: 4px; }
.card:hover { border-color: var(--line-2); color: var(--ink); }
.card .num { font-size: 18px; font-weight: 700; font-family: var(--mono); line-height: 1.15; }
.card .lbl { font-size: 12.5px; color: var(--ink-2); }
.card.ok { border-left-color: var(--ok); } .card.down { border-left-color: var(--red); } .card.warn, .card.maint { border-left-color: var(--warn); } .card.unknown { border-left-color: var(--unknown); }
.card.down .num { color: var(--red); } .card.warn .num { color: var(--warn); }
.cols.three { grid-template-columns: 1fr 1fr 1fr; }
@media (max-width: 1100px) { .cols.three { grid-template-columns: 1fr; } }
.timeline { border-left: 2px solid var(--line-2); margin: .3rem 0 .3rem .4rem; padding-left: 1rem; }
.tl { display: grid; grid-template-columns: 150px auto 1fr; gap: .6rem; align-items: baseline; padding: .25rem 0; position: relative; }
.tl::before { content: ""; position: absolute; left: calc(-1rem - 6px); top: .6rem; width: 8px; height: 8px; border-radius: 50%; background: var(--mute); }
.tl.incident::before { background: var(--red); } .tl.placement::before { background: var(--act); }
.tl .when { font-family: var(--mono); font-size: 12px; }
details.more { margin-top: 1.2rem; }
details.more summary { list-style: none; display: inline-block; }
details.more h3 { margin-top: 1rem; text-transform: uppercase; font-size: 11.5px; letter-spacing: .08em; color: var(--ink-2); }
.modal { position: fixed; inset: 0; background: rgba(0,0,0,.55); z-index: 40; display: flex; align-items: flex-start; justify-content: center; padding: 4vh 1rem; overflow: auto; }
.modal[hidden] { display: none; }
.modalbox { background: var(--ground); border: 1px solid var(--line-2); border-radius: var(--r); box-shadow: var(--shadow); width: min(1100px, 100%); position: relative; max-height: 92vh; overflow: auto; }
.modalbox .close { position: absolute; top: .5rem; right: .5rem; z-index: 2; }
.modalbody { padding: 1rem 1.2rem; }
.graph text { font-family: var(--mono); font-size: 11px; fill: var(--mute); }
.foot { max-width: min(2200px, 96vw); margin: 2rem auto 1rem; padding: 0 1.2rem; font-size: 12px; }
/* A status page is a 900px column; a footer spanning the whole window
   under it reads as belonging to something else. */
.foot.narrow { max-width: 900px; padding: 0; text-align: center; }
.foot a { color: var(--mute); }

/* A badge on a site row is also a filter: it looks clickable. */
table.sites .tag.badge { cursor: pointer; }
table.sites .tag.badge:hover { border-color: var(--act); color: var(--act); }
.actions form.inline { display: inline-flex; gap: .4rem; align-items: center; }

/* Per-family pills: IPv4 and IPv6, each for itself. */
table.sites .fam { display: inline-block; min-width: 1.15rem; text-align: center; border-radius: 4px; font-family: var(--mono); font-size: 11px; padding: 0 .18rem; border: 1px solid var(--line); color: var(--mute); margin-right: .18rem; }
table.sites .fam.ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 45%, transparent); }
table.sites .fam.down { color: var(--red); border-color: color-mix(in srgb, var(--red) 50%, transparent); background: color-mix(in srgb, var(--red) 12%, transparent); }
table.sites .fam.warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 50%, transparent); }

/* Columns the user turned off (saved on their account). */
#tree.no-resp .c-resp, #tree.no-fam .c-fam, #tree.no-status .c-status, #tree.no-since .c-since, #tree.no-addr .c-addr, #tree.no-detail .c-detail, #tree.no-mdns .c-mdns { display: none; }
#tree.no-badges .tag.badge { display: none; }
.cols-picker { position: relative; display: inline-block; }
.cols-picker .menu { position: absolute; right: 0; top: 100%; margin-top: .3rem; background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: .55rem .8rem; display: flex; flex-direction: column; gap: .3rem; z-index: 30; white-space: nowrap; box-shadow: 0 8px 24px rgba(0,0,0,.35); }

/* The pulse: the plan above, the results as they land. */
.pulse .feed { border-top: 1px solid var(--line); }
.pulse .feed .row { display: flex; gap: .6rem; padding: .28rem 0; border-bottom: 1px solid var(--line); align-items: baseline; font-size: 13px; }
.pulse .feed .row .what { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pulse #upcoming td.num { width: 3.2rem; }

/* The pulse tape: planned checks drift in from the right, cross the
   now-line, light up as their result lands. */
.pad { padding: 1.1rem 1.4rem; }
/* contain: the belt is its own world — a tick that reflows the table
   below must not reach in, and a chip mounting inside must not reach
   out (a stutter at every refresh on Firefox). */
.tape { position: relative; height: 104px; overflow: hidden; background: var(--panel); border: 1px solid var(--line); border-radius: 8px; margin-bottom: 1rem; contain: layout paint style; }
#tapetrack { position: absolute; inset: 0; }
/* The belt is one canvas: a clear and a blit per chip each frame,
   no DOM, no layers, no layout. */
.tapecanvas { position: absolute; inset: 0; display: block; z-index: 1; }
/* The belt's two strips, moved by the compositor (translateX), never
   repainted per frame. */
.tapestrip { position: absolute; top: 0; left: 0; will-change: transform; display: block; image-rendering: auto; pointer-events: none; }
/* The bar is the middle, everywhere: it is where a tick stops and
   waits for its answer, and the code puts it at half the width. */
.tape .now-line { position: absolute; left: 50%; top: 0; bottom: 0; width: 2px; background: var(--act); opacity: .65; z-index: 2; }
.tape .tape-legend { position: absolute; right: .6rem; bottom: .25rem; font-size: 11px; z-index: 2; }
.chip { cursor: pointer; position: absolute; padding: .06rem .4rem; border-radius: 4px; font-family: var(--mono); font-size: 11px; background: var(--panel-3); border: 1px solid var(--line); color: var(--ink-2); white-space: nowrap; max-width: 220px; overflow: hidden; text-overflow: ellipsis; }
.chip.ghost { opacity: .4; border-style: dashed; }
.chip.ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 45%, transparent); }
.chip.down { color: var(--red); border-color: color-mix(in srgb, var(--red) 55%, transparent); background: color-mix(in srgb, var(--red) 14%, transparent); }
.chip.warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 50%, transparent); }

/* A parent's caret unfolds its subdomains. */
table.sites .caret { background: none; border: 1px solid var(--line); color: var(--mute); border-radius: 4px; font-size: 10px; margin-left: .45rem; cursor: pointer; padding: 0 .3rem; line-height: 1.5; }
table.sites .caret.open { color: var(--act); border-color: var(--act); }

/* The settings form on the policy page. */
form.settings input.short { width: 6.5rem; }
form.settings .tune { display: flex; flex-wrap: wrap; gap: .9rem 1.4rem; align-items: end; margin: .9rem 0; }
form.settings .tune label { display: flex; flex-direction: column; gap: .25rem; font-size: 13px; color: var(--ink-2); }

/* The activity tape: full height on /activity, a strip on the
   overview; the now-line in the middle; a label per lane. */
.tape.full { height: calc(100vh - 240px); min-height: 380px; }
.tape { background-image: repeating-linear-gradient(90deg, color-mix(in srgb, var(--line) 55%, transparent) 0 1px, transparent 1px 100%); background-position: 0 0; }
.tape.home { height: 192px; margin-bottom: 1.2rem; }
.tape .now-line { left: 50%; }
.tape .lanelbl { position: absolute; left: .6rem; font-size: 11px; z-index: 2; font-family: var(--mono); }
.chip { max-width: none; }

/* Status filter buttons: pressed = shown, the colours are the statuses'. */
.fbtns { display: inline-flex; gap: .35rem; }
/* A filter button wears its own colour from the start, faded, and
   comes up to full strength when it is pressed: the reader sees what
   each one means before clicking it. */
.fbtns .fb { background: none; border: 1px solid var(--line); border-radius: 999px; padding: .15rem .75rem; font-size: 12px; color: var(--mute); cursor: pointer; opacity: .62; transition: opacity .12s ease, background-color .12s ease; }
.fbtns .fb:hover { opacity: .85; }
.fbtns .fb.on { opacity: 1; font-weight: 600; }
.fbtns .fb.down { color: var(--red); border-color: color-mix(in srgb, var(--red) 45%, transparent); }
.fbtns .fb.warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 45%, transparent); }
.fbtns .fb.ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 45%, transparent); }
.fbtns .fb.maint { color: var(--act); border-color: color-mix(in srgb, var(--act) 45%, transparent); }
/* A number field holds three digits, not a sentence — and what can be
   filled can be emptied. */
.clearable { position: relative; display: inline-flex; align-items: center; }
.clearable input.ms { width: 5.2rem; padding-right: 1.4rem; }
.clearbtn { position: absolute; right: .15rem; background: none; border: 0; color: var(--mute); cursor: pointer; font-size: 11px; line-height: 1; padding: .15rem .25rem; }
.clearbtn:hover { color: var(--ink); }
.nowrap { white-space: nowrap; }
/* Each figure with its own name above it, and room between them: four
   numbers in a row with no labels is a number soup, whoever is
   reading. */
.hostblock summary .vitals { display: inline-flex; gap: 1rem; margin: 0 .3rem; vertical-align: middle; }
.vitals .v { display: inline-flex; flex-direction: column; line-height: 1.15; }
.vitals .v i { font-style: normal; font-size: 9.5px; text-transform: uppercase; letter-spacing: .07em; color: var(--mute); }
.vitals .v b { font-family: var(--mono); font-size: 12.5px; font-weight: 600; color: var(--ink); }
.vitals .v u { text-decoration: none; font-family: var(--mono); font-size: 10.5px; color: var(--mute); margin-top: -1px; }
.hostblock summary .services { display: inline-flex; gap: .25rem; flex-wrap: wrap; margin-left: .4rem; }
#foldall { margin-left: .3rem; }
.fbtns .fb.mute { color: var(--ink-2); }
/* Every status the mapping knows has its chip in its own colour —
   nothing falls back to grey for want of a rule. */
.fbtns .fb.ext { color: var(--ext); border-color: color-mix(in srgb, var(--ext) 45%, transparent); }
.fbtns .fb.unknown { color: var(--unknown); border-color: color-mix(in srgb, var(--unknown) 45%, transparent); }
.fbtns .fb.on.down, .fbtns .fb.down:hover { color: var(--red); border-color: color-mix(in srgb, var(--red) 55%, transparent); }
.fbtns .fb.on.down { background: color-mix(in srgb, var(--red) 14%, transparent); }
.fbtns .fb.on.warn, .fbtns .fb.warn:hover { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 55%, transparent); }
.fbtns .fb.on.warn { background: color-mix(in srgb, var(--warn) 12%, transparent); }
.fbtns .fb.on.ok, .fbtns .fb.ok:hover { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 50%, transparent); }
.fbtns .fb.on.ok { background: color-mix(in srgb, var(--ok) 12%, transparent); }
.fbtns .fb.on.maint, .fbtns .fb.maint:hover { color: var(--act); border-color: color-mix(in srgb, var(--act) 50%, transparent); }
.fbtns .fb.on.maint { background: color-mix(in srgb, var(--act) 12%, transparent); }
.fbtns .fb.on.mute { color: var(--ink-2); border-color: var(--ink-2); background: color-mix(in srgb, var(--ink-2) 10%, transparent); }

/* A host's services, one pill each, right on the overview. */
.hostblock .services { display: flex; flex-wrap: wrap; gap: .3rem; padding: .5rem .9rem .2rem; }
.hostblock .services .svc { border: 1px solid var(--line); border-radius: 5px; padding: .12rem .45rem; font-size: 12px; color: var(--ink-2); text-decoration: none; white-space: nowrap; }
.hostblock .services .svc.ok { border-color: color-mix(in srgb, var(--ok) 35%, transparent); }
.hostblock .services .svc.ok:hover { border-color: var(--ok); }
.hostblock .services .svc.down { color: var(--red); border-color: color-mix(in srgb, var(--red) 55%, transparent); background: color-mix(in srgb, var(--red) 12%, transparent); }
.hostblock .services .svc.warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 55%, transparent); }

/* A tick still unresolved at the LEFT edge pins there: the jam is the delay. */
.chip.pending { border-color: var(--act); border-style: solid; opacity: .9; z-index: 3; }
/* The bar reveals: a soft landing pulse. */
.chip.landed { animation: land .45s ease-out; }
@keyframes land { from { box-shadow: 0 0 0 6px color-mix(in srgb, var(--act) 25%, transparent); } to { box-shadow: none; } }
/* Soft separators between lanes; the labels sit in their own box. */
.tape .lanesep { position: absolute; left: 0; right: 0; height: 1px; background: linear-gradient(90deg, transparent, var(--line) 15%, var(--line) 85%, transparent); opacity: .5; }
.tape .lanelbl { background: var(--panel); border: 1px solid var(--line); border-radius: 5px; padding: .05rem .45rem; z-index: 4; }

/* The tape's own settings: speed and effects, the user's. */
.tape .tape-gear { position: absolute; right: .5rem; top: .35rem; z-index: 5; }
.tape .tape-gear summary { list-style: none; cursor: pointer; color: var(--mute); border: 1px solid var(--line); border-radius: 5px; padding: 0 .4rem; background: var(--panel); }
.tape .tape-gear summary:hover { color: var(--ink); }
.tape .tape-gear .menu { position: absolute; right: 0; top: 100%; margin-top: .3rem; background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: .55rem .8rem; display: flex; flex-direction: column; gap: .4rem; white-space: nowrap; box-shadow: 0 8px 24px rgba(0,0,0,.35); font-size: 12.5px; }
.tape.no-fx .chip.landed { animation: none; }


.tape-gear .paceset, .tape-gear .modeset { display: inline-flex; gap: .3rem; }
.tape-gear .modeset button { background: none; border: 1px solid var(--line); border-radius: 999px; padding: .1rem .6rem; font-size: 12px; color: var(--mute); cursor: pointer; }
.tape-gear .modeset button.on { color: var(--act); border-color: var(--act); }
.tape-gear .paceset button { background: none; border: 1px solid var(--line); border-radius: 999px; padding: .1rem .6rem; font-size: 12px; color: var(--mute); cursor: pointer; }
.tape-gear .paceset button.on { color: var(--act); border-color: var(--act); }

/* A tick with no journey to make appears in place, softly. */
.chip.fade { animation: chipfade .3s ease-out; }
@keyframes chipfade { from { opacity: 0; } to { opacity: 1; } }

/* The host page: service tiles, the machine card, the metric charts. */
.cards.svc { margin: .2rem 0 .4rem; }
a.card { color: var(--ink); cursor: pointer; }
a.card:hover { border-color: var(--act); }
.card.unknown .num { color: var(--mute); }
.machine .gauges { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: .55rem 1.1rem; margin-top: .3rem; }
.gauge .lbl { font-size: 12px; color: var(--mute); display: block; margin-bottom: .2rem; }
.gauge .lbl b { color: var(--ink); font-weight: 600; }
.gauge .bar { display: block; position: relative; height: 7px; background: var(--panel-3); border-radius: 4px; overflow: hidden; }
.gauge .bar i { position: absolute; left: 0; top: 0; bottom: 0; background: var(--act); border-radius: 4px; }
.gauge .bar.warn i { background: var(--warn); }
.gauge .bar.down i { background: var(--red); }
/* Stacked, never side by side: one shared time axis to
   correlate. */
.machine .mgrid { display: grid; grid-template-columns: 1fr; gap: .3rem; }
.mchart h3 { margin: .3rem 0 .1rem; font-size: 11.5px; text-transform: uppercase; letter-spacing: .07em; color: var(--mute); }
.mchart .mgraph { height: 130px; }
.mchart .k { font-size: 11px; text-transform: none; letter-spacing: 0; margin-left: .5rem; }
.mchart .k::before { content: ""; display: inline-block; width: 12px; height: 3px; margin-right: .25rem; vertical-align: middle; }
.graph .rx { stroke: var(--chart); stroke-width: 1.6; }
.graph .tx { stroke: var(--warn); stroke-width: 1.6; }

/* Hierarchy on the tiles: the label reads first, the value is the
   news; the ping is the base and stands out. */
.tile { gap: .15rem; }
.tile .lbl { display: flex; align-items: center; gap: .35rem; }
.tile.feat { grid-column: span 2; }
.tile.feat .num { font-size: 34px; }
.mstats { margin-left: .6rem; font-family: var(--mono); font-size: 11px; text-transform: none; letter-spacing: 0; color: var(--mute); }
.mstats b { color: var(--ink); font-weight: 650; }
.graph .sel rect { fill: color-mix(in srgb, var(--act) 18%, transparent); stroke: var(--act); stroke-width: 1; }
.mgraph { cursor: crosshair; }
.users .utable td { vertical-align: middle; }
.users .utable .lbl { display: block; font-size: 11.5px; margin-bottom: .15rem; }
.users .utable .bar { display: block; max-width: 280px; position: relative; height: 6px; background: var(--panel-3); border-radius: 4px; overflow: hidden; }
.users .utable .bar i { position: absolute; left: 0; top: 0; bottom: 0; background: var(--act); border-radius: 4px; }

/* Legend chips mask their series; each user has a colour. */
.k.off, .ku.off { opacity: .4; text-decoration: line-through; }
.legend .k[data-sk], .mchart .k { user-select: none; }
.mchart .ku { font-family: var(--mono); margin-right: .55rem; }
/* The per-user legend: a machine has hundreds of accounts, so the list
   folds, searches, and says which site each login serves. */
.uleg .uhead { display: flex; align-items: center; gap: .5rem; margin-bottom: .3rem; }
.uleg .usearch {
  font: inherit; font-family: var(--mono); padding: .1rem .4rem; width: 14rem; max-width: 45%;
  border: 1px solid var(--line); border-radius: var(--r); background: var(--ground); color: var(--ink);
}
.uleg .usearch:focus { outline: none; border-color: var(--act); }
.uleg .ucount { white-space: nowrap; }
.uleg .ufold { cursor: pointer; white-space: nowrap; }
.uleg .ulist { max-height: 9rem; overflow-y: auto; line-height: 1.7; }
/* Two readings on a host's line: what the machine serves, and what
   the sites are doing. Separated so the eye does not mix them. */
#tree summary .group + .group::before { content: "|"; opacity: .35; margin: 0 .45rem 0 .25rem; }
/* The ticks that say what a channel carries. */
.carries { border: 1px solid var(--line); border-radius: var(--r); padding: .5rem .7rem; margin: .2rem 0; }
.carries .hint { margin: 0 0 .2rem; }
.carries legend { padding: 0 .3rem; color: var(--mute); font-size: 12.5px; }
.carries .ticks { display: flex; flex-wrap: wrap; align-items: center; gap: .2rem .1rem; margin: .35rem 0; color: var(--mute); font-size: 12.5px; }
.carries .tick { display: inline-flex; align-items: center; gap: .3rem; margin-left: .8rem; white-space: nowrap; color: var(--ink); }
.carries .tick input { margin: 0; }
/* What is ticked and what is merely possible must not read the same:
   a group ruled out by an "all" or by a mode is dimmed, not hidden —
   the reader still sees what they could choose. */
.tick.off, .ticks.off { opacity: .45; }
.alertform { align-items: flex-end; gap: .7rem; flex-wrap: wrap; }
.alertform fieldset { border: 1px solid var(--line); border-radius: var(--r); padding: .35rem .7rem; margin: 0; }
.alertform fieldset legend { padding: 0 .3rem; color: var(--mute); font-size: 12px; }
.alertform .importance .ticks { gap: .1rem .8rem; align-items: flex-end; }
.alertform .importance .urow { margin: 0; font-size: 12px; }
.alertform .importance select { font-size: 12px; }
.alertform .ticks { display: inline-flex; flex-wrap: wrap; align-items: center; gap: .1rem; font-size: 12.5px; }
.alertform .chanpick { margin-left: .8rem; padding-left: .8rem; border-left: 1px solid var(--line); }
/* A form's buttons belong on one line: what it does and the way out
   of it. */
.formacts { display: flex; gap: .5rem; align-items: center; }
/* How loud each thing is on a channel: a row per kind of news, side
   by side so the whole scale is read at once. */
.urgency .rows { display: grid; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); gap: .45rem .9rem; margin-top: .35rem; }
.urgency .urow { margin: 0; color: var(--ink); font-size: 12.5px; }
.urgency .urow select { font-size: 12.5px; }
/* A channel's buttons stay on one line rather than wrapping under the
   name of the next one. */
.list td.acts { white-space: nowrap; }
.list td.acts button { margin-right: .25rem; }
.ownerfold { border: 0; background: none; color: var(--mute); cursor: pointer; font: inherit; padding: 0 .25rem 0 0; }
.ownerfold:hover { color: var(--ink); }
/* A list of open incidents is a list, not a page: it scrolls in place
   rather than pushing everything below out of reach. */
.alerts.scrollable { max-height: 15rem; overflow-y: auto; padding-right: .3rem; }
.secthead { margin-top: 1.1rem; }
/* A site that points elsewhere: watched in case it comes back,
   never alarming, and never confused with a failure. */
.tag.ext { color: var(--ext); border-color: color-mix(in srgb, var(--ext) 45%, transparent); background: color-mix(in srgb, var(--ext) 14%, transparent); }
.dot.ext { background: var(--ext); }
.card.ext { border-left-color: var(--ext); }
.card.ext .num { color: var(--ext); }
.svc.ext { border-color: var(--ext); }
.c-ext { color: var(--maint); }
/* What a site's records could be doing better: said, never raised. */
/* A site's faults, spelled out on its own page. The lists carry the
   same three sentences in a hover, which reaches a desktop and no
   phone; here they are read, not hunted for. The left rule carries the
   severity so the eye sorts them before reading. */
.siteproblems { margin: .4rem 0 .8rem; }
.problemchips { display: flex; flex-wrap: wrap; gap: .3rem .4rem; align-items: flex-start; }
.problemchips details.problem { display: inline-block; }
.problemchips details.problem summary { list-style: none; cursor: pointer; }
.problemchips details.problem summary::-webkit-details-marker { display: none; }
.problemchips details.problem[open] { flex-basis: 100%; }
.problemchips details.problem[open] summary { margin-bottom: .3rem; }
.problembody { background: var(--panel); border: 1px solid var(--line); border-left: 3px solid var(--unknown); border-radius: var(--r-s); padding: .5rem .8rem; max-width: 60rem; }
details.problem.down .problembody { border-left-color: var(--red); }
details.problem.warn .problembody { border-left-color: var(--warn); }
.problembody .means, .problembody .do, .problembody .whose { display: block; line-height: 1.45; }
.problembody .means { color: var(--ink-2); }
.problembody .do { color: var(--ink); margin-top: .25rem; }
.problembody .whose { font-size: 12px; margin-top: .2rem; }

.notices { margin: .6rem 0 0; }
.notices p { margin: .15rem 0; }
/* The site cards over a host's list: smaller than the headline cards,
   and the one in force is marked. */
.sitecards { margin-top: .2rem; }
.sitecards .card { cursor: pointer; }
.sitecards .card.picked { outline: 2px solid var(--act); outline-offset: -2px; }
.uleg .useg { display: inline-flex; border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
.uleg .useg button {
  font: inherit; font-size: .82rem; padding: .05rem .45rem; border: 0; border-right: 1px solid var(--line);
  background: var(--ground); color: var(--mute); cursor: pointer;
}
.uleg .useg button:last-child { border-right: 0; }
.uleg .useg button.on { background: var(--panel-2, var(--panel)); color: var(--ink); font-weight: 600; }

.graph .uall { stroke: var(--ink); stroke-width: 2; opacity: .85; }
.graph .uall.band { fill: var(--ink); opacity: .12; stroke: none; }
.uleg .ku .usite { opacity: .65; color: inherit; text-decoration: none; }
.uleg .ku .usite:hover { opacity: 1; text-decoration: underline; }
.uleg .ku.off .usite { opacity: .45; }
.mchart .ku::before { content: ""; display: inline-block; width: 12px; height: 3px; margin-right: .3rem; vertical-align: middle; }
.graph .u0 { stroke: var(--chart); }
.graph .u1 { stroke: var(--chart-2); }
.graph .u2 { stroke: var(--warn); }
.graph .u3 { stroke: #c678dd; }
.graph .u4 { stroke: #56b6c2; }
.graph .u5 { stroke: var(--red); }
.graph .u6 { stroke: #d19a66; }
.graph .u7 { stroke: var(--mute); }

/* Legends live under their graph. */
.mchart .legend, .mchart .uleg { margin: .15rem 0 .5rem; display: flex; flex-wrap: wrap; gap: .2rem .9rem; align-items: center; }
.mchart .uleg { font-size: 11.5px; }

/* A hidden field is hidden, whatever a layout rule says. */
[hidden] { display: none !important; }

/* The machine's dials: CPU and memory read as a needle, the rest as a
   number over the last five minutes. Disk space is not a headline: it
   lives under the disk chart. */
.machine .dial { width: 100%; max-width: 148px; height: 74px; display: block; margin: .05rem 0 0; }
.dial .track { fill: none; stroke: var(--panel-3); stroke-width: 9; stroke-linecap: round; }
.dial .fill { fill: none; stroke-width: 9; stroke-linecap: round; }
.dial .fill.ok { stroke: var(--chart); } .dial .fill.warn { stroke: var(--warn); } .dial .fill.down { stroke: var(--red); }
/* Two directions on one dial: what comes in outside, what goes out
   inside — a link saturates either way. */
.dial .fill.dir { stroke-width: 5; }
.dial .fill.dir.up { stroke: var(--chart); }
.dial .fill.dir.dn { stroke: var(--red); }
.dial .fill.dir.dl { stroke: var(--chart-2); }
.dial .tick { stroke: var(--line-2); stroke-width: 1.5; }
.dial .needle { stroke: var(--ink); stroke-width: 2.5; stroke-linecap: round; }
/* The needle glides to its new value; it does not jump. */
.dial .needle-g { transition: transform .12s ease-out; }
@media (prefers-reduced-motion: reduce) { .dial .needle-g { transition: none; } }
.dial .needle.warn { stroke: var(--warn); } .dial .needle.down { stroke: var(--red); }
.dial .needle.off { stroke: none; }
.machine .quietline { margin: .4rem 0 0; font-weight: 600; }
.dial .hub { fill: var(--ink); }
.dial .val { fill: var(--ink); font-family: var(--mono); font-size: 17px; font-weight: 700; }
.dial .val .pc { font-size: 12px; fill: var(--mute); }
.machine .sparkwrap { position: relative; width: 100%; margin-top: auto; }
.machine .spark { width: 100%; height: 30px; display: block; margin-top: .25rem; opacity: .95; cursor: crosshair; }
/* No link speed to measure against, so no gauge: the rate draws
   itself, what comes in above the line and what goes out below, and
   the block keeps the height of the ones beside it. */
.machine .sparkwrap.big { width: 100%; }
.machine .sparkwrap.big .spark { height: 116px; }
.mstat .num.rates { display: flex; gap: .9rem; align-items: baseline; justify-content: center; font-size: 15px; }
.mstat .num.rates .in { color: var(--chart); }
.mstat .num.rates .out { color: var(--red); }
.spark .sc { fill: var(--mute); font-family: var(--mono); font-size: 8.5px; opacity: .8; }
.machine .sparkwrap .tip { font-size: 11px; }
.spark path { fill: none; stroke-width: 1.4; vector-effect: non-scaling-stroke; }
.spark .total { stroke: var(--chart); } .spark .rx { stroke: var(--chart); } .spark .tx { stroke: var(--warn); }
.spark .area { stroke: none; fill: color-mix(in srgb, var(--chart) 16%, transparent); }
.mstat .num.two { font-size: 15.5px; }
.mstat .sub { text-overflow: ellipsis; }

/* What the machine IS rides on the title line, after the badges; the
   status badge carries how long it has held. */
.head h1 .what { font-size: 12px; font-weight: 400; font-family: var(--mono); letter-spacing: 0; margin-left: .35rem; }
.mchart h3 .addrs { font-size: 10.5px; text-transform: none; letter-spacing: 0; margin-left: .4rem; }
.mstat .sub.spec { white-space: normal; line-height: 1.35; font-size: 10.5px; }

/* The three loads read by weight: one minute green, five blue,
   fifteen red — a high fifteen is the one that matters. */
.graph .l1 { stroke: var(--chart); stroke-width: 1.6; }
.graph .l5 { stroke: var(--chart-2); stroke-width: 1.6; }
.graph .l15 { stroke: var(--red); stroke-width: 1.6; }

/* The thresholds a volume is judged on, drawn where they are. */
.graph .thr { stroke-dasharray: 3 4; stroke-width: 1; }
.graph .thr.warn { stroke: color-mix(in srgb, var(--warn) 70%, transparent); }
.graph .thr.down { stroke: color-mix(in srgb, var(--red) 70%, transparent); }
.mchart .mleg { font-size: 11.5px; }
/* Memory reads as bands: what processes hold, what the kernel keeps
   for them, what is free — and the line of what is really available.
   The swap in use hangs below the axis. */
.mchart.tall .mgraph { height: 190px; }
/* A stacked band is drawn in ITS OWN colour, not a faded one: a
   translucent fill takes the colour of whatever is behind it, so the
   swatch in the legend and the swatch in the tooltip never matched
   what the eye saw on the chart. One colour per thing, defined once,
   used by the band, the legend and the tooltip. The grid is drawn
   OVER the bands instead of under them, which is what the
   transparency was there to achieve. */
:root { --mem-used: #d98b3d; --mem-buf: #8b6cff; --mem-cache: #5c98ff; --mem-free: #5b6674; --mem-swap: #ff5252; --mem-avail: #59d38f; }
@media (prefers-color-scheme: light) { :root:not([data-theme="dark"]) { --mem-free: #b9c2cc; } }
:root[data-theme="light"] { --mem-free: #b9c2cc; }
/* A band is a TINT of its colour, a line is the colour itself. Opaque
   tint, not transparency: mixed with the panel rather than laid over
   whatever is behind, so the swatch in the legend is exactly what the
   eye sees, while a line still reads over any band without needing an
   outline around it. */
.graph path.fill { fill: color-mix(in srgb, var(--sk, var(--chart)) 42%, var(--panel)); }
.legend .k.band::before { background: color-mix(in srgb, var(--sk, var(--chart)) 42%, var(--panel)); }
.graph path.boundary { stroke-width: 2.2; fill: none; }
.graph .m-avail { stroke: var(--mem-avail); stroke-width: 2.2; stroke-dasharray: 5 3; fill: none; }
.nowv .n.m-used { color: var(--orange); } .nowv .n.m-avail { color: var(--chart); }

/* The live control: one pace for the page, and a dot that pulses only
   when data came back. */
.livegroup { display: inline-flex; align-items: center; gap: .4rem; margin-left: auto; }
.livegroup select { padding: .3rem .4rem; font-size: 12px; }
.livebtn { display: inline-flex; align-items: center; gap: .5rem; border-radius: 999px; padding: .32rem .9rem .32rem .6rem; font-size: 12.5px; border: 1px solid var(--line); background: var(--panel-2); color: var(--ink); cursor: pointer; }
.livebtn .dot { width: 9px; height: 9px; border-radius: 50%; background: var(--mute); display: inline-block; }
.livebtn.on .dot { background: var(--ok); }
.livebtn .ic { width: 14px; text-align: center; font-size: 11px; color: var(--mute); }
.livebtn.on { border-color: color-mix(in srgb, var(--ok) 50%, transparent); }
.livebtn.on .dot.tick { animation: tick .45s ease-out; }
@keyframes tick {
  0% { transform: scale(1.8); box-shadow: 0 0 0 4px color-mix(in srgb, var(--ok) 50%, transparent); }
  100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) { .livebtn.on .dot.tick { animation: none; } }
@media (max-width: 900px) { .livegroup { order: 9; width: 100%; justify-content: flex-end; } }

/* Two subjects on one axis: what answers from outside, and what the
   machine does inside. */
.mgrid .grouphead { margin: 1.1rem 0 .3rem; padding-bottom: .3rem; border-bottom: 1px solid var(--line); font-size: 12px; text-transform: uppercase; letter-spacing: .08em; color: var(--ink-2); }
.mgrid .grouphead:first-child { margin-top: .2rem; }
.mgrid .grouphead .dim { text-transform: none; letter-spacing: 0; font-size: 11.5px; margin-left: .4rem; }
/* A failure is a moment, not a line: amber while it is being
   confirmed, red once the incident is real. */
.graph .span { pointer-events: none; }
.graph .span.confirming { fill: color-mix(in srgb, var(--warn) 22%, transparent); }
.graph .span.down { fill: color-mix(in srgb, var(--red) 28%, transparent); }
svg .span.silent { pointer-events: none; fill: color-mix(in srgb, var(--red) 28%, var(--panel)); }

/* Not yet asked again: the line carries on, dashed, to the edge. */
.graph .pending { fill: none; stroke-width: 1.4; stroke-dasharray: 3 4; opacity: .55; vector-effect: non-scaling-stroke; }

/* The lines of one subject: a port, a family, each its own colour. */
.graph .sl0 { stroke: var(--chart); } .nowv .n.sl0 { color: var(--chart); }
.graph .sl1 { stroke: var(--chart-2); } .nowv .n.sl1 { color: var(--chart-2); }
.graph .sl2 { stroke: #e5c07b; } .nowv .n.sl2 { color: #e5c07b; }
.graph .sl3 { stroke: #c678dd; } .nowv .n.sl3 { color: #c678dd; }
.graph .sl4 { stroke: #56b6c2; } .nowv .n.sl4 { color: #56b6c2; }
.graph .sl5 { stroke: #ff79c6; } .nowv .n.sl5 { color: #ff79c6; }
.graph .sl6 { stroke: #d19a66; } .nowv .n.sl6 { color: #d19a66; }
.graph .sl7 { stroke: #8be9fd; } .nowv .n.sl7 { color: #8be9fd; }
.graph [class^="sl"], .graph [class*=" sl"] { stroke-width: 1.6; fill: none; }
.graph .band[class*="sl"] { stroke: none; fill: color-mix(in srgb, var(--chart) 16%, transparent); }
.mchart .svcleg { font-size: 11.5px; }

/* The two roads of one service: v4 and v6 on the same chart. */
.graph .f4 { stroke: var(--chart); stroke-width: 1.8; fill: none; }
.graph .f6 { stroke: var(--chart-2); stroke-width: 1.8; fill: none; }
.graph .band.f4 { fill: color-mix(in srgb, var(--chart) 18%, transparent); stroke: none; }
.graph .band.f6 { fill: color-mix(in srgb, var(--chart-2) 18%, transparent); stroke: none; }
.nowv .n.f4 { color: var(--chart); } .nowv .n.f6 { color: var(--chart-2); }

/* A service's chart: its answer, and where it failed. */
.nowv .n.svcdown { color: var(--red); }
.mchart h3 a.plain { color: inherit; text-decoration: none; }
.mchart h3 a.plain:hover { color: var(--act); }

/* The value now, beside the title, in the series' colour. */
.mchart h3 .nowv { margin-left: .6rem; font-family: var(--mono); font-size: 13px; letter-spacing: 0; text-transform: none; }
.mchart h3 .nowv .n { font-weight: 700; margin-right: .5rem; }
.nowv .n.total, .nowv .n.up { color: var(--chart); } .nowv .n.l5 { color: var(--chart-2); }
.nowv .n.tx { color: var(--warn); } .nowv .n.dn, .nowv .n.l15 { color: var(--red); }
.nowv .n.l1 { color: var(--ok); }
/* The thresholds are named in the legend, not left as two dashes. */
.k.thrk::before { content: ""; display: inline-block; width: 12px; height: 0; border-top: 2px dashed var(--warn); margin-right: .3rem; vertical-align: middle; }
.k.thrk.down::before { border-top-color: var(--red); }

/* A rate is a bar from the middle line: what arrives goes up in blue,
   what leaves goes down in red — the side says the direction, the
   colour repeats it. */
.graph .fill { stroke: none; }
.graph .fill.up { fill: color-mix(in srgb, var(--chart) 62%, transparent); }
.graph .fill.dn { fill: color-mix(in srgb, var(--red) 62%, transparent); }
.graph .fill.dl { fill: color-mix(in srgb, var(--chart-2) 62%, transparent); }
.graph .fill.peak.dl { fill: color-mix(in srgb, var(--chart-2) 26%, transparent); }
.graph .fill.peak.up { fill: color-mix(in srgb, var(--chart) 26%, transparent); }
.graph .fill.peak.dn { fill: color-mix(in srgb, var(--red) 26%, transparent); }
.spark .up { stroke: var(--chart); } .spark .dn { stroke: var(--red); } .spark .dl { stroke: var(--chart-2); }
.spark .area.up { fill: color-mix(in srgb, var(--chart) 30%, transparent); }
.spark .area.dn { fill: color-mix(in srgb, var(--red) 30%, transparent); }

/* One window for every chart: the range chips sit in the title, the
   axis is shared, dragging moves in time. */
.machine .tranges { display: inline-flex; gap: .25rem; flex-wrap: wrap; margin-left: .4rem; }
.machine .tranges button { background: none; border: 1px solid var(--line); border-radius: 999px; padding: .05rem .5rem; font-size: 11.5px; color: var(--mute); cursor: pointer; }
.machine .tranges button.on { color: var(--act); border-color: var(--act); }
.machine .tranges .treset { color: var(--warn); border-color: var(--warn); }
/* The gestures belong between the instruments and the charts, on
   their own line, spaced. */
.machine .navhint { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: .15rem 1.4rem; margin: .9rem 0 .1rem; padding-top: .5rem; border-top: 1px solid var(--line); font-size: 10.5px; letter-spacing: .02em; }
.mgraph { cursor: grab; }
.mgraph.grabbing { cursor: grabbing; }
.mchart .spec { margin: .05rem 0 .55rem; font-size: 11px; }

/* The machine reads as stat blocks: label, the number, the context,
   the bar — not a list of sentences. */
.machinegrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: .45rem 1rem; margin-top: .35rem; align-items: stretch; }
.mstat { display: flex; flex-direction: column; align-items: center; text-align: center; gap: .12rem; min-width: 0; }
/* Every block's sparkline sits on the same line, dial or number. */
.mstat .sparkwrap { margin-top: auto; }
.mstat .lbl { font-size: 12.5px; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mstat .num { font-size: 17px; font-weight: 700; font-family: var(--mono); line-height: 1.15; color: var(--ink); white-space: nowrap; }
.mstat .sub { font-size: 11.5px; color: var(--mute); font-family: var(--mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mstat .bar { display: block; width: 100%; position: relative; height: 6px; background: var(--panel-3); border-radius: 4px; overflow: hidden; margin-top: .15rem; }
.mstat .bar i { position: absolute; left: 0; top: 0; bottom: 0; background: var(--act); border-radius: 4px; }
.mstat .bar.warn i { background: var(--warn); }
.mstat .bar.down i { background: var(--red); }



/* The tooltip names its series in colour. */
.tip .tipk { display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin-right: .4rem; }

/* Sixteen user colours — system users are many. */
.graph .u8 { stroke: #61afef; }
.graph .u9 { stroke: #98c379; }
.graph .u10 { stroke: #e5c07b; }
.graph .u11 { stroke: #ff79c6; }
.graph .u12 { stroke: #8be9fd; }
.graph .u13 { stroke: #bd93f9; }
.graph .u14 { stroke: #ffb86c; }
.graph .u15 { stroke: #7f848e; }
.ku.more { border: 1px dashed var(--line-2); border-radius: 999px; padding: 0 .45rem; }
.ku.more::before { display: none; }
.ku.more.on { border-color: var(--act); color: var(--ink); }


/* ———— one token per series ————— A series has ONE colour, written
   once here, and everything that shows that series reads it: the
   swatch under the chart, the name beside the swatch, the swatch in
   the tooltip and the name in the tooltip. Declared three or four
   times each instead, colouring the names reaches some and not
   others. Adding a series is one line. */
.k.total, .tipk.total, .tipn.total, .graph .total { --sk: var(--chart); }
.k.ttfb, .tipk.ttfb, .tipn.ttfb, .graph .ttfb { --sk: var(--act-2); }
.k.rtt, .tipk.rtt, .tipn.rtt, .graph .rtt { --sk: var(--warn); }
.k.warm, .tipk.warm, .tipn.warm, .graph .warm { --sk: var(--ok); }
.k.rx, .tipk.rx, .tipn.rx, .graph .rx { --sk: var(--chart); }
.k.tx, .tipk.tx, .tipn.tx, .graph .tx { --sk: var(--warn); }
.k.up, .tipk.up, .tipn.up, .graph .up { --sk: var(--chart); }
.k.dn, .tipk.dn, .tipn.dn, .graph .dn { --sk: var(--red); }
.k.dl, .tipk.dl, .tipn.dl, .graph .dl { --sk: var(--chart-2); }
.k.l1, .tipk.l1, .tipn.l1, .graph .l1 { --sk: var(--chart); }
.k.l5, .tipk.l5, .tipn.l5, .graph .l5 { --sk: var(--chart-2); }
.k.l15, .tipk.l15, .tipn.l15, .graph .l15 { --sk: var(--red); }
.k.f4, .tipk.f4, .tipn.f4, .graph .f4 { --sk: var(--chart); }
.k.f6, .tipk.f6, .tipn.f6, .graph .f6 { --sk: var(--chart-2); }
.k.svcdown, .tipk.svcdown, .tipn.svcdown, .graph .svcdown { --sk: var(--red); }
.k.peermed, .tipk.peermed, .tipn.peermed, .graph .peermed { --sk: var(--chart-2); }
.k.peerband, .tipk.peerband, .tipn.peerband, .graph .peerband { --sk: var(--chart-2); }
.k.m-used, .tipk.m-used, .tipn.m-used, .graph .m-used { --sk: var(--mem-used); }
.k.m-buf, .tipk.m-buf, .tipn.m-buf, .graph .m-buf { --sk: var(--mem-buf); }
.k.m-cache, .tipk.m-cache, .tipn.m-cache, .graph .m-cache { --sk: var(--mem-cache); }
.k.m-free, .tipk.m-free, .tipn.m-free, .graph .m-free { --sk: var(--mem-free); }
.k.m-swap, .tipk.m-swap, .tipn.m-swap, .graph .m-swap { --sk: var(--mem-swap); }
.k.m-avail, .tipk.m-avail, .tipn.m-avail, .graph .m-avail { --sk: var(--mem-avail); }
.k.uall, .tipk.uall, .tipn.uall, .graph .uall, .k.utotal { --sk: var(--ink); }
/* The phases a response time is made of, stacked: connect, TLS, the
   server's own thinking, the transfer, and whatever the total holds
   that none of them claimed. */
.k.ph1, .tipk.ph1, .tipn.ph1, .graph .ph1 { --sk: var(--chart-2); }
.k.ph2, .tipk.ph2, .tipn.ph2, .graph .ph2 { --sk: var(--act-2); }
.k.ph3, .tipk.ph3, .tipn.ph3, .graph .ph3 { --sk: var(--chart); }
.k.ph4, .tipk.ph4, .tipn.ph4, .graph .ph4 { --sk: var(--warn); }
.k.ph5, .tipk.ph5, .tipn.ph5, .graph .ph5 { --sk: var(--unknown); }
.k.s0, .tipk.s0, .tipn.s0, .graph .s0 { --sk: var(--chart); }
.k.s1, .tipk.s1, .tipn.s1, .graph .s1 { --sk: var(--act); }
.k.s2, .tipk.s2, .tipn.s2, .graph .s2 { --sk: var(--act-2); }
.k.s3, .tipk.s3, .tipn.s3, .graph .s3 { --sk: var(--warn); }
.k.s4, .tipk.s4, .tipn.s4, .graph .s4 { --sk: var(--red); }
.k.s5, .tipk.s5, .tipn.s5, .graph .s5 { --sk: var(--chart-2); }
.k.s6, .tipk.s6, .tipn.s6, .graph .s6 { --sk: var(--ok); }
.k.s7, .tipk.s7, .tipn.s7, .graph .s7 { --sk: var(--act); }
.k.s8, .tipk.s8, .tipn.s8, .graph .s8 { --sk: var(--warn); }
.k.s9, .tipk.s9, .tipn.s9, .graph .s9 { --sk: var(--unknown); }
.k.sl0, .tipk.sl0, .tipn.sl0, .graph .sl0 { --sk: var(--chart); }
.k.sl1, .tipk.sl1, .tipn.sl1, .graph .sl1 { --sk: var(--chart-2); }
.k.sl2, .tipk.sl2, .tipn.sl2, .graph .sl2 { --sk: #e5c07b; }
.k.sl3, .tipk.sl3, .tipn.sl3, .graph .sl3 { --sk: #c678dd; }
.k.sl4, .tipk.sl4, .tipn.sl4, .graph .sl4 { --sk: #56b6c2; }
.k.sl5, .tipk.sl5, .tipn.sl5, .graph .sl5 { --sk: #ff79c6; }
.k.sl6, .tipk.sl6, .tipn.sl6, .graph .sl6 { --sk: #d19a66; }
.k.sl7, .tipk.sl7, .tipn.sl7, .graph .sl7 { --sk: #8be9fd; }
.k.u0, .tipk.u0, .tipn.u0, .graph .u0 { --sk: var(--chart); }
.k.u1, .tipk.u1, .tipn.u1, .graph .u1 { --sk: var(--chart-2); }
.k.u2, .tipk.u2, .tipn.u2, .graph .u2 { --sk: var(--warn); }
.k.u3, .tipk.u3, .tipn.u3, .graph .u3 { --sk: #c678dd; }
.k.u4, .tipk.u4, .tipn.u4, .graph .u4 { --sk: #56b6c2; }
.k.u5, .tipk.u5, .tipn.u5, .graph .u5 { --sk: var(--red); }
.k.u6, .tipk.u6, .tipn.u6, .graph .u6 { --sk: #d19a66; }
.k.u7, .tipk.u7, .tipn.u7, .graph .u7 { --sk: var(--mute); }
.k.u8, .tipk.u8, .tipn.u8, .graph .u8 { --sk: #61afef; }
.k.u9, .tipk.u9, .tipn.u9, .graph .u9 { --sk: #98c379; }
.k.u10, .tipk.u10, .tipn.u10, .graph .u10 { --sk: #e5c07b; }
.k.u11, .tipk.u11, .tipn.u11, .graph .u11 { --sk: #ff79c6; }
.k.u12, .tipk.u12, .tipn.u12, .graph .u12 { --sk: #8be9fd; }
.k.u13, .tipk.u13, .tipn.u13, .graph .u13 { --sk: #bd93f9; }
.k.u14, .tipk.u14, .tipn.u14, .graph .u14 { --sk: #ffb86c; }
.k.u15, .tipk.u15, .tipn.u15, .graph .u15 { --sk: #7f848e; }
.legend .k::before, .tip .tipk { background: var(--sk, var(--chart)); }
.legend .k, .tip .tipn { color: var(--sk, inherit); }
.tip .tipn { font-weight: 600; }
/* The way out to the site an account serves: a mark, not a second
   name on the line. */
.ku .usite { margin-left: .25rem; color: var(--mute); text-decoration: none; }
.ku .usite:hover { color: var(--act); }
/* A swatch that is a dashed rule, not a block, keeps its own shape. */
.k.thrk.down::before { border-top-color: var(--red); }
.legend .k.off { color: var(--mute); }

/* A login, a domain, a path: never shouted in capitals by a title's
   text-transform (the first letters take a capital, the names are
   written as they are). */
.mchart h3 .mono, .mchart h3 .name, .mchart h3 .dim { text-transform: none; letter-spacing: 0; }
.mchart h3 .dim { font-weight: 400; margin-left: .35rem; }

/* ————— one check, looked at closely (the monitor and site pages) —————
   The same frame and the same colours as the host page: a reader who
   learnt one chart has learnt them all. */
.tcharts .mchart.tall .mgraph { height: 220px; }
.tcharts .nav-help { margin: .1rem 0 .4rem; }
.tcharts .nav-help .tstate { margin-left: .6rem; color: var(--ink-2); }
.tcharts.picked .nav-help .tstate::before { content: "▸ "; }
/* The second family is the same measure on another road: same colour,
   dashed, so the eye pairs them instead of reading two subjects. */
.graph path.f6 { stroke-dasharray: 5 3; opacity: .85; }
.mchart .k.u0::before, .legend .k.u0::before { background: var(--chart); }
.mchart .k.uall::before, .legend .k.uall::before { background: var(--ink); }
.tcharts .legend .k[data-tsk] { cursor: pointer; }
.tcharts .legend .k.off { opacity: .45; text-decoration: line-through; }
.legend .k.sl1::before { background: var(--chart-2); }
.legend .k.sl2::before { background: #e5c07b; }

/* A host with no site matching the filter stays on the page, dimmed:
   the machine and its services are never hidden by a filter that is
   about sites. */
.hostblock.nomatch > summary { opacity: .55; }
.hostblock.nomatch > summary .sitecount::after { content: " — none matches the filter"; font-style: italic; }
.count .clearf { margin-left: .4rem; color: var(--act); text-decoration: none; }
.count .clearf:hover { text-decoration: underline; }

/* A row the filter left out. The owner fold uses [hidden]; the filter
   uses this: one property each, so neither can undo the other. */
tr.fout, .fout { display: none !important; }

/* The machine's other sites: the neighbours' lines are dashed and the
   site's own is the only solid one, so the two are never read as the
   same kind of thing. */
.graph .peerband { fill: none; stroke: var(--chart-2); stroke-dasharray: 4 3; opacity: .8; }
.graph .peermed { stroke: var(--chart-2); stroke-width: 1.4; stroke-dasharray: 5 3; fill: none; }
.legend .k.peermed::before { background: var(--chart-2); }
.legend .k.peerband::before { background: var(--chart-2); opacity: .8; }
.tcharts .legend .pstats { margin-left: auto; }

/* A section that folds: the whole title is the handle. */
.foldhead { cursor: pointer; user-select: none; }
.foldhead .foldbtn { background: none; border: 0; color: var(--mute); font-size: 13px; cursor: pointer; padding: 0 .35rem 0 0; }
.foldhead:hover .foldbtn { color: var(--ink); }
.foldhead a { cursor: pointer; }
.livegroup .blurbtn { width: 26px; padding: .28rem 0; text-align: center; font-size: 13px; line-height: 1; }

/* ———— a phone ————— The same pages, read on a 390-pixel screen: two
   cards a row, tables that scroll inside their own box instead of
   pushing the page sideways, and the columns an admin can do without
   on the move. */
@media (max-width: 700px) {
  main { padding: .7rem; }
  .cards.compact { grid-template-columns: 1fr 1fr; }
  .card .num { font-size: 18px; }
  table.list, table.sites { display: block; overflow-x: auto; max-width: 100%; }
  table.list > tbody, table.sites > tbody, table.list > thead, table.sites > thead { display: table; width: 100%; }
  #tree .c-addr, #tree .c-since, #tree .c-detail { display: none; }
  .treebar { gap: .35rem; }
  .treebar #treefilter { min-width: 0; flex: 1 1 100%; }
  .head h1 { font-size: 19px; word-break: break-word; }
  .chart { padding: .5rem .6rem; }
  .legend { flex-wrap: wrap; gap: .3rem .7rem; }
  .tape { height: 128px; }
  .tape .chip { max-width: 150px; font-size: 10.5px; }
  /* An incident line stacks instead of holding four columns open. */
  .tl, .alerts .tl { grid-template-columns: auto 1fr; gap: .2rem .5rem; }
  .tl .when { grid-column: 1; }
  .tl .tag { justify-self: start; }
  .tl .what { grid-column: 1 / -1; }
  .alerts .tl > a[href^="/incidents"] { display: none; }
  .services { flex-wrap: wrap; }
  .cards { gap: .4rem; }
  .foot { padding: 0 .7rem; }
}

/* The wall, stacked: a tile whose list is long splits into columns
   rather than running off the bottom of the screen, and the whole
   thing uses the width it is given. */
.wallsect { font-size: 12px; text-transform: uppercase; letter-spacing: .09em; color: var(--ink-2); margin: 1.1rem 0 .4rem; }
.wallsect:first-of-type { margin-top: 0; }
.wall .tilerows { columns: 320px auto; column-gap: 1.2rem; }
.wall .tilerows .siterow { break-inside: avoid; }
.wall .tile.core { border-color: color-mix(in srgb, var(--red) 35%, var(--line)); }
.wall .tile.svc { border-color: color-mix(in srgb, var(--warn) 35%, var(--line)); }
/* In the popup the wall is a panel, not a page. */
.modalbody .wall { min-height: 0; padding: .2rem; background: none; }
.modalbody .wallhead .big { font-size: 22px; }
.modalbody .walltiles { grid-template-columns: 1fr; }
.modalbody .wall .tilerows { columns: auto; }
.wallpeek { font-size: 13px; padding: .25rem .5rem; }

/* Two lines, small: the name, then what it took. */
.chip { line-height: 1.15; }
.chip b { display: block; font-weight: 500; overflow: hidden; text-overflow: ellipsis; }
.chip i { display: block; font-style: normal; font-size: 9.5px; opacity: .65; }
.tape.full .chip { font-size: 12px; max-width: 240px; }
.tape.full .chip i { font-size: 10.5px; }
/* A check still to come must be visible against the belt, not a ghost
   the same colour as the background. */
.chip.ghost { border-style: dashed; border-color: var(--line-2); color: var(--ink-2); background: color-mix(in srgb, var(--panel-3) 60%, transparent); }
.chip.waiting { border-style: solid; border-color: color-mix(in srgb, var(--act) 70%, var(--line)); color: var(--ink); box-shadow: 0 0 0 2px color-mix(in srgb, var(--act) 18%, transparent); }
/* Bars: one belt-wide choice, never a chip that turns into one and
   back. A bar is a coloured mark, not a shrunken label. */
#tapetrack.bars .chip { width: 12px; max-width: 12px; padding: 0; overflow: hidden; height: 15px; border-radius: 3px; }
#tapetrack.bars .chip b, #tapetrack.bars .chip i { display: none; }
#tapetrack.bars .chip.landed.ok { background: var(--ok); border-color: var(--ok); }
#tapetrack.bars .chip.landed.down { background: var(--red); border-color: var(--red); }
#tapetrack.bars .chip.landed.warn { background: var(--warn); border-color: var(--warn); }
#tapetrack.bars .chip.landed.mute { background: var(--mute); border-color: var(--mute); }
#tapetrack.bars .chip.ghost { background: color-mix(in srgb, var(--ink) 14%, transparent); border-color: var(--line-2); }
/* Appearing anywhere but the right edge: fade in, never pop. */
.chip.appear { animation: chipin .45s ease-out; }
@keyframes chipin { from { opacity: 0; transform: translateX(10px); } to { opacity: 1; transform: none; } }

/* The lane's name sits over the belt: it needs its own ground, or a
   note passing behind it is unreadable. */
.tape .lanelbl { background: var(--panel); padding: 0 .3rem; border-radius: 4px; z-index: 3; }

/* What a check is actually saying, at the top of its own page. */
.reasonline { margin: .3rem 0 .5rem; padding: .35rem .6rem; border-radius: var(--r-s); font-family: var(--mono); font-size: 12.5px; background: var(--panel-2); border-left: 3px solid var(--line-2); }
.reasonline.down { border-left-color: var(--red); }
.reasonline.warn { border-left-color: var(--warn); }
.reasonline.ok { border-left-color: var(--ok); }

/* A packet on its way to the line already wears the answer it had last
   time, faintly; it turns solid when its own answer lands. An arriving
   unknown is then told apart from an established one at a glance. */
.chip.ghost.was-ok { border-color: color-mix(in srgb, var(--ok) 45%, var(--line)); background: color-mix(in srgb, var(--ok) 9%, transparent); color: var(--ink-2); }
.chip.ghost.was-down { border-color: color-mix(in srgb, var(--red) 45%, var(--line)); background: color-mix(in srgb, var(--red) 9%, transparent); color: var(--ink-2); }
.chip.ghost.was-warn { border-color: color-mix(in srgb, var(--warn) 45%, var(--line)); background: color-mix(in srgb, var(--warn) 9%, transparent); color: var(--ink-2); }
.chip.ghost.was-maint, .chip.ghost.was-mute { border-color: var(--line-2); }
/* Answered: solid, and saturated. */
.chip.landed { color: var(--ink); }
.chip.landed.ok { background: color-mix(in srgb, var(--ok) 26%, transparent); border-color: var(--ok); }
.chip.landed.down { background: color-mix(in srgb, var(--red) 30%, transparent); border-color: var(--red); }
.chip.landed.warn { background: color-mix(in srgb, var(--warn) 28%, transparent); border-color: var(--warn); }
/* And a state that CHANGED says so, once. */
.chip.changed { animation: chipchange 1.6s ease-out; }
@keyframes chipchange {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--ink) 55%, transparent); transform: scale(1.14); }
  35%  { box-shadow: 0 0 0 7px color-mix(in srgb, var(--ink) 0%, transparent); transform: scale(1); }
  100% { box-shadow: 0 0 0 0 transparent; }
}

/* Linear or logarithmic, the reader's choice, next to the legend. */
.logtoggle { margin-left: auto; font-size: 10.5px; padding: .05rem .4rem; border: 1px solid var(--line); border-radius: 999px; background: none; color: var(--mute); cursor: pointer; }
.logtoggle.on { color: var(--act); border-color: var(--act); }
/* Which road to read the check on: both together, or one alone. It
   sits at the right end of the legend, before the scale toggle. */
.famsel { margin-left: auto; display: inline-flex; gap: .2rem; }
.famsel + .logtoggle { margin-left: .35rem; }
.famsel button { font-size: 10.5px; padding: .05rem .4rem; border: 1px solid var(--line); border-radius: 999px; background: none; color: var(--mute); cursor: pointer; }
.famsel button.on { color: var(--act); border-color: var(--act); }

/* A reseller's customers sit under it, and the nesting must be
   visible without counting pixels. A rule down the left of the nested
   block says where it belongs; the padding alone did not. */
/* Every fault a domain has, each one a filter. They are small and
   quiet: the column is read when something is wrong, not stared at. */
/* The faults take the room they need and no more: what fits stays on
   the line, the rest folds behind a count the reader opens — a row
   that spills its badges over the column beside it is unreadable. */
table.sites td.c-wrong { max-width: 20rem; overflow: hidden; }
table.sites td.c-wrong .probs { display: flex; flex-wrap: wrap; gap: .1rem .2rem; max-height: 1.35rem; overflow: hidden; }
table.sites td.c-wrong.open .probs { max-height: none; }
.probmore { background: none; border: 0; color: var(--mute); font-size: 10.5px; cursor: pointer; padding: 0 .2rem; white-space: nowrap; }
.probmore:hover { color: var(--act); }
#tree.no-notes .tag.prob.note { display: none; }
.tag.prob { font-size: 10.5px; padding: 0 .35rem; margin: 0 .2rem .1rem 0; display: inline-block; border-radius: var(--r-s); border: 1px solid var(--line); color: var(--ink-2); }
.tag.prob:hover { border-color: var(--act); color: var(--ink); }
.tag.prob.down { color: var(--red); border-color: color-mix(in srgb, var(--red) 40%, transparent); }
.tag.prob.warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, transparent); }
.tag.prob.note { color: var(--mute); }
#tree.no-wrong .c-wrong { display: none; }
table.sites tr.owner.d1 td, table.sites tbody.d1 td.name { box-shadow: inset 2px 0 0 var(--line-2); }
table.sites tr.owner.d2 td, table.sites tbody.d2 td.name { box-shadow: inset 2px 0 0 var(--line-2), inset 1.4rem 0 0 -1.2rem var(--line-2); }
table.sites tr.owner.d1 td { padding-left: 2.2rem; }
table.sites tr.owner.d2 td { padding-left: 3.6rem; }
table.sites tr.owner.d1 .under, table.sites tr.owner.d2 .under { margin-right: .15rem; }
table.sites tbody.d1 td.name { padding-left: 2.6rem; }
table.sites tbody.d2 td.name { padding-left: 4rem; }
/* What an alias reaches, rather than what it owns. */
table.list tr.via td { opacity: .72; font-style: italic; }


/* the public status page */
.statuspage { max-width: 900px; margin: 0 auto; }
.statuspage .banner { display: flex; align-items: center; gap: .6rem; padding: .8rem 1rem; border-radius: var(--r); border: 1px solid var(--line); background: var(--panel); font-size: 16px; font-weight: 600; margin: .5rem 0 1.2rem; }
.statuspage .banner.ok { border-color: color-mix(in srgb, var(--ok) 40%, transparent); background: color-mix(in srgb, var(--ok) 10%, var(--panel)); }
.statuspage .banner.warn { border-color: color-mix(in srgb, var(--warn) 40%, transparent); background: color-mix(in srgb, var(--warn) 10%, var(--panel)); }
.statuspage .banner.down { border-color: color-mix(in srgb, var(--red) 40%, transparent); background: color-mix(in srgb, var(--red) 10%, var(--panel)); }
.statuspage .banner.maint { border-color: color-mix(in srgb, var(--maint) 40%, transparent); background: color-mix(in srgb, var(--maint) 10%, var(--panel)); }
.statuspage .comp { padding: .7rem 0; border-bottom: 1px solid var(--line); }
.statuspage .comprow { display: flex; align-items: center; gap: .6rem; margin-bottom: .35rem; }
.statuspage .clabel { font-weight: 600; flex: 1; }
.statuspage .cword { font-size: 13px; }
.statuspage .cavail { font-size: 13px; min-width: 9rem; text-align: right; }
.statuspage .c-ok { color: var(--ok); } .statuspage .c-warn { color: var(--warn); } .statuspage .c-down { color: var(--red); } .statuspage .c-maint { color: var(--maint); } .statuspage .c-unknown, .statuspage .c-ext { color: var(--mute); }
.daybar { display: flex; gap: 2px; }
.daybar i { flex: 1; height: 22px; border-radius: 2px; background: var(--panel-3); min-width: 0; }
.daybar i.ok { background: var(--ok); } .daybar i.warn { background: var(--warn); } .daybar i.down { background: var(--red); } .daybar i.maint { background: var(--maint); }
.daybar i.none { background: var(--panel-3); }
.pubcurrent, .pubwindows { margin: 1.4rem 0; }
.pubcurrent h2, .pubwindows h2, .pubincidents h2 { margin-bottom: .5rem; }
.pubnone { margin: .2rem 0 0; }
.pubwin { padding: .6rem .9rem; border-radius: var(--r); border: 1px solid color-mix(in srgb, var(--maint) 40%, transparent); background: color-mix(in srgb, var(--maint) 8%, var(--panel)); margin-bottom: .5rem; }
.pubwin p, .pubinc p { margin: .3rem 0 0; }
.pubincidents h2 { margin-top: 1.4rem; }
.pubincidents { margin-top: 2.6rem; }
.pubinc { padding: .6rem 0; border-bottom: 1px solid var(--line); }
.pubinc summary { list-style: none; cursor: pointer; }
.pubinc summary::-webkit-details-marker { display: none; }
.pubinc summary > div:first-child::after { content: " ▾"; color: var(--mute); font-size: 12px; }
.pubinc[open] summary > div:first-child::after { content: " ▴"; }
.pubinc .pubtimeline { margin: .4rem 0 0 .4rem; padding-left: .8rem; border-left: 2px solid var(--line-2); }
.pubcard { padding: .8rem 1rem; border-radius: var(--r); border: 1px solid var(--line); border-left-width: 4px; background: var(--panel); margin-bottom: .6rem; }
.pubcard.down { border-left-color: var(--red); } .pubcard.warn { border-left-color: var(--warn); } .pubcard.info { border-left-color: var(--act); }
.pubcardhead { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; margin-bottom: .3rem; }
.pubtitle { font-weight: 600; font-size: 15px; flex: 1; color: var(--ink); }
.pubupdate p { margin: .3rem 0; }
.pubtimeline { margin-top: 1rem; }
.pubentry { display: grid; grid-template-columns: 13rem 1fr; gap: .6rem; padding: .7rem 0; border-top: 1px solid var(--line); }
.pubentry .pubtext p { margin: 0 0 .4rem; }
@media (max-width: 640px) { .pubentry { grid-template-columns: 1fr; gap: .2rem; } }
.upedit summary { list-style: none; cursor: pointer; display: inline-block; margin-top: .3rem; }
.upedit summary::-webkit-details-marker { display: none; }
.upedit[open] summary { display: none; }
.upedit form { margin-top: .4rem; padding: .6rem .8rem; border: 1px solid var(--line); border-radius: var(--r); background: var(--panel); }
.affected .ticks { display: flex; flex-wrap: wrap; gap: .2rem 1rem; margin: .3rem 0; }
.pubform textarea.wide { width: 100%; }
.pubform fieldset { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: .6rem; align-items: end; border: 1px solid var(--line); border-radius: var(--r); padding: .4rem .8rem .8rem; }
.pubform fieldset legend { font-size: 12px; color: var(--mute); text-transform: uppercase; letter-spacing: .06em; }
.pubform fieldset > .wide { grid-column: 1 / -1; }
.affected label.tick { display: inline-flex; flex-direction: row; align-items: center; gap: .35rem; color: var(--ink); }
.affected > label.tick { display: flex; margin-top: .5rem; }
.affected label.tick input { width: auto; flex: 0 0 auto; margin: 0; }
.pubform .actions, form.grid .actions { display: flex; gap: .5rem; align-items: center; grid-column: 1 / -1; }
.monedit summary { list-style: none; display: inline-block; margin-top: .4rem; }
.certdet summary { list-style: none; cursor: pointer; }
.certdet summary::-webkit-details-marker { display: none; }
.certdet summary h2 { display: inline; }
.certdet summary h2::after { content: " ▾"; color: var(--mute); font-size: 12px; }
.certdet[open] summary h2::after { content: " ▴"; }
.checkurl summary { cursor: pointer; }
.alertdet { margin: .6rem 0; }
.alertdet summary { cursor: pointer; }
.checkurl form { margin-top: .3rem; }
.monedit summary::-webkit-details-marker { display: none; }
.monedit form { margin-top: .4rem; padding: .6rem .8rem; border: 1px solid var(--line); border-radius: var(--r); background: var(--panel); }
.pubwhen .dim { display: block; margin-top: .25rem; }
.pubfoot { margin-top: 2rem; text-align: center; }
.statusform fieldset { border: 1px solid var(--line); border-radius: var(--r); padding: .4rem .8rem; }
.statusform fieldset legend { font-size: 12px; color: var(--mute); text-transform: uppercase; letter-spacing: .06em; }
.statusform .tick { display: inline-block; margin-right: 1rem; }
.statusform label.wide, .statusform fieldset { grid-column: 1 / -1; }
.statusform textarea { width: 100%; }


/* the save bar of a settings page, and the name server sets */
.savebar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 30; display: flex; justify-content: flex-end; align-items: center; gap: 1rem; padding: .6rem 1.2rem; background: var(--panel); border-top: 1px solid var(--line-2); box-shadow: var(--shadow); }
.savebar[hidden] { display: none; }
.nsedit .nsset { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; padding: .4rem 0; border-bottom: 1px solid var(--line); }
.nsedit .nsname { width: 9rem; }
.nsedit .chips { display: inline-flex; flex-wrap: wrap; gap: .3rem; align-items: center; flex: 1; }
.nsedit .tag .x { padding: 0 .2rem; margin-left: .2rem; line-height: 1; }

.statuspage details.compdet > summary { list-style: none; cursor: pointer; }
.statuspage details.compdet > summary::-webkit-details-marker { display: none; }
.statuspage .caret { font-size: 11px; margin-right: .4rem; transition: transform .15s; }
.statuspage details[open] .caret { transform: rotate(180deg); }
.statuspage .compmore { margin: .5rem 0 0 1.2rem; padding-left: .8rem; border-left: 2px solid var(--line); }
.statuspage .sub { display: flex; align-items: center; gap: .5rem; padding: .2rem 0; font-size: 13px; }
.statuspage .slabel { flex: 1; }
.statuspage .subgrid { display: flex; flex-wrap: wrap; gap: .3rem .9rem; padding: .3rem 0; font-size: 12.5px; }
.statuspage .adminlink { margin-left: .5rem; font-weight: 400; }

.copy, .openlink { padding: 0 .3rem; margin-left: .15rem; font-size: 12px; line-height: 1.2; vertical-align: baseline; color: var(--mute); }
.copy:hover, .openlink:hover { color: var(--ink); }

.head2 .headcols { display: grid; grid-template-columns: 1.4fr 1fr; gap: .4rem 1.5rem; margin: .3rem 0 .2rem; }
.head2 .headcol p { margin: .15rem 0; }
.head2 .reasonline { margin-top: 0; }
@media (max-width: 800px) { .head2 .headcols { grid-template-columns: 1fr; } }
.sites .copy { opacity: 0; }
.sites tr:hover .copy, .sites .copy:focus { opacity: 1; }

.statuspage .sectitle { display: flex; align-items: center; gap: .5rem; margin: 1.4rem 0 .2rem; }
.statuspage .secdesc { margin: 0 0 .4rem; }
.statuspage .subhead { margin: .5rem 0 .1rem; font-size: 11px; text-transform: uppercase; letter-spacing: .06em; }
.statuspage .sub { display: block; padding: .25rem 0; }
.statuspage .sub .daybar.small { margin-top: 3px; }
.statuspage .subrow { display: flex; align-items: center; gap: .5rem; font-size: 13px; }
.statuspage .daybar.small i { height: 10px; }
.statuspage .cnote { font-weight: 400; margin-left: .4rem; }
.layout .lsection { border: 1px solid var(--line); border-radius: var(--r); padding: .5rem .7rem; margin: .5rem 0; background: var(--panel); }
.layout .lhead { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; margin-bottom: .3rem; }
.layout .ltitle { width: 14rem; font-weight: 600; }
.layout .ldesc { flex: 1; min-width: 12rem; }
.layout .litem { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; padding: .25rem 0; border-top: 1px solid var(--line); }
.layout .lname { min-width: 9rem; }
.layout .llabel, .layout .lnote { flex: 1; min-width: 9rem; }
.layout .ladd { display: flex; gap: .4rem; align-items: center; padding-top: .4rem; border-top: 1px dashed var(--line); margin-top: .2rem; }

.pubchartbox { margin: .4rem 0 .2rem; }
.pubchart { width: 100%; height: 90px; display: block; }
.pubchart .line { fill: none; stroke: var(--chart); stroke-width: 1.6; vector-effect: non-scaling-stroke; }
.pubchart .axis { stroke: var(--line-2); stroke-width: 1; vector-effect: non-scaling-stroke; }
.pubchart .grid { stroke: var(--line); stroke-width: 1; stroke-dasharray: 3 3; vector-effect: non-scaling-stroke; }
.pubchart text { font-family: var(--mono); font-size: 10px; fill: var(--mute); }
.layout .lopts { padding: .2rem 0 .4rem 1.5rem; font-size: 12.5px; }
.layout .lopts .tick { margin-right: .8rem; }
.layout .lopts2 { margin-top: .2rem; }

.openinc { margin: .4rem 0 .2rem; padding: .4rem .7rem; border-left: 3px solid var(--red); background: color-mix(in srgb, var(--red) 6%, var(--panel)); border-radius: 0 var(--r) var(--r) 0; }
.openinc .incline { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; padding: .15rem 0; }
.openinc .ackbox { color: var(--ok); font-size: 13px; }
.openinc .ackform { margin: 0; }

/* acknowledged: down, and in someone's hands — its own colour, never red */
.tag.ack { color: var(--ack); border-color: color-mix(in srgb, var(--ack) 45%, transparent); background: color-mix(in srgb, var(--ack) 12%, transparent); }
.dot.ack { background: var(--ack); }
.c-ack { color: var(--ack); }
.card.ack { border-color: color-mix(in srgb, var(--ack) 45%, transparent); }
.card.ack .num { color: var(--ack); }
.fb.ack { color: var(--ack); }

/* one cross on every search field, the browser's own turned off */
input[type=search]::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; display: none; }
.searchbox { position: relative; display: inline-flex; align-items: center; }
.searchbox input[type=search] { padding-right: 1.5rem; }
.searchbox .clearbtn { position: absolute; right: .2rem; top: 50%; transform: translateY(-50%); border: 0; background: none; color: var(--mute); cursor: pointer; padding: 0 .25rem; font-size: 12px; line-height: 1; }
.searchbox .clearbtn:hover { color: var(--ink); }


/* the machine's line: one grid, the same columns on every machine */
.hostblock summary { display: grid; grid-template-columns: 1.1rem minmax(11rem, 15rem) 5.2rem 7.5rem 6.5rem 27rem minmax(12rem, 1fr) auto; grid-template-areas: "caret name state svc rtt vitals load tags" "caret services services services services services services services"; align-items: center; column-gap: .6rem; row-gap: .25rem; }
.hostblock summary::before { grid-area: caret; align-self: start; margin-top: .15rem; }
.hostblock summary .c-name { grid-area: name; display: inline-flex; align-items: center; gap: .5rem; min-width: 0; }
.hostblock summary .c-name .hostname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hostblock summary .c-state { grid-area: state; }
.hostblock summary .c-svc { grid-area: svc; font-size: 13px; white-space: nowrap; }
.hostblock summary .c-rtt { grid-area: rtt; font-size: 13px; white-space: nowrap; }
.hostblock summary .c-rtt i { font-style: normal; font-size: 9.5px; text-transform: uppercase; letter-spacing: .07em; color: var(--mute); }
.hostblock summary .c-vitals { grid-area: vitals; }
.hostblock summary .vitals { display: grid; grid-template-columns: 5.5rem 7.5rem 6.5rem 6.5rem; gap: 0; margin: 0; }
.hostblock summary .c-load { grid-area: load; font-size: 13px; white-space: normal; line-height: 1.25; }
.hostblock summary .c-tags { grid-area: tags; display: inline-flex; gap: .25rem; flex-wrap: wrap; }
.hostblock summary .c-services { grid-area: services; margin-left: 0; }
@media (max-width: 1100px) { .hostblock summary { display: flex; flex-wrap: wrap; } .hostblock summary .vitals { display: inline-flex; gap: 1rem; } }

/* the groups, said: a title and a rule between two of them */
.grouptitle { margin: 1.4rem 0 .4rem; padding-bottom: .25rem; border-bottom: 1px solid var(--line-2); font-size: 12px; text-transform: uppercase; letter-spacing: .08em; color: var(--mute); }
#tree > .grouptitle:first-child { margin-top: .4rem; }

.ownerpick { width: 13rem; }

/* The host page's chart sections: foldable, remembered, and the
   tables of a section stack with its charts. */
.mgrid .foldbody { display: grid; grid-template-columns: 1fr; gap: .3rem; }
.mgrid .grouphead.foldhead { cursor: pointer; user-select: none; }
.mgrid .grouphead .foldbtn { background: none; border: 0; color: var(--mute); font-size: 12px; cursor: pointer; padding: 0 .35rem 0 0; }
.mgrid .grouphead:hover .foldbtn { color: var(--ink); }
.mgrid .foldbody > h4 { margin: .4rem 0 .1rem; font-size: 12.5px; font-weight: 600; }
.mgrid .foldbody > h4 .small { font-weight: 400; }
.mgrid .foldbody > table.list { margin-bottom: .5rem; }
.machine h2 .foldall { margin-left: .4rem; }
.tag.selfpill { text-decoration: none; margin-right: .4rem; }

/* the wall's latest changes: the link to a line's history on one line */
#wallev td:last-child { white-space: nowrap; }

/* a chip taken away from a pick (ctrl+click) is dimmed, as a legend's line is */
.fbtns .fb.off { opacity: .45; }
.wall .wallbar { margin: -.2rem 0 .8rem; }


.pager { display: flex; gap: 1rem; justify-content: center; padding: .4rem 0 .1rem; font-size: 12.5px; }
.pager a { color: var(--mute); text-decoration: none; border: 1px solid var(--line); border-radius: 999px; padding: .15rem .8rem; }
.pager a:hover { color: var(--ink); border-color: var(--line-2); }

/* ---- SMALL SCREENS, STRUCTURALLY. Filters that overrun their line
   wrap or scroll; charts that do not fit side by side stack. Three
   rules, at the source, so that nothing added later starts wide:
   a bar of buttons wraps, a grid child may shrink, a chart takes the
   width it is given. The page never scrolls sideways; what is wider
   than the screen — a table — scrolls inside its own box. */
.fbtns, .chips, .tranges, .foldall, .tabs, .counts, .menu, .who, .grouphead, .uhead, .headcols, .inline, form.inline, .legend, .services, .family { flex-wrap: wrap; min-width: 0; }
.top > * { min-width: 0; }
.machinegrid > *, .cards > *, .walltiles > *, .sitegrid > *, .cols > *, .grid > * { min-width: 0; }
.mchart svg, .graph, svg.graph { width: 100%; max-width: 100%; display: block; }
.tip { max-width: min(92vw, 420px); max-height: 80vh; overflow: hidden; }
.modalbox { max-width: 100%; max-height: 96vh; overflow: auto; }
body { overflow-x: hidden; }
@media (max-width: 700px) {
  .top { padding: .5rem .6rem; gap: .4rem; }
  .brand { font-size: 15px; }
  .machinegrid, .walltiles, .sitegrid, .cols, .cols.three, .grid { grid-template-columns: 1fr; }
  .cards { grid-template-columns: 1fr 1fr; }
  .modal { padding: 1.5vh .4rem; }
  .fbtns { display: flex; }
  .grouphead, h2, h3 { word-break: break-word; }
  .tape { height: 96px; }
  #tree, .tree { max-width: 100%; overflow-x: auto; }
  input, select, textarea { max-width: 100%; }
}

/* One owner's page shows its subdomains outright: the unfold caret
   would toggle nothing there. */
#tree[data-expand-kids] .caret { display: none; }

/* A picklist: tick many, find by typing. The list has real height —
   scrolling a four-line multi-select through a hundred names is not
   an interface. */
.picklist { border: 1px solid var(--edge, rgba(128,128,128,.35)); border-radius: 6px; padding: .4rem; max-width: 34rem; }
.picklist .pickfilter { width: 100%; margin-bottom: .35rem; }
.picklist .pickitems { max-height: 15rem; overflow: auto; display: flex; flex-direction: column; gap: .1rem; }
.picklist .pickitems .check { margin: 0; padding: .1rem .2rem; }
.picklist .pickcount { display: block; margin-top: .3rem; }

/* The DNS glyph: one character says where the delegation points. */
.nsico { font-size: 10px; cursor: default; }
.nsico.ok { color: var(--ok); }
.nsico.warn { color: var(--warn); }
.nsico.off { color: var(--mute); opacity: .6; }

/* The first act is clickable: the welcome panel's two forms, and the
   same pair behind "+ Add" once the page has content. */
.addpair { display: flex; gap: 1rem; flex-wrap: wrap; justify-content: center; text-align: left; margin: 1rem 0; }
.addpair form { flex: 1 1 300px; max-width: 26rem; background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: .9rem 1.1rem; display: flex; flex-direction: column; gap: .55rem; }
.addpair h3 { margin: 0; }
.addpair p { margin: 0; }
.addpair label { display: flex; flex-direction: column; gap: .25rem; font-size: 13px; color: var(--ink-2); }
.addpair input, .addpair select { width: 100%; }
.addpair button { align-self: flex-start; }
.welcome { max-width: 60rem; margin: 0 auto; }
h2 .addmenu { position: relative; display: inline-block; font-size: 13px; font-weight: normal; margin-left: .6rem; vertical-align: middle; }
h2 .addmenu .addwrap { position: absolute; left: 0; top: 100%; margin-top: .3rem; background: var(--ground); border: 1px solid var(--line); border-radius: 8px; padding: .4rem; z-index: 30; box-shadow: 0 8px 24px rgba(0,0,0,.35); width: min(56rem, 90vw); }

/* The browser's scroll anchoring fights a live page: a patched row
   destroys the anchor node and the viewport "compensates" upward,
   ~130px at a time, so the page crawls away from under the reader.
   Everything here is live — the regions, the tape, the vitals — and
   the refresher preserves scroll on its own swaps, so the browser
   must not try to help anywhere on the page. */
html { overflow-anchor: none; }

/* An ancestor shown only to give a filtered match its indentation:
   context, not a match. */
tr.site.ghosted > td { opacity: .45; }

/* The settings are a section with tabs, not a hunt through a
   dropdown. */
.settingstabs { flex-wrap: wrap; padding: .45rem max(1rem, env(safe-area-inset-left)); margin: 0; border-bottom: 1px solid var(--line); background: var(--panel); }

/* The live pill: play/pause + the cadence, everything else in the
   little menu the ▾ opens. */
.livegroup { position: relative; display: inline-flex; align-items: center; gap: 0; }
.livegroup .cadbtn { border: 1px solid var(--line); border-left: 0; background: var(--panel-2); color: var(--ink-2); padding: .25rem .55rem; border-radius: 0 999px 999px 0; cursor: pointer; font-size: 12.5px; }
.livegroup .livebtn { border-radius: 999px 0 0 999px; }
.livegroup .pop-menu { position: absolute; right: 0; top: 100%; margin-top: .3rem; background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: .6rem .8rem; display: flex; flex-direction: column; gap: .35rem; z-index: 40; white-space: nowrap; box-shadow: 0 8px 24px rgba(0,0,0,.35); }
.livegroup .pop-menu[hidden] { display: none; }
.livegroup .pop-menu .chips { display: flex; gap: .25rem; }

/* The header breathes on a phone: tighter paddings, no dead half —
   and the account chores tuck in. */
@media (max-width: 720px) {
  header.top .wrap { gap: .25rem; padding: .3rem .5rem; }
  .menu a, .menu .drop > a { padding: .3rem .5rem; }
  .who { gap: .25rem; }
  .who a.mono { display: none; }   /* the login name: the account lives under Settings anyway */
  .settingstabs { overflow-x: auto; flex-wrap: nowrap; scrollbar-width: none; }
}

/* An ultrawide screen holds the fleet in two columns: the machines
   side by side, the group titles across. The rows inside a block do
   not change, so the live patching neither knows nor cares. */
@media (min-width: 2400px) {
  #tree { display: grid; grid-template-columns: 1fr 1fr; gap: 0 1.6rem; align-items: start; }
  /* min-width:0 or the widest table blows its track past the screen;
     a table too wide for its half scrolls inside its block, the page
     never does. */
  #tree > details.hostblock { min-width: 0; overflow-x: auto; }
  /* Half a screen holds the machine's line on TWO rows: name, state,
     services, RTT and tags on the first; the vitals and the sites'
     count on the second. One 65rem row in a 1600px half spilled its
     tags out of view. */
  #tree > details.hostblock summary {
    grid-template-columns: 1.1rem minmax(11rem, 15rem) 5.2rem 7.5rem 6.5rem minmax(0, 1fr) auto;
    grid-template-areas: "caret name state svc rtt load tags" "caret vitals vitals vitals vitals vitals vitals" "caret services services services services services services";
  }
  #tree > details.hostblock summary .c-vitals { min-width: 0; }
  /* A leaf block has no table to scroll: its summary wraps, and the
     stray scrollbar under the name servers goes. */
  #tree > details.hostblock.leaf { overflow-x: visible; }
  #tree > h2.grouptitle, #tree > section, #tree > .empty, #tree > details.hostblock.span2 { grid-column: 1 / -1; }
  .alerts.timeline.scrollable { column-count: 2; column-gap: 1.6rem; }
}
/* Past the 2200px clamp, the screen is the width: dead side margins
   on an ultrawide screen are not a design. */
@media (min-width: 2300px) { main, .foot { max-width: 96vw; } }
/* A domain's DNS as of an instant: what has gone since struck through,
   what came since said under it. */
.dnsthen .gone { text-decoration: line-through; color: var(--mute); }
.dnsthen .since { color: var(--ok); }
.dnschanges tr.on td { background: color-mix(in srgb, var(--act) 12%, transparent); }
.dnsat { margin: .4rem 0 .8rem; }
.dnschanges .nowrap { white-space: nowrap; }
.dnsthen { margin-bottom: 1rem; }
