/*
 * Dr Ahorro · Back office — sistema de diseño.
 *
 * Una consola de operaciones, no una app de usuario: se mira muchas horas, se
 * compara mucho número y se decide rápido. El diseño se ordena alrededor de eso.
 *
 * ## Tres reglas que explican casi todo lo de abajo
 *
 * **1. Tokens con nombre de ROL, no de color.** `--sup-1` es "la superficie de
 * una tarjeta", no "gris oscuro". Por eso el tema claro son veinte líneas y no
 * una segunda hoja entera: cambia lo que el rol vale, no dónde se usa.
 *
 * **2. Una escala, no números sueltos.** Espaciados en múltiplos de 4 y tipografía
 * en una escala fija. Cuando cada margen se elige a ojo, dos pantallas hechas con
 * un mes de diferencia no se parecen, y la consola se siente hecha de pedazos.
 *
 * **3. Sin dependencias externas.** Ni fuentes de Google, ni librerías de íconos,
 * ni CSS de un CDN. El resto de `apps/web` se sirve tal cual desde el VPS y esta
 * consola también: una fuente remota le agrega al login un tercero que puede
 * estar caído, ser lento o registrar quién entra. Los íconos son emoji del
 * sistema y la tipografía es la del sistema operativo, que además es la que la
 * persona ya lee más rápido.
 */

/* ══════════════════════════════════════════════════════════════════════════
   1. Tokens
   ══════════════════════════════════════════════════════════════════════════ */

:root {
  /* ── Superficies. Cuanto más alto el número, más "cerca" está del ojo. ── */
  --sup-0: #0a0e1a;   /* fondo de página */
  --sup-1: #111726;   /* tarjetas, barra lateral */
  --sup-2: #182033;   /* estados hover, campos */
  --sup-3: #1e2740;   /* menús */

  /* ── Texto, en tres pesos de presencia ── */
  --txt: #e9edf7;     /* lo que se lee */
  --txt-2: #a3aec7;   /* etiquetas, apoyo */
  /* 5.08:1 sobre tarjeta. El valor anterior (#6d789a) daba 4.09 y no llegaba
     al mínimo AA de 4.5 — y encima este color se usa en texto de 11 px, que
     necesita MÁS contraste, no menos. Medido, no elegido a ojo. */
  --txt-3: #7c88ab;   /* metadatos, "hace 2 h" */

  --linea: #232c45;
  --linea-fuerte: #33405f;

  /* ── Acento ── */
  --acento: #5b93ff;
  --acento-vivo: #7aa8ff;
  --acento-suave: rgba(91, 147, 255, .14);
  --sobre-acento: #06122b;

  /* ── Semánticos. Cada uno con su fondo suave, para no calcularlo inline ── */
  --ok: #3ddc8a;
  --ok-suave: rgba(61, 220, 138, .13);
  --warn: #f7c15a;
  --warn-suave: rgba(247, 193, 90, .13);
  --error: #ff7b7b;
  --error-suave: rgba(255, 123, 123, .13);

  /* ── Espaciado: todo múltiplo de 4 ── */
  --e1: 4px;  --e2: 8px;  --e3: 12px; --e4: 16px;
  --e5: 24px; --e6: 32px; --e7: 48px; --e8: 64px;

  /* ── Tipografía ── */
  --fuente: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  /* Para ids y para números que se comparan en columna. */
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  --t-xs: 11px; --t-s: 12px; --t-m: 13px; --t-base: 14px;
  --t-l: 16px;  --t-xl: 20px; --t-2xl: 26px; --t-3xl: 34px;

  --r1: 6px; --r2: 10px; --r3: 14px; --r-full: 999px;

  --sombra-1: 0 1px 2px rgba(0, 0, 0, .3);
  --sombra-2: 0 6px 20px -8px rgba(0, 0, 0, .55);
  --sombra-3: 0 24px 60px -20px rgba(0, 0, 0, .7);

  --transicion: 140ms cubic-bezier(.4, 0, .2, 1);

  color-scheme: dark;
}

/*
 * Tema claro.
 *
 * No es "el oscuro dado vuelta": las superficies claras necesitan MENOS
 * contraste entre niveles y MÁS peso en los bordes, porque sin sombra fuerte
 * una tarjeta blanca sobre fondo blanco no se despega. Por eso `--linea` sube
 * de presencia acá y las sombras se ablandan.
 */
:root[data-tema="claro"] {
  --sup-0: #f6f7fb;
  --sup-1: #ffffff;
  --sup-2: #eef1f8;
  --sup-3: #ffffff;

  --txt: #131a2b;
  --txt-2: #4d5875;
  --txt-3: #666f8a;   /* 4.99:1 sobre blanco; el anterior daba 3.83 */

  --linea: #dde2ee;
  --linea-fuerte: #c3cbdf;

  --acento: #2f6bde;
  --acento-vivo: #1d55c4;
  --acento-suave: rgba(47, 107, 222, .1);
  --sobre-acento: #ffffff;

  --ok: #12874f;
  --ok-suave: rgba(18, 135, 79, .1);
  --warn: #8a5d09;
  --warn-suave: rgba(138, 93, 9, .12);
  --error: #c02b2b;
  --error-suave: rgba(192, 43, 43, .1);

  --sombra-1: 0 1px 2px rgba(16, 24, 40, .06);
  --sombra-2: 0 8px 24px -12px rgba(16, 24, 40, .18);
  --sombra-3: 0 24px 60px -24px rgba(16, 24, 40, .28);

  color-scheme: light;
}

/* ══════════════════════════════════════════════════════════════════════════
   2. Base
   ══════════════════════════════════════════════════════════════════════════ */

*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  background: var(--sup-0);
  color: var(--txt);
  font-family: var(--fuente);
  font-size: var(--t-base);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-synthesis: none;
}

/* Los números se comparan en columna todo el tiempo: sin ancho tabular,
   "40.984" y "1.215" no se alinean y hay que leerlos de a uno. */
b, strong, .num, .cnt, .badge, td, th, .cal-pct, .pct {
  font-variant-numeric: tabular-nums;
}

a { color: var(--acento); text-decoration: none; transition: color var(--transicion); }
a:hover { color: var(--acento-vivo); text-decoration: underline; }

code, kbd {
  font-family: var(--mono);
  font-size: .92em;
  background: var(--sup-2);
  border: 1px solid var(--linea);
  border-radius: var(--r1);
  padding: 1px 5px;
}

