/**
 * Portada de Sydak Living — iteración 5 «HomeLimpia» (entregada 2026-08-11).
 *
 * Portado A MANO desde HomeLimpia/estilos.css (que a su vez sale del recorte
 * por capas del mockup nueva-home-2.tif, 4096×2733). Este fichero NO procede
 * del generador de la iteración 4: aquel sigue existiendo y sigue funcionando,
 * pero desde 2026-08-11 escribe dentro de NuevaPortada/build/ (claves
 * `tema.twig` y `tema.css` de NuevaPortada/build/params.json), no en el tema.
 * css/components/home.css queda intacto como destino suyo: no lo toques desde
 * aquí ni al revés.
 *
 * REGLA DE ORO: toda posición va en % del lienzo original de 4096×2733 y sale
 * literal de HomeLimpia/posiciones.json. NO tocar esos porcentajes ni
 * redondearlos: la reproducción es exacta a cualquier ancho porque es la MISMA
 * composición escalada, no una reconstrucción.
 *
 * ENCUADRE: A SANGRE COMPLETA, igual que el prototipo. `.portada` mide el 100 %
 * del ancho de la ventana y la página se desplaza en vertical cuando el lienzo
 * sale más alto que ella. Es la decisión del cliente del 2026-08-11: prefiere
 * no tener márgenes a no tener barra de scroll. REVIERTE el «encaje» que hubo
 * entremedias —lienzo limitado a 100dvh × 4096/2733 y centrado con <body> en
 * flex, sin scroll pero con bandas #ddcebd a los lados—, que era el desvío
 * [PORTE 2] y ya no existe. Con él se van el flex de <body>, el `flex:none`, el
 * `min()` del ancho, el `body{display:block}` que lo deshacía en móvil y el
 * fichero css/components/home-limpia-drupal.css entero (neutralizaba el wrapper
 * .dialog-off-canvas-main-canvas de core, que sólo estorbaba porque era él, y
 * no `.portada`, quien se convertía en flex item). Ver la nota del final.
 *
 * Lo que este fichero añade al prototipo: el área táctil, los estados táctiles,
 * las reglas del overlay de navegación y el indicador de scroll.
 *
 * Cada desvío respecto a HomeLimpia/estilos.css va marcado [PORTE] con su
 * porqué. LA NUMERACIÓN CAMBIÓ el 2026-08-11 al revertirse el encaje: de los
 * once del porte original sobreviven NUEVE —caen el encaje y el
 * `body{display:block}` que lo deshacía— y se renumeran en orden de aparición
 * para no dejar huecos; ocho de ellos siguen intactos y el noveno, la condición
 * del régimen móvil ([PORTE 7]), sólo cambia de umbral por el mismo motivo. Se
 * les suman DOS añadidos de esta revisión: [PORTE 5] los estados táctiles y
 * [PORTE 11] el indicador de scroll. Y desde el 2026-08-14, [PORTE 12]: el
 * rótulo de la derecha deja de ser PRIVATE ACCESS y pasa a ser CONTACTO →
 * /contact, con una pieza NUEVA compuesta con las letras del propio mockup
 * (§1 y §4). DOCE en total, agrupados en siete asuntos: esquema de color, MENU
 * como <button>, foco y estados, régimen móvil, overlay, indicador y CONTACTO.
 * [PORTE 6] y [PORTE 9] no son desvíos de diseño sino arreglos de sendos fallos
 * del prototipo (el rótulo de la derecha no era pulsable en escritorio; el área
 * táctil de MENU no llegaba a 44 px en móvil); van documentados en su sitio.
 *
 * Medido con Playwright a 15 viewports: a 4096×2733 el render es IDÉNTICO al
 * del prototipo (|Δ| 0,0000 por canal, máximo 0) y la geometría coincide
 * dígito a dígito, MENU incluido. Esa medida NO se ve afectada por la vuelta a
 * la sangre completa: en esa ventana la razón es exactamente la del lienzo, de
 * modo que el encaje ya escogía el 100 % y no había ni bandas ni centrado que
 * quitar. Lo que sí desaparece es el desplazamiento uniforme de +0,203 px que
 * se medía a 1600×1068 —el lienzo mide allí 1067,578 px de alto en una ventana
 * de 1068 y el centrado repartía la diferencia—: ahora arranca en y=0 y el
 * sobrante de 0,42 px queda abajo, sobre el fondo. La verificación de esta
 * revisión lo vuelve a medir.
 */

/* ════ 0. Base — copia literal de HomeLimpia/estilos.css ═══════════════ */

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }

