/* Panel de producto. Sobrio, denso y legible: la pantalla la mira alguien
   que va a tomar una decisión con esto, no alguien que la admira. */

:root {
  --tinta: #16191d;
  --tinta-2: #4a5159;
  --tinta-3: #79818a;
  --papel: #ffffff;
  --papel-2: #f6f7f9;
  --linea: #e3e6ea;
  --linea-2: #ccd2d9;
  --acento: #1f4e79;
  --acento-suave: #e8eef4;
  --alerta: #8a5a00;
  --alerta-suave: #fdf3e0;
  --cero: #9aa1a9;
  --marca-mencion: #fff3b8;
  --radio: 10px;
  --sombra: 0 1px 2px rgba(20, 25, 30, .06), 0 4px 14px rgba(20, 25, 30, .05);
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  /* ── El tile de marca ───────────────────────────────────────────────────
     Los 375 activos de `assets/logos/` son **todos 512×256**: logotipos
     apaisados, proporción 2:1, medidos uno por uno en la cabecera PNG. Un
     tile cuadrado con `object-fit: contain` los pintaba a la mitad de su
     altura —34×17 dentro de un cuadro de 34— y, como casi todos traen
     margen interno, lo que quedaba en pantalla era una hilacha o un cuadro
     en blanco: «Universidad de Chile» salía como una tira, y PUC, U. de
     Concepción, USACH y Adolfo Ibáñez salían vacías.

     Por eso el ancho se DERIVA del alto por la proporción del activo, en
     vez de escribirse como un segundo número suelto que la próxima vez se
     cambia en un sitio y se olvida en el otro.

     El alto pintado es 32 y no 34 para que la caja con su borde siga
     midiendo 34 de alto y la fila no cambie de altura. Y el tamaño va al
     **content-box** a propósito: `object-fit` encuadra la imagen dentro de
     la caja de contenido, así que si el borde se descontara del ancho la
     proporción pintada dejaría de ser 2:1 por dos píxeles y el logo
     volvería a tener franjas vacías, chicas pero vacías. */
  --logo-borde: 1px;
  --logo-alto: 32px;
  --logo-ancho: calc(var(--logo-alto) * 2);   /* 2:1, la del activo */
  --logo-caja-alto: calc(var(--logo-alto) + var(--logo-borde) * 2);
  --logo-caja-ancho: calc(var(--logo-ancho) + var(--logo-borde) * 2);

  /* El papel OSCURO del tile. 87 de los 375 activos son variantes de
     logotipo blanco sobre transparente —las que las marcas publican para
     fondos oscuros— y sobre `--papel-2` no se ven: la tinta y el papel
     tienen el mismo tono, así que el tile queda en blanco. Arreglar la
     geometría sólo agrandó el hueco.

     Cuál activo lo necesita NO se decide acá ni al pintar: lo decide
     `tinta_de_logo.py`, que mide cada archivo una vez y deja la medida como
     dato. El servidor manda `fondo` en el payload del logo y el front se
     limita a poner la clase. Por eso este color tiene que seguir siendo el
     mismo que `FONDO_OSCURO` de ese módulo: si cambia uno, cambia el otro y
     la tabla se regenera.

     Oscurecer el tile para TODOS no era opción: rompería los 288 logotipos
     de tinta oscura, que son la mayoría. */
  --papel-logo-oscuro: #22262c;
  --linea-logo-oscuro: #343a43;
  /* El borde discontinuo del `provisorio` sobre el papel oscuro. `--tinta-3`
     es el tono sobre papel claro y sobre el oscuro se apaga; este es el
     mismo gris subido hasta que la discontinuidad se siga viendo. */
  --tinta-3-sobre-oscuro: #9aa3ad;

  /* ── La araña por superficie ─────────────────────────────────────────
     Las dos series NO se separan sólo por opacidad: difieren en tono, en
     trazo —continuo contra discontinuo— y en la forma del vértice. Quien
     no distingue bien los colores las separa igual, y en una impresión en
     blanco y negro también.

     Los tonos salen de las variables de arriba y no de literales nuevos:
     el panel tiene hoy un solo tema, y el día que tenga otro la araña lo
     sigue sin que haya que acordarse de este bloque. Los dos rellenos son
     lo único con alfa propio, porque un relleno tiene que dejar ver la
     reja y la serie de atrás, y para eso no alcanza un color sólido. */
  --arana-propia: var(--acento);
  --arana-propia-relleno: rgba(31, 78, 121, .16);
  --arana-tenue: var(--tinta-2);
  --arana-tenue-relleno: rgba(74, 81, 89, .07);
  --arana-reja: var(--linea);
  --arana-borde: var(--linea-2);
}

* { box-sizing: border-box; }

/* `hidden` TIENE que ocultar. La hoja del navegador trae `[hidden]{display:
   none}`, pero es de origen UA: cualquier regla de autor que fije `display`
   con especificidad >= (0,1,0) le gana. Acá el caso vivo es `.login`
   (0,1,0, `display:grid`), que es el único elemento al que hoy `app.js` le
   pone `hidden`: sin esta regla el gate de login tapa el panel entero con
   un overlay `position:fixed;inset:0` aunque el atributo esté bien puesto.
   Pasó exactamente así en el panel de avance.

   Va GLOBAL y no en `.login[hidden]`: el defecto no es de ese elemento, es
   de cualquier elemento que combine `hidden` con una clase o un id que
   traiga `display`. Una regla por caso obliga a acordarse; esta no. Y hay
   un candidato latente a la vista: `#login-btn{display:flex}`, que hoy
   nunca lleva `hidden` pero lo llevaría en cuanto alguien replique el
   manejo de «sin client_id» del otro panel — y una `.login[hidden]` lo
   habría dejado roto.

   Y va con `!important` porque sin eso no alcanza: una `[hidden]{display:
   none}` de autor empata en especificidad con `.login` y pierde por orden,
   y pierde de plano contra `#login-btn`, que es (1,0,0). `!important` la
   hace inmune al orden y a la especificidad, que es justo lo que se espera
   de una regla base.

   Es seguro aunque este `app.js` SÍ use `style.display` (en `verMarca`,
   para la cabecera de la ficha): ese elemento se crea al vuelo y nunca
   lleva `hidden`. Y si algún día lo llevara, que `hidden` le gane al estilo
   inline es el comportamiento correcto, no un efecto colateral. */