h1, h2, h3 { margin: 0; line-height: 1.25; letter-spacing: -.01em; }
h2 { font-size: var(--t-2xl); font-weight: 700; margin-bottom: var(--e2); }
h3 { font-size: var(--t-l); font-weight: 650; }

/*
 * El foco visible no es opcional acá: se navega mucho con teclado y el anillo
 * por defecto del navegador desaparece sobre fondo oscuro. `:focus-visible` y
 * no `:focus` para que no aparezca al hacer clic con el mouse.
 */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--acento);
  outline-offset: 2px;
  border-radius: var(--r1);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

#app.cargando { display: grid; place-items: center; min-height: 100dvh; color: var(--txt-3); }

/* ══════════════════════════════════════════════════════════════════════════
   3. Login
   ══════════════════════════════════════════════════════════════════════════ */

.login {
  display: grid;
  place-items: center;
  min-height: 100dvh;
  padding: var(--e4);
  /* Un degradado muy suave: da profundidad sin competir con la tarjeta. */
  background:
    radial-gradient(1200px 600px at 50% -10%, var(--acento-suave), transparent 70%),
    var(--sup-0);
}
.login-card {
  width: 100%;
  max-width: 380px;
  background: var(--sup-1);
  border: 1px solid var(--linea);
  border-radius: var(--r3);
  padding: var(--e6) var(--e5) var(--e5);
  box-shadow: var(--sombra-3);
}
.login-card h1 { font-size: var(--t-xl); font-weight: 700; margin-bottom: var(--e2); }
.login-card .sub { color: var(--txt-2); font-size: var(--t-m); margin: 0 0 var(--e5); }

/* ══════════════════════════════════════════════════════════════════════════
   4. Formularios
   ══════════════════════════════════════════════════════════════════════════ */

.campo { display: flex; flex-direction: column; gap: var(--e1); margin-bottom: var(--e3); }
.campo.crece { flex: 1; min-width: 180px; }
.campo label { font-size: var(--t-s); font-weight: 600; color: var(--txt-2); letter-spacing: .01em; }

input, select, textarea {
  width: 100%;
  padding: 9px 11px;
  background: var(--sup-2);
  border: 1px solid var(--linea);
  border-radius: var(--r2);
  color: var(--txt);
  font: inherit;
  font-size: var(--t-m);
  transition: border-color var(--transicion), box-shadow var(--transicion), background var(--transicion);
}
input::placeholder { color: var(--txt-3); }
input:hover, select:hover, textarea:hover { border-color: var(--linea-fuerte); }
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--acento);
  /* Halo en vez de outline: no desplaza nada y se ve igual en los dos temas. */
  box-shadow: 0 0 0 3px var(--acento-suave);
}
select {
  appearance: none;
  /* La flecha va como SVG en línea: traer una librería de íconos para un
     triangulito sería una dependencia entera por esto. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='none' stroke='%236d789a' stroke-width='1.6' d='M1 1.5 6 6.5l5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 11px center;
  background-size: 11px;
  padding-right: 32px;
}
input[type="checkbox"] { width: auto; accent-color: var(--acento); }

.par-campos { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--e3); }
.par-campos .ancho { grid-column: 1 / -1; }

/* ══════════════════════════════════════════════════════════════════════════
   5. Botones
   ══════════════════════════════════════════════════════════════════════════ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--e2);
  padding: 9px 16px;
  border: 1px solid transparent;
  border-radius: var(--r2);
  background: var(--acento);
  color: var(--sobre-acento);
  font: inherit;
  font-size: var(--t-m);
  font-weight: 650;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--transicion), border-color var(--transicion),
              transform var(--transicion), opacity var(--transicion);
}
.btn:hover { background: var(--acento-vivo); text-decoration: none; }
/* El hundido al presionar es lo que hace que un clic se sienta atendido cuando
   la respuesta del servidor tarda medio segundo. */
.btn:active { transform: translateY(1px); }
.btn[disabled] { opacity: .5; cursor: not-allowed; transform: none; }

.btn.secundario { background: var(--sup-2); color: var(--txt); border-color: var(--linea); }
.btn.secundario:hover { background: var(--sup-3); border-color: var(--linea-fuerte); }

.btn.peligro { background: transparent; color: var(--error); border-color: var(--error); }
.btn.peligro:hover { background: var(--error-suave); }

.btn.full { width: 100%; }
.btn.chico { padding: 6px 11px; font-size: var(--t-s); }

/* ══════════════════════════════════════════════════════════════════════════
   6. Estructura de la consola
   ══════════════════════════════════════════════════════════════════════════ */

.shell { display: grid; grid-template-columns: 248px 1fr; min-height: 100dvh; }

.side {
  background: var(--sup-1);
  border-right: 1px solid var(--linea);
  padding: var(--e5) var(--e3) var(--e4);
  display: flex;
  flex-direction: column;
  gap: var(--e1);
  /* Se queda a la vista aunque la tabla de al lado tenga 500 filas. */
  position: sticky;
  top: 0;
  height: 100dvh;
  overflow-y: auto;
}
.side .marca { font-weight: 800; font-size: var(--t-l); padding: 0 var(--e2) var(--e4); letter-spacing: -.01em; }
.side .marca small {
  display: block;
  font-weight: 500;
  font-size: var(--t-xs);
  color: var(--txt-3);
  letter-spacing: .06em;
  text-transform: uppercase;
  margin-top: 2px;
}

.nav-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--e3);
  padding: 9px var(--e3);
  border-radius: var(--r2);
  color: var(--txt-2);
  cursor: pointer;
  font-size: var(--t-m);
  font-weight: 550;
  border: 1px solid transparent;
  transition: background var(--transicion), color var(--transicion);
}
.nav-item:hover { background: var(--sup-2); color: var(--txt); text-decoration: none; }
.nav-item.activo { background: var(--acento-suave); color: var(--txt); font-weight: 650; }
/* Marca vertical del ítem activo: se reconoce antes de leer el texto. */
.nav-item.activo::before {
  content: "";
  position: absolute;
  left: 0; top: 50%;
  width: 3px; height: 18px;
  margin-top: -9px;
  border-radius: 0 var(--r1) var(--r1) 0;
  background: var(--acento);
}
.nav-item .ic { width: 18px; text-align: center; font-size: var(--t-l); line-height: 1; }

.nav-item .badge {
  margin-left: auto;
  font-size: var(--t-xs);
  font-weight: 700;
  color: var(--txt-3);
  background: var(--sup-0);
  border: 1px solid var(--linea);
  border-radius: var(--r-full);
  padding: 1px 7px;
}
/* Cero fuentes usables no se disimula: la categoría existe y no sirve. */
.nav-item .badge.cero { color: var(--warn); border-color: var(--warn); background: var(--warn-suave); }

