:root {
  --accent: #ffaa00;
  --accent-dim: #a86c00;
  /* These three used to be fixed hex values completely independent of
     --accent (e.g. --bg: #0a0700 has a warm amber undertone baked in
     permanently) — so picking a new accent color only ever moved
     text/border colors, while the whole page background stayed stuck
     looking orange-ish no matter what was picked. Deriving them from
     --accent via color-mix() means the whole theme actually shifts
     together, and it's fully automatic: CSS custom properties re-cascade
     on their own whenever JS updates --accent, no extra JS needed here. */
  --bg: color-mix(in srgb, var(--accent) 6%, #050302);
  --panel: color-mix(in srgb, var(--accent) 9%, #0d0906);
  --panel-border: color-mix(in srgb, var(--accent) 24%, #1a140d);
  --text: #f2e9d8;
  --text-dim: #a89a80;
  --font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --font-mono: 'Share Tech Mono', Consolas, monospace;
  --good: #3ddc84;
  --danger: #ff5c5c;
}

* { box-sizing: border-box; }

/* Browser UA stylesheets underline links via a pseudo-class selector
   (e.g. a:any-link), which has higher specificity than a plain custom
   class like .btn-outline. Several "buttons" in this app (CTAs, nav
   links) are actually <a> tags, so a bare class-only override loses to
   the browser default. Matching the pseudo-class specificity here means
   every custom link style below reliably wins without needing
   !important anywhere. */
a, a:link, a:visited { text-decoration: none; }

/* This generic utility class existed in an old style.css that was never
   actually <link>-ed from index.html (only styles.css is) — meaning
   every element relying on bare .hidden for show/hide (Settings tabs,
   owner-gated content blocks, the AI/ticket quick-action boxes, etc.)
   was never actually being hidden at all despite the class being applied.
   This is the fix — a single missing rule explains the entire "sections
   all showing at once" symptom. */
.hidden { display: none !important; }

/* ---------- Icons ---------- */
svg.icon {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  vertical-align: -3px;
  margin-right: 8px;
}
.nav-item svg.icon { margin-right: 10px; }
.icon-btn svg.icon, .btn-text svg.icon { margin-right: 0; width: 15px; height: 15px; }
.ctrl-btn svg.icon { margin-right: 0; width: 18px; height: 18px; }
.ctrl-btn-main svg.icon { width: 18px; height: 18px; fill: currentColor; stroke: none; }
.server-picker svg.icon { margin-right: 0; }
.server-picker .chev { margin-left: auto; width: 14px; height: 14px; }
.brand svg.icon { width: 22px; height: 22px; color: var(--accent); margin-right: 0; }
.search-box svg.icon { margin-right: 0; color: var(--text-dim); }
.qa-btn svg.icon { margin-right: 6px; }
.logout-btn svg.icon { margin-right: 6px; width: 14px; height: 14px; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 14px;
}

.app {
  display: grid;
  grid-template-columns: 240px 1fr;
  min-height: 100vh;
}

/* ---------- Page background art (any section, via Customize Backgrounds) ----------
   ONE video/image layer attached to <body>, position: fixed, so it stays
   perfectly still while every page's content scrolls over it — same
   technique landing.html/.js already uses for its hero. Every section
   shares this same layer (applyPageBackgrounds() in app.js just swaps
   which URL is loaded into it), so a video background shows up
   identically everywhere, not just on whichever page happens to be
   active. #dash-bg-video / #dash-bg-image / #dash-bg-scrim are created
   once by ensureDashBgLayers() and updated on every switchPage() call.
   This replaces the previous approach: a <video class="page-bg-video">
   injected INSIDE each tall (min-height: 1800px), scrolling .page
   element, position: absolute relative to that page — which meant the
   video scrolled away with the content after one screen's height
   instead of staying put.

   PERF NOTE: every backdrop-filter: blur(...) in this file (sidebar,
   topbar, .panel, .home-feature-card, etc.) now sits on top of a
   CONSTANTLY CHANGING backdrop (the playing video) instead of a static
   image like before — the browser has to recompute each blurred
   element's sample fresh on every video frame instead of caching it
   after the first paint. That's the actual cost of "video everywhere,"
   not the video decode itself. Blur radii below were trimmed (16px→8px
   etc.) to cut that cost; if it's still heavy on lower-end devices, the
   next lever is fewer simultaneously-blurred elements on one screen
   (e.g. the Home page's 12-card module grid) rather than the radius. */
.dash-bg-video,
.dash-bg-image {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  object-fit: cover;
  z-index: -3;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.35s ease;
}
.dash-bg-video.active,
.dash-bg-image.active { opacity: 1; }
.dash-bg-image { background-size: cover; background-position: center; }

.dash-bg-scrim {
  position: fixed;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.35s ease;
  background: radial-gradient(ellipse at center, rgba(10, 7, 0, 0.35) 0%, rgba(10, 7, 0, 0.5) 60%, rgba(10, 7, 0, 0.65) 100%);
}
.dash-bg-scrim.active { opacity: 1; }

/* ---------- Sidebar ---------- */
.sidebar {
  /* Translucent glass instead of a flat opaque fill, so the fixed video
     behind it actually shows through — same treatment as .landing-nav. */
  background: rgba(9, 6, 3, 0.55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-right: 1px solid var(--panel-border);
  display: flex;
  flex-direction: column;
  padding: 20px 14px;
}

.brand { display: flex; align-items: center; gap: 10px; margin-bottom: 24px; }
.brand-icon { color: var(--accent); font-size: 20px; }
.brand-name { color: var(--accent); font-weight: bold; letter-spacing: 1px; font-size: 15px; }
.brand-sub { color: var(--text-dim); font-size: 9px; letter-spacing: 2px; font-family: var(--font-mono); }

/* Sidebar brand header — bot avatar stacked above the name, distinct
   from the .brand layout still used on the login card. */
.sidebar .brand { flex-direction: column; gap: 8px; }
.sidebar .brand .brand-name { font-size: 14px; }
.brand-avatar {
  width: 56px; height: 56px; border-radius: 50%;
  background-color: var(--panel); background-size: cover; background-position: center;
  border: 1px solid var(--panel-border);
}

.nav-section-label {
  color: var(--text-dim);
  font-size: 10px;
  letter-spacing: 1.5px;
  margin: 14px 8px 6px;
}

.server-picker {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 6px;
  padding: 8px 10px;
  margin-bottom: 8px;
  cursor: pointer;
}
.server-picker .chev { margin-left: auto; color: var(--text-dim); }

.nav-list { display: flex; flex-direction: column; gap: 2px; margin-bottom: 6px; }
.nav-item {
  color: var(--text-dim);
  text-decoration: none;
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
}
.nav-item:hover { background: var(--panel); color: var(--text); }
.nav-item.active {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
  border: 1px solid var(--accent-dim);
}

/* Collapsible nav group (currently just "Announcements": Join/Leave/
   Ban/Boost) — the toggle row behaves like any other .nav-item visually,
   it just expands/collapses .nav-subgroup instead of switching pages
   directly. Toggled via app.js adding/removing "expanded" on both the
   group wrapper (rotates the chevron) and the subgroup (reveals it). */
.nav-group-toggle {
  display: flex;
  align-items: center;
}
.nav-chevron {
  margin-left: auto;
  margin-right: 0;
  color: var(--text-dim);
  transition: transform 0.15s ease;
}
.nav-group.expanded .nav-chevron { transform: rotate(180deg); }

.nav-subgroup {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 0;
  overflow: hidden;
}
.nav-group.expanded .nav-subgroup {
  max-height: 280px; /* comfortably fits up to ~5-6 sub-items; see .nav-subitem below */
}
.nav-subitem {
  padding-left: 34px; /* indented under the toggle's icon+label */
  font-size: 12.5px;
}

/* The toggle itself picks up .active styling (same rule as any other
   .nav-item) whenever app.js determines the currently-active page is
   one of this group's sub-pages, so "Announcements" stays visibly
   highlighted even while collapsed — same idea as the reference
   screenshot where the parent row stays legible and only the active
   child is bold. */

.sidebar-user {
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 8px;
  padding: 10px;
  position: relative;
}
.user-avatar {
  width: 32px; height: 32px; border-radius: 50%; background-color: #443311; flex-shrink: 0;
  background-size: cover; background-position: center; background-repeat: no-repeat;
}

/* Wraps a .user-avatar so Discord's animated profile decoration (the
   ring/frame around the avatar) can sit centered on top of it without
   affecting layout — the decoration image is deliberately larger than
   the avatar itself and offset via absolute positioning, matching how
   Discord renders it natively. */
.avatar-decoration-wrap { position: relative; flex-shrink: 0; display: inline-flex; }
.avatar-decoration {
  position: absolute;
  top: 50%; left: 50%;
  width: 136%; height: 136%;
  transform: translate(-50%, -50%);
  pointer-events: none;
  user-select: none;
}

/* Smaller variant for the topbar widget, where .user-avatar-sm shrinks
   the base avatar down from the sidebar's 32px. */
.user-avatar-sm { width: 26px; height: 26px; }
.avatar-decoration-wrap-sm .avatar-decoration { width: 140%; height: 140%; }

/* Mini "signed in as" widget in the topbar, next to Logout — mirrors
   .sidebar-user but compact enough to sit inline with the icon buttons. */
.topbar-user {
  display: flex; align-items: center; gap: 8px;
  padding: 4px 10px 4px 4px;
  border: 1px solid var(--panel-border);
  border-radius: 20px;
  background: var(--panel);
}
.topbar-user-text { line-height: 1.15; }
.topbar-user-name { font-size: 12px; font-weight: 600; }
.topbar-user-role { font-size: 10px; color: var(--text-dim); }
.user-name { font-size: 12px; }
.user-role { font-size: 10px; color: var(--text-dim); }
.status-dot {
  width: 8px; height: 8px; border-radius: 50%; background: var(--good);
  position: absolute; right: 10px; top: 10px;
}

/* ---------- Topbar ---------- */
.main { display: flex; flex-direction: column; min-width: 0; }
.topbar {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 16px 24px;
  border-bottom: 1px solid var(--panel-border);
  background: rgba(9, 6, 3, 0.3);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.search-box {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 6px;
  padding: 8px 12px;
  flex: 1;
  max-width: 420px;
  color: var(--text-dim);
}
.search-box input {
  background: none; border: none; outline: none; color: var(--text);
  font-family: var(--font); font-size: 13px; width: 100%;
}
.search-box.small { max-width: 260px; }

.topbar-icons { display: flex; align-items: center; gap: 10px; margin-left: auto; }
.icon-btn {
  width: 34px; height: 34px; border-radius: 50%;
  background: var(--panel); border: 1px solid var(--panel-border);
  color: var(--text-dim); cursor: pointer;
}
.icon-btn:hover { color: var(--accent); }
.logout-btn {
  background: none; border: 1px solid var(--accent-dim); color: var(--accent);
  padding: 8px 16px; border-radius: 6px; cursor: pointer; font-family: var(--font);
}
.logout-btn:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); }
.logout-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  color: var(--text-dim);
  border-color: var(--panel-border);
}
.logout-btn:disabled:hover { background: none; }

/* ---------- Content grid ---------- */
.page { display: none; }
.page.active { display: grid; grid-template-columns: 1fr 320px; gap: 20px; padding: 20px 24px; }

/* Pages other than Music/Login aren't built yet — a plain, honest
   placeholder instead of pretending they're finished. No background art,
   no glass panels; just the flat --bg color showing through, per the
   brief that only Login and Music get the styled treatment right now. */
.page.placeholder-page.active {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 60vh;
  padding: 20px 24px;
  color: var(--text-dim);
  font-size: 14px;
  text-align: center;
}
/* The background is now the fixed, full-viewport #dash-bg-video/
   #dash-bg-image layer (see above) — it covers the whole screen
   regardless of this box's height, so the old 1800px scroll-height
   hack isn't needed. This just gives the "coming soon" text more room. */
.page.placeholder-page.bg-active.active {
  min-height: 70vh;
  align-items: flex-start;
  padding-top: 140px;
}
/* Guarantees the "coming soon" text stays readable even when this
   section has a bright custom background configured — a solid frosted
   chip behind just the text, rather than relying on the page-wide
   overlay gradient to darken enough everywhere content might sit. */
.placeholder-inner {
  background: rgba(10, 7, 0, 0.68);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--panel-border);
  border-radius: 10px;
  padding: 16px 28px;
}

.content-main { display: flex; flex-direction: column; gap: 20px; min-width: 0; }
.right-rail { display: flex; flex-direction: column; gap: 20px; }

.panel {
  background: rgba(20, 16, 10, 0.42);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid var(--panel-border);
  border-radius: 10px;
  padding: 18px 20px;
}
.panel-title {
  color: var(--accent);
  font-size: 12px;
  letter-spacing: 1.5px;
  margin-bottom: 14px;
}
.panel-title.accent { display: flex; align-items: center; gap: 6px; }
.panel-title-row { display: flex; justify-content: space-between; align-items: center; }
.live-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--good); display: inline-block; }

