/*
 * Capa visual v1: neutra y funcional, a propósito.
 *
 * No hay identidad de marca todavía. Lo único que aquí no es negociable es la
 * legibilidad: la nube tiene que leerse desde la última fila de la sala, así
 * que el contraste y el tamaño mandan sobre cualquier consideración estética.
 *
 * La paleta institucional de Duoc UC entra en fase 2 tocando solo estas
 * variables.
 */

:root {
  --papel: #ffffff;
  --tinta: #111111;
  --tinta-suave: #4a4a4a;
  --linea: #d6d6d6;
  --superficie: #f4f4f4;
  --alerta: #a3231b;
  --exito: #1c6b3f;

  --radio: 6px;
  --fuente: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
}

/*
 * Modo nocturno. Se acciona a mano desde la barra, nunca por la preferencia del
 * sistema: el sistema se pone oscuro por la hora del día, y aquí lo que decide
 * es la luz de la sala, que solo el profesor ve.
 *
 * Los valores de --papel y --tinta deben coincidir con TEMAS en js/tono.js, que
 * es donde se mide el contraste de la nube.
 */
:root[data-tema="oscuro"] {
  --papel: #1f1f1f;
  --tinta: #f5f5f5;
  --tinta-suave: #b4b4b4;
  --linea: #3d3d3d;
  --superficie: #2b2b2b;
  --alerta: #ef6a60;
  --exito: #6cc48f;
}

* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

body {
  margin: 0;
  font-family: var(--fuente);
  color: var(--tinta);
  background: var(--papel);
  -webkit-text-size-adjust: 100%;
}

button {
  font: inherit;
  cursor: pointer;
}

.oculto,
[hidden] {
  display: none !important;
}

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

.boton {
  border: 1px solid var(--tinta);
  background: var(--papel);
  color: var(--tinta);
  border-radius: var(--radio);
  padding: 0.6rem 1rem;
  font-weight: 600;
  line-height: 1.2;
}

.boton:hover {
  background: var(--superficie);
}

.boton:focus-visible {
  outline: 3px solid var(--tinta);
  outline-offset: 2px;
}

.boton--principal {
  background: var(--tinta);
  color: var(--papel);
}

/*
 * El hover no baja a negro: en modo nocturno el botón principal es claro y su
 * texto es oscuro, así que oscurecer el fondo dejaba el texto en 1,27:1 —
 * invisible. Se apaga con un token, que además sigue a la paleta cuando entre
 * la de Duoc.
 */
.boton--principal:hover {
  background: var(--tinta-suave);
}

.boton--grande {
  padding: 1rem 1.75rem;
  font-size: 1.25rem;
}

.boton--peligro {
  border-color: var(--alerta);
  background: var(--alerta);
  color: var(--papel);
}

.boton--fantasma {
  border-color: var(--linea);
  color: var(--tinta-suave);
}

/* --- Pantalla de inicio del profesor ------------------------------------ */

.pantalla {
  min-height: 100vh;
  min-height: 100dvh;
}

.inicio {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2rem;
  max-width: 44rem;
  margin: 0 auto;
  padding: 3rem 1.5rem;
}

.inicio h1 {
  font-size: clamp(2rem, 5vw, 3rem);
  margin: 0;
  letter-spacing: -0.02em;
}

.inicio p {
  margin: 0;
  color: var(--tinta-suave);
  font-size: 1.125rem;
  line-height: 1.5;
}

.salas-hoy {
  border-top: 1px solid var(--linea);
  padding-top: 1.5rem;
}

.salas-hoy h2 {
  font-size: 0.875rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--tinta-suave);
  margin: 0 0 0.75rem;
}

.salas-hoy ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.5rem;
}

.salas-hoy button {
  width: 100%;
  text-align: left;
  display: flex;
  gap: 1rem;
  align-items: baseline;
  border: 1px solid var(--linea);
  background: var(--papel);
  border-radius: var(--radio);
  padding: 0.75rem 1rem;
}

.salas-hoy button:hover {
  background: var(--superficie);
}

.salas-hoy code {
  font-weight: 700;
  letter-spacing: 0.12em;
}