.side .pie {
  margin-top: auto;
  padding: var(--e3) var(--e2) 0;
  border-top: 1px solid var(--linea);
  font-size: var(--t-s);
  color: var(--txt-3);
  display: flex;
  flex-direction: column;
  gap: var(--e2);
}
.side .pie .mail { color: var(--txt-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Cambiar de tema. Va en el pie porque se toca una vez y no se busca más. */
.tema {
  display: inline-flex;
  align-items: center;
  gap: var(--e2);
  padding: 5px var(--e2);
  background: transparent;
  border: 1px solid var(--linea);
  border-radius: var(--r2);
  color: var(--txt-3);
  font: inherit;
  font-size: var(--t-s);
  cursor: pointer;
  transition: background var(--transicion), color var(--transicion);
}
.tema:hover { background: var(--sup-2); color: var(--txt-2); }

/* `min-width: 0` no es cosmético: sin él, un ítem de grid arrastra el
   `min-width: auto` del CSS y **se niega a achicarse por debajo de su
   contenido**. Con la tabla de precios (nueve columnas) la columna del main se
   calculaba en 1.076px dentro de un hueco de 1.032, y el sobrante empujaba la
   página entera 44px a la derecha: el `overflow-x: auto` de la tabla no llegaba
   a actuar nunca porque el que desbordaba era el body. */
.main { padding: var(--e6) var(--e6) var(--e8); max-width: 1500px; min-width: 0; }
.desc { color: var(--txt-2); font-size: var(--t-m); margin: 0 0 var(--e4); max-width: 82ch; }

.seccion-titulo {
  margin: var(--e6) 0 var(--e3);
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--txt-3);
  padding-bottom: var(--e2);
  border-bottom: 1px solid var(--linea);
}

/* ── Selector de país ─────────────────────────────────────────────────── */
.paises {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e1);
  padding: 0 var(--e1) var(--e3);
  margin-bottom: var(--e2);
  border-bottom: 1px solid var(--linea);
  /* `start` y no el `stretch` de flex: si no, al colapsar a una columna los
     botones se estiran hasta el pie como pastillas verticales. */
  align-items: start;
}
.pais {
  flex: 1 0 44px;
  max-width: 25%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  padding: 6px 2px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r2);
  color: var(--txt-3);
  cursor: pointer;
  font: inherit;
  line-height: 1.1;
  transition: background var(--transicion), color var(--transicion), border-color var(--transicion);
}
.pais:hover { background: var(--sup-2); color: var(--txt-2); }
.pais.activo { background: var(--acento-suave); border-color: var(--acento); color: var(--txt); }
.pais .bandera { font-size: 18px; }
.pais .cod { font-size: 10px; font-weight: 700; letter-spacing: .06em; }

/* ══════════════════════════════════════════════════════════════════════════
   7. Tarjetas
   ══════════════════════════════════════════════════════════════════════════ */

.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: var(--e4); }

.card {
  background: var(--sup-1);
  border: 1px solid var(--linea);
  border-radius: var(--r3);
  padding: var(--e4);
  box-shadow: var(--sombra-1);
  transition: border-color var(--transicion), box-shadow var(--transicion), transform var(--transicion);
}
/* Sólo las clicables se levantan. Una tarjeta que se mueve sin serlo promete
   una interacción que no existe. */
.card[data-i]:hover, .card[data-pais]:hover {
  border-color: var(--linea-fuerte);
  box-shadow: var(--sombra-2);
  transform: translateY(-1px);
}
.card h3 { display: flex; align-items: center; gap: var(--e2); flex-wrap: wrap; }
.card .fuente { color: var(--txt-3); font-size: var(--t-s); margin: var(--e1) 0 var(--e4); }
.card.apagada { opacity: .68; }
.card.apagada:hover { opacity: 1; }

.num { font-size: var(--t-3xl); font-weight: 750; letter-spacing: -.02em; line-height: 1.1; margin-bottom: var(--e2); }
.num small { font-size: var(--t-m); font-weight: 500; color: var(--txt-3); letter-spacing: 0; }

.filas { margin: var(--e3) 0 0; font-size: var(--t-m); }
.fila { display: flex; justify-content: space-between; gap: var(--e4); padding: 5px 0; color: var(--txt-2); }
/* Línea sutil entre filas: ayuda a seguir la vista de la etiqueta al valor
   cuando la tarjeta es ancha. */
.filas .fila + .fila { border-top: 1px solid var(--linea); }
.fila b { color: var(--txt); font-weight: 650; text-align: right; font-variant-numeric: tabular-nums; }

/* ══════════════════════════════════════════════════════════════════════════
   8. Chips, avisos y vacíos
   ══════════════════════════════════════════════════════════════════════════ */

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--e1);
  font-size: var(--t-xs);
  font-weight: 650;
  padding: 3px 9px;
  border-radius: var(--r-full);
  border: 1px solid transparent;
  white-space: nowrap;
}
.chip.fresco { background: var(--ok-suave); color: var(--ok); border-color: color-mix(in srgb, var(--ok) 30%, transparent); }
.chip.viejo  { background: var(--warn-suave); color: var(--warn); border-color: color-mix(in srgb, var(--warn) 30%, transparent); }
.chip.rancio { background: var(--error-suave); color: var(--error); border-color: color-mix(in srgb, var(--error) 30%, transparent); }
.chip.neutro { background: var(--sup-2); color: var(--txt-2); border-color: var(--linea); }

.aviso {
  border-radius: var(--r2);
  padding: var(--e3) var(--e4);
  font-size: var(--t-m);
  margin: var(--e3) 0;
  border: 1px solid;
  /* La barra a la izquierda hace que el tipo de aviso se reconozca antes de
     leerlo. */
  border-left-width: 3px;
}
.aviso.ok     { background: var(--ok-suave); color: var(--ok); border-color: color-mix(in srgb, var(--ok) 30%, transparent); border-left-color: var(--ok); }
.aviso.warn   { background: var(--warn-suave); color: var(--warn); border-color: color-mix(in srgb, var(--warn) 30%, transparent); border-left-color: var(--warn); }
.aviso.error  { background: var(--error-suave); color: var(--error); border-color: color-mix(in srgb, var(--error) 30%, transparent); border-left-color: var(--error); }
.aviso.neutro { background: var(--sup-2); color: var(--txt-2); border-color: var(--linea); border-left-color: var(--linea-fuerte); }
.aviso code { background: color-mix(in srgb, currentColor 12%, transparent); border-color: transparent; }

