:root{
  /* Light Universum theme (matches the console apps). */
  --bg:#f6f7fb; --bg2:#eef1f8; --panel:#ffffff; --panel2:#ffffff;
  --line:#e6e9f2; --line2:#dfe3ee;
  --txt:#1d2233; --muted:#5b6473; --dim:#8891a4;
  --blue:#2B3086; --violet:#4560E6; --cyan:#2B3086; --green:#0E9F6E; --amber:#B45309; --red:#D20A11;
  --grad:linear-gradient(90deg,#2B3086 0%,#4560E6 100%);
  --sans:-apple-system,BlinkMacSystemFont,"SF Pro Text","Segoe UI",Inter,Roboto,"Helvetica Neue",Arial,sans-serif;
  --mono:ui-monospace,"SF Mono","Cascadia Code","Segoe UI Mono",Consolas,Menlo,monospace;
  color-scheme:light;
}
/* Dark Universum theme, driven by /universum/theme.js (html.dark + data-theme, see .docker/nginx.conf).
   Token values match the DS dark palette: surfaces #0f1117/#151823/#1a1e2b/#20253a, text
   #f1f3f9/#d5d9e6, muted #9aa3b8, borders #262b3d/#323853, accent red #ff5a60, brand blue #6b7cff.
   Every rule below already reads these custom properties, so redefining them here re-themes the
   whole site — only a handful of literal (non-token) colors need their own html.dark overrides,
   further down. body-text/bg contrast: #f1f3f9 on #0f1117 = 17.0:1 (verified, ≥ 4.5:1). */
html.dark{
  --bg:#0f1117; --bg2:#151823; --panel:#1a1e2b; --panel2:#20253a;
  --line:#262b3d; --line2:#323853;
  --txt:#f1f3f9; --muted:#d5d9e6; --dim:#9aa3b8;
  --blue:#6b7cff; --violet:#8b98ff; --cyan:#6b7cff; --green:#34d399; --amber:#fbbf24; --red:#ff5a60;
  --grad:linear-gradient(90deg,#6b7cff 0%,#8b98ff 100%);
  color-scheme:dark;
}
*{box-sizing:border-box;margin:0;padding:0}
html,body{min-height:100%}
body{font-family:var(--sans);background:var(--bg);color:var(--txt);line-height:1.55;
  background-image:radial-gradient(1100px 600px at 85% -10%,rgba(69,96,230,.06),transparent 60%),
                  radial-gradient(900px 500px at -10% 110%,rgba(43,48,134,.05),transparent 60%);}
::selection{background:rgba(139,92,246,.4)}
a{color:var(--cyan);text-decoration:none}
code{font-family:var(--mono);font-size:.92em}

/* ---------- gate de login ---------- */
#gate{position:fixed;inset:0;z-index:100;display:flex;align-items:center;justify-content:center;padding:24px;background:var(--bg)}
#gate[hidden]{display:none}
.gate-card{max-width:440px;width:100%;text-align:center}
.gate-card .bolt{font-size:40px;filter:drop-shadow(0 0 12px rgba(251,191,36,.5))}
.gate-card h1{font-size:30px;font-weight:800;margin:14px 0 6px}
.gate-card h1 .g{background:var(--grad);-webkit-background-clip:text;background-clip:text;color:transparent}
.gate-card p{color:var(--muted);margin-bottom:26px;font-size:14.5px}
.gate-card .err{color:var(--red);font-size:13px;margin-top:14px;min-height:18px}
.btn-ms{display:inline-flex;align-items:center;gap:10px;background:var(--grad);color:#fff;font-weight:800;
  border:none;border-radius:11px;padding:13px 26px;font-size:15px;cursor:pointer;box-shadow:0 8px 24px rgba(43,48,134,.22)}
.btn-ms:hover{filter:brightness(1.05)}
.gate-card .hint{margin-top:22px;font-size:12px;color:var(--dim)}

/* ---------- topbar ---------- */
#top{position:sticky;top:0;z-index:40;height:60px;display:flex;align-items:center;justify-content:space-between;
  padding:0 22px;border-bottom:1px solid var(--line);background:rgba(255,255,255,.9);backdrop-filter:blur(8px)}
#top .brand{display:flex;align-items:center;gap:12px;min-width:0}
#top .brand a{display:flex;align-items:center;gap:12px;color:inherit}
#top .bolt{font-size:22px}
#top h2{font-size:16px;font-weight:800}
#top h2 .g{background:var(--grad);-webkit-background-clip:text;background-clip:text;color:transparent}
#top .sub{font-size:11px;color:var(--dim)}
#top .apps{display:flex;align-items:center;gap:4px;margin-left:18px}
#top .apps a{padding:6px 12px;border-radius:8px;font-size:13px;font-weight:500;color:var(--muted)}
#top .apps a:hover{background:rgba(0,0,0,.045);color:var(--txt)}
#top .apps a.on{background:rgba(210,10,17,.08);color:#D20A11;font-weight:600}
#top .right{display:flex;align-items:center;gap:12px;font-size:12.5px;color:var(--muted);margin-left:auto}
#top .sn-mark{display:inline-block;flex:none;width:27px;height:18px;background:url(/universum/assets/logos/spaceneedle.png) no-repeat;background-size:84px auto;background-position:-28px -7px}
#top .user{font-family:var(--mono);font-size:11.5px;background:var(--panel);border:1px solid var(--line);border-radius:999px;padding:6px 13px}
#top .out{background:none;border:1px solid var(--line);color:var(--muted);border-radius:8px;padding:6px 12px;font-size:12px;cursor:pointer}
#top .out:hover{border-color:var(--violet);color:var(--txt)}

/* ---------- hub ---------- */
.wrap{max-width:1180px;margin:0 auto;padding:5vh 5vw 12vh}
.hero{margin-bottom:18px}
.hero .kick{font-size:12px;letter-spacing:.3em;text-transform:uppercase;color:var(--cyan);font-weight:700}
.hero h1{font-size:clamp(30px,4.6vw,52px);font-weight:800;letter-spacing:-.02em;margin-top:10px}
.hero h1 .g{background:var(--grad);-webkit-background-clip:text;background-clip:text;color:transparent}
.hero p{color:var(--muted);max-width:70ch;margin-top:14px;font-size:15px}
.searchbar{margin-top:22px;display:flex;gap:10px;flex-wrap:wrap;align-items:center}
.searchbar input{flex:1;min-width:220px;background:var(--bg2);border:1px solid var(--line2);border-radius:10px;color:var(--txt);padding:11px 14px;font-size:14px;font-family:var(--sans)}
.searchbar input:focus{outline:none;border-color:var(--cyan)}

.sec{margin-top:42px}
.sec h3{font-size:13px;letter-spacing:.18em;text-transform:uppercase;color:var(--violet);font-weight:700;margin-bottom:16px;display:flex;align-items:center;gap:12px}
.sec h3::after{content:"";flex:1;height:1px;background:linear-gradient(90deg,rgba(167,139,250,.35),transparent)}
.grid{display:grid;gap:14px;grid-template-columns:repeat(3,1fr)}
.grid.feat{grid-template-columns:1fr}
@media(max-width:900px){.grid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:580px){.grid,#top{}.grid{grid-template-columns:1fr}}

.card{display:block;background:var(--panel);border:1px solid var(--line);border-radius:16px;padding:18px 20px;position:relative;overflow:hidden;transition:border-color .18s,background .18s,transform .12s}
.card::before{content:"";position:absolute;top:0;left:0;right:0;height:2px;background:var(--grad);opacity:.5}
.card:hover{border-color:var(--violet);background:var(--panel2);transform:translateY(-2px)}
.card .top{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:6px}
.card h4{font-size:clamp(15px,1.3vw,18px);font-weight:700}
.card.feat h4{font-size:clamp(20px,2.2vw,26px)}
.card p{font-size:13px;color:var(--muted);line-height:1.5}
.ver{font-family:var(--mono);font-size:11px;font-weight:700;white-space:nowrap;border-radius:999px;padding:3px 10px;
  color:#BAE6FD;background:rgba(56,189,248,.1);border:1px solid rgba(56,189,248,.22)}
.ver.pre{color:var(--amber);background:rgba(251,191,36,.1);border-color:rgba(251,191,36,.28)}
.ver.stub{color:var(--muted);background:rgba(148,163,184,.1);border-color:rgba(148,163,184,.25)}
.links{display:flex;gap:8px;flex-wrap:wrap;margin-top:13px}
.chip{font-size:12px;border-radius:8px;padding:6px 11px;border:1px solid var(--line);color:var(--txt);background:var(--panel);cursor:pointer;transition:border-color .15s,background .15s}
.chip:hover{border-color:var(--cyan);background:var(--panel2)}
.chip.deck{border-color:rgba(139,92,246,.35)}
.chip.md{border-color:rgba(56,189,248,.25)}
.chip .c{color:var(--dim);font-family:var(--mono);font-size:10px;margin-left:5px}
.mdlist{margin-top:12px;display:flex;flex-direction:column;gap:5px}
.mdlist a{font-size:12.5px;color:var(--muted);padding:4px 0;display:flex;align-items:center;gap:8px}
.mdlist a:hover{color:var(--cyan)}
.mdlist a .raw{margin-left:auto;font-size:10.5px;color:var(--dim);font-family:var(--mono);border:1px solid var(--line);border-radius:6px;padding:1px 6px}
.mdlist a .raw:hover{color:var(--cyan);border-color:var(--cyan)}
.empty{font-size:12.5px;color:var(--dim);font-style:italic}

.foot{margin-top:54px;padding-top:22px;border-top:1px solid var(--line);font-size:12px;color:var(--dim);line-height:1.7}
.foot code{color:#BAE6FD}
.foot a{border-bottom:1px dotted rgba(34,211,238,.4)}

/* ---------- viewer de markdown ---------- */
.doc{max-width:920px;margin:0 auto;padding:4vh 5vw 14vh}
.doc .crumbs{font-size:12.5px;color:var(--dim);margin-bottom:8px}
.doc .crumbs a{color:var(--muted)}
.doc .toolbar{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:6px 0 26px;padding-bottom:16px;border-bottom:1px solid var(--line)}
.doc .toolbar .raw{font-size:12.5px;border:1px solid var(--line);border-radius:8px;padding:7px 13px;color:var(--muted)}
.doc .toolbar .raw:hover{border-color:var(--cyan);color:var(--txt)}
.md{font-size:15.5px;line-height:1.72}
.md h1{font-size:clamp(26px,3.4vw,36px);font-weight:800;letter-spacing:-.015em;margin:8px 0 18px}
.md h2{font-size:clamp(21px,2.4vw,27px);font-weight:800;margin:34px 0 12px;padding-bottom:8px;border-bottom:1px solid var(--line)}
.md h3{font-size:19px;font-weight:700;margin:26px 0 10px;color:#cfe0f5}
.md h4{font-size:16px;font-weight:700;margin:20px 0 8px;color:var(--muted)}
.md p{margin:12px 0}
.md a{border-bottom:1px dotted rgba(34,211,238,.45)}
.md strong{color:#fff;font-weight:700}
.md em{color:#cfe0f5}
.md ul,.md ol{margin:12px 0 12px 26px}
.md li{margin:5px 0}
.md blockquote{border-left:3px solid var(--violet);background:rgba(139,92,246,.06);margin:16px 0;padding:10px 16px;color:var(--muted);border-radius:0 8px 8px 0}
.md hr{border:none;border-top:1px solid var(--line);margin:28px 0}
.md code{background:rgba(56,189,248,.09);border:1px solid rgba(56,189,248,.16);border-radius:5px;padding:.08em .4em;color:#BAE6FD;font-size:.9em}
.md pre{background:#070b14;border:1px solid var(--line2);border-radius:10px;padding:14px 16px;overflow:auto;margin:16px 0}
.md pre code{background:none;border:none;padding:0;color:#cbd5e1;font-size:13px;line-height:1.6}
.md table{width:100%;border-collapse:collapse;margin:16px 0;font-size:13.5px;display:block;overflow-x:auto}
.md th,.md td{border:1px solid var(--line);padding:8px 12px;text-align:left;vertical-align:top}
.md th{background:var(--panel);font-weight:700;color:#cfe0f5}
.md tr:nth-child(even) td{background:rgba(255,255,255,.015)}
.md img{max-width:100%;border-radius:10px;border:1px solid var(--line)}
.md .err{color:var(--red)}

@media(max-width:760px){
  #top{padding:0 14px}
  #top .sub{display:none}
  .wrap{padding:4vh 5vw 12vh}
}

/* ---------- theme toggle (header, next to .sn-mark) ---------- */
#top .theme-toggle{display:inline-flex;align-items:center;justify-content:center;flex:none;
  width:30px;height:30px;border-radius:8px;border:1px solid var(--line);background:none;color:var(--muted);
  cursor:pointer;transition:border-color .15s,color .15s,background-color .15s}
#top .theme-toggle:hover{border-color:var(--violet);color:var(--txt);background:rgba(0,0,0,.03)}
#top .theme-toggle svg{width:16px;height:16px;display:block}

/* ---------- dark-mode overrides for literal (non-token) colors ---------- */
/* Everything else in this file reads var(--bg)/--panel/--txt/etc., already re-themed by the
   html.dark token block up top. These are the few rules that hardcode a color instead. */
html.dark ::selection{background:rgba(107,124,255,.45);color:#f1f3f9}

html.dark #top{background:rgba(15,17,23,.88)}
html.dark #top .apps a:hover{background:rgba(255,255,255,.06)}
/* The active app-switcher pill (Docs, in the "apps" nav) — light theme washes it with the brand
   red at 8% opacity; the dark equivalent needs a stronger wash to read against the dark topbar. */
html.dark #top .apps a.on{background:rgba(255,90,96,.16);color:#ff5a60}
html.dark #top .theme-toggle:hover{background:rgba(255,255,255,.06)}
/* .sn-mark is a fixed-color PNG sprite (not a currentColor mask), so it can go invisible against
   a dark topbar regardless of its own ink color — give it a light backing chip instead of trying
   to recolor the bitmap. */
html.dark #top .sn-mark{background-color:#f1f3f9;border-radius:4px}

html.dark .btn-ms{box-shadow:0 8px 24px rgba(0,0,0,.45)}
