/* ===================================================================
   qNet Web Shell — shared theme + base styles
   Court (default) · Ember · Frost
   =================================================================== */

/* Display serif — self-hosted so every machine renders the same, screen-legible
   type (no Mac-only fonts falling back to Times on Windows). Spectral is designed
   for on-screen reading. Served from _content/qNet.Web.Shell/fonts/. */
@font-face {
    font-family: "Spectral"; font-style: normal; font-weight: 400; font-display: swap;
    src: url(fonts/spectral-400.woff2) format("woff2");
}
@font-face {
    font-family: "Spectral"; font-style: normal; font-weight: 500; font-display: swap;
    src: url(fonts/spectral-500.woff2) format("woff2");
}
@font-face {
    font-family: "Spectral"; font-style: normal; font-weight: 600; font-display: swap;
    src: url(fonts/spectral-600.woff2) format("woff2");
}

/*
 * THEME STRUCTURE
 * :root = Court defaults (full token set)
 * html.theme-ember = warm oxblood-black overrides (AFTER :root)
 * html.theme-frost = cold slate-black overrides (AFTER :root)
 * All void/ink/line/accent/glow tokens are fully themed.
 */

/* ── Scale tokens (theme-agnostic — same across Court/Ember/Frost) ─
   Added for the admin design-system extension (qNet.Web.Admin foundation).
   Purely additive: does not touch color tokens or legacy aliases below. ── */
:root {
    /* spacing (4px base) */
    --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-5: 20px; --space-6: 24px; --space-8: 32px;
    /* radius */
    --radius-sm: 8px; --radius: 12px; --radius-lg: 16px; --radius-pill: 20px;
    /* elevation */
    --shadow-1: 0 1px 0 rgba(255,255,255,.02);
    --shadow-2: 0 8px 24px rgba(0,0,0,.35);
    /* z-index */
    --z-header: 20; --z-modal: 40; --z-popover: 50;
    /* motion */
    --motion-fast: .12s; --motion: .15s; --motion-view: .24s; --ease: cubic-bezier(.2,.6,.2,1);
}

/* ── Court (default) ────────────────────────────────────────────── */
:root {
    /* Background surface layers */
    --void-0: #0A0813;
    --void-1: #100C1C;
    --void-2: #171226;
    --void-3: #1F1833;

    /* Text */
    --ink:       #ECE6F2;
    --ink-dim:   #A59DBA;
    --ink-faint: #8F88A6;

    /* Borders */
    --line:        rgba(170,150,220,.14);
    --line-strong: rgba(170,150,220,.32);

    /* Primary accent: gold/amber */
    --accent:        #E8B84B;
    --accent-bright: #F6EAC9;
    /* Secondary accent: violet */
    --accent-2:        #8B7CF0;
    --accent-2-bright: #A995FF;

    /* Aliases — keep old markup working */
    --gold:          var(--accent);
    --gold-bright:   var(--accent-bright);
    --violet:        var(--accent-2);
    --violet-bright: var(--accent-2-bright);
    /* Heading-gradient midtone — arcane lavender so Court H1s read violet, not icy blue. */
    --starlight:     #D9C9FF;

    /* Glow tokens — used in body ambient gradient + shadows */
    --glow-primary: rgba(139,124,240,.14);
    --glow-accent:  rgba(232,184,75,.06);

    /* Semantic */
    --good:  #5FD49A;
    --ember: #E2552C;
    --warn:  #E0B34E;

    /* Typography */
    --serif: "Spectral","Hoefler Text","Iowan Old Style","Constantia","Palatino Linotype",Georgia,"Times New Roman",serif;
    --sans:  ui-sans-serif,system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
    --mono:  ui-monospace,"SF Mono","Cascadia Code","Consolas",monospace;
}

/* ── Ember: warm oxblood-black ──────────────────────────────────── */
html.theme-ember {
    /* Background — warm very-dark tones */
    --void-0: #120A08;
    --void-1: #1B0F0B;
    --void-2: #241511;
    --void-3: #2E1B16;

    /* Text — warm cream tones */
    --ink:       #F2E8E2;
    --ink-dim:   #C4A79B;
    --ink-faint: #A88D84;

    /* Borders — warm rust tint */
    --line:        rgba(220,100,80,.14);
    --line-strong: rgba(220,100,80,.32);

    /* Accents — ember fire */
    --accent:        #F0672E;
    --accent-bright: #F5C19C;
    --accent-2:        #D4A24E;
    --accent-2-bright: #EFD4A0;

    /* Aliases */
    --gold:          var(--accent);
    --gold-bright:   var(--accent-bright);
    --violet:        var(--accent-2);
    --violet-bright: var(--accent-2-bright);
    --starlight:     #F5C19C;

    /* Glow — warm ember/orange */
    --glow-primary: rgba(200,60,20,.14);
    --glow-accent:  rgba(212,79,42,.08);

    --ember: #B83220;
}

/* ── Frost: cold slate-black ────────────────────────────────────── */
html.theme-frost {
    /* Background — cold very-dark tones */
    --void-0: #080B12;
    --void-1: #0C111B;
    --void-2: #111724;
    --void-3: #18202F;

    /* Text — cold blue-white tones */
    --ink:       #E6ECF2;
    --ink-dim:   #9FB0C4;
    --ink-faint: #8096AC;

    /* Borders — cool blue tint */
    --line:        rgba(100,160,220,.14);
    --line-strong: rgba(100,160,220,.32);

    /* Accents — steel blue + silver */
    --accent:        #5AA0E0;
    --accent-bright: #B8E0F7;
    --accent-2:        #AEBECF;
    --accent-2-bright: #D4E4F0;

    /* Aliases */
    --gold:          var(--accent);
    --gold-bright:   var(--accent-bright);
    --violet:        var(--accent-2);
    --violet-bright: var(--accent-2-bright);
    --starlight:     #C9EEFF;

    /* Glow — cold cyan/blue */
    --glow-primary: rgba(58,120,200,.14);
    --glow-accent:  rgba(74,144,196,.07);

    --ember: #C0392B;
}

/* ================================================================
   BASE RESET + TYPOGRAPHY
   ================================================================ */

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }

body {
    margin: 0; min-height: 100vh;
    font-family: var(--sans); line-height: 1.6; color: var(--ink);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    /* All glow stops use CSS vars — no hardcoded rgba */
    background:
        radial-gradient(120% 80% at 50% -8%, var(--glow-primary), transparent 60%),
        radial-gradient(90% 60% at 85% 4%, var(--glow-accent), transparent 55%),
        var(--void-0);
    background-attachment: fixed;
}

