/* PIA — las pantallas de Element a ancho de TELÉFONO.
 *
 * POR QUÉ UN ARCHIVO APARTE Y NO pia-theme.css NI pia-simplificar.css
 * Los tres tocan Element y hacen cosas distintas, y la cabecera de
 * pia-simplificar.css ya dejó dicho el criterio: pia-theme.css es EL ARCHIVO
 * DEL ACENTO (pinta), pia-simplificar.css ESCONDE. Esto ni pinta ni esconde:
 * ADAPTA la caja. Quien venga a cambiar el azul no debería tener que leer
 * reglas de layout, y quitar este <link> del index.html tiene que devolver el
 * comportamiento de escritorio intacto — cosa que sólo es verdad si está solo.
 *
 * POR QUÉ GANA SIN !important
 * Element mete su CSS dentro de `@layer app-web` (comprobado sobre el CSS
 * SERVIDO, no supuesto: `@layer compound-tokens, compound-web,
 * shared-components, app-web` es la primera línea de theme-legacy-light.css).
 * El CSS sin capa gana a cualquier CSS en capa pase lo que pase con la
 * especificidad. Este archivo está fuera de toda capa a propósito, igual que
 * sus dos hermanos.
 *
 * =============================================================================
 * EL DEFECTO QUE ESTE ARCHIVO VINO A ARREGLAR — nodo 81c66f4e, 18-ago-2026
 * =============================================================================
 *
 * La pantalla de bienvenida del tenant se cortaba a lo ancho en cualquier
 * teléfono: "Iniciar sesión" se salía por el borde derecho. Lo encontró
 * 604e4b53 en el simulador de iPhone, y se reproducía IGUAL en la WKWebView de
 * la app y en un Safari virgen — o sea que era la página, no la concha.
 *
 * LA CAUSA ES UNA SOLA DECLARACIÓN, y es de Element, no de PIA:
 *
 *     .mx_DefaultWelcome .mx_DefaultWelcome_buttons a { width: 380px }
 *
 * Un 380 a fuego en los botones. Nadie lo acota, y la tarjeta entera se
 * construye HACIA AFUERA desde ese número:
 *
 *       380  el botón, a fuego
 *     +  96  el aire de .mx_Welcome (--cpd-space-12x por lado)
 *     = 476  .mx_Welcome
 *     +  24  el aire del envoltorio de cristal (content-box)
 *     = 500  .mx_AuthPage_modal
 *
 * Los 500px NO son un ancho de tarjeta declarado en ninguna parte: son el 380
 * escapándose hacia afuera. Medido: `.mx_DefaultWelcome_buttons` tiene
 * min-content == max-content == 380 mientras sus botones sólo piden 87px. La
 * tarjeta NO PUEDE encoger. Por eso el iPad se veía bien —le sobra ancho— y
 * todos los teléfonos mal: se salía 180px a 320, 110px a 390 y 70px a 430.
 *
 * ⚠️ POR QUÉ scrollWidth NO VE ESTE FALLO, que es la trampa que costó una
 * medición entera. `.mx_AuthPage` computa `overflow: auto`: es un contenedor de
 * scroll, así que los 500px NUNCA llegan al documento — se absorben como scroll
 * interno. `document.documentElement.scrollWidth` da 390 a 390 y 320 a 320 CON
 * EL FALLO DELANTE y la página pintada del todo. Es una métrica
 * ESTRUCTURALMENTE CIEGA a este bug, no un número que salió mal por accidente.
 * La señal buena es por elemento: `getBoundingClientRect().right > innerWidth`,
 * que es lo que recorre scripts/sonda-bienvenida-movil.mjs.
 * (El primer intento además midió una página en blanco, y su
 * `scrollWidth == innerWidth` era el verde de que no había cargado nada. Son
 * DOS fallos distintos apilados: arreglar el render no habría salvado la cifra.)
 *
 * =============================================================================
 * EL CRITERIO — LEEME-DISENO.md §10, que ya estaba decidido
 * =============================================================================
 *
 * No se inventa nada aquí. §10 lo decidió el 17-ago midiendo el portal:
 *   M1 · UN SOLO punto de corte, 480px. No hay un segundo.
 *   M2 · lo que se adapta es el AIRE, NUNCA la letra — y por TOKEN
 *        (--pia-margen-lienzo, --pia-aire-tarjeta), que ya traen su @media
 *        dentro. Por eso aquí no se vuelve a escribir ni un 16 ni un 20: esa
 *        regla ya derivó una vez por reescribir el número en cada pantalla.
 *   M5 · suelo de toque de 44px.  ← OJO: esta pantalla NO lo cumple, y este
 *        archivo NO lo arregla. Ver la nota del final.
 */

/* --- 1 · La tarjeta no puede ser más ancha que la pantalla -----------------
 *
 * En escritorio y en tablet queda EXACTAMENTE como hoy: `min()` elige los
 * 500px mientras quepan, así que a 1280 o en un iPad la tarjeta sigue midiendo
 * 500px al píxel. Sólo por debajo de ~564px empieza a mandar el otro lado.
 *
 * Se acota con el token del margen del lienzo y no con `100%` a secas para que
 * la tarjeta no llegue a tocar los bordes del teléfono: a ≤480px el token vale
 * 16px por lado él solo (M2), sin que este archivo tenga que saberlo.
 *
 * EL `:has(.mx_Welcome)` NO ES DECORATIVO — acota la regla a la pantalla de
 * BIENVENIDA. `.mx_AuthPage_modal` es también la tarjeta del ACCESO y la del
 * registro, y ésas hoy NO se salen: su ancho lo decide su contenido. Fijarles
 * un `width` las volvería de 500px en escritorio, que es más de lo que miden
 * ahora — un arreglo que rompe dos pantallas sanas para curar una enferma.
 * (`:has()` ya se usa en pia-simplificar.css: `body:has(.mx_AuthPage)`.)
 */
.mx_AuthPage_modal:has(.mx_Welcome) {
  width: min(500px, 100% - var(--pia-margen-lienzo) * 2);
}

