/* ============================================================================
   Sistema visual de Brainstock Pharma: vidrio, sombras, radios y movimiento.

   La idea en una linea: lo que FLOTA sobre el contenido es vidrio (barra
   lateral, barra superior, menus, notificaciones, modales, paleta, asistente,
   avisos); lo que se TRABAJA es solido (tarjetas, tablas, numeros,
   formularios), porque se lee todo el dia en el mostrador.

   Cada valor esta en DESIGN.md con su porque. Los colores de texto sobre
   vidrio estan verificados contra el peor fondo posible en
   pruebas/contraste_vidrio.py: si se toca un vidrio, se corre eso.

   Orden de las capas de seguridad, de afuera hacia adentro:
     1. sin backdrop-filter (navegador viejo)   -> fondos solidos
     2. prefers-reduced-transparency: reduce    -> fondos solidos
     3. prefers-reduced-motion: reduce          -> sin animaciones
   ========================================================================= */

:root {
  /* --- vidrio: color de cada nivel, con transparencia --- */
  --vidrio-oscuro: rgba(5, 38, 36, 0.87);      /* barra lateral */
  --vidrio-1: rgba(255, 255, 255, 0.72);       /* barra superior */
  --vidrio-2: rgba(255, 255, 255, 0.84);       /* menus, notificaciones */
  --vidrio-3: rgba(255, 255, 255, 0.90);       /* modales, paleta, asistente, avisos */

  /* --- el mismo nivel, solido: sin backdrop-filter o con transparencia reducida --- */
  --vidrio-oscuro-solido: #0b3532;
  --vidrio-1-solido: #f7fbfa;
  --vidrio-2-solido: #ffffff;
  --vidrio-3-solido: #ffffff;

  /* --- desenfoque por nivel: mas alto el nivel, mas separado del fondo --- */
  --desenfoque-1: 14px;
  --desenfoque-2: 22px;
  --desenfoque-3: 30px;
  --saturacion-vidrio: 170%;

  /* --- el borde del vidrio: una linea de luz arriba y un filo alrededor --- */
  --brillo-claro: inset 0 1px 0 rgba(255, 255, 255, 0.95), inset 0 0 0 1px rgba(255, 255, 255, 0.5);
  --brillo-oscuro: inset 0 1px 0 rgba(255, 255, 255, 0.10), inset 0 0 0 1px rgba(149, 236, 221, 0.10);
  --filo-claro: rgba(15, 60, 56, 0.09);
  /* reflejo: una luz suave que baja desde el borde de arriba */
  --reflejo-claro: linear-gradient(180deg, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0) 42%);
  --reflejo-oscuro: linear-gradient(180deg, rgba(149, 236, 221, 0.10), rgba(149, 236, 221, 0) 30%);

  /* --- sombras: una por altura, teñidas del verde de la marca --- */
  --sombra-0: 0 1px 2px rgba(11, 67, 64, 0.05);
  --sombra-1: 0 1px 2px rgba(11, 67, 64, 0.06), 0 6px 18px -8px rgba(11, 67, 64, 0.16);
  --sombra-2: 0 2px 6px rgba(11, 67, 64, 0.06), 0 16px 36px -12px rgba(11, 67, 64, 0.24);
  --sombra-3: 0 4px 12px rgba(11, 67, 64, 0.08), 0 30px 70px -18px rgba(11, 67, 64, 0.36);

  /* --- radios --- */
  --radio-control: 8px;     /* botones, inputs */
  --radio-tarjeta: 12px;    /* tarjetas, tablas */
  --radio-flotante: 16px;   /* menus, barra superior, avisos */
  --radio-panel: 20px;      /* barra lateral, modales, asistente */

  /* --- movimiento --- */
  --curva-salida: cubic-bezier(0.22, 1, 0.36, 1);     /* frena al llegar */
  --curva-resorte: cubic-bezier(0.34, 1.36, 0.64, 1); /* se pasa un poquito y vuelve */
  --dur-rapida: 140ms;   /* hover, press */
  --dur-media: 200ms;    /* cambios de estado */
  --dur-panel: 260ms;    /* un panel que aparece */

  /* --- fondo ambiental --- */
  --fondo-base: #f5faf9;
}


/* ----------------------------------------------------------------------------
   Fondo ambiental: para que el vidrio luzca tiene que haber algo atras.
   Cuatro manchas de la paleta sobre un blanco apenas verde. Es fixed a
   proposito: no se mueve al scrollear, asi que el navegador lo pinta una vez
   y no lo repinta en cada scroll.
   ------------------------------------------------------------------------- */
body.fondo-ambiental {
  background-color: var(--fondo-base);
}
body.fondo-ambiental::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(60vmax 52vmax at -6% -8%, rgba(47, 191, 172, 0.26), transparent 62%),
    radial-gradient(48vmax 42vmax at 104% 6%, rgba(149, 236, 221, 0.40), transparent 60%),
    radial-gradient(56vmax 50vmax at 86% 108%, rgba(23, 160, 142, 0.16), transparent 62%),
    radial-gradient(42vmax 42vmax at 8% 96%, rgba(201, 246, 238, 0.65), transparent 60%),
    var(--fondo-base);
}

/* Lo que se trabaja va solido sobre el fondo ambiental. En main las tablas,
   las filas de Alertas, las listas con borde y los estados vacios no tienen
   fondo propio: se apoyan en el gris casi blanco de la pagina y no hace falta.
   Sobre el degradado quedaban transparentes, contra la regla de que el vidrio
   es solo lo que flota. (Lo encontro contraste_real.py midiendo el fondo de
   la pagina: el texto de las tablas aparecia como texto sobre el degradado.) */
.fondo-ambiental table.brand,
.fondo-ambiental .fila-alerta,
.fondo-ambiental .divide-y.border,
.fondo-ambiental .estado-vacio {
  background-color: #ffffff;
}

/* El texto secundario que va directo sobre el fondo (la descripcion del
   encabezado, las fechas del periodo, los titulos de seccion, las ayudas, el
   link de "volver") pasa de slate-500 a slate-600: contra la zona mas
   saturada del degradado, slate-500 da 3,8:1 y no llega a AA. Adentro de una
   superficie solida slate-500 pasa, y no se toca. */
.fondo-ambiental .page-container .text-slate-500:not(:is(.card, .stat-tile, table, .fila-alerta, .divide-y, .estado-vacio, .modal, .drawer, [class*="alert-"]) *),
.fondo-ambiental .page-container .nav-link:not(:hover) {
  color: rgb(71, 85, 105); /* slate-600 */
}


/* ----------------------------------------------------------------------------
   Vidrio. Primero el caso seguro (solido), despues el vidrio de verdad solo
   donde el navegador lo soporta.
   ------------------------------------------------------------------------- */
.vidrio-oscuro {
  background-color: var(--vidrio-oscuro-solido);
  box-shadow: var(--brillo-oscuro), var(--sombra-3);
}
.vidrio-1, .vidrio-2, .vidrio-3 {
  border: 1px solid var(--filo-claro);
}
.vidrio-1 { background-color: var(--vidrio-1-solido); box-shadow: var(--brillo-claro), var(--sombra-1); }
.vidrio-2 { background-color: var(--vidrio-2-solido); box-shadow: var(--brillo-claro), var(--sombra-2); }
.vidrio-3 { background-color: var(--vidrio-3-solido); box-shadow: var(--brillo-claro), var(--sombra-3); }

