/* ==========================================================================
   IRIS CUP 2026 - Panel admin

   Escrito a mano, sin Tailwind. El glob de `tailwind.config.mjs` es
   `./src/**`, asi que estos PHP no reciben ni una utilidad; meterlos al glob
   obligaria a un segundo build solo para el panel.

   Los tokens son los MISMOS nombres que `src/styles/global.css`, con los mismos
   valores RGB crudos, y el tema se lee del mismo `localStorage['iris-tema']`.
   Asi el panel y el sitio no se separan cuando alguien ajuste un color.

   Diferencia deliberada con el sitio: esto es una herramienta de trabajo. Sin
   Lenis, sin Motion, sin circuito ambiental, sin halos grandes. Densidad de
   dato y lectura rapida por encima de espectaculo.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Fuentes propias

   Antes se pedian a fonts.googleapis.com en cada carga. Ese `<link>` bloquea
   el pintado, y medido desde aca costaba ~250 ms sobre los ~200 ms del
   servidor: casi medio segundo de pantalla en blanco por navegacion, que es
   justo lo que se sentia mal al moverse entre pantallas.

   Servidas desde el mismo dominio son 68 KB que el navegador cachea una vez y
   reusa en todas las pantallas, sin round trip a terceros. Solo el subconjunto
   latin, que cubre el español.

   `font-display: swap` para que el texto se lea desde el primer frame con la
   fuente del sistema y cambie cuando la propia este lista.
   -------------------------------------------------------------------------- */

/*
  Las rutas de las fuentes son RELATIVAS a esta hoja, no absolutas desde la raiz.

  `url('fuentes/x.woff2')` se resuelve contra la URL del propio CSS, asi que
  funciona igual servido como `admin.iriscup.bo/admin.css` que como
  `prueba.iriscup.bo/admin/admin.css`. Con `/fuentes/...` el panel de pruebas
  las pedia a la raiz del sitio publico y caian en 404: el panel se veia con
  estilos pero con la tipografia del navegador.
*/
@font-face {
  font-family: 'Orbitron Iris';
  font-style: normal;
  font-weight: 500 900;
  font-display: swap;
  src: url('fuentes/orbitron-latin.woff2') format('woff2');
}
@font-face {
  font-family: 'Xolonium Iris';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fuentes/xolonium-regular.woff2') format('woff2');
}
@font-face {
  font-family: 'Xolonium Iris';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fuentes/xolonium-bold.woff2') format('woff2');
}
@font-face {
  font-family: 'Roboto Iris';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('fuentes/roboto-latin.woff2') format('woff2');
}
:root {
  --chip-sm: 8px;
  --chip-md: 14px;

  /* Oro rosa oficial del Manual de Marca IRIS CUP 2026 */
  --c-oro: 201 158 124;          /* #C99E7C */
  --c-oro-bright: 236 208 184;   /* #ECD0B8 (oro rosa luz) */
  --c-oro-deep: 138 100 73;      /* #8A6449 (oro rosa hondo) */

  /* Púrpura IRIS institucional */
  --c-purpura: 95 46 172;        /* #5F2EAC */
  --c-purpura-deep: 42 21 82;    /* #2A1552 (púrpura hondo) */

  /* Cuarzo (filos y luminiscencia de transmisión) */
  --c-indigo: 160 140 216;       /* #A08CD8 */
  --c-indigo-soft: 217 208 242;  /* #D9D0F2 (cuarzo luz) */

  /* Obsidiana institucional y carbón */
  --c-obsidiana: 14 9 29;        /* #0E091D (fondo institucional) */
  --c-obsidiana-800: 10 7 21;    /* #0A0715 (carbón profundo de placas) */
  --c-obsidiana-700: 21 16 41;   /* #151029 (superficie elevada) */

  /* Tintas oficiales de lectura */
  --c-texto: 243 239 250;        /* #F3EFFA */
  --c-texto-muted: 207 198 232;  /* #CFC6E8 */
  --c-texto-faint: 165 152 200;  /* #A598C8 */

  /* Estados según la Signal Rule */
  --c-ok: 74 158 106;            /* #4A9E6A */
  /* El texto de los avisos, que no es el mismo color del filo: sobre carbon
     el verde y el rojo del filo no se leen, y hacen falta sus versiones luz. */
  --c-ok-texto: 167 243 208;     /* #A7F3D0 */
  --c-error-texto: 252 165 165;  /* #FCA5A5 */
  --c-alerta: 201 158 124;       /* #C99E7C */
  --c-error: 198 74 62;          /* #C64A3E */

  --hairline: rgba(160, 140, 216, 0.22);

  --f-titulo: 'Orbitron Iris', 'Xolonium Iris', system-ui, sans-serif;
  --f-rotulo: 'Xolonium Iris', 'Orbitron Iris', sans-serif;
  --f-cuerpo: 'Roboto Iris', system-ui, -apple-system, sans-serif;
  /* El panel no tiene un rol mono en el manual: las tablas si necesitan
     columnas de numeros que alineen, asi que va la mono del sistema y no
     una cuarta familia autoalojada. */
  --f-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  color-scheme: dark;
}

/* Tema alternativo de alto contraste */
[data-tema='claro'] {
  --c-oro: 142 96 64;
  --c-oro-bright: 115 74 46;
  --c-oro-deep: 82 50 28;

  --c-purpura: 95 46 172;
  --c-purpura-deep: 242 238 250;

  --c-indigo: 110 90 170;
  --c-indigo-soft: 80 60 140;

  --c-obsidiana: 245 242 248;
  --c-obsidiana-800: 255 255 255;
  --c-obsidiana-700: 236 230 244;

  --c-texto: 18 12 30;
  --c-texto-muted: 65 52 82;
  --c-texto-faint: 105 90 125;

  --c-ok: 30 106 62;
  --c-error: 158 38 28;
  --c-ok-texto: 22 88 50;
  --c-error-texto: 140 30 22;
  /* Faltaba: sin esto las chapas "pendiente" quedaban en oro rosa claro
     sobre blanco (2,4:1). */
  --c-alerta: 142 96 64;

  --hairline: rgba(95, 46, 172, 0.22);

  color-scheme: light;
}


*,
*::before,
*::after {
  box-sizing: border-box;
  /* Regla 1 del sistema: radio 0 en todo el documento. */
  border-radius: 0;
}

/*
  El atributo `hidden` nativo pone `display: none` por defecto, pero es una
  regla de la hoja del navegador: cualquier `display` propio -como el de
  `.tramos` o `.boton`, que son `grid`/`inline-flex`- la pisa aunque el
  elemento lleve el atributo. `panel.js` alterna `hidden` en decenas de sitios
  (la escalera de precios, las fichas, los campos extra) esperando que eso
  alcance para ocultar, y sin esta regla no ocultaba nada: el estado vacio de
  los tramos, por ejemplo, quedaba visible al lado de las filas ya cargadas.
*/
[hidden] {
  display: none !important;
}

