/* Operaciones (math) — keypad round.
   All visual properties use CSS vars so skins override without !important.
   Defaults reproduce the original look exactly — no visual change without a skin.

   ESTÁNDAR RESPONSIVE («primero se reparte el espacio, luego se dibuja»):
   la ronda SIEMPRE llena la altura de su contenedor y el teclado es el elemento
   flexible — sus 4 filas se reparten el alto con minmax(0,1fr) y encogen para
   caber. Pregunta + display + teclado completo (incluido 0 / Borrar / Enviar)
   son SIEMPRE visibles, sin scroll, en cualquier marco (player no-fullscreen,
   fullscreen, VS o Equipos). Las medidas usan unidades de CONTENEDOR (cqmin),
   no de viewport (vmin/vh), para responder al MARCO y no a la ventana. */

.ww-math { display: flex; flex-direction: column; height: 100%; min-height: 0; }
/* La ronda toma el alto RESTANTE tras la cabecera (flex:1), nunca height:100%
   —que se sumaría al alto del HUD y desbordaría el marco—. */
.ww-math-round { flex: 1 1 auto; min-height: 0; }

.ww-keypad-round {
  display: flex; flex-direction: column; align-items: center;
  /* EL BLOQUE VA JUNTO Y EL AIRE A LOS BORDES. Primero fue `flex-start` (todo el
     hueco de golpe entre la pregunta y las teclas: una banda vacía en medio) y
     luego `space-evenly`, que lo repartió en tres huecos y separó el enunciado
     de su teclado. Un teclado de 3×4 en un panel el doble de alto que ancho NO
     puede llenar sin deformarse, así que lo que sobra va FUERA del bloque: la
     pregunta y las teclas quedan juntas —se leen como una sola cosa— y el aire
     se reparte arriba y abajo. */
  justify-content: center;
  gap: var(--math-gap, clamp(.4rem, 2cqmin, 1.1rem));
  padding: var(--math-pad, 0);
  height: 100%; min-height: 0;
  box-sizing: border-box;
  /* LA CALCULADORA ES UNA SOLA PIEZA, y el tope de ancho es del BLOQUE, no del
     teclado (dueño, 2026-08-22, con captura de Individual a pantalla completa:
     «la actividad se dispersó»). El tope vivía en `.ww-keypad`, así que en una
     pantalla ancha el teclado se quedaba en su sitio pero la cabecera —que mide
     el 100 % de su caja— se estiraba a todo el marco: la operación quedaba a la
     izquierda y el visor pegado al borde derecho, a un palmo del teclado. Con el
     tope aquí, cabecera y teclado comparten ancho y se leen como una calculadora.
     En VS el bloque ya trae su propio tope (más estricto, calculado con la
     cabecera) y sigue mandando por especificidad. */
  width: 100%;
  margin-inline: auto;
  /* EL BLOQUE REPARTE SU PROPIO ALTO (§0: un modo no puede conocer una plantilla
     concreta). Esta cuenta vivía en `styles/vs.css`: era el MODO quien restaba la
     cabecera, quien sabía que la rejilla es de 3 columnas por 4 filas y quien
     tenía escrito el hueco en `1.5rem`. Tres datos privados de la calculadora en
     una hoja que no debería saber que la calculadora existe — y por eso la
     plantilla tuvo que volverse rígida para que la cuenta ajena siguiera siendo
     cierta. Ahora el modo solo dice DOS valores (cuánto vale ahí una cabecera y
     cuál es su tope) y la cuenta la hace quien conoce la anatomía.
     El tope sale de la geometría: al teclado le queda el alto de la caja menos la
     cabecera y el hueco, y de ahí —por la proporción de su propia rejilla— su
     ancho máximo. Así el bloque llena lo que puede sin deformar las teclas. */
  --math-ancho: min(
    100cqw,
    var(--math-tope, 75cqh),
    calc((100cqh - var(--math-head-min, 0px) - var(--math-gap, 1.1rem))
         * var(--key-cols, 3) / var(--key-rows, 4))
  );
  max-width: min(100%, var(--math-ancho));

  /* ══ LA MEDIDA MADRE: UNA CIFRA ═════════════════════════════════════════════
     El «3 × 4 =» y el «7» de una tecla salían de fórmulas DISTINTAS —y había
     tres juegos de ellas, uno por modo: nueve en total para tres textos que en
     una calculadora son del mismo tamaño—. Por eso no cuadraban a la vista y por
     eso un tema tenía que perseguirlos de uno en uno (dueño, 2026-08-22: «deben
     tener el mismo origen para que sí sean idénticos y poder controlar los temas
     más fácilmente»).
     Ahora hay UNA medida —lo que mide una cifra— y los tres textos SON esa medida:
     idénticos, como pidió el dueño.
     · Un MODO (VS, Equipos) redeclara SOLO `--math-cifra`, no tres fórmulas.
     · Un TEMA cambia toda la tipografía de la calculadora con ese mismo token.
     · `--key-size` / `--math-q-size` / `--display-size` siguen existiendo como
       escotilla para un tema que necesite descuadrar una pieza a propósito.
     Hubo un momento un multiplicador por pieza (`--key-escala` y compañía): no lo
     consumía nadie, y como la red «un solo origen» exige que las tres midan lo
     mismo, cualquier valor distinto de 1 rompía CI. Una escotilla que el propio
     test prohíbe usar no es una escotilla.
     Y LA LETRA MIRA EL ANCHO EN EL QUE TIENE QUE CABER. Este era el fondo del
     fallo de «la caja del resultado no tiene un lugar» (dueño, 2026-08-24, con
     captura a 1280×800): la medida salía del lado corto de la CAJA, sin saber
     nada del ancho del BLOQUE, así que al crecer la letra el enunciado y el hueco
     de respuesta dejaban de caber en su fila; `flex-wrap` partía la cabecera en
     dos y la segunda línea se salía de su banda, con el teclado encima. Se probó
     dejar encoger al hueco (arregla 7 de 11 tamaños), y también al enunciado
     (entonces «2 × 6 =» se parte en dos líneas: peor). Ninguna de las dos toca la
     causa — que la letra no cabe—, solo mueven dónde se ve.
     El techo por ancho la hace caber POR CONSTRUCCIÓN: la cabecera es una fila
     con la operación y el hueco. El divisor se CALIBRÓ midiendo 11 formas de
     ventana a pantalla completa: 8, 9 y 10 dan cero roturas, y se elige el 10
     por ser el más conservador de los tres (el 12 llegó a estar escrito en este
     comentario cuando el código ya ponía 10 — un comentario que no cuadra con su
     línea es peor que no tenerlo). Al ir en la MEDIDA MADRE, las teclas encogen
     con ella y los tres textos siguen siendo el mismo tamaño. */
  --math-cifra: max(1rem, min(11cqmin, calc(var(--math-ancho) / 10)));
}

