/* =====================================================================
   ZAYBERHUB | PANEL ADMINISTRATIVO — TIENDA DE PANTALONES
   Paleta denim: índigo oscuro, grises cálidos, acento camel/mostaza
   ===================================================================== */

/* ---------------------------------------------------------------------
   1. VARIABLES GLOBALES
   --------------------------------------------------------------------- */
:root {
  /* Paleta principal — índigo denim */
  --color-primary: #3a5fa0;
  --color-primary-dark: #2c4a7c;
  --color-primary-light: #eef2fa;
  --color-primary-soft: #c8d6ee;

  /* Acento camel / mostaza */
  --color-accent: #b5843a;
  --color-accent-light: #f5edd8;

  /* Estados */
  --color-success: #2d7a50;
  --color-success-light: #e0f2ea;
  --color-danger: #c0392b;
  --color-danger-light: #fce8e6;
  --color-warning: #c07a1a;
  --color-warning-light: #fdf0d8;
  --color-info: #1a6fa8;
  --color-info-light: #dceef9;

  /* Neutros — gris cálido */
  --color-bg: #f2f1ee;
  --color-surface: #ffffff;
  --color-border: #d8d5cf;
  --color-border-soft: #e8e5df;
  --color-text: #1e1c18;
  --color-text-secondary: #5a5650;
  --color-text-muted: #9a9590;

  /* Sidebar — índigo muy oscuro */
  --color-sidebar-bg: #0f1826;
  --color-sidebar-bg-hover: #1a2640;
  --color-sidebar-text: #8fa0b8;
  --color-sidebar-text-active: #ffffff;

  /* Tipografía */
  --font-base: "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, Helvetica, Arial, sans-serif;
  --font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;

  /* Radios — más cuadrados, estilo industrial */
  --radius-sm: 4px;
  --radius-md: 6px;
  --radius-lg: 10px;
  --radius-pill: 999px;

  /* Sombras sutiles */
  --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.06);
  --shadow-sm: 0 1px 4px rgba(0, 0, 0, 0.08);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.10);
  --shadow-lg: 0 8px 28px rgba(0, 0, 0, 0.13);

  /* Layout */
  --sidebar-width: 256px;
  --sidebar-width-collapsed: 72px;
  --topbar-height: 64px;
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 40px;
  --space-8: 56px;

  /* Movimiento — curvas con "desaceleración" suave (se sienten más fluidas
     que ease) y duraciones un poco más largas para que 120 Hz se note. */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-spring: cubic-bezier(0.32, 0.72, 0, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --transition-fast: 0.18s var(--ease-out);
  --transition-base: 0.32s var(--ease-out);

  /* Liquid glass (modo claro) */
  --glass-bg: rgba(255, 255, 255, 0.44);
  --glass-bg-strong: rgba(255, 255, 255, 0.62);
  --glass-border: rgba(255, 255, 255, 0.70);
  --glass-edge: rgba(15, 24, 38, 0.08);
  --glass-highlight: rgba(255, 255, 255, 0.90);
  --glass-sheen: none;
  --glass-shadow: 0 12px 40px rgba(20, 30, 50, 0.16), 0 2px 8px rgba(20, 30, 50, 0.06);
  --glass-blur: 14px;
  --glass-sat: 1.7;
}

/* ---------------------------------------------------------------------
   1.b MODO OSCURO
   Se activa poniendo data-theme="dark" en <html> (ver el script inline
   anti-parpadeo en el <head> de cada página y el botón del topbar).
   Como casi todo el panel ya se apoya en estas variables, redefinirlas
   aquí basta para tintar el 95% de la interfaz sin tocar cada regla.
   --------------------------------------------------------------------- */
:root[data-theme="dark"] {
  --color-primary: #5b85c9;
  --color-primary-dark: #3a5fa0;
  --color-primary-light: #1c2a3f;
  --color-primary-soft: #2a3c58;

  --color-accent: #d1a15c;
  --color-accent-light: #3a3120;

  --color-success: #4caf7d;
  --color-success-light: #16332590;
  --color-danger: #e0685a;
  --color-danger-light: #3a201e;
  --color-warning: #d99a3f;
  --color-warning-light: #3a2e18;
  --color-info: #4d9bd6;
  --color-info-light: #182f3d;

  --color-bg: #13161c;
  --color-surface: #1b1f28;
  --color-border: #2c3140;
  --color-border-soft: #242834;
  --color-text: #e9eaed;
  --color-text-secondary: #a3a8b5;
  --color-text-muted: #6d7386;

  --color-sidebar-bg: #0b0e14;
  --color-sidebar-bg-hover: #171c26;
  --color-sidebar-text: #8fa0b8;
  --color-sidebar-text-active: #ffffff;

  --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.30);
  --shadow-sm: 0 1px 4px rgba(0, 0, 0, 0.35);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.40);
  --shadow-lg: 0 8px 28px rgba(0, 0, 0, 0.50);

  /* Liquid glass (modo oscuro) */
  --glass-bg: rgba(34, 40, 54, 0.38);
  --glass-bg-strong: rgba(27, 31, 42, 0.60);
  --glass-border: rgba(255, 255, 255, 0.12);
  --glass-edge: rgba(255, 255, 255, 0.10);
  --glass-highlight: rgba(255, 255, 255, 0.16);
  --glass-sheen: none;
  --glass-shadow: 0 14px 44px rgba(0, 0, 0, 0.60), 0 2px 8px rgba(0, 0, 0, 0.35);
}

:root[data-theme="dark"] body { color-scheme: dark; }
:root[data-theme="dark"] ::-webkit-scrollbar-thumb { background: #3a3f4d; }
:root[data-theme="dark"] ::-webkit-scrollbar-thumb:hover { background: #4a5063; }
:root[data-theme="dark"] .data-table thead th { background: #20242e; }
:root[data-theme="dark"] .badge-neutral { background: #2c3140; color: var(--color-text-secondary); }
:root[data-theme="dark"] .switch .slider::before { background: #e9eaed; }

/* (La transición claro<->oscuro ya no vive aquí: antes solo 5 selectores se
   animaban y el resto cambiaba de golpe, por eso se veía "a pedacitos".
   Ahora la maneja la View Transitions API desde script.js; ver sección
   "MOVIMIENTO Y LIQUID GLASS" al final de este archivo.) */

/* ---------------------------------------------------------------------
   2. RESET Y BASE
   --------------------------------------------------------------------- */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  /* Evita que iOS/Android reajusten el tamaño de letra al rotar pantalla */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  font-family: var(--font-base);
  background-color: var(--color-bg);
  color: var(--color-text);
  line-height: 1.5;
  min-height: 100vh;
  min-height: 100dvh; /* alto real de pantalla en móviles (evita salto por la barra de Safari) */
  /* Red de seguridad: cualquier elemento que se pase por unos px de ancho
     ya no genera scroll horizontal fantasma en el celular. */
  overflow-x: hidden;
}

a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; }
img { max-width: 100%; display: block; }
video, canvas, svg { max-width: 100%; height: auto; display: block; }

button {
  font-family: inherit;
  cursor: pointer;
  border: none;
  background: none;
}

input, select, textarea {
  font-family: inherit;
  font-size: 0.9rem;
  color: var(--color-text);
}

table { border-collapse: collapse; width: 100%; }

h1, h2, h3, h4, h5, h6 {
  font-weight: 600;
  line-height: 1.25;
}

:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

::-webkit-scrollbar { width: 7px; height: 7px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #c8c4bc; border-radius: var(--radius-pill); }
::-webkit-scrollbar-thumb:hover { background: #a8a49c; }

/* ---------------------------------------------------------------------
   3. UTILIDADES
   --------------------------------------------------------------------- */
.text-secondary { color: var(--color-text-secondary); }
.text-muted     { color: var(--color-text-muted); }
.text-success   { color: var(--color-success); }
.text-danger    { color: var(--color-danger); }
.text-warning   { color: var(--color-warning); }
.text-primary   { color: var(--color-primary); }
.fw-600 { font-weight: 600; }
.fw-700 { font-weight: 700; }
.mt-1 { margin-top: var(--space-1); }
.mt-2 { margin-top: var(--space-2); }
.mt-3 { margin-top: var(--space-3); }
.mt-4 { margin-top: var(--space-4); }
.mt-5 { margin-top: var(--space-5); }
.mb-2 { margin-bottom: var(--space-2); }
.mb-3 { margin-bottom: var(--space-3); }
.mb-4 { margin-bottom: var(--space-4); }
.mb-5 { margin-bottom: var(--space-5); }
.flex { display: flex; }
.flex-col { display: flex; flex-direction: column; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
.gap-2 { gap: var(--space-2); }
.gap-3 { gap: var(--space-3); }
.gap-4 { gap: var(--space-4); }
.w-full { width: 100%; }

.icon-placeholder {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.1em;
  height: 1.1em;
  border-radius: 3px;
  flex-shrink: 0;
}

/* ---------------------------------------------------------------------
   4. LAYOUT — SIDEBAR + TOPBAR + MAIN
   --------------------------------------------------------------------- */
.app-shell {
  display: grid;
  grid-template-columns: var(--sidebar-width) 1fr;
  min-height: 100vh;
  min-height: 100dvh;
}

/* ---- SIDEBAR ---- */
.sidebar {
  background: var(--color-sidebar-bg);
  color: var(--color-sidebar-text);
  display: flex;
  flex-direction: column;
  padding: var(--space-4) var(--space-3);
  padding-left: max(var(--space-3), env(safe-area-inset-left));
  overflow-y: auto;
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100dvh;
}

.sidebar__brand {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-2) var(--space-5);
}

.brand-logo {
  display: block;
  height: auto;
  object-fit: contain;
}

.brand-logo--sidebar {
  width: 100%;
  max-width: 150px;
}

.brand-logo--aside {
  width: 100%;
  max-width: 200px;
}

.brand-logo--box {
  width: 100%;
  max-width: 130px;
  margin-bottom: var(--space-5);
}

.sidebar__brand-text span {
  display: block;
  font-size: 0.68rem;
  font-weight: 400;
  color: var(--color-sidebar-text);
  letter-spacing: 0.5px;
  text-transform: uppercase;
  margin-top: 1px;
}

.sidebar__section-label {
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: #415168;
  padding: var(--space-4) var(--space-2) var(--space-2);
  font-weight: 600;
}

.sidebar__nav {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.sidebar__link {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 9px var(--space-3);
  border-radius: var(--radius-md);
  font-size: 0.87rem;
  font-weight: 500;
  color: var(--color-sidebar-text);
  transition: background var(--transition-fast), color var(--transition-fast);
}

.sidebar__link .icon-placeholder {
  color: #5a7090;
  font-size: 1rem;
}

.sidebar__link:hover {
  background: var(--color-sidebar-bg-hover);
  color: #d4dce8;
}

.sidebar__link:hover .icon-placeholder {
  color: #8fa8c8;
}

.sidebar__link.is-active {
  background: var(--color-primary);
  color: #fff;
}

.sidebar__link.is-active .icon-placeholder {
  color: #c8d8f0;
}

.sidebar__link--logout {
  margin-top: var(--space-3);
  color: #c08080;
}

.sidebar__link--logout .icon-placeholder {
  color: #c08080;
}

.sidebar__link--logout:hover {
  background: rgba(192, 57, 43, 0.18);
  color: #e09090;
}

.sidebar__footer {
  margin-top: auto;
  padding-top: var(--space-4);
  border-top: 1px solid #1e2e44;
}

.sidebar__user {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  border-radius: var(--radius-md);
  background: rgba(255,255,255,0.04);
}

.sidebar__user:hover {
  background: rgba(255,255,255,0.08);
}

.sidebar__user > div {
  min-width: 0;
  flex: 1;
}

.sidebar__avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--color-accent);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 0.78rem;
  flex-shrink: 0;
}

.sidebar__user-name,
.sidebar__user-role {
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sidebar__user-name { color: #d8e0ec; font-size: 0.82rem; font-weight: 600; }
.sidebar__user-role { font-size: 0.70rem; color: #5a7090; margin-top: 1px; }

/* ---- MAIN AREA ---- */
.main {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
  min-width: 0;
}

/* ---- TOPBAR ---- */
.topbar {
  height: var(--topbar-height);
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--space-5);
  padding-left: max(var(--space-5), env(safe-area-inset-left));
  padding-right: max(var(--space-5), env(safe-area-inset-right));
  position: sticky;
  top: 0;
  z-index: 20;
  gap: var(--space-4);
}

.topbar__menu-toggle {
  display: none;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  align-items: center;
  justify-content: center;
  color: var(--color-text-secondary);
}

.topbar__search {
  /* Buscador centrado entre el título y las acciones. Si no cabe (script.js),
     se mueve al menú del botón de la derecha. */
  flex: 1 1 240px;
  width: 240px;
  min-width: 170px;
  max-width: 380px;
  margin: 0 auto;
  position: relative;
}

.topbar__search input {
  width: 100%;
  padding: 9px var(--space-4) 9px 40px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  font-size: 0.85rem;
}

.topbar__search input:focus {
  border-color: var(--color-primary);
  background: var(--color-surface);
  outline: none;
}

.topbar__search .icon-placeholder {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--color-text-muted);
}

.topbar__breadcrumb {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.topbar__breadcrumb .eyebrow {
  font-size: 0.68rem;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.07em;
}

.topbar__breadcrumb h1 {
  font-size: 1.1rem;
  font-weight: 600;
}

.topbar__actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.topbar__icon-btn {
  width: 38px;
  height: 38px;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-text-secondary);
  position: relative;
  flex-shrink: 0;
  cursor: pointer;
}

.topbar__icon-btn:hover {
  background: var(--color-bg);
}

.topbar__icon-btn .dot {
  position: absolute;
  top: 7px;
  right: 7px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--color-danger);
  border: 2px solid var(--color-surface);
}

.topbar__store-select {
  padding: 7px 12px;
  border: 1px solid var(--color-primary-soft);
  border-radius: var(--radius-md);
  font-size: 0.82rem;
  font-weight: 600;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  cursor: pointer;
}

/* ---- CONTENT ---- */
.content {
  padding: var(--space-5);
  flex: 1;
}

.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-bottom: var(--space-5);
}

.page-header h2 {
  font-size: 1.3rem;
  margin-bottom: 3px;
}

.page-header p {
  color: var(--color-text-secondary);
  font-size: 0.87rem;
}

/* ---------------------------------------------------------------------
   5. BOTONES / BADGES / TARJETAS
   --------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 9px 16px;
  border-radius: var(--radius-md);
  font-size: 0.84rem;
  font-weight: 600;
  transition: background var(--transition-fast), border-color var(--transition-fast);
  border: 1px solid transparent;
  white-space: nowrap;
}

.btn-primary   { background: var(--color-primary); color: #fff; }
.btn-primary:hover { background: var(--color-primary-dark); }

.btn-secondary { background: var(--color-surface); color: var(--color-text); border-color: var(--color-border); }
.btn-secondary:hover { background: var(--color-bg); }

.btn-outline   { background: transparent; color: var(--color-primary); border-color: var(--color-primary-soft); }
.btn-outline:hover { background: var(--color-primary-light); }

.btn-success   { background: var(--color-success); color: #fff; }
.btn-success:hover { background: #24633f; }

.btn-danger    { background: var(--color-danger); color: #fff; }
.btn-danger:hover { background: #a0302a; }

.btn-danger-ghost { background: var(--color-danger-light); color: var(--color-danger); }
.btn-danger-ghost:hover { background: #f8d4d0; }

.btn-warning   { background: var(--color-warning); color: #fff; }
.btn-warning:hover { background: #a06214; }

.btn-sm    { padding: 5px 11px; font-size: 0.77rem; }
.btn-lg    { padding: 11px 22px; font-size: 0.92rem; }
.btn-block { width: 100%; }
.btn-icon  { width: 34px; height: 34px; padding: 0; border-radius: var(--radius-sm); }

.btn-group { display: flex; gap: var(--space-2); flex-wrap: wrap; }

/* Badges */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 10px;
  border-radius: var(--radius-pill);
  font-size: 0.72rem;
  font-weight: 600;
  white-space: nowrap;
}

.badge::before {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
}

.badge-success { background: var(--color-success-light); color: var(--color-success); }
.badge-danger  { background: var(--color-danger-light);  color: var(--color-danger); }
.badge-warning { background: var(--color-warning-light); color: var(--color-warning); }
.badge-info    { background: var(--color-info-light);    color: var(--color-info); }
.badge-neutral { background: #ebe8e2; color: var(--color-text-secondary); }
.badge-primary { background: var(--color-primary-light); color: var(--color-primary); }

/* Tarjetas */
.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
}

.card-pad { padding: var(--space-5); }

.card__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--color-border-soft);
}

