/* Quetebe Panel Solar — styles */
@import url('https://fonts.googleapis.com/css2?family=Rubik:wght@400;500;600;700&family=Poppins:wght@600;700;800&display=swap');

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  --sidebar-w: 230px;
  --amber:     #e65100;
  --amber-dk:  #bf360c;
  --bg:        #f8fafc;
  --surface:   #ffffff;
  --border:    #e2e8f0;
  --text:      #1e293b;
  --muted:     #64748b;
  /* Alias retrocompat: muchas pages (subscriptions.php, client.php,
     plants.php…) usan var(--dark) — variable que existió en versiones
     antiguas y se renombró a --text, pero los var(--dark) sueltos
     quedaron por todo el codebase. Mantenemos el alias para que
     funcionen en ambos temas sin tener que buscar y reemplazar 200+
     ocurrencias en 50+ ficheros. */
  --dark:      var(--text);
  --card-bg:   var(--surface);
  --card:      var(--surface);
  --bg-soft:   #f1f5f9;
  --green:     #10b981;
  --red:       #ef4444;
  --yellow:    #f59e0b;
  --blue:      #3b82f6;
  --sidebar-bg:#1a1a2e;
  --sidebar-tx:#94a3b8;
  --sidebar-active:#ff7043;
  --radius:    8px;
}

body {
  font-family: 'Rubik', -apple-system, BlinkMacSystemFont, sans-serif;
  font-size: 14px;
  color: var(--text);
  background: var(--bg);
  line-height: 1.5;
  /* `overflow-x:hidden` en body/layout rompe `position: sticky` en
     ciertas combinaciones de Chrome/Safari + flex. `clip` evita el
     scroll horizontal sin convertir el body en un scroll container
     problemático para la sidebar. */
  overflow-x: clip;
}

h1, h2, h3, .page-header h1, .card-title {
  font-family: 'Poppins', 'Rubik', sans-serif;
}

/* ── LAYOUT ─────────────────────────────────────── */

.layout {
  display: flex;
  align-items: flex-start;
  min-height: 100vh;
  width: 100%;
  max-width: 100%;
  position: relative;
}

/* ── SIDEBAR ────────────────────────────────────── */

.sidebar {
  width: var(--sidebar-w);
  background: var(--sidebar-bg);
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  position: sticky;
  top: 0;
  left: 0;
  height: 100dvh;
  min-height: 100vh;
  margin: 0 !important;
  /* Como flex-item sticky, no debe estirarse a la altura del layout o
     acaba "despegándose" y scrolleando con la página en páginas largas. */
  align-self: flex-start;
}

.sidebar-logo {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 20px 16px 18px;
  border-bottom: 1px solid rgba(255,255,255,.07);
  text-decoration: none;
}
.sidebar-logo-name {
  font-family: 'Poppins', sans-serif;
  font-weight: 700;
  font-size: 16px;
  color: #f1f5f9;
  line-height: 1.15;
  letter-spacing: -.01em;
}
.sidebar-logo-sub {
  font-size: 9.5px;
  color: rgba(255,255,255,.4);
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  margin-top: 1px;
}

.sidebar-nav {
  flex: 1;
  padding: 12px 8px;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border-radius: var(--radius);
  color: var(--sidebar-tx);
  text-decoration: none;
  font-weight: 500;
  transition: background .15s, color .15s;
}
.nav-item:hover { background: rgba(255,255,255,.06); color: #f1f5f9; }
.nav-item.active { background: rgba(230,81,0,.18); color: var(--sidebar-active); }

/* Badge de contador (ej. vencidas en Tareas) */
.nav-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 6px;
  border-radius: 9px;
  background: #dc2626;
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .02em;
  line-height: 1;
}

/* Sub-navegación colgante (ej. Monitoreo → Solares). Se muestra sólo cuando
   el ítem padre está activo — así el rail queda compacto en reposo. */
.nav-sub {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 2px 0 6px 32px; /* alineado con el texto del padre, no con su icono */
  border-left: 1px solid rgba(255,255,255,.08);
  padding-left: 10px;
}
.nav-sub-item {
  color: var(--sidebar-tx);
  text-decoration: none;
  font-size: 12.5px;
  padding: 5px 8px;
  border-radius: 6px;
  transition: background .15s, color .15s;
}
.nav-sub-item:hover { background: rgba(255,255,255,.05); color: #f1f5f9; }
.nav-sub-item.active { color: var(--sidebar-active); background: rgba(230,81,0,.10); font-weight: 600; }

.sidebar-footer {
  padding: 10px 10px 12px;
  border-top: 1px solid rgba(255,255,255,.07);
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
}
/* Cuando theme.js hace appendChild del toggle, lo centramos bajo el pill. */
.sidebar-footer .theme-toggle {
  align-self: center;
  margin-right: 0;
}

/* Botón "píldora" de usuario: abre el menú de ajustes/secundarios. */
.user-pill {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius);
  color: var(--sidebar-tx);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  text-align: left;
  transition: background .15s, color .15s, border-color .15s;
}
.user-pill:hover,
.user-pill.open {
  background: rgba(255,255,255,.06);
  color: #f1f5f9;
  border-color: rgba(255,255,255,.08);
}
.user-pill.active {
  background: rgba(230,81,0,.14);
  color: var(--sidebar-active);
}
.user-pill-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--amber) 0%, var(--amber-dk) 100%);
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .02em;
  flex-shrink: 0;
}
.user-pill-name {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 500;
}
.user-pill-caret {
  opacity: .6;
  transition: transform .15s, opacity .15s;
}
.user-pill.open .user-pill-caret {
  transform: rotate(180deg);
  opacity: 1;
}

/* Popover del user menu: flota por encima del footer, ancla abajo-izquierda. */
.user-menu {
  position: absolute;
  left: 8px;
  right: 8px;
  bottom: calc(100% - 6px);
  background: #24243a;       /* sólido — sin alpha ni var con transparencia */
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 10px;
  padding: 6px;
  box-shadow: 0 12px 28px rgba(0,0,0,.55), 0 2px 8px rgba(0,0,0,.35);
  z-index: 1000;             /* delante del overlay del aside contraído */
  animation: userMenuIn .12s ease-out;
}
/* Cuando el sidebar está colapsado, los items del popover se cortan
   porque el ancho del sidebar es 56px. Lo sacamos a la derecha del
   sidebar para que se vea entero, y forzamos un ancho mínimo legible. */
.layout.sidebar-collapsed .user-menu {
  left: calc(100% + 6px);
  right: auto;
  bottom: 8px;
  min-width: 220px;
}
@keyframes userMenuIn {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}
.user-menu[hidden] { display: none; }

.user-menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 6px;
  color: var(--sidebar-tx);
  text-decoration: none;
  font-size: 13px;
  font-weight: 500;
  transition: background .12s, color .12s;
}
.user-menu-item:hover {
  background: rgba(255,255,255,.07);
  color: #f1f5f9;
}
.user-menu-item.active {
  background: rgba(230,81,0,.18);
  color: var(--sidebar-active);
}
.user-menu-item-danger { color: #fca5a5; }
.user-menu-item-danger:hover { background: rgba(239,68,68,.14); color: #fecaca; }
.user-menu-sep {
  height: 1px;
  margin: 6px 4px;
  background: rgba(255,255,255,.08);
}

/* ── MAINTENANCE SECTION TABS ──────────────────────────────────────────
   Sub-nav compartido entre subscriptions.php y plants.php. Se renderiza
   al inicio del <main>, por encima del page-header. */
.maint-tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 22px;
  border-bottom: 2px solid var(--border);
}
.maint-tab {
  padding: 10px 18px;
  text-decoration: none;
  color: var(--muted);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .01em;
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  transition: color .15s, border-color .15s;
}
.maint-tab:hover { color: var(--text); }
.maint-tab.active {
  color: var(--amber-dk);
  border-bottom-color: var(--amber);
}

/* ── MAIN ───────────────────────────────────────── */

.main {
  flex: 1 1 auto;
  padding: 32px 36px;
  max-width: none;
  width: 100%;
  overflow-x: auto;
  /* min-width:0 para que flex children con grid/textos largos puedan
     hacer overflow correctamente sin "salir" del layout. */
  min-width: 0;
  min-height: 100vh;
}
/* Las pantallas tipo "cliente de email" (bandeja) necesitan TODO el
   ancho disponible — sin esto, al colapsar el sidebar queda una franja
   blanca a la derecha que rompe la sensación de "app pantalla completa".
   Padding 0 para que la bandeja vaya a sangre pegada al sidebar y al
   borde derecho. Cada hijo (breadcrumbs, mb-stage) gestiona su propio
   padding interno. */
/* Paginas de tablas anchas (p.ej. historial de llamadas): ocupan todo el
   ancho disponible sin cambiar el padding ni el layout normal. */
.main.main-wide { max-width: none; }

.main.main-fluid {
  max-width: none;
  width: auto;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  padding: 0 !important;
  margin: 0 !important;
  background: var(--surface);
  overflow: hidden;
}
/* Breadcrumbs dentro de main-fluid: barra superior fina con borde, no
   un bloque grande con margen — gana altura para la bandeja. */
.main.main-fluid > .qtb-breadcrumbs {
  padding: 8px 14px !important;
  margin: 0 !important;
  border: 0 !important;
  border-bottom: 1px solid var(--border) !important;
  background: var(--surface);
  border-radius: 0;
}

.page-header { margin-bottom: 28px; }
.page-header h1 { font-size: 22px; font-weight: 700; }
.page-sub { color: var(--muted); margin-top: 4px; font-size: 13px; }
.back-link { font-size: 13px; color: var(--muted); text-decoration: none; display: block; margin-bottom: 6px; }
.back-link:hover { color: var(--text); }

/* ── STATS GRID ─────────────────────────────────── */

.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 16px;
  margin-bottom: 28px;
}

