/* ============================================================================
 * 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;
}

/* An <a> since the logo leads back to the public landing — reset the UA
   link paint so the wordmark keeps the body ink */
.login-logo { display: flex; align-items: center; gap: 11px; color: inherit; text-decoration: none; }

.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; }

/* ---- 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;
    /* One step above --surface-raised: the canvas's "selected / secondary
       control" ground (active filter chip, secondary button) */
    --surface-elev: #1c1c1f;
    --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;
    --danger: #eb5757;
    --danger-solid: #eb5757;
    --grey: #8a8f98;

    /* Geometry */
    --sidebar-w: 224px;
    --topbar-h: 46px;
    --radius-card: 8px;
    /* Canvas draws every 30-32px control at 6px, not 8 - the console's controls
       read as chips, and 8px on a 30px box rounds them toward pills */
    --radius-control: 6px;
    --radius-modal: 10px;
    /* Canvas control heights: 30px for a topbar action, 32px for a filter row */
    --control-h: 32px;

    /* 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;
    /* Canvas: the sidebar is the page ground (#08090a), the pane beside it is
       one step up (#0f1011). Drawing it on --surface-sunk inverted that — the
       rail read as a trench cut below the page instead of the floor the page
       sits on */
    background: var(--bg);
    border-right: 1px solid var(--hairline);
    display: flex;
    flex-direction: column;
    padding: 14px 10px 10px;
}

/* An <a> since the logo leads back to the public landing */
.sidebar-logo { display: flex; align-items: center; gap: 9px; padding: 2px 6px 14px; color: inherit; text-decoration: none; }

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

.sidebar-logo .name { font-size: 13.5px; font-weight: 600; letter-spacing: -0.01em; }
.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: 1px; overflow-y: auto; flex: 1; }

/* No margin: the group label's own top padding is the separation on the canvas */
.nav-group { margin-top: 0; }

/* Canvas: plain sans at 11.5px on a .05em track — the mono/.12em version was
   payment's label voice and read louder than the items underneath it */
.nav-label {
    font-size: 11.5px;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--text-faint);
    padding: 10px 8px 4px;
}

.nav-item {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 6px 8px;
    border-radius: 6px;
    color: var(--text-muted);
    font-size: 13px;
    text-decoration: none;
    position: relative;
    transition: background .12s, color .12s;
}

/* The icon takes the row's own colour on the canvas — it is not a second
   channel of information, so it must not be lit independently */
.nav-item svg { flex: none; opacity: .9; }
.nav-item:hover { background: rgba(255, 255, 255, .04); color: var(--text-high); }

.nav-item.active { background: var(--surface-elev); color: var(--text-high); }

.sidebar-account {
    display: flex;
    align-items: center;
    gap: 9px;
    /* Canvas: the rule runs the full width of the rail, so the row bleeds back
       out through the sidebar's 10px padding */
    margin: 0 -10px;
    padding: 10px 12px 2px;
    border-top: 1px solid var(--hairline);
    text-decoration: none;
    color: inherit;
    transition: background .12s;
}

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

.sidebar-account .avatar {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: var(--surface-elev);
    border: 1px solid var(--hairline-strong);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: var(--mono);
    font-size: 10.5px;
    color: var(--text-body);
    flex: none;
    text-transform: uppercase;
}

.sidebar-account .who { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.sidebar-account .who { line-height: 1.25; }
.sidebar-account .who .n { font-size: 12.5px; color: var(--text-body); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sidebar-account .who .e { font-size: 11.5px; color: var(--text-faint); 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;
    /* 18px, same as .content - the breadcrumb and the first card must share
       one left edge */
    padding: 0 18px;
    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); }

/* Canvas: the content pane fills the frame at padding:18px and stacks its
   blocks on gap:14px - it is not centred and has no max width. Centring at
   1320px was the single loudest deviation: on anything wider than ~1550px it
   put hundreds of pixels of dead margin down both sides of a console whose
   whole point is density. */
.content { flex: 1; min-height: 0; overflow-y: auto; padding: 18px 18px 28px; }
.content-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 14px; }
.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: 10px; margin-bottom: 14px; }
/* Canvas: the card sits on the raised surface (#141516), one step ABOVE the
   pane it lies on - drawing it in the pane colour is what made every card
   disappear into the background. Label is plain sans sentence case; only the
   value and the sub line are mono. */
.stat-card { background: var(--surface-raised); border: 1px solid var(--hairline); border-radius: var(--radius-card); padding: 11px 13px; }
.stat-card .k { font-size: 12.5px; color: var(--text-muted); }
.stat-card .v { font-family: var(--mono); font-size: 21px; font-weight: 600; letter-spacing: -0.02em; margin-top: 4px; color: var(--text); }
.stat-card .d { font-family: var(--mono); font-size: 11.5px; margin-top: 4px; color: var(--text-faint); 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: 6px;
    height: 30px;
    padding: 0 12px;
    border-radius: var(--radius-control);
    font-size: 12.5px;
    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;
    /* Both must be stated. A <button class="btn"> carrying no variant otherwise
       falls back to the UA's `buttonface`/`buttontext` - and on a page that
       never declares color-scheme: dark, buttonface is WHITE. */
    background: transparent;
    color: var(--text-body);
    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); }

/* Canvas: the secondary button is a filled chip on #1c1c1f, not a transparent
   outline - on the pane colour a transparent one reads as a bare label */
