/* =========================================================================
   estilo.css — web de Franz Gómez · Arte Escénico (diseño v2)

   LAS REGLAS DE LA CASA. No se saltan aunque vuelva a cambiar el diseño.
   Están arriba del todo porque son las que evitan reabrir fallos ya cerrados.

   1. MÓVIL PRIMERO. Lo de arriba es lo que ve un móvil; las @media solo
      AÑADEN cosas para pantallas grandes. Así una pantalla pequeña nunca
      hereda una anchura fija que la desborde. Comprobado de 320 a 1440 px.

   2. NADA DE FUERA, PERO LAS TIPOGRAFÍAS SON PROPIAS. Esta regla cambió el
      2026-10-23 y conviene leer por qué. Antes decía «ni @font-face»: la web
      usaba la tipografía del aparato. Ahora hay dos familias de verdad
      (Playfair Display e Inter), y siguen sin salir de este servidor: los
      .woff2 están en estaticos/fuentes/, se publican en /v/<version>/fuentes/
      y la cabecera Content-Security-Policy sigue siendo font-src 'self'.
      LO QUE NO CAMBIA: ni un @import, ni una url() a otro dominio, ni un
      enlace a fonts.googleapis.com. Si alguien escribe uno, el navegador lo
      bloquea. (La única excepción de toda la política es frame-src para el
      reproductor de vídeo, y solo cuando el visitante pulsa.)

   3. CONTRASTE MEDIDO, NO ESTIMADO. El mínimo que pide WCAG 2.2 AA es 4,5:1
      para texto normal, 3:1 para texto grande y 3:1 para los bordes de los
      controles. Todos los pares que se usan de verdad están calculados y
      anotados en el bloque de fichas de abajo, con su número.

      EL CONTRASTE DEL TEXTO NO PUEDE DEPENDER DEL PÍXEL QUE LE TOQUE DETRÁS.
      Eso no es un detalle de estilo: es lo que hace que el contraste sea un
      número comprobable y no una estimación. La primera versión de la portada
      ponía el texto sobre un degradado encima de la foto, se leía bien, y
      axe-core la dejaba en «no se puede determinar el contraste» con toda la
      razón.

      HAY DOS MANERAS DE CUMPLIRLO, Y SE USAN LAS DOS:
        a) FONDO OPACO. Es lo que hacen .video__rotulo y los botones. Si le
           pones transparencia al fondo de .video__rotulo, LO ROMPES.
        b) VELO CON SUELO MEDIDO. Es lo que hace el héroe desde el 2026-10-24:
           una opacidad MÍNIMA garantizada sobre la zona del texto, con el
           peor caso posible (fotografía blanca del todo) calculado y escrito
           en el propio CSS. Hoy el suelo es 0,80, el peor caso es #333333 y
           el par más apretado da 4,85:1. La tabla entera está en el bloque 7.
           Si bajas ese 0,80, REHAZ LA TABLA. No vale estimarlo a ojo: se
           calcula y se comprueba sustituyendo la fotografía por una imagen
           blanca.

   4. EL FOCO SE VE SIEMPRE, y sobre los dos tonos. Anillo de 2 px con
      separación de 3 px, del color del texto del tono en el que esté (17:1
      sobre tinta, 15:1 sobre papel). Nunca `outline: none`.
      LA ÚNICA EXCEPCIÓN son los títulos de tarjeta de los bloques 8 y 10, y
      está DOCUMENTADA ahí mismo con la condición que la hace válida: el
      anillo se dibuja en la tarjeta entera con :focus-within, porque el área
      que se pulsa es la tarjeta y no las letras. Si alguien quita una de las
      dos reglas tiene que quitar la otra.
      Y EL FOCO NO SE ESCONDE DETRÁS DE LA CABECERA: de eso se encarga el
      scroll-padding-top del bloque 3 (WCAG 2.2 AA, 2.4.11).

   5. SIN UNIDADES FIJAS PARA EL TEXTO. Todo en rem/em, de modo que si el
      visitante agranda la letra del navegador, la web crece con ella. Los
      clamp() van en rem + vw, nunca en px.

   6. OBJETIVOS DE PULSACIÓN DE 44 px. Todo lo que se pulsa (menú, botones,
      entradas de la cartelera, fachadas de vídeo) tiene 2.75rem de alto
      mínimo y 2.75rem de ancho mínimo.

   7. EL MOVIMIENTO NO ESCONDE NADA. Las apariciones viven DENTRO de
      @media (prefers-reduced-motion: no-preference) y su estado inicial es
      visible: la animación solo retrasa, nunca oculta. Sin JavaScript y con
      el movimiento reducido, la web se ve entera. No hay carruseles.

   CÓMO ESTÁ ORGANIZADO ESTO
   Dos tonos que alternan por secciones. Cada sección declara su tono con UNA
   clase (.tono--tinta, .tono--tinta-honda, .tono--papel, .tono--papel-hondo)
   y esa clase redefine cuatro variables locales: --fondo, --letra,
   --letra-2, --acento, --rotulo, --filete, --borde. TODOS los componentes
   usan esas variables, así que el mismo componente funciona sobre los dos
   tonos sin una sola regla duplicada.
   ========================================================================= */


/* ======================================================================
   1. TIPOGRAFÍAS PROPIAS

   Dos familias, subconjunto «latin», en woff2 y servidas desde aquí.
   108 KB las tres caras juntas (38,4 + 21,9 + 48,3), por debajo del tope de
   140 KB que fija el plan.

   font-display: swap — el texto se lee desde el primer momento con la
   tipografía de reserva y cambia cuando llega la propia. Nunca hay un hueco
   en blanco esperando a una fuente.

   unicode-range — el del subconjunto latin de Google. Si en un texto aparece
   un carácter que no está en ese rango (una flecha →, por ejemplo), el
   navegador NI SIQUIERA pide el fichero y lo pinta con la fuente de reserva.
   Por eso las flechas de esta hoja se dibujan con SVG y no con caracteres.

   Los dos ficheros «normales» son fuentes variables: el mismo fichero sirve
   para el peso 400 y para el 600, así que declararlos dos veces NO descarga
   nada dos veces. Es lo que hace Google en su propio CSS.
   ====================================================================== */

@font-face {
  font-family: "Playfair Display";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fuentes/playfair-display-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: "Playfair Display";
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fuentes/playfair-display-latin-cursiva.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;
}

/* ----------------------------------------------------------------------
   LAS DOS CARAS DE RESERVA, CON LAS MEDIDAS CORREGIDAS

   El problema que resuelven: con font-display: swap, el texto se pinta
   primero con la fuente del sistema y después cambia. Si las dos fuentes no
   miden lo mismo, la página DA UN SALTO en ese momento. Además de feo es un
   fallo de accesibilidad: alguien que iba a pulsar un enlace acaba pulsando
   otro.

   La solución son estas dos caras intermedias. No descargan nada (src: local)
   y llevan las medidas de la fuente de verdad, así que el intercambio no
   mueve el texto.

   LOS NÚMEROS ESTÁN MEDIDOS, no copiados. Se midieron el 2026-10-23 en
   Chromium 155 con canvas.measureText a 1000 px, sobre una muestra en
   castellano:

                      ascenso  descenso  ancho de la muestra
     Playfair Display  1,082    0,251     38,870 em
     Inter             0,969    0,241     42,199 em
     Liberation Serif  0,891    0,216     36,350 em   (= medidas de Times New Roman)
     Liberation Sans   0,905    0,212     40,077 em   (= medidas de Arial)

   De ahí salen:
     size-adjust serif = 38,870 / 36,350 = 106,9 %
     size-adjust sans  = 42,199 / 40,077 = 105,3 %
   y los ascent/descent-override, que se aplican ANTES de size-adjust (o sea
   que el valor final es override × size-adjust: comprobado midiéndolo, no
   leyéndolo):
     serif: 1,082 / 1,069 = 101,2 %   y   0,251 / 1,069 = 23,5 %
     sans:  0,969 / 1,053 =  92,0 %   y   0,241 / 1,053 = 22,9 %

   Comprobación final: con estos valores la cara de reserva mide ascenso
   1,082, descenso 0,251 y 38,858 em de ancho, frente a los 38,870 em de
   Playfair. La diferencia es de tres diezmilésimas: el salto desaparece.

   Por qué Times New Roman y Arial y no Georgia: son las dos únicas fuentes de
   las que se pueden MEDIR las medidas aquí mismo (Liberation Serif y
   Liberation Sans son métricamente idénticas) y están en Windows, en macOS y,
   vía Liberation, en Linux. Georgia sigue en la pila de reserva de más abajo,
   detrás de estas caras, por si acaso.
   ---------------------------------------------------------------------- */

@font-face {
  font-family: "Playfair reserva";
  src: local("Times New Roman"), local("Liberation Serif"), local("Nimbus Roman"),
       local("Tinos"), local("DejaVu Serif");
  ascent-override: 101.2%;
  descent-override: 23.5%;
  line-gap-override: 0%;
  size-adjust: 106.9%;
}

@font-face {
  font-family: "Inter reserva";
  src: local("Arial"), local("Liberation Sans"), local("Helvetica Neue"),
       local("Arimo"), local("DejaVu Sans");
  ascent-override: 92%;
  descent-override: 22.9%;
  line-gap-override: 0%;
  size-adjust: 105.3%;
}


