/* ═══════════════════════════════════════════════════════════════════════════
   GRID · hoja de MARCA (landing + barra + pie)
   ---------------------------------------------------------------------------
   Se carga DESPUÉS de sistema.css y solo pisa tres cosas: la barra superior, el
   pie y la portada. Todo lo que es la aplicación del torneo —tablero, tabla,
   horario, mesa— sigue gobernado por sistema.css y no se toca. Por eso casi
   todo aquí cuelga de `body.ruta-inicio`.

   Tres decisiones dan el carácter, y no son el color:
     1. Dos familias con trabajos distintos: Montserrat habla, JetBrains Mono
        instrumenta (rótulos, cifras, metadatos). Saira (negra, inclinada, en
        mayúsculas) es la firma y aparece contadas veces.
     2. Radio 0 en todo. Rectángulos con filete de 1px, sin sombras.
     3. Cuadrados, no círculos: el punto de estado es un cuadrado de 8px.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Saira (SIL Open Font License 1.1) — solo la cursiva, variable recortada a lo que GRID usa (20-oct):
   peso 500–900 y ancho 90–100 %, latín básico + Latin-1 + puntuación («» – — · €), 62 KB (antes 140 KB
   con 100–900 y 50–125 %). Rehacer: grid-clubes/maquetas/carga/LEEME.md. La firma siempre va inclinada.
   `swap` para que no bloquee jamás el titular: si tarda, se lee en Montserrat y luego cambia. */
@font-face {
  font-family: 'Saira';
  src: url('img/saira-italic.woff2?v=20261020b') format('woff2');
  font-weight: 500 900; font-stretch: 90% 100%; font-style: italic; font-display: swap;
}


/* ─── Rótulo técnico. El recurso que más se repite en todo el sistema. ───── */
.g-rot {
  font-family: var(--g-mono);
  font-size: 11px; font-weight: 500; letter-spacing: .18em;
  text-transform: uppercase; color: var(--g-tinta-2);
  display: inline-flex; align-items: center; gap: 8px;
}
/* Sin el cuadrado rojo delante (Entrega 3): el rojo es solo para la acción principal y
   para «en vivo», y ese punto se repetía en cada rótulo de la aplicación. */
.g-rot em { font-style: normal; color: var(--g-rojo-tx); }

/* ─── BARRA (global: se ve en todas las rutas) ───────────────────────────── */
body .barra {
  background: color-mix(in srgb, var(--g-sup) 94%, transparent);
  border-bottom: 1px solid var(--g-filete);
  backdrop-filter: blur(12px);
}
/* 30 px, como el recorrido: es el mínimo al que las tres garras que hacen de «I» todavía
   se leen; por debajo se empastan y el logotipo deja de leerse como GRID. */
.marca-logo { height: 30px; width: auto; display: block; }

/* Grupos de navegación: en la portada se ven los anclajes de la landing; dentro
   de la aplicación, las rutas. `body.ruta-inicio` ya lo pone app.js. */
.nav-landing { display: none; }
body.ruta-inicio .nav-landing { display: flex; }
body.ruta-inicio .nav-app     { display: none; }

/* La navegación de la barra, con y sin sesión: la `.tb-nav` del recorrido. Mono 10,5 px, sin
   iconos; la activa solo se pone blanca (nada de raya ni icono rojos). */
.nav-landing a, .barra-nav .ruta-btn {
  font: 400 10.5px var(--g-mono); letter-spacing: .14em; text-transform: uppercase;
  color: var(--g-tinta-2); text-decoration: none; background: none; border: 0; border-radius: var(--r-sm);
  height: 36px; min-height: 0; padding: 0 10px; cursor: pointer;
  display: inline-flex; align-items: center; transition: color .16s ease, background .16s ease;
}
.nav-landing a:hover, .barra-nav .ruta-btn:hover { color: var(--g-tinta); background: var(--hundido-2); text-decoration: none; }
/* En el celular estos destinos son la barra inferior. Dejarlos también arriba
   desbordaba la barra a lo ancho (553 px de contenido en una pantalla de 375). Por debajo de
   700 y no de 780 (P1): a 768 la barra de arriba lleva el menú, como la muestra. */
@media (max-width: 699px) { body.ruta-inicio .nav-landing { display: none; } }

/* El botón de acceso vive en la misma fila que el selector de idioma: si uno es
   cuadrado y el otro redondeado, la barra se ve montada de dos sistemas. */
body .barra .btn { border-radius: var(--r-sm); }

/* Selector de idioma */
/* Discreto: dos palabras en mono, la elegida en blanco. El recorrido no lo tiene; se queda
   porque funciona, pero sin caja ni color que compita con «Entrar». */
.g-idioma { display: flex; gap: 0; }
.g-idioma button {
  appearance: none; background: none; border: 0; cursor: pointer;
  font-family: var(--g-mono); font-size: 11px; font-weight: 600; letter-spacing: .1em;
  color: var(--tinta-3); padding: 0 6px; min-height: 26px; border-radius: 4px;
  transition: background .16s ease, color .16s ease;
}
.g-idioma button:hover { color: var(--fuerte); }
.g-idioma button[aria-pressed="true"] { color: var(--fuerte); }
/* Con el dedo, 44×44 de área: 44 de ancho y el alto crece por fuera sin engordar la barra. */
@media (pointer: coarse) {
  .g-idioma button { position: relative; min-width: 44px; }
  .g-idioma button::after { content: ''; position: absolute; inset: -9px 0; }
}

/* ─── LANDING ────────────────────────────────────────────────────────────── */
body.ruta-inicio { background: var(--g-negro); color: var(--g-tinta); }
body.ruta-inicio .marco,
body.ruta-inicio .contenedor { background: transparent; }

.lp { max-width: 1180px; margin-inline: auto; padding-inline: 24px; }
@media (max-width: 640px) { .lp { padding-inline: 18px; } }

/* Secciones */
/* Igual que en la banda: `padding-block`. `.lp-sec` va SIEMPRE junto a `.lp`, y el
   atajo `padding` le borraba el margen lateral. Se nota solo por debajo de 1180px,
   que es justo donde importa. */
.lp-sec { padding-block: 76px; }
@media (max-width: 640px) { .lp-sec { padding-block: 54px; } }

/* ─── PIE: se mudó a portada.css (P1) ─────────────────────────────────────── */

/* ─── NAVEGACIÓN INFERIOR (móvil) ────────────────────────────────────────
   Al estilo del Portal: cuatro destinos, pulgar abajo. Solo en la portada y
   solo en pantalla estrecha. */
.lp-tabbar { display: none; }
@media (max-width: 699px) {
  body.ruta-inicio .lp-tabbar {
    display: grid; grid-template-columns: repeat(4, 1fr);
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
    background: color-mix(in srgb, var(--g-sup) 97%, transparent); border-top: 1px solid var(--g-filete);
    backdrop-filter: blur(12px);
    padding-bottom: env(safe-area-inset-bottom);
  }
}
.lp-tabbar a {
  position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; min-height: 58px; text-decoration: none; color: var(--g-tinta-2);
  font-family: var(--g-mono); font-size: 8.5px; letter-spacing: .08em; text-transform: uppercase;
  transition: color .16s ease;
}
.lp-tabbar a i { font-size: 20px; line-height: 1; }
.lp-tabbar a.on { color: var(--fuerte); }
.lp-tabbar a.on::before { content: ''; position: absolute; top: 0; left: 30%; right: 30%; height: 2px; background: var(--g-rojo); }

/* ─── MOVIMIENTO ─────────────────────────────────────────────────────────
   Sutil y con causa: cada bloque entra una vez al aparecer, nada se repite en
   bucle y nada se mueve al pasar el ratón. */
@keyframes lp-entra { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
/* Se esconden SOLO cuando el observador ya está montado (`html.rev-on`). Sin esa
   condición, cualquier fallo de JavaScript dejaba media landing invisible para
   siempre y sin un solo error en consola: el modo de fallo correcto es «se ve
   todo de golpe», nunca «no se ve nada». */
html.rev-on .lp-rev { opacity: 0; }
html.rev-on .lp-rev.visto { animation: lp-entra .55s cubic-bezier(.22,.61,.36,1) both; }

@media (prefers-reduced-motion: reduce) {
  .lp-rev, .lp-rev.visto { animation: none !important; opacity: 1 !important; transform: none !important; }
  * { transition-duration: .01ms !important; }
}

/* ─── PANTALLA DE CARGA · el logo que se rellena ──────────────────────────
   Aparece SOLO si la carga se demora: el velo nace transparente y su animación
   de entrada arranca a los 350 ms. En una conexión decente el navegador ya
   terminó y el velo se retira sin haberse visto nunca — que es justo lo que se
   quiere: un fogonazo de pantalla negra es peor que no tener pantalla de carga.

   El logo (`img/grid.svg`, el mismo de la barra) se usa como MÁSCARA (`mask-image`): el archivo solo
   aporta la silueta, el color lo pone el CSS. Así el relleno es una caja roja que sube
   bajo el recorte del logo, sin una sola línea de JavaScript. */
#gridCarga {
  position: fixed; inset: 0; z-index: 9000;
  display: grid; place-items: center; gap: 18px;
  background: var(--g-negro);
  opacity: 0;
  animation: gc-aparece .28s ease .35s forwards;
}
#gridCarga.gc-fin { animation: gc-sale .3s ease forwards; pointer-events: none; }
@keyframes gc-aparece { to { opacity: 1; } }
@keyframes gc-sale    { to { opacity: 0; visibility: hidden; } }

.gc-caja { display: grid; justify-items: center; gap: 16px; }
.gc-garra { position: relative; width: 168px; aspect-ratio: 5208 / 1432; }
/* Las dos capas comparten máscara: abajo el logo apagado, encima el rojo que sube. */
.gc-garra::before, .gc-garra::after {
  content: ''; position: absolute; inset: 0;
  -webkit-mask: url('img/grid.svg?v=20261016a') no-repeat center / contain;
          mask: url('img/grid.svg?v=20261016a') no-repeat center / contain;
}
.gc-garra::before { background: var(--linea); }
.gc-garra::after {
  background: linear-gradient(180deg, var(--g-rojo-tx), var(--g-rojo));
  animation: gc-llena 1.5s cubic-bezier(.45,.05,.55,.95) infinite;
}
/* `inset(arriba derecha abajo izquierda)`. Para que SUBA hay que encoger el recorte
   de ABAJO; encoger el de arriba la llenaría al revés. Luego el nivel baja solo. */
@keyframes gc-llena {
  0%        { clip-path: inset(0 0 100% 0); }   /* vacía */
  55%, 70%  { clip-path: inset(0 0 0 0); }      /* llena */
  100%      { clip-path: inset(100% 0 0 0); }   /* el nivel cae */
}
.gc-tx {
  font-family: var(--g-mono); font-size: 11px; font-weight: 600;
  letter-spacing: .28em; text-transform: uppercase; color: var(--g-tinta-2);
}
@media (prefers-reduced-motion: reduce) {
  #gridCarga { animation: none; opacity: 1; }
  #gridCarga.gc-fin { display: none; }
  .gc-garra::after { animation: none; clip-path: none; opacity: .85; }
}

/* ─── La landing manda en su propio ancho ─────────────────────────────────
   `.contenedor` y `.marco` traen el ancho y el margen de la APLICACIÓN. En la
   portada estorban: la banda de datos va de borde a borde y los márgenes los
   pone `.lp`. Solo en `ruta-inicio`; dentro de un torneo todo sigue igual. */
body.ruta-inicio .marco,
body.ruta-inicio .marco-cue,
body.ruta-inicio main.contenedor { max-width: none; padding: 0; }
body.ruta-inicio #p-inicio.panel { padding: 0 0 20px; }

/* ═══════════════════════════════════════════════════════════════════════════
   LA APLICACIÓN, EN EL MISMO SISTEMA  (Los valores se mudaron a tokens.css.)
   ───────────────────────────────────────────────────────────────────────────
   Hasta aquí la portada era oscura y cuadrada y el torneo seguía siendo blanco
   y redondeado: dos productos pegados con cinta. Se unifica reasignando los
   TOKENS de `sistema.css`, no reescribiéndolo. Sus 58 KB están escritos contra
   `--papel`, `--tinta`, `--linea`…, así que cambiar el significado de esas seis
   variables cambia tablas, tarjetas, botones, chips y modales de una vez.

   Lo que NO se toca: la estructura, los nombres de clase y el HTML. Un rediseño
   que además mueve el marcado es un rediseño que no se puede revertir.
   ═════════════════════════════════════════════════════════════════════════ */

/* `color-scheme` lo pone tokens.css en <html> según el modo y el body lo hereda: aquí decía
   `dark` y en claro los campos de fecha y las barras de scroll salían negros. */
html, body { background: var(--fondo); }

/* La barra de scroll de la PÁGINA la pinta `<html>`: sin esto queda una franja
   blanca al lado de una aplicación negra. */
html { scrollbar-color: var(--linea-fuerte) var(--fondo); }

/* Lo que `sistema.css` dejó con color fijo en vez de token. Cada uno se veía
   como un parche blanco en cuanto el fondo pasó a negro. */
.barra { border-bottom: 1px solid var(--linea); }
.tarjeta, .caja, .panel-cab, table, thead, tbody, tr, th, td { border-color: var(--linea); }
thead th { background: var(--hundido); color: var(--tinta-2); }
tbody tr:hover { background: color-mix(in srgb, var(--fuerte) 3%, transparent); }

/* ─── `--marino` hacía DOS trabajos ───────────────────────────────────────
   Era a la vez el fondo oscuro (barra, columna, cabeceras de tarjeta) y el
   color del TEXTO fuerte sobre papel blanco. Al invertir el tema, lo segundo
   se volvió tinta negra sobre fondo negro: los títulos de sección seguían ahí,
   ilegibles, y en la captura parecía que faltaban.

   Los fondos ya llevan su `color:#fff` al lado y no necesitan nada. Estos son
   los catorce sitios donde `--marino` era TEXTO. Van en `--fuerte` y no en `--marino`
   porque app.js reescribe `--marino` cuando el club configura su color
   secundario: cualquier arreglo que dependa de esa variable dura hasta que
   alguien elija un color en la configuración. */