.btn-outline { background: var(--surface-elev); border-color: var(--hairline-strong); color: var(--text-body); }
.btn-outline:not([disabled]):hover { background: #232327; 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: 28px; padding: 0 10px; font-size: 12px; }
/* Filter-row height: a button standing in the toolbar beside the selects must
   be the same box they are, or it reads as a different class of control */
.toolbar .btn { height: var(--control-h); }

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

/* Canvas: 20px tall, 5px radius, 11.5px in the UI sans - the mono 11px/6px
   version read a size larger than every pill on the design and squared off
   against the 5px-radius chips beside it */
.pill {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 20px;
    font-size: 11.5px;
    font-weight: 400;
    padding: 0 7px;
    border-radius: 5px;
    /* No text-transform: the label decides its own case. It used to force
       lowercase because every value was a raw DB one, and that silently
       rewrote the names the screens actually chose - "Chat Completions"
       reached the DOM and rendered "chat completions". A stylesheet that
       edits copy is a stylesheet you have to remember */
    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; }
/* The canvas gives a classification its own geometry: a notch smaller
   (19px / 4px radius) and mono, because what it holds is a wire value. */
.pill-nodot { height: 19px; padding: 0 6px; border-radius: 4px; font-family: var(--mono); font-size: 11px; }

.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-red    { color: var(--danger); background: rgba(235, 87, 87, .12); border-color: rgba(235, 87, 87, .3); }
.pill-grey   { color: var(--grey); background: rgba(138, 143, 152, .10); border-color: rgba(138, 143, 152, .24); }
/* 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); }

/* The Accepted column renders its API names quiet: a row carries up to five
   of them beside a slug, a provider and a price, and Title Case in that
   density competes with the identifiers the eye is actually scanning for.
   Opt-in and named, unlike the blanket lowercase this file used to put on
   every .pill — that one silently rewrote copy the screens had chosen.
   The DOM keeps the real name, so copy and find-in-page still work */
.pill-lower { text-transform: lowercase; }


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

/* Canvas: the filter row runs on gap:8px and its left edge lines up with the
   first table column (11px), so the search box and the Name header share one
   vertical rule */
.toolbar { display: flex; align-items: center; gap: 8px; padding: 10px 11px; border-bottom: 1px solid var(--hairline); 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: var(--control-h);
    background: var(--surface-raised);
    border: 1px solid var(--hairline-strong);
    border-radius: var(--radius-control);
    padding: 0 10px 0 30px;
    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 --------------------------------------------------------------- */

/* Canvas: a panel is a card on the raised surface (#141516) - that is what all
   38 content cards on the design use. Painting it the pane colour is what made
   every card on the dashboard disappear into its own background.
   The exception is a list page, where the panel IS the table: there the canvas
   leaves the wrapper unfilled so rows sit straight on the pane and the page
   reads as one surface, not a card on a card. `.table-scroll` is the structural
   marker for that case - every list template has exactly one. */
.panel { background: var(--surface-raised); border: 1px solid var(--hairline); border-radius: var(--radius-card); overflow: hidden; }
.panel:has(> .table-scroll) { background: var(--surface); }

.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; }

/* Canvas: the header is a filled band (#141516) closed by a hairline, and its
   labels are plain 11.5px sentence case. The mono/uppercase/letter-spaced
   version shouted over the data and left the band invisible, so the table had
   no top edge at all. */
.table thead tr { background: var(--surface-raised); }

.table th {
    text-align: left;
    font-size: 11.5px;
    font-weight: 400;
    color: var(--text-muted);
    height: 32px;
    padding: 0 11px;
    border-bottom: 1px solid var(--hairline);
    white-space: nowrap;
}

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

/* Canvas row: 36px tall on 11px side padding, separated by a #191a1b rule -
   a hair darker than the header hairline, so rows group and the header still
   reads as the lid. `height` on a cell is a floor, so the two-line cells
   still grow.
   ⚠️ The 7px vertical padding is what makes that growth livable. With `0`
   the floor centred a single line, but a two-line cell grew flush against
   both rules — the status pill sat welded to the header hairline with its
   sub-line jammed under it. A single line is unaffected: 7 + 20 + 7 still
   fits inside the 36px floor, so only the cells that grow pay for it. */
.table td {
    height: 36px;
    padding: 7px 11px;
    font-size: 12.5px;
    color: var(--text-body);
    border-bottom: 1px solid #191a1b;
    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;
}
/* The pagination bar below brings its own top rule; without this the last row
   and the pager stack two hairlines into one thick line */
.table tbody tr:last-child td { border-bottom: 0; }
.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: 9px 11px; border-top: 1px solid var(--hairline); 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-family: var(--mono); font-size: 11.5px; color: var(--text-faint); }
.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;
    /* 480 on the user side (canvas 09), vs the manager's 462 */
    width: 480px;
    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-raised); 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; }
/* Canvas: an inset box inside the drawer sits ABOVE the drawer ground, not
   below it - sunk (#0c0d0e) made every framed section read as a hole */
.drawer-section.framed { background: var(--surface-raised); border: 1px solid var(--hairline); border-radius: 8px; padding: 14px 16px; margin: 14px 0; }
.section-title { font-size: 11.5px; letter-spacing: .05em; 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(--danger);
    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(--green); box-shadow: 0 0 0 4px var(--surface-raised), 0 0 8px rgba(109, 199, 139, .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); }
.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(--green); border-color: rgba(109, 199, 139, .32); background: rgba(109, 199, 139, .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-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 var(--hairline); }
.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: 8px;
    height: var(--control-h);
    padding: 0 10px;
    background: var(--surface-raised);
    border: 1px solid var(--hairline-strong);
    border-radius: var(--radius-control);
    color: var(--text-body);
    font-size: 12.5px;
    font-family: inherit;
    cursor: pointer;
    white-space: nowrap;
    transition: background .12s, border-color .12s, color .12s;
}

.dd-trigger:hover { background: var(--surface-elev); border-color: #34343a; color: var(--text-high); }
/* Canvas: a filter holding a non-default value steps up a surface and takes
   full-strength text - that difference is the only cue that a list is filtered */
.dd-trigger.dd-set { background: var(--surface-elev); border-color: #34343a; 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 */
/* Canvas segmented: 2px rail on #141516 inside a hairline, and the selected
   option is a #2a2b30 chip - NOT a white pill. The white one was borrowed from
   a light-surface component and read as a primary action in a filter row. */
.range-toggle { display: flex; gap: 0; flex: none; background: var(--surface-raised); border: 1px solid var(--hairline); border-radius: 7px; padding: 2px; }
.range-opt { appearance: none; background: transparent; border: none; font: inherit; font-size: 12.5px; color: var(--text-muted); padding: 5px 14px; border-radius: 5px; cursor: pointer; transition: color .12s, background .12s; }
.range-opt:hover { color: var(--text-high); }
.range-opt.on { background: var(--hairline-strong); color: var(--text-high); }

.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(--green); }

/* ---- 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-raised); 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(--green); }
.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(--green); }
.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; }

.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: label / track / value on one grid, the TRACK pinned so
   every meter is the same length and the percentage follows it ragged
   (see manager.css for the full note) */
.qmini { display: grid; grid-template-columns: auto 140px auto; justify-content: start;
         align-items: center; gap: 3px 6px; }
.qmini-label { font-family: var(--mono); font-size: 10.5px; color: var(--text-faint); white-space: nowrap; }
.qmini-track { 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); white-space: nowrap; }

/* 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-raised); border: 1px solid var(--hairline); 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-raised); border: 1px solid var(--hairline); 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-raised); border: 1px solid var(--hairline); }
.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 */
/* 5px, not 3: the pill above it is a bordered box, so the two need more air
   between them than two bare text lines would */
.fault-sub { margin-top: 5px; 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-size: 11.5px; letter-spacing: .05em; 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; }

/* ============================================================================
 * User-console additions (stage 4 batch 0) — everything below is user-side
 * only; the shared blocks above stay byte-aligned with the manager sheet so
 * later diffs show real divergence, not drift.
 * ========================================================================== */

/* ---- Third-party sign-in (Login / Register shared) ----------------------- */

.oauth-stack { display: flex; flex-direction: column; gap: 9px; }