@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .vidrio-oscuro {
    background: var(--reflejo-oscuro), var(--vidrio-oscuro);
    -webkit-backdrop-filter: blur(var(--desenfoque-2)) saturate(var(--saturacion-vidrio));
    backdrop-filter: blur(var(--desenfoque-2)) saturate(var(--saturacion-vidrio));
  }
  .vidrio-1 {
    background: var(--reflejo-claro), var(--vidrio-1);
    -webkit-backdrop-filter: blur(var(--desenfoque-1)) saturate(var(--saturacion-vidrio));
    backdrop-filter: blur(var(--desenfoque-1)) saturate(var(--saturacion-vidrio));
  }
  .vidrio-2 {
    background: var(--reflejo-claro), var(--vidrio-2);
    -webkit-backdrop-filter: blur(var(--desenfoque-2)) saturate(var(--saturacion-vidrio));
    backdrop-filter: blur(var(--desenfoque-2)) saturate(var(--saturacion-vidrio));
  }
  .vidrio-3 {
    background: var(--reflejo-claro), var(--vidrio-3);
    -webkit-backdrop-filter: blur(var(--desenfoque-3)) saturate(var(--saturacion-vidrio));
    backdrop-filter: blur(var(--desenfoque-3)) saturate(var(--saturacion-vidrio));
  }
}

/* Quien pidio menos transparencia en el sistema operativo recibe los mismos
   paneles, solidos. Va despues del @supports para ganarle. */
