/* =========================================================================
   App shell layout: boot loader, login, server-selection homepage, and the
   per-server dashboard (sidebar + topbar + content). Includes the responsive
   drawer behaviour for tablet/mobile.
   ========================================================================= */

/* --------------------------------------------------------------- boot loader */
.boot-loader {
  position: fixed; inset: 0; z-index: 100;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--s-4); background: var(--bg);
  transition: opacity var(--t-slow), visibility var(--t-slow);
}
.boot-loader.hidden { opacity: 0; visibility: hidden; display: flex !important; pointer-events: none; }
.boot-loader.hidden .boot-ring { animation: none; }
.boot-ring {
  width: 52px; height: 52px; border-radius: 50%;
  border: 3px solid var(--red-tint); border-top-color: var(--red-bright);
  animation: spin 0.8s linear infinite;
}
.boot-status { color: var(--text-2); font-size: var(--fs-sm); min-height: 1em; opacity: 0; transition: opacity var(--t); }
.boot-status.visible { opacity: 1; }

/* --------------------------------------------------------------- login */
.auth-screen {
  min-height: 100vh; display: grid; place-items: center; padding: var(--s-5);
  animation: fadeIn var(--t-slow);
}
.auth-card {
  width: 100%; max-width: 400px;
  background: linear-gradient(180deg, var(--bg-elevated), var(--bg-card));
  border: 1px solid var(--border-strong);
  border-radius: var(--r-xl);
  padding: var(--s-8) var(--s-7);
  box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column; gap: var(--s-3);
  text-align: center;
  position: relative; overflow: hidden;
  animation: authCardRiseIn 680ms cubic-bezier(0.16, 1, 0.3, 1) backwards;
}
@keyframes authCardRiseIn {
  from { opacity: 0; transform: translateY(min(38vh, 320px)) scale(0.97); }
  72% { opacity: 1; }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
.auth-card::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 3px;
  background: linear-gradient(90deg, transparent, var(--red-bright), transparent);
}
.auth-mark {
  width: 64px; height: 64px; margin: 0 auto var(--s-2);
  border-radius: var(--r-lg);
  background: linear-gradient(145deg, var(--red-bright), var(--red-hover));
  display: grid; place-items: center;
  font-weight: 800; font-size: 1.5rem; color: #fff; letter-spacing: -0.03em;
  box-shadow: var(--shadow-red);
  overflow: hidden;
}
.auth-mark img { width: 100%; height: 100%; object-fit: cover; }
/* Roblox verification callback page (roblox_routes.py) result icon --
   a real circle with a soft glow (matching .auth-mark's box-shadow above it)
   instead of the small rounded-square pill those classes are normally on. */