.card__header h3 { font-size: 0.95rem; }
.card__body { padding: var(--space-5); }

/* Grillas */
.grid-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-4);
}

.grid-2   { display: grid; grid-template-columns: 2fr 1fr; gap: var(--space-4); }
/* Variante de .grid-2 con columnas iguales (usada en la fila de 4 tarjetas
   del dashboard). Antes se lograba con un style="grid-template-columns:
   repeat(2, 1fr)" inline en el HTML, pero un estilo inline le gana SIEMPRE
   a las reglas de los @media de abajo (aunque sean más específicas), así
   que esa fila quedaba forzada a 2 columnas incluso en celular y por eso
   el navegador achicaba toda la página para que "cupiera". Al ser una
   clase normal, la cascada de los @media (que sí bajan .grid-2 a 1
   columna en pantallas chicas) vuelve a aplicar correctamente. */
.grid-2--equal { grid-template-columns: repeat(2, 1fr); }
.grid-3   { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-4); }
.grid-4   { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-4); }
/* auto-fill reserva tantas "pistas" de columna como quepan en el ancho
   disponible, aunque no haya tarjetas para llenarlas todas: esas pistas
   vacías igual ocupan su espacio (por el 1fr), así que las tarjetas reales
   quedaban apretadas a la izquierda y todo el resto de la fila (y de las
   filas siguientes) se veía en blanco — por ejemplo en Tiendas, con solo
   4 tarjetas en una pantalla ancha. auto-fit colapsa esas pistas vacías a
   0 y reparte ese espacio entre las tarjetas que sí existen, así que la
   fila siempre llena el ancho real disponible, sin importar cuántas
   tarjetas haya ni qué tan ancha sea la pantalla (celular, tablet o PC).*/
.grid-auto { display: grid; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); gap: var(--space-4); }

/* Tarjeta KPI */
.stat-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-5);
}

.stat-card__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

/* stat-card--lg ocupa 2 columnas en grid-stats */
.stat-card--lg {
  grid-column: span 2;
}

.stat-card--lg .stat-card__value { font-size: 2rem; }

@media (max-width: 640px) {
  .stat-card--lg { grid-column: span 1; }
}

.stat-card__icon {
  width: 38px;
  height: 38px;
  border-radius: var(--radius-md);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
}

.stat-card__label {
  font-size: 0.76rem;
  color: var(--color-text-secondary);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.stat-card__value {
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.stat-card__trend {
  font-size: 0.75rem;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-weight: 500;
  color: var(--color-text-muted);
}

.trend-up   { color: var(--color-success); }
.trend-down { color: var(--color-danger); }

/* Tarjeta de tienda */
.store-card {
  padding: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.store-card__header { display: flex; justify-content: space-between; align-items: flex-start; }

.store-card__icon {
  width: 44px;
  height: 44px;
  border-radius: var(--radius-md);
  background: var(--color-primary-light);
  color: var(--color-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
}

.store-card__metrics {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px dashed var(--color-border);
}

.store-card__metric span { display: block; }
.store-card__metric .value { font-weight: 700; font-size: 0.92rem; }
.store-card__metric .label { font-size: 0.68rem; color: var(--color-text-muted); margin-top: 1px; }

/* Actividad reciente */
.activity-list { display: flex; flex-direction: column; }

.activity-item {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--color-border-soft);
}

.activity-item:last-child { border-bottom: none; }

.activity-item__icon {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.activity-item__text { font-size: 0.84rem; }
.activity-item__time { font-size: 0.72rem; color: var(--color-text-muted); }

/* ---------------------------------------------------------------------
   6. FORMULARIOS
   --------------------------------------------------------------------- */
.form-grid         { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-4); }
.form-grid--3      { grid-template-columns: repeat(3, 1fr); }
.form-field        { display: flex; flex-direction: column; }
.form-field--full  { grid-column: 1 / -1; }

.field-float { position: relative; }

.field-float input,
.field-float select,
.field-float textarea {
  width: 100%;
  padding: 17px var(--space-4) 7px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  transition: border-color var(--transition-fast);
}

.field-float textarea { min-height: 90px; resize: vertical; padding-top: 20px; }

.field-float label {
  position: absolute;
  left: 14px;
  top: 13px;
  font-size: 0.84rem;
  color: var(--color-text-muted);
  pointer-events: none;
  transition: top var(--transition-fast), left var(--transition-fast), font-size var(--transition-fast), color var(--transition-fast);
  background: var(--color-surface);
  padding: 0 3px;
}

.field-float input:focus,
.field-float select:focus,
.field-float textarea:focus {
  outline: none;
  border-color: var(--color-primary);
}

.field-float input:focus + label,
.field-float input:not(:placeholder-shown) + label,
.field-float select:focus + label,
.field-float select + label,
.field-float textarea:focus + label,
.field-float textarea:not(:placeholder-shown) + label {
  top: -7px;
  left: 11px;
  font-size: 0.67rem;
  font-weight: 600;
  color: var(--color-primary);
}

.field-hint { font-size: 0.71rem; color: var(--color-text-muted); margin-top: 3px; }

/* Fila "Producto + Agregar al carrito" (ventas.php): select flexible junto
   a un botón de ancho natural. En móvil se apilan completos, cada uno al
   100% de ancho, para que el select nunca se encoja a su contenido. */
.tp-producto-row {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: flex-end;
}
.tp-producto-row__select { flex: 1 1 240px; min-width: 0; }
.tp-producto-row__btn { flex: 0 0 auto; margin-bottom: 2px; white-space: nowrap; }

@media (max-width: 640px) {
  .tp-producto-row { flex-direction: column; align-items: stretch; }
  .tp-producto-row__select { flex: 1 1 auto; width: 100%; }
  .tp-producto-row__btn { width: 100%; margin-bottom: 0; }
}


.checkbox-row,
.radio-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 0.85rem;
}

input[type="checkbox"],
input[type="radio"] {
  width: 16px;
  height: 16px;
  accent-color: var(--color-primary);
}

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
}

.filter-bar__search {
  position: relative;
  flex: 1;
  min-width: 180px;
}

.filter-bar__search input {
  width: 100%;
  padding: 9px var(--space-4) 9px 38px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  font-size: 0.84rem;
}

.filter-bar__search input:focus {
  outline: none;
  border-color: var(--color-primary);
}

.filter-bar__search .icon-placeholder {
  position: absolute;
  left: 11px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--color-text-muted);
}

.filter-bar select {
  padding: 9px 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  font-size: 0.83rem;
  min-width: 130px;
}

/* ---------------------------------------------------------------------
   7. TABLAS
   --------------------------------------------------------------------- */
.table-wrap {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-xs);
}

/* .table-scroll es el único scroll horizontal permitido del sistema.
   Para que se note que es una tabla desplazable (y no contenido cortado
   sin avisar), se agrega un difuminado en el borde derecho que solo se ve
   cuando realmente hay más contenido para desplazar (background-attachment:
   local crea dos "guardas" de gradiente que se pegan al contenido, no al
   viewport del scroll, así que desaparecen naturalmente al llegar al final). */
.table-scroll {
  overflow-x: auto;
  background:
    linear-gradient(to right, var(--color-surface) 30%, rgba(255,255,255,0)),
    linear-gradient(to right, rgba(255,255,255,0), var(--color-surface) 70%) 100% 0,
    linear-gradient(to right, rgba(20,20,20,0.10), rgba(20,20,20,0)),
    linear-gradient(to left, rgba(20,20,20,0.10), rgba(20,20,20,0)) 100% 0;
  background-repeat: no-repeat;
  background-color: var(--color-surface);
  background-size: 24px 100%, 24px 100%, 10px 100%, 10px 100%;
  background-attachment: local, local, scroll, scroll;
}

.data-table {
  width: 100%;
  min-width: 680px;
  /* table-layout:fixed evita que el algoritmo automático de columnas
     "colapse" una columna a casi 0px cuando el ancho disponible es
     menor al contenido total: como overflow-wrap/word-break:break-word
     permiten partir en cualquier punto, el layout automático las
     encogía hasta 1 carácter por línea (nombres/correos verticales)
     mientras las columnas con badges cortos se quedaban con todo el
     espacio. Con layout fijo, cada columna recibe una porción estable
     del ancho de la tabla y el texto largo se envuelve en palabras/
     fragmentos legibles en vez de una letra por renglón. */
  table-layout: fixed;
}

.data-table thead th {
  text-align: left;
  font-size: 0.70rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-text-muted);
  background: #f7f5f2;
  padding: 12px var(--space-4);
  border-bottom: 1px solid var(--color-border);
  white-space: nowrap;
  font-weight: 600;
}

.data-table tbody td {
  padding: 13px var(--space-4);
  font-size: 0.85rem;
  border-bottom: 1px solid var(--color-border-soft);
  vertical-align: middle;
}

.data-table tbody tr:hover { background: var(--color-primary-light); }
.data-table tbody tr:last-child td { border-bottom: none; }

.table-thumb {
  width: 40px;
  height: 40px;
  border-radius: var(--radius-sm);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-text-muted);
  font-size: 0.64rem;
  overflow: hidden;
}

.table-actions { display: flex; gap: 5px; }

/* .tp-cell-persona: celdas "avatar + nombre" (usuarios, vendedores, ventas
   por vendedor). Bug real encontrado: la celda es un contenedor flex y el
   nombre iba como texto suelto (sin envolver en un elemento), así que el
   navegador le creaba una "caja anónima" flex que el sistema NO puede
   seleccionar por CSS. Esa caja anónima usa min-width:auto por defecto y,
   al tener overflow-wrap/word-break:break-word encima, su ancho mínimo de
   contenido se calculaba letra por letra en vez de palabra por palabra:
   con una columna angosta, el nombre terminaba con una letra por renglón.
   Solución real (no solo CSS): el nombre ahora va en un <span> propio
   (.tp-cell-persona__nombre), así sí es un elemento seleccionable al que
   podemos forzar min-width:0 y dejar que se achique y envuelva por
   palabras como cualquier texto normal dentro de un flex item. */
.tp-cell-persona__nombre {
  min-width: 0;
  flex: 1 1 auto;
  overflow-wrap: break-word;
}

.table-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) var(--space-5);
  border-top: 1px solid var(--color-border-soft);
  flex-wrap: wrap;
  gap: var(--space-3);
}

.pagination { display: flex; gap: 4px; align-items: center; }

.pagination button,
.pagination a {
  width: 30px;
  height: 30px;
  border-radius: var(--radius-sm);
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--color-text-secondary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
}

.pagination button.is-active   { background: var(--color-primary); color: #fff; }
.pagination button:hover:not(.is-active),
.pagination a:hover            { background: var(--color-bg); }
.pagination button:disabled,
.pagination button[disabled]   { opacity: 0.4; cursor: not-allowed; }

/* Indicador de stock */
.stock-indicator { display: flex; align-items: center; gap: 7px; }
.stock-bar { width: 56px; height: 5px; border-radius: var(--radius-pill); background: var(--color-border-soft); overflow: hidden; }
.stock-bar span { display: block; height: 100%; border-radius: var(--radius-pill); }
.stock-alto    span { background: var(--color-success); width: 90%; }
.stock-medio   span { background: var(--color-warning); width: 55%; }
.stock-bajo    span { background: var(--color-danger);  width: 22%; }
.stock-agotado span { background: var(--color-text-muted); width: 4%; }

/* Chips de variante (color/talla) */
.variant-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--color-border);
  font-size: 0.70rem;
  font-weight: 600;
  background: var(--color-bg);
}

.variant-chip .swatch {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  border: 1px solid rgba(0,0,0,0.15);
}

/* ---------------------------------------------------------------------
   8. GRÁFICOS SIMULADOS EN CSS
   --------------------------------------------------------------------- */
.chart-bars {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  height: 150px;
  padding-top: var(--space-4);
}

.chart-bars .bar {
  flex: 1;
  border-radius: 4px 4px 0 0;
  background: var(--color-primary);
  position: relative;
  min-height: 4px;
  opacity: 0.85;
}

.chart-bars .bar span {
  position: absolute;
  bottom: -20px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 0.66rem;
  color: var(--color-text-muted);
  white-space: nowrap;
}

.chart-bars .bar.is-muted { background: var(--color-border); opacity: 1; }

.chart-donut {
  width: 140px;
  height: 140px;
  border-radius: 50%;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  background: conic-gradient(
    var(--color-primary) 0deg 160deg,
    var(--color-success) 160deg 250deg,
    var(--color-accent)  250deg 310deg,
    var(--color-border-soft) 310deg 360deg
  );
}

.chart-donut__hole {
  width: 90px;
  height: 90px;
  border-radius: 50%;
  background: var(--color-surface);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.chart-donut__hole strong { font-size: 1.1rem; }
.chart-donut__hole span  { font-size: 0.66rem; color: var(--color-text-muted); }

.chart-legend { display: flex; flex-direction: column; gap: var(--space-2); }
.chart-legend li { display: flex; align-items: center; gap: 7px; font-size: 0.79rem; }
.chart-legend .dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }

.chart-line {
  height: 130px;
  border-radius: var(--radius-md);
  background:
    linear-gradient(0deg, transparent 24%, var(--color-border-soft) 25%, transparent 26%) 0 0/100% 25%,
    linear-gradient(180deg, var(--color-primary-light), transparent);
  position: relative;
  overflow: hidden;
}

.chart-line svg { width: 100%; height: 100%; }

/* Barra de progreso */
.progress {
  width: 100%;
  height: 7px;
  border-radius: var(--radius-pill);
  background: var(--color-border-soft);
  overflow: hidden;
}

.progress span {
  display: block;
  height: 100%;
  border-radius: var(--radius-pill);
  background: var(--color-primary);
}

/* ---------------------------------------------------------------------
   9. LOGIN
   --------------------------------------------------------------------- */
.login-page {
  min-height: 100vh;
  min-height: 100dvh; /* alto real de pantalla en móviles (evita salto por la barra de Safari) */
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  position: relative;
  background: radial-gradient(130% 100% at 25% 0%, #0a1026 0%, #050813 55%, #02040b 100%);
  overflow: hidden;
}

@keyframes star-twinkle-a {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.6; }
}

@keyframes star-twinkle-b {
  0%, 100% { opacity: 0.65; }
  50%      { opacity: 1; }
}

/* Giro del cielo: la capa es más grande que la pantalla (150vmax) para que
   al rotar sobre su centro nunca se vean esquinas vacías. */
@keyframes star-orbit {
  from { transform: translate(-50%, -50%) rotate(0deg); }
  to   { transform: translate(-50%, -50%) rotate(360deg); }
}
@keyframes star-orbit-rev {
  from { transform: translate(-50%, -50%) rotate(360deg); }
  to   { transform: translate(-50%, -50%) rotate(0deg); }
}

