/* Rotermeller web — la piel de las maquetas del 5-sep, no una parecida.
 *
 * **Los colores están medidos de `diseno/referencias/`, no elegidos a ojo**: filtrando
 * por tono y saturación sobre las seis imágenes, que es lo único que acierta (un
 * muestreo por punto cae en el antialias o en la ilustración). Acento `#6C3DF2` con
 * 105.366 px en H 256; fondo `#F5F3FE`; cápsula del item activo `#EBE5FD`.
 *
 * **La derivación del acento se ha quedado como estaba y da la piel casi exacta**: el
 * `mezclar(blanco, acento, k)` de `tema.js` —portado de `Tema.swift`— produce con el
 * morado #F5F1FE de fondo (medido #F5F3FE) y #EAE4FD de cápsula (medido #EBE5FD). Uno y
 * dos puntos de 255 en un canal: por debajo de lo que se ve, y a cambio el selector de
 * acento sigue funcionando en vez de haber cableado seis hex a mano.
 *
 * El resto de valores sigue saliendo de `Compartido/Tema.swift`: tinta 161A24, radios
 * y sombras muy suaves (nada de manchas oscuras bajo las tarjetas). El acento lo escribe
 * `tema.js` en el `:root` porque lo elige el alumno y de él se derivan fondo y superficies.
 *
 * Sin build, sin CDN, sin fuentes de fuera: la CSP del vhost no las dejaría cargar y
 * además una web que espera a un servidor ajeno para pintar texto no es instantánea. */

:root {
  /* **El lila de Rotermeller, disponible en toda la web.**
   *
   * Estos tokens existían SÓLO dentro de `.lamina`, que tiene su paleta fija a propósito.
   * Todo lo que se escribió fuera usando `var(--p)` o `var(--p-soft)` —la tarjeta de espera,
   * el selector de tipo, el taller, las miniaturas, el paso de apartado— se pintaba **sin
   * color**: los rótulos salían grises y los discos de las flechas, transparentes. Se vio el
   * 6-sep en la navegación entre apartados.
   *
   * `.lamina` conserva su propia copia más abajo: la lámina es material que se imprime y se
   * reconoce, y no puede cambiar de color aunque estos tokens cambien algún día. */
  --p: #7657F6; --p-dark: #5034D9; --p-med: #9278FF;
  --p-soft: #F1EDFF; --p-xsoft: #F8F6FF;
  --t1: #151426;

  --acento: #FF594D;
  --acento-texto: #FFFFFF;
  --acento-suave: #FFE7E5;
  --fondo: #F7F6F2;
  --superficie: #FFFFFF;
  --tinta: #161A24;
  --secundario: #77777F;
  --inactivo: #66696F;
  /* La línea de dentro de las tarjetas, medida entre dos filas de «Tus tareas de hoy»:
   * #F7F5F8. Es lila y clarísima, no el gris cálido de la app. */
  --divisor: #EFEDF7;
  --amarillo: #FFD76A;
  --ok: #159B5B;
  --aviso: #E0680E;
  --peligro: #DC2B3F;

  --r-pequeno: 14px;
  --r-medio: 20px;
  --r-grande: 26px;
  --capsula: 999px;

  --e-xs: 4px;
  --e-sm: 8px;
  --e-md: 16px;
  --e-lg: 24px;
  --e-xl: 32px;

  /* Sombra teñida de morado, no negra: sobre un fondo lila una sombra gris se ve sucia.
   * Es lo que hace que la tarjeta se despegue del fondo **sin necesitar borde** — que es
   * como están en las maquetas (barrido del borde de una tarjeta: el lila pasa a blanco
   * sin ninguna línea en medio). */
  --sombra-tarjeta: 0 1px 2px rgba(76,40,160,.04), 0 8px 24px rgba(76,40,160,.06);
  --sombra-flotante: 0 10px 34px rgba(76,40,160,.16);

  /* `ui-rounded` es la SF Rounded del sistema en Apple, que es la que usa la app. Fuera
   * de Apple no existe y cae en la del sistema, que es lo correcto: mejor la fuente
   * nativa que descargar una web font de 80 KB para imitar una que ya está instalada. */
  --tipo: ui-rounded, "SF Pro Rounded", system-ui, -apple-system, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, sans-serif;

  --barra: 64px;         /* alto de la barra inferior en móvil */
  --lateral: 250px;      /* ancho de la barra lateral (medido: 243-258 en las 6 maquetas) */
  /* Ancho de la columna derecha, medido en las doce maquetas por el canal de lila entre
   * las dos columnas: 325 · 341 · 347 · 348 · 387 · 388 · 388 px en las que la llevan
   * estrecha. `hoy` es la excepción (609 px, casi mitad y mitad) y por eso existe
   * `.columnas.par` en vez de haber puesto un porcentaje que no cuadra en ninguna. */
  --lado: 360px;
  --marco: 36px;         /* aire entre la barra lateral y el contenido (medido ~30-45) */

  /* Los rellenos pastel de las pastillas de estadística, medidos uno a uno dentro de su
   * recuadro en `hoy.png`. No se derivan del acento: en la maqueta son cuatro familias
   * de tono distintas (rosa, lila, verde, naranja) y derivarlas daría cuatro lilas. */
  --past-rosa: #F7ECF8;    --past-rosa-tinta: #A3419F;
  --past-lila: #F1EEFE;    --past-lila-tinta: #633FF7;
  --past-verde: #E9F8EE;   --past-verde-tinta: #26A24C;
  --past-naranja: #FEF3EA; --past-naranja-tinta: #FE8522;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--fondo);
  color: var(--tinta);
  font-family: var(--tipo);
  font-size: 16px;
  line-height: 1.45;
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
}

/* El teclado del móvil y la barra de Safari cambian el alto: `100vh` deja un hueco o
 * corta. `dvh` es lo que mide la ventana de verdad en cada momento. */
body { min-height: 100dvh; }

button, input, textarea, select { font: inherit; color: inherit; }
button { cursor: pointer; }
a { color: var(--acento); text-decoration: none; }

/* Se quita el contorno del navegador SOLO para el ratón: quitarlo también al teclado
 * deja la web imposible de recorrer con Tab, que es como la usa quien no puede usar
 * ratón. `:focus-visible` es exactamente esa distinción. */
:focus { outline: none; }
:focus-visible { outline: 2px solid var(--acento); outline-offset: 2px; border-radius: 6px; }

/* Quien ha pedido menos movimiento en su sistema no quiere las transiciones de nadie. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ------------------------------------------------------------------ armazón */
/*
 * Tres piezas, las mismas en las seis maquetas: **barra lateral blanca · barra superior
 * (buscador, campana, avatar) · dos columnas**. En el móvil no hay ninguna de las tres:
 * la barra lateral se sustituye por la de abajo, la superior desaparece y las dos
 * columnas se apilan. Las maquetas son sólo de escritorio y el móvil de hoy funciona;
 * lo que no se puede hacer es romperlo por copiar un diseño que no lo contempla.
 */

.app {
  display: grid;
  grid-template-columns: 1fr;
  min-height: 100dvh;
  /* Por lo mismo que `.contenido`: sin esto la propia rejilla crece con su contenido. */
  min-width: 0;
}
.app > * { min-width: 0; }

.lateral { display: none; }

.marco {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.contenido {
  /* **`min-width: 0` no es opcional aquí.** Un hijo de una rejilla (o de un flex) tiene
   * `min-width: auto`, o sea que se niega a encogerse por debajo del ancho mínimo de su
   * contenido: la rejilla del Horario (756 px) estiraba la PÁGINA entera en vez de
   * desplazarse dentro de su caja, y en el móvil todo salía cortado por la derecha.
   * Medido: 807 px de página en una ventana de 390. */
  min-width: 0;
  padding: var(--e-md);
  /* Hueco para la barra de abajo + el área segura del iPhone. Sin `safe-area` la última
   * fila de una lista queda debajo de la barra de gestos y no se puede tocar. */
  padding-bottom: calc(var(--barra) + env(safe-area-inset-bottom) + var(--e-lg));
  width: 100%;
}

@media (min-width: 900px) {
  /* **El blanco de la barra lateral se pinta en la rejilla, no en la barra.** La barra es
   * `sticky` y mide `100dvh`, así que en cualquier página más alta que la ventana su blanco
   * se acababa a media página y debajo quedaba una columna de lila: se leía como si la
   * barra estuviera cortada. Pintando la columna en el fondo de `.app`, el blanco llega
   * hasta abajo del todo sin que la barra tenga que crecer ni dejar de ser pegajosa. */
  .app {
    grid-template-columns: var(--lateral) 1fr;
    background: linear-gradient(to right,
      var(--superficie) 0 var(--lateral), var(--fondo) var(--lateral));
  }
  /* **La barra no desplaza: desplaza su lista de enlaces.** Con `overflow-y:auto` en
   * `.lateral`, el pie (chip de sincronía + Modo foco) se iba con el desbordamiento:
   * medido, el contenido pide 1127 px y hacía falta una ventana de **1113 px de alto**
   * para que el chip llegara a verse. En una de 913 quedaba 133 px por debajo del corte,
   * dentro de un scroll que nadie desplaza — o sea, invisible siempre. Con `overflow:
   * hidden` aquí y el scroll en `.lateral-enlaces`, lo que sobra se lo come la lista y el
   * pie se queda clavado abajo a cualquier alto. */
  .lateral {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--e-lg) 14px var(--e-md);
    background: transparent;   /* lo pinta `.app`, ver arriba */
    position: sticky;
    top: 0;
    height: 100dvh;
    overflow: hidden;
  }
  /* `min-height: 0` es lo que hace que un hijo de flex pueda encoger por debajo de su
   * contenido; sin él sigue midiendo 1127 px y el pie vuelve a caerse fuera. */
  .lateral-enlaces {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 2px;
    /* La barra de desplazamiento sólo cuando hace falta y sin comerse el ancho útil. */
    scrollbar-width: thin;
    /* **Un divisor puede leerse como «aquí se acaba la lista».** Con el pie clavado
     * abajo, el último enlace visible queda pegado a una línea y las secciones que
     * quedan debajo dejan de existir para quien mira. Este desvanecido dice que hay
     * más: se apaga solo al llegar al fondo, y **si la lista cabe entera la línea de
     * tiempo no existe** y `--fundido` se queda en 0 — o sea, no hay nada que fundir
     * cuando no hay nada debajo. Donde no haya animaciones por scroll, tampoco: se ve
     * la lista tal cual, que es el estado bueno. */
    mask-image: linear-gradient(to bottom, #000 calc(100% - var(--fundido)), transparent);
    animation: fundido-enlaces linear both;
    animation-timeline: scroll(self block);
  }
  @keyframes fundido-enlaces {
    from { --fundido: 26px; }
    to   { --fundido: 0px; }
  }
  .lateral-pie {
    flex: none;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding-top: 12px;
    margin-top: 8px;
    /* Un divisor separa el pie de la lista: sin él, con la lista desplazada, el último
     * enlace y el chip se leen como la misma cosa. */
    border-top: 1px solid var(--divisor);
  }
  /* **Sin borde a la derecha.** En las maquetas el blanco de la barra se recorta contra
   * el lila del fondo y no hay línea: una de 1 px la ensucia y se ve en la captura. */
  /* **La barra superior comparte caja con el contenido.** Es hermana suya dentro de
   * `.marco`, no hija, así que no heredaba ni el relleno ni el ancho máximo: medido, el
   * contenido iba de 250 a 1670 y la barra de 250 a **1712**, o sea el buscador y el
   * avatar pegados al borde de la ventana. Y `.contenido` tampoco estaba centrado: con
   * `max-width: 1420` en una ventana ancha dejaba 42 px muertos a un lado.
   *
   * Las dos medidas van juntas a propósito: si se separan, vuelven a descuadrarse. */
  .contenido, .superior {
    padding-inline: var(--marco);
    max-width: 1420px;    /* el ancho útil de las maquetas (1672 − 250 − 2×36) */
    width: 100%;
    margin-inline: auto;
  }
  .contenido { padding-bottom: var(--e-xl); }
  /* Ojo: esconder aquí la barra inferior NO funciona. Su regla `display:flex` está más
   * abajo en este mismo fichero y, a igualdad de especificidad, gana la última — es el
   * mismo fallo que en la Cabina con `/fx.css` cargándose antes del monolito. El
   * `display:none` de escritorio va DESPUÉS de `.barra-inferior`, al final. */
}

/* --------------------------------------------------------------- barra superior */
/*
 * Buscador ancho + campana + avatar, pegados a la derecha y **dentro de la franja del
 * héroe**, que es donde están en las maquetas: no es una barra de sitio propio, flota
 * sobre el lila con la ilustración pasando por detrás.
 *
 * En el móvil no sale. El buscador es global y todavía no se ha decidido qué busca
 * (`diseno/DISENO.md`), así que enseñar una lupa que no hace nada sería peor que no
 * enseñarla; hasta entonces va con `disabled` y su rótulo lo dice.
 */
.superior { display: none; }

@media (min-width: 900px) {
  .superior {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 16px;
    padding: 18px 0 0;
    /* Por encima de la ilustración del héroe, que se le mete por debajo. */
    position: relative;
    z-index: 3;
  }
}

.buscador {
  display: flex;
  align-items: center;
  gap: 10px;
  /* Más ancho que antes: en la maqueta ocupa casi la mitad de la barra, no un rincón. */
  width: min(520px, 38vw);
  padding: 13px 20px;
  border-radius: var(--capsula);
  background: var(--superficie);
  /* **Sombra, no borde.** Con borde se lee como un campo de formulario; con sombra, como
   * la barra de búsqueda que es. Es lo que hace la maqueta. */
  border: 0;
  box-shadow: 0 1px 2px rgba(76,40,160,.04), 0 6px 18px rgba(76,40,160,.06);
  color: var(--secundario);
}
.buscador input { font-size: 15px; }
.buscador svg { flex: none; width: 18px; height: 18px; }
.buscador input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  font-size: 14px;
  color: var(--tinta);
}
.buscador input::placeholder { color: var(--secundario); }
.buscador { position: relative; }

/* El panel de resultados del buscador y el de la campana. Cuelgan de su botón, no del
 * documento: así se colocan solos y desaparecen con él. */
