/* Shell, topbar, menú de usuario y sidebar — rediseño "Brix" */

/* Estructura de 3 capas (ver diagrama de referencia):
   Capa 1 — fondo del sistema/ventana: .app-shell, gris (--color-bg-page),
     de borde a borde — tiene que notarse como margen alrededor de la Capa 2.
   Capa 2 — marco general: .body-layout, un único contenedor continuo,
     blanco, que incluye tanto la sidebar como el fondo detrás del panel —
     por eso la sidebar NO tiene su propio fondo/radio/sombra, vive dentro
     de esta misma capa. Inset 24px de la Capa 1 en los 4 lados.
   Capa 3 — panel de contenido: .main-content, gris un poco más marcado
     que la Capa 1, inset 24px de la Capa 2 arriba/derecha/abajo, pero
     contiguo a la sidebar a la izquierda (sin separación extra ahí). */
.app-shell {
  height: 100vh;
  /* Color sólido de respaldo (mientras carga la imagen o si falla) +
     imagen decorativa de fondo. background-attachment:fixed para que
     quede anclada a la ventana y no se mueva con el scroll interno del
     panel; background-size:cover + position:center para que las esferas
     de las esquinas no se pierdan en ningún ancho soportado. */
  background-color: var(--app-shell-bg-color);
  background-image: var(--app-shell-bg-image);
  background-size: cover;
  background-position: center;
  background-attachment: fixed;
  /* El margen real entre la Capa 1 y la Capa 2 va acá: antes .body-layout
     no tenía margin propio, solo padding INTERNO (el espacio entre su
     propio borde y el sidebar/contenido) — el gris de la Capa 1 apenas se
     asomaba en las 4 esquinas redondeadas, nunca como franja completa.
     Usa --shell-outer-inset (más grande que --shell-inset) para que la
     Capa 1 tenga presencia clara alrededor del marco. */
  padding: var(--shell-outer-inset);
}

.body-layout {
  display: flex;
  gap: 0;
  height: 100%;
  overflow: hidden;
  position: relative;
  padding: var(--shell-inset);
  /* Color de respaldo (mientras carga la imagen o si falla) + imagen de
     vidrio esmerilado detrás de sidebar + panel de contenido. La imagen
     es full-bleed (sin esquinas ni márgenes propios), así que el radio y
     la sombra del marco los sigue dando el resto de esta regla. */
  background-color: var(--panel-frame-bg-color);
  background-image: var(--panel-frame-bg-image);
  background-size: cover;
  background-position: center;
  border-radius: var(--radius-shell);
  /* Con la Capa 1 ahora ilustrada (en vez de un gris liso), este marco
     necesita su propio levante para no perder la separación de capas
     contra un fondo con tanto detalle. El halo inset (--layer-seam-glow)
     suaviza el salto de color donde termina la imagen de la Capa 1 y
     empieza la de este marco. */
  box-shadow: var(--shadow-raised), var(--layer-seam-glow);
}

/* El scroll real vive en .main-content-scroll (hijo absoluto) para que el
   scrollbar recto no corte las esquinas redondeadas de este panel.
   Fondo de Capa 3 (imagen clara + respaldo sólido) — va detrás de las
   cards, que siguen siendo blanco sólido (--color-bg-surface). */
.main-content {
  flex: 1;
  min-width: 0;
  position: relative;
  overflow: hidden;
  margin: var(--shell-inset) var(--shell-inset) var(--shell-inset) 0;
  background-color: var(--content-bg-color);
  background-image: var(--content-bg-image);
  background-size: cover;
  background-position: center;
  border-radius: var(--radius-panel);
  /* Mismo criterio que el marco: suaviza el salto de color con la imagen
     de la Capa 2 justo detrás. */
  box-shadow: var(--layer-seam-glow);
}

.main-content-scroll {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  /* Nunca scroll horizontal a este nivel: los elementos que de verdad
     necesitan desbordar de lado (tablas anchas, etc.) llevan su propio
     contenedor con overflow-x:auto (ver .table-scroll) — cualquier otro
     desborde acá es un bug de layout, no algo que haya que scrollear. */
  overflow-x: hidden;
  padding: var(--content-pad-top) var(--content-pad-x) var(--space-8);
}

/* Scrollbar propia, fina y discreta en vez de la nativa (gruesa, sin
   redondear). */
.main-content-scroll {
  scrollbar-width: thin;
  scrollbar-color: var(--color-border) transparent;
}

.main-content-scroll::-webkit-scrollbar {
  width: 8px;
}

.main-content-scroll::-webkit-scrollbar-track {
  background: transparent;
}

.main-content-scroll::-webkit-scrollbar-thumb {
  background: var(--color-border);
  border-radius: var(--radius-full);
}

.main-content-scroll::-webkit-scrollbar-thumb:hover {
  background: var(--color-text-muted);
}

/* ═══════════════════════════════════════════════════════
   Topbar — fila superior: saludo a la izquierda, acciones
   a la derecha (campana + CTA primario + menú de usuario).
   Transparente, sin barra sólida — todo flota sobre el lienzo.
   ═══════════════════════════════════════════════════════ */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  margin-bottom: var(--space-8);
  flex-wrap: wrap;
}

/* Especificidad extra (.surface > .topbar, no solo .topbar) a propósito:
   components.css define ".surface > * { position: relative; z-index: 1; }"
   con la misma especificidad de clase — sin este selector más específico,
   ese z-index:1 le gana por orden de cascada (components.css carga después
   de layout.css) y los menús desplegables de la topbar (buscador/campana/
   usuario) quedan tapados por las cards de contenido de más abajo. */