/* «2 × 2 =» Y EL RESULTADO, EN LA MISMA LÍNEA (dueño, 2026-08-17, con captura):
   apilados, la operación y su hueco de respuesta se leían como dos cosas
   distintas y el bloque quedaba alto y suelto. Juntos son UNA frase —el
   enunciado completo— y el conjunto queda compacto. Si no cabe (móvil muy
   estrecho o número largo), el hueco baja solo: `flex-wrap`, no un breakpoint. */
.ww-keypad-head {
  flex: 0 0 auto;
  /* LOS DOS MARCOS, LA MISMA ALTURA. El hueco del «0» salía más bajo que la
     chapa del «2 × 6» —cada uno con su relleno— y juntos parecían dos piezas de
     sitios distintos. `stretch` los iguala al más alto sea cual sea el tema, sin
     que ninguno tenga que saber cuánto mide el otro. */
  display: flex; align-items: stretch; justify-content: center;
  flex-wrap: wrap;
  gap: var(--math-head-gap, clamp(.35rem, 1.8cqmin, 1.1rem));
  /* LA CABECERA OCUPA EL ANCHO DEL TECLADO, como el visor de una calculadora
     de verdad: si mide solo su texto, queda una pastilla estrecha encima de un
     teclado ancho. La operación se lleva el sobrante y el hueco de respuesta
     conserva su ancho mínimo. */
  width: 100%;
  max-width: 100%;
  /* LA CHAPA ES DEL TAMAÑO DE UNA TECLA, no de su texto (dueño, 2026-08-22:
     «2×6 y 0 están muy pequeños sus cajas respecto de las de abajo»). La letra
     ya era la MAYOR de la pantalla —1,3× la cifra de una tecla—, pero su caja
     medía el texto más un relleno mínimo: 29 px de alto contra teclas de 71.
     En una calculadora de verdad el visor no es más bajo que una fila de
     teclas. Se pide por token para que cada modo diga cuánto vale ahí «una
     tecla»; sin token, el alto lo sigue dando el contenido.
     LA BANDA ES UN SUELO, NO UN TECHO — y ese es el segundo medio filo del fallo
     de «la caja del resultado no tiene un lugar» (dueño, 2026-08-24). Llegó a ser
     un alto EXACTO para que la cuenta del bloque —que resta este valor— siguiera
     siendo cierta cuando un tema le añade relleno a la chapa. Pero un alto exacto
     no da sitio: cuando el contenido no cabía en la fila, `flex-wrap` lo mandaba a
     una segunda línea que caía FUERA de la banda, y el teclado se pintaba encima.
     El primer medio filo (el techo por ancho de `--math-cifra`) hace que quepa en
     una fila con la operación que genera la plantilla. Pero la operación la
     escribe el profe y puede ser «144 ÷ 12» o más larga: no hay medida que valga
     para todo. Con un suelo, ese caso raro ENSANCHA la banda y el teclado encoge
     un poco —feo pero legible— en vez de esconder el hueco de la respuesta.
     Correcto por construcción en lo normal, y que ceda por lo bajo en lo raro. */
  min-height: var(--math-head-min, auto);
}