.s-title, .panel-cab h2, .modal h3, .reglas-cab b, .herr h3, .evento h3,
.portada-tx h2, .portada-tit, .m-marcador, .banda-cuando b, .banda .nm,
.det-dato b, .campeon { color: var(--fuerte); }
.campeon { background: var(--marca-suave); border-color: var(--marca); }

/* Cuando no hay escudo de club, el hueco lo ocupa la «G» de GRID: sin el círculo
   blanco de un escudo real, que sobre negro es un foco. */
.escudo-generico {
  background: none !important; padding: 0 !important; border-radius: 0 !important;
  object-fit: contain; opacity: .9;
}

/* Dentro de un torneo y en Mis jornadas el pie no va (recorrido): es sitio de trabajo, no de
   presentación. */
body:is(.ruta-evento, .ruta-casa, .ruta-jornadas, .ruta-staff, .ruta-enlace) .lp-pie { display: none; }   /* ruta-enlace: un enlace de jornada mientras carga (Ola 3) */

/* Los que no tienen equipo se enseñan como chips bajo la lista (pestaña Equipos). */
.eq-sueltos { padding: 14px 16px; border-top: 1px solid var(--linea); }
.eq-sueltos > div { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }

/* ═══ POP-UPS · el fondo se queda quieto ══════════════════════════════════
   `body{overflow:hidden}` ya estaba, y aun así al llegar al final de un modal
   largo el scroll seguía en la página de detrás: el navegador ENCADENA el
   scroll al ancestro cuando el contenedor se acaba. Eso es `overscroll-behavior`,
   no `overflow`. Y `scrollbar-gutter` evita el salto lateral de la página
   entera al aparecer y desaparecer la barra de scroll. */
html { scrollbar-gutter: stable; }
/* El fondo oscuro y desenfocado de las ventanas vive con ellas: «Ventanas» en piezas.css. */
.modal {
  background: var(--papel);
  border: 1px solid var(--linea-fuerte);
  box-shadow: var(--sombra-alta);
  overscroll-behavior: contain;
}
.modal h3 {
  font-family: 'Montserrat', sans-serif; font-weight: 800; text-transform: uppercase;
  letter-spacing: -.01em; font-size: 1.15rem; color: var(--fuerte);
}
.modal .pista { color: var(--tinta-2); }
.modal-acciones { border-top: 1px solid var(--linea); padding-top: var(--e4); }
.modal input, .modal select, .modal textarea {
  background: var(--fondo); border: 1px solid var(--linea-fuerte);
  color: var(--tinta); border-radius: var(--r-sm);
}
/* Foco gris como el recorrido: el rojo es de la acción principal y de «en vivo». */
.modal input:focus, .modal select:focus, .modal textarea:focus { border-color: var(--tinta-3); outline: 0; }

/* ═══ LA CARA PÚBLICA · cuatro pantallas ══════════════════════════════════ */
/* `es-landing` la ponen las cuatro rutas públicas (`app.js`). Antes esto colgaba
   de `ruta-inicio` y al partir la portada en cuatro, tres de ellas se quedaban
   sin barra, sin ancho y sin navegación inferior. */
body.es-landing { background: var(--g-negro); color: var(--g-tinta); }
/* `.marco-cue` mete 24px de margen lateral: es el aire de la aplicación, donde el
   contenido nunca toca el borde. En la cara pública estorba, porque la foto del hero
   y la banda de datos van A SANGRE y los márgenes los pone `.lp`. */
body.es-landing .marco,
body.es-landing .marco-cue,
body.es-landing main.contenedor { max-width: none; padding: 0; background: transparent; }
body.es-landing .panel { padding: 0 0 24px; }
body.es-landing .nav-landing { display: flex; }
body.es-landing .nav-app { display: none; }

.nav-landing a.active { color: var(--fuerte); }

@media (max-width: 699px) {
  body.es-landing .lp-tabbar {
    display: grid; grid-template-columns: repeat(4, 1fr);
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
    background: color-mix(in srgb, var(--g-sup) 97%, transparent); border-top: 1px solid var(--g-filete);
    backdrop-filter: blur(12px); padding-bottom: env(safe-area-inset-bottom);
  }
  body.es-landing .nav-landing { display: none; }
}

/* ─── La barra, dentro de la aplicación ──────────────────────────────────
   Los destinos llevan el mismo tratamiento que los anclajes de la cara pública (regla
   de arriba, junto a `.nav-landing a`): mono en mayúsculas, sin iconos, y la activa
   solo en blanco. */
/* El `display` de arriba le ganaba a `.admin-only{display:none}` (más especificidad): sin
   sesión salían «Mis jornadas» y «Ajustes», que solo llevan a la ventana de entrar. */
body:not(.is-admin) .barra-nav .ruta-btn.admin-only { display: none; }
body:not(.nivel-admin) .barra-nav .ruta-btn.solo-admin { display: none; }
.barra-nav .ruta-btn.active { color: var(--fuerte); background: none; }
.nav-app { gap: 4px; }

/* Con sesión (Entrega 3, maqueta «Organizar»): Inicio · Jornadas · Staff en Montserrat, y la
   activa con una raya roja que se apoya en el borde de abajo de la barra. La barra pública
   sigue en mono: es otra cara. */
body.is-admin .nav-app .ruta-btn { position: relative; font: 700 13.5px var(--g-sans); letter-spacing: 0;
  text-transform: none; padding: 0 12px; }
body.is-admin .nav-app .ruta-btn.active::after { content: ''; position: absolute; left: 12px; right: 12px;
  bottom: -10px; height: 2px; background: var(--g-rojo); }
.barra-in { position: relative; }

/* El escudo del club: 34 px, redondo, con un aro de 2 px de su color (el fondo de `.esc`
   asoma por el relleno). Abre el menú de la cuenta. Con el dedo se toca en 44. */
#btnAdmin.yo { display: inline-flex; align-items: center; border: 0; background: none; padding: 4px;
  border-radius: 999px; cursor: pointer; flex: none; position: relative; }