.oauth-btn {
    display: flex; align-items: center; justify-content: center; gap: 9px;
    height: 38px; width: 100%;
    background: #17181c; border: 1px solid #2a2b30; border-radius: 7px;
    color: #f7f8f8; font-size: 13.5px; font-weight: 500; font-family: inherit;
    cursor: pointer; text-decoration: none;
    transition: background .12s ease, border-color .12s ease;
}
.oauth-btn:hover { background: #1c1d22; border-color: #34353b; }
.oauth-btn svg { flex: none; }

.or-divider {
    display: flex; align-items: center; gap: 12px;
    margin: 16px 0; color: #4d5157; font-size: 11.5px;
    text-transform: lowercase; letter-spacing: .02em;
}
.or-divider::before, .or-divider::after {
    content: ""; flex: 1; height: 1px; background: #1f2024;
}

/* ---- Auth page furniture -------------------------------------------------- */

/* "Already have one? Sign in" — the line above the card's heading actions */
.auth-alt { margin: 6px 0 0; font-size: 13px; color: #8a8f98; }
.auth-alt a { color: var(--accent); text-decoration: none; }
.auth-alt a:hover { color: var(--accent-hover); }

/* Sent / done states: icon + copy, replacing the form */
.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; }
.auth-state p .who { color: #f7f8f8; }

/* Resend line with its cooldown counter */
.resend-line { font-size: 12.5px; color: #4d5157; }
.resend-line a { color: var(--accent); text-decoration: none; }
.resend-line a:hover { color: var(--accent-hover); }
.resend-line a[aria-disabled="true"] { color: #4d5157; pointer-events: none; }

/* One-time API key reveal (activation success / first OAuth sign-in) */
.key-reveal {
    display: flex; align-items: center; gap: 8px;
    background: #101116; border: 1px solid #2a2b30; border-radius: 7px;
    padding: 10px 12px; margin-top: 4px;
}
.key-reveal code {
    flex: 1; font-family: 'Geist Mono', monospace; font-size: 12px;
    color: #f7f8f8; word-break: break-all;
}
.key-reveal button {
    flex: none; display: flex; align-items: center; justify-content: center;
    width: 26px; height: 26px; border-radius: 6px;
    background: transparent; border: 1px solid #2a2b30; color: #8a8f98; cursor: pointer;
}
.key-reveal button:hover { color: #f7f8f8; border-color: #34353b; }

/* Label row with a trailing action ("Password    Forgot?") */
.label-row { display: flex; align-items: center; justify-content: space-between; }
.label-row a { font-size: 12px; color: var(--accent); text-decoration: none; }
.label-row a:hover { color: var(--accent-hover); }

/* Panel body copy (placeholder pages) */
.panel h3 { margin: 0; padding: 16px 18px 0; font-size: 14.5px; font-weight: 600; }
.panel .muted { margin: 8px 0 0; padding: 0 18px 16px; font-size: 13px; line-height: 1.6; color: #8a8f98; }
.panel .key-reveal { margin: 0 18px 16px; }

/* Sidebar foot: account row + the sign-out control beside it */
/* One row, one card: the account link and the sign-out control share the
   hover surface — the icon lives inside the row, not beside it */
/* Symmetric breathing room: card → divider 10px, divider → row 10px */
.sidebar-foot { display: flex; align-items: center; gap: 2px; padding-right: 6px; border-top: 1px solid var(--hairline); }
.sidebar-foot .sidebar-account { flex: 1; min-width: 0; }
.signout-form { flex: none; margin: 0; }
.signout-form button {
    display: flex; align-items: center; justify-content: center;
    width: 30px; height: 30px; border-radius: 7px;
    background: transparent; border: none; color: #4d5157; cursor: pointer;
}
.signout-form button:hover { color: #f7f8f8; background: rgba(255, 255, 255, .05); }

/* ---- Overview (stage 4 batch 1) ------------------------------------------ */

/* Flex/grid blocks the JS toggles: an author display beats the UA's
   [hidden] rule, so state it explicitly (the recurring pitfall) */
.notice-banner[hidden], .duo-grid[hidden], .chart-card[hidden] { display: none; }

/* Low-balance notice — amber, not red: the user did nothing wrong, they just
   need to deposit (canvas 06) */
.notice-banner {
    display: flex; align-items: center; gap: 10px;
    background: rgba(206, 163, 74, .08); border: 1px solid rgba(206, 163, 74, .35);
    border-radius: var(--radius-card); padding: 11px 14px; margin-bottom: 18px;
    font-size: 13px; color: #e8c87e;
}
.notice-banner .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--amber); flex: none; }
.notice-banner a { margin-left: auto; color: var(--amber); text-decoration: none; font-weight: 500; white-space: nowrap; }
.notice-banner a:hover { color: #e8c87e; }

/* First-run checklist — replaces the chart until the first request lands */
.checklist { display: flex; flex-direction: column; gap: 10px; padding: 16px 18px 18px; max-width: 840px; }
.checklist-head { padding: 16px 18px 0; }
.checklist-head .t { font-size: 15px; font-weight: 600; color: var(--text-high); }
.checklist-head .d { font-size: 12.5px; color: var(--text-muted); margin-top: 5px; }
/* Table row action buttons: right-aligned with real space between them.
   Appended bare into the cell they touched, so Edit and Disable read as a
   single two-tone control. */
td.row-actions { display: flex; gap: 8px; justify-content: flex-end; align-items: center; }

.check-step {
    display: flex; align-items: center; gap: 14px;
    background: #101116; border: 1px solid #1f2024; border-radius: 8px; padding: 12px 14px;
}
.check-step .n {
    width: 26px; height: 26px; border-radius: 50%; flex: none;
    display: flex; align-items: center; justify-content: center;
    font-family: var(--mono); font-size: 12px; color: var(--text-muted);
    border: 1px solid #2a2b30;
}
/* The tick is already accent-coloured; a green ring around it put two
   different "this is fine" colours in one 26px circle and read as a
   mismatch. Tint the ring with the accent instead, so the badge is one
   colour with the check inside it. */
.check-step.done .n { background: color-mix(in srgb, var(--accent) 12%, transparent); border-color: color-mix(in srgb, var(--accent) 40%, transparent); color: var(--accent); }
.check-step .txt { flex: 1; min-width: 0; }
.check-step .t { font-size: 13.5px; font-weight: 500; color: var(--text-high); }
.check-step .d { font-size: 12.5px; color: var(--text-muted); margin-top: 3px; }
.check-step .done-tag { font-family: var(--mono); font-size: 11.5px; color: var(--accent); flex: none; }

/* Recent activity: the requests table beside the ledger table */
.recent-grid { display: grid; grid-template-columns: 1fr; }
.recent-grid .mini-table td:first-child { color: var(--text-faint); font-family: var(--mono); font-size: 11.5px; }

/* Two trailing links in one panel head */
.panel-links { display: flex; align-items: center; gap: 14px; }

/* Requests drawer: the wire-level error section (batch 2) — the canvas's
   red-tinted frame, the category as a red tag above our own sentence */
.err-box {
    display: flex; flex-direction: column; align-items: flex-start; gap: 8px;
    padding: 12px; border-radius: 7px;
    background: rgba(235, 87, 87, .08); border: 1px solid rgba(235, 87, 87, .24);
}
.drawer-section .err-sentence { font-size: 12.5px; color: var(--text-body); margin: 0; line-height: 1.55; }

/* ---- Credits (batch 3): the ledger + 330px redeem grid and the
   three-stage checkout, aligned to canvas 10 ------------------------------ */

.input {
    height: 34px; padding: 0 12px; border-radius: var(--radius-control);
    background: #101116; border: 1px solid #2a2b30; color: var(--text-high);
    font-size: 13px; outline: none;
}
.input:focus { border-color: #828fff; box-shadow: 0 0 0 3px rgba(130, 143, 255, .14); }
.input::placeholder { color: var(--text-faint); }

/* Ledger on the left, the redeem card as the canvas's 330px rail */
.credits-grid {
    display: grid; grid-template-columns: minmax(0, 1fr) 330px;
    gap: 12px; align-items: start; margin-bottom: 18px;
}
@media (max-width: 1100px) { .credits-grid { grid-template-columns: minmax(0, 1fr); } }

.redeem-card { padding: 14px 15px; display: flex; flex-direction: column; gap: 12px; }
.redeem-card .t { font-size: 13px; font-weight: 500; color: var(--text-high); }
.redeem-card .input { width: 100%; font-size: 13px; letter-spacing: .08em; }
.redeem-card .btn { height: 32px; font-size: 12.5px; }
.redeem-div { height: 1px; background: var(--hairline); }
.redeem-err {
    display: flex; align-items: center; gap: 9px; padding: 10px 11px; border-radius: 7px;
    background: rgba(235, 87, 87, .08); border: 1px solid rgba(235, 87, 87, .26);
    font-size: 12.5px; color: var(--danger); line-height: 1.5;
}
.redeem-ok {
    display: flex; align-items: center; gap: 9px; padding: 10px 11px; border-radius: 7px;
    background: rgba(109, 199, 139, .10); border: 1px solid rgba(109, 199, 139, .28);
    font-family: var(--mono); font-size: 12.5px; color: var(--green); line-height: 1.5;
}
.redeem-ok svg { flex: none; }
.redeem-err[hidden], .redeem-ok[hidden] { display: none; }
.redeem-card .hint { font-size: 11.5px; color: var(--text-faint); line-height: 1.55; margin: 0; }

/* -- checkout modal (the canvas dialogs' 480px) -- */
.deposit-modal { width: 30rem; }
.deposit-sub { font-size: 12.5px; color: var(--text-muted); margin: 5px 0 0; }
.deposit-note { font-size: 12.5px; color: var(--text-muted); margin: 2px 0; }
.deposit-label { font-size: 12.5px; color: var(--text-body); margin: 14px 0 7px; }
.deposit-err { font-size: 12.5px; color: #eb5757; margin-top: 10px; }
.deposit-err[hidden] { display: none; }

/* $10 / $50 / $100 / Custom — one four-column grid */
.preset-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-top: 4px; }
.preset-grid .btn { height: 38px; padding: 0; font-family: var(--mono); font-size: 13px; border-radius: 7px; }
.preset-btn.active { border-color: #828fff; color: var(--text-high); background: rgba(130, 143, 255, .1); }
.preset-custom { height: 38px; padding: 0 8px; text-align: center; border-radius: 7px; }

/* Network, then token — two picks instead of one grid of every pair.
   Eight methods laid out flat would be eight cells, and each chain added
   later two more; this way a new chain is one more chip on the same row.
   ⚠️ The chain marks are inline <svg>: the CSP is img-src 'self', so a
   data: URI image or a CDN logo is blocked outright. Same constraint that
   made the checkbox a pure-CSS tick. */
.chain-rail { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.chain-chip {
    min-width: 0;
    display: flex; align-items: center; justify-content: center; gap: 7px; height: 38px;
    background: transparent; border: 1px solid var(--hairline-strong); border-radius: 7px;
    color: var(--text-body); cursor: pointer; font-size: 12px; font-family: inherit;
}
.chain-chip .n { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chain-chip.active { border-color: #828fff; background: rgba(130, 143, 255, .1); color: var(--text-high); }
.chain-mark { width: 17px; height: 17px; flex: none; display: inline-flex; }
.chain-mark svg { display: block; width: 100%; height: 100%; }

.method-row { display: flex; gap: 8px; }
.method-btn {
    flex: 1; min-width: 0;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
    height: 44px;
    background: transparent; border: 1px solid var(--hairline-strong); border-radius: 7px;
    color: var(--text-body); cursor: pointer; font-family: inherit;
}
.method-btn .sym { font-size: 12.5px; color: var(--text-high); }
/* The network, spelt out again under the token. By the time the eye is
   here the chain chip is out of focus, and USDT sent on the wrong network
   is an unrecoverable transfer */
.method-btn .chain { font-size: 10.5px; color: var(--text-faint); max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.method-btn.active { border-color: #828fff; background: rgba(130, 143, 255, .1); }

/* "You send" — a quiet summary row: label left, amount right */
.send-line {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    margin-top: 14px; padding: 10px 11px; border-radius: 6px;
    background: var(--surface-sunk); border: 1px solid var(--hairline);
}
.send-line .l { font-size: 12.5px; color: var(--text-muted); }
.send-line .v { font-size: 13.5px; color: var(--text-high); }

/* -- pay stage -- */
.pay-clock {
    display: inline-flex; align-items: center; height: 22px; padding: 0 8px; border-radius: 5px;
    background: rgba(206, 163, 74, .12); border: 1px solid rgba(206, 163, 74, .28);
    color: var(--amber); font-size: 11.5px; white-space: nowrap;
}
.pay-amount { display: flex; align-items: baseline; gap: 8px; margin-bottom: 13px; flex-wrap: wrap; }
.pay-amount .n { font-size: 21px; font-weight: 600; color: var(--text-high); }
.pay-amount .sym { font-size: 13.5px; color: var(--text-muted); }
/* The network rides beside the amount, mark and all — the amount and the
   chain are one instruction, not a figure with a footnote */
.pay-chain {
    align-self: center;
    display: inline-flex; align-items: center; gap: 6px; height: 22px; padding: 0 8px;
    border: 1px solid var(--hairline-strong); border-radius: 5px;
    color: var(--text-muted); font-size: 11.5px; white-space: nowrap;
}

/* QR beside the address block */
.pay-row { display: flex; gap: 13px; align-items: flex-start; }
.qr-box { width: 104px; height: 104px; flex: none; padding: 8px; background: #ffffff; border-radius: 8px; }
.qr-box svg { display: block; width: 100%; height: 100%; }
.pay-side { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 7px; }
.pay-label { font-size: 11.5px; color: var(--text-faint); }
.pay-address {
    display: flex; align-items: center; gap: 8px; padding: 8px 10px;
    background: var(--surface-sunk); border: 1px solid var(--hairline-strong); border-radius: 6px;
}
.pay-address code { flex: 1; min-width: 0; font-family: var(--mono); font-size: 11.5px; color: var(--text-high); word-break: break-all; }
.copy-inline {
    flex: none; display: flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; border-radius: 5px;
    background: #1c1c1f; border: 1px solid var(--hairline-strong); color: var(--text-muted); cursor: pointer;
}
.copy-inline:hover { color: var(--text-high); border-color: #34353b; }
.pay-note { font-size: 11px; color: #4d5157; margin: 0; line-height: 1.5; }
/* The one sentence that has to survive being skimmed: token AND network,
   both emphasised, right under the address they apply to */
.pay-note b { color: var(--text-muted); font-weight: 500; }

/* The status strip: spinner, state, the tx trailing right */
.pay-status {
    display: flex; align-items: center; gap: 9px; margin-top: 13px; padding: 9px 11px;
    border-radius: 6px; background: var(--surface-sunk); border: 1px solid var(--hairline);
}
.pay-status .st { font-size: 11.5px; }
.pay-status .st.confirming { color: var(--blue); }
.pay-status .grow { flex: 1; }
.spin {
    width: 12px; height: 12px; flex: none; border-radius: 50%;
    border: 2px solid var(--hairline-strong); border-top-color: var(--text-faint);
    animation: spin-turn .9s linear infinite;
}
.spin.blue { border-top-color: var(--blue); }
@keyframes spin-turn { to { transform: rotate(360deg); } }
.tx-link { font-family: var(--mono); font-size: 11px; color: var(--text-faint); text-decoration: none; }
a.tx-link:hover { color: var(--accent); text-decoration: underline; }

/* -- terminal frames: badge, title, mono line, sub — left-aligned like the
   canvas; the modal head is hidden, the frame is its own heading -- */
.done-badge {
    display: inline-flex; align-items: center; justify-content: center;
    width: 30px; height: 30px; border-radius: 8px; margin: 6px 0 11px;
}
.done-badge.ok { background: rgba(109, 199, 139, .12); color: var(--green); border: 1px solid rgba(109, 199, 139, .28); }
.done-badge.gone { background: rgba(138, 143, 152, .1); color: var(--text-muted); border: 1px solid rgba(138, 143, 152, .24); }
.done-badge.warn { background: rgba(206, 163, 74, .12); color: var(--amber); border: 1px solid rgba(206, 163, 74, .28); }
.done-title { font-size: 14.5px; font-weight: 500; color: var(--text-high); }
.done-amount { font-family: var(--mono); font-size: 13px; margin-top: 9px; }
.done-amount.ok { color: var(--green); }
.done-amount.gone { color: var(--text-muted); }
.done-amount.warn { color: var(--amber); }
.done-sub { font-size: 12px; color: var(--text-muted); margin: 9px 0 0; line-height: 1.55; }
.done-sub .hi { font-family: var(--mono); color: var(--text-body); }
.modal-body .wfull { margin: 14px 0 18px; }

/* ---- Small user-console utilities --------------------------------------- */

.wfull { width: 100%; }
/* An empty stat value (no pending order) reads faint, per the canvas */
.stat-card .v.faint { color: var(--text-faint); }
/* A body-coloured mono link (usage/requests model cells): the canvas keeps
   these quiet — the accent mono link stays the trace id's walk-in */
.mono-link { font-family: var(--mono); font-size: 12px; }
.table .muted { color: var(--text-muted); }

/* ---- Overview alignment (canvas 06) -------------------------------------- */

/* Title + range toggle share the head's left, the legend takes the right */
.chart-titlerow { display: flex; align-items: center; gap: 12px; }
/* By-model rows wear the canvas's metrics inside the Overview panel */
.bar-rows.inset .bar-name { width: 200px; font-size: 11.5px; color: var(--text-body); }
.bar-rows.inset .bar-track { height: 8px; }
.bar-rows.inset .bar-pct { width: 34px; }
.bar-rows.inset .bar-val { width: 56px; font-size: 11.5px; color: var(--text-high); }
/* Recent activity: ledger rows sit one step sunk from the request rows */
.mini-table.ledger-side tr { background: var(--surface-sunk); }
/* Fixed columns like the canvas: the model cell takes what is left and
   truncates; the value columns right-align. Without this the widest model
   slug pushes the status column out of the panel. */
.recent-grid .mini-table { table-layout: fixed; }
.recent-grid .mini-table td:first-child { width: 94px; }
.recent-grid .mini-table td:nth-child(2) { overflow: hidden; text-overflow: ellipsis; }
.recent-grid .mini-table td:nth-child(3) { width: 96px; text-align: right; }
.recent-grid .mini-table td:last-child { width: 112px; }
/* The ledger's columns carry longer values (dates, six-decimal amounts) */
.recent-grid .mini-table.ledger-side td:first-child { width: 112px; }
.recent-grid .mini-table.ledger-side td:nth-child(3) { width: 118px; }
.recent-grid .mini-table.ledger-side td:last-child { width: 116px; }

/* ---- Models (batch 4) ----------------------------------------------------- */

/* Custom-model rows wear the canvas's violet tint over the shared table */
.custom-row { background: rgba(181, 156, 255, .05); cursor: pointer; }
.custom-row:hover td { background: rgba(181, 156, 255, .04); }
.alias-cell { display: inline-flex; align-items: center; gap: 7px; }
.tag-row { display: inline-flex; gap: 5px; }
.row-click { cursor: pointer; }

.edit-link { font-size: 11.5px; color: var(--accent); }
.edit-link:hover { color: #a3adff; }

.models-foot { font-size: 11.5px; color: var(--text-faint); line-height: 1.6; max-width: 940px; margin: 0 0 18px; }
.models-foot .mono { font-family: var(--mono); font-size: 11px; color: var(--text-muted); }

/* The create/edit modal — one frame, three numbered steps (canvas 560px) */
.custom-modal { width: 560px; }
.custom-modal .modal-body > p { margin: 0 0 16px; font-size: 12.5px; color: var(--text-muted); }
.step { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
.step:last-child { margin-bottom: 4px; }
.step-head { display: flex; align-items: center; gap: 8px; }
.step-n {
    width: 18px; height: 18px; border-radius: 50%;
    background: var(--surface-sunk); border: 1px solid var(--hairline-strong);
    display: inline-flex; align-items: center; justify-content: center;
    font-family: var(--mono); font-size: 10.5px; color: var(--text-muted); flex: none;
}
.step-title { font-size: 12.5px; color: var(--text-body); }
.step-hint { font-size: 11.5px; color: var(--text-faint); }

.base-trigger { width: 100%; justify-content: space-between; }
.base-trigger .dd-value { font-family: var(--mono); font-size: 12.5px; }
.base-meta { font-family: var(--mono); font-size: 11px; color: #4d5157; }

/* Ordered prompt picks: display order is injection order; the handle drags */
.prompt-pick { border: 1px solid var(--hairline); border-radius: 7px; overflow: hidden; }
.prompt-row {
    display: flex; align-items: center; gap: 10px; padding: 9px 11px;
    border-bottom: 1px solid #191a1b; cursor: pointer; user-select: none;
}
.prompt-row:last-child { border-bottom: none; }
.prompt-row.on { background: rgba(130, 143, 255, .05); }
.prompt-row .drag { color: #3a3c42; cursor: grab; flex: none; }
.prompt-row.on .drag { color: var(--text-faint); }
.prompt-row .box {
    width: 16px; height: 16px; border-radius: 4px; border: 1px solid #34343a;
    flex: none; display: inline-flex; align-items: center; justify-content: center; color: #ffffff;
}
.prompt-row.on .box { background: var(--accent-solid); border-color: var(--accent-solid); }
.prompt-row .nm {
    flex: 1; min-width: 0; font-size: 12.5px; color: var(--text-muted);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.prompt-row.on .nm { color: var(--text-high); }
.prompt-row .tk { font-family: var(--mono); font-size: 11px; color: #4d5157; }
.prompt-row.on .tk { color: var(--text-faint); }
.prompt-row.drop-above { box-shadow: inset 0 2px 0 var(--accent); }
.prompt-row.drop-below { box-shadow: inset 0 -2px 0 var(--accent); }
.pick-foot { font-family: var(--mono); font-size: 11px; color: var(--text-faint); }

.alias-rules { font-size: 11.5px; color: var(--text-faint); line-height: 1.6; }
.alias-rules .mono { font-family: var(--mono); font-size: 11px; color: var(--text-body); }
.alias-err {
    display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-radius: 6px;
    background: rgba(235, 87, 87, .08); border: 1px solid rgba(235, 87, 87, .24);
    font-family: var(--mono); font-size: 11.5px; color: var(--danger);
}
.alias-err[hidden] { display: none; }
.alias-err svg { flex: none; }

.custom-foot-hint { font-family: var(--mono); font-size: 11px; color: #4d5157; align-self: center; }
.modal-actions .grow { flex: 1; }

/* Prompt editor: the body is the point — give it room */
.prompt-text { min-height: 220px; resize: vertical; font-size: 12px; line-height: 1.55; }
.danger-link { font-size: 11.5px; color: var(--danger); cursor: pointer; margin-top: 2px; align-self: flex-start; }
.danger-link:hover { text-decoration: underline; }

/* Fixed layout so the half-width management pair cannot push past its
   panel (the recent-activity lesson applied here): narrow columns pinned,
   the flexible ones ellipsize */
#mgmt-table, #prompt-table { table-layout: fixed; }
#mgmt-table th:nth-child(3) { width: 76px; }
#mgmt-table th:nth-child(4) { width: 116px; }
#prompt-table th:nth-child(2) { width: 88px; }
#prompt-table th:nth-child(3) { width: 186px; }
#prompt-table th:nth-child(4) { width: 52px; }
#mgmt-table td, #prompt-table td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ============================================================================
 * Batch 5 · Settings (user canvas 12)
 * ========================================================================== */

/* Two independent card columns; each stacks at its own pace */
.settings-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; align-items: start; max-width: 1160px; }
.settings-col { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
@media (max-width: 1020px) { .settings-cols { grid-template-columns: 1fr; } }

/* List-style cards (identities, sessions) paint rows edge to edge */
.account-card.flush { padding: 0; overflow: hidden; }

.set-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 14px; }
.account-card.flush .set-head { padding: 14px 16px; border-bottom: 1px solid var(--hairline); margin-bottom: 0; }
.set-title { font-size: 13.5px; font-weight: 500; color: var(--text-high); display: flex; align-items: center; gap: 9px; }
.set-hint { font-size: 11.5px; color: var(--text-faint); }

/* Profile head: initials avatar + name + email */
.set-profile { display: flex; align-items: center; gap: 13px; margin-bottom: 14px; }
.set-profile .avatar {
    width: 44px;
    height: 44px;
    flex: none;
    border-radius: 50%;
    background: #1c1c1f;
    border: 1px solid var(--hairline-strong);
    display: grid;
    place-items: center;
    font-family: var(--mono);
    font-size: 14.5px;
    color: var(--text-body);
}
.set-profile .who { min-width: 0; }
.set-profile .who .nm { font-size: 14.5px; color: var(--text-high); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.set-profile .who .em { font-family: var(--mono); font-size: 12px; color: var(--text-muted); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* In-card forms: stacked fields, actions bottom-right */
.set-form { display: flex; flex-direction: column; gap: 12px; }
.set-form .pair { display: grid; grid-template-columns: 1fr 1fr; gap: 11px; }
.set-note { font-size: 11.5px; color: var(--text-faint); line-height: 1.55; }
.set-actions { display: flex; justify-content: flex-end; gap: 8px; }
.set-error { font-size: 12px; color: var(--danger); line-height: 1.5; }
.set-error[hidden] { display: none; }

/* A label row that carries a small action on the right ("Change…") */
.field .label-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 7px; }
.field .label-row label { margin-bottom: 0; }
.field .label-row .mini-link { font-size: 11.5px; color: var(--accent); cursor: pointer; }
.field .label-row .mini-link:hover { color: var(--accent-hover); }

/* Read-only field look: same box, sunk and muted */
.field input[readonly] { color: var(--text-faint); border-color: var(--hairline); font-family: var(--mono); font-size: 12.5px; }
.field input[readonly]:focus { border-color: var(--hairline); box-shadow: none; }

/* Connected accounts rows */
.id-row { display: flex; align-items: center; gap: 12px; padding: 13px 16px; border-bottom: 1px solid #191a1b; }
.id-row:last-child { border-bottom: none; }
.id-row .logo {
    width: 30px;
    height: 30px;
    flex: none;
    border-radius: 8px;
    background: var(--surface);
    border: 1px solid var(--hairline-strong);
    display: grid;
    place-items: center;
    color: var(--text-body);
}
.id-row .who { flex: 1; min-width: 0; }
.id-row .who .nm { font-size: 13px; color: var(--text-high); }
.id-row .who .em { font-family: var(--mono); font-size: 11.5px; color: var(--text-muted); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.id-row .who .off { font-size: 11.5px; color: var(--text-faint); margin-top: 2px; }

/* The last-way-in warning under the identity list */
.warn-line { display: flex; align-items: flex-start; gap: 9px; padding: 0 16px 14px; font-size: 12px; color: #e5c98a; line-height: 1.55; }
.warn-line svg { flex: none; margin-top: 1px; color: var(--amber); }

/* Sessions table: no header, four columns, current marked */
.sess-table { width: 100%; table-layout: fixed; font-size: 12.5px; border-collapse: collapse; }
.sess-table td { height: 40px; padding: 0 8px; border-bottom: 1px solid #191a1b; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sess-table tr:last-child td { border-bottom: none; }
.sess-table td:first-child { padding-left: 16px; color: var(--text-body); }
.sess-table td.ip, .sess-table td.seen { font-family: var(--mono); font-size: 12px; color: var(--text-muted); }
.sess-table td.seen { color: var(--text-faint); }
.sess-table td.act { padding-right: 16px; text-align: right; width: 76px; }
.sess-table td.ip { width: 118px; }
.sess-table td.seen { width: 96px; }
.sess-table .current { font-size: 11.5px; color: var(--green); }
.sess-table .revoke { font-size: 11.5px; color: var(--danger); cursor: pointer; }
.sess-table .revoke:hover { text-decoration: underline; }
.sess-empty { padding: 18px 16px; font-size: 12.5px; color: var(--text-faint); }

/* Email-change modal: code input next to its send/countdown button */
.code-row { display: flex; gap: 8px; }
.code-row input { flex: 1; min-width: 0; }
.code-row .btn { flex: none; }

/* ---- Public site: frame --------------------------------------------------- */
/* The anonymous marketing/reference pages (landing, models, docs, status,
   terms, privacy). Same token system; the frame is the canvas's public
   shell — 56px top bar, content, 56px footer. */

.pub-shell { min-height: 100vh; display: flex; flex-direction: column; }

.pub-nav {
    height: 56px; flex: none;
    border-bottom: 1px solid var(--hairline);
    display: flex; align-items: center; justify-content: space-between;
    padding: 0 32px;
}

.pub-logo { display: inline-flex; align-items: center; gap: 9px; text-decoration: none; }
.pub-logo .mark {
    width: 22px; height: 22px; border-radius: 6px; background: var(--accent);
    display: inline-flex; align-items: center; justify-content: center;
}
.pub-logo .name { font-size: 14.5px; font-weight: 600; color: var(--text); letter-spacing: -0.01em; }
/* The product half is muted, same as the console lockup — one wordmark,
   not two */
.pub-logo .name span { color: var(--text-muted); font-weight: 400; }

.pub-nav-links { display: flex; align-items: center; gap: 22px; }
.pub-nav-links > a { font-size: 13px; color: var(--text-muted); text-decoration: none; transition: color .12s; }
.pub-nav-links > a:hover { color: var(--text-body); }
.pub-nav-links > a.active { color: var(--text); }
.pub-nav-links > a.pub-signin { color: var(--text-body); }
.pub-nav-links > a.pub-signin:hover { color: var(--text); }
.pub-nav-divider { width: 1px; height: 18px; background: var(--hairline); }

.pub-cta, .pub-nav-links > a.pub-cta {
    display: inline-flex; align-items: center; height: 30px; padding: 0 13px;
    border-radius: 6px; background: var(--accent-solid); color: #fff;
    font-size: 12.5px; font-weight: 500; text-decoration: none;
    transition: filter .12s;
}
.pub-cta:hover { filter: brightness(1.1); }

.pub-main { flex: 1; display: flex; flex-direction: column; }

.pub-foot {
    height: 56px; flex: none;
    border-top: 1px solid var(--hairline); background: var(--surface-sunk);
    display: flex; align-items: center; justify-content: space-between;
    padding: 0 32px;
}
.pub-foot-note { font-family: var(--mono); font-size: 11.5px; color: #4d5157; }
.pub-foot-links { display: flex; align-items: center; gap: 18px; }
.pub-foot-links a { font-size: 12.5px; color: var(--text-faint); text-decoration: none; }
.pub-foot-links a:hover { color: var(--text-muted); }

/* ---- Public site: landing hero -------------------------------------------- */

.pub-hero {
    flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
    padding: 132px 32px 140px; gap: 22px; text-align: center;
}
.pub-hero h1 {
    margin: 0; font-size: 46px; font-weight: 600; letter-spacing: -0.038em; line-height: 1.08;
    color: var(--text); max-width: 800px;
}
.pub-hero .sub { margin: 0; font-size: 16px; line-height: 1.6; color: var(--text-muted); max-width: 540px; }

.pub-live {
    display: flex; align-items: center; gap: 10px; margin-top: 2px;
    font-family: var(--mono); font-size: 12px; color: var(--text-faint);
    text-decoration: none; transition: color .12s;
}
.pub-live:hover { color: var(--text-muted); }
.pub-live .sep { color: var(--hairline-strong); }

.pub-hero-ctas { display: flex; gap: 10px; margin-top: 14px; }
.pub-btn-primary {
    display: inline-flex; align-items: center; height: 38px; padding: 0 18px;
    border-radius: 7px; background: var(--accent-solid); color: #fff;
    font-size: 13.5px; font-weight: 500; text-decoration: none; transition: filter .12s;
}
.pub-btn-primary:hover { filter: brightness(1.1); }
.pub-btn-ghost {
    display: inline-flex; align-items: center; height: 38px; padding: 0 18px;
    border-radius: 7px; border: 1px solid var(--hairline-strong); background: var(--surface-raised);
    color: var(--text-body); font-size: 13.5px; text-decoration: none; transition: border-color .12s;
}
.pub-btn-ghost:hover { border-color: rgba(255, 255, 255, .26); }

@media (max-width: 720px) {
    .pub-hero { padding: 72px 24px 80px; }
    .pub-hero h1 { font-size: 34px; }
    .pub-nav, .pub-foot { padding: 0 20px; }
    .pub-foot { flex-direction: column; height: auto; padding: 14px 20px; gap: 8px; }
}

/* ---- Public site: content pages ------------------------------------------- */

.pub-page { width: 100%; max-width: 1180px; margin: 0 auto; padding: 36px 32px 64px; }

.pub-page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 18px; margin-bottom: 20px; flex-wrap: wrap; }
.pub-page-head h1 { margin: 0 0 7px; font-size: 28px; font-weight: 600; letter-spacing: -0.025em; color: var(--text); }
.pub-page-head .sub { font-size: 13.5px; color: var(--text-muted); }
.pub-page-tools { display: flex; gap: 8px; align-items: center; }

.pub-search { position: relative; }
.pub-search svg { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: var(--text-faint); pointer-events: none; }
.pub-search input {
    width: 260px; height: 34px; padding: 0 10px 0 30px;
    background: var(--surface-sunk); border: 1px solid rgba(255, 255, 255, .12); border-radius: 8px;
    color: var(--text); font-size: 12.5px; font-family: inherit; outline: none;
    transition: border-color .12s;
}
.pub-search input:focus { border-color: rgba(130, 143, 255, .5); }
.pub-search input::placeholder { color: var(--text-faint); }

/* Endpoint-surface tags on the public models table */
.pub-tag {
    display: inline-flex; align-items: center; height: 19px; padding: 0 6px;
    border-radius: 4px; border: 1px solid var(--hairline-strong);
    color: var(--text-muted); font-size: 11px; font-family: var(--mono);
}
.pub-tag + .pub-tag { margin-left: 5px; }
/* Same reasoning as .pill-lower: the Accepted column stays quiet */
.pub-tag-lower { text-transform: lowercase; }

/* ---- Public site: status --------------------------------------------------- */

.pub-status-head { display: flex; align-items: center; gap: 11px; margin-bottom: 20px; }
.pub-status-head h1 { margin: 0; font-size: 28px; font-weight: 600; letter-spacing: -0.025em; color: var(--text); }
.pub-status-head .updated { margin-left: auto; font-family: var(--mono); font-size: 11.5px; color: var(--text-faint); }

.pub-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.pub-dot.ok { background: var(--green); box-shadow: 0 0 0 4px rgba(109, 199, 139, .16); }
.pub-dot.bad { background: var(--amber); box-shadow: 0 0 0 4px rgba(206, 163, 74, .16); }

.pub-band-card {
    background: var(--surface-raised); border: 1px solid var(--hairline); border-radius: 8px;
    padding: 16px 18px; display: flex; flex-direction: column; gap: 11px; margin-bottom: 20px;
}
.pub-band-head { display: flex; align-items: center; justify-content: space-between; }
.pub-band-head .t { font-size: 13px; color: var(--text); }
.pub-band-head .pct { font-family: var(--mono); font-size: 11.5px; color: var(--green); }
.pub-band { display: flex; gap: 3px; }
.pub-band span { flex: 1; height: 32px; border-radius: 3px; background: var(--hairline); }
.pub-band span.ok { background: rgba(109, 199, 139, .75); }
.pub-band span.warn { background: rgba(206, 163, 74, .8); }
.pub-band span.bad { background: rgba(235, 87, 87, .8); }
.pub-band-scale { display: flex; justify-content: space-between; font-family: var(--mono); font-size: 10.5px; color: #4d5157; }

.pub-endpoints .head { padding: 11px 16px; border-bottom: 1px solid var(--hairline); font-size: 13px; color: var(--text); }
.pub-state {
    display: inline-flex; align-items: center; gap: 5px; height: 20px; padding: 0 7px;
    border-radius: 5px; font-size: 11.5px;
}
.pub-state .d { width: 5px; height: 5px; border-radius: 50%; }
.pub-state.ok { background: rgba(109, 199, 139, .12); border: 1px solid rgba(109, 199, 139, .28); color: var(--green); }
.pub-state.ok .d { background: var(--green); }
.pub-state.bad { background: rgba(206, 163, 74, .12); border: 1px solid rgba(206, 163, 74, .28); color: var(--amber); }
.pub-state.bad .d { background: var(--amber); }

/* ---- Public site: docs ------------------------------------------------------ */

.pub-docs { display: flex; align-items: stretch; flex: 1; width: 100%; max-width: 1180px; margin: 0 auto; }

.pub-docs-nav {
    width: 236px; flex: none; border-right: 1px solid var(--hairline);
    padding: 24px 16px; display: flex; flex-direction: column; gap: 2px;
    /* One long page — the nav stays put and tracks the reader's section */
    position: sticky; top: 0; align-self: flex-start;
    max-height: 100vh; overflow-y: auto;
}
.pub-docs-nav .grp {
    font-size: 11.5px; color: var(--text-faint); letter-spacing: .05em; text-transform: uppercase;
    padding: 14px 8px 5px;
}
.pub-docs-nav .grp:first-child { padding-top: 0; }
.pub-docs-nav .itm { display: block; padding: 5px 8px; border-radius: 5px; font-size: 13px; }
.pub-docs-nav a.itm { color: var(--text-body); text-decoration: none; }
.pub-docs-nav a.itm:hover { color: var(--text); }
.pub-docs-nav .itm.active { background: var(--accent-soft); color: var(--accent); }
/* Entries that exist in the plan but not yet as pages — visibly parked */
.pub-docs-nav span.itm { color: var(--text-faint); cursor: default; }

.pub-docs-body {
    flex: 1; min-width: 0; padding: 32px 40px 64px; max-width: 900px;
    display: flex; flex-direction: column; gap: 26px;
}
.pub-docs-body .eyebrow {
    font-family: var(--mono); font-size: 11.5px; color: var(--accent);
    letter-spacing: .1em; text-transform: uppercase;
}
.pub-docs-body h1 { margin: 7px 0 9px; font-size: 28px; font-weight: 600; letter-spacing: -0.025em; color: var(--text); }
.pub-docs-body .lede { margin: 0; font-size: 14px; line-height: 1.65; color: var(--text-muted); }

/* One anchored section of the single docs page */
.pub-doc {
    display: flex; flex-direction: column; gap: 22px;
    padding-top: 26px; border-top: 1px solid var(--hairline);
    scroll-margin-top: 20px;
}
.pub-doc-title { margin: 0; font-size: 20px; font-weight: 600; letter-spacing: -0.02em; color: var(--text); }
.pub-doc-lede { margin: -12px 0 0; font-size: 13.5px; line-height: 1.65; color: var(--text-muted); }

.pub-doc-sec { display: flex; flex-direction: column; gap: 11px; }
.pub-doc-sec > h3 { margin: 0; font-size: 15.5px; font-weight: 500; color: var(--text); }
.pub-doc-sec > p { margin: 0; font-size: 13.5px; line-height: 1.65; color: var(--text-muted); }
.pub-doc-sec code, .pub-inline-code { font-family: var(--mono); font-size: .95em; color: var(--text-body); }

.pub-code { border: 1px solid var(--hairline); border-radius: 9px; overflow: hidden; background: var(--surface-sunk); }
.pub-code-bar {
    display: flex; align-items: center; justify-content: space-between;
    background: var(--surface-raised); border-bottom: 1px solid var(--hairline); padding: 0 12px;
}
.pub-code-tabs { display: flex; }
.pub-code-tabs button {
    padding: 10px 13px; background: none; border: 0; cursor: pointer;
    font-family: inherit; font-size: 12.5px; color: var(--text-muted);
    border-bottom: 1.5px solid transparent; margin-bottom: -1px;
}
.pub-code-tabs button.active { color: var(--text); border-bottom-color: var(--accent); }
.pub-copy {
    display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 9px;
    border-radius: 5px; border: 1px solid var(--hairline-strong); background: #1c1c1f;
    color: var(--text-muted); font-size: 11.5px; font-family: inherit; cursor: pointer;
}
.pub-copy:hover { color: var(--text-body); }

.pub-pre {
    margin: 0; padding: 14px 16px; overflow-x: auto;
    font-family: var(--mono); font-size: 12.5px; line-height: 1.85; color: var(--text-muted);
    white-space: pre;
}
.pub-pre .hl { color: var(--text-body); background: rgba(130, 143, 255, .07); box-shadow: -16px 0 0 rgba(130, 143, 255, .07), 16px 0 0 rgba(130, 143, 255, .07); }
.pub-pre[hidden] { display: none; }

.pub-kv {
    display: flex; flex-direction: column; gap: 7px; padding: 13px 14px;
    border-radius: 8px; background: var(--surface-sunk); border: 1px solid var(--hairline);
    font-family: var(--mono); font-size: 12.5px; color: var(--text-body);
}

.pub-err-pre {
    margin: 0; border-radius: 8px; background: var(--surface-sunk); border: 1px solid var(--hairline);
    padding: 14px 16px; font-family: var(--mono); font-size: 12.5px; color: var(--text-muted);
    line-height: 1.8; white-space: pre-wrap; overflow-x: auto;
}

.pub-chips { display: flex; gap: 7px; flex-wrap: wrap; }
.pub-chip {
    display: inline-flex; align-items: center; height: 22px; padding: 0 8px;
    border-radius: 5px; font-size: 11.5px; font-family: var(--mono);
}
.pub-chip.blue { background: rgba(94, 160, 239, .12); border: 1px solid rgba(94, 160, 239, .28); color: var(--blue); }
.pub-chip.amber { background: rgba(206, 163, 74, .12); border: 1px solid rgba(206, 163, 74, .28); color: var(--amber); }
.pub-chip.red { background: rgba(235, 87, 87, .12); border: 1px solid rgba(235, 87, 87, .28); color: var(--danger); }

@media (max-width: 860px) {
    .pub-docs { flex-direction: column; }
    .pub-docs-nav { width: 100%; border-right: 0; border-bottom: 1px solid var(--hairline); padding: 16px; }
    .pub-docs-body { padding: 24px 20px 48px; }
}

/* ---- Public site: legal ----------------------------------------------------- */

.pub-legal { width: 100%; max-width: 760px; margin: 0 auto; padding: 48px 32px 80px; }
.pub-legal .eyebrow {
    font-family: var(--mono); font-size: 11.5px; color: var(--accent);
    letter-spacing: .1em; text-transform: uppercase;
}
.pub-legal h1 { margin: 7px 0 9px; font-size: 28px; font-weight: 600; letter-spacing: -0.025em; color: var(--text); }
.pub-legal .lede { margin: 0 0 4px; font-size: 14px; line-height: 1.65; color: var(--text-muted); }
.pub-legal .meta { font-family: var(--mono); font-size: 11.5px; color: var(--text-faint); }
.pub-legal h2 { margin: 34px 0 10px; font-size: 15.5px; font-weight: 500; color: var(--text); }
.pub-legal p { margin: 0 0 12px; font-size: 13.5px; line-height: 1.7; color: var(--text-muted); }
.pub-legal a { color: var(--accent); text-decoration: none; }
.pub-legal a:hover { color: var(--accent-hover); }

/* ---- Public site: docs code tokens ---------------------------------------- */
/* Painted by /static/js/public/docs.js over pre[data-lang] text nodes.
   Restrained four-hue scheme; the default code ink stays muted so the
   colored tokens carry the structure. */

.tok-k { color: var(--violet); }      /* keyword / flag / literal */
.tok-s { color: var(--green); }       /* string */
.tok-c { color: var(--text-faint); }  /* comment */
.tok-n { color: var(--amber); }       /* number */
.tok-p { color: var(--blue); }        /* property / header name */

/* Single-snippet code blocks: a static label where quickstart has tabs */
.pub-code-label { padding: 10px 13px; font-size: 12.5px; color: var(--text-faint); font-family: var(--mono); }

/* ---- Public site: column widths ------------------------------------------- */
/* The CSP (default-src 'self') blocks style attributes, so colgroup widths
   live here, per table. */

#pm-table col:nth-child(1) { width: 30%; }
#pm-table col:nth-child(2) { width: 12%; }
#pm-table col:nth-child(3) { width: 10%; }
#pm-table col:nth-child(4) { width: 13%; }
#pm-table col:nth-child(5) { width: 13%; }
#pm-table col:nth-child(6) { width: 22%; }

.pub-endpoints col:nth-child(1) { width: 50%; }
.pub-endpoints col:nth-child(2) { width: 25%; }
.pub-endpoints col:nth-child(3) { width: 25%; }

.tbl-endpoints col:nth-child(1) { width: 44%; }
.tbl-endpoints col:nth-child(2) { width: 14%; }
.tbl-endpoints col:nth-child(3) { width: 42%; }

.tbl-limits col:nth-child(1) { width: 12%; }
.tbl-limits col:nth-child(2) { width: 32%; }
.tbl-limits col:nth-child(3) { width: 56%; }

.tbl-retention col:nth-child(1) { width: 36%; }
.tbl-retention col:nth-child(2) { width: 30%; }
.tbl-retention col:nth-child(3) { width: 34%; }
