/* ============================================================================
 * Manager console stylesheet — loads after base.css.
 *
 * Currently: the login flow (two-step, split layout) and the interim index
 * placeholder. Console shell (sidebar / tables / drawers) joins this file as
 * those pages are built.
 * ========================================================================== */

/* ---- Login: split layout ------------------------------------------------- */

.login-shell {
    position: fixed;
    inset: 0;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
}

.login-brand {
    background: #0c0d0e;
    border-right: 1px solid #1f2024;
    padding: 48px 52px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
}

.login-logo { display: flex; align-items: center; gap: 11px; }

.login-logo .mark {
    display: inline-flex;
    width: 24px;
    height: 24px;
    border-radius: 7px;
    background: #828fff;
    align-items: center;
    justify-content: center;
    flex: none;
}

.login-logo .name { font-size: 16px; letter-spacing: -0.02em; font-weight: 600; }
.login-logo .name span { color: #8a8f98; font-weight: 400; }

.login-eyebrow {
    font-family: 'Geist Mono', monospace;
    font-size: 12px;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: #828fff;
}

.login-brand h1 {
    font-size: 30px;
    font-weight: 600;
    letter-spacing: -0.03em;
    line-height: 1.15;
    margin: 16px 0 0;
    max-width: 380px;
}

.login-features { margin-top: 30px; display: flex; flex-direction: column; gap: 16px; max-width: 400px; }

.login-feature { display: flex; gap: 12px; }
.login-feature svg { color: #828fff; flex: none; margin-top: 2px; }
.login-feature .t { font-size: 14px; font-weight: 500; }
.login-feature .d { font-size: 13px; color: #8a8f98; line-height: 1.5; }

.login-version { font-family: 'Geist Mono', monospace; font-size: 11px; color: #3a3c42; }

.login-side { display: grid; place-items: center; padding: 32px; }

.login-card { width: 100%; max-width: 352px; }

.login-card h2 { font-size: 22px; font-weight: 600; letter-spacing: -0.02em; margin: 0; }

.login-sub { font-size: 13.5px; color: #8a8f98; margin: 8px 0 0; line-height: 1.5; }
.login-sub .who { color: #f7f8f8; font-family: 'Geist Mono', monospace; }

.login-form { margin-top: 26px; display: flex; flex-direction: column; gap: 16px; }

/* ---- Form controls ------------------------------------------------------- */

.field label { display: block; font-size: 12.5px; color: #8a8f98; margin-bottom: 7px; }

.field input {
    width: 100%;
    height: 38px;
    background: #0c0d0e;
    border: 1px solid #2a2b30;
    border-radius: 8px;
    padding: 0 12px;
    color: #f7f8f8;
    font-size: 13.5px;
    font-family: inherit;
    outline: none;
    transition: border-color .12s, box-shadow .12s;
}

.field input:focus { border-color: #828fff; box-shadow: 0 0 0 3px rgba(130, 143, 255, .14); }

.remember { display: flex; align-items: center; gap: 9px; font-size: 13px; color: #8a8f98; cursor: pointer; user-select: none; }

/* Custom checkbox: pure CSS check (no data: URI images — img-src is 'self') */
.remember input {
    appearance: none;
    width: 16px;
    height: 16px;
    border-radius: 5px;
    border: 1px solid #34343a;
    background: #0c0d0e;
    margin: 0;
    cursor: pointer;
    position: relative;
    transition: background .12s, border-color .12s;
}

.remember input:checked { background: #7170ff; border-color: #7170ff; }

.remember input:checked::after {
    content: "";
    position: absolute;
    left: 4.5px;
    top: 1.5px;
    width: 4px;
    height: 8px;
    border: solid #ffffff;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}

.login-primary {
    width: 100%;
    height: 38px;
    background: #7170ff;
    color: #ffffff;
    border: none;
    border-radius: 8px;
    font-size: 13.5px;
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
    margin-top: 2px;
    transition: background .12s, opacity .12s;
}

.login-primary:hover { background: #7f7eff; }
.login-primary[disabled] { opacity: .55; cursor: default; }
.login-primary[disabled]:hover { background: #7170ff; }

/* ---- Alerts / notes ------------------------------------------------------ */

.login-alert {
    display: flex;
    gap: 9px;
    background: rgba(235, 87, 87, .10);
    border: 1px solid rgba(235, 87, 87, .28);
    border-radius: 7px;
    padding: 9px 11px;
    font-size: 12.5px;
    color: #eb5757;
    line-height: 1.5;
}

.login-alert svg { flex: none; margin-top: 1px; }

.login-alert[hidden] { display: none; }

.login-note { display: flex; align-items: center; gap: 8px; margin-top: 22px; font-size: 12px; color: #4d5157; }

/* ---- Step 2 (TOTP) ------------------------------------------------------- */

.login-back {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: transparent;
    border: none;
    color: #8a8f98;
    font-size: 13px;
    font-family: inherit;
    cursor: pointer;
    padding: 0;
    margin-bottom: 20px;
    transition: color .12s;
}

.login-back:hover { color: #f7f8f8; }

.code-input {
    width: 100%;
    height: 52px;
    margin-top: 24px;
    background: #0c0d0e;
    border: 1px solid #2a2b30;
    border-radius: 8px;
    text-align: center;
    letter-spacing: .5em;
    font-family: 'Geist Mono', monospace;
    font-size: 22px;
    color: #f7f8f8;
    outline: none;
    transition: border-color .12s, box-shadow .12s;
}

.code-input:focus { border-color: #828fff; box-shadow: 0 0 0 3px rgba(130, 143, 255, .14); }

.login-alt { text-align: center; margin-top: 18px; }

.login-alt a { font-size: 12.5px; color: #8a8f98; text-decoration: none; transition: color .12s; }
.login-alt a:hover { color: #828fff; }

/* ---- Interim index placeholder ------------------------------------------- */

.stub-shell { min-height: 100vh; display: grid; place-items: center; padding: 32px; }

.stub-card {
    width: 100%;
    max-width: 420px;
    border: 1px solid #1f2024;
    border-radius: 14px;
    background: #0f1011;
    padding: 32px;
    text-align: center;
}

.stub-card .mark {
    display: inline-flex;
    width: 40px;
    height: 40px;
    border-radius: 11px;
    background: #828fff;
    align-items: center;
    justify-content: center;
}

.stub-card h1 { font-size: 19px; font-weight: 600; letter-spacing: -0.02em; margin: 18px 0 0; }

.stub-card p { font-size: 13.5px; color: #8a8f98; line-height: 1.6; margin: 10px 0 0; }

.stub-card .who { color: #f7f8f8; font-family: 'Geist Mono', monospace; font-size: 13px; }

.stub-card form { margin-top: 22px; }

.btn-ghost {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    height: 36px;
    padding: 0 16px;
    background: transparent;
    border: 1px solid #2a2b30;
    border-radius: 8px;
    color: #d0d6e0;
    font-size: 13px;
    font-family: inherit;
    cursor: pointer;
    transition: border-color .12s, color .12s;
}

.btn-ghost:hover { border-color: #34343a; color: #f7f8f8; }

/* ---- Segmented code input (canvas 01 · 2FA frame) ------------------------ */

.code-cells { display: flex; gap: 9px; margin-top: 26px; }

.code-cells input {
    flex: 1;
    min-width: 0;
    height: 52px;
    background: #0c0d0e;
    border: 1px solid #2a2b30;
    border-radius: 8px;
    text-align: center;
    font-family: 'Geist Mono', monospace;
    font-size: 21px;
    color: #f7f8f8;
    outline: none;
    caret-color: #828fff;
    transition: border-color .12s, box-shadow .12s;
}

.code-cells input:focus { border-color: #828fff; box-shadow: 0 0 0 3px rgba(130, 143, 255, .14); }

.code-cells.invalid input { border-color: rgba(235, 87, 87, .55); }

/* ---- First-login enrollment (QR + setup key, canvas 12 · 2FA flow) ------- */

.totp-setup { display: flex; gap: 16px; align-items: flex-start; margin-top: 22px; }

.totp-setup[hidden] { display: none; }

.totp-setup .qr {
    width: 116px;
    height: 116px;
    flex: none;
    border-radius: 8px;
    background: #f7f8f8;
    padding: 8px;
}

.totp-setup .qr svg { display: block; width: 100%; height: 100%; }

.totp-setup .setup-side { display: flex; flex-direction: column; gap: 9px; min-width: 0; }

.totp-setup .setup-note { font-size: 12.5px; color: #8a8f98; line-height: 1.6; }

.setup-key {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    border-radius: 6px;
    background: #0f1011;
    border: 1px solid #2a2b30;
}

.setup-key .key {
    font-family: 'Geist Mono', monospace;
    font-size: 12px;
    color: #f7f8f8;
    letter-spacing: .06em;
    word-break: break-all;
}

.setup-key button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    flex: none;
    border-radius: 5px;
    border: 1px solid #2a2b30;
    background: #1c1c1f;
    color: #8a8f98;
    cursor: pointer;
    transition: color .12s, border-color .12s;
}

.setup-key button:hover { color: #f7f8f8; border-color: #34343a; }

.setup-hint { font-family: 'Geist Mono', monospace; font-size: 11px; color: #4d5157; }

/* Spacing for the two standalone step forms (no .login-form flex gap there) */

#totp-form .login-alert, #step-recovery .login-alert { margin-top: 16px; }

#totp-form .login-primary { margin-top: 20px; }

#recovery-form .login-primary { margin-top: 22px; }

/* ---- Login footer row (back + recovery toggle) --------------------------- */

.login-footer { display: flex; align-items: center; justify-content: space-between; margin-top: 18px; }

.login-footer a { font-size: 12.5px; color: #8a8f98; text-decoration: none; transition: color .12s; }

.login-footer a:hover { color: #a3adff; }

/* ---- Error page state (icon + copy inside the login card) ---------------- */

.auth-state { display: flex; flex-direction: column; gap: 14px; }
.auth-state .state-icon {
    width: 40px; height: 40px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    background: var(--accent-soft); color: var(--accent);
}
.auth-state .state-icon.warn { background: rgba(242, 153, 74, .12); color: #f2994a; }
.auth-state p { margin: 0; font-size: 13.5px; line-height: 1.6; color: #b4b8c0; }

/* ---- Recovery-code frame (shown once after first-login enrollment) ------- */

.recovery-code {
    margin-top: 22px;
    padding: 14px 16px;
    border-radius: 8px;
    background: #0f1011;
    border: 1px solid #2a2b30;
    text-align: center;
    font-family: 'Geist Mono', monospace;
    font-size: 16px;
    letter-spacing: .08em;
    color: #f7f8f8;
    user-select: all;
}

/* ---- Responsive ----------------------------------------------------------- */

@media (max-width: 880px) {
    .login-shell { grid-template-columns: 1fr; }
    .login-brand { display: none; }
}

/* ============================================================================
 * Console shell + shared components (Wave A foundation).
 *
 * Design tokens (docs/html/design_handoff · README) live as CSS variables so
 * every surface reads one source; shell, tables, drawer, modal, dropdown and
 * toast are all driven off them. No inline styles anywhere — the CSP forbids
 * them — so state is toggled by class only.
 * ========================================================================== */

:root {
    /* Surfaces */
    --bg: #08090a;
    --surface: #0f1011;
    --surface-raised: #141516;
    --surface-sunk: #0c0d0e;
    --hairline: #1f2024;
    --hairline-strong: #2a2b30;
    --row-hover: rgba(255, 255, 255, .025);

    /* Text */
    --text: #f7f8f8;
    --text-high: #f7f8f8;
    --text-body: #d0d6e0;
    --text-muted: #8a8f98;
    --text-faint: #62666d;

    /* Accent + status hues */
    --accent: #828fff;
    --accent-solid: #7170ff;
    --green: #6dc78b;
    --accent-hover: #a3adff;
    --accent-deep: #12122b;
    --accent-soft: rgba(130, 143, 255, .12);
    --accent-ring: rgba(130, 143, 255, .14);
    --light: #E5E5E6;
    --blue: #5ea0ef;
    --violet: #b59cff;
    --amber: #cea34a;
    --orange: #F5A97F;
    --danger: #eb5757;
    --danger-solid: #eb5757;
    --grey: #9A9A9A;

    /* Geometry */
    --sidebar-w: 224px;
    --topbar-h: 46px;
    --content-max: 1320px;
    --radius-card: 8px;
    --radius-control: 8px;
    --radius-modal: 10px;

    /* Shadow */
    --shadow-modal: 0 30px 80px rgba(0, 0, 0, .6);
    --shadow-drawer: -24px 0 70px rgba(0, 0, 0, .55);
    --shadow-toast: 0 16px 40px rgba(0, 0, 0, .5);

    --mono: 'Geist Mono', monospace;
}

/* ---- Shell layout -------------------------------------------------------- */

.console { display: grid; grid-template-columns: var(--sidebar-w) minmax(0, 1fr); height: 100vh; overflow: hidden; }

.sidebar {
    height: 100vh;
    background: var(--surface-sunk);
    border-right: 1px solid var(--hairline);
    display: flex;
    flex-direction: column;
    padding: 18px 14px 14px;
}

.sidebar-logo { display: flex; align-items: center; gap: 10px; padding: 4px 8px 20px; }

.sidebar-logo .mark {
    display: inline-flex;
    width: 22px;
    height: 22px;
    border-radius: 7px;
    background: var(--accent);
    align-items: center;
    justify-content: center;
    flex: none;
}

.sidebar-logo .name { font-size: 15px; font-weight: 600; letter-spacing: -0.02em; }
.sidebar-logo .name span { color: var(--text-muted); font-weight: 400; }

/* The environment badge rides the wordmark (NicoSoft AI · dev): tiny,
   accent-tinted, lowercase-mono — version-badge voice, not a control */
.sidebar-logo .env-badge {
    flex: none;
    font-family: var(--mono);
    font-size: 10px;
    letter-spacing: .08em;
    line-height: 1;
    text-transform: uppercase;
    color: var(--accent);
    background: color-mix(in srgb, var(--accent) 13%, transparent);
    border-radius: 5px;
    padding: 3px 6px;
    margin-top: 1px;
}

.nav { display: flex; flex-direction: column; gap: 2px; overflow-y: auto; flex: 1; }

.nav-group { margin-top: 16px; }
.nav-group:first-child { margin-top: 4px; }

.nav-label {
    font-family: var(--mono);
    font-size: 10.5px;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--text-faint);
    padding: 0 8px 6px;
}

.nav-item {
    display: flex;
    align-items: center;
    gap: 10px;
    height: 34px;
    padding: 0 10px;
    border-radius: 8px;
    color: var(--text-body);
    font-size: 13.5px;
    text-decoration: none;
    position: relative;
    transition: background .12s, color .12s;
}

.nav-item svg { flex: none; color: var(--text-faint); transition: color .12s; }
.nav-item:hover { background: rgba(255, 255, 255, .04); color: var(--text-high); }
.nav-item:hover svg { color: var(--text-muted); }

.nav-item.active { background: #1f2024; color: var(--text); }
.nav-item.active svg { color: var(--accent); }

.nav-item.active::before {
    content: "";
    position: absolute;
    left: -14px;
    top: 7px;
    bottom: 7px;
    width: 2px;
    background: var(--accent);
    border-radius: 0 2px 2px 0;
}

.sidebar-account {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 12px;
    padding: 10px 8px;
    border-top: 1px solid var(--hairline);
    text-decoration: none;
    color: inherit;
    border-radius: 8px;
    transition: background .12s;
}

.sidebar-account:hover { background: rgba(255, 255, 255, .04); }

.sidebar-account .avatar {
    width: 30px;
    height: 30px;
    border-radius: 8px;
    background: var(--surface-raised);
    border: 1px solid var(--hairline-strong);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 11.5px;
    font-weight: 600;
    color: var(--text-high);
    flex: none;
    text-transform: uppercase;
}

.sidebar-account .who { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.sidebar-account .who .n { font-size: 13px; color: var(--text-high); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sidebar-account .who .e { font-size: 11.5px; color: var(--text-faint); font-family: var(--mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.main { min-width: 0; height: 100vh; display: flex; flex-direction: column; background: var(--surface); }

.topbar {
    flex: none;
    height: var(--topbar-h);
    border-bottom: 1px solid var(--hairline);
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 0 24px;
    background: var(--surface);
}

.topbar h1 { font-size: 15px; font-weight: 600; letter-spacing: -0.01em; margin: 0; }
.topbar-right { display: flex; align-items: center; gap: 14px; margin-left: auto; }
/* Page-mounted topbar actions wear the design's 30px control height — one
   rule, so every button up here is the same size by construction */
.topbar-tools { display: flex; align-items: center; gap: 8px; }
.topbar-tools .btn { height: 30px; padding: 0 12px; font-size: 12.5px; }

.topbar-meta { font-family: var(--mono); font-size: 11.5px; color: var(--text-faint); }

.content { flex: 1; min-height: 0; overflow-y: auto; padding: 26px max(28px, calc((100% - var(--content-max)) / 2)) 60px; }
.content-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 20px; }
.content-head h1 { font-size: 21px; font-weight: 600; letter-spacing: -0.02em; margin: 0; }
.content-head p { font-size: 13.5px; color: var(--text-muted); margin: 6px 0 0; line-height: 1.5; max-width: 640px; }

/* ---- Summary cards ------------------------------------------------------- */

.summary { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; margin-bottom: 18px; }
/* hidden must win over the grid display (the [hidden] pit) — Logs carries one
   summary row per tab and swaps them, so both would show at once without it */
.summary[hidden] { display: none; }
.stat-card { background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--radius-card); padding: 15px 16px; }
.stat-card .k { font-family: var(--mono); font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--text-faint); }
.stat-card .v { font-family: var(--mono); font-size: 22px; font-weight: 600; letter-spacing: -0.02em; margin-top: 10px; color: var(--text); }
.stat-card .d { font-family: var(--mono); font-size: 11.5px; margin-top: 5px; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

@media (max-width: 820px) { .summary { grid-template-columns: repeat(2, 1fr); } }

/* ---- Buttons ------------------------------------------------------------- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    height: 36px;
    padding: 0 15px;
    border-radius: var(--radius-control);
    font-size: 13px;
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
    border: 1px solid transparent;
    white-space: nowrap;
    /* An action that navigates is an <a class="btn">; without this it keeps the
       user agent's underline and reads as a link wearing a button */
    text-decoration: none;
    transition: background .12s, border-color .12s, color .12s, box-shadow .12s, opacity .12s;
}

.btn svg { flex: none; }
.btn[disabled] { opacity: .5; cursor: default; }

.btn-primary { background: var(--accent-solid); color: #ffffff; font-weight: 500; }
.btn-primary:not([disabled]):hover { background: #7f7eff; }

/* Light solid button for a page-level create action (Add rule / Add chain …).
   Named -lighted, not -light: .btn-light is the login page's full-width
   (width:100%) submit button, a different component. */
.btn-lighted { background: var(--light); color: #08090a; font-weight: 600; }
.btn-lighted:not([disabled]):hover { background: #FFFFFF; box-shadow: 0 2px 12px rgba(0, 0, 0, .45); }

.btn-outline { background: transparent; border-color: var(--hairline-strong); color: var(--text-body); }
.btn-outline:not([disabled]):hover { border-color: #34343a; color: var(--text); }

.btn-danger { background: transparent; border-color: rgba(235, 87, 87, .4); color: var(--danger); }
.btn-danger:not([disabled]):hover { background: rgba(235, 87, 87, .1); border-color: rgba(235, 87, 87, .6); }

/* Outline info button — the non-destructive "check / re-verify" drawer action */
.btn-info { background: transparent; border-color: rgba(94, 160, 239, .4); color: var(--blue); }
.btn-info:not([disabled]):hover { background: rgba(94, 160, 239, .1); border-color: rgba(94, 160, 239, .6); }

.btn-sm { height: 30px; padding: 0 11px; font-size: 12px; }

/* ---- Status pills (README badge palette) --------------------------------- */

.pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-family: var(--mono);
    font-size: 11px;
    font-weight: 500;
    padding: 3px 8px;
    border-radius: 6px;
    text-transform: lowercase;
    white-space: nowrap;
    border: 1px solid transparent;
}

.pill::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; flex: none; }

/* The dot marks a live state (enabled / error / revoked). A classification —
   a protocol, an endpoint, an error kind — wears the same box without it, so
   the two never read as the same kind of fact. `tag()` in cell.js adds this. */
.pill-nodot::before { display: none; }

.pill-green  { color: var(--green); background: rgba(109, 199, 139, .12); border-color: rgba(109, 199, 139, .28); }
.pill-violet { color: var(--violet); background: rgba(181, 156, 255, .12); border-color: rgba(181, 156, 255, .28); }
.pill-blue   { color: var(--blue); background: rgba(94, 160, 239, .12); border-color: rgba(94, 160, 239, .28); }
.pill-amber  { color: var(--amber); background: rgba(206, 163, 74, .12); border-color: rgba(206, 163, 74, .28); }
.pill-orange { color: var(--orange); background: rgba(245, 169, 127, .12); border-color: rgba(245, 169, 127, .28); }
.pill-red    { color: var(--danger); background: rgba(235, 87, 87, .12); border-color: rgba(235, 87, 87, .3); }
.pill-grey   { color: var(--grey); background: rgba(255, 255, 255, .05); border-color: rgba(255, 255, 255, .15); }
/* Outline is not a status colour: it labels a category (protocol, provider,
   endpoint, credit channel) and must stay visually below the tinted pills. */
.pill-outline { color: var(--text-muted); background: transparent; border-color: var(--hairline-strong); }

/* ---- Filter toolbar ------------------------------------------------------ */

.toolbar { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-bottom: 1px solid #1f2024; flex-wrap: wrap; }
/* Tab-switched toolbars (Events) hide via the attribute */
.toolbar[hidden] { display: none; }

.search { position: relative; flex: 1; min-width: 200px; }
.search > svg { position: absolute; left: 11px; top: 50%; transform: translateY(-50%); color: var(--text-faint); pointer-events: none; }
.search input {
    width: 100%;
    height: 34px;
    background: var(--surface-sunk);
    border: 1px solid rgba(255, 255, 255, .12);
    border-radius: 8px;
    padding: 0 11px 0 32px;
    color: var(--text-high);
    font-size: 12.5px;
    font-family: inherit;
    outline: none;
    transition: border-color .12s;
}
.search input::placeholder { color: var(--text-faint); }
.search input:focus { border-color: var(--accent); }

/* ---- Table --------------------------------------------------------------- */

.panel { background: var(--surface); border: 1px solid #1f2024; border-radius: var(--radius-card); overflow: hidden; }

.table-scroll { overflow-x: auto; }
.table { width: 100%; border-collapse: collapse; }
/* Column-dense tables keep a floor width and scroll horizontally under it */
.table.wide { min-width: 820px; }

.table th {
    text-align: left;
    font-family: var(--mono);
    font-size: 10.5px;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--text-faint);
    padding: 11px 14px;
    white-space: nowrap;
}

.table th.num, .table td.num { text-align: right; }

.table td {
    padding: 12px 14px;
    font-size: 12.5px;
    color: var(--text-body);
    border-top: 1px solid rgba(255, 255, 255, .05);
    vertical-align: middle;
    /* Content stays whole: wide tables scroll sideways (.table-scroll), so a
       cell never truncates or wraps — two-line cells use block children,
       which nowrap does not affect */
    white-space: nowrap;
}
.table tbody tr.clickable { cursor: pointer; transition: background .1s; }
.table tbody tr.clickable:hover { background: var(--row-hover); }

.table .mono { font-family: var(--mono); }
.table .strong { color: var(--text-high); }
.table .accent { color: var(--accent); }
/* Muted cell — a placeholder value (e.g. a Wave C runtime metric not yet wired) */
.table .faint { color: var(--text-faint); }
/* A bare value the row's severity should still colour (an HTTP status) */
.table .tone-red { color: var(--danger); }
.table .tone-amber { color: var(--amber); }
/* Fixed-format cells (timestamps) must never wrap mid-value */
.table .nowrap { white-space: nowrap; }
.cell-two { display: flex; flex-direction: column; gap: 2px; }
.cell-two .sub { font-size: 11px; color: var(--text-faint); font-family: var(--mono); }
/* A pill is sized by its label. As a flex child it stretches to the column and
   reads as a bar — but only align-self, never align-items on the container:
   the numeric two-line cells rely on stretch to keep their text right-aligned */
.cell-two > .pill { align-self: flex-start; }
/* Inline cell: label + trailing pill, vertically centred */
.cell-inline { display: flex; align-items: center; gap: 8px; }
/* Request-id cell: truncated id + inline copy affordance */
.reqid { display: inline-flex; align-items: center; gap: 6px; }

/* ---- Empty state --------------------------------------------------------- */

.empty { padding: 56px 24px; text-align: center; }
.empty svg { color: var(--text-faint); opacity: .6; margin-bottom: 12px; }
.empty .t { font-size: 13.5px; color: var(--text-high); }
.empty .d { font-size: 12.5px; color: var(--text-muted); margin-top: 4px; }

/* ---- Load failure -------------------------------------------------------- */

/* Where a fetch failed, said in the space its data was going to fill, with the
   retry beside it. Persistent on purpose: a toast outlives nothing, and the
   void it leaves behind reads as "loaded, and empty". */
.load-fallback { padding: 34px 24px; text-align: center; }
.load-fallback .t { font-size: 13px; color: var(--text-high); }
.load-fallback .d { font-size: 12.5px; color: var(--text-muted); line-height: 1.45; margin-top: 4px; }
.load-fallback .btn-ghost { height: 30px; padding: 0 14px; margin-top: 14px; font-size: 12.5px; }
/* Centred in the attention panel, like the all-clear state beside it */
.attn-list .load-fallback { margin: auto 0; }
/* One message across the chain grid, not one squeezed into its first column */
.chain-grid .load-fallback { grid-column: 1 / -1; }
/* The row flavour brings its own padding */
.table .load-fallback-row td { padding: 0; }

/* ---- Pagination ---------------------------------------------------------- */

.pagination { display: flex; align-items: center; justify-content: space-between; padding: 11px 16px; border-top: 1px solid #1f2024; flex-wrap: wrap; gap: 10px; }
/* Author display beats the UA hidden rule — the pair is mandatory on any
   component class that carries display (the recurring [hidden] pit) */
.pagination[hidden] { display: none; }
.pagination .range { font-size: 12px; color: #7A7A7A; }
.pagination .pager { display: flex; align-items: center; gap: 6px; }
.pagination .page-ind { font-size: 12px; color: var(--text-body); font-variant-numeric: tabular-nums; padding: 0 6px; min-width: 48px; text-align: center; }

/* ---- Overlay-based surfaces: drawer, modal ------------------------------- */

.overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, .5);
    z-index: 100;
    animation: overlay-in .2s ease;
}

@keyframes overlay-in { from { opacity: 0; } to { opacity: 1; } }

/* Detail drawer — 462px right slide-in */
.drawer {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: 462px;
    max-width: 92vw;
    background: var(--surface);
    border-left: 1px solid var(--hairline-strong);
    box-shadow: var(--shadow-drawer);
    z-index: 101;
    display: flex;
    flex-direction: column;
    animation: drawer-in .26s cubic-bezier(.4, 0, .2, 1);
}

@keyframes drawer-in { from { transform: translateX(100%); } to { transform: translateX(0); } }

.drawer-head { padding: 20px 22px 16px; border-bottom: 1px solid var(--hairline); }
.drawer-head .title-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.drawer-head h3 { font-size: 17px; font-weight: 600; letter-spacing: -0.01em; margin: 0; }
.drawer-head .sub { font-size: 12.5px; color: var(--text-muted); margin: 5px 0 0; font-family: var(--mono); }
.drawer-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.drawer-tag { font-family: var(--mono); font-size: 11px; color: var(--text-muted); background: var(--surface-sunk); border: 1px solid var(--hairline); border-radius: 6px; padding: 3px 8px; }

.drawer-body { padding: 6px 22px 20px; overflow-y: auto; flex: 1; }

.drawer-section { padding: 16px 0; border-bottom: 1px solid var(--hairline); }
.drawer-section:last-child { border-bottom: none; }
.drawer-section.framed { background: var(--surface-sunk); border: 1px solid var(--hairline); border-radius: 8px; padding: 14px 16px; margin: 14px 0; }
.section-title { font-family: var(--mono); font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--text-faint); margin-bottom: 12px; }

/* The webhook payload the integrator received, indented by the page for
   reading. `pre`, never `pre-wrap`: the indentation is the structure, and
   rewrapping a long string value mid-line would read as a line break that is
   not in the data. A line too long for the box scrolls the box, not the drawer
   around it */
.payload { max-height: 280px; overflow: auto; margin: 0; padding: 12px 14px; white-space: pre;
    background: var(--surface-sunk); border: 1px solid var(--hairline); border-radius: 8px;
    font-family: var(--mono); font-size: 11.5px; line-height: 1.6; color: var(--text-body); }

.kv { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; padding: 6px 0; }
.kv .k { font-size: 12.5px; color: var(--text-muted); flex: none; }
.kv .v { font-size: 12.5px; color: var(--text-high); text-align: right; word-break: break-word; }
.kv .v.mono { font-family: var(--mono); }
/* Health tone on a metric value (WS health, lag, price-feed staleness) */
.kv .v.tone-green { color: var(--accent); }
.kv .v.tone-amber { color: var(--amber); }
.kv .v.tone-red { color: var(--danger); }
.kv .v.tone-blue { color: var(--blue); }
.kv .v.tone-violet { color: var(--violet); }

/* Two equal columns, so buttons align into rows instead of wrapping ragged at
   their label widths. .wide spans the row — for an action deliberately set
   apart from the pairs (the primary, the destructive one), and for a lone
   trailing button that would otherwise sit half-width. */
.drawer-actions { padding: 16px 22px; border-top: 1px solid var(--hairline); display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.drawer-actions .wide { grid-column: 1 / -1; }

/* Trailing drawer callout (e.g. append-only notice) */
.drawer-note { display: flex; gap: 9px; margin-top: 10px; padding: 11px 13px; font-size: 12px; line-height: 1.5; color: var(--text-muted); background: var(--surface-sunk); border: 1px solid var(--hairline); border-radius: 8px; }
.drawer-note svg { color: var(--text-faint); flex: none; margin-top: 1px; }

/* Centered modal — 412px (confirm / form / 2FA) */
.modal {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 412px;
    max-width: 94vw;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
    background: var(--surface-raised);
    border: 1px solid var(--hairline-strong);
    border-radius: var(--radius-modal);
    box-shadow: var(--shadow-modal);
    /* Above the drawer pair (101): dialogs opened from a drawer (Adjust
       credit, Revoke) must dim it, not hide behind it */
    z-index: 111;
    animation: modal-in .2s ease;
}

/* The modal's own backdrop outranks the drawer for the same reason; the
   shared .overlay class is told apart by what follows it */
.overlay:has(+ .modal) { z-index: 110; }

@keyframes modal-in { from { opacity: 0; transform: translate(-50%, -46%) scale(.98); } to { opacity: 1; transform: translate(-50%, -50%) scale(1); } }

.modal-head { padding: 20px 22px 0; flex: none; }
.modal-head h3 { font-size: 16px; font-weight: 600; letter-spacing: -0.01em; margin: 0; }
.modal-body { padding: 12px 22px 4px; font-size: 13px; color: var(--text-body); line-height: 1.55; overflow-y: auto; min-height: 0; }
.modal-body .field { margin-top: 14px; }
.modal-actions { padding: 18px 22px 20px; display: flex; justify-content: flex-end; gap: 9px; flex: none; }

.modal-body label { display: block; font-size: 12.5px; color: var(--text-body); margin-bottom: 7px; }
.modal-body input, .modal-body textarea {
    width: 100%;
    background: var(--surface-sunk);
    border: 1px solid var(--hairline-strong);
    border-radius: var(--radius-control);
    padding: 9px 12px;
    color: var(--text-high);
    font-size: 13.5px;
    font-family: inherit;
    outline: none;
    transition: border-color .12s, box-shadow .12s;
}
.modal-body textarea { resize: vertical; min-height: 72px; }
.modal-body input:focus, .modal-body textarea:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-ring); }

.warn-note {
    display: flex;
    gap: 9px;
    background: rgba(235, 87, 87, .09);
    border: 1px solid rgba(235, 87, 87, .3);
    border-radius: 8px;
    padding: 11px 12px;
    font-size: 12.5px;
    color: var(--orange);
    line-height: 1.5;
    margin-top: 14px;
}
.warn-note svg { flex: none; margin-top: 1px; }

/* Settings edit modal extras */
.modal-body .modal-sub { font-size: 12px; color: var(--text-muted); margin: 6px 0 14px; }
.modal-body input.mono { font-family: var(--mono); font-size: 13px; }
.modal-note { display: flex; align-items: center; gap: 8px; margin-top: 14px; font-size: 12px; color: var(--text-muted); }
.modal-note .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--amber); flex: none; }
.modal-error { margin-top: 12px; font-size: 12px; color: var(--danger); }

/* ---- Wide detail modal --------------------------------------------------- */
/* Wider than the compact 412px confirm/form base — the frame the trace and
   lifecycle views share. .modal-fixed pins the height too, for a body whose
   content streams in: the frame opens at its final size and never grows step by
   step. Views whose content is known up front (the lifecycle) omit it and let
   the modal size to what it holds. Both scroll inside on short viewports
   (max-height: 90vh is inherited from .modal). */
.modal-wide { width: 34rem; }
.modal-fixed { height: 64rem; }
.modal-fixed .modal-body { flex: 1; }

.modal-headrow { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; }
.modal-headsub { font-family: var(--mono); font-size: 11px; color: var(--text-faint); margin-top: 6px; line-height: 1.5; }
.modal-headsub.break { word-break: break-all; }

.modal-statepill { flex: none; display: inline-flex; align-items: center; font-size: 12px; font-weight: 600; border-radius: 20px; padding: 5px 12px; border: 1px solid transparent; white-space: nowrap; }
.modal-statepill.tone-grey { color: var(--grey); background: rgba(255, 255, 255, .05); border-color: var(--hairline-strong); }
.modal-statepill.tone-green { color: var(--accent); background: rgba(130, 143, 255, .12); border-color: rgba(130, 143, 255, .28); }
.modal-statepill.tone-red { color: var(--danger); background: rgba(235, 87, 87, .12); border-color: rgba(235, 87, 87, .3); }
.modal-statepill.tone-amber { color: var(--amber); background: rgba(206, 163, 74, .12); border-color: rgba(206, 163, 74, .28); }
.modal-statepill.tone-violet { color: var(--violet); background: rgba(181, 156, 255, .12); border-color: rgba(181, 156, 255, .28); }
.modal-statepill.tone-blue { color: var(--blue); background: rgba(94, 160, 239, .12); border-color: rgba(94, 160, 239, .28); }
.modal-statepill.tone-outline { color: var(--text-muted); background: transparent; border-color: var(--hairline-strong); }

.rv-note { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--text-muted); padding: 4px 0 2px; }
.rv-note svg { color: var(--text-faint); flex: none; }

.rv-section { padding: 16px 0 2px; border-top: 1px solid var(--hairline); margin-top: 14px; }
.rv-section:first-of-type { border-top: none; margin-top: 6px; }

/* ---- Timeline ------------------------------------------------------------ */
/* The shared vertical event rail: a dot on a hairline spine, a time + tag head,
   then title, detail and supporting lines. Two views render into it — the
   re-verify trace (steps arriving live, time = elapsed) and the order lifecycle
   (events reconstructed from the ledger, time = clock + offset) — so the shape
   is defined once here and once in components/timeline.js. */
.tl { margin: 14px 0 4px 5px; border-left: 1px solid var(--hairline-strong); padding-left: 22px; }
.tl-event { position: relative; padding-bottom: 18px; }
.tl-event:last-child { padding-bottom: 2px; }
.tl-dot { position: absolute; left: -28px; top: 2px; width: 9px; height: 9px; border-radius: 50%; background: var(--text-faint); box-shadow: 0 0 0 4px var(--surface-raised); }
.tl-dot.violet { background: var(--violet); }
.tl-dot.green { background: var(--accent); box-shadow: 0 0 0 4px var(--surface-raised), 0 0 8px rgba(130, 143, 255, .55); }
.tl-dot.red { background: var(--danger); box-shadow: 0 0 0 4px var(--surface-raised), 0 0 8px rgba(235, 87, 87, .5); }
.tl-dot.amber { background: var(--amber); box-shadow: 0 0 0 4px var(--surface-raised); }
/* Transport phases (connect / headers / idle / total) — never reached the
   upstream at all, which is a different failure from one it answered with */
.tl-dot.orange { background: var(--orange); box-shadow: 0 0 0 4px var(--surface-raised); }
.tl-head { display: flex; align-items: center; gap: 12px; }
.tl-time { font-family: var(--mono); font-size: 11px; color: var(--text-faint); min-width: 58px; display: inline-flex; align-items: baseline; gap: 7px; }
.tl-offset { color: var(--text-muted); }
.tl-tag { font-family: var(--mono); font-size: 10.5px; color: var(--text-muted); border: 1px solid var(--hairline-strong); border-radius: 7px; padding: 2px 8px; white-space: nowrap; }
.tl-tag.violet { color: var(--violet); border-color: rgba(181, 156, 255, .32); background: rgba(181, 156, 255, .08); }
.tl-tag.green { color: var(--accent); border-color: rgba(130, 143, 255, .32); background: rgba(130, 143, 255, .08); }
.tl-tag.red { color: var(--danger); border-color: rgba(235, 87, 87, .32); background: rgba(235, 87, 87, .08); }
.tl-tag.amber { color: var(--amber); border-color: rgba(206, 163, 74, .32); background: rgba(206, 163, 74, .08); }
.tl-tag.orange { color: var(--orange); border-color: rgba(245, 169, 127, .32); background: rgba(245, 169, 127, .08); }
.tl-title { font-size: 13.5px; font-weight: 500; color: var(--text-high); margin-top: 8px; }
.tl-detail { font-family: var(--mono); font-size: 11.5px; color: var(--text-muted); margin-top: 3px; line-height: 1.55; word-break: break-word; }
.tl-sub { font-family: var(--mono); font-size: 11px; color: var(--text-faint); margin-top: 4px; line-height: 1.5; word-break: break-word; }

/* A step the order has not reached: drawn hollow and dimmed, so an in-flight
   order shows what it is still waiting for without claiming it happened. */
.tl-event.upcoming .tl-dot { background: transparent; border: 1px solid var(--hairline-strong); }
.tl-event.upcoming .tl-title { color: var(--text-muted); font-weight: 400; }
.tl-event.upcoming .tl-detail, .tl-event.upcoming .tl-tag { color: var(--text-faint); }

/* A moment computed rather than recorded — a batch passing the stuck threshold
   is broadcast_at plus a config value, not an event anything wrote down. The
   dot keeps its tone but becomes a ring: a scanner reads dots, not the sub-line
   that explains it. The title stays full strength, because the moment is real
   even though the record is not. Only the amber tone is spelled out because
   only the stuck threshold is derived; another one would be one line. */
.tl-event.derived .tl-dot { background: transparent; border: 1px solid var(--hairline-strong); }
.tl-event.derived .tl-dot.amber { border-color: var(--amber); }

/* The webhook an event triggered, inline under it */
.tl-web { display: inline-flex; align-items: center; gap: 7px; margin-top: 7px; padding: 4px 9px; font-family: var(--mono); font-size: 10.5px; color: var(--text-muted); background: var(--surface-sunk); border: 1px solid var(--hairline); border-radius: 7px; }
.tl-web svg { color: var(--text-faint); flex: none; }
.tl-web .ok { color: var(--accent); }
.tl-web .bad { color: var(--danger); }

/* On-chain vs registry table */
.rv-cmp { width: 100%; border-collapse: collapse; margin-top: 6px; }
.rv-cmp th { text-align: left; font-family: var(--mono); font-size: 9.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--text-faint); font-weight: 400; padding: 0 12px 9px 0; }
.rv-cmp th:last-child { padding-right: 0; }
.rv-cmp td { padding: 9px 12px 9px 0; font-size: 12.5px; border-top: 1px solid var(--hairline); vertical-align: middle; }
.rv-cfield { color: var(--text-muted); }
.rv-con, .rv-creg { font-family: var(--mono); color: var(--text-high); }
.rv-con.faint, .rv-creg.faint { color: var(--text-faint); }
.rv-con.diff { color: var(--danger); }
.rv-cmark { text-align: right; padding-right: 0; width: 24px; }
.rv-cmark .rv-ok { color: var(--accent); }
.rv-cmark .rv-bad { color: var(--danger); }
.rv-none { color: var(--text-faint); }

/* Verdict banner */
.rv-verdict { display: flex; gap: 11px; align-items: flex-start; margin-top: 14px; padding: 12px 14px; border-radius: 11px; border: 1px solid transparent; }
.rv-vic { flex: none; width: 22px; height: 22px; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin-top: 1px; }
.rv-vt { font-size: 13.5px; font-weight: 600; }
.rv-vd { font-size: 12.5px; color: var(--text-body); margin-top: 3px; line-height: 1.55; }
.rv-v-ok { background: rgba(130, 143, 255, .08); border-color: rgba(130, 143, 255, .24); }
.rv-v-ok .rv-vic { background: rgba(130, 143, 255, .16); color: var(--accent); }
.rv-v-ok .rv-vt { color: var(--accent); }
.rv-v-bad { background: rgba(235, 87, 87, .08); border-color: rgba(235, 87, 87, .26); }
.rv-v-bad .rv-vic { background: rgba(235, 87, 87, .16); color: var(--danger); }
.rv-v-bad .rv-vt { color: var(--danger); }
.rv-v-warn { background: rgba(206, 163, 74, .08); border-color: rgba(206, 163, 74, .26); }
.rv-v-warn .rv-vic { background: rgba(206, 163, 74, .16); color: var(--amber); }
.rv-v-warn .rv-vt { color: var(--amber); }

/* ---- Settings page ------------------------------------------------------- */

/* Snapshot card: a stat-card like every other page's, deliberately not one of
   the settings group cards below — what it reports is not a setting but whether
   the settings below are the ones actually in force. State and action sit
   bottom-right, the corner the eye lands on last after reading the numbers. */
/* Rides in the same column flow as the group cards, so it is one column wide by
   construction and the groups pack around it instead of leaving the right half
   empty beside it. Kept visually a stat-card, because what it reports is not a
   setting but whether the settings below are the ones actually in force. */
.snapshot-card { break-inside: avoid; margin-bottom: 14px; }
.snapshot-card.drifted { border-color: rgba(235, 87, 87, .35); background: rgba(235, 87, 87, .04); }
.snapshot-card .d .sep { margin: 0 7px; opacity: .45; }
.snapshot-card .d .hi { color: var(--text-body); }
.snapshot-note { margin: 11px 0 0; font-size: 11.5px; line-height: 1.6; color: var(--text-faint); }
.snapshot-actions { display: flex; align-items: center; justify-content: flex-end; gap: 8px; margin-top: 14px; }
/* Matches btn-sm's box exactly — a pill and a button side by side read as one
   control strip only if they share a baseline and a height */
.snapshot-actions .pill { height: 30px; padding: 0 11px; box-sizing: border-box; border-radius: var(--radius-control); }
.snapshot-drift { margin-top: 9px; font-size: 11.5px; color: var(--danger); }
.snapshot-drift .keys { display: block; margin-top: 4px; color: var(--text-body); overflow-wrap: anywhere; }

/* ---- Settings page (hot-config editor) ---------------------------------- */

.settings-note { font-size: 12px; color: var(--text-muted); margin-bottom: 16px; line-height: 1.5; }

/* Reload cadence in the topbar, next to the breadcrumb */
.settings-reload { font-family: var(--mono); font-size: 11.5px; color: var(--text-faint); }

/* Masonry via CSS columns: the groups are wildly uneven (1 row vs 20), so a
   row-aligned grid stretches short cards and strands a tall one beside an empty
   half. Columns pack each card to its content and balance the two heights. */
.settings-grid { columns: 2; column-gap: 14px; }
@media (max-width: 900px) { .settings-grid { columns: 1; } }

.settings-card { background: var(--surface); border: 1px solid var(--hairline-strong); border-radius: var(--radius-card); overflow: hidden; break-inside: avoid; margin-bottom: 14px; }

/* The whole head toggles the card; the chevron turns as it opens */
.settings-card-head { display: flex; align-items: center; gap: 11px; width: 100%; text-align: left; padding: 13px 16px; border: none; background: transparent; cursor: pointer; transition: background .1s; }
.settings-card-head:hover { background: rgba(255, 255, 255, .02); }
.settings-chevron { flex: none; color: var(--text-faint); transition: transform .15s; }
.settings-card:not(.collapsed) .settings-chevron { transform: rotate(90deg); }
.settings-card-head .t { font-size: 13px; font-weight: 600; color: var(--text-high); }
.settings-card-head .p { font-size: 11px; color: var(--text-faint); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.settings-card-head .n { margin-left: auto; flex: none; font-size: 11px; color: var(--text-faint); }
.settings-card-head .n .dot { color: var(--accent); }

.settings-body { border-top: 1px solid var(--hairline); }
.settings-card.collapsed .settings-body { display: none; }
.settings-rows { display: flex; flex-direction: column; }
.settings-foot { display: flex; justify-content: flex-end; padding: 11px 16px; border-top: 1px solid var(--hairline); }

.setting-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; padding: 12px 16px; border-top: 1px solid rgba(255, 255, 255, .04); }
.setting-row:first-child { border-top: none; }
/* Differs from its code default — the violet tint the design calls for */
.setting-row.changed { background: var(--accent-soft); }
/* Long comma-lists take the full row width: key on top, textarea below */
.setting-row.long { flex-direction: column; gap: 8px; }

.setting-label { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; padding-top: 6px; }
.setting-row.long .setting-label { padding-top: 0; }
.setting-key { font-family: var(--mono); font-size: 12px; color: var(--text-body); overflow-wrap: anywhere; }
.setting-desc { font-size: 11.5px; color: var(--text-faint); line-height: 1.45; }

.setting-control { display: flex; align-items: center; gap: 8px; flex: none; }
.setting-row.long .setting-control { align-self: stretch; }

.setting-input { height: 32px; padding: 0 10px; background: var(--surface-sunk); border: 1px solid var(--hairline-strong); border-radius: var(--radius-control); color: var(--text-body); font-size: 12.5px; font-family: inherit; width: 240px; }
.setting-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-ring); }
.setting-num { width: 130px; text-align: right; font-family: var(--mono); }
.setting-textarea { flex: 1; width: 100%; height: auto; padding: 8px 10px; font-family: var(--mono); font-size: 12px; line-height: 1.5; resize: vertical; white-space: pre-wrap; word-break: break-word; }

.setting-check { flex: none; align-self: center; }
.setting-check .check-label { min-width: 22px; }

.setting-reset { flex: none; }
.setting-def { font-size: 11px; color: var(--text-faint); }

/* ---- Account page -------------------------------------------------------- */

.account { max-width: 720px; }

.account-card { background: var(--surface); border: 1px solid var(--hairline-strong); border-radius: var(--radius-card); padding: 20px; }
.account-card + .account-card { margin-top: 14px; }

.profile-head { display: flex; align-items: center; gap: 14px; }
.profile-head .avatar {
    width: 48px;
    height: 48px;
    flex: none;
    border-radius: 12px;
    background: var(--surface-raised);
    border: 1px solid var(--hairline-strong);
    display: grid;
    place-items: center;
    font-family: var(--mono);
    font-size: 15px;
    font-weight: 600;
    color: var(--text-high);
    text-transform: uppercase;
}
.profile-id { min-width: 0; }
.profile-id .name { font-size: 16px; font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.profile-id .sub { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
.session-pill { margin-left: auto; flex: none; }

.profile-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px 24px; margin-top: 20px; border-top: 1px solid var(--hairline); padding-top: 16px; }
.profile-grid .k { font-size: 11.5px; color: var(--text-faint); }
.profile-grid .v { font-size: 13px; color: var(--text-body); margin-top: 3px; overflow-wrap: anywhere; }

/* Security rows card: tighter vertical padding, the rows own their spacing */
.account-card.sec-list { padding: 6px 20px; }
.sec-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 16px 0; border-top: 1px solid var(--hairline); }
.sec-row:first-child { border-top: none; }
.sec-info { min-width: 0; }
.sec-info .t { font-size: 13.5px; font-weight: 500; color: var(--text-high); display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.sec-info .d { font-size: 12px; color: var(--text-muted); margin-top: 3px; line-height: 1.5; }
.sec-btns { display: flex; gap: 8px; flex: none; }

/* Two-factor enroll modal: QR + manual key side by side → verify → shown-once code */
.account-2fa { max-width: 34rem; }
.tf-step { font-size: 12px; font-weight: 600; color: var(--text-high); margin: 16px 0 10px; }
.tf-step:first-child { margin-top: 2px; }
.tfa-setup { display: flex; gap: 16px; align-items: center; margin: 4px 0; }
.tfa-qr {
    width: 128px;
    height: 128px;
    flex: none;
    border-radius: 10px;
    border: 1px solid var(--hairline-strong);
    background: #FFFFFF;
    padding: 8px;
}
.tfa-qr svg { width: 100%; height: 100%; display: block; }
.tfa-key { min-width: 0; }
.tfa-key .k { font-size: 11.5px; color: var(--text-faint); margin-bottom: 6px; }
.tfa-key .val { font-family: var(--mono); font-size: 14px; letter-spacing: .06em; color: var(--text-high); word-break: break-all; }
.tfa-key .hint { font-size: 11.5px; color: var(--text-faint); margin-top: 9px; line-height: 1.45; }

.tf-code { text-align: center; font-family: var(--mono); font-size: 18px; letter-spacing: .3em; }
.tf-hint { font-size: 11.5px; line-height: 1.5; margin-top: 4px; }

.recovery-box { background: var(--surface-sunk); border: 1px solid var(--accent-ring); border-radius: 8px; padding: 14px; margin: 12px 0; }
.recovery-box .k { font-size: 11px; color: var(--accent); margin-bottom: 8px; }
.recovery-box .val { font-family: var(--mono); font-size: 17px; letter-spacing: .05em; color: var(--text-high); text-align: center; word-break: break-all; }
.recovery-tools { display: flex; gap: 8px; justify-content: center; margin-top: 12px; }

/* A monospaced 6-digit code input (2FA), spaced for legibility */
.modal-body input.code { font-family: var(--mono); letter-spacing: .2em; }

/* ---- IP blocklist page --------------------------------------------------- */

/* Inline mono span inside body copy (e.g. /manager · /v1) */
.mono-inline { font-family: var(--mono); color: var(--text-body); }
/* Reason column: cap width, let long reasons wrap rather than stretch the table */
.table td.clamp { max-width: 260px; }
/* An expiry dropdown used as a full-width form control inside a modal */
.modal-body .field .dd-trigger { width: 100%; justify-content: space-between; margin-top: 0; }

/* ---- Custom dropdown (portaled popover) ---------------------------------- */

.dd-trigger {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    height: 34px;
    padding: 0 11px;
    background: var(--surface-sunk);
    border: 1px solid rgba(255, 255, 255, .12);
    border-radius: 8px;
    color: var(--text-body);
    font-size: 12.5px;
    font-family: inherit;
    cursor: pointer;
    white-space: nowrap;
    transition: border-color .12s, color .12s;
}

.dd-trigger:hover { border-color: rgba(255, 255, 255, .26); color: var(--text-high); }
/* Inline-block so a scripted min-width (widest-option lock) holds and the label
   left-aligns instead of the trigger resizing with the selection */
/* Left-align inside the (min-width) box: the trigger is a <button>, whose
   default text-align: center would otherwise centre a short value */
.dd-value { display: inline-block; text-align: left; }
.dd-trigger svg { color: var(--text-faint); flex: none; opacity: .6; }

.dd-menu {
    position: fixed;
    z-index: 200;
    max-height: 300px;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: #161616;
    border: 1px solid #2a2b30;
    border-radius: 8px;
    box-shadow: 0 16px 44px rgba(0, 0, 0, .55);
    animation: pop-in .13s ease;
}

/* The scrolling half of the menu — the search row above it stays pinned */
.dd-list { overflow-y: auto; min-height: 0; padding: 5px; }

.dd-search { flex: none; padding: 6px; border-bottom: 1px solid #26272c; }

.dd-search input {
    width: 100%;
    height: 28px;
    padding: 0 9px;
    border-radius: 6px;
    border: 1px solid #2a2b30;
    background: #0f1011;
    color: var(--text);
    font-size: 12.5px;
    outline: none;
}

.dd-search input:focus { border-color: #3a3b44; }

/* hidden must win over the option's flex display (the [hidden] pit) */
.dd-option[hidden] { display: none; }

.dd-empty { padding: 8px 10px; font-size: 12.5px; color: var(--text-faint); }

@keyframes pop-in {
    from { opacity: 0; transform: translateY(6px) scale(.98); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}

.dd-option {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 8px 10px;
    border-radius: 7px;
    font-size: 13px;
    color: var(--text-body);
    cursor: pointer;
    /* Never wrap: the menu sizes to its widest label (dropdown.js sets a
       min-width and lets the content decide the rest) */
    white-space: nowrap;
}

/* Only engages when a label is long enough that the menu hit the viewport cap;
   min-width:0 is what lets a flex item shrink below its own content at all */
.dd-option .dd-label { overflow: hidden; text-overflow: ellipsis; min-width: 0; }

.dd-option:hover { background: #1f2024; color: var(--text); }
.dd-option .tick { color: var(--accent); opacity: 0; }
.dd-option.selected .tick { opacity: 1; }
.dd-option.selected { color: var(--text-high); }

/* Custom checkbox — the login page's pure-CSS check (appearance:none, no
   native platform chrome, no data: URIs), sized for dialog forms */
.check-row { display: flex; gap: 14px; flex-wrap: wrap; }

/* label.check, not .check: .modal-body label sets display:block at equal
   file-order-beats-it specificity — the element tag keeps this one ahead */
label.check {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin-bottom: 0;
    font-size: 12.5px;
    color: var(--text-body);
    cursor: pointer;
    user-select: none;
}

/* padding:0 matters: the .modal-body input blanket pads 9px 12px, which
   would inflate the 16px box into a pill (the same blanket-rule pollution
   as label's display:block) */
.check input {
    appearance: none;
    width: 16px;
    height: 16px;
    padding: 0;
    flex: none;
    border-radius: 5px;
    border: 1px solid var(--hairline-strong);
    background: #0c0d0e;
    margin: 0;
    cursor: pointer;
    position: relative;
    transition: background .12s, border-color .12s;
}

.check input:checked { background: var(--accent-solid); border-color: var(--accent-solid); }

.check input:checked::after {
    content: "";
    position: absolute;
    left: 4.5px;
    top: 1.5px;
    width: 4px;
    height: 8px;
    border: solid #ffffff;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}

.check-label { white-space: nowrap; }

/* ---- Toast --------------------------------------------------------------- */

.toast-wrap { position: fixed; right: 22px; bottom: 22px; z-index: 300; display: flex; flex-direction: column; gap: 10px; }

.toast {
    display: flex;
    align-items: center;
    gap: 10px;
    background: var(--surface-raised);
    border: 1px solid var(--hairline-strong);
    border-radius: 8px;
    box-shadow: var(--shadow-toast);
    padding: 12px 15px;
    font-size: 13px;
    color: var(--text-high);
    animation: toast-in .22s ease;
}

.toast .dot { width: 7px; height: 7px; border-radius: 50%; flex: none; background: var(--accent); }
.toast.danger .dot { background: var(--danger); }
.toast.info .dot { background: var(--blue); }

@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }

/* Copy affordance on drawer values / cells */
.copy-btn { background: none; border: none; color: var(--text-faint); cursor: pointer; padding: 2px; display: inline-flex; transition: color .12s; }
.copy-btn:hover { color: var(--accent); }

/* Solid confirm tones (tinted confirm button) + drawer close + demo layout */
.btn-danger-solid { background: var(--danger-solid); color: #FFFFFF; font-weight: 600; }
.btn-danger-solid:not([disabled]):hover { background: #E5352F; }
.btn-info-solid { background: var(--blue); color: var(--accent-deep); font-weight: 600; }
.btn-info-solid:not([disabled]):hover { background: #A5E0FD; }

.drawer-head .title-row { align-items: flex-start; }
.drawer-head .title-right { display: flex; align-items: center; gap: 10px; flex: none; }
.drawer-close {
    background: none;
    border: none;
    color: var(--text-faint);
    cursor: pointer;
    padding: 3px;
    display: inline-flex;
    border-radius: 6px;
    transition: color .12s, background .12s;
}
.drawer-close:hover { color: var(--text-high); background: #1f2024; }

.demo-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; flex: none; }
.signout-row { margin-top: 22px; }

/* ---- Dashboard ----------------------------------------------------------- */

/* Range toggle. Buttons, not links: the choice re-reads a payload rather than
   navigating, and the page must stay where the reader left it */
.range-toggle { display: flex; gap: 2px; flex: none; background: var(--surface); border: 1px solid var(--hairline-strong); border-radius: var(--radius-control); padding: 3px; }
.range-opt { appearance: none; background: transparent; border: none; font: inherit; font-size: 12.5px; color: var(--text-muted); padding: 5px 12px; border-radius: 6px; cursor: pointer; transition: color .12s, background .12s; }
.range-opt:hover { color: var(--text-high); }
.range-opt.on { background: var(--text); color: var(--bg); font-weight: 500; }

.dash-grid { display: grid; grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr); gap: 14px; }

/* The card detail line takes a tone only where rising is good news —
   settlement. Nothing else on this page colours a direction */
.stat-card .d.tone-green { color: var(--accent); }

/* ---- Dashboard · settlement chart ---------------------------------------- */

.chart-card { padding: 18px 18px 14px; }
.chart-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.chart-title { font-size: 13.5px; font-weight: 600; color: var(--text-high); }
.chart-sub { font-size: 12px; color: var(--text-faint); margin-top: 3px; }

/* The plot box: the SVG fills it, and the hover overlay is positioned over it by
   percentage. overflow is visible so an edge dot or the tooltip can sit a few px
   into the card's padding rather than being clipped at the frame. */
.chart-plot { position: relative; margin-top: 16px; overflow: visible; }
.chart-svg { display: block; width: 100%; height: 190px; }
.chart-grid { stroke: rgba(255, 255, 255, .05); stroke-width: 1; }

/* Hover overlay — HTML over the SVG, so text and dots stay true under the SVG's
   non-uniform scale. pointer-events pass through to the plot underneath. */
.chart-layer { position: absolute; inset: 0; pointer-events: none; }
.chart-cross { position: absolute; top: 0; bottom: 14px; width: 1px; background: var(--hairline-strong); transform: translateX(-0.5px); }
.chart-dot { position: absolute; width: 9px; height: 9px; border-radius: 50%; transform: translate(-50%, -50%); box-shadow: 0 0 0 2px var(--surface); }
.chart-sw { width: 10px; height: 2px; border-radius: 1px; flex: none; }

.chart-tip { position: absolute; top: 4px; z-index: 2; pointer-events: none; transform: translateX(12px); }
.chart-tip.flip { transform: translateX(calc(-100% - 12px)); }
.chart-tip-card { min-width: 194px; padding: 8px 10px; background: #1c1c1f; border: 1px solid var(--hairline-strong); border-radius: 8px; box-shadow: 0 8px 22px rgba(0, 0, 0, .4); }
.chart-tip-h { font-size: 11.5px; font-weight: 600; color: var(--text-high); margin-bottom: 6px; }
.chart-tip-row { display: flex; align-items: center; gap: 7px; font-size: 11.5px; line-height: 1.75; }
.chart-tip-nm { color: var(--text-muted); }
.chart-tip-val { margin-left: auto; font-family: var(--mono); color: var(--text-high); font-variant-numeric: tabular-nums; }

.chart-axis { display: flex; justify-content: space-between; margin-top: 8px; font-family: var(--mono); font-size: 10.5px; color: #4d5157; }

.chart-legend { display: flex; justify-content: center; gap: 22px; margin-top: 12px; }
.chart-leg-item { display: inline-flex; align-items: center; gap: 7px; font-size: 12px; color: var(--text-muted); }
.chart-leg-name { color: var(--text-high); font-weight: 500; }
.chart-leg-val { font-family: var(--mono); color: var(--text-high); font-variant-numeric: tabular-nums; }

/* ---- Dashboard · needs attention ----------------------------------------- */

.attn-card { display: flex; flex-direction: column; padding: 16px 18px; }
.attn-list { display: flex; flex-direction: column; flex: 1; gap: 8px; margin-top: 14px; }
.attn-item { display: flex; gap: 11px; padding: 10px 11px; border: 1px solid var(--hairline); border-radius: 8px; text-decoration: none; transition: background .12s, border-color .12s; }
.attn-item:hover { background: var(--row-hover); border-color: var(--hairline-strong); }
.attn-dot { width: 8px; height: 8px; flex: none; margin-top: 5px; border-radius: 50%; background: var(--grey); }
.attn-dot.tone-red { background: var(--danger); }
.attn-dot.tone-amber { background: var(--amber); }
.attn-text { min-width: 0; }
.attn-t { font-size: 13px; font-weight: 500; color: var(--text-high); }
.attn-d { font-size: 12px; color: var(--text-muted); line-height: 1.45; margin-top: 2px; }
/* Centred, because this panel is as tall as the chart beside it and a good-news
   message pinned to the top of all that space reads as content that failed to
   arrive */
.attn-clear { margin: auto 0; padding: 22px 4px; font-size: 12.5px; color: var(--text-muted); line-height: 1.45; }
.attn-clear-t { font-size: 13px; color: var(--text-high); }
.attn-clear-d { margin-top: 4px; }

/* ---- Dashboard · chain health -------------------------------------------- */

.section-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 26px 0 12px; }
.section-link { font-size: 12.5px; color: var(--text-muted); text-decoration: none; transition: color .12s; }
.section-link:hover { color: var(--accent); }

.chain-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
.chain-card { background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--radius-card); padding: 15px 16px; }
.chain-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
/* One line, always. A wrapped network name would push that card's metrics half
   a line below its neighbours', and those rows exist to be compared across
   cards — the comparison is worth more than the two words a long name loses at
   the narrowest width. The full name is on the element's title */
.chain-name { min-width: 0; font-size: 13.5px; font-weight: 600; color: var(--text-high); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chain-head .pill { flex: none; }
.chain-meta { font-family: var(--mono); font-size: 11px; color: var(--text-faint); margin-top: 3px; }
.chain-metric { display: flex; justify-content: space-between; gap: 10px; font-size: 11.5px; margin-top: 12px; }
.chain-metric .k { color: var(--text-faint); }
.chain-metric .v { font-family: var(--mono); color: var(--text-body); font-variant-numeric: tabular-nums; }
.chain-metric .v.tone-green { color: var(--accent); }
.chain-metric .v.tone-amber { color: var(--amber); }
.chain-bar { height: 5px; margin-top: 6px; border-radius: 5px; background: #1f2024; overflow: hidden; }
.chain-bar-fill { height: 100%; border-radius: 5px; background: var(--grey); }
.chain-bar-fill.tone-green { background: var(--accent); }
.chain-bar-fill.tone-amber { background: var(--amber); }
.chain-idle { margin-top: 14px; font-size: 11.5px; line-height: 1.5; color: var(--text-faint); }

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

/* Four across, then straight to two. Never three: the registry holds four
   networks, and a three-wide grid renders them as a row of three with one
   stranded underneath. The breakpoint is where a card stops fitting the longest
   network name beside its pill, not where the viewport hits a round number */
@media (max-width: 1240px) {
    .chain-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 820px) {
    .console { grid-template-columns: 1fr; }
    .sidebar { display: none; }
    .chain-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ---- Topbar breadcrumb (canvas: "Group / Page") -------------------------- */

.crumbs { display: flex; align-items: center; gap: 7px; font-size: 13px; color: var(--text-muted); }

.crumbs .sep { color: #3a3c42; }

.crumbs .here { color: var(--text); }

/* ---- Screen placeholder (skeleton stage only) ---------------------------- */

.placeholder {
    min-height: 60vh;
    display: grid;
    place-items: center;
}

.placeholder .inner { text-align: center; max-width: 380px; }

.placeholder .glyph {
    display: inline-flex;
    width: 40px;
    height: 40px;
    border-radius: 10px;
    background: var(--surface-raised);
    border: 1px solid var(--hairline);
    align-items: center;
    justify-content: center;
    color: var(--text-faint);
}

.placeholder h2 { font-size: 15.5px; font-weight: 600; margin: 14px 0 0; color: var(--text); }

.placeholder p { font-size: 13px; color: var(--text-muted); line-height: 1.6; margin: 8px 0 0; }


/* ============================================================================
 * Dashboard (stage 3): pool banner, curve-chart chrome extras, mini tables
 * and share-bar rows. The curve look itself (gradients, smoothing, hover)
 * is drawn by js/components/chart.js; these are its surroundings.
 * ========================================================================== */

.topbar-tools { display: flex; align-items: center; }

.warn-note.amber {
    background: rgba(206, 163, 74, .1);
    border-color: rgba(206, 163, 74, .28);
    color: #e5c98a;
    align-items: center;
    margin: 0 0 16px;
}
.warn-note[hidden] { display: none; }
.warn-note.amber svg { color: var(--amber); }
.warn-note.amber .grow { flex: 1; }
.warn-note.amber strong { color: var(--amber); font-weight: 600; }
.warn-note.amber .key { font-family: var(--mono); color: var(--amber); }
.warn-note.amber .turn-on {
    display: inline-flex;
    align-items: center;
    height: 28px;
    padding: 0 11px;
    border-radius: 6px;
    background: rgba(206, 163, 74, .16);
    border: 1px solid rgba(206, 163, 74, .4);
    color: #e5c98a;
    font-size: 12px;
    text-decoration: none;
    flex: none;
}
.warn-note.amber .turn-on:hover { background: rgba(206, 163, 74, .24); }

.duo-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-bottom: 18px; }
@media (max-width: 1100px) { .duo-grid { grid-template-columns: minmax(0, 1fr); } }

/* Every top-level block on a page carries the same 18px under it. .summary and
   .duo-grid always did; a bare panel used as a page block did not — which went
   unnoticed for eight screens because each had exactly one and put it last. */
.content > .panel { margin-bottom: 18px; }

/* Head-right legend (the canvas keeps chart legends beside the title) */
.chart-leg { display: flex; gap: 12px; align-items: center; font-size: 11.5px; color: var(--text-muted); }
.chart-leg .chart-leg-item { gap: 5px; font-size: 11.5px; }

.chart-none { height: 190px; display: grid; place-items: center; font-size: 12.5px; color: var(--text-faint); }

/* Window-wide stats row under the latency curve */
.chart-foot { display: flex; justify-content: space-between; margin-top: 8px; font-family: var(--mono); font-size: 10.5px; color: #4d5157; }
.chart-foot[hidden] { display: none; }

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

.panel-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 11px 14px; border-bottom: 1px solid var(--hairline); }
.panel-title { font-size: 13px; font-weight: 500; color: var(--text-high); }
.panel-hint { font-size: 11.5px; color: var(--text-faint); }
.panel-link { font-size: 11.5px; color: var(--text-muted); text-decoration: none; transition: color .12s; }
.panel-link:hover { color: var(--accent); }

.mini-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.mini-table td { padding: 0 14px; height: 36px; border-bottom: 1px solid #191a1b; white-space: nowrap; }
.mini-table tr:last-child td { border-bottom: none; }
.mini-table td:last-child { text-align: right; }
.mini-table a { color: var(--text-body); text-decoration: none; transition: color .12s; }
.mini-table a:hover { color: var(--accent); }
.mini-table a.accent { color: var(--accent); }
.mini-table .mono { font-family: var(--mono); font-size: 11.5px; }
.mini-table .faint { color: var(--text-faint); }
.mini-table .strong { color: var(--text-high); }
.mini-table .warn-text { color: var(--amber); }
.mini-table a.rid { display: inline-block; max-width: 168px; overflow: hidden; text-overflow: ellipsis; vertical-align: middle; }
/* The channel column is the one unbounded cell: a name like
   "OAuth · codex · someone@example.com" is longer than the panel, and with
   nowrap on every cell it pushed the request id past the right edge instead
   of ellipsizing. Bounding it here keeps the row inside its panel. */
.mini-table td.chan-cell { max-width: 0; width: 100%; overflow: hidden; }
.mini-table a.chan { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.mini-empty { padding: 26px 14px; text-align: center; font-size: 12.5px; color: var(--text-faint); }
.mini-empty.warn { color: var(--amber); }

/* ---- Share-bar rows (model spend, errors by kind) ------------------------- */

/* No horizontal padding of its own: rows share the card's left edge, so
   the list lines up under the title instead of floating indented */
.bar-rows { padding: 12px 0 0; display: flex; flex-direction: column; gap: 8px; }
/* Inside a bare .panel (no chart-card padding around it), the rows carry
   their own inset — without it the bars run edge to edge and the last row
   sits on the card border */
.bar-rows.inset { padding: 12px 14px 14px; }
.bar-row { display: flex; align-items: center; gap: 10px; min-width: 0; }
.bar-name { width: 186px; flex: none; font-family: var(--mono); font-size: 11px; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-decoration: none; transition: color .12s; }
a.bar-name:hover { color: var(--accent); }
.bar-track { flex: 1; height: 9px; border-radius: 2px; background: #1c1c1f; overflow: hidden; }
.bar-fill { display: block; height: 100%; border-radius: 2px; background: var(--accent); }
.bar-val { width: 62px; flex: none; text-align: right; font-family: var(--mono); font-size: 11px; color: var(--text-body); }
.bar-pill { width: 132px; flex: none; justify-content: flex-start; overflow: hidden; }
.bar-count { width: 40px; flex: none; text-align: right; font-family: var(--mono); font-size: 11px; color: var(--text-body); }
.bar-pct { width: 40px; flex: none; text-align: right; font-family: var(--mono); font-size: 11px; color: var(--text-faint); }

.stat-card .v.bad { color: var(--danger); }
.stat-card .v.warn { color: var(--amber); }
.stat-card .d.warn { color: var(--amber); }
.stat-card .d.bad { color: var(--danger); }

/* ---- Channels / Models --------------------------------------------------- */

/* The kind segmented control reuses the range-toggle skeleton; the count sits
   quieter than the label */
.seg-count { opacity: .55; font-family: var(--mono); margin-left: 5px; }


/* Quota mini bars in the OAuth table cell: two labelled 4px tracks */
.qmini { display: flex; flex-direction: column; gap: 3px; min-width: 150px; }
.qmini-row { display: flex; align-items: center; gap: 6px; }
/* Wide enough for the longest window name (weekly/monthly) so the track
   never rides over the text; anything longer ellipsizes.
   ⚠️ Left-aligned, not right: right-aligning inside a fixed 44px box pushed
   every "5h"/"7d" toward the middle of the box, so the whole Quota column
   read as indented against its own header — the prototype has it flush left
   like every other column. */
.qmini-label { font-family: var(--mono); font-size: 10.5px; color: var(--text-faint); width: 44px; flex: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: left; }
.qmini-track { flex: 1; height: 4px; border-radius: 2px; background: #1f2024; overflow: hidden; }
.qmini-fill { display: block; height: 4px; border-radius: 2px; background: var(--accent); }
.qmini-val { font-family: var(--mono); font-size: 10.5px; color: var(--text-muted); width: 34px; flex: none; text-align: right; }

/* Drawer health strip: one mono line answering "is it dead right now" */
.health-line { display: flex; align-items: center; gap: 8px; padding: 9px 11px; border-radius: 7px; background: var(--surface); border: 1px solid #1f2024; font-family: var(--mono); font-size: 11.5px; color: var(--text-body); flex-wrap: wrap; }
.health-line .k { color: var(--text-faint); }
.health-line .sep { color: #3a3c42; }
.health-line .ok { color: var(--green); }
.health-line .warn { color: #cea34a; }
.health-line .bad { color: #eb5757; }

/* Drawer face rows: extra wire → resolved base */
.face-row { display: flex; align-items: center; gap: 8px; padding: 7px 10px; border-radius: 6px; background: var(--surface); border: 1px solid #1f2024; font-family: var(--mono); font-size: 11.5px; }
.face-row .proto { color: #b59cff; }
.face-row .arrow { color: #3a3c42; }
.face-row .base { color: var(--text-muted); word-break: break-all; }
.face-row .miss { color: #cea34a; }

/* Drawer quota-window cards: label + used bar + reset/checked line; a stale
   window dims whole and wears the tag — routing does not believe it */
.quota-card { display: flex; flex-direction: column; gap: 5px; padding: 9px 10px; border-radius: 6px; background: var(--surface); border: 1px solid #1f2024; }
.quota-card.stale { opacity: .55; }
.quota-head { display: flex; align-items: center; justify-content: space-between; }
.quota-name { display: flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--text-body); }
.quota-tag { display: inline-flex; align-items: center; height: 18px; padding: 0 5px; border-radius: 4px; border: 1px solid #34343a; color: var(--text-muted); font-size: 10.5px; font-family: var(--mono); }
.quota-pct { font-family: var(--mono); font-size: 12px; color: var(--text-body); }
.quota-track { height: 5px; border-radius: 3px; background: #1f2024; overflow: hidden; }
.quota-fill { display: block; height: 5px; border-radius: 3px; }
.quota-foot { display: flex; align-items: center; justify-content: space-between; font-family: var(--mono); font-size: 11px; }
.quota-foot .resets { color: var(--text-muted); }
.quota-foot .checked { color: var(--text-faint); }

/* Red state box (refresh failed) — the .warn-note shape in the error tone */
.err-note { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-radius: 6px; background: rgba(235, 87, 87, .10); border: 1px solid rgba(235, 87, 87, .28); font-family: var(--mono); font-size: 11.5px; color: #eb5757; }
.err-note[hidden] { display: none; }

/* Test modal: wide two-pane request/result */
.modal-test { width: min(1068px, 92vw); }
.test-note { display: inline-flex; align-items: center; gap: 7px; padding: 7px 10px; border-radius: 6px; background: rgba(206, 163, 74, .12); border: 1px solid rgba(206, 163, 74, .28); color: #e5c98a; font-size: 11.5px; }
/* The probe knobs above the two panes: model picker + prompt text */
.test-controls { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; margin-bottom: 14px; }
.test-control { display: flex; flex-direction: column; gap: 6px; }
/* Fixed width + ellipsis: picking a long slug must not reflow the row
   (the trigger growing is what made the whole modal appear to flash) */
.test-control .dd-trigger { width: 300px; min-width: 0; }
.test-control .dd-trigger .dd-value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.test-control-wide { flex: 1; min-width: 220px; }

.test-control input {
    height: 32px;
    padding: 0 10px;
    border-radius: 7px;
    border: 1px solid #2a2b30;
    background: #0f1011;
    color: var(--text);
    font-size: 12px;
    outline: none;
    width: 100%;
}

.test-control input:focus { border-color: #3a3b44; }

.test-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
@media (max-width: 900px) { .test-grid { grid-template-columns: minmax(0, 1fr); } }
.test-col-title { font-size: 11.5px; color: var(--text-faint); letter-spacing: .05em; text-transform: uppercase; margin-bottom: 8px; }
/* Refresh keeps the old preview and dims it — swapping to a one-line
   placeholder collapses the modal's height and snaps it back (the flash) */
.test-pre.stale { opacity: .55; }

.test-pre { transition: opacity .12s; border-radius: 7px; background: #0c0d0e; border: 1px solid #1f2024; padding: 12px; font-family: var(--mono); font-size: 11.5px; color: var(--text-muted); line-height: 1.75; white-space: pre-wrap; word-break: break-all; max-height: 320px; overflow: auto; margin: 0; }
.test-status { display: flex; align-items: center; gap: 9px; margin-bottom: 9px; }
.test-timing { font-family: var(--mono); font-size: 11.5px; color: var(--text-muted); }
.test-foot-note { display: block; margin-top: 8px; font-family: var(--mono); font-size: 11px; color: var(--text-faint); }

/* Timeline: an entry's request-id link-through */
.tl-link { font-family: var(--mono); font-size: 11px; color: var(--accent); text-decoration: none; }
.tl-link:hover { text-decoration: underline; }

/* ==========================================================================
   Generations — the server-paged ledger table
   ========================================================================== */

/* In-place filter links (user / model / channel cells): body-colored until
   hovered, so the table doesn't shout; the rid column keeps the accent —
   it is the walk into the trace. */
.cell-link { color: var(--text-body); text-decoration: none; }
.cell-link:hover { color: var(--accent); }
.cell-link.mono { color: var(--accent); }
.cell-link.mono:hover { text-decoration: underline; }

/* status cell's second line: fault_party · fault_reason */
.fault-sub { margin-top: 3px; font-size: 10.5px; color: var(--text-faint); font-family: var(--mono); }

.empty .btn { margin-top: 14px; }
.btn[hidden] { display: none; }

/* ==========================================================================
   Trace — summary card + attempt timeline
   ========================================================================== */

.trace-search { display: flex; gap: 10px; margin-bottom: 16px; }
.trace-search[hidden] { display: none; }
.trace-search .grow { flex: 1; }
.trace-search input { font-family: var(--mono); }
/* Same box as the input it sits beside (.search input is 34px) */
.trace-search .btn { height: 34px; }

.trace-summary { padding: 15px 17px; margin-bottom: 18px; }
.ts-head { display: flex; align-items: center; gap: 12px; margin-bottom: 13px; }
.ts-id { display: flex; align-items: center; gap: 9px; flex: 1; min-width: 0; }
.ts-id .mono { font-size: 15px; color: var(--text-high); overflow: hidden; text-overflow: ellipsis; }
.ts-grid { display: flex; flex-wrap: wrap; gap: 9px 26px; }
.ts-kv { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.ts-k { font-size: 11.5px; color: var(--text-faint); }
.ts-v { font-size: 12.5px; color: var(--text-body); }

.trace-attempts { max-width: 980px; }
.trace-label { font-size: 11.5px; color: var(--text-faint); letter-spacing: .05em; text-transform: uppercase; margin-bottom: 10px; }

.att-row { display: flex; gap: 14px; }
.att-rail { display: flex; flex-direction: column; align-items: center; flex: none; width: 26px; }
.att-dot {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: var(--mono);
    font-size: 11.5px;
    flex: none;
}
.att-dot.green { color: var(--green); background: rgba(109, 199, 139, .12); border: 1px solid rgba(109, 199, 139, .34); }
.att-dot.red { color: var(--danger); background: rgba(235, 87, 87, .12); border: 1px solid rgba(235, 87, 87, .34); }
.att-dot.amber { color: var(--amber); background: rgba(206, 163, 74, .12); border: 1px solid rgba(206, 163, 74, .34); }
.att-dot.grey { color: var(--text-muted); background: rgba(154, 154, 154, .1); border: 1px solid rgba(154, 154, 154, .3); }
.att-spine { flex: 1; width: 1px; background: var(--hairline); margin-top: 6px; }

.att-card { flex: 1; min-width: 0; border: 1px solid var(--hairline); border-radius: 8px; background: var(--surface); overflow: hidden; margin-bottom: 14px; }
.att-head { display: flex; align-items: center; gap: 10px; padding: 11px 14px; flex-wrap: wrap; }
.att-card:has(.att-body) .att-head { border-bottom: 1px solid var(--hairline); }
.att-name { font-size: 13.5px; color: var(--text-high); }
.att-proto {
    display: inline-flex;
    align-items: center;
    height: 19px;
    padding: 0 6px;
    border-radius: 4px;
    border: 1px solid #2a2b30;
    color: var(--text-muted);
    font-size: 11px;
}
.att-timing { margin-left: auto; font-size: 11.5px; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.att-open { margin-left: 12px; font-size: 12px; color: var(--accent); text-decoration: none; white-space: nowrap; }
.att-open:hover { text-decoration: underline; }

.att-body { padding: 12px 14px; display: flex; flex-direction: column; gap: 11px; }
.att-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; }
.att-cell { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.att-k { font-size: 11.5px; color: var(--text-faint); }
.att-v { font-size: 12.5px; color: var(--text-body); overflow: hidden; text-overflow: ellipsis; }
.att-v.tone-red { color: var(--danger); }
.att-line { font-size: 12px; color: var(--text-body); word-break: break-word; }
.att-line.faint { color: var(--text-faint); }

.att-bh { display: flex; flex-direction: column; gap: 6px; }
.att-bh-head { display: flex; align-items: center; justify-content: space-between; }
.att-bh-head .mono { font-size: 11.5px; color: var(--text-faint); }
.att-pre {
    margin: 0;
    border-radius: 6px;
    background: #0c0d0e;
    border: 1px solid var(--hairline);
    padding: 11px 12px;
    font-family: var(--mono);
    font-size: 11.5px;
    color: var(--text-muted);
    line-height: 1.7;
    white-space: pre-wrap;
    word-break: break-all;
    max-height: 360px;
    overflow: auto;
}

/* Zero-attempt rejection: the reason card sits where the timeline would */
.trace-reject { border: 1px solid rgba(235, 87, 87, .3); border-radius: 8px; background: var(--surface); padding: 15px 17px; }
.tr-title { font-size: 13.5px; font-weight: 500; color: var(--text-high); margin-bottom: 10px; }
.tr-pills { display: flex; gap: 7px; margin-bottom: 11px; }
.tr-msg { font-family: var(--mono); font-size: 12px; color: var(--danger); margin-bottom: 10px; word-break: break-word; }
.tr-note { font-size: 12px; color: var(--text-faint); line-height: 1.6; }
.tr-gap { margin-bottom: 14px; }

/* ---- Events ------------------------------------------------------------- */

/* The retention footnote under the pagination — policy made visible */
.retention-note {
    padding: 10px 18px 13px;
    border-top: 1px solid var(--hairline);
    font-size: 11px;
    color: var(--text-faint);
}

/* Reason column: our-side trigger text, kept subdued next to the pills */
.reason-cell { font-size: 11.5px; color: var(--text-muted); }

/* ---- Users -------------------------------------------------------------- */

/* Drawer sub-tables (API keys / credit ledger): compact grid rows */
.sub-table { display: flex; flex-direction: column; gap: 2px; }
.sub-row {
    display: grid;
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) auto auto auto;
    gap: 10px;
    align-items: center;
    padding: 6px 0;
    border-bottom: 1px solid var(--hairline);
    font-size: 12px;
}
.sub-row:last-of-type { border-bottom: none; }
.sub-row.ledger { grid-template-columns: auto auto minmax(0, 1fr) auto; }
.sub-row .mono { font-size: 11.5px; }
.sub-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-body); }
.sub-action { min-width: 62px; text-align: right; }
.sub-amount { text-align: right; }
.sub-amount.pos { color: var(--green); }
.sub-amount.neg { color: var(--danger); }
.sub-more { display: inline-block; margin-top: 9px; font-size: 12px; }

/* Negative balances read as debt at a glance; under a dollar is the warning
   before that, since the next call is what turns it negative */
.neg { color: var(--danger); }
.low { color: var(--amber); }

/* Adjust-credit dialog: direction segmented + live balance preview */
.adjust-seg { width: fit-content; }
.adjust-preview { min-height: 18px; font-size: 11.5px; color: var(--text-faint); margin-top: 2px; }

/* ---- Utility classes ------------------------------------------------------
   Static looks belong here, never to scripted styles: only data-driven
   values (bar widths, dropdown positions) go through the CSSOM. */
.v-stack { display: flex; flex-direction: column; gap: 6px; }
.v-stack.tight { gap: 2px; }
.text-danger { color: var(--danger); }
.text-green { color: var(--green); }
.text-amber { color: var(--amber); }
/* Reserve one line of height so async text doesn't reflow the form */
.min-line { min-height: 18px; }

/* ---- Performance: runtime panels -----------------------------------------
   Panel A is four gauges side by side rather than a table: each answers a
   different question and none of them is a row in a series. Below the fold
   the page returns to the ordinary panel/table vocabulary. */
.rt-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.rt-cell { padding: 13px 14px; border-right: 1px solid var(--hairline); display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.rt-cell:last-child { border-right: none; }
.rt-label { font-family: var(--mono); font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--text-faint); }
.rt-value { font-family: var(--mono); font-size: 17px; font-weight: 600; color: var(--text); display: flex; align-items: baseline; gap: 6px; min-width: 0; }
.rt-value .unit { font-size: 11.5px; font-weight: 400; color: var(--text-faint); }
.rt-sub { font-family: var(--mono); font-size: 11px; color: var(--text-muted); line-height: 1.5; white-space: pre-line; }
.rt-track { height: 6px; border-radius: 2px; background: #1c1c1f; overflow: hidden; }
.rt-fill { display: block; height: 100%; border-radius: 2px; background: var(--accent); }
/* Degraded is a designed state, not a crash — it gets a stable place to
   appear rather than being inferred from odd behaviour elsewhere */
.rt-cell.degraded { background: rgba(235, 87, 87, .06); }
.rt-cell.degraded .rt-value { color: var(--danger); }

/* Task table: an overdue row is the whole reason this table exists, so it
   carries a tint and not only a coloured word */
.table tbody tr.overdue { background: rgba(235, 87, 87, .06); }
.task-result { display: flex; align-items: center; gap: 6px; }
.task-dot { width: 6px; height: 6px; border-radius: 50%; flex: none; background: var(--green); }
.task-dot.amber { background: var(--amber); }
.task-dot.red { background: var(--danger); }
.task-dot.grey { background: var(--grey); }

/* Panel C stacks snapshots over caches; the divider marks where the meaning
   changes from "how old" to "how effective" */
.snap-list { padding: 12px 14px 14px; display: flex; flex-direction: column; gap: 12px; }
.snap-row { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.snap-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.snap-name { font-size: 12px; color: var(--text-body); }
.snap-count { font-family: var(--mono); font-size: 10.5px; color: var(--text-faint); margin-left: 7px; }
.snap-age { font-family: var(--mono); font-size: 11px; color: var(--text-muted); white-space: nowrap; }
.snap-next { font-family: var(--mono); font-size: 10.5px; color: var(--text-faint); }
.snap-divider { height: 1px; background: var(--hairline); }
.cache-row { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.cache-val { font-family: var(--mono); font-size: 13px; color: var(--text); white-space: nowrap; }
/* The unreachable-runtime frame is one statement, not one gauge among four */
.rt-cell.solo { grid-column: 1 / -1; border-right: none; }
