Find a file
SITO 7d5dbeec60 Cuenta de externas, arreglos de seguridad, títulos arriba y despliegue
- Rol «externas» para la asamblea de externas: pide sin cupo, siempre con el
  colectivo de fuera y su contacto, y sus solicitudes salen en naranja hasta
  que la asamblea de la Enre las confirma.
- /pedir/ explica en una línea que los colectivos externos piden fecha en la
  asamblea de externas, los lunes de 19:00 a 20:00.
- Seguridad: argon2 limitado a dos cálculos a la vez y el intento se cuenta
  antes de calcular (60 accesos simultáneos llevaban el proceso a 3,8 GB);
  bloqueo por cuenta a 20 fallos para que no se pueda dejar fuera a la
  asamblea; avisos por sesión en vez de por URL; sig sin «..»; eventos de
  31 días como mucho; parámetros de argon2 acotados.
- Títulos pegados arriba en todas las páginas; la franja de la enredadera
  recupera ese alto para seguir llenando la pantalla.
- despliegue/: instalar.sh, cuenta.sh, servicio de systemd con el proceso
  encerrado, fragmento de nginx que además deja de servir .git y las notas
  internas, y configuración de ejemplo. Ninguna contraseña en el repositorio.
2026-09-23 12:15:33 +02:00
despliegue Cuenta de externas, arreglos de seguridad, títulos arriba y despliegue 2026-09-23 12:15:33 +02:00
fuentes Sección «Pedir evento» con gestor de reservas y calendario legible en móvil 2026-09-23 11:32:25 +02:00
gestor Cuenta de externas, arreglos de seguridad, títulos arriba y despliegue 2026-09-23 12:15:33 +02:00
INFO Rediseño de la enredadera y páginas nuevas 2026-09-09 00:34:53 +02:00
subdir Sección «Pedir evento» con gestor de reservas y calendario legible en móvil 2026-09-23 11:32:25 +02:00
.gitignore Cuenta de externas, arreglos de seguridad, títulos arriba y despliegue 2026-09-23 12:15:33 +02:00
404.html Sección «Pedir evento» con gestor de reservas y calendario legible en móvil 2026-09-23 11:32:25 +02:00
calendario.html Sección «Pedir evento» con gestor de reservas y calendario legible en móvil 2026-09-23 11:32:25 +02:00
code-462w-pink.zip commit web inicial 2025-11-06 21:37:51 +01:00
Code462WPink-Regular.ttf commit web inicial 2025-11-06 21:37:51 +01:00
code_.png commit web inicial 2025-11-06 21:37:51 +01:00
colectivos.html Sección «Pedir evento» con gestor de reservas y calendario legible en móvil 2026-09-23 11:32:25 +02:00
context.txt feat: calendario gancio-calendar + horarios semanales + mejoras CSS 2026-04-09 00:09:34 +02:00
eventos.html Sección «Pedir evento» con gestor de reservas y calendario legible en móvil 2026-09-23 11:32:25 +02:00
favicon.ico Rediseño de la enredadera y páginas nuevas 2026-09-09 00:34:53 +02:00
favicon.svg Rediseño de la enredadera y páginas nuevas 2026-09-09 00:34:53 +02:00
index.css Cuenta de externas, arreglos de seguridad, títulos arriba y despliegue 2026-09-23 12:15:33 +02:00
index.html Sección «Pedir evento» con gestor de reservas y calendario legible en móvil 2026-09-23 11:32:25 +02:00
info.txt commit web inicial 2025-11-06 21:37:51 +01:00
panel.html Sección «Pedir evento» con gestor de reservas y calendario legible en móvil 2026-09-23 11:32:25 +02:00
README.md La enredadera serpentea entre filas y los brotes cuelgan de un tallo 2026-09-14 20:38:40 +02:00
tatus.html Sección «Pedir evento» con gestor de reservas y calendario legible en móvil 2026-09-23 11:32:25 +02:00

Web del CSO La Enredadera de Tetuán

Sitio estático: HTML y CSS. No hay build, ni framework, ni dependencias. Se despliega copiando la carpeta y sirviéndola con cualquier servidor web.

Todo el JavaScript que hay son los dos calendarios, que venían de antes y funcionan. La navegación, el menú, las fichas de colectivo y el brote de REDES son CSS puro: funcionan con JavaScript desactivado. Comprobado, no supuesto: se desactiva el JS por CDP y se mira. Los dos calendarios, que sí lo necesitan, avisan de ello con un <noscript> y dicen dónde mirar.