.stat-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
}
.stat-card.highlight { border-color: var(--amber); background: #fffbeb; }
.stat-value { font-size: 32px; font-weight: 700; line-height: 1; }
.stat-label { font-size: 12px; color: var(--muted); margin-top: 6px; }
.stat-card.highlight .stat-value { color: var(--amber-dk); }

/* ── FILTER TABS ────────────────────────────────── */

.filter-tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 16px;
  border-bottom: 2px solid var(--border);
  padding-bottom: 0;
}

.tab {
  padding: 8px 14px;
  text-decoration: none;
  color: var(--muted);
  font-size: 13px;
  font-weight: 500;
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  transition: color .15s, border-color .15s;
}
.tab:hover { color: var(--text); }
.tab.active { color: var(--amber-dk); border-bottom-color: var(--amber); }

/* ── TABLE ──────────────────────────────────────── */

.table-wrap {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
.table thead { background: #f8fafc; }
.table th {
  padding: 10px 14px;
  text-align: left;
  font-weight: 600;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--muted);
  border-bottom: 1px solid var(--border);
}
.table td {
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
.table tbody tr:last-child td { border-bottom: none; }
.table tbody tr:hover { background: rgba(230,81,0,.06); }

.client-name { font-weight: 600; }

/* Nombres de cliente SIEMPRE en mayúsculas en toda la UI. Aplica a las
   distintas clases que usamos según el contexto (tabla de servicios,
   ficha de cliente, buscadores, bandejas, etc.) — así con un solo
   selector cubrimos todo sin tener que mutar los datos. Stripe y STEL
   devuelven nombres mezclados ("PAUL DE HAES" vs "Paul Allen Stotesbury")
   y Antonio quiere verlos normalizados a golpe de vista. */
.cust-name,
.client-name,
.customer-name,
.lsv-name,
.qtb-client-name { text-transform: uppercase; }

/* ── BADGES ─────────────────────────────────────── */

.badge {
  display: inline-block;
  padding: 2px 7px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
}
.badge-solar { background: #fef3c7; color: #92400e; }
.badge-brand { background: #eff6ff; color: #1d4ed8; }

.status-badge {
  display: inline-block;
  padding: 3px 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
}
.status-active   { background: #dcfce7; color: #166534; }
.status-warning  { background: #fef9c3; color: #854d0e; }
.status-inactive { background: #f1f5f9; color: var(--muted); }
.status-none     { background: #f1f5f9; color: var(--muted); }

/* ── BUTTONS ────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  transition: background .15s, border-color .15s;
}
.btn:hover { background: #f1f5f9; }
.btn-sm { padding: 4px 10px; font-size: 12px; }
.btn-primary { background: var(--amber); border-color: var(--amber-dk); color: #fff; }
.btn-primary:hover { background: var(--amber-dk); }
.btn-full { width: 100%; justify-content: center; }

/* ── FORMS ──────────────────────────────────────── */

.form-group { margin-bottom: 16px; }
.form-group label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  margin-bottom: 5px;
  text-transform: uppercase;
  letter-spacing: .04em;
}
.form-group input,
.form-group select,
.form-group textarea {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: 14px;
  font-family: inherit;
  background: var(--surface);
  color: var(--text);
  transition: border-color .15s;
}
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
  outline: none;
  border-color: var(--amber);
  box-shadow: 0 0 0 3px rgba(230,81,0,.13);
}
.form-hint { font-size: 11px; color: var(--muted); margin-top: 4px; display: block; }

.form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

.divider { border: none; border-top: 1px solid var(--border); margin: 20px 0; }

/* ── CARDS ──────────────────────────────────────── */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  margin-bottom: 16px;
}
.card-title {
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--muted);
  margin-bottom: 14px;
}
.card-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 36px;
  color: var(--muted);
  text-align: center;
}

/* ── ENTITY RELATIONSHIPS ───────────────────────── */

.qtb-rel-card {
  overflow: hidden;
}

.qtb-rel-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 14px;
  margin-bottom: 12px;
}

.qtb-rel-title {
  margin: 0 0 3px;
  font-size: 15px;
  font-weight: 800;
  color: var(--text);
}

.qtb-rel-sub {
  color: var(--muted);
  font-size: 12.5px;
  line-height: 1.35;
}

.qtb-rel-total,
.qtb-rel-chip {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--bg-soft);
  color: var(--muted);
  font-size: 12px;
  line-height: 1;
}

.qtb-rel-total {
  padding: 7px 10px;
  font-weight: 700;
}

.qtb-rel-summary {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin-bottom: 14px;
}

.qtb-rel-chip {
  gap: 5px;
  padding: 6px 9px;
}

.qtb-rel-chip strong {
  color: var(--text);
}

.qtb-rel-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 12px;
}

.qtb-rel-group {
  min-width: 0;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
}

.qtb-rel-group-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
  font-size: 12px;
  font-weight: 800;
  color: var(--muted);
  text-transform: uppercase;
}

.qtb-rel-group-title strong {
  color: var(--text);
  font-size: 12px;
}

.qtb-rel-items {
  display: flex;
  flex-direction: column;
}

.qtb-rel-item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  min-height: 40px;
  padding: 9px 12px;
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid rgba(148, 163, 184, .18);
}

.qtb-rel-item:last-child {
  border-bottom: 0;
}

a.qtb-rel-item:hover {
  background: var(--bg-soft);
}

.qtb-rel-item-main {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
}

.qtb-rel-item-meta,
.qtb-rel-more,
.qtb-rel-note,
.qtb-rel-empty,
.qtb-rel-error,
.qtb-rel-muted {
  color: var(--muted);
  font-size: 12px;
}