body {
  background: #ddcebd;
  font-family: Georgia, 'Times New Roman', serif;
  -webkit-font-smoothing: antialiased;
}

/* [PORTE 1] data-division="home" trae color-scheme:dark desde tokens.css, que
   la librería home-nav carga para el overlay. Aquí no hay nada oscuro que
   anunciar —la portada es una pared marfil— y el esquema oscuro tiñe las
   barras de scroll y los controles del agente de usuario.
   CORRECCIÓN sobre el diseño: no vale declararlo en `body` a secas. El
   selector de tokens.css es [data-division="home"] (0,1,0) y `body` es
   (0,0,1), así que gana tokens.css aunque este fichero cargue después
   —medido: color-scheme salía `dark`—. Se sube a un selector de atributo sin
   valor: (0,1,1) gana, y sirve para cualquier división por si el helper
   sydak_living_preprocess_html() llegara a poner otra en la portada. */
body[data-division] { color-scheme: light; }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ════ 1. Contenedor: a sangre completa ════════════════════════════════
   Copia literal de HomeLimpia/estilos.css:23. Sin tope de ancho y sin encaje:
   `.portada` mide lo que mide la ventana, el lienzo conserva su proporción y
   la reproducción es 1:1 a cualquier ancho. Aquí no hay nada que calcular
   —esta sección existe sólo para dejar dicho que la ausencia de reglas es
   deliberada—; el porqué está en la nota del final del fichero.
   Consecuencia buscada: la página se desplaza en vertical siempre que la
   ventana sea más apaisada que el lienzo (1,4987:1). A 1920×1080 la página
   mide 1281 px y sobran 201 bajo el pliegue; de ahí el indicador de §6.
   `body` NO lleva ni min-height ni display:flex: el flex era del encaje, y de
   rebote convertía en flex item la barra de administración de Gin (323 px de
   scroll horizontal con PRIVATE ACCESS fuera de la ventana para el usuario
   autenticado) y obligaba a neutralizar el wrapper de core en un fichero
   aparte. Sin él, el wrapper vuelve a ser un <div> de bloque normal y
   `.portada` ocupa su ancho sin ayuda de nadie. */

.portada {
  position: relative;       /* OJO: sin z-index. Ver §5. */
  margin: 0 auto;
  width: 100%;
}

/* .hero recorta; .lienzo mantiene SIEMPRE la proporción original, de modo que
   los % de los hijos siguen refiriéndose al lienzo completo aunque el hero se
   acorte en móvil. */
.hero   { position: relative; width: 100%; aspect-ratio: 4096 / 2733; overflow: hidden; }
.lienzo { position: absolute; top: 0; left: 0; width: 100%; aspect-ratio: 4096 / 2733; }

/* Sin decoding="async" en el HTML y sin object-fit aquí: .lienzo ya tiene la
   proporción exacta del lienzo, así que height:auto da la altura justa. El
   atributo decoding="async" hacía que el fondo no llegara a pintarse en la
   captura, y en una imagen LCP como ésta no aporta nada. */
.fondo { position: absolute; top: 0; left: 0; width: 100%; height: auto; display: block; }

/* Cada pieza se coloca por su esquina superior izquierda y su ancho; el alto
   lo deduce la imagen, así no hay redondeos que descuadren nada.
   height:auto es imprescindible en .pieza, no sólo en las imágenes hijas: el
   logo es un <img> que ES la pieza y, con los width/height del HTML actuando
   de valor presentacional, sin esto se estira en vertical. */
.pieza { position: absolute; margin: 0; padding: 0; border: 0; background: none;
         height: auto; }
.pieza img, .pieza picture, .feature__img { display: block; width: 100%; height: auto; }

/* ── Contrato de posiciones: literal de HomeLimpia/posiciones.json ────── */
.pieza--menu        { left:  2.3926%; top:  4.6469%; width:  8.0811%; }
/* [PORTE 12] CONTACTO — el único elemento de esta portada que NO está en
   HomeLimpia/posiciones.json, porque no está en el mockup. El cliente pidió el
   2026-08-14 sustituir «PRIVATE ACCESS» y su llave por un enlace a CONTACTO, y
   ahí ya no hay nada que recortar: la palabra no existe en el diseño. Tampoco
   valía escribirla con una webfont del tema —la tipografía del diseño nunca se
   identificó (11 serifas probadas glifo a glifo, las cuatro primeras dentro de
   0,02 de IoU entre sí)—, así que habría quedado OTRA letra justo al lado del
   grabado real de MENU.
   Lo que se hace es seguir el método de la iteración 5 un paso más allá: la
   pieza se COMPONE con las letras del propio mockup (C, T y A de «PRIVATE
   ACCESS» a tamaño natural; la O de «ATMOSPHERE» y la N de «SYDAK LIVING»
   reducidas a la altura de mayúscula de la barra, 29 px), con el hueco medido
   en «PRIVATE ACCESS» (8 px). El generador es HomeLimpia/build/letras_contacto.py
   y estos tres números salen literales de su informe,
   HomeLimpia/build/informes/letras-contacto.json → geometria.
   Caja 307×56 px en el lienzo de 4096×2733, con el borde derecho en x=3987 —el
   mismo que tenía la caja de PRIVATE ACCESS, así que el aire de la derecha no
   cambia— y la línea de base en y=175, que es la del rótulo anterior Y la de
   MENU (medido: los tres a 175). */