Ver la web en local

python3 -m http.server 8099 --bind 127.0.0.1

y abrir http://127.0.0.1:8099/. Tiene que servirse por HTTP: si abres el fichero con file:// fallan las rutas absolutas y el calendario de convoca.la.


Los ficheros

Fichero Qué es
index.html Portada: la enredadera con seis hojas
colectivos.html Las doce hojas de colectivos: once con ficha y Tattoo Circus, que lleva a su micrositio
calendario.html Horarios semanales de cada colectivo
eventos.html Agenda de convoca.la
subdir/campa.html Campañas
subdir/sobre_nosotrxs.html Quiénes somos y la historia del espacio
subdir/contacto.html Dónde estamos y cómo proponer algo
tatus.html, panel.html Tattoo Circus: micrositio aparte, con su propio CSS
404.html Página de error, con el mismo armazón que el resto
index.css Todo el estilo del sitio, menos los dos del Tattoo Circus
INFO/ Imágenes. 12 de las 18 no se usan (3,2 MB): ver pendientes
favicon.svg, favicon.ico Icono: una hoja verde con los nervios en rosa
Code462WPink-Regular.ttf La fuente de los títulos, servida desde aquí

Añadir una hoja a la enredadera

Copia un <li> entero y cambia el enlace y el texto. Nada más. La posición, el ángulo y el tamaño salen solos de :nth-child, así que la hoja nueva se coloca en el punto que le toca sin tocar el CSS.

<li>
  <a class="hoja" href="/donde-va.html">
    <svg class="hoja-svg" viewBox="0 0 100 114" aria-hidden="true"><use href="#hoja-forma"></use></svg>
    <span class="hoja-txt">Como se llama</span>
  </a>
</li>

Variantes:

  • class="hoja brota" — hoja más tenue, para un colectivo que existe pero todavía no ha escrito su ficha.
  • Para que abra una ficha en vez de ir a otra página, el enlace apunta a #ficha-loquesea y añades el <article class="ficha" id="ficha-loquesea"> al final del documento, copiando uno de los que ya hay.

Aviso: los ciclos son de 6. Si añades una séptima hoja a la portada, la raíz seguirá pasando por su sitio, pero repasa a ojo que no se pise con la vecina — y pasa el banco de pruebas (más abajo).


Los colores

Están todos en :root, al principio de index.css. Para recolorear el sitio entero solo hay que tocar ahí.

Variable Para qué
--verde, --verde-hondo, --verde-humo fondos
--rosa contorno de las hojas y acentos. Nunca para texto normal: da 3.1:1
--rosa-legible el rosa para textos y enlaces: 6.3:1
--verde-vivo nervios y zarcillos. Es adorno: 1.7:1, no vale para texto
--verde-hoja el verde legible, para subtítulos
--tinta, --tinta-suave textos
--marron, --negro las dos hebras de la raíz

Los contrastes están medidos contra WCAG AA. Si cambias un color, mídelo: hay un cálculo hecho en ../BITACORA.md que puedes reutilizar.


Las tres medidas de la enredadera

Están en .enredadera, y son tres cosas distintas a propósito. Antes eran una sola variable y se estorbaban entre sí.

Variable Qué manda
--fila la separación: alto de la franja. Más alta = hojas más apartadas y menos hueco abajo
--hoja-base el tamaño de la hoja
--col el ancho real de columna, que es el tope de la hoja

Por qué separadas: estirar la franja para que llene la pantalla agrandaba también las hojas y volvía a juntarlas. Ese fue el callejón de «--fila a 63vh», anotado en ../BITACORA.md.

Y --col no es 15vw: coinciden solo por debajo de 1680px. A partir de ahí la rejilla deja de crecer (max-width:1680px) pero 15vw sigue subiendo, así que a 1920 las hojas se salían de su columna y se pisaban.

En móvil mandan otras dos, en .enredadera-wrap:

  • --ancho-hoja, de la que salen a la vez el ancho de la hoja y el hueco bajo la cabecera, porque las hojas de móvil giran hacia arriba y sobresalen ~0.96 de su ancho por encima de donde se agarran. Si se separan esas dos medidas, la primera hoja se come el subtítulo. Va contra las dos dimensiones —min(28vw, 13.6vh)—: sólo con vw, en una pantalla baja las seis hojas no entran sin deslizar.
  • --celda, el alto de cada <li>. Es más corto que la hoja a propósito: las hojas alternan lado, así que se entrelazan como en una enredadera de verdad. Reparte entre las seis lo que queda tras la cabecera, el hueco de entrada y lo que la última asoma por abajo, así que la portada entra sin deslizar de 320x568 para arriba.

