/* =========================================
   1. RESET & BASE VARIABLES
   ========================================= */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
}

:root {
  /* ── Surfaces ─────────────────────────────────────────────── */
  --bg-main: #F5F5F7;
  --bg-panel: #FFFFFF;
  --bg-panel-hover: #F0F0F2;
  --bg-subtle: #F9FAFB;
  /* legacy aliases, kept so older markup keeps working */
  --bg-primary: #F5F5F7;
  --bg-secondary: #FFFFFF;
  --bg-card: #FFFFFF;

  /* ── Stacking order ───────────────────────────────────────────
     There were four bare numbers scattered through the sheet and the views,
     and no way to tell which was meant to sit above which. A dropdown at 900
     lost to a sidebar at 1000, which is how the device menu ended up
     unreadable behind the navigation. */
  --z-sticky: 100;    /* table headers and anything that stays put while scrolling */
  --z-sidebar: 1000;  /* the off-canvas sidebar on narrow screens */
  --z-menu: 1100;     /* dropdowns - above the sidebar, below any dialog */
  --z-modal: 10000;   /* dialogs, which cover everything */

  /* ── One accent colour ────────────────────────────────────── */
  --primary: #65A30D;
  --primary-dark: #4D7C0F;
  --primary-soft: rgba(101, 163, 13, 0.12);
  /* darker shade for filled surfaces: white text needs it to reach AA contrast */
  --primary-strong: #4D7C0F;
  --text-on-primary: #FFFFFF;
  --neon-lime: #65A30D; /* legacy alias for --primary */

  /* ── Status colours (only these three carry meaning) ──────── */
  --success: #65A30D;
  --success-soft: rgba(101, 163, 13, 0.12);
  --danger: #DC2626;
  --danger-soft: rgba(220, 38, 38, 0.10);
  --warning: #B45309;
  --warning-soft: rgba(180, 83, 9, 0.12);
  --info: #0E7490;
  --info-soft: rgba(14, 116, 144, 0.12);

  /* ── Grays ────────────────────────────────────────────────── */
  --gray-50: #F9FAFB;
  --gray-100: #F3F4F6;
  --gray-200: #E5E7EB;
  --gray-300: #D1D5DB;
  --gray-600: #6B7280;
  --gray-700: #374151;
  --gray-800: #1F2937;
  --gray-900: #111827;

  /* ── Text ─────────────────────────────────────────────────── */
  --text-primary: #111827;
  --text-secondary: #6B7280;
  --text-dark: #111111;

  /* ── Chart marks ──────────────────────────────────────────────
     Separate from the UI tokens: the bright dark-mode lime sits outside the
     lightness band a chart surface needs, so charts get their own steps. */
  --chart-pos: #4D7C0F;
  --chart-neg: #DC2626;
  --chart-neutral: #0E7490;
  --chart-grid: rgba(0, 0, 0, 0.08);
  --link: #4D7C0F;

  /* ── Borders & radius ─────────────────────────────────────── */
  --border-color: #E5E7EB;
  --border-subtle: rgba(0, 0, 0, 0.06);
  --border-radius-lg: 16px;
  --border-radius-md: 10px;
  --border-radius-sm: 6px;
}

/* Dark Mode */
body.dark-mode {
  --bg-main: #0A0A0A;
  --bg-panel: #141515;
  --bg-panel-hover: #1E2020;
  --bg-subtle: #1A1A1E;
  --bg-primary: #0A0A0A;
  --bg-secondary: #141515;
  --bg-card: #141515;

  --primary: #B5FF3C;
  --primary-dark: #9AE62E;
  --primary-soft: rgba(181, 255, 60, 0.16);
  --primary-strong: #B5FF3C;
  /* the lime is bright: text sitting on it must be dark, not white */
  --text-on-primary: #0A0A0A;
  --neon-lime: #B5FF3C;

  --success: #B5FF3C;
  --success-soft: rgba(181, 255, 60, 0.16);
  --danger: #F87171;
  --danger-soft: rgba(248, 113, 113, 0.16);
  --warning: #FBBF24;
  --warning-soft: rgba(251, 191, 36, 0.16);
  --info: #67E8F9;
  --info-soft: rgba(103, 232, 249, 0.16);

  --gray-50: #1A1A1E;
  --gray-100: #222226;
  --gray-200: #2A2A2E;
  --gray-300: #3A3A40;
  --gray-600: #8A8A8E;
  --gray-700: #CCCCCC;
  --gray-800: #E0E0E0;
  --gray-900: #F0F0F0;

  --text-primary: #FFFFFF;
  --text-secondary: #8A8A8E;
  --text-dark: #F0F0F0;

  --border-color: #2A2A2A;
  --border-subtle: rgba(255, 255, 255, 0.08);

  --chart-pos: #65A30D;
  --chart-neg: #DC2626;
  --chart-neutral: #22A5C4;
  --chart-grid: rgba(255, 255, 255, 0.10);
  --link: #B5FF3C;
}