/* Cielo estrellado — capa 1: estrellas grandes con halo, giro lento */
.login-page::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 150vmax;
  height: 150vmax;
  transform: translate(-50%, -50%);
  will-change: transform, opacity;
  animation:
    star-orbit 280s linear infinite,
    star-twinkle-a 4.5s ease-in-out infinite;
  background-image:
    radial-gradient(7.6px 7.6px at 34.1% 18.6%, rgba(170,200,255,0.55), transparent 70%),
    radial-gradient(1.8px 1.8px at 34.1% 18.6%, #ffffff, transparent 62%),
    radial-gradient(3.1px 3.1px at 78.9% 13.5%, #ffffff, transparent 62%),
    radial-gradient(7.6px 7.6px at 86.9% 24.3%, rgba(170,200,255,0.55), transparent 70%),
    radial-gradient(1.8px 1.8px at 86.9% 24.3%, #d6e4ff, transparent 62%),
    radial-gradient(3.1px 3.1px at 42.6% 26.7%, #d6e4ff, transparent 62%),
    radial-gradient(8.8px 8.8px at 10.3% 55.9%, rgba(170,200,255,0.55), transparent 70%),
    radial-gradient(2.1px 2.1px at 10.3% 55.9%, #ffeccf, transparent 62%),
    radial-gradient(2.8px 2.8px at 90.3% 56.9%, #ffffff, transparent 62%),
    radial-gradient(8.8px 8.8px at 92.9% 9.2%, rgba(170,200,255,0.55), transparent 70%),
    radial-gradient(2.1px 2.1px at 92.9% 9.2%, #ffffff, transparent 62%),
    radial-gradient(3.1px 3.1px at 42.7% 53.7%, #ffffff, transparent 62%),
    radial-gradient(7.6px 7.6px at 55.4% 66.4%, rgba(170,200,255,0.55), transparent 70%),
    radial-gradient(1.8px 1.8px at 55.4% 66.4%, #ffeccf, transparent 62%),
    radial-gradient(1.8px 1.8px at 56.4% 21.9%, #ffeccf, transparent 62%),
    radial-gradient(13.0px 13.0px at 69.1% 55.8%, rgba(170,200,255,0.55), transparent 70%),
    radial-gradient(3.1px 3.1px at 69.1% 55.8%, #ffffff, transparent 62%),
    radial-gradient(2.4px 2.4px at 49.7% 52.9%, #d6e4ff, transparent 62%),
    radial-gradient(10.1px 10.1px at 57.7% 45.8%, rgba(170,200,255,0.55), transparent 70%),
    radial-gradient(2.4px 2.4px at 57.7% 45.8%, #ffffff, transparent 62%),
    radial-gradient(2.1px 2.1px at 76.5% 67.9%, #ffffff, transparent 62%),
    radial-gradient(10.1px 10.1px at 56.7% 52.3%, rgba(170,200,255,0.55), transparent 70%),
    radial-gradient(2.4px 2.4px at 56.7% 52.3%, #d6e4ff, transparent 62%),
    radial-gradient(1.8px 1.8px at 30.9% 93.2%, #ffeccf, transparent 62%),
    radial-gradient(8.8px 8.8px at 42.6% 73.1%, rgba(170,200,255,0.55), transparent 70%),
    radial-gradient(2.1px 2.1px at 42.6% 73.1%, #d6e4ff, transparent 62%),
    radial-gradient(1.8px 1.8px at 43.0% 91.6%, #ffeccf, transparent 62%);
  background-repeat: repeat;
  background-size: 520px 520px;
  pointer-events: none;
}

/* Capa 2: estrellas pequeñas y densas, giran en sentido contrario (profundidad) */
.login-page::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 150vmax;
  height: 150vmax;
  transform: translate(-50%, -50%);
  will-change: transform, opacity;
  animation:
    star-orbit-rev 420s linear infinite,
    star-twinkle-b 3.4s ease-in-out infinite;
  background-image:
    radial-gradient(7.6px 7.6px at 56.7% 84.5%, rgba(170,200,255,0.4), transparent 70%),
    radial-gradient(1.7px 1.7px at 56.7% 84.5%, rgba(255,255,255,0.95), transparent 60%),
    radial-gradient(1.9px 1.9px at 68.0% 58.7%, rgba(255,255,255,0.85), transparent 60%),
    radial-gradient(1.9px 1.9px at 81.3% 90.9%, rgba(255,255,255,1), transparent 60%),
    radial-gradient(7.6px 7.6px at 65.1% 9.6%, rgba(170,200,255,0.4), transparent 70%),
    radial-gradient(1.7px 1.7px at 65.1% 9.6%, rgba(255,255,255,1), transparent 60%),
    radial-gradient(1.9px 1.9px at 57.2% 66.7%, rgba(255,255,255,0.95), transparent 60%),
    radial-gradient(1.7px 1.7px at 69.9% 85.6%, rgba(255,255,255,0.85), transparent 60%),
    radial-gradient(5.9px 5.9px at 90.5% 36.7%, rgba(170,200,255,0.4), transparent 70%),
    radial-gradient(1.3px 1.3px at 90.5% 36.7%, rgba(255,255,255,0.95), transparent 60%),
    radial-gradient(1.5px 1.5px at 9.4% 74.7%, rgba(255,255,255,1), transparent 60%),
    radial-gradient(1.9px 1.9px at 26.8% 40.0%, rgba(255,255,255,0.85), transparent 60%),
    radial-gradient(7.6px 7.6px at 19.3% 41.0%, rgba(170,200,255,0.4), transparent 70%),
    radial-gradient(1.7px 1.7px at 19.3% 41.0%, rgba(255,255,255,0.85), transparent 60%),
    radial-gradient(1.7px 1.7px at 79.4% 83.5%, rgba(255,255,255,1), transparent 60%),
    radial-gradient(1.9px 1.9px at 42.2% 37.0%, rgba(255,255,255,0.85), transparent 60%),
    radial-gradient(6.8px 6.8px at 17.9% 20.2%, rgba(170,200,255,0.4), transparent 70%),
    radial-gradient(1.5px 1.5px at 17.9% 20.2%, rgba(255,255,255,1), transparent 60%),
    radial-gradient(1.5px 1.5px at 25.5% 48.6%, rgba(255,255,255,0.95), transparent 60%),
    radial-gradient(1.7px 1.7px at 29.9% 17.4%, rgba(255,255,255,1), transparent 60%),
    radial-gradient(5.9px 5.9px at 56.1% 91.7%, rgba(170,200,255,0.4), transparent 70%),
    radial-gradient(1.3px 1.3px at 56.1% 91.7%, rgba(255,255,255,0.95), transparent 60%),
    radial-gradient(1.9px 1.9px at 86.8% 75.8%, rgba(255,255,255,0.95), transparent 60%),
    radial-gradient(1.9px 1.9px at 40.7% 13.5%, rgba(255,255,255,0.85), transparent 60%),
    radial-gradient(8.5px 8.5px at 21.5% 94.6%, rgba(170,200,255,0.4), transparent 70%),
    radial-gradient(1.9px 1.9px at 21.5% 94.6%, rgba(255,255,255,0.85), transparent 60%),
    radial-gradient(1.3px 1.3px at 14.1% 59.3%, rgba(255,255,255,0.85), transparent 60%),
    radial-gradient(1.7px 1.7px at 56.1% 53.4%, rgba(255,255,255,1), transparent 60%),
    radial-gradient(8.5px 8.5px at 6.3% 84.4%, rgba(170,200,255,0.4), transparent 70%),
    radial-gradient(1.9px 1.9px at 6.3% 84.4%, rgba(255,255,255,0.85), transparent 60%),
    radial-gradient(1.7px 1.7px at 62.4% 91.9%, rgba(255,255,255,0.95), transparent 60%),
    radial-gradient(1.9px 1.9px at 15.3% 82.1%, rgba(255,255,255,0.95), transparent 60%),
    radial-gradient(5.9px 5.9px at 48.5% 11.9%, rgba(170,200,255,0.4), transparent 70%),
    radial-gradient(1.3px 1.3px at 48.5% 11.9%, rgba(255,255,255,1), transparent 60%),
    radial-gradient(1.5px 1.5px at 35.5% 28.4%, rgba(255,255,255,1), transparent 60%);
  background-repeat: repeat;
  background-size: 260px 260px;
  pointer-events: none;
}

.login-aside {
  background: transparent;
  color: #fff;
  padding: var(--space-8);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  position: relative;
  overflow: hidden;
  z-index: 1;
}

.login-aside__brand {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  position: relative;
}

.login-aside__content {
  max-width: 400px;
  position: relative;
}

.login-aside__content h2 {
  font-size: 1.9rem;
  line-height: 1.2;
  margin-bottom: var(--space-4);
  font-weight: 700;
}

.login-aside__content p {
  color: rgba(255,255,255,0.65);
  font-size: 0.92rem;
  line-height: 1.6;
}

.login-aside__stats {
  display: flex;
  gap: var(--space-6);
  margin-top: var(--space-6);
  padding-top: var(--space-5);
  border-top: 1px solid rgba(255,255,255,0.12);
}

.login-aside__stats strong {
  display: block;
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--color-accent);
}

.login-aside__stats span {
  font-size: 0.70rem;
  color: rgba(255,255,255,0.5);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.login-aside__footer {
  font-size: 0.73rem;
  color: rgba(255,255,255,0.4);
  position: relative;
}

.login-main {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6);
  background: transparent;
  position: relative;
  z-index: 1;
}

.login-box {
  width: 100%;
  max-width: 360px;
  background: rgba(15, 17, 26, 0.72);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: var(--radius-lg, 16px);
  padding: var(--space-6);
  backdrop-filter: blur(10px);
  box-shadow: 0 20px 60px rgba(0,0,0,0.5);
}

.login-box h1 { color: #ffffff; }
.login-box p.subtitle { color: rgba(255,255,255,0.65); }
.login-box .login-box__options { color: rgba(255,255,255,0.8); }
.login-box .login-box__options a { color: var(--color-accent); }
.login-box .login-box__footer { color: rgba(255,255,255,0.55); }

.login-box__logo {
  width: 48px;
  height: 48px;
  border-radius: var(--radius-md);
  background: var(--color-accent);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 1.15rem;
  margin-bottom: var(--space-5);
  letter-spacing: 0.5px;
}

.login-box h1 { font-size: 1.4rem; margin-bottom: 5px; }
.login-box p.subtitle { color: var(--color-text-secondary); font-size: 0.87rem; margin-bottom: var(--space-5); }

.login-box form { display: flex; flex-direction: column; gap: var(--space-4); }

.login-box__options {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 0.79rem;
}

.login-box__options a { color: var(--color-primary); font-weight: 600; }

.login-box__divider {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  color: var(--color-text-muted);
  font-size: 0.70rem;
  text-transform: uppercase;
  margin: var(--space-2) 0;
}

.login-box__divider::before,
.login-box__divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--color-border);
}

.login-box__footer {
  margin-top: var(--space-5);
  font-size: 0.77rem;
  color: var(--color-text-muted);
  text-align: center;
}

/* ---------------------------------------------------------------------
   10. COMPONENTES DE MÓDULOS
   --------------------------------------------------------------------- */

/* Tabs */
.tabs {
  display: flex;
  gap: 0;
  border-bottom: 2px solid var(--color-border);
  margin-bottom: var(--space-5);
  overflow-x: auto;
}

.tabs button {
  padding: 10px var(--space-4);
  font-size: 0.84rem;
  font-weight: 600;
  color: var(--color-text-secondary);
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  white-space: nowrap;
}

.tabs button:hover { color: var(--color-text); }
.tabs button.is-active { color: var(--color-primary); border-color: var(--color-primary); }

.tabs a.btn-tab-link {
  padding: 10px var(--space-4);
  font-size: 0.84rem;
  font-weight: 600;
  color: var(--color-text-secondary);
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  white-space: nowrap;
  text-decoration: none;
}

.tabs a.btn-tab-link:hover { color: var(--color-text); }

/* Selector de sucursal */
.tp-sucursal-switch {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-2);
  margin-bottom: var(--space-4);
}

.tp-sucursal-switch__label {
  font-size: 0.76rem;
  font-weight: 600;
  color: var(--color-text-secondary);
  padding: 0 var(--space-2);
}

.tp-sucursal-tab {
  padding: 6px 14px;
  font-size: 0.81rem;
  font-weight: 600;
  color: var(--color-text-secondary);
  background: transparent;
  border-radius: var(--radius-pill);
  border: 1px solid transparent;
}

.tp-sucursal-tab:hover { color: var(--color-text); }

.tp-sucursal-tab.is-active {
  color: var(--color-primary);
  background: var(--color-primary-light);
  border-color: var(--color-primary-soft);
}

.tp-sucursal-tab:disabled { opacity: 0.4; cursor: not-allowed; }

.tp-sucursal-note {
  font-size: 0.81rem;
  color: var(--color-text-secondary);
  background: var(--color-primary-light);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
  margin-bottom: var(--space-4);
}

.tp-sucursal-note strong { color: var(--color-primary); }

.tp-bodega-nota {
  font-size: 0.81rem;
  color: var(--color-text-secondary);
  background: var(--color-warning-light);
  border: 1px dashed var(--color-warning);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  margin-top: var(--space-4);
}

/* Timeline */
.timeline { display: flex; flex-direction: column; }

.timeline-item {
  display: flex;
  gap: var(--space-4);
  padding-bottom: var(--space-5);
  position: relative;
}

.timeline-item::before {
  content: "";
  position: absolute;
  left: 15px;
  top: 32px;
  bottom: 0;
  width: 2px;
  background: var(--color-border-soft);
}

.timeline-item:last-child::before { display: none; }

.timeline-dot {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--color-primary-light);
  color: var(--color-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  font-size: 0.73rem;
  font-weight: 700;
  z-index: 1;
}

.timeline-content strong { font-size: 0.86rem; display: block; }
.timeline-content span   { font-size: 0.77rem; color: var(--color-text-muted); }

/* Pasos de estado horizontal */
.status-steps {
  display: flex;
  align-items: center;
  width: 100%;
}

.status-step {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  flex: 1;
  position: relative;
}

.status-step .circle {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--color-border-soft);
  color: var(--color-text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.73rem;
  font-weight: 700;
  border: 2px solid var(--color-border);
}

.status-step.is-done    .circle { background: var(--color-success); color: #fff; border-color: var(--color-success); }
.status-step.is-current .circle { background: var(--color-primary); color: #fff; border-color: var(--color-primary); }
.status-step span.label { font-size: 0.70rem; color: var(--color-text-secondary); text-align: center; }

.status-step::after {
  content: "";
  position: absolute;
  top: 14px;
  left: 50%;
  width: 100%;
  height: 2px;
  background: var(--color-border-soft);
  z-index: -1;
}

.status-step:last-child::after { display: none; }
.status-step.is-done::after    { background: var(--color-success); }

/* Empty state */
.empty-state {
  text-align: center;
  padding: var(--space-8) var(--space-5);
  color: var(--color-text-secondary);
}

.empty-state .icon-placeholder {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--color-bg);
  margin: 0 auto var(--space-4);
}

/* KPI de reportes */
.report-card {
  padding: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.report-card__icon {
  width: 42px;
  height: 42px;
  border-radius: var(--radius-md);
  display: flex;
  align-items: center;
  justify-content: center;
}

.ranking-list { display: flex; flex-direction: column; gap: var(--space-3); }

.ranking-item { display: flex; align-items: center; gap: var(--space-3); }

.ranking-item .pos {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--color-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--color-text-secondary);
  flex-shrink: 0;
}

.ranking-item__info { flex: 1; }
.ranking-item__info strong { font-size: 0.82rem; display: block; }
.ranking-item__info .progress { margin-top: 4px; }

/* Toggle switch */
.switch { position: relative; display: inline-block; width: 40px; height: 22px; }
.switch input { opacity: 0; width: 0; height: 0; }
.switch .slider {
  position: absolute; inset: 0;
  background: var(--color-border);
  border-radius: var(--radius-pill);
  transition: var(--transition-fast);
}
.switch .slider::before {
  content: "";
  position: absolute;
  width: 16px; height: 16px;
  left: 3px; top: 3px;
  background: #fff;
  border-radius: 50%;
  transition: var(--transition-fast);
  box-shadow: var(--shadow-xs);
}
.switch input:checked + .slider { background: var(--color-primary); }
.switch input:checked + .slider::before { transform: translateX(18px); }

.settings-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4) 0;
  border-bottom: 1px solid var(--color-border-soft);
}

.settings-row:last-child { border-bottom: none; }
.settings-row__label strong { display: block; font-size: 0.86rem; }
.settings-row__label span  { font-size: 0.77rem; color: var(--color-text-muted); }

.color-swatch-picker { display: flex; gap: var(--space-3); }
.color-swatch-picker .swatch {
  width: 34px; height: 34px;
  border-radius: 50%;
  border: 2px solid var(--color-surface);
  box-shadow: 0 0 0 2px var(--color-border);
  cursor: pointer;
}
.color-swatch-picker .swatch.is-selected { box-shadow: 0 0 0 2px var(--color-primary); }

.upload-box {
  border: 1.5px dashed var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-6);
  text-align: center;
  color: var(--color-text-muted);
  font-size: 0.82rem;
}

/* Métricas de marketing */
.roi-badge {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  font-weight: 700;
  font-size: 1.35rem;
  color: var(--color-success);
}

.roi-badge span { font-size: 0.73rem; font-weight: 500; color: var(--color-text-muted); }

/* ---------------------------------------------------------------------
   11. RESPONSIVE
   --------------------------------------------------------------------- */
@media (max-width: 1366px) {
  .content { padding: var(--space-4); }
}

@media (max-width: 1024px) {
  .app-shell { grid-template-columns: var(--sidebar-width-collapsed) 1fr; }
  .sidebar__brand-text,
  .sidebar__section-label,
  .sidebar__link span.link-text,
  .sidebar__user-name,
  .sidebar__user-role { display: none; }
  .sidebar__brand { justify-content: center; padding-left: 0; padding-right: 0; }
  .sidebar__link  { justify-content: center; }
  .sidebar__user  { justify-content: center; }
  .grid-2 { grid-template-columns: 1fr; }
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .form-grid, .form-grid--3 { grid-template-columns: repeat(2, 1fr); }
  .login-page    { grid-template-columns: 1fr; }
  .login-aside   { display: none; }
}

/* Tablets (ej. iPad de 11", ~700-1024px de ancho, sea en formato
   celular con menú hamburguesa o con el sidebar ya colapsado a íconos).
   La regla de arriba baja .grid-2 a 1 sola columna igual que en un
   celular angosto, pero acá sobra ancho de sobra: cada tarjeta terminaba
   estirada a todo el contenido (~700-950px) con un ícono y una línea de
   texto perdidos en medio de un espacio enorme. En este rango sí entran
   2 columnas parejas sin apretar nada. Por debajo de 700px (celulares)
   se mantiene 1 columna como hasta ahora, y por encima de 1024px sigue
   el 2fr/1fr de escritorio sin cambios. */
@media (min-width: 700px) and (max-width: 1024px) {
  .grid-2 { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 768px) {
  .app-shell { grid-template-columns: 1fr; }
  .sidebar {
    position: fixed;
    left: 0; top: 0; bottom: 0;
    width: 240px;
    transform: translateX(-100%);
    transition: transform 0.42s var(--ease-spring);
    z-index: 100;
    height: 100%;
    height: 100dvh;
    padding-bottom: max(var(--space-4), env(safe-area-inset-bottom));
  }
  .sidebar.is-open { transform: translateX(0); }
  .sidebar.is-dragging { transition: none; }
  .sidebar__brand-text,
  .sidebar__section-label,
  .sidebar__link span.link-text,
  .sidebar__user-name,
  .sidebar__user-role { display: block; }
  .sidebar__brand { justify-content: flex-start; }
  .sidebar__link  { justify-content: flex-start; }
  .sidebar__user  { justify-content: flex-start; }
  .topbar__menu-toggle { display: flex; }
  .grid-3 { grid-template-columns: repeat(2, 1fr); }
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .card__body .grid-2 { grid-template-columns: 1fr; }
  .store-card__metrics { grid-template-columns: repeat(3, 1fr); }
  .status-steps { flex-wrap: wrap; row-gap: var(--space-4); }

  /* Fondo oscuro detrás del menú lateral abierto: toca fuera para cerrarlo
     (antes no existía, así que el menú quedaba flotando sin forma clara
     de cerrarlo salvo el botón hamburguesa). */
  .tp-sidebar-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(10, 14, 24, 0.5);
    z-index: 90;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--transition-base);
  }
  .tp-sidebar-backdrop.is-visible {
    opacity: 1;
    pointer-events: auto;
  }
  /* Evita que el fondo se desplace detrás del menú mientras está abierto
     (bug clásico de doble-scroll en Safari/Chrome móvil). */
  body.tp-sidebar-open { overflow: hidden; }

  /* Objetivos táctiles más cómodos en pantallas de celular (mínimo 44x44,
     recomendación de accesibilidad táctil) y separación para evitar toques
     accidentales entre botones adyacentes. */
  .btn-icon { width: 44px; height: 44px; }
  .topbar__icon-btn { width: 44px; height: 44px; }
  .tp-modal__close { width: 44px; height: 44px; }
  .pagination button,
  .pagination a { width: 40px; height: 40px; }
  .table-actions,
  .btn-group { gap: 8px; }
}

@media (max-width: 480px) {
  .content { padding: var(--space-3); }
  .topbar  { padding: 0 var(--space-3); }
  .grid-stats,
  .grid-3,
  .grid-4 { grid-template-columns: 1fr; }
  .form-grid, .form-grid--3 { grid-template-columns: 1fr; }
  .page-header { flex-direction: column; align-items: stretch; }
  .card__header { flex-direction: column; align-items: flex-start; gap: var(--space-2); }
  .table-footer { flex-direction: column; align-items: stretch; }
}

/* Barras de filtros (.tp-filtros-bar) y buscadores: cada campo debe ocupar
   el 100% del ancho disponible en móvil, apilados verticalmente, sin el
   min-width fijo que en pantallas angostas los hacía desbordar. */
@media (max-width: 640px) {
  .tp-filtros-bar { flex-direction: column; align-items: stretch; }
  .tp-filtros-bar .form-field,
  .tp-filtros-bar select,
  .tp-filtros-bar input,
  .tp-filtros-bar .btn { min-width: 0; width: 100%; }
  .filter-bar__search { min-width: 0 !important; width: 100%; }
}

/* iOS Safari hace zoom automático de toda la página al enfocar un campo
   cuyo font-size calculado es menor a 16px. Por eso, en pantallas de
   celular/tablet chico, forzamos 16px en todos los campos editables. */
@media (max-width: 768px) {
  input, select, textarea { font-size: 16px; }
}

@media (max-width: 360px) {
  html { font-size: 15px; }
  .stat-card__value { font-size: 1.25rem; }
}

/* Dropdown de notificaciones — reglas BASE (escritorio).
   IMPORTANTE: estas reglas deben ir físicamente ANTES del @media de abajo.
   Como ambos bloques usan el mismo selector (.tp-dropdown, .tp-dropdown-wrap),
   tienen exactamente la misma especificidad; en CSS, a igual especificidad
   gana la regla que aparece MÁS ABAJO en el archivo, sin importar si está
   dentro de un @media o no (mientras la condición del @media siga
   cumpliéndose). Antes este bloque base estaba escrito más abajo que el
   @media del bottom-sheet, así que en celular/tablet la regla base
   "ganaba" por orden de aparición y pisaba position:fixed, transform,
   etc. — esto era la causa real de que la campanita/el sobre no
   funcionaran en ningún dispositivo. Moviendo este bloque antes del
   @media, la cascada vuelve a ser la esperada: el @media (que va después)
   manda en pantallas chicas, y este bloque manda en escritorio. */
.tp-dropdown {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  width: 290px;
  max-width: calc(100vw - 32px); /* red de seguridad en ventanas angostas de escritorio o con zoom del navegador */
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  z-index: 220;
  overflow: hidden;
  transform-origin: top right;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateY(-6px) scale(0.98);
  transition: opacity 0.15s ease, transform 0.15s ease, visibility 0s linear 0.15s;
}

.tp-dropdown.is-open {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateY(0) scale(1);
  transition: opacity 0.15s ease, transform 0.15s ease;
}

.tp-dropdown__handle { display: none; }

.tp-dropdown-wrap { position: relative; display: inline-flex; }

/* El dropdown de notificaciones/pendientes normalmente se ancla al ícono
   que lo abre (right: 0 respecto a ese ícono). En celular eso se rompía
   de dos formas: el panel de 290px quedaba cortado o se salía de la
   pantalla, y además "Pendientes de atención" quedaba casi pegado al
   borde y era difícil de tocar/cerrar bien.
   En vez de seguir anclándolo al ícono, en pantallas de celular/tablet
   chico se convierte en un panel tipo "hoja inferior" (bottom sheet):
   sube desde abajo, ocupa todo el ancho, tiene una manija visual arriba
   y se puede cerrar deslizando hacia abajo (además de tocar el fondo
   oscuro, la tecla Escape o el mismo ícono). Ver script.js. */
@media (max-width: 768px) {
  .tp-dropdown-wrap { position: static; }

  .tp-dropdown {
    position: fixed;
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    max-width: none;
    display: flex;
    flex-direction: column;
    max-height: min(78vh, 78dvh);
    border: none;
    border-radius: 18px 18px 0 0;
    box-shadow: 0 -12px 32px rgba(10, 14, 24, 0.28);
    transform: translateY(100%);
    transform-origin: center bottom;
    transition: transform 0.28s cubic-bezier(0.32, 0.72, 0, 1), visibility 0s linear 0.28s;
    padding-bottom: max(var(--space-3), env(safe-area-inset-bottom));
  }

  .tp-dropdown.is-open {
    transform: translateY(0);
    transition: transform 0.28s cubic-bezier(0.32, 0.72, 0, 1);
  }

  /* Mientras se está arrastrando con el dedo, JS agrega esta clase y fija
     el desplazamiento en línea (--tp-drag-y): sin transición, para que
     el panel siga al dedo en tiempo real. */
  .tp-dropdown.is-dragging {
    transition: none;
    transform: translateY(var(--tp-drag-y, 0));
  }

  /* Manija de arrastre: la señal visual de "esto se desliza" */
  .tp-dropdown__handle {
    display: flex;
    justify-content: center;
    padding: 10px 0 4px;
    flex-shrink: 0;
    touch-action: none;
    cursor: grab;
  }
  .tp-dropdown__handle::before {
    content: "";
    width: 36px;
    height: 4px;
    border-radius: 999px;
    background: var(--color-border);
  }

  .tp-dropdown__header { flex-shrink: 0; }

  .tp-dropdown__list {
    flex: 1 1 auto;
    max-height: none;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
  }

  /* z-index 15: a propósito por DEBAJO del z-index:20 de .topbar. El
     panel (.tp-dropdown, z-index:220) vive DENTRO de .topbar, que crea
     su propio contexto de apilamiento (position:sticky + z-index). Ese
     220 solo compite puertas adentro de .topbar; hacia afuera, todo
     .topbar (con el panel ya incluido) pesa como un solo bloque al
     nivel de SU PROPIO z-index (20). Antes este fondo tenía z-index:215
     (por encima de 20), así que terminaba tapando TODO el bloque —
     panel de notificaciones incluido, no solo el resto de la pantalla,
     que era justo el reporte del cliente ("se vuelve opaco todo, no
     solo el fondo"). Con 15 (< 20), el fondo se queda por debajo de
     .topbar y de su panel, y solo oscurece el resto del contenido. */
  .tp-sheet-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(10, 14, 24, 0.5);
    z-index: 15;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.25s ease;
  }
  .tp-sheet-backdrop.is-visible {
    opacity: 1;
    pointer-events: auto;
  }

  body.tp-sheet-open { overflow: hidden; }
}

/* En pantallas muy angostas el store-select podía empujar el resto de
   acciones del topbar fuera de la pantalla (texto largo como "Bodega
   Central" sin ningún límite de ancho). Se acota y se recorta con "…". */
@media (max-width: 480px) {
  .topbar__actions { gap: 6px; }
  .topbar__store-select {
    max-width: 108px;
    padding: 7px 8px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

/* ---------------------------------------------------------------------
   12. INTERACTIVIDAD — MODAL, TOASTS, DROPDOWN
   --------------------------------------------------------------------- */

/* Con un <dialog class="tp-modal"> abierto (showModal()), el fondo por
   defecto del navegador se sigue pudiendo desplazar/hacer scroll detrás
   del modal (verificado). Se bloquea aquí, en cualquier tamaño de
   pantalla, no solo en móvil, ya que el problema también ocurre con
   mouse/trackpad en escritorio. Ver el bloque correspondiente en
   script.js que agrega/quita esta clase. */
body.tp-modal-open { overflow: hidden; }

/* Overlay + Modal */
.tp-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(10, 14, 24, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  z-index: 300;
  animation: tp-fade-in 0.15s ease;
}

.tp-modal {
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  width: min(480px, calc(100vw - 32px));
  max-height: min(88vh, 88dvh);
  flex-direction: column;
  overflow: hidden;
}

/* En pantallas muy angostas (< 480px) el modal usa casi todo el ancho/alto
   disponible en vez de dejar espacio muerto alrededor; el cuerpo sigue
   haciendo su propio scroll vertical (.tp-modal__body ya tiene overflow-y:
   auto) para que el contenido nunca se desborde de la pantalla. Aplica a
   TODAS las variantes (.tp-modal--ancho, .tp-camara-modal) porque todas
   heredan de .tp-modal. */
@media (max-width: 480px) {
  .tp-modal,
  .tp-modal--ancho,
  .tp-camara-modal {
    width: calc(100vw - 16px);
    max-height: min(96vh, 96dvh);
  }
  .tp-modal-overlay { padding: var(--space-2); }
}

.tp-modal__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--color-border-soft);
}

.tp-modal__header h3 { font-size: 1rem; margin: 0; }

.tp-modal__close {
  background: none;
  border: none;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  color: var(--color-text-secondary);
  width: 30px;
  height: 30px;
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
}

.tp-modal__close:hover { background: var(--color-bg); color: var(--color-text); }

.tp-modal__body { padding: var(--space-5); overflow-y: auto; }
.tp-modal__body .form-grid { margin-bottom: 0; }

.tp-modal__footer {
  padding: var(--space-3) var(--space-5);
  border-top: 1px solid var(--color-border-soft);
  display: flex;
  justify-content: flex-end;
  gap: var(--space-3);
}

.tp-modal__view-row {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  padding: 8px 0;
  border-bottom: 1px solid var(--color-border-soft);
  font-size: 0.85rem;
}

.tp-modal__view-row:last-child { border-bottom: none; }
.tp-modal__view-row span:first-child { color: var(--color-text-secondary); }
.tp-modal__view-row span:last-child  { font-weight: 600; text-align: right; }

/* Bloque de texto largo dentro de un modal "ver detalle" (ej. auditoría):
   a diferencia de .tp-modal__view-row (par etiqueta/valor en una sola
   línea, pensado para datos cortos), acá el contenido puede ser un
   párrafo entero, así que va en su propia línea con envoltura normal
   por palabra. */
.tp-modal__detalle-completo {
  margin-top: var(--space-3);
  padding: var(--space-3);
  background: var(--color-bg);
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-sm);
  font-size: 0.85rem;
  line-height: 1.5;
  overflow-wrap: break-word;
}

/* Enlace tipo "Ver más": se ve y se comporta como un hipervínculo (sin
   fondo ni borde de botón) para no competir visualmente con el texto
   corto de la celda, pero sigue siendo <button> por accesibilidad
   (teclado/lector de pantalla) en vez de un <a href="#">. */
.tp-link-btn {
  display: inline;
  padding: 0;
  border: none;
  background: none;
  color: var(--color-primary);
  font-size: inherit;
  font-weight: 600;
  text-decoration: underline;
  cursor: pointer;
  white-space: nowrap;
}
.tp-link-btn:hover { color: var(--color-primary-dark); }

@keyframes tp-fade-in { from { opacity: 0; } to { opacity: 1; } }

/* Dropdown de notificaciones
   Ya no depende del atributo [hidden] (display:none no se puede animar):
   el estado abierto/cerrado ahora lo controla la clase .is-open, así que
   tanto el fade de escritorio como el bottom-sheet de celular pueden
   transicionar suavemente en vez de aparecer/desaparecer de golpe.
   (Las reglas base .tp-dropdown / .tp-dropdown.is-open / .tp-dropdown-wrap
   / .tp-dropdown__handle viven más arriba, justo antes del @media del
   bottom-sheet — ver la nota ahí sobre el orden de cascada.) */
.tp-dropdown__header {
  padding: var(--space-3) var(--space-4);
  font-weight: 600;
  font-size: 0.84rem;
  border-bottom: 1px solid var(--color-border-soft);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

.tp-dropdown__badge {
  font-weight: 600;
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-primary);
  background: var(--color-primary-light);
  border-radius: 999px;
  padding: 2px 8px;
}

/* Pulso breve del punto de notificación cuando el polling detecta algo
   nuevo (transferencia, stock bajo, auditoría, etc.). */
@keyframes tpDotPulse {
  0%   { transform: scale(1);   box-shadow: 0 0 0 0 rgba(var(--color-danger-rgb, 220, 38, 38), 0.55); }
  60%  { transform: scale(1.35); box-shadow: 0 0 0 6px rgba(var(--color-danger-rgb, 220, 38, 38), 0); }
  100% { transform: scale(1);   box-shadow: 0 0 0 0 rgba(var(--color-danger-rgb, 220, 38, 38), 0); }
}
.tp-dot--pulse { animation: tpDotPulse 0.9s ease-out 2; }

.tp-dropdown__empty {
  padding: var(--space-5) var(--space-4);
  text-align: center;
  color: var(--color-text-secondary);
  font-size: 0.81rem;
}

.tp-dropdown__list { max-height: 320px; overflow-y: auto; }

.tp-dropdown__item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--color-border-soft);
  font-size: 0.81rem;
  color: var(--color-text-secondary);
}

.tp-dropdown__item:last-child { border-bottom: none; }
.tp-dropdown__item strong { color: var(--color-text); font-size: 0.83rem; }
.tp-dropdown__item time { font-size: 0.72rem; color: var(--color-text-secondary); }

.tp-dropdown__item--link {
  cursor: pointer;
  text-decoration: none;
  transition: background 0.15s ease;
}
.tp-dropdown__item--link:hover { background: var(--color-bg); }
.tp-dropdown__item--link span { color: var(--color-text); font-weight: 500; }

.topbar__icon-btn { position: relative; }

/* Toasts */
.tp-toast-stack {
  position: fixed;
  bottom: var(--space-5);
  right: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  z-index: 400;
}

.tp-toast {
  background: #1e1c18;
  color: #fff;
  padding: 11px 16px;
  border-radius: var(--radius-md);
  font-size: 0.84rem;
  box-shadow: var(--shadow-lg);
  animation: tp-toast-in 0.18s ease;
  max-width: 300px;
}

.tp-toast.tp-toast--success { background: var(--color-success); }
.tp-toast.tp-toast--danger  { background: var(--color-danger); }

/* Toast destacado de transferencias: color de acento propio + borde
   luminoso para que salte a la vista frente a los demás toasts. */
.tp-toast.tp-toast--transferencia {
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: var(--color-info);
  border: 1px solid rgba(255, 255, 255, 0.35);
  cursor: pointer;
  animation: tp-toast-in 0.18s ease, tp-toast-glow 1.4s ease-in-out 1;
}
.tp-toast.tp-toast--transferencia strong { font-size: 0.78rem; letter-spacing: 0.02em; }
.tp-toast.tp-toast--saliendo { opacity: 0; transform: translateX(12px); transition: var(--transition-base); }

@keyframes tp-toast-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes tp-toast-glow {
  0%   { box-shadow: var(--shadow-lg), 0 0 0 0 rgba(26, 111, 168, 0.55); }
  50%  { box-shadow: var(--shadow-lg), 0 0 0 8px rgba(26, 111, 168, 0); }
  100% { box-shadow: var(--shadow-lg), 0 0 0 0 rgba(26, 111, 168, 0); }
}

/* Filas vacías
   Antes esta celda sumaba var(--space-8) (56px) de relleno propio
   ADEMÁS del padding que ya trae .empty-state (56px 24px) por dentro,
   así que un simple ícono + una línea de texto terminaba envuelto en
   ~112px de aire arriba y abajo. Se veía como un bloque gris enorme
   y casi vacío, más notorio cuanto más ancha es la tarjeta (tablets
   y pantallas grandes). Se deja que .empty-state maneje su propio
   espacio y aquí solo se agrega el padding lateral de la celda. */
.tp-empty-row td { padding: 0 var(--space-4) !important; }

/* Placeholder de tabs */
.tp-tab-placeholder {
  text-align: center;
  padding: var(--space-8) var(--space-5);
  color: var(--color-text-secondary);
  font-size: 0.87rem;
}

/* ---------------------------------------------------------------------
   13. ALERTAS FLASH Y <dialog> NATIVO
   --------------------------------------------------------------------- */
.alert {
  padding: 11px 15px;
  border-radius: var(--radius-md);
  font-size: 0.85rem;
  margin-bottom: var(--space-4);
  border: 1px solid transparent;
  animation: tp-fade-in 0.2s ease, tp-alert-out 0.25s ease 4s forwards;
}

.alert-success { background: var(--color-success-light); color: var(--color-success); border-color: var(--color-success); }
.alert-danger  { background: var(--color-danger-light);  color: var(--color-danger);  border-color: var(--color-danger); }
.alert-info    { background: var(--color-info-light);    color: var(--color-info);    border-color: var(--color-info); }

@keyframes tp-alert-out {
  from { opacity: 1; }
  to   { opacity: 0; max-height: 0; padding-top: 0; padding-bottom: 0; margin-bottom: 0; overflow: hidden; }
}

/* <dialog> nativo */
dialog.tp-modal:not([open]) {
  display: none;
}

dialog.tp-modal {
  /* El <dialog> nativo hereda CanvasText (blanco en modo oscuro del sistema);
     se fija al color del tema para que nunca quede texto blanco sobre fondo claro. */
  color: var(--color-text);
}

dialog.tp-modal[open] {
  display: flex;
  border: none;
  padding: 0;
  inset: 0;
  margin: auto;
  animation: tp-fade-in 0.15s ease;
}

dialog.tp-modal::backdrop {
  background: rgba(10, 14, 24, 0.6);
  animation: tp-fade-in 0.15s ease;
}

.tp-modal__form    { display: contents; }

.tp-form-actions {
  padding: var(--space-3) var(--space-5);
  padding-bottom: max(var(--space-3), env(safe-area-inset-bottom));
  border-top: 1px solid var(--color-border-soft);
  display: flex;
  justify-content: flex-end;
  gap: var(--space-3);
}

.tp-inline-form .form-grid { margin-bottom: 0; }

/* ------------------------------------------------------------
   Módulo de variantes de producto (color + talla) — productos.php
   ------------------------------------------------------------ */
.tp-modal--ancho {
  width: min(720px, calc(100vw - 32px));
}

.tp-variantes-editor {
  margin-top: var(--space-4);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border-soft);
}

.tp-color-picker {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 10px 0 14px;
}

.tp-swatch-btn {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 2px solid var(--color-border-soft);
  cursor: pointer;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.06) inset;
  transition: transform 0.1s ease, border-color 0.1s ease;
}

.tp-swatch-btn:hover { transform: scale(1.08); }

.tp-swatch-btn.is-active {
  border-color: var(--color-primary, #2f6fed);
  box-shadow: 0 0 0 2px var(--color-primary, #2f6fed);
}

.tp-swatch-dot {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  border: 1px solid rgba(0,0,0,0.15);
  vertical-align: middle;
  margin-right: 4px;
}

.tp-swatch-row {
  display: flex;
  align-items: center;
  gap: 4px;
}

.tp-variantes-tabla-wrap {
  max-height: 260px;
  overflow-y: auto;
}

.tp-variantes-tabla th, .tp-variantes-tabla td {
  padding: 6px 8px;
  font-size: 0.82rem;
}

/* ------------------------------------------------------------
   Resumen por variante y filtros — inventario.php
   ------------------------------------------------------------ */
.tp-resumen-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 18px;
}

.tp-resumen-fila {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 0;
  font-size: 0.82rem;
  border-bottom: 1px dashed var(--color-border-soft);
}

.tp-resumen-fila strong { margin-left: auto; }

.tp-filtros-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 12px;
}

.tp-filtros-bar .form-field { min-width: 160px; margin-bottom: 0; }

/* ---------------------------------------------------------------------
   14. ESCANEO POR CÁMARA (Fase 5)
   El modal usa <dialog class="tp-modal tp-camara-modal"> — el MISMO
   patrón nativo (showModal()/close(), bloque 13 de arriba) que usan
   todos los demás modales del proyecto (bodega.php, caja.php,
   productos.php, etc.). Este bloque solo agrega lo específico del
   visor de video; .tp-modal/.tp-modal__*/.tp-form-actions ya cubren
   el resto (fondo, tamaño, header, footer).
   --------------------------------------------------------------------- */
.tp-camara-modal { width: min(420px, calc(100vw - 32px)); }

.tp-camara-body { display: flex; flex-direction: column; gap: var(--space-3); }

.tp-camara-video-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 3;
  background: #000;
  border-radius: var(--radius-md);
  overflow: hidden;
}

.tp-camara-video { width: 100%; height: 100%; object-fit: cover; display: block; }

.tp-camara-visor {
  position: absolute;
  inset: 12% 10%;
  border: 2px solid rgba(255, 255, 255, 0.85);
  border-radius: var(--radius-sm);
  pointer-events: none;
  box-shadow: 0 0 0 999px rgba(0, 0, 0, 0.28);
}

.tp-camara-flash {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.12s ease;
}

.tp-camara-flash--activo { opacity: 1; }
.tp-camara-flash--exito  { background: rgba(58, 158, 108, 0.35); }
.tp-camara-flash--error  { background: rgba(196, 62, 50, 0.35); }

.tp-camara-estado {
  margin: 0;
  font-size: 0.85rem;
  color: var(--color-text-secondary);
  min-height: 1.2em;
}

.tp-camara-manual-aviso { margin: 0; font-size: 0.85rem; }

.tp-camara-footer { flex-wrap: wrap; }

/* ================================================================
   15. CARRITO DE VENTA — INTEGRACIÓN CON ESCANEO (Fase 6)
   Lista de líneas del carrito en la tarjeta "Resumen del carrito"
   de ventas.php, más el toast de advertencia (stock insuficiente)
   que no existía todavía — reutiliza el mismo componente .tp-toast
   ya usado por transferencias y por esta misma fase para éxito/error.
   ================================================================ */
.tp-carrito-lista {
  list-style: none;
  margin: 0 0 12px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.tp-carrito-linea {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface-alt, var(--color-surface));
  transition: background 0.15s ease;
}

.tp-carrito-linea--nueva {
  animation: tp-carrito-linea-in 0.25s ease;
}

@keyframes tp-carrito-linea-in {
  from { background: var(--color-success); opacity: 0.4; }
  to   { background: var(--color-surface-alt, var(--color-surface)); opacity: 1; }
}

.tp-carrito-linea__info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.tp-carrito-linea__nombre { font-weight: 600; font-size: 0.88rem; }
.tp-carrito-linea__detalle { font-size: 0.78rem; color: var(--color-text-secondary); }

.tp-carrito-linea__acciones { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.tp-carrito-linea__cantidad {
  width: 48px;
  text-align: center;
  padding: 4px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: 0.85rem;
}

.tp-carrito-linea__quitar {
  background: none;
  border: none;
  color: var(--color-danger);
  cursor: pointer;
  font-size: 1rem;
  line-height: 1;
  padding: 4px 6px;
}

.tp-carrito-linea--advertencia {
  border-color: var(--color-warning, #c98a1f);
}

.tp-carrito-total {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 10px;
  border-top: 1px dashed var(--color-border);
  font-size: 0.95rem;
}

/* Toast de advertencia (stock justo/insuficiente): no existía ninguna
   variante ámbar del componente .tp-toast, solo success/danger. */
.tp-toast.tp-toast--warning { background: var(--color-warning, #c98a1f); }

/* ---------------------------------------------------------------------
   19. ENDURECIMIENTO RESPONSIVE — zoom (navegador Ctrl+/- o pellizco táctil)
   --------------------------------------------------------------------- */
/*
   El zoom del navegador reduce el ancho de pantalla EFECTIVO en px CSS
   (a 200% de zoom, una pantalla de 1024px "se ve" como ~512px), así que
   los mismos media queries de móvil ya cubren ese caso — pero solo si
   nada dentro de un contenedor flex/grid genera desborde horizontal.
   Por defecto, los hijos de flex/grid tienen min-width:auto, es decir NO
   se encogen más allá del contenido más largo que tengan adentro (un
   correo, una referencia de producto, un nombre largo). Eso es lo que
   normalmente "rompe" el layout al hacer zoom in, no el zoom en sí.
*/
.app-shell > *,
.content > *,
.grid-2 > *, .grid-3 > *, .grid-4 > *, .grid-stats > *, .grid-auto > *,
.form-grid > *, .form-grid--3 > *,
.card__header > *, .page-header > *,
.topbar > *, .store-card__header > *, .settings-row > *,
.flex > *, .flex-col > * {
  min-width: 0;
}

/* Texto largo sin espacios (emails, referencias, SKUs, URLs) debe poder
   partirse en vez de forzar scroll horizontal fuera de .table-scroll. */
.card, .content, .stat-card, .form-field, .page-header,
.data-table td, .data-table th,
.topbar__breadcrumb h1, .tp-dropdown__item, .settings-row__label {
  overflow-wrap: break-word;
  word-break: break-word;
}

/* Nada dentro del área de contenido debe exceder el 100% del viewport
   visible, sin importar el nivel de zoom aplicado. */
.content, .card, .form-grid, .form-grid--3,
.grid-2, .grid-3, .grid-4, .grid-stats {
  max-width: 100%;
}

/* ================================================================
   16. BOTÓN DE ESCANEO POR CÁMARA (disparador de TpCamaraEscaneo)
   El motor de la Fase 5 (barcode_scanner_camara.js) existía pero
   ninguna página tenía un botón visible para abrirlo. Este bloque da
   estilo al botón (icono de cámara) y a la fila que lo ubica junto al
   campo de código de barras, reutilizando la misma variable de bordes/
   radios/colores que el resto del sistema de diseño.
   ================================================================ */
.tp-scan-row {
  display: flex;
  align-items: stretch;
  gap: var(--space-2);
}

.tp-scan-row > .filter-bar__search,
.tp-scan-row > input {
  flex: 1 1 auto;
  min-width: 0;
}

.btn-scan-camara {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text-secondary);
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast);
}

.btn-scan-camara:hover,
.btn-scan-camara:focus-visible {
  background: var(--color-primary-soft);
  color: var(--color-primary);
  border-color: var(--color-primary);
  outline: none;
}

.btn-scan-camara svg { width: 19px; height: 19px; display: block; }

/* Variante para cuando el botón va junto a un .tp-producto-row__btn de
   texto (productos.php): mismo alto que ese botón, sin ancho fijo. */
.tp-producto-row__btn.btn-scan-camara { width: 42px; padding: 0; }

/* .tp-input: campo de escaneo "grande" usado en recepción y
   transferencias. Antes solo tenía padding/font-size inline y ningún
   borde/fondo propio (heredaba el estilo nativo del navegador). */
.tp-input {
  width: 100%;
  box-sizing: border-box;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text);
}

.tp-input:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--color-primary-soft);
}

/* =====================================================================
   CORRECCIONES DE LA AUDITORÍA (19-sep-2026)
   ===================================================================== */

/* --- 2.1 #1 · Menú lateral abierto por defecto en móvil/tablet ---------
   El menú ya se comportaba como panel deslizante (cerrado por defecto),
   pero solo por debajo de 768px. Entre 769px y 1024px seguía ocupando
   una columna fija de la rejilla, que en un celular grande o una tablet
   en vertical se ve exactamente como "el menú está abierto y tapa el
   contenido". Aquí se extiende el comportamiento deslizante hasta
   1024px: el menú SIEMPRE empieza cerrado y solo se abre al tocar el
   botón de menú del topbar. */
@media (max-width: 1024px) {
  .app-shell { grid-template-columns: 1fr; }

  .sidebar {
    position: fixed;
    left: 0; top: 0; bottom: 0;
    width: 260px;
    max-width: 85vw;
    transform: translateX(-100%);
    transition: transform 0.42s var(--ease-spring);
    z-index: 100;
    height: 100%;
    height: 100dvh;
    padding-bottom: max(var(--space-4), env(safe-area-inset-bottom));
    box-shadow: 0 0 40px rgba(0, 0, 0, 0.35);
  }
  .sidebar.is-open    { transform: translateX(0); }
  .sidebar.is-dragging { transition: none; }

  /* En este rango el menú es un panel completo, así que los textos que el
     modo "riel de iconos" ocultaba vuelven a mostrarse. */
  .sidebar__brand-text,
  .sidebar__section-label,
  .sidebar__link span.link-text,
  .sidebar__user-name,
  .sidebar__user-role { display: block; }
  .sidebar__brand { justify-content: flex-start; padding-left: var(--space-2); }
  .sidebar__link  { justify-content: flex-start; }
  .sidebar__user  { justify-content: flex-start; }

  /* El botón hamburguesa debe existir en todo el rango en el que el menú
     está oculto; si no, no habría forma de abrirlo. */
  .topbar__menu-toggle { display: flex; }

  .tp-sidebar-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(10, 14, 24, 0.5);
    z-index: 90;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--transition-base);
  }
  .tp-sidebar-backdrop.is-visible { opacity: 1; pointer-events: auto; }
  body.tp-sidebar-open { overflow: hidden; }
}

