/* fonts.css */
/* ==========================================================================
   TikTok Sans — variable en peso (300–900), ancho (75–150) y tamaño óptico.
   --------------------------------------------------------------------------
   La cara de FM26 nunca se identificó y probablemente sea un encargo: no hay
   forma honesta de decir «es ésta». Lo que sí se puede hacer —y es lo que se
   hizo el 20 de agosto de 2026— es medir a las candidatas contra la captura y
   contra el propio juego, y elegir con números.

   LAS TRES CONDICIONES DURAS, que dejan doce candidatas de las mil y pico de
   Google Fonts: eje de ANCHO que baje a 75 (los dos registros del sistema son
   una decisión de sistema, no un efecto de la cara), peso variable en el tramo
   400–700, y cifras tabulares de verdad. La ficha técnica no separa a esas
   doce; lo que las separa es lo que MIDEN.

   LAS DOS MEDIDAS QUE DECIDIERON, tomadas en el juego y no en una muestra:

     · el primer piso del chrome, que a 1440 entra con CERO píxeles de sobra
     · la ficha del futbolista, que entra en 1600×1000 con 19 de sobra

                        barra a 1440      ficha a 1600×1000    parecido
     Anek Latin          entra            981 px (sobran 19)   4.º
     Asap (la de antes)  entra            981 px (sobran 19)   3.º
     TikTok Sans        −32 px            998 px (sobran 2)    2.º
     Zalando Sans       −53 px           1015 px (FALTAN 29)   1.º

   Comprimir el eje para recuperar ancho no es una salida: una geométrica
   redonda al 87 % deja de ser redonda, que era lo que se venía a buscar. Lo que
   sí se puede hacer es mirar la factura y decidir si se paga.

   **Y ACÁ SE ELIGIÓ MAL UNA VEZ, que es la parte que vale escribir.** La
   primera vuelta puso Anek Latin porque costaba cero, y costar cero no era la
   pregunta: la pregunta era a cuál se parece. Puestas las cuatro con los
   rótulos de la captura al lado, el orden de PARECIDO es Zalando ≥ TikTok >
   Asap > Anek — o sea que Anek, la que se había elegido, era la última. Se
   había optimizado el coste y presentado como si fuera el parecido.

   Peor: las dos medidas se habían tratado como leyes cuando son facturas. Los
   cortes del chrome se habían movido tres veces esa misma tarde.

   **TikTok Sans es la más parecida que la pantalla puede pagar.** La ficha ya
   le entra sin tocar nada (998 px sobre 1000). La barra le debe 32 px a 1440, y
   32 px es exactamente lo que ocupa el logo de competición — que el reloj de al
   lado ya escribe con palabras, y que por eso mismo era el primero de la fila en
   irse. Se paga adelantando ese corte de 1300 a 1500.

   **ZALANDO ESTÁ DESCARTADA, Y NO POR EL ANCHO.** Lo de abajo decía que era la
   que gana si algún día se decide pagar los 53 px de barra y los 29 de ficha.
   Es falso y quedó vencido: su factura de espacio resultó pagable —el aire de
   la ficha bajó de 12 a 8 y entró—. Lo que la mata es una propiedad de la
   cara: **su `tnum` incluye al carácter de espacio.** Con la Regla Tabular
   puesta en `body`, cada espacio de la interfaz pasaba a medir lo que mide un
   dígito —10,11 px contra 4,16— y toda la prosa del juego se leía suelta. Es
   la única de las cuatro que lo hace y no hay forma de separarlo desde CSS.

   Bajar la regla a las superficies de dato tampoco alcanza, porque acá la
   etiqueta y el número viven en el mismo elemento: «Tiros lejanos 1» es una
   fila sola. El detalle entero está en `DESIGN.md`, bajo la Regla de la Cara
   Compatible. No se vuelve a abrir esta puerta.

   Y LA CARA DE FM26 YA TIENE NOMBRE, aunque no sirva para copiarla: son DOS.
   `FM Universe`, un encargo de Nomad Studio con la fundición Pangram Pangram
   sobre la familia Formula, que no está a la venta; y `ABC Social` de Dinamo
   para el texto. Se midieron las dos en las páginas de muestra de sus
   fundiciones el 20/9/2026: las dos pasan la prueba del espacio, pero Formula
   no tiene eje de ancho —sus seis anchos son familias aparte— y es 20,1 % más
   ancha que la nuestra a igual altura de equis; ABC Social tiene eje 75–125 y
   es 6,7 % más ancha, pagable pero no gratis, y encima cuesta licencia.

   Se sirve desde el propio proyecto, no desde un CDN. La cadena de respaldo
   (system-ui y compañía) no tiene eje de ancho: si la cara no carga, los dos
   registros del sistema colapsan en uno y la voz de marcador desaparece sin
   avisar. Alojarla acá vuelve ese fallo imposible y hace que el juego funcione
   sin conexión.

   El ancho comprimido se queda en 78 %: el eje de TikTok arranca también en 75,
   así que el número cae en el mismo sitio. Se midió, no se supuso.
   ========================================================================== */