/* ======================================================================
   2. LAS FICHAS

   Los contrastes de esta tabla están calculados con la fórmula de WCAG 2.x,
   no estimados a ojo. Dos de los valores del plan no llegaban al 4,5:1 y se
   han corregido aquí, que es lo que el propio plan manda hacer:

     --rojo-vivo  era #cf4d3d  -> 4,30:1 sobre tinta.  AHORA #d25647 -> 4,64:1
     --oro-hondo  era #8a6420  -> 4,01:1 sobre papel-hondo. AHORA #7e5b1d -> 4,62:1

   TABLA DE CONTRASTES (letra sobre fondo):

     crema         #f6f3ed  sobre tinta       #121110   17,03:1
     crema         #f6f3ed  sobre tinta-honda #0b0a09   17,86:1
     crema-apagada #cdc6ba  sobre tinta       #121110   11,12:1
     crema-tenue   #aaa49a  sobre tinta       #121110    7,62:1
     oro           #c29a5b  sobre tinta       #121110    7,25:1
     oro           #c29a5b  sobre tinta-honda #0b0a09    7,60:1
     rojo-vivo     #d25647  sobre tinta       #121110    4,64:1
     rojo-vivo     #d25647  sobre tinta-honda #0b0a09    4,86:1
     tinta-texto   #1c1a17  sobre papel       #f2eee7   15,01:1
     tinta-texto   #1c1a17  sobre papel-hondo #e5ded4   13,01:1
     tinta-apagada #4f4941  sobre papel       #f2eee7    7,69:1
     tinta-apagada #4f4941  sobre papel-hondo #e5ded4    6,66:1
     oro-hondo     #7e5b1d  sobre papel       #f2eee7    5,34:1
     oro-hondo     #7e5b1d  sobre papel-hondo #e5ded4    4,62:1
     rojo          #9f3025  sobre papel       #f2eee7    6,21:1
     rojo          #9f3025  sobre papel-hondo #e5ded4    5,38:1
     blanco        #ffffff  sobre rojo        #9f3025    7,18:1   (texto de los botones)
     blanco        #ffffff  sobre rojo-hover  #8b2a20    8,57:1   (.boton:hover)

   BORDES DE CONTROL (piden 3:1, no 4,5:1):
     borde-tinta   #787167  sobre tinta       #121110    3,91:1
     borde-papel   #7a7369  sobre papel       #f2eee7    4,05:1

   DECORACIÓN PURA (filetes de separación: no son texto ni control, no les
   aplica mínimo):
     filete-tinta  #3a3630  sobre tinta       #121110    1,57:1
     filete-papel  #c3b9a8  sobre papel       #f2eee7    1,68:1

   AVISOS:
     provisional sobre tinta #ffc266 / #121110  11,82:1
     provisional sobre papel #7e5b1d / #f2eee7   5,34:1
     error       sobre tinta #ff9b9b / #121110   9,35:1
     error       sobre papel #9e2b20 / #f2eee7   6,44:1
     correcto    sobre tinta #a8d5a2 / #121110  11,41:1
     correcto    sobre papel #1f6b3a / #f2eee7   5,64:1

   DOS PROHIBICIONES QUE SALEN DE LA TABLA:
     - El ORO (#c29a5b) NO se usa nunca sobre papel: da 2,25:1. Sobre papel el
       rótulo va en --oro-hondo.
     - El ROJO-VIVO (#d25647) NO se usa como fondo con texto encima: con crema
       encima da 3,67:1. Como fondo de botón se usa el --rojo (#9f3025), que
       con blanco da 7,18:1.
   ====================================================================== */

:root {
  /* fondos */
  --tinta:          #121110;
  --tinta-honda:    #0b0a09;
  --papel:          #f2eee7;
  --papel-hondo:    #e5ded4;

  /* letra */
  --crema:          #f6f3ed;
  --crema-apagada:  #cdc6ba;
  --crema-tenue:    #aaa49a;
  --tinta-texto:    #1c1a17;
  --tinta-apagada:  #4f4941;

  /* acentos */
  --rojo:           #9f3025;
  --rojo-vivo:      #d25647;
  --oro:            #c29a5b;
  --oro-hondo:      #7e5b1d;

  /* líneas */
  --filete-tinta:   #3a3630;
  --filete-papel:   #c3b9a8;
  --borde-tinta:    #787167;
  --borde-papel:    #7a7369;

  /* avisos */
  --prov-tinta:     #ffc266;
  --prov-papel:     #7e5b1d;
  --error-tinta:    #ff9b9b;
  --error-papel:    #9e2b20;
  --bien-tinta:     #a8d5a2;
  --bien-papel:     #1f6b3a;

  /* tipografías */
  --serif: "Playfair Display", "Playfair reserva", Georgia, "Times New Roman",
           Times, serif;
  --sans:  "Inter", "Inter reserva", system-ui, -apple-system, "Segoe UI",
           Roboto, Arial, sans-serif;

  /* rejilla editorial */
  --lienzo:  86.25rem;                    /* 1380 px a 16 px de base */
  --canal:   clamp(1.25rem, 5vw, 4.75rem); /* 20 px -> 76 px */
  --prosa:   40rem;

  /* ritmo vertical */
  --aire:     clamp(3.5rem, 9vw, 8rem);
  --aire-mini: clamp(2rem, 5vw, 3.5rem);

  /* ALTO DE LA CABECERA FIJA. No es decoración: de esta variable dependen dos
     cosas que se rompían sin ella (ver bloque 4).
       1. html { scroll-padding-top }, para que lo que recibe el foco no quede
          escondido detrás de la cabecera (WCAG 2.2 AA, 2.4.11).
       2. el alto máximo del panel del menú desplegado, para que a 400 % de
          zoom se pueda llegar a todas las secciones (WCAG 1.4.10).
     Los dos valores están MEDIDOS en pantalla, no estimados, y hay que
     volverlos a medir si se cambia la cabecera o la píldora de demo.
     MEDIDO el 2026-10-24, con el menú plegado y la píldora de demo cerrada:
       320 px de ancho ... 143 px   <- el caso peor en móvil (la frase de la
       390 px de ancho ... 123 px      píldora se parte en dos líneas)
       568 px de ancho ... 123 px
       1440 px de ancho .. 133 px   <- en escritorio el logotipo es más grande
     O sea que en escritorio la cabecera es MÁS ALTA que en un móvil de 390,
     pero menos que en uno de 320. Por eso el valor de móvil cubre los 143 y el
     de escritorio los 133, y no al revés: no es un descuido.
     Se redondea hacia arriba para que un píxel de más no deje la línea de foco
     pegada al borde. */
  --alto-cabecera: 9.25rem;       /* 148 px: 143 medidos + holgura */

  /* La flecha de los enlaces «seguir leyendo», dibujada en SVG. No se usa el
     carácter → porque no está en el subconjunto latin de las tipografías y el
     navegador lo pintaría con otra familia distinta. */
  --flecha: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 16'%3E%3Cpath d='M0 7h19.2L14 1.4 15.3 0 24 8l-8.7 8L14 14.6 19.2 9H0z'/%3E%3C/svg%3E");

  /* tono por omisión: tinta */
  --fondo:   var(--tinta);
  --letra:   var(--crema);
  --letra-2: var(--crema-apagada);
  --letra-3: var(--crema-tenue);
  --acento:  var(--rojo-vivo);
  --rotulo:  var(--oro);
  --filete:  var(--filete-tinta);
  --borde:   var(--borde-tinta);
  --prov:    var(--prov-tinta);
  --error:   var(--error-tinta);
  --bien:    var(--bien-tinta);
  --tarjeta: var(--tinta-honda);
}

/* Los cuatro tonos. UNA clase cambia la sección entera. */
.tono--tinta {
  --fondo: var(--tinta);  --letra: var(--crema);  --letra-2: var(--crema-apagada);
  --letra-3: var(--crema-tenue); --acento: var(--rojo-vivo); --rotulo: var(--oro);
  --filete: var(--filete-tinta); --borde: var(--borde-tinta);
  --prov: var(--prov-tinta); --error: var(--error-tinta); --bien: var(--bien-tinta);
  --tarjeta: var(--tinta-honda);
  color-scheme: dark;
}
.tono--tinta-honda {
  --fondo: var(--tinta-honda); --letra: var(--crema); --letra-2: var(--crema-apagada);
  --letra-3: var(--crema-tenue); --acento: var(--rojo-vivo); --rotulo: var(--oro);
  --filete: var(--filete-tinta); --borde: var(--borde-tinta);
  --prov: var(--prov-tinta); --error: var(--error-tinta); --bien: var(--bien-tinta);
  --tarjeta: var(--tinta);
  color-scheme: dark;
}
.tono--papel {
  --fondo: var(--papel); --letra: var(--tinta-texto); --letra-2: var(--tinta-apagada);
  --letra-3: var(--tinta-apagada); --acento: var(--rojo); --rotulo: var(--oro-hondo);
  --filete: var(--filete-papel); --borde: var(--borde-papel);
  --prov: var(--prov-papel); --error: var(--error-papel); --bien: var(--bien-papel);
  --tarjeta: var(--papel-hondo);
  color-scheme: light;
}
.tono--papel-hondo {
  --fondo: var(--papel-hondo); --letra: var(--tinta-texto); --letra-2: var(--tinta-apagada);
  --letra-3: var(--tinta-apagada); --acento: var(--rojo); --rotulo: var(--oro-hondo);
  --filete: var(--filete-papel); --borde: var(--borde-papel);
  --prov: var(--prov-papel); --error: var(--error-papel); --bien: var(--bien-papel);
  --tarjeta: var(--papel);
  color-scheme: light;
}

.tono--tinta, .tono--tinta-honda, .tono--papel, .tono--papel-hondo {
  background: var(--fondo);
  color: var(--letra);
}


/* ======================================================================
   3. CIMIENTOS
   ====================================================================== */

*, *::before, *::after { box-sizing: border-box; }