.vacio {
  padding: var(--e6) var(--e4);
  text-align: center;
  color: var(--txt-3);
  font-size: var(--t-m);
  background: var(--sup-1);
  border: 1px dashed var(--linea-fuerte);
  border-radius: var(--r3);
}

/* ══════════════════════════════════════════════════════════════════════════
   9. Esqueletos de carga
   ══════════════════════════════════════════════════════════════════════════

   Antes acá había un solo `.spinner`: un rectángulo gris de 78 px con brillo,
   igual para una tabla de seis columnas que para tres tarjetas. Ocupaba lugar,
   sí, pero NO el lugar que iba a ocupar el contenido, así que la pantalla
   saltaba lo mismo cuando llegaban los datos — y encima con la espera de por
   medio, que es lo que hace que el salto se note.

   El esqueleto sirve cuando tiene la FORMA de lo que viene. Por eso acá no hay
   un componente "esqueleto" sino piezas que se montan sobre el mismo markup
   que el contenido real: `.tabla`, `.grid`+`.card`, `.filas`. Lo único propio
   es `.sk-b`, la barra gris que reemplaza a un texto que todavía no está. Si
   mañana cambia el padding de `.tabla th`, el esqueleto cambia con ella sin que
   nadie se acuerde de venir hasta acá.

   El gris sale de `--sup-2` y no de un `#eee` fijo: en tema oscuro un `#eee`
   sería un cartel blanco sobre fondo negro, que es exactamente lo contrario de
   "esto todavía no está". */

/* El contenedor lleva `aria-busy="true"` y un texto para lector de pantalla
   (`.sk-sr`): un div gris no le dice nada a quien no lo ve, y "no dice nada" se
   confunde con "no hay datos". */
.sk-sr {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* La barra. El brillo se mueve con `background-position` y no con un
   pseudo-elemento desplazado: así una barra dentro de una celda de tabla no
   necesita `overflow:hidden` en la celda para que el brillo no se escape. */
.sk-b {
  display: block;
  height: 12px;
  width: 100%;
  border-radius: var(--r1);
  background:
    linear-gradient(90deg,
      var(--sup-2) 0%,
      color-mix(in srgb, var(--txt-3) 20%, var(--sup-2)) 50%,
      var(--sup-2) 100%);
  background-size: 220% 100%;
  animation: sk-brillo 1.5s linear infinite;
}
@keyframes sk-brillo { from { background-position: 120% 0; } to { background-position: -120% 0; } }

/* Un esqueleto es una espera, y una espera que late puede ser un problema real
   para quien tiene sensibilidad al movimiento. Sin animación sigue haciendo su
   trabajo —la forma ya está— así que se apaga entera, no se ralentiza. */
@media (prefers-reduced-motion: reduce) {
  .sk-b { animation: none; }
}

/* Alto y ancho de la barra según qué texto reemplaza. Los anchos son impares a
   propósito: cuatro barras del mismo largo se leen como una grilla de un juego,
   no como texto que está por llegar. */
.sk-b.alto  { height: 26px; }
.sk-b.bajo  { height: 10px; }
.sk-b.w30   { width: 30%; }
.sk-b.w45   { width: 45%; }
.sk-b.w60   { width: 60%; }
.sk-b.w75   { width: 75%; }
.sk-b.w90   { width: 90%; }

/* Bloque de texto: párrafos. El margen entre líneas es el interlineado real
   (1.5 sobre 13 px ≈ 20 px), para que tres líneas de esqueleto midan lo mismo
   que tres líneas de texto. */
.sk-texto .sk-b { margin-bottom: 8px; }
.sk-texto .sk-b:last-child { margin-bottom: 0; }

/* Fila de métricas: los números grandes de un panel, con su etiqueta abajo. */
.sk-metricas { display: flex; gap: var(--e5); flex-wrap: wrap; margin: var(--e4) 0 var(--e5); }
.sk-metricas > div { display: flex; flex-direction: column; gap: var(--e2); min-width: 96px; }

/* En la tabla la celda manda el alto; la barra sólo pinta adentro. */
.tabla td .sk-b { max-width: 100%; }

/* Un chip de cadena del esqueleto ocupa el mismo lugar que uno real, pero no se
   puede tocar: sin esto se ilumina al pasar el mouse y promete un clic que no
   existe. */
.sk .cadena { cursor: default; }
.sk .cadena:hover { border-color: var(--linea); background: var(--sup-1); transform: none; }

/* Lo mismo con las casillas del calendario de descuentos. */
.cal-dia.sk { cursor: default; }
.cal-dia.sk:hover { border-color: var(--linea); transform: none; }

/* El aviso de "se mostró lo guardado porque no pudimos actualizar".
 *
 * Flota abajo a la derecha y se va solo. Va así, y no como un cartel arriba de
 * la sección, porque el dato QUE SE ESTÁ VIENDO sigue siendo bueno: es de hace
 * un rato, no está mal. Un cartel rojo empujando la tabla hacia abajo por un
 * corte de red de dos segundos asusta más de lo que informa; y borrar lo que ya
 * estaba en pantalla sería tirar información buena por una falla de transporte.
 *
 * Distinto es `#avisoFrescura`, que sí grita: ese avisa que el DATO está viejo
 * en el servidor, no que nuestro pedido no llegó. */
.no-refresco {
  position: fixed;
  right: var(--e4);
  bottom: var(--e4);
  z-index: 900;
  max-width: 300px;
  padding: var(--e3) var(--e4);
  border-radius: var(--r2);
  background: var(--sup-3);
  border: 1px solid var(--linea-fuerte);
  box-shadow: var(--sombra-2);
  color: var(--txt-2);
  font-size: var(--t-s);
  line-height: 1.45;
  animation: no-refresco-entra 180ms ease-out;
}
.no-refresco b { color: var(--txt); font-weight: 700; }
@keyframes no-refresco-entra { from { opacity: 0; transform: translateY(6px); } }
@media (prefers-reduced-motion: reduce) { .no-refresco { animation: none; } }

/* ══════════════════════════════════════════════════════════════════════════
   10. Tablas
   ══════════════════════════════════════════════════════════════════════════ */

.tabla {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--t-m);
  background: var(--sup-1);
  border: 1px solid var(--linea);
  border-radius: var(--r3);
  overflow: hidden;
}
.tabla th {
  text-align: left;
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--txt-3);
  padding: var(--e3) var(--e4);
  background: var(--sup-2);
  border-bottom: 1px solid var(--linea);
  /* El encabezado queda a la vista al scrollear una tabla larga: sin esto, a la
     fila 40 ya nadie sabe qué columna está mirando. */
  position: sticky;
  top: 0;
  z-index: 2;
}
.tabla td { padding: var(--e3) var(--e4); border-bottom: 1px solid var(--linea); vertical-align: top; }
.tabla tbody tr:last-child td { border-bottom: none; }
.tabla tbody tr { transition: background var(--transicion); }
.tabla tbody tr:hover { background: var(--sup-2); }
.tabla .acc { text-align: right; white-space: nowrap; }