h1, h2, h3 {
    font-family: var(--serif); letter-spacing: .02em;
    color: var(--accent); font-weight: 600;
}
a { color: var(--accent-2); text-decoration: none; transition: color .15s ease; }
a:hover { color: var(--accent-2-bright); }
::selection { background: var(--accent-2); color: var(--void-0); }

/* ================================================================
   COURT SHELL LAYOUT
   ================================================================ */

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

.court-header {
    display: flex; align-items: center; justify-content: space-between; gap: 1rem;
    padding: 0.85rem clamp(1rem, 4vw, 2rem);
    border-bottom: 1px solid var(--line);
    /* Header uses void tokens so it themes with the background */
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--void-1) 85%, transparent),
        color-mix(in srgb, var(--void-0) 60%, transparent));
    backdrop-filter: blur(10px);
    position: sticky; top: 0; z-index: 20;
}

.brand { display: flex; align-items: center; gap: 0.65rem; color: var(--ink); }
.brand:hover { color: var(--ink); }
/* Brand mark glow uses accent glow token */
.brand-mark {
    color: var(--accent);
    font-size: 1.4rem; line-height: 1;
    filter: drop-shadow(0 0 10px color-mix(in srgb, var(--accent) 50%, transparent));
}
.brand-name { font-family: var(--serif); font-size: 1.3rem; letter-spacing: .01em; }
.brand-name strong { color: var(--accent); font-weight: 600; }

.court-main { flex: 1; width: 100%; }

.court-footer {
    text-align: center; padding: 2.5rem 0 3rem;
    color: var(--ink-faint);
    font-family: var(--mono); font-size: .7rem; letter-spacing: .18em; text-transform: uppercase;
}
.court-footer::before {
    content: ""; display: block;
    width: 60px; height: 1px;
    background: var(--line);
    margin: 0 auto 1.5rem;
}

/* ================================================================
   TOP NAV COMPONENTS
   ================================================================ */

/* App switcher */
.app-switcher {
    display: inline-flex; align-items: stretch;
    border: 1px solid var(--line); border-radius: 10px; overflow: hidden;
    background: color-mix(in srgb, var(--void-2) 60%, transparent);
}
.app-switcher-chip {
    display: inline-flex; align-items: center; gap: .35rem;
    padding: .28rem .7rem;
    font-family: var(--mono); font-size: .6rem; letter-spacing: .08em; text-transform: uppercase;
    color: var(--ink-faint); text-decoration: none;
    border-right: 1px solid var(--line);
    transition: color .12s, background .12s;
}
.app-switcher-chip:last-child { border-right: none; }
.app-switcher-chip:hover { color: var(--ink); background: color-mix(in srgb, var(--accent-2) 10%, transparent); }
.app-switcher-chip.disabled { opacity: .38; cursor: default; pointer-events: none; }
.app-switcher-chip.current {
    color: var(--accent);
    background: color-mix(in srgb, var(--accent) 8%, transparent);
    pointer-events: none;
}
.app-switcher-sigil { font-size: .85rem; line-height: 1; }

/* Theme switcher */
.theme-switcher {
    display: inline-flex; align-items: stretch;
    border: 1px solid var(--line-strong); border-radius: 8px; overflow: hidden;
    background: var(--void-3); gap: 0;
}
.theme-switcher [data-theme] {
    display: inline-flex; align-items: center; gap: .35rem;
    padding: .28rem .6rem;
    font-family: var(--mono); font-size: .6rem; letter-spacing: .07em; text-transform: uppercase;
    color: var(--ink-faint); background: transparent;
    border: none; border-right: 1px solid var(--line); cursor: pointer;
    transition: color .12s, background .12s;
    white-space: nowrap;
}
.theme-switcher [data-theme]:last-child { border-right: none; }
.theme-switcher [data-theme]:hover { color: var(--ink); background: color-mix(in srgb, var(--accent-2) 8%, transparent); }
.theme-switcher [data-theme].ts-active { color: var(--accent); background: rgba(255,255,255,.04); }
.theme-swatch {
    width: .55rem; height: .55rem; border-radius: 50%; flex-shrink: 0;
    border: 1px solid rgba(255,255,255,.18);
}
.ts-swatch-court { background: #E8B84B; }
.ts-swatch-ember { background: #F0672E; }
.ts-swatch-frost { background: #5AA0E0; }

/* ================================================================
   TOP NAV — shell-owned, identical across every qNet site.
   Three regions: left cluster (brand + app-switcher) / centered nav
   buttons (per-site) / right cluster (theme popover + user area).
   ================================================================ */
.top-nav {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center; gap: 1rem;
    padding: 0.7rem clamp(1rem, 4vw, 2rem);
    border-bottom: 1px solid var(--line);
    position: sticky; top: 0; z-index: 40;
}
/* The frosted background lives on a pseudo-element, NOT on .top-nav itself: a backdrop-filter (like
   transform/filter) on an element makes it the containing block for any position:fixed descendant, which
   would clip the settings modal's full-viewport scrim to the header's box. Absolutely-positioned, so it
   stays out of the grid flow; z-index:-1 keeps it behind the nav content. */
.top-nav::before {
    content: ""; position: absolute; inset: 0; z-index: -1;
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--void-1) 85%, transparent),
        color-mix(in srgb, var(--void-0) 60%, transparent));
    backdrop-filter: blur(10px);
}
.top-nav-left   { display: flex; align-items: center; gap: 1.15rem; justify-self: start; min-width: 0; }
.top-nav-center { display: flex; align-items: center; gap: .3rem; justify-self: center; min-width: 0; }
.top-nav-right  { display: flex; align-items: center; gap: .6rem; justify-self: end; }

/* Stretchable center — opt-in modifier so an app can fill the nav center with wide content
   (e.g. a breadcrumb + search box) instead of the default centered row of narrow nav buttons. */
.top-nav--appfill { grid-template-columns: auto 1fr auto; }
.top-nav--appfill .top-nav-center { justify-self: stretch; }

/* Brand + app-switcher: the switcher collapses into a floating panel revealed only on hover or
   keyboard focus of the brand cluster (pure CSS — no JS, no @rendermode; the nav is static SSR).
   Both the brand link and every chip inside the panel are natively focusable, so tabbing into
   the panel keeps :focus-within (and therefore the panel) open. */
