/* ============================================================================
   Gestión — hoja de estilos única.

   Móvil primero: la pantalla del vendedor es la que más se usa y la que peor
   contexto tiene (sol, una mano, apuro). Botones grandes, contraste alto y
   nada que dependa de pasar el mouse por encima.
   ========================================================================= */

:root {
  --paper: #eef0ec;
  --surface: #ffffff;
  --surface-2: #f6f8f4;
  --line: #d9ded6;
  --line-strong: #bcc4b8;
  --ink: #141b17;
  --ink-2: #4a554e;
  --ink-3: #6f7b73;
  --pine: #0f5f4b;
  --pine-hover: #0c4c3c;
  --pine-soft: #e2efe9;
  --slate: #2e5c7a;
  --slate-soft: #e4edf3;
  --brass: #8a5a11;
  --brass-soft: #f4ead9;
  --rust: #8c3a2e;
  --rust-soft: #f5e5e2;
  --sombra: 0 1px 2px rgba(20, 27, 23, 0.06), 0 8px 24px -18px rgba(20, 27, 23, 0.3);
  --r: 8px;
  --nav-h: 62px;

  /* Escala de espaciado, en múltiplos de 4. Tenerla en variables es lo que
     hace que la densidad se pueda ajustar en un solo lugar en vez de en
     doscientos `padding` sueltos. */
  --e1: 4px;  --e2: 8px;  --e3: 12px; --e4: 16px; --e5: 24px; --e6: 32px;

  /* El alto mínimo de cualquier cosa que se toque con el dedo. La densidad no
     puede comerse esto: un renglón de 36 px entra más veces en la pantalla
     pero se falla al tocarlo, y el vendedor lo usa parado en la vereda. */
  --toque: 48px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #0d1210;
    --surface: #151b18;
    --surface-2: #1b231f;
    --line: #28322d;
    --line-strong: #3c4841;
    --ink: #e8ece8;
    --ink-2: #a9b5ae;
    --ink-3: #7f8b84;
    --pine: #4fbd99;
    --pine-hover: #6bd0af;
    --pine-soft: #12302a;
    --slate: #82b4d6;
    --slate-soft: #142633;
    --brass: #d6a045;
    --brass-soft: #2b2113;
    --rust: #e08272;
    --rust-soft: #2f1b17;
    --sombra: 0 1px 2px rgba(0, 0, 0, 0.5), 0 10px 30px -22px rgba(0, 0, 0, 0.9);
  }
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  min-height: 100%;
}

body {
  background: var(--paper);
  color: var(--ink);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}

h1, h2, h3 { margin: 0; letter-spacing: -0.015em; line-height: 1.2; }
h1 { font-size: 1.5rem; font-weight: 700; }
h2 { font-size: 1.15rem; font-weight: 650; }
h3 { font-size: 0.95rem; font-weight: 650; }
p { margin: 0; }

a { color: var(--pine); }

.mono, .num {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}

/* --------------------------------------------------------------- layout -- */

#app { min-height: 100vh; }

.layout {
  display: flex;
  min-height: 100vh;
}

/* La barra lateral es una columna de tres piezas: marca arriba, lista en el
   medio y pie abajo. El `overflow: hidden` de acá y el `overflow-y: auto` del
   `.menu` son los que hacen que se desplace la lista sola y no la barra
   entera: así el pie —Configuración y cerrar sesión— queda siempre a la
   vista, y no hay que arrastrar nada para encontrarlo. */
.sidebar {
  display: none;
  width: 228px;
  flex-shrink: 0;
  background: var(--surface);
  border-right: 1px solid var(--line);
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
}