El tallo de móvil son tres dibujos, no uno: la onda que empieza a la derecha, su espejo y el remate con espiral de la última celda. La onda es x = 50 ± 28·cos(pi·y/100) en un recuadro de 100x100 que se pinta cuadrado —background-size:var(--celda) 100%—, así que la escala sale uniforme. En los dos bordes la tangente es vertical: por eso dos celdas seguidas empalman sin junta, y por eso los extremos caen justo donde se agarra la hoja. Si tocas la amplitud, toca también el --centrar de las hojas, que vale AM/100.


Cuidado con --tam dentro de una hoja

Las reglas por hoja son de la forma:

.enredadera > li:nth-child(12n+4) .hoja{ --giro:154deg; --tam:0.92; }

Ese .hoja es un descendiente, así que alcanza también a las hojas que haya dentro del <li> —los brotes de REDES— y con especificidad (0,3,1), que le gana a cualquier .una-clase. Poner --tam en .hoja-brote no hacía nada: los brotes salían con el --tam de REDES, al doble de tamaño, y se comían a las hojas vecinas.

Regla: dentro de un <li> de la enredadera, no confíes en --tam. Si necesitas un tamaño propio, escríbelo en la medida, sin var(--tam).


La raíz (los dibujos de la enredadera)

Los dibujos —la bajada desde el título, la franja de ordenador, su remate y el tallo de móvil— no están escritos a mano: los genera un script, porque el trenzado hay que calcularlo (la perpendicular a lo largo del recorrido).

cd ../prueba && python3 raiz2.py     # regenera raiz2.json

Después hay que reinyectar los SVG en el CSS. Y lo más importante:

Los puntos por donde pasa la raíz y las alturas de las que cuelgan las hojas (--y en las reglas nth-child(12n+N)) tienen que coincidir. Si mueves uno sin mover el otro, las hojas quedan flotando sin tocar la raíz.

Para eso está ../coherencia.py: compara el CSS contra el JSON y avisa. Pásalo siempre después de tocar la raíz.

La franja de ordenador: dos filas, no una

La franja es la única parte que se repite, porque una página puede tener más hojas de las que caben en una fila: colectivos tiene doce, o sea dos.

El dibujo lleva dos filas: la pasada de izquierda a derecha y, debajo, esa misma pasada en espejo —un <use> del mismo grupo, así que no pesa el doble—. Entra y sale vertical por las dos esquinas, de modo que empalma con su espejo por la derecha y con la copia siguiente por la izquierda. Puesto con repeat-y y background-size:100% calc(var(--fila) * 2), la enredadera serpentea por las filas que haga falta sin una sola junta. Antes el dibujo era de una fila y remataba en espiral: en colectivos se veían dos ramas sueltas, la segunda empezando otra vez desde el margen izquierdo.

De ahí salen tres cosas encadenadas:

  • La tanda de las reglas por hoja es de doce (nth-child(12n+N)), no de seis: las seis de la pasada y las seis del espejo, que son las mismas leídas del revés y con el giro cambiado de signo. ../coherencia.py lo comprueba.
  • El tallo va en dos capas, no en el fondo del <ul>: .enredadera::before pinta todas las filas menos la última (top:0; bottom:var(--fila)) y .enredadera::after pinta la última con el remate en espiral. Las dos con z-index:-1, que es donde estaba el fondo al que sustituyen.
  • Si la última fila es par, la pasada va de derecha a izquierda y el remate se pinta en espejo. Lo decide un :has() sobre dónde cae el último <li> dentro de la tanda de doce, así que añadir una hoja sigue sin tocar nada.

La bajada del título