.surface > .topbar {
  position: relative;
  z-index: 30;
}

.topbar-greeting { min-width: 0; }

.topbar-greeting h1 {
  margin: 0;
  font-family: var(--font-family-heading);
  font-size: 32px;
  font-weight: var(--weight-bold);
  color: var(--color-text-heading);
  letter-spacing: -0.5px;
  line-height: 1.3;
}

.topbar-greeting p {
  margin: 6px 0 0;
  font-size: 14px;
  font-weight: var(--weight-regular);
  color: #9CA3AF;
  line-height: 1.5;
}

/* Topbar en 2 filas: arriba buscador + notificaciones + tema + usuario
   (alineados a la derecha, con más aire entre sí); abajo título+subtítulo
   a la izquierda y la acción principal + refresh a la derecha. Misma
   estructura en las 6 secciones del sidebar. */
.topbar--split {
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
}

.topbar-row {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  flex-wrap: wrap;
}

/* El buscador queda a la izquierda (justo arriba del título de la fila
   de abajo) y notificaciones+tema+usuario agrupados a la derecha en
   .topbar-icons — no todo junto contra el borde derecho. */
/* nowrap: con flex-wrap:wrap (heredado de .topbar-row) el buscador y el
   grupo de íconos "envolvían" a una línea fantasma vacía antes de la
   línea real con contenido — el row terminaba midiendo bastante más
   alto que sus dos hijos sin que se viera nada distinto. Acá los dos
   siempre entran en una sola línea (los breakpoints angostos ya
   colapsan el buscador/la topbar por su cuenta), así que no hace falta
   permitir el wrap. */
.topbar-row--top { justify-content: space-between; flex-wrap: nowrap; }
.topbar-icons {
  display: flex;
  align-items: center;
  gap: var(--topbar-actions-gap);
}

/* Fila de arriba (buscador + notificaciones + tema + usuario) más baja —
   con los botones-ícono a su tamaño de siempre (42px) la topbar de 2
   filas quedaba con demasiado alto muerto arriba del título. */
.topbar-icons .icon-btn-round,
.topbar-icons > .theme-toggle { width: 38px; height: 38px; }
.topbar-icons .user-menu .avatar { width: 30px; height: 30px; }
.topbar-row--bottom { justify-content: space-between; }

.topbar-row-actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-shrink: 0;
}

.topbar-actions {
  display: flex;
  align-items: center;
  gap: var(--topbar-actions-gap);
  flex-shrink: 0;
  flex-wrap: wrap;
  justify-content: flex-end;
  row-gap: var(--space-3);
}
.topbar .btn-primary { white-space: nowrap; }
.topbar .user-menu-name,
.topbar .user-menu-role { white-space: nowrap; }

/* Botón-ícono circular (campana de notificaciones) */
.icon-btn-round {
  width: 42px;
  height: 42px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  background: var(--color-bg-surface);
  color: var(--color-text-secondary);
  cursor: pointer;
  box-shadow: var(--shadow-card);
  transition: background 0.15s, color 0.15s, transform 0.15s var(--ease-out), box-shadow 0.15s;
}

.icon-btn-round:hover {
  color: var(--color-primary);
  transform: translateY(-1px);
  box-shadow: var(--shadow-float);
}
.icon-btn-round:active { transform: scale(0.95); }
.icon-btn-round svg { width: 19px; height: 19px; }

/* ── Menú de usuario ──────────────────────────────────── */
/* Modo flotante (páginas que todavía no migraron): arriba a la derecha */
.user-menu {
  position: absolute;
  top: 26px;
  right: 40px;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 6px 5px var(--space-4);
  background: var(--color-bg-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  box-shadow: var(--shadow-card);
}

/* Modo integrado en la topbar */
.topbar .user-menu {
  position: static;
  top: auto;
  right: auto;
}

.user-menu .avatar {
  width: 32px;
  height: 32px;
  font-size: var(--text-sm);
}

.user-menu .user-menu-logout {
  width: 28px;
  height: 28px;
  color: var(--color-text-muted);
}

.user-menu .user-menu-logout svg { width: 16px; height: 16px; }

@media (max-width: 640px) {
  .user-menu { top: var(--space-4); right: var(--space-5); padding: 5px; }
  .user-menu-info { display: none; }
}

.user-menu-info {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: var(--leading-tight);
}

.user-menu-name {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-text-primary);
}

.user-menu-role {
  font-size: var(--text-xs);
  color: var(--color-text-secondary);
  text-transform: capitalize;
}

.avatar {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-full);
  background: var(--gradient-primary);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  flex-shrink: 0;
  box-shadow: var(--glow-primary);
}

.user-menu-logout {
  width: 32px;
  height: 32px;
  border: none;
  background: transparent;
  border-radius: var(--radius-full);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-text-secondary);
  cursor: pointer;
  transition: background 0.15s, color 0.15s, transform 0.15s var(--ease-out);
}

.user-menu-logout:hover {
  background: var(--color-danger-bg);
  color: var(--color-danger);
  transform: scale(1.08);
}
.user-menu-logout:active { transform: scale(0.94); }

/* ── Toggle de modo oscuro/claro — mismo look que el botón de logout ── */
.theme-toggle {
  position: relative;
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  border: none;
  background: transparent;
  border-radius: var(--radius-full);
  color: var(--color-text-secondary);
  cursor: pointer;
  transition: background 0.15s, color 0.15s, transform 0.15s var(--ease-out);
}
.theme-toggle:hover { background: var(--color-primary-bg); color: var(--color-primary); transform: scale(1.08); }
.theme-toggle:active { transform: scale(0.94); }

