:root {
  --sidebar-width: 250px;
  --sidebar-collapsed-width: 76px;
  --brand: #4f46e5;
  --brand-dark: #3730a3;
}

body {
  background-color: #f4f6fb;
}

/* Bootstrap 5.3's [data-bs-theme=dark] already re-themes every stock
   component (.card, .table, .btn, .modal, .dropdown, forms, etc) via its
   own CSS variables - only the custom classes below (app shell chrome)
   need an explicit dark override. The sidebar itself is deliberately left
   unchanged: it's a fixed brand-colored dark gradient in both themes. */
[data-bs-theme="dark"] body {
  background-color: #0f1115;
}

[data-bs-theme="dark"] .app-topbar {
  background: #1a1d23;
  border-bottom-color: #2a2d35;
}

[data-bs-theme="dark"] .app-footer {
  color: #6b7280;
}

[data-bs-theme="dark"] .stat-card {
  box-shadow: 0 1px 3px rgba(0,0,0,0.5);
}

/* Many pages use Bootstrap's .bg-white utility on card-header/breadcrumb
   elements to make them stand out against the light gray body background
   in light mode - but .bg-white is a fixed literal-white utility, NOT
   theme-aware like .text-bg-* helpers, so it stayed bright white in dark
   mode against now-light-colored text, killing contrast. Re-point it at
   Bootstrap's own dark-mode surface/text variables instead. */
[data-bs-theme="dark"] .bg-white {
  background-color: var(--bs-tertiary-bg) !important;
  color: var(--bs-body-color);
}

.app-shell {
  display: flex;
  min-height: 100vh;
}

.app-sidebar {
  width: var(--sidebar-width);
  background: linear-gradient(180deg, #1e1b4b 0%, #312e81 100%);
  color: #e0e7ff;
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  overflow-y: auto;
  overflow-x: hidden;
  z-index: 1030;
  transition: transform 0.2s ease, width 0.2s ease;
}

.sidebar-brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 1.25rem 1.25rem;
  font-weight: 700;
  font-size: 1.1rem;
  color: #fff;
  border-bottom: 1px solid rgba(255,255,255,0.1);
  white-space: nowrap;
}

.sidebar-nav {
  list-style: none;
  padding: 0.75rem;
  margin: 0;
}

.sidebar-nav li a {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.65rem 0.9rem;
  border-radius: 0.5rem;
  color: #c7d2fe;
  text-decoration: none;
  font-size: 0.92rem;
  margin-bottom: 0.15rem;
  white-space: nowrap;
  transition: background 0.15s ease, color 0.15s ease;
}

.sidebar-nav li a:hover {
  background: rgba(255,255,255,0.08);
  color: #fff;
}

.sidebar-nav li a.active {
  background: var(--brand);
  color: #fff;
}

.app-main {
  flex: 1;
  margin-left: var(--sidebar-width);
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  transition: margin-left 0.2s ease;
}

/* Desktop-only sidebar minisize (icon-only). Guarded to lg+ so a
   collapsed preference saved from a desktop session never shrinks the
   off-canvas mobile sidebar (which is either fully hidden or fully shown
   via .show, never meant to be narrow - see the max-width query below). */
@media (min-width: 992px) {
  html.sidebar-collapsed .app-sidebar {
    width: var(--sidebar-collapsed-width);
  }
  html.sidebar-collapsed .app-main {
    margin-left: var(--sidebar-collapsed-width);
  }
  html.sidebar-collapsed .sidebar-brand {
    justify-content: center;
    padding-left: 0.5rem;
    padding-right: 0.5rem;
  }
  html.sidebar-collapsed .sidebar-brand span,
  html.sidebar-collapsed .sidebar-nav li a span {
    display: none;
  }
  html.sidebar-collapsed .sidebar-nav li a {
    justify-content: center;
    padding-left: 0;
    padding-right: 0;
  }
  html.sidebar-collapsed #sidebarCollapseIconExpanded {
    display: none;
  }
  html.sidebar-collapsed #sidebarCollapseIconCollapsed {
    display: inline-block !important;
  }
}

.app-topbar {
  display: flex;
  align-items: center;
  background: #fff;
  padding: 0.75rem 1.5rem;
  border-bottom: 1px solid #e5e7eb;
  position: sticky;
  top: 0;
  z-index: 1020;
}