/* LA TIPOGRAFÍA DE LA CALCULADORA, por token. Arcade la escribía directamente
   sobre `.ww-keypad-q`, `.ww-keypad-display` y `.ww-key` (tres invasiones para
   una sola decisión); ahora declara `--math-font` una vez y estas tres la leen.
   El respaldo es `inherit` A PROPÓSITO: la tecla es un `<button>` y los controles
   de formulario no heredan la fuente solos. `revert` (devolver la del navegador)
   parecía más conservador y NO lo es — en producción Bootstrap deja al botón
   heredando, así que habría cambiado la tipografía en el sitio real. La historia
   completa, en `tools/shots.mjs`: se midió con Bootstrap sin cargar. */
.ww-keypad-q,
.ww-keypad-display,
.ww-keypad .ww-key { font-family: var(--math-font, inherit); }


.ww-keypad-q {
  flex: 1 1 auto;   /* se lleva el ancho que sobra tras el hueco de respuesta */
  display: flex; align-items: center; justify-content: center;
  /* MISMA MEDIDA QUE UNA CIFRA (ver `--math-cifra` en .ww-keypad-round). Antes
     tenía fórmula propia y por eso el enunciado nunca casaba con las teclas. */
  font-size: var(--math-q-size, var(--math-cifra));
  font-weight: var(--math-q-weight, 800);
  color: var(--math-q-color, inherit);
  /* La CHAPA: sin tema, el enunciado es texto suelto (todo transparente y sin
     relleno). Un tema la convierte en la placa del plató o el cartel de la
     recreativa pidiendo estos tokens — nunca escribiendo sobre esta regla. */
  background: var(--math-q-bg, transparent);
  border: var(--math-q-border, 0);
  border-radius: var(--math-q-radius, 0);
  padding: var(--math-q-pad, 0);
  box-shadow: var(--math-q-shadow, none);
  text-shadow: var(--math-q-text-shadow, none);
  text-align: center; line-height: 1.1;
}