/* Variante standalone — cuando el toggle vive suelto en la topbar (no
   metido dentro de la píldora de usuario), toma el mismo look circular
   que los demás icon-btn-round (campana, refrescar). */
.topbar-actions > .theme-toggle,
.topbar-icons > .theme-toggle {
  width: 42px;
  height: 42px;
  border: 1px solid var(--color-border);
  background: var(--color-bg-surface);
  box-shadow: var(--shadow-card);
  transition: background 0.15s, color 0.15s, transform 0.15s var(--ease-out), box-shadow 0.15s;
}
.topbar-actions > .theme-toggle:hover,
.topbar-icons > .theme-toggle:hover {
  background: var(--color-bg-surface);
  color: var(--color-primary);
  transform: translateY(-1px);
  box-shadow: var(--shadow-float);
}
.topbar-actions > .theme-toggle:active,
.topbar-icons > .theme-toggle:active { transform: scale(0.95); }

.theme-toggle-icon {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 17px;
  height: 17px;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transform: scale(0.5) rotate(-40deg);
  transition: opacity 0.2s var(--ease-out), transform 0.2s var(--ease-out);
}
.theme-toggle-icon svg { width: 100%; height: 100%; }
.theme-toggle-icon--sun { opacity: 1; transform: scale(1) rotate(0deg); }
.theme-toggle.is-dark .theme-toggle-icon--sun { opacity: 0; transform: scale(0.5) rotate(40deg); }
.theme-toggle.is-dark .theme-toggle-icon--moon { opacity: 1; transform: scale(1) rotate(0deg); }

@media (prefers-reduced-motion: reduce) {
  .theme-toggle, .theme-toggle-icon { transition: none; }
}

/* ═══════════════════════════════════════════════════════
   Topbar compartida — buscador global, campana de notificaciones y
   menú de usuario desplegable. Mismo componente en todas las páginas
   del panel (Panel general, Productos, Auditoría, Reportes,
   Configuración, Ayuda).
   ═══════════════════════════════════════════════════════ */

/* ── Buscador global en la topbar (mismo look que .search-input) ── */
.dash-search {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex: 0 1 var(--topbar-search-basis);
  min-width: var(--topbar-search-min-w);
  background: var(--color-bg-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  padding: 9px 16px;
  box-shadow: 0 1px 2px rgba(15, 45, 80, 0.04);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.dash-search:focus-within {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--color-primary-bg);
}
.dash-search-ic { display: flex; flex-shrink: 0; color: var(--color-text-secondary); }
.dash-search-ic svg { width: 16px; height: 16px; }
.dash-search input {
  border: none;
  background: transparent;
  outline: none;
  width: 100%;
  font-family: var(--font-family);
  font-size: var(--text-base);
  color: var(--color-text-primary);
}
.dash-search input::placeholder { color: var(--color-text-muted); }
.dash-search input::-webkit-search-cancel-button { -webkit-appearance: none; }

.dash-menu-anchor { position: relative; }

/* Menú desplegable genérico de la topbar — usa .dropdown-menu de
   components.css, solo cambia el anclaje (a la derecha) y la apertura. */
.dash-menu {
  left: auto;
  right: 0;
  min-width: 260px;
}
.dash-menu-anchor.open > .dash-menu {
  opacity: 1;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}
.dash-menu--user { min-width: 210px; padding: var(--space-2) 0; }

/* ── Menú de usuario desplegable (con chevron) ── */
.topbar .user-menu { position: relative; }
.user-menu-trigger {
  display: flex;
  align-items: center;
  gap: 10px;
  border: none;
  background: none;
  padding: 0;
  cursor: pointer;
  font-family: var(--font-family);
}
.user-menu-chevron {
  width: 14px;
  height: 14px;
  color: var(--color-text-muted);
  transition: transform 0.15s var(--ease-out);
  flex-shrink: 0;
}
.user-menu.open .user-menu-chevron { transform: rotate(180deg); }
.user-menu.open > .dash-menu--user {
  opacity: 1;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}
.dash-menu--user .dropdown-item svg { width: 16px; height: 16px; flex-shrink: 0; }

@media (max-width: 1180px) {
  .dash-search { flex-basis: 220px; }
}
@media (max-width: 620px) {
  .dash-search { flex-basis: 100%; order: -1; }
}

/* ═══════════════════════════════════════════════════════
   Sidebar — flush a la izquierda, mismo tono que el lienzo,
   separada por un borde fino. Expandida 244px, colapsable a 76px.
   ═══════════════════════════════════════════════════════ */
.sidebar {
  width: 244px;
  min-width: 244px;
  /* Sin fondo/radio/sombra propios: vive dentro de la Capa 2
     (.body-layout), que ya aporta ese fondo de forma continua. */
  background: transparent;
  border: none;
  border-radius: 0;
  box-shadow: none;
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  position: relative;
  z-index: 1;
  overflow: hidden;
  transition: width 0.22s cubic-bezier(0.4, 0, 0.2, 1),
              min-width 0.22s cubic-bezier(0.4, 0, 0.2, 1);
}

.sidebar.collapsed {
  width: 76px;
  min-width: 76px;
}

/* ── Logo ─────────────────────────────────────── */
/* Sin fondo propio: el sidebar es una sola superficie continua (Capa 2,
   ver .body-layout) — el logo y el menú no son cajas separadas. */
.sidebar-logo {
  flex-shrink: 0;
  padding: var(--space-6) var(--space-6) var(--space-5) var(--space-6);
}

.sidebar-logo-img {
  display: block;
  width: 160px;
  height: auto;
}

.sidebar-logo-img--dark { display: none; }
:root[data-theme='dark'] .sidebar-logo-img--light { display: none; }
:root[data-theme='dark'] .sidebar-logo-img--dark {
  display: block;
  /* El PNG oscuro trae bastante más margen transparente alrededor que el
     claro: a igual ancho de caja se ve visiblemente más chico. Se agranda
     para que el trazo visible quede del mismo tamaño que el logo claro. */
  width: 200px;
  margin-left: -20px;
}

.sidebar.collapsed .sidebar-logo { display: none; }

/* ── Botón de colapso — círculo, arriba a la derecha ── */
.sidebar-toggle {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  width: 30px;
  height: 30px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-bg-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  color: var(--color-primary);
  cursor: pointer;
  z-index: 3;
  box-shadow: var(--shadow-card);
  transition: background 0.15s, box-shadow 0.15s, transform 0.22s;
}

.sidebar-toggle:hover {
  background: var(--color-primary-bg);
  transform: scale(1.08);
}

.sidebar.collapsed .sidebar-toggle { transform: rotate(180deg); }
.sidebar.collapsed .sidebar-toggle:hover { transform: rotate(180deg) scale(1.08); }

.sidebar-toggle svg { width: 15px; height: 15px; }

/* ── Contenedor de navegación ─────────────────── */
.sidebar-nav {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4) var(--space-5);
  overflow-y: auto;
  overflow-x: hidden;
  position: relative;
  z-index: 2;
  scrollbar-width: none;
}