/* --- 1bis · Y que el contenido OCUPE la tarjeta, en vez de encogerse ------
 *
 * ESTA REGLA NO ES UN REMATE: sin ella la de arriba ROMPE EL ESCRITORIO, y así
 * salió medido antes de subirla a la imagen. `.mx_AuthPage_modal` es un flex
 * en fila y `.mx_AuthPage_modalContent` es su ítem. Mientras el botón imponía
 * 380px, el ítem medía 500 porque su contenido lo obligaba. En cuanto el botón
 * deja de imponerlo (regla 2), el ítem se encoge a su propio texto —el máximo
 * pasa a ser el del <h1>, 316px— y la tarjeta se queda con la caja de 500px y
 * el contenido flotando dentro a 436. Medido a 1280px: botón 380 → 316.
 *
 * `flex: 1` (base 0 + crecer) hace que el ítem ocupe los 500px de la tarjeta.
 *
 * SON DOS NIVELES, NO UNO, y el segundo se descubrió midiendo: poner esto sólo
 * en `.mx_AuthPage_modalContent` dejaba el botón en 316px igual, porque el
 * modalContent es TAMBIÉN un flex en fila y su envoltorio de cristal se
 * encogía a su contenido un piso más abajo (436px). Hay que estirar hasta
 * llegar a `.mx_Welcome`.
 *
 * EL SEGUNDO SELECTOR VA POR `> *` Y NO POR `._glass_sepwu_8` A PROPÓSITO: ese
 * nombre lleva un hash de compilación de Element y cambia en cuanto la imagen
 * de base se actualice. Una regla anclada a él dejaría de aplicar en silencio y
 * el corte volvería entero. En la pantalla de bienvenida ese hijo es UNO solo
 * (comprobado: `modalContent` tiene 1 hijo en #/welcome), así que `> *` y
 * "el envoltorio" son hoy la misma cosa, sin depender de cómo se llame.
 *
 * Y EL `min-width: 0` ES LA MITAD QUE SE OLVIDA — §10 M6. Un ítem flex no
 * encoge por debajo de su min-content mientras `min-width` valga `auto`, y el
 * min-content de este ítem son 436px: en un teléfono de 390 la tarjeta volvería
 * a salirse, con las reglas puestas y pareciendo que no hacen nada.
 */
.mx_AuthPage_modal:has(.mx_Welcome) > .mx_AuthPage_modalContent,
.mx_AuthPage_modal:has(.mx_Welcome) > .mx_AuthPage_modalContent > * {
  flex: 1;
  min-width: 0;
}

/* --- 2 · El 380 del botón pasa de SUELO a TECHO ---------------------------
 *
 * Ésta es la línea que arregla el fallo. `width: 100%` hace que el botón deje
 * de imponer su ancho hacia arriba —ahora lo recibe de la tarjeta— y el
 * `max-width` conserva los 380px de siempre en cuanto hay sitio, así que en
 * escritorio el botón mide 380px igual que antes.
 *
 * NO BASTA CON PONERLE `max-width: 100%` AL BOTÓN Y DEJAR EL `width: 380px`,
 * que es el arreglo de una línea que primero parece que vale. Un `max-width`
 * en porcentaje se resuelve contra un contenedor cuyo ancho depende, a su vez,
 * del propio botón: durante el cálculo intrínseco el navegador lo trata como
 * `none`, la aportación min-content del botón sigue siendo 380 y la tarjeta
 * sigue midiendo 500. Hay que romper la circularidad por arriba (regla 1) y
 * por abajo (ésta); una sola de las dos no mueve un píxel.
 */
.mx_AuthPage .mx_DefaultWelcome_buttons a {
  width: 100%;
  max-width: 380px;
}

/* --- 2bis · Y el bloque que los contiene, que se centraba en vez de llenar --
 *
 * Tercer piso de lo mismo, y también salió midiendo y no leyendo. `.mx_Welcome`
 * es `flex-direction: column` con `align-items: center`, así que en el eje
 * horizontal sus hijos se ajustan a su contenido en vez de estirarse. Mientras
 * el botón imponía 380px eso no se notaba —el contenido YA medía 380—; en
 * cuanto el botón pasa a `width: 100%`, `.mx_DefaultWelcome` se encoge al
 * máximo de su <h1> (316px) y arrastra al botón con él. Medido a 1280px:
 * tarjeta 500 y aire 48 correctos, y el botón en 316 igualmente.
 *
 * `align-self: stretch` lo devuelve al ancho de la tarjeta. NO descentra nada:
 * lo de dentro sigue centrado por `.mx_DefaultWelcome { text-align: center }` y
 * por el `margin: 0 auto` del logo, que son de Element y no se tocan.
 */
.mx_AuthPage .mx_Welcome > .mx_DefaultWelcome {
  align-self: stretch;
}

/* --- 3 · M2 · a ≤480px lo que encoge es el AIRE ---------------------------
 *
 * Element gasta 48px de aire por lado (--cpd-space-12x). En un teléfono de
 * 320px eso son 96px —el 30% de la pantalla— en márgenes. §10 M2 dice que a
 * ≤480px el aire de tarjeta baja a 20px, y `--pia-aire-tarjeta` ya vale eso
 * ahí dentro, así que basta con consumirlo.
 *
 * Se tocan SÓLO los lados. El aire de arriba y abajo se queda como está: M2
 * habla del ancho útil, y bajar el vertical sería un cambio que nadie ha
 * medido — justo lo que M1 prohíbe al prohibir breakpoints inventados.
 *
 * El resultado a 390px: 358 de tarjeta − 24 de cristal − 40 de aire = 294px de
 * ancho útil, contra los 380 que la pantalla exigía y no tenía.
 */
@media (max-width: 480px) {
  .mx_AuthPage .mx_Welcome {
    padding-left: var(--pia-aire-tarjeta);
    padding-right: var(--pia-aire-tarjeta);
  }
}

