/* SDLV Telemetry Hub — standalone dark theme (self-contained; no dependency on the demo CSS). */
:root{
  --bg:#0e1116; --panel:#161b22; --panel2:#1c2230; --ink:#e6edf3; --dim:#8b98a5;
  --line:#2a313c; --line2:#38404d; --accent:#4c9ffe; --accent-dim:#2b4a6f;
  --critical:#e85a6a; --warning:#f0993a; --ok:#4bd0a0; --info:#6ea8fe;
  --r:8px; --r-sm:5px;
}
*{box-sizing:border-box}
html,body{margin:0;height:100%}
body{background:var(--bg);color:var(--ink);font:14px/1.5 system-ui,-apple-system,Segoe UI,Roboto,sans-serif}
a{color:var(--accent);text-decoration:none} a:hover{text-decoration:underline}

/* ── top bar ── */
/* Header wraps the tab row instead of scrolling it — every tab (Published, Keys,
   Users…) stays visible; the ugly horizontal scrollbar is gone. Brand + who keep
   their own line; the tabs flow between them and push the header taller if needed. */
.hub-top{display:flex;align-items:center;gap:16px;padding:7px 16px;min-height:52px;background:var(--panel);border-bottom:1px solid var(--line);position:sticky;top:0;z-index:5}
.brand{font-weight:700;letter-spacing:.3px;white-space:nowrap;flex:none}
.brand span{color:var(--accent);font-weight:600}
.tabs{display:flex;gap:2px;flex:1;flex-wrap:wrap;overflow:visible}
.tabs button{background:none;border:0;color:var(--dim);padding:6px 10px;border-radius:var(--r-sm);cursor:pointer;font:inherit;white-space:nowrap;display:flex;align-items:center;gap:6px}
.tabs button:hover{color:var(--ink);background:var(--panel2)}
.tabs button.active{color:var(--ink);background:var(--accent-dim)}
.tabs .pill{background:var(--critical);color:#fff;border-radius:10px;font-size:11px;padding:0 6px;min-width:18px;text-align:center;font-weight:600}
.tabs .pill.neutral{background:var(--accent-dim);color:var(--info)}
.tabs .pill.zero{background:var(--line2);color:var(--dim)}
.who{color:var(--dim);font-size:13px;white-space:nowrap;flex:none;margin-left:auto}
/* Thin, unobtrusive scrollbars everywhere (was: chunky default bars on the tab row
   and tables). */
.hub-main,.wrap-scroll,.drawer{scrollbar-width:thin;scrollbar-color:var(--line2) transparent}
::-webkit-scrollbar{width:9px;height:9px}
::-webkit-scrollbar-thumb{background:var(--line2);border-radius:5px}
::-webkit-scrollbar-thumb:hover{background:var(--dim)}
::-webkit-scrollbar-track{background:transparent}

/* ── main ── */
.hub-main{padding:16px;max-width:1500px;margin:0 auto}
.toolbar{display:flex;gap:8px;align-items:center;margin-bottom:12px;flex-wrap:wrap}
.toolbar input[type=search],.toolbar select{background:var(--panel);border:1px solid var(--line2);color:var(--ink);border-radius:var(--r-sm);padding:6px 9px;font:inherit}
/* Segmented control (Published: Patterns / KB / Disk rules) */
.seg{display:inline-flex;border:1px solid var(--line2);border-radius:var(--r-sm);overflow:hidden}
.seg button{background:var(--panel);border:0;border-left:1px solid var(--line2);color:var(--dim);padding:6px 11px;cursor:pointer;font:inherit;font-size:13px}
.seg button:first-child{border-left:0}
.seg button:hover{color:var(--ink);background:var(--panel2)}
.seg button.on{background:var(--accent-dim);color:var(--ink)}
.toolbar input[type=search]{min-width:240px}
.toolbar .spacer{flex:1}
.toolbar .count{color:var(--dim);font-size:13px}

/* ── table ── */
.tbl{width:100%;border-collapse:collapse;background:var(--panel);border:1px solid var(--line);border-radius:var(--r);overflow:hidden}
.tbl th,.tbl td{padding:8px 10px;text-align:left;border-bottom:1px solid var(--line);vertical-align:top}
/* Header sticks to the top of its OWN scroll container (.wrap-scroll), not the
   viewport — offsetting by the 52px top bar (whose scroll parent this isn't)
   dropped the header down over the first data row. z-index + shadow keep it
   above the rows and legible once pinned. */
.tbl th{color:var(--dim);font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.4px;cursor:default;background:var(--panel2);position:sticky;top:0;z-index:2;box-shadow:inset 0 -1px 0 var(--line2)}
.tbl tbody tr:hover{background:var(--panel2)}
.tbl tbody tr.click{cursor:pointer}
.tbl td.mono,.mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12.5px}
.tbl .num{text-align:right;font-variant-numeric:tabular-nums}
/* Vertical scroll on the wrapper too, so the sticky header has something to
   pin against and long lists don't push the toolbar off-screen. */