/* ---------- Now playing ---------- */
.now-playing-body { display: flex; gap: 20px; }
.artwork {
  width: 200px; height: 200px; border-radius: 50%; flex-shrink: 0;
  background: radial-gradient(circle at 30% 20%, color-mix(in srgb, var(--accent) 18%, transparent), transparent 60%), linear-gradient(145deg, #2a2115, #14100a);
  border: 1px solid var(--panel-border);
  display: flex; align-items: center; justify-content: center;
  font-size: 44px; color: var(--accent-dim);
  background-size: cover; background-position: center;
}
.track-info { flex: 1; min-width: 0; }
.badge-playing {
  background: color-mix(in srgb, var(--accent) 15%, transparent); color: var(--accent);
  font-size: 10px; letter-spacing: 1px; padding: 3px 8px; border-radius: 4px;
}
.track-title { margin: 8px 0 4px; font-size: 20px; }
.track-subtitle { color: var(--text-dim); font-size: 13px; }
.track-source { color: var(--text-dim); font-size: 12px; margin-bottom: 4px; }
.track-requester { color: var(--text-dim); font-size: 11px; margin-bottom: 10px; }

.visualizer {
  height: 40px; margin-bottom: 10px;
  display: flex; align-items: flex-end; gap: 2px;
}
.viz-bar {
  flex: 1;
  background: var(--accent);
  opacity: 0.65;
  border-radius: 1px;
  min-height: 3px;
  transition: height 0.15s ease-out;
}

.progress-track, .volume-track {
  position: relative; height: 4px; background: var(--panel-border);
  border-radius: 2px; cursor: pointer; touch-action: none;
}
.progress-fill, .volume-fill { position: absolute; left: 0; top: 0; height: 100%; background: var(--accent); border-radius: 2px; }
.progress-handle, .volume-handle {
  position: absolute; top: 50%; width: 12px; height: 12px; border-radius: 50%;
  background: var(--accent); transform: translate(-50%, -50%);
}
.time-row { display: flex; justify-content: space-between; color: var(--text-dim); font-size: 11px; margin: 6px 0 14px; font-family: var(--font-mono); }

.controls-row { display: flex; align-items: center; gap: 14px; margin-bottom: 14px; }
.ctrl-btn {
  background: none; border: none; color: var(--text-dim); font-size: 16px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 50%;
  transition: background 0.15s, color 0.15s, transform 0.1s;
}
.ctrl-btn:hover:not(:disabled) { color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); }
.ctrl-btn:active:not(:disabled) { transform: scale(0.92); }
.ctrl-btn:disabled { opacity: 0.35; cursor: not-allowed; }
.ctrl-btn-main {
  width: 42px; height: 42px; border-radius: 50%; background: var(--accent);
  color: #1a1200; font-size: 16px;
}
.ctrl-btn-main:hover { color: #1a1200; background: #ffc040; }
.ctrl-btn-main:active { transform: scale(0.94); }

.volume-row { display: flex; align-items: center; gap: 10px; color: var(--text-dim); font-size: 12px; }
.volume-row .volume-track { flex: 1; max-width: 200px; }
.icon-btn-small {
  width: 22px; height: 22px; border-radius: 50%; background: var(--panel);
  border: 1px solid var(--panel-border); color: var(--text-dim); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
.icon-btn-small:hover { color: var(--accent); }
.icon-btn-small svg.icon { margin-right: 0; width: 12px; height: 12px; }

/* ---------- Queue ---------- */
.queue-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }
.queue-page-size { display: flex; align-items: center; gap: 10px; color: var(--text-dim); font-size: 12px; }
.queue-page-size select {
  background: var(--panel); color: var(--text); border: 1px solid var(--panel-border);
  border-radius: 6px; padding: 6px 8px; font-family: var(--font);
}
.queue-search-row { display: flex; gap: 10px; margin-bottom: 14px; }
.btn-outline {
  background: none; border: 1px solid var(--panel-border); color: var(--text-dim);
  border-radius: 6px; padding: 8px 14px; cursor: pointer; font-family: var(--font);
  text-decoration: none; display: inline-flex; align-items: center;
}
.btn-outline:hover { border-color: var(--accent-dim); color: var(--accent); }

/* Logs page — category filter tabs and per-category badges (see
   app.js's LOG_CATEGORY_META for the label/color each category maps
   to). Tabs are plain buttons toggled via .active, same interaction
   pattern as .nav-item elsewhere, just horizontal instead of stacked. */
.log-category-tabs { display: flex; gap: 6px; flex-wrap: wrap; }
.log-tab {
  background: none; border: 1px solid var(--panel-border); color: var(--text-dim);
  border-radius: 6px; padding: 6px 12px; font-size: 12.5px; cursor: pointer; font-family: var(--font);
}
.log-tab:hover { border-color: var(--accent-dim); color: var(--text); }
.log-tab.active { background: color-mix(in srgb, var(--accent) 12%, transparent); border-color: var(--accent-dim); color: var(--accent); }

.log-badge {
  display: inline-block; padding: 3px 9px; border-radius: 5px;
  font-size: 11px; letter-spacing: 0.3px; white-space: nowrap;
}
.log-badge-member { background: rgba(100, 180, 255, 0.14); color: #7fc4ff; }
.log-badge-message { background: rgba(255, 255, 255, 0.08); color: var(--text-dim); }
.log-badge-server { background: color-mix(in srgb, var(--accent) 14%, transparent); color: var(--accent); }
.log-badge-announcement { background: rgba(244, 127, 255, 0.14); color: #f47fff; }
.log-badge-music { background: rgba(80, 220, 150, 0.14); color: #5cd99a; }

.log-desc-title { font-weight: 600; color: var(--text); }
.log-desc-body { color: var(--text-dim); font-size: 12.5px; margin-top: 2px; }
.log-time { color: var(--text-dim); font-size: 12px; white-space: nowrap; }

.queue-table { width: 100%; border-collapse: collapse; }
.queue-table th {
  text-align: left; color: var(--text-dim); font-size: 11px; letter-spacing: 0.5px;
  padding: 8px 10px; border-bottom: 1px solid var(--panel-border);
}
.queue-table td { padding: 10px; border-bottom: 1px solid rgba(255,255,255,0.03); font-size: 13px; }
.queue-table tr:hover td { background: color-mix(in srgb, var(--accent) 3%, transparent); }
.play-row-btn {
  background: var(--accent); color: #1a1200; border: none; border-radius: 4px;
  width: 28px; height: 28px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.15s, transform 0.1s;
}
.play-row-btn:hover { background: #ffc040; }
.play-row-btn:active { transform: scale(0.9); }
.play-row-btn svg.icon { margin: 0; width: 12px; height: 12px; fill: currentColor; stroke: none; }

/* ---------- Right rail ---------- */
.btn-text { background: none; border: none; color: var(--text-dim); cursor: pointer; font-family: var(--font); font-size: 12px; }
.btn-text:hover { color: var(--accent); }

.log-list { display: flex; flex-direction: column; gap: 6px; max-height: 260px; overflow-y: auto; font-size: 11px; font-family: var(--font-mono); }
.log-entry { color: var(--text-dim); display: flex; gap: 8px; }
.log-entry .log-time { color: var(--text-dim); opacity: 0.6; flex-shrink: 0; }
.log-entry .log-msg { color: var(--accent); opacity: 0.9; }

.toggle-row { display: flex; justify-content: space-between; align-items: center; padding: 8px 0; font-size: 13px; }
.switch { position: relative; display: inline-block; width: 38px; height: 20px; }
.switch input { opacity: 0; width: 0; height: 0; }
.slider {
  position: absolute; cursor: pointer; inset: 0; background: var(--panel-border);
  border-radius: 20px; transition: 0.2s;
}
.slider::before {
  content: ''; position: absolute; width: 14px; height: 14px; left: 3px; bottom: 3px;
  background: var(--text-dim); border-radius: 50%; transition: 0.2s;
}
input:checked + .slider { background: var(--accent-dim); }
input:checked + .slider::before { transform: translateX(18px); background: var(--accent); }

.volume-control-row { display: flex; justify-content: space-between; font-size: 12px; color: var(--text-dim); margin: 10px 0 6px; }

.quick-actions-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.qa-btn {
  background: var(--bg); border: 1px solid var(--panel-border); color: var(--text);
  border-radius: 6px; padding: 10px; cursor: pointer; font-family: var(--font); font-size: 12px;
  display: flex; align-items: center; justify-content: center;
  transition: border-color 0.15s, background 0.15s, transform 0.1s;
}
.qa-btn:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); }
.qa-btn:active { transform: scale(0.97); }
.qa-danger { color: var(--danger); }
.qa-danger:hover { border-color: var(--danger); background: rgba(255,92,92,0.08); }

.status-row { display: flex; justify-content: space-between; padding: 6px 0; font-size: 12px; color: var(--text-dim); font-family: var(--font-mono); }
.status-good { color: var(--good); }
.status-bad { color: var(--danger); }

/* ---------- DJ Mode overlay ---------- */
.dj-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 50;
}
.dj-overlay.hidden { display: none; }
.dj-panel {
  width: 380px;
  max-width: 92vw;
  background: rgba(20, 16, 10, 0.96);
  /* PERF: this panel is 96% opaque — at that opacity almost none of
     what's behind it (the playing background video, plus whatever
     glass .panel elements are still composited underneath, e.g. the
     Advanced Management roles list behind the role edit form) is even
     visible through it. blur(20px) was nonetheless the single heaviest
     backdrop-filter radius anywhere in this file, paying full
     per-frame recompute cost for a blur that's nearly imperceptible
     against a near-opaque fill. Every one of the 9 modals sharing this
     class (DJ Mode, Add to Queue, role/channel edit form, etc.) was
     paying that cost the whole time it was open. Trimmed to a radius
     that's visually indistinguishable here but far cheaper to compute.
     Paired with the JS in ensureDashBgLayers() that now also pauses
     the background video entirely while any modal is open. */
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.dj-section { margin-top: 18px; }
.dj-label {
  display: flex; justify-content: space-between; align-items: center;
  font-size: 12px; color: var(--text-dim); margin-bottom: 8px;
}
.dj-label span { color: var(--accent); font-family: var(--font-mono); }
.dj-select {
  width: 100%;
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--panel-border);
  border-radius: 6px;
  padding: 9px 10px;
  font-family: var(--font);
  font-size: 13px;
}
.dj-amp-buttons { display: flex; gap: 8px; margin-top: 10px; }
.dj-amp-buttons .btn-outline { flex: 1; padding: 7px 8px; font-size: 11px; text-align: center; }
.btn-outline-accent { border-color: var(--accent); color: var(--accent); }
.btn-outline-accent:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); }
.field-error {
  margin-top: 8px;
  font-size: 12px;
  color: var(--danger);
}
.field-error.hidden { display: none; }
/* .field-input never had any CSS backing it — inputs/selects/textareas
   using only this class fell back to the browser's raw white default
   (Social Announcements' Platform select, URL field, and both message
   textareas; Invite Tracker's user-ID lookup box). Elements that also
   get wrapped by makeThemedSelect() in app.js (Channel/Role dropdowns)
   were fine regardless, since that JS hides the real <select> and shows
   its own separately-styled display div — this rule is what everything
   ELSE was missing. */