.auth-result-icon {
  width: 60px; height: 60px; margin: 0 auto var(--s-3);
  border-radius: 50%; display: grid; place-items: center;
  border-width: 1px;
}
.auth-result-icon svg { width: 28px; height: 28px; }
.auth-result-icon.badge-success { box-shadow: 0 0 22px rgba(50, 213, 131, 0.35); }
.auth-result-icon.badge-error { box-shadow: 0 0 22px rgba(255, 93, 104, 0.35); }
.auth-card h1 { font-size: var(--fs-2xl); }
.auth-legal { font-size: var(--fs-xs); margin-top: var(--s-1); }
.auth-legal a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.auth-legal a:hover { color: var(--text); }
.auth-card .field, .auth-card input { text-align: left; }
.auth-card input {
  width: 100%; background: var(--bg-input);
  border: 1px solid var(--border); border-radius: var(--r-sm);
  padding: 12px 14px; transition: border-color var(--t), box-shadow var(--t);
}
.auth-card input:focus { border-color: var(--border-red); box-shadow: var(--ring); }
.auth-screen.is-discord-leaving .auth-card { animation: authDiscordCommit 560ms cubic-bezier(0.22, 0.76, 0.28, 1) both; }
.auth-screen.is-discord-leaving .auth-mark { animation: authMarkCommit 560ms cubic-bezier(0.22, 0.76, 0.28, 1) both; }
.auth-screen.is-discord-leaving .auth-card h1,
.auth-screen.is-discord-leaving .auth-card > p:not(#login-error) { animation: authCopyCommit 420ms var(--ease) forwards; }
@keyframes authDiscordCommit {
  45% { transform: translateY(-5px) scale(1.012); border-color: rgba(88, 101, 242, 0.55); box-shadow: 0 24px 70px -28px rgba(88, 101, 242, 0.7); }
  to { transform: translateY(-9px) scale(0.985); opacity: 0.82; border-color: rgba(88, 101, 242, 0.42); }
}
@keyframes authMarkCommit {
  40% { transform: translateY(-3px) rotate(-3deg) scale(1.08); box-shadow: 0 0 0 5px rgba(88, 101, 242, 0.10), var(--shadow-red); }
  to { transform: translateY(-2px) rotate(0) scale(0.96); opacity: 0.8; }
}
@keyframes authCopyCommit { to { opacity: 0.44; transform: translateY(-3px); } }
.auth-divider { display: flex; align-items: center; gap: var(--s-3); color: var(--text-muted); font-size: var(--fs-xs); margin: var(--s-1) 0; }
.auth-divider::before, .auth-divider::after { content: ""; flex: 1; height: 1px; background: var(--border); }
.auth-hint { color: var(--text-muted); font-size: var(--fs-xs); margin-top: var(--s-2); }
.auth-desc { font-size: var(--fs-sm); line-height: 1.5; margin-top: calc(var(--s-1) * -1); }

/* =======================================================================
   SERVER-SELECTION HOMEPAGE
   ======================================================================= */
.select-shell { display: grid; grid-template-columns: var(--sidebar-w) 1fr; min-height: 100vh; }

.select-sidebar, .dash-sidebar {
  position: sticky; top: 0; align-self: start;
  height: 100vh; overflow-x: hidden; overflow-y: auto;
  background: var(--bg-sidebar);
  border-right: 1px solid var(--border);
  display: flex; flex-direction: column;
  padding: var(--s-5) var(--s-4);
  gap: var(--s-2);
  /* Otherwise scrolling to the end of the sidebar's own scroll range lets
     the same wheel gesture "chain" into scrolling the main page behind it. */
  overscroll-behavior: contain;
}
/* The dash sidebar's nav list scrolls on its own; brand/search stay put at the
   top and the footer stays put at the bottom, so collapsing the footer menu
   (or a long nav list) never shifts or scrolls the search box out of view. */
.dash-sidebar { overflow-y: hidden; }
.dash-sidebar .settings-search { flex: none; }
/* No flex-grow: the nav list sizes to its own content (sidebar-spacer below
   still pushes the footer down), and only shrinks + scrolls on its own once
   the whole sidebar's content can't fit in the viewport. */
.dash-nav { overflow-y: auto; min-height: 0; overscroll-behavior: contain; }

/* brand block shared by both sidebars */
.brand { display: flex; align-items: center; gap: var(--s-3); padding: var(--s-2) var(--s-2) var(--s-4); }
.brand-mark {
  width: 40px; height: 40px; border-radius: 12px; flex: none;
  background: linear-gradient(145deg, var(--red-bright), var(--red-hover));
  display: grid; place-items: center; color: #fff; font-weight: 800; letter-spacing: -0.03em;
  box-shadow: 0 6px 18px -6px var(--red-glow-strong);
  overflow: hidden;
}
.brand-mark img { width: 100%; height: 100%; object-fit: cover; }
.brand-copy { min-width: 0; }
.brand-name { font-weight: 700; font-size: var(--fs-md); letter-spacing: -0.01em; }
.brand-sub { color: var(--text-muted); font-size: var(--fs-xs); display: flex; align-items: center; gap: 6px; }

/* generic sidebar nav item */
.nav-item {
  display: flex; align-items: center; gap: var(--s-3);
  padding: 9px 11px; border-radius: var(--r-sm);
  color: var(--text-2); cursor: pointer; background: transparent;
  /* Real (transparent) border instead of an inset box-shadow ring: a
     box-shadow ring drawn on top of a rounded gradient background
     anti-aliases on a different pass than the corner clip and left a
     hairline seam at the top edge on hover/active in Chrome. A border
     participates in the same box as border-radius, so the corner is
     always consistent. */
  border: 1px solid transparent; background-clip: padding-box;
  width: 100%; text-align: left; font-size: var(--fs-md); font-weight: 500;
  /* Background/color intentionally untransitioned -- instant hover feedback. */
  transition: border-color var(--t-fast);
  position: relative;
}
.nav-item:hover { background: var(--bg-hover); color: var(--text); }
.nav-item.active, .nav-item.active:hover {
  background: var(--red-tint); color: var(--red-bright); border-color: transparent;
  box-shadow: inset 3px 0 0 var(--red-bright);
}
.nav-item.active::before { display: none; }
/* The two legal links are anchors, not buttons -- strip the default
   underline/visited colour so they sit flush with the button nav items. */
a.nav-item { text-decoration: none; }
a.nav-item:visited { color: var(--text-2); }
a.nav-item:hover, a.nav-item:visited:hover { color: var(--text); }
.nav-item svg { width: 18px; height: 18px; flex: none; }
.nav-item .nav-badge { margin-left: auto; }

.sidebar-spacer { flex: 1; }
.sidebar-foot { border-top: 1px solid var(--border); padding-top: var(--s-3); margin-top: var(--s-3); display: flex; flex-direction: column; gap: var(--s-1); }

/* collapsible group of secondary footer items (All servers / My account / Accounts / Dark theme) */
.sidebar-foot-menu {
  display: flex; flex-direction: column; gap: var(--s-1);
  max-height: 400px; opacity: 1; overflow: hidden;
  transition: max-height var(--t), opacity var(--t), margin var(--t);
}
.sidebar-foot-menu.collapsed { max-height: 0; opacity: 0; pointer-events: none; }

/* user block at bottom of sidebar */
.user-block { display: flex; align-items: center; gap: var(--s-2); padding: var(--s-3) var(--s-2); border-radius: var(--r-sm); }
.user-block .user-copy { min-width: 0; flex: 1; }
.user-block .user-name { font-weight: 600; font-size: var(--fs-sm); }
.user-block .user-role { font-size: var(--fs-xs); }

.user-menu-toggle {
  display: flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; flex: none; border-radius: var(--r-sm);
  background: transparent; border: none; color: var(--text-muted); cursor: pointer;
  transition: background var(--t), color var(--t), transform var(--t);
}
.user-menu-toggle:hover { background: var(--bg-hover); color: var(--text); }
.user-menu-toggle svg { transition: transform var(--t); }
.user-menu-toggle.is-collapsed svg { transform: rotate(-90deg); }

.logout-btn-inline {
  display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; flex: none; margin-left: auto; border-radius: var(--r-sm);
  background: transparent; border: none; color: var(--text-muted); cursor: pointer;
  transition: background var(--t), color var(--t);
}
.logout-btn-inline:hover { background: var(--red-tint); color: var(--red-bright); }

/* ---- select main area */
.select-main { padding: var(--s-8) var(--s-8) var(--s-9); max-width: var(--content-max); width: 100%; margin: 0 auto; }
.select-head { margin-bottom: var(--s-6); }
.select-head h1 { font-size: var(--fs-3xl); margin-bottom: var(--s-2); }
.select-head p { color: var(--text-2); max-width: 60ch; }
.select-controls { display: flex; gap: var(--s-3); flex-wrap: wrap; align-items: center; margin: var(--s-6) 0; }
.search-box {
  display: flex; align-items: center; gap: var(--s-2); flex: 1; min-width: 220px;
  background: var(--bg-input); border: 1px solid var(--border);
  border-radius: var(--r-sm); padding: 0 12px;
  transition: border-color var(--t), box-shadow var(--t);
}
.search-box:focus-within { border-color: var(--border-red); box-shadow: var(--ring); }
.search-box svg { color: var(--text-muted); flex: none; }
.search-box input { flex: 1; background: transparent; border: none; padding: 11px 0; }
.search-box input:focus { outline: none; box-shadow: none; }

.select-section-title {
  display: flex; align-items: center; gap: var(--s-3);
  margin: var(--s-7) 0 var(--s-4); font-size: var(--fs-lg); font-weight: 650;
}
.select-section-title:first-of-type { margin-top: var(--s-2); }
.select-section-title .count { color: var(--text-muted); font-weight: 500; font-size: var(--fs-sm); }
.select-section-title .link {
  margin-left: auto; font-size: var(--fs-sm); color: var(--red-bright); cursor: pointer; font-weight: 500;
}

.server-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: var(--s-4);
}