.salas-hoy span {
  color: var(--tinta-suave);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --- Sala en curso (proyector) ------------------------------------------ */

.sala {
  display: grid;
  grid-template-rows: auto 1fr;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

.barra {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  padding: 0.75rem 1.25rem;
  border-bottom: 1px solid var(--linea);
  background: var(--papel);

  /* Suelo para el lienzo: por muchos botones que haya y por angosta que sea la
     ventana, la barra nunca puede quedarse con más de un tercio de la pantalla.
     Sin este tope, al partirse en varias líneas llegó a dejar el lienzo en 0. */
  max-height: 34dvh;
  overflow: auto;
}

.barra__pregunta {
  flex: 1;
  margin: 0;
  font-size: clamp(1.1rem, 2.2vw, 1.9rem);
  font-weight: 600;
  line-height: 1.25;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.marca {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--tinta-suave);
  white-space: nowrap;
}

.contador {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  white-space: nowrap;
  color: var(--tinta-suave);
}

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

.acciones .boton {
  padding: 0.45rem 0.8rem;
  font-size: 0.9rem;
}

/* En pantallas angostas (el portátil antes de conectar el proyector) los
   botones aplastan la pregunta hasta dejarla ilegible. Se baja a su propia
   línea en vez de competir por el ancho. */
@media (max-width: 900px) {
  .barra {
    flex-wrap: wrap;
    gap: 0.75rem 1rem;
  }

  .barra__pregunta {
    order: 3;
    flex-basis: 100%;
    -webkit-line-clamp: 3;
  }
}

/* --- Lienzo de la nube --------------------------------------------------- */

.lienzo {
  position: relative;
  overflow: hidden;
}

.nube {
  position: absolute;
  inset: 0;
}

.palabra {
  position: absolute;
  left: 50%;
  top: 50%;
  border: 0;
  background: transparent;
  padding: 0.05em 0.15em;
  margin: 0;
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
  border-radius: 4px;
  transition: font-size 380ms ease, color 380ms ease, opacity 300ms ease;
}

/*
 * Respiración. Va en la propiedad `translate`, que es independiente de
 * `transform` y se compone con ella: la posición sigue viviendo en `transform`,
 * así que el movimiento NO puede alterar la colocación. Oscila alrededor de su
 * sitio y vuelve.
 *
 * Cada palabra recibe su duración y su desfase desde JS, para que el conjunto
 * nunca lata al unísono. Animar `translate` y `scale` lo resuelve el compositor
 * sin recalcular el diseño de la página: sale gratis durante los 80 minutos de
 * clase.
 */
.palabra {
  animation: respirar var(--respira-duracion, 6s) ease-in-out var(--respira-desfase, 0s) infinite;
}

@keyframes respirar {
  0%,
  100% {
    translate: 0 0;
  }
  25% {
    translate: 2px -3px;
  }
  50% {
    translate: 0 -1px;
  }
  75% {
    translate: -2px -3px;
  }
}

.palabra--entra {
  animation:
    aparecer 420ms ease both,
    respirar var(--respira-duracion, 6s) ease-in-out var(--respira-desfase, 0s) infinite;
}

/* Pulso cuando alguien acaba de escribir esa palabra. */
.palabra--sube {
  animation:
    latir 600ms ease-out,
    respirar var(--respira-duracion, 6s) ease-in-out var(--respira-desfase, 0s) infinite;
}

@keyframes latir {
  0% {
    scale: 1;
  }
  35% {
    scale: 1.14;
  }
  100% {
    scale: 1;
  }
}

/* Gemelo oculto que sirve de regla. Sin transición ni animación: es lo que
   permite medir el tamaño final de una palabra y no el de mitad de camino. */
/* Durante el cambio de tema no hay fundido: el color nuevo entra de golpe,
   junto con el fondo. Ver el manejador de #btn-tema. */
:root.sin-transicion .palabra {
  transition: none;
}

.palabra--regla {
  left: -9999px;
  top: 0;
  transform: none;
  transition: none;
  animation: none;
  translate: none;
  scale: none;
  visibility: hidden;
  pointer-events: none;
}

@keyframes aparecer {
  from {
    opacity: 0;
    scale: 0.85;
  }
  to {
    opacity: 1;
    scale: 1;
  }
}

.palabra:hover,
.palabra:focus-visible {
  outline: 2px dashed var(--alerta);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .palabra,
  .palabra--entra,
  .palabra--sube {
    transition: none;
    animation: none;
    translate: none;
    scale: none;
  }

  /* El botón también se levanta al pasar por encima; con el movimiento
     reducido no se levanta. */
  .boton {
    transition: none;
  }

  .boton:hover {
    transform: none;
  }
}

/* --- Ingreso: QR y código ------------------------------------------------ */

/*
 * El QR es la única forma de entrar a la sala, así que NADA puede taparlo.
 * Estos z-index no son decoración: los paneles a sangre (`.aviso-grande`) y el
 * diálogo de pregunta vienen después en el DOM y, sin esto, pintan encima —
 * dejando en pantalla el mensaje "escanea el QR" sobre el QR tapado, que es un
 * bloqueo del que la clase no sale.
 */
.ingreso {
  position: absolute;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  background: var(--papel);
}

.ingreso--grande {
  inset: 0;
  justify-content: center;
  z-index: 2;
  transition: padding-top 200ms ease;
}

/*
 * Franja inferior del lienzo. Los conteos y el QR viven aquí dentro en vez de
 * posicionarse cada uno por su cuenta: con dos tarjetas absolutas compitiendo
 * por la misma esquina, cada vez que cambiaba el ancho una acababa tapando a la
 * otra. En un contenedor flex eso no puede pasar por construcción.
 *
 * `pointer-events: none` en la franja para no robarle clics a las palabras de
 * la nube que queden debajo; las tarjetas los recuperan.
 */
.pie-lienzo {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 3;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem;
  pointer-events: none;
}

.pie-lienzo > * {
  pointer-events: auto;
}

.ingreso--esquina {
  position: static;
  margin-left: auto; /* pegado a la derecha aunque no haya conteos */
  padding: 0.75rem;
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  flex: none;
  cursor: zoom-in;
  transition: transform 160ms ease, box-shadow 160ms ease;
}

.ingreso--esquina:hover,
.ingreso--esquina:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 8px 24px rgb(0 0 0 / 18%);
}

.ingreso--esquina:focus-visible {
  outline: 3px solid var(--tinta);
  outline-offset: 3px;
}

/* La vista grande solo se cierra con clic cuando está ampliada a propósito;
   antes de lanzar la pregunta no hay nada a lo que volver. */
.ingreso--ampliado {
  cursor: zoom-out;
}

.ingreso__pista {
  margin: 0;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--tinta-suave);
  text-align: center;
}