/* EL RÓTULO DEL TEMA — un hueco declarado, no una invasión. Arcade le pone
   «SOLVE!» encima al enunciado con un `::before` escrito sobre la anatomía de
   Operaciones. Es decoración legítima del tema, así que la plantilla le OFRECE
   el sitio: sin `--math-q-rotulo` el pseudo-elemento no existe (`content: none`)
   y no ocupa ni un píxel. */
.ww-keypad-q::before {
  content: var(--math-q-rotulo, none);
  display: block;
  /* Hueco y espaciado van FIJOS: se ofrecieron como tokens y no los pedía nadie.
     Este fichero ya tuvo que retirar `--key-escala` y compañía por lo mismo
     (arriba); un mando que nadie usa no es flexibilidad, es superficie que
     mantener. El TAMAÑO sí queda por token, y no por si acaso: en `math.css`
     ningún `font-size` puede ir literal —lo exige el ratchet de §3, que trata
     esta hoja como ejemplar— y quitarlo rompió CI al instante. */
  margin-bottom: .4em;
  letter-spacing: .15em;
  font-size: var(--math-q-rotulo-size, .5em);
  color: var(--math-q-rotulo-color, inherit);
  text-shadow: var(--math-q-rotulo-shadow, none);
}

.ww-keypad-eq { opacity: var(--math-eq-opacity, .55); color: var(--math-eq-color, inherit); }

/* EL HUECO DE LA RESPUESTA SE REPARTE LA FILA, no la rompe (dueño, 2026-08-24,
   con captura a 1280×800: «la caja del resultado no tiene un lugar»).
   Aquí pedía un ancho MÍNIMO duro (`max(5rem, 34cqmin)`) y encima no podía
   encoger (`flex: 0 0 auto`). Con la cifra pequeña sobraba sitio y no se notaba;
   al crecer la letra, el enunciado más ese mínimo dejaron de caber en la fila, la
   cabecera se partió en dos líneas —`flex-wrap` haciendo lo que se le pidió— y la
   segunda línea se salió de la banda de la cabecera, que tiene alto declarado:
   el teclado se pintó encima y la caja del «0» quedó asomando detrás de la tecla
   del 2. No era un caso raro: pasaba en 6 de 7 tamaños a pantalla completa.
   La cabecera es UNA fila con dos partes: la operación se lleva el sobrante y el
   hueco de respuesta un tercio, y AMBOS pueden encoger. Así no hay nada que
   partir. No es una medida nueva: es exactamente lo que ya declaraban los dos
   modos que alguien se paró a afinar (`styles/scaffold.css`, para el duelo y para
   equipos) — la regla base era la única que seguía pidiendo un mínimo duro, y por
   eso el fallo aparecía justo donde esos ajustes no llegaban. */