[hidden] { display: none !important; }

body {
  margin: 0;
  font: 15px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
        "Helvetica Neue", Arial, sans-serif;
  color: var(--tinta);
  background: var(--papel-2);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { margin: 0; font-weight: 600; letter-spacing: -.01em; }

/* ── Cabecera ─────────────────────────────────────────────────────────── */

.cabecera {
  display: flex; align-items: center; justify-content: space-between;
  gap: 24px; padding: 14px 28px; background: var(--papel);
  border-bottom: 1px solid var(--linea); position: sticky; top: 0; z-index: 20;
}
.marca-app { display: flex; align-items: center; gap: 12px; }
.marca-app h1 { font-size: 16px; }
.punto {
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--acento); flex: none;
}
.corrida { margin: 1px 0 0; font-size: 12px; color: var(--tinta-3); font-family: var(--mono); }

/* ── Con qué se está midiendo (DEC-029 (a)) ─────────────────────────────
   `matcher` y `pesos`, pegados bajo la línea de corrida —que ya declara el
   `run_id`— y presentes en todas las vistas.

   El tamaño es deliberado y va en las dos direcciones. Tiene que verse SIN
   buscarla: su función es que alguien note que el servicio quedó apuntando
   a otra medición, y un rótulo detrás de un menú o al pie de la página no
   lo nota nadie. Y no puede competir con el contenido: el panel es para
   leer marcas y puntajes, no versiones. De ahí 11px y `--tinta-3`, un paso
   por debajo de la línea de corrida, que ya es la más tenue del
   encabezado.

   El valor en monoespaciado porque es un identificador y se compara
   carácter a carácter contra lo que dice la configuración del despliegue.
   El subrayado punteado aparece SOLO cuando el valor va abreviado: es la
   señal de que falta texto y de que el resto está a un hover. Sin esa
   señal, un valor cortado se lee como el valor entero — que es peor que no
   mostrarlo. */
.medicion { margin: 2px 0 0; font-size: 11px; color: var(--tinta-3); }
.medicion .campo { white-space: nowrap; }
.medicion .rotulo-campo { color: var(--tinta-3); }
.medicion .valor-campo { font-family: var(--mono); color: var(--tinta-2); }
.medicion .valor-campo.abreviado { text-decoration: underline dotted var(--linea-2); text-underline-offset: 2px; cursor: help; }
.medicion .sep { color: var(--linea-2); }

/* `margin-left:auto` y no un contenedor nuevo: la cabecera ya era
   `space-between` con dos hijos, y al entrar el tercero —el botón de salir—
   ese reparto dejaba las migas flotando en el MEDIO de la barra. El margen
   automático se come el espacio libre antes de las migas, así que la marca
   queda a la izquierda y migas y salida quedan juntas a la derecha. */
.migas { display: flex; align-items: center; gap: 6px; font-size: 13px; flex-wrap: wrap; margin-left: auto; }
.migas button {
  background: none; border: 0; color: var(--acento); cursor: pointer;
  font: inherit; padding: 4px 6px; border-radius: 6px;
}
.migas button:hover { background: var(--acento-suave); }
.migas .sep { color: var(--linea-2); }
.migas .aqui { color: var(--tinta-2); padding: 4px 6px; }

/* ── El rótulo de 1 de 5. Fijo, no descartable. ───────────────────────── */