/* server card */
.server-card {
  display: flex; align-items: center; gap: var(--s-3);
  background: linear-gradient(180deg, var(--bg-card), var(--bg-card-2));
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: var(--s-4);
  cursor: pointer;
  transition: transform var(--t) var(--ease), border-color var(--t), box-shadow var(--t), background var(--t);
  position: relative; overflow: hidden;
  animation: fadeUp var(--t-slow) var(--ease-out) both;
}
.server-card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 2px;
  pointer-events: none;
  border-radius: inherit;
  background: linear-gradient(90deg, transparent, var(--red-bright), transparent);
  opacity: 0;
  transition: opacity var(--t);
}
.server-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-red); }
.server-card:hover::before { opacity: 1; }
.server-card:focus-visible { border-color: var(--border-red); box-shadow: var(--ring-focus); }
.server-card .avatar { width: 52px; height: 52px; border-radius: 14px; }
.server-card .sc-body { min-width: 0; flex: 1; }
.server-card .sc-name { font-weight: 650; font-size: var(--fs-md); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.server-card .sc-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 4px; }
.server-card .sc-arrow { color: var(--text-muted); transition: opacity var(--t), visibility var(--t), transform var(--t), color var(--t); flex: none; }
.server-card:hover .sc-arrow { color: var(--red-bright); transform: translateX(3px); }
.server-card.hide-control-active .sc-arrow,
/* The hide button appears on any card hover/focus (not just hovering the
   button itself, which is all hide-control-active tracks) -- so the arrow
   has to fade out on that same trigger, or hovering anywhere else on the
   card left both visible at once, overlapping in the top-right corner. */