.field-input {
  width: 100%;
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--panel-border);
  border-radius: 6px;
  padding: 9px 10px;
  font-family: var(--font);
  font-size: 13px;
}
.field-input::placeholder { color: var(--text-dim); }
.field-input:focus { outline: none; border-color: var(--accent-dim); }
.field-success {
  margin-top: 8px;
  font-size: 12px;
  color: #2ecc71;
}
.field-success.hidden { display: none; }
.dj-textarea { resize: vertical; min-height: 110px; line-height: 1.5; }
.field-note {
  margin-top: 8px;
  font-size: 11px;
  color: var(--text-dim);
  line-height: 1.4;
}

/* ---------- Appearance / Theme: preview strip + large color picker ---------- */
.theme-preview-strip {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  padding: 16px;
  background: rgba(0, 0, 0, 0.2);
  border: 1px solid var(--panel-border);
  border-radius: 8px;
}
.theme-preview-strip .nav-item { padding: 8px 14px; border-radius: 6px; }

.theme-swatch { transition: transform 0.1s, border-color 0.15s; }
.theme-swatch:hover { transform: scale(1.08); }
.theme-swatch.active { border-color: var(--text) !important; }

.theme-picker-wrap { display: flex; gap: 20px; flex-wrap: wrap; margin-bottom: 4px; }