.brand-wrap { position: relative; display: inline-flex; align-items: center; }
.brand-wrap .app-switcher {
    position: absolute; top: calc(100% + 10px); left: 0; z-index: 60;
    flex-direction: column; align-items: stretch; gap: .1rem; overflow: visible;
    padding: .35rem; border-radius: 12px;
    background: var(--void-1); box-shadow: 0 12px 32px -12px rgba(0,0,0,.7);
    opacity: 0; visibility: hidden; pointer-events: none;
    transform: translateY(-4px);
    transition: opacity var(--motion) ease, transform var(--motion) ease, visibility var(--motion);
}
.brand-wrap .app-switcher-chip { border-right: none; border-radius: 8px; justify-content: flex-start; }
/* Hover bridge: the panel floats 10px below the brand, so moving the pointer down from the logo crosses an
   empty gap where neither the brand nor the panel is under the cursor — .brand-wrap:hover drops and the
   panel collapses before you reach it. This transparent strip fills that gap and, being part of the panel
   (a descendant of .brand-wrap), keeps :hover continuous from the logo into the menu. It inherits the
   panel's pointer-events, so it's inert while the panel is hidden and live only once it's revealed. */
.brand-wrap .app-switcher::before {
    content: ""; position: absolute; left: 0; right: 0; top: -10px; height: 10px;
}
.brand-wrap:hover .app-switcher,
.brand-wrap:focus-within .app-switcher {
    opacity: 1; visibility: visible; pointer-events: auto; transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
    .brand-wrap .app-switcher { transition: none; }
}

/* Centered nav buttons (per-site content; empty on Home/Vault for now) */
.nav-btn {
    font-family: var(--sans); font-size: .9rem; color: var(--ink-dim);
    text-decoration: none; padding: .4rem .8rem; border-radius: 9px;
    border: 1px solid transparent; white-space: nowrap;
    transition: color .15s ease, background .15s ease, border-color .15s ease;
}
.nav-btn:hover { color: var(--ink); background: color-mix(in srgb, var(--ink) 6%, transparent); }
.nav-btn.active, .nav-btn[aria-current="page"] {
    color: var(--accent);
    border-color: color-mix(in srgb, var(--accent) 35%, transparent);
    background: color-mix(in srgb, var(--accent) 10%, transparent);
}

/* Theme popover (palette icon → swatch panel) */
.theme-pop { position: relative; }
.theme-pop > summary {
    list-style: none; cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
    width: 34px; height: 34px; border-radius: 9px; color: var(--ink-dim);
    border: 1px solid var(--line); background: transparent;
    transition: color .15s ease, border-color .15s ease;
}
.theme-pop > summary::-webkit-details-marker { display: none; }
.theme-pop > summary::marker { content: ""; }
.theme-pop > summary:hover { color: var(--accent); border-color: var(--line-strong); }
.theme-pop[open] > summary { color: var(--accent); border-color: var(--accent); }
.theme-pop-panel {
    position: absolute; right: 0; top: calc(100% + 8px); z-index: 60;
    padding: .5rem; border: 1px solid var(--line); border-radius: 12px;
    background: var(--void-1); box-shadow: 0 12px 32px -12px rgba(0,0,0,.7);
}
/* Inside the popover the swatches stack vertically */
.theme-pop-panel .theme-switcher { flex-direction: column; border: none; gap: .1rem; }
.theme-pop-panel .theme-switcher [data-theme] { border: none; border-radius: 8px; justify-content: flex-start; }

/* User area: dropdown (authed) / sign-in link (anon) */
.user-menu { position: relative; }
.user-menu > summary { list-style: none; cursor: pointer; }
.user-menu > summary::-webkit-details-marker { display: none; }
.user-menu > summary::marker { content: ""; }
.user-pill {
    display: inline-flex; align-items: center; gap: .55rem;
    padding: .3rem .55rem .3rem .75rem;
    border: 1px solid var(--line); border-radius: 12px;
    background: rgba(255,255,255,.02);
    font-family: var(--serif); font-size: .95rem; color: var(--ink);
}
.user-pill .display-name { color: var(--ink); font-size: 1rem; }
.user-pill .title-affix { font-size: .75rem; font-style: italic; color: var(--accent); opacity: .85; }
.user-pill .caret { width: 14px; height: 14px; color: var(--ink-faint); transition: transform .2s ease; }
.user-menu[open] .user-pill .caret { transform: rotate(180deg); }
.user-menu-panel {
    position: absolute; right: 0; top: calc(100% + 8px); z-index: 60; min-width: 190px;
    padding: .4rem; border: 1px solid var(--line); border-radius: 12px;
    background: var(--void-1); box-shadow: 0 12px 32px -12px rgba(0,0,0,.7);
    display: flex; flex-direction: column; gap: .15rem;
}
.user-menu-panel .menu-item {
    display: flex; align-items: center; gap: .55rem; padding: .5rem .7rem; border-radius: 8px;
    font: inherit; font-size: .9rem; color: var(--ink-dim); text-decoration: none;
    background: transparent; border: none; width: 100%; text-align: left; cursor: pointer;
}
.user-menu-panel .menu-item:hover { background: color-mix(in srgb, var(--ink) 7%, transparent); color: var(--ink); }
.user-menu-panel .menu-item.danger:hover { color: #ffb39a; }
.user-menu-panel form { margin: 0; }
.user-menu-panel .menu-ico { width: 1.1em; text-align: center; opacity: .8; }

.nav-signin {
    font-family: var(--sans); font-size: .9rem; color: var(--accent); text-decoration: none;
    padding: .45rem 1rem; border-radius: 9px;
    border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
    transition: background .15s ease;
}
.nav-signin:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent); }

/* Responsive: tighten regions; collapse app-switcher labels + brand text on narrow screens */
@media (max-width: 760px) {
    .top-nav { grid-template-columns: auto 1fr auto; gap: .5rem; }
    .top-nav-center { overflow-x: auto; scrollbar-width: none; }
    .top-nav-center::-webkit-scrollbar { display: none; }
    .brand-name { display: none; }
    .app-switcher-chip > span:not(.app-switcher-sigil) { display: none; }
}

/* ================================================================
   RANK PILL — contrast-safe on all themes, all ranks
   ================================================================ */

/*
 * Color passed as CSS custom property --rank-color.
 * text: color-mix(55% rank + 45% white) — safe even for very dark ranks
 * bg:   color-mix(14% rank + transparent) — subtle tint
 * border: color-mix(40% rank + transparent)
 * dot:  color-mix(75% rank + 25% white) — bright dot anchor
 */
