/* =====================================================================
   FRED'S · SISTEMA VISUAL
   =====================================================================
   Orden: tokens → base → tipografía → piezas comunes → secciones.

   ── LAS DECISIONES QUE EXPLICAN TODO LO DEMÁS ────────────────────────

   1 · LA WEB ES CLARA. NO ES OSCURA.
       ⚠️ El sitio publicado tiene `body { background: #fff }` en su propio
       tema, y los fondos que declara Elementor son dorado (46 veces) y
       blanco (13). No hay ni un fondo oscuro en toda la marca.
       Se montó primero sobre azul profundo y estaba mal: ese azul era una
       invención, no la marca. El papel es claro y el azul se queda donde
       le toca, como tinta y como acento.

       La paleta, medida sobre el sitio publicado: dorado #cc9933 (155
       usos), azul petróleo #1b7892 y turquesa #009999.
       Un solo acento en toda la página: el dorado. Nada más.

   2 · ESQUINAS RECTAS EN TODO.
       Botones, tarjetas, imágenes, campos: radio 0. Una sola forma para
       todo el sitio. Un botón redondeado dentro de una maqueta recta es
       lo que hace que una web parezca montada por piezas sueltas.

   3 · LA PORTADA ABRE AL 100% Y SIN TEXTO ENCIMA.
       Regla de Grupo Anderson's: la primera pantalla es el vídeo entero,
       de borde a borde. Nada de heros partidos 50/50 para abrir.
       Y como en Señor Frog's y en Nicoletta, el vídeo no lleva titular
       encima: la primera palabra de la web vive en la banda azul que
       viene justo debajo. Así no hay texto que proteger y el vídeo se ve
       limpio.
       Lo único que se superpone es la cabecera, y ésa sí lleva velo
       propio: sin él, sobre el fotograma más claro del vídeo el menú en
       blanco se quedaba en 2,2:1 de contraste.

   4 · EN MÓVIL LAS TARJETAS NO SE APILAN: SE DESLIZAN.
       Carrusel con anclaje y la vecina asomando, para que se vea que
       hay más. El scroll de la página no se alarga.

   5 · UN SOLO MODO: CLARO.
       Todo el color sale de variables, pero NO se sigue el modo oscuro del
       sistema. En un Mac en oscuro la web salía negra sin que nadie lo
       hubiera decidido, y la identidad de la marca no la elige el sistema
       operativo del visitante.
   ===================================================================== */

/* =====================================================================
   📱 TOCAR UNA FOTO NO LA AGRANDA (2026-09-15)
   =====================================================================
   Carlos: «aprieto una imagen y hace zoom horrible, daña la movilidad».
   En Safari del iPhone eso son TRES cosas distintas, y ninguna la
   reproduce el simulador (WebKit de Playwright tocó las 70 fotos del
   sitio sin que ninguna cambiara de tamaño):

     1. MANTENER PULSADA una foto abre la vista previa del sistema, que
        la amplía encima de la página → `-webkit-touch-callout: none`.
     2. DOBLE TOQUE acerca la página entera, y en un sitio lleno de fotos
        y tarjetas que se tocan es fácil dispararlo sin querer →
        `touch-action: manipulation`. ⭐ NO quita el PELLIZCO: ampliar con
        dos dedos sigue funcionando, que es de accesibilidad. Por eso NO
        se toca el `viewport` con `user-scalable=no`.
     3. `:hover` PEGADO: en táctil el primer toque deja el hover puesto y
        la foto se queda crecida (hasta 1.16 en las cartas de Cancún).
        Todos los hover que escalan fotos van ya dentro de
        `@media (hover: hover) and (pointer: fine)`.
   ===================================================================== */
html { touch-action: manipulation; }
img, video, picture { -webkit-touch-callout: none; -webkit-user-drag: none; }


/* ── Tokens ────────────────────────────────────────────────────────── */
:root {
  /* ═══════════════════════════════════════════════════════════════════
     LA PALETA — tomada del PSD `FS_MailingVillas.psd` (2026-08-13)
     ═══════════════════════════════════════════════════════════════════
     ⭐ EL PSD ES LA GUÍA, no al revés. Estos cuatro colores son los que
     usa el mailing de las Villas y a partir de aquí mandan en la web.

     ⛔ Lo que había antes —dorado #cc9933, turquesa #009999 y azul
     pizarra #263b47, medidos en el sitio publicado— queda archivado en
     `_docs/paleta-anterior-2026-08-13/`.                               */
  --arena:     #d4c3b0;   /* el papel del sitio */
  --terracota: #a05b33;   /* el acento: rellenos de botón y bloques */
  --marron:    #7c533e;   /* las superficies oscuras */
  --crema:     #f3e6d8;   /* el claro que se levanta */

  /* ⚠️ VERSIONES PARA TINTA. Los colores del PSD NO se pueden usar como
     texto sobre su propio fondo: la terracota sobre arena da 3,03:1 y el
     marrón 3,87:1, cuando el mínimo es 4,5. En el mailing eso pasa
     desapercibido porque el texto es enorme; en una web con cuerpo de
     16 px, no. Estas versiones bajan sólo la LUZ —mismo tono, misma
     saturación— hasta llegar al mínimo, así que se siguen leyendo como
     el mismo color. */
  --terracota-tinta: #7a4527;   /* 4,52:1 sobre arena */
  --tinta:           #483024;   /* 7,10:1 sobre arena */
  --tinta-suave:     #6d4937;   /* 4,60:1 sobre arena */
  --linea:           #b9a48a;

  /* ═══════════════════════════════════════════════════════════════════
     ⭐ EL ACENTO, EN UN INTERRUPTOR (2026-09-10)
     ═══════════════════════════════════════════════════════════════════
     Carlos vio el rojo del cartel Sea & Spice sobre los fondos del sitio
     y sobre los dos botones: «me gusta eso, haz esos cambios primero,
     pero guarda lo anterior por si quiero cambiarle».

     Así que el acento dejó de ser un color y pasó a ser un ROL. Todo lo
     que antes decía `--terracota` ahora dice `--acento`, y cambiar la
     web entera de vuelta es cambiar estas dos líneas:

         --acento:       var(--terracota);
         --acento-tinta: var(--terracota-tinta);

     ⛔ La terracota NO se borró: sigue declarada ahí arriba y sigue
     siendo la del PSD de las Villas. La foto del CSS anterior está en
     `_interno/_docs/paleta-terracota-2026-09-10/`.

     ⚠️ EL ROJO NO NECESITA VERSIÓN PARA TINTA. La terracota sí la
     necesitaba: sobre arena daba 3,03:1 y había que oscurecerla hasta
     #7a4527 para llegar a 4,52. El rojo del cartel da **4,75 sobre
     arena** tal cual, 5,50 sobre arena clara, 6,65 sobre crema y 8,15
     sobre blanco. Por eso las dos variables apuntan al mismo color: la
     segunda existe para que volver a la terracota siga siendo cambiar
     dos líneas, no sesenta.

     ⭐ PARA COMPARARLAS EN VIVO, sin tocar el archivo: cualquier página
     acepta `?paleta=terracota` y se pinta con la vieja. Lo monta
     `partials/head.php`.                                              */
  --acento:       var(--rojo-spice);
  --acento-tinta: var(--rojo-spice);

  /* ⚠️ La escala de papeles se LEVANTA, no se hunde. El arena del PSD ya
     está en su límite: cualquier versión más honda deja el texto suave
     por debajo de 4,5. Así que el respiro y las superficies elevadas van
     hacia el claro, y el segundo escalón es la propia crema del PSD. */
  --arena-clara: #e0d2c1;

  /* Roles: lo que usan los componentes. Cambiarlos cambia el modo.
     ⚠️ Los componentes usan SIEMPRE estos, nunca los crudos de arriba. */
  --fondo:         var(--arena);        /* el papel, como en el PSD */
  --fondo-alto:    var(--crema);        /* superficies que se levantan */
  --fondo-hondo:   var(--arena-clara);  /* secciones de respiro */
  --texto:         var(--tinta);
  --texto-suave:   var(--tinta-suave);
  --borde:         var(--linea);
  /* ⚠️ BLANCO, no la crema: sobre la terracota la crema se queda en
     4,24:1. El blanco da 5,20 sobre terracota y 6,64 sobre marrón, así
     que sirve para las dos superficies oscuras. */
  --sobre-hondo:   #ffffff;
  /* ⭐ EL PAPEL BLANCO — Carlos, 2026-08-17: «podemos aplicar algunas
     partes blancas en el home, por lo menos un poco». El sitio es de
     papel arena; el blanco entra como TERCER escalón, no como fondo
     general: donde la página necesita respirar entre dos bloques con
     mucha materia. La marca sigue siendo la arena. */
  --fondo-blanco:  #ffffff;

  /* ═══════════════════════════════════════════════════════════════════
     LA LÍNEA SEA & SPICE — del PSD `FS_Sea&Spice_Invitación.psd`
     ═══════════════════════════════════════════════════════════════════
     Carlos, 2026-09-10: «podemos generar un fondo como esa textura para
     usarlo, e instalar la tipografía roja, que esa es la nueva línea de
     Fred's». Aquí quedan las tres piezas, MEDIDAS del PSD y listas para
     usar. ⚠️ Nada de esto cambia todavía cómo se ve el sitio: no se
     aplica a ningún componente hasta que Carlos diga dónde va.

     ⭐ EL ROJO. #a20618 exacto, leído en el texto «ILVIC QUEVEDO» del
     cartel (el titular «Sea & Spice» lo da un punto más oscuro porque la
     textura pasa por encima). Aguanta como TINTA en los cuatro fondos
     del sitio sin retocarlo: 8,15:1 sobre blanco, 6,79 sobre el papel
     nuevo, 6,65 sobre crema y 4,75 sobre arena — el mínimo es 4,5. Y al
     revés, blanco sobre el rojo da 8,15, así que también sirve de
     relleno de botón.

     ⭐ EL PAPEL. La textura del cartel, convertida en una baldosa de
     640 px que se repite sin costura (el salto en la unión mide 2,36
     contra 2,58 del propio grano: la costura es MENOS visible que la
     fibra del papel). 64 KB en WebP. Su color medio es #efecea, que es
     el que se pinta debajo mientras la imagen carga.

     ⚠️ CÓMO TEÑIRLA. La baldosa es casi blanca a propósito. Para papel
     de otro color no se retoca la imagen: se pone el color debajo y se
     mezcla con `background-blend-mode: multiply`. Así una sola imagen
     sirve para el papel claro, el arena y la crema.

     ⭐ LA CALIGRÁFICA. Mr Dafoe, declarada en `fuentes.css`. Para firmar
     un nombre en grande, nunca para leer.                              */
  --rojo-spice:   #a20618;
  --papel-color:  #efecea;
  --papel:        url('../img/textura/papel-freds.webp');
  --papel-lado:   640px;   /* el lado de la baldosa, a 1× */
  /* ⚠️ LA MISMA BALDOSA, YA EN MARRÓN. Sobre el marrón NO se usa la
     baldosa clara con `background-blend-mode: multiply`: el blend obliga
     al navegador a rasterizar la capa aparte y el borde derecho del
     relleno del cruce salía como una LÍNEA CLARA de un píxel —medida:
     pico de 126 sobre un fondo de 90—. Esta versión trae el papel ya
     multiplicado por el #7c533e, así que se pinta como una imagen
     normal, sin blend y sin línea. Su media cae en el marrón de marca al
     decimal, así que las superficies con papel y las lisas son el mismo
     color. 35 KB. */
  --papel-marron: url('../img/textura/papel-marron.webp');
  --caligrafia:   'Mr Dafoe', 'Snell Roundhand', cursive;

  /* ═══════════════════════════════════════════════════════════════════
     EL COLOR DEL BOTÓN — el atardecer (2026-08-21)
     ═══════════════════════════════════════════════════════════════════
     ⭐ Carlos: «Fred's es colores de atardecer». El RELLENO del botón
     deja de ser la terracota del PSD y se va al naranja del sol bajo.
     La terracota sigue mandando en todo lo demás —el bloque de cierre,
     los bordes, las tintas—: esto es sólo el botón.

     ⚠️ Cuanto más vivo el naranja, MENOS contraste aguanta el blanco de
     encima. `#c1571a` es lo más luminoso que aún llega a 4,5:1 con texto
     blanco. Si se sube hacia el ámbar o el amarillo, el texto tiene que
     voltearse a tinta honda — es lo que hace solo el afinador `?botones`.

     ⚠️ El relleno da 2,63:1 contra el papel arena y el mínimo para el
     contorno de un control es 3:1. Por eso el botón lleva SIEMPRE el
     borde hondo: es lo que lo dibuja contra el papel, no el relleno.   */
  /* ⭐ 2026-09-10 · EL BOTÓN SE VA AL ROJO. Carlos aprobó los dos botones
     del cartel Sea & Spice —el relleno rojo y el de contorno— tal cual:
     «me gusta eso, haz esos cambios primero». El naranja de atardecer NO
     se borra: queda aquí debajo con su nombre y vuelve entero con
     `?paleta=terracota`.

     El rojo aguanta mejor que el naranja en los dos sitios donde había
     que medir: blanco encima da 8,15:1 (el naranja daba 4,52, justo en
     el mínimo) y contra el papel arena da 4,75, así que ya no depende
     del borde para dibujarse — aunque el borde se queda, que es lo que
     lo separa de un bloque de color plano. */
  --boton:       var(--rojo-spice);   /* el relleno: 8,15:1 con blanco */
  --boton-honda: #7b0512;             /* el mismo con menos luz: hover y borde */
  --boton-tinta: #ffffff;             /* lo que va encima */
  --boton-borde: var(--boton-honda);  /* 6,53:1 sobre el papel */
  /* ⛔ EL ATARDECER, GUARDADO. Lo que había del 2026-08-21 al 2026-09-10:
     «Fred's es colores de atardecer», el naranja del sol bajo. Cuanto más
     vivo el naranja, menos contraste aguanta el blanco encima: #c1571a
     era lo más luminoso que aún llegaba a 4,5:1. */
  --boton-atardecer:       #c1571a;
  --boton-atardecer-hondo: #9c4411;
  /* ⚠️ EL NARANJA QUE SE PUEDE LEER SOBRE EL PAPEL. El del botón vive
     debajo de un texto blanco, así que su contraste se mide contra el
     blanco; cuando el naranja es el TEXTO y el arena el fondo, hace falta
     otro. `--boton-honda` da 3,77:1 —vale para un contorno, no para
     letras a 22px semibold, que necesitan 4,5—. Éste es el mismo tono de
     atardecer con la luz bajada hasta cumplir: 4,52:1, medido.
     Lo usan los apartados de la carta. */
  /* ⭐ 2026-09-10 · también al rojo: sobre el papel arena da 4,75:1, por
     encima del 4,52 que daba el naranja hondo. El naranja queda al lado
     para el interruptor. */
  --acento-titulo:           var(--rojo-spice);
  --acento-titulo-atardecer: #873d12;

  /* ═══════════════════════════════════════════════════════════════════
     TIPOGRAFÍA — también del PSD
     ═══════════════════════════════════════════════════════════════════
     Georgia para los titulares y Verdana para el texto, que es lo que
     usa el mailing.

     ⚠️ Las dos son fuentes DE SISTEMA: están en todos los Windows y
     todos los Mac desde hace veinte años, así que no hay que descargar
     nada. Eso quita de la web los 1,4 MB de Montserrat y Nunito Sans que
     se servían antes.

     ⚠️ La reserva son fuentes CONCRETAS, nunca `system-ui`: eso
     significaría «la letra que tenga configurada este ordenador» y haría
     que la web se viera distinta en cada máquina. */
  /* ⭐ 'Titular Freds' NO es una fuente descargada: es Georgia con los
     NÚMEROS en Verdana. Carlos, 2026-08-14: «donde haya número, que no
     sea Georgia» — los dígitos de Georgia son de estilo antiguo (bailan
     como minúsculas, con rabos) y en fechas y precios se ven débiles.
     El truco: dos @font-face con el mismo nombre; el que lleva
     `unicode-range` de dígitos apunta a Verdana local y GANA sólo para
     0–9; el resto cae al de Georgia. Cero descargas, aplica en TODO el
     sitio de golpe. Definidos justo después de este bloque. */
  /* ⭐ 2026-08-26 · SE FUE LA SERIF. Al cliente le mandaron quitarla, así
     que Georgia sale de los titulares y entra **Jost** —revival de Futura
     con licencia libre— en los dos papeles. El porqué de Jost y no de la
     Futura de verdad está en `assets/css/fuentes.css`.
     ⚠️ El truco de 'Titular Freds' (Georgia con los dígitos en Verdana)
     deja de hacer falta: Jost trae cifras de caja alta, que es justo lo
     que Carlos pedía el 2026-08-14 con «donde haya número, que no sea
     Georgia». Los dos @font-face de abajo se quedan sin usar, no se
     borran: si vuelve la serif, vuelven con ella. */
  --titulo: 'Jost', 'Futura', 'Century Gothic', 'Trebuchet MS', sans-serif;
  --cuerpo: 'Jost', 'Futura', 'Century Gothic', 'Trebuchet MS', sans-serif;

  /* Escala fluida: un solo salto entre móvil y escritorio, sin saltos
     bruscos por el camino.
     ⚠️ Verdana pinta MÁS GRANDE que Nunito Sans al mismo tamaño (su ojo
     medio es mayor), así que los cuerpos bajan un punto respecto a lo
     que había. */
  --t-titular:  clamp(1.95rem, 5.2vw, 3.9rem);
  /* ⭐ UNA SOLA ESCALA DE SECCIÓN EN TODA LA WEB — Carlos, 2026-08-17:
     «todos los títulos tienen distintos tamaños, el de grupos y el de
     prensa son distintos». Estaba en tres: 34px la portada, 38px el blog
     y los cierres, y 54px las secciones nuevas.

     ⚠️ MANDA LA PEQUEÑA, la de GRUPOS. Se unificó primero hacia arriba
     —a la escala de Señor Frog's, 52px— y Carlos lo corrigió en el acto:
     «el título de grupos era el correcto, los grandes había que llevarlos
     al pequeño». Este sitio no es Frog's: su titular es Georgia, que a 54
     px pesa mucho más que la Oswald condensada de allí. */
  --t-seccion:  clamp(1.38rem, 3.4vw, 2.125rem);
  /* ⚠️ 16px FIJOS, no un clamp que crece. Carlos, 2026-08-20, sobre la
     bajada de la portada en pantalla grande: «tiene que estar a 16, o
     sea bájale, está gigante». Antes iba de 16 en el teléfono a 18,24 a
     partir de ~1300px de ancho, y ese techo era lo que se veía grande.
     Ahora mide lo mismo en todas las pantallas.
     ⚠️ Queda POR DEBAJO del texto corrido (17px). Es a propósito y es lo
     que él pidió; si algún día la entrada tiene que volver a pesar más
     que el cuerpo, se sube aquí y se mueven sus 24 piezas a la vez. */
  /* ⚠️ 2026-08-26 · SUBE A 17 AL CAMBIAR DE LETRA, y sigue siendo el
     mismo diseño. Lo que Carlos aprobó el 2026-08-20 no era el número 16
     sino cómo se veía: la entrada un pelo por encima del texto corrido
     (16 contra 15,5 de Verdana). Al pasar a Jost el cuerpo sube a 16,5, y
     dejar la entrada en 16 la habría puesto POR DEBAJO del texto que
     acompaña — la bajada del hero se vería más pequeña que un párrafo
     cualquiera. Se conserva la proporción, no la cifra. */
  --t-sub:      1.0625rem;   /* 17px */
  --t-rotulo:   .7rem;

  /* ⭐ EL TEXTO CORRIDO, EN DOS ESCALONES Y NO EN NUEVE (2026-08-18)
     La auditoría de este día encontró NUEVE cuerpos distintos de Verdana
     para lo mismo —.92, .93, .94, .95, .96, .98, 1, 1.02 y 1.06rem—,
     repartidos por secciones que se fueron escribiendo por separado. Con
     eso no hay «buena línea» posible: cada página parecía calibrada a su
     manera. Ahora hay dos papeles y nada más:

       --t-cuerpo  el texto que se lee de corrido (el mismo del body)
       --t-apoyo   lo que acompaña: descripciones densas, notas, pies

     Y por encima de los dos sigue `--t-sub`, que es la ENTRADA de una
     página (la bajada bajo el titular). Tres tamaños, tres papeles. */
  /* ⚠️ 15,5px. Carlos, 2026-08-20, sobre el cuerpo de las reseñas —que
     es el mismo de todo el texto corrido—: «manda todo a 15,5». Venía de
     17. Cambiar la variable mueve las ~100 piezas de cuerpo del sitio a
     la vez, que es justo para lo que está.
     ⚠️ Y el APOYO baja con él, de 15,2 a 14,5: a 15,2 se quedaba a tres
     décimas del cuerpo y los dos papeles dejaban de distinguirse —que es
     el problema que se arregló el 2026-08-18, cuando había nueve cuerpos
     de Verdana para lo mismo—. El escalón se conserva. */
  /* ⚠️ 2026-08-26 · SUBEN UN PUNTO AL CAMBIAR DE LETRA, y no es capricho.
     La altura de la x —lo que de verdad decide cómo de grande se ve un
     texto— es 54,5% del em en Verdana y 46,0% en Jost, medido en los
     archivos. Al mismo cuerpo, Jost se lee más pequeña. Igualarlo del
     todo pediría 18,4px y eso rompería la maqueta entera; el punto de
     más es el compromiso: 16,5 en Jost dan la misma mancha que ~15,7 de
     Verdana. El ESCALÓN de 1px entre cuerpo y apoyo se conserva, que es
     lo que mantiene los dos papeles distintos (§40). */
  --t-cuerpo:   1.03125rem;  /* 16,5px, el mismo que lleva el <body> */
  --t-apoyo:    .96875rem;   /* 15,5px */
  --t-boton:    .76rem;      /* 12,2px: uno solo para todos los botones */
  /* ⭐ EL TÍTULO DE UNA TARJETA. Uno solo para todo el sitio: la
     auditoría del 2026-08-17 encontró CINCO tamaños distintos para lo
     mismo —19px en el blog, 20 en la carta, 21 en los pases y en Kids,
     23 en prensa y 26 en los planes de Cancún—. Manda el de los pases de
     la portada, que es el que ya estaba aprobado. */
  --t-tarjeta:  1.32rem;
  /* ⭐ EL TÍTULO DE UNA ENTRADA DE BLOG — 16px. Carlos, 2026-08-21: «los
     títulos del blog, ¿por qué no lo hacemos en 16?».
     No es un tamaño nuevo: la fila de «Últimas del blog» de la portada y
     de `/cancun/` ya estaba en 16 desde que se cerró la escala el
     2026-08-18 —«34 sección · 21,1 tarjeta · 16 blog»—. Lo que pasaba es
     que la rejilla de `/blog/` y los relacionados del pie de un post se
     habían quedado en el tamaño de TARJETA, 21,1, y por eso no cuadraban
     con los de la portada. Ahora el papel tiene nombre y está escrito en
     un solo sitio, así que no se pueden volver a separar. */
  --t-blog:     1rem;

  /* EL CRUCE de la cocina a la barra (2026-08-18, reordenado el 19). Los
     números que mandan en su ritmo, sueltos aquí para poder tocarlos
     desde el afinador `?cruce` sin recompilar nada:
       --cruce-alto    cuánto scroll dura la escena entera
       --cruce-sale    cuándo ARRANCA la ola que cubre
       --cruce-tapa    en qué punto (0→1) queda la pantalla toda marrón
       --cruce-suelta  en qué punto empieza a destaparse
       --cruce-cierra  cuándo la ola que se retira TERMINA de salir
       --cruce-cara    cuándo enciende el texto de la cara que entra
     ⚠️ El orden manda y no se puede alterar sin volver a medir:
     sale < tapa < suelta < cierra ≤ cara. */
  --cruce-alto:   215svh;   /* sólo el tramo del cruce; el riel entero lo
                               suman las piezas de las dos caras */
  --cruce-sale:   .12;
  --cruce-tapa:   .35;
  --cruce-suelta: .64;
  --cruce-cierra: .91;
  --cruce-cara:   .91;

  /* ⚠️ POR QUÉ EL CRUCE MIDE 215svh Y NO 170 (2026-08-19). Los dos huecos
     nuevos —el que usa la cocina para irse y el que espera la barra— hay
     que PAGARLOS con scroll, o salen del ritmo que Carlos ya aprobó. Los
     números están puestos para que los tres tramos de siempre midan
     exactamente lo que medían: barrido 51svh, tapado 61 y retirada 58.
     Lo que crece es la escena, no la prisa. En scroll: 25 · 51 · 61 · 58
     · 19 svh. */

  /* ⚠️ El tramo TAPADO pasó de un 10% del cruce a un 36% (2026-08-18):
     ahí vive la cita de Food&Travel y con 10svh de scroll no daba tiempo
     ni a leerla. Sigue siendo el 30% del cruce: ~57svh.

     ⭐ POR QUÉ HAY UN HUECO AL PRINCIPIO Y OTRO AL FINAL (2026-08-19).
     Carlos, sobre dos capturas: «cuando la ola llega al texto se ve como
     un error; el texto debe desaparecer ANTES de que la ola le llegue» y
     «el texto de la bebida aparece antes de que la ola termine de
     llegar». Medido con `_herramientas/medir-cruce.js`: el texto de
     cocina se quedaba a opacidad 1 mientras su caja pasaba de 0 a 98%
     cubierta de marrón, y el de la barra encendía con la suya aún 27%
     tapada. Por eso la ola ya no arranca en 0 sino en `--cruce-sale`
     —ese hueco es el que usa la cocina para irse— y ya no termina en 1
     sino en `--cruce-cierra`, dejando el final limpio para que entre la
     barra sobre pantalla quieta. */

  /* Los tres botones de la cabecera (idioma · grupos · reservar) comparten
     una sola altura desde el 2026-08-18; en móvil ya era 38 desde el 14. */
  --alto-boton-cabecera: 38px;

  /* Ritmo */
  --aire:        22px;           /* aire lateral en móvil */
  --ancho:       1240px;
  --medida:      62ch;           /* lectura cómoda; Verdana ocupa más */
  --hueco-bloque: clamp(52px, 6.5vw, 104px);

  /* ⭐ LA OLA DE MARCA — el mismo filo ondulado que cruza los pases de la
     portada, disponible para todo el sitio. Las interiores no lo usaban y
     por eso se leían como cajas de plantilla: el sistema tiene un motivo
     fuerte y ellas se salían de él.
     Es el polígono base que generó `_herramientas/generar-olas.py`; los
     pases siguen teniendo el suyo por platillo para poder interpolar. */
  --ola-marca: polygon(16.11% 0%, 17.38% 2%, 17.90% 5%, 17.72% 8%, 16.97% 10%, 15.91% 12%, 14.77% 15%, 13.80% 18%, 13.12% 20%, 12.75% 22%, 12.60% 25%, 12.47% 28%, 12.17% 30%, 11.50% 32%, 10.35% 35%, 8.74% 38%, 6.79% 40%, 4.75% 42%, 2.91% 45%, 1.56% 48%, 0.93% 50%, 1.13% 52%, 2.13% 55%, 3.76% 58%, 5.76% 60%, 7.81% 62%, 9.63% 65%, 11.00% 68%, 11.84% 70%, 12.17% 72%, 12.14% 75%, 11.96% 78%, 11.84% 80%, 11.95% 82%, 12.35% 85%, 13.00% 88%, 13.74% 90%, 14.32% 92%, 14.52% 95%, 14.12% 98%, 13.03% 100%, 100% 100%, 100% 0%);

  /* Para lo que ENTRA o SALE: arranca rápido y frena mucho. */
  --curva: cubic-bezier(.16, 1, .3, 1);
  /* ⚠️ Para lo que sólo cambia de COLOR. La curva de arriba es un
     expo-out muy marcado: en un desplazamiento se lee como energía, pero
     en un cambio de color hace que salte de golpe y luego no pase nada.
     Un color quiere una curva pareja. */
  --curva-color: cubic-bezier(.4, 0, .2, 1);

  /* Alto real de la cabecera. Lo mide y lo publica `sitio.js`; este valor
     es sólo la reserva para el primer pintado y para cuando no hay
     JavaScript. ⛔ No escribir la altura a mano en ningún otro sitio. */
  --alto-cabecera: 88px;
  --alto-indice: 45px;
}

/* Los números de los títulos, en Verdana — ver la nota de `--titulo`. */
@font-face {
  font-family: 'Titular Freds';
  src: local('Georgia');
  font-weight: normal;
}
@font-face {
  font-family: 'Titular Freds';
  src: local('Georgia Bold'), local('Georgia-Bold');
  font-weight: bold;
}
@font-face {
  font-family: 'Titular Freds';
  src: local('Verdana');
  font-weight: normal;
  unicode-range: U+0030-0039;
}
@font-face {
  font-family: 'Titular Freds';
  src: local('Verdana Bold'), local('Verdana-Bold');
  font-weight: bold;
  unicode-range: U+0030-0039;
}


/* ⛔ NO HAY MODO OSCURO. A propósito.
   La web de Fred's es clara, como el sitio publicado. Se probó a seguir el
   modo del sistema (`prefers-color-scheme`) y el resultado es que en un Mac
   configurado en oscuro —que son muchos— la web sale negra sin que nadie lo
   haya decidido. La identidad de la marca no la elige el sistema operativo
   del visitante.

   Si algún día se quiere modo oscuro, se hace con un interruptor propio en
   la web, no automático. */


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

html {
  /* ⭐ LA WEB DECLARA SU PROPIO ESQUEMA, no hereda el del visitante.
     Sin esta línea, en un ordenador configurado en oscuro el navegador
     pinta EN OSCURO lo que él controla aunque la página sea blanca: la
     barra de desplazamiento, los campos de formulario, los desplegables
     y el fondo que asoma al rebotar el scroll. La página salía clara y
     el marco alrededor, negro. */
  color-scheme: light;
  /* El color con que el navegador pinta lo seleccionado y las casillas
     también sale de los ajustes del sistema si no se fija aquí. */
  accent-color: var(--acento);
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* la cabecera fija y el índice de la carta no tapan las anclas */
  scroll-padding-top: calc(var(--alto-cabecera) + var(--alto-indice) + 12px);
}

body {
  margin: 0;
  background: var(--fondo);
  color: var(--texto);
  font-family: var(--cuerpo);
  /* ⚠️ En píxeles y no con la variable, como estaba desde el principio:
     así el cuerpo base no depende de nada. Pero es EL MISMO PAPEL que
     `--t-cuerpo`, así que los dos números cambian juntos o se abre otra
     vez la brecha de cuerpos distintos para lo mismo. */
  font-size: 16.5px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, video, svg { max-width: 100%; display: block; height: auto; }

a { color: inherit; text-underline-offset: .22em; }

::selection { background: var(--acento); color: #fff; }

:focus-visible {
  outline: 2px solid var(--acento);
  outline-offset: 3px;
}

.salto-contenido {
  position: absolute; left: -9999px;
  background: var(--acento); color: #fff; padding: 12px 20px; z-index: 100;
}
.salto-contenido:focus { left: 12px; top: 12px; }

.contenedor { max-width: var(--ancho); margin: 0 auto; padding-inline: var(--aire); }

/* ── Tipografía ────────────────────────────────────────────────────── */
h1, h2, h3, h4 {
  font-family: var(--titulo);
  font-weight: 600;
  letter-spacing: -.015em;
  line-height: 1.1;
  margin: 0;
  text-wrap: balance;
}

/* ⭐ LA ESCALA, POR DEFECTO — Carlos, 2026-08-18
   =====================================================================
   Hasta hoy esta regla NO daba tamaño, así que un encabezado al que
   nadie hubiera puesto una clase caía en el tamaño del NAVEGADOR (1.5em
   para un h2) y se salía de la escala sin que se notara. Así estaban:

     · /groups/        «Exclusive villas» y el de contacto → 25,5px
     · /reservations/  «Hours» y «Address»                 → 13,1px

   Ninguno de los dos tenía una sola línea de CSS propia. Ahora el que no
   diga nada sale ya en la escala de la casa, y el que necesite otra cosa
   la pide con su clase — que es como debe ser.

   ⚠️ El h1 se queda fuera a propósito: los suyos ya los ponen el hero y
   el banner, y meterlo aquí lo dispararía a `--t-titular`.
   ⚠️ Los h2 de reservaciones son un caso aparte y lo dicen ellos mismos
   con su clase: van de rótulo, no de titular (ver `.reservas h2`). */
h2 { font-size: var(--t-seccion); }
h3 { font-size: var(--t-tarjeta); }
h4 { font-size: var(--t-sub); }

p { margin: 0 0 1em; max-width: var(--medida); }

/* ── VIUDAS ────────────────────────────────────────────────────────
   ⭐ LEY DE LA CASA (Carlos, 2026-08-17): en ninguna parte de la web
   puede quedar una palabra sola en la última línea.

   Primera capa, la barata: `text-wrap: pretty` le pide al navegador que
   reparta las líneas para que la última no se quede huérfana. Cubre todo
   el texto corrido de golpe, incluidos los textos que vienen de la base
   de datos y que nadie va a repasar a mano.

   ⚠️ NO BASTA SOLA: es una petición, no una garantía, y los navegadores
   viejos la ignoran. La segunda capa —`sin_viuda()` en `partials/init.php`,
   que cose las dos últimas palabras con un espacio duro— es la que
   asegura los textos que sí controlamos. Las dos juntas.

   Se mide con `_herramientas/buscar-viudas.js`, que recorre las 23 rutas
   en tres anchos y cuenta las que quedan. */
p, li, figcaption, blockquote, dd, dt, address,
.plato__desc, .tarjeta__extracto, .blog-home__titulo, .tarjeta__titulo {
  text-wrap: pretty;
}

/* El rótulo pequeño de sección. Se usa con cuentagotas: si aparece
   encima de cada bloque, deja de significar nada. */
.rotulo {
  font-family: var(--titulo);
  font-size: var(--t-rotulo);
  font-weight: 600;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--acento-tinta);
  margin: 0 0 .9em;
}

/* ── Botones ───────────────────────────────────────────────────────── */
.boton {
  display: inline-block;
  font-family: var(--titulo);
  font-size: var(--t-boton);
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 15px 30px;
  border: 1px solid currentColor;
  color: var(--texto);
  background: transparent;
  white-space: nowrap;
  transition: background .22s var(--curva-color), color .22s var(--curva-color),
              border-color .22s var(--curva-color), transform .16s var(--curva);
}
.boton:hover { background: var(--texto); color: var(--fondo); }
.boton:active { transform: translateY(1px); }

/* El botón principal: el NARANJA DE ATARDECER, con texto BLANCO.
   ⚠️ Cuando el acento era dorado, encima iba tinta oscura. Con la
   terracota del PSD eso ya no vale: un marrón sobre terracota da 1,8:1.
   El blanco da 5,20:1, que es lo único que cumple sobre aquel relleno.
   ⭐ 2026-08-21: el relleno pasa a `--boton` (#c1571a). El blanco sigue
   siendo el que va encima —4,50:1—, y el borde es el tono hondo, que es
   lo que dibuja el botón contra el papel arena. */
.boton--principal {
  background: var(--boton);
  border-color: var(--boton-borde);
  color: var(--boton-tinta);
}
.boton--principal:hover {
  background: var(--boton-honda);
  border-color: var(--boton-honda);
  color: #fff;
}

/* Sobre las secciones oscuras el botón de línea cambia de tinta. Sin
   esto hereda la tinta del modo claro y queda invisible sobre el azul. */
/* Sobre la terracota del cierre el botón va en blanco, y el principal se
   invierte a marrón hondo, que es lo que más resalta ahí. */
.cierre-carta .boton {
  color: #fff; border-color: rgb(255 255 255 / .7);
}
.cierre-carta .boton:hover { background: #fff; color: var(--acento-tinta); border-color: #fff; }
/* ⛔ Este botón era `#4a3125` sobre terracota: **2.3:1** de contraste
   contra su propia banda. Se leía como un bloque plano pegado al fondo,
   no como un botón. Carlos, 2026-08-14: «se pierde el estilo del botón».
   El crema de la paleta da 4.24 contra la banda y 6.32 con su texto
   dentro — casi el doble por fuera y muy holgado por dentro. Es además
   lo que ya hacía el `:hover` de los botones de línea de esta sección. */
.cierre-carta .boton--principal {
  background: var(--crema); border-color: var(--crema);
  color: var(--acento-tinta);
  margin-top: clamp(18px, 3vh, 30px);   /* aire propio: no lo heredaba de nadie */
}
.cierre-carta .boton--principal:hover {
  background: #fff; border-color: #fff; color: var(--acento-tinta);
}

/* ⭐ EL BOTÓN NARANJA SOBRE LA ESCENA OSCURA DE GRUPOS
   =====================================================================
   Carlos, 2026-08-21: «igual al de Book a table», así que aquí también
   va el relleno naranja. Pero el naranja contra el marrón del velo da
   **1,03:1**: el botón existía y no se veía, que es justo lo que este
   sitio no hace. Lo que lo dibuja es un borde CLARO —6,6:1 contra el
   velo—, no un cambio de relleno. El color se respeta; lo que se añade
   es el contorno que le faltaba. */
.grupos-home__texto .boton--principal {
  border-color: var(--crema);
}
.grupos-home__texto .boton--principal:hover {
  background: var(--boton-honda); border-color: #fff;
}

/* El botón CLARO: para las secciones oscuras, donde el relleno terracota
   se apaga contra el velo. Papel de la casa y tinta encima — el mismo
   contraste que un botón normal, pero invertido. */
.boton--claro {
  background: var(--crema); border-color: var(--crema); color: var(--tinta);
}
.boton--claro:hover { background: #fff; border-color: #fff; color: var(--acento-tinta); }

/* ── Cabecera ──────────────────────────────────────────────────────── */
.cabecera {
  position: fixed; inset: 0 0 auto 0; z-index: 50;
  transition: background .35s var(--curva), border-color .35s var(--curva);
  border-bottom: 1px solid transparent;
}
/* La cabecera es del color del papel, como el resto del sitio. Para eso
   el logo tiene una versión oscura: el original es blanco y sobre papel
   claro desaparecía. */
.cabecera { background: var(--fondo); border-bottom-color: var(--borde); }
.cabecera.solida {
  background: var(--fondo);
  box-shadow: 0 1px 0 var(--borde);
}

/* ── La cabecera sobre el hero de la portada ────────────────────────
   Regla de la casa: la portada abre con el vídeo ocupando el 100% de la
   pantalla, y la cabecera flota encima sin caja para no partirlo. Es lo
   que ya hacen Señor Frog's y Nicoletta.

   Mientras flota, el logo es el BLANCO y la tinta del menú es blanca; en
   cuanto se baja de 40 px entra `.solida` y todo vuelve al papel y al
   logo oscuro. Las dos versiones del logo viven en el HTML: cambiarlas
   por JS haría parpadear la imagen en cada scroll.

   La legibilidad no la da una cortinilla plana —eso mataría el vídeo—
   sino el degradado de `.hero--video::after`, oscuro sólo en la franja
   de arriba, que es justo donde vive este menú.                        */
/* ⛔ NADA DE CAJA DETRÁS DE LA CABECERA EN LA PORTADA.
   Hubo aquí un velo azul translúcido con desenfoque, al estilo del pill
   rojo de Señor Frog's. Se quitó: por muy suave que fuera, se leía como
   una caja gris pegada encima del vídeo y partía la imagen en dos.

   La legibilidad se resuelve sin caja, con dos cosas que no se ven:
     · el viñeteado de arriba del hero (`.hero--video::after`), que es un
       degradado continuo desde el borde de la pantalla y se lee como
       fotografía, no como interfaz;
     · una sombra en la propia letra, que es lo que la despega del fondo
       cuando el fotograma es claro.
   Las dos juntas, y ninguna dibuja un contorno. */
:is(.pagina-home, .con-banner) .cabecera:not(.solida) {
  background: transparent;
  border-bottom-color: transparent;
  box-shadow: none;
}
/* ⚠️ `.cabecera__grupos` YA NO ESTÁ AQUÍ. Estas tres reglas pintan de
   blanco y sombrean lo que es texto suelto sobre el vídeo; desde el
   2026-08-21 ese botón lleva relleno naranja y letra blanca propias, y
   heredar de aquí le borraba el color y le metía sombra en la letra. */
:is(.pagina-home, .con-banner) .cabecera:not(.solida) .nav__enlace,
:is(.pagina-home, .con-banner) .cabecera:not(.solida) .cabecera__idioma,
:is(.pagina-home, .con-banner) .cabecera:not(.solida) .cabecera__marca {
  text-shadow: 0 1px 10px rgba(10, 20, 28, .75), 0 1px 2px rgba(10, 20, 28, .5);
}
/* El logo no es texto: se le da la misma sombra por filtro. */
:is(.pagina-home, .con-banner) .cabecera:not(.solida) .cabecera__marca {
  filter: drop-shadow(0 1px 10px rgba(10, 20, 28, .75))
          drop-shadow(0 1px 2px rgba(10, 20, 28, .5));
}
/* Sobre el vídeo, el wordmark se pinta en blanco. */
:is(.pagina-home, .con-banner) .cabecera:not(.solida) .cabecera__marca { background-color: #fff; }

:is(.pagina-home, .con-banner) .cabecera:not(.solida) .nav__enlace,
:is(.pagina-home, .con-banner) .cabecera:not(.solida) .cabecera__idioma {
  color: #fff;
}
:is(.pagina-home, .con-banner) .cabecera:not(.solida) .cabecera__idioma { border-color: rgba(255,255,255,.55); }
:is(.pagina-home, .con-banner) .cabecera:not(.solida) .cabecera__idioma:hover {
  border-color: #fff; color: #fff; background: rgba(255,255,255,.12);
}
:is(.pagina-home, .con-banner) .cabecera:not(.solida) .cabecera__hamburguesa span { background: #fff; }
.cabecera__interior {
  max-width: var(--ancho); margin: 0 auto;
  padding: 6px var(--aire);        /* la mitad del aire de antes (eran 12) */
  display: flex; align-items: center; gap: 10px;
  /* ⚠️ El mínimo baja de 68 a 44 px porque si no, no serviría de nada
     recortar el aire: con 68 de mínimo el alto lo mandaba esta línea y no
     el contenido. 44 px es la zona táctil mínima, por debajo de eso los
     enlaces dejan de poder pulsarse con el pulgar. */
  min-height: 44px;
  /* Por encima del velo de la portada, que se pinta en el ::before. */
  position: relative; z-index: 1;
}
/* ⚠️ En escritorio la cabecera va A TODO EL ANCHO con 60 px de aire fijo,
   no metida en la caja de 1240 px del resto del sitio. Lo pidió Carlos el
   2026-08-11.

   Consecuencia buscada: el logo YA NO queda alineado en vertical con los
   titulares de las secciones de abajo, que siguen dentro de la caja
   centrada. En pantallas anchas la diferencia es grande —a 1920 px los
   titulares empiezan a 340 px del borde y el logo a 60—, así que si algún
   día se busca esa alineación, esto es lo que hay que revertir.

   En móvil no cambia nada: los 22 px de `--aire` de siempre. */
@media (min-width: 900px) {
  /* Tres zonas: logo a la izquierda, el menú CENTRADO y las acciones
     (idioma + reservar) a la derecha.

     Va en rejilla de `1fr auto 1fr` y no en flex con márgenes automáticos
     porque así el menú queda en el centro REAL de la pantalla. Con flex
     quedaría centrado entre el logo y el botón, que miden distinto, y se
     vería descuadrado hacia un lado.

     `justify-self` en los extremos evita que el enlace del logo estire su
     zona clicable por toda la columna. */
  .cabecera__interior {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 18px;
    max-width: none;
    padding: 7px 60px;    /* la mitad del aire de antes (eran 14) */
  }
  .cabecera__logo { justify-self: start; }
  .cabecera__nav { justify-self: center; margin-left: 0; }
  .cabecera__acciones { justify-self: end; margin-left: 0; }
}
/* El wordmark, pintado con máscara. La tinta la pone `background-color`:
   oscura sobre papel, blanca sobre el vídeo de la portada.

   `aspect-ratio` con las medidas reales del archivo (2513×579) reserva
   el alto desde el primer pintado, así que la cabecera no salta.

   Tamaño: un 30 % por debajo del primer montaje (eran 150/180 px), a
   petición de Carlos el 2026-08-11. */
.cabecera__marca {
  display: block;
  width: 105px;
  aspect-ratio: 2513 / 579;
  background-color: var(--texto);
  /* ⛔ RUTA RELATIVA, NO ABSOLUTA. Esto decía `/assets/img/...` y el logo
     DESAPARECÍA cuando el sitio no vive en la raíz del dominio —Carlos lo
     subió a `157.230.218.127/fredsnewweb/` el 2026-08-21 y la cabecera
     salió sin logo—.
     El filtro `iniciar_base_url()` arregla las rutas absolutas del HTML,
     pero NO entra en los archivos CSS: éstos se sirven tal cual. Desde
     `/assets/css/` la imagen está en `../img/`, y eso vale igual en la
     raíz que en una subcarpeta, sin depender de ningún filtro. */
  -webkit-mask: url("../img/marca/freds-wordmark.png") no-repeat center / contain;
          mask: url("../img/marca/freds-wordmark.png") no-repeat center / contain;
}
@media (min-width: 900px) { .cabecera__marca { width: 126px; } }

.cabecera__nav { display: none; margin-left: auto; }
.nav { list-style: none; display: flex; gap: 28px; margin: 0; padding: 0; }
.nav__enlace {
  font-family: var(--titulo); font-size: .76rem; font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; text-decoration: none;
  /* 44px de alto: es la zona de toque mínima cómoda, y en escritorio
     además ensancha el blanco de la barra. */
  padding: 12px 0; display: inline-flex; align-items: center; min-height: 44px;
  border-bottom: 1px solid transparent;
  transition: border-color .25s var(--curva), color .25s var(--curva);
}
.nav__enlace:hover { color: var(--acento-tinta); border-bottom-color: var(--acento); }

.nav__item--submenu { position: relative; }
.nav__submenu {
  /* ⚠️ Sin `min-width: 190px` (2026-09-15): con los enlaces a 18 px del
     filo izquierdo, la caja dejaba 103 px vacíos a la derecha de «Food
     Menu». Ahora se ciñe a su enlace más largo y el aire es igual a los
     dos lados. */
  position: absolute; top: 100%; left: -22px; width: max-content;
  list-style: none; margin: 0; padding: 10px 0;
  background: var(--fondo-alto); border: 1px solid var(--borde);
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity .22s var(--curva), transform .22s var(--curva), visibility .22s;
}
.nav__item--submenu:hover .nav__submenu,
.nav__desplegable[aria-expanded="true"] + .nav__submenu {
  opacity: 1; visibility: visible; transform: none;
}
.nav__submenu a {
  display: block; padding: 9px 22px; text-decoration: none;
  font-size: .88rem;
}
.nav__submenu a:hover { background: var(--fondo-hondo); color: var(--acento-tinta); }


.cabecera__acciones { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.cabecera__nav + .cabecera__acciones { margin-left: 0; }

.cabecera__idioma {
  font-family: var(--titulo); font-size: .72rem; font-weight: 600;
  letter-spacing: .14em; text-decoration: none;
  padding: 10px; border: 1px solid var(--borde);
  transition: border-color .25s var(--curva), color .25s var(--curva);
}
.cabecera__idioma:hover { border-color: var(--acento); color: var(--acento-tinta); }

/* El botón de Reservar está SIEMPRE visible, también en móvil: es la
   acción que da de comer al restaurante. Lo que cambia es la etiqueta. */
.cabecera__reserva { display: inline-block; padding: 12px 16px; }
@media (min-width: 900px) { .cabecera__reserva { padding: 13px 24px; } }
.cabecera__reserva-largo { display: none; }
.cabecera__reserva-corto { display: inline; }

.cabecera__hamburguesa {
  width: 40px; height: 44px; margin-right: -8px; background: none; border: 0; cursor: pointer;
  display: grid; gap: 5px; place-content: center; padding: 0;
}
.cabecera__hamburguesa span {
  display: block; width: 22px; height: 2px; background: var(--texto);
  transition: transform .3s var(--curva), opacity .2s;
}
.cabecera__hamburguesa[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.cabecera__hamburguesa[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.cabecera__hamburguesa[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }


/* ── Menú móvil ──────────────────────────────────────────────────────
   ⚠️ 2026-08-13 · ENTRA, no aparece de golpe. Antes pasaba de `hidden` a
   visible sin transición: un salto seco en el elemento más usado del
   móvil, y la hamburguesa que lo abre sí morphea. Ahora baja desde el
   filo de la cabecera, que es de donde viene.

   ⚠️ Se anima con `@starting-style`, no con `@keyframes`: así el estado
   se puede RETOMAR a mitad. Con keyframes, cerrar antes de que termine
   de abrirse reinicia la animación desde cero y da un tirón.

   ⚠️ `display` va en `transition-behavior: allow-discrete`, porque el
   panel usa el atributo `hidden`: sin eso el navegador lo quita del
   layout antes de que la salida haya terminado. */
.menu-movil {
  /* ⭐ NO LLEGA AL FILO IZQUIERDO. Deja 52px por los que se sigue viendo
     la página de debajo, y eso es lo que hace que el menú se lea como
     una hoja que se ha puesto ENCIMA y no como otra pantalla. Es lo que
     hace el de Frog's, y funciona por el mismo motivo. */
  position: fixed; inset: var(--alto-cabecera) 0 0 52px; z-index: 45;
  /* Marrón de la casa: el papel arena no valía porque es el mismo color
     que la página, y el menú no se despegaba de lo que hay detrás. */
  background: var(--marron);
  padding: 22px 26px calc(18px + var(--hueco-barra, 144px));
  overflow-y: auto;
  box-shadow: -18px 0 40px rgba(26, 16, 10, .34);

  opacity: 1; transform: translateX(0);
  transition: opacity .22s var(--curva-color),
              transform .3s var(--curva),
              display .3s allow-discrete;
}
.menu-movil[hidden] {
  display: none;
  opacity: 0; transform: translateX(14px);
}
@starting-style {
  .menu-movil:not([hidden]) { opacity: 0; transform: translateX(14px); }
}
@media (prefers-reduced-motion: reduce) {
  .menu-movil, .menu-movil[hidden] { transform: none; }
}

/* ── El interruptor de idioma, arriba ───────────────────────────────
   Antes era el último elemento de la lista, entre «Blog» y el final:
   un idioma no es un destino más, es un interruptor, y ahí abajo ni se
   veía. */
.menu-movil__idiomas { display: flex; gap: 8px; margin-bottom: 20px; }
/* ⚠️ `.menu-movil .menu-movil__idioma`, no la clase a secas: si no, la
   regla de los ENLACES del menú —que es `.menu-movil a`, y pesa más que
   una clase suelta— le imponía su cuerpo de 1.24rem y sus versalitas.
   Se veía clarísimo: el «EN» pequeño dentro de su píldora y el «ES»
   enorme saliéndose de la suya. */
.menu-movil .menu-movil__idioma {
  font-family: var(--titulo); font-size: .72rem; font-weight: 700;
  letter-spacing: .16em;
  min-width: 46px; min-height: 34px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid rgb(255 255 255 / .34);
  /* ⚠️ .80, no .72: sobre el marrón del panel, .72 se queda en 4,35:1 y
     el mínimo es 4,5. Con .80 sube a 4,95. Medido, no elegido a ojo. */
  color: rgb(255 255 255 / .80); text-decoration: none;
}
.menu-movil .menu-movil__idioma.es-actual {
  background: var(--boton); border-color: var(--boton-borde); color: #fff;
}
.menu-movil .menu-movil__idioma:hover { padding-left: 0; }

.menu-movil ul { list-style: none; margin: 0; padding: 0; }

/* ── Los enlaces: peso de titular, no de párrafo ────────────────────
   ⚠️ VAN EN VERSALITAS. En minúsculas y a 1.1rem —como estaban— los
   ocho pesaban lo mismo que el texto corrido del sitio y la lista no
   tenía jerarquía ninguna. */
.menu-movil a {
  /* ⚠️ 12px de aire y 1.14rem, no 14 y 1.24: con los ocho enlaces, las
     tres cartas y el botón de reservar, la lista no cabía de una vez en
     una pantalla de 844 y el botón quedaba escondido detrás de la barra
     de abajo. Medido a 390×844. */
  display: block; padding: 12px 0; text-decoration: none;
  font-family: var(--titulo); font-size: 1.14rem; font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase;
  color: #fff;
  border-bottom: 1px solid rgb(255 255 255 / .14);
  transition: color .18s var(--curva-color), padding-left .18s var(--curva);
}
.menu-movil a:hover, .menu-movil a:active { color: var(--boton); padding-left: 6px; }

/* Las tres cartas cuelgan de «Menú»: más pequeñas, y con un filete del
   color de la casa que dice de quién dependen. */
.menu-movil__hijo a {
  font-size: .88rem; font-weight: 500; letter-spacing: .1em;
  /* ⚠️ .80: con .74 el nombre de la carta daba 4,48:1 sobre el panel,
     dos centésimas por debajo del mínimo. */
  color: rgb(255 255 255 / .80);
  padding-left: 16px; margin-left: 2px;
  border-left: 2px solid var(--boton);
  border-bottom-color: rgb(255 255 255 / .08);
}

/* La acción, al final del todo y a todo el ancho. */
.menu-movil__reservar {
  display: block; text-align: center; margin-top: 24px;
}

main { padding-top: var(--alto-cabecera); }
.pagina-home main { padding-top: 0; }   /* la portada empieza bajo la cabecera */

/* =====================================================================
   PORTADA
   =====================================================================
   ⭐ LA REGLA DE LA CASA: la portada abre al 100%.
   Todas las webs de Grupo Anderson's arrancan con el vídeo ocupando la
   pantalla entera. Nada de heros partidos en dos columnas: el 50/50 no
   se usa para abrir. Comprobado en Señor Frog's (`.hero{height:100dvh}`
   con el vídeo en `object-fit:cover`) y en Nicoletta (slider a ancho
   completo). En los dos, además, el hero NO lleva titular encima: es
   media pura, y la primera palabra de la página vive en la banda que
   viene justo debajo. Aquí se hace igual.

   Eso resuelve de paso el problema que tenía el hero partido: no hay que
   proteger ningún titular del vídeo claro, porque no hay titular. Lo
   único que se superpone es la cabecera, y de eso se encarga la franja
   de arriba del degradado.
   ===================================================================== */
/* ── La apertura: el vídeo se retira y el texto ocupa su sitio ──────
   El vídeo se queda pegado arriba y la banda azul sube por encima. Lo
   hace `position: sticky` de CSS, no GSAP: el `pin` inyecta un
   `pin-spacer` que descoloca todo lo que venga después.

   ⛔ Nada de `overflow` en `.apertura` — anclaría el sticky a este
   contenedor en el Safari de iPhone. */
.apertura { position: relative; background: var(--marron); }

.hero--video {
  position: sticky; top: 0;
  width: 100%;
  /* ⛔ `lvh`, NI `dvh` NI `svh`. Vale para TODAS las pantallas pegadas
     del sitio (portada, banners, propuesta, Las Villas, pases, grupos).
     · 2026-09-23 · Con `dvh` el vídeo cambiaba de alto al plegarse la
       barra de Safari —justo al empezar a bajar— y se re-encuadraba de
       golpe. Se pasó a `svh`.
     · 2026-09-28 · Carlos, con captura del iPhone: con la barra PLEGADA,
       `svh` (el alto con la barra desplegada) se quedaba ~80 px corto y
       asomaba una franja marrón vacía bajo la escena de Las Villas.
     `lvh` es el alto con la barra plegada: tapa siempre la pantalla y
     tampoco cambia con la barra. Con la barra desplegada, lo que sobra
     queda debajo de ella, fuera de la vista. En escritorio no hay barra
     que plegar: lvh = svh = vh. Es el mismo alto que mide
     `altoPantalla()` en sitio.js. Los RIELES siguen en `svh`. */
  height: 100lvh;
  min-height: 520px;      /* en apaisado de móvil, que no quede una ranura */
  overflow: hidden;
  background: var(--marron);  /* mientras el vídeo carga, azul, nunca blanco */
}
.hero__media { position: absolute; inset: 0; }
.hero__video {
  width: 100%; height: 100%; object-fit: cover; display: block;
  /* Se va quedando atrás mientras la banda sube y se desenfoca, como si
     la vista se fuera del vídeo al texto. `--retirada` la publica el JS
     entre 0 y 1.

     ⚠️ El 1.12 de base no es estético, es margen de seguridad. Un
     `blur` difumina TAMBIÉN el borde de la imagen: sin escalar de más,
     por los cuatro lados asomaría un halo del fondo. La regla es margen
     ≥ 2× el radio del desenfoque, y en móvil ese margen es el más
     apretado (12 % de 390 px = 23 px de sobra por lado, para 8 px de
     blur). Si algún día se sube el blur, hay que subir esto también. */
  transform: scale(1.12) translateY(calc(var(--retirada, 0) * -4%));
  filter: blur(calc(var(--retirada, 0) * 8px));
  will-change: transform, filter;
}
@media (min-width: 900px) {
  /* En escritorio hay margen de sobra para desenfocar más. */
  .hero__video { filter: blur(calc(var(--retirada, 0) * 14px)); }
}
/* El apagado. Cuanto más sube la banda, más se hunde el vídeo en el azul
   de la casa. No llega a 1: el vídeo nunca desaparece del todo, sigue
   intuyéndose detrás. */
.hero--video::before {
  content: "";
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: var(--marron);
  opacity: calc(var(--retirada, 0) * .78);
}
.hero--video::after { z-index: 2; }

/* La banda pasa POR ENCIMA del vídeo pegado. */
.bienvenida { position: relative; z-index: 3; }

/* Las piezas del texto entran escalonadas cuando la banda llega. El
   retardo lo pone `--n` en cada una desde el JS. Igual que el resto del
   sitio, sólo esconde si hay JavaScript que pueda devolverlas. */
.js .bienvenida__pieza {
  opacity: 0; transform: translateY(22px);
  transition: opacity .7s var(--curva), transform .7s var(--curva);
  transition-delay: calc(var(--n, 0) * .09s);
}
.js .bienvenida.visible .bienvenida__pieza { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .hero__video { transform: none; filter: none; }
  .hero--video::before { opacity: 0; }
  .js .bienvenida__pieza { opacity: 1; transform: none; transition: none; }
}

/* La única capa sobre el vídeo. Oscura arriba —donde vive el menú—,
   completamente limpia en el centro para que el vídeo se vea puro, y un
   punto abajo para que el vídeo no choque a hueso con la banda que
   sigue. `pointer-events: none` porque encima hay enlaces.

   ⚠️ La franja de arriba SÍ es lo que hace legible el menú, desde que se
   quitó la caja de la cabecera. Es larga a propósito —muere al 34 % de
   la pantalla— porque así se lee como el viñeteado de una fotografía y
   no como un rectángulo puesto encima. Acortarla la convierte en caja;
   aclararla deja el menú por debajo del mínimo de contraste sobre los
   fotogramas claros.                                                   */
.hero--video::after {
  content: "";
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg,
    /* Sin la franja oscura de arriba (2026-10-09, «quitar fade de
       header»): el menú se sostiene con la sombra de su propia letra. */
    rgba(124, 83, 62, 0)     0%,
    rgba(124, 83, 62, 0)    70%,
    rgba(124, 83, 62, .40) 100%);
}

/* ── La banda de bienvenida ─────────────────────────────────────────
   Aquí es donde empieza a hablar la web: el rótulo, el titular, la
   entrada y las dos acciones. Es el sitio que en Señor Frog's ocupa la
   banda roja del WELCOME. Va sobre el azul de la laguna para que el
   corte con el vídeo sea un golpe de marca y no un desvanecido. */
/* ── La banda de bienvenida, en cristal ─────────────────────────────
   No es un bloque opaco: es un cristal esmerilado por el que se sigue
   viendo el vídeo, ya desenfocado y apagado por la retirada. El azul es
   el de la marca (`--pizarra`), no un negro — Fred's no tiene negro en
   su paleta.

   ⚠️ El azul sólido vive en `.apertura`, no aquí. Es el respaldo: si el
   vídeo no llegara a estar detrás —no ha cargado, el `sticky` no se
   aplica, el navegador no soporta `backdrop-filter`— el texto blanco
   quedaría sobre el papel blanco del body y no se leería nada. Con el
   respaldo, lo peor que pasa es que se vea el azul plano de siempre. */
.bienvenida {
  position: relative;
  color: var(--sobre-hondo);
  /* Cuánto tarda el cristal en formarse. El aire de arriba se calcula a
     partir de aquí para que el texto empiece SIEMPRE cuando el cristal
     ya está hecho: si el rótulo cayera dentro del fundido, se leería
     sobre el vídeo a medio tapar. Cambiar el fundido mueve el aire solo. */
  --fundido: 200px;
  padding-top: calc(var(--fundido) + 24px);
  padding-bottom: clamp(56px, 7vw, 96px);
}
@media (min-width: 900px) { .bienvenida { --fundido: 320px; padding-top: calc(var(--fundido) + 40px); } }
/* ⚠️ El cristal vive en esta capa y NO en el fondo de la sección, por la
   máscara: `mask-image` afecta también a los hijos, así que puesta en la
   sección se comería el texto por arriba. Aquí sólo desvanece el cristal.

   El borde de arriba nace transparente y el cristal se va formando a lo
   largo de `--fundido`, para que la banda emerja del vídeo en vez de
   cortarlo con un canto recto.

   ⚠️ Los pasos intermedios NO son decorativos: un degradado de dos
   paradas sube de golpe por el medio y se ve una banda fantasma justo
   ahí. Con estas cuatro paradas la curva arranca lenta y cierra suave,
   que es lo que hace que el cristal parezca «ir llegando». */
.bienvenida::before {
  content: "";
  position: absolute; inset: 0; z-index: 0;
  background: color-mix(in srgb, var(--marron) 78%, transparent);
  /* ⚠️ 18px, no 22. El techo recomendado para un blur que se anima son
     20px: por encima cuesta caro, y aquí el elemento ocupa la pantalla
     entera y su máscara se mueve con el scroll. En el Safari de iPhone
     es donde primero se nota. A simple vista 18 y 22 no se distinguen. */
  -webkit-backdrop-filter: blur(18px) saturate(130%);
  backdrop-filter: blur(18px) saturate(130%);
  --curva-fundido: linear-gradient(180deg,
    transparent 0,
    rgba(0,0,0,.07) calc(var(--fundido) * .20),
    rgba(0,0,0,.26) calc(var(--fundido) * .44),
    rgba(0,0,0,.58) calc(var(--fundido) * .66),
    rgba(0,0,0,.86) calc(var(--fundido) * .86),
    #000 var(--fundido));
  -webkit-mask-image: var(--curva-fundido);
  mask-image: var(--curva-fundido);
}
/* ── La SALIDA de la banda ─────────────────────────────────────────
   ⚠️ 2026-08-14 · Se veía una línea justo donde acaba la banda y empieza
   la escena de la propuesta. Medido: arriba #7d513a y abajo #7c533e. La
   diferencia es de cuatro puntos, pero es un corte ABRUPTO sobre un
   plano liso, y eso el ojo lo lee como una raya.

   El porqué: esta banda es un CRISTAL translúcido sobre el vídeo
   (`--marron` al 78 % más `backdrop-filter`), así que su marrón real
   depende del fotograma que haya detrás y nunca coincide con el marrón
   puro donde arranca el degradado de la escena siguiente.

   ⭐ No se puede igualar un color que cambia con el vídeo: lo que se hace
   es LLEVAR la banda al marrón exacto en sus últimos píxeles. Así los dos
   lados de la costura llegan al mismo `#7c533e` y no hay nada que
   empalmar.

   ⚠️ Va en `::after` y en `z-index: 0`, por encima del cristal y por
   debajo del contenido, que vive en `z-index: 1`. */
.bienvenida::after {
  content: "";
  position: absolute; inset: auto 0 0 0; z-index: 0;
  height: clamp(90px, 13vh, 160px);
  pointer-events: none;
  background: linear-gradient(180deg,
    rgb(124 83 62 / 0)    0%,
    rgb(124 83 62 / .28) 34%,
    rgb(124 83 62 / .62) 62%,
    rgb(124 83 62 / .88) 84%,
    rgb(124 83 62 / 1)  100%);
}

/* El contenido, por encima del cristal y fuera de su máscara. */
.bienvenida__interior { position: relative; z-index: 1; }
.bienvenida__interior {
  max-width: var(--ancho); margin: 0 auto; padding-inline: var(--aire);
}
.bienvenida .hero__marca { color: var(--crema); }
.bienvenida .hero__titulo {
  /* El mínimo del clamp lo fija el caso más apretado: el titular INGLÉS
     en un móvil de 390 px, que es el texto más largo en el hueco más
     estrecho. Con 1,55rem caía en tres líneas ahí. */
  font-size: clamp(1.38rem, 3.4vw, 2.125rem);   /* techo 34px, a peticion de Carlos */
  color: #fff;
  text-transform: uppercase;
  /* ⚠️ La medida está calculada para que el titular caiga en DOS LÍNEAS
     en los dos idiomas, que es como lo quiere Carlos. En mayúsculas
     ocupa bastante más ancho que en caja baja: el inglés («ENJOY THE
     BEST SEAFOOD AT FRED'S CANCUN») son 39 caracteres y con la medida
     anterior de 20ch caía en tres.

     `text-wrap: balance` reparte las dos líneas para que queden
     parecidas en vez de dejar una larga y una corta.

     Si algún día cambia el titular en `_datos/contenido.php`, hay que
     mirar que siga cayendo en dos. */
  max-width: 24ch;
  text-wrap: balance;
  letter-spacing: -.005em;
  line-height: 1.08;
}
.bienvenida .hero__bajada {
  font-size: var(--t-sub);
  color: rgba(244, 241, 234, .82);
  /* ⚠️ Sin márgenes. Los tenía de cuando debajo iban los botones de
     reservar y carta; al retirarse (2026-08-11) ese hueco de 2em seguía
     ahí y descuadraba el nivelado: la columna quedaba centrada, pero el
     texto visible aparecía 9 px más alto que el titular. */
  margin: 0;
  max-width: 52ch;
}

/* ── Los párrafos de la portada, justificados ───────────────────────
   ⛔ NADA DE PARTIR PALABRAS. Se probó `hyphens: auto` —que es lo que
   normalmente acompaña al justificado para que no se abran ríos de
   blanco— y Carlos no quiere ver ni un guion de corte en la web
   (2026-08-11). Así que el justificado va sin separación silábica y el
   aire sobrante se reparte entre las palabras.

   Para que ese aire no cante, el ancho de línea es generoso: cuantos más
   caracteres caben por línea, menos se nota el estiramiento. Si algún
   párrafo queda con huecos feos, la salida es ensanchar su medida, NO
   volver a poner guiones. */
/* ⚠️ NO entran aquí las secciones con el texto CENTRADO —la propuesta
   culinaria y, desde el 2026-08-13, grupos—: justificar un párrafo
   centrado deja las líneas estiradas a ambos lados y la última suelta en
   medio. Grupos estuvo en esta lista mientras su texto iba a la
   izquierda. */
.pagina-home .bienvenida .hero__bajada {
  text-align: justify;
  hyphens: none;
  -webkit-hyphens: none;
  text-wrap: pretty;
}
.hero__acciones { display: flex; gap: 12px; flex-wrap: wrap; }
/* Sobre el azul, el botón secundario va de filo blanco: el filo oscuro
   de siempre desaparecía. */
.bienvenida .boton:not(.boton--principal) {
  border-color: rgba(255,255,255,.6); color: #fff;
}
.bienvenida .boton:not(.boton--principal):hover {
  border-color: #fff; background: rgba(255,255,255,.1); color: #fff;
}
.hero__marca {
  font-family: var(--titulo); font-size: var(--t-rotulo); font-weight: 600;
  letter-spacing: .26em; text-transform: uppercase;
  color: var(--acento-tinta); margin: 0 0 1.5em;
}

/* Heros de las páginas interiores: sobrios, sin imagen.
   ⚠️ QUEDA SÓLO PARA EL 404. Todo lo demás lleva banner — ver abajo. */
.hero {
  padding: clamp(56px, 8vw, 104px) 0 clamp(32px, 4vw, 56px);
  max-width: var(--ancho); margin: 0 auto; padding-inline: var(--aire);
}
.hero__titulo { font-size: var(--t-titular); }
.hero__bajada { font-size: var(--t-sub); color: var(--texto-suave); margin-top: .9em; }

/* ── EL SELLO DE OPENTABLE, ARRIBA A LA DERECHA ─────────────────────
   Carlos, 2026-08-20. Se trajo del sitio original, donde vive dentro del
   slider del hero a 150px pegado al filo derecho.

   ⚠️ Aquí la cabecera FLOTA sobre el vídeo, así que el sello arranca por
   debajo de ella (`--alto-cabecera` + aire) o se le mete debajo del menú.
   ⚠️ Y va por DEBAJO de la cabecera en `z-index`: si se pusiera encima,
   taparía los botones de reservar al abrir el menú de móvil.
   ⚠️ `pointer-events: none` — es un sello, no un control: que no robe el
   clic a nada de lo que hay detrás. */
.hero__sello {
  position: absolute; z-index: 3;
  top: calc(var(--alto-cabecera) + clamp(10px, 2vw, 26px));
  right: clamp(var(--aire), 3.5vw, 52px);
  /* Carlos, 2026-09-14: «bájale 20%». Era clamp(84px, 10vw, 150px). */
  width: clamp(67px, 8vw, 120px); height: auto;
  pointer-events: none;
  filter: drop-shadow(0 6px 18px rgb(30 18 12 / .28));
}
.hero__antetitulo {
  font-family: var(--titulo); font-size: var(--t-rotulo); font-weight: 600;
  letter-spacing: .24em; text-transform: uppercase; color: var(--acento-tinta);
  margin: 0 0 .8em;
}
.hero__dato { color: var(--texto-suave); font-size: var(--t-apoyo); }

/* =====================================================================
   EL BANNER DE LAS PÁGINAS INTERIORES
   =====================================================================
   ⭐ LEY DE LA CASA (Carlos, 2026-08-17): TODA página lleva su banner, y
   debajo el titular escrito para SEO. Antes las interiores abrían con el
   h1 suelto sobre el papel y parecían a medio hacer.

   La anatomía es la MISMA que la portada, y por la misma razón:
     · la imagen manda sola, a sangre y sin texto encima (regla del
       grupo: media pura, nada de titulares sobre foto);
     · el titular vive en la banda que viene justo debajo, donde se lee
       siempre igual de bien pase lo que pase en la foto;
     · la cabecera flota encima sin caja, con su sombra de letra, y se
       vuelve sólida en cuanto se baja de 40 px.

   La diferencia con la portada: el banner no ocupa 100dvh sino algo más
   de medio alto, para que el titular y el arranque del contenido se vean
   sin tener que desplazar. Se afina en un solo sitio, `--alto-banner`.
   ===================================================================== */
/* ── LA APERTURA DE LAS INTERIORES ─────────────────────────────────
   La MISMA que la portada: la imagen se queda pegada y la banda del
   titular sube por encima. Antes cada interior tenía su propio hero
   estático y Carlos lo cortó en seco: «no puedes tener heros diferentes,
   todos con el efecto del hero del home».

   ⛔ Ningún ancestro con `overflow` (ni `clip`): eso ancla el sticky al
   ancestro en el Safari de iPhone y el efecto se rompe. Ya pasó en
   Señor Frog's y en la portada de este sitio. */
.banner-apertura { position: relative; background: var(--marron); }

.banner {
  /* Abre al 100%, como manda la casa. */
  position: sticky; top: 0;
  width: 100%; height: 100lvh;
  background: var(--marron);   /* el color de espera mientras carga */
}
.banner__media,
.banner__media img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
/* El mismo viñeteado de arriba que la portada: oscurece SÓLO la franja
   donde vive el menú, y se lee como fotografía, no como interfaz.
   ⛔ Nada de cortinilla plana sobre toda la imagen. */
/* ⚠️ LOS VALORES DE ESTE DEGRADADO ESTÁN MEDIDOS, no elegidos a ojo.
   Con el primero que se puso (.55 arriba) el menú blanco caía a 2,8:1
   sobre el punto más claro de los banners de laguna y cielo — por debajo
   del 4,5 que necesita. Medido con la cabecera oculta y buscando el peor
   píxel de la franja del menú en las ocho páginas. Si se cambia una foto
   de banner, se vuelve a medir. */
.banner::after {
  content: ''; position: absolute; inset: 0 0 auto 0;
  height: calc(var(--alto-cabecera) + 110px);
  background: linear-gradient(to bottom,
              rgba(18, 12, 8, .80), rgba(18, 12, 8, .62) 45%,
              rgba(18, 12, 8, .22) 78%, transparent);
  pointer-events: none; z-index: 1;
}

/* ── La banda del titular ──────────────────────────────────────────── */
/* ── LA BANDA: UN CRISTAL, NO UN BLOQUE ────────────────────────────
   Carlos, 2026-08-17: «no veo los bloques totalmente marrones, en blur
   como en el hero». Tenía razón: la banda de la portada es un CRISTAL
   translúcido que se forma sobre el vídeo —marrón al 78 % más
   `backdrop-filter`— y las de las interiores eran marrón plano. Con el
   mismo movimiento y distinto material, se notaba que eran otra cosa.

   Aquí va la misma receta: el cristal en `::before` con máscara de
   fundido —para que se forme según sube, no de golpe— y el cierre en
   marrón puro en `::after`, para que la costura con lo que viene debajo
   no deje raya.

   ⚠️ 18px de desenfoque, no más: el techo de un blur que se mueve son
   ~20, y por encima se nota en el Safari de iPhone. Es el mismo valor
   que la portada.

   ⭐ Y el texto CENTRADO, como pidió Carlos. */
.banner-banda {
  position: relative; z-index: 3;
  color: var(--sobre-hondo);
  --fundido: clamp(120px, 18vh, 220px);
  padding-top: calc(var(--fundido) + clamp(16px, 2vw, 28px));
  padding-bottom: clamp(52px, 7vw, 92px);
  text-align: center;
}
.banner-banda::before {
  content: "";
  position: absolute; inset: 0; z-index: 0;
  /* ⚠️ 86 %, no el 78 % de la portada. Allí el cristal se forma sobre un
     VÍDEO oscuro; aquí, sobre fotos de mediodía —la laguna, el aula de
     Kids— que son mucho más claras. Medido en las ocho páginas con
     banner: al 78 % el texto blanco se quedaba entre 4,5 y 4,8:1, es
     decir, aprobando raspado y con algunas por debajo. Al 86 % el
     desenfoque se sigue viendo y el texto tiene margen. */
  background: color-mix(in srgb, var(--marron) 86%, transparent);
  -webkit-backdrop-filter: blur(18px) saturate(130%);
  backdrop-filter: blur(18px) saturate(130%);
  --curva-fundido: linear-gradient(180deg,
    transparent 0,
    rgba(0,0,0,.07) calc(var(--fundido) * .20),
    rgba(0,0,0,.26) calc(var(--fundido) * .44),
    rgba(0,0,0,.58) calc(var(--fundido) * .66),
    rgba(0,0,0,.86) calc(var(--fundido) * .86),
    #000 var(--fundido));
  -webkit-mask-image: var(--curva-fundido);
  mask-image: var(--curva-fundido);
}
/* El cierre en marrón puro: el cristal depende de la foto que tenga
   detrás y nunca coincide con el marrón sólido de la sección siguiente.
   No se iguala un color que cambia — se lleva la banda al marrón exacto
   en sus últimos píxeles. */
.banner-banda::after {
  content: "";
  position: absolute; inset: auto 0 0 0; z-index: 0;
  height: clamp(90px, 13vh, 160px); pointer-events: none;
  background: linear-gradient(180deg,
    rgb(124 83 62 / 0) 0%, rgb(124 83 62 / .28) 34%,
    rgb(124 83 62 / .62) 62%, rgb(124 83 62 / .88) 84%,
    rgb(124 83 62 / 1) 100%);
}
/* Sin `backdrop-filter` (navegadores viejos), el cristal se queda
   transparente y el texto caería sobre la foto: entonces manda el marrón
   sólido de siempre. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .banner-banda::before { background: var(--marron); }
}

/* Las piezas del texto entran escalonadas cuando la banda llega, igual
   que en la banda de bienvenida de la portada. El retardo lo pone `--n`
   desde el JS. Sólo se esconden si hay JavaScript que pueda devolverlas. */
.js .banner-banda__pieza {
  opacity: 0; transform: translateY(22px);
  transition: opacity .7s var(--curva), transform .7s var(--curva);
  transition-delay: calc(var(--n, 0) * .09s);
}
.js .banner-banda.visible .banner-banda__pieza { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .js .banner-banda__pieza { opacity: 1; transform: none; transition: none; }
}
/* El contenido, por encima del cristal y fuera de su máscara. */
.banner-banda__interior {
  position: relative; z-index: 1;
  max-width: var(--ancho); margin: 0 auto; padding-inline: var(--aire);
}
/* ⚠️ `margin-inline: auto` — el antetítulo es un `<p>` y hereda el
   `max-width: var(--medida)` de todos los párrafos: 62ch, que a 11px son
   494px. Con la banda centrada, su TEXTO salía centrado dentro de esa
   caja de 494, pero la caja seguía pegada a la izquierda. Se veía un
   eyebrow descolgado del titular. Lo mismo para el dato del pie. */
.banner-banda__antetitulo {
  font-family: var(--titulo); font-size: var(--t-rotulo); font-weight: 600;
  letter-spacing: .26em; text-transform: uppercase;
  color: var(--crema); margin: 0 auto 1.1em; max-width: none;
}
/* ⚠️ A LA ESCALA DEL HOME (Carlos, 2026-08-17: «revisa los títulos de la
   página, que sean como los del home»). El h1 de la portada vive en la
   banda de bienvenida y mide 34px; éste estaba en 62 y hacía que cada
   interior pareciera de otro sitio. */
.banner-banda__titulo {
  font-size: var(--t-seccion); line-height: 1.05;
  max-width: 24ch; text-wrap: balance; margin: 0 auto;
}
.banner-banda__bajada {
  font-size: var(--t-sub); margin: 1em auto 0; max-width: 56ch;
  color: var(--crema);
}
.banner-banda__dato {
  margin: 1.4em auto 0; font-size: var(--t-apoyo); color: var(--crema);
  padding-top: 1.2em; border-top: 1px solid rgba(255, 255, 255, .22);
  display: table;   /* se ajusta al texto y el `auto` lo centra */
}
.banner-banda__acciones {
  display: flex; gap: 12px; flex-wrap: wrap; margin-top: 1.8em;
  justify-content: center;
}
/* Sobre el marrón, el botón secundario va de filo blanco (igual que en la
   banda de bienvenida: el filo oscuro de siempre desaparece). */
.banner-banda .boton:not(.boton--principal) {
  border-color: rgba(255,255,255,.6); color: #fff;
}
.banner-banda .boton:not(.boton--principal):hover {
  border-color: #fff; background: rgba(255,255,255,.1); color: #fff;
}

/* ── SECCIONES EN BLANCO ────────────────────────────────────────────
   El respiro del sitio. Se usan con cuentagotas y siempre PEGADAS a algo
   con materia —una escena oscura, una foto— para que el blanco se lea
   como aire y no como un hueco sin terminar. */
.claro { background: var(--fondo-blanco); }
/* Sobre blanco, el filo de las tarjetas necesita un punto más de peso:
   el borde de arena se disolvía. */
.claro .tarjeta, .claro .prensa__nota { border-color: var(--linea); }

/* La página con banner arranca pegada arriba, como la portada: la
   cabecera flota sobre la imagen en vez de empujarla. */
.con-banner main { padding-top: 0; }

/* ⚠️ Aquí había un zoom de entrada de la imagen. Se retiró al pasar a la
   apertura de la portada: el gesto ya lo hace la banda subiendo, y dos
   movimientos a la vez en la primera pantalla se pisan. */

/* ── Bloques genéricos ─────────────────────────────────────────────── */
.bloque { padding-block: var(--hueco-bloque); }
/* Las secciones de respiro no invierten el modo: cambian de papel, no de
   mundo. Arena en vez de blanco, y la misma tinta de siempre. */
.hondo {
  background: var(--fondo-hondo);
  color: var(--texto);
}
.hondo .rotulo { color: var(--acento-tinta); }
.hondo p { color: var(--texto-suave); }

/* La propuesta culinaria: una sola idea, ancha, sin adornos. */
/* ── La propuesta culinaria: escena en dos tiempos ──────────────────
   Primero se lee el titular solo, centrado. Al seguir bajando el titular
   sube, entra la descripción y el fondo cambia a la otra foto.

   Anatomía de siempre en este proyecto:
     .propuesta       el RIEL. Alto y transparente: sólo mide el recorrido.
     .propuesta__pega la PANTALLA, pegada con `sticky`. Lleva el fondo.
   ⛔ Sin `pin` de GSAP: el `pin-spacer` que inyecta descoloca el start y
   el end de todo lo que venga después.
   ⛔ Ningún ancestro con `overflow`, o el `sticky` se ancla a él en el
   Safari de iPhone.

   `--p` la publica el JS de 0 a 1 a lo largo del riel. De ahí salen los
   tres momentos: `--sube` (el titular), `--desc` (la descripción) y
   `--fondo2` (el cruce de fotos).                                      */
.propuesta { position: relative; height: 250svh; background: var(--marron); }

/* ── La salida de la banda de bienvenida ────────────────────────────
   El azul de la apertura moría en un canto recto contra la foto de esta
   escena y se veía la línea del corte. Aquí baja fundido.

   ⚠️ Va en el RIEL (`.propuesta`) y no en la pantalla pegada
   (`.propuesta__pega`): si estuviera dentro del `sticky` viajaría con
   él y el degradado se pasearía por toda la escena en vez de quedarse
   en la costura. `z-index: 2` lo pone por encima de la pantalla, que
   crea su propio contexto con `isolation`.

   ⚠️ Los alfas van explícitos hasta el cero (`rgb(124 83 62 / 0)`) y NO
   con la palabra `transparent`: en la interpolación, `transparent` es
   negro con alfa cero, y por el medio del degradado aparecería un velo
   gris sucio. Es el mismo azul de `--pizarra` escrito a pelo, como en
   el velo de aquí abajo.

   ⚠️ Las paradas intermedias no son adorno: con dos paradas la curva
   sube de golpe por el centro y se ve una banda fantasma justo ahí. */
.propuesta::before {
  content: "";
  position: absolute; z-index: 2; pointer-events: none;
  inset: 0 0 auto 0;
  height: clamp(110px, 16vh, 220px);
  background: linear-gradient(180deg,
    rgb(124 83 62 / 1)   0%,
    rgb(124 83 62 / .94) 18%,
    rgb(124 83 62 / .74) 40%,
    rgb(124 83 62 / .42) 64%,
    rgb(124 83 62 / .14) 84%,
    rgb(124 83 62 / 0)  100%);
}

.propuesta__pega {
  position: sticky; top: 0;
  height: 100lvh; min-height: 520px;
  overflow: hidden;                 /* recorta el zoom de las fotos */
  display: grid; place-items: center;
  isolation: isolate;
}

.propuesta__fondo { position: absolute; inset: 0; z-index: -2; }
.propuesta__foto {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  /* Escalada de más para que el desplazamiento no descubra los bordes. */
  transform: scale(1.1) translateY(calc(var(--p, 0) * -2.5%));
  will-change: transform;
}
/* La segunda entra por encima. No se mueve sola: la cruza `--fondo2`. */
.propuesta__foto--segunda { opacity: var(--fondo2, 0); }

/* ── LOS TRES TIEMPOS ───────────────────────────────────────────────
   Carlos, 2026-08-17: «la foto bien sin overlay, luego blur la foto,
   luego el overlay y luego texto». El mismo esquema que Grupos.

     0 → .16   la foto LIMPIA. Ni velo ni desenfoque.
   .14 → .46   el desenfoque y el velo, juntos.
   .42 → …     el titular, y después la descripción.

   ⚠️ Los tramos se pisan a propósito: encadenados a tope se leen como
   tres pasos sueltos; solapados, como un solo movimiento.

   `--vela` es el mando de los dos primeros tiempos. Se calcula en CSS a
   partir de `--p`, que ya publica el JS: no hace falta tocar el motor. */
.propuesta__pega { --vela: clamp(0, calc((var(--p, 1) - .14) * 3.1), 1); }

.propuesta__foto--velada { opacity: var(--vela); }
/* La gemela de la SEGUNDA foto sólo aparece cuando el cruce ya ha
   ocurrido: si no, las dos borrosas se sumarían y el fondo se iría a
   plano. */
.propuesta__foto--velada2 { opacity: calc(var(--vela) * var(--fondo2, 0)); }

/* ⚠️ Velo uniforme, no lateral. Con el texto centrado no hay un «lado»
   libre donde apoyarlo: la protección tiene que cubrir el centro. Se
   queda en .52 —lo justo para leer— y las esquinas de arriba y abajo
   suman un punto más, que es donde el cielo quema. */
.propuesta__pega::before {
  content: "";
  position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(180deg,
      rgba(124, 83, 62, .34) 0%, rgba(124, 83, 62, 0) 30%,
      rgba(124, 83, 62, 0) 70%, rgba(124, 83, 62, .38) 100%),
    rgba(124, 83, 62, .68);
  /* El velo entra con el desenfoque, no está desde el principio. */
  opacity: var(--vela, 1);
}

.propuesta__interior {
  max-width: var(--ancho); margin: 0 auto; padding-inline: var(--aire);
  width: 100%;
}
/* Centrado: el titular vive en mitad de la pantalla hasta que sube.
   ⚠️ `position: relative` porque la descripción cuelga de aquí en
   absoluto: si estuviera en el flujo normal, ocuparía su hueco desde el
   principio —aunque sea invisible— y empujaría al titular hacia arriba,
   que dejaría de estar centrado en el primer tiempo. */
.propuesta__texto {
  position: relative;
  /* Ancho para que el titular quepa en UNA línea en escritorio: en
     mayúsculas a 34 px, «NUESTRA PROPUESTA CULINARIA» pide unos 620 px.
     En móvil no cabe de ninguna manera y cae en dos, que es lo normal. */
  max-width: 62ch; margin-inline: auto; text-align: center;
}

.propuesta h2 {
  font-size: clamp(1.38rem, 3.4vw, 2.125rem);   /* techo 34px, como el de arriba */
  text-transform: uppercase;
  letter-spacing: -.005em;
  line-height: 1.08;
  color: #fff;
  /* ⚠️ El titular entra DESPUÉS del velo: sobre la foto limpia caería
     encima de la madera clara y no se leería. Empieza en .42, cuando el
     velo ya está hecho (termina en .46). */
  opacity: clamp(0, calc((var(--p, 1) - .42) * 5), 1);
  /* Sube al llegar el segundo tiempo. El desplazamiento es el que deja
     sitio a la descripción sin que el bloque se descentre del todo. */
  transform: translateY(calc(var(--sube, 0) * -1 * clamp(38px, 7vh, 74px)));
}
.propuesta__desc {
  position: absolute; left: 0; right: 0;
  top: calc(100% + clamp(16px, 2.4vh, 28px));
  opacity: var(--desc, 0);
  transform: translateY(calc((1 - var(--desc, 0)) * 26px));
}
.propuesta__desc p {
  /* Medida calculada para que la descripción caiga en TRES líneas en
     escritorio. Si se cambia el texto en `_datos/contenido.php`, hay que
     mirar que siga cuadrando. */
  max-width: 64ch;
  margin: 0 auto;
  font-size: var(--t-sub);        /* el mismo cuerpo que la entrada del hero */
  color: rgba(244, 241, 234, .92);
  text-align: center;             /* centrado: aquí no se justifica */
}

/* ── EN EL TELÉFONO, LA MISMA ESCENA MÁS CORTA Y CON LA FOTO VIVA ───
   (2026-09-11)

   Medido en un iPhone de 390×664: el riel daba 1.660 px, y de los 996 de
   recorrido el titular no empezaba hasta los 418. Más de la mitad de la
   escena era pantalla velada sin nada encima —los «600 px de foto
   desenfocada» que salieron en la barrida de huecos del día 10—.

   Y al final del recorrido la pantalla acababa en MARRÓN LISO: en
   escritorio el desenfoque al 100 % más el velo de .68 se leen como
   ambiente porque hay 1.400 px de foto donde reconocer el sitio; en 390
   no queda ni la lámpara ni la mesa, sólo una mancha. Aquí:

     · el riel baja de 250 a 220svh y todos los tiempos se adelantan;
     · el desenfoque se queda a MEDIA MEZCLA (.58): la foto nítida sigue
       debajo, así que el comedor se reconoce;
     · y el velo deja de ser una capa plana y pasa a ser un degradado que
       protege la franja del texto y suelta la de arriba.

   ⚠️ SÓLO MÓVIL. El escritorio se queda exactamente como está: ahí la
   escena está aprobada. El reparto de `--sube`, `--fondo2` y `--desc`
   —que lo publica el JS— tiene su propio guion en `sitio.js`.         */
@media (max-width: 899px) {
  .propuesta { height: 220svh; }

  /* El velo y el desenfoque entran antes, para dejar sitio al texto. */
  .propuesta__pega { --vela: clamp(0, calc((var(--p, 1) - .06) * 4.5), 1); }

  /* A media mezcla: lo justo para que el texto se despegue del fondo sin
     borrar la foto. Con el 1 de escritorio, aquí no se ve nada. */
  .propuesta__foto--velada  { opacity: calc(var(--vela) * .58); }
  .propuesta__foto--velada2 { opacity: calc(var(--vela) * var(--fondo2, 0) * .58); }

  /* El titular entra en cuanto el velo está hecho, no a mitad de riel. */
  .propuesta h2 { opacity: clamp(0, calc((var(--p, 1) - .20) * 5.5), 1); }

  /* Protección por franjas en vez de capa plana: fuerte donde cae el
     texto —del 42 % al 70 % de la pantalla— y floja arriba, que es donde
     se reconoce el techo de madera y las lámparas.

     ⚠️ Los alfas de la franja central NO son a ojo. Con .58/.74 la
     descripción daba 4,29:1 contra el 3 % más claro de su propio fondo,
     y a su cuerpo —el de la entrada del hero, que no es texto grande— el
     mínimo que se le pide son 4,5. Con .66/.80 sube a 4,9 y la foto se
     sigue reconociendo. Medido con el comprobador de contraste, no de
     reojo: ver [[feedback-comprobar-que-se-ve]].                       */
  .propuesta__pega::before {
    background: linear-gradient(180deg,
      rgba(124, 83, 62, .40)   0%,
      rgba(124, 83, 62, .14)  20%,
      rgba(124, 83, 62, .66)  42%,
      rgba(124, 83, 62, .80)  70%,
      rgba(124, 83, 62, .72) 100%);
  }
}

@media (prefers-reduced-motion: reduce) {
  /* Sin escena: el riel se disuelve y se ve todo junto y quieto. */
  .propuesta { height: auto; }
  .propuesta__pega { position: static; height: auto; padding-block: clamp(64px, 9vw, 120px); }
  .propuesta__foto { transform: none; }
  .propuesta__foto--segunda { opacity: 0; }
  .propuesta h2 { transform: none; }
  .propuesta__desc { opacity: 1; transform: none; }
}

/* ── Las tres fotos de la cocina ────────────────────────────────────
   ⚠️ En móvil NO se apilan: se deslizan. Es la regla de la casa —tres
   fotos apiladas alargan el scroll y se leen como tres bloques sueltos—.
   La vecina asoma por el borde (el `85%` de ancho) para que se vea que
   hay más, y el anclaje deja cada una centrada al soltar el dedo.

   Todo en CSS, sin JavaScript: un carrusel con scroll nativo se maneja
   con el dedo mejor que cualquier cosa que se programe encima. */
.cocina {
  list-style: none; margin: clamp(32px, 4vw, 56px) 0 0; padding: 0;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 85%;
  gap: 14px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  /* el aire lateral se recorta y se devuelve como padding para que la
     primera foto no quede pegada al borde de la pantalla */
  margin-inline: calc(var(--aire) * -1);
  padding-inline: var(--aire);
  scrollbar-width: none;
}
.cocina::-webkit-scrollbar { display: none; }
.cocina__foto {
  scroll-snap-align: center; scroll-snap-stop: always; margin: 0;
  overflow: hidden;              /* el marco recorta el zoom del hover */
  box-shadow: 0 10px 30px rgba(26, 34, 41, .13);
}
.cocina__foto img {
  width: 100%; height: 100%; object-fit: cover;
  aspect-ratio: 4 / 5;
  transition: transform .7s var(--curva);
}
/* El zoom pasa DENTRO del marco: la foto crece y el recuadro no se
   mueve. Al revés —escalando el marco— se empujaría a las vecinas. */
@media (hover: hover) and (pointer: fine) {
  .cocina__foto:hover img { transform: scale(1.06); }
}

@media (min-width: 900px) {
  /* En escritorio, el texto a la izquierda y las fotos a la derecha, en
     tres columnas escalonadas: la del medio sube y las de los lados
     bajan. Es lo que convierte tres fotos en fila en una composición.  */
  /* ⛔ Sin dos columnas: la sección dejó de ser «texto + fotos» y pasó a
     ser una escena a todo el ancho con la foto de fondo. El texto ocupa
     la mitad izquierda por su propia medida (`max-width` en ch), no por
     una rejilla. */
  .cocina {
    grid-auto-flow: row;
    grid-template-columns: repeat(3, 1fr);
    grid-auto-columns: auto;
    gap: 16px;
    overflow: visible;
    margin: 0; padding: 0;
    align-items: center;
  }
  /* ── El escalón y la profundidad al scroll ──────────────────────
     Cada foto tiene una posición de reposo distinta —la del medio
     levantada, las de los lados bajas— y además se mueve a su propia
     velocidad mientras la sección cruza la pantalla. Eso es lo que da
     fondo: si las tres se movieran igual, se leerían como un bloque.

     `--p` la publica el JS entre -1 y 1 según dónde esté la sección
     respecto al centro de la pantalla. Las amplitudes son distintas y
     no simétricas a propósito: con 20 / 44 / 28 el grupo respira; con
     valores espejo parece un acordeón.

     ⛔ Sin transición en el `transform`: lo manda el scroll, y una
     transición lo dejaría persiguiendo al dedo con retraso. */
  .cocina__foto { will-change: transform; }
  .cocina__foto:nth-child(1) { transform: translateY(calc(14px + var(--p, 0) * 20px)); }
  .cocina__foto:nth-child(2) { transform: translateY(calc(-26px + var(--p, 0) * 44px)); }
  .cocina__foto:nth-child(3) { transform: translateY(calc(14px + var(--p, 0) * 28px)); }
  .cocina__foto:nth-child(2) img { aspect-ratio: 3 / 4; }
}

/* =====================================================================
   LAS TRES CARTAS
   =====================================================================
   Rejilla asimétrica: la de alimentos ocupa el doble, porque es la que
   busca la gente. En móvil se convierte en carrusel.
   ===================================================================== */
.cartas-home__lista, .indice-cartas {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 14px;
  grid-auto-flow: column;
  grid-auto-columns: 78%;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--aire);
  padding-inline: var(--aire);
  padding-bottom: 8px;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.cartas-home__lista::-webkit-scrollbar,
.indice-cartas::-webkit-scrollbar { display: none; }
.cartas-home__item, .indice-cartas__item { scroll-snap-align: start; scroll-snap-stop: always; }

.cartas-home__item a, .indice-cartas__enlace {
  display: block; text-decoration: none; position: relative;
  background: var(--fondo-hondo); overflow: hidden;
}
/* Igual que en el viaje: el nombre se apoya en una franja, no en un velo. */
.cartas-home__item a:has(img)::after {
  content: ''; position: absolute; inset: auto 0 0 0; height: 46%;
  background: linear-gradient(to top, rgb(8 16 24 / .8), transparent);
  pointer-events: none;
}
.cartas-home__item span { z-index: 2; }
.cartas-home__item img, .indice-cartas img {
  width: 100%; aspect-ratio: 3 / 4; object-fit: cover;
  opacity: .78;
  transition: transform .26s var(--curva), opacity .26s var(--curva);
}
@media (hover: hover) and (pointer: fine) {
  .cartas-home__item a:hover img, .indice-cartas__enlace:hover img {
    transform: scale(1.045); opacity: .95;
  }
}
/* Cuando todavía no hay foto, la tarjeta no se rompe ni deja un hueco
   vacío: se resuelve con el color de la casa y una franja del alto justo. */
.cartas-home__item a:not(:has(img)) {
  min-height: 280px; display: grid; align-items: end;
}
.indice-cartas__enlace:not(:has(img)) {
  background: var(--fondo-hondo); min-height: 132px;
  display: flex; align-items: flex-end; padding: 20px 22px;
  border-top: 3px solid var(--acento);
}
.indice-cartas__enlace:not(:has(img)) h2 { color: var(--texto); margin: 0; }
.cartas-home__item span, .indice-cartas h2 {
  position: absolute; left: 22px; right: 22px; bottom: 20px;
  font-family: var(--titulo); font-weight: 600; font-size: 1rem;
  letter-spacing: .16em; text-transform: uppercase; color: #fff;
  text-shadow: 0 2px 14px rgb(0 0 0 / .7);
}
/* Sin foto no hay sombra que valga: la tarjeta es arena y la tinta, tinta. */
.cartas-home__item a:not(:has(img)) span {
  color: var(--texto); text-shadow: none;
}
/* En el índice, el nombre de la carta ES el título de la tarjeta: va a
   la escala de tarjeta del sitio, no a la del rótulo sobre foto que
   comparte regla con la portada. */
.indice-cartas h2 {
  position: static; color: inherit; text-shadow: none; margin-top: .7em;
  font-size: var(--t-tarjeta); letter-spacing: .06em;
}
.indice-cartas__enlace { background: none; }
.indice-cartas__apartados {
  list-style: none; margin: .5em 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 6px 14px;
  font-size: .84rem;
}
.indice-cartas__apartados a { color: var(--texto-suave); text-decoration: none; padding: 3px 0; display: inline-block; }
.indice-cartas__apartados a:hover { color: var(--acento-tinta); }
.indice-cartas__cuenta {
  font-family: var(--titulo); font-size: var(--t-rotulo); letter-spacing: .12em;
  text-transform: uppercase; color: var(--acento-tinta); margin-top: .7em;
}

/* ── La cita ───────────────────────────────────────────────────────── */
/* ⛔ LA CITA SE RETIRÓ DE LA PORTADA el 2026-08-13. Este bloque ya no lo
   usa ninguna vista; se deja escrito como el resto de lo retirado. */
.cita { padding-block: clamp(72px, 10vw, 140px); text-align: center; }
.cita blockquote {
  margin: 0 auto; max-width: 20ch;
  font-family: var(--titulo); font-weight: 300;
  font-size: clamp(1.5rem, 4.2vw, 2.6rem); line-height: 1.25;
}
.cita blockquote p { max-width: none; margin: 0; }
/* Las palabras de la cita se encienden una a una con el scroll. El
   espacio entre ellas lo pone el propio texto, no un margen. */
.cita__palabra { display: inline-block; }
.cita cite {
  display: block; margin-top: 1.5em; font-style: normal;
  font-family: var(--titulo); font-size: var(--t-rotulo); font-weight: 600;
  letter-spacing: .24em; text-transform: uppercase; color: var(--acento-tinta);
}

/* ── Grupos ──────────────────────────────────────────────────────────
   La foto —el interior de una villa, con la mesa larga puesta— ocupa el
   FONDO de la sección, y el texto va encima y CENTRADO.

   Rehecha cuatro veces el 2026-08-13; el porqué de cada descarte está en
   `_vistas/home.php` y en el RESUMEN.

   ⚠️ El techo de 700 px NO es un capricho: la foto mide 780 de alto —lo
   máximo que da sin ampliarla— y necesita un 10 % de sobra para el
   recorrido del parallax. Subir la sección obliga a ampliar la foto y se
   ve blanda.

   ⚠️ `overflow: hidden` es seguro aquí porque dentro no hay nada
   `sticky`. La prohibición de la casa es sobre los ANCESTROS de una
   escena pegada, que en el Safari de iPhone se anclan a él.

   ⚠️ `isolation: isolate` para que los `z-index` negativos del fondo y
   del velo se queden dentro de la sección. */
.grupos-home {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  min-height: clamp(480px, 72svh, 700px);
  display: grid; align-items: center;
  color: var(--sobre-hondo);
  background: var(--marron);      /* mientras la foto carga, azul, nunca blanco */
}

/* La foto es un 10 % más alta que la sección y ese sobrante es justo el
   recorrido: nunca descubre un borde.
   ⚠️ El 110 % y el ±5 % están emparejados: si se sube uno hay que subir
   el otro, y entonces hay que revisar que la foto dé esa altura. */
.grupos-home__fondo { position: absolute; inset: -5% 0; z-index: -2; }
/* ⚠️ En MÓVIL no hay cinta: no hay riel ni `--avance` que la mueva, y seis
   fotos verticales quietas serían una tira muerta. Se enseña la primera a
   sangre y ya. La cinta borrosa no pinta nada ahí. */
.grupos-galeria--velada { display: none; }
.grupos-galeria {
  position: absolute; inset: 0;
  display: block; overflow: hidden;
}
.grupos-galeria img { display: none; }
/* ⚠️ En móvil sale la QUINTA, no la primera, y está ELEGIDA MIDIENDO.
   Aquí la foto va bajo un velo fijo con el texto encima, así que no vale
   cualquiera: con la primera el texto quedaba en 4,88:1 pero la escena se
   veía una mancha marrón; con la tercera —la luminosa— la foto lucía pero
   el texto caía a 3,48. Probadas las seis con el velo al .74, la quinta
   da 5,44:1 y además se ve de qué es la foto. */
.grupos-galeria img:nth-child(5) {
  display: block; width: 100%; height: 100%; object-fit: cover;
}
.grupos-home__foto {
  width: 100%; height: 100%;
  object-fit: cover;
  transform: translateY(calc((var(--desliza, .5) - .5) * 10%));
  will-change: transform;
}

/* Velo uniforme: con el texto centrado no hay un lado libre donde
   apoyarlo, la protección tiene que cubrir el medio. Las esquinas de
   arriba y abajo suman un punto, que es donde la foto quema.

   ⚠️ El .74 está MEDIDO sobre esta foto, no elegido a ojo. La villa es
   mucho más clara que la palapa que había antes: con .66 el rótulo
   dorado se quedaba en 3,35:1 y el mínimo para ese tamaño es 4,5. Si se
   cambia la foto hay que volver a medir el rótulo, que es lo primero que
   se cae por ser el texto más pequeño y el de menos contraste. */
.grupos-home::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(180deg,
      rgb(124 83 62 / .26)   0%, rgb(124 83 62 / 0)   26%,
      rgb(124 83 62 / 0)    74%, rgb(124 83 62 / .30) 100%),
    rgb(124 83 62 / .86);
}

.grupos-home__interior {
  position: relative;
  max-width: var(--ancho); margin: 0 auto; padding-inline: var(--aire);
  width: 100%;
  padding-block: clamp(52px, 8vh, 88px);
}
/* ⭐ Todo centrado, como pidió Carlos. La medida se topa para que el
   titular no se estire de borde a borde en pantalla ancha. */
.grupos-home__texto { max-width: 44rem; margin-inline: auto; text-align: center; }

/* ⚠️ El rótulo va en BLANCO aquí, no en el dorado claro del resto de
   secciones oscuras. Está medido sobre esta foto: el dorado se quedaba
   en 3,98:1 incluso con el velo al .74, y para 11,5 px el mínimo es 4,5.
   Subir más el velo tapaba la foto, que es justo lo que la sección tiene
   que enseñar. El acento dorado no se pierde: lo lleva el botón, que es
   sólido y tiene su propio contraste comprobado. */
.grupos-home .rotulo { color: rgba(255, 255, 255, .92); }
/* ⚠️ EN MAYÚSCULAS, como TODOS los titulares de la portada (Carlos,
   2026-08-13). Estuvo en caja normal porque la frase es larga y en
   versales cansa más de leer, pero la coherencia manda: los otros cinco
   van en mayúsculas y éste desentonaba.
   Al pasarlo, baja al techo de 34 px de la casa —a 38 px en versales se
   comía la sección— y la medida sube a 26ch para que siga cayendo en
   tres líneas. */
.grupos-home h2 {
  /* el valor de esta línea es el que se convirtió en `--t-seccion` */
  font-size: var(--t-seccion);
  text-transform: uppercase;
  letter-spacing: -.005em; line-height: 1.08;
  color: #fff;
  margin: .5em auto 0; max-width: 26ch;
}
.grupos-home p {
  margin: 1.1em auto 2.2em;
  color: rgba(244, 241, 234, .92);
  max-width: 54ch;
}

/* ⭐ LA LÍNEA ANTERIOR, A UN PARÁMETRO DE DISTANCIA. `?paleta=terracota`
   en cualquier página y esa visita vuelve ENTERA a como estaba antes del
   2026-09-10: la terracota y el naranja de atardecer, el marrón liso sin
   papel y la cita en Jost. Es para mirar y comparar —Carlos: «guarda lo
   anterior por si quiero cambiarle»—; no cambia nada en el servidor ni
   se recuerda de una página a otra. */
:root[data-paleta="terracota"] {
  --acento:        var(--terracota);
  --acento-tinta:  var(--terracota-tinta);
  --boton:         var(--boton-atardecer);
  --boton-honda:   var(--boton-atardecer-hondo);
  --acento-titulo: var(--acento-titulo-atardecer);
}
/* Lo que no es un color no cabe en una variable: el papel del manto y la
   letra de la cita se apagan aquí. */
:root[data-paleta="terracota"] .pase__onda,
:root[data-paleta="terracota"] .cruce__ola,
:root[data-paleta="terracota"] .cruce__relleno { background-image: none; }
@media (min-width: 900px) {
  :root[data-paleta="terracota"] .pases__cita blockquote {
    font-family: var(--titulo);
    font-size: clamp(30px, 3.2vw, 44px);
    line-height: 1.2;
    max-width: 18ch;
    padding-inline: 0;
    margin-bottom: .6em;
  }
}

/* =====================================================================
   🧪 MUESTRA · PALETA MEDITERRANEAN (2026-09-15)
   =====================================================================
   Carlos pasó una lámina «Mediterranean Color Palette» de Canva y pidió
   verla aplicada «cambiando el rojo, el crema, el rosa; las letras rojas
   del diseño, como acuarela, ésas déjalas, pero quiero ver qué tal».

   ⭐ 2026-09-17 · DEJÓ DE SER MUESTRA. Carlos eligió la B («Muestra B
   (8603)») y es la paleta de la web: `partials/head.php` la enciende por
   defecto. La A sigue viéndose con `FREDS_PALETA=mediterranea` (8602) y
   la línea Sea & Spice de antes con `FREDS_PALETA=sea-spice`.
   (Texto original: «ES UNA MUESTRA, NO UN CAMBIO. Sólo se enciende cuando
   el servidor local arranca con `FREDS_PALETA=mediterranea`».)

   Los cuatro colores, medidos de la captura: terracota #BE805B, azul agua
   #92B0AE, verde oliva #9B977C y arena #D4C3AF (casi idéntica al papel
   del sitio, #d4c3b0, así que el papel no cambia).

   ⚠️ LA TERRACOTA CRUDA NO SE LEE: blanco encima da 3,3:1 y sobre arena
   no llega a 3. Se baja SÓLO la luz, mismo tono y saturación:
     #a46641  relleno del botón · 4,61:1 con blanco
     #875436  hover y borde     · 6,24:1 con blanco
     #73482e  texto sobre arena · 4,56:1
   La cruda #BE805B se queda para lo que no es letra: filetes, olas.
   ⛔ Las caligráficas (`.firma`, el título de la portada de los pases)
   leen `--rojo-spice` directo y NO cambian: así lo pidió. */
:root[data-paleta^="mediterranea"] {
  --med-terracota: #BE805B;
  --med-agua:      #92B0AE;
  --med-oliva:     #9B977C;
  /* ⭐ 2026-09-17, AL PASARLA A LA WEB: la terracota cruda como FONDO
     (reservas, paginación, botón de grupos) daba 3,27:1 con blanco encima.
     `buscar-contraste.js` lo midió. Acento = la terracota con 14 % menos
     de luz, la misma que las superficies: blanco 5,86 · crema 4,64. La
     cruda sigue en `--med-terracota` para quien la quiera decorativa. */
  --acento:        #8d5838;
  --acento-tinta:  #73482e;
  --acento-titulo: #73482e;
  /* Carlos, 2026-09-15: «me gustaría los botones en verdes o algo».
     El oliva de la lámina (#9B977C) con blanco encima da 2,95:1; bajada
     sólo la luz: relleno #79755d (4,63:1 con blanco) y borde/hover
     #64614d (6,22 con blanco, 3,63 contra el papel: dibuja el contorno).
     La terracota de antes: #a46641 / #875436. */
  --boton:         #79755d;
  --boton-honda:   #64614d;
  /* La crema pasa a un oliva muy claro (25 % sobre blanco): tinta encima
     9,65:1, y como texto claro sobre el marrón sigue funcionando. */
  --crema:         #e6e5de;
  /* Carlos, 2026-09-15, sobre la ola: «este terracota es del que yo
     pasé?» — no, era el marrón de la casa (#7c533e). «Sí, cambia el
     marrón a terracota para ver». Va la terracota con la luz bajada
     (#a46641, 4,61:1 con blanco) y no la cruda #BE805B, que con la frase
     blanca del cruce encima se quedaba en 3,27. ⚠️ Los textos en crema
     sobre estas superficies bajan a 3,65:1: aceptable para mirar, no
     para publicar. La textura es `papel-marron.webp` reteñida a la misma
     media (`papel-terracota.webp`, 14 KB). */
  /* ⭐ 2026-09-17: #a46641 → #8d5838. Con la crema encima daba 3,65:1
     (barra de app, banners, portada) — «aceptable para mirar, no para
     publicar», y ya se publica. Mismo tono con 14 % menos de luz; la
     baldosa `papel-terracota.webp` se volvió a teñir a esta media. */
  --marron:        #8d5838;
  --papel-marron:  url('../img/textura/papel-terracota.webp');
}
/* Los tres fundidos que escriben el marrón a mano (`rgb(124 83 62)`): con
   el marrón en variable no se enteraban y dejaban una banda marrón. */
:root[data-paleta^="mediterranea"] .bienvenida::after,
:root[data-paleta^="mediterranea"] .banner-banda::after {
  background: linear-gradient(180deg,
    rgb(141 88 56 / 0)    0%,
    rgb(141 88 56 / .28) 34%,
    rgb(141 88 56 / .62) 62%,
    rgb(141 88 56 / .88) 84%,
    rgb(141 88 56 / 1)  100%);
}
/* 2026-09-28 · Carlos: «se marca esa línea, antes no se veía». La
   escena de Las Villas (`.palapas`) quedó fuera de esta lista y su
   fundido seguía en el marrón viejo: la banda acababa en #8e5838 y la
   escena arrancaba en #7c533e, un corte recto a lo ancho de la pantalla. */
:root[data-paleta^="mediterranea"] .palapas::before,
:root[data-paleta^="mediterranea"] .propuesta::before {
  background: linear-gradient(180deg,
    rgb(141 88 56 / 1)   0%,
    rgb(141 88 56 / .94) 18%,
    rgb(141 88 56 / .74) 40%,
    rgb(141 88 56 / .42) 64%,
    rgb(141 88 56 / .14) 84%,
    rgb(141 88 56 / 0)  100%);
}
/* La piel de la barra de app lleva `fill="#7c533e"` escrito en el SVG
   (`partials/app-nav.php`); una propiedad CSS le gana al atributo. */
:root[data-paleta^="mediterranea"] .app-nav__piel { fill: var(--marron); }
:root[data-paleta^="mediterranea"] .hero--video::after {
  background: linear-gradient(180deg,
    /* Sin la franja oscura de arriba (2026-10-09, «quitar fade de
       header»): el menú se sostiene con la sombra de su propia letra. */
    rgba(141, 88, 56, 0)     0%,
    rgba(141, 88, 56, 0)    70%,
    rgba(141, 88, 56, .40) 100%);
}
/* ⭐ 2026-09-17 · Lo que `buscar-contraste.js` seguía cazando con la terracota
   ya oscurecida (3,9–4,4:1): la letra CREMA sobre los fundidos de los
   banners y la portada, el párrafo del cristal de Las Villas y el menú de
   la cabecera sobre la portada. La crema de esta paleta es un oliva muy
   claro (#e6e5de) y sobre terracota no llega: esos textos van en blanco,
   el cristal de Las Villas un poco más tupido y el velo de arriba de la
   portada un punto más denso. */
:root[data-paleta^="mediterranea"] .bienvenida .hero__marca,
:root[data-paleta^="mediterranea"] .banner-banda__antetitulo,
:root[data-paleta^="mediterranea"] .banner-banda__bajada,
:root[data-paleta^="mediterranea"] .banner-banda__dato { color: #fff; }
:root[data-paleta^="mediterranea"] .palapas__texto { background: color-mix(in srgb, var(--marron) 88%, transparent); }
:root[data-paleta^="mediterranea"] .palapas__texto > p:not(.rotulo) { color: #fff; }

/* El rosa: el canto de la ola era el acento al 30 %; pasa al azul agua. */
:root[data-paleta^="mediterranea"] .pase__onda--eco,
:root[data-paleta^="mediterranea"] .cruce__ola--eco {
  background: color-mix(in srgb, var(--med-agua) 75%, transparent);
}

/* =====================================================================
   🧪 MUESTRA B · MEDITERRANEAN REPARTIDA COMO LA LÁMINA (2026-09-15)
   =====================================================================
   Carlos: «lo veo muy beige». Medido en la muestra A: el beige ocupaba el
   38 % de la portada, el 51 % de /cancun/ y el 80 % de la carta, y el
   azul agua no pasaba del 2,5 % en ninguna. En la lámina los cuatro
   colores pesan lo mismo y son BLOQUES, no detalles.

   Hereda todo lo de la A (selector por prefijo) y además:
     · las secciones de respiro (`--fondo-hondo`) pasan a AZUL AGUA: el
       lado de la barra, el pie de las tarjetas, el índice de la carta;
     · las superficies claras y la sección blanca de prensa, a OLIVA CLARO;
     · el pie, a OLIVA OSCURO con letra clara.

   ⚠️ Sobre el agua #92B0AE la tinta suave (3,4:1) y la terracota de texto
   (3,36) no se leían: se bajan de luz hasta 4,6 sin cambiar de tono, y
   siguen dando 6,2 sobre el arena. El borde de botón, a #5a5745 (3,14
   contra el agua: dibuja el contorno). Sólo se enciende en el 8603. */
/* ⛔ CARLOS, sobre la barra con el agua de fondo y la ola terracota
   encima: «no se pueden repetir doble fondo, y ese azul de fondo
   horrible». Así que en la B el AGUA NO ES FONDO en ningún sitio (el
   lado de la barra, la galería, el índice y las franjas de la carta
   volvieron al papel) y dos superficies de color no se tocan. Lo que
   queda de la B es lo que no era azul: oliva claro y el pie oliva. */
:root[data-paleta="mediterranea-b"] {
  --fondo-alto:     #d9d8cc;   /* tinta 8,5:1 · tinta suave 5,5 */
  --pie-oliva:      #55523f;   /* crema encima 6,24:1 · blanco 7,88 */
}
:root[data-paleta="mediterranea-b"] .claro { background: var(--fondo-alto); }

/* El pie en oliva oscuro */
:root[data-paleta="mediterranea-b"] .pie {
  background: var(--pie-oliva); color: #e6e5de; border-top-color: var(--pie-oliva);
}
:root[data-paleta="mediterranea-b"] .pie a,
:root[data-paleta="mediterranea-b"] .pie__legal,
:root[data-paleta="mediterranea-b"] .pie__legal-enlace { color: #e6e5de; }
:root[data-paleta="mediterranea-b"] .pie a:hover,
:root[data-paleta="mediterranea-b"] .pie__legal-enlace:hover { color: #ffffff; }
:root[data-paleta="mediterranea-b"] .pie__titulo { color: #ffffff; }
:root[data-paleta="mediterranea-b"] .pleca__grupo { background: var(--pie-oliva); }
:root[data-paleta="mediterranea-b"] .pleca__marco,
:root[data-paleta="mediterranea-b"] .pie__legal { border-color: rgb(230 229 222 / .35); }
/* Los logos iban en negro al 42 %: sobre oliva oscuro, en claro. */
:root[data-paleta="mediterranea-b"] .pleca__grupo img,
:root[data-paleta="mediterranea-b"] .pleca__marcas img,
:root[data-paleta="mediterranea-b"] .pie__marca img { filter: brightness(0) invert(1); }
/* En claro al 42 % se quedaban lavados sobre el oliva. */
:root[data-paleta="mediterranea-b"] .pleca__marcas img { opacity: .72; }



/* ⭐ 2026-09-17 · `scroll-snap-stop: always` acompaña a cada
   `scroll-snap-align` (lo recomendó `auditar-slider-movil.js`): sin él, un
   deslizón rápido del dedo se salta dos o tres tarjetas y se pierde la
   cuenta de dónde está uno. Con él, cada empujón avanza UNA. */
/* =====================================================================
   LAS DOS UTILIDADES DE LA LÍNEA SEA & SPICE (2026-09-10)
   =====================================================================
   Se declaran aquí y no se usan todavía en ninguna vista: son el
   material listo para cuando se decida dónde entra la línea nueva.

   `.papel` pinta la textura sobre el color que lleve el elemento. Si el
   elemento no trae color propio, sale el papel claro del cartel. La
   baldosa se repite a su tamaño real; en pantallas de 2× el navegador
   ya la pinta al doble de densidad sin que haya que hacer nada.

   `.firma` es la caligráfica: grande, holgada y con el rojo de la línea.
   ⚠️ Lleva un pelo de `padding` a los lados porque los trazos de la Mr
   Dafoe se salen de su propia caja —la «S» arranca a la izquierda del
   punto de origen— y sin ese aire se recortan contra el borde. */
.papel {
  background-color: var(--papel-color);
  background-image: var(--papel);
  background-size: var(--papel-lado) var(--papel-lado);
  background-repeat: repeat;
  background-blend-mode: multiply;
}
.firma {
  font-family: var(--caligrafia);
  font-weight: 400;
  color: var(--rojo-spice);
  font-size: clamp(2.6rem, 7vw, 5.2rem);
  line-height: 1.05;
  padding-inline: .12em;
  text-transform: none;   /* ⛔ jamás en versales: no tiene mayúsculas de verdad */
}

/* =====================================================================
   EL PAPEL, SÓLO EN EL ESCENARIO MARRÓN (2026-09-10)
   =====================================================================
   Carlos: «la textura no en todo, quizás en dos partes nada más, o sea
   quizás en el sólido marrón ese que pasa de un lado a otro».

   Ese sólido es UNA sola pieza contada en dos tiempos, y por eso son dos
   partes y no dos secciones sueltas:

     1. `.pase__onda` — la ola marrón que ocupa media pantalla detrás de
        cada plato y de cada copa, y que cambia de lado al pasar de la
        cocina («Plato a plato», masa a la derecha) a la barra («Copa a
        copa», espejada a la izquierda).
     2. `.cruce__ola` + `.cruce__relleno` — el manto que barre la
        pantalla entera para hacer ese cambio. Es el MISMO marrón,
        moviéndose.

   ⛔ SE PROBÓ EN `.propuesta` Y NO SIRVE. Es el riel marrón de la escena
   de arriba, pero encima lleva una foto a sangre desenfocada: el marrón
   no se ve en ningún momento, así que la textura era peso sin efecto.
   Medido, no supuesto: la desviación de la zona salía idéntica con
   textura y sin ella.

   Con el papel encima, el manto deja de leerse como una capa de color y
   pasa a leerse como una superficie que se desplaza: la materia va con
   él. Eso es lo que pedía Carlos.

   ⚠️ EL RESTO DEL SITIO NO LLEVA TEXTURA. Ni el papel arena, ni las
   fotos, ni las secciones con imagen de fondo. Si algún día se quiere en
   más sitios, se añade la clase `.papel` — no se toca esto.

   ⚠️ `multiply` Y NO `overlay`. Sobre un marrón hondo, `overlay` levanta
   las motas claras del papel y salpica el escenario de puntos blancos;
   `multiply` sólo deja pasar las sombras de la fibra, que es lo que se
   busca: materia, no ruido.

   ⚠️ LA COSTURA ENTRE LA OLA Y SU RELLENO. Son dos cajas pegadas, cada
   una con su propio origen de baldosa, así que el dibujo del papel NO
   continúa de una a otra. Con este grano —seis niveles de desviación
   sobre 255— no se ve, y medirlo no daba: se comprobó a ojo en tres
   momentos del barrido. Si algún día se sube el contraste de la
   textura, esto es lo primero que se rompe. */
@media (min-width: 900px) {
  .pase__onda,
  .cruce__ola,
  .cruce__relleno {
    background-image: var(--papel-marron);
    background-size: var(--papel-lado) var(--papel-lado);
  }
  /* ⛔ El eco NO lleva papel: es un canto de color translúcido pegado al
     filo de la ola, no una superficie. Con textura se ensuciaba. */
}

/* =====================================================================
   LAS VILLAS — la tarde se hace noche con el scroll (2026-09-07)
   (el espacio se llama Las Villas desde el 2026-09-10; la clase sigue
   siendo `.palapas` para no romper el JS ni el CSS ya escrito)
   =====================================================================
   Carlos: «quiero que esté como de tarde y mientras hago scroll el sol
   vaya bajando». Es un TIME-LAPSE de Seedance (SU foto del atardecer →
   noche, cámara clavada) que avanza conforme se baja. El porqué de cada decisión —video en vez
   de tres fijas, sin sol, sin lámparas— está en `_vistas/home.php`.

   Anatomía de la casa: riel alto (`.palapas`) + pantalla pegada
   (`.palapas__pega`). El JS publica `--avance` (0→1) y todo lo demás es
   CSS. ⛔ Sin GSAP. ⛔ Sin `overflow` en los ancestros de la pantalla
   pegada. ⛔ Sin <video>: en el iPhone, un video buscando fotograma a
   cada scroll se traba; las imágenes cruzando opacidad, no.

   ⭐ ES UN <video> FROTADO CON EL SCROLL. El JS le pone `currentTime`
   siguiendo `--avance` con suavizado (escritorio) o lo reproduce al
   quedar pegado (táctil). Antes fueron fotogramas sueltos, a fundido y
   luego a corte, y Carlos vio blur en uno y temblor en el otro; el
   porqué está en `_vistas/home.php`.

   ⚠️ EL LIENZO EMULA `object-fit: cover` A MANO. Es una caja con la
   proporción de los fotogramas (`--proporcion`, la publica el PHP) que
   mide lo que haga falta para cubrir la pantalla. Así se puede elegir
   qué punto de la imagen se centra (`--foco-x`) — con `object-fit`
   habría que repetir `object-position` en cada una de las 16.

   ⚠️ En MÓVIL la imagen se ve por menos de un tercio de su ancho.
   `--foco-x` dice qué punto se centra: al 32 % entra la palapa
   izquierda con la laguna. En escritorio va al 50 %: la caja mide justo
   el 100 % y cualquier otro foco descubriría un borde.

   El largo del riel y el foco se afinan en vivo con `?sol` (pruebas).
   ===================================================================== */
.palapas {
  position: relative;
  height: calc(var(--riel, 340) * 1svh);
  background: var(--marron);
  --foco-x: 50%;
  --proporcion: 1.7778;     /* ancho / alto del video (16:9); la publica el PHP */
}

/* ── LA SALIDA DE LA BANDA DE BIENVENIDA ────────────────────────────
   (2026-09-11) Carlos, con la captura del corte: «quiero el
   difuminado». Desde que Las Villas subió al segundo puesto, el marrón
   de la banda muere en un canto recto contra el cielo del vídeo —medido
   en la costura: #7c533e arriba, #93999c abajo, de un píxel al
   siguiente—. Es el mismo remate que llevaba la propuesta culinaria
   cuando ocupaba este sitio, movido a su nuevo vecino.

   ⚠️ Va en el RIEL (`.palapas`) y no en la pantalla pegada
   (`.palapas__pega`): dentro del `sticky` viajaría con él y el degradado
   se pasearía por toda la escena en vez de quedarse en la costura.
   `z-index: 2` lo pone por encima de la pantalla, que crea su propio
   contexto con `isolation`.

   ⚠️ Los alfas van explícitos hasta el cero (`rgb(124 83 62 / 0)`) y NO
   con la palabra `transparent`: en la interpolación, `transparent` es
   negro con alfa cero, y por el medio del degradado saldría un velo gris
   sucio — justo encima de un cielo de atardecer, que es donde más se
   notaría.

   ⚠️ Las paradas intermedias no son adorno: con dos paradas la curva
   sube de golpe por el centro y se ve una banda fantasma ahí. */
.palapas::before {
  content: "";
  position: absolute; z-index: 2; pointer-events: none;
  inset: 0 0 auto 0;
  height: clamp(110px, 16vh, 220px);
  background: linear-gradient(180deg,
    rgb(124 83 62 / 1)   0%,
    rgb(124 83 62 / .94) 18%,
    rgb(124 83 62 / .74) 40%,
    rgb(124 83 62 / .42) 64%,
    rgb(124 83 62 / .14) 84%,
    rgb(124 83 62 / 0)  100%);
}
.palapas__pega {
  position: sticky; top: 0;
  height: 100lvh; min-height: 560px;
  overflow: hidden;
  container-type: size;
  isolation: isolate;
  color: var(--sobre-hondo);
}
.palapas__lienzo {
  position: absolute; left: 50%; top: 50%;
  width: max(100cqw, calc(100cqh * var(--proporcion)));
  aspect-ratio: var(--proporcion);
  translate: calc(-1 * var(--foco-x)) -50%;
  /* ⛔ AQUÍ HUBO UN ZOOM LENTO (`scale` de 1 a 1,05 con `will-change`).
     Carlos: «¿por qué el video se pone así de feo, como que se hace
     blur?». Medido: con el zoom la nitidez caía a la MITAD (263 contra
     532 de varianza laplaciana en el mismo recorte). El compositor
     rasteriza la capa promocionada y luego la escala, y 16 imágenes de
     2560 en una capa son demasiado para que lo haga a resolución
     completa. Sin zoom: la imagen se pinta tal cual. */
}
.palapas__video {
  position: absolute; inset: 0;
  width: 100%; height: 100%; display: block;
  object-fit: cover;
  background: var(--marron);
}
/* ⛔ AQUÍ VIVIÓ `.palapas__capa`: la regla de una línea que encendía el
   fotograma k al cruzar (k-½)/(n-1) del avance, con `--n` y `--k`. Se
   fue con los fotogramas; si vuelven, está en `_maquetas/palapas-32-
   fotogramas/LEEME.txt` el porqué. */

/* ⛔ AQUÍ VIVIÓ EL SOL: `.palapas__cielo` (recorte al horizonte con
   `clip-path` y máscara del cielo para pasar detrás de los techos),
   `.palapas__sol` (disco + halo bajando en diagonal) y
   `.palapas__reflejo` (columna de luz en el agua). Carlos lo retiró el
   mismo día que se hizo: «no muestres el sol, con el cambio de tiempo
   está bien». La hora la cuenta la luz de las tres capas. */

/* El texto: en una caja de cristal —el marrón translúcido con desenfoque
   de las aperturas— porque encima pasa un cielo que va del azul claro al
   índigo y ningún texto suelto aguanta contraste en los tres.

   ⚠️ EN ESCRITORIO VA AL COSTADO IZQUIERDO. Carlos, 2026-09-10: «quiero
   el cuadro a un lado para que se vea un poco el efecto de la foto». En
   el centro la caja se comía justo las palapas y la laguna, que son el
   time-lapse entero; arrinconada a la izquierda tapa sólo la palapa del
   borde y deja el atardecer a la vista. El costado se alinea con el
   contenedor del sitio (`--ancho`), no con el filo de la pantalla, para
   que caiga en la misma columna que el resto de la portada. Y va CENTRADA
   EN ALTURA (Carlos, el mismo día): al costado, pegada abajo, la caja
   colgaba de una esquina; en el eje de la pantalla se lee como una placa
   puesta sobre la escena. En MÓVIL sigue abajo y centrada de lado a lado:
   ahí la caja ocupa el ancho, no hay costado que ganar, y el pie tiene
   que dejar sitio a la barra de app. */
.palapas__interior {
  position: absolute; inset: 0;
  display: grid; align-items: center; justify-items: start;
  padding-block: clamp(44px, 8vh, 84px);
  padding-inline: max(clamp(var(--aire), 4vw, 64px), calc((100% - var(--ancho)) / 2));
}
.palapas__texto {
  max-width: 36rem; text-align: left;
  padding: clamp(22px, 3vw, 34px) clamp(22px, 4vw, 46px) clamp(26px, 3.4vw, 38px);
  background: color-mix(in srgb, var(--marron) 78%, transparent);
  -webkit-backdrop-filter: blur(18px) saturate(130%);
  backdrop-filter: blur(18px) saturate(130%);
}
.palapas .rotulo { color: rgba(255, 255, 255, .92); }
.palapas h2 {
  font-size: var(--t-seccion);
  text-transform: uppercase;
  letter-spacing: -.005em; line-height: 1.08;
  color: #fff;
  margin: .5em 0 0; max-width: 20ch;
}
.palapas__texto > p:not(.rotulo) {
  margin: 1em 0 1.8em;
  color: rgba(244, 241, 234, .92);
  max-width: 42ch;
}
/* Las piezas entran escalonadas con el scroll, sólo cuando el JS ha
   encendido la escena (`palapas--viva`): sin JS el texto se ve entero y
   quieto, que no vuelva a pasar lo de la bienvenida. */
/* ⚠️ La CAJA también entra: si sólo entraran las letras, el cristal se
   vería un rato vacío, una mancha marrón sin nada dentro. */
.palapas--viva .palapas__texto {
  opacity: clamp(0, calc((var(--avance, 0) - .01) / .07), 1);
}
.palapas--viva .palapas__texto > * {
  opacity: var(--t, 1);
  translate: 0 calc((1 - var(--t, 1)) * 22px);
}
.palapas--viva .palapas__texto > :nth-child(1) { --t: clamp(0, calc((var(--avance, 0) - .02) / .08), 1); }
.palapas--viva .palapas__texto > :nth-child(2) { --t: clamp(0, calc((var(--avance, 0) - .05) / .09), 1); }
.palapas--viva .palapas__texto > :nth-child(3) { --t: clamp(0, calc((var(--avance, 0) - .09) / .09), 1); }
.palapas--viva .palapas__texto > :nth-child(4) { --t: clamp(0, calc((var(--avance, 0) - .13) / .09), 1); }

/* La línea de avance del pie, como en la galería. */
.palapas__barra {
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 2px; background: rgba(255, 255, 255, .16);
}
.palapas__avance {
  display: block; height: 100%;
  background: var(--acento);
  transform: scaleX(var(--avance, 0)); transform-origin: 0 50%;
}

@media (max-width: 899px) {
  .palapas { --riel: 280; --foco-x: 32%; }
  .palapas__pega { min-height: 0; }
  /* ⚠️ La pantalla está PEGADA, así que la barra de app del pie tapa
     siempre lo mismo: el botón necesita quedar por encima de ella. */
  /* ⭐ 2026-09-28 · Carlos: «que el cuadro del contenido quede en el centro
     de altura». Iba pegado abajo (`align-items: end`) sobre el alto de la
     pantalla pegada, que desde hoy es `lvh`: con la barra del navegador
     a la vista ese fondo queda debajo de ella y la caja se metía bajo la
     barra de app.
     Ahora la caja se centra en lo que SE VE: la capa mide `dvh` (sigue a
     la barra del navegador) y descuenta la cabecera arriba y la barra de
     app abajo. La foto sigue en `lvh` y no se mueve; si la barra aparece
     o se va, sólo la caja se recoloca, y lo hace con transición. */
  .palapas__interior {
    bottom: auto;
    height: 100svh;               /* reserva sin soporte de dvh */
    height: 100dvh;
    align-items: center;
    padding-top: var(--alto-cabecera);
    /* 128 = lo que ocupa la barra de app desde el borde: 36 de `bottom`
       + 62 de barra + 30 del hueco de la burbuja (ver `.app-nav`). Con
       96 la caja quedaba 32 px por debajo del centro. */
    padding-bottom: calc(128px + env(safe-area-inset-bottom, 0px));
    transition: height .35s var(--curva);
  }
  /* ⭐ EN MÓVIL LA CAJA ENTRA MÁS TARDE (2026-09-10). Carlos: «quiero que
     ese cuadro salga un poquito después». En el teléfono la sección
     ocupa 1.968 px y la caja aparecía casi a la vez que asomaba la
     escena, en cuanto el avance pasaba de .01; el atardecer no daba
     tiempo a verse solo. Todos los umbrales se corren +.14, que en esta
     pantalla son unos 175 px más de scroll: la foto se ve sola un rato
     y luego llega el texto.

     ⚠️ SÓLO EN MÓVIL. El escritorio se quedó como Carlos lo aprobó esta
     misma tarde; ahí la caja va al costado y con su tiempo. */
  .palapas--viva .palapas__texto {
    opacity: clamp(0, calc((var(--avance, 0) - .15) / .07), 1);
  }
  .palapas--viva .palapas__texto > :nth-child(1) { --t: clamp(0, calc((var(--avance, 0) - .16) / .08), 1); }
  .palapas--viva .palapas__texto > :nth-child(2) { --t: clamp(0, calc((var(--avance, 0) - .19) / .09), 1); }
  .palapas--viva .palapas__texto > :nth-child(3) { --t: clamp(0, calc((var(--avance, 0) - .23) / .09), 1); }
  .palapas--viva .palapas__texto > :nth-child(4) { --t: clamp(0, calc((var(--avance, 0) - .27) / .09), 1); }

  /* Móvil: la caja vuelve al centro y al ancho de la pantalla —el costado
     de escritorio no cabe aquí. */
  .palapas__interior { justify-items: center; }
  .palapas__texto { padding: 18px 18px 22px; max-width: 44rem; text-align: center; }
  .palapas h2 { max-width: 19ch; margin-inline: auto; }
  .palapas__texto > p:not(.rotulo) { max-width: 30ch; margin: 1em auto 1.4em; }
}

/* Sin movimiento: no hay riel; se ve el póster (su foto), el texto entero
   y quieto. El JS no arranca y el video no se pide. */
@media (prefers-reduced-motion: reduce) {
  .palapas { height: auto; --avance: .55; }
  .palapas__pega { position: relative; height: clamp(480px, 72svh, 700px); }
  .palapas__avance { display: none; }
}

/* =====================================================================
   BLOG EN LA PORTADA
   =====================================================================
   Tres entradas iguales, en fila. Carlos, 2026-08-13: «quiero mis tres
   columnas».

   ⚠️ Lo que se conserva de los montajes anteriores, porque costó
   encontrarlo: la fecha de antetítulo DENTRO del enlace, el titular
   cortado a tres líneas para que las columnas midan lo mismo, y el
   enlace de «Todas las entradas» en vez de un segundo botón «Blog».

   ⚠️ Todo el interior del enlace va en `span`, no en `h3`/`p`: mezclar
   títulos de sección dentro de un enlace ensucia el índice de
   encabezados de la página, que aquí está medido.
   ===================================================================== */
.blog-home { padding-block: var(--hueco-bloque); }
.blog-home__interior { max-width: var(--ancho); margin: 0 auto; padding-inline: var(--aire); }
.blog-home h2 {
  font-size: var(--t-seccion); margin: 0;
  text-transform: uppercase; letter-spacing: -.005em;
}

/* El título y el enlace a todo el blog comparten línea. */
.blog-home__cabeza {
  display: flex; flex-wrap: wrap; gap: 10px 20px;
  align-items: baseline; justify-content: space-between;
  margin-bottom: clamp(20px, 3vh, 34px);
}
/* Enlace de texto con flecha, no botón: al lado de un titular grande, un
   botón con caja compite con él en vez de acompañarlo. */
.blog-home__todas {
  font-family: var(--titulo); font-size: .76rem; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase;
  text-decoration: none; color: var(--acento-tinta);
  display: inline-flex; align-items: center; gap: 9px;
  min-height: 44px;                /* zona de toque */
}
.blog-home__todas svg { width: 17px; height: 17px; transition: transform .3s var(--curva); }
/* ⚠️ Sólo con ratón: en táctil un toque dispara `:hover` y el elemento
   se queda movido después de soltar el dedo. */
@media (hover: hover) and (pointer: fine) {
  .blog-home__todas:hover svg { transform: translateX(4px); }
}

.blog-home__lista { list-style: none; margin: 0; padding: 0; }

/* ── La tarjeta ────────────────────────────────────────────────────
   Carlos, 2026-08-13: «envuélvelos en un marco sutil de sombras».

   ⚠️ ESQUINAS RECTAS, como todo en este sitio. Es una de las cinco
   decisiones que ordenan el diseño y una sombra no la cambia.

   ⚠️ Es la ÚNICA sombra del sitio junto a la del botón flotante, así que
   va corta a propósito: dos capas muy suaves —una de contacto y otra de
   ambiente— sobre papel casi blanco. Una sombra fuerte aquí se leería
   como de otra web.

   El borde de 1px hace el trabajo cuando la sombra casi no se ve, que es
   lo que pasa en pantallas con poco contraste. */
.blog-home__enlace {
  text-decoration: none; color: inherit;
  display: block; height: 100%;
  background: var(--fondo-alto);
  border: 1px solid var(--linea);
  box-shadow: 0 1px 2px rgb(26 34 41 / .04),
              0 8px 22px rgb(26 34 41 / .06);
  transition: box-shadow .35s var(--curva), transform .35s var(--curva),
              border-color .35s var(--curva);
}
.blog-home__enlace:hover {
  transform: translateY(-3px);
  border-color: rgb(26 34 41 / .14);
  box-shadow: 0 2px 4px rgb(26 34 41 / .06),
              0 16px 38px rgb(26 34 41 / .12);
}
/* Quien pide menos movimiento no recibe el levantamiento; la sombra sí,
   que no se mueve. */
@media (prefers-reduced-motion: reduce) {
  .blog-home__enlace:hover { transform: none; }
}

.blog-home__foto { display: block; overflow: hidden; background: var(--fondo-hondo); }
.blog-home__foto img {
  width: 100%; aspect-ratio: 3 / 2; object-fit: cover; display: block;
  /* ⚠️ 260ms, no 700. A 700 la foto seguía creciendo mucho después de que
     el ratón se hubiera ido: el techo para UI son 300ms. */
  transition: transform .26s var(--curva);
}
@media (hover: hover) and (pointer: fine) {
  .blog-home__enlace:hover .blog-home__foto img { transform: scale(1.04); }
}

/* El texto ya no cuelga de la foto: vive dentro de la tarjeta y necesita
   su propio aire por los cuatro lados. */
.blog-home__texto {
  display: block;
  padding: clamp(16px, 1.6vw, 22px) clamp(16px, 1.6vw, 22px) clamp(18px, 1.9vw, 26px);
  /* Fecha y titular AL CENTRO — Carlos, 2026-08-14. Los dos juntos: el
     titular centrado con la fecha a la izquierda quedaría cojo. */
  text-align: center;
}
.blog-home__fecha {
  display: block;
  font-family: var(--titulo); font-size: .68rem; letter-spacing: .14em;
  text-transform: uppercase; color: var(--texto-suave);
  margin-bottom: .5em;
}
.blog-home__titulo {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3;
  overflow: hidden;                /* tres líneas: así las columnas miden igual */
  font-family: var(--titulo); font-weight: 600; line-height: 1.3;
  font-size: var(--t-blog);
}
.blog-home__enlace:hover .blog-home__titulo { color: var(--acento-tinta); }

/* ── Móvil: se desliza, no se apila ────────────────────────────────── */
@media (max-width: 899px) {
  .blog-home__lista {
    display: grid; gap: 14px;
    grid-auto-flow: column; grid-auto-columns: 76%;
    overflow-x: auto; scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--aire);
    margin-inline: calc(var(--aire) * -1); padding-inline: var(--aire);
    padding-bottom: 8px;
    -webkit-overflow-scrolling: touch; scrollbar-width: none;
  }
  .blog-home__lista::-webkit-scrollbar { display: none; }
  .blog-home__item { scroll-snap-align: start; scroll-snap-stop: always; }
}

/* ── Escritorio: las tres columnas ─────────────────────────────────── */
@media (min-width: 900px) {
  .blog-home__lista {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: clamp(20px, 2.4vw, 34px);
    /* `stretch` y no `start`: las tres tarjetas miden lo mismo aunque un
       titular caiga en dos líneas y otro en tres. Con `start` cada una
       se quedaba a su alto y las sombras dibujaban un escalón. */
    align-items: stretch;
  }
}

/* =====================================================================
   LA GALERÍA DE LA PORTADA
   =====================================================================
   Diez fotos del sitio: el aire, la laguna, la mesa, la noche y la
   comida. Ocupa el hueco que dejó el viaje de las cartas (2026-08-12).

   ⭐ Es un SLIDER, por encargo de Carlos (2026-08-12, tarde). Antes fue un
   mosaico en rejilla; funcionaba, pero pedía la pantalla entera para
   contarse y la portada ya es larga. En carrusel la sección ocupa una
   franja y la galería se recorre.

   ⭐ Cada foto CONSERVA SU PROPORCIÓN: todas comparten alto y el ancho lo
   pone la imagen, así que las verticales salen estrechas y las
   horizontales anchas. Eso es lo que hace que se lea como una galería de
   material variado y no como una fila de recortes iguales.

   Se recorre de cuatro maneras y todas mueven lo mismo, el `scrollLeft`:
   arrastrando con el ratón, con las flechas, con el dedo y con el
   teclado. Nada de librerías: `scroll-snap` nativo.

   ⛔ Sin librería de carrusel. Este proyecto ya sirve GSAP desde el propio
   servidor y no añade un CDN por nada — ver la nota del pie de la home.

   ⚠️ `scroll-behavior: smooth` va en la LISTA, no en `html`: puesto
   arriba se lleva por delante los saltos de ancla del índice de la carta.
   ===================================================================== */
.galeria { padding-block: var(--hueco-bloque); }

.galeria__cabeza {
  margin-bottom: clamp(22px, 3.4vh, 40px);
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 20px; flex-wrap: wrap;
}
.galeria__cabeza h2 {
  font-size: clamp(1.38rem, 3.4vw, 2.125rem);   /* el techo de 34px de la casa */
  text-transform: uppercase; letter-spacing: -.005em; line-height: 1.08;
  margin: 0;
}

/* ── Los mandos ────────────────────────────────────────────────────
   Sólo con ratón: en táctil se arrastra y dos botones sobran. Se
   esconden por TIPO DE PUNTERO y no por ancho de pantalla, que es lo
   que deja sin flechas a un portátil táctil de 1440. */
.galeria__mandos { display: none; gap: 8px; }
@media (hover: hover) and (pointer: fine) {
  .galeria__mandos { display: flex; }
}
.galeria__flecha {
  width: 46px; height: 46px;            /* zona de toque por encima del mínimo */
  display: grid; place-items: center;
  background: transparent; color: var(--texto);
  border: 1px solid var(--linea);
  cursor: pointer;
  transition: background .22s var(--curva-color), color .22s var(--curva-color),
              border-color .22s var(--curva-color), opacity .22s var(--curva-color);
}
.galeria__flecha svg { width: 20px; height: 20px; }
.galeria__flecha:hover:not(:disabled) {
  background: var(--texto); border-color: var(--texto); color: var(--fondo);
}
/* Deshabilitada en los extremos: se ve que no hay más, en vez de pulsar
   contra una pared. */
.galeria__flecha:disabled { opacity: .3; cursor: default; }

/* ── La cinta ──────────────────────────────────────────────────────── */
.galeria__lista {
  list-style: none; margin: 0; padding: 0;
  display: flex; gap: 14px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  /* Sangra hasta el borde de la pantalla: la primera foto se alinea con
     el titular y las demás siguen saliendo por la derecha. Eso es lo que
     dice «esto continúa» sin ponerle una sombra encima. */
  padding-inline: max(var(--aire), calc((100vw - var(--ancho)) / 2 + var(--aire)));
  scroll-padding-inline: max(var(--aire), calc((100vw - var(--ancho)) / 2 + var(--aire)));
  padding-bottom: 4px;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  cursor: grab;
}
.galeria__lista::-webkit-scrollbar { display: none; }
.galeria__lista:focus-visible { outline: 2px solid var(--acento-tinta); outline-offset: 4px; }
/* Mientras se arrastra: el cursor cambia y se apaga el snap, o el
   navegador pelea con el arrastre a cada píxel. */
.galeria__lista.arrastrando {
  cursor: grabbing; scroll-snap-type: none; scroll-behavior: auto;
}
.galeria__lista.arrastrando img { pointer-events: none; }

.galeria__pieza {
  flex: 0 0 auto;                 /* que no se encojan para caber todas */
  scroll-snap-align: start; scroll-snap-stop: always;
  /* ⚠️ El alto lo manda todo: el ancho de cada foto sale de él y de su
     proporción. Subió de 520 a 700 px el 2026-08-13 a petición de
     Carlos. Si se vuelve a subir hay que REGENERAR las imágenes —hoy
     miden 1600 px de lado las horizontales y 1100 las verticales—, o a
     partir de aquí empezarán a verse blandas en pantalla retina. */
  height: clamp(320px, 68svh, 700px);
  overflow: hidden;
  background: var(--fondo-hondo); /* el hueco no parpadea en blanco al cargar */
}
.galeria__pieza img {
  /* ⭐ Alto fijo y ancho AUTO: aquí nace la variedad de la cinta. */
  height: 100%; width: auto; max-width: none; display: block;
  object-fit: cover;
  transition: transform .26s var(--curva);   /* ⚠️ ver la nota del blog */
  user-select: none; -webkit-user-drag: none;
}

/* ⚠️ En móvil el ancho SÍ se limita. Con el alto a 68svh una panorámica
   pide 860 px de ancho en una pantalla de 390: no se vería entera nunca,
   habría que deslizar dos veces para pasar una sola foto. Aquí se topa
   al ancho de la pantalla menos el aire, y la foto se recorta por el
   centro. Es el único sitio donde se sacrifica la proporción, y a
   cambio cabe una foto por pantalla con la vecina asomando. */
@media (max-width: 899px) {
  .galeria__pieza { max-width: calc(100vw - var(--aire) * 3); }
  .galeria__pieza img { width: 100%; }
}
@media (hover: hover) {
  .galeria__pieza:hover img { transform: scale(1.04); }
}

/* La foto es pulsable: el botón no añade caja ni fondo, sólo hace de
   zona de clic. `display: block` para que no deje el hueco de la línea
   base debajo de la imagen. */
.galeria__abrir {
  display: block; width: 100%; height: 100%;
  padding: 0; margin: 0; border: 0; background: none;
  cursor: zoom-in;
}
.galeria__abrir:focus-visible { outline: 3px solid var(--acento); outline-offset: -3px; }
/* Mientras se arrastra la cinta, el cursor manda sobre el de la foto. */
.galeria__lista.arrastrando .galeria__abrir { cursor: grabbing; }


/* =====================================================================
   EL VISOR DE LA GALERÍA
   =====================================================================
   `<dialog>` nativo: el navegador atrapa el foco dentro, cierra con
   Escape y apila por encima de todo sin pelear con `z-index`.

   ⚠️ El fondo es el AZUL PIZARRA de la marca a mucha opacidad, no negro:
   Fred's no tiene negro en su paleta. Es la única superficie oscura del
   sitio y está justificada — sobre papel claro una foto no se mira, se
   ojea.
   ===================================================================== */
.visor {
  width: 100vw; max-width: 100vw;
  height: 100dvh; max-height: 100dvh;
  padding: 0; border: 0; margin: 0;
  background: color-mix(in srgb, var(--marron) 96%, #000);
  color: #fff;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: stretch;
  gap: clamp(6px, 1.5vw, 20px);
  overscroll-behavior: contain;
}
.visor::backdrop { background: color-mix(in srgb, var(--marron) 92%, #000); }
.visor:not([open]) { display: none; }

/* ⚠️ 2026-08-13 · ENTRA, no aparece de golpe. Un `<dialog>` que se abre
   sin transición es un salto seco, y éste tapa la pantalla entera.
   La foto sube un poco y aparece; el fondo sólo se funde.

   ⚠️ Con `@starting-style` y `allow-discrete`, que es lo que permite
   animar un elemento que pasa de `display: none` a visible. Sin
   `allow-discrete` el navegador lo muestra de golpe y sólo anima la
   salida.
   ⚠️ Escala desde .98, nunca desde 0: nada en el mundo real aparece de
   la nada. */
.visor, .visor::backdrop {
  transition: opacity .24s var(--curva-color),
              transform .28s var(--curva),
              display .28s allow-discrete,
              overlay .28s allow-discrete;
}
.visor { opacity: 1; transform: scale(1); }
.visor:not([open]) { opacity: 0; transform: scale(.98); }
@starting-style {
  .visor[open] { opacity: 0; transform: scale(.98); }
  .visor[open]::backdrop { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .visor, .visor:not([open]) { transform: none; }
}

/* ⛔ `minmax(0, 1fr)` y `min-height: 0`, NUNCA `1fr` a secas. Una pista
   `1fr` trae `min-height: auto`, así que se estira hasta el tamaño
   natural de la imagen: el marco llegó a medir 2108 px en una ventana de
   900, la foto se salía por arriba y el pie se iba fuera de pantalla.
   Lo mismo vale para la columna del medio en `.visor`. */
.visor__marco {
  margin: 0; padding: clamp(52px, 7vh, 78px) 0 clamp(46px, 6vh, 64px);
  height: 100%; min-height: 0; min-width: 0;
  display: grid; grid-template-rows: minmax(0, 1fr) auto; gap: 14px;
  justify-items: center; align-items: center;
}
.visor__foto {
  max-width: 100%; max-height: 100%;
  width: auto; height: auto;
  min-height: 0; min-width: 0;
  object-fit: contain;
  display: block;
  /* ⭐ La foto entera SIEMPRE: aquí no se recorta nada. Es lo que
     distingue el visor de la cinta, donde sí se topa en móvil. */
}
.visor__pie {
  display: flex; flex-wrap: wrap; gap: 4px 16px;
  align-items: baseline; justify-content: center;
  text-align: center; padding-inline: var(--aire);
  font-size: .9rem; color: rgba(255,255,255,.82);
  max-width: 68ch;
}
.visor__cuenta {
  font-family: var(--titulo); font-size: .72rem; letter-spacing: .14em;
  color: var(--crema);
}

/* ── Los mandos ────────────────────────────────────────────────────── */
.visor__flecha, .visor__cerrar {
  background: none; border: 0; color: #fff; cursor: pointer;
  display: grid; place-items: center;
  width: 56px; height: 56px;         /* muy por encima del mínimo táctil */
  opacity: .78;
  transition: opacity .22s var(--curva-color), transform .22s var(--curva);
}
/* ⚠️ El visor alinea sus columnas con `stretch` —lo necesita el marco de
   la foto para ocupar el alto—, así que las flechas hay que centrarlas a
   mano. Sin esto se van arriba y la derecha choca con el aspa. */
.visor__flecha { align-self: center; }
.visor__flecha svg { width: 28px; height: 28px; }
.visor__cerrar svg { width: 22px; height: 22px; }
.visor__flecha:hover, .visor__cerrar:hover { opacity: 1; }
.visor__flecha:disabled { opacity: .22; cursor: default; }
.visor__flecha, .visor__cerrar { outline-offset: 2px; }
.visor__flecha:focus-visible, .visor__cerrar:focus-visible { outline: 2px solid var(--acento); opacity: 1; }

/* ⚠️ Con fondo propio: va encima de la foto y sobre una zona clara —el
   agua turquesa de una cenital, por ejemplo— una equis blanca a secas
   desaparece. */
.visor__cerrar {
  position: absolute; top: clamp(8px, 1.6vh, 18px); right: clamp(8px, 1.6vw, 18px);
  z-index: 2;
  background: color-mix(in srgb, var(--marron) 72%, transparent);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}

/* En móvil las flechas se salen del sitio: bajan sobre la foto, a los
   lados, donde el pulgar llega. */
@media (max-width: 699px) {
  .visor { grid-template-columns: 1fr; }
  .visor__flecha {
    position: absolute; bottom: clamp(10px, 2vh, 20px); z-index: 2;
    background: color-mix(in srgb, var(--marron) 70%, transparent);
  }
  .visor__flecha--izq { left: 10px; }
  .visor__flecha--der { right: 10px; }
  .visor__marco { padding-bottom: clamp(76px, 11vh, 96px); }
}

/* ── La barra de avance ────────────────────────────────────────────
   Una línea fina que dice cuánto queda. La rellena `--avance`, que
   publica el JS de 0 a 1; sin JS se queda a cero y no molesta. */
.galeria__barra {
  margin-top: clamp(18px, 2.6vh, 28px);
  height: 2px; background: var(--linea);
}
.galeria__avance {
  display: block; height: 100%;
  background: var(--acento);
  transform: scaleX(var(--avance, 0)); transform-origin: 0 50%;
  transition: transform .18s linear;
}

/* ⛔ Aquí vivía `.galeria__cartas`, tres botones a las cartas al pie de
   la galería. Retirados el 2026-08-12: las tres cartas ya están en el
   submenú de la cabecera —que va fija toda la página— y los pases de
   cocina y barra llevan su propio botón. Era el cuarto sitio de la
   portada con el mismo enlace. */


/* =====================================================================
   EL VIAJE DE LAS CARTAS  ·  ⛔ RETIRADO EL 2026-08-12
   =====================================================================
   Ya no lo usa ninguna vista: la portada lo cambió por la galería de
   aquí arriba. Se deja escrito, como se hizo con `.cocina`, porque el
   patrón —riel + pantalla pegada + `translateZ` sobre `perspective`— es
   el que mejor ha funcionado en este proyecto y se querrá reutilizar.

   Riel alto + pantalla pegada + escenario con `perspective`. La
   perspectiva es lo que convierte el `translateZ` de cada carta en
   profundidad de verdad: los bordes de la foto se abren al acercarse.
   Con un `scale` eso no pasa, y se nota.

   Mientras el JavaScript no enciende el viaje (`.viaje--activo`), lo que
   se ve es el carrusel de siempre: en móvil, sin JavaScript o con menos
   movimiento, nadie se queda sin las tres cartas.
   ===================================================================== */
.viaje { position: relative; }
.viaje__pega { display: none; }
.viaje__plano { padding-block: var(--hueco-bloque); }
.viaje__rotulo { max-width: var(--ancho); margin-inline: auto; padding-inline: var(--aire); }

@media (min-width: 901px) {
  /* El riel: una pantalla y media por carta, más media de entrada. */
  .viaje { height: 500svh; }
  .viaje__pega {
    display: block; position: sticky; top: 0;
    height: 100lvh; overflow: hidden;
  }
  .viaje__rotulo { position: absolute; top: 96px; left: 0; right: 0; z-index: 3; }

  .viaje__escenario {
    position: absolute; inset: 0;
    display: grid; place-items: center;
    /* ⭐ La pieza clave: sin esto el translateZ no se ve como profundidad. */
    perspective: 1100px;
    perspective-origin: 50% 46%;
  }
  .viaje__carta {
    grid-area: 1 / 1;              /* las tres ocupan el mismo sitio */
    width: min(34vw, 420px);
    transform-style: preserve-3d;
    will-change: transform, opacity, filter;
    opacity: 0;
  }
  .viaje__carta a { display: block; text-decoration: none; position: relative; }
  /* Un degradado SÓLO en la franja del nombre, no un velo sobre la foto
     entera. La sombra de letra sola no basta cuando debajo hay una foto
     clara: el nombre de la carta tiene que leerse siempre. */
  .viaje__carta a::after {
    content: ''; position: absolute; inset: auto 0 0 0; height: 42%;
    background: linear-gradient(to top, rgb(8 16 24 / .78), transparent);
    pointer-events: none;
  }
  .viaje__carta img {
    width: 100%; aspect-ratio: 3 / 4; object-fit: cover;
    box-shadow: 0 40px 80px rgb(15 25 35 / .28);
  }
  .viaje__nombre {
    position: absolute; z-index: 2; left: 24px; right: 24px; bottom: 22px;
    font-family: var(--titulo); font-weight: 600; font-size: 1.05rem;
    letter-spacing: .18em; text-transform: uppercase; color: #fff;
    text-shadow: 0 2px 16px rgb(0 0 0 / .75);
  }
  /* Cuando el viaje está encendido, el carrusel plano se retira. */
  .viaje.viaje--activo .viaje__plano { display: none; }
}

/* =====================================================================
   CASCADA — lo que entra, entra en orden
   =====================================================================
   Prensa, blog, zonas del Kids Club y platos de la carta. El retardo de
   cada pieza lo pone el JavaScript en `--retardo`; el movimiento lo hace
   el navegador solo.
   ===================================================================== */
.js .cascada {
  opacity: 0; transform: translateY(26px);
  transition: opacity .7s var(--curva) var(--retardo, 0ms),
              transform .7s var(--curva) var(--retardo, 0ms);
}
.js .cascada--entra { opacity: 1; transform: none; }

/* La línea de avance bajo el índice de la carta: cuánto queda por leer. */
.carta__avance {
  position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
  background: var(--acento); transform: scaleX(0); transform-origin: 0 50%;
  will-change: transform;
}
.carta__indice { position: sticky; }

/* Utilidad: texto sólo para lectores de pantalla. */
.visualmente-oculto {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* =====================================================================
   LA CARTA
   ===================================================================== */
.carta__cambio { border-block: 1px solid var(--borde); }
.carta__cambio ul {
  max-width: var(--ancho); margin: 0 auto; padding: 0 var(--aire);
  list-style: none; display: flex; gap: 0; overflow-x: auto;
  scrollbar-width: none;
}
.carta__cambio ul::-webkit-scrollbar { display: none; }
.carta__cambio a {
  display: block; padding: 18px 26px; text-decoration: none;
  font-family: var(--titulo); font-size: .76rem; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase; white-space: nowrap;
  color: var(--texto-suave);
  border-bottom: 2px solid transparent;
  transition: color .25s var(--curva), border-color .25s var(--curva);
}
.carta__cambio a:hover { color: var(--texto); }
.carta__cambio a[aria-current] { color: var(--texto); border-bottom-color: var(--acento); }

/* Índice pegajoso de apartados.
   ⚠️ Fondo SÓLIDO, no translúcido. Se probó con `color-mix` al 94 % y
   `backdrop-filter`, y los nombres de los platos se leían a través de la
   barra mientras pasaban por detrás. Una barra de navegación no necesita
   efecto: necesita que se lea lo que pone. */
.carta__indice {
  position: sticky; top: var(--alto-cabecera); z-index: 20;
  background: var(--fondo);
  border-bottom: 1px solid var(--borde);
}
.carta__indice ul {
  max-width: var(--ancho); margin: 0 auto; padding: 0 var(--aire);
  list-style: none; display: flex; gap: 22px; overflow-x: auto;
  scrollbar-width: none;
}


.carta__indice ul::-webkit-scrollbar { display: none; }
/* Un desvanecido al borde para que se vea que la lista sigue, en vez de
   cortar un rótulo por la mitad y parecer un fallo. */
.carta__indice, .carta__cambio {
  -webkit-mask-image: linear-gradient(90deg, #000 0, #000 92%, transparent 100%);
          mask-image: linear-gradient(90deg, #000 0, #000 92%, transparent 100%);
}
@media (min-width: 900px) {
  .carta__indice, .carta__cambio { -webkit-mask-image: none; mask-image: none; }
}
.carta__indice a {
  display: flex; align-items: center; min-height: 44px; padding: 10px 0; text-decoration: none; white-space: nowrap;
  font-family: var(--titulo); font-size: .72rem; font-weight: 500;
  letter-spacing: .13em; text-transform: uppercase; color: var(--texto-suave);
  border-bottom: 2px solid transparent;
  transition: color .25s var(--curva), border-color .25s var(--curva);
}
.carta__indice a:hover { color: var(--texto); }
.carta__indice a.actual { color: var(--acento-tinta); border-bottom-color: var(--acento); }

/* ── El icono de cada apartado — Carlos, 2026-08-21 ─────────────────
   Doce nombres en versalitas, del mismo cuerpo y en una fila que se
   desliza, se leen como un muro: no se distingue uno de otro sin
   pararse a leer. Con una silueta delante, cada apartado se reconoce de
   un vistazo y la fila deja de ser un bloque gris.

   ⚠️ Hereda el color del enlace (`currentColor`), así que se enciende
   con él al llegar a su apartado. Y `flex: 0 0 auto` para que no lo
   encoja la fila deslizante: sin eso los iconos se aplastan a 9px
   cuando hay muchos apartados. */
.carta__icono {
  width: 17px; height: 17px; flex: 0 0 auto;
  margin-right: 7px; opacity: .78;
  transition: opacity .25s var(--curva);
}
.carta__indice a:hover .carta__icono,
.carta__indice a.actual .carta__icono { opacity: 1; }

/* ═══════════════════════════════════════════════════════════════════
   EL ÍNDICE, ABAJO Y FLOTANDO — Carlos, 2026-08-21
   ═══════════════════════════════════════════════════════════════════
   «Baja lo de pasta y eso para abajo, con iconos, en una pill flotante
   slide.»

   Pegado bajo la cabecera se comía 45px de pantalla en un teléfono
   —encima de una cabecera que ya ocupa 57— y empujaba la carta hacia
   abajo todo el rato. Abajo no le quita sitio a nada: el pulgar llega
   solo y la carta se lee entera.

   ⭐ SE PUEDE PORQUE EN LAS CARTAS NO HAY BARRA DE APP. Es la única
   parte del sitio donde ese hueco de abajo está libre, y por eso aquí
   cabe y en el resto no. Si algún día la barra vuelve a las cartas,
   esto y ella se pisan.

   La forma es la de la barra de app —misma píldora, mismo marrón, mismo
   aire al borde—: no se inventa un componente nuevo para lo mismo.

   ⚠️ ESTE BLOQUE VA DESPUÉS de las reglas normales del índice, no
   antes. Puesto arriba, la regla base `.carta__indice a` —que pesa lo
   mismo— ganaba por ir después y el texto salía en tinta marrón sobre
   el marrón de la píldora: no se leía nada. */
@media (max-width: 899px) {
  .carta__indice {
    position: fixed; z-index: 44;
    top: auto;
    left: 8px; right: 8px;
    bottom: calc(14px + env(safe-area-inset-bottom, 0px));
    background: var(--marron);
    border: 0; border-radius: 26px;
    box-shadow: 0 10px 30px rgba(26, 16, 10, .38);
    /* ⚠️ El desvanecido del borde va SÓLO a la derecha aquí: con la
       píldora redondeada, el de la izquierda se comía la primera
       silueta y parecía que el icono estaba cortado. */
    -webkit-mask-image: linear-gradient(90deg, #000 0, #000 88%, transparent 100%);
            mask-image: linear-gradient(90deg, #000 0, #000 88%, transparent 100%);
  }
  .carta__indice ul { gap: 4px; padding: 0 6px; scroll-snap-type: x proximity; }
  .carta__indice li { scroll-snap-align: center; scroll-snap-stop: always; }
  .carta__indice a {
    min-height: 46px; padding: 8px 14px;
    color: rgb(255 255 255 / .82);
    border-bottom: 0; border-radius: 20px;
    /* ⛔ EN FILA, NO EN COLUMNA. El primer intento puso la silueta encima
       y el nombre debajo, como la barra de app. Pero allí los nombres son
       de una palabra —HOME, BOOK— y aquí hay «TACOS & QUESADILLAS»: con
       `nowrap` y una columna de 46px, el texto se salía por los lados y
       se montaba encima de los apartados vecinos. En fila cada uno ocupa
       lo que mide y la píldora se desliza, que es para lo que está. */
    flex-direction: row; gap: 7px;
    font-size: .62rem; letter-spacing: .11em;
  }
  .carta__indice a.actual {
    color: #fff; background: rgb(255 255 255 / .12);
    border-bottom-color: transparent;
  }
  .carta__icono { width: 18px; height: 18px; margin-right: 0; }

  /* Y la carta necesita sitio al final para que la píldora no le tape
     el último plato. La cuenta es la de la propia píldora. */
  .pagina-food-menu main, .pagina-mixology main, .pagina-desserts main {
    padding-bottom: calc(46px + 16px + 14px + 22px + env(safe-area-inset-bottom, 0px));
  }
}

/* ⚠️ Iba en TERRACOTA y era el único título de sección del sitio con
   otro color (auditoría 2026-08-17). Los títulos son de tinta; el acento
   se reserva para rótulos y enlaces. */
/* ── Los apartados, como abre una carta de verdad ──────────────────
   Carlos, 2026-08-24, eligiendo la maqueta C: el apartado deja de estar
   centrado y en tinta —donde se confundía con un titular más del sitio— y
   abre a la IZQUIERDA, grande, en el naranja de atardecer y con un filete
   que se estira hasta el borde. Es lo que marca el corte entre FRESH y
   HOT sin necesidad de un bloque de color.

   ⚠️ El filete se estira con lo que SOBRE (`flex: 1`), no con un ancho
   fijo: así funciona igual con «FRESH» que con «TACOS & QUESADILLAS».
   ⚠️ EL COLOR SE MIDIÓ, Y EL PRIMERO NO PASABA. Se puso `--boton-honda`
   pensando que a 24px valía la regla de texto grande (3:1) — pero el
   título quedó en 22,08 con peso 600, y «grande» sólo empieza en 18,66
   si el peso es 700. A 3,77:1 no cumplía. Lleva `--acento-titulo`, el
   mismo tono de atardecer hundido hasta 4,52:1. */
.carta__grupo {
  font-size: var(--t-seccion); text-align: left;
  margin: clamp(56px, 7vw, 96px) 0 0;
}
.carta__seccion {
  padding-block: clamp(36px, 5vw, 56px);
  /* Que el índice pegajoso no se coma el título al saltar a un apartado. */
  scroll-margin-top: calc(var(--alto-cabecera, 88px) + 16px);
}
/* ⚠️ EL CUERPO SALE DE LA ESCALA, NO SE INVENTA. El primer intento le
   puso un `clamp` propio de 24 → 29,6px y el auditor de escalas lo cazó:
   dos cuerpos distintos para el mismo papel. FRESH y HOT son títulos de
   SECCIÓN de la carta, así que llevan `--t-seccion` como los demás
   títulos de sección del sitio: 22,1 en el teléfono y 34 en la pantalla.
   Lo que lo separa de STARTERS —que es el grupo— no es el tamaño: es el
   color y el filete. */
.carta__titulo {
  display: flex; align-items: center; gap: 14px;
  font-size: var(--t-seccion);
  letter-spacing: .05em; text-transform: uppercase; text-align: left;
  color: var(--acento-titulo);
}
.carta__titulo::after {
  content: ""; flex: 1; height: 1px;
  background: linear-gradient(90deg, var(--acento-titulo), transparent);
}
.carta__nota { color: var(--texto-suave); font-size: var(--t-apoyo); margin-top: .9em; }

/* ⭐ CADA PLATO, UNA TARJETA — Carlos, 2026-08-21: «métemelos en card».
   Antes eran filas sueltas sobre el papel, separadas sólo por aire: con
   55 platos seguidos, la vista no encontraba dónde empieza uno y acaba
   el otro. La tarjeta le pone borde al bocado.

   ⚠️ ESQUINAS RECTAS, como todo el sitio. Y papel elevado —la crema del
   PSD— sobre el arena: es el mismo escalón que usan las demás
   superficies que se levantan, no un gris inventado para esto. */
/* ⛔ LA TARJETA SE FUE — Carlos, 2026-08-24, eligiendo la maqueta C.
   Las tarjetas se pusieron el 21 de agosto para que la vista supiera dónde
   acaba un plato y empieza el otro, y ese problema lo resolvían. Pero con
   31 de 55 platos sin foto, cada tarjeta enseñaba ADEMÁS su hueco vacío:
   una caja vacía se ve mucho más que un renglón vacío.

   Ahora separa una línea fina sobre el papel del sitio, que es como lo
   hace la carta de Frog's —la referencia que puso él— y como se separan
   las cosas en el resto de esta web. Lo que llena el hueco es el icono del
   apartado; eso vive en `.plato__silueta`, más abajo.

   ⚠️ Medido antes y después a 390px: la carta pasa de 13,0k a 12,8k px de
   alto y el plato deja de ir de 66 a 304 —los 31 sin foto ya no se
   encogen a la mitad de alto que sus vecinos—.
   ⚠️ Las tres maquetas que NO se eligieron están guardadas en
   `_maquetas/carta-movil/`, con el porqué de cada una. */
.carta__platos { display: grid; gap: 0; margin-top: 20px; }
.plato {
  background: none;
  border: 0;
  border-bottom: 1px solid var(--borde);
  padding: 18px 0;
}
/* ⚠️ El último sin línea sólo donde la carta va en UNA columna: con dos,
   `:last-child` es el último del grid entero y dejaba la columna izquierda
   cerrada y la derecha abierta. Con dos columnas la línea final cierra el
   apartado, que es lo que se quiere. */
@media (max-width: 899px) {
  .plato:last-child { border-bottom: 0; }
}

/* ⚠️ El plato es una fila: miniatura a un lado, texto al otro. Se probó
   con la foto a todo el ancho de la columna y ocupaba media pantalla por
   platillo: en una carta de 55 platos, la foto acompaña, no manda.

   ⭐ TODOS LOS PLATOS LLEVAN LA REJILLA, TENGAN FOTO O NO — Carlos,
   2026-08-21. Antes los que no tenían foto ocupaban la fila entera y
   empezaban pegados al margen, mientras los que sí la tienen empezaban
   200px más adentro: la carta se leía como dos listas mezcladas. Con 31
   de 55 platos sin foto, eso es más de la mitad desalineada.

   Ahora el hueco de la foto se RESERVA siempre. Cuando no hay imagen no
   se dibuja nada —nada de 31 cuadrados grises—: sólo se respeta el
   sitio, y todos los nombres arrancan en la misma vertical. */
.plato {
  display: grid; grid-template-columns: 100px minmax(0, 1fr);
  gap: .35em 14px; align-items: start; align-content: start;
}
.plato__nombre { grid-column: 2; }
.plato__desc   { grid-column: 2; }
/* ⚠️ La foto ocupa las dos filas y el texto la segunda columna. Sin esto
   el nombre cae al lado de la foto pero la descripción se va DEBAJO de
   ella, en una columna de 96 px, y sale una palabra por línea. */
.plato__foto { grid-row: 1 / span 2; }
/* ⚠️ EN VERSALITAS. Es lo que hace que la columna se lea como una carta
   y no como una lista de párrafos: el nombre y la descripción dejan de
   pesar lo mismo. Frog's lo lleva a 700; la Titular Freds a 600 ya marca
   igual, que es de trazo más fino. */
.plato__nombre {
  font-family: var(--titulo); font-size: 1rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .06em; margin: 0 0 .35em;
}
/* La ración va aparte del nombre, en gris y más pequeña: es un dato,
   no parte de cómo se llama el plato. */
.plato__racion {
  font-family: var(--cuerpo); font-weight: 400; font-size: .82em;
  color: var(--texto-suave); margin-left: .5em; letter-spacing: 0;
}
/* ⛔ El precio NO va con `float: right`. Al ir después del nombre en el
   HTML, el texto ya está colocado cuando aparece el float y no lo
   esquiva: en móvil el precio se montaba encima del nombre en 23 platos
   (2026-08-31, al traer los precios del menú del cliente). Los dos
   extremos de la línea, con el precio entero y sin partir. */
.plato__nombre     { display: flex; align-items: baseline; gap: .75em; flex-wrap: nowrap; }
.plato__nombre-txt { flex: 1 1 auto; min-width: 0; }
/* ⚠️ Sin `flex-shrink: 0` el precio se parte —«$1,\n200»— en cuanto el
   nombre es largo; y con `wrap` salta a una línea suya y queda suelto a
   la derecha. Se queda en la primera línea, que es donde lo busca quien
   lee una carta. */
.plato__precio     { flex: 0 0 auto; margin-left: auto; white-space: nowrap; color: var(--acento-tinta); }
/* ⭐ A LA IZQUIERDA, no justificado — Carlos, 2026-08-21: «todo va en el
   menú justificado a la izquierda».
   La ley de la casa manda justificar las descripciones con la última
   línea centrada, y eso vale para un párrafo que se lee de corrido. En
   una CARTA no: son 55 descripciones cortas, de dos o tres líneas, y
   cada una acababa con su última línea centrada — la columna quedaba
   con el borde izquierdo aserrado y las frases bailando. Aquí manda la
   lectura en lista: todo alineado por la izquierda. */
.plato__desc {
  color: var(--texto-suave); font-size: var(--t-apoyo); margin: 0;
  /* ⚠️ 1,55 y no el 1,65 del cuerpo: en dos o tres líneas dentro de una
     columna estrecha, el interlineado del texto corrido abre la fila de
     más y el plato deja de leerse como una unidad. */
  line-height: 1.55;
  text-align: left;
}
/* ⚠️ 100 × 112, EN RETRATO, no cuadrada. Es la medida de la carta de
   Frog's, y no es capricho: el rectángulo alto enseña más plato que el
   cuadrado con el mismo ancho de columna. */
.plato__foto {
  width: 100px; height: 112px; object-fit: cover; margin: 0;
  background: var(--fondo-hondo);
}
/* ── El hueco de los platos sin foto ────────────────────────────────
   ⭐ NADIE SIN CARA. Ocupa exactamente lo que ocuparía la foto, para que
   los nombres sigan arrancando todos en la misma vertical, y lleva el
   icono de su apartado en trazo fino sobre el papel hondo.
   ⚠️ Cuando el plato reciba su fotografía esto desaparece solo: lo decide
   la vista, no el CSS. */
.plato__silueta {
  grid-row: 1 / span 2;
  width: 100px; height: 112px;
  display: flex; align-items: center; justify-content: center;
  background: var(--fondo-hondo);
}
.plato__silueta svg { width: 42px; height: 42px; opacity: .45; }
@media (min-width: 900px) {
  .plato { grid-template-columns: 120px minmax(0, 1fr); gap: .35em 18px; padding: 22px 0; }
  .plato__foto,
  .plato__silueta { width: 120px; height: 134px; }
  .plato__silueta svg { width: 50px; height: 50px; }
}
.plato--destacado .plato__nombre { color: var(--acento-tinta); }

.aviso-vacio { text-align: center; color: var(--texto-suave); padding: 64px var(--aire); }

/* Cierre de página: la llamada a reservar, en la terracota del PSD.
   ⚠️ Con texto BLANCO: 5,20:1. La tinta oscura que llevaba cuando el
   acento era dorado se queda en 1,8:1 sobre este color. */
.cierre-carta {
  background: var(--acento); color: #fff;
  text-align: center; padding: clamp(64px, 9vw, 120px) var(--aire);
}
/* ⚠️ El titular llevaba `--t-seccion` pero NINGÚN ancho, así que en una
   pantalla grande se estiraba a 1.236px en una sola línea, pegado a los
   bordes, mientras el párrafo de debajo iba limitado a 48ch: el bloque
   quedaba descompensado. Medido el 2026-08-18 en 1280px. */
.cierre-carta h2 { font-size: var(--t-seccion); max-width: 26ch; margin-inline: auto; }
.cierre-carta p { margin: 1em auto 2em; color: rgb(255 255 255 / .92); max-width: 48ch; }

/* =====================================================================
   PRENSA
   ===================================================================== */
/* ⚠️ SIN CAJA, como las citas del bloque de reseñas. Eran diez recuadros
   iguales con filo y fondo levantado: una rejilla de tarjetas idénticas es
   lo que hace que una página se lea como plantilla. Lo que ordena aquí es
   un filete arriba y el aire. */
.prensa { list-style: none; margin: 0; padding: 0; display: grid;
          gap: clamp(30px, 3.6vw, 52px); }
.prensa__nota {
  background: none;
  padding: clamp(20px, 2.2vw, 28px) 0 0;
  border: 0; border-top: 2px solid var(--acento);
  transition: transform .35s var(--curva);
}
@media (hover: hover) and (pointer: fine) {
  .prensa__nota:hover { transform: translateY(-2px); }
}
.prensa__medio {
  font-family: var(--titulo); font-size: .7rem; font-weight: 600;
  letter-spacing: .2em; text-transform: uppercase; color: var(--acento-tinta);
  margin: 0 0 .7em;
}
/* El titular del medio es la cita: a tamaño de lectura, no de pie de
   foto. */
.prensa__titulo { font-size: var(--t-tarjeta); margin-bottom: .5em; }
.prensa__texto { color: var(--texto-suave); font-size: var(--t-cuerpo); }
.prensa__enlace {
  font-family: var(--titulo); font-size: .74rem; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--acento-tinta); text-decoration: none;
  /* Zona de toque de 44px: el enlace es la acción de la tarjeta, no una
     palabra suelta dentro de un párrafo. */
  display: inline-flex; align-items: center; min-height: 44px;
  box-shadow: inset 0 -1px 0 currentColor;
}
.prensa__enlace:hover { color: var(--acento-tinta); }

/* =====================================================================
   KIDS CLUB
   ===================================================================== */
/* ⚠️ El bloque que había aquí (tres columnas de texto plano, con la foto
   suelta encima y el título en versalitas) se retiró el 2026-08-17 al
   rehacer la página. Lo vigente está al final del archivo, en la sección
   «FREDDIE'S KIDS CLUB». */

/* =====================================================================
   RESERVACIONES
   ===================================================================== */
.reservas { display: grid; gap: 48px; padding-bottom: var(--hueco-bloque); }
.reservas h2 {
  /* ⚠️ Estos h2 no son titulares: son ETIQUETAS de dato —«Horario»,
     «Dirección»— y ya venían con el traje de rótulo (versalitas, mucho
     espaciado, terracota). Lo que no cuadraba era el cuerpo: .82rem
     (13,1px) cuando el rótulo de la casa es .7rem. Ahora usan la misma
     escala que todos los rótulos del sitio. */
  font-size: var(--t-rotulo); font-family: var(--titulo); letter-spacing: .2em;
  text-transform: uppercase; color: var(--acento-tinta);
  margin-bottom: .7em;
}
.reservas h2:not(:first-child) { margin-top: 2em; }
.reservas address { font-style: normal; }
.reservas__contacto { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 1.6em; }
.reservas__widget { border: 1px solid var(--borde); padding: clamp(22px, 3vw, 38px); }

/* =====================================================================
   BLOG
   ===================================================================== */
/* ── EL ÍNDICE DEL BLOG, EN TARJETAS ───────────────────────────────
   Carlos, 2026-08-17: «esto tiene que ser en card». Eran foto, fecha,
   titular y extracto sueltos y centrados sobre el papel: sin caja que los
   contuviera, tres entradas seguidas se leían como un solo bloque de
   texto con fotos intercaladas, y el titular no se distinguía del
   extracto.

   Ahora es la MISMA tarjeta que el resto del sitio: caja de papel
   levantado, filo de 1px y esquinas rectas.

   ⭐ 2026-08-17 · Carlos: «quítale el extracto y colócale botón, centra
   los títulos». Sin el extracto —que era el arranque del post cortado a
   mitad de frase— la tarjeta se queda en fecha, titular y botón, y así
   el centrado sí funciona: lo que había desaconsejado el centrado era
   tener cuatro párrafos de largo distinto uno debajo de otro. */
.blog__rejilla {
  list-style: none; margin: 0 auto; display: grid;
  gap: clamp(18px, 2vw, 28px);
  /* ⚠️ La rejilla no vivía dentro de `.contenedor` y con las tarjetas
     puestas se veía: llegaban a tocar el filo de la pantalla. */
  /* ⚠️ Con padding-top 0 las tarjetas nacían pegadas a la banda del
     banner, sin un respiro entre el marrón y la primera foto. */
  max-width: var(--ancho);
  padding: clamp(36px, 5vw, 72px) var(--aire) var(--hueco-bloque);
}
.blog__rejilla .tarjeta {
  display: flex; flex-direction: column;
  background: var(--fondo-alto);
  border: 1px solid var(--borde);
  overflow: hidden;
  transition: border-color .3s var(--curva), transform .3s var(--curva);
}
@media (hover: hover) and (pointer: fine) {
  .blog__rejilla .tarjeta:hover { border-color: var(--acento); transform: translateY(-3px); }
}
.blog__rejilla a { text-decoration: none; display: block; }
.blog__rejilla img {
  width: 100%; aspect-ratio: 3 / 2; object-fit: cover; display: block;
  transition: transform .5s var(--curva);
}
@media (hover: hover) and (pointer: fine) {
  .blog__rejilla .tarjeta:hover img { transform: scale(1.03); }
}
.blog__rejilla .tarjeta > a:first-child { overflow: hidden; }

.tarjeta__cuerpo {
  padding: clamp(22px, 2.4vw, 32px);
  display: flex; flex-direction: column; gap: .55em;
  flex: 1 1 auto;
  text-align: center; align-items: center;
}
.blog__rejilla .tarjeta__meta {
  margin: 0; font-family: var(--titulo);
  font-size: var(--t-rotulo); font-weight: 600; letter-spacing: .18em;
  text-transform: uppercase; color: var(--acento-tinta);
}
/* ⚠️ `.tarjeta__titulo` es SÓLO del blog: la llevan la rejilla de
   `/blog/` y los relacionados del pie de un post, y nadie más. Por eso
   el tamaño puede ir en la clase y vale para los dos sitios; antes lo
   ponía `h3 { font-size: var(--t-tarjeta) }`, la escala por defecto de
   los encabezados, y de ahí venía el descuadre. */
.blog__rejilla h2, .blog__rejilla h3, .tarjeta__titulo {
  font-size: var(--t-blog); margin: 0; line-height: 1.3;
  text-wrap: balance;   /* centrado, las líneas se reparten parejas */
}
/* El botón cierra la tarjeta y se apoya abajo: con titulares de una y de
   tres líneas, los botones de la fila quedan a la misma altura. */
.tarjeta__boton {
  /* ⚠️ Aquí había un `padding-top: 12px` que pisaba los 15 de `.boton`:
     con el botón vacío no se veía, pero desde que lleva relleno naranja
     (2026-08-21) dejaba 12 de aire arriba y 15 abajo, y el texto salía
     descentrado dentro de su propia caja. El aire de separación lo pone
     `margin-top: auto`, que es lo suyo; el de dentro, `.boton`. */
  margin-top: auto;
  align-self: center;
  /* ⛔ Tenía cuerpo propio (.78rem) y era el ÚNICO botón del sitio con
     una letra distinta. Hereda el de `.boton` y se acabó. */
  letter-spacing: .16em;
}
.blog__rejilla .tarjeta__extracto {
  margin: 0; color: var(--texto-suave); font-size: var(--t-apoyo);
}
.blog__rejilla a:hover h2, .blog__rejilla a:hover h3 { color: var(--acento-tinta); }

@media (min-width: 720px)  { .blog__rejilla { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1040px) { .blog__rejilla { grid-template-columns: repeat(3, 1fr); } }

/* ── LA ENTRADA DEL BLOG ────────────────────────────────────────────
   Carlos, 2026-08-17: «las fotos van primero a un 80% de ocupación de
   pantalla, el título en dos líneas, centrado y con letras más
   pequeñas». Abre como abre el resto del sitio: media primero, texto
   después. */
.post__portada {
  margin: 0 0 clamp(28px, 4vw, 56px);
  width: 100%; height: 80svh;
  background: var(--marron);   /* color de espera mientras carga */
}
.post__portada img {
  width: 100%; height: 100%; object-fit: cover; display: block;
}

.post { max-width: 74ch; margin: 0 auto; padding: 0 var(--aire) var(--hueco-bloque); }

/* La cabecera de la entrada: ancho propio, MAYOR que el de lectura.
   ⚠️ Dentro del artículo el titular heredaba los 74ch de la columna de
   texto, y con eso uno de 87 caracteres no cabía en dos líneas por mucho
   que se le topara la medida. Aquí tiene 980px y baja de tamaño —lo que
   pidió Carlos: «letras más pequeñas»—, y con las dos cosas los
   titulares del blog caen en DOS líneas. Los kilométricos (uno de los
   562 tiene 129 caracteres) siguen cayendo en tres: para meterlos en dos
   habría que recortarles el titular, y el titular es del cliente. */
.post__cabeza {
  max-width: 980px; margin: 0 auto;
  padding: 0 var(--aire); text-align: center;
}
.post__titulo {
  font-size: clamp(1.3rem, 2.2vw, 1.72rem);
  line-height: 1.16; margin: 0 0 .5em;
  text-wrap: balance;
}
.post__cabeza .post__meta { margin-bottom: clamp(26px, 3.4vw, 44px); }
.post__cuerpo { font-size: var(--t-cuerpo); }
.post__cuerpo img { margin: 2em 0; width: 100%; }
.post__cuerpo h2, .post__cuerpo h3 { margin-top: 1.8em; margin-bottom: .5em; }
.post__cuerpo a { color: var(--acento-tinta); }
.post--legal .post__cuerpo { font-size: var(--t-apoyo); color: var(--texto-suave); }

.paginacion {
  display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;
  padding: 0 var(--aire) var(--hueco-bloque);
}
.paginacion a, .paginacion span {
  min-width: 46px; min-height: 46px; display: grid; place-items: center;
  border: 1px solid var(--borde); text-decoration: none; font-size: .86rem;
}
.paginacion a:hover { border-color: var(--acento); color: var(--acento-tinta); }
.paginacion .actual { background: var(--acento); border-color: var(--acento); color: #fff; }

/* =====================================================================
   LINKTREE  (página de paso desde redes, sin cabecera ni pie)
   ===================================================================== */
.linktree {
  max-width: 440px; margin: 0 auto; padding: 56px var(--aire); text-align: center;
}
.linktree__logo { margin: 0 auto; width: 170px; }
.linktree__lema {
  font-family: var(--titulo); font-size: var(--t-rotulo); font-weight: 600;
  letter-spacing: .22em; text-transform: uppercase; color: var(--acento-tinta);
  margin-top: 1.4em;
}
.linktree__enlaces { list-style: none; margin: 34px 0; padding: 0; display: grid; gap: 10px; }
.linktree__enlaces .boton { width: 100%; }
.linktree__pie { color: var(--texto-suave); font-size: .86rem; }

/* ── Pie ───────────────────────────────────────────────────────────── */
.pie {
  background: var(--fondo-hondo); color: var(--texto-suave);
  border-top: 1px solid var(--borde);
  padding: clamp(56px, 7vw, 88px) var(--aire) 32px;
  font-size: var(--t-apoyo);
}
.pie__interior { max-width: var(--ancho); margin: 0 auto; display: grid; gap: 38px; }
.pie__titulo {
  font-family: var(--titulo); font-size: var(--t-rotulo); font-weight: 600;
  letter-spacing: .2em; text-transform: uppercase; color: var(--texto); margin: 0 0 1em;
}
.pie ul { list-style: none; margin: 0; padding: 0; }
.pie a { color: var(--texto-suave); text-decoration: none; display: block; padding: 8px 0; }
.pie a:hover { color: var(--acento-tinta); }
.pie__marca img { width: 156px; margin-bottom: 16px; }
.pie__lema {
  font-family: var(--titulo); font-size: var(--t-rotulo); font-weight: 600;
  letter-spacing: .2em; text-transform: uppercase; color: var(--acento-tinta);
}
.pie__direccion { font-style: normal; margin-bottom: 1em; }
.pie__dato { display: block; padding: 4px 0; }
.pie__redes { display: flex; gap: 18px; margin-top: .6em; flex-wrap: wrap; }
.pie__redes a { padding: 10px 0; font-size: .86rem; }
/* =====================================================================
   LA PLECA DE GRUPO ANDERSON'S
   =====================================================================
   Las 16 marcas del grupo en un marco, con el logo del grupo partiendo
   el filo de arriba. Traída de Señor Frog's el 2026-08-12.

   ⚠️ La diferencia con Frog's es el color. Allí la pleca se apoya en una
   banda roja y los logos se invierten a blanco. El pie de Fred's es
   arena claro, así que aquí se tiñen de tinta con `brightness(0)` y se
   apagan un poco: 16 logos negros a plena carga pesan más que el propio
   pie y le roban la atención al contenido.

   ⚠️ El logo del grupo lleva el fondo del pie a los lados para CORTAR la
   línea del marco. Si se cambia el fondo del pie, hay que cambiarlo
   también aquí o aparecerá un trozo de borde cruzándolo.
   ===================================================================== */
/* ⚠️ Sin margen superior desde que el pie se quedó sin las cuatro
   columnas (2026-08-12): la pleca es ahora lo primero del pie y el
   `padding` del propio `.pie` ya le da todo el aire que necesita. */
.pleca { margin-top: 0; }
.pleca__marco {
  position: relative;
  max-width: var(--ancho); margin: 0 auto;
  border: 1px solid var(--borde);
  padding: clamp(40px, 5vw, 54px) clamp(18px, 3vw, 34px) clamp(24px, 3vw, 34px);
}
.pleca__grupo {
  position: absolute; top: 0; left: 50%;
  transform: translate(-50%, -50%);
  background: var(--fondo-hondo);      /* el mismo papel del pie: tapa la línea */
  padding: 2px 22px; line-height: 0;
}
.pleca__grupo img {
  height: clamp(38px, 5vw, 52px); width: auto; display: block;
  filter: brightness(0); opacity: .72;
}

.pleca__marcas {
  display: flex; flex-wrap: wrap;
  align-items: center; justify-content: center;
  gap: 18px 26px;
}
.pleca__marcas a {
  display: inline-flex; align-items: center; justify-content: center;
  /* Zona de toque: los logos miden 26px de alto y solos se quedarían muy
     por debajo del mínimo de 44px para el dedo. */
  min-height: 44px; padding: 0 2px;
  /* ⛔ `flex: 0 0 auto` es OBLIGATORIO. Sin él, en la fila sin envolver
     de escritorio los enlaces se encogen —flex-shrink vale 1 por
     defecto— y como los SVG del grupo no traen ancho ni alto propios,
     sólo `viewBox`, se quedan en CERO y la pleca sale vacía. Sólo
     sobrevivía el PNG del Nassau Port, que sí tiene medidas. En Frog's
     esto se resolvió con `display: contents`, pero eso aquí se llevaría
     por delante la zona de toque. */
  flex: 0 0 auto;
}
.pleca__marcas img {
  /* Alto fijo y ancho tope: los SVG no traen medidas propias, así que sin
     un `height` concreto el navegador les da su tamaño por defecto. */
  /* ⚠️ ANCHO FIJO, no `auto` (2026-09-15). Los 16 logos cargan en
     diferido y, mientras no llegan, miden 0 de ancho: cabían todos en
     una fila y, al cargar, la pleca pasaba de 106 a 292 px y empujaba el
     pie entero mientras se bajaba en el teléfono. Con la caja reservada
     el logo se encaja dentro (`contain`) y no se mueve nada. */
  height: 26px; width: 62px; max-width: 62px;
  object-fit: contain;
  filter: brightness(0); opacity: .42;
  transition: opacity .22s var(--curva-color), transform .22s var(--curva);
}
.pleca__marcas a:focus-visible img { opacity: .92; transform: translateY(-2px); }
@media (hover: hover) and (pointer: fine) {
  .pleca__marcas a:hover img { opacity: .92; transform: translateY(-2px); }
}

@media (min-width: 1100px) {
  /* En pantalla ancha caben las 16 en una sola fila, que es como se lee
     de un vistazo que son una familia y no una lista. */
  .pleca__marcas { flex-wrap: nowrap; justify-content: space-between; gap: 10px; }
  .pleca__marcas img { height: 30px; width: 54px; max-width: 54px; }
}

.pie__legal {
  text-align: center; margin: 40px 0 0; font-size: .8rem; color: var(--texto-suave);
  padding-top: 24px; border-top: 1px solid var(--borde);
  display: flex; flex-wrap: wrap; gap: 4px 20px;
  align-items: center; justify-content: center;
  /* ⚠️ Hay un `p { max-width: var(--medida) }` global —la medida de
     lectura— y este párrafo también lo heredaba: el copyright salía
     dentro de una caja de 490 px pegada a la izquierda, con la línea de
     arriba cortada a un tercio del ancho. Aquí no se lee un texto
     corrido, se cierra el pie. */
  max-width: none;
}
/* Zona de toque de 44px para el único enlace que queda en el pie. El
   copyright toma la misma altura para que los dos queden a nivel. */
.pie__legal-texto,
.pie__legal-enlace {
  display: inline-flex; align-items: center; min-height: 44px;
}
.pie__legal-enlace {
  color: var(--texto-suave); text-decoration: none;
  transition: color .22s var(--curva-color);
}
.pie__legal-enlace:hover { color: var(--acento-tinta); }

/* =====================================================================
   MOVIMIENTO
   =====================================================================
   Una sola idea: lo que entra en pantalla aparece. Sin bucles infinitos,
   sin parallax, sin secuestrar el scroll. Lo mueve un
   IntersectionObserver desde sitio.js, nunca un escuchador de scroll.
   ===================================================================== */
/* ⚠️ Sólo se esconde si hay JavaScript que pueda devolverlo (la clase
   `js` la pone el head). Sin JavaScript el sitio se lee entero. */
.js .revelar {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity .8s var(--curva), transform .8s var(--curva);
}
.js .revelar.visible { opacity: 1; transform: none; }

/* ⚠️ EL MENÚ COMPLETO ENTRA A PARTIR DE 1000px, no de 900.
   Al entrar Cancún en la barra el nav creció y a 900px se metía debajo
   del logo. Medido forzando el nav visible a cada ancho: a 940px sobran
   18px por cada lado, y a 900px FALTAN 14 en inglés y 20 en español —el
   español es el que manda, que sus etiquetas son más largas.
   Por debajo de 1000 manda la hamburguesa, que lleva los mismos enlaces.
   Si se añade otra entrada al menú, se vuelve a medir. */
@media (min-width: 1000px) {
  .cabecera__nav { display: block; }
  .cabecera__hamburguesa { display: none; }
}

/* ── Escritorio ────────────────────────────────────────────────────── */
@media (min-width: 900px) {
  .cabecera__reserva-largo { display: inline; }
  .cabecera__reserva-corto { display: none; }

  /* ⛔ El hero NO se parte en escritorio. Antes había aquí un
     `grid-template-columns` que lo dejaba en 50/50 con el texto a un lado
     y el vídeo al otro. En Grupo Anderson's la portada abre al 100% y ese
     reparto no se usa. La regla completa está en el bloque PORTADA. */

  /* La bienvenida se reparte: el titular a la izquierda y la entrada a
     la derecha.

     La columna del titular pesa más que la del texto porque en
     mayúsculas y a dos líneas necesita sitio: con el reparto anterior
     (1.05fr) la línea más larga pedía 655 px donde sólo había 576, y
     caía en tres líneas. */
  /* Centrado, no `start`: las dos columnas miden distinto —el titular son
     dos líneas grandes y el texto cuatro pequeñas— y ancladas arriba el
     titular quedaba colgando sobre un hueco vacío. Al retirarse los
     botones el desnivel se notaba más. 2026-08-11 */
  .bienvenida__interior {
    display: grid; grid-template-columns: 1.25fr 1fr;
    gap: clamp(32px, 5vw, 72px); align-items: center;
  }
  /* ⛔ Aquí había un `margin-top: .35em` en la entrada, que servía para
     casar su primera línea con la del titular cuando se alineaban por
     arriba. Con el centrado sobra, y dejarlo descuadraba el nivelado. */

  /* Las tarjetas dejan de deslizarse y se reparten. La de alimentos
     ocupa el doble: es la que busca la gente. */
  .cartas-home__lista, .indice-cartas {
    grid-auto-flow: row; grid-auto-columns: auto;
    grid-template-columns: 1.4fr 1fr 1fr;
    overflow: visible; padding-inline: var(--aire); gap: 18px;
  }
  .cartas-home__item img { aspect-ratio: 4 / 5; }
  .cartas-home__item:first-child img { aspect-ratio: 3 / 4.4; }

  /* ⚠️ SIN HUECO VERTICAL: desde el 2026-08-24 lo que separa un plato del
     siguiente es la línea, no el aire. Con los 34px de antes la línea
     quedaba flotando a media distancia de los dos y no se sabía de cuál
     era. El hueco entre las dos COLUMNAS se queda. */
  .carta__platos { grid-template-columns: 1fr 1fr; gap: 0 60px; }
  /* ⛔ Aquí estaba también `.blog-home__lista` a tres columnas, de cuando
     eran tres tarjetas iguales. Al rehacer el bloque el 2026-08-12 esta
     regla —que viene DESPUÉS en el archivo— pisaba el nuevo reparto de
     «una manda y dos acompañan» y las tres volvían a salir en fila.
     El del blog completo (`.blog__rejilla`) sí sigue a tres. */
  .blog__rejilla { grid-template-columns: repeat(3, 1fr); }
  .kids__zonas { grid-template-columns: repeat(3, 1fr); }
  .prensa { grid-template-columns: 1fr 1fr; gap: 18px; }
  .reservas { grid-template-columns: 1fr 1fr; gap: 64px; }
  .pie__interior { grid-template-columns: 1.4fr 1fr 1fr 1fr; }
  /* ⛔ Aquí había un `grid-template-columns: 1fr 1fr` para la propuesta,
     de cuando la sección era sólo titular y párrafo. Pisaba —por venir
     después en el archivo— al reparto que necesita ahora que lleva las
     tres fotos. El reparto vive en el bloque de LA PROPUESTA CULINARIA,
     junto al resto de sus reglas. */
  /* ⛔ Y aquí había un `.propuesta p { margin-top: 0 }`, de cuando el
     titular iba en una columna y el párrafo en la otra: entonces no
     hacía falta separarlos. Ahora viven en la misma columna y ese cero
     dejaba el texto pegado al titular. */
  /* ⛔ Aquí había un `.grupos-home__interior` a `1fr 1fr`, del montaje que
     tenía el titular en una columna y el párrafo en la otra. Al rehacer
     la sección el 2026-08-13 esta regla —que viene DESPUÉS en el
     archivo— pisaba el reparto nuevo de foto + texto. Es la segunda vez
     que pasa lo mismo en este archivo, después del blog: cuando se
     rehace un componente hay que buscar su nombre en TODO el CSS, no
     sólo donde vive su bloque. */
}

@media (min-width: 1200px) {
  .carta__platos { grid-template-columns: repeat(2, 1fr); gap: 0 88px; }
}

/* Quien pide menos movimiento, no lo recibe.

   ⚠️ Esto es lo ÚNICO del ordenador del visitante que la web sigue
   obedeciendo, y a propósito: no es un ajuste de gusto como el modo
   oscuro, es un ajuste médico. Quien lo activa suele hacerlo porque el
   movimiento en pantalla le provoca mareo o migraña. No cambia ni un
   color, ni una letra, ni una medida: la web se ve exactamente igual,
   sólo que las cosas aparecen sin deslizarse. La identidad no se toca.

   ⛔ 2026-08-13 · ESTE BLOQUE MATABA DEMASIADO. Llevaba un
   `transition-duration: .01ms !important` sobre `*`, que apaga TODAS las
   transiciones, no sólo las que mueven: también el cambio de color de un
   botón al pasar por encima, el del enlace al recibir el foco y el del
   borde de una tarjeta. Eso NO es movimiento, es feedback — y sin él la
   interfaz deja de responder para quien más ayuda necesita. El propio
   comentario de aquí arriba prometía «no cambia ni un color» y el código
   hacía justo lo contrario.

   Menos movimiento significa MENOS Y MÁS SUAVE, no CERO. Ahora la
   transición se limita a las propiedades que NO desplazan —color,
   opacidad, borde, sombra—, así que nada se mueve pero la web sigue
   contestando cuando la tocas.

   ⛔ Y NO se pone `transform: none` sobre `*`. Parece la solución
   evidente y rompe el sitio: aquí `transform` no sólo anima, también
   COLOCA. El logo del grupo va centrado con `translate(-50%,-50%)`, la
   barra de avance de la galería se dibuja con `scaleX()`, y los platos
   de los pases se dimensionan con `scale(.9)`. Apagarlo a lo bruto
   descoloca las tres cosas. Los `transform` que sí animan los neutraliza
   cada escena en su propio bloque de `prefers-reduced-motion` —hay siete
   repartidos por este archivo—, que es donde se sabe cuál mueve y cuál
   coloca. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    /* Se apaga el desplazamiento, no la respuesta. */
    transition-property: opacity, color, background-color, border-color,
                         box-shadow, fill, stroke, filter !important;
    transition-duration: .18s !important;
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
  }
  .js .revelar { opacity: 1; transform: none; }
}

/* =====================================================================
   BOTÓN FLOTANTE DE GRUPOS
   =====================================================================
   Fijo abajo a la derecha, en todas las páginas menos las de grupos.

   ⚠️ El hueco de abajo lleva `env(safe-area-inset-bottom)`: en un iPhone
   sin botón físico, la barra de gestos se come los últimos 34 px y el
   botón quedaría pisado por ella.

   ⚠️ El `z-index` es 40, por DEBAJO de la cabecera (50) y del menú
   desplegado: si se pone por encima, tapa el menú de móvil cuando está
   abierto.
   ===================================================================== */
.flotante-grupos {
  position: fixed;
  right: clamp(16px, 2.5vw, 28px);
  bottom: calc(clamp(16px, 2.5vw, 28px) + env(safe-area-inset-bottom, 0px));
  z-index: 40;

  display: inline-flex; align-items: center; gap: 10px;
  min-height: 52px;                /* zona táctil holgada */
  padding: 0 20px;
  /* El turquesa de marca con letra e icono en blanco, a petición de
     Carlos (2026-08-11). Va en otro color que «Reservar mesa» a
     propósito: dos botones dorados en pantalla compiten entre sí en vez
     de turnarse, y reservar debe seguir siendo la acción principal.
     ⭐ 2026-08-21: Carlos zanjó la duda —«igual al de Book a table»—, así
     que este también se va al naranja. La distinción entre las dos
     llamadas no la lleva el color: la lleva el sitio donde vive cada
     una. Si algún día vuelven a competir, el que se mueve es éste.

     ⚠️ Aquel turquesa daba 3,5:1 con el blanco encima, por debajo del
     mínimo de 4,5. El naranja de atardecer llega a 4,52 y su borde hondo
     es lo que lo separa del papel: los dos números se miden, no se
     estiman. */
  background: var(--boton);
  color: var(--boton-tinta);
  border: 1px solid var(--boton-borde);
  font-family: var(--titulo);
  font-size: var(--t-boton); font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase;
  text-decoration: none;
  box-shadow: 0 6px 20px rgba(26, 34, 41, .28);
  transition: background .25s var(--curva), transform .25s var(--curva),
              box-shadow .25s var(--curva);
}
.flotante-grupos:hover {
  background: var(--boton-honda);  /* el mismo naranja, un punto más hondo */
  border-color: var(--boton-honda);
  color: #fff;
  transform: translateY(-2px);
  box-shadow: 0 10px 26px rgba(26, 34, 41, .34);
}
.flotante-grupos:active { transform: translateY(0); }
.flotante-grupos__icono { width: 22px; height: 22px; flex: 0 0 auto; }

/* En móvil se queda en círculo: la palabra ocuparía media pantalla y el
   botón taparía el contenido. El nombre sigue en el `aria-label`. */
@media (max-width: 599px) {
  .flotante-grupos {
    width: 56px; height: 56px; min-height: 0; padding: 0;
    border-radius: 50%;
    justify-content: center;
  }
  .flotante-grupos__texto { display: none; }
  .flotante-grupos__icono { width: 24px; height: 24px; }
}

@media (prefers-reduced-motion: reduce) {
  .flotante-grupos, .flotante-grupos:hover { transition: none; transform: none; }
}

/* Quien pide menos movimiento ve las tres fotos quietas en su sitio. */
@media (prefers-reduced-motion: reduce) {
  .cocina__foto { transform: none !important; }
  .cocina__foto img, .cocina__foto:hover img { transition: none; transform: none; }
}

/* =====================================================================
   LA PORTADA DE LOS PASES — papel claro y el título a mano (2026-09-11)
   =====================================================================
   Carlos: «a esto hay que crearle una portada con la textura pero claro
   y con este texto, pero el título en la letra esa rara y lo otro
   normal». El texto es el de la propuesta culinaria, que se apagó esa
   misma mañana; sale de sus mismas claves, no copiado.

   ⭐ TODO EN VARIABLES `--pp-*`: son las que mueve el afinador en vivo
   (`?afinar=portada`). Los valores de aquí abajo son el punto de
   partida; los que elija Carlos con los deslizadores se pegan encima.

   ⚠️ LA CALIGRÁFICA TIENE DOS REGLAS PROPIAS, ya pagadas en `.firma`:
     ⛔ nunca en versales —no tiene mayúsculas de verdad, y `uppercase`
        la convierte en una mezcla ilegible—;
     ⚠️ `padding-inline` obligatorio: sus trazos se salen de la caja del
        texto y contra el borde de la columna se recortan.

   ⚠️ Y NO ES TEXTO PARA LEER, es una firma. Por eso el párrafo va en la
   Jost de siempre: es lo que Carlos llamó «lo otro normal».           */
/* ⭐ LOS NÚMEROS LOS ELIGIÓ CARLOS CON EL AFINADOR (2026-09-11), a
   1.440 px de ancho: firma 61, párrafo 19, hueco 56.

   ⚠️ Llegan en PÍXELES FIJOS y aquí no pueden quedarse así, o el título
   mediría lo mismo en un teléfono que en un monitor. Cada uno se ha
   convertido en una recta que pasa por DOS puntos: lo que la portada ya
   medía a 390 px —que Carlos no afinó y por tanto no se toca— y lo que
   él eligió a 1.440. Entre medias interpola sola, y los `clamp` la
   sujetan por los dos extremos. Comprobado: 390 → 41,6 / 16,5 / 18 y
   1.440 → 61 / 19 / 56, al decimal. */
.portada-pases {
  --pp-titulo:  clamp(2.6rem, calc(2.1496rem + 1.848vw), 3.8125rem);
  --pp-color:   var(--rojo-spice);             /* su tinta */
  /* ⚠️ `--t-cuerpo` (16,5) y NO `--t-sub` (17). El primer intento usó la
     entrada del hero y el auditor de escalas lo cazó al vuelo: este
     párrafo no es una entrada, es texto de sección, el mismo papel que
     el de Las Villas o el de Grupos. Dos cuerpos para un mismo papel es
     justo lo que esa auditoría existe para impedir. */
  /* ⭐ 19 px a 1.440, no los 16,5 del texto corrido: lo eligió Carlos con
     el afinador. Es una decisión de diseño, no un descuido — el párrafo
     de una portada pesa más que un párrafo de sección—, así que lo que se
     ajusta es la REGLA: se le declara papel propio en el auditor de
     escalas, igual que a la firma. En el teléfono sigue en 16,5, que es
     lo que había y él no afinó. */
  --pp-texto:   clamp(1.03125rem, calc(.9732rem + .238vw), 1.1875rem);
  --pp-hueco:   clamp(18px, calc(.2429rem + 3.619vw), 56px);   /* firma → párrafo */
  --pp-medida:  52ch;                          /* la medida del párrafo */
  --pp-aire:    clamp(72px, 11vh, 150px);      /* el alto, por arriba y abajo */
  --pp-tinta:   var(--tinta);                  /* el color del párrafo */

  position: relative;
  padding-block: var(--pp-aire);
}
.portada-pases__interior {
  max-width: var(--ancho); margin: 0 auto; padding-inline: var(--aire);
  text-align: center;
}
.portada-pases__titulo {
  font-family: var(--caligrafia);
  font-weight: 400;
  font-size: var(--pp-titulo);
  line-height: 1.06;
  color: var(--pp-color);
  text-transform: none;          /* ⛔ jamás en versales */
  letter-spacing: 0;
  padding-inline: .12em;         /* ⚠️ el aire que piden sus trazos */
  margin: 0 0 var(--pp-hueco);
  /* ⭐ DESGASTADO COMO EL CARTEL — Carlos, 2026-09-14: «que tenga un
     poquito de desgaste como el master». En el PSD «Sea & Spice» va en
     `multiply` con motas y rayones blancos de sello gastado. Aquí: el mismo
     `multiply` (el grano del papel asoma dentro de la letra) y una máscara
     de motas en baldosa de 512 px (`desgaste-titulo.png`, generada, sin
     costura). Sigue siendo TEXTO: se lee, se traduce y cuenta para SEO.
     Para quitarlo, borrar estas líneas.
     ⚠️ Una máscara recorta TODO lo que sale de la caja del elemento, y las
     colas de la Mr Dafoe (y, ff, g) cuelgan muy por debajo de su renglón:
     sin este aire se cortaban en seco. Se da caja por arriba y por abajo y
     se devuelve con márgenes negativos, así el título no se mueve. */
  padding-block: .15em .4em;
  margin-top: -.15em;
  margin-bottom: calc(var(--pp-hueco) - .4em);
  mix-blend-mode: multiply;
  -webkit-mask-image: url('../img/textura/desgaste-titulo.png');
          mask-image: url('../img/textura/desgaste-titulo.png');
  -webkit-mask-size: 256px 256px;
          mask-size: 256px 256px;
}
.portada-pases__texto {
  font-size: var(--pp-texto);
  color: var(--pp-tinta);
  max-width: var(--pp-medida);
  margin-inline: auto;
  margin-block: 0;
}

/* ── 50/50: EL TEXTO A LA IZQUIERDA, LA ILUSTRACIÓN A LA DERECHA ──────
   Carlos, 2026-09-14. La ilustración es del estilo del cartel Sea &
   Spice —óleo empastado recortado sobre el papel— con la langosta de la
   carta. Va en PNG/WebP con transparencia: el papel es el de la sección,
   no uno pintado dentro de la imagen, o se vería la costura.

   En el teléfono se apila: texto arriba, ilustración debajo y más
   pequeña. El texto sigue centrado en los dos. */
/* ⭐ EL FONDO ES EL PAPEL DEL CARTEL, ENTERO — Carlos, 2026-09-14: «usa esa
   imagen de fondo para esa sección, la actual se ve como gigante».
   La de `.papel` es una baldosa de 640 px repetida y teñida: a pantalla
   completa el grano salía grueso. Esta es la hoja de papel del propio
   cartel Sea & Spice (1920 px, grano fino), puesta UNA vez a `cover`, sin
   repetir y sin `multiply` — ya trae su color.
   El original está en `_interno/_material-cliente/nueva-linea/`. */
.portada-pases.papel {
  background-color: #efece8;
  background-image: image-set(url('../img/textura/papel-seaspice-1280.webp') 1x, url('../img/textura/papel-seaspice.webp') 2x);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-blend-mode: normal;
}
@media (min-width: 900px) {
  .portada-pases.papel { background-image: url('../img/textura/papel-seaspice.webp'); }
}
/* Carlos, 2026-09-14: «bájale el tamaño a los platillos un 20 %, en grupo, al
   plato y bebida». Era min(78vw, 360px) en el teléfono y el 100 % de la
   columna en escritorio (tope 68svh / 620px): todo pasa al 80 %.
   Y luego «hazlo un 10 % más grande»: del 80 % al 88 %. */
.portada-pases__ilustracion { margin: var(--pp-hueco) auto 0; max-width: min(68.64vw, 317px); }
.portada-pases__ilustracion img {
  display: block; width: 100%; height: auto;
  /* la misma sombra corta que el sello: la apoya en el papel sin despegarla */
  filter: drop-shadow(0 14px 22px rgb(30 18 12 / .16));
}
@media (min-width: 900px) {
  .portada-pases__interior:has(.portada-pases__ilustracion) {
    display: grid; grid-template-columns: 1fr 1fr;
    align-items: center; gap: clamp(24px, 4vw, 72px);
    width: 100%;
  }
  /* Carlos, 2026-09-14: «necesito que se justifique a la izquierda».
     Sólo en escritorio: en el teléfono el texto va centrado (ley de la
     casa para móvil) y ahí no hay columna al lado con la que alinearse.
     ⚠️ La firma conserva su `padding-inline`, así que su primer trazo
     arranca .12em más adentro que el párrafo: se compensa con un margen
     negativo igual para que los dos empiecen en la misma vertical. */
  .portada-pases__interior:has(.portada-pases__ilustracion) .portada-pases__columna { text-align: left; }
  .portada-pases__interior:has(.portada-pases__ilustracion) .portada-pases__titulo { margin-inline-start: -.12em; }
  .portada-pases__interior:has(.portada-pases__ilustracion) .portada-pases__texto { margin-inline: 0; }
  /* Carlos, 2026-09-14: «plato del lado izquierdo y texto del derecho». Se
     cambia con `order` y no en el HTML: en el teléfono el texto sigue
     arriba y la ilustración debajo, y el orden de lectura no cambia. */
  .portada-pases__ilustracion {
    order: -1;
    margin: 0; max-width: none;
    width: 100%; justify-self: center;
  }
  .portada-pases__ilustracion img { max-height: min(59.84svh, 546px); width: auto; max-width: 88%; margin-inline: auto; }
}

/* ── EN ESCRITORIO NO ES UNA BANDA: ES LA PRIMERA CARA DE LA ESCENA ──
   Carlos, 2026-09-11: «esa portada debe ir encima del efecto de los
   platillos, no como banner arriba». Vive DENTRO de `.pases__pega`, la
   pantalla que ya está pegada, y cubre la escena entera mientras dura su
   tramo; después se retira hacia arriba y deja ver los platillos.

   Es la misma ley que Carlos fijó para los propios pases el 2026-08-18:
   «todo debe hacerse en una misma sección, de qué vale ese efecto solo».
   Una banda apilada delante habría alargado la página y roto esa unidad.

   ⚠️ EN MÓVIL NO. Ahí la escena se deshace —los pases son sliders y
   `.pases__pega` deja de estar pegada—, así que la portada se queda en
   el flujo, como un bloque normal: es lo que hacen todas las piezas de
   esta escena en el teléfono. Ver [[feedback-movil-no-toca-desktop]].

   ⛔ Y NO SE VA FUNDIÉNDOSE: SE RETIRA. El primer montaje la desvanecía,
   y a media transparencia la firma quedaba cruzada encima de «Plate after
   plate» y de las ostras — dos textos distintos leyéndose a la vez, que
   es exactamente lo que esta escena evita en el cruce relevando las caras
   CON LA PANTALLA TAPADA.

   Así que el papel sube y descubre la escena, opaco de principio a fin,
   igual que la banda de bienvenida se desliza sobre el vídeo del hero:
   un folio que se retira, no una imagen que se disuelve.

   ⚠️ Se está QUIETA más de la mitad de su tramo y sale en el último 40 %:
   el movimiento es lo último que pasa, no lo que acompaña a la lectura. */
@media (min-width: 900px) {
  .portada-pases {
    position: absolute; inset: 0; z-index: 3;
    display: grid; place-items: center;
    padding-block: 0;
    /* `--portada` la publica el JS: 0 cuando la escena asoma, 1 cuando su
       tramo se ha consumido. */
    /* `--pp-espera`: cuánto de su tramo se queda QUIETA antes de empezar
       a irse. Es el mando que decide si da tiempo a leerla. */
    --pp-espera: .58;
    --pp-sale: clamp(0, calc((var(--portada, 1) - var(--pp-espera))
                             / (1 - var(--pp-espera))), 1);

    /* ⭐ SE VA DESENFOCÁNDOSE — Carlos, 2026-09-11: «esa portada
       desaparece y entran los platos, eso desaparece con blur o algo».

       ⚠️ EN DOS TIEMPOS, Y NO A LA VEZ. Primero se va el TEXTO, con el
       papel todavía opaco tapando la escena; sólo cuando la firma ya no
       está se va el papel y aparecen los platos. Hecho de una sola pieza
       —todo difuminándose junto— vuelve el fallo del primer montaje: a
       media transparencia la firma se lee encima de «Plate after plate».

       ⚠️ El papel se va con `scale(1.03)`. `filter: blur()` difumina
       TAMBIÉN el borde de la caja, así que sin ese pelo de más se veía
       asomar el filo de la escena por los cuatro lados durante la
       salida. */
    --pp-papel: clamp(0, calc((var(--pp-sale) - .48) / .52), 1);
    opacity: calc(1 - var(--pp-papel));
    filter: blur(calc(var(--pp-papel) * 9px));
    scale: calc(1 + var(--pp-papel) * .03);
  }
  /* El texto se adelanta al papel: se desenfoca y se va en la primera
     mitad de la salida, cuando todavía no se ve nada detrás. */
  .portada-pases__interior {
    --pp-t: clamp(0, calc(var(--pp-sale) / .5), 1);
    translate: 0 calc(var(--pp-t) * -26px);
    opacity: calc(1 - var(--pp-t));
    filter: blur(calc(var(--pp-t) * 13px));
  }
}

/* =====================================================================
   LOS PASES — de la cocina y de la barra
   =====================================================================
   Dos bloques a mitades con las columnas invertidas entre sí. La foto,
   el nombre y la descripción cambian a la vez mientras se baja.

   Anatomía de siempre: riel alto (`.pase`) + pantalla pegada
   (`.pase__pega`). El alto del riel depende de cuántas piezas haya, que
   lo publica el PHP en `--piezas`: con cuatro platos hace falta más
   recorrido que con dos, o pasarían atropelladamente.

   ⛔ Sin `pin` de GSAP. ⛔ Sin `overflow` en los ancestros.
   ===================================================================== */
/* ⭐ EL RIEL, AHORA UNO SOLO (2026-08-18)
   Antes cada pase traía su propio riel y su propia pantalla pegada. Hoy
   hay un único riel para las dos caras y el cruce entre ellas:

     cocina (piezas × 62svh) + cruce + barra (piezas × 62svh) + la
     pantalla pegada (100lvh), que es lo que el sticky se «come» al final.

   El fondo cambia de arena a arena clara al pasar de cara — y lo hace
   con la pantalla TAPADA de marrón, así que nadie ve el salto. */
.pases {
  position: relative;
  /* ⭐ EL TRAMO DE LA PORTADA VA DENTRO DEL RIEL (2026-09-11). Carlos:
     «esa portada debe ir encima del efecto de los platillos, no como
     banner arriba». Así que no es una sección que se apile antes: es el
     PRIMER TRAMO de esta misma escena, con la pantalla ya pegada.
     ⚠️ El JS descuenta este tramo antes de repartir el resto, para que
     el cruce siga cayendo exactamente donde Carlos lo aprobó. */
  --pp-riel: 70svh;
  height: calc((var(--piezas-a, 3) + var(--piezas-b, 3)) * 62svh
               + var(--cruce-alto) + 100lvh + var(--pp-riel, 0svh));
  background: var(--fondo);
}
.pases[data-cara="barra"] { background: var(--fondo-hondo); }

.pases__pega {
  position: sticky; top: 0;
  height: 100lvh; min-height: 560px;
  overflow: hidden;
}

/* Las dos caras, superpuestas en el mismo sitio. La que no toca no se ve
   NI SE LEE: `visibility` la saca también del lector de pantalla y del
   tabulador, que con `opacity: 0` seguirían entrando en ella. */
.pases .pase {
  position: absolute; inset: 0;
  display: grid; align-items: center;
  height: auto; background: none;
}
/* ⭐ CADA CARA SE VA Y VIENE CON EL MARRÓN
   =====================================================================
   Las olas van DETRÁS de las caras —el plato y la copa se apoyan sobre
   la mancha, que es el diseño de siempre—, así que si las caras no se
   apagaran se verían FLOTANDO sobre el marrón: el titular «Glass after
   glass» aparecía en gris oscuro sobre marrón, ilegible, mientras el
   manto todavía cubría su mitad.

   ⭐ NO SE APAGAN A LA VEZ, Y NO SE APAGAN CUANDO LES LLEGA LA OLA, SINO
   ANTES (2026-08-19). La primera versión fundía la cara ENTERA de .18 al
   tapado, que es exactamente el rato en que el filo la estaba cruzando:
   el texto se veía a media tinta con media caja sobre arena y media
   sobre marrón, y Carlos lo leyó como lo que parecía, un error de
   tiempo. Medido con `_herramientas/medir-cruce.js`.

   Ahora cada mitad tiene su tiempo y todos caben en el hueco que hay
   ANTES de que la ola arranque (`--cruce-sale`):

     foto de cocina   0   → .07   la ola entra por la derecha y la foto
                                  es lo primero que alcanzaría
     texto de cocina  .02 → .10   un pelo después, para que se lea como
                                  un barrido y no como un apagón

   El filo no toca la columna de texto hasta ~.145 (medido): quedan
   cuatro centésimas de margen entre que el texto termina de irse y la
   ola llega a donde estaba.

   Y se van HACIA LA IZQUIERDA, que es a donde barre la ola: se leen
   empujados por ella, no borrados por ella. Carlos: «quizás moverse con
   la ola mientras se desvanece».

   ⚠️ La copa sí nace sobre el marrón, y así debe ser: en la fase de la
   barra la ola vive justo debajo de ella. Por eso entra con un fundido y
   no descubriéndose con el filo — descubrirla exigiría que el manto se
   retirase de una zona en la que, al final, se queda. Su TEXTO es otra
   cosa: ése espera a `--cruce-cara`, que ahora cae al terminar la ola
   (`--cruce-cierra`) y no antes. */
.pases .pase[data-cara="cocina"] .pase__medios,
.pases .pase[data-cara="cocina"] .pase__texto,
.pases .pase[data-cara="barra"]  .pase__medios,
.pases .pase[data-cara="barra"]  .pase__texto {
  opacity: var(--t, 1);
  translate: calc((1 - var(--t, 1)) * var(--empuje, -46px)) 0;
}
.pases .pase[data-cara="cocina"] .pase__medios {
  --t: calc(1 - clamp(0, calc(var(--avance, 0) / .07), 1));
}
.pases .pase[data-cara="cocina"] .pase__texto {
  --t: calc(1 - clamp(0, calc((var(--avance, 0) - .02) / .08), 1));
}
/* La copa entra durante la retirada —sobre el marrón, como se aprobó— y
   el texto sólo cuando la pantalla ya está quieta. Los dos vienen desde
   la derecha: la ola se retira hacia la izquierda y lo que entra detrás
   la sigue. */
.pases .pase[data-cara="barra"] .pase__medios {
  --empuje: 46px;
  --t: clamp(0, calc((var(--avance, 0) - calc(var(--cruce-cierra) - .10)) / .09), 1);
}
.pases .pase[data-cara="barra"] .pase__texto {
  --empuje: 46px;
  --t: clamp(0, calc((var(--avance, 0) - var(--cruce-cara)) / calc(1 - var(--cruce-cara))), 1);
}
.pases .pase[data-cara="barra"] { visibility: hidden; }
.pases[data-cara="barra"] .pase[data-cara="cocina"] { visibility: hidden; }
.pases[data-cara="barra"] .pase[data-cara="barra"]  { visibility: visible; }

/* El ancla de «Drinks» de la barra de app. Sin tamaño: sólo marca el
   punto del riel al que hay que bajar, y el JS le pone el `top`. */
.pases__ancla { position: absolute; left: 0; width: 1px; height: 1px; }

.pase {
  position: relative;
  height: calc(var(--piezas, 4) * 62svh + 38svh);
  background: var(--fondo);
}
.pase--invertido { background: var(--fondo-hondo); }

.pase__pega {
  position: sticky; top: 0;
  height: 100lvh; min-height: 560px;
  display: grid; align-items: center;
}
.pase__interior {
  max-width: var(--ancho); margin: 0 auto; width: 100%;
  padding-inline: var(--aire);
  display: grid; gap: clamp(24px, 4vw, 64px);
  align-items: center;
}

/* ── La columna del texto ──────────────────────────────────────────
   Las fichas se apilan en la MISMA celda y sólo se ve una. Van en grid
   y no en absoluto para que la columna reserve el alto de la ficha más
   larga: si no, el bloque daría un salto cada vez que cambia el plato. */
.pase__fichas {
  display: grid;
  margin: clamp(18px, 2.4vh, 30px) 0 clamp(24px, 3vh, 38px);
}
.pase__ficha {
  grid-area: 1 / 1;
  opacity: 0; transform: translateY(14px);
  transition: opacity .5s var(--curva), transform .5s var(--curva);
  pointer-events: none;
}
.pase__ficha.es-actual { opacity: 1; transform: none; pointer-events: auto; }
.pase__ficha h3 {
  font-family: var(--titulo); font-weight: 600;
  /* ⚠️ Era un clamp que en móvil bajaba a 16,8px: el nombre del platillo
     medía menos que cualquier otro título de tarjeta del sitio. Una sola
     escala, también aquí (2026-08-18). */
  font-size: var(--t-tarjeta);
  text-transform: uppercase; letter-spacing: .04em;
  margin: 0 0 .5em;
}
.pase__ficha p {
  margin: 0; color: var(--texto-suave);
  font-size: var(--t-cuerpo); max-width: 44ch;
}
.pase__texto h2 {
  font-size: clamp(1.38rem, 3.4vw, 2.125rem);   /* techo 34px, como los demás */
  text-transform: uppercase; letter-spacing: -.005em; line-height: 1.08;
}

/* ── La columna de la foto ─────────────────────────────────────────
   Las fotos también se apilan en una sola celda. La que sale entra
   subiendo un poco; la que se va, baja. */
.pase__medios {
  list-style: none; margin: 0; padding: 0;
  display: grid;
  place-items: center;
}
.pase__medio {
  grid-area: 1 / 1;
  opacity: 0;
  transform: translateY(26px) scale(.97);
  transition: opacity .55s var(--curva), transform .55s var(--curva);
}
.pase__medio.es-actual { opacity: 1; transform: none; }
.pase__medio img {
  width: 100%; height: auto;
  /* El plato es el motivo de la escena, así que va grande — pero un 20 %
     por debajo del primer montaje (era 88svh y escala 1.14), que llenaba
     demasiado y dejaba la copa tocando los bordes. */
  max-height: 70svh; object-fit: contain;
  transform: scale(.9);
}
@media (min-width: 900px) {
  /* Se desplaza un poco hacia el borde de la pantalla, que es lo que hace
     que un producto recortado se lea como pieza y no como foto metida en
     una caja. */
  /* Carlos, 2026-09-17, con los platos ya a 45°: «aumenta 20 % el tamaño».
     .91 × 1.2 = 1.092. Los platos a 45° son anchos y bajos y dentro del
     lienzo cuadrado se leían chicos. Y con las fotos a 23° («si me gustó
     más»), un 15 % más todavía: 1.092 × 1.15 = 1.256.
     Y «unos 60px más a la izquierda»: el `translateX(-60px)` va
     DELANTE de la escala, o la escala lo convierte en 66 px. */
  .pase:not(.pase--invertido) .pase__medio img { transform: translateX(-60px) scale(1.256) translateX(4%); }
  /* ⚠️ Por debajo de 1200 px la columna es estrecha: con los 60 px y el
     tamaño grande el platillo llegaba a PISAR el texto (medido: −6 px a
     1024). Ahí se mueve sólo 20 px y se queda en el tamaño anterior. */
  @media (max-width: 1199px) {
    .pase:not(.pase--invertido) .pase__medio img { transform: translateX(-20px) scale(1.092) translateX(4%); }
  }
  /* Carlos, 2026-09-17: «todos los vasos de drinks unos 70px más a la
     derecha». El `translateX(70px)` va DELANTE de la escala: detrás,
     la escala lo encogería a 64 px. Sólo escritorio; en el teléfono
     son tarjetas centradas.
     Y luego: «un 10 % más chiquito» → .91 × .9 = .819. Escala desde el
     centro, así que el centro del vaso no se mueve.
     Y otro 10 % más: .819 × .9 = .737. */
  .pase--invertido .pase__medio img { transform: translateX(70px) scale(.737) translateX(-4%); }
}

@media (min-width: 900px) {
  .pase__interior { grid-template-columns: 1fr 1fr; }
  /* ⭐ Las columnas invertidas: en el bloque de la barra la foto va a la
     izquierda y el texto a la derecha. Se hace con `order` y no
     reordenando el HTML para que el orden de lectura siga siendo el
     mismo en los dos: primero de qué se habla, después la foto. */
  .pase--invertido .pase__texto  { order: 2; }
  .pase--invertido .pase__medios { order: 1; }

  /* ⭐ EL BLOQUE DE TEXTO VA CENTRADO EN SU MEDIA PANTALLA (2026-09-15).
     Carlos: «en la descripción de las bebidas hay más espacio a la
     derecha que a la izquierda». La columna mide media rejilla (568 px a
     1440) pero la descripción se corta a 44ch (~436 px): alineado a la
     izquierda, el bloque se pegaba a la ola y dejaba ~160 px muertos
     antes del margen.

     ⛔ SE PROBÓ PEGARLO AL MARGEN DE FUERA y se pasó de largo: la ola es
     diagonal y ocupa media pantalla, así que el aire hasta ella quedaba
     el doble que el del margen (242 contra 122 px a 1440). Centrado en
     su columna, los dos lados salen casi iguales (176 / 188 px).
     Va en las DOS caras: la cocina tenía el mismo hueco, espejado.
     El renglón sigue alineado a la izquierda: se mueve el bloque, no la
     lectura. La caja se ciñe a la ficha más larga, así que no salta al
     cambiar de plato. Medido con `_herramientas/buscar-descuadres.js`, y
     el cruce con `medir-cruce.js` sigue limpio. */
  .pase__texto { justify-self: center; width: fit-content; max-width: 100%; }
}

/* Sin escena: se ve la primera pieza, quieta, y la sección deja de ser
   un riel. */
@media (prefers-reduced-motion: reduce) {
  .pase { height: auto; }
  .pase__pega { position: static; height: auto; padding-block: var(--hueco-bloque); }
  .pase__ficha, .pase__medio { transition: none; }
}


/* =====================================================================
   EL MODAL DE RESERVA
   =====================================================================
   El widget de OpenTable, abierto desde el botón de la cabecera sin
   sacar a nadie de la página.

   ⚠️ Este modal SÍ va sobre papel claro, al revés que el visor de la
   galería: allí lo oscuro sirve para mirar una foto, aquí hay que leer y
   rellenar un formulario. Y el widget viene con sus propios colores
   claros de fábrica: sobre fondo oscuro se vería un recuadro blanco
   flotando.
   ===================================================================== */
.modal-reserva {
  position: fixed; z-index: 61;          /* sobre el velo, bajo la barra */
  border: 0; padding: 0; margin: auto;
  inset: 0;
  max-width: min(560px, calc(100vw - 2 * var(--aire)));
  width: 100%;
  max-height: min(92dvh, 900px);
  background: var(--fondo);
  color: var(--texto);
  overflow: hidden;               /* el que desplaza es la caja de dentro */
}
/* ⛔ Ya no hay `::backdrop`: el modal se abre con `show()`, no con
   `showModal()`, para que la barra de app pueda ir POR ENCIMA. El fondo
   lo pinta este pseudo-elemento del `body`, que sí obedece al z-index.
   ⚠️ Se queda por debajo de la barra a propósito: se puede seguir
   cambiando de pestaña con el modal abierto. */
body.con-modal::before {
  content: ""; position: fixed; inset: 0; z-index: 60;
  background: color-mix(in srgb, var(--marron) 74%, transparent);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  animation: velo-entra .24s var(--curva-color) both;
}
@keyframes velo-entra { from { opacity: 0 } to { opacity: 1 } }
.modal-reserva:not([open]) { display: none; }

/* Entra igual que el visor: sube un poco y aparece. Ver la nota de allí
   sobre `@starting-style` y `allow-discrete`. */
.modal-reserva, .modal-reserva::backdrop {
  transition: opacity .24s var(--curva-color),
              transform .28s var(--curva),
              display .28s allow-discrete,
              overlay .28s allow-discrete;
}
.modal-reserva { opacity: 1; transform: translateY(0); }
.modal-reserva:not([open]) { opacity: 0; transform: translateY(12px); }
@starting-style {
  .modal-reserva[open] { opacity: 0; transform: translateY(12px); }
  .modal-reserva[open]::backdrop { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .modal-reserva, .modal-reserva:not([open]) { transform: none; }
}

/* ⭐ En móvil el modal NACE DE LA BURBUJA. El botón de reservar vive en
   el centro de la barra, abajo, así que el modal crece desde ahí y sube
   en vez de aparecer suelto en mitad de la pantalla. Es la regla de la
   casa para todo lo que se abre desde un disparador: el movimiento tiene
   que explicar de dónde viene.

   ⚠️ `transform-origin` al 50% 100% —abajo en el centro— porque ahí es
   donde está la burbuja. Si el botón cambiara de sitio, esto cambia. */
/* ⭐ EN MÓVIL EL MODAL BAJA DESDE ARRIBA. Carlos lo pidió así desde el
   principio y yo lo monté al revés dos veces: primero creciendo desde la
   burbuja y luego subiendo desde el filo de abajo.

   ⚠️ Y viniendo de arriba se resuelve solo el otro problema: la BARRA DE
   APP SE QUEDA VISIBLE abajo. Cuando la hoja subía desde el filo, las dos
   ocupaban el mismo sitio y había que esconder la barra. */
@media (max-width: 899px) {
  .modal-reserva {
    max-width: 100vw; width: 100vw;
    /* Pegada al filo de ARRIBA. */
    margin: 0 auto auto;
    max-height: 86dvh;
    transform-origin: 50% 0;
    /* Sólo las esquinas de abajo: es una hoja que baja. */
    border-radius: 0 0 18px 18px;
  }
  .modal-reserva__caja {
    max-height: 86dvh;
    /* Aire arriba por la barra del navegador, y abajo para el asa. */
    padding-top: calc(20px + env(safe-area-inset-top, 0px));
    padding-bottom: 26px;
  }
  /* Baja desde fuera de la pantalla. */
  .modal-reserva:not([open]) { transform: translateY(-100%); }
  @starting-style {
    .modal-reserva[open] { transform: translateY(-100%); }
  }
  /* El asa ya no es un `::after` decorativo: es el `<button>` de cierre,
     definido más abajo. Aquí sólo se le da el aire de la safe-area. */
  .modal-reserva__asa { margin-bottom: env(safe-area-inset-bottom, 0px); }
}
@media (max-width: 899px) and (prefers-reduced-motion: reduce) {
  .modal-reserva, .modal-reserva:not([open]) { transform: none; }
}

.modal-reserva__caja {
  max-height: min(92dvh, 900px);
  overflow-y: auto;
  overscroll-behavior: contain;   /* el fondo no se mueve al llegar al final */
  padding: clamp(20px, 3.4vw, 30px);
}

/* El título va SOLO y CENTRADO desde el 2026-08-14: se retiró el botón de
   cerrar que lo acompañaba a la derecha, así que ya no hay nada que
   repartir con `space-between`. */
.modal-reserva__cabeza {
  margin-bottom: clamp(14px, 2.4vh, 22px);
  text-align: center;
}
.modal-reserva__titulo {
  font-size: clamp(1.05rem, 2.4vw, 1.32rem);
  text-transform: uppercase; letter-spacing: .02em; margin: 0;
}
/* Recibe el foco al abrir, pero no se le dibuja recuadro: no es un
   control, sólo el punto de partida del lector de pantalla. */
.modal-reserva__titulo:focus { outline: none; }
/* ⛔ Se retiraron `.modal-reserva__cerrar` (el botón X) y
   `.modal-reserva__telefono` el 2026-08-14 a petición de Carlos. El
   teléfono sigue pulsable en `/reservations/` y en el JSON-LD del `head`.

   ===================================================================
   EL ASA — ahora es el cierre, no un adorno
   ===================================================================
   Antes era un `::after` decorativo. Al quitar la X pasó a ser el único
   control visible, así que es un `<button>` de verdad: se toca y cierra.
   La caja táctil mide 44px de alto aunque la raya sólo pinte 4, que es
   el mínimo que se puede acertar con el pulgar. */
.modal-reserva__asa {
  display: block; width: 100%; height: 44px;
  margin: clamp(10px, 1.8vh, 16px) 0 0;
  padding: 0; border: 0; background: none; cursor: pointer;
  position: relative;
}
.modal-reserva__asa::before {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 46px; height: 4px; border-radius: 4px;
  background: var(--linea);
  transform: translate(-50%, -50%);
  transition: background .22s var(--curva-color), width .22s var(--curva);
}
.modal-reserva__asa:hover::before,
.modal-reserva__asa:focus-visible::before { background: var(--texto-suave); width: 60px; }

/* Si el conector no responde, el hueco del widget no deja un agujero. */
.modal-reserva--sin-widget #ot-widget { display: none; }


/* =====================================================================
   📱 LA BARRA DE APP — sólo en móvil
   =====================================================================
   Cinco pestañas con RESERVAR en el medio y una burbuja que viaja a la
   activa mientras el borde de la barra se hunde a su alrededor.

   El efecto es el de la demo «Meniscus»: la cuenca NO se dibuja aquí, la
   calcula `sitio.js` resolviendo la tangencia entre el borde y la
   burbuja, y la escribe en el `path` del SVG. Este archivo sólo pone el
   aspecto.

   ⚠️ Fuera de 900px la barra NO EXISTE. En escritorio está la cabecera.
   ===================================================================== */
.app-nav { display: none; }

@media (max-width: 899px) {
  /* ⭐ EL PIE NO PUEDE QUEDAR DEBAJO DE LA BARRA — Carlos, 2026-08-21:
     «creo que el navbar está mal anclado en mobile».
     =====================================================================
     La barra va `fixed`, así que no ocupa sitio en la página: flotaba
     encima del final del contenido y **se comía el último tramo del
     pie** —la pleca de marcas de Anderson's quedaba cortada por debajo—.
     Al llegar abajo del todo, lo último del sitio no se podía leer.

     Se reserva su hueco al final del documento. La cuenta es la de la
     propia barra, no un número inventado: lo que mide (62) + el aire de
     arriba para la burbuja (30) + lo que flota sobre el borde (36) + el
     borde seguro del iPhone, y 16 de respiro para que el pie no acabe
     pegado al canto de la barra.

     ⚠️ Va en `body` y no en `.pie`: el pie no es lo único que puede
     quedar al final —una carta larga, una entrada del blog— y así vale
     para todos. */
  :root { --hueco-barra: calc(62px + 30px + 36px + 16px + env(safe-area-inset-bottom, 0px)); }
  body { padding-bottom: var(--hueco-barra); }

  /* ⚠️ Y si hay PIE, el hueco lo pone ÉL. Puesto en el `body`, la franja
     reservada se quedaba del color del papel debajo de un pie de otro
     color: se veía una banda clara al final, como si la página estuviera
     rota. El pie tiene su propio fondo, así que el hueco desaparece
     dentro de él. */
  body:has(.pie) { padding-bottom: 0; }
  .pie { padding-bottom: var(--hueco-barra); }
  /* ⛔ Salvo donde no hay barra: en las tres cartas no sale, y ese hueco
     quedaría vacío al final de la página.
     ⚠️ `body.pagina-…`, no `.pagina-… body`: la clase de página vive EN
     el body, no en un ancestro. Escrito al revés no aplicaba nada. */
  body.pagina-food-menu, body.pagina-mixology, body.pagina-desserts { padding-bottom: 0; }

  /* ⭐ LAS MEDIDAS VIVEN AQUÍ Y SÓLO AQUÍ. `sitio.js` las LEE de estas
     variables para dibujar el `path`, así que la burbuja y su hueco no
     se pueden volver a descuadrar: antes cada uno calculaba su vertical
     por su cuenta y se habían ido 5 px. */
  .app-nav {
    /* ⭐ z-index 62: POR ENCIMA del modal (61) y de su velo (60). Es lo
       que pidió Carlos —«el menú debe estar 100% por encima de todo»— y
       lo que obligó a abrir el modal con `show()` en vez de
       `showModal()`: el modo modal lo habría puesto en el top layer del
       navegador, donde ningún z-index alcanza. */
    z-index: 62;
    --nav-alto:    62px;
    --nav-aire:    30px;   /* hueco de arriba para que la burbuja no se recorte */
    --burbuja:     44px;   /* diámetro */
    --burbuja-y:   -11px;  /* su centro, respecto al borde superior de la barra */
    --holgura:      5px;   /* ⭐ lo que la cuenca es MÁS ANCHA que la burbuja.
                              ⛔ Con 3 el foso alrededor de la esfera casi
                              desaparecía — quedó a la vista en la captura
                              de la -057. Cinco es el aire que se LEE. */
    /* ⭐ EL RADIO DE LAS ESQUINAS, y no es decorativo: es lo que decide
       cuánto aire queda entre la cuenca de la burbuja y la esquina.
       Era la mitad del alto (31px, píldora perfecta) y con eso, en las
       pestañas de los extremos, sólo quedaban **12.24px** de barra recta
       entre la esquina y el hombro: las dos curvas se encadenaban sin
       tramo recto y el hueco de la burbuja no se leía. Carlos, 2026-08-14:
       «de home a menu no tiene el espacio» — en menu quedaban 69.3px y se
       veía perfecto; en home, 12.24 y no.
       Con 24px la recta sube a 20.3px sin tocar el reparto de los iconos
       (1.31 frente a 1.28) y la barra sigue leyéndose redondeada.
       ⚠️ Lo lee el JS: es el `R` del path. */
    --radio:       20px;
    --hombro:       7px;   /* lo que tardan los hombros en volver al borde.
                              ⛔ Vivía suelto en el JS (`var S = 15`) y podía
                              desincronizarse del CSS, que es justo el fallo
                              que ya produjo un descuadre de 5px. Aquí manda. */

    display: block;
    position: fixed;
    /* ⚠️ Sin esto el navegador se queda el gesto para hacer scroll y la
       burbuja se suelta a mitad de arrastre. */
    touch-action: none;
    left: 50%; transform: translateX(-50%);
    /* ⚠️ 36px: en el Chrome de iOS hay una botonera abajo y la barra
       quedaba pegada a ella. Carlos pidió 10px más el 2026-08-14: seguía
       leyéndose pegada al filo de la pantalla. */
    bottom: calc(36px + env(safe-area-inset-bottom, 0px));
    width: min(96%, 430px);   /* 3% más de ancho = 3% más de aire entre iconos */

    /* ⛔ AQUÍ ESTABA EL FALLO QUE CARLOS REPORTÓ CUATRO VECES.
       Era `height: var(--nav-alto)` + `padding-top: var(--nav-aire)`. Con
       el `box-sizing: border-box` global (línea 155), esos 62px INCLUYEN
       el padding: la caja de contenido se quedaba en 32px. Pero el SVG y
       el `<ul>` sí miden 62px enteros y arrancan en el borde de contenido,
       o sea **colgaban 30px por debajo de la propia caja de la barra**.

       Consecuencia: `bottom: 36px` se cumplía en la CAJA —y por eso toda
       comprobación de DOM decía «36px, correcto»— mientras la píldora que
       se ve acababa a **6px** del filo de la pantalla. Carlos la veía
       pegada abajo porque LO ESTABA. Auditoría del 2026-08-14.

       La altura total es ahora `aire + alto`, que es lo que el diseño da
       por supuesto, y los hijos vuelven a caber dentro. */
    height: calc(var(--nav-aire) + var(--nav-alto));
    padding-top: var(--nav-aire);
  }

  /* ⭐ LA PÍLDORA LA PINTA UN SVG, con el color como ATRIBUTO `fill` en
     el HTML — nunca con `var()`, que el Safari de iPhone no resuelve en
     SVG. Y NO se usa `clip-path`, que ese mismo Safari tampoco aplica.
     Los dos caminos se probaron el 2026-08-14 y los dos dejaban la barra
     invisible en el móvil de Carlos. */
  .app-nav__lienzo {
    /* ⚠️ `inset` con `top` Y `height` a la vez es una sobre-restricción:
       el `bottom: 0` se ignora. Se deja explícito arriba/abajo para que la
       altura la decida la caja y no pueda volver a desbordarse. */
    position: absolute; top: var(--nav-aire); bottom: 0; left: 0; right: 0;
    width: 100%;
    overflow: visible; pointer-events: none;
    /* Dos sombras: una corta y densa que despega la píldora del fondo aun
       cuando el color de detrás es casi el mismo, y otra larga y suave
       que le da el peso. Sobre terracota, la corta es la que trabaja. */
    filter: drop-shadow(0 2px 6px rgb(38 24 16 / .40))
            drop-shadow(0 12px 28px rgb(38 24 16 / .32));
  }
  /* Respaldo mientras el JS no ha escrito el path: píldora recta.
     `.app-nav--sin-svg` la deja puesta PARA SIEMPRE: la enciende el JS
     cuando comprueba que el path no ha ocupado superficie real. Se pierde
     la cuenca, pero la barra nunca se queda sin fondo. */
  .app-nav:not(.app-nav--listo) .app-nav__lienzo { display: none; }
  /* ⚠️ `visibility`, NO `display`: el respaldo es reversible y para
     perdonarlo hay que poder volver a MEDIR el path. Con `display: none`
     el SVG mide 0×0 para siempre y la condena se bloqueaba a sí misma. */
  .app-nav--sin-svg .app-nav__lienzo { visibility: hidden; }
  .app-nav:not(.app-nav--listo) .app-nav__lista,
  .app-nav--sin-svg .app-nav__lista {
    background: var(--marron); border-radius: var(--radio);
    box-shadow: 0 2px 6px rgb(38 24 16 / .40), 0 12px 28px rgb(38 24 16 / .32),
                inset 0 0 0 1.5px rgb(243 230 216 / .5);   /* el mismo filo claro */
  }

  /* ── Las pestañas ───────────────────────────────────────────────── */
  .app-nav__lista {
    position: relative; z-index: 1;
    height: var(--nav-alto);
    list-style: none; margin: 0;
    /* ⚠️ Este aire NO es estético: sin él, el centro de la primera y la
       última pestaña quedan tan pegados al borde que la cuenca no cabe
       —el hombro se saldría de la píldora— y el path caía en el respaldo
       recto. Con 20px entraba justo; en un iPhone real la burbuja de la
       última pestaña seguía rozando el filo y la etiqueta se cortaba, así
       que son 30. */
    /* ⭐ REPARTO PAREJO — Carlos, 2026-08-14 noche, con captura marcada:
       «¿estás viendo esos espacios? no se ve bien, ¿es simétrico?». Los
       extremos medían 74px contra 57 de separación interna (ratio 1.30) y
       se veía descompensado.

       El reparto perfectamente parejo pide margen = separación = W/6, o
       sea `pad = W/12` (cx = 0.8·pad + 0.1·W = W/6). Para que la cuenca
       QUEPA en ese margen hubo que afinar la geometría entera:

           hombro 11→7 · radio 24→20 · holgura 5
           reach(7) = √((7+27)² − (7+11)²) = 28.84
           mínimo   = 28.84 + 7 + 20 = 55.84px

       En pantallas normales W/6 ≥ 62: sobra. En las muy estrechas W/6
       baja del mínimo, y ahí manda el segundo término del `max()` —
       exactamente el mínimo con 1px de colchón, `(56.8 − 0.1·W)/0.8` —
       aceptando ratio 1.17 en un iPhone SE a cambio de no perder nunca
       la cuenca.

       | barra  | margen | separación | ratio |
       |  307px |  56.8  |    48.4    | 1.17  |
       |  374px |  62.4  |    62.4    | 1.00  |
       |  413px |  68.8  |    68.8    | 1.00  |
    */
    padding-inline: max(8.333%, calc(71px - 12.5%));
    display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
    /* ⛔ Era `align-items: center`, y con eso los `<li>` NO se estiraban:
       medían lo que su contenido (icono 22 + hueco 3 + rótulo 9 = 34px) y
       el área que se puede pulsar se quedaba en 34px, muy por debajo de
       los 44px que pide iOS, aunque la barra midiera 62. `stretch` los
       hace altos como la barra; el centrado lo hace ya cada `.app-nav__item`
       con su propio `justify-content: center`. Auditoría del 2026-08-14. */
    align-items: stretch;
  }
  .app-nav__lista > li { display: flex; }
  .app-nav__item {
    display: flex; flex-direction: column; align-items: center; gap: 3px;
    flex: 1; height: 100%; justify-content: center;
    text-decoration: none; -webkit-tap-highlight-color: transparent;
    /* Acompaña al `draggable="false"` del HTML: sin esto, en iOS el
       arrastre selecciona el rótulo y saca el menú contextual. */
    -webkit-user-select: none; user-select: none; -webkit-user-drag: none;
    color: rgb(255 255 255 / .58);
    transition: color .22s var(--curva-color);
  }
  .app-nav__icono { display: grid; place-items: center; height: 22px; }
  .app-nav__icono svg { width: 21px; height: 21px; }
  .app-nav__texto {
    font-family: var(--titulo); font-size: 9px; font-weight: 700;
    letter-spacing: .1em; text-transform: uppercase; line-height: 1;
    opacity: 0; transition: opacity .2s var(--curva-color);
  }

  /* La pestaña activa: su icono y su texto se apagan, porque quien los
     lleva es la burbuja. */
  /* ⛔ `aria-current` SÓLO manda antes de que arranque el JS. Lo pinta
     PHP en la pestaña de la página y no se quita nunca, así que mientras
     estuvo en este selector la pestaña de la página se quedaba en
     transparente PARA SIEMPRE: al abrir el modal la burbuja viajaba a
     Reservar e Inicio se quedaba sin icono, porque el trazo se pinta con
     `currentColor`. Detectado el 2026-08-14 en la captura del modal.
     A partir de que el JS añade `.viva`, el único que manda es
     `.es-activo`, que sí viaja con la burbuja. */
  .app-nav:not(.viva) .app-nav__item[aria-current="page"],
  .app-nav__item.es-activo { color: transparent; }
  /* ⚠️ El icono de la pestaña activa COLAPSA, no sólo se apaga: quien lo
     lleva ahora es la burbuja, y si se queda ocupando su hueco empuja la
     etiqueta contra el filo de abajo. */
  .app-nav__item.es-activo .app-nav__icono {
    height: 0; opacity: 0; overflow: hidden;
  }
  .app-nav__item.es-activo .app-nav__texto {
    opacity: 1; color: var(--crema);
    /* Baja un poco: la etiqueta vive bajo la burbuja, no en el centro. */
    margin-top: 14px;
    /* Entra al final, cuando la burbuja ya ha llegado. */
    transition-delay: .13s;
  }

  /* ── La burbuja ─────────────────────────────────────────────────
     Sobresale por encima del borde: es lo que obliga a la barra a
     hundirse. La coloca el JS en `--x`. */
  .app-nav__burbuja {
    position: absolute; z-index: 2; pointer-events: none;
    /* ⚠️ La vertical sale de las variables de arriba, NO de un número a
       mano: el centro de la burbuja tiene que caer exactamente donde el
       `path` dibuja el fondo de la cuenca. */
    top: calc(var(--nav-aire) + var(--burbuja-y) - var(--burbuja) / 2);
    /* ⛔ Se coloca con `left`, NO con `transform`. Parece peor —el
       transform es más barato— pero un `transform` se compone en el hilo
       del COMPOSITOR mientras el `clip-path` de la barra se calcula en el
       PRINCIPAL: la burbuja se pintaba un fotograma antes que su hueco y
       se veía adelantada a la cuenca a mitad de viaje. Con `left` los dos
       van en el mismo paso. Son cinco posiciones, no un bucle de scroll:
       el coste es irrelevante y la sincronía no. */
    left: calc(var(--x, 50%) - var(--burbuja) / 2);
    width: var(--burbuja); height: var(--burbuja); border-radius: 50%;
    display: grid; place-items: center;
    background: var(--acento, #a05b33);
    box-shadow: 0 6px 18px rgb(160 91 51 / .45);
    /* ⚠️ SIN transición en la posición: a la burbuja la mueve el bucle de
       `sitio.js`, fotograma a fotograma, junto con el borde. Si además la
       animara el CSS, los dos motores se pelean y se separa del hueco. */
    transition: background .3s var(--curva-color),
                box-shadow .3s var(--curva-color),
                opacity .2s var(--curva-color);
    opacity: 0;
  }
  .app-nav--listo .app-nav__burbuja { opacity: 1; }
  /* Mientras el dedo la lleva NO hay transición: va pegada a él. Se
     devuelve al soltar, para que el enganche a la pestaña sí se vea. */
  .app-nav--arrastrando .app-nav__burbuja { transition: none; }
  .app-nav--arrastrando .app-nav__burbuja-icono { opacity: 1; }
  .app-nav--arrastrando { cursor: grabbing; }
  .app-nav__burbuja-icono { display: grid; place-items: center; color: #fff; }
  .app-nav__burbuja-icono svg { width: 19px; height: 19px; }
  /* ⚠️ El icono se va y entra el nuevo A MITAD del viaje, no al final:
     es lo que hace que la burbuja parezca una sola cosa que cambia de
     estado, y no dos iconos cruzándose. */
  /* ⚠️ El icono NO se apaga durante todo el viaje —así «se perdía»—: se
     cambia a mitad de camino desde el JS y sólo parpadea al hacerlo. */
  .app-nav__burbuja-icono { transition: opacity .14s var(--curva-color); }

  /* Mientras viaja se eleva un poco: el despegue y el aterrizaje. */
  .app-nav--viajando .app-nav__burbuja { box-shadow: 0 12px 26px rgb(160 91 51 / .5); }

  /* ── El resplandor de debajo ─────────────────────────────────────── */
  /* ⛔ `z-index: 0` NO bastaba. El `.app-nav__lienzo` es `absolute` sin
     z-index, o sea `auto` = 0 también, y a igualdad de capa gana el que va
     DESPUÉS en el documento: el `::after`. El resplandor se pintaba encima
     de la píldora y le teñía el relleno de naranja — medido, más de la
     mitad de la barra dejaba de ser `#7c533e` exacto (#7d533e…#7f533d).
     Auditoría del 2026-08-14. Con `-1` se va detrás del todo, que es su
     sitio: es un resplandor DE DEBAJO. */
  .app-nav::after {
    content: ""; position: absolute; z-index: -1; pointer-events: none;
    left: 0; right: 0; bottom: -14px; height: 30px;
    background: radial-gradient(60% 100% at var(--x, 50%) 0%,
                var(--acento, #a05b33) 0%, transparent 72%);
    opacity: .3; filter: blur(11px);
    transition: opacity .3s var(--curva-color), background .3s var(--curva-color);
  }

  /* ⚠️ Aire al final de la página para que la barra no tape el pie.
     ⛔ 2026-09-17: esta regla decía 96 px y PISABA a la de arriba, que usa
     `--hueco-barra` (144 px + el área segura, medidos de la barra). Con 96
     la barra tapaba la última línea del pie —«Fred's in Cancun»— en ocho
     rutas; lo cazó `_herramientas/tapa-barra` de la auditoría de móvil.
     Ahora las dos dicen lo mismo y manda la medida, no un número a ojo. */
  .pie { padding-bottom: var(--hueco-barra); }

  /* ⛔ El botón flotante de Grupos se retira: Grupos ya es una pestaña de
     la barra, y los dos viven fijos abajo. */
  .flotante-grupos { display: none; }
}

@media (max-width: 899px) and (prefers-reduced-motion: reduce) {
  /* La burbuja sigue marcando dónde estás, pero salta en vez de viajar. */
  .app-nav__burbuja { transition: background .2s, box-shadow .2s; }
  .app-nav__item.es-activo .app-nav__texto { transition-delay: 0s; }
}


/* =====================================================================
   EL PASO DE UNA PÁGINA A OTRA
   =====================================================================
   Carlos, 2026-08-14: «apenas empiece a mover debe ponerse blur, y luego
   saltar a la otra, y que entre con blur».

   Son TRES tiempos, y el primero es el que faltaba:

     1. AL PULSAR — la página actual se desenfoca EN EL ACTO, antes de
        que empiece a cargarse nada. Lo enciende `sitio.js` poniendo la
        clase `saliendo` en cuanto se toca una pestaña.
     2. EL SALTO — la navegación ocurre con la pantalla ya borrosa, así
        que el cambio no se ve como un corte.
     3. AL LLEGAR — la nueva entra desenfocada y se afila.

   ⚠️ El paso 1 NO lo puede hacer la View Transition API: ésa sólo empieza
   cuando el navegador ya tiene la página nueva. Entre el toque y ese
   momento hay una espera —la red— y es justo ahí donde se veía el tirón.
   ===================================================================== */
@view-transition { navigation: auto; }

/* 1 · El desenfoque inmediato, en cuanto se toca. */
.saliendo main,
.saliendo .cabecera,
.saliendo .pie {
  filter: blur(5px);
  opacity: .55;
  transition: filter .2s var(--curva-color), opacity .2s var(--curva-color);
}
/* ⚠️ La barra de app NO se desenfoca: es el mando con el que se está
   navegando y tiene que seguir nítido bajo el dedo. */

/* 3 · La que llega entra desenfocada y se afila. */
@keyframes pagina-entra {
  from { opacity: 0; filter: blur(5px); }
  to   { opacity: 1; filter: blur(0); }
}
/* La vieja ya está borrosa por el paso 1: aquí sólo se apaga. */
::view-transition-old(root) { animation: none; opacity: 0; }
::view-transition-new(root) { animation: pagina-entra .32s var(--curva-color) both; }

@media (prefers-reduced-motion: reduce) {
  .saliendo main, .saliendo .cabecera, .saliendo .pie { filter: none; opacity: .6; }
  ::view-transition-new(root) { animation: none; }
}


/* =====================================================================
   EL WIDGET DE RESERVAS, VESTIDO DE FRED'S
   =====================================================================
   El conector de Grupo Anderson's monta su propio HTML dentro de
   `#ot-widget`. ⭐ NO es un iframe: son `div` con clases `otw-*`, así que
   se puede vestir entero desde aquí.

   Venía con caja blanca, tipografía del sistema y un botón TURQUESA que
   no es de ninguna paleta de esta casa. Ahora usa el papel, la letra y
   la terracota de Fred's.

   ⚠️ Son estilos sobre el HTML de un tercero: si el conector cambia sus
   clases, esto deja de aplicar y el widget vuelve a su aspecto de
   fábrica. No se rompe — se ve como venía. Las clases están anotadas
   arriba por si hay que revisarlas.
   ===================================================================== */
#ot-widget .otw,
#ot-widget .otw-body {
  background: transparent !important;
  border: 0 !important;
  box-shadow: none !important;
  font-family: var(--cuerpo) !important;
  color: var(--texto) !important;
  padding: 0 !important;
}

/* Las etiquetas: rótulo de la casa, no negrita de sistema. */
#ot-widget label,
#ot-widget .otw-row > label {
  font-family: var(--titulo) !important;
  font-size: .68rem !important;
  letter-spacing: .14em !important;
  text-transform: uppercase !important;
  color: var(--texto-suave) !important;
  font-weight: 600 !important;
}

/* Los tres campos: línea inferior, esquinas rectas, letra de la casa. */
#ot-widget .otw-date-trigger,
#ot-widget .otw-time-trigger,
#ot-widget .otw-pax-trigger,
#ot-widget .otw-sel,
#ot-widget input {
  font-family: var(--cuerpo) !important;
  font-size: 1rem !important;
  color: var(--texto) !important;
  background: transparent !important;
  border: 0 !important;
  border-bottom: 1px solid var(--linea) !important;
  border-radius: 0 !important;
  padding: 10px 0 !important;
  min-height: 46px !important;          /* zona de toque */
  box-shadow: none !important;
}
#ot-widget .otw-drop-arrow { color: var(--acento-tinta) !important; }

/* ⭐ El botón, en el naranja de atardecer: es la MISMA acción que el
   «Reservar mesa» del sitio, así que lleva el mismo color. Venía en
   turquesa, que no existe en esta paleta desde que manda el PSD, y
   luego en la terracota. */
#ot-widget .otw-btn {
  background: var(--boton) !important;
  color: var(--boton-tinta) !important; /* 4,50:1 sobre el relleno */
  font-family: var(--titulo) !important;
  font-size: .78rem !important;
  font-weight: 700 !important;
  letter-spacing: .16em !important;
  text-transform: uppercase !important;
  /* ⛔ Estaba a `border: 0`. Con la terracota se salvaba por los pelos
     —3,03:1 contra el papel arena—, pero el naranja de atardecer sólo
     llega a 2,63 y el mínimo del contorno de un control es 3:1: sin
     borde, el botón dejaba de dibujarse contra el papel. El borde hondo
     es lo mismo que lleva `.boton--principal`. Medido, no a ojo. */
  border: 1px solid var(--boton-borde) !important;
  box-sizing: border-box !important;    /* el borde no puede crecer la caja */
  border-radius: 0 !important;          /* esquinas rectas, como todo */
  padding: 17px 24px !important;
  min-height: 52px !important;
  box-shadow: none !important;
  transition: background .22s var(--curva-color) !important;
}
#ot-widget .otw-btn:hover,
#ot-widget .otw-btn:active { background: var(--boton-honda) !important; }

/* Los desplegables de hora y comensales. */
#ot-widget .otw-cal-pop,
#ot-widget .otw-time-pop,
#ot-widget .otw-pax-pop {
  background: var(--fondo-alto) !important;
  border: 1px solid var(--linea) !important;
  border-radius: 0 !important;
  box-shadow: 0 12px 30px rgb(38 24 16 / .18) !important;
  font-family: var(--cuerpo) !important;
}
#ot-widget .otw-time-opt,
#ot-widget .otw-pax-opt {
  color: var(--texto) !important;
  min-height: 44px !important;
  display: flex !important; align-items: center !important;
}
#ot-widget .otw-time-opt:hover,
#ot-widget .otw-pax-opt:hover {
  background: var(--acento) !important; color: #fff !important;
}

/* «Powered by OpenTable»: se queda —es su marca y va en el contrato— pero
   sin competir con el resto. */
#ot-widget .otw-pob {
  opacity: .5 !important;
  font-size: .66rem !important;
  letter-spacing: .1em !important;
}
#ot-widget .otw-err { color: #8a2f2f !important; font-family: var(--cuerpo) !important; }


/* =====================================================================
   GRUPOS EN LA CABECERA — Carlos, 2026-08-14
   =====================================================================
   Bajó de la barra de app a la cabecera, junto a Reservar. En móvil la
   cabecera va justa (logo, idioma, grupos, reservar, hamburguesa), así
   que aquí se acorta: menos aire lateral y un cuerpo más pequeño, sin
   tocar el botón de reservar, que es el que manda.
   ===================================================================== */
/* ⭐ SÓLO EN MÓVIL — Carlos, 2026-08-21: «ese de grupo en el header es
   solo para mobile». En escritorio «Groups» ya está en el menú de
   navegación, a dos dedos de aquí: el botón lo repetía. En móvil ese
   menú se esconde tras la hamburguesa, así que ahí sí hace falta.
   Arriba, en escritorio, quedan el idioma y «Reservar». */
.cabecera__grupos {
  white-space: nowrap; padding: 12px 16px; font-size: .7rem;
  background: var(--boton); color: var(--boton-tinta);
  border-color: var(--boton-borde);
}
.cabecera__grupos:hover {
  background: var(--boton-honda); border-color: var(--boton-honda);
  color: #fff;
}

/* ⭐ LOS TRES DE LA CABECERA, LA MISMA CAJA — Carlos, 2026-08-18
   =====================================================================
   «Estos botones no tienen el mismo algo... déjalos del mismo tamaño y
   de paso bájale el margen interno de altura.» Medido antes del cambio
   en 1440px: idioma **41**, grupos **44,5** y reservar **48** de alto,
   con tres cuerpos distintos (11,52 · 11,2 · 12,16). Cada uno traía su
   propio relleno: 10px el idioma, 12/16 grupos y 13/24 reservar.

   La cura es la misma que ya se aplicó en móvil el 2026-08-14 (ver la
   regla gemela dentro de `max-width: 900px`): una altura fija, el aire
   vertical a cero y el texto centrado con flex. Sólo cambia el aire
   LATERAL, que es lo que distingue un botón cuadrado de un CTA ancho.

   ⚠️ Va DESPUÉS de `.cabecera__idioma` (546), de `.cabecera__reserva`
   (556-557) y de `.cabecera__grupos` (3476): las cuatro pesan lo mismo
   (0,1,0) y en el empate manda la última. Si esta regla se mueve hacia
   arriba, el padding viejo vuelve a ganar.

   ⚠️ `min-width: 901px` y no 900: en 900 clavados manda el bloque de
   móvil, que ya deja idioma y grupos en esta misma caja.
   ===================================================================== */
@media (min-width: 901px) {
  .cabecera__idioma,
  .cabecera__grupos,
  .cabecera__reserva {
    box-sizing: border-box;
    height: var(--alto-boton-cabecera);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding-block: 0;
    line-height: 1;
    font-size: .72rem;
  }
  .cabecera__idioma  { padding-inline: 12px; }
  .cabecera__grupos  { padding-inline: 16px; }
  .cabecera__reserva { padding-inline: 26px; }
}

/* ⭐ SÓLO EN MÓVIL — Carlos, 2026-08-21: «ese de grupo en el header es
   solo para mobile». A partir de 1000px el menú de navegación aparece
   con «Groups» dentro, a dos dedos de aquí, y el botón lo repetía.
   ⚠️ Va DESPUÉS del bloque de 901px a propósito: aquel le da
   `display: inline-flex` y, puesta antes, esta regla no se aplicaba.
   Se vio en pantalla, no en el código. */
@media (min-width: 1000px) { .cabecera__grupos { display: none; } }

@media (max-width: 900px) {
  .cabecera__grupos { padding: .5rem .7rem; font-size: .68rem; letter-spacing: .06em; }
  .cabecera__acciones { gap: .4rem; }

  /* ⛔ EN LAS CARTAS, GRUPOS SE VA. Son las únicas páginas del móvil donde
     el botón de RESERVAR sigue en la cabecera (no hay barra de app), y con
     logo + idioma + grupos + reservar + hamburguesa no cabía nada:
     medido el 2026-08-14 en 390px, la hamburguesa arrancaba en **x=400**
     —entera fuera de la pantalla— y RESERVAR acababa en 394, cortado. En
     español es peor porque «Reservar» ocupa 123px frente a los 81 de
     «Book». Como aquí tampoco hay barra de app, esas páginas se quedaban
     SIN NINGUNA FORMA DE NAVEGAR.
     Grupos sigue en el menú de la hamburguesa y en el pie. */
  .pagina-food-menu .cabecera__grupos,
  .pagina-mixology  .cabecera__grupos,
  .pagina-desserts  .cabecera__grupos { display: none; }

  /* Y que nada pueda volver a empujar la hamburguesa fuera: la cabecera
     recorta antes de desbordar. */
  .cabecera__interior { min-width: 0; }
  .cabecera__acciones { min-width: 0; flex-shrink: 0; }
  .cabecera__logo { min-width: 0; overflow: hidden; }

  /* ⛔ El botón flotante de grupos se apaga en móvil: Grupos ya está en
     la cabecera y aquí abajo se montaba sobre la barra de app. */
  .flotante-grupos { display: none; }
}


/* =====================================================================
   LA BARRA DORMIDA — 2026-08-14
   =====================================================================
   En las páginas que no son ninguna de las cinco pestañas (Prensa,
   Reservas, Grupos, los legales, el linktree) no hay sección que
   encender: la burbuja se esconde y la barra queda recta. Antes se
   plantaba en Inicio con su rótulo debajo y la barra mentía sobre dónde
   estabas. Al tocar cualquier pestaña despierta y la burbuja aparece ya
   en su destino, sin viajar desde Inicio.
   ===================================================================== */
.app-nav--dormida .app-nav__burbuja {
  opacity: 0; transform: translate(-50%, 6px) scale(.7);
  pointer-events: none;
}
.app-nav--dormida .app-nav__texto { opacity: 0; }


/* =====================================================================
   EL BOOK DE LA CABECERA SE VA DEL MÓVIL — Carlos, 2026-08-14
   =====================================================================
   Reservar ya vive en el centro de la barra de app, con su burbuja. Dos
   botones de lo mismo en la misma pantalla es ruido, y la cabecera del
   móvil iba justa (logo, idioma, grupos, reservar, hamburguesa).

   ⛔ SALVO EN LAS CARTAS. Esas tres páginas —comida, mixología, postres—
   NO pintan la barra de app: llevan su propio índice pegajoso abajo y
   las dos barras se montarían. Si aquí se quitara también el botón,
   serían las únicas páginas del móvil sin ninguna forma de reservar.

   ⚠️ En ESCRITORIO se queda: allí no hay barra de app, y es la acción
   que da de comer al restaurante.
   ===================================================================== */
@media (max-width: 900px) {
  .cabecera__reserva { display: none; }

  /* Las cartas no tienen barra abajo: el botón vuelve.
     ⚠️ `inline-flex` y no `inline-block` (2026-08-18): con la caja de
     altura fija de abajo, un `inline-block` deja el texto pegado arriba
     porque no hay centrado que lo baje. Y este selector pesa 0,2,0, así
     que es AQUÍ donde hay que decirlo: una regla suelta más abajo
     perdería el empate. */
  .pagina-food-menu .cabecera__reserva,
  .pagina-mixology  .cabecera__reserva,
  .pagina-desserts  .cabecera__reserva { display: inline-flex; }

  /* Y en esas cartas, RESERVAR con la misma caja que idioma y grupos
     (medido el 2026-08-18 en 390px: daba 46 de alto contra los 38 de
     ES). Sólo se toca la ALTURA: el aire lateral se queda en 16px
     porque ahí el ancho está medido al filo — el 2026-08-14 la
     hamburguesa llegó a salirse de la pantalla. */
  .cabecera__reserva {
    box-sizing: border-box;
    height: var(--alto-boton-cabecera);
    padding-block: 0;
    align-items: center;
    justify-content: center;
    line-height: 1;
  }
}


/* =====================================================================
   EL SELLO DE VERSIÓN — sólo aparece en pruebas (ver `partials/footer.php`)
   =====================================================================
   Dice qué copia estás viendo. Si no coincide con la que se acaba de
   anunciar, es caché: recargar en vez de depurar. Se toca y desaparece.
   Va por encima de todo, barra y modal incluidos, porque su trabajo es
   precisamente responder cuando algo parece roto.
   ===================================================================== */
.sello-version {
  position: fixed; z-index: 999;
  left: 8px; bottom: calc(8px + env(safe-area-inset-bottom, 0px));
  font: 600 10px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: .04em;
  padding: 5px 7px; border: 0; border-radius: 4px;
  /* ⚠️ Era `opacity: .55` sobre el conjunto, y eso lavaba a la vez el
     texto y su plaquita: sobre el crema del sitio bajaba de 3:1. Ahora la
     transparencia va SÓLO en el fondo, y el texto se queda opaco. */
  background: rgb(38 24 16 / .82); color: #f3e6d8;
  cursor: pointer;
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  transition: opacity .2s var(--curva-color);
}
.sello-version:hover, .sello-version:focus-visible { opacity: 1; }
@media print { .sello-version { display: none; } }


/* =====================================================================
   LA CABECERA DEL MÓVIL, ESPEJADA — Carlos, 2026-08-14 noche
   =====================================================================
   «El logo del lado derecho y pegado del lado izquierdo el menú
   hamburguesa, botón grupos y idioma.» Se hace con `order`, sin tocar el
   HTML: el DOM se queda como está (lectores de pantalla y tabulador
   siguen su orden lógico) y sólo cambia el pintado.

   ⚠️ SÓLO EN MÓVIL. En escritorio no hay hamburguesa y el orden clásico
   (logo a la izquierda, navegación al centro) se queda como está.
   ===================================================================== */
/* ⛔ El espejo completo duró una versión: Carlos lo devolvió — «logo a la
   izquierda, los otros a la derecha». Lo que SÍ quedó del cambio es el
   orden interno de las acciones (hamburguesa · grupos · idioma) y la caja
   única de Grupos e Idioma. */
@media (max-width: 900px) {
  /* Las acciones, empujadas al borde derecho. El selector repite el `+`
     A PROPÓSITO: la regla global `.cabecera__nav + .cabecera__acciones
     { margin-left: 0 }` pesa más que un selector simple (0,2,0 contra
     0,1,0) y sin igualarla en especificidad este `auto` perdía — la fila
     entera se quedaba pegada al logo. Medido en la versión -054. */
  .cabecera__acciones,
  .cabecera__nav + .cabecera__acciones { margin-left: auto; }

  /* Dentro de las acciones: grupos · idioma · hamburguesa — la
     hamburguesa PEGADA AL BORDE derecho, que es donde el pulgar la
     espera (Carlos, 2026-08-14 noche). */
  .cabecera__grupos      { order: 1; }
  .cabecera__idioma      { order: 2; }
  .cabecera__reserva     { order: 3; }   /* sólo existe en las cartas */
  .cabecera__hamburguesa { order: 4; margin-left: 0; margin-right: -8px; }

  /* ⭐ IDIOMA Y GRUPOS, LA MISMA CAJA. Cada uno traía su padding y su
     cuerpo (36px contra 44) y se veían de tamaños distintos — lo señaló
     Carlos. Una sola regla manda sobre los dos: misma altura, mismo
     cuerpo, mismo aire. */
  .cabecera__idioma,
  .cabecera__grupos {
    box-sizing: border-box;
    height: 38px; padding: 0 12px;
    display: inline-flex; align-items: center;
    font-size: .7rem; letter-spacing: .06em; line-height: 1;
  }
}


/* =====================================================================
   📱 LOS PASES EN MÓVIL: SLIDERS — Carlos, 2026-08-14
   =====================================================================
   «Los platillos del menú y de drink como buenos sliders modernos.»
   La escena de scroll (riel de ~3 pantallas por pase) se apaga y cada
   pase se vuelve un carrusel de deslizar, según la ley de la casa:
   snap del navegador, CSS puro, la vecina asomando, y el scroll de la
   página deja de alargarse (el riel pasa de 286svh a alto natural).

   El truco del orden: `display: contents` en `.pase__texto` disuelve la
   columna y sus hijos pasan a ser piezas de la rejilla del interior, así
   se intercalan con el slider SIN tocar el HTML (que en escritorio sigue
   siendo la escena de dos columnas): rótulo → titular → fotos → puntos →
   ficha → botón.
   ===================================================================== */
.pase__puntos { display: none; }

@media (max-width: 899px) {
  .pase, .pase--invertido { height: auto; }
  .pase__pega { position: static; height: auto; min-height: 0; padding-block: var(--hueco-bloque); }

  /* ⭐ LA ESCENA SE DESHACE (2026-08-18). Aquí los pases son sliders, no
     una escena de scroll: el riel se colapsa, la pantalla deja de
     pegarse y las dos caras vuelven a ser dos bloques, uno debajo de
     otro. El fondo lo lleva cada cara, que es quien lo tenía cuando
     eran dos secciones. */
  .pases { height: auto; background: var(--fondo); }
  .pases__pega { position: static; height: auto; min-height: 0; overflow: visible; }
  .pases .pase { position: static; padding-block: var(--hueco-bloque); }
  .pases .pase[data-cara="cocina"],
  .pases .pase[data-cara="barra"] { opacity: 1; visibility: visible; }
  /* ⚠️ Y sus mitades, con la MISMA forma de selector que las reglas de
     la escena: escritas más cortas («.pases .pase .pase__texto») pierden
     por especificidad contra `.pase[data-cara="barra"] .pase__texto` y
     el texto de la barra se queda a cero — comprobado el 2026-08-19. */
  .pases .pase[data-cara="cocina"] .pase__medios,
  .pases .pase[data-cara="cocina"] .pase__texto,
  .pases .pase[data-cara="barra"]  .pase__medios,
  .pases .pase[data-cara="barra"]  .pase__texto { opacity: 1; translate: none; }
  .pases .pase[data-cara="cocina"] { background: var(--fondo); }
  .pases .pase[data-cara="barra"]  { background: var(--fondo-hondo); }

  .pase__texto { display: contents; }
  .pase__interior { display: grid; gap: 0; text-align: center; }
  .pase__texto .rotulo { order: 1; margin-bottom: .5em; }
  .pase__texto h2     { order: 2; margin: 0; }
  .pase__medios       { order: 3; }
  .pase__puntos       { order: 4; }
  .pase__fichas       { order: 5; margin: clamp(12px, 2vh, 20px) 0 20px; }
  .pase__texto .boton { order: 6; justify-self: center; }

  /* ── La pista ──────────────────────────────────────────────────────
     A sangre completa (deshace el aire del interior) y con el hueco
     lateral exacto para que el primer y el último plato puedan CENTRARSE:
     (100vw − ancho del plato) / 2. */
  .pase__medios {
    display: flex;
    margin-inline: calc(var(--aire) * -1);
    padding: 8px calc((100vw - 72vw) / 2) 0;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    place-items: initial;
  }
  .pase__medios::-webkit-scrollbar { display: none; }

  /* ⭐ CADA PIEZA ES UNA TARJETA (2026-08-18). El JS le mete dentro su
     ficha de texto, así que aquí el `li` deja de ser «una foto» y pasa a
     ser la card entera: foto arriba, nombre y descripción debajo, todo
     sobre el mismo papel y deslizándose junto.
     ⚠️ `align-items: stretch` en la pista (por defecto en flex) hace que
     todas midan lo que la más alta: con descripciones de distinto largo,
     si no, cada tarjeta acababa a una altura y el carrusel bailaba. */
  .pase.con-cards .pase__medio {
    background: var(--fondo-hondo);
    border: 1px solid var(--borde);
    border-radius: 14px;
    padding: 18px 16px 22px;
    display: flex; flex-direction: column;
    transition: border-color .4s var(--curva-color), background .4s var(--curva-color);
  }
  .pase.con-cards.pase--invertido .pase__medio { background: var(--fondo); }

  /* ⛔ La sombra de apoyo se retira: existía para asentar un plato
     RECORTADO que flotaba sobre el papel. Dentro de una tarjeta con su
     fondo y su filo ya no asienta nada — y como el `::after` cuelga del
     `li`, había quedado debajo del texto, como una mancha. */
  .pase.con-cards .pase__medio::after { display: none; }

  /* La ficha, ya dentro de la tarjeta: aquí no se apila ni se apaga —eso
     es cosa de la escena de escritorio—, se lee entera. */
  .pase.con-cards .pase__ficha {
    position: static; opacity: 1; transform: none;
    pointer-events: auto; margin-top: 14px;
  }
  .pase.con-cards .pase__ficha h3 { margin-bottom: 8px !important; }
  .pase.con-cards .pase__ficha p { margin: 0; }
  /* La caja que las tenía se queda vacía: fuera. */
  .pase.con-cards .pase__fichas { display: none; }

  /* La barra de app flota sobre el contenido: sin este hueco, los puntos
     y el botón de la carta se quedan debajo de ella al final del bloque. */
  /* ⚠️ Bajó de 108 a 50 (Carlos, 2026-08-18): «reduce el margen del botón
     al borde de abajo unos 50px, o por lo menos el mismo espacio que el
     de arriba». Los 108 estaban para que el remate no muriese bajo la
     barra de app —que mide 92—; con 50 el botón puede quedar un momento
     por debajo de ella, pero no queda inaccesible: detrás viene otra
     sección y basta con seguir bajando. */
  .pase.con-cards { padding-bottom: calc(50px + env(safe-area-inset-bottom, 0px)); }

  /* ⚗️ PRUEBA A LA VISTA — Carlos, 2026-08-18: «en mobile puedes separar
     los card y quitarle la descripción, plis, para ver cómo se ve».
     =====================================================================
     Dos cambios, los dos reversibles en una línea cada uno:

       1. las tarjetas se separan con un hueco de verdad (antes iban
          pegadas, sólo con el aire del snap);
       2. la descripción se apaga y en la tarjeta queda la foto y el
          nombre.

     ⚠️ Es una PRUEBA para mirarla en el teléfono, no una decisión: para
     deshacerla se borra este bloque y todo vuelve como estaba. Si se
     queda, hay que decidir qué pasa con la descripción — hoy sólo se
     oculta, y el texto sigue en el documento. */
  .pase.con-cards .pase__medios { gap: 16px; }
  .pase.con-cards .pase__ficha p { display: none; }
  .pase.con-cards .pase__ficha { margin-top: 10px; }
  /* ⚠️ 18px por decisión de Carlos (2026-08-18), no los 21,1 de
     `--t-tarjeta`: dentro de la tarjeta, con el nombre en versalitas y a
     dos líneas, la escala del sitio pesaba demasiado. Es una EXCEPCIÓN
     declarada —va como papel aparte en el auditor de escalas— y sólo
     vive en el teléfono: en escritorio el nombre sigue en la escala. */
  .pase.con-cards .pase__ficha h3 {
    font-size: 18px;
    margin-bottom: 0 !important;
  }

  /* El botón, despegado de los puntos: iban pegados y parecían la misma
     pieza (Carlos, 2026-08-18). */
  .pase.con-cards .pase__texto .boton {
    margin-top: 26px;
    /* 14px por decisión de Carlos: es el único botón del sitio con
       cuerpo propio, y va declarado como excepción en el auditor de
       escalas para que el informe no mienta. */
    font-size: 14px;
  }

  .pase__medio {
    flex: 0 0 72vw;
    scroll-snap-align: center; scroll-snap-stop: always;
    /* ⛔ Deshace el apilado de la escena de escritorio: aquí TODOS los
       platos existen a la vez, uno al lado del otro. */
    grid-area: auto; opacity: 1; transform: none;
    transition: none;
  }
  .pase__medio img {
    max-height: 40svh;
    /* El plato vecino espera pequeño y apagado; el central respira. */
    transform: scale(.82) translateY(6px);
    opacity: .45;
    transition: transform .5s var(--curva), opacity .4s var(--curva-color);
  }
  .pase__medio.es-central img { transform: none; opacity: 1; }

  /* La sombra de apoyo: el plato recortado FLOTA y esto lo asienta. */
  .pase__medio::after {
    content: ""; display: block;
    width: 52%; height: 12px; margin: 4px auto 0;
    border-radius: 50%;
    background: radial-gradient(50% 50% at 50% 50%, rgb(38 24 16 / .30), transparent 72%);
    transform: scale(.6); opacity: .4;
    transition: transform .5s var(--curva), opacity .4s var(--curva-color);
  }
  .pase__medio.es-central::after { transform: none; opacity: 1; }

  /* ── Los puntos ── el actual se estira a píldora, como en las apps. */
  .pase__puntos {
    display: flex; justify-content: center; gap: 0;
    margin-top: 8px;
  }
  /* ⚠️ EL PUNTO MIDE 7px, PERO LO QUE SE PULSA MIDE 44 (auditoría de
     móvil, 2026-08-19). El botón entero era del tamaño del punto: 22×7,
     una diana imposible con el pulgar y por debajo del mínimo de 44 que
     sigue el resto del sitio. Ahora el botón es la caja grande —invisible
     y sin fondo— y el punto se pinta dentro con un pseudo-elemento. El
     aire entre puntos lo dan las cajas, así que el `gap` baja a 0 y el
     margen superior a 8: por fuera se ve exactamente igual que antes. */
  .pase__puntos button {
    /* ⚠️ 2026-09-17: medían 30 px de ancho y el dedo pide 44 (lo cazó
       `auditar-slider-movil.js`). Se ensancha la ZONA DE TOQUE, no el punto:
       el círculo lo pinta el `::before` y no se entera. */
    width: 44px; height: 44px;
    border: 0; padding: 0; background: none; cursor: pointer;
    display: grid; place-items: center;
  }
  .pase__puntos button::before {
    content: ""; display: block;
    width: 7px; height: 7px; border-radius: 99px;
    background: color-mix(in srgb, var(--texto) 25%, transparent);
    transition: width .3s var(--curva), background .3s var(--curva-color);
  }
  .pase__puntos button.es-actual::before { width: 22px; background: var(--acento); }

  /* La ficha centrada, con el ancho de leer. */
  .pase__ficha p { max-width: 34ch; margin-inline: auto; }
}


}


/* =====================================================================
   🖥 EL DECORADO DE LOS PASES — la OLA diagonal que muta (2026-08-14)
   =====================================================================
   Segunda versión el mismo día. La primera era un `border-radius`
   orgánico y Carlos lo clavó: «eso es un círculo, no olas, y no está
   diagonal». Su referencia es una masa que ATRAVIESA la pantalla en
   ángulo, del borde superior al inferior, con el filo ondulado e
   irregular — no una elipse flotando.

   Es un `clip-path: polygon()` de 23 puntos: la ola es el filo izquierdo
   (21 muestras de una diagonal con DOS senos superpuestos — con pocos
   puntos el filo salía anguloso, «papel rasgado») y cierra por el borde
   derecho. Cada platillo trae SU polígono —mismo número de puntos, que
   es la condición para que el navegador pueda interpolar— y la
   transición hace el oleaje al cambiar. Los generó
   `_herramientas/generar-olas.py` con senos; para retocarlas, tocar las
   amplitudes/frecuencias ahí y volcar.

   ⛔ No se usa `d: path()` en CSS: Safari no lo soporta. Los polígonos
   con puntos parejos se animan en todas partes.

   El ECO va detrás con la misma mecánica en terracota tenue, desfasado y
   con una deriva perpetua (anima `translate`, la propiedad suelta, para
   no pelearse con el `transform: scaleX(-1)` del espejo).
   ===================================================================== */
.pase__decorado { display: none; }

@media (min-width: 900px) {
  .pase__pega { overflow: hidden; }
  .pase__interior { position: relative; z-index: 1; }

  .pase__decorado {
    display: block; position: absolute; inset: 0; pointer-events: none;
  }

  /* ⭐ UNA SOLA FORMA POR PLATO, compartida. La ola y su eco leen la
     MISMA variable `--ola`: el eco es la ola desplazada, no una forma
     propia — cuando tenía la suya se cruzaban y el filo hacía un pico
     rasgado en mitad de la pantalla (captura de Carlos, «mira esa
     cagada», 2026-08-14). Y la receta del oleaje, tras TRES intentos:
     un seno DOMINANTE y lento (lóbulos anchos, amplitud ~8%) más uno
     suave que rompe la regularidad. Con frecuencia alta salía zigzag
     («un rayo»); con amplitud corta salía recta («no hay olas cero»).
     ⭐ LAS FORMAS FINALES LAS ELIGIÓ CARLOS A MANO con el afinador
     (`?olas`, 2026-08-14 23:04): diagonal que arranca casi en la esquina
     (94–96% arriba) y baja empinada, con oleaje suave. Sus parámetros
     exactos están en el diag.log de esa hora; para retocar, otra vez el
     afinador — no adivinar aquí.
     ⚠️ Y el muestreo importa tanto como la forma: con 21 puntos los
     tramos rectos medían ~47px y en un monitor grande el filo se veía
     FACETADO, a esquinas («¿por qué salen tan feas?»). Con 81 puntos
     (cada 1.25%) los tramos bajan a ~12px y el ojo lee curva continua. */
  .pase { --ola: polygon(97.75% 0%, 97.40% 1.25%, 96.97% 2.5%, 96.46% 3.75%, 95.88% 5%, 95.22% 6.25%, 94.48% 7.5%, 93.68% 8.75%, 92.81% 10%, 91.89% 11.25%, 90.92% 12.5%, 89.91% 13.75%, 88.87% 15%, 87.82% 16.25%, 86.76% 17.5%, 85.70% 18.75%, 84.66% 20%, 83.64% 21.25%, 82.65% 22.5%, 81.70% 23.75%, 80.81% 25%, 79.97% 26.25%, 79.19% 27.5%, 78.47% 28.75%, 77.83% 30%, 77.24% 31.25%, 76.73% 32.5%, 76.27% 33.75%, 75.88% 35%, 75.54% 36.25%, 75.25% 37.5%, 75.00% 38.75%, 74.79% 40%, 74.60% 41.25%, 74.43% 42.5%, 74.27% 43.75%, 74.10% 45%, 73.92% 46.25%, 73.73% 47.5%, 73.51% 48.75%, 73.25% 50%, 72.95% 51.25%, 72.61% 52.5%, 72.22% 53.75%, 71.77% 55%, 71.27% 56.25%, 70.72% 57.5%, 70.11% 58.75%, 69.45% 60%, 68.74% 61.25%, 67.98% 62.5%, 67.19% 63.75%, 66.36% 65%, 65.51% 66.25%, 64.64% 67.5%, 63.75% 68.75%, 62.86% 70%, 61.98% 71.25%, 61.10% 72.5%, 60.24% 73.75%, 59.41% 75%, 58.61% 76.25%, 57.84% 77.5%, 57.12% 78.75%, 56.43% 80%, 55.79% 81.25%, 55.19% 82.5%, 54.64% 83.75%, 54.13% 85%, 53.66% 86.25%, 53.23% 87.5%, 52.83% 88.75%, 52.46% 90%, 52.11% 91.25%, 51.78% 92.5%, 51.46% 93.75%, 51.14% 95%, 50.82% 96.25%, 50.49% 97.5%, 50.15% 98.75%, 49.78% 100%, 100% 100%, 100% 0%); }
  .pase[data-plato="1"] { --ola: polygon(96.86% 0%, 95.49% 1.25%, 94.12% 2.5%, 92.78% 3.75%, 91.45% 5%, 90.16% 6.25%, 88.89% 7.5%, 87.65% 8.75%, 86.44% 10%, 85.27% 11.25%, 84.14% 12.5%, 83.04% 13.75%, 81.98% 15%, 80.95% 16.25%, 79.97% 17.5%, 79.02% 18.75%, 78.11% 20%, 77.24% 21.25%, 76.40% 22.5%, 75.60% 23.75%, 74.83% 25%, 74.09% 26.25%, 73.38% 27.5%, 72.71% 28.75%, 72.06% 30%, 71.43% 31.25%, 70.84% 32.5%, 70.26% 33.75%, 69.71% 35%, 69.18% 36.25%, 68.67% 37.5%, 68.18% 38.75%, 67.71% 40%, 67.25% 41.25%, 66.81% 42.5%, 66.39% 43.75%, 65.98% 45%, 65.58% 46.25%, 65.21% 47.5%, 64.84% 48.75%, 64.49% 50%, 64.15% 51.25%, 63.83% 52.5%, 63.52% 53.75%, 63.22% 55%, 62.94% 56.25%, 62.66% 57.5%, 62.40% 58.75%, 62.15% 60%, 61.91% 61.25%, 61.67% 62.5%, 61.45% 63.75%, 61.23% 65%, 61.01% 66.25%, 60.80% 67.5%, 60.59% 68.75%, 60.38% 70%, 60.16% 71.25%, 59.94% 72.5%, 59.71% 73.75%, 59.47% 75%, 59.21% 76.25%, 58.93% 77.5%, 58.63% 78.75%, 58.31% 80%, 57.96% 81.25%, 57.57% 82.5%, 57.16% 83.75%, 56.70% 85%, 56.20% 86.25%, 55.66% 87.5%, 55.08% 88.75%, 54.44% 90%, 53.75% 91.25%, 53.01% 92.5%, 52.22% 93.75%, 51.36% 95%, 50.46% 96.25%, 49.49% 97.5%, 48.47% 98.75%, 47.39% 100%, 100% 100%, 100% 0%); }
  .pase[data-plato="2"] { --ola: polygon(88.52% 0%, 88.16% 1.25%, 87.80% 2.5%, 87.45% 3.75%, 87.10% 5%, 86.75% 6.25%, 86.39% 7.5%, 86.01% 8.75%, 85.63% 10%, 85.22% 11.25%, 84.80% 12.5%, 84.35% 13.75%, 83.87% 15%, 83.37% 16.25%, 82.84% 17.5%, 82.27% 18.75%, 81.68% 20%, 81.05% 21.25%, 80.38% 22.5%, 79.69% 23.75%, 78.96% 25%, 78.19% 26.25%, 77.40% 27.5%, 76.57% 28.75%, 75.72% 30%, 74.84% 31.25%, 73.94% 32.5%, 73.01% 33.75%, 72.07% 35%, 71.11% 36.25%, 70.14% 37.5%, 69.15% 38.75%, 68.17% 40%, 67.18% 41.25%, 66.19% 42.5%, 65.21% 43.75%, 64.23% 45%, 63.27% 46.25%, 62.32% 47.5%, 61.39% 48.75%, 60.48% 50%, 59.59% 51.25%, 58.73% 52.5%, 57.89% 53.75%, 57.09% 55%, 56.31% 56.25%, 55.57% 57.5%, 54.85% 58.75%, 54.18% 60%, 53.53% 61.25%, 52.92% 62.5%, 52.33% 63.75%, 51.78% 65%, 51.26% 66.25%, 50.76% 67.5%, 50.29% 68.75%, 49.84% 70%, 49.41% 71.25%, 49.00% 72.5%, 48.60% 73.75%, 48.22% 75%, 47.84% 76.25%, 47.47% 77.5%, 47.09% 78.75%, 46.72% 80%, 46.34% 81.25%, 45.95% 82.5%, 45.55% 83.75%, 45.14% 85%, 44.70% 86.25%, 44.25% 87.5%, 43.78% 88.75%, 43.27% 90%, 42.75% 91.25%, 42.19% 92.5%, 41.60% 93.75%, 40.99% 95%, 40.34% 96.25%, 39.66% 97.5%, 38.95% 98.75%, 38.21% 100%, 100% 100%, 100% 0%); }
  .pase[data-plato="3"] { --ola: polygon(95.56% 0%, 94.95% 1.25%, 94.35% 2.5%, 93.75% 3.75%, 93.16% 5%, 92.58% 6.25%, 92.00% 7.5%, 91.42% 8.75%, 90.85% 10%, 90.27% 11.25%, 89.71% 12.5%, 89.14% 13.75%, 88.57% 15%, 88.00% 16.25%, 87.43% 17.5%, 86.86% 18.75%, 86.28% 20%, 85.70% 21.25%, 85.10% 22.5%, 84.50% 23.75%, 83.89% 25%, 83.26% 26.25%, 82.62% 27.5%, 81.96% 28.75%, 81.29% 30%, 80.60% 31.25%, 79.89% 32.5%, 79.16% 33.75%, 78.41% 35%, 77.64% 36.25%, 76.85% 37.5%, 76.03% 38.75%, 75.19% 40%, 74.33% 41.25%, 73.45% 42.5%, 72.55% 43.75%, 71.63% 45%, 70.68% 46.25%, 69.72% 47.5%, 68.75% 48.75%, 67.76% 50%, 66.75% 51.25%, 65.74% 52.5%, 64.71% 53.75%, 63.69% 55%, 62.65% 56.25%, 61.62% 57.5%, 60.59% 58.75%, 59.57% 60%, 58.55% 61.25%, 57.54% 62.5%, 56.55% 63.75%, 55.57% 65%, 54.61% 66.25%, 53.67% 67.5%, 52.76% 68.75%, 51.87% 70%, 51.00% 71.25%, 50.17% 72.5%, 49.37% 73.75%, 48.60% 75%, 47.86% 76.25%, 47.15% 77.5%, 46.48% 78.75%, 45.84% 80%, 45.24% 81.25%, 44.67% 82.5%, 44.12% 83.75%, 43.61% 85%, 43.13% 86.25%, 42.67% 87.5%, 42.24% 88.75%, 41.83% 90%, 41.44% 91.25%, 41.07% 92.5%, 40.70% 93.75%, 40.35% 95%, 40.01% 96.25%, 39.67% 97.5%, 39.33% 98.75%, 38.98% 100%, 100% 100%, 100% 0%); }

  /* ⭐ LAS OLAS DE DRINKS SON OTRAS — Carlos afinó un juego mirando los
     platillos (23:04) y otro mirando los tragos (23:15, diag.log del
     2026-08-14): cocina conserva el primero y Copa a copa lleva el suyo.
     El espejo (`scaleX(-1)`) se mantiene: estas formas ya se dibujan
     pensadas para el lado izquierdo. */
  .pase--invertido { --ola: polygon(87.35% 0%, 86.72% 1.25%, 86.16% 2.5%, 85.67% 3.75%, 85.26% 5%, 84.92% 6.25%, 84.63% 7.5%, 84.37% 8.75%, 84.13% 10%, 83.89% 11.25%, 83.63% 12.5%, 83.33% 13.75%, 82.97% 15%, 82.55% 16.25%, 82.05% 17.5%, 81.47% 18.75%, 80.82% 20%, 80.09% 21.25%, 79.31% 22.5%, 78.48% 23.75%, 77.62% 25%, 76.76% 26.25%, 75.91% 27.5%, 75.09% 28.75%, 74.32% 30%, 73.60% 31.25%, 72.97% 32.5%, 72.41% 33.75%, 71.92% 35%, 71.51% 36.25%, 71.17% 37.5%, 70.88% 38.75%, 70.62% 40%, 70.38% 41.25%, 70.14% 42.5%, 69.88% 43.75%, 69.58% 45%, 69.22% 46.25%, 68.80% 47.5%, 68.30% 48.75%, 67.72% 50%, 67.07% 51.25%, 66.34% 52.5%, 65.56% 53.75%, 64.73% 55%, 63.87% 56.25%, 63.01% 57.5%, 62.16% 58.75%, 61.34% 60%, 60.57% 61.25%, 59.85% 62.5%, 59.22% 63.75%, 58.66% 65%, 58.17% 66.25%, 57.76% 67.5%, 57.42% 68.75%, 57.13% 70%, 56.87% 71.25%, 56.63% 72.5%, 56.39% 73.75%, 56.13% 75%, 55.83% 76.25%, 55.47% 77.5%, 55.05% 78.75%, 54.55% 80%, 53.97% 81.25%, 53.32% 82.5%, 52.59% 83.75%, 51.81% 85%, 50.98% 86.25%, 50.12% 87.5%, 49.26% 88.75%, 48.41% 90%, 47.59% 91.25%, 46.82% 92.5%, 46.10% 93.75%, 45.47% 95%, 44.91% 96.25%, 44.42% 97.5%, 44.01% 98.75%, 43.67% 100%, 100% 100%, 100% 0%); }
  .pase--invertido[data-plato="1"] { --ola: polygon(76.65% 0%, 76.54% 1.25%, 76.40% 2.5%, 76.22% 3.75%, 76.00% 5%, 75.73% 6.25%, 75.41% 7.5%, 75.04% 8.75%, 74.60% 10%, 74.10% 11.25%, 73.54% 12.5%, 72.93% 13.75%, 72.27% 15%, 71.56% 16.25%, 70.82% 17.5%, 70.04% 18.75%, 69.24% 20%, 68.43% 21.25%, 67.62% 22.5%, 66.82% 23.75%, 66.03% 25%, 65.27% 26.25%, 64.54% 27.5%, 63.86% 28.75%, 63.22% 30%, 62.64% 31.25%, 62.12% 32.5%, 61.65% 33.75%, 61.25% 35%, 60.90% 36.25%, 60.61% 37.5%, 60.37% 38.75%, 60.17% 40%, 60.02% 41.25%, 59.89% 42.5%, 59.79% 43.75%, 59.70% 45%, 59.61% 46.25%, 59.52% 47.5%, 59.41% 48.75%, 59.27% 50%, 59.10% 51.25%, 58.88% 52.5%, 58.62% 53.75%, 58.30% 55%, 57.93% 56.25%, 57.50% 57.5%, 57.01% 58.75%, 56.46% 60%, 55.85% 61.25%, 55.19% 62.5%, 54.49% 63.75%, 53.75% 65%, 52.97% 66.25%, 52.18% 67.5%, 51.37% 68.75%, 50.56% 70%, 49.75% 71.25%, 48.96% 72.5%, 48.20% 73.75%, 47.47% 75%, 46.78% 76.25%, 46.14% 77.5%, 45.55% 78.75%, 45.02% 80%, 44.55% 81.25%, 44.14% 82.5%, 43.79% 83.75%, 43.49% 85%, 43.25% 86.25%, 43.05% 87.5%, 42.89% 88.75%, 42.76% 90%, 42.66% 91.25%, 42.57% 92.5%, 42.48% 93.75%, 42.38% 95%, 42.27% 96.25%, 42.14% 97.5%, 41.97% 98.75%, 41.76% 100%, 100% 100%, 100% 0%); }
  .pase--invertido[data-plato="2"] { --ola: polygon(95.89% 0%, 95.25% 1.25%, 94.58% 2.5%, 93.87% 3.75%, 93.13% 5%, 92.35% 6.25%, 91.53% 7.5%, 90.67% 8.75%, 89.78% 10%, 88.86% 11.25%, 87.90% 12.5%, 86.91% 13.75%, 85.89% 15%, 84.85% 16.25%, 83.78% 17.5%, 82.69% 18.75%, 81.58% 20%, 80.46% 21.25%, 79.32% 22.5%, 78.18% 23.75%, 77.04% 25%, 75.90% 26.25%, 74.76% 27.5%, 73.63% 28.75%, 72.51% 30%, 71.40% 31.25%, 70.31% 32.5%, 69.25% 33.75%, 68.21% 35%, 67.20% 36.25%, 66.21% 37.5%, 65.26% 38.75%, 64.34% 40%, 63.46% 41.25%, 62.62% 42.5%, 61.81% 43.75%, 61.04% 45%, 60.30% 46.25%, 59.61% 47.5%, 58.95% 48.75%, 58.32% 50%, 57.73% 51.25%, 57.17% 52.5%, 56.64% 53.75%, 56.14% 55%, 55.66% 56.25%, 55.21% 57.5%, 54.77% 58.75%, 54.35% 60%, 53.94% 61.25%, 53.54% 62.5%, 53.14% 63.75%, 52.74% 65%, 52.34% 66.25%, 51.94% 67.5%, 51.52% 68.75%, 51.09% 70%, 50.64% 71.25%, 50.18% 72.5%, 49.69% 73.75%, 49.17% 75%, 48.63% 76.25%, 48.06% 77.5%, 47.45% 78.75%, 46.82% 80%, 46.15% 81.25%, 45.44% 82.5%, 44.70% 83.75%, 43.93% 85%, 43.12% 86.25%, 42.28% 87.5%, 41.40% 88.75%, 40.50% 90%, 39.57% 91.25%, 38.61% 92.5%, 37.63% 93.75%, 36.62% 95%, 35.60% 96.25%, 34.57% 97.5%, 33.52% 98.75%, 32.47% 100%, 100% 100%, 100% 0%); }
  .pase--invertido[data-plato="3"] { --ola: polygon(90.10% 0%, 89.27% 1.25%, 88.43% 2.5%, 87.59% 3.75%, 86.78% 5%, 85.99% 6.25%, 85.23% 7.5%, 84.52% 8.75%, 83.86% 10%, 83.24% 11.25%, 82.68% 12.5%, 82.18% 13.75%, 81.74% 15%, 81.35% 16.25%, 81.00% 17.5%, 80.71% 18.75%, 80.45% 20%, 80.21% 21.25%, 80.00% 22.5%, 79.80% 23.75%, 79.60% 25%, 79.39% 26.25%, 79.15% 27.5%, 78.89% 28.75%, 78.58% 30%, 78.23% 31.25%, 77.82% 32.5%, 77.36% 33.75%, 76.82% 35%, 76.23% 36.25%, 75.57% 37.5%, 74.84% 38.75%, 74.05% 40%, 73.21% 41.25%, 72.32% 42.5%, 71.39% 43.75%, 70.43% 45%, 69.44% 46.25%, 68.45% 47.5%, 67.45% 48.75%, 66.47% 50%, 65.51% 51.25%, 64.57% 52.5%, 63.68% 53.75%, 62.83% 55%, 62.04% 56.25%, 61.31% 57.5%, 60.63% 58.75%, 60.02% 60%, 59.47% 61.25%, 58.98% 62.5%, 58.54% 63.75%, 58.15% 65%, 57.80% 66.25%, 57.49% 67.5%, 57.20% 68.75%, 56.93% 70%, 56.67% 71.25%, 56.39% 72.5%, 56.11% 73.75%, 55.80% 75%, 55.46% 76.25%, 55.08% 77.5%, 54.66% 78.75%, 54.18% 80%, 53.66% 81.25%, 53.08% 82.5%, 52.45% 83.75%, 51.77% 85%, 51.05% 86.25%, 50.28% 87.5%, 49.48% 88.75%, 48.65% 90%, 47.81% 91.25%, 46.96% 92.5%, 46.11% 93.75%, 45.28% 95%, 44.46% 96.25%, 43.68% 97.5%, 42.93% 98.75%, 42.23% 100%, 100% 100%, 100% 0%); }


  .pase__onda {
    position: absolute; inset: 0;
    /* ⚠️ `background-color` y NO el atajo `background`: el atajo borra la
       imagen, y desde el 2026-09-10 esta ola lleva el papel encima (se
       pone más arriba, en «El papel, sólo en el escenario marrón»). */
    background-color: var(--marron);
    clip-path: var(--ola);
    transition: clip-path 1.3s var(--curva);
  }
  /* En el pase invertido la ola entra por la IZQUIERDA: espejo puro. */
  .pase--invertido .pase__onda { transform: scaleX(-1); }

  .pase__onda--eco {
    background: color-mix(in srgb, var(--acento) 30%, transparent);
    /* La misma ola, corrida HACIA EL LADO CLARO: así asoma como un canto
       terracota pegado al filo. `translate` es la propiedad suelta: no
       pisa el `scaleX(-1)` del espejo… y justo por eso NO SE ESPEJA SOLA.
       ⛔ En Drinks (masa a la izquierda) el corrimiento a la izquierda
       metía el eco DEBAJO de la ola y desaparecía — «¿por qué el de menú
       tiene doble ola y la de drink no?» (Carlos, 2026-08-14). El pase
       invertido lo corre al lado contrario, con su deriva espejada. */
    translate: -2.2% 0;
    animation: pase-oleaje 22s ease-in-out infinite alternate;
  }
  @keyframes pase-oleaje {
    from { translate: -1.4% 0; }
    to   { translate: -3.2% 0; }
  }
  .pase--invertido .pase__onda--eco {
    translate: 2.2% 0;
    animation-name: pase-oleaje-espejo;
  }
  @keyframes pase-oleaje-espejo {
    from { translate: 1.4% 0; }
    to   { translate: 3.2% 0; }
  }
  }

  /* ⛔ El número del plato se retiró: «no quiero número» (2026-08-14). */
}

@media (prefers-reduced-motion: reduce) {
  .pase__onda--eco { animation: none; }
}


/* =====================================================================
   🖥 EL CRUCE — de «Plato a plato» a «Copa a copa» (2026-08-18)
   =====================================================================
   Carlos: «cuando termine los platillos de la cocina, vamos a hacer que
   todo se cubra de marrón, las olas pasen al lado izquierdo y luego
   empiecen las bebidas».

   Riel de dos pantallas + pantalla pegada, como todas las escenas de la
   casa. El JS publica `--avance` (0→1) y aquí no se hace otra cosa que
   leerlo: reversible, pegado al dedo y sin GSAP.

   ⭐ NO HAY NINGÚN EFECTO NUEVO. La pieza que se mueve es la ola que ya
   usan los dos pases, con su mismo marrón y su mismo canto terracota; lo
   único que se añade es un RELLENO pegado a cada ola, porque una ola
   sola nunca puede tapar una pantalla entera: cubre su mitad y deja la
   otra al aire.

   Los dos mantos:

     --sale   ola de cocina (masa a la derecha) + relleno a su derecha.
              Reposo = exactamente donde la deja el pase de cocina, para
              que el empalme de entrada no dé un salto.
     --queda  ola de la barra (masa a la izquierda, espejada) + su eco +
              relleno a su izquierda. Reposo = exactamente donde la tiene
              el pase de la barra, por lo mismo pero al salir.

   ⚠️ Todo se mide en % del PROPIO manto, que mide el 100% de la pantalla
   útil. Nada de `vw`: `100vw` incluye la barra de scroll y aquí eso son
   ~15px de desborde horizontal en toda la portada.
   ===================================================================== */
.pases__olas { display: none; }

@media (min-width: 900px) {
  /* Es decorado y nada más: ni se clica ni se selecciona ni se pone
     delante de nada que sí sirva. Va DEBAJO de las dos caras. */
  .pases__olas {
    display: block; position: absolute; inset: 0;
    pointer-events: none; z-index: 0;
  }
  .pases .pase { z-index: 1; }

  .cruce__manto { position: absolute; inset: 0; }
  .cruce__ola {
    position: absolute; inset: 0;
    background-color: var(--marron);   /* el atajo borraría el papel */
  }
  .cruce__relleno { position: absolute; top: 0; width: 100%; height: 100%; background-color: var(--marron); }

  /* ── La que sale ──────────────────────────────────────────────────
     De 0 a -100%: una pantalla ENTERA de recorrido, no media.
     ⚠️ Medio barrido no basta: la ola no es una mitad recta sino una
     diagonal —arriba la masa ocupa un 11% del ancho y abajo un 62%—, así
     que a -50% quedaba destapada toda la banda de arriba. Con -100% el
     relleno acaba tapando por sí solo, sin depender del solape.
     Se apaga en .44, con todo cubierto: el relevo no se ve. */
  .cruce__manto--sale {
    /* ⚠️ Arranca en `--cruce-sale`, no en 0: el hueco de delante es el
       que usa la cocina para irse antes de que el filo la alcance. */
    translate: calc(clamp(0, calc((var(--avance, 0) - var(--cruce-sale)) / calc(var(--cruce-tapa) - var(--cruce-sale))), 1) * -100%) 0;
    opacity: calc(1 - clamp(0, calc((var(--avance, 0) - var(--cruce-tapa) - .02) / .02), 1));
  }
  .cruce__ola--cocina { clip-path: var(--ola-entra); }
  /* ⚠️ Los rellenos SOLAPAN 6px con su ola. Pegados al milímetro dejaban
     una LÍNEA CLARA de un píxel en la costura —las dos cajas caen en
     posiciones fraccionarias y el antialiasing abre una hendidura por la
     que se veía el canto de detrás (2026-08-18)—. Se ve en cualquier
     captura del cruce a media apertura.
     ⛔ SE PROBÓ A SUBIRLOS A 6px el 2026-09-10 y no era eso. Al poner el
     papel con `background-blend-mode`, la línea clara volvió (pico de
     126 sobre un fondo de 90) y al ensanchar el solape la línea
     simplemente SE MOVIÓ con el borde: no era una hendidura entre las
     dos cajas, era el borde del propio relleno, que con blend se
     rasteriza aparte y deja un píxel sin multiplicar. Se arregló
     quitando el blend —la baldosa del marrón viene ya multiplicada— y
     los 2px se quedan como estaban. */
  .cruce__manto--sale .cruce__relleno { left: calc(100% - 2px); width: calc(100% + 2px); }

  /* ── La que queda ─────────────────────────────────────────────────
     Enciende en .40 (tapado) desde +100%, que es la única posición que
     garantiza pantalla llena venga la ola que venga: ahí el relleno solo
     ya cubre de 0 a 100. De .52 en adelante se retira hasta el 0, que es
     su sitio de siempre.
     El filo que descubre la pantalla ES la ola: por eso el marrón no se
     va como un telón recto, sino rompiendo. */
  .cruce__manto--queda {
    /* ⚠️ Termina en `--cruce-cierra`, no en 1: el hueco de detrás es el
       que espera el texto de la barra para nacer con la pantalla ya
       quieta. Si acabara en 1, el texto encendería mientras el filo
       todavía cruza su columna — que es justo el defecto que se
       corrigió el 2026-08-19. */
    translate: calc(100% - clamp(0, calc((var(--avance, 0) - var(--cruce-suelta)) / calc(var(--cruce-cierra) - var(--cruce-suelta))), 1) * 100%) 0;
    opacity: clamp(0, calc((var(--avance, 0) - var(--cruce-tapa) + .02) / .02), 1);
  }
  /* El canto terracota: la MISMA ola de su manto, corrida, y siempre por
     DEBAJO —va primero en el HTML— para que sólo asome por el filo. */
  .cruce__ola--eco { background: color-mix(in srgb, var(--acento) 30%, transparent); }
  .cruce__manto--sale .cruce__ola--eco { clip-path: var(--ola-entra); translate: -2.2% 0; }
  .cruce__ola--barra,
  .cruce__manto--queda .cruce__ola--eco { clip-path: var(--ola-queda); transform: scaleX(-1); }
  .cruce__manto--queda .cruce__ola--eco { translate: 2.2% 0; }
  .cruce__manto--queda .cruce__relleno { left: -100%; width: calc(100% + 2px); }
}

/* =====================================================================
   🖥 LA CITA DEL MARRÓN — Carlos, 2026-08-18
   =====================================================================
   «El espacio todo marrón entre los platillos y el bar... vamos a meter
   un texto para que no se vea marrón plano, un texto que ayude al
   efecto, bien armado, que entre y salga.»

   Vive en el hueco tapado y sólo ahí. Se apoya en los mismos números del
   cruce, así que si se mueve el ritmo con `?cruce` la cita se ajusta
   sola: entra cuando ya está todo marrón (tapa + .04) y se ha ido antes
   de que empiece a destaparse (suelta − .04).

   ⛔ NO SE REVELA PALABRA A PALABRA. Ese fue el defecto que la sacó de la
   portada en agosto: con `scrub` quedaba medio escrita a media pantalla y
   parecía un fallo de carga. Aquí entra ENTERA y sale ENTERA; lo único
   escalonado es la firma, que va tres centésimas detrás.
   ===================================================================== */
.pases__cita { display: none; }

@media (min-width: 900px) {
  .pases__cita {
    display: grid; align-content: center; justify-items: center;
    position: absolute; inset: 0; z-index: 2;
    margin: 0; padding-inline: var(--aire);
    text-align: center; pointer-events: none;

    /* ⚠️ Las rampas son fracciones del cruce, así que al alargar el cruce
       de 170 a 215svh (2026-08-19) se comían el rato en que la cita está
       QUIETA, que es el único que sirve para leerla. Bajadas de .08/.06 a
       .06/.05 para que siga parada los mismos ~29svh de siempre. */
    --cita-entra: clamp(0, calc((var(--avance, 0) - (var(--cruce-tapa) + .02)) / .06), 1);
    --cita-sale:  clamp(0, calc((var(--avance, 0) - (var(--cruce-suelta) - .06)) / .05), 1);
    opacity: calc(var(--cita-entra) - var(--cita-sale));
  }

  /* ⭐ 2026-09-10 · LA CITA VA EN LA CALIGRÁFICA. Carlos, sobre la
     captura del manto marrón: «aquí quiero la tipografía esas raras
     rojas». La letra es la Mr Dafoe del cartel Sea & Spice; es el único
     sitio de la portada donde entra, y por eso funciona: una firma en
     medio de una pantalla vacía de color.

     ⛔ EN ROJO NO PUEDE IR, Y NO ES UN CAPRICHO: el rojo del cartel sobre
     este marrón da **1,23:1** —medido—, cuando el mínimo para leer es
     4,5. Sería un texto invisible. El rojo de esa letra vive en el
     cartel porque su fondo es papel casi blanco; aquí el fondo es el
     marrón de marca. Se queda en blanco, que da 6,64:1.
     Si algún día se quiere ESTA cita en rojo, lo que hay que cambiar es
     el fondo, no el color de la letra.

     ⚠️ SUBE DE 44 A 80px. Una caligráfica de trazo fino necesita tamaño:
     a los 44px de la Jost los remates se rompían.

     ⚠️ EL ANCHO MANDA SOBRE EL RITMO, no sobre la medida de lectura. La
     Mr Dafoe pinta tan estrecho que a 22ch la cita entraba en UNA línea
     de lado a lado de la pantalla y las comillas quedaban colgando en
     los extremos. A 15ch vuelve a romper en dos líneas, que es como
     estaba pensada la escena.

     ⚠️ El `padding-inline` no es adorno: los trazos de esta letra se
     salen de su propia caja —la «T» arranca a la izquierda del punto de
     origen— y sin ese aire se recortan contra el borde. */
  /* ⚠️ EL SELECTOR NOMBRA A LOS DOS. Desde el 2026-09-11 la pieza no es
     una cita sino una frase de la casa (`.pases__cita__frase`), pero el
     `blockquote` se queda escrito: si algún día vuelve la de Food&Travel
     —que sigue guardada en `_datos/contenido.php`— se pinta igual sin
     tocar nada aquí. */
  .pases__cita blockquote,
  .pases__cita__frase {
    font-family: var(--caligrafia);
    font-weight: 400;
    font-size: clamp(46px, 5.4vw, 80px);
    line-height: 1.12;
    color: #fff;
    max-width: 15ch;
    padding-inline: .1em;
    /* El hueco de abajo era para la firma del medio. Sin firma no hay
       nada que separar, y con él la frase quedaba descentrada en la
       pantalla: la caja medía media línea de más por debajo. */
    margin: 0 0 .5em;
    /* Sube al entrar y sigue subiendo al salir: un solo sentido, como
       todo lo que se mueve en esta portada. */
    translate: 0 calc((1 - var(--cita-entra)) * 22px - var(--cita-sale) * 22px);
  }

  .pases__cita__frase { margin-bottom: 0; }

  .pases__cita figcaption {
    font-family: var(--titulo);
    font-size: .78rem; font-weight: 600;
    letter-spacing: .18em; text-transform: uppercase;
    /* Sólida, sin transparencia: medida sobre el marrón da 5,21:1, que es
       lo que pide un cuerpo pequeño (el mínimo son 4,5). */
    color: #efe2d4;
    /* La raya la pone el CSS: en el dato va sólo el nombre del medio. */
    translate: 0 calc((1 - var(--cita-entra)) * 30px - var(--cita-sale) * 14px);
    opacity: clamp(0, calc((var(--avance, 0) - (var(--cruce-tapa) + .05)) / .06), 1);
  }
  .pases__cita figcaption::before { content: "— "; }
}

/* Sin movimiento: la escena se deshace y quedan las dos caras, una
   debajo de otra, con su primera pieza a la vista. Lo mismo que hace el
   móvil. */
@media (prefers-reduced-motion: reduce) {
  .pases__olas { display: none; }
  .pases { height: auto; }
  .pases__pega { position: static; height: auto; min-height: 0; }
  .pases .pase { position: static; padding-block: var(--hueco-bloque); }
  .pases .pase[data-cara="cocina"],
  .pases .pase[data-cara="barra"] { opacity: 1; visibility: visible; }
  /* ⚠️ Y sus mitades, con la MISMA forma de selector que las reglas de
     la escena: escritas más cortas («.pases .pase .pase__texto») pierden
     por especificidad contra `.pase[data-cara="barra"] .pase__texto` y
     el texto de la barra se queda a cero — comprobado el 2026-08-19. */
  .pases .pase[data-cara="cocina"] .pase__medios,
  .pases .pase[data-cara="cocina"] .pase__texto,
  .pases .pase[data-cara="barra"]  .pase__medios,
  .pases .pase[data-cara="barra"]  .pase__texto { opacity: 1; translate: none; }
  .pases .pase[data-cara="cocina"] { background: var(--fondo); }
  .pases .pase[data-cara="barra"]  { background: var(--fondo-hondo); }
}


/* =====================================================================
   🖥 GRUPOS, ESCENA DE SCROLL — «entran con scroll» (2026-08-14)
   =====================================================================
   Sólo en escritorio y sólo sin `prefers-reduced-motion`. El riel mide
   230svh: la pantalla se pega y quedan ~130svh de recorrido para que las
   piezas entren UNA A UNA, empujadas por el scroll y reversibles:

       avance:   0 ─ .10 ─────── .30 ─────── .50 ─────── .70 ── 1
       pieza:        rótulo      titular     descripción  botón

   Cada pieza calcula su propio tiempo `--t` con un clamp sobre
   `--avance` (que escribe el JS): opacidad = --t, y sube 34px→0. El
   fondo hace un zoom lentísimo de 1.12→1 con el mismo avance.

   ⚠️ `var(--avance, 1)`: si el JS no llega, TODO visible. Una escena
   jamás puede costar contenido.
   ===================================================================== */
@media (min-width: 900px) and (prefers-reduced-motion: no-preference) {
  .grupos-home {
    height: 230svh;
    min-height: 0;
    display: block;
    overflow: visible;         /* el riel no recorta a su pantalla pegada */
  }
  .grupos-home__pega {
    position: sticky; top: 0;
    height: 100lvh; min-height: 560px;
    display: grid; align-items: center;
    overflow: hidden;
    isolation: isolate;
  }
  /* ══════════════════════════════════════════════════════════════════
     LOS TRES TIEMPOS — Carlos, 2026-08-17
     ══════════════════════════════════════════════════════════════════
     «La foto original, luego se va poniendo blur mientras sale el
     overlay, luego las letras».

       0 → .22   LA FOTO, limpia. Ni velo ni desenfoque: primero se ve
                 dónde estamos.
     .18 → .52   El desenfoque y el velo, JUNTOS. La foto se retira a
                 fondo de escena mientras el color de la casa la cubre.
     .48 → 1     LAS LETRAS, escalonadas como estaban (rótulo, titular,
                 texto, botón).

     ⚠️ Los tramos se PISAN un poco a propósito (.18 antes de que acabe
     el primero, .48 antes de que acabe el segundo). Encadenados a tope
     la escena se lee como tres pasos sueltos; solapados, como un solo
     movimiento.

     ⚠️ El velo tiene que estar ENTERO cuando entra la primera letra: el
     .74 está medido para que el texto blanco pase de 4,5:1 sobre esta
     foto. Por eso las letras empiezan en .48 y el velo termina en .52,
     y no al revés. */
  .grupos-home::before { content: none; }

  /* El velo, ahora con su propia entrada. */
  .grupos-home__pega::before {
    content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
    background:
      linear-gradient(180deg,
        rgb(124 83 62 / .26)   0%, rgb(124 83 62 / 0)   26%,
        rgb(124 83 62 / 0)    74%, rgb(124 83 62 / .30) 100%),
      rgb(124 83 62 / .86);
    opacity: clamp(0, calc((var(--avance, 1) - .18) * 2.95), 1);
  }

  /* ── LA CINTA ────────────────────────────────────────────────────
     Las seis fotos en fila, desplazándose a la izquierda conforme baja
     el scroll. Es el gesto que hace «galería» sin sacar un carrusel con
     flechas dentro de una escena que ya tiene su propio movimiento.

     ⚠️ Se mueve con `translate3d`, que va en el compositor. Con `left`
     o `margin` habría que recalcular el diseño en cada fotograma. */
  .grupos-galeria {
    position: absolute; inset: 0;
    display: flex; align-items: center; gap: clamp(12px, 1.4vw, 22px);
    padding-inline: clamp(12px, 1.4vw, 22px);
    width: max-content;
    transform: translate3d(calc(var(--avance, 0) * -34%), 0, 0);
    will-change: transform;
  }
  /* ⚠️ `display: block` explícito: la regla de móvil esconde todas las
     fotos menos la primera, y sin devolverlas aquí la cinta se quedaba
     en una sola imagen estirada. */
  .grupos-galeria img,
  .grupos-galeria img:first-child {
    display: block;
    height: 82svh; width: auto; object-fit: cover;
    flex: 0 0 auto;
  }
  /* La cinta borrosa, encima y a la misma altura: aparece con el velo. */
  .grupos-galeria--velada {
    opacity: clamp(0, calc((var(--avance, 1) - .18) * 2.95), 1);
  }

  .grupos-home__texto .rotulo {
    --t: clamp(0, calc((var(--avance, 1) - .48) * 6), 1);
    opacity: var(--t);
    translate: 0 calc((1 - var(--t)) * 34px);
  }
  .grupos-home__texto h2 {
    --t: clamp(0, calc((var(--avance, 1) - .58) * 6), 1);
    opacity: var(--t);
    translate: 0 calc((1 - var(--t)) * 42px);
  }
  .grupos-home__texto p:not(.rotulo) {
    --t: clamp(0, calc((var(--avance, 1) - .68) * 6), 1);
    opacity: var(--t);
    translate: 0 calc((1 - var(--t)) * 34px);
  }
  .grupos-home__texto .boton {
    --t: clamp(0, calc((var(--avance, 1) - .78) * 6), 1);
    opacity: var(--t);
    translate: 0 calc((1 - var(--t)) * 26px);
  }
}

/* =====================================================================
   FREDDIE'S KIDS CLUB · LAS TRES ZONAS, EN TARJETAS QUE SE APILAN
   =====================================================================
   TERCERA versión, y la buena (2026-08-17). Antes fueron tres cajas
   iguales («muy de IA») y luego filas alternas con el número a tamaño de
   titular. Carlos: «que los 1 2 3 sean card que se montan uno encima de
   otro como los que venimos usando, quita los números grandes, y el
   tamaño del título como las del home».

   ⭐ EL APILADO: cada tarjeta se queda PEGADA y la siguiente sube por
   encima, escalonada unos píxeles para que se vea el filo de la de
   abajo — el mismo recurso de las escenas pegadas del sitio, sin GSAP ni
   pin: `position: sticky` y lo resuelve el navegador.

   ⚠️ El escalón lo pone `--i` desde el HTML. Sin él, las tres se pegarían
   a la MISMA altura y no se vería que hay tres, sólo la última.

   ⚠️ En MÓVIL no se apilan: se deslizan. Es la ley de la casa, y aquí
   además el apilado triplicaría el scroll de la página.

   ⚠️ Los títulos van a la escala de las tarjetas del home (21px), no a la
   de sección: dentro de una tarjeta, un título de 34 compite con el
   titular de la sección que la contiene.
   ===================================================================== */
.zonas__titulo {
  font-size: var(--t-seccion); line-height: 1.05;
  margin: 0 0 clamp(24px, 3vw, 44px);
  text-transform: uppercase; letter-spacing: -.015em;
  text-wrap: balance;
}

/* ── Móvil: carrusel ───────────────────────────────────────────────── */
.zonas__lista {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 16px;
  grid-auto-flow: column; grid-auto-columns: 80%;
  overflow-x: auto; scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--aire);
  padding-inline: var(--aire); padding-bottom: 8px;
  scrollbar-width: none;
}
.zonas__lista::-webkit-scrollbar { display: none; }
.zona { scroll-snap-align: start; scroll-snap-stop: always; }

.zona__card {
  height: 100%;
  background: var(--fondo-alto);
  border: 1px solid var(--borde);
  overflow: hidden;
  display: flex; flex-direction: column;
}
.zona__foto img {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block;
}
.zona__texto { padding: clamp(20px, 2.2vw, 30px); }
.zona__titulo { font-size: var(--t-tarjeta); margin: 0; }
.zona__cuerpo {
  margin: .7em 0 0; color: var(--texto-suave); font-size: var(--t-cuerpo);
}

/* ── Escritorio: se apilan ─────────────────────────────────────────── */
@media (min-width: 900px) {
  .zonas__lista {
    grid-auto-flow: row; grid-template-columns: 1fr;
    overflow: visible; padding-inline: 0;
    gap: clamp(26px, 3vw, 46px);
    /* ⚠️ Poco aire por debajo: con las tres tarjetas el recorrido ya lo
       dan ellas. Con 140px la última se quedaba pegada arriba, sola y
       flotando sobre el hueco, mucho después de que la escena acabara. */
    padding-bottom: clamp(20px, 3vh, 48px);
  }

  .zona {
    position: sticky;
    top: calc(var(--alto-cabecera) + 32px + var(--i, 0) * 26px);
    max-width: var(--ancho); margin-inline: auto; width: 100%;
    padding-inline: var(--aire);
  }

  .zona__card {
    flex-direction: row; align-items: stretch;
    /* Alto suficiente para que el apilado se LEA. Con tarjetas bajas se
       ven las tres a la vez y no se percibe que una tapa a la otra. */
    min-height: clamp(320px, 46vh, 420px);
    /* La sombra es lo que hace legible el apilado: sin ella, tres cajas
       montadas se leen como una sola caja larga. */
    box-shadow: 0 -1px 0 var(--borde), 0 -18px 40px rgb(51 34 24 / .13);
  }
  .zona__foto {
    flex: 0 0 46%;
    /* el filo de ola de la casa, en el corte entre foto y texto */
    clip-path: var(--ola-marca);
    transform: scaleX(-1);
  }
  .zona__foto img { height: 100%; aspect-ratio: auto; transform: scaleX(-1); }
  .zona__texto {
    flex: 1 1 auto;
    display: flex; flex-direction: column; justify-content: center;
    padding: clamp(30px, 3.4vw, 52px);
  }
  /* ⚠️ Sólo el ancho de línea: el cuerpo ya lo pone `--t-cuerpo` y
     antes esto lo subía a 1.02rem, que era un décimo tamaño más.
     ⭐ 2026-08-21: el tope se va —le sobraban 94px de su propia
     columna— y el texto pasa a justificado, como el resto del sitio. */
  .zona__cuerpo { max-width: none; text-align: justify; }
}

/* =====================================================================
   CANCÚN · LA PÁGINA DE DESTINO
   =====================================================================
   Existe para quien busca el destino, no la marca. Se construye con lo
   que ya hay —la ficha de la casa, las tres cartas, la prensa y el
   blog— y su único componente propio es el bloque de «dónde estamos».
   ===================================================================== */
/* La foto volvió el 2026-08-19 (Carlos: «debe de 50 50 o con efecto»),
   pero no como estaba: ahora sale del ancho de la caja y llega al filo de
   la ventana, y se mueve despacio dentro de su marco. Los detalles, en el
   bloque de dos columnas de más abajo. */
.cancun-donde__interior { display: block; }
.cancun-donde__texto h2,
.cancun-comer h2,
.cancun-planes h2,
.destino-zona__texto h2,
.destino-dosaguas__panel h2 {
  /* versalitas como el resto de títulos de sección, a la escala de las
     páginas interiores */
  text-transform: uppercase; letter-spacing: -.015em;
  font-size: var(--t-seccion); line-height: 1.05;
  text-wrap: balance;
}
.cancun-donde__texto h2 { margin: 0 0 .6em; }
/* ⭐ EL TEXTO LLEGA HASTA LA LÍNEA — Carlos, 2026-08-21: «vamos a
   justificarlo, pero vamos a ampliar el contenedor de texto y llevarlo
   hasta donde llega la línea que separa descripción y ficha».
   Esa línea es el `border-top` de `.cancun-ficha` y ocupa la columna
   entera, así que lo único que hacía falta era quitarle el tope de
   lectura al párrafo: `--medida` son 62ch y lo cortaba antes.
   ⚠️ Es una EXCEPCIÓN al ancho de lectura de la casa, y se sostiene
   porque aquí la columna ya es media página: el renglón se queda en
   ~86 caracteres, no en la línea infinita que `--medida` evita. */
.cancun-donde__texto p {
  max-width: none; margin-bottom: 1em;
  text-align: justify;
}

.cancun-ficha {
  list-style: none; margin: clamp(26px, 3vw, 40px) 0 0; padding: 0;
  display: grid; gap: 18px 40px;
  border-top: 1px solid var(--borde); padding-top: clamp(20px, 2.4vw, 28px);
}
@media (min-width: 760px) {
  .cancun-ficha { grid-template-columns: repeat(3, auto); justify-content: start; }
}
.cancun-ficha li { display: grid; gap: 4px; }
.cancun-ficha address { font-style: normal; }
.cancun-ficha a { color: var(--acento-tinta); }
.cancun-ficha__rotulo {
  font-family: var(--titulo); font-size: var(--t-rotulo); font-weight: 600;
  letter-spacing: .22em; text-transform: uppercase; color: var(--texto-suave);
}
/* ⛔ `.cancun-donde__acciones` — la fila de «Cómo llegar» + «Reservar»
   de esta sección. Los dos botones se fueron el 2026-08-21 al entrar el
   mapa (ver `_vistas/destino.php`); la regla se queda escrita porque la
   sigue nombrando el bloque de centrado del móvil, y porque si vuelven,
   vuelven así. */
.cancun-donde__acciones { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 1.8em; }

.cancun-donde__foto { margin: 0; }
.cancun-donde__marco { display: block; }
.cancun-donde__foto img {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block;
}

/* ── EL MAPA DE GOOGLE, EN EL TONO DE LA CASA ───────────────────────
   Carlos, 2026-08-21: «dale filtro de color que vaya con el tono».
   Google sirve su mapa en su azul y su verde, y ahí dentro se lee como
   una ventana a otra web.

   ⛔ NO se hace con `sepia()`. Se probaron cinco recetas de filtro y
   todas fallan por el mismo sitio: el sepia iguala la LUZ del agua y de
   la tierra, y el mapa pierde lo único que tiene que decir de un
   vistazo, que es dónde acaba la laguna. Con sepia al 70% ya no se
   distinguían.

   ⭐ Se hace con una capa de TERRACOTA en `mix-blend-mode: color`: esa
   mezcla se queda con el TONO de la capa y respeta la LUMINOSIDAD de lo
   que hay debajo. El mapa entero pasa a la gama de la casa —un duotono—
   y el agua se sigue distinguiendo de la tierra porque es más oscura,
   no porque sea azul.

   ⚠️ `pointer-events: none` no es un detalle: sin él la capa se come el
   arrastre y el mapa queda muerto.
   ⚠️ `isolation: isolate` encierra la mezcla en el marco. Sin eso, el
   blend busca el fondo de la página y tiñe lo que hay detrás.

   Se afina en vivo con `?mapa` en la URL. */
:root {
  --mapa-tinte:   var(--acento);
  --mapa-fuerza:  .85;   /* cuánto tira del tono de la casa */
  --mapa-color:   .92;   /* saturación base, antes de teñir */
  --mapa-luz:    1.02;
}
.cancun-mapa .cancun-donde__marco {
  position: relative; isolation: isolate;
  filter: saturate(var(--mapa-color)) brightness(var(--mapa-luz));
}
.cancun-mapa .cancun-donde__marco::after {
  content: ""; position: absolute; inset: 0;
  background: var(--mapa-tinte);
  mix-blend-mode: color;
  opacity: var(--mapa-fuerza);
  pointer-events: none;
}
.cancun-mapa iframe {
  width: 100%; aspect-ratio: 4 / 3; display: block;
  border: 0;
  /* El mapa es una superficie, no una foto: mientras carga se ve el
     papel de la casa y no un rectángulo blanco. */
  background: var(--fondo-hondo);
}
/* ⚠️ En móvil el mapa se queda más bajo: a 4/3 ocupaba casi una pantalla
   entera y empujaba fuera todo lo que viene después. */
@media (max-width: 599px) {
  .cancun-mapa iframe { aspect-ratio: 4 / 3.4; }
}
.cancun-donde__foto figcaption {
  margin-top: 10px; font-size: var(--t-apoyo); color: var(--texto-suave);
}

/* ── LAS DOS COLUMNAS DE «DÓNDE ESTAMOS» ────────────────────────────
   Carlos, 2026-08-19: «no está bien, debe de 50 50 o con efecto».
   Las dos cosas: mitad y mitad, y la foto moviéndose despacio dentro de
   su marco al bajar (`.parallax-foto`, el JS le escribe `--p`).

   ⭐ LA FOTO SALE DE LA CAJA. Se estira hasta el filo derecho de la
   ventana con un margen negativo calculado —`50% - 50vw` es justo lo que
   sobra del contenedor a cada lado—, y por eso esta sección no se lee
   como otra de dos columnas más: es la única de la página que rompe el
   ancho. ⚠️ `100vw` incluye la barra de scroll y abriría desborde
   horizontal; el margen negativo, no.

   ⚠️ La ficha (dirección · horario · teléfono) pasa a COLUMNA aquí: en
   fila de tres dentro de media página, «Blvd. Kukulcán Km 14.5, Hotel
   Zone, Cancún, Mexico» se parte en tres líneas y deja de leerse como un
   dato. */
@media (min-width: 1000px) {
  /* ⚠️ LA FOTO SE QUEDA DENTRO DE LA CAJA. Hubo un rato en que salía del
     ancho y llegaba al filo de la ventana; Carlos, 2026-08-19: «esa foto
     está muy pegada al borde». Ahora acaba en la misma columna que el
     resto del contenido de la página, que es lo que hace que un sitio se
     lea alineado.

     ⛔ Y de aquel intento queda escrito lo que NO se debe hacer para
     sacar una foto de la caja, que costó dos vueltas: `calc(50% - 50vw)`
     falla por partida doble —dentro de una rejilla el `50%` se mide
     contra la COLUMNA y no contra el contenedor (la foto se pasaba 315px
     de la ventana), y `100vw` incluye la barra de scroll, que abre
     desborde horizontal—. La forma buena era `padding-inline` en la caja
     con la cuenta de `.contenedor`. */
  .cancun-donde__interior {
    display: grid; grid-template-columns: 1fr 1fr;
    gap: clamp(40px, 4.5vw, 80px); align-items: center;
  }
  .cancun-donde__marco {
    display: block; overflow: hidden;   /* el marco que recorta el paralaje */
  }
  .cancun-donde__foto img {
    aspect-ratio: auto; height: min(72svh, 640px);
    /* ⚠️ EL RECORRIDO TIENE QUE CABER EN EL SOBRANTE. La imagen se
       agranda un 15%, así que a cada lado sobran (640 × .15) / 2 = 48px;
       moverla 38 deja diez de margen. Con 1.12 y 46 —lo primero que
       puse— sobraban 38 y se movía 46: por los extremos del recorrido
       asomaba el fondo por el canto. */
    scale: 1.15;
    translate: 0 calc(var(--p, 0) * -38px);
    will-change: translate;
  }
  .cancun-donde__interior .cancun-ficha { grid-template-columns: 1fr; gap: 14px; }
  /* ⛔ Aquí el párrafo tenía `max-width: 46ch`, que es lo que lo dejaba
     acabando un palmo antes que la línea de la ficha. Se quitó el
     2026-08-21: ahora los dos acaban en el mismo sitio. */
}
/* ⚠️ Aquí las fotos llevaban el filo de ola de la marca y se retiró el
   2026-08-17: sobre una foto entera —no sobre el borde de una tarjeta—
   el recorte se come media imagen y se lee como un error de máscara, no
   como un motivo. Carlos: «estas fotos están feas». En su lugar va la
   GALERÍA (ver más abajo). La ola sigue donde sí funciona: el filo de
   las tarjetas de Kids. */
.cancun-donde__foto figcaption {
  margin-top: .7em; font-size: .88rem; color: var(--texto-suave);
}

/* Las tres cartas, en fila de fichas. No repiten las portadas del índice:
   aquí sólo hacen de puente, y una tarjeta con foto competiría con el
   bloque de arriba. */
.cancun-comer h2 { margin: 0 0 .55em; }
/* La entrada llena su columna y va justificada, como el resto de la
   página desde el 2026-08-21. Le sobraban 176px. */
.cancun-comer__entrada { max-width: none; text-align: justify; }
.cancun-cartas {
  list-style: none; margin: clamp(28px, 3vw, 40px) 0 0; padding: 0;
  display: grid; gap: 12px;
}
/* ⚠️ La CIFRA es el argumento: «55 platillos» dice más que el nombre de
   la carta, y en este sitio los dígitos son Verdana. Antes iba en
   versalitas de 13px al pie de una cajita y no la leía nadie. */
.cancun-cartas a {
  display: flex; flex-direction: column; gap: .3em;
  padding: clamp(18px, 2vw, 24px) 0;
  background: none; border: 0; border-top: 1px solid var(--borde);
  text-decoration: none; color: var(--texto);
  transition: border-color .26s var(--curva), transform .26s var(--curva);
}
.cancun-cartas a:hover { border-color: var(--acento); }
.cancun-cartas a:hover .cancun-cartas__nombre { color: var(--acento-tinta); }
.cancun-cartas__nombre {
  font-family: var(--titulo); font-size: clamp(1.3rem, 2.2vw, 1.65rem);
  transition: color .26s var(--curva);
}
/* ⭐ LA ACCIÓN, en el sitio donde estaba la cifra (2026-08-19).
   Carlos: «en vez de item diga see menu y te envíe al menú». La fila
   entera era ya un enlace a la carta, pero no lo decía en ninguna parte:
   la cifra informaba —«55 items»— y no invitaba a pulsar.

   ⚠️ NO se pinta como la cifra que sustituye. Un «SEE MENU» a 2,1rem en
   negrita gritaría más que el nombre de la carta, que es lo que hay que
   leer primero; va en versalitas de botón, que es el traje que esta casa
   le pone a las acciones. La flecha se separa al pasar por encima: el
   único movimiento, y sólo con el puntero. */
/* ⭐ LA FOTO DE CADA CARTA, EN SU MARCO (2026-08-19)
   Carlos: «coloca las fotos en un marco o algo, un efecto».

   El marco es una caja que recorta y la foto vive DENTRO, más grande de
   lo que se ve: al pasar por encima la foto se acerca despacio y el
   marco no se mueve ni un píxel. Es el mismo gesto que la portada usa en
   sus fotos, con lo cual no hay vocabulario nuevo.

   ⚠️ El zoom va en la IMAGEN y el recorte en el marco. Al revés —dando
   `scale` al marco— se movería la fila entera y la lista dejaría de
   alinearse.
   ⚠️ La foto es decorado: `alt=""`. El nombre de la carta está al lado y
   en texto. */
.cancun-cartas__marco {
  flex: 0 0 auto;
  display: block; overflow: hidden;
  width: clamp(64px, 7vw, 88px); aspect-ratio: 4 / 5;
  background: var(--fondo-hondo);
  outline: 1px solid var(--borde); outline-offset: 0;
  transition: outline-color .3s var(--curva);
}
.cancun-cartas__marco img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  scale: 1.06;
  transition: scale .55s var(--curva);
}
@media (hover: hover) and (pointer: fine) {
  .cancun-cartas a:hover .cancun-cartas__marco img { scale: 1.16; }
}
.cancun-cartas a:hover .cancun-cartas__marco { outline-color: var(--acento); }

.cancun-cartas__texto {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: column; gap: 6px;
}
@media (min-width: 560px) {
  .cancun-cartas__texto {
    flex-direction: row; align-items: baseline;
    justify-content: space-between; gap: 16px;
  }
}
/* ⭐ En el teléfono, nombre y botón van al CENTRO de su hueco (2026-09-15).
   Apilados y a la izquierda dejaban 170 px vacíos a la derecha de cada
   fila, contra la ley del móvil («todo al centro»). La foto no se mueve:
   se centra lo que queda a su lado. */
@media (max-width: 559px) {
  .cancun-cartas .cancun-cartas__texto { align-items: center; text-align: center; }
  /* ⚠️ Con el padre delante: la caja del botón se declara MÁS ABAJO con
     `align-self: flex-start` y, a igual especificidad, ganaba ella. */
  .cancun-cartas .cancun-cartas__accion { align-self: center; }
}
/* ⭐ Carlos, 2026-08-21: «igual al de Book a table». Era una palabra con
   flecha y ahora es el botón de la casa, con su relleno naranja.
   ⚠️ NO se le puede poner la clase `.boton` en el HTML: esto vive DENTRO
   del `<a>` de la tarjeta —un botón dentro de un enlace no es válido—,
   así que se le da aquí la misma caja y el mismo color. */
.cancun-cartas__accion {
  font-family: var(--titulo); font-size: var(--t-boton);
  text-transform: uppercase; letter-spacing: .16em; font-weight: 600;
  background: var(--boton); color: var(--boton-tinta);
  border: 1px solid var(--boton-borde);
  padding: 12px 20px;
  display: inline-flex; align-items: center; gap: .7em;
  white-space: nowrap; align-self: flex-start;
  transition: background .22s var(--curva-color), border-color .22s var(--curva-color);
}
.cancun-cartas a:hover .cancun-cartas__accion {
  background: var(--boton-honda); border-color: var(--boton-honda);
}
.cancun-cartas__accion::after {
  content: "→";
  transition: translate .26s var(--curva);
}
.cancun-cartas a:hover .cancun-cartas__accion::after { translate: 5px 0; }

/* ⚠️ La cifra es TEXTO que informa, no adorno: va en la terracota de
   tinta y a plena opacidad. En terracota plana y al 50% se quedaba en
   1,5:1 sobre el papel — ilegible, por muy grande que fuera. (Se retiró
   de `/cancun/` el 2026-08-19; la regla se queda por si vuelve a hacer
   falta en otra lista.) */
.cancun-cartas__dato {
  font-family: var(--cuerpo); font-weight: 700;
  font-size: clamp(1.4rem, 2.8vw, 2.1rem); line-height: 1;
  color: var(--acento-tinta);
  letter-spacing: -.02em; text-transform: none;
}

/* Con quién vienes: tres planes. En móvil, carrusel (ley de la casa). */
.cancun-planes h2 { margin: 0 0 clamp(28px, 3.4vw, 48px); }
.cancun-planes__lista {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 16px;
  grid-auto-flow: column; grid-auto-columns: 76%;
  overflow-x: auto; scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--aire);
  padding-inline: var(--aire); margin-inline: calc(var(--aire) * -1);
  padding-bottom: 8px; scrollbar-width: none;
}
.cancun-planes__lista::-webkit-scrollbar { display: none; }
/* Igual que las citas: el filete de arriba ordena, la caja sobraba. */
.cancun-plan {
  scroll-snap-align: start; scroll-snap-stop: always;
  background: none; border: 0; border-top: 2px solid var(--acento);
  padding: clamp(20px, 2.2vw, 28px) 0 0;
  display: flex; flex-direction: column; gap: .7em;
}
.cancun-plan h3 { font-size: var(--t-tarjeta); margin: 0; }
.cancun-plan p { color: var(--texto-suave); margin: 0; }
.cancun-plan__enlace {
  margin-top: auto; align-self: flex-start;
  font-family: var(--titulo); font-size: .84rem; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--acento-tinta); text-decoration: none;
  border-bottom: 1px solid var(--acento); padding-bottom: 3px;
  /* zona de toque cómoda sin inflar la caja visual */
  display: inline-flex; align-items: center; min-height: 44px;
}
.cancun-plan__enlace:hover { color: var(--tinta); border-color: var(--tinta); }

@media (min-width: 860px) {
  .cancun-cartas { grid-template-columns: repeat(3, 1fr); gap: 16px; }
  .cancun-cartas a { flex-direction: column; align-items: flex-start; gap: 8px; }
  .cancun-planes__lista {
    grid-auto-flow: row; grid-template-columns: repeat(3, 1fr);
    overflow: visible; padding-inline: 0; margin-inline: 0;
    gap: clamp(18px, 2vw, 28px);
  }
}

/* ── La zona, dentro de la página de destino ────────────────────────
   La Riviera Maya se cuenta aquí, no en una página aparte. (Desde el
   2026-08-19 vive dentro de la escena de dos aguas, aquí debajo; estas
   reglas quedan por si el bloque vuelve a usarse suelto en otro
   destino.) */
.destino-zona__interior { display: block; }
.destino-zona__texto h2 { margin: 0 0 .6em; }
.destino-zona__texto p { max-width: var(--medida); margin-bottom: 1em; }
.destino-zona__foto { margin: 0; }
.destino-zona__foto img {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block;
}

/* =====================================================================
   LA ESCENA DE DOS AGUAS — la foto quieta y el texto que se releva
   =====================================================================
   Carlos, 2026-08-19: «estas dos partes pueden parecer un carrusel de
   arriba abajo con la imagen de un lado fija y sólo cambie la info del
   lado izquierdo».

   ⭐ NO HAY JAVASCRIPT. El relevo lo hace `position: sticky`: la foto se
   queda clavada mientras su columna vecina —que es más alta que ella—
   sigue subiendo. El navegador lo resuelve en el compositor, va pegado
   al dedo y no hay nada que se pueda desincronizar.

   ⚠️ La columna de texto tiene que ser MÁS ALTA que la foto o no hay
   nada que pegar: si algún día un destino se queda con un solo panel, la
   foto simplemente no se pega y la sección se lee como cualquier otra de
   dos columnas. Por eso los paneles piden altura mínima en vez de altura
   fija.

   ⚠️ El `top` cuenta con la cabecera, que va fija: sin sumarla, la foto
   se pega DEBAJO del menú y se le come el filo.

   Móvil aparte, más abajo: allí no hay dos columnas que pegar. */
.destino-dosaguas__interior { display: block; }
.destino-dosaguas__panel h2 { margin: 0 0 .6em; }
/* ⭐ EL ACOMODO DEL TEXTO — Carlos, 2026-08-21
   =====================================================================
   «Tiene que ser todo el texto de la página de Cancún, porque arriba
   está bien pero lo de Riviera Maya no; hazle ese acomodo a todas las
   secciones menos el home.»

   El acomodo son DOS cosas, y no van siempre juntas:
     · el texto LLENA su columna, en vez de quedarse un palmo antes;
     · y va JUSTIFICADO.

   ⚠️ Lo primero SÓLO donde el texto vive en una columna. Se le preguntó
   a Carlos por las secciones de ancho completo —«Villas exclusivas» de
   Grupos tiene sitio para 155 caracteres por renglón— y eligió dejarlas
   como están: ahí el texto conserva su medida de lectura y el hueco de
   la derecha. Justificado sí, estirado no.

   Se midió el sitio entero antes de tocar nada: de todo el texto
   corrido de las páginas que no son la portada, sólo TRES bloques se
   quedaban cortos dentro de su propia columna. Son los de aquí. */
.destino-dosaguas__panel p {
  max-width: none; margin-bottom: 1em;   /* llena la columna: le sobraban 176px */
  text-align: justify;
}
.destino-dosaguas__foto { margin: 0; }
.destino-dosaguas__foto img {
  width: 100%; object-fit: cover; display: block;
}

@media (min-width: 900px) {
  .destino-dosaguas__interior {
    display: grid;
    /* La foto no baja de 380px ni pasa de 44%: por debajo se vuelve una
       tira y por encima le come el ancho de lectura al texto. */
    grid-template-columns: 1fr clamp(380px, 42%, 560px);
    gap: clamp(40px, 4.5vw, 84px);
    align-items: start;
  }
  .destino-dosaguas__columna { display: grid; }
  /* Cada panel ocupa casi una pantalla y se centra frente a la foto: así
     el paso de uno a otro se lee como un relevo y no como dos párrafos
     seguidos. `align-content` y no `justify-content`: lo que se centra es
     el bloque dentro de su alto. */
  .destino-dosaguas__panel {
    /* ⚠️ Un pelo MÁS BAJO que la foto a propósito. Con la misma altura,
       el panel corto centrado dejaba 180px de vacío por arriba y otros
       180 por abajo, y ese hueco entre los dos textos se leía como el
       espacio en blanco que veníamos a quitar. */
    min-height: min(62svh, 545px);
    display: grid; align-content: center;
    padding-block: clamp(24px, 3vw, 44px);
  }
  /* ⛔ Aquí había `max-width: 46ch`, el mismo tope que tenía «Where we
     are»: es lo que dejaba el texto acabando antes que su columna. */
  .destino-dosaguas__foto {
    position: sticky;
    top: calc(var(--alto-cabecera) + clamp(16px, 2.4vw, 40px));
  }
  .destino-dosaguas__foto img {
    height: min(74svh, 660px);
  }
  /* Las tres cartas caben en columna dentro de media página: en fila de
     tres se quedaban en 120px cada una y la cifra —que es el argumento—
     no tenía sitio. */
  .destino-dosaguas .cancun-cartas { grid-template-columns: 1fr; gap: 0; }
  .destino-dosaguas .cancun-cartas a { flex-direction: row; align-items: center;
    justify-content: flex-start; gap: clamp(14px, 1.6vw, 22px); }
}

/* La fila de una carta es SIEMPRE horizontal —foto a un lado, nombre y
   acción al otro—, también en el móvil: apilada, cada una medía casi
   media pantalla y las tres se leían como tres bloques sueltos en vez de
   como una lista. */
.cancun-cartas a {
  flex-direction: row; align-items: center;
  gap: clamp(14px, 3.5vw, 22px);
}

/* En móvil no hay dos columnas que pegar: la foto sube al principio —es
   lo que sitúa antes de contar nada— y los dos paneles caen debajo, uno
   detrás de otro. Nada de pegar aquí: en una pantalla estrecha una foto
   clavada se come la mitad del sitio que necesita el texto. */
@media (max-width: 899px) {
  .destino-dosaguas__interior { display: grid; gap: clamp(26px, 5vw, 38px); }
  .destino-dosaguas__foto { order: -1; }
  .destino-dosaguas__foto img { height: min(58svh, 460px); }
  .destino-dosaguas__panel + .destino-dosaguas__panel {
    margin-top: clamp(30px, 7vw, 48px);
  }
}



/* ── TODOS LOS TÍTULOS DE SECCIÓN, A LA MISMA ESCALA ────────────────
   Los de la portada llevaban su propio tamaño desde que se montaron sus
   escenas, y con las páginas interiores al día se veía el desajuste: dos
   títulos del mismo rango medían 34 y 54. Se igualan aquí, al final, para
   que no haya que ir persiguiendo el `font-size` dentro de cada escena.
   ⚠️ NO entran los que no son títulos de sección: el titular de una nota
   de prensa, el de una tarjeta de blog, el del modal y los rótulos de la
   ficha de reservas tienen su propio tamaño a propósito. */
.propuesta__texto h2,
.pase__texto h2,
.galeria__cabeza h2,
.grupos-home__texto h2,
.blog-home h2,
.cierre-carta h2 {
  font-size: var(--t-seccion);
  line-height: 1.02;
  letter-spacing: -.015em;
}

/* =====================================================================
   LA PLECA DE PRENSA — las cabeceras de los medios
   =====================================================================
   Carlos, 2026-08-17: «¿dónde está prensa en el home con los logos?», y
   luego «título igual que los demás y que sea por lo menos en slider».

   ⚠️ Los logos vienen a UNA TINTA y en el MISMO LIENZO (520×150) desde
   `generar-logos-prensa.py`, ya equilibrados por área. Aquí sólo se les
   da un ancho: si se normalizara el alto, «EL FINANCIERO» saldría tres
   veces más ancho que «FOOD & TRAVEL».

   LA CINTA: dos filas idénticas desfilando juntas. Cuando la primera
   termina de salir por la izquierda, la segunda está justo detrás y el
   bucle no tiene costura. La animación mueve `transform`, que va en el
   compositor: no repinta ni recalcula nada en cada fotograma.
   ===================================================================== */
.pleca-prensa {
  padding-block: clamp(44px, 5vw, 76px);
  border-block: 1px solid var(--borde);
  overflow: hidden;   /* la cinta sale del ancho a propósito */
}
/* Título de sección como el resto de la portada, no un rótulo pequeño. */
.pleca-prensa__titulo {
  font-size: var(--t-seccion);
  line-height: 1.05; letter-spacing: -.015em;
  text-transform: uppercase; text-align: center;
  margin: 0 0 clamp(28px, 3.4vw, 48px);
  text-wrap: balance;
}

.pleca-prensa__cinta {
  --hueco-pleca: clamp(28px, 4vw, 64px);
  display: flex; gap: var(--hueco-pleca);
  width: max-content;
  /* Los bordes se desvanecen: sin esto, los logos aparecen y desaparecen
     de golpe contra el filo de la pantalla. */
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.pleca-prensa__fila {
  list-style: none; margin: 0; padding: 0;
  display: flex; align-items: center; gap: var(--hueco-pleca);
  flex: 0 0 auto;
  animation: pleca-desfile 44s linear infinite;
}
@keyframes pleca-desfile {
  to { transform: translateX(calc(-100% - var(--hueco-pleca))); }
}
/* Al pasar por encima se para: si alguien quiere leer una cabecera, que
   pueda. */
.pleca-prensa:hover .pleca-prensa__fila,
.pleca-prensa:focus-within .pleca-prensa__fila { animation-play-state: paused; }

/* Un 20% más grandes — Carlos, 2026-08-17. Del clamp(96, 9vw, 118) al
   clamp(115, 10.8vw, 142). Al desfilar en cinta ya no hay que hacerlos
   caber en una fila, así que el tope lo pone la legibilidad. */
.pleca-prensa__fila img {
  /* ⭐ Un 50% más grandes en escritorio (Carlos, 2026-08-18): el rango
     entero sube —115/10,8vw/142 pasa a 172/16,2vw/213—, así que escala
     igual en cualquier ancho. El `height: auto` es lo que conserva la
     proporción de cada cabecera: no se deforma ninguna.
     ⚠️ En el teléfono manda la regla de más abajo, que los deja en 155. */
  width: clamp(172px, 16.2vw, 213px); height: auto;
  /* Un punto por debajo del negro: son marcas ajenas, acompañan y no
     compiten con la tinta de los titulares de la casa. */
  opacity: .62;
  transition: opacity .3s var(--curva);
}
.pleca-prensa__fila li:hover img { opacity: 1; }

/* ⚠️ Sin movimiento automático, la cinta se desliza A MANO. Quien pide
   menos animación no pide menos contenido: si la fila se quedara quieta,
   los logos que se salen del ancho no habría forma de verlos. */
@media (prefers-reduced-motion: reduce) {
  .pleca-prensa__fila { animation: none; }
  .pleca-prensa__fila[aria-hidden="true"] { display: none; }
  .pleca-prensa__cinta {
    width: auto; overflow-x: auto;
    scroll-snap-type: x proximity;
    padding-inline: var(--aire); scrollbar-width: none;
  }
  .pleca-prensa__cinta::-webkit-scrollbar { display: none; }
  .pleca-prensa__fila li { scroll-snap-align: center; scroll-snap-stop: always; }
}

/* ⭐ Carlos, 2026-08-21: esto era un enlace con flecha y ahora es un
   BOTÓN. Todo lo que lo pintaba —familia, cuerpo, tinta, versalitas—
   lo trae ya `.boton .boton--principal`; aquí sólo se queda lo que es
   propio de su sitio: que se centre en la pleca y su aire de arriba.
   ⚠️ Es `inline-flex`, no `flex`: en `flex` el botón se estiraba a todo
   el ancho del contenedor y dejaba de parecer un botón. */
.pleca-prensa__enlace {
  display: inline-flex; align-items: center; gap: 10px;
  margin-top: clamp(24px, 3vw, 38px);
  min-height: 44px;
}
/* El centrado lo pone el contenedor, no el botón. */
.pleca-prensa .contenedor:has(> .pleca-prensa__enlace) { text-align: center; }
.pleca-prensa__enlace svg { width: 18px; height: 18px; transition: transform .26s var(--curva); }
.pleca-prensa__enlace:hover svg { transform: translateX(4px); }

/* La cabecera del medio dentro de la cita: mismo logo, alineado a la
   izquierda y algo mayor, que aquí sí es el sello de quién habla. */
.prensa-cita__logo {
  width: clamp(118px, 12vw, 152px); height: auto;
  opacity: .78; margin: 0 0 .3em -6px;   /* -6px: el lienzo trae aire propio */
  align-self: flex-start;
}

/* =====================================================================
   RESEÑAS — tarjetas en carrusel
   =====================================================================
   Carlos, 2026-08-17: «esto son reseñas de personas, quita los logos de
   prensa y hazlo quizás en card para que tenga slider, y usa otro tipo
   de letra».

   ⭐ LA LETRA ES LO QUE LAS DISTINGUE. La cita va en VERDANA y la firma
   en Georgia — justo al revés que las citas de prensa, donde la cita es
   Georgia y el medio va en versalitas. Así se sabe de un vistazo si
   habla una persona o un medio, y sin sacar una tercera familia: el PSD
   de la marca sólo tiene esas dos.

   ⚠️ Carrusel SIEMPRE, también en escritorio. Las reseñas no son tres
   fijas: son una lista que crece, y una rejilla obliga a elegir cuántas
   caben. Con el carrusel entran las que haya.
   ===================================================================== */
/* ── EL FONDO ───────────────────────────────────────────────────────
   Carlos, 2026-08-17: «la sección de blog en el home tiene muchas
   secciones seguidas… mejor a reseñas ponle fondo de fotografía blur».

   Es la fachada de noche, desenfocada: la única foto NOCTURNA del sitio,
   así que corta de verdad la sucesión de bloques claros. Desenfocada
   pesa 9 KB —el desenfoque no necesita resolución— y no compite con las
   tarjetas, que es lo que hay que leer.

   ⚠️ Sigue siendo una web clara: esto es un acento, como el hero y la
   banda de bienvenida. No se pinta oscura la página, se pinta oscura
   UNA sección.

   ⚠️ El velo está MEDIDO, no elegido a ojo: el titular va en blanco y
   sobre los neones dorados de la foto sin velo se quedaba corto. */
.resenas {
  position: relative; isolation: isolate;
  color: var(--sobre-hondo);
  background: var(--marron);        /* mientras carga, nunca blanco */
}
.resenas::before {
  content: ""; position: absolute; inset: 0; z-index: -2;
  /* ⛔ Relativa, no absoluta: con el sitio en una subcarpeta la absoluta
     da 404 y la sección se queda sin fondo. Misma trampa que el logo. */
  background: url('../img/marca/fondo-resenas.webp') center / cover no-repeat;
}
.resenas::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(180deg, rgb(35 22 14 / .42), rgb(35 22 14 / .18) 45%, rgb(35 22 14 / .50)),
    rgb(124 83 62 / .28);
}

.resenas__cabeza {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: clamp(26px, 3.2vw, 44px);
}
.resenas__cabeza h2 {
  font-size: var(--t-seccion); margin: 0; line-height: 1.05;
  text-transform: uppercase; letter-spacing: -.015em;
}
/* Sobre el fondo oscuro, la tinta terracota desaparece: va en crema. */
.resenas__todas {
  display: inline-flex; align-items: center; gap: 8px; margin-left: auto;
  color: var(--crema); text-decoration: none;
  font-family: var(--titulo); font-weight: 600;
  font-size: .92rem; letter-spacing: .04em; text-transform: uppercase;
}
.resenas__todas svg { width: 18px; height: 18px; transition: transform .26s var(--curva); }
.resenas__todas:hover svg { transform: translateX(4px); }

.resenas__lista {
  list-style: none; margin: 0; padding: 0;
  /* El hueco entre tarjetas, con nombre: hace falta para calcular cuánto
     mide cada una si se quieren DOS por pantalla. */
  --hueco: clamp(14px, 1.6vw, 22px);
  display: grid; gap: var(--hueco);
  grid-auto-flow: column;
  grid-auto-columns: min(84%, 380px);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: max(var(--aire), (100vw - var(--ancho)) / 2 + var(--aire));
  padding-inline: max(var(--aire), (100vw - var(--ancho)) / 2 + var(--aire));
  padding-bottom: 10px;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.resenas__lista::-webkit-scrollbar { display: none; }

/* ⭐ DOS RESEÑAS POR PANTALLA EN ESCRITORIO — Carlos, 2026-08-18:
   «en desktop las reseñas están grandes, que sólo aparezcan dos y las
   demás en carrusel». Con los 380px de antes entraban TRES en 1440 y la
   cuarta asomaba; ahora cada tarjeta ocupa la mitad del ancho útil —el
   contenedor menos su aire y menos el hueco— y el resto sigue estando,
   sólo que deslizando.
   ⚠️ Es el único cambio de la jornada que toca el escritorio, y se hace
   porque lo pidió expresamente. */
@media (min-width: 900px) {
  .resenas__lista {
    grid-auto-columns: calc((min(100vw, var(--ancho)) - var(--aire) * 2 - var(--hueco)) / 2);
  }
}
.resena { scroll-snap-align: start; scroll-snap-stop: always; }

.resena__caja {
  margin: 0; height: 100%;
  background: var(--fondo-alto);
  border: 1px solid var(--borde);
  padding: clamp(26px, 2.8vw, 36px);
  display: flex; flex-direction: column; gap: 1.1em;
  position: relative;
}
/* La comilla, de adorno y detrás. */
.resena__caja::before {
  content: '“';
  position: absolute; top: .04em; right: .18em;
  font-family: var(--titulo); font-size: 4.2rem; line-height: 1;
  color: var(--acento); opacity: .16; pointer-events: none;
}

.resena__estrellas {
  margin: 0; color: var(--acento); font-size: 1rem; letter-spacing: .12em;
}
.resena__estrellas .apagada { opacity: .28; }

/* ⭐ La cita, en VERDANA: es la voz de una persona, no la de un medio. */
.resena__caja blockquote { margin: 0; }
.resena__caja blockquote p {
  margin: 0;
  font-family: var(--cuerpo);
  font-size: var(--t-cuerpo); line-height: 1.6;
  color: var(--texto); text-wrap: pretty;
}

.resena__firma {
  margin-top: auto; padding-top: 1.1em;
  border-top: 1px solid var(--borde);
  display: flex; flex-direction: column; gap: .25em;
}
.resena__autor {
  font-family: var(--titulo); font-size: 1.05rem; color: var(--texto);
}
/* El punto que separaba fuente y fecha cuando iban en el mismo span. */
.resena__fecha::before { content: "· "; }

/* ⭐ LA TARJETA DE RESEÑA, DESNUDA Y AL CENTRO — Carlos, 2026-08-18
   =====================================================================
   Primero en el teléfono y luego, con las mismas palabras, en escritorio:
   «quita lo mismo que de mobile, lo de read, lo de TripAdvisor, las
   estrellas, y mándalo al centro».

   Queda la cita, el nombre y la fecha. Nada más.

   ⚠️ Sin fuente ni enlace, la cita pierde de dónde sale. Se avisó: son
   reseñas reales de TripAdvisor y la atribución era lo que permitía
   comprobarlo. Si se quiere recuperar sin ensuciar la tarjeta, lo suyo es
   UN enlace bajo el bloque —«Ver las 5.033 opiniones»— y no repetirlo en
   cada una.
   ⚠️ El marcado sigue ahí: se oculta, no se borra. Volver a enseñarlo es
   quitar este `display: none`. */
.resena__estrellas,
.resena__fuente,
.resena__enlace { display: none; }
/* Sin fuente delante, la fecha se queda sin su punto de separación. */
.resena__fecha::before { content: none; }

/* Cita, nombre y fecha, todo centrado. */
.resena__caja { text-align: center; }
.resena__caja blockquote p { text-align: center; }
.resena__firma { align-items: center; text-align: center; }
.resenas__cabeza { justify-content: center; text-align: center; }

/* ⚠️ La fecha lleva el MISMO traje que la fuente. Al separarlas en dos
   spans (2026-08-18) se quedó sin estilo y salía en el color heredado
   del bloque —blanco sobre el papel claro de la tarjeta, ilegible—.
   ⚠️ Y van dentro de `.resena__origen` porque la firma es una columna:
   sueltas, cada una caía en su propia línea y la fecha arrastraba el
   punto de separación al principio, como si le faltara algo delante. */
.resena__origen { display: block; }
.resena__fuente,
.resena__fecha {
  font-size: .82rem; color: var(--texto-suave);
  letter-spacing: .04em;
}
.resena__enlace {
  margin-top: .5em; align-self: flex-start;
  font-family: var(--titulo); font-size: .78rem; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--acento-tinta); text-decoration: none;
  border-bottom: 1px solid var(--acento); padding-bottom: 2px;
  /* ⚠️ Este `display` viene DESPUÉS del `display: none` que retira el
     enlace, y con la misma especificidad ganaba: el «Read» seguía saliendo
     en escritorio. Se marca para que, si algún día vuelve el enlace, esto
     no lo resucite por accidente (2026-08-18). */
  display: none;
  align-items: center; min-height: 44px;
}
.resena__enlace:hover { color: var(--tinta); border-color: var(--tinta); }


/* =====================================================================
   LA GALERÍA DE LA ZONA
   =====================================================================
   Carlos, 2026-08-17: «coloca una galería aquí de Riviera Maya o algo».
   Sustituye a la foto suelta con recorte de ola.

   Cinta deslizable a sangre, sin flechas ni puntos: es una galería para
   pasear, no un componente que haya que operar. El anclaje deja cada
   foto en su sitio al soltar, y la primera arranca alineada con el texto
   de la página, no pegada al filo de la pantalla.
   ===================================================================== */
.galeria-zona { padding-block: clamp(28px, 4vw, 56px); }
.galeria-zona__lista {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: clamp(10px, 1.2vw, 18px);
  grid-auto-flow: column;
  grid-auto-columns: min(72%, 340px);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  /* el aire lateral iguala al del contenido: la primera foto empieza
     donde empiezan los titulares */
  --sangria: max(var(--aire), (100vw - var(--ancho)) / 2 + var(--aire));
  scroll-padding-inline: var(--sangria);
  padding-inline: var(--sangria);
  padding-bottom: 10px;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.galeria-zona__lista::-webkit-scrollbar { display: none; }
.galeria-zona__lista li { scroll-snap-align: start; scroll-snap-stop: always; }
.galeria-zona__lista img {
  width: 100%; aspect-ratio: 3 / 4; object-fit: cover; display: block;
  transition: transform .5s var(--curva);
}
@media (hover: hover) and (pointer: fine) {
  .galeria-zona__lista li:hover img { transform: scale(1.03); }
}
@media (min-width: 900px) {
  .galeria-zona__lista { grid-auto-columns: min(34%, 420px); }
}


/* =====================================================================
   📱 LEY DEL MÓVIL: TODO EL TEXTO AL CENTRO — Carlos, 2026-08-18
   =====================================================================
   «Todos los textos van al centro, o sea: el eyebrow va al centro, luego
   separación del título unos 10px, luego el título centrado, y 10px, y
   la descripción esa debe estar justificada y la última línea centrada.
   Aplícalo a todos.»

       ┌─────────────────┐
       │   DE LA COCINA  │  ← eyebrow, centrado
       │      ↕ 10px     │
       │  PLATO A PLATO  │  ← titular, centrado
       │      ↕ 10px     │
       │ Texto  justifi- │  ← descripción, justificada…
       │ cado a los dos  │
       │    dos lados    │  ← …y la última línea, centrada
       └─────────────────┘

   ⛔ VA AL FINAL DEL ARCHIVO Y SÓLO DENTRO DEL CORTE DE MÓVIL. El
   escritorio queda intacto: es ley de la casa desde hoy que un arreglo
   de móvil no altera un diseño de escritorio ya aprobado.

   ⚠️ `text-align-last` es lo que centra la ÚLTIMA línea; sin ella, un
   texto justificado deja la última línea suelta a la izquierda, que es
   justo lo que Carlos no quiere. Safari de iPhone la soporta desde la 16.
   Donde no llegue, el texto se queda justificado y la última a la
   izquierda: se degrada, no se rompe.

   ⚠️ Con la columna estrecha del teléfono, justificar abre «ríos» de
   espacio entre palabras. Por eso va con `hyphens: auto`, que parte las
   palabras largas y aprieta la mancha.
   ===================================================================== */
@media (max-width: 899px) {

  /* ── Los titulares y sus rótulos, al centro ─────────────────────── */
  /* ⚠️ El modal de reservas va aparte de `main` —vive al final del
     documento para que nada pueda taparlo—, así que hay que nombrarlo o
     se queda fuera de la ley. */
  /* ⚠️ El h1 entra también (2026-08-18, tarde). Se había quedado fuera
     porque la ley hablaba de eyebrow → título → descripción, y el titular
     del hero no sigue ese patrón — pero Carlos lo vio en el teléfono y
     tiene razón: si TODO va al centro, el titular de la portada también.
     Los h1 de las páginas interiores ya venían centrados con el banner. */
  /* ⚠️ NO TODOS LOS EYEBROW LLEVAN LA CLASE `.rotulo`: el del hero es
     `.hero__marca` y el de las interiores `.banner-banda__antetitulo`.
     Sin nombrarlos, la ley los trataba como PÁRRAFO y salían justificados
     y con su margen viejo —16,8px en el hero, 12,3 en el banner— en vez
     de centrados a 10. Se vio en el teléfono (2026-08-18). */
  main :is(h1, h2, h3, h4),
  main .rotulo,
  main .eyebrow,
  main :is(.hero__marca, .banner-banda__antetitulo),
  .modal-reserva :is(h2, h3, h4),
  .modal-reserva .rotulo {
    text-align: center;
  }

  /* Las dos separaciones que pidió Carlos, exactas.
     ⚠️ Con `!important`, y no por pereza: cada sección del sitio trae su
     propio margen escrito con una clase (`.pase__texto h2`, `.cierre-carta
     p`…), que pesa más que este selector. Medido antes de ponerlo: los
     rótulos salían a 5,6px y los títulos a 0, 13 o 28. Esto es una LEY
     que manda sobre el ritmo de cada sección, así que tiene que ganar.
     ⚠️ También se pone el margen de ARRIBA a cero: si no, al margen de
     abajo se le suma el de arriba del vecino y los 10px dejan de ser 10. */
  main :is(.rotulo, .eyebrow, .hero__marca, .banner-banda__antetitulo) {
    margin-top: 0 !important;
    margin-bottom: 10px !important;
  }
  /* ⚠️ Bajo el TÍTULO van 18, no 10 (Carlos, 2026-08-18, viéndolo en el
     teléfono). Los 10 del eyebrow al título se quedan: lo que va junto
     tiene que verse junto. Pero con 10 también debajo, el párrafo
     arrancaba pegado al titular y el bloque no respiraba. El escalón
     10 → 18 es lo que separa «el rótulo pertenece al título» de «aquí
     empieza otra cosa». */
  main :is(h1, h2, h3, h4),
  .modal-reserva :is(h2, h3, h4) {
    margin-top: 0 !important;
    margin-bottom: 18px !important;
  }
  main :is(h1, h2, h3, h4) + p,
  main :is(.rotulo, .eyebrow) + p { margin-top: 0 !important; }

  /* ⚠️ LA PROPUESTA DE LA PORTADA NO SE SEPARA CON MÁRGENES. Su
     descripción va en `position: absolute`, colgada del titular con
     `top: calc(100% + …)`, así que la ley de los 18px no le llegaba: la
     separaba un `clamp(16px, 2.4vh, 28px)` que en un teléfono da 20,3.
     Carlos lo pidió igual que el resto (2026-08-18). Y ojo al medirlo:
     esa pieza nace con `translateY(26px)` y sólo sube cuando la escena
     avanza, así que medida sin revelar da 46px y parece otra cosa. */
  .propuesta__desc {
    top: calc(100% + 18px);
    /* ⚠️ Y HAY QUE SUBIRLA CON EL TITULAR. El titular se desplaza hacia
       arriba con la escena (`--sube`, hasta 74px), pero la descripción
       está colgada del BLOQUE, no de él: al subir el titular, el hueco
       se estiraba de 18 a 77px. Aquí se le suma el mismo desplazamiento,
       así que los 18 se mantienen durante toda la escena.
       El primer sumando es su propia entrada, que ya estaba. */
    transform: translateY(calc(
      (1 - var(--desc, 0)) * 26px
      - var(--sube, 0) * clamp(38px, 7vh, 74px)
    ));
  }

  /* ── La descripción: justificada, con la última línea al centro ──── */
  main p:not(.rotulo):not(.eyebrow):not(.hero__marca):not(.banner-banda__antetitulo),
  .modal-reserva p:not(.rotulo):not(.eyebrow) {
    text-align: justify;
    text-align-last: center;
    -webkit-hyphens: auto;
    hyphens: auto;
    /* Los párrafos llevan `max-width` para no pasarse de medida; sin esto
       la caja se quedaría pegada a la izquierda y el centrado del texto
       no se notaría. */
    margin-inline: auto;
  }

  /* ── Y lo que va con el texto: los botones ──────────────────────────
     Con el texto centrado, un botón pegado a la izquierda canta. Las
     filas de botones se centran igual —y las que envuelven, también—,
     porque si no el bloque pierde el eje justo debajo del párrafo.
     Se centra la CAJA (flex/grid); el botón conserva su ancho. */
  main :is(.grupos__contacto, .reservas__contacto, .cancun-donde__acciones,
           .zona__acciones, .cierre-carta__acciones) {
    justify-content: center;
  }
  /* ⚠️ La DIRECCIÓN de /reservaciones/ (2026-09-15) no es un <p>, así
     que se quedaba a la izquierda debajo de un horario centrado. Va
     centrada pero NO justificada: justificar una dirección en dos líneas
     abría «Blvd.    Kukulcán    Km» de lado a lado. */
  /* Lo mismo el DATO del banner (dirección en /cancun/, horario en el
     Kids Club): dos líneas justificadas abrían «Blvd.   Kukulcán   Km».
     ⛔ NO se excluye con otro `:not()` en el selector del justificado:
     eso le sube la especificidad y pasa a ganarle a la regla que centra
     las reseñas (36 rutas rotas, lo cazó auditar-movil.js). Aquí va con
     la MISMA especificidad que el justificado y, por ir detrás, gana. */
  main address,
  main p.banner-banda__dato:not(.rotulo):not(.eyebrow):not(.hero__marca) { text-align: center; hyphens: manual; }
  main :is(h2, h3, h4) + .boton,
  main p + .boton,
  main .boton:only-child { margin-inline: auto; }
  main .pase__texto .boton { justify-self: center; }

  /* ── Lo que NO entra ────────────────────────────────────────────────
     Tres sitios donde centrar y justificar estropea en vez de arreglar:

       · el LISTADO DE PLATOS de las cartas, donde el nombre va a la
         izquierda y el precio a la derecha en la misma línea: centrarlo
         rompe esa relación y deja los precios flotando;
       · el WIDGET DE RESERVAS, que es de terceros y tiene su maqueta;
       · los datos sueltos de una ficha (horario, dirección), que son un
         dato y no un párrafo.

     Si Carlos los quiere también, se quitan de aquí y ya está. */
  /* ⭐ LAS FICHAS DE LOS SLIDERS, CENTRADAS SIN JUSTIFICAR (Carlos,
     2026-08-18): «que la descripción de las bebidas y comida sí estén al
     centro, sin necesidad de justificar». Son textos cortos de dos o tres
     líneas dentro de una tarjeta estrecha: justificados abrían huecos
     enormes entre palabras y se leían peor que centrados. */
  /* ⚠️ Hacen falta cuatro clases para ganarle a la regla del justificado
     de más arriba, que lleva cuatro `:not()` y pesa 0,4,2. Con
     `main .pase__ficha p` (0,1,2) perdía y el texto seguía justificado
     dentro de la tarjeta. */
  main .pase.con-cards .pase__medio .pase__ficha p { text-align: center; hyphens: manual; }

  /* ⭐ LAS CITAS DE LAS RESEÑAS, TAMPOCO JUSTIFICADAS. En una tarjeta de
     291px, justificar un párrafo de ocho líneas abría ríos de espacio
     entre palabras —se veía en el teléfono— y encima cada línea acababa
     en un guión. Centradas se leen; y son citas, que es lo que pide el
     centro. Cuatro clases para ganarle a la ley del justificado. */
  main .resenas .resenas__lista .resena .resena__caja blockquote p {
    text-align: center; hyphens: manual;
  }

  /* ⭐ DENTRO DE UNA TARJETA, EL TEXTO VA CENTRADO — no justificado.
     Carlos, 2026-08-18: «los card de zona Kids en mobile deben ir
     centrados, no justificado; hablo de la descripción». Es la tercera
     vez que lo pide —antes fueron las fichas de los pases y las citas de
     las reseñas—, así que aquí se cierra el patrón: en una tarjeta
     estrecha, justificar abre huecos entre palabras y parte con guiones.
     Se incluyen los planes de Cancún, que son la misma clase de tarjeta.

     ⚠️ Con `!important` porque la ley del justificado pesa 0,4,2 y estos
     selectores no llegan; es una excepción a una ley, y la ley también se
     escribió así. */
  /* ⚠️ EN UNA TARJETA CON `gap`, EL HUECO SE SUMA AL MARGEN. `.cancun-plan`
     es un flex en columna con `gap: .7em`, así que los 18px que la ley
     pone bajo el título se convertían en 30 (auditoría de móvil,
     2026-08-19). El gap se apaga y mandan los márgenes de la ley, que es
     quien fija el ritmo en el teléfono; el enlace del final recupera su
     aire por su cuenta. */
  main .cancun-plan { gap: 0; }
  main .cancun-plan .cancun-plan__enlace { margin-top: 18px; }

  main .zona__cuerpo,
  main .cancun-plan p {
    text-align: center !important;
    text-align-last: auto !important;
    hyphens: manual !important;
  }

  /* La cabecera del bloque era una fila con el titular a la izquierda y
     el enlace de prensa a la derecha. Retirado el enlace, el titular se
     quedaba descolgado contra el borde: al centro, como todo lo demás. */
  /* ── LAS TARJETAS DE RESEÑA EN EL TELÉFONO — Carlos, 2026-08-18 ─────
     «Que sólo aparezca 1, no 1,5; quítale las estrellas, quítale
     TripAdvisor, deja la fecha, quita el read, deja el nombre, y reduce
     el margen de abajo de la descripción.»

     ⚠️ Sin la fuente ni el enlace, la cita pierde de dónde sale. Se lo
     dije a Carlos y decidió así para el teléfono; en ESCRITORIO se quedan
     los dos, que es donde la atribución sigue a la vista. */
  .resenas__lista {
    /* Una tarjeta por pantalla, no una y media: el ancho de la ventana
       menos el aire de los lados. */
    grid-auto-columns: calc(100vw - var(--aire) * 2);
  }
  /* Y la descripción, más pegada a la firma. */
  .resena__caja blockquote { margin-bottom: 0; }
  .resena__caja blockquote p { margin-bottom: 0; }
  .resena__firma { margin-top: 14px; }
  /* Sin estrellas, sin fuente y sin enlace, la caja se quedaba con un
     hueco muerto debajo de la fecha: se ajusta al contenido que queda. */
  .resena__caja { padding-bottom: clamp(20px, 3vw, 28px); }

  /* ⚠️ EL HUECO BAJO LA FECHA NO ERA UN MARGEN. En el carrusel todas las
     tarjetas medían lo que la MÁS ALTA —la reseña más larga—, así que las
     cortas quedaban con 55px de aire muerto debajo. Medido: 27px arriba
     contra 75 abajo. Con `align-items: start` cada tarjeta toma su propia
     altura y el hueco desaparece.
     ⚠️ A cambio, el bloque cambia de alto al pasar de una reseña a otra.
     Con una tarjeta por pantalla se nota poco y es lo normal en un
     carrusel de citas; si molesta, se vuelve a la altura común y el aire
     se reparte con `justify-content: space-between`. */
  .resenas__lista { align-items: start; }


  /* ⭐ UNA TARJETA POR PANTALLA EN TODOS LOS CARRUSELES DE TEXTO
     =====================================================================
     Carlos, 2026-08-18: «estos arreglos hazlo en las otras secciones a
     nivel mobile». Lo mismo que se hizo con las reseñas: donde había 1,4
     o 1,5 tarjetas —media tarjeta cortada a la derecha— ahora hay UNA,
     con un filo de la siguiente que dice que el carrusel sigue.

     Medido antes: blog 1,48 · índice de cartas 1,44 · zonas de Kids 1,41
     · planes de Cancún 1,48. Todos son `grid` con las columnas en
     porcentaje (76–80%), así que basta con darles el ancho de la ventana
     menos su aire.

     ⛔ LAS GALERÍAS DE FOTOS NO ENTRAN. Ahí ver dos imágenes a la vez es
     parte del asunto: una galería que enseña una sola foto deja de
     parecer una galería. Si Carlos las quiere también, se añaden aquí.
     ⛔ Y tampoco los pases de comida y bebida: su tarjeta ya se ajustó
     aparte y él la aprobó con la vecina asomando. */
  .blog-home__lista,
  .indice-cartas,
  .zonas__lista,
  .cancun-planes__lista {
    grid-auto-columns: calc(100vw - var(--aire) * 2);
  }

  /* Los logos de la pleca de prensa, un 35% más grandes en el teléfono
     (Carlos, 2026-08-18): 115 → 155px. En la cinta caben igual, que para
     eso desfila; y a 115 las cabeceras de los medios se leían apretadas.
     ⚠️ Sólo móvil: en escritorio siguen en su clamp de 115–142. */
  .pleca-prensa__fila img { width: 155px; }

  /* Las cabeceras de dos piezas —titular a la izquierda, enlace a la
     derecha— no cumplían la ley del centro: el titular se quedaba pegado
     al borde. En el teléfono se apilan y las dos van centradas. */
  .resenas__cabeza,
  .blog-home__cabeza {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    text-align: center;
  }

  main :is(.carta__platos, .plato, .plato__desc) :is(p, h3, h4),
  main :is(.carta__platos, .plato) p,
  .plato__desc,
  #ot-widget :is(p, h2, h3, h4),
  .reservas__widget :is(p, h2, h3, h4) {
    text-align: initial;
    text-align-last: auto;
    hyphens: manual;
  }

  /* ⭐ LA CARTA VA A LA IZQUIERDA — Carlos, 2026-08-21: «todo va en el
     menú justificado a la izquierda». Son 55 descripciones de dos o
     tres líneas; cada una acababa con su última línea centrada y la
     columna quedaba bailando.

     ⚠️ EL PESO DE ESTE SELECTOR ESTÁ ELEGIDO, NO ES CASUAL. Vale 0,4,2
     —cuatro clases y dos elementos, `main` y `p`—: lo justo para empatar
     con el `main p:not()×4` de arriba y ganarle por ir después, sin
     pasarse. El `p` delante de `.plato__desc` no sobra: sin él son 0,4,1
     y pierde. Se contó mal a la primera y la carta seguía justificada.
     ⛔ El primer intento fue añadir un `:not(.plato__desc)` a aquella
     regla, y **rompió las reseñas**: el `:not()` de más la subía a 0,5,2
     y le pasaba por encima a `main .resenas … blockquote p` (0,4,3), que
     estaba escrita justamente para ganar esa pelea. 36 incidencias en el
     auditor. Tocar la especificidad de una regla global mueve cosas que
     no se ven desde aquí. */
  main .carta__seccion .carta__platos .plato p.plato__desc {
    text-align: left;
    text-align-last: auto;
    hyphens: manual;
  }
}


/* ── El texto de «Villas exclusivas», en Grupos ─────────────────────
   Sólo justificado. Aquí NO se estira: la sección es de ancho completo
   y el renglón se iría a 155 caracteres. Lo eligió Carlos el
   2026-08-21, con las dos opciones medidas delante. */
.grupos__villas p { text-align: justify; }

/* =====================================================================
   LA CARTA DEL QR
   =====================================================================
   Carlos, 2026-08-31: la web va sin precios y el menú del código QR con
   ellos. Es la misma carta: aquí sólo se ordena el hecho de que van las
   TRES seguidas en una página, que es lo que se lee en la mesa.

   ⚠️ Ni un color ni una tipografía nuevos: todo sale de las variables
   que ya usa la carta de la web. Lo único propio es el aire entre las
   tres cartas y la nota legal del pie.
   ===================================================================== */
.carta-qr__cabeza {
  padding-top: clamp(18px, 5vw, 34px);
  padding-bottom: clamp(10px, 3vw, 18px);
  text-align: center;
}
.carta-qr__cabeza h1 {
  font-family: var(--titulo); font-size: var(--t-seccion);
  color: var(--acento-titulo); margin: 0;
  text-transform: uppercase; letter-spacing: .08em;
}
.carta-qr__pie-nota {
  /* ⚠️ `--t-rotulo`, no un tamaño inventado: el auditor de escalas canta
     en cuanto un papel tiene dos cuerpos, y una nota es un DATO. */
  margin: .4em 0 0; font-size: var(--t-rotulo); color: var(--texto-suave);
  letter-spacing: .04em;
}
/* Cada carta empieza donde acaba la anterior, y se nota: sin esta
   separación las tres se leen como una lista interminable. */
.carta-qr__bloque + .carta-qr__bloque { margin-top: clamp(28px, 7vw, 56px); }
/* El nombre de la carta manda sobre el del apartado: sin esto,
   «Alimentos» se leía más flojo que «ENTRADAS», que cuelga de él. Lleva
   el filete de los títulos de la carta, no un adorno nuevo. */
.carta-qr__rotulo {
  display: flex; align-items: center; gap: 14px;
  max-width: var(--ancho); margin: 0 auto clamp(10px, 3vw, 18px);
  padding: 0 var(--aire);
  /* ⚠️ `--t-seccion`, el tamaño que le toca a un título de sección. La
     carta se distingue del apartado por COLOR y por el filete grueso, no
     por ser más grande — la misma lección de la maqueta C. */
  font-family: var(--titulo); font-size: var(--t-seccion);
  line-height: 1.1; text-transform: uppercase; letter-spacing: .04em;
  color: var(--acento-titulo); font-weight: 700;
}
.carta-qr__rotulo::after {
  content: ""; flex: 1; height: 2px;
  background: linear-gradient(90deg, var(--acento-titulo), transparent);
}
.carta-qr__legal {
  margin: clamp(28px, 7vw, 48px) auto clamp(18px, 5vw, 32px);
  font-size: var(--t-rotulo); color: var(--texto-suave); text-align: center;
  letter-spacing: .04em; text-wrap: balance;
}