/* =============================================================================
 * 4 · M5 · EL SUELO DE TOQUE DE 44px — nodo d0648b07, 18-ago-2026
 * =============================================================================
 *
 * Lo que este archivo dejaba escrito como pendiente. Medido de nuevo, ya con el
 * FORMULARIO de acceso delante (ver más abajo por qué eso importa), a 320, 390 y
 * 430px con emulación de móvil por CDP y Space Grotesk e Inter comprobadas:
 *
 *   #/welcome   "Iniciar sesión" ................ 36px   (faltan 8)
 *               "Crear cuenta" .................. 36px   (faltan 8)
 *               desplegable de idioma ........... 35px   (faltan 9)
 *   #/login     los dos campos .................. 39px   (faltan 5)
 *               "Iniciar sesión" (submit) ....... 36px   (faltan 8)
 *               "¿Olvidó su contraseña?" ........ 18px   (faltan 26)
 *               "Crea una cuenta" ............... 15px   (faltan 29)
 *
 * SON OCHO ELEMENTOS, NO SEIS. El "seis" que traía la nota de este archivo
 * contaba los dos campos como uno y se dejaba fuera el submit de #/login. No
 * cambia el arreglo, pero sí lo que hay que comprobar al cerrarlo: la sonda
 * cuenta ELEMENTOS y tiene que bajar de 8 a 0, no de 6 a 0.
 *
 * --- EL CRITERIO PARA LOS ENLACES DE TEXTO, que era la decisión pendiente ----
 *
 * Pregunta: ¿un enlace de texto cuenta como "control tocable" bajo M5?
 *
 * DECIDIDO: un enlace cuenta —y le aplica el suelo— CUANDO ES LA ÚNICA ACCIÓN
 * DE SU LÍNEA. Si comparte línea con otro enlace, o vive dentro de un párrafo de
 * prosa, NO le aplica y se queda con su alto de texto.
 *
 * La razón es geométrica, no de gusto, y por eso la regla se puede aplicar sin
 * discutirla cada vez. Un enlace de texto mide 15-18px de alto: los 44px NO
 * CABEN en su línea, así que crecer significa por fuerza invadir las líneas de
 * arriba y de abajo. Si el enlace es el único de su línea, esa invasión no le
 * quita el sitio a nadie —el elemento está en el flujo y empuja a sus vecinos en
 * vez de pisarlos— y el suelo sale gratis. Si al lado hay OTRO enlace, las dos
 * áreas de 44px se solapan y el dedo deja de poder elegir: le habrías dado 44px
 * a los dos y acertar sería PEOR que antes. Un suelo de toque que crea ambigüedad
 * de toque no es un arreglo.
 *
 * Los dos enlaces de estas pantallas son cada uno el único de su línea, así que
 * los dos suben a 44. Element mismo distingue los dos casos en sus clases
 * (`_kind_link` para el que ocupa su línea, `_kind_link_inline` para el que va
 * dentro de una frase), pero ESA no es la prueba: la prueba es cuántas acciones
 * hay en la línea. "Crea una cuenta" es `_inline` y aun así sube, porque
 * "¿Primera vez? Crea una cuenta" no es prosa: es una llamada a la acción con
 * dos palabras de preámbulo.
 *
 * POR ESO ESTAS REGLAS ESTÁN ACOTADAS A `.mx_AuthPage` Y NO SON GLOBALES. Dentro
 * del chat de Element hay enlaces en línea DE VERDAD —dentro de un mensaje, en
 * un párrafo de ajustes— y ahí el mismo criterio dice que NO deben subir. Una
 * regla global sobre `.mx_AccessibleButton_kind_link_inline` aplicaría el suelo
 * justo donde el criterio lo prohíbe. El criterio es por línea; el selector sólo
 * puede llegar hasta donde se ha medido.
 *
 * --- Y CÓMO se da el área, que no es lo mismo en un bloque que en línea -------
 *
 * "¿Olvidó su contraseña?" es un BLOQUE: basta `min-height` + centrado. Al estar
 * en el flujo, crecer EMPUJA al submit hacia abajo en vez de solaparlo. Sin el
 * centrado el texto se quedaría pegado arriba y los 26px nuevos parecerían un
 * fallo de espaciado.
 *
 * "Crea una cuenta" es EN LÍNEA (`display: inline`), y ahí `padding` NO SIRVE:
 * el relleno vertical de un elemento en línea no cuenta para la altura de línea,
 * así que la caja crecería PINTANDO por encima de sus vecinos sin separarlos —
 * y, peor, `getBoundingClientRect()` seguiría dando 15px, o sea que la sonda no
 * lo vería y el arreglo pasaría por hecho estando sin hacer. Un `::after`
 * absoluto tiene el mismo problema: agranda el área real pero deja la medición
 * en 15px, y un arreglo que el instrumento no puede ver no se puede cerrar.
 * `inline-flex` sí: la caja pasa a ser de verdad de 44px, la línea crece con
 * ella y la sonda lo mide.
 *
 * --- POR QUÉ VAN DENTRO DE @media Y NO SUELTAS -------------------------------
 *
 * M5 vive en §10, que es la sección de MÓVIL, y lo medido son teléfonos. El
 * punto de corte es el único que M1 permite, 480px, y no se inventa uno nuevo.
 * Dejar el escritorio intacto no es pereza: es la invariante que 81c66f4e pagó
 * por conservar en este mismo archivo, y un ratón no necesita 44px.
 * LÍMITE CONOCIDO Y DELIBERADO: una tablet táctil de 820px se queda con los
 * 36px. La consulta correcta para taparlo sería `(pointer: coarse)`, no un
 * segundo ancho — pero nadie ha medido PIA en una tablet todavía, y meter una
 * condición que no se ha medido es justo lo que M1 prohíbe. Queda dicho aquí
 * para que quien lo mida no tenga que volver a deducirlo.
 */