.rank-pill {
    display: inline-flex; align-items: center; gap: .4rem;
    font-family: var(--mono); font-size: .68rem; letter-spacing: .14em; text-transform: uppercase;
    padding: .28rem .75rem;
    border-radius: 8px;
    border: 1px solid color-mix(in srgb, var(--rank-color, var(--accent)) 40%, transparent);
    background: color-mix(in srgb, var(--rank-color, var(--accent)) 14%, transparent);
    color: color-mix(in srgb, var(--rank-color, var(--accent)) 55%, white);
}
.rank-pill::before {
    content: ""; display: block;
    width: 6px; height: 6px; border-radius: 50%;
    background: color-mix(in srgb, var(--rank-color, var(--accent)) 75%, white);
    box-shadow: 0 0 6px color-mix(in srgb, var(--rank-color, var(--accent)) 55%, transparent);
}

/* ================================================================
   FORM CONTROLS (base — fully tokenized)
   ================================================================ */

.form-control,
input[type=text], input[type=password], input[type=email], select {
    font: inherit; color: var(--ink);
    background: var(--void-3); border: 1px solid var(--line); border-radius: 9px; padding: .55rem .7rem;
}
input:focus, select:focus, .form-control:focus {
    outline: none;
    border-color: var(--accent-2);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-2) 20%, transparent);
}

/* ================================================================
   FRAMEWORK BITS
   ================================================================ */

.blazor-error-boundary { background: #7a1320; padding: 1rem 1rem 1rem 3.7rem; color: white; }
.blazor-error-boundary::after { content: "An error has occurred."; }
.valid.modified:not([type=checkbox]) { outline: 1px solid var(--good); }
.invalid { outline: 1px solid var(--ember); }
.validation-message { color: #f0a9b2; }

/* Unhandled-error banner. Hidden until blazor.web.js sets display:block on a
   real error — themed to the Court instead of the framework's lightyellow strip.
   Lives here so every qNet app gets it without per-app scoped CSS. */
#blazor-error-ui {
    display: none;
    position: fixed; inset: auto 0 0 0; z-index: 1200;
    padding: .8rem 1.25rem;
    font-family: var(--sans); font-size: .9rem; color: var(--ink);
    background: color-mix(in srgb, var(--void-1) 92%, #000);
    border-top: 1px solid color-mix(in srgb, #f04747 55%, var(--line));
    box-shadow: 0 -8px 30px -12px rgba(0,0,0,.7);
    backdrop-filter: blur(6px);
}
#blazor-error-ui::before { content: "\26A0"; margin-right: .55rem; color: #f04747; }
#blazor-error-ui .reload {
    color: var(--accent); text-decoration: underline; text-underline-offset: 2px;
    margin-left: .35rem; cursor: pointer;
}
#blazor-error-ui .dismiss { float: right; cursor: pointer; color: var(--ink-faint); padding: 0 .3rem; }
#blazor-error-ui .dismiss:hover { color: var(--ink); }

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* ── Title effects (TitledName) ─────────────────────────────────────────────
   The username sits outside .ttl-fx unless StyleName is set, so only the title is styled.
   Default colour = theme accent; inline background/color/filter carries the rest. fx-clip clips
   the fill (+ shimmer highlight layer) to the glyphs; glow is an inline drop-shadow, so all effects
   layer. Heavy effects + backdrops are omitted by the component on compact surfaces. */
.ttl-fx { color: var(--accent); }
.ttl-fx.fx-clip {
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
}
.ttl-fx.fx-shimmer {
    animation-name: ttl-shimmer;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
}
/* Two-layer background: [shimmer highlight, fill] — move only the highlight, keep the fill static. */
@keyframes ttl-shimmer { from { background-position: 200% 0, 0 0; } to { background-position: -200% 0, 0 0; } }
@media (prefers-reduced-motion: reduce) { .ttl-fx.fx-shimmer { animation: none; } }

/* Constrained backdrops behind the whole name — soft, rounded, translucent by construction. */
.display-name[class*="bd-"] { --bd-c: var(--accent); }
.bd-halo { padding: 0 .5em; background: radial-gradient(ellipse at center, color-mix(in srgb, var(--bd-c) 42%, transparent), transparent 72%); }
.bd-plate { display: inline-block; padding: .05em .6em; border-radius: 999px; background: color-mix(in srgb, var(--bd-c) 16%, transparent); border: 1px solid color-mix(in srgb, var(--bd-c) 32%, transparent); }
.bd-panel { display: inline-block; padding: .05em .55em; border-radius: 6px; background: color-mix(in srgb, var(--bd-c) 14%, transparent); border: 1px solid color-mix(in srgb, var(--bd-c) 28%, transparent); }
.bd-frame { display: inline-block; padding: .05em .55em; border-radius: 6px; background: color-mix(in srgb, var(--bd-c) 6%, transparent); border: 1px solid color-mix(in srgb, var(--bd-c) 48%, transparent); }
.bd-underglow { padding: 0 .15em .1em; box-shadow: 0 .5em .5em -.35em color-mix(in srgb, var(--bd-c) 65%, transparent); }

/* ================================================================
   ADMIN DESIGN-SYSTEM PRIMITIVES (QCard/QButton/QBadge/QStatTile/
   QStatusDot) — additive, `q-` prefixed so nothing collides with the
   selectors above. Built entirely from existing color tokens + the
   scale tokens declared at the top of this file. Background layering
   maps the mockup's 4-stop bg/bg-2/panel/panel-2 onto the 4-stop
   void-0..3 scale (darkest→lightest, same relative order).
   ================================================================ */

/* ── QCard: gradient panel + hairline + optional header row ────── */
.q-card {
    background: linear-gradient(180deg, var(--void-2), var(--void-1));
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-1), var(--shadow-2);
}
.q-card-hd {
    display: flex; align-items: center; gap: var(--space-3);
    padding: 13px var(--space-5);
    border-bottom: 1px solid var(--line);
    font-family: var(--sans); font-size: .81rem; font-weight: 600; letter-spacing: .2px;
    color: var(--ink);
}
.q-card-bd { padding: var(--space-4) var(--space-5); }

/* ── QButton: gold primary / default / ghost / danger, md/sm ───── */
.q-btn {
    font: inherit; font-size: .89rem; color: var(--ink); cursor: pointer;
    background: var(--void-3); border: 1px solid var(--line-strong);
    padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm);
    transition: border-color var(--motion-fast) var(--ease), background var(--motion-fast) var(--ease),
        color var(--motion-fast) var(--ease), filter var(--motion-fast) var(--ease);
}
.q-btn:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--line-strong)); }
.q-btn:disabled { opacity: .5; cursor: default; pointer-events: none; }
.q-btn--gold {
    background: linear-gradient(145deg, var(--accent), color-mix(in srgb, var(--accent) 55%, var(--void-0)));
    color: var(--void-0);
    border-color: color-mix(in srgb, var(--accent) 55%, var(--void-0));
    font-weight: 650;
}
.q-btn--gold:hover { filter: brightness(1.06); border-color: color-mix(in srgb, var(--accent) 55%, var(--void-0)); }
.q-btn--ghost { background: transparent; }
.q-btn--danger { color: var(--ember); border-color: color-mix(in srgb, var(--ember) 45%, var(--line-strong)); }
.q-btn--danger:hover { background: color-mix(in srgb, var(--ember) 14%, transparent); border-color: color-mix(in srgb, var(--ember) 45%, var(--line-strong)); }
.q-btn--sm { padding: 4px var(--space-2); font-size: .78rem; }