.pieza--contacto    { left: 89.8438%; top:  4.8664%; width:  7.4951%; }
.pieza--logo        { left: 41.2354%; top: 11.6356%; width: 21.4111%; }
.pieza--tit-sydak   { left: 27.9785%; top: 46.7984%; width: 49.7803%; }
.pieza--tit-claim   { left: 33.5693%; top: 55.5434%; width: 38.208%;  }
.pieza--tit-tagline { left: 38.3301%; top: 65.2763%; width: 27.2949%; }
.feature--1 { left: 19.6045%; top: 80.5342%; width: 10.2051%; }
.feature--2 { left: 37.3535%; top: 80.2781%; width:  8.0078%; }
.feature--3 { left: 54.6631%; top: 80.3879%; width:  7.251%;  }
.feature--4 { left: 70.5322%; top: 80.3879%; width: 11.8408%; }

/* ════ 2. Zonas interactivas ═══════════════════════════════════════════ */

.pieza--menu, .pieza--contacto, .feature {
  cursor: pointer;
  text-decoration: none;
  transition: opacity .25s ease, transform .25s ease;
}

/* [PORTE 2] MENU pasa de <a href="/menu"> (una ruta que no existe y daría 404)
   a <button> que abre el overlay de navegación del sitio: hay que quitarle los
   estilos de agente de usuario o el grabado se desplaza una fracción de píxel.
   Nada de font-size ni de familia: el botón no contiene texto vivo —el rótulo
   va DENTRO del grabado— y su único hijo es un <picture> en display:block.
   line-height:0 es cinturón contra el hueco de línea base que algunos agentes
   dejan dentro de <button>; va DESPUÉS de `font: inherit`, que lo resetearía. */
.pieza--menu {
  -webkit-appearance: none; appearance: none;
  background: none; border: 0; padding: 0; color: inherit;
  font: inherit; line-height: 0; text-align: left;
}

.pieza--menu:hover, .pieza--contacto:hover, .feature:hover { opacity: .62; }
.feature:hover { transform: translateY(-.4%); }

.pieza--menu:focus-visible, .pieza--contacto:focus-visible, .feature:focus-visible {
  outline: 2px solid #6b5636;
  /* [PORTE 3] .6vw sin tope da 23 px de separación a 3840 px de ventana y el
     halo se cuela bajo el logo. Se limita a 8 px. Invisible para el diff de
     píxeles: el anillo de foco no aparece en ningún render de verificación. */
  outline-offset: min(.6vw, 8px);
  opacity: 1;
}

/* [PORTE 4] Área táctil >= 44 px SIN MOVER UN PÍXEL DE TINTA.
   Un pseudoelemento que se expande desde el centro de la caja hasta 44 px
   cuando la caja es menor, y que se queda a ras cuando ya lo es. El
   min(0px, …) es lo que da la continuidad: con caja de 8 px de alto sale
   −18 px arriba y abajo (8+36 = 44); con caja de 100 px sale 0 y no hace nada.
   Los % de inset-block se resuelven contra el ALTO de la caja y los de
   inset-inline contra su ANCHO, que es justo lo que se quiere.
   Hace falta porque el grabado de MENU es diminuto: su caja mide 8,0811 % del
   ancho de la ventana y, como el ráster es de 331×71, su alto es ese ancho por
   71/331 — o sea 0,01733 veces la ventana. A 1920 px salen 155,2×33,3 y a
   900 px, 72,7×15,6. Sólo pasa de 44 px de alto por encima de 2540 px de
   ventana. (A sangre completa la caja es un 18,6 % mayor que con el encaje a
   1920×1080 —155,2 frente a 130,8—, así que el margen sólo puede mejorar.)
   Consecuencia para la verificación: la GEOMETRÍA se mide sobre el <img> y la
   ACCESIBILIDAD sobre el <a>/<button> (su ::after), no sobre la misma caja.
   Nota medida: .hero recorta (overflow:hidden), así que la mitad de la
   expansión que sobresale por encima del borde superior del hero no es
   pulsable. Fuera del régimen móvil eso no llega a doler: el grabado arranca a
   3,10 % del ancho de la ventana (0,046469 del hero, que es 0,66724 del ancho)
   y la mitad de la expansión pide 22 − 0,00867·ancho, de modo que los dos se
   cruzan en 554 px — 59,5 contra 5,4 px a 1920, y 17,6 contra 17,1 en el
   apaisado más pequeño del catálogo, 568×320. Por debajo de esos 554 px de
   ancho en apaisado sí se comería unas décimas, pero ahí no llega ningún
   viewport auditado. En móvil, en cambio, MENU se quedaba en 39,1 px a
   320x568: lo corrige [PORTE 9] al final de §4, volcando la expansión hacia
   abajo sólo en ese régimen. Ninguno de los 13 viewports auditados baja de 44. */
