/* ===========================================================================
   Concurso de Payas · Clínica Témpora
   Sistema de diseño derivado de clinicatempora.cl

   Tres decisiones sostienen todo lo demás; si se pierden, el sitio deja de
   parecerse a la marca aunque los colores estén bien:

     1. Titulares GRANDES y LIVIANOS (peso 300). Es lo más distintivo de
        Témpora. Poner los títulos en negrita es el error que convierte esta
        paleta en una plantilla genérica cualquiera.
     2. UN SOLO acento. El lima aparece en lo accionable y en poco más;
        repartirlo por todas partes lo apaga.
     3. Superficies planas con borde de un píxel. Nada de sombras flotando:
        la profundidad viene del cambio de tono, no del desenfoque.
   =========================================================================== */

:root {
  /* --- Pizarra ------------------------------------------------------- */
  --pizarra-900: #2b343a;   /* pie, barras */
  --pizarra-800: #39434a;   /* fondo de página */
  --pizarra-700: #414c54;   /* tarjetas */
  --pizarra-600: #4d585f;   /* bordes marcados, hover */

  /* --- Acento -------------------------------------------------------- */
  --lima:        #b4d335;
  --lima-viva:   #c6e34a;
  --lima-honda:  #94b022;

  /* --- Tinta --------------------------------------------------------- */
  --sobre-lima:  #1b2226;   /* texto sobre el lima */
  --blanco:      #ffffff;
  --texto:       #dce3e7;
  /* Los dos grises se eligieron midiendo, no a ojo: --texto-2 alcanza 4,69:1
     sobre el fondo de tarjeta, que es la superficie más clara donde aparece, y
     --texto-3 se reserva para apoyos cortos sobre el fondo de página. Un gris
     más apagado se veía mejor en la maqueta y era ilegible en un celular al
     sol, que es donde de verdad se va a leer esto. */
  --texto-2:     #b3bfc7;
  --texto-3:     #93a0a8;

  /* --- Bordes -------------------------------------------------------- */
  --linea:       rgb(255 255 255 / var(--alfa-borde));
  --linea-viva:  rgb(255 255 255 / calc(var(--alfa-borde) * 2.2));

  /* --- Semánticos ---------------------------------------------------- */
  --exito:       #7cc98f;
  --alerta:      #e8b45c;
  --error:       #ec8079;

  /* --- Forma --------------------------------------------------------- */
  --radio-s:  calc(var(--redondeo) * .57);
  --radio-m:  var(--redondeo);
  --radio-l:  calc(var(--redondeo) * 1.43);
  --radio-xl: calc(var(--redondeo) * 2);

  /* --- Movimiento ---------------------------------------------------- */
  --curva:   cubic-bezier(.22, .61, .36, 1);
  --resorte: cubic-bezier(.34, 1.3, .64, 1);
  --rapido:  150ms;
  --normal:  260ms;
  --lento:   420ms;

  /* --- Medidas ------------------------------------------------------- */
  --ancho:  1200px;
  --canal:  clamp(1.15rem, 4vw, 3rem);

  --display: "Manrope", "Segoe UI", system-ui, sans-serif;
  --texto-f: "Manrope", "Segoe UI", system-ui, sans-serif;
  --ui:      "Roboto", "Segoe UI", system-ui, sans-serif;
  --mono:    ui-monospace, "Cascadia Mono", Consolas, monospace;

  /* --- Administrable desde /admin/apariencia --------------------------
     Lo que hay aquí es el diseño original. El panel lo sobrescribe con un
     bloque <style> que va después de esta hoja, así que si ese bloque no
     estuviera —o alguien restableciera el aspecto— el sitio vuelve solo a
     verse como se diseñó. Nada de esto se repite en dos sitios. */
  --escala-titulo: 1;      /* multiplica el tamaño de h1 y h2            */
  --escala-texto:  1;      /* multiplica el tamaño del cuerpo de texto   */
  --peso-titulo:   300;    /* la firma de Témpora: titulares livianos    */
  --alto-linea:    1.65;
  --redondeo:      14px;   /* de aquí salen los cuatro radios de arriba  */
  --radio-boton:   8px;
  --grosor-borde:  1px;
  --alfa-borde:    .10;    /* cuánto se ve la línea de cada caja         */
  /* Copia del grosor del sitio bajo otro nombre. Existe para que un bloque pueda
     redefinir `--grosor-borde` a partir de ella: una variable no puede
     referirse a SÍ MISMA —queda inválida— así que hace falta un segundo nombre
     del que partir. Aquí no se lee ninguna `--bloque-…`, que es lo que la
     distingue del fallo de `--sombra-caja` y lo que permite declararla en la
     raíz sin problema. */
  --grosor-base:   var(--grosor-borde);
  --densidad:      1;      /* multiplica el aire dentro y entre bloques  */
  /* Apagada es una sombra TRANSPARENTE y no `none`, y no es un capricho: se
     usa dentro de una lista —`box-shadow: var(--sombra), var(--sombra-caja)`—
     y `none` en una lista no es una sombra vacía, es un valor invalido que se
     lleva por delante la declaración entera. Se ve exactamente igual. */
  --sombra:        0 0 0 rgb(0 0 0 / 0);

  /* El valor NEUTRO de la sombra por bloque: una sombra transparente, que es lo
     que ven los elementos que no están dentro de ningún bloque.

     Aquí estaba el cálculo entero, y era un fallo: una variable que contiene
     otras se resuelve DONDE SE DECLARA, así que `var(--bloque-sombra)` se leía
     en `:root` —donde siempre vale 0— y el control de sombra del editor no
     hacía absolutamente nada, se pusiera donde se pusiera. Es el mismo error que
     el comentario de `--bloque-tinte` describe correctamente unas líneas más
     abajo; aquí se había escrito al revés. El cálculo vive ahora dentro de
     `[data-bloque]`, que es donde `--bloque-sombra` vale lo que alguien eligió. */
  --sombra-caja:   0 0 0 rgb(0 0 0 / 0);

  /* Los controles finos de la maqueta. `--densidad` los mueve todos a la vez;
     éstos permiten ajustar una medida sin arrastrar a las demás. Los que
     multiplican van sin unidad, y la regla que los usa aplica el calc() sobre
     su propio clamp(): así el ajuste entre celular y monitor se conserva. */
  --espacio-seccion: 1;
  --alto-hero:       1;
  --pad-tarjeta:     1;
  --espacio-parrafo: 1;
  --gap-rejilla:     16px;
  --tarjeta-min:     230px;
  --ancho-texto:     68ch;   /* en caracteres: es lo que cansa la vista */

  /* El contorno que se enciende al pasar por encima. Se apaga neutralizando
     estas variables —el borde vuelve al normal y el halo a la sombra de la
     caja—, no quitando la regla: así hay UNA sola regla de hover en la hoja y
     no dos versiones que puedan separarse. */
  --neon:       #b4d335;
  --neon-borde: var(--neon);
  --neon-halo:  0 0 0 1px var(--neon), 0 0 25px color-mix(in srgb, var(--neon) 38%, transparent);
  --elevar:     0px;

  /* El cristal de las cajas de texto. Lo sobrescribe el panel; esto es lo que
     se ve si el bloque generado no llegara. */
  --vidrio-fondo:      color-mix(in srgb, var(--pizarra-700) 76%, transparent);
  --vidrio-desenfoque: 14px;
  --vidrio-borde:      rgb(255 255 255 / .18);
}

/* Diseño de un solo mundo visual: la marca es oscura y el sitio también.
   Se declara explícitamente para no heredar el fondo de quien nos aloje. */
html { color-scheme: dark; }

*, *::before, *::after { box-sizing: border-box; }

/* ===========================================================================
   `hidden` significa oculto. Sin excepciones.

   Esta regla existe porque el mismo error apareció DIEZ veces en este archivo,
   cada una parcheada por separado —`.aviso[hidden]`, `.teatro[hidden]`,
   `.tira-pieza[hidden]`…— y la undécima se coló hasta producción: el resumen de
   puntajes del jurado se abría con el reproductor de video encima, porque el
   JavaScript ponía `hidden` en `.jurado-escena` y esa clase declara
   `display: grid`.

   El motivo es una regla de la cascada que no se ve venir: el navegador oculta
   los elementos con `[hidden]` mediante `display: none` en su hoja por defecto,
   y CUALQUIER `display` escrito por nosotros le gana, por poca especificidad que
   tenga. O sea que poner `display: flex` o `display: grid` en una clase deja
   sordo el atributo `hidden` de ese elemento, en silencio y para siempre.

   Con `!important` aquí el atributo vuelve a ser lo que dice ser, y sobra tener
   que acordarse caso por caso. Si alguna vez hiciera falta un elemento marcado
   como `hidden` pero visible, ese elemento no debería llevar `hidden`: para eso
   están `aria-hidden`, `.solo-lectores` o una clase propia.

   `bin/pruebas/maqueta.test.php` comprueba que esta regla siga aquí y que nadie
   vuelva a escribir un parche por elemento.
   =========================================================================== */
[hidden] { display: none !important; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--pizarra-800);
  color: var(--texto);
  font-family: var(--texto-f);
  font-size: calc(clamp(1rem, .96rem + .18vw, 1.075rem) * var(--escala-texto));
  line-height: var(--alto-linea);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
}

img, video, svg { max-width: 100%; height: auto; display: block; }

/* ------------------------------------------------------------ tipografía */

h1, h2, h3, h4 {
  font-family: var(--display);
  color: var(--blanco);
  margin: 0 0 .55em;
  text-wrap: balance;
}

/* El peso liviano en tamaños grandes es la firma de Témpora. */
h1 {
  font-size: calc(clamp(2.3rem, 1.5rem + 3.4vw, 4.1rem) * var(--escala-titulo));
  font-weight: var(--peso-titulo);
  line-height: 1.06;
  letter-spacing: -.022em;
}
h2 {
  font-size: calc(clamp(1.7rem, 1.25rem + 2vw, 2.75rem) * var(--escala-titulo));
  font-weight: var(--peso-titulo);
  line-height: 1.12;
  letter-spacing: -.018em;
}
/* De aquí para abajo el texto es funcional, no expresivo: gana la legibilidad. */
h3 {
  font-size: clamp(1.06rem, .98rem + .35vw, 1.2rem);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -.005em;
}
h4 {
  font-size: 1rem;
  font-weight: 600;
}

/* La separación entre párrafos se declara con el selector más flojo que hay
   —un elemento suelto— para que las utilidades .mb-0 y .mt-2 le sigan ganando
   sin tener que subirles la especificidad. */
p { margin: 0 0 calc(1.05em * var(--espacio-parrafo)); text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

a { color: var(--lima); text-decoration-thickness: 1px; text-underline-offset: .2em; }
a:hover { color: var(--lima-viva); }

strong { font-weight: 600; color: var(--blanco); }

::selection { background: var(--lima); color: var(--sobre-lima); }

:focus-visible {
  outline: 2px solid var(--lima);
  outline-offset: 3px;
  border-radius: 4px;
}

/* Micro-etiqueta con tracking amplio, en eco al logotipo T E M P O R A. */
.eyebrow {
  font-family: var(--ui);
  font-size: .7rem;
  font-weight: 500;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--lima);
  margin: 0 0 1.1rem;
}

/* --------------------------------------------------------------- soportes */

.contenedor {
  /* `--bloque-ancho` la pone el editor del sitio cuando una sección pide otro
     ancho; sin nadie que la ponga manda el del sitio. Va en el `width` y no en
     un `max-width` aparte para que «sin límite» sea de verdad sin límite. */
  width: min(100% - (var(--canal) * 2), var(--bloque-ancho, var(--ancho)));
  margin-inline: auto;
}
.contenedor--angosto { --ancho: 820px; }

.solo-lectores {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.saltar {
  position: absolute;
  top: -100px; left: 1rem;
  z-index: 100;
  background: var(--lima);
  color: var(--sobre-lima);
  padding: .7rem 1.2rem;
  border-radius: 0 0 var(--radio-s) var(--radio-s);
  font-weight: 600;
  text-decoration: none;
  transition: top var(--rapido) var(--curva);
}
.saltar:focus { top: 0; }

/* ------------------------------------------------------------ ornamento */

/* La hoja lima que sangra por detrás. Aparece UNA vez por pantalla y en una
   sola esquina: repetida pierde toda la gracia y ensucia la lectura. */
.halo {
  position: fixed;
  z-index: -1;
  pointer-events: none;
  top: 0;
  left: 0;
  right: 0;
  /* Mismo motivo que en .fondo-foto: alto estable frente a la barra del
     navegador, para que el resplandor no se estire al desplazarse. */
  height: 100vh;
  height: 100lvh;
  overflow: hidden;
}
.halo::before {
  content: "";
  position: absolute;
  left: -18vw;
  top: 32vh;
  width: 62vw;
  height: 62vw;
  max-width: 900px;
  max-height: 900px;
  border-radius: 50%;
  background:
    conic-gradient(from 210deg,
      transparent 0deg,
      color-mix(in srgb, var(--lima) 42%, transparent) 55deg,
      color-mix(in srgb, var(--lima) 10%, transparent) 120deg,
      transparent 165deg);
  filter: blur(60px);
  opacity: .5;
}

/* -------------------------------------------------------------- cabecera */

.cabecera {
  position: sticky;
  top: 0;
  z-index: 40;
  background: color-mix(in srgb, var(--pizarra-800) 82%, transparent);
  backdrop-filter: saturate(1.4) blur(16px);
  border-bottom: var(--grosor-borde) solid var(--linea);
}

.cabecera__fila {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  min-height: 74px;
}

/* Logotipo: letras separadas con la O convertida en anillo, como la marca. */
.marca {
  display: inline-flex;
  align-items: center;
  gap: .1em;
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(.95rem, .88rem + .3vw, 1.1rem);
  letter-spacing: .34em;
  text-transform: uppercase;
  color: var(--blanco);
  text-decoration: none;
  white-space: nowrap;
}
.marca__anillo {
  display: inline-block;
  width: .78em;
  height: .78em;
  border: 1.5px solid var(--lima);
  border-radius: 50%;
  margin-inline: .06em .28em;
  transition: transform var(--normal) var(--resorte);
}
.marca:hover .marca__anillo { transform: scale(1.22); }
/* El `max()` pone un suelo de 11 px sin renunciar a que el sufijo sea más
   chico que el nombre: en proporción pura caía a 10,2 px, que en la barra
   superior de un monitor grande es una línea gris que no se lee. */
/* El logo subido. Se escala por el ALTO y el ancho sale solo, así que un logo
   apaisado y uno cuadrado se ven bien sin que nadie tenga que recortarlos. */
.marca--logo { gap: .6rem; }
.marca__logo {
  height: var(--logo-alto, 34px);
  width: auto;
  max-width: min(240px, 46vw);
  object-fit: contain;
  display: block;
}

.marca__sufijo {
  font-family: var(--ui);
  font-size: max(11px, .62em);
  letter-spacing: .16em;
  color: var(--texto-2);
  margin-left: .9em;
  padding-left: .9em;
  border-left: var(--grosor-borde) solid var(--linea-viva);
}
@media (max-width: 680px) { .marca__sufijo { display: none; } }

.nav {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: .2rem;
}

.nav a {
  font-family: var(--ui);
  font-size: .88rem;
  font-weight: 500;
  color: var(--texto-2);
  text-decoration: none;
  padding: .55rem .9rem;
  border-radius: var(--radio-s);
  transition: color var(--rapido) var(--curva), background var(--rapido) var(--curva);
  white-space: nowrap;
}
.nav a:hover { color: var(--blanco); background: rgb(255 255 255 / .06); }
.nav a[aria-current="page"] { color: var(--lima); }

@media (max-width: 560px) {
  .cabecera__fila { min-height: 64px; gap: .5rem; }
  .nav { gap: 0; }
  .nav a { padding: .5rem .55rem; font-size: .82rem; }
}

/* --------------------------------------------------------------- botones */

.boton {
  --fondo: var(--lima);
  --frente: var(--sobre-lima);
  --borde: transparent;

  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .6rem;
  appearance: none;
  cursor: pointer;
  border: 1px solid var(--borde);
  background: var(--fondo);
  color: var(--frente);
  font-family: var(--ui);
  font-size: .93rem;
  font-weight: 500;
  line-height: 1;
  letter-spacing: .01em;
  text-decoration: none;
  padding: .95rem 1.6rem;
  min-height: 48px;
  border-radius: var(--radio-boton);
  transition:
    background var(--rapido) var(--curva),
    color var(--rapido) var(--curva),
    border-color var(--rapido) var(--curva),
    box-shadow var(--rapido) var(--curva),
    transform var(--rapido) var(--curva);
}

/* --- el neón de los botones ------------------------------------------------

   Al tocarlos o pasarles el cursor NO cambian de color: se les enciende un
   recubrimiento de neón alrededor. Lo pidió la organización y de paso resuelve
   algo que el color no resolvía: un botón que se aclara al pasar por encima se
   confunde con un botón deshabilitado que se aclara, y el halo no se confunde
   con nada.

   El color del halo sale del PROPIO fondo del botón, no de una variable fija.
   Así el botón lima brilla lima y el fantasma brilla blanco, sin escribir una
   regla por variante — y si alguien cambia el acento desde Apariencia, el neón
   lo sigue solo.

   `:focus-visible` recibe lo mismo: quien navega con el tabulador tiene que ver
   dónde está, y darle un tratamiento distinto al del cursor sería mantener dos
   apariencias para la misma idea. */

.boton:hover:not(:disabled),
.boton:focus-visible:not(:disabled) {
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--fondo) 75%, transparent),
    0 0 18px color-mix(in srgb, var(--fondo) 45%, transparent);
  transform: translateY(-1px);
}

