/* ===========================================================================
   MainSail Down Detector — design system

   One vocabulary. The app previously ran two: .panel/.metric-grid/.split on the
   dashboard and .card/.grid-2/.kicker everywhere else, so pages did not read as
   the same product. .card and .grid-2 are now aliases of .panel and .split
   rather than a parallel system.

   Dark only, on purpose — this gets read at 2am during an outage.
   Status is never signalled by colour alone; every state carries a glyph or a
   word as well, so it survives both colour blindness and a bad phone screen.
   =========================================================================== */

:root {
    /* surfaces */
    --bg: #0a0b0d;
    --surface: #121419;
    --surface-2: #171a21;
    --surface-3: #1d212a;
    --line: rgba(255, 255, 255, 0.085);
    --line-strong: rgba(255, 255, 255, 0.16);

    /* type */
    --text: #e7e9ec;
    --text-dim: #b3b9c3;
    --muted: #868d98;

    /* brand — sampled from the radar sweep in the logo */
    --brand: #8fe63f;
    --brand-dim: rgba(143, 230, 63, 0.14);

    /* status */
    --up: #4ade80;
    --warn: #fbbf24;
    --down: #f87171;
    --info: #7dd3fc;

    --up-bg: rgba(74, 222, 128, 0.12);
    --warn-bg: rgba(251, 191, 36, 0.12);
    --down-bg: rgba(248, 113, 113, 0.12);

    --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
    --sans: "IBM Plex Sans", "Segoe UI", system-ui, -apple-system, sans-serif;

    --radius: 14px;
    --radius-sm: 9px;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px rgba(0, 0, 0, 0.25);
}

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-family: var(--sans);
    font-size: 14px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

a { color: var(--info); text-decoration: none; }
a:hover { text-decoration: underline; }
button, input, select, textarea { font: inherit; color: inherit; }
img { max-width: 100%; display: block; }
h1, h2, h3, h4 { margin: 0; font-weight: 600; letter-spacing: -0.01em; }

/* Keyboard users get a visible ring everywhere. */
:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
    border-radius: 4px;
}

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