Es el dibujo más delicado de los tres, porque empalma con dos cosas a la vez: el título por arriba y la franja por la esquina de abajo a la izquierda.

  • Su viewBox es 1000x72 y la caja que lo pinta mide --bajada, o sea el 7.2% de --rejilla. Los dos números van juntos: si cambias uno, cambia el otro, o el dibujo se deforma —preserveAspectRatio es none—.
  • Las hebras no son stroke sino cintas rellenas de grosor variable (../prueba/cinta.py), afiladas en la punta y del grosor de la franja —9 y 5.5— en el empalme. Si tocas el grosor de la franja, toca también ése.
  • El recorrido llega vertical al margen izquierdo: es lo que evita el pico contra la franja. No lo hagas terminar en diagonal.
  • --fila descuenta --bajada por su nombre. No vuelvas a meterla en una constante fija: la bajada mide en proporción al ancho, no en vh.

El brote de REDES

Al pulsar REDES salen tres hojas pequeñas, una por red. Cuelgan de un tallo de verdad, no flotan: cada <li> del brote lleva un ::before que es su trozo de tallo, y los tres se encadenan —el primero va hasta el agarre en la enredadera, el segundo hasta el primero y el tercero hasta el segundo—, así que lo que se dibuja es un solo brote con tres hojas, no tres hojas sueltas.

Dos cifras por hoja bastan, y son las mismas que la colocan leídas del revés:

.brotes > li:nth-child(2){ --largo:0.605; --ang:262.4deg; }
  • --largo va en unidades de --r y --ang es absoluto, porque el <li> no gira (gira la hoja que lleva dentro).
  • Por eso lo que se coloca es la punta del rabillo —translate(-50%,0), no (-50%,-50%)—: si se colocara el centro de la hoja, el punto donde empieza el tallo dependería de lo que mida la hoja, que va en vw, y el ángulo no podría ser una constante.
  • Si mueves un nudo, recalcula las dos: --largo es la distancia al nudo anterior y --ang = atan2(dx, -dy).

En ordenador el brote sale hacia abajo y a la izquierda, al hueco que dejan Eventos y Campañas. En móvil no cabe un abanico: el tallo es vertical y las hojas ocupan los ~130px del centro, así que lo único libre son las franjas de los lados —62px a 390, 86 a 360, 110 a 320—. Ahí el brote sale por la izquierda, pasa por debajo de la hoja de REDES y trepa por el margen. Antes salía a la derecha y se comía Eventos y Campañas.


El banco de pruebas

cd ..
python3 coherencia.py            # raíz y hojas cuadran
python3 qa.py --breve            # las 10 páginas en 15 pantallas
python3 qa.py index.html         # una sola, con detalle

Puntuación 0 = perfecto. Mide, en cada página y cada tamaño de pantalla:

  • desborde horizontal
  • si la portada entra sin deslizar en ordenador
  • hojas cortadas por los bordes
  • hojas que se pisan entre sí
  • etiquetas que se solapan
  • los brotes de REDES: que no se salgan, no pisen a las hojas, no se toquen entre ellos y no partan su etiqueta en dos líneas
  • contraste de todos los textos contra su fondo real, con el umbral de WCAG AA (4.5, o 3.0 si la letra es grande). Ojo: las fuentes usan clamp() con vw, así que un titular puede ser «grande» en ordenador y dejar de serlo en móvil — por eso se mide en las quince pantallas y no en una
  • contenido perdido dentro de elementos con overflow oculto
  • foco fantasma: enlaces que se tabulan pero no se ven
  • espacio muerto en los bordes
  • el menú desplegado: que se alcancen todos los enlaces

El banco va por CDP, y no es un capricho

chromium --dump-dom y --screenshot sujetan la ventana a un mínimo de ~500px: si pides 320, maqueta a 500. La captura encima engaña, porque reescala la imagen al ancho pedido y parece buena. Da igual --headless, --headless=new o --headless=old.

Durante un tiempo el banco midió así, y las cuatro pantallas de móvil (430, 390, 360 y 320) daban todas la medida de 500: el 28% de cada barrido era falso. Por eso cdp.py levanta chromium con --remote-debugging-port y fija el viewport con Emulation.setDeviceMetricsOverride, que sí respeta cualquier ancho. Hace falta --remote-allow-origins=* o el websocket devuelve 403.

No vuelvas a medir con --dump-dom. Si un día das con números idénticos en varios anchos distintos, eso es la señal: el ancho no está cambiando.

Al medir cosas que se animan (los brotes, el menú) hay que quitar la transición antes, o se mide a medio camino. Y --r y las demás variables con calc() no se pueden leer con getPropertyValue: devuelven el texto. Se miden creando un testigo con width:var(--r).

Recorrer el foco