.theme-picker-sv {
  position: relative;
  width: 260px;
  height: 200px;
  border-radius: 8px;
  overflow: hidden;
  cursor: crosshair;
  border: 1px solid var(--panel-border);
  touch-action: none;
}
.theme-picker-sv canvas { display: block; width: 100%; height: 100%; }
.theme-picker-cursor {
  position: absolute;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5), 0 0 4px rgba(0, 0, 0, 0.6);
  transform: translate(-50%, -50%);
  pointer-events: none;
}

.theme-picker-hue {
  position: relative;
  width: 260px;
  height: 18px;
  border-radius: 9px;
  margin-top: 14px;
  cursor: pointer;
  touch-action: none;
  background: linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000);
  border: 1px solid var(--panel-border);
}
.theme-picker-hue-thumb {
  position: absolute;
  top: -3px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5), 0 0 4px rgba(0, 0, 0, 0.6);
  transform: translate(-50%, 0);
  pointer-events: none;
}

.theme-picker-side {
  display: flex;
  flex-direction: column;
  min-width: 180px;
}
.theme-picker-swatch {
  width: 100%;
  height: 56px;
  border-radius: 8px;
  border: 1px solid var(--panel-border);
  margin-bottom: 12px;
}
#theme-custom-color {
  background: none;
  border: none;
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 13px;
  width: 100%;
  text-transform: lowercase;
}
#theme-custom-color:focus { outline: none; }

/* ---------- Customize Backgrounds panel ---------- */
.bg-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 6px;
  border-bottom: 1px solid var(--panel-border);
}
.bg-row:last-child { border-bottom: none; }
.bg-row-info { flex: 1; min-width: 0; }
.bg-row-label { font-weight: 600; font-size: 13px; color: var(--text); }
.bg-row-sub { font-size: 11px; color: var(--text-dim); margin-top: 2px; }
/* The preview box never crops: max-width/max-height + object-fit:contain
   on the <img> means the whole image is always visible, letterboxed
   inside the box at its own aspect ratio, rather than being cover-cropped
   like the actual page background is. */
.bg-row-preview {
  width: 170px;
  height: 96px;
  flex-shrink: 0;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid var(--panel-border);
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.bg-row-preview img,
.bg-row-preview video {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  display: block;
}
.bg-row-empty { font-size: 10px; color: var(--text-dim); text-align: center; padding: 0 8px; }
.bg-row-actions { display: flex; flex-direction: column; gap: 6px; flex-shrink: 0; width: 92px; }
.bg-row-actions .btn-outline { padding: 6px 8px; font-size: 11px; text-align: center; white-space: nowrap; }
.bg-row-actions .bg-reset-btn:disabled { opacity: 0.35; cursor: not-allowed; }


/* Collapse to a single column only below this width — on a normal
   desktop window this block does not apply at all. */
@media (max-width: 1100px) {
  .app { grid-template-columns: 1fr; }
  .sidebar { display: none; }
  .page.active { grid-template-columns: 1fr; }
  .now-playing-body { flex-direction: column; }
}

/* ---------- Leveling page ---------- */
.lvl-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-top: 14px;
  font-size: 12px;
  color: var(--text-dim);
}

.lvl-user-search-row { display: flex; gap: 10px; margin-bottom: 10px; }
.lvl-user-search-row .search-box { flex: 1; max-width: none; }

.lvl-user-card {
  border: 1px solid var(--panel-border);
  border-radius: 8px;
  padding: 16px;
  margin-top: 10px;
  background: color-mix(in srgb, var(--accent) 3%, transparent);
}
.lvl-user-card.hidden { display: none; }
.lvl-user-card-header { display: flex; align-items: center; gap: 12px; }
.lvl-user-card-header .track-subtitle { color: var(--text-dim); font-size: 12px; }
.lvl-user-rank {
  margin-left: auto;
  font-family: var(--font-mono);
  color: var(--accent);
  font-size: 20px;
  font-weight: bold;
}