.mono { font-family: var(--mono); font-size: 0.92em; }
.muted, .fine, .panel-foot { color: var(--muted); font-size: 12px; }
.is-dim { opacity: 0.5; }
.tier-soft { border-color: rgba(148, 163, 184, 0.35); }
.verdict-tag { display: inline-block; padding: 0.1rem 0.5rem; border-radius: 999px; font-size: 0.78rem; white-space: nowrap; border: 1px solid rgba(148, 163, 184, 0.35); color: var(--muted, #94a3b8); }
.verdict-realoutage { border-color: rgba(248, 113, 113, 0.5); color: #fca5a5; }
.verdict-probefailure { border-color: rgba(251, 191, 36, 0.45); color: #f6dfa4; }
.verdict-selfinflicted { border-color: rgba(96, 165, 250, 0.45); color: #bfdbfe; }
.review-row > td { background: rgba(148, 163, 184, 0.06); }
.review-edit textarea, .review-edit select { width: 100%; }
.review-text { white-space: pre-wrap; margin: 0.15rem 0 0; line-height: 1.45; }
.review-read { display: grid; grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr)); gap: 0.5rem 1.5rem; font-size: 0.88rem; }
.review-label { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted, #94a3b8); }
.review-meta, .review-empty { font-size: 0.78rem; margin: 0.4rem 0 0; }
.review-row > td { padding-top: 0.25rem; padding-bottom: 0.9rem; }

/* ---------------------------------------------------------------- shell -- */

.app-shell {
    min-height: 100vh;
    display: grid;
    grid-template-columns: 244px 1fr;
}

.rail {
    background: #08090b;
    border-right: 1px solid var(--line);
    padding: 20px 14px;
    display: flex;
    flex-direction: column;
    gap: 24px;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
}

.brand { display: block; padding: 2px 6px 0; }
.brand img { width: 100%; height: auto; }
.brand-sub {
    display: block;
    margin-top: 8px;
    color: var(--muted);
    font-size: 10px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
}

.nav-section { display: flex; flex-direction: column; gap: 2px; }

.nav-kicker {
    color: var(--muted);
    font-size: 10px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    padding: 0 10px 6px;
}

.nav-link {
    display: block;
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    color: var(--text-dim);
    border-left: 2px solid transparent;
}

.nav-link:hover { background: rgba(255, 255, 255, 0.04); color: #fff; text-decoration: none; }

.nav-link.active {
    background: var(--brand-dim);
    border-left-color: var(--brand);
    color: #fff;
    font-weight: 500;
}

.rail-foot { margin-top: auto; display: flex; flex-direction: column; gap: 8px; }
.user-chip { color: var(--muted); font-size: 12px; padding: 0 10px; overflow-wrap: anywhere; }

.stage { min-width: 0; display: flex; flex-direction: column; }

.topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 14px 28px;
    border-bottom: 1px solid var(--line);
    background: rgba(10, 11, 13, 0.85);
    backdrop-filter: blur(8px);
    position: sticky;
    top: 0;
    z-index: 20;
}

.topbar .armslist-mark { height: 26px; width: auto; opacity: 0.85; }

.canvas {
    padding: 20px 28px 56px;
    display: flex;
    flex-direction: column;
    gap: 16px;
    max-width: 1500px;
    width: 100%;
}

.page-title { font-size: 20px; margin: 0; }

/* --------------------------------------------------------------- panels -- */

.panel, .card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 18px 20px;
    min-width: 0;
}

.panel-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}

.panel-label, .kicker {
    color: var(--muted);
    font-size: 11px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    font-weight: 500;
    margin: 0 0 8px;
}

.panel-head .panel-label { margin: 0; }
.panel-link { font-size: 12px; }

.metric-grid { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.split, .grid-2 { display: grid; gap: 14px; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); }
/* Full-width panels stacked vertically — for pages with a table too wide to sit
   beside anything. */
.stack { display: grid; gap: 14px; }
.form-narrow { max-width: 460px; }
.field-grid { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }

.metric {
    font-family: var(--mono);
    font-size: 32px;
    letter-spacing: -0.04em;
    line-height: 1.1;
    font-weight: 500;
}

.metric span, .metric small { font-size: 13px; color: var(--muted); margin-left: 5px; font-family: var(--sans); }
.panel.is-alarm { border-color: rgba(248, 113, 113, 0.4); }
.panel.is-alarm .metric { color: var(--down); }

/* ------------------------------------------------------------ status hero -- */

.status-hero {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 24px;
    flex-wrap: wrap;
    padding: 20px 22px;
    border-radius: var(--radius);
    border: 1px solid var(--line);
    background: var(--surface);
    position: relative;
    overflow: hidden;
}

.status-hero::before {
    content: "";
    position: absolute;
    inset: 0 auto 0 0;
    width: 3px;
    background: var(--muted);
}

.status-hero.is-up::before { background: var(--up); }
.status-hero.is-warn::before { background: var(--warn); }
.status-hero.is-down::before { background: var(--down); }

.status-kicker { color: var(--muted); font-size: 12px; letter-spacing: 0.06em; }

.status-word {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 30px;
    font-weight: 600;
    letter-spacing: -0.03em;
    margin-top: 2px;
}

/* The dot is decorative; the word beside it carries the meaning. */
.status-dot {
    width: 11px; height: 11px;
    border-radius: 50%;
    background: var(--muted);
    flex: none;
}

.status-hero.is-up .status-word { color: var(--up); }
.status-hero.is-up .status-dot { background: var(--up); box-shadow: 0 0 0 4px var(--up-bg); }
.status-hero.is-warn .status-word { color: var(--warn); }
.status-hero.is-warn .status-dot { background: var(--warn); box-shadow: 0 0 0 4px var(--warn-bg); }
.status-hero.is-down .status-word { color: var(--down); }
.status-hero.is-down .status-dot { background: var(--down); box-shadow: 0 0 0 4px var(--down-bg); animation: pulse 1.6s ease-in-out infinite; }

@keyframes pulse { 50% { box-shadow: 0 0 0 9px transparent; } }

.status-sub { margin: 6px 0 0; color: var(--muted); overflow-wrap: anywhere; }

.status-flags { display: flex; gap: 26px; margin: 0; flex-wrap: wrap; }
.status-flags div { min-width: 0; }
.status-flags dt { color: var(--muted); font-size: 10px; text-transform: uppercase; letter-spacing: 0.1em; }
.status-flags dd { margin: 2px 0 0; font-size: 14px; font-weight: 500; }

.pill {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 7px;
    border-radius: 99px;
    background: var(--surface-3);
    border: 1px solid var(--line);
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-dim);
}

/* -------------------------------------------------------------- banners -- */

.banner {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 8px;
    padding: 12px 16px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--line);
    background: var(--surface-2);
    font-size: 13px;
}