.app-content {
  padding: 1.5rem;
  flex: 1;
}

.app-footer {
  padding: 1rem 1.5rem;
  font-size: 0.8rem;
  color: #9ca3af;
  display: flex;
  gap: 0.4rem;
}

.stat-card {
  border: none;
  border-radius: 0.9rem;
  box-shadow: 0 1px 3px rgba(0,0,0,0.06);
}

.stat-card .stat-value {
  font-size: 1.6rem;
  font-weight: 700;
}

.status-dot {
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  display: inline-block;
  margin-right: 0.35rem;
}
.status-dot.online, .status-dot.active { background: #22c55e; }
.status-dot.stopped, .status-dot.inactive { background: #9ca3af; }
.status-dot.errored, .status-dot.failed { background: #ef4444; }
.status-dot.launching, .status-dot.activating,
.status-dot["waiting restart"] { background: #f59e0b; }
.status-dot.unknown { background: #6b7280; }

.log-viewer {
  background: #0b1021;
  color: #d1d5db;
  font-family: "SFMono-Regular", Consolas, monospace;
  font-size: 0.8rem;
  padding: 1rem;
  border-radius: 0.5rem;
  max-height: 480px;
  overflow-y: auto;
  white-space: pre-wrap;
  word-break: break-all;
}

.secret-value {
  font-family: monospace;
}

/* Circular resource gauges (Dashboard) - pure CSS conic-gradient, no chart
   library needed. --percent/--gauge-color are set inline/via JS per
   gauge; --track-color follows the current theme so the unfilled ring
   segment doesn't look like a light-mode leftover in dark mode. */
.gauge {
  --percent: 0;
  --gauge-color: var(--brand);
  --track-color: #e5e7eb;
  width: 108px;
  height: 108px;
  border-radius: 50%;
  background: conic-gradient(var(--gauge-color) calc(var(--percent) * 1%), var(--track-color) 0);
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  margin: 0 auto;
  transition: background 0.3s ease;
}

[data-bs-theme="dark"] .gauge {
  --track-color: #2a2d35;
}

.gauge::before {
  content: '';
  position: absolute;
  inset: 12px;
  border-radius: 50%;
  background: var(--bs-body-bg);
}

.gauge-value {
  position: relative;
  z-index: 1;
  font-weight: 700;
  font-size: 1.15rem;
}

.server-info-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 2rem;
  font-size: 0.85rem;
}

.server-info-strip .label {
  color: var(--bs-secondary-color, #6c757d);
  margin-right: 0.35rem;
}

.quick-count-tile {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding: 1rem;
}

.quick-count-tile .icon-box {
  width: 46px;
  height: 46px;
  border-radius: 0.7rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.3rem;
  color: #fff;
  flex-shrink: 0;
}

@media (max-width: 991.98px) {
  .app-sidebar {
    transform: translateX(-100%);
  }
  .app-sidebar.show {
    transform: translateX(0);
  }
  .app-main {
    margin-left: 0;
  }
}

/* Global "something is happening" feedback (see app.js's PanelLoading) - a
   slim top progress bar for page navigations/form submits, plus a button
   spinner state so a clicked button visibly acknowledges the click instead
   of looking dead until the next page finishes loading. */
.panel-loading-bar {
  position: fixed;
  top: 0;
  left: 0;
  height: 3px;
  width: 0%;
  background: var(--brand);
  z-index: 2000;
  opacity: 0;
  transition: width 0.25s ease, opacity 0.2s ease;
  pointer-events: none;
}
.panel-loading-bar.is-active {
  opacity: 1;
}

.btn.is-loading {
  position: relative;
  color: transparent !important;
  pointer-events: none;
}
.btn.is-loading::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 1rem;
  height: 1rem;
  margin: -0.5rem 0 0 -0.5rem;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-right-color: transparent;
  color: var(--bs-body-color);
  animation: panel-btn-spin 0.6s linear infinite;
}
.btn.is-loading.btn-primary::after,
.btn.is-loading.btn-danger::after,
.btn.is-loading.btn-success::after,
.btn.is-loading.btn-warning::after,
.btn.is-loading.btn-info::after,
.btn.is-loading.btn-dark::after {
  color: #fff;
}
@keyframes panel-btn-spin {
  to { transform: rotate(360deg); }
}