.server-card:hover .sc-arrow,
.server-card:focus-within .sc-arrow {
  opacity: 0;
  visibility: hidden;
  transform: translateX(0);
}
.server-card.is-opening .sc-arrow {
  opacity: 1;
  visibility: visible;
}
.server-card.is-opening {
  pointer-events: none; border-color: var(--red-bright);
  box-shadow: var(--shadow-red), inset 0 0 0 1px var(--border-red);
  animation: serverCardOpen 440ms var(--ease-out) both;
}
.server-card.is-opening .sc-arrow { color: var(--red-bright); transform: translateX(5px); }
/* The click-to-enter animation still counts as a hover (the pointer is still
   over the card), which brought the hide button back just as the arrow's own
   is-opening rule (above) was un-hiding it -- same overlap, now during the
   transition instead of a plain hover. */
.server-card.is-opening .card-hide-btn { opacity: 0 !important; }
@keyframes serverCardOpen {
  45% { transform: translateY(-3px) scale(1.012); }
  to { transform: translateY(-1px) scale(0.995); opacity: 0.86; }
}
::view-transition-old(selected-server),
::view-transition-new(selected-server) { animation-duration: 420ms; animation-timing-function: var(--ease-out); }
::view-transition-old(root) { animation: fadeOut 220ms var(--ease) both; }
::view-transition-new(root) { animation: fadeIn 320ms var(--ease-out) both; }

/* Small secondary action: present on focus/touch, otherwise it stays out of
   the way until the card is intentionally inspected. */