html {
  background: rgb(var(--c-obsidiana));
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100dvh;
  background: rgb(var(--c-obsidiana));
  color: rgb(var(--c-texto));
  font-family: var(--f-cuerpo);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

:focus-visible {
  outline: 2px solid rgb(var(--c-oro-bright));
  outline-offset: 3px;
}

a {
  color: rgb(var(--c-oro-bright));
  text-decoration: none;
}
a:hover {
  text-decoration: underline;
}

/* --------------------------------------------------------------------------
   Formas del sistema
   -------------------------------------------------------------------------- */

/* Cortes a 45 grados. Un `border` real no sobrevive a `clip-path`, asi que el
   borde se simula con un contenedor de fondo y 1px de padding. */
.chip-sm {
  clip-path: polygon(
    0 0,
    calc(100% - var(--chip-sm)) 0,
    100% var(--chip-sm),
    100% 100%,
    0 100%
  );
}

.bisel {
  padding: 1px;
  background: linear-gradient(
    135deg,
    rgb(var(--c-oro) / 0.42),
    rgb(var(--c-purpura) / 0.75) 52%,
    rgb(var(--c-indigo) / 0.34)
  );
}
.bisel > * {
  background: rgb(var(--c-obsidiana-800));
}

.etiqueta-dato {
  font-family: var(--f-rotulo);
  font-weight: 600;
  font-size: 0.6875rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

/* Numeros de plata: tabular para que las columnas se puedan comparar de un
   vistazo. Sin esto un 1 ocupa menos que un 8 y la columna baila. */
.mono,
.monto {
  font-family: var(--f-mono);
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   Estructura
   -------------------------------------------------------------------------- */

.barra {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 1.5rem;
  padding: 0.875rem 1.25rem;
  background: rgb(var(--c-obsidiana-800));
  border-bottom: 1px solid var(--hairline);
}

.barra__marca {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  font-family: var(--f-titulo);
  font-weight: 700;
  letter-spacing: 0.04em;
  color: rgb(var(--c-oro-bright));
  text-transform: uppercase;
  font-size: 0.9rem;
}

.barra__marca img {
  display: block;
  width: 1.75rem;
  height: 1.75rem;
  object-fit: cover;
}

.barra__nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  margin-right: auto;
}

.barra__nav a {
  padding: 0.4rem 0.7rem;
  color: rgb(var(--c-texto-muted));
  font-family: var(--f-rotulo);
  font-size: 0.76rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  border: 1px solid transparent;
}
.barra__nav a:hover {
  color: rgb(var(--c-texto));
  border-color: var(--hairline);
  text-decoration: none;
}
.barra__nav a[aria-current='page'] {
  color: rgb(var(--c-oro-bright));
  border-color: rgb(var(--c-oro) / 0.6);
  background: rgb(var(--c-purpura) / 0.15);
}

.barra__usuario {
  font-size: 0.78rem;
  color: rgb(var(--c-texto-faint));
  text-align: right;
  line-height: 1.3;
}

.contenido {
  max-width: 1400px;
  margin: 0 auto;
  padding: 1.75rem 1.25rem 4rem;
}

.titulo {
  margin: 0 0 0.35rem;
  font-family: var(--f-titulo);
  font-size: clamp(1.4rem, 2.8vw, 1.95rem);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  line-height: 1.1;
  /* Era #ffffff fijo: en el tema claro el titulo de cada pantalla quedaba
     blanco sobre casi blanco (1,1:1). */
  color: rgb(var(--c-texto));
}

.subtitulo {
  margin: 0 0 1.75rem;
  color: rgb(var(--c-texto-muted));
  max-width: 68ch;
}

.tarjeta {
  background: rgb(var(--c-obsidiana-800));
  border: 1px solid var(--hairline);
  border-top: 1px solid rgb(var(--c-oro) / 0.5);
  padding: 1.25rem;
  margin-bottom: 1rem;
}

.tarjeta__titulo {
  margin: 0 0 1rem;
  font-family: var(--f-titulo);
  font-size: 0.88rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: rgb(var(--c-oro-bright));
}


.rejilla {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}

/*
   Rejilla de CAMPOS, no de tarjetas.

   Las tarjetas del tablero quieren estirarse hasta la altura de la fila; los
   campos no. Sin esto, un campo sin texto de ayuda al lado de uno que si lo
   tiene se estira para alcanzarlo, y como `.campo` es a su vez una grilla, el
   que crece es el input: quedan casillas de distinto alto en la misma fila sin
   ninguna razon visible.
   -------------------------------------------------------------------------- */
.rejilla--campos {
  align-items: start;
}

/* --------------------------------------------------------------------------
   Editor de nomina, dentro de la ficha de una inscripcion

   Un `<fieldset>` liviano por jugador, con `.rejilla.rejilla--campos` adentro
   para los campos: la misma grilla generica que ya usa el resto del panel para
   cualquier grupo de campos, no una clase pensada para otra cosa. Reusar
   `.tramo` aca --que trae su propio `--cols-tramo` de cinco columnas fijas,
   afinado para esa fila puntual-- habria maquetado los siete campos del
   jugador con el molde equivocado.
   -------------------------------------------------------------------------- */
.nomina-editor__jugador {
  margin: 0 0 0.75rem;
  padding: 0.75rem 0.9rem;
  border: 1px solid rgb(var(--c-purpura) / 0.4);
  background: rgb(var(--c-purpura) / 0.04);
}

.nomina-editor__jugador legend {
  padding: 0 0.35rem;
  color: rgb(var(--c-oro-bright));
}

.nomina-editor__acciones {
  display: flex;
  gap: 0.6rem;
  align-items: center;
  margin-top: 0.5rem;
}

/* --------------------------------------------------------------------------
   Formularios

   Regla del sistema, heredada de DESIGN.md: la etiqueta SIEMPRE arriba del
   input y el error SIEMPRE debajo. Nunca un `placeholder` como unica
   explicacion de que hace un campo: desaparece al primer caracter.
   -------------------------------------------------------------------------- */

.campo {
  display: grid;
  gap: 0.4rem;
  margin-bottom: 1.1rem;
}

.campo__etiqueta {
  font-family: var(--f-mono);
  font-weight: 500;
  font-size: 0.625rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgb(var(--c-texto-muted));
}

.campo__ayuda {
  font-size: 0.78rem;
  color: rgb(var(--c-texto-faint));
}

/* --------------------------------------------------------------------------
   Campos adicionales del formulario publico

   Cada fila es una definicion, no una respuesta: titulo, tipo, ejemplo y si
   se exige. En escritorio se compara de un vistazo; en telefono se apila sin
   comprimir las etiquetas ni los selectores.
   -------------------------------------------------------------------------- */
.campos-extra {
  display: grid;
  gap: 0.75rem;
  margin-bottom: 0.85rem;
}

.campo-extra {
  position: relative;
  display: grid;
  grid-template-columns: minmax(9rem, 1.2fr) minmax(7rem, 0.65fr) minmax(9rem, 1fr) auto;
  gap: 0.7rem;
  align-items: end;
  padding: 0.85rem 3.4rem 0.85rem 0.85rem;
  border: 1px solid rgb(var(--c-purpura) / 0.35);
  background: rgb(var(--c-purpura) / 0.05);
}

.campo-extra .campo {
  margin-bottom: 0;
}

.campo-extra__obligatorio {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  min-height: 2.7rem;
  font-size: 0.78rem;
  color: rgb(var(--c-texto-muted));
  white-space: nowrap;
}

.campo-extra__obligatorio input {
  width: auto;
}

@media (max-width: 760px) {
  .campo-extra {
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
  }
}

.campo__error {
  font-size: 0.78rem;
  font-weight: 600;
  color: rgb(var(--c-error));
}

/*
  Los tipos van enumerados y no con `input:not([type=checkbox])` porque las
  casillas y los radios necesitan quedar fuera. Ojo al agregar uno nuevo: el que
  falte en esta lista se dibuja con el control nativo del navegador, con su
  ancho intrinseco y su fondo claro, y en una columna angosta se desborda de la
  celda. Es lo que le pasaba a los `datetime-local` de la escalera de precios.
*/
input[type='text'],
input[type='password'],
input[type='number'],
input[type='url'],
input[type='search'],
input[type='file'],
input[type='email'],
input[type='tel'],
input[type='datetime-local'],
input[type='date'],
input[type='time'],
select,
textarea {
  width: 100%;
  min-width: 0;
  padding: 0.6rem 0.7rem;
  background: rgb(var(--c-obsidiana));
  border: 1px solid rgb(var(--c-purpura) / 0.6);
  color: rgb(var(--c-texto));
  font-family: inherit;
  font-size: 0.95rem;
  transition: border-color 0.25s ease;
}

input:hover,
select:hover,
textarea:hover {
  border-color: rgb(var(--c-indigo) / 0.5);
}

input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  border-color: rgb(var(--c-oro));
}

textarea {
  min-height: 11rem;
  resize: vertical;
  line-height: 1.6;
}

[aria-invalid='true'] {
  border-color: rgb(var(--c-error));
}

.campo__contador {
  font-family: var(--f-mono);
  font-size: 0.7rem;
  color: rgb(var(--c-texto-faint));
  text-align: right;
}

/* --------------------------------------------------------------------------
   Botones
   -------------------------------------------------------------------------- */

.boton {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.65rem 1.15rem;
  border: 1px solid transparent;
  background: rgb(var(--c-oro));
  color: rgb(var(--c-obsidiana));
  font-family: var(--f-rotulo);
  font-size: 0.82rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  cursor: pointer;
  transition: filter 0.25s ease;
  clip-path: polygon(
    0 0,
    calc(100% - var(--chip-sm)) 0,
    100% var(--chip-sm),
    100% 100%,
    0 100%
  );
}
/* Hover por brillo, no por cambio de color: el token no se mueve. */
.boton:hover {
  filter: brightness(1.18);
  text-decoration: none;
}
.boton:active {
  transform: scale(0.99);
}
.boton[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
}

.boton--fantasma {
  background: transparent;
  border-color: rgb(var(--c-purpura) / 0.7);
  color: rgb(var(--c-texto));
}
.boton--fantasma:hover {
  border-color: rgb(var(--c-oro) / 0.6);
  color: rgb(var(--c-oro-bright));
}

.boton--peligro {
  background: rgb(var(--c-error));
  color: #fff;
}

.boton--chico {
  padding: 0.4rem 0.7rem;
  font-size: 0.72rem;
}

/* --------------------------------------------------------------------------
   Avisos
   -------------------------------------------------------------------------- */

/*
  Borde completo de 1px, fondo teñido y texto del mismo color, igual que
  `.marca--*`. Nada de barra gruesa a un costado: el sistema usa hairlines de
  1px y resplandores, y una pestaña de color es vocabulario ajeno.

  El estado no depende solo del color: cada aviso lleva su propio texto, y los
  de error y exito ademas llegan con `role="alert"` o `role="status"`.
*/
.aviso {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.85rem 1.1rem;
  margin-bottom: 1.25rem;
  border: 1px solid rgb(var(--c-oro) / 0.45);
  background: rgb(var(--c-oro) / 0.09);
  color: rgb(var(--c-texto));
  font-size: 0.9rem;
  line-height: 1.4;
}
.aviso__icono {
  flex-shrink: 0;
}
.aviso--ok {
  border-color: rgb(var(--c-ok) / 0.6);
  background: rgb(var(--c-ok) / 0.12);
  color: rgb(var(--c-ok-texto));
}
.aviso--error {
  border-color: rgb(var(--c-error) / 0.75);
  background: rgb(var(--c-error) / 0.18);
  color: rgb(var(--c-error-texto));
  box-shadow: 0 0 16px rgb(var(--c-error) / 0.2);
}

/* --------------------------------------------------------------------------
   Tabla de inscripciones. Densidad: muchas filas legibles sin scroll lateral
   en escritorio, y con scroll contenido en movil.
   -------------------------------------------------------------------------- */

.tabla-envoltorio {
  overflow-x: auto;
  border: 1px solid var(--hairline);
  background: rgb(var(--c-obsidiana-800));
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.86rem;
}

thead th {
  position: sticky;
  top: 0;
  background: rgb(var(--c-obsidiana-700));
  padding: 0.6rem 0.7rem;
  text-align: left;
  white-space: nowrap;
  font-family: var(--f-mono);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgb(var(--c-texto-muted));
  border-bottom: 1px solid var(--hairline);
}

tbody td {
  padding: 0.6rem 0.7rem;
  border-bottom: 1px solid rgb(var(--c-purpura) / 0.28);
  vertical-align: top;
}

tbody tr:hover {
  background: rgb(var(--c-purpura) / 0.12);
}

td.derecha,
th.derecha {
  text-align: right;
}

/* Distintivos de estado. Sin puntos decorativos: el texto ya es el estado. */
.marca {
  display: inline-block;
  padding: 0.15rem 0.5rem;
  font-family: var(--f-mono);
  font-size: 0.625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  border: 1px solid;
}
.marca--pendiente {
  color: rgb(var(--c-alerta));
  border-color: rgb(var(--c-alerta) / 0.5);
  background: rgb(var(--c-alerta) / 0.1);
}
.marca--aprobada {
  color: rgb(var(--c-ok));
  border-color: rgb(var(--c-ok) / 0.5);
  background: rgb(var(--c-ok) / 0.12);
}
.marca--rechazada {
  color: rgb(var(--c-error-texto));
  border-color: rgb(var(--c-error) / 0.5);
  background: rgb(var(--c-error) / 0.1);
}

/* --------------------------------------------------------------------------
   Medidor de cupo
   -------------------------------------------------------------------------- */

.cupo {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}
.cupo__cifra {
  font-family: var(--f-mono);
  font-variant-numeric: tabular-nums;
  font-size: 1.6rem;
  font-weight: 700;
  line-height: 1;
}
.cupo__de {
  color: rgb(var(--c-texto-faint));
  font-size: 0.85rem;
}
.cupo__barra {
  margin-top: 0.6rem;
  height: 4px;
  background: rgb(var(--c-purpura) / 0.4);
}
.cupo__lleno {
  height: 100%;
  background: rgb(var(--c-oro));
}
.cupo__lleno[data-tope='si'] {
  background: rgb(var(--c-error));
}

/* --------------------------------------------------------------------------
   Login: una sola columna centrada, sin barra de navegacion
   -------------------------------------------------------------------------- */

.entrada {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 1.25rem;
}
.entrada__caja {
  width: 100%;
  max-width: 24rem;
}

/* --------------------------------------------------------------------------
   Vista previa del comprobante
   -------------------------------------------------------------------------- */

.comprobante {
  display: block;
  max-width: 100%;
  height: auto;
  border: 1px solid var(--hairline);
}
.comprobante--pdf {
  width: 100%;
  height: 70vh;
  border: 1px solid var(--hairline);
}

/* --------------------------------------------------------------------------
   Feedback de navegacion

   El panel son cargas de pagina completas. Entre el clic y el HTML nuevo pasan
   ~200 ms en los que el navegador no muestra NADA, y eso se lee como "no paso
   nada" o como que la aplicacion se colgo. Estas tres piezas cubren ese hueco.
   -------------------------------------------------------------------------- */

/* 1. Barra de progreso. Aparece recien a los 180 ms: si la pagina llega antes,
      no se ve nunca y se evita el parpadeo en cada clic. */
.progreso {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 100;
  height: 2px;
  width: 100%;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: linear-gradient(
    90deg,
    rgb(var(--c-oro) / 0.5),
    rgb(var(--c-oro-bright)),
    rgb(var(--c-indigo-soft))
  );
  opacity: 0;
  pointer-events: none;
  /* Solo transform y opacity: no fuerza reflow mientras corre. */
  transition:
    transform 0.4s cubic-bezier(0.16, 1, 0.3, 1),
    opacity 0.2s ease;
}
.progreso[data-activa='true'] {
  opacity: 1;
  /* Avanza hasta 3/4 y espera: no se miente con un 100% que no llego. */
  transform: scaleX(0.75);
  transition:
    transform 2.6s cubic-bezier(0.12, 0.8, 0.24, 1),
    opacity 0.15s ease;
}

/* 2. El elemento pulsado responde en el acto. Es el feedback que mas importa:
      confirma que el clic se registro, aunque el HTML tarde. */
[data-cargando='true'] {
  color: rgb(var(--c-oro-bright)) !important;
  border-color: rgb(var(--c-oro) / 0.6) !important;
}
.barra__nav a[data-cargando='true'] {
  background: rgb(var(--c-oro) / 0.12);
}

/* 3. Formulario enviandose. El boton no se deshabilita (eso descartaria su
      `name`/`value` del envio, y la bandeja depende de `accion=aprobar`);
      se bloquea el puntero y se marca visualmente. */
form[data-enviando='true'] .boton {
  pointer-events: none;
  opacity: 0.6;
}
form[data-enviando='true'] .boton[data-pulsado='true'] {
  opacity: 1;
  position: relative;
  padding-right: 2.6rem;
}
form[data-enviando='true'] .boton[data-pulsado='true']::after {
  content: '';
  position: absolute;
  right: 1rem;
  top: 50%;
  width: 0.85rem;
  height: 0.85rem;
  margin-top: -0.45rem;
  border: 2px solid currentColor;
  border-top-color: transparent;
  animation: girar 0.7s linear infinite;
}

@keyframes girar {
  to {
    transform: rotate(360deg);
  }
}

.pie {
  margin-top: 2.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--hairline);
  color: rgb(var(--c-texto-faint));
  font-size: 0.78rem;
}