/* Un botón transparente no tiene color propio del que sacar el halo: el suyo
   lo da el acento del sitio, que es lo que se ve alrededor del borde. */
.boton--fantasma:hover:not(:disabled),
.boton--fantasma:focus-visible:not(:disabled),
.boton--tenue:hover:not(:disabled),
.boton--tenue:focus-visible:not(:disabled) {
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--lima) 70%, transparent),
    0 0 18px color-mix(in srgb, var(--lima) 35%, transparent);
}

.boton:active:not(:disabled) { transform: translateY(0); }
.boton:disabled { opacity: .38; cursor: not-allowed; }

/* La flecha avanza al pasar el cursor: el mismo gesto que usa la marca. */
.boton::after {
  content: "→";
  font-size: 1.05em;
  line-height: 1;
  transition: transform var(--normal) var(--curva);
}
.boton:hover:not(:disabled)::after { transform: translateX(4px); }
.boton--sin-flecha::after { content: none; }

.boton--fantasma {
  --fondo: transparent;
  --frente: var(--blanco);
  --borde: var(--linea-viva);
}
/* Sólo el borde se aviva, para que el neón tenga de dónde agarrarse. El fondo
   se queda como está: lo que marca el estado es el halo. */
.boton--fantasma:hover:not(:disabled),
.boton--fantasma:focus-visible:not(:disabled) { --borde: var(--lima); }

.boton--tenue {
  --fondo: rgb(255 255 255 / .07);
  --frente: var(--texto);
  --borde: transparent;
}
.boton--tenue:hover:not(:disabled),
.boton--tenue:focus-visible:not(:disabled) { --frente: var(--blanco); }

.boton--grande { padding: 1.1rem 2rem; font-size: 1rem; min-height: 56px; }
.boton--bloque { width: 100%; }

.boton[data-ocupado="1"] { pointer-events: none; opacity: .75; }
.boton[data-ocupado="1"]::after {
  content: "";
  width: 1em; height: 1em;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-top-color: transparent;
  animation: girar .7s linear infinite;
}
@keyframes girar { to { transform: rotate(1turn); } }

.boton-icono {
  display: grid;
  place-items: center;
  width: 40px; height: 40px;
  flex: none;
  border: 0;
  border-radius: 50%;
  background: rgb(255 255 255 / .07);
  color: var(--texto-2);
  font-size: .95rem;
  cursor: pointer;
  transition: background var(--rapido) var(--curva), color var(--rapido) var(--curva);
}
.boton-icono:hover { background: rgb(255 255 255 / .14); color: var(--blanco); }

/* -------------------------------------------------------------- secciones */

/* Tres factores multiplicando el mismo hueco, y cada uno responde a una
   pregunta distinta: `--densidad` es «cuánto respira el sitio», `--espacio-
   seccion` es «cuánto se separan las secciones entre sí», y `--bloque-espacio`
   es «cuánto respira ESTE bloque». Los dos primeros los pone Apariencia y valen
   en todas partes; el tercero lo pone Disposición y vale sólo dentro del bloque
   que lo declara. Multiplicarlos —en vez de que uno pise a otro— es lo que
   permite ajustar uno sin perder lo que se había decidido en los otros. */
.seccion { padding: calc(clamp(3rem, 7vw, 6rem) * var(--densidad) * var(--espacio-seccion) * var(--bloque-espacio, 1)) 0; }
.seccion--compacta { padding: calc(clamp(2rem, 4vw, 3.25rem) * var(--densidad) * var(--espacio-seccion) * var(--bloque-espacio, 1)) 0; }

.seccion__intro { max-width: var(--ancho-texto); margin-bottom: clamp(2rem, 4vw, 3rem); }
.seccion__intro p { color: var(--texto-2); font-size: 1.06rem; }

.centrado { text-align: center; }
.centrado .seccion__intro { margin-inline: auto; }

/* ---------------------------------------------------------------- portada */

.hero {
  padding: calc(clamp(3rem, 8vw, 7rem) * var(--densidad) * var(--alto-hero) * var(--bloque-espacio, 1)) 0
           calc(clamp(2.5rem, 5vw, 4rem) * var(--densidad) * var(--alto-hero) * var(--bloque-espacio, 1));
}

.hero__grid {
  display: grid;
  gap: clamp(2.5rem, 5vw, 4.5rem);
  align-items: center;
}
@media (min-width: 940px) { .hero__grid { grid-template-columns: 1.08fr .92fr; } }

.hero h1 .resalte {
  color: var(--lima);
  font-weight: 400;
}

.hero__bajada {
  font-size: clamp(1.05rem, 1rem + .35vw, 1.25rem);
  color: var(--texto-2);
  max-width: 54ch;
  margin-bottom: 2rem;
}

/* --- el tema de la paya, en el encabezado ---------------------------------

   Es un REQUISITO —el primer criterio de evaluación lo mide y con menos de 3
   puntos la paya queda fuera— así que se lee como un aviso y no como un párrafo
   más. Lima al borde izquierdo: es la marca que el sitio usa para lo accionable,
   y aquí lo accionable es «que tu paya trate de esto».

   `align-items: start` para que el icono quede a la altura del rótulo y no
   centrado respecto a dos renglones de texto. */

.hero__tema {
  display: flex;
  align-items: start;
  gap: .7rem;
  margin: 1.35rem 0;
  padding: .85rem 1rem;
  border-radius: var(--radio-m);
  border: var(--grosor-borde) solid color-mix(in srgb, var(--lima) 32%, transparent);
  border-left: 3px solid var(--lima);
  background: color-mix(in srgb, var(--lima) 7%, transparent);
}
.hero__tema-icono { width: 20px; height: 20px; flex: none; margin-top: .15rem; color: var(--lima); }

.hero__tema-rotulo {
  margin: 0;
  font-family: var(--ui);
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--lima);
}
/* `min-width: 0` porque vive en una caja flexible: sin él, un texto largo no se
   encoge y estira el encabezado entero. Cuarta vez en este proyecto. */
.hero__tema-texto { margin: .25rem 0 0; font-size: .95rem; color: var(--texto); min-width: 0; }
.hero__tema > div { min-width: 0; }

.hero__acciones { display: flex; flex-wrap: wrap; gap: .8rem; }

.hero__pie {
  margin-top: 2.25rem;
  padding-top: 1.5rem;
  border-top: var(--grosor-borde) solid var(--linea);
  font-family: var(--ui);
  font-size: .88rem;
  color: var(--texto-2);
}

/* --- los dos premios, al lado del titular ---------------------------------

   Ocupan el hueco donde estaban las dos categorías. Se apilan en una columna
   en pantalla chica y se ponen lado a lado en cuanto hay sitio: son dos cajas
   con una cifra dentro, y a 375 px en dos columnas la cifra se parte en dos
   renglones —que es justo lo que no puede pasarle a «$1.000.000»—.

   `auto-fit` con un mínimo: si sólo hay un premio escrito, ocupa el ancho
   entero él solo en vez de dejar media fila vacía al lado. */

.galardones {
  display: grid;
  gap: calc(var(--gap-rejilla) * var(--bloque-separacion, 1));
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 480px) {
  .galardones { grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr)); }
}

.galardon {
  padding: calc(clamp(1.4rem, 3vw, 2rem) * var(--densidad) * var(--pad-tarjeta) * var(--bloque-relleno, 1)) 1.25rem;
  box-shadow: var(--sombra);
  border-radius: var(--radio-m);
  background: var(--pizarra-700);
  border: var(--grosor-borde) solid var(--linea);
  text-align: center;
  min-width: 0;
  transition: border-color var(--normal) var(--curva), transform var(--normal) var(--curva);
}
.galardon:hover { border-color: color-mix(in srgb, var(--lima) 45%, transparent); transform: translateY(-3px); }

.galardon__icono { width: 46px; height: 46px; margin: 0 auto .75rem; color: var(--lima); }

.galardon__lugar {
  font-family: var(--ui);
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--lima);
  margin: 0;
}

/* La cifra es lo que se viene a leer, así que es lo más grande de la caja.
   `text-wrap: balance` reparte «Un implante capilar en Clínica Témpora» en
   renglones parecidos en vez de dejar una palabra suelta abajo; el navegador
   que no lo entienda simplemente lo ignora. */
.galardon__premio {
  font-family: var(--display);
  font-size: clamp(1.05rem, .9rem + .5vw, 1.32rem);
  font-weight: 600;
  line-height: 1.25;
  color: var(--blanco);
  margin: .3rem 0 0;
  text-wrap: balance;
  overflow-wrap: anywhere;
}
.galardon__nota { font-size: .84rem; color: var(--texto-2); margin: .45rem 0 0; }

/* ------------------------------------------------------------- tarjetas */

.tarjeta {
  background: var(--pizarra-700);
  border: var(--grosor-borde) solid var(--linea);
  border-radius: var(--radio-m);
  padding: calc(clamp(1.4rem, 3vw, 2.25rem) * var(--densidad) * var(--pad-tarjeta) * var(--bloque-relleno, 1));
  box-shadow: var(--sombra);
}
.tarjeta--acento { border-color: color-mix(in srgb, var(--lima) 40%, transparent); }

.rejilla {
  display: grid;
  gap: calc(var(--gap-rejilla) * var(--bloque-separacion, 1));
  /* El ancho mínimo es lo que decide cuántas columnas caben; el `min(…,100%)`
     es lo que impide que en un celular angosto la rejilla desborde. */
  grid-template-columns: repeat(auto-fit, minmax(min(var(--tarjeta-min), 100%), 1fr));
}

/* Tarjeta con marca de verificación, como el «¿Qué incluye?» de la clínica. */
.punto {
  padding: calc(1.6rem * var(--densidad) * var(--pad-tarjeta) * var(--bloque-relleno, 1)) calc(1.35rem * var(--densidad) * var(--pad-tarjeta) * var(--bloque-relleno, 1));
  box-shadow: var(--sombra);
  border-radius: var(--radio-m);
  background: var(--pizarra-700);
  border: var(--grosor-borde) solid var(--linea);
  text-align: center;
}
.punto__marca { width: 30px; height: 30px; margin: 0 auto .85rem; color: var(--lima); }
.punto h3 { margin-bottom: .35rem; }
.punto p { font-size: .92rem; color: var(--texto-2); margin: 0; }

/* Cifras */
.dato {
  padding: calc(1.5rem * var(--pad-tarjeta) * var(--bloque-relleno, 1)) calc(1.25rem * var(--pad-tarjeta) * var(--bloque-relleno, 1));
  border-radius: var(--radio-m);
  background: var(--pizarra-700);
  border: var(--grosor-borde) solid var(--linea);
  text-align: center;
}
.dato__cifra {
  display: block;
  font-family: var(--display);
  font-size: calc(clamp(2.1rem, 1.6rem + 2vw, 3rem) * var(--escala-titulo));
  font-weight: var(--peso-titulo);
  line-height: 1;
  color: var(--lima);
  font-variant-numeric: tabular-nums;
}
.dato__etiqueta {
  display: block;
  margin-top: .5rem;
  font-family: var(--ui);
  font-size: .82rem;
  color: var(--texto-2);
}

/* Pasos numerados: el número ES la información, por eso se muestra. */
.pasos { counter-reset: paso; display: grid; gap: calc(var(--gap-rejilla) * var(--bloque-separacion, 1)); grid-template-columns: repeat(auto-fit, minmax(min(var(--tarjeta-min), 100%), 1fr)); }
.paso {
  counter-increment: paso;
  padding: calc(1.75rem * var(--densidad) * var(--pad-tarjeta) * var(--bloque-relleno, 1)) 1.4rem calc(1.5rem * var(--densidad) * var(--pad-tarjeta) * var(--bloque-relleno, 1));
  box-shadow: var(--sombra);
  border-radius: var(--radio-m);
  background: var(--pizarra-700);
  border: var(--grosor-borde) solid var(--linea);
}
.paso::before {
  content: counter(paso, decimal-leading-zero);
  display: block;
  font-family: var(--ui);
  font-size: .78rem;
  font-weight: 500;
  letter-spacing: .18em;
  color: var(--lima);
  margin-bottom: .9rem;
}
.paso p { font-size: .93rem; color: var(--texto-2); margin: 0; }

/* ------------------------------------------------------------ formularios */

.campo { margin-bottom: 1.35rem; }

.campo > label,
.campo__titulo {
  display: block;
  font-family: var(--ui);
  font-size: .85rem;
  font-weight: 500;
  color: var(--texto);
  margin-bottom: .5rem;
}

.campo__ayuda { font-size: .84rem; color: var(--texto-3); margin: .45rem 0 0; }

.entrada {
  width: 100%;
  min-height: 52px;
  padding: .9rem 1.05rem;
  border-radius: var(--radio-s);
  border: var(--grosor-borde) solid var(--linea-viva);
  background: rgb(0 0 0 / .18);
  color: var(--blanco);
  font-family: var(--texto-f);
  font-size: 1rem;
  transition: border-color var(--rapido) var(--curva), background var(--rapido) var(--curva);
}
.entrada::placeholder { color: var(--texto-3); }
.entrada:hover { border-color: var(--pizarra-600); }
.entrada:focus {
  outline: none;
  border-color: var(--lima);
  background: rgb(0 0 0 / .28);
}
.entrada[aria-invalid="true"] { border-color: var(--error); }

select.entrada { appearance: none; background-image: none; cursor: pointer; }
textarea.entrada { resize: vertical; min-height: 110px; line-height: 1.6; }

.campo__error {
  display: none;
  font-family: var(--ui);
  font-size: .84rem;
  color: var(--error);
  margin-top: .45rem;
}
.campo[data-error="1"] .campo__error { display: block; }

.trampa {
  position: absolute !important;
  left: -9999px !important;
  opacity: 0 !important;
  height: 0 !important;
  pointer-events: none;
}

/* Aquí vivía el selector de categoría del formulario. Se retiró con el paso a
   una sola categoría: el campo dejó de preguntarse —la pone el servidor— y unas
   reglas para un control que ya no se pinta son de las que sobreviven a tres
   rediseños sin que nadie sepa de qué eran. Si vuelve a haber más de una, se
   recupera del historial de `git` junto con su formulario. */

/* --- aceptación --- */

.acepto {
  display: flex;
  gap: .85rem;
  align-items: flex-start;
  padding: 1rem 1.15rem;
  border-radius: var(--radio-s);
  border: var(--grosor-borde) solid var(--linea-viva);
  background: rgb(0 0 0 / .14);
  cursor: pointer;
  transition: border-color var(--rapido) var(--curva), background var(--rapido) var(--curva);
}
.acepto:hover { border-color: var(--pizarra-600); }
.acepto input { width: 22px; height: 22px; flex: none; accent-color: var(--lima); margin-top: .12rem; }
.acepto span { font-size: .95rem; }
.acepto:has(input:checked) {
  border-color: color-mix(in srgb, var(--lima) 55%, transparent);
  background: color-mix(in srgb, var(--lima) 8%, transparent);
}

/* ------------------------------------------------------------ caja bases */

.bases-envoltura { position: relative; }

.bases-caja {
  max-height: clamp(230px, 48vh, 440px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 1.4rem 1.5rem;
  border-radius: var(--radio-m);
  border: var(--grosor-borde) solid var(--linea-viva);
  background: rgb(0 0 0 / .16);
  font-size: .93rem;
  line-height: 1.72;
  color: var(--texto);
  scrollbar-width: thin;
  scrollbar-color: var(--pizarra-600) transparent;
}
.bases-caja h2 {
  font-size: 1.02rem;
  font-weight: 600;
  color: var(--lima);
  margin: 1.8rem 0 .6rem;
  letter-spacing: 0;
}
.bases-caja h2:first-child { margin-top: 0; }
.bases-caja ol, .bases-caja ul { padding-left: 1.3rem; margin: 0 0 1em; }
.bases-caja li { margin-bottom: .45rem; }
.bases-caja::-webkit-scrollbar { width: 10px; }
.bases-caja::-webkit-scrollbar-thumb { background: var(--pizarra-600); border-radius: 999px; border: 3px solid transparent; background-clip: padding-box; }

.bases-aviso {
  padding: .85rem 1rem;
  border-left: 2px solid var(--lima);
  background: color-mix(in srgb, var(--lima) 8%, transparent);
  border-radius: 0 var(--radio-s) var(--radio-s) 0;
  font-size: .9rem;
}

.bases-fin {
  position: absolute;
  left: 50%; bottom: 14px;
  translate: -50%;
  padding: .38rem .95rem;
  border-radius: 999px;
  background: var(--lima);
  color: var(--sobre-lima);
  font-family: var(--ui);
  font-size: .76rem;
  font-weight: 500;
  pointer-events: none;
  transition: opacity var(--normal) var(--curva), translate var(--normal) var(--curva);
}
.bases-envoltura[data-leido="1"] .bases-fin { opacity: 0; translate: -50% 8px; }

/* ------------------------------------------------------------- asistente */

.progreso-pasos {
  display: flex;
  gap: .5rem;
  list-style: none;
  margin: 0 0 2.5rem;
  padding: 0;
}
.progreso-paso {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: .5rem;
  font-family: var(--ui);
  font-size: .78rem;
  font-weight: 500;
  color: var(--texto-3);
  text-align: center;
}
.progreso-paso::before {
  content: "";
  height: 3px;
  border-radius: 999px;
  background: var(--linea);
  transition: background var(--lento) var(--curva);
}
.progreso-paso[data-estado="activo"] { color: var(--lima); }
.progreso-paso[data-estado="activo"]::before { background: var(--lima); }
.progreso-paso[data-estado="listo"] { color: var(--texto-2); }
.progreso-paso[data-estado="listo"]::before { background: color-mix(in srgb, var(--lima) 45%, transparent); }
@media (max-width: 560px) { .progreso-paso span { display: none; } }

.wizard-paso { display: none; }
.wizard-paso[data-activo="1"] { display: block; animation: entrar var(--lento) var(--curva) both; }
@keyframes entrar {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}

.wizard-acciones {
  display: flex;
  gap: .7rem;
  flex-wrap: wrap;
  align-items: center;
  margin-top: 1.75rem;
}
.wizard-acciones .boton--fantasma:first-child { margin-right: auto; }

/* Las acciones del archivo ya elegido van justo ENCIMA de la previa, así que
   necesitan aire por debajo y no por arriba: separan de la zona de elegir y se
   apoyan sobre el video. */
.wizard-acciones--archivo { margin-top: 1.25rem; margin-bottom: .25rem; }

/* ------------------------------------------------------------ subir video */

.selector-modo {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .3rem;
  padding: .3rem;
  border-radius: var(--radio-s);
  background: rgb(0 0 0 / .22);
  border: var(--grosor-borde) solid var(--linea);
  margin-bottom: 1.5rem;
}
.selector-modo button {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--texto-2);
  font-family: var(--ui);
  font-size: .9rem;
  font-weight: 500;
  padding: .7rem 1rem;
  min-height: 46px;
  border-radius: calc(var(--radio-s) - 2px);
  cursor: pointer;
  transition: background var(--normal) var(--curva), color var(--normal) var(--curva);
}
.selector-modo button[aria-selected="true"] { background: var(--lima); color: var(--sobre-lima); }
.selector-modo button[disabled] { opacity: .35; cursor: not-allowed; }

