/* ════════════════════════════════════════════════════════════════════
   TECNOBOX TRACK — PIXEL ART / RETRO
   1-sept-2026 · escalas y elevación, 2-sept-2026.

   Calcado de los 7 mockups de los diseñadores (`D:\Downloads\Nuevo
   Design`). La paleta NO está estimada a ojo: se midió leyendo los
   píxeles de los propios mockups con un canvas.

   ── Qué cambió el 2-sept y por qué ──────────────────────────────────
   Se midió el archivo anterior: 13 tamaños de fuente, 30 combinaciones
   de padding, 11 gaps, 8 radios y 10 hexadecimales sueltos. Eso no es
   una escala, son decisiones sueltas tomadas de a una — lo contrario de
   lo que Apple llama *Craft* ("cada valor de espaciado, tiempo y
   alineación es una decisión deliberada que podés defender").

   Ahora hay SEIS pasos de tipografía, SEIS de espaciado, TRES radios,
   DOS grosores de borde y TRES niveles de elevación. Todo lo demás sale
   de ahí. Si un bloque "necesita" 14 px, lo que necesita es 12 o 16.

   Tres reglas que conviene no romper:

   1. `image-rendering: pixelated` en TODO PNG de pixel art. Sin eso el
      navegador interpola al escalar y el retro se ve barato.
   2. **Si tiene sombra, se hunde al presionarlo.** La sombra dura acá es
      el equivalente del material translúcido de Apple: codifica
      jerarquía. Una tarjeta con la misma sombra que un botón promete una
      interacción que no existe.
   3. El tracking depende del TAMAÑO. Los títulos van con tracking
      negativo (a 26 px las letras ya se leen separadas) y los rótulos
      chicos con tracking positivo. Un solo valor para todos está mal en
      algún lado por definición.
   ════════════════════════════════════════════════════════════════════ */

/* ── Tipografías ─────────────────────────────────────────────────────
   DOS familias, no tres, y ninguna de mapa de bits (3-sept-2026).

   ── Por qué se fueron las pixel ─────────────────────────────────────
   Pixelify Sans, Silkscreen y Jersey 25 eran fieles al mockup, pero una
   tipografía de mapa de bits sigue siendo de mapa de bits: a 9 px en
   mayúsculas está en el límite de lo legible, y en una tabla de catálogo
   con SKU de 13 dígitos que difieren en uno solo (6959532304848 contra
   6959532304831) cuesta leer de verdad. Estaba anotado como decisión
   pendiente desde el 1-sept y se tomó.

   **El lenguaje pixel art NO se fue**: los iconos, las ilustraciones,
   los bordes duros, las sombras desplazadas y los bloques siguen igual.
   Lo que cambió es la letra, que ahora es una tipografía real.

   ── Por qué estas dos, medidas y no elegidas a ojo ──────────────────
   Se compararon doce candidatas renderizando los casos que fallan de
   verdad: los dos SKU que difieren en un dígito, un nombre de producto
   largo en mayúsculas, la columna de plata y los rótulos de 9 px. Se
   midió el ancho de cada una con `tools/medir.mjs`, porque el ancho es
   lo que decide si la tabla entra en un celular.

   **Chakra Petch — la interfaz.** Sus esquinas cortadas en plano son lo
   más cercano a un bloque de píxel que existe en una tipografía de
   contornos: rima con el marco duro y con los iconos sin pedir permiso.
   Y es la más compacta de las seis candidatas en MAYÚSCULAS (239 px
   contra 263 de Archivo en la misma línea de rótulos), que importa
   porque esta interfaz está llena de rótulos en caja alta.

   **Chivo Mono — los datos.** Monoespaciada, con el cero barrado y el
   3/8/9 inconfundibles, que es exactamente lo que fallaba. Se descartó
   Martian Mono por ancha (557 px contra 477 en el nombre largo: un 17%
   más de tabla) e IBM Plex Mono por ser la que todo el mundo usa por
   reflejo.

   ⚠️ La letra ahora ocupa MÁS. Medido: el nombre largo pasa de 363 px
   con Jersey 25 a 477 con Chivo Mono, un 31% más. La tabla scrollea
   dentro de su caja, así que no rompe la página — pero si algún día se
   agrega una columna a Bodega, esto es lo que hay que volver a medir.

   Auto-hospedadas y no por CDN a propósito: esto lo abre gente de bodega
   desde el celular y a veces con mala señal. Se bajan con
   `node tools/bajar-fuente.mjs "Chakra Petch" 400,600,700 public/fuentes`,
   solo los subsets latin y latin-ext. Las dos son SIL Open Font License
   1.1, que permite auto-hospedarlas. Ver public/fuentes/LEEME.txt. */