.lvl-user-actions { margin-top: 18px; display: flex; flex-direction: column; gap: 14px; }
.lvl-action-group .dj-label { margin-bottom: 6px; }
.lvl-action-row { display: flex; gap: 8px; flex-wrap: wrap; }
.lvl-action-row input[type="number"] { min-width: 90px; }
.lvl-action-row .btn-outline { white-space: nowrap; }

.lvl-config-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-bottom: 6px;
}
.lvl-config-grid .dj-label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 12px;
  color: var(--text-dim);
}
.lvl-config-grid input { margin-top: 2px; }

.lvl-milestone-rewards-cell { display: flex; flex-wrap: wrap; gap: 6px; }
.lvl-reward-chip {
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border: 1px solid var(--accent-dim);
  color: var(--accent);
  border-radius: 20px;
  padding: 3px 10px;
  font-size: 11px;
}
.lvl-milestone-delete {
  background: none;
  border: 1px solid var(--panel-border);
  color: var(--danger);
  border-radius: 6px;
  padding: 6px 10px;
  cursor: pointer;
  font-size: 11px;
}
.lvl-milestone-delete:hover { border-color: var(--danger); background: rgba(255, 92, 92, 0.08); }

.lvl-preview-result.hidden { display: none; }
.lvl-preview-result { margin-top: 4px; }

.lvl-top3-row { display: flex; align-items: center; gap: 8px; padding: 6px 0; font-size: 12px; }
.lvl-top3-medal { font-size: 16px; width: 22px; text-align: center; }
.lvl-top3-name { flex: 1; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lvl-top3-xp { color: var(--text-dim); font-family: var(--font-mono); font-size: 11px; }

.lvl-banner-preview-wrap { margin: 10px 0; }
.lvl-banner-preview-wrap img { width: 100%; max-height: 220px; object-fit: cover; border-radius: 8px; display: block; }
.lvl-banner-preview-wrap img.hidden { display: none; }
.lvl-banner-empty { padding: 10px 0; }
.lvl-banner-empty.hidden { display: none; }

.lvl-banner-dropzone {
  border: 2px dashed var(--panel-border);
  border-radius: 8px;
  padding: 24px 16px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  color: var(--text-dim);
  font-size: 13px;
  transition: border-color 0.15s, background 0.15s;
}
.lvl-banner-dropzone:hover,
.lvl-banner-dropzone.drag-over {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 5%, transparent);
  color: var(--text);
}
.lvl-banner-dropzone .icon { width: 26px; height: 26px; color: var(--accent); }

/* ---------- Level-up template picker (Leveling page) ---------- */
.lvl-tpl-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 12px;
}
.lvl-tpl-card {
  position: relative;
  padding: 0;
  background: color-mix(in srgb, var(--accent) 4%, #050302);
  border: 1px solid var(--panel-border);
  border-radius: 10px;
  overflow: hidden;
  cursor: pointer;
  text-align: left;
  color: var(--text);
  font-family: inherit;
  transition: border-color 0.15s, transform 0.15s, box-shadow 0.15s;
}
.lvl-tpl-card:hover { border-color: var(--accent-dim); transform: translateY(-1px); }
.lvl-tpl-card.selected {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent), 0 0 16px color-mix(in srgb, var(--accent) 35%, transparent);
}
.lvl-tpl-thumb {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 5 / 2;
  background: #050302;
  overflow: hidden;
}
.lvl-tpl-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.lvl-tpl-thumb-classic {
  background: linear-gradient(135deg, #1a1200, #3a2400);
  color: var(--accent);
  font-size: 12px;
  letter-spacing: 2px;
  text-transform: uppercase;
}
.lvl-tpl-meta { display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 8px 10px; }
.lvl-tpl-name { font-size: 12px; font-weight: 600; }
.lvl-tpl-tags { display: flex; gap: 4px; }
.lvl-tpl-tag {
  font-size: 9px;
  letter-spacing: 1px;
  text-transform: uppercase;
  padding: 2px 6px;
  border-radius: 10px;
  border: 1px solid var(--accent-dim);
  color: var(--accent);
}

.lvl-tpl-preview { margin-top: 16px; border: 1px solid var(--panel-border); border-radius: 10px; padding: 12px; }
.lvl-tpl-preview-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.lvl-tpl-preview-name { font-size: 12px; letter-spacing: 1.5px; text-transform: uppercase; color: var(--accent); }
.lvl-tpl-preview-level { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--text-dim); }
.lvl-tpl-preview-level input { width: 80px; }
.lvl-tpl-preview-stage { display: flex; flex-direction: column; align-items: center; gap: 8px; min-height: 80px; justify-content: center; }
.lvl-tpl-preview-stage img { width: 100%; max-width: 760px; border-radius: 10px; display: block; }
.lvl-tpl-preview-stage img.hidden { display: none; }
.lvl-tpl-preview-stage img.loading { opacity: 0.45; }

/* ---------- Login page (login.html) ---------- */
.login-body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
}

.login-hero {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px 20px;
  background-image:
    linear-gradient(180deg, rgba(10, 7, 0, 0.35) 0%, rgba(10, 7, 0, 0.88) 62%, var(--bg) 100%),
    url('/login-bg.webp');
  background-size: cover;
  background-position: center 30%;
}