.zona-soltar {
  position: relative;
  display: grid;
  place-items: center;
  gap: .7rem;
  padding: clamp(2.25rem, 6vw, 3.5rem) 1.5rem;
  border-radius: var(--radio-m);
  border: 1px dashed var(--linea-viva);
  background: rgb(0 0 0 / .14);
  text-align: center;
  cursor: pointer;
  transition: border-color var(--normal) var(--curva), background var(--normal) var(--curva);
}
.zona-soltar:hover, .zona-soltar[data-encima="1"] {
  border-color: var(--lima);
  background: color-mix(in srgb, var(--lima) 6%, transparent);
}
.zona-soltar__icono { width: 42px; height: 42px; color: var(--lima); }
.zona-soltar__titulo { font-family: var(--display); font-size: 1.1rem; font-weight: 600; color: var(--blanco); }
.zona-soltar__nota { font-size: .86rem; color: var(--texto-3); margin: 0; }
.zona-soltar input[type="file"] { position: absolute; inset: 0; opacity: 0; cursor: pointer; }

/* --- grabadora --- */

.grabadora {
  position: relative;
  border-radius: var(--radio-m);
  overflow: hidden;
  background: #000;
  aspect-ratio: 9 / 16;
  max-height: 62vh;
  margin-inline: auto;
}
@media (min-width: 760px) { .grabadora { aspect-ratio: 16 / 9; max-height: none; } }

.grabadora video { width: 100%; height: 100%; object-fit: cover; }
.grabadora video[data-espejo="1"] { transform: scaleX(-1); }

.grabadora__capa {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 1rem;
  pointer-events: none;
  background: linear-gradient(180deg, rgb(0 0 0 / .4) 0%, transparent 24%, transparent 60%, rgb(0 0 0 / .6) 100%);
}
.grabadora__capa > * { pointer-events: auto; }
.grabadora__superior { display: flex; align-items: center; gap: .7rem; }

.grabadora__tiempo {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .35rem .8rem;
  border-radius: 999px;
  background: rgb(0 0 0 / .55);
  backdrop-filter: blur(6px);
  color: var(--blanco);
  font-family: var(--ui);
  font-variant-numeric: tabular-nums;
  font-size: .87rem;
  font-weight: 500;
}
.grabadora__punto { width: 8px; height: 8px; border-radius: 50%; background: #ff5147; }
.grabadora[data-grabando="1"] .grabadora__punto { animation: latir 1.1s ease-in-out infinite; }
@keyframes latir { 50% { opacity: .25; } }

/* El tiempo que QUEDA, arriba a la derecha. `margin-left: auto` lo empuja hasta
   el borde sin necesidad de un `space-between` que descolocaría el vúmetro del
   contador de la izquierda. Se ve más grande que el resto de la capa a
   propósito: es el dato que decide cuándo hay que cerrar la paya. */
.grabadora__restante {
  margin-left: auto;
  padding: .35rem .85rem;
  border-radius: 999px;
  background: rgb(0 0 0 / .55);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  color: var(--blanco);
  font-family: var(--ui);
  font-variant-numeric: tabular-nums;
  font-size: 1.05rem;
  font-weight: 500;
  letter-spacing: .02em;
  transition: background var(--rapido) var(--curva), color var(--rapido) var(--curva);
}

/* Los últimos diez segundos se avisan en rojo. La grabadora ya marcaba ese
   tramo con `dataset.porTerminar` —que en el HTML es `data-por-terminar`— para
   el anillo del botón; aquí se reusa en vez de contar el tiempo dos veces. */
.grabadora[data-por-terminar="1"] .grabadora__restante {
  background: #d33a30;
  color: #fff;
}

.grabadora__inferior { display: flex; align-items: center; justify-content: center; gap: 1.5rem; }

.rec-envoltura { position: relative; display: grid; place-items: center; }
.rec {
  width: 74px; height: 74px;
  border-radius: 50%;
  border: 3px solid rgb(255 255 255 / .85);
  background: transparent;
  cursor: pointer;
  display: grid; place-items: center;
  padding: 0;
  transition: transform var(--normal) var(--resorte);
}
.rec:hover { transform: scale(1.05); }
.rec__nucleo {
  width: 56%; height: 56%;
  border-radius: 50%;
  background: #ff5147;
  transition: all var(--normal) var(--resorte);
}
.grabadora[data-grabando="1"] .rec__nucleo { border-radius: 5px; width: 38%; height: 38%; }

.rec-secundario {
  width: 46px; height: 46px;
  border-radius: 50%;
  border: 0;
  background: rgb(255 255 255 / .16);
  backdrop-filter: blur(8px);
  color: var(--blanco);
  font-family: var(--ui);
  font-size: .85rem;
  cursor: pointer;
  display: grid; place-items: center;
  transition: background var(--rapido) var(--curva);
}
.rec-secundario:hover { background: rgb(255 255 255 / .28); }

.anillo { position: absolute; inset: -7px; pointer-events: none; }
.anillo circle { fill: none; stroke-width: 3; }
.anillo .pista { stroke: rgb(255 255 255 / .2); }
.anillo .avance {
  stroke: var(--lima);
  stroke-linecap: round;
  transform: rotate(-90deg);
  transform-origin: 50% 50%;
  transition: stroke-dashoffset .25s linear;
}

.vumetro { display: flex; align-items: flex-end; gap: 3px; height: 24px; }
.vumetro span { width: 3px; height: 4px; border-radius: 2px; background: rgb(255 255 255 / .3); transition: height .08s linear, background .08s linear; }
.vumetro span[data-activo="1"] { background: var(--lima); }

.cuenta-atras {
  position: absolute; inset: 0; z-index: 3;
  display: grid; place-items: center;
  background: rgb(0 0 0 / .6);
  color: var(--blanco);
  font-family: var(--display);
  font-size: clamp(4.5rem, 20vw, 9rem);
  font-weight: 300;
}
.cuenta-atras span { animation: pulso 1s var(--curva) both; }
@keyframes pulso {
  from { opacity: 0; transform: scale(1.5); }
  40%  { opacity: 1; transform: scale(1); }
  to   { opacity: 0; transform: scale(.9); }
}

/* --- progreso de subida --- */

.progreso {
  margin-top: 1.4rem;
  padding: 1.25rem 1.4rem;
  border-radius: var(--radio-m);
  background: rgb(0 0 0 / .18);
  border: var(--grosor-borde) solid var(--linea);
}
.progreso__fila {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  font-family: var(--ui);
  font-size: .87rem;
  margin-bottom: .75rem;
}
.progreso__etiqueta { font-weight: 500; color: var(--blanco); }
.progreso__detalle { color: var(--texto-2); font-variant-numeric: tabular-nums; }

.barra { height: 6px; border-radius: 999px; background: rgb(255 255 255 / .1); overflow: hidden; }
.barra__relleno {
  height: 100%;
  width: 0;
  border-radius: 999px;
  background: var(--lima);
  transition: width .35s var(--curva);
}

/* --- la capa de subida -----------------------------------------------------

   Mientras el video sube, el progreso deja de ser una barra dentro de la
   tarjeta y pasa a estar POR ENCIMA de todo, con el fondo desenfocado. Dos
   razones: en un celular la barra quedaba fuera de la pantalla justo en el
   único momento del formulario en que hay que esperar sin tocar nada, y una
   capa impide seguir editando algo que ya se está enviando.

   El desenfoque va con un velo del 40 %: sin él, sobre una ilustración clara el
   texto blanco de la capa se pierde igual por mucho que esté borrosa. */

.capa-subida {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  padding: var(--canal);
  background: rgb(15 20 24 / .4);
  -webkit-backdrop-filter: blur(10px) saturate(1.1);
  backdrop-filter: blur(10px) saturate(1.1);
}

.capa-subida__caja {
  width: min(30rem, 100%);
  padding: clamp(1.3rem, 4vw, 2rem);
  border-radius: var(--radio-l);
  background: var(--pizarra-700);
  border: var(--grosor-borde) solid var(--vidrio-borde);
  box-shadow: 0 24px 60px rgb(0 0 0 / .45);
  text-align: center;
}

/* Dentro de la capa el progreso ya no es una caja aparte: la caja es la capa. */
.capa-subida .progreso {
  margin-top: 0;
  padding: 0;
  background: none;
  border: 0;
}
.capa-subida__nota { margin: 1rem 0 1.25rem; }

/* Con la capa abierta el fondo no se desplaza: es una espera, no un sitio del
   que uno se pueda ir sin decidir. */
body[data-subiendo] { overflow: hidden; }

.vista-previa {
  margin-top: 1.25rem;
  border-radius: var(--radio-m);
  overflow: hidden;
  background: #000;
  border: var(--grosor-borde) solid var(--linea);
}
.vista-previa video { width: 100%; max-height: 54vh; }

/* --------------------------------------------------------------- galería */

.votacion-cabecera {
  position: sticky;
  top: 74px;
  z-index: 30;
  padding: 1.1rem 0;
  background: color-mix(in srgb, var(--pizarra-800) 90%, transparent);
  backdrop-filter: blur(14px);
  border-bottom: var(--grosor-borde) solid var(--linea);
}
@media (max-width: 560px) { .votacion-cabecera { top: 64px; } }

.buscador { position: relative; }
.buscador__icono {
  position: absolute;
  left: 1.05rem; top: 50%;
  translate: 0 -50%;
  width: 18px; height: 18px;
  color: var(--texto-3);
  pointer-events: none;
}
.buscador .entrada { padding-left: 3rem; padding-right: 3rem; }
.buscador__limpiar {
  position: absolute;
  right: .65rem; top: 50%;
  translate: 0 -50%;
  width: 32px; height: 32px;
  border: 0; border-radius: 50%;
  background: rgb(255 255 255 / .1);
  color: var(--texto-2);
  cursor: pointer;
  display: none;
  place-items: center;
}
.buscador[data-con-texto="1"] .buscador__limpiar { display: grid; }

.filtros { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; margin-top: .85rem; }

.chip {
  appearance: none;
  border: var(--grosor-borde) solid var(--linea-viva);
  background: transparent;
  color: var(--texto-2);
  font-family: var(--ui);
  font-size: .85rem;
  font-weight: 500;
  padding: .45rem 1rem;
  min-height: 40px;
  border-radius: 999px;
  cursor: pointer;
  transition: all var(--rapido) var(--curva);
}
.chip:hover { border-color: var(--pizarra-600); color: var(--blanco); }
.chip[aria-pressed="true"] { background: var(--lima); border-color: var(--lima); color: var(--sobre-lima); }
.filtros__conteo { margin-left: auto; font-family: var(--ui); font-size: .84rem; color: var(--texto-3); }

.galeria {
  display: grid;
  gap: clamp(.9rem, 2vw, 1.35rem);
  grid-template-columns: repeat(auto-fill, minmax(min(255px, 100%), 1fr));
  padding: 2rem 0 clamp(7rem, 20vh, 11rem);
}

.participante {
  position: relative;
  display: flex;
  flex-direction: column;
  appearance: none;
  padding: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  border-radius: var(--radio-m);
  overflow: hidden;
  background: var(--pizarra-700);
  border: var(--grosor-borde) solid var(--linea);
  transition:
    border-color var(--normal) var(--curva),
    transform var(--normal) var(--resorte),
    box-shadow var(--normal) var(--curva);
}
.participante:hover, .participante:focus-visible {
  transform: translateY(-5px);
  border-color: var(--linea-viva);
  box-shadow: 0 14px 34px rgb(0 0 0 / .35);
}
.participante[aria-pressed="true"] {
  border-color: var(--lima);
  transform: translateY(-4px) scale(1.015);
  box-shadow: 0 0 0 1px var(--lima), 0 16px 38px rgb(0 0 0 / .4);
}

.galeria .participante { animation: aparecer var(--lento) var(--curva) backwards; }
.galeria .participante:nth-child(1) { animation-delay: 20ms; }
.galeria .participante:nth-child(2) { animation-delay: 50ms; }
.galeria .participante:nth-child(3) { animation-delay: 80ms; }
.galeria .participante:nth-child(4) { animation-delay: 110ms; }
.galeria .participante:nth-child(5) { animation-delay: 140ms; }
.galeria .participante:nth-child(6) { animation-delay: 170ms; }
.galeria .participante:nth-child(n+7) { animation-delay: 200ms; }
@keyframes aparecer {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

.participante__medio {
  position: relative;
  aspect-ratio: 16 / 10;
  background: var(--pizarra-900);
  overflow: hidden;
}
.participante__medio img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--lento) var(--curva); }
.participante:hover .participante__medio img { transform: scale(1.05); }

.participante__sin-imagen {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  color: rgb(255 255 255 / .18);
}
.participante__sin-imagen svg { width: 46px; height: 46px; }

.participante__play {
  position: absolute;
  right: .7rem; bottom: .7rem;
  width: 38px; height: 38px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: rgb(0 0 0 / .55);
  backdrop-filter: blur(6px);
  color: var(--blanco);
  opacity: 0;
  transform: scale(.85);
  transition: opacity var(--normal) var(--curva), transform var(--normal) var(--resorte);
}
.participante__play svg { width: 13px; height: 13px; }
.participante:hover .participante__play,
.participante:focus-visible .participante__play { opacity: 1; transform: scale(1); }

.participante__marca {
  position: absolute;
  top: .7rem; left: .7rem;
  width: 28px; height: 28px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: var(--lima);
  color: var(--sobre-lima);
  opacity: 0;
  transform: scale(.5);
  transition: all var(--normal) var(--resorte);
}
.participante__marca svg { width: 14px; height: 14px; }
.participante[aria-pressed="true"] .participante__marca { opacity: 1; transform: none; }

.participante__cuerpo { padding: .95rem 1.05rem 1.15rem; display: flex; flex-direction: column; gap: .5rem; }
.participante__nombre {
  font-family: var(--display);
  font-size: 1rem;
  font-weight: 600;
  color: var(--blanco);
  line-height: 1.3;
}
.participante__nombre mark { background: color-mix(in srgb, var(--lima) 40%, transparent); color: var(--blanco); border-radius: 2px; }

.etiqueta-categoria {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  font-family: var(--ui);
  font-size: .74rem;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--texto-2);
}
.etiqueta-categoria::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
}
.etiqueta-categoria[data-cat="pelado"] { color: var(--lima); }
.etiqueta-categoria[data-cat="peludo"] { color: #8fb8d8; }

.sin-resultados { grid-column: 1 / -1; text-align: center; padding: 4rem 1rem; color: var(--texto-2); }
.sin-resultados__icono { width: 42px; height: 42px; margin: 0 auto 1rem; color: var(--texto-3); }

/* ------------------------------------------------------- panel de voto */

.panel-voto {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 50;
  max-height: 92dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--pizarra-900);
  border-top: var(--grosor-borde) solid var(--linea-viva);
  border-radius: var(--radio-xl) var(--radio-xl) 0 0;
  box-shadow: 0 -18px 50px rgb(0 0 0 / .5);
  transform: translateY(110%);
  transition: transform var(--lento) var(--curva);
  padding-bottom: env(safe-area-inset-bottom, 0);
}
.panel-voto[data-abierto="1"] { transform: none; }

.panel-voto__asa { width: 40px; height: 4px; border-radius: 999px; background: var(--linea-viva); margin: .8rem auto .2rem; }
.panel-voto__interior { padding: .5rem var(--canal) 1.75rem; width: min(100%, 700px); margin-inline: auto; }