body {
  background-color: var(--bg-main);
  color: var(--text-primary);
  min-height: 100vh;
  overflow-x: hidden;
  line-height: 1.6;
  transition: background-color 0.3s ease, color 0.3s ease;
}

/* =========================================
   2. LAYOUT (Sidebar + Main)
   ========================================= */
.dashboard-layout {
  display: grid;
  grid-template-columns: 220px 1fr;
  min-height: 100vh;
}

/*
 * The page scrolls, not this box.
 *
 * This used to be its own scroll container - overflow-y: auto with
 * max-height: 100vh - which made it clip everything inside it. A dropdown on a
 * card low in the view was cut off entirely: all eight items below the fold,
 * none reachable. Because one axis was auto the other computed to auto too, so
 * it clipped sideways as well, which looked like the sidebar covering the menu.
 *
 * The sidebar is position: sticky, so it stays put on its own while the page
 * scrolls. Two scroll containers were never needed.
 */
.main-content {
  padding: 32px;
  display: flex;
  flex-direction: column;
  gap: 24px;
  min-width: 0;
}

/* Legacy container support */
.container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 20px;
}

/* =========================================
   3. SIDEBAR
   ========================================= */
.sidebar {
  background-color: var(--bg-panel);
  padding: 24px;
  display: flex;
  flex-direction: column;
  border-right: 1px solid var(--border-color);
  height: 100vh;
  position: sticky;
  top: 0;
}

.sidebar .logo {
  display: block;
  margin-bottom: 32px;
  text-decoration: none;
}

.sidebar .logo-img {
  width: 120px;
  height: auto;
  transition: filter 0.3s ease;
}

body.dark-mode .sidebar .logo-img,
body.dark-mode .login-logo-img {
  filter: brightness(1.6) saturate(0.8);
}

.nav-menu {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex-grow: 1;
}

.nav-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 16px;
  color: var(--text-secondary);
  text-decoration: none;
  border-radius: var(--border-radius-sm);
  font-weight: 400;
  font-size: 0.875rem;
  transition: all 0.15s ease;
  cursor: pointer;
  border: none;
  background: none;
  width: 100%;
  text-align: left;
}

.nav-item:hover {
  color: var(--text-primary);
}

.nav-item.active {
  color: var(--text-primary);
  font-weight: 600;
}

.nav-icon {
  font-size: 1rem;
  width: 20px;
  text-align: center;
  flex-shrink: 0;
}

.nav-logout-form { margin: 0; }

.nav-item-logout {
  color: var(--text-secondary);
  font-size: 0.8125rem;
  /* it is a button now, so it posts; styled to sit like the links around it */
  background: none;
  border: 0;
  width: 100%;
  text-align: left;
  font-family: inherit;
  cursor: pointer;
}

.nav-item-logout:hover {
  color: var(--danger);
}

.sidebar-footer {
  margin-top: auto;
  padding-top: 20px;
  border-top: 1px solid var(--border-color);
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.sidebar-user {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  background: var(--bg-panel-hover);
  border-radius: var(--border-radius-md);
  font-size: 0.875rem;
}

.sidebar-user .user-avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--primary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.875rem;
  color: var(--text-dark);
  font-weight: 700;
}

.sidebar-user .user-name {
  color: var(--text-primary);
  font-weight: 500;
}

.sidebar-user .user-role {
  color: var(--text-secondary);
  font-size: 0.75rem;
}

