      /* ══════════════════════════════════════════════════════════════════════════════════════
         Design tokens.

         Light is the default because this is a dashboard people keep open all day next to
         Stripe and a terminal, and because every value below has to clear 4.5:1 on white —
         the old glass-on-black theme hid low-contrast text behind blur and looked fine only
         because nothing had to be read carefully.

         Dark is a real second theme, not an inversion: it follows the OS by default and can
         be pinned from the settings popover. Both are defined on :root so a token always has
         a value even if a media query never matches.
         ══════════════════════════════════════════════════════════════════════════════════ */
      :root {
        --bg: #f6f7f9;
        /* Text ON the accent fill. Flips with the theme because the accent itself does:
           a deep emerald in light mode wants white, the bright emerald in dark wants ink.
           A TOKEN, not a theme-scoped `button` rule — that rule out-specified .ghost,
           .link and .nav-item and painted the whole sidebar near-black in dark mode. */
        --on-accent: #ffffff;
        --surface: #ffffff;
        --surface-2: #fafbfc;
        --surface-3: #f2f4f7;
        --border: #e4e8ee;
        --border-2: #d3dae3;
        --ink: #12172b;
        --ink-2: #45506b;
        --dim: #6b7688;
        --accent: #0b8f6a;
        --accent-hi: #0a7f5e;
        --accent-soft: #e8f6f1;
        --accent-brd: #b7e2d3;
        --danger: #c0392b;
        --danger-soft: #fdeceb;
        --danger-brd: #f3c4c0;
        --warn: #9a5b00;
        --warn-soft: #fff6e6;
        --warn-brd: #f0d9a8;
        --info-soft: #eef2ff;
        --shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.06);
        --shadow: 0 2px 8px rgba(16, 24, 40, 0.07), 0 1px 2px rgba(16, 24, 40, 0.05);
        --shadow-lg: 0 12px 32px rgba(16, 24, 40, 0.14);
        --radius: 10px;
        --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, monospace;
        --sidebar-w: 244px;

        /* The minimum comfortable touch target. Applied under `pointer: coarse` only — a
           44px-tall Refresh button is correct on a phone and absurd next to a mouse. */
        --tap: 44px;

        /* Safe-area insets, named once so every rule below reads as intent rather than as
           four repetitions of a function call. Every use is wrapped in `max()` against the
           design padding rather than added to it — adding would double the padding on a
           plain desktop window, where the insets are legitimately 0.

           They are declared as literal `0px` HERE and only promoted to `env()` inside the
           `@supports` block below. That indirection is load-bearing, not stylistic: a
           declaration containing `var()` that resolves to something invalid is "invalid at
           computed-value time", which does NOT fall back to an earlier declaration the way
           an ordinary invalid value does — it falls back to unset. So had `--sat` been
           `env(...)` directly, an engine that does not know `env()` would not merely lose
           the inset, it would compute `padding: var(--sat) …` to nothing and strip the
           padding off the topbar, the content and the sign-in screen. This way `var(--sat)`
           is always a valid length and the insets are a pure enhancement. */
        --sat: 0px;
        --sar: 0px;
        --sab: 0px;
        --sal: 0px;
      }

      @supports (padding: env(safe-area-inset-top)) {
        :root {
          --sat: env(safe-area-inset-top);
          --sar: env(safe-area-inset-right);
          --sab: env(safe-area-inset-bottom);
          --sal: env(safe-area-inset-left);
        }
      }

      @media (prefers-color-scheme: dark) {
        :root:not([data-theme="light"]) {
          --bg: #0c1012;
          --on-accent: #06231a;
          --surface: #141a1d;
          --surface-2: #171e21;
          --surface-3: #1d2529;
          --border: #253036;
          --border-2: #32414a;
          --ink: #e8eef0;
          --ink-2: #b3c1c6;
          --dim: #8a9aa1;
          --accent: #34d399;
          --accent-hi: #6ee7b7;
          --accent-soft: rgba(52, 211, 153, 0.12);
          --accent-brd: rgba(52, 211, 153, 0.32);
          --danger: #f87171;
          --danger-soft: rgba(248, 113, 113, 0.12);
          --danger-brd: rgba(248, 113, 113, 0.34);
          --warn: #fbbf24;
          --warn-soft: rgba(251, 191, 36, 0.12);
          --warn-brd: rgba(251, 191, 36, 0.32);
          --info-soft: rgba(99, 102, 241, 0.12);
          --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
          --shadow: 0 2px 10px rgba(0, 0, 0, 0.45);
          --shadow-lg: 0 16px 40px rgba(0, 0, 0, 0.6);
        }
      }
      :root[data-theme="dark"] {
        --bg: #0c1012;
        --on-accent: #06231a;
        --surface: #141a1d;
        --surface-2: #171e21;
        --surface-3: #1d2529;
        --border: #253036;
        --border-2: #32414a;
        --ink: #e8eef0;
        --ink-2: #b3c1c6;
        --dim: #8a9aa1;
        --accent: #34d399;
        --accent-hi: #6ee7b7;
        --accent-soft: rgba(52, 211, 153, 0.12);
        --accent-brd: rgba(52, 211, 153, 0.32);
        --danger: #f87171;
        --danger-soft: rgba(248, 113, 113, 0.12);
        --danger-brd: rgba(248, 113, 113, 0.34);
        --warn: #fbbf24;
        --warn-soft: rgba(251, 191, 36, 0.12);
        --warn-brd: rgba(251, 191, 36, 0.32);
        --info-soft: rgba(99, 102, 241, 0.12);
        --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
        --shadow: 0 2px 10px rgba(0, 0, 0, 0.45);
        --shadow-lg: 0 16px 40px rgba(0, 0, 0, 0.6);
      }

      * { box-sizing: border-box; }
      html, body { height: 100%; }
      body {
        margin: 0;
        font: 14px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, "Helvetica Neue", Arial, sans-serif;
        color: var(--ink);
        background: var(--bg);
        -webkit-font-smoothing: antialiased;
        /* iOS paints a grey box over every tapped control for ~300ms. Removing it is only
           safe because every interactive element below has a real :active state. */
        -webkit-tap-highlight-color: transparent;
        /* No rubber-band bounce past the ends of the page — the tell that this is a web
           page in a browser rather than an app. Scrolling WITHIN a pane is untouched. */
        overscroll-behavior-y: none;
      }

      /* Honour the OS setting. Everything below animates for polish, nothing for meaning,
         so all of it can stop without losing information. */
      @media (prefers-reduced-motion: reduce) {
        *, *::before, *::after {
          animation-duration: 0.01ms !important;
          animation-iteration-count: 1 !important;
          transition-duration: 0.01ms !important;
          scroll-behavior: auto !important;
        }
      }

      /* Never let a focus ring be invisible because a container clips it. */
      :focus-visible { outline: none; }
      a { color: var(--accent); text-decoration: none; }
      a:hover { text-decoration: underline; }
      .hidden { display: none !important; }
      .mono { font-family: var(--mono); font-size: 0.94em; }
      .muted { color: var(--dim); }
      .row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
      .spread { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }

      /* ── Controls ───────────────────────────────────────────────────────────────────── */
      input, select {
        background: var(--surface);
        border: 1px solid var(--border-2);
        color: var(--ink);
        border-radius: 8px;
        padding: 9px 11px;
        font: inherit;
        outline: none;
        width: 100%;
        transition: border-color 0.12s, box-shadow 0.12s;
      }
      input::placeholder { color: var(--dim); }
      input:focus, select:focus {
        border-color: var(--accent);
        box-shadow: 0 0 0 3px var(--accent-soft);
      }
      input.key, input.mono { font-family: var(--mono); }
      label.field { display: block; margin-bottom: 12px; }
      label.field > span {
        display: block; font-size: 12px; font-weight: 600; color: var(--ink-2);
        margin-bottom: 5px; letter-spacing: 0.1px;
      }

      button {
        background: var(--accent);
        color: var(--on-accent);
        border: 1px solid var(--accent);
        border-radius: 8px;
        padding: 9px 15px;
        font: inherit;
        font-weight: 600;
        cursor: pointer;
        transition: background 0.12s, border-color 0.12s, box-shadow 0.12s, transform 0.04s;
        white-space: nowrap;
      }
      button:hover { background: var(--accent-hi); border-color: var(--accent-hi); }
      button:focus-visible { box-shadow: 0 0 0 3px var(--accent-soft); outline: none; }
      button:active { transform: translateY(0.5px); }
      button:disabled { opacity: 0.55; cursor: not-allowed; transform: none; }

      button.ghost {
        background: var(--surface); color: var(--ink-2); border-color: var(--border-2); font-weight: 600;
      }
      button.ghost:hover { background: var(--surface-3); border-color: var(--border-2); color: var(--ink); }
      button.danger {
        background: transparent; color: var(--danger); border-color: var(--danger-brd); font-weight: 600;
      }
      button.danger:hover { background: var(--danger-soft); border-color: var(--danger); }
      button.sm { padding: 5px 11px; font-size: 12.5px; border-radius: 7px; }
      button.wide { width: 100%; justify-content: center; }
      button.link {
        background: none; border: none; color: var(--accent); padding: 0; font-weight: 600;
      }
      button.link:hover { background: none; text-decoration: underline; color: var(--accent-hi); }

      /* ── Touch ergonomics ───────────────────────────────────────────────────────────────
         Keyed on `pointer: coarse`, NOT on viewport width. A phone in landscape is a wide
         viewport that still has a thumb on it, and a narrow desktop window is a narrow
         viewport that still has a mouse — width answers the wrong question.

         Two things happen here and they are unrelated except in cause:

         1. Every control reaches 44×44. `.sm` buttons were 27px tall, `.icon-btn` 34px,
            and `.nav-item` ~34px, which is fine under a cursor and a coin-flip under a
            thumb. `min-height` rather than `height` so a wrapped label still fits.

         2. Inputs go to 16px. Below 16px, iOS Safari ZOOMS THE PAGE on focus and does not
            zoom back out — the viewport is then wider than the layout for the rest of the
            session, which reads as a broken app. 16px is the threshold, not a preference. */
      @media (pointer: coarse) {
        button, .nav-item, .seg button, .theme-seg button, .icon-btn {
          min-height: var(--tap);
        }
        button, .icon-btn { min-width: var(--tap); }
        button.sm { padding: 10px 14px; font-size: 13.5px; }
        button.link { min-height: var(--tap); min-width: 0; display: inline-flex; align-items: center; }
        .icon-btn { width: var(--tap); height: var(--tap); }
        input, select, textarea { font-size: 16px; min-height: var(--tap); }
        /* Inline links inside prose get a bigger hit area without disturbing line flow. */
        .card-body a, .notice a { padding: 4px 0; }
      }

      /* ── Auth screen ────────────────────────────────────────────────────────────────── */
      /* `100dvh` is the *dynamic* viewport height — it tracks mobile browser chrome as the
         address bar collapses and expands. `100vh` on iOS is the LARGEST height the viewport
         ever takes, so a `min-height: 100vh` sign-in screen is always taller than the visible
         area and the page scrolls when it has nothing to scroll to. The `100vh` line stays
         first as the fallback for engines without `dvh`. */
      .auth-screen {
        min-height: 100vh;
        min-height: 100dvh;
        display: grid; place-items: center;
        padding:
          max(32px, var(--sat)) max(20px, var(--sar))
          max(32px, var(--sab)) max(20px, var(--sal));
        background:
          radial-gradient(680px 340px at 50% -8%, var(--accent-soft), transparent 70%),
          var(--bg);
      }
      .auth-box { width: 100%; max-width: 424px; }
      .auth-brand { display: flex; align-items: center; gap: 11px; justify-content: center; margin-bottom: 22px; }
      .logo {
        width: 34px; height: 34px; border-radius: 9px; display: grid; place-items: center;
        background: var(--accent); color: var(--on-accent); font-weight: 800; font-size: 17px; flex: none;
      }
      .auth-brand b { font-size: 16px; letter-spacing: -0.1px; }

      .auth-card {
        background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
        padding: 26px 26px 22px; box-shadow: var(--shadow);
      }
      .auth-card h1 { margin: 0 0 4px; font-size: 19px; letter-spacing: -0.2px; }
      .auth-card .sub { color: var(--dim); font-size: 13.5px; margin: 0 0 20px; }

      /* Segmented audience switch — the two HUMAN doors. The API key is not here on
         purpose: it is a machine credential, and giving it equal billing is what made the
         old screen read as three coequal logins. */
      .seg {
        display: grid; grid-template-columns: 1fr 1fr; gap: 3px; padding: 3px;
        background: var(--surface-3); border: 1px solid var(--border); border-radius: 9px;
        margin-bottom: 20px;
      }
      .seg button {
        background: none; border: 1px solid transparent; color: var(--dim);
        font-size: 13px; font-weight: 600; padding: 7px 8px; border-radius: 7px;
      }
      .seg button:hover { background: none; color: var(--ink); border-color: transparent; }
      .seg button.on {
        background: var(--surface); color: var(--ink); border-color: var(--border);
        box-shadow: var(--shadow-sm);
      }

      .auth-foot {
        margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--border);
        display: flex; align-items: center; justify-content: space-between; gap: 10px;
        font-size: 12.5px; color: var(--dim); flex-wrap: wrap;
      }
      .code-sent {
        background: var(--accent-soft); border: 1px solid var(--accent-brd); color: var(--ink-2);
        border-radius: 8px; padding: 9px 11px; font-size: 12.5px; margin-bottom: 14px;
      }
      #authCode { letter-spacing: 6px; text-align: center; font-size: 17px; font-family: var(--mono); }

      /* ── App shell ──────────────────────────────────────────────────────────────────── */
      .shell {
        display: grid; grid-template-columns: var(--sidebar-w) 1fr;
        min-height: 100vh;
        min-height: 100dvh;
      }

      .sidebar {
        background: var(--surface); border-right: 1px solid var(--border);
        display: flex; flex-direction: column; position: sticky; top: 0;
        height: 100vh;
        height: 100dvh;
        padding-left: var(--sal);
      }
      .side-brand {
        display: flex; align-items: center; gap: 10px;
        padding: max(16px, var(--sat)) 18px 16px;
        border-bottom: 1px solid var(--border);
      }
      .side-brand b { font-size: 14.5px; letter-spacing: -0.1px; display: block; }
      .side-brand .env { font-size: 11.5px; color: var(--dim); }

      nav.side-nav { padding: 12px 10px; overflow-y: auto; flex: 1; }
      .nav-label {
        font-size: 11px; font-weight: 700; letter-spacing: 0.6px; text-transform: uppercase;
        color: var(--dim); padding: 10px 10px 6px;
      }
      .nav-item {
        display: flex; align-items: center; gap: 10px; width: 100%;
        background: none; border: 1px solid transparent; color: var(--ink-2);
        padding: 8px 10px; border-radius: 8px; font-size: 13.5px; font-weight: 500;
        cursor: pointer; text-align: left; margin-bottom: 2px;
      }
      .nav-item:hover { background: var(--surface-3); color: var(--ink); border-color: transparent; }
      .nav-item.active {
        background: var(--accent-soft); color: var(--accent); border-color: var(--accent-brd); font-weight: 600;
      }
      .nav-item svg { width: 16px; height: 16px; flex: none; opacity: 0.85; }

      .side-foot {
        border-top: 1px solid var(--border);
        padding: 12px 12px max(12px, var(--sab));
      }
      .acct {
        display: flex; align-items: center; gap: 9px; padding: 8px 9px; border-radius: 9px;
        background: var(--surface-2); border: 1px solid var(--border); margin-bottom: 9px;
      }
      .acct .who { min-width: 0; flex: 1; }
      .acct .who .k { font-size: 12.5px; font-weight: 600; }
      .acct .who .v {
        font-size: 11.5px; color: var(--dim); font-family: var(--mono);
        overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
      }
      .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--border-2); flex: none; }
      .dot.on { background: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
      .dot.admin { background: var(--warn); box-shadow: 0 0 0 3px var(--warn-soft); }
      .roletag { font-size: 11px; font-weight: 700; letter-spacing: 0.3px; text-transform: uppercase; }

      .main { min-width: 0; display: flex; flex-direction: column; }
      /* The bar is sticky, so its padding — not a spacer above it — has to carry the notch:
         a spacer would scroll away and let the title slide under the status bar. */
      .topbar {
        position: sticky; top: 0; z-index: 20;
        display: flex; align-items: center; gap: 12px;
        padding: var(--sat) max(24px, var(--sar)) 0 max(24px, var(--sal));
        min-height: calc(57px + var(--sat));
        background: var(--surface); border-bottom: 1px solid var(--border);
      }
      .topbar h1 { margin: 0; font-size: 16px; font-weight: 650; letter-spacing: -0.15px; margin-right: auto; }
      .icon-btn {
        background: none; border: 1px solid var(--border-2); color: var(--ink-2);
        width: 34px; height: 34px; border-radius: 8px; display: grid; place-items: center; padding: 0;
      }
      .icon-btn:hover { background: var(--surface-3); border-color: var(--border-2); color: var(--ink); }
      .icon-btn svg { width: 16px; height: 16px; }
      #sidebarToggle { display: none; }

      /* The bottom inset is padding rather than margin so the last card can still be scrolled
         clear of the home indicator instead of sitting permanently underneath it. */
      .content {
        padding: 24px max(24px, var(--sar)) max(24px, calc(24px + var(--sab))) max(24px, var(--sal));
        max-width: 1120px; width: 100%;
      }

      /* ── Cards & tables ─────────────────────────────────────────────────────────────── */
      .card {
        background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
        box-shadow: var(--shadow-sm); margin-bottom: 18px; overflow: hidden;
      }
      .card > .card-head {
        display: flex; align-items: center; justify-content: space-between; gap: 12px;
        padding: 14px 18px; border-bottom: 1px solid var(--border); background: var(--surface-2);
        flex-wrap: wrap;
      }
      .card > .card-head h2 {
        margin: 0; font-size: 13.5px; font-weight: 650; letter-spacing: -0.05px; color: var(--ink);
        text-transform: none;
      }
      .card > .card-head .hint { font-size: 12.5px; color: var(--dim); font-weight: 400; }
      .card > .card-body { padding: 18px; }
      .card > .card-body.tight { padding: 0; }
      .card h2 { font-size: 13.5px; }
      .sub-head {
        font-size: 12px; font-weight: 700; letter-spacing: 0.5px; text-transform: uppercase;
        color: var(--dim); margin: 0 0 12px;
      }

      table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
      th {
        text-align: left; color: var(--dim); font-weight: 600; font-size: 11.5px;
        text-transform: uppercase; letter-spacing: 0.4px; padding: 10px 18px;
        background: var(--surface-2); border-bottom: 1px solid var(--border); white-space: nowrap;
      }
      td { padding: 12px 18px; border-top: 1px solid var(--border); vertical-align: middle; }
      tbody tr:first-child td { border-top: none; }
      tbody tr:hover td { background: var(--surface-2); }
      tr.sel td { background: var(--accent-soft) !important; }
      td.mono, th.r { font-family: var(--mono); }
      .scroll { overflow-x: auto; }
      .empty { color: var(--dim); padding: 22px 18px; font-size: 13.5px; text-align: center; }
      td .empty, .card-body > .empty { text-align: left; padding: 14px 0; }

      /* ── Badges ─────────────────────────────────────────────────────────────────────── */
      .badge {
        display: inline-block; padding: 2.5px 9px; border-radius: 999px;
        font-size: 11.5px; font-weight: 650; letter-spacing: 0.1px; border: 1px solid transparent;
      }
      .badge.plan { background: var(--info-soft); color: var(--ink-2); border-color: var(--border-2); }
      .badge.active { background: var(--accent-soft); color: var(--accent); border-color: var(--accent-brd); }
      .badge.paused, .badge.deploying, .badge.past_due, .badge.none {
        background: var(--warn-soft); color: var(--warn); border-color: var(--warn-brd);
      }
      .badge.archived, .badge.halted, .badge.canceled, .badge.revoked {
        background: var(--danger-soft); color: var(--danger); border-color: var(--danger-brd);
      }

      /* ── Stats, plans, banners ──────────────────────────────────────────────────────── */
      .stat { font-family: var(--mono); font-size: 27px; font-weight: 700; letter-spacing: -0.5px; }
      .metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 14px; }
      .metric {
        border: 1px solid var(--border); border-radius: 10px; padding: 14px 16px; background: var(--surface-2);
      }
      .metric .k { font-size: 12px; color: var(--dim); font-weight: 600; margin-bottom: 4px; }

      .plans { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; }
      .plan {
        border: 1px solid var(--border); border-radius: 11px; padding: 16px; text-align: center;
        background: var(--surface-2);
      }
      .plan.current { border-color: var(--accent); background: var(--accent-soft); }
      .plan .name { font-weight: 650; font-size: 14px; }
      .plan .price { font-family: var(--mono); font-size: 21px; margin: 6px 0 2px; font-weight: 700; }
      .plan .q { font-size: 12.5px; color: var(--dim); }
      .plan .cap { font-size: 11.5px; color: var(--dim); margin: 6px 0 10px; }

      .banner {
        display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap;
        padding: 14px 16px; border-radius: 11px; margin-bottom: 18px;
        background: var(--warn-soft); border: 1px solid var(--warn-brd);
      }
      .banner .lead { font-weight: 700; color: var(--warn); }
      .reveal {
        margin-top: 14px; padding: 14px; border: 1px solid var(--warn-brd);
        border-radius: 10px; background: var(--warn-soft);
      }
      .reveal .warn { color: var(--warn); font-size: 12.5px; }
      .caphint {
        margin-bottom: 14px; padding: 11px 13px; border-radius: 9px;
        background: var(--warn-soft); border: 1px solid var(--warn-brd); color: var(--warn); font-size: 13px;
      }
      code.url { word-break: break-all; font-size: 12.5px; font-family: var(--mono); }

      /* ── Forms in cards ─────────────────────────────────────────────────────────────── */
      form.inline { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
      form.inline .full { grid-column: 1 / -1; }
      form.inline button { grid-column: 1 / -1; justify-self: start; padding: 9px 18px; }
      @media (max-width: 720px) { form.inline { grid-template-columns: 1fr; } }
      .form-sep { border-top: 1px solid var(--border); margin: 18px 0 0; padding-top: 18px; }

      /* ── Settings popover ───────────────────────────────────────────────────────────── */
      .pop-back { position: fixed; inset: 0; z-index: 60; background: rgba(16, 24, 40, 0.25); }
      .pop {
        position: fixed; z-index: 61; top: 64px; right: 24px; width: 320px;
        background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
        box-shadow: var(--shadow-lg); padding: 16px;
      }
      .pop h3 { margin: 0 0 14px; font-size: 13.5px; font-weight: 650; }
      .pop .note { font-size: 11.5px; color: var(--dim); margin-top: 5px; line-height: 1.45; }
      .theme-seg { display: grid; grid-template-columns: repeat(3, 1fr); gap: 3px; padding: 3px;
        background: var(--surface-3); border: 1px solid var(--border); border-radius: 8px; }
      .theme-seg button {
        background: none; border: 1px solid transparent; color: var(--dim);
        font-size: 12.5px; font-weight: 600; padding: 6px 4px; border-radius: 6px;
      }
      .theme-seg button:hover { background: none; color: var(--ink); }
      .theme-seg button.on { background: var(--surface); color: var(--ink); border-color: var(--border); }

      .toast {
        position: fixed;
        right: max(20px, calc(20px + var(--sar)));
        left: max(20px, calc(20px + var(--sal)));
        bottom: max(20px, calc(20px + var(--sab)));
        max-width: 380px; margin-left: auto; z-index: 80;
        background: var(--surface); border: 1px solid var(--border-2); border-radius: 10px;
        padding: 12px 15px; box-shadow: var(--shadow-lg); color: var(--ink); font-size: 13.5px;
        opacity: 0; transform: translateY(10px); transition: opacity 0.18s, transform 0.18s;
        pointer-events: none;
      }
      .toast.show { opacity: 1; transform: none; }
      .toast.err { border-color: var(--danger); color: var(--danger); background: var(--danger-soft); }

      /* ── Notices ────────────────────────────────────────────────────────────────────────
         One component, three tones. Used wherever this console has to state a limitation of
         the deployment rather than render data — which it does a lot, on purpose. */
      .notice {
        border: 1px solid var(--border-2); background: var(--surface-2); color: var(--ink-2);
        border-radius: 10px; padding: 13px 15px; font-size: 13px; line-height: 1.55;
      }
      .notice + .notice { margin-top: 12px; }
      .notice .lead { font-weight: 700; color: var(--ink); display: block; margin-bottom: 4px; }
      .notice.warn { background: var(--warn-soft); border-color: var(--warn-brd); }
      .notice.warn .lead { color: var(--warn); }
      .notice.bad { background: var(--danger-soft); border-color: var(--danger-brd); }
      .notice.bad .lead { color: var(--danger); }
      .notice code { font-family: var(--mono); font-size: 0.92em; word-break: break-all; }

      /* ── The control-plane reachability strip ───────────────────────────────────────────
         A static console served by Caddy renders perfectly while the API behind it is dead —
         the failure that looks like success. This is the only element on the page that is
         allowed to appear without any data behind it, because its entire job is to say that
         there is no data behind anything else. */
      .api-strip {
        position: sticky; top: 0; z-index: 40;
        padding: max(10px, calc(10px + var(--sat))) 16px 10px;
        background: var(--danger-soft); border-bottom: 1px solid var(--danger-brd);
        color: var(--danger); font-size: 12.5px; font-weight: 600;
        display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
      }
      .api-strip .detail { font-weight: 400; color: var(--ink-2); font-family: var(--mono); font-size: 11.5px; }
      .api-strip button { margin-left: auto; }

      /* ── Key/value list (profile, getting started) ──────────────────────────────────── */
      .kv { display: grid; grid-template-columns: minmax(120px, auto) 1fr; gap: 10px 18px; font-size: 13.5px; }
      .kv dt { color: var(--dim); font-weight: 600; font-size: 12.5px; }
      .kv dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
      @media (max-width: 560px) { .kv { grid-template-columns: 1fr; gap: 2px 0; } .kv dd { margin-bottom: 10px; } }

      /* ── Copyable code block ────────────────────────────────────────────────────────────
         `pre` scrolls on its own axis rather than wrapping: a curl command broken across
         lines at arbitrary points is a command that does not survive being pasted. */
      .snippet { position: relative; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-3); }
      .snippet pre {
        margin: 0; padding: 14px 15px; overflow-x: auto; font-family: var(--mono);
        font-size: 12.5px; line-height: 1.6; color: var(--ink);
      }
      .snippet .copy { position: absolute; top: 8px; right: 8px; }
      .snippet + .snippet { margin-top: 12px; }
      .snippet-label { font-size: 12px; font-weight: 600; color: var(--ink-2); margin: 16px 0 7px; }
      .snippet-label:first-child { margin-top: 0; }

      /* ── Modal dialogs ──────────────────────────────────────────────────────────────────
         Used for the two moments a native `confirm()` is not good enough: revealing a key
         that is shown once, and revoking one. On a phone this docks to the bottom, in thumb
         reach, rather than floating in the middle where the reach is worst. */
      .scrim {
        position: fixed; inset: 0; z-index: 90; background: rgba(16, 24, 40, 0.45);
        display: grid; place-items: center; padding: 20px;
        overscroll-behavior: contain;
      }
      .dialog {
        background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
        box-shadow: var(--shadow-lg); width: 100%; max-width: 460px;
        max-height: calc(100dvh - 40px); overflow-y: auto;
        padding: 22px;
      }
      .dialog h2 { margin: 0 0 6px; font-size: 16px; letter-spacing: -0.15px; }
      .dialog .sub { margin: 0 0 16px; color: var(--dim); font-size: 13px; line-height: 1.55; }
      .dialog .actions { display: flex; gap: 10px; margin-top: 18px; flex-wrap: wrap; }
      .dialog .actions button { flex: 1 1 auto; }
      @media (max-width: 560px) {
        .scrim { place-items: end center; padding: 0; }
        .dialog {
          max-width: none; border-radius: 16px 16px 0 0; border-bottom: none;
          padding: 20px 18px max(20px, calc(20px + var(--sab)));
          max-height: 92dvh;
        }
        .dialog .actions { flex-direction: column-reverse; }
      }

      /* The reveal-once key itself. Big, monospaced, selectable, and given its own box so
         "this is the thing to copy" needs no explaining. */
      .secret {
        font-family: var(--mono); font-size: 13px; line-height: 1.6; word-break: break-all;
        background: var(--surface-3); border: 1px solid var(--border-2); border-radius: 9px;
        padding: 13px 14px; user-select: all; -webkit-user-select: all;
      }
      .ack {
        display: flex; align-items: flex-start; gap: 10px; margin-top: 16px;
        font-size: 13px; color: var(--ink-2); cursor: pointer; line-height: 1.5;
      }
      .ack input { width: 20px; height: 20px; min-height: 0; flex: none; margin-top: 1px; accent-color: var(--accent); }

      /* ── Responsive ─────────────────────────────────────────────────────────────────── */
      @media (max-width: 900px) {
        .shell { grid-template-columns: 1fr; }
        .sidebar {
          position: fixed; z-index: 70; left: 0; top: 0; width: min(270px, 84vw);
          transform: translateX(-100%); transition: transform 0.2s; box-shadow: var(--shadow-lg);
          padding-left: 0;
        }
        .sidebar.open { transform: none; }
        #sidebarToggle { display: grid; }
        .content {
          padding: 18px max(16px, var(--sar)) max(18px, calc(18px + var(--sab))) max(16px, var(--sal));
        }
        .topbar { padding: var(--sat) max(16px, var(--sar)) 0 max(16px, var(--sal)); }

        /* The drawer previously opened over the page with nothing behind it: no way to
           dismiss it except finding the same 44px button again, and the content underneath
           still took taps. */
        .nav-scrim {
          position: fixed; inset: 0; z-index: 69; background: rgba(16, 24, 40, 0.4);
        }

        /* The settings popover becomes a bottom sheet — a 320px card pinned to the top-right
           corner is the least reachable place on a phone. */
        .pop {
          top: auto; bottom: 0; left: 0; right: 0; width: auto;
          border-radius: 16px 16px 0 0;
          padding: 18px 18px max(18px, calc(18px + var(--sab)));
          max-height: 90dvh; overflow-y: auto;
        }
      }
    