@font-face {
  font-family: 'TikTok Sans';
  font-style: normal;
  font-weight: 300 900;
  font-stretch: 75% 150%;
  font-display: swap;
  src: url('fonts/tiktok-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: 'TikTok Sans';
  font-style: normal;
  font-weight: 300 900;
  font-stretch: 75% 150%;
  font-display: swap;
  src: url('fonts/tiktok-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;
}

/* tokens.css */
/* ==========================================================================
   El Camino DT — Design tokens
   --------------------------------------------------------------------------
   Mundo visual: LA TRANSMISIÓN.

   El fondo es el azul-negro de un estudio de televisión deportiva, no el
   verde-negro de una pizarra. El color de canal es el VIOLETA, y se gasta
   pleno: la opción elegida no se subraya, se rellena. El magenta es la voz de
   los rótulos, como el titular de un placa. Es el mundo de FM26, que es el
   norte declarado del proyecto, leído de su propia interfaz (`referencia/
   fm26/notas.md`) y no de memoria.

   **El color dice DOS cosas distintas y no hay que mezclarlas:**

   - **Violeta = estado interactivo.** Dónde estás, qué elegiste, qué está
     activo. Es el único color que responde al dedo.
   - **Verde = valor bueno.** Una calificación alta, un atributo de élite, una
     racha ganada. No se puede pulsar; se lee. (Fue verde-LIMA hasta el 20 de
     agosto de 2026, cuando la captura de FM26 a resolución nativa mostró que
     ahí todo lo bueno va en verde de verdad. Ver la familia más abajo.)

   El sistema anterior las tenía colapsadas en un solo acento, y por eso una
   fila seleccionada y un delantero de 17 se pintaban igual. FM26 las separa
   —su calificación buena va en verde mientras el botón activo va violeta— y
   esa separación es la mejora real de este mundo, no el repintado.

   (Esta frase decía «verde oliva», leído del video comprimido. La captura
   nativa dice verde. Es la corrección que trajo el giro de la familia.)

   Regla que no cambió: el color significa algo o no se usa.
   ========================================================================== */

:root {
  /* ----------------------------------------------------------------------
     1. PRIMITIVAS — la paleta cruda. No usar directamente en componentes.
     ---------------------------------------------------------------------- */

  /* Tinta: neutro con desviación AZUL-VIOLETA. 13 pasos, porque una UI densa
     necesita muchas capas de superficie para separar sin dibujar bordes. Los
     escalones de luminancia son los mismos de siempre: lo que giró es el
     matiz, así que ningún contraste de texto se movió. */
  --ink-1000: hsl(0 0% 0%);
  --ink-950:  hsl(0 0% 3%);
  --ink-900:  hsl(0 0% 6%);
  --ink-850:  hsl(0 0% 9%);
  --ink-800:  hsl(0 0% 13%);
  --ink-750:  hsl(0 0% 17%);
  --ink-700:  hsl(0 0% 30%);
  --ink-600:  hsl(0 0% 44%);
  --ink-500:  hsl(0 0% 57%);
  /* 59 % y no 55, y la segunda vuelta enseña más que la primera. A 55 el
     `--text-muted` que sale de acá daba 4,40:1 sobre la tarjeta, contra un piso
     de 4,5: el gris con el que está escrita la mitad de las etiquetas del juego
     no llegaba. Se subió a 57 midiendo contra los fondos DECLARADOS —panel,
     tarjeta, chrome— y seguía corto, porque el fondo real de una etiqueta no es
     el token: es el token con el lavado de su fila encima. Sobre la fila par de
     la cebra y sobre el lavado violeta del seleccionado quedaba en 4,29–4,44.
     59 es el mínimo que cruza en los fondos MEDIDOS, que son los que cuentan, y
     deja nueve puntos hasta `--text-secondary`, así que la escala no se junta.
     La lección, para el próximo: el fondo se mide COMPUESTO y en la pantalla,
     no se deduce del token. */
  --ink-400:  hsl(0 0% 72%);
  --ink-350:  hsl(0 0% 73%);  /* mínimo legible sobre el relleno de tramo 2 */
  --ink-300:  hsl(0 0% 86%);
  --ink-200:  hsl(0 0% 94%);
  --ink-100:  hsl(0 0% 100%);

  /* Violeta: el color de canal. Es lo interactivo y nada más. El 500 es el
     relleno pleno del control elegido, y lleva texto BLANCO encima (5,97:1). */
  --acido-700: hsl(64 100% 20%);
  --acido-600: hsl(64 100% 30%);
  --acido-500: hsl(64 100% 50%);
  /* El paso que faltaba entre el 500 y el 400, y nació con un número: es el
     violeta más claro que todavía deja pasar el blanco —4,92 contra 4,19 del
     400—, y por eso es el que enciende el degradado de CONTINUAR al pasarle el
     dedo. Ver `--accent-degradado-hover`. */
  --acido-450: hsl(64 100% 55%);
  --acido-400: hsl(64 100% 58%);
  --acido-300: hsl(64 95% 70%);
  --acido-200: hsl(64 90% 83%);

  /* Magenta: la voz de los rótulos en versalitas, y desde el 20 de agosto de
     2026 el arranque del degradado de la acción principal. Los dos pasos
     hondos (500 y 450) existen SÓLO para eso: un rótulo en versalitas a este
     nivel de saturación no pasa contraste sobre panel, así que no se usan como
     texto en ningún sitio. */
  --hueso-500: hsl(0 0% 88%);
  /* EL MAGENTA QUE DEJA PASAR EL BLANCO, y existe porque el 500 no. Como fondo
     de un rótulo blanco el 500 da **3,59** contra un piso de 4,5, y ése es el
     fondo de la acción principal del juego: el degradado de CONTINUAR arranca
     ahí. Éste es el mismo matiz ocho puntos más oscuro: **4,63**. El 500 se
     queda donde estaba —la portada, que no le escribe blanco encima. */
  --hueso-550: hsl(0 0% 62%);
  --hueso-450: hsl(0 0% 90%);
  --hueso-400: hsl(0 0% 100%);
  --hueso-300: hsl(0 0% 94%);

  /* Verde: EL VALOR BUENO. Una calificación alta, un atributo de élite, un
     partido ganado, un gol.

     ERA VERDE-LIMA («la cal», hsl 72–80) y giró a verde de verdad el 20 de
     agosto de 2026, que era la última diferencia de paleta que quedaba con la
     fuente. En la captura del portal de FM26 a resolución nativa, todo lo bueno
     —el punto del partido ganado, la flecha que sube, la pastilla de
     rendimiento— va en un verde saturado, no en lima. El lima venía de leer un
     video comprimido de YouTube, que es la misma fuente que describía el fondo
     como «casi negro» sin poder decir de qué color era.

     EL GIRO SE MIDIÓ, no se estimó. Rotar el matiz a luminancia constante daba
     un verde menta pálido en los pasos altos (#c7fadd), que es verde en el
     nombre y blanco en la pantalla. Así que se eligió el verde que la fuente
     muestra y se COMPROBARON los ocho pares de contraste del sistema: el peor
     es la cifra de élite sobre su propio relleno, 6,17:1, sobre un piso de
     4,5:1, y ninguno baja. Lo que se pierde son entre 0,5 y 1,8 puntos de
     contraste sobre unos números que iban de 9 a 14: aire de sobra.

     El 500 es además el punto donde el giro casi no se nota en la cuenta
     —0,3716 de luminancia contra 0,3717—, que es la prueba de que la escala
     está donde tiene que estar. */
  --verde-700: hsl(150 45% 22%);
  --verde-600: hsl(148 52% 32%);
  --verde-500: hsl(146 62% 45%);
  --verde-400: hsl(145 68% 55%);
  --verde-300: hsl(144 74% 68%);
  --verde-200: hsl(143 80% 80%);

  /* Ámbar: amonestación, contrato por vencer, atención. */
  --amber-500: hsl(40 90% 52%);
  --amber-400: hsl(40 92% 62%);
  --amber-300: hsl(41 94% 74%);

  /* Arcilla: lesión, baja forma, negativo. El color de la cancha de tierra. */
  --clay-500: hsl(9 62% 47%);
  --clay-400: hsl(9 68% 57%);
  --clay-300: hsl(10 74% 70%);

  /* Naranja: TU CLUB. Es el único color del sistema que no describe un estado
     ni un valor sino una PERTENENCIA — cuál de estas veinte filas sos vos.
     Entra medido de la fuente: en el portal de FM26 el club dirigido aparece
     en naranja en la tabla, en la programación y en el resultado, mientras el
     violeta sigue marcando lo que se pulsa. Era el trabajo que acá hacía el
     violeta, y por eso una fila de tabla parecía seleccionada sin serlo. */
  --nar-500: hsl(24 92% 52%);
  --nar-400: hsl(26 95% 62%);
  --nar-300: hsl(28 96% 72%);

  /* EL CÉSPED. Entra el 20 de agosto de 2026 y da vuelta la decisión más vieja
     del sistema —«el campo se dibuja como una pizarra, no como un césped»—,
     que se sostenía en el recorte comprimido de 2025. Leído a 1:1 en el video
     de FM26, **el campo de tácticas es verde**, con dos verdes de franja y
     líneas blancas.



     Los valores NO salen del muestreo directo: el cuadro viene decodificado en
     otro espacio de color —el canal rojo sale en cero en todos los píxeles— y
     los hexadecimales del video no son los que se ven. Lo que sí se puede leer
     de ahí es la RELACIÓN: el campo es un paso más oscuro que el panel que lo
     contiene, y las líneas son blancas. Esos son los tres valores de acá, con
     la luminancia elegida para que lo que se apoya encima —camisetas de club,
     dorsales, marcas— siga leyéndose; eso sí está medido, club por club. */
/* ══════════════════════════════════════════════════════════════════════════
   LA PALETA CAMBIA EL CHROME, NO EL MUNDO (22/9/2026)
   ══════════════════════════════════════════════════════════════════════════
   «Esto queda muertísimo. No apaguemos NADA, que mantenga el espíritu de FM,
   pese a que lleguemos a cambiar paletas de colores. TODO tiene que destacar,
   resaltar.» —Alberto, con la cancha del partido al lado.

   Tenía razón y el error fue de concepto, no de número: al pasar el juego a la
   paleta ácida arrastré la CANCHA con el resto y la dejé en `hsl(0 0% 11%)`,
   o sea el mismo gris del fondo de página, con las líneas amarillas. Eso no es
   repintar: es apagar. La cancha quedó dibujada como un plano y no como un
   campo.

   Y encima pisaba una medición: el verde del césped y sus dos franjas entraron
   leídos 1:1 del video de FM26 —está escrito más arriba, en la sección del
   césped— y una paleta de chrome no tiene autoridad sobre eso.

   LA REGLA, QUE VALE PARA LA PRÓXIMA PALETA TAMBIÉN: lo que la paleta puede
   mover es la SUPERFICIE del sistema —fondos, líneas, tintas, el acento—.
   Lo que no puede tocar es el MUNDO: el césped, los colores de los 1.656
   clubes, y las familias que significan algo —verde de valor bueno, ámbar de
   aviso, arcilla de peligro, naranja de tu club—. Si una paleta apaga algo de
   eso, la paleta está mal, no el mundo.

   El césped además sube medio punto de luz y dos de saturación respecto de
   main: sobre un chrome neutro y oscuro como éste, el verde de antes quedaba
   más apagado de lo que se veía sobre el azul-noche. Es el mismo verde, puesto
   para que resalte igual contra el fondo nuevo.
   ══════════════════════════════════════════════════════════════════════════ */
  --campo:        hsl(152 44% 16%);
  --campo-franja: hsl(152 42% 19.5%);
  /* OPACA. El motor del partido le aplica su propia `globalAlpha` (0,34 para
     las líneas, 0,40 para los puntos), así que un token que ya trajera alfa se
     multiplicaría con ella y dejaría la línea en 0,14 — invisible. Quien la
     quiera translúcida desde CSS la diluye él, que es lo que hace `.cancha`. */
  --campo-linea:  hsl(0 0% 100%);
  /* EL PASTO GASTADO Y EL BARRO (24/9/2026), las dos tintas del desgaste de la
     cancha del partido: la tierra que asoma donde se pisa —el área chica, el
     punto del penal, el círculo— y lo mismo mojado. No son colores de acento
     ni de marca: son del piso, y se usan traslúcidos sobre `--campo`, así que
     el césped sigue mandando. Opacos por lo mismo que la cal: el motor les
     pone su alfa. */
  --campo-gastado: hsl(38 24% 30%);
  --campo-barro:   hsl(26 32% 14%);

  /* ----------------------------------------------------------------------
     2. SEMÁNTICAS — lo que usan los componentes.
     ---------------------------------------------------------------------- */

  /* Superficies */
  --bg-page:      var(--ink-950);
  --bg-chrome:    var(--ink-900);   /* barra de navegación */
  --bg-panel:     var(--ink-850);   /* paneles de contenido */
  --bg-row:       var(--ink-800);   /* filas, celdas elevadas */
  --bg-raised:    var(--ink-750);   /* controles sobre panel */
  --bg-hover:     hsl(0 0% 15%);
  --bg-active:    hsl(0 0% 20%);
  --bg-selected:  hsl(64 100% 50% / 0.14);

  /* Líneas. Una UI densa se ordena con hairlines, no con sombras. */
  --line-hairline: hsl(0 0% 18%);
  --line:          var(--ink-700);
  --line-strong:   var(--ink-600);

  /* EL CONTORNO DE UN CONTROL NO ES UNA LÍNEA MÁS, Y POR ESO TIENE TOKEN
     PROPIO. Un hairline entre dos filas ordena y puede ser tenue; el contorno
     de un botón es lo que dice DÓNDE está el botón, y eso WCAG 1.4.11 lo pide
     a 3:1. `--line` daba **1,32** contra el panel y `--line-strong` **1,82**:
     el botón callado prácticamente no se dibujaba, y así llegó a producción
     —«Simular toda la temporada», 3/9/2026—.

     No se tocó `--line`, y es a propósito: lo usan unas setenta reglas en
     dieciocho hojas para bordes de panel, de tarjeta y separadores, que no
     necesitan 3:1 y cambiarlos sería rehacer el aspecto del juego para
     arreglar un botón. El defecto no era el valor de `--line`: era usar la
     línea de ordenar donde hacía falta la de identificar.

     EL 51 % ESTÁ MEDIDO EN TRES VUELTAS, no elegido. Con `--ink-500` (42 %) los
     botones callados subieron de 1,23–1,32 a **2,67–2,87**: mejor y todavía
     corto, y esa es justo la altura que se ve bien y no cruza. A 47 % quedaban
     cinco por debajo, entre 2,68 y 2,94, todos sobre las superficies más claras
     —`plantel` y `mercado`—, porque el mismo borde rinde menos cuanto más claro
     es lo que tiene detrás. A 51 % cruzan todos. **El fondo se mide compuesto y
     en la pantalla, no se deduce del token**, que es la misma lección que dejó
     escrita `--ink-400` doce renglones más arriba.

     Y NO SE FUE MÁS ARRIBA A PROPÓSITO. `--ink-400` habría dado holgura de
     sobra y un contorno de 4,5, que en una pantalla de sesenta controles grita:
     el piso es 3 porque a partir de ahí se identifica el control, no porque más
     sea mejor. El hover sí va a `--ink-400`: un escalón por encima, para que
     pasar el cursor siga significando algo.

     En números, con `herramientas/barrido-contraste.html` sobre las 23
     pantallas: los hallazgos de contorno pasaron de **385 a 233**, y los 146 de
     `button.action` se fueron enteros. Lo que queda es de otras familias
     —`desp__btn`, `history__btn`, `club-chip`, `mini__btn`— y una sola de
     `.action`: el botón PLENO de `mercado`, cuyo relleno de acento da 2,68
     contra su panel. Ése no es este token y no se tocó: es el violeta de marca.
     */
  --line-control:        hsl(0 0% 58%);
  --line-control-strong: var(--ink-400);

  /* Texto */
  --text-primary:   var(--ink-100);
  --text-secondary: var(--ink-300);
  --text-muted:     var(--ink-400);
  --text-disabled:  var(--ink-500);

  /* Sobre el relleno violeta va BLANCO, no tinta. Con el acento anterior —una
     lima clara— el texto oscuro era la única salida legible; sobre el violeta
     saturado pasa lo contrario, y es además lo que hace FM26. */
  --text-on-accent: hsl(64 30% 7%);

  /* Un icono habilitado no es texto deshabilitado. Este token existe para que
     los iconos tenues pasen 3:1 incluso sobre la superficie más clara del
     sistema (--bg-raised), donde --text-disabled se queda corto. */
  --icon-quiet:     hsl(0 0% 64%);

  /* Acento: LO INTERACTIVO. Dónde estás, qué elegiste, qué está activo. */
  --accent:        var(--acido-500);
  --accent-strong: var(--acido-400);
  --accent-dim:    var(--acido-600);
  --accent-wash:   hsl(64 100% 50% / 0.13);
  --accent-wash-hi: hsl(64 100% 50% / 0.22);  /* hover del botón de acento suave */
  /* EL BORDE DEL ACENTO SUBE DE 0,45 A 0,85 DE OPACIDAD (3/9/2026). Con 0,45, el
     violeta compuesto sobre el panel del diálogo daba **1,74** contra el fondo y
     **1,70** contra su propio relleno —medido en la opción elegida de la mesa de
     `mercado`, con el alfa compuesto y las transiciones apagadas—, o sea que la
     pastilla que dice «esto es lo que hay puesto» era la que menos se dibujaba.
     El piso de WCAG 1.4.11 para el contorno de un control es 3.

     EL 0,85 ESTÁ MEDIDO EN EL DIÁLOGO Y NO ELEGIDO. La escalera entera, sobre el
     par que manda en cada criterio:

         alfa   vs relleno   vs lo de atrás
         0,45      1,70          1,74      ← lo que había
         0,75      2,48          2,68
         0,85      2,81          3,08      ← cruza con la vara de la casa
         0,95      3,16          3,53
         1,00      3,35          3,77      ← violeta OPACO

     Dos cosas que hay que llevarse de esa tabla. La primera: **ni con el violeta
     opaco se llega a 3 contra el relleno**, porque ahí es violeta sobre violeta y
     el alfa no puede arreglar eso — lo que identifica ese control es su borde
     contra la PANTALLA, que es lo que mide `barrido-contraste.html`. La segunda:
     por eso el número es 0,85 y no 0,95; con 0,95 el lavado deja de ser lavado y
     se movería el aspecto de dieciséis reglas en once hojas para ganar una
     décima en un par que no manda.

     `--accent-wash` NO se toca: el relleno sigue siendo el mismo violeta suave, y
     lo único que cambia es cuánto se dibuja el contorno. */
  --accent-line:   hsl(64 100% 52% / 0.85);   /* borde de pastilla/botón de acento */

  /* EL VIOLETA QUE ESCRIBE. Medido: como tinta de texto chico, `--accent` da
     2,56–2,95:1 y `--accent-strong` 3,51–4,05, contra un piso de 4,5. Ninguno
     de los dos llega, y se estaban usando para escribir cifras —«US$ 13M» en
     una propuesta, el dorsal en la ficha, el número del día de partido—. El
     primero de la rampa que cruza es `--acido-300`, y ésa es toda la razón por la
     que este token existe: un color que PINTA bien no sirve para ESCRIBIR, y la
     diferencia son dos escalones de la misma rampa. */
  --accent-texto:  var(--acido-300);

  /* ESTÁS ACÁ, en la NAVEGACIÓN. Magenta y no violeta, que es lo que hace FM26
     con su sección activa. Y no es un capricho de tono: son dos significados
     distintos que se pisaban. El violeta contesta «esto lo elegiste vos» —una
     formación, un filtro, una fila—; este magenta contesta «de acá cuelga lo
     que estás mirando», que no se elige, se hereda de dónde estás parado.
     Compartían color a veinte píxeles uno del otro, con dos violetas apenas
     distintos, y eso se lee como dos cosas sin saber cuáles.
     Contraste MEDIDO sobre la barra 6,32:1 y sobre panel 6,02:1; el violeta que
     había daba 4,51 y 4,30 —o sea que la subbarra estaba POR DEBAJO del piso de
     4,5 y nadie lo había medido. */
  --nav-aqui:      var(--acido-400);

  /* TU CLUB. Nunca es un estado y nunca es pulsable: dice de quién es la fila.
     Se usa en el nombre y en la marca de canto, jamás como relleno pleno — un
     bloque naranja al lado de un bloque violeta son dos acentos peleando, y el
     que gana tiene que ser el que responde al dedo. */
  --tuyo:      var(--nar-400);
  --tuyo-wash: hsl(26 95% 62% / 0.12);
  --tuyo-line: hsl(26 95% 62% / 0.55);

  /* EL DEGRADADO DE LA ACCIÓN PRINCIPAL. La única superficie con degradado del
     producto, y es una excepción declarada a la regla de mundo que los prohíbe:
     en la captura de FM26 el botón que hace pasar el tiempo va de magenta a
     violeta y es el objeto más brillante de la pantalla. No es decoración — es
     lo que separa a LA acción de cualquier otro botón de acento, que siguen
     siendo violeta pleno. Fuera del chrome, ningún degradado.

     Y EL RÓTULO SE LEE, que hasta el 8/9/2026 no. El degradado iba de
     `--hueso-500` a `--acido-500` y el rótulo es blanco de 16 en negrita, o sea que
     el piso es 4,5 y no 3: **3,59 en la punta magenta**, y la cuenta no cruza
     los 4,5 hasta el 45,5 % del ancho del botón —el rótulo empieza en el 10 %—.
     El hover estaba peor por las DOS puntas, 3,08 y 4,19, así que apoyar el
     dedo hacía el rótulo menos legible en vez de más. Diecinueve pantallas, el
     objeto más visible de todas, y ninguna vara lo había mirado: el barrido de
     contraste eximía los degradados.

     Se bajó el magenta ocho puntos —`--hueso-550`, 4,63— y el hover dejó de
     aclararse por la izquierda para encenderse por la derecha, con `--acido-450`
     (4,92). Lo que no se podía era subir el rótulo a 18,66 px para caer en el
     piso de 3: el presupuesto de la píldora son 222 px con «Te esperan 12
     tareas» adentro, y está medido en `chrome.css`. */
  --accent-degradado:       linear-gradient(96deg, hsl(54 100% 42%) 0%, hsl(64 100% 52%) 100%);
  --accent-degradado-hover: linear-gradient(96deg, hsl(54 100% 48%) 0%, hsl(64 100% 58%) 100%);

  /* Rótulo: la etiqueta de sección en versalitas. Es el segundo acento y no
     tiene ningún otro trabajo — nunca es un estado, nunca es pulsable. */
  --label-color:   var(--hueso-300);

  /* Tintes de fondo para una cifra juzgada (calificación de partido). Se
     mantienen por debajo del 20 %: por encima, el número deja de pasar 4,5:1.
     Van en CAL, no en violeta: es un valor, no un estado. */
  --tint-good: hsl(146 52% 45% / 0.20);
  --tint-bad:  hsl(9 62% 47% / 0.20);
  /* El tercero de la rampa, que faltaba. La familia tenía el verde y el rojo
     pero no el ámbar, y el primero que necesitó marcar una advertencia con
     fondo —el futbolista puesto en venta— se lo iba a inventar en su hoja.
     Mismo 20 % y mismo matiz que `--amber-400`, para que sea el tinte DE ese
     color y no un ámbar parecido. */
  --tint-warn: hsl(40 92% 62% / 0.20);

  /* Estados semánticos */
  --warn:   var(--amber-400);
  --danger: var(--clay-400);
  --good:   var(--verde-400);

  /* Foco. Nunca se remueve, nunca es sutil. */
  --focus-ring: hsl(64 95% 70%);

  /* El velo y la sombra del modal. Existen como token porque estaban escritos
     a mano en TRES archivos con tres valores distintos —`hsl(160 22% 4%)`,
     `hsl(157 18% 4%)`, `hsl(160 20% 5%)`— que nadie eligió: son la misma idea
     copiada tres veces y desviándose. Y los tres se quedaron con el matiz
     VERDE del mundo anterior cuando la tinta giró al azul, así que el fondo
     del diálogo tiraba a verde sobre una pantalla azul.

     El velo también viste el control que se apoya sobre el retrato: el
     trabajo es el mismo —garantizar contraste sobre algo que no controlás— y
     dos tokens para un trabajo son dos valores que se separan con el tiempo. */
  --velo: hsl(0 0% 0% / 0.82);

  /* La ÚNICA sombra del sistema, y está justificada: un modal tiene que
     despegarse del plano o no se lee como modal. Cualquier otra sombra que
     aparezca es una regresión, no una excepción nueva. */
  --sombra-modal: 0 0 0 1px hsl(0 0% 34%), 0 24px 60px hsl(0 0% 0% / 0.9);

  /* ----------------------------------------------------------------------
     3. RAMPA DE ATRIBUTOS (1–20)
     --------------------------------------------------------------------
     Rampa de LUMINANCIA en un solo tono, no de matiz (rojo→verde). Dos
     razones: el ojo encuentra "lo brillante" más rápido que "lo verde", y
     no depende de distinguir rojo de verde. El número siempre acompaña,
     así que el color nunca es el único portador de significado.

     Sigue en CAL a propósito, ahora que el acento es violeta: un atributo
     no es un control. Que la rampa de calidad y el estado interactivo usen
     colores distintos es lo que permite leer una tabla de un vistazo sin
     confundir "elegido" con "bueno".
     ---------------------------------------------------------------------- */
  /* CUATRO TRAMOS Y NO CINCO, con los cortes de FM26 —16, 11 y 6— medidos en dos
     fichas oficiales sin una sola discrepancia. Lo que cambia de verdad no es el
     número de escalones: es QUÉ PESA CADA COLOR.

     La rampa vieja tenía verde en tres de sus cinco tramos, desde el 10, y eso
     MEDIDO sobre los 24.174 futbolistas del universo daba **30,3 % de verde**.
     Un color que se lleva un tercio del padrón no distingue a nadie: decía
     «bueno» de tres de cada diez. Con los cortes de la fuente el verde baja a
     **6,2 %**, que es lo que hace que un 16 salte de la tabla.

     El precio está medido y se acepta a ojos abiertos: el tramo ámbar se lleva
     el **70,9 %**. Es mucho, y es lo que hay — nuestro `nivel` es un promedio y
     los promedios se apilan en el medio: el 61 % del universo vive entre 11 y
     14. Tampoco es un cambio de naturaleza, porque el tramo mayoritario viejo
     ya se llevaba el 54,9 %. La rampa no está para repartir parejo: está para
     que salte lo excepcional.

     Los colores son NUESTROS tokens y no los hex de la captura, porque los
     nuestros están medidos contra nuestros fondos. Da casi igual: el ámbar de
     FM26 (#ffb82a) da 10,46:1 sobre el panel y `--amber-400` da 10,54 — son el
     mismo color. El que NO se puede copiar es su gris del tramo flojo:
     #6c6f78 da 3,60:1, por debajo del piso.

     Y sí, esto le da al ámbar un segundo trabajo —era «lo que apura»— pero lo
     gana bien: es el color de «esto está bien sin ser excepcional», que es
     exactamente lo que dice un 13. Ver la Regla de la Rampa en `DESIGN.md`.
     ---------------------------------------------------------------------- */
  --attr-1-fill: transparent;                     /*  ≤5    flojo   */
  --attr-1-text: var(--text-muted);
  --attr-2-fill: hsl(242 20% 20% / 0.55);         /*  6–10  normal  */
  --attr-2-text: var(--ink-200);
  --attr-3-fill: hsl(228 38% 42% / 0.20);         /* 11–15  bueno   */
  --attr-3-text: var(--amber-400);
  --attr-4-fill: hsl(150 45% 40% / 0.26);         /* 16+    élite   */
  --attr-4-text: var(--verde-400);
  /* El quinto tramo ya no existe. Se deja apuntando al cuarto por si algún
     guion viejo todavía emite `data-tier="5"`: mejor que herede el élite a que
     se quede sin relleno y sin cifra encendida. */
  --attr-5-fill: var(--attr-4-fill);
  --attr-5-text: var(--attr-4-text);

  /* LO QUE LE IMPORTA AL ROL. Una marca al canto de la fila de atributo que NO
     habla de calidad —de eso hablan los cinco tokens de arriba— sino de si ese
     atributo cuenta para el rol elegido. Son dos preguntas distintas sobre la
     misma fila y por eso llevan colores distintos: el número dice «qué tan
     bueno es» y la marca dice «si importa acá».

     Medidos de FM26: su verde es hsl(114 80% 82%) y nuestro `--verde-200` está
     a dos décimas de contraste, así que se reusa. El azul, hsl(215 89% 76%), no
     existía en la paleta y entra ahora — es el único color del sistema que no
     es ni un valor, ni un estado, ni una identidad: es una relevancia. */
  --azul-300:  hsl(215 85% 76%);
  --rol-clave:  var(--verde-200);
  --rol-sosten: var(--azul-300);

  /* LA SUPERFICIE DEL DÍA DEL PARTIDO. FM26 le da a la sección táctica un color
     de superficie propio: el panel donde se arma el equipo va sobre un TEAL
     —#036150, o sea hsl(169 94% 20%)— con un borde más claro, mientras el resto
     de la pantalla sigue en el azul-negro de siempre. El verde no está sólo en
     el dibujo del campo: está en lo que lo contiene, y el césped es otro verde
     (#114b3a, hsl 162) más apagado y menos azulado.

     El TONO se copia y la LUMINANCIA no. El teal de la fuente tiene 0,0915 de
     luminancia, seis veces la de nuestras superficies, y MEDIDO sobre él sólo
     sobrevive el texto primario: el secundario da 3,00, el apagado 2,21 y el
     ámbar 4,32. El 9 % de luminosidad es el máximo que deja pasar los cinco
     tonos de texto que usa ese panel, con el apagado en 4,63.

     Y no hace falta más para que se note, porque **lo que separa a este panel
     de los otros es el tono, no el brillo**: un teal saturado al lado de un
     azul-gris se distingue aunque los dos midan lo mismo de claros. */
  --tactico-fondo: hsl(0 0% 7%);
  --tactico-borde: hsl(0 0% 34%);

  /* LA LÍNEA, EN COLOR. FM26 pinta la etiqueta de rol de cada ficha de la cancha
     según la línea, y los matices avanzan con la posición: teal atrás, verde en
     el medio, magenta arriba, y el arquero en un gris azulado aparte. Se copian
     TAL CUAL —son los cinco valores medidos de la captura— porque con blanco
     encima cumplen todos: el peor da 5,29:1.

     Y son FONDOS DE UNA ETIQUETA DE VOCABULARIO CERRADO, no tintas de acento:
     doce puestos, once fichas, una sola pantalla. Por eso el magenta acá no
     pelea con el de la navegación ni el teal con el de la superficie táctica —
     el de la navegación es una TINTA sobre fondo oscuro y éste un RELLENO con
     texto blanco, y el táctico es una superficie de 9 % de luz contra una
     pastilla de 31 %. Si alguna vez estos colores salen de la cancha, esta
     excepción deja de valer y hay que rediscutirla. */
  --linea-por: hsl(240 20% 29%);
  --linea-def: hsl(175 97% 24%);
  --linea-med: hsl(149 80% 26%);
  --linea-del: hsl(321 76% 31%);

  /* ----------------------------------------------------------------------
     4. TIPOGRAFÍA
     --------------------------------------------------------------------
     Una sola familia. Anek Latin es variable en peso Y ancho: el ancho
     condensado hace de voz de marcador (nombres, dorsales, resultados) y el
     ancho normal carga los datos. Una familia, dos registros.

     Es la tercera cara del proyecto —Archivo, Asap y ésta— y la primera que se
     eligió MIDIENDO en vez de describiendo. La cara de FM26 no se identificó y
     probablemente sea un encargo, así que no hay forma honesta de decir «es
     ésta»; lo que sí se puede hacer es medir a las candidatas contra el propio
     juego. Doce familias de Google Fonts cumplen las tres condiciones duras
     (eje de ancho hasta 75, peso 400–700, cifras tabulares), y las dos que más
     se parecen a la fuente mirándolas —Zalando Sans y TikTok Sans— rompen la
     pantalla: sus cifras tabulares piden entre 10 % y 22 % más de ancho, y esto
     es una pared de números en columna. Anek cuesta cero: mismo alto de ficha,
     misma barra. El detalle y la tabla están en `fonts.css`.

     Lo que NO cambió con la cara: los ocho tamaños, los dos registros de ancho
     y el 78 % del comprimido. Se comprobó uno por uno — el eje de Anek arranca
     en 75, igual que el de Asap, y a 78 % la voz de marcador mide 0,742 de la
     normal, que es la misma distancia que había.
     ---------------------------------------------------------------------- */
  /* --------------------------------------------------------------------
     Y EL RESPALDO SE ELIGIÓ MIDIENDO, como la cara. Hasta el 7/9/2026 el
     primero de la lista era `ui-sans-serif` —la cara de sistema— y eso hacía
     que cada recarga se viera moverse: `fonts.css` pide `font-display: swap`,
     así que el primer pintado sale con el respaldo y la línea se REACOMODA
     cuando llega TikTok Sans. Medido en el DOM sobre la barra de secciones a
     18px/700, con el `letter-spacing` de la barra puesto:

       TikTok Sans                          495,93 px
       ui-sans-serif (la de sistema)        461,33 px   → 34,6 px · 7,5 %
       Helvetica Neue                       495,35 px   → 0,58 px · 0,12 %
       Arial                                493,51 px   → 2,4 px  · 0,49 %

     Los seis rótulos se corrían 34,6 px solos, sobre una pantalla por lo demás
     quieta y con la superficie de trabajo todavía en suspenso. Poniendo
     delante una cara métricamente igual, el reacomodo baja a medio píxel y
     deja de verse — sin `size-adjust` y sin una cara de respaldo inventada: la
     que ya está en la máquina mide lo mismo.

     EL ORDEN ES POR MÉTRICA Y NO POR GUSTO: Helvetica Neue (macOS), Arial
     (Windows y macOS), Segoe UI y Roboto detrás. Las genéricas quedan al
     final, que es donde tienen que estar — son la red por si no hay ninguna.

     LO QUE MEDÍ Y LO QUE NO, dicho para el que lo revise: los cuatro números
     de arriba son de macOS/Chrome. Windows y Android están RAZONADOS por las
     métricas conocidas de Arial y Roboto, no medidos acá. Si alguna vez hay
     una máquina de esas a mano, la vara es la misma: el ancho de esa cadena
     contra el de TikTok Sans.

     Y NO CAMBIA NADA DE LO QUE `fonts.css` DECIDIÓ: ninguna de estas caras
     tiene eje de ancho, igual que las genéricas que había, así que el argumento
     de alojar la cara en el proyecto —que sin ella los dos registros del
     sistema colapsan en uno— sigue valiendo exactamente igual.
     -------------------------------------------------------------------- */
  --font-ui: 'TikTok Sans', 'Helvetica Neue', Arial, 'Segoe UI', Roboto, ui-sans-serif, system-ui, sans-serif;

  /* Escala fija en rem, ratio ~1.15. En producto la escala fluida molesta:
     el usuario mira siempre al mismo DPI y a la misma distancia.

     La escala subió DOS veces, y las dos por el mismo motivo. La primera
     (10-11-12-13-15 → 11-12-13-14-16) fue medir la fuente y descubrir que FM26
     es menos denso de lo que este sistema creía. La segunda es ésta —un
     escalón más, y esta vez TAMBIÉN en los tres tamaños de arriba— y sale de
     mirar el juego en la pantalla en la que se juega de verdad: en un monitor
     ancho, 14px de dato base y 11 de versalita se leen como letra chica, y la
     densidad deja de ser una virtud cuando hay que acercarse. Los tres de
     arriba suben con el resto porque la jerarquía es RELATIVA: dejar la
     navegación en 18 mientras el cuerpo pasa a 15 le come el escalón que la
     hacía navegación.

     Los pasos siguen siendo los mismos ocho y ninguna pantalla estrenó un
     tamaño propio: agrandar la tipografía es mover ESTA lista, y si una
     pantalla se rompe se arregla su composición, no su `font-size`. */
  --fs-2xs: 0.8125rem;  /* 13px — etiquetas micro en versalitas */
  --fs-xs:  0.875rem;   /* 14px — etiquetas */
  --fs-sm:  0.9375rem;  /* 15px — datos secundarios */
  --fs-md:  1rem;       /* 16px — dato base */
  --fs-lg:  1.125rem;   /* 18px — títulos de panel, valores destacados */
  --fs-xl:  1.3125rem;  /* 21px — la navegación primaria */
  --fs-2xl: 1.625rem;   /* 26px */
  --fs-3xl: 2.125rem;   /* 34px — nombre del jugador */

  /* 52px — EL CUERPO EDITORIAL, y el único escalón que no usa ninguna pantalla
     de gestión: es el titular de la portada de noticias y el marcador de su
     apertura. Vive acá y no en `portada.css` justamente por la regla de arriba
     —agrandar la tipografía es mover ESTA lista, no estrenar un tamaño en una
     hoja—, y está declarado como lo que es: una voz, no un tamaño suelto. Es
     el mismo registro de `.tapa__titular` en `home.css`, un escalón más chico
     porque adentro del juego el titular convive con el chrome del club. */
  --fs-editorial: 3.25rem;

  --lh-tight: 1.15;
  --lh-snug:  1.3;
  --lh-body:  1.5;

  --tracking-label: 0.08em;  /* versalitas necesitan aire */
  --tracking-tight: -0.01em;

  /* Los DOS registros de ancho. Sólo existen estos dos: el comprimido es la
     voz de marcador (nombres, dorsales, cifras grandes, reloj) y el normal
     carga todo lo demás. Un tercer valor intermedio no se lee como registro,
     se lee como inconsistencia — 84 %, 88 % y 92 % son el mismo ancho con
     tres nombres. Se aplican con font-stretch, que mapea al eje wdth.

     78 % y no 76 %: el eje de Asap arrancaba en 75 y el de Archivo en 62, así
     que el mismo número no cae en el mismo sitio del eje. A 76 el marcador
     quedaba a un punto del extremo y se leía aplastado. Anek arranca también en
     75, así que el 78 se quedó donde estaba — comprobado, no supuesto: a 78 %
     un nombre largo mide 0,742 de lo que mide a 100, la misma proporción que
     daba Asap. */
  --wd-condensed: 78%;
  --wd-normal: 100%;

  /* ----------------------------------------------------------------------
     5. ESPACIADO — escala apretada. Una UI densa vive entre 2px y 24px.
     ---------------------------------------------------------------------- */
  /* ----------------------------------------------------------------------
     LA ESCALA DEL SITIO ENTERO
     ----------------------------------------------------------------------
     Un solo número que agranda o achica TODO: la letra, los espacios, los
     iconos, los escudos, las líneas de un píxel y los modales. Se aplica con
     `zoom` sobre `:root`, en `app.css`.

     Por qué `zoom` y no subir la escala tipográfica: los tamaños de letra son
     rem y escalarían solos, pero el resto del sistema NO. Hay unos setecientos
     valores en píxeles repartidos entre las veintiocho hojas —los 22 px de
     renglón, los 16 del icono, los 42 del escudo grande, los hairlines— y
     tocarlos de a uno rompería justamente lo que hace que esto se vea como una
     sola cosa: las proporciones entre ellos. Con `zoom` no se toca ninguno y
     todas las relaciones se conservan exactas.

     LO QUE ESTO LE HACE A DESIGN.md: la interfaz estaba medida 1:1 contra
     FM26, y con esto pasa a estar medida 1:1 y mostrada un 4 % más grande. Las
     proporciones del documento siguen valiendo todas; lo que cambia es el
     tamaño con el que se ven. Si alguna vez hay que volver a comparar contra
     los recortes de `referencia/fm26/`, se pone en 1 y se compara.

     Comprobado que el `<dialog>` también escala: el top layer hereda el zoom
     del root, así que los modales crecen con todo lo demás y no hace falta
     tocarles el ancho.

     ERA 1,08 Y BAJÓ A 1,04 EL 31/8/2026, y el motivo fue mirar el plantel: la
     pantalla más densa del juego —dos columnas, veintiocho renglones de tabla y
     una cancha al lado— pedía rodar 476 px a 1440×900. La escala no es lo que
     cierra esa cuenta, pero sí lo que la achica, y **lo que devuelve no es
     scroll sino CONTENIDO**: a 1440×900 la tira de estadísticas del plantel
     pasa de dos renglones a uno, entran dos futbolistas más en la lista y entra
     una columna más de la tabla. Medido, en píxeles de maquetación:

       ventana      con 1,08        con 1,04
       1440×900     1333×833        1384×865
       1920×1080    1777×999        1846×1038
       375×812       347×751         360×781

     LO QUE SE PAGA es que todo se ve un 3,7 % más chico, y eso hay que decirlo
     en vez de esconderlo: es la mitad de lo que se había ganado subiendo a
     1,08. La excepción de contraste que este sistema tiene declarada —el `DT`
     del lockup, 3,28:1, que cumple sólo por ser TEXTO GRANDE— sigue en pie: se
     pinta a 23,9 px contra los 18,66 que pide la regla, y la mide el porte de
     `.tapa__marca`, no esta escala.

     Y NO ES UN NÚMERO QUE SE TOQUE SOLO: cada décima mueve el alto y el ancho
     de maquetación de las veinticinco pantallas a la vez, o sea todos los
     umbrales medidos contra la ventana. Bajarla da MÁS sitio, que es la
     dirección barata; subirla es la que rompe.

     QUÉ NÚMEROS DE LAS HOJAS ENVEJECEN CON ESTO, dicho una vez acá en vez de
     fingir un barrido por las veintiocho: los que salen de dividir una VENTANA
     por la escala —«a 1440 la fila tiene 1.333 de maquetación», el alto útil de
     una pantalla que no rueda— se mueven un 3,7 % y quedan escritos contra
     1,08. Los que describen el CONTENIDO o un valor fijo del CSS —el piso de
     386 de la cancha, los 47,2 de una ficha, los 128,05 de la cabecera de la
     portada— no se mueven: son píxeles de maquetación puestos por la hoja, no
     por la ventana. Las menciones que enseñaban a dividir por «1,08» pasaron a
     nombrar el token en esta misma tanda, para que la próxima décima no las
     vuelva a dejar mintiendo. */
  /* BAJÓ DE 1,04 A 0,88 EL 21/9/2026, Y ES EL CAMBIO MÁS GRANDE DE ESTA TANDA.
     --------------------------------------------------------------------------
     Alberto pidió la interfaz de FM26 y durante tres vueltas le entregué piezas
     —el riel, la banda de cabecera, la versalita, dos paneles nuevos— y las
     tres veces contestó lo mismo: «sigue igual». Tenía razón las tres. Lo que
     separa a esa referencia de este juego no era ninguna de esas piezas: es la
     DENSIDAD. Un gestor se lee como un gestor cuando entra mucho en pantalla.

     Medido en el Portal, con la misma partida y la misma ventana: a 1,04 la
     tabla de Torneos muestra 8 clubes; a 0,86, diecisiete. El resto de la
     pantalla se aprieta en la misma proporción y recién ahí se parece.

     POR QUÉ 0,88 Y NO 0,86. El boceto que Alberto aprobó tiene una base
     efectiva de 12,9 px (13,5 × 0,959). Este juego tiene base 16, así que
     igualarlo exacto pedía 0,81 —y 0,81 es dejar la letra en 13 px, que es
     justo lo que FM dice en su propia página haber ido a CORREGIR: «unreadable
     font sizes». 0,88 deja la base efectiva en 14,1 px: mucho más denso que
     antes y todavía legible. Se prefiere quedarse del lado de la legibilidad.

     LO QUE ARRASTRA, y por eso se mira dos veces antes de moverla: `zoom` no
     toca las unidades de ventana ni las media queries. Cada umbral escrito en
     píxeles de ventana —los cortes del chrome, los dos anchos del riel— vale
     ahora para MÁS contenido del que valía, así que se vuelven a medir, no se
     dan por buenos. Y cualquier cuenta que mezcle `getBoundingClientRect()` con
     un valor de hoja tiene que dividir por este token, nunca por un número
     escrito a mano. */
  /* 0,92 DESDE EL 29/9/2026, y la subió Alberto: «escudos y textos un poco más
     grande en todo el sitio, please». Es la misma perilla y el mismo motivo por
     el que existe —la legibilidad contra la densidad—, movida un escalón hacia
     el lado de leer: la base efectiva pasa de 14,1 a 14,7 px. El techo de
     0,914 del escudo del afiche —ver abajo— se levantó en el mismo cambio con
     la línea que estaba propuesta en `inicio.css`. */
  --escala-sitio: 0.92;

  /* EL ALTO DE LA VENTANA, MEDIDO DESDE ADENTRO DEL ZOOM. Es el token que
     tienen que usar todas las pantallas que se miden contra la ventana, y no
     `100dvh` a secas.

     Por qué: `zoom` agranda lo que se dibuja, pero NO toca las unidades de
     ventana. Adentro del subárbol escalado `100dvh` sigue valiendo los píxeles
     de la ventana y después se pinta un 8 % más grande, así que una pantalla
     de `height: 100dvh` mide un 4 % MÁS que la ventana. Con `overflow: hidden`
     —que es como se escribe «esta pantalla no se baja»— ese 8 % de abajo no se
     recorta: desaparece, y con él lo que viva ahí. Fue exactamente lo que se
     llevó el botón de empezar del selector de clubes y el de seguir del
     sorteo, que son los dos únicos controles que hacen avanzar esas pantallas.

     Dividir por la escala deshace la cuenta: el resultado se pinta con el zoom
     y vuelve a dar el alto real de la ventana. Con la escala en 1 la división
     no hace nada, así que el token sigue siendo correcto si algún día se
     compara 1:1 contra la fuente. */
  --alto-ventana: calc(100dvh / var(--escala-sitio));

  --sp-1: 2px;
  --sp-2: 4px;
  --sp-3: 6px;
  --sp-4: 8px;
  --sp-5: 12px;
  --sp-6: 16px;
  --sp-7: 20px;
  --sp-8: 24px;
  --sp-9: 32px;

  /* ----------------------------------------------------------------------
     6. FORMA Y MOVIMIENTO
     ---------------------------------------------------------------------- */

  /* Radios de LA TRANSMISIÓN: una placa de televisión tiene la esquina
     redonda. Subieron un escalón entero contra el sistema anterior —que era
     casi recto— porque medidos sobre la fuente los de FM26 rondan los 8px en
     tarjeta y los 6 en control. Lo que NO subió es el radio de la fila de
     dato: una cápsula de 12px sobre un renglón de 22 rompe la lectura
     vertical de la columna, y esa regla no la cambia ningún norte. */
  --r-hair: 1px;   /* pips, barras y banderas: casi recto, sólo mata el pixel */
  --r-xs: 3px;
  --r-sm: 5px;
  --r-md: 8px;
  --r-lg: 12px;
/* EL RADIO DE UNA TARJETA, QUE YA NO ES EL DE UN BOTÓN (21/9/2026, pedido de
   Alberto: «que sean un poco más redondas»). Las tarjetas compartían `--r-md`
   con los controles, y son dos cosas de escalas distintas: en una caja de 500
   px 8 px de radio se leen como una esquina recta, y en un botón de 28 px de
   alto 14 se leerían como una pastilla. Un token propio deja mover el de las
   cajas sin tocar el de los mandos, que era lo que impedía subirlo. */
  --r-tarjeta: 14px;
  --r-pill: 999px;
  /* EL RADIO DE UN BOTÓN (8/10/2026, Alberto: «unificá los botones en todo el
     sitio»): todo lo que es BOTÓN va en píldora —las acciones, los botones,
     los desplegables y los botones propios de cada pantalla—, en una sola
     regla al final de `app.css`. Lo que no es un botón aunque se toque —una
     solapa, un selector de segmentos, una tarjeta de opción, una fila, un
     dorsal, una ficha de la cancha— conserva su esquina: en píldora se
     confundiría con un botón. */
  --r-boton: var(--r-pill);

  /* --------------------------------------------------------------------------
     EL EJE Z
     --------------------------------------------------------------------------
     La escala existía de hecho —cero números mágicos en todo el sistema— pero
     vivía repartida a mano en cuatro hojas, y los cuatro 60 coincidían por
     disciplina. Tokenizada el 25/8/2026, la escalera es la que ya era:

       contenido (1-3, apilado local, se queda en cada hoja)
         < barra pegajosa < flotantes del chrome (menú, buscador, subnav)
         < desplegable de controles < globo del title

     El desplegable va por encima de TODO lo del chrome porque se abre adentro
     de diálogos modales; el globo, por encima del desplegable, porque un
     title se lee hasta sobre un panel abierto. */
  --z-chrome: 20;
  --z-flotante: 60;
  --z-desplegable: 90;
  --z-globo: 95;

  /* Producto: el movimiento comunica estado, nunca decora. 120–200ms. */
  --ease: cubic-bezier(0.2, 0, 0, 1);
  --dur-fast: 120ms;
  --dur: 180ms;

  /* Cambiar de pantalla y salir a la cancha son dos distancias más largas que
     un cambio de estado, y necesitan su propio par. La curva de llegada frena
     hasta casi detenerse: una pantalla que aterriza no rebota. */
  --ease-entrada: cubic-bezier(0.16, 1, 0.3, 1);
  --dur-pantalla: 240ms;  /* de una pantalla a la siguiente */
  --dur-escena: 420ms;    /* los reflectores sobre el campo, al empezar */

  /* Y LA CURVA DE LO QUE SE VA, que es la de llegada al revés y no la misma.

     Hasta el 1/9/2026 el sistema sólo sabía LLEGAR. El panel del desplegable se
     borraba del DOM de un fotograma a otro, y los cinco modales se apagaban
     igual: de las dos mitades de cada interacción, la de abrir estaba animada y
     la de cerrar era un corte. Ésa era la causa de fondo de que una interfaz
     con transiciones en todos lados se sintiera seca — no le faltaba
     movimiento, le faltaba la mitad del que ya tenía.

     Arranca despacio y ACELERA, que es lo contrario de `--ease-entrada`: lo que
     llega frena hasta apoyarse, lo que se va se saca de encima. Y lo que dura
     es `--dur-fast` y nunca `--dur-pantalla` —la salida es más corta que la
     llegada—, porque una salida lenta no se lee como calma sino como espera. */
  --ease-salida: cubic-bezier(0.4, 0, 1, 1);

  /* LA GRAMÁTICA DE LA LLEGADA (11/10/2026, «más en cascada»). Una sola para
     todo el sitio: la usan la llegada de cada pantalla, las solapas y las
     vistas internas (`cascada()` en `movimiento.js`) y las entradas propias
     de las hojas que todavía las tienen. Cada pieza tarda `--mov-pieza`, la
     siguiente sale `--mov-desfase` después, a partir de la pieza número
     `--mov-tope` llegan todas juntas, y suben `--mov-distancia`. Con ocho
     escalones la última pieza aterriza a los ~590 ms; lo que se ve armarse
     son los primeros 300–450. */
  --mov-pieza: 340ms;
  --mov-desfase: 32ms;
  --mov-tope: 8;
  --mov-distancia: 10px;
  --mov-curva: var(--ease-entrada);
  /* Lo que tarda en irse la pantalla de antes, encima de la nueva. */
  --mov-cruce: 260ms;

  /* ----------------------------------------------------------------------
     7. LOS DOS RITMOS DE FILA
     --------------------------------------------------------------------
     El sistema anterior tenía uno solo, 22px, y lo aplicaba a todo. Medido
     sobre FM26, eso es cierto para las TABLAS y falso para las listas que se
     leen: su bandeja respira al doble. Son dos trabajos distintos —escanear
     treinta números contra leer cinco titulares— y ahora tienen dos alturas.

     Si una pantalla nueva no sabe cuál le toca, la pregunta es: ¿esto se
     escanea en columna o se lee de a uno?
     --------------------------------------------------------------------
     La fila de TABLA se queda en 22px con el cuerpo a 14: la densidad alta de
     FM26 está justamente ahí, y a 1,3 de interlínea el texto entra. La de
     LECTURA sube a 52, que es donde su bandeja respira. */
  /* SE QUEDA EN 22 aunque la escala haya subido dos escalones, y no es
     descuido: con el cuerpo en 16px la caja de texto mide 20,8 y entra —lo que
     no entra es la ficha del jugador. Probado: a 24, la ficha pasa a medir
     1.029px y se lleva puesto el «entra en 1600×1000 sin scroll» que esta guía
     declara, porque son catorce filas de atributo por columna y dos píxeles
     cada una son exactamente los veintiocho que sobran. La fila de tabla es la
     pieza más apretada del sistema y ése es su trabajo. */
  --row-h: 22px;        /* TABLA: atributos, clasificación, programación */

  /* LOS DOS RITMOS DE `.data-table`, MEDIDOS Y NO ELEGIDOS.
     ----------------------------------------------------------------------
     `--row-h` es honesto para lo que usa: la fila de atributo, la del once y
     las barras del buscador miden 22 de verdad. Lo que NUNCA lo usó es
     `.data-table`, y por eso sus once tablas se habían abierto solas de 27,5 a
     46 px —un abanico de 18,5— sin que ninguna pantalla lo decidiera: el alto
     salía de lo más alto que hubiera adentro más el relleno que cada hoja
     hubiera puesto.

     Medidas las once, no era un abanico sino DOS GRUPOS, y el corte es de
     contenido: las de texto y números caían entre 27,5 y 34,7, y las que
     llevan un control adentro —un botón, un desplegable— entre 45,8 y 46. El
     segundo grupo ya estaba de acuerdo consigo mismo con dos décimas de
     diferencia; el que no, era el primero.

     · 32 sale de FM26, medido en sus dos tablas densas de la misma captura por
       dos caminos —los atributos de la ficha y las estadísticas de temporada—:
       32,0 y 31,9 normalizados a 1920. Ver `referencia/fm26/notas.md`.
     · 46 es NUESTRO número y se queda: `entrenamiento.css` ya tiene escrito por
       qué —«un botón de 20 dentro de una fila de 22 no deja aire arriba ni
       abajo»— y forzarlo a 32 sería apretar lo único que hay que tocar con el
       dedo. */
  --fila-tabla: 32px;          /* texto y números */
  --fila-tabla-control: 46px;  /* la que lleva un botón o un desplegable */

  /* Y LA MISMA PREGUNTA, UN PISO MÁS ABAJO: ¿SE BARRE O SE LEE?
     ----------------------------------------------------------------------
     `--row-h` es el renglón que se BARRE: una columna de treinta y seis
     atributos o de seis rieles, que el ojo recorre en vertical buscando uno.
     Ahí 22 px es el trabajo del renglón y por eso el token existe.

     Pero la fila del once no se barre: se LEE, renglón por renglón, veintitrés
     apilados en la columna más angosta de la pantalla con puesto, dorsal,
     apellido, medidor y nota. `partido.css` ya lo tenía escrito y ya lo había
     resuelto —«a 22px con 2px entre medio el bloque deja de tener renglones y
     pasa a ser un muro»— con un **27 escrito a mano**, que es lo único que
     faltaba: el número estaba razonado y no estaba en el sistema, así que
     `--row-h` decía 22 y la fila medía 27 sin que el token se enterara.

     Es la misma forma que la de arriba y la misma que FM26: DOS ritmos, y el
     corte no es de tamaño sino de para qué está la fila. Medido ese día, las
     cuatro formas que comparten «la fila de 22px» miden 22 (`.attr`), 22
     (`.thr`), 20 (`.cell`, que no es una fila sino una casilla cuadrada) y 27
     (`.lineup__row`). Nunca compartieron el relleno, y resulta que tampoco
     compartían la altura. */
  --fila-lectura: 27px;        /* la fila que se lee de a una, no se barre */
  /* Subió de 56 a 62 el 20 de agosto de 2026, medido sobre la captura del
     portal de FM26 a resolución nativa: sus filas de bandeja miden 62 y el
     avatar 40. Los 56 venían de un recorte de video comprimido, que es la
     misma fuente que decía que el fondo era «casi negro» sin poder decir de
     qué color. La fila de TABLA no acompaña y sigue en 22: son dos ritmos
     distintos y ésa es justamente la regla. */
  --row-lectura: 62px;  /* LISTA: bandeja, resultados, cualquier titular */

  /* El primer piso del chrome lo manda el ESCUDO, que en FM26 es lo más
     grande de la barra (~90px sobre 1920). A nuestro ancho de trabajo son 60,
     y una fila de 48px no lo contiene: sube a 76. */
  --chrome-h: 76px;
  --subnav-h: 32px;
}

/* ==========================================================================
   LA ESCALA, ELEGIDA POR EL QUE JUEGA (22/9/2026)
   --------------------------------------------------------------------------
   `--escala-sitio` arriba vale 0,88 y ese número lo eligió Alberto el 21/9
   persiguiendo la densidad de FM26. El bloque de allá arriba cuenta la pelea
   entera y termina en una frase que es justo la que abre esta puerta: «0,81 es
   dejar la letra en 13 px, que es lo que FM dice haber ido a corregir… se
   prefiere quedarse del lado de la legibilidad».

   Esa preferencia es correcta PARA UN DEFECTO, y un defecto es una apuesta
   sobre alguien que no conocés. El primer deep dive de FM27 —22/9/2026— vende
   exactamente la salida: una escala que se ajusta a cómo juega cada uno. Al que
   mira de cerca en un monitor grande le sobra legibilidad y le falta tabla; al
   que juega en una portátil le pasa al revés. Los dos tienen razón y no hay un
   número que los contente.

   TRES PASOS Y NO UN DESLIZADOR, por el mismo argumento que este sistema usa
   para los dos registros de ancho: los valores intermedios no se leen como una
   elección, se leen como ruido. Cada paso mueve la base efectiva lo bastante
   como para verse.

     data-escala      escala   base efectiva   qué es
     ---------------  ------   -------------   ------------------------------
     "comoda"          1,00      16,0 px       la base del sistema, 1:1 contra
                                               los recortes de referencia/fm26
     (sin atributo)    0,88      14,1 px       LO DE HOY. El que nunca toque
     o "normal"                                esto no ve ningún cambio.
     "densa"           0,81      13,0 px       la densidad exacta del boceto
                                               que Alberto aprobó (13,5 × 0,959)

   POR QUÉ 0,81 SE OFRECE AUNQUE SE HAYA RECHAZADO COMO DEFECTO. No es la misma
   decisión: rechazarlo como defecto es elegir por todos, ofrecerlo es que lo
   elija el que lo quiere. El renglón de FM sobre «unreadable font sizes» habla
   de una letra que el jugador no pidió, no de una que fue a buscar.

   LO QUE ARRASTRA, y está dicho igual arriba: `zoom` NO toca las unidades de
   ventana ni las media queries. Cada umbral escrito en píxeles de ventana vale
   ahora para tres cantidades de contenido distintas. Eso NO se da por bueno: lo
   mide `herramientas/vara-escala.mjs`, que recorre las pantallas a los tres
   pasos y a los anchos de trabajo buscando desborde y controles que se caen
   fuera de `--alto-ventana`. Antes de mover un número de acá, se corre.

   EL ATRIBUTO LO PONE `scripts/puerta.js` ANTES DEL PRIMER PINTADO, y va ahí y
   no en un archivo propio porque es el único guion que las 85 páginas cargan en
   la cabecera. Si no cargara, no hay atributo y queda 0,88: el juego se ve como
   hoy. Un defecto que es el estado de ayer no es un defecto.

   --------------------------------------------------------------------------
   EL TECHO DE 0,914, QUE NO LO PONE LA LETRA SINO EL ESCUDO
   --------------------------------------------------------------------------
   Lo midió la sesión del módulo de noticias y está comprobado acá: los escudos
   son PNG de 256 px de lado (`assets/escudos/`, 1.677 archivos). En Retina cada
   píxel CSS son dos físicos, y encima va esta escala, así que un escudo de
   ancho W se dibuja a `W × escala × 2` físicos. Pedirle más de 256 al archivo
   es lo que se ve como pixelado.

     pieza             ancho    escala máxima
     ----------------  ------   -------------
     afiche            140 px      0,914      ← el que manda
     pizarra            84 px      1,524
     pizarra angosta    64 px      2,000

   El afiche lo decide todo: su `width: 140px` (`styles/inicio.css:1277`) se
   eligió CONTRA este techo con la escala en 0,88, y deja diez píxeles de
   margen. O sea que los dos escalones de abajo —0,88 y 0,81— pasan, y
   **"comoda" (1,00) rompe el escudo del afiche** tal como está la hoja hoy.

   POR ESO «COMODA» ESTÁ DECLARADA PERO EL CONTROL NO EXISTE. La escalera entera
   queda escrita porque el mecanismo es el mismo para los tres; lo que falta
   antes de ofrecerle 1,00 a nadie es una línea en `inicio.css` que le saque a
   ese ancho la dependencia del número:

       width: min(140px, calc(128px / var(--escala-sitio)));

   A 0,88 da `min(140, 145,5)` = 140 —idéntico a hoy, sin cambio visible— y a
   1,00 da 128, que se dibuja a 256 físicos justos. Es zona de otra sesión y
   está propuesta, no aplicada. **Mientras esa línea no esté, "comoda" no se
   ofrece.**

   Y LA VARA QUE LO CAZA YA EXISTE: `herramientas/vara-escudos-sin-pixelar.mjs`,
   19 pantallas a DPR 2. Mide con la escala que tenga la hoja, así que con el
   atributo puesto se la puede correr escalón por escalón.
   ========================================================================== */
html[data-escala="comoda"] { --escala-sitio: 1; }
html[data-escala="normal"] { --escala-sitio: 0.92; }
html[data-escala="densa"]  { --escala-sitio: 0.81; }