#btnAdmin.yo:hover { background: var(--hundido-2); }
#btnAdmin.yo .esc, .yo-q .esc { width: 34px; height: 34px; padding: 2px; }
@media (pointer: coarse) { #btnAdmin.yo::after { content: ''; position: absolute; inset: -5px; } }
/* La cabecera del menú del escudo (la ventana de opciones): escudo y «persona · rol». */
.yo-q { display: flex; gap: 10px; align-items: center; padding: 4px 18px 12px; border-bottom: 1px solid var(--linea); margin-bottom: 4px; }
.yo-q .esc { width: 38px; height: 38px; }
.yo-q span { font-size: 12px; color: var(--tinta-2); }

/* ─── La barra en pantallas estrechas ────────────────────────────────────
   En el celular la barra lleva solo logotipo, idioma y «Entrar» (o el avatar): los
   destinos bajan a la barra de abajo. Aquí solo se aprieta el marco. */
@media (max-width: 480px) {
  .barra-in { padding-inline: 12px; gap: 8px; }
  .g-idioma button { padding: 0 6px; font-size: 10px; }
}
@media (max-width: 380px) {
  .marca-logo { height: 26px; }
  .barra-nav { gap: 0; }
}
/* Cara «Firme» (Entrega 1): esquina corta en botones y chips, no esquina viva. */
.chip, .btn, .btn-sm { border-radius: var(--r-sm); }

/* «En vivo» usaba el rojo de hover (#b71c1c) sobre el tinte de error: 2,79:1 sobre
   negro. El chip es literalmente lo que dice si la jornada está corriendo. Sobre `--fondo` (era
   #140a0c): con el `--error-bg` oscuro el rojo de letra bajaba a 4,34:1; así 4,62 y en claro 4,9. */
.chip-vivo { background: var(--fondo); color: var(--g-rojo-tx); border: 1px solid var(--error-linea); }
.chip-vivo::before { background: var(--g-rojo-tx); }

/* ═══════════════════════════════════════════════════════════════════════════
   DOS AMBIENTES, NO UNO
   ───────────────────────────────────────────────────────────────────────────
   Sin sesión: la presentación. Con sesión: el programa, y nada más. Devolver a
   la landing desde la barra era la forma más rápida de perder lo que tenías
   delante — y encima el idioma, que fuera vende, dentro no hace nada.
   ═════════════════════════════════════════════════════════════════════════ */
body.is-admin .nav-landing,
body.is-admin .lp-tabbar,
body.is-admin .g-idioma,
body.is-admin .ruta-btn.sin-sesion { display: none !important; }
.sin-sesion { display: inline-flex; }

/* ─── La barra inferior del programa ─────────────────────────────────────
   Solo en pantalla táctil. En escritorio la navegación de arriba y la columna
   lateral bastan, y una barra fija abajo solo come alto. */
.ap-tabbar { display: none; }
@media (max-width: 900px) {
  body:not(.es-landing) .ap-tabbar {
    display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 70;
    background: color-mix(in srgb, var(--g-sup) 97%, transparent); border-top: 1px solid var(--linea);
    backdrop-filter: blur(12px); padding-bottom: env(safe-area-inset-bottom);
  }
  /* Sitio para que la barra no tape la última fila de cualquier pantalla. */
  body:not(.es-landing) .panel { padding-bottom: 84px; }
}
/* La `.abajo` del recorrido: la activa en blanco con una raya roja corta y centrada arriba
   (del 30 al 70 %), no un filete a todo el ancho. */
.ap-tabbar button {
  position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; min-height: 58px; background: none; border: 0; cursor: pointer; color: var(--tinta-3);
  font-family: var(--g-mono); font-size: 8.5px; letter-spacing: .08em; text-transform: uppercase;
  transition: color .15s ease;
}
.ap-tabbar button i { font-size: 20px; line-height: 1; }
.ap-tabbar button.on { color: var(--fuerte); }
.ap-tabbar button.on::before { content: ''; position: absolute; top: 0; left: 30%; right: 30%; height: 2px; background: var(--marca); }
.ap-tabbar button:active { background: color-mix(in srgb, var(--fuerte) 5%, transparent); }

/* ═══ VENTANA DE OPCIONES · el menú táctil ════════════════════════════════
   Sustituye a las filas de botoncitos y a los lápices de 32px puestos al lado
   de cada cosa: en un teléfono eso no se acierta. Cada opción es una franja de 56px.
   Desde la Entrega 3b sale al centro, como todas las ventanas: el fondo, la caja y el
   movimiento son los de «Ventanas» (piezas.css). Aquí solo lo suyo. */
.hoja-fondo { position: fixed; inset: 0; z-index: 1400; }   /* encima de las demás ventanas */
/* `display:flex` gana a la regla del navegador para `[hidden]`, así que la hoja
   cerrada seguía tapando la pantalla entera e interceptando cada clic. */
.hoja-fondo[hidden] { display: none !important; }
.hoja { max-width: 440px; padding: 0 0 10px; overflow-y: auto; }
.hoja-cab { display: flex; align-items: center; gap: 10px; padding: 14px 14px 8px 18px; }
.hoja-tit { flex: 1; min-width: 0; margin: 0; font: 800 17px/1.25 var(--g-sans); color: var(--tinta); }
.hoja-op {
  display: flex; align-items: center; gap: 14px; width: 100%;
  min-height: 56px; padding: 0 18px; background: none; border: 0; cursor: pointer;
  text-align: left; color: var(--tinta); font-size: .98rem;
}
.hoja-op:hover, .hoja-op:focus-visible { background: color-mix(in srgb, var(--fuerte) 5%, transparent); }
.hoja-op i { width: 20px; font-size: 17px; color: var(--tinta-3); flex: none; }
.hoja-op b { font-weight: 600; display: block; }
.hoja-op em {
  display: block; font-style: normal; margin-top: 2px;
  font-size: .8rem; color: var(--tinta-3);
}
.hoja-op.peligro { color: var(--error); }
.hoja-op.peligro i { color: var(--error); }
.hoja-sep { border: 0; border-top: 1px solid var(--linea); margin: 6px 0; }
body.con-hoja { overflow: hidden; }
/* El ✕ de las ventanas: redondo, gris, se aclara al pasar. */
.x { width: 34px; height: 34px; border-radius: 50%; border: 0; background: var(--alzado); color: var(--tinta-2);
  display: grid; place-items: center; flex: none; padding: 0; cursor: pointer; font-size: 16px; }
.x:hover, .x:focus-visible { color: var(--tinta); }

/* El azul de TEXTO no sirve de relleno: `.btn-secundario` salía cian con letras
   blancas —«+ Grupo», «Elegir formato», «Buscar en el Club»— y se veía pegado de
   otra aplicación. */
.btn-secundario {
  background: var(--alzado); color: var(--tinta);
  border: 1px solid var(--linea-fuerte);
}
.btn-secundario:hover { border-color: var(--tinta-3); color: var(--fuerte); }

/* ─── El escudo del equipo ───────────────────────────────────────────────
   Siempre un círculo. Con imagen: la imagen recortada a cubrir. Sin imagen: las iniciales
   en blanco sobre el color del equipo (en negro si el color es claro, clase `esc--clara`).
   El tamaño de la letra se mide contra el propio escudo (`cqw`), así sirve a 26 px y a 150. */
.esc {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 34px; height: 34px; overflow: hidden; border-radius: 50%;
  container-type: inline-size;
  background: var(--esc-c, var(--tinta-3));
  color: #fff;   /* color fijo: iniciales sobre el color del EQUIPO (no el del club: --sobre-marca las volvía negras con un club amarillo) */
}
.esc--clara { color: #0b0c10; }   /* color fijo: iniciales oscuras sobre un color de equipo claro, en los dos modos */
.esc > b { font: 700 40cqw/1 var(--g-mono); letter-spacing: -.02em; }
.esc img { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: 50%; }
/* Con imagen, el color del equipo queda como un aro alrededor (gestor, 2-oct): el fondo del
   círculo asoma por el relleno. NO en %: el % del relleno se mide contra el ancho del PADRE,
   y en una fila ancha se comía el círculo entero (imagen de 0 px, 2-oct).
   Dentro, fondo neutro: un PNG transparente no se mezcla con el color del aro. */
.esc:has(img) { padding: 3px; }
.ar-eq-id .esc:has(img) { padding: 5px; }
.esc:has(img) img { background: var(--fondo); }
.esc--sm { width: 26px; height: 26px; }
.esc--lg { width: 46px; height: 46px; }

@media (max-width: 700px) {
  /* Títulos de sección: 1,5rem en 390px es un titular de portada. */
  .s-title, .panel-cab h2 { font-size: 1.25rem !important; }
  .s-eye { font-size: 9.5px; }
}

/* ═══ LA TARJETA DEL GRUPO ════════════════════════════════════════════════
   Seis botones en fila, y debajo cada equipo con un lápiz y una × de 32px
   pegados. En 390px eran tres renglones de botones antes del primer dato, y
   «eliminar» quedaba a cinco milímetros de «editar». Ahora: un menú, y el
   equipo entero es el botón. */
.gr-tarjeta { margin-bottom: 16px; }
.gr-cab {
  display: flex; align-items: center; gap: 12px;
  padding: 13px 14px; border-bottom: 1px solid var(--linea); background: var(--hundido);
}
.gr-id { display: flex; align-items: center; gap: 12px; flex: 1; min-width: 0; }
.gr-letra {
  display: flex; align-items: center; justify-content: center; flex: none;
  width: 38px; height: 38px; background: var(--hundido-2);
  border: 1px solid var(--linea-fuerte);
  font-family: var(--g-mono); font-size: 14px; font-weight: 700; color: var(--fuerte);
  text-transform: uppercase;
}
.gr-cab h3 {
  margin: 0; font-family: 'Montserrat', sans-serif; font-weight: 700; font-size: 1rem;
  text-transform: uppercase; letter-spacing: -.01em; color: var(--fuerte);
}
.gr-meta {
  margin: 3px 0 0; font-family: var(--g-mono); font-size: 10px;
  letter-spacing: .08em; text-transform: uppercase; color: var(--tinta-3);
}
.gr-marcador {
  font-family: var(--g-mono); font-size: 13px; font-weight: 700; color: var(--tinta-2);
  font-variant-numeric: tabular-nums; flex: none;
}
.gr-marcador.lleno { color: var(--ok-tx); }
.gr-mas {
  flex: none; width: 44px; height: 44px; background: none; cursor: pointer;
  border: 1px solid var(--linea-fuerte); color: var(--tinta-2);
  display: flex; align-items: center; justify-content: center; font-size: 15px;
}
.gr-mas:hover { color: var(--fuerte); border-color: var(--tinta-3); background: color-mix(in srgb, var(--fuerte) 4%, transparent); }

/* La única acción que se queda a la vista: sin formato no hay cruce que repartir,
   así que el grupo no sirve para nada hasta que se elige. */
.gr-cta {
  display: flex; align-items: center; gap: 13px; width: 100%; text-align: left;
  min-height: 62px; padding: 0 14px; margin-bottom: 16px; cursor: pointer;
  background: var(--hundido-2); border: 1px solid var(--linea-fuerte);
  color: var(--tinta);
}
.gr-cta:hover { background: var(--alzado); }
.gr-cta > i { font-size: 17px; color: var(--marca-osc); flex: none; }
.gr-cta > i:last-child { margin-left: auto; color: var(--tinta-3); }
.gr-cta b { display: block; font-weight: 600; font-size: .96rem; }
.gr-cta em {
  display: block; font-style: normal; margin-top: 2px;
  font-size: .78rem; color: var(--tinta-3);
}
.gr-cta--rojo > i:first-child { color: var(--ok-tx); }

@media (max-width: 560px) {
  .gr-cab { padding: 11px 12px; gap: 10px; }
  .gr-letra { width: 34px; height: 34px; font-size: 12px; }
}


/* ─── Lo que quedó con color FIJO en `sistema.css` ───────────────────────
   Todo esto estaba escrito para papel blanco y no pasó por token, así que el
   cambio de tema no lo alcanzó. Sale uno a uno midiendo el contraste sobre la
   página ya pintada; a ojo no se ven, porque varios solo aparecen al pasar el
   ratón o al salir un aviso. */

/* Fila de tabla bajo el ratón: pintaba la celda de #FAFCFF y el texto claro
   desaparecía. 1,26:1 — el peor de todos, y se ve en CADA tabla. */
tbody tr:hover td { background: color-mix(in srgb, var(--fuerte) 4.5%, transparent); }


/* Avisos: los `-bg` ya son tintes oscuros, pero los colores de texto seguían
   siendo los de papel blanco. El informativo daba 1,65. */
.aviso-info { background: var(--azul-suave); border-color: var(--azul-linea); color: var(--azul-osc); }
.aviso-ok { color: var(--ok-tx); }
.aviso-alerta { color: var(--alerta); }
.aviso-error { color: var(--error); }

/* El aviso flotante: verde #10b981 con letras blancas da 2,54. Es oscuro en los dos modos, como
   el de la muestra en claro (y como el `.toast` de sistema.css, sobre el marino). */
.toast { border-radius: var(--r); }
/* El aviso flotante no tapa botones: un toque durante el aviso llega a lo que hay debajo (los «Escribir resultado», «Corregir»). Solo su acción («Deshacer»/«Ir») es tocable. */
.toast { pointer-events: none; }
.toast .toast-ir { pointer-events: auto; }
/* Con la ventana de camisetas abierta el aviso sube: abajo tapaba «Otro número» y «Sin número» durante 4 s. */
body.con-fl .toast { bottom: auto; top: 16px; }
.toast.success { background: #0c3b2c; color: #d6f5e8; border: 1px solid var(--ok-linea); }   /* color fijo: el aviso flotante es oscuro en los dos modos */
.toast.error { background: #3b1214; color: #ffd9d7; border: 1px solid var(--error-linea); }   /* color fijo: el aviso flotante es oscuro en los dos modos */

/* ─── Bloque plegable ────────────────────────────────────────────────────
   `<details>` nativo: sin JavaScript, accesible por teclado y recordado por el
   navegador al volver atrás. El resumen dice lo que hay dentro, así que no hace
   falta abrirlo para saberlo. */
.plegable > summary {
  cursor: pointer; list-style: none; user-select: none;
  display: flex; align-items: center; gap: 12px;
}
.plegable > summary::-webkit-details-marker { display: none; }
.plegable > summary:hover { background: var(--hundido-2); }
.ple-resumen {
  font-family: var(--g-mono); font-size: 10.5px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--tinta-3); text-align: right;
}
.ple-flecha { flex: none; color: var(--tinta-3); transition: transform .18s ease; }
.plegable[open] > summary .ple-flecha { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) { .ple-flecha { transition: none; } }

/* ═══════════════════════════════════════════════════════════════════════════
   GRID · SaaS — acceso, legal, configuración y consola de cancha
   2026-09-12
   ═══════════════════════════════════════════════════════════════════════════ */

/* `hidden` quiere decir escondido, y punto.
   La hoja de estilos del navegador trae `[hidden]{display:none}`, pero cualquier regla
   de autor con `display` le gana: `.campo{display:flex}` dejaba visible un campo al que
   el JavaScript acababa de poner `hidden`. Ya lo pagamos una vez con la hoja inferior y
   lo volvimos a pagar con el nombre del club en el registro, así que se arregla en la
   raíz y no elemento por elemento. */
[hidden] { display: none !important; }

/* ── Legal ────────────────────────────────────────────────────────────────── */
.lp-legal { padding-block: 44px 72px; }
.lg-ficha {
  display: flex; flex-wrap: wrap;   /* flex y no grid: la última fila se estira y no deja casillas grises vacías */
  gap: 1px; background: var(--linea); border: 1px solid var(--linea); margin-bottom: 40px;
}
.lg-ficha > div { background: var(--papel); padding: 14px 16px; flex: 1 1 190px; }
.lg-ficha > div:nth-child(4) { flex-basis: 270px; }   /* el correo cabe entero */
.lg-ficha a { overflow-wrap: break-word; }   /* solo parte si no cabe, y antes lo hace en el <wbr> tras la @ */
.lg-ficha span { display: block; font: 600 10px/1 var(--g-mono, monospace); letter-spacing: .14em;
  text-transform: uppercase; color: var(--tinta-3); margin-bottom: 6px; }
.lg-ficha b { font-size: 14px; color: var(--tinta); overflow-wrap: anywhere; }
.lg-h { margin: 34px 0 12px; font-size: 18px; color: var(--fuerte); letter-spacing: -.01em; }   /* token: Legal también se ve en claro (P1) */
.lp-legal p { color: var(--tinta-2); line-height: 1.65; margin: 0 0 12px; max-width: 72ch; }
.lp-legal p b, .lg-lista b { color: var(--tinta); }
.lg-lista { margin: 0 0 12px; padding-left: 20px; }
.lg-lista li { color: var(--tinta-2); line-height: 1.6; margin-bottom: 7px; }
.lg-menores .callout__t { color: var(--marca-osc); }
.lg-pie { margin-top: 40px; padding-top: 20px; border-top: 1px solid var(--linea);
  font-size: 13px; color: var(--tinta-3) !important; }

/* ── Configuración ────────────────────────────────────────────────────────── */
.cfg-carga { padding: 48px; text-align: center; color: var(--tinta-3); }
.cfg-sub { margin: var(--e4) 0 6px; font-size: 13px; color: var(--tinta); }
.cfg-nota { font-size: 12px; color: var(--tinta-3); line-height: 1.55; margin: 0 0 var(--e3); }
.cfg-fila { display: flex; justify-content: space-between; gap: var(--e3); padding: 9px 0;
  border-bottom: 1px solid var(--linea); font-size: 13px; }
.cfg-fila:last-of-type { border-bottom: 0; }
.cfg-fila span { color: var(--tinta-3); }
.cfg-fila b { color: var(--tinta); text-align: right; }
/* Tu club (Entrega 3): el escudo grande, redondo, con un aro de 4 px de su color. */
.cfg-foto { display: flex; align-items: center; gap: 16px; margin: 14px 0 16px; }
.cfg-foto .esc { width: 84px; height: 84px; padding: 4px; }
.cfg-bts { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; }
/* El archivo va oculto a la vista (`.solo-lector`) pero no al teclado: el foco cae en él y
   el anillo se pinta en la etiqueta, que es lo que se ve. */
.cfg-subir:focus-within { outline: 2px solid var(--azul); outline-offset: 2px; }
.cfg-colores { display: flex; flex-wrap: wrap; gap: 14px; margin-top: var(--e3); }
.cfg-colores label { display: flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 700; color: var(--tinta-2); cursor: pointer; }
.cfg-colores input[type=color] { width: 30px; height: 30px; padding: 0; border: 2px solid var(--linea-fuerte);
  border-radius: 8px; background: none; cursor: pointer; }
.cfg-colores input[type=color]::-webkit-color-swatch-wrapper { padding: 0; }
.cfg-colores input[type=color]::-webkit-color-swatch { border: 0; border-radius: 5px; }
.cfg-asi { font-weight: 800; font-size: 13px; color: var(--tinta-2); margin: 18px 0 0; }
.cfg-prev { display: flex; align-items: center; gap: 12px; border: 1px solid var(--linea); border-radius: 10px;
  padding: 12px; margin: 6px 0 4px; color: #fff; }   /* color fijo: ui.js le pone de fondo el color del club oscurecido a 7:1 */
.cfg-prev .esc { width: 40px; height: 40px; }
.cfg-prev .pista { color: #ffffffb3; }   /* color fijo: sobre el color del club, como arriba */
.cfg-cuerpo { padding-top: var(--e2); }

/* ── Consola de cancha ────────────────────────────────────────────────────────
   El día del partido esto es TODA la pantalla: sin barra, sin pestañas, sin nada
   que tocar por error. `100dvh` y no `100vh` porque en el móvil la barra del
   navegador se mete dentro de `vh` y los botones de abajo quedan tapados justo
   cuando hay que pulsarlos.                                                    */
/* Se apaga por ELEMENTO (`footer`, `header`) y no solo por clase: el pie se llama
   `.lp-pie` y no `.pie`, así que la lista por nombres lo dejó vivo y metía 164 px de
   más al final — el scroll aparecía justo cuando el partido estaba en marcha. */
/* `footer` a secas, no: el pie de la página es `.lp-pie` y es el único que hay que apagar.
   Con el selector de elemento se apagaba también el pie de cada baldosa de la torre —que
   es un `<footer>` legítimo—, así que «sin mesa» no se veía y la torre callaba justo lo
   que existe para gritar. Es la segunda vez que este selector se pasa de listo. */
/* Con `:is()` en vez de repetir la lista por cada pantalla: eran cuatro renglones para
   dos, y sumar la grada los habría puesto en seis. Ahora añadir una pantalla sin cromo es
   escribir su clase una vez. */
body:is(.es-consola, .es-grada, .es-arena)
  :is(.barra, .ap-tabbar, .lp-tabbar, .lp-pie, .barra-nav, .g-idioma) { display: none !important; }
body:is(.es-consola, .es-grada, .es-arena)
  :is(.marco, .marco-cue, .contenedor) { min-height: 0; height: auto; }
/* La grada NO va aquí: es una página que se lee de arriba abajo —la tira de partidos y
   debajo la tabla—, así que necesita su scroll vertical. La arena ocupa
   exactamente una pantalla y el scroll ahí solo estorba. La consola tampoco va desde la
   Entrega 2: su cara es la de la mesa del recorrido, que no se estira a la pantalla, y en un
   teléfono bajo los botones de abajo tienen que poder alcanzarse. */
body.es-arena { overflow: hidden; }
/* `.contenedor` —con E— es quien lleva el `max-width: 1440px`. La regla decía `.contenido`,
   que no existe, así que el tope nunca se quitaba: la TORRE, que se hizo para el televisor
   del coliseo, salía desde S201 capada a 1440 px con 480 de negro a cada lado en cualquier
   pantalla más ancha. No se vio porque se midió a 1280 y a 1440. El relleno lateral de
   `.marco-cue` va en la misma lista por lo mismo: 24 px de margen a cada lado son sitio
   robado al marcador en una pantalla que existe para el marcador. */
body:is(.es-consola, .es-grada, .es-arena)
  :is(.contenedor, .marco-cue, #p-cancha, #p-grada, #p-arena) {
  padding: 0; margin: 0; max-width: none; }

.cn-entrada { min-height: 100dvh; display: flex; flex-direction: column; justify-content: center;
  align-items: center; text-align: center; padding: var(--e5); background: var(--fondo); }
.cn-entrada .cn-logo { height: 34px; width: auto; margin-bottom: var(--e4); }
.cn-entrada h2 { margin: 0 0 8px; font-size: 20px; color: var(--fuerte); }
.cn-entrada p { margin: 0 0 var(--e5); max-width: 34ch; color: var(--tinta-2); font-size: 13px; line-height: 1.6; }
.cn-entrada form { width: 100%; max-width: 340px; text-align: left; }
.cn-grande { width: 100%; margin-top: var(--e4); padding: 15px; font-size: 15px; }

.cn { min-height: 100dvh; display: flex; flex-direction: column; background: var(--fondo); }
/* La lista se desplaza POR DENTRO: la consola tiene el scroll de la página apagado, y en
   cuadros una cancha con doce partidos ya no cabe en un teléfono — los de abajo quedaban
   fuera de alcance. */
.cn:not(.cn-juego) { height: 100dvh; }
.cn-cab { flex: none; display: flex; align-items: center; justify-content: space-between; gap: var(--e3);
  padding: 10px var(--e4); border-bottom: 1px solid var(--linea); background: var(--papel); }
.cn-cab b { display: block; font-size: 14px; color: var(--tinta); }
.cn-cab small { display: block; font-size: 11px; color: var(--tinta-3); }
.cn-red { font: 600 11px/1 var(--g-mono, monospace); letter-spacing: .04em; display: flex;
  align-items: center; gap: 6px; padding: 6px 9px; border: 1px solid var(--linea); white-space: nowrap; }
/* Solo pide color lo que pide atención: «Todo guardado» es lo normal y va en gris. */
.cn-red.bien   { color: var(--tinta-3); }
.cn-red.espera { color: var(--alerta);   border-color: var(--alerta-linea); }
.cn-red.mal    { color: var(--error);    border-color: var(--error-linea);  background: var(--error-bg); }

/* Cuadros, no filas: cada partido es una tarjeta cuadrada que se toca entera,
   y la cuadrícula reparte tantas por fila como quepan. */
.cn-lista { flex: 1; min-height: 0; overflow-y: auto; padding: var(--e3);
  display: grid; grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
  gap: var(--e2); align-content: start; }
.cn-item { display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; aspect-ratio: 1; padding: var(--e3); text-align: center; cursor: pointer;
  background: var(--papel); border: 1px solid var(--linea); color: var(--tinta); position: relative; }
.cn-item:active { background: var(--hundido-2); }
.cn-item.vivo  { border-color: var(--error-linea); }
.cn-item.listo { opacity: .62; }
.cn-hora { font: 700 14px/1 var(--g-led); color: var(--tinta-3); }
.cn-vs { display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 0; width: 100%; }
.cn-vs b { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; max-width: 100%; }
.cn-vs i { font-style: normal; font-size: 10px; color: var(--tinta-3); letter-spacing: .1em; }
.cn-mk { font: 700 22px/1 var(--g-led); color: var(--led); text-shadow: var(--led-brillo); white-space: nowrap;
  word-spacing: .3em; }  /* el espacio de DSEG7 mide .2em: «161·44» quedaba pegado */
.cn-item:not(.vivo, .listo) .cn-mk { color: var(--tinta-3); text-shadow: none; }
.cn-vs b { color: var(--tinta); }
.cn-chip { position: absolute; top: 6px; right: 6px; padding: 3px 7px; background: var(--marca);
  color: var(--sobre-marca); font: 700 9px/1 var(--g-mono, monospace); letter-spacing: .1em; }

/* Lista de la cancha con la tarjeta de «Mis partidos» (31-oct): foto del coliseo arriba, hora en píldora,
   equipo en la firma, y abajo estado + marcador. Se toca la tarjeta entera. Las tarjetas van centradas
   (3 partidos no quedan pegados a la izquierda) y Elso llena el espacio de abajo. */
.cn-lista { display: flex; flex-direction: column; align-items: center; gap: 40px; padding: 40px 24px; }
.cn-ps { width: 100%; max-width: 1180px; display: flex; flex-wrap: wrap; justify-content: center; gap: 24px; }
.cn-item { flex: 0 1 360px; aspect-ratio: auto; padding: 0; gap: 0; align-items: stretch; justify-content: flex-start;
  text-align: left; border-radius: 16px; overflow: hidden; font: inherit; transition: transform .2s, box-shadow .2s; }
.cn-item:hover { transform: translateY(-3px); box-shadow: 0 12px 28px rgba(10,20,38,.12); }   /* color fijo: tarjeta sobre la foto del coliseo */
.cn-item.listo { opacity: 1; }
.cn-por { position: relative; min-height: 176px; padding: 20px 22px; display: flex; flex-direction: column; justify-content: flex-end;
  color: #fff; background: linear-gradient(180deg, rgba(10,20,38,.35), rgba(10,20,38,.92)), url('img/coliseo.jpg') center/cover, #0f1e3b; }   /* color fijo: tarjeta sobre la foto del coliseo */
.cn-por .cn-hora { position: absolute; top: 16px; right: 18px; font: 700 14px var(--g-sans); color: #fff;   /* color fijo: tarjeta sobre la foto del coliseo */
  background: rgba(255,255,255,.14); padding: 5px 12px; border-radius: 999px; }   /* color fijo: tarjeta sobre la foto del coliseo */
.cn-vs { display: block; }
.cn-vs b { display: block; color: #fff; font: italic 900 28px/1.05 var(--g-firma); text-transform: uppercase; white-space: normal; }   /* color fijo: tarjeta sobre la foto del coliseo */
.cn-vs i, .cn-vs b + i + b { display: inline; font: 600 15px var(--g-sans); text-transform: none; color: rgba(255,255,255,.9); letter-spacing: 0; }   /* color fijo: tarjeta sobre la foto del coliseo */
.cn-vs i::after { content: ' '; }
.cn-pie { display: flex; align-items: center; gap: 12px; padding: 16px 22px; background: var(--papel); }
.cn-est { flex: 1; display: inline-flex; align-items: center; gap: 6px; font: 600 11px var(--g-sans); letter-spacing: .12em;
  text-transform: uppercase; color: var(--tinta-2); }
.cn-est::before { content: ''; width: 8px; height: 8px; border-radius: 50%; background: var(--alerta); }
.cn-item.vivo .cn-est::before { background: var(--marca); }
.cn-item.listo .cn-est::before { background: var(--tinta-3); }
.cn-mk { font-size: 22px; }
.cn-chip { top: 16px; left: 18px; right: auto; border-radius: 999px; }
.cn-elso { display: flex; align-items: center; gap: 28px; max-width: 620px; }
.cn-elso .elso-pie { --h: 210px !important; }
.cn-elso b { display: block; font: italic 900 30px/1.05 var(--g-firma); text-transform: uppercase; color: var(--tinta); }
.cn-elso p { margin: 10px 0 0; color: var(--tinta-2); font-size: 15px; line-height: 1.55; }
@media (max-width: 640px) {
  .cn-lista { gap: 28px; padding: 16px; }
  .cn-item { flex-basis: 100%; }
  .cn-por { min-height: 132px; padding: 16px 18px; }
  .cn-vs b { font-size: 24px; }
  .cn-elso { gap: 16px; }
  .cn-elso .elso-pie { --h: 130px !important; }
  .cn-elso b { font-size: 22px; }
  .cn-elso p { font-size: 14px; }
  /* En el celular, con 3 o más partidos la pantalla ya está llena: Elso sobra. */
  .cn-ps:has(> .cn-item:nth-child(3)) ~ .cn-elso { display: none; }
}
/* En computador el bloque (tarjetas + Elso) va al centro de la pantalla, no pegado arriba.
   Con márgenes auto y no `justify-content: center`: si hay muchos partidos, el de arriba no queda cortado. */
@media (min-width: 641px) { .cn-ps { margin-top: auto; } .cn-elso { margin-bottom: auto; } }

/* Un hijo de flex no baja de su ancho de contenido salvo que se le diga. El aviso de
   la página legal desbordaba 21 px dentro de su caja y empujaba 2 px de scroll lateral
   a la página entera a 375. Se arregla donde nace —el aviso— y no tapando el síntoma
   con `overflow:hidden` en el contenedor, que además cortaría el texto. */
.aviso { min-width: 0; }
.aviso > * { min-width: 0; overflow-wrap: break-word; }

/* ═══════════════════════════════════════════════════════════════════════════
   S194 · LA VENTANA DE CONFIGURACIÓN, EL ACCESO Y EL DOCUMENTO LEGAL
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Configuración: ventana por apartados ─────────────────────────────────────
   Como pestaña obligaba a abandonar lo que estuvieras haciendo. Como ventana se abre
   encima, y por dentro son apartados (`apartados()`, ui.js): uno a la vez. */
.modal-cfg {
  max-width: 760px; padding: 0;
  display: flex; flex-direction: column; height: min(84vh, 660px); overflow: hidden;
}
/* La cabecera de todas las ventanas (Ventanas 2026): sin tinte, título 700 17, el ✕ redondo; el filete solo cuando el cuerpo corrió. */
.cfgw-cab {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
  padding: 18px var(--v-pad) 12px; flex: none; transition: box-shadow .15s;
}
.corrido .cfgw-cab { box-shadow: 0 1px 0 var(--linea); }
.cfgw-cab > .v-x { margin: -6px -8px 0 0; }
.cfgw-cab h2 { margin: 0; font: 700 17px/1.3 var(--g-sans); text-transform: none; letter-spacing: 0; color: var(--tinta); }
/* El cuerpo es lo que hace scroll; los apartados (`.aj`, piezas.css) van dentro. */
.cfgw-cuerpo { flex: 1; min-height: 0; overflow-y: auto; padding: 4px var(--v-pad) 16px; }
.cfgw-cuerpo .aj-idx { top: 0; }
.cfg-acciones { margin-top: var(--e4); padding-top: var(--e4); border-top: 1px solid var(--linea); }
.aj-sec .campo + .campo, .aj-sec .aviso { margin-top: var(--e3); }
.aj-sec .cfg-sub { margin: var(--e5) 0 6px; font-size: 13px; color: var(--tinta);
  padding-top: var(--e4); border-top: 1px solid var(--linea); }
/* El enlace salía en el azul por defecto del navegador, que no es de esta paleta. */
.aj-sec a { color: var(--marca-osc); text-decoration: underline; text-underline-offset: 2px; }

/* En el celular sigue siendo una ventana al centro (C4), con menos relleno. */
/* En el celular, hoja desde abajo del alto de lo que trae (revisión 27-oct: las 4 opciones no ocupan la pantalla entera). */
@media (max-width: 620px) { .modal-cfg { height: auto; max-height: 92dvh; } }

/* ── Legal: es un documento, no una sección de la portada ─────────────────────
   Con la cabecera de la landing la firma «GRID» salía a 58 px bajo un título de 32
   —casi el doble— y el trazo de la garra se montaba encima del título. Una página de
   términos no necesita firma de marca: necesita jerarquía y un camino de vuelta. */
.lg-doc { max-width: 880px; }
.lg-cab { margin-bottom: 36px; }
.lg-volver {
  display: inline-flex; align-items: center; gap: 4px; margin-bottom: 22px;
  padding: 0 14px 0 8px; min-height: 38px;
  border: 1px solid var(--linea-fuerte); background: var(--hundido); color: var(--tinta-2);
  font-size: 13px; border-radius: 0;
}
.lg-volver:hover { color: var(--tinta); border-color: var(--marca); }
.lg-volver i { font-size: 15px; }
.lg-titulo {
  font-family: var(--g-sans); font-weight: 800; text-transform: uppercase;
  letter-spacing: -.01em; font-size: clamp(21px, 2.8vw, 30px); line-height: 1.12;
  color: var(--fuerte); margin: 10px 0 0;
}
.lg-bajada {
  margin: 12px 0 0; max-width: 60ch; color: var(--tinta-2);
  font-size: 14.5px; line-height: 1.6;
}
.lp-legal { padding-block: 36px 72px; }
/* Legal L1 · el visor de los documentos completos (`legal/*.md` → LEGAL.md): tablas con scroll propio, citas y listas. */
.lg-md > .lg-h:first-child { margin-top: 0; }
.lg-md h2.lg-h { font-size: 20px; } .lg-md h4.lg-h { font-size: 15.5px; margin-top: 24px; }
.lg-md p, .lg-md li { color: var(--tinta-2); line-height: 1.65; }
.lg-md p { margin: 0 0 12px; max-width: 78ch; }
.lg-md a, .lp-legal .lg-lista a { color: var(--marca-osc); text-decoration: underline; text-underline-offset: 2px; }
.lg-md code { font-family: var(--g-mono, monospace); font-size: .9em; }
.lg-md hr { border: 0; border-top: 1px solid var(--linea); margin: 28px 0; }
.lg-tabla { overflow-x: auto; margin: 0 0 16px; border: 1px solid var(--linea); }
.lg-tabla table { border-collapse: collapse; width: 100%; font-size: 13.5px; }
.lg-tabla th, .lg-tabla td { text-align: left; vertical-align: top; padding: 9px 12px; border-bottom: 1px solid var(--linea); color: var(--tinta-2); line-height: 1.5; }
.lg-tabla td, .lg-tabla th { overflow-wrap: anywhere; }
/* En el celular nada se corta a la derecha: las tablas de rótulo/valor (la identificación del proveedor) se apilan, y las demás se ajustan al ancho. */
@media (max-width: 619px) {
  .lg-tabla table { font-size: 12.5px; }
  .lg-tabla th, .lg-tabla td { padding: 7px 8px; }
  .lg-tabla--kv tr { display: block; border-bottom: 1px solid var(--linea); padding: 4px 0; }
  .lg-tabla--kv td { display: block; border: 0; padding: 2px 10px; }
  .lg-tabla--kv td:first-child { font: 600 10px/1.4 var(--g-mono, monospace); letter-spacing: .12em; text-transform: uppercase; color: var(--tinta-3); padding-top: 6px; }
}
.lg-tabla th { color: var(--tinta); font-weight: 700; background: var(--hundido); }
.lg-cita { margin: 0 0 16px; padding: 10px 16px; border-radius: var(--r); background: var(--hundido); }
.lg-cita p { margin: 8px 0; }
.lg-docs small { color: var(--tinta-3); margin-left: 6px; }
.lg-cargando { color: var(--tinta-3); }

/* ═══════════════════════════════════════════════════════════════════════════
   S201 · LA FILA DEL PANEL ES EL BOTÓN
   ═══════════════════════════════════════════════════════════════════════════ */

/* Texto que solo leen los lectores de pantalla. La columna de acciones no lleva rótulo
   visible —sería ruido— pero sin nombre la tabla se lee «columna cuatro». */
.solo-lector {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* La mitad que faltaba del estándar de tablas: el envoltorio con scroll ya estaba
   (`.tabla-caja`), la de esconder columnas no. En un teléfono, cinco columnas no caben
   y el scroll lateral esconde justo la que importa. */
@media (max-width: 560px) { .mob-hide { display: none !important; } }

.tb-torneos tbody tr { cursor: pointer; transition: background .12s ease; }
.tb-torneos tbody tr:hover { background: var(--hundido); }
/* El foco se ve en el botón de la fila, que es lo que alcanza el tabulador; la fila
   entera no se enfoca a propósito —un `<tr>` con `tabindex` se anuncia «fila» y no dice
   que abra nada—. */
.tb-torneos tbody tr:has(.tb-mas:focus-visible) { background: var(--hundido); }
.tb-torneos .tb-acc { text-align: right; width: 1%; white-space: nowrap; }
.tb-mas { min-width: 40px; padding: 0 10px; color: var(--tinta-2); }
.tb-mas:hover { color: var(--tinta); }
.tb-torneos .chip + .chip { margin-left: 6px; }
/* La visibilidad es un dato de segunda fila: se lee si se busca, no compite con el estado. */
.tb-vis { background: transparent; border: 1px solid var(--linea-fuerte); color: var(--tinta-3); }
@media (max-width: 560px) {
  .tb-torneos .tb-vis { display: none; }   /* va en el menú, como la fecha */
  .tb-torneos tbody td { padding-block: 13px; }
}
/* El diálogo recibe el foco para que el tabulador y el lector entren por el título; no
   debe pintar anillo —no es un control, es el contenedor—. */
.hoja:focus { outline: none; }

/* ═══ LA GRADA ════════════════════════════════════════════════════════════
   La pantalla de la familia. Un teléfono en una mano, de pie, a cuatro metros de la
   cancha: el marcador manda, el resto acompaña. Medido antes de escribirla: lo que
   recibía una familia era la clasificación del organizador —3,4 pantallas de scroll de
   una tabla de ocho columnas— y un horario titulado «Mesa de control». */
.gr-cab {
  display: flex; align-items: center; gap: var(--e3);
  padding: 10px var(--e4); border-bottom: 1px solid var(--linea);
  background: var(--papel); position: sticky; top: 0; z-index: 5;
}
.gr-x {
  width: 38px; height: 38px; flex: none; display: grid; place-items: center;
  background: var(--hundido); border: 1px solid var(--linea-fuerte); color: var(--tinta);
  cursor: pointer; border-radius: 0;
}
.gr-x:hover { background: var(--hundido-2); }
.gr-tit { flex: 1; min-width: 0; }
.gr-tit b { display: block; font: 800 14px/1.2 var(--g-sans); text-transform: uppercase;
  letter-spacing: .02em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.gr-tit small { display: block; font-size: 11px; color: var(--tinta-3); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.gr-red {
  flex: none; font: 800 9.5px/1 var(--g-sans); letter-spacing: .12em; text-transform: uppercase;
  padding: 6px 8px; border: 1px solid var(--linea-fuerte); color: var(--tinta-3);
}
.gr-red.flojo { color: var(--alerta-tx); border-color: currentColor; }
.gr-red.mal   { color: var(--g-rojo-tx); border-color: currentColor; }

/* ── a quién sigo ── */
.gr-yo {
  display: flex; align-items: center; gap: var(--e3); width: 100%;
  padding: var(--e3) var(--e4); background: var(--hundido); border: 0;
  border-bottom: 1px solid var(--linea); color: var(--tinta); cursor: pointer; text-align: left;
}
.gr-yo:hover { background: var(--hundido-2); }
.gr-yo i:first-child, .gr-eq-b i { width: 10px; align-self: stretch; min-height: 34px;
  background: var(--eq, var(--tinta-3)); flex: none; }
.gr-yo span, .gr-eq-b span { flex: 1; min-width: 0; }
.gr-yo .esc, .gr-eq-b .esc { flex: none; width: 40px; height: 40px; }   /* el «span» de arriba lo estiraba en óvalo */
.gr-yo b, .gr-eq-b b { display: block; font: 800 15px/1.2 var(--g-sans); text-transform: uppercase; }
.gr-yo em, .gr-eq-b em { display: block; font-style: normal; font-size: 11px; color: var(--tinta-3); }

/* ── elegir equipo ── */
.gr-elige { padding: var(--e5) var(--e4); }
.gr-elige h2 { font: 800 1.35rem/1.15 var(--f-titulo, var(--g-sans)); margin-bottom: 6px; }
.gr-nota { color: var(--tinta-3); font-size: .9rem; margin-bottom: var(--e4); }
.gr-eqs { display: grid; gap: 1px; background: var(--linea); border: 1px solid var(--linea); }
.gr-eq-b { display: flex; align-items: center; gap: var(--e3); padding: var(--e3);
  background: var(--papel); border: 0; color: var(--tinta); cursor: pointer; text-align: left;
  min-height: 56px; }          /* 56 px: el objetivo táctil, no un icono al lado */
.gr-eq-b:hover { background: var(--hundido); }
.gr-eq-b.on { background: var(--hundido-2); outline: 2px solid var(--marca); outline-offset: -2px; }

/* ── la tira de partidos ── */
.gr-tira {
  /* `position: relative` no es decoración: sin ella el `offsetParent` de las tarjetas es
     el `<body>` y `offsetLeft` devuelve la posición en la PÁGINA —24 px de relleno
     incluidos—, no dentro de la tira. Hoy cuela porque el encaje corrige la diferencia;
     con un relleno mayor que medio ancho de tarjeta, la tira arrancaría en el partido
     equivocado. */
  position: relative;
  display: flex; overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth;
  overscroll-behavior-x: contain; scrollbar-width: none; -ms-overflow-style: none;
}
.gr-tira::-webkit-scrollbar { display: none; }
.gr-c { flex: 0 0 100%; min-width: 100%; scroll-snap-align: center; padding: var(--e4); }
.gr-c-cab { display: flex; justify-content: space-between; align-items: center; gap: var(--e2);
  font: 700 11.5px/1 var(--g-sans); letter-spacing: .1em; text-transform: uppercase;
  color: var(--tinta-3); margin-bottom: var(--e3); }
.gr-c-est { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.gr-c-h { font: 700 14px/1 var(--g-led); font-style: normal; letter-spacing: normal; color: var(--tinta-2); }
.gr-c-est b { font: 700 15px/1 var(--g-led); letter-spacing: normal; text-shadow: var(--led-brillo); }
.gr-c.vivo .gr-c-est { color: var(--g-rojo-tx); }
.gr-c.fin  .gr-c-est { color: var(--tinta-2); }
.gr-viva { width: 7px; height: 7px; background: currentColor; animation: grLatido 1.4s infinite; }
@keyframes grLatido { 0%, 100% { opacity: 1 } 50% { opacity: .25 } }

.gr-c-eq { display: grid; gap: 1px; background: var(--linea); border: 1px solid var(--linea); }
.gr-lado { display: flex; align-items: center; gap: var(--e3); padding: var(--e3);
  background: var(--papel); }
/* El equipo que sigue la familia va marcado: en un partido entre «Naranja» y «Rojo», a
   cuatro metros y con el sol de frente, saber cuál de los dos es el tuyo no es evidente. */
.gr-lado.mio { background: var(--hundido-2); }
.gr-lado.mio .gr-lado-n { color: var(--tinta); font-weight: 800; }
.gr-lado-n { flex: 1; min-width: 0; font: 700 1.05rem/1.2 var(--g-sans); text-transform: uppercase;
  color: var(--tinta-2); overflow: hidden; text-overflow: ellipsis; }
.gr-lado-p { font: 700 2.6rem/1 var(--g-led); white-space: nowrap;
  color: var(--led); text-shadow: var(--led-brillo); }
/* Antes de empezar, el 0-0 no es un marcador: es que todavía no hay nada. */
.gr-c.previo .gr-lado-p { color: var(--tinta-3); opacity: .5; text-shadow: none; }
.gr-c-pie { min-height: 1.2em; margin-top: var(--e2); font-size: .88rem; color: var(--tinta-2); }

.gr-puntos { display: flex; justify-content: center; gap: 7px; padding: 0 0 var(--e4); }
.gr-puntos i { width: 7px; height: 7px; background: var(--linea-fuerte); cursor: pointer;
  border: 0; padding: 0; }
.gr-puntos i.on { background: var(--marca); }

/* ── la tabla, en corto ── */
.gr-tabla { padding: var(--e4); border-top: 1px solid var(--linea); }
.gr-tabla h3 { font: 800 11.5px/1 var(--g-sans); letter-spacing: .14em; text-transform: uppercase;
  color: var(--tinta-3); margin-bottom: var(--e3); }
.gr-t { width: 100%; border-collapse: collapse; font-size: .92rem; }
.gr-t th { font: 700 10px/1 var(--g-sans); letter-spacing: .08em; text-transform: uppercase;
  color: var(--tinta-3); text-align: left; padding: 0 6px 8px; }
.gr-t td { padding: 9px 6px; border-top: 1px solid var(--linea); }
.gr-t .num { text-align: right; width: 42px; }
.gr-t .pts { font-weight: 800; }
.gr-t .gr-t-eq { display: flex; align-items: center; gap: 8px; }
.gr-t tr.yo td { background: var(--hundido-2); font-weight: 700; }
.gr-t tr.yo td:first-child { box-shadow: inset 3px 0 0 var(--marca); }

.gr-carga, .gr-vacia { padding: var(--e6) var(--e4); text-align: center; color: var(--tinta-3); }
.gr-vacia i { font-size: 2rem; display: block; margin-bottom: var(--e3); }
.gr-vacia b { color: var(--tinta); }

/* En un portátil la tira no tiene por qué ocupar 1400 px: la tarjeta es una ficha. */
@media (min-width: 720px) {
  #gradaBody { max-width: 560px; margin: 0 auto; border-inline: 1px solid var(--linea);
    min-height: 100dvh; }
  .gr-lado-p { font-size: 3rem; }
}
@media (prefers-reduced-motion: reduce) {
  .gr-tira { scroll-behavior: auto; }
  .gr-viva { animation: none; }
}

/* ═══ LA ARENA ════════════════════════════════════════════════════════════
   El marcador del pabellón: UN partido en el televisor, leído desde veinte metros.
   Todo lo que no sea el marcador va en una franja fina; el marcador se lleva el resto.

   El tamaño se limita por LOS DOS EJES —`min(vh, vw)`— y no solo por el alto: un
   marcador dimensionado con `vh` a secas desborda a lo ancho en cuanto llega a dos
   cifras en una pantalla apaisada, y esta pantalla existe para las apaisadas. */
/* Una columna de alto completo con la cabecera y el pie fijos y el marcador quedándose lo
   que sobre. Antes eran tres altos en `vh` que sumaban 100 — y dejaban de sumar 100 en
   cuanto un `min-height` entraba en juego: en una tableta apaisada sobraban 9 px y la
   página, que no debería tener scroll, lo tenía. */
#arenaBody { display: flex; flex-direction: column; height: 100dvh; overflow: hidden; }
.ar-cab {
  display: flex; align-items: center; gap: var(--e4); flex: none;
  height: 9vh; min-height: 44px; padding: 0 clamp(12px, 2vw, 32px);
  border-bottom: 1px solid var(--linea); background: var(--papel);
}
.ar-c {
  font: 800 clamp(13px, 2.4vh, 30px)/1 var(--g-sans); letter-spacing: .1em; text-transform: uppercase;
  color: var(--tinta); background: var(--hundido); border: 1px solid var(--linea-fuerte);
  padding: .5em .8em; cursor: pointer; flex: none; border-radius: 0;
}
.ar-c:hover { background: var(--hundido-2); }
.ar-ev {
  flex: 1; min-width: 0; font: 700 clamp(11px, 2vh, 24px)/1 var(--g-sans); letter-spacing: .06em;
  text-transform: uppercase; color: var(--tinta-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* El aviso de congelación ocupa sitio de verdad: es el fallo más caro de esta pantalla
   —doscientas personas dando por bueno un marcador de hace cinco minutos—. */
.ar-red {
  flex: none; font: 800 clamp(10px, 1.9vh, 22px)/1 var(--g-sans); letter-spacing: .12em;
  text-transform: uppercase; padding: .5em .7em;
  border: 2px solid var(--linea-fuerte); color: var(--tinta-3);
}
.ar-red.flojo { color: var(--alerta-tx); border-color: currentColor; }
.ar-red.mal   { color: var(--g-rojo-tx); border-color: currentColor;
                animation: arLatido 1.2s infinite; }
@keyframes arLatido { 0%, 100% { opacity: 1 } 50% { opacity: .3 } }

/* Columnas en fracciones FIJAS, no `auto`. Con la del medio en `auto` el reloj mandaba
   sobre el reparto: a 1920 se llevaba 1000 px y dejaba 460 por equipo, así que el marcador
   —dimensionado contra el viewport— se salía 41 px de su columna y la cortaba. */
.ar {
  display: grid; grid-template-columns: 38fr 24fr 38fr; align-items: stretch;
  flex: 1; min-height: 0; gap: 1px; background: var(--linea);
}
/* Cada columna se mide a SÍ MISMA (`cqw`) y no al viewport: es lo único que garantiza que
   la cifra quepa, porque lo que la limita es el ancho de su columna, no el de la pantalla.
   El tope se calcula para TRES cifras —un partido puede pasar de 100— y el `vh` evita que
   en una pantalla muy ancha y baja el marcador se coma el alto. */
.ar-eq {
  container-type: inline-size;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(4px, 1.5vh, 18px); padding: clamp(8px, 2vh, 28px) clamp(6px, 1.5vw, 24px);
  background: var(--papel); border-top: clamp(8px, 1.6vh, 20px) solid var(--eq, var(--tinta-3));
  min-width: 0; overflow: hidden;
}
/* El nombre se PARTE en dos renglones en vez de cortarse: los equipos de colores caben en
   uno, pero un torneo externo llega con «Colegio San Ignacio» y recortarlo a «Colegio San…»
   en el marcador del pabellón deja a media tribuna sin saber quién juega. */
.ar-eq-n {
  font: 800 clamp(15px, min(7vh, 16cqw), 72px)/1.05 var(--g-sans); letter-spacing: .02em;
  text-transform: uppercase; text-align: center; color: var(--tinta);
  max-width: 100%; overflow: hidden;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; line-clamp: 3;
}
.ar-eq-n.medio { font-size: clamp(15px, min(5.5vh, 11cqw), 56px); }
.ar-eq-n.largo { font-size: clamp(14px, min(4.5vh, 8cqw), 44px); }
/* Cada cifra LED ocupa .816em: con 58cqw caben dos en el 95 % de la columna, y un
   partido que pasa de 100 (`.c3`) baja a 39cqw para que la tercera no se corte. */
.ar-eq-p {
  font: 700 clamp(48px, min(40vh, 58cqw), 520px)/1 var(--g-led);
  letter-spacing: normal; white-space: nowrap;
  color: var(--led); text-shadow: var(--led-brillo);
}
.ar-eq-p.c3 { font-size: clamp(40px, min(40vh, 39cqw), 380px); }
.ar.previo .ar-eq-p { color: var(--tinta-3); opacity: .45; text-shadow: none; }

.ar-medio {
  container-type: inline-size;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(4px, 1.2vh, 14px); padding: 0 clamp(6px, 1.5vw, 28px); background: var(--papel);
  min-width: 0; overflow: hidden;
}
.ar-per {
  font: 800 clamp(11px, min(4vh, 9cqw), 48px)/1 var(--g-sans); letter-spacing: .12em;
  text-transform: uppercase; color: var(--tinta-3); white-space: nowrap;
}
.ar-per b { font: 700 1.3em/1 var(--g-led); letter-spacing: normal; color: var(--led); text-shadow: var(--led-brillo); }
/* «10:00» en LED mide 3,46em: 26cqw lo deja en el 90 % de la columna del medio. */
.ar-reloj {
  font: 700 clamp(26px, min(14vh, 26cqw), 150px)/1 var(--g-led); letter-spacing: normal;
  color: var(--tinta); white-space: nowrap;
}
.ar.vivo .ar-reloj { color: var(--led); text-shadow: var(--led-brillo); }
.ar-reloj.ar-txt { color: var(--tinta-3); }

.ar-pie {
  display: flex; align-items: center; gap: clamp(8px, 2vw, 28px); flex: none;
  height: 13vh; min-height: 40px; padding: 0 clamp(12px, 2vw, 32px);
  border-top: 1px solid var(--linea); background: var(--hundido); overflow: hidden;
}
.ar-pie-e { font: 800 clamp(10px, 2vh, 24px)/1 var(--g-sans); letter-spacing: .16em;
  text-transform: uppercase; color: var(--tinta-3); flex: none; }
.ar-pie-h { font: 700 clamp(16px, min(5vh, 4vw), 56px)/1 var(--g-led); color: var(--tinta); flex: none; }
.ar-pie-t { font: 700 clamp(13px, min(3.6vh, 3vw), 40px)/1.1 var(--g-sans); text-transform: uppercase;
  color: var(--tinta-2); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.ar-nada, .ar-carga { flex: 1; min-height: 0; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: var(--e3); text-align: center; padding: var(--e5); }
.ar-nada b { font: 800 clamp(20px, 5vh, 56px)/1.1 var(--g-sans); text-transform: uppercase; }
.ar-nada span { color: var(--tinta-3); font-size: clamp(13px, 2.2vh, 24px); }

/* En vertical —una tableta de pie, o el portátil girado— las tres columnas no caben:
   los equipos se apilan y el reloj queda en medio, que es como se lee un marcador. */
@media (max-aspect-ratio: 1/1) {
  .ar { grid-template-columns: 1fr; grid-template-rows: 1fr auto 1fr; }
  /* En vertical la baldosa es ancha y baja: el mismo `cqw` daría una cifra más alta que su
     propia fila. Manda el alto de la fila, y el nombre pasa al lado en vez de encima. */
  .ar-eq { flex-direction: row; justify-content: space-between; gap: var(--e4); }
  /* De pie el nombre va al LADO del marcador, con la mitad del ancho: aquí no se recorta a
     tres renglones, se deja correr. Un nombre largo hace crecer su fila y el marcador se
     achica solo, que es mejor que enseñar «Colegio San Ignacio de…». */
  .ar-eq-n { text-align: left; font-size: clamp(14px, min(6vw, 26cqw), 48px);
    -webkit-line-clamp: none; line-clamp: none; display: block; }
  .ar-eq-n.medio { font-size: clamp(14px, min(5vw, 22cqw), 40px); }
  .ar-eq-n.largo { font-size: clamp(13px, min(4vw, 17cqw), 32px); }
  .ar-eq-p { font-size: clamp(44px, min(30vh, 26cqw), 200px); }
  .ar-eq-p.c3 { font-size: clamp(40px, min(30vh, 20cqw), 160px); }
  .ar-medio { flex-direction: row; gap: var(--e4); padding: clamp(6px, 2vh, 18px); }
  /* En fila el rótulo comparte ancho con el reloj: a 390 px «3.º CUARTO» a 9cqw se salía por la izquierda y se perdía el «3.º». */
  .ar-per { font-size: clamp(11px, min(4vh, 5cqw), 48px); }
  .ar-reloj { font-size: clamp(26px, min(9vh, 17cqw), 110px); }   /* 22cqw + el rótulo de al lado pasaban de los 390 px */
}
@media (prefers-reduced-motion: reduce) { .ar-red.mal { animation: none; } }

/* ═══ OBS · la arena en modo transmisión (`?overlay=1`, ui.js `pintarOverlay`) ═══════════════
   La «Fuente de navegador» de OBS pone la página sobre el video y lo que no se pinta queda
   transparente. Así que aquí NO queda nada de la arena: ni fondo, ni cabecera, ni velo de
   carga, ni Elso. Solo una barra con el marcador.

   · Transparente de verdad. `html.ov` lo pone el <head> de index.html antes del primer pintado
     (si no, hay un destello oscuro hasta que carga el JS). `color-scheme: normal` y no `dark`: con
     `dark` el navegador pinta el lienzo de negro opaco aunque el fondo diga transparente, y OBS
     lo muestra como un cuadro negro. Los tokens oscuros se quedan (`.siempre-oscuro`): la letra es clara.
   · Todo en `em`, y el `em` sale del ancho de la fuente (`1vw`): la barra está pensada para
     1920×1080 (a tamaño m, ~1090 px) y escala sola a 1280×720. `tam` solo cambia ese factor.
   · Nombres de equipo en una línea, con «…»: dos renglones crecerían la barra sobre el video. */
html.ov { color-scheme: normal; scrollbar-gutter: auto; overflow: hidden; }
html.ov,
html.ov body,
html.ov :is(.marco, .marco-cue, .contenedor, main, #p-arena, #arenaBody) { background: transparent !important; }
html.ov :is(#gridCarga, .guia-caja, .ayuda-elso, #toast, .tour, .franja, .lp-pie, .ap-tabbar, .barra, .g-idioma) { display: none !important; }

div.ov { --k: 1; --ov-fondo: rgb(10 20 38 / .92);   /* color fijo: el marino de GRID (--fondo, #0a1426) al 92 %, que deja ver un poco el video */
  position: fixed; left: 50%; transform: translateX(-50%); font: 700 calc(1vw * var(--k))/1 var(--g-sans); color: var(--fuerte); }
.ov-s { --k: .8; }
.ov-l { --k: 1.25; }
.ov-abajo  { bottom: 4vh; }
.ov-arriba { top: 4vh; }
.ov-barra { display: flex; align-items: stretch; width: 57em; height: 5em; background: var(--ov-fondo); }

.ov-eq { position: relative; flex: 1 1 0; min-width: 0; display: flex; align-items: center; gap: .7em; padding: 0 .3em 0 1.2em; }
.ov-vis { flex-direction: row-reverse; padding: 0 1.2em 0 .3em; }
/* La banda fina del color del equipo, en el borde de su lado. */
.ov-banda { position: absolute; top: 0; bottom: 0; width: .4em; background: var(--eq, var(--tinta-3)); }
.ov-loc .ov-banda { left: 0; }
.ov-vis .ov-banda { right: 0; }
div.ov .esc { width: 3.2em; height: 3.2em; }
div.ov .esc:has(img) { padding: .2em; }
.ov-n { flex: 1; min-width: 0; font: 800 1.45em/1.1 var(--g-sans); letter-spacing: .02em; text-transform: uppercase;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ov-vis .ov-n { text-align: right; }
/* Como en la arena, la LONGITUD manda el tamaño: un nombre largo baja de letra antes de recortarse. */
.ov-n.medio { font-size: 1.2em; }
.ov-n.largo { font-size: 1.05em; }

/* El marcador, en LED como el de la arena, centrado en la barra. El «Bonus» va en absoluto, en el
   hueco de debajo: al aparecer o irse la cifra no se mueve. */
.ov-p { position: relative; flex: none; width: 3.8em; height: 100%; display: flex; align-items: center; justify-content: center; }
.ov-pt { font: 700 2.1em/1 var(--g-led); letter-spacing: normal; white-space: nowrap; color: var(--led); text-shadow: var(--led-brillo); }
.ov-pt.c3 { font-size: 1.6em; }
.ov-previo .ov-pt { color: var(--tinta-3); opacity: .55; text-shadow: none; }
.ov-bonus { position: absolute; bottom: .35em; left: 50%; transform: translateX(-50%); padding: .22em .65em;
  background: var(--error); color: var(--fuerte);   /* blanco: la arena para transmisión siempre lleva los tokens oscuros */
  font: 800 .6em/1 var(--g-sans); letter-spacing: .12em; text-transform: uppercase; }

/* Estado y reloj, entre rayas. */
.ov-medio { flex: none; width: 13em; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .35em;
  border-left: 1px solid var(--linea-fuerte); border-right: 1px solid var(--linea-fuerte); }
.ov-est { display: inline-flex; align-items: center; gap: .55em; font: 800 .72em/1 var(--g-sans); letter-spacing: .18em;
  text-transform: uppercase; color: var(--tinta-2); white-space: nowrap; }
.ov-vivo .ov-est { color: var(--fuerte); }
.ov-fin .ov-est { font-size: 1.1em; color: var(--fuerte); }
.ov-punto { width: .65em; height: .65em; border-radius: 50%; background: var(--g-rojo-tx); }
.ov-reloj { display: inline-flex; align-items: center; gap: .7em; }
/* El período va en letra normal y blanca, no en LED: un «º» en segmentos se lee «2 o 07:42». */
.ov-per { font: 800 .85em/1 var(--g-sans); color: var(--fuerte); white-space: nowrap; }   /* «2.º cuarto» / «Prórroga 2»: una línea */
.ov-reloj b { font: 700 1.65em/1 var(--g-led); letter-spacing: normal; color: var(--led); text-shadow: var(--led-brillo); }
.ov-hora { font: 700 1.05em/1 var(--g-sans); color: var(--fuerte); white-space: nowrap; }

/* La firma, discreta, pegada a la derecha de la barra (la barra queda centrada). El punto gris
   se enciende si dejan de llegar datos: la barra se queda con lo último, sin cartel. */
.ov-firma { position: absolute; left: 100%; bottom: 0; margin-left: .5em; height: 2.9em; padding: 0 .9em 0 .8em; box-sizing: border-box;
  display: flex; align-items: center; gap: .7em; background: var(--ov-fondo);
  font: 900 .7em/1 var(--g-sans); letter-spacing: .26em; color: var(--tinta-2); }
/* Con la barra arriba, la firma cuelga del borde de arriba: queda del lado del video que la barra toca. */
.ov-arriba .ov-firma { top: 0; bottom: auto; }
.ov-red { width: .65em; height: .65em; border-radius: 50%; background: var(--tinta-3); visibility: hidden; margin-right: -.1em; }
.ov-red.ov-sin-red { visibility: visible; }

/* ═══ §18 · ELEGIR FORMATO ────────────────────────────────────────────────────
   Una fila por opción: icono · nombre y una línea · la cifra que decide, a la derecha.

   El detalle NO va en un panel al lado, como en la referencia que lo inspiró: ese panel
   se llena al PASAR EL RATÓN, y en un teléfono no hay ratón —quedaría una columna muerta
   en la mitad de los anchos—. Aquí se despliega DENTRO de la opción elegida, así que hay
   una sola columna en todos los tamaños y el botón de confirmar nace donde se está
   mirando. El detalle es HERMANO de la fila y no hijo: un botón dentro de otro botón no
   es HTML válido y el navegador lo desarma. */
.fmt-lista { display: grid; }

.fmt-op {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center;
  gap: var(--e3); width: 100%; text-align: left; min-height: 60px;
  padding: var(--e3) 0; border: 0; border-radius: 0;
  background: none; color: var(--tinta); font-family: inherit; cursor: pointer;
  transition: background .12s;
}
/* Ventanas 2026: cada formato es una FILA (filete entre filas); la elegida se abre debajo en el único bloque teñido. */
.fmt-mas + .fmt-op, .fmt-op + .fmt-op { border-top: 1px solid var(--linea); }
.fmt-op:hover:not(:disabled) { background: color-mix(in srgb, var(--fuerte) 5%, transparent); }
.fmt-op[aria-checked="true"] .fmt-tx b { color: var(--marca-osc); }
.fmt-op:disabled { opacity: .5; cursor: not-allowed; }

.fmt-ico { display: flex; justify-content: center; gap: 2px; width: 44px; color: var(--tinta-2); font-size: 1.15rem; line-height: 1; }   /* columna fija: los textos de las filas arrancan en la misma línea */
.fmt-op:disabled .fmt-ico { color: var(--tinta-3); }

.fmt-tx { display: grid; gap: 2px; min-width: 0; }
.fmt-tx b { font-size: .98rem; font-weight: 700; }
.fmt-tx em { font-style: normal; font-size: .84rem; color: var(--tinta-2); }

/* La cifra de la derecha es el argumento entero de la pantalla: en una jornada formativa
   se elige formato por cuántos partidos juega cada niño, no por el nombre del formato. */
.fmt-meta { text-align: right; font-family: var(--g-mono); font-size: 1.1rem; font-weight: 700;
  white-space: nowrap; font-variant-numeric: tabular-nums; }
.fmt-meta small { display: block; font: 500 12px/1.3 var(--g-sans); color: var(--tinta-3); letter-spacing: 0; text-transform: none; }

.fmt-mas { display: none; padding: 0 var(--e3) var(--e3); margin-bottom: var(--e3);
  border-radius: 10px; background: var(--hundido-2); }
.fmt-op[aria-checked="true"] + .fmt-mas { display: block; }

.fmt-rot { font: 600 12px/1.3 var(--g-sans); color: var(--tinta-3);
  margin: var(--e3) 0 var(--e2); }
.fmt-pasos { display: grid; gap: 6px; margin-bottom: var(--e3); }
.fmt-paso { display: flex; align-items: center; gap: 8px; font-size: .88rem; }
.fmt-paso i { color: var(--marca); font-size: .95rem; }
.fmt-cifras { display: flex; gap: var(--e4); flex-wrap: wrap; font-size: .84rem;
  font-variant-numeric: tabular-nums; margin-bottom: var(--e3); color: var(--tinta-2); }
.fmt-cifras b { font-family: var(--g-mono); font-size: 1rem; color: var(--tinta); }
/* Los distintivos —«Recomendado», «No cabe»— van en la FILA y no en el detalle: son
   justamente lo que decide cuál abrir. En el detalle no los vería nadie hasta después de
   elegir, que es tarde. «Cabe bien» no se enseña: es lo normal, y decirlo en las cuatro
   filas es tinta que no cambia ninguna decisión. */
.fmt-n { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
/* Rótulo de sección dentro de una hoja. Mismo tipo de letra que el del detalle de un
   formato: son la misma idea —decir de qué va el bloque que viene— en dos sitios. */
.hoja-rot { font-family: var(--g-mono); font-size: .68rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--tinta-3);
  padding: var(--e3) var(--e3) 4px; }

/* ═══ §19 · FALTAS Y PUNTOS EN LA CONSOLA ────────────────────────────────────
   Una sola ventana para «¿de quién es la falta?» y «¿quién anotó?». El camino principal son las
   camisetas de la plantilla, de un toque: en un partido las faltas y los puntos se reparten entre
   ocho o diez dorsales y casi todo es repetir a alguien. El teclado numérico es para el que no
   está en la plantilla. */
/* La capa es la ventana de siempre (piezas.css «Ventanas 2026»: velo, caja chica de 420, hoja desde abajo en el celular). */
.fl-capa { position: fixed; inset: 0; z-index: 1150; display: none; align-items: center; justify-content: center; padding: 24px; }

/* Con una plantilla larga la ventana no cabe en un celular: el título y los botones de abajo se
   quedan fijos y lo del medio (`.fl-cue`) tiene su propio scroll. */
.fl { display: flex; flex-direction: column; overflow: hidden; }
.fl-cue { flex: 1; display: grid; gap: 12px; align-content: start; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 0 var(--v-pad) 16px; }
.fl-cab, .fl-pie { flex: none; }

.fl-cab { display: flex; align-items: flex-start; gap: 12px; padding: 18px var(--v-pad) 12px; transition: box-shadow .15s; }
.corrido > .fl-cab { box-shadow: 0 1px 0 var(--linea); }
.fl-cab > .tx { flex: 1; min-width: 0; }
.fl-cab > .v-x { margin: -6px -8px 0 0; }
.fl-cab .v-sub { margin: 4px 0 0; display: block; }
.fl-cab .v-sub .dot { margin-right: 8px; vertical-align: 1px; }
.fl-cab .v-sub .pista { display: inline; margin: 0; font-size: inherit; color: inherit; }
.fl-cab .v-sub b { color: var(--tinta); }

/* Las camisetas: rejilla de 4. Cada una es un botón entero, superficie de botón sin filete. */
.fl-cams { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.fl-cam { display: block; width: 100%; min-width: 0; min-height: 44px; padding: 0; border: 0; border-radius: 10px; background: var(--hundido-2);
  color: inherit; font: inherit; cursor: pointer; }
html[data-tema="claro"] .fl-cam { background: var(--alzado); }
.fl-cam .cam { width: 100%; box-sizing: border-box; border: 0; background: none; padding: 10px 4px 8px; }
.fl-cam:active { background: var(--linea); }
/* La cifra de la esquina es lo que hay que leer de un vistazo. */
.fl-cam .cam-esq { top: 6px; right: 8px; font: 800 12px/1 var(--g-mono); color: var(--tinta-2); }
/* Cuatro personales: una más y sale. Cinco: fuera. Se avisa ANTES, porque una mesa que se
   entera al quinto toque ya dejó jugar a alguien que no podía. */
.fl-cam.casi .cam-esq { color: var(--alerta-tx); }
.fl-cam.fuera .cam-esq { color: var(--error); }
.fl-cam:disabled { cursor: not-allowed; opacity: .4; }   /* fuera del partido: apagada, como los demás botones sin uso */

.fl-pantalla { text-align: center; font: 700 2.2rem/1 var(--g-led); letter-spacing: normal;
  padding: var(--e2); background: var(--hundido); border-radius: var(--r-sm); min-height: 52px;
  color: var(--tinta); }
/* «dorsal» es una palabra: en segmentos se leería «dorSAL». */
.fl-pantalla.vacia { color: var(--tinta-3); font: 700 1rem/36px var(--g-mono); letter-spacing: .06em; text-shadow: none; }

.fl-pad { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.fl-pad button { min-height: 56px; border: 0; border-radius: 10px;
  background: var(--alzado); color: var(--tinta); font: 700 1.35rem/1 var(--g-led); cursor: pointer; }
.fl-pad button:active { background: var(--linea); }
/* La acción principal del teclado, en blanco: rojo aquí sería «borrar» o «error». */
.fl-pad .fl-ok { background: var(--tinta); border-color: var(--tinta); color: var(--fondo);
  font-family: var(--g-sans); font-size: 1rem; }
.fl-pad .fl-ok:disabled { opacity: .4; cursor: not-allowed; }

/* El pie de la ventana (Ventanas 2026): botones de 44 a la derecha, en fila también en el celular; «Deshacer» discreto. */
.fl-pie { display: flex; justify-content: flex-end; gap: 8px; padding: 12px var(--v-pad); border-top: 1px solid var(--linea); }
.fl-pie button { flex: 0 1 auto; min-height: 44px; padding: 0 16px; border: 0; border-radius: 10px; background: var(--alzado); color: var(--tinta);
  font: 700 14px/1.15 var(--g-sans); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: 8px; white-space: nowrap; }
.fl-pie button:hover:not(:disabled) { background: var(--linea-fuerte); }
.fl-pie .fl-des { background: none; color: var(--tinta-2); }
/* En el computador los tres no cabían en la caja de 420 y el primero se salía por la izquierda (revisión 27-oct): «Deshacer», que es
   texto, va a la izquierda con menos relleno y los otros dos a la derecha. */
@media (min-width: 621px) { .fl-pie button { padding: 0 14px; } .fl-pie .fl-des { order: -1; margin-right: auto; padding: 0 10px; } }
.fl-pie .fl-des:hover:not(:disabled) { background: var(--hundido-2); color: var(--tinta); }
.fl-pie .fi { font-size: 14px; line-height: 1; }
.fl-pie .fi::before { font-family: uicons-solid-rounded !important; }
.fl-pie button:disabled { opacity: .35; cursor: not-allowed; }
@media (max-width: 620px) { .fl-pie { padding-bottom: calc(12px + env(safe-area-inset-bottom)); } .fl-pie button { flex: 1 1 0; min-width: 0; padding: 0 6px; font-size: 13.5px; white-space: normal; } }

/* R3 · tipo de falta (FIBA 2026): las fichas de elección de las ventanas (piezas.css «Ventanas 2026»), una fila de tres por fila;
   «Entrenador / Banco» son dos botones grandes que ocupan el lugar de las camisetas. */
.fl-tipos { display: flex; width: 100%; box-sizing: border-box; }
.fl-tipos > button { flex: 1 1 auto; justify-content: center; padding: 0 10px; }
.fl-ents { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.fl-ents button { min-height: 72px; border: 0; border-radius: 10px; background: var(--alzado);
  color: var(--tinta); font: 700 1rem var(--g-sans); cursor: pointer; }
.fl-ents button:active { background: var(--linea); }
/* Descalificado: «fuera» con «Desc.» debajo de la camiseta, en rojo (el título del botón y su aria-label dicen «Descalificado»; entero no cabía en 76 px). */
.fl-cam.desc .cam-nom { color: var(--error); }

/* R3 · el aviso al árbitro: franja ARRIBA, encima de la ventana de camisetas (z-index mayor), con borde rojo. Se queda hasta tocar «Avisé»;
   el de bonus es más chico y se va solo. Mientras está, la ventana y el aviso flotante se corren (`--aviso-h`, medida en ui.js) para que
   la franja nunca tape los botones de la ventana. */
.aviso-arb { position: fixed; z-index: 1300; top: max(8px, env(safe-area-inset-top)); left: 12px; right: 12px; margin-inline: auto;
  max-width: 440px; display: grid; gap: 8px; }
.aviso-arb[hidden] { display: none; }
/* La franja es oscura con letra clara en los dos modos, como el aviso flotante: los colores viven aquí, una vez. */
.aviso-arb { --av-fondo: #16161c; --av-tx: #fff; --av-tx-2: #ffd9d7; --av-pulso: #ffa39e; --av-sombra: rgba(0, 0, 0, .5); }   /* color fijo: franja oscura en claro y en oscuro */
.aviso-it { display: flex; align-items: center; gap: 12px; padding: 12px; border-radius: var(--r); background: var(--av-fondo); color: var(--av-tx);
  border: 2px solid var(--error); box-shadow: 0 8px 28px var(--av-sombra); }
.aviso-it.bonus { padding: 8px 12px; border-width: 1px; }
.aviso-ico { flex: none; display: grid; place-items: center; width: 44px; }
.aviso-ico svg { width: 44px; height: auto; display: block; }
.aviso-ico .fi { font-size: 26px; }
.aviso-it.bonus .aviso-ico { width: 28px; }
.aviso-tx { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.aviso-tx b { font: 800 1rem/1.25 var(--g-sans); overflow-wrap: anywhere; }
.aviso-tx span { font-size: .84rem; line-height: 1.3; color: var(--av-tx-2); }
.aviso-it.bonus .aviso-tx b { font-size: .88rem; }
.aviso-it.bonus .aviso-tx span { font-size: .78rem; }
.aviso-it button { flex: none; min-height: 44px; padding: 0 16px; border: 0; border-radius: var(--r-sm); background: var(--av-tx); color: var(--av-fondo);
  font: 800 .95rem var(--g-sans); cursor: pointer; }
@media (prefers-reduced-motion: no-preference) { .aviso-it.grave { animation: avisoLate 1.1s ease-in-out infinite; } }
@keyframes avisoLate { 50% { border-color: var(--av-pulso); } }
body.con-aviso .fl-capa { padding-top: calc(var(--aviso-h, 0px) + 16px); }
body.con-aviso .fl { max-height: calc(100dvh - 48px - var(--aviso-h, 0px)); }
body.con-aviso .toast { bottom: auto; top: calc(var(--aviso-h, 0px) + 24px); }

/* El bonus en la pantalla del pabellón: se lee a veinte metros o no sirve de nada. */
.ar-bonus { display: inline-block; margin-top: clamp(4px, 1vh, 12px);
  padding: clamp(2px, .6vh, 7px) clamp(8px, 2cqw, 20px); border-radius: var(--r-full);
  background: var(--error); color: #fff;   /* color fijo: blanco sobre el rojo de error (la Pantalla es siempre oscura) */
  font: 800 clamp(11px, min(2.6vh, 5cqw), 34px)/1 var(--g-sans);
  letter-spacing: .12em; text-transform: uppercase; }

/* ═══════════════════════════════════════════════════════════════════════════
   §20 · NÚMEROS DE TABLERO
   Todo número que se lee como en un tablero de baloncesto —marcador, reloj, período,
   posesión, faltas, los +1/+2/+3 y el teclado de dorsales— va en segmentos LED:
   DSEG7 Classic Bold (SIL OFL, paquete npm `dseg` 0.46.0, sin modificar),
   autohospedada como 'DSEG7'. A DSEG7 le falta el «+»: lo pone DSEG14, misma
   familia y mismos anchos, que solo se descarga si en la página aparece un «+».
   Encendido = rojo con un brillo MUY ligero. Lo que no está en juego (horas, el -1)
   va en gris, como un segmento apagado.
   OJO: DSEG7 también dibuja LETRAS en segmentos. Va solo en elementos con cifras; en
   un rótulo con número («Período 3», «2 faltas») el número va en su propio `<b>`.
   ═══════════════════════════════════════════════════════════════════════════ */
@font-face {
  font-family: 'DSEG7';
  src: url('img/dseg7-classic-bold.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'DSEG14';
  src: url('img/dseg14-classic-bold.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap; unicode-range: U+002B;
}
@keyframes ledLate { 50% { opacity: .3; } }

/* ─── La piel de tablero: negro y gris ──────────────────────────────────────────
   Las cuatro pantallas del marcador reasignan sus grises a NEUTROS: los del resto de
   la app tiran a azul pizarra y, junto al rojo LED, parecían otro aparato. Mismo truco
   que el tema oscuro de arriba —cambiar lo que significan los tokens, no reescribir
   cada componente—. Solo tokens que el JS NO escribe en <html>: los de marca del club
   (`--marca`, `--marino`…) no se tocan, o esta regla le taparía su color.
   Los grises van SOLO en oscuro (P2): Anotar, la consola de cancha y la grada siguen el modo,
   y en claro llevan los tokens claros de toda la app, como «App · Demo → Anotar» de la muestra
   (tarjetas blancas y los números del marcador en letra fuerte, oscura). Antes la piel ponía su
   negro encima de los `--alzado`/`--fuerte` claros y salía mitad y mitad. La Pantalla para el
   público pone `.siempre-oscuro` en <html> y lleva la piel siempre.
   `--r-full: 0` apaga las píldoras que el sistema dejó vivas (el aviso flotante, el
   «Bonus», la etiqueta del equipo en el teclado de faltas): aquí todo es de esquina viva. */
/* Ola 3 · decisión del gestor (27-oct): la MESA en oscuro es el azul marino de la maqueta (celular-2026), no los grises neutros.
   La mesa, sus hojas (faltas) y la planilla que se abre desde ella; la grada, la arena y la impresión (.pl-imp) siguen en gris (abajo). */
html:is(:not([data-tema="claro"]), .siempre-oscuro) :is(body.es-consola, .mesa-capa, body.con-mesa .fl-capa, .pl-capa) {
  --fondo: #0a1426; --papel: #0f1c35; --hundido: #0c182d; --hundido-2: #13223f; --alzado: #1a2b4d;   /* color fijo: el marino de la maqueta, solo en oscuro */
  --linea: #24365a; --linea-fuerte: #2c4170; --g-negro: #0a1426;                                       /* color fijo: ídem */
  --tinta: #e8edf5; --tinta-2: #a9b4c8; --tinta-3: #7a87a0;                                            /* color fijo: ídem */
}
html:is(:not([data-tema="claro"]), .siempre-oscuro) :is(body.es-grada, body.es-arena, .pl-imp) {
  --fondo: #0a0a0a; --papel: #111111; --hundido: #161616; --hundido-2: #1c1c1c;   /* color fijo: los grises neutros del tablero, solo en oscuro */
  --g-negro: #0a0a0a; --linea: #262626; --linea-fuerte: #3a3a3a;                  /* color fijo: ídem */
  --tinta: #f2f2f2; --tinta-2: #a8a8a8; --tinta-3: #858585;                         /* color fijo: ídem */
}
body:is(.es-consola, .es-grada, .es-arena), .mesa-capa, body.con-mesa .fl-capa, .pl-capa, .pl-imp { --r-full: 0; }
body:is(.es-consola, .es-grada, .es-arena) .punto { border-radius: 0; }
/* El aviso flotante sobre el tablero: gris neutro, solo con la piel (en oscuro). En claro se queda
   el oscuro de toda la app (sistema.css y `.toast.success/.error`): su letra es fija y clara, y con
   el `--hundido-2` claro de fondo quedaba en 1,1:1. */
html:is(:not([data-tema="claro"]), .siempre-oscuro) body:is(.es-consola, .es-grada, .es-arena) .toast {
  background: var(--hundido-2); border: 1px solid var(--linea-fuerte); }

/* ─── El escudo en el marcador ─────────────────────────────────────────────────
   El de cada equipo si lo subieron, y si no el emblema que `escudoEquipo` dibuja con su
   color. Donde ya hay una franja del color del equipo al lado (grada, torre), el escudo
   pierde la suya: dos franjas seguidas se leían como un borde roto. */
.gr-lado .esc { width: 36px; height: 36px; }
.ar-eq-id { display: flex; flex-direction: column; align-items: center;
  gap: clamp(6px, 1.4vh, 16px); max-width: 100%; min-width: 0; }
.ar-eq-id .esc { width: clamp(40px, min(12vh, 22cqw), 150px); height: clamp(40px, min(12vh, 22cqw), 150px); }
/* De pie, el escudo va ENCIMA del nombre y no al lado: al lado le robaba el ancho y
   «NARANJA» salía «NARANJ». La fila es alta y lo que falta es ancho. */
@media (max-aspect-ratio: 1/1) {
  .ar-eq-id { align-items: flex-start; }
  .ar-eq-id .esc { width: clamp(32px, min(7vh, 15cqw), 90px); height: clamp(32px, min(7vh, 15cqw), 90px); }
}


/* ─── La camiseta de cada equipo (camisetas.js) ──────────────────────────────────
   El cuadro que arma `Camiseta.pieza()`: el dibujo, el nombre debajo y, si viene, la
   cifra en la esquina (el número del equipo en la jornada). Mismo cuadro hundido que el
   resto de las tarjetas; el nombre en la letra normal de GRID y la cifra en la mono. */
.cam { position: relative; display: inline-flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 10px 8px 9px; background: var(--hundido); border: 1px solid var(--linea); border-radius: var(--r-sm); }
.cam > svg { display: block; max-width: 100%; height: auto; }
.cam-nom { font: 700 12px/1.3 var(--g-sans); color: var(--tinta); text-align: center; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cam-esq { position: absolute; top: 6px; right: 8px; font: 600 11px/1 var(--g-mono); color: var(--tinta-2); }

/* Las camisetas en las pantallas: la fila de Ajustes → La jornada y los jugadores de la ficha del equipo.
   Ancho fijo por cuadro: así un nombre largo se corta con «…» (.cam-nom) en vez de ensanchar la fila. */
.cam-fila { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: var(--e3); }
.cam-fila .cam { width: 88px; }
.cam-propias { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; margin-top: var(--e3); }
.cam-propias .pista { margin: 0; }
.ficha-cams { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 10px; }
.ficha-cams .cam { width: 100%; min-width: 0; }

/* ─── El creador de camisetas (abrirCreadorCamiseta, tablero.js) ─────────────────────
   La maqueta aprobada: vista grande a la izquierda y opciones a la derecha; en el celular la vista va
   arriba, pequeña y pegada (la ves cambiar mientras bajas por las opciones). Título fijo arriba y botón
   fijo abajo: solo el cuerpo hace scroll. Lo elegido va en gris con borde (aria-pressed), nunca en negro. */
/* Ventanas 2026: la ventana grande de todas; cabecera con el título 700 17 y, debajo, el punto del color con el nombre (sin pastilla).
   La vista previa es el único bloque teñido; las opciones son fichas sin filete. */
.modal:has(> .cam-ven) { padding: 0; max-width: 760px; overflow: hidden; }
.cam-ven { display: flex; flex-direction: column; max-height: calc(100dvh - 48px); }
.cam-cab { flex: none; display: flex; flex-direction: column; align-items: flex-start; gap: 4px; padding: 18px 56px 12px var(--v-pad); transition: box-shadow .15s; }
.corrido .cam-cab { box-shadow: 0 1px 0 var(--linea); }
.ventana .cam-cab h3 { margin: 0; font: 700 17px/1.3 var(--g-sans); text-transform: none; letter-spacing: 0; }
.cam-chip { display: inline-flex; align-items: center; gap: 8px; max-width: 100%; font: 500 13px/1.4 var(--g-sans); color: var(--tinta-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cam-punto { flex: none; width: 8px; height: 8px; border-radius: 50%; }
.cam-cue { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 4px var(--v-pad) 16px;
  display: grid; grid-template-columns: 280px minmax(0, 1fr); gap: 24px; align-items: start; }
.cam-prev { position: sticky; top: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
  padding: 26px 10px; background: radial-gradient(circle at 50% 40%, var(--alzado), var(--hundido) 70%); border-radius: 10px; }
.cam-prev small { font: 600 12px/1.3 var(--g-sans); letter-spacing: 0; text-transform: none; color: var(--tinta-3); }
.cam-grande svg { display: block; width: min(240px, 100%); height: auto; }
.cam-muestra { font: 800 18px/1.2 var(--g-sans); color: var(--tinta); }
/* `container-type`: las letras de 6 cuadros pasan a 3 por fila cuando el panel de opciones es angosto (@container abajo). */
.cam-ops { display: flex; flex-direction: column; gap: 16px; min-width: 0; container-type: inline-size; }
.cam-blq { min-width: 0; }
.cam-blq .rot { display: block; margin-bottom: 8px; }
/* Cuello (2 opciones) y borde (4). Cada segmentado va entero en UNA línea: si Cuello y Borde no caben juntos,
   el Borde baja a su propia fila completa (flex-wrap), nunca se parte en dos renglones (visto en un panel de ~800 px). */
.cam-dos { display: flex; flex-wrap: wrap; gap: 16px 28px; }
.cam-dos > .cam-blq { flex: 0 0 auto; max-width: 100%; }
.cam-dos .seg { flex-wrap: nowrap; }
.cam-dos .seg > button { white-space: nowrap; }
.cam-tiles { display: grid; grid-template-columns: repeat(var(--cols), minmax(0, 1fr)); gap: 10px; }
.cam-tiles--3 { max-width: 456px; }   /* tres acabados: cuadros como los de la maqueta, no de ancho completo */
.cam-op { display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 0; padding: 8px 4px; cursor: pointer;
  background: var(--hundido-2); border: 0; border-radius: 10px; color: var(--tinta-2); font: 600 11.5px/1.25 var(--f-texto); }
html[data-tema="claro"] .cam-op { background: var(--alzado); }
.cam-op:hover { color: var(--tinta); }
.cam-op[aria-pressed="true"] { background: var(--alzado); box-shadow: inset 0 0 0 1px var(--tinta-2); color: var(--tinta); }
html[data-tema="claro"] .cam-op[aria-pressed="true"] { background: var(--papel); }
.cam-op-dib { display: block; max-width: 100%; line-height: 0; }
.cam-op-dib svg { display: block; max-width: 100%; height: auto; }
/* El nombre NUNCA se parte a mitad de palabra (antes `overflow-wrap: anywhere`: «Universit/aria», «Deportiv/a»).
   Primero se achica la letra según el ancho del cuadro (cqw, de 9,5 a 11,5 px) para que quepa entero; si aun así una
   palabra no cabe, se corta con «…» (el nombre completo va en el `title` del botón). Entre palabras sí baja de renglón. */
.cam-op { container-type: inline-size; }
.cam-op-nom { max-width: 100%; text-align: center; overflow: hidden; text-overflow: ellipsis;
  overflow-wrap: normal; word-break: normal; hyphens: none; font-size: clamp(9.5px, 19cqw, 11.5px); }
.cam-cols { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.cam-sw { flex: none; width: 32px; height: 32px; padding: 0; cursor: pointer; border-radius: var(--r-sm); background: var(--sw);
  border: 1px solid color-mix(in srgb, var(--tinta) 28%, transparent); }
.cam-sw:hover { border-color: var(--tinta-3); }
.cam-sw[aria-pressed="true"], .cam-auto[aria-pressed="true"] { outline: 2px solid var(--tinta); outline-offset: 2px; }
.cam-auto { height: 32px; padding: 0 12px; cursor: pointer; background: var(--hundido-2); color: var(--tinta-2);
  border: 0; border-radius: 10px; font: 600 12.5px var(--g-sans); }
.cam-auto[aria-pressed="true"] { color: var(--tinta); background: var(--alzado); }
/* `.modal .cam-aviso`: `.modal .pista` (sistema.css) le ganaba el tamaño y el color. */
.modal .cam-aviso { margin: 8px 0 0; font-size: 12.5px; line-height: 1.45; color: var(--alerta-tx); }
.modal .cam-aviso[hidden] { display: none; }
.cam-jor { margin-top: -4px; }
.cam-pie { flex: none; display: flex; align-items: center; flex-wrap: wrap; gap: 8px 14px; padding: 12px var(--v-pad);
  border-top: 1px solid var(--linea); background: var(--papel); }
.cam-pie .btn { flex: none; white-space: nowrap; }
.cam-pie .pista { flex: 1 1 200px; min-width: 0; margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--tinta-2); }
/* Panel de opciones angosto (~800 px de pantalla): seis letras en una fila no dejan ver «Universitaria» entera. */
@container (max-width: 520px) {
  .cam-tiles[style*="--cols:6"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 720px) {
  .cam-ven { max-height: 92dvh; }
  .cam-cue { display: flex; flex-direction: column; align-items: stretch; gap: 14px; padding: 0 var(--v-pad) 16px; }
  .cam-prev { z-index: 1; flex-direction: row; justify-content: flex-start; gap: 14px; margin: 0 calc(-1 * var(--v-pad)); padding: 10px var(--v-pad);
    border-bottom: 1px solid var(--linea); border-radius: 0; background: var(--papel); }
  .cam-prev small { display: none; }
  .cam-grande svg { width: 104px; }
  .cam-muestra { font-size: 16px; }
  .cam-dos { gap: 20px; }
  .cam-tiles[style*="--cols:5"], .cam-tiles[style*="--cols:6"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .cam-sw { width: 38px; height: 38px; }
  .cam-auto { height: 38px; }
  .cam-pie { padding-bottom: calc(12px + env(safe-area-inset-bottom)); }
  .cam-pie .btn { flex: 1 1 100%; }
  .cam-pie .pista { flex-basis: 100%; }
}

/* 31-oct (gestor) · «Antes de ver los nombres» (ui.js `pedirNombres`): el diseño de los avisos de datos — Elso con candado, título GRID, lo que se acepta en lista. */
.modal:has(> .acn) { padding: 0; max-width: 520px; overflow: hidden; }
.acn-cab { display: flex; gap: 14px; align-items: flex-end; padding: 20px 22px 0; }
.acn-cab .elso-pie { flex: none; margin-bottom: -4px; }
.acn-cab h3 { font: italic 900 24px/1.05 var(--g-firma); text-transform: uppercase; margin: 0 0 6px; }
.acn-cab p { margin: 0 0 14px; font-size: 13px; color: var(--tinta-2); }
.acn-cu { border-top: 1px solid var(--linea); padding: 16px 22px; font-size: 14px; line-height: 1.55; }
.acn-cu ul { margin: 12px 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 9px; }
.acn-cu li { display: flex; gap: 10px; align-items: flex-start; }
.acn-cu li i { flex: none; width: 20px; height: 20px; border-radius: 5px; display: grid; place-items: center; background: var(--tinta); color: var(--papel); }
.acn-pie { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; justify-content: space-between; padding: 14px 22px 18px; border-top: 1px solid var(--linea); }
.acn-pie small { font-size: 11.5px; color: var(--tinta-3); flex: 1 1 200px; }
.acn-bt { display: flex; gap: 8px; }

/* 1-nov · «Publicar los nombres» en la página del torneo: una fila calma, sin filo de color */
.tn-nombres { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 12px 0 0; padding: 10px 14px; border: 1px solid var(--linea); border-radius: 10px; background: var(--alzado); color: var(--tinta-2); font-size: 14px; }
.tn-nombres > span { flex: 1; min-width: 220px; line-height: 1.45; }
.tn-nombres > span > :first-child { vertical-align: -2px; margin-right: 6px; }
.tn-nombres b { color: var(--tinta); }