.sidebar-nav::-webkit-scrollbar { display: none; }

.sidebar.collapsed .sidebar-nav { padding: 60px var(--space-3) var(--space-5); }

/* ── Ítems de navegación ───────────────────────────────────────────
   Inactivo: ícono dentro de su propio contenedor (fondo del acento a baja
   opacidad, redondeado), en un tono apagado; texto gris azulado apagado.
   Activo: sin pastilla ni contenedor — ícono y texto en el color de
   acento sólido, texto en semibold. */
.nav-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 16px;
  border-radius: var(--radius-full);
  text-decoration: none;
  color: var(--color-nav-text-muted);
  font-size: var(--text-md);
  font-weight: var(--weight-regular);
  white-space: nowrap;
  overflow: hidden;
  flex-shrink: 0;
  transition: background 0.14s, color 0.14s, transform 0.1s var(--ease-out);
}

.nav-item:hover {
  background: rgba(46, 127, 232, 0.06);
}

.nav-item:active { transform: scale(0.985); }

/* Ícono liso, sin contenedor propio — el color (gris para inactivo, azul
   para activo) es lo único que los distingue. Íconos con relleno sólido
   (fill: currentColor en el SVG), no de trazo fino. */
.nav-item-icon {
  position: relative;
  width: 23px;
  height: 23px;
  min-width: 23px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-nav-icon-muted);
  flex-shrink: 0;
  transition: color 0.14s;
}

.nav-item-icon svg { width: 20px; height: 20px; }

/* Íconos ilustrados (PNG con transparencia, dibujados por el cliente) en vez
   de SVG con currentColor: como el color no se puede heredar en un raster,
   van 2 imágenes superpuestas (gris "default" y azul "active", mismo patrón
   que el logo claro/oscuro del sidebar) y se cruzan con opacity según el
   estado — así el ícono se sigue viendo azul en :hover/.active igual que
   antes. */
.nav-item-icon-img {
  position: absolute;
  inset: 0;
  width: 23px;
  height: 23px;
  margin: auto;
  transition: opacity 0.14s;
}
.nav-item-icon-img--default { opacity: 1; }
.nav-item-icon-img--active { opacity: 0; }
.nav-item:hover .nav-item-icon-img--default,
.nav-item.active .nav-item-icon-img--default { opacity: 0; }
.nav-item:hover .nav-item-icon-img--active,
.nav-item.active .nav-item-icon-img--active { opacity: 1; }

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

/* Ítem activo — sin pastilla ni contenedor de ícono: solo color sólido. */
.nav-item.active {
  background: transparent;
  color: var(--color-primary);
  font-weight: var(--weight-semibold);
}

.nav-item.active .nav-item-icon { color: var(--color-primary); }
.nav-item.active:hover { background: transparent; color: var(--color-primary); }
.nav-item.active:hover .nav-item-icon { color: var(--color-primary); }

.nav-item-label {
  overflow: hidden;
  white-space: nowrap;
  transition: opacity 0.15s;
}

/* Colapsada: solo íconos, centrados */
.sidebar.collapsed .nav-item {
  padding: 8px;
  justify-content: center;
  gap: 0;
}

.sidebar.collapsed .nav-item-label {
  opacity: 0;
  width: 0;
}

/* ── Rótulo de sección ─────────────────────────── */
.nav-section-label {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-3);
  padding: var(--space-3) var(--space-3) var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  white-space: nowrap;
  flex-shrink: 0;
}

.nav-section-label::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--color-border);
}

.sidebar.collapsed .nav-section-label { display: none; }

/* ─────────────────────────────────────────────
   Card promo al pie de la sidebar — ícono + título en fila, descripción
   y botón de acción abajo (estructura de la referencia). Fondo casi blanco
   con borde sutil. Se oculta al colapsar.
   ───────────────────────────────────────────── */
.sidebar-help {
  flex-shrink: 0;
  position: relative;
  z-index: 2;
  margin: var(--space-3) var(--space-3) var(--space-6);
  padding: var(--space-4);
  border-radius: 16px;
  background: var(--color-bg-surface);
  border: 1px solid var(--color-border-light);
  box-shadow: var(--shadow-card);
}

.sidebar.collapsed .sidebar-help {
  opacity: 0;
  pointer-events: none;
  height: 0;
  margin: 0;
  padding: 0;
  border: none;
  overflow: hidden;
}