.voto-elegido {
  display: flex;
  align-items: center;
  gap: .85rem;
  padding: .8rem .95rem;
  border-radius: var(--radio-s);
  background: rgb(255 255 255 / .05);
  margin-bottom: 1.25rem;
}
.voto-elegido__mini { width: 58px; height: 40px; border-radius: 6px; object-fit: cover; flex: none; background: var(--pizarra-800); }
.voto-elegido__texto { flex: 1; min-width: 0; }
.voto-elegido__nombre { font-family: var(--display); font-weight: 600; color: var(--blanco); line-height: 1.25; }
.voto-elegido__cambiar {
  border: 0; background: transparent; cursor: pointer;
  font-family: var(--ui); font-size: .85rem; font-weight: 500;
  color: var(--lima); padding: .4rem;
}

.voto-etapa { display: none; }
.voto-etapa[data-activa="1"] { display: block; animation: entrar var(--normal) var(--curva) both; }

.otp { display: flex; gap: .5rem; justify-content: center; margin: 1.35rem 0; }
.otp input {
  width: clamp(42px, 13vw, 56px);
  height: clamp(52px, 15vw, 66px);
  text-align: center;
  font-family: var(--display);
  font-size: clamp(1.35rem, 5vw, 1.8rem);
  font-weight: 400;
  border-radius: var(--radio-s);
  border: var(--grosor-borde) solid var(--linea-viva);
  background: rgb(0 0 0 / .22);
  color: var(--blanco);
  transition: border-color var(--rapido) var(--curva), transform var(--rapido) var(--resorte);
}
.otp input:focus { outline: none; border-color: var(--lima); transform: translateY(-2px); }
.otp[data-error="1"] input { border-color: var(--error); animation: sacudir .4s var(--curva); }
@keyframes sacudir {
  25% { transform: translateX(-5px); }
  50% { transform: translateX(5px); }
  75% { transform: translateX(-2px); }
}

/* ----------------------------------------------------------------- avisos */

.aviso {
  padding: .95rem 1.15rem;
  border-radius: var(--radio-s);
  border: var(--grosor-borde) solid var(--linea);
  background: rgb(255 255 255 / .04);
  font-size: .93rem;
  margin-bottom: 1.25rem;
}
.aviso__cabeza { display: block; font-family: var(--ui); font-weight: 500; margin-bottom: .3rem; color: var(--blanco); }
.aviso--exito    { border-color: color-mix(in srgb, var(--exito) 40%, transparent); background: color-mix(in srgb, var(--exito) 10%, transparent); }
.aviso--error    { border-color: color-mix(in srgb, var(--error) 45%, transparent); background: color-mix(in srgb, var(--error) 10%, transparent); }
.aviso--atencion { border-color: color-mix(in srgb, var(--alerta) 40%, transparent); background: color-mix(in srgb, var(--alerta) 10%, transparent); }
.aviso--info     { border-color: color-mix(in srgb, var(--lima) 32%, transparent); background: color-mix(in srgb, var(--lima) 7%, transparent); }

.brindis {
  position: fixed;
  left: 50%; bottom: 1.5rem;
  translate: -50%;
  z-index: 90;
  display: flex;
  flex-direction: column;
  gap: .55rem;
  width: min(92vw, 400px);
  pointer-events: none;
}
.brindis__item {
  padding: .85rem 1.15rem;
  border-radius: var(--radio-s);
  background: var(--pizarra-900);
  border: var(--grosor-borde) solid var(--linea-viva);
  color: var(--texto);
  font-size: .92rem;
  box-shadow: 0 12px 32px rgb(0 0 0 / .45);
  animation: subir var(--normal) var(--resorte) both;
}
.brindis__item[data-tipo="exito"] { border-color: color-mix(in srgb, var(--exito) 55%, transparent); }
.brindis__item[data-tipo="error"] { border-color: color-mix(in srgb, var(--error) 55%, transparent); }
@keyframes subir {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}

/* ------------------------------------------------------------ celebración */

.celebracion { text-align: center; padding: clamp(3rem, 9vw, 6rem) 0; }
.celebracion__sello {
  width: clamp(84px, 20vw, 112px);
  aspect-ratio: 1;
  margin: 0 auto 2rem;
  border-radius: 50%;
  display: grid;
  place-items: center;
  border: 1px solid var(--lima);
  color: var(--lima);
  animation: sellar 620ms var(--resorte) both;
}
.celebracion__sello svg { width: 42%; height: 42%; }
@keyframes sellar {
  from { opacity: 0; transform: scale(.6); }
  to   { opacity: 1; transform: none; }
}

/* --- el llamado a Instagram de la pantalla de agradecimiento --------------

   Va inmediatamente después de confirmar que el video llegó, que es el único
   momento del recorrido en que la persona acaba de hacer algo por el concurso y
   está mirando la pantalla. Por eso el título es grande de verdad —compite con
   el h1 de arriba a propósito— y el botón usa el tamaño mayor. */

.gracias-ig {
  margin: clamp(1.75rem, 4vw, 2.5rem) 0;
  display: grid;
  gap: 1rem;
  justify-items: center;
}

.gracias-ig__titulo {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(1.35rem, 1.05rem + 1.4vw, 2rem);
  font-weight: var(--peso-titulo);
  line-height: 1.2;
  color: var(--blanco);
  text-wrap: balance;
}

/* ---------------------------------------------------------------- bases */

/* Una sola columna, sin índice lateral. El índice era `position: sticky` y el
   texto de las bases le pasaba por encima al desplazar, así que se leían los
   dos superpuestos. Un documento que se lee de corrido no lo necesitaba. */
.bases-texto { max-width: var(--ancho-texto); }
.bases-texto h2 {
  font-size: clamp(1.25rem, 1.1rem + .7vw, 1.6rem);
  font-weight: 400;
  color: var(--blanco);
  margin-top: 2.75rem;
  scroll-margin-top: 110px;
}
.bases-texto h2:first-of-type { margin-top: 0; }
.bases-texto li { margin-bottom: .55rem; }
.bases-texto ol, .bases-texto ul { padding-left: 1.3rem; }

/* -------------------------------------------------------------- resultados */

.podio { display: grid; gap: var(--gap-rejilla); grid-template-columns: repeat(auto-fit, minmax(min(var(--tarjeta-min),100%), 1fr)); margin-bottom: 2.5rem; }
.podio__puesto {
  text-align: center;
  padding: calc(1.75rem * var(--bloque-relleno, 1)) calc(1.25rem * var(--bloque-relleno, 1));
  border-radius: var(--radio-m);
  background: var(--pizarra-700);
  border: var(--grosor-borde) solid var(--linea);
}
.podio__puesto[data-lugar="1"] { border-color: var(--lima); }
.podio__lugar { font-family: var(--ui); font-size: .74rem; font-weight: 500; letter-spacing: .18em; text-transform: uppercase; color: var(--lima); }
.podio__votos { font-family: var(--display); font-size: 2.2rem; font-weight: var(--peso-titulo); color: var(--blanco); line-height: 1.1; margin-top: .5rem; }

.tabla { width: 100%; border-collapse: collapse; font-size: .93rem; }
.tabla th, .tabla td { padding: .8rem .7rem; text-align: left; border-bottom: var(--grosor-borde) solid var(--linea); }
.tabla th { font-family: var(--ui); font-size: .74rem; font-weight: 500; letter-spacing: .12em; text-transform: uppercase; color: var(--texto-3); }
.tabla tbody tr:hover { background: rgb(255 255 255 / .03); }
.tabla-envoltura { overflow-x: auto; }

/* -------------------------------------------------------------------- pie */

.pie {
  margin-top: auto;
  background: var(--pizarra-900);
  border-top: var(--grosor-borde) solid var(--linea);
  padding: clamp(2.5rem, 5vw, 4rem) 0 2rem;
  font-size: .92rem;
  color: var(--texto-2);
}
.pie__grid { display: grid; gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(min(215px, 100%), 1fr)); }
.pie__titulo {
  font-family: var(--ui);
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--texto-3);
  margin-bottom: .8rem;
}
.pie a { color: var(--texto); text-decoration: none; }
.pie a:hover { color: var(--lima); }
.pie__legal { margin-top: 2.5rem; padding-top: 1.5rem; border-top: var(--grosor-borde) solid var(--linea); font-size: .82rem; color: var(--texto-3); }

/* ----------------------------------------------------------- utilidades */

.fila { display: flex; gap: .7rem; flex-wrap: wrap; align-items: center; }
.fila--centrada { justify-content: center; }
.apilado { display: grid; gap: 1rem; }
.texto-suave { color: var(--texto-2); }
.texto-pequeno { font-size: .86rem; }
.mt-0 { margin-top: 0; } .mb-0 { margin-bottom: 0; }
.mt-2 { margin-top: 1.5rem; } .mt-3 { margin-top: 2.25rem; }
.mb-2 { margin-bottom: 1.5rem; }

.cuenta-regresiva { display: inline-flex; gap: .4rem; font-family: var(--ui); font-variant-numeric: tabular-nums; color: var(--blanco); }
.cuenta-regresiva b { font-weight: 500; }

.icono { width: 1em; height: 1em; flex: none; }

/* ------------------------------------------------- respeto al usuario */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .participante:hover { transform: none; }
}

/* ---------------------------------------------- áreas táctiles en móvil */

/* En pantallas sin cursor preciso, todo control se lleva a 44 px de alto.
   Los enlaces dentro de un párrafo quedan fuera a propósito: agrandarlos
   rompería el ritmo del texto, y ahí el dedo apunta a la palabra, no al borde. */
@media (hover: none), (max-width: 640px) {
  .nav a,
  .voto-elegido__cambiar,
  .buscador__limpiar,
  .selector-modo button,
  .chip,
  .etapa-boton,
  .jurado-paso,
  .teatro__pie .boton {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }

  .etapa-boton { display: grid; align-content: center; }

  .buscador__limpiar { width: 44px; }

  .marca { padding-block: .6rem; }

  /* Las casillas de verificación se dibujan a 16 px por defecto, que con el
     pulgar es un blanco muy chico. La etiqueta entera ya es pulsable, pero la
     casilla tiene que verse lo bastante grande como para que se note que lo es. */
  .acepto input[type="checkbox"],
  .campo input[type="checkbox"] {
    width: 24px;
    height: 24px;
    flex: none;
  }
  .acepto {
    min-height: 44px;
    align-items: center;
  }

  /* El panel de voto se lee y se opera con el pulgar: más aire abajo. */
  .panel-voto__interior { padding-bottom: 2.25rem; }
}

/* ===========================================================================
   Piezas que administra el panel de apariencia
   =========================================================================== */

/* --- iconos subidos como PNG ------------------------------------------

   Un icono del repertorio es SVG y hereda el color del texto que lo rodea;
   un PNG trae sus propios colores y no hay forma de teñirlo. Por eso ocupa
   algo más de sitio: sin el color de acento que lo destaque necesita tamaño
   para leerse igual de rápido. `object-fit: contain` es lo que garantiza que
   un logo apaisado no salga estirado dentro de una caja cuadrada. */

img.icono--png {
  width: 1.35em;
  height: 1.35em;
  object-fit: contain;
  flex: none;
}
.galardon__icono.icono--png,
.punto__marca.icono--png { width: 100%; height: 100%; }

/* --- imagen de fondo ---------------------------------------------------

   Va en su propia capa fija por debajo de todo (z-index -2, uno más atrás que
   el halo) y no como fondo del <body> por dos razones: el desenfoque se puede
   aplicar aquí sin arrastrar el contenido, y el velo que la oscurece es un
   pseudoelemento que se puede regular sin repintar la foto.

   La regla de `background-image` no está aquí sino en el bloque que genera
   Services\Estilos, porque depende del ancho de la pantalla y de qué imágenes
   haya subido el administrador. */

.fondo-foto {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: -2;
  pointer-events: none;
  background-color: var(--pizarra-800);

  /* Alto FIJO al del viewport grande, no `inset: 0`.
     En un celular la barra de direcciones se esconde al bajar y reaparece al
     subir, y con eso cambia el alto de la ventana. Con `inset: 0` la capa
     seguía ese vaivén, y como la imagen se ajusta con `cover`, se reescalaba
     en cada cambio: el fondo «daba un salto» al llegar al final de la página y
     otro al volver a subir. Anclándola al alto máximo, la imagen se calcula una
     vez y ya no se mueve; lo que asoma o se esconde es la barra, no el dibujo.
     `lvh` es exactamente esa medida —el viewport con la barra retraída— y
     `vh` queda de reserva para navegadores que aún no la entiendan. */
  height: 100vh;
  height: 100lvh;
}
.fondo-foto::after {
  content: "";
  position: absolute;
  inset: 0;
  /* El valor real lo pone el panel; este es el mínimo que evita que un
     descuido deje la portada ilegible sobre una foto clara. */
  background: color-mix(in srgb, var(--pizarra-800) 55%, transparent);
}

/* --- mascota 3D --------------------------------------------------------

   El recuadro existe siempre que haya modelo; el lienzo lo crea el módulo
   sólo si el navegador puede dibujar en 3D. Mientras carga no se ve nada:
   un adorno que aparece tarde es mejor que un cuadro vacío desde el principio.

   No captura el puntero. El modo «mira hacia el mouse» escucha el movimiento
   en el documento, así que la mascota puede reaccionar sin robarle un clic al
   contenido que tenga debajo. */

.mascota {
  position: fixed;
  z-index: 40;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--lento) var(--curva);
  /* El tamaño y la separación los pone el panel. */
  width: 150px;
  height: 150px;
  left: 18px;
  bottom: 18px;
}
.mascota[data-listo] { opacity: 1; }
.mascota canvas { width: 100%; height: 100%; display: block; }

/* En pantallas bajas y apaisadas —un celular de lado— la esquina inferior es
   justo donde queda el contenido. Se aparta en vez de taparlo. */
@media (max-height: 520px) {
  .mascota { display: none; }
}

/* ===========================================================================
   Reproductor, teatro y panel del jurado
   =========================================================================== */

/* --- el reproductor, compartido ----------------------------------------

   La caja mantiene su forma 16:9 desde el primer píxel, con la miniatura de
   telón. Si en vez de eso creciera al montar el video, la página daría un
   salto justo cuando alguien acaba de pulsar algo, que es el peor momento.

   La variable --cartel la pone JavaScript con la ruta de la miniatura. */

.reproductor {
  position: relative;
  aspect-ratio: 16 / 9;
  width: 100%;
  overflow: hidden;
  border-radius: var(--radio-l);
  border: var(--grosor-borde) solid var(--linea-viva);
  background: #000 var(--cartel, none) center / cover no-repeat;
}
.reproductor__marco { position: absolute; inset: 0; }
.reproductor__marco-drive,
.reproductor__video {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
  background: #000;
}
.reproductor__video { object-fit: contain; }

/* Un video grabado con el celular es VERTICAL, y metido en una caja 16:9 se ve
   como una tira estrecha entre dos franjas negras — que es exactamente lo que
   se reportó de la muestra de payas.

   Aquí manda el ALTO: el ancho se calcula a partir de él para que el 9/16 quepa
   entero sin salirse por abajo. Al revés —ancho del 100 % y `max-height`— el
   navegador recorta la altura y deja de respetar la proporción, con lo que la
   caja vuelve a quedar más ancha que alta.

   `--alto-video` la pone quien usa la caja, porque no es la misma decisión
   dentro de una franja de la portada que en una capa a pantalla completa. Va
   declarada dos veces a propósito: `svh` es la medida correcta en un celular
   —la ventana con la barra de direcciones a la vista— y un navegador que no la
   conozca se queda con la de `vh`, en vez de perder la declaración entera. */
.reproductor--vertical {
  aspect-ratio: 9 / 16;
  width: min(100%, calc(var(--alto-video, 60vh) * 9 / 16));
  margin-inline: auto;
}

/* El menú del reproductor es de Drive, y a Drive hay que darle SITIO.

   Vive dentro de un marco de otro dominio, así que desde aquí no se le puede
   cambiar ni un color ni esconderle un botón: la política del navegador lo
   impide, y es la misma razón por la que tampoco se le puede dar a reproducir.
   Lo único que se controla desde fuera es cuánto espacio tiene para maquetar.

   Y ahí estaba el problema. Un video vertical mide unos 250 px de ancho, y en
   250 px la barra de Drive no cabe: amontona los botones encima del video y le
   sale una barra de desplazamiento propia —se ve en la captura, al pie—. Se le
   da un marco más ancho del que se va a ver y se encoge con `transform`, así
   que Drive maqueta con holgura y el resultado ocupa exactamente la misma caja
   de siempre.

   El factor es un término medio a propósito. Más chico afina más la barra y
   deja los botones difíciles de acertar con el dedo; más grande los deja
   cómodos y vuelve a amontonarlos. Está en una variable para poder moverlo sin
   volver a deducir la cuenta.

   El origen va arriba a la izquierda para que lo que sobra caiga hacia dentro
   de la caja, que ya recorta con `overflow: hidden`. */
.reproductor--vertical .reproductor__marco-drive {
  --escala-drive: .625;
  width: calc(100% / var(--escala-drive));
  height: calc(100% / var(--escala-drive));
  transform: scale(var(--escala-drive));
  transform-origin: top left;
}

/* El botón de arranque tapa toda la caja: en un celular, apuntar a un círculo
   de 60 px es más difícil que tocar donde sea. */