@media (prefers-reduced-transparency: reduce) {
  .vidrio-oscuro, .vidrio-1, .vidrio-2, .vidrio-3 {
    -webkit-backdrop-filter: none !important;
    backdrop-filter: none !important;
  }
  .vidrio-oscuro { background: var(--vidrio-oscuro-solido) !important; }
  .vidrio-1 { background: var(--vidrio-1-solido) !important; }
  .vidrio-2 { background: var(--vidrio-2-solido) !important; }
  .vidrio-3 { background: var(--vidrio-3-solido) !important; }
  body.fondo-ambiental::before { display: none; }
  /* lo que desenfoca sin ser un panel de vidrio: la barra de acciones de
     Venta (bg-white/95 backdrop-blur de Tailwind) */
  .backdrop-blur, [class*="backdrop-blur-"] {
    -webkit-backdrop-filter: none !important;
    backdrop-filter: none !important;
  }
  [data-barra-acciones] { background-color: #fff !important; }
}


/* ----------------------------------------------------------------------------
   Barra lateral: un panel de vidrio oscuro que flota, separado de los bordes.
   ------------------------------------------------------------------------- */
.barra-lateral {
  border-radius: var(--radio-panel);
  view-transition-name: barra-lateral;
}
@media (min-width: 1024px) {
  .barra-lateral {
    top: 12px !important;
    bottom: 12px !important;
    left: 12px !important;
    height: auto !important;
  }
  /* 256 de barra + 12 de margen a cada lado */
  .con-barra-lateral { padding-left: 280px; }
  /* En escritorio, detras de la barra lateral solo esta el fondo ambiental,
     que ya es un degradé suave: desenfocarlo no cambia nada que se vea, y es
     el area desenfocada mas grande de la pantalla. Se deja la transparencia
     y se saca el desenfoque. Asi quedan dos capas desenfocadas fijas (la
     barra superior y la gota) y a lo sumo una mas que se abre encima. */
  .barra-lateral.vidrio-oscuro {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}
@media (max-width: 1023.98px) {
  .barra-lateral {
    top: 8px !important;
    bottom: 8px !important;
    left: 8px !important;
    height: auto !important;
    max-width: calc(100vw - 16px);
  }
  /* El cajon se esconde con -translate-x-full de Tailwind; separado 8px del
     borde, -100% dejaria asomar una franja y la sombra. Se corre un poco mas
     tocando solo la variable, sin pisar el mecanismo de abrir y cerrar. */
  .barra-lateral.-translate-x-full { --tw-translate-x: calc(-100% - 24px); }
}

.barra-lateral .sidebar-link {
  border: 0;
  display: flex;
  align-items: center;
  gap: 12px;
  border-radius: 10px;
  padding: 8px 12px;
  font-size: 14px;
  line-height: 20px;
  font-weight: 500;
  color: #e6f3f1;
  transition: background-color var(--dur-rapida) ease, color var(--dur-rapida) ease;
}
.barra-lateral .sidebar-link svg { color: #a9d3cc; transition: color var(--dur-rapida) ease; }
.barra-lateral .sidebar-link:hover { background-color: rgba(255, 255, 255, 0.07); color: #ffffff; }
.barra-lateral .sidebar-link:hover svg { color: #c9f6ee; }
.barra-lateral .sidebar-link:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px rgba(92, 218, 200, 0.55);
}
/* la pantalla actual: una "gota" de vidrio claro adentro del oscuro */
.barra-lateral .sidebar-link.activo {
  color: #ffffff;
  background: linear-gradient(180deg, rgba(149, 236, 221, 0.22), rgba(149, 236, 221, 0.12));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.16), inset 0 0 0 1px rgba(149, 236, 221, 0.20);
}
.barra-lateral .sidebar-link.activo svg { color: #95ecdd; }
.barra-lateral .titulo-grupo {
  padding: 0 12px 4px;
  font-size: 12px;
  line-height: 16px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #b8dcd6;
}
.barra-lateral .control-lateral {
  border: 1px solid rgba(149, 236, 221, 0.16);
  background-color: rgba(255, 255, 255, 0.06);
  color: #e6f3f1;
  border-radius: var(--radio-control);
  transition: background-color var(--dur-rapida) ease, border-color var(--dur-rapida) ease;
}
.barra-lateral .control-lateral:hover { background-color: rgba(255, 255, 255, 0.10); border-color: rgba(149, 236, 221, 0.28); }
.barra-lateral .control-lateral:focus-visible { outline: none; box-shadow: 0 0 0 2px rgba(92, 218, 200, 0.55); }
.barra-lateral select.control-lateral option { color: #0f172a; }
.barra-lateral .separador-lateral { border-top: 1px solid rgba(149, 236, 221, 0.12); }
.barra-lateral .texto-secundario { color: #c4e3de; }


/* ----------------------------------------------------------------------------
   Barra superior: vidrio claro que flota arriba. El contenido pasa por
   debajo desenfocado, que es donde se ve que es vidrio. Es chica a proposito:
   lo que se desenfoca al scrollear es solo su franja.
   ------------------------------------------------------------------------- */
.barra-superior {
  border-radius: var(--radio-flotante);
  view-transition-name: barra-superior;
}
/* En escritorio la barra superior no queda pegada arriba al scrollear. Pegada
   y desenfocando, tenia que desenfocar toda la pagina que pasaba por debajo:
   medido con la CPU a 6x, retrasaba el primer pintado de Stock (la pantalla
   mas larga) en ~1,5 segundos. Sin quedar pegada nunca pasa contenido por
   debajo, detras solo esta el fondo ambiental, y el desenfoque sobra. La
   navegacion siempre visible ya la da la barra lateral.
   En el celular si queda pegada y desenfocada: tiene el boton del menu. */
@media (min-width: 1024px) {
  .barra-superior {
    position: relative !important;
    top: auto !important;
  }
  .barra-superior.vidrio-1 {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}


/* ----------------------------------------------------------------------------
   Capas que aparecen: menus, notificaciones, modales, paleta, asistente.
   Entran con un resorte corto desde su punto de origen.
   ------------------------------------------------------------------------- */
.menu-flotante {
  border-radius: var(--radio-flotante);
  animation: aparecerMenu var(--dur-panel) var(--curva-resorte);
  transform-origin: top right;
}
@keyframes aparecerMenu {
  from { opacity: 0; transform: translateY(-6px) scale(0.96); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* El velo de atras de un modal oscurece pero NO desenfoca: desenfocar la
   pantalla entera es lo mas caro que se le puede pedir a una PC vieja, y el
   modal ya se separa solo con su propio vidrio y su sombra. */
.velo-modal {
  background-color: rgba(6, 42, 40, 0.30);
  animation: aparecerVelo var(--dur-media) var(--curva-salida);
}
@keyframes aparecerVelo { from { opacity: 0; } to { opacity: 1; } }

.panel-modal {
  border-radius: var(--radio-panel);
  animation: aparecerModal var(--dur-panel) var(--curva-resorte);
}
@keyframes aparecerModal {
  from { opacity: 0; transform: translateY(8px) scale(0.965); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

.panel-asistente {
  border-radius: var(--radio-panel);
  animation: aparecerAsistente var(--dur-panel) var(--curva-resorte);
  transform-origin: bottom right;
}
@keyframes aparecerAsistente {
  from { opacity: 0; transform: translateY(10px) scale(0.94); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}


/* ----------------------------------------------------------------------------
   Boton del asistente: una gota de vidrio teñida de la marca. En Chrome y
   Edge ademas refracta lo que tiene detras (ver .con-refraccion abajo).
   ------------------------------------------------------------------------- */
.gota {
  background: linear-gradient(160deg, #17a08e, #0a655d);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.35), inset 0 -2px 6px rgba(3, 37, 35, 0.35),
              0 8px 22px -6px rgba(10, 101, 93, 0.55);
  transition: transform var(--dur-media) var(--curva-resorte), box-shadow var(--dur-media) ease;
}
.gota:hover { transform: translateY(-2px) scale(1.04); }
.gota:active { transform: scale(0.94); }

/* Refraccion: el filtro SVG #refraccion deforma lo que esta detras, como una
   lente. Solo en Chromium (backdrop-filter con url()): lo decide un script
   que agrega .con-refraccion al <html>. En el resto de los navegadores la
   gota se ve igual, sin la deformacion.

   Solo al pasar el mouse o con foco, no todo el tiempo: la gota esta fija
   sobre la pagina que scrollea, y un filtro SVG no lo acelera la placa de
   video. Medido con la CPU a 6x, prendida todo el tiempo retrasaba el primer
   pintado de Stock ~0,8 segundos. En reposo es una gota solida y no cuesta
   nada; la lente aparece cuando uno va a usarla. */
.con-refraccion .gota:hover,
.con-refraccion .gota:focus-visible {
  background: linear-gradient(160deg, rgba(23, 160, 142, 0.78), rgba(10, 101, 93, 0.86));
  -webkit-backdrop-filter: url(#refraccion) blur(1.5px) saturate(160%);
  backdrop-filter: url(#refraccion) blur(1.5px) saturate(160%);
}


/* ----------------------------------------------------------------------------
   Superficies de trabajo: solidas. Solo se ajusta la sombra para que asienten
   sobre el fondo ambiental en vez de flotar planas.
   ------------------------------------------------------------------------- */
.superficie {
  background-color: #ffffff;
  border: 1px solid rgba(15, 60, 56, 0.08);
  box-shadow: var(--sombra-1);
}


/* El icono de cada encabezado de pantalla: una ficha blanca con la luz del
   vidrio, para que no se pierda sobre el fondo ambiental (un verde claro
   sobre otro verde claro casi no se veia). */
.ficha-icono {
  background: linear-gradient(180deg, #ffffff, #f1fbf9);
  box-shadow: inset 0 1px 0 #ffffff, 0 0 0 1px rgba(15, 60, 56, 0.08), var(--sombra-1);
}


/* ----------------------------------------------------------------------------
   Botones: una linea de luz arriba y, en el primario, un halo de su color.
   ------------------------------------------------------------------------- */
.btn-primary {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22), 0 1px 2px rgba(3, 37, 35, 0.2);
}
.btn-primary:hover:not(:disabled) {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22), 0 8px 20px -6px rgba(13, 128, 116, 0.55);
}


/* ----------------------------------------------------------------------------
   Transiciones entre pantallas: Brainstock son paginas de verdad. Con las
   transiciones de vista entre documentos (Chrome y Edge), la barra lateral y
   la superior quedan quietas y solo cambia el contenido. Donde no hay soporte
   se usa la entrada de pagina de siempre.
   ------------------------------------------------------------------------- */
@view-transition { navigation: auto; }
::view-transition-old(root) { animation: 120ms var(--curva-salida) both salirContenido; }
::view-transition-new(root) { animation: 180ms var(--curva-salida) both entrarContenido; }
::view-transition-group(barra-lateral),
::view-transition-group(barra-superior) { animation-duration: 0s; }
@keyframes salirContenido { to { opacity: 0; } }
@keyframes entrarContenido { from { opacity: 0; transform: translateY(6px); } }

@supports not (view-transition-name: none) {
  .page-container { animation: entradaPagina 220ms var(--curva-salida); }
}


/* ----------------------------------------------------------------------------
   Segunda pasada: movimiento con intencion.

   .entrada-escalonada: los hijos entran de a uno, subiendo apenas. Cada hijo
   lleva --i (su orden) en el markup o se lo pone el JS. Es solo opacidad y
   transform, lo mas barato de animar, y nada espera a que termine: se puede
   usar la pantalla mientras entra.
   ------------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  .entrada-escalonada > * {
    animation: entradaSubir 480ms var(--curva-salida) both;
    animation-delay: calc(var(--i, 0) * 60ms);
  }
}
@keyframes entradaSubir {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}

/* Una barra que se llena desde la izquierda (Mas vendidos, progreso). */
@media (prefers-reduced-motion: no-preference) {
  .barra-crece { transform-origin: left center; animation: barraCrece 700ms var(--curva-salida) both; animation-delay: calc(var(--i, 0) * 70ms + 150ms); }
}
@keyframes barraCrece { from { transform: scaleX(0); } }

/* Algo que aparece con un resorte corto (un numero que cambia, un tilde). */
@media (prefers-reduced-motion: no-preference) {
  .resorte { animation: resorte 420ms var(--curva-resorte) both; }
}
@keyframes resorte {
  0%   { transform: scale(.6); opacity: 0; }
  60%  { transform: scale(1.08); opacity: 1; }
  100% { transform: scale(1); }
}


/* ---- Estados vacios con presencia (segunda pasada) ----
   Todos: el icono deja de ser un circulo gris y pasa a una ficha menta con un
   anillo, que entra con un resorte corto. Los importantes (carrito vacio, sin
   alertas, sin ventas) llevan una ilustracion propia (ilustracion() en
   _componentes.html). El selector es doble porque el CDN de Tailwind inyecta
   su CSS despues de este archivo y a igual especificidad ganaria el suyo. */
.estado-vacio .estado-vacio-icono {
  height: 64px; width: 64px; padding: 16px; margin-bottom: 8px;
  border-radius: 20px;
  background: linear-gradient(145deg, #e6f7f4, #c9f6ee);
  color: #0a655d;
  box-shadow: 0 0 0 6px rgba(201, 246, 238, .45), 0 10px 22px -14px rgba(10, 101, 93, .55);
}
.estado-vacio .estado-vacio-titulo { color: #1e293b; }
.estado-vacio-ilustracion { width: 128px; height: 96px; margin-bottom: 4px; }
.ilustracion-marco { display: inline-block; line-height: 0; }
/* La ilustracion entra entera, en su marco (.ilustracion-marco, un span),
   con un resorte corto, y queda quieta. Antes se movian piezas de adentro
   del SVG (el carrito flotaba, el haz del lector iba y venia, el tilde se
   dibujaba, los destellos giraban) durante unos 5 segundos: le costaba a
   Venta, la pantalla que mas se carga (vuelve despues de cada venta), mas
   procesador que toda la pantalla en main. Flotar la ilustracion entera
   tampoco sale gratis (74ms medidos). Ver "Que se anima y que no" en
   DESIGN.md. */
@media (prefers-reduced-motion: no-preference) {
  .estado-vacio .estado-vacio-icono { animation: resorte 480ms var(--curva-resorte) both; }
  .ilustracion-marco { animation: resorte 480ms var(--curva-resorte) both; }
  /* el carrito vacio de Venta vuelve despues de cada venta: aparece quieto */
  #carrito-vacio .ilustracion-marco, #carrito-vacio .estado-vacio-icono { animation: none; }
}
/* el tilde que se dibuja: lo usa el sello de alerta resuelta */
@keyframes trazarTilde { to { stroke-dashoffset: 0; } }


/* ---- Alerta resuelta (segunda pasada) ----
   Antes de plegarse, la fila se pone verde (gestionada) o celeste
   (pospuesta) con una marca a la izquierda, y las acciones se cambian por un
   sello con un tilde que se dibuja. */
.fondo-ambiental .fila-alerta { transition: background-color .25s ease, box-shadow .25s ease; }
.fondo-ambiental .fila-alerta.fila-resuelta { background-color: #ecfdf5; box-shadow: inset 4px 0 0 #10b981; }
.fondo-ambiental .fila-alerta.fila-pospuesta { background-color: #f0f9ff; box-shadow: inset 4px 0 0 #0ea5e9; }
.sello-alerta {
  display: inline-flex; align-items: center; gap: 6px;
  border-radius: 9999px; padding: 4px 12px 4px 8px;
  background: #d1fae5; color: #065f46;
  font-size: 14px; line-height: 20px; font-weight: 500;
}
.sello-alerta svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; }
.sello-alerta.sello-pospuesta { background: #e0f2fe; color: #075985; }
@media (prefers-reduced-motion: no-preference) {
  .sello-alerta { animation: resorte 400ms var(--curva-resorte) both; }
  .sello-alerta path, .sello-alerta circle { stroke-dasharray: 52; stroke-dashoffset: 52; animation: trazarTilde .45s var(--curva-salida) .1s forwards; }
}


/* ---- Venta (segunda pasada) ----
   Producto agregado: el renglon nuevo entra con un destello menta; si ya
   estaba, la cantidad pulsa. El total salta y un "+1" sube y se desvanece.
   Venta registrada: el sello (tilde en un circulo) entra entero, con un
   rebote. */
.carrito-mas-uno {
  position: absolute; right: 0; top: -2px; pointer-events: none;
  font-size: 12px; font-weight: 500; color: #0a655d; opacity: 0;
}
.venta-ok-sello { position: relative; height: 44px; width: 44px; flex-shrink: 0; }
.venta-ok-sello svg { position: relative; z-index: 1; height: 44px; width: 44px; }
.venta-ok-circulo { fill: #d1fae5; stroke: #10b981; stroke-width: 3; }
.venta-ok-tilde { fill: none; stroke: #047857; stroke-width: 4; stroke-linecap: round; stroke-linejoin: round; }
@media (prefers-reduced-motion: no-preference) {
  /* El destello es una capa encima que solo cambia de opacidad (lo barato):
     animar el color de fondo repintaba el renglon en cada cuadro. */
  /* el estado va en atributos data- (no clases): ver marcarUltimoCambio en venta.html */
  [data-cambio] { position: relative; }
  [data-cambio="nuevo"] { animation: filaEntra 380ms var(--curva-salida) both; }
  [data-cambio]::after {
    content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: 8px;
    background: #d7f5ef; opacity: 0; animation: destello 1.2s ease-out both;
  }
  [data-cambio="sumado"] input { animation: salto 320ms var(--curva-resorte); }
  #carrito-total[data-salto] { display: inline-block; }
  #carrito-total[data-salto="0"] { animation: salto 340ms var(--curva-resorte); }
  #carrito-total[data-salto="1"] { animation: salto2 340ms var(--curva-resorte); }
  .carrito-mas-uno[data-sube="0"] { animation: masUno 850ms var(--curva-salida) both; }
  .carrito-mas-uno[data-sube="1"] { animation: masUno2 850ms var(--curva-salida) both; }

  .venta-ok { animation: ventaOkEntra 420ms var(--curva-resorte) both; }
  /* El sello entra entero con un rebote (transform: lo hace la placa de
     video). Antes el circulo y el tilde se dibujaban trazo por trazo (animar
     un trazo adentro de un SVG repinta en cada cuadro), con un anillo y seis
     puntos que se abrian (siete capas mas): con la CPU frenada 4 veces,
     confirmar la venta tardaba 487ms contra 336 de main
     (pruebas/flujo_venta.py). */
  .venta-ok-sello { animation: selloEntra 460ms var(--curva-resorte) .1s both; }
}
@keyframes filaEntra { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }
@keyframes destello { 0% { opacity: .9; } 100% { opacity: 0; } }
/* dos copias de cada animacion: alternar el nombre la reinicia sin forzar un recalculo */
/* el numero no desaparece: solo se agranda un poco y vuelve */
@keyframes salto { 40% { transform: scale(1.18); } }
@keyframes salto2 { 40% { transform: scale(1.18); } }
@keyframes masUno { 0% { opacity: 0; transform: translateY(4px); } 25% { opacity: 1; } 100% { opacity: 0; transform: translateY(-14px); } }
@keyframes masUno2 { 0% { opacity: 0; transform: translateY(4px); } 25% { opacity: 1; } 100% { opacity: 0; transform: translateY(-14px); } }
@keyframes ventaOkEntra { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }
@keyframes selloEntra { from { opacity: 0; transform: scale(.6); } to { opacity: 1; transform: none; } }


/* ---- Stock (segunda pasada) ----
   Fichas de estado con su cuenta arriba de la tabla, y un medidor de nivel
   debajo de cada cantidad (escala: el doble del minimo, el minimo marcado a
   la mitad). */
.ficha-estado {
  display: inline-flex; align-items: center; gap: 8px;
  border: 1px solid #e2e8f0; border-radius: 9999px; background: #ffffff;
  padding: 6px 8px 6px 14px; min-height: 36px;
  font-size: 14px; font-weight: 500; color: #334155;
  transition: border-color .15s ease, background-color .15s ease, box-shadow .15s ease;
}
.ficha-estado:hover { border-color: #5cdac8; }
.ficha-estado:focus-visible { outline: none; box-shadow: 0 0 0 4px rgba(23, 160, 142, .22); }
.ficha-estado[aria-pressed="true"] { border-color: #0d8074; background: #0d8074; color: #ffffff; }
.ficha-cuenta {
  min-width: 26px; border-radius: 9999px; padding: 1px 8px;
  background: #f1f5f9; color: #334155; font-size: 12px; text-align: center; font-variant-numeric: tabular-nums;
}
/* verde mas oscuro y solido: el blanco translucido encima del verde aclaraba el fondo y el numero daba 3,3:1 */
.ficha-estado[aria-pressed="true"] .ficha-cuenta { background: #0a5a52; color: #ffffff; }
.ficha-punto { height: 8px; width: 8px; border-radius: 9999px; }
.punto-rojo { background: #e11d48; }
.punto-ambar { background: #f59e0b; }
.punto-ambar-oscuro { background: #b45309; }
.punto-verde { background: #10b981; }
.ficha-estado[aria-pressed="true"] .ficha-punto { box-shadow: 0 0 0 2px #ffffff; }

.nivel-stock {
  display: block; margin: 6px 0 0 auto; height: 4px; width: 64px; overflow: hidden; border-radius: 9999px;
  background: linear-gradient(90deg, transparent calc(50% - 1px), #94a3b8 calc(50% - 1px), #94a3b8 calc(50% + 1px), transparent calc(50% + 1px)), #e2e8f0;
}
.nivel-stock > span { display: block; height: 100%; border-radius: 9999px; }
.nivel-ok > span { background: #17a08e; }
.nivel-bajo > span { background: #f59e0b; }
.nivel-vacio > span { background: #e11d48; min-width: 4px; }
/* Las barras no crecen al entrar: son una por producto (15 en la primera
   pagina) y cada una animada es una capa mas; le costaban a Stock 41ms de
   procesador al cargar (pruebas/cpu_por_efecto.py), y sin ellas Stock queda
   igual que en main. */


/* ---- Avatares (segunda pasada) ----
   Cada persona tiene un color, el mismo en todas partes: el login, la barra
   lateral, Usuarios, Vendedores, Mi perfil. Sale del id (id % 6), asi que no
   cambia nunca. Texto oscuro sobre fondo claro: todos pasan AA. */
.avatar-0 { background: #d7f5ef; color: #0a655d; }
.avatar-1 { background: #dbeefe; color: #0b4f7a; }
.avatar-2 { background: #fdefc8; color: #8a3b0c; }
.avatar-3 { background: #ebe6fd; color: #53239e; }
.avatar-4 { background: #fde2e5; color: #93132f; }
.avatar-5 { background: #dcf7e3; color: #17603a; }
.avatar {
  display: inline-flex; height: 32px; width: 32px; flex-shrink: 0;
  align-items: center; justify-content: center; border-radius: 9999px;
  font-size: 12px; font-weight: 500; line-height: 1;
}
.avatar-chico { height: 28px; width: 28px; font-size: 11px; }


/* ---- Transferencias (segunda pasada) ----
   El recorrido de un envio: Enviada -> En transito -> Recibida, con la
   linea llena hasta donde llego. */
.envio-icono {
  display: flex; height: 40px; width: 40px; flex-shrink: 0; align-items: center; justify-content: center;
  border-radius: 12px; background: #fef3c7; color: #b45309;
}
.envio-icono-ok { background: #d1fae5; color: #047857; }
/* El destino y quien lo mando necesitan su lugar: con flex-1 solo, a 360px
   el texto quedaba de 50px ("a / Farmacia / Sur") y las etiquetas del
   recorrido se le encimaban. Con esta base, si no entran los dos en el
   renglon, el recorrido baja al siguiente. */
.fila-envio > :first-child { flex: 1 1 13rem; }
.recorrido {
  position: relative; display: grid; grid-template-columns: repeat(3, 76px);
  list-style: none; margin: 0; padding: 0;
}
.recorrido::before, .recorrido::after {
  content: ""; position: absolute; top: 6px; left: 38px; height: 2px; border-radius: 2px;
}
.recorrido::before { right: 38px; background: #e2e8f0; }
.recorrido::after { width: calc((100% - 76px) / 2); background: #f59e0b; }
.recorrido-completo::after { width: calc(100% - 76px); background: #10b981; }
.recorrido-paso { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: center; gap: 4px; }
.recorrido-punto { position: relative; height: 14px; width: 14px; border-radius: 9999px; background: #ffffff; border: 2px solid #cbd5e1; }
.recorrido-paso.hecho .recorrido-punto { background: #f59e0b; border-color: #f59e0b; }
.recorrido-completo .recorrido-paso.hecho .recorrido-punto { background: #10b981; border-color: #10b981; }
.recorrido-paso.actual .recorrido-punto { background: #ffffff; border-color: #f59e0b; box-shadow: 0 0 0 4px rgba(245, 158, 11, .2); }
.recorrido-texto { font-size: 12px; line-height: 16px; color: #475569; white-space: nowrap; }
.recorrido-paso.actual .recorrido-texto { color: #92400e; font-weight: 500; }
@media (prefers-reduced-motion: no-preference) {
  /* La barra del recorrido no crece al entrar, y el punto del paso en curso
     late una vez y queda quieto: Transferir gastaba al cargar un 10% mas de
     procesador que en main (pruebas/cpu_carga.py, 14 vueltas). El latido es
     un anillo que crece y se desvanece (transform y opacidad); animar la
     sombra repintaba en el procesador en cada cuadro. */
  .recorrido-paso.actual .recorrido-punto::after {
    content: ""; position: absolute; inset: -2px; border-radius: 9999px; opacity: 0;
    background: rgba(245, 158, 11, .45); animation: latidoAmbar 2.4s ease-out 1;
  }
}
@keyframes latidoAmbar { from { opacity: 1; transform: scale(1); } to { opacity: 0; transform: scale(2.4); } }


/* ---- Movimientos (segunda pasada): el tipo como chip ---- */
.chip-movimiento {
  display: inline-flex; align-items: center; gap: 6px;
  border-radius: 9999px; padding: 2px 10px 2px 8px;
  font-size: 13px; line-height: 20px; font-weight: 500;
}
.tipo-venta  { background: #e6f7f4; color: #0a655d; }
.tipo-entra  { background: #dcfce7; color: #166534; }
.tipo-sale   { background: #e0f2fe; color: #075985; }
.tipo-ajuste { background: #f1f5f9; color: #334155; }
.tipo-baja   { background: #ffe4e6; color: #9f1239; }


/* ---- Contabilidad (segunda pasada): de cada $100, costo y margen ---- */
.composicion-barra { display: flex; height: 14px; width: 100%; overflow: hidden; border-radius: 9999px; background: #f1f5f9; }
.composicion-costo { background: #f59e0b; }
.composicion-margen { background: #10b981; }
/* (no crecen al entrar: Contabilidad gastaba al cargar un 8% mas de procesador
   que en main, pruebas/cpu_carga.py con 14 vueltas) */


/* En la tabla de escritorio (todas las sucursales), una sucursal por renglon
   y sin partir el nombre: "Farmacia Sur, Farmacia Belgrano, Farmacia Central"
   ocupaba cinco renglones en una columna de 126px y las filas median 125px
   (en main, 85): entraban 5 productos por pantalla a 1280x800. En el celular
   siguen seguidas, con coma. */
@media (min-width: 640px) {
  #tabla-stock .c-sucursal .sucursal-nombre { display: block; white-space: nowrap; }
  /* sin partir el nombre, la columna pedia 3px de mas a 1280: 8px por lado
     en vez de 12 (tablas_entran.py) */
  #tabla-stock .c-sucursal { padding-left: 0.5rem; padding-right: 0.5rem; }
  #tabla-stock .c-sucursal .sucursal-coma { display: none; }
}

/* ---- Stock en el celular (segunda pasada): cada producto es una tarjeta ----
   La tabla no entraba: la sucursal se partia en cuatro renglones, la cantidad
   quedaba cortada y el estado se veia scrolleando de costado. En pantallas
   angostas cada fila pasa a ser una tarjeta: el nombre y el estado arriba;
   cantidad (con su medidor), minimo y en cuanto se agota, cada uno con su
   etiqueta; la sucursal y los lotes al pie. En escritorio no cambia nada. */
@media (max-width: 639px) {
  #tabla-stock thead { display: none; }
  #tabla-stock, #tabla-stock tbody { display: block; width: 100%; }
  #tabla-stock tr.fila-producto, #tabla-stock tr.fila-lote {
    display: grid;
    grid-template-columns: 28px repeat(3, minmax(0, 1fr));
    grid-template-areas:
      "check prod prod estado"
      ".     cant min  agota"
      ".     suc  suc  lotes";
    column-gap: 10px; row-gap: 10px;
    padding: 14px 12px; border-bottom: 1px solid #e2e8f0;
  }
  /* el lote: su texto ocupa todo el renglon (con la etiqueta de vencimiento
     al lado se cortaba), y el vencimiento va una sola vez, en la etiqueta */
  #tabla-stock tr.fila-lote {
    grid-template-areas:
      "check prod prod prod"
      ".     cant suc  estado"
      ".     lotes lotes lotes";
    background: #f8fafc;
  }
  #tabla-stock tr.fila-lote .c-producto .lote-vence { display: none; }
  #tabla-stock td { display: block; min-width: 0; padding: 0; border: 0; text-align: left; }
  #tabla-stock td.c-producto { padding-left: 0; }
  #tabla-stock .c-check { grid-area: check; }
  #tabla-stock .c-producto { grid-area: prod; }
  #tabla-stock .c-estado { grid-area: estado; justify-self: end; }
  #tabla-stock .c-cantidad { grid-area: cant; font-size: 20px; line-height: 28px; }
  #tabla-stock .c-minimo { grid-area: min; }
  #tabla-stock .c-agota { grid-area: agota; }
  #tabla-stock .c-sucursal { grid-area: suc; font-size: 12px; line-height: 16px; }
  #tabla-stock .c-lotes { grid-area: lotes; font-size: 12px; line-height: 16px; }
  #tabla-stock tr.fila-producto .c-lotes { justify-self: end; }
  #tabla-stock tr.fila-lote .c-minimo, #tabla-stock tr.fila-lote .c-agota { display: none; }
  #tabla-stock .c-disponible { grid-column: 2 / -1; }
  #tabla-stock td[data-etiqueta]::before {
    content: attr(data-etiqueta); display: block; margin-bottom: 2px;
    font-size: 12px; line-height: 16px; font-weight: 500; letter-spacing: .02em; color: #475569;
  }
  #tabla-stock .nivel-stock { margin-left: 0; }
}


/* ---- Tablas como tarjetas en el celular (segunda pasada) ----
   .tabla-tarjetas: en pantallas angostas cada fila es una tarjeta. La celda
   .celda-titulo (lo que identifica la fila: el producto, la persona) va
   primero y ocupa todo el ancho; el resto se acomoda de a dos, cada dato con
   su etiqueta (data-etiqueta). En escritorio la tabla queda igual. */
@media (max-width: 639px) {
  table.tabla-tarjetas thead { display: none; }
  table.tabla-tarjetas, table.tabla-tarjetas tbody { display: block; width: 100%; }
  table.tabla-tarjetas tbody tr {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px 16px; padding: 14px 12px; border-bottom: 1px solid #e2e8f0;
  }
  table.tabla-tarjetas tbody td { display: block; min-width: 0; padding: 0; border: 0; text-align: left; white-space: normal; }
  /* table.brand.compacta (app.css) le pone relleno a las celdas y le gana a
     la linea de arriba: en la tarjeta no va */
  table.tabla-tarjetas.compacta tbody td { padding: 0; }
  table.tabla-tarjetas tbody td.celda-titulo { order: -1; grid-column: 1 / -1; font-size: 16px; line-height: 24px; }
  table.tabla-tarjetas tbody td.num { text-align: left; }
  /* una celda con barra y texto no entra en media tarjeta: va a lo ancho */
  table.tabla-tarjetas tbody td.celda-ancha { grid-column: 1 / -1; }
  /* un dato que no hay («—») no ocupa lugar en la tarjeta: en Contabilidad,
     cada producto sin precio era una tarjeta de cuatro guiones (100px) y con
     los 49 de la demo la pantalla media 11.650px a 360 */
  table.tabla-tarjetas tbody td[data-vacia] { display: none; }
  /* inline-block y no block: asi la etiqueta no hereda el tachado de una
     fila anulada (el tachado pasa a los hijos en bloque, no a los inline-block) */
  table.tabla-tarjetas tbody td[data-etiqueta]::before {
    content: attr(data-etiqueta); display: inline-block; width: 100%; margin-bottom: 2px;
    font-size: 12px; line-height: 16px; font-weight: 500; color: #475569;
  }
}


/* ----------------------------------------------------------------------------
   Tanda E: Dispositivos.

   Cada equipo es una fila-tarjeta. El icono dice el estado de un vistazo
   (verde: registrado; ambar: con un codigo sin usar; gris: sin registrar), y
   el texto lo dice igual al lado: el color nunca es lo unico. En el celular
   el estado y las acciones bajan a su propio renglon.
   ------------------------------------------------------------------------- */
.equipo-fila {
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  align-items: center; gap: 12px 16px;
}
.equipo-estado, .equipo-acciones { grid-column: 1 / -1; }
.equipo-acciones { display: flex; flex-wrap: wrap; gap: 8px; }
/* columnas de ancho fijo para el estado y las acciones: asi quedan alineadas
   de una tarjeta a la otra, como en una tabla */
@media (min-width: 768px) {
  .equipo-fila { grid-template-columns: 48px minmax(0, 1fr) 14rem; }
  .equipo-estado { grid-column: auto; }
  .equipo-acciones { grid-column: 2 / -1; }
}
@media (min-width: 1280px) {
  .equipo-fila { grid-template-columns: 48px minmax(0, 1fr) 14rem 20rem; }
  .equipo-acciones { grid-column: auto; justify-content: flex-end; }
}
.equipo-icono {
  display: flex; align-items: center; justify-content: center;
  width: 48px; height: 48px; border-radius: 14px;
}
.equipo-icono-registrado    { background: #d7f5ef; color: #0a655d; }
.equipo-icono-codigo        { background: #fef3c7; color: #b45309; }
.equipo-icono-sin-registrar { background: #f1f5f9; color: #475569; }
.equipo-icono-inactivo      { background: #f1f5f9; color: #94a3b8; }
/* el equipo desde el que se esta mirando: un borde de la marca, para
   encontrarlo sin leer */
.card.equipo-este {
  border-color: #5cdac8;
  box-shadow: 0 0 0 1px #5cdac8, 0 1px 2px rgba(11, 67, 64, .06), 0 6px 18px -8px rgba(11, 67, 64, .16);
}

/* El codigo de alta, como un vale: grande para dictarlo por telefono, con
   borde punteado de cupon. Separado de a letras para leerlo de a una. */
/* (.card.alta-vale y no .alta-vale: app.css se carga despues y su .card
   pisaria el borde y el fondo) */
.card.alta-vale { border-color: #95ecdd; background: linear-gradient(180deg, #eefcfa, #ffffff 75%); }
.alta-codigo {
  display: inline-block; max-width: 100%;
  padding: 8px 16px; border: 2px dashed #5cdac8; border-radius: 14px; background: #ffffff;
  font-size: 24px; line-height: 32px; font-weight: 500; letter-spacing: .14em;
  font-variant-numeric: tabular-nums; color: #0b514c; overflow-wrap: anywhere;
}
@media (min-width: 640px) { .alta-codigo { font-size: 32px; line-height: 44px; } }
.alta-pasos { display: grid; gap: 12px; font-size: 14px; line-height: 20px; color: #475569; }
.alta-pasos li { display: flex; align-items: flex-start; gap: 12px; }
.alta-paso-numero {
  flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; margin-top: -2px; border-radius: 999px;
  background: #0d8074; color: #ffffff; font-size: 12px; font-weight: 500;
}


/* ----------------------------------------------------------------------------
   Tanda E: Conteo; tanda F: los flujos de carga (Recibir transferencia,
   Nueva transferencia, Recepcion). Las mismas piezas en las cuatro:

   .avance-barra   el avance partido: lo que dio bien (verde de la marca) y
                   lo que dio distinto (ambar), sobre lo que falta. Las cifras
                   van escritas en .avance-leyenda: la barra nunca es lo unico.
   .ficha-carga    el producto elegido, en una superficie menta, con la
                   cantidad en grande (.ficha-cantidad).
   .chip-dato      un dato corto al costado de una fila (ubicacion, unidades).
   .boton-quitar   la cruz para sacar una linea, con area de toque de 36px.
   [data-recien]   lo recien hecho, marcado en su lista hasta la proxima
                   recarga.
   ------------------------------------------------------------------------- */
.avance-barra { display: flex; height: 10px; overflow: hidden; border-radius: 999px; background: #f1f5f9; }
.avance-barra > span { height: 100%; }
.avance-ok { background: #0d8074; }
.avance-dif { background: #b45309; }
.avance-leyenda { display: flex; flex-wrap: wrap; gap: 6px 20px; font-size: 14px; line-height: 20px; color: #475569; }
.avance-leyenda li { display: inline-flex; align-items: center; gap: 8px; }
.avance-punto { width: 10px; height: 10px; flex-shrink: 0; border-radius: 999px; }
.chip-dato {
  flex-shrink: 0; white-space: nowrap; border-radius: 6px; background: #f1f5f9; padding: 2px 8px;
  font-size: 12px; line-height: 16px; color: #475569; font-variant-numeric: tabular-nums;
}
.chip-dato-sin { background: transparent; color: #64748b; }
.boton-quitar {
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 36px; height: 36px; border-radius: 10px; color: #be123c;
  transition: background-color 150ms ease;
}
.boton-quitar:hover { background: #fff1f2; }
.boton-quitar:focus-visible { outline: 2px solid #be123c; outline-offset: 2px; }
.ficha-carga { border: 1px solid #95ecdd; border-radius: 16px; background: #eefcfa; padding: 16px; }
@media (min-width: 640px) { .ficha-carga { padding: 20px; } }
/* (dos clases: .input de app.css se carga despues y le ganaria) */
.ficha-carga .ficha-cantidad { font-size: 24px; line-height: 32px; font-variant-numeric: tabular-nums; }
/* lo recien contado queda apenas tenido hasta la proxima recarga; el tinte
   va detras del texto (isolation + z-index), asi nunca le baja el contraste */
.fila-detalle[data-recien] { isolation: isolate; background: #f3fcfa; }
@media (prefers-reduced-motion: no-preference) {
  .ficha-carga:not([hidden]) { animation: entradaSubir 240ms var(--curva-salida) both; }
  .fila-detalle[data-recien]::after {
    content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
    background: #c9f6ee; opacity: 0; animation: destello 1.6s ease-out both;
  }
}


/* ----------------------------------------------------------------------------
   Tanda E: interruptor y pantallas de ajustes (Mi perfil, Configuracion de
   alertas).

   El interruptor es la casilla de siempre (input type=checkbox, con
   role=switch): el formulario manda lo mismo. Apagado: contorno y perilla
   oscuros (4,8:1 contra el blanco, se ve que es un control); prendido:
   relleno de la marca con la perilla blanca. La perilla se corre con
   transform, lo unico que se anima. (input[type=checkbox].interruptor: el
   estilo base de las casillas esta en app.css, que se carga despues.)
   ------------------------------------------------------------------------- */
input[type="checkbox"].interruptor {
  -webkit-appearance: none; appearance: none;
  position: relative; flex-shrink: 0; margin: 0; cursor: pointer;
  width: 44px; height: 26px; border-radius: 999px;
  border: 2px solid #64748b; background: #ffffff;
  transition: background-color 150ms ease, border-color 150ms ease;
}
input[type="checkbox"].interruptor::before {
  content: ""; position: absolute; left: 3px; top: 50%;
  width: 14px; height: 14px; border-radius: 999px; background: #64748b;
  transform: translateY(-50%);
  transition: transform 180ms var(--curva-salida), width 180ms var(--curva-salida), height 180ms var(--curva-salida);
}
input[type="checkbox"].interruptor:checked { background: #0d8074; border-color: #0d8074; }
input[type="checkbox"].interruptor:checked::before { width: 18px; height: 18px; background: #ffffff; transform: translate(16px, -50%); }
input[type="checkbox"].interruptor:focus-visible { outline: 2px solid #0d8074; outline-offset: 3px; box-shadow: none; }
@media (prefers-reduced-motion: reduce) {
  input[type="checkbox"].interruptor, input[type="checkbox"].interruptor::before { transition: none; }
}
/* la fila del interruptor: el texto es la etiqueta, toda la fila se toca */
.interruptor-fila {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 14px 16px; border: 1px solid #e2e8f0; border-radius: 14px; background: #ffffff; cursor: pointer;
}

/* Ajustes: cada seccion con su titulo y su explicacion a la izquierda y los
   controles a la derecha (en el celular, uno arriba del otro). Es como se
   leen las pantallas de configuracion: primero de que se trata, despues que
   se toca. */
.ajuste { display: grid; gap: 16px; padding: 24px 0; border-top: 1px solid #e2e8f0; }
.ajuste:first-of-type { padding-top: 0; border-top: 0; }
@media (min-width: 768px) {
  .ajuste { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 32px; }
}
.ajuste-titulo { display: flex; align-items: center; gap: 12px; font-size: 16px; line-height: 24px; font-weight: 500; color: #0f172a; }
.ajuste-icono {
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 36px; height: 36px; border-radius: 12px;
}
.ajuste-texto p { margin-top: 8px; font-size: 14px; line-height: 20px; color: #475569; }
.ajuste-efecto { margin-top: 8px; font-size: 14px; line-height: 20px; color: #475569; }
.ajuste-efecto strong { font-weight: 500; color: #0b514c; }
.ajustes-pie {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 12px 16px;
  padding-top: 24px; border-top: 1px solid #e2e8f0;
}
/* Un interruptor suele aplicarse al instante; aca hay que tocar Guardar.
   Apenas se toca algo del formulario, al lado del boton lo dice. */
.ajustes-sin-guardar {
  display: inline-flex; align-items: center; gap: 8px; margin-right: auto;
  font-size: 14px; line-height: 20px; font-weight: 500; color: #b45309;
}
/* un numero con su unidad al lado, adentro del mismo campo */
.campo-unidad { position: relative; display: flex; align-items: center; max-width: 16rem; }
.campo-unidad .input { padding-right: 5.5rem; font-variant-numeric: tabular-nums; }
.campo-unidad span {
  position: absolute; right: 14px; pointer-events: none;
  font-size: 14px; line-height: 20px; color: #475569;
}
/* un campo con un icono adentro, a la izquierda */
.campo-icono { position: relative; }
.campo-icono > svg, .campo-icono > i {
  position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
  width: 16px; height: 16px; color: #64748b; pointer-events: none;
}
.campo-icono .input { padding-left: 2.5rem; }


/* ----------------------------------------------------------------------------
   Tanda E: el ticket como un papel.

   Borde de abajo dentado, como un ticket cortado de la impresora, y la
   sombra que sigue ese corte (drop-shadow y no box-shadow, que seria un
   rectangulo). Una venta anulada lleva un sello. Al imprimir no va nada de
   esto (ver el @media print de ticket.html).
   ------------------------------------------------------------------------- */
.ticket-papel {
  position: relative; background: #ffffff;
  border-radius: 16px 16px 0 0;
  padding: 28px 24px 32px;
  filter: drop-shadow(0 1px 1px rgba(11, 67, 64, .08)) drop-shadow(0 12px 18px rgba(11, 67, 64, .14));
}
@media (min-width: 640px) { .ticket-papel { padding: 36px 36px 40px; } }
.ticket-papel::after {
  content: ""; position: absolute; left: 0; right: 0; top: 100%; height: 8px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='8' viewBox='0 0 16 8'%3E%3Cpath d='M0 0h16L8 8z' fill='%23ffffff'/%3E%3C/svg%3E") repeat-x left top / 16px 8px;
}
.ticket-logo { width: 36px; height: 36px; margin: 0 auto 8px; }
.ticket-logo .trazo { fill: none; stroke: #0a655d; stroke-width: 3; stroke-linecap: round; }
.ticket-logo .mitad { fill: #2fbfac; }
.ticket-logo .cruz { fill: none; stroke: #0d8074; stroke-width: 3.5; stroke-linecap: round; }
.ticket-sello {
  display: inline-block; transform: rotate(-6deg);
  border: 2px solid #be123c; border-radius: 8px; padding: 2px 14px;
  font-size: 16px; line-height: 24px; font-weight: 500; letter-spacing: .24em; text-transform: uppercase;
  color: #be123c;
}
.ticket-total { border-top: 3px double #cbd5e1; }


/* ----------------------------------------------------------------------------
   Tanda G: Venta en pantallas bajas.

   Los mas vendidos, en escritorio, como ranking en la columna derecha: una
   fila por producto, con su puesto, que al tocarla lo busca.
   ------------------------------------------------------------------------- */
.top-hoy-fila {
  display: flex; width: 100%; align-items: center; gap: 12px;
  border-radius: 10px; padding: 8px 8px; text-align: left;
  font-size: 14px; line-height: 20px; font-weight: 500; color: #1e293b;
  transition: background-color 150ms ease;
}
.top-hoy-fila:hover { background: #eefcfa; }
.top-hoy-fila:focus-visible { outline: 2px solid #0d8074; outline-offset: 1px; }
.top-hoy-puesto {
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 24px; height: 24px; border-radius: 999px;
  background: #eefcfa; color: #0a655d; font-size: 12px; font-weight: 500; font-variant-numeric: tabular-nums;
}


/* ----------------------------------------------------------------------------
   Reducir movimiento: sin animaciones de entrada, sin resortes, sin
   transiciones de pantalla. Lo demas (vidrio, colores) queda igual.
   ------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
  .menu-flotante, .velo-modal, .panel-modal, .panel-asistente, .page-container { animation: none !important; }
  .gota, .gota:hover, .gota:active { transform: none !important; transition: none !important; }
}


/* ----------------------------------------------------------------------------
   Cifras que suben: una rueda de digitos (base.js, subirCifra). Cada digito
   es una ventana de un renglon con una cinta del 0 al 9 adentro, que se corre
   con transform hasta el suyo: la anima la placa de video, sin recalcular ni
   repintar la pagina. Cifras de ancho fijo (tabular-nums): el numero no
   cambia de ancho mientras rueda.
   ------------------------------------------------------------------------- */
.rueda { display: inline-flex; font-variant-numeric: tabular-nums; }
/* las cifras que ruedan, con digitos de ancho fijo tambien despues: al
   terminar, la rueda se cambia por el numero solo y no se mueve nada */
[data-contar], #dashboard-contenido [data-valor] { font-variant-numeric: tabular-nums; }
.rueda-digito { display: inline-block; height: 1lh; overflow: hidden; }
@supports not (height: 1lh) { .rueda-digito { height: 1.334em; } }
.rueda-cinta { display: block; white-space: pre; transform: translateY(0); }
@media (prefers-reduced-motion: no-preference) {
  .rueda-cinta { transition: transform 900ms var(--curva-salida); }
}