/* --------------------------------------------------------------------------
   Ficha de inscripcion

   Un `<dialog>` nativo. No hace falta ni telon propio, ni trampa de foco, ni
   manejo de Escape: `showModal()` da las tres cosas y las da bien.
   -------------------------------------------------------------------------- */

.enlace-ficha {
  border: 0;
  background: none;
  padding: 0;
  margin-top: 0.25rem;
  font: inherit;
  font-size: 0.78rem;
  color: rgb(var(--c-oro-bright));
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.enlace-ficha:hover {
  color: rgb(var(--c-oro));
}

dialog.ficha:not([open]) {
  display: none !important;
}

dialog.ficha[open],
.ficha[open] {
  display: block !important;
  position: fixed !important;
  inset: 0 !important;
  margin: auto !important;
  width: min(48rem, calc(100vw - 2rem)) !important;
  max-height: calc(100vh - 3rem) !important;
  height: fit-content !important;
  padding: 1.75rem !important;
  border: 1px solid rgb(var(--c-purpura) / 0.7) !important;
  background: rgb(var(--c-obsidiana-800)) !important;
  color: rgb(var(--c-texto)) !important;
  overflow-y: auto !important;
  z-index: 999999 !important;
  box-shadow: 0 16px 50px rgba(0, 0, 0, 0.9), 0 0 30px rgb(var(--c-purpura) / 0.5) !important;
}

/*
  La ficha del editor de tramos, mas ancha que la de inscripcion.

  El ancho no es gusto: la fila de un tramo vuelve a su forma de tabla cuando su
  contenedor pasa de 52rem (ver el `@container` de `.tramos`). Con 64rem de
  dialogo menos el padding quedan unos 60rem para la escalera, que es lo que
  hace que el editor se vea como una tabla y no como cinco tarjetas apiladas.
  Debajo de eso el propio `@container` la apila sola, asi que en un telefono
  esto no rompe nada.
*/
dialog.ficha--editor[open],
.ficha--editor[open] {
  width: min(64rem, calc(100vw - 2rem)) !important;
}

@media (max-width: 600px) {
  dialog.ficha[open],
  .ficha[open],
  dialog.ficha--editor[open],
  .ficha--editor[open] {
    width: calc(100vw - 1rem) !important;
    padding: 1rem !important;
    max-height: calc(100vh - 1.5rem) !important;
  }
}

/* El pie del editor: la regla a la izquierda, las acciones a la derecha. */
.ficha__pie {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: 1.5rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--hairline);
}

.ficha__pie-nota {
  margin: 0;
  font-family: var(--f-mono);
  font-size: 0.72rem;
  color: rgb(var(--c-texto-muted));
}

.ficha__pie-acciones {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

/* La cruz de cerrar, en la cabecera de cualquier ficha. */
.ficha__cerrar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  flex: none;
  padding: 0;
  border: 1px solid rgb(var(--c-purpura) / 0.5);
  background: transparent;
  color: rgb(var(--c-texto-faint));
  cursor: pointer;
  transition:
    color 0.2s ease,
    border-color 0.2s ease;
}

.ficha__cerrar:hover {
  border-color: rgb(var(--c-oro) / 0.8);
  color: rgb(var(--c-oro-bright));
}

.ficha__cerrar:focus-visible {
  outline: 2px solid rgb(var(--c-oro));
  outline-offset: 2px;
}

.ficha::backdrop,
dialog.ficha::backdrop {
  background: rgba(10, 10, 15, 0.85) !important;
  backdrop-filter: blur(4px) !important;
}

.ficha__cabecera {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--hairline);
}

.ficha__titulo {
  margin: 0.3rem 0 0;
  font-size: 1.35rem;
  font-weight: 700;
  color: rgb(var(--c-oro-bright));
}

.ficha__seccion {
  margin: 1.5rem 0 0.6rem;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgb(var(--c-texto-muted));
}

/* Rejilla de datos con bordes por `gap`: mismo truco que el sitio publico. */
.ficha__datos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 1px;
  margin: 1rem 0 0;
  background: var(--hairline);
  border: 1px solid var(--hairline);
}
.ficha__datos > div {
  background: rgb(var(--c-obsidiana-800));
  padding: 0.7rem 0.85rem;
}
.ficha__datos dt {
  font-family: var(--f-mono);
  font-size: 0.6rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgb(var(--c-texto-faint));
}
.ficha__datos dd {
  margin: 0.3rem 0 0;
  font-size: 0.92rem;
}

.ficha__nomina {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 1px;
  background: var(--hairline);
  border: 1px solid var(--hairline);
}
.ficha__nomina li {
  display: grid;
  grid-template-columns: 9rem 1fr;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.5rem 0.85rem;
  background: rgb(var(--c-obsidiana-800));
}
.ficha__rol {
  font-size: 0.6rem;
  color: rgb(var(--c-oro));
}

/* Los enlaces a las fotos van bajo el detalle del jugador, no bajo su rol:
   `grid-column: 2` los alinea con el resto del texto en vez de con la
   insignia angosta de la primera columna. */
.ficha__fotos-documento {
  grid-column: 2;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 0.9rem;
  margin-top: 0.3rem;
}
.ficha__fotos-documento .campo__ayuda {
  font-size: 0.7rem;
}

/*
  Los datos del jugador (nombre, ciudad, documento, cuentas, plataforma), en
  chips con etiqueta en vez de una sola linea de texto separada por " · ".
  Mismo `grid-column: 2` que las fotos, por el mismo motivo: sin el, cae en
  la columna angosta de 9rem de la insignia de rol y se desborda encimado.

  Cada chip es "ETIQUETA valor", no una definicion de lista aparte: con seis
  jugadores por equipo, un `<dl>` completo por fila --como el de los datos
  del equipo, arriba en la misma pagina-- pesa visualmente mas que la
  informacion que muestra. Esto es lo mismo dicho mas chico.
*/
.ficha__jugador-datos {
  grid-column: 2;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.3rem 1.1rem;
  margin-top: 0.35rem;
}
.ficha__jd {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4rem;
  font-size: 0.82rem;
  color: rgb(var(--c-texto));
  max-width: 100%;
}
.ficha__jd b {
  flex: none;
  font-family: var(--f-mono);
  font-weight: 500;
  font-size: 0.58rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgb(var(--c-texto-faint));
}
.ficha__jd .mono {
  word-break: break-all;
}
/* La cuenta (Steam, FACEIT) trae ademas un enlace: el texto que escribio el
   jugador puede ser un ID64, una vanity URL o el enlace entero, y el
   encargado no tiene por que resolver esa forma a mano para verificarla. */
.ficha__jd--cuenta .enlace-ficha {
  margin-top: 0;
  font-size: 0.72rem;
  white-space: nowrap;
}

.ficha__pie {
  display: flex;
  justify-content: flex-end;
  margin-top: 1.75rem;
  padding-top: 1rem;
  border-top: 1px solid var(--hairline);
}

/* Visor de comprobante inline y modal compacto */
.comprobante-caja-inline {
  margin-top: 0.6rem;
  padding: 0.85rem;
  border: 1px solid var(--hairline);
  background: rgb(var(--c-obsidiana-700));
}

.comprobante-caja__acciones {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 0.75rem;
}

.comprobante-caja__previo {
  display: flex;
  justify-content: center;
  align-items: center;
  background: #0a0a0f;
  border: 1px solid var(--hairline);
  max-height: 280px;
  overflow: hidden;
}

.comprobante-img-previo {
  max-height: 280px;
  max-width: 100%;
  object-fit: contain;
  cursor: pointer;
  transition: transform 0.25s ease;
}

.comprobante-img-previo:hover {
  transform: scale(1.02);
}

.comprobante-iframe-previo {
  width: 100%;
  height: 280px;
  border: none;
  background: #fff;
}

/* Modal secundario compacto de 640px para la misma pagina */
dialog.comprobante-dialog-compacto[open] {
  width: min(40rem, calc(100vw - 2rem)) !important;
  max-height: calc(100vh - 4rem) !important;
  padding: 1.25rem !important;
  z-index: 1000000 !important;
}

.comprobante-dialog__cabecera {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-bottom: 0.75rem;
  margin-bottom: 0.85rem;
  border-bottom: 1px solid var(--hairline);
}

.comprobante-dialog__cuerpo {
  display: flex;
  justify-content: center;
  align-items: center;
  max-height: calc(100vh - 12rem);
  overflow: auto;
  background: #000;
  border: 1px solid var(--hairline);
}

.comprobante-img-modal {
  max-width: 100%;
  max-height: 65vh;
  object-fit: contain;
}

.comprobante-iframe-modal {
  width: 100%;
  height: 65vh;
  border: none;
  background: #fff;
}

/* --------------------------------------------------------------------------
   Celda de decision
   -------------------------------------------------------------------------- */

.decision__forma {
  display: grid;
  gap: 0.35rem;
  min-width: 13rem;
}

.decision__botones {
  display: flex;
  gap: 0.35rem;
}

.decision__nota {
  margin: 0 0 0.25rem;
  font-size: 0.85rem;
  max-width: 22rem;
}

/* Cerrado por defecto: reabrir una decision tiene que costar un clic
   deliberado, no estar a un dedo de distancia del cursor. */