.reproductor__arranque {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  gap: .7rem;
  justify-items: center;
  appearance: none;
  border: 0;
  cursor: pointer;
  color: var(--blanco);
  font-family: var(--ui);
  font-size: .88rem;
  letter-spacing: .04em;
  /* Un velo oscuro sobre la miniatura: sin él, el botón desaparece encima de
     una foto clara. */
  background: linear-gradient(to top, rgb(0 0 0 / .55), rgb(0 0 0 / .25));
  transition: background var(--normal) var(--curva);
}
.reproductor__arranque:hover { background: linear-gradient(to top, rgb(0 0 0 / .4), rgb(0 0 0 / .12)); }
.reproductor[data-estado="abierto"] .reproductor__arranque { display: none; }

.reproductor__arranque-circulo {
  display: grid;
  place-items: center;
  width: 68px; height: 68px;
  border-radius: 50%;
  background: var(--lima);
  color: var(--sobre-lima);
  transition: transform var(--normal) var(--resorte);
}
.reproductor__arranque-circulo svg { width: 26px; height: 26px; margin-left: 3px; }
.reproductor__arranque:hover .reproductor__arranque-circulo { transform: scale(1.07); }

.reproductor__falta {
  display: grid;
  place-items: center;
  height: 100%;
  padding: 1.5rem;
  text-align: center;
  color: var(--texto-2);
  font-size: .92rem;
}

/* --- la muestra de payas de la portada ----------------------------------

   Una rejilla de tarjetas de video, cada una con su reproductor. Las columnas
   las decide el ancho disponible y no un número fijo: con cuatro payas
   destacadas en un monitor salen cuatro en fila, y con cinco se reparten en
   dos filas sin dejar ninguna huérfana ocupando el ancho entero.

   El mínimo es 260 px porque por debajo de eso el nombre de una persona con
   dos apellidos se parte en tres renglones y las tarjetas de la fila dejan de
   medir lo mismo. */

.payas-muestra {
  display: grid;
  gap: calc(var(--gap-rejilla) * var(--bloque-separacion, 1));
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
}

/* Cada paya es un BOTÓN que abre el video encima de la página. Se estilan a
   mano las propiedades que un botón trae de fábrica —fondo, borde, alineación—
   porque heredarlas dejaría una tarjeta con aspecto de control de formulario. */
.paya-tarjeta {
  display: grid;
  gap: .55rem;
  align-content: start;
  min-width: 0;
  /* Es una CAJA de verdad —recibe la sombra y el resalte que se ajustan desde
     el editor— así que necesita su redondeo. Sin él, esos efectos se dibujan
     como un rectángulo de ángulos rectos alrededor. */
  border-radius: var(--radio-m);
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
}

/* La miniatura, con su proporción fija desde el primer píxel. Sin ella la
   rejilla daría un salto al cargar las imágenes. */
.paya-tarjeta__medio {
  position: relative;
  display: block;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border-radius: var(--radio-m);
  border: var(--grosor-borde) solid var(--linea-viva);
  background: var(--pizarra-900);
}
.paya-tarjeta__medio img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform var(--lento) var(--curva);
}
.paya-tarjeta:hover .paya-tarjeta__medio img,
.paya-tarjeta:focus-visible .paya-tarjeta__medio img { transform: scale(1.05); }

/* El botón de reproducir va SIEMPRE visible, no sólo al pasar por encima: en
   una pantalla táctil no existe «pasar por encima», y sin él una miniatura no
   se distingue de una foto cualquiera. */
.paya-tarjeta__play {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  background: linear-gradient(to top, rgb(0 0 0 / .5), rgb(0 0 0 / .12));
}
.paya-tarjeta__play svg {
  width: 54px;
  height: 54px;
  padding: 15px;
  border-radius: 50%;
  background: var(--lima);
  color: var(--sobre-lima);
  transition: transform var(--normal) var(--resorte);
}
.paya-tarjeta:hover .paya-tarjeta__play svg,
.paya-tarjeta:focus-visible .paya-tarjeta__play svg { transform: scale(1.08); }

.paya-tarjeta__pie {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: .5rem .7rem;
  font-family: var(--ui);
  font-size: .78rem;
  color: var(--blanco);
  text-align: center;
  background: linear-gradient(to top, rgb(0 0 0 / .6), transparent);
}

.paya-tarjeta__nombre {
  font-family: var(--display);
  font-size: 1.02rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--blanco);
  overflow-wrap: anywhere;
}
.paya-tarjeta__autor {
  font-size: .86rem;
  color: var(--texto-2);
  overflow-wrap: anywhere;
}

/* El nombre va CENTRADO bajo su miniatura, no pegado a la izquierda: la
   miniatura ocupa el ancho de la tarjeta y un nombre corto a un lado deja la
   fila descuadrada.

   Se escribe con la reserva del `var()` y no como valor fijo. La alineación es
   uno de los controles del editor, y llega heredada desde el bloque: un
   `text-align: center` a secas ganaría a lo heredado y dejaría muerto el
   control para estas dos líneas. Así, sin tocar nada manda el centro, y en
   cuanto alguien elija una alineación manda la suya. */
.paya-tarjeta__nombre,
.paya-tarjeta__autor { text-align: var(--bloque-alineacion, center); }

/* --- el video de la sección del jurado -----------------------------------

   Un hueco opcional: sin enlace puesto la plantilla no pinta nada, así que esta
   regla no tiene sobre qué actuar y la sección queda exactamente como estaba.

   El alto va en píxeles y no en parte de la pantalla porque esto vive DENTRO de
   la página, no encima: una caja que midiera media ventana movería de sitio a
   todo lo que tiene debajo según el aparato desde el que se mire. */
.equipo-video {
  --alto-video: 520px;
  margin-bottom: clamp(2rem, 4vw, 3rem);
}

/* --- teatro de la galería pública -------------------------------------- */

.teatro {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  padding: clamp(.75rem, 3vw, 2rem);

  /* Cuánto ocupa el marco del teatro además del video: el título, los botones
     de abajo, los huecos y los rellenos. De aquí sale el alto que le queda al
     video, y es distinto en los dos: el de la portada tiene dos botones y el de
     la votación tres, con el de votar ocupando su propia fila en un celular. */
  --hueco-teatro: 260px;
}
.teatro--votacion { --hueco-teatro: 340px; }
/* Lo de atrás se DIFUMINA, no se tapa.

   El velo estaba casi opaco —.82— y con eso el desenfoque no se veía: la capa
   se leía como un fondo negro, o sea como haber cambiado de página. Que la
   portada siga ahí, borrosa, es lo que dice que el video está ENCIMA de ella y
   que cerrarlo devuelve al mismo sitio.

   Se cambian las dos cosas a la vez porque van juntas: bajar el velo sin subir
   el desenfoque deja el texto de atrás legible compitiendo con el de delante.
   Y va con el prefijo de Safari, que es donde más se usa esto. */
.teatro__fondo {
  position: absolute;
  inset: 0;
  background: rgb(15 19 22 / .5);
  -webkit-backdrop-filter: blur(16px) saturate(1.1);
  backdrop-filter: blur(16px) saturate(1.1);
}
/* Los DOS teatros enseñan videos verticales, así que la caja es estrecha: con
   los 940 px que tenía, el video quedaba en una columna central rodeada de
   vacío. */
.teatro__caja {
  position: relative;
  width: min(100%, 460px);
  max-height: 100%;
  overflow-y: auto;
  display: grid;
  gap: 1rem;
  padding: clamp(1rem, 3vw, 1.6rem);
  border-radius: var(--radio-xl);
  border: var(--grosor-borde) solid var(--linea-viva);
  background: var(--pizarra-800);
}
.teatro__cabecera {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
}
.teatro__nombre {
  font-size: clamp(1.25rem, 1rem + 1.2vw, 1.7rem);
  font-weight: var(--peso-titulo);
  margin: 0 0 .3rem;
}
.teatro__pie {
  display: flex;
  flex-wrap: wrap;
  gap: .6rem;
  align-items: center;
  justify-content: space-between;
}
/* El botón de votar manda: en móvil ocupa la fila entera y los de navegación
   se reparten la de abajo. */
.teatro__pie .boton--grande { order: -1; flex: 1 1 100%; }

@media (min-width: 720px) {
  .teatro__pie .boton--grande { order: 0; flex: 0 0 auto; }
}

/* Mientras el teatro está abierto, la página de atrás no se desplaza: si lo
   hiciera, al cerrar aparecería en otro punto de la galería. */
body[data-teatro] { overflow: hidden; }

/* --- el teatro de la portada, que enseña videos verticales ---------------

   Es el mismo componente y con dos diferencias, las dos por lo mismo: aquí el
   video es vertical. La caja es estrecha —con los 940 px del de la galería el
   video quedaría en una columna central rodeada de vacío— y el reproductor
   calcula su ancho a partir de la altura de la ventana, para que el 9/16 quepa
   entero junto con el título y los botones de moverse.

   El 62 % deja sitio para la cabecera y el pie sin que la caja llegue a
   necesitar su propia barra de desplazamiento. */
/* El alto del video es el 62 % de la ventana Y ADEMÁS lo que quede después del
   título y de los botones. Los dos límites hacen falta.

   Con sólo el porcentaje, en una ventana baja —un portátil, o un celular de
   lado— ese 62 % más lo que ocupa el marco no cabe, y la caja no se limita a
   asomar: como el alto del reproductor lo fija su proporción y no su fila, se
   DIBUJA ENCIMA de los botones. Medido: en una ventana de 455 px el video
   tapaba 45 px del pie.

   El `max()` es el suelo. Sin él, en una ventana ridículamente baja el segundo
   límite se vuelve negativo y la caja desaparece. */
.teatro .reproductor--vertical {
  --alto-video: max(160px, min(62vh, 100vh - var(--hueco-teatro)));
  --alto-video: max(160px, min(62svh, 100svh - var(--hueco-teatro)));
}

/* --- barra del panel del jurado ---------------------------------------- */

.jurado-cuerpo { background: var(--pizarra-800); }

.jurado-barra {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  padding: .8rem var(--canal);
  background: var(--pizarra-900);
  border-bottom: var(--grosor-borde) solid var(--linea);
}
.jurado-barra__marca { display: flex; align-items: center; gap: .6rem; }
.jurado-barra__anillo {
  width: 20px; height: 20px;
  border-radius: 50%;
  border: 2px solid var(--lima);
  flex: none;
}
.jurado-barra__titulo {
  font-family: var(--display);
  font-size: 1.02rem;
  font-weight: 500;
  color: var(--blanco);
}
.jurado-barra__cuenta {
  display: flex;
  align-items: center;
  gap: .8rem;
  margin-left: auto;
}
.jurado-barra__nombre { font-family: var(--ui); font-size: .85rem; color: var(--texto-2); }

.jurado-avance { display: grid; gap: .3rem; min-width: 180px; flex: 1 1 180px; }
.jurado-avance__pista {
  height: 6px;
  border-radius: 999px;
  background: rgb(255 255 255 / .12);
  overflow: hidden;
}
.jurado-avance__relleno {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 999px;
  background: var(--lima);
  transition: width var(--lento) var(--curva);
}
.jurado-avance__texto {
  font-family: var(--ui);
  font-size: .76rem;
  color: var(--texto-3);
  font-variant-numeric: tabular-nums;
}

/* --- taller de calificación --------------------------------------------- */

.jurado-principal { padding-bottom: 2rem; }

.jurado-taller {
  display: grid;
  gap: clamp(1rem, 2.5vw, 1.6rem);
  padding: clamp(1rem, 3vw, 1.75rem) var(--canal);
  max-width: var(--ancho);
  margin-inline: auto;
  grid-template-areas:
    "escena"
    "notas"
    "resumen"
    "tira";
}
/* `min-width: 0` en los tres no es un adorno: un elemento de rejilla se niega
   por defecto a encogerse por debajo de su contenido, y la tira de payas es una
   fila de seis tarjetas de 148 px. Sin esto, esa fila estiraba TODA la pantalla
   a novecientos y pico píxeles en un celular, y el desbordamiento se veía en el
   panel entero, no sólo en la tira. */
.jurado-escena { grid-area: escena; display: grid; gap: .9rem; align-content: start; min-width: 0; }

/* El video del panel de evaluación va en VERTICAL, que es como se graba una
   paya. El alto se acota contra la ventana y con un tope en píxeles: sin el
   tope, en un monitor alto la caja crecería hasta dejar las notas fuera de
   pantalla, y en esta pantalla el video y las notas se miran a la vez — es toda
   la razón de que estén lado a lado. */
.jurado-escena .reproductor {
  --alto-video: min(58vh, 560px);
  --alto-video: min(58svh, 560px);
}
.jurado-notas   { grid-area: notas; min-width: 0; }
.jurado-resumen { grid-area: resumen; min-width: 0; }
.jurado-tira    { grid-area: tira; min-width: 0; }

/* En pantalla ancha el video y las notas van lado a lado: mirar hacia abajo
   entre cada nota y el video es justo lo que cansa después de veinte payas. */
@media (min-width: 1000px) {
  .jurado-taller {
    grid-template-columns: minmax(0, 1.55fr) minmax(320px, 1fr);
    grid-template-areas:
      "escena  notas"
      "resumen resumen"
      "tira    tira";
  }
}

.jurado-ficha {
  display: flex;
  align-items: center;
  gap: .8rem;
}
.jurado-ficha__centro { flex: 1; min-width: 0; text-align: center; }
.jurado-ficha__posicion {
  font-family: var(--ui);
  font-size: .74rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--texto-3);
  margin: 0 0 .2rem;
}
.jurado-ficha__nombre {
  font-size: clamp(1.3rem, 1rem + 1.4vw, 1.9rem);
  font-weight: var(--peso-titulo);
  margin: 0 0 .35rem;
  line-height: 1.15;
}
.jurado-paso {
  appearance: none;
  flex: none;
  width: 48px; height: 48px;
  border-radius: 50%;
  border: var(--grosor-borde) solid var(--linea-viva);
  background: transparent;
  color: var(--texto);
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
  transition: border-color var(--rapido) var(--curva), color var(--rapido) var(--curva);
}
.jurado-paso:hover { border-color: var(--lima); color: var(--lima); }

/* --- las notas ---------------------------------------------------------- */

.jurado-notas {
  padding: clamp(1.1rem, 2.5vw, 1.6rem);
  border-radius: var(--radio-l);
  border: var(--grosor-borde) solid var(--linea);
  background: var(--pizarra-700);
  box-shadow: var(--sombra);
  align-self: start;
}
.jurado-notas__cabecera {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
}
.jurado-notas__cabecera h2 { font-size: 1.05rem; font-weight: 600; margin: 0; }

.jurado-guardado {
  font-family: var(--ui);
  font-size: .76rem;
  color: var(--texto-3);
  transition: color var(--rapido) var(--curva);
}
.jurado-guardado[data-estado="guardado"] { color: var(--exito); }
.jurado-guardado[data-estado="error"] { color: var(--error); }

/* `min-width: 0` en los hijos, otra vez. Un elemento de rejilla se niega por
   defecto a encogerse por debajo de su contenido, y el contenido de cada ítem
   es la fila de cinco notas: sin esto, la caja de la nota se hace más ancha que
   el panel que la contiene y se sale por la derecha. */
.jurado-items { display: grid; gap: 1rem; margin-top: 1rem; }
.jurado-items > * { min-width: 0; }

.jurado-item {
  margin: 0;
  padding: .9rem;
  border: var(--grosor-borde) solid var(--linea);
  border-radius: var(--radio-m);
  background: rgb(0 0 0 / .14);
  transition: border-color var(--normal) var(--curva);
}
/* Un ítem ya puntuado se marca en el borde, no con un icono: se ve de reojo
   cuáles faltan sin tener que leer nada. */
.jurado-item[data-puesta="1"] { border-color: color-mix(in srgb, var(--lima) 45%, transparent); }
.jurado-item__nombre {
  padding: 0;
  font-family: var(--display);
  font-size: .98rem;
  font-weight: 600;
  color: var(--blanco);
}
.jurado-item__texto { margin: .3rem 0 .7rem; font-size: .83rem; color: var(--texto-2); }

/* `minmax(0, 1fr)` y no `1fr` a secas.
   
   `1fr` significa «reparte el sobrante, pero nunca por debajo del contenido», y
   el contenido de cada columna es un rótulo como «Cumplimiento destacado»: la
   palabra más larga fija un ancho mínimo que el navegador respeta AUNQUE NO
   QUEPA, y entonces la fila entera se sale de su caja.
   
   Eso pasó de verdad: subir el rótulo de 9,6 px a 11,2 px —porque 9,6 px era
   ilegible— ensanchó «Cumplimiento» lo justo para reventar el panel del jurado.
   Con `minmax(0, …)` las columnas se encogen y el rótulo parte la línea, que es
   lo que debía pasar desde el principio: así la maqueta deja de depender del
   largo exacto de una palabra al tamaño exacto de una letra. */