.resultados {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  width: min(380px, 92vw);
  max-height: 60dvh;
  overflow-y: auto;
  padding: 6px;
  border-radius: 16px;
  background: var(--superficie);
  box-shadow: var(--sombra-flotante);
  z-index: 20;
  text-align: left;
  cursor: default;
}
.buscador .resultados { left: 0; right: auto; width: 100%; }
.resultado {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 9px 10px;
  border: 0;
  border-radius: 12px;
  background: transparent;
  text-align: left;
  font: inherit;
  color: inherit;
}
.resultado:hover { background: var(--acento-suave); }
.resultado .crece { display: flex; flex-direction: column; min-width: 0; }
.resultado .titulo {
  font-size: 14px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.resultado .detalle {
  font-size: 12px; color: var(--secundario);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.resultado-vacio { padding: 16px 12px; font-size: 14px; color: var(--secundario); text-align: center; }
.cinta-icono.pequena { width: 30px; height: 30px; border-radius: 9px; }
/* El color del icono dice la urgencia sin necesidad de leer. */
.nivel-peligro .cinta-icono { background: var(--past-rosa); color: var(--past-rosa-tinta); }
.nivel-aviso   .cinta-icono { background: var(--past-naranja); color: var(--past-naranja-tinta); }

/* Campana y avatar: dos círculos del mismo tamaño, que es lo que iguala la fila. */
.redondo {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: 0;
  background: var(--superficie);
  box-shadow: 0 1px 2px rgba(76,40,160,.04), 0 6px 18px rgba(76,40,160,.06);
  color: var(--tinta);
  position: relative;
  flex: none;
}
/* El punto de aviso de la campana. Es `::after` y no un nodo: no tiene que existir para
 * un lector de pantalla, que ya oye el rótulo del botón. */
/* El punto de aviso de la campana. Es `::after` y no un nodo: no tiene que existir para
 * un lector de pantalla, que ya oye el rótulo del botón. Va **arriba a la derecha y
 * grande**, como en la maqueta: un punto de 8 px no se ve al pasar la vista. */
.redondo.avisa::after {
  content: "";
  position: absolute;
  top: 4px; right: 3px;
  width: 13px; height: 13px;
  border-radius: 50%;
  background: #F5333F;
  border: 2.5px solid var(--superficie);
}
.yo {
  width: 52px; height: 52px;
  background: var(--acento);
  color: var(--acento-texto);
  box-shadow: none;
  font-weight: 800;
  font-size: 20px;
}

/* ------------------------------------------------------------------- el héroe */
/*
 * Título enorme, frase de ánimo, la ilustración a la derecha y su bocadillo. La franja
 * **no lleva fondo propio**: se midió y es el mismo lila que el resto de la página
 * (#F3EFFD contra #F4F3FA, o sea lo mismo con el ruido del PNG). Lo que la hace parecer
 * una franja es la ilustración y que debajo empiezan las tarjetas blancas.
 */
/* **Dos alturas, porque en las maquetas hay dos héroes.** El compacto —diez pantallas—
 * es sólo título, frase y a veces un botón a la derecha; el grande —`hoy` y `horario`—
 * lleva el saludo enorme y la ilustración entera. En el compacto la cara de Rotermeller
 * no desaparece: se va a la primera tarjeta de la columna derecha, que es donde está en
 * Notas, Asignaturas, Apuntes y Asistencia. */
.heroe {
  position: relative;
  padding: 14px 0 var(--e-lg);
  display: flex;
  align-items: center;
  gap: var(--e-lg);
}
.heroe-texto { align-self: flex-start; padding-top: 6px; }
.heroe.grande h1 { font-size: clamp(32px, 4.2vw, 52px); }
/* **El alto reservado sólo donde hay ilustración que reservar.** Puesto sin condición
 * dejaba en el móvil 200 px de lila vacío bajo el título: ahí la ilustración está oculta
 * (`.heroe-arte` se apaga por debajo de 1180) y el hueco se quedaba igual. */
@media (min-width: 1180px) {
  .heroe.grande { min-height: 200px; padding-top: 6px; }
}
.heroe-accion { margin-left: auto; align-self: center; position: relative; z-index: 2; }
.heroe-texto { flex: 1; min-width: 0; position: relative; z-index: 2; }
.heroe h1 {
  margin: 0;
  font-size: clamp(30px, 3.6vw, 46px);
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.05;
}
.heroe .sub {
  margin: 10px 0 0;
  color: var(--secundario);
  font-size: 17px;
  max-width: 46ch;
}
.heroe .lema { margin: 6px 0 0; font-size: 15px; color: var(--secundario); }

/* La ilustración. **Se sale por arriba con margen negativo, no con `position:absolute`.**
 * En las maquetas la cabeza de Rotermeller llega al borde superior de la página, por
 * detrás de la barra superior — pero el bocadillo va pegado a su izquierda y la cita a su
 * derecha, así que los tres tienen que quedarse en la misma fila y ordenarse solos. Con la
 * ilustración absoluta, el bocadillo se iba al extremo derecho del héroe (se vio en la
 * primera captura) y había que colocarlo también a mano. */
.heroe-arte {
  flex: none;
  z-index: 1;
  pointer-events: none;
  /* El subir por detrás de la barra superior es cosa **del héroe grande**: ahí la cabeza
   * de Rotermeller llega al borde de la página. En el compacto la ilustración es pequeña y
   * va debajo del buscador, así que sólo compensa su propio aire. */
  /* **Nada de margen negativo por abajo.** Lo tenía (-28 px) para «apurar» el héroe, y lo
   * que hacía era sacar el dibujo fuera de su caja: lo que se pinta después —la barra del
   * Horario, la primera tarjeta— va encima y **le cortaba el cuerpo por la mitad**. Por
   * arriba sí sale, que es lo que hace la maqueta, y ahí no hay nada que lo tape. */
  margin: -12px -10px 0 0;
  align-self: flex-start;
}
/* Lo que sube la ilustración del héroe grande por detrás de la barra superior. **Va atado
 * al alto del dibujo, no a un número suelto**: estaba en -78 px, calibrado para una cara de
 * 260 px, y al bajarla a 190 le cortaba la cabeza. Con -20 el dibujo entra entero y sigue
 * solapando la barra, que es lo que hace la maqueta. */
.heroe.grande .heroe-arte { margin-top: -20px; }
/* **NO poner aquí `width: auto`.** `avatar()` pone `width`/`height` de verdad en el `<img>`
 * para reservar el hueco; `width: auto` anula el atributo y entonces manda el tamaño
 * intrínseco del fichero —hasta 1.774 px—, recortado por este `max-height`. Resultado: TODOS
 * los avatares del héroe se pintaban a 260 px pidieran 120 o 130, y por eso se salían de su
 * sitio y pisaban el buscador. No da error ni desborda la página: sólo se ve como «ese
 * dibujo está enorme». Lo caza `mirar.mjs` con el diagnóstico de imágenes. */
.heroe-arte .avatar { max-width: 100%; }
@media (max-width: 1180px) { .heroe-arte { display: none; } }

/* El bocadillo que sale de la ilustración. Blanco, esquina inferior izquierda picuda. */
.bocadillo {
  position: relative;
  align-self: center;
  margin-bottom: 28px;
  z-index: 2;
  background: var(--superficie);
  border: 1px solid var(--divisor);
  border-radius: 14px;
  padding: 10px 14px;
  font-size: 14px;
  line-height: 1.35;
  max-width: 200px;
  box-shadow: var(--sombra-tarjeta);
}
.bocadillo::after {
  content: "";
  position: absolute;
  left: 22px; bottom: -7px;
  width: 12px; height: 12px;
  background: var(--superficie);
  border-right: 1px solid var(--divisor);
  border-bottom: 1px solid var(--divisor);
  transform: rotate(45deg);
}
@media (max-width: 1180px) { .bocadillo { display: none; } }

/* La cita manuscrita de la derecha del héroe. Cursiva de verdad, no una fuente traída
 * de fuera: la CSP no la dejaría y no vale gastar 80 KB en cuatro palabras. */
.cita-heroe {
  position: relative;
  z-index: 2;
  align-self: center;
  font-style: italic;
  font-size: 17px;
  font-weight: 600;
  line-height: 1.35;
  max-width: 190px;
  text-align: center;
}
@media (max-width: 1400px) { .cita-heroe { display: none; } }

/* La página entera de una vista: héroe arriba y, debajo, una o dos columnas. */
.pagina { display: flex; flex-direction: column; min-width: 0; }
/* 20 px entre bloques, no 16. La columna no separa sólo tarjetas iguales: separa
 * secciones distintas —el héroe, la rejilla de fichas, la fila de atajos, el pie— y con
 * 16 px se leían como un bloque apelmazado. */
.principal { min-width: 0; display: flex; flex-direction: column; gap: 20px; }

/* ---------------------------------------------------------------- dos columnas */
/*
 * Contenido a la izquierda y tarjetas de apoyo a la derecha. **Dos proporciones, no
 * una**: cinco maquetas llevan la columna derecha estrecha (medido: empieza en x≈1270
 * de 1672, o sea ~72/28) y `hoy` la lleva casi a la mitad (x≈983, ~51/49) porque ahí
 * cabe la fila de cuatro pastillas. `.columnas.par` es esa segunda.
 */
.columnas { display: grid; gap: var(--e-md); min-width: 0; }
.columnas > * { min-width: 0; }
/* **El `gap` tiene que llegar también al `div` de dentro.** Las vistas construyen su
 * columna derecha como un `div` plano y `pagina()` lo mete dentro del `aside.lado`: el
 * aside acaba con **un solo hijo**, así que su `gap` no separaba nada y las tarjetas
 * quedaban pegadas —el botón «Nueva conversación» tenía 4 px hasta la siguiente—. Medido
 * con `MEDIRCAJA=1`. Con el selector doble vale para las dos formas de montarla. */
.columnas .lado,
.columnas .lado > div { display: flex; flex-direction: column; gap: var(--e-md); }

@media (min-width: 1100px) {
  .columnas { grid-template-columns: minmax(0, 1fr) var(--lado); gap: 30px; }
  .columnas.par { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}

/* **El iPad en vertical no es un móvil grande.** Un iPad mide 744-834 px de ancho en
 * vertical, o sea por debajo del corte de la barra lateral (900) y del de las columnas
 * (1100): se veía todo en una sola columna, con media pantalla vacía a los lados. Desde
 * 820 px caben la columna principal y el lado de 360 sin apretar nada, así que ahí ya se
 * reparte. Por debajo (iPad mini y móviles) sigue en una columna, que es lo correcto.
 *
 * **Y se corta en 899 a propósito**: a partir de 900 entra la barra lateral (250 px), así
 * que con el lado de 360 la columna principal se quedaba en ~270 y se salían de su caja el
 * chip del documento, los trozos del horario y las fichas de nota. De 900 a 1099 mandan la
 * lateral y una sola columna, como antes. */
@media (min-width: 820px) and (max-width: 899px) {
  .columnas { grid-template-columns: minmax(0, 1fr) var(--lado); gap: 20px; }
  .columnas.par { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}

/* **Y en un monitor grande, el contenido no se queda pegado a la izquierda.** A 2560 px la
 * página ocupaba hasta ~2070 y dejaba una franja muerta a la derecha: se lee como si
 * faltara algo. Con un tope y `margin-inline: auto` queda centrado en la zona útil, que es
 * lo que hace cualquier panel a esos anchos. El tope es generoso a propósito: encoger el
 * contenido en pantallas grandes molesta más que el hueco. */
@media (min-width: 1800px) {
  .contenido { max-width: 1600px; margin-inline: auto; }
}

/* --------------------------------------------------------- cabecera de pantalla */
/*
 * La cabecera de las pantallas que aún no tienen héroe. Se queda porque las trece vistas
 * la usan y migrarlas es el paso 3 de la fase; con la piel nueva sólo cambia de tamaño.
 */

.cabecera {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--e-md);
  margin: var(--e-sm) 0 var(--e-lg);
}
.cabecera h1 {
  margin: 0;
  font-size: clamp(28px, 6vw, 36px);
  font-weight: 800;
  letter-spacing: -0.02em;
}
.cabecera .sub {
  margin: 2px 0 0;
  color: var(--secundario);
  font-size: 15px;
}

/* ------------------------------------------------------------------ el panel */

/* El vistazo de arriba. `auto-fit` y no `auto-fill`: con tres baldosas y sitio para
 * cuatro, `auto-fill` deja una columna vacía a la derecha y la fila se ve descuadrada. */
.baldosas {
  display: grid;
  gap: var(--e-sm);
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  margin-bottom: var(--e-md);
}
.baldosa {
  display: flex;
  flex-direction: column;
  gap: 2px;
  text-align: left;
  padding: 14px var(--e-md);
  background: var(--superficie);
  border: 0;
  border-radius: var(--r-medio);
  box-shadow: var(--sombra-tarjeta);
  font: inherit;
  color: inherit;
}
button.baldosa { cursor: pointer; transition: transform .12s ease, box-shadow .12s ease; }
button.baldosa:hover { transform: translateY(-2px); box-shadow: var(--sombra-flotante); }
button.baldosa:active { transform: none; }
.baldosa-alto { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
.baldosa-rotulo {
  font-size: 12px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--secundario);
}
.baldosa-icono { display: flex; color: var(--secundario); }
.baldosa-valor {
  font-size: 30px; font-weight: 800; letter-spacing: -0.03em; line-height: 1.05;
  font-variant-numeric: tabular-nums;
}
.baldosa-pie { font-size: 13px; color: var(--secundario); }

/* El anillo, con su cifra centrada encima. */
.anillo { position: relative; display: grid; place-items: center; flex: none; }
.anillo-centro { position: absolute; text-align: center; line-height: 1.1; }
.anillo-valor { font-size: 26px; font-weight: 800; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; }
.anillo-rotulo { font-size: 12px; color: var(--secundario); margin-top: 2px; }

/* Las barritas de los últimos días. */
.barras { display: flex; align-items: flex-end; gap: 6px; margin-top: var(--e-sm); }
.barra { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; height: 100%; gap: 4px; }
.barra-tallo { border-radius: 6px 6px 3px 3px; }
.barra-pie { font-size: 10px; color: var(--secundario); text-align: center; }

/* El anillo y lo que va a su lado, que en el móvil se pone debajo.
 *
 * **No se llama `.dos`**: ese nombre ya estaba cogido más abajo por una rejilla de dos
 * columnas iguales, y como esa regla va después, ganaba ella — el anillo se quedaba en
 * media tarjeta y las barras llenaban sólo la otra mitad. Parecía un fallo de las
 * barras y era un nombre repetido. */
.anillo-fila { display: flex; gap: var(--e-lg); align-items: center; flex-wrap: wrap; }
.anillo-fila > .crece { flex: 1; min-width: 180px; }

/* ------------------------------------------------------------------ la marca */
/*
 * El logotipo viene sobre blanco y **se cuelga tal cual**: el blanco lo quita
 * `mix-blend-mode: multiply`, que sobre un fondo casi blanco es exacto y conserva el
 * degradado y el antialias. Recortarle un alfa a mano deja siempre halo en los bordes
 * —ya costó un rato en la Cabina— y aquí no hace ninguna falta: la web no tiene tema
 * oscuro, así que el logotipo nunca cae sobre algo que no sea claro.
 */
.logo {
  display: block;
  height: auto;
  max-width: 100%;
  mix-blend-mode: multiply;
}
.logo.centrado { margin-inline: auto; }

/* ------------------------------------------------------------------ avatares */
/*
 * Las caras de Rotermeller. Son ilustraciones recortadas, sin fondo propio: se cuelgan
 * sobre lo que haya y no llevan marco ni sombra —el dibujo ya trae su mancha de color—.
 * La excepción es el banner de Campus, que sí viene con su fondo dibujado dentro.
 */
.avatar.centrado { margin-inline: auto; }
.avatar {
  display: block;
  height: auto;          /* el width/height del atributo reserva el hueco; manda el CSS */
  max-width: 100%;
  flex: none;
  user-select: none;
  -webkit-user-drag: none;
}

/* La cabecera de una pantalla con su cara al lado. La ilustración cede primero: por
 * debajo de 380 px de ancho desaparece antes que dejar el título en dos palabras. */
.cabecera .avatar { margin-bottom: -6px; }
@media (max-width: 380px) { .cabecera .avatar { display: none; } }

/* Una cara dentro de una tarjeta, a la derecha del texto. */
.con-cara { display: flex; align-items: center; gap: var(--e-md); }
.con-cara > .crece { flex: 1; min-width: 0; }

/* ------------------------------------------------------------------ tarjetas */

.tarjeta {
  background: var(--superficie);
  border-radius: var(--r-medio);
  padding: var(--e-md) 18px;
  box-shadow: var(--sombra-tarjeta);
  /* **Sin borde**: medido en las maquetas, el lila del fondo pasa a blanco sin línea. */
  border: 0;
}
.tarjeta + .tarjeta { margin-top: var(--e-md); }
.tarjeta h2 {
  margin: 0 0 var(--e-sm);
  font-size: 16px;
  font-weight: 700;
}

.rejilla {
  display: grid;
  gap: var(--e-md);
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}

/* --------------------------------------------------------------------- filas */

.fila {
  display: flex;
  align-items: center;
  gap: var(--e-md);
  padding: var(--e-sm) 0;
  border-bottom: 1px solid var(--divisor);
  text-align: left;
  width: 100%;
  background: none;
  border-left: 0; border-right: 0; border-top: 0;
}
.fila:last-child { border-bottom: 0; }
.fila .crece { flex: 1; min-width: 0; }
.fila .titulo { font-weight: 600; }
/* Un título largo no puede empujar la fecha fuera de la tarjeta. */
.fila .titulo, .fila .detalle { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fila .detalle { color: var(--secundario); font-size: 14px; }

/* La mancha de color de la asignatura tiñe la fila entera, que es la decisión de diseño
 * de la app: el color es el protagonista, no un punto de 8 pt. Pero **el color nunca va
 * solo**: el nombre de la asignatura acompaña siempre, porque quien no distingue el azul
 * del morado sigue necesitando saber de qué es. */
.pastilla {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: var(--capsula);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
}

.punto { width: 10px; height: 10px; border-radius: 50%; flex: none; }

/* -------------------------------------------------------------------- cifras */

.cifra { display: flex; flex-direction: column; gap: 2px; }
.cifra .valor {
  font-size: 30px;
  font-weight: 800;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.cifra .rotulo { color: var(--secundario); font-size: 13px; }

/* -------------------------------------------------------------------- botones */

.boton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--e-sm);
  padding: 12px 18px;
  border-radius: var(--capsula);
  border: 0;
  background: var(--acento);
  color: var(--acento-texto);
  font-weight: 700;
  transition: transform .12s ease, filter .12s ease;
}
.boton:hover { filter: brightness(1.05); }
.boton:active { transform: scale(.97); }
.boton.suave { background: var(--acento-suave); color: var(--tinta); }
.boton.plano { background: transparent; color: var(--acento); padding: 8px 10px; }
.boton.peligro { background: var(--peligro); color: #fff; }
.boton[disabled] { opacity: .5; pointer-events: none; }

.acciones { display: flex; gap: var(--e-sm); flex-wrap: wrap; }

/* ------------------------------------------------------------------ formulario */

.campo { display: flex; flex-direction: column; gap: 6px; margin-bottom: var(--e-md); }
.campo label { font-size: 14px; font-weight: 600; color: var(--secundario); }
/* **`.aj-campo` va en la misma regla, no en una copia.** El campo del nombre en Ajustes
   se quedó fuera al rehacer la pantalla y salía con el borde negro que pinta el navegador
   por defecto: un recuadro duro en medio de una pantalla de esquinas redondeadas. */
.campo input, .campo textarea, .campo select,
.aj-campo input, .aj-campo textarea, .aj-campo select {
  padding: 12px 14px;
  border-radius: var(--r-pequeno);
  border: 1px solid var(--divisor);
  background: var(--fondo);
  width: 100%;
}
.campo textarea { min-height: 120px; resize: vertical; }
.campo input:focus, .campo textarea:focus, .campo select:focus,
.aj-campo input:focus, .aj-campo textarea:focus, .aj-campo select:focus {
  border-color: var(--acento);
  background: var(--superficie);
}
.dos { display: grid; grid-template-columns: 1fr 1fr; gap: var(--e-md); }
@media (max-width: 520px) { .dos { grid-template-columns: 1fr; } }

/* ------------------------------------------------------------------ estados */

.vacio {
  text-align: center;
  padding: var(--e-xl) var(--e-md);
  color: var(--secundario);
}
.vacio .icono { font-size: 40px; margin-bottom: var(--e-sm); opacity: .5; }
.vacio h3 { margin: 0 0 6px; color: var(--tinta); font-size: 18px; }
.vacio p { margin: 0 auto var(--e-md); max-width: 42ch; }

/* ------------------------------------------------------------- barra inferior */

.barra-inferior {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  display: flex;
  background: rgba(255,255,255,.92);
  backdrop-filter: saturate(180%) blur(20px);
  border-top: 1px solid var(--divisor);
  padding-bottom: env(safe-area-inset-bottom);
  z-index: 40;
}
.barra-inferior a {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  height: var(--barra);
  color: var(--inactivo);
  font-size: 11px;
  font-weight: 600;
}
.barra-inferior a.activo { color: var(--acento); }
.barra-inferior svg { width: 22px; height: 22px; }

/* Aquí, después de las reglas de la barra, y no en el `@media` de arriba: si no, la
 * `display:flex` de dos líneas más arriba lo pisa y la barra de móvil sale también en
 * escritorio, tapando el pie de todas las listas. */
@media (min-width: 900px) {
  .barra-inferior { display: none; }
}

/* --------------------------------------------------------------- barra lateral */

/* La marca de arriba: la carita, el nombre y «Tu profe particular» debajo. En las
 * maquetas conviven las dos formas —en `hoy` y `horario` el nombre va escrito al lado de
 * la carita, en `tareas` y `estudio` es el logotipo dibujado—. Se usa el logotipo, que es
 * la marca de verdad; el nombre en negrita de la tipografía del sistema no lo es. */
.lateral-marca {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 10px var(--e-sm);
}
.lateral > .lema {
  font-size: 12px;
  color: var(--secundario);
  padding: 0 10px var(--e-md);
  margin-top: -2px;
}

.navitem {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-radius: var(--r-pequeno);
  color: var(--tinta);
  font-weight: 600;
  font-size: 15px;
}
.navitem:hover { background: var(--fondo); }
/* La cápsula lila del item activo. Medida: #EBE5FD, que es justo lo que da la derivación
 * del acento (#EAE4FD) — por eso no va cableada. */
.navitem.activo { background: var(--acento-suave); color: var(--acento); font-weight: 700; }
.navitem svg { width: 20px; height: 20px; flex: none; }
.navgrupo {
  margin: var(--e-md) 0 var(--e-xs);
  padding: 0 14px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--secundario);
  font-weight: 700;
}

/* El alto del desvanecido del pie de la lista de enlaces. Registrado con `@property`
 * porque una variable sin tipo **no se puede animar**: salta de un valor a otro. */
@property --fundido {
  syntax: "<length>";
  inherits: false;
  initial-value: 0px;
}

/* ------------------------------------------------------------ estado de sincronía */
/*
 * **Una web que sincroniza sin decirlo obliga a fiarse.** En las maquetas es el chip de
 * abajo del todo («● Al día · ¡Vas genial!» con su chevron), así que aquí el estado real
 * de la sincronía ocupa ese sitio en vez de inventarse un rótulo de ánimo fijo: dice lo
 * que pasa de verdad y encima se puede pulsar para forzar una vuelta.
 */

.sincro {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  /* Antes `margin-top: auto`, que no hacía nada: sin espacio libre computa 0, y encima el
   * chip no era el último de la barra (Modo foco iba después). Lo de pegarlo abajo lo
   * resuelve ahora `.lateral-pie`. */
  padding: 10px 12px;
  border-radius: var(--r-pequeno);
  border: 1px solid var(--divisor);
  background: var(--superficie);
  text-align: left;
  font-size: 13px;
  color: var(--tinta);
}
.sincro:hover { border-color: var(--acento); }
.sincro .luz { width: 10px; height: 10px; border-radius: 50%; background: var(--ok); flex: none; }
.sincro .crece { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.sincro .titulo { font-weight: 700; font-size: 13px; line-height: 1.25;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sincro .detalle {
  font-size: 11px; color: var(--secundario); line-height: 1.25;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sincro .girar { color: var(--secundario); flex: none; display: flex; }
.sincro:hover .girar { color: var(--acento); }
/* Mientras sincroniza, la flecha gira: es lo que dice que el botón hizo algo. */
.sincro.sincronizando .girar { animation: girar 1.1s linear infinite; }
@keyframes girar { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .sincro.sincronizando .girar { animation: none; }
}
.sincro.sincronizando .luz { background: var(--acento); animation: latir 1s ease-in-out infinite; }
.sincro.error .luz, .sincro.sinRed .luz { background: var(--aviso); }
@keyframes latir { 50% { opacity: .25; } }

/* ----------------------------------------------------------------------- hojas */
/*
 * El marco de los siete editores. Tres decisiones que valen para todos:
 * cabecera con icono y una frase que dice para qué sirve · cuerpo que se desplaza solo ·
 * **pie fijo**, porque antes «Guardar» era la última fila del formulario y en un editor
 * largo había que bajar hasta el fondo para descubrir que existía.
 */

.velo {
  position: fixed;
  inset: 0;
  background: rgba(28, 18, 60, .38);
  backdrop-filter: blur(3px);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 60;
}
@media (min-width: 700px) { .velo { align-items: center; padding: 24px; } }

.hoja {
  background: var(--superficie);
  width: min(560px, 100%);
  max-height: 92dvh;
  display: flex;
  flex-direction: column;
  border-radius: var(--r-grande) var(--r-grande) 0 0;
  box-shadow: 0 24px 60px rgba(28,18,60,.28);
  overflow: hidden;
}
@media (min-width: 700px) { .hoja { border-radius: 22px; } }

.hoja-alto {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 20px 20px 16px;
  border-bottom: 1px solid var(--divisor);
}
.hoja-alto h2 { margin: 0; font-size: 19px; font-weight: 800; letter-spacing: -0.02em; }
.hoja-sub { margin: 3px 0 0; font-size: 13px; color: var(--secundario); }
.hoja-cerrar { width: 34px; height: 34px; color: var(--secundario); }
.hoja-cerrar:hover { color: var(--tinta); border-color: var(--acento); }

.hoja-cuerpo { padding: 20px; overflow-y: auto; flex: 1; min-height: 0; }
/* El último campo no necesita su margen: el pie ya trae su propio aire. */
.hoja-cuerpo > *:last-child { margin-bottom: 0; }

.hoja-pie {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 20px;
  border-top: 1px solid var(--divisor);
  background: var(--superficie);
  /* En el móvil, por encima de la barra de gestos. */
  padding-bottom: calc(14px + env(safe-area-inset-bottom));
}
/* «Borrar» como texto rojo y lejos del primario: en botón macizo compite con «Guardar»
 * por la mirada, y es el que no se puede deshacer. */
.boton.plano-peligro {
  background: transparent;
  color: var(--peligro);
  padding: 10px 12px;
}
.boton.plano-peligro:hover { background: var(--past-rosa); }

/* --------------------------------------------------------------------- avisos */

.aviso {
  padding: 12px 14px;
  border-radius: var(--r-pequeno);
  background: var(--acento-suave);
  font-size: 14px;
  margin-bottom: var(--e-md);
}
.aviso.mal { background: #FDE7E9; color: #8E1D28; }
.aviso.bien { background: #E4F5EC; color: #0E5D38; }
/* «Atención» no es «mal»: es lo que hay que mirar hoy —un plazo abierto, un temario a
 * medias de bajar— y va en ámbar para que se distinga de un fallo de verdad. El de
 * información se queda con el lila de la casa, que es el `.aviso` de siempre. */
/* Tinta propia y no `--past-naranja-tinta`: ese naranja es para una cifra grande y un
 * icono, y sobre el crema de la pastilla un párrafo entero se queda por debajo del
 * contraste mínimo. */
.aviso.atencion { background: var(--past-naranja); color: #8A4A05; }

/* ------------------------------------------------------------------ utilidades */

.dim { color: var(--secundario); }
.pequeno { font-size: 13px; }
.negrita { font-weight: 700; }
.centrado { text-align: center; }
.entre { display: flex; align-items: center; justify-content: space-between; gap: var(--e-sm); }
.pila { display: flex; flex-direction: column; gap: var(--e-sm); }
.linea { display: flex; align-items: center; gap: var(--e-sm); flex-wrap: wrap; }
.nowrap { white-space: nowrap; }
.tachado { text-decoration: line-through; color: var(--secundario); }

/* Sólo para lectores de pantalla: el rótulo que el diseño resuelve con un icono sigue
 * teniendo que existir para quien no ve el icono. */
.solo-lectores {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Cualquier cosa ancha (una rejilla de horario, una tabla) se desplaza dentro de su
 * caja. El cuerpo de la página no puede desplazarse en horizontal nunca. */
.desliza { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* ============================================================ PIEZAS DE LA PIEL
 *
 * Las cinco piezas que se repiten en las doce maquetas. Van aquí abajo, después de todo
 * lo demás, **a propósito**: a igualdad de especificidad gana la última regla del
 * fichero, así que lo nuevo pisa a lo viejo sin necesidad de un solo `!important`. Es la
 * misma lección que la barra inferior y que `/fx.css` en la Cabina.
 */

/* ------------------------------------------------------- 1) cinta de tarjeta */
/* Icono en cuadrado lila + título + «Ver todas →» a la derecha. */

.cinta {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}
.cinta-icono {
  display: grid;
  place-items: center;
  width: 34px; height: 34px;
  flex: none;
  border-radius: 11px;
  background: var(--acento-suave);
  color: var(--acento);
}
.cinta h2 { margin: 0; font-size: 17px; font-weight: 700; flex: 1; min-width: 0; }
.cinta .vertodas {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 0;
  background: transparent;
  color: var(--acento);
  font-size: 14px;
  font-weight: 600;
  padding: 4px 2px;
  white-space: nowrap;
}
.cinta .vertodas:hover { text-decoration: underline; }

/* -------------------------------------------- 2) pastilla de estadística */
/*
 * Relleno pastel, icono y cifra en la misma línea, rótulo debajo y un pie. Los cuatro
 * tonos están medidos en `hoy.png` (ver `diseno/DISENO.md`): **no se derivan del acento**
 * porque en la maqueta son cuatro familias de tono distintas y derivarlas daría cuatro
 * lilas. Por eso el tono se pide por su nombre y no se calcula.
 */
.estadisticas {
  display: grid;
  gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
.estadistica {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 14px 16px 16px;
  border-radius: 16px;
  background: var(--past-lila);
  color: var(--tinta);
  text-align: left;
  border: 0;
  font: inherit;
}
button.estadistica { cursor: pointer; transition: transform .12s ease; }
button.estadistica:hover { transform: translateY(-2px); }
.estadistica .alto { display: flex; align-items: center; gap: 10px; }
.estadistica .valor {
  font-size: 27px; font-weight: 800; letter-spacing: -0.03em; line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.estadistica .rotulo { font-size: 14px; font-weight: 600; margin-top: 6px; }
.estadistica .pie { font-size: 13px; opacity: .72; }
.estadistica svg { flex: none; }

.estadistica.rosa    { background: var(--past-rosa); }
.estadistica.rosa    .valor, .estadistica.rosa    svg, .estadistica.rosa    .rotulo { color: var(--past-rosa-tinta); }
.estadistica.lila    { background: var(--past-lila); }
.estadistica.lila    .valor, .estadistica.lila    svg, .estadistica.lila    .rotulo { color: var(--past-lila-tinta); }
.estadistica.verde   { background: var(--past-verde); }
.estadistica.verde   .valor, .estadistica.verde   svg, .estadistica.verde   .rotulo { color: var(--past-verde-tinta); }
.estadistica.naranja { background: var(--past-naranja); }
.estadistica.naranja .valor, .estadistica.naranja svg, .estadistica.naranja .rotulo { color: var(--past-naranja-tinta); }

/* --------------------------------------------------- 3) chips de filtro */
/* Barra blanca con las pastillas dentro; la activa en lila con el texto en morado. */

.chips {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 5px;
  border-radius: var(--capsula);
  background: var(--superficie);
  box-shadow: var(--sombra-tarjeta);
  /* Con muchos filtros y poca ventana se desplaza dentro de su caja, que nunca puede
   * empujar el ancho de la página. */
  overflow-x: auto;
  scrollbar-width: none;
}
.chips::-webkit-scrollbar { display: none; }
.chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 15px;
  border: 0;
  border-radius: var(--capsula);
  background: transparent;
  color: var(--tinta);
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
}
.chip:hover { background: var(--fondo); }
.chip.activo { background: var(--acento-suave); color: var(--acento); font-weight: 700; }
.chip .cuenta {
  min-width: 20px;
  padding: 1px 6px;
  border-radius: var(--capsula);
  background: var(--past-lila);
  color: var(--past-lila-tinta);
  font-size: 12px;
  font-weight: 700;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.chip .cuenta.rosa    { background: var(--past-rosa);    color: var(--past-rosa-tinta); }
.chip .cuenta.verde   { background: var(--past-verde);   color: var(--past-verde-tinta); }
.chip .cuenta.naranja { background: var(--past-naranja); color: var(--past-naranja-tinta); }

/* ---------------------------------------- 4bis) la barra de filtros de Tareas */
/*
 * Tres filas como mucho —cajones, día y (plegado) asignatura y prioridad—, cada una con
 * su rótulo a la izquierda. **El rótulo es lo que las separa**: tres tiras de cápsulas
 * sin nada delante se leen como una sola tira larga y no se entiende que sean preguntas
 * distintas. Va con `align-items: center` y no `baseline` porque las cápsulas tienen su
 * propio relleno y el rótulo se descolgaba.
 */
.filtros {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: var(--e-md);
}
.filtros-fila {
  display: flex;
  align-items: center;
  gap: 10px;
  /* Que la tira de chips pueda encogerse y desplazarse por dentro en vez de estirar la
   * fila: sin esto, con doce días la barra empuja el ancho de la página. */
  min-width: 0;
}
.filtros-fila > .chips { min-width: 0; }
.filtros-rotulo {
  flex: none;
  width: 74px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--secundario);
}
/* «Más filtros» va fuera de la cápsula de los cajones —no es un cajón más, es lo que
 * despliega los otros dos—, así que se pinta su propia caja. */
.chip-mas {
  flex: none;
  padding: 8px 14px;
  border: 1px solid var(--divisor);
  background: var(--superficie);
  box-shadow: var(--sombra-tarjeta);
  color: var(--secundario);
}
.chip-mas:hover { background: var(--superficie); border-color: var(--acento); color: var(--acento); }
.chip-mas.activo { background: var(--acento-suave); border-color: transparent; color: var(--acento); }
.chip-mas svg { flex: none; }

/* En ventana estrecha el rótulo se sube encima de sus chips: a 74 px de rótulo más una
 * tira de doce días no queda sitio para leer ninguno de los dos. */
@media (max-width: 900px) {
  .filtros-fila { flex-direction: column; align-items: stretch; gap: 6px; }
  .filtros-rotulo { width: auto; }
  .chip-mas { align-self: flex-start; }
}

/* ---------------------------------------- 4) fila con casilla y chevron */
/*
 * **La casilla es un botón de verdad, no un adorno.** En la maqueta es un círculo vacío
 * que al marcarse se llena de morado con su check; aquí además tiene que poder pulsarse
 * sin abrir la tarea, así que es un `<button>` aparte con su propio rótulo — si fuese
 * parte de la fila, marcar una tarea abriría el editor.
 */
.fila-casilla {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 11px 0;
  border-bottom: 1px solid var(--divisor);
}
.fila-casilla:last-child { border-bottom: 0; }
.casilla {
  width: 26px; height: 26px;
  flex: none;
  border-radius: 50%;
  border: 2px solid #D8D4E6;
  background: var(--superficie);
  display: grid;
  place-items: center;
  color: transparent;
  transition: background .12s ease, border-color .12s ease;
}
.casilla:hover { border-color: var(--acento); }
.casilla.hecha { background: var(--acento); border-color: var(--acento); color: var(--acento-texto); }
.fila-casilla .crece { flex: 1; min-width: 0; }
.fila-casilla .titulo { font-weight: 600; font-size: 15px; }
.fila-casilla .titulo.tachado { color: var(--secundario); }
.fila-casilla .bajo {
  display: flex; align-items: center; gap: 8px;
  margin-top: 4px; font-size: 13px; color: var(--secundario);
}
.fila-casilla .bajo svg { width: 14px; height: 14px; }
.fila-casilla .derecha { color: var(--secundario); font-size: 13px; white-space: nowrap; }
.fila-casilla .chevron { color: #C9C4DA; display: flex; flex: none; }
button.fila-casilla { width: 100%; background: none; border-left: 0; border-right: 0; border-top: 0; text-align: left; }
button.fila-casilla:hover .chevron { color: var(--acento); }

/* ------------------------------------------- 5) tarjeta de ánimo (columna derecha) */
/* La cara de Rotermeller con una frase. Es lo que sustituye a la ilustración del héroe
 * en las diez pantallas de héroe compacto. El dibujo va sobre un disco lila, que es lo
 * que le da borde en la maqueta sin necesidad de recortarlo. */
.animo { display: flex; align-items: center; gap: 14px; }
.animo .disco {
  width: 76px; height: 76px;
  flex: none;
  border-radius: 50%;
  background: var(--acento-suave);
  display: grid;
  place-items: center;
  overflow: hidden;
}
/* El dibujo no es cuadrado y el disco sí: sin `cover` se recorta por un lado y la cara
 * sale descentrada. Con `width/height` al 100 % el atributo del `<img>` deja de mandar. */
.animo .disco .avatar { width: 100%; height: 100%; object-fit: cover; object-position: center top; }
.animo p { margin: 0; font-size: 15px; line-height: 1.4; }

/* ------------------------------------------------------- 6) barra de progreso */
.progreso { height: 8px; border-radius: var(--capsula); background: #EDEAF7; overflow: hidden; }
.progreso > span { display: block; height: 100%; border-radius: var(--capsula); background: var(--acento); }

/* El cuerpo pulsable de la fila con casilla: es hermano de la casilla, no su padre (ver
 * `filaCasilla` en `ui.js`), así que tiene que crecer él y llevar la fila por dentro. */
.cuerpo-fila {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 12px;
  background: none;
  border: 0;
  padding: 0;
  text-align: left;
  font: inherit;
  color: inherit;
}
.cuerpo-fila > .crece { flex: 1; min-width: 0; }
button.cuerpo-fila:hover .titulo { color: var(--acento); }

/* ------------------------------------------- 7) marca de estado e insignia */

/* «En 3 días», «Falta», «Justificada». Tono de la piel, no color de asignatura. */
.marca {
  display: inline-flex;
  align-items: center;
  padding: 5px 12px;
  border-radius: var(--capsula);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  background: var(--past-lila);
  color: var(--past-lila-tinta);
}
.marca.rosa    { background: var(--past-rosa);    color: var(--past-rosa-tinta); }
.marca.verde   { background: var(--past-verde);   color: var(--past-verde-tinta); }
.marca.naranja { background: var(--past-naranja); color: var(--past-naranja-tinta); }

/* Las iniciales de la asignatura en su color, en claro. */
.insignia {
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  flex: none;
  border-radius: 13px;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: -0.02em;
}

/* El detalle por tramos: fecha · hora · aula · peso, cada uno con su iconito. */
.detalle.tramos {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  white-space: normal;
  overflow: visible;
}
.detalle .tramo { display: inline-flex; align-items: center; gap: 5px; }
.detalle .tramo svg { flex: none; }

/* La pastilla de asignatura de las filas de la maqueta ocupa una columna fija a la
 * izquierda, no se pega al título: así los títulos de todas las filas quedan alineados. */
.fila > .pastilla { min-width: 116px; justify-content: center; }
.fila > .chevron { color: #C9C4DA; display: flex; flex: none; }
button.fila:hover > .chevron { color: var(--acento); }

/* La tarjeta de una asignatura, con su color en el borde izquierdo. */
.tarjeta.conborde { border-left: 6px solid var(--acento); }

/* La cifra grande al lado de un anillo (no dentro), como «4 · exámenes próximos». */
.valor-suelto {
  font-size: 30px; font-weight: 800; letter-spacing: -0.03em; line-height: 1.05;
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------ piezas propias de Notas */

/* La tira de tres cifras de `notas.png`: una tarjeta partida en tres con su línea. */
.trozos { display: flex; align-items: center; flex-wrap: wrap; }
.trozo {
  display: flex;
  align-items: center;
  gap: 14px;
  flex: 1;
  min-width: 190px;
  padding: 6px 20px;
}
.trozo + .trozo { border-left: 1px solid var(--divisor); }
.trozo-icono {
  display: grid; place-items: center;
  width: 44px; height: 44px; flex: none;
  border-radius: 50%;
  background: var(--acento-suave);
  color: var(--acento);
}
.trozo-valor {
  font-size: 28px; font-weight: 800; letter-spacing: -0.03em; line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.trozo-rotulo { font-size: 14px; color: var(--secundario); }
/* Con poca ventana la línea vertical entre trozos queda torcida: se apilan. */
@media (max-width: 720px) {
  .trozo + .trozo { border-left: 0; border-top: 1px solid var(--divisor); }
}

.nota-grande { font-size: 26px; font-weight: 800; letter-spacing: -0.02em; flex: none; }

/* La frase de «necesitas un X», con su iconito. */
.pista {
  display: flex; align-items: flex-start; gap: 7px;
  margin: 8px 0 0; color: var(--secundario);
}
.pista svg { flex: none; margin-top: 2px; }

/* Las notas de una asignatura: fichas en rejilla, no filas de lista. */
.notas-sueltas {
  display: grid;
  gap: 10px;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  margin: 12px 0 4px;
}
.ficha-nota {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: 0;
  border-radius: var(--r-pequeno);
  background: var(--fondo);
  text-align: left;
  font: inherit;
  color: inherit;
  min-width: 0;
}
.ficha-nota:hover { background: var(--acento-suave); }
.ficha-nota .ficha-icono { color: var(--secundario); display: flex; flex: none; }
.ficha-nota .crece { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.ficha-nota .titulo {
  font-weight: 600; font-size: 14px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ficha-nota .detalle { font-size: 12px; color: var(--secundario); }
.ficha-nota-valor {
  flex: none;
  padding: 3px 10px;
  border-radius: 9px;
  font-weight: 700;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}

/* `.crece` significa «crece» en CUALQUIER caja flexible, no sólo dentro de una fila o del
 * anillo. Se puso primero como `.linea > .crece` y se quedó corto dos veces: la nota
 * grande de una tarjeta de asignatura se pegaba al nombre en vez de irse al borde
 * derecho, y las barras de «En qué has estudiado» salían **de ancho cero**, o sea
 * invisibles, porque su caja no crecía. Las reglas más específicas de arriba
 * (`.fila .crece`, `.anillo-fila > .crece`) siguen ganando donde hacen falta. */
.crece { flex: 1; min-width: 0; }

/* La columna fija de la pastilla y el detalle en tramos son decisiones **de escritorio**:
 * vienen de alinear los títulos de las maquetas, que son de 1672 px. En un móvil esos
 * 116 px se comen el título ("Parci…") y los cuatro tramos caen en cuatro líneas. Aquí la
 * pastilla vale lo que ocupa y el detalle se aprieta. */
@media (max-width: 900px) {
  /* Y no basta con quitar el ancho fijo: con la pastilla, el título, la marca y el
   * chevron en la misma línea de 390 px, un nombre largo («Programación II») sigue
   * dejando el título en «Parci…». Aquí **el título se lleva la línea entera** y lo demás
   * baja debajo. Va por `order` y no reordenando el DOM: el orden de lectura correcto es
   * el del HTML, y quien navega con teclado o lector de pantalla lo agradece. */
  .fila { flex-wrap: wrap; row-gap: 8px; align-items: flex-start; }
  .fila > * { order: 2; }
  .fila > .crece { order: 1; flex-basis: 100%; }
  .fila > .chevron { order: 3; margin-left: auto; }
  .fila > .pastilla { min-width: 0; }
  .detalle.tramos { gap: 4px 10px; font-size: 12px; }
}

/* ------------------------------------------------ piezas propias de Racha */

.racha-alto { display: flex; align-items: center; gap: var(--e-lg); flex-wrap: wrap; }
.disco-grande {
  display: grid; place-items: center;
  width: 96px; height: 96px; flex: none;
  border-radius: 50%;
  background: var(--acento-suave);
  color: var(--acento);
}
.racha-numero {
  font-size: 54px; font-weight: 800; letter-spacing: -0.04em; line-height: 1;
  font-variant-numeric: tabular-nums;
}
.racha-hoy {
  font-size: 28px; font-weight: 800; letter-spacing: -0.03em;
  color: var(--acento);
  font-variant-numeric: tabular-nums;
}
/* El chip lila de «¡Sigue así! / Cada día suma». */
.animo-chip {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px;
  border-radius: 14px;
  background: var(--acento-suave);
  color: var(--acento);
  flex: none;
}
.animo-chip .dim { color: var(--acento); opacity: .75; }

/* «En qué has estudiado»: nombre, barra y minutos en una línea. El nombre lleva un ancho
 * fijo para que todas las barras empiecen a la vez — si no, la gráfica no se lee. */
.fila-reparto {
  display: flex; align-items: center; gap: 14px;
  padding: 7px 0;
}
.reparto-nombre {
  flex: none; width: 140px;
  font-size: 13px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@media (max-width: 700px) { .reparto-nombre { width: 96px; } }

/* -------------------------------------------- piezas propias de Asignaturas */

/* La parte derecha de una fila de asignatura: la barra de tareas y la media. */
.asig-derecha { display: flex; align-items: center; gap: 18px; flex: none; }
.asig-barra { width: 190px; display: flex; flex-direction: column; gap: 5px; }
.asig-nota {
  font-size: 19px; font-weight: 800; letter-spacing: -0.02em;
  min-width: 46px; text-align: right;
  font-variant-numeric: tabular-nums;
}
/* En una ventana estrecha la barra sobra antes que el nombre de la asignatura. */
@media (max-width: 1000px) { .asig-barra { display: none; } }

/* La variante apretada de la tira de cifras, para cuando va en la columna derecha. */
.trozos.apretados .trozo { padding: 2px 12px; min-width: 0; gap: 0; }
.trozos.apretados .trozo-valor { font-size: 22px; }
.trozos.apretados .trozo-rotulo { font-size: 12px; }

/* ---------------------------------------------- piezas propias de Apuntes */

/* El buscador ancho de la pantalla (no el de la barra superior, que está apagado). */
.busca-fila { display: flex; gap: 12px; margin-bottom: var(--e-md); }
.buscador.ancho { width: 100%; padding: 12px 18px; }
.buscador.ancho input { font-size: 15px; }
/* `entrada()` trae los estilos de `.campo input`; dentro del buscador manda el buscador. */
.buscador input[type="search"] {
  border: 0; background: transparent; padding: 0; border-radius: 0; width: auto;
}

/* Cada apunte es una tarjeta pulsable, no una fila. */
.tarjeta.apunte {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  width: 100%;
  text-align: left;
  font: inherit;
  color: inherit;
  margin-bottom: var(--e-md);
}
.tarjeta.apunte:hover .apunte-titulo { color: var(--acento); }
.apunte-icono {
  display: grid; place-items: center;
  width: 42px; height: 42px; flex: none;
  border-radius: 12px;
}
.apunte-alto { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.apunte-titulo { font-size: 16px; font-weight: 700; }
.apunte-fijado { color: var(--aviso); font-size: 15px; }
.apunte-cuerpo {
  display: block;
  margin-top: 3px;
  color: var(--secundario);
  font-size: 14px;
  /* Dos líneas y corta: el resumen es un anzuelo, no el apunte. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.apunte-pie {
  display: flex; align-items: center; gap: 6px;
  margin-top: 8px; font-size: 13px; color: var(--secundario);
}
.tarjeta.apunte > .chevron { color: #C9C4DA; display: flex; flex: none; align-self: center; }

/* ------------------------------------------------------ 8) mini calendario */

.minimes-alto {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; margin-bottom: 10px;
}
.minimes-titulo { font-weight: 700; font-size: 15px; flex: 1; }
.minimes-flecha {
  display: grid; place-items: center;
  width: 28px; height: 28px; flex: none;
  border: 0; border-radius: 9px;
  background: transparent; color: var(--secundario);
}
.minimes-flecha:hover { background: var(--acento-suave); color: var(--acento); }
.minimes-dias {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
  text-align: center;
}
.minimes-cabecera { font-size: 11px; font-weight: 700; color: var(--secundario); padding-bottom: 4px; }
.minimes-dia {
  position: relative;
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: inherit;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  padding: 0;
}
button.minimes-dia:hover { background: var(--acento-suave); }
.minimes-dia.hoy { background: var(--acento); color: var(--acento-texto); font-weight: 700; }
/* El día elegido del selector de fecha: se lleva el relleno, y «hoy» se queda con un aro.
 * Ver `miniMes(..., { elegido })` — sólo pasa en el selector, no en Calendario. */
.minimes-dia.elegido { background: var(--acento); color: var(--acento-texto); font-weight: 700; }
.minimes.eligiendo .minimes-dia.hoy {
  background: transparent;
  color: var(--acento);
  font-weight: 700;
  box-shadow: inset 0 0 0 1.5px var(--acento);
}

/* ---------------------------------------------- el selector de fecha y hora propio */
/*
 * El campo cerrado se parece a los demás de los editores (misma altura, mismo borde) y no
 * anuncia que es especial: lo que cambia es lo que abre. El botón del calendario va DENTRO
 * del borde, no al lado, porque al lado se lee como dos controles y el que teclea no sabe
 * cuál es el campo.
 */
.selfecha {
  display: flex;
  align-items: center;
  gap: 4px;
  padding-right: 4px;
  border: 1px solid var(--divisor);
  border-radius: var(--r-pequeno);
  background: var(--superficie);
}
.selfecha:focus-within { border-color: var(--acento); }
.selfecha-texto {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  padding: 11px 12px;
  font: inherit;
  font-weight: 600;
  color: var(--tinta);
}
.selfecha-texto:focus { outline: none; }
.selfecha-boton {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px; height: 34px;
  border: 0;
  border-radius: var(--r-pequeno);
  background: transparent;
  color: var(--secundario);
}
.selfecha-boton:hover { background: var(--acento-suave); color: var(--acento); }

/* El panel vive en la capa superior (`popover`), así que se coloca con `fixed` a mano.
 * `margin: 0` porque el `popover` trae márgenes de agente de usuario que descuadran la
 * colocación calculada, e `inset: auto` para que no lo centre él. */
.selfecha-panel {
  position: fixed;
  inset: auto;
  margin: 0;
  z-index: 90;
  width: 300px;
  max-width: calc(100vw - 16px);
  padding: 14px;
  border: 1px solid var(--divisor);
  border-radius: var(--r-medio);
  background: var(--superficie);
  box-shadow: 0 18px 48px rgba(24, 16, 56, .18);
  color: var(--tinta);
}
.selfecha-panel:not([popover]) { display: none; }
.selfecha-panel:not([popover]).visible { display: block; }

.selfecha-atajos { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.selfecha-atajo {
  padding: 6px 11px;
  border: 1px solid var(--divisor);
  border-radius: var(--capsula);
  background: var(--fondo);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--tinta);
}
.selfecha-atajo:hover { border-color: var(--acento); color: var(--acento); }

.selfecha-hora {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--divisor);
}
/* Sin borde arriba cuando la hora es lo único que hay (modo `hora`): una línea que no
 * separa nada de nada se lee como que falta algo encima. */
.selfecha-panel > .selfecha-hora:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.selfecha-rotulo {
  font-size: 12px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--secundario);
}
.selfecha-reloj { display: flex; align-items: center; gap: 4px; }
.selfecha-reloj select { padding: 8px 10px; font-variant-numeric: tabular-nums; }
.selfecha-dosp { font-weight: 800; color: var(--secundario); }

.selfecha-pie { display: flex; justify-content: flex-end; margin-top: 12px; }
.selfecha-listo {
  padding: 8px 18px;
  border: 0;
  border-radius: var(--capsula);
  background: var(--acento);
  color: var(--acento-texto);
  font: inherit;
  font-weight: 700;
}
/* Los puntos van bajo el número, dentro de la celda: fuera desplazan la rejilla entera. */
.minimes-puntos {
  position: absolute;
  bottom: 1px; left: 0; right: 0;
  display: flex; justify-content: center; gap: 2px;
}
.minimes-puntos .punto { width: 4px; height: 4px; }
.minimes-dia.hoy .minimes-puntos .punto { box-shadow: 0 0 0 1px var(--acento-texto); }

/* La leyenda de colores de debajo del mini calendario. */
.leyenda { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-top: 12px; font-size: 12px; }
.leyenda span.linea { gap: 6px; color: var(--secundario); }

/* El porcentaje de asistencia de una fila, al lado de su barra. */
.asig-pct {
  font-size: 14px; font-weight: 700; min-width: 46px; text-align: right;
  font-variant-numeric: tabular-nums; color: var(--secundario);
}
/* El quinto tono: para «sin faltas», que no es ni bueno-verde ni aviso. */
.marca.lima { background: var(--acento-suave); color: var(--acento); }

/* ---------------------------------------------- piezas propias de Estudio */

/* La tarjeta del reloj: enfoque · anillo · ánimo, y los botones debajo. */
.reloj-tres {
  display: flex; align-items: center; justify-content: center;
  gap: var(--e-lg); flex-wrap: wrap;
}
.panel-lado {
  flex: 1; min-width: 200px; max-width: 280px;
  padding: 18px 20px;
  border-radius: var(--r-medio);
  background: var(--fondo);
  display: flex; flex-direction: column; gap: 6px;
}
.panel-lado.derecho { text-align: center; align-items: center; }
.panel-titulo { font-size: 18px; font-weight: 800; letter-spacing: -0.02em; }

/* La tarjeta de la cita, con el fondo lila de la maqueta. */
.tarjeta.cita { background: var(--acento-suave); }
.cita-texto {
  margin: 0; font-style: italic; font-weight: 700; font-size: 16px;
  line-height: 1.35; color: var(--acento);
}

/* El desplegable de la hoja de iconos: cápsula blanca con borde y su chevron. El del
 * navegador a pelo desentona con todo lo demás (se vio en Estudio). El chevron se dibuja
 * con un `background-image` porque `appearance: none` quita también el del sistema. */
select {
  appearance: none;
  -webkit-appearance: none;
  width: 100%;
  padding: 11px 38px 11px 16px;
  border-radius: var(--capsula);
  border: 1px solid var(--divisor);
  background: var(--superficie)
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2377777F' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>")
    no-repeat right 14px center / 16px;
  font-size: 15px;
}
select:focus { border-color: var(--acento); }
/* En un formulario el campo sigue siendo rectangular, como el resto de `.campo`. */
.campo select { border-radius: var(--r-pequeno); background-color: var(--fondo); }

/* La barrita de color de «Próxima clase». */
.barrita { width: 4px; align-self: stretch; min-height: 38px; border-radius: 999px; flex: none; }
/* Una cinta sin título es sólo el icono: en el mini calendario el título ya lo pone el mes. */
.cinta h2:empty { display: none; }

/* ------------------------------------------- piezas propias de Calendario */

.mes-alto { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; }
.mes-titulo { margin: 0; font-size: 19px; font-weight: 800; flex: 1; text-align: center; }
.mes-rejilla { display: grid; grid-template-columns: repeat(7, 1fr); gap: 5px; }
.mes-cabecera {
  text-align: center; padding-bottom: 8px;
  font-size: 12px; font-weight: 600; color: var(--secundario);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mes-dia {
  aspect-ratio: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; padding: 0;
  border: 1px solid var(--divisor);
  border-radius: 12px;
  background: var(--superficie);
  color: var(--tinta);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.mes-dia:hover { border-color: var(--acento); }
.mes-dia.hoy { border: 2px solid var(--acento); font-weight: 800; }
.mes-dia.activo { background: var(--acento); color: var(--acento-texto); border-color: var(--acento); }
/* Con la ventana estrecha los días cuadrados se vuelven ilegibles: se dejan más bajos. */
@media (max-width: 620px) { .mes-dia { aspect-ratio: auto; padding: 10px 0; } }

/* El enlace con flecha de las tarjetas de apoyo («Saber más →», «Ver ayuda →»). */
.enlace-flecha {
  display: inline-flex; align-items: center; gap: 7px;
  color: var(--acento); font-weight: 600; font-size: 14px;
}
.enlace-flecha:hover { text-decoration: underline; }

/* Las muestras de color de Ajustes: círculos en fila, con la elegida marcada. */
.tarjeta [role="radiogroup"] { gap: 12px; }

/* Rótulos de los días: el nombre entero en escritorio, la inicial en el móvil. */
.mes-cabecera .corto { display: none; }
@media (max-width: 780px) {
  .mes-cabecera .largo { display: none; }
  .mes-cabecera .corto { display: inline; }
}

.clase-nombre { font-size: 21px; font-weight: 800; letter-spacing: -0.02em; }

/* ============================================================ REPASO DE LA PIEL
 * Arreglos del repaso del 5-sep, después de mirar las doce pantallas enteras (no sólo lo
 * que cabe en la ventana) y de medir el DOM con `mirar.mjs`.
 */

/* **Doble espaciado.** `.principal` y `.lado` separan sus hijos con `gap`, pero
 * `.tarjeta + .tarjeta` añade encima su `margin-top`: las tarjetas que cuelgan directas de
 * la columna quedaban a 32 px y las que van dentro de un `div` intermedio a 16. Medido con
 * `MEDIR=1 node mirar.mjs`: Hoy daba «32, 32, 16» y Tareas «16, 16, 16…». El margen se
 * queda para las que sí viven dentro de un contenedor sin `gap`. */
.principal > .tarjeta + .tarjeta,
.lado > .tarjeta + .tarjeta { margin-top: 0; }
/* Y la tarjeta de apunte llevaba su propio `margin-bottom`, que sumaba igual. */
.principal > .tarjeta.apunte { margin-bottom: 0; }

/* **La cara del disco salía descabezada.** `object-position: center top` recorta desde el
 * borde de arriba del PNG, que en estas ilustraciones es aire: la cara quedaba en la mitad
 * de abajo y cortada. Se centra en el tercio superior, que es donde está la cabeza. */
.animo .disco { width: 82px; height: 82px; }
/* Tamaño en píxeles, no en `%`: dentro de un `grid` con `place-items:center` el 100 % no
 * se resolvía contra el disco y la imagen salía 12 px más alta, desbordándolo (la recortaba
 * el `overflow`, así que sólo se veía como un encuadre raro). Lo cazó el diagnóstico de
 * imágenes de `mirar.mjs`. */
.animo .disco .avatar { width: 82px; height: 82px; object-position: 50% 22%; }

/* El subtítulo del héroe se partía en dos líneas en las pantallas sin ilustración, donde
 * sobra sitio de largo. Sólo se estrecha cuando hay dibujo que esquivar. */
.heroe .sub { max-width: 68ch; }
.heroe.grande .sub { max-width: 46ch; }

/* Un botón plano al final de una tarjeta se salía del ritmo de sus bordes: su relleno
 * propio lo desplazaba a la izquierda del contenido y añadía aire por abajo. */
.tarjeta > .boton.plano:last-child { margin: 4px 0 -4px -10px; }

/* La gráfica de barras se apoya en una línea base: sin ella, los días sin estudiar
 * flotaban y no se leía dónde empieza la escala. */
.barras {
  border-bottom: 1px solid var(--divisor);
  padding-bottom: 0;
}
.barra-pie { padding-top: 5px; }

/* En el móvil el botón del héroe iba al lado del título y estrujaba el subtítulo a tres
 * líneas de dos palabras. Baja debajo, a lo ancho, que además es donde se toca mejor. */
@media (max-width: 700px) {
  .heroe { flex-wrap: wrap; }
  .heroe-texto { flex: 1 1 100%; }
  .heroe-accion { margin-left: 0; width: 100%; }
  .heroe-accion .boton { width: 100%; }
}

/* ================================================================== EL TUTOR
 * La pantalla de chat. El hilo se desplaza dentro de su tarjeta, no la página: así el
 * campo de escribir se queda siempre a la vista, que es lo que espera cualquiera que
 * haya usado un chat.
 */

.tarjeta.chat { display: flex; flex-direction: column; padding: 0; overflow: hidden; }
.hilo {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 20px;
  /* Alto fijo y desplazamiento propio. `dvh` porque en el móvil la barra de Safari cambia
   * el alto de la ventana y con `vh` el campo se quedaba debajo del teclado. */
  height: min(62dvh, 620px);
  overflow-y: auto;
  scroll-behavior: smooth;
}

.turno { display: flex; align-items: flex-end; gap: 8px; max-width: 82%; }
.turno.de-ella { align-self: flex-start; }
.turno.de-el { align-self: flex-end; flex-direction: row-reverse; }
.turno .cara { flex: none; width: 38px; height: 38px; border-radius: 50%;
  overflow: hidden; background: var(--acento-suave); display: grid; place-items: center; }
.turno .cara .avatar { width: 38px; height: 38px; object-fit: cover; object-position: 50% 22%; }

.burbuja {
  padding: 12px 16px;
  border-radius: 18px;
  background: var(--fondo);
  font-size: 15px;
  line-height: 1.5;
  min-width: 0;
}
.burbuja p { margin: 0; }
.burbuja p + p { margin-top: 10px; }
.de-ella .burbuja { border-bottom-left-radius: 6px; }
.de-el .burbuja {
  background: var(--acento);
  color: var(--acento-texto);
  border-bottom-right-radius: 6px;
}

/* «Está pensando»: tres puntos, no un texto. Un rótulo fijo se lee como un error. */
.burbuja.pensando { display: flex; gap: 5px; align-items: center; padding: 16px; }
.punto-pensando {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--secundario);
  animation: pensar 1.2s ease-in-out infinite;
}
.punto-pensando:nth-child(2) { animation-delay: .18s; }
.punto-pensando:nth-child(3) { animation-delay: .36s; }
@keyframes pensar { 0%, 60%, 100% { opacity: .25; } 30% { opacity: 1; } }

.aviso.reintentar { display: flex; align-items: center; gap: 12px; margin: 0; }

/* El vacío del chat: la cara, qué sabe y cuatro preguntas para empezar. Un chat en blanco
 * con el cursor parpadeando no dice qué se le puede pedir. */
.hilo-vacio { margin: auto; text-align: center; max-width: 46ch; }
.hilo-vacio h2 { margin: 12px 0 6px; font-size: 20px; font-weight: 800; }
.hilo-vacio p { margin: 0; font-size: 15px; }
.sugerencias { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-top: 18px; }
.sugerencia {
  border: 1px solid var(--divisor);
  background: var(--superficie);
  border-radius: var(--capsula);
  padding: 9px 15px;
  font-size: 14px;
  font-weight: 600;
  color: var(--acento);
}
.sugerencia:hover { background: var(--acento-suave); border-color: var(--acento-suave); }

/* La fila de escribir, pegada abajo. */
.escribir-fila {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  padding: 14px 16px;
  border-top: 1px solid var(--divisor);
  background: var(--superficie);
}
.escribir {
  flex: 1;
  min-width: 0;
  resize: none;
  border: 1px solid var(--divisor);
  border-radius: 20px;
  padding: 11px 16px;
  background: var(--fondo);
  font-size: 15px;
  line-height: 1.4;
  max-height: 132px;
}
.escribir:focus { border-color: var(--acento); background: var(--superficie); }
.enviar {
  flex: none;
  display: grid; place-items: center;
  width: 44px; height: 44px;
  border: 0; border-radius: 50%;
  background: var(--acento);
  color: var(--acento-texto);
}
.enviar:hover { filter: brightness(1.06); }

/* ============================================== TEST · EXPLÍCAMELO · LLAMADA */

/* La espera del generador de tests. **No es una barra de progreso de verdad** —no se sabe
 * cuánto queda—, así que se acerca al final sin llegar nunca: prometer un 100 % que no
 * llega es peor que no prometer nada. */
.espera-barra {
  height: 8px; border-radius: var(--capsula); background: var(--acento-suave);
  overflow: hidden; max-width: 360px; margin: 0 auto;
}
.espera-barra > span {
  display: block; height: 100%; width: 4%;
  border-radius: var(--capsula); background: var(--acento);
  transition: width .9s linear;
}

/* Las preguntas del test. */
.enunciado { margin: 0 0 14px; font-size: 16px; font-weight: 600; line-height: 1.45; }
.opciones { display: flex; flex-direction: column; gap: 8px; }
.opcion {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--divisor);
  border-radius: var(--r-pequeno);
  background: var(--superficie);
  text-align: left; font: inherit; color: inherit;
}
.opcion:hover:not(:disabled) { border-color: var(--acento); }
.opcion .letra {
  display: grid; place-items: center;
  width: 26px; height: 26px; flex: none;
  border-radius: 50%;
  background: var(--fondo);
  font-size: 13px; font-weight: 800;
}
.opcion.elegida { border-color: var(--acento); background: var(--acento-suave); }
.opcion.elegida .letra { background: var(--acento); color: var(--acento-texto); }
/* Corregido: la buena siempre en verde, aunque no la eligiera — si sólo se marcase la
 * fallada, el alumno se queda sin saber cuál era. */
.opcion.buena { border-color: var(--ok); background: var(--past-verde); }
.opcion.buena .letra { background: var(--ok); color: #fff; }
.opcion.mala { border-color: var(--peligro); background: var(--past-rosa); }
.opcion.mala .letra { background: var(--peligro); color: #fff; }
.opcion:disabled { cursor: default; }

/* Grabar. El botón es grande a propósito: se usa hablando, a veces de pie. */
.grabar-fila { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin: 4px 0 6px; }
.grabar {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 12px 20px;
  border: 0; border-radius: var(--capsula);
  background: var(--acento); color: var(--acento-texto);
  font-weight: 700;
  position: relative;
}
.grabar.grabando { background: var(--peligro); }
/* El pulso dice «te estoy oyendo» sin un texto que haya que leer. */
.grabar .pulso {
  position: absolute; inset: 0;
  border-radius: var(--capsula);
  box-shadow: 0 0 0 0 rgba(234,31,69,.55);
  animation: pulsar 1.6s ease-out infinite;
}
@keyframes pulsar { to { box-shadow: 0 0 0 14px rgba(234,31,69,0); } }
.crono { font-variant-numeric: tabular-nums; font-weight: 700; font-size: 18px; color: var(--peligro); }

/* Los pasos numerados de las tarjetas de apoyo. */
.paso { display: flex; gap: 12px; align-items: flex-start; padding: 7px 0; }
.paso-n {
  display: grid; place-items: center;
  width: 24px; height: 24px; flex: none;
  border-radius: 50%;
  background: var(--acento-suave); color: var(--acento);
  font-size: 13px; font-weight: 800;
}

/* La llamada. */
.tarjeta.llamada { text-align: center; padding: 34px 20px; }
.llamada-cara {
  width: 168px; height: 168px; margin: 0 auto 18px;
  border-radius: 50%;
  background: var(--acento-suave);
  display: grid; place-items: center;
  overflow: hidden;
  transition: box-shadow .3s ease;
}
.llamada-cara .avatar { width: 168px; height: 168px; object-fit: cover; object-position: 50% 20%; }
.llamada-cara.oyendo { box-shadow: 0 0 0 0 rgba(108,61,242,.45); animation: pulsar-lila 1.8s ease-out infinite; }
.llamada-cara.hablando { box-shadow: 0 0 0 8px var(--acento-suave); }
@keyframes pulsar-lila { to { box-shadow: 0 0 0 22px rgba(108,61,242,0); } }
.llamada-estado { margin: 0; font-size: 22px; font-weight: 800; letter-spacing: -0.02em; }
.llamada-crono { margin: 6px 0 0; font-size: 22px; }

/* La tarjeta de puntuación del test, como en la app: la cara a la izquierda dice el
 * resultado antes de que dé tiempo a leer el número, y la nota a la derecha. */
.tarjeta.puntuacion { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.tarjeta.puntuacion .avatar { flex: none; }
.puntuacion-cifras {
  flex: 1; min-width: 200px;
  display: flex; flex-direction: column; align-items: flex-end; gap: 6px; text-align: right;
}
.cinta-veredicto {
  padding: 6px 14px;
  border-radius: var(--capsula);
  color: #fff;
  font-size: 12px; font-weight: 800; letter-spacing: .08em;
}
.puntuacion-nota {
  font-size: 46px; font-weight: 800; letter-spacing: -0.03em; line-height: 1;
  font-variant-numeric: tabular-nums;
}
.veredicto {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 10px 12px; margin-top: 4px;
  border-radius: 14px;
  background: var(--acento-suave);
  font-size: 13px; text-align: left; line-height: 1.4;
}
.veredicto-estrella {
  display: grid; place-items: center;
  width: 24px; height: 24px; flex: none;
  border-radius: 50%;
  background: var(--acento); color: var(--acento-texto);
}
.titulo-seccion { margin: 6px 0 0; font-size: 17px; font-weight: 800; }

/* ================================================ LAS MAQUETAS NUEVAS (5-sep, 2ª tanda)
 * Tests, Tutor y Explícamelo tú. Lo común: cejilla sobre el título, tarjetas con icono
 * pastel, rejillas de atajos y una columna derecha más rica.
 */

/* La línea pequeña en mayúsculas de encima del título. */
.cejilla {
  margin: 0 0 6px;
  font-size: 12px; font-weight: 700; letter-spacing: .1em;
  color: var(--acento); text-transform: uppercase;
}

/* El saludo al lado del avatar de la barra superior. */
.cuenta {
  display: flex; align-items: center; gap: 10px;
  border: 0; background: transparent; padding: 0; font: inherit; color: inherit;
}
.cuenta-texto { display: flex; flex-direction: column; text-align: left; line-height: 1.25; }
.cuenta-hola { font-size: 15px; font-weight: 800; white-space: nowrap; }
.cuenta-lema { font-size: 12px; color: var(--secundario); white-space: nowrap; }
@media (max-width: 1100px) { .cuenta-texto { display: none; } }

/* Modo foco, al pie de la barra lateral. */
.foco-fila {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 10px 12px;   /* la separación la da el `gap` de `.lateral-pie` */
  border: 0; border-radius: var(--r-pequeno);
  background: transparent; text-align: left; font: inherit; color: inherit;
}
.foco-fila:hover { background: var(--fondo); }
.foco-fila .titulo { font-size: 13px; font-weight: 700; display: block; }
.foco-fila .detalle { font-size: 11px; color: var(--secundario); display: block; }
.interruptor {
  width: 40px; height: 23px; flex: none;
  border-radius: var(--capsula);
  background: #D8D4E6;
  position: relative;
  transition: background .16s ease;
}
.interruptor .bolita {
  position: absolute; top: 3px; left: 3px;
  width: 17px; height: 17px; border-radius: 50%;
  background: #fff;
  transition: transform .16s ease;
}
.interruptor.on { background: var(--acento); }
.interruptor.on .bolita { transform: translateX(17px); }
/* Lo que el modo foco quita: la columna de apoyo y las filas de atajos. */
body.foco .columnas { grid-template-columns: minmax(0, 1fr); }
body.foco .lado, body.foco .accesos, body.foco .cuatro { display: none; }

/* El héroe de Tests. **No es una tarjeta**: en la maqueta es la cabecera de la pantalla,
 * sobre el lila, con la ilustración a la derecha saliéndose por abajo. */
.cabecera-test {
  display: flex; align-items: flex-end; gap: 24px;
  padding: 10px 0 0;
  /* **La ilustración se apoya en el borde de abajo del héroe**, no flota centrada: así el
   * canto recto con el que acaba el dibujo queda pegado al fondo y no se lee como un
   * recorte a media altura, que es lo que se veía. */
}
.cabecera-test-texto { flex: 1; min-width: 0; padding-bottom: 18px; }
.titulo-test {
  margin: 0;
  font-size: clamp(30px, 3.6vw, 46px);
  font-weight: 800; letter-spacing: -0.03em; line-height: 1.05;
}
.titulo-test .acentuado { color: var(--acento); }
/* **El dibujo se desvanece por abajo.** Los avatares del juego son bustos que acaban en un
 * canto recto —están hechos para ir sobre una tarjeta, no sueltos sobre el fondo—, y ese
 * corte a media altura se lee como una imagen mal recortada. Con la máscara se funde con
 * el lila, que es lo que hacen los renders de las maquetas. No hace falta tocar el PNG. */
.cabecera-test-arte {
  flex: none; align-self: flex-end; display: block;
  -webkit-mask-image: linear-gradient(to bottom, #000 72%, transparent 97%);
  mask-image: linear-gradient(to bottom, #000 72%, transparent 97%);
}
@media (max-width: 1000px) { .cabecera-test-arte { display: none; } }

/* Las cuatro tarjetas de «qué sacas de esto». */
/* **Las cuatro fichas.** Icono y título en la misma línea, descripción debajo y la flecha
 * sólo al pasar por encima. La versión anterior tenía el icono arriba a la izquierda, un
 * chevron flotando arriba a la derecha y el texto abajo, con un vacío en medio: se veían
 * descuadradas porque cada descripción ocupa un número distinto de líneas. */
.cuatro {
  display: grid; gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  align-items: stretch;
}
.ficha-test {
  position: relative;
  display: flex; flex-direction: column; gap: 10px;
  padding: 20px;
  border: 1px solid transparent; border-radius: var(--r-medio);
  background: var(--superficie);
  box-shadow: var(--sombra-tarjeta);
  text-align: left; font: inherit; color: inherit;
  transition: transform .14s ease, box-shadow .14s ease, border-color .14s ease;
  height: 100%;
}
.ficha-test:hover {
  transform: translateY(-3px);
  box-shadow: var(--sombra-flotante);
  border-color: var(--acento-suave);
}
.ficha-alto { display: flex; align-items: center; gap: 12px; }
.ficha-titulo { font-size: 16px; font-weight: 800; letter-spacing: -0.01em; }
.ficha-test:hover .ficha-titulo { color: var(--acento); }
/* La flecha, abajo a la derecha y sólo al pasar: un chevron siempre visible en cada
 * tarjeta es cuatro flechas compitiendo por la atención sin decir nada. */
.ficha-flecha {
  position: absolute; right: 16px; bottom: 14px;
  display: flex; color: var(--acento);
  opacity: 0; transform: translateX(-6px);
  transition: opacity .14s ease, transform .14s ease;
}
.ficha-test:hover .ficha-flecha { opacity: 1; transform: none; }
.ficha-detalle { font-size: 13px; color: var(--secundario); line-height: 1.5; padding-right: 22px; }

/* La fila de accesos rápidos. **Su rótulo va en su propia línea**: en la misma, con seis
 * pastillas al lado, se leía como una más y encima era lo primero que se cortaba al
 * encoger la ventana. */
.accesos {
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
  padding: 8px 0;
}
.accesos > .pequeno.dim, .accesos > .cejilla { flex-basis: 100%; margin: 0 0 2px; }
.acceso {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 10px 16px;
  border: 1px solid var(--divisor); border-radius: var(--capsula);
  background: var(--superficie);
  font-size: 13px; font-weight: 600; color: var(--tinta);
}
.acceso:hover { border-color: var(--acento); color: var(--acento); }
.acceso svg { color: var(--acento); }

/* La bienvenida del Tutor y sus sugerencias con icono. */
.bienvenida {
  display: flex; align-items: center; gap: 16px;
  padding: 18px; border-radius: var(--r-medio);
  background: var(--fondo);
}
.bienvenida-cara {
  width: 108px; height: 108px; flex: none;
  border-radius: 20px; overflow: hidden;
  background: var(--acento-suave);
  display: grid; place-items: center;
}
.bienvenida-cara .avatar { width: 108px; height: 108px; object-fit: cover; object-position: 50% 20%; }
.bienvenida-hola { margin: 0 0 6px; font-size: 20px; font-weight: 800; color: var(--acento); }
.bienvenida p { margin: 0; font-size: 14px; line-height: 1.5; }

.sugerencias { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 10px; }
.sugerencia {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 14px;
  border: 1px solid var(--divisor); border-radius: var(--r-pequeno);
  background: var(--superficie);
  font-size: 14px; font-weight: 600; color: var(--tinta);
  text-align: left;
}
.sugerencia:hover { border-color: var(--acento); background: var(--acento-suave); }

/* «Herramientas rápidas» de la columna derecha. */
.herramienta {
  display: flex; align-items: center; gap: 12px;
  width: 100%; padding: 9px 4px;
  border: 0; background: transparent; text-align: left; font: inherit; color: inherit;
  border-radius: 12px;
}
.herramienta:hover { background: var(--fondo); }
.herramienta .crece { display: flex; flex-direction: column; min-width: 0; }
.herramienta .titulo { font-size: 14px; font-weight: 700; }
.herramienta .detalle { font-size: 12px; color: var(--secundario); }
.boton-ancho .boton { width: 100%; padding: 16px 18px; }

/* Los tonos de `.cinta-icono`, para que el icono no sea siempre lila. */
.cinta-icono.rosa    { background: var(--past-rosa);    color: var(--past-rosa-tinta); }
.cinta-icono.verde   { background: var(--past-verde);   color: var(--past-verde-tinta); }
.cinta-icono.naranja { background: var(--past-naranja); color: var(--past-naranja-tinta); }
.cinta-icono.lila    { background: var(--past-lila);    color: var(--past-lila-tinta); }

/* El micro sobre la cara y la onda de sonido de la llamada. */
.llamada-cara { position: relative; }
.llamada-micro {
  position: absolute; bottom: -6px; left: 50%; transform: translateX(-50%);
  display: grid; place-items: center;
  width: 52px; height: 52px;
  border-radius: 50%;
  background: var(--acento); color: var(--acento-texto);
  box-shadow: 0 6px 18px rgba(108,61,242,.35);
}
.onda { display: flex; align-items: center; justify-content: center; gap: 4px; height: 34px; margin: 16px 0 10px; }
.onda span {
  width: 4px; height: 8px; border-radius: 999px;
  background: var(--acento-suave);
}
/* **Sólo se mueven mientras escucha.** Quietas dicen «no te estoy oyendo», que es lo que
 * hay que poder saber de un vistazo en una llamada. */
.onda.viva span { background: var(--acento); animation: onda 1s ease-in-out infinite; }
@keyframes onda { 0%, 100% { height: 8px; } 50% { height: 30px; } }

/* Botón con contorno: la alternativa secundaria de las maquetas nuevas. */
.boton.contorno {
  background: var(--superficie);
  color: var(--tinta);
  box-shadow: inset 0 0 0 1px var(--divisor);
}
.boton.contorno:hover { box-shadow: inset 0 0 0 1px var(--acento); color: var(--acento); }
/* Un «acceso» que es sólo un ejemplo, no un botón: esto se habla, no se pulsa. */
.acceso.mudo { cursor: default; }
.acceso.mudo:hover { border-color: var(--divisor); color: var(--tinta); }
.contador { font-size: 12px; color: var(--secundario); font-variant-numeric: tabular-nums; }

/* --------------------------------------------- el resultado del test, a pantalla entera */
.final {
  position: relative;
  border-radius: var(--r-grande);
  padding: 28px;
  background: linear-gradient(150deg, #FFF 40%, var(--past-rosa));
}
.final.bien { background: linear-gradient(150deg, #FFF 40%, var(--past-verde)); }
.final-cerrar { position: absolute; top: 18px; right: 18px; }
.final-alto { display: flex; align-items: center; gap: 24px; flex-wrap: wrap; }
.final-arte { flex: none; }
.final-titulo { margin: 0; font-size: clamp(28px, 3.4vw, 42px); font-weight: 800; letter-spacing: -0.03em; }
.final-sub { margin: 4px 0 14px; font-size: 19px; font-weight: 600; }
.final-cifra { margin: 0 0 16px; font-size: 15px; color: var(--secundario); }
.final-cifra strong { color: var(--tinta); }
.final-mensaje {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 14px 16px; border-radius: 16px;
  background: rgba(255,255,255,.72);
  font-size: 14px; line-height: 1.45; max-width: 52ch;
}
.metricas {
  display: grid; gap: 12px; margin: 22px 0;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
.metrica {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 16px; border-radius: var(--r-medio);
  background: var(--superficie); box-shadow: var(--sombra-tarjeta);
}
.metrica-valor { font-size: 22px; font-weight: 800; line-height: 1.1; font-variant-numeric: tabular-nums; }
.metrica-rotulo { font-size: 13px; color: var(--secundario); }
.final-opciones { margin-bottom: 20px; }
.opcion-final {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 12px 14px; margin-bottom: 8px;
  border: 0; border-radius: var(--r-pequeno);
  background: var(--fondo); text-align: left; font: inherit; color: inherit;
}
.opcion-final:hover { background: var(--acento-suave); }
.opcion-final .crece { display: flex; flex-direction: column; min-width: 0; }
.opcion-final .titulo { font-size: 14px; font-weight: 700; }
.opcion-final .detalle { font-size: 12px; color: var(--secundario); }
.opcion-final .chevron { color: #C9C4DA; display: flex; }
.final-acciones { justify-content: center; }

/* --------------------------------------------------- hacer el test, pregunta a pregunta */
.volver {
  display: inline-flex; align-items: center; gap: 6px;
  border: 0; background: transparent; padding: 4px 2px; margin-bottom: 4px;
  font: inherit; font-weight: 600; color: var(--secundario);
}
.volver:hover { color: var(--acento); }
.marcar {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 10px 14px;
  border: 1px solid var(--divisor); border-radius: var(--capsula);
  background: var(--superficie); font: inherit; font-size: 14px; font-weight: 600; color: var(--secundario);
}
.marcar.puesta { border-color: var(--acento); color: var(--acento); background: var(--acento-suave); }

.paginas { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; justify-content: center; }
/* **`.pagina-num`, no `.pagina`.** `.pagina` ya era el contenedor que devuelve `pagina()`
 * de `ui.js` —la página entera de una vista— y ponerle aquí `width: 34px` la encogió a un
 * botón: la pantalla de Tests salió con el texto en una palabra por línea. Es la misma
 * trampa que ya costó un rato con `.dos`, y por eso está escrita en el CLAUDE.md:
 * **`grep` en `estilos.css` antes de estrenar una clase**. */
.pagina-num {
  width: 34px; height: 34px; flex: none;
  border: 1px solid var(--divisor); border-radius: 50%;
  background: var(--superficie);
  font: inherit; font-size: 13px; font-weight: 700; color: var(--tinta);
  display: grid; place-items: center;
}
.pagina-num:hover { border-color: var(--acento); }
/* Contestada, marcada y actual son tres cosas distintas y tienen que verse las tres. */
.pagina-num.hecha { background: var(--acento-suave); border-color: transparent; color: var(--acento); }
.pagina-num.marcada { box-shadow: inset 0 0 0 2px var(--aviso); }
.pagina-num.activa { background: var(--acento); border-color: var(--acento); color: var(--acento-texto); }
.pagina-num.flecha { color: var(--secundario); }
.pagina-num[disabled] { opacity: .4; }
.finalizar {
  display: inline-flex; align-items: center; gap: 7px;
  margin-left: 8px; padding: 8px 14px;
  border: 1px solid var(--peligro); border-radius: var(--capsula);
  background: transparent; color: var(--peligro);
  font: inherit; font-size: 13px; font-weight: 700;
}
.finalizar:hover { background: var(--past-rosa); }

/* Los pasos de la espera del generador. */
.pasos-espera { list-style: none; margin: 18px auto 0; padding: 0; max-width: 260px; text-align: left; }
.paso-espera {
  display: flex; align-items: center; gap: 10px;
  padding: 5px 0; font-size: 14px; color: var(--secundario);
}
.paso-marca {
  display: grid; place-items: center;
  width: 20px; height: 20px; flex: none;
  border-radius: 50%;
  border: 2px solid #D8D4E6; background: transparent; color: transparent;
}
.paso-espera.listo { color: var(--tinta); font-weight: 600; }
.paso-espera.listo .paso-marca { background: var(--acento); border-color: var(--acento); color: #fff; }

/* Los iconos 3D de la barra. **No se tiñen con `currentColor`** —son PNG a todo color— y
 * por eso el item activo se marca con la cápsula lila y el texto en morado, no con el
 * icono: si el icono no puede cambiar de color, tiene que hacerlo lo de alrededor. */
.icono3d { width: 24px; height: 24px; flex: none; object-fit: contain; }
.barra-inferior .icono3d { width: 26px; height: 26px; }

/* ------------------------------------------------- la columna derecha de Tests */

.tarjeta-racha {
  display: flex; align-items: center; gap: 12px;
  width: 100%; text-align: left; font: inherit; color: inherit; border: 0;
}
.tarjeta-racha .crece { display: flex; flex-direction: column; min-width: 0; }
.racha-cifra { font-size: 22px; font-weight: 800; letter-spacing: -0.02em; line-height: 1.1; }
.mini-barras { display: flex; align-items: flex-end; gap: 3px; height: 34px; flex: none; }
.mini-barras span { width: 6px; border-radius: 3px 3px 1px 1px; background: var(--acento-suave); }
.mini-barras span:last-child { background: var(--acento); }
.tarjeta-racha .chevron { color: #C9C4DA; display: flex; flex: none; }

.tarjeta.cita-marca { background: var(--acento-suave); position: relative; }
.cita-marca .comillas {
  font-size: 34px; font-weight: 800; color: var(--acento); line-height: 1;
  display: block; margin-bottom: -6px;
}
.cita-marca p { margin: 0; font-size: 14px; line-height: 1.45; }

.fila-test { display: flex; align-items: center; gap: 10px; padding: 8px 0; }
.fila-test + .fila-test { border-top: 1px solid var(--divisor); }
.fila-test .crece { display: flex; flex-direction: column; min-width: 0; }
.fila-test .titulo {
  font-size: 14px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fila-test .detalle { font-size: 12px; color: var(--secundario); }
.boton.pequenito { padding: 7px 14px; font-size: 13px; }

.tarjeta.promo {
  display: flex; align-items: center; gap: 12px;
  background: linear-gradient(135deg, var(--acento-suave), var(--past-rosa));
  overflow: hidden;
}
.promo h3 { margin: 0; font-size: 16px; font-weight: 800; }
.promo .avatar { flex: none; margin: -14px -14px -18px 0; }

/* ------------------------------------------------------------------ el pie */

.pie-pagina {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  padding: 26px 2px 8px;
  border-top: 1px solid var(--divisor);
  margin-top: 20px;
}
.pie-marca { font-weight: 800; font-size: 14px; }
.pie-lema { font-size: 13px; color: var(--secundario); margin-left: 8px; }
.pie-enlaces { display: flex; gap: 18px; }
.pie-enlaces a { font-size: 13px; color: var(--secundario); }
.pie-enlaces a:hover { color: var(--acento); }

/* ---------------------------------- centrado y aire de los bloques con avatar */
/*
 * Ruben: «los avatares, bloques, etc, todo centrado bien». El problema era que cada sitio
 * alineaba a su manera: unos arriba, otros abajo, otros con un margen negativo que sólo
 * valía para un tamaño. La regla, en un sitio: **una ilustración dentro de una caja va
 * centrada verticalmente con lo que tiene al lado**, y quien quiera que se salga lo pide.
 */
.con-cara, .animo, .bienvenida, .tarjeta.promo,
.tarjeta.puntuacion, .final-alto, .reloj-tres { align-items: center; }
.con-cara .avatar, .tarjeta.promo .avatar { align-self: center; }
/* Los discos y círculos que recortan una cara: siempre el mismo encuadre. */
.animo .disco .avatar, .bienvenida-cara .avatar,
.turno .cara .avatar, .llamada-cara .avatar { object-fit: cover; object-position: 50% 20%; }


/* ------------------------------------------------- adjuntos en el chat del Tutor */

.clip {
  display: grid; place-items: center;
  width: 42px; height: 42px; flex: none;
  border: 0; border-radius: 50%;
  background: transparent; color: var(--secundario);
}
.clip:hover { background: var(--acento-suave); color: var(--acento); }

/* Lo que está a punto de mandarse, encima del campo: se ve qué se adjunta y se puede
 * quitar antes de enviar. Sin esto, adjuntar es un acto de fe. */
.adjunto-puesto {
  display: flex; align-items: center; gap: 10px;
  margin: 0 16px; padding: 8px 10px;
  border-radius: var(--r-pequeno);
  background: var(--acento-suave);
  font-size: 13px;
}
.adjunto-puesto img { width: 40px; height: 40px; border-radius: 8px; object-fit: cover; flex: none; }
.adjunto-puesto .crece {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600;
}
.adjunto-puesto .redondo { width: 28px; height: 28px; }

/* La foto ya enviada, dentro de su burbuja. */
.adjunto-foto {
  display: block; max-width: 100%; width: 260px;
  border-radius: 12px; margin-bottom: 8px;
}
.adjunto-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px; margin-bottom: 8px;
  border-radius: var(--capsula);
  background: rgba(255,255,255,.22);
  font-size: 12px; font-weight: 600;
}

/* La misma cura para las otras dos ilustraciones sueltas sobre el fondo: la del héroe
 * grande de Hoy y Horario, y la de la tarjeta promo. */
.heroe-arte .avatar, .tarjeta.promo .avatar {
  -webkit-mask-image: linear-gradient(to bottom, #000 78%, transparent 99%);
  mask-image: linear-gradient(to bottom, #000 78%, transparent 99%);
}

/* ------------------------------------------------ la cabecera que es una imagen */
/*
 * El texto y la ilustración van dentro del PNG que pasa Ruben. Encima se coloca el botón
 * **de verdad**, tapando el que está dibujado: mismo sitio, mismo tamaño, mismo color y
 * mismo radio, todo en **porcentajes** para que siga cuadrando a cualquier ancho.
 *
 * El botón dibujado mide 511×109 px sobre una imagen de 2067×761 — medido buscando la
 * mancha de su morado en el propio fichero, no a ojo — y el radio es la mitad del alto,
 * o sea una cápsula.
 */
.heroe-img { position: relative; line-height: 0; }
.heroe-img img { width: 100%; height: auto; display: block; border-radius: var(--r-grande); }
.heroe-img-boton {
  position: absolute;
  /* El padding lo pone el tamaño: la caja ya viene dada por el botón dibujado. */
  padding: 0;
  border-radius: 999px;
  background: #6C3AF2;
  color: #FFFFFF;
  /* La letra crece con la imagen; el mínimo evita que se vuelva ilegible en una ventana
   * estrecha, donde de todas formas la cabecera pasa a su versión apilada. */
  font-size: clamp(14px, 1.15vw, 20px);
  font-weight: 700;
  gap: 12px;
  line-height: 1;
}
.heroe-img-boton:hover { filter: brightness(1.08); }
.heroe-img-boton:active { transform: scale(.985); }

/* Por debajo de 760 px la imagen se queda diminuta y el botón, dentro de ella, ilegible:
 * ahí la imagen pasa a ser decoración y el botón baja debajo, a su tamaño normal. */
@media (max-width: 760px) {
  .heroe-img-boton {
    position: static; width: auto !important; height: auto !important;
    padding: 14px 22px; margin-top: 14px; font-size: 16px;
  }
  .heroe-img { line-height: 1.45; }
}

/* Una tarjeta que es una imagen: ocupa el ancho de la columna y conserva su proporción.
 * No lleva sombra ni relleno propios — el dibujo ya trae su fondo y sus esquinas. */
.tarjeta-img {
  display: block;
  width: 100%;
  /* **`min-width: 0` no es opcional.** Un hijo de un flex tiene `min-width: auto`, o sea
   * que se niega a encogerse por debajo de su ancho natural: la imagen mide 820 px de
   * origen y se salía 25 px por la izquierda de una columna de 360. Es la misma trampa que
   * ya costó un rato con la rejilla del Horario. */
  min-width: 0;
  max-width: 100%;
  height: auto;
  border-radius: var(--r-medio);
}
.lado > * { min-width: 0; }
.pie-version {
  margin-left: 12px; font-size: 11px; color: var(--secundario);
  font-variant-numeric: tabular-nums; opacity: .7;
}

/* Una tarjeta-imagen con su botón real encima del dibujado. Mismo patrón que la cabecera:
 * las medidas van en porcentajes sacados del propio PNG, así tapan el mismo sitio a
 * cualquier ancho. El botón de esta lleva **fondo blanco y texto oscuro**, que es como
 * está pintado — sobre el lila de la tarjeta, uno morado desaparecería. */
.tarjeta-img-caja { position: relative; line-height: 0; container-type: inline-size; }
.img-boton {
  position: absolute;
  padding: 0;
  border-radius: 999px;
  background: #FFFFFF;
  color: var(--tinta);
  /* **La letra se mide contra la tarjeta, no contra la ventana.** Esta promo vive en la
   * columna de 360 px, así que un `vw` la hacía grande de más y «Ver cómo funciona» se
   * partía en dos líneas dentro de un botón de una. Con `cqw` la letra encoge con la
   * tarjeta, y el `nowrap` garantiza que nunca parta. */
  font-size: clamp(10px, 3.6cqw, 15px);
  font-weight: 700;
  gap: 8px;
  line-height: 1;
  white-space: nowrap;
  box-shadow: none;
}
.img-boton svg { color: var(--acento); }
.img-boton:hover { filter: none; background: #FFF; box-shadow: 0 4px 14px rgba(76,40,160,.16); }
/* En una columna estrecha el botón dentro de la imagen se queda ilegible: baja debajo. */
@media (max-width: 860px) {
  .img-boton {
    position: static; width: auto !important; height: auto !important;
    padding: 12px 20px; margin-top: 12px; font-size: 14px;
  }
  .tarjeta-img-caja { line-height: 1.45; }
}

/* La bienvenida del Tutor, que es una imagen. Ocupa el ancho del hilo y conserva su
 * proporción; `min-width: 0` porque el hilo es un flex en columna y sin él la imagen se
 * negaría a encoger por debajo de su ancho natural. */
.bienvenida-img {
  display: block; width: 100%; min-width: 0; height: auto;
  /* **Menos ancha.** A todo el ancho del hilo (~1.000 px) quedaba una banda muy larga y
   * baja; con el tope se lee como una tarjeta. El alto va con ella: la proporción está
   * dentro del fichero y no se puede estirar sin deformar el dibujo. */
  max-width: 780px;
  border-radius: var(--r-medio);
  margin: 0 auto 6px;
}

/* La espera del generador. **Acotada y centrada**: sin tope se estiraba a todo el ancho de
 * la columna (más de 1.000 px) y quedaba una tarjeta enorme con la ilustración flotando en
 * medio y el texto en una línea larguísima. Es una pantalla de espera, no un panel. */
.tarjeta.generando {
  max-width: 560px;
  margin: 0 auto;
  padding: 28px 24px 24px;
}
.tarjeta.generando .avatar { margin-bottom: 4px; }
.tarjeta.generando .titulo-test { font-size: clamp(22px, 2.2vw, 28px); }
.tarjeta.generando > .dim { max-width: 42ch; margin-inline: auto; }
/* La cita de debajo, al mismo ancho que la tarjeta: descolgada a todo lo ancho se leía
 * como si fuera de otra pantalla. (Aquí había también tres fichas; las quitó Ruben.) */
.tarjeta.generando ~ .tarjeta.cita { max-width: 560px; margin-inline: auto; }

/* Un héroe que es un render entero (bocadillo + ilustración en el mismo fichero).
 *
 * **Con desvanecido abajo**, aunque el fondo del PNG sea transparente: el dibujo acaba en
 * un canto —los libros y el portátil se cortan— y ese borde recto contra el lila se lee
 * como una imagen mal recortada. La máscara lo funde con el fondo. */
.heroe-render {
  display: block;
  width: 100%;
  max-width: 520px;
  min-width: 0;
  height: auto;
  -webkit-mask-image: linear-gradient(to bottom, #000 74%, transparent 98%);
  mask-image: linear-gradient(to bottom, #000 74%, transparent 98%);
}
.heroe-arte:has(.heroe-render) { margin: 0; align-self: center; }

/* ---------------------------------------------------------------------------
 * La pantalla de entrar, partida en dos como el render que pasó Ruben.
 *
 * **Las dos mitades son UNA tarjeta**, no dos cajas pegadas: en el render hay una sola
 * pieza blanca redondeada flotando sobre el lila, con la ilustración ocupando su mitad
 * izquierda a sangre. Por eso el radio y la sombra van en el contenedor y las esquinas se
 * recortan con `overflow: hidden`, en vez de repartir radios entre los dos hijos —que es
 * como lo hice primero y dejaba un canto recto en la juntura.
 *
 * La mitad izquierda es una imagen y punto: el titular, la nota manuscrita con su flecha
 * y los tres pies con sus iconos van dentro del fichero. Se recorta con `object-fit:
 * cover` porque la ventana casi nunca tiene la proporción del dibujo, y con
 * `object-position` alto para que la cara no se salga nunca del encuadre.
 * ------------------------------------------------------------------------ */
.entrar {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  background: var(--fondo);
  padding: 24px;
}
.entrar-marco {
  width: min(1080px, 100%);
  display: grid;
  grid-template-columns: 1fr 1fr;
  background: var(--superficie);
  border-radius: var(--r-grande);
  overflow: hidden;
  box-shadow: var(--sombra, 0 18px 50px rgba(108, 58, 242, .10));
}
.entrar-arte { position: relative; overflow: hidden; background: var(--fondo); }
.entrar-arte img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 50% 32%;
  display: block;
}
.entrar-panel { display: grid; place-items: center; padding: 48px 32px; }
.entrar-caja { width: min(360px, 100%); }

/* El aviso de «esto lo tienes regalado», arriba de la hoja de planes. */
.planes-regalo {
  margin: 0 0 14px; padding: 11px 14px;
  border-radius: var(--r-medio);
  background: var(--acento-suave);
  color: var(--tinta);
  text-align: center;
}

/* === «¿Qué estudias?» (8-sep) ============================================
   Eran cuatro barras a todo lo ancho, una debajo de otra: llenaban la hoja y dejaban los
   campos del centro y el curso por debajo del pliegue, así que nadie los veía hasta
   desplazarse. En rejilla de dos, las cuatro opciones y lo que se pregunta después caben
   en la misma pantalla. */
.qe-opciones { display: grid; gap: 10px; grid-template-columns: 1fr 1fr; margin-bottom: 20px; }
.qe-opcion {
  display: flex; align-items: center; gap: 12px; text-align: left;
  padding: 14px 15px; border-radius: var(--r-medio);
  background: var(--superficie); border: 2px solid var(--divisor);
  font: inherit; color: inherit; cursor: pointer;
  transition: border-color .15s ease, background .15s ease, transform .15s ease;
}
.qe-opcion:hover { border-color: color-mix(in srgb, var(--acento) 45%, var(--divisor)); transform: translateY(-1px); }
.qe-opcion.elegida { background: var(--acento-suave); border-color: var(--acento); }
.qe-opcion-emoji { font-size: 22px; line-height: 1; flex: 0 0 auto; }
.qe-opcion-texto { display: grid; gap: 2px; flex: 1 1 auto; min-width: 0; }
.qe-opcion-titulo { font-weight: 700; font-size: 15.5px; }
.qe-opcion-detalle { font-size: 12.5px; color: var(--secundario); line-height: 1.3; }
.qe-opcion-check {
  flex: 0 0 22px; height: 22px; border-radius: 50%;
  display: grid; place-items: center; background: var(--acento); color: #fff;
}
.qe-opcion-check.apagado { visibility: hidden; }

.qe-extras {
  padding: 16px; border-radius: var(--r-medio);
  background: var(--fondo); border: 1px solid var(--divisor);
  margin-bottom: 18px;
}
.qe-extras-titulo { font-weight: 700; margin-bottom: 4px; }
.qe-extras-ayuda { margin: 0 0 14px; font-size: 13px; color: var(--secundario); line-height: 1.45; }
/* El último campo del bloque no arrastra su margen: dejaba un hueco raro antes del botón. */
.qe-extras .campo:last-child { margin-bottom: 0; }

.qe-pie { display: grid; gap: 8px; justify-items: center; }
.qe-pie .boton { width: 100%; justify-content: center; }
.qe-pie p { margin: 0; text-align: center; }

@media (max-width: 520px) { .qe-opciones { grid-template-columns: 1fr; } }

/* === Ajustes, por grupos (8-sep) ==========================================
   Antes eran siete tarjetas idénticas en fila: la del plan pesaba lo mismo que la del
   color, y para encontrar «cerrar sesión» había que leerlas todas. Ahora hay rótulo de
   grupo, el consumo en baldosas y lo irreversible en su propio marco. */
.aj-grupo { margin-bottom: 30px; }
.aj-grupo-cabeza { margin: 0 2px 12px; }
.aj-grupo-titulo {
  margin: 0; font-size: 13px; font-weight: 700;
  letter-spacing: .09em; text-transform: uppercase; color: var(--secundario);
}
.aj-grupo-sub { margin: 4px 0 0; font-size: 14px; color: var(--secundario); }

/* --- el plan --- */
.aj-plan-cabeza {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; flex-wrap: wrap; margin-bottom: 16px;
}
.aj-plan-nombre { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.aj-plan-pastilla {
  display: inline-block; padding: 6px 16px; border-radius: 999px;
  background: var(--fondo); border: 1px solid var(--divisor);
  font-weight: 800; font-size: 16px; letter-spacing: -.01em;
}
/* El de pago se pinta con el acento: es la única pastilla de la pantalla que dice algo
   distinto de las demás, y en gris no se distinguía del rótulo de al lado. */
.aj-plan-pastilla.es-pago { background: var(--acento); border-color: var(--acento); color: #fff; }
.aj-plan-lema { font-size: 14px; color: var(--secundario); }
.aj-plan-botones { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.aj-plan-pie { margin: 14px 0 0; }

.aj-usos { display: grid; gap: 10px; grid-template-columns: repeat(4, 1fr); }
.aj-uso {
  display: grid; gap: 6px; align-content: start;
  padding: 14px; border-radius: var(--r-medio);
  background: var(--fondo); border: 1px solid var(--divisor);
}
.aj-uso-nombre { font-size: 13px; color: var(--secundario); }
.aj-uso-cifra { font-size: 15px; display: flex; align-items: baseline; gap: 4px; }
.aj-uso-cifra strong { font-size: 22px; letter-spacing: -.02em; }
.aj-uso.sin-tope .aj-uso-cifra { align-items: center; color: var(--ok); font-weight: 600; }
.aj-uso-barra {
  display: block; height: 6px; border-radius: 3px; overflow: hidden;
  background: color-mix(in srgb, var(--divisor) 70%, transparent);
}
.aj-uso-barra-va { display: block; height: 100%; border-radius: 3px; transition: width .3s ease; }
.aj-uso-pie { font-size: 12px; color: var(--secundario); }

/* --- personalización, a dos columnas --- */
.aj-dos { display: grid; gap: 16px; grid-template-columns: 1fr 1fr; align-items: start; }
.aj-campo { display: grid; gap: 6px; }
.aj-etiqueta { font-size: 13px; font-weight: 600; color: var(--secundario); }
.aj-ayuda { font-size: 13px; color: var(--secundario); line-height: 1.45; }
.aj-separador { height: 1px; background: var(--divisor); margin: 16px 0; }

.aj-colores { display: grid; gap: 10px; grid-template-columns: repeat(5, 1fr); }
.aj-color {
  display: grid; gap: 6px; justify-items: center;
  border: 0; background: transparent; cursor: pointer; padding: 4px 0;
  font: inherit; color: var(--secundario);
}
.aj-color-muestra {
  width: 34px; height: 34px; border-radius: 50%;
  display: grid; place-items: center; color: #fff;
  box-shadow: 0 0 0 2px var(--superficie), 0 0 0 2px transparent;
  transition: box-shadow .15s ease, transform .15s ease;
}
.aj-color:hover .aj-color-muestra { transform: scale(1.08); }
.aj-color.elegido .aj-color-muestra { box-shadow: 0 0 0 2px var(--superficie), 0 0 0 4px var(--tinta); }
.aj-color-nombre { font-size: 11.5px; }
.aj-color.elegido .aj-color-nombre { color: var(--tinta); font-weight: 600; }

/* --- filas de acción --- */
.aj-lista { display: grid; }
.aj-accion {
  display: flex; align-items: center; gap: 14px;
  padding: 14px 0; border-top: 1px solid var(--divisor);
}
.aj-lista .aj-accion:first-child { border-top: 0; }
.aj-accion-icono {
  flex: 0 0 36px; height: 36px; display: grid; place-items: center;
  border-radius: 10px; background: var(--acento-suave); color: var(--acento);
}
.aj-accion-texto { display: grid; gap: 2px; flex: 1 1 auto; min-width: 0; }
.aj-accion-titulo { font-weight: 600; }
.aj-accion-detalle { font-size: 13px; color: var(--secundario); line-height: 1.4; }
.aj-accion-boton { flex: 0 0 auto; }
.aj-accion.peligro .aj-accion-icono { background: #FDE7E9; color: #8E1D28; }

/* --- estado de la sincronía --- */
.aj-estado {
  display: flex; align-items: center; gap: 12px;
  padding: 14px; border-radius: var(--r-medio);
  background: var(--fondo); border: 1px solid var(--divisor);
  margin-bottom: 4px;
}
.aj-estado-punto {
  width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto;
  background: var(--ok);
}
.aj-estado-punto.pendiente { background: #E8833A; }
.aj-estado-titulo { display: block; font-weight: 600; }

/* --- lo que no tiene vuelta atrás --- */
.aj-peligro {
  margin-top: 16px; padding: 16px 18px;
  border-radius: var(--r-grande);
  background: var(--superficie);
  border: 1px solid #F0C4CA;
}
.aj-peligro-titulo {
  display: flex; align-items: center; gap: 7px;
  color: #8E1D28; font-weight: 700; font-size: 13px;
  letter-spacing: .06em; text-transform: uppercase; margin-bottom: 6px;
}
.aj-peligro .aj-accion { border-top: 0; padding-bottom: 0; }

@media (max-width: 1100px) {
  .aj-usos { grid-template-columns: repeat(2, 1fr); }
  .aj-dos { grid-template-columns: 1fr; }
}
@media (max-width: 620px) {
  .aj-usos { grid-template-columns: repeat(2, 1fr); }
  .aj-colores { grid-template-columns: repeat(4, 1fr); }
  /* El botón debajo del texto: en fila, con el detalle de dos líneas, no cabe. */
  .aj-accion { flex-wrap: wrap; }
  .aj-accion-boton { width: 100%; }
  .aj-accion-boton .boton { width: 100%; justify-content: center; }
}

/* --- La cinta del mes regalado -------------------------------------------
   Va en tono de acento y no en verde de «bien» ni en amarillo de «ojo»: no es un aviso
   de sistema, es algo que se le da. Cuando quedan pocos días cambia a ámbar, que es
   cuando sí hay algo que hacer (o al menos que saber). */
.regalo {
  display: flex; align-items: center; gap: 14px;
  padding: 16px 18px; margin-bottom: 14px;
  border-radius: var(--r-medio);
  background: var(--acento-suave);
  border: 1px solid color-mix(in srgb, var(--acento) 28%, transparent);
}
.regalo.acaba { background: #FFF4E2; border-color: #F0C070; }
.regalo-icono { font-size: 26px; line-height: 1; flex: 0 0 auto; }
.regalo-acciones { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.regalo-boton { padding: 9px 16px; font-size: 14px; }
.regalo-cerrar {
  border: 0; background: transparent; cursor: pointer;
  color: var(--secundario); display: grid; place-items: center;
  padding: 6px; border-radius: 8px;
}
.regalo-cerrar:hover { background: rgba(0,0,0,.06); color: var(--tinta); }
@media (max-width: 620px) {
  /* En estrecho, el botón y la equis debajo del texto: en fila se comen el titular. */
  .regalo { flex-wrap: wrap; }
  .regalo-acciones { width: 100%; justify-content: flex-end; }
}

/* **Primeros pasos.** Filas pulsables, no una lista de texto: cada paso lleva a la
 * pantalla donde se hace, que es la única forma de que una lista de tareas sirva de algo.
 * El hecho se apaga —queda como prueba de avance— y el pendiente conserva la flecha. */
.pasos { display: grid; gap: 8px; margin-top: 14px; }
.pasos-cabeza { display: flex; align-items: center; gap: 14px; }
/* El anillo no se encoge aunque el rótulo sea largo, y el botón de ocultar se va al
 * borde: `.crece` es quien se come el espacio sobrante. */
.pasos-cabeza .anillo { flex: 0 0 auto; }
.pasos-cabeza .entrar-enlace { flex: 0 0 auto; align-self: flex-start; }
.paso {
  display: flex; align-items: center; gap: 12px;
  width: 100%; text-align: left;
  padding: 12px 14px;
  background: var(--fondo);
  border: 1px solid var(--divisor);
  border-radius: var(--r-medio);
  font: inherit; color: inherit; cursor: pointer;
  transition: border-color .15s ease, transform .15s ease;
}
.paso:hover { border-color: var(--acento); transform: translateX(2px); }
.paso-marca {
  flex: 0 0 26px; height: 26px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--acento-suave); color: var(--acento);
  font-size: 13px; font-weight: 700;
}
.paso-texto { display: grid; gap: 2px; flex: 1 1 auto; min-width: 0; }
.paso-titulo { font-weight: 600; }
.paso-detalle { font-size: 13px; color: var(--secundario); }
.paso-flecha { color: var(--acento); display: grid; place-items: center; }
/* El hecho no se tacha: se apaga. Un texto tachado en una lista de cuatro líneas es
 * ilegible, y aquí sigue haciendo falta poder leer lo que ya se hizo. */
.paso.hecho { opacity: .55; }
.paso.hecho .paso-marca { background: #E4F5EC; color: #0E5D38; }
.paso.hecho:hover { transform: none; border-color: var(--divisor); }

/* **Las dos puertas: entrar o crear cuenta.** Un selector de dos, no dos pantallas: el
 * formulario es el mismo (un móvil y un SMS) y separarlo en dos direcciones obligaría a
 * volver atrás a quien se equivoca de puerta. La pastilla activa se pinta con el acento
 * porque el resto de la pantalla ya lo usa; el borde marca el grupo sin encerrarlo. */
.entrar-puertas {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px;
  padding: 4px;
  margin-bottom: 18px;
  background: var(--fondo);
  border: 1px solid var(--divisor);
  border-radius: 999px;
}
.entrar-puerta {
  border: 0;
  background: transparent;
  color: var(--secundario);
  font: inherit;
  font-weight: 600;
  font-size: 14px;
  padding: 9px 10px;
  border-radius: 999px;
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.entrar-puerta:hover { color: var(--tinta); }
.entrar-puerta.activa { background: var(--acento); color: #fff; }
/* Sin ilustración al lado (la espera y el «ya tenías cuenta»): una sola columna, o la
 * mitad izquierda se queda vacía y la caja aparece descentrada. */
.entrar-marco-solo { grid-template-columns: 1fr; max-width: 520px; }

.entrar-marca { text-align: center; margin-bottom: 26px; }
/* La corona con alto fijo y `width: auto`: es lo único de esta pantalla que NO puede
 * estirarse al ancho de su caja. */
.entrar-corona { display: block; margin: 0 auto 14px; height: 62px; width: auto; }
.entrar-marca h1 { margin: 0; font-size: clamp(23px, 2.2vw, 29px); letter-spacing: -.02em; }
.entrar-lema { margin: 8px 0 0; color: var(--secundario); font-size: 15px; }

/* El campo con el icono dentro, como en el render.
 *
 * Los estilos base van AQUÍ y no heredados: `entrada()` los recibe de `.campo input`, y
 * este campo no vive dentro de un `.campo` —lleva el icono superpuesto—, así que sin esto
 * salía como un `input` pelado del navegador. El relleno izquierdo lo pone esta regla para
 * que el icono no pise el texto por mucho que crezca la letra. */
.entrar-campo { position: relative; }
.entrar-campo input {
  width: 100%;
  height: 52px;
  padding: 0 16px 0 46px;
  border-radius: var(--r-pequeno);
  border: 1px solid var(--divisor);
  background: var(--superficie);
  font-size: 15px;
}
.entrar-campo input:focus { border-color: var(--acento); outline: none; }
.entrar-campo-icono {
  position: absolute; left: 15px; top: 50%; transform: translateY(-50%);
  color: var(--secundario); pointer-events: none; display: flex;
}

.entrar-fila {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin: 14px 0 18px;
}
.entrar-recordar { display: flex; align-items: center; gap: 8px; font-size: 14px; cursor: pointer; }
.entrar-recordar input { accent-color: var(--acento); width: 18px; height: 18px; }

/* El botón ancho del render, con la flecha detrás del texto. */
.boton.entrar-enviar { width: 100%; justify-content: center; height: 52px; font-size: 16px; }

.entrar-pie { text-align: center; margin: 22px 0 0; color: var(--secundario); font-size: 14px; }
.entrar-pie strong { color: var(--acento); }

/* **En móvil se va la ilustración.** Es un dibujo vertical: dejarlo arriba empujaría el
 * formulario fuera de la primera pantalla, que es el único sitio donde tiene que estar. */
@media (max-width: 900px) {
  .entrar { padding: 0; place-items: stretch; }
  .entrar-marco {
    grid-template-columns: 1fr; width: 100%; min-height: 100dvh;
    border-radius: 0; box-shadow: none;
  }
  .entrar-arte { display: none; }
  .entrar-panel { padding: 32px 20px; }
}

/* El campo del código: mismo alto y mismo trato que el del móvil, pero con las seis cifras
 * separadas y centradas. El `padding-right` iguala al izquierdo **a mano**: con el icono
 * sólo a la izquierda, un texto centrado queda descentrado 46 px hacia la derecha. */
.entrar-campo-codigo input {
  padding-right: 46px;
  font-size: 26px;
  font-weight: 700;
  letter-spacing: .3em;
  text-align: center;
}

/* Los enlaces del segundo paso. Son `button` y no `a` porque no llevan a ninguna
 * dirección: cambian de paso o piden otro SMS. Se les quita la pinta de botón. */
.entrar-enlace {
  background: none; border: 0; padding: 0;
  color: var(--acento); font: inherit; font-size: 14px; font-weight: 600;
  cursor: pointer;
}
.entrar-enlace:hover { text-decoration: underline; }

/* ---------------------------------------------------------------------------
 * La pantalla de «descárgate la app», que es lo ÚNICO que ve un teléfono.
 *
 * Se maqueta para el caso peor —un iPhone SE, 375x667— y no para el mejor: lo que tiene
 * que caber en la primera pantalla, sin desplazar, es la corona, el titular y el botón.
 * Todo lo demás puede quedar por debajo del pliegue.
 * ------------------------------------------------------------------------ */
.movil {
  min-height: 100dvh;
  background: var(--fondo);
  display: grid;
  place-items: start center;
  padding: 28px 20px 40px;
}
.movil-caja { width: min(440px, 100%); text-align: center; }
.movil-caja h1 {
  margin: 0 0 10px;
  font-size: clamp(24px, 7vw, 31px);
  line-height: 1.15;
  letter-spacing: -.02em;
}
.movil-lema { margin: 0 0 20px; color: var(--secundario); font-size: 15px; line-height: 1.5; }

/* La ilustración **recortada**, no encogida: es un dibujo vertical y entero empujaría el
 * botón fuera de la primera pantalla, que es justo donde tiene que estar. Se recorta por
 * arriba, que es donde está la cara. */
.movil-arte {
  height: clamp(150px, 26vh, 220px);
  border-radius: var(--r-medio);
  overflow: hidden;
  margin-bottom: 22px;
  background: var(--superficie);
}
.movil-arte img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 22%; display: block; }

.boton.movil-descarga, a.boton.movil-descarga {
  width: 100%; justify-content: center; height: 54px; font-size: 16px;
  text-decoration: none;
}
/* El botón apagado de cuando aún no hay a dónde mandar: **gris y sin puntero**, para que
 * no parezca que no funciona sino que todavía no toca. */
.movil-descarga.apagada {
  background: var(--divisor); color: var(--secundario); cursor: default;
  box-shadow: none;
}

.movil-pies {
  display: grid; gap: 12px; text-align: left;
  margin: 26px 0 0; padding: 18px;
  background: var(--superficie); border-radius: var(--r-medio);
}
.movil-pie-item { display: flex; align-items: center; gap: 12px; }
.movil-pie-titulo { display: block; font-weight: 600; font-size: 14px; }
.movil-pie-detalle { display: block; color: var(--secundario); font-size: 13px; }

.movil-nota { margin: 18px 0 0; color: var(--secundario); font-size: 13px; line-height: 1.5; }

}

/* El resultado del test, **a pantalla completa**, como en `test-resultado.png`.
 *
 * En la maqueta el resultado ocupa el ancho entero: no hay columna de apoyo, ni racha, ni
 * próximos exámenes. Y tiene sentido — es el final de algo, no una tarjeta más de una
 * lista, y lo que se quiere es que se lea la nota y se elija qué hacer, no que compita con
 * seis tarjetas al lado. Estaba escrito en el traspaso como hecho y no lo estaba.
 *
 * Se hace con `:has()` y no con una clase puesta desde el JS a propósito: la fase la
 * decide `vistas/test.js` y tendría que acordarse de quitar la clase al salir; así lo
 * decide el propio contenido y no hay estado que se quede pegado. */
.columnas:has(.final) .lado,
.columnas:has(.pregunta-viva) .lado { display: none; }
@media (min-width: 1100px) {
  .columnas:has(.final),
  .columnas:has(.pregunta-viva) { grid-template-columns: minmax(0, 1fr); }
}

/* El disco de color detrás de la ilustración, verde si aprueba y rosa si no. En la maqueta
 * es lo que da el veredicto **antes de leer nada**, y por eso va detrás del dibujo y no
 * como un icono más. */
.final-arte { position: relative; z-index: 1; }
.final-alto { position: relative; }
.final-alto::before {
  content: "";
  position: absolute;
  left: 0; top: 50%;
  width: clamp(140px, 16vw, 200px);
  aspect-ratio: 1;
  transform: translateY(-58%);
  border-radius: 50%;
  background: var(--acento-suave);
  z-index: 0;
}
.final.bien .final-alto::before { background: #DCF5E6; }
.final.mal  .final-alto::before { background: #FDE4E9; }

/* La corrección al momento del test, como en la app.
 *
 * El color lo dice todo antes de leer: verde si acierta, rojo si no. La correcta se marca
 * **siempre**, aunque no la haya elegido — si sólo se marcase su fallo se queda sin saber
 * cuál era, que es justo lo que quería saber. */
.correccion {
  border-radius: var(--r-pequeno);
  padding: 12px 14px;
  margin-bottom: 14px;
  border: 1px solid transparent;
}
.correccion.bien { background: #EAF8F0; border-color: #C9EBD8; }
.correccion.mal  { background: #FDECEF; border-color: #F6D3DA; }
.correccion-cabeza {
  display: flex; align-items: center; gap: 7px;
  font-weight: 800; font-size: 13px; margin-bottom: 4px;
}
.correccion.bien .correccion-cabeza { color: var(--ok); }
.correccion.mal  .correccion-cabeza { color: var(--peligro); }
.correccion-texto { margin: 0; font-size: 14px; line-height: 1.5; }

/* Las opciones ya contestadas. `disabled` las apaga en el navegador, así que hay que
 * devolverles el color a mano: sin esto salían las cuatro grises y no se distinguía la
 * buena de la fallada, que es lo único que importa en ese momento. */
.opcion:disabled { cursor: default; opacity: 1; }
.opcion.acertada {
  border-color: var(--ok); background: #EAF8F0; color: var(--tinta);
}
.opcion.acertada .letra { background: var(--ok); color: #fff; }
.opcion.acertada > svg, .opcion.acertada svg { color: var(--ok); }
.opcion.fallada {
  border-color: var(--peligro); background: #FDECEF; color: var(--tinta);
}
.opcion.fallada .letra { background: var(--peligro); color: #fff; }
.opcion.fallada svg { color: var(--peligro); }
/* Las que no se eligieron: se apagan para que no compitan, pero se siguen leyendo. */
.opcion.apagada { opacity: .5; }

/* La cara de Rotermeller en el chat: su retrato redondo, no un avatar de cuerpo entero.
 * `object-fit: cover` sobre un disco — el render ya viene circular, pero así aguanta si
 * algún día llega uno cuadrado. */
.cara-tutor {
  width: 38px; height: 38px;
  border-radius: 50%;
  object-fit: cover;
  display: block;
}

/* Explícamelo: elegir entre hablar y escribir.
 *
 * **Dos pestañas de verdad, no dos botones sueltos.** Antes «Escribir» sólo enfocaba un
 * área que ya estaba a la vista: se leía como una elección y no elegía nada. Ahora cada
 * una manda lo que se ve debajo, y por eso se pintan como un selector con la activa
 * marcada — la forma tiene que decir que son excluyentes. */
.modos {
  display: grid; grid-template-columns: 1fr 1fr; gap: 6px;
  padding: 5px; margin-bottom: 16px;
  background: var(--fondo); border-radius: var(--capsula);
}
.modo {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 10px 14px; border: 0; border-radius: var(--capsula);
  background: transparent; color: var(--secundario);
  font: inherit; font-weight: 600; font-size: 14px; cursor: pointer;
}
.modo.activo {
  background: var(--superficie); color: var(--tinta);
  box-shadow: var(--sombra-tarjeta);
}

/* El micrófono, grande y centrado: en modo voz es LA acción de la pantalla, no un botón
 * más de una fila. */
.micro-caja { display: grid; justify-items: center; gap: 10px; padding: 10px 0 4px; }
.micro-caja .grabar {
  width: 76px; height: 76px; border-radius: 50%;
  display: grid; place-items: center; padding: 0;
}
.micro-pie { margin: 0; color: var(--secundario); font-size: 14px; text-align: center; }

.area-explicacion {
  width: 100%; max-height: none; min-height: 150px;
  border-radius: var(--r-pequeno); resize: vertical;
}

.acciones-explicar { display: flex; gap: 10px; align-items: center; margin-top: 16px; }
/* El primario, ancho: es el final del camino de la pantalla y tiene que pesar más que
 * «Empezar de nuevo», que sólo deshace. */
.acciones-explicar .boton.ancho { flex: 1; justify-content: center; height: 50px; }
@media (max-width: 620px) {
  .acciones-explicar { flex-direction: column; align-items: stretch; }
}

/* El botón «Ir al Tutor» de la columna de Hablar. `.img-boton` a secas es blanco —así es
 * el de la promo de Tests— y aquí el dibujado debajo es morado, así que sin esto se vería
 * un botón blanco encima de uno morado. Las medidas de Ruben: degradado #6D39F7→#7C32FF,
 * cápsula, texto blanco y su sombra teñida. */
.img-boton.morado {
  background: linear-gradient(90deg, #6D39F7, #7C32FF);
  color: #FFFFFF;
  box-shadow: 0 8px 24px rgba(109, 57, 247, .20);
}

/* Los tickers: el retrato redondo de la tarjeta de ánimo. Cuadrado y recortado en círculo
 * —el render ya viene circular, pero así aguanta si llega uno que no lo es—. */
.ticker {
  width: 76px; height: 76px; flex: none;
  border-radius: 50%;
  object-fit: cover;
  display: block;
}

/* El botón de «Hablar con Rotermeller», encima del render. Las medidas de Ruben: degradado
 * #5530F5 → #8128F6 y cápsula. `.heroe-img-boton` a secas es morado plano. */
.heroe-img-boton.degradado {
  background: linear-gradient(90deg, #5530F5, #8128F6);
  box-shadow: 0 10px 28px rgba(85, 48, 245, .22);
}

/* El logo nuevo lleva la corona, el nombre y el lema en un solo dibujo, así que ya no es
 * una pieza que acompaña a un texto: es la marca entera. Se centra en la barra y se le
 * deja aire por debajo, que es lo que antes daba el `<div class="lema">` que se ha
 * quitado. `width: auto` para que mande el alto y no se estire. */
.lateral-marca { justify-content: center; padding: 4px 10px 16px; }
/* **Alto fijo y ancho automático.** Con sólo `width: auto` mandaba la regla base de
 * `.logo` y se pintaba a 64 px de alto pidiendo 40 (medido: 202x64 en un hueco de 202) —
 * o sea, la marca más grande de lo previsto y comiéndose el aire de la barra. Poniendo el
 * alto aquí no hay nada que pueda inflarlo. */
.lateral-marca .logo { height: 60px; width: auto; max-width: 100%; }
/* En la barra encogida no cabe el nombre entero: se recorta a la corona y el arranque, que
 * es lo que hace cualquier marca en un carril de 66 px. */
.lateral.mini .lateral-marca { padding: 4px 0 12px; }

/* ---------------------------------------------------------------------------
   DOCUMENTOS · el temario en PDF

   Tres pantallas dentro de la misma sección —la lista, el índice y el lector—, así que
   aquí hay tres bloques. Lo único que no es «una tarjeta más» es el lector: un apartado
   de temario son cuatro mil caracteres seguidos y se lee o no se lee según la medida de
   línea y el interlineado, no según lo bonito que quede.
   --------------------------------------------------------------------------- */

.doc-tarjeta {
  display: flex; align-items: center; gap: 14px; width: 100%;
  text-align: left; cursor: pointer;
}
.doc-tarjeta + .doc-tarjeta { margin-top: var(--e-md); }
.doc-icono {
  width: 44px; height: 44px; flex: none;
  border-radius: 14px; display: grid; place-items: center;
}
.doc-titulo { display: block; font-weight: 700; font-size: 16px; }
.doc-pie { display: block; font-size: 13px; color: var(--secundario); margin-top: 3px; }
.doc-avance { display: flex; align-items: center; gap: 10px; margin-top: 8px; }
/* La barra no puede comerse el ancho entero: al lado va cuántos llevas. */
.doc-avance .progreso { flex: 1; min-width: 60px; max-width: 220px; }
.doc-marcas { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.doc-tarjeta .doc-marcas { margin-top: 8px; }

/* --- el índice --- */

.doc-fila { align-items: center; gap: 12px; }
/* El cuerpo pulsable es un botón dentro de una caja que no lo es: el HTML no admite un
 * botón dentro de otro, y el círculo del estado tiene que poder pulsarse sin abrir el
 * apartado. Es el mismo montaje que `filaCasilla`. */
.doc-boton {
  background: none; border: 0; padding: 0; text-align: left; cursor: pointer;
  font: inherit; color: inherit; min-width: 0;
}
.doc-circulo {
  width: 26px; height: 26px; flex: none;
  border-radius: 50%; padding: 0; cursor: pointer;
}

/* --- el lector --- */

.doc-texto {
  /* **65 caracteres de medida.** Una línea de 900 px de temario no se lee: el ojo pierde
   * el renglón al volver. Es lo único de este bloque que no es estética. */
  max-width: 68ch;
  font-size: 16px; line-height: 1.7;
  color: var(--tinta);
  white-space: normal;
  overflow-wrap: anywhere;
}

/* --- los bloques de lectura (puerto de `LectorSeccion` de la app) ---
 *
 * El temario, el resumen y el esquema se pintan con las mismas piezas: si el resumen se
 * leyera con otra letra que el apartado, cambiar de uno a otro obligaría a reaprender la
 * página. Lo que cambia respecto al móvil es la **medida**: en el iPhone manda el ancho de
 * la pantalla y aquí manda el ojo, así que la columna se topa en 68ch y el cuerpo sube a
 * 16,5 px con más interlineado, que es lo que aguanta una sesión larga en un monitor. */

.doc-lectura, .doc-texto { max-width: 68ch; }
.doc-lectura > * + *, .doc-texto > * + * { margin-top: 18px; }
/* **Un título agarra a su párrafo.** Con el mismo aire arriba y abajo, un epígrafe flota
 * entre dos bloques y no se sabe a cuál pertenece; el espacio va DELANTE del título, no
 * detrás. Es lo mismo que hace la app con su `padding(.top)`. */
.doc-lectura > .lec-titulo + *, .doc-texto > .lec-titulo + * { margin-top: 8px; }

.lec-parrafo {
  margin: 0;
  font-size: 16.5px; line-height: 1.72;
  color: var(--tinta);
  overflow-wrap: anywhere;
}

/* Dos escalones y no cinco: en una columna de 700 px más niveles no se distinguen y sólo
 * hacen ruido. `.uno` es el epígrafe que manda. */
.lec-titulo {
  margin: 26px 0 0; font-weight: 700; line-height: 1.35;
  color: var(--tinta);
  font-size: 17px;
}
.lec-titulo.uno { font-size: 20px; margin-top: 30px; }
.doc-lectura > .lec-titulo:first-child,
.doc-texto > .lec-titulo:first-child { margin-top: 0; }

/* **La marca en su columna y el texto alineado con el texto.** Con la viñeta pegada, la
 * segunda línea de un punto largo vuelve al margen y la lista deja de leerse como lista. */
.lec-lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px; }
.lec-lista li { display: flex; align-items: baseline; gap: 10px; font-size: 16.5px; line-height: 1.6; color: var(--tinta); }
.lec-marca { flex: none; font-weight: 700; color: #0E9BAF; min-width: 12px; text-align: right; }
.lec-lista.numerada .lec-marca { min-width: 24px; }

/* El recuadro de la academia. Filo de color y fondo tenue: se reconoce de un vistazo al
 * pasar la página, que es para lo que está. Y **aquí está el naranja**: es de los
 * «Ojo al dato» del propio temario, no un aviso de la web. */
.lec-destacado {
  position: relative;
  border-radius: 12px;
  background: rgba(224, 104, 14, .07);
  padding: 13px 16px 13px 18px;
  overflow: hidden;
}
.lec-destacado::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: #E0680E; border-radius: 2px;
}
.lec-rotulo {
  display: block; margin-bottom: 5px;
  font-size: 11.5px; font-weight: 700; letter-spacing: .06em;
  color: #A34C05;
}
.lec-destacado p { margin: 0; font-size: 16px; line-height: 1.65; color: var(--tinta); }

/* Lo que dice la ley, separado de lo que dice el autor. En una oposición esa diferencia
 * es literalmente la pregunta del examen. */
.lec-cita {
  margin: 0; padding-left: 16px;
  border-left: 3px solid rgba(29, 111, 232, .45);
  font-family: Georgia, "Times New Roman", serif;
  font-style: italic; font-size: 16px; line-height: 1.66;
  color: var(--tinta); opacity: .92;
}
.doc-subrayado {
  color: inherit;
  border-radius: 4px;
  padding: 1px 2px;
  /* El rotulador se ve, pero no tapa: sobre amarillo puro el texto pierde contraste. */
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}
.doc-rotuladores {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--divisor);
}
.doc-rotulador {
  width: 26px; height: 26px; flex: none;
  border-radius: 50%; border: 2px solid var(--divisor); padding: 0; cursor: pointer;
}
.doc-rotulador.fijo { cursor: default; width: 18px; height: 18px; }
.doc-acciones { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 12px; }
.doc-pasos { display: flex; align-items: center; gap: 12px; }

/* El sello de lo que ha escrito la IA. **No es un adorno**: dice que lo que se lee no es
 * el temario sino lo que un modelo entendió del temario, y por eso va antes del texto y
 * no en letra pequeña al final. */
.sello-ia {
  display: flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 600;
  color: var(--acento);
  background: var(--acento-suave);
  border-radius: var(--capsula);
  padding: 5px 10px;
  margin-bottom: 12px;
  width: fit-content;
  max-width: 100%;
}
.sello-ia svg { flex: none; }
.sello-ia span { overflow-wrap: anywhere; }

/* ---------------------------------------------------------------------------
   CONVOCATORIAS
   --------------------------------------------------------------------------- */

.conv-dato {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 0;
  border-bottom: 1px solid var(--divisor);
}
.conv-dato:last-child { border-bottom: 0; padding-bottom: 0; }
.conv-dato .titulo { font-weight: 600; font-size: 15px; }
.conv-dato .detalle { font-size: 13px; color: var(--secundario); margin-top: 2px; }
/* El valor no se parte a mitad de palabra pero tampoco puede empujar la tarjeta: se le
 * deja alinearse a la derecha y envolver si hace falta. */
.conv-valor {
  font-weight: 700; font-size: 15px; text-align: right;
  flex: none; max-width: 55%; overflow-wrap: anywhere;
}
.conv-enlace {
  font-weight: 700; font-size: 14px; color: var(--acento);
  text-decoration: none; flex: none;
  border: 1px solid var(--acento-suave); border-radius: var(--capsula);
  padding: 5px 12px;
}
.conv-enlace:hover { background: var(--acento-suave); }

/* Cuatro cifras repartidas por la tarjeta (el semáforo del Temario y el de un documento).
 * Con `gap` fijo se apiñaban a la izquierda y dejaban media tarjeta vacía, que se lee
 * como si faltara algo por cargar. */
.cuatro-cifras {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}
.cuatro-cifras .cifra { text-align: left; min-width: 0; }

/* **La lista de secciones desplaza, y hay que verlo.** El pie de la barra (el chip de
 * sincronía y el modo foco) va clavado abajo y los enlaces pasan por debajo: en el perfil
 * de oposiciones son catorce secciones y en una ventana normal las últimas quedan fuera.
 * Sin ninguna señal, la barra parece cortada a cuchillo — y quien no sepa que se desplaza
 * no encuentra Ajustes.
 *
 * El degradado va sobre el PIE y no como máscara de la lista: una máscara desvanece la
 * última fila siempre, haya o no haya nada más abajo, y entonces miente al revés. */
.lateral-pie { position: relative; }
.lateral-pie::before {
  content: "";
  position: absolute; left: 0; right: 0; bottom: 100%;
  height: 26px;
  background: linear-gradient(to top, var(--superficie, #fff), transparent);
  pointer-events: none;
}

/* **Una pastilla larga no puede descolocar la fila entera.** En universidad las
 * asignaturas se llaman «Cálculo I» y no se nota; en oposiciones son «Tema 8. El
 * procedimiento administrativo común» y la lista de sesiones salía en zigzag, con el texto
 * de cada fila empezando a una altura distinta. Se le pone tope y se corta con puntos
 * suspensivos: el nombre entero sigue estando en el `title` y en la propia sección.
 *
 * `flex: none` para que no la encoja el hueco, y `min-width` para que las filas queden
 * alineadas entre sí — que es lo que se estaba perdiendo. */
.fila > .pastilla {
  flex: none;
  min-width: 132px;
  max-width: 190px;
  overflow: hidden;
  text-overflow: ellipsis;
  display: inline-block;
  line-height: 20px;
}

/* Por debajo de 900 px la pastilla se queda sin sitio: pierde el mínimo y encoge. */
@media (max-width: 900px) {
  .fila > .pastilla { min-width: 0; max-width: 120px; }
}

/* ---------------------------------------------------------------------------
   EL SELECTOR DE FUENTE (de qué va el test o la explicación)

   Sustituye a un `<select>` que no se podía vestir ni leer: cuarenta y tantas líneas
   planas, sin iconos, sin jerarquía y con las sangrías descartadas por el propio
   desplegable. Mismo motivo y mismo trato que el selector de fecha.
   --------------------------------------------------------------------------- */

.selfuente-caja { min-width: 0; }
.selfuente {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--divisor); border-radius: var(--r-pequeno);
  background: var(--superficie); color: var(--tinta);
  font: inherit; text-align: left; cursor: pointer;
}
.selfuente:hover { border-color: var(--acento); }
.selfuente[aria-expanded="true"] { border-color: var(--acento); box-shadow: 0 0 0 3px var(--acento-suave); }
.selfuente > svg:last-child { flex: none; color: var(--secundario); transform: rotate(90deg); }
.selfuente-rotulo { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; }
.selfuente-titulo {
  display: block; font-weight: 600; font-size: 15px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.selfuente-detalle {
  display: block; font-size: 12.5px; color: var(--secundario);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.selfuente-panel {
  position: fixed; inset: auto; margin: 0; z-index: 95;
  max-width: calc(100vw - 16px);
  padding: 0; overflow: hidden;
  border: 1px solid var(--divisor); border-radius: var(--r-medio);
  background: var(--superficie); color: var(--tinta);
  box-shadow: 0 18px 48px rgba(24, 16, 56, .18);
}
.selfuente-panel:not([popover]) { display: none; }
.selfuente-panel:not([popover]).visible { display: block; }

.selfuente-busca {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px; border-bottom: 1px solid var(--divisor);
  color: var(--secundario);
}
.selfuente-busca input {
  flex: 1; border: 0; background: none; font: inherit; font-size: 14px;
  color: var(--tinta); outline: none; padding: 0; min-width: 0;
}

/* **El panel se desplaza, no crece sin fin.** Un temario de 45 apartados no cabe en
 * ninguna pantalla, y un panel más alto que la ventana deja las últimas opciones fuera. */
.selfuente-lista { max-height: min(50vh, 420px); overflow-y: auto; padding: 6px 0; }

.selfuente-grupo {
  display: flex; align-items: center; gap: 7px;
  padding: 9px 12px 5px;
  font-size: 11.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  color: var(--secundario);
}
.selfuente-grupo svg { flex: none; }
.selfuente-cuenta {
  margin-left: auto; letter-spacing: 0; font-weight: 600;
  background: var(--acento-suave); color: var(--acento);
  border-radius: var(--capsula); padding: 1px 7px;
}

.selfuente-op {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 7px 12px; border: 0; background: none; cursor: pointer;
  font: inherit; color: inherit; text-align: left;
}
.selfuente-op:hover { background: var(--acento-suave); }
.selfuente-op.activa { background: var(--acento-suave); }
.selfuente-op.activa .selfuente-titulo { color: var(--acento); }
.selfuente-op svg { flex: none; color: var(--acento); }
.selfuente-op .selfuente-titulo { font-weight: 500; }
.selfuente-op.activa .selfuente-titulo { font-weight: 700; }
.selfuente-vacio { padding: 18px 12px; text-align: center; font-size: 14px; color: var(--secundario); }

/* El filete de los apartados: **la sangría sola no basta** para ver que cuelgan de su
 * documento cuando la lista es larga y hay que desplazarla — se pierde la referencia del
 * padre en cuanto sale de la pantalla. */
.selfuente-op[style*="padding-left: 2"],
.selfuente-op[style*="padding-left: 4"],
.selfuente-op[style*="padding-left: 5"] { position: relative; }
.selfuente-op[style*="padding-left: 2"]::before,
.selfuente-op[style*="padding-left: 4"]::before,
.selfuente-op[style*="padding-left: 5"]::before {
  content: ""; position: absolute; left: 18px; top: 0; bottom: 0;
  width: 2px; border-radius: 2px; background: var(--divisor);
}
.selfuente-op.activa::before { background: var(--acento); }

/* ---------------------------------------------------------------------------
   LAS LÁMINAS DE ESQUEMA

   Los cuatro esquemas dibujados como en la lámina que pasó Ruben: cinta con el tipo, la
   marca a la derecha, titular grande y el dibujo debajo. El formato guardado sigue siendo
   el mismo texto de líneas con guiones que escribe y lee la app — lo que cambia es que
   aquí se pinta la forma en vez de la lista.
   --------------------------------------------------------------------------- */

.lamina {
  margin: 0;
  background: var(--superficie);
  border: 1px solid var(--divisor);
  border-radius: 18px;
  padding: 20px 22px 22px;
}
.lamina-alto { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.lamina-cinta {
  background: var(--acento-suave); color: var(--acento);
  border-radius: var(--capsula); padding: 4px 12px;
  font-size: 11px; font-weight: 700; letter-spacing: .09em;
}
.lamina-marca {
  margin-left: auto; color: var(--acento);
  font-size: 12.5px; font-weight: 600; opacity: .85;
}
.lamina-titulo { margin: 0; font-size: 26px; line-height: 1.2; font-weight: 700; color: var(--tinta); }
.lamina-sub { margin: 4px 0 18px; font-size: 14px; color: var(--secundario); }

/* Lo común a los cuatro: la bolita de los puntos y el punto de detalle. */
.esq-punto {
  display: flex; align-items: flex-start; gap: 8px;
  margin: 0 0 5px; font-size: 14px; line-height: 1.5; color: var(--tinta);
}
.esq-punto:last-child { margin-bottom: 0; }
.esq-punto.hondo { padding-left: 16px; }
.esq-punto.mini { font-size: 12.5px; margin-bottom: 3px; }
.esq-bolita {
  flex: none; width: 6px; height: 6px; margin-top: 7px;
  border-radius: 50%; background: var(--acento);
}
.esq-linea { margin: 0 0 6px; font-size: 14.5px; line-height: 1.5; color: var(--tinta); }

/* --- 1 · Árbol: pastilla a la izquierda, lo que cuelga a la derecha --- */
.esq-arbol .esq-fila {
  display: grid; grid-template-columns: 128px minmax(0, 1fr);
  gap: 18px; align-items: start;
  padding: 11px 0;
  border-top: 1px solid var(--divisor);
}
.esq-arbol .esq-fila:first-child { border-top: 0; padding-top: 0; }
.esq-etiqueta {
  background: var(--acento-suave); color: var(--acento);
  border-radius: 9px; padding: 5px 10px;
  font-size: 13px; font-weight: 700; text-align: center;
  overflow-wrap: anywhere;
}

/* --- 2 · Línea de tiempo: los hitos en fila, sobre su hilo --- */
/* **Se desplaza de lado, no reflúa.** Una línea de tiempo partida en tres renglones deja
 * de ser una línea de tiempo. */
.esq-tiempo { overflow-x: auto; padding-bottom: 6px; }
.esq-hilo { display: flex; align-items: flex-start; gap: 0; min-width: min-content; }
.esq-hito {
  display: flex; flex-direction: column; align-items: center;
  min-width: 148px; max-width: 190px; padding: 0 8px;
  position: relative;
}
/* El hilo pasa por detrás de los círculos, a su altura. */
.esq-hito::before {
  content: ""; position: absolute; top: 41px; left: 0; right: 0; height: 2px;
  background: var(--divisor);
}
.esq-hito:first-child::before { left: 50%; }
.esq-hito:last-child::before { right: 50%; }
.esq-fecha { font-size: 14px; font-weight: 700; color: var(--acento); margin-bottom: 8px; }
.esq-nodo {
  position: relative; z-index: 1;
  width: 34px; height: 34px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--acento-suave); color: var(--acento);
  border: 2px solid var(--superficie);
}
.esq-tarjeta {
  margin-top: 14px; width: 100%;
  border: 1px solid var(--divisor); border-radius: 12px;
  padding: 10px 11px;
  font-size: 12.5px;
}
.esq-tarjeta .esq-punto { font-size: 12.5px; }

/* --- 3 · Comparativa --- */
.esq-tabla-caja { overflow-x: auto; }
.esq-tabla { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.esq-tabla th, .esq-tabla td {
  text-align: left; padding: 9px 12px;
  border-bottom: 1px solid var(--divisor);
  vertical-align: top;
}
.esq-tabla thead th {
  background: var(--acento-suave); color: var(--acento);
  font-weight: 700; font-size: 12.5px;
  border-bottom: 0;
}
.esq-tabla thead th:first-child { border-top-left-radius: 10px; border-bottom-left-radius: 10px; }
.esq-tabla thead th:last-child { border-top-right-radius: 10px; border-bottom-right-radius: 10px; }
.esq-tabla tbody th { font-weight: 700; color: var(--acento); white-space: nowrap; }
.esq-columnas { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 16px; }
.esq-columna { border: 1px solid var(--divisor); border-radius: 12px; padding: 12px 14px; }
.esq-columna h4 { margin: 0 0 8px; font-size: 14.5px; color: var(--acento); }

/* --- 4 · Mapa mental --- */
.esq-mapa {
  position: relative;
  display: grid; grid-template-columns: 1fr auto 1fr; gap: 24px; align-items: center;
}
/* Los conectores, en una capa por detrás y en porcentajes: siguen a las tarjetas cuando
 * cambia el ancho sin medir nada en JavaScript. */
/* El SVG va por detrás y **en píxeles del contenedor**, no en una rejilla de porcentajes
 * deformada: los hilos se calculan midiendo dónde está cada tarjeta (ver `conectar`). */
.esq-hilos { position: absolute; inset: 0; pointer-events: none; z-index: 0; overflow: visible; }
.esq-hilos path {
  fill: none; stroke: var(--acento); stroke-width: 1.5; opacity: .5;
  stroke-linecap: round;
}
.esq-remate { fill: var(--acento); opacity: .75; }
.esq-lado { display: flex; flex-direction: column; gap: 18px; position: relative; z-index: 1; }
.esq-rama { display: flex; gap: 10px; align-items: flex-start; }
.esq-rama h5 { margin: 0 0 6px; font-size: 14px; font-weight: 700; color: var(--tinta); }
.esq-rama-icono {
  flex: none; width: 30px; height: 30px; border-radius: 9px;
  display: grid; place-items: center;
  background: var(--acento-suave); color: var(--acento);
}
.esq-centro {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  background: var(--acento-suave); color: var(--acento);
  border-radius: 16px; padding: 20px 22px;
  text-align: center; max-width: 190px;
}
.esq-centro strong { font-size: 16px; line-height: 1.3; color: var(--tinta); }
.esq-centro-icono { display: grid; place-items: center; }

/* En una columna estrecha el mapa no cabe en tres columnas: se apila y los hilos sobran. */
@media (max-width: 760px) {
  .esq-mapa { grid-template-columns: 1fr; }
  .esq-hilos { display: none; }
}

/* **La lámina ES la tarjeta, no va dentro de otra.** Metida en la tarjeta «Esquema»
 * quedaba un marco dentro de otro, que es justo lo que la maqueta no tiene: pierde el
 * borde y el fondo y se queda con su cabecera. */
.tarjeta > .lamina,
.doc-lectura > .lamina { border: 0; padding: 4px 0 0; background: none; }

/* En el mapa, la columna de la izquierda mira hacia el centro: es lo que hace que el
 * dibujo se lea como un mapa y no como dos listas con un cuadro en medio. */
/* **Las ramas de la izquierda NO se invierten.** Se probó con el icono y el texto girados
 * hacia el centro y en la lámina de Ruben van igual que las de la derecha: girarlas hace
 * que las dos mitades se lean en direcciones distintas. */
.esq-centro { padding: 22px 24px; }
.esq-centro strong { font-size: 17px; }

/* --- El árbol, como el ESQUEMA 1 de la lámina: nº, rótulo, cuándo y qué --- */
.esq-arbol .esq-fila {
  grid-template-columns: 190px minmax(0, 1fr);
  gap: 20px;
  align-items: stretch;
}
.esq-rotulo {
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--acento-suave); border-radius: 12px; padding: 12px 13px;
}
.esq-n {
  flex: none; width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--acento); color: var(--acento-texto, #fff);
  font-size: 12.5px; font-weight: 700;
}
.esq-arbol .esq-etiqueta {
  background: none; padding: 0; text-align: left;
  color: var(--tinta); font-size: 14px; line-height: 1.35;
}
/* Dos columnas dentro: el cuándo estrecho y a la izquierda, el qué ocupando el resto. Es
 * lo que deja leer la columna de fechas en vertical de un vistazo. */
.esq-par { display: grid; grid-template-columns: 128px minmax(0, 1fr); gap: 14px; padding: 3px 0; }
.esq-par.solo { grid-template-columns: minmax(0, 1fr); }
.esq-cuando { font-size: 13px; font-weight: 600; color: var(--acento); }
.esq-que { font-size: 13.5px; line-height: 1.5; color: var(--tinta); }

/* --- Las dos acciones de la lámina --- */
.lamina-caja { display: flex; flex-direction: column; gap: 12px; }
.lamina-acciones { display: flex; gap: 8px; flex-wrap: wrap; }

/* --- Verla en grande --- */
/* **Sin la barra lateral ni la columna de apoyo**: lo que estorba para mirar un esquema es
 * todo lo demás. Y con su propio desplazamiento, que una línea de tiempo larga no cabe. */
.lamina-velo { align-items: flex-start; }
.lamina-grande {
  position: relative;
  width: min(1200px, calc(100vw - 32px));
  max-height: calc(100vh - 48px);
  overflow: auto;
  margin: 24px auto;
  background: var(--superficie);
  border-radius: 20px;
  padding: 26px 28px 22px;
  box-shadow: 0 24px 64px rgba(24, 16, 56, .28);
}
.lamina-cerrar { position: absolute; top: 14px; right: 14px; z-index: 2; }
.lamina-grande .lamina { border: 0; padding: 0; }
.lamina-grande .lamina-titulo { font-size: 30px; }
/* En grande sí caben las medidas de la lámina de verdad. */
.lamina-grande .esq-arbol .esq-fila { grid-template-columns: 230px minmax(0, 1fr); }
.lamina-grande .esq-hito { min-width: 168px; }

/* --- Descargar en PDF ---
 *
 * Se imprime la página: el diálogo del navegador ya trae «Guardar como PDF», sale con las
 * fuentes y los vectores intactos —un PDF hecho con canvas saldría pixelado— y no añade
 * una librería de 300 KB para algo que el sistema hace mejor. Lo nuestro son estas reglas.
 */
.solo-al-imprimir { display: none; }

@media print {
  /* Todo fuera menos la lámina: la barra, la columna de apoyo, los botones y el velo. */
  body.imprimiendo > #raiz,
  body.imprimiendo .velo { display: none !important; }
  body.imprimiendo .solo-al-imprimir { display: block; }
  body.imprimiendo { background: #fff; }

  .solo-al-imprimir .lamina { border: 0; padding: 0; }
  /* **Nada de partirse entre dos páginas.** Una fila de la cronología cortada a la mitad,
   * o un hito sin su tarjeta, es exactamente lo que hace inútil un esquema impreso. */
  .esq-fila, .esq-hito, .esq-rama, .esq-columna, .esq-tabla tr { break-inside: avoid; }
  .lamina-titulo, .lamina-sub { break-after: avoid; }
  .lamina-acciones, .lamina-cerrar { display: none !important; }
  /* El fondo de las pastillas y de la cabecera de la tabla tiene que imprimirse: sin esto
   * el navegador se los come y la tabla sale sin cabecera distinguible. */
  .esq-rotulo, .esq-etiqueta, .esq-nodo, .esq-centro, .esq-rama-icono,
  .esq-tabla thead th, .lamina-cinta { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  /* Y la línea de tiempo no puede desplazarse en papel: se deja envolver. */
  .esq-tiempo { overflow: visible; }
  .esq-hilo { flex-wrap: wrap; gap: 12px; }
  .esq-hito::before { display: none; }
}

/* El botón de cerrar se comía la marca de la lámina («roterr… ×»): se le hace sitio. */
.lamina-grande .lamina-alto { padding-right: 44px; }
/* Y el mapa, en grande, respira: con la altura por contenido se quedaba apelotonado
 * arriba dejando media lámina vacía, que es lo contrario de «verlo en grande». */
.lamina-grande .esq-mapa { min-height: 380px; gap: 40px; padding: 12px 0; }
.lamina-grande .esq-rama h5 { font-size: 15px; }
.lamina-grande .esq-punto.mini { font-size: 13.5px; }
.lamina-grande .esq-centro { max-width: 230px; }
.lamina-grande .esq-centro strong { font-size: 19px; }

/* **Una lámina no puede empujar el ancho de lo que la contiene.**
 *
 * La línea de tiempo lleva `min-width: min-content` en su hilo para no partirse en varios
 * renglones, y eso, sin un `min-width: 0` por encima, se propaga hacia arriba: la lámina
 * pedía el ancho de sus ocho hitos y en una rejilla se comía a las de al lado — medido en
 * el banco, la cronología se quedaba en 355 px y cada descripción salía en cinco líneas.
 * Es la misma trampa que ya está apuntada para `.contenido` y la rejilla del Horario. */
.lamina, .lamina-caja, .esq, .esq-cuerpo, .esq-fila > * { min-width: 0; }

/* Y con sitio de verdad, la columna del «qué» respira: la del «cuándo» se queda en su
 * ancho y no roba, pero por debajo de cierto punto es mejor apilar que partir cada frase
 * en cinco renglones. */
.esq-par { grid-template-columns: 118px minmax(160px, 1fr); }
@media (max-width: 620px) {
  .esq-par { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .esq-arbol .esq-fila { grid-template-columns: minmax(0, 1fr); gap: 10px; }
}

/* La línea de tiempo, como en la lámina: **todas las tarjetas arrancan a la misma altura**
 * y el hilo pasa recto por los círculos. Con la altura por contenido quedaban escalonadas
 * y el dibujo dejaba de leerse como una línea. */
.esq-hilo { align-items: stretch; }
.esq-hito { justify-content: flex-start; }
.esq-tarjeta { flex: 1; }

/* Los hitos, más estrechos: en la lámina caben nueve en el ancho de una tarjeta, y con
 * 148 px cabían cinco y el resto quedaba fuera del desplazamiento. */
.esq-hito { min-width: 112px; max-width: 150px; padding: 0 6px; }
.esq-tarjeta { padding: 9px 10px; font-size: 12px; }
.esq-tarjeta .esq-punto { font-size: 12px; gap: 6px; }
.esq-fecha { font-size: 13px; }

/* La banda de abajo de la línea de tiempo: lo que vino después y no es un hito. */
.esq-banda {
  display: flex; align-items: center; gap: 22px; flex-wrap: wrap;
  margin-top: 18px; padding: 14px 16px;
  background: var(--acento-suave); border-radius: 14px;
}
.esq-banda-rotulo {
  display: flex; align-items: center; gap: 8px; flex: none;
  font-size: 13.5px; font-weight: 700; color: var(--acento);
}
.esq-banda-icono {
  width: 28px; height: 28px; border-radius: 9px; display: grid; place-items: center;
  background: var(--superficie); color: var(--acento);
}
.esq-banda-items { display: flex; gap: 26px; flex-wrap: wrap; flex: 1; }
.esq-banda-item { display: flex; align-items: flex-start; gap: 8px; font-size: 13px; }
.esq-banda-item strong { display: block; color: var(--tinta); font-size: 14px; }
.esq-banda-item span { color: var(--secundario); line-height: 1.45; }

/* Los hitos, al ancho de la lámina: nueve tienen que caber en 750 px sin desplazarse, que
 * es lo que hace que se lea como una línea y no como un carrusel. */
.esq-hito { min-width: 86px; max-width: 120px; padding: 0 4px; }
.esq-tarjeta { padding: 8px 8px; font-size: 11.5px; }
.esq-tarjeta .esq-punto { font-size: 11.5px; gap: 5px; margin-bottom: 4px; }
.esq-fecha { font-size: 12px; text-align: center; line-height: 1.25; }

/* Nueve hitos tienen que caber en el ancho de una lámina (≈750 px). Con 86 px se salían
 * tres y la línea acababa cortada por la derecha, que es peor que apretada: una línea de
 * tiempo a la que le falta el final no cuenta el proceso. */
.esq-hito { min-width: 74px; max-width: 104px; padding: 0 3px; }
.esq-hilo { gap: 2px; }
.esq-tarjeta { padding: 7px 7px; font-size: 11px; border-radius: 10px; }
.esq-tarjeta .esq-punto { font-size: 11px; gap: 5px; margin-bottom: 4px; line-height: 1.4; }
.esq-tarjeta .esq-linea { font-size: 11px; line-height: 1.4; margin-bottom: 5px; }
.esq-fecha { font-size: 11.5px; }
.esq-nodo { width: 30px; height: 30px; }
.esq-hito::before { top: 38px; }

/* **Las ramas se arriman al centro, no al borde de la lámina.**
 *
 * Cada `.esq-rama` ocupaba el ancho entero de su columna, así que su borde interior —de
 * donde tira el hilo— caía en medio del hueco: los conectores de la izquierda morían en el
 * aire a mitad de camino y el dibujo dejaba de parecer un mapa. Con las tarjetas ajustadas
 * a su contenido y alineadas hacia dentro, el hilo sale del texto y llega al centro.
 */
/* Aire entre el centro y las ramas: sin él la curva del hilo no tiene sitio donde
 * formarse y sale una recta vertical pegada al centro. */
.esq-mapa { gap: 58px; align-items: center; }
.esq-lado { align-items: flex-start; }
.esq-mapa > .esq-lado:first-of-type { align-items: flex-end; }
.esq-rama { max-width: 310px; width: max-content; }
/* En la columna de la izquierda el icono va pegado al texto y el hilo sale del propio
 * bloque, que es lo que hace que se lea como una rama y no como dos listas sueltas. */
.esq-mapa > .esq-lado:first-of-type .esq-rama { text-align: left; }

/* Cuando el apartado no daba para el esquema pedido: se dice, en vez de dejar la cinta
 * anunciando un cuadro comparativo con un árbol debajo. */
.lamina-caida {
  margin: 0 0 14px; padding: 9px 12px;
  background: var(--past-naranja); color: #8A4A05;
  border-radius: 10px; font-size: 13px;
}
/* Un árbol de una sola rama: sin la columna de la pastilla. */
.esq-arbol.suelto .esq-fila { grid-template-columns: minmax(0, 1fr); }
.esq-titulillo { margin: 0 0 8px; font-size: 15px; font-weight: 700; color: var(--tinta); }

/* Las etiquetas de estado de la lámina de piezas. Cuando un punto del esquema empieza por
 * «Importante», «Dato clave», «Atención»… sale con su pastilla de color en vez de con una
 * bolita: es lo que hace que al repasar el ojo encuentre lo que importa sin leerlo todo. */
.esq-punto.con-etiqueta { align-items: baseline; gap: 8px; }
.esq-tag {
  flex: none; border-radius: var(--capsula); padding: 2px 9px;
  font-size: 11.5px; font-weight: 700; line-height: 1.5;
}
.esq-tag.lila   { background: var(--acento); color: #fff; }
.esq-tag.roja   { background: #FDE7E9; color: #8E1D28; }
.esq-tag.verde  { background: #E4F5EC; color: #0E5D38; }
.esq-tag.azul   { background: #E7EEFD; color: #17458F; }
.esq-tag.ambar  { background: var(--past-naranja); color: #8A4A05; }
.esq-tag.gris   { background: var(--fondo); color: var(--secundario); }
.esq-punto.mini .esq-tag { font-size: 10.5px; padding: 1px 7px; }

/* ═══════════════════════════════════════════════════════════════════════════
   SISTEMA DE ESQUEMAS · especificación de Ruben (6-sep)
   ═══════════════════════════════════════════════════════════════════════════

   Los cuatro esquemas son **un solo producto**: mismo contenedor, mismo header, mismos
   colores, radios, iconos y espaciados. Lo único que cambia entre ellos es cómo se
   organiza la información.

   **La paleta es fija y no sigue al acento del alumno**, que es lo contrario de lo que
   hace el resto de la web. Es deliberado: una lámina es material de estudio que se
   imprime, se comparte y se reconoce como de Rotermeller; si cambiara de color según quien
   la mire, dejaría de ser una identidad. Todos los espaciados son múltiplos de 4. */

.lamina {
  --p: #7657F6; --p-dark: #5034D9; --p-med: #9278FF;
  --p-soft: #F1EDFF; --p-xsoft: #F8F6FF;
  --t1: #151426; --t2: #676278; --t3: #918CA0; --t-body: #27243A;
  --bd: #ECE8F5; --bd-light: #F2EFF8;

  position: relative;
  width: 100%; max-width: 760px; min-height: 540px;
  padding: 28px;
  background: #fff;
  border: 1px solid #F0EDFA;
  border-radius: 20px;
  box-shadow: 0 8px 30px rgba(76, 45, 140, .06);
  box-sizing: border-box;
  overflow: hidden;
  font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  color: var(--t1);
}
/* Dentro de una tarjeta del lector la lámina ya está enmarcada: pierde su propio marco
 * pero conserva TODO lo demás, que es lo que la hace reconocible. */
.tarjeta > .lamina, .doc-lectura > .lamina {
  border: 0; box-shadow: none; padding: 0; min-height: 0; max-width: none;
}

.lamina-alto { display: block; margin: 0; padding: 0; }
.lamina-cinta {
  height: 24px; padding: 0 12px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 999px;
  background: var(--p-soft); color: #6246E5;
  font-size: 11px; font-weight: 700; line-height: 1; letter-spacing: normal;
  text-transform: uppercase;
}
.lamina-marca {
  position: absolute; top: 20px; right: 24px; margin: 0;
  font-size: 13px; font-weight: 500; color: var(--p-med); opacity: 1;
}
.lamina-titulo {
  margin: 10px 0 0;
  font-size: 26px; font-weight: 700; line-height: 1.15; letter-spacing: -.6px;
  color: var(--t1);
}
.lamina-sub { margin: 3px 0 0; font-size: 14px; font-weight: 400; line-height: 1.4; color: var(--t2); }
.lamina .esq { margin-top: 12px; }

/* --- 1 · Jerárquico: número · etapa · fecha · descripción --- */
.esq-arbol { display: flex; flex-direction: column; gap: 8px; }
.esq-arbol .esq-fila {
  width: 100%; min-height: 76px;
  display: grid; grid-template-columns: 36px 140px minmax(0, 1fr);
  gap: 12px; padding: 12px 14px;
  background: var(--p-xsoft); border-radius: 12px; border: 0;
  align-items: start;
}
.esq-n {
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--p); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 700;
}
.esq-etapa { margin: 3px 0 0; font-size: 13px; font-weight: 700; line-height: 1.3; color: var(--t1); }
.esq-par { grid-template-columns: 95px minmax(0, 1fr); gap: 12px; padding: 2px 0; }
.esq-cuando { font-size: 11px; font-weight: 600; line-height: 1.5; color: var(--t-body); }
.esq-que, .esq-linea { font-size: 11px; font-weight: 400; line-height: 1.5; color: var(--t-body); }
.esq-arbol.suelto .esq-fila { grid-template-columns: minmax(0, 1fr); }

/* --- 2 · Línea de tiempo --- */
.esq-tiempo { width: 100%; overflow-x: auto; overflow-y: hidden; padding-top: 35px; }
.esq-hilo { display: flex; position: relative; min-width: 900px; gap: 0; align-items: flex-start; }
/* La línea, por detrás y a la altura de los iconos. */
.esq-hilo::before {
  content: ""; position: absolute; top: 76px; left: 30px; right: 30px;
  height: 2px; background: #BBAEFF;
}
.esq-hito {
  width: 95px; min-width: 95px; max-width: 95px; padding: 0;
  display: flex; flex-direction: column; align-items: center; position: relative;
}
.esq-hito::before { display: none; }
.esq-fecha {
  font-size: 11px; font-weight: 700; color: var(--p-dark);
  text-align: center; margin-bottom: 14px; line-height: 1.3;
}
.esq-nodo {
  width: 44px; height: 44px; border-radius: 50%;
  background: var(--p-soft); color: #6246E5; border: 0;
  display: flex; align-items: center; justify-content: center;
}
.esq-punto-linea {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--p); margin-top: 8px; z-index: 2;
}
.esq-tarjeta {
  width: 88px; min-height: 120px; padding: 10px 8px; margin-top: 10px;
  background: var(--p-xsoft); border: 1px solid var(--bd); border-radius: 10px;
  flex: none;
}
.esq-tarjeta .esq-linea, .esq-tarjeta .esq-punto { font-size: 10px; line-height: 1.4; color: var(--t-body); }
.esq-tarjeta .esq-linea { font-weight: 700; color: var(--t1); }

/* --- Banda de reformas --- */
.esq-banda {
  width: 100%; min-height: 105px; padding: 16px 18px; margin-top: 16px;
  background: #F5F1FF; border-radius: 14px;
  display: grid; grid-template-columns: 150px repeat(3, minmax(0, 1fr)); gap: 0;
  align-items: center;
}
.esq-banda-rotulo { display: flex; align-items: center; gap: 12px; font-size: 13px; font-weight: 700; color: var(--p-dark); }
.esq-banda-icono { width: 40px; height: 40px; background: #ECE5FF; border-radius: 50%; color: #6246E5; }
.esq-banda-items { display: contents; }
.esq-banda-item { display: block; padding: 0 18px; border-left: 1px solid #D8CFF5; }
.esq-banda-item .esq-bolita { display: none; }
.esq-banda-item strong { font-size: 13px; font-weight: 700; color: var(--p-dark); }
.esq-banda-item span { font-size: 11px; line-height: 1.4; color: var(--t-body); }

/* --- 4 · Tabla --- */
.esq-tabla-caja { overflow-x: auto; margin-top: 18px; }
.esq-tabla {
  width: 100%; min-width: 480px;
  border-collapse: separate; border-spacing: 0;
  border: 1px solid var(--bd); border-radius: 12px; overflow: hidden;
}
.esq-tabla thead th {
  height: 32px; background: #EDE7FF; color: var(--p-dark);
  font-size: 11px; font-weight: 700; text-align: left; padding: 7px 10px;
  border: 0; border-radius: 0;
}
.esq-tabla td, .esq-tabla tbody th {
  padding: 6px 10px; font-size: 10.5px; font-weight: 400; line-height: 1.3;
  color: var(--t-body); border-bottom: 1px solid var(--bd); border-right: 1px solid var(--bd);
  vertical-align: top; text-align: left;
}
.esq-tabla tbody th { font-weight: 700; color: var(--p-dark); white-space: normal; }
.esq-tabla td:last-child { border-right: 0; }
.esq-tabla tbody tr:last-child td, .esq-tabla tbody tr:last-child th { border-bottom: 0; }
.esq-tabla tbody td:first-of-type { font-weight: 600; }

/* --- 3 · Mapa mental (posiciones de la spec) --- */
.esq-mapa {
  position: relative; width: 100%; min-height: 390px; margin-top: 20px;
  display: block; gap: 0;
}
.esq-hilos { position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: visible; }
.esq-hilos path { fill: none; stroke: #9278FF; stroke-width: 2; stroke-linecap: round; opacity: 1; }

.esq-centro {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 150px; min-height: 125px; padding: 18px;
  border-radius: 22px;
  background: linear-gradient(135deg, #9C83FF 0%, #7657F6 100%);
  color: #fff; z-index: 2; max-width: none;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; box-sizing: border-box;
}
.esq-centro-icono { margin-bottom: 10px; color: #fff; }
.esq-centro strong { font-size: 16px; font-weight: 700; line-height: 1.25; color: #fff; }

.esq-mapa .esq-rama {
  position: absolute; z-index: 2; width: 195px; max-width: 195px; display: block;
}
.esq-mapa .esq-izq { left: 0; }
.esq-mapa .esq-der { right: 0; }
.esq-rama-alto {
  display: flex; align-items: center; gap: 10px;
  min-height: 38px; padding: 8px 12px;
  background: #F1EDFF; border-radius: 12px;
}
.esq-rama-alto h5 { margin: 0; font-size: 12px; font-weight: 700; color: #151426; line-height: 1.25; }
.esq-rama-icono {
  width: 38px; height: 38px; border-radius: 50%; flex: none;
  background: #F1EDFF; color: #6246E5;
  display: flex; align-items: center; justify-content: center;
}
.esq-mapa .esq-rama-alto .esq-rama-icono { background: #fff; width: 26px; height: 26px; }
/* La lista, sobre el blanco y NO dentro de otra tarjeta. */
.esq-rama-lista {
  margin: 8px 0 0; padding-left: 16px;
  font-size: 11px; line-height: 1.5; color: #27243A;
}
.esq-rama-lista li { margin-bottom: 2px; }

/* --- Responsive de la spec --- */
/* **`screen` y no a secas.** Una hoja A4 tiene ~718 px útiles, así que sin esto la
 * impresión entraba por el corte de móvil: el mapa mental salía en el PDF como una
 * lista vertical con el nodo central al final y sin un solo conector. */
@media screen and (max-width: 1199px) { .lamina { padding: 24px; } .lamina-titulo { font-size: 24px; } }
@media screen and (max-width: 767px) {
  .lamina { padding: 18px; border-radius: 16px; }
  .lamina-titulo { font-size: 22px; }
  .esq-arbol .esq-fila { grid-template-columns: 32px minmax(0, 1fr); }
  .esq-etapa { grid-column: 2; }
  .esq-cuerpo { grid-column: 2; }
  .esq-tabla { min-width: 720px; }
  /* El mapa deja de ser horizontal y pasa a árbol vertical. */
  .esq-mapa { min-height: 0; }
  .esq-mapa .esq-rama, .esq-centro {
    position: static; transform: none; width: 100%; max-width: none; margin-bottom: 16px;
  }
  .esq-hilos { display: none; }
}

/* --- La lámina en el PDF --- */
@media print {
  /* Ancho de la hoja, no los 760 de pantalla: si no, media página queda en blanco. */
  .solo-al-imprimir .lamina {
    max-width: none; width: 100%; min-height: 0;
    border: 0; box-shadow: none; padding: 0;
  }
  /* La marca se solapaba con el título al perder el padding: se recoloca. */
  /* La marca se salía por el canto derecho de la hoja. */
  .solo-al-imprimir .lamina-marca { top: 2px; right: 6px; }
  .solo-al-imprimir .lamina-titulo { padding-right: 110px; }
  /* El mapa se imprime como mapa: horizontal, con sus nodos y sus hilos. */
  .esq-mapa { min-height: 420px; }
  .esq-hilos { display: block !important; }
  .esq-mapa .esq-rama { position: absolute; width: 190px; }
  .esq-centro { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: 150px; }
  /* Y la línea de tiempo cabe en la hoja en vez de irse por el lado. */
  .esq-hilo { min-width: 0; flex-wrap: wrap; row-gap: 16px; }
  .esq-hilo::before { display: none; }
  .esq-hito { width: auto; min-width: 88px; max-width: 110px; }
}

/* En grande la lámina ocupa el panel: con `max-width: 760` se quedaba pequeña a la
 * izquierda dejando 440 px de hueco, que es lo contrario de «verlo en grande». */
.lamina-grande .lamina { max-width: none; }
.lamina-grande .esq-mapa { min-height: 460px; }

/* Cuando la columna de apoyo se queda vacía —dentro de un apartado— la rejilla se colapsa
 * y el contenido ocupa el ancho entero. Sin esto quedaría una franja de 360 px en blanco a
 * la derecha, que es peor que tener la columna. */
.columnas:has(> .lado > div:empty) { grid-template-columns: minmax(0, 1fr); }
.columnas > .lado:has(> div:empty) { display: none; }

/* --- 1 · Árbol jerárquico: ORGANIGRAMA ---
 *
 * Raíz arriba, un bus horizontal y las ramas colgando. **Los conectores son CSS, no SVG
 * medido**: se imprimen igual que se ven y no hay que recalcular nada al cambiar el ancho,
 * que es lo que costó tres intentos en el mapa mental. */
.esq-org { display: flex; flex-direction: column; align-items: center; }
.esq-raiz {
  display: flex; align-items: center; gap: 14px;
  background: var(--p-soft); border-radius: 16px; padding: 16px 26px;
  max-width: 420px;
}
.esq-raiz-icono {
  width: 44px; height: 44px; border-radius: 12px; flex: none;
  background: #fff; color: #6246E5; display: grid; place-items: center;
}
.esq-raiz strong { display: block; font-size: 20px; font-weight: 700; color: var(--t1); line-height: 1.2; }
.esq-anio { display: block; font-size: 16px; font-weight: 700; color: var(--p); }

/* El tronco: la línea vertical que baja de un nivel al siguiente. */
.esq-tronco { width: 2px; height: 24px; background: #BBAEFF; flex: none; }
.esq-tronco.largo { height: 34px; }

.esq-ramas {
  display: grid; grid-template-columns: repeat(var(--n, 4), minmax(0, 1fr));
  gap: 14px; width: 100%;
}
.esq-nodo-arbol { position: relative; padding-top: 22px; }
/* El ramal vertical de cada nodo… */
.esq-nodo-arbol::before {
  content: ""; position: absolute; top: 0; left: 50%; width: 2px; height: 22px;
  background: #BBAEFF;
}
/* …y el bus horizontal, montado con medio tramo por nodo: así llega justo del primero al
 * último y no se sale por los lados. */
.esq-nodo-arbol::after {
  content: ""; position: absolute; top: 0; height: 2px; background: #BBAEFF;
  left: 0; right: 0;
}
.esq-nodo-arbol:first-child::after { left: 50%; }
.esq-nodo-arbol:last-child::after { right: 50%; }
.esq-ramas > .esq-nodo-arbol:only-child::after { display: none; }

.esq-caja { background: var(--p-xsoft); border-radius: 14px; padding: 0 0 12px; height: 100%; }
.esq-caja-alto {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 12px; background: var(--p-soft);
  border-radius: 14px 14px 0 0;
}
.esq-caja-alto strong { display: block; font-size: 13px; font-weight: 700; color: var(--t1); line-height: 1.25; }
.esq-caja-alto .esq-anio { font-size: 13px; }
.esq-caja-icono {
  width: 34px; height: 34px; border-radius: 10px; flex: none;
  background: #fff; color: #6246E5; display: grid; place-items: center;
}
.esq-caja-lista { list-style: none; margin: 10px 0 0; padding: 0 12px; }
.esq-caja-lista li { position: relative; padding-left: 14px; margin-bottom: 10px; }
.esq-caja-lista li::before {
  content: ""; position: absolute; left: 0; top: 6px;
  width: 6px; height: 6px; border-radius: 50%; background: var(--p);
}
.esq-caja-lista strong { display: block; font-size: 11.5px; font-weight: 700; color: var(--t1); }
.esq-caja-lista span { display: block; font-size: 11px; line-height: 1.4; color: var(--t2); }

/* La segunda planta (las reformas) y sus hojas. */
.esq-planta {
  display: flex; align-items: center; gap: 12px;
  background: var(--p-soft); border-radius: 12px; padding: 10px 20px;
}
.esq-planta strong { font-size: 15px; font-weight: 700; color: var(--t1); }
.esq-planta-icono {
  width: 32px; height: 32px; border-radius: 10px; flex: none;
  background: #fff; color: #6246E5; display: grid; place-items: center;
}
.esq-hoja {
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--p-xsoft); border-radius: 12px; padding: 12px;
}
.esq-hoja-icono {
  width: 34px; height: 34px; border-radius: 10px; flex: none;
  background: var(--p-soft); color: #6246E5; display: grid; place-items: center;
}
.esq-hoja-titulo { display: block; font-size: 15px; font-weight: 700; color: var(--p); }
.esq-hoja-texto { display: block; font-size: 11px; line-height: 1.4; color: var(--t-body); margin-top: 2px; }

@media screen and (max-width: 767px) {
  .esq-ramas { grid-template-columns: minmax(0, 1fr); }
  .esq-nodo-arbol::after { display: none; }
}

/* ---- La lámina como imagen ------------------------------------------------
   La imagen va a todo el ancho del lector: para eso se vació la columna de
   apoyo dentro de un apartado. `height:auto` y no una altura fija porque los
   cuatro tipos no tienen la misma proporción —la línea de tiempo es vertical y
   los otros tres apaisados— y recortarla se comería fechas. */
.lamina-imagen { margin: 0; }
.lamina-img {
  display: block;
  /* **Tiene que caber de un vistazo.** A todo el ancho, una lámina vertical de 1024×1536
   * se iba a 1.300 px de alto y había que bajar para verla entera, que es justo lo
   * contrario de para lo que sirve un esquema. Se acota por ALTO, no por ancho: las
   * apaisadas siguen llenando la columna y las verticales entran en la pantalla.
   * Para verla grande está «Pantalla completa» —y la propia imagen, que abre igual—. */
  max-width: 100%;
  max-height: 68vh;
  width: auto; height: auto;
  margin: 0 auto;
  border-radius: 18px;
  background: #fff;
  cursor: zoom-in;
}
@media print {
  /* En papel no hay pantalla que medir: entera y a la caja. */
  .lamina-img { max-height: none; width: 100%; }
}
.lamina-imagen-caja .lamina-acciones { margin-top: 10px; }
.lamina-velo .lamina-img { border-radius: 12px; max-height: 86vh; width: auto; max-width: 100%; }

@media print {
  /* **La regla de impresión de la lámina dibujada no vale para una imagen.**
     Sin esto el PDF parte el esquema por la mitad entre dos páginas, que es
     justo lo que no puede pasar en la hoja que el alumno se lleva al examen. */
  .lamina-imagen { break-inside: avoid; page-break-inside: avoid; }
  .lamina-img { max-height: 92vh; object-fit: contain; }
  /* Los botones no se imprimen: en papel no se pulsa nada. */
  .lamina-imagen-caja .lamina-acciones { display: none; }
}

/* El contador mientras se dibuja la lámina.
   **Es una tarjeta, no una línea de texto.** Como apunte gris pasaba desapercibido y
   parecía que no estaba pasando nada: durante cuarenta segundos hay que ver que
   Rotermeller está trabajando. Va con su cara y su barra, en el lila de la marca. */
.lamina-espera {
  display: flex; align-items: center; gap: 14px;
  margin: 4px 0 14px;
  padding: 12px 16px;
  border-radius: 16px;
  background: var(--p-soft);
  border: 1px solid #C9BCFF;
}
.lamina-espera-cara {
  /* El retrato del Tutor, en disco, como en la conversación. Alto fijo para que la tarjeta
     no dé un salto cuando la imagen acaba de cargar. */
  flex: none; width: 46px; height: 46px; border-radius: 50%;
  object-fit: cover; background: #fff;
}
.lamina-espera-titulo {
  display: block; font-size: 15px; font-weight: 700; color: var(--t1); line-height: 1.25;
}
.lamina-espera-cuenta {
  display: block; margin-top: 2px; font-size: 13px; color: var(--secundario);
}
.lamina-espera-barra {
  display: block; margin-top: 9px; height: 6px; border-radius: 99px;
  background: #fff; overflow: hidden;
}
.lamina-espera-barra-va {
  display: block; height: 100%; width: 0; border-radius: 99px;
  background: linear-gradient(90deg, #8E77F0, #6246E5);
  /* La barra se mueve una vez por segundo: la transición hace que se deslice en vez de
     dar saltos, que es lo que la delataría como un contador y no como un progreso. */
  transition: width 1s linear;
}
@media (max-width: 560px) { .lamina-espera-cara { display: none; } }
@media (prefers-reduced-motion: reduce) { .lamina-espera-barra-va { transition: none; } }
@media print { .lamina-espera { display: none; } }

/* «Rehacer» no es un tipo más: se separa de las pastillas para que no parezca otra
   opción del mismo grupo, que es lo que haría dudar de cuál está elegida. */
.doc-rehacer { margin-left: auto; }
@media screen and (max-width: 700px) { .doc-rehacer { margin-left: 0; } }

/* ---- Que el esquema se vea COMPLETO ---------------------------------------
   El organigrama repartía el ancho que hubiera entre sus ramas: con cinco
   hojas en un hueco de ~750 px salían columnas de 128 px y el texto se partía
   palabra a palabra y se solapaba (visto el 6-sep con «Tres únicas reformas»).
   Repartir a partes iguales sólo funciona mientras quepan.

   Ahora cada rama tiene un mínimo legible y, si no caben, **el esquema se
   desplaza de lado dentro de su caja** en vez de aplastarse: es lo que ya hacía
   la línea de tiempo, y por la misma razón —un esquema ilegible no es un
   esquema—. La lámina en IMAGEN no tiene este problema: es una sola pieza a
   todo el ancho, y además está «Pantalla completa». */
.esq-ramas {
  grid-template-columns: repeat(var(--n, 4), minmax(160px, 1fr));
}
.esq.esq-org {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  padding-bottom: 4px;
}
/* Con `align-items: center` el contenido más ancho que la caja se sale por la
   izquierda y no se puede alcanzar desplazando. `safe center` lo evita. */
.esq.esq-org { align-items: safe center; }

@media print {
  /* En papel no hay desplazamiento: se encoge lo que haga falta para que entre
     entero, que es justo lo que el alumno se lleva al examen. */
  .esq.esq-org { overflow-x: visible; }
  .esq-ramas { grid-template-columns: repeat(var(--n, 4), minmax(0, 1fr)); }
}

/* ---- Galería de «Mis esquemas» --------------------------------------------
   Miniaturas en rejilla. **La lámina se encoge, no se recorta**: recortando se
   perdería justo la parte de abajo, que es donde caen las reformas y las
   conclusiones, y una miniatura que miente no sirve como índice. */
.esq-galeria {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 14px;
}
.esq-mini {
  display: flex; flex-direction: column; gap: 0;
  padding: 0; border: 1px solid var(--divisor); border-radius: 14px;
  background: var(--superficie); overflow: hidden; cursor: pointer;
  text-align: left; font: inherit; color: inherit;
  transition: border-color .15s, transform .15s;
}
.esq-mini:hover { border-color: var(--p); transform: translateY(-2px); }
.esq-mini:focus-visible { outline: 2px solid var(--p); outline-offset: 2px; }
.esq-mini-lienzo {
  position: relative; aspect-ratio: 16 / 11; overflow: hidden;
  background: #fff; border-bottom: 1px solid var(--divisor);
}
.esq-mini-img { width: 100%; height: 100%; object-fit: contain; display: block; }
/* El dibujo se pinta a tamaño real y se reduce: así la miniatura enseña la lámina
   entera, no su esquina de arriba a la izquierda. */
.esq-mini-dibujo {
  /* Se pinta a tamaño real y se encoge. **Anclada arriba a la izquierda, no centrada**:
     centrarla con `place-items` dejó las miniaturas EN BLANCO —un elemento de 900 px
     centrado en 220 se sale por los dos lados y el recorte se lo come—, y esto ya estaba
     probado. Encogerla es lo que permite enseñar la lámina entera; recortarla dejaría
     fuera la parte de abajo, que es donde caen las reformas y las conclusiones. */
  position: absolute; top: 0; left: 0;
  width: 900px;
  transform: scale(.245); transform-origin: top left;
  pointer-events: none;
}
.esq-mini-dibujo .lamina-acciones, .esq-mini-dibujo .lamina-espera { display: none; }
.esq-mini-pie { display: block; padding: 10px 12px; }
.esq-mini-titulo {
  display: block; font-size: 14px; font-weight: 600; color: var(--t1); line-height: 1.3;
  /* Dos líneas y elipsis: los títulos de un temario son largos y sin tope la rejilla
     se descuadra fila a fila. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.esq-mini-tipo { display: block; margin-top: 3px; font-size: 12px; color: var(--p); font-weight: 600; }
.doc-icono-esq { background: var(--p-soft); color: #6246E5; }

/* ---- Pedirle un cambio al esquema ----------------------------------------- */
.esq-retoque { margin-top: 12px; }
.esq-retoque-campo { width: 100%; resize: vertical; min-height: 62px; font: inherit; }
.esq-retoque-pie {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 8px;
}
@media print { .esq-retoque { display: none; } }

/* ---- El apartado como una página ------------------------------------------
   Se lee como un documento, no como una caja de una web: ancho de lectura,
   márgenes generosos y tipografía de texto largo. Un temario se lee durante
   horas y a todo el ancho de un monitor no se sigue el renglón. */
.doc-pagina {
  background: #fff;
  border: 1px solid var(--divisor);
  border-radius: 10px;
  /* **A todo el ancho de la tarjeta, no en una columna centrada.** Lo pidió Ruben. La
   * columna de 68ch venía de que una línea muy larga cuesta más de seguir —el ojo pierde el
   * renglón al volver—, pero dejaba media tarjeta en blanco a los lados y parecía un error
   * de maquetación más que una decisión. Manda él. */
  padding: 26px clamp(18px, 3vw, 34px);
  max-width: none;
  box-shadow: 0 1px 2px rgba(24,16,56,.04), 0 6px 18px rgba(24,16,56,.03);
}
.doc-editado { margin: 0 0 10px; }
.doc-editor {
  display: block; width: 100%; resize: vertical;
  /* 60vh dejaba una caja de pantalla y media. Lo justo para trabajar, y se estira a mano. */
  min-height: 340px;
  font-family: inherit; color: inherit;
  /* Misma métrica que en lectura: lo que se escribe tiene que verse como se leerá. */
  font-size: 16px; line-height: 1.7;
}
.doc-editor:focus { outline: 2px solid var(--p); outline-offset: 1px; }
.doc-editor-pie {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  max-width: 68ch; margin: 10px auto 0;
}
@media print {
  /* En papel la página ya es la página: fuera sombra, borde y tope de ancho. */
  .doc-pagina { box-shadow: none; border: 0; max-width: none; padding: 0; }
  .doc-rotuladores, .doc-editor-pie { display: none; }
}

/* ---- Elegir la clase de resumen o de esquema ------------------------------- */
.doc-selector { font-weight: 600; }
.doc-tipos { display: grid; gap: 8px; }
@media (min-width: 620px) { .doc-tipos { grid-template-columns: 1fr 1fr; } }
.doc-tipo {
  display: block; text-align: left; font: inherit; color: inherit; cursor: pointer;
  padding: 11px 13px; border-radius: 12px;
  border: 1px solid var(--divisor); background: var(--superficie);
  transition: border-color .15s, background .15s;
}
.doc-tipo:hover { border-color: var(--tono); }
.doc-tipo.activo {
  border-color: var(--tono);
  background: color-mix(in srgb, var(--tono) 11%, transparent);
}
.doc-tipo:focus-visible { outline: 2px solid var(--tono); outline-offset: 2px; }
.doc-tipo-alto { display: flex; align-items: center; gap: 8px; }
/* El icono en su disco del color de la forma: es lo que hace que la que ya usas se
   encuentre de un vistazo entre diez, sin leer los diez nombres. */
.doc-tipo-icono {
  display: grid; place-items: center; flex: none;
  width: 26px; height: 26px; border-radius: 8px;
  background: color-mix(in srgb, var(--tono) 15%, transparent);
  color: var(--tono);
}
.doc-tipo-nombre { font-weight: 700; font-size: 14.5px; color: var(--t1); }
.doc-tipo-para {
  display: block; margin-top: 3px; font-size: 12.5px; color: var(--secundario); line-height: 1.4;
}

/* ---- El semáforo del apartado ---------------------------------------------
   Cada estado con SU color, el mismo que ya usa el temario. Cuatro botones
   iguales no son un semáforo: el color es el dato. */
.doc-estados { display: flex; gap: 8px; flex-wrap: wrap; }
.doc-estado {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 14px; border-radius: 999px; cursor: pointer;
  font: inherit; font-size: 13.5px; font-weight: 600;
  color: var(--secundario);
  background: var(--superficie);
  border: 1px solid var(--divisor);
  transition: border-color .15s, background .15s, color .15s;
}
.doc-estado-punto {
  width: 9px; height: 9px; border-radius: 50%; flex: none;
  background: var(--tono);
  /* Sin puesto, el punto va apagado: así el color se lee como «esto es lo que serías si
     lo pulsas» y no como «esto es lo que eres». */
  opacity: .45;
  transition: opacity .15s, box-shadow .15s;
}
.doc-estado:hover { border-color: var(--tono); color: var(--t1); }
.doc-estado:hover .doc-estado-punto { opacity: .8; }
.doc-estado:focus-visible { outline: 2px solid var(--tono); outline-offset: 2px; }
.doc-estado.activo {
  border-color: var(--tono);
  /* 18 en hexadecimal ≈ 9 % de opacidad: el color se nota sin comerse el texto. */
  background: color-mix(in srgb, var(--tono) 14%, transparent);
  color: var(--t1);
}
.doc-estado.activo .doc-estado-punto {
  opacity: 1;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--tono) 25%, transparent);
}
@media print { .doc-estados { display: none; } }

/* ---- El editor del apartado, a pantalla completa ---------------------------
   Escribir es escribir: lo que estorba es todo lo demás. Mismo criterio que la
   lámina en grande. */
.doc-editor-velo { align-items: stretch; padding: 0; }
.doc-editor-hoja {
  display: flex; flex-direction: column;
  width: 100%; height: 100%;
  background: var(--fondo);
  padding: 16px clamp(14px, 4vw, 40px) 20px;
  gap: 12px;
}
.doc-editor-alto {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  max-width: 78ch; width: 100%; margin: 0 auto;
}
.doc-editor-titulo { display: block; font-size: 17px; font-weight: 700; color: var(--t1); }
.doc-editor-velo .doc-editor {
  /* Crece con la ventana en vez de tener un alto fijo: es lo único que hace que esto sea
     «a pantalla completa» y no una caja grande. */
  flex: 1; min-height: 0; width: 100%; max-width: 78ch; margin: 0 auto;
  background: #fff; border: 1px solid var(--divisor); border-radius: 12px;
  padding: 22px clamp(16px, 3vw, 34px);
  resize: none;
}
.doc-editor-pista { max-width: 78ch; width: 100%; margin: 0 auto; text-align: right; }
@media (max-width: 620px) { .doc-editor-alto .boton { flex: 1; } }

/* ---- Que el temario no sea un pegote --------------------------------------
   **Los párrafos no se separaban.** `.doc-texto > * + * { margin-top: 18px }`
   existía, pero `.lec-parrafo { margin: 0 }` va DESPUÉS en esta hoja y con la
   misma especificidad (0,1,0), así que ganaba y dejaba los párrafos pegados uno
   detrás de otro. Medido en el navegador el 6-sep: `margin-top: 0px`.

   Un apartado de temario así es un muro de texto: el ojo no encuentra dónde
   empieza cada idea y no hay por dónde agarrarse para estudiar. Se arregla con
   un selector más específico (0,2,0) en vez de un `!important`, que taparía el
   síntoma y dejaría la regla de arriba mintiendo. */
.doc-texto .lec-parrafo + .lec-parrafo,
.doc-lectura .lec-parrafo + .lec-parrafo { margin-top: 22px; }

/* Lo mismo con lo que va detrás de un párrafo o de una lista: sin esto, una
   lista pegada al párrafo anterior parece continuación de su última frase. */
.doc-texto .lec-parrafo + .lec-lista,
.doc-texto .lec-lista + .lec-parrafo,
.doc-lectura .lec-parrafo + .lec-lista,
.doc-lectura .lec-lista + .lec-parrafo { margin-top: 20px; }

/* Y una primera línea con sangría: es lo que hace que un párrafo se reconozca
   como párrafo en un texto largo, y es lo que hacen los libros de los que sale
   este temario. Sólo a partir del segundo — el primero no la lleva nunca. */
.doc-texto .lec-parrafo + .lec-parrafo { text-indent: 1.4em; }

/* ---- La lámina en grande, con zoom -----------------------------------------
   Ajustada a la pantalla, una lámina con mucho contenido se lee con lupa. Aquí
   se puede acercar y arrastrar, como un plano. */
.lamina-velo-zoom {
  align-items: stretch; padding: 0;
  flex-direction: column; display: flex;
}
.lamina-zoom-barra {
  display: flex; align-items: center; gap: 10px; flex: none;
  padding: 10px clamp(10px, 2vw, 20px);
  background: var(--superficie); border-bottom: 1px solid var(--divisor);
}
.lamina-zoom {
  flex: 1; min-height: 0; overflow: auto;
  display: grid; place-items: center;
  padding: 16px;
  overscroll-behavior: contain;
}
/* Acercada, la imagen deja de centrarse: si se quedara centrada, al desplazar
   se movería el hueco en vez del dibujo. */
.lamina-zoom.acercada { place-items: start center; cursor: grab; }
.lamina-zoom.moviendo { cursor: grabbing; }
.lamina-zoom-img {
  display: block; border-radius: 10px; background: #fff;
  cursor: zoom-in; max-width: none;
}
.lamina-zoom-img.ajustada {
  /* Ajustada: entera en pantalla. `contain` y no `cover`, que recortaría. */
  max-width: 100%; max-height: calc(100vh - 120px);
  width: auto; height: auto;
}
.lamina-zoom-barra .lamina-cerrar { position: static; }


/* El tope de 68ch de `.doc-texto` se suelta dentro de la página: si no, la página
   ocuparía la tarjeta entera pero el texto seguiría en su columna estrecha, que es
   justo lo que se venía a quitar. */
.doc-texto.doc-pagina { max-width: none; }
.doc-editor-pie { max-width: none; }

/* ---- El taller del esquema: lámina a la izquierda, chat a la derecha -------
   Retocar un esquema sin verlo es mandar un encargo a ciegas. Aquí se ve lo que
   hay mientras se pide el cambio, y la lámina se rehace delante. */
.taller-velo { align-items: stretch; padding: 0; }
.taller {
  display: flex; flex-direction: column;
  width: 100%; height: 100%; background: var(--fondo);
}
.taller-alto {
  display: flex; align-items: center; gap: 12px; flex: none;
  padding: 12px clamp(12px, 2vw, 22px);
  background: var(--superficie); border-bottom: 1px solid var(--divisor);
}
.taller-titulo { display: block; font-size: 16px; font-weight: 700; color: var(--t1); }
.taller-alto .lamina-cerrar { position: static; }

.taller-cuerpo { flex: 1; min-height: 0; display: flex; }
.taller-lienzo {
  /* **`min-height: 0` no es opcional.** Sin él, un hijo de un flex no puede encoger por
     debajo de su contenido: el alto del lienzo lo fijaba la imagen y `max-height: 100%`
     no tenía contra qué medirse, así que la lámina se salía por abajo. */
  flex: 1; min-width: 0; min-height: 0; overflow: auto;
  /* **Flex y no `grid` + `place-items`.** Con la rejilla, la pista es de alto automático y
     se dimensiona al contenido: el `max-height: 100%` de la imagen no tenía contra qué
     medirse y la lámina se salía por abajo. En flex, el alto del contenedor sí es definido
     (`flex: 1` + `min-height: 0`) y el porcentaje resuelve. */
  display: flex; align-items: center; justify-content: center;
  padding: 18px; background: var(--fondo);
}
.taller-img {
  max-width: 100%; max-height: 100%; width: auto; height: auto;
  border-radius: 12px; background: #fff; cursor: zoom-in;
  box-shadow: 0 2px 10px rgba(24,16,56,.06);
}
.taller-lienzo .lamina { max-width: 100%; }

.taller-chat {
  flex: none; width: min(400px, 42vw);
  display: flex; flex-direction: column; min-height: 0;
  border-left: 1px solid var(--divisor); background: var(--superficie);
}
.taller-hilo { flex: 1; min-height: 0; overflow-y: auto; padding: 16px; display: grid; gap: 10px; }
.taller-turno { display: flex; }
.taller-turno.de-el { justify-content: flex-end; }
.taller-burbuja {
  max-width: 86%; padding: 9px 13px; border-radius: 14px;
  font-size: 14px; line-height: 1.5; white-space: pre-wrap;
  background: var(--p-soft); color: var(--t1);
}
.taller-turno.de-el .taller-burbuja { background: var(--p); color: #fff; }
.taller-burbuja.pensando { opacity: .7; font-style: italic; }
.taller-pie { flex: none; padding: 12px 14px; border-top: 1px solid var(--divisor); }
/* El compositor: **una sola superficie**, no un cuadro de texto con dos botones
   sueltos debajo. Con el tirador de redimensionar a la vista y dos botones del
   tamaño de los de un formulario, aquello parecía un formulario y no un chat. */
.taller-compositor {
  border: 1px solid var(--divisor); border-radius: 16px;
  background: var(--fondo); padding: 8px 8px 8px 12px;
  transition: border-color .15s, box-shadow .15s;
}
.taller-compositor:focus-within {
  border-color: var(--p);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--p) 14%, transparent);
}
.taller-campo {
  display: block; width: 100%;
  border: 0; background: none; outline: none; resize: none;
  font: inherit; font-size: 14.5px; line-height: 1.5; color: var(--t1);
  padding: 4px 0; max-height: 160px;
}
.taller-compositor-pie { display: flex; align-items: center; gap: 8px; margin-top: 4px; }
.taller-clip, .taller-enviar {
  display: grid; place-items: center; cursor: pointer; padding: 0;
  border-radius: 50%; border: 0; flex: none;
}
.taller-clip {
  width: 30px; height: 30px; background: none; color: var(--secundario);
}
.taller-clip:hover { background: var(--p-soft); color: var(--p); }
.taller-enviar {
  width: 34px; height: 34px; background: var(--p); color: #fff;
  transition: transform .12s, filter .15s;
}
.taller-enviar:hover { filter: brightness(1.08); transform: scale(1.05); }
.taller-clip:focus-visible, .taller-enviar:focus-visible {
  outline: 2px solid var(--p); outline-offset: 2px;
}
.taller-adjunto {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Los atajos: lo que se pide casi siempre, a un toque. Rellenan el campo, no envían. */
.taller-atajos { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 9px; }
.taller-atajo {
  font: inherit; font-size: 12.5px; cursor: pointer;
  padding: 5px 10px; border-radius: 999px;
  border: 1px solid var(--divisor); background: var(--fondo); color: var(--secundario);
}
.taller-atajo:hover { border-color: var(--p); color: var(--p); }
.taller-atajo:focus-visible { outline: 2px solid var(--p); outline-offset: 2px; }

/* En estrecho, uno debajo del otro: dos columnas de 200 px no sirven para nada. */
@media (max-width: 860px) {
  .taller-cuerpo { flex-direction: column; }
  .taller-chat { width: 100%; border-left: 0; border-top: 1px solid var(--divisor); max-height: 52%; }
  .taller-lienzo { flex: 1; }
}

/* ---- Acciones sobre una lámina de la galería -------------------------------
   La tarjeta deja de ser un botón entero: la parte que abre el apartado es su
   propio botón y las acciones van encima, arriba a la derecha. */
.esq-mini { position: relative; padding: 0; }
.esq-mini-abrir {
  display: block; width: 100%; padding: 0; border: 0; background: none;
  font: inherit; color: inherit; text-align: left; cursor: pointer;
}
.esq-mini-abrir:focus-visible { outline: 2px solid var(--p); outline-offset: -2px; border-radius: 13px; }
.esq-mini-acciones {
  position: absolute; top: 8px; right: 8px;
  display: flex; gap: 6px;
  /* Aparecen al acercarse, pero **siempre visibles en táctil**: en un móvil no hay hover y
     un botón que sólo sale al pasar el ratón es un botón que no existe. */
  opacity: 0; transition: opacity .15s;
}
.esq-mini:hover .esq-mini-acciones,
.esq-mini:focus-within .esq-mini-acciones { opacity: 1; }
@media (hover: none) { .esq-mini-acciones { opacity: 1; } }
.esq-mini-accion {
  display: grid; place-items: center;
  width: 28px; height: 28px; border-radius: 8px; cursor: pointer;
  border: 1px solid var(--divisor); background: rgba(255,255,255,.94);
  color: var(--secundario); padding: 0;
  box-shadow: 0 1px 3px rgba(24,16,56,.08);
}
.esq-mini-accion:hover { color: var(--t1); border-color: var(--p); }
.esq-mini-accion.peligro:hover { color: #C4342B; border-color: #E7A9A3; }
.esq-mini-accion:focus-visible { outline: 2px solid var(--p); outline-offset: 2px; }


/* ---- El sello de la IA, más discreto --------------------------------------
   Era una pastilla con una frase larga encima de cada resumen y de cada
   esquema. En un apartado salen dos: a la tercera pantalla ya no se lee
   ninguna, y una advertencia que no se lee no advierte de nada. */
.sello-ia {
  display: flex; align-items: center; gap: 8px;
  margin: 0 0 12px; padding: 0; background: none; border: 0;
}
.sello-cara { width: 22px; height: 22px; border-radius: 50%; flex: none; object-fit: cover; }
.sello-texto {
  display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
  font-size: 12.5px; line-height: 1.4;
}
.sello-texto strong { font-weight: 600; color: var(--secundario); }
.sello-dato { color: var(--p); font-weight: 600; }
/* La advertencia, en gris y detrás de un punto: presente sin competir con el contenido. */
.sello-aviso { color: var(--secundario); opacity: .8; }
.sello-aviso::before { content: "· "; }

/* ---- La barra de acciones de la lámina ------------------------------------
   Las acciones sobre la lámina que ya está —descargar, verla en grande,
   dibujarla otra vez— van como iconos: no compiten con «Pedirle un cambio»,
   que es lo que de verdad se hace aquí. */
.lamina-imagen .lamina-acciones { justify-content: center; gap: 6px; }
.lamina-icono {
  display: grid; place-items: center; cursor: pointer; padding: 0;
  width: 34px; height: 34px; border-radius: 10px;
  border: 1px solid var(--divisor); background: var(--superficie); color: var(--secundario);
  transition: color .15s, border-color .15s, background .15s;
}
.lamina-icono:hover { color: var(--p); border-color: var(--p); background: var(--p-soft); }
.lamina-icono:focus-visible { outline: 2px solid var(--p); outline-offset: 2px; }
/* La fila de abajo: la acción principal, el selector y, al final, rehacer. */
.doc-acciones.con-taller { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }


/* ---- Pasar de apartado -----------------------------------------------------
   Con el título de a dónde vas. «Siguiente» a secas no dice nada; saber que lo
   próximo es «1.3. Los derechos fundamentales» es lo que te hace seguir. */
.doc-pasos {
  display: grid; grid-template-columns: 1fr 1fr; gap: 12px; align-items: stretch;
  /* **Aire por arriba.** Las tarjetas de paso quedaban pegadas a la del apartado y las dos
     franjas blancas se leían como una sola pieza partida por una raya. */
  margin-top: 18px;
}
.doc-paso-hueco { display: block; }
.doc-paso {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 14px 16px; border-radius: 14px; cursor: pointer;
  border: 1px solid var(--divisor); background: var(--superficie);
  font: inherit; color: inherit; text-align: left;
  transition: border-color .15s, transform .15s, box-shadow .15s;
}
.doc-paso.adelante { text-align: right; }
.doc-paso:hover {
  border-color: var(--p); transform: translateY(-2px);
  box-shadow: 0 4px 14px rgba(24,16,56,.06);
}
.doc-paso:focus-visible { outline: 2px solid var(--p); outline-offset: 2px; }
.doc-paso-rotulo {
  display: block; font-size: 11.5px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--p);
}
.doc-paso-titulo {
  display: block; margin-top: 2px; font-size: 14.5px; font-weight: 600; color: var(--t1);
  line-height: 1.35;
  /* Dos líneas: los títulos de un temario son largos y sin tope las dos tarjetas
     acaban con alturas distintas. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.doc-paso-flecha {
  display: grid; place-items: center; flex: none;
  width: 32px; height: 32px; border-radius: 50%;
  background: var(--p-soft); color: var(--p);
}
@media (max-width: 620px) { .doc-pasos { grid-template-columns: 1fr; } }
@media print { .doc-pasos { display: none; } }

/* ---- El selector de tema, con más presencia --------------------------------
   Es la primera decisión de Explícamelo y de Tests —de qué vas a hablar— y se
   veía como un campo de formulario cualquiera. Ahora se lee como lo que es: el
   tema elegido, con su icono en el acento de la casa. */
.selfuente {
  padding: 12px 14px;
  border-radius: 14px;
  border-color: color-mix(in srgb, var(--acento) 32%, var(--divisor));
  background: linear-gradient(180deg,
              color-mix(in srgb, var(--acento) 5%, var(--superficie)), var(--superficie));
  transition: border-color .15s, box-shadow .15s, transform .12s;
}
.selfuente:hover { transform: translateY(-1px); box-shadow: 0 3px 12px rgba(24,16,56,.06); }
/* El icono, en un disco del acento: es lo que hace que el tema se distinga de un
   desplegable de ajustes a un metro de la pantalla. */
.selfuente .cinta-icono.pequena {
  width: 34px; height: 34px; border-radius: 11px;
  background: var(--acento-suave); color: var(--acento);
}
.selfuente-titulo { font-size: 15.5px; font-weight: 700; }
.selfuente-detalle { color: var(--acento); font-weight: 600; opacity: .95; }
/* La flecha, en su propio disco: se lee como «esto se abre» y no como un adorno. */
.selfuente > svg:last-child {
  width: 26px; height: 26px; padding: 5px; border-radius: 50%;
  background: var(--acento-suave); color: var(--acento); box-sizing: border-box;
}

/* ---- Cuánto detalle lleva el esquema ---------------------------------------
   Es una decisión distinta de la forma, así que va en su propio bloque y no
   mezclada entre las diez formas. */
.doc-bloque { margin-bottom: 18px; }
.doc-bloque-rotulo {
  margin: 0 0 8px; font-size: 11.5px; font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase; color: var(--secundario);
}
.doc-detalles { display: grid; gap: 8px; grid-template-columns: repeat(3, 1fr); }
@media (max-width: 560px) { .doc-detalles { grid-template-columns: 1fr; } }
.doc-detalle {
  display: block; text-align: left; font: inherit; color: inherit; cursor: pointer;
  padding: 10px 12px; border-radius: 12px;
  border: 1px solid var(--divisor); background: var(--superficie);
  transition: border-color .15s, background .15s;
}
.doc-detalle:hover { border-color: var(--tono); }
.doc-detalle.activo {
  border-color: var(--tono);
  background: color-mix(in srgb, var(--tono) 12%, transparent);
}
.doc-detalle:focus-visible { outline: 2px solid var(--tono); outline-offset: 2px; }
.doc-detalle-alto { display: flex; align-items: center; gap: 7px; }
.doc-detalle-nombre { font-weight: 700; font-size: 14px; color: var(--t1); }
.doc-detalle-lineas { font-size: 11.5px; font-weight: 600; color: var(--tono); }
.doc-detalle-para {
  display: block; margin-top: 3px; font-size: 12px; color: var(--secundario); line-height: 1.35;
}
/* Las tres barritas: cuánto ocupa cada nivel, de un vistazo y sin leer el número. */
.doc-detalle-medida { display: inline-flex; align-items: flex-end; gap: 2px; height: 13px; }
.doc-detalle-medida span {
  width: 3px; border-radius: 2px; background: var(--divisor);
}
.doc-detalle-medida span:nth-child(1) { height: 5px; }
.doc-detalle-medida span:nth-child(2) { height: 9px; }
.doc-detalle-medida span:nth-child(3) { height: 13px; }
.doc-detalle-medida span.llena { background: var(--tono); }

/* ---- Los dos pasos de la espera --------------------------------------------
   Escribir el esquema y dibujar la lámina son dos trabajos seguidos. Verlos
   los dos es lo que dice por dónde va y cuánto queda. */
.espera-pasos { display: flex; gap: 14px; flex-wrap: wrap; margin: 5px 0 2px; }
.espera-paso {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; color: var(--secundario); opacity: .55;
}
.espera-punto {
  display: grid; place-items: center; flex: none;
  width: 14px; height: 14px; border-radius: 50%;
  border: 1.5px solid currentColor; box-sizing: border-box;
}
/* El que ya está: relleno y con su marca. */
.espera-paso.hecho { opacity: 1; color: var(--p); }
.espera-paso.hecho .espera-punto { background: var(--p); border-color: var(--p); color: #fff; }
/* El que se está haciendo: en negrita y con el punto latiendo, para que se distinga del
   que ya pasó sin necesidad de leer. */
.espera-paso.activo { opacity: 1; color: var(--t1); font-weight: 600; }
.espera-paso.activo .espera-punto {
  border-color: var(--p); color: var(--p);
  animation: espera-late 1.1s ease-in-out infinite;
}
@keyframes espera-late {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--p) 45%, transparent); }
  50%      { box-shadow: 0 0 0 4px color-mix(in srgb, var(--p) 0%, transparent); }
}
@media (prefers-reduced-motion: reduce) { .espera-paso.activo .espera-punto { animation: none; } }

/* ---- Color en las miniaturas de «Mis esquemas» -----------------------------
   El mismo color que la forma tiene en el selector: veinte miniaturas en gris
   obligan a leer los veinte rótulos para encontrar la que buscas. */
.esq-mini { border-top: 3px solid var(--tono); }
.esq-mini:hover { border-color: var(--divisor); border-top-color: var(--tono); }
.esq-mini-lienzo { background: color-mix(in srgb, var(--tono) 4%, #fff); }
.esq-mini-tipo {
  display: flex; align-items: center; gap: 5px;
  margin-top: 4px; font-size: 12px; font-weight: 600; color: var(--tono);
}
.esq-mini-icono {
  display: grid; place-items: center; flex: none;
  width: 19px; height: 19px; border-radius: 6px;
  background: color-mix(in srgb, var(--tono) 15%, transparent);
}
/* El nivel de detalle, en su propio color y sólo cuando no es el normal. */
.esq-mini-detalle {
  margin-left: auto; padding: 1px 7px; border-radius: 999px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .02em;
  color: var(--tono2); background: color-mix(in srgb, var(--tono2) 13%, transparent);
}

/* La marca del esquema en el índice: su forma, con su color. Un índice de cuarenta
   apartados con «Esquema» repetido cuarenta veces no dice nada; con la forma sí. */
.marca-esq {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px 3px 7px; border-radius: 999px;
  font-size: 11.5px; font-weight: 600; line-height: 1.3; white-space: nowrap;
  color: var(--tono);
  background: color-mix(in srgb, var(--tono) 12%, transparent);
}
.marca-esq svg { flex: none; }
/* En estrecho sólo el icono: el nombre de la forma no cabe y la fila se parte. */
@media (max-width: 620px) {
  .marca-esq span { display: none; }
  .marca-esq { padding: 4px; }
}

/* ---- El muro: lo que se ve cuando se acaba el plan -------------------------
   **No se pinta como un error, porque no lo es.** Con el mismo ámbar que un
   fallo de red, un límite del plan se lee como «se ha roto» y el alumno se va
   en vez de plantearse pagar. */
.muro {
  padding: 16px 18px; border-radius: 16px; margin: 4px 0 12px;
  background: var(--p-soft); border: 1px solid #C9BCFF;
}
.muro-alto { display: flex; align-items: flex-start; gap: 12px; }
.muro-icono {
  display: grid; place-items: center; flex: none;
  width: 34px; height: 34px; border-radius: 11px;
  background: #fff; color: var(--p);
}
.muro-titulo { display: block; font-size: 15px; color: var(--t1); }
.muro-cuenta { display: block; margin-top: 2px; }
.muro-acciones { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
@media print { .muro { display: none; } }

/* ---- Tu plan y lo que llevas usado ---------------------------------------- */
.uso-plan {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin: -2px 0 14px;
}
.uso-plan-nombre {
  font-size: 15px; font-weight: 700; color: var(--p);
  padding: 5px 12px; border-radius: 999px; background: var(--p-soft);
}
.uso-fila { margin-bottom: 14px; }
.uso-alto { display: flex; align-items: baseline; gap: 10px; margin-bottom: 6px; }
.uso-nombre { font-size: 14px; font-weight: 600; color: var(--t1); }
.uso-cuenta { margin-left: auto; font-size: 12.5px; color: var(--secundario); }
.uso-barra {
  display: block; height: 7px; border-radius: 99px;
  background: var(--divisor); overflow: hidden;
}
.uso-barra-va { display: block; height: 100%; border-radius: 99px; transition: width .3s ease; }

/* ---- Los planes -------------------------------------------------------------
   Tres columnas y el de en medio destacado. En estrecho, uno debajo de otro y
   **el destacado NO se sube arriba**: reordenar la lista al girar el móvil hace
   que quien la estaba leyendo pierda el sitio. */
/* Mensual o anual. Es un grupo de radio de verdad (no dos botones sueltos): con teclado
   se recorre con las flechas y el lector de pantalla dice cuál está elegido. */
.planes-periodo {
  /* `width: max-content` + `margin auto` lo centra sin tocar la hoja que lo contiene. */
  display: flex; width: max-content; gap: 4px; margin: 0 auto 18px; padding: 4px;
  border-radius: 999px; background: var(--divisor);
}
.planes-periodo-op {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 16px; border: 0; border-radius: 999px; cursor: pointer;
  font: inherit; font-size: 13.5px; font-weight: 600;
  color: var(--secundario); background: transparent;
}
.planes-periodo-op.activo { color: var(--t1); background: var(--superficie); box-shadow: 0 1px 3px rgba(0,0,0,.08); }
.planes-ahorro {
  padding: 2px 8px; border-radius: 999px; font-size: 11px; font-weight: 700;
  color: #fff; background: var(--p);
}
/* Lo que se ahorra al año, bajo el precio. En lila y no en verde: el verde ya significa
   «esto entra en tu plan» en la lista de debajo, y dos verdes distintos confunden. */
.plan-ahorro {
  display: inline-block; margin-top: 4px; font-size: 12px; font-weight: 700; color: var(--p);
}

.planes { display: grid; gap: 16px; grid-template-columns: repeat(3, 1fr); align-items: stretch; }
@media (max-width: 780px) { .planes { grid-template-columns: 1fr; } }

.plan {
  position: relative; display: flex; flex-direction: column;
  padding: 22px 20px; border-radius: 18px;
  border: 1px solid var(--divisor); background: var(--superficie);
}
.plan.destacado { border-color: var(--p); box-shadow: 0 8px 28px rgba(118, 87, 246, .14); }
.plan.tuyo { border-color: var(--p); background: var(--p-soft); }
.plan-cinta {
  position: absolute; top: -10px; left: 20px;
  padding: 3px 11px; border-radius: 999px;
  font-size: 11.5px; font-weight: 700; letter-spacing: .02em;
  color: #fff; background: var(--p);
}
.plan-cinta-tuyo { background: var(--t1); }

.plan-nombre { display: block; font-size: 17px; color: var(--t1); }
.plan-precio { display: flex; align-items: baseline; gap: 8px; margin: 6px 0 2px; flex-wrap: wrap; }
.plan-cifra { font-size: 32px; font-weight: 800; color: var(--t1); line-height: 1; }
.plan-periodo { font-size: 12.5px; color: var(--secundario); }
.plan-lema { margin: 8px 0 0; font-size: 13.5px; color: var(--secundario); line-height: 1.45; }

.plan-lista { list-style: none; margin: 16px 0 0; padding: 0; display: grid; gap: 9px; }
.plan-lista li { display: flex; align-items: flex-start; gap: 9px; font-size: 13.5px; line-height: 1.45; }
.plan-marca {
  display: grid; place-items: center; flex: none;
  width: 18px; height: 18px; border-radius: 50%; margin-top: 1px;
}
.plan-si .plan-marca { background: color-mix(in srgb, #2FA36B 15%, transparent); color: #2FA36B; }
.plan-si { color: var(--t1); }
/* Lo que NO entra se enseña, no se esconde: enterarse al chocar es peor que saberlo antes. */
.plan-no .plan-marca { background: var(--divisor); color: var(--secundario); }
.plan-no { color: var(--secundario); }

.plan-nota {
  margin: 14px 0 0; padding: 9px 11px; border-radius: 10px;
  font-size: 12.5px; line-height: 1.45;
  background: var(--p-soft); color: var(--t1);
}
/* El pie abajo del todo, para que los tres botones queden a la misma altura aunque las
   listas tengan distinto largo. */
.plan-pie { margin-top: auto; padding-top: 18px; }
.plan-pie .boton { width: 100%; justify-content: center; }
.planes-pie { margin: 18px 0 0; text-align: center; }

/* ================================================================= MODO APP
 *
 * Lo que hace que en el teléfono esto **no se parezca** a la app de iPhone sino que sea
 * la misma pantalla. La clase la pone `tema.aplicar()` (ver `tema.esModoApp`) en el
 * `<html>`, y cuelga de ahí en vez de de un `@media` porque la condición no es sólo el
 * ancho: una ventana estrecha del ordenador sigue siendo la web.
 *
 * Los valores están sacados de `Compartido/Tema.swift` y medidos sobre las capturas del
 * simulador (`iPhone 17e`, 390 pt), no elegidos a ojo. */

html.modo-app {
  /* El divisor de la app es gris cálido, no el lila de las maquetas (`Rotermeller.divisor`). */
  --divisor: #ECEBE8;
  /* Y las sombras son negras y suavísimas (`Rotermeller.Sombra`): sobre el crema, una
   * sombra teñida de morado se ve sucia. */
  --sombra-tarjeta: 0 1px 2px rgba(0,0,0,.04), 0 8px 24px rgba(0,0,0,.06);
  --sombra-flotante: 0 8px 20px rgba(0,0,0,.12);
}

/* ---------------------------------------------- la barra de pestañas en cápsula
 *
 * En la app no es una franja pegada al borde con una línea encima: es una **cápsula
 * blanca que flota** sobre el contenido, con el activo en coral. `BarraPestanasRotermeller`
 * en `Vistas/RootView.swift`: relleno 6/8, cápsula, sombra flotante y 16 px de aire a los
 * lados. */
html.modo-app .barra-inferior {
  left: 16px; right: 16px;
  bottom: calc(8px + env(safe-area-inset-bottom));
  background: var(--superficie);
  backdrop-filter: none;
  border-top: 0;
  border-radius: var(--capsula);
  box-shadow: var(--sombra-flotante);
  padding: 8px 6px;
  padding-bottom: 8px;      /* el hueco del iPhone ya lo pone `bottom`, no se suma dos veces */
}
html.modo-app .barra-inferior a {
  height: auto;
  gap: 3px;
  border-radius: var(--capsula);
  padding: 2px 0;
}
/* **Los iconos de la barra son planos, no los 3D de las maquetas.** En la app son SF
 * Symbols que se tiñen de coral al estar activos, y ahí está media identidad de la barra:
 * un PNG a todo color no puede teñirse, así que en modo app se apaga y sale el trazo. */
html.modo-app .barra-inferior .icono3d { display: none; }
html.modo-app .barra-inferior svg { width: 24px; height: 24px; }
html.modo-app .barra-inferior a.activo { color: var(--acento); font-weight: 700; }

/* La cápsula flota **encima** del contenido, así que la última tarjeta de cualquier lista
 * tiene que poder subir por encima de ella o queda tapada. 64 de barra + 8 de aire + el
 * hueco del iPhone. */
html.modo-app .contenido { padding-bottom: calc(84px + env(safe-area-inset-bottom)); }

/* ---------------------------------------- instalada = teléfono, también en tablet
 *
 * Decisión de Ruben (9-sep). Hasta ahora una tablet de 900+ px caía en el reparto de
 * escritorio —barra lateral, dos columnas— aunque estuviese instalada desde Google Play:
 * se veía la piel de la app con la maquetación de la web, que es la peor mezcla de las
 * dos. En modo app manda el teléfono a cualquier ancho.
 *
 * Va por clase y no por `@media` porque la condición **no es el ancho**: una ventana
 * estrecha del ordenador sigue siendo la web. Y gana a los `@media (min-width: 900px)`
 * de arriba por especificidad (0-2-1 contra 0-1-0), no por estar al final — que es lo
 * que hay que conservar si algún día se mueve este bloque. */
html.modo-app .app { grid-template-columns: 1fr; background: var(--fondo); }
html.modo-app .lateral,
html.modo-app .superior { display: none; }
html.modo-app .barra-inferior { display: flex; }
html.modo-app .contenido {
  padding-inline: var(--e-md);
  max-width: none;
  margin-inline: 0;
}
/* Una sola columna: en la app no hay columna de apoyo, todo va en el hilo principal. */
html.modo-app .columnas,
html.modo-app .columnas.par { grid-template-columns: minmax(0, 1fr); }

/* ================================================== HOY, LA DEL TELÉFONO (`hoy-movil.js`)
 *
 * El porte de `Vistas/HoyView.swift`. **Las medidas son las de la app en puntos**, leídas
 * del Swift y comprobadas contra la captura del simulador (iPhone 17e, 390 pt), no
 * elegidas a ojo: 26 de radio de tarjeta, 18 de relleno, 190 de ancho del héroe, 62 de
 * cara, 54 de columna de la hora, 38 de botón redondo.
 *
 * Todo cuelga de `.mhoy*` y sólo lo pinta esa vista, que sólo existe en modo app: aquí no
 * se toca ni una clase compartida, así que la web de escritorio no se entera. */

.mhoy { display: flex; flex-direction: column; gap: var(--e-lg); }
.mhoy .crece { flex: 1; min-width: 0; }
.mhoy .mdim { color: var(--secundario); }
.mhoy .mpequeno { font-size: 13px; }
.mhoy .mnegrita { font-size: 15px; font-weight: 600; color: var(--tinta); }
.mhoy .mrotulo { font-size: 11px; font-weight: 700; color: var(--secundario); }
.mhoy .mchevron { color: var(--acento); display: flex; flex: none; }

.mtarjeta {
  background: var(--superficie);
  border-radius: var(--r-grande);
  box-shadow: var(--sombra-tarjeta);
  /* La cinta de color llega a los bordes redondeados: sin esto asoman cuatro esquinas
   * blancas por encima del coral. */
  overflow: hidden;
}

/* ------------------------------------------------------- cabecera: saludo y héroe */

.mhoy-cabeza { position: relative; padding-top: 6px; min-height: 156px; }
/* Sangrada por la derecha: el brazo viene cortado en el arte de origen, así que el borde
 * del PNG tiene que coincidir con el borde físico de la pantalla para que el corte
 * parezca sangrado y no un recorte mal hecho. Compensa entero el relleno del contenido. */
.mhoy-hero { position: absolute; right: calc(var(--e-md) * -1); top: 0; width: 190px; height: auto; }
/* Los 116 px que le cede al héroe son los mismos de la app: con menos, «Tienes un día
 * productivo» se sale por los dos lados. */
.mhoy-saludo { position: relative; z-index: 1; padding-right: 116px; }
.mhoy-saludo h1 { margin: 0; font-size: 34px; font-weight: 800; line-height: 1.12; letter-spacing: -.4px; }
.mhoy-hola { color: var(--acento); }
.mhoy-lema {
  position: relative;
  width: max-content; max-width: 100%;
  margin: 8px 0 0;
  display: flex; flex-direction: column; gap: 3px;
  font-size: 15px; font-weight: 500; line-height: 1.25; color: var(--secundario);
}
/* El subrayado coral del diseño: una cápsula de 74x2,5 bajo «por delante». */
.mhoy-lema::after {
  content: ""; position: absolute; left: 0; bottom: -3px;
  width: 74px; height: 2.5px; border-radius: var(--capsula);
  background: color-mix(in srgb, var(--acento) 50%, transparent);
}
.mhoy-campana {
  position: absolute; right: 0; top: 2px;
  width: 40px; height: 40px; border: 0; border-radius: 50%;
  background: var(--superficie); color: var(--tinta);
  box-shadow: var(--sombra-tarjeta);
  display: grid; place-items: center;
}

/* ------------------------------------------------- la cinta de color de una tarjeta */

.mcinta {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 18px;
  background: var(--acento); color: #FFF;
}
.mcinta-rotulo { font-size: 12px; font-weight: 800; letter-spacing: .6px; }
/* `fixedSize` de la app: sin tope, «Lunes» salía partido en «Lu-nes». */
.mcinta-fin { margin-left: auto; font-size: 13px; font-weight: 600; white-space: nowrap; }

/* -------------------------------------------------------------- próxima clase */

.mclase-cuerpo { display: flex; align-items: flex-start; gap: 14px; padding: 18px; }
.mclase-nombre { margin: 0; font-size: 22px; font-weight: 700; line-height: 1.2; color: var(--tinta); }
.mclase-datos {
  display: flex; flex-wrap: wrap; gap: 6px 16px;
  margin-top: 12px;
  font-size: 13px; font-weight: 500; color: var(--secundario);
}
.mdato { display: inline-flex; align-items: center; gap: 5px; }
.mclase-cuenta {
  display: flex; align-items: baseline; gap: 7px;
  margin-top: 14px; font-size: 13px; color: var(--secundario);
}
.mcuenta { font-size: 22px; font-weight: 800; color: var(--acento); font-variant-numeric: tabular-nums; }
.mclase-cuenta-curso { flex-direction: column; align-items: stretch; gap: 6px; }
.mclase-cuenta-curso .mcuenta { font-size: 15px; }
.mbarra { height: 6px; border-radius: var(--capsula); background: var(--acento-suave); overflow: hidden; }
.mbarra-va { display: block; height: 100%; width: 0; border-radius: var(--capsula); background: var(--acento); transition: width .4s linear; }
.mclase-cara { flex: none; }
.msinclase { display: flex; align-items: center; gap: 12px; padding: 18px; }

/* ----------------------------------------------------------------- tu plan de hoy */

.mplan { position: relative; }
.mplan .mcinta { padding: 9px 14px 9px 18px; }
.mplan-cara { margin-left: auto; flex: none; }
/* **Un filo de luz dando vueltas al borde.** Es el único efecto que sobrevivió en la app:
 * el destello que cruzaba la franja y la malla de color quedaban de plástico. El truco de
 * las dos máscaras es lo que permite pintar sólo el borde con un degradado cónico, que no
 * se puede hacer con `border-image` sin perder las esquinas redondeadas. */
@property --mplan-giro { syntax: "<angle>"; initial-value: 0deg; inherits: false; }
.mplan::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 2px;
  background: conic-gradient(from var(--mplan-giro),
    color-mix(in srgb, var(--acento) 5%, transparent),
    color-mix(in srgb, var(--acento) 65%, transparent),
    rgba(255,255,255,.95),
    color-mix(in srgb, var(--acento) 65%, transparent),
    color-mix(in srgb, var(--acento) 5%, transparent));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite: exclude;
  animation: mplan-girar 4s linear infinite;
  pointer-events: none;
}
@keyframes mplan-girar { to { --mplan-giro: 360deg; } }
@media (prefers-reduced-motion: reduce) { .mplan::after { animation: none; } }
.mplan { box-shadow: 0 10px 22px color-mix(in srgb, var(--acento) 28%, transparent), var(--sombra-tarjeta); }

.mplan-fila { display: flex; align-items: flex-start; gap: 14px; padding: 14px 18px; }
.mplan-hora { width: 54px; flex: none; display: flex; flex-direction: column; align-items: center; gap: 2px; }
.mplan-hora b { font-size: 15px; font-weight: 800; color: var(--tinta); font-variant-numeric: tabular-nums; }
.mplan-hora span { font-size: 11px; font-weight: 600; color: var(--secundario); }
.mplan-marcas { display: flex; align-items: center; flex-wrap: wrap; gap: 7px; margin-bottom: 5px; }
.mplan-examen { font-size: 11px; font-weight: 800; color: var(--acento); }
.mplan-pie { margin: 0; padding: 0 18px 14px; font-size: 11px; color: var(--secundario); }
.mraya { border: 0; border-top: 1px solid var(--divisor); margin: 0; }
/* La raya del plan empieza donde empieza el texto (54 de hora + 14 de hueco + 18 de
 * relleno), no de borde a borde: si no, parte también la columna de la hora. */
.mraya-plan { margin-left: 76px; }
.mplay {
  flex: none; width: 38px; height: 38px; border: 0; border-radius: 50%;
  background: var(--acento); color: #FFF;
  display: grid; place-items: center;
  transition: transform .12s ease;
}
.mplay:active { transform: scale(.92); }

/* ------------------------------------------------------------ tareas pendientes */

.mtareas { display: flex; flex-direction: column; gap: 12px; }
.mtareas-cabeza { display: flex; align-items: center; gap: 6px; }
.mtareas-cabeza h2 { margin: 0; font-size: 19px; font-weight: 700; color: var(--tinta); }
.mcuenta-pastilla {
  font-size: 12px; font-weight: 700; color: #FFF;
  background: var(--acento); border-radius: var(--capsula); padding: 3px 8px;
}
.mvertodas {
  border: 0; background: none; padding: 0;
  display: inline-flex; align-items: center; gap: 2px;
  font-size: 15px; font-weight: 600; color: var(--secundario);
}
.mtareas-lista { display: flex; flex-direction: column; gap: 10px; }
.mtareas-vacio { display: flex; align-items: center; gap: 10px; padding: 16px; color: var(--secundario); font-size: 15px; }
.mtareas-vacio svg { color: var(--acento); flex: none; }

.mtarea {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 14px; border-radius: var(--r-medio);
  transition: opacity .2s ease;
}
.mtarea.hecha { opacity: .55; }
/* La casilla se tiñe del color de la asignatura, no del acento: es lo que hace que en una
 * lista de cuatro tareas se vea de un vistazo de qué es cada una (`BotonHecha`). */
.mtarea .casilla { border-color: color-mix(in srgb, var(--casilla) 45%, transparent); background: transparent; }
.mtarea .casilla.hecha { background: var(--casilla); border-color: var(--casilla); color: #FFF; }
.mtarea-cuerpo {
  flex: 1; min-width: 0; border: 0; background: none; padding: 0;
  text-align: left; display: flex; flex-direction: column; gap: 6px;
}
.mtarea-titulo { font-size: 15px; font-weight: 600; color: var(--tinta); }
.mtarea-titulo.tachado { text-decoration: line-through; color: var(--secundario); }
.mtarea-bajo { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.mtarea-marca {
  font-size: 11px; font-weight: 700; color: #FFF;
  border-radius: var(--capsula); padding: 3px 7px;
}
.mtarea-barrita { width: 3px; height: 12px; border-radius: var(--capsula); display: inline-block; }

/* -------------------------------------------- la barra de preguntarle a Rotermeller */

.mpregunta {
  display: flex; align-items: center; gap: 12px;
  width: 100%; padding: 8px; border: 0;
  border-radius: var(--capsula);
  background: var(--superficie);
  box-shadow: var(--sombra-flotante);
  color: var(--secundario); font-size: 15px; text-align: left;
}
.mpregunta-cara { border-radius: 50%; object-fit: cover; flex: none; }
.mpregunta-micro {
  flex: none; width: 38px; height: 38px; border-radius: 50%;
  background: var(--acento); color: #FFF;
  display: grid; place-items: center;
}

/* ------------------------------------- la primera tarjeta del que no va a clase */

.mopo { padding: 18px; display: flex; flex-direction: column; gap: 14px; }
.mopo-cuenta { display: flex; align-items: flex-start; gap: 12px; }
.mopo-nombre { font-size: 15px; font-weight: 600; }
.mopo-dias { display: flex; align-items: baseline; gap: 7px; }
.mopo-dias b { font-size: 38px; font-weight: 800; line-height: 1; }
.mopo-dias span { font-size: 15px; font-weight: 500; color: var(--secundario); }
.mopo-pedir, .mopo-tema, .mopo-hecho { display: flex; align-items: center; gap: 10px; }
.mopo-pedir { border: 0; background: none; padding: 0; text-align: left; width: 100%; }
.mopo-tema .boton.mini { padding: 9px 14px; font-size: 13px; border-radius: var(--capsula); }
.mopo-hecho { font-size: 13px; font-weight: 500; color: var(--tinta); }
.mopo-hecho svg { color: var(--ok); flex: none; }

/* --------------------------------------------------- lo que arrastras (instituto y FP) */

.marrastra { padding: 18px; display: flex; flex-direction: column; gap: 12px; }
.marrastra-cabeza { display: flex; align-items: center; gap: 8px; }
.marrastra-cabeza h2 { margin: 0; font-size: 16px; font-weight: 700; color: var(--tinta); }
.marrastra-cabeza svg { color: var(--aviso); flex: none; }
.marrastra p { margin: 0; }
.marrastra-fila {
  display: flex; align-items: center; gap: 10px;
  border: 0; text-align: left; width: 100%;
  padding: 12px; border-radius: var(--r-medio);
  background: color-mix(in srgb, var(--aviso) 10%, #FFFFFF);
}

.mvacio { padding: 24px; text-align: center; }
.mvacio h2 { margin: 12px 0 6px; font-size: 18px; color: var(--tinta); }
.mvacio p { margin: 0 0 var(--e-md); color: var(--secundario); }

/* ------------------------------------------------- la puerta, en modo app
 *
 * **Es la primera pantalla del TWA y era la que delataba que esto es una web**: el marco
 * de 1080 px con la lámina publicitaria morada al lado, que es la portada de la web. Una
 * app no se abre con un cartel de producto: se abre con su marca y el campo.
 *
 * No hay diseño nuevo — se reusa el reparto que ya tenía el móvil (`@media (max-width:
 * 900px)`), forzado a cualquier ancho, porque en la tablet instalada el ancho no decide
 * nada: decide el sello. */
html.modo-app .entrar { padding: 0; place-items: stretch; }
html.modo-app .entrar-marco {
  grid-template-columns: 1fr; width: 100%; min-height: 100dvh;
  border-radius: 0; box-shadow: none;
}
html.modo-app .entrar-arte { display: none; }
html.modo-app .entrar-panel { padding: 32px 20px; }

/* **En la tablet, ancho — como el iPad.** Decisión de Ruben (9-sep), que corrige la de
 * esta misma mañana: no una app de teléfono centrada en medio de la pantalla, sino la app
 * usando el ancho, que es lo que hace la de iOS en un iPad (no tiene reparto propio para
 * iPad: son las mismas pantallas estiradas).
 *
 * La Lenovo mide **1333 × 800 dp** en apaisado, o sea un iPad de largo. El tope de 1100 es
 * para que en un monitor la app no se convierta en una tira de texto de dos metros; en la
 * tablet no recorta nada.
 *
 * Y la Hoy reparte en dos columnas a partir de 1000: en un lienzo de 1333 px, la tarjeta
 * de la clase y el plan uno debajo del otro dejan media pantalla vacía y obligan a
 * desplazar para ver lo que cabía de sobra. Es el mismo criterio que ya usa el escritorio,
 * aplicado al ancho de verdad y no al aparato. */
html.modo-app .contenido { max-width: 1100px; margin-inline: auto; }
html.modo-app .barra-inferior { max-width: 1100px; margin-inline: auto; }

@media (min-width: 1000px) {
  html.modo-app .mhoy {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: start;
    column-gap: var(--e-lg);
  }
  /* La cabecera manda a lo ancho: el saludo y Rotermeller ocupan las dos columnas, como
   * la cabecera de cualquier app en iPad. */
  html.modo-app .mhoy-cabeza { grid-column: 1 / -1; }
  /* Y la barra de preguntarle también: es la acción de toda la pantalla, no de una mitad. */
  html.modo-app .mpregunta { grid-column: 1 / -1; }
  html.modo-app .mhoy-hero { width: 240px; }
  html.modo-app .mhoy-cabeza { min-height: 190px; }
}

/* La puerta en modo app, copiada de `Vistas/Auth/PhoneLoginView.swift`: Rotermeller al
 * teléfono a 200 px, el titular en dos líneas con la segunda en coral y subrayada a mano,
 * y el lema debajo. Relleno horizontal 22, como allí. */
html.modo-app .entrar-panel { padding: 8px 22px 32px; }
html.modo-app .entrar-marca-app { text-align: center; margin-bottom: 20px; }
html.modo-app .entrar-hero-app { display: block; margin: 0 auto; height: 200px; width: auto; }
html.modo-app .entrar-titular-app {
  display: flex; flex-direction: column; align-items: center; gap: 0;
  margin: 0; font-size: 34px; font-weight: 800; line-height: 1.1; letter-spacing: -.4px;
  color: var(--tinta);
}
html.modo-app .entrar-subrayado { position: relative; color: var(--acento); }
html.modo-app .entrar-subrayado::after {
  content: ""; position: absolute; left: 4%; right: 4%; bottom: -5px; height: 3px;
  border-radius: var(--capsula); background: var(--acento);
}
html.modo-app .entrar-lema { display: flex; flex-direction: column; margin-top: 14px; }
html.modo-app .entrar-rotulo-app {
  display: block; margin-bottom: 8px; font-size: 16px; font-weight: 700; color: var(--tinta);
}
html.modo-app .entrar-caja { width: min(420px, 100%); }