.card-hide-btn {
  position: absolute;
  top: var(--s-3);
  right: var(--s-3);
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--r-xs);
  background: color-mix(in srgb, var(--bg-elevated) 88%, transparent);
  color: var(--text-muted);
  cursor: pointer;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity var(--t), transform var(--t) var(--ease), color var(--t), background var(--t), border-color var(--t), box-shadow var(--t);
}
.server-card:hover .card-hide-btn,
.server-card:focus-within .card-hide-btn {
  opacity: 1;
  transform: none;
}
.card-hide-btn:hover {
  color: var(--red-bright);
  background: var(--red-tint);
  border-color: var(--border-red);
  box-shadow: 0 6px 16px -10px var(--red-glow-strong);
}
.card-hide-btn:focus-visible {
  opacity: 1;
  transform: none;
  border-color: var(--red-bright);
}

@media (hover: none) {
  .card-hide-btn { opacity: 1; transform: none; }
  /* Touch devices cannot reveal one action on hover and swap it with the
     other. Give the persistent hide action the card's trailing slot and
     remove the decorative enter arrow from regular server cards. */
  .server-card:not(.card-invite) .sc-arrow {
    opacity: 0;
    visibility: hidden;
  }
}

/* invite / add card */
.server-card.card-invite {
  border-style: dashed; background: var(--red-tint-2);
}
.server-card.card-invite .avatar { background: var(--red-tint); color: var(--red-bright); }

/* disabled "other servers" card */
.server-card.card-muted { cursor: not-allowed; opacity: 0.62; }
.server-card.card-muted:hover { transform: none; border-color: var(--border); box-shadow: var(--shadow-md); }
.server-card.card-muted .sc-arrow { display: none; }

/* =======================================================================
   PER-SERVER DASHBOARD
   ======================================================================= */
.dash-shell {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  width: 100%;
  max-width: 100%;
  min-width: 0;
  min-height: 100vh;
}

.dash-sidebar { z-index: var(--z-sidebar); }