.qtb-rel-item-meta {
  justify-self: end;
  max-width: 120px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.qtb-rel-more,
.qtb-rel-note,
.qtb-rel-empty,
.qtb-rel-error {
  padding: 10px 12px;
}

.qtb-rel-error {
  color: #b91c1c;
}

@media (max-width: 720px) {
  .qtb-rel-head {
    align-items: stretch;
    flex-direction: column;
  }
  .qtb-rel-total {
    align-self: flex-start;
  }
  .qtb-rel-list {
    grid-template-columns: 1fr;
  }
  .qtb-rel-item {
    grid-template-columns: 1fr;
    gap: 3px;
  }
  .qtb-rel-item-meta {
    justify-self: start;
    max-width: 100%;
  }
}

/* ── INFO GRID ──────────────────────────────────── */

.info-grid { display: flex; flex-direction: column; gap: 8px; }
.info-row { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.info-label { font-size: 12px; color: var(--muted); white-space: nowrap; }
.info-value { font-size: 13px; font-weight: 500; text-align: right; }

/* ── SUBSCRIPTION TIER ──────────────────────────── */

.sub-tier {
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-bottom: 8px;
}
.sub-basic   { background: #eff6ff; border-left: 4px solid #3b82f6; }
.sub-medium  { background: #f0fdf4; border-left: 4px solid #10b981; }
.sub-premium { background: #fffbeb; border-left: 4px solid #f59e0b; }
.sub-none    { background: #f8fafc; border-left: 4px solid #cbd5e1; }
.sub-tier-name { font-size: 16px; font-weight: 700; }
.sub-tier-freq { font-size: 12px; color: var(--muted); margin-top: 2px; }

/* ── TWO-COL LAYOUT ─────────────────────────────── */

.two-col {
  display: grid;
  grid-template-columns: 1fr 340px;
  gap: 20px;
  align-items: start;
}

/* ── ALERTS ─────────────────────────────────────── */

.alert {
  padding: 10px 14px;
  border-radius: var(--radius);
  font-size: 13px;
  margin-bottom: 16px;
}
.alert-success { background: #dcfce7; color: #166534; border: 1px solid #bbf7d0; }
.alert-error   { background: #fee2e2; color: #991b1b; border: 1px solid #fecaca; }
.alert-info    { background: #eff6ff; color: #1d4ed8; border: 1px solid #bfdbfe; }

/* ── UTILITIES ──────────────────────────────────── */

.text-muted  { color: var(--muted); }
.text-sm     { font-size: 12px; }
.text-mono   { font-family: 'SF Mono', 'Menlo', monospace; }
.text-warning{ color: var(--yellow); }

/* ── LOGIN PAGE ─────────────────────────────────── */

.login-body {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  background: linear-gradient(135deg, #1a1a2e 0%, #0f172a 60%, #1a0a00 100%);
}

.login-box {
  background: var(--surface);
  border-radius: 12px;
  padding: 36px;
  width: 100%;
  max-width: 380px;
  box-shadow: 0 20px 60px rgba(0,0,0,.3);
}

.login-logo {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 28px;
  font-size: 18px;
  font-weight: 700;
}

/* ── RESPONSIVE ─────────────────────────────────── */

@media (max-width: 900px) {
  /* Sidebar colapsable — se desliza desde la izquierda al pulsar el
     hamburger. Por defecto está fuera de pantalla; cuando body tiene
     la clase .sidebar-open, entra. */
  .sidebar {
    position: fixed;
    top: 0; left: 0; bottom: 0;
    width: 260px;
    transform: translateX(-105%);
    transition: transform .22s ease-out;
    z-index: 150;
    box-shadow: 4px 0 16px rgba(15,23,42,.3);
  }
  body.sidebar-open .sidebar { transform: translateX(0); }

  /* Overlay semi-transparente que se activa con la sidebar abierta.
     Clic en él → cierra la sidebar. */
  .sidebar-overlay {
    position: fixed; inset: 0;
    background: rgba(15,23,42,.5);
    z-index: 140;
    opacity: 0;
    pointer-events: none;
    transition: opacity .22s;
  }
  body.sidebar-open .sidebar-overlay {
    opacity: 1;
    pointer-events: auto;
  }

  /* Botón hamburger fijo arriba-izquierda, sólo visible en móvil.
     Touch target ≥ 44×44 como manda iOS. */
  .sidebar-mobile-toggle {
    position: fixed;
    top: 12px; left: 12px;
    z-index: 130;
    width: 44px; height: 44px;
    display: flex;
    align-items: center; justify-content: center;
    background: var(--sidebar-bg);
    color: #fff;
    border: 0;
    border-radius: 10px;
    font-size: 22px;
    cursor: pointer;
    box-shadow: 0 4px 12px rgba(15,23,42,.25);
  }

  /* Si el usuario ha colapsado el rail de escritorio, mantenemos ese
     comportamiento también en viewport estrecho en lugar de mezclarlo con
     el drawer móvil. Esto evita la franja rara a la izquierda y deja la
     bandeja pegada al rail. */
  .layout.sidebar-collapsed .sidebar {
    position: sticky;
    top: 0;
    left: auto;
    bottom: auto;
    width: var(--sidebar-w);
    transform: none;
    transition: none;
    z-index: auto;
    box-shadow: none;
  }
  .layout.sidebar-collapsed .main {
    padding: 0 !important;
  }
  .layout.sidebar-collapsed .sidebar-mobile-toggle,
  .layout.sidebar-collapsed .sidebar-overlay,
  .layout.sidebar-collapsed .sidebar-collapse-toggle {
    display: none !important;
  }

  .main { padding: 72px 14px 20px; }
  .two-col { grid-template-columns: 1fr; }
  .form-row { grid-template-columns: 1fr; }
  .stats-grid { grid-template-columns: 1fr 1fr; }

  /* Tablas con scroll horizontal para no romper el layout en móvil. */
  table { min-width: 100%; }
  .table-responsive,
  .tasks-wrap > table,
  .sub-wrap > .card table {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
}
@media (min-width: 901px) {
  .sidebar-mobile-toggle, .sidebar-overlay { display: none; }
}

/* ── THEME TOGGLE (3 estados: claro / oscuro / auto) ──────────────────── */

.theme-toggle {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 2px;
  border: 1px solid rgba(255,255,255,.1);
  border-radius: 999px;
  background: rgba(255,255,255,.03);
  margin-right: 6px;
}
.theme-toggle button {
  width: 22px;
  height: 22px;
  border: none;
  background: transparent;
  color: var(--sidebar-tx);
  border-radius: 999px;
  font-size: 12px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background .15s, color .15s;
}
.theme-toggle button:hover { color: #f1f5f9; }
.theme-toggle button.active {
  background: rgba(230,81,0,.22);
  color: var(--sidebar-active);
}

/* ── DARK THEME ────────────────────────────────────────────────────────
   Se activa con <html data-theme="dark">, o con data-theme="auto" /
   sin atributo cuando el OS está en modo oscuro. */

:root[data-theme="dark"] {
  --bg:       #0f172a;
  --surface:  #1a1f2e;
  --border:   #334155;
  --text:     #e2e8f0;
  --muted:    #94a3b8;
  /* --dark/--card-bg/--bg-soft heredan vía var() — pero las
     redefinimos explícitas para evitar fallback warnings y para
     poder afinar contraste en hover (bg-soft sobre dark debe ser
     un poco más claro que el surface, no el #f1f5f9 de light). */
  --dark:     var(--text);
  --card-bg:  var(--surface);
  --bg-soft:  #1f2937;
  /* P279 -- sin esto, los widgets NATIVOS del navegador (selector de
     fecha/hora emergente, flechitas de number, scrollbars) se siguen
     dibujando en el tema claro del sistema aunque el input ya tenga
     background/color oscuros via CSS -- el popup del calendario de
     <input type=date> salia blanco con texto negro sobre una pagina
     oscura. color-scheme le dice al navegador qué paleta usar para
     todo lo que él mismo pinta (fuera del control de CSS normal). */
  color-scheme: dark;
}
:root[data-theme="dark"] .table thead,
:root[data-theme="dark"] .btn:hover                { background: #131826; }
/* Hover de filas: tinte marca sutil en lugar de un gris más oscuro que
   el surface — se distingue mejor y acompaña al accent naranja del panel. */
:root[data-theme="dark"] .table tbody tr:hover     { background: rgba(230,81,0,.10); }
:root[data-theme="dark"] .table tbody tr:hover td  { color: var(--text); }
:root[data-theme="dark"] .back-link:hover          { color: var(--text); }
:root[data-theme="dark"] .stat-card.highlight      { background: rgba(245,158,11,.08); border-color: var(--amber); }
:root[data-theme="dark"] .stat-card.highlight .stat-value { color: var(--yellow); }
:root[data-theme="dark"] .filter-tabs              { border-bottom-color: var(--border); }
:root[data-theme="dark"] .tab:hover                { color: var(--text); }
:root[data-theme="dark"] .badge-solar              { background: rgba(245,158,11,.18); color: #fcd34d; }
:root[data-theme="dark"] .badge-brand              { background: rgba(59,130,246,.18); color: #93c5fd; }
:root[data-theme="dark"] .status-active            { background: rgba(16,185,129,.16); color: #6ee7b7; }
:root[data-theme="dark"] .status-warning           { background: rgba(234,179,8,.16);  color: #fde68a; }
:root[data-theme="dark"] .status-inactive,
:root[data-theme="dark"] .status-none              { background: rgba(148,163,184,.14); color: var(--muted); }
:root[data-theme="dark"] .alert-success            { background: rgba(16,185,129,.14); color: #6ee7b7; border-color: rgba(16,185,129,.3); }
:root[data-theme="dark"] .alert-error              { background: rgba(239,68,68,.14);  color: #fca5a5; border-color: rgba(239,68,68,.3); }
:root[data-theme="dark"] .alert-info               { background: rgba(59,130,246,.14); color: #93c5fd; border-color: rgba(59,130,246,.3); }
:root[data-theme="dark"] .sub-basic                { background: rgba(59,130,246,.10); }
:root[data-theme="dark"] .sub-medium               { background: rgba(16,185,129,.10); }
:root[data-theme="dark"] .sub-premium              { background: rgba(245,158,11,.10); }
:root[data-theme="dark"] .sub-none                 { background: rgba(148,163,184,.08); }
:root[data-theme="dark"] .form-group input,
:root[data-theme="dark"] .form-group select,
:root[data-theme="dark"] .form-group textarea     { background: #0f172a; color: var(--text); border-color: var(--border); }
:root[data-theme="dark"] .form-group input:focus,
:root[data-theme="dark"] .form-group select:focus,
:root[data-theme="dark"] .form-group textarea:focus { box-shadow: 0 0 0 3px rgba(230,81,0,.2); }

/* Modales (usados en plants.php) */
:root[data-theme="dark"] .modal-box                { background: var(--surface); color: var(--text); }
:root[data-theme="dark"] .modal-header             { border-bottom-color: var(--border); }
/* Header inline-styled azul de los modales de captura de sesión
   (FusionSolar / APsystems) — el azul claro en dark es ilegible. */
:root[data-theme="dark"] .modal-header[style*="background"] {
  background: rgba(59,130,246,.15) !important;
}
:root[data-theme="dark"] .modal-header .modal-title[style*="color"] {
  color: #93c5fd !important;
}
:root[data-theme="dark"] .plant-summary            { background: #131826; }

/* Cache-status-bar en plants.php (tiene estilos en <style> inline, pero los
   pills/cards heredan de --surface/--border) */
:root[data-theme="dark"] .cache-provider-status    { background: var(--surface); border-color: var(--border); }

/* Provider badges en filas de la tabla (plants.php) */
:root[data-theme="dark"] .provider-fs              { background: rgba(67,160,71,.18);  color: #6ee7b7; }
:root[data-theme="dark"] .provider-aps             { background: rgba(33,150,243,.18); color: #90caf9; }
:root[data-theme="dark"] .provider-deye            { background: rgba(186,104,200,.18); color: #ce93d8; }

/* Componentes QTB nuevos en dark mode */
:root[data-theme="dark"] .qtb-breadcrumbs          { background: var(--surface); border-color: var(--border); box-shadow: 0 1px 2px rgba(0,0,0,.2); }
:root[data-theme="dark"] .qtb-bc-back              { background: transparent; color: var(--text); border-color: var(--border); }
:root[data-theme="dark"] .qtb-bc-back:hover        { background: rgba(255,255,255,.04); border-color: #64748b; }
:root[data-theme="dark"] .qtb-bc-link              { color: #93c5fd; }
:root[data-theme="dark"] .qtb-bc-link:hover        { background: rgba(59,130,246,.12); }
:root[data-theme="dark"] .qtb-bc-sep               { color: #475569; }
:root[data-theme="dark"] .qtb-empty                { background: rgba(255,255,255,.02); border-color: var(--border); }
:root[data-theme="dark"] .qtb-skeleton             { background: linear-gradient(90deg, #1e293b 0%, #334155 50%, #1e293b 100%); background-size: 200% 100%; }

/* Modal scroll fix: el backdrop oscurecido ya es semi-transparente, no
   hay cambios. Pero el fondo del modal blanco debe oscurecerse. Las
   páginas ya definen .modal con var(--surface) en muchos casos, pero
   algunas lo dejan #fff duro. Añadimos fallback aquí. */
:root[data-theme="dark"] .modal-back[data-open="1"] > .modal,
:root[data-theme="dark"] .modal-back[data-open="1"] > div.modal,
:root[data-theme="dark"] .modal-back[data-open="1"] > .modal-box { background: var(--surface); color: var(--text); }

/* Toast en dark: los colores kind ya son fuertes y legibles sobre
   cualquier fondo, no requieren overrides. */

/* Auto: seguir preferencia del sistema si el usuario eligió "auto" o no eligió nada */
@media (prefers-color-scheme: dark) {
  :root[data-theme="auto"],
  :root:not([data-theme]) {
    --bg:       #0f172a;
    --surface:  #1a1f2e;
    --border:   #334155;
    --text:     #e2e8f0;
    --muted:    #94a3b8;
    --dark:     var(--text);
    --card-bg:  var(--surface);
    --bg-soft:  #1f2937;
    color-scheme: dark; /* P279 -- ver nota gemela en el bloque [data-theme="dark"] */
  }
  :root[data-theme="auto"] .table thead,
  :root[data-theme="auto"] .btn:hover              { background: #131826; }
  :root[data-theme="auto"] .table tbody tr:hover   { background: rgba(230,81,0,.10); }
  :root[data-theme="auto"] .table tbody tr:hover td { color: var(--text); }
  :root[data-theme="auto"] .stat-card.highlight    { background: rgba(245,158,11,.08); border-color: var(--amber); }
  :root[data-theme="auto"] .stat-card.highlight .stat-value { color: var(--yellow); }
  :root[data-theme="auto"] .filter-tabs            { border-bottom-color: var(--border); }
  :root[data-theme="auto"] .tab:hover              { color: var(--text); }
  :root[data-theme="auto"] .badge-solar            { background: rgba(245,158,11,.18); color: #fcd34d; }
  :root[data-theme="auto"] .badge-brand            { background: rgba(59,130,246,.18); color: #93c5fd; }
  :root[data-theme="auto"] .status-active          { background: rgba(16,185,129,.16); color: #6ee7b7; }
  :root[data-theme="auto"] .status-warning         { background: rgba(234,179,8,.16);  color: #fde68a; }
  :root[data-theme="auto"] .status-inactive,
  :root[data-theme="auto"] .status-none            { background: rgba(148,163,184,.14); color: var(--muted); }
  :root[data-theme="auto"] .alert-success          { background: rgba(16,185,129,.14); color: #6ee7b7; border-color: rgba(16,185,129,.3); }
  :root[data-theme="auto"] .alert-error            { background: rgba(239,68,68,.14);  color: #fca5a5; border-color: rgba(239,68,68,.3); }
  :root[data-theme="auto"] .alert-info             { background: rgba(59,130,246,.14); color: #93c5fd; border-color: rgba(59,130,246,.3); }
  :root[data-theme="auto"] .sub-basic              { background: rgba(59,130,246,.10); }
  :root[data-theme="auto"] .sub-medium             { background: rgba(16,185,129,.10); }
  :root[data-theme="auto"] .sub-premium            { background: rgba(245,158,11,.10); }
  :root[data-theme="auto"] .sub-none               { background: rgba(148,163,184,.08); }
  :root[data-theme="auto"] .form-group input,
  :root[data-theme="auto"] .form-group select,
  :root[data-theme="auto"] .form-group textarea    { background: #0f172a; color: var(--text); border-color: var(--border); }
  :root[data-theme="auto"] .modal-box              { background: var(--surface); color: var(--text); }
  :root[data-theme="auto"] .modal-header           { border-bottom-color: var(--border); }
  :root[data-theme="auto"] .modal-header[style*="background"] { background: rgba(59,130,246,.15) !important; }
  :root[data-theme="auto"] .modal-header .modal-title[style*="color"] { color: #93c5fd !important; }
  :root[data-theme="auto"] .cache-provider-status  { background: var(--surface); border-color: var(--border); }
  :root[data-theme="auto"] .provider-fs            { background: rgba(67,160,71,.18);  color: #6ee7b7; }
  :root[data-theme="auto"] .provider-aps           { background: rgba(33,150,243,.18); color: #90caf9; }
  :root[data-theme="auto"] .provider-deye          { background: rgba(186,104,200,.18); color: #ce93d8; }
}

/* ═════════════════════════════════════════════════════════════════════════
   Accesibilidad global — focus rings visibles y consistentes.
   Sin esto el usuario con teclado no sabe dónde está.
   ═════════════════════════════════════════════════════════════════════════ */
*:focus-visible {
  outline: 2px solid #1d4ed8;
  outline-offset: 2px;
  border-radius: 4px;
}
:root[data-theme="dark"] *:focus-visible {
  outline-color: #60a5fa;
}

/* ═════════════════════════════════════════════════════════════════════════
   Dark-mode global overrides para inline-styles hardcodeados.

   Las páginas tienen MUCHOS style="background:#fff", style="background:#fef2f2"
   etc. que pintan claro hardcoded y rompen el dark. Refactorizar archivo a
   archivo cada inline-style es semanas de curro. Esta sección intercepta
   los patrones más frecuentes con attribute selectors para sobreescribirlos
   sólo en dark.

   Nota: usar !important es deliberado — los inline-styles tienen mayor
   specificity y sólo se les puede ganar con !important. La regla cubre
   tanto data-theme="dark" como data-theme="auto" + @media prefers dark.
   ═════════════════════════════════════════════════════════════════════════ */

/* Helper macro: la lista de selectores raíz que activan dark mode.  */
/* (CSS no tiene macros, así que repetimos el `[data-theme="dark"], …`
   en cada bloque. Se duplica pero es lo más sencillo.) */

/* — Backgrounds blancos hardcodeados → surface oscuro — */
:root[data-theme="dark"] [style*="background:#fff"],
:root[data-theme="dark"] [style*="background: #fff"],
:root[data-theme="dark"] [style*="background:white"]      { background: var(--surface) !important; }

/* — Tints pastel (rojo/ámbar/azul/verde) → rgba sobre surface oscuro — */
:root[data-theme="dark"] [style*="background:#fef2f2"],
:root[data-theme="dark"] [style*="background:#fee2e2"],
:root[data-theme="dark"] [style*="background:#fef3c7"],
:root[data-theme="dark"] [style*="background:#ffebee"]    { background: rgba(239,68,68,.10) !important; color: #fca5a5 !important; }

:root[data-theme="dark"] [style*="background:#fffbeb"],
:root[data-theme="dark"] [style*="background:#fff3e0"],
:root[data-theme="dark"] [style*="background:#fff7ed"]    { background: rgba(245,158,11,.10) !important; }

:root[data-theme="dark"] [style*="background:#eff6ff"],
:root[data-theme="dark"] [style*="background:#dbeafe"],
:root[data-theme="dark"] [style*="background:#e3f2fd"]    { background: rgba(59,130,246,.10) !important; }

:root[data-theme="dark"] [style*="background:#f0fdf4"],
:root[data-theme="dark"] [style*="background:#dcfce7"],
:root[data-theme="dark"] [style*="background:#e8f5e9"],
:root[data-theme="dark"] [style*="background:#f1f8e9"]    { background: rgba(16,185,129,.10) !important; }

/* — Gradientes pastel completos en estilos inline (típico atencion/dashboard) — */
:root[data-theme="dark"] [style*="linear-gradient(135deg,#fef2f2"],
:root[data-theme="dark"] [style*="linear-gradient(135deg, #fef2f2"] { background: linear-gradient(135deg, rgba(239,68,68,.12), rgba(239,68,68,.04)) !important; }
:root[data-theme="dark"] [style*="linear-gradient(135deg,#fffbeb"],
:root[data-theme="dark"] [style*="linear-gradient(135deg, #fffbeb"] { background: linear-gradient(135deg, rgba(245,158,11,.12), rgba(245,158,11,.04)) !important; }
:root[data-theme="dark"] [style*="linear-gradient(135deg,#eff6ff"],
:root[data-theme="dark"] [style*="linear-gradient(135deg, #eff6ff"] { background: linear-gradient(135deg, rgba(59,130,246,.12), rgba(59,130,246,.04)) !important; }
:root[data-theme="dark"] [style*="linear-gradient(135deg,#f0fdf4"],
:root[data-theme="dark"] [style*="linear-gradient(135deg, #f0fdf4"] { background: linear-gradient(135deg, rgba(16,185,129,.12), rgba(16,185,129,.04)) !important; }

/* — Textos hardcoded oscuros sobre fondos pastel → tonos pastel del color — */
/* Rojos */
:root[data-theme="dark"] [style*="color:#991b1b"],
:root[data-theme="dark"] [style*="color:#7f1d1d"],
:root[data-theme="dark"] [style*="color:#b71c1c"],
:root[data-theme="dark"] [style*="color:#c62828"],
:root[data-theme="dark"] [style*="color:#dc2626"]         { color: #fca5a5 !important; }
/* Naranjas / ámbares */
:root[data-theme="dark"] [style*="color:#9a3412"],
:root[data-theme="dark"] [style*="color:#92400e"],
:root[data-theme="dark"] [style*="color:#bf360c"],
:root[data-theme="dark"] [style*="color:#e65100"]         { color: #fcd34d !important; }
/* Azules */
:root[data-theme="dark"] [style*="color:#0d47a1"],
:root[data-theme="dark"] [style*="color:#1e40af"],
:root[data-theme="dark"] [style*="color:#1565c0"]         { color: #93c5fd !important; }
/* Verdes */
:root[data-theme="dark"] [style*="color:#166534"],
:root[data-theme="dark"] [style*="color:#1b5e20"],
:root[data-theme="dark"] [style*="color:#388e3c"]         { color: #6ee7b7 !important; }
/* Grises oscuros mid-tone (tablas, etc) → muted del tema */
:root[data-theme="dark"] [style*="color:#374151"]         { color: var(--text) !important; }

/* Mismas reglas para data-theme="auto" cuando el OS está en dark. Lo
   duplicamos dentro del @media para no aplicarse en light. */
@media (prefers-color-scheme: dark) {
  :root[data-theme="auto"] [style*="background:#fff"],
  :root[data-theme="auto"] [style*="background: #fff"],
  :root[data-theme="auto"] [style*="background:white"]    { background: var(--surface) !important; }

  :root[data-theme="auto"] [style*="background:#fef2f2"],
  :root[data-theme="auto"] [style*="background:#fee2e2"],
  :root[data-theme="auto"] [style*="background:#fef3c7"],
  :root[data-theme="auto"] [style*="background:#ffebee"]  { background: rgba(239,68,68,.10) !important; color: #fca5a5 !important; }

  :root[data-theme="auto"] [style*="background:#fffbeb"],
  :root[data-theme="auto"] [style*="background:#fff3e0"],
  :root[data-theme="auto"] [style*="background:#fff7ed"]  { background: rgba(245,158,11,.10) !important; }

  :root[data-theme="auto"] [style*="background:#eff6ff"],
  :root[data-theme="auto"] [style*="background:#dbeafe"],
  :root[data-theme="auto"] [style*="background:#e3f2fd"]  { background: rgba(59,130,246,.10) !important; }

  :root[data-theme="auto"] [style*="background:#f0fdf4"],
  :root[data-theme="auto"] [style*="background:#dcfce7"],
  :root[data-theme="auto"] [style*="background:#e8f5e9"],
  :root[data-theme="auto"] [style*="background:#f1f8e9"]  { background: rgba(16,185,129,.10) !important; }

  :root[data-theme="auto"] [style*="linear-gradient(135deg,#fef2f2"],
  :root[data-theme="auto"] [style*="linear-gradient(135deg, #fef2f2"] { background: linear-gradient(135deg, rgba(239,68,68,.12), rgba(239,68,68,.04)) !important; }
  :root[data-theme="auto"] [style*="linear-gradient(135deg,#fffbeb"],
  :root[data-theme="auto"] [style*="linear-gradient(135deg, #fffbeb"] { background: linear-gradient(135deg, rgba(245,158,11,.12), rgba(245,158,11,.04)) !important; }
  :root[data-theme="auto"] [style*="linear-gradient(135deg,#eff6ff"],
  :root[data-theme="auto"] [style*="linear-gradient(135deg, #eff6ff"] { background: linear-gradient(135deg, rgba(59,130,246,.12), rgba(59,130,246,.04)) !important; }
  :root[data-theme="auto"] [style*="linear-gradient(135deg,#f0fdf4"],
  :root[data-theme="auto"] [style*="linear-gradient(135deg, #f0fdf4"] { background: linear-gradient(135deg, rgba(16,185,129,.12), rgba(16,185,129,.04)) !important; }

  :root[data-theme="auto"] [style*="color:#991b1b"],
  :root[data-theme="auto"] [style*="color:#7f1d1d"],
  :root[data-theme="auto"] [style*="color:#b71c1c"],
  :root[data-theme="auto"] [style*="color:#c62828"],
  :root[data-theme="auto"] [style*="color:#dc2626"]       { color: #fca5a5 !important; }
  :root[data-theme="auto"] [style*="color:#9a3412"],
  :root[data-theme="auto"] [style*="color:#92400e"],
  :root[data-theme="auto"] [style*="color:#bf360c"],
  :root[data-theme="auto"] [style*="color:#e65100"]       { color: #fcd34d !important; }
  :root[data-theme="auto"] [style*="color:#0d47a1"],
  :root[data-theme="auto"] [style*="color:#1e40af"],
  :root[data-theme="auto"] [style*="color:#1565c0"]       { color: #93c5fd !important; }
  :root[data-theme="auto"] [style*="color:#166534"],
  :root[data-theme="auto"] [style*="color:#1b5e20"],
  :root[data-theme="auto"] [style*="color:#388e3c"]       { color: #6ee7b7 !important; }
  :root[data-theme="auto"] [style*="color:#374151"]       { color: var(--text) !important; }
}

/* Cards genéricos del panel — page-header, table cells, etc — el resto
   de los estilos ya usan vars; sólo nos quedaba neutralizar los inline. */

/* ─────────────────────────────────────────────────────────────────────────
   Forms — inputs / selects / textareas globales en dark.
   La regla `:root[data-theme="auto"] .form-group input` ya estaba pero
   sólo afecta a campos con la clase form-group. Generalizamos a todos
   los inputs/selects para evitar que aparezcan blancos en cualquier page.
   ─────────────────────────────────────────────────────────────────────── */
:root[data-theme="dark"] input[type="text"],
:root[data-theme="dark"] input[type="search"],
:root[data-theme="dark"] input[type="email"],
:root[data-theme="dark"] input[type="number"],
:root[data-theme="dark"] input[type="date"],
:root[data-theme="dark"] input[type="time"],
:root[data-theme="dark"] input[type="tel"],
:root[data-theme="dark"] input[type="url"],
:root[data-theme="dark"] input[type="password"],
:root[data-theme="dark"] select,
:root[data-theme="dark"] textarea {
    background: #0f172a;
    color: var(--text);
    border-color: var(--border);
}
:root[data-theme="dark"] input::placeholder,
:root[data-theme="dark"] textarea::placeholder { color: var(--muted); opacity: .8; }

@media (prefers-color-scheme: dark) {
  :root[data-theme="auto"] input[type="text"],
  :root[data-theme="auto"] input[type="search"],
  :root[data-theme="auto"] input[type="email"],
  :root[data-theme="auto"] input[type="number"],
  :root[data-theme="auto"] input[type="date"],
  :root[data-theme="auto"] input[type="time"],
  :root[data-theme="auto"] input[type="tel"],
  :root[data-theme="auto"] input[type="url"],
  :root[data-theme="auto"] input[type="password"],
  :root[data-theme="auto"] select,
  :root[data-theme="auto"] textarea {
      background: #0f172a;
      color: var(--text);
      border-color: var(--border);
  }
  :root[data-theme="auto"] input::placeholder,
  :root[data-theme="auto"] textarea::placeholder { color: var(--muted); opacity: .8; }
}

/* ─────────────────────────────────────────────────────────────────────────
   Tablas y links de "subscriptions.php" / "client.php": cliente en
   azul-marino casi invisible, productos en gris oscuro, emails muted
   ilegibles. Subimos los textos hardcoded más comunes en dark.
   ─────────────────────────────────────────────────────────────────────── */
:root[data-theme="dark"] [style*="color:#0f172a"],
:root[data-theme="dark"] [style*="color:#1e293b"],
:root[data-theme="dark"] [style*="color:#334155"],
:root[data-theme="dark"] [style*="color:#475569"]      { color: var(--text) !important; }

/* Links azul oscuro (#1d4ed8, #1e40af, #1565c0) → azul claro legible */
:root[data-theme="dark"] [style*="color:#1d4ed8"],
:root[data-theme="dark"] [style*="color: #1d4ed8"],
:root[data-theme="dark"] [style*="color:#2563eb"]      { color: #93c5fd !important; }

/* Verdes oscuros adicionales */
:root[data-theme="dark"] [style*="color:#0f5132"],
:root[data-theme="dark"] [style*="color:#15803d"]      { color: #6ee7b7 !important; }

@media (prefers-color-scheme: dark) {
  :root[data-theme="auto"] [style*="color:#0f172a"],
  :root[data-theme="auto"] [style*="color:#1e293b"],
  :root[data-theme="auto"] [style*="color:#334155"],
  :root[data-theme="auto"] [style*="color:#475569"]    { color: var(--text) !important; }
  :root[data-theme="auto"] [style*="color:#1d4ed8"],
  :root[data-theme="auto"] [style*="color: #1d4ed8"],
  :root[data-theme="auto"] [style*="color:#2563eb"]    { color: #93c5fd !important; }
  :root[data-theme="auto"] [style*="color:#0f5132"],
  :root[data-theme="auto"] [style*="color:#15803d"]    { color: #6ee7b7 !important; }
}

/* ─────────────────────────────────────────────────────────────────────────
   subscriptions.php — la tabla principal usa clases sub-row, sub-cust,
   sub-product, etc. Las hacemos legibles en dark.
   ─────────────────────────────────────────────────────────────────────── */
:root[data-theme="dark"] .sub-cust,
:root[data-theme="dark"] .sub-product,
:root[data-theme="dark"] .sub-amount,
:root[data-theme="dark"] td.cust,
:root[data-theme="dark"] td.product,
:root[data-theme="dark"] td.amount               { color: var(--text); }
:root[data-theme="dark"] .sub-cust-email,
:root[data-theme="dark"] .sub-product-id,
:root[data-theme="dark"] td.cust-email,
:root[data-theme="dark"] td.product-id           { color: var(--muted); }
@media (prefers-color-scheme: dark) {
  :root[data-theme="auto"] .sub-cust,
  :root[data-theme="auto"] .sub-product,
  :root[data-theme="auto"] .sub-amount,
  :root[data-theme="auto"] td.cust,
  :root[data-theme="auto"] td.product,
  :root[data-theme="auto"] td.amount             { color: var(--text); }
  :root[data-theme="auto"] .sub-cust-email,
  :root[data-theme="auto"] .sub-product-id,
  :root[data-theme="auto"] td.cust-email,
  :root[data-theme="auto"] td.product-id         { color: var(--muted); }
}

/* ─────────────────────────────────────────────────────────────────────────
   Las stat-cards / mini-cards de "Quetebe Fibra" / "Quetebe Ingeniería"
   en subscriptions.php usan gradiente azul-claro hardcoded en su CSS
   (background:#dbeafe, etc.). Ya quedan cubiertos por los overrides
   anteriores [style*="background:#dbeafe"] etc., pero los TÍTULOS
   ("Quetebe Fibra") usan color hardcoded. Subimos:
   ─────────────────────────────────────────────────────────────────────── */
:root[data-theme="dark"] .stripe-account-title,
:root[data-theme="dark"] .acct-title,
:root[data-theme="dark"] .acct-name              { color: var(--text); }

/* ─────────────────────────────────────────────────────────────────────────
   comms.php — las filas de conversaciones (números de teléfono) usan
   color hardcoded oscuro que en dark queda casi invisible. Las clases
   cm-* se hacen text del tema.
   ─────────────────────────────────────────────────────────────────────── */
:root[data-theme="dark"] .cm-conv-name,
:root[data-theme="dark"] .cm-conv-number,
:root[data-theme="dark"] .cm-conv-preview,
:root[data-theme="dark"] .cm-conv-row .name,
:root[data-theme="dark"] .conv-row .name        { color: var(--text); }
:root[data-theme="dark"] .cm-conv-meta,
:root[data-theme="dark"] .cm-conv-time,
:root[data-theme="dark"] .conv-time             { color: var(--muted); }
@media (prefers-color-scheme: dark) {
  :root[data-theme="auto"] .cm-conv-name,
  :root[data-theme="auto"] .cm-conv-number,
  :root[data-theme="auto"] .cm-conv-preview,
  :root[data-theme="auto"] .cm-conv-row .name,
  :root[data-theme="auto"] .conv-row .name      { color: var(--text); }
  :root[data-theme="auto"] .cm-conv-meta,
  :root[data-theme="auto"] .cm-conv-time,
  :root[data-theme="auto"] .conv-time           { color: var(--muted); }
}

/* Skip-link accesible — lo primero en orden de tab. Permite a usuarios
   con teclado saltar directo al contenido sin pasar por toda la sidebar. */
.skip-link {
  position: absolute;
  top: -40px;
  left: 8px;
  background: #1d4ed8;
  color: #fff;
  padding: 8px 16px;
  border-radius: 6px;
  text-decoration: none;
  font-size: 14px;
  font-weight: 600;
  z-index: 9999;
  transition: top .12s;
}
.skip-link:focus {
  top: 8px;
}

/* Touch targets mínimos 44x44 en móvil (WCAG 2.5.5) */
@media (max-width: 640px) {
  button, .btn, .btn-primary, .btn-plain, .btn-inline,
  a.btn, a.btn-primary, a.btn-plain, a.btn-inline,
  .tab-btn, .lang-tab {
    min-height: 40px;
    min-width: 40px;
  }
  input[type="checkbox"], input[type="radio"] {
    min-width: 20px;
    min-height: 20px;
  }
}

/* ═════════════════════════════════════════════════════════════════════════
   Breadcrumbs: barra de navegación de profundidad.
   Uniforme en todas las páginas de detalle. Muestra dónde estás y cómo
   volver a cualquier nivel superior con un clic.
   ═════════════════════════════════════════════════════════════════════════ */
.qtb-breadcrumbs {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin: 0 0 16px;
  padding: 10px 14px;
  /* Antes era #fff hardcodeado → en dark quedaba como una banda blanca
     muy molesta dentro de la página oscura. Ahora respeta el surface
     del tema (light: blanco, dark: #1a1f2e). */
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  font-size: 12px;
  color: var(--muted);
  box-shadow: 0 1px 2px rgba(15,23,42,.03);
}
.qtb-bc-back {
  background: none;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 4px 10px;
  font-size: 12px;
  color: var(--text);
  cursor: pointer;
  transition: background .12s, border-color .12s;
  font-weight: 500;
  flex-shrink: 0;
}
/* Hover usa rgba en vez de un gris fijo, para que también se vea bien
   sobre fondo oscuro. */
.qtb-bc-back:hover { background: rgba(148,163,184,.12); border-color: #94a3b8; }
.qtb-bc-list {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
  list-style: none;
  margin: 0;
  padding: 0;
  flex: 1;
  min-width: 0;
}
.qtb-bc-item {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
  max-width: 100%;
}
.qtb-bc-link {
  color: #1d4ed8;
  text-decoration: none;
  font-weight: 500;
  padding: 2px 6px;
  border-radius: 4px;
  transition: background .12s;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
  max-width: 40ch;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Hover/sep en rgba para no chocar con dark. */
.qtb-bc-link:hover { background: rgba(29,78,216,.10); text-decoration: underline; }
.qtb-bc-sep {
  color: #94a3b8;
  font-weight: 400;
  user-select: none;
  margin: 0 2px;
}

/* Overrides explícitos en dark — los links azul oscuro casi se pierden
   contra #1a1f2e. Usamos un azul más claro y sin tintes de hover heavy. */
:root[data-theme="dark"] .qtb-bc-link        { color: #93c5fd; }
:root[data-theme="dark"] .qtb-bc-link:hover  { background: rgba(147,197,253,.12); }
:root[data-theme="dark"] .qtb-bc-sep         { color: #64748b; }
@media (prefers-color-scheme: dark) {
  :root[data-theme="auto"] .qtb-bc-link       { color: #93c5fd; }
  :root[data-theme="auto"] .qtb-bc-link:hover { background: rgba(147,197,253,.12); }
  :root[data-theme="auto"] .qtb-bc-sep        { color: #64748b; }
}
.qtb-bc-active {
  color: var(--text);
  font-weight: 600;
  padding: 2px 6px;
  white-space: nowrap;
  max-width: 50ch;
  overflow: hidden;
  text-overflow: ellipsis;
}
.qtb-bc-icon { font-size: 13px; }

@media (max-width: 640px) {
  .qtb-breadcrumbs { padding: 8px 10px; gap: 8px; }
  .qtb-bc-link { max-width: 22ch; }
  .qtb-bc-active { max-width: 30ch; }
}

/* ═════════════════════════════════════════════════════════════════════════
   Loading skeletons — barras grises animadas para "cargando..."
   Uso: <div class="qtb-skeleton" style="height:20px;width:60%"></div>
   El shimmer da sensación de progreso sin spinners ruidosos.
   ═════════════════════════════════════════════════════════════════════════ */
.qtb-skeleton {
  background: linear-gradient(90deg, #e2e8f0 0%, #f1f5f9 50%, #e2e8f0 100%);
  background-size: 200% 100%;
  animation: qtbShimmer 1.4s ease-in-out infinite;
  border-radius: 6px;
  display: block;
  height: 16px;
}
.qtb-skeleton + .qtb-skeleton { margin-top: 8px; }
@keyframes qtbShimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
/* Variantes rápidas */
.qtb-skeleton-row { display: flex; gap: 12px; align-items: center; padding: 10px 0; }
.qtb-skeleton-row .qtb-skeleton { margin: 0; }

/* ═════════════════════════════════════════════════════════════════════════
   Empty states — mostrar claramente cuando no hay datos, con CTA.
   Uso:
     <div class="qtb-empty">
       <div class="qtb-empty-ico">📭</div>
       <div class="qtb-empty-title">Sin tareas todavía</div>
       <div class="qtb-empty-hint">Cuando haya tareas pendientes aparecerán aquí.</div>
       <button class="btn-primary">+ Crear tarea</button>
     </div>
   ═════════════════════════════════════════════════════════════════════════ */
.qtb-empty {
  text-align: center;
  padding: 40px 20px;
  background: #fafafa;
  border: 1px dashed var(--border);
  border-radius: 12px;
  color: var(--muted);
}
.qtb-empty-ico {
  font-size: 40px;
  margin-bottom: 8px;
  opacity: 0.7;
}
.qtb-empty-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 4px;
}
.qtb-empty-hint {
  font-size: 13px;
  color: var(--muted);
  max-width: 400px;
  margin: 0 auto 14px;
  line-height: 1.4;
}
.qtb-empty .btn,
.qtb-empty .btn-primary,
.qtb-empty .btn-plain {
  margin-top: 4px;
}

/* ═════════════════════════════════════════════════════════════════════════
   Modales: scroll global para que nunca se corte el contenido.
   Las páginas definen sus propios .modal-back / .modal en <style> inline,
   pero estas reglas se aplican después y con !important para garantizar
   el comportamiento consistente en todo el panel.
   ═════════════════════════════════════════════════════════════════════════ */

/* Backdrop que permite scroll cuando el modal es más alto que la ventana.
   align-items: flex-start + margin:auto en el modal hace que esté
   centrado verticalmente si cabe, y pegado arriba cuando no cabe (para
   que el scroll funcione correctamente empezando por el principio). */
.modal-back[data-open="1"] {
  align-items: flex-start !important;
  overflow-y: auto !important;
  padding: 24px 16px !important;
}

/* El modal en sí: altura máxima razonable y scroll interno como fallback,
   aunque el scroll principal sucede en el backdrop. margin:auto centra
   cuando hay espacio. */
.modal-back[data-open="1"] > .modal,
.modal-back[data-open="1"] > div.modal {
  margin: auto !important;
  max-height: none !important;
}

/* Tablet/móvil: padding menor y ancho más generoso. */
@media (max-width: 640px) {
  .modal-back[data-open="1"] {
    padding: 12px 8px !important;
  }
}

/* ─── stel-picker (combobox con búsqueda async sobre STEL) ────────────── */
.stel-picker-root { position: relative; }
/* Cuando el dropdown está abierto, el host se eleva por encima de los
   siguientes hermanos (otros pickers o cells del form-grid) para que
   los items que caen fuera del cell sean clicables. */
.stel-picker-root.stel-picker-open { z-index: 200; }
.stel-picker-wrap { position: relative; }
.stel-picker-input {
  width: 100%;
  padding: 7px 28px 7px 9px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
  font-size: 13px;
}
.stel-picker-input:focus { outline: 2px solid #93c5fd; outline-offset: -2px; }
.stel-picker-clear {
  position: absolute;
  right: 6px; top: 50%; transform: translateY(-50%);
  background: transparent;
  border: 0;
  color: var(--muted);
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  padding: 2px 6px;
}
.stel-picker-clear:hover { color: #dc2626; }
.stel-picker-list {
  /* El JS la coloca con position: fixed + coords calculadas para
     escapar overflows y stacking contexts. Aquí solo el aspecto. */
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0,0,0,.18);
  max-height: 280px;
  overflow-y: auto;
  display: none;
}
.stel-picker-list.show { display: block; }
.stel-picker-row {
  padding: 7px 10px;
  cursor: pointer;
  border-bottom: 1px solid var(--border);
}
.stel-picker-row:last-child { border-bottom: 0; }
.stel-picker-row.active,
.stel-picker-row:hover { background: var(--bg-soft); }
.stel-picker-label { font-size: 13px; color: var(--text); font-weight: 500; }
.stel-picker-sub   { font-size: 11px; color: var(--muted); margin-top: 2px; }
.stel-picker-empty { padding: 10px; color: var(--muted); font-size: 12px; font-style: italic; text-align: center; }
.stel-picker-err   { color: #dc2626; }

/* ── SIDEBAR COLAPSABLE ──────────────────────────────────────────────
   Toggle global: añade clase .sidebar-collapsed al <div class="layout">
   y el sidebar pasa de 230px a 60px. Items: solo iconos, label oculto,
   tooltip al hover. Persistido en localStorage("panel.sidebar.collapsed"). */
.layout.sidebar-collapsed { --sidebar-w: 60px; }
/* Garantía: cuando el sidebar está colapsado, .main aprovecha TODO el
   ancho liberado, indeoendientemente de si lleva clase main-fluid o no.
   Esto cubre el caso de pantallas que aún tienen el max-width antiguo. */
.layout.sidebar-collapsed .main {
  max-width: none !important;
  margin-left: 0 !important;
  padding-left: 0 !important;
}
.layout.sidebar-collapsed .sidebar {
  flex: 0 0 var(--sidebar-w);
}

/* Wrapper del logo + botón toggle: el logo ya no es el ÚNICO clickable.
   El botón toggle vive al lado, fuera del <a>, así puede capturar su
   propio click sin que el navegador siga el href del logo a Dashboard. */
.sidebar-logo-row {
  display: flex; align-items: center;
  border-bottom: 1px solid rgba(255,255,255,.07);
  padding: 6px 12px;
  gap: 8px;
}
.sidebar-logo-row .sidebar-logo {
  flex: 1; padding: 14px 4px; border-bottom: 0;
  display: flex; align-items: center; gap: 11px;
  text-decoration: none; min-width: 0;
}
.layout.sidebar-collapsed .sidebar-logo-row {
  flex-direction: column; gap: 4px; padding: 8px 4px;
}
.layout.sidebar-collapsed .sidebar-logo-row .sidebar-logo {
  display: none;  /* en colapsado solo dejamos el botón */
}
.layout.sidebar-collapsed .sidebar-logo-name,
.layout.sidebar-collapsed .sidebar-logo-sub,
.layout.sidebar-collapsed .nav-item span:not(.nav-badge),
.layout.sidebar-collapsed .sidebar-footer .role-pill,
.layout.sidebar-collapsed .sidebar-footer .username,
.layout.sidebar-collapsed .sidebar-footer .footer-actions { display: none !important; }

/* Theme toggle (claro/oscuro/auto) en sidebar colapsado: los 3 botones
   no caben horizontalmente en 60px. Los apilamos verticalmente y
   reducimos su tamaño para que respiren bien dentro del pill. */
.layout.sidebar-collapsed .sidebar-footer { padding: 8px 4px; }
.layout.sidebar-collapsed .sidebar-footer .theme-toggle {
  flex-direction: column;
  gap: 1px;
  padding: 2px;
  margin: 0 auto;
  align-self: center;
}
.layout.sidebar-collapsed .sidebar-footer .theme-toggle button {
  width: 28px;
  height: 24px;
  font-size: 11px;
}
/* User pill (avatar AT) en colapsado: solo el círculo, sin texto. */
.layout.sidebar-collapsed .user-pill {
  padding: 4px;
  justify-content: center;
}
.layout.sidebar-collapsed .user-pill-name,
.layout.sidebar-collapsed .user-pill-caret { display: none !important; }
.layout.sidebar-collapsed .user-pill-avatar { margin: 0 auto; }

/* Wrapper alrededor de cada (nav-item + su nav-sub) — sirve de ancla
   de positioning para el flyout. */
.nav-item-wrap { position: relative; }

/* En colapsado, el submenú con clase .open (item activo) NO debe expandirse
   abajo como en modo expandido — sería ilegible en 60px. Sólo aparece
   como flyout al hover sobre el item padre. */
.layout.sidebar-collapsed .nav-sub {
  display: none;
  margin: 0 !important;
  padding: 0 !important;
  border-left: 0 !important;
}
.layout.sidebar-collapsed .nav-item-wrap.has-sub:hover .nav-sub,
.layout.sidebar-collapsed .nav-item-wrap.has-sub .nav-sub:hover,
.layout.sidebar-collapsed .nav-item-wrap.has-sub:focus-within .nav-sub {
  display: flex !important;
  flex-direction: column;
  position: absolute;
  /* Pegado al rail: lo solapamos ligeramente para que no exista una
     "grieta" al mover el ratón hacia la derecha. */
  left: calc(100% - 8px);
  top: 0;
  background: #1a1a2e;
  border: 1px solid rgba(255,255,255,.10);
  border-radius: 8px;
  padding: 6px 0;
  min-width: 200px;
  box-shadow: 0 8px 22px rgba(0,0,0,.35);
  z-index: 1100;
}
.layout.sidebar-collapsed .nav-item-wrap.has-sub:hover::after,
.layout.sidebar-collapsed .nav-item-wrap.has-sub:focus-within::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: 100%;
  width: 16px;
}
.layout.sidebar-collapsed .nav-sub::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: -12px;
  width: 12px;
}
.layout.sidebar-collapsed .nav-sub a {
  padding: 7px 14px;
  color: rgba(255,255,255,.78);
  text-decoration: none;
  font-size: 12.5px;
  white-space: nowrap;
  display: block;
}
.layout.sidebar-collapsed .nav-sub a:hover { background: rgba(255,255,255,.08); color: #fff; }
.layout.sidebar-collapsed .nav-sub a.active { color: var(--sidebar-active); }
/* Tooltip data-label NO se muestra cuando el item tiene sub-menú: usamos
   el flyout en su lugar. */
.layout.sidebar-collapsed .nav-item.has-children[data-label]:hover::after { display: none; }
.layout.sidebar-collapsed .sidebar-logo { padding: 18px 0; justify-content: center; }
.layout.sidebar-collapsed .sidebar-logo-img { margin: 0 auto; }
.layout.sidebar-collapsed .nav-item {
  justify-content: center;
  padding: 10px 0;
  position: relative;
}
.layout.sidebar-collapsed .nav-item .nav-badge {
  position: absolute;
  top: 4px; right: 8px;
  font-size: 9px;
  padding: 0 4px;
  min-width: 14px; height: 14px; line-height: 14px;
  border-radius: 999px;
}
/* Tooltip al hover en colapsado */
.layout.sidebar-collapsed .nav-item[data-label]:hover::after {
  content: attr(data-label);
  position: absolute;
  left: 100%; top: 50%;
  transform: translateY(-50%);
  margin-left: 6px;
  background: #1a1a2e;
  color: #f1f5f9;
  padding: 4px 9px;
  border-radius: 6px;
  font-size: 12px;
  white-space: nowrap;
  z-index: 1000;
  box-shadow: 0 2px 8px rgba(0,0,0,.3);
  pointer-events: none;
}
/* Botón toggle. Va al lado del logo. */
.sidebar-collapse-toggle {
  background: transparent;
  border: 1px solid rgba(255,255,255,.10);
  border-radius: 6px;
  color: rgba(255,255,255,.55);
  cursor: pointer;
  padding: 4px 6px;
  font-size: 14px;
  margin-left: auto;
  display: flex; align-items: center; justify-content: center;
  width: 28px; height: 28px;
  flex-shrink: 0;
  transition: background .12s ease, color .12s ease;
}
.sidebar-collapse-toggle:hover { background: rgba(255,255,255,.08); color: #fff; }
.sidebar-collapse-toggle svg { transition: transform .18s ease; }
.layout.sidebar-collapsed .sidebar-collapse-toggle { margin: 0 auto; }
/* Cuando el sidebar está colapsado, la flecha apunta hacia FUERA
   (derecha) — porque pulsando expandes. Cuando está expandido, la
   flecha apunta hacia DENTRO (izquierda) — porque pulsando colapsas.
   El SVG base (polylines hacia la izquierda) se queda como está
   en estado expandido y se rota 180° en colapsado. */
.layout.sidebar-collapsed .sidebar-collapse-toggle svg { transform: rotate(180deg); }

/* ── Campanita de notificaciones del sistema ─────────────────────────────── */
.sidebar-notif-bell {
  background: transparent;
  border: 1px solid rgba(255,255,255,.10);
  border-radius: 6px;
  color: rgba(255,255,255,.55);
  cursor: pointer;
  padding: 4px 6px;
  display: flex; align-items: center; justify-content: center;
  width: 28px; height: 28px;
  flex-shrink: 0;
  position: relative;
  transition: background .12s ease, color .12s ease;
}
.sidebar-notif-bell:hover {
  background: rgba(255,255,255,.08);
  color: #fff;
}
/* Punto rojo cuando hay alertas */
.sidebar-notif-bell .notif-dot {
  position: absolute;
  top: 4px; right: 4px;
  width: 7px; height: 7px;
  background: #ef4444;
  border-radius: 50%;
  border: 1.5px solid #1a1a2e;
  animation: notif-pulse 1.8s ease-in-out infinite;
}
/* Estado snoozeado: dot atenuado, sin pulsar */
.sidebar-notif-bell.snoozed .notif-dot {
  background: rgba(239,68,68,.45);
  animation: none;
}
@keyframes notif-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%       { opacity: .6; transform: scale(1.2); }
}
/* En colapsado, ocultar la campanita */
.layout.sidebar-collapsed .sidebar-notif-bell { display: none; }

/* ── Panel desplegable de avisos ─────────────────────────────────────────── */
.notif-panel {
  position: absolute;
  top: 54px; left: 12px;
  width: 300px;
  background: #1a1a2e;
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 10px;
  box-shadow: 0 8px 28px rgba(0,0,0,.45);
  z-index: 1200;
  font-size: 13px;
  color: #e2e8f0;
  overflow: hidden;
}
.notif-header {
  display: flex; align-items: center;
  padding: 10px 14px;
  border-bottom: 1px solid rgba(255,255,255,.08);
  gap: 8px;
}
.notif-header strong { flex: 1; font-size: 13px; }
.notif-close {
  background: transparent; border: none; cursor: pointer;
  color: rgba(255,255,255,.5); font-size: 18px; line-height: 1;
  padding: 0 2px;
  transition: color .12s;
}
.notif-close:hover { color: #fff; }
.notif-empty {
  padding: 14px;
  color: rgba(255,255,255,.5);
  font-size: 12.5px;
  text-align: center;
}
.notif-list { max-height: 280px; overflow-y: auto; }
.notif-row {
  padding: 10px 14px;
  border-bottom: 1px solid rgba(255,255,255,.06);
}
.notif-row:last-child { border-bottom: 0; }
.notif-row-title { font-weight: 600; font-size: 12.5px; margin-bottom: 3px; }
.notif-row-detail { font-size: 11.5px; color: rgba(255,255,255,.6); line-height: 1.45; }
.notif-row-link { display: inline-block; margin-top: 5px; font-size: 11.5px; color: #60a5fa; text-decoration: none; }
.notif-row-link:hover { text-decoration: underline; }
/* Colores por severidad */
.notif-critical .notif-row-title { color: #fca5a5; }
.notif-warning  .notif-row-title { color: #fcd34d; }
.notif-footer {
  padding: 8px 14px;
  border-top: 1px solid rgba(255,255,255,.08);
}
.notif-snooze {
  width: 100%; background: rgba(255,255,255,.07); border: 1px solid rgba(255,255,255,.12);
  border-radius: 6px; color: rgba(255,255,255,.7); font-size: 12px;
  padding: 6px 10px; cursor: pointer; transition: background .12s;
}
.notif-snooze:hover { background: rgba(255,255,255,.13); color: #fff; }

/* ═════════════════════════════════════════════════════════════════════════
   Z-INDEX DE MODALES (fix panel-wide, P239).
   La barra superior / sidebar sticky y el chrome de navegación viven en
   z 1000–1200. Los overlays de modal estaban en z-200, así que la barra
   "se quedaba pegada arriba" tapando la cabecera del modal en TODAS las
   pantallas. Elevamos ambos convenios de modal por encima de ese chrome
   (y por debajo del skip-link 9999). Solo sube z-index: no cambia layout.
   ═════════════════════════════════════════════════════════════════════════ */
.qz-modal-back, .qz-modal-back.open,
.modal-back, .modal-back[data-open="1"] {
  z-index: 1500 !important;
}

/* ── Visualización móvil (Fase 1): utilidades anti-desborde ──────────
   Contenedor con scroll interno para tablas anchas: el scroll DENTRO de
   una card/sección es aceptable; el del body (o el pan de .main) no. */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%; }
.table-scroll > table { min-width: 100%; }

/* ── Fase 1 (P4xx visualización): tablas de listado y controles que
   desbordaban el viewport en móvil/tablet (barrido tools/visual_sweep).
   Regla de oro: con el zoom bloqueado NADA puede quedar cortado — las
   tablas anchas pasan a scroll INTERNO (display:block+overflow) y los
   controles rígidos ceden. Scope ≤1024px para no alterar escritorio. */
@media (max-width: 1024px) {
  table[id^="qtf_"], table.sub-table, table.pa-table, table.cdrs, table.pap,
  table.ti-t, table.u-table, table.cl-t, table.bill-table, table.prod-table,
  table.qz-t, table.vr-table, table.log-tbl, table.gsc-t, table.ag-list,
  table#items-table, table#creds-table, table#rules-table, table#tbl-edit-q,
  table.qz-lines-table, /* tanda 2: líneas del editor de pedidos/partes (7 col fijas ≈650px) */
  #benefits-panel .card > table {
    display: block;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    max-width: 100%;
  }
  /* Controles de formulario nunca más anchos que su contenedor (selects con
     opciones kilométricas, inputs file…). box-sizing global = border-box. */
  select, input, textarea { max-width: 100%; }
  /* Filas de controles que no cabían en una línea */
  .dc-controls { flex-wrap: wrap; }
}
@media (max-width: 640px) {
  /* Ficha de perfil: etiqueta encima del campo en pantallas estrechas */
  .pf-row-2 { grid-template-columns: 1fr; }
}
/* Tanda 2 del barrido: casos residuales */
@media (max-width: 1024px) {
  /* fieldset no encoge por defecto (min-width:min-content) — growth y formularios */
  fieldset { min-width: 0; }
  /* tablas dentro de las cards del panel de uso IA */
  .ai-grid table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%; }
  /* Cabeceras de drawer (catálogo de presupuestos, wizard AC…): el input
     flex:1 no encogía (min-width:auto) y el select con opciones largas
     asomaba +30px fuera del cajón (barrido interactivo tanda 2). */
  .qz-drawer-h input, .qz-drawer-h select { min-width: 0; }
}
@media (max-width: 640px) {
  .ai-grid, .gbp-grid { grid-template-columns: minmax(0,1fr) !important; }
}

/* ═════════════════════════════════════════════════════════════════════════
   TANDA 2 (P4xx visualización) — TAP TARGETS ≥40px EN TÁCTIL.
   Censo del barrido (tools/visual_sweep, m390): 8.734 objetivos <40px en
   134 páginas; ~80% eran componentes COMPARTIDOS. Estrategia central aquí
   + remates por página. Dos patrones:
     (a) crecer de verdad (min-height) donde el diseño lo tolera;
     (b) expandir el área táctil SIN mover el diseño: padding + margen
         negativo equivalente — el line box no crece, el hit box sí
         (los toques en la zona expandida caen en el enlace; donde pisa
         al vecino gana el que está debajo del dedo, como siempre).
   Escritorio intacto: todo va en media query.
   ═════════════════════════════════════════════════════════════════════════ */
@media (max-width: 900px) {
  /* Sidebar en modo drawer (breakpoint 900 del propio drawer): alturas
     táctiles. Mayor ofensor del censo: ~62 enlaces <40px POR PÁGINA
     (50 sub-items de 29px + 12 items de 39px). El drawer scrollea:
     crecer aquí es gratis. */
  .nav-item { min-height: 44px; }
  .nav-sub { gap: 0; }
  .nav-sub-item { display: flex; align-items: center; min-height: 40px; }
  .theme-toggle button { width: 40px; height: 40px; }
}
@media (max-width: 1024px) {
  /* Botones y selects compartidos (filtros de cabecera qtf_*, barras de
     herramientas, .qz-sel/.kb-sel/.wa-tab…). El button≥40 global de ≤640
     ya existía; esto cubre también tablet. */
  .btn, .btn-sm { min-height: 40px; }
  input[type="submit"], input[type="button"] { min-height: 40px; }
  select { min-height: 40px; }
  /* Pestañas y subnavegaciones compartidas entre módulos */
  .tab { display: inline-flex; align-items: center; min-height: 40px; }
  .sat-subnav-tab { min-height: 40px; }
  .settings-strip-link { min-height: 40px; }
  /* Familias de pestañas-píldora de página (SAT, presupuestos de trabajo,
     catálogo por marca): mismo mínimo táctil. */
  .qz-tab, .wq-tab, .brand-tab { display: inline-flex; align-items: center; min-height: 40px; }
  /* Breadcrumbs: botón Atrás y migas tocables */
  .qtb-bc-back, .qtb-bc-link { min-height: 40px; }
  /* Enlaces de celda en listados (refs, clientes, teléfonos): patrón (b) —
     en un elemento inline el padding vertical NO mueve el layout (manda el
     line-height) pero SÍ amplía la caja de toque: de ~15px a ≥41px de alto.
     En horizontal, padding + margen negativo IGUAL = mismo sitio, +18px de
     ancho táctil (iconitos y refs cortas). Los pocos block/inline-block
     quedan compensados por los margenes. Se excluyen los que tienen fondo
     visible (botones/chips/badges). */
  td a:not([class*="btn"]):not([class*="chip"]):not([class*="badge"]):not([class*="tag"]) {
    padding: 13px 9px;
    margin: -13px -9px;
  }
  /* Cabeceras ordenables de las tablas qtf: 35px → ≥41px de alto (y ancho:
     la col "#" rondaba 39.6px). Con .layout delante para ganar el empate de
     especificidad contra `.layout .table thead th` de theme-2026.css (que
     carga después y reponía padding 9px 14px). */
  .layout table[id^="qtf_"] th.qtf-sortable,
  table[id^="qtf_"] th.qtf-sortable { padding: 12px 15px; }
  /* El skip-link (solo teclado) crece con el resto de <a>: se esconde más
     arriba para que no asome un borde por la parte superior. */
  .skip-link { top: -72px; padding: 12px 16px; }
}