/* =========================================
   4. PAGE HEADER
   ========================================= */
.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.page-title {
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--text-primary);
}

.page-subtitle {
  font-size: 0.9375rem;
  color: var(--text-secondary);
  margin-top: 4px;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 12px;
}

/* Legacy header (hidden when sidebar is used) */
.header {
  display: none;
}

/* =========================================
   5. PANELS & CARDS
   ========================================= */
.panel, .card {
  background-color: var(--bg-panel);
  border-radius: var(--border-radius-lg);
  padding: 24px;
  border: 1px solid var(--border-subtle);
}

.card {
  margin-bottom: 0;
}

.card-title {
  font-size: 1.125rem;
  font-weight: 600;
  margin-bottom: 16px;
  color: var(--text-primary);
}

/* KPI Cards */
.kpi-grid, .stats-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
}

@media (max-width: 1200px) {
  .kpi-grid, .stats-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}





/* Stat cards (legacy + new) */
.stat-card {
  background: var(--bg-panel);
  padding: 20px 24px;
  border-radius: var(--border-radius-md);
  border: 1px solid var(--border-subtle);
}

.stat-content { flex: 1; }
.stat-value { font-size: 2rem; font-weight: 700; color: var(--text-primary); line-height: 1; }
.stat-label { font-size: 0.75rem; color: var(--text-secondary); margin-top: 6px; text-transform: uppercase; letter-spacing: 0.05em; }
.stat-subtitle { font-size: 0.6875rem; color: var(--text-secondary); margin-top: 2px; }

.stat-card-primary { border-top: 3px solid var(--primary); }
.stat-card-info { border-top: 3px solid var(--info); }
.stat-card-success { border-top: 3px solid var(--primary); }
.stat-card-warning { border-top: 3px solid var(--warning); }

/* =========================================
   6. BUTTONS
   ========================================= */
.btn {
  padding: 8px 16px;
  border: none;
  border-radius: var(--border-radius-sm);
  cursor: pointer;
  font-size: 0.8125rem;
  font-weight: 500;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: all 0.15s ease;
}

.btn-primary {
  background: var(--primary-strong);
  color: var(--text-on-primary);
}

.btn-primary:hover {
  filter: brightness(1.08);
}

.btn-success {
  background: var(--primary-strong);
  color: var(--text-on-primary);
}

.btn-success:hover {
  opacity: 0.9;
}

.btn-danger {
  background: var(--danger);
  color: white;
}

.btn-danger:hover {
  opacity: 0.9;
}

.btn-secondary {
  background: var(--gray-200);
  color: var(--text-primary);
}

.btn-secondary:hover {
  background: var(--gray-300);
}

.btn-sm {
  padding: 6px 12px;
  font-size: 0.75rem;
}

.btn-outline {
  background: transparent;
  border: 1px solid var(--border-color);
  color: var(--text-primary);
}

.btn-outline:hover {
  border-color: var(--primary);
  color: var(--primary);
}

/* =========================================
   7. FORMS
   ========================================= */
.form-group {
  margin-bottom: 1rem;
}

.form-label {
  display: block;
  margin-bottom: 0.5rem;
  font-weight: 500;
  font-size: 0.875rem;
  color: var(--text-secondary);
}

.form-input {
  width: 100%;
  padding: 10px 14px;
  border: 1px solid var(--border-color);
  border-radius: var(--border-radius-sm);
  font-size: 0.9375rem;
  background: var(--bg-main);
  color: var(--text-primary);
  transition: all 0.2s ease;
}

.form-input:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(181, 255, 60, 0.15);
}

.form-input::placeholder {
  color: var(--text-secondary);
}

select.form-input {
  cursor: pointer;
}

textarea.form-input {
  resize: vertical;
}

.form-checkbox {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}

.form-checkbox input[type="checkbox"] {
  accent-color: var(--primary);
  width: 18px;
  height: 18px;
}

.error {
  background: var(--danger-soft);
  color: #FCA5A5;
  border: 1px solid rgba(230, 57, 70, 0.3);
  padding: 12px 16px;
  border-radius: var(--border-radius-sm);
  margin-bottom: 1rem;
  font-size: 0.875rem;
}