/* Grupo secundario del sidebar — Configuración/Ayuda, debajo de la card
   "Guía del panel" en vez de mezclados con el menú principal de arriba. */
.sidebar-secondary-nav {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: 0 var(--space-4) var(--space-4);
}

/* Íconos más chicos que los del menú principal (23px): es un grupo
   secundario, no debe competir visualmente con la navegación primaria. */
.nav-item--secondary .nav-item-icon,
.nav-item--secondary .nav-item-icon-img {
  width: 19px;
  height: 19px;
  min-width: 19px;
}

.sidebar-help-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: var(--space-3);
}

.sidebar-help-icon {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  background: var(--gradient-primary);
  color: #fff;
  box-shadow: var(--glow-primary);
}

.sidebar-help-icon svg { width: 17px; height: 17px; }

.sidebar-help-title {
  margin: 0;
  font-size: var(--text-md);
  font-weight: var(--weight-bold);
  line-height: 1.25;
  color: var(--color-text-heading);
}

.sidebar-help-text {
  margin: 0 0 var(--space-4);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: var(--color-text-secondary);
}

.sidebar-help-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  width: 100%;
  padding: 10px var(--space-3);
  border-radius: 12px;
  border: none;
  background: var(--gradient-primary);
  box-shadow: var(--glow-primary);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: #fff;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.15s var(--ease-out), box-shadow 0.15s, background 0.15s;
}

.sidebar-help-btn:hover {
  background: var(--gradient-primary-hover);
  transform: translateY(-1px);
  box-shadow: 0 12px 26px -8px rgba(46, 127, 232, 0.5);
}
.sidebar-help-btn:active { transform: scale(0.98); }

.sidebar-help-btn svg { width: 14px; height: 14px; flex-shrink: 0; }

.sidebar-decoration { display: none; }

@media (prefers-reduced-motion: reduce) {
  .sidebar,
  .sidebar-toggle,
  .nav-item,
  .nav-item-icon,
  .nav-item-label,
  .sidebar-help,
  .sidebar-help-btn,
  .icon-btn-round { transition: none; }
}

/* ═══════════════════════════════════════════════════════
   Notebook estándar (1280–1599px) — el diseño se pensó para desktop
   grande (≥1600px); acá los 24px de margen/padding de la Capa 1/2/3 y
   los tamaños de fuente grandes quedan desproporcionados y le restan
   espacio útil al contenido. No toca nada fuera de este rango: ni
   ≥1600px ni los breakpoints de mobile/tablet que ya existen (1180px,
   620px), que son más angostos y siguen aplicando por su cuenta.
   ═══════════════════════════════════════════════════════ */
@media (min-width: 1280px) and (max-width: 1599px) {
  /* La Capa 1 sigue necesitando notarse acá, pero con menos aire que en
     desktop grande para no restarle tanto espacio útil al contenido. */
  .app-shell { padding: var(--space-6); }
  .body-layout { padding: var(--space-3); }
  .main-content { margin: var(--space-3) var(--space-3) var(--space-3) 0; }

  .sidebar { width: 220px; min-width: 220px; }

  .main-content-scroll { padding: 40px var(--space-5) var(--space-8); }

  .topbar-greeting h1 { font-size: 26px; }

  /* Topbar en 2 filas: botones-ícono más chicos para que la fila 2
     (título + acción) no le robe tanto alto a la última fila de cards
     del dashboard. El gap entre filas ya se achicó en la base. */
  .topbar-icons .icon-btn-round,
  .topbar-icons > .theme-toggle { width: 36px; height: 36px; }
  .topbar-icons .user-menu .avatar { width: 28px; height: 28px; }
}

/* ── Adaptación por ALTURA (notebooks bajas) ─────────────────────
   Igual que en tokens.css: estos bloques reaccionan solo a la ALTURA
   del viewport y van después de los de ancho para poder pisarlos
   cuando ambas condiciones se dan a la vez (ej. 1366x768 real, que
   entra en el tier de ancho de arriba Y en este de altura). Compacta
   topbar/sidebar sin ocultar ninguna opción ni tocar diseño/colores. */
@media (max-height: 800px) {
  .topbar { margin-bottom: var(--space-4); }
  .topbar-greeting h1 { font-size: 22px; }
  .topbar-greeting p { margin-top: 3px; }

  .main-content-scroll { padding: var(--content-pad-top) var(--content-pad-x) var(--space-5); }

  .sidebar-logo { padding: var(--space-3) var(--space-5) var(--space-3) var(--space-5); }
  .sidebar-logo-img { width: 128px; }

  .sidebar-nav { gap: 2px; padding: var(--space-2) var(--space-3) var(--space-3); }
  .nav-item { padding: 6px 14px; }
  .nav-section-label { margin-top: var(--space-2); padding: var(--space-2) var(--space-2) 4px; }

  .sidebar-help { margin: var(--space-2) var(--space-2) var(--space-3); padding: var(--space-3); }
  .sidebar-secondary-nav { padding: 0 var(--space-3) var(--space-2); gap: 2px; }

  .dash-search { padding: 6px 14px; }
}

@media (max-height: 680px) {
  .sidebar-logo { padding: var(--space-2) var(--space-4) var(--space-2) var(--space-4); }
  .sidebar-logo-img { width: 108px; }
  .sidebar-help { margin: var(--space-2) var(--space-2) var(--space-2); padding: 10px; }
}

/* Backdrop del drawer mobile: oculto por defecto acá (fuera de cualquier
   media query, así siempre gana por especificidad igual + orden de
   cascada sobre la regla que lo muestra en la media query de abajo —
   tiene que declararse ANTES de esa media query). Solo se muestra dentro
   de @media (max-width: 860px), más abajo. */