.wrap-scroll{overflow:auto;border-radius:var(--r);max-height:calc(100vh - 150px)}

/* ── badges / chips ── */
.badge{display:inline-block;padding:1px 7px;border-radius:10px;font-size:11px;font-weight:600;line-height:1.6;white-space:nowrap}
.badge.crit{background:rgba(232,90,106,.16);color:var(--critical);border:1px solid rgba(232,90,106,.4)}
.badge.warn{background:rgba(240,153,58,.16);color:var(--warning);border:1px solid rgba(240,153,58,.4)}
.badge.ok{background:rgba(75,208,160,.16);color:var(--ok);border:1px solid rgba(75,208,160,.4)}
.badge.info{background:rgba(110,168,254,.16);color:var(--info);border:1px solid rgba(110,168,254,.4)}
.badge.mut{background:var(--panel2);color:var(--dim);border:1px solid var(--line2)}
.chip{display:inline-block;background:var(--panel2);border:1px solid var(--line2);color:var(--dim);border-radius:var(--r-sm);padding:0 6px;font-size:11px;margin:1px 2px 1px 0}

/* ── buttons ── */
button.btn,a.btn{display:inline-flex;align-items:center;gap:5px;background:var(--panel2);border:1px solid var(--line2);color:var(--ink);border-radius:var(--r-sm);padding:6px 11px;cursor:pointer;font:inherit;text-decoration:none;line-height:1.3}
button.btn:hover,a.btn:hover{border-color:var(--accent);color:#fff;text-decoration:none}
button.btn.primary,a.btn.primary{background:var(--accent-dim);border-color:var(--accent);color:#fff}
button.btn.danger:hover{border-color:var(--critical);color:var(--critical)}
button.btn.sm,a.btn.sm{padding:3px 8px;font-size:12px}
button.btn:disabled{opacity:.45;cursor:not-allowed}

/* ── pagination ── */
.pager{display:flex;gap:6px;align-items:center;justify-content:center;margin:14px 0;color:var(--dim)}

/* ── drawer ── */
.drawer{position:fixed;top:0;right:0;width:min(680px,94vw);height:100%;background:var(--panel);border-left:1px solid var(--line2);box-shadow:-8px 0 30px rgba(0,0,0,.4);z-index:20;overflow-y:auto}
.drawer-inner{padding:18px}
.drawer h2{margin:.2em 0 .1em;font-size:17px}
.drawer .close{position:absolute;top:12px;right:14px}
.kv{display:grid;grid-template-columns:130px 1fr;gap:2px 12px;margin:12px 0;font-size:13px}
.kv dt{color:var(--dim)} .kv dd{margin:0;word-break:break-word}
pre.block{background:#0a0d12;border:1px solid var(--line);border-radius:var(--r-sm);padding:10px;overflow:auto;font-family:ui-monospace,Consolas,monospace;font-size:12px;max-height:340px;white-space:pre-wrap;word-break:break-word}
.section-h{color:var(--dim);text-transform:uppercase;font-size:11px;letter-spacing:.5px;margin:16px 0 6px;border-top:1px solid var(--line);padding-top:12px}
.actions{display:flex;gap:8px;flex-wrap:wrap;margin:14px 0}

/* ── misc ── */
.empty{color:var(--dim);text-align:center;padding:40px}
.samples{font-family:ui-monospace,Consolas,monospace;font-size:11.5px;color:var(--dim)}
.toast{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);background:var(--panel2);border:1px solid var(--accent);color:var(--ink);padding:10px 16px;border-radius:var(--r);z-index:40;box-shadow:0 6px 20px rgba(0,0,0,.4)}

/* ── login ── */
.hub-login{display:grid;place-items:center;min-height:100vh}
.login-card{background:var(--panel);border:1px solid var(--line2);border-radius:12px;padding:28px;width:320px;display:flex;flex-direction:column;gap:12px}
.login-brand{font-weight:700;font-size:18px;text-align:center;margin-bottom:4px}
.login-brand span{color:var(--accent)}
.login-card label{display:flex;flex-direction:column;gap:4px;font-size:13px;color:var(--dim)}
.login-card input{background:var(--bg);border:1px solid var(--line2);color:var(--ink);border-radius:var(--r-sm);padding:9px}
.login-card button{background:var(--accent-dim);border:1px solid var(--accent);color:#fff;border-radius:var(--r-sm);padding:10px;cursor:pointer;font:inherit;font-weight:600}
.login-err{background:rgba(232,90,106,.16);border:1px solid var(--critical);color:var(--critical);border-radius:var(--r-sm);padding:8px;font-size:13px;text-align:center}
.login-foot{color:var(--dim);font-size:11px;text-align:center;margin-top:4px}

/* ══ Keys panel ══════════════════════════════════════════════════════════════
   An access key is a credential with a lifecycle, so it reads as an object, not
   just a table cell: a masked mono token, two capability pills (what it may do),
   a live on/off switch, and its last contact. The reveal card is the one loud
   moment — the only time the full secret is ever shown. */

/* Masked key token in the table. */
.keytok{font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:12.5px;color:var(--ink);background:var(--bg);border:1px solid var(--line);border-radius:var(--r-sm);padding:2px 7px;letter-spacing:.3px}

/* Capability pills — colour-coded by what the scope grants (blue=send, green=receive). */
.scope{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:600;border-radius:10px;padding:1px 8px;line-height:1.7;white-space:nowrap;margin-right:4px}
.scope.on-ingest{background:rgba(110,168,254,.14);color:var(--info);border:1px solid rgba(110,168,254,.4)}
.scope.on-updates{background:rgba(75,208,160,.14);color:var(--ok);border:1px solid rgba(75,208,160,.4)}
.scope.off{background:var(--panel2);color:var(--dim);border:1px solid var(--line2);text-decoration:line-through;text-decoration-color:var(--line2)}

/* Enable/disable switch. */
.tgl{--w:34px;position:relative;display:inline-block;width:var(--w);height:18px;flex:none;cursor:pointer;vertical-align:middle}
.tgl input{position:absolute;opacity:0;width:100%;height:100%;margin:0;cursor:pointer}
.tgl .track{position:absolute;inset:0;background:var(--line2);border-radius:9px;transition:background .15s}
.tgl .track::after{content:"";position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;background:#cdd6e0;transition:transform .15s}
.tgl input:checked + .track{background:var(--ok)}
.tgl input:checked + .track::after{transform:translateX(16px);background:#fff}
.tgl input:focus-visible + .track{outline:2px solid var(--accent);outline-offset:2px}

/* A disabled (revoked) key row reads as dimmed. */
.tbl tbody tr.revoked td{opacity:.5}
.tbl tbody tr.revoked td .tgl,.tbl tbody tr.revoked td .btn{opacity:1}

.key-meta{color:var(--dim);font-size:11.5px}
.key-meta b{color:var(--ink);font-weight:600}

/* ── the one-time secret reveal (drawer) ── */
.reveal{background:linear-gradient(180deg,var(--panel2),var(--panel));border:1px solid var(--accent);border-radius:var(--r);padding:18px;margin:6px 0 4px}
.reveal .rl-eyebrow{color:var(--accent);font-size:11px;font-weight:700;letter-spacing:1px;text-transform:uppercase;margin-bottom:10px}
.reveal .rl-secret{display:flex;gap:8px;align-items:stretch}
.reveal .rl-secret code{flex:1;font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:15px;color:#fff;background:var(--bg);border:1px solid var(--line2);border-radius:var(--r-sm);padding:11px 12px;word-break:break-all;user-select:all}
.reveal .rl-warn{display:flex;gap:8px;align-items:flex-start;margin-top:12px;color:var(--warning);font-size:12.5px;line-height:1.5}
.reveal .rl-warn svg{flex:none;margin-top:1px}

/* ── new-key form (drawer) ── */
/* Only the top-level field labels are the small-caps eyebrow style. The scope
   options are ALSO <label>s nested in .keyform, so scope everything below to the
   FORM FIELD labels via > and reset case on the option text — otherwise the
   uppercase/letter-spacing bleeds onto "Send data / push telemetry…". */
.keyform > label{display:block;margin:14px 0 5px;color:var(--dim);font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.4px}
.keyform input[type=text]{width:100%;background:var(--bg);border:1px solid var(--line2);color:var(--ink);border-radius:var(--r-sm);padding:9px 10px;font:inherit}
.scope-picker{display:flex;flex-direction:column;gap:8px;margin-top:4px}
.scope-opt{display:flex;gap:10px;align-items:flex-start;background:var(--panel2);border:1px solid var(--line2);border-radius:var(--r-sm);padding:10px 12px;cursor:pointer;text-transform:none;letter-spacing:normal}
.scope-opt:hover{border-color:var(--accent)}
.scope-opt input{margin:2px 0 0;flex:none}
.scope-opt > span{display:flex;flex-direction:column}
.scope-opt .so-t{font-weight:600;font-size:13px;color:var(--ink)}
.scope-opt .so-d{color:var(--dim);font-size:12px;margin-top:2px}