python3 teclado.py      # se usa desde otro script: ver el ejemplo al final

Pulsa Tab de verdad por CDP y anota cada parada. Mover activeElement con .focus() no vale: no prueba el orden de tabulación ni lo que el navegador se salta. Va aparte del banco porque cada parada es una ida y vuelta al navegador y en las 98 mediciones sería eterno.

Cuidado: la sonda se recorta

SONDA_JS no es el texto entero de la sonda: se recorta desde la línea var d=document.documentElement hasta donde escribía su resultado. Todo lo que se ponga fuera de ese trozo desaparece sin avisar. Pasó con el apagado de animaciones: estuvo seis vueltas escrito y sin aplicarse. Al tocar la sonda, comprobar que lo nuevo está de verdad:

python3 -c "import qa; print('sinAnim' in qa.SONDA_JS)"

La sonda apaga las animaciones

Lo primero que hace es meter *{animation:none!important}. La portada tiene una entrada animada que acaba a los 0.8s y la sonda mide a los 1.1s: medir tan cerca del final es pedir problemas. Como la animación termina en el estado normal, apagarla deja justo lo que hay que medir.

Cuidado al medir cosas que se abren

La barra lateral cierra con transition: visibility 0s .32s. Si un bloque de la sonda la abre y la cierra, todo lo que se mida después la ve todavía abierta. Ha mordido tres veces: al foco, a los brotes y al contraste. Por eso el bloque del menú y el de los brotes quitan la transición mientras miden y la reponen al salir. Si añades una comprobación nueva, no la pongas detrás de una que abra algo sin ese cuidado.

Lo que el banco no ve, y hay que mirar a ojo:

  • Las fichas de colectivo y los dos calendarios.

  • Los avisos de reserva. El .gancio-fallback de eventos.html y el <noscript> de calendario.html sólo se dibujan cuando el componente externo no carga o no hay JavaScript. Cuando el banco mide, no están, así que sus colores y tamaños no se comprueban solos. Ahí se coló un contraste de 3.4:1. Para revisarlos hay que bloquear el script a mano:

    nav._envia("Network.enable")
    nav._envia("Network.setBlockedURLs", {"urls": ["*rosa.frama.io*"]})
    

Qué NO tocar

El IIFE del calendario semanal (calendario.html, dentro de <script>). Lleva los horarios escritos a mano en WEEKLY y COLORS, y reglas especiales —todos los viernes Hacklab salvo el segundo que es Art-Lab; Fridays el segundo y el último viernes—. Para cambiar un horario se editan esos arrays, no el resto del código.

Y hay un contrato entre ese script y el CSS: el script escribe style="--bg:...; --fg:..." en cada píldora de color, y .cal-pill del CSS las lee con color-mix(). Esas dos variables no se declaran en ninguna parte del CSS —sólo se usan—, así que parecen sobrar y no sobran. Si se quitan las reglas que las usan, las píldoras se quedan sin color.

El web component de gancio (eventos.html). Se carga desde rosa.frama.io y trae la agenda de mad.convoca.la. El identificador del lugar es places="42", comprobado contra la API.

No se puede recolorear. Durante un tiempo el CSS le pasaba once variables --calendar-* y aquí ponía que se tematizaba con ellas. Es falso: el componente las redefine dentro de su propio shadow DOM —una tanda para .light y otra para .dark— y esa definición gana a la que herede del host. Comprobado: se le pasaba --calendar-surface:#f5faef y su .calendar seguía calculando #ffffff. Tampoco expone ningún ::part. Las once variables se quitaron: no hacían nada.

Lo único que se puede hacer es enmarcarlo desde fuera (borde, radio, sombra, fondo), que es lo que hay en la regla gancio-calendar, para que la tarjeta blanca se lea como un panel puesto a propósito.