@font-face {
  font-family: "Chakra Petch"; font-style: normal; font-weight: 400;
  font-display: swap; src: url(fuentes/chakrapetch-400-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Chakra Petch"; font-style: normal; font-weight: 400;
  font-display: swap; src: url(fuentes/chakrapetch-400-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Chakra Petch"; font-style: normal; font-weight: 600;
  font-display: swap; src: url(fuentes/chakrapetch-600-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Chakra Petch"; font-style: normal; font-weight: 600;
  font-display: swap; src: url(fuentes/chakrapetch-600-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Chakra Petch"; font-style: normal; font-weight: 700;
  font-display: swap; src: url(fuentes/chakrapetch-700-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Chakra Petch"; font-style: normal; font-weight: 700;
  font-display: swap; src: url(fuentes/chakrapetch-700-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Chivo Mono"; font-style: normal; font-weight: 400;
  font-display: swap; src: url(fuentes/chivomono-400-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Chivo Mono"; font-style: normal; font-weight: 400;
  font-display: swap; src: url(fuentes/chivomono-400-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Chivo Mono"; font-style: normal; font-weight: 700;
  font-display: swap; src: url(fuentes/chivomono-700-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Chivo Mono"; font-style: normal; font-weight: 700;
  font-display: swap; src: url(fuentes/chivomono-700-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* ── Paleta MEDIDA de los mockups ───────────────────────────────
     Marco/sidebar #0B1618 · contenido #F4F0ED · pill activa #71A401 ·
     header de tabla #589B01 · barras #5C8E02 · ámbar #F4AD04.
     Ojo: el verde del mockup es más oscuro y oliva que el #90C838 del
     isotipo. El logo conserva el suyo; la interfaz usa estos. */
  --negro: #0B1618;
  --negro-alto: #16241F;
  --borde-marco: #2C3D38;

  --crema: #F4F0ED;
  --crema-2: #EAE5DC;
  --crema-3: #DCD5C9;

  --verde-vivo: #71A401;
  --verde: #5C9101;
  --verde-osc: #3D6300;
  --verde-claro: #9BD127;

  /* Verde SOLO para superficies con texto blanco encima (encabezado de
     tabla y barra de título de sección). El #5C9101 del mockup da 3.81:1
     con blanco, medido — y WCAG AA pide 4.5 para texto de menos de 18.7
     px, que es justo lo que va ahí: rótulos de 9 y 11 px en tipografía de
     mapa de bits. Este da 5.15:1. Es el mismo verde apenas más oscuro; el
     de las barras y las pills sigue siendo --verde. */
  --verde-tabla: #4A7A00;

  --ambar: #F4AD04;
  --rojo: #D64541;
  --azul: #3E7CB1;

  --tinta: #14201C;
  --tinta-2: #54625D;
  --tinta-clara: #C9D6CE;

  /* Los diez hexadecimales que antes vivían sueltos por el archivo. Los
     rellenos claros de las pills son el caso típico: se eligieron a ojo
     uno por uno, y con el token al lado del color del que derivan se ve
     que son una familia y no seis colores distintos. */
  --blanco: #fff;
  --relleno-ambar: #FDF3DC;
  --tinta-ambar: #8A6102;
  --relleno-azul: #E4EEF6;
  --tinta-azul: #2C5D86;
  --relleno-verde: #E7F2D6;
  --tinta-verde: #40660A;
  --relleno-rojo: #FBE4E3;
  --tinta-rojo: #A3302C;
  --gris-marcador: #9AA6A0;      /* placeholder de los campos */
  --verde-tenue: rgba(113, 164, 1, 0.16);
  --verde-tenue-2: rgba(113, 164, 1, 0.14);

  /* ── Escala tipográfica: SEIS pasos, no trece ──────────────────
     En `rem`, no en px: quien agrandó la letra de su sistema tiene que
     ver la interfaz más grande, no idéntica. El tracking y el
     interlineado son parte del paso, no un ajuste aparte — la jerarquía
     se arma con los tres juntos. */
  --t-titulo: 1.625rem;    /* 26px · título de página */
  --t-cifra: 1.875rem;     /* 30px · número de tarjeta */
  --t-cuerpo: 1rem;        /* 16px · texto, menú, buscador */
  --t-tabla: 0.9375rem;    /* 15px · celdas */
  --t-rotulo: 0.6875rem;   /* 11px · etiquetas en mayúsculas */
  --t-micro: 0.5625rem;    /* 9px  · ejes, badges */

  --tr-titulo: -0.02em;    /* negativo: a 26px las letras ya se separan */
  --tr-rotulo: 0.06em;     /* positivo: a 11px hay que abrirlas */
  --tr-micro: 0.08em;

  /* ── Escala de espaciado: base 4 ────────────────────────────────
     La que corresponde a un sistema construido sobre una grilla de
     píxeles. Todo padding, gap y margen sale de acá. */
  --e1: 0.25rem;   /*  4px */
  --e2: 0.5rem;    /*  8px */
  --e3: 0.75rem;   /* 12px */
  --e4: 1rem;      /* 16px */
  --e5: 1.5rem;    /* 24px */
  --e6: 2rem;      /* 32px */

  /* Radios: tres. 0 para lo que es rejilla, `--r` para todo lo que es
     una pieza, y `--r-pill` para las etiquetas de estado. */
  --r: 0.5rem;
  --r-pill: 999px;

  /* Bordes: dos. Interno para separadores y badges, estructural para
     paneles, botones y tarjetas. */
  --b-int: 2px;
  --b-est: 3px;

  /* ── Elevación: TRES niveles, cada uno con significado ──────────
     En pixel art no hay translucidez, pero la sombra dura desplazada
     hace el mismo trabajo que el material de Apple: codificar jerarquía.

       0 · pegado      sin sombra    es parte del fondo (filas, rejilla)
       1 · apoyado     --elev-1      contenido sobre el lienzo
       2 · accionable  --elev-2      se puede tocar, y BAJA al presionar

     La regla que lo convierte en sistema: si tiene sombra y no se hunde
     al presionarlo, no debería tener sombra. */
  --elev-1: var(--b-est) var(--b-est) 0 var(--crema-3);
  --elev-2: var(--b-est) var(--b-est) 0 var(--verde-osc);

  /* DOS familias, con un trabajo cada una. Antes eran tres, y la
     diferencia entre `--display` y `--rotulo` la cargaba la fuente; ahora
     la cargan el tamaño, el peso y la caja alta, que es donde ya vivía la
     jerarquía. Una familia menos es una decisión menos que defender.

       --interfaz  todo lo que se LEE: menú, títulos, botones, rótulos
       --dato      todo lo que se COMPARA: SKU, cifras, tablas, ejes

     La regla para saber cuál va: si el ojo recorre la columna hacia
     abajo buscando una diferencia, es `--dato`. Si lee de izquierda a
     derecha, es `--interfaz`. */
  --interfaz: "Chakra Petch", ui-sans-serif, system-ui, sans-serif;
  --dato: "Chivo Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;

  --sidebar: 15.5rem;

  /* Objetivo táctil mínimo. Apple pide 44 px y esto lo usa gente de
     bodega desde el celular, con las manos ocupadas. */
  --tactil: 2.75rem;
}

* { box-sizing: border-box; }

/* Todo lo que sea pixel art se escala SIN interpolar. Es la regla que
   separa "retro" de "borroso". */
img, .ilustracion, .op::before, .tarjeta::before, .marca-pill,
#icono-pagina, .vacio, .orden-ind, .caja-entrada::before, .demo-cartel::before {
  image-rendering: pixelated;
}

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  padding: var(--e3);
  min-height: 100dvh;
  background: var(--negro);
  color: var(--tinta);
  font-family: var(--interfaz);
  font-size: var(--t-cuerpo);
  line-height: 1.5;
}

h1, h2, h3 { margin: 0; font-weight: 700; }
p { margin: 0 0 var(--e3); }

code {
  font-family: var(--dato);
  font-size: var(--t-tabla);
  background: var(--crema-2);
  border: var(--b-int) solid var(--crema-3);
  padding: 0 var(--e1);
}

:focus-visible {
  outline: var(--b-est) solid var(--verde-vivo);
  outline-offset: 1px;
}
::selection { background: var(--verde-vivo); color: var(--negro); }

/* Barras de scroll cuadradas: una barra redondeada al lado de una
   interfaz de bloques se nota. */
* { scrollbar-width: thin; scrollbar-color: var(--verde-osc) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: var(--crema-2); }
*::-webkit-scrollbar-thumb { background: var(--verde-osc); border: var(--b-int) solid var(--crema-2); }
*::-webkit-scrollbar-thumb:hover { background: var(--verde); }

/* ⚠️ ESTA REGLA ES LA QUE ARREGLA EL LOGIN (29-ago-2026).
   `[hidden]` es una regla del navegador con especificidad de ETIQUETA;
   un selector de CLASE como `.entrada { display: grid }` le gana. O sea
   que poner `entrada.hidden = true` desde el JavaScript NO la escondía:
   la clave se validaba bien, el token se emitía bien, y la pantalla de
   entrada se quedaba encima tapando la plataforma. Se veía como "el
   login falla" cuando en realidad el login funcionaba.
   Cada vez que se le ponga `display` a algo que se esconde con `hidden`,
   hay que agregar su par `[hidden]`. */
[hidden] { display: none !important; }

/* ════════════════════════════════════════════════════════════════════
   PANTALLA DE ENTRADA
   ════════════════════════════════════════════════════════════════════ */

.entrada {
  min-height: calc(100dvh - var(--e6));
  display: grid; place-items: center;
  padding: var(--e4);
}

.caja-entrada {
  position: relative;
  background: var(--crema);
  border: var(--b-est) solid var(--negro);
  border-radius: var(--r);
  box-shadow: 0 0 0 var(--b-est) var(--borde-marco);
  padding: var(--e6) var(--e5) var(--e5);
  width: min(27rem, 100%);
}

/* La llave y el candado, arriba a la derecha de la caja. Dice de qué se
   trata la pantalla antes de leer una palabra, que es justo lo que una
   ilustración tiene que hacer. Decorativa: el texto ya lo dice todo, así
   que va por background y el lector de pantalla no la anuncia. */
.caja-entrada::before {
  content: "";
  position: absolute; top: calc(-1 * var(--e5)); right: calc(-1 * var(--e2));
  width: 4.5rem; height: 4.5rem;
  background: center / contain no-repeat url(iconos/entrada-clave.png);
}

.marca-entrada { margin: 0 0 var(--e3); }
.marca-entrada img { display: block; width: 100%; max-width: 15rem; height: auto; margin: 0 auto; }

.bajada {
  font-family: var(--interfaz); font-weight: 600;
  font-size: var(--t-rotulo); text-transform: uppercase;
  letter-spacing: var(--tr-rotulo); line-height: 1.3;
  color: var(--tinta-2); margin: var(--e2) 0 var(--e4);
}

.caja-entrada input {
  width: 100%; padding: var(--e3) var(--e3);
  border: var(--b-est) solid var(--negro); border-radius: 0;
  font-family: var(--dato); font-size: var(--t-cuerpo);
  background: var(--blanco); color: var(--tinta);
  min-height: var(--tactil);
}
.caja-entrada input:focus { outline: none; border-color: var(--verde); }

.fila-btns { display: flex; gap: var(--e2); margin-top: var(--e3); }
.fila-btns .btn { flex: 1; justify-content: center; }
.error {
  color: var(--rojo); min-height: 1.25rem;
  margin: var(--e3) 0 0; font-size: var(--t-tabla);
}
.pie {
  font-family: var(--interfaz); font-size: var(--t-micro); font-weight: 600;
  letter-spacing: var(--tr-micro); line-height: 1.7;
  color: var(--tinta-2); margin: var(--e4) 0 0; text-align: center;
}

/* Las personas, como botones. Área grande a propósito: la persona de
   bodega entra desde el celular, con las manos ocupadas.

   El desplazamiento al presionar imita una tecla física: el botón baja a
   ocupar el lugar de su propia sombra. Es el único movimiento del
   sistema, y es instantáneo — el feedback vive en el `pointer-down`, no
   al soltar, y en pixel art una transición suave desentona. */
.gente { display: grid; gap: var(--e2); grid-template-columns: repeat(2, 1fr); }
.persona {
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--e1);
  padding: var(--e3); cursor: pointer; text-align: left;
  min-height: var(--tactil);
  font-family: var(--interfaz);
  background: var(--crema-2);
  border: var(--b-est) solid var(--negro);
  border-radius: var(--r);
  color: var(--tinta);
  box-shadow: var(--elev-2);
}
.persona:hover { background: var(--crema); border-color: var(--verde); }
.persona:active { transform: translate(var(--b-est), var(--b-est)); box-shadow: none; }
.persona b { font-size: var(--t-tabla); }
.persona small {
  font-family: var(--interfaz); font-size: var(--t-micro); font-weight: 600;
  letter-spacing: var(--tr-micro);
  text-transform: uppercase; color: var(--tinta-2);
}

/* ════════════════════════════════════════════════════════════════════
   ARMAZÓN — marco negro, sidebar oscuro, contenido crema
   ════════════════════════════════════════════════════════════════════ */

.app {
  display: grid;
  grid-template-columns: var(--sidebar) 1fr;
  gap: var(--e3);
  min-height: calc(100dvh - var(--e6));
  padding: var(--e3);
  background: var(--negro);
  border: var(--b-est) solid var(--borde-marco);
  border-radius: var(--r);
}

aside {
  position: relative;
  display: flex; flex-direction: column;
  padding: var(--e4) var(--e3);
  background: linear-gradient(180deg, var(--negro-alto) 0%, var(--negro) 55%);
  border: var(--b-int) solid var(--borde-marco);
  border-radius: var(--r);
  overflow: hidden;
}

.marca { padding: 0 var(--e1) var(--e4); line-height: 1; }
/* En el sidebar va el logo claro: el original tiene la palabra "Tecno"
   en tinta negra y sobre este fondo desaparece. La pantalla de entrada,
   que es crema, sigue usando el original.

   El logo del sidebar es SVG y trae `shape-rendering="crispEdges"`
   adentro: dibuja los bloques con borde duro por su cuenta, a cualquier
   tamaño y sin depender de que el CSS acierte con el redondeo. Por eso
   se le apaga `image-rendering`, que sobre un vector no aporta nada. */
.marca img {
  display: block; width: 100%; max-width: 11.875rem; height: auto;
  image-rendering: auto;
}

.menu { display: flex; flex-direction: column; gap: var(--e1); }

/* ── Separador de área: ◆- ECOMMERCE ------◆ ──────────────────────
   El rombo y la línea de guiones del mockup, sin ningún asset: son dos
   pseudo-elementos y un borde punteado. */
.area-tit {
  display: flex; align-items: center; gap: var(--e2);
  font-family: var(--interfaz); font-size: var(--t-micro); font-weight: 600;
  text-transform: uppercase; letter-spacing: var(--tr-micro);
  color: var(--verde-vivo);
  padding: var(--e4) var(--e1) var(--e2);
  white-space: nowrap;
}
.area-tit:first-child { padding-top: 0; }
.area-tit::before { content: "◆"; color: var(--verde); }
.area-tit::after {
  content: ""; flex: 1 1 auto; min-width: 0.625rem;
  border-top: var(--b-int) dashed var(--verde-osc);
}

.op {
  position: relative;
  display: flex; align-items: center; gap: var(--e3);
  text-align: left; padding: var(--e2) var(--e3);
  min-height: var(--tactil);
  border: var(--b-int) solid transparent; border-radius: var(--r);
  background: none; cursor: pointer;
  font-family: var(--interfaz); font-size: var(--t-cuerpo);
  color: var(--tinta-clara);
}

/* El icono de cada módulo. Son PNG de pixel art de ~24x24 píxeles
   lógicos, generados desde las ilustraciones del set con
   `tools/pixelar.ps1` (paleta cerrada y alfa binario). */
.op::before {
  content: "";
  flex: 0 0 auto; width: 1.375rem; height: 1.375rem;
  background: center / contain no-repeat;
}
.op[data-ir="hoy"]::before        { background-image: url(iconos/nav-hoy.png); }
.op[data-ir="alertas"]::before    { background-image: url(iconos/nav-alertas.png); }
.op[data-ir="etiquetas"]::before  { background-image: url(iconos/nav-etiquetas.png); }
.op[data-ir="bodega"]::before     { background-image: url(iconos/nav-bodega.png); }
.op[data-ir="ventas"]::before     { background-image: url(iconos/nav-ventas.png); }
.op[data-ir="marketing"]::before  { background-image: url(iconos/nav-marketing.png); }
.op[data-ir="reportes"]::before   { background-image: url(iconos/nav-reportes.png); }
.op[data-ir="config"]::before     { background-image: url(iconos/nav-config.png); }
/* Los módulos de Mercado Libre repiten el icono de su par de ecommerce.
   Están `disabled`, así que no llevan `data-ir`: se enganchan por el
   nombre que sí tienen. */
.op[data-icono-ml="hoy"]::before       { background-image: url(iconos/nav-hoy.png); }
.op[data-icono-ml="ventas"]::before    { background-image: url(iconos/nav-ventas.png); }
.op[data-icono-ml="bodega"]::before    { background-image: url(iconos/nav-bodega.png); }
.op[data-icono-ml="etiquetas"]::before { background-image: url(iconos/nav-etiquetas.png); }
.op[data-icono-ml="reportes"]::before  { background-image: url(iconos/nav-reportes.png); }
.op[data-icono-ml="comisiones"]::before { background-image: url(iconos/met-etiqueta.png); }

.op:hover { background: var(--verde-tenue-2); color: var(--blanco); }

/* El módulo activo: pill verde llena, como en el mockup. El borde negro
   y la luz de arriba son lo que le dan el relieve de botón de consola. */
.op.activa {
  background: linear-gradient(180deg, var(--verde-vivo) 0%, var(--verde) 100%);
  border-color: var(--negro);
  color: var(--negro);
  font-weight: 700;
  box-shadow: inset 0 var(--b-int) 0 rgba(255, 255, 255, 0.35);
}
.op.activa:hover { color: var(--negro); }

/* Apagada de verdad: el botón lleva `disabled`, esto solo lo dice. */
.op.apagada { opacity: .38; cursor: not-allowed; }
.op.apagada:hover { background: none; color: var(--tinta-clara); }

.pronto {
  margin-left: auto;
  font-family: var(--interfaz); font-size: var(--t-micro); font-weight: 600;
  letter-spacing: var(--tr-micro);
  background: var(--ambar); color: var(--negro);
  border: var(--b-int) solid var(--negro);
  padding: 0 var(--e1);
}

/* La naturaleza muerta del pie del sidebar: caja, camión, etiqueta y
   bolsa. Es lo que hace la plataforma, dicho sin palabras. */
.ilustracion {
  margin: auto 0 var(--e3);
  width: 100%; aspect-ratio: 1 / 1;
  max-height: 9rem;
  opacity: .92;
  background: center bottom / contain no-repeat url(iconos/ilustracion-bodega.png);
}

.user {
  text-align: left; padding: var(--e2) var(--e3);
  min-height: var(--tactil);
  background: var(--negro-alto);
  border: var(--b-int) solid var(--borde-marco);
  border-radius: var(--r);
  color: var(--tinta-clara);
  cursor: pointer; font-family: var(--interfaz); font-size: var(--t-tabla);
}
.user:hover { border-color: var(--verde); color: var(--blanco); }
.user small {
  display: block; font-family: var(--interfaz); font-size: var(--t-micro); font-weight: 600;
  letter-spacing: var(--tr-micro);
  text-transform: uppercase; color: var(--verde-vivo);
}

/* ── Contenido ──────────────────────────────────────────────────── */

main {
  min-width: 0;
  background: var(--crema);
  border: var(--b-int) solid var(--borde-marco);
  border-radius: var(--r);
  overflow: hidden;
}

.barra {
  display: flex; align-items: center; gap: var(--e3);
  padding: var(--e3) var(--e5);
  background: var(--crema);
  border-bottom: var(--b-est) solid var(--negro);
  position: sticky; top: 0; z-index: 5;
}

/* El icono grande del módulo actual. Cuál se dibuja lo decide el CSS a
   partir de `body[data-vista]`, que escribe `ir()` — así no hay una
   línea de markup por módulo. */
#icono-pagina {
  flex: 0 0 auto; width: 2.375rem; height: 2.375rem;
  background: center / contain no-repeat;
}
body[data-vista="hoy"]       #icono-pagina { background-image: url(iconos/nav-hoy.png); }
body[data-vista="alertas"]   #icono-pagina { background-image: url(iconos/nav-alertas.png); }
body[data-vista="etiquetas"] #icono-pagina { background-image: url(iconos/nav-etiquetas.png); }
body[data-vista="bodega"]    #icono-pagina { background-image: url(iconos/nav-bodega.png); }
body[data-vista="ventas"]    #icono-pagina { background-image: url(iconos/nav-ventas.png); }
body[data-vista="marketing"] #icono-pagina { background-image: url(iconos/nav-marketing.png); }
body[data-vista="reportes"]  #icono-pagina { background-image: url(iconos/nav-reportes.png); }
body[data-vista="config"]    #icono-pagina { background-image: url(iconos/nav-config.png); }

#titulo {
  font-size: var(--t-titulo);
  letter-spacing: var(--tr-titulo);   /* NEGATIVO: a 26px hay que juntarlas */
  line-height: 1.05;
}

.barra .btn { margin-left: auto; }
.icono {
  display: none; border: 0; background: none;
  font-size: var(--t-titulo); line-height: 1;
  min-width: var(--tactil); min-height: var(--tactil);
  cursor: pointer; color: var(--tinta);
}
.modo {
  font-family: var(--interfaz); font-size: var(--t-micro); font-weight: 600;
  letter-spacing: var(--tr-micro);
  text-transform: uppercase; color: var(--tinta-2);
}

.cuerpo { padding: var(--e5) var(--e5) var(--e6); max-width: 94rem; }
.sub {
  font-family: var(--interfaz); font-size: var(--t-micro); font-weight: 600;
  text-transform: uppercase; letter-spacing: var(--tr-micro);
  line-height: 1.6;
  color: var(--tinta-2); margin: 0 0 var(--e4);
}
.cargando { color: var(--tinta-2); }

/* ════════════════════════════════════════════════════════════════════
   PIEZAS
   ════════════════════════════════════════════════════════════════════ */

/* Botones con relieve de tecla: sombra dura desplazada, y al presionar
   el botón baja a ocupar el lugar de su sombra. Sin transición — el
   movimiento instantáneo es parte del lenguaje. Elevación 2: se toca. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--e2);
  padding: var(--e2) var(--e4);
  min-height: var(--tactil);
  background: var(--crema);
  border: var(--b-est) solid var(--negro);
  border-radius: var(--r);
  box-shadow: var(--elev-1);
  cursor: pointer;
  font-family: var(--interfaz); font-size: var(--t-tabla); font-weight: 700;
  color: var(--tinta);
  /* Un botón puede ser un `<a>` (el "Salir del demo" lo es, porque de
     verdad navega). Sin esto le queda el subrayado del enlace y deja de
     verse como sus hermanos. */
  text-decoration: none;
}
.btn:hover { background: var(--blanco); border-color: var(--verde); }
.btn:active { transform: translate(var(--b-est), var(--b-est)); box-shadow: none; }
.btn:disabled { opacity: .45; cursor: default; transform: none; box-shadow: none; }

.btn.solido {
  background: linear-gradient(180deg, var(--verde-vivo) 0%, var(--verde) 100%);
  color: var(--negro);
  box-shadow: var(--elev-2);
}
.btn.solido:hover { border-color: var(--negro); filter: brightness(1.08); }

/* La variante chica sigue siendo un botón: mantiene la sombra y el
   hundido, solo baja de tamaño y de grosor de borde.

   Lo que NO baja es el objetivo táctil. Medido, con 2rem quedaba en
   58×32 px: pasa el mínimo de WCAG 2.2 (24×24) pero no los 44 que pide
   Apple, y el "Listo" de Alertas y los números de paginación se tocan
   desde el celular igual que cualquier otro botón. Que un botón sea
   visualmente más chico no lo hace menos apretable. */
.btn.mini {
  padding: var(--e1) var(--e3); font-size: var(--t-rotulo);
  border-width: var(--b-int); min-height: var(--tactil);
}

/* La fila de acciones de una sección. Lleva aire ARRIBA también: pegada
   al panel anterior parece pertenecerle, y pertenece a la tabla de
   abajo. */
.acciones {
  display: flex; gap: var(--e2); flex-wrap: wrap;
  margin: var(--e3) 0 var(--e3);
}
/* Salvo cuando viene justo después de la barra verde de su sección: ahí
   ya son lo mismo y separarlos rompería el bloque. */
h2 + .acciones { margin-top: var(--e3); }

/* ── Tarjetas de métrica ─────────────────────────────────────────────
   Icono a la izquierda, rótulo arriba, número grande. Como en el mockup.

   ⚠️ POR DEFECTO NO LLEVAN SOMBRA. Antes tenían la misma que los
   botones y no eran clickeables: eso promete una interacción que no
   existe, que es exactamente lo que rompe la *Familiaridad* ("lo que se
   ve igual tiene que comportarse igual"). Las que SÍ navegan llevan
   `.accionable`, y esas sí tienen sombra y se hunden. */
.tarjetas {
  display: grid; gap: var(--e3);
  grid-template-columns: repeat(auto-fill, minmax(13.5rem, 1fr));
}
.tarjeta {
  display: grid; align-items: center;
  grid-template-columns: 1fr;
  gap: 0 var(--e3);
  padding: var(--e3) var(--e4);
  background: var(--crema);
  border: var(--b-est) solid var(--negro);
  border-radius: var(--r);
  text-align: left;
  font-family: var(--interfaz);
  color: var(--tinta);
}
.tarjeta[data-icono] { grid-template-columns: 2.625rem 1fr; }
.tarjeta[data-icono]::before {
  content: "";
  grid-row: 1 / span 3;
  width: 2.625rem; height: 2.625rem;
  background: center / contain no-repeat;
}
.tarjeta small {
  font-family: var(--interfaz); font-size: var(--t-micro); font-weight: 600;
  text-transform: uppercase; letter-spacing: var(--tr-micro);
  line-height: 1.2;
  color: var(--tinta-2);
}
.tarjeta b {
  display: block;
  font-family: var(--dato); font-size: var(--t-cifra); font-weight: 400;
  letter-spacing: var(--tr-titulo); line-height: 1.1;
  color: var(--verde-osc);
}
.tarjeta span { font-size: var(--t-rotulo); color: var(--tinta-2); }
.tarjeta.alerta { border-color: var(--ambar); }
.tarjeta.alerta b { color: var(--tinta-ambar); }

/* Una tarjeta que lleva a algún lado. "Sin stock: 4" debería poder
   abrirse en la lista de esos 4 — el mapeo entre el control y lo que
   afecta es lo que hace que no haga falta explicarlo. */
.tarjeta.accionable {
  cursor: pointer;
  box-shadow: var(--elev-1);
}
.tarjeta.accionable:hover { border-color: var(--verde); background: var(--blanco); }
.tarjeta.accionable:active { transform: translate(var(--b-est), var(--b-est)); box-shadow: none; }
.tarjeta.accionable.alerta { box-shadow: var(--b-est) var(--b-est) 0 var(--relleno-ambar); }

/* Los iconos de métrica. Cada `data-icono` es una LLAVE, no una ruta: el
   JavaScript no sabe nombres de archivo, así que cambiar un icono es
   tocar una línea acá y nada más. */
.tarjeta[data-icono="carro"]::before      { background-image: url(iconos/met-carro.png); }
.tarjeta[data-icono="caja"]::before       { background-image: url(iconos/met-caja.png); }
.tarjeta[data-icono="camion"]::before     { background-image: url(iconos/met-camion.png); }
.tarjeta[data-icono="etiqueta"]::before   { background-image: url(iconos/met-etiqueta.png); }
.tarjeta[data-icono="impresora"]::before  { background-image: url(iconos/met-impresora.png); }
.tarjeta[data-icono="grafico"]::before    { background-image: url(iconos/met-grafico.png); }
.tarjeta[data-icono="alerta"]::before     { background-image: url(iconos/met-alerta.png); }
.tarjeta[data-icono="escudo"]::before     { background-image: url(iconos/met-escudo.png); }
.tarjeta[data-icono="nube"]::before       { background-image: url(iconos/met-nube.png); }
.tarjeta[data-icono="base"]::before       { background-image: url(iconos/met-base.png); }
.tarjeta[data-icono="adulto"]::before     { background-image: url(iconos/met-adulto.png); }
.tarjeta[data-icono="canales"]::before    { background-image: url(iconos/met-canales.png); }
.tarjeta[data-icono="ajustes"]::before    { background-image: url(iconos/met-ajustes.png); }

/* ── Barra de título de sección ──────────────────────────────────────
   El `<h2>` deja de ser un texto suelto y pasa a ser la barra verde del
   mockup, con su cuadradito de viñeta. Cuando lo que sigue es una tabla
   se unen en un solo panel: `:has()` mira hacia adelante, que es lo que
   permite redondear solo las esquinas de arriba. */
h2 {
  display: flex; align-items: center; gap: var(--e2);
  margin: var(--e5) 0 var(--e3);
  padding: var(--e2) var(--e3);
  background: var(--verde-tabla);
  border: var(--b-est) solid var(--negro);
  border-radius: var(--r);
  font-family: var(--interfaz); font-size: var(--t-rotulo); font-weight: 600;
  text-transform: uppercase; letter-spacing: var(--tr-rotulo); line-height: 1.3;
  color: var(--blanco);
}
h2::before {
  content: ""; flex: 0 0 auto;
  width: 0.6875rem; height: 0.6875rem;
  background: var(--verde-claro);
  border: var(--b-int) solid var(--negro);
}
h2:has(+ .tabla-caja),
h2:has(+ .graf),
h2:has(+ .barrash) { margin-bottom: 0; border-radius: var(--r) var(--r) 0 0; }
h2 + .tabla-caja,
h2 + .graf,
h2 + .barrash { margin-top: 0; border-top: 0; border-radius: 0 0 var(--r) var(--r); }

/* Una nota al pie de un panel, pegada a él y no flotando en el medio.
   La proximidad es la que dice de qué habla. */
h2 + .tabla-caja + .nota,
.graf + .nota, .barrash + .nota, .tabla-caja + .nota {
  margin: var(--e2) 0 var(--e5);
}

/* ── Tablas ──────────────────────────────────────────────────────────
   La tabla scrollea DENTRO de su caja: si el body scrolleara en
   horizontal, en el celular se pierde el menú y la barra. */
.tabla-caja {
  overflow-x: auto;
  background: var(--crema);
  border: var(--b-est) solid var(--negro);
  border-radius: var(--r);
}
table { border-collapse: collapse; width: 100%; font-family: var(--dato); font-size: var(--t-tabla); }
th, td {
  text-align: left; padding: var(--e2) var(--e3);
  border-bottom: var(--b-int) solid var(--crema-3);
  white-space: nowrap;
  line-height: 1.4;
}
thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--verde-tabla);
  color: var(--blanco);
  font-family: var(--interfaz); font-size: var(--t-micro); font-weight: 600;
  text-transform: uppercase; letter-spacing: var(--tr-micro);
  border-bottom: var(--b-est) solid var(--negro);
  padding: 0;
}
/* El contenido de la cabecera va en un botón cuando la columna ordena, y
   en un span cuando no. Los dos con el mismo padding, así el renglón no
   se corre al pasar de una a otra. */
thead th > * {
  display: flex; align-items: center; gap: var(--e1);
  width: 100%; padding: var(--e2) var(--e3);
  font: inherit; letter-spacing: inherit; text-transform: inherit;
  color: inherit; background: none; border: 0; text-align: inherit;
}
thead th.num > * { justify-content: flex-end; }
thead th button {
  cursor: pointer;
  min-height: var(--tactil);
}
thead th button:hover { background: var(--verde-osc); }

/* La flechita de orden. Es el mismo dibujo del set (dos flechas), y
   gira 180° cuando el orden se invierte. */
.orden-ind {
  flex: 0 0 auto; width: 0.75rem; height: 0.75rem;
  background: center / contain no-repeat url(iconos/met-orden.png);
  opacity: .35;
}
thead th[aria-sort] .orden-ind { opacity: 1; }
thead th[aria-sort="descending"] .orden-ind { transform: rotate(180deg); }

tbody tr:nth-child(even) { background: var(--crema-2); }
tbody tr:hover { background: var(--verde-tenue); }
tbody tr:last-child td { border-bottom: 0; }
td b { font-weight: 700; }

/* Números alineados a la derecha y tabulares. Una columna de plata
   desalineada obliga a leer cifra por cifra en vez de comparar de un
   vistazo. */
td.num, th.num, .num {
  text-align: right;
  font-family: var(--dato);
  font-variant-numeric: tabular-nums;
}

/* ── La casilla de selección ─────────────────────────────────────────
   ⚠️ Medía 13×13 px. Es EL objetivo táctil de la persona que empaca en
   EcoProLux, que la toca desde el celular con las manos ocupadas: es el
   control con el que marca lo que despachó. Trece píxeles es un objetivo
   que se falla y se vuelve a intentar, y a veces se falla marcando el
   pedido de al lado.

   La casilla sube a 24 px (el mínimo de WCAG 2.2) y además va dentro de
   un `<label>` que ocupa la celda entera, así que el área que responde
   son los 44 px de alto de la fila. El label no es decoración: es lo que
   hace que tocar al lado de la casilla también la marque. */
.sel-caja {
  display: flex; align-items: center;
  min-height: var(--tactil);
  padding: 0 var(--e2);
  margin: calc(-1 * var(--e2)) calc(-1 * var(--e3));
  cursor: pointer;
}
.sel {
  width: 1.5rem; height: 1.5rem;
  accent-color: var(--verde-tabla);
  cursor: pointer;
}

/* La fila que está por acabarse se marca sola. La pregunta real de
   Bodega no es "qué productos hay" —eso ya se sabe— sino "qué se está
   por acabar", y con 49 filas de idéntico peso visual esa pregunta no
   se contesta. Un borde, no una columna nueva. */
tbody tr.poco td:first-child { box-shadow: inset var(--b-est) 0 0 var(--ambar); }
tbody tr.nada td:first-child { box-shadow: inset var(--b-est) 0 0 var(--rojo); }

/* Toda la fila abre la ficha, no solo el nombre. Como texto suelto el
   enlace medía 17 px de alto y Apple recomienda 44 — esto lo usa gente
   de bodega desde el celular con las manos ocupadas. */
tbody tr.clicable { cursor: pointer; }
tbody tr.clicable td { height: var(--tactil); }
.fila-clic {
  color: var(--tinta);
  /* El subrayado va por text-decoration y NO por border-bottom: el borde
     sigue a la CAJA y se despega del texto. text-decoration sigue a las
     letras. */
  text-decoration: underline;
  text-decoration-color: var(--crema-3);
  text-decoration-thickness: var(--b-int);
  text-underline-offset: 3px;
}
tbody tr.clicable:hover .fila-clic { color: var(--verde-osc); text-decoration-color: var(--verde); }

/* El estado vacío lleva su ilustración: una caja abierta con chispas.
   Una tabla que solo dice "sin datos" se lee como algo que falló; con el
   dibujo se lee como algo que todavía no pasó, que es la verdad. Va por
   background porque es decorativa — el texto ya dice lo mismo. */
.vacio {
  color: var(--tinta-2); text-align: center;
  padding: 7.5rem var(--e5) var(--e5);
  font-family: var(--interfaz); font-size: var(--t-rotulo); font-weight: 600;
  letter-spacing: var(--tr-rotulo); line-height: 1.6;
  text-transform: uppercase;
  background: center var(--e5) / 5.25rem 5.25rem no-repeat url(iconos/vacio-sin-datos.png);
}
/* Dentro de una tabla el vacío es una celda: ahí el dibujo entero
   desbalancea la fila, así que va más chico. */
td.vacio { padding: 6rem var(--e4) var(--e4); background-size: 4.25rem 4.25rem; white-space: normal; }

/* ── Badges de estado ────────────────────────────────────────────────
   ⚠️ UNA PILL ES UNA ETIQUETA, NO UN CONTROL, y la forma tiene que
   decirlo. Antes `.pill` (PUBLICADO, BORRADOR) y `.chip` (selector de
   período) se veían casi iguales: dos cápsulas con borde. Quien
   intentaba hacer clic en un estado no obtenía nada y no entendía por
   qué.

   Ahora la etiqueta va TOTALMENTE redondeada y SIN sombra; el control va
   con esquina de 8 px, sombra y hundido. La forma pasa a decir la
   función.

   El color sí es información: distinguir "despachada" de "cancelada" no
   es decoración. */
.pill {
  display: inline-flex; align-items: center; gap: var(--e1);
  padding: var(--e1) var(--e3);
  font-family: var(--interfaz); font-size: var(--t-micro); font-weight: 600;
  text-transform: uppercase; letter-spacing: var(--tr-micro); line-height: 1.2;
  background: var(--crema-2); color: var(--tinta-2);
  border: var(--b-int) solid var(--tinta-2);
  border-radius: var(--r-pill);
  white-space: nowrap;
}
.pill::before {
  content: ""; width: 0.375rem; height: 0.375rem; flex: 0 0 auto;
  background: currentColor; border-radius: 50%;
}
.pill.pendiente  { background: var(--relleno-ambar); color: var(--tinta-ambar); border-color: var(--ambar); }
.pill.preparando { background: var(--relleno-azul); color: var(--tinta-azul); border-color: var(--azul); }
.pill.despachada,
.pill.entregada,
.pill.publicado  { background: var(--relleno-verde); color: var(--tinta-verde); border-color: var(--verde); }
.pill.cancelada  { background: var(--relleno-rojo); color: var(--tinta-rojo); border-color: var(--rojo); }
.pill.sinstock   { background: var(--relleno-ambar); color: var(--tinta-ambar); border-color: var(--ambar); }

/* La marca de producto restringido. Reemplaza al emoji 🔞: un glifo del
   sistema operativo metido en una pantalla de pixel art se ve pegado, y
   además cambia de dibujo en cada plataforma. */
.marca-pill {
  display: inline-block; width: 1.5rem; height: 1.5rem; vertical-align: -0.35rem;
  background: center / contain no-repeat url(iconos/met-adulto.png);
}

/* ── Avisos y notas ──────────────────────────────────────────────── */
.aviso-caja {
  display: flex; align-items: flex-start; gap: var(--e3);
  background: var(--crema-2);
  border: var(--b-est) solid var(--negro);
  border-left-width: var(--e2); border-left-color: var(--verde);
  border-radius: var(--r);
  padding: var(--e3) var(--e4);
  margin-bottom: var(--e4);
}
.aviso-caja.malo { border-left-color: var(--rojo); }
.aviso-caja.ojo { border-left-color: var(--ambar); }
.aviso-caja p:last-child { margin-bottom: 0; }

/* La ilustración del aviso, cuando la hay. Es un `::before` con llave,
   igual que las tarjetas: el JavaScript pasa `escudo` o `nube`, nunca
   una ruta. */
.aviso-caja[data-icono]::before {
  content: ""; flex: 0 0 auto;
  width: 2.75rem; height: 2.75rem;
  background: center / contain no-repeat;
  image-rendering: pixelated;
}
.aviso-caja[data-icono="escudo"]::before { background-image: url(iconos/met-escudo.png); }
.aviso-caja[data-icono="nube"]::before   { background-image: url(iconos/met-nube.png); }
.aviso-caja[data-icono="base"]::before   { background-image: url(iconos/met-base.png); }
.aviso-caja[data-icono="alerta"]::before { background-image: url(iconos/met-alerta.png); }
.aviso-caja[data-icono="ajustes"]::before { background-image: url(iconos/met-ajustes.png); }
.aviso-caja[data-icono="caja"]::before   { background-image: url(iconos/met-caja.png); }
.aviso-caja[data-icono="grafico"]::before { background-image: url(iconos/met-grafico.png); }
.aviso-caja[data-icono="canales"]::before { background-image: url(iconos/met-canales.png); }

.nota { color: var(--tinta-2); font-size: var(--t-rotulo); line-height: 1.6; }

/* Toast: barra sólida abajo. La transición va en `steps()` para que
   entre a saltos y no deslizándose — coherente con el resto. */
.aviso {
  position: fixed; bottom: var(--e5); left: 50%;
  transform: translate(-50%, 7.5rem);
  display: flex; align-items: center; gap: var(--e3);
  background: var(--negro); color: var(--crema);
  border: var(--b-est) solid var(--verde);
  border-radius: var(--r);
  padding: var(--e2) var(--e4);
  font-family: var(--interfaz); font-size: var(--t-tabla);
  z-index: 50; max-width: 90vw;
  transition: transform 140ms steps(4, end);
}
.aviso.ver { transform: translate(-50%, 0); }
.aviso.malo { border-color: var(--rojo); }
/* El "Deshacer" del toast. Apple pide perdón para los resbalones:
   no un diálogo antes —que se aprende a clickear sin leer— sino una
   salida después. */
.aviso .btn { min-height: 2rem; padding: var(--e1) var(--e3); font-size: var(--t-rotulo); }

/* ── Buscador ────────────────────────────────────────────────────── */
.buscador {
  width: 100%; padding: var(--e2) var(--e3); margin: 0 0 var(--e3);
  min-height: var(--tactil);
  background: var(--blanco); color: var(--tinta);
  border: var(--b-est) solid var(--negro); border-radius: var(--r);
  font-family: var(--dato); font-size: var(--t-cuerpo);
}
.buscador::placeholder { color: var(--gris-marcador); }
.buscador:focus { outline: none; border-color: var(--verde); }

/* La fila de herramientas de una tabla: buscador a la izquierda, lo que
   la acompaña a la derecha, y las dos cosas alineadas por su base. */
.herramientas {
  display: flex; gap: var(--e2); align-items: center; flex-wrap: wrap;
  margin-bottom: var(--e3);
}
.herramientas .buscador { flex: 1 1 16rem; margin: 0; }

/* ── Paginación ──────────────────────────────────────────────────── */
.paginas {
  display: flex; align-items: center; gap: var(--e2); flex-wrap: wrap;
  margin: var(--e3) 0 var(--e5);
}
.paginas .cuenta {
  font-family: var(--interfaz); font-size: var(--t-micro); font-weight: 600;
  letter-spacing: var(--tr-micro); text-transform: uppercase;
  color: var(--tinta-2); margin-left: auto;
}

/* ── Config ──────────────────────────────────────────────────────── */
/* Config es un formulario, no un tablero: estirado a 1.200 px el campo
   queda perdido a la izquierda con medio metro de crema al lado. Se
   acota al ancho en que la ayuda de cada valor todavía se lee de
   corrido. */
.conf {
  max-width: 46rem;
  background: var(--crema);
  border: var(--b-est) solid var(--negro);
  border-radius: var(--r);
  padding: var(--e3) var(--e4); margin-bottom: var(--e3);
}
.conf b { display: block; font-size: var(--t-tabla); }
.conf .nota { margin: var(--e1) 0 var(--e3); }
.conf-fila { display: flex; gap: var(--e2); align-items: center; flex-wrap: wrap; }
.conf-fila .buscador { margin: 0; max-width: 17rem; }

/* ── Gráficos y tabs de período ──────────────────────────────────── */
.graf {
  background: var(--crema);
  border: var(--b-est) solid var(--negro);
  border-radius: var(--r);
  padding: var(--e3) var(--e4) var(--e2);
}
/* Texto dentro del SVG. Va acá y no en atributos del propio SVG para
   que herede los tokens y las tipografías como todo lo demás. */
.graf-cifra {
  font-family: var(--dato); font-size: 15px; fill: var(--tinta);
}
.graf-eje {
  font-family: var(--interfaz); font-weight: 600; font-size: 9px; fill: var(--tinta-2);
}

.graf-leyenda {
  display: flex; gap: var(--e4); flex-wrap: wrap; margin: 0 0 var(--e3);
  font-family: var(--interfaz); font-size: var(--t-micro); font-weight: 600;
  letter-spacing: var(--tr-micro); text-transform: uppercase;
  color: var(--tinta-2);
}
.graf-leyenda i {
  display: inline-block; width: 0.6875rem; height: 0.6875rem; margin-right: var(--e1);
  border: var(--b-int) solid var(--negro); vertical-align: -1px;
}

/* ── Dona ────────────────────────────────────────────────────────── */
.dona-caja { display: flex; gap: var(--e5); align-items: center; flex-wrap: wrap; }
.dona-svg { width: 11.875rem; height: 11.875rem; flex: 0 0 auto; }
.dona-leyenda {
  list-style: none; margin: 0; padding: 0;
  flex: 1 1 15rem; min-width: 15rem;
}
.dona-leyenda li {
  display: grid; grid-template-columns: 1rem 1fr auto auto;
  align-items: center; gap: var(--e3);
  padding: var(--e1) 0; border-bottom: var(--b-int) solid var(--crema-3);
}
.dona-leyenda li:last-child { border-bottom: 0; }
.dona-color {
  width: 0.8125rem; height: 0.8125rem; border: var(--b-int) solid var(--negro);
}
.dona-nom { text-transform: capitalize; }
.dona-pct { color: var(--tinta-2); font-size: var(--t-tabla); min-width: 3.5rem; }

/* ── Barras horizontales ─────────────────────────────────────────── */
.barrash {
  list-style: none; margin: 0; padding: var(--e3) var(--e4);
  background: var(--crema); border: var(--b-est) solid var(--negro); border-radius: var(--r);
}
.barrash li {
  display: grid; grid-template-columns: minmax(5.5rem, 10rem) 1fr auto auto;
  align-items: center; gap: var(--e3); padding: var(--e1) 0;
}
.barrash-nom { text-transform: capitalize; }
.barrash-pista {
  height: 0.9375rem; background: var(--crema-2);
  border: var(--b-int) solid var(--negro); display: block;
}
/* Sin transición y sin esquinas: la barra es un bloque, como todo acá. */
.barrash-pista i { display: block; height: 100%; background: var(--verde); }
.barrash-pct { color: var(--tinta-2); font-size: var(--t-tabla); min-width: 3.5rem; }

.graf-pie {
  display: flex; justify-content: space-between; gap: var(--e3);
  font-family: var(--interfaz); font-size: var(--t-micro); font-weight: 600;
  letter-spacing: var(--tr-micro);
  color: var(--tinta-2); margin-top: var(--e1);
}

/* Las tabs de período del mockup: recuadros con relieve, el activo en
   verde lleno. Son CONTROLES, así que llevan esquina de 8 px, sombra de
   nivel 2 y se hunden — lo contrario de las pills. */
.chips { display: flex; gap: var(--e2); flex-wrap: wrap; margin: 0 0 var(--e4); }
.chip {
  padding: var(--e2) var(--e4);
  min-height: var(--tactil);
  background: var(--crema);
  border: var(--b-est) solid var(--negro);
  border-radius: var(--r);
  box-shadow: var(--elev-1);
  cursor: pointer;
  font-family: var(--interfaz); font-size: var(--t-tabla);
  color: var(--tinta);
}
.chip:hover { background: var(--blanco); border-color: var(--verde); }
.chip:active { transform: translate(var(--b-est), var(--b-est)); box-shadow: none; }
.chip.on {
  background: linear-gradient(180deg, var(--verde-vivo) 0%, var(--verde) 100%);
  color: var(--negro); font-weight: 700;
  box-shadow: var(--elev-2);
}

/* Cartel del modo local (SIN_CLAVES=1). Lo agrega el JS solo cuando el
   servidor dice que se entró sin clave, así que en producción no existe.
   No intercepta clics: es un aviso, no un elemento de la interfaz. */
#cartel-local {
  position: fixed; bottom: var(--e3); right: var(--e3); z-index: 90;
  padding: var(--e1) var(--e3);
  background: var(--ambar); color: var(--negro);
  border: var(--b-int) solid var(--negro);
  border-radius: var(--r);
  font-family: var(--interfaz); font-size: var(--t-micro); font-weight: 600;
  letter-spacing: var(--tr-micro);
  text-transform: uppercase;
  pointer-events: none;
}

/* ── Modo demo ───────────────────────────────────────────────────────
   Una franja que no se puede confundir con la plataforma real. Es lo
   único de toda la interfaz que usa el ámbar como fondo de un bloque
   ancho, a propósito: mostrar datos inventados creyendo que son reales
   es el error caro de esta pantalla. */
.demo-cartel {
  display: flex; align-items: center; gap: var(--e3);
  background: var(--relleno-ambar);
  border: var(--b-est) solid var(--negro);
  border-left-width: var(--e2); border-left-color: var(--ambar);
  border-radius: var(--r);
  padding: var(--e3) var(--e4);
  margin-bottom: var(--e4);
}
.demo-cartel::before {
  content: ""; flex: 0 0 auto;
  width: 3.25rem; height: 3.25rem;
  background: center / contain no-repeat url(iconos/modo-demo.png);
}
.demo-cartel b { display: block; font-size: var(--t-tabla); }
.demo-cartel .nota { margin: 0; color: var(--tinta-ambar); }
.demo-cartel .btn { margin-left: auto; }

/* ── Celular ─────────────────────────────────────────────────────── */
@media (max-width: 53.75rem) {
  body { padding: var(--e2); }
  .app { grid-template-columns: 1fr; padding: var(--e2); gap: var(--e2); }
  aside {
    position: fixed; inset: var(--e3) auto var(--e3) var(--e3);
    width: 15.75rem; z-index: 20;
    background: var(--negro);
    transform: translateX(-120%);
    transition: transform 160ms steps(5, end);
    box-shadow: var(--e2) 0 0 rgba(0, 0, 0, .35);
  }
  body.menu-abierto aside { transform: none; }
  .icono { display: block; }
  .barra { padding: var(--e2) var(--e3); gap: var(--e2); }
  #titulo { font-size: 1.3125rem; }
  #icono-pagina { width: 1.875rem; height: 1.875rem; }
  .cuerpo { padding: var(--e4) var(--e3) var(--e6); }
  .gente { grid-template-columns: 1fr; }
  .caja-entrada { padding: var(--e5) var(--e4); }
  .caja-entrada::before { width: 3.25rem; height: 3.25rem; top: calc(-1 * var(--e4)); right: 0; }
  .tarjetas { grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); }
  /* La ilustración se come el alto útil del cajón en una pantalla chica,
     donde lo que importa es llegar al módulo. */
  .ilustracion { display: none; }
  .demo-cartel { flex-wrap: wrap; }
  .demo-cartel .btn { margin-left: 0; }
}

/* Quien pidió más contraste en su sistema operativo está diciendo que le
   cuesta leer. Acá eso importa más que en otras interfaces, porque la
   tipografía de mapa de bits a 9 px ya está en el límite: los rótulos
   suben de tamaño, los grises intermedios se van a tinta plena y los
   bordes se marcan. */
@media (prefers-contrast: more) {
  :root {
    --tinta-2: #2E3A35;
    --crema-3: #B9B0A0;
    --verde-tabla: #3D6300;
    --t-micro: 0.6875rem;
  }
  .graf-eje { fill: var(--tinta); font-size: 11px; }
  thead th { font-size: 0.625rem; }
  .op { color: var(--blanco); }
}

/* Quien pidió menos movimiento no pidió menos respuesta: el botón sigue
   cambiando de color al presionarlo, lo que se apaga es el
   desplazamiento. En pixel art no hay animaciones ambientales, así que
   acá solo queda apagar los pocos movimientos de interacción. */
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
  .btn:active, .chip:active, .persona:active, .tarjeta.accionable:active { transform: none; }
}