/* --- 2.1 #2 · "Recordarme" solapado con "¿Olvidaste tu contraseña?" ----
   La fila era un flex rígido en space-between: en pantallas angostas los
   dos textos se pisaban. Ahora puede envolver, y por debajo de 420px se
   apila verticalmente. */
.login-box__options {
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
  row-gap: var(--space-2);
  line-height: 1.35;
}
.login-box__options .checkbox-row { flex: 0 1 auto; }
.login-box__options a { flex: 0 1 auto; white-space: nowrap; }

@media (max-width: 420px) {
  .login-box__options {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-3);
  }
  .login-box__options a { white-space: normal; }
}

/* --- 2.2 #4 · Floating labels con fondo blanco sobre la card oscura ----
   Los campos del login heredaban el fondo claro de --color-surface, y la
   etiqueta flotante dibujaba un rectángulo blanco sobre el vidrio oscuro.
   Dentro de .login-box los campos pasan a ser translúcidos y la etiqueta
   deja de pintar fondo. */
.login-box .field-float input,
.login-box .field-float select {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.18);
  color: #ffffff;
}
.login-box .field-float input::placeholder { color: rgba(255, 255, 255, 0.35); }
.login-box .field-float input:focus,
.login-box .field-float select:focus {
  background: rgba(255, 255, 255, 0.1);
  border-color: var(--color-accent, #4f8cff);
}
.login-box .field-float label {
  background: transparent;
  padding: 0;
  color: rgba(255, 255, 255, 0.6);
}
.login-box .field-float input:focus + label,
.login-box .field-float input:not(:placeholder-shown) + label {
  color: rgba(255, 255, 255, 0.85);
  left: 14px;
}
/* Autocompletado de Chrome: evita el bloque amarillo/blanco sólido. */
.login-box .field-float input:-webkit-autofill,
.login-box .field-float input:-webkit-autofill:focus {
  -webkit-text-fill-color: #ffffff;
  -webkit-box-shadow: 0 0 0 1000px rgba(30, 34, 48, 0.95) inset;
  caret-color: #ffffff;
}

.login-box__hint {
  font-size: 0.74rem;
  color: rgba(255, 255, 255, 0.55);
  margin: -4px 0 2px;
}
.login-box__footer a { color: var(--color-accent, #4f8cff); font-weight: 600; }

/* =====================================================================
   COMPATIBILIDAD iOS / SAFARI + APP INSTALADA (19-sep-2026)
   El panel se había probado sobre todo en Chrome. Este bloque cubre lo
   que Safari (iPhone/iPad/Mac) necesita con prefijo propio, y el modo
   "pantalla de inicio" (standalone), donde no hay barra del navegador y
   el contenido queda debajo de la barra de estado del sistema.
   ===================================================================== */

/* --- 1. Alto real de pantalla en Safari iOS --------------------------
   Safari antiguo (iOS 15 y anteriores) no entiende 100dvh y se queda con
   100vh, que incluye la barra inferior → la página quedaba cortada.
   -webkit-fill-available sí funciona ahí. El orden importa: cada regla
   posterior pisa a la anterior solo si el navegador la entiende. */
@supports (-webkit-touch-callout: none) {
  body,
  .app-shell,
  .login-page { min-height: -webkit-fill-available; }
  .sidebar    { height: -webkit-fill-available; }
}

/* --- 2. Prefijos -webkit- que Safari exige --------------------------- */
.login-box,
.tp-dropdown,
.tp-modal__dialog {
  -webkit-backdrop-filter: blur(10px);
}

.table-scroll,
.tp-modal__body,
.sidebar,
.content {
  -webkit-overflow-scrolling: touch; /* inercia de scroll en iOS */
}

/* iOS pinta un flash gris al tocar cualquier elemento; se reemplaza por
   los estados :active propios del diseño. */
a, button, .btn, .sidebar__link, label, summary {
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}

/* Safari no aplica la tipografía ni el borde del tema a los campos si no
   se le quita antes su apariencia nativa (los <select> y los botones de
   iOS se veían redondeados y grises, distintos a Chrome). */
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]),
select,
textarea {
  -webkit-appearance: none;
  appearance: none;
}
/* iOS le pone esquinas redondeadas y degradado propio a los botones. */
.btn, button.btn { -webkit-appearance: none; appearance: none; }
/* La flecha del select la dibuja el navegador; al quitar la apariencia
   nativa hay que devolverla a mano para que no quede un campo "pelado". */
select,
.field-float select,
.filter-bar select,
.tp-filtros-bar select,
.topbar__store-select,
.form-field select {
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 18px) calc(50% + 2px), calc(100% - 13px) calc(50% + 2px);
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 34px;
}