.ww-keypad-display {
  flex: 0 1 30%;
  display: flex; align-items: center; justify-content: center;
  min-width: 0;
  font-size: var(--display-size, var(--math-cifra));
  font-weight: 800; text-align: center; font-variant-numeric: tabular-nums;
  padding: var(--display-pad, .1rem 1rem);
  border: var(--display-border, 3px solid #dee2e6);
  border-radius: var(--display-radius, .6rem);
  background: var(--display-bg, #fff);
  color: var(--display-fg, #212529);
  text-shadow: var(--display-text-shadow, none);
  box-shadow: var(--display-shadow, none);
}
/* EL ACIERTO/ERROR TAMBIÉN ES DEL TEMA. Antes tv-show fijaba `color: #fff` con
   más especificidad que estas dos reglas y el visor NO cambiaba de color al
   acertar; al pasar a tokens, `.is-ok` empezó a ganar y el visor se volvía
   verde. Ni una cosa ni la otra por accidente: el color de acierto y de error
   son tokens propios, con el verde/rojo de siempre por defecto, y un tema que
   quiera el suyo (o ninguno) lo declara. */
.ww-keypad-display.is-ok {
  border-color: var(--display-ok, var(--ww-success, #198754));
  color: var(--display-ok-fg, var(--display-ok, var(--ww-success, #198754)));
}
.ww-keypad-display.is-no {
  border-color: var(--display-no, var(--ww-danger, #dc3545));
  color: var(--display-no-fg, var(--display-no, var(--ww-danger, #dc3545)));
}

/* El teclado es el elemento FLEXIBLE: ocupa el alto restante y sus filas se
   reparten ese alto (grid-auto-rows: 1fr) → siempre caben las 4 filas. */
.ww-keypad {
  flex: 1 1 auto; min-height: 0;
  display: grid;
  grid-template-columns: repeat(var(--key-cols, 3), minmax(0, 1fr));
  grid-auto-rows: minmax(0, 1fr);
  gap: var(--key-gap, clamp(.3rem, 1.4cqmin, .7rem));
  margin-top: var(--keypad-top, 0);
  /* EL TOPE ES LA FORMA, NO UN NÚMERO. Aquí ponía `min(100%, 360px)`: en una
     pizarra 4K el teclado se quedaba en 360 px —el 60 % de su caja— y el resto
     era aire («fíjate en todo el aire que tiene», con captura). Un tope en px no
     escala (§3). El tope de verdad es que las teclas no se estiren: el ancho no
     pasa de 3/4 del ALTO de la caja, que es la proporción del propio teclado
     (3 columnas × 4 filas). Así llena lo que puede y conserva su forma. */
  width: 100%;                             /* el tope de ancho lo pone el BLOQUE (.ww-keypad-round) */
  height: 100%;                            /* respaldo para navegadores que no resuelven flex-basis en grid */
}
.ww-keypad .ww-key {
  min-height: 0; min-width: 0;
  display: flex; align-items: center; justify-content: center;
  /* LA CIFRA DE LA TECLA ES LA MEDIDA MADRE (`--math-cifra`, en
     .ww-keypad-round): el enunciado y el visor son múltiplos de ESTO. La fórmula
     que había aquí se mudó allí sin cambiar de valor. Historia de sus dos techos
     fijos, por si alguien piensa en reponerlos: primero `1.9rem` (con teclas de
     190 px el dígito se quedaba en 30) y luego `3.4rem` (en la pizarra 4K a
     pantalla completa, 54 px sobre una tecla de 395). Un techo en `rem` no
     escala NUNCA; el techo real lo pone `cqmin`. */
  font-size: var(--key-size, var(--math-cifra));
  font-weight: var(--key-weight, 700);
  /* UN SOLO token de relleno. Hubo un `padding-block` aparte y le comía la
     mitad vertical al `--key-pad` público; luego un `--key-pad-block` anidado
     DENTRO de su fallback, que lo volvía invisible en cuanto alguien declarara
     `--key-pad`. Un token, dos ejes: `--key-pad: .62em 0`. */
  padding: var(--key-pad, 0);
  border: var(--key-border, 2px solid #ced4da);
  background: var(--key-bg, #fff);
  color: var(--key-fg, #212529);
  border-radius: var(--key-radius, .5rem);
  box-shadow: var(--key-shadow, none);
  /* VOCABULARIO DEL SKIN (§3, ampliado en la migración de temas 2026-08-22).
     Lo que un tema necesita para hacer una tecla de plató o de recreativa —
     tipografía, relieve del texto, alto del cuerpo, cómo se hunde al pulsar—
     ahora se PIDE por token en vez de escribirse encima de esta regla. El
     fallback es exactamente lo que había, así que sin tema nada cambia. */
  text-shadow: var(--key-text-shadow, none);
  transition: var(--key-transition, none);
  line-height: 1;
  /* Respuesta táctil inmediata y MULTITÁCTIL fiable: `none` evita que el
     navegador trate cada toque como posible scroll/zoom (lo que añade latencia
     y, en pizarras lentas, puede descartar el 2º dedo simultáneo del rival). */
  touch-action: none;
  user-select: none; -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.ww-keypad .ww-key:active {
  transform: var(--key-press, translateY(1px));
  /* La sombra al pulsar cae en la NORMAL si el tema no declara una propia. Ojo:
     el defecto tiene que ser `--key-shadow` y no `none` — esta regla es (0,3,0)
     y con `none` borraba al pulsar el resplandor que un tema declare en su
     `.ww-key` (0,2,0): la tecla parpadeaba a plano (lo cazó /code-review).
     Por eso un tema con relieve DEBE declarar `--key-shadow`, aunque además lo
     pinte directo mientras le quede deuda de migración. */
  box-shadow: var(--key-shadow-active, var(--key-shadow, none));
}

/* ── NI ESTIRADO NI DEFORMADO (dueño, 2026-08-17, con captura de pantalla
   completa: «está súper estirado, y peor aún solo en una dirección»).
   Llenar el hueco NO es la meta: el teclado tiene una FORMA (3 columnas × 4
   filas) y estirarlo solo a lo alto convierte las teclas en rectángulos
   larguísimos. Aquí el ancho es el mayor que cabe SIN pasarse de alto —el alto
   sale de la proporción, no del hueco— y lo que sobra queda como AIRE
   alrededor, con el bloque centrado.
   Alcance: la pantalla del alumno (Individual, Tarea, En vivo). VS y Equipos
   NO entran: ahí el teclado comparte un panel estrecho con el del rival y su
   reparto está verificado con capturas (styles/scaffold.css §andamio). */
/* EL TOPE ES DEL BLOQUE, NO DEL TECLADO. `52cqh` vivía solo en `.ww-keypad`, así
   que en una pantalla ancha el teclado se quedaba en su sitio y la cabecera —que
   mide el 100 % de su caja— se estiraba a todo el marco: medido a pantalla
   completa, bloque 403..1162 con el teclado en 520..1045 y el visor pegado al
   borde derecho, a 120 px del teclado («la actividad se dispersó», dueño con
   captura). Con el tope en el bloque, cabecera y teclado comparten ancho y se
   leen como una sola calculadora. */
.ww-math-round .ww-keypad-round,
#s-round .ww-keypad-round {
  justify-content: center;
  /* `52cqh` es el tope que deja aire: 52 de ancho ⇒ 69 de alto, y el resto del
     hueco queda para el enunciado y el margen. Se declara como TOPE y la cuenta
     del bloque (arriba) ya lo mete en su `min()`. */
  --math-tope: 52cqh;
  margin-inline: auto;
}
.ww-math-round .ww-keypad,
#s-round .ww-keypad {
  flex: 0 1 auto;
  align-self: center;
  aspect-ratio: var(--key-cols, 3) / var(--key-rows, 4);
  height: auto;
  width: 100%;
}
.ww-keypad .ww-key-ok {
  background: var(--key-ok-bg, var(--ww-success, #198754));
  color: var(--key-ok-fg, #fff);
  /* El ✓ hereda el BORDE de la tecla y solo decide su COLOR: es lo único que
     cambia en los dos temas, así que un token de borde entero sobraba (y su
     color quedaba pisado por este de todas formas). Transparente por defecto. */
  border: var(--key-border, 2px solid #ced4da);
  border-color: var(--key-ok-border-color, transparent);
  box-shadow: var(--key-ok-shadow, var(--key-shadow, none));
}
.ww-keypad .ww-key-fn {
  background: var(--key-fn-bg, #f1f3f5);
  color: var(--key-fn-fg, var(--key-fg, #212529));
  border: var(--key-fn-border, var(--key-border, 2px solid #ced4da));
  box-shadow: var(--key-fn-shadow, var(--key-shadow, none));
}