.escala {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: .45rem;
}
.escala__opcion {
  position: relative;
  display: grid;
  gap: .15rem;
  justify-items: center;
  padding: .6rem .3rem;
  border-radius: var(--radio-s);
  border: var(--grosor-borde) solid var(--linea-viva);
  background: transparent;
  cursor: pointer;
  /* Alto generoso a propósito: es un control que se usa con el pulgar veinte
     veces seguidas, muchas veces desde un celular. */
  min-height: 58px;
  transition: border-color var(--rapido) var(--curva), background var(--rapido) var(--curva);
}
.escala__opcion input { position: absolute; opacity: 0; pointer-events: none; }
.escala__numero {
  font-family: var(--display);
  font-size: 1.3rem;
  font-weight: var(--peso-titulo);
  line-height: 1;
  color: var(--texto);
}
.escala__rotulo {
  font-family: var(--ui);
  /* Una palabra larga en una columna estrecha se parte en vez de empujar. */
  overflow-wrap: anywhere;
  font-size: .72rem;
  color: var(--texto-3);
  text-align: center;
  line-height: 1.2;
}
.escala__opcion:hover { border-color: var(--pizarra-600); }
.escala__opcion:has(input:checked) {
  border-color: var(--lima);
  background: color-mix(in srgb, var(--lima) 14%, transparent);
}
.escala__opcion:has(input:checked) .escala__numero { color: var(--lima); }
.escala__opcion:has(input:focus-visible) { outline: 2px solid var(--lima); outline-offset: 2px; }
.escala__opcion:has(input:disabled) { opacity: .5; cursor: not-allowed; }

.jurado-acciones { display: grid; gap: .7rem; margin-top: 1.2rem; }
.jurado-acciones kbd {
  display: inline-block;
  padding: .05em .4em;
  border-radius: 4px;
  border: 1px solid var(--linea-viva);
  background: rgb(0 0 0 / .25);
  font-family: var(--mono);
  font-size: .82em;
}

.jurado-listo {
  margin-top: 1.2rem;
  padding: 1.1rem;
  border-radius: var(--radio-m);
  border: var(--grosor-borde) solid color-mix(in srgb, var(--lima) 45%, transparent);
  background: color-mix(in srgb, var(--lima) 10%, transparent);
  text-align: center;
}
.jurado-listo__icono { width: 30px; height: 30px; color: var(--lima); margin: 0 auto .5rem; }
.jurado-listo__titulo { font-family: var(--display); font-weight: 600; color: var(--blanco); margin: 0 0 .3rem; }

/* --- la tira de abajo ---------------------------------------------------- */

.jurado-tira__pista {
  display: flex;
  gap: .6rem;
  overflow-x: auto;
  padding: .3rem .1rem 1rem;
  scroll-snap-type: x proximity;
  scrollbar-width: thin;
}
.tira-pieza {
  scroll-snap-align: center;
  flex: none;
  width: 148px;
  display: grid;
  gap: .35rem;
  padding: 0;
  appearance: none;
  border: 0;
  background: none;
  cursor: pointer;
  text-align: left;
}
.tira-pieza__medio {
  position: relative;
  display: block;
  aspect-ratio: 16 / 10;
  border-radius: var(--radio-s);
  overflow: hidden;
  border: 2px solid transparent;
  background: var(--pizarra-700);
  transition: border-color var(--rapido) var(--curva);
}
.tira-pieza__medio img { width: 100%; height: 100%; object-fit: cover; }
.tira-pieza__sin-imagen { display: grid; place-items: center; height: 100%; color: var(--texto-3); }
.tira-pieza__sin-imagen svg { width: 22px; height: 22px; }
.tira-pieza[aria-selected="true"] .tira-pieza__medio { border-color: var(--lima); }

.tira-pieza__visto {
  position: absolute;
  top: 5px; right: 5px;
  display: grid;
  place-items: center;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: var(--lima);
  color: var(--sobre-lima);
  opacity: 0;
  transform: scale(.6);
  transition: opacity var(--normal) var(--curva), transform var(--normal) var(--resorte);
}
.tira-pieza__visto svg { width: 13px; height: 13px; }
.tira-pieza[data-completo="1"] .tira-pieza__visto { opacity: 1; transform: scale(1); }
/* Lo ya calificado se atenúa: lo que queda por hacer resalta solo. */
.tira-pieza[data-completo="1"] .tira-pieza__medio img { opacity: .55; }

.tira-pieza__nombre {
  font-family: var(--ui);
  font-size: .76rem;
  color: var(--texto-2);
  line-height: 1.25;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.tira-pieza[aria-selected="true"] .tira-pieza__nombre { color: var(--blanco); }

.jurado-vacio {
  max-width: 46ch;
  margin: clamp(3rem, 10vw, 6rem) auto;
  text-align: center;
  color: var(--texto-2);
}
.jurado-vacio__icono { width: 34px; height: 34px; color: var(--texto-3); margin: 0 auto 1rem; }

/* --- Evaluación: piezas del panel del evaluador ------------------------- */

/* La ronda que le toca al evaluador, junto al título de su panel. */
.jurado-barra__ronda {
  padding: .15rem .55rem;
  border-radius: 999px;
  border: 1px solid var(--linea-viva);
  font-family: var(--ui);
  font-size: .7rem;
  letter-spacing: .04em;
  color: var(--texto-3);
  white-space: nowrap;
}

/* El criterio que filtra se marca: no suma puntos, decide si la paya sigue, y
   quien evalúa tiene que saberlo antes de poner el número. */
.jurado-item[data-filtra="1"] { border-color: color-mix(in srgb, var(--alerta) 45%, transparent); }
.jurado-item__marca {
  display: inline-block;
  margin-left: .4rem;
  padding: .1rem .5rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--alerta) 22%, transparent);
  font-family: var(--ui);
  /* Sube de .62rem: es el rótulo que avisa de que este número no suma, decide.
     A diez píxeles no se lee de reojo, que es como se lee mientras se evalúa. */
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--alerta);
  vertical-align: middle;
}

/* Cinco opciones no caben con el mismo aire que tres: los rótulos se ocultan y
   quedan como título emergente, y el número manda. En pantalla ancha vuelven. */
.escala--cinco { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: .3rem; }
.escala--cinco .escala__opcion { padding: .55rem .15rem; min-height: 52px; }
.escala--cinco .escala__rotulo { display: none; }

@media (min-width: 1240px) {
  .escala--cinco .escala__rotulo {
    display: block;
    /* Estaba en .6rem, o sea 9,6 px. Es el rótulo que un evaluador mira
       durante horas seguidas para decidir una nota: es el último texto del
       sitio que debería quedar por debajo del mínimo legible. */
    font-size: .7rem;
    line-height: 1.15;
  }
  .escala--cinco .escala__opcion { min-height: 66px; }
}

/* --- selector de etapas de la preselección -------------------------------

   Dos botones grandes y con el pendiente a la vista. Un desplegable habría
   ocupado menos, pero aquí lo que importa es ver de un vistazo cuánto falta en
   la etapa en la que NO se está: es el dato que decide cuándo saltar. */

.etapas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
  gap: .6rem;
  max-width: var(--ancho);
  margin: 1rem auto 0;
  padding-inline: var(--canal);
}
.etapa-boton {
  display: grid;
  gap: .15rem;
  padding: .8rem 1rem;
  text-align: left;
  appearance: none;
  cursor: pointer;
  border-radius: var(--radio-m);
  border: var(--grosor-borde) solid var(--linea-viva);
  background: var(--pizarra-700);
  color: var(--texto-2);
  transition: border-color var(--rapido) var(--curva), background var(--rapido) var(--curva);
}
.etapa-boton:hover { border-color: var(--pizarra-600); }
.etapa-boton[aria-selected="true"] {
  border-color: var(--lima);
  background: color-mix(in srgb, var(--lima) 12%, var(--pizarra-700));
  color: var(--texto);
}
.etapa-boton__numero {
  font-family: var(--ui);
  font-size: .72rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--texto-3);
}
.etapa-boton[aria-selected="true"] .etapa-boton__numero { color: var(--lima); }
.etapa-boton__nombre {
  font-family: var(--display);
  font-size: .96rem;
  font-weight: 600;
  color: var(--blanco);
  line-height: 1.2;
}
.etapa-boton__faltan {
  font-family: var(--ui);
  font-size: .74rem;
  color: var(--texto-3);
  font-variant-numeric: tabular-nums;
}

/* El aviso de «terminaste esta etapa, te falta la otra». Es un botón entero
   para que el salto sea un toque, no una búsqueda del selector de arriba. */
.jurado-aviso-etapa {
  margin-top: 1rem;
  padding: .9rem 1rem;
  border-radius: var(--radio-m);
  border: var(--grosor-borde) solid color-mix(in srgb, var(--alerta) 45%, transparent);
  background: color-mix(in srgb, var(--alerta) 10%, transparent);
  color: var(--texto);
  font-size: .88rem;
  cursor: pointer;
}
.jurado-aviso-etapa:hover { border-color: var(--alerta); }

.jurado-tira__nota {
  margin: 0 0 .6rem;
  font-family: var(--ui);
  font-size: .78rem;
  color: var(--texto-3);
}

/* Un criterio de otra etapa no se dibuja: `hidden` por sí solo pierde contra
   la especificidad de las reglas de arriba. */

/* --- resumen de puntajes, antes de enviar --------------------------------

   Ocupa el ancho completo y reemplaza al taller: es una pantalla de repaso, y
   mezclarla con la de calificar dejaría el video sin sitio. Se llega por el
   botón de la barra de etapas, y de aquí sale el envío. */

.jurado-resumen {
  grid-column: 1 / -1;
  grid-row: 1 / -1;
  min-width: 0;
  padding: clamp(1.1rem, 2.5vw, 1.6rem);
  border-radius: var(--radio-l);
  border: var(--grosor-borde) solid var(--linea);
  background: var(--pizarra-700);
  box-shadow: var(--sombra);
}

.jurado-resumen__cabecera {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  align-items: flex-end;
  justify-content: space-between;
  margin-bottom: 1rem;
}
.jurado-resumen__orden .entrada { min-width: 220px; }

/* La tabla puede tener doscientas filas: se le da alto máximo y encabezado
   pegado, para no perder de vista qué columna es cuál al bajar. */
.jurado-resumen__caja {
  position: relative;
  overflow: auto;
  max-height: min(60dvh, 640px);
  border-radius: var(--radio-s);
  border: var(--grosor-borde) solid var(--linea);
}
.jurado-resumen__tabla { margin: 0; }
.jurado-resumen__tabla thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--pizarra-900);
  white-space: nowrap;
}
.jurado-resumen__tabla td { vertical-align: middle; }

.resumen-nombre { min-width: 12ch; line-height: 1.3; }
.resumen-nombre .etiqueta-categoria { font-size: .7rem; }

.resumen-nota {
  width: 100%;
  min-width: 62px;
  min-height: 40px;
  padding: .35rem .4rem;
  border-radius: var(--radio-s);
  border: var(--grosor-borde) solid var(--linea-viva);
  background: rgb(0 0 0 / .22);
  color: var(--texto);
  font-family: var(--ui);
  font-size: .95rem;
  text-align: center;
}
.resumen-nota:focus-visible { outline: 2px solid var(--lima); outline-offset: 1px; }

.resumen-total {
  font-family: var(--display);
  font-size: 1.25rem;
  font-weight: var(--peso-titulo);
  color: var(--blanco);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.resumen-total__max { font-size: .72rem; color: var(--texto-3); font-weight: 400; }

/* Una fila sin puntaje completo se marca: es lo que impide enviar, y hay que
   poder encontrarla de un vistazo entre doscientas. */
.jurado-resumen__tabla tr[data-incompleta] { background: color-mix(in srgb, var(--alerta) 9%, transparent); }
.jurado-resumen__tabla tr[data-incompleta] .resumen-total { color: var(--alerta); }

.jurado-resumen__envio {
  margin-top: 1.2rem;
  padding-top: 1.2rem;
  border-top: var(--grosor-borde) solid var(--linea);
  display: grid;
  gap: .6rem;
}
.jurado-resumen__envio [data-error="1"] { color: var(--error); }

.etapa-boton--resumen[aria-selected="true"] {
  border-color: var(--lima);
}

@media (max-width: 640px) {
  .jurado-resumen__cabecera { align-items: stretch; }
  .jurado-resumen__orden .entrada { min-width: 0; width: 100%; }
  .jurado-resumen__caja { max-height: none; }

  /* En un celular la tabla se lee de lado; el encabezado pegado arriba deja de
     tener sentido cuando lo que se desplaza es el ancho. */
  .jurado-resumen__tabla thead th { position: static; }
  .resumen-nota { min-width: 54px; min-height: 44px; }
}

/* ===========================================================================
   Vidrio esmerilado

   Con una ilustración de fondo, el texto suelto sobre ella se pierde: no por
   contraste de color —eso se mide y se cumple— sino porque el ojo tiene que
   separar las letras de las banderitas que pasan por detrás. La solución es
   apoyarlo todo sobre un cristal traslúcido que desenfoca lo de atrás.

   Es una excepción CONSCIENTE a la tercera regla del diseño de Témpora
   («superficies planas, la profundidad viene del cambio de tono»). La regla
   asume un fondo liso; con una ilustración detrás, un plano opaco tapa el
   dibujo y uno transparente no deja leer. El vidrio es lo que permite tener
   las dos cosas. Se apaga entero desde /admin/apariencia y todo vuelve a ser
   plano.

   `--vidrio-fondo`, `--vidrio-desenfoque` y `--vidrio-borde` los emite
   Services\Estilos: siguen a la paleta y al interruptor del panel.
   =========================================================================== */

.vidrio,
.tarjeta,
.punto,
.paso,
.dato,
.galardon,
.podio__puesto,
.seccion__intro,
.hero__texto,
.celebracion,
.sin-resultados {
  /* `--bloque-vidrio` es lo que el editor del sitio deja regular por bloque:
     multiplica a la vez lo que TAPA el cristal y lo que DESENFOCA, porque son
     la misma decisión —«cuánto vidrio»— y separarlas en dos controles obliga a
     entender por qué un cristal muy transparente y muy borroso se ve mal. Sin
     nadie que la ponga vale 1, o sea exactamente lo elegido en Apariencia. */
  background: color-mix(in srgb, var(--vidrio-fondo) calc(var(--bloque-vidrio, 1) * 100%), transparent);
  -webkit-backdrop-filter: blur(calc(var(--vidrio-desenfoque) * var(--bloque-vidrio, 1))) saturate(1.15);
  backdrop-filter: blur(calc(var(--vidrio-desenfoque) * var(--bloque-vidrio, 1))) saturate(1.15);
  border: var(--grosor-borde) solid var(--vidrio-borde);
  border-radius: var(--radio-m);
  /* La del sitio y, encima, la que haya pedido el bloque. Dos capas y no una
     porque son dos decisiones distintas: la general no se pierde al ajustar
     una sección, y ajustar una sección no obliga a repetir la general. */
  box-shadow: var(--sombra), var(--sombra-caja);
}

/* Los bloques que antes eran texto suelto necesitan aire por dentro: hasta
   ahora no tenían caja que rellenar. */
.seccion__intro,
.hero__texto {
  padding: calc(clamp(1.2rem, 3vw, 1.9rem) * var(--pad-tarjeta));
}

/* Las pantallas de cierre —gracias, voto emitido, fase cerrada— son una sola
   frase centrada. Pasan de ocupar el ancho entero a ser una tarjeta. */
.celebracion {
  max-width: 62ch;
  margin-inline: auto;
  padding: clamp(2rem, 6vw, 3.25rem) clamp(1.4rem, 4vw, 2.5rem);
}

.seccion__intro {
  /* Deja de ser una columna estrecha y suelta para ser una caja: el ancho
     máximo se conserva porque una línea de texto muy larga se lee peor. */
  max-width: var(--ancho-texto);
}
.centrado .seccion__intro { margin-inline: auto; }

.hero__texto { border-radius: var(--radio-l); }

/* --- el contorno de neón ---------------------------------------------------

   Pedido explícito: que al pasar por encima de una caja con texto se le encienda
   el contorno. Se aplica a las mismas cajas que llevan cristal, que son
   justamente «las cajas con texto» del sitio.

   Va con `@media (hover: hover)` porque en una pantalla táctil no existe pasar
   por encima: el navegador simula un hover que se queda PEGADO tras el toque, y
   la caja se quedaría encendida hasta que se tocara otra cosa. Ese efecto
   fantasma es peor que no tener el efecto.

   `--neon-borde` y `--neon-halo` los emite Services\Estilos; apagado el efecto
   valen lo que valdría la caja en reposo, así que esta regla se puede dejar
   escrita sin condicionarla. */

@media (hover: hover) and (pointer: fine) {
  .vidrio,
  .tarjeta,
  .punto,
  .paso,
  .dato,
  .galardon,
  .podio__puesto,
  .seccion__intro,
  .hero__texto,
  .celebracion,
  .sin-resultados {
    transition:
      border-color var(--normal) var(--curva),
      box-shadow var(--normal) var(--curva),
      translate var(--normal) var(--curva);
  }

  .vidrio:hover,
  .tarjeta:hover,
  .punto:hover,
  .paso:hover,
  .dato:hover,
  .galardon:hover,
  .podio__puesto:hover,
  .seccion__intro:hover,
  .hero__texto:hover,
  .celebracion:hover,
  .sin-resultados:hover {
    border-color: var(--neon-borde);
    box-shadow: var(--neon-halo);
    translate: 0 calc(-1 * var(--elevar));
  }

  /* Los galardones ya tenían su propio hover, escrito antes y con un
     `transform` que competiría con el `translate` de aquí. Se les quita para
     que mande uno solo. */
  .galardon:hover { transform: none; }
}

/* El halo lima del sitio y el arco de la ilustración quedan DETRÁS del cristal,
   que es donde tienen que estar: el vidrio los difumina en vez de competir. */

/* --- sin soporte de desenfoque -------------------------------------------

   Firefox lo trae desde hace tiempo y Safari e iOS desde antes, pero un
   navegador viejo sin `backdrop-filter` mostraría el texto sobre un cristal
   transparente y sin difuminar, que es justo el problema que esto venía a
   resolver. Ahí se cae a un plano opaco, que se ve peor pero se lee igual. */

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .vidrio,
  .tarjeta,
  .punto,
  .paso,
  .dato,
  .galardon,
  .podio__puesto,
  .seccion__intro,
  .hero__texto,
  .celebracion,
  .sin-resultados {
    background: var(--pizarra-700);
  }
}