.pieza--menu::after, .pieza--contacto::after, .feature::after {
  content: '';
  position: absolute;
  inset-block:  min(0px, calc((100% - 44px) / 2));
  inset-inline: min(0px, calc((100% - 44px) / 2));
}

/* [PORTE 5] Estados táctiles. AÑADIDO de esta revisión, no viene del porte:
   ni HomeLimpia/estilos.css ni el porte tenían una sola regla :active, y la
   portada anterior sí (css/components/home.css, bloque @media (hover: none)).
   En un dispositivo sin puntero el :hover no llega a existir —o peor, se queda
   pegado tras el toque—, así que el único acuse de recibo posible es :active.
   Mismo valor que la portada anterior (.68) para que las dos se sientan igual;
   la transición de opacidad ya está declarada arriba y la desactiva
   prefers-reduced-motion como en todo lo demás.
   El realce propio del navegador se apaga porque pinta un RECTÁNGULO gris
   sobre la caja entera del elemento, y aquí las cajas no son rectángulos
   visibles sino grabados con alfa: en las cuatro features delataría el hueco
   entre el emblema y su texto, y en MENU y PRIVATE ACCESS la caja incluye la
   expansión invisible del área táctil de [PORTE 4]/[PORTE 9]. El acuse lo da
   la opacidad, que sí sigue la forma de la tinta. */
@media (hover: none) {
  .pieza--menu, .pieza--contacto, .feature { -webkit-tap-highlight-color: transparent; }
  .pieza--menu:active, .pieza--contacto:active, .feature:active { opacity: .68; }
}

@media (prefers-reduced-motion: reduce) {
  .pieza--menu, .pieza--contacto, .feature { transition: none; }
  .feature:hover { transform: none; }
}

/* ════ 3. Las 4 features ═══════════════════════════════════════════════
   En escritorio van absolutas sobre .portada, cuyo alto coincide con el del
   lienzo, de modo que los mismos % valen. */
.features { position: absolute; inset: 0; }
.feature  { position: absolute; display: block; }

/* [PORTE 6] ARREGLO DE UN FALLO DEL PROTOTIPO, no un desvío de diseño.
   .features es una capa absoluta a inset:0 que cubre TODA la portada, va
   después en el DOM y no lleva z-index, así que en escritorio captura el
   puntero sobre el rótulo de la derecha y el enlace no se puede pulsar. Medido
   con elementFromPoint en el centro de .pieza--private (el nombre que tenía
   entonces; hoy .pieza--contacto ocupa ese sitio): devuelve `nav.features`
   tanto en HomeLimpia/index.html (1920×1080 y 1535×1024) como en el porte
   antes de esta regla. MENU se libraba por casualidad: le da z-index 60 el
   bloque del overlay (§5).
   Se arregla por hit-testing y no con z-index: pointer-events no toca el
   orden de pintado, así que el diff de píxeles no puede verlo. La capa deja
   de recibir eventos y los recuperan sólo las cuatro features. */
.features { pointer-events: none; }
.feature  { pointer-events: auto; }