.success {
  background: var(--success-soft);
  color: var(--primary);
  border: 1px solid rgba(181, 255, 60, 0.3);
  padding: 12px 16px;
  border-radius: var(--border-radius-sm);
  margin-bottom: 1rem;
  font-size: 0.875rem;
}

/* =========================================
   8. TABLES
   ========================================= */
.table {
  width: 100%;
  border-collapse: collapse;
}

.table-wrapper {
  overflow-x: auto;
  border-radius: var(--border-radius-md);
  border: 1px solid var(--border-subtle);
}

.table th {
  background: var(--bg-main);
  padding: 10px 14px;
  text-align: left;
  font-weight: 600;
  font-size: 0.8125rem;
  color: var(--text-secondary);
  border-bottom: 1px solid var(--border-color);
  white-space: nowrap;
}

.table td {
  padding: 10px 14px;
  border-bottom: 1px solid var(--border-subtle);
  color: var(--text-primary);
  font-size: 0.8125rem;
}

.table tr:hover {
  background: var(--bg-panel-hover);
}

/* =========================================
   9. GRIDS
   ========================================= */
.grid {
  display: grid;
  gap: 24px;
}

.grid-2 {
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}

.grid-3 {
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}

/* Device lists use auto-fill, not auto-fit: auto-fit collapses the empty
   tracks, so a customer with one device got a single card stretched across the
   whole page. auto-fill keeps the columns, so one card stays card-sized and a
   dozen still fill the row. Kept separate from .grid-2 because the hardware
   form and the stats panels do want a lone child to span. */
.device-grid {
  display: grid;
  gap: 24px;
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
}

.device-grid .device-card code {
  overflow-wrap: anywhere;
}

.grid-2-col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
}

/* =========================================
   10. DEVICE CARDS
   ========================================= */
.device-card {
  border: 1px solid var(--border-subtle);
  padding: 20px;
  border-radius: var(--border-radius-lg);
  background: var(--bg-panel);
  transition: transform 0.2s, box-shadow 0.2s;
}

.device-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
}

.device-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.device-name {
  font-weight: 600;
  font-size: 1.125rem;
}