.sidebar-backdrop { display: none; }

/* ═══════════════════════════════════════════════════════
   Mobile (≤860px) — la sidebar deja de ocupar espacio del layout y pasa
   a ser un drawer que se superpone (fixed) con un backdrop atrás. Ya NO
   hay botón hamburguesa flotante propio: la isla de navegación (más
   abajo, .bottom-navbar) reemplaza esa función — su último ítem ("Más")
   abre el mismo drawer (sigue usando [data-sidebar-mobile-toggle], sin
   cambios en sidebar.js). El botón flotante anterior vivía suelto encima
   del layout sin relación con el buscador, y por eso se solapaba con él;
   sacarlo de raíz resuelve eso sin necesitar ningún ajuste de z-index.
   Mismo breakpoint que ya usan historial.css/configuracion.css, reusado
   en vez de inventar otro. El botón de colapsar-a-iconos de desktop no
   tiene sentido acá (el drawer ya arranca cerrado, mostrando todo el
   texto cuando se abre) — se oculta.
   ═══════════════════════════════════════════════════════ */
@media (max-width: 860px) {
  /* Full page: en mobile no hay lugar (ni sentido) para las 3 capas
     "ventana dentro de ventana" del diseño desktop (margen + marco +
     panel, cada uno con su propio inset/radio/sombra) — el contenido
     ocupa la pantalla entera, borde a borde. */
  .app-shell { padding: 0; }
  .body-layout {
    padding: 0;
    border-radius: 0;
    box-shadow: none;
    background-image: none;
  }
  .main-content {
    margin: 0;
    border-radius: 0;
    box-shadow: none;
    background-image: none;
    background-color: var(--color-bg-panel);
  }
  /* padding-bottom con lugar para la isla de navegación (ver
     .bottom-navbar mas abajo: flota a --mobile-nav-bottom-offset del
     borde, con --mobile-nav-height de alto) + su propio inset de home
     indicator + un poco de aire extra, así el contenido nunca queda
     tapado al llegar al final del scroll. */
  .main-content-scroll {
    padding: var(--space-3) var(--space-4)
      calc(var(--mobile-nav-height) + var(--mobile-nav-bottom-offset) + var(--space-4) + env(safe-area-inset-bottom, 0px));
  }

  /* Header más bajo: menos aire entre la fila de arriba (buscador+
     acciones) y la de abajo (título+CTA), y el título/subtítulo achicados. */
  .topbar { margin-bottom: var(--space-4); }
  .topbar--split { gap: 8px; }
  .topbar-greeting h1 { font-size: 22px; }
  .topbar-greeting p { margin-top: 3px; }

  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    /* min-width le gana a max-width cuando entran en conflicto — con
       min-width:280px fijo el tope de 82vw nunca se aplicaba en pantallas
       angostas de verdad (320px). width:min() sí lo resuelve. */
    width: min(280px, 82vw);
    min-width: 0;
    z-index: 210;
    background: var(--color-bg-sidebar);
    box-shadow: var(--shadow-raised);
    transform: translateX(-100%);
    transition: transform 0.25s var(--ease-out);
  }
  .sidebar.mobile-open { transform: translateX(0); }
  /* Ignora el colapso-a-iconos de desktop mientras el drawer está en modo
     mobile: si el usuario había colapsado la sidebar en su sesión de
     desktop, esa preferencia (guardada en localStorage) no debe abrir un
     drawer angosto/roto acá — siempre se abre expandida, con texto. Hay
     que revertir cada regla de .collapsed una por una (no hay un shorthand
     "quitar todos los estilos de esta clase" en CSS). */
  .sidebar.collapsed { width: min(280px, 82vw); min-width: 0; }
  .sidebar.collapsed .sidebar-logo { display: block; }
  .sidebar.collapsed .sidebar-nav { padding: var(--space-3) var(--space-4) var(--space-5); }
  .sidebar.collapsed .nav-item { padding: 8px 16px; justify-content: flex-start; gap: 10px; }
  .sidebar.collapsed .nav-item-label { opacity: 1; width: auto; }
  .sidebar.collapsed .nav-section-label { display: flex; }
  .sidebar.collapsed .sidebar-help {
    opacity: 1;
    pointer-events: auto;
    height: auto;
    margin: var(--space-3) var(--space-3) var(--space-6);
    padding: var(--space-4);
    border: 1px solid var(--color-border-light);
    overflow: visible;
  }
  .sidebar-toggle { display: none; }

  .sidebar-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 200;
    background: rgba(15, 21, 38, 0.45);
  }
  .sidebar-backdrop.mobile-open { display: block; }

  /* Buscador + campana + tema + usuario: en nowrap no entraban en
     320-375px. Junto con la regla que ya pone el buscador en su propia
     linea (mas abajo, breakpoint 620px), esto evita el desborde. Ya no
     hay ningún ícono flotante que separar de este buscador (ver arriba). */
  .topbar-row--top { flex-wrap: wrap; row-gap: var(--space-2); }
  .topbar-icons .icon-btn-round,
  .topbar-icons > .theme-toggle { width: 44px; height: 44px; }
  .topbar-icons .user-menu .avatar { width: 32px; height: 32px; }

  /* ── Header "hero" con degradé — compartido por las páginas que ya
     migraron a este patrón (agregan la clase .dash-mobile-hero puntualmente
     en su <header>; el resto de las páginas no la tiene, así que esta
     regla no les afecta en nada). Bloque de color con saludo +
     notificaciones + buscador + avatar y esquina inferior curva. Degradé
     de dos tonos del azul de marca (--gradient-kpi-hero, mismo criterio
     que la card "Total de productos" de desktop) — nada de colores fuera
     de la paleta ya establecida. margin-left/right negativo = sangra a
     los bordes de la pantalla (cancela el padding lateral de
     .main-content-scroll); el padding interno lo repone para que el
     contenido quede alineado con el resto de las cards. Si la página
     tiene una card destacada justo debajo (ver dashboard.css/productos.css),
     esa página agrega su propio margin-top (--mobile-hero-gap) para
     separarla del bloque de color con aire real — acá no se asume nada
     de esa separación, es cosa de cada página. */
  .dash-mobile-hero {
    margin-left: calc(-1 * var(--space-4));
    margin-right: calc(-1 * var(--space-4));
    /* Bug real, primer intento fallido: probé cancelar el padding-top de
       .surface (el padre directo del header) con un margin-top negativo
       fijo acá. No funciona en general: .surface y .main-content-scroll
       tienen padding-top distinto según la página (0, 16 o hasta 56px
       sumado, según si la página resetea .surface y/o carga
       productos.css, que a su vez agrega padding-top SOLO por debajo de
       720px vía su propio @media) — un valor fijo de margin-top no
       puede cubrir todas esas combinaciones a la vez sin pasarse o
       quedarse corto en algún ancho. La solución real está en cada
       página (ver auditoria.css/reportes.css/configuracion.css/
       ayuda.css/dashboard.css/productos.css): ponen .surface y
       .main-content-scroll en padding-top:0 directamente cuando hay
       .dash-mobile-hero, en vez de intentar cancelar el valor que sea
       con un cálculo. El padding interno de acá compensa para que el
       contenido (buscador/íconos) no quede pegado al borde de la
       pantalla; env(safe-area-inset-top) de más por si corre bajo el
       notch/status bar de un celular real. */
    /* Aire real (no negativo) antes del siguiente bloque — con el header
       y la primera card del mismo azul, sin esto se percibían como una
       sola forma continua en vez de "card flotando sobre el header".
       Puesto acá (compartido) en vez de en cada página: cubre las 6
       páginas por igual sin overrides repetidos, incluidas las que no
       tienen una card destacada debajo (el margin simplemente colapsa
       contra el margin-top:0 de su primer hijo). */
    margin-bottom: var(--mobile-hero-gap);
    padding: calc(var(--space-5) + env(safe-area-inset-top, 0px)) var(--space-4) var(--space-4);
    background: var(--mobile-hero-gradient);
    border-radius: 0 0 var(--mobile-hero-radius-bottom) var(--mobile-hero-radius-bottom);
  }
  .dash-mobile-hero .topbar-greeting h1 { color: var(--mobile-hero-text); }
  .dash-mobile-hero .topbar-greeting p { color: var(--mobile-hero-text-muted); }
  /* Sin el buscador como input (ahora es un ícono más, ver abajo),
     .topbar-row--top queda con un solo hijo (.topbar-icons) —
     space-between con un solo ítem lo deja pegado a la izquierda; acá va
     a la derecha, como en la referencia. */
  .dash-mobile-hero .topbar-row--top { justify-content: flex-end; }
  .dash-mobile-hero .topbar-icons { gap: 8px; }
  .dash-mobile-hero [data-mobile-search-toggle] { display: inline-flex; }
  /* Nombre/rol del usuario ("Preview Admin") no entra junto a 5 íconos
     en 320-375px — mismo criterio que cualquier header mobile con
     avatar: queda solo el círculo + chevron, el nombre se ve en el menú
     desplegable al tocarlo. */
  .dash-mobile-hero .user-menu-info { display: none; }

  /* ── Buscador como ícono + overlay a pantalla completa ───────────────
     Reemplaza la fila suelta de la ronda anterior (patrón SaaS mobile
     estándar: lupa en el header, no un input siempre expandido en el
     flujo). El <form> real (con su input ya cableado por
     initTopbarSearch()) se "porta" (mueve, no copia — mismo patrón que
     las hojas de detalle) a .dash-mobile-search-overlay-body al entrar a
     mobile; initMobileHeroLayout() en topbar.js arma el ícono trigger y
     el cierre. Fuera de .surface (ver dashboard.html: junto a
     .bottom-navbar/.dash-detail-sheet) para no heredar la animación con
     transform de ".surface > *" como containing block de este
     position:fixed. */
  .dash-mobile-search-overlay {
    position: fixed;
    inset: 0;
    z-index: 300;
    background: var(--color-bg-surface);
    flex-direction: column;
    padding: calc(var(--space-4) + env(safe-area-inset-top, 0px)) var(--space-4) var(--space-4);
    opacity: 0;
    transform: translateY(-12px);
    transition: opacity var(--mobile-sheet-duration) ease-out, transform var(--mobile-sheet-duration) ease-out;
  }
  .dash-mobile-search-overlay:not([hidden]) { display: flex; }
  .dash-mobile-search-overlay--open { opacity: 1; transform: translateY(0); }
  .dash-mobile-search-overlay-head { display: flex; align-items: center; margin-bottom: var(--space-3); }
  .dash-mobile-search-overlay-close {
    width: 44px;
    height: 44px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    background: none;
    color: var(--color-text-secondary);
    cursor: pointer;
  }
  .dash-mobile-search-overlay-body { flex: 1; }
  .dash-mobile-search-overlay-body .dash-search { width: 100%; }

  /* ── FAB "Cargar producto" ────────────────────────────────────────────
     Reemplaza el botón que vivía en la fila suelta. Se "porta" (mismo
     .btn-primary de siempre, con su href/handler intactos — ver
     initMobileHeroLayout()) a este slot fijo, arriba de la isla de
     navegación (mismo --mobile-nav-height/--mobile-nav-bottom-offset ya
     resueltos para ella, así nunca se solapan). Fuera de .surface por la
     misma razón que el overlay de búsqueda. */
  .dash-mobile-fab-slot {
    position: fixed;
    right: var(--mobile-fab-side-inset);
    bottom: calc(var(--mobile-fab-bottom-offset) + env(safe-area-inset-bottom, 0px));
    z-index: 196;
  }
  .dash-mobile-fab-slot .btn-primary {
    width: var(--mobile-fab-size);
    height: var(--mobile-fab-size);
    padding: 0;
    border-radius: var(--radius-full);
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: var(--shadow-raised);
  }
  .dash-mobile-fab-slot .btn-primary .btn-icon { font-size: 26px; line-height: 1; }
  /* El texto ("Cargar producto") sigue en el DOM para el nombre accesible
     del botón en desktop — acá se oculta visualmente, no con display:none
     (eso lo sacaría del árbol de accesibilidad y el FAB quedaría sin
     nombre para lectores de pantalla). */
  .dash-mobile-fab-slot .btn-primary > span:not(.btn-icon) {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
  }
}