/* --- 3. Barra de estado en modo app instalada ------------------------
   Con apple-mobile-web-app-status-bar-style=black-translucent el sistema
   dibuja la hora y la batería ENCIMA de la página. Sin este relleno, el
   topbar y el login quedaban tapados por la barra de estado del iPhone. */
@media (display-mode: standalone), (display-mode: minimal-ui) {
  .topbar {
    height: auto;
    min-height: var(--topbar-height);
    padding-top: env(safe-area-inset-top, 0px);
  }
  .sidebar      { padding-top: max(var(--space-4), env(safe-area-inset-top)); }
  .login-main,
  .login-aside  { padding-top: max(var(--space-6), env(safe-area-inset-top)); }
  .content      { padding-bottom: max(var(--space-4), env(safe-area-inset-bottom)); }
  /* En la app instalada no hay barra de navegador: el texto no debe poder
     seleccionarse por accidente al mantener pulsado, como en una app real.
     Los campos y el contenido de tablas sí siguen siendo seleccionables. */
  .sidebar, .topbar, .btn {
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
  }
}
/* iOS antiguo no soporta la media query display-mode; el JS añade esta
   clase al <html> cuando detecta navigator.standalone. */
html.tp-standalone .topbar {
  height: auto;
  min-height: var(--topbar-height);
  padding-top: env(safe-area-inset-top, 0px);
}
html.tp-standalone .sidebar    { padding-top: max(var(--space-4), env(safe-area-inset-top)); }
html.tp-standalone .login-main { padding-top: max(var(--space-6), env(safe-area-inset-top)); }

