/* ============================================================================
   Gunitados CMG · sistema «ensayo»

   CONTRATO DE DIRECCIÓN
   THESIS: el gunitado es un trabajo que se mide, y esta web enseña la medición
     en vez de prometer calidad. Rechaza el escaparate de constructora con foto
     velada y también el plano técnico minimalista, que es su opuesto obvio.
   OWN-WORLD: el cuadro de mandos de la máquina. Rojo Arnabat, manómetro de
     presión de trabajo, contador de horas, etiquetas serigrafiadas, amarillo
     de aviso. Reconocible sin una palabra.
   STORY: quien entra ve obra de verdad a tamaño grande, entiende en un
     vistazo qué hace esta gente, y llama.
   FIRST VIEWPORT: foto de obra a sangre sin velo, titular condensado abajo a
     la izquierda, acción visible.
   FORM: dirección 5 (ensayo), seed 81c98673, con la corrección del informe de
     referencias: la personalidad la lleva la fotografía, no el movimiento.
   ========================================================================== */

/* ── Fuentes autoalojadas. Ninguna petición a terceros. ─────────────────── */
@font-face{
  font-family:'Big Shoulders';font-style:normal;font-weight:400 900;
  font-display:swap;src:url('fuentes/big-shoulders-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Inter';font-style:normal;font-weight:400 700;
  font-display:swap;src:url('fuentes/inter-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Inter';font-style:normal;font-weight:400 700;
  font-display:swap;src:url('fuentes/inter-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}

:root{
  /* Materia, tomada del propio cuadro de mandos de la máquina */
  --grafito:#141715;
  --grafito-2:#1D211E;
  /* `--grafito-3:#282D29` se retira por el mismo motivo que `--agua`: ninguna
     regla lo usaba, y el único sitio donde ese valor está de verdad es
     `img/esquema-via-humeda.svg`, escrito a mano. Comprobado buscándolo en todo
     `web/` y `fuente/` antes de quitarlo. */
  --hormigon:#9EA29A;
  --cal:#EAE8E1;
  --papel:#EDEAE1;
  --papel-2:#DFDCD2;

  /* EL ACENTO ES EL ROJO ARNABAT DESDE EL 13-08-2026, Y NO ES UN CAMBIO DE
     GUSTO: ESTÁ MEDIDO.
     ------------------------------------------------------------------------
     El ámbar de interfaz que había aquí, `#E2B33C`, está a distancia
     perceptual CIEDE2000 **5,8** del amarillo de las tablas de encofrado que
     salen en las fotos de obra. Por debajo de 11 dos colores son la misma
     familia y se confunden. Y ese amarillo ocupa **152.905 px** de la portada
     contra **23.881** del acento: hay seis veces más de ese color puesto por
     el material que puesto por la interfaz.

     Un acento es el color que aparece poco para que se note cuando aparece.
     Ese no se notaba, y no se arregla usando menos ámbar. Oscurecerlo tampoco:
     para separarlo de las fotos hay que llegar a `#7A5A0F`, que ya es marrón.
     No existe un ámbar que siga siendo ámbar y se distinga del encofrado.

     El rojo de la máquina está a CIEDE2000 **39,5** de ese amarillo, no lo
     tiene ninguna foto, y sale de la propia Arnabat, que es roja en el 46,8 %
     de su superficie. Las mediciones, en
     `.trabajo/2026-08-13-pulido/identidad.md`.

     TRES VALORES Y NI UNO MÁS. Cada uno existe porque una medición de
     contraste obliga a él, y ninguno puede hacer el trabajo de otro:

       --accion        relleno de la acción principal y marca de interacción.
                       Con cal encima da 4,57:1. Con grafito encima daría
                       3,22:1, y por eso el texto del botón pasa a ser cal.
       --accion-2      el mismo rojo un escalón por debajo. Hace las dos cosas
                       que el de arriba no puede: marcar que la pieza está
                       siendo tocada (5,78:1 con cal encima, y CIEDE2000 5,9
                       respecto al reposo, o sea que el cambio se ve) y leerse
                       como texto sobre papel (5,89:1, donde el de reposo da
                       4,66 y pasa raspando).
       --accion-claro  el rojo que aguanta como texto y como marca sobre
                       grafito: 5,24:1. El de reposo ahí da 3,22:1 y no llega.

     Los tres los mide `docs/color.mjs`, que además comprueba su distancia
     CIEDE2000 al amarillo de las fotos para que este fallo no pueda volver. */
  --accion:#C0341C;
  --accion-2:#A62A14;
  --accion-claro:#E0644B;

  /* EL ÁMBAR SE QUEDA, PERO SOLO PARA LO QUE SU NOMBRE DICE: AVISAR.
     Hoy eso es exactamente un uso, el hueco de un dato legal que todavía falta
     (`.pendiente`), y vive en páginas sin una sola foto. Que un aviso sea
     ámbar y una acción sea roja es la distinción que el sistema no tenía
     mientras el ámbar hacía las dos cosas a la vez. */
  --aviso:#E2B33C;
  --aviso-txt:#7A5A0F;

  /* `--maquina:#C0341C` se retira: era el mismo valor que `--accion`, o sea el
     mismo dato escrito dos veces, que es como se desincronizan las paletas.
     Lo que decía su nombre lo dice ahora el comentario de arriba.

     `--agua:#2E6E82` también se retira, y por el motivo contrario: no lo usaba
     nadie. Se declaró para no dejar el valor suelto dentro de dos SVG, y los
     dos SVG lo siguieron llevando escrito a mano. Un archivo SVG externo no ve
     las variables de esta hoja, así que el sitio donde ese azul se decide son
     `img/esquema-via-humeda.svg` e `img/seccion-talud.svg`, y aquí sobraba. */

  /* Tinta */
  --tinta:#141715;
  --tinta-2:#4E534E;
  --tinta-3:#5A605A;

  --linea:#83837F;      /* funcional: 3:1 contra papel y contra hoja */
  --filete:#D5D2C8;
  --filete-osc:rgba(234,232,225,.14);
  --filete-osc-2:rgba(234,232,225,.28);

  /* Siete pasos y ni uno más */
  --t-xs:.75rem;
  --t-sm:.875rem;
  --t-base:1.0625rem;
  --t-md:1.1875rem;
  --t-lg:clamp(1.3rem,2.2vw,1.55rem);
  --t-xl:clamp(1.9rem,4.6vw,3rem);
  /* 42,4 px a 360 de ancho y 64 px FIJOS a partir de 1.100. El titular deja de
     crecer con la ventana: lo fija una decisión, no el viewport.

     Estaba en clamp(3rem,8vw,6.2rem), que a 1440 daba 99,2 px medidos, y a
     1024 daba exactamente los 82 px que el CLAUDE.md prohíbe por escrito. La
     decisión aprobada era 42, y el `8vw` se la había comido sin que nadie lo
     notara: un valor fluido sin tope real revierte solo cualquier decisión de
     tamaño la primera vez que alguien mira en una pantalla grande.

     Un titular que grita es el tic de IA más reconocible que hay. Aquí el
     contraste lo dan el peso y el color. */
  --t-2xl:clamp(2.65rem,2.4rem + 3.2vw,4rem);

  /* Escala de espaciado. Los dos últimos pasos se recortaron a propósito para
     que la home no pida más scroll del necesario: de 4 y 6,5 rem a 3 y 4,5. */
  --e-1:.5rem;  --e-2:1rem;   --e-3:1.5rem;
  --e-4:2.25rem; --e-5:3rem;  --e-6:4.5rem; --e-7:7rem;

  --r:2px;
  --sombra:0 1px 2px rgba(20,23,21,.06),0 12px 32px -22px rgba(20,23,21,.3);

  /* La segunda sombra del sistema, y la unica que se añade desde que se fijo
     que habria una sola. Mario aprobo el 13-08-2026 rehacer el material de los
     botones porque «se ven muy toscos», y toscos era literal: eran manchas de
     color planas con una esquina mordida por un chaflan.

     No es una sombra decorativa, es el canto de una tecla, y por eso son cuatro
     capas y no una: filete de luz en el borde de arriba, canto oscuro en el de
     abajo, una linea de contacto que apoya la pieza en el papel, y una sombra
     corta y baja que le da el grosor. Al pulsar se retira todo menos el rastro
     interior, y la pieza baja 2 px. Eso es lo que hace un boton fisico y es lo
     que faltaba.

     Cuenta como token y no como valor suelto para que siga habiendo control:
     el dia que alguien quiera una tercera sombra tiene que escribirla aqui,
     donde se ve que ya hay dos. */
  --tecla:inset 0 1px 0 rgba(255,255,255,.42),
          inset 0 -2px 0 rgba(20,23,21,.22),
          0 1px 0 rgba(20,23,21,.18),
          0 2px 6px -2px rgba(20,23,21,.28);
  --tecla-hundida:inset 0 1px 0 rgba(255,255,255,.2),
                  inset 0 -1px 0 rgba(20,23,21,.22);

  --ease-out:cubic-bezier(0.23,1,0.32,1);
  --ease-in-out:cubic-bezier(0.77,0,0.175,1);

  --ancho:1240px;
  /* LA VOZ DE ETIQUETA DE MÁQUINA, AHORA ELEGIDA
     Esta variable la usan los rótulos, las claves de la placa de
     características, los números de los índices y las migas: es el elemento
     tipográfico más repetido del sitio después del cuerpo. Y era el stack
     monoespaciado del sistema operativo, con lo que se veía distinta en cada
     máquina y nadie había decidido cómo.

     Pasa a ser Big Shoulders, que el sitio ya carga y ya precarga: cuesta
     **cero bytes de más**. Con el espaciado abierto y el peso medio hace de
     etiqueta serigrafiada, que es exactamente lo que representa. Se conserva
     el respaldo monoespaciado por si la fuente no llegara. */
  --mono:'Big Shoulders',ui-monospace,'SF Mono',SFMono-Regular,'Cascadia Mono',monospace;
  --foco:#141715;
}

/* ── Base ───────────────────────────────────────────────────────────────── */
*,*::before,*::after{box-sizing:border-box}
*{margin:0;padding:0}
html{
  /* Las dos reservas son para el foco, no para los anclajes.
     `scroll-padding-top` ya existia y esta comprobado que funciona: con la
     cabecera pegajosa de 4,25rem encima, el recorrido con tabulador de las 17
     paginas no dejo NI UN elemento tapado por ella.

     La de abajo es nueva y vale medio rem. Medido a 1440x900 el 13-08-2026:
     al llevar el foco a un enlace del final de una seccion, el navegador lo
     deja pegado al borde inferior de la ventana (y=864, alto 34, o sea abajo
     en 898 de 900) y los 4 px de anillo que van por fuera de la caja caen
     fuera de la pantalla. Pasaba en 12 de las 17 paginas. Reservando 8 px, el
     anillo entra entero. `medicion.mjs` sobrescribe este valor mientras el
     aviso de cookies esta puesto, con el alto real del aviso. */
  scroll-behavior:smooth;scroll-padding-top:5rem;scroll-padding-bottom:.5rem;
  -webkit-text-size-adjust:100%;
  /* clip y NUNCA hidden: hidden cambia el contenedor de scroll y rompe
     animation-timeline sin dar ningún error. */
  overflow-x:clip;
}
body{
  font-family:'Inter',system-ui,-apple-system,sans-serif;
  font-size:var(--t-base);line-height:1.65;
  color:var(--tinta);background:var(--papel);
  overflow-x:clip;-webkit-font-smoothing:antialiased;
}
img,svg,video{max-width:100%;height:auto;display:block}
picture{display:contents}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
/* La selección de texto también es acento: es el usuario marcando dónde está
   actuando. Cal encima y no grafito, que sobre este rojo da 3,22:1. */
::selection{background:var(--accion);color:var(--cal)}
:focus-visible{outline:2px solid var(--foco);outline-offset:2px}
.seccion-osc,.pie,.hero{--foco:var(--cal)}

.saltar{
  position:absolute;left:1rem;top:0;transform:translateY(-120%);z-index:200;
  background:var(--tinta);color:var(--papel);padding:.75rem 1.25rem;
  font-weight:600;font-size:var(--t-sm);transition:transform .25s var(--ease-out);
}
.saltar:focus{transform:translateY(0)}

/* ── Tipografía ─────────────────────────────────────────────────────────── */
h1,h2,h3,h4,.display{
  font-family:'Big Shoulders','Arial Narrow',system-ui,sans-serif;
  font-weight:800;line-height:.92;letter-spacing:0;
  text-transform:uppercase;text-wrap:balance;
}
h1{font-size:var(--t-2xl)}
h2{font-size:var(--t-xl)}
h3{font-size:var(--t-lg);font-weight:700}
h4{font-family:'Inter',sans-serif;font-size:var(--t-md);font-weight:650;
   text-transform:none;letter-spacing:-.015em;line-height:1.3}
/* Medida máxima por defecto, y no solo donde alguien se acuerde de ponerla.
   ------------------------------------------------------------------------
   `.medida` existía desde el principio, pero es opcional: hay que recordar
   añadirla. Medido a 1440 el 08-08-2026, dos párrafos se habían quedado sin
   ella y salían a 111 y 84 caracteres por línea, con el techo de la pauta en
   75. No es un descuido de quien los escribió: es que el valor por defecto era
   «todo el ancho que haya».

   Ahora el valor por defecto es una medida legible y `.medida` sigue estando
   para cuando se quiere más estrecha. Las tablas, las rejillas y los pies de
   figura no se ven afectados porque no son párrafos sueltos. */
p{text-wrap:pretty;max-width:72ch}
.medida{max-width:62ch}
/* Los que sí deben ocupar su caja entera: dentro de una celda, un pie de
   figura o un aviso, la medida la pone el contenedor y no el párrafo. */
td p,th p,figcaption p,.ck-texto p,.exp-panel p{max-width:none}

/* Las celdas de tabla NO se limitan, y es una decisión.
   La línea más larga que queda en todo el sitio son 82 caracteres, en una
   celda de la tabla técnica de refuerzo estructural. Limitarla obligaría a la
   columna a estrecharse, la tabla crecería a lo alto y las filas dejarían de
   compararse de un vistazo, que es para lo que existe una tabla. Una celda no
   se lee como un párrafo: se lee en horizontal y contra la fila de al lado. */
strong,b{font-weight:600}
.dato{font-family:var(--mono);font-variant-numeric:tabular-nums;letter-spacing:-.02em}

/* EL RÓTULO DE SECCIÓN SE RETIRA, y esto merece explicación porque estaba en
   todas las secciones desde la v1.

   Era un texto corto en mayúsculas, con tracking abierto y una rayita delante,
   colocado encima de cada h2. Ese objeto tiene nombre propio en el catálogo de
   tics de interfaz generada: el *tracked uppercase eyebrow*. Uno solo es un
   sistema; en todas las secciones es una gramática que nadie eligió, y lo que
   comunica de verdad es «aquí empieza una sección», que ya lo dice el titular.

   Se quitan seis de la home y tres de cada página de obra. Dos cosas se ganan a
   la vez: desaparece el tic, y la página deja de tener un elemento de más antes
   de cada bloque, que es parte de por qué se leía cargada.

   La clase NO se borra: la siguen usando las migas de la apertura, que no son
   un eyebrow decorativo sino la ruta de navegación, y el pie de la ficha del
   hero.

   Y LA RAYITA SÍ SE BORRA, 13-08-2026. Se quedó con el argumento de que en una
   miga «hace de guion de ruta», que es una justificación de la función y no
   del aspecto. Medido en el navegador: un filete de 22x2 px, a 11,2 px de un
   texto en versalitas rastreadas de palo estrecho, y el elemento que va justo
   detrás es el H1. En 15 de las 17 páginas, siempre en la primera pantalla.
   Están los cinco atributos que definen el *tracked uppercase eyebrow* del
   catálogo de tics de interfaz generada, y el ojo no lee el `aria`: lee la
   forma. Es la queja literal de Mario, «esas líneas antes de un encabezado, el
   sobreencabezado ese con la línea, son super de IA».

   La ruta se lee igual sin ella: `INICIO / PISCINAS` ya lleva su barra. Lo que
   se va es la raya, no la miga. */
.rotulo{
  font-family:var(--mono);font-size:var(--t-xs);letter-spacing:.16em;
  text-transform:uppercase;color:var(--tinta-3);margin-bottom:var(--e-2);
  display:flex;align-items:center;gap:.7rem;
}
.seccion-osc .rotulo,.hero .rotulo{color:var(--hormigon)}
.entradilla{font-size:var(--t-md);color:var(--tinta-2);line-height:1.6}
.seccion-osc .entradilla{color:var(--hormigon)}
.sep-t{margin-top:var(--e-2)}
.sep-t-g{margin-top:var(--e-3)}

/* ── Rejilla ────────────────────────────────────────────────────────────── */
.envoltura{width:min(100% - 2.5rem,var(--ancho));margin-inline:auto}
/* TRES RITMOS, Y ASIMÉTRICOS
   ------------------------------------------------------------------------
   Medido sobre las 84 secciones del sitio: existían DOS paddings verticales,
   los dos simétricos, y el 84 % usaba 48 px donde el CLAUDE.md de la raíz pide
   96 como mínimo. Un solo ritmo repetido 84 veces es lo primero que delata una
   plantilla, y coinciden en ello las dos skills de criterio que se consultaron.

   Ahora hay tres pasos y son asimétricos: cada sección deja algo más de aire
   por abajo que por arriba, que es lo que hace que un bloque se lea como
   terminado y no como cortado.

   El paso `--e-7` es un octavo escalón de espaciado, y se declara aquí como lo
   que es: una excepción pedida a propósito. No toca la escala tipográfica, que
   sigue teniendo sus siete tamaños. */
.seccion{padding-block:var(--e-6) calc(var(--e-6) + 1rem)}
.seccion-ancla{padding-block:var(--e-7) calc(var(--e-7) + 1rem)}
.seccion-apretada{padding-block:var(--e-5) calc(var(--e-5) + .5rem)}
/* Aquí NO se usa content-visibility. Se probó y el alto estimado que reserva
   inflaba la página de 5.333 a 5.936 px sin que hubiera más contenido: la
   barra de scroll mentía sobre lo que quedaba por leer. En una página de seis
   pantallas el ahorro de pintado no compensa ese efecto. */
.seccion-osc{background:var(--grafito);color:var(--cal)}
.seccion-osc h1,.seccion-osc h2,.seccion-osc h3,.seccion-osc h4{color:var(--cal)}
.seccion-osc p{color:var(--hormigon)}
/* `.seccion-hoja` se queda SIN fondo propio, a propósito.
   ------------------------------------------------------------------------
   Alternaba papel y papel-2 en bandas ABAB a lo largo de toda la página. Es
   una de las formas más reconocibles de rellenar una web sin componerla: el
   fondo cambia porque toca, no porque cambie lo que se cuenta.

   Un solo papel en todo el sitio. Lo que separa una sección de la siguiente
   pasa a ser el aire y el filete de `.regla`, que ya existían y ya lo hacían.

   La clase no se borra del HTML: se vacía aquí. Así ninguna página se rompe y
   el día que haga falta un segundo papel para algo concreto, hay un sitio
   donde ponerlo con un motivo escrito al lado. */
.seccion-hoja{}
/* `.regla` SE VACÍA, 13-08-2026, y es el hermano mayor del caso del rótulo.
   ------------------------------------------------------------------------
   Era `border-top:1px solid var(--filete)`, medido a 1440 px de ancho (el
   viewport entero, no la envoltura de 1240) y contado en el navegador: **40
   filetes idénticos repartidos por 11 páginas**, y en las 11 el elemento que
   llevan dentro es un H2. Mismo grosor, mismo color y mismo ancho las 40
   veces. Un recurso de separación repetido cuarenta veces sin variar deja de
   componer y pasa a ser el ritmo de una plantilla.

   Lo que separa las secciones ya estaba puesto y no era el filete: son 72 px
   de aire por arriba y 88 por abajo (`--e-6` asimétrico), o 48 y 56 en las
   apretadas. El propio comentario de `.seccion-hoja`, tres líneas más arriba,
   ya lo daba por hecho al retirar las bandas de fondo alternas. Y el CLAUDE.md
   de la raíz es explícito: el espacio en blanco es una decisión, no lo que
   sobra.

   La clase no se borra del HTML, se vacía aquí, igual que `.seccion-hoja`: así
   ninguna página se rompe y queda un sitio donde volver a poner un separador
   con el motivo escrito al lado, si alguna vez hace falta. */
.regla{}

/* ── Botones ────────────────────────────────────────────────────────────── */
/* Un rectángulo con las cuatro esquinas iguales y el texto en minúsculas es un
   botón de formulario, no una pieza de esta web. Este lleva el CHAFLÁN de una
   placa de máquina: la esquina inferior derecha cortada a 45 grados, que es
   como viene troquelada cualquier chapa de un equipo de obra. Es la misma
   familia de la que sale la etiqueta serigrafiada de la regleta de datos.

   El chaflán lo hace `clip-path`, así que no añade ningún radio nuevo al
   sistema, que sigue teniendo uno solo. */
/* Sin versalitas. El texto del botón se lee, no se rotula: «Contar la obra» en
   mayúsculas ocupa más, se lee más despacio y es la forma en que se escriben
   los botones de casi cualquier plantilla. Las versalitas se quedan donde
   significan algo en este sistema: los rótulos de máquina y los titulares. */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:.55rem;
  padding:.95rem 1.7rem;border:1.5px solid transparent;
  font-weight:650;font-size:var(--t-sm);letter-spacing:.01em;
  position:relative;overflow:hidden;
  border-radius:var(--r);
}
/* EL CHAFLAN SE RETIRA, 13-08-2026.

   Existio para marcar la jerarquia por la forma: la accion principal era una
   placa troquelada y la secundaria un marco. La intencion era buena y el
   resultado no: recortar una sola esquina a 45 grados sobre una pieza plana no
   se lee como troquel, se lee como esquina mordida. Sobre grafito era peor,
   porque por el corte asomaba el fondo oscuro.

   Y tenia un coste que no se habia contado: `clip-path` recorta TODO lo que
   sale de la caja, sombras exteriores incluidas. Mientras estuvo puesto, el
   boton no podia tener cuerpo aunque se quisiera. Era la causa tecnica de que
   se viera plano, no una consecuencia estetica.

   La jerarquia sigue sin depender del color, que es lo que se le pedia: ahora
   la marca el material. La principal es una pieza con canto, relleno y
   grosor; la secundaria es un contorno sin cuerpo. Se distinguen de un vistazo
   y tambien en escala de grises. */
/* El hundimiento y el tirón magnético se declaran juntos en la sección de la
   boquilla, con `scale` y `translate` como propiedades independientes: si el
   tirón usara `transform` machacaría al hundimiento, y el botón dejaría de
   responder al pulsarlo justo cuando el cursor está encima. */

/* EL FILETE ROJO DEL HOVER SE RETIRA, 13-08-2026, Y ES CONSECUENCIA DIRECTA
   DEL CAMBIO DE ACENTO.
   ------------------------------------------------------------------------
   Aquí había un filete de 2 px del rojo de la máquina que se trazaba de
   izquierda a derecha por el borde inferior del botón al sobrevolarlo. Estaba
   bien argumentado mientras el relleno era ámbar: el rojo era entonces «la
   marca de que estás encima» y no significaba ninguna otra cosa en un botón.

   Desde hoy el relleno ES ese rojo, así que quedaban dos salidas y ninguna
   servía: dejarlo rojo es dibujar rojo sobre rojo, y cambiarlo de color es
   inventar un SEGUNDO gesto de interacción en un sistema que declara por
   escrito que tiene uno solo (la marca de 3 px que crece desde el centro, en
   el explorador, el índice y los canales).

   Así que desaparece, y el hover del botón principal pasa a marcarlo el
   material, que es lo que se le pedía a este botón desde el principio: el rojo
   baja un escalón a `--accion-2` y el canto de tecla se queda puesto. Medido:
   CIEDE2000 5,9 entre los dos rojos, o sea un cambio que se ve; y el texto
   cal encima mejora de 4,57:1 a 5,78:1 en vez de empeorar. */
.btn svg{width:1.05em;height:1.05em;flex:0 0 auto}

/* LA SEGUNDA MEDIDA DE BOTÓN, DECLARADA EN VEZ DE HEREDADA POR DESCUIDO.
   ------------------------------------------------------------------------
   Medido: `.btn-solido` daba 55,5 px de alto con letra de 14 px, y la misma
   clase en la cabecera daba 42,6 con letra de **12**. Un salto del 23 % en la
   caja y del 14 % en la letra entre dos instancias de la misma clase, y los
   12 px eran el escalón más pequeño de la escala usado justo en el botón de
   acción más visible del sitio, el que va en las 17 cabeceras.

   Que en una barra de 68 px de alto el botón sea más bajo no es un defecto: lo
   que era un defecto es que además encogiera la letra y que eso estuviera
   escrito dos veces en sitios distintos. Aquí hay UNA medida compacta, se
   declara una sola vez, y **la letra es la misma que la del botón grande**. Lo
   único que cambia es el relleno vertical. */
.cab-tel{font-size:var(--t-sm);padding:.5rem 1.05rem}

/* LA JERARQUÍA VIVE EN EL MATERIAL, Y EN LOS CUATRO ESTADOS.
   ------------------------------------------------------------------------
   Esto era el defecto más grave de los botones y lo introdujo la propia pasada
   que les puso material, hace unas horas: al sobrevolar, el principal se
   volvía `--cal` con texto grafito, y el secundario sobre oscuro TAMBIÉN. Los
   tres valores coincidían (fondo #EAE8E1, texto #141715, borde #EAE8E1) en dos
   botones que van pegados en el hero y en el cierre de las 17 páginas. La
   jerarquía no se perdía: se invertía, porque el secundario sobrevolado pesaba
   más que el principal en reposo.

   La regla que lo cierra es de una línea y vale para siempre:

     EL PRINCIPAL SIEMPRE TIENE CUERPO. EL SECUNDARIO NUNCA LO GANA.

   El principal es una pieza rellena con canto y grosor en los cuatro estados,
   y lo único que cambia es el escalón de rojo. El secundario es un contorno en
   los cuatro estados: al sobrevolarlo se le afila el borde y se le mete un
   lavado tenue, pero no se rellena. Así no hay ningún estado en que los dos
   puedan parecerse, y se distinguen también en escala de grises. */
.btn-solido{background:var(--accion);color:var(--cal);border-color:var(--accion);
  box-shadow:var(--tecla)}
.btn-solido:hover{background:var(--accion-2);border-color:var(--accion-2)}
/* Al pulsar se retira el canto y la pieza baja: el hundimiento lo pone la regla
   de `translate` de la seccion de la boquilla, aqui solo se apaga la sombra. */
.btn-solido:active{box-shadow:var(--tecla-hundida)}

.btn-linea{border-color:var(--linea);color:var(--tinta)}
.btn-linea:hover{background:var(--papel-2);border-color:var(--tinta)}
/* Sobre grafito el borde pasa de `--filete-osc-2` a `--hormigon`, y no es
   estética: cal al 28 % sobre grafito compone `#50524E`, que da **2,29:1**
   contra el fondo y no llega al 3:1 que pide WCAG 2.2 SC 1.4.11 para el borde
   de un control. Es decir, el contorno que sostiene toda la jerarquía del
   secundario estaba por debajo del mínimo. `--hormigon` da 6,95:1 y ya existía:
   no hace falta ningún color nuevo. */
.seccion-osc .btn-linea,.hero .btn-linea{border-color:var(--hormigon);color:var(--cal)}
/* El lavado sale del propio token con `color-mix`, así que no entra ni un hex
   nuevo al sistema. Cal al 12 % sobre grafito compone `#2E302D`, y el texto cal
   encima da 10,86:1. */
.seccion-osc .btn-linea:hover,.hero .btn-linea:hover{
  background:color-mix(in srgb,var(--cal) 12%,transparent);
  border-color:var(--cal);color:var(--cal)}

/* Subrayado permanente y no solo al pasar: un enlace dentro de un párrafo no
   puede distinguirse solo por el color (WCAG 1.4.1). Medido con axe: fallaba en
   la política de privacidad y en el aviso legal. */
.enlace{
  color:var(--accion-2);font-weight:600;
  text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px;
  transition:text-decoration-thickness .2s var(--ease-out),color .18s var(--ease-out);
}
.enlace:hover{text-decoration-thickness:2px}
/* Al pulsar, el enlace se vuelve tinta. Es el único pulsable del sistema que no
   puede hundirse 1 px: `translate` no se aplica a una caja en línea no
   reemplazada, así que en un enlace dentro de un párrafo no haría nada. El
   cambio de color sí ocurre, y además sube el contraste (de 5,89:1 a 15,01:1)
   en vez de bajarlo, que es lo que pasaría bajando la opacidad. */
.enlace:active{color:var(--tinta)}
.seccion-osc .enlace{color:var(--accion-claro)}
.seccion-osc .enlace:active{color:var(--cal)}

/* ── Cabecera ───────────────────────────────────────────────────────────── */
.cabecera{
  position:sticky;top:0;z-index:90;background:var(--papel);
  border-bottom:1px solid var(--filete);
}
.cabecera-int{
  width:min(100% - 2.5rem,var(--ancho));margin-inline:auto;height:4.25rem;
  display:flex;align-items:center;justify-content:space-between;gap:var(--e-3);
}
.marca{
  display:flex;align-items:baseline;gap:.5rem;
  font-family:'Big Shoulders';font-weight:800;font-size:1.45rem;
  text-transform:uppercase;line-height:1;
}
.marca span{
  font-family:var(--mono);font-size:var(--t-xs);font-weight:400;letter-spacing:.12em;
  text-transform:uppercase;color:var(--tinta-3);
}
.menu ul{display:flex;align-items:center;gap:var(--e-3);list-style:none}
.menu a:not(.btn){font-size:var(--t-sm);color:var(--tinta-2);
  transition:color .18s var(--ease-out),translate .16s var(--ease-out)}
.menu a:not(.btn):hover{color:var(--tinta)}
.menu a:not(.btn):active{translate:0 1px}
.menu a[aria-current="page"]:not(.btn){color:var(--tinta);font-weight:600}
/* Aquí había un `.menu .btn{font-size:var(--t-xs);padding:.65rem 1.05rem}` con
   los mismos valores que `.cab-tel`. Los dos se retiran y la medida compacta se
   declara una sola vez, en la sección de botones. Y el duplicado era peor de lo
   que parecía: `.menu` no contiene ningún `.btn` desde que el teléfono salió a
   la barra el 08-08-2026, así que esa regla y su gemela de móvil no aplicaban a
   nada. Dos reglas muertas manteniendo viva la contradicción de tamaños. */
.hamburguesa{
  display:none;width:2.6rem;height:2.6rem;border:1px solid var(--linea);
  border-radius:var(--r);align-items:center;justify-content:center;
  background:transparent;
  transition:background-color .18s var(--ease-out),border-color .18s var(--ease-out),
    translate .16s var(--ease-out);
}
/* El control de navegación del móvil no tenía NI hover NI pulsado: en un iPhone,
   que es el entorno de referencia declarado del proyecto, tocar el menú no
   producía ninguna respuesta hasta que el panel terminaba de abrirse. Ahora
   responde con lo mismo que responde todo lo demás: lavado de papel hundido,
   borde a tinta, y 1 px de hundimiento al tocarlo. */
.hamburguesa:hover{background:var(--papel-2);border-color:var(--tinta)}
.hamburguesa:active{background:var(--papel-2);border-color:var(--tinta);translate:0 1px}
.hamburguesa i{display:block;width:15px;height:1.5px;background:var(--tinta);position:relative}
.hamburguesa i::before,.hamburguesa i::after{
  content:"";position:absolute;left:0;width:15px;height:1.5px;background:var(--tinta);
  transition:transform .3s var(--ease-in-out);
}
.hamburguesa i::before{top:-5px}
.hamburguesa i::after{top:5px}
.hamburguesa[aria-expanded="true"] i{background:transparent}
.hamburguesa[aria-expanded="true"] i::before{transform:translateY(5px) rotate(45deg)}
.hamburguesa[aria-expanded="true"] i::after{transform:translateY(-5px) rotate(-45deg)}

/* ── HERO ────────────────────────────────────────────────────────────────
   La foto es la pieza, no el fondo. Nueve de las once webs del sector que se
   midieron para este encargo sostienen la página con obra real y sin velo
   encima; la que se rechazó por aburrida no tenía nada que mirar. */
/* EL ZÓCALO, Y POR QUÉ NO HAY VELO
   ------------------------------------------------------------------------
   Aquí había un degradado que llegaba al 94 % de opacidad y cubría el 72 % de
   la altura del hero. El comentario que tenía justo encima decía «la foto se
   ve», y el contrato de dirección de la cabecera de este archivo dice «foto de
   obra a sangre SIN velo». Tres documentos del proyecto contra lo que hacía el
   código, y ganaba el código.

   Además tenía un defecto que solo se ve al cambiar la foto: el contraste del
   titular dependía de que la foto fuera oscura por abajo a la izquierda.
   Funcionaba con la de la ferralla por casualidad. Con la de la máquina y el
   camión, que es clara, no habría funcionado.

   Ahora la foto ocupa la parte de arriba entera y sin tocar, y el texto va
   sobre una placa de grafito opaco con el filete ámbar de etiqueta de máquina.
   El contraste pasa a ser una constante medible en vez de una propiedad de
   cada imagen, y la foto se ve completa, que es más vistoso. */
.hero{
  position:relative;min-height:min(88dvh,780px);
  display:flex;flex-direction:column;justify-content:flex-end;
  background:var(--grafito);color:var(--cal);overflow:clip;
}
/* La foto ocupa el hueco que deja el zócalo, no todo el hero. Sin esto el
   zócalo se apoya sobre la foto y la tapa por abajo, en vez de ir debajo. */
.hero-foto{position:absolute;inset:0;z-index:0}
.hero-foto img{width:100%;height:100%;object-fit:cover;object-position:center 42%}
/* El zócalo va a sangre: el fondo llega a los dos bordes y es la `.envoltura`
   de dentro la que limita el texto. Cuando el fondo lo llevaba el mismo
   elemento que limitaba el ancho, la placa quedaba flotando en el centro con
   la foto asomando por los lados, que es justo lo que no se buscaba. */
/* EN APILADO NO HAY FILETE, 13-08-2026. Aquí había `border-top:2px solid
   var(--aviso)`: una raya de ancho completo justo encima del H1, que es
   literalmente el objeto del que se queja Mario. En escritorio se retiró al
   pasar el hero a dos mitades, porque ahí el filete se convirtió en la junta
   vertical entre foto y texto; por debajo de 1000 px seguía siendo horizontal y
   seguía estando encima del titular. O sea que estaba arreglado justo donde no
   se juzga este sitio, que es el móvil. */
.hero-txt{
  position:relative;z-index:2;width:100%;
  background:var(--grafito);
  padding:var(--e-4) 0;
}
.hero h1{max-width:14ch;margin-block:var(--e-2) var(--e-3)}
.hero h1 em{font-style:normal}
.hero .entradilla{max-width:46ch;color:#C6C9C2}
.hero-acciones{display:flex;gap:.7rem;flex-wrap:wrap;margin-top:var(--e-3)}

/* Ficha de obra sobre la foto, arriba a la derecha: dice qué se está viendo */
.hero-ficha{
  position:absolute;top:var(--e-3);right:5vw;z-index:2;
  background:color-mix(in srgb,var(--grafito) 72%,transparent);backdrop-filter:blur(8px);
  -webkit-backdrop-filter:blur(8px);
  border:1px solid var(--filete-osc);border-radius:var(--r);
  padding:.7rem .9rem;font-family:var(--mono);font-size:var(--t-xs);
  letter-spacing:.1em;text-transform:uppercase;color:var(--hormigon);
  max-width:min(58vw,290px);
}
.hero-ficha b{color:var(--cal);font-weight:500;display:block;margin-top:.2rem}

/* ── HERO A DOS MITADES EN ESCRITORIO, 13-08-2026 ────────────────────────
   Hasta hoy el hero eran dos bandas apiladas: la foto de lado a lado arriba y
   el zocalo de grafito de lado a lado debajo. Se leia como dos rectangulos sin
   relacion, y tenia un coste medido: a 1440 el titular empezaba en y=470, o sea
   que el 52 % de la primera pantalla no contenia ni una palabra del mensaje. En
   movil, 410 de 844. Media pantalla de foto antes de saber de que va esto.

   Ahora el texto ocupa la mitad izquierda y la foto la derecha, a sangre y de
   altura completa. El titular pasa a y=270 y la foto se ve mejor por ser mas
   alta. El filete deja de ser una raya horizontal decorativa y pasa a ser
   el canto que separa las dos mitades, que es donde de verdad significa algo.

   EL TEXTO NO LLEVA PADDING CALCULADO, y esa es la decision importante. La
   tentacion era hacer el hero un grid y meterle
   `padding-left:calc((100vw - var(--ancho))/2)`, pero `100vw` incluye la barra
   de scroll y el resto de la pagina se alinea con `.envoltura`, que no la
   incluye: el hero habria quedado desalineado unos 7 px con TODAS las secciones
   de debajo, en Windows y solo a veces. Aqui la `.envoltura` conserva su
   centrado de siempre y lo que se recorta es el FONDO, con un pseudo-elemento.
   La alineacion sale exacta sin calcular nada.

   Debajo de 1000 px no cambia nada: en movil las dos mitades no caben y la
   composicion apilada es la correcta. */
@media (min-width:1000px){
  /* La junta entre las dos mitades es UN solo numero, y por eso es una
     variable. Escrita dos veces se descuadro a la primera: la foto arrancaba en
     el 46 % y el fondo de texto acababa en el 54 %, porque en `inset` el segundo
     valor es la distancia DESDE la derecha y no el ancho. El grafito tapaba
     115 px de foto y el filete caia encima de la imagen en vez de en la junta.
     Con una variable las dos mitades no pueden dejar de casar.

     El filete es `--hormigon` y no el acento, y eso NO es un descuido. Nacio
     ambar, cuando el ambar era el acento del sitio. Al pasar el acento a rojo
     el 13-08-2026 se llevo al gris a proposito: una junta entre dos
     superficies es estructura, no accion, y el acento de este sistema marca lo
     segundo. `--hormigon` se eligio porque cumple 3:1 contra las dos cosas que
     separa, el grafito y una foto que puede ser de cualquier color. */
  .hero{display:block;min-height:min(86dvh,760px);--junta:46%}
  .hero-foto{inset:0 0 0 var(--junta)}
  .hero-foto img{object-position:center 45%}
  .hero-txt{position:absolute;inset:0;z-index:2;
    background:none;border-top:0;padding:0;
    display:flex;align-items:center}
  /* La junta es HORMIGÓN y no el acento. Es el canto donde se tocan dos
     materiales, no una acción, y un filete de 2 px por 760 de alto con el color
     de la acción es color marcando importancia, que es justo lo que el
     CLAUDE.md de la raíz prohíbe. Contra el grafito da 6,95:1, así que se ve
     como lo que es: un borde mecanizado. */
  .hero-txt::before{content:"";position:absolute;
    inset:0 calc(100% - var(--junta)) 0 0;
    background:var(--grafito);border-right:2px solid var(--hormigon)}
  .hero-txt .envoltura{position:relative}

  /* NINGUNA PIEZA DE TEXTO CRUZA LA JUNTA, y esto hubo que medirlo para verlo.
     La `.envoltura` sigue centrada respecto a la pagina entera, asi que su
     borde derecho cae muy por dentro de la foto: son las medidas en `ch` las
     que estaban conteniendo el texto, y en cuanto la letra crecia dejaban de
     bastar. Medido a 1000 px, la entradilla se pasaba 15 px por encima de la
     imagen, y el contenedor de los botones se extendia entre 520 y 722 px
     sobre la foto, invisible pero comiendose el area de hover.

     El tope es el 43 % de la envoltura y no un `ch` mas: hecha la cuenta, el
     ancho util real (junta menos margen de pagina) es entre el 45,3 % y el
     45,8 % de la envoltura en todo el rango de 1000 a 2560 px, o sea
     practicamente constante. Con 43 % queda holgura en los dos extremos y no
     hace falta ningun punto de ruptura mas. `min()` deja que sigan mandando las
     medidas en `ch` cuando son las mas cortas, que es a partir de 1100. */
  .hero h1{max-width:min(11ch,43%)}
  .hero .entradilla{max-width:min(38ch,43%)}
  .hero-acciones{max-width:43%}
  /* La ficha de obra baja a la esquina inferior de la foto. Arriba a la derecha
     se comia el cielo de la imagen, que es lo unico que la situa. */
  .hero-ficha{top:auto;bottom:var(--e-3);right:var(--e-3)}
}

/* ── EXPLORADOR DE OBRAS ─────────────────────────────────────────────────
   Lista · foto · detalle. Es interactividad que sirve para decidir, no
   adorno: se elige una obra y cambian la foto y sus datos sin recargar.
   Sin JavaScript funciona igual, como una lista de enlaces a cada página. */
.explorador{display:grid;grid-template-columns:minmax(0,4fr) minmax(0,6fr) minmax(0,4fr);
  border:1px solid var(--filete);border-radius:var(--r);overflow:hidden;background:var(--papel)}
.exp-lista{list-style:none;border-right:1px solid var(--filete)}
.exp-lista li+li{border-top:1px solid var(--filete)}
.exp-boton{
  width:100%;display:grid;grid-template-columns:2.4rem 1fr auto;gap:.7rem;
  align-items:baseline;padding:1.05rem 1.1rem;text-align:left;position:relative;
  transition:background-color .2s var(--ease-out),translate .16s var(--ease-out);
}
.exp-boton .n{font-family:var(--mono);font-size:var(--t-xs);color:var(--tinta-3)}
.exp-boton .t{font-family:'Big Shoulders';font-weight:700;font-size:1.32rem;text-transform:uppercase;line-height:1}
.exp-boton .f{font-family:var(--mono);font-size:var(--t-xs);color:var(--tinta-3);opacity:0;transition:opacity .2s}
.exp-boton::before{
  content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--accion);
  transform:scaleY(0);transform-origin:50% 50%;transition:transform .25s var(--ease-out);
}
.exp-boton:hover{background:var(--papel-2)}
/* Al pulsar, la fila se hunde 1 px. El botón de acción se hunde 2 porque es una
   tecla con canto; una fila de lista no tiene canto que hundir, así que baja la
   mitad. Es el mismo gesto a la escala que le toca, y estaba sin poner en 8 de
   las 13 variantes pulsables del sitio. */
.exp-boton:active{translate:0 1px}
.exp-boton[aria-current="true"]{background:var(--grafito);color:var(--cal)}
.exp-boton[aria-current="true"]::before{transform:scaleY(1)}
/* Sobre el fondo grafito de la fila activa, el rojo de reposo daría 3,22:1
   contra el fondo. El claro da 5,24:1 y es el mismo acento. */
.exp-boton[aria-current="true"]::before{background:var(--accion-claro)}
.exp-boton[aria-current="true"] .n,.exp-boton[aria-current="true"] .f{color:var(--hormigon);opacity:1}
/* EL ANILLO DEL EXPLORADOR VA POR DENTRO, Y EN CLARO.
   ------------------------------------------------------------------------
   Aqui coincidian tres cosas que se anulaban entre si. Enfocar un boton
   dispara `mostrar()`, que le pone `aria-current="true"`, o sea que el boton
   se tiñe de grafito EN EL MISMO INSTANTE en que recibe el foco. Y el anillo,
   que se dibuja 2 px por fuera de la caja, se encontraba con esto, medido el
   13-08-2026 a 1440:

     · izquierda: recortado 2 px por `.explorador{overflow:hidden}`, porque el
       boton toca el borde de la carcasa
     · derecha:   #141715 sobre el #1D211E de `.exp-media`, que da 1,11:1
     · y su propio fondo era ese mismo #141715

   Dos correcciones, ninguna de composicion. `outline-offset:-2px` mete el
   anillo dentro de la caja, donde ni lo recorta la carcasa ni invade el panel
   de al lado. Y sobre el fondo grafito se usa el mismo token claro que ya
   gobierna las secciones oscuras: cal sobre grafito son 12,63:1 medidos por
   `docs/color.mjs`, no un valor nuevo. */
.exp-boton:focus-visible{outline-offset:-2px}
.exp-boton[aria-current="true"]{--foco:var(--cal)}
.exp-media{position:relative;background:var(--grafito-2);min-height:340px;overflow:clip}
/* Túneles enseña su diagrama y no una foto: no hay foto propia de un túnel.
   Un dibujo no se recorta como una fotografía, así que se contiene sobre su
   papel en vez de llenar el hueco. */
.exp-media img.es-diagrama{object-fit:contain;background:var(--papel);padding:var(--e-2)}
/* La foto no se funde: se PROYECTA. Entra barrida de izquierda a derecha con
   `clip-path`, que es como aparece de verdad un paño gunitado, pasada a
   pasada, y llega con un punto de escala de más que se asienta al terminar.
   Un cross-fade de opacidad es lo que hace cualquier galería; esto solo lo
   puede hacer esta.

   La opacidad se queda porque el recorte no descarta el pintado en todos los
   motores, y dos imágenes a la vez en el mismo hueco es un riesgo que no
   compensa. Una sola regla para las tres propiedades: en dos bloques
   separados, el segundo machacaba la transición del primero y el barrido no
   llegaba a ocurrir. */
.exp-media img{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:0;scale:1.04;clip-path:inset(0 100% 0 0);
  transition:opacity .38s var(--ease-out),clip-path .52s var(--ease-out),
    scale .52s var(--ease-out);
}
.exp-media img.activa{opacity:1;scale:1;clip-path:inset(0 0 0 0)}
.exp-detalle{border-left:1px solid var(--filete);padding:1.3rem}
.exp-panel{display:none}
.exp-panel.activo{display:block}
.exp-panel h3{margin-bottom:.7rem}
.exp-panel p{font-size:var(--t-sm);color:var(--tinta-2)}
.exp-datos{list-style:none;margin-top:1rem;border-top:1px solid var(--filete)}
.exp-datos li{display:flex;justify-content:space-between;gap:.8rem;padding:.55rem 0;
  border-bottom:1px solid var(--filete);font-size:var(--t-sm)}
.exp-datos dt,.exp-datos .k{color:var(--tinta-3);font-family:var(--mono);font-size:var(--t-xs);
  letter-spacing:.08em;text-transform:uppercase}
.exp-datos .v{font-weight:600;text-align:right}
.exp-panel .btn{margin-top:1.1rem;width:100%}

/* ── APERTURA DE PÁGINA INTERIOR ─────────────────────────────────────────
   Estas clases NO existían: las catorce interiores se escribieron con
   `.apertura` y el CSS de la v3 no la definió nunca. El resultado medido era
   un h1 pegado a la cabecera, sin un solo píxel de aire.

   La home abre con foto a sangre y no se puede repetir aquí: no hay catorce
   fotos propias, y clonar el hero catorce veces convierte el gesto en
   plantilla. Abren como lo que son, la ficha ampliada de la obra que se
   acaba de ver en el explorador de la home. Mismo dato, más grande: quien
   pulsa «Piscinas» allí encuentra aquí los mismos cuatro valores. */
.apertura{padding-block:var(--e-5) var(--e-4);border-bottom:1px solid var(--filete)}
/* Aquí había un `.apertura + .regla{border-top:0}` que evitaba que el filete
   de cierre de la apertura y el de apertura de `.regla` sumaran 2 px. Con
   `.regla` vacía ya no hay nada que sumar, y una regla que corrige algo que no
   existe es la clase de código que después nadie se atreve a tocar. */
.apertura h1{margin-block:var(--e-2) var(--e-3);max-width:17ch}
.apertura .entradilla{max-width:52ch}
.apertura-acciones{display:flex;gap:.7rem;flex-wrap:wrap;margin-top:var(--e-3)}

/* Migas. Van dentro del rótulo porque son la etiqueta de esta página, y el
   enlace se subraya al pasar para que se lea como enlace y no como adorno. */
.rotulo a{box-shadow:inset 0 -1px 0 currentColor;
  transition:color .18s var(--ease-out),translate .16s var(--ease-out)}
.rotulo a:hover{color:var(--tinta)}
.rotulo a:active{translate:0 1px}
.seccion-osc .rotulo a:hover,.apertura-obra .rotulo a:hover{color:var(--cal)}

/* Variante de obra: fondo grafito y la imagen al lado. Lleva además
   `seccion-osc` en el HTML, así que hereda de ahí el color del texto en vez
   de repetirlo. */
.apertura-obra{border-bottom:0;padding-bottom:0}
.ap-rejilla{display:grid;grid-template-columns:minmax(0,7fr) minmax(0,5fr);
  gap:var(--e-5);align-items:stretch}
.ap-vista{display:flex;flex-direction:column}
/* La foto llena el alto de la columna en vez de flotar centrada en ella: con
   una proporción fija se quedaba pequeña al lado de un titular de dos líneas
   y una entradilla de cuatro, y la apertura volvía a ser un bloque de texto
   con una estampita al lado.

   `height:0` con `flex-basis:0` es lo que hace que la altura de la fila la
   marque el TEXTO y no la imagen. Sin eso, la regla base `img{height:auto}`
   le da su alto intrínseco: la foto de la tolva es de 480x848, y a media
   columna eso son 848 px de banda para acompañar a cuatro líneas de texto.
   Medido en /maquinaria/, que era la única apertura con una foto vertical. */
.ap-vista img{width:100%;flex:1 1 0;height:0;min-height:250px;object-fit:cover;
  border-radius:var(--r);background:var(--grafito-2)}
/* El diagrama es un dibujo sobre fondo claro: se contiene en vez de recortarse,
   y se le da el papel debajo para que no flote sobre el grafito. */
.ap-vista.es-diagrama img{object-fit:contain;background:var(--papel);padding:var(--e-2)}
.ap-vista figcaption{margin-top:.7rem;padding-top:.6rem;border-top:1px solid var(--filete-osc);
  font-family:var(--mono);font-size:var(--t-xs);letter-spacing:.08em;text-transform:uppercase;
  color:var(--hormigon)}

/* LA PLACA DE CARACTERÍSTICAS, QUE ANTES ERA UNA FILA DE MÉTRICAS
   ------------------------------------------------------------------------
   Esto eran cuatro valores en fila horizontal bajo el titular, en 11 de las 12
   páginas que la llevan. El CLAUDE.md de la raíz cita esa forma exacta como
   tic catalogado en 4 de 4 fuentes que recopilan señales de web generada, y la
   web ya la había retirado una vez: volvió con otro contenido y la misma
   forma. Cambiar «500+ CLIENTES | 20 AÑOS» por «ESPESOR | ARMADO | BULONES»
   arregla la mentira, no el tic.

   En columna, con la clave a la izquierda y el valor a la derecha, deja de ser
   una barra de estadísticas de landing y pasa a ser lo que dice ser: la placa
   de características de la máquina. Y queda igual que `.canales` y
   `.exp-datos`, que ya existían y ya lo hacían así. */
.tira-datos{
  list-style:none;display:grid;grid-template-columns:1fr;
  max-width:34rem;margin-top:var(--e-4);
  border-top:1px solid var(--filete-osc-2);
}
.tira-datos li{
  display:flex;justify-content:space-between;align-items:baseline;gap:var(--e-2);
  padding:.6rem 0;min-width:0;border-bottom:1px solid var(--filete-osc);
}
.tira-datos .k{font-family:var(--mono);font-size:var(--t-xs);letter-spacing:.08em;
  text-transform:uppercase;color:var(--hormigon);flex:0 0 auto}
.tira-datos .v{font-weight:600;color:var(--cal);line-height:1.35;text-align:right}
a.v{text-decoration:underline;text-underline-offset:.25em;text-decoration-color:var(--filete-osc-2)}
a.v:hover{text-decoration-color:currentColor}
/* Sobre papel, cuando la apertura es clara */
.apertura:not(.apertura-obra) .tira-datos{border-top-color:var(--linea)}
.apertura:not(.apertura-obra) .tira-datos li{border-bottom-color:var(--filete)}
.apertura:not(.apertura-obra) .tira-datos .k{color:var(--tinta-3)}
.apertura:not(.apertura-obra) .tira-datos .v{color:var(--tinta)}

/* ── ÍNDICE DE OTRAS OBRAS ───────────────────────────────────────────────
   También sin definir hasta ahora: los seis enlaces se renderizaban como un
   párrafo corrido de texto seguido, «01 Piscinas → Un vaso monolítico 02
   Túneles → …». Lleva la misma marca ámbar a la izquierda que el explorador,
   que es el único gesto de interacción de la web. */
/* El filete lo pinta cada enlace con su propia sombra de 1 px, no el fondo del
   contenedor asomando por los huecos. Con cinco obras en tres columnas la
   última celda va vacía, y con el truco del fondo esa celda se rellenaba de
   gris: un bloque muerto donde no hay nada. Las sombras se solapan sobre el
   hueco de 1 px y dan una línea limpia. */
/* DE REJILLA DE TRES TARJETAS A LISTA, Y POR QUÉ
   ------------------------------------------------------------------------
   Eran tres columnas iguales de tarjetas, que es de los primeros anti-patrones
   que cataloga cualquier guía de rediseño, y aquí además tenía dos defectos
   propios medidos:

   · Con cinco elementos en tres columnas, la última celda queda vacía. Un
     hueco en una rejilla simétrica se lee como que falta algo.
   · Las líneas base de los títulos se descuadraban 7 px entre columnas, porque
     las tildes de las versalitas empujan la caja de línea de unos sí y de
     otros no. En una fila de tres, ese desnivel se ve.

   En lista de filas los dos desaparecen a la vez: no hay hueco que rellenar y
   cada fila tiene su propia línea base. Y se lee como el índice de un
   documento técnico, que es lo que dice ser. */
.indice{display:grid;grid-template-columns:1fr;border-top:1px solid var(--filete)}
.indice a{position:relative;display:grid;align-items:baseline;
  grid-template-columns:2.5rem minmax(7rem,12rem) 1fr 2rem;gap:var(--e-2);
  padding:var(--e-2) var(--e-2) var(--e-2) 1.6rem;
  border-bottom:1px solid var(--filete);
  transition:background .2s var(--ease-out),translate .16s var(--ease-out)}
/* Exactamente la misma marca que el explorador de la home: rojo de la Arnabat,
   3 px, creciendo desde el centro. Es el único gesto de interacción de la web
   y no puede tener dos versiones. */
.indice a::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;
  background:var(--accion);transform:scaleY(0);transform-origin:50% 50%;
  transition:transform .25s var(--ease-out)}
.indice a:hover{background:var(--papel-2)}
.indice a:hover::before{transform:scaleY(1)}
.indice a:active{translate:0 1px}
/* EL ÍNDICE ESTABA ROTO, Y NADIE LO HABÍA MEDIDO.
   ------------------------------------------------------------------------
   La rejilla declara cuatro columnas `2.5rem / 7-12rem / 1fr / 2rem`, pensadas
   para número, nombre, descripción y flecha. Pero en el HTML la flecha va
   ANTES que la descripción, y una rejilla coloca por orden de documento, no por
   nombre de clase. Resultado medido a 1440:

     num 40x20   ·   nom 192x27   ·   flecha 886x28   ·   que 32x252

   La flecha se quedaba con los 886 px del `1fr` y la descripción entera caía en
   la columna de 32 px reservada para la flecha, un carácter por línea. Cada
   fila medía **292 px de alto** en vez de unos 70, y son 5 o 6 filas al final
   de 6 páginas: es una parte del «no se acaba nunca» que midió la auditoría.

   Se arregla con `order` y no con `grid-column`, a propósito: en móvil la
   rejilla tiene tres columnas y una asignación por número se saldría de ella.
   Y no se toca el HTML, porque el orden del documento es el correcto para el
   teclado y para el lector de pantalla: primero adónde va, después el detalle. */
.indice .que{order:3}
.indice .flecha{order:4}
.indice .num{font-family:var(--mono);font-size:var(--t-xs);color:var(--tinta-3)}
.indice .nom{font-family:'Big Shoulders','Arial Narrow',sans-serif;font-weight:700;
  font-size:var(--t-lg);line-height:1.1}
.indice .flecha{font-family:var(--mono);color:var(--tinta-3);text-align:right;
  transition:transform .28s var(--ease-out)}
.indice a:hover .flecha{transform:translateX(3px)}
.indice .que{font-size:var(--t-sm);color:var(--tinta-2);line-height:1.5;max-width:62ch}
/* Aquí había una segunda copia de `.indice a:hover{background:var(--papel-2)}`,
   idéntica a la de arriba. Retirada. */

/* ── Tablas ─────────────────────────────────────────────────────────────── */
.tabla{width:100%;border-collapse:collapse;font-size:var(--t-sm)}
.tabla caption{text-align:left;font-size:var(--t-sm);color:var(--tinta-2);padding-bottom:var(--e-2)}
.tabla th,.tabla td{text-align:left;padding:.8rem .9rem;border-bottom:1px solid var(--filete);vertical-align:top}
.tabla thead th{font-family:var(--mono);font-size:var(--t-xs);font-weight:400;letter-spacing:.1em;
  text-transform:uppercase;color:var(--tinta-3);border-bottom:1px solid var(--linea)}
.tabla tbody tr:last-child th,.tabla tbody tr:last-child td{border-bottom:0}
.tabla td.num{font-family:var(--mono);font-variant-numeric:tabular-nums}
.tabla td.cifra{white-space:nowrap}
.tabla tbody th{font-weight:500}
.seccion-osc .tabla th,.seccion-osc .tabla td{border-color:var(--filete-osc)}
.seccion-osc .tabla thead th{color:var(--hormigon);border-color:var(--hormigon)}
.seccion-osc .tabla caption{color:var(--hormigon)}

/* ── Composición ────────────────────────────────────────────────────────── */
.dos{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--e-5);align-items:start}
.dos-desigual{grid-template-columns:minmax(0,7fr) minmax(0,5fr)}
.a-sangre{margin-right:calc(50% - 50vw);width:auto}

.figura{background:var(--papel);border:1px solid var(--filete);border-radius:var(--r);padding:var(--e-3)}
.figura img{width:100%}
.figura figcaption{margin-top:var(--e-2);padding-top:var(--e-2);border-top:1px solid var(--filete);
  font-size:var(--t-sm);color:var(--tinta-2)}
.figura figcaption b{font-family:var(--mono);font-size:var(--t-xs);text-transform:uppercase;
  letter-spacing:.1em;color:var(--tinta-3);display:block;margin-bottom:.35rem;font-weight:400}
.seccion-osc .figura{background:var(--grafito-2);border-color:var(--filete-osc)}
.seccion-osc .figura figcaption{color:var(--hormigon);border-color:var(--filete-osc)}

/* Secuencia de obra */
.obra{display:grid;grid-template-columns:minmax(0,7fr) minmax(0,5fr);gap:var(--e-2)}
.obra figure{display:flex;flex-direction:column;min-width:0}
.obra .grande{grid-row:span 2}
.obra img{width:100%;height:100%;object-fit:cover;border-radius:var(--r);background:var(--papel-2)}
.obra .grande img{aspect-ratio:4/3}
.obra .chica img{aspect-ratio:16/9}
.obra figcaption{padding-top:.6rem;margin-top:.6rem;border-top:1px solid var(--filete);
  font-size:var(--t-sm);color:var(--tinta-2)}
.obra figcaption b{font-family:var(--mono);font-size:var(--t-xs);font-weight:400;letter-spacing:.1em;
  text-transform:uppercase;color:var(--tinta-3);display:block;margin-bottom:.2rem}
.seccion-osc .obra figcaption{color:var(--hormigon);border-color:var(--filete-osc)}
.seccion-osc .obra figcaption b{color:var(--hormigon)}

/* DOS LISTAS, PORQUE SON DOS COSAS
   ------------------------------------------------------------------------
   Todo iba con `.exclusiones`: los avisos de «cuándo NO conviene» y las
   secuencias de ejecución, que tienen orden. La marca roja delante significa
   aviso, y delante de un paso de obra no significa nada.

   Además, cuando el texto ocupaba todo el ancho de la sección, la línea medía
   **140 caracteres**. El techo cómodo son 75, y el CLAUDE.md de la raíz lo fija
   entre 65 y 75. A 140 el ojo pierde el renglón al volver.

   `.exclusiones` se queda para lo que avisa, con su marca roja. `.pasos` es
   nueva y es para lo que tiene orden: raíl fijo para el título, medida
   controlada para el texto, y el número en la voz de etiqueta de máquina. */
/* EL GUION ROJO SE RETIRA, 13-08-2026. Eran **49**, en 9 páginas, con 11 en
   `/problemas-y-reparaciones/` solamente.
   ------------------------------------------------------------------------
   Era un filete de 13x2 px delante de un `<b>` en `display:block` que hace de
   micro-titular. Dicho así se ve lo que es: **la misma gramática del rótulo a
   escala pequeña**, raya corta y texto destacado detrás, cuarenta y nueve
   veces. Y desde hoy hay un segundo motivo, de significado: el rojo es el
   acento y significa «aquí se actúa». En una lista de cuándo NO conviene
   gunitar no se actúa: se lee. Un color que marca acción delante de contenido
   que no la tiene deja de marcar nada.

   No se sustituye por un guion gris, que sería el mismo objeto en otro color.
   La jerarquía la lleva ya el `<b>`, que es 17 px de tinta contra 14 px de
   tinta-2, y la separación la lleva el filete del propio `<li>`, que es lo que
   hace una lista. El sangrado de 2 rem se retira con el guion: sin marca no
   hay nada que alojar en él. */
.exclusiones{list-style:none;border-top:1px solid var(--filete)}
.exclusiones li{padding:var(--e-2) 0;border-bottom:1px solid var(--filete);
  position:relative;font-size:var(--t-sm);color:var(--tinta-2)}
.exclusiones li b{color:var(--tinta);font-weight:600;display:block;font-size:var(--t-base);margin-bottom:.15rem}
/* La medida va en el `li` y no en sus hijos, y esa es la diferencia entre que
   funcione o no: el texto de cada aviso es un nodo suelto detrás del `<b>`, sin
   elemento propio, así que una regla sobre los hijos no lo alcanza.

   Medido a 1440 el 08-08-2026: en las secciones a dos columnas la línea salía a
   60 caracteres, pero en las de ancho completo llegaba a **146**. El techo de la
   pauta son 75. */
.exclusiones li{max-width:70ch}
.seccion-osc .exclusiones,.seccion-osc .exclusiones li{border-color:var(--filete-osc)}
.seccion-osc .exclusiones li{color:var(--hormigon)}
.seccion-osc .exclusiones li b{color:var(--cal)}

.pasos{list-style:none;counter-reset:paso;border-top:1px solid var(--filete)}
.pasos li{
  display:grid;grid-template-columns:2.4rem minmax(9rem,14rem) minmax(0,62ch);
  gap:var(--e-2);align-items:baseline;
  padding:var(--e-2) 0;border-bottom:1px solid var(--filete);
  font-size:var(--t-sm);color:var(--tinta-2);
}
.pasos li::before{
  content:counter(paso,decimal-leading-zero);counter-increment:paso;
  font-family:var(--mono);font-size:var(--t-xs);letter-spacing:.08em;color:var(--tinta-3);
}
.pasos li b{color:var(--tinta);font-weight:600;font-size:var(--t-base);line-height:1.25}
.seccion-osc .pasos,.seccion-osc .pasos li{border-color:var(--filete-osc)}
.seccion-osc .pasos li{color:var(--hormigon)}
.seccion-osc .pasos li b{color:var(--cal)}
.seccion-osc .pasos li::before{color:var(--hormigon)}

.ficha-maquina img{background:var(--papel-2);
  border:1px solid var(--filete);border-radius:var(--r);padding:var(--e-3) var(--e-2)}

/* ── Preguntas ──────────────────────────────────────────────────────────── */
/* EL CONTROL VUELVE AL LADO DE SU ETIQUETA
   ------------------------------------------------------------------------
   El signo de abrir estaba pegado al borde derecho del contenedor, que en
   escritorio queda a 1.070 px medidos del final de la pregunta. Quien lee la
   pregunta tiene que cruzar la pantalla entera para encontrar el control que
   la abre, y el ojo hace ese viaje en cada una de las once páginas que llevan
   preguntas.

   Ahora la marca va a la izquierda, delante de la pregunta, y el bloque se
   limita a 52rem: el control y su etiqueta se leen como una sola cosa.

   Y la pregunta deja de ir en versalitas. Una pregunta en mayúsculas no se lee
   como pregunta, se lee como rótulo. */
.faq{border-top:1px solid var(--filete);max-width:52rem}
.faq details{border-bottom:1px solid var(--filete)}
.faq summary{padding:var(--e-2) 0 var(--e-2) 2rem;position:relative;cursor:pointer;list-style:none;
  font-family:'Big Shoulders';font-weight:700;font-size:var(--t-lg);line-height:1.15;
  transition:translate .16s var(--ease-out)}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after,.faq summary::before{content:"";position:absolute;left:0;top:1.4em;
  width:11px;height:2px;background:var(--tinta-2);
  transition:background-color .18s var(--ease-out)}
.faq summary::before{transform:rotate(90deg);transition:transform .25s var(--ease-out),
  background-color .18s var(--ease-out)}
.faq details[open] summary::before{transform:rotate(0)}
/* EL DESPLEGABLE NO DABA NINGUNA SEÑAL AL SOBREVOLARLO, y son **44 filas de
   832x60,5 px en 11 páginas**: la superficie pulsable más grande del sitio
   después del índice de obras. Medido con puntero real: cero píxeles de
   diferencia entre reposo y hover. Y había incoherencia interna, porque
   `.indice a` y `.exp-boton`, que son filas pulsables del mismo tipo, sí
   cambiaban de fondo.

   Aquí no puede ir la marca de 3 px de la izquierda porque ese sitio ya lo
   ocupa el signo de abrir. Así que responde el propio signo: se tiñe del acento
   al sobrevolar, que es exactamente donde se va a pulsar y lo que se va a
   accionar. Y la fila se hunde 1 px al tocarla, como el resto de filas. */
.faq summary:hover::before,.faq summary:hover::after{background:var(--accion)}
.seccion-osc .faq summary:hover::before,.seccion-osc .faq summary:hover::after{background:var(--accion-claro)}
.faq summary:active{translate:0 1px}
.faq .respuesta{padding-left:2rem}
.faq .respuesta{padding-bottom:var(--e-3);color:var(--tinta-2);font-size:var(--t-sm);max-width:70ch}
.faq .respuesta p+p{margin-top:.7rem}
.seccion-osc .faq,.seccion-osc .faq details{border-color:var(--filete-osc)}
.seccion-osc .faq .respuesta{color:var(--hormigon)}
.seccion-osc .faq summary::after,.seccion-osc .faq summary::before{background:var(--hormigon)}

/* ── Formulario ─────────────────────────────────────────────────────────── */
.form{display:grid;gap:var(--e-3)}
.campo{display:grid;gap:.4rem}
.campo-doble{display:grid;grid-template-columns:1fr 1fr;gap:var(--e-2)}
label{font-size:var(--t-sm);font-weight:600}
label .opc{font-weight:400;color:var(--tinta-3)}
/* 16 px y no 14 en los campos, y es un hecho de la plataforma y no un gusto:
   Safari de iPhone hace zoom automático al enfocar un campo cuya letra mide
   menos de 16 px, y al salir del campo no vuelve atrás. Quien rellena esto
   desde una obra se queda con la página ampliada y descuadrada a mitad del
   formulario. El resto de la interfaz sigue en la escala de siete pasos: esto
   es --t-base, que ya existe, no un tamaño nuevo. */
input,select,textarea{
  font:inherit;font-size:var(--t-base);width:100%;padding:.7rem .85rem;
  background:var(--papel);color:var(--tinta);border:1.5px solid var(--linea);border-radius:var(--r);
  transition:border-color .18s var(--ease-out),box-shadow .18s var(--ease-out);
}
textarea{min-height:7.5rem;resize:vertical;line-height:1.55}
select{appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 6l4 4 4-4' fill='none' stroke='%236A6F69' stroke-width='1.4'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right .7rem center;background-size:15px;padding-right:2.2rem}
input::placeholder,textarea::placeholder{color:var(--tinta-3)}
/* EL `outline:0` SE RETIRA, y esto no es una preferencia: era el fallo mas
   grave del recorrido con teclado.
   ------------------------------------------------------------------------
   Este bloque sustituia el anillo por un borde tenido y una sombra interior.
   Funciona mientras el campo esta en reposo, pero `.campo.mal input` (0,2,1)
   gana por especificidad a `input:focus` (0,1,1) y vuelve a pintar las MISMAS
   dos propiedades en rojo. Con el anillo ya suprimido, un campo en error se ve
   exactamente igual enfocado que sin enfocar.

   Medido el 13-08-2026 en Chromium y en WebKit, comparando pixel a pixel la
   captura con el foco puesto y sin el, sobre el mismo recorte:

     campo #nombre EN ERROR   ->      0 pixeles de diferencia
     el mismo campo en reposo -> 1.556 pixeles, 15,01:1

   Y el momento en que eso ocurre es el peor posible: al enviar el formulario
   vacio, `app.js` mueve el foco al primer campo malo. O sea que justo cuando
   se lleva al usuario a un sitio, deja de haber nada que diga donde esta.
   WCAG 2.2 SC 2.4.7 (Foco visible, AA) y SC 1.4.11 (Contraste de lo que no es
   texto, AA).

   Quitando `outline:0` vuelve a aplicar el anillo global de `:focus-visible`,
   que ninguna regla de error toca. El borde y la sombra se quedan: no estorban
   y siguen marcando el campo activo tambien con el raton. */
input:focus,select:focus,textarea:focus{border-color:var(--tinta);box-shadow:inset 0 0 0 1px var(--tinta)}
.ayuda{font-size:var(--t-xs);color:var(--tinta-3)}
/* EL ROJO DEL ERROR Y EL ROJO DE LA ACCIÓN SON EL MISMO, Y HAY QUE DECIRLO.
   ------------------------------------------------------------------------
   Estaba escrito a mano tres veces como `#C0341C`, que hasta hoy era el rojo
   de la máquina y desde hoy es el acento. Se pasa al token, y con eso queda a
   la vista una coincidencia que antes escondía el hex: en un formulario, el
   botón de enviar y un campo mal rellenado llevan la misma familia de color.

   No se resuelve inventando un cuarto rojo. Se resuelve por la forma, que es
   la misma regla que separa el botón principal del secundario:

     LA ACCIÓN SE MARCA CON RELLENO. EL ERROR SE MARCA CON CONTORNO Y TEXTO.

   Ningún objeto de este sitio puede estar en los dos estados a la vez: un botón
   no se valida y un campo no se rellena de color. Si algún día hiciera falta un
   rojo de error de verdad, entra como token propio y con su medición, no como
   un hex suelto dentro de una regla de formulario.

   `--accion-2` y no `--accion`: el mensaje de error mide 12 px, y el de reposo
   sobre papel da 4,66:1, que pasa AA raspando. Este da 5,89:1. */
.error-campo{font-size:var(--t-xs);color:var(--accion-2);display:none}
.campo.mal input,.campo.mal select,.campo.mal textarea,
.consent.mal input{border-color:var(--accion-2);box-shadow:inset 0 0 0 1px var(--accion-2)}
.campo.mal .error-campo,.consent.mal+.error-campo{display:block}
.tarro{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.consent{display:grid;grid-template-columns:auto 1fr;gap:.65rem;align-items:start;
  font-size:var(--t-sm);color:var(--tinta-2)}
.consent input{width:1.05rem;height:1.05rem;margin-top:.2rem}

/* ── Canales ────────────────────────────────────────────────────────────── */
.canales{list-style:none;border-top:1px solid var(--filete)}
.canales li{border-bottom:1px solid var(--filete)}
.canales a{display:flex;align-items:baseline;justify-content:space-between;gap:var(--e-2);
  padding:.9rem 0 .9rem .85rem;position:relative}
/* La marca era ÁMBAR aquí y ROJA en el explorador y en el índice, siendo las
   tres «el único gesto de interacción de la web» según el propio CSS. Tres
   copias del mismo gesto y una de otro color: eso no lo caza ninguna regla de
   contraste, solo se ve poniéndolas en fila. Ahora las tres son el acento. */
.canales a::before{content:"";position:absolute;left:0;top:.6rem;bottom:.6rem;width:3px;
  background:var(--accion);transform:scaleY(0);transform-origin:50% 50%;
  transition:transform .22s var(--ease-out)}
.canales a:hover::before,.canales a:focus-visible::before{transform:scaleY(1)}
/* El hundimiento se compone con el tirón magnético en la misma propiedad, igual
   que en `.btn`: con dos propiedades distintas, una machacaría a la otra. */
.canales a:active{translate:var(--iman-x) calc(var(--iman-y) + 1px)}
.seccion-osc .canales a::before{background:var(--accion-claro)}
.canales .q{font-family:var(--mono);font-size:var(--t-xs);letter-spacing:.1em;
  text-transform:uppercase;color:var(--tinta-3)}
.canales .v{font-weight:600;display:flex;align-items:center;gap:.4rem}
.seccion-osc .canales,.seccion-osc .canales li{border-color:var(--filete-osc)}
.seccion-osc .canales .q{color:var(--hormigon)}

/* ── Pie ────────────────────────────────────────────────────────────────── */
.pie{background:var(--grafito);color:var(--hormigon);padding-block:var(--e-5) var(--e-3);font-size:var(--t-sm)}
/* De cuatro columnas a dos, sin perder un solo enlace.
   ------------------------------------------------------------------------
   El pie de cuatro columnas iguales es una de las formas más repetidas que
   hay, y aquí además la tercera columna repetía casi entera la barra de
   navegación de arriba.

   La tentación era borrar esa columna. No se hace, y el motivo es una medición
   ajena: la página de vía seca o húmeda **no recibe ningún enlace de cuerpo
   desde ninguna página indexable**, así que el del pie es de los pocos que
   tiene. Borrarlo por estética la dejaría más huérfana de lo que ya está.

   Así que se reagrupa en vez de recortar: la marca ocupa su columna y las tres
   listas comparten la otra en una rejilla propia que fluye. Se va el aspecto
   de granja de enlaces y se queda cada enlace donde estaba. */
.pie-rejilla{display:grid;grid-template-columns:1.4fr 2fr;gap:var(--e-5) var(--e-4)}
.pie-listas{display:grid;grid-template-columns:repeat(auto-fit,minmax(9rem,1fr));gap:var(--e-4)}
.pie .pie-tit{font-family:var(--mono);font-size:var(--t-xs);font-weight:400;letter-spacing:.12em;
  text-transform:uppercase;color:var(--hormigon);margin-bottom:var(--e-2)}
.pie ul{list-style:none;display:grid;gap:.15rem}
/* Los enlaces del pie se quedaban en 17 px de alto. Con el relleno pasan de
   24, que es el mínimo de WCAG 2.5.8, sin depender de la excepción de
   espaciado entre centros. En un móvil se agradece. */
.pie a{color:var(--cal);transition:color .18s var(--ease-out),translate .16s var(--ease-out);
  display:inline-block;padding-block:.35rem}
.pie a:hover{color:var(--accion-claro)}
.pie a:active{translate:0 1px}
.pie .marca{color:var(--cal)}
.pie .marca span{color:var(--hormigon)}
.pie-desc{margin-top:var(--e-2);max-width:32ch}
.pie-legal{margin-top:var(--e-4);padding-top:var(--e-2);border-top:1px solid var(--filete-osc);
  display:flex;justify-content:space-between;gap:var(--e-2);flex-wrap:wrap;font-size:var(--t-xs)}

/* ── Texto legal ────────────────────────────────────────────────────────── */
/* 72 y no 78. El `ch` mide el ancho del cero de la fuente, que en Inter es más
   estrecho que la letra media de un texto en español, así que un contenedor de
   78ch da líneas de 82 caracteres reales. Medido a 1440 en el aviso legal y en
   la política de cookies. */
.texto-legal{max-width:72ch}
.texto-legal h2{font-size:var(--t-lg)}
.texto-legal p{color:var(--tinta-2)}
/* El hueco de un dato legal que falta. Es el ÚNICO sitio donde queda ámbar, y
   ahora ámbar significa exactamente una cosa: falta algo. Los dos valores
   salen de los tokens con `color-mix` en vez de ir escritos a mano, que era
   otra copia esperando a desincronizarse. */
.pendiente{background:color-mix(in srgb,var(--aviso) 22%,transparent);color:var(--aviso-txt);
  padding:.1rem .4rem;border-radius:var(--r);
  font-weight:600;font-family:var(--mono);font-size:var(--t-xs)}

/* ── MOVIMIENTO ──────────────────────────────────────────────────────────
   Se escribe con animaciones nativas por scroll, que en Safari 26.4 corren en
   el hilo del compositor, no en el principal. Van dentro de:
     · @supports  porque animation-timeline aún no es Baseline
     · @media (prefers-reduced-motion: no-preference)  porque la animación es
       la excepción que se añade, no la norma que se quita.
   Sin las dos condiciones, el contenido se ve entero y quieto. */
.revela{opacity:1}

@supports (animation-timeline:view()){
  @media (prefers-reduced-motion:no-preference){
    /* Se anima SOLO el desplazamiento, nunca la opacidad.
       Motivo medido, no estético: con opacity:0 de partida, 9 de 16 bloques se
       quedaban invisibles con el elemento centrado en pantalla mientras el
       compositor resolvía el temporizador. Un texto que no se lee es el peor
       fallo posible de una web, y un fundido no vale ese riesgo. Desplazando
       solo, el peor caso es un bloque 24 px más abajo, que no se nota. */
    .revela{
      animation:entra linear both;
      animation-timeline:view();
      animation-range:entry 0% entry 62%;
    }
    @keyframes entra{
      from{transform:translateY(24px)}
      to{transform:none}
    }

    /* Pero NO la misma entrada para todo. Catorce bloques subiendo 24 px con
       la misma curva no es un lenguaje de movimiento, es un tic: el ojo lo
       aprende en el segundo bloque y a partir de ahí solo registra repetición.
       Cada material entra como le corresponde.

       Las figuras y las bandas de obra se DESCUBREN, con el mismo barrido que
       proyecta las fotos del explorador. Es el gesto de la web. */
    .obra.revela,.figura.revela,.ap-vista{
      animation:descubre linear both;
      animation-timeline:view();
      animation-range:entry 0% entry 58%;
    }
    @keyframes descubre{
      from{clip-path:inset(0 0 14% 0);transform:translateY(18px)}
      to{clip-path:inset(0 0 0 0);transform:none}
    }

    /* Las listas escalonan, porque son listas y se leen en orden. El retardo
       total se corta en el sexto: más allá, quien va rápido ve aparecer texto
       por debajo de donde ya está mirando. */
    .exclusiones.revela li,.indice.revela a,.tira-datos li{
      animation:entra linear both;
      animation-timeline:view();
      animation-range:entry 0% entry 50%;
    }
    .exclusiones.revela li:nth-child(2),.indice.revela a:nth-child(2),.tira-datos li:nth-child(2){animation-range:entry 4% entry 54%}
    .exclusiones.revela li:nth-child(3),.indice.revela a:nth-child(3),.tira-datos li:nth-child(3){animation-range:entry 8% entry 58%}
    .exclusiones.revela li:nth-child(4),.indice.revela a:nth-child(4),.tira-datos li:nth-child(4){animation-range:entry 12% entry 62%}
    .exclusiones.revela li:nth-child(n+5),.indice.revela a:nth-child(n+5){animation-range:entry 16% entry 66%}
    /* La lista ya no se mueve como bloque: lo hacen sus hijos. */
    .exclusiones.revela,.indice.revela{animation:none}
    /* Profundidad en el hero: la foto y el texto se mueven a distinta
       velocidad al bajar, que es lo que hace que se lean como dos planos y no
       como una estampa plana. Dos capas bastan; ni partículas ni bucles
       infinitos, que es justo lo que las webs del sector que funcionan no
       llevan. */
    .hero-foto img{
      animation:asienta linear both;
      animation-timeline:view();
      animation-range:cover 0% cover 100%;
    }
    @keyframes asienta{from{scale:1.08;translate:0 -2%}to{scale:1;translate:0 3%}}

    /* El texto ya NO hace parallax. Cuando iba flotando sobre el degradado,
       moverlo a distinta velocidad que la foto daba profundidad. Ahora es una
       placa opaca apoyada en el borde inferior: separarla de la foto abriría
       una franja de grafito debajo, y una placa que se despega de su base deja
       de leerse como material y pasa a leerse como error.

       La profundidad la sigue dando la foto, que sí se mueve. Dos planos que
       se mueven a distinta velocidad siguen siendo dos planos aunque uno esté
       quieto. */
  }
}
/* Curva lineal a propósito: en una animación atada al scroll la aceleración
   la pone el dedo, y añadir un ease encima se percibe como retardo. Es la
   excepción declarada a la regla de casa sobre linear. */

/* ── EL IMPACTO ──────────────────────────────────────────────────────────
   El único momento con autoría de toda la web, y sale del producto y no del
   catálogo de efectos: el hormigón no se vierte, se dispara a más de cien
   metros por segundo y lo compacta el golpe. El titular lo dice con palabras
   desde la primera versión y hasta ahora no pasaba nada al leerlo.

   Se dispara UNA línea, no las dos. «No se vierte» se queda quieta y es
   justamente su quietud la que hace legible el golpe de la segunda: si entran
   las dos, no hay contraste y vuelve a ser una entrada de las de siempre.

   Ocurre una vez, al cargar, y no se repite al hacer scroll. */
/* Las dos líneas del titular en el mismo color, y la jerarquía por PESO.
   La segunda iba teñida de gris hormigón, que es teñir media frase de un color
   distinto para marcar importancia: exactamente lo que el CLAUDE.md de la raíz
   prohíbe cuando dice «jerarquía por peso, tamaño y espacio, no por color». Y
   encima bajaba el contraste justo en la palabra que carga el mensaje. */
.hero h1 .quieta{display:block;font-weight:600}
.hero h1 .impacta{display:block;position:relative;font-style:normal;font-weight:800}

@media (prefers-reduced-motion:no-preference){
  /* Parte de opacidad .3 y no de 0: si algo impidiera que la animación
     terminase, el titular se lee igual. Es la misma regla que gobierna los
     revelados por scroll, donde se midió que 9 de 16 bloques podían quedarse
     invisibles. Un titular que no se lee no lo compensa ningún efecto. */
  .hero h1 .impacta{animation:disparo .74s cubic-bezier(0.16,1,0.3,1) both}
  .hero h1 .quieta{animation:asoma .5s cubic-bezier(0.16,1,0.3,1) both}

  @keyframes asoma{
    from{translate:0 14px;opacity:.4}
    to{translate:0 0;opacity:1}
  }
  /* Llega desde fuera, desenfocado por la velocidad, y para en seco pasándose
     un pelo. El desenfoque es lo que vende la velocidad: sin él es un deslizado
     más. Va acotado a una línea de texto, que es una región pequeña, así que no
     hunde los fotogramas. */
  @keyframes disparo{
    0%   {translate:-38% 0;filter:blur(10px);opacity:.3}
    58%  {translate:1.5% 0;filter:blur(0);opacity:1}
    76%  {translate:-.8% 0}
    100% {translate:0 0}
  }

  /* La chispa del impacto: una banda corta que cruza la línea justo cuando
     llega, y desaparece. No queda ningún bucle encendido. */
  .hero h1 .impacta::after{
    content:"";position:absolute;inset:-2% -4%;pointer-events:none;
    background:linear-gradient(96deg,transparent 42%,color-mix(in srgb,var(--accion-claro) 55%,transparent) 50%,transparent 58%);
    opacity:0;animation:chispa .5s .42s ease-out both;
  }
  @keyframes chispa{
    0%  {opacity:0;translate:-30% 0}
    35% {opacity:1}
    100%{opacity:0;translate:34% 0}
  }

  /* La foto acusa el golpe. Dos píxeles y 160 ms: por debajo no se nota y por
     encima parece que la página se ha roto. */
  .hero-foto{animation:acusa .16s .44s ease-out both}
  @keyframes acusa{
    0%,100%{translate:0 0}
    40%    {translate:0 2px}
    70%    {translate:0 -1px}
  }
}

/* ── LA BOQUILLA ─────────────────────────────────────────────────────────
   El cursor de esta web es la boquilla de la lanza. Al moverse deprisa el
   anillo se estira en la dirección del movimiento, igual que el chorro al
   salir; parado, vuelve a ser un círculo.

   Todo el comportamiento vive aquí: app.js solo escribe cuatro números
   (--px, --py, --vel, --ang) y no toca ni una propiedad de estilo calculada.
   El retardo tampoco lo temporiza JavaScript, lo pone la transición de abajo,
   que es lo que hace que el anillo persiga al punto en vez de ir pegado. */
:root{--px:0; --py:0; --vel:0; --ang:0}

.boquilla{position:fixed;left:0;top:0;z-index:300;pointer-events:none;
  opacity:1;transition:opacity .25s var(--ease-out)}
.boquilla.fuera{opacity:0}
.boquilla i{position:absolute;left:0;top:0;display:block}

/* NO es un círculo con un punto dentro. Ese objeto, anillo grande persiguiendo
   a un punto pequeño, es EL cursor personalizado por defecto: sale igual en
   cualquier portfolio y en cualquier agencia, y por eso no dice nada de quien
   lo lleva.

   Este es una MARCA DE REGISTRO, la cruz con hueco central que se imprime en
   la esquina de un plano para alinear las hojas. Es del oficio: quien maneja
   planos la reconoce sin que nadie se la explique, y no se parece a la de
   nadie más. Al moverse, los cuatro brazos se abren en la dirección de la
   mano, que es lo que hace un chorro al salir de la boquilla. */
/* EL TAMAÑO SE HACE CON `transform`, NO CON `width`. 13-08-2026.
   ------------------------------------------------------------------------
   Las dos piezas de la marca cambiaban de tamaño animando `width`, `height` y
   `margin`. Los anti-patrones del workspace dicen «solo `transform` y
   `opacity`», y aquí se incumplía en el peor sitio posible: la marca cambia de
   tamaño CADA vez que el puntero pasa por encima de un enlace, o sea cientos de
   veces por sesión, y cada cambio pedía recalcular composicion.

   `--k` es el factor de estado. Va dentro de `transform` y no de la propiedad
   `scale` a proposito, porque `scale` ya la ocupa el estirado por velocidad y
   los dos tiempos son incompatibles: el estirado tiene que ser INSTANTANEO
   para que siga al pulso de la mano, y el cambio de estado tiene que
   interpolar. `transform` y las propiedades individuales se componen, asi que
   cada uno se queda con su tiempo. Con una sola propiedad habria que elegir, y
   cualquiera de las dos elecciones se siente mal. */
.bq-punto{width:3px;height:3px;margin:-1.5px;background:var(--accion);
  --k:1;
  translate:calc(var(--px) * 1px) calc(var(--py) * 1px);
  transform:scale(var(--k));
  transition:transform .18s var(--ease-out)}

/* Los cuatro brazos se dibujan con dos degradados: uno vertical y otro
   horizontal, con el centro transparente. Un solo elemento, ninguna imagen y
   ningún nodo de más. */
.bq-anillo{
  width:46px;height:46px;margin:-23px;
  --k:1;
  background:
    linear-gradient(to bottom,var(--accion) 0 34%,transparent 34% 66%,var(--accion) 66% 100%) 50%/1.5px 100% no-repeat,
    linear-gradient(to right, var(--accion) 0 34%,transparent 34% 66%,var(--accion) 66% 100%) 50%/100% 1.5px no-repeat;
  translate:calc(var(--px) * 1px) calc(var(--py) * 1px);
  rotate:calc(var(--ang) * 1deg);
  /* La apertura sale de la velocidad: la marca se estira en el eje del
     movimiento y se estrecha en el perpendicular. */
  scale:calc(1 + var(--vel) * .013) calc(1 - var(--vel) * .006);
  transform:scale(var(--k));
  /* `difference` es lo que hace que se vea sobre la foto oscura del hero y
     sobre el papel claro sin cambiar de color a mano. */
  mix-blend-mode:difference;
  transition:transform .26s var(--ease-out),rotate .26s var(--ease-out);
}
/* SE ACABO LA PERSECUCION, y la pidió Mario. 13-08-2026.
   ------------------------------------------------------------------------
   Aquí había `transition:translate .085s linear`, que es lo que hacía que el
   anillo llegara 85 ms después que el punto. Mario dijo que el cursor «tiene la
   misma interfaz que la otra página», y al abrir piscinascmg.es y mirarla se le
   dio la razón con la medida delante: allí hay un punto de 8 px y un anillo de
   42 px que persigue con retardo. Aquí se rediseñó la FORMA el 08-08 y se dejó
   intacta la ANATOMÍA, que es lo único que se percibe en movimiento: la forma
   de marca de registro solo se aprecia con el ratón parado, que es justo cuando
   nadie la está mirando.

   Sin retardo, las dos piezas van clavadas al puntero y lo que queda propio de
   esta web es lo que hace la marca al moverse y al apuntar: se abre con la
   velocidad y gira 45 grados sobre lo pulsable. Eso no lo hace la hermana. */

/* Sobre algo pulsable la marca gira 45 grados y se cierra: pasa de estar
   midiendo a estar apuntando. El giro es lo que se nota, no el tamaño. */
/* Los factores salen de los tamaños que había, para que la marca se vea igual
   que estaba decidida: 30/46 sobre lo pulsable y 19/46 al disparar, y el punto
   de 3 a 5 px. Lo único que cambia es CÓMO se llega a ese tamaño. */
.boquilla.sobre .bq-anillo{--k:.652;rotate:calc(var(--ang) * 1deg + 45deg)}
.boquilla.sobre .bq-punto{--k:1.667}

/* Al pulsar, dispara: la marca se cierra de golpe sobre el punto. */
.boquilla.dispara .bq-anillo{--k:.413}

/* Con la boquilla puesta se esconde el cursor del sistema. Solo entonces: si
   el script no llegara a correr, el puntero normal sigue ahí. Se exceptúan los
   campos de texto, donde la barra de inserción dice dónde se va a escribir y
   ningún dibujo la sustituye. */
.con-boquilla,.con-boquilla a,.con-boquilla button,.con-boquilla summary,
.con-boquilla label,.con-boquilla select{cursor:none}
.con-boquilla input[type="text"],.con-boquilla input[type="email"],
.con-boquilla input[type="tel"],.con-boquilla textarea{cursor:text}

/* Atracción magnética. El desplazamiento lo calcula app.js y lo entrega en dos
   variables; aquí se compone con el hundimiento de :active, que tiene que
   seguir funcionando encima del tirón. */
.btn,.canales a{--iman-x:0px;--iman-y:0px}
/* El hundimiento pasa de `scale(.97)` a bajar 2 px, 13-08-2026. Encoger es lo
   que hace un boton pintado; bajar es lo que hace una tecla, y desde hoy esto
   es una tecla. Va en la misma propiedad que el tiron magnetico, compuesto con
   `calc`, porque son el mismo eje y con dos propiedades distintas una
   machacaria a la otra.

   Y el tiempo de `translate` baja de 300 a 160 ms por culpa de este cambio: a
   300 el boton volvia a subir despues de soltarlo con un retardo que se siente
   blando. El tiron del iman no sufre, porque son 6 px como mucho y la curva
   tiene la salida larga. */
.btn{translate:var(--iman-x) var(--iman-y);
  transition:background-color .2s var(--ease-out),color .2s var(--ease-out),
    border-color .2s var(--ease-out),translate .16s var(--ease-out),
    box-shadow .16s var(--ease-out)}
.btn:active{translate:var(--iman-x) calc(var(--iman-y) + 2px)}
.canales a{translate:var(--iman-x) var(--iman-y);transition:translate .3s var(--ease-out)}

/* ── OBJETIVOS DE PULSACIÓN (WCAG 2.2, SC 2.5.8) ─────────────────────────
   El criterio pide 24x24 px CSS como mínimo. Medido con el navegador: los
   enlaces del menú de escritorio daban 17 px de alto, los del pie 17, y las
   migas 20. Todos por debajo.

   Se resuelve con relleno vertical y no agrandando la letra: el texto se queda
   como está y lo que crece es el área que responde al dedo y al puntero. En el
   menú del pie eso ya se había hecho una vez; faltaban el menú principal, las
   migas y los enlaces de texto de las páginas legales.

   AÑADIDO EL 13-08-2026: el teléfono de la ficha de contacto, medido con axe y
   con el navegador a 390 px, daba **23 px de alto**. Uno por debajo, y es el
   peor sitio donde puede faltar: `PRODUCT.md` dice que el éxito de esta web es
   que suene el teléfono, y que el teléfono y el WhatsApp son la vía real de
   contacto de este sector. Un dato de una lista puede quedarse pequeño; una
   acción de conversión, no.

   En la misma pasada aparecieron otros dos enlaces por debajo de 24 px:
   «política de privacidad» (17 px) y «Piscinas CMG» (20 px). Esos NO se tocan y
   no es descuido: los dos van dentro de una frase, y SC 2.5.8 excluye
   expresamente el objetivo cuyo tamaño lo limita la altura de línea del texto
   que lo rodea. Agrandarlos rompería el renglón para cumplir un criterio que ya
   se cumple por excepción. */
.menu a:not(.btn),.rotulo a,.pie a,.pie-legal a,
.tira-datos a{display:inline-flex;align-items:center;min-height:24px}
.marca{min-height:24px;display:inline-flex;align-items:center;flex-wrap:wrap}
/* En el pie, los enlaces de lista ya llevaban relleno propio; se conserva. */

/* ── ESTADO DE CARGA ─────────────────────────────────────────────────────
   Un sitio estático de 15 páginas no tiene esperas que justifiquen una pantalla
   de carga: montarla sería inventar una espera para poder decorarla. Lo único
   que de verdad tarda aquí es el envío del formulario, que sale a un servidor,
   y ese sí necesita decir que está ocurriendo algo.

   Y no es un círculo girando. Son TRES PASADAS que se llenan una tras otra,
   que es literalmente como se alcanza el espesor de proyecto: la primera sella
   y sirve de base, la segunda completa, la tercera remata. El indicador cuenta
   el trabajo de la casa en vez de ser el disco de siempre. */
.cargando{display:inline-flex;gap:3px;align-items:center;vertical-align:middle}
.cargando i{display:block;width:14px;height:3px;background:currentColor;opacity:.28}

@media (prefers-reduced-motion:no-preference){
  .cargando i{animation:pasada 1.15s var(--ease-in-out) infinite}
  .cargando i:nth-child(2){animation-delay:.16s}
  .cargando i:nth-child(3){animation-delay:.32s}
  @keyframes pasada{
    0%,72%,100%{opacity:.28;scale:1 1}
    26%        {opacity:1;  scale:1 2.4}
  }
}
/* Con movimiento reducido no se anima nada, pero el estado tiene que seguir
   siendo legible: entonces habla el texto del botón, que cambia igual. */

.btn[aria-busy="true"]{pointer-events:none}
.btn[aria-busy="true"] .cargando{color:inherit}

/* ── Adaptación ─────────────────────────────────────────────────────────── */
@media (max-width:1040px){
  .explorador{grid-template-columns:minmax(0,5fr) minmax(0,7fr)}
  .exp-detalle{grid-column:1 / -1;border-left:0;border-top:1px solid var(--filete)}
  .indice{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:960px){
  .dos,.dos-desigual{grid-template-columns:1fr;gap:var(--e-4)}
  .pie-rejilla{grid-template-columns:1fr}
  /* En móvil los pasos dejan de ser rejilla y pasan a bloque con el número
     colocado a la izquierda.

     El motivo es concreto: el texto de cada paso es un nodo suelto detrás del
     `<b>`, sin elemento propio. En una rejilla, un nodo así se convierte en un
     item anónimo y cae en la primera celda libre, que al pasar de tres
     columnas a dos es la del número: medido, el texto quedaba en 79 px de
     ancho, nueve caracteres por línea. Con `display:block` no hay celdas que
     repartir y el texto fluye detrás de su título, que es lo que se quiere. */
  /* La medida se pone también aquí, y no solo en la rejilla de escritorio: al
     apilarse, el texto pasa a ocupar el ancho entero del contenedor y a 768 px
     daba 82 caracteres por línea. En la versión de tres columnas la medida la
     ponía la tercera columna; al desaparecer, desaparecía con ella. */
  .pasos li{display:block;position:relative;padding-left:2.4rem;max-width:72ch}
  .pasos li::before{position:absolute;left:0;top:var(--e-2)}
  .pasos li b{display:block;margin-bottom:.2rem}
  .indice a{grid-template-columns:2.5rem 1fr 2rem;row-gap:.35rem}
  .indice .que{grid-column:2 / -1}
  /* En apilado la flecha vuelve a la primera fila, a la derecha del nombre: aquí
     el orden del documento ya era el bueno y el `order` de escritorio la
     empujaba debajo de la descripción. */
  .indice .flecha{order:0}
  /* La imagen de apertura pasa arriba: en columna, la foto antes que el
     titular deja el h1 fuera del primer viewport. */
  .ap-rejilla{grid-template-columns:1fr;gap:var(--e-4)}
  .ap-vista{order:2}
  .ap-vista img{aspect-ratio:16/9}
}
@media (max-width:780px){
  /* Dos columnas: hay que rehacer los filetes, porque `li+li` los pinta
     suponiendo una sola fila. */
  /* La rejilla 2x2 de móvil se retira: la placa ya es de una sola columna en
     todos los anchos, así que no hay nada que reordenar aquí. */
}
@media (max-width:820px){
  /* EN MÓVIL LA FOTO TIENE ALTURA PROPIA, NO LA QUE SOBRE
     ------------------------------------------------------------------------
     Con el hero limitado a una pantalla y el zócalo apoyado abajo, el texto
     se come el sitio: medido a 390x844, el zócalo ocupaba 537 px de 692 y la
     foto se quedaba en 155, el **22 %**. En escritorio el reparto sale al
     44 % porque el texto ocupa menos alto, pero en móvil la foto pasaba a ser
     una franja y dejaba de contar nada.

     Así que en móvil el hero deja de caber a la fuerza en una pantalla: la
     foto reclama su 40 % del alto de la ventana y el texto ocupa lo que
     necesite debajo. Se pierde el «hero de una pantalla», que es una
     convención, y se gana que la obra se vea, que es el argumento. */
  .hero{min-height:auto}
  /* 34dvh y no 40. Con 40 el botón «Contar la obra» acababa en el píxel 840 de
     una ventana de 844: entraba, pero por cuatro píxeles, y eso no es que
     entre, es que no ha salido todavía. Cualquier barra de navegador algo más
     alta o una tipografía de reserva lo empujaba fuera del primer viewport, y
     es el botón que sostiene la conversión de la página. */
  .hero-foto{position:static;height:34dvh;min-height:13rem}
  .hero-foto img{height:100%}

  .hamburguesa{display:none}
  .js .hamburguesa{display:flex}
  .menu{padding:0 0 var(--e-2)}
  /* El panel se ajusta a lo que tiene dentro en vez de ocupar la pantalla.
     Con `inset:4.25rem 0 0 0` cubría los 844 px de alto de un iPhone para
     mostrar cuatro enlaces, y dejaba más de mil píxeles de papel vacío debajo.
     Un panel a pantalla completa se justifica cuando hay algo que llenarla;
     para cuatro enlaces es un telón. */
  .js .menu{
    position:fixed;inset:4.25rem 0 auto 0;max-height:calc(100dvh - 4.25rem);
    background:var(--papel);border-bottom:1px solid var(--linea);
    padding:var(--e-3) 1.25rem calc(var(--e-3) + env(safe-area-inset-bottom));
    overflow-y:auto;overscroll-behavior:contain;
    opacity:0;visibility:hidden;transform:translateY(-8px);
    /* LA VISIBILIDAD SE CONMUTA AL INSTANTE AL ABRIR Y CON RETARDO AL CERRAR.
       ------------------------------------------------------------------------
       Estaba como `visibility .32s`, y medido el 13-08-2026 a 390x844 eso
       dejaba los cuatro enlaces del menu con `visibility:hidden` durante los
       320 ms enteros de la apertura: no aceptaban el foco, ni por programa ni
       con el tabulador, hasta que terminaba la transicion. Un panel que tarda
       un tercio de segundo en existir para el teclado.

       `visibility 0s` al abrir lo hace visible en el mismo fotograma, y como
       la opacidad sigue en 0 y sube en 280 ms, en pantalla no cambia nada: la
       entrada se ve igual. Al cerrar, `0s .32s` retrasa el apagado hasta que
       el desvanecido ha terminado, que es lo que la regla anterior conseguia
       por accidente y sigue haciendo falta. */
    transition:opacity .28s var(--ease-out),transform .32s var(--ease-out),visibility 0s .32s;
  }
  .js .menu.abierto{opacity:1;visibility:visible;transform:none;
    transition:opacity .28s var(--ease-out),transform .32s var(--ease-out),visibility 0s}
  .menu>ul{flex-direction:column;align-items:stretch;gap:0}
  .menu li{border-bottom:1px solid var(--filete)}
  .menu li:last-child{border-bottom:0}
  .menu a:not(.btn){display:flex;align-items:center;justify-content:space-between;
    padding:1rem 0;font-size:var(--t-md);font-family:'Big Shoulders';font-weight:700;
    text-transform:uppercase;color:var(--tinta)}
  /* Sin `:not(:last-child)`. Esa condición venía de cuando el último elemento
     de la lista era el botón del teléfono, que no lleva flecha. El teléfono
     salió del menú a la barra el 08-08-2026, así que el último ya es un enlace
     normal y se quedaba sin su flecha mientras los otros tres la tenían. */
  .menu a:not(.btn)::after{content:"\2192";font-family:var(--mono);
    color:var(--tinta-3);font-size:var(--t-sm)}
  /* Aquí había un `.menu .btn{...}` para el botón de teléfono dentro del panel
     desplegable. No aplica a nada desde que el teléfono salió a la barra el
     08-08-2026: `.menu` solo contiene los cuatro enlaces. Se retira. */
  html:not(.js) .cabecera{position:static}
  html:not(.js) .cabecera-int{height:auto;flex-wrap:wrap;padding-block:var(--e-2)}
  .explorador{grid-template-columns:1fr}
  .exp-lista{border-right:0;border-bottom:1px solid var(--filete)}
  .exp-media{min-height:260px;order:-1}
  .exp-detalle{border-top:1px solid var(--filete)}
}
@media (max-width:760px){
  .obra{grid-template-columns:1fr}
  .obra .grande{grid-row:auto}
  .obra .chica img{aspect-ratio:4/3}
  .a-sangre{margin-right:0}
}
@media (max-width:600px){
  :root{--e-6:4.5rem;--e-5:3rem}
  .envoltura,.cabecera-int{width:min(100% - 2rem,var(--ancho))}
  .campo-doble{grid-template-columns:1fr}
  .pie-rejilla{grid-template-columns:1fr;gap:var(--e-3)}
  .hero{min-height:82dvh}
  .hero-acciones .btn{width:100%}
  .hero-ficha{display:none}
  .indice{grid-template-columns:1fr}
  /* EN EL MÓVIL, «OTRAS OBRAS» PIERDE LOS RESÚMENES. 13-08-2026.
     ------------------------------------------------------------------------
     Medido: en un iPhone, este índice ocupa 691 px al final de una página que
     ya lleva ocho pantallas. Son 138 px por enlace, y 80 de esos 138 son un
     resumen de dos o tres líneas que se lee entero al llegar a esa página.

     Aquí el índice no es contenido, es navegación de salida: quien llega ha
     terminado de leer sobre SU obra y está eligiendo si mirar otra. Para eso
     basta el nombre, que es «Taludes» o «Túneles» y no necesita glosa. En
     escritorio se queda, porque ahí ocupa una columna que de todos modos
     estaría vacía y ayuda a decidir sin cambiar de página.

     Se oculta con `display:none` y no visualmente: si el texto no se enseña,
     tampoco se le lee a nadie con lector de pantalla, que estaría escuchando
     cinco resúmenes seguidos para elegir un enlace. El nombre del enlace y el
     `aria-label` del `<nav>` bastan para saber dónde lleva. */
  .indice .que{display:none}
  .apertura{padding-block:var(--e-4) var(--e-3)}
  .apertura-acciones .btn{width:100%}
  .tabla{font-size:var(--t-xs)}
  .tabla th,.tabla td{padding:.65rem .5rem}
  .tabla-caja{overflow-x:auto;-webkit-overflow-scrolling:touch}
}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;scroll-behavior:auto!important;
  }
  .revela{opacity:1;transform:none}
}

/* WCAG 2.2 SC 2.5.8: la casilla de consentimiento daba 17x17 px. */
.consent input[type="checkbox"]{width:24px;height:24px;accent-color:var(--accion-2)}

/* ── PICTURE ──────────────────────────────────────────────────────────────
   `display: contents` hace que el <picture> no exista como caja: sus <source>
   no pintan nada y el <img> queda como hijo directo de lo que fuera su abuelo.

   Sin esto, envolver una imagen en <picture> rompe cualquier regla que dependa
   de la relacion padre-hijo, y aqui hay dos que lo hacen: el explorador
   posiciona `.exp-media img` en absoluto sobre su contenedor, y `.ap-vista img`
   usa `flex-basis: 0`. Las dos dejarian de aplicar al colarse un elemento en
   medio, y no darian ningun error: solo se veria mal. */
picture{display:contents}

/* ── EL TELEFONO EN LA BARRA ──────────────────────────────────────────────
   Estaba dentro de `.menu`, que en movil vive plegado tras la hamburguesa, asi
   que devolvia `visibility: hidden`. Medido a 390 px el 08-08-2026: el primer
   telefono pulsable de verdad aparecia a 6.203 px en la portada, siete
   pantallas de scroll. Ahora vive en la barra y es lo unico que acompana a la
   marca cuando no cabe nada mas.

   El orden visual lo pone `order` y no el HTML, porque en el documento el
   telefono va antes que la hamburguesa a proposito: con teclado se alcanza
   antes la accion que el menu.

   El tamaño de esta pieza ya no se decide aquí: la medida compacta se declara
   una sola vez, en la sección de botones. Lo que queda es lo único que es
   propio de estar en una barra, que el número no se parta en dos líneas. */
.cab-tel{white-space:nowrap}

/* ── AVISO DE COOKIES ─────────────────────────────────────────────────────
   Una placa de papel que sube desde el borde inferior, del mismo material que
   el resto: sin cristal, sin sombra difusa y sin radio nuevo.

   Tres decisiones que NO son de estilo y que no se pueden deshacer sin romper
   el cumplimiento, porque la guia de la AEPD las exige:

   1. `Rechazar` y `Aceptar` llevan la misma clase, el mismo tamano y el mismo
      contraste. Ni el ambar ni el rojo Arnabat pueden destacar uno de los dos.
   2. Es `position: fixed`, no un bloque que empuje el contenido. Un aviso que
      desplaza la pagina al aparecer genera salto de composicion, y ese salto
      entra en la evaluacion de la pagina de destino de Google Ads.
   3. No tapa las acciones de conversion: en movil deja hueco por debajo y el
      cuerpo del aviso puede desplazarse si el texto no cabe. */
.ck{
  position:fixed;left:0;right:0;bottom:0;z-index:120;
  background:var(--papel);border-top:1px solid var(--linea);
  box-shadow:var(--sombra);
  padding:var(--e-3) 0 calc(var(--e-3) + env(safe-area-inset-bottom));
  max-height:min(85dvh,44rem);overflow-y:auto;overscroll-behavior:contain;
}
.ck[hidden]{display:none}
.ck-caja{width:min(100% - 2.5rem,var(--ancho));margin-inline:auto}
.ck-tit{
  font-family:'Big Shoulders';font-weight:800;font-size:var(--t-lg);
  text-transform:uppercase;line-height:1;letter-spacing:.01em;
}
.ck-texto{margin-top:var(--e-2);max-width:68ch;color:var(--tinta-2);font-size:var(--t-sm)}
.ck-texto p+p{margin-top:.6rem}
.ck-acciones{
  margin-top:var(--e-3);display:flex;flex-wrap:wrap;align-items:center;gap:var(--e-2);
}
/* La tercera via. Es un boton de texto y no un tercer boton con marco: tiene
   que verse sin discusion, pero no puede competir en peso con los dos que de
   verdad deciden, que son los que la guia exige que sean iguales entre si. */
.ck-mas{
  font-size:var(--t-xs);letter-spacing:.09em;text-transform:uppercase;font-weight:650;
  color:var(--tinta);text-decoration:underline;text-underline-offset:.35em;
  text-decoration-thickness:1px;text-decoration-color:var(--linea);
  padding:.4rem 0;min-height:44px;display:inline-flex;align-items:center;
}
.ck-mas:hover{text-decoration-color:var(--tinta)}
.ck-pie{margin-top:var(--e-2);font-size:var(--t-xs);color:var(--tinta-3);max-width:68ch}

.ck-grupos{margin-top:var(--e-3);display:grid;gap:var(--e-2)}
.ck-grupo{border-top:1px solid var(--filete);padding-top:var(--e-2)}
.ck-grupo p{margin-top:.4rem;font-size:var(--t-xs);color:var(--tinta-2);max-width:68ch}
.ck-grupo-cab{display:flex;align-items:center;justify-content:space-between;gap:var(--e-2)}
.ck-nombre{
  font-family:var(--mono);font-size:var(--t-xs);letter-spacing:.08em;
  text-transform:uppercase;color:var(--tinta);font-weight:600;
}
.ck-siempre{font-family:var(--mono);font-size:var(--t-xs);color:var(--tinta-3)}

/* El interruptor. Es la palanca de un cuadro de mandos, no un `toggle` de
   aplicacion: rectangulo de esquina viva, y la posicion encendida se marca con
   el ambar de etiqueta de maquina que ya usa el resto del sistema. */
.ck-interruptor{display:flex;align-items:center;gap:.7rem;cursor:pointer;min-height:44px}
.ck-interruptor input{position:absolute;opacity:0;width:0;height:0}
.ck-palanca{
  width:42px;height:22px;border:1.5px solid var(--linea);border-radius:var(--r);
  background:var(--papel-2);position:relative;flex:0 0 auto;
  transition:background .2s var(--ease-out),border-color .2s var(--ease-out);
}
/* El 1 px de radio de la cabeza es la ÚNICA excepción al radio único del
   sistema, y es aritmética, no gusto: para que dos curvas sean concéntricas, el
   radio interior es el exterior menos la separación, o sea 2 - 2 = 0... y con 0
   la cabeza se ve más afilada que su carcasa. 1 px es el término medio y se
   deja escrito aquí para que no parezca un valor suelto olvidado. */
.ck-palanca::after{
  content:"";position:absolute;top:2px;left:2px;width:15px;height:14px;
  background:var(--tinta-3);border-radius:1px;
  transition:translate .22s var(--ease-out),background .22s var(--ease-out);
}
/* La palanca encendida lleva el acento, no el ámbar: encender un grupo de
   cookies es una acción del usuario, no un aviso. La cabeza de la palanca pasa
   a cal, porque sobre este rojo el grafito daría 3,22:1. */
.ck-interruptor input:checked+.ck-palanca{background:var(--accion);border-color:var(--accion-2)}
.ck-interruptor input:checked+.ck-palanca::after{translate:20px 0;background:var(--cal)}
.ck-interruptor input:focus-visible+.ck-palanca{outline:2px solid var(--foco);outline-offset:3px}

/* El enlace permanente del pie: no lleva a ninguna parte, abre el panel aqui
   mismo, asi que es un boton. Se pinta como los enlaces que tiene al lado para
   que no parezca otra cosa. */
.pie-boton{
  color:inherit;font:inherit;text-decoration:underline;text-underline-offset:.25em;
  text-decoration-color:var(--filete-osc-2);
  display:inline-flex;align-items:center;min-height:24px;
}
.pie-boton:hover{text-decoration-color:currentColor}

@media (max-width:820px){
  /* En movil la barra se queda con lo imprescindible: marca, telefono y menu.
     El telefono va antes que la hamburguesa, que es lo que se toca menos. */
  .cab-tel{order:2}
  .hamburguesa{order:3}
  .menu{order:4}
}
@media (max-width:420px){
  /* Cuando el ancho aprieta, lo que se recorta es el relleno del boton, nunca
     el boton. El numero se sigue leyendo entero. */
  .cab-tel{padding:.5rem .7rem;letter-spacing:.02em}
  .marca span{display:none}
}
@media (max-width:370px){
  /* AQUÍ SÍ BAJA LA LETRA, Y ES UN ESCALÓN DECLARADO, NO EL DESCUIDO QUE HABÍA.
     Subir el botón de la barra de 12 a 14 px lo ensancha entre 9 y 14 px, y
     medido a 360 eso partía «GUNITADOS CMG» en dos líneas: caben 328 px de
     barra y hacían falta 336,6. A 375 y a 390, que son los iPhone, entra de
     sobra y la letra se queda en 14.

     Por debajo de 371 px el número baja al escalón más pequeño de la escala,
     que es el mismo recurso que la línea de al lado usa para esconder el
     descriptivo de la marca: en el ancho más apretado el sistema quita cosas
     por regla escrita, no por accidente. */
  /* El relleno vertical sube para compensar la letra: la caja se queda en 42 px
     de alto, que es la de los demás anchos. Lo que encoge es la letra, no el
     objetivo de pulsación. */
  .cab-tel{font-size:var(--t-xs);padding-block:.65rem}
}
@media (max-width:600px){
  .ck-caja{width:min(100% - 2rem,var(--ancho))}
  /* Los dos botones ocupan la mitad cada uno y siguen siendo identicos. */
  .ck-acciones .btn{flex:1 1 calc(50% - var(--e-2))}
  .ck-mas{flex:1 1 100%;justify-content:center}
}