.marca {
  padding: 10px 12px 9px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  flex: none;
  border-bottom: 1px solid var(--line);
}
.marca-quien { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.marca strong { font-size: 1rem; letter-spacing: -0.02em; }
.marca span {
  font-size: 0.72rem; color: var(--ink-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
}

.sidebar-pie {
  flex: none;
  margin-top: auto;
  padding: 5px 8px 7px;
  border-top: 1px solid var(--line);
  display: flex; flex-direction: column; gap: 2px;
  background: var(--surface);
}

/* Cerrar sesión: apagar el sistema es de las pocas cosas del sistema que no
   se pueden deshacer, así que el botón se ve pero no llama. Recién al
   pasarle el mouse toma el color de alerta. */
.marca-salir {
  display: flex; align-items: center; gap: 9px;
  padding: 5px 10px;
  border: 1px solid transparent; border-radius: 6px;
  background: none; color: var(--ink-3);
  font: inherit; font-size: 0.8rem; font-weight: 550; line-height: 1.2;
  min-height: 0; cursor: pointer; white-space: nowrap; text-align: left;
  justify-content: flex-start; width: 100%;
}
.marca-salir svg { width: 16px; height: 16px; flex: none; }
.marca-salir:hover {
  border-color: var(--rust); color: var(--rust); background: var(--rust-soft);
}

.menu {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  padding: 3px 8px 4px;
  display: flex; flex-direction: column; gap: 0;
}
/* La barra tiene veinte entradas: sin un corte visible entre secciones son
   veinte renglones iguales y encontrar uno es leerlos todos. La línea hace
   el trabajo que el espacio en blanco solo no alcanzaba a hacer. */
.menu-grupo {
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  font-weight: 650;
  color: var(--ink-3);
  margin: 3px 2px 0;
  padding: 5px 8px 2px;
  border-top: 1px solid var(--line);
}
.menu-grupo:first-child { margin-top: 0; padding-top: 2px; border-top: 0; }

/* El renglón del menú. Vale igual para la lista del medio y para el pie:
   Configuración y cerrar sesión no son otra clase de cosa, y si se vieran
   distintas el ojo tendría que aprender dos vocabularios en la misma barra. */
.menu a, .sidebar-pie a {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 5px 10px;
  border-radius: 6px;
  color: var(--ink-2);
  text-decoration: none;
  font-size: 0.855rem;
  font-weight: 500;
  line-height: 1.3;
}
.menu a:hover, .sidebar-pie a:hover { background: var(--surface-2); color: var(--ink); }
/* La barra de la izquierda no es adorno: el fondo suave solo, en verde claro
   sobre blanco, es una diferencia de luminosidad chica y a plena luz se
   pierde. La barra se ve aunque el color no llegue. */
.menu a.activo, .sidebar-pie a.activo {
  background: var(--pine-soft);
  color: var(--pine);
  font-weight: 650;
  box-shadow: inset 3px 0 0 var(--pine);
  padding-left: 13px;
}
.menu-ico { display: flex; flex: none; color: var(--ink-3); }
.menu a:hover .menu-ico, .sidebar-pie a:hover .menu-ico { color: var(--ink-2); }
.menu a.activo .menu-ico, .sidebar-pie a.activo .menu-ico { color: var(--pine); }
.menu a svg, .sidebar-pie a svg { width: 16px; height: 16px; flex: none; }

/* --------------------------------------------------- el buscador de todo -- */

.buscar-todo {
  display: flex; align-items: center; gap: 8px; width: 100%;
  margin-top: 7px; padding: 4px 8px;
  border: 1px solid var(--line); border-radius: 7px;
  background: var(--surface-2); color: var(--ink-3);
  font: inherit; font-size: 0.8rem; min-height: 0; cursor: pointer;
  justify-content: flex-start; text-align: left;
}
.buscar-todo svg { width: 15px; height: 15px; flex: none; }
.buscar-todo:hover { border-color: var(--line-strong); color: var(--ink-2); }
.buscar-todo kbd {
  margin-left: auto; font: inherit; font-size: 0.66rem; font-weight: 600;
  color: var(--ink-3); border: 1px solid var(--line); border-radius: 4px;
  padding: 1px 5px; background: var(--surface); white-space: nowrap;
}

/* El panel se abre arriba y no centrado: el ojo ya está arriba cuando aprieta
   Ctrl+K, y así los resultados crecen hacia abajo sin mover lo que ya se leyó. */
.bg-fondo {
  position: fixed; inset: 0; z-index: 120;
  background: rgba(18, 26, 21, .38);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 8vh 16px 16px;
}
.bg-caja {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 12px; box-shadow: 0 24px 60px -20px rgba(20, 27, 23, .45);
  width: min(620px, 100%); display: flex; flex-direction: column;
  max-height: 74vh; overflow: hidden;
}
.bg-campo {
  display: flex; align-items: center; gap: 10px;
  padding: 13px 16px; border-bottom: 1px solid var(--line); flex: none;
}
.bg-campo svg { width: 18px; height: 18px; color: var(--ink-3); flex: none; }
.bg-campo input {
  flex: 1; border: 0; background: none; color: var(--ink);
  font: inherit; font-size: 1rem; outline: none; padding: 0; min-width: 0;
}
.bg-campo input::-webkit-search-cancel-button { display: none; }
.bg-lista { overflow-y: auto; padding: 6px; flex: 1; min-height: 0; }
.bg-grupo {
  font-size: 0.66rem; text-transform: uppercase; letter-spacing: .09em;
  font-weight: 650; color: var(--ink-3); padding: 9px 10px 4px;
}
.bg-item {
  display: flex; align-items: baseline; gap: 10px; width: 100%;
  padding: 7px 10px; border: 0; border-radius: 7px; background: none;
  font: inherit; text-align: left; justify-content: flex-start;
  min-height: 0; cursor: pointer; color: var(--ink);
}
/* El resaltado del renglón elegido va por fondo Y por la barra de la
   izquierda, igual que en el menú: un solo lenguaje para «esto es lo que
   estás por abrir». */
.bg-item.elegido {
  background: var(--pine-soft); color: var(--pine);
  box-shadow: inset 3px 0 0 var(--pine);
}
.bg-tit { font-weight: 600; flex: none; max-width: 58%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bg-det { color: var(--ink-3); font-size: 0.82rem; margin-left: auto;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bg-item.elegido .bg-det { color: var(--pine); opacity: .8; }
.bg-vacio { padding: 22px 12px; text-align: center; color: var(--ink-3);
  font-size: 0.88rem; }
.bg-pie {
  border-top: 1px solid var(--line); padding: 8px 14px; flex: none;
  font-size: 0.72rem; color: var(--ink-3);
}

/* --------------------------------------------------- la barra plegada ----- */

.plegar {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 5px 10px; border: 1px solid transparent; border-radius: 6px;
  background: none; color: var(--ink-3); font: inherit; font-size: 0.8rem;
  font-weight: 550; min-height: 0; cursor: pointer;
  justify-content: flex-start; text-align: left;
}
.plegar svg { width: 16px; height: 16px; flex: none; }
.plegar:hover { background: var(--surface-2); color: var(--ink-2); }

/* Plegada quedan sólo los dibujos. Ciento sesenta píxeles menos de barra son
   ciento sesenta más de tabla, que en un listado de doce columnas es una
   columna entera. El nombre de cada sección sigue estando en el `title`. */
.sidebar.plegada { width: 58px; }
.sidebar.plegada .menu-txt,
.sidebar.plegada .marca-quien,
.sidebar.plegada .buscar-todo kbd { display: none; }
.sidebar.plegada .marca { padding: 11px 8px 10px; align-items: center; }
.sidebar.plegada .buscar-todo,
.sidebar.plegada .menu a,
.sidebar.plegada .sidebar-pie a,
.sidebar.plegada .marca-salir,
.sidebar.plegada .plegar { justify-content: center; padding-left: 0; padding-right: 0; }
.sidebar.plegada .menu a.activo,
.sidebar.plegada .sidebar-pie a.activo { padding-left: 0; }
.sidebar.plegada .buscar-todo { margin-top: 0; }
.sidebar.plegada .menu-grupo {
  font-size: 0; padding: 7px 0 0; margin: 5px 6px 0; height: 1px;
}
.sidebar.plegada .plegar svg { transform: rotate(180deg); }

/* Cuando la lista no entra, el corte tiene que verse. Un renglón cortado al
   ras del borde inferior se lee como el último de la lista y las secciones de
   abajo dejan de existir. El degradado dice «sigue». */
.sidebar.hay-mas .menu {
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 22px), transparent);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 22px), transparent);
}

.contenido {
  flex: 1;
  min-width: 0;
  padding: 18px 16px calc(var(--nav-h) + 28px);
  max-width: 1180px;
  margin: 0 auto;
  width: 100%;
}

.encabezado {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 18px;
}
.encabezado .titulo { display: flex; flex-direction: column; gap: 2px; }
.encabezado .titulo p { color: var(--ink-3); font-size: 0.85rem; }
.acciones { display: flex; gap: 8px; flex-wrap: wrap; }

/* En el teléfono la pantalla es el recurso escaso: el título y su bajada se
   comen un sexto de lo que hay antes de mostrar el primer dato. */
@media (max-width: 859px) {
  h1 { font-size: 1.3rem; }
  .encabezado { margin-bottom: var(--e3); gap: var(--e2); }
  .contenido { padding-top: var(--e3); }
}

/* Barra inferior en teléfono */
.tabbar {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  height: var(--nav-h);
  background: var(--surface);
  border-top: 1px solid var(--line);
  display: flex;
  z-index: 40;
  padding-bottom: env(safe-area-inset-bottom);
}
.tabbar a {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  color: var(--ink-3);
  text-decoration: none;
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  min-width: 0;
  padding: 0 2px;
}
/* La pastilla detrás del ícono. Marcar la pestaña activa sólo con el color
   funciona en el escritorio y no en la calle: con el sol de frente y el
   brillo al mínimo, verde y gris se ven iguales. La forma se ve igual. */