/* ════ 4. Móvil: se sacrifica el encuadre, no la fidelidad ═════════════
   [PORTE 7] La condición del prototipo era (max-width: 767px) a secas. Aquí
   lleva dos cambios, y los dos son consecuencia de la sangre completa.

   (a) EL ASPECTO. La recomposición presume ALTURA que gastar: su página mide
   1,9 veces el ancho (todo va en vw o en % del ancho, así que la razón es
   constante), de modo que sólo cabe sin scroll con aspecto <= 0,52. Un móvil
   en apaisado (844×390, 740×360, 568×320) cumple lo de estrecho pero no lo de
   alto, y recompuesto daría 1 610 px de página en una ventana de 390. Para él
   lo correcto es el régimen normal, que además le sienta bien: a 844×390 el
   lienzo mide 844×563, el encuadre del mockup queda intacto y el scroll se
   queda en 173 px.

   (b) EL ANCHO SUBE DE 767 A 1023 px, para que entre el TABLET VERTICAL. Con
   el encaje —lienzo limitado en alto y centrado— 768×1024 salía entero; a
   sangre completa el lienzo mide 768×512, ocupa la mitad superior de la
   pantalla y deja 512 px de #ddcebd muerto debajo, con el titular en 31 px.
   Recompuesto llena la pantalla y el titular sube a 54 px, a cambio de 442 px
   de scroll — que es exactamente lo que el cliente ha aceptado a cambio de no
   tener márgenes. Ninguno de los otros 12 viewports auditados cambia de
   régimen.

   ⚠️ Esta cadena está replicada CARÁCTER A CARÁCTER en otros tres sitios: la
   variable {% set movil %} de templates/layout/page--front.html.twig (sizes
   del fondo y <source media> de las variantes -solo), el imagesizes del
   preload en sydak_living.theme y HomeLimpia/build/verificar_drupal.py, que
   los cruza. Si se desincronizan, el navegador descarga el fondo dos veces.
   Todo lo de dentro es copia literal del prototipo salvo lo marcado. */
@media (max-width: 1023px) and (max-aspect-ratio: 1/1) {

  /* Un lienzo apaisado a 390 px deja el titular en 15,7 px: encoger el hero no
     arregla nada. Se acerca el lienzo al 175 % y se recorta por los lados, con
     lo que SYDAK LIVING pasa a 27,5 px de caja. El alto del hero corta justo
     antes de la banda de features, que va debajo. */
  .hero   { aspect-ratio: auto; height: 88vw; }
  .lienzo { width: 175%; left: -37.5%; }

  /* la barra se reancla a las esquinas del hero y crece para ser tocable */
  .pieza--menu    { left: 4%; top: 3.4%; width: 22%; }
  /* [PORTE 12] CONTACTO en móvil. El 34 % de PRIVATE ACCESS medía una caja de
     542 px que llevaba dentro la llave; ésta mide 307, y para que la letra
     salga EXACTAMENTE del mismo tamaño en pantalla el % escala con la caja:
     34 × 307/542 = 19,26.
     El `top` sí cambia de criterio, y a mejor: se alinea la línea de base con
     la de MENU en vez de heredar un valor que no cuadraba. Con top: 3,2 % la
     base de PRIVATE ACCESS caía a 7,40vw del borde del hero y la de MENU a
     6,18vw — 1,2vw de desnivel (4,7 px a 390 de ancho) entre dos rótulos que
     se leen como una sola barra. La caja nueva pone su tinta entre el 23,2 % y
     el 75 % de su alto, así que 4,03 % de los 88vw del hero deja su base
     también en 6,18vw. En escritorio no hace falta nada de esto: las dos piezas
     salen de las coordenadas del mockup y ya comparten la base (y=175). */
  .pieza--contacto { left: auto; right: 4%; top: 4.03%; width: 19.26%; }

  .features {
    position: static;
    display: grid;
    grid-template-columns: 1fr 1fr;
    justify-items: center;
    align-items: start;
    gap: 8vw 4vw;
    padding: 9vw 4vw 11vw;
    background: #ddcebd;
  }

  /* [PORTE 8] En el prototipo es `static`. Hace falta `relative` para que el
     ::after del área táctil se posicione contra la propia feature y no contra
     .portada.
     CORRECCIÓN sobre el diseño, que daba por hecho que `relative` no movía
     nada «porque no lleva offsets»: sí los lleva. Las reglas de contrato
     .feature--N declaran left/top, que en `static` el motor ignora y en
     `relative` vuelven a aplicar como desplazamiento. Medido a 390×844: la
     retícula se rompía y feature--4 se iba 105 px fuera del viewport
     (scrollWidth 495 sobre 390). left/top a `auto` = desplazamiento 0, que es
     exactamente lo que hacía el `static` del prototipo. */
  .feature { position: relative; left: auto; top: auto; }
  .feature:hover { transform: none; }

  /* Cada una ocupa el porcentaje de su celda que le corresponde por su ancho
     natural (ancho/485), centrada: las cuatro a la misma escala, 0,3538 a
     390 px. Igualar los anchos en pantalla igualaría lo accidental (la
     longitud de la línea de texto) y desigualaría lo esencial (el icono). */
  .feature--1 { width:  86.19%; }   /* 418 / 485 px */
  .feature--2 { width:  67.63%; }   /* 328 / 485 px */
  .feature--3 { width:  61.24%; }   /* 297 / 485 px */
  .feature--4 { width: 100.00%; }   /* 485 / 485 px */

  /* [PORTE 9] El área táctil crece SÓLO HACIA ABAJO en el régimen móvil.
     El min(0px, calc((100% - 44px)/2)) de §2 reparte la expansión a partes
     iguales arriba y abajo, y aquí la mitad de arriba se pierde: MENU y
     PRIVATE ACCESS se anclan a 3,4 % / 3,2 % del alto del hero y .hero
     recorta (overflow:hidden), así que lo que sobresale por encima del borde
     no es pulsable. Medido con elementFromPoint en la portada servida: la
     caja del grabado de MENU a 320x568 mide 15,1 px de alto con top 9,56 px,
     pide 14,45 px por arriba y 4,89 caen fuera → 39,1 px efectivos, por
     debajo incluso del suelo de aviso de 40 px del propio harness (también
     41,2 a 360x740, 42,8 a 390x844, y PRIVATE 42,6 a 320x568).
     Anclando el borde superior a 0 y volcando toda la expansión hacia abajo
     —donde sobra hero: el área llega a 53,6 px de un hero de 281,6 px a
     320 px de ancho— salen 44,0 px efectivos limpios. NO mueve un píxel de
     tinta: el pseudoelemento es transparente y la caja del grabado sigue
     midiendo 12,80x9,56 exactamente igual que antes.
     Sólo MENU y PRIVATE: las features van en la retícula estática de abajo,
     fuera del recorte, y ya pasan de sobra. Fuera del régimen móvil la
     expansión sigue siendo simétrica (esta regla vive dentro de la media
     query) porque allí el grabado está lo bastante lejos del borde: los dos
     valores sólo se cruzan por debajo de 554 px de ancho, donde no llega
     ningún viewport del catálogo. Las cuentas, en [PORTE 4]. */
  .pieza--menu::after, .pieza--contacto::after {
    inset-block: 0 min(0px, calc(100% - 44px));
  }
}