@media (max-width: 480px) {
  /* Los dos botones de la bienvenida y el submit del acceso. Los tres son el
     mismo componente de Element (`_button_<hash>`) y los tres traen
     `min-height: 36px`. NO se apunta a esa clase: lleva un hash de compilación
     y dejaría de aplicar en silencio cuando la imagen de base se actualice —
     el mismo motivo por el que la regla 1bis va por `> *`. Se apunta por dónde
     viven, que es estable. */
  .mx_AuthPage .mx_DefaultWelcome_buttons a,
  .mx_AuthPage .mx_Login_submit {
    min-height: 44px;
  }

  /* Los campos. El alto de 39px sale de 22,5 de línea + 16 de relleno, y el
     `box-sizing: border-box` de Element hace que este `min-height` sea el alto
     TOTAL de la caja. `.mx_Field` es flex y crece con su campo, así que el
     filete redondeado que se ve sube con él y no se queda desencajado.
     Se toca el ALTO y sólo el alto PORQUE ESTE ARREGLO ES DE ALTURAS. La letra
     la sube la sección 5, y eso NO es una violación de M3 sino su cumplimiento:
     M3 es un SUELO de 16px, escrito contra quien lo ENCOJA, y estos campos
     estaban por debajo. (Redacción corregida en el commit de la sección 5: la
     frase anterior decía «M3 prohíbe expresamente tocar la letra», que se lee
     como una prohibición general y manda al siguiente lector en la dirección
     contraria.) */
  .mx_AuthPage .mx_Field input {
    min-height: 44px;
  }

  /* El desplegable de idioma: 35px que salen de su contenido, sin relleno ni
     `min-height` propios. Ya es flex; le falta el centrado vertical, o el texto
     se queda arriba dentro de la caja nueva. */
  .mx_AuthPage .mx_Dropdown_input {
    min-height: 44px;
    align-items: center;
  }

  /* "¿Olvidó su contraseña?" — el enlace de bloque. Ver el criterio arriba. */
  .mx_AuthPage .mx_Login_forgot {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
  }

  /* "Crea una cuenta" — el enlace en línea. `inline-flex` en vez de padding por
     lo explicado arriba: es lo único que hace crecer la línea de verdad y lo
     único que la sonda puede medir. `vertical-align: middle` mantiene el texto
     alineado con el "¿Primera vez?" que lo precede en la misma línea. */
  .mx_AuthPage .mx_AccessibleButton_kind_link_inline {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    vertical-align: middle;
  }

  /* --- 4bis · LA CUARTA PANTALLA DE ACCESO, QUE NO SE HABÍA MIRADO ------------
   *
   * "Iniciar sesión en su lugar" de #/forgot_password: 31px, faltan 13. Lo
   * encontró 03123bbe el 18-ago auditando las cuatro pantallas sin sesión, y no
   * estaba en la lista de arriba por un motivo que conviene dejar dicho: la
   * sonda que cerró este nodo —sonda-bienvenida-movil.mjs— visita #/welcome y
   * #/login Y NADA MÁS. Su verde nunca dijo nada de #/forgot_password ni de
   * #/register, pero se leía como si dijera «las pantallas de acceso cumplen».
   * Una sonda que no abre una pantalla no la aprueba; la deja sin mirar, que se
   * parece mucho y no es lo mismo. Ahora las cuatro las recorre
   * scripts/sonda-toque-movil.mjs.
   *
   * SUBE, POR EL CRITERIO DE §10ter: es la ÚNICA acción de su línea —va sola
   * debajo del botón "Enviar email", comprobado en la captura a 390px— así que
   * crecer EMPUJA al resto en vez de solaparlo y no crea ninguna ambigüedad de
   * toque. Es el mismo caso que "¿Olvidó su contraseña?" de #/login, dos
   * pantallas antes en el mismo camino.
   *
   * Y ES UN BLOQUE QUE YA ES FLEX Y YA CENTRA (medido: `display: flex`,
   * `align-items: center`), así que aquí basta el `min-height` y NO se repite el
   * centrado de las reglas de arriba: una declaración que no cambia nada es una
   * pista falsa para el que venga a entender por qué esta regla es distinta. */
  .mx_AuthPage .mx_AuthBody_sign-in-instead-button {
    min-height: 44px;
  }
}

/* =============================================================================
 * 5 · M3 · LA LETRA DEL CAMPO SUBE A SU SUELO DE 16px — nodo fbe30898, 18-ago
 * =============================================================================
 *
 * ESTO NO ES UNA VIOLACIÓN DE M2, Y CONVIENE LEERLO ANTES DE BORRARLO.
 * M2 dice «lo que se adapta es el AIRE, NUNCA la letra», y va dirigida a quien
 * ENCOGE el tipo para que le quepa algo en un teléfono. Aquí no se adapta nada:
 * el valor es el MISMO en todos los anchos —16px, el de §2— y lo que se hace es
 * dejar de estar por debajo de él. Una letra que no cambia con el ancho no es
 * una letra adaptada. M3 lo dice en positivo: «los 16px del campo no se tocan».
 * Estaban tocados: a 15px.
 *
 * Y NO ES ESTÉTICA, que es la otra forma de que alguien lo baje otra vez:
 * SAFARI EN iOS HACE ZOOM sobre la página al enfocar un campo de menos de 16px.
 * El paciente se queda con la pantalla ampliada y descolocada justo mientras
 * escribe su contraseña, que es el peor momento posible de esta app. Es un
 * comportamiento del sistema operativo, no un gusto: 15px NO es «casi 16».
 *
 * MEDIDO a 320px con emulación de móvil por CDP, Space Grotesk e Inter
 * comprobadas cargadas y el formulario pintado contra el Synapse real
 * (--homeserver-real; con el homeserver caído esta pantalla es OTRA y no tiene
 * campos que medir):
 *
 *                            antes          después
 *   font-size                15px           16px
 *   line-height              22,5px         24px
 *   alto de la caja          44px           44px      <- NO se mueve, y está bien
 *   ancho del campo          189px          205px
 *   borde derecho            255px          263px     (de 320 disponibles)
 *   scrollWidth / innerWidth 320 / 320      320 / 320
 *   desbordes silenciosos    0              0
 *
 * EL ALTO NO SE MUEVE Y NO SIGNIFICA QUE ESTO NO HAYA HECHO NADA. A 16px la
 * línea pasa a 24 y con los 16 de relleno la caja pediría 40px, que sigue por
 * debajo del suelo de toque: manda el `min-height: 44px` de la sección 4. Por
 * eso el instrumento que verifica ESTA sección es el contador de TAMAÑOS DE
 * LETRA de la sonda y no el de alturas, que aquí es estructuralmente ciego.
 *
 * EL ANCHO ERA EL RIESGO Y POR ESO ESTO NO ENTRÓ EN EL NODO DE ALTURAS. Un
 * alto no cambia lo que ocupa el texto; un tamaño de letra sí. El campo crece
 * 16px (189 → 205) porque es un ítem flex y su base crece con la letra, así que
 * había que volver a medir el ancho a 320px, que es donde la tarjeta va justa.
 * Medido arriba: el borde derecho queda en 263 de 320, no aparece ningún
 * desborde nuevo y no hay ni un desbordado silencioso dentro de .mx_AuthPage.
 *
 * LA ETIQUETA SE QUEDA EN 15px A PROPÓSITO. §2 fija los 16px para el CAMPO, y
 * el zoom de Safari lo dispara el control que recibe el teclado, no su rótulo.
 * Subir la etiqueta sería adaptar tipografía sin ninguna regla que lo pida —
 * eso sí sería M2. Medido: la etiqueta larga («Nombre de usuario») pide 137px y
 * tiene 137, o sea que tampoco es un problema de ancho esperando a pasar.
 *
 * SE NOMBRA EL TOKEN Y NO SE REESCRIBE EL 16, por M2: `--pia-txt-campo` vive en
 * pia-tokens.css con su propio aviso de no bajarlo, y ese fichero SÍ llega a
 * Element (entra por COPY en element/Dockerfile). Volver a teclear el número es
 * exactamente lo que hizo derivar el aire en dos pantallas — ver §10bis.
 *
 * VAN LOS TRES CONTROLES DE TECLADO, no sólo `input`. Hoy sólo existen los dos
 * `input` de #/login (medido: el selector engancha 2 elementos y ninguno más),
 * pero el contador de la sonda puntúa `input`, `textarea` y `select` juntos
 * porque son los tres que disparan el zoom de iOS. Una regla que protegiera
 * menos de lo que su detector vigila produciría un día un rojo que no se puede
 * arreglar leyendo este archivo.
 *
 * NO SE TOCAN NI LOS BOTONES NI EL DESPLEGABLE DE IDIOMA, y también están a
 * 15px. No es un olvido: el zoom de iOS lo disparan los campos que reciben
 * texto por teclado, y el desplegable de Element es un `div`, no un `select`.
 * Darles 16px sería aplicarles una regla que no les habla.
 *
 * LÍMITE CONOCIDO Y DELIBERADO, el mismo que la sección 4: por encima de 480px
 * los campos se quedan en 15px, así que un iPad táctil con Safari seguiría
 * haciendo zoom. La consulta correcta para taparlo es `(pointer: coarse)`, no un
 * segundo ancho (M1), y nadie ha medido PIA en una tablet. Además §2 no es una
 * sección de móvil —su tabla dice que el campo mide 16px y punto—, así que lo
 * verdaderamente correcto sería subirlo también en escritorio; pero eso vive en
 * otro fichero y en una pantalla que nadie ha medido, y este archivo tiene la
 * invariante de devolver el escritorio intacto si se le quita el <link>.
 */