.tabbar a .tab-ico {
  display: flex; align-items: center; justify-content: center;
  width: 46px; height: 24px; border-radius: 12px;
}
.tabbar a svg { width: 21px; height: 21px; }
.tabbar a span:last-child {
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tabbar a.activo { color: var(--pine); font-weight: 700; }
.tabbar a.activo .tab-ico { background: var(--pine-soft); }
.tabbar a:active .tab-ico { background: var(--surface-2); }

@media (min-width: 860px) {
  .sidebar { display: flex; }
  .tabbar { display: none; }
  .contenido { padding: 26px 30px 60px; }
  :root { --nav-h: 0px; }
}

/* --------------------------------------------------------------- piezas -- */

.tarjeta {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 16px;
}
.tarjeta + .tarjeta { margin-top: 14px; }
.tarjeta > h2, .tarjeta > h3 { margin-bottom: 12px; }

.grilla { display: grid; gap: 12px; }
.grilla.c2 { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.grilla.c3 { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.grilla.c4 { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }

.dato {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 13px 15px;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.dato .rotulo {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--ink-3);
  font-weight: 600;
}
.dato .valor { font-size: 1.4rem; font-weight: 700; letter-spacing: -0.02em; }
.dato .pie { font-size: 0.78rem; color: var(--ink-3); }
.dato .linea-valor {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--e2); flex-wrap: wrap;
}

/* La comparación contra el mes pasado.
   Lleva flecha ADEMÁS de color: hay quien no distingue el verde del rojo, y
   una diferencia que sólo se ve por el color no se ve. El color lo elige la
   tarjeta y no el signo: en gastos, subir es la mala noticia. */
.delta {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 0.72rem; font-weight: 700; white-space: nowrap;
  padding: 2px 7px; border-radius: 999px;
  font-variant-numeric: tabular-nums;
}
.delta.sube { background: var(--pine-soft); color: var(--pine); }
.delta.baja { background: var(--rust-soft); color: var(--rust); }
.delta.neutro {
  background: var(--surface-2); color: var(--ink-3); font-weight: 600;
}

/* La minicurva. Sin ejes ni números a propósito: no está para leer valores
   —para eso está el informe— sino para ver si el número de arriba viene de
   una subida, de una bajada o de una meseta. */
.minicurva { width: 100%; height: 24px; display: block; margin: 6px 0 2px; }
.mc-linea { fill: none; stroke: var(--pine); stroke-width: 1.5;
  vector-effect: non-scaling-stroke; stroke-linejoin: round; }
.mc-area { fill: var(--pine); opacity: 0.12; }
.mc-punto { fill: var(--pine); }
.dato.acento { border-left: 3px solid var(--pine); }
.dato.alerta { border-left: 3px solid var(--brass); }
.dato.malo { border-left: 3px solid var(--rust); }

/* ------------------------------------------------------------- botones --- */

button, .boton {
  font: inherit;
  font-weight: 600;
  font-size: 0.88rem;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--ink);
  padding: 9px 15px;
  border-radius: 6px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  text-decoration: none;
  min-height: 40px;
  transition: background 0.12s ease, border-color 0.12s ease;
}
button:hover, .boton:hover { background: var(--surface-2); }
button:active { transform: translateY(1px); }
button:disabled { opacity: 0.5; cursor: not-allowed; }

button.primario, .boton.primario {
  background: var(--pine);
  border-color: var(--pine);
  color: #fff;
}
button.primario:hover { background: var(--pine-hover); border-color: var(--pine-hover); }
@media (prefers-color-scheme: dark) {
  button.primario, .boton.primario { color: #06120e; }
}

button.peligro { color: var(--rust); border-color: var(--rust); background: transparent; }
button.peligro:hover { background: var(--rust-soft); }
button.chico { min-height: 32px; padding: 5px 11px; font-size: 0.8rem; }
button.grande { min-height: 52px; font-size: 1rem; width: 100%; }
button.plano { border-color: transparent; background: transparent; color: var(--ink-2); }
button.plano:hover { background: var(--surface-2); }

*:focus-visible { outline: 2px solid var(--pine); outline-offset: 2px; }

/* ------------------------------------------------------------ formulario - */

.campo { display: flex; flex-direction: column; gap: 5px; margin-bottom: 12px; }
.campo label { font-size: 0.78rem; font-weight: 600; color: var(--ink-2); }
.campo .ayuda { font-size: 0.75rem; color: var(--ink-3); }

input, select, textarea {
  font: inherit;
  font-size: 16px; /* evita el zoom automático de iOS/Android al enfocar */
  padding: 10px 12px;
  border: 1px solid var(--line-strong);
  border-radius: 6px;
  background: var(--surface);
  color: var(--ink);
  width: 100%;
  min-height: 42px;
}
input:focus, select:focus, textarea:focus { border-color: var(--pine); outline: none; }
input[type="number"] { text-align: right; font-variant-numeric: tabular-nums; }
textarea { min-height: 72px; resize: vertical; }

/* Las casillas y los redondeles no son campos de texto: el width:100% de
   arriba los estiraba a lo ancho de la fila y dejaba la etiqueta lejísimos. */
input[type="checkbox"], input[type="radio"] {
  width: 18px; height: 18px; min-height: 0; padding: 0;
  flex: 0 0 auto; accent-color: var(--pine); cursor: pointer;
}
/* Etiqueta con casilla al lado, del tamaño que hace falta y no más. */
.casilla {
  display: inline-flex; align-items: center; gap: 9px; cursor: pointer;
  font-size: 0.92rem; color: var(--ink-2);
}
.casilla:hover { color: var(--ink); }

.fila { display: grid; gap: 12px; grid-template-columns: 1fr 1fr; }
.fila.c3 { grid-template-columns: 1fr 1fr 1fr; }
@media (max-width: 620px) { .fila, .fila.c3 { grid-template-columns: 1fr; } }

/* El buscador queda pegado arriba mientras se scrollea. Con doscientos
   clientes, la alternativa es volver hasta el principio cada vez que uno se
   equivoca de letra. El fondo es opaco a propósito: si no, los renglones se
   ven pasar por debajo del texto. */
.buscador {
  position: sticky; top: 0; z-index: 5;
  margin: 0 calc(-1 * var(--e4)) var(--e3);
  padding: var(--e2) var(--e4);
  background: var(--paper);
}
.buscador input { padding-left: 38px; }
.buscador svg { left: calc(var(--e4) + var(--e3)); }
@media (min-width: 860px) {
  .buscador { margin: 0 0 var(--e3); padding: 0; background: none; position: relative; }
  .buscador svg { left: var(--e3); }
}
.buscador svg {
  position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
  width: 17px; height: 17px; color: var(--ink-3); pointer-events: none;
}

/* ----------------------------------------------------------------- tabla - */

.tabla-scroll {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
  -webkit-overflow-scrolling: touch;
}
/*
   Las tablas son donde se pasa el día quien usa esto, así que van densas y
   parejas. Tres reglas que no son adorno:

     · TODOS los números en cifras tabulares y a la derecha. Las columnas de
       plata sólo se comparan de un vistazo si las unidades caen una debajo de
       la otra; con cifras de ancho variable el ojo tiene que leer cada una.
     · El renglón no crece: el texto largo se corta con puntos suspensivos y
       queda entero en el `title`. Antes «ALMACEN DEL CHEQUE 8AA0E7» partía la
       fila en tres y una tabla de veinte clientes ocupaba sesenta renglones.
     · El encabezado queda fijo al scrollear. Sin eso, a la décima fila ya no
       se sabe qué columna es cuál.
*/
table {
  border-collapse: collapse; width: 100%; font-size: 0.84rem;
  font-variant-numeric: tabular-nums;
}
thead th {
  position: sticky; top: 0; z-index: 2;
  text-align: left;
  padding: 8px 12px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--line-strong);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-2);
  white-space: nowrap;
  font-weight: 700;
}
tbody td { padding: 7px 12px; border-bottom: 1px solid var(--line); vertical-align: middle; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr.clickable { cursor: pointer; }
tbody tr.clickable:hover td { background: var(--surface-2); }
td.der, th.der { text-align: right; font-variant-numeric: tabular-nums; }
/* El texto que no entra se corta acá y no estira la fila. El nombre completo
   queda en el `title`, que es donde lo busca quien necesita verlo entero. */
td.recorta {
  max-width: 30ch; min-width: 9ch;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
td.centro, th.centro { text-align: center; }
td.nowrap, th.nowrap { white-space: nowrap; }
/* Para las tablas que se editan adentro de un modal: los campos ya traen su
   propio aire, la celda no tiene que agregar más. */
table.compacta tbody td { padding: 4px 6px; }
table.compacta thead th { padding: 6px; }
table.compacta input, table.compacta select { margin: 0; }
tfoot td {
  padding: 10px 12px;
  border-top: 1px solid var(--line-strong);
  font-weight: 700;
  background: var(--surface-2);
}

/* --------------------------------------------------------------- chips --- */

.chip {
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  padding: 2px 8px;
  border-radius: 20px;
  border: 1px solid transparent;
  white-space: nowrap;
}
.chip.ok { background: var(--pine-soft); color: var(--pine); border-color: var(--pine); }
.chip.info { background: var(--slate-soft); color: var(--slate); border-color: var(--slate); }
.chip.aviso { background: var(--brass-soft); color: var(--brass); border-color: var(--brass); }
.chip.malo { background: var(--rust-soft); color: var(--rust); border-color: var(--rust); }
.chip.neutro { background: var(--surface-2); color: var(--ink-3); border-color: var(--line-strong); }

/* ---------------------------------------------------------------- lista -- */
/*
   Una tarjeta suelta por renglón, con su borde y su separación, entraba tres
   clientes en la pantalla de un teléfono. Buscar entre doscientos así es
   scrollear sesenta veces. Ahora la lista es UN bloque con líneas finas
   adentro —lo que hace cualquier agenda o cliente de correo— y entran ocho o
   nueve sin que el renglón deje de ser cómodo de tocar: el alto mínimo sigue
   siendo el del dedo (--toque), lo que se achicó es el aire entre medio.
*/
.lista {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
}
.item {
  background: none;
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  padding: 9px var(--e3);
  min-height: var(--toque);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e3);
  cursor: pointer;
}
.item:last-child { border-bottom: 0; }
.item:hover { background: var(--surface-2); }
.item:active { background: var(--pine-soft); }
.item .izq { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
/* El nombre en una sola línea con puntos suspensivos: partido en tres
   renglones, cada cliente ocupaba lo que ocupan tres. */
.item .izq strong {
  font-size: 0.9rem; font-weight: 650;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.item .izq span {
  font-size: 0.75rem; color: var(--ink-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.item .der { text-align: right; flex-shrink: 0; display: flex; flex-direction: column; gap: 2px; align-items: flex-end; }
.item .der .monto { font-weight: 700; font-variant-numeric: tabular-nums; }

/* Las listas que no son de renglones tocables —tarjetas con formulario
   adentro, por ejemplo— siguen necesitando separarse. */
.lista.sueltos {
  background: none; border: 0; border-radius: 0;
  gap: var(--e2); overflow: visible;
}
.lista.sueltos > * {
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--surface);
}

/* --------------------------------------------------------- catálogo móvil */

.cat-item {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.cat-item.en-carrito { border-color: var(--pine); background: var(--pine-soft); }
.cat-cab { display: flex; justify-content: space-between; gap: 12px; align-items: flex-start; }
.cat-nombre { font-weight: 650; font-size: 0.95rem; line-height: 1.3; }
/* El cartel de novedad, igual que en la hoja impresa. Va pegado al nombre y
   no en un renglón propio: en una lista de ciento veinte artículos, un
   renglón más por producto nuevo empuja el resto fuera de la pantalla. */
.chip-nuevo {
  display: inline-block; margin-left: 6px; vertical-align: 2px;
  padding: 1px 6px; border-radius: 3px;
  background: var(--pine); color: #fff;
  font-size: 0.6rem; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; white-space: nowrap;
}
@media (prefers-color-scheme: dark) { .chip-nuevo { color: #06120e; } }
.cat-meta { font-size: 0.76rem; color: var(--ink-3); margin-top: 2px; }
.cat-precio { font-weight: 700; font-size: 1rem; white-space: nowrap; font-variant-numeric: tabular-nums; }
.cat-pie { display: flex; align-items: center; justify-content: space-between; gap: 10px; }

.stepper { display: flex; align-items: center; gap: 0; }
.stepper button {
  width: 42px; height: 42px; min-height: 42px; padding: 0;
  font-size: 1.25rem; font-weight: 700; border-radius: 6px;
}
.stepper input {
  width: 68px; height: 42px; min-height: 42px; text-align: center;
  border-radius: 0; border-left: 0; border-right: 0; padding: 0;
}
.stepper button:first-child { border-radius: 6px 0 0 6px; }
.stepper button:last-child { border-radius: 0 6px 6px 0; }

.barra-carrito {
  position: fixed;
  left: 0; right: 0;
  bottom: var(--nav-h);
  background: var(--pine);
  color: #fff;
  padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  z-index: 35;
  box-shadow: 0 -6px 20px -12px rgba(0, 0, 0, 0.5);
}
.barra-carrito .resumen { display: flex; flex-direction: column; gap: 1px; }
.barra-carrito .resumen small { font-size: 0.72rem; opacity: 0.85; }
.barra-carrito .resumen strong { font-size: 1.1rem; font-variant-numeric: tabular-nums; }
.barra-carrito button { background: #fff; color: var(--pine); border-color: #fff; }
@media (min-width: 860px) { .barra-carrito { left: 232px; bottom: 0; } }

/* ---------------------------------------------------------------- modal -- */

.fondo-modal {
  position: fixed; inset: 0;
  background: rgba(10, 15, 12, 0.55);
  display: flex; align-items: flex-end; justify-content: center;
  z-index: 60;
  padding: 0;
}
@media (min-width: 620px) { .fondo-modal { align-items: center; padding: 24px; } }

.modal {
  background: var(--surface);
  width: 100%;
  max-width: 620px;
  max-height: 92vh;
  overflow-y: auto;
  border-radius: 14px 14px 0 0;
  border: 1px solid var(--line);
  box-shadow: var(--sombra);
}
@media (min-width: 620px) { .modal { border-radius: 12px; } }
.modal-cab {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 18px; border-bottom: 1px solid var(--line);
  position: sticky; top: 0; background: var(--surface); z-index: 2;
}
.modal-cuerpo { padding: 18px; }

/* --------------------------------------------------------------- solapas ---
   Para las fichas largas: los datos generales, los fiscales, las condiciones
   y los contactos son cosas distintas y no se cargan en el mismo momento. */
.solapas-tira {
  display: flex; gap: 2px; overflow-x: auto; margin-bottom: 16px;
  border-bottom: 1px solid var(--line); -webkit-overflow-scrolling: touch;
}
.solapas-tira button {
  width: auto; flex: 0 0 auto; background: none; border: 0; border-radius: 0;
  border-bottom: 2px solid transparent; padding: 8px 14px; margin-bottom: -1px;
  font-size: 0.86rem; font-weight: 600; color: var(--ink-3); white-space: nowrap;
}
.solapas-tira button:hover { color: var(--ink); background: var(--surface-2); }
.solapas-tira button.activa { color: var(--ink); border-bottom-color: var(--pine); }
.solapas-tira button .cuantos {
  font-size: 0.72rem; color: var(--ink-3); font-weight: 500; margin-left: 5px;
}
.modal-pie {
  padding: 14px 18px; border-top: 1px solid var(--line);
  display: flex; gap: 10px; justify-content: flex-end;
  position: sticky; bottom: 0; background: var(--surface);
}
.modal-pie button { flex: 1; }
@media (min-width: 620px) { .modal-pie button { flex: 0 0 auto; } }

/* ---------------------------------------------------------------- login -- */

.login-wrap {
  min-height: 100vh;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
}
.login {
  width: 100%; max-width: 380px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 30px 26px;
  box-shadow: var(--sombra);
}
.login h1 { margin-bottom: 4px; }
.login .sub { color: var(--ink-3); font-size: 0.85rem; margin-bottom: 22px; }

/* --------------------------------------------------------------- avisos -- */

.aviso {
  padding: 11px 14px;
  border-radius: 6px;
  font-size: 0.86rem;
  border: 1px solid;
  margin-bottom: 12px;
}
.aviso.error { background: var(--rust-soft); color: var(--rust); border-color: var(--rust); }
.aviso.ok { background: var(--pine-soft); color: var(--pine); border-color: var(--pine); }
.aviso.atencion { background: var(--brass-soft); color: var(--brass); border-color: var(--brass); }
.aviso.dato { background: var(--slate-soft); color: var(--slate); border-color: var(--slate); }

#tostadas {
  position: fixed; top: 12px; left: 50%; transform: translateX(-50%);
  z-index: 100; display: flex; flex-direction: column; gap: 8px;
  width: calc(100% - 24px); max-width: 440px; pointer-events: none;
  transition: top 0.15s ease;
}
/* Con la barra de sincronización arriba, los avisos bajan para no taparla. */
body.con-barra-estado #tostadas { top: 76px; }
@media (min-width: 860px) { body.con-barra-estado #tostadas { top: 64px; } }
@media (prefers-reduced-motion: reduce) { #tostadas { transition: none; } }
.tostada {
  background: var(--ink); color: var(--paper);
  padding: 11px 15px; border-radius: 8px; font-size: 0.87rem; font-weight: 500;
  box-shadow: var(--sombra); animation: entrar 0.16s ease-out;
}
.tostada.error { background: var(--rust); color: #fff; }
.tostada.ok { background: var(--pine); color: #fff; }
@keyframes entrar { from { opacity: 0; transform: translateY(-8px); } }
@media (prefers-reduced-motion: reduce) { .tostada { animation: none; } }

.vacio {
  text-align: center; padding: 44px 20px; color: var(--ink-3);
  display: flex; flex-direction: column; gap: 8px; align-items: center;
}
.vacio strong { color: var(--ink-2); font-size: 0.95rem; }
.vacio p { font-size: 0.85rem; max-width: 34ch; }

.cargando { padding: 40px; text-align: center; color: var(--ink-3); font-size: 0.88rem; }

/* Barra de estado de la sincronización. Va arriba de todo y sólo aparece
   cuando hay algo que decir: sin conexión, o pedidos esperando irse. */
.barra-estado {
  background: var(--rust);
  color: #fff;
  padding: 9px 14px;
  font-size: 0.83rem;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  position: sticky;
  top: 0;
  z-index: 30;
  /* Se estira hasta los bordes, anulando el padding del contenido. */
  margin: -18px -16px 16px;
}
@media (min-width: 860px) {
  .barra-estado { margin: -26px -30px 20px; }
}
.barra-estado.pendiente { background: var(--brass); }
.barra-estado button {
  background: rgba(255, 255, 255, 0.16);
  border-color: rgba(255, 255, 255, 0.5);
  color: #fff;
  flex-shrink: 0;
}
.barra-estado button:hover { background: rgba(255, 255, 255, 0.28); }

hr.sep { border: 0; border-top: 1px solid var(--line); margin: 16px 0; }

.pos { color: var(--pine); }
.neg { color: var(--rust); }
/* Un comprobante vencido se tiene que ver vencido sin leer la fecha. */
tbody tr.vencida td { background: var(--rust-soft); }
.tenue { color: var(--ink-3); }
.chiquito { font-size: 0.8rem; }
.der-texto { text-align: right; }
.flex { display: flex; gap: 10px; align-items: center; }
.flex.entre { justify-content: space-between; }
.flex.wrap { flex-wrap: wrap; }
.crece { flex: 1; min-width: 0; }
.mt { margin-top: 14px; }
.mb { margin-bottom: 14px; }

@media print {
  .sidebar, .tabbar, .acciones, .barra-carrito, #tostadas,
  .cartel-app { display: none !important; }
  body { background: #fff; }
  .contenido { padding: 0; max-width: none; }
  .tarjeta, .tabla-scroll { border: 0; }
}

/* Bloques que se abren: el detalle de lo que se salteó al importar, por
   ejemplo. Por defecto el navegador los muestra sin ningún indicio de que se
   pueden tocar. */
details { margin-top: 10px; }
details summary {
  cursor: pointer;
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--slate);
  padding: 6px 2px;
  user-select: none;
}
details summary:hover { color: var(--pine); }
details[open] summary { margin-bottom: 4px; }

/* Los recuadros de las fotos de la lista de precios aceptan que se les
   arrastre un archivo encima. Sin un cambio visible al pasar por arriba,
   nadie descubre que se puede: el borde punteado es todo el aviso. */
.foto-rubro { transition: box-shadow .12s, border-color .12s; }
.foto-rubro.encima {
  border-color: var(--pine);
  box-shadow: inset 0 0 0 2px var(--pine-soft);
}
.foto-rubro.encima img { opacity: 0.45; }

/* Cuatro columnas en una fila de formulario. Existía `.c3` y varias pantallas
   pedían `.c4`: sin la regla caían en dos columnas y el filtro quedaba con
   celdas vacías al lado. */
.fila.c4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) { .fila.c4 { grid-template-columns: 1fr 1fr; } }
@media (max-width: 620px) { .fila.c4 { grid-template-columns: 1fr; } }

/* `hidden` tiene que ganarle a cualquier `display` del autor.
   La regla del navegador es `[hidden]{display:none}`, y pierde contra
   cualquier clase nuestra: un `.fila` escondido con `el.hidden = true` se
   seguía viendo, porque `.fila{display:grid}` va después. Aparecía como un
   formulario que pide una caja para un gasto que no sale de ninguna. */
[hidden] { display: none !important; }

/* -------------------------------------------------------------- reportes -
   Una sola pantalla para los veintinueve listados: el índice a la izquierda
   y el reporte a la derecha. En celular el índice pasa arriba, porque una
   columna de 210px al lado de una tabla no entra en ningún teléfono. */
.rep-layout { display: grid; grid-template-columns: 210px 1fr; gap: 18px; align-items: start; }
.rep-menu {
  display: flex; flex-direction: column; gap: 2px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r); padding: 8px; position: sticky; top: 12px;
}
.rep-menu .menu-grupo { margin: 8px 2px 0; }
.rep-menu .menu-grupo:first-child { margin-top: 0; }
.rep-item {
  /* `justify-content` porque los botones del sistema son flex y centran su
     contenido: `text-align` solo no los mueve, y un índice centrado se lee
     como un cartel y no como una lista. */
  display: flex; justify-content: flex-start; text-align: left;
  background: transparent; border: 0; cursor: pointer;
  font: inherit; font-size: 0.855rem; font-weight: 500; color: var(--ink-2);
  padding: 6px 9px; border-radius: 6px; width: 100%;
}
.rep-item:hover { background: var(--surface-2); color: var(--ink); }
/* Mismo resaltado que la barra lateral: un solo lenguaje para «acá estás». */
.rep-item.activo {
  background: var(--pine-soft); color: var(--pine); font-weight: 650;
  box-shadow: inset 3px 0 0 var(--pine); padding-left: 12px;
}
/* El índice tiene cincuenta y tres informes. Con el alto de un botón —cuarenta
   píxeles, que es lo que hace falta para tocarlo con el dedo— la lista mide
   dos mil y encontrar uno es desplazar. En el escritorio se apunta con el
   mouse, así que acá el renglón vale menos alto; en el teléfono la regla de
   abajo lo devuelve al tamaño del dedo. */
@media (min-width: 901px) {
  .rep-item { min-height: 0; padding: 5px 9px; }
  .rep-item.activo { padding-left: 12px; }
}
.rep-panel { min-width: 0; }
/* La columna por la que está ordenada la tabla, para que el criterio no haya
   que deducirlo mirando los números. */
th.ordenada { color: var(--pine); }
@media (max-width: 900px) {
  .rep-layout { grid-template-columns: 1fr; }
  .rep-menu { position: static; flex-direction: row; flex-wrap: wrap; }
  .rep-menu .menu-grupo { width: 100%; }
  .rep-item { width: auto; }
}

/* ------------------------------------------------------------- apagado ---
   La pantalla que queda después de cerrar el sistema. Tapa todo y no se
   puede cerrar a propósito: el servidor se está apagando mientras se lee,
   así que cualquier cosa que se toque abajo daría un error de red. */
.apagado {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(18, 26, 21, .82);
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
.apagado-caja {
  background: var(--surface); border-radius: var(--r); padding: 28px 30px;
  max-width: 470px; box-shadow: 0 20px 60px rgba(0, 0, 0, .35);
}
.apagado-caja h2 { margin: 0 0 10px; font-size: 1.25rem; }
.apagado-caja p { margin: 0 0 10px; line-height: 1.5; }
.apagado-caja p:last-child { margin-bottom: 0; }

/* ------------------------------------------------------------ reportes ---
   La tabla de un reporte se lee distinto que una lista de pantalla: se
   recorre con el dedo buscando un número, y muchas veces se imprime. Así que
   los números van con cifras de ancho fijo —una columna de importes que no
   alinea no se puede comparar de un vistazo— y el total se despega del
   cuerpo en vez de ser un renglón más. */
table.reporte { font-variant-numeric: tabular-nums; }
table.reporte thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--surface-2);
  border-bottom: 2px solid var(--line-strong);
  font-size: 0.72rem; letter-spacing: 0.06em;
}
table.reporte tbody td { padding: 7px 10px; }
table.reporte tbody tr:hover td { background: var(--surface-2); }

/* Los bloques: un extracto de cuenta se lee por cliente, no como una tira
   de doscientos renglones seguidos. */
table.reporte tr.bloque td {
  background: var(--pine-soft); color: var(--pine);
  border-top: 1px solid var(--pine); border-bottom: 1px solid var(--pine);
  padding: 9px 10px; font-size: 0.85rem;
}
table.reporte tr.bloque strong { text-transform: uppercase; letter-spacing: 0.04em; }
table.reporte tr.subtotal td {
  background: var(--surface-2); font-weight: 700;
  border-top: 1px solid var(--line-strong);
  border-bottom: 2px solid var(--line-strong);
}
/* «Saldo anterior» no es un documento: es de dónde viene el saldo. */
table.reporte tr.anterior td { color: var(--ink-3); font-style: italic; }

table.reporte tfoot td {
  background: var(--pine); color: #fff; font-weight: 800;
  font-size: 0.92rem; padding: 10px; border: none;
}
table.reporte tfoot td:first-child { letter-spacing: 0.08em; }


/* --------------------------------------------------------------- gráficos */
/*
   Una sola serie y un solo color: el largo de la barra o la altura de la
   línea es lo que dice el dato, así que pintar cada una distinta agregaría
   ocho colores que no significan nada. La grilla y los ejes van en gris
   claro —son referencia, no dato— y los números del gráfico van abreviados:
   la cifra exacta está en la tabla de abajo.
*/
.grafico-caja { padding: var(--e4) var(--e4) var(--e3); }
.grafico-caja > h3 { margin-bottom: var(--e3); }
/* `overflow:hidden` y no visible: una etiqueta larga se sale del recuadro y
   se dibuja encima de la barra lateral. Se recorta acá y el nombre completo
   queda en el título emergente de la barra. */
.grafico { width: 100%; height: auto; display: block; overflow: hidden; }

.g-barra { fill: var(--pine); }
.g-barra.resto { fill: var(--ink-3); opacity: 0.45; }
.g-area { fill: var(--pine); opacity: 0.10; }
.g-linea { fill: none; stroke: var(--pine); stroke-width: 2;
  stroke-linejoin: round; stroke-linecap: round; }
.g-punto { fill: var(--pine); stroke: var(--surface); stroke-width: 2; }
.g-grilla { stroke: var(--line); stroke-width: 1; }

/* Los textos del gráfico llevan color de texto, nunca el de la serie: el
   color identifica la barra, no la palabra que está al lado. */
.g-etiqueta { fill: var(--ink-2); font-size: 11.5px; }
.g-cifra { fill: var(--ink); font-size: 12px; font-weight: 650;
  font-variant-numeric: tabular-nums; }
.g-eje { fill: var(--ink-3); font-size: 11px;
  font-variant-numeric: tabular-nums; }

/* En el teléfono el gráfico se sale de la pantalla si mantiene el ancho de
   la etiqueta: se deja scrollear en horizontal, que es lo que hace cualquier
   tabla ancha, en vez de apretarlo hasta que no se lea. */
@media (max-width: 620px) {
  .grafico-caja { overflow-x: auto; }
  /* El ancho mínimo es por la columna de nombres de las barras: sin él,
     «Distribuidora del Litoral SA» queda en tres píxeles. Los gráficos de
     los paneles del inicio no lo llevan —son líneas, sin columna de
     nombres— y prefieren achicarse a hacer scrollear el tablero. */
  .grafico-caja .grafico { min-width: 520px; }
  .panel-cuerpo { overflow-x: auto; }
}

/* ============================================================ paneles ==== */
/*
   El panel es la unidad del tablero: título, algo que mirar, y un pie que
   dice de qué período habla. Se ve como las tarjetas del resto del sistema
   —el mismo borde, el mismo radio, la misma sombra— porque es una tarjeta
   más: si los paneles del inicio tuvieran su propio estilo, el tablero
   parecería otro programa.
*/
.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
  display: flex; flex-direction: column;
}
.panel-cab {
  display: flex; align-items: center; gap: var(--e3);
  padding: 12px var(--e4) 10px;
  border-bottom: 1px solid var(--line);
}
.panel-cab h3 { margin: 0; flex: 1; min-width: 0; }
/* El enlace al informe no compite con el título: es gris hasta que se lo
   toca. Está para el que ya vio el panel y quiere el detalle, no para
   llamar la atención antes de que se lea el panel. */
.panel-ir {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 0.78rem; font-weight: 600; color: var(--ink-3);
  text-decoration: none; white-space: nowrap; flex: none;
}
.panel-ir svg { width: 14px; height: 14px; }
.panel-ir:hover { color: var(--pine); }
.panel-cuerpo { padding: var(--e4); flex: 1; min-width: 0; }
.panel-pie {
  padding: 8px var(--e4) 10px; border-top: 1px solid var(--line);
  background: var(--surface-2);
  font-size: 0.75rem; color: var(--ink-3);
}
.panel-vacio {
  padding: var(--e5) var(--e3); text-align: center;
  color: var(--ink-3); font-size: 0.88rem;
}

/* Dos paneles al lado en escritorio, uno debajo del otro en el teléfono. */
.paneles { display: grid; gap: var(--e3); grid-template-columns: 1fr; }
@media (min-width: 860px) {
  .paneles { grid-template-columns: 1fr 1fr; }
}

/* ------------------------------------------------------------ ranking --- */
/*
   Nombre, barra y cifra en tres columnas fijas. Las barras arrancan todas en
   la misma vertical porque si no, comparar largos deja de funcionar: el ojo
   compara desde dónde empiezan, no cuánto miden.
*/
.rank { display: flex; flex-direction: column; gap: 7px; }
.rank-fila { display: grid; grid-template-columns: 38% 1fr auto; gap: var(--e2);
  align-items: center; }
.rank-nom {
  font-size: 0.83rem; color: var(--ink-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rank-barra { background: var(--surface-2); border-radius: 4px; height: 16px;
  overflow: hidden; }
.rank-relleno { display: block; height: 100%; background: var(--pine);
  border-radius: 4px; }
.rank-cifra {
  font-size: 0.8rem; font-weight: 650; color: var(--ink);
  font-variant-numeric: tabular-nums; white-space: nowrap; min-width: 5ch;
  text-align: right;
}

/* -------------------------------------------------- deuda por antigüedad - */
/*
   Una sola barra partida en tramos: son partes de un todo Y están ordenados,
   así que se ve a la vez cuánto es cada tramo y qué proporción de la deuda
   representa. Una torta mostraría lo segundo y perdería el orden, que acá es
   lo que importa: «más de 90 días» no es una categoría más, es el final de
   una escala.

   La escala de color va de claro a oscuro con la antigüedad: un solo tono en
   cinco pasos, no cinco colores sueltos. Y «a vencer» va en gris porque no es
   un tramo más de la escala —todavía no venció—, es otra cosa. Cada tramo
   lleva su rótulo y su importe abajo, así que el color nunca carga solo con
   el significado.
*/
.antig-barra {
  display: flex; height: 30px; border-radius: 6px; overflow: hidden;
  background: var(--surface-2);
}
.antig-tramo { display: block; height: 100%; }
.antig-tramo.a_vencer { background: #9aa69e; }
.antig-tramo.t30 { background: #e3b063; }
.antig-tramo.t60 { background: #d08a47; }
.antig-tramo.t90 { background: #b85f35; }
.antig-tramo.t90mas { background: #8c3a2e; }
.antig-ref {
  display: flex; flex-wrap: wrap; gap: var(--e2) var(--e4);
  margin-top: var(--e3);
}
.antig-item { display: inline-flex; align-items: center; gap: 6px;
  font-size: 0.8rem; color: var(--ink-2); }
.antig-punto { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.antig-punto.a_vencer { background: #9aa69e; }
.antig-punto.t30 { background: #e3b063; }
.antig-punto.t60 { background: #d08a47; }
.antig-punto.t90 { background: #b85f35; }
.antig-punto.t90mas { background: #8c3a2e; }
.antig-monto { font-weight: 650; color: var(--ink);
  font-variant-numeric: tabular-nums; }

/* La línea de comparación del gráfico: punteada y gris. No es un dato de
   igual jerarquía que el año en curso, es el fondo contra el que se lo lee. */
.g-linea.contra {
  stroke: var(--ink-3); stroke-width: 1.4; stroke-dasharray: 5 4; fill: none;
}
.g-punto.contra { fill: var(--ink-3); stroke: none; opacity: .55; }

/* El gráfico dibujado con recuadro chico —el del teléfono— necesita la letra
   más grande en unidades del recuadro: se va a achicar junto con todo lo
   demás cuando el SVG se estire al ancho de la tarjeta. Ver `graficoLinea`. */
.grafico.chico .g-eje { font-size: 14px; }
.grafico.chico .g-cifra { font-size: 15px; }
.grafico.chico .g-etiqueta { font-size: 14px; }

/* ==================================================== la hoja de abajo ==== */
/*
   Sube desde el borde inferior y no aparece en el centro por una razón
   física: la mano sostiene el teléfono por abajo y el pulgar llega cómodo
   hasta poco más de la mitad de la pantalla. Un diálogo centrado deja los
   botones donde el pulgar no llega y obliga a usar las dos manos.
*/
.hoja-fondo {
  position: fixed; inset: 0; z-index: 150;
  background: rgba(18, 26, 21, 0);
  display: flex; align-items: flex-end; justify-content: center;
  transition: background 0.2s ease;
}
.hoja-fondo.puesta { background: rgba(18, 26, 21, .42); }
.hoja-fondo.yendose { background: rgba(18, 26, 21, 0); }

.hoja-abajo {
  background: var(--surface);
  width: min(560px, 100%);
  max-height: 88vh;
  border-radius: 16px 16px 0 0;
  border: 1px solid var(--line); border-bottom: 0;
  box-shadow: 0 -8px 40px -12px rgba(20, 27, 23, .35);
  display: flex; flex-direction: column;
  /* Empieza abajo de todo y sube: es lo que hace que se entienda de dónde
     salió y hacia dónde se la puede empujar para cerrarla. */
  transform: translateY(100%);
  transition: transform 0.24s cubic-bezier(.2, .8, .3, 1);
  padding-bottom: env(safe-area-inset-bottom);
}
.hoja-fondo.puesta .hoja-abajo { transform: translateY(0); }
.hoja-fondo.yendose .hoja-abajo { transform: translateY(100%); }
.hoja-abajo.alta { height: 78vh; }

/* La pestaña. Es lo que dice «esto se agarra y se tira»: sin ella, que la
   hoja se pueda arrastrar es un secreto. La zona sensible es mucho más alta
   que la rayita, porque el dedo no apunta con esa precisión. */
.hoja-pestana {
  padding: 10px 0 6px; display: flex; justify-content: center;
  cursor: grab; touch-action: none; flex: none;
}
.hoja-pestana span {
  display: block; width: 42px; height: 4px; border-radius: 2px;
  background: var(--line-strong);
}
.hoja-cab {
  display: flex; align-items: center; gap: var(--e3);
  padding: 2px var(--e4) 10px; border-bottom: 1px solid var(--line); flex: none;
}
.hoja-cab h2 { flex: 1; min-width: 0; font-size: 1.05rem; }
.hoja-cuerpo { overflow-y: auto; flex: 1; min-height: 0;
  overscroll-behavior: contain; }
.hoja-pie {
  padding: var(--e3) var(--e4); border-top: 1px solid var(--line);
  background: var(--surface-2); flex: none;
}

/* Quien pidió menos movimiento en el sistema operativo no quiere que una
   hoja se le deslice por la pantalla. Aparece y ya. */
@media (prefers-reduced-motion: reduce) {
  .hoja-abajo, .hoja-fondo { transition: none; }
}

/* ------------------------------------------- la lista para elegir -------- */
.hoja-buscar {
  width: 100%; border: 0; border-bottom: 1px solid var(--line);
  padding: var(--e3) var(--e4); font: inherit; font-size: 1rem;
  background: var(--surface); color: var(--ink); outline: none;
  position: sticky; top: 0; z-index: 1;
}
.hoja-lista { display: flex; flex-direction: column; padding: var(--e1) 0; }
.hoja-item {
  display: flex; align-items: center; gap: var(--e3); width: 100%;
  padding: 0 var(--e4); min-height: var(--toque);
  border: 0; background: none; color: var(--ink);
  font: inherit; font-size: 0.95rem; text-align: left;
  justify-content: space-between; cursor: pointer;
  border-bottom: 1px solid var(--line);
}
.hoja-item:last-child { border-bottom: 0; }
.hoja-item:active { background: var(--surface-2); }
.hoja-item.elegido { color: var(--pine); font-weight: 650;
  background: var(--pine-soft); box-shadow: inset 3px 0 0 var(--pine); }
.hoja-item svg { width: 18px; height: 18px; flex: none; }
.hoja-vacio { padding: var(--e5); text-align: center; color: var(--ink-3); }

/* ------------------------------------------- el menú en la hoja ---------- */
.hoja-menu { display: flex; flex-direction: column; padding-bottom: var(--e2); }
.hoja-menu-grupo {
  font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.09em;
  font-weight: 650; color: var(--ink-3);
  padding: var(--e4) var(--e4) var(--e1);
}
.hoja-menu-item {
  display: flex; align-items: center; gap: var(--e3);
  padding: 0 var(--e4); min-height: var(--toque);
  color: var(--ink-2); text-decoration: none; font-size: 0.95rem;
  border-bottom: 1px solid var(--line);
}
.hoja-menu-item:active { background: var(--surface-2); }
.hoja-menu-item.activo {
  color: var(--pine); font-weight: 650; background: var(--pine-soft);
  box-shadow: inset 3px 0 0 var(--pine);
}
.hoja-menu-item svg { width: 19px; height: 19px; flex: none; }
/* «Instalar la app» es un botón y no un enlace —no lleva a ninguna pantalla—
   pero en la lista tiene que verse igual que los demás renglones. */
button.hoja-menu-item {
  width: 100%; background: none; border: 0; border-bottom: 1px solid var(--line);
  border-radius: 0; font: inherit; text-align: left; justify-content: flex-start;
}
button.hoja-menu-item:hover { background: var(--surface-2); }

/* Texto corrido adentro de una hoja de abajo: instrucciones, explicaciones. */
.hoja-texto { padding: var(--e3) var(--e4) var(--e4); display: flex; flex-direction: column; gap: var(--e3); }
.hoja-texto p { margin: 0; color: var(--ink-2); line-height: 1.55; }
.hoja-texto .aviso { display: flex; flex-direction: column; gap: 3px; }

/* ------------------------------------------- instalar y versión nueva ---- */
/*
   Un solo cartel, abajo, arriba de la barra de pestañas. Es el único lugar
   donde el sistema interrumpe sin que le pregunten, así que: uno por vez,
   siempre con la salida a la vista, y nunca arriba de la pantalla —tapar el
   título es lo que hace que la gente cierre sin leer—.
*/
.cartel-app {
  position: fixed;
  left: var(--e3); right: var(--e3);
  bottom: calc(var(--nav-h) + env(safe-area-inset-bottom) + var(--e3));
  z-index: 45;
  display: flex; align-items: center; gap: var(--e3);
  padding: var(--e3) var(--e3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.18);
  animation: subir 0.22s ease;
}
.cartel-app.nuevo { border-color: var(--pine); box-shadow: 0 8px 28px rgba(15, 95, 75, 0.28); }
.cartel-ico {
  flex: none; display: flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 10px;
  background: var(--pine-soft); color: var(--pine);
}
.cartel-ico svg { width: 21px; height: 21px; }
.cartel-texto { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.cartel-texto strong { font-size: 0.9rem; }
.cartel-texto span { font-size: 0.78rem; color: var(--ink-3); }
.cartel-botones { display: flex; gap: 6px; flex: none; }
@keyframes subir { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .cartel-app { animation: none; } }

/* En el teléfono el texto y los botones no entran en un renglón. */
@media (max-width: 560px) {
  .cartel-app { flex-wrap: wrap; }
  .cartel-botones { width: 100%; justify-content: flex-end; }
}
/* En el escritorio no ocupa el ancho de la pantalla: va en la esquina. */
@media (min-width: 860px) {
  .cartel-app { left: auto; width: min(420px, calc(100vw - 60px)); right: 26px; bottom: 26px; }
}
/* Los avisos flotantes suben para no quedar debajo del cartel. */
body.con-cartel-app .barra-carrito { bottom: calc(var(--nav-h) + 84px); }

/* ------------------------------- el selector convertido en botón --------- */
/*
   El `<select>` real sigue en el documento —escondido pero vivo— porque de él
   dependen setenta y siete pantallas que leen su valor y escuchan su evento.
   Esto es sólo la cara visible. Ver `selector()` en app.js.
*/
.sel-oculto {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.sel-boton {
  display: flex; align-items: center; gap: var(--e2); width: 100%;
  min-height: var(--toque); padding: 0 var(--e3);
  border: 1px solid var(--line-strong); border-radius: var(--r);
  background: var(--surface); color: var(--ink);
  font: inherit; font-size: 0.95rem; text-align: left;
  justify-content: space-between; cursor: pointer;
}
.sel-boton .sel-txt {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sel-boton svg { width: 18px; height: 18px; flex: none; color: var(--ink-3); }
.sel-boton:active { background: var(--surface-2); }

/* --------------------------------------------- el botón «Más» del tabbar - */
/*
   Es un botón y no un enlace porque no lleva a ninguna pantalla: abre el menú
   ahí mismo. Se ve exactamente igual que las otras pestañas —mismo alto,
   misma pastilla, misma letra— porque para el que lo usa es una pestaña más.
*/
.tab-mas {
  flex: 1; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 3px; min-width: 0; padding: 0 2px;
  border: 0; background: none; color: var(--ink-3);
  font: inherit; font-size: 0.66rem; font-weight: 600; letter-spacing: 0.01em;
  cursor: pointer; min-height: 0;
}
.tab-mas .tab-ico {
  display: flex; align-items: center; justify-content: center;
  width: 46px; height: 24px; border-radius: 12px;
}
.tab-mas svg { width: 21px; height: 21px; }
.tab-mas.activo { color: var(--pine); font-weight: 700; }
.tab-mas.activo .tab-ico { background: var(--pine-soft); }
.tab-mas:active .tab-ico { background: var(--surface-2); }

/* El rebote de la página al tirar hacia abajo se queda adentro de la app: sin
   esto, en Android el gesto arrastra toda la ventana y la app se despega del
   borde, que es lo que delata que no es una app nativa. */
html, body { overscroll-behavior-y: contain; }