.ingreso__pista--cerrar {
  font-size: 0.9rem;
  letter-spacing: 0.06em;
}

/* Antes de lanzar la pregunta no se puede volver a ninguna nube: la pista de
   cierre solo tiene sentido cuando el QR se amplió desde la esquina. */
.ingreso--grande:not(.ingreso--ampliado) .ingreso__pista--cerrar {
  display: none;
}

@media (max-height: 620px) {
  .ingreso--esquina .ingreso__pista {
    display: none;
  }
}

/*
 * En modo nocturno la tarjeta del QR NO se invierte. Un QR claro sobre oscuro
 * es poco fiable para muchas cámaras, y ese QR es la única puerta de entrada a
 * la sala: no se arriesga por estética. Queda como un recuadro claro sobre el
 * fondo oscuro, que además lo destaca más.
 */
:root[data-tema="oscuro"] .ingreso {
  background: #ffffff;
  color: #111111;
}

:root[data-tema="oscuro"] .ingreso .ingreso__pie,
:root[data-tema="oscuro"] .ingreso .url-sala {
  color: #4a4a4a;
}

/* Mientras se escribe la pregunta, el QR se corre hacia abajo para dejarle
   sitio al diálogo en vez de quedar debajo de él. */
body.pidiendo .ingreso--grande {
  padding-top: 15rem;
}

body.pidiendo .ingreso--grande .qr {
  width: min(30vh, 30vw);
}

body.pidiendo .ingreso--grande .codigo-grande {
  font-size: clamp(2rem, 6vh, 3.5rem);
}

/* Ventana baja (el portátil antes de conectar el proyector, o la barra partida
   en dos líneas): la tarjeta del QR se compacta para seguir cabiendo entera en
   el lienzo. Si no cabe, el `overflow: hidden` del lienzo la recorta y el QR
   desaparece — el mismo fallo de siempre entrando por otra puerta. */
@media (max-height: 620px) {
  .ingreso--esquina {
    padding: 0.5rem;
    gap: 0.25rem;
  }

  .ingreso--esquina .qr {
    width: 72px;
    min-width: 72px;
  }

  .ingreso--esquina .codigo-grande {
    font-size: 1.05rem;
  }

  .ingreso--esquina .ingreso__pie {
    display: none;
  }
}