/* En escritorio el menú cabe en horizontal y la cabecera es más baja. El
   corte es el MISMO que usa el menú (48em): si se cambia uno, se cambia el
   otro, o el hueco reservado dejará de coincidir con la cabecera de verdad. */
@media (min-width: 48em) {
  :root { --alto-cabecera: 8.75rem; }   /* 140 px: 133 medidos + holgura */
}

/* LA FRANJA DE TABLETA, QUE NADIE HABÍA MEDIDO (cerrada el 2026-10-24).
   De 768 a 941 px el menú ya está en horizontal (el corte es 48em) pero los
   siete enlaces NO caben en una línea y se envuelven en DOS. Eso sube la
   cabecera a 164 px, mientras la variable decía 140: 24 px de menos.
   Consecuencia medida antes del arreglo: al tabular quedaban TRES elementos
   tapados EN PARTE por la cabecera fija. Seguía cumpliendo el nivel AA (2.4.11
   exige que no queden tapados DEL TODO), pero un cambio de tipografía o una
   palabra más larga en el menú lo convertía en fallo de verdad.

   MEDIDO, no estimado, el 2026-10-24 sobre la web servida, con el menú plegado
   y la píldora de demo cerrada:
     767 px ... 122,59   <- todavía con el botón de móvil
     768 px ... 164,17   <- empieza la franja: menú en horizontal, DOS líneas
     941 px ... 164,17   <- último ancho con dos líneas
     942 px ... 132,58   <- el menú ya cabe en una línea
   Los bordes están buscados por bisección, uno a uno.

   OJO AL NÚMERO: el borrador del plan hablaba de «entre 768 y 928 px». La
   medición dice 941, no 928. Se deja escrito el valor medido.

   POR QUÉ EL TOPE ES 58.875em (942 px) Y NO 58.8125em (941 px), que sería el
   exacto: entre 941 y 942 px hay anchuras fraccionarias de verdad (las produce
   el zoom del navegador), y ahí la cabecera sigue midiendo 164. Con el tope
   exacto, esas anchuras se quedarían fuera de esta regla y volverían a
   reservar 140 px, o sea el fallo otra vez. Con 942 px, lo único que pasa en
   ese píxel concreto es que se reserva de más, que no rompe nada: reservar de
   más solo baja un poco lo que recibe el foco; reservar de menos lo esconde. */
@media (min-width: 48em) and (max-width: 58.875em) {
  :root { --alto-cabecera: 10.75rem; }  /* 172 px: 164,17 medidos + holgura */
}

/* Y SI EL VISITANTE DESPLIEGA LA PÍLDORA DE DEMO, la cabecera crece y el hueco
   reservado tiene que crecer con ella, o lo que reciba el foco volvería a
   quedar debajo.
   DONDE NO HAYA :has() (navegadores anteriores a 2023) esta regla no se
   aplica y queda el valor de antes, que es exactamente el comportamiento de
   hoy: se degrada a lo que había, no a algo peor.

   AJUSTADO EL 2026-10-24, al medir la franja de tableta. Con la píldora
   abierta, entre 768 y 941 px la cabecera mide 200,17 px y aquí decía 200: se
   quedaba corta por 0,17 px. Eso no esconde nada, pero una variable que dice
   200 cuando la cosa mide 200,17 es una variable equivocada, y el día que
   alguien sume una línea deja de ser un detalle. Medido con la píldora
   abierta: 196,69 a 320 px, 176,59 a 390, 200,17 de 768 a 941 y 168,58 a 1440.
   13rem son 208 px, que cubre el caso peor con holgura.
   Esta regla GANA a los dos :root de arriba, también al de la franja, porque
   :has(.demo[open]) es más específico que :root: vale para cualquier anchura y
   no hay que repetirla dentro de cada media. */
html:has(.demo[open]) { --alto-cabecera: 13rem; }   /* 208 px: 200,17 medidos + holgura */

html {
  background: var(--tinta);
  color-scheme: dark;
  -webkit-text-size-adjust: 100%;
  scroll-behavior: auto;

  /* EL FOCO NO SE ESCONDE DETRÁS DE LA CABECERA (WCAG 2.2 AA, 2.4.11 «Focus
     Not Obscured»). La cabecera es position: sticky, así que sin esto todo lo
     que el navegador «lleva a la vista» —tabular hacia atrás, pulsar un
     ancla, el autofocus del resumen de errores del formulario— acababa
     justo debajo de ella y no se veía. Medido antes del arreglo: tabulando
     hacia atrás en la portada quedaban 2 elementos tapados del todo a 1440 px
     y 3 a 390 px, y el campo al que lleva un error del formulario quedaba
     ENTERO detrás de la cabecera.
     Sin una línea de JavaScript: es el navegador quien lo tiene en cuenta. */
  scroll-padding-top: var(--alto-cabecera);
}

/* El desplazamiento suave solo si el visitante no ha pedido lo contrario. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  margin: 0;
  background: var(--tinta);
  color: var(--crema);
  font-family: var(--sans);
  font-size: 100%;
  line-height: 1.65;
  /* Ni un desbordamiento horizontal, pase lo que pase con una foto o con una
     palabra larga. */
  overflow-x: hidden;
}

img, picture, svg { max-width: 100%; }
img { height: auto; }

h1, h2, h3, h4 {
  font-family: var(--serif);
  font-weight: 400;
  line-height: 1.06;
  letter-spacing: -0.012em;
  text-wrap: balance;
  margin: 0;
}

p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }

a { color: inherit; }

/* EL FOCO, LO PRIMERO, para que no lo pise ninguna regla posterior.
   currentColor: sobre tinta sale crema (17:1) y sobre papel sale tinta
   (15:1), así que se ve en los dos tonos sin escribirlo dos veces. */
:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
  border-radius: 1px;
}

::selection { background: var(--rojo); color: #ffffff; }

.lienzo {
  width: 100%;
  max-width: var(--lienzo);
  margin-inline: auto;
  padding-inline: var(--canal);
}

/* Solo para lectores de pantalla. */
.oculto-visual {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}


/* --------------------------------------------------- saltar al contenido
   Plegado (alto 0) hasta que recibe el foco, y entonces se despliega y
   empuja la página hacia abajo.

   NO se usa display:none ni visibility:hidden: eso lo sacaría del orden de
   tabulación y dejaría de existir justo para quien lo necesita.

   Y NO se usa position:absolute con un transform, que es la receta habitual,
   por una razón concreta: htmlcs (el segundo analizador de la auditoría) no
   sabe calcular el contraste de un elemento posicionado en absoluto, porque
   no puede saber qué hay debajo, y lo deja en «requiere revisión manual».
   Aquí el enlace está en el flujo normal y lleva su propio fondo opaco, así
   que el contraste es comprobable por una máquina. Cuesta un empujón de la
   página al enfocarlo, que solo ve quien va con teclado y que además le avisa
   de dónde está. */
.saltar {
  display: block;
  height: 0;
  overflow: hidden;
  background: var(--papel);
  color: var(--tinta-texto);
  font-family: var(--sans);
  font-size: 0.9375rem;
  font-weight: 600;
  text-decoration: underline;
  text-align: center;
}
.saltar:focus {
  height: auto;
  padding: 0.9rem var(--canal);
}


/* ======================================================================
   4. CABECERA

   Logotipo a la izquierda, menú a la derecha y «Entradas» como botón
   perfilado. Eso es lo que pedía el plan y es justo lo contrario de la v1
   (menú centrado, logotipo convertido en titular).

   EL FONDO SE OPACA AL BAJAR, Y SIN UNA LÍNEA DE JAVASCRIPT. Se hace con
   animation-timeline: scroll(), que es CSS puro: mientras la página está
   arriba la cabecera es transparente y deja ver la fotografía del héroe, y en
   cuanto se baja un poco se vuelve opaca. Donde el navegador no lo soporta
   (Firefox y Safari, hoy) la cabecera se queda OPACA desde el principio, que
   es el estado seguro: el texto del menú nunca se queda sobre la fotografía.
   ====================================================================== */

.cabecera {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--tinta);
  border-bottom: 1px solid var(--filete-tinta);
  --letra: var(--crema);
  --letra-2: var(--crema-apagada);
  --rotulo: var(--oro);
  --filete: var(--filete-tinta);
  color: var(--crema);
}

@supports (animation-timeline: scroll()) {
  @media (min-width: 48em) {
    .cabecera--portada {
      background: transparent;
      border-bottom-color: transparent;
      animation: posarse linear both;
      animation-timeline: scroll();
      animation-range: 0 12rem;
    }
    @keyframes posarse {
      from { background-color: rgba(18, 17, 16, 0); border-bottom-color: rgba(58, 54, 48, 0); }
      to   { background-color: rgba(18, 17, 16, 1); border-bottom-color: rgba(58, 54, 48, 1); }
    }
  }
}

.cabecera__caja {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 4.25rem;
  padding-block: 0.6rem;
}

.cabecera__marca {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
  min-height: 2.75rem;
  text-decoration: none;
}
.cabecera__marca picture { display: block; }
.cabecera__marca img {
  display: block;
  width: 8.5rem;
  height: auto;
}
@media (min-width: 48em) {
  .cabecera__marca img { width: 10.5rem; }
}

/* --- el botón del menú (solo móvil, y solo si hay JavaScript) ------------
   Viene con el atributo «hidden» desde el servidor y lo quita menu.js. Sin
   JavaScript no aparece y la lista se queda desplegada, que es lo correcto:
   un botón que no hace nada sería peor que no tener botón. */
.menu__boton {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  min-height: 2.75rem;
  min-width: 2.75rem;
  padding: 0.4rem 0.7rem;
  border: 1px solid var(--borde-tinta);
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
}
.menu__boton[hidden] { display: none; }