.device-status {
  padding: 4px 12px;
  border-radius: 20px;
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.device-status.open {
  background: var(--success-soft);
  color: var(--primary);
  border: 1px solid rgba(181, 255, 60, 0.3);
}

.device-status.closed {
  background: rgba(138, 138, 142, 0.15);
  color: var(--text-secondary);
  border: 1px solid rgba(138, 138, 142, 0.2);
}

.device-actions {
  display: flex;
  gap: 8px;
  margin-top: 16px;
  flex-wrap: wrap;
}

.device-iot-actions {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border-color);
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

/* Overflow menu for the actions a device card cannot show all at once.
   Everyday control stays as buttons; setup, deployment and deletion move in
   here so the card has one obvious thing to look at. */
.action-menu {
  position: relative;
  display: inline-block;
}

.action-menu-dropdown {
  display: none;
  position: absolute;
  right: 0;
  top: 100%;
  margin-top: 6px;
  min-width: 210px;
  background: var(--bg-panel);
  border: 1px solid var(--border-color);
  border-radius: var(--border-radius-md);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
  z-index: var(--z-menu);
  padding: 4px 0;
}

.action-menu.open .action-menu-dropdown {
  display: block;
}

/*
 * A card lifts 2px on hover, and any transform makes an element a stacking
 * context - so the menu's z-index applied only inside the card, and the card
 * itself competed with the sidebar at z-index auto and lost. Raising the card
 * while its menu is open carries the menu up with it.
 */
.device-card:has(.action-menu.open) {
  position: relative;
  z-index: var(--z-menu);
}

/* A card sitting near the right edge would push its menu off screen */
.action-menu.action-menu--left .action-menu-dropdown {
  right: auto;
  left: 0;
}

/*
 * A card near the bottom of the page opens its menu upwards instead. Without
 * this the menu runs off the bottom of the window with nothing to scroll to,
 * because an absolutely positioned panel adds no page height - every item was
 * there, and none of them reachable.
 */
.action-menu.action-menu--up .action-menu-dropdown {
  top: auto;
  bottom: 100%;
  margin-top: 0;
  margin-bottom: 6px;
}

/* Set from JavaScript to whatever room the window actually has, so a menu with
   many items stays usable on a short screen rather than running off it. */
.action-menu.open .action-menu-dropdown {
  overflow-y: auto;
}

.action-menu-dropdown button,
.action-menu-dropdown a {
  display: block;
  width: 100%;
  box-sizing: border-box;
  text-align: left;
  padding: 9px 16px;
  background: none;
  border: none;
  color: var(--text-primary);
  text-decoration: none;
  font-size: 0.875rem;
  font-family: inherit;
  cursor: pointer;
}

.action-menu-dropdown button:hover,
.action-menu-dropdown a:hover,
.action-menu-dropdown button:focus-visible,
.action-menu-dropdown a:focus-visible {
  background: var(--bg-panel-hover);
  color: var(--primary-strong);
  outline: none;
}

/* Deleting a device is not in the same class as opening a hardware page */
.action-menu-separator {
  height: 1px;
  margin: 4px 0;
  background: var(--border-subtle);
}

.action-menu-dropdown .action-menu-danger {
  color: var(--danger);
}

.action-menu-dropdown .action-menu-danger:hover,
.action-menu-dropdown .action-menu-danger:focus-visible {
  background: var(--danger);
  color: var(--text-on-primary, #fff);
}

.action-menu-caret {
  margin-left: 6px;
  font-size: 0.7em;
  line-height: 1;
}

/* =========================================
   11. BADGES
   ========================================= */
/* Links in running text and tables.
   The colour comes from a variable rather than a `body.dark-mode a` override:
   that selector outranks component classes like .nav-item and would repaint the
   sidebar. As a bare element selector, every component still wins. */
a {
  color: var(--link);
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

.badge {
  display: inline-block;
  padding: 4px 10px;
  border-radius: 20px;
  font-size: 0.75rem;
  font-weight: 600;
}

.badge-success {
  background: var(--success-soft);
  color: var(--primary);
}

.badge-danger {
  background: var(--danger-soft);
  color: var(--danger);
}

.badge-gray,
.badge-neutral {
  background: rgba(138, 138, 142, 0.15);
  color: var(--text-secondary);
}

.badge-warning {
  background: var(--warning-soft);
  color: var(--warning);
}

.badge-info {
  background: var(--info-soft);
  color: var(--info);
}

.badge-primary {
  background: var(--primary-soft);
  color: var(--primary-dark);
}

body.dark-mode .badge-primary {
  color: var(--primary);
}

/* Small dot used in front of status labels */
.status-dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  margin-right: 0.4rem;
  background: var(--text-secondary);
  vertical-align: middle;
}

.status-dot.is-online { background: var(--success); }
.status-dot.is-offline { background: var(--text-secondary); }
.status-dot.is-alert { background: var(--danger); }

/* =========================================
   12. LOGIN
   ========================================= */
.login-container {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-main);
  padding: 2rem;
}

.login-card {
  background: var(--bg-panel);
  padding: 2.5rem;
  border-radius: var(--border-radius-lg);
  border: 1px solid var(--border-color);
  width: 100%;
  max-width: 450px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
}

.login-title {
  font-size: 2rem;
  font-weight: 700;
  text-align: center;
  margin-bottom: 0.5rem;
  color: var(--text-primary);
}

.login-subtitle {
  text-align: center;
  color: var(--text-secondary);
  margin-bottom: 2rem;
}

/* =========================================
   13. CODE & MISC
   ========================================= */
.code-block {
  background: var(--bg-main);
  color: var(--primary);
  padding: 16px;
  border-radius: var(--border-radius-sm);
  font-family: 'JetBrains Mono', 'Courier New', monospace;
  font-size: 0.875rem;
  overflow-x: auto;
  margin: 1rem 0;
  border: 1px solid var(--border-color);
}

code {
  background: var(--gray-100);
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 0.8125rem;
}

/* Dropdown menus (legacy support) */
.admin-menu, .customer-menu { position: relative; display: inline-block; }

.admin-menu-trigger, .customer-menu-trigger {
  background: var(--bg-panel-hover);
  color: var(--text-primary);
  border: 1px solid var(--border-color);
  padding: 8px 16px;
  border-radius: var(--border-radius-sm);
  cursor: pointer;
  font-size: 0.875rem;
  font-weight: 500;
  transition: all 0.2s;
}

.admin-menu-trigger:hover, .customer-menu-trigger:hover {
  background: var(--gray-200);
}

.admin-menu-dropdown, .customer-menu-dropdown {
  display: none;
  position: absolute;
  right: 0;
  top: 100%;
  margin-top: 8px;
  background: var(--bg-panel);
  border: 1px solid var(--border-color);
  border-radius: var(--border-radius-md);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  min-width: 200px;
  z-index: var(--z-menu);
}

.admin-menu-dropdown a, .customer-menu-dropdown a {
  display: block;
  padding: 10px 16px;
  color: var(--text-primary);
  text-decoration: none;
  transition: all 0.2s;
  border-bottom: 1px solid var(--border-subtle);
  font-size: 0.875rem;
}

.admin-menu-dropdown a:last-child, .customer-menu-dropdown a:last-child {
  border-bottom: none;
}

.admin-menu-dropdown a:hover, .customer-menu-dropdown a:hover {
  background: var(--bg-panel-hover);
  color: var(--primary);
}

.admin-menu.active .admin-menu-dropdown, .customer-menu.active .customer-menu-dropdown {
  display: block;
}

/* =========================================
   14. ACTIVITY STATS (used in dashboards)
   ========================================= */
.activity-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 16px;
}