.qr {
  display: block;
}

.ingreso--grande .qr {
  width: min(46vh, 46vw);
}

.ingreso--esquina .qr {
  width: 11vh;
  min-width: 88px;
}

.qr svg {
  display: block;
  width: 100%;
  height: auto;
}

.ingreso__pie {
  margin: 0;
  text-align: center;
  color: var(--tinta-suave);
  font-size: 0.95rem;
}

.ingreso--esquina .ingreso__pie {
  font-size: 0.75rem;
}

.codigo-grande {
  font-size: clamp(2.5rem, 8vh, 5rem);
  font-weight: 800;
  letter-spacing: 0.18em;
  margin: 0;
  line-height: 1;
}

.ingreso--esquina .codigo-grande {
  font-size: 1.5rem;
  letter-spacing: 0.12em;
}

.url-sala {
  font-size: clamp(1rem, 2.4vh, 1.5rem);
  color: var(--tinta-suave);
  margin: 0;
  word-break: break-all;
  text-align: center;
}

/* --- Avisos a pantalla completa ----------------------------------------- */

.aviso-grande {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  background: var(--papel);
  text-align: center;
  padding: 2rem;
}

.aviso-grande strong {
  font-size: clamp(2rem, 9vh, 6rem);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.aviso-grande span {
  font-size: clamp(1rem, 3vh, 1.75rem);
  color: var(--tinta-suave);
}

/* --- Panel de conteos ---------------------------------------------------- */

/* Espeja la tarjeta del QR, en la esquina opuesta. El tamaño manda cuál se
   repitió más; este panel dice cuántas veces. */
.conteos {
  padding: 0.75rem 1rem;
  background: var(--papel);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  /* Cede espacio antes que el QR: el QR es la puerta de entrada a la sala y los
     conteos son información secundaria. */
  min-width: 0;
  flex: 0 1 auto;
  overflow: hidden;
}

.conteos h2 {
  margin: 0 0 0.5rem;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--tinta-suave);
  font-weight: 700;
}

.conteos ol {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.3rem;
}

.conteos li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.25rem;
  font-size: clamp(0.95rem, 2.2vh, 1.35rem);
  line-height: 1.2;
}

.conteos li span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
}

.conteos li b {
  font-variant-numeric: tabular-nums;
  color: var(--tinta-suave);
}

@media (max-height: 620px) {
  .conteos {
    padding: 0.5rem 0.75rem;
  }

  .conteos li {
    font-size: 0.9rem;
  }
}

/* --- Estado de red ------------------------------------------------------- */

.estado-red {
  position: fixed;
  left: 1rem;
  bottom: 1rem;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.9rem;
  border-radius: 999px;
  background: var(--alerta);
  color: var(--papel);
  font-size: 0.9rem;
  font-weight: 600;
  z-index: 20;
}

/* --- Barra de moderación ------------------------------------------------- */

.moderacion {
  position: fixed;
  left: 50%;
  bottom: 1.5rem;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 1rem;
  background: var(--tinta);
  color: var(--papel);
  border-radius: var(--radio);
  z-index: 30;
  max-width: calc(100vw - 2rem);
}

.moderacion p {
  margin: 0;
  font-size: 1rem;
}

.moderacion .boton {
  border-color: var(--papel);
  background: transparent;
  color: var(--papel);
}

.moderacion .boton--peligro {
  border-color: var(--alerta);
  background: var(--alerta);
}

/* --- Diálogo de pregunta ------------------------------------------------- */

/*
 * El diálogo se ancla arriba y no oscurece la pantalla: mientras el profesor
 * escribe la pregunta, los alumnos ya tienen que poder escanear el QR. El
 * `pointer-events: none` del velo es parte de lo mismo — sin él, la capa
 * seguiría interceptando el QR aunque se vea.
 */
.velo {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 1.5rem;
  background: transparent;
  pointer-events: none;
  z-index: 40;
}

.dialogo {
  background: var(--papel);
  border: 1px solid var(--tinta);
  border-radius: var(--radio);
  box-shadow: 0 14px 44px rgb(0 0 0 / 22%);
  padding: 1.5rem;
  width: min(40rem, 100%);
  display: grid;
  gap: 1rem;
  pointer-events: auto;
}