@media (max-width: 480px) {
  .mx_AuthPage .mx_Field input,
  .mx_AuthPage .mx_Field textarea,
  .mx_AuthPage .mx_Field select {
    font-size: var(--pia-txt-campo);
  }
}

/* =============================================================================
 * 6 · M6 · EL TOOLTIP INVISIBLE QUE LLEVA LA URL DEL HOMESERVER — nodo 27bd0a75
 * =============================================================================
 *
 * EL FALLO. A 320px, #/login producía scroll horizontal de verdad: scrollWidth
 * 325 sobre 320. El culpable es un tooltip de Element marcado como INVISIBLE
 * (`_invisible_`) que lleva dentro la URL del homeserver, o sea que no se ve
 * nada raro en pantalla y aun así la página se mueve al deslizar. No es una
 * regresión de la sección 4: está igual en las mediciones de antes y de después.
 *
 * CÓMO SE SALE, que es lo que decide el arreglo. El tooltip lo coloca
 * floating-ui así (leído del atributo `style` en la página viva):
 *
 *     position: absolute; left: 0; top: 0; transform: translate(5px, 6px)
 *
 * Su bloque contenedor es el inicial, así que el navegador le da el ancho de
 * ajuste = min(disponible, max-content) = 320 … y DESPUÉS el `transform` lo
 * empuja 5px a la derecha. Los 5px de desborde son la traslación, que se aplica
 * cuando el ancho ya está decidido. De ahí salen las dos cosas que NO funcionan,
 * las dos medidas y no supuestas:
 *
 * Y LA RAZÓN DE FONDO NO ES DE ESTE ELEMENTO: UN `transform` NO ES LAYOUT.
 * Ocurre después de que el ancho esté decidido, así que NINGUNA declaración de
 * layout —`width`, `max-width`, `min-width`, `overflow-wrap`— puede compensar una
 * traslación, por construcción. Sólo se le gana encogiendo la caja hasta que caja
 * + desplazamiento quepan, que es lo que hace el techo de abajo. Todo lo que
 * coloque floating-ui —tooltips, menús, popovers— es inmune a M6 por la misma
 * razón, así que esto vale para una clase entera y no para un tooltip.
 *
 *   `max-width: 100%`        el 100% es 320 → sigue saliendo a 325. No mueve nada.
 *   `min-width: 0` a secas   la caja ya computaba `min-width: 0px`. Cero efecto.
 *
 * ⚠️ M6 TAL CUAL —`min-width:0` + `overflow-wrap`— NO ARREGLA ESTO SOLA, y
 * merece quedar escrito porque es la receta que el canon manda para «todo lo que
 * imprima un dato ajeno» y aquí se queda a medias. Medido, con la caja y el
 * texto por separado: `overflow-wrap` sólo baja el ancho MÍNIMO del contenido, y
 * el que manda aquí es el DISPONIBLE, que no depende de dónde rompa el texto.
 * Con el túnel de hoy la caja se queda en [5..325] con la regla puesta, idéntica
 * al píxel a no tener nada. Una regla que no mueve un píxel es peor que ninguna:
 * ocupa el sitio del arreglo y pasa la revisión.
 *
 * LO QUE FALTA ES UN TECHO, Y NO PUEDE SER UN NÚMERO. El ancho del tooltip lo
 * fija el largo de la URL del homeserver, que hoy es un túnel de cloudflared con
 * nombre generado y CAMBIA SOLO: con el túnel anterior se salía 4px y con el de
 * ahora 5. Cualquier `max-width` en píxeles sería un número afinado contra el
 * túnel de esta semana. El techo va contra el VIEWPORT y contra el token del
 * margen del lienzo, que es el mismo patrón que ya usa la regla 1 de este
 * archivo: un tooltip tampoco tiene por qué tocar los bordes del teléfono.
 * Margen de seguridad medido: el token da 32px y la traslación es de 5-6px, o
 * sea 26px de holgura sobre el único número que aquí no controlamos.
 *
 * ES UNA COTA, NO UNA INVARIANTE, y conviene no leerlo como «resuelto para
 * cualquier desplazamiento». Si floating-ui llegara a colocar este tooltip con
 * una traslación mayor que la holgura, se saldría otra vez Y LA REGLA SEGUIRÍA
 * PARECIENDO CORRECTA MIENTRAS FALLA. El número se nombra justo para que quien
 * lo revise sepa contra qué compararlo.
 *
 * Y HACEN FALTA LAS DOS COSAS, CADA UNA CONTRA UN FALLO DISTINTO. Se probó con
 * el caso duro del canon —un dominio SIN GUIONES, que el navegador no sabe
 * romper solo (§10, «Por qué existe M6»)— porque el túnel de hoy lleva guiones y
 * con él TODO parece verde. A 320px, con una URL sin guiones del mismo largo:
 *
 *   sin nada .................. viewport 412 · caja [5..412] · 2 elementos fuera
 *   sólo el techo ............. viewport 341 · caja [6..294] · 1 elemento fuera
 *                               la CAJA obedece y el TEXTO se sale a 341: es el
 *                               desborde silencioso de M6, en su forma de manual
 *   sólo `min-width: 0` ....... idéntico a no poner nada
 *   techo + `overflow-wrap` ... viewport 320 · caja [6..294] · 0 fuera ✔
 *
 * El techo evita que la CAJA se salga de la pantalla; el `overflow-wrap` evita
 * que el TEXTO se salga de la caja. Con el túnel de hoy la segunda mitad no se
 * nota, y ése es justo el motivo de escribirla: se nota el día que un homeserver
 * se llame sin guiones, y ese día nadie va a estar mirando.
 *
 * POR QUÉ NO HAY `min-width: 0`, que M6 pide como «la mitad que se olvida».
 * Medido arriba: aquí no hace falta, y se deja fuera en vez de ponerlo por si
 * acaso. El texto es un ítem flex y su mínimo automático es su ancho de
 * min-content; `overflow-wrap: anywhere` —a diferencia de `break-word`— SÍ
 * reduce ese min-content, así que ya deja encoger al ítem y `min-width: 0` no
 * cambia un píxel (comprobado también poniéndolo en el hijo con `> *`). M6 sigue
 * siendo verdad para `break-word` y para las cadenas de flex con más contenido
 * al lado; no lo es para esta forma. Poner una declaración que no hace nada es
 * el error que este mismo bloque acaba de documentar dos párrafos más arriba.
 *
 * EL SELECTOR NO PUEDE LLEVAR EL HASH. La clase real es `_tooltip_1nqnq_8`, y
 * ese `1nqnq` es un hash de compilación de Element: una regla anclada a él
 * dejaría de aplicar EN SILENCIO en cuanto se actualice la imagen de base y el
 * scroll volvería entero. Es el mismo motivo por el que la regla 1bis va por
 * `> *` y no por `._glass_sepwu_8`. Se ancla por el trozo del nombre que sale
 * del código fuente de Element y no del build, `_tooltip_`.
 *
 * Y SE ACOTA POR `body:has(.mx_AuthPage)` Y NO POR `.mx_AuthPage`, que es lo que
 * uno escribiría. El tooltip NO vive dentro de la tarjeta: floating-ui lo saca a
 * un portal colgado del <body>. Medido: `.mx_AuthPage [class*="_tooltip_"]`
 * engancha 0 elementos y `body:has(.mx_AuthPage) [class*="_tooltip_"]` engancha
 * 1, que es el que hay. Ese `body:has()` ya se usa en pia-simplificar.css. El
 * acotado importa: dentro del chat de Element hay tooltips de verdad, y ésos no
 * se han medido.
 */
