/* Inventario de Hardware TECNOMAX */

/* ---------------------------------------------------------------------------
   IDENTIDAD VISUAL TECNOMAX (2026-08-12)
   ---------------------------------------------------------------------------
   Se conserva el azul institucional de siempre; lo que cambia es lo que lo
   rodea. Todo el sistema (esta hoja, catalogo.css, ficha.css, ticket.css y
   etiquetas.css) toma los colores de aqui: cambiando un valor en este bloque
   se cambia en las 115 pantallas de una vez.

   La copia anterior quedo guardada en estilo_anterior_respaldo.css. Para
   volver atras basta reemplazar este archivo por esa copia y reiniciar.

   Los grises NO son grises de fabrica: llevan una pizca de azul, que es lo
   que hace que una pantalla se vea de marca y no de plantilla.
--------------------------------------------------------------------------- */
:root {
  /* --- Marca. El azul se usa con avaricia (2026-08-14) -----------------
     #1f4e79 NO cambia: esta en el logo, en la franja de los PDF
     (pdf_utils.py), en las etiquetas impresas y en los 3 manuales.
     Cambiarlo desalinearia la pantalla con todo lo impreso.
     Lo que cambio es DONDE aparece: antes estaba en titulos, precios,
     codigos, flechas y numeros; ahora queda para tres cosas -- la accion
     primaria, los enlaces y el foco. Los titulos van en tinta. */
  --azul: #1f4e79;          /* accion primaria, enlaces, foco */
  --azul-claro: #2a6291;    /* hover y foco -- desaturado */
  --azul-fuerte: #0b2338;   /* barra superior: mas tinta que azul */
  /* Bug corregido el 2026-08-14: esta variable se definia a si misma
     (`var(--azul-tenue)`), lo que en CSS la deja INVALIDA -- no es un valor,
     es "sin valor". Las 7 reglas que la usaban (hover de fila de equipo, de
     familia, boton de comentar, foco) quedaban sin fondo, o sea que el
     resaltado al pasar el mouse no se veia. Se le pone el tinte azul claro
     que el comentario original describia. */
  --azul-tenue: #e8f0f8;    /* fondo de lo seleccionado */

  /* Colores de estado. Se reservan para lo que SIGNIFICA algo: nunca
     decorativos. Mas profundos y menos saturados que antes -- un sistema
     serio es sobrio en la decoracion y agresivo en la alerta. */
  --rojo: #99201a;
  --verde: #14663a;
  --ambar: #8a5600;

  /* Escala de grises azulada. Los grises NO son de fabrica: llevan una
     pizca de azul, que es lo que hace que se vean de marca. */
  --texto: #0f1720;         /* tinta */
  --suave: #5b6673;         /* texto secundario */
  --tenue: #8b96a2;         /* terciario: rotulos de columna, metadatos */
  --borde: #dde3e9;         /* linea de caja */
  --borde-suave: #eceff3;   /* separacion entre filas */
  --borde-fuerte: #c7cfd8;  /* separador estructural (bajo un th) */
  --fondo: #f4f6f8;         /* fondo de pagina */
  --superficie: #ffffff;    /* toda caja de contenido */
  --superficie-2: #fafbfc;  /* cabecera de tabla, bloque embebido, hover */

  /* Fondos semanticos: apenas tenidos, NO pasteles. Con 40 filas en
     pantalla, un pastel saturado pinta la pagina entera de color. */
  --verde-fondo: #f2f7f4;
  --ambar-fondo: #fdf8ef;
  --rojo-fondo: #fcf3f2;
  --azul-fondo: #f1f5f9;
  --naranja-fondo: #fdf4ec;

  /* Una superficie fija NO flota: se delimita con una linea. La sombra
     queda solo para lo que de verdad esta por encima del contenido
     (menus, dialogos, barras pegajosas). */
  --sombra: none;
  --sombra-flotante: 0 8px 24px rgba(11,35,56,.14);

  /* Tres radios, no trece. Las pildoras de 999px eran el marcador visual
     mas fuerte de "app moderna" y el mas lejano de "sistema serio". */
  --radio: 4px;             /* panel, tabla, input, boton */
  --radio-chico: 3px;       /* chapas, pastillas, chips */
  --radio-grande: 6px;      /* dialogos y desplegables */

  /* Tipografia. Segoe UI Variable viene de fabrica en Windows 11 y es mas
     limpia en tamanos chicos; donde no este, cae a Segoe UI sin que se
     note. Seis tamanos, sin medios puntos. */
  --fuente: "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system, Arial, sans-serif;
  --fuente-titulo: "Segoe UI Variable Display", "Segoe UI", system-ui, Arial, sans-serif;
  --fuente-mono: Consolas, "Cascadia Mono", "Courier New", monospace;
  --t-xs: 11px;             /* th, miga, rotulos */
  --t-sm: 12px;             /* chapas, pastillas, notas */
  --t-base: 13px;           /* tablas, formularios, botones */
  --t-md: 14px;             /* cuerpo de pagina */
  --t-lg: 16px;             /* h2 */
  --t-xl: 20px;             /* h1 */
  --t-dato: 24px;           /* numero de KPI */

  --ancho: 1280px;          /* las tablas de este sistema llegan a 10 columnas */
}

/* Numeros que se comparan columna a columna, sin bailar de fila en fila.
   Es lo que hace que una tabla de precios se lea como un estado de cuenta.
   Regla unica: no hace falta tocar ninguna plantilla. */
td, th.num, .mono, .num, .tarjeta-numero, .tarjeta-repuesto-numero,
.precio-final, .precio-fijo, .cuota-numero, .tabla-desglose td,
dl.datos dd, .kpi-valor, .dias b,
input[type="number"], input[inputmode="decimal"] {
  font-variant-numeric: tabular-nums;
}

* { box-sizing: border-box; }

/* Un elemento con "hidden" tiene que quedar oculto SIEMPRE. Sin esto,
   cualquier clase con "display: flex" o "grid" le gana al atributo y el
   elemento se ve igual -- pasaba con el formulario de "Nueva conversacion"
   del CRM, que nacia desplegado (encontrado el 2026-08-12 al mirar la
   pantalla; por HTTP no se nota). */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--fondo);
  color: var(--texto);
  font-family: var(--fuente);
  font-size: var(--t-md);
  line-height: 1.5;
}

.contenedor { max-width: var(--ancho); margin: 0 auto; padding: 0 24px; }

/* ---------- Barra superior: seis modulos con desplegable ---------- */

/* Color plano en vez de degradado, y sin sombra: la barra se separa del
   contenido por su propio color, no por un efecto. */
.barra {
  background: var(--azul-fuerte);
  color: #fff; position: relative; z-index: 50;
}

.barra-interior {
  display: flex; align-items: center; gap: 18px;
  flex-wrap: wrap; min-height: 52px;
}

.marca {
  display: flex; align-items: center; gap: 10px; flex-shrink: 0;
  color: #fff; text-decoration: none;
}
.marca img { height: 32px; width: auto; }