.login-card {
  max-width: 440px;
  text-align: left;
}
.login-card .brand { margin-bottom: 22px; }
.login-eyebrow {
  font-size: 11px;
  color: var(--accent);
  letter-spacing: 0.25em;
  text-transform: uppercase;
  margin: 0 0 10px 0;
  font-family: var(--font-mono);
}
.login-title { margin: 0 0 12px 0; font-size: 26px; color: var(--text); }
.login-copy { color: var(--text-dim); line-height: 1.55; margin-bottom: 22px; }
.login-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  background: var(--accent);
  color: #1a1200;
  font-weight: bold;
  padding: 13px 26px;
  border-radius: 6px;
  text-decoration: none;
  font-size: 15px;
}
.login-btn:hover { background: #ffc040; }
.login-back-link {
  display: block;
  text-align: center;
  margin-top: 14px;
  color: var(--text-dim);
  font-size: 12.5px;
  text-decoration: none;
}
.login-back-link:hover { color: var(--accent); }

/* ---------- Server picker dropdown ---------- */
.server-picker { cursor: pointer; position: relative; }
.server-dropdown {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  background: #0d0a05;
  border: 1px solid var(--panel-border);
  border-radius: 8px;
  padding: 6px;
  z-index: 30;
  max-height: 260px;
  overflow-y: auto;
}
.server-dropdown.hidden { display: none; }
.server-dropdown-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
  color: var(--text);
}
.server-dropdown-item:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.server-dropdown-item.active { color: var(--accent); }
.server-dropdown-item img { width: 20px; height: 20px; border-radius: 50%; }
.server-dropdown-empty { padding: 10px; font-size: 12px; color: var(--text-dim); }
.server-dropdown { max-height: 340px; }
.server-dropdown-label { padding: 8px 10px 4px; font-size: 10px; letter-spacing: 0.08em; color: var(--text-dim); }
.server-dropdown-item > span:not(.server-icon):not(.server-badge) { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.server-dropdown-item .server-icon {
  width: 20px; height: 20px; border-radius: 50%; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; background: color-mix(in srgb, var(--accent) 18%, transparent);
}
.server-badge { font-size: 10px; padding: 2px 7px; border-radius: 999px; white-space: nowrap; flex-shrink: 0; text-decoration: none; }
.server-badge.owner { color: var(--accent); border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent); }
.server-badge.invite { color: #0d0a05; background: var(--accent); font-weight: 600; }
.server-badge.invite:hover { filter: brightness(1.1); }
.server-badge.locked { color: var(--text-dim); border: 1px solid var(--panel-border); }
.server-item-locked { opacity: 0.55; cursor: not-allowed; }
.server-item-invite { cursor: default; }
.server-item-locked:hover, .server-item-invite:hover { background: transparent; }

/* ---------- User box / logout ---------- */
.logout-btn {
  background: none;
  border: 1px solid var(--panel-border);
  color: var(--text-dim);
  border-radius: 6px;
  padding: 6px 14px;
  cursor: pointer;
  font-family: var(--font);
  font-size: 12px;
}
.logout-btn:hover { border-color: var(--danger); color: var(--danger); }
.logout-btn:disabled { opacity: 0.5; cursor: default; }
.logout-btn:disabled:hover { border-color: var(--panel-border); color: var(--text-dim); }

/* ---------- Responsive: only collapse to a single stacked column at
   genuinely narrow (phone/small-tablet) widths, not a normal desktop or
   laptop window — that was 1000px before, which was too aggressive and
   collapsed the sidebar/right-rail even on reasonably-sized windows. ---------- */
@media (max-width: 640px) {
  .app { grid-template-columns: 1fr; }
  .sidebar { display: none; }
  .page.active { grid-template-columns: 1fr; }
  .now-playing-body { flex-direction: column; }
}

/* ---------------------------------------------------------------------
   Themed <select> — used by makeThemedSelect() in app.js. This never
   had ANY CSS backing it anywhere in this codebase (not even in the old
   unlinked style.css) — the wrapper divs existed in the DOM but with no
   styling, while the raw native <select> underneath was never actually
   hidden, so the native browser dropdown (white background, OS-default
   highlight color) was what people were really seeing all along.
------------------------------------------------------------------------ */
.themed-select {
  position: relative;
  display: inline-block;
  min-width: 180px;
}

/* The real <select> stays in the DOM and fully functional (still fires
   real 'change' events, still holds the real .value) — just made
   invisible and non-interactive, since all visible interaction now goes
   through .themed-select-display / .themed-select-list instead. */
.themed-select select {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  pointer-events: none;
}

.themed-select-display {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 6px;
  padding: 8px 10px;
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
  user-select: none;
  transition: border-color 0.15s ease;
}
.themed-select-display:hover { border-color: var(--accent-dim); }
.themed-select.open .themed-select-display { border-color: var(--accent); }
.themed-select-display-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.themed-select-display .icon {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  stroke: var(--text-dim);
  fill: none;
  stroke-width: 2;
  transition: transform 0.15s ease;
}
.themed-select.open .themed-select-display .icon { transform: rotate(180deg); }

.themed-select-list {
  display: none;
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 50;
  max-height: 240px;
  overflow-y: auto;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 6px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
}
.themed-select.open .themed-select-list { display: block; }

.themed-select-option {
  padding: 8px 10px;
  font-size: 13px;
  color: var(--text-dim);
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.themed-select-option:hover {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--text);
}
.themed-select-option.selected {
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}

/* ---------------------------------------------------------------------
   Settings page clarity pass — Settings is a dense, important admin
   surface, so it gets its own slightly larger/brighter typography
   rather than reusing the compact 12px --text-dim styling built for
   small dashboard status widgets elsewhere in the app.
------------------------------------------------------------------------ */
.settings-panel .panel-title {
  font-size: 15px;
  letter-spacing: 1px;
  margin-bottom: 16px;
}
.settings-panel .toggle-row {
  font-size: 14px;
  color: var(--text);
  padding: 10px 4px;
  border-bottom: 1px solid var(--panel-border);
}
.settings-panel .toggle-row:last-of-type { border-bottom: none; }
.settings-panel .status-row {
  font-size: 13px;
  color: var(--text);
  font-family: var(--font);
  padding: 8px 4px;
}
.settings-panel input[type="text"],
.settings-panel input[type="password"] {
  font-size: 13px;
  padding: 9px 10px;
}
.settings-panel .field-error {
  color: var(--danger);
  font-size: 12px;
  margin-top: 6px;
}

/* Settings tab bar — bigger, clearer active state so the current
   section is unambiguous at a glance. */
.settings-tab {
  font-size: 13px;
  font-weight: 600;
  padding: 12px 16px;
}
.settings-tab.active {
  color: var(--accent);
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}

/* API Keys rows — replaces plain colored text with proper badges, a
   masked key preview, and a distinct "this is the active AI provider"
   marker. */
.ak-key-row {
  padding: 12px 4px;
  border-bottom: 1px solid var(--panel-border);
}
.ak-key-row:last-of-type { border-bottom: none; }
.ak-key-row-header {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}
.ak-key-label { font-size: 14px; color: var(--text); }
.ak-key-preview {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-dim);
  letter-spacing: 1px;
}
.ak-badge {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 999px;
}
.ak-badge-good { color: var(--good); background: color-mix(in srgb, var(--good) 15%, transparent); }
.ak-badge-bad { color: var(--danger); background: color-mix(in srgb, var(--danger) 15%, transparent); }
.ak-badge-active { color: var(--accent); background: color-mix(in srgb, var(--accent) 18%, transparent); border: 1px solid var(--accent-dim); }

/* Log Channels / AI Config rows — same row/label clarity treatment. */
.settings-panel select {
  font-size: 13px;
}
/* =========================================================================
   HOME PAGE — welcome/landing screen shown first, before Dashboard/Music.
   Reuses existing tokens (--accent, --panel, --panel-border, .panel,
   .btn-outline, .status-good, .live-dot) so it matches the rest of the
   app instead of introducing a second visual language.
   ========================================================================= */
.home-wrap {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  gap: 34px;
  padding: 6px 2px 10px;
  /* Tall enough to reach the bottom of the viewport (minus the topbar)
     even when the hero + modules + marquee don't naturally fill it —
     that's what gives .home-bottom-block's margin-top: auto below
     something to push against, so MODULES+marquee land flush with the
     page's true bottom edge instead of stopping right under the hero.
     On genuinely tall content this has no effect — the wrap just grows
     past it like normal. */
  min-height: calc(100vh - 90px);
}

/* Groups the module grid + marquee so they move together as one block
   (see index.html) — margin-top: auto inside .home-wrap's flex column
   pushes this whole group down to the bottom, while the 34px gap
   between MODULES and the marquee stays exactly as tight as every
   other section, since they're not being pushed apart from each other,
   just together from the hero above them. */
.home-bottom-block {
  display: flex;
  flex-direction: column;
  gap: 34px;
  margin-top: auto;
}