.marca-tag {
  display: inline-block;
  font-size: var(--t-xs);
  font-weight: 650;
  color: var(--txt-2);
  background: var(--sup-2);
  border: 1px solid var(--linea);
  border-radius: var(--r1);
  padding: 1px 6px;
  margin-left: var(--e1);
}

.barra { display: flex; flex-wrap: wrap; gap: var(--e3); align-items: flex-end; margin-bottom: var(--e4); }
.barra .campo { margin-bottom: 0; }

/* ══════════════════════════════════════════════════════════════════════════
   11. Cadenas
   ══════════════════════════════════════════════════════════════════════════
   El nivel intermedio entre "categoría" y "un punto suelto": nadie piensa en
   5.117 estaciones, piensa en YPF. */
.cadenas { display: flex; flex-wrap: wrap; gap: var(--e2); margin-bottom: var(--e2); }
.cadena {
  display: inline-flex;
  align-items: center;
  gap: var(--e3);
  padding: 8px var(--e3);
  background: var(--sup-1);
  border: 1px solid var(--linea);
  border-radius: var(--r2);
  color: var(--txt);
  font: inherit;
  font-size: var(--t-m);
  font-weight: 550;
  cursor: pointer;
  transition: border-color var(--transicion), background var(--transicion), transform var(--transicion);
}
.cadena:hover { border-color: var(--acento); background: var(--sup-2); transform: translateY(-1px); }
.cadena .nom { font-weight: 600; }
.cadena .cnt {
  font-size: var(--t-xs);
  font-weight: 700;
  color: var(--txt-3);
  background: var(--sup-0);
  border-radius: var(--r-full);
  padding: 1px 8px;
}
/* Un punto al lado del nombre: de esta cadena no tenemos precios. Va como
   marca discreta y no como color del botón entero porque no es un error —es
   información— y teñir la mitad de la tira de rojo la vuelve ilegible. */
.cadena .sin-precios {
  color: var(--warn);
  font-weight: 900;
  margin-left: 4px;
  cursor: help;
}
.cadena .chip { padding: 0 6px; font-size: 10px; }

/* Lo que la fuente oficial mete en esta sección sin ser de este rubro.
   Plegado, no borrado: que el padrón traiga 339 puntos que no corresponden es
   justo el dato que hace falta para reclamarlo en el origen. */
.otro-rubro {
  border: 1px solid var(--linea);
  border-radius: var(--r2);
  padding: var(--e3);
  margin-bottom: var(--e2);
  background: var(--sup-0);
}
.otro-rubro > summary {
  cursor: pointer;
  font-size: var(--t-s);
  font-weight: 600;
  color: var(--txt-2);
  list-style-position: inside;
}
.otro-rubro > summary:hover { color: var(--txt); }
.otro-rubro[open] > summary { margin-bottom: var(--e3); }
.otro-rubro .desc { margin-top: 0; }

/* ══════════════════════════════════════════════════════════════════════════
   12. Panel de detalle
   ══════════════════════════════════════════════════════════════════════════ */

.overlay {
  position: fixed;
  inset: 0;
  background: rgba(4, 7, 15, .62);
  backdrop-filter: blur(3px);
  display: flex;
  justify-content: flex-end;
  z-index: 50;
  animation: aparecer 160ms ease-out;
}
@keyframes aparecer { from { opacity: 0; } }

.drawer {
  width: min(620px, 100%);
  background: var(--sup-1);
  border-left: 1px solid var(--linea);
  padding: var(--e5);
  overflow-y: auto;
  box-shadow: var(--sombra-3);
  animation: entrar 200ms cubic-bezier(.2, .8, .2, 1);
}
@keyframes entrar { from { transform: translateX(24px); opacity: .4; } }

.drawer .head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--e3); margin-bottom: var(--e2); }
.drawer .head h3 { font-size: var(--t-xl); font-weight: 700; }
.cerrar {
  flex: 0 0 auto;
  width: 32px; height: 32px;
  display: grid; place-items: center;
  background: transparent;
  border: 1px solid var(--linea);
  border-radius: var(--r2);
  color: var(--txt-2);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  transition: background var(--transicion), color var(--transicion);
}
.cerrar:hover { background: var(--sup-2); color: var(--txt); }

.drawer .id {
  font-family: var(--mono);
  font-size: var(--t-s);
  color: var(--txt-3);
  word-break: break-all;
  margin-bottom: var(--e4);
}

.mapa-link {
  display: flex;
  gap: var(--e3);
  padding: var(--e3) var(--e4);
  background: var(--sup-2);
  border: 1px solid var(--linea);
  border-radius: var(--r2);
  margin-bottom: var(--e3);
  font-size: var(--t-m);
}
.mapa-link .coord { color: var(--txt-3); font-family: var(--mono); font-size: var(--t-s); margin: 2px 0 var(--e2); }

.kv { display: grid; grid-template-columns: minmax(90px, auto) 1fr; gap: var(--e2) var(--e4); margin: var(--e3) 0; font-size: var(--t-m); }
.kv dt { color: var(--txt-3); }
.kv dd { margin: 0; color: var(--txt); }

.solo-lectura { font-size: var(--t-s); color: var(--txt-3); padding: var(--e2) 0; }

.enlaces { display: flex; flex-wrap: wrap; gap: var(--e2) var(--e4); margin-top: var(--e3); font-size: var(--t-m); }
.notas { margin: var(--e2) 0 0; padding-left: var(--e5); color: var(--txt-2); font-size: var(--t-m); }
.notas li { margin-bottom: var(--e1); }

.mensaje:empty { display: none; }

/* ── Historial de cambios ─────────────────────────────────────────────── */
.hist { display: flex; flex-direction: column; gap: var(--e2); }
.hist .item { background: var(--sup-2); border: 1px solid var(--linea); border-radius: var(--r2); padding: var(--e3); font-size: var(--t-s); }
.hist .cuando { color: var(--txt-3); }
.hist .quien { color: var(--txt-2); font-weight: 600; margin: 2px 0 var(--e1); }
.hist .cambio { font-family: var(--mono); font-size: var(--t-xs); margin-top: 2px; }
.hist .cambio .k { color: var(--txt-3); }
.hist .antes { color: var(--error); text-decoration: line-through; }
.hist .despues { color: var(--ok); }