/* ════ 5. [PORTE 10] Overlay del menú del sitio ════════════════════════
   El overlay y el comportamiento son los del resto del sitio (nav-main.css +
   nav.js, librería sydak_living/home-nav): aquí sólo vive el botón, que es el
   grabado del mockup, y el botón de cierre.

   CLAVE DE APILADO: .portada es position:relative SIN z-index y .hero es
   position:relative SIN z-index, así que NINGUNO crea contexto de apilado
   (overflow:hidden tampoco lo crea). A diferencia de la .stage de
   NuevaPortada —position:fixed, que sí lo crea—, aquí el botón MENU puede
   subir por encima del overlay desde DENTRO de la composición.
   ⚠️ NO AÑADIR z-index, transform, filter, opacity<1, will-change ni
   container-type a .portada ni a .hero: cualquiera de ellos crea contexto de
   apilado y deja el botón MENU enterrado bajo el overlay. */

.pieza--menu { z-index: 60; }        /* .c-nav abre a z-index 50 */

/* Estado abierto. El rótulo «MENU» va DENTRO del grabado: no hay texto vivo
   que recolorear como en NuevaPortada (allí .menu .rotulo era un <span>).
   Se invierte la tinta del propio ráster: brightness(0) lleva todo color a
   negro CONSERVANDO EL ALFA, e invert(1) lo vuelve blanco. El recorte tiene
   alfa en cada glifo, así que la palabra sale en blanco sobre --div-bg-deep
   (#221812 en la paleta home) con el mismo dibujo. Funciona igual sobre
   menu.webp y sobre menu-solo.webp. */
html.is-nav-open .pieza--menu img        { filter: brightness(0) invert(1) opacity(.82); }
html.is-nav-open .pieza--menu:hover img  { filter: brightness(0) invert(1) opacity(1); }
html.is-nav-open .pieza--menu:hover      { opacity: 1; }

/* El overlay es opaco y tapa la composición: sin esto los enlaces de debajo
   siguen recibiendo el puntero. El foco lo corta el atributo inert que pone
   nav.js sobre [data-nav-inert] (ver js/nav.js).
   Va sobre .feature y no sobre .features porque tras [PORTE 6] la capa ya no
   recibe eventos nunca y quien los tiene es cada feature. */
html.is-nav-open .feature,
html.is-nav-open .pieza--contacto { pointer-events: none; }