/* ── QBadge: pill status/rank chip (Rank variant renders RankPill instead) ── */
.q-badge {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 2px var(--space-3); border-radius: var(--radius-pill);
    font-size: .78rem; font-weight: 600;
    border: 1px solid var(--line-strong); background: var(--void-3); color: var(--ink-dim);
}
.q-badge--gold {
    color: var(--accent); border-color: color-mix(in srgb, var(--accent) 45%, transparent);
    background: color-mix(in srgb, var(--accent) 8%, transparent);
}
.q-badge--bright-gold {
    color: var(--accent-bright); border-color: color-mix(in srgb, var(--accent-bright) 45%, transparent);
    background: color-mix(in srgb, var(--accent-bright) 8%, transparent);
}
.q-badge--violet {
    color: var(--accent-2); border-color: color-mix(in srgb, var(--accent-2) 40%, transparent);
    background: color-mix(in srgb, var(--accent-2) 8%, transparent);
}
/* "Blue" badges use --starlight — the design-system's semantic map assigns the cool
   blue-ish rank tone (e.g. Dread Knight) to this token rather than a literal hex. */
.q-badge--blue {
    color: var(--starlight); border-color: color-mix(in srgb, var(--starlight) 40%, transparent);
    background: color-mix(in srgb, var(--starlight) 8%, transparent);
}
.q-badge--green {
    color: var(--good); border-color: color-mix(in srgb, var(--good) 40%, transparent);
    background: color-mix(in srgb, var(--good) 8%, transparent);
}
.q-badge--red {
    color: var(--ember); border-color: color-mix(in srgb, var(--ember) 40%, transparent);
    background: color-mix(in srgb, var(--ember) 8%, transparent);
}
.q-badge--dim { color: var(--ink-faint); }

/* ── QStatTile: self-contained stat card (eyebrow + big value + delta) ── */
.q-stat {
    background: linear-gradient(180deg, var(--void-2), var(--void-1));
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-1), var(--shadow-2);
    padding: var(--space-4) 17px;
    position: relative; overflow: hidden;
}
.q-stat-k {
    display: flex; align-items: center; gap: 7px;
    color: var(--ink-dim); font-size: .72rem; text-transform: uppercase; letter-spacing: .04em;
}
.q-stat-v { font-family: var(--sans); font-size: 27px; font-weight: 700; margin-top: 6px; letter-spacing: .02em; color: var(--ink); }
.q-stat-d { font-size: .69rem; margin-top: 3px; }
.q-stat-d--up { color: var(--good); }
.q-stat-d--down { color: var(--ember); }
.q-stat-d--faint { color: var(--ink-faint); }
.q-stat-d--muted { color: var(--ink-dim); }
.q-stat-extra { margin-top: var(--space-2); }

/* ── QStatusDot: presence dot (online/away/offline) ─────────────── */
.q-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; flex: none; }
.q-dot--on { background: var(--good); box-shadow: 0 0 8px var(--good); }
.q-dot--away { background: var(--warn); }
.q-dot--off { background: var(--ink-faint); }

/* ================================================================
   ADMIN APP-SHELL (AdminShell/PageHeader) — additive, `q-adminshell`/
   `q-pagehead` prefixed. Full-width sticky header (brand · centered
   search · bell + identity), sticky 250px sidebar, centered content.
   ================================================================ */

.q-adminshell { display: flex; flex-direction: column; min-height: 100vh; }

.q-adminshell-top {
    display: grid; grid-template-columns: 1fr minmax(360px, 600px) 1fr;
    align-items: center; gap: var(--space-5);
    padding: 0 var(--space-5);
    height: 64px;
    border-bottom: 1px solid var(--line);
    position: sticky; top: 0; z-index: var(--z-header);
    background: color-mix(in srgb, var(--void-0) 80%, transparent);
    backdrop-filter: blur(12px);
}

.q-adminshell-brand { display: flex; align-items: center; gap: 11px; justify-self: start; min-width: 0; }
.q-adminshell-mark {
    width: 34px; height: 34px; border-radius: var(--radius-sm); flex: none;
    display: grid; place-items: center;
    background: linear-gradient(145deg, color-mix(in srgb, var(--accent) 30%, var(--void-2)), var(--void-2));
    border: 1px solid color-mix(in srgb, var(--accent) 55%, var(--void-0));
    color: var(--accent); font-weight: 800;
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 8%, transparent), var(--shadow-2);
}
.q-adminshell-brand-text { min-width: 0; line-height: 1.2; }
.q-adminshell-brand-text strong { font-family: var(--serif); font-size: 15.5px; letter-spacing: .3px; color: var(--ink); }
.q-adminshell-brand-text small {
    display: block; color: var(--ink-faint); font-size: 10px; letter-spacing: 2.6px;
    text-transform: uppercase; margin-top: 3px;
}

.q-adminshell-search { justify-self: center; width: 100%; }

.q-adminshell-tright { justify-self: end; display: flex; align-items: center; gap: var(--space-3); }
.q-adminshell-bell {
    width: 38px; height: 38px; border-radius: var(--radius-sm); flex: none;
    background: var(--void-2); border: 1px solid var(--line);
    display: grid; place-items: center; color: var(--ink-dim); cursor: pointer;
    transition: color var(--motion) var(--ease), border-color var(--motion) var(--ease);
}
.q-adminshell-bell:hover { color: var(--accent); border-color: var(--line-strong); }

