/*
 * Shared admin/ISP panel theme -- single source of truth for the sidebar,
 * topbar, and per-page content colors, which previously lived as three
 * independent, never-unified systems: a dark blue gradient hardcoded
 * separately in sidebar.php and topbar.php's own inline <style> blocks,
 * and an identical purple :root block copy-pasted into ~25 individual
 * page files. This file replaces all three with one palette; pages keep
 * referencing the same variable names (--accent, --success, etc.) they
 * always did, just pointed at new values.
 *
 * Loaded once from header.php, after adminlte.min.css and styles.css so
 * it can freely override AdminLTE's own defaults via normal cascade order.
 */

:root {
  /* Brand identity: light blue + white + gold */
  --accent: #1E88C7;
  --accent-dark: #0F6698;
  --accent-bg: #EAF4FB;
  --gold: #C9972B;
  --gold-bg: #FBF3E0;

  /* Status colors -- conventional, never repurposed for brand */
  --success: #10b981;
  --warning: #f59e0b;
  --danger: #ef4444;

  /* Neutrals */
  --dark: #16324A;
  --gray: #6b7280;
  --border: #E3ECF3;
  --surface: #F7FAFC;

  /* Sidebar/topbar chrome -- new tokens, replacing the two hardcoded
     gradients that used to live in sidebar.php/topbar.php separately.
     --chrome-bg is deliberately NEVER part of admin/header.php's custom-
     theme override block (see includes/theme_color.php) -- the sidebar/
     topbar surface itself always stays white no matter what accent an
     ISP picks, confirmed product decision (2026-09-03); only the accent
     color, active-item highlight, and icon chips theme. */
  --chrome-bg: #ffffff;
  --chrome-border: #E3ECF3;
  --chrome-text: #33475A;
  --chrome-muted: #7B93A8;
  --chrome-active-bg: #EAF4FB;
  --chrome-active-text: #0F6698;
  --chrome-active-edge: var(--gold);
}

/* ───────────────── Topbar (admin/topbar.php) ───────────────── */

.main-header {
  background: var(--chrome-bg);
  border-bottom: 1px solid var(--chrome-border);
  box-shadow: 2px 0 12px rgba(16,50,74,0.04);
}
.main-header .nav-link { color: var(--chrome-text); }
.main-header .nav-link:hover { color: var(--chrome-active-text); }
.main-header .sub-badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 12px; border-radius: 999px; font-size: 12px; font-weight: 600;
  text-decoration: none; margin-right: 6px; white-space: nowrap;
}
.main-header .sub-badge:hover { opacity: 0.88; }
.main-header .sub-badge.state-trial { background: var(--accent-bg); color: var(--accent-dark); }
.main-header .sub-badge.state-active { background: var(--accent-bg); color: var(--accent-dark); }
.main-header .sub-badge.state-grace { background: var(--gold-bg); color: var(--gold); }
.main-header .sub-badge.state-locked { background: #FDECEA; color: var(--danger); }
.main-header .demo-badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 12px; border-radius: 999px; font-size: 12px; font-weight: 600;
  margin-right: 6px; white-space: nowrap;
  background: var(--accent-bg); color: var(--accent-dark);
}