.banner::before { content: "●"; font-size: 9px; line-height: 1.6; }
.banner-warn { border-color: rgba(251, 191, 36, 0.4); background: var(--warn-bg); color: #f6dfa4; }
.banner-warn::before { content: "▲"; color: var(--warn); }
.banner-danger { border-color: rgba(248, 113, 113, 0.4); background: var(--down-bg); color: #f7c4c4; }
.banner-danger::before { content: "■"; color: var(--down); }
.banner-muted { color: var(--text-dim); }
.banner-muted::before { content: "❚❚"; font-size: 8px; color: var(--muted); }
.banner-note { color: var(--muted); }

.inline-warn {
    margin: 8px 0 0;
    padding: 8px 12px;
    border-left: 2px solid var(--warn);
    background: var(--warn-bg);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    font-size: 12px;
    color: #f6dfa4;
}

/* --------------------------------------------------------------- charts -- */

.chart { margin: 0; }
.chart-svg { width: 100%; height: auto; display: block; overflow: visible; }
.chart-empty { padding: 40px 0; text-align: center; color: var(--muted); font-size: 13px; }

.grid { stroke: rgba(255, 255, 255, 0.055); stroke-width: 1; }
.axis-line { stroke: var(--line-strong); stroke-width: 1; }
.axis { fill: var(--muted); font-size: 10px; font-family: var(--mono); }

.thr { stroke-width: 1; stroke-dasharray: 3 4; }
.thr-warn { stroke: rgba(251, 191, 36, 0.55); }
.thr-down { stroke: rgba(248, 113, 113, 0.55); }
.thr-label { font-size: 9px; letter-spacing: 0.08em; text-transform: uppercase; }
.thr-warn-t { fill: rgba(251, 191, 36, 0.8); }
.thr-down-t { fill: rgba(248, 113, 113, 0.8); }

.fault-band { fill: rgba(248, 113, 113, 0.16); }

.ser-home { fill: none; stroke: #c3cad4; stroke-width: 1.75; stroke-linejoin: round; stroke-linecap: round; }
.ser-search { fill: none; stroke: var(--brand); stroke-width: 1.75; stroke-linejoin: round; stroke-linecap: round; }
.ser-home-fill { fill: rgba(195, 202, 212, 0.07); stroke: none; }
.ser-search-fill { fill: rgba(143, 230, 63, 0.09); stroke: none; }

.chart-caption {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 10px;
    color: var(--muted);
    font-size: 11px;
}

.ser-key { width: 9px; height: 2px; border-radius: 2px; display: inline-block; }
.ser-key-home { background: #c3cad4; }
.ser-key-search { background: var(--brand); }
.chart-meta { margin-left: auto; font-family: var(--mono); }
.chart-meta-fault { color: var(--down); }

.range-tabs { display: flex; gap: 2px; background: var(--surface-2); border-radius: var(--radius-sm); padding: 2px; }

.range-tab {
    border: 0;
    background: transparent;
    color: var(--muted);
    padding: 5px 11px;
    border-radius: 7px;
    cursor: pointer;
    font-size: 12px;
}

.range-tab:hover { color: var(--text); }
.range-tab.is-active { background: var(--surface-3); color: var(--text); font-weight: 500; }

/* -------------------------------------------------------------- buttons -- */

.btn, .ghost-btn, .primary-btn, .danger-btn, .warn-btn, .login-submit, .btn-primary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--line-strong);
    background: var(--surface-2);
    color: var(--text);
    padding: 8px 14px;
    cursor: pointer;
    font-size: 13px;
    transition: background 0.12s ease, border-color 0.12s ease;
    text-decoration: none;
}

.btn:hover, .ghost-btn:hover { background: var(--surface-3); text-decoration: none; }

.btn-solid, .primary-btn, .login-submit, .btn-primary {
    background: var(--brand);
    color: #0a0b0d;
    border-color: transparent;
    font-weight: 600;
}

.btn-solid:hover, .primary-btn:hover, .login-submit:hover, .btn-primary:hover { filter: brightness(1.08); }

.btn-danger, .danger-btn { border-color: rgba(248, 113, 113, 0.45); color: #ffb4b4; background: var(--down-bg); }
.btn-danger:hover, .danger-btn:hover { background: rgba(248, 113, 113, 0.2); }
.btn-warn, .warn-btn { border-color: rgba(251, 191, 36, 0.45); color: #f3d48a; background: var(--warn-bg); }
.btn-warn:hover, .warn-btn:hover { background: rgba(251, 191, 36, 0.2); }
.btn-tiny { padding: 3px 9px; font-size: 11px; }
.btn-lg { padding: 11px 18px; font-size: 14px; }

.btn:disabled, .btn-primary:disabled, button:disabled { opacity: 0.45; cursor: not-allowed; }

.btn-row, .actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; align-items: center; }
.save-bar {
    display: flex;
    gap: 12px;
    align-items: center;
    flex-wrap: wrap;
    padding: 14px 0 0;
    position: sticky;
    bottom: 0;
    background: linear-gradient(transparent, var(--bg) 40%);
}

.desk-copy { margin: 0 0 8px; }
.toast { margin: 12px 0 0; color: var(--up); font-size: 12px; }
.toast.is-error { color: var(--down); }

.status-chip {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    padding: 3px 9px;
    border-radius: 99px;
    border: 1px solid var(--line);
}

.status-chip.is-on { color: var(--up); border-color: rgba(74, 222, 128, 0.4); background: var(--up-bg); }
.status-chip.is-off { color: var(--muted); }

/* Incident state carries a glyph as well as a colour. */
.state-tag {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    white-space: nowrap;
}

.state-tag::before { font-size: 9px; }
.state-alerting { color: var(--down); }
.state-alerting::before { content: "■"; }
.state-acknowledged { color: var(--warn); }
.state-acknowledged::before { content: "▲"; }
.state-failover { color: var(--info); }
.state-failover::before { content: "◆"; }
.state-closed { color: var(--muted); }
.state-closed::before { content: "●"; }

.test-result { font-size: 12px; }
.test-result.is-ok { color: var(--up); }
.test-result.is-bad { color: var(--down); }
.test-result.is-ok::before { content: "✓ "; }
.test-result.is-bad::before { content: "✕ "; }

/* --------------------------------------------------- ad-hoc domain check -- */

.check-bar { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; }
.check-field { flex: 1 1 320px; margin-bottom: 0; }
.check-bar .btn { flex: none; padding: 9px 18px; }

.slow-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 7px; }

.slow-list li {
    display: grid;
    grid-template-columns: 74px minmax(0, 1fr);
    gap: 10px;
    align-items: baseline;
    font-size: 12px;
}

.slow-ms { text-align: right; color: var(--warn); }
.slow-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

@media (max-width: 900px) {
    .check-bar .btn { width: 100%; }
}

/* ------------------------------------------------------------ waterfall -- */

.waterfall { display: flex; flex-direction: column; gap: 2px; max-height: 560px; overflow-y: auto; overflow-x: hidden; }

.wf-row {
    display: grid;
    grid-template-columns: 104px minmax(0, 1.1fr) minmax(80px, 1.3fr) 68px;
    gap: 10px;
    align-items: center;
    font-size: 12px;
    color: var(--text);
    width: 100%;
    text-align: left;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    padding: 6px 8px;
    cursor: pointer;
}

.wf-row:hover, .wf-row.is-open { background: rgba(255, 255, 255, 0.04); border-color: var(--line); }
.wf-row.is-slow .wf-ms { color: var(--warn); font-weight: 600; }

.wf-kind { color: var(--muted); font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wf-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wf-track { height: 7px; background: rgba(255, 255, 255, 0.05); border-radius: 99px; position: relative; }
.wf-bar { position: absolute; top: 0; height: 100%; background: #8b929c; border-radius: 99px; }
.wf-row.is-slow .wf-bar { background: var(--warn); }
.wf-ms { font-family: var(--mono); text-align: right; color: var(--muted); }

.wf-detail {
    margin: 2px 8px 8px;
    padding: 12px 14px;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: var(--surface-2);
    font-size: 13px;
}

.wf-detail p { margin: 0 0 8px; }
.wf-url { overflow-wrap: anywhere; }

/* --------------------------------------------------------------- tables -- */

.table-wrap { overflow-x: auto; margin: 0 -4px; }

/* The roster carries nine columns. Left to shrink freely it crushes the toggle
   buttons into unreadable slivers, so hold a floor and let the wrapper scroll. */
.roster-table { min-width: 900px; }
.table { width: 100%; border-collapse: collapse; }
.table th, .table td { text-align: left; padding: 9px 8px; border-bottom: 1px solid var(--line); }
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: rgba(255, 255, 255, 0.02); }

.table th {
    color: var(--muted);
    font-size: 10px;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    white-space: nowrap;
}

/* ---------------------------------------------------------------- forms -- */

.field { display: block; margin-bottom: 14px; }
.field > span { display: block; color: var(--text-dim); font-size: 12px; margin-bottom: 5px; font-weight: 500; }
.field small { display: block; color: var(--muted); font-size: 11px; margin-top: 5px; line-height: 1.45; }
.field-danger > span { color: #f3d48a; }

.checkbox { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; cursor: pointer; font-size: 13px; }
.checkbox input { width: 15px; height: 15px; accent-color: var(--brand); cursor: pointer; }

.form-control, .form-select, .field input, .field select, .field textarea,
input[type=text], input[type=password], input[type=email], input[type=number], input[type=tel], input[type=url] {
    width: 100%;
    background: #0c0e12;
    border: 1px solid var(--line-strong);
    color: var(--text);
    border-radius: var(--radius-sm);
    padding: 9px 11px;
}

.form-control:focus, .form-select:focus, .field input:focus, input:focus {
    outline: none;
    border-color: var(--brand);
    box-shadow: 0 0 0 3px var(--brand-dim);
}

input::placeholder { color: #5c636e; }

/* Bootstrap-shaped class names, kept because the scaffolded Identity pages emit
   them. Bootstrap itself is not loaded — these are dark-theme equivalents so
   those pages match the rest of the app instead of rendering unstyled. */
.form-label { display: block; color: var(--text-dim); font-size: 12px; margin-bottom: 5px; }
.form-floating { position: relative; margin-bottom: 12px; }
.form-floating > label { display: block; color: var(--muted); font-size: 12px; margin-bottom: 5px; }
.mb-3 { margin-bottom: 12px; }
.w-100 { width: 100%; }
.row { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.col-md-4, .col-xl-6, .col-md-6, .col-lg-6 { min-width: 0; }
.text-danger, .validation-message { color: var(--down); font-size: 12px; }
.validation-errors { list-style: none; padding: 0; margin: 0 0 12px; }

.alert {
    padding: 11px 14px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--line);
    background: var(--surface-2);
    font-size: 13px;
    margin-bottom: 14px;
}

.alert-danger { border-color: rgba(248, 113, 113, 0.4); background: var(--down-bg); color: #f7c4c4; }
.alert-warning { border-color: rgba(251, 191, 36, 0.4); background: var(--warn-bg); color: #f6dfa4; }
.alert-success { border-color: rgba(74, 222, 128, 0.4); background: var(--up-bg); color: #bdf0cf; }

/* Bootstrap glyphicon references in the scaffolded pages, without Bootstrap. */
.glyphicon { display: none; }

/* ---------------------------------------------------------------- login -- */

.login-shell {
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: 24px;
    background:
        radial-gradient(760px 380px at 50% -8%, rgba(143, 230, 63, 0.09), transparent 55%),
        var(--bg);
}

.login-card {
    width: min(430px, 100%);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 18px;
    padding: 30px;
    box-shadow: var(--shadow);
}

/* Sits above the form, not under the button: on a phone the bottom of a long form is off
   screen at exactly the moment something goes wrong there. */
.form-alert {
    margin: 0 0 16px;
    padding: 10px 12px;
    border: 1px solid color-mix(in srgb, var(--down) 45%, transparent);
    border-left-width: 3px;
    border-radius: 8px;
    background: color-mix(in srgb, var(--down) 10%, transparent);
    color: var(--text);
    font-size: 13px;
    line-height: 1.5;
}

/* A live checklist beats a sentence describing the rules: it says which one is still missing
   rather than making someone compare their password against a paragraph. */
.rule-list {
    list-style: none;
    margin: -8px 0 16px;
    padding: 0;
    display: grid;
    gap: 3px;
    font-size: 11px;
    color: var(--muted);
}

.rule-list li { display: flex; gap: 7px; align-items: baseline; }
.rule-list li.is-met { color: var(--up); }
.rule-list .rule-mark { width: 9px; flex: none; text-align: center; }

.login-brand { margin-bottom: 20px; }
.login-brand img { width: 240px; max-width: 100%; height: auto; }
.login-card h1 { margin: 0 0 4px; font-size: 20px; }
.login-card .lede { color: var(--muted); margin: 0 0 22px; }
.login-submit { width: 100%; padding: 11px; margin-top: 6px; }

/* ------------------------------------------------------------ speedtest -- */

/* A sonar dial rather than a spinner. A spinner says "something is happening";
   this says what is happening — a probe going out to a remote host and waiting
   for the return — and then becomes the result instead of being replaced by it.
   The sweep decelerates into a graded arc, so the wait and the answer are one
   continuous object.

   Everything below is CSS and inline SVG. Nothing here polls the server: the one
   live value is the elapsed timer, which the component pushes. */

.radar-wrap { display: grid; place-items: center; padding: 6px 0 2px; }

.radar {
    position: relative;
    width: min(268px, 74vw);
    aspect-ratio: 1;
    display: grid;
    place-items: center;

    /* Every colour in the dial derives from this, so grading the result is one
       property change rather than a sweep through a dozen rules. */
    --dial: var(--brand);
    --dial-soft: color-mix(in srgb, var(--dial) 22%, transparent);
}

.radar.is-fast { --dial: var(--up); }
.radar.is-slow { --dial: var(--warn); }
.radar.is-bad  { --dial: var(--down); }

.radar-glass {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 1px solid var(--line);
    background:
        radial-gradient(circle at 50% 38%, color-mix(in srgb, var(--dial) 9%, transparent), transparent 64%),
        var(--surface-2);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.04),
        inset 0 0 44px rgba(0, 0, 0, 0.55),
        0 20px 44px -26px rgba(0, 0, 0, 0.95);
    transition: box-shadow 600ms ease;
}

.radar.is-done .radar-glass {
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.04),
        inset 0 0 44px rgba(0, 0, 0, 0.55),
        0 0 0 1px color-mix(in srgb, var(--dial) 26%, transparent),
        0 0 46px -6px color-mix(in srgb, var(--dial) 28%, transparent);
}

/* Range rings, crosshairs and ticks. */
.radar-face { position: absolute; inset: 0; width: 100%; height: 100%; }
.radar-grid { fill: none; stroke: var(--line); stroke-width: 1; }
.radar-tick { stroke: var(--line); stroke-width: 1; }

/* The mark on the dial where the site is officially slow. Drawn from the
   configured threshold, not a decorative number. */
.radar-limit {
    stroke: color-mix(in srgb, var(--warn) 70%, transparent);
    stroke-width: 2;
    stroke-linecap: round;
}

.radar-arc {
    fill: none;
    stroke: var(--dial);
    stroke-width: 5;
    stroke-linecap: round;
    transform: rotate(-90deg);
    transform-origin: 50% 50%;
    stroke-dasharray: 100;
    stroke-dashoffset: 100;
    opacity: 0;
    filter: drop-shadow(0 0 7px color-mix(in srgb, var(--dial) 55%, transparent));
    /* Long, heavily eased: the arc should feel like it is settling on a
       measurement rather than snapping to a number. */
    transition: stroke-dashoffset 1150ms cubic-bezier(0.16, 1, 0.3, 1),
                opacity 320ms ease,
                stroke 420ms ease;
}

.radar.is-done .radar-arc { opacity: 1; }

/* The sweep: a conic gradient with a hard leading edge and a long tail, masked
   into a ring so it does not wash out the readout. */
.radar-sweep {
    position: absolute;
    inset: 5px;
    border-radius: 50%;
    background: conic-gradient(from 0deg,
        color-mix(in srgb, var(--dial) 62%, transparent) 0deg,
        color-mix(in srgb, var(--dial) 20%, transparent) 22deg,
        color-mix(in srgb, var(--dial) 5%, transparent) 62deg,
        transparent 96deg,
        transparent 360deg);
    -webkit-mask: radial-gradient(circle, transparent 33%, #000 34%);
            mask: radial-gradient(circle, transparent 33%, #000 34%);
    opacity: 0;
    transition: opacity 500ms ease;
}

.radar-arm {
    position: absolute;
    left: 50%;
    top: 5px;
    bottom: 50%;
    width: 1px;
    margin-left: -0.5px;
    background: linear-gradient(to bottom,
        color-mix(in srgb, var(--dial) 85%, transparent),
        transparent);
    opacity: 0;
    transition: opacity 500ms ease;
}

.radar.is-running .radar-sweep,
.radar.is-running .radar-arm {
    opacity: 1;
    animation: radar-spin 1900ms linear infinite;
}

/* Sonar returns. Three, staggered, so the dial has a pulse of its own rather
   than one lonely expanding circle. */
.radar-ping {
    position: absolute;
    inset: 5px;
    border-radius: 50%;
    border: 1px solid color-mix(in srgb, var(--dial) 55%, transparent);
    transform: scale(0.34);
    opacity: 0;
    pointer-events: none;
}

.radar.is-running .radar-ping { animation: radar-ping 2400ms ease-out infinite; }
.radar.is-running .radar-ping:nth-of-type(2) { animation-delay: 800ms; }
.radar.is-running .radar-ping:nth-of-type(3) { animation-delay: 1600ms; }

/* One return on arrival, so the result lands rather than appears. */
.radar.is-done .radar-echo {
    animation: radar-ping 900ms cubic-bezier(0.16, 1, 0.3, 1) 1;
}

.radar-readout {
    position: relative;
    text-align: center;
    line-height: 1.15;
    padding: 0 18%;
}

.radar-kicker {
    font-size: 10px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--muted);
    margin-bottom: 6px;
}

.radar-value {
    font-family: "IBM Plex Mono", ui-monospace, monospace;
    font-size: clamp(30px, 11vw, 44px);
    font-weight: 500;
    color: var(--text);
    font-variant-numeric: tabular-nums;
    animation: radar-rise 520ms cubic-bezier(0.16, 1, 0.3, 1) both;
}

.radar-value small {
    font-size: 0.42em;
    color: var(--muted);
    margin-left: 3px;
    letter-spacing: 0.04em;
}

.radar-grade {
    margin-top: 7px;
    font-size: 11px;
    letter-spacing: 0.13em;
    text-transform: uppercase;
    color: var(--dial);
    animation: radar-rise 520ms cubic-bezier(0.16, 1, 0.3, 1) 120ms both;
}

.radar-note { margin-top: 5px; font-size: 11px; color: var(--muted); }

@keyframes radar-spin { to { transform: rotate(360deg); } }

@keyframes radar-ping {
    0%   { transform: scale(0.34); opacity: 0.7; }
    70%  { opacity: 0.1; }
    100% { transform: scale(1); opacity: 0; }
}

@keyframes radar-rise {
    from { opacity: 0; transform: translateY(7px); }
    to   { opacity: 1; transform: none; }
}

/* Reduced motion keeps every piece of information and drops the movement. The
   sweep becomes a steady ring, so "running" is still legible without rotation. */
@media (prefers-reduced-motion: reduce) {
    .radar.is-running .radar-sweep,
    .radar.is-running .radar-arm,
    .radar.is-running .radar-ping,
    .radar.is-done .radar-echo { animation: none; }

    .radar.is-running .radar-sweep {
        background: none;
        border: 2px solid color-mix(in srgb, var(--dial) 45%, transparent);
    }

    .radar.is-running .radar-ping { opacity: 0.25; transform: scale(0.72); }
    .radar-value, .radar-grade { animation: none; }
    .radar-arc { opacity: 1; }

    .status-hero.is-down .status-dot { animation: none; }
    * { transition: none !important; }
}

/* ----------------------------------------------------------- error bar -- */

#blazor-error-ui {
    display: none;
    position: fixed;
    bottom: 0; left: 0; right: 0;
    background: #2a1214;
    color: #ffd0d0;
    padding: 12px 16px;
    z-index: 50;
    border-top: 1px solid rgba(248, 113, 113, 0.4);
}

#blazor-error-ui.show, #blazor-error-ui.components-reconnect-show { display: block; }
#blazor-error-ui .reload, #blazor-error-ui .dismiss { color: #fff; text-decoration: underline; cursor: pointer; margin-left: 10px; }

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

@media (max-width: 1180px) {
    .split, .grid-2 { grid-template-columns: minmax(0, 1fr); }
}

/* Below this the sidebar becomes a top bar. Reading this on a phone during an
   outage is the case that matters most, so it gets real attention rather than
   a single-column fallback. */
@media (max-width: 900px) {
    .app-shell { grid-template-columns: 1fr; }

    .rail {
        height: auto;
        position: static;
        flex-direction: row;
        align-items: center;
        gap: 14px;
        padding: 10px 14px;
        border-right: 0;
        border-bottom: 1px solid var(--line);
        overflow-x: auto;
    }

    .brand { flex: none; padding: 0; }
    .brand img { width: 150px; }
    .brand-sub { display: none; }
    .nav-kicker { display: none; }

    .nav-section { flex-direction: row; gap: 4px; flex: none; }

    .nav-link {
        white-space: nowrap;
        border-left: 0;
        border-bottom: 2px solid transparent;
        border-radius: var(--radius-sm) var(--radius-sm) 0 0;
        padding: 7px 11px;
    }

    .nav-link.active { border-left: 0; border-bottom-color: var(--brand); }

    .rail-foot { margin-top: 0; margin-left: auto; flex-direction: row; align-items: center; flex: none; }
    .rail-foot .nav-link { padding: 7px 10px; }
    .rail-foot form { flex: none; }
    .user-chip { white-space: nowrap; padding: 0 6px; }

    .topbar { padding: 12px 16px; position: static; }
    .canvas { padding: 16px 16px 48px; }
    .status-hero { padding: 16px; }
    .status-word { font-size: 25px; }
    .status-flags { gap: 18px; width: 100%; }
    .metric { font-size: 27px; }
    .panel, .card { padding: 15px 16px; }

    /* The waterfall's four columns cannot survive a phone width, so the timing
       bar moves to its own row beneath the name rather than being squeezed
       to nothing or forcing the page to scroll sideways. */
    .wf-row {
        grid-template-columns: 1fr auto;
        grid-template-areas:
            "name ms"
            "kind kind"
            "track track";
        gap: 4px 10px;
        padding: 8px;
        border-color: var(--line);
        margin-bottom: 2px;
    }

    .wf-name { grid-area: name; white-space: normal; overflow-wrap: anywhere; }
    .wf-kind { grid-area: kind; }
    .wf-track { grid-area: track; }
    .wf-ms { grid-area: ms; }

    .range-tabs { width: 100%; overflow-x: auto; }
    .save-bar { position: static; }
}

@media (max-width: 560px) {
    .metric-grid { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
    .status-flags { gap: 14px; }
    .login-card { padding: 22px; }
}

/* Tables never fit a phone; let them scroll inside their own panel instead of
   breaking the page layout. */
@media (max-width: 760px) {
    .panel > .table, .card > .table { display: block; overflow-x: auto; white-space: nowrap; }
}

/* -------------------------------------------------------- account pages -- */

.account-split { display: grid; gap: 14px; grid-template-columns: 210px minmax(0, 1fr); align-items: start; }
.account-nav { display: flex; flex-direction: column; gap: 2px; padding: 14px 10px; }
.account-nav .nav-kicker { padding-bottom: 8px; }

/* The scaffolded Identity pages emit bare h2/h3 headings with no classes. */
.account-split article h2,
.account-split article h3 { font-size: 15px; margin: 0 0 4px; }
.account-split article h4 { font-size: 13px; color: var(--muted); margin: 0 0 12px; font-weight: 500; }
.account-split article form { max-width: 460px; }
.account-split article hr { border: 0; border-top: 1px solid var(--line); margin: 14px 0; }

@media (max-width: 900px) {
    .account-split { grid-template-columns: minmax(0, 1fr); }
    .account-nav { flex-direction: row; flex-wrap: wrap; }
    .account-nav .nav-kicker { display: none; }
}

/* ------------------------------------------------------ prompt editor -- */

.prompt-editor { margin-top: 14px; border-top: 1px solid var(--line); padding-top: 12px; }

.prompt-editor > summary {
    cursor: pointer;
    color: var(--text-dim);
    font-size: 12px;
    list-style: none;
    user-select: none;
}

.prompt-editor > summary::-webkit-details-marker { display: none; }
.prompt-editor > summary::before { content: "▸ "; color: var(--muted); }
.prompt-editor[open] > summary::before { content: "▾ "; }
.prompt-editor > summary:hover { color: var(--text); }

/* Monospaced and line-wrapped off: the script is laid out in numbered steps whose
   indentation carries meaning, and reflowing it makes the structure unreadable. */
.prompt-text {
    font-family: var(--mono) !important;
    font-size: 12px !important;
    line-height: 1.5;
    white-space: pre;
    overflow-wrap: normal;
    overflow-x: auto;
}

.placeholder-list { margin: 6px 0 0; padding-left: 18px; }
.placeholder-list li { margin-bottom: 3px; }

/* ------------------------------------------------------------ invites -- */

.invite-panel { border-color: var(--brand); margin-bottom: 14px; }
.invite-link-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

.invite-link {
    flex: 1 1 380px;
    font-family: var(--mono);
    font-size: 12px;
    /* Anyone holding this link can set that account's password, so it reads as a secret
       rather than as ordinary body text. */
    background: var(--surface-2) !important;
}

/* -------------------------------------------------------- inline edits -- */

/* A cell that is also the control for editing it. Looks like text until hovered,
   so the table stays readable rather than becoming a wall of input boxes. */
.link-cell {
    background: none;
    border: 0;
    padding: 0;
    font: inherit;
    color: inherit;
    cursor: pointer;
    text-align: left;
    border-bottom: 1px dotted transparent;
}

.link-cell:hover { color: var(--brand); border-bottom-color: var(--brand); }

.cell-input {
    width: 100%;
    min-width: 110px;
    padding: 3px 6px !important;
    font-size: 12px !important;
}

/* ---------------------------------------------------------- dns switch -- */

/* Reads as a physical switch rather than a button, because its resting position is
   information: which side it sits on is what customers are currently seeing. */
/* The DNS control is a labelled button plus a confirmation, not a toggle. A switch whose
   label reads "Production" cannot say whether that is the current state or the one it is
   about to move to, and this is the one control in the application with a customer on the
   other end of it. */

.confirm-panel {
    margin-top: 14px;
    padding: 14px 16px;
    border: 1px solid color-mix(in srgb, var(--warn) 42%, transparent);
    border-left-width: 3px;
    border-radius: var(--radius-sm);
    background: color-mix(in srgb, var(--warn) 7%, var(--surface-2));
}

.confirm-lede {
    margin: 0 0 6px;
    font-size: 14px;
    font-weight: 600;
    color: var(--text);
}

.confirm-panel .muted { margin: 0 0 12px; font-size: 12.5px; line-height: 1.55; }
.confirm-panel .btn-row { margin: 0; }

/* The status read-out turns amber when visitors are not seeing the real site, so the one
   abnormal state on the page is the one that draws the eye. */
.status-flags dd.is-maintenance-now { color: var(--warn); font-weight: 600; }

/* A value the application reads rather than owns. Sized and spaced like an input so it lines
   up with the editable fields beside it, but plainly not one - no border, no box. */
.readonly-value {
    margin: 0;
    padding: 8px 0 7px;
    min-height: 34px;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 8px;
    font-family: var(--mono);
    font-size: 13px;
}

.readonly-value .muted { font-family: var(--sans); font-size: 11px; }
.readonly-value .is-bad { color: var(--down); font-family: var(--sans); font-size: 12px; }

.link-btn {
    background: none;
    border: 0;
    padding: 0;
    color: var(--info);
    font-size: inherit;
    cursor: pointer;
    text-decoration: underline;
}

.link-btn:disabled { color: var(--muted); cursor: wait; text-decoration: none; }

/* ----------------------------------------------------------- fault log -- */

.fault-log { margin-top: 14px; border-top: 1px solid var(--line); padding-top: 10px; }

.fault-log > summary {
    cursor: pointer;
    color: var(--text-dim);
    font-size: 12px;
    list-style: none;
    user-select: none;
}

.fault-log > summary::-webkit-details-marker { display: none; }
.fault-log > summary::before { content: "▸ "; color: var(--muted); }
.fault-log[open] > summary::before { content: "▾ "; }
.fault-log > summary:hover { color: var(--text); }

.fault-table { margin-top: 8px; font-size: 12px; }
.fault-table th, .fault-table td { padding: 6px 8px; vertical-align: top; }
.fault-reason { color: var(--text-dim); overflow-wrap: anywhere; }

.fault-tag {
    display: inline-block;
    padding: 1px 7px;
    border-radius: 999px;
    font-size: 10px;
    letter-spacing: 0.04em;
    white-space: nowrap;
    border: 1px solid var(--line-strong);
}

/* Red counted against uptime; amber did not. The distinction is the whole point of
   separating probe faults from site faults, so it has to survive into the UI. */
.fault-tag.is-site { color: var(--down); border-color: rgba(248, 113, 113, 0.4); }
.fault-tag.is-probe { color: var(--warn); border-color: rgba(243, 212, 138, 0.35); }

/* -------------------------------------------------------- voice preview -- */

.voice-preview {
    width: 100%;
    max-width: 320px;
    height: 34px;
    margin-top: 8px;
    /* The native player is light-on-light in most browsers; this keeps it legible
       on a dark panel without rebuilding the control. */
    filter: invert(0.92) hue-rotate(180deg);
    border-radius: var(--radius-sm);
}

/* ------------------------------------------------------------ phone PIN -- */

.pin-edit { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.pin-edit input { width: 110px; font-family: var(--mono); letter-spacing: 0.2em; }

/* ------------------------------------------------------ severity tiers -- */

.tier-note {
    margin: 16px 0 10px;
    padding: 8px 12px;
    border-left: 2px solid var(--line-strong);
    background: var(--surface-2);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    font-size: 12px;
    color: var(--text-dim);
}

.tier-note strong { color: var(--text); }
.tier-warn { border-left-color: var(--warn); }
.tier-down { border-left-color: var(--down); }

.alert-toggles { display: flex; gap: 3px; flex-wrap: wrap; }
.alert-toggles .btn-tiny { padding: 2px 7px; font-size: 10px; }

.table-scroll { overflow-x: auto; }