.q-adminshell-body { display: grid; grid-template-columns: 250px 1fr; flex: 1; min-height: 0; }

/* Minimal frame (unauthorized / not-found): generic brand + controls only, full-width content, no sidebar. */
.q-adminshell--minimal .q-adminshell-top { grid-template-columns: 1fr auto; }
.q-adminshell--minimal .q-adminshell-body { grid-template-columns: 1fr; }

.q-adminshell-side {
    background: linear-gradient(180deg, var(--void-1), var(--void-0));
    border-right: 1px solid var(--line);
    display: flex; flex-direction: column;
    padding: var(--space-4); gap: var(--space-1);
    position: sticky; top: 64px;
    height: calc(100vh - 64px);
    overflow-y: auto;
}

/* ── AdminShell sidebar nav items (app supplies the items into the Sidebar slot; styled here
      globally, NOT scoped, so a consuming app's nav component picks them up) ───────────────── */
.q-nav-group {
    color: var(--ink-faint);
    font-size: 10px; letter-spacing: 2px; text-transform: uppercase;
    margin: var(--space-3) var(--space-3) var(--space-1);
}
.q-nav-group:first-child { margin-top: var(--space-1); }
.q-nav-item {
    display: flex; align-items: center; gap: 11px;
    padding: 9px 11px; border-radius: var(--radius-sm);
    color: var(--ink-dim); font-weight: 500; text-decoration: none;
    border: 1px solid transparent; cursor: pointer;
    transition: background var(--motion-fast) var(--ease), color var(--motion-fast) var(--ease);
}
.q-nav-item svg { width: 17px; height: 17px; flex: none; opacity: .9; }
.q-nav-item:hover { background: color-mix(in srgb, var(--ink) 6%, transparent); color: var(--ink); }
.q-nav-item.active, .q-nav-item[aria-current="page"] {
    background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 14%, transparent), transparent);
    color: var(--ink); border-color: var(--line-strong);
    box-shadow: inset 2px 0 0 var(--accent);
}
.q-nav-item--dim { opacity: .45; pointer-events: none; }
.q-nav-item .q-nav-tag {
    margin-left: auto; font-size: 10.5px;
    background: var(--void-2); color: var(--ink-dim);
    padding: 1px 7px; border-radius: var(--radius-pill); border: 1px solid var(--line);
}

.q-adminshell-content { padding: var(--space-6) 34px 40px; width: 100%; max-width: 1720px; margin: 0 auto; }

@media (max-width: 900px) {
    .q-adminshell-top { grid-template-columns: auto 1fr auto; }
    .q-adminshell-brand-text { display: none; }
    .q-adminshell-body { grid-template-columns: 1fr; }
    .q-adminshell-side { position: static; height: auto; border-right: none; border-bottom: 1px solid var(--line); }
}

/* ── PageHeader: opens every AdminShell content view ────────────── */
.q-pagehead { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--space-4); margin-bottom: var(--space-5); }
.q-pagehead h1 { font-size: 22px; margin: 0 0 2px; font-weight: 660; letter-spacing: .2px; }
.q-pagehead-crumb { color: var(--ink-faint); font-size: 12.5px; }
.q-pagehead-actions { display: flex; align-items: center; gap: var(--space-2); }

/* ── Form controls: themed by default across the admin content, so bare
      inputs/selects/textareas read as premium without per-field classes.
      Scoped to .q-adminshell-content so the header search + login stay untouched.
      QSwitch/QSegment are <button>s, so they're unaffected. ──────────────── */
.q-adminshell-content input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
.q-adminshell-content select,
.q-adminshell-content textarea {
    background: var(--void-2);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm);
    color: var(--ink);
    padding: 9px 12px;
    font: inherit;
    font-size: .9rem;
    line-height: 1.3;
    outline: none;
    transition: border-color var(--motion-fast) var(--ease), box-shadow var(--motion-fast) var(--ease);
}
.q-adminshell-content input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):hover,
.q-adminshell-content select:hover,
.q-adminshell-content textarea:hover {
    border-color: color-mix(in srgb, var(--accent) 55%, var(--line-strong));
}
.q-adminshell-content input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):focus,
.q-adminshell-content select:focus,
.q-adminshell-content textarea:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}
.q-adminshell-content input::placeholder,
.q-adminshell-content textarea::placeholder { color: var(--ink-faint); }

/* Native <select>: drop the OS chevron for a themed one so it matches the dark surface. */
.q-adminshell-content select {
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%239aa3b5' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>");
    background-repeat: no-repeat;
    background-position: right 11px center;
    padding-right: 32px;
    cursor: pointer;
}
/* Tint the number spinner so it isn't a bright white OS block on the dark field (Chromium). */
.q-adminshell-content input[type="number"]::-webkit-inner-spin-button,
.q-adminshell-content input[type="number"]::-webkit-outer-spin-button { filter: invert(.65); opacity: .6; }


/* ── QSearchMenu: searchable, keyboard-navigable dropdown (positioned popover + search bar + grouped list,
   with a persistent ✓ on the current value and a distinct top "clear/none" row). ── */