.whatsapp-group-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 14px; border-radius: 999px; font-size: 12.5px; font-weight: 600;
  text-decoration: none; margin-right: 6px; white-space: nowrap;
  background: #25D366; color: #ffffff;
}
.whatsapp-group-btn:hover { background: #1DA851; color: #ffffff; }
.whatsapp-group-btn i { font-size: 14px; }
@media (max-width: 575.98px) {
  .whatsapp-group-btn span { display: none; }
  .whatsapp-group-btn { padding: 6px 10px; }
}

/* Topbar recovery pill for the dashboard's "Refer an ISP" banner once
   it's been dismissed (admin.referral_banner_dismissed) -- same shape
   as .whatsapp-group-btn, accent-blue to match the banner's own
   gradient instead of WhatsApp green. */
.refer-earn-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 14px; border-radius: 999px; font-size: 12.5px; font-weight: 600;
  text-decoration: none; margin-right: 6px; white-space: nowrap;
  background: linear-gradient(135deg, #0f6698, #1e88c7); color: #ffffff;
}
.refer-earn-btn:hover { opacity: 0.9; color: #ffffff; }
.refer-earn-btn i { font-size: 14px; }
@media (max-width: 575.98px) {
  .refer-earn-btn span { display: none; }
  .refer-earn-btn { padding: 6px 10px; }
}

/* "Write a Review" topbar pill -- feature isn't live yet, so it's styled
   visually muted/disabled (not a real disabled attribute -- it still
   needs to respond to a click with a "Coming soon" toast). */
.write-review-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 14px; border-radius: 999px; font-size: 12.5px; font-weight: 600;
  border: 1.5px solid #9aa5b1; background: transparent; color: var(--chrome-text);
  opacity: 0.6; margin-right: 6px; white-space: nowrap; cursor: pointer;
}
.write-review-btn:hover { opacity: 0.85; }
.write-review-btn i { font-size: 14px; }
@media (max-width: 575.98px) {
  .write-review-btn span { display: none; }
  .write-review-btn { padding: 6px 10px; }
}

/* Topbar icon buttons (refer/ticket/notification/settings/fullscreen) --
   a visible button at rest (bordered + filled), not just on hover, so the
   affordance still reads correctly on touch devices with no hover state */
.topbar-icon-btn {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: 8px;
  border: 1px solid var(--chrome-border); background: var(--surface);
  font-size: 15px; cursor: pointer; color: var(--chrome-text); margin: 0 3px;
}
.topbar-icon-btn:hover { background: var(--accent-bg); color: var(--chrome-active-text); border-color: var(--accent); }

.topbar-search {
  display: flex; align-items: center; position: relative;
  background: var(--surface); border: 1px solid var(--chrome-border); border-radius: 8px;
  padding: 0 10px; margin-left: 8px; height: 36px; width: 260px;
}
.topbar-search i { color: var(--chrome-muted); font-size: 12.5px; margin-right: 8px; }
.topbar-search input {
  border: none; background: transparent; outline: none; font-size: 13px;
  color: var(--chrome-text); width: 100%; font-family: inherit;
}
.topbar-search input::placeholder { color: var(--chrome-muted); }
@media (max-width: 767.98px) {
  .topbar-search { display: none; }
}

.notif-dot {
  position: absolute; top: 5px; right: 6px; width: 8px; height: 8px;
  border-radius: 50%; background: var(--danger); border: 1.5px solid #fff;
}

.topbar-numeric-badge {
  position: absolute; top: 1px; right: 1px; min-width: 16px; height: 16px; padding: 0 3px;
  border-radius: 999px; background: var(--danger); color: #fff; border: 1.5px solid #fff;
  font-size: 10px; font-weight: 700; line-height: 13px; text-align: center;
}

.notif-dropdown-menu, .settings-dropdown-menu {
  background: #fff; border: 1px solid var(--chrome-border); border-radius: 8px;
  padding: 6px; min-width: 260px; box-shadow: 0 12px 28px rgba(16,50,74,0.14);
}
.notif-dropdown-title {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px;
  color: var(--chrome-muted); padding: 8px 10px 6px;
}
.notif-row, .settings-dropdown-menu .dropdown-item {
  display: flex; align-items: center; gap: 10px; font-size: 13px; color: var(--chrome-text);
  border-radius: 6px; padding: 8px 10px;
}
.notif-row i, .settings-dropdown-menu .dropdown-item i { width: 16px; text-align: center; font-size: 13px; }
.notif-row:hover, .settings-dropdown-menu .dropdown-item:hover,
.notif-row:focus, .settings-dropdown-menu .dropdown-item:focus {
  background: var(--accent-bg); color: var(--accent-dark);
}
.notif-empty {
  display: flex; align-items: center; gap: 8px; padding: 14px 10px;
  color: var(--chrome-muted); font-size: 13px;
}
.notif-empty i { color: var(--success); }

.notif-dropdown-menu { max-width: 320px; }
#topbarNotifList { max-height: 340px; overflow-y: auto; }
.notif-row { align-items: flex-start; }
.notif-row-body { flex: 1; min-width: 0; }
.notif-row-msg { overflow: hidden; text-overflow: ellipsis; white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.notif-row-time { font-size: 10.5px; color: var(--chrome-muted); margin-top: 2px; }
.notif-row.unread { background: #fff7ed; }
.notif-row.unread:hover, .notif-row.unread:focus { background: #fef3ec; }
.notif-badge-label {
  display: inline-block; font-size: 9px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.4px; color: #fff; background: var(--accent); padding: 1px 6px; border-radius: 999px; margin-right: 5px; vertical-align: middle;
}
.notif-view-all {
  display: block; text-align: center; font-size: 12px; font-weight: 700; color: var(--accent-dark);
  padding: 9px 10px 6px; margin-top: 4px; border-top: 1px solid var(--chrome-border);
}
.notif-view-all:hover { color: var(--accent); text-decoration: none; }

/* Refer-a-Friend modal */
.refer-modal-content { border-radius: 12px; border: none; }
.refer-modal-subtitle { color: var(--gray); font-size: 13px; margin-bottom: 14px; }
.refer-copy-row { display: flex; gap: 8px; margin-bottom: 12px; }
.refer-copy-row input {
  flex: 1; padding: 9px 12px; border: 1px solid var(--border); border-radius: 8px;
  font-size: 12.5px; background: var(--surface); color: var(--gray);
}
.refer-whatsapp-btn { display: flex; align-items: center; justify-content: center; gap: 8px; }

/* Router-setup onboarding gate -- full-viewport, not dismissible */
#routerSetupGate {
  position: fixed; inset: 0; z-index: 999999;
  background: rgba(22,50,74,0.6);
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
}
.router-gate-card {
  background: #fff; border-radius: 14px; max-width: 440px; width: 100%;
  padding: 32px 28px; text-align: center;
  box-shadow: 0 24px 60px rgba(16,50,74,0.3);
}
.router-gate-icon {
  width: 56px; height: 56px; border-radius: 14px; margin: 0 auto 16px;
  background: var(--accent-bg); color: var(--accent-dark);
  display: flex; align-items: center; justify-content: center; font-size: 24px;
}
.router-gate-card h2 { font-size: 19px; font-weight: 700; color: var(--dark); margin-bottom: 10px; }
.router-gate-card p { font-size: 13.5px; color: var(--gray); line-height: 1.55; margin-bottom: 20px; }
.router-gate-actions { display: flex; flex-direction: column; gap: 10px; margin-bottom: 16px; }
.router-gate-actions .btn { padding: 11px; font-size: 13.5px; font-weight: 600; border-radius: 8px; }
.router-gate-actions .btn-primary { background: var(--accent); border-color: var(--accent); }
.router-gate-actions .btn-outline {
  background: transparent; border: 1.5px solid var(--chrome-border); color: var(--chrome-text);
}
.router-gate-actions .btn-outline:hover { background: var(--surface); }
.router-gate-contact { font-size: 12px; color: var(--chrome-muted); }

/* ───────────────── Sidebar (admin/sidebar.php) ───────────────── */

.main-sidebar {
  background: var(--chrome-bg);
  border-right: 1px solid var(--chrome-border);
  box-shadow: 2px 0 12px rgba(16,50,74,0.04);
}

/* AdminLTE's fixLayoutHeight() (assets/dist/js/adminlte.js) measures this
   inner .sidebar div's natural, unclipped content height and stretches
   .content-wrapper to match it if it's the tallest of {window, header,
   footer, sidebar} -- it normally relies on the overlayScrollbars plugin
   to visually clip this div at runtime, but that clipping happens *after*
   the height measurement on first load, so a sidebar taller than the
   viewport (icon chips + profile card + collapsible sections pushed this
   past one screen's height on common laptop viewports) was stretching
   every page's content area to match, leaving a large empty gap below
   short-content pages. Capping it here with max-height + overflow-y means
   jQuery's own .height() reads back a viewport-bounded number, so that
   branch of fixLayoutHeight() never fires -- independent of whether/when
   overlayScrollbars itself finishes initializing. */
.main-sidebar .sidebar {
  max-height: calc(100vh - 2.93725rem - 1px);
  overflow-y: auto;
  scrollbar-width: thin;
}
.main-sidebar .sidebar::-webkit-scrollbar { width: 6px; }
.main-sidebar .sidebar::-webkit-scrollbar-thumb { background: var(--chrome-border); border-radius: 999px; }
.main-sidebar .sidebar::-webkit-scrollbar-track { background: transparent; }

/* Belt-and-braces on top of the sidebar cap above: adminlte.js's
   fixLayoutHeight() sets .content-wrapper's min-height as an inline style
   (see assets/dist/js/adminlte.js, SELECTOR_CONTENT), computed from
   whichever of {window, header, footer, sidebar, control-sidebar} measured
   tallest at the moment it ran -- on some pages/timings this still comes
   out taller than the viewport, leaving a large empty scrollable gap below
   short content (reported live on settlement_accounts.php and other short
   pages even after capping the sidebar's own height above). A stylesheet
   rule marked !important beats a plain inline style in the cascade, so
   this unconditionally caps it at one viewport regardless of what
   adminlte.js computed or when -- the gray background still fills the
   screen on short pages (99vh, not 0, so it doesn't look visibly
   truncated), it just never grows past it. */
.content-wrapper {
  min-height: 99vh !important;
}

.brand-link { padding: 14px 16px; border-bottom: 1px solid var(--chrome-border); }
.brand-row { display: flex; align-items: center; gap: 10px; }
.brand-logo-sq { flex-shrink: 0; width: 32px; height: 32px; border-radius: 7px; object-fit: cover; background: var(--accent-bg); }
.brand-col { min-width: 0; display: flex; flex-direction: column; text-align: left; }
.brand-text { font-size: 14px; font-weight: 600; color: var(--chrome-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 1.25; }
.brand-tagline { font-size: 10.5px; color: var(--chrome-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 1.3; }

/* User panel / profile card */
.user-panel-wrap {
  margin: 10px 12px; border: 1px solid var(--chrome-border); border-radius: 12px;
  background: var(--surface); position: relative; overflow: hidden;
}
.user-panel-toggle { display: flex; align-items: center; gap: 10px; padding: 12px 14px; cursor: pointer; transition: background 0.15s; text-decoration: none; }
.user-panel-toggle:hover, .user-panel-toggle[aria-expanded="true"] { background: var(--accent-bg); }
.user-avatar {
  flex-shrink: 0; width: 36px; height: 36px; border-radius: 50%;
  background: var(--accent-bg); color: var(--accent-dark);
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 700; letter-spacing: 0.3px;
}
.user-meta { flex: 1; min-width: 0; }
.user-name { font-size: 13px; font-weight: 700; color: var(--chrome-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.user-role {
  display: inline-block; margin-top: 2px; padding: 2px 8px; border-radius: 999px;
  background: var(--gold-bg); color: var(--gold); font-size: 9.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.4px;
}
.user-caret { flex-shrink: 0; font-size: 11px; color: var(--chrome-muted); transition: transform 0.15s; }
.user-panel-toggle[aria-expanded="true"] .user-caret { transform: rotate(180deg); }

.user-dropdown-menu {
  background: #fff; border: 1px solid var(--chrome-border); border-radius: 8px;
  padding: 6px; min-width: 200px; box-shadow: 0 12px 28px rgba(16,50,74,0.14);
}
.user-dropdown-menu .dropdown-item { display: flex; align-items: center; gap: 9px; font-size: 13px; color: var(--chrome-text); border-radius: 6px; padding: 8px 10px; }
.user-dropdown-menu .dropdown-item i { width: 16px; text-align: center; font-size: 13px; }
.user-dropdown-menu .dropdown-item:hover, .user-dropdown-menu .dropdown-item:focus { background: var(--accent-bg); color: var(--accent-dark); }
.user-dropdown-menu .dropdown-item.text-danger { color: var(--danger); }
.user-dropdown-menu .dropdown-item.text-danger:hover { background: rgba(239,68,68,0.08); color: var(--danger); }
.user-dropdown-menu .dropdown-divider { border-color: var(--chrome-border); margin: 6px 4px; }

/* Nav links */
.nav-sidebar .nav-item { margin-bottom: 2px; }
.nav-sidebar .nav-link {
  display: flex; align-items: center; border-radius: 8px; margin: 1px 8px; padding: 8px 10px;
  color: var(--chrome-text); font-size: 13px; border-left: 3px solid transparent; transition: all 0.15s;
}
.nav-sidebar .nav-link:hover { background: var(--surface); color: var(--chrome-text); }
.nav-sidebar .nav-link.active {
  /* All three !important: AdminLTE's own bundled adminlte.min.css ships
     `.sidebar-light-primary .nav-sidebar>.nav-item>.nav-link.active`
     (5 class selectors, specificity 0,5,0 -- beats this rule's 0,3,0) that
     hardcodes background-color:#007bff/color:#fff. Without !important
     here, a custom theme color's active-nav background silently lost to
     AdminLTE's stock blue regardless of what admin/appearance.php saved
     -- confirmed live, this was the single most visible "some parts
     don't change" symptom reported by a user. */
  background: var(--chrome-active-bg) !important; color: var(--chrome-active-text) !important;
  font-weight: 600; border-left-color: var(--chrome-active-edge) !important;
}
.nav-sidebar .nav-link.disabled { opacity: 0.5; pointer-events: none; }

/* Icon chips -- small colored rounded-square wrapper, replacing a bare
   glyph directly on the (formerly dark) background */
.nav-icon-chip {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 9px; margin-right: 10px; flex-shrink: 0; font-size: 13.5px;
}
/* chip-blue deliberately follows the accent variables, not a fixed hex
   -- it's the color used on 6 of the sidebar's top nav items (Dashboard,
   Active Users, Users, Add User, Tickets, Reports), so it's the single
   most visible spot a custom theme needs to actually show up. The other
   chip-* colors stay fixed category colors (green/gold/pink/violet/teal/
   gray), same as status colors elsewhere in this file -- only the ONE
   chip that used to coincide with the default theme's own blue gets
   re-pointed at the variable. */
.nav-icon-chip.chip-blue   { background: var(--accent-bg); color: var(--accent); }
.nav-icon-chip.chip-green  { background: #E7F6EF; color: #0E9F6E; }
.nav-icon-chip.chip-gold   { background: #FBF3E0; color: #C9972B; }
.nav-icon-chip.chip-pink   { background: #FDECEF; color: #E0567C; }
.nav-icon-chip.chip-violet { background: #EFEAFB; color: #7C5CD6; }
.nav-icon-chip.chip-teal   { background: #E6F6F8; color: #17A2B8; }
.nav-icon-chip.chip-gray   { background: #F1F3F5; color: #5A6B7A; }

.badge { font-size: 10px; font-weight: 600; padding: 3px 7px; }

.nav-header { color: var(--chrome-muted); font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.6px; padding: 16px 20px 6px; margin: 0; }

/* Promo/utility pill -- same visual language as .user-role, generalized
   for a future "Coming Soon"/"EARN"-style nav badge */
.nav-pill-badge {
  display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: 999px;
  background: var(--gold-bg); color: var(--gold); font-size: 9px; font-weight: 700; text-transform: uppercase;
}

/* YouTube-style top progress bar, shown by admin-nav.js during a pjax
   navigation -- created on first use, reused after that. */
#pjax-progress {
  position: fixed; top: 0; left: 0; height: 3px; width: 0%;
  background: var(--accent);
  background: linear-gradient(90deg, var(--accent), var(--gold));
  z-index: 99999; opacity: 0;
  transition: width 0.2s ease-out, opacity 0.25s ease;
  pointer-events: none;
}
#pjax-progress.active { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  #pjax-progress { transition: none; }
}

/* ───────────── Toastr override -- professional white-card style ─────────────
   Toastr's stock notifications (assets/plugins/toastr/toastr.min.css) are
   solid-colour boxes with a baked-in base64 icon sprite. Replaced here with
   a white card, a left accent bar, and a real icon chip matching the rest
   of the theme -- pure CSS override, so every existing toastr.success()/
   error()/warning()/info() call site across the app gets this for free. */
#toast-container > div {
  background-color: #fff;
  background-image: none !important;
  color: var(--dark);
  border-radius: 10px;
  border: 1px solid var(--border);
  box-shadow: 0 12px 32px rgba(16,50,74,0.16), 0 2px 6px rgba(16,50,74,0.06);
  opacity: 1; filter: none;
  padding: 14px 16px 14px 54px;
  position: relative;
}
#toast-container > div:hover {
  box-shadow: 0 16px 38px rgba(16,50,74,0.2), 0 2px 6px rgba(16,50,74,0.08);
  opacity: 1; filter: none;
}
#toast-container > div::before {
  content: '';
  position: absolute; left: 14px; top: 14px;
  width: 26px; height: 26px; border-radius: 8px;
  font-family: 'Font Awesome 6 Free'; font-weight: 900; font-size: 13px;
  line-height: 26px; text-align: center;
}
#toast-container > .toast-success { background-color: #fff; border-left: 4px solid var(--success); }
#toast-container > .toast-success::before { content: '\f00c'; background: #E7F6EF; color: var(--success); }
#toast-container > .toast-error { background-color: #fff; border-left: 4px solid var(--danger); }
#toast-container > .toast-error::before { content: '\f00d'; background: #FDECEA; color: var(--danger); }
#toast-container > .toast-warning { background-color: #fff; border-left: 4px solid var(--warning); }
#toast-container > .toast-warning::before { content: '\f071'; background: var(--gold-bg); color: var(--warning); }
#toast-container > .toast-info { background-color: #fff; border-left: 4px solid var(--accent); }
#toast-container > .toast-info::before { content: '\f05a'; background: var(--accent-bg); color: var(--accent); }

#toast-container > div .toast-title { font-weight: 700; font-size: 13.5px; color: var(--dark); margin-bottom: 2px; }
#toast-container > div .toast-message { font-size: 12.5px; color: var(--gray); line-height: 1.45; }
#toast-container > div .toast-message a, #toast-container > div .toast-message label { color: var(--accent); }
#toast-container > div .toast-close-button { color: var(--gray); text-shadow: none; opacity: 0.6; }
#toast-container > div .toast-close-button:hover { opacity: 1; color: var(--dark); }
#toast-container > .toast-progress { background-color: var(--accent); opacity: 0.3; height: 3px; }

/* ───────────────── Dark mode (admin/appearance.php) ─────────────────
   Global best-effort toggle, added 2026-09-12. Applied via
   html[data-theme="dark"] -- set by a tiny inline <script> in
   admin/header.php (there's no literal <html> tag anywhere in this
   app's admin pages for PHP to write an attribute onto directly; every
   page goes straight from header.php's </head> to its own <body>, so
   JS setting the attribute on the implicit root element is the only
   way in). html[data-theme="dark"] is MORE specific than a bare :root
   (a real, deliberate reason: several individual admin/*.php pages
   still open their own local `:root { ... }` block for page-specific
   tuning -- this guarantees the dark palette below always wins over
   those without needing to touch every one of those files).

   Deliberately does NOT touch --accent/--accent-dark/--accent-bg or
   --chrome-active-* -- those are the admin's own brand-color
   customization (includes/theme_color.php), orthogonal to light/dark
   and left alone so a custom color still shows correctly in dark mode.

   The .card/.content-wrapper/table/input etc. rules below are a
   deliberately blunt, !important-backed catch-all: most individual
   admin pages hardcode a plain white card background directly (not the
   --surface variable), a byproduct of ~54 page files built over time
   without a shared card component. This is the "best-effort everywhere"
   tradeoff the user explicitly chose over a much larger per-page
   precision pass -- the shared chrome (sidebar/topbar/dashboard) is
   exact since it's fully variable-driven already; a handful of more
   custom-built inner pages may still show a stray light element, fixable
   piecemeal as reported rather than guessed at up front. */
html[data-theme="dark"] {
  --gray: #94a3b8;
  --border: #2d3748;
  --surface: #0f1420;
  --dark: #e2e8f0;

  --chrome-bg: #161b26;
  --chrome-border: #232a38;
  --chrome-text: #cbd5e1;
  --chrome-muted: #8895ab;
}

html[data-theme="dark"] body { background: var(--surface); color: var(--dark); }

html[data-theme="dark"] .card,
html[data-theme="dark"] .box,
html[data-theme="dark"] .modal-content,
html[data-theme="dark"] table {
  background: #161b26 !important;
  color: #e2e8f0 !important;
  border-color: #2d3748 !important;
}

html[data-theme="dark"] th {
  background: #10141d !important;
  color: #94a3b8 !important;
  border-color: #2d3748 !important;
}

html[data-theme="dark"] td { border-color: #232a38 !important; }

html[data-theme="dark"] input,
html[data-theme="dark"] select,
html[data-theme="dark"] textarea {
  background: #0f1420 !important;
  color: #e2e8f0 !important;
  border-color: #2d3748 !important;
}

html[data-theme="dark"] input::placeholder,
html[data-theme="dark"] textarea::placeholder {
  color: #64748b;
}

html[data-theme="dark"] .no-data { color: #94a3b8 !important; }