.activity-stat-item { text-align: center; }
.activity-stat-label { font-size: 0.8125rem; color: var(--text-secondary); margin-bottom: 4px; }
.activity-stat-value { font-size: 1.5rem; font-weight: 700; color: var(--text-primary); }
.activity-opens { color: var(--primary); }
.activity-closes { color: var(--warning); }

/* =========================================
   15. PROGRESS BARS
   ========================================= */



/* =========================================
   16. DASHBOARD STATS BAR
   ========================================= */
.dash-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
  gap: 1px;
  background: var(--border-color);
  border: 1px solid var(--border-color);
  border-radius: var(--border-radius-md);
  overflow: hidden;
}

.dash-stat {
  background: var(--bg-panel);
  padding: 20px 16px;
  text-align: center;
}

.dash-stat-value {
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--text-primary);
  line-height: 1;
}

.dash-stat-sub {
  font-size: 1rem;
  font-weight: 400;
  color: var(--text-secondary);
}

.dash-stat-label {
  font-size: 0.6875rem;
  color: var(--text-secondary);
  margin-top: 6px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* =========================================
   17. DARK MODE TOGGLE
   ========================================= */
.dark-mode-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 12px;
  color: var(--text-secondary);
  font-size: 0.875rem;
  cursor: pointer;
  border-radius: var(--border-radius-sm);
  transition: background 0.2s;
}

.dark-mode-toggle:hover {
  background: var(--bg-panel-hover);
}

.toggle-track {
  width: 36px;
  height: 20px;
  background: var(--gray-300);
  border-radius: 10px;
  position: relative;
  transition: background 0.2s;
}

.toggle-track.active {
  background: var(--primary);
}

.toggle-thumb {
  width: 16px;
  height: 16px;
  background: white;
  border-radius: 50%;
  position: absolute;
  top: 2px;
  left: 2px;
  transition: left 0.2s;
}

.toggle-track.active .toggle-thumb {
  left: 18px;
}

/* =========================================
   17. SEARCH BAR
   ========================================= */
.search-bar {
  background-color: var(--bg-panel);
  border: 1px solid var(--border-color);
  padding: 10px 16px;
  border-radius: 20px;
  color: var(--text-primary);
  width: 250px;
  font-size: 0.875rem;
  transition: border-color 0.2s;
}

.search-bar::placeholder { color: var(--text-secondary); }
.search-bar:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(181, 255, 60, 0.1);
}

/* =========================================
   17. UTILITIES
   ========================================= */
.mt-1 { margin-top: 0.5rem; }
.mt-2 { margin-top: 1rem; }
.mb-1 { margin-bottom: 0.5rem; }
.mb-2 { margin-bottom: 1rem; }
.text-center { text-align: center; }
.text-sm { font-size: 0.875rem; }