.modulos { display: flex; align-items: center; gap: 2px; flex-wrap: wrap; }
.modulo { position: relative; }
.modulo > a {
  display: flex; align-items: center; gap: 7px; height: 34px; padding: 0 11px;
  color: #c3d3e2; text-decoration: none; font-size: var(--t-base); font-weight: 600;
  border-radius: var(--radio); white-space: nowrap;
  transition: background .15s, color .15s;
}
.modulo > a:hover, .modulo:hover > a { background: rgba(255,255,255,.08); color: #fff; }
/* Sin emojis en la navegacion (decision del usuario, 2026-08-14): ningun
   sistema serio pone un emoji en su menu. Se apagan desde aqui, sin tocar
   base.html -- los <span class="icono"> siguen en el HTML por si algun dia
   se quieren volver a encender o reemplazar por iconos de verdad. */
.modulo .icono { display: none; }
/* El punto azul de cada opcion del desplegable tampoco aporta. */
.desplegable .punto { display: none; }
.modulo .icono { font-size: 15px; line-height: 1; }
.flecha {
  width: 0; height: 0; margin-left: 2px;
  border-left: 4px solid transparent; border-right: 4px solid transparent;
  border-top: 4.5px solid currentColor; opacity: .7;
}

/* El desplegable se abre al pasar el mouse y tambien con el teclado (focus),
   para que se pueda navegar sin raton. */
.desplegable {
  position: absolute; top: calc(100% + 6px); left: 0; min-width: 232px;
  background: #fff; border-radius: var(--radio-grande); padding: 7px;
  border: 1px solid var(--borde);
  box-shadow: var(--sombra-flotante);
  display: none;
}
.modulo:hover .desplegable, .modulo:focus-within .desplegable { display: block; }
/* Puente invisible: evita que el menu se cierre al bajar el mouse hacia el. */
.modulo:hover .desplegable::after {
  content: ""; position: absolute; top: -8px; left: 0; right: 0; height: 8px;
}
.desplegable::before {
  content: ""; position: absolute; top: -6px; left: 22px; width: 12px; height: 12px;
  background: #fff; border-left: 1px solid var(--borde); border-top: 1px solid var(--borde);
  transform: rotate(45deg); border-radius: var(--radio-chico) 0 0 0;
}
.desplegable-titulo {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: 1.3px;
  color: #9aa8b8; font-weight: 700; padding: 8px 12px 6px;
}
.desplegable a {
  display: flex; align-items: center; gap: 10px; padding: 9px 12px;
  color: var(--texto); text-decoration: none; font-size: 14px;
  border-radius: var(--radio); transition: background .12s;
}
.desplegable a:hover { background: #e8f0f8; color: var(--azul); }
.desplegable .punto {
  width: 7px; height: 7px; border-radius: 50%; background: var(--azul-claro);
  flex-shrink: 0; opacity: .55;
}
/* Separador visual dentro de un desplegable con varias secciones (ej. menu
   "Inventario" reorganizado el 2026-08-11: agrupa modulos ya existentes,
   solo cambia donde se ven, no que hacen). */
.desplegable-separador { height: 1px; background: var(--borde); margin: 6px 4px; }

.barra-derecha { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.barra-derecha .quien { color: #b9cde0; font-size: 13px; }
.barra-derecha .salir {
  color: #e8eef5; text-decoration: none; padding: 6px 12px;
  border-radius: var(--radio); font-size: 13.5px; border: 1px solid rgba(255,255,255,.35);
}
.barra-derecha .salir:hover { background: rgba(255,255,255,.15); color: #fff; }

/* ---------- Barra: menu de tablet (2026-08-13) ---------- */
/* Oculto en escritorio -- solo aparece por debajo de 900px (ver el
   @media mas abajo), que es donde la barra de 8 modulos ya no entra en
   una sola fila (caso real: Bodega usa tablet para Recepcion de Cargas). */
.menu-boton {
  display: none; flex-direction: column; justify-content: center; align-items: center;
  gap: 4px; width: 38px; height: 38px; margin-left: auto;
  background: transparent; border: 1px solid rgba(255,255,255,.35);
  border-radius: var(--radio); cursor: pointer; padding: 0;
}
.menu-boton-barra { display: block; width: 18px; height: 2px; background: #fff; border-radius: var(--radio-chico); }

@media (max-width: 900px) {
  .menu-boton { display: flex; }
  .marca { order: 1; }
  .menu-boton { order: 2; }
  .barra-derecha { order: 3; margin-left: 0; }

  /* La barra de modulos se colapsa entera detras del boton... */
  .modulos { display: none; order: 4; width: 100%; flex-direction: column; align-items: stretch; gap: 2px; padding: 10px 0 14px; }
  .barra-interior.menu-abierto .modulos { display: flex; }
  .modulo { width: 100%; }
  .modulo > a { width: 100%; justify-content: space-between; }

  /* ...y cada desplegable se abre en modo acordeon (con la flecha), no al
     pasar el mouse -- en touch no existe el hover. */
  .modulo:hover .desplegable, .modulo:focus-within .desplegable { display: none; }
  .modulo.abierto .desplegable { display: block; }
  .desplegable {
    position: static; width: 100%; margin: 2px 0 6px; box-shadow: none;
    border: none; background: rgba(255,255,255,.08); border-radius: var(--radio);
  }
  .desplegable::before { display: none; }
  .desplegable-titulo { color: #b9cde0; }
  .desplegable a { color: #e8eef5; }
  .desplegable a:hover { background: rgba(255,255,255,.14); color: #fff; }
}

/* ---------- Estructura ---------- */

main { padding-top: 24px; padding-bottom: 40px; min-height: 60vh; }

/* Titulos algo mas grandes y ajustados, para que la jerarquia se lea sin
   depender del color. */
/* Titulos en TINTA, no en azul (2026-08-14): el azul queda para la accion,
   los enlaces y el foco. Tres pesos en todo el sistema: 400 / 600 / 700. */
h1 {
  font-family: var(--fuente-titulo);
  font-size: var(--t-xl); margin: 0; letter-spacing: -.01em;
  color: var(--texto); font-weight: 600;
}
h2 {
  font-family: var(--fuente-titulo);
  font-size: var(--t-lg); margin: 0 0 12px; color: var(--texto); font-weight: 600;
}
h2 small { font-weight: 400; color: var(--suave); margin-left: 8px; font-size: var(--t-base); }

.titulo-fila {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; flex-wrap: wrap; margin-bottom: 4px;
}
/* La miga en mayusculas chicas espaciadas es, junto con la tabla, lo que
   hace que una pantalla se lea como "modulo de un sistema" y no como
   "pagina web". */
.miga {
  font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .08em;
  color: var(--tenue); font-weight: 600; margin: 0 0 6px;
}
.subtitulo { color: var(--suave); font-size: var(--t-base); margin: 0 0 16px; }

/* ---------- LA TARJETA (2026-08-14) ----------
   .panel es EL contenedor de contenido del sistema y el patron oficial de
   organizacion visual: cada bloque de informacion vive en su propia
   tarjeta con su titulo. El usuario lo eligio como estandar viendo la
   ficha del equipo (Resumen comercial / Costos y repuestos /
   Identificacion) -- toda pantalla nueva se arma asi.

   Una tarjeta NO flota: se delimita con una linea. La jerarquia la dan el
   espacio y el borde, no la sombra. */
.panel {
  background: var(--superficie); border: 1px solid var(--borde);
  border-radius: var(--radio);
  padding: 16px 18px; margin-bottom: 14px; box-shadow: var(--sombra);
}
/* La cabecera de la tarjeta lleva regla. Se aplica a las 120 plantillas de
   una vez porque todas ya usan <section class="panel"><h2>. */
.panel > h2:first-child {
  padding-bottom: 10px; margin: 0 0 14px;
  border-bottom: 1px solid var(--borde-suave);
}
/* Una tabla dentro de una tarjeta angosta se corta (caso real: "Costos y
   repuestos" en media pantalla, con la columna Tecnico cortada). La
   tarjeta la deja desplazarse en vez de recortarla. */
.panel > .tabla-scroll { margin-left: -18px; margin-right: -18px; width: auto;
  border-left: 0; border-right: 0; border-radius: 0; }
.panel > .tabla-scroll:last-child { margin-bottom: -16px; border-bottom: 0; }

.pie { color: var(--suave); font-size: 13px; padding-bottom: 24px; }

/* Formulario modal (ej. "+ Nuevo Vendedor" en el punto de venta): el
   elemento nativo <dialog> ya trae centrado y bloqueo de la pagina de atras,
   solo se le da el mismo aspecto que .panel. */
.modal-panel {
  background: #fff; border: 1px solid var(--borde); border-radius: var(--radio-grande);
  padding: 20px 24px; max-width: 480px; width: 90%;
}
.modal-panel::backdrop { background: rgba(15, 23, 42, .45); }
.modal-panel form { display: flex; flex-direction: column; gap: 12px; }
.modal-panel label { display: block; font-size: 13px; color: var(--suave); }
.modal-panel label input, .modal-panel label textarea { margin-top: 5px; }

/* Cuentas bancarias (tablero y punto de venta): minimalista a proposito, sin
   recuadro ni fondo por cuenta -- solo tipografia y una linea fina abajo
   para separar, como una lista. */
.cuentas-banco {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 20px 28px;
}
.cuenta-tarjeta {
  display: flex; flex-direction: column; gap: 3px;
  padding-bottom: 14px; border-bottom: 1px solid var(--borde);
}
.cuenta-tarjeta-cabecera { display: flex; align-items: center; gap: 8px; margin-bottom: 2px; }
.cuenta-logo {
  width: 22px; height: 22px; border-radius: var(--radio); object-fit: contain;
  flex-shrink: 0;
}
.cuenta-logo-texto {
  display: flex; align-items: center; justify-content: center;
  background: none; color: var(--suave); font-size: 10px; font-weight: 700;
  border: 1px solid var(--borde);
}
.cuenta-tipo { color: var(--suave); font-size: 13px; }
.cuenta-numero { font-size: 17px; font-weight: 700; letter-spacing: .3px; }
.cuenta-titular { font-size: 13px; color: var(--suave); }
.cuenta-titular b { color: var(--texto); font-weight: 600; }
.cuenta-detalle { font-size: 12px; color: var(--suave); }
.cuenta-tarjeta .boton-mini {
  margin-top: 8px; align-self: flex-start;
  background: none; border: none; padding: 0; color: var(--azul);
  font-weight: 600;
}
.cuenta-tarjeta .boton-mini:hover { text-decoration: underline; }

/* ---------- Avisos y pastillas ---------- */

/* Aviso con una barra de color a la izquierda en vez de todo el fondo
   teñido: informa igual y no grita. */
.aviso {
  padding: 11px 15px; border-radius: var(--radio); margin: 0 0 16px;
  border: 1px solid var(--borde); border-left: 3px solid var(--suave);
  background: #fff; color: var(--texto);
}
.aviso.ok { background: #f4faf6; border-color: #cfe6d8; border-left-color: var(--verde); color: #14512c; }
.aviso.error { background: #fdf6f5; border-color: #eecfcc; border-left-color: var(--rojo); color: #7d1a15; }
/* Ni bien ni error: algo que conviene corregir pero no rompe nada
   (ej. un ID del sistema que quedo con el nombre de Windows, 2026-08-12). */
.aviso.atencion { background: #fefaf3; border-color: #eeddb9; border-left-color: var(--ambar); color: #6e4611; }

.contadores { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
/* Un <form>/<button> que necesita verse como un boton mas en una fila de
   pastillas y enlaces (ej. "Imprimir etiquetas de <ubicacion>"). */
.form-en-linea { display: contents; }
/* De burbuja a control de sistema: el cambio real es el radio (999 -> 4). */
.pastilla {
  background: var(--superficie); border: 1px solid var(--borde); border-radius: var(--radio);
  padding: 3px 10px; font-size: var(--t-sm); color: var(--suave); text-decoration: none;
}
.pastilla b { color: var(--texto); font-weight: 700; }
.pastilla.roja { border-color: #e6cac7; background: var(--rojo-fondo); color: var(--rojo); font-weight: 600; }
.pastilla.roja b { color: var(--rojo); }
/* Para una cifra que no es mala pero pide atencion (2026-08-14): el dinero
   comprometido en pedidos que todavia no llegaron. */
.pastilla.ambar { border-color: #ebdcc0; background: var(--ambar-fondo); color: var(--ambar); font-weight: 600; }
.pastilla.ambar b { color: var(--ambar); }
a.pastilla { text-decoration: none; }
.pastilla.activa { background: var(--azul); border-color: var(--azul); color: #fff; }

/* Chip de confianza para la razon extraida de comentarios (Reporte de
   Equipos Fuera de Venta) -- verde: el comentario lo explica directo;
   amarillo: se detecto por palabra clave; rojo: no se encontro nada
   claro, hay que revisar a mano. */
.chip-razon {
  display: inline-block; padding: 3px 10px; border-radius: var(--radio-chico);
  font-size: 12px; font-weight: 600; margin-bottom: 4px;
}
.chip-razon.verde { background: #e7f5ec; color: var(--verde); }
.chip-razon.amarillo { background: #fff4e0; color: #8a5a00; }
.chip-razon.rojo { background: #fdecea; color: var(--rojo); }

/* La salud de la bateria pasa de texto de color a pastilla con punto: se
   distingue de un vistazo en una tabla larga sin tener que leer el numero.
   Se hace solo con CSS -- ninguna plantilla cambia. */
.salud {
  font-weight: 600; display: inline-flex; align-items: center; gap: 6px;
  padding: 2px 9px; border-radius: var(--radio-chico); font-size: 12.5px;
  border: 1px solid transparent; white-space: nowrap;
}
.salud::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
.salud.buena { color: var(--verde); background: #e9f4ed; border-color: #c3e0cd; }
.salud.mala { color: var(--rojo); background: #fbeceb; border-color: #eec7c4; }

/* Estado de un equipo dentro de una tabla. La clase se venia usando en
   lista_agrupada.html y captura_excel_mapear.html desde antes, pero NUNCA
   tuvo estilo: salia como texto suelto. Encontrado el 2026-08-12. */
/* La base de .chapa-estado la da ahora el selector agrupado de las cinco
   familias (2026-08-14); aqui quedan solo sus modificadores. */
.chapa-estado.vigente { color: var(--verde); background: var(--verde-fondo); border-color: #cfe0d6; }
.chapa-estado.vence { color: var(--ambar); background: var(--ambar-fondo); border-color: #ebdcc0; }
.chapa-estado.vencida { color: var(--rojo); background: #fbeceb; border-color: #eec7c4; }
.nota-roja { color: var(--rojo); font-size: 13px; margin-left: 8px; }

/* ---------- Buscador, botones y formularios ---------- */

.buscador { display: flex; gap: 8px; margin: 0 0 18px; flex-wrap: wrap; }
.buscador input { flex: 1; min-width: 240px; }

/* ---------- BUSQUEDA EN VIVO Y AUTOCOMPLETADO (2026-08-14) ----------
   Dos componentes reutilizables, con el mismo criterio que las PESTANAS: el
   JavaScript vive una sola vez en base.html y una pantalla solo declara
   atributos "data-". Si manana hay que cambiar como se busca, se cambia en
   un solo lugar. Ver el bloque de base.html para el contrato completo.

   1) .buscador-vivo   -> filtra al escribir lo que YA esta en la pagina.
   2) .autocompletar   -> lista desplegable de sugerencias del servidor.

   Lo que NO cambia: el formulario GET sigue debajo. Sin JavaScript, o si
   algo falla, todo se comporta como antes (Enter -> el servidor busca). */

/* Aviso de "no hay coincidencias": lo crea el JS, no las plantillas. */
.filtro-sin-resultados { color: var(--suave); margin: 12px 0 18px; }

/* La caja envuelve al input para poder colgar la lista justo debajo, del
   mismo ancho. La crea el JS alrededor del input, asi ninguna plantilla
   tiene que cambiar su marcado. */
.autocompletar-caja { position: relative; flex: 1; min-width: 240px; }
.autocompletar-caja > input { width: 100%; }

.autocompletar-lista {
  position: absolute; z-index: 40; left: 0; right: 0; top: calc(100% + 2px);
  margin: 0; padding: 4px; list-style: none;
  background: var(--superficie);
  border: 1px solid var(--borde-fuerte); border-radius: var(--radio-grande);
  box-shadow: var(--sombra-flotante);
  max-height: 280px; overflow-y: auto;
}
.autocompletar-lista[hidden] { display: none; }

.autocompletar-opcion {
  padding: 6px 9px; border-radius: var(--radio); cursor: pointer;
  font-size: var(--t-base); line-height: 1.35;
}
/* El estado activo se marca con FONDO, no solo con color de texto: tiene que
   verse de un vistazo cual va a entrar si se presiona Enter. Es la misma
   marca para el teclado y para el mouse -- una sola clase, no dos. */
.autocompletar-opcion.activa { background: var(--azul-tenue); }
.autocompletar-opcion .detalle { color: var(--suave); font-size: var(--t-sm); }
.autocompletar-vacio { padding: 6px 9px; color: var(--suave); font-size: var(--t-base); }

@media print { .autocompletar-lista { display: none !important; } }

input, select, textarea {
  font: inherit; font-size: var(--t-base); color: inherit; background: var(--superficie);
  border: 1px solid var(--borde-fuerte); border-radius: var(--radio);
  padding: 6px 10px; width: 100%;
}
input:focus, select:focus, textarea:focus {
  outline: 2px solid var(--azul-claro); outline-offset: -1px; border-color: var(--azul-claro);
}
textarea { resize: vertical; }
select[multiple] { resize: vertical; overflow-y: auto; }

/* Ojito para mostrar/ocultar contrasena (2026-08-25). El boton se agrega
   siempre como el ultimo hijo de .campo-clave, por eso el JS lo encuentra
   con previousElementSibling en vez de necesitar un id por campo. */
.campo-clave { position: relative; }
.campo-clave input { padding-right: 34px; }
.campo-clave .btn-ojo {
  position: absolute; right: 3px; top: 50%; transform: translateY(-50%);
  width: 26px; height: 26px; padding: 0; border: none; background: none;
  display: flex; align-items: center; justify-content: center;
  color: var(--suave); cursor: pointer; border-radius: var(--radio-chico);
}
.campo-clave .btn-ojo:hover { color: var(--azul); background: var(--azul-tenue); }
.campo-clave .btn-ojo svg { width: 18px; height: 18px; }

/* Un solo boton lleno por pantalla (la accion principal); el resto en claro,
   para que siempre se sepa cual es la accion esperada. */
button, .boton-claro {
  font: inherit; font-size: var(--t-base); cursor: pointer;
  border-radius: var(--radio); padding: 7px 14px;
  border: 1px solid var(--azul); background: var(--azul); color: #fff;
  font-weight: 600;
  text-decoration: none; display: inline-block; white-space: nowrap;
}
button:hover { background: var(--azul-fuerte); border-color: var(--azul-fuerte); }
.boton-claro {
  background: #fff; color: var(--texto); border-color: var(--borde);
  font-weight: 600;
}
.boton-claro:hover { background: #fff; border-color: var(--azul-claro); color: var(--azul); }
.boton-rojo { background: #fff; color: var(--rojo); border-color: #e0b4b0; }
.boton-rojo:hover { background: var(--rojo); color: #fff; }

/* Boton solido para acciones que no se pueden deshacer (limpiar bitacora). */
.boton-peligro { background: var(--rojo); border-color: var(--rojo); color: #fff; }
.boton-peligro:hover { background: #8f1c15; }
.boton-peligro:disabled {
  background: #e7c9c6; border-color: #e7c9c6; color: #fff; cursor: not-allowed;
}

.acciones { display: flex; gap: 8px; flex-wrap: wrap; }

.formulario { display: flex; flex-direction: column; gap: 12px; align-items: flex-start; }
.formulario label { display: block; width: 100%; font-size: var(--t-sm); color: var(--suave); }
.formulario label input, .formulario label select, .formulario label textarea { margin-top: 5px; }
.dos-columnas {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 14px; width: 100%;
}
.fila-form { display: flex; gap: 6px; align-items: center; }
.fila-form input { min-width: 150px; }
.fila-form .campo-clave { flex: 1; min-width: 150px; }
.fila-form .campo-clave input { min-width: 0; width: 100%; }

.zona-peligro { margin-top: 26px; }

/* ---------- Tablas ---------- */

.tabla-scroll { overflow-x: auto; background: #fff;
  border: 1px solid var(--borde); border-radius: var(--radio);
  box-shadow: var(--sombra); }
.panel .tabla-scroll { border: none; border-radius: 0; box-shadow: none; }

/* Barra fantasma arriba de una tabla ancha (2026-08-18): mismo ancho de
   scroll que la tabla real, puesta con JS (base.html) solo cuando hace
   falta. No es una tabla ni la duplica -- es un div vacio con la barra del
   navegador encima. Altura fija chica: solo tiene que existir la barra, no
   verse contenido adentro. */
.tabla-scroll-arriba { overflow-x: auto; overflow-y: hidden; height: 16px; }
.panel > .tabla-scroll-arriba { margin-left: -18px; margin-right: -18px; width: auto; }

table { border-collapse: collapse; width: 100%; font-size: var(--t-base); }
th, td { text-align: left; }
/* Encabezados sin franja de color: mayusculas chicas y grises sobre un
   fondo apenas distinto. La atencion queda en los datos, no en el marco. */
th {
  background: var(--superficie-2); color: var(--tenue); font-weight: 600;
  font-size: var(--t-xs); letter-spacing: .06em; text-transform: uppercase;
  white-space: nowrap; border-bottom: 1px solid var(--borde-fuerte);
  padding: 7px 12px;
}
/* Las filas se separan con una linea muy tenue, no con el borde fuerte.
   Alto resultante ~33px (antes ~41px): entran 6 u 8 filas mas por pantalla. */
td { border-bottom: 1px solid var(--borde-suave); padding: 8px 12px; }
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover { background: var(--superficie-2); }
.num, td.num, th.num { text-align: right; }
/* El enlace de tabla en peso normal: antes cada fila tenia dos o tres
   palabras en negrita azul y la pantalla entera pesaba igual. */
td a { color: var(--azul); font-weight: 400; text-decoration: none; }
td a:hover { text-decoration: underline; }
.mono { font-family: var(--fuente-mono); font-size: var(--t-sm); }
/* Una fila que se puede tocar tiene que parecer tocable. */
tr[onclick] { cursor: pointer; }
.destacado { font-weight: 700; font-size: 15px; letter-spacing: .5px; color: var(--azul); }

/* ---------- Listas de datos ---------- */

dl.datos {
  display: grid; grid-template-columns: minmax(150px, 210px) 1fr;
  gap: 8px 18px; margin: 0;
}
dl.datos dt { color: var(--suave); font-size: 13px; }
dl.datos dd { margin: 0; }

/* Codigo de barras dentro de la ficha del equipo */

.panel-con-barras {
  display: flex; gap: 26px; align-items: flex-start;
  justify-content: space-between; flex-wrap: wrap;
}
.panel-con-barras .datos { flex: 1 1 420px; }

.barras-ficha {
  flex: 0 0 auto; text-align: center;
  border: 1px solid var(--borde); border-radius: var(--radio);
  padding: 12px 14px 10px; background: #fff;
}
.barras-ficha svg { display: block; max-width: 100%; height: auto; margin: 0 auto; }
.barras-ficha-codigo {
  font-family: Consolas, "Courier New", monospace;
  font-weight: 700; font-size: 15px; letter-spacing: 1.5px; margin-top: 2px;
}
.barras-ficha-enlace {
  display: inline-block; margin-top: 7px;
  font-size: 12px; color: var(--azul-claro); text-decoration: none;
}
.barras-ficha-enlace:hover { text-decoration: underline; }
.barras-ficha-enlace-boton {
  display: inline-block; margin-top: 7px; margin-right: 10px;
  font-size: 12px; color: var(--azul-claro); text-decoration: none;
  background: none; border: none; padding: 0; cursor: pointer; font-weight: 700;
}
.barras-ficha-enlace-boton:hover { text-decoration: underline; }

/* ---------- Comentarios ---------- */

.comentario-nuevo { margin-bottom: 20px; }

ol.comentarios {
  list-style: none; margin: 0; padding: 0;
  border-top: 1px solid var(--borde);
}
ol.comentarios li { padding: 12px 0 13px; border-bottom: 1px solid var(--borde); }
ol.comentarios li:last-child { border-bottom: none; padding-bottom: 0; }

.comentario-cabecera {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  font-size: 13px; color: var(--suave); margin-bottom: 4px;
}
.comentario-fecha {
  font-family: Consolas, "Courier New", monospace;
  font-weight: 700; color: var(--azul); font-size: 14px;
}
.comentario-hora { font-family: Consolas, "Courier New", monospace; font-size: 12px; }
.comentario-autor {
  background: var(--superficie-2); border-radius: var(--radio-chico); padding: 1px 10px; font-size: 12px;
}
.comentario-etiqueta {
  color: var(--suave); font-size: 12px; font-style: italic;
}

/* Ultimo comentario asomado en la ficha del equipo */
.ultimo-comentario {
  border-left: 3px solid var(--borde); padding-left: 12px; margin-bottom: 14px;
}
.boton-comentarios { display: inline-block; }

/* Boton de comentarios en cada fila de la lista de equipos */
.boton-comentar {
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  border: 1px solid var(--borde); border-radius: var(--radio-chico); padding: 3px 11px;
  font-size: 13px; font-weight: 600; color: var(--azul);
  text-decoration: none; background: #fff;
}
.boton-comentar:hover { background: var(--azul-tenue); border-color: var(--azul-claro); }
.boton-comentar .cuenta {
  background: var(--azul); color: #fff; border-radius: var(--radio-chico);
  padding: 0 7px; font-size: 12px;
}

.comentario-borrar { margin-left: auto; }
.comentario-borrar button {
  background: none; border: none; color: var(--suave);
  font-size: 18px; line-height: 1; padding: 0 5px; border-radius: var(--radio);
}
.comentario-borrar button:hover { background: #fdecea; color: var(--rojo); }

/* El texto se muestra tal como se escribio, respetando los renglones. */
.comentario-texto { white-space: pre-wrap; }

.filtro-comentarios { align-items: flex-end; }
.filtro-comentarios .filtro-fecha {
  flex: 0 0 auto; font-size: 13px; color: var(--suave);
}
.filtro-comentarios .filtro-fecha input { margin-top: 4px; width: auto; }

.celda-comentario { white-space: pre-wrap; min-width: 260px; }
.sub-celda { color: var(--suave); font-size: 12px; }
.nowrap { white-space: nowrap; }

/* Descripcion de una linea de cotizacion: titulo + specs en renglones
   separados, tal como se guarda (ver descripcion_de_producto() en app.py). */
.descripcion-linea { white-space: pre-line; }

/* ---------- Roles y permisos ---------- */

.rol-chapa {
  background: rgba(255,255,255,.18); border-radius: var(--radio-chico);
  padding: 1px 9px; margin-left: 6px; font-size: 11.5px; font-weight: 600;
  color: #fff;
}

.celda-permisos { max-width: 520px; }
.permiso {
  display: inline-block; background: var(--superficie-2); border-radius: var(--radio);
  padding: 1px 7px; margin: 2px 3px 2px 0; font-size: 11.5px;
  font-family: Consolas, "Courier New", monospace; color: var(--suave);
}
.permiso.todo { background: #e7f5ec; color: var(--verde); font-weight: 700; }

/* Nota explicativa dentro de un panel */
.nota-panel { color: var(--suave); font-size: 13px; margin: -4px 0 16px; }
/* Cuando la nota va SUELTA debajo de una tabla/panel, no dentro de uno
   (ej. la leyenda de Disponibles/En proceso/En garantia bajo la tabla de
   familias en /equipos, 2026-08-13): separacion extra arriba para que no
   se lea pegada al bloque de encima. */
.nota-panel-separada { margin-top: 18px; }

/* Corregir un comentario desde la propia tabla (solo administrador) */
.editar-comentario { display: flex; gap: 6px; align-items: flex-start; }
.editar-comentario textarea { min-width: 240px; font-size: 13px; }
.boton-mini { padding: 3px 10px; font-size: 12px; }
.solo-imprimir-bloque { display: none; }
@media print { .solo-imprimir-bloque { display: block; } }

.vacio { color: var(--suave); }
.solo-imprimir { display: none; }

/* ---------- Venta y garantia ---------- */

/* El boton de vender es verde a proposito: es la accion que cierra el trato
   y tiene que distinguirse de un vistazo del resto de botones claros. */
.boton-vender {
  display: inline-block;
  background: var(--verde); color: #fff; border: 1px solid var(--verde);
  border-radius: var(--radio); padding: 5px 14px; font-size: 13px;
  font-weight: 600; text-decoration: none; cursor: pointer;
}
.boton-vender:hover { background: #17632f; color: #fff; }

.boton-vender-grande {
  background: var(--verde); border-color: var(--verde);
  padding: 11px 26px; font-size: 16px; font-weight: 600;
}
.boton-vender-grande:hover { background: #17632f; }

.menu-venta { background: rgba(255,255,255,.18); font-weight: 600; }

/* Como esta la garantia de un equipo, de un vistazo */
/* Base unificada arriba; aqui solo los modificadores. */
.chapa-garantia.vigente { background: var(--verde-fondo); border-color: #cfe0d6; color: var(--verde); }
.chapa-garantia.proxima-a-vencer { background: var(--ambar-fondo); border-color: #ebdcc0; color: var(--ambar); }
.chapa-garantia.vencida { background: var(--rojo-fondo); border-color: #e6cac7; color: var(--rojo); }

/* Estado de una solicitud de repuestos */
/* ---------- Chapas de estado (rediseno 2026-08-14) ----------
   De pildora pastel a etiqueta rectangular con punto de color. El punto lo
   pinta currentColor, asi que NO hay que declararlo en cada modificador.
   Un selector agrupado cubre las cinco familias sin tocar plantillas. */
.chapa-solicitud, .chapa-ot, .chapa-garantia, .chapa-capital, .chapa-estado,
.chapa-ingreso, .chapa-meta, .chapa-prioridad {
  display: inline-flex; align-items: center; gap: 6px;
  border-radius: var(--radio-chico); padding: 2px 8px;
  font-size: var(--t-xs); font-weight: 600; letter-spacing: .01em;
  white-space: nowrap;
  border: 1px solid var(--borde); background: var(--superficie); color: var(--suave);
}
.chapa-solicitud::before, .chapa-ot::before, .chapa-garantia::before,
.chapa-capital::before, .chapa-estado::before, .chapa-ingreso::before,
.chapa-meta::before, .chapa-prioridad::before {
  content: ""; width: 5px; height: 5px; border-radius: 50%;
  background: currentColor; flex-shrink: 0;
}
/* Prioridad de la Sugerencia de Traslado a Tienda (2026-08-21): alta = vale
   la pena traerla (verde), media = aporta algo (ambar), baja = ya hay algo
   muy parecido en el destino (gris neutral -- no es un error, solo no hace
   falta). */
.chapa-prioridad.alta { background: var(--verde-fondo); border-color: #cfe0d6; color: var(--verde); }
.chapa-prioridad.media { background: var(--ambar-fondo); border-color: #ebdcc0; color: var(--ambar); }
.chapa-prioridad.baja { background: var(--superficie-2); border-color: var(--borde); color: var(--suave); }

/* Lista de unidades dentro del <details> de "N disponibles" (Sugerencia de
   Traslado a Tienda, 2026-08-21) -- una por linea, con su casilla. */
.opcion-unidad { display: flex; align-items: center; gap: 6px; padding: 3px 0; }
/* Chapa en tamano grande, para la cabecera de un expediente. Antes se
   hacia con estilo suelto repetido en varias plantillas. */
.chapa-grande { font-size: var(--t-sm); padding: 4px 11px; }

.chapa-solicitud.pendiente { background: var(--ambar-fondo); border-color: #ebdcc0; color: var(--ambar); }
.chapa-solicitud.aprobada { background: var(--verde-fondo); border-color: #cfe0d6; color: var(--verde); }
.chapa-solicitud.rechazada { background: var(--rojo-fondo); border-color: #e6cac7; color: var(--rojo); }
/* Recepcion de traslados (2026-08-24): mismos colores que aprobada/rechazada,
   con el nombre de clase que usa ItemTraslado.estado ("aceptado"/"rechazado",
   distinto del genero de "aprobada"/"rechazada" de arriba). */
.chapa-solicitud.aceptado { background: var(--verde-fondo); border-color: #cfe0d6; color: var(--verde); }
.chapa-solicitud.rechazado { background: var(--rojo-fondo); border-color: #e6cac7; color: var(--rojo); }
.chapa-solicitud.en-compra { background: var(--naranja-fondo); border-color: #e8cdb4; color: #a1490a; }
.chapa-solicitud.disponible { background: var(--azul-fondo); border-color: #ccd9e6; color: var(--azul); }
.chapa-solicitud.entregada { background: var(--verde-fondo); border-color: #cfe0d6; color: var(--verde); }
.chapa-solicitud.finalizada { background: var(--superficie-2); border-color: var(--borde); color: var(--suave); }

/* Verificador de Familias (2026-08-17): completa / insuficiente / inexistente.
   Mismos tres colores y las mismas variables que las demas chapas -- verde lo
   que ya esta, ambar lo que falta completar, rojo lo que ni se ha empezado. */
.chapa-meta.completa { background: var(--verde-fondo); border-color: #cfe0d6; color: var(--verde); }
.chapa-meta.insuficiente { background: var(--ambar-fondo); border-color: #ebdcc0; color: var(--ambar); }
.chapa-meta.inexistente { background: var(--rojo-fondo); border-color: #e6cac7; color: var(--rojo); }

/* Estado de una orden de trabajo del Taller. Mismos colores que
   .chapa-solicitud, en una clase propia para que quede claro de que
   entidad es cada etiqueta. */
/* Base unificada arriba; aqui solo los modificadores. */
.chapa-ot.pendiente { background: var(--ambar-fondo); border-color: #ebdcc0; color: var(--ambar); }
.chapa-ot.aprobada { background: var(--verde-fondo); border-color: #cfe0d6; color: var(--verde); }
.chapa-ot.rechazada { background: var(--rojo-fondo); border-color: #e6cac7; color: var(--rojo); }
.chapa-ot.en-compra { background: var(--naranja-fondo); border-color: #e8cdb4; color: #a1490a; }
.chapa-ot.disponible { background: var(--azul-fondo); border-color: #ccd9e6; color: var(--azul); }
.chapa-ot.entregada { background: var(--verde-fondo); border-color: #cfe0d6; color: var(--verde); }

/* Semaforo de capital utilizado por socio (Control de Capital, 2026-08-10).
   Mismos 4 colores que ya usan .chapa-garantia/.chapa-solicitud, en una
   clase propia con sus 4 umbrales (verde/amarillo/naranja/rojo). Tecnomax
   no usa esta clase: no tiene limite. */
/* Base unificada arriba; aqui solo los 4 umbrales. Es un SEMAFORO: se
   desatura con el resto, pero nunca se le quita el color -- es la unica
   forma de leer el capital de un socio de un vistazo. */
.chapa-capital.verde { background: var(--verde-fondo); border-color: #cfe0d6; color: var(--verde); }
.chapa-capital.amarillo { background: var(--ambar-fondo); border-color: #ebdcc0; color: var(--ambar); }
.chapa-capital.naranja { background: var(--naranja-fondo); border-color: #e8cdb4; color: #a1490a; }
.chapa-capital.rojo { background: var(--rojo-fondo); border-color: #e6cac7; color: var(--rojo); }

/* Indicadores del dashboard de Solicitudes de Repuestos: version minimalista,
   sin iconos ni recuadros de color (a diferencia de .tarjeta del tablero de
   inicio, que se dejo intacta). Un punto de color es toda la señal. */
/* auto-fit y no repeat(6): el tablero de Cargas pone SIETE tarjetas y la
   septima caia sola en una segunda fila, descolgada (2026-08-16). Con
   auto-fit, seis siguen entrando en una fila y siete tambien. */
.tarjetas-repuestos {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px; margin-bottom: 22px;
}
.tarjeta-repuesto {
  display: block; text-decoration: none; color: inherit;
  background: #fff; border: 1px solid var(--borde); border-radius: var(--radio);
  padding: 14px 16px;
  transition: border-color .12s, background .12s;
}
/* Solo la que de verdad lleva a algun lado se ilumina: una tarjeta que se ve
   igual y no responde al clic es una promesa rota (2026-08-16). */
a.tarjeta-repuesto:hover { border-color: var(--azul-claro); background: var(--superficie-2); }
.tarjeta-repuesto-etiqueta {
  display: flex; align-items: center; gap: 7px;
  font-size: 11px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .6px; color: var(--suave); margin-bottom: 10px;
}
.tarjeta-repuesto-punto {
  width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0;
  background: var(--color-punto, var(--suave));
}
.tarjeta-repuesto-numero {
  font-size: 26px; font-weight: 700; color: var(--texto);
  letter-spacing: -.5px; line-height: 1;
}

@media (max-width: 1100px) {
  .tarjetas-repuestos { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 640px) {
  .tarjetas-repuestos { grid-template-columns: repeat(2, 1fr); }
}

.texto-rojo { color: var(--rojo); }
.texto-verde { color: var(--verde); }

/* Grafico mensual de Gestion de Cargas: barras simples en CSS puro, sin
   depender de ninguna libreria externa (el sistema no usa ninguna). */
.grafico-barras-css {
  display: flex; align-items: flex-end; gap: 6px;
  height: 160px; padding-top: 20px;
}
.grafico-barras-css-columna {
  flex: 1; display: flex; flex-direction: column; align-items: center;
  height: 100%; justify-content: flex-end;
}
.grafico-barras-css-valor { font-size: 11px; color: var(--suave); margin-bottom: 3px; }
.grafico-barras-css-barra {
  width: 100%; max-width: 26px; border-radius: var(--radio-chico) 4px 0 0;
  background: var(--azul-claro, var(--azul));
  height: var(--altura, 0%); min-height: 2px;
  transition: height .2s;
}
.grafico-barras-css-etiqueta {
  font-size: 10px; color: var(--suave); margin-top: 6px; white-space: nowrap;
}

/* Aviso de tracking duplicado, debajo del campo (Gestion de Cargas). */
.aviso-tracking { padding: 4px 8px; margin: 4px 0 0; font-size: 11.5px; }

/* Una venta anulada sigue en la lista, pero apagada */
.fila-anulada td { color: var(--suave); text-decoration: line-through; }
.fila-anulada td:last-child { text-decoration: none; }

.precio-final { font-size: 17px; margin: 4px 0 0; }
.precio-final b { color: var(--azul); font-size: 22px; }

/* En el mostrador el precio se lee, no se escribe: se muestra como un dato
   fijo y no como una casilla, para que nadie intente cambiarlo ahi. */
.precio-fijo {
  margin-top: 5px;
  padding: 8px 12px;
  background: var(--azul-tenue);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  font-size: 20px;
  font-weight: 700;
  color: var(--azul);
  font-variant-numeric: tabular-nums;
}

.sub-titulo {
  font-size: 14px; color: var(--suave); font-weight: 600;
  margin: 18px 0 8px; padding-top: 12px; border-top: 1px solid var(--borde);
}

/* Checklist de accesorios que deja el cliente */
.checklist { display: flex; flex-direction: column; gap: 8px; }
.checklist-fila { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.checklist-casilla {
  display: flex; align-items: center; gap: 7px;
  min-width: 150px; font-size: 14px; cursor: pointer;
}
.checklist-casilla input { width: auto; margin: 0; }
.checklist-nota { flex: 1; min-width: 180px; font-size: 13px; }

/* Chip con icono para cada accesorio (2026-08-11): mismo lenguaje visual
   que ".chip-especial" de la ficha tecnica (icono + pastilla que se
   resalta al marcarla), pero definido aqui porque estas pantallas
   (garantia, taller) no cargan ficha.css. */
.chip-accesorio {
  display: flex; align-items: center; gap: 8px; cursor: pointer; user-select: none;
  border: 1px solid var(--borde); border-radius: var(--radio-chico); padding: 7px 14px 7px 10px;
  min-width: 150px; font-size: 14px; color: var(--texto);
  transition: background .12s, border-color .12s, color .12s;
}
.chip-accesorio input { position: absolute; opacity: 0; width: 0; height: 0; }
.chip-accesorio svg { width: 20px; height: 20px; flex: 0 0 auto; }
.chip-accesorio:hover { border-color: var(--azul-claro); }
.chip-accesorio.elegida { background: #e6f0fb; border-color: #b9d3f0; color: var(--azul); }
.chip-accesorio.deshabilitado { cursor: default; opacity: .75; }
.chip-accesorio input:focus-visible ~ svg { outline: 2px solid var(--azul-claro); outline-offset: 2px; }

/* ---------- Tablero de inicio ---------- */

/* .miga se definia aqui por segunda vez y, por venir despues, le ganaba a
   la de arriba. Eliminada el 2026-08-14: la definicion unica esta con los
   titulos, cerca de h1/h2, que es donde se busca. */

.tarjetas {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 16px; margin-bottom: 22px;
}
/* Tarjeta de resumen del tablero: mas sobria. Sin sombra grande, sin
   levantarse al pasar el mouse y sin la barra de color a la izquierda -- el
   dato manda, no el adorno. */
.tarjeta {
  display: block; text-decoration: none; color: inherit;
  background: #fff; border: 1px solid var(--borde); border-radius: var(--radio);
  padding: 15px 17px; position: relative; overflow: hidden;
  box-shadow: var(--sombra);
  transition: border-color .12s;
}
.tarjeta:hover { border-color: var(--azul-claro); }
.tarjeta-alto {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
}
.tarjeta-etiqueta {
  font-size: 12.5px; color: var(--suave); font-weight: 600;
  text-transform: uppercase; letter-spacing: .7px;
}
.tarjeta-icono {
  width: 42px; height: 42px; border-radius: var(--radio-grande); flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; font-size: 19px;
  background: var(--fondo-icono, #e8f0f8);
}
.tarjeta-numero {
  font-size: var(--t-dato); font-weight: 600; letter-spacing: -.02em;
  color: var(--azul-fuerte); margin: 6px 0 2px; line-height: 1;
  font-variant-numeric: tabular-nums;
}
.tarjeta-pie { font-size: 12.5px; color: var(--suave); }
.delta { font-weight: 700; padding: 1px 7px; border-radius: var(--radio-chico); font-size: 11.5px; }
.delta.sube { background: #e8f5ec; color: var(--verde); }
.delta.avisa { background: #fdf3e3; color: #a1600a; }

.filas-inicio { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }

.lista-avisos { display: flex; flex-direction: column; gap: 2px; }
.item-aviso {
  display: flex; align-items: center; gap: 13px; padding: 11px;
  border-radius: var(--radio-grande); text-decoration: none; color: inherit;
}
.item-aviso:hover { background: var(--fondo); }
.dias {
  width: 50px; height: 48px; border-radius: var(--radio-grande); flex-shrink: 0;
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; line-height: 1;
  background: #fdf3e3; color: #a1600a;
}
.dias b { font-size: 17px; font-weight: 700; }
.dias span {
  font-size: 9.5px; text-transform: uppercase; letter-spacing: .5px; margin-top: 2px;
}
.dias.urgente { background: #fdecea; color: var(--rojo); }
.item-datos { min-width: 0; }
.item-datos b { display: block; font-size: 14px; font-weight: 600; }
.item-datos span { font-size: 12.5px; color: var(--suave); }

/* ---------- Inventario agrupado por familias ---------- */

.barra-vista {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin: 0 0 14px;
}
.conmutador {
  display: inline-flex; background: #fff; border: 1px solid var(--borde);
  border-radius: var(--radio); padding: 2px; gap: 2px;
}
.conmutador a {
  padding: 5px 12px; border-radius: var(--radio); font-size: 13px; font-weight: 600;
  color: var(--suave); text-decoration: none;
}
.conmutador a:hover { background: var(--fondo); color: var(--azul); }
.conmutador a.activa { background: var(--azul); color: #fff; font-weight: 600; }

/* El conmutador de los dos mundos del inventario (Laptops / Otro
   Inventario, 2026-08-13). Reutiliza .conmutador entero; solo se le da aire
   propio porque va suelto arriba de la pantalla y no dentro de
   .barra-vista. */
.conmutador-mundos { margin: 0 0 14px; }

.tabla-familias { width: 100%; border-collapse: collapse; }
.tabla-familias > thead th { white-space: nowrap; }
.tabla-familias .num { text-align: right; font-variant-numeric: tabular-nums; }

/* ---------- Grupos de marca (2026-08-13) ----------
   Un nivel por encima de las familias. Cada grupo es un <tbody> con una
   sola fila de cabecera; sus familias son los <tbody class="familia"> que
   vienen despues, marcados con el mismo data-marca (no se pueden anidar
   <tbody>, ver el JS de lista_agrupada.html). */
.fila-marca { cursor: pointer; }
.fila-marca > td {
  background: #eaf0f7; border-top: 1px solid var(--borde);
  padding: 10px 14px; font-size: 14px;
}
.fila-marca:hover > td { background: #e1eaf4; }
.nombre-marca {
  color: var(--azul); text-transform: uppercase; letter-spacing: .6px;
}
.cuenta-marca { color: var(--suave); font-size: 12.5px; margin-left: 10px; }

/* Mismo triangulo que el de familia, un poco mas grande por ser el nivel
   de arriba. */
.flecha-marca {
  display: inline-block; width: 0; height: 0; margin-right: 10px;
  vertical-align: middle;
  border-top: 6px solid transparent; border-bottom: 6px solid transparent;
  border-left: 8px solid var(--azul); transition: transform .12s;
}
.grupo-marca.abierta .flecha-marca { transform: rotate(90deg); }

/* Familia escondida porque su grupo de marca esta cerrado. Es distinto de
   que la familia este cerrada: eso solo esconde sus equipos. */
.familia.marca-cerrada { display: none; }

/* Cada familia es un <tbody>. Abierta o cerrada se decide con la clase. */
.fila-familia { cursor: pointer; }
.fila-familia:hover > td { background: var(--azul-tenue); }
.fila-familia > td {
  border-top: 1px solid var(--borde);
  padding-top: 9px; padding-bottom: 9px;
}
.familia.abierta .fila-familia > td { background: var(--azul-tenue); }

/* El triangulo del explorador de carpetas: apunta a la derecha cerrado y
   hacia abajo abierto. Se dibuja con CSS para que no dependa de ninguna
   fuente ni imagen. */
.flecha-familia {
  display: inline-block; width: 0; height: 0; margin-right: 9px;
  vertical-align: middle;
  border-top: 5px solid transparent; border-bottom: 5px solid transparent;
  border-left: 7px solid var(--azul-claro);
  transition: transform .12s;
}
.familia.abierta .flecha-familia { transform: rotate(90deg); }

.codigo-familia { font-size: 15px; color: var(--azul); letter-spacing: .5px; }

/* Alineacion unica de los botones de accion (2026-08-13, pedido del usuario):
   antes .acciones-familia venia justo despues del texto del codigo en el
   flujo normal, asi que familias con codigo mas largo (ej. "1507-LB" vs
   "1308") empujaban sus botones mas a la derecha que las demas filas. Ahora
   el bloque codigo+flecha tiene ancho fijo y la celda es flex, asi los
   botones siempre arrancan en la misma columna sin importar el largo del
   codigo. */
.celda-familia { display: flex; align-items: center; }
.codigo-familia-bloque { display: inline-block; width: 92px; flex: 0 0 auto; }

/* Menu de tres puntos de cada familia (2026-08-20): reemplaza los 6
   botones apilados (Editar/Precios/Imprimir/Accion/Existencias/Renombrar),
   que estiraban la fila a lo alto sin necesidad -- ver
   alternarMenuFamilia() en base.html. */
.menu-familia { position: relative; display: inline-block; vertical-align: middle; margin-left: 10px; }
.menu-familia-boton {
  width: 30px; height: 30px; display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--borde); border-radius: var(--radio); background: #fff;
  color: var(--suave); font-size: 16px; line-height: 1; cursor: pointer;
}
.menu-familia-boton:hover { background: #f2f6fa; color: var(--texto); }
.menu-familia-lista {
  position: absolute; top: calc(100% + 4px); right: 0; min-width: 150px;
  background: #fff; border: 1px solid var(--borde); border-radius: var(--radio-grande);
  box-shadow: var(--sombra-flotante); padding: 6px; display: none; z-index: 5;
}
.menu-familia.abierta .menu-familia-lista { display: block; }
.menu-familia-lista a {
  display: block; padding: 8px 10px; color: var(--texto); text-decoration: none;
  font-size: var(--t-base); border-radius: var(--radio); white-space: nowrap;
}
.menu-familia-lista a:hover { background: #e8f0f8; color: var(--azul); }
/* El item "Imprimir" es un <form>/<button> (manda un POST que imprime
   directo, no un enlace de descarga) pero se ve identico a los demas. */
.menu-familia-lista form { margin: 0; }
.menu-familia-lista .boton-menu-familia {
  display: block; width: 100%; text-align: left; padding: 8px 10px;
  color: var(--texto); font-size: var(--t-base); font-family: inherit;
  border: none; background: none; border-radius: var(--radio); cursor: pointer;
}
.menu-familia-lista .boton-menu-familia:hover { background: #e8f0f8; color: var(--azul); }

/* Los equipos de la familia viven en una fila que ocupa todo el ancho. */
.fila-equipos > td { padding: 0; background: var(--superficie-2); }
.familia:not(.abierta) .fila-equipos { display: none; }

.tabla-equipos { width: 100%; border-collapse: collapse; }
.tabla-equipos th {
  background: #f2f6fa; color: var(--suave); font-size: 10.5px;
  text-transform: uppercase; letter-spacing: .7px; padding: 7px 12px;
  border-bottom: 1px solid var(--borde);
}
.tabla-equipos th:first-child, .tabla-equipos td:first-child { padding-left: 34px; }
.tabla-equipos td {
  padding: 9px 12px; font-size: 13.5px; border-bottom: 1px solid var(--superficie-2);
}
.tabla-equipos tr:last-child td { border-bottom: none; }
.tabla-equipos tbody tr { cursor: pointer; }
.tabla-equipos tbody tr:hover td { background: var(--azul-tenue); }
/* El equipo cuyo nombre coincide con lo buscado, marcado para encontrarlo
   de un vistazo cuando la familia trae muchos. */
.tabla-equipos tr.resaltado td { background: #fff8e1; }
.tabla-equipos tr.resaltado td:first-child { box-shadow: inset 4px 0 0 #e0a800; }
/* La ultima laptop agregada (2026-08-13): recordatorio personal, se apaga
   solo -- ver mostrar_marca_reciente() en app.py. Selector sin
   ".tabla-equipos" porque "Lista completa" (lista.html) usa una tabla sin
   esa clase. */
tr.reciente td { background: #e8f2fb; }
tr.reciente td:first-child { box-shadow: inset 4px 0 0 var(--azul-claro); }

@media print {
  .familia .fila-equipos { display: table-row !important; }
  .barra-vista { display: none !important; }
  /* Al imprimir sale el inventario COMPLETO, sin importar que grupos de
     marca quedaran cerrados en pantalla (2026-08-13) -- mismo criterio que
     la linea de arriba con las familias. */
  .familia.marca-cerrada { display: table-row-group !important; }
}

/* ---------- Centro de Captura ---------- */

.puertas {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 16px; margin-bottom: 22px;
}
.puerta {
  display: block; text-decoration: none; color: inherit;
  background: #fff; border: 1px solid var(--borde); border-radius: var(--radio-grande);
  padding: 22px; box-shadow: none;
  transition: transform .12s, box-shadow .12s;
}
.puerta[href$="#scanner"] { cursor: default; opacity: .92; }
.puerta:not([href$="#scanner"]):hover {
  box-shadow: none;
}
.puerta-icono {
  width: 52px; height: 52px; border-radius: var(--radio-grande);
  display: flex; align-items: center; justify-content: center; font-size: 25px;
  background: var(--fondo-icono, #e8f0f8); margin-bottom: 14px;
}
.puerta h2 { font-size: 17px; margin: 0 0 8px; }
.puerta p { font-size: 13.5px; color: var(--texto); margin: 0 0 8px; }
.puerta .puerta-nota { color: var(--suave); font-size: 12.5px; }
.puerta-cuenta {
  display: inline-block; margin-top: 6px; font-size: 12px; font-weight: 600;
  color: var(--suave); background: var(--fondo); border-radius: var(--radio-chico);
  padding: 3px 11px;
}

/* Elegir entre dar de alta uno o varios equipos */
.modos { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.modo {
  display: flex; gap: 11px; align-items: flex-start; cursor: pointer;
  border: 1px solid var(--borde); border-radius: var(--radio-grande); padding: 14px 16px;
  background: #fff; transition: border-color .12s, background .12s;
}
.modo:hover { border-color: var(--azul-claro); }
.modo input { width: auto; margin: 2px 0 0; flex-shrink: 0; }
.modo span { font-size: 13px; color: var(--suave); line-height: 1.45; }
.modo span b {
  display: block; font-size: 14.5px; color: var(--texto);
  font-weight: 600; margin-bottom: 3px;
}
.modo:has(input:checked) { border-color: var(--azul); background: #f4f8fc; }

.tres-columnas {
  display: grid; grid-template-columns: repeat(3, minmax(150px, 1fr));
  gap: 14px; width: 100%;
}
.previo { font-size: 13.5px; color: var(--suave); margin: 12px 0 0; }
.previo b { color: var(--azul); font-family: Consolas, "Courier New", monospace; }

.ids-nuevos {
  list-style: none; padding: 0; margin: 0 0 14px;
  display: flex; flex-wrap: wrap; gap: 8px;
}
.ids-nuevos li {
  background: #e8f0f8; color: var(--azul); border-radius: var(--radio);
  padding: 6px 13px; font-weight: 700; font-size: 14px;
}

@media (max-width: 700px) {
  .modos { grid-template-columns: 1fr; }
  .tres-columnas { grid-template-columns: 1fr; }
}

ol.pasos, ol.pasos-asistente { margin: 0; }
ol.pasos { padding-left: 20px; color: var(--texto); font-size: 14px; }
ol.pasos li { margin-bottom: 5px; }

/* Los tres pasos del asistente de importacion */
.pasos-asistente {
  display: flex; gap: 8px; flex-wrap: wrap;
  list-style: none; padding: 0; margin: 0 0 20px;
}
.pasos-asistente li {
  display: flex; align-items: center; gap: 8px;
  background: #fff; border: 1px solid var(--borde); border-radius: var(--radio);
  padding: 8px 16px; font-size: 13.5px; color: var(--suave);
}
.pasos-asistente li b {
  width: 21px; height: 21px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--fondo); color: var(--suave); font-size: 12px;
}
.pasos-asistente li.activo {
  border-color: var(--azul); color: var(--azul); font-weight: 600;
}
.pasos-asistente li.activo b { background: var(--azul); color: #fff; }
.pasos-asistente li.hecho { color: var(--verde); border-color: #bcdfc9; }
.pasos-asistente li.hecho b { background: var(--verde); color: #fff; }

/* Relacionar columna del archivo con campo del sistema */
.mapeo { display: flex; flex-direction: column; }
.mapeo-fila {
  display: grid; grid-template-columns: 1fr 280px; gap: 14px;
  align-items: center; padding: 11px 0; border-bottom: 1px solid var(--borde);
}
.mapeo-fila:last-child { border-bottom: none; }
.mapeo-fila label b { display: block; font-weight: 600; font-size: 14.5px; }
.mapeo-donde {
  font-size: 11.5px; color: var(--suave); text-transform: uppercase;
  letter-spacing: .6px;
}
.mapeo-fila select { width: 100%; }

@media (max-width: 1000px) {
  .puertas { grid-template-columns: 1fr; }
  .mapeo-fila { grid-template-columns: 1fr; gap: 6px; }
}

/* ---------- Configuracion ---------- */

.ajustes { display: flex; flex-direction: column; }
.ajuste {
  display: grid; grid-template-columns: 1fr 210px; gap: 6px 20px;
  padding: 16px 0; border-bottom: 1px solid var(--borde); align-items: start;
}
.ajuste:first-child { padding-top: 0; }
.ajuste:last-child { border-bottom: none; }
.ajuste label { font-size: 15px; }
.ajuste label b { display: block; font-weight: 600; }
.ajuste-ayuda {
  display: block; font-size: 13px; color: var(--suave); margin-top: 3px;
  max-width: 62ch;
}
.ajuste-campo { grid-row: span 2; }
.ajuste-campo input { width: 100%; font-size: 17px; font-weight: 600; }
.ajuste-defecto {
  display: block; font-size: 11.5px; color: var(--suave); margin-top: 5px;
}
.ajuste-rastro { font-size: 12px; color: var(--suave); }

@media (max-width: 1100px) {
  .tarjetas { grid-template-columns: repeat(2, 1fr); }
  .filas-inicio { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
  .tarjetas { grid-template-columns: 1fr; }
  .ajuste { grid-template-columns: 1fr; }
  .ajuste-campo { grid-row: auto; }
}

/* ---------- Pantalla de entrada ---------- */

.pantalla-login {
  display: flex; align-items: center; justify-content: center;
  min-height: 100vh; padding: 20px; background: var(--azul);
}
.tarjeta-login {
  background: #fff; border-radius: var(--radio-grande); padding: 34px 30px;
  width: 100%; max-width: 380px;
  display: flex; flex-direction: column; gap: 14px;
  box-shadow: 0 2px 12px rgba(11,35,56,.16);
}
.tarjeta-login img { height: 40px; width: auto; align-self: center; }
.tarjeta-login h1 { font-size: 19px; text-align: center; color: var(--azul); margin: 0 0 4px; }
.tarjeta-login label { font-size: 13px; color: var(--suave); }
.tarjeta-login input { margin-top: 5px; }
.tarjeta-login button { margin-top: 6px; padding: 10px; }

/* ---------- Ubicaciones y traslados ---------- */

.barra-traslado {
  position: sticky; bottom: 0; margin-top: 14px;
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  background: #fff; border: 1px solid var(--borde); border-radius: var(--radio-grande);
  padding: 12px 16px; box-shadow: var(--sombra-flotante);
}
.barra-traslado label { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--suave); }
.barra-traslado select { width: auto; }
.barra-traslado #cuenta-traslado { font-weight: 600; color: var(--azul); }

/* Cantidad a trasladar, Sugerencia de Traslado a Tienda (2026-08-21). */
.barra-cantidad {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-bottom: 10px; padding-bottom: 10px; border-bottom: 1px solid var(--borde);
}
.barra-cantidad label { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--suave); }

/* ---------- CRM de conversaciones (Fase 1, 2026-08-12) ---------- */

/* Tres zonas: lista, hilo y ficha. En pantallas angostas se apilan, con la
   lista primero (es por donde se entra). */
.crm-cuerpo {
  display: grid; gap: 14px; align-items: start;
  grid-template-columns: minmax(240px, 320px) minmax(320px, 1fr) minmax(230px, 300px);
}
@media (max-width: 1100px) { .crm-cuerpo { grid-template-columns: 1fr; } }

.crm-lista { padding: 6px; max-height: 70vh; overflow-y: auto; }
.crm-fila {
  display: block; text-decoration: none; color: inherit;
  padding: 9px 11px; border-radius: var(--radio); border: 1px solid transparent;
}
.crm-fila:hover { background: var(--fondo); }
.crm-fila.activa { background: #eef4fa; border-color: var(--azul-claro); }
.crm-fila + .crm-fila { border-top: 1px solid var(--borde); border-radius: 0; }
.crm-fila-alto { display: flex; justify-content: space-between; gap: 8px; align-items: baseline; }
.crm-fecha { font-size: 11.5px; color: var(--suave); white-space: nowrap; }
.crm-fila-medio { display: flex; gap: 8px; font-size: 12px; color: var(--suave); }
.crm-canal { font-weight: 600; }
.crm-ultimo {
  font-size: 12.5px; color: var(--suave); margin: 3px 0 5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.crm-fila-chips { display: flex; flex-wrap: wrap; gap: 5px; }

.chip-crm {
  font-size: 11px; padding: 2px 8px; border-radius: var(--radio-chico);
  border: 1px solid var(--borde); background: #fff; color: var(--suave);
}
.chip-crm.pendiente { background: #fdecea; border-color: #f3c4c0; color: var(--rojo); }
.chip-crm.archivada { background: #eef0f3; }
.chip-crm.estado-ganada { background: #e7f5ec; border-color: #bcdfc9; color: var(--verde); }
.chip-crm.estado-perdida { background: #fdecea; border-color: #f3c4c0; color: var(--rojo); }
.chip-crm.estado-cotizada { background: #fff4e0; border-color: #f0d3a0; color: #8a5a00; }

.crm-hilo { display: flex; flex-direction: column; min-height: 320px; }
.crm-hilo-cabecera {
  display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  border-bottom: 1px solid var(--borde); padding-bottom: 9px; margin-bottom: 10px;
}
.crm-hilo-cabecera .acciones { display: flex; gap: 6px; }
.crm-numero { font-size: 12px; color: var(--suave); margin-left: 6px; }
.crm-sub { font-size: 12.5px; color: var(--suave); margin-top: 2px; }

.crm-mensajes { display: flex; flex-direction: column; gap: 9px; max-height: 44vh; overflow-y: auto; }
.crm-mensaje { max-width: 82%; padding: 8px 11px; border-radius: var(--radio-grande); border: 1px solid var(--borde); }
.crm-mensaje.entrante { align-self: flex-start; background: var(--fondo); }
.crm-mensaje.saliente { align-self: flex-end; background: #eef4fa; border-color: #cfe0ee; }
.crm-mensaje.nota { align-self: stretch; background: #fffbe9; border-color: #f0e2b0; max-width: none; }
.crm-mensaje-texto { white-space: pre-wrap; font-size: 14px; }
.crm-mensaje-pie { font-size: 11px; color: var(--suave); margin-top: 4px; }

.crm-responder { margin-top: 12px; }
.crm-aviso-canal {
  font-size: 12.5px; color: #8a5a00; background: #fff4e0;
  border: 1px solid #f0d3a0; border-radius: var(--radio); padding: 7px 10px; margin-bottom: 6px;
}
.crm-responder textarea { width: 100%; background: #f2f4f7; color: var(--suave); }
.crm-nota-form { display: flex; gap: 8px; align-items: flex-end; margin-top: 10px; }
.crm-nota-form textarea { flex: 1; }

.crm-lateral h3 { font-size: 13px; color: var(--azul); margin: 14px 0 5px; }
.crm-lateral h3:first-child { margin-top: 0; }
.crm-datos { display: grid; grid-template-columns: auto 1fr; gap: 3px 10px; margin: 0; font-size: 13px; }
.crm-datos dt { color: var(--suave); }
.crm-datos dd { margin: 0; }
.crm-mini-lista { list-style: none; padding: 0; margin: 6px 0 0; font-size: 12.5px; }
.crm-mini-lista li { padding: 2px 0; border-bottom: 1px solid var(--borde); }
.crm-form-mini { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.crm-form-mini label { font-size: 12px; color: var(--suave); }
.crm-form-mini button { align-self: flex-start; }
.crm-familia { font-weight: 600; margin: 0; }
.vacio-mini { font-size: 12.5px; color: var(--suave); margin: 4px 0; }
/* Los filtros de la bandeja van en una sola linea que se parte sola. Sin
   esto, cada select ocupaba el ancho completo (input/select nacen con
   width:100%) y quedaban uno debajo del otro. */
.filtro-crm { flex-wrap: wrap; align-items: center; }
.filtro-crm select { width: auto; min-width: 160px; flex: 0 0 auto; }
.filtro-crm .filtro-fecha { width: auto; flex: 0 0 auto; }
.filtro-crm .filtro-fecha input { width: auto; }
.filtro-crm input[name="buscar"] { flex: 1 1 240px; min-width: 200px; }

/* ---------- Financiamiento (calculadora de cuotas, 2026-08-12) ---------- */

/* La cuota es el dato que el vendedor le dice al cliente: se muestra grande
   y sola, como el numero de una tarjeta del tablero. */
.panel-cuota { text-align: center; }
.cuota-etiqueta {
  margin: 0; font-size: 13px; color: var(--suave);
  text-transform: uppercase; letter-spacing: .04em;
}
.cuota-numero {
  margin: 6px 0; font-size: 40px; font-weight: 700; color: var(--azul);
  line-height: 1.1;
}
.cuota-pie { margin: 0; font-size: 13px; color: var(--suave); }

/* El desglose paso a paso (monto, comision, subtotal, intereses, total):
   la misma lectura de arriba hacia abajo que tenia la hoja de Excel. */
.tabla-desglose { width: 100%; max-width: 460px; border-collapse: collapse; }
.tabla-desglose td { padding: 7px 0; border-bottom: 1px solid var(--borde); }
.tabla-desglose td.num { text-align: right; font-variant-numeric: tabular-nums; }
.tabla-desglose .fila-subtotal td { font-weight: 600; }
.tabla-desglose .fila-total td {
  font-weight: 700; color: var(--azul); border-bottom: none;
}

/* Fila de total generica para cualquier tabla de datos (2026-08-21):
   pensada para un <tfoot>, asi no se cuenta como fila del cuerpo. */
tfoot .fila-total td {
  font-weight: 700; color: var(--azul); border-top: 2px solid var(--azul);
}

/* El plazo elegido, dentro de la tabla de todos los plazos del banco. */
tr.fila-elegida td { background: #fff8e1; }
tr.fila-elegida td:first-child { box-shadow: inset 4px 0 0 #e0a800; }

/* ---------- Casillas (mudadas desde ficha.css el 2026-08-14) ----------
   Componente generico: una casilla con su texto al lado. Vivia en ficha.css,
   que base.html no carga, asi que fuera de la Ficha Tecnica salia sin
   estilo. La ficha las sigue viendo igual. */

.casillas { display: flex; flex-direction: column; gap: 10px; }
.casilla {
  display: flex; align-items: center; gap: 9px; cursor: pointer; font-size: 14px;
}
.casilla input { width: 17px; height: 17px; margin: 0; flex: 0 0 auto; }

/* ---------- Repuestos en transito (2026-08-14) ----------
   Indicador de atraso para dentro de una tabla. Es distinto de ".dias" del
   tablero de inicio a proposito: aquel es una caja de 50x48 pensada para
   una lista de avisos, y dentro de una celda se come la fila. Aqui hace
   falta algo que quepa en linea con el texto.
   El color NO reemplaza al numero: "9 dias tarde" se lee igual en blanco y
   negro o si alguien no distingue rojo de verde. */

.atraso {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.atraso::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: var(--verde); flex-shrink: 0;
}
.atraso.tibio::before { background: var(--ambar); }
.atraso.tarde::before { background: var(--rojo); }
.atraso.tarde { color: var(--rojo); font-weight: 600; }
.atraso.sin-fecha { color: var(--suave); }
.atraso.sin-fecha::before { background: var(--borde); }

/* Fila de una orden atrasada. Tono muy suave: la fila sigue siendo
   legible, el que grita es el indicador de arriba. */
tr.fila-atrasada td { background: #fdf6f5; }
tr.fila-proxima td { background: #fffcf5; }

/* Celda de existencias del catalogo de repuestos: el numero grande es lo
   LIBRE (lo que de verdad se puede tomar hoy) y debajo, chiquito, lo que
   esta apartado y lo que viene en camino. Los tres van juntos siempre. */
.existencias b { font-size: 15px; }
.existencias .sub-celda { margin-top: 2px; }

/* ---------- Campos opcionales plegados (2026-08-14) ----------
   Para que un formulario largo se abra corto. El sistema no usaba <details>
   en ninguna pantalla; este es el primero. Se usa en las dos pantallas de
   compra de repuestos. */

details.opcionales {
  border-top: 1px dashed var(--borde);
  margin-top: 14px; padding-top: 12px;
}
details.opcionales > summary {
  cursor: pointer; list-style: none;
  font-size: 13px; font-weight: 600; color: var(--azul);
  display: flex; align-items: center; gap: 7px;
}
details.opcionales > summary::-webkit-details-marker { display: none; }
details.opcionales > summary::before {
  content: "+"; font-weight: 700; font-size: 15px; line-height: 1;
  width: 16px; text-align: center;
}
details.opcionales[open] > summary::before { content: "\2212"; }
details.opcionales > summary:focus-visible {
  outline: 2px solid var(--azul-claro); outline-offset: 2px; border-radius: var(--radio-chico);
}
details.opcionales > *:not(summary) { margin-top: 12px; }

/* El total del lote, calculado en vivo debajo del formulario de compra. */
.total-lote {
  display: flex; flex-wrap: wrap; gap: 6px 18px; align-items: baseline;
  background: var(--azul-tenue); border-radius: var(--radio);
  padding: 11px 14px; margin-top: 14px; font-size: 13.5px;
}
.total-lote b { font-size: 16px; color: var(--azul-fuerte);
  font-variant-numeric: tabular-nums; }
.total-lote .rotulo { color: var(--suave); }

/* ---------- Arreglos de clases que se usaban sin existir (2026-08-14) ----------
   Encontrados al revisar el modulo de repuestos. Son el mismo tipo de error
   que ".chapa-estado" del 2026-08-12: la clase esta en el HTML pero no en
   ninguna hoja, asi que no hacia nada. */

/* Se usa en 7 plantillas (catalogo e inventario de repuestos, categorias,
   tipos y compatibilidades de cargadores, socios, prefijos TMX, cuentas
   bancarias) y no existia: los botones de accion quedaban pegados. */
.celda-acciones {
  display: flex; gap: 6px; flex-wrap: wrap; align-items: center;
}
.celda-acciones form { display: inline; margin: 0; }

/* (tr[onclick] se movio arriba, junto a las reglas de tabla.) */

/* Chapa de estado en tamano grande, para la cabecera de un expediente.
   Se venia haciendo con estilo suelto repetido en varias pantallas. */
.chapa-grande { font-size: 14px; padding: 5px 14px; }

/* Fila de una pieza dentro del formulario de solicitud. Antes reutilizaba
   .mapeo-fila (la rejilla de 2 columnas del asistente de importacion de
   Excel), asi que el boton "Quitar" que agrega el JS entraba como tercer
   hijo de un grid de dos y caia fuera de sitio. */
.fila-pieza {
  display: flex; gap: 8px; flex-wrap: wrap; align-items: flex-end;
  margin-bottom: 10px;
}
.fila-pieza > label { flex: 1 1 220px; margin: 0; }
.fila-pieza > label.cantidad-pieza { flex: 0 0 110px; }

/* Aviso en vivo de si la pieza ya esta en bodega, mientras se escribe la
   solicitud. Verde = no hace falta comprar; ambar = habra que comprarla. */
.aviso-existencia {
  font-size: 13px; border-radius: var(--radio); padding: 9px 12px; margin: 4px 0 0;
  border: 1px solid var(--borde); background: var(--fondo);
}
.aviso-existencia.hay { border-color: #bcdfc9; background: #e7f5ec; color: var(--verde); }
.aviso-existencia.no-hay { border-color: #f0d3a0; background: #fff4e0; color: var(--ambar); }

/* Tarjeta de una pieza dentro del expediente de la solicitud. Antes era un
   .panel dentro de otro .panel con estilo suelto, apoyado en una variable
   (--fondo-suave) que no existe en :root -- se veia por el color de
   respaldo, de casualidad. */
.tarjeta-pieza {
  background: var(--fondo); border: 1px solid var(--borde);
  border-radius: var(--radio-grande); padding: 14px 16px; margin-top: 12px;
}

/* ---------- Detalle plegable dentro de una tarjeta (2026-08-14) ----------
   Para una tabla que repite lo mismo muchas veces. Caso que lo motivo: una
   laptop con 8 modulos de RAM identicos gastaba ocho filas para decir
   "16 GB". Arriba queda una linea que resume, y el detalle se abre si de
   verdad hace falta.

   Se abre solo (atributo "open" desde la plantilla) cuando hay pocas filas:
   con una o dos, plegarlo seria pedir un clic para nada. */

details.detalle > summary {
  cursor: pointer; list-style: none;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: var(--t-base); color: var(--suave);
  padding: 4px 0;
}
details.detalle > summary::-webkit-details-marker { display: none; }
details.detalle > summary::before {
  content: "\25B8"; color: var(--tenue); font-size: 11px;
  width: 10px; flex: 0 0 auto; transition: transform .12s;
}
details.detalle[open] > summary::before { transform: rotate(90deg); }
details.detalle > summary:hover { color: var(--azul); }
details.detalle > summary:focus-visible {
  outline: 2px solid var(--azul-claro); outline-offset: 2px; border-radius: var(--radio-chico);
}
/* El "Ver los 8 modulos" a la derecha: es la accion, y se lee como enlace. */
details.detalle > summary .ver {
  margin-left: auto; color: var(--azul); font-weight: 600; font-size: var(--t-sm);
}
/* Variante "simple": el detalle no tiene una linea que lo resuma, asi que el
   texto va pegado a la flecha en vez de empujado a la derecha (si no, queda
   solo y desconectado al otro extremo del panel). La usa Bateria, donde lo
   unico que se muestra arriba es la salud. */
details.detalle.simple > summary .ver { margin-left: 0; }
/* El detalle puede ser una tabla o una lista de datos: las dos respiran igual. */
details.detalle > .datos { margin-top: 10px; }
details.detalle[open] > summary .ver-abrir,
details.detalle:not([open]) > summary .ver-cerrar { display: none; }
details.detalle > .tabla-scroll { margin-top: 10px; }
/* Al imprimir sale todo abierto, pero eso NO se puede hacer desde CSS: el
   navegador esconde el contenido de <details> por su cuenta, no con display.
   Lo abre un script de base.html en "beforeprint". Aqui solo se esconde la
   flecha y el "Ver los N", que en papel no significan nada. */
@media print {
  details.detalle > summary::before,
  details.detalle > summary .ver { display: none; }
}

/* ---------- PESTANAS (mudadas desde ficha.css el 2026-08-14) ----------
   Componente reutilizable: separan grandes categorias de informacion en una
   pantalla que si no seria larguisima. Dentro de cada hoja van las tarjetas
   (.panel) de siempre.

   Vivian en ficha.css, que base.html no carga, asi que solo servian en la
   Ficha Tecnica y en la Orden de Trabajo. Ahora funcionan en cualquier
   pantalla, y el JavaScript que las mueve esta una sola vez en base.html.

   Cuando usarlas: la pantalla pasa de dos pantallas de alto, son bloques
   distintos (no filas repetidas) y normalmente se mira uno a la vez. Si
   alguna respuesta es no, no llevan pestanas. */

.pestanas {
  display: flex; gap: 2px; flex-wrap: wrap;
  margin: 0 0 16px;
  border-bottom: 1px solid var(--borde);
}
.pestanas .pestana {
  background: none; border: 0; border-bottom: 2px solid transparent;
  border-radius: var(--radio-chico) var(--radio-chico) 0 0;
  color: var(--suave); font-weight: 600; font-size: var(--t-base);
  padding: 9px 14px; margin-bottom: -1px; white-space: nowrap; cursor: pointer;
}
.pestanas .pestana:hover { background: var(--superficie-2); color: var(--azul); }
.pestanas .pestana.activa { color: var(--azul); border-bottom-color: var(--azul); }
.pestanas .pestana:focus-visible { outline: 2px solid var(--azul-claro); outline-offset: -2px; }
/* Contador al lado del nombre ("Costos y repuestos 3"): dice cuanto hay
   adentro sin obligar a entrar. */
.pestanas .pestana .cuenta {
  font-weight: 400; font-size: var(--t-xs); color: var(--tenue); margin-left: 5px;
}

/* La hoja de cada pestana. ".panel-ficha" y ".panel-ot" son los nombres que
   ya usaban la Ficha Tecnica y el Taller: se conservan para no tocar esas
   dos plantillas, y ".hoja" es el nombre para lo que venga de ahora en mas. */
.hoja.oculto, .panel-ficha.oculto, .panel-ot.oculto { display: none; }

/* ---------- Linea de tiempo del ciclo (2026-08-14) ----------
   Distinta de la Bitacora (que es una tabla): la bitacora cuenta TODO lo que
   paso y crece sin limite; esto muestra los hitos del ciclo, incluidos los
   que todavia NO ocurrieron. Ese es su valor: se ve lo que falta.
   Los pendientes van al 55% en vez de esconderse, para que la pantalla
   ensene el proceso completo sin manual. */

.linea-tiempo { list-style: none; margin: 0; padding: 0 0 0 24px; position: relative; }
.linea-tiempo::before {
  content: ""; position: absolute; left: 4px; top: 7px; bottom: 7px;
  width: 2px; background: var(--borde);
}
.lt-item { position: relative; padding-bottom: 18px; }
.lt-item:last-child { padding-bottom: 0; }
.lt-item::before {
  content: ""; position: absolute; left: -24px; top: 4px;
  width: 10px; height: 10px; border-radius: 50%;
  background: #fff; border: 2px solid var(--borde); box-sizing: border-box;
}
.lt-item.hecho::before { background: var(--verde); border-color: var(--verde); }
.lt-item.aqui::before {
  background: var(--azul); border-color: var(--azul);
  box-shadow: 0 0 0 3px var(--azul-tenue);
}
.lt-item.pendiente { opacity: .55; }
.lt-titulo { font-size: 14px; font-weight: 600; }
.lt-item.aqui .lt-titulo { color: var(--azul); }
.lt-meta { font-size: 12.5px; color: var(--suave); font-variant-numeric: tabular-nums; }
.lt-nota { font-size: 13px; margin-top: 2px; }

/* ---------- Editor de etiqueta personalizada (2026-08-15) ----------
   Un mini disenador de etiquetas 3x1 para la BT320. La regla de oro esta en
   el JS de la plantilla: TODO se guarda en milimetros sobre la etiqueta
   real, nunca en pixeles de pantalla. El pixel cambia con el monitor y con
   el zoom; el milimetro es el mismo en la pantalla y en el papel. */

.eti-barra { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.eti-sep { width: 1px; height: 22px; background: var(--borde); margin: 0 3px; }
.eti-grupo { display: inline-flex; border: 1px solid var(--borde); border-radius: var(--radio); overflow: hidden; }
.eti-grupo .boton-mini { border: 0; border-right: 1px solid var(--borde); border-radius: 0; }
.eti-grupo .boton-mini:last-child { border-right: 0; }
.eti-barra .boton-mini.activa {
  background: var(--azul); border-color: var(--azul); color: #fff;
}

/* Dos columnas: la etiqueta manda, las propiedades acompanan. */
.eti-cols { grid-template-columns: 1fr 300px; align-items: start; }
@media (max-width: 900px) { .eti-cols { grid-template-columns: 1fr; } }

.eti-zona {
  display: flex; justify-content: center;
  padding: 22px 22px 30px; background: var(--superficie-2);
  border: 1px solid var(--borde); border-radius: var(--radio); overflow: auto;
}
.eti-marco { position: relative; flex: 0 0 auto; }
/* El lienzo es la etiqueta fisica: blanco, con su borde real. */
.eti-lienzo {
  position: relative; background: #fff; border: 1px solid var(--borde-fuerte);
  overflow: hidden;
}
/* Lo que la impresora no garantiza en el borde. */
.eti-segura { position: absolute; border: 1px dashed var(--borde-fuerte); pointer-events: none; }
.eti-regla {
  position: absolute; font-size: var(--t-xs); color: var(--tenue);
  font-family: var(--fuente-mono);
}
.eti-regla.ancho { left: 0; right: 0; bottom: -18px; text-align: center; }
.eti-regla.alto { top: 0; bottom: 0; right: -46px; display: flex; align-items: center; }

/* Cada texto de la etiqueta. Arial y negro puro: es lo que dibuja GDI del
   otro lado (ver impresora_etiquetas.py). */
.eti-texto {
  position: absolute; white-space: pre; cursor: move; user-select: none;
  font-family: Arial, Helvetica, sans-serif; color: #000; line-height: 1;
  padding: 1px 2px; border: 1px solid transparent;
}
.eti-texto:hover { border-color: var(--azul-borde, #b9d3f0); }
.eti-texto.elegido { border-color: var(--azul); background: rgba(31, 78, 121, .05); }
.eti-texto.fuera { border-color: var(--rojo); background: rgba(153, 32, 26, .08); }
/* En la vista previa no se dibuja ningun marco: solo el resultado. */
.eti-texto.sin-marco { border-color: transparent !important; background: none !important; cursor: default; }

.eti-aviso-zona { font-size: var(--t-base); margin: 12px 0 0; }
.eti-aviso-zona.bien { color: var(--verde); }
.eti-aviso-zona.mal { color: var(--rojo); font-weight: 600; }

.eti-previa { max-width: 90vw; }

/* ---------- Impresion ---------- */

@media print {
  body { background: #fff; font-size: 11pt; }
  .barra, .pie, .no-imprimir, .buscador, .contadores { display: none !important; }
  .solo-imprimir { display: grid; }
  main { padding: 0; }
  .contenedor { max-width: none; padding: 0; }
  .panel { border: 1px solid #bbb; border-radius: 0; padding: 10px 12px;
    margin-bottom: 12px; break-inside: avoid; }
  .tabla-scroll { border: none; overflow: visible; }
  th { background: #e6e6e6 !important; -webkit-print-color-adjust: exact; }
  a { color: #000; text-decoration: none; }
  /* Al imprimir salen TODAS las pestanas, no solo la que estaba abierta: en
     papel no hay donde hacer clic. */
  .hoja.oculto, .panel-ficha.oculto, .panel-ot.oculto { display: block !important; }
}

/* ---------- Documentos de un caso de garantia (2026-08-15) ----------
   Los tres papeles del caso (recepcion, etiqueta, reporte) viven dentro del
   panel "Estado del caso", separados del resto por una regla: son
   consecuencia del estado, no un bloque suelto encima del boton de guardar. */
.documentos-caso {
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--borde-suave);
}
.documentos-caso h3 {
  font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .5px;
  color: var(--tenue); font-weight: 700; margin: 0 0 8px;
}
.documentos-caso form { margin: 0; }

/* ---------- Trabajo tecnico: panel del tecnico y reparto (2026-08-15) ----------
   Filas-tarjeta en vez de tabla a proposito: el tecnico abre "Mi taller" en el
   telefono con las manos ocupadas, y una tabla ahi deja los botones fuera de
   pantalla. Reutiliza .item-aviso / .dias; esto solo agrega el contenedor y la
   fila de acciones. */
.fila-trabajo {
  padding: 4px 0 10px;
}
.fila-trabajo + .fila-trabajo {
  border-top: 1px solid var(--borde-suave);
}
.fila-trabajo.detenida .item-datos b { color: var(--suave); }
.acciones-trabajo {
  display: flex; gap: 8px; flex-wrap: wrap; align-items: center;
  padding: 0 11px 0 74px;   /* alineado con .item-datos, salvando el bloque de dias */
}
.acciones-trabajo form { margin: 0; }
.acciones-trabajo .detalle { margin: 0; }
.fila-trabajo .aviso { margin: 4px 11px 8px 74px; }

/* Barra de "asignar los marcados": queda pegada al pie de la tabla. */
.barra-asignar {
  margin-top: 12px; padding-top: 12px;
  border-top: 1px solid var(--borde-suave);
}

@media (max-width: 700px) {
  /* En telefono los botones vuelven al margen: ya no hay lugar para
     alinearlos con el texto. */
  .acciones-trabajo, .fila-trabajo .aviso { padding-left: 11px; margin-left: 11px; }
}

/* ---------- Identificacion y fotos de la PIEZA (2026-08-15, Fase 2) ----------
   Antes una solicitud decia "solicito pantalla" y compras tenia que adivinar
   cual. Estos campos no son obligatorios: lo que empuja a llenarlos es el
   medidor, que ven tanto el que pide como el que compra. */
.bloque-pieza + .bloque-pieza {
  margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--borde-suave);
}
.rejilla-pieza {
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px 14px; margin: 8px 0 10px;
}
.rejilla-pieza .ancho-completo { grid-column: 1 / -1; }
.rejilla-pieza label { font-size: var(--t-sm); color: var(--suave); }
.rejilla-pieza input, .rejilla-pieza select { width: 100%; margin-top: 4px; }

.identificacion-pieza {
  margin: 10px 0; padding: 10px 0; border-top: 1px solid var(--borde-suave);
}

/* Cuantos de los datos que sirven para comprar trae la pieza. Ambar mientras
   falte algo, verde cuando ya se puede comprar sin preguntar. */
.medidor-compra {
  margin: 6px 0 10px; padding: 7px 11px; font-size: var(--t-sm);
  border-radius: var(--radio); border: 1px solid #eeddb9;
  background: var(--ambar-fondo); color: #6e4611;
}
.medidor-compra.completo {
  border-color: #cfe0d6; background: var(--verde-fondo); color: var(--verde);
}

/* Galeria de la pieza, separada de la del equipo a proposito: la etiqueta de
   una pantalla no dice nada sobre la laptop. Va en estilo.css y NO en
   ficha.css, que base.html no carga (mismo caso de .casillas el 2026-08-14). */
.galeria-pieza {
  display: flex; gap: 12px; flex-wrap: wrap; margin: 10px 0;
}
.foto-pieza {
  margin: 0; width: 190px; border: 1px solid var(--borde);
  border-radius: var(--radio); overflow: hidden; background: var(--superficie);
}
.foto-pieza img { width: 100%; height: 130px; object-fit: cover; display: block; }
.foto-pieza figcaption {
  padding: 7px 9px; font-size: var(--t-sm); line-height: 1.4;
}
.foto-pieza figcaption .vacio { display: block; font-size: var(--t-xs); margin-top: 3px; }
/* Las dos categorias que llevan un numero que compras va a LEER se marcan en
   azul; el resto en gris. Una miniatura no deja leer un Part Number, asi que
   el rotulo tiene que decir que hay adentro. */
.marca-foto {
  display: inline-block; padding: 1px 7px; border-radius: var(--radio-chico);
  font-size: var(--t-xs); font-weight: 600; text-transform: uppercase;
  letter-spacing: .4px; background: var(--superficie-2); color: var(--suave);
  border: 1px solid var(--borde);
}
.marca-foto.identifica {
  background: var(--azul); color: #fff; border-color: var(--azul);
}

/* Botones que abren la camara directo, con la categoria ya decidida. */
.botones-foto { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 6px; }
.botones-foto form { margin: 0; }
.boton-foto { cursor: pointer; display: inline-block; }

@media (max-width: 700px) {
  .rejilla-pieza { grid-template-columns: 1fr; }
  .foto-pieza { width: 100%; }
}

/* ---------- Expediente tecnico de la laptop (2026-08-15, Fase 3) ----------
   Reutiliza .linea-tiempo / .lt-* de la historia de una pieza. Lo unico propio
   es esconder las lineas que no son hitos: ".oculto" a secas solo estaba
   definido para .hoja/.panel-ficha/.panel-ot, asi que aqui hace falta la
   regla. Sin el conmutador, el expediente son 300 lineas de "cambio
   ram_instalada" y nadie lo abre dos veces. */
.lt-item.solo-todo.oculto { display: none; }
.lt-item.solo-todo { opacity: .75; }
@media print {
  /* En papel sale TODO: no hay donde hacer clic, mismo criterio que las
     pestanas y los detalles plegables. */
  .lt-item.solo-todo.oculto { display: list-item !important; }
}

/* ---------- Lo que falta para cerrar una orden (2026-08-15, Fase 4) ----------
   No alcanza con negarle el boton al tecnico: hay que decirle QUE le falta y
   llevarlo a donde se resuelve. Ambar, no rojo: no es un error, es trabajo
   que todavia no termino. */
.falta-cerrar {
  margin: 4px 11px 8px 74px; padding: 8px 11px;
  border: 1px solid #eeddb9; border-left: 3px solid var(--ambar);
  background: var(--ambar-fondo); border-radius: var(--radio);
  font-size: var(--t-sm); color: #6e4611;
}
.falta-cerrar ul { margin: 4px 0 0; padding-left: 18px; }
.falta-cerrar li { margin: 2px 0; }
.falta-cerrar a { color: inherit; }

@media (max-width: 700px) {
  .falta-cerrar { margin-left: 11px; }
}

/* ---------- Sugerencias del analisis de comentarios (2026-08-15, Fase 5) ----
   Van SIEMPRE pegadas al comentario del que salieron: una sugerencia sola se
   lee como diagnostico, y esto lo hace una heuristica de palabras clave que
   puede fallar. */
.sugerencia { margin-bottom: 6px; line-height: 1.35; }
.sugerencia:last-child { margin-bottom: 0; }
.sugerencia .sub-celda { display: block; }

/* Propuesta del reparto automatico (2026-08-15): se distingue del resto
   porque todavia NO esta guardada. */
.panel-propuesta { border-left: 3px solid var(--azul); }

/* ---------- Carga de importacion: la tabla de lineas (2026-08-16) ----------
   .tabla-carga-lineas y .fila-linea-carga se usaban en cargas_form.html
   desde que nacio el modulo y NO existian en ninguna hoja: los anchos de
   columna vivian como style="width:Npx" repetidos en los <th> y no habia
   nada mas. Mismo caso que .celda-acciones (2026-08-14).

   Es la pantalla donde el agente de aduanas pasa casi todo su tiempo y una
   carga real llega a 20+ trackings, asi que la tabla tiene encabezado
   pegajoso, numero de fila y las lineas de tipo "Laptop" marcadas: son las
   unicas que entran al inventario y las unicas que reparten flete. */

/* La tarifa por Kg es la misma en casi todas las lineas de una carga real:
   se escribe una vez arriba y se copia sola. La columna sigue existiendo
   porque una linea puede tener otra. */
.control-tarifa {
  display: flex; gap: 8px 18px; flex-wrap: wrap; align-items: flex-end;
  margin-bottom: 14px;
}
.control-tarifa label {
  flex: 0 0 240px; font-size: var(--t-sm); color: var(--suave);
}
.control-tarifa label input,
.control-tarifa label select { margin-top: 5px; width: 100%; }

/* Forma de envio: DOS BOTONES excluyentes, no un desplegable (2026-08-16).
   Elegir es un clic en vez de dos, y el activo dice con que tarifa esta
   calculada la carga sin abrir nada. El activo va en azul porque es el
   ESTADO de la carga, no una accion pendiente. */
.campo-envio { flex: 0 0 auto; }
.rotulo-envio {
  display: block; font-size: var(--t-sm); color: var(--suave);
}
.botones-envio { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 5px; }
.boton-envio { display: inline-flex; align-items: baseline; gap: 7px; }
.boton-envio .precio-envio {
  font-weight: 400; font-size: var(--t-sm); color: var(--suave);
  font-variant-numeric: tabular-nums;
}
.boton-envio.activa {
  background: var(--azul); border-color: var(--azul); color: #fff;
}
.boton-envio.activa:hover { background: var(--azul-claro); border-color: var(--azul-claro); color: #fff; }
.boton-envio.activa .precio-envio { color: #fff; opacity: .85; }
.control-tarifa p {
  flex: 1 1 260px; margin: 0 0 5px; color: var(--suave); font-size: var(--t-base);
}

/* Pie de la tabla: el boton y su ayuda en la misma linea. */
.pie-lineas-carga {
  display: flex; gap: 10px; flex-wrap: wrap; align-items: center;
  margin-top: 10px;
}
.pie-lineas-carga span { color: var(--suave); font-size: var(--t-base); }

.tabla-carga-lineas { counter-reset: linea-carga; }
.tabla-carga-lineas th { position: sticky; top: 0; z-index: 2; }
/* La altura la limita el contenedor, no la tabla: asi el encabezado se queda
   arriba y la barra de totales (pegajosa abajo) siempre se ve. */
.caja-lineas-carga { max-height: 56vh; overflow: auto; }

.tabla-carga-lineas th.col-num,
.tabla-carga-lineas td.col-num { width: 34px; text-align: right; color: var(--tenue); }
.tabla-carga-lineas td.col-num::before {
  counter-increment: linea-carga; content: counter(linea-carga);
  font-size: var(--t-sm); font-variant-numeric: tabular-nums;
}
.tabla-carga-lineas th.col-cantidad, .tabla-carga-lineas td.col-cantidad { width: 88px; }
/* Cargadores declarados por el agente de aduanas (2026-08-17). */
.tabla-carga-lineas th.col-tipo, .tabla-carga-lineas td.col-tipo { width: 140px; }
.tabla-carga-lineas th.col-cargadores,
.tabla-carga-lineas td.col-cargadores { width: 96px; }
.tabla-carga-lineas th.col-peso, .tabla-carga-lineas td.col-peso { width: 96px; }
.tabla-carga-lineas th.col-forma, .tabla-carga-lineas td.col-forma { width: 152px; }
/* Un campo bloqueado por no aplicar (cargadores en una fila que no es Laptop):
   se ve apagado pero SIGUE viajando en el envio -- es readonly, no disabled,
   porque el servidor lee las columnas por posicion. */
.campo-apagado { background: var(--azul-fondo); color: var(--tenue); }
.tabla-carga-lineas th.col-total, .tabla-carga-lineas td.col-total { width: 96px; text-align: right; }
.tabla-carga-lineas th.col-quitar, .tabla-carga-lineas td.col-quitar { width: 74px; }
.tabla-carga-lineas td { padding: 5px 8px; vertical-align: top; }
.tabla-carga-lineas input, .tabla-carga-lineas select { margin: 0; }

/* Filete azul en la fila que SI entra al inventario -- mismo recurso que
   .campo-familia usa para "esto pertenece a algo mayor". Se pinta sobre la
   primera celda porque un <tr> no admite borde con border-collapse. */
.fila-linea-carga td:first-child { border-left: 3px solid transparent; }
.fila-linea-carga.es-laptop td:first-child { border-left-color: var(--azul); }
/* Una fila a la que le falta un dato que cuesta plata (tracking o peso). */
.fila-linea-carga.incompleta td { background: var(--ambar-fondo); }

/* En el telefono siete columnas de inputs no se usan, y el agente puede
   estar en la aduana. Cada linea pasa a ser una tarjeta, igual que
   .fila-pieza y las filas-tarjeta de /mi-taller. */
@media (max-width: 900px) {
  .caja-lineas-carga { max-height: none; }
  .tabla-carga-lineas thead { display: none; }
  .tabla-carga-lineas, .tabla-carga-lineas tbody { display: block; width: auto; }
  /* Va con "tr.fila-linea-carga" y las celdas con ".col-*": las reglas de
     ancho de arriba llevan clase + tipo, y una clase sola perdia contra
     ellas -- la tarjeta nunca se armaba y las celdas conservaban sus anchos
     de escritorio (encontrado midiendo a 375px, no leyendo el CSS). */
  .tabla-carga-lineas tr.fila-linea-carga {
    border: 1px solid var(--borde); border-radius: var(--radio);
    padding: 8px; margin-bottom: 10px;
    display: grid; grid-template-columns: 1fr 1fr; gap: 6px 8px;
  }
  .tabla-carga-lineas tr.fila-linea-carga.es-laptop { border-left: 3px solid var(--azul); }
  .tabla-carga-lineas td { border: none; padding: 0; width: auto; }
  .tabla-carga-lineas td:first-child { border-left: none; }
  .tabla-carga-lineas td::before {
    content: attr(data-rotulo); display: block;
    font-size: var(--t-xs); color: var(--tenue); text-transform: uppercase;
    letter-spacing: .06em; margin-bottom: 2px;
  }
  /* El tracking es el dato largo: ocupa la fila entera, arriba. */
  .tabla-carga-lineas td.col-tracking { grid-column: 1 / -1; order: 1; width: auto; }
  .tabla-carga-lineas td.col-num { display: none; }
  .tabla-carga-lineas td.col-cantidad { order: 2; width: auto; }
  .tabla-carga-lineas td.col-tipo { order: 4; width: auto; }
  .tabla-carga-lineas td.col-cargadores { order: 5; width: auto; }
  .tabla-carga-lineas td.col-peso { order: 6; width: auto; }
  .tabla-carga-lineas td.col-forma { order: 7; width: auto; }
  .tabla-carga-lineas td.col-total {
    order: 8; width: auto; text-align: left; align-self: end;
  }
  .tabla-carga-lineas td.col-quitar {
    order: 9; width: auto; text-align: right; align-self: end;
  }
  .tabla-carga-lineas td.col-quitar::before { content: none; }
}

/* La barra de totales no puede quedar fuera de pantalla mientras se escribe
   la fila 15: se queda pegada abajo de la tarjeta. Reutiliza .total-lote
   (el mismo componente de la compra de repuestos) y por eso lleva sombra:
   es de las pocas cosas que de verdad flotan sobre el contenido. */
.total-lote.pegajoso {
  position: sticky; bottom: 0; z-index: 3;
  box-shadow: var(--sombra-flotante);
}
/* El flete por laptop es la consecuencia de lo que se escribe arriba, no un
   total mas: va separado del resto de la barra. */
.total-lote .consecuencia {
  flex-basis: 100%; margin: 0; padding-top: 7px;
  border-top: 1px solid #cfdcea; color: var(--suave); font-size: var(--t-base);
}
.total-lote .consecuencia b { font-size: var(--t-md); }

/* ---------- Sugerencias de familia al dar de alta (2026-08-16) ----------
   El sistema recomienda; la persona decide. Por eso son OPCIONES elegibles y
   no un aviso que solo se lee: cada una es una salida distinta y ninguna
   viene impuesta. */
.panel-sugerencias { border-left: 3px solid var(--azul); }

.opcion-familia {
  display: flex; gap: 9px; align-items: flex-start;
  border: 1px solid var(--borde); border-radius: var(--radio);
  padding: 10px 12px; margin-bottom: 8px; cursor: pointer;
}
.opcion-familia:hover { border-color: var(--azul-claro); background: var(--superficie-2); }
.opcion-familia input { width: auto; margin: 3px 0 0; flex-shrink: 0; }
.opcion-cuerpo { display: flex; flex-direction: column; gap: 3px; }
/* El color dice de que TIPO de coincidencia se trata, con el mismo criterio
   del resto del sistema: verde lo que calza, ambar lo que espera un dato,
   rojo lo que de verdad se contradice. */
.opcion-familia.clara { border-left: 3px solid var(--verde); }
.opcion-familia.posible { border-left: 3px solid var(--ambar); }
.opcion-familia.diferente { border-left: 3px solid var(--rojo); }
.opcion-familia .dif-confirmada { font-size: var(--t-base); color: var(--rojo); }
.opcion-familia .sin-determinar { font-size: var(--t-base); color: var(--ambar); }

/* Fila que necesita que una persona la mire antes de darla por buena
   (Catalogo de Componentes y "Completar familias", 2026-08-16). Ambar, no
   rojo: no esta mal, esta sin avalar. */
tr.revisar td { background: var(--ambar-fondo); }

/* ---------- Entregar la carga a Bodega (2026-08-16) ----------
   La accion es irreversible PARA EL AGENTE (pierde la edicion), asi que no
   puede vivir en la fila de acciones junto a "Volver". Va en su propia
   tarjeta al pie, con los numeros que se congelan a la vista.
   NO lleva rojo a proposito: no es destructivo, es el paso normal del
   trabajo -- un rojo aqui enseñaria a ignorar el rojo donde si importa. */
.panel-entrega { border-left: 3px solid var(--azul); }
.panel-entrega .resumen-entrega {
  background: var(--azul-tenue); border-radius: var(--radio);
  padding: 10px 13px; margin: 12px 0; font-size: var(--t-base);
}
.panel-entrega .resumen-entrega b { font-variant-numeric: tabular-nums; }
.panel-entrega .confirmar-entrega {
  display: flex; align-items: flex-start; gap: 8px;
  margin: 12px 0; font-size: var(--t-md);
}
.panel-entrega .confirmar-entrega input { width: auto; margin: 2px 0 0; }

/* ---------- Nuevo Ingreso: la hoja de costos de una carga (2026-08-17) ----
   Pantalla de trabajo de quien lleva la contabilidad. La decision de diseno
   es que el COSTO REAL (compra + flete) sea lo mas grande de cada bloque:
   es el unico numero que se copia a Sage, y el que Hugo venia calculando a
   mano. Lo que escribe es chico; lo que se lleva es grande. */
.chapa-ingreso.gris { background: var(--superficie-2); border-color: var(--borde); color: var(--suave); }
.chapa-ingreso.ambar { background: var(--ambar-fondo); border-color: #ebdcc0; color: var(--ambar); }
.chapa-ingreso.azul { background: var(--azul-fondo); border-color: #ccd9e6; color: var(--azul); }
.chapa-ingreso.verde { background: var(--verde-fondo); border-color: #cfe0d6; color: var(--verde); }

/* "Que falta" en la lista: varias faltas apiladas, no una frase larga. */
.celda-falta { display: flex; flex-direction: column; gap: 3px; }
.celda-falta .falta { font-size: var(--t-xs); color: var(--ambar); font-weight: 600; }
.celda-falta .falta.suave { color: var(--suave); font-weight: 500; }

/* Encabezado de la importacion: datos de solo lectura, en rejilla. */
.datos-ingreso {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
}
.datos-ingreso > div {
  background: var(--superficie-2); border: 1px solid var(--borde);
  border-radius: var(--radio); padding: 9px 12px;
}
.datos-ingreso span { display: block; font-size: var(--t-xs); color: var(--suave); margin-bottom: 2px; }
.datos-ingreso b { font-size: var(--t-md); font-variant-numeric: tabular-nums; }
/* El flete por laptop es el numero que entra en cada costo: se destaca. */
.datos-ingreso .destacado { background: var(--azul-tenue); border-color: #ccd9e6; }
.datos-ingreso .destacado b { color: var(--azul); }

.campo-ebay { font-family: var(--fuente-mono); font-size: var(--t-sm); margin: 0; }

/* Un bloque por modelo: es la unidad con la que llega la factura. */
.modelo-ingreso {
  border: 1px solid var(--borde); border-radius: var(--radio);
  padding: 13px 15px; margin-bottom: 13px;
}
/* Barra izquierda como semaforo silencioso: ambar si le falta costo, borde
   normal si ya lo tiene. Sin rojo: que falte un costo no es un error. */
.modelo-ingreso.pendiente { border-left: 3px solid var(--ambar); }
.modelo-ingreso.listo { border-left: 3px solid var(--verde); }
.modelo-ingreso-cabeza {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 12px; flex-wrap: wrap; margin-bottom: 10px;
}
.modelo-ingreso-cabeza .suave { color: var(--suave); font-size: var(--t-sm); margin-left: 8px; }
.modelo-ingreso-cuenta { font-size: var(--t-sm); color: var(--suave); }
.modelo-ingreso-cuenta .falta { color: var(--ambar); font-weight: 600; margin-left: 8px; }
.aviso-modelo {
  background: var(--ambar-fondo); border: 1px solid #ebdcc0;
  border-radius: var(--radio-chico); padding: 7px 11px;
  font-size: var(--t-sm); color: var(--ambar); margin: 0 0 10px;
}
.modelo-ingreso-cuerpo {
  display: grid; grid-template-columns: minmax(180px, 240px) 1fr;
  gap: 18px; align-items: start;
}
.modelo-ingreso-cuerpo label { margin: 0; }
.modelo-ingreso-cuenta-real {
  display: flex; gap: 24px; flex-wrap: wrap;
  background: var(--azul-tenue); border-radius: var(--radio);
  padding: 10px 14px; align-self: stretch; align-items: center;
}
.modelo-ingreso-cuenta-real span { display: block; font-size: var(--t-xs); color: var(--suave); }
.modelo-ingreso-cuenta-real b { font-variant-numeric: tabular-nums; }
.modelo-ingreso-cuenta-real small { display: block; font-size: var(--t-xs); color: var(--suave); }
.numero-grande { font-size: 22px; color: var(--azul); line-height: 1.2; }
.modelo-ingreso-detalle { margin-top: 11px; }
.modelo-ingreso-detalle summary {
  cursor: pointer; font-size: var(--t-sm); color: var(--azul);
}
.modelo-ingreso-detalle .tabla-scroll { margin-top: 9px; }

.barra-guardar {
  display: flex; align-items: center; gap: 13px;
  margin: 16px 0 22px;
}
.barra-guardar .suave { color: var(--suave); font-size: var(--t-sm); }

.panel-listo { border-left: 3px solid var(--azul); }

@media (max-width: 700px) {
  .modelo-ingreso-cuerpo { grid-template-columns: 1fr; gap: 11px; }
}

/* Detector de Familias Similares (2026-08-17). Tres clases chicas, todas con
   variables ya existentes: ni un hexadecimal suelto ni un radio literal. */
.nota-menor {
  display: block; font-size: var(--t-xs); color: var(--suave);
  font-weight: 400; letter-spacing: 0;
}
.grupo-similar {
  border: 1px solid var(--borde); border-radius: var(--radio);
  padding: 10px 12px; margin-top: 10px;
}
.grupo-similar h3 {
  margin: 0 0 6px; font-size: var(--t-md); display: flex;
  align-items: center; gap: 8px; flex-wrap: wrap;
}
.lista-simple { margin: 0; padding-left: 18px; }
.lista-simple li { margin-bottom: 4px; }