@media (max-width: 480px) {
  body:has(.mx_AuthPage) [class*="_tooltip_"] {
    box-sizing: border-box;
    max-width: calc(100vw - var(--pia-margen-lienzo) * 2);
    overflow-wrap: anywhere;
  }
}

/* =============================================================================
 * 7 · LA TARJETA DE VERIFICACIÓN DE DISPOSITIVO — nodo 607440c9, 18-ago-2026
 * =============================================================================
 *
 * MEDIDO por 7554dfea en la WebView real de Android (PIA_API36, no en Chrome de
 * escritorio): `.mx_AuthPage_modal` mide 664px en un viewport de 412 — 252px
 * fuera de pantalla — y la «X» de saltar (`.mx_CompleteSecurity_skip`) queda a
 * `right:640`, inalcanzable con `elementFromPoint` en su propio centro. Se
 * puede llegar a ella arrastrando (`scrollLeft` hasta 251.8), pero nada indica
 * que haya que hacerlo: no está "inusable", está sin pista.
 *
 * ⚠️ LA CLASE SE LLAMA `.mx_CompleteSecurityBody`, NO `.mx_CompleteSecurity`.
 * El primer resumen de este nodo usaba el nombre corto y un `:has()` contra él
 * no habría enganchado nada — verificado esta vez contra el DOM real, paso a
 * paso, con un usuario de prueba aislado (sin puentes) en vez de la cuenta
 * root, para no arriesgar las conversaciones reales que cuelgan de ella.
 *
 * LA CADENA, medida nivel a nivel desde `.mx_AuthPage_modal` (que aquí NO
 * cambia de la de #/welcome — es el mismo layout compartido de Element):
 *
 *   .mx_AuthPage_modal                    664px  flex, 1 hijo
 *   > .mx_AuthPage_modalContent           664px  flex, 1 hijo
 *   > > ._glass_sepwu_8 (el cristal)      664px  flex, 1 hijo
 *   > > > .mx_CompleteSecurityBody        640px  BLOCK (no flex), 2 hijos
 *   > > > > ... > .mx_EncryptionCard      600px  ← LA CAUSA
 *
 * `.mx_EncryptionCard` trae `width: 600px` A FUEGO, de Element. Es el mismo
 * defecto que el botón de 380px de #/welcome (sección 2) — un número fijo que
 * ningún ancestro acota — pero un piso más abajo: aquí NO llega por min-content
 * de un botón, es un `width` literal en un descendiente de bloque, y por eso
 * el arreglo necesita UN NIVEL MÁS de relevo que el de #/welcome.
 *
 * TRES PIEZAS, cada una contra un tramo distinto de la cadena:
 *
 * (a) Acota la tarjeta, igual que la regla 1 — mismo patrón, mismo token.
 * (b) El relevo de flex:1 + min-width:0 (§10 M6) tiene que llegar hasta
 *     `.mx_CompleteSecurityBody`, no sólo hasta el cristal como en #/welcome:
 *     aquí hay un envoltorio más antes de tocar el bloque que contiene el
 *     540px real que hay que ajustar. `.mx_CompleteSecurityBody` es BLOCK y no
 *     flex, pero eso no la libra: sigue siendo el hijo único de un contenedor
 *     flex (el cristal), así que sigue necesitando poder encoger como ítem.
 * (c) El 600 de `.mx_EncryptionCard` pasa de SUELO a TECHO, igual que la
 *     regla 2 con el botón de 380. Sin ESTA pieza, (a) y (b) no bastan: el
 *     bloque encogería alrededor de una tarjeta que sigue pidiendo 600px fijos
 *     y el desborde reaparecería un piso más abajo.
 *
 * NO SE ACOTA `.mx_EncryptionCard` a esta pantalla con `:has()` A PROPÓSITO:
 * es un componente compartido de todo el flujo de cifrado dentro de
 * `.mx_AuthPage` (verificación, «¿no puedes confirmarlo?», crear clave de
 * recuperación), y las tres pantallas comparten el mismo defecto — igual que
 * el `.mx_AuthPage .mx_Field input` de la sección 5 no se acota a #/login.
 * Fuera de `.mx_AuthPage` (por ejemplo en Ajustes) esta regla no llega.
 *
 * VERIFICADO reconstruyendo la imagen y volviendo a medir en la misma WebView:
 * `.mx_AuthPage_modal` 664px → 380px (viewport 412 − 2×16 del margen del
 * lienzo), 0 elementos con el borde derecho fuera de los 412px del viewport.
 */