/* ══════════════════════════════════════════════════════════════════════════
   13. Calendario de descuentos
   ══════════════════════════════════════════════════════════════════════════
   Siete columnas arrancando en lunes. La intensidad del fondo sale del mejor
   porcentaje del día (`--fuerza`, 0 a 1): el mes se lee de un golpe en vez de
   fila por fila. */
.cal { display: grid; grid-template-columns: repeat(7, 1fr); gap: var(--e2); margin: var(--e4) 0 var(--e2); }
.cal-cab {
  text-align: center;
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--txt-3);
  padding-bottom: var(--e1);
}
.cal-hueco { min-height: 1px; }
.cal-dia {
  min-height: 84px;
  padding: var(--e2) var(--e3);
  border: 1px solid var(--linea);
  border-radius: var(--r2);
  background:
    linear-gradient(color-mix(in srgb, var(--acento) calc(var(--fuerza, 0) * 24%), transparent),
                    color-mix(in srgb, var(--acento) calc(var(--fuerza, 0) * 24%), transparent)),
    var(--sup-1);
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 1px;
  transition: border-color var(--transicion), transform var(--transicion);
}
.cal-dia:hover { border-color: var(--acento); transform: translateY(-1px); }
.cal-dia.vacio { cursor: default; opacity: .45; background: var(--sup-1); border-style: dashed; padding: var(--e2) var(--e3); text-align: left; }
.cal-dia.vacio:hover { border-color: var(--linea); transform: none; }
.cal-num { font-size: var(--t-s); font-weight: 700; color: var(--txt-2); }
.cal-pct { font-size: var(--t-xl); font-weight: 750; line-height: 1.1; margin-top: auto; letter-spacing: -.02em; }
.cal-n { font-size: var(--t-xs); color: var(--txt-3); }

.pct { color: var(--ok); font-size: var(--t-base); font-weight: 700; }

/* ══════════════════════════════════════════════════════════════════════════
   13bis. Análisis de precios
   ══════════════════════════════════════════════════════════════════════════
   Una tabla de producto × cadena. La densidad acá es una virtud: la pregunta
   es "¿cuánto sale esto en cada una?" y se contesta con la vista, no leyendo
   fila por fila. Por eso el precio más barato se destaca en verde y el que
   está muy por encima del promedio en ámbar: el ojo encuentra el patrón antes
   que la cabeza lea los números. */

/* La tabla es más ancha que la pantalla en cuanto hay seis cadenas. Que scrollee
   ELLA y no la página: el scroll horizontal del body rompe toda la consola. */
.tabla-scroll { overflow-x: auto; border-radius: var(--r2); }

.tabla.precios { min-width: 720px; }
.tabla.precios tbody tr { cursor: pointer; }
.tabla.precios .p-cad { text-align: right; text-transform: capitalize; }
.tabla.precios .p-nombre { min-width: 260px; }
.p-meta { color: var(--txt-3); font-size: var(--t-xs); margin-top: 3px; }
.p-meta .chip { margin-left: 6px; }