/* =========================================
   18. RESPONSIVE
   ========================================= */
@media (max-width: 768px) {
  .dashboard-layout {
    grid-template-columns: 1fr;
  }

  .sidebar {
    position: fixed;
    left: -260px;
    top: 0;
    width: 260px;
    z-index: var(--z-sidebar);
    transition: left 0.3s ease;
    box-shadow: 4px 0 20px rgba(0, 0, 0, 0.5);
  }

  .sidebar.open {
    left: 0;
  }

  .mobile-menu-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    position: fixed;
    top: 16px;
    left: 16px;
    z-index: calc(var(--z-sidebar) - 1);
    width: 44px;
    height: 44px;
    background: var(--bg-panel);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-sm);
    color: var(--text-primary);
    font-size: 1.25rem;
    cursor: pointer;
  }

  .main-content {
    padding: 24px 16px;
    padding-top: 72px;
    max-height: none;
  }

  .page-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
  }

  .page-title { font-size: 1.4rem; }

  .grid-2, .grid-3, .grid-2-col {
    grid-template-columns: 1fr;
  }

  .kpi-grid, .stats-grid {
    grid-template-columns: 1fr;
  }

  .device-actions .btn { flex: 1 1 calc(50% - 4px); text-align: center; }

  .table { min-width: 600px; }

  .modal-content {
    margin: 5% 2.5%;
    padding: 20px;
    width: 95%;
  }
}

@media (min-width: 769px) {
  .mobile-menu-toggle {
    display: none;
  }
}

@media (max-width: 480px) {
  .main-content { padding: 16px 12px; padding-top: 64px; }
  .page-title { font-size: 1.25rem; }
  .device-header { flex-direction: column; align-items: flex-start; gap: 8px; }
  .device-actions .btn { flex: 1 1 100%; }
}

/* Touch improvements */
@media (hover: none) and (pointer: coarse) {
  .btn { min-height: 44px; }
  .form-input { min-height: 44px; }
  .nav-item { min-height: 44px; }
}

/* Deleting a device is not a tidy-up - it strands hardware in the field until
   someone drives out with a cable. The warning is styled to be read, not
   dismissed. */
.delete-warning {
  border: 1px solid var(--danger);
  border-radius: var(--border-radius-md);
  background: var(--bg-panel-hover);
  padding: 14px 16px;
  margin: 12px 0 20px 0;
}

.delete-warning-title {
  margin: 0 0 8px 0;
  color: var(--danger);
  font-weight: 600;
}

.delete-warning ul {
  margin: 0;
  padding-left: 20px;
  color: var(--text-secondary);
  font-size: 0.875rem;
  line-height: 1.5;
}

.delete-warning li + li {
  margin-top: 6px;
}

/* Heartbeat interval: the running cost estimate and the comparison table */
.ping-estimate {
  font-size: 0.875rem;
  color: var(--text-secondary);
}

.ping-estimate-high {
  color: var(--danger);
  font-weight: 600;
}

.ping-estimate-invalid {
  color: var(--warning, var(--danger));
}

.ping-table {
  width: 100%;
  margin-top: 0.75rem;
  border-collapse: collapse;
  font-size: 0.8125rem;
}

.ping-table th,
.ping-table td {
  text-align: left;
  padding: 6px 10px;
  border-bottom: 1px solid var(--border-subtle);
}

.ping-table th {
  color: var(--text-secondary);
  font-weight: 600;
}