.decision__cambiar {
  margin-top: 0.6rem;
}
.decision__cambiar summary {
  cursor: pointer;
  font-size: 0.75rem;
  color: rgb(var(--c-texto-faint));
}
.decision__cambiar summary:hover {
  color: rgb(var(--c-oro-bright));
}
.decision__cambiar[open] summary {
  margin-bottom: 0.5rem;
}

/* Texto preformateado de los cuerpos editables, para respetar los saltos. */
.cuerpo-previo {
  white-space: pre-wrap;
  font-size: 0.88rem;
  color: rgb(var(--c-texto-muted));
  line-height: 1.65;
  margin: 0;
}

@media (prefers-reduced-motion: reduce) {
  * {
    transition-duration: 0.001ms !important;
  }
  /*
    La barra y el spinner siguen apareciendo, pero sin movimiento: quitarlos
    del todo dejaria sin feedback a quien pidio menos animacion, que es
    precisamente quien mas necesita saber que algo esta pasando.
  */
  .progreso[data-activa='true'] {
    transform: scaleX(1);
  }
  form[data-enviando='true'] .boton[data-pulsado='true']::after {
    animation: none;
    border-top-color: currentColor;
    opacity: 0.5;
  }
}

/* --------------------------------------------------------------------------
   Precio por equipo y por jugador

   Van uno al lado del otro porque son la misma cifra dicha de dos formas, y
   apilados se leen como dos precios distintos. El de por jugador se angosta:
   es el derivado, no el que se cobra.
   -------------------------------------------------------------------------- */

.par-monto {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.75fr);
  gap: 0.9rem;
  align-items: start;
}