Cosas pendientes de la asamblea

  • Orden de los colectivos. Los cinco con la ficha sin escribir (brota) van seguidos al final, así que la segunda fila entera sale desvaída. Repartidos entre las dos filas se leería como "esta hoja está brotando" y no como "la mitad de abajo está apagada". El orden lo decide la asamblea.

  • Hacklab: el párrafo de su ficha lo escribí yo de forma provisional porque la sección original no tenía ni una línea de texto. Conviene que lo revise la gente del hacklab y lo ponga en sus palabras.

  • Bicilab: el texto dice «domingos a las 17:00» y el calendario lo pinta a las 19:00. Hay que decidir cuál es la hora buena.

  • «Asamblea ext.» aparece en el calendario semanal pero no tiene color asignado en COLORS, así que su píldora sale en blanco y no figura en la leyenda. Las otras once etiquetas sí. O se le pone color, o se decide que va neutra a propósito y entonces conviene explicarlo en la leyenda.

  • En el calendario la etiqueta pone «Fridays 🌱» y en la leyenda «Fridays for Future». El color sí casa, pero los dos nombres deberían ser el mismo para que la leyenda se entienda.

  • Ficha de Feminismos: pone «el derecho a la libre intervención del embarazo». La expresión habitual es «interrupción», y aquí el cambio de palabra cambia el sentido. No lo he tocado porque el texto es suyo, pero conviene que lo miren.

  • Ficha de Bicilab: «Bocata de espaguetis todos los domingos a las 17:00 nos engrasamos las manos y recuperamos tu bicicleta!» son dos frases pegadas sin puntuación, y a la exclamación le falta el «¡» de apertura. Tampoco lo he tocado: es su voz.

  • Dos botones apuntaban a PDF que no existen (/archivos/biblioteca.pdf y /archivos/asamblea.pdf). Los quité y dejé el comentario en el HTML: cuando subáis los ficheros, se reponen.

  • Las campañas tenían seis botones que no llevaban a ninguna parte. Quitados, con nota en el HTML de lo que prometía cada uno.


La página de error

404.html existe, pero el servidor tiene que saber usarla. Con nginx:

error_page 404 /404.html;

Sin esa línea, un enlace roto enseña el error por defecto del servidor y la página no se usa nunca.


Al compartir el enlace

Todas las páginas llevan og:title, og:description y og:image para que Mastodon, Telegram o WhatsApp enseñen una vista previa decente. La imagen es INFO/cso_laenre.jpeg, la foto de la fachada con el cartel pintado a mano.

Una pega conocida: la og:image va en ruta relativa, porque el dominio propio del sitio no aparece escrito en ningún fichero —todos los enlaces internos son relativos y las únicas URLs absolutas son de subdominios (hacklab.laenre.net, okupanel.laenre.net)—. La mayoría de plataformas la resuelven, pero lo seguro es ponerla absoluta. Cuando confirméis el dominio, cambiad las ocho líneas og:image por la URL completa.


Accesibilidad

Se ha cuidado y medido:

  • Contrastes AA en todos los textos.
  • Anillo de foco visible sobre cualquier fondo (en rosa era invisible sobre las propias hojas).
  • Nada oculto se puede tabular.
  • Áreas de toque medidas en las ocho páginas: todo lo pulsable llega a los 24px que pide WCAG 2.5.8, y casi todo a 44. Lo que queda por debajo son enlaces dentro de una frase, exentos por la norma. Ojo con la píldora del calendario en móvil: se ve de 10px pero mide 24, gracias a un relleno vertical con background-clip:content-box. Necesita box-sizing:content-box, o el border-box global se come la altura y la barra desaparece.
  • :active en todo lo pulsable: en un móvil no hay :hover y sin él el toque no responde. .tarjeta queda fuera a propósito: es un div que no lleva a ninguna parte.
  • color-scheme declarado: light en el sitio, dark en el Tattoo Circus. Sin eso, un navegador en tema oscuro pinta en oscuro lo que el CSS no controla (barras de desplazamiento, controles, el lienzo inicial).
  • Las imágenes de contenido llevan texto alternativo que describe la imagen, no que repite el nombre del colectivo. Si un enlace es sólo una imagen, el nombre del enlace va en un aria-label que dice a dónde va: el alt describe el dibujo, y para un enlace eso no sirve.
  • El logo de la barra lateral va con alt="", decorativo a propósito: justo debajo hay un <h2> que ya dice «La Enredadera», y con alt puesto, cuando la imagen no cargaba, el texto se dibujaba recortado dentro de la caja de 48px.
  • Se respeta prefers-reduced-motion, y también el retardo: la entrada de la enredadera va escalonada, y anular sólo la duración dejaba las hojas invisibles hasta 0.3s para luego aparecer de golpe.

Límite conocido: al ser CSS puro, las fichas no se cierran con Escape y el contenido de detrás sigue siendo tabulable. Se cierran con la ✕, pulsando fuera o con el botón atrás del navegador. Arreglarlo exigiría JavaScript.