/* server switcher pill in dash sidebar */
.server-switch {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-2) var(--s-3); border-radius: var(--r-sm);
  background: var(--bg-input); border: 1px solid var(--border);
  cursor: pointer; width: 100%; text-align: left; margin-bottom: var(--s-2);
  transition: border-color var(--t), background var(--t);
}
.server-switch:hover { border-color: var(--border-strong); background: var(--bg-hover); }
.server-switch .avatar { width: 34px; height: 34px; border-radius: 10px; }
.server-switch .ss-copy { min-width: 0; flex: 1; }
.server-switch .ss-name { font-weight: 600; font-size: var(--fs-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.server-switch .ss-sub { color: var(--text-muted); font-size: var(--fs-xs); }
.server-switch .ss-caret { color: var(--text-muted); flex: none; }

/* settings search */
.settings-search { margin-bottom: var(--s-3); }

/* nav categories + accordion */
.nav-cat { margin-top: var(--s-4); }
.nav-cat-label {
  padding: 0 12px var(--s-2); font-size: var(--fs-xs); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted);
}
.nav-group { }
.nav-group > .nav-item .nav-chevron { margin-left: auto; transition: transform var(--t); color: var(--text-muted); }
.nav-group.open > .nav-item .nav-chevron { transform: rotate(90deg); }
.nav-sub {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows var(--t-slow) var(--ease);
}
.nav-group.open .nav-sub { grid-template-rows: 1fr; }
.nav-sub-inner { overflow: hidden; }
.nav-subitem {
  display: flex; align-items: center; gap: var(--s-2);
  padding: 8px 12px 8px 40px; border-radius: var(--r-xs);
  color: var(--text-2); cursor: pointer; border: none; background: transparent;
  width: 100%; text-align: left; font-size: var(--fs-sm);
  /* Background/color intentionally untransitioned -- instant hover feedback. */
  position: relative;
}
.nav-subitem::before {
  content: ""; position: absolute; left: 21px; top: 0; bottom: 0; width: 1px; background: var(--border);
}
.nav-subitem:hover { background: var(--bg-hover); color: var(--text); }
.nav-subitem[data-panel="tickets_panels"] { display: none; }
.nav-subitem.active, .nav-subitem.active:hover { color: var(--red-bright); font-weight: 600; background: var(--red-tint); }
.nav-subitem.active::before { background: var(--red-bright); }

/* ---- dashboard main column */
.dash-main { display: flex; flex-direction: column; min-width: 0; }

.dash-topbar {
  position: sticky; top: 0; z-index: var(--z-topbar);
  display: flex; align-items: center; gap: var(--s-4);
  padding: 0 var(--s-6); height: var(--topbar-h);
  background: color-mix(in srgb, var(--bg-sidebar) 96%, var(--bg) 4%);
  border-bottom: 1px solid var(--border);
}
.dash-topbar .breadcrumbs { display: flex; align-items: center; gap: 8px; font-size: var(--fs-sm); color: var(--text-2); min-width: 0; }
.dash-topbar .breadcrumbs .crumb-sep { color: var(--text-muted); }
.dash-topbar .breadcrumbs .crumb-current { color: var(--text); font-weight: 600; }
.dash-topbar .topbar-actions { margin-left: auto; display: flex; align-items: center; gap: var(--s-3); }
.last-updated { font-size: var(--fs-xs); color: var(--text-muted); }

.dash-content { padding: var(--s-6) var(--s-6) var(--s-9); max-width: var(--content-max); width: 100%; margin: 0 auto; flex: 1; }
.page-head { margin-bottom: var(--s-5); }
.page-head h1 { font-size: var(--fs-2xl); margin-bottom: 2px; }
.page-head p { color: var(--text-2); }

/* Every sidebar destination enters with the same bottom-to-top motion. Using
   one direction keeps overview, management, engagement, and admin pages from
   feeling like different navigation systems. */
.panel { animation: panelIn 300ms cubic-bezier(0.22, 0.76, 0.28, 1) both; }
@keyframes panelIn {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}

/* Staggered reveal for the blocks inside a freshly navigated panel: each of
   the first few children starts fractionally later, so a page assembles
   itself instead of snapping in as one slab. Capped at 6 — beyond that the
   delay would be perceived as the page being slow rather than deliberate.
   `both` holds the from-state during the delay so nothing flashes first. */
.panel > .card,
.panel > .stat-row,
.panel > .settings-card-grid,
.panel > .list-heading,
.panel > .lb-list,
.panel > .overview-2col { animation: panelChildIn 420ms var(--ease-out) both; }
/* Delays are scoped to the same selector list on purpose: a bare
   `.panel > *:nth-child()` would also retime any unrelated animation a
   different child happens to own. */
.panel > .card:nth-child(2),
.panel > .stat-row:nth-child(2),
.panel > .settings-card-grid:nth-child(2),
.panel > .list-heading:nth-child(2),
.panel > .lb-list:nth-child(2),
.panel > .overview-2col:nth-child(2) { animation-delay: 40ms; }
.panel > .card:nth-child(3),
.panel > .stat-row:nth-child(3),
.panel > .settings-card-grid:nth-child(3),
.panel > .list-heading:nth-child(3),
.panel > .lb-list:nth-child(3),
.panel > .overview-2col:nth-child(3) { animation-delay: 80ms; }
.panel > .card:nth-child(4),
.panel > .stat-row:nth-child(4),
.panel > .settings-card-grid:nth-child(4),
.panel > .list-heading:nth-child(4),
.panel > .lb-list:nth-child(4),
.panel > .overview-2col:nth-child(4) { animation-delay: 115ms; }
.panel > .card:nth-child(n + 5),
.panel > .stat-row:nth-child(n + 5),
.panel > .settings-card-grid:nth-child(n + 5),
.panel > .list-heading:nth-child(n + 5),
.panel > .lb-list:nth-child(n + 5),
.panel > .overview-2col:nth-child(n + 5) { animation-delay: 150ms; }
@keyframes panelChildIn {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

/* The router keeps the outgoing panel's height until the browser has had a
   moment to scroll home, then eases into the incoming page's footprint. */
#panel-host.is-page-resizing {
  overflow: visible;
  transition: height 300ms cubic-bezier(0.22, 0.76, 0.28, 1);
  will-change: height;
}
/* grid used inside settings panels */
.grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-3); }
.grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-3); }
.grid-auto { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: var(--s-3); }
.stat-row { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: var(--s-3); }
.wide { grid-column: 1 / -1; }