.dialogo h2 {
  margin: 0;
  font-size: 1.25rem;
}

.dialogo textarea {
  font: inherit;
  font-size: 1.25rem;
  padding: 0.75rem;
  border: 1px solid var(--tinta);
  border-radius: var(--radio);
  resize: vertical;
  min-height: 5.5rem;
  width: 100%;
}

.dialogo__acciones {
  display: flex;
  gap: 0.75rem;
  justify-content: flex-end;
}

.dialogo__error {
  margin: 0;
  color: var(--alerta);
  font-weight: 600;
}

/* --- Pantalla del alumno ------------------------------------------------- */

.alumno {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  max-width: 30rem;
  margin: 0 auto;
  padding: 1.5rem 1.25rem 3rem;
}

.alumno__marca {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--tinta-suave);
  margin: 0;
}

.alumno__pregunta {
  font-size: 1.5rem;
  line-height: 1.3;
  font-weight: 700;
  margin: 0;
}

.bloque {
  display: grid;
  gap: 1.25rem;
}

.campos {
  display: grid;
  gap: 0.75rem;
}

.campos label {
  display: grid;
  gap: 0.35rem;
  font-size: 0.875rem;
  color: var(--tinta-suave);
}

.campos input {
  font: inherit;
  font-size: 1.25rem;
  padding: 0.85rem;
  border: 1px solid var(--tinta);
  border-radius: var(--radio);
  width: 100%;
}

.campos input:focus-visible {
  outline: 3px solid var(--tinta);
  outline-offset: 1px;
}

.alumno .boton {
  width: 100%;
  padding: 1rem;
  font-size: 1.125rem;
}

.mensaje {
  padding: 1rem;
  border-radius: var(--radio);
  border: 1px solid var(--linea);
  background: var(--superficie);
  margin: 0;
  line-height: 1.5;
}

.mensaje--error {
  border-color: var(--alerta);
  color: var(--alerta);
  background: var(--papel);
  font-weight: 600;
}

.mensaje--exito {
  border-color: var(--exito);
  color: var(--exito);
  background: var(--papel);
  font-weight: 600;
}

.entrada-codigo {
  display: grid;
  gap: 0.75rem;
}

.entrada-codigo input {
  font: inherit;
  font-size: 2rem;
  font-weight: 700;
  letter-spacing: 0.3em;
  text-align: center;
  text-transform: uppercase;
  padding: 0.75rem;
  border: 1px solid var(--tinta);
  border-radius: var(--radio);
  width: 100%;
}

.pie {
  color: var(--tinta-suave);
  font-size: 0.875rem;
  line-height: 1.5;
  margin: 0;
}

/* --- Panel de lectura ----------------------------------------------------- */

/*
 * Anclado arriba y acotado en alto, nunca a sangre. La franja inferior es del
 * QR y de los conteos: un panel `inset: 0` los tapa, que es exactamente el
 * fallo que apareció publicado. Y su z-index queda por debajo del de
 * `.ingreso--grande` (2), así que la vista ampliada del QR siempre gana.
 */
.lectura {
  position: absolute;
  top: 1.5rem;
  left: 50%;
  translate: -50% 0;
  width: min(46rem, 92%);
  max-height: 55dvh;
  overflow: auto;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: 1.5rem 1.75rem;
  background: var(--papel);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  box-shadow: 0 8px 32px rgb(0 0 0 / 18%);
  cursor: pointer;
  text-align: left;
}

.lectura:focus-visible {
  outline: 3px solid var(--tinta);
  outline-offset: 2px;
}

.lectura h2 {
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--tinta-suave);
}

/* Grande porque se lee desde la última fila, igual que la nube. */
#lectura-texto {
  font-size: clamp(1.05rem, 2.4vh, 1.6rem);
  line-height: 1.5;
  color: var(--tinta);
  text-wrap: pretty;
}

/* De cuántas respuestas salió la lectura que se está viendo. Va entre el texto
   y la pista, con una línea encima que la separa sin encerrarla en una caja. */
.lectura__pie {
  font-size: 0.85rem;
  color: var(--tinta-suave);
  padding-top: 0.6rem;
  border-top: 1px solid var(--linea);
}

.lectura__pista {
  font-size: 0.8rem;
  color: var(--tinta-suave);
}

.lectura--error #lectura-texto {
  color: var(--alerta);
}
