/* ==========================================================================
   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(245 35% 4%);
  --ink-950:  hsl(244 32% 6%);
  --ink-900:  hsl(243 28% 8.5%);
  --ink-850:  hsl(243 25% 11%);
  --ink-800:  hsl(242 22% 14%);
  --ink-750:  hsl(242 20% 17%);
  --ink-700:  hsl(241 18% 21%);
  --ink-600:  hsl(240 15% 30%);
  --ink-500:  hsl(240 12% 42%);
  /* 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(239 12% 59%);
  --ink-350:  hsl(239 12% 60%);  /* mínimo legible sobre el relleno de tramo 2 */
  --ink-300:  hsl(238 14% 68%);
  --ink-200:  hsl(237 16% 82%);
  --ink-100:  hsl(236 20% 93%);

  /* 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). */
  --vio-700: hsl(273 70% 30%);
  --vio-600: hsl(273 72% 40%);
  --vio-500: hsl(273 75% 53%);
  --vio-400: hsl(273 80% 62%);
  --vio-300: hsl(275 85% 72%);
  --vio-200: hsl(280 90% 82%);

  /* 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. */
  --mag-500: hsl(300 82% 52%);
  --mag-450: hsl(300 88% 60%);
  --mag-400: hsl(292 85% 66%);
  --mag-300: hsl(292 91% 73%);

  /* 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. */
  --campo:        hsl(152 42% 15%);
  --campo-franja: hsl(152 40% 18%);
  /* 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%);

  /* ----------------------------------------------------------------------
     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(242 22% 16%);
  --bg-active:    hsl(242 22% 19%);
  --bg-selected:  hsl(273 70% 55% / 0.16);

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

  /* 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(0 0% 100%);

  /* 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(240 12% 52%);

  /* Acento: LO INTERACTIVO. Dónde estás, qué elegiste, qué está activo. */
  --accent:        var(--vio-500);
  --accent-strong: var(--vio-400);
  --accent-dim:    var(--vio-600);
  --accent-wash:   hsl(273 70% 55% / 0.14);
  --accent-wash-hi: hsl(273 70% 55% / 0.24);  /* hover del botón de acento suave */
  --accent-line:   hsl(273 75% 60% / 0.45);   /* 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 `--vio-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(--vio-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(--mag-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. */
  --accent-degradado:       linear-gradient(96deg, var(--mag-500) 0%, var(--vio-500) 100%);
  --accent-degradado-hover: linear-gradient(96deg, var(--mag-450) 0%, var(--vio-400) 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(--mag-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: var(--vio-300);

  /* 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(245 35% 3% / 0.72);

  /* 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 24px 60px hsl(245 40% 2% / 0.6);

  /* ----------------------------------------------------------------------
     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(169 80% 9%);
  --tactico-borde: hsl(172 45% 32%);

  /* 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.
     ---------------------------------------------------------------------- */
  --font-ui: 'TikTok Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe 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 */

  --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. */
  --escala-sitio: 1.04;

  /* 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;
  --r-pill: 999px;

  /* --------------------------------------------------------------------------
     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);

  /* ----------------------------------------------------------------------
     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;
}