/* gated (conditionally shown) sections */
[data-gate].gated-off { display: none; }
[data-gate] { overflow-anchor: none; transition: opacity var(--t), transform var(--t); }
[data-gate].gating-out { opacity: 0; transform: translateY(-4px); }
[data-gate].gate-splash { animation: gateReveal 240ms var(--ease-out); }
@keyframes gateReveal { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

/* =======================================================================
   RESPONSIVE
   ======================================================================= */
.mobile-topbar { display: none; }
.sidebar-backdrop {
  display: none; position: fixed; inset: 0; z-index: calc(var(--z-sidebar) - 1);
  background: rgba(4, 5, 9, 0.72);
  animation: fadeIn var(--t);
}

@media (max-width: 1080px) {
  .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 900px) {
  :root { --sidebar-w: 248px; }
  .select-shell, .dash-shell {
    grid-template-columns: minmax(0, 1fr);
    width: 100%;
    max-width: 100%;
    min-width: 0;
  }
  .select-main, .dash-main, .dash-content, .dash-topbar, .mobile-topbar,
  #panel-host, .panel {
    width: 100%;
    max-width: 100%;
    min-width: 0;
  }

  /* sidebars become slide-in drawers */
  .select-sidebar, .dash-sidebar {
    position: fixed; top: 0; left: 0; z-index: var(--z-modal);
    width: var(--sidebar-w); height: 100vh;
    transform: translateX(-100%);
    transition: transform var(--t-slow) var(--ease);
    box-shadow: var(--shadow-lg);
  }
  body.drawer-open .select-sidebar,
  body.drawer-open .dash-sidebar { transform: translateX(0); }
  body.drawer-open .sidebar-backdrop { display: block; }

  .mobile-topbar {
    display: flex; align-items: center; gap: var(--s-3);
    position: sticky; top: 0; z-index: var(--z-topbar);
    height: 56px; padding: 0 var(--s-4);
    background: color-mix(in srgb, var(--bg-sidebar) 97%, var(--bg) 3%);
    border-bottom: 1px solid var(--border);
  }
  .mobile-topbar .m-title { font-weight: 650; flex: 1; }
  .mobile-command-trigger {
    width: 36px; height: 36px; flex: none; display: grid; place-items: center;
    border: 1px solid var(--border); border-radius: var(--r-sm);
    background: var(--bg-card-2); color: var(--text-2); cursor: pointer;
  }
  .dash-topbar .command-trigger { display: none; }
  .hamburger {
    width: 40px; height: 40px; border: 1px solid var(--border); border-radius: var(--r-sm);
    background: var(--bg-card-2); display: grid; place-items: center; cursor: pointer;
  }
  .dash-topbar { top: 56px; }
  .select-main, .dash-content { padding-left: var(--s-4); padding-right: var(--s-4); padding-top: var(--s-5); }
  .select-main h1 { font-size: var(--fs-2xl); }
}

@media (max-width: 640px) {
  .grid-2, .grid-3 { grid-template-columns: 1fr; }
  .server-grid { grid-template-columns: 1fr; }
  .dash-topbar { padding: 0 var(--s-4); }
  .modal-foot { flex-direction: column-reverse; }
  .modal-foot .btn { width: 100%; }
}

/* ---- light-theme: the frosted bars used a hardcoded dark tint ---- */
:root[data-theme="light"] .dash-topbar,
:root[data-theme="light"] .mobile-topbar { background: rgba(255, 255, 255, 0.85); }

/* theme toggle button matches the sidebar nav items */
.theme-toggle-btn .theme-ic { display: inline-flex; }