/* Botón de cierre. Vive FUERA de .portada y va anclado al VIEWPORT, no a la
   composición: a sangre completa la página se desplaza, y una × pegada a la
   esquina del lienzo se iría con el scroll justo cuando hace falta —el overlay
   es position:fixed y se ve entera desde cualquier posición de la página—.
   (Antes el motivo era el contrario, las bandas del encaje; el que vale ahora
   es éste, y manda lo mismo.)
   Arriba a la DERECHA, no a la izquierda como en NuevaPortada: a la izquierda
   se solapa con el propio MENU en cuanto la ventana es estrecha (a 390 px la
   × cae en 14,14 y MENU en 15,6/11,7 — se pisan y gana la × por orden de DOM).
   A la derecha cae sobre PRIVATE ACCESS, que con el menú abierto está tapado
   por el overlay y con pointer-events:none. */
.c-nav-close {
  display: none;
  position: fixed;
  z-index: 60;
  top: max(2.2vh, 14px);
  right: max(2.2vw, 14px);
  width: 44px; height: 44px;
  background: none; border: 0; padding: 0;
  cursor: pointer;
  color: var(--div-on-deep);          /* #E3C9A5 en la paleta home */
}
html.is-nav-open .c-nav-close { display: block; }
.c-nav-close::before, .c-nav-close::after {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 22px; height: 1.5px; background: currentColor;
}
.c-nav-close::before { transform: translate(-50%, -50%) rotate(45deg); }
.c-nav-close::after  { transform: translate(-50%, -50%) rotate(-45deg); }
.c-nav-close:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }

/* ════ 6. [PORTE 11] Indicador de scroll ═══════════════════════════════
   AÑADIDO de esta revisión: no está en el prototipo y hace falta desde que la
   portada va a sangre completa. Las cuatro divisiones son la ÚNICA navegación
   de esta página y caen bajo el pliegue en cuanto la ventana es más apaisada
   que el lienzo: a 1920×1080 arrancan en y = 1032 de una página de 1281, y a
   3840×1080 ni se intuyen. Sin una señal, la portada parece acabar en el
   titular.
   Es un FILETE, no un control: 1 px de ancho, 48 px de alto, en el bronce de
   la marca (#8a6a4a, el mismo de la paleta de esta portada) y desvanecido
   hacia arriba con un degradado para que se lea como una marca de la
   composición. No lleva flecha, ni texto, ni caja. En el HTML va
   aria-hidden="true" y sin foco; aquí, pointer-events:none. No sustituye a
   nada: el orden de tabulación ya lleva a las cuatro divisiones sin él.
   z-index 40: por debajo del overlay (.c-nav, 50) y del botón MENU y la ×
   (60), que son los únicos que deben poder taparlo.
   OBSERVACIÓN MEDIDA, por si alguien la ve y la toma por un fallo: en las
   ventanas cuyo pliegue cae sobre la banda de divisiones (16:9 y 16:10, de
   1,70 a 1,86 de aspecto) el filete queda casi encima del separador vertical
   que la propia composición tiene entre ART y CURATED, que está en el 49,878 %
   del lienzo (x=2043 de 4096, medido sobre images/home-limpia/fondo.webp).
   El filete va al 50 % exacto, así que la separación es de 0,122 % del ancho
   —2,3 px a 1920— y a tamaño real se leen como una sola línea con un
   escalón mínimo. Se deja centrado a propósito: el centro geométrico es lo
   que se puede afirmar y comprobar; alinearlo con el separador sería atar el
   CSS a una coordenada del cuadro. */