@media (max-width: 600px) {
  .par-monto {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* --------------------------------------------------------------------------
   Vista previa: calendario en chips y cuadro por zonas
   -------------------------------------------------------------------------- */

/* El enlace que sale del panel se distingue del resto de la barra. */
.barra__nav-aparte {
  margin-left: auto;
  color: rgb(var(--c-oro-bright)) !important;
}

.calendario-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

.calendario-chip {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  align-items: center;
  gap: 0 0.7rem;
  min-width: 11rem;
  padding: 0.6rem 0.9rem;
  border: 1px solid var(--hairline);
  background: rgb(var(--c-purpura) / 0.06);
}

.calendario-chip--final {
  border-color: rgb(var(--c-oro) / 0.55);
  background: rgb(var(--c-oro) / 0.08);
}

.calendario-chip__dia {
  grid-row: 1 / 3;
  font-family: var(--f-titulo);
  font-size: 1.9rem;
  font-weight: 700;
  line-height: 1;
  color: rgb(var(--c-oro-bright));
  font-variant-numeric: tabular-nums;
}

.calendario-chip__mes {
  font-family: var(--f-mono);
  font-size: 0.62rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgb(var(--c-texto-faint));
}

.calendario-chip__nota {
  font-size: 0.72rem;
  line-height: 1.35;
  color: rgb(var(--c-texto-muted));
}

/*
  El cuadro en columnas: una por ronda. No lleva los conectores del sitio
  publico a proposito -aca se viene a comprobar los cruces, no a admirarlos- y
  dibujarlos en el panel obligaria a mantener dos veces el mismo truco de CSS.
*/
.cuadro-zonas {
  display: flex;
  gap: 1rem;
  overflow-x: auto;
  padding-bottom: 0.5rem;
}

.cuadro-ronda {
  display: grid;
  align-content: start;
  gap: 0.4rem;
  min-width: 12rem;
}

.cuadro-cruce {
  display: grid;
  gap: 1px;
  border: 1px solid var(--hairline);
  background: var(--hairline);
}

.cuadro-cruce span {
  padding: 0.35rem 0.6rem;
  background: rgb(var(--c-obsidiana-800));
  font-size: 0.8rem;
  color: rgb(var(--c-texto-muted));
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cuadro-cruce__gana {
  color: rgb(var(--c-oro-bright)) !important;
  font-weight: 600;
}

/* --------------------------------------------------------------------------
   Cronograma en lista

   Una fila por partida, con el dia como fila de separacion. La forma sale de
   como se lee un cronograma en papel: se busca el dia, y adentro se recorre el
   orden de los cruces. Un resumen que solo diga "4 partidas" obliga a abrir
   otra pantalla para saber cuales.
   -------------------------------------------------------------------------- */

.cronograma-lista .dia-cabecera td {
  padding: 0.85rem 1rem;
  background: rgb(var(--c-purpura) / 0.14);
  border-top: 1px solid var(--hairline);
}

.cronograma-lista .dia-cabecera--final td {
  background: rgb(var(--c-oro) / 0.12);
}

/* El dia, la chapa y las rondas en una linea que respira. */
.cronograma-lista .dia-cabecera strong {
  margin: 0 0.6rem;
}

.cronograma-lista .dia-cabecera .campo__ayuda {
  display: inline;
}

.cronograma-lista__n {
  font-weight: 600;
  color: rgb(var(--c-oro-bright));
  white-space: nowrap;
}

.cronograma-lista__n .campo__ayuda {
  display: block;
  font-weight: 400;
}

.cronograma-lista__dia-mas {
  color: rgb(var(--c-error));
  font-weight: 700;
  font-size: 0.7rem;
}

/* Cada cruce de una tanda simultanea, separado por un pelo. */
.cruce {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.15rem 0.5rem;
  padding: 0.2rem 0;
}

.cruce + .cruce {
  border-top: 1px solid var(--hairline);
}

.cruce__bloque {
  font-family: var(--f-mono);
  font-size: 0.62rem;
  letter-spacing: 0.12em;
  padding: 0.05rem 0.35rem;
  border: 1px solid rgb(var(--c-purpura) / 0.6);
  color: rgb(var(--c-texto-faint));
}

.cruce__vs {
  font-size: 0.75rem;
  color: rgb(var(--c-texto-faint));
}

/* Un cruce sin equipos se titula por su ronda, no con dos "por definir". */
.cruce__ronda {
  color: rgb(var(--c-texto-muted));
}

/*
  El tope de cierre, arriba de la tabla que gobierna. Va en linea con el boton
  para que se lea como un ajuste suelto y no como un formulario mas.
*/
.calendario-limite {
  display: flex;
  flex-wrap: wrap;
  align-items: start;
  gap: 1rem;
  margin-bottom: 1.5rem;
  padding: 0.9rem 1.1rem;
  border: 1px solid rgb(var(--c-oro) / 0.3);
  background: rgb(var(--c-oro) / 0.05);
}

.calendario-limite .campo {
  flex: 1 1 18rem;
  margin-bottom: 0;
}

.calendario-limite .boton {
  margin-top: 1.35rem;
}

/* --------------------------------------------------------------------------
   Calendario fijado por la organizacion

   Lo que el encargado lee pero no toca. Se dibuja como dato, no como formulario
   apagado: un input deshabilitado invita a intentar escribirlo.
   -------------------------------------------------------------------------- */

.calendario-fijo {
  display: grid;
  gap: 0.5rem;
  margin-bottom: 1.25rem;
  padding: 0.9rem 1.1rem;
  border: 1px solid rgb(var(--c-oro) / 0.3);
  background: rgb(var(--c-oro) / 0.05);
}

.calendario-fijo__linea {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.25rem 0.75rem;
  margin: 0;
}

/* La etiqueta no compite con el dato: se le da un ancho fijo para que los
   valores queden alineados entre lineas. */
.calendario-fijo__linea .campo__etiqueta {
  min-width: 11rem;
}

/* --------------------------------------------------------------------------
   Editor de tramos de precio

   Es una tabla, no una pila de formularios. Leer una escalera es comparar
   montos entre filas, y eso solo funciona si los montos caen en la misma
   columna y el encabezado se escribe una sola vez.

   El encabezado y las filas comparten `--cols-tramo`, asi que no se pueden
   desalinear al tocar un ancho. Abajo de 900px la tabla se rinde: el
   encabezado desaparece, cada fila pasa a ser una tarjeta y las etiquetas que
   arriba estaban ocultas vuelven a verse. Por eso siguen en el marcado en vez
   de haberlas borrado.
   -------------------------------------------------------------------------- */

/*
  Oculta a la vista, presente para el lector de pantalla.

  `display:none` no sirve: sacaria la etiqueta tambien del arbol accesible y
  dejaria cinco campos sin nombre por fila.
*/
.solo-lectores {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --------------------------------------------------------------------------
   Resumen de la escalera en la tarjeta

   Lo que queda en la pagina cuando el editor se fue al dialogo: para que sirve
   pasar por aca es para ver de un vistazo que tramos hay y cuanto cobran, no
   para editarlos. Es una lista de solo lectura, sin una sola casilla.
   -------------------------------------------------------------------------- */

.tramos-resumen {
  display: grid;
  gap: 1px;
  margin: 0 0 0.9rem;
  padding: 0;
  list-style: none;
  background: var(--hairline);
  border: 1px solid var(--hairline);
}

.tramos-resumen__fila {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.15rem 0.7rem;
  padding: 0.6rem 0.75rem;
  background: rgb(var(--c-obsidiana-800));
}

/*
  La fila con problemas se marca aca tambien: si no, la unica pista de que hay
  algo mal seria el contador de abajo, y no diria cual.

  El tinte va como imagen SOBRE el color de la fila, no en su lugar. Puesto como
  `background-color` translucido, lo que se ve por detras no es el fondo de la
  tarjeta sino el hairline purpura que separa las filas, y la fila mala salia
  violeta en vez de roja.
*/
.tramos-resumen__fila--mala {
  background-image: linear-gradient(
    rgb(var(--c-error) / 0.1),
    rgb(var(--c-error) / 0.1)
  );
  box-shadow: inset 2px 0 0 rgb(var(--c-error));
}

.tramos-resumen__nombre {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
  font-weight: 600;
  font-size: 0.88rem;
}

.tramos-resumen__fechas {
  grid-column: 1;
  font-size: 0.72rem;
  color: rgb(var(--c-texto-muted));
}

/*
  Las dos cifras alineadas a la derecha y en columna: el precio por cabeza en el
  cuerpo del texto y el del equipo debajo, apagado. Es el mismo orden de
  importancia que en el editor y en el sitio publico.
*/
.tramos-resumen__monto {
  grid-row: 1 / 3;
  grid-column: 2;
  align-self: center;
  text-align: right;
  font-size: 0.88rem;
  font-variant-numeric: tabular-nums;
}

.tramos-resumen__equipo {
  display: block;
  font-size: 0.7rem;
  color: rgb(var(--c-texto-faint));
}

.tramos-resumen__vacio {
  margin: 0 0 0.9rem;
  padding: 0.85rem;
  border: 1px dashed rgb(var(--c-purpura) / 0.55);
  background: rgb(var(--c-purpura) / 0.04);
  color: rgb(var(--c-texto-muted));
  font-size: 0.85rem;
}

/* El aviso de que el resumen quedo viejo tras editar sin guardar. */
.tramos-resumen__sucio {
  margin: 0.7rem 0 0;
  color: rgb(var(--c-alerta));
  font-size: 0.78rem;
  line-height: 1.5;
}

/* --------------------------------------------------------------------------
   Escalera de precios

   Por que esto responde al CONTENEDOR y no a la ventana.

   La tarjeta vive en la columna angosta del reparto 2:1, asi que en un monitor
   de 1400px mide unos 400px: cinco campos y un boton no entran en esa fila por
   mucha pantalla que haya detras. La version anterior colapsaba a tarjetas con
   `@media (max-width: 900px)`, que es justo al reves de lo que hace falta:

     - ventana de 1400px -> columna de 400px -> daba la tabla, que se desbordaba
     - ventana de 800px  -> una sola columna, tarjeta de 740px -> daba las
       tarjetas apiladas, con sitio de sobra para la tabla

   Con `@container` la pregunta se hace donde corresponde: cuanto mide la caja
   que tiene que dibujar la fila. La forma apilada es la de por defecto, asi que
   un navegador sin soporte se queda con la que funciona en cualquier ancho.
   -------------------------------------------------------------------------- */

.tramos {
  /*
    Las dos fechas piden mas ancho que los dos montos: un `datetime-local`
    tiene que mostrar `24/08/2026 00:00` y el icono del calendario, y recortado
    a la mitad no se puede leer lo que dice. `50.00` entra en cualquier parte.
  */
  --cols-tramo:
    minmax(0, 1fr) minmax(0, 1.3fr) minmax(0, 1.3fr)
    minmax(0, 0.72fr) minmax(0, 0.72fr) 2rem;
  container-type: inline-size;
  display: grid;
  gap: 0.5rem;
}

/*
  La cabecera de la tabla. Solo aparece cuando la fila esta en modo tabla; en
  modo tarjeta cada campo lleva su etiqueta a la vista y repetirla arriba seria
  decir dos veces lo mismo.

  Va con `aria-hidden` porque es decorativa: las etiquetas de verdad son las de
  cada campo, que nunca se sacan del arbol accesible.
*/
.tramos__cabecera {
  display: none;
  grid-template-columns: var(--cols-tramo);
  gap: 0.6rem;
  align-items: end;
  padding: 0 0.75rem 0.1rem;
}

.tramo {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.7rem;
  padding: 0.85rem 3rem 0.85rem 0.85rem;
  border: 1px solid rgb(var(--c-purpura) / 0.35);
  background: rgb(var(--c-purpura) / 0.05);
}

/* La fila con problemas se marca entera, no solo con el texto de abajo. */
.tramo--malo {
  border-color: rgb(var(--c-error) / 0.65);
  background: rgb(var(--c-error) / 0.07);
}

/* Los campos de una fila no llevan el margen inferior que traen sueltos. */
.tramo .campo {
  margin-bottom: 0;
  position: relative;
}

/*
  Los dos pares que se leen juntos: el rango de fechas y las dos caras del
  precio. Se parten solos cuando no entran de a dos, sin preguntarle nada a
  nadie, y en modo tabla desaparecen como caja (`display: contents`) para que
  sus cuatro campos caigan directo en las columnas de la fila.
*/
.tramo__par {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--min-par, 9rem), 1fr));
  gap: 0.6rem 0.7rem;
}

/*
  El minimo de cada par decide cuando se parte en dos lineas, y no es el mismo
  para los dos: una fecha necesita casi el doble que un monto. Con un unico
  minimo, o las fechas quedaban recortadas o los montos se apilaban de a uno
  teniendo sitio de sobra, que es justo donde hace falta verlos juntos.
*/
.tramo__par--fechas {
  --min-par: 10.5rem;
}

.tramo__par--montos {
  /*
    6.5rem y no 7: dentro del dialogo en un telefono de 390px a la fila le
    quedan 234px utiles, y dos columnas de 7rem mas el hueco piden 235. Por ese
    pixel los dos montos se apilaban justo donde mas interesa verlos juntos.
  */
  --min-par: 6.5rem;
}

/*
  El precio por jugador es el que se guarda; el de por equipo se deriva. Se
  distinguen con el filo dorado del panel y no con un color nuevo: en una fila
  de cinco campos, dos cajas identicas obligan a leer la etiqueta cada vez.
*/
.tramo__campo--guarda input {
  border-color: rgb(var(--c-oro) / 0.5);
}

.tramo__campo--derivado input {
  background: transparent;
  color: rgb(var(--c-texto-muted));
}

.tramo__marca {
  position: absolute;
  top: -0.55rem;
  right: 0;
  pointer-events: none;
}

.tramo__error {
  grid-column: 1 / -1;
  margin-top: 0.15rem;
}

/*
  Los QR del tramo: el del equipo y el del equipo con suplente.

  El bloque ocupa la fila entera --tambien en modo tabla, donde las seis
  columnas ya van apretadas-- porque una miniatura escaneable no entra en 0.72fr
  y un selector de archivo recortado a 110px no dice que archivo tiene.

  Los dos van uno al lado del otro cuando hay sitio, y apilados cuando no. Verlos
  juntos es lo que hace evidente que son dos montos del mismo tramo: separados
  por una fila entera, el segundo se lee como si fuera de otra cosa.
*/
.tramo__qrs {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 0.6rem 1.2rem;
  border-top: 1px dashed rgb(var(--c-purpura) / 0.35);
  padding-top: 0.6rem;
}

.tramo__qr {
  min-width: 0;
}

/*
  El monto que cobra cada codigo. Va en la etiqueta porque es el dato que decide
  cual de los dos hay que generar en el banco, y en dorado porque es plata: en
  una fila con dos casillas iguales, el monto es lo unico que las distingue.
*/
.tramo__qr-monto {
  color: rgb(var(--c-oro));
  margin-left: 0.35rem;
  text-transform: none;
  letter-spacing: 0;
}

.tramo__qr-caja {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}

/* Chica pero suficiente para reconocer cual es; el enlace la abre entera. */
.tramo__qr-vista {
  display: block;
  width: 3.5rem;
  height: 3.5rem;
  object-fit: contain;
  background: #fff;
  padding: 0.15rem;
  border: 1px solid rgb(var(--c-purpura) / 0.4);
}

.tramo__qr-quitar {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.8rem;
  color: rgb(var(--c-texto-muted));
  white-space: nowrap;
}

.tramo__qr-quitar input {
  width: auto;
}

.tramo__qr input[type='file'] {
  flex: 1 1 12rem;
  min-width: 0;
}

/*
  Quitar es una accion destructiva y va como icono: con texto se comia el ancho
  de una columna entera en cada fila para repetir la misma palabra. En modo
  tarjeta se ancla arriba a la derecha, que es el hueco que le deja el
  `padding-right` de la fila.
*/
.tramo__quitar {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: 1px solid rgb(var(--c-purpura) / 0.5);
  background: transparent;
  color: rgb(var(--c-texto-faint));
  cursor: pointer;
  transition:
    color 0.2s ease,
    border-color 0.2s ease;
}

.tramo__quitar:hover {
  border-color: rgb(var(--c-error) / 0.8);
  color: rgb(var(--c-error));
}

.tramo__quitar:focus-visible {
  outline: 2px solid rgb(var(--c-oro));
  outline-offset: 2px;
}

/* La aclaracion del par de montos: una vez debajo de la escalera, no una vez
   por fila. Repetida en cada tramo dejaba de leerse a la segunda. */
.tramos__nota {
  margin: 0.55rem 0 0;
  color: rgb(var(--c-texto-muted));
  font-size: 0.78rem;
  line-height: 1.5;
}

/* --------------------------------------------------------------------------
   Modo tabla: solo cuando la caja da el ancho de verdad.
   -------------------------------------------------------------------------- */

@container (min-width: 52rem) {
  .tramos__cabecera {
    display: grid;
  }

  .tramo {
    grid-template-columns: var(--cols-tramo);
    gap: 0.6rem;
    align-items: center;
    padding: 0.55rem 0.75rem;
  }

  /* Los pares dejan de ser caja y sus campos pasan a ser columnas de la fila. */
  .tramo__par {
    display: contents;
  }

  .tramo__quitar {
    position: static;
  }

  /*
    El chip de "rige ahora" cuelga por encima de la fila, y en modo tabla la
    fila es baja: sin este hueco el chip se apoyaba sobre el borde superior del
    campo del nombre y le tapaba el primer renglon. El hueco se abre solo en la
    fila que lo lleva, para no separar las demas.
  */
  .tramo:has(.tramo__marca) {
    padding-top: 1.5rem;
  }

  .tramo .tramo__marca {
    top: -1.25rem;
  }

  /*
    La etiqueta de cada campo se oculta A LA VISTA, no al lector de pantalla:
    arriba esta la cabecera diciendo lo mismo para quien ve la tabla. Con
    `display: none` quedarian cinco campos sin nombre por fila.
  */
  .tramo__etiqueta {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
}

/*
  El hueco, entre las dos filas que lo abren.

  Antes vivia en una tabla aparte debajo del editor: se leia ahi y se arreglaba
  arriba. Dibujado en su lugar, la fila que hay que mover queda a la vista.
*/
.tramo-hueco {
  margin: 0;
  padding: 0.5rem 0.8rem;
  border-left: 2px solid rgb(var(--c-alerta) / 0.6);
  background: rgb(var(--c-alerta) / 0.07);
  color: rgb(var(--c-texto-muted));
  font-size: 0.78rem;
  line-height: 1.45;
}

/* Un hueco sin monto base no es una pausa: es cobrar cero. */
.tramo-hueco--grave {
  border-left-color: rgb(var(--c-error));
  background: rgb(var(--c-error) / 0.1);
  color: rgb(var(--c-texto));
}

/*
  Estado vacio. Es lo que ve un encargado que entra por primera vez, asi que
  explica que es un tramo en vez de dejar un boton suelto sin contexto.
*/
.tramos-vacio {
  display: grid;
  justify-items: start;
  gap: 0.6rem;
  padding: 1.25rem;
  border: 1px dashed rgb(var(--c-purpura) / 0.55);
  background: rgb(var(--c-purpura) / 0.04);
}

.tramos-vacio__titulo {
  margin: 0;
  font-weight: 700;
  color: rgb(var(--c-texto));
}

.tramos-vacio .campo__ayuda {
  max-width: 60ch;
}

/* --------------------------------------------------------------------------
   Reporte de Equipo para Imprimir / Exportar
   -------------------------------------------------------------------------- */

.reporte-encabezado-impresion {
  display: none;
  border-bottom: 2px solid rgb(var(--c-oro));
  padding-bottom: 0.75rem;
  margin-bottom: 1.25rem;
}

/*
  Lo que solo tiene sentido en papel.

  En pantalla el encargado hace clic en "Ver anverso"; en la hoja impresa ese
  enlace no sirve, y se oculta. Pero ocultarlo a secas dejaba el reporte
  diciendo unicamente que fotos FALTABAN, nunca cuales estaban: en un
  documento que respalda una verificacion, la confirmacion es justamente el
  dato que hay que poder leer.
*/
.solo-impresion {
  display: none;
}
.reporte-encabezado__titulo {
  font-family: var(--f-titulo);
  font-size: 1.25rem;
  font-weight: 700;
  color: #000;
  text-transform: uppercase;
}
.reporte-encabezado__subtitulo {
  font-family: var(--f-mono);
  font-size: 0.85rem;
  color: #444;
  margin-top: 0.25rem;
}

@media print {
  /* Ocultar toda la interfaz y navegacion para que no ocupe espacio de diseño */
  header.barra,
  footer.pie,
  .tarjeta,
  .tabla-envoltorio,
  .aviso,
  .titulo,
  .subtitulo,
  nav.barra__nav,
  dialog.ficha:not([open]) {
    display: none !important;
  }

  body {
    background: #fff !important;
    color: #000 !important;
    margin: 0 !important;
    padding: 0 !important;
  }

  main.contenido {
    padding: 0 !important;
    margin: 0 !important;
  }

  /* Formato limpio de 1 sola hoja para la ficha abierta */
  dialog.ficha[open] {
    display: block !important;
    position: static !important;
    transform: none !important;
    width: 100% !important;
    max-width: 100% !important;
    margin: 0 !important;
    padding: 0.5cm 1cm !important;
    border: none !important;
    background: #fff !important;
    color: #000 !important;
    box-shadow: none !important;
    overflow: visible !important;
    page-break-after: avoid;
    break-after: avoid;
  }

  .reporte-encabezado-impresion {
    display: block !important;
    border-bottom: 2px solid #000 !important;
    margin-bottom: 1.25rem !important;
  }

  /* Reemplaza en el papel a los enlaces de foto, que se ocultan abajo. */
  .solo-impresion {
    display: inline !important;
    color: #000 !important;
  }

  .reporte-encabezado__titulo {
    color: #000 !important;
  }

  .ficha__cabecera,
  .ficha__datos,
  .ficha__nomina,
  .ficha__seccion,
  .ficha__titulo,
  .ficha__datos dd,
  .ficha__datos dt {
    color: #000 !important;
    background: transparent !important;
  }

  .ficha__datos {
    border: 1px solid #ddd !important;
    background: #ddd !important;
  }

  .ficha__datos > div {
    background: #fff !important;
  }

  .ficha__nomina {
    border: 1px solid #ddd !important;
  }

  .ficha__nomina li {
    background: #fff !important;
    border-bottom: 1px solid #eee !important;
  }

  /*
    Lo que en papel no se puede tocar. Los botones del comprobante
    --"Descargar", "Ampliar vista", el zoom-- salian impresos como botones
    muertos al lado de la imagen; `.solo-impresion` cubre el caso de las fotos
    de documento, que ademas necesitan dejar constancia de que estan.
  */
  /*
    El `[open]` no sobra: `dialog.ficha[open]` de mas arriba vale 0,2,1 y el
    visor lleva las dos clases, asi que sin el se imprimiria encima de la
    ficha si quedo abierto. Con `[open]` empatan en especificidad y gana este,
    que viene despues en la hoja.
  */
  .ficha__pie,
  .enlace-ficha,
  .comprobante-caja__acciones,
  dialog.comprobante-dialog-compacto[open],
  [data-cerrar-ficha],
  [data-imprimir-reporte] {
    display: none !important;
  }
}

/* --------------------------------------------------------------------------
   Partidas en el telefono

   La tabla de resultados es la pantalla que el encargado usa parado al lado de
   la cancha. Envuelta en `.tabla-envoltorio` no rompia el layout, pero obligaba
   a arrastrarla a la derecha en cada partida para llegar a los botones.

   A 900px deja de ser tabla: cada partida es una tarjeta y las etiquetas de la
   cabecera vuelven desde `data-etiqueta`. Es el mismo patron que ya usan los
   tramos de precio, no uno nuevo: si funciona ahi, funciona aca, y el panel
   sigue comportandose de una sola manera.
   -------------------------------------------------------------------------- */

/* Los dos botones de equipo, uno al lado del otro mientras entren. */
.decision__botones {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

/*
  44px de alto minimo. Los botones chicos del panel miden 28, y estos deciden
  quien avanza en la llave: un toque errado no se nota hasta dos rondas
  despues, cuando el equipo equivocado ya paso. El area tactil es la unica
  defensa contra eso, y el pulgar no apunta como el mouse.
*/
.decision__botones .boton {
  min-height: 44px;
  flex: 1 1 auto;
}

/*
  El ganador elegido se distingue por borde y peso, no solo por relleno. La
  final se juega en un galpon con sol entrando: un matiz de fondo se pierde,
  un borde grueso no.
*/
.decision__botones .boton[aria-pressed='true'] {
  border-width: 2px;
  border-color: rgb(var(--c-oro-bright));
  font-weight: 700;
}

@media (max-width: 900px) {
  /* La tabla se desarma en tarjetas. `display:block` en los elementos de tabla
     es lo unico que el navegador respeta para esto sin reescribir el markup. */
  .tabla--partidas,
  .tabla--partidas tbody,
  .tabla--partidas tr,
  .tabla--partidas td,
  .tabla--inscripciones,
  .tabla--inscripciones tbody,
  .tabla--inscripciones tr,
  .tabla--inscripciones td,
  .tabla--entradas,
  .tabla--entradas tbody,
  .tabla--entradas tr,
  .tabla--entradas td {
    display: block;
    width: auto;
  }

  /* La cabecera ya no encabeza nada: cada celda lleva su etiqueta encima. */
  .tabla--partidas thead,
  .tabla--inscripciones thead,
  .tabla--entradas thead {
    display: none;
  }

  .tabla--partidas tr,
  .tabla--inscripciones tr,
  .tabla--entradas tr {
    border: 1px solid var(--hairline);
    border-top: 1px solid rgb(var(--c-oro) / 0.5);
    background: rgb(var(--c-obsidiana-700));
    padding: 0.9rem;
    margin-bottom: 0.75rem;
    clip-path: polygon(
      0 0,
      calc(100% - var(--chip-sm)) 0,
      100% var(--chip-sm),
      100% 100%,
      0 100%
    );
  }

  .tabla--partidas td,
  .tabla--inscripciones td,
  .tabla--entradas td {
    border: 0;
    padding: 0.35rem 0;
  }

  .tabla--partidas td::before,
  .tabla--inscripciones td::before,
  .tabla--entradas td::before {
    content: attr(data-etiqueta);
    display: block;
    margin-bottom: 0.25rem;
    font-family: var(--f-rotulo);
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: rgb(var(--c-texto-muted));
  }

  /* El cruce, el equipo o el comprador es el titulo de la tarjeta */
  .tabla--partidas td[data-etiqueta='Cruce']::before,
  .tabla--inscripciones td[data-etiqueta='Equipo']::before,
  .tabla--entradas td[data-etiqueta='Comprador']::before {
    display: none;
  }

  .tabla--partidas td[data-etiqueta='Cruce'] strong,
  .tabla--inscripciones td[data-etiqueta='Equipo'] strong,
  .tabla--entradas td[data-etiqueta='Comprador'] strong {
    display: block;
    font-family: var(--f-titulo);
    font-size: 1.05rem;
    color: rgb(var(--c-oro-bright));
  }

  /* En tarjeta los botones ocupan el ancho: es el objetivo mas facil de acertar */
  .tabla--partidas td[data-etiqueta='Guardar'] .boton,
  .tabla--inscripciones td[data-etiqueta='Decisión'] .boton,
  .tabla--entradas td[data-etiqueta='Acciones'] .boton {
    width: 100%;
    min-height: 44px;
    justify-content: center;
  }

  .tabla--inscripciones .decision__forma {
    min-width: 0;
    width: 100%;
  }

  .tabla--inscripciones .decision__botones {
    flex-direction: column;
  }

  .tabla-envoltorio:has(.tabla--partidas),
  .tabla-envoltorio:has(.tabla--inscripciones),
  .tabla-envoltorio:has(.tabla--entradas) {
    border: none;
    background: transparent;
  }
}

/* --------------------------------------------------------------------------
   Barra de guardado de Disciplina

   El formulario tiene 26 campos en 10 tarjetas. Con el boton al final, guardar
   desde el telefono era recorrer varias pantallas sin saber si lo de arriba
   habia quedado. Pegada al pie, el guardado esta siempre a un toque y el texto
   dice en que estado esta el formulario.
   -------------------------------------------------------------------------- */

.barra-guardar {
  position: sticky;
  bottom: 0;
  z-index: 5;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: 1.5rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--hairline);
  /* Opaco a proposito: se superpone al formulario mientras se hace scroll, y
     translucido dejaria leer dos textos encimados. */
  background: rgb(var(--c-obsidiana-800));
  box-shadow: 0 -8px 24px rgb(10 10 15 / 0.45);
}

.barra-guardar__estado {
  margin: 0;
  font-family: var(--f-mono);
  font-size: 0.72rem;
  color: rgb(var(--c-texto-muted));
}

/* Los dos estados que importan se dicen con color Y con palabras: el texto ya
   cambia solo, el color es refuerzo, no el unico portador. */
.barra-guardar[data-tono='sucio'] .barra-guardar__estado {
  color: rgb(var(--c-oro-bright));
}

.barra-guardar[data-tono='error'] {
  border-color: rgb(var(--c-oro) / 0.55);
}

.barra-guardar[data-tono='error'] .barra-guardar__estado {
  color: rgb(var(--c-oro-bright));
}

@media (max-width: 600px) {
  .barra-guardar {
    /* En telefono manda el boton: ancho completo, altura tactil. */
    flex-direction: column;
    align-items: stretch;
  }

  .barra-guardar .boton {
    width: 100%;
    min-height: 44px;
  }
}

/* ==========================================================================
   Vista mobile del panel

   Medido con el panel abierto a 375 y 414px, no deducido del CSS: Disciplina
   se desbordaba 155px y Torneo 106px, con 24 y 42 elementos interactivos por
   debajo de los 44px de alto minimo.

   La causa raiz era una sola. `.barra` es un flex sin `wrap`, asi que la marca
   mas seis enlaces mas el usuario mas dos botones fijaban un ancho minimo de
   ~480px. Eso ensancha el documento entero, y todo lo demas se acomoda contra
   ese ancho falso: por eso `.rejilla`, que con `auto-fit` deberia dar una sola
   columna a 375px, entraba en dos y cortaba la segunda.

   Arreglar la barra tira abajo la cascada. El resto de este bloque son los
   minimos tactiles y las dos tablas que quedaban sueltas.
   ========================================================================== */

/*
  Red de seguridad. `clip` y no `hidden`: `hidden` en el elemento raiz rompe
  `position: sticky` en los descendientes, y la barra y el guardado dependen
  de sticky.
*/
html,
body {
  overflow-x: clip;
}

@media (max-width: 700px) {
  /* ---------- La barra deja de empujar ---------- */

  .barra {
    flex-wrap: wrap;
    gap: 0.5rem 0.75rem;
    padding: 0.6rem 0.9rem;
  }

  .barra__marca {
    /* Toma la fila entera: al lado de la nav es lo que forzaba el ancho. */
    flex: 1 0 100%;
  }

  /*
    La nav pasa a ser una tira que se desliza. Se prefiere a un menu
    hamburguesa porque son seis destinos y ninguno es secundario: el encargado
    salta entre Disciplinas, Inscripciones y Torneo todo el tiempo, y esconder
    eso detras de un toque extra es peor que deslizar.
  */
  .barra__nav {
    flex: 1 1 100%;
    display: flex;
    flex-wrap: nowrap;
    gap: 0.25rem;
    overflow-x: auto;
    /* Sin esto el ultimo enlace queda pegado al borde y no se ve que sigue. */
    padding-bottom: 0.25rem;
    scrollbar-width: thin;
  }

  .barra__nav a {
    flex: 0 0 auto;
    white-space: nowrap;
  }

  .barra__usuario {
    flex: 1 1 100%;
    justify-content: flex-start;
    flex-wrap: wrap;
    gap: 0.5rem;
  }

  /* ---------- Una columna, siempre ---------- */

  /*
    Refuerzo explicito. Con la barra arreglada `auto-fit` ya resuelve solo,
    pero dejarlo escrito evita que el proximo campo ancho vuelva a partir la
    pantalla en dos columnas cortadas.
  */
  .rejilla,
  .rejilla--campos {
    grid-template-columns: minmax(0, 1fr);
  }

  /* ---------- Minimos tactiles ---------- */

  /*
    44px. Medidos: la nav estaba en 34, los botones de Tema y Salir en 30, las
    pestanas de disciplina en 34 y los campos en 41. El pulgar no apunta como
    el mouse, y estas pantallas se usan de pie.
  */
  .barra__nav a,
  .barra__usuario .boton,
  .pestanas a,
  .boton {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }

  input[type='text'],
  input[type='number'],
  input[type='datetime-local'],
  input[type='date'],
  input[type='time'],
  input[type='url'],
  input[type='email'],
  input[type='tel'],
  input[type='password'],
  input[type='file'],
  select,
  textarea {
    min-height: 44px;
  }

  /*
    Las casillas median 14px. Son las que eligen los dias de la semana del
    cronograma y las que activan el suplente: siete cuadrados de 14px pegados
    uno al lado del otro es una loteria con el pulgar, y marcar el dia
    equivocado corre todo el calendario.

    Se agranda la casilla y, sobre todo, se le da altura tactil a la etiqueta
    que la envuelve: el area que se toca es la etiqueta entera, no el cuadrito.
  */
  input[type='checkbox'],
  input[type='radio'] {
    width: 1.35rem;
    height: 1.35rem;
    min-height: 0;
  }

  label:has(> input[type='checkbox']),
  label:has(> input[type='radio']) {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    min-height: 44px;
  }

  /* ---------- Tablas que quedaban sueltas ---------- */

  /*
    El cronograma se desbordaba 52px: la columna de horario caia fuera. No se
    convierte en tarjetas como la de partidas porque aca la lectura es
    comparativa —una jornada, en orden— y romperla en tarjetas la haria mas
    larga y menos util. Se desliza, que para leer alcanza.
  */
  .cronograma-lista {
    display: block;
    overflow-x: auto;
    max-width: 100%;
  }
}

/* --------------------------------------------------------------------------
   Reparto principal de Disciplina: contenido y barra lateral

   Vivia como `style` inline en juegos.php, y por eso el breakpoint de mobile
   no podia colapsarlo: un inline le gana a cualquier hoja. A 375px la segunda
   tarjeta quedaba cortada al medio y, con el `overflow-x: clip` de la raiz,
   directamente invisible.
   -------------------------------------------------------------------------- */

.rejilla--principal {
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  align-items: start;
}

@media (max-width: 700px) {
  .rejilla--principal {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* --------------------------------------------------------------------------
   Puerta

   Se usa de pie, con una mano, a pleno sol o en un pabellon a oscuras. El
   resultado ocupa todo el ancho y se lee por color y por texto a la vez: el
   color solo no alcanza para quien no distingue rojo de verde.
   -------------------------------------------------------------------------- */
.puerta {
  display: grid;
  gap: 1rem;
  max-width: 560px;
}

.puerta__visor {
  position: relative;
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  overflow: hidden;
  border: 1px solid currentColor;
  background: #000;
}

.puerta__visor video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.puerta__visor .boton,
.puerta__sin-camara {
  position: relative;
  z-index: 1;
  margin: 1rem;
  text-align: center;
}

.puerta__sin-camara {
  color: #fff;
}

.puerta__resultado {
  padding: 1.25rem;
  border: 2px solid transparent;
}

.puerta__resultado[data-estado='espera'] {
  border-color: rgb(128 128 128 / 0.35);
}

.puerta__resultado[data-estado='valida'] {
  border-color: #1e8e4f;
  background: rgb(30 142 79 / 0.14);
}

.puerta__resultado[data-estado='usada'] {
  border-color: #c98a12;
  background: rgb(201 138 18 / 0.14);
}

.puerta__resultado[data-estado='invalida'] {
  border-color: #c0392b;
  background: rgb(192 57 43 / 0.14);
}

.puerta__estado {
  margin: 0;
  font-size: 1.6rem;
  font-weight: 700;
  line-height: 1.2;
}

.puerta__detalle {
  margin: 0.4rem 0 0;
}

.puerta__manual {
  display: flex;
  gap: 0.75rem;
  align-items: flex-end;
}

/* --------------------------------------------------------------------------
   Partidas ya jugadas, en la pantalla de carga de resultados

   El encargado tiene que poder barrer la lista y ver de un vistazo que queda
   por tocar. La fila jugada se apaga y su HORA se tacha: la cita es lo que ya
   paso. El cruce NO se tacha, porque a partir de ahi la fila deja de decir
   "cuando" y pasa a decir "quien gano", que es el dato que se quiere leer.

   Es la MISMA señal que ve el publico en el cronograma del sitio
   (`.txt-run-fila[data-jugada]` en src/styles/torneo.css). Que el panel y la
   pagina se lean igual es lo que permite cargar mirando el panel y confiar en
   lo que quedo publicado sin ir a revisarlo.
   -------------------------------------------------------------------------- */

.tabla--partidas tr[data-jugada] {
  color: rgb(var(--c-texto-muted));
}

.hora--jugada {
  text-decoration: line-through;
  text-decoration-color: rgb(var(--c-oro) / 0.85);
  text-decoration-thickness: 1px;
}

/* El ganador ya marcado se sigue leyendo a pleno: es el dato de la fila. */
.tabla--partidas tr[data-jugada] .boton[aria-pressed='true'] {
  color: rgb(var(--c-texto));
}

/* --------------------------------------------------------------------------
   Permisos por perfil (Usuarios)

   Una tarjeta por perfil, con un interruptor por seccion. El interruptor es
   un rectangulo con un taco, sin radio, como todo el panel: prendido lleva el
   oro rosa, apagado queda en el filo de cuarzo. Al lado, en palabras, lo que
   significa ("Entra" / "No entra"), para que el estado no dependa solo del
   color.
   -------------------------------------------------------------------------- */

.permisos__intro {
  margin: 0 0 0.9rem;
}

.permisos__super {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 1.25rem;
  padding: 0.7rem 0.9rem;
  border: 1px solid var(--hairline);
  color: rgb(var(--c-texto-muted));
  font-size: 0.875rem;
}

.permisos__perfiles {
  display: grid;
  gap: 1rem;
}

@media (min-width: 900px) {
  .permisos__perfiles {
    grid-template-columns: 1fr 1fr;
  }
}

.permisos__perfil {
  min-width: 0;
  margin: 0;
  padding: 1rem 1.1rem 0.9rem;
  border: 1px solid var(--hairline);
  border-top: 2px solid rgb(var(--c-purpura));
}

.permisos__titulo {
  padding: 0 0.35rem;
  font-family: var(--f-titulo);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgb(var(--c-texto));
}

.permisos__quien {
  margin: 0.2rem 0 0.4rem;
}

.permisos__cuenta {
  margin: 0 0 0.6rem;
  color: rgb(var(--c-texto-muted));
  font-size: 0.85rem;
}

.permisos__cuenta strong {
  color: rgb(var(--c-oro-bright));
  font-family: var(--f-mono);
}

.permisos__grupo {
  margin: 1rem 0 0.35rem;
  font-family: var(--f-rotulo);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgb(var(--c-texto-faint));
}

.permisos__lista {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--hairline);
}

.permiso {
  border-bottom: 1px solid var(--hairline);
}

/* Lo que cambio y todavia no se guardo: filo de oro rosa a la izquierda. */
.permiso[data-cambiado] {
  box-shadow: inset 3px 0 0 rgb(var(--c-oro));
  background: rgb(var(--c-oro) / 0.06);
}

.permisos .permiso__fila {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 0.8rem;
  min-height: 44px;
  padding: 0.6rem 0.5rem;
  cursor: pointer;
}

/* En el telefono el estado en palabras baja debajo del texto: al costado le
   robaba el ancho a la descripcion. */
@media (max-width: 520px) {
  .permisos .permiso__fila {
    grid-template-columns: auto 1fr;
  }

  .permisos .permiso__estado {
    grid-column: 2;
    text-align: left;
  }
}

.permiso__fila:hover {
  background: rgb(var(--c-indigo) / 0.05);
}

.permiso__texto {
  display: grid;
  gap: 0.1rem;
  min-width: 0;
}

.permiso__texto strong {
  color: rgb(var(--c-texto));
  font-size: 0.92rem;
  font-weight: 600;
}

.permiso__texto small {
  color: rgb(var(--c-texto-faint));
  font-size: 0.78rem;
  line-height: 1.35;
}

/*
  El interruptor. Va con `.permisos` delante porque la regla de casillas del
  panel para pantallas chicas (`input[type='checkbox']`, 1,35 rem) pesa mas que
  una clase sola y lo aplastaba contra el texto.
*/
.permisos .permiso__switch {
  appearance: none;
  position: relative;
  flex: 0 0 auto;
  width: 2.6rem;
  min-width: 2.6rem;
  height: 1.4rem;
  min-height: 1.4rem;
  margin: 0;
  border: 1px solid rgb(var(--c-indigo) / 0.55);
  background: rgb(var(--c-obsidiana));
  cursor: pointer;
  transition: background-color 140ms, border-color 140ms;
}

.permisos .permiso__switch::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: calc(1.4rem - 6px);
  height: calc(1.4rem - 6px);
  background: rgb(var(--c-texto-faint));
  transition: transform 140ms, background-color 140ms;
}

.permisos .permiso__switch:checked {
  border-color: rgb(var(--c-oro));
  background: rgb(var(--c-oro) / 0.22);
}

.permisos .permiso__switch:checked::after {
  transform: translateX(1.2rem);
  background: rgb(var(--c-oro-bright));
}

.permiso__switch:focus-visible {
  outline: 2px solid rgb(var(--c-oro));
  outline-offset: 2px;
}

/* El estado en palabras, para que no dependa solo del color. */
.permiso__estado {
  min-width: 4.6rem;
  font-family: var(--f-mono);
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  text-align: right;
  text-transform: uppercase;
}

.permiso__estado::after {
  content: 'No entra';
  color: rgb(var(--c-texto-faint));
}

.permiso__switch:checked ~ .permiso__estado::after {
  content: 'Entra';
  color: rgb(var(--c-ok));
}

.permisos__fijos {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 1.2rem;
  margin: 0.9rem 0 0;
  color: rgb(var(--c-texto-faint));
  font-size: 0.78rem;
}

.permisos__acciones {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  margin-top: 1.1rem;
}

.permisos__pendiente {
  color: rgb(var(--c-oro-bright));
  font-size: 0.85rem;
}

.permisos__fabrica {
  margin-left: auto;
}

@media (prefers-reduced-motion: reduce) {
  .permiso__switch,
  .permiso__switch::after {
    transition: none;
  }
}

/* Login: "mantener la sesion en este equipo". */
.entrada__recordar {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  min-height: 44px;
  margin: 0.2rem 0 0.4rem;
  color: rgb(var(--c-texto-muted));
  cursor: pointer;
}

/* ==========================================================================
   Cabecera del panel

   Marca, navegacion en tres grupos y la cuenta. En escritorio todo en una
   fila: los grupos se separan con un filo vertical, cada destino lleva su
   icono (trazo de 1.6, el mismo en los ocho) y la seccion actual se marca con
   un filo de oro rosa abajo y la placa purpura, no con un recuadro alrededor.

   Debajo de 1250 px la nav se esconde detras de "Menu" y se abre como un
   panel de baldosas agrupadas. Sin JavaScript la nav queda siempre abierta:
   el panel nunca se queda sin navegacion.
   ========================================================================== */

.iris-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.cab {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: stretch;
  gap: 1rem;
  min-height: 60px;
  padding: 0 1rem;
  background: rgb(var(--c-obsidiana-800));
  border-bottom: 1px solid var(--hairline);
}

/* Filo de oro rosa arriba: la orla de la marca, de 2 px como en el sitio. */
.cab::before {
  content: '';
  position: absolute;
  inset: 0 0 auto;
  height: 2px;
  background: linear-gradient(90deg, rgb(var(--c-oro-bright)), rgb(var(--c-oro)) 45%, rgb(var(--c-oro-deep)));
}

.cab svg {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.cab__marca {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 0.6rem;
  padding-right: 1rem;
  border-right: 1px solid var(--hairline);
  color: rgb(var(--c-oro-bright));
  font-family: var(--f-titulo);
  font-size: 0.9rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
}

.cab__marca:hover {
  text-decoration: none;
  color: rgb(var(--c-texto));
}

.cab__marca img {
  display: block;
  width: 30px;
  height: 30px;
}

.cab__marca small {
  display: block;
  color: rgb(var(--c-texto-faint));
  font-family: var(--f-rotulo);
  font-size: 0.56rem;
  font-weight: 400;
  letter-spacing: 0.22em;
}

.cab__nav {
  display: flex;
  flex: 1 1 auto;
  align-items: stretch;
  min-width: 0;
}

.cab__grupo {
  display: flex;
  align-items: stretch;
}

.cab__grupo + .cab__grupo {
  margin-left: 0.4rem;
  padding-left: 0.4rem;
  border-left: 1px solid var(--hairline);
}

/* El nombre del grupo solo se lee en el panel del telefono. */
.cab__grupo-nombre {
  display: none;
}

.cab__item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0 0.7rem;
  color: rgb(var(--c-texto-muted));
  font-family: var(--f-rotulo);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  text-decoration: none;
  transition: color 140ms, background-color 140ms;
}

.cab__item svg {
  flex: 0 0 auto;
  color: rgb(var(--c-texto-faint));
  transition: color 140ms;
}

.cab__item:hover {
  color: rgb(var(--c-texto));
  background: rgb(var(--c-indigo) / 0.07);
  text-decoration: none;
}

.cab__item:hover svg {
  color: rgb(var(--c-indigo));
}

.cab__item[aria-current='page'] {
  color: rgb(var(--c-oro-bright));
  background: rgb(var(--c-purpura) / 0.2);
}

.cab__item[aria-current='page'] svg {
  color: rgb(var(--c-oro));
}

.cab__item[aria-current='page']::after {
  content: '';
  position: absolute;
  inset: auto 0.5rem 0;
  height: 2px;
  background: rgb(var(--c-oro));
}

.cab__item:focus-visible,
.cab__marca:focus-visible,
.cab__abrir:focus-visible,
.cab__cuenta summary:focus-visible,
.cab__opcion:focus-visible {
  outline: 2px solid rgb(var(--c-oro));
  outline-offset: -2px;
}

/*
  Lo que espera una accion. Con la cifra centrada de verdad: la monoespaciada
  del sistema tiene la linea base baja y el numero quedaba caido dentro de la
  chapa. `line-height: 1` y flex la centran por la caja, no por la linea.
*/
.cab__aviso {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.35rem;
  height: 1.2rem;
  padding: 0 0.3rem;
  background: rgb(var(--c-oro));
  color: rgb(var(--c-obsidiana-800));
  font-family: var(--f-cuerpo);
  font-size: 0.7rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  letter-spacing: 0;
}

/* La cuenta. */
.cab__cuenta {
  position: relative;
  flex: 0 0 auto;
  display: flex;
  margin-left: auto;
  border-left: 1px solid var(--hairline);
}

.cab__cuenta summary {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0 0.3rem 0 1rem;
  list-style: none;
  cursor: pointer;
}

.cab__cuenta summary::-webkit-details-marker {
  display: none;
}

.cab__avatar {
  display: grid;
  place-items: center;
  width: 2.1rem;
  height: 2.1rem;
  border: 1px solid rgb(var(--c-oro) / 0.6);
  background: rgb(var(--c-purpura) / 0.35);
  color: rgb(var(--c-oro-bright));
  font-family: var(--f-titulo);
  font-size: 0.78rem;
  font-weight: 800;
}

.cab__quien {
  display: grid;
  line-height: 1.2;
  text-align: left;
}

.cab__quien b {
  overflow: hidden;
  /* Un nombre largo no puede empujar a la navegacion: se corta con puntos y
     entero queda en el desplegable. */
  max-width: 9.5rem;
  color: rgb(var(--c-texto));
  font-size: 0.82rem;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cab__quien small {
  color: rgb(var(--c-texto-faint));
  font-family: var(--f-rotulo);
  font-size: 0.58rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.cab__flecha {
  color: rgb(var(--c-texto-faint));
  transition: transform 160ms;
}

.cab__cuenta[open] .cab__flecha {
  transform: rotate(180deg);
}

.cab__desplegable {
  position: absolute;
  top: calc(100% + 1px);
  right: 0;
  z-index: 30;
  display: grid;
  min-width: 15rem;
  padding: 0.4rem 0;
  border: 1px solid var(--hairline);
  border-top: 1px solid rgb(var(--c-oro) / 0.6);
  background: rgb(var(--c-obsidiana-700));
}

.cab__desplegable-quien {
  display: grid;
  gap: 0.15rem;
  margin: 0;
  padding: 0.6rem 1rem 0.75rem;
  border-bottom: 1px solid var(--hairline);
  color: rgb(var(--c-texto-faint));
  font-size: 0.76rem;
}

.cab__desplegable-quien b {
  color: rgb(var(--c-texto));
  font-size: 0.88rem;
}

.cab__desplegable form {
  margin: 0;
}

.cab__opcion {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  width: 100%;
  min-height: 44px;
  padding: 0 1rem;
  border: 0;
  background: none;
  color: rgb(var(--c-texto-muted));
  font: inherit;
  font-size: 0.86rem;
  text-align: left;
  cursor: pointer;
}

.cab__opcion:hover {
  background: rgb(var(--c-indigo) / 0.08);
  color: rgb(var(--c-texto));
}

.cab__opcion--salir:hover {
  color: rgb(var(--c-error));
}

/* El boton "Menu": solo en pantallas donde la nav no entra en una fila. */
.cab__abrir {
  display: none;
}

/*
  Compacta, entre 1250 y 1599 px: con los ocho destinos del superadmin la
  cuenta se montaba sobre Bitacora y Usuarios. La cuenta queda en las
  iniciales (el nombre sigue en el desplegable) y los destinos se juntan.
*/
@media (min-width: 1250px) and (max-width: 1599px) {
  .cab {
    gap: 0.6rem;
  }

  .cab__marca {
    padding-right: 0.7rem;
  }

  .cab__item {
    gap: 0.35rem;
    padding: 0 0.5rem;
    font-size: 0.68rem;
    letter-spacing: 0.06em;
  }

  .cab__grupo + .cab__grupo {
    margin-left: 0.25rem;
    padding-left: 0.25rem;
  }

  .cab__quien {
    display: none;
  }

  .cab__cuenta summary {
    padding-left: 0.7rem;
  }
}

@media (max-width: 1249px) {
  .cab {
    flex-wrap: wrap;
    align-items: center;
    padding: 0 0.75rem;
  }

  .cab__marca {
    border-right: 0;
    min-height: 58px;
  }

  .cab__abrir {
    display: none;
    align-items: center;
    gap: 0.45rem;
    order: 2;
    min-height: 44px;
    margin-left: auto;
    padding: 0 0.9rem;
    border: 1px solid var(--hairline);
    background: none;
    color: rgb(var(--c-texto));
    font-family: var(--f-rotulo);
    font-size: 0.7rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    cursor: pointer;
  }

  .cab__cuenta {
    order: 3;
    margin-left: 0.5rem;
    border-left: 0;
    min-height: 58px;
  }

  .cab__cuenta summary {
    padding: 0;
  }

  .cab__quien,
  .cab__flecha {
    display: none;
  }

  /* El panel de la nav: grupos con su nombre y baldosas grandes. */
  .cab__nav {
    order: 4;
    flex: 1 0 100%;
    flex-direction: column;
    gap: 0.9rem;
    padding: 0.9rem 0 1.1rem;
    border-top: 1px solid var(--hairline);
  }

  .cab__grupo {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
    gap: 0.4rem;
  }

  .cab__grupo + .cab__grupo {
    margin: 0;
    padding: 0;
    border: 0;
  }

  .cab__grupo-nombre {
    display: block;
    grid-column: 1 / -1;
    color: rgb(var(--c-texto-faint));
    font-family: var(--f-rotulo);
    font-size: 0.6rem;
    letter-spacing: 0.2em;
    text-transform: uppercase;
  }

  .cab__item {
    min-width: 0;
    min-height: 48px;
    padding: 0 0.65rem;
    border: 1px solid var(--hairline);
    font-size: 0.68rem;
    letter-spacing: 0.04em;
  }

  .cab__item > span:not(.cab__aviso) {
    overflow: hidden;
    min-width: 0;
    text-overflow: ellipsis;
  }

  /*
    En la baldosa el aviso va como chapa en la esquina, no en la fila: al
    lado del rotulo, "Inscripciones" en media pantalla de 360 px o empujaba
    el numero fuera de la baldosa o se cortaba con puntos.
  */
  .cab__aviso {
    position: absolute;
    top: -1px;
    right: -1px;
    margin: 0;
  }

  .cab__item[aria-current='page'] {
    border-color: rgb(var(--c-oro) / 0.6);
  }

  .cab__item[aria-current='page']::after {
    inset: 0 auto 0 0;
    width: 2px;
    height: auto;
  }

  /* Con JavaScript: el boton aparece y la nav espera a que la abran. */
  html[data-js] .cab__abrir {
    display: inline-flex;
  }

  html[data-js] .cab:not([data-abierto]) .cab__nav {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .cab__item,
  .cab__item svg,
  .cab__flecha {
    transition: none;
  }
}

@media print {
  header.cab {
    display: none !important;
  }
}