.menu__rayas {
  display: block;
  width: 1.15rem;
  height: 0.6rem;
  border-top: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
}

@media (min-width: 48em) {
  .menu__boton { display: none !important; }
}

.menu__lista {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.15rem 0.35rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.menu__enlace {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0.25rem 0.6rem;
  color: var(--crema-apagada);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
}
.menu__enlace:hover { color: var(--crema); }
.menu__enlace.es-actual {
  color: var(--crema);
  box-shadow: inset 0 -1px 0 0 var(--oro);
}

/* «Entradas», perfilado. */
.menu__enlace--entradas {
  border: 1px solid var(--borde-tinta);
  color: var(--crema);
  margin-left: 0.35rem;
}
.menu__enlace--entradas:hover { border-color: var(--oro); }
.menu__enlace--entradas.es-actual { box-shadow: none; border-color: var(--oro); }

/* En móvil el menú es una columna debajo de la cabecera. */
@media (max-width: 47.99em) {
  .cabecera__caja { flex-wrap: wrap; }
  .menu {
    flex-basis: 100%;
    order: 3;

    /* EL PANEL DESPLEGADO CABE EN LA VENTANA, SIEMPRE (WCAG 1.4.10 «Reflow»).
       El fallo que arregla, medido el 2026-10-24: a 320x256 px —el caso de
       prueba exacto de 400 % de zoom— la cabecera con el menú abierto medía
       526 px dentro de una ventana de 256, y como es position: sticky
       desplazarse no servía de nada: Videoblog, Entradas y Contacto no se
       podían ver NUNCA. Pasaba también a 568x320, que es un móvil normal en
       apaisado.
       Con esto el panel se queda con lo que sobra de la ventana y se
       desplaza por dentro. CSS puro: menu.js no se entera. */
    max-height: calc(100dvh - var(--alto-cabecera));
    overflow-y: auto;
    /* El desplazamiento del panel se queda en el panel y no arrastra la
       página entera cuando se llega al final. */
    overscroll-behavior: contain;
  }
  .menu[hidden] { display: none; }

  /* EL ESTADO PLEGADO NO DEPENDE DE QUE menu.js HAYA LLEGADO.
     La lista llega DESPLEGADA del servidor (lo correcto sin JavaScript) y
     menu.js, que va con defer, la plegaba DESPUÉS de pintar: la página pegaba
     un bote de 347 px hacia arriba (CLS 0,382 en /blog, /entradas y
     /contacto, donde la v1 medía 0).
     Ahora la clase «js» la pone estaticos/js/clase-js.js en el <head> y SIN
     defer, o sea antes del primer pintado, así que el navegador dibuja la
     cabecera ya plegada y no hay nada que mover.
     Sin JavaScript no hay clase «js» y todo sigue como estaba: lista
     desplegada y ningún botón.
     OJO: menu.js pone y quita la clase «menu--abierto» ADEMÁS del atributo
     hidden. Hacen falta las dos: el atributo es lo que cuenta la verdad al
     lector de pantalla y la clase es lo que gana a esta regla. */
  html.js .menu { display: none; }
  html.js .menu.menu--abierto { display: block; }

  .menu__lista {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    border-top: 1px solid var(--filete-tinta);
    padding-block: 0.25rem 0.75rem;
  }
  .menu__enlace {
    justify-content: flex-start;
    padding-inline: 0;
  }
  .menu__enlace--entradas {
    margin-left: 0;
    margin-top: 0.5rem;
    justify-content: center;
  }
}

/* --- la píldora de demo, dentro de la cabecera --------------------------

   UN SOLO AVISO POR PÁGINA, Y DE UNA LÍNEA. Antes la banda traía la frase
   entera: 92 px de alto en un móvil de 390 px, o sea más de la mitad de los
   161 px que medía la cabecera, y el primer tercio de la pantalla. Ahora la
   píldora es la línea corta y la explicación larga se despliega al pulsarla.

   Es un <details>/<summary>, o sea CSS y HTML y ni una línea de JavaScript:
   el navegador se encarga del aria-expanded y del teclado. Lo único que hace
   el CSS es quitar el triángulo que pinta el navegador (que no se puede
   colocar ni dar color) y dibujar el suyo, que hereda currentColor. */
.demo {
  margin: 0;
  padding-block: 0 0.6rem;
  color: var(--crema-tenue);
  font-size: 0.75rem;
  line-height: 1.5;
}

.demo__pildora,
.demo--llana {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  /* Regla 6 de la casa: 2.75rem de alto para todo lo que se pulsa. Y de paso
     fija el alto de la banda aunque la frase se parta en dos líneas en una
     pantalla estrecha: 2 líneas de 0.75rem miden 36 px y caben dentro. */
  min-height: 2.75rem;
}
.demo__pildora {
  cursor: pointer;
  /* El marcador del navegador se quita por los dos caminos que existen. */
  list-style: none;
}
.demo__pildora::-webkit-details-marker { display: none; }

/* El indicador de «esto se abre», dibujado: media caja girada 45°. No es un
   carácter ▸ porque no está en el subconjunto latin de las tipografías y el
   navegador lo pintaría con otra familia (misma razón que la flecha de
   .enlace-mas). Hereda currentColor, así que su contraste es el del texto. */
.demo__pildora::after {
  content: "";
  flex: 0 0 auto;
  width: 0.4rem;
  height: 0.4rem;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  transform: translateY(-0.12em) rotate(45deg);
}
.demo[open] > .demo__pildora::after {
  transform: translateY(0.1em) rotate(-135deg);
}

.demo__frase { flex: 1 1 14rem; }

.demo__detalle {
  max-width: var(--prosa);
  margin: 0 0 0.35rem;
  color: var(--crema-tenue);
}

.demo__etiqueta {
  flex: 0 0 auto;
  border: 1px solid var(--prov-tinta);
  padding: 0.05rem 0.45rem;
  color: var(--prov-tinta);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}


/* ======================================================================
   5. REJILLA EDITORIAL Y CABECERA DE SECCIÓN

   LO QUE SE CORRIGE DE LA PREVIA: allí el rótulo ocupaba una columna entera
   y el titular arrancaba a mitad de página, con un hueco raro a la izquierda.
   Aquí el rótulo va en la columna 1, el titular y la entradilla van de la 3 a
   la 9, y lo que queda a la derecha es margen óptico a propósito.
   ====================================================================== */

.seccion {
  padding-block: var(--aire);
}
.seccion + .seccion { border-top: 0; }

.rejilla-12 {
  display: grid;
  gap: 1.25rem;
  grid-template-columns: 1fr;
}
@media (min-width: 62em) {
  .rejilla-12 {
    grid-template-columns: repeat(12, 1fr);
    column-gap: 1.5rem;
  }
}

.cab-seccion {
  margin-bottom: var(--aire-mini);
}
.cab-seccion__rotulo {
  grid-column: 1 / -1;
  margin: 0 0 0.75rem;
  color: var(--rotulo);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}
.cab-seccion__cuerpo { grid-column: 1 / -1; }

@media (min-width: 62em) {
  .cab-seccion__rotulo {
    grid-column: 1 / span 2;
    /* alineado con la primera línea del titular, no con su caja */
    margin-top: 0.7rem;
  }
  .cab-seccion__cuerpo { grid-column: 3 / span 7; }
}

.cab-seccion__indice {
  display: inline-block;
  margin-right: 0.6rem;
  color: var(--acento);
  font-variant-numeric: tabular-nums;
}

.titular {
  font-size: clamp(2.25rem, 1.1rem + 5vw, 4.5rem);
}
.titular--mediano {
  font-size: clamp(1.9rem, 1rem + 3.6vw, 3.25rem);
}

.entradilla {
  max-width: 34em;
  margin-top: 1.1rem;
  color: var(--letra-2);
  font-size: clamp(1rem, 0.95rem + 0.3vw, 1.125rem);
}
.entradilla p:last-child { margin-bottom: 0; }

.prosa {
  max-width: var(--prosa);
  color: var(--letra-2);
}
.prosa h2, .prosa h3, .prosa h4 {
  margin: 1.8em 0 0.5em;
  color: var(--letra);
  font-size: 1.5rem;
}
.prosa h2:first-child, .prosa h3:first-child { margin-top: 0; }
.prosa ul { margin: 0 0 1em; padding-left: 1.2em; }
.prosa li { margin-bottom: 0.35em; }
.prosa a { color: var(--letra); text-underline-offset: 0.2em; }

/* LA CITA ES EL ÚNICO SITIO CON CURSIVA, y por eso existe el tercer fichero
   de fuente (playfair-display-latin-cursiva.woff2, 21,9 KB). Si algún día se
   quita la cursiva de aquí, ese fichero deja de pedirse y hay que quitarlo
   también del repositorio: una fuente que no usa nadie es peso muerto. */
.prosa blockquote,
.cita {
  margin: 1.5em 0;
  padding-left: 1.1rem;
  border-left: 2px solid var(--acento);
  color: var(--acento);
  font-family: var(--serif);
  font-size: clamp(1.35rem, 1.1rem + 1vw, 1.95rem);
  font-style: italic;
  line-height: 1.3;
}
.prosa blockquote p, .cita p { margin: 0; }

.nota {
  max-width: var(--prosa);
  color: var(--letra-3);
  font-size: 0.9375rem;
}


/* ======================================================================
   6. BOTONES

   Dos: el lleno (rojo con blanco, 7,18:1) y el fantasma (perfilado, hereda
   el color de la letra del tono). Los dos miden 2.75rem de alto mínimo.
   ====================================================================== */

.boton,
.boton--fantasma {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.75rem;
  min-width: 2.75rem;
  padding: 0.7rem 1.5rem;
  border: 1px solid transparent;
  font-family: var(--sans);
  font-size: 0.78125rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
}

.boton {
  background: var(--rojo);
  border-color: var(--rojo);
  color: #ffffff;
}
.boton:hover { background: #8b2a20; border-color: #8b2a20; }

/* VACUNA, NO ARREGLO DE UN FALLO DE HOY. El anillo de :focus-visible usa
   currentColor, y el color de .boton es #ffffff porque va sobre rojo. Pero el
   anillo se dibuja FUERA del botón, o sea sobre el fondo de la sección, no
   sobre el rojo. Hoy no pasa nada porque ningún botón de esta web vive sobre
   un tono claro. El día que alguien ponga uno en una sección papel, el anillo
   sería blanco sobre papel: 1,16:1 sobre #f2eee7 y 1,33:1 sobre #e5ded4, o
   sea invisible, y nadie se daría cuenta hasta que alguien intentara navegar
   con el teclado. (El informe de accesibilidad daba 1,04:1 para este par: el
   número exacto, calculado con la fórmula de WCAG 2.x contra los dos fondos
   de papel que existen en esta hoja, es el de arriba. El fondo cambia, la
   conclusión no.)
   var(--letra) es el color del texto del tono en el que esté el botón: 17:1
   sobre tinta y 15:1 sobre papel. Una línea, y el problema no puede pasar. */
.boton:focus-visible { outline-color: var(--letra); }

.boton--fantasma {
  background: transparent;
  border-color: var(--borde);
  color: var(--letra);
}
.boton--fantasma:hover { border-color: var(--letra); }

.acciones {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 1.75rem 0 0;
}

/* El enlace «seguir leyendo» de las tarjetas: versalitas con filete y una
   flecha DIBUJADA (SVG en un data:, que img-src 'self' data: sí permite).
   No es el carácter →, que no está en el subconjunto latin de las fuentes y
   obligaría al navegador a pintarlo con otra familia distinta. */
.enlace-mas {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 2.75rem;
  color: var(--letra);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  box-shadow: inset 0 -1px 0 0 var(--borde);
}
.enlace-mas:hover { box-shadow: inset 0 -1px 0 0 currentColor; }
.enlace-mas::after {
  content: "";
  width: 0.85rem;
  height: 0.6rem;
  background: currentColor;
  -webkit-mask: var(--flecha) center / contain no-repeat;
  mask: var(--flecha) center / contain no-repeat;
}


/* ======================================================================
   7. EL HÉROE

   Tres capas: la fotografía a sangre, un velo que le da el tono, y el texto
   sobre un VELO CON SUELO MEDIDO.

   QUÉ CAMBIÓ EL 2026-10-24 Y POR QUÉ. Hasta ahora el texto iba sobre un panel
   NEGRO OPACO, y eso tapaba media fotografía y cortaba a Franz justo por el
   borde del rectángulo. La previa que le gusta al cliente tiene la fotografía
   entera con el texto encima.

   LA REGLA 3 DE LA CASA SIGUE EN PIE: el contraste del texto NO puede
   depender del píxel que le toque detrás. Lo que cambia es CÓMO se cumple.
   Antes se cumplía poniendo un fondo opaco. Ahora se cumple garantizando una
   OPACIDAD MÍNIMA sobre la zona del texto y calculando el PEOR CASO POSIBLE,
   que es una fotografía blanca del todo (#ffffff):

     fondo efectivo en el peor caso = 0,20 x 255 = 51 -> #333333

   y con ese fondo, los cinco pares que se usan en el héroe dan (fórmula de
   WCAG 2.x, calculados, no estimados):

     crema          #f6f3ed  sobre #333333   11,41:1   (nombre, lema)
     crema-apagada  #cdc6ba  sobre #333333    7,45:1   (entradilla)
     crema-tenue    #aaa49a  sobre #333333    5,11:1   (índice, borde fantasma)
     oro            #c29a5b  sobre #333333    4,85:1   (rótulo)
     blanco         #ffffff  sobre rojo #9f3025  7,18:1 (el botón es opaco)

   El mínimo es 4,85:1, por encima del 4,5:1 que pide la norma para texto
   normal, y el borde del botón fantasma da 5,11:1, por encima del 3:1 que
   piden los controles. COMPROBADO ADEMÁS EN PANTALLA sustituyendo la
   fotografía del héroe por una imagen blanca del todo y midiendo ahí.

   POR QUÉ 0,80 Y NO 0,78, QUE ES LO QUE DECÍA EL PLAN. Porque el 78 % solo
   daba de sobra para el texto crema (10,57:1). Con 0,78 el peor caso es
   #383838 y ahí el rótulo de oro se queda en 4,50:1 justo en el límite y el
   borde del botón fantasma (--borde-tinta #787167) baja a 2,43:1, por debajo
   del 3:1. Con 0,80 y el borde del fantasma subido a --crema-tenue dentro del
   héroe, los cinco pares pasan con margen. Son dos puntos de opacidad: la
   fotografía se sigue viendo igual.

   SI ALGUIEN BAJA ESTE NÚMERO, QUE REHAGA LA TABLA. Y si le pone al héroe un
   texto de otro color, que lo calcule contra #333333, no contra --tinta-honda.
   ====================================================================== */

.heroe {
  position: relative;
  background: var(--tinta-honda);
  color: var(--crema);
  isolation: isolate;
}

.heroe__foto {
  display: block;
  position: absolute;
  inset: 0;
  z-index: 0;
}

/* EL ENCUADRE, CON LOS NÚMEROS DELANTE (revisado el 2026-10-24).

   La fotografía del campo (duende-campo) mide 3840x1920, o sea 2:1 exactos, y
   Franz está hacia el 52 % del ancho.

   EN ESCRITORIO EL REENCUADRE APENAS PUEDE HACER NADA, y conviene que conste
   en vez de fingir lo contrario. El hueco del héroe a 1440 px mide unos
   1440x790 (1,82:1), así que «cover» escala por el alto y el ancho escalado
   queda en 1580 px: el recorte horizontal TOTAL son 140 px. Moviendo
   object-position de un extremo al otro, Franz se desplaza 140 px como mucho.
   Lo que de verdad hace que ya no quede cortado por el borde es que el panel
   haya dejado de ser opaco. Aquí se le da el empujón que se puede dar (de
   44 % a 38 %: unos 8 px hacia la derecha) y nada más.

   EN MÓVIL SÍ MANDA, y está al final de esta misma sección. */
.heroe__foto img {
  /* display: block NO es decorativo: una <img> en línea arrastra el hueco de
     la línea base y hacía que el <picture> midiera 7 px más que la imagen. En
     móvil esos 7 px eran una franja de fotografía SIN el velo encima, justo
     debajo del degradado. */
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 38% 45%;
}

/* EL VELO SOLO DA TONO, y desde el 2026-10-24 da MENOS. Antes llegaba a 0,94
   por la izquierda, justo donde va el texto, y se sumaba al panel: con el
   panel ya opaco daba igual, pero con un velo del 80 % encima la fotografía
   habría quedado al 2 % de luz y no se vería nada debajo del texto, que es
   exactamente lo contrario de lo que pide esta ronda. Ahora el velo se queda
   en lo que hace falta para que la cabecera y el pie del héroe no compitan
   con la fotografía, y el suelo de contraste lo pone el velo del texto, que
   es el único que tiene que ser un número. */
.heroe__velo {
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(90deg, rgba(11,10,9,0.50) 0%, rgba(11,10,9,0.28) 40%, rgba(11,10,9,0.06) 70%, rgba(11,10,9,0.34) 100%),
    linear-gradient(0deg, rgba(11,10,9,0.72) 0%, rgba(11,10,9,0) 48%);
}

/* El panel y el índice van en la MISMA fila, los dos pegados abajo: el panel a
   la izquierda y el índice a la derecha. Si el índice fuera a una fila
   propia, el héroe crecería 45 px y dejaría de caber en una pantalla de
   portátil, que es justo donde se mira primero. */
.heroe__caja {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: end;
  min-height: min(86vh, 44rem);
  padding-block: clamp(2.5rem, 9vh, 5.5rem) clamp(2rem, 5vh, 3rem);
}
@media (min-width: 62em) {
  .heroe__caja {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: end;
    column-gap: 2rem;
  }
}

/* EL VELO DEL TEXTO, CON SU SUELO ESCRITO.
   0.80 es el SUELO GARANTIZADO sobre la zona del texto: con él, el fondo
   efectivo nunca es más claro que #333333 pase lo que pase en la fotografía
   (ver la tabla del principio de este bloque). Es un valor PLANO a propósito
   sobre toda el área del texto: un degradado no se puede garantizar, porque
   el ancho del panel y el del hueco cambian con la pantalla y el porcentaje
   del degradado que le toca al texto cambia con ellos.

   Lo único que se desvanece es el BORDE DERECHO, y solo dentro del relleno,
   que es donde NO hay ni una letra: así desaparece la línea vertical dura que
   cortaba a Franz por la mitad sin tocar el suelo del texto. Por eso el
   último tramo del degradado empieza exactamente en
   «100% - el relleno derecho».

   --borde SE SUBE A --crema-tenue DENTRO DEL HÉROE: el borde del botón
   fantasma es --borde-tinta (#787167) y sobre el peor caso #333333 daba
   2,43:1, por debajo del 3:1 que piden los bordes de control. Con crema-tenue
   da 5,11:1. Es la única pieza del héroe que cambia de color. */
.heroe__panel {
  --velo-aire: clamp(1.5rem, 4vw, 2.5rem);
  --borde: var(--crema-tenue);
  max-width: 38rem;
  padding: var(--velo-aire);
  border-left: 2px solid var(--rojo-vivo);
  background: linear-gradient(90deg,
      rgba(0, 0, 0, 0.88) 0%,
      rgba(0, 0, 0, 0.80) calc(100% - var(--velo-aire)),
      rgba(0, 0, 0, 0.38) 100%);
}

.heroe__rotulo {
  margin: 0 0 0.9rem;
  color: var(--oro);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}

.heroe__nombre {
  margin: 0;
  font-size: clamp(3.875rem, 1.5rem + 9vw, 8.875rem);
  line-height: 0.92;
  letter-spacing: -0.02em;
}

.heroe__lema {
  max-width: 20em;
  margin: 1.1rem 0 0;
  color: var(--crema);
  font-family: var(--serif);
  font-size: clamp(1.4rem, 1rem + 1.7vw, 2.25rem);
  line-height: 1.15;
}

.heroe__entradilla {
  max-width: 34em;
  margin: 1rem 0 0;
  color: var(--crema-apagada);
}

/* El índice «01 · Escena / Cámara / Palabra», abajo a la derecha. Es
   decoración tipográfica, así que va fuera del panel y con su propia sombra
   de texto NO: lleva su propio velo con el MISMO suelo del 80 % que el panel,
   por la misma razón y con los mismos números (crema-tenue 5,11:1 y crema
   11,41:1 sobre el peor caso #333333). Si se quedara opaco mientras el panel
   es un velo, se vería un recuadro negro suelto en medio de la fotografía. */
.heroe__indice {
  display: none;
}
@media (min-width: 62em) {
  .heroe__indice {
    display: block;
    align-self: end;
    justify-self: end;
    margin: 0;
    background: rgba(0, 0, 0, 0.80);
    padding: 0.45rem 0.75rem;
    color: var(--crema-tenue);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.2em;
    text-align: right;
    text-transform: uppercase;
  }
  .heroe__indice b {
    display: block;
    color: var(--crema);
    font-size: 0.875rem;
    font-variant-numeric: tabular-nums;
  }
}


/* EN MÓVIL EL HÉROE DEJA DE SER UNA SUPERPOSICIÓN Y PASA A SER DOS PIEZAS:
   una banda de fotografía arriba y el panel debajo, montado unos milímetros
   sobre ella.

   Por qué, con el número delante. En una pantalla de 390 px el hueco del
   héroe es más alto que ancho, la fotografía del campo es 2:1 y el panel se
   come 545 px de los 704 que mide el héroe. O sea que por encima del panel
   solo quedan 110 px: el 15 % de arriba de la foto, que es cielo. Franz está
   al 40 % del alto, así que NO SE LE VE. Y no se arregla con object-position:
   a esa proporción no hay recorte vertical que valga, y bajar el panel hace
   crecer el héroe en la misma proporción, de modo que el porcentaje visible no
   cambia. Para que apareciera habría que dejar el panel por debajo de los
   960 px, y entonces en el primer golpe de vista no se leería ni el nombre.

   Con la banda se ve la fotografía entera y se lee el panel entero. Sigue
   siendo a sangre: la banda ocupa todo el ancho. Y el texto sigue sin estar
   nunca encima de la fotografía, que es la regla 3. */
@media (max-width: 47.99em) {
  .heroe__foto {
    position: relative;
    aspect-ratio: 4 / 3;
  }

  /* EL ENCUADRE DE LA BANDA, CON EL NÚMERO (2026-10-24).
     La banda es 4:3 y la fotografía 2:1, así que «cover» escala por el ALTO:
     a 390 px de ancho el ancho escalado son 585 px y el recorte es de 195 px,
     TODO horizontal. Consecuencia que conviene tener clara: por arriba no se
     recorta nada, o sea que a esta proporción la cabeza de Franz NO la puede
     cortar el encuadre. Lo que sí decide object-position es por dónde se corta
     a los lados, y ahí sí se nota: con el 44 % anterior Franz quedaba al 56 %
     del ancho de la banda, escorado a la derecha y medio tapado por el panel
     que sube 3rem. Con el 56 % queda centrado (0,52 x 585 - 0,56 x 195 = 195,
     o sea la mitad justa de los 390). */
  .heroe__foto img { object-position: 56% 50%; }

  .heroe__velo {
    bottom: auto;
    aspect-ratio: 4 / 3;
    background: linear-gradient(0deg, rgba(11, 10, 9, 0.92) 0%, rgba(11, 10, 9, 0.04) 58%);
  }
  .heroe__caja {
    min-height: 0;
    margin-top: -3rem;
    padding-block: 0 clamp(2rem, 6vh, 3rem);
  }
  .heroe__panel { max-width: none; }
}


/* ======================================================================
   8. TARJETA DE OBRA
   ====================================================================== */

.rejilla-obras {
  display: grid;
  gap: var(--aire-mini) 1.5rem;
  grid-template-columns: 1fr;
  margin: 0;
  padding: 0;
  list-style: none;
}
@media (min-width: 48em) {
  .rejilla-obras { grid-template-columns: repeat(2, 1fr); }
}

.obra-tarjeta {
  position: relative;
  display: flex;
  flex-direction: column;
}
.obra-tarjeta__foto {
  display: block;
  overflow: hidden;
  background: var(--tarjeta);
  aspect-ratio: 16 / 10;
}
.obra-tarjeta__foto img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.obra-tarjeta__cuerpo { padding-top: 1.1rem; }

.obra-tarjeta__genero {
  margin: 0 0 0.5rem;
  color: var(--acento);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.obra-tarjeta__titulo {
  margin: 0 0 0.6rem;
  font-size: clamp(1.5rem, 1.2rem + 1.1vw, 2.125rem);
}
.obra-tarjeta__titulo a { text-decoration: none; }
/* UN SOLO ENLACE POR TARJETA, estirado sobre toda ella. Así quien navega de
   enlace en enlace con lector de pantalla oye el título una vez y no tres. */
.obra-tarjeta__titulo a::after {
  content: "";
  position: absolute;
  inset: 0;
}
.obra-tarjeta__texto {
  margin: 0;
  color: var(--letra-2);
}
/* El foco se ve en TODA la tarjeta, porque el área que se pulsa es la
   tarjeta entera. */
.obra-tarjeta:focus-within { outline: 2px solid var(--letra); outline-offset: 6px; }
/* LA ÚNICA EXCEPCIÓN A «NUNCA outline: none» DE TODA LA HOJA, Y ESTÁ AQUÍ
   ESCRITA PARA QUE NADIE LA «ARREGLE». El comentario venía de la v1, la v2 lo
   perdió y el verificador lo echó en falta con razón: sin él, el día que
   alguien busque «outline: none» en este fichero va a quitarlo y va a romper
   el foco sin enterarse.

   POR QUÉ SE PUEDE QUITAR AQUÍ. El enlace del título está estirado sobre la
   tarjeta entera con un ::after, así que el área que se pulsa NO son las
   letras del título: es la tarjeta. Un anillo alrededor de las letras diría
   que el teclado está en un sitio más pequeño que el que responde. Por eso el
   anillo se dibuja en la TARJETA, con :focus-within, que es el elemento que de
   verdad se pulsa.

   CONDICIÓN PARA QUE SIGA VALIENDO: la regla :focus-within de arriba tiene que
   existir y tiene que estar en el MISMO elemento que lleva el ::after
   estirado. Si se quita una, hay que quitar la otra. Quitar solo esta deja un
   anillo pequeño y feo. Quitar solo la otra deja la tarjeta SIN NINGÚN aviso
   de dónde está el teclado, que es un incumplimiento de 2.4.7. */
.obra-tarjeta__titulo a:focus-visible { outline: none; }


/* ======================================================================
   9. CARTELERA (próximas funciones)

   Una línea por función: día grande, mes, recinto, hora, precio y botón.
   En móvil la misma información se apila; no hay tabla que desbordar.
   ====================================================================== */

.cartelera {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--filete);
}

.cartel-linea {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.35rem 1.25rem;
  align-items: center;
  padding-block: 1.5rem;
  border-bottom: 1px solid var(--filete);
}
@media (min-width: 56em) {
  .cartel-linea {
    grid-template-columns: 5rem minmax(0, 1fr) auto auto;
    gap: 1.5rem;
  }
}

.cartel-linea__fecha {
  grid-row: span 2;
  text-align: center;
  font-family: var(--serif);
  line-height: 1;
}
@media (min-width: 56em) { .cartel-linea__fecha { grid-row: auto; } }

.cartel-linea__dia {
  display: block;
  font-size: clamp(2rem, 1.5rem + 1.6vw, 3rem);
  font-variant-numeric: tabular-nums;
}
.cartel-linea__mes {
  display: block;
  margin-top: 0.2rem;
  color: var(--letra-2);
  font-family: var(--sans);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.cartel-linea__donde {
  margin: 0 0 0.3rem;
  color: var(--acento);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.cartel-linea__obra {
  margin: 0;
  font-size: clamp(1.35rem, 1.1rem + 1vw, 1.875rem);
}

.cartel-linea__datos {
  margin: 0;
  color: var(--letra-2);
  font-size: 0.9375rem;
}
.cartel-linea__datos div { display: flex; gap: 0.4rem; }
.cartel-linea__datos dt { color: var(--letra-3); }
.cartel-linea__datos dd { margin: 0; }

.cartel-linea__accion { grid-column: 1 / -1; }
@media (min-width: 56em) { .cartel-linea__accion { grid-column: auto; } }

.cartel-linea__nota {
  grid-column: 1 / -1;
  margin: 0.5rem 0 0;
  color: var(--letra-3);
  font-size: 0.875rem;
}


/* ======================================================================
   10. TARJETA DE ARTÍCULO
   ====================================================================== */

.rejilla-notas {
  display: grid;
  gap: var(--aire-mini) 1.5rem;
  grid-template-columns: 1fr;
  margin: 0;
  padding: 0;
  list-style: none;
}
@media (min-width: 42em) { .rejilla-notas { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 62em) { .rejilla-notas { grid-template-columns: repeat(3, 1fr); } }

.nota-tarjeta { position: relative; }
.nota-tarjeta__foto {
  display: block;
  overflow: hidden;
  background: var(--tarjeta);
  aspect-ratio: 3 / 2;
  margin-bottom: 1rem;
}
.nota-tarjeta__foto img { width: 100%; height: 100%; object-fit: cover; }

.nota-tarjeta__fecha {
  margin: 0 0 0.45rem;
  color: var(--acento);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.nota-tarjeta__titulo {
  margin: 0 0 0.6rem;
  font-size: clamp(1.35rem, 1.15rem + 0.8vw, 1.75rem);
}
.nota-tarjeta__titulo a { text-decoration: none; }
.nota-tarjeta__titulo a::after { content: ""; position: absolute; inset: 0; }
.nota-tarjeta__texto { margin: 0 0 0.8rem; color: var(--letra-2); }
.nota-tarjeta:focus-within { outline: 2px solid var(--letra); outline-offset: 6px; }
/* Misma excepción y mismas condiciones que en .obra-tarjeta: ver el bloque 8. */
.nota-tarjeta__titulo a:focus-visible { outline: none; }


/* ======================================================================
   11. FACHADA DE VÍDEO

   Los nombres de clase de este bloque los escriben src/Video.php y
   estaticos/js/video.js. NO se renombran sin tocar los dos.
   ====================================================================== */

.rejilla-videos {
  display: grid;
  gap: var(--aire-mini) 1.5rem;
  grid-template-columns: 1fr;
  margin: 0;
  padding: 0;
  list-style: none;
}
@media (min-width: 48em) { .rejilla-videos { grid-template-columns: repeat(2, 1fr); } }

.video { position: relative; }

.video__fachada {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}

.video__imagen {
  position: relative;
  display: block;
  overflow: hidden;
  background: var(--tinta-honda);
  aspect-ratio: 16 / 9;
}
.video__mini { display: block; height: 100%; }
.video__mini img { width: 100%; height: 100%; object-fit: cover; }

.video__velo {
  position: absolute;
  inset: 0;
  background: rgba(11, 10, 9, 0.35);
}

/* El triángulo SÍ va encima de la fotografía, pero es un dibujo sin texto y
   lleva su propio disco oscuro debajo, así que se ve sobre cualquier foto. */
.video__play {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--crema);
}
.video__play svg {
  width: 3.5rem;
  height: 3.5rem;
  border-radius: 50%;
  background: rgba(11, 10, 9, 0.6);
}
.video__fachada:hover .video__play { color: var(--rojo-vivo); }

/* El rótulo va DEBAJO de la miniatura y sobre fondo OPACO: su contraste es
   un número, no «depende del píxel que le toque detrás». */
.video__rotulo {
  display: flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0.75rem 0;
  background: var(--fondo, var(--tinta));
  color: var(--letra, var(--crema));
  font-size: 0.78125rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.video__marco {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  height: auto;
  border: 0;
  background: #000;
}

/* LA SALIDA PERMANENTE HACIA EL VÍDEO. La pinta src/Video.php debajo de cada
   fachada y video.js no la toca: es lo único que queda si el reproductor no
   llega a cargar (bloqueador, red que filtra YouTube, mala cobertura).
   Discreta a propósito —no compite con el rótulo de la fachada— pero con su
   subrayado y sus 2.75rem de alto de pulsación, porque es un enlace de verdad
   y a veces es el único que sirve. */
.video__salida {
  margin: 0.4rem 0 0;
  font-size: 0.8125rem;
}
.video__salida a {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  color: var(--letra-3);
  text-underline-offset: 0.2em;
}
.video__salida a:hover { color: var(--letra); }

.video__aviso {
  max-width: var(--prosa);
  margin-top: 1.25rem;
  color: var(--letra-3);
  font-size: 0.875rem;
}
.video__pie { margin-top: 0.75rem; color: var(--letra-2); }

.video-solo { max-width: 56rem; }


/* ======================================================================
   12. BLOQUE «ACERCA DE MÍ» DE LA PORTADA, y dos columnas en general
   ====================================================================== */

/* minmax(0, 1fr) Y NO 1fr, aunque sea una sola columna. El mínimo implícito
   de «1fr» es min-content, así que un hijo con un tamaño mínimo intrínseco
   grande —el <select> «De qué se trata», 309 px por su opción más larga—
   estira la columna por encima del ancho de la pantalla. A 320 px eso
   recortaba 9 px de texto, y con el overflow-x: hidden del body no había
   forma de llegar a ellos (WCAG 1.4.12). La otra mitad del arreglo es el
   min-width: 0 del propio <select>, en el bloque 14. */
.dos-columnas {
  display: grid;
  gap: var(--aire-mini) 2.5rem;
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}
@media (min-width: 54em) {
  .dos-columnas { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
  .dos-columnas--texto-primero { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
}

.retrato {
  background: var(--tarjeta);
}
.retrato img { display: block; width: 100%; }

/* Dos separaciones con nombre. Existen como CLASE y no como atributo style
   porque la política de contenidos es style-src 'self': un style="..." en el
   HTML lo bloquearía el navegador y el hueco desaparecería. */
.separa { margin-top: 1.5rem; }
.separa-mas { margin-top: 2rem; }


/* ======================================================================
   13. GALERÍA Y OBRA SUELTA
   ====================================================================== */

.galeria {
  display: grid;
  gap: 1.5rem;
  grid-template-columns: 1fr;
  margin: 0;
  padding: 0;
  list-style: none;
}
@media (min-width: 48em) { .galeria { grid-template-columns: repeat(2, 1fr); } }

.galeria__figura { margin: 0; }
.galeria__figura img { display: block; width: 100%; }
.galeria__figura figcaption {
  margin-top: 0.5rem;
  color: var(--letra-3);
  font-size: 0.875rem;
}

.volver {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  color: var(--rotulo);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.vecinas {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr;
  margin-top: var(--aire-mini);
  padding-top: var(--aire-mini);
  border-top: 1px solid var(--filete);
}
@media (min-width: 42em) { .vecinas { grid-template-columns: repeat(2, 1fr); } }

.vecinas__enlace {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  min-height: 2.75rem;
  padding: 1rem;
  border: 1px solid var(--filete);
  text-decoration: none;
}
.vecinas__enlace:hover { border-color: var(--borde); }
.vecinas__enlace--adelante { text-align: right; }
.vecinas__que {
  color: var(--rotulo);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.vecinas__titulo { font-family: var(--serif); font-size: 1.25rem; }


/* ======================================================================
   14. FORMULARIO
   ====================================================================== */

.campo { margin-bottom: 1.5rem; }
.campo label {
  display: block;
  margin-bottom: 0.4rem;
  color: var(--letra-2);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.campo__pista { margin: 0 0 0.4rem; color: var(--letra-3); font-size: 0.875rem; }
.campo__error { margin: 0 0 0.4rem; color: var(--error); font-size: 0.875rem; font-weight: 600; }

/* EL CAMPO TRAMPA (src/Antirrobot.php). display:none y no «fuera de la
   pantalla»: así no está en el árbol de accesibilidad, no lo lee ningún lector
   de pantalla y no recibe el foco. Un campo escondido con position:absolute SÍ
   lo leen, y le piden a alguien que rellene un campo que no existe.
   Un <input> con display:none SE SIGUE ENVIANDO, que es justo lo que hace
   falta: el robot lo rellena y el envío se tira. */
.trampa { display: none; }

/* El aviso que va junto al botón de enviar, con el enlace a /legal. */
.campo__legal {
  max-width: var(--prosa);
  margin: 1rem 0 0;
  color: var(--letra-3);
  font-size: 0.8125rem;
}
.campo__legal a { color: var(--letra-2); text-underline-offset: 0.2em; }
.campo__legal a:hover { color: var(--letra); }

.campo input,
.campo select,
.campo textarea {
  display: block;
  width: 100%;
  /* min-width: 0 NO ES REDUNDANTE con width: 100%, y aquí está el fallo que
     arregla (1.4.12, medido el 2026-10-24 a 320 px): un <select> tiene un
     tamaño mínimo intrínseco igual al de su opción más larga («Contratar una
     función» llegaba a 309 px). Dentro de una rejilla con «1fr», cuyo mínimo
     es min-content, ese ancho estiraba la columna entera y, con el
     overflow-x: hidden del body, se recortaban 9 px de texto sin forma de
     llegar a ellos. Con min-width: 0 el <select> deja de imponer su mínimo.
     La otra mitad del arreglo es el minmax(0, 1fr) de .dos-columnas.
     Y no es un caso raro: el mismo mecanismo se dispara con una tipografía de
     reserva más ancha, sin ninguna hoja de estilo del visitante. */
  min-width: 0;
  min-height: 2.75rem;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--borde);
  background: transparent;
  color: var(--letra);
  font-family: var(--sans);
  font-size: 1rem;
  line-height: 1.5;
}
.campo textarea { min-height: 9rem; resize: vertical; }
.campo input:hover, .campo select:hover, .campo textarea:hover { border-color: var(--letra-2); }
.campo [aria-invalid="true"] { border-color: var(--error); border-width: 2px; }

.aviso {
  margin: 0 0 1.75rem;
  padding: 1rem 1.15rem;
  border-left: 3px solid var(--letra-3);
}
.aviso__titulo { margin: 0 0 0.5rem; font-size: 1.25rem; }
.aviso p:last-child, .aviso ul:last-child { margin-bottom: 0; }
.aviso ul { margin: 0; padding-left: 1.2em; }
.aviso--bien { border-left-color: var(--bien); color: var(--bien); }
.aviso--mal { border-left-color: var(--error); color: var(--error); }
.aviso--pendiente { border-left-color: var(--prov); color: var(--letra-2); }
.aviso--pendiente .aviso__titulo { color: var(--prov); }

/* El titular de la columna de datos es más pequeño que el de una sección: es
   un rótulo de barra lateral, no un titular de portada. */
.datos-contacto h2 {
  margin-bottom: 1.25rem;
  font-size: clamp(1.5rem, 1.25rem + 0.9vw, 2rem);
}
.datos-contacto__lista { margin: 0; padding: 0; list-style: none; }
.datos-contacto__lista li { margin-bottom: 1rem; }
.datos-contacto__que {
  display: block;
  color: var(--rotulo);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
/* EL CORREO Y EL TELÉFONO TIENEN QUE PODER PARTIRSE (2026-10-24).
   «contacto@franzgomezarte.com» es una sola palabra de 27 caracteres sin
   espacios. MEDIDO a 320 px con el espaciado de texto de WCAG 1.4.12
   (0,12 em entre letras): el enlace mide 309 px y su borde derecho cae en
   329, o sea 9 px fuera de la ventana. Y como el body lleva
   overflow-x: hidden, esos 9 px no producen barra de desplazamiento: se
   pierden y no hay forma de llegar a ellos.
   Es el mismo fallo de 1.4.12 que el del <select> del formulario, por el mismo
   mecanismo (un mínimo intrínseco que no cabe) pero en otro elemento: por eso
   hacen falta los dos arreglos y no basta con uno.
   «anywhere» y no «break-word»: solo «anywhere» reduce también el tamaño
   MÍNIMO del elemento, que es justo lo que aquí hay que reducir. El min-width
   es para que el texto, que dentro de un inline-flex es un elemento flexible
   anónimo, pueda encogerse por debajo de su min-content. */
.datos-contacto__lista a {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  min-width: 0;
  overflow-wrap: anywhere;
  font-size: 1.0625rem;
}
.datos-contacto__nota { margin-top: 1rem; color: var(--letra-3); font-size: 0.875rem; }


/* ======================================================================
   15. LA MARCA DE PROVISIONAL

   LO QUE CAMBIÓ EL 2026-10-24, Y POR QUÉ. Hasta ahora el sello era un rótulo
   en versalitas, «TEXTO PROVISIONAL», del color de aviso. Contado sobre las
   capturas de la v2: en la portada se leía ANTES que el nombre de Franz, en
   /obras salía una vez por tarjeta, en /acerca quedaba justo encima de la cita
   y en /entradas había cinco avisos de lo mismo en una pantalla. El andamio de
   la demo gritaba más que el contenido.

   Ahora lo visible es una BARRA CORTA EN EL MARGEN y el texto va en
   .oculto-visual. El aviso no se ha quitado: se ha callado. Quien usa lector
   de pantalla sigue oyendo «Texto provisional» exactamente igual que antes, y
   eso NO ES NEGOCIABLE: que se vea menos no puede significar que se anuncie
   menos. El texto lo pone src/Marca.php, no este fichero.

   La barra lleva aria-hidden en el HTML porque es la misma información dicha
   en color: sin eso se leería dos veces.
   ====================================================================== */

.prov { border-left: 2px dotted var(--prov); padding-left: 1rem; }

.prov__sello {
  /* line-height: 0 para que el párrafo mida lo que mide la barra y no lo que
     mediría una línea de texto que ya no se ve. */
  margin: 0 0 0.55rem;
  line-height: 0;
}
.prov__marca {
  display: inline-block;
  width: 1.5rem;
  height: 0.1875rem;          /* 3 px */
  background: var(--prov);
}

/* EN LAS TARJETAS Y EN LA CARTELERA, SOLO EL RÓTULO, SIN EL FILETE. El filete
   de puntos envolvía la fotografía entera y la dejaba desalineada con las
   tarjetas de al lado. Lo que avisa de verdad es el TEXTO «Texto provisional»,
   que se lee y se traduce, y ese se queda: el filete era el refuerzo, no el
   aviso. (Ver src/Marca.php.) */
.obra-tarjeta.prov,
.nota-tarjeta.prov,
.video-tarjeta.prov,
.cartel-linea.prov {
  border-left: 0;
  padding-left: 0;
}

/* Una cita dentro de un bloque provisional ya lleva el filete de puntos del
   bloque: el suyo propio sobraría y se verían dos líneas pegadas. */
.prov > .cita {
  border-left: 0;
  padding-left: 0;
  margin-top: 0;
}

/* Un bloque provisional justo detrás de un texto largo necesita aire: si no,
   su rótulo queda pegado a la última línea de arriba y parece que es parte de
   ella.

   OJO CON EL SELECTOR. Aquí había un «.prov + .prov» y era un error medido el
   2026-10-24: en /videoblog las cuatro tarjetas llevan la clase «prov», son
   hermanas y son CELDAS DE UNA REJILLA, así que ese margen de 28 px se le
   aplicaba a tres de las cuatro y las descolocaba en vertical dentro de su
   fila. Un selector de hermano adyacente no sabe si lo que tiene al lado es un
   párrafo o una celda. Por eso la regla pide explícitamente que detrás vaya un
   texto largo. */
.prosa + .prov { margin-top: 1.75rem; }


/* ======================================================================
   16. EL PIE
   ====================================================================== */

.pie {
  background: var(--tinta-honda);
  border-top: 1px solid var(--filete-tinta);
  color: var(--crema-tenue);
  padding-block: var(--aire-mini);
  --letra: var(--crema);
  --letra-2: var(--crema-apagada);
  --rotulo: var(--oro);
}
.pie__caja {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.pie__derechos, .pie__marca { margin: 0; }
.pie__marca { color: var(--crema); font-weight: 600; }
.pie__menu ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1.25rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.pie__menu a {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
}


/* ======================================================================
   17. PÁGINAS INTERIORES
   ====================================================================== */

.pagina { padding-block: var(--aire); }
.pagina--estrecha .prosa { max-width: var(--prosa); }

.bloque { margin-top: var(--aire-mini); }
.bloque h2 {
  margin-bottom: 1rem;
  font-size: clamp(1.6rem, 1.3rem + 1.2vw, 2.25rem);
}
.bloque--estrecho { max-width: var(--prosa); }

.articulo__foto { margin: 0 0 var(--aire-mini); }
.articulo__foto img { display: block; width: 100%; }
.articulo__fecha {
  margin: 0;
  color: var(--rotulo);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}


/* ======================================================================
   18. APARICIONES AL BAJAR

   REGLA 7, escrita en CSS: NO SE TOCA LA OPACIDAD. Lo único que se anima es
   un desplazamiento de 12 px hacia arriba. El contenido está SIEMPRE opaco y
   siempre legible, en cualquier momento de la animación.

   POR QUÉ NO UN DESVANECIDO, que es lo habitual. Porque un desvanecido con
   animation-timeline: view() deja el bloque a opacidad baja mientras no está
   en pantalla, y eso ES esconder contenido: se comprobó el 2026-10-24 con una
   captura de la página entera y las seis secciones de abajo salían
   prácticamente invisibles. Si el cálculo del desplazamiento falla, o si la
   página se imprime, o si una herramienta la mira sin desplazarse, con
   opacidad se pierde el texto y con transform no se pierde nada.

   Y las tres barreras siguen puestas: @media (prefers-reduced-motion:
   no-preference), @supports y ni una línea de JavaScript.
   ====================================================================== */

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .aparece {
      animation: aparecer linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 40%;
    }
    @keyframes aparecer {
      from { transform: translateY(0.75rem); }
      to   { transform: none; }
    }
  }
}

/* Cinturón y tirantes: si alguien añade mañana una transición, aquí se
   apagan todas de golpe para quien ha pedido menos movimiento. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}


/* ======================================================================
   19. IMPRESIÓN
   ====================================================================== */

@media print {
  .cabecera, .pie__menu, .video__play, .acciones { display: none; }
  body, .tono--tinta, .tono--tinta-honda { background: #fff; color: #000; }
}


/* ======================================================================
   20. LISTADO DE VÍDEO BLOG

   Reutiliza la tipografía de la tarjeta de obra (mismo tamaño, misma
   familia) y solo añade la separación entre la fachada y su texto.

   EL ORDEN DEL CÓDIGO Y EL ORDEN VISUAL SON DISTINTOS AQUÍ, Y ES A PROPÓSITO
   (2026-10-24). En el HTML el encabezado va ANTES que la fachada, para que
   quien usa lector de pantalla oiga el título del vídeo antes que el botón que
   lo reproduce (antes se oía «Ver el vídeo: El duende de La Mancha, botón» y
   después el encabezado que lo titula). Lo que se ve no cambia: la miniatura
   sigue arriba, porque este «order» la sube.

   CUÁNDO SE PUEDE HACER ESTO Y CUÁNDO NO. Aquí se puede porque lo ÚNICO
   enfocable de la tarjeta es la fachada: no hay dos paradas de tabulación cuyo
   orden pueda contradecir al visual, que es lo que prohíbe 2.4.3. En el
   formulario de contacto NO se puede, y por eso allí el orden de tabulación es
   el del código y no se toca. Si algún día esta tarjeta lleva un segundo
   enlace, hay que quitar este «order».
   ====================================================================== */

.video-tarjeta {
  display: flex;
  flex-direction: column;
}
.video-tarjeta .video { order: 0; }
.video-tarjeta__cuerpo { order: 1; padding-top: 1.1rem; }