.p-precio { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.p-vacia { text-align: right; color: var(--txt-3); }
/* Verde = acá conviene comprarlo. Ámbar = más de 15% arriba del promedio. */
.p-min { color: var(--ok); font-weight: 700; }
.p-alto { color: var(--warn); }
.p-gana { font-weight: 750; }
.p-lista { display: block; font-size: var(--t-xs); color: var(--txt-3); font-weight: 400; text-decoration: line-through; }
/* Los descuentos, en su propia columna. Antes eran un `%` suelto pegado al
   precio y "$390 %" se leía como si el precio fuera una tasa. En una columna
   de plata va plata; lo que es un porcentaje va donde dice que lo es. */
.p-promos { text-align: right; white-space: normal; line-height: 1.9; }
.p-promos .chip { margin-left: 3px; }

/* Ficha del producto */
.p-ficha-cab { display: flex; gap: var(--e3); align-items: flex-start; margin-bottom: var(--e2); }
.p-img { width: 84px; height: 84px; object-fit: contain; background: var(--sup-2); border-radius: var(--r2); flex: none; }
.p-grande { font-size: var(--t-xl); font-weight: 700; letter-spacing: -.01em; margin-top: 4px; }
.p-grande small { font-size: var(--t-m); font-weight: 400; color: var(--txt-3); }
.p-comparar { display: flex; flex-wrap: wrap; gap: var(--e3); }

/* Gráfico de historial. SVG a mano, sin ninguna librería: son cuatro líneas y
   traer una dependencia de 60 kB para dibujarlas no se paga. */
.p-grafico { background: var(--sup-0); border: 1px solid var(--linea); border-radius: var(--r2); padding: var(--e3); }
.p-svg { width: 100%; height: auto; display: block; }
.p-eje { stroke: var(--linea); stroke-width: 1; }
.p-tick { fill: var(--txt-3); font-size: 10px; font-family: inherit; }
.p-linea { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.p-leyenda { display: flex; flex-wrap: wrap; gap: var(--e3); margin-top: var(--e3); font-size: var(--t-s); }
.p-leg { display: inline-flex; align-items: center; gap: 5px; color: var(--txt-2); }
.p-leg::before { content: ''; width: 12px; height: 3px; border-radius: 2px; background: currentColor; }
.p-leg small { color: var(--txt-3); }

/* Una paleta de seis, que es el máximo de cadenas que puede tener un producto.
   Se repite con módulo si algún día son más: seis líneas distinguibles es el
   límite real de un gráfico de este tamaño, sumar colores no agrega lectura. */
.p-linea.c0, .p-leg.c0 { stroke: #4f8cff; color: #4f8cff; }
.p-linea.c1, .p-leg.c1 { stroke: #22c55e; color: #22c55e; }
.p-linea.c2, .p-leg.c2 { stroke: #f59e0b; color: #f59e0b; }
.p-linea.c3, .p-leg.c3 { stroke: #ec4899; color: #ec4899; }
.p-linea.c4, .p-leg.c4 { stroke: #14b8a6; color: #14b8a6; }
.p-linea.c5, .p-leg.c5 { stroke: #a855f7; color: #a855f7; }

.card.alerta { border-color: color-mix(in srgb, var(--warn) 45%, var(--linea)); }
.card.alerta .num { color: var(--warn); }

/* ══════════════════════════════════════════════════════════════════════════
   14. Móvil
   ══════════════════════════════════════════════════════════════════════════
   La consola es densa a propósito —es una herramienta de trabajo— pero tiene
   que poder abrirse desde el teléfono para mirar un error o pausar un scraping
   que se disparó mal. Eso es lo que se optimiza: consultar y actuar sobre una
   cosa puntual, no editar planillas.

   El corte es 900px y no 720: entre medio, la barra de 248px se come un cuarto
   de la pantalla y la tabla de al lado queda ilegible. */
@media (max-width: 900px) {
  .shell { grid-template-columns: 1fr; }

  .side {
    /* Explícito: sigue siendo una columna (marca, países, secciones, pie), sólo
       que ahora arriba en vez de al costado. */
    flex-direction: column;
    height: auto;
    overflow-y: visible;
    border-right: none;
    border-bottom: 1px solid var(--linea);
    padding: var(--e3);
    z-index: 20;
    box-shadow: var(--sombra-2);
  }
  .side .marca { padding: 0 var(--e1) var(--e2); }

  .paises {
    padding: 0 0 var(--e2);
    /* Sin el tope del 25%, que es de la barra angosta: acá hay ancho de sobra. */
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .paises::-webkit-scrollbar { display: none; }
  .pais { max-width: none; flex: 0 0 46px; }

  .nav {
    display: flex;
    gap: var(--e1);
    overflow-x: auto;
    scrollbar-width: none;
    padding-bottom: 2px;
    /* El scroll frena en cada ítem: con inercia libre es fácil pasarse y no
       saber en cuál quedó. */
    scroll-snap-type: x proximity;
  }
  .nav::-webkit-scrollbar { display: none; }
  .nav-item { flex: 0 0 auto; scroll-snap-align: start; }
  .nav-item.activo::before { display: none; }

  .side .pie {
    margin-top: var(--e2);
    padding: var(--e2) var(--e1) 0;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--e3);
  }

  .main { padding: var(--e4) var(--e3) var(--e7); }
  h2 { font-size: var(--t-xl); }
  .seccion-titulo { margin-top: var(--e5); }

  .grid { grid-template-columns: 1fr; }

  /* La tabla scrollea dentro de su caja. Sin esto, una tabla ancha desplaza
     TODA la página en horizontal y el menú se va de vista. */
  .tabla { display: block; overflow-x: auto; white-space: nowrap; }
  .tabla th { position: static; }
  .tabla td, .tabla th { white-space: normal; min-width: 112px; }
  .tabla td:first-child { min-width: 168px; }

  /* A 375px, un panel de 620px asomando por el costado no se lee ni se cierra. */
  .drawer { width: 100%; border-left: none; border-radius: 0; padding: var(--e4); }
  .par-campos { grid-template-columns: 1fr; }

  .barra { flex-direction: column; align-items: stretch; }
  .barra .campo, .barra .btn { width: 100%; }

  .cal { gap: var(--e1); }
  .cal-dia { min-height: 62px; padding: 5px 6px; }
  .cal-pct { font-size: var(--t-base); }
  .cal-n { font-size: 10px; }

  /* La tabla de precios ya scrollea dentro de `.tabla-scroll`; la regla de
     arriba le pondría un segundo scroll adentro del primero, que en un teléfono
     es imposible de manejar. Acá se le devuelve el comportamiento de tabla. */
  .tabla-scroll .tabla { display: table; overflow-x: visible; }
  .tabla.precios td, .tabla.precios th { min-width: 0; }
  .tabla.precios .p-nombre { min-width: 200px; }

  .p-ficha-cab { flex-direction: column; }
  .p-comparar .btn { width: auto; flex: 1 1 auto; }
}

/* ══════════════════════════════════════════════════════════════════════════
   15. Impresión
   ══════════════════════════════════════════════════════════════════════════
   Alguien va a querer llevar una tabla de errores a una reunión. */
@media print {
  .side, .barra, .btn, .cerrar, .overlay, .no-refresco { display: none !important; }
  /* Un esqueleto impreso es una mancha gris: lo que no llegó, no se imprime. */
  .sk-b { display: none !important; }
  .shell { grid-template-columns: 1fr; }
  html, body { background: #fff; color: #000; }
  .card, .tabla { border-color: #ccc; box-shadow: none; break-inside: avoid; }
  a { color: #000; text-decoration: underline; }
}

/* El cartel de "no pudimos actualizar" vive FUERA de `<main>`: cada sección
   reescribe `main.innerHTML` y se lo llevaría puesto. Esta columna los apila
   sin tocar el layout de la grilla del shell. */
.shell > .col { display: flex; flex-direction: column; min-width: 0; overflow: auto; }
.shell > .col > #avisoFrescura:not(:empty) { padding: var(--e4) var(--e4) 0; }
.shell > .col > .main { overflow: visible; }

/* ══════════════════════════════════════════════════════════════════════════
   16. Pestañas
   ══════════════════════════════════════════════════════════════════════════
   Dos públicos que no se mezclan: a los administradores se les avisa que algo
   se rompió, a los usuarios se les manda un aviso de producto. Comparten
   pantalla porque los dos son "cosas que salen de acá", pero mostrarlos juntos
   invitaría a mandarle a la gente un mail que dice "falló la corrida de SEPA". */
.tabs {
  display: flex;
  gap: var(--e1);
  border-bottom: 1px solid var(--linea);
  margin: var(--e5) 0 var(--e4);
  overflow-x: auto;
}
.tab {
  appearance: none;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  color: var(--txt-2);
  font: inherit;
  font-weight: 600;
  padding: var(--e3) var(--e4);
  cursor: pointer;
  white-space: nowrap;
  /* El -1px monta el borde del botón sobre el del contenedor, así la pestaña
     activa se ve pegada al contenido y no flotando encima de una línea. */
  margin-bottom: -1px;
}
.tab:hover { color: var(--txt); background: var(--sup-2); }
.tab[aria-selected="true"] { color: var(--acento-vivo); border-bottom-color: var(--acento); }
.tab .cuenta {
  display: inline-block;
  margin-left: var(--e2);
  padding: 0 6px;
  border-radius: 999px;
  background: var(--sup-2);
  color: var(--txt-3);
  font-size: var(--t-xs);
}

/* ══════════════════════════════════════════════════════════════════════════
   17. Ficha de producto: foto, y las dos góndolas
   ══════════════════════════════════════════════════════════════════════════
   Un producto puede venderse en un supermercado y en la tienda de una estación
   de servicio, y esos dos precios NO se comparan: sobre los artículos que están
   en las dos, la estación está más cara en el 86% de los casos. La ficha los
   muestra en dos secciones y con la leyenda puesta; lo de acá es sólo la ropa. */

/* El hueco de la foto que no tenemos.
   Es el caso frecuente y no la excepción: 202 de los 373 artículos que vende una
   estación no tienen foto en ninguna capa del catálogo. Por eso el vacío está
   dibujado —un cuadro con una marca neutra— en vez de descubierto: el ternario
   anterior emitía string vacío y el flex de `.p-ficha-cab` colapsaba.
   El glifo va en un `::after` y la imagen encima, así una URL que el CDN de la
   cadena dejó de servir cae en el mismo cuadro con `onerror="this.remove()"`. */
.p-img-vacia { position: relative; display: grid; place-items: center; overflow: hidden; }
.p-img-vacia::after {
  content: '▤';
  color: var(--txt-3);
  font-size: 24px;
  line-height: 1;
  opacity: .55;
}
.p-img-vacia > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: var(--sup-2);
  border-radius: inherit;
}
/* La miniatura del listado por sucursal. Misma caja, un tercio del tamaño. */
.p-img-chica { width: 34px; height: 34px; border-radius: var(--r1); }
.p-img-chica::after { font-size: 13px; }

/* Un artículo en una lista: foto chica a la izquierda, nombre y procedencia al
   lado. `align-items: flex-start` y no `center`: cuando la fila tiene dos
   renglones de metadatos, centrar la foto la deja flotando. */
.p-fila-art { display: flex; gap: var(--e2); align-items: flex-start; }
.p-abrir {
  color: var(--txt);
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px dotted var(--linea-fuerte);
}
.p-abrir:hover { color: var(--acento-vivo); border-bottom-color: var(--acento); }

/* Las dos medianas, una al lado de la otra, con la diferencia.
   Es lo único de la sección de estaciones que compara los dos canales, y por eso
   está separado de las tablas: adentro de una fila, un porcentaje entre canales
   se lee como si fuera un "vs promedio" más. */
.p-canales {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e4);
  background: var(--sup-1);
  border: 1px solid var(--linea);
  border-radius: var(--r2);
  padding: var(--e3);
  margin-bottom: var(--e3);
}
.p-canales > div { display: flex; flex-direction: column; gap: 2px; }
.p-canales .fuente { color: var(--txt-3); font-size: var(--t-xs); }
.p-canales b { font-size: var(--t-l); font-variant-numeric: tabular-nums; }

/* Una columna de la grilla de productos que NO es de supermercado.
   Sus celdas están todas vacías —el precio de una tienda de estación vive en la
   ficha, no en esta grilla— y una columna en blanco sin rótulo se lee como "esta
   cadena no vende nada". Apagada, no escondida: la ficha la nombra. */
.p-cad-otro { color: var(--txt-3); font-style: italic; }

/* ── Interruptor on/off ──────────────────────────────────────────────────────
   Un checkbox de verdad debajo: el estado lo lleva el input, así que teclado y
   lectores de pantalla funcionan sin una línea de JS. Lo que se pinta es el
   `::after` del riel. */
.sw { position: relative; display: inline-flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; }
.sw input { position: absolute; opacity: 0; width: 0; height: 0; }
.sw .riel {
  width: 38px; height: 22px; border-radius: 999px; flex: none;
  background: var(--linea-fuerte); position: relative;
  transition: background var(--transicion);
}
.sw .riel::after {
  content: ''; position: absolute; top: 3px; left: 3px;
  width: 16px; height: 16px; border-radius: 50%;
  background: #fff; box-shadow: var(--sombra-1);
  transition: transform var(--transicion);
}
.sw input:checked + .riel { background: var(--ok, #16a34a); }
.sw input:checked + .riel::after { transform: translateX(16px); }
.sw input:disabled + .riel { opacity: .5; cursor: not-allowed; }
.sw input:focus-visible + .riel { outline: 2px solid var(--acento); outline-offset: 2px; }
.sw .et { font-size: var(--t-s); color: var(--txt-2); }

/* La lista larga scrollea adentro de su caja y no estira la página: con 1.215
   sucursales de Día, la barra del navegador deja de servir para nada. */
.lista-scroll { max-height: 60vh; overflow-y: auto; border: 1px solid var(--linea); border-radius: var(--r2); }
.fila-cadena { display: flex; align-items: center; gap: 14px; padding: 10px 12px; border-bottom: 1px solid var(--linea); flex-wrap: wrap; }
.fila-cadena:last-child { border-bottom: 0; }
.fila-cadena .nom { flex: 1; min-width: 160px; }
.fila-cadena.apagada .nom { opacity: .6; }
.sucursales-de { background: var(--sup-2); padding: 8px 12px 12px 28px; border-bottom: 1px solid var(--linea); }

/* ── Uso de la app (telemetría) ──────────────────────────────────────────── */

.tel-resumen { display: flex; gap: 26px; flex-wrap: wrap; margin: 16px 0 20px; }
.tel-resumen div { display: flex; flex-direction: column; }
.tel-resumen b { font-size: 22px; line-height: 1.2; }
.tel-resumen span { font-size: 12px; opacity: .65; }

/* La serie es una lectura de un vistazo, no un gráfico para medir: por eso no
   lleva ejes ni números. Lo que importa es la forma — si sube, si cae, si hay
   un día raro—. El valor exacto está en el title de cada barra. */
.tel-serie {
  display: flex; align-items: flex-end; gap: 2px; height: 90px;
  margin-bottom: 24px; padding: 8px; border-radius: 8px;
  background: rgba(127, 127, 127, .08);
}
.tel-bar { flex: 1; height: 100%; display: flex; align-items: flex-end; min-width: 3px; }
.tel-bar > div { width: 100%; background: #0073CF; border-radius: 2px 2px 0 0; min-height: 2px; }

.tel-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 16px; }
.tel-card { border: 1px solid rgba(127, 127, 127, .22); border-radius: 10px; padding: 14px; }
.tel-card h3 { margin: 0 0 10px; font-size: 14px; display: flex; justify-content: space-between; }
.tel-total { opacity: .6; font-weight: 400; }
.tel-card table { width: 100%; border-collapse: collapse; font-size: 13px; }
.tel-card td { padding: 5px 0; border-bottom: 1px solid rgba(127, 127, 127, .12); }
/* Los números tabulares alinean las unidades en columna aunque cambie el ancho
   de cada dígito, que es lo que hace comparable un ranking de un vistazo. */
.tel-n { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