/* ---------- Hero ---------- */
.home-hero {
  display: grid;
  grid-template-columns: 1fr 360px;
  gap: 32px;
  align-items: center;
  padding: 28px 6px 8px;
}
.home-hero-content { min-width: 0; }
.home-badge-pill {
  display: inline-flex; align-items: center; gap: 7px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid var(--accent-dim);
  color: var(--accent);
  font-size: 11px; letter-spacing: 0.5px; font-weight: 600;
  padding: 5px 12px; border-radius: 999px; margin-bottom: 18px;
}
.home-hero-title {
  font-size: 42px; line-height: 1.15; margin: 0 0 16px; letter-spacing: -0.5px;
  font-weight: 800;
}
.home-hero-title .accent-text { color: var(--accent); }
.home-hero-subtitle {
  color: var(--text-dim); font-size: 15px; line-height: 1.6; max-width: 520px; margin: 0 0 26px;
}
.home-hero-actions { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 30px; }
.btn-solid-accent {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--accent); color: #1a1200; border: 1px solid var(--accent);
  border-radius: 6px; padding: 11px 20px; cursor: pointer; font-family: var(--font);
  font-size: 14px; font-weight: 700;
  text-decoration: none;
  transition: background 0.15s, transform 0.1s, box-shadow 0.15s;
  box-shadow: 0 0 0 0 transparent;
}
.btn-solid-accent:hover { box-shadow: 0 0 24px color-mix(in srgb, var(--accent) 45%, transparent); }
.btn-solid-accent svg.icon { color: #1a1200; }
.btn-solid-accent:hover { background: #ffc040; }
.btn-solid-accent:active { transform: scale(0.97); }
.home-hero-actions .btn-outline { display: inline-flex; align-items: center; gap: 8px; padding: 11px 20px; font-size: 14px; }
.home-hero-stats { display: flex; gap: 34px; }
.home-stat { display: flex; flex-direction: column; gap: 3px; }
.home-stat-value { font-size: 22px; font-weight: 700; font-family: var(--font-mono); color: var(--text); }
.home-stat-label { font-size: 11px; color: var(--text-dim); letter-spacing: 0.5px; }

/* ---------- Hero preview card ---------- */
.home-preview { padding: 20px; }
.home-preview-header { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
.home-preview-avatar {
  width: 44px; height: 44px; border-radius: 50%; flex-shrink: 0;
  background-color: var(--panel); background-size: cover; background-position: center;
  border: 1px solid var(--panel-border);
}
.home-preview-name { font-size: 15px; font-weight: 700; }
.home-preview-sub { font-size: 12px; color: var(--text-dim); }
.home-preview-body { display: flex; flex-direction: column; gap: 9px; margin-bottom: 16px; }
.home-preview-row {
  display: flex; justify-content: space-between; align-items: center;
  font-size: 12.5px; color: var(--text-dim);
  padding-bottom: 9px; border-bottom: 1px solid var(--panel-border);
}
.home-preview-row:last-child { border-bottom: none; padding-bottom: 0; }
.home-preview-features {
  display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 16px;
}
.home-preview-features span {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11px; color: var(--text-dim);
  background: var(--panel); border: 1px solid var(--panel-border);
  border-radius: 999px; padding: 4px 10px 4px 8px;
}
.home-preview-features svg.icon { width: 12px; height: 12px; margin-right: 0; color: var(--accent); }
.home-preview-actions { display: flex; gap: 8px; }
.home-preview-actions .btn-outline { flex: 1; text-align: center; font-size: 12.5px; padding: 9px 10px; }

/* ---------- Section label ---------- */
.home-section-label {
  color: var(--accent); font-size: 12px; letter-spacing: 1.5px; font-weight: 700;
  padding: 0 6px;
}

/* ---------- Module grid ---------- */
.home-feature-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 14px;
  padding: 0 6px;
}
.home-feature-card {
  background: rgba(20, 16, 10, 0.42);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid var(--panel-border);
  border-radius: 10px;
  padding: 18px;
  cursor: pointer;
  transition: border-color 0.15s, transform 0.12s, background 0.15s;
}
.home-feature-card:hover {
  border-color: var(--accent-dim);
  background: color-mix(in srgb, var(--accent) 6%, rgba(20, 16, 10, 0.42));
  transform: translateY(-2px);
}
.home-feature-card:active { transform: translateY(0) scale(0.99); }
.home-feature-card svg.icon { width: 22px; height: 22px; color: var(--accent); margin-right: 0; margin-bottom: 12px; display: block; }
.home-feature-title { font-size: 14.5px; font-weight: 700; margin-bottom: 6px; }
.home-feature-desc { font-size: 12.5px; color: var(--text-dim); line-height: 1.5; }

/* ---------- Marquee ---------- */
.home-marquee {
  /* Sits directly after the module grid via the normal flex gap — the
     two move together as one unit (see .home-bottom-block above), so
     there's never a gap between MODULES and this regardless of where
     the block as a whole lands on the page. */
  overflow: hidden;
  border-top: 1px solid var(--panel-border);
  border-bottom: 1px solid var(--panel-border);
  /* Shorter row — was padding: 18px 0 at font-size: 20px (~56px tall
     including borders); trimmed both down for a slimmer strip. */
  padding: 10px 0;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.home-marquee-track {
  display: flex; align-items: center; gap: 18px; white-space: nowrap; width: max-content;
  font-size: 15px; font-weight: 700; color: var(--text-dim);
  animation: home-marquee-scroll 32s linear infinite;
}
.home-marquee-track:hover { animation-play-state: paused; }
.home-marquee-dot { color: var(--accent-dim); font-size: 14px; }
@keyframes home-marquee-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

@media (max-width: 1100px) {
  .home-hero { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
  .home-hero-title { font-size: 32px; }
  .home-hero-stats { gap: 22px; }
}

/* ---------- Tasks (Daily/Weekly Tasks + Boost Events) ----------
   No existing section uses in-page tabs (every other multi-view section
   is a separate sidebar sub-page instead), so this is a small,
   self-contained addition rather than repurposing something that
   doesn't quite fit. Everything else on the Tasks page reuses existing
   classes (.panel, .queue-table, .dj-overlay/.dj-panel, .dj-label/
   .dj-select, .btn-outline, .lvl-milestone-rewards-cell/.lvl-reward-chip,
   .lvl-milestone-delete, .field-error/.field-note) for visual
   consistency with the rest of the dashboard. */
.tsk-tabs { display: flex; gap: 6px; margin-bottom: 16px; flex-wrap: wrap; }
.tsk-tab {
  background: transparent; border: 1px solid var(--border); color: var(--text-dim);
  font: inherit; font-size: 12px; font-weight: 700; letter-spacing: 0.4px; text-transform: uppercase;
  padding: 8px 14px; border-radius: 8px; cursor: pointer; transition: all 0.15s ease;
}
.tsk-tab:hover { color: var(--text); border-color: var(--accent-dim); }
.tsk-tab.active { color: var(--accent); border-color: var(--accent); background: var(--accent-glow, rgba(255,255,255,0.04)); }

.tsk-reward-row { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; }
.tsk-reward-row .dj-select { flex: 1; }
.tsk-reward-row .tsk-reward-amount { max-width: 120px; }

.log-item { padding: 6px 8px; border-radius: 6px; background: var(--panel-alt, rgba(255,255,255,0.03)); }

/* ---------- Verification: captcha template gallery ----------
   Reuses .panel/.dj-label/.dj-select/.toggle-row/.switch/.btn-outline/
   .field-note/.field-error for everything else on the page — only the
   thumbnail grid itself needed new rules. */
.vf-template-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 12px;
  margin-top: 10px;
}
.vf-template-card {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 8px;
  cursor: pointer;
  transition: all 0.15s ease;
  background: var(--panel-alt, rgba(255,255,255,0.03));
}
.vf-template-card:hover { border-color: var(--accent-dim); }
.vf-template-card.selected { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; }
.vf-template-card img {
  width: 100%;
  height: auto;
  border-radius: 6px;
  display: block;
  background: #000;
}
.vf-template-name {
  font-size: 12px;
  font-weight: 700;
  margin-top: 6px;
  text-align: center;
  color: var(--text);
}
.vf-template-desc {
  font-size: 11px;
  color: var(--text-dim);
  text-align: center;
  margin-top: 2px;
}
.vf-slider-row { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
.vf-slider-row input[type="range"] { flex: 1; }
.vf-slider-value { min-width: 28px; text-align: center; font-weight: 700; color: var(--accent); }
.vf-gate-status { display: flex; align-items: center; gap: 8px; margin-top: 10px; font-size: 12px; color: var(--text-dim); }
.vf-gate-status .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--text-dim); }
.vf-gate-status .dot.live { background: #2ecc71; }
.vf-role-list {
  max-height: 180px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.vf-role-checkbox-row { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text); }
.vf-role-checkbox-row input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--accent); }
.vf-role-empty { font-size: 12px; color: var(--text-dim); padding: 4px 0; }

/* --- AI Config: token meter + feature switches --- */
.aiu-meter { margin: 10px 0; }
.aiu-meter-head { display: flex; justify-content: space-between; font-size: 12px; margin-bottom: 4px; }
.aiu-track { height: 10px; border-radius: 5px; background: color-mix(in srgb, var(--accent) 10%, transparent); border: 1px solid var(--panel-border); overflow: hidden; }
.aiu-fill { height: 100%; width: 0; background: var(--accent); border-radius: 5px; transition: width .4s ease, background .3s ease; }
.aiu-fill.warn { background: #ff8c42; }
.aiu-fill.danger { background: var(--danger); }
.aiu-hourly { display: flex; align-items: flex-end; gap: 2px; height: 48px; margin-top: 4px; }
.aiu-hourly span { flex: 1; min-height: 2px; background: color-mix(in srgb, var(--accent) 70%, transparent); border-radius: 2px 2px 0 0; }
.aiu-group { margin-top: 12px; font-size: 11px; letter-spacing: 1px; text-transform: uppercase; opacity: .7; }
.aiu-feature .aiu-feature-text { flex: 1; padding-right: 12px; }
.aiu-feature .aiu-feature-desc { display: block; font-size: 11px; opacity: .65; margin-top: 2px; }
.aiu-feature .aiu-feature-tokens { font-size: 12px; opacity: .8; min-width: 70px; text-align: right; padding-right: 12px; white-space: nowrap; }
.aiu-feature.aiu-off .aiu-feature-text, .aiu-feature.aiu-dim { opacity: .55; }
.aiu-tag { font-size: 10px; border: 1px solid var(--panel-border); border-radius: 8px; padding: 0 6px; margin-left: 6px; opacity: .8; }
.settings-panel input[type="number"] {
  background: var(--bg); border: 1px solid var(--panel-border); color: var(--text);
  font-family: var(--font); font-size: 13px; padding: 9px 10px; border-radius: 6px; outline: none;
}
.settings-panel input[type="number"]:focus { border-color: var(--accent); }


/* ---------- Server selection pop-up ---------- */
.srv-modal {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  padding: 16px;
  /* Light scrim so the dashboard background (image/video) still shows through. */
  background: rgba(0, 0, 0, 0.3);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}
.srv-modal.hidden { display: none; }
.srv-panel {
  width: min(520px, 100%);
  max-height: min(78vh, 640px);
  display: flex; flex-direction: column; gap: 10px;
  padding: 16px;
  /* Same translucent glass as .panel / .sidebar (slightly denser so the
     scrolling text stays readable over busy backgrounds). */
  background: rgba(20, 16, 10, 0.5);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--panel-border);
  border-radius: 12px;
  box-shadow: 0 18px 60px rgba(0, 0, 0, 0.35);
}
.srv-head { display: flex; align-items: center; justify-content: space-between; }
.srv-title { font-size: 15px; font-weight: 700; color: var(--accent); letter-spacing: 0.02em; }
.srv-close {
  background: transparent; border: 0; color: var(--text-dim);
  font-size: 24px; line-height: 1; cursor: pointer; padding: 0 6px;
}
.srv-close:hover { color: var(--text); }
.srv-search {
  width: 100%; box-sizing: border-box;
  background: rgba(0, 0, 0, 0.22); color: var(--text);
  border: 1px solid var(--panel-border); border-radius: 8px;
  padding: 10px 12px; font-size: 13px; font-family: var(--font);
}
.srv-search:focus { outline: none; border-color: var(--accent); }
.srv-filters { display: flex; gap: 6px; flex-wrap: wrap; }
.srv-chip {
  background: transparent; color: var(--text-dim);
  border: 1px solid var(--panel-border); border-radius: 999px;
  padding: 4px 12px; font-size: 11px; cursor: pointer; font-family: var(--font);
}
.srv-chip:hover { color: var(--text); }
.srv-chip.active { color: #0d0a05; background: var(--accent); border-color: var(--accent); font-weight: 600; }
.srv-list {
  flex: 1; min-height: 120px;
  overflow-y: auto; overscroll-behavior: contain;
  display: flex; flex-direction: column; gap: 4px;
  padding-right: 4px;
}
.srv-list::-webkit-scrollbar { width: 8px; }
.srv-list::-webkit-scrollbar-thumb { background: var(--panel-border); border-radius: 8px; }
.srv-section { padding: 10px 4px 2px; font-size: 10px; letter-spacing: 0.08em; color: var(--text-dim); }
.srv-section span { color: var(--accent); margin-left: 4px; }
.srv-row {
  display: flex; align-items: center; gap: 12px;
  padding: 9px 10px; border-radius: 8px;
  border: 1px solid transparent;
  cursor: pointer;
}
.srv-row { background: rgba(255, 255, 255, 0.03); }
.srv-row:hover, .srv-row:focus-visible { background: color-mix(in srgb, var(--accent) 12%, transparent); outline: none; }
.srv-row.active { border-color: color-mix(in srgb, var(--accent) 45%, transparent); background: color-mix(in srgb, var(--accent) 8%, transparent); }
.srv-row img, .srv-row .server-icon { width: 36px; height: 36px; border-radius: 50%; flex-shrink: 0; object-fit: cover; font-size: 15px; }
.srv-info { flex: 1; min-width: 0; }
.srv-name { font-size: 13px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.srv-sub { font-size: 11px; color: var(--text-dim); margin-top: 2px; }
.srv-go { font-size: 11px; color: var(--accent); white-space: nowrap; }
.srv-row-static { cursor: default; }
.srv-row-static:hover { background: rgba(255, 255, 255, 0.03); }
.srv-row-locked { opacity: 0.55; cursor: not-allowed; }
.srv-empty { padding: 18px 8px; text-align: center; font-size: 12px; color: var(--text-dim); }
@media (max-width: 520px) {
  .srv-modal { align-items: flex-end; padding: 0; }
  .srv-panel { width: 100%; max-height: 85vh; border-radius: 14px 14px 0 0; }
}
.srv-row .server-icon {
  display: inline-flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); font-weight: 700;
}
.srv-notice {
  padding: 8px 10px; font-size: 11px; color: var(--text-dim);
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
  border-radius: 8px;
}
.srv-notice a { color: var(--accent); font-weight: 600; }