.pista-scroll {
  display: none;                       /* sólo donde hay scroll; ver 6.1 */
  position: fixed;
  z-index: 40;
  left: 50%;
  bottom: max(2.4vh, 18px);
  width: 1px;
  height: 48px;
  transform: translateX(-50%);
  pointer-events: none;
  background: linear-gradient(to top,
              #8a6a4a 0%, rgba(138, 106, 74, .55) 42%, rgba(138, 106, 74, 0) 100%);
}

/* 6.1 CUÁNDO hay scroll. Se calcula, no se adivina; y como en los dos
   regímenes TODO el alto de la página es proporcional al ancho de la ventana,
   el criterio se reduce en ambos a un umbral de aspecto:

   · A sangre completa la página es el lienzo y nada más, así que mide
     ancho/1,4987 y desborda exactamente cuando la ventana es más apaisada que
     el propio lienzo: min-aspect-ratio 4096/2733. Al ras (1535×1024 → 1024,21
     px de página) sobran 0,21 px, que no son scroll de verdad: ahí el filete
     se vería, y es justo lo que apaga el interruptor exacto de 6.2.

   · En la recomposición móvil el alto es 0,8800 (hero, 88vw) + 1,0284
     (retícula de features: gaps y padding en vw, anchos en % de celda) =
     1,9084 veces el ancho. MEDIDO en los once anchos de 320 a 1023 px, donde
     sale constante hasta la cuarta cifra, no supuesto. Desborda cuando el
     aspecto pasa de 1/1,9084 = 0,5240, y de ahí el 1000/1908. No es
     redundante con el otro umbral: hay móviles que NO desbordan —390×844 da
     744 px de página en 844 de ventana— y ésos no deben enseñar el filete. */
@media (min-aspect-ratio: 4096/2733) {
  .pista-scroll { display: block; }
}
@media (max-width: 1023px) and (max-aspect-ratio: 1/1) and (min-aspect-ratio: 1000/1908) {
  .pista-scroll { display: block; }
}

/* 6.2 Se desvanece al desplazarse, SIN UNA LÍNEA DE JS: una animación atada a
   la línea de tiempo de scroll del documento. Hace dos cosas a la vez:
   · el fundido, en el primer 20 % del recorrido y como mucho en 160 px, de
     modo que en una página larga (3840×1080, 1482 px de scroll) no se eternice
     y en una corta (1920×1080, 201 px) no sea un parpadeo;
   · y el INTERRUPTOR EXACTO: si el documento no tiene scroll, la línea de
     tiempo está inactiva, la animación no aplica ningún valor y manda el
     estado base, que aquí es opacity:0. O sea que donde el navegador soporta
     scroll() el filete sólo se pinta si hay scroll DE VERDAD, y las media
     queries de 6.1 quedan de respaldo para el que no lo soporte.
     COMPROBADO en el Chromium 149 del venv, en dos bancos: en uno de prueba,
     CSS.supports('animation-timeline','scroll(root block)') = true, documento
     de 300 px en ventana de 600 → opacidad calculada 0, documento de 2000 px →
     1 arriba, 0,571 a 120 px de scroll y 0 a partir de 280; y en la portada
     servida a 1920×1080 (201 px de recorrido, de los que el 20 % son 40) la
     opacidad va 1 → 0,751 → 0,502 → 0,253 → 0,005 en pasos de 10 px y se queda
     en 0. A 1535×1024, donde sobran 0,21 px que el navegador no considera
     scroll, la media query enciende el filete y el interruptor lo deja en 0:
     medido, display block con opacidad 0. Y CSS.supports('animation-range',
     '0 min(20%, 160px)') = true, con valor calculado '0px min(20%, 160px)'. */
@supports (animation-timeline: scroll()) {
  .pista-scroll {
    opacity: 0;
    animation: pista-scroll-fundido linear both;
    animation-timeline: scroll(root block);
    animation-range: 0 min(20%, 160px);
  }
  @keyframes pista-scroll-fundido {
    from { opacity: 1; }
    to   { opacity: 0; }
  }
}

/* Con el overlay abierto no hay nada que insinuar: la página que se desplaza
   queda detrás y el menú es fijo. Dos clases (0,2,1) le ganan a las media
   queries de 6.1 (0,1,0) sin recurrir a !important. */
html.is-nav-open .pista-scroll { display: none; }

/* Sin deriva y sin animación con movimiento reducido: el filete se queda
   quieto y visible mientras haya scroll según 6.1. Se pierde el interruptor
   fino de 6.2 —vuelve a mandar el umbral de aspecto—, que es el lado por el
   que conviene equivocarse: enseñar una marca de 1 px de más es preferible a
   animar a quien ha pedido que no se le anime. */
@media (prefers-reduced-motion: reduce) {
  .pista-scroll { animation: none; opacity: 1; }
}

/* ══════════════════════════════════════════════════════════════════════
   Sin max-width A PROPÓSITO: el hero va a sangre completa. Es la última línea
   de HomeLimpia/estilos.css y sigue siendo la razón de ser de §1. Un tope de
   ancho deja el lienzo más pequeño que la ventana y la reproducción deja de
   ser 1:1 (con max-width:2400px a 4096 px de viewport todo salía a escala
   0,586); el encaje del 2026-08-11 no era un tope en píxeles, pero hacía lo
   mismo por el otro lado —limitar el ancho por el alto disponible— y con el
   mismo efecto: bandas de #ddcebd y composición encogida.
   El precio de no tenerlas es la barra de scroll vertical, y es el precio que
   el cliente ha elegido pagar. */