/* Evita el "rebote" blanco al llegar al final del scroll en iOS, que
   delataba que era una página web dentro de un navegador. */
html {
  overscroll-behavior-y: none;
  background-color: var(--color-bg);
}

/* --- 4. Bloqueo de scroll de fondo con el menú abierto ---------------
   En iOS, overflow:hidden en el body NO detiene el scroll: hay que fijar
   el body. La posición se guarda y restaura desde script.js. */
body.tp-sidebar-open {
  position: fixed;
  width: 100%;
  overflow: hidden;
}

/* --- 5. <dialog> en Safari anterior a 15.4 ---------------------------
   Esos Safari no tienen showModal(): TODOS los modales del panel (nuevo
   producto, venta, caja, restablecer contraseña…) simplemente no abrían.
   script.js instala un sustituto que usa estas clases. */
dialog.tp-modal.tp-dialog-fallback {
  display: none;
  position: fixed;
  inset: 0;
  margin: auto;
  border: none;
  padding: 0;
  z-index: 1000;
}
dialog.tp-modal.tp-dialog-fallback.tp-dialog-abierto {
  display: flex;
  animation: tp-fade-in 0.15s ease;
}
.tp-dialog-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(10, 14, 24, 0.6);
  z-index: 999;
  animation: tp-fade-in 0.15s ease;
}

/* --- 6. Detalles de render que solo se veían mal en Safari ----------- */
/* Safari necesita altura explícita en los contenedores flex con scroll,
   si no, la tabla se desborda fuera de la tarjeta. */
.table-scroll { max-width: 100%; overflow-x: auto; }
/* Safari redondea distinto los inputs dentro de un grid: sin min-width:0
   un campo largo ensancha toda la rejilla y rompe el formulario. */
.form-grid > *,
.filter-bar > * { min-width: 0; }
/* Safari no hereda la fuente en los campos; sin esto los formularios se
   veían con la tipografía del sistema y no con la del panel. */
input, select, textarea, button { font-family: inherit; font-size: inherit; }
/* El gap en flex no existe en Safari < 14.1: se emula con margen. */
@supports not (gap: 1rem) {
  .login-box__options > * { margin-right: var(--space-3); }
  .table-actions > *,
  .btn-group > *          { margin-right: 8px; }
}

/* Safari iOS sin soporte de dvh: script.js calcula el alto real de la
   ventana y lo publica en --tp-vh. */
html.tp-ios .app-shell,
html.tp-ios .login-page,
html.tp-ios .sidebar { min-height: var(--tp-vh, 100vh); }
html.tp-ios .sidebar { height: var(--tp-vh, 100vh); }

/* ── Gestión dinámica admin (métodos de pago, transportadoras, tiendas) ── */
.tp-editable {
  cursor: pointer;
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  transition: background 0.15s;
  flex: 1;
}
.tp-editable:hover { background: var(--color-bg-hover, rgba(0,0,0,.06)); }
.form-input--inline {
  width: 100%;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 4px 8px;
  background: var(--color-bg-input, var(--color-bg));
  color: var(--color-text);
}


/* ═══════════════════════════════════════════════════════════════
   CALCULADORA FLOTANTE (calculadora.js)
   Usa solo los tokens de color del sistema, así que en modo oscuro
   cambia sola junto con el resto de la app. Ventana arrastrable en
   escritorio/tablet; en celular queda apoyada abajo y también se
   puede mover desde su barra de título.
   ═══════════════════════════════════════════════════════════════ */
.topbar__icon-btn.is-active {
  background: var(--color-primary-light);
  border-color: var(--color-primary-soft);
  color: var(--color-primary);
}

.tp-calc {
  position: fixed;
  z-index: 230;
  width: 332px;
  max-width: calc(100vw - 16px);
  max-height: calc(100vh - 24px);
  max-height: calc(100dvh - 24px);
  display: flex;
  flex-direction: column;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg), 0 0 0 1px rgba(0, 0, 0, 0.02);
  color: var(--color-text);
  font-family: var(--font-base);
  overflow: hidden;
  outline: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.tp-calc[hidden] { display: none; }
.tp-calc.is-dragging { box-shadow: 0 14px 40px rgba(10, 14, 24, 0.28); }
.tp-calc.is-dragging .tp-calc__head { cursor: grabbing; }

.tp-calc--sci { width: 420px; }

.tp-calc__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: 8px 8px 8px 12px;
  background: var(--color-sidebar-bg);
  color: var(--color-sidebar-text-active);
  cursor: grab;
  touch-action: none;
  flex-shrink: 0;
}
.tp-calc__title {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.84rem;
  font-weight: 600;
  min-width: 0;
}
.tp-calc__title svg { color: var(--color-sidebar-text); flex-shrink: 0; }
.tp-calc__head-actions { display: inline-flex; align-items: center; gap: 4px; }

.tp-calc__chip,
.tp-calc__close {
  font: inherit;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--color-sidebar-text);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  padding: 5px 8px;
  cursor: pointer;
  line-height: 1;
}
.tp-calc__chip:hover,
.tp-calc__close:hover { background: var(--color-sidebar-bg-hover); color: var(--color-sidebar-text-active); }
.tp-calc__chip[aria-pressed="true"] {
  background: var(--color-sidebar-bg-hover);
  color: var(--color-sidebar-text-active);
  border-color: rgba(143, 160, 184, 0.35);
}
.tp-calc__close { font-size: 0.85rem; padding: 5px 9px; }

.tp-calc__body {
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* Pantalla */
.tp-calc__screen {
  padding: 10px 14px 8px;
  background: var(--color-bg);
  border-bottom: 1px solid var(--color-border-soft);
  text-align: right;
  min-height: 92px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  flex-shrink: 0;
}
.tp-calc__meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 20px;
  flex-direction: row-reverse;
}
.tp-calc__mem {
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--color-accent);
  background: var(--color-accent-light);
  border-radius: var(--radius-sm);
  padding: 2px 6px;
}
.tp-calc__ang {
  font: inherit;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--color-primary);
  background: var(--color-primary-light);
  border: 1px solid var(--color-primary-soft);
  border-radius: var(--radius-sm);
  padding: 2px 7px;
  cursor: pointer;
}
.tp-calc__ang[hidden], .tp-calc__mem[hidden] { display: none; }
.tp-calc__expr {
  font-size: 0.95rem;
  color: var(--color-text-secondary);
  min-height: 1.4em;
  white-space: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  font-variant-numeric: tabular-nums;
}
.tp-calc__expr::-webkit-scrollbar { display: none; }
.tp-calc__res {
  font-size: 2.15rem;
  font-weight: 600;
  line-height: 1.2;
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
}
.tp-calc__res::-webkit-scrollbar { display: none; }
.tp-calc__res.is-error { font-size: 0.92rem; font-weight: 600; color: var(--color-danger); white-space: normal; line-height: 1.35; padding: 6px 0; }
.tp-calc__res.is-flash { animation: tpCalcFlash 0.35s ease-out; }
@keyframes tpCalcFlash { from { color: var(--color-primary); } to { color: var(--color-text); } }
.tp-calc--shake { animation: tpCalcShake 0.28s ease; }
@keyframes tpCalcShake { 25% { transform: translateX(-4px); } 75% { transform: translateX(4px); } }