.mx_AuthPage_modal:has(.mx_CompleteSecurityBody) {
  width: min(500px, 100% - var(--pia-margen-lienzo) * 2);
}

.mx_AuthPage_modal:has(.mx_CompleteSecurityBody) > .mx_AuthPage_modalContent,
.mx_AuthPage_modal:has(.mx_CompleteSecurityBody) > .mx_AuthPage_modalContent > *,
.mx_AuthPage_modal:has(.mx_CompleteSecurityBody)
  > .mx_AuthPage_modalContent
  > *
  > * {
  flex: 1;
  min-width: 0;
}

.mx_AuthPage .mx_EncryptionCard {
  width: 100%;
  max-width: 600px;
}

/* --- 7bis · M5 · el suelo de toque de la «X» de saltar --------------------
 *
 * `.mx_CompleteSecurity_skip` mide 20×20 de contenido + 4px de relleno = 28×28
 * (medido, `box-sizing: content-box`). Es `position: absolute; top; right`
 * dentro de un encabezado de alto 0, así que basta con subir el relleno: con
 * el mismo `box-sizing`, 20 + 2×12 = 44. No se toca `top` ni `right` — el
 * icono se desplaza unos px hacia el interior de la tarjeta en vez de quedarse
 * clavado en la esquina, que es preferible a que seis nodos midan lo mismo M5
 * seis veces con seis geometrías distintas. Sólo en móvil, igual que la
 * sección 4: en escritorio la «X» no compite por espacio y un ratón no
 * necesita 44px.
 */
@media (max-width: 480px) {
  .mx_AuthPage .mx_CompleteSecurity_skip {
    padding: 12px;
  }
}

/* =============================================================================
 * 8 · EL HUECO VACÍO ABAJO EN #/welcome Y #/login — nodo b602ccba, 18-ago-2026
 * =============================================================================
 *
 * Reportado por Zey con capturas reales del emulador PIA_API36 (Android 16,
 * edge-to-edge): en las dos pantallas la tarjeta queda pegada arriba y deja un
 * hueco vacío enorme abajo. NO es un contenedor sin `align-items`/
 * `justify-content` — se midió esa cadena entera (`.mx_AuthPage_modal` →
 * `.mx_AuthPage` → `body` → `html`) y los tres dan `align-items: normal`,
 * `justify-content: normal` en TODOS los anchos, incluido escritorio a
 * 1280px. Ir a "arreglar" eso habría sido perseguir un síntoma que ni existe:
 * `.mx_AuthPage` no centra por flex, nunca lo ha hecho.
 *
 * LA CAUSA REAL, de Element y no de PIA — leída del CSS servido
 * (theme-light.css), no supuesta:
 *
 *     .mx_AuthPage_modal { margin: 100px auto auto }
 *     @media (max-height: 768px) { .mx_AuthPage_modal { margin-top: 50px } }
 *     @media (max-width:  480px) { .mx_AuthPage_modal { margin-top: 0    } }
 *
 * Element "centra" la tarjeta con un `margin-top` fijo que se va achicando
 * (100 → 50 → 0), NUNCA con centrado de verdad. A ≤480px de ancho —que es
 * TODOS los teléfonos, M1— el margen queda en 0 sin condición ninguna: la
 * tarjeta se pega arriba y lo que sobre de alto se queda vacío debajo, porque
 * `margin-bottom` sigue en `auto` (se lo dio el `margin: 100px auto auto` de
 * arriba, y ningún breakpoint lo toca). Con la altura de viewport de ANTES
 * —más corta, sin edge-to-edge— ese vacío cabía casi todo bajo el pliegue y
 * apenas se notaba. A 915px reales (PIA_API36, 1080×2400 / 2,625) el hueco
 * medido es de 520px en #/welcome y 535px en #/login: MÁS DE LA MITAD de la
 * pantalla. No es una regresión de esta noche — la regla de Element ya
 * pegaba la tarjeta arriba antes del arreglo de edge-to-edge — pero antes el
 * WebView entregaba menos alto útil y el defecto quedaba oculto por debajo
 * del pliegue; el arreglo de edge-to-edge no lo causó, lo hizo VISIBLE.
 *
 * EL ARREGLO ES UNA LÍNEA, y usa el mismo mecanismo de Element en vez de
 * pelear contra él: `margin-top: auto`. Con `margin-bottom` ya en `auto` por
 * la regla base, las dos juntas hacen que el flex en columna de `.mx_AuthPage`
 * reparta el espacio libre por IGUAL arriba y abajo — centrado de verdad, no
 * un número que se aproxima. Y SE DEGRADA SOLO si el contenido no cabe: los
 * márgenes `auto` de flexbox se resuelven a 0 cuando el espacio libre es
 * negativo (spec, no suposición), así que una pantalla con formulario largo
 * no gana un recorte nuevo — se queda como hoy, pegada arriba con scroll.
 *
 * NO VA EN UN `:has()` A PROPÓSITO. A diferencia de la sección 1 —que acota a
 * `:has(.mx_Welcome)` porque fijar un `width` en TODAS las tarjetas de
 * `.mx_AuthPage_modal` rompería acceso y registro (su ancho lo decide su
 * contenido, y hoy no se salen)— aquí no hay ningún efecto colateral que
 * evitar: centrar verticalmente una tarjeta que hoy vive pegada arriba no
 * puede romper una pantalla sana, porque NINGUNA pantalla de `.mx_AuthPage`
 * está usando ese hueco vacío para nada. Por eso el selector es
 * `.mx_AuthPage_modal` a secas: welcome, login, registro, verificación
 * (sección 7) y cualquier pantalla futura de este flujo se centran igual, sin
 * tener que acordarse de añadir un `:has()` nuevo cada vez que aparezca una.
 *
 * SÓLO EN MÓVIL, dentro del `@media (max-width: 480px)` que ya trae la propia
 * regla de Element que se está sobrescribiendo — mismo corte que M1, y el
 * escritorio (donde Element ya usa `margin-top: 100px`, un offset fijo que
 * nadie ha reportado roto) queda intacto si se quita el `<link>`.
 *
 * VERIFICADO en vivo contra Element real (localhost:8080) con Chrome headless
 * aislado (perfil + puerto propios, sin tocar el emulador — otro agente lo
 * tenía en uso para el nodo 607440c9 esa misma noche), tres alturas de
 * viewport distintas a 412px de ancho:
 *
 *   alto   hueco ANTES (arriba=0)   hueco DESPUÉS (arriba = abajo)
 *   915px  520px                    260px / 260px
 *   700px  305px                    137.5px / 137.5px
 *   844px  ...                      209.5px / 209.5px (a 320px de ancho)
 *
 * Centrado exacto al medio píxel en los tres casos. CONFIRMADO tras
 * reconstruir la imagen (`docker compose build element`, md5 del CSS servido
 * igual al del árbol de trabajo) y volver a medir contra Synapse real a
 * 412×915 —la resolución física del PIA_API36—: welcome 260px/260px, login
 * 267,5px/267,5px. Capturas en el nodo b602ccba.
 */