.q-searchmenu { position: absolute; z-index: var(--z-popover); top: calc(100% + 6px); left: 0; display: flex; flex-direction: column; min-width: 260px; max-width: 340px; background: var(--void-2); border: 1px solid var(--line-strong); border-radius: var(--radius); box-shadow: var(--shadow-2); overflow: hidden; }
.q-searchmenu-search { display: flex; align-items: center; gap: 7px; padding: 9px 11px; border-bottom: 1px solid var(--line); background: color-mix(in srgb, var(--ink) 3%, transparent); }
.q-searchmenu-icon { width: 14px; height: 14px; flex: 0 0 auto; color: var(--ink-faint); fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.q-searchmenu-input { flex: 1; min-width: 0; font: inherit; font-size: .86rem; color: var(--ink); background: transparent; border: 0; outline: none; padding: 0; }
.q-searchmenu-input::placeholder { color: var(--ink-faint); }
.q-searchmenu-list { max-height: 320px; overflow-y: auto; padding: 5px; }
.q-searchmenu-group { font-family: var(--mono); font-size: .55rem; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-faint); padding: 6px 8px 4px; }
.q-searchmenu-list > .q-searchmenu-group:not(:first-child) { border-top: 1px solid var(--line); margin-top: 5px; padding-top: 9px; }
.q-searchmenu-item { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; font: inherit; font-size: .85rem; color: var(--ink-dim); background: transparent; border: 0; border-radius: 8px; padding: 6px 9px; cursor: pointer; transition: background var(--motion-fast) var(--ease); }
.q-searchmenu-item:hover { background: color-mix(in srgb, var(--ink) 6%, transparent); color: var(--ink); }
.q-searchmenu-item--active { background: color-mix(in srgb, var(--accent) 15%, transparent); color: var(--ink); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 38%, transparent); }
.q-searchmenu-check { width: 14px; flex: 0 0 auto; text-align: center; color: var(--ink-faint); font-size: .8rem; }
.q-searchmenu-check--current { color: var(--accent); }
.q-searchmenu-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.q-searchmenu-sec { color: var(--ink-faint); font-size: .78rem; flex: 0 0 auto; }
.q-searchmenu-alert { flex: 0 0 auto; font-size: .6rem; color: var(--ember); border: 1px solid color-mix(in srgb, var(--ember) 40%, transparent); border-radius: 5px; padding: 0 5px; }
.q-searchmenu-item--clear { color: var(--ink-dim); }
.q-searchmenu-item--clear .q-searchmenu-label { font-style: italic; }
.q-searchmenu-empty { color: var(--ink-faint); font-size: .82rem; padding: 14px 9px; text-align: center; }

/* ================================================================
   SETTINGS — the ⚙ launcher (TopNav) + the shared Settings modal
   ================================================================ */

/* Icon-only gear in the top-nav right cluster (replaces the theme popover trigger). */
.settings-launcher {
    display: inline-flex; align-items: center; justify-content: center;
    width: 34px; height: 34px; border-radius: 9px; color: var(--ink-dim); cursor: pointer;
    border: 1px solid var(--line); background: transparent;
    transition: color .15s ease, border-color .15s ease;
}
.settings-launcher:hover { color: var(--accent); border-color: var(--line-strong); }
.settings-launcher svg { transition: transform .35s ease; transform-origin: 50% 50%; }
.settings-launcher:hover svg { transform: rotate(40deg); }

/* ---- Modal layout: left tab-rail + content pane (roomy, headroom for future settings) ---- */
.stg { display: flex; gap: 0; min-height: 24rem; }
.stg-rail {
    flex: 0 0 12rem; display: flex; flex-direction: column; gap: .15rem;
    padding-right: 1rem; border-right: 1px solid var(--line);
}
.stg-rail-group {
    font-family: var(--mono); font-size: .62rem; letter-spacing: .14em; text-transform: uppercase;
    color: var(--ink-faint); padding: .2rem .6rem .45rem;
}
.stg-tab {
    display: flex; align-items: center; gap: .6rem; text-align: left; cursor: pointer;
    font-family: var(--sans); font-size: .92rem; color: var(--ink-dim);
    padding: .55rem .7rem; border: 1px solid transparent; border-radius: 10px; background: transparent;
    transition: color .14s ease, background .14s ease, border-color .14s ease;
}
.stg-tab:hover { color: var(--ink); background: color-mix(in srgb, var(--accent-2) 8%, transparent); }
.stg-tab--active {
    color: var(--accent-bright); background: color-mix(in srgb, var(--accent) 12%, transparent);
    border-color: color-mix(in srgb, var(--accent) 30%, transparent);
}
.stg-tab-ico { font-size: .95rem; opacity: .85; }

.stg-panel { flex: 1 1 auto; min-width: 0; padding-left: 1.6rem; }
.stg-h { font-family: var(--serif); font-size: 1.25rem; color: var(--ink); margin: 0 0 .2rem; }
.stg-sub { font-family: var(--sans); font-size: .85rem; color: var(--ink-faint); margin: 0 0 1.2rem; }

/* ---- Theme preview cards (theme tokens are html-scoped, so each carries its own signature palette) ---- */
.stg-themes { display: grid; grid-template-columns: repeat(3, 1fr); gap: .9rem; max-width: 34rem; }
.stg-theme-card {
    --c-bg: var(--void-2); --c-panel: var(--void-3); --c-accent: var(--accent); --c-accent2: var(--accent-2); --c-ink: var(--ink);
    display: flex; flex-direction: column; gap: .55rem; cursor: pointer; padding: .5rem;
    border: 1px solid var(--line-strong); border-radius: 14px; background: var(--void-1);
    transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.stg-theme-card:hover { transform: translateY(-2px); }
.stg-theme-card--active {
    border-color: var(--c-accent);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--c-accent) 45%, transparent), 0 12px 26px -18px rgba(0,0,0,.8);
}
/* Each card carries its theme's real token values (:root / html.theme-* are html-scoped, so a nested
   preview can't inherit them) — surfaces, ink, both accents, and the heading/starlight tint. */