/* --- piezas que ya tenían fondo propio ----------------------------------- */

/* La cabecera pegada de la galería y el panel de voto flotan sobre el fondo
   igual que las cajas de texto: si se quedaran opacos, el sitio tendría dos
   lenguajes visuales a la vez. */
.votacion-cabecera,
.panel-voto,
.teatro__caja {
  -webkit-backdrop-filter: blur(calc(var(--vidrio-desenfoque) * var(--bloque-vidrio, 1))) saturate(1.15);
  backdrop-filter: blur(calc(var(--vidrio-desenfoque) * var(--bloque-vidrio, 1))) saturate(1.15);
}
.votacion-cabecera { background: var(--vidrio-fondo); }

/* La tarjeta de un participante lleva imagen dentro: el cristal va sólo en la
   parte del texto, no encima de la miniatura. */
.participante {
  background: color-mix(in srgb, var(--vidrio-fondo) calc(var(--bloque-vidrio, 1) * 100%), transparent);
  box-shadow: var(--sombra), var(--sombra-caja);
}

/* ===========================================================================
   Lo que cada bloque puede ajustar — el editor del sitio

   Un bloque marcado con `data-bloque` puede cambiar su tipografía, sus
   tamaños, la forma de su caja y el aire que la rodea sin tocar el resto del
   sitio. Las variables las emite `Services\Maqueta`, acotadas a ese atributo;
   aquí sólo se declara QUIÉN LAS LEE. Los valores por defecto que aparecen
   como reserva de cada `var()` son los mismos que declara `Disposicion.php`, y
   `bin/pruebas/maqueta.test.php` falla si se separan.

   Todo lo que se multiplica se multiplica sobre lo que ya hay —`--escala-texto`,
   `--escala-titulo`, `--redondeo`— en vez de sustituirlo: así, agrandar un
   bloque no deshace la escala general elegida en Apariencia. Y por eso todos
   los usos llevan reserva: la inmensa mayoría de los elementos del sitio no
   están dentro de ningún bloque, y sin ella quedarían en cero.

   **Dos familias de variables.** Las `--bloque-…` se heredan: lo que se ajusta
   en una sección vale también para las cajas de dentro, salvo que la caja diga
   otra cosa. Las `--dp-…` no: `Maqueta::neutras()` las vuelve a dejar en blanco
   en cada `[data-bloque]`, porque estirar una franja no debe estirar además
   cada tarjeta que lleva dentro.
   =========================================================================== */

/* --- texto e iconos ------------------------------------------------------ */

[data-bloque] {
  font-size: calc(1em * var(--bloque-texto, 1));
  /* La tipografía del bloque, si pidió una. `inherit` de reserva es lo mismo
     que no decir nada, porque `font-family` ya se hereda. */
  font-family: var(--bloque-fuente, inherit);
  text-align: var(--bloque-alineacion, inherit);
}

/* Los títulos llevan la del bloque si la hay y, si no, la de titulares del
   sitio — que es exactamente la regla que había antes de existir el editor. */
[data-bloque] h1,
[data-bloque] h2,
[data-bloque] h3 { font-family: var(--bloque-fuente, var(--display)); }

[data-bloque] h1 { font-size: calc(clamp(2.3rem, 1.5rem + 3.4vw, 4.1rem) * var(--escala-titulo) * var(--bloque-titulo, 1)); }
[data-bloque] h2 { font-size: calc(clamp(1.7rem, 1.25rem + 2vw, 2.75rem) * var(--escala-titulo) * var(--bloque-titulo, 1)); }
[data-bloque] h3 { font-size: calc(1.06rem * var(--bloque-titulo, 1)); }

[data-bloque] .galardon__icono,
[data-bloque] .punto__marca,
[data-bloque] .celebracion__sello {
  width: calc(var(--icono-base, 40px) * var(--bloque-icono, 1));
  height: calc(var(--icono-base, 40px) * var(--bloque-icono, 1));
}
[data-bloque] .galardon__icono { --icono-base: 46px; }
[data-bloque] .punto__marca { --icono-base: 30px; }
[data-bloque].celebracion__sello { --icono-base: 74px; }

[data-bloque] .dato__cifra {
  font-size: calc(clamp(2.1rem, 1.6rem + 2vw, 3rem) * var(--escala-titulo) * var(--bloque-titulo, 1));
}

/* --- la forma de la caja ------------------------------------------------- */

[data-bloque] {
  /* `auto` de reserva en los dos es el valor inicial de la propiedad, así que
     un bloque sin nada puesto se comporta exactamente como antes. */
  width: var(--dp-ancho, auto);
  min-height: var(--dp-alto, auto);
  opacity: var(--dp-opacidad, 1);

  /* Dónde queda la caja cuando mide menos que el ancho completo.

     La reserva es el margen que el elemento tenía ANTES de existir este
     control, y por eso hay dos reglas y no una: casi todos los bloques valían
     cero, y tres de ellos —los contenedores de las pantallas de cierre y de
     resultados, y el sello— venían centrados con `auto`. Escribir una sola
     regla con reserva `0` los habría descentrado sin que nadie tocara nada.

     No se hereda a propósito. Con una variable heredada, achicar una tarjeta
     dentro de un contenedor centrado la centraría también, y ésa es una
     decisión distinta que le toca tomar a quien edita esa tarjeta. */
  margin-inline: var(--dp-margen, 0);

  /* Dónde queda el contenido dentro de la caja, de arriba abajo. `normal` es el
     valor inicial de la propiedad, así que un bloque sin nada puesto se
     comporta igual que antes. Funciona en una caja normal, en una rejilla y en
     una flexible, que es lo que permite ofrecerlo en TODOS los bloques sin
     tener que cambiarle el `display` a ninguno. */
  align-content: var(--dp-alinear-y, normal);

  /* El grosor del borde de ESTA caja. Multiplica el del sitio en vez de
     sustituirlo, así que en 0 la línea desaparece y a 100 queda como el resto.
     Se redeclara la variable en vez de escribir `border-width` para no tener
     que repetir aquí el color y el estilo de cada una de las once reglas que
     dibujan un borde — cada una sigue usando `var(--grosor-borde)` como
     siempre, y aquí vale otra cosa. */
  --grosor-borde: calc(var(--grosor-base) * var(--bloque-borde, 1));

  /* Una palabra larga se PARTE antes que salirse.

     Sin esto, achicar una caja con el tirador hasta que su titular no cabe
     dejaba el texto asomando por fuera del borde, y desde fuera eso se lee como
     «la caja ya no se achica» y «el texto quedó descentrado» — que es como se
     reportó. La caja sí se achicaba; lo que no se achicaba era la palabra. */
  overflow-wrap: break-word;

  /* El redondeo se vuelve a derivar de `--redondeo` para el bloque y todo lo
     que lleve dentro, multiplicado por su curvatura. Las proporciones son las
     mismas que emite Services\Estilos: cambiarlas en un sitio y no en el otro
     haría que una caja dentro de un bloque se redondeara distinto que la misma
     caja fuera de él. */
  --radio-s:  calc(var(--redondeo) * .57  * var(--bloque-curvatura, 1));
  --radio-m:  calc(var(--redondeo) *        var(--bloque-curvatura, 1));
  --radio-l:  calc(var(--redondeo) * 1.43 * var(--bloque-curvatura, 1));
  --radio-xl: calc(var(--redondeo) * 2    * var(--bloque-curvatura, 1));

  /* La sombra que añade ESTE bloque, encima de la del sitio. Se declara aquí y
     no en `:root` por lo mismo que el tinte de abajo: una variable que contiene
     otras se resuelve donde SE DECLARA, y arriba `--bloque-sombra` vale siempre
     0. Estuvo arriba y por eso el control no hacía nada. */
  --sombra-caja: 0 calc(10px * var(--bloque-sombra, 0)) calc(28px * var(--bloque-sombra, 0))
                 rgb(0 0 0 / calc(.45 * var(--bloque-sombra, 0)));

  /* El tinte de resalte. Se declara aquí y no en `:root` porque una variable
     que contiene otras se resuelve donde SE DECLARA: puesta arriba se quedaría
     con el color de la raíz —ninguno— y ningún bloque podría cambiarla.
     Sin color elegido queda transparente, o sea invisible. */
  --bloque-tinte: color-mix(in srgb,
                    var(--dp-resalte, transparent) calc(var(--dp-resalte-alfa, 0.25) * 100%),
                    transparent);

  /* Va como imagen y no como color de fondo para no borrar el fondo que la
     caja ya tuviera: se apoya ENCIMA. Ningún elemento que lleve `data-bloque`
     usa `background-image` para otra cosa. */
  background-image: linear-gradient(var(--bloque-tinte), var(--bloque-tinte));

}

/* La sombra del sitio y, encima, la que haya pedido ese bloque.

   **Sólo en las CAJAS.** Estuvo en `[data-bloque]` a secas —para que el control
   funcionara en un premio y no sólo en las cajas de vidrio— y eso se la dio
   también a las SECCIONES, que nunca habían tenido ninguna. Una `<section>`
   ocupa el ancho de la pantalla, así que su sombra no se ve como una sombra: se
   ve como una raya oscura cruzando la página bajo cada franja, y con el redondeo
   heredado, como un rectángulo alrededor de media portada. Se reportó tal cual y
   con razón: eso antes no estaba.

   `data-caja` lo emite el helper `bloque()` con la misma frontera que usa el
   editor para decidir qué se recuadra: una caja vive DENTRO de otra cosa, una
   franja no. `.lb` es la tarjeta de un bloque creado desde el panel, que hereda
   la variable de su franja y sí es una caja aunque no lleve la marca.

   Y va después de las reglas de clase, así que gana con la misma especificidad
   sin necesidad de `!important`. */
[data-bloque][data-caja],
.lb { box-shadow: var(--sombra), var(--sombra-caja); }

/* Los tres que venían centrados. Van con más especificidad que la regla de
   arriba, así que ganan pase lo que pase con el orden del archivo, y siguen
   admitiendo que el editor los mueva. */
.contenedor[data-bloque],
.celebracion__sello[data-bloque] { margin-inline: var(--dp-margen, auto); }

/* ---------------------------------------------------------------- el jurado

   La tarjeta de una persona: foto redonda arriba y tres líneas debajo, del
   wireframe que entregó la organización. Las cuatro filas van con `subgrid`
   —igual que los premios y por el mismo motivo— para que un nombre de dos
   renglones no baje la descripción de esa tarjeta respecto a las de al lado. */

.rejilla--personas { --tarjeta-min: 210px; }

.persona {
  text-align: center;
  padding: calc(1.5rem * var(--densidad) * var(--pad-tarjeta) * var(--bloque-relleno, 1))
           calc(1.1rem * var(--densidad) * var(--pad-tarjeta) * var(--bloque-relleno, 1));
  border-radius: var(--radio-l);
  background: var(--pizarra-700);
  border: var(--grosor-borde) solid var(--linea);
  box-shadow: var(--sombra);
}

/* La foto se recorta en círculo con `cover`: así una foto vertical y una
   apaisada se ven igual de redondas sin pedirle a nadie que las recorte antes.
   El círculo se dibuja aunque no haya foto, para que las tarjetas sin imagen
   no descoloquen la fila. */
.persona__foto {
  width: min(148px, 62%);
  aspect-ratio: 1;
  margin: 0 auto calc(1rem * var(--bloque-separacion, 1));
  border-radius: 50%;
  overflow: hidden;
  background: var(--pizarra-600, var(--linea));
  border: var(--grosor-borde) solid var(--linea-viva);
}
.persona__foto img { width: 100%; height: 100%; object-fit: cover; display: block; }

.persona__nombre { margin: 0; font-size: calc(1.15rem * var(--bloque-titulo, 1)); }
.persona__desc   { margin: .25rem 0 0; font-size: .92rem; color: var(--texto-2); }
.persona__apodo  {
  margin: .5rem 0 0;
  font-family: var(--ui);
  font-size: .84rem;
  color: var(--texto-3);
}

@supports (grid-template-rows: subgrid) {
  .rejilla--personas { grid-template-rows: auto auto auto auto; }
  .rejilla--personas > .persona {
    display: grid;
    grid-row: span 4;
    grid-template-rows: subgrid;
    align-content: start;
    row-gap: 0;
  }
  /* Con subgrid el margen inferior de la foto lo pone la fila, no el elemento:
     dejarlo duplicaría el hueco. */
  .rejilla--personas > .persona .persona__foto { margin-bottom: 0; }
  .rejilla--personas { row-gap: calc(var(--gap-rejilla) * var(--bloque-separacion, 1)); }
}

/* --- las filas de una rejilla se alinean entre cajas ----------------------

   El fallo: «Categoría Implante Capilar» ocupa dos renglones y «Categoría
   Abierta» uno, así que el premio de la primera quedaba un renglón más abajo
   que el de la segunda. Dos tarjetas iguales que no se leen a la misma altura,
   y no hay forma de arreglarlo escribiendo textos más cortos — la organización
   pone los nombres que quiera.

   `subgrid` es lo que lo resuelve de verdad: las filas las manda la REJILLA, no
   cada tarjeta, así que el icono de todas empieza donde el icono de todas, y el
   premio donde el premio. La alternativa —darle un alto mínimo al título a ojo—
   es adivinar cuántos renglones va a ocupar el texto más largo, y se rompe en
   cuanto alguien escribe uno más.

   Va dentro de `@supports` porque un navegador sin `subgrid` tiene que quedarse
   exactamente como estaba: desalineado, pero entero. */
@supports (grid-template-rows: subgrid) {
  .rejilla:has(> .punto),
  .pasos {
    /* Tres filas: lo de arriba —icono o número—, el título y el cuerpo. */
    grid-template-rows: auto auto auto;
  }
  .rejilla > .punto,
  .pasos > .paso {
    display: grid;
    grid-row: span 3;
    grid-template-rows: subgrid;
    /* El aire entre las filas de dentro lo sigue mandando la caja, no la
       rejilla, o el hueco entre el título y el texto sería el mismo que el
       hueco entre tarjetas. */
    row-gap: .45rem;
    align-content: start;
  }

  /* Los premios van APARTE porque tienen CUATRO filas: icono, rótulo, premio y
     letra chica. Metidos en la regla de tres de arriba, la cuarta no cabía en
     el subgrid y se apilaba encima de la tercera — la letra chica del primer
     premio pintada sobre el premio, en las tres anchuras. Lo cazó la auditoría
     del navegador como «SOLAPADO … se pisan (100 %)»; leyendo el CSS no se ve,
     porque la regla es correcta y lo que estaba mal era cuántos hijos tiene la
     caja que la usa.

     La cuarta fila existe aunque el segundo premio no traiga letra chica: es la
     rejilla la que manda las filas, así que una caja con tres hijos ocupa las
     tres primeras y deja la última vacía. Eso es justamente lo que alinea los
     dos premios entre sí. */
  .galardones { grid-template-rows: auto auto auto auto; }
  .galardones > .galardon {
    display: grid;
    grid-row: span 4;
    grid-template-rows: subgrid;
    row-gap: .3rem;
    align-content: start;
  }
  /* Con subgrid el hueco lo pone la fila: los márgenes propios lo duplicarían. */
  .galardones > .galardon > .galardon__icono { margin-bottom: 0; }
  .galardones > .galardon > .galardon__premio,
  .galardones > .galardon > .galardon__nota { margin-top: 0; }
}

/* --- columnas ------------------------------------------------------------

   Sólo de tablet hacia arriba. En un celular manda siempre el apilado: tres
   columnas en 375 px no son tres columnas, son tres rendijas. La reserva de
   cada una es su propia regla de más arriba, repetida a propósito —es la única
   forma de decir «si nadie pidió columnas, déjalo como estaba»—. */

@media (min-width: 768px) {
  [data-bloque] .rejilla,
  [data-bloque] .pasos,
  [data-bloque] .podio,
  [data-bloque].rejilla,
  [data-bloque].pasos,
  [data-bloque].podio {
    grid-template-columns: var(--bloque-columnas, repeat(auto-fit, minmax(min(var(--tarjeta-min), 100%), 1fr)));
  }

  [data-bloque] .galeria,
  [data-bloque].galeria {
    grid-template-columns: var(--bloque-columnas, repeat(auto-fill, minmax(min(255px, 100%), 1fr)));
  }
}

/* --- el bloque que se está editando -------------------------------------

   Sólo lo pone el editor del sitio desde el panel, sobre la página cargada en
   su vista previa. En el sitio de verdad este atributo no lo escribe nadie, así
   que la regla no puede aparecer donde no toca. */

/* El bloque que se está editando.

   Era `2px dashed` con separación, y en una sección que ocupa el ancho de la
   pantalla eso no se lee como «esto está seleccionado»: se lee como una raya
   horizontal atravesando la página, que fue justo lo que se reportó. Ahora es
   una línea fina y continua, pegada al borde, y quien de verdad dice qué está
   elegido son los tiradores de las esquinas. */