.ping-table td:not(:first-child) {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.ping-table-default td {
  font-weight: 600;
  color: var(--text-primary);
}

/* Firmware release notes, shown before an update can be queued. Monospaced and
   pre-wrapped because the notes are written as plain text with headings and
   bullets, and reflowing them loses the structure. */
.build-detail {
  margin-top: 1rem;
  border: 1px solid var(--border-color);
  border-radius: var(--border-radius-md);
  background: var(--bg-panel-hover);
  padding: 12px 14px;
}

.build-detail-head {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-bottom: 10px;
}

.build-detail-head > span:first-child {
  font-weight: 600;
  color: var(--text-primary);
}

.build-detail-head .text-sm {
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

.build-detail-notes {
  margin: 0;
  max-height: 260px;
  overflow-y: auto;
  white-space: pre-wrap;
  word-break: break-word;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--text-secondary);
}

/* =========================================
   SETTINGS PAGES
   One panel, sections as rows: what it is on the left, the fields on the
   right. Shared by the admin customer form and the customer's own Settings,
   so the two read as the same product. Fields take their natural width - a
   three-digit limit does not get a full-width box.
   ========================================= */
.settings-panel {
  background: var(--bg-panel);
  border: 1px solid var(--border-color);
  border-radius: var(--border-radius-md);
}

.settings-section {
  display: grid;
  grid-template-columns: minmax(180px, 240px) 1fr;
  gap: 32px;
  padding: 28px 28px;
  border-top: 1px solid var(--border-color);
}

.settings-section:first-child { border-top: 0; }

.settings-section-intro h2 {
  font-size: 0.9375rem;
  font-weight: 600;
  margin: 0 0 6px;
  color: var(--text-primary);
}

.settings-section-intro p {
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--text-secondary);
  margin: 0;
  max-width: 28ch;
}

.settings-section-body { min-width: 0; }
.settings-section-body > * + * { margin-top: 16px; }
.settings-section-body .form-group { margin-bottom: 0; }

/* A row of fields that each take only the width they need */
.field-row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px 24px;
  align-items: flex-end;
}

.field-row .form-group { margin: 0; }
.field-row .form-input { width: auto; }
.form-input.w-xs { width: 9ch; text-align: right; font-variant-numeric: tabular-nums; }
.form-input.w-sm { width: 14ch; }
.form-input.w-md { width: 24ch; }
.form-input.w-lg { width: 38ch; max-width: 100%; }
.form-input.w-full { width: 100%; }

.form-help {
  color: var(--text-secondary);
  font-size: 0.8125rem;
  margin: 6px 0 0;
}

/* A rule written as a sentence, with the numbers as fields */
.rule-sentence {
  font-size: 0.9375rem;
  line-height: 2.4;
  color: var(--text-primary);
}

.rule-sentence .form-input {
  display: inline-block;
  width: 7.5ch;
  padding: 4px 8px;
  margin: 0 2px;
  text-align: right;
  font-variant-numeric: tabular-nums;
  vertical-align: baseline;
}

/* Two checkboxes side by side read as a pair, not a list */
.choice-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 32px;
}

.choice-row .form-checkbox { font-size: 0.9375rem; color: var(--text-primary); }

/* Read-only values: id, secret. Plain text on the panel, monospace only
   because the eye needs to count characters. */
.readonly-value {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.readonly-value code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.8125rem;
  color: var(--text-primary);
  background: var(--bg-main);
  border: 1px solid var(--border-subtle);
  border-radius: var(--border-radius-sm);
  padding: 6px 10px;
  word-break: break-all;
}

.btn-link {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-size: 0.8125rem;
  color: var(--link);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.btn-link:hover { color: var(--primary-dark); }

/* The one place on a settings page where a red button belongs */
.danger-zone {
  margin-top: 24px;
  padding: 20px 28px;
  border: 1px solid var(--danger-soft);
  border-radius: var(--border-radius-md);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}

.danger-zone p { margin: 0; font-size: 0.8125rem; color: var(--text-secondary); }
.danger-zone strong { display: block; font-size: 0.9375rem; color: var(--text-primary); margin-bottom: 4px; }

/* Empty tables say what to do, in the table's own voice */
.table td.empty { color: var(--text-secondary); font-style: normal; }

.header-actions .btn + .btn { margin-left: 0; }

@media (max-width: 820px) {
  .settings-section { grid-template-columns: 1fr; gap: 12px; padding: 20px; }
  .settings-section-intro p { max-width: none; }
  .danger-zone { padding: 16px 20px; }
  /* On a phone every field takes the full row; a 38ch box has nowhere to go */
  .field-row .form-group { flex: 1 1 100%; }
  .field-row .form-input,
  .form-input.w-sm, .form-input.w-md, .form-input.w-lg { width: 100%; }
  .form-input.w-xs, .rule-sentence .form-input { width: auto; min-width: 7.5ch; }
}