.stg-theme-card--court { --c-bg: #171226; --c-panel: #1F1833; --c-nav: #100C1C; --c-accent: #E8B84B; --c-accent2: #8B7CF0; --c-ink: #ECE6F2; --c-head: #D9C9FF; }
.stg-theme-card--ember { --c-bg: #241511; --c-panel: #2E1B16; --c-nav: #1B0F0B; --c-accent: #F0672E; --c-accent2: #D4A24E; --c-ink: #F2E8E2; --c-head: #F5C19C; }
.stg-theme-card--frost { --c-bg: #111724; --c-panel: #18202F; --c-nav: #0C111B; --c-accent: #5AA0E0; --c-accent2: #AEBECF; --c-ink: #E6ECF2; --c-head: #B8E0F7; }

/* A faithful mini-mockup of the app in that theme: a nav strip, a heading, body text, an accent button
   and a secondary chip — all in the theme's own colors. */
.stg-tp {
    display: flex; flex-direction: column; border-radius: 9px; overflow: hidden; background: var(--c-bg);
    border: 1px solid color-mix(in srgb, var(--c-ink) 14%, transparent); aspect-ratio: 16 / 10;
}
.stg-tp-nav {
    display: flex; align-items: center; gap: .3rem; height: 26%; padding: 0 .45rem;
    background: var(--c-nav); border-bottom: 1px solid color-mix(in srgb, var(--c-ink) 10%, transparent);
}
.stg-tp-dot { width: .5rem; height: .5rem; border-radius: 999px; background: var(--c-accent);
    box-shadow: 0 0 5px color-mix(in srgb, var(--c-accent) 60%, transparent); flex: none; }
.stg-tp-navline { height: .3rem; width: 40%; border-radius: 3px; background: color-mix(in srgb, var(--c-ink) 32%, transparent); }
.stg-tp-body { flex: 1 1 auto; display: flex; flex-direction: column; gap: .3rem; padding: .5rem .55rem; }
.stg-tp-h { height: .46rem; width: 66%; border-radius: 3px; background: var(--c-head); }
.stg-tp-line { height: .3rem; border-radius: 3px; background: color-mix(in srgb, var(--c-ink) 42%, transparent); }
.stg-tp-line--1 { width: 88%; }
.stg-tp-line--2 { width: 60%; }
.stg-tp-row { display: flex; align-items: center; gap: .35rem; margin-top: auto; }
.stg-tp-btn { height: .62rem; width: 34%; border-radius: 4px; background: var(--c-accent); }
.stg-tp-chip { height: .55rem; width: 26%; border-radius: 999px;
    background: color-mix(in srgb, var(--c-accent2) 30%, transparent);
    border: 1px solid color-mix(in srgb, var(--c-accent2) 60%, transparent); }

.stg-theme-name {
    display: flex; align-items: center; justify-content: space-between;
    font-family: var(--sans); font-size: .9rem; color: var(--ink); padding: 0 .15rem;
}
.stg-check { color: var(--c-accent); font-weight: 700; }

/* ---- Toast position picker: a mini "screen" with six targets ---- */
.stg-posgrid {
    position: relative;
    display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(2, 1fr); gap: .4rem;
    width: 15rem; aspect-ratio: 16 / 10; padding: .5rem;
    border: 1px solid var(--line-strong); border-radius: 12px;
    background: color-mix(in srgb, var(--void-0) 55%, transparent);
}
/* Mini top-nav across the top of the preview screen (with a tiny accent "brand" dot) — top toasts at 0
   offset sit under it, and the default +56 Y nudges the active preview dot to just below it. */
.stg-screen-nav {
    position: absolute; top: .5rem; left: .5rem; right: .5rem; height: 12px; z-index: 0;
    border-radius: 6px 6px 0 0; pointer-events: none;
    background: linear-gradient(180deg, color-mix(in srgb, var(--void-1) 92%, transparent), color-mix(in srgb, var(--void-0) 70%, transparent));
    border-bottom: 1px solid var(--line-strong);
}
.stg-screen-nav::before {
    content: ""; position: absolute; left: 5px; top: 50%; transform: translateY(-50%);
    width: 4px; height: 4px; border-radius: 999px; background: var(--accent);
}
.stg-pos {
    position: relative; z-index: 1;
    display: flex; cursor: pointer; padding: .35rem; background: transparent;
    border: 1px dashed var(--line); border-radius: 8px;
    transition: border-color .14s ease, background .14s ease;
}
.stg-pos:hover { border-color: var(--line-strong); background: color-mix(in srgb, var(--accent-2) 8%, transparent); }
.stg-pos-dot {
    width: .8rem; height: .55rem; border-radius: 3px; background: var(--ink-faint);
    transition: transform .08s ease-out, background .14s ease;
}
/* Every position always previews ITS OWN default offset: top positions sit ~12px down (scaled 56px, i.e.
   just below the mini-nav); bottom positions at 0. */
.stg-pos--tl .stg-pos-dot,
.stg-pos--tc .stg-pos-dot,
.stg-pos--tr .stg-pos-dot { transform: translateY(12px); }
.stg-pos--active { border-style: solid; border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
/* The ACTIVE target's dot instead reads as the live toast — accent-filled, glowing, translated by the
   scaled LIVE offset (--prev-dx/dy, set inline on .stg-posgrid) so it moves as you drag. Declared AFTER
   the per-position default above, so it wins for the active dot (including an active top position). */
.stg-pos--active .stg-pos-dot {
    background: var(--accent);
    box-shadow: 0 0 6px color-mix(in srgb, var(--accent) 70%, transparent);
    transform: translate(var(--prev-dx, 0), var(--prev-dy, 0));
}
.stg-pos--tl { align-items: flex-start; justify-content: flex-start; }
.stg-pos--tc { align-items: flex-start; justify-content: center; }
.stg-pos--tr { align-items: flex-start; justify-content: flex-end; }
.stg-pos--bl { align-items: flex-end; justify-content: flex-start; }
.stg-pos--bc { align-items: flex-end; justify-content: center; }
.stg-pos--br { align-items: flex-end; justify-content: flex-end; }

/* Offset scrubbers: hold-LMB and drag left/right (qnetScrub) to nudge the toast X/Y offset. */
.stg-offset { display: flex; align-items: center; gap: .6rem; margin-top: 1.3rem; flex-wrap: wrap; }
.stg-offset-label { font-family: var(--sans); font-size: .82rem; color: var(--ink-dim); }
.stg-offset-hint { color: var(--ink-faint); font-size: .72rem; }
.stg-scrub {
    display: inline-flex; align-items: baseline; gap: .45rem; cursor: ew-resize; user-select: none;
    padding: .38rem .7rem; min-width: 5rem; border: 1px solid var(--line-strong); border-radius: 9px;
    background: var(--void-2); touch-action: none;
    transition: border-color .14s ease, background .14s ease, box-shadow .14s ease;
}
.stg-scrub:hover { border-color: var(--accent); }
.stg-scrub.qscrubbing {
    border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 16%, transparent);
}
.stg-scrub-axis { font-family: var(--mono); font-size: .66rem; letter-spacing: .1em; color: var(--ink-faint); }
.stg-scrub-val {
    font-family: var(--mono); font-size: .9rem; color: var(--ink);
    min-width: 2.4rem; text-align: right; font-variant-numeric: tabular-nums;
}

.stg-test {
    margin-top: 1.4rem; cursor: pointer; font-family: var(--sans); font-size: .85rem; color: var(--ink-dim);
    padding: .5rem 1rem; border: 1px solid var(--line-strong); border-radius: 10px; background: var(--void-2);
    transition: color .14s ease, border-color .14s ease;
}
.stg-test:hover { color: var(--ink); border-color: var(--accent); }

@media (max-width: 640px) {
    .stg { flex-direction: column; min-height: 0; }
    .stg-rail { flex-basis: auto; flex-direction: row; flex-wrap: wrap; border-right: none; border-bottom: 1px solid var(--line); padding: 0 0 .6rem; }
    .stg-panel { padding-left: 0; padding-top: 1.2rem; }
    .stg-themes { grid-template-columns: repeat(2, 1fr); }
}