/* Teclado */
.tp-calc__pad {
  display: grid;
  grid-template-columns: 1fr;
  gap: 6px;
  padding: 8px;
}
.tp-calc__pad[hidden] { display: none; }
.tp-calc__mem-row,
.tp-calc__sci,
.tp-calc__basic { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
.tp-calc__sci[hidden] { display: none; }

.tp-calc__k {
  font: inherit;
  font-size: 1rem;
  font-weight: 500;
  height: 46px;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text);
  cursor: pointer;
  padding: 0;
  transition: background var(--transition-fast), border-color var(--transition-fast), transform 0.06s ease;
  touch-action: manipulation;
}
.tp-calc__k:hover { background: var(--color-bg); }
.tp-calc__k:active { transform: scale(0.96); }
.tp-calc__k:focus-visible,
.tp-calc__chip:focus-visible,
.tp-calc__close:focus-visible,
.tp-calc__ang:focus-visible,
.tp-calc__hist-item:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 1px; }

.tp-calc__k--fn { background: var(--color-bg); color: var(--color-text-secondary); font-weight: 600; }
.tp-calc__k--fn:hover { background: var(--color-border-soft); }
.tp-calc__k--op { background: var(--color-primary-light); border-color: var(--color-primary-soft); color: var(--color-primary); font-size: 1.15rem; font-weight: 600; }
.tp-calc__k--op:hover { background: var(--color-primary-soft); }
.tp-calc__k--eq { background: var(--color-primary); border-color: var(--color-primary); color: #fff; font-size: 1.2rem; font-weight: 600; }
.tp-calc__k--eq:hover { background: var(--color-primary-dark); }
.tp-calc__k--mem { height: 30px; font-size: 0.75rem; font-weight: 600; color: var(--color-text-secondary); background: transparent; border-color: transparent; }
.tp-calc__k--mem:hover { background: var(--color-bg); }
.tp-calc__sci .tp-calc__k { height: 38px; font-size: 0.85rem; color: var(--color-text-secondary); background: var(--color-bg); }
.tp-calc__sci .tp-calc__k:hover { background: var(--color-border-soft); }

/* Modo científico en pantallas anchas: científico a la izquierda, básico a la derecha */
@media (min-width: 720px) {
  .tp-calc--sci { width: 560px; }
  .tp-calc--sci .tp-calc__pad {
    grid-template-columns: 1fr 1fr;
    grid-template-areas: "mem mem" "sci basic";
    column-gap: 10px;
    align-items: start;
  }
  .tp-calc--sci .tp-calc__grid-top { grid-area: mem; }
  .tp-calc--sci .tp-calc__sci { grid-area: sci; }
  .tp-calc--sci .tp-calc__basic { grid-area: basic; }
  .tp-calc--sci .tp-calc__sci .tp-calc__k { height: 46px; }
}

/* Historial */
.tp-calc__hist { padding: 8px; display: flex; flex-direction: column; gap: 6px; min-height: 200px; }
.tp-calc__hist[hidden] { display: none; }
.tp-calc__hist-top { display: flex; align-items: center; justify-content: space-between; font-size: 0.78rem; font-weight: 600; color: var(--color-text-secondary); padding: 0 4px; }
.tp-calc__hist-top .tp-calc__chip { color: var(--color-primary); }
.tp-calc__hist-top .tp-calc__chip:hover { background: var(--color-primary-light); color: var(--color-primary); }
.tp-calc__hist-list { display: flex; flex-direction: column; gap: 4px; max-height: 320px; overflow-y: auto; }
.tp-calc__hist-item {
  font: inherit;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  width: 100%;
  padding: 8px 10px;
  background: var(--color-surface);
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-md);
  cursor: pointer;
  text-align: right;
}
.tp-calc__hist-item:hover { background: var(--color-bg); }
.tp-calc__hist-e { font-size: 0.78rem; color: var(--color-text-secondary); word-break: break-all; }
.tp-calc__hist-v { font-size: 1.05rem; font-weight: 600; color: var(--color-text); }
.tp-calc__hist-empty { padding: var(--space-5) var(--space-3); text-align: center; font-size: 0.8rem; color: var(--color-text-muted); }

/* Celular */
@media (max-width: 600px) {
  .tp-calc, .tp-calc--sci { width: min(380px, calc(100vw - 16px)); }
  .tp-calc__k { height: 44px; }
  .tp-calc__sci .tp-calc__k { height: 34px; font-size: 0.8rem; }
  .tp-calc__k--mem { height: 26px; }
  .tp-calc__screen { min-height: 80px; padding-top: 8px; }
  .tp-calc__res { font-size: 2rem; }
  .tp-calc__chip { padding: 7px 9px; }
  .tp-calc__close { padding: 7px 11px; }
}
@media (max-height: 640px) and (max-width: 600px) {
  .tp-calc__k { height: 40px; }
  .tp-calc__sci .tp-calc__k { height: 32px; }
  .tp-calc__screen { min-height: 72px; }
}

@media (prefers-reduced-motion: reduce) {
  .tp-calc--shake, .tp-calc__res.is-flash { animation: none; }
  .tp-calc__k { transition: none; }
}


/* ═══════════════════════════════════════════════════════════════
   MENÚ DESPLEGABLE "EXPORTAR" (creditos.php)
   <details> nativo: funciona con teclado y sin JS; el script de la
   página solo lo cierra al tocar fuera. En celular se ancla al borde
   para no salirse de la pantalla.
   ═══════════════════════════════════════════════════════════════ */
.tp-menu { position: relative; display: inline-block; }
.tp-menu > summary { list-style: none; cursor: pointer; user-select: none; }
.tp-menu > summary::-webkit-details-marker { display: none; }
.tp-menu[open] > summary { background: var(--color-primary-light); }
.tp-menu__caret { font-size: 0.7rem; margin-left: 2px; transition: transform var(--transition-fast); }
.tp-menu[open] .tp-menu__caret { transform: rotate(180deg); }
.tp-menu__list {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  min-width: 250px;
  max-width: calc(100vw - 32px);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  padding: 4px;
  z-index: 60;
}
.tp-menu__list a {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  color: var(--color-text);
  text-decoration: none;
}
.tp-menu__list a:hover,
.tp-menu__list a:focus-visible { background: var(--color-primary-light); outline: none; }
.tp-menu__list strong { font-size: 0.86rem; font-weight: 600; }
.tp-menu__list small { font-size: 0.74rem; color: var(--color-text-secondary); }

/* ---------------------------------------------------------------------
   Ojito para ver/ocultar la contraseña (login). El botón va dentro de
   .field-float, después del <label>, así no rompe el selector
   "input:focus + label" que hace flotar la etiqueta.
   --------------------------------------------------------------------- */
.field-float--password input { padding-right: 46px; }
/* Edge/IE dibujan su propio ojito en los campos de contraseña: se oculta para no duplicarlo. */
.field-float--password input::-ms-reveal,
.field-float--password input::-ms-clear { display: none; }
.pw-toggle {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--color-text-secondary);
  cursor: pointer;
}
.pw-toggle:hover,
.pw-toggle:focus-visible { color: var(--color-primary); outline: none; }
.pw-toggle:focus-visible { box-shadow: 0 0 0 2px var(--color-primary-soft, rgba(79, 140, 255, 0.35)); }
.pw-toggle svg { width: 19px; height: 19px; display: block; }
.pw-toggle .pw-toggle__ojo-tachado { display: none; }
.pw-toggle.is-visible .pw-toggle__ojo { display: none; }
.pw-toggle.is-visible .pw-toggle__ojo-tachado { display: block; }
.login-box .pw-toggle { color: rgba(255, 255, 255, 0.6); }
.login-box .pw-toggle:hover,
.login-box .pw-toggle:focus-visible { color: #ffffff; }

/* ---------------------------------------------------------------------
   TOPBAR COMPACTO (celular)
   Si calculadora, modo claro/oscuro, campana y sobre no caben en el topbar,
   script.js le pone .is-compact y se ve un solo botón "Notificaciones y
   accesos" con un panel. El modo compacto completo solo aplica en pantallas
   de hasta 768px. En pantallas más anchas, si solo el buscador no cabe,
   pasa al menú (.is-search-menu) y los demás botones se quedan en la barra.
   --------------------------------------------------------------------- */
.tp-topbar-more { display: none; }

.topbar.is-compact .tp-topbar-more,
.topbar.is-search-menu .tp-topbar-more { display: inline-flex; }

/* Icono del botón: lupa si solo el buscador se movió al menú; campana si es el
   modo compacto completo (celular). */
.tp-more-icon--campana { display: none; }
.topbar.is-compact .tp-more-icon--lupa { display: none; }
.topbar.is-compact .tp-more-icon--campana { display: inline; }

/* Títulos del menú y accesos: sin modo compacto el menú solo trae el buscador. */
.tp-hdr-accesos { display: none; }
.topbar.is-compact .tp-hdr-buscar { display: none; }
.topbar.is-compact .tp-hdr-accesos { display: inline; }
.topbar:not(.is-compact) #tpTopbarMenu .tp-menu-item { display: none; }

/* Buscador cuando vive dentro del menú. */
.tp-menu-search-slot:empty { display: none; }
.topbar__search--en-menu {
  display: block;
  flex: none;
  width: auto;
  min-width: 0;
  max-width: none;
  margin: 0;
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--color-border-soft);
}
.tp-busq-res {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  width: max(100%, 320px);
  max-height: min(70vh, 480px);
  overflow-y: auto;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  z-index: 230;
}
.tp-busq-res[hidden] { display: none; }
.tp-busq-res__grupo {
  padding: 8px 14px 4px;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--color-text-muted);
}
.tp-busq-res__item {
  display: block;
  padding: 9px 14px;
  color: var(--color-text);
  text-decoration: none;
  font-size: 0.88rem;
  border-top: 1px solid var(--color-border-soft);
}
.tp-busq-res__item small { display: block; color: var(--color-text-secondary); font-size: 0.76rem; }
.tp-busq-res__item:hover,
.tp-busq-res__item.is-activo { background: var(--color-bg); }
.tp-busq-res__vacio { padding: 14px; font-size: 0.86rem; color: var(--color-text-secondary); }
.tp-busq-res__todos { font-weight: 600; color: var(--color-primary); }
.topbar__search--en-menu .tp-busq-res {
  position: static;
  width: auto;
  max-height: 40vh;
  margin-top: 8px;
  box-shadow: none;
}
.topbar__search--en-menu .icon-placeholder { left: calc(var(--space-4) + 12px); }
.topbar__search--en-menu input { font-size: 16px; /* evita el zoom automático en iPhone */ }
.topbar.is-compact #tpCalcToggle,
.topbar.is-compact #tpThemeToggle { display: none; }
/* Campana y sobre: se esconde solo el botón; el panel de cada uno sigue
   existiendo (se abre desde el menú) y no deja hueco en el topbar. */
.topbar.is-compact .tp-dropdown-wrap:not(.tp-topbar-more) { display: contents; }
.topbar.is-compact .tp-dropdown-wrap:not(.tp-topbar-more) > .topbar__icon-btn { display: none; }

/* Medición: sin encogerse ni partir líneas, para saber cuánto ocupa todo de verdad. */
.topbar.is-midiendo > * { flex: 0 0 auto; }
.topbar.is-midiendo .topbar__breadcrumb h1,
.topbar.is-midiendo .topbar__breadcrumb .eyebrow { white-space: nowrap; }

.tp-menu-item {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 12px;
  width: 100%;
  background: none;
  border: none;
  border-bottom: 1px solid var(--color-border-soft);
  text-align: left;
  font: inherit;
  font-size: 0.92rem;
  color: var(--color-text);
  cursor: pointer;
  padding: var(--space-3) var(--space-4);
  min-height: 48px;
}
.tp-menu-item:hover,
.tp-menu-item:focus-visible { background: var(--color-bg); outline: none; }
.tp-menu-item svg { flex-shrink: 0; color: var(--color-text-secondary); }
.tp-menu-item__icono {
  flex-shrink: 0;
  width: 18px;
  text-align: center;
  font-size: 1.05rem;
  line-height: 1;
  color: var(--color-text-secondary);
}
.tp-menu-item__texto { flex: 1 1 auto; min-width: 0; font-weight: 500; }
.tp-menu-item__punto {
  flex-shrink: 0;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--color-danger);
}
.tp-menu-item__punto[hidden] { display: none; }



/* ── Imagen de producto (formularios de alta) ─────────────────────── */
.tp-imagen-field__label { display:block; font-size:0.8rem; color:var(--color-text-secondary); margin-bottom:6px; }
.tp-imagen-field__row { display:flex; align-items:center; gap:var(--space-3, 12px); }
.tp-imagen-field__preview {
  width:64px; height:64px; flex:0 0 64px; border-radius:var(--radius-sm);
  border:1px dashed var(--color-border); background:var(--color-bg) center/cover no-repeat;
  display:flex; align-items:center; justify-content:center; color:var(--color-text-muted); font-size:0.7rem;
}
.table-thumb img { width:100%; height:100%; object-fit:cover; display:block; }

/* ── Inventario agrupado por referencia (desplegable de tallas) ───── */
.tp-inv-grupo > summary { list-style:none; cursor:pointer; display:flex; align-items:center; gap:10px; }
.tp-inv-grupo > summary::-webkit-details-marker { display:none; }
.tp-inv-grupo > summary::before { content:"▸"; font-size:0.8rem; color:var(--color-text-muted); transition:transform .15s; }
.tp-inv-grupo[open] > summary::before { transform:rotate(90deg); }
.tp-inv-detalle { margin:10px 0 4px 18px; }
.tp-inv-detalle table { min-width:auto; width:100%; }
tr.tp-inv-fila-detalle > td { background:var(--color-bg); padding-top:4px; padding-bottom:12px; }

/* ── Variante cortada de una talla lisa (editor de tallas) ────────── */
.tp-variantes-tabla tr.tp-fila-cortado td { background:var(--color-bg); }
.tp-variantes-tabla .tp-tambien-cortado { font-size:0.78rem; color:var(--color-text-secondary); white-space:nowrap; }

/* ── Selector Liso / Cortado del editor de tallas ─────────────────────
   Antes llevaba estilos en línea con "background:", que borraba la flecha
   del desplegable. Ahora la flecha se dibuja aquí y se ve siempre. */
.tp-variantes-tabla select.tp-select-tipo {
  width: 120px;
  padding: 4px 30px 4px 8px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background-color: var(--color-surface);
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 15px) calc(50% + 1px), calc(100% - 10px) calc(50% + 1px);
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  color: var(--color-text);
  font-size: 0.82rem;
  cursor: pointer;
}
.tp-variantes-tabla select.tp-select-tipo:disabled { cursor: not-allowed; opacity: 0.6; }


/* =====================================================================
   MOVIMIENTO Y LIQUID GLASS
   Va al FINAL del archivo a propósito: pisa reglas anteriores sin tocarlas.

   Principios para que se sienta fluido a 120 Hz (el navegador pinta a la
   frecuencia real de la pantalla; esto es lo que lo deja llegar ahí):
   - Todo lo que se mueve usa SOLO transform y opacity (los pinta la GPU,
     sin recalcular layout ni repintar la página).
   - Nada de "transition: all" ni de animar width/height/top/left.
   - El cambio claro/oscuro NO anima cientos de elementos a la vez: toma
     una "foto" de la pantalla y la revela con un círculo (View
     Transitions API, ver script.js), así no pierde fotogramas.
   - Todo respeta prefers-reduced-motion y prefers-reduced-transparency.
   ===================================================================== */

/* ---------------------------------------------------------------------
   A. BASE TÁCTIL Y SCROLL
   --------------------------------------------------------------------- */
html { -webkit-tap-highlight-color: transparent; }

a, button, .btn, summary, label, select,
input[type="checkbox"], input[type="radio"] {
  touch-action: manipulation; /* sin el retraso de ~300 ms del doble toque */
}

.sidebar,
.tp-dropdown,
.tp-modal__body,
dialog.tp-modal { overscroll-behavior: contain; }

.table-scroll { overscroll-behavior-x: contain; } /* evita el "atrás" accidental al deslizar una tabla */

/* ---------------------------------------------------------------------
   B. TRANSICIÓN CLARO <-> OSCURO
   B1. Con View Transitions (Chrome/Edge/Safari recientes): revelado
       circular desde el botón. Mientras dura, se apagan las transiciones
       individuales para que no peleen con la "foto".
   --------------------------------------------------------------------- */