@media (max-width: 480px) {
  .mx_AuthPage_modal {
    margin-top: auto;
  }
}

/* =============================================================================
 * LO QUE ESTE ARCHIVO NO ARREGLA, A PROPÓSITO
 * =============================================================================
 *
 * Este bloque nació como lista de PENDIENTES y hoy es HISTORIA: los dos ya están
 * arreglados, en las secciones 5 y 6. Se conserva —en vez de borrarlo— porque lo
 * que cuesta reconstruir no es el defecto sino POR QUÉ fue un nodo aparte, y sin
 * eso el siguiente lector ve dos arreglos vecinos en el mismo fichero y los
 * vuelve a fundir en uno.
 *
 * 1 · LA LETRA DE 15px EN LOS CAMPOS DE #/login → ARREGLADO, sección 5.
 * Por qué no entró aquí: la sección 4 sube ALTURAS, y un alto no cambia lo que
 * ocupa el texto; un tamaño de letra SÍ. Subir 15 → 16 ensancha el campo (medido:
 * 189 → 205px) dentro de una tarjeta que a 320px ya va justa, así que obligaba a
 * volver a medir el ANCHO — una comprobación que un nodo de alturas no hace y que
 * no se puede colar de rebote. Tenía nodo propio: fbe30898.
 *
 * 2 · EL DESBORDE A LO ANCHO DE #/login A 320px → ARREGLADO, sección 6.
 * Por qué no entró aquí: NO era una regresión de la sección 4 —sale idéntico en
 * las mediciones de antes y de después— y no es un problema de alturas en
 * absoluto. Además su ancho lo fija un dato ajeno que cambia solo (el nombre del
 * túnel), o sea que pedía un arreglo de forma distinta —un techo, no un número—
 * y una comprobación distinta. Tenía nodo propio: 27bd0a75.
 *
 * -----------------------------------------------------------------------------
 * CÓMO SE MIDIÓ ESTO, que es la parte que no se puede repetir de memoria
 * -----------------------------------------------------------------------------
 *
 * El 18-ago-2026 Synapse estuvo en bucle de reinicio (`database disk image is
 * malformed`) y los dos túneles de cloudflared estaban muertos. CON EL SERVIDOR
 * INALCANZABLE ELEMENT NO PINTA EL FORMULARIO: cambia la tarjeta entera por «No
 * se puede conectar con el servidor», y los controles a medir NO EXISTEN en el
 * DOM. Una corrida así no mide de menos: mide OTRA PANTALLA, y encima distinta
 * en cada ancho según lo que hubiera llegado a pintar.
 *
 * Por eso la sonda tiene dos flags, y NO son intercambiables:
 *   --servidor-simulado    inventa las respuestas del homeserver. Para cuando no
 *                          hay servidor. Suficiente para iterar, NO para cerrar.
 *   --homeserver-real URL  manda las peticiones al Synapse de VERDAD por otra
 *                          puerta (localhost:8008), saltándose el túnel muerto.
 *                          No inventa nada: sólo cambia la ruta de transporte, y
 *                          una ruta no entra en el cálculo de una altura.
 *
 * LA MEDICIÓN QUE CIERRA ESTE ARREGLO es la segunda, y además con la imagen
 * RECONSTRUIDA (este fichero entra por COPY, no por volumen: editarlo y recargar
 * no cambia nada, ver el flag --css-local y su aviso). Comprobado que la imagen
 * servía este fichero comparando md5 antes de medir:
 *
 *     node scripts/sonda-bienvenida-movil.mjs --homeserver-real http://localhost:8008
 *
 * Resultado: 0 controles por debajo de 44px en las dos pantallas a 320, 390 y
 * 430. Y a 481 y 1280 vuelven los 36/35/39/18/15 de siempre, que es la prueba de
 * que el escritorio quedó intacto y de que el corte es exactamente el de M1.
 */