[data-previa-sel] {
  outline: 1px solid color-mix(in srgb, var(--lima) 55%, transparent);
  outline-offset: 0;
}

/* ===========================================================================
   Las franjas que crea la organización — app/Libres.php

   Doce formas y una sola plantilla de PHP: lo que cambia entre «Sólo una
   imagen» y «Imagen a la izquierda» no es la estructura sino qué piezas se
   pintan y cómo se colocan, y de la colocación se encarga esto. Doce plantillas
   serían doce sitios donde arreglar el día que cambie el botón.

   Todo cuelga de `.lb--<forma>`, así que una forma nueva es una regla nueva y
   nada más. Y lo que no lleve regla propia se ve como la de siempre —título,
   texto y botón, uno debajo de otro—, que es el comportamiento correcto para
   algo que todavía no se ha decidido cómo se ve.
   =========================================================================== */

.lb { display: grid; gap: calc(1.2rem * var(--bloque-separacion, 1)); }
.lb__texto { display: grid; gap: .6rem; align-content: start; }
.lb__cuerpo { color: var(--texto-2); margin: 0; }
.lb__accion { margin-top: .4rem; }

/* La imagen llena su hueco sin deformarse. `aspect-ratio` con `cover` es lo que
   permite que dos franjas seguidas con fotos de distinta forma se vean iguales
   —que es justo lo que se espera de una plantilla— sin recortar el archivo al
   subirlo, que sería irreversible. */
.lb__figura { margin: 0; position: relative; }
.lb__figura img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--radio-m);
}

/* Un icono sobre la foto. Lleva su propio disco de fondo porque una foto puede
   ser de cualquier color y un icono suelto encima desaparece en la mitad. */
.lb__sello {
  position: absolute;
  left: 50%;
  bottom: -22px;
  transform: translateX(-50%);
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--pizarra-700);
  border: var(--grosor-borde) solid var(--lima);
  color: var(--lima);
}
.lb__sello .icono { width: 22px; height: 22px; }

/* --- las formas ---------------------------------------------------------- */

.lb--solo-titulo,
.lb--llamado,
.lb--imagen-titulo,
.lb--icono-titulo-texto,
.lb--icono-imagen { text-align: center; }

.lb--solo-titulo .lb__texto,
.lb--llamado .lb__texto { justify-items: center; }

/* El llamado a la acción lleva el acento del sitio, como la caja verde de la
   portada: es el mismo papel y tiene que leerse igual. */
/* El llamado a la acción se marca con el borde de acento, igual que la caja
   verde de la portada: es el mismo papel y tiene que leerse igual. Un fondo
   lima entero rompería la segunda regla del diseño de Témpora —un solo acento,
   y en lo accionable—, que aquí es el botón. */
.lb--llamado { border-color: color-mix(in srgb, var(--lima) 40%, transparent); }

.lb--solo-imagen .lb__texto { display: none; }
.lb--solo-imagen .lb__figura img { aspect-ratio: 21 / 9; }

.lb--imagen-titulo .lb__figura img,
.lb--imagen-arriba .lb__figura img { aspect-ratio: 16 / 9; }

.lb--icono-imagen .lb__figura { margin-bottom: 26px; }
.lb--icono-imagen .lb__figura img { aspect-ratio: 16 / 9; }

/* Las dos de imagen al lado. Se apilan en un celular y no es un ajuste
   cosmético: dos columnas en 375 px son dos rendijas, y la foto quedaría en una
   tira de 150 px con el texto partido palabra a palabra. */
@media (min-width: 720px) {
  .lb--imagen-izquierda,
  .lb--imagen-derecha {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: center;
    gap: calc(1.8rem * var(--bloque-separacion, 1));
  }
  .lb--imagen-derecha .lb__figura { order: 2; }
}
.lb--imagen-izquierda .lb__figura img,
.lb--imagen-derecha .lb__figura img { aspect-ratio: 4 / 3; }

/* La cita: la frase manda y la firma es el pie. */
.lb--cita { text-align: center; }
.lb__cita {
  margin: 0;
  font-family: var(--display);
  font-weight: var(--peso-titulo);
  font-size: calc(clamp(1.3rem, 1rem + 1.4vw, 1.9rem) * var(--bloque-titulo, 1));
  line-height: 1.35;
}
.lb__cita::before { content: "“"; }
.lb__cita::after  { content: "”"; }
.lb__firma {
  margin: .8rem 0 0;
  font-family: var(--ui);
  font-size: .9rem;
  color: var(--texto-3);
}

/* ===========================================================================
   La vista previa se TOCA — sólo dentro del editor

   Todo esto cuelga de `[data-edicion]`, que es un atributo que el panel escribe
   en el `<html>` de la previa DESDE FUERA del marco. El sitio público no lo
   lleva nunca, así que ninguna de estas reglas puede aparecer donde no toca —y
   la marca sólo se puede poner con sesión de administración, porque sin ella
   `?previa=1` no hace nada.

   Existe por un pedido que se repitió dos veces: la lista de nombres de la
   izquierda obligaba a adivinar cuál era la caja que se estaba mirando. Ahora
   se pasa por encima, se ve su nombre, y un clic lleva a sus controles.
   =========================================================================== */

/* ---------------------------------------------------------------------------
   La marca de un texto editable NO puede tener caja.

   Va con `display: contents` y no es un detalle de estilo: es la condición para
   que esto pueda existir. La vista previa sirve para decidir cómo queda la
   página, así que la maqueta del editor tiene que ser IDÉNTICA a la del sitio;
   si la propia marca la mueve, deja de servir para lo único que hace.

   Y la movía. Un `<span>` hijo de un contenedor flexible se BLOCKIFICA —lo dice
   la especificación: todo hijo de un flex se convierte en bloque, se ponga el
   display que se ponga—, y los enlaces del menú dejaron de encoger: la portada
   desbordaba 248 px en un celular. Lo cazó la auditoría del navegador en su
   primera pasada sobre el modo editor, que es exactamente para lo que se añadió
   esa pantalla a la lista.

   `display: contents` hace que el span no genere ninguna caja: sus hijos se
   colocan como si colgaran directamente del padre. La consecuencia es que
   tampoco se le puede pintar un fondo ni un borde, y por eso lo que se ilumina
   al pasar por encima es su PADRE — ver `[data-ed-texto]` más abajo.
   --------------------------------------------------------------------------- */
.ed-txt { display: contents; }

[data-edicion] [data-bloque] { cursor: pointer; }

/* La caja bajo el cursor. Es un `outline` y no un `border` a propósito: un
   borde ocupa sitio y correría la maqueta justo mientras se está ajustando. */
[data-edicion] [data-bloque][data-ed-hover] {
  outline: 1px dashed color-mix(in srgb, var(--lima) 45%, transparent);
  outline-offset: 0;
}

/* ---------------------------------------------------------------------------
   Los tiradores para estirar la caja elegida.

   Van en un marco `fixed` por encima de todo, con las medidas de la caja en
   cuatro variables que escribe el panel desde fuera. No se dibujan sobre el
   propio elemento —con `::after`, por ejemplo— porque el elemento puede tener
   `overflow: hidden` y recortarlos justo cuando hacen falta.

   Sólo tres: derecha, abajo y la esquina. Los de arriba y la izquierda moverían
   la caja además de estirarla, y una caja de este editor vive en el flujo de la
   página, no en una posición.
   --------------------------------------------------------------------------- */
.ed-tiradores {
  position: fixed;
  left: var(--ed-x, 0);
  top: var(--ed-y, 0);
  width: var(--ed-w, 0);
  height: var(--ed-h, 0);
  z-index: 9998;
  pointer-events: none;
}
.ed-tirador {
  position: absolute;
  appearance: none;
  padding: 0;
  width: 14px;
  height: 14px;
  border: 2px solid var(--pizarra-800);
  border-radius: 50%;
  background: var(--lima);
  pointer-events: auto;
  /* `touch-action: none` es lo que impide que el navegador se quede con el
     gesto para desplazar la página: sin él, arrastrar un tirador en una tableta
     mueve la página y la caja no cambia. */
  touch-action: none;
}
/* El rótulo de lo elegido: su nombre y, mientras se arrastra, su medida.

   Sustituye al recuadro en las franjas —donde un borde alrededor de media
   pantalla no dice «esto está elegido»— y hace más, porque además lo NOMBRA.
   Va pegado a la esquina de arriba a la izquierda, o por dentro cuando el
   elemento empieza tan arriba que fuera no cabría. */
.ed-chapa {
  position: absolute;
  left: 0;
  bottom: calc(100% + 4px);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: .16rem .5rem;
  border-radius: var(--radio-s);
  background: var(--lima);
  color: var(--sobre-lima);
  font-family: var(--ui);
  font-size: .73rem;
  font-weight: 500;
  line-height: 1.4;
  pointer-events: none;
}
.ed-tiradores[data-arriba="dentro"] .ed-chapa { bottom: auto; top: 4px; left: 4px; }

.ed-tirador[data-lado="x"]  { right: -7px; top: calc(50% - 7px); cursor: ew-resize; }
.ed-tirador[data-lado="y"]  { bottom: -7px; left: calc(50% - 7px); cursor: ns-resize; }
.ed-tirador[data-lado="xy"] { right: -7px; bottom: -7px; cursor: nwse-resize; }

/* Mientras se arrastra, el texto de la página no se selecciona: sin esto, un
   tirón sobre un titular lo deja resaltado en azul a mitad del gesto. */
[data-ed-estirando] { user-select: none; -webkit-user-select: none; }
[data-ed-estirando] .ed-tirador { cursor: inherit; }

/* Un texto editable. Se ilumina el elemento que lo CONTIENE, porque la marca
   en sí no tiene caja que iluminar —ver `display: contents` más arriba—. En
   reposo no se ve nada: la página tiene que seguir pareciéndose a la página, o
   deja de servir para decidir cómo queda.

   Se usa `box-shadow` y no `outline` ni `background` a propósito: `outline` en
   un elemento en línea que ocupa dos renglones se dibuja mal en algunos
   navegadores, y una sombra no ocupa sitio, así que no corre nada. */
[data-edicion] [data-ed-texto] {
  cursor: text;
  border-radius: 3px;
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--lima) 16%, transparent);
  background: color-mix(in srgb, var(--lima) 16%, transparent);
}
[data-edicion] [data-ed-escribiendo] {
  box-shadow: 0 0 0 3px var(--lima);
  background: color-mix(in srgb, var(--lima) 10%, transparent);
}
[data-edicion] .ed-txt:focus { outline: none; }

/* El rótulo que dice a qué se está apuntando. Lo crea el panel dentro de la
   previa y lo coloca con dos variables; va `fixed` para que no dependa de
   dónde esté el desplazamiento ni de qué elemento tenga debajo. */
.ed-rotulo {
  position: fixed;
  left: var(--ed-x, 0);
  top: var(--ed-y, 0);
  z-index: 9999;
  pointer-events: none;
  max-width: 70vw;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: .18rem .5rem;
  border-radius: var(--radio-s);
  background: var(--lima);
  color: var(--sobre-lima);
  font-family: var(--ui);
  font-size: .74rem;
  font-weight: 500;
  line-height: 1.4;
}

/* ===========================================================================
   Ajustes de pantalla chica — AL FINAL DEL ARCHIVO A PROPÓSITO

   Las reglas de más abajo ganan a las de más arriba cuando la especificidad
   empata, y las secciones del panel de evaluación y del teatro se escribieron
   después del bloque táctil general. Poniendo estos ajustes al final se evita
   el fallo silencioso de una regla móvil que nunca llega a aplicarse: no da
   error, simplemente no pasa nada, y sólo se nota midiendo.
   =========================================================================== */

@media (max-width: 640px) {

  /* --- barra del panel de evaluación -----------------------------------

     Ocupaba 164 px de alto en un celular —una quinta parte de la pantalla—
     porque los tres bloques se apilaban en tres filas. Ahora son dos: la marca
     con el botón de salir arriba, y el avance ocupando el ancho completo. */

  .jurado-barra {
    padding: .6rem var(--canal);
    gap: .5rem .8rem;
    row-gap: .5rem;
  }
  .jurado-barra__marca { flex: 1 1 auto; min-width: 0; }
  .jurado-barra__titulo {
    font-size: .92rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  /* La ronda se oculta: obligaba a una tercera fila y el mismo dato ya está
     como título del bloque de notas, a dos dedos de distancia. */
  .jurado-barra__ronda { display: none; }
  .jurado-barra__cuenta { flex: 0 0 auto; gap: .5rem; }
  .jurado-barra__nombre {
    max-width: 9ch;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .jurado-avance { flex: 1 1 100%; order: 4; }

  /* --- tira de payas ---------------------------------------------------- */

  .tira-pieza { width: 128px; }
  .jurado-tira__pista { gap: .7rem; padding-bottom: 1.1rem; }

  /* --- escala de 1 a 5 --------------------------------------------------- */

  /* Cinco opciones en 360 px dan 47 px cada una: justo por encima del mínimo
     para un pulgar, y sólo si no pierden ni un píxel más en separación. */
  .escala--cinco { gap: .25rem; }
  .escala--cinco .escala__opcion { padding: .5rem .1rem; }

  /* --- los dos teatros, en celular ---------------------------------------

     NINGUNO se hace a sangre, y eso costó llegar a entenderlo. Una caja a
     pantalla completa tapa el fondo entero, así que el desenfoque de detrás no
     se ve y la capa se lee como haber cambiado de página; y con el contenido
     pegado arriba, un video vertical quedaba en el borde de arriba con media
     pantalla vacía debajo. Se arregló primero en el de la portada y se
     reportó igual en el de la votación: es el mismo comportamiento y ahora es
     una sola regla, no una general y su excepción.

     Queda una tarjeta centrada, con la página difuminada asomando alrededor. */
  .teatro {
    --hueco: clamp(.6rem, 3vw, 1rem);
    /* Abajo se suma la franja del indicador de inicio del teléfono: los botones
       de moverse entre videos son lo último de la caja y ahí es donde quedarían
       debajo de ella. */
    padding: var(--hueco) var(--hueco) calc(var(--hueco) + env(safe-area-inset-bottom, 0px));
    place-items: center;
  }
  .teatro__caja {
    width: 100%;
    /* El 100 % es el hueco que deja el relleno, no la ventana entera. */
    max-height: 100%;
    padding: .85rem;
    align-content: center;
  }
  .teatro__pie { gap: .5rem; }
  .teatro__pie .boton--fantasma { flex: 1 1 0; justify-content: center; }

  /* En un celular el marco ocupa menos: la caja lleva menos relleno y el título
     es más chico. Medido, son unos 185 px en el de la portada y unos 240 en el
     de la votación, que tiene un botón más y el de votar en su propia fila. Se
     redondea hacia arriba: pasarse deja el video algo más chico, quedarse corto
     lo hace desbordar sobre los botones. */
  .teatro { --hueco-teatro: 210px; }
  .teatro--votacion { --hueco-teatro: 290px; }

  /* El mismo doble límite que en pantalla grande, y por lo mismo: un celular de
     lado es una ventana baja. En un celular la cabecera y los botones pesan más
     en proporción, así que el porcentaje baja de 62 a 56 y el hueco que ocupa
     el marco se descuenta igual. */
  .teatro .reproductor--vertical {
    --alto-video: max(160px, min(56vh, 100vh - var(--hueco-teatro)));
    --alto-video: max(160px, min(56svh, 100svh - var(--hueco-teatro)));
  }

  /* Y el video del jurado, que dentro de la página compite con el ancho de la
     pantalla y no con su alto. */
  .equipo-video { --alto-video: 460px; }

  /* --- rondas del panel -------------------------------------------------- */

  .etapas { gap: .5rem; }

  /* --- el resumen del jurado: enviar, arriba -----------------------------

     La tabla del resumen puede tener doscientas filas y se desplaza por dentro.
     Con el botón de enviar debajo de ella, en un celular hay que pasar la tabla
     entera para llegar al único botón que cierra el trabajo — y es el momento
     en que ya se revisaron los totales y sólo queda pulsarlo.

     Se mueve con `order`, así que en el HTML sigue estando DESPUÉS de la tabla:
     el orden de lectura y el del tabulador se mantienen, que es lo correcto —
     enviar es lo último que se hace, aunque se dibuje lo primero. Es la misma
     solución que el botón de votar en el teatro de la galería.

     El borde y el relleno de arriba cambian de lado con él: separaban el envío
     de la tabla que tenía encima y ahora la tabla queda debajo. */
  .jurado-resumen {
    display: flex;
    flex-direction: column;
  }
  .jurado-resumen__cabecera { order: 1; }
  .jurado-resumen__envio    { order: 2; }
  .jurado-resumen__caja     { order: 3; }

  .jurado-resumen__envio {
    margin-top: 0;
    margin-bottom: 1.2rem;
    padding-top: 0;
    padding-bottom: 1.2rem;
    border-top: 0;
    border-bottom: var(--grosor-borde) solid var(--linea);
  }
}

/* En horizontal y con poca altura —un celular de lado— la barra pegada arriba
   y la tira de abajo dejan sin sitio al video, que es lo único que importa. */
@media (max-height: 520px) and (orientation: landscape) {
  .jurado-barra { position: static; }
  .jurado-tira__pista { padding-bottom: .5rem; }
  .tira-pieza { width: 104px; }
  .tira-pieza__nombre { display: none; }
}