/* ═══════════════════════════════════════════════════════
   Bottom navbar — barra de navegación fija abajo, además del botón
   hamburguesa (no en su lugar): acceso directo a las secciones
   principales sin tener que abrir el drawer, más un último ítem que sí
   lo abre (para Configuración/Ayuda). Mismo patrón de ícono doble
   default/active que .nav-item del sidebar (PNG con transparencia, sin
   currentColor). Oculta fuera de mobile.
   ═══════════════════════════════════════════════════════ */
.bottom-navbar { display: none; }

/* Ícono de búsqueda del header "hero" — solo tiene sentido en mobile (en
   desktop el buscador sigue siendo el input de siempre, no un ícono).
   Mismo criterio que .bottom-navbar: oculto por defecto, se muestra
   dentro de la banda mobile más abajo. */
[data-mobile-search-toggle] { display: none; }

@media (max-width: 860px) {
  /* Isla flotante, no una barra de borde a borde: separada de los 4
     bordes, esquinas redondeadas completas, sombra difusa notoria — se
     lee como un elemento flotando sobre el contenido, no como parte del
     marco de la pantalla. */
  .bottom-navbar {
    display: flex;
    position: fixed;
    left: var(--mobile-nav-side-inset);
    right: var(--mobile-nav-side-inset);
    bottom: calc(var(--mobile-nav-bottom-offset) + env(safe-area-inset-bottom, 0px));
    z-index: 195;
    height: var(--mobile-nav-height);
    justify-content: space-around;
    align-items: stretch;
    padding: 0 var(--mobile-nav-side-inset);
    background: var(--color-bg-surface);
    border: none;
    border-radius: var(--mobile-nav-radius);
    box-shadow: var(--mobile-nav-shadow);
  }

  .bottom-nav-item {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    min-height: 44px;
    padding: 6px 4px;
    border: none;
    background: none;
    color: var(--color-nav-text-muted);
    text-decoration: none;
    font-family: var(--font-family);
    cursor: pointer;
    transition: color 0.14s;
  }
  .bottom-nav-item:active { transform: scale(0.95); }

  .bottom-nav-icon {
    position: relative;
    width: 22px;
    height: 22px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--color-nav-icon-muted);
  }
  .bottom-nav-icon svg { width: 22px; height: 22px; }

  /* Halo detrás del ícono activo — fondo tenue del azul de acento,
     redondeado, mismo criterio visual que el resto del sistema para
     marcar "sección actual" (ver --mobile-nav-active-bg/-radius en
     tokens.css). Pseudo-elemento en vez de un wrapper nuevo en el markup
     de las 7 páginas: pinta siempre detrás de los <img> del ícono (son
     hijos reales, más tarde en el DOM que un ::before). */
  .bottom-nav-icon::before {
    content: '';
    position: absolute;
    inset: -7px -12px;
    border-radius: var(--mobile-nav-active-radius);
    background: transparent;
    transition: background 0.14s;
  }
  .bottom-nav-item.active .bottom-nav-icon::before {
    background: var(--mobile-nav-active-bg);
  }

  .bottom-nav-icon-img {
    position: absolute;
    inset: 0;
    width: 22px;
    height: 22px;
    margin: auto;
    transition: opacity 0.14s;
  }
  .bottom-nav-icon-img--default { opacity: 1; }
  .bottom-nav-icon-img--active { opacity: 0; }
  .bottom-nav-item.active .bottom-nav-icon-img--default { opacity: 0; }
  .bottom-nav-item.active .bottom-nav-icon-img--active { opacity: 1; }

  .bottom-nav-item.active { color: var(--color-primary); }
  .bottom-nav-item.active .bottom-nav-icon { color: var(--color-primary); }

  .bottom-nav-label {
    font-size: 11px;
    font-weight: var(--weight-medium);
    line-height: 1;
  }
  .bottom-nav-item.active .bottom-nav-label { font-weight: var(--weight-semibold); }

  /* Toast: con la isla flotando sobre el borde inferior, se sube por
     encima de ella en vez de superponerse. */
  .toast {
    bottom: calc(var(--mobile-nav-height) + var(--mobile-nav-bottom-offset) + env(safe-area-inset-bottom, 0px) + var(--space-3));
  }
}

@media (prefers-reduced-motion: reduce) {
  .bottom-nav-item, .bottom-nav-icon-img { transition: none; }
}