.rotulo {
  padding: 9px 28px; background: #2b3138; color: #eef1f4;
  font-size: 13px; line-height: 1.45; position: sticky; top: 57px; z-index: 19;
}
.rotulo strong { color: #fff; font-weight: 600; }
.rotulo.incoherente { background: #7a2d2d; }

/* ── Estructura ───────────────────────────────────────────────────────── */

main { padding: 24px 28px 64px; max-width: 1180px; margin: 0 auto; }
.cargando, .vacio { color: var(--tinta-3); padding: 32px 0; }

.tarjeta {
  background: var(--papel); border: 1px solid var(--linea);
  border-radius: var(--radio); box-shadow: var(--sombra); margin-bottom: 18px;
}
.tarjeta > header {
  padding: 14px 18px; border-bottom: 1px solid var(--linea);
  display: flex; align-items: baseline; justify-content: space-between; gap: 16px;
}
.tarjeta > header h2 { font-size: 15px; }
.tarjeta > .cuerpo { padding: 6px 18px 16px; }

.sub { font-size: 12.5px; color: var(--tinta-3); margin: 3px 0 0; }
.nota { font-size: 12.5px; color: var(--tinta-2); }
.tenue { color: var(--tinta-3); }

/* ── La grilla de categorías ──────────────────────────────────────────────

   Una tarjeta por categoría, con el podio por delante y la categoría
   entera por detrás. Reemplaza al ranking unificado de las 427 marcas.

   **Las dos caras van en posición absoluta y la tarjeta lleva la altura.**
   Es lo que hace posible la vuelta: las dos caras ocupan el mismo hueco,
   una rotada 180°, y `backface-visibility: hidden` esconde la que mira para
   atrás. Si cada cara llevara su alto, el dorso —que tiene hasta 18 filas—
   estiraría la tarjeta y la vuelta saldría a los saltos. */

.grilla {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 16px;
}

.tarjeta-cat {
  position: relative;
  height: 284px;
  perspective: 1400px;
  /* El alto cambia cuando la tarjeta se da vuelta, y ese cambio también es
     movimiento: va con la vuelta y se apaga con ella. */
  transition: height .45s ease;
}

/* La tarjeta dada vuelta ocupa la grilla entera: el gráfico de barras
   necesita ancho para que el nombre y la barra convivan, y es además la
   señal de que esta tarjeta es la pantalla y no una más de 55. */
.tarjeta-cat.volteada {
  grid-column: 1 / -1;
  height: 520px;
  z-index: 1;
}

.tarjeta-cat .cara {
  position: absolute;
  inset: 0;
  background: var(--papel);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  box-shadow: var(--sombra);
  overflow: hidden;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  transition: transform .45s ease;
}

.tarjeta-cat .cara.frente { transform: rotateY(0deg); }
.tarjeta-cat .cara.dorso { transform: rotateY(180deg); display: flex; flex-direction: column; }
.tarjeta-cat.volteada .cara.frente { transform: rotateY(-180deg); }
.tarjeta-cat.volteada .cara.dorso { transform: rotateY(0deg); }

/* ── La cara ── */

.tarjeta-cat .voltear {
  display: flex; flex-direction: column; align-items: stretch;
  width: 100%; height: 100%;
  padding: 16px 16px 18px;
  background: none; border: 0; cursor: pointer;
  font: inherit; color: inherit; text-align: left;
}
.tarjeta-cat .voltear:hover { background: var(--papel-2); }
/* El foco del teclado tiene que verse: la vuelta se puede hacer con tab y
   Enter, y un foco invisible la deja inutilizable para quien no usa mouse. */
.tarjeta-cat .voltear:focus-visible,
.tarjeta-cat .volver:focus-visible {
  outline: 2px solid var(--acento); outline-offset: -2px;
}

.cat-nombre { font-size: 14.5px; font-weight: 600; }
.cat-tamano { font-size: 12px; color: var(--tinta-3); margin: 2px 0 0; }

/* ── El podio ──
   Arriba el líder —o los dos que comparten el puesto 1, del MISMO tamaño—
   y abajo los que siguen, más chicos. El tamaño es la jerarquía, así que
   dos marcas arriba tienen que medir igual: una más grande que la otra
   afirmaría un orden que la medición niega. */

.podio { margin-top: auto; display: flex; flex-direction: column; gap: 12px; }
.podio-fila { display: flex; align-items: flex-end; justify-content: center; gap: 14px; }
.podio-fila.abajo { gap: 18px; }

.podio-marca, .podio-empate {
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  min-width: 0; max-width: 50%;
}
.podio-nombre {
  font-size: 11px; color: var(--tinta-2); text-align: center;
  max-width: 108px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* El tile del líder es más grande que el de abajo. Las medidas derivan de
   `--logo-alto` por la misma razón que el tile de la fila: la proporción
   2:1 es la del activo, y escribir el ancho como un segundo número suelto
   es cambiarlo en un sitio y olvidarlo en el otro.

   **Las cuatro variables se vuelven a declarar juntas, a propósito.** Un
   `var()` dentro del valor de una custom property se sustituye en el
   elemento donde esa property se DECLARA, así que `--logo-ancho`, que vive
   en `:root`, ya llega resuelto con el `--logo-alto` de `:root`: pisar solo
   el alto acá daría un tile de 46 de alto y 64 de ancho —la proporción del
   tile de la fila— y el logo volvería a tener franjas vacías. */
.podio .protagonico .caja-logo {
  --logo-alto: 46px;
  --logo-ancho: calc(var(--logo-alto) * 2);
  --logo-caja-alto: calc(var(--logo-alto) + var(--logo-borde) * 2);
  --logo-caja-ancho: calc(var(--logo-ancho) + var(--logo-borde) * 2);
}
.podio .abajo .caja-logo {
  --logo-alto: 26px;
  --logo-ancho: calc(var(--logo-alto) * 2);
  --logo-caja-alto: calc(var(--logo-alto) + var(--logo-borde) * 2);
  --logo-caja-ancho: calc(var(--logo-ancho) + var(--logo-borde) * 2);
}
.podio .protagonico .monograma { font-size: 16px; }
.podio .abajo .monograma { font-size: 11px; }
.podio .protagonico .podio-nombre { font-size: 12.5px; color: var(--tinta); font-weight: 550; }

/* ── El ícono de empate ──
   Ocupa el casillero que el podio habría partido. No es un logo degradado
   ni un hueco: es un signo de igual, dos barras del mismo largo. */
.icono-empate { width: 34px; height: 34px; fill: var(--acento); }
.icono-empate .icono-empate-aro {
  fill: var(--acento-suave); stroke: #c4d5e6; stroke-width: 2;
}
.podio .protagonico .icono-empate { width: 52px; height: 52px; }
.podio-empate .podio-nombre { color: var(--acento); max-width: 140px; white-space: normal; }
/* Cuando la banda partida se lleva dos casilleros, el ícono ocupa los dos:
   dejar uno vacío al lado se leería como que ahí falta algo. */
.podio-empate.ancho { max-width: 100%; }

/* ── El dorso ── */

.dorso-cabecera {
  padding: 13px 18px; border-bottom: 1px solid var(--linea);
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  flex: none;
}
.dorso-cabecera h2 { font-size: 15px; }
.volver {
  font: inherit; font-size: 12.5px; padding: 6px 10px; flex: none;
  border: 1px solid var(--linea-2); border-radius: 8px;
  background: var(--papel); color: var(--tinta); cursor: pointer;
}
.volver:hover { background: var(--acento-suave); }

/* El gráfico de barras scrollea DENTRO de la tarjeta. Hay categorías de 18
   marcas y la tarjeta no puede crecer con ellas: la grilla de atrás se
   reacomodaría cada vez que se abre una categoría larga. */
.barras { overflow-y: auto; flex: 1 1 auto; }

/* ── Movimiento ──
   La vuelta es decoración: dice lo mismo que el cambio de contenido. Quien
   pidió menos movimiento la recibe instantánea, no degradada. */
@media (prefers-reduced-motion: reduce) {
  .tarjeta-cat,
  .tarjeta-cat .cara { transition: none; }
}

@media (max-width: 760px) {
  .grilla { grid-template-columns: 1fr; }
  .tarjeta-cat.volteada { height: 560px; }
}

/* ── Controles ────────────────────────────────────────────────────────── */

.controles { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 16px; }
select, .segmento button {
  font: inherit; font-size: 13px; padding: 7px 11px;
  border: 1px solid var(--linea-2); border-radius: 8px;
  background: var(--papel); color: var(--tinta); cursor: pointer;
}
.segmento { display: inline-flex; }
.segmento button { border-radius: 0; border-left-width: 0; }
.segmento button:first-child { border-radius: 8px 0 0 8px; border-left-width: 1px; }
.segmento button:last-child { border-radius: 0 8px 8px 0; }
.segmento button[aria-pressed="true"] {
  background: var(--acento); border-color: var(--acento); color: #fff;
}

/* ── Filas de marca ───────────────────────────────────────────────────── */

.fila {
  display: grid;
  grid-template-columns: var(--logo-caja-ancho) 1fr 186px 108px 124px;
  gap: 14px; align-items: center; padding: 11px 18px;
  border-top: 1px solid var(--linea); cursor: pointer; background: none;
  border-left: 0; border-right: 0; border-bottom: 0; width: 100%;
  text-align: left; font: inherit; color: inherit;
}
.fila:first-child { border-top: 0; }
.fila:hover { background: var(--papel-2); }

/* El cuadro del logo. El monograma usa EXACTAMENTE la misma caja que una
   imagen, para que una categoría entera sin logos se vea igual de
   terminada que una con todos. */
.logo, .monograma {
  box-sizing: content-box;
  width: var(--logo-ancho); height: var(--logo-alto);
  border-radius: 8px; flex: none;
  object-fit: contain; background: var(--papel-2);
  border: var(--logo-borde) solid var(--linea);
}
/* El monograma lleva el MISMO borde que la imagen, solo que invisible.
   Ponerlo en `0` lo dejaba dos píxeles más chico que el tile con imagen
   —el tamaño va al content-box— y la grilla bailaba según hubiera activo,
   que es justo lo que esta caja compartida existe para evitar. */
.monograma {
  display: grid; place-items: center; color: #fff;
  border-color: transparent;
  font-size: 12.5px; font-weight: 600; letter-spacing: .02em;
}

/* El tile de papel oscuro. Va sobre `.logo` —la imagen— y no sobre la caja,
   porque lo que tiene que cambiar de fondo es el rectángulo que la imagen
   ocupa: el activo es transparente y lo que se ve por detrás es este color.
   El monograma NUNCA la lleva: trae su propio color de fondo y sus
   iniciales blancas, y pisárselo lo rompería. */
.logo.en-oscuro {
  background: var(--papel-logo-oscuro);
  border-color: var(--linea-logo-oscuro);
}

/* ── Logo sin confirmar ───────────────────────────────────────────────────
 *
 * Un logo `media` o `estimada` se muestra, pero no está confirmado. Tres
 * decisiones, y la primera no es negociable:
 *
 * 1 · NO depende solo del color. Una diferencia únicamente cromática
 *     desaparece para quien no distingue esos tonos, y desaparece entera en
 *     una captura en blanco y negro o en un PDF impreso — que es exactamente
 *     cómo va a circular este panel. La señal que manda es el **borde
 *     discontinuo** más la **esquina doblada**: las dos sobreviven sin color
 *     y sobreviven en escala de grises.
 *
 * 2 · Se lee como PROVISORIO, no como problema. Nada de rojo ni de ícono de
 *     advertencia: un logo estimado no es un error, es una hipótesis que
 *     alguien va a confirmar. Si se marcara en rojo, el panel se vería roto
 *     cuando en realidad está siendo honesto. Por eso el tono es el gris
 *     azulado de la tinta secundaria y no el de alerta.
 *
 * 3 · El motivo está a un hover, en el `title` de la caja.
 */
.caja-logo {
  position: relative; flex: none;
  width: var(--logo-caja-ancho); height: var(--logo-caja-alto);
}
.caja-logo.provisorio .logo,
.caja-logo.provisorio .monograma {
  border: var(--logo-borde) dashed var(--tinta-3);
  background: var(--papel-2);
  opacity: .88;
}
/* Un logo sin confirmar que ADEMÁS necesita papel oscuro. Son dos
   propiedades independientes —si está confirmado, y sobre qué se lee— y las
   dos tienen que sobrevivir juntas: el papel cambia, las dos señales de
   `provisorio` se quedan.

   La especificidad está contada: `.caja-logo.provisorio .logo` es (0,3,0) y
   le ganaba a `.logo.en-oscuro`, que es (0,2,0), así que los provisorios de
   tinta blanca volvían al papel claro y quedaban invisibles igual que
   antes. Esta regla es (0,4,0) y gana. El borde discontinuo se mantiene,
   sólo sube de tono para que la discontinuidad se siga viendo sobre el
   papel oscuro.

   Y la `opacity` NO se hereda acá: sobre papel claro bajarle el contraste a
   un logo oscuro lo deja «apagado», que es justo lo que se quiere decir;
   sobre papel oscuro, bajarle el contraste a una tinta blanca la empuja de
   vuelta hacia el fondo, que es el defecto que esta tanda arregla. La
   señal de «sin confirmar» ya la dan el borde y la esquina, que son
   geométricas y sobreviven en blanco y negro. */
.caja-logo.provisorio .logo.en-oscuro {
  background: var(--papel-logo-oscuro);
  border: var(--logo-borde) dashed var(--tinta-3-sobre-oscuro);
  opacity: 1;
}
/* La esquina doblada: segunda señal, puramente geométrica. */
.caja-logo.provisorio::after {
  content: ""; position: absolute; right: -1px; bottom: -1px;
  width: 0; height: 0;
  border-left: 8px solid transparent;
  border-bottom: 8px solid var(--tinta-3);
  border-bottom-right-radius: 3px;
}
.marca-provisoria {
  font-size: 11px; color: var(--tinta-3); border: 1px dashed var(--linea-2);
  border-radius: 999px; padding: 1px 7px; white-space: nowrap;
}

.nombre { font-weight: 550; }
.donde { font-size: 12px; color: var(--tinta-3); }

/* La barra del puntaje. Continua a propósito: `puntaje` SÍ es una
   escala continua de 0 a 100. La que no se dibuja continua es `presencia`,
   que solo toma unos pocos valores: una por respuesta de la celda, más el
   cero. */
.barra { height: 7px; border-radius: 4px; background: var(--linea); overflow: hidden; }
.barra > i { display: block; height: 100%; background: var(--acento); }
.cifra { font-family: var(--mono); font-size: 13.5px; text-align: right; }
.cifra .unidad { color: var(--tinta-3); font-size: 11px; }

/* Un cero MEDIDO se dibuja distinto de un hueco: lleva su denominador
   pegado y un tono propio, en vez de una celda vacía. */
.cero-medido { color: var(--cero); }
.cero-medido .denominador { font-size: 11px; }
.sin-dato { color: var(--tinta-3); font-style: italic; }

.puesto { font-size: 12.5px; color: var(--tinta-2); text-align: right; white-space: nowrap; }
/* El percentil, deletreado. En la columna es más angosto que la frase que
   lo explica, así que baja un punto de tamaño antes que recortarse: una
   etiqueta cortada con «…» vuelve a ser una abreviatura, que es el defecto
   que esto vino a arreglar. */
.puesto .donde { font-size: 11.5px; }

/* ── Chips ────────────────────────────────────────────────────────────── */

.chip {
  display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px;
  padding: 2px 8px; border-radius: 999px; background: var(--papel-2);
  border: 1px solid var(--linea); color: var(--tinta-2); white-space: nowrap;
}
.chip.aviso { background: var(--alerta-suave); border-color: #eccb8e; color: var(--alerta); }
/* Las etiquetas que EXPLICAN dejaron de ser abreviaturas, así que algunas
   ya no caben en una línea de una pantalla angosta. `nowrap` las haría
   desbordar sobre la columna de al lado; acá se dejan partir. */
.fila .chip, .sup-cabecera .chip { white-space: normal; }

/* La explicación de la sensibilidad, dicha entera en la ficha de marca.
   Un `title` no existe para quien mira esto en una tablet ni para quien lo
   imprime, y es la etiqueta más accionable del panel. */
.nota.aviso {
  color: var(--alerta); background: var(--alerta-suave);
  border: 1px solid #eccb8e; border-radius: 8px;
  padding: 9px 12px; margin-top: 10px;
}
.chip.empate { background: var(--acento-suave); border-color: #c4d5e6; color: var(--acento); }

/* ── Bandas de empate ─────────────────────────────────────────────────── */

/* Se dibuja como banda y no como lista numerada: dos marcas separadas por
   menos que el umbral de ruido de su categoría son indistinguibles, y una
   lista ordenada promete un orden que la medición no sostiene. */
.banda { border-top: 1px solid var(--linea); }
.banda:first-child { border-top: 0; }
.banda.indistinguible { background: linear-gradient(90deg, var(--acento-suave) 0 3px, transparent 3px); }
.banda-cabecera {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 18px 3px; font-size: 12px; color: var(--tinta-3);
}
.banda.indistinguible .banda-cabecera { color: var(--acento); }

/* ── Superficies ──────────────────────────────────────────────────────── */

.superficie { border-top: 1px solid var(--linea); padding: 13px 18px; }
.superficie:first-child { border-top: 0; }
.sup-cabecera { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.sup-nombre { font-weight: 550; min-width: 132px; }

/* Las pastillas, UNA POR RESPUESTA de la celda. `presencia` solo puede
   tomar unos pocos valores porque cada superficie aporta un puñado de
   respuestas —hoy 3: 1 reactivo × 3 repeticiones—, y cuántas son lo dice el
   dato, no esta hoja. Dibujarla como barra continua sugeriría una precisión
   que no existe. */
.pastillas { display: inline-flex; gap: 3px; }
.pastilla {
  width: 15px; height: 15px; border-radius: 4px;
  border: 1px solid var(--linea-2); background: var(--papel);
}
.pastilla.llena { background: var(--acento); border-color: var(--acento); }
.pastilla.sep { margin-left: 7px; }

.por-reactivo { display: flex; gap: 14px; margin-top: 7px; font-size: 12px; color: var(--tinta-2); flex-wrap: wrap; }
.por-reactivo b { font-family: var(--mono); font-weight: 600; }

.celdas-drill { margin-top: 9px; }
.celdas-drill button {
  font: inherit; font-size: 12.5px; padding: 5px 10px; cursor: pointer;
  border: 1px solid var(--linea-2); border-radius: 8px; background: var(--papel);
  color: var(--acento);
}
.celdas-drill button:hover { background: var(--acento-suave); }

/* ── Identidad del puntaje ────────────────────────────────────────────── */

.identidad {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 16px 18px; background: var(--papel-2); border-radius: var(--radio);
  margin-bottom: 4px;
}
.term { text-align: center; }
.term .val { font-family: var(--mono); font-size: 21px; font-weight: 600; }
.term .et { font-size: 11.5px; color: var(--tinta-3); display: block; margin-top: 1px; }
.op { font-size: 17px; color: var(--tinta-3); }

/* ── El drill-down ────────────────────────────────────────────────────── */

.respuesta { border-top: 1px solid var(--linea); padding: 16px 18px; }
.respuesta:first-child { border-top: 0; }
.resp-cabecera { display: flex; gap: 9px; align-items: center; flex-wrap: wrap; margin-bottom: 9px; }
.resp-cabecera .id { font-family: var(--mono); font-size: 11px; color: var(--tinta-3); }

.texto-llm {
  font-size: 14.5px; line-height: 1.62; color: var(--tinta);
  border-left: 3px solid var(--linea); padding-left: 15px;
  max-height: 340px; overflow: auto;
}
.texto-llm.aparece { border-left-color: var(--acento); }
.texto-llm h2, .texto-llm h3, .texto-llm h4 { font-size: 14.5px; margin: 14px 0 5px; }
.texto-llm p { margin: 9px 0; }
.texto-llm ul, .texto-llm ol { margin: 9px 0; padding-left: 22px; }
.texto-llm li { margin: 3px 0; }
.texto-llm code {
  font-family: var(--mono); font-size: .88em; background: var(--papel-2);
  padding: 1px 4px; border-radius: 4px;
}
.texto-llm pre { background: var(--papel-2); padding: 11px; border-radius: 8px; overflow: auto; }
.texto-llm blockquote {
  margin: 9px 0; padding-left: 12px; border-left: 2px solid var(--linea-2);
  color: var(--tinta-2);
}
.texto-llm hr { border: 0; border-top: 1px solid var(--linea); margin: 14px 0; }
.texto-llm a { color: var(--acento); }
.tabla-scroll { overflow-x: auto; margin: 9px 0; }
.texto-llm table { border-collapse: collapse; font-size: 13px; }
.texto-llm th, .texto-llm td {
  border: 1px solid var(--linea); padding: 5px 9px; text-align: left; vertical-align: top;
}
.texto-llm th { background: var(--papel-2); font-weight: 600; }

/* La mención, resaltada en su `pos_char`. */
mark.mencion {
  background: var(--marca-mencion); color: inherit;
  border-radius: 3px; padding: 1px 2px; box-shadow: 0 0 0 1px #e8d268;
}

.fuentes { margin-top: 11px; font-size: 12px; color: var(--tinta-2); }
.fuentes a { color: var(--acento); }
.fuentes li { margin: 2px 0; }

/* ── Login ────────────────────────────────────────────────────────────── */

.login {
  position: fixed; inset: 0; background: var(--papel-2);
  display: grid; place-items: center; z-index: 50;
}
.caja-login {
  background: var(--papel); padding: 32px; border-radius: 14px;
  box-shadow: var(--sombra); max-width: 420px; text-align: center;
}
.caja-login h2 { margin-bottom: 10px; }
#login-btn { display: flex; justify-content: center; margin: 18px 0 14px; }
/* El botón del login. Antes lo dibujaba `google.accounts.id.renderButton`;
   con Firebase el botón es nuestro, así que su estilo vive acá. */
.btn-login {
  appearance: none; cursor: pointer; font: inherit; font-weight: 600;
  padding: 10px 18px; border-radius: 8px;
  border: 1px solid var(--acento); background: var(--acento); color: #fff;
}
.btn-login:hover:not(:disabled) { filter: brightness(1.15); }
.btn-login:disabled { cursor: progress; opacity: .6; }

/* ── Salir ──────────────────────────────────────────────────────────────
   Discreto a propósito. Es una SALIDA, no una acción del panel: el único
   botón con relleno sólido sigue siendo el de opinar, que es el que la gente
   del piloto tiene que encontrar sin buscarlo. Acá alcanza con que esté
   donde se lo busca —el extremo de la cabecera— y que se note al pasar por
   encima. */
.btn-salir {
  appearance: none; cursor: pointer; font: inherit; font-size: 13px;
  padding: 5px 12px; border-radius: 999px; flex: none;
  border: 1px solid var(--linea-2); background: none; color: var(--tinta-2);
}
.btn-salir:hover:not(:disabled) { border-color: var(--acento); color: var(--acento); }
.btn-salir:disabled { cursor: progress; opacity: .6; }

@media (max-width: 760px) {
  main, .cabecera, .rotulo { padding-left: 16px; padding-right: 16px; }
  .fila { grid-template-columns: 30px 1fr 84px; gap: 10px; }
  .fila .barra-celda, .fila .puesto { display: none; }
  .rotulo { position: static; }
}

/* El estado de una fuente citada. `resuelta` es información de auditoría y
   va tenue; `sin_resolver` es una advertencia —ese enlace no se puede
   abrir— y tiene que notarse sin gritar. */
.fuentes .resolucion {
  font-size: 11px; padding: 1px 6px; border-radius: 999px;
  border: 1px solid var(--linea-2); color: var(--tinta-3);
}
.fuentes .resolucion[data-resolucion="sin_resolver"] {
  border-color: var(--alerta); color: var(--alerta);
}
/* Cuando la etiqueta de una fuente es un dominio y no un título. El
   contrato C12 avisa que `title` no siempre es un título: en Gemini la
   superficie pone ahí el dominio. Se muestra como lo que es, en vez de
   pasarlo por un título de artículo que nunca existió. */
.fuentes .dominio { font-family: var(--mono, ui-monospace, monospace); }


/* ── La araña por superficie ───────────────────────────────────────────
   El gráfico escala entero con su `viewBox`, así que acá no hay ni un
   tamaño de letra del SVG en píxeles: todo lo de adentro está en unidades
   del `viewBox` y el navegador las convierte. El tope de ancho existe para
   que en una pantalla grande el gráfico no se coma la tarjeta. */
.arana-caja {
  padding: 16px 18px 6px;
  display: grid; gap: 14px;
  grid-template-columns: minmax(0, 1fr);
  /* El bloque entero —gráfico, leyenda y tabla— va en una columna del
     ancho de una lectura. A todo el ancho de la tarjeta los valores de la
     tabla quedan a varios centímetros de su superficie y hay que seguir la
     fila con el dedo. */
  max-width: 620px; margin: 0 auto; width: 100%;
}
.arana { display: block; width: 100%; max-width: 460px; height: auto; margin: 0 auto; }

.arana-reja .arana-anillo { fill: none; stroke: var(--arana-reja); stroke-width: 1.5; }
.arana-reja .arana-borde { stroke: var(--arana-borde); stroke-width: 2.5; }
.arana-reja .arana-radio { stroke: var(--arana-reja); stroke-width: 1.5; }

/* La serie de la marca: trazo continuo y vértice redondo. */
.arana-propia .arana-area {
  fill: var(--arana-propia-relleno);
  stroke: var(--arana-propia); stroke-width: 3; stroke-linejoin: round;
}
.arana-propia .arana-vertice { fill: var(--arana-propia); stroke: none; }
/* El eje donde la marca no apareció: el vértice queda en el centro —es un
   cero medido— y se dibuja HUECO para que no se lea igual que un valor
   bajo. El papel de adentro es el de la tarjeta, no blanco fijo. */
.arana-propia .arana-vertice-hueco {
  fill: var(--papel); stroke: var(--arana-propia); stroke-width: 2.5;
}
/* La serie de atrás: trazo discontinuo y vértice cuadrado. */
.arana-tenue .arana-area {
  fill: var(--arana-tenue-relleno);
  stroke: var(--arana-tenue); stroke-width: 2.5; stroke-linejoin: round;
  stroke-dasharray: 9 6;
}
.arana-tenue .arana-vertice { fill: var(--arana-tenue); stroke: none; }

.arana-ejes text { fill: var(--tinta-2); dominant-baseline: middle; }
.arana-ejes .arana-nombre { font-size: 19px; }
/* El ordinal sólo entra en pantalla angosta — ver el bloque de abajo. */
.arana-ejes .arana-ordinal { font-size: 24px; font-weight: 700; display: none; }

.arana-leyenda { display: flex; flex-wrap: wrap; gap: 6px 18px; font-size: 12.5px; }
.arana-entrada { display: inline-flex; align-items: center; gap: 7px; color: var(--tinta-2); }
.arana-muestra { width: 22px; height: 22px; flex: none; }
.arana-muestra .arana-area { fill: none; }

.arana-tabla { border-collapse: collapse; width: 100%; font-size: 12.5px; }
.arana-tabla th, .arana-tabla td {
  text-align: left; padding: 4px 8px; border-bottom: 1px solid var(--linea);
}
.arana-tabla thead th { color: var(--tinta-3); font-weight: 600; }
.arana-tabla .arana-val { text-align: right; font-variant-numeric: tabular-nums; }
.arana-tabla .tenue { color: var(--tinta-3); }
/* El ordinal es el puente entre la punta de un eje y su fila. En pantalla
   ancha el nombre está en las dos partes y la columna estorba; en angosta
   es lo único que las une. */
.arana-tabla .arana-ord { display: none; color: var(--tinta-3); width: 1px; }

@media (max-width: 760px) {
  /* El SVG escala entero, así que achicarlo achica la letra: a este ancho
     el nombre de la plataforma sale ilegible. En vez de recortarlo, el eje
     pasa a decir su ordinal y el nombre se lee en la tabla, que a este
     ancho es la que carga con todo. */
  .arana-caja { padding-left: 16px; padding-right: 16px; }
  .arana-ejes .arana-nombre { display: none; }
  .arana-ejes .arana-ordinal { display: block; }
  .arana-tabla .arana-ord { display: table-cell; }
}

/* ── Opinar: el botón flotante del piloto ─────────────────────────────────

   El botón vive FIJO abajo a la derecha y cuelga de `<body>`, así que está
   en las cuatro vistas sin que ninguna tenga que ponerlo. Su `z-index` es
   menor que el del gate de login (50): si alguna vez el gate aparece con el
   panel detrás, lo que tiene que estar adelante es el gate.

   El modal se oculta con `hidden`, que acá SÍ oculta gracias a la regla
   global `[hidden]{display:none !important}` de más arriba — exactamente el
   defecto que ese `!important` vino a cerrar, ahora con un segundo elemento
   que combina `hidden` con un `display` de autor. */

.opinar-btn {
  position: fixed; right: 20px; bottom: 20px; z-index: 40;
  appearance: none; cursor: pointer; font: inherit; font-weight: 600;
  padding: 11px 20px; border-radius: 999px;
  border: 1px solid var(--acento); background: var(--acento); color: #fff;
  box-shadow: var(--sombra);
}
.opinar-btn:hover { filter: brightness(1.15); }

.opinar-panel {
  position: fixed; inset: 0; z-index: 45;
  background: rgba(20, 25, 30, .38);
  display: grid; place-items: center; padding: 20px;
}
.opinar-caja {
  background: var(--papel); border-radius: 14px; padding: 24px;
  box-shadow: var(--sombra); width: min(560px, 100%);
  max-height: 88vh; overflow: auto;
}
.opinar-caja h2 { margin-bottom: 12px; font-size: 18px; }

/* La cita de lo que la persona tenía seleccionado. Se dibuja como cita
   —barra al costado, tipografía de texto citado— para que no se confunda
   con lo que ella escribe debajo. */
.opinar-cita {
  margin: 0 0 14px; padding: 8px 12px;
  border-left: 3px solid var(--acento); background: var(--acento-suave);
  border-radius: 0 var(--radio) var(--radio) 0;
}
.opinar-cita-texto {
  margin: 0; font-size: 13px; color: var(--tinta-2);
  max-height: 120px; overflow: auto; white-space: pre-wrap;
}

.opinar-tipos { border: 0; padding: 0; margin: 0 0 12px; }
.opinar-tipos legend {
  padding: 0; font-size: 12px; font-weight: 600; color: var(--tinta-2);
  margin-bottom: 6px;
}
.opinar-tipo {
  display: inline-flex; align-items: center; gap: 6px;
  margin: 0 14px 4px 0; font-size: 13px; cursor: pointer;
}

.opinar-texto {
  width: 100%; font: inherit; font-size: 14px; padding: 10px;
  border: 1px solid var(--linea-2); border-radius: var(--radio);
  resize: vertical; background: var(--papel); color: var(--tinta);
}
.opinar-cuenta {
  margin: 4px 0 12px; font-size: 11px; color: var(--tinta-3);
  text-align: right;
}
/* Pasado el tope no se recorta nada: se MARCA, y el envío lo rechaza con
   su mensaje. Recortar un pegado sin avisar deja un comentario que se lee
   como si la persona lo hubiera dejado a medias. */
.opinar-cuenta.pasado { color: var(--alerta); font-weight: 600; }

.opinar-foto { margin-bottom: 12px; }
.opinar-previa {
  margin: 10px 0 0; padding: 8px; border: 1px solid var(--linea);
  border-radius: var(--radio); background: var(--papel-2);
}
/* La previa se topa en alto. Sin tope, una captura apaisada empuja el pie
   del formulario fuera del pliegue y «Enviar» hay que ir a buscarlo
   scrolleando — medido en la pantalla el 2026-10-02, con la ventana de
   1280×900 del arnés. Lo que la previa tiene que contestar es «¿es esto lo
   que querés mandar?», y eso se contesta igual en 30vh. */
.opinar-previa img {
  display: block; width: 100%; height: auto; max-height: 30vh;
  object-fit: contain; border-radius: 6px;
  border: 1px solid var(--linea-2); background: var(--papel);
}
.opinar-previa-pie {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin: 0 0 8px; font-size: 12px; color: var(--tinta-2);
}

.opinar-aviso { margin: 0 0 10px; font-size: 12px; color: var(--tinta-2); }
.opinar-aviso.malo { color: var(--alerta); font-weight: 600; }

/* El pie se queda PEGADO abajo de la caja. La caja scrollea por dentro
   —`max-height` más `overflow:auto`— así que sin esto «Enviar» puede
   quedar fuera de la vista con el formulario entero abierto. */
.opinar-pie {
  display: flex; align-items: center; justify-content: flex-end; gap: 14px;
  position: sticky; bottom: -24px;
  padding: 12px 0 0; margin-bottom: -24px;
  background: linear-gradient(to bottom, transparent, var(--papel) 14px);
}
.btn-opinar {
  appearance: none; cursor: pointer; font: inherit; font-weight: 600;
  padding: 9px 18px; border-radius: 8px;
  border: 1px solid var(--acento); background: var(--acento); color: #fff;
}
.btn-opinar:hover:not(:disabled) { filter: brightness(1.15); }
.btn-opinar:disabled { cursor: progress; opacity: .6; }

.opinar-enlace {
  appearance: none; background: none; border: 0; padding: 0;
  font: inherit; font-size: 12px; color: var(--acento);
  text-decoration: underline; cursor: pointer;
}
.opinar-enlace:disabled { cursor: progress; opacity: .6; }

/* El acuse. Va fuera del formulario, que para entonces ya se cerró. */
.opinar-gracias {
  position: fixed; right: 20px; bottom: 76px; z-index: 46;
  max-width: 320px; padding: 12px 16px;
  background: var(--tinta); color: var(--papel);
  border-radius: var(--radio); box-shadow: var(--sombra); font-size: 13px;
}
.opinar-gracias p { margin: 0; }
.opinar-gracias-aviso { margin-top: 6px !important; color: #ffd98a; }

/* El corte es 520 y no 760 porque lo que se aprieta es un botón flotante
   sobre el pulgar: a 760 el panel se reordena, pero el botón abajo a la
   derecha todavía cae bien. */
@media (max-width: 520px) {
  .opinar-btn { right: 12px; bottom: 12px; }
  .opinar-gracias { right: 12px; left: 12px; max-width: none; bottom: 68px; }
}