html.tp-theme-vt::view-transition-old(root),
html.tp-theme-vt::view-transition-new(root) {
  animation: none;
  mix-blend-mode: normal;
}
html.tp-theme-vt::view-transition-old(root) { z-index: 1; }
html.tp-theme-vt::view-transition-new(root) { z-index: 2; }

html.tp-theme-vt *,
html.tp-theme-vt *::before,
html.tp-theme-vt *::after {
  transition: none !important;
}

/* B2. Respaldo para navegadores sin View Transitions: fundido corto y
       parejo en TODAS las superficies a la vez (no solo en 5 selectores). */
html.tp-theme-fade *,
html.tp-theme-fade *::before,
html.tp-theme-fade *::after {
  transition:
    background-color 0.32s var(--ease-out),
    color 0.32s var(--ease-out),
    border-color 0.32s var(--ease-out),
    fill 0.32s var(--ease-out),
    stroke 0.32s var(--ease-out),
    box-shadow 0.32s var(--ease-out) !important;
}

/* Ícono sol/luna: gira al cambiar (lo dispara script.js) */
#tpThemeToggleIcon { display: inline-block; }

/* ---------------------------------------------------------------------
   C. NAVEGACIÓN ENTRE PÁGINAS
   Fundido suave al pasar de una pantalla a otra (Chrome/Edge 126+ y
   Safari 18.2+). En el resto de navegadores simplemente se ignora.
   --------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
}
html:not(.tp-theme-vt)::view-transition-old(root) { animation: tp-vt-out 0.14s var(--ease-out) both; }
html:not(.tp-theme-vt)::view-transition-new(root) { animation: tp-vt-in 0.28s var(--ease-out) both; }
@keyframes tp-vt-out { to   { opacity: 0; } }
@keyframes tp-vt-in  { from { opacity: 0; } }

/* ---------------------------------------------------------------------
   D. INTERACCIONES: botones, filas, campos
   --------------------------------------------------------------------- */
.btn {
  transition:
    background-color var(--transition-fast),
    border-color var(--transition-fast),
    color var(--transition-fast),
    box-shadow var(--transition-fast),
    transform 0.22s var(--ease-spring);
}
.btn:active:not(:disabled) { transform: scale(0.97); }

.topbar__icon-btn {
  transition:
    background-color var(--transition-fast),
    border-color var(--transition-fast),
    color var(--transition-fast),
    box-shadow var(--transition-fast),
    transform 0.22s var(--ease-spring);
}
.topbar__icon-btn:active { transform: scale(0.92); }

.sidebar__link {
  transition:
    background-color var(--transition-fast),
    color var(--transition-fast),
    box-shadow var(--transition-fast),
    transform 0.22s var(--ease-spring);
}
.sidebar__link:active { transform: scale(0.98); }

.data-table tbody tr { transition: background-color var(--transition-fast); }

input:not([type="checkbox"]):not([type="radio"]),
select,
textarea {
  transition:
    border-color var(--transition-fast),
    box-shadow var(--transition-fast),
    background-color var(--transition-fast);
}

/* ---------------------------------------------------------------------
   E. LIQUID GLASS
   Receta: fondo translúcido + desenfoque con saturación + borde fino +
   reflejo en el borde superior + un destello diagonal muy suave.
   Solo en superficies que flotan sobre contenido (barra superior, menús,
   modales, avisos). Las tablas y tarjetas de datos se quedan sólidas
   para que se lean bien.
   --------------------------------------------------------------------- */

/* E1. Barra superior. El desenfoque va en un ::before porque backdrop-filter
       directamente sobre .topbar la volvería "bloque contenedor" de sus
       hijos position:fixed (los menús tipo hoja del celular se romperían). */
.topbar {
  background: var(--color-surface);                                   /* respaldo */
  background: color-mix(in srgb, var(--color-surface) 56%, transparent);
  border-bottom-color: var(--glass-edge);
  box-shadow: inset 0 -1px 0 var(--glass-edge), 0 10px 28px -20px rgba(10, 14, 24, 0.45);
}
.topbar::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: var(--glass-sheen);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
}

/* E2. Botones de ícono del topbar como "fichas" de vidrio */
.topbar__icon-btn {
  background: var(--glass-bg);
  border-color: var(--glass-edge);
  box-shadow: inset 0 1px 0 var(--glass-highlight), 0 1px 2px rgba(10, 14, 24, 0.08);
}
.topbar__icon-btn:hover { background: var(--glass-bg-strong); }

/* E3. Menús desplegables (campana, sobre, usuario) */
.tp-dropdown {
  background: var(--glass-bg-strong);
  background-image: var(--glass-sheen);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
}
.tp-dropdown__header { border-bottom-color: var(--glass-edge); }

@media (min-width: 769px) {
  .tp-dropdown {
    border-color: var(--glass-edge);
    box-shadow: var(--glass-shadow), inset 0 1px 0 var(--glass-highlight);
    transform: translateY(-8px) scale(0.96);
    transition: opacity 0.2s var(--ease-out), transform 0.3s var(--ease-spring), visibility 0s linear 0.3s;
  }
  .tp-dropdown.is-open {
    transform: translateY(0) scale(1);
    transition: opacity 0.2s var(--ease-out), transform 0.42s var(--ease-spring);
  }
}

/* Hoja inferior del celular: reflejo superior + fondo con desenfoque suave */
@media (max-width: 768px) {
  .tp-dropdown {
    border-top: 1px solid var(--glass-edge);
    box-shadow: 0 -14px 44px rgba(10, 14, 24, 0.32), inset 0 1px 0 var(--glass-highlight);
  }
  .tp-sheet-backdrop,
  .tp-sidebar-backdrop {
    -webkit-backdrop-filter: blur(5px);
    backdrop-filter: blur(5px);
  }
}

/* E4. Modales (<dialog>). Más opacos que los menús: llevan formularios. */
dialog.tp-modal {
  background: color-mix(in srgb, var(--color-surface) 76%, transparent);
  background-image: var(--glass-sheen);
  border: 1px solid var(--glass-edge);
  box-shadow: var(--glass-shadow), inset 0 1px 0 var(--glass-highlight);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
}
dialog.tp-modal .tp-modal__header,
dialog.tp-modal .tp-form-actions { border-color: var(--glass-edge); }

/* Entrada y SALIDA animadas del modal (Chrome 117+, Safari 17.4+, Firefox 129+).
   Donde no exista allow-discrete se usa solo la animación de entrada. */
dialog.tp-modal[open] { animation: tp-modal-in 0.42s var(--ease-spring) both; }
dialog.tp-modal::backdrop {
  background: rgba(10, 14, 24, 0.42);
  -webkit-backdrop-filter: blur(8px) saturate(1.2);
  backdrop-filter: blur(8px) saturate(1.2);
  animation: tp-fade-in 0.3s var(--ease-out) both;
}
@keyframes tp-modal-in {
  from { opacity: 0; transform: translateY(16px) scale(0.965); }
  to   { opacity: 1; transform: none; }
}

@supports (transition-behavior: allow-discrete) {
  dialog.tp-modal {
    opacity: 0;
    transform: translateY(16px) scale(0.965);
    transition:
      opacity 0.24s var(--ease-out),
      transform 0.42s var(--ease-spring),
      overlay 0.42s allow-discrete,
      display 0.42s allow-discrete;
  }
  dialog.tp-modal[open] {
    opacity: 1;
    transform: none;
    animation: none;
  }
  @starting-style {
    dialog.tp-modal[open] {
      opacity: 0;
      transform: translateY(16px) scale(0.965);
    }
  }

  dialog.tp-modal::backdrop {
    background-color: rgba(10, 14, 24, 0);
    -webkit-backdrop-filter: blur(0px);
    backdrop-filter: blur(0px);
    animation: none;
    transition:
      background-color 0.32s var(--ease-out),
      backdrop-filter 0.32s var(--ease-out),
      -webkit-backdrop-filter 0.32s var(--ease-out),
      overlay 0.32s allow-discrete,
      display 0.32s allow-discrete;
  }
  dialog.tp-modal[open]::backdrop {
    background-color: rgba(10, 14, 24, 0.42);
    -webkit-backdrop-filter: blur(8px) saturate(1.2);
    backdrop-filter: blur(8px) saturate(1.2);
  }
  @starting-style {
    dialog.tp-modal[open]::backdrop {
      background-color: rgba(10, 14, 24, 0);
      -webkit-backdrop-filter: blur(0px);
      backdrop-filter: blur(0px);
    }
  }
}

/* Cierre del modal sin saltos.
   Al cerrar, el <dialog> pierde [open] y con eso las reglas que lo centran
   (inset:0 + margin:auto); el navegador lo suelta en la esquina superior
   izquierda mientras dura la animación de salida y parecía que "se iba a la
   izquierda" sin cerrar. Se mantiene la misma geometría abierto y cerrado, y
   la salida es más corta que la entrada. */
dialog.tp-modal:not([open]) {
  position: fixed;
  inset: 0;
  margin: auto;
  border: none;
  padding: 0;
}
@supports (transition-behavior: allow-discrete) {
  dialog.tp-modal:not([open]) {
    transform: translateY(8px) scale(0.98);
    transition:
      opacity 0.18s var(--ease-out),
      transform 0.18s var(--ease-out),
      overlay 0.18s allow-discrete,
      display 0.18s allow-discrete;
  }
  dialog.tp-modal:not([open])::backdrop {
    transition:
      background-color 0.18s var(--ease-out),
      backdrop-filter 0.18s var(--ease-out),
      -webkit-backdrop-filter 0.18s var(--ease-out),
      overlay 0.18s allow-discrete,
      display 0.18s allow-discrete;
  }
}

/* Modal legado (overlay + .tp-modal): entrada con el mismo resorte */
.tp-modal-overlay { animation: tp-fade-in 0.28s var(--ease-out) both; }
.tp-modal-overlay > .tp-modal { animation: tp-modal-in 0.42s var(--ease-spring) both; }

/* E5. Avisos (toasts) */
.tp-toast {
  background: rgba(30, 28, 24, 0.80);
  background: color-mix(in srgb, #1e1c18 80%, transparent);
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: var(--glass-shadow), inset 0 1px 0 rgba(255, 255, 255, 0.22);
  -webkit-backdrop-filter: blur(14px) saturate(1.6);
  backdrop-filter: blur(14px) saturate(1.6);
  animation-duration: 0.38s;
  animation-timing-function: var(--ease-spring);
}
.tp-toast.tp-toast--success { background: color-mix(in srgb, var(--color-success) 84%, transparent); }
.tp-toast.tp-toast--danger  { background: color-mix(in srgb, var(--color-danger) 84%, transparent); }
.tp-toast.tp-toast--transferencia { background: color-mix(in srgb, var(--color-info) 86%, transparent); }
@keyframes tp-toast-in {
  from { opacity: 0; transform: translateY(10px) scale(0.97); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* E6. Pantalla de acceso: cristal translúcido y fusionado con el fondo.
   Sin brillo diagonal, borde casi invisible y poco tinte, para que el
   formulario parezca un vidrio sobre el cielo y no una tarjeta aparte. */
.login-box {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.015);
  border: 1px solid rgba(255, 255, 255, 0.07);
  box-shadow:
    0 12px 40px rgba(0, 0, 0, 0.22),
    inset 0 1px 0 rgba(255, 255, 255, 0.08);
  -webkit-backdrop-filter: blur(1.5px) saturate(1.5);
  backdrop-filter: blur(1.5px) saturate(1.5);
}

/* Texto legible sobre el cristal */
.login-box p.subtitle { color: rgba(255, 255, 255, 0.78); }
.login-box .login-box__footer { color: rgba(255, 255, 255, 0.68); }

/* E7. Detalles de reflejo en los elementos activos */
.btn-primary {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.24), 0 1px 2px rgba(10, 14, 24, 0.16);
}
.sidebar__link.is-active {
  background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.20), rgba(255, 255, 255, 0) 60%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.26), 0 8px 20px -8px color-mix(in srgb, var(--color-primary) 70%, transparent);
}

/* ---------------------------------------------------------------------
   F. ACCESIBILIDAD Y RESPALDOS
   --------------------------------------------------------------------- */

/* Sin soporte de backdrop-filter: superficies sólidas (nada se ve "raro") */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .topbar { background: var(--color-surface); }
  .tp-dropdown { background: var(--color-surface); background-image: none; }
  dialog.tp-modal { background: var(--color-surface); background-image: none; }
  .tp-toast { background: #1e1c18; }
  .tp-toast.tp-toast--success { background: var(--color-success); }
  .tp-toast.tp-toast--danger  { background: var(--color-danger); }
  .tp-toast.tp-toast--transferencia { background: var(--color-info); }
  .login-box { background: rgba(15, 17, 26, 0.92); }
}

/* Quien pidió "reducir transparencia" en su sistema: todo sólido */
@media (prefers-reduced-transparency: reduce) {
  .topbar { background: var(--color-surface); }
  .topbar::before { display: none; }
  .tp-dropdown, dialog.tp-modal { background: var(--color-surface); background-image: none; }
  .tp-dropdown, dialog.tp-modal, dialog.tp-modal::backdrop, .tp-toast, .login-box,
  .tp-sheet-backdrop, .tp-sidebar-backdrop {
    -webkit-backdrop-filter: none !important;
    backdrop-filter: none !important;
  }
}

/* Quien pidió "reducir movimiento": sin animaciones ni transiciones */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}


/* ---------------------------------------------------------------------
   G. CONFIGURACIÓN → SONIDOS
   --------------------------------------------------------------------- */
.tp-son-volumen__control {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 220px;
  max-width: 100%;
}
.tp-son-volumen__control output {
  min-width: 3.2em;
  text-align: right;
  font-weight: 600;
  font-size: 0.86rem;
  font-variant-numeric: tabular-nums;
  color: var(--color-text);
}
.tp-son-item__acciones {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-shrink: 0;
}

/* Control de volumen: pista con relleno hasta el valor actual */
#sonVolumen {
  -webkit-appearance: none;
  appearance: none;
  flex: 1;
  min-width: 120px;
  height: 22px;            /* área táctil cómoda; la pista visible es más fina */
  background: transparent;
  cursor: pointer;
  touch-action: pan-y;
}
#sonVolumen::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: var(--radius-pill);
  background: linear-gradient(to right,
    var(--color-primary) var(--tp-rango, 70%),
    var(--color-border) var(--tp-rango, 70%));
}
#sonVolumen::-moz-range-track {
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--color-border);
}
#sonVolumen::-moz-range-progress {
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--color-primary);
}
#sonVolumen::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 20px;
  height: 20px;
  margin-top: -7px;
  border-radius: 50%;
  border: 1px solid var(--glass-edge);
  background: #fff;
  box-shadow: 0 1px 4px rgba(10, 14, 24, 0.35), inset 0 1px 0 #fff;
  transition: transform 0.2s var(--ease-spring);
}
#sonVolumen::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 1px solid var(--glass-edge);
  background: #fff;
  box-shadow: 0 1px 4px rgba(10, 14, 24, 0.35);
}
#sonVolumen:active::-webkit-slider-thumb { transform: scale(1.15); }
#sonVolumen:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 4px; border-radius: var(--radius-pill); }

/* Con el interruptor general apagado, el resto de la tarjeta se atenúa
   (lo pinta :has; en navegadores sin :has simplemente no se atenúa). */
#secSonidos:has(#sonActivo:not(:checked)) .tp-son-volumen,
#secSonidos:has(#sonActivo:not(:checked)) .tp-son-item__acciones {
  opacity: 0.45;
}
.tp-son-volumen, .tp-son-item__acciones { transition: opacity var(--transition-base); }

@media (max-width: 600px) {
  #secSonidos .settings-row { flex-wrap: wrap; gap: var(--space-3); }
  .tp-son-volumen__control { width: 100%; }
}
