/* Maxito Tattoo — capa de sitio.
   Los tokens y las primitivas de marca (.rotulo, .script, .btn, campos de
   formulario, tipografía) viven en css/marca.css, derivado del rótulo pintado
   de la vitrina. Este archivo solo agrega los componentes propios del sitio.

   Reglas del rótulo que este archivo respeta:
   - Negro de fondo siempre.
   - Rye solo en títulos; Archivo en toda la interfaz (nav, botones, chips, campos).
   - Un solo script por pantalla: Sacramento vive únicamente en el hero.
   - El rojo nunca es texto (3.3:1). Solo contorno y sombra.
   - La sombra dura va abajo-derecha, sólida y sin desenfoque. */

/* marca.css pinta todos los enlaces de cian y los subraya; eso es correcto para
   texto corrido, pero no para nav, botones y tarjetas, que se reponen acá. */
a { color: inherit; text-decoration: none; }

/* **La vuelta al cian para el texto corrido, y ahora es automática.**
   `.prosa` existía desde el principio para esto y **no se usó ni una sola vez**,
   así que el mismo defecto apareció tres veces en dos días: el enlace del cierre
   de /cuidados/, cinco en /preguntas/, y los dos de rescate. Un mecanismo que
   hay que acordarse de activar no es un mecanismo. Un `<a>` dentro de un `<p>`
   *es* un enlace en texto corrido, por definición, así que se pinta solo.
   `.prosa` se queda en el selector por si algún contenedor lo necesita sin ser
   un párrafo.

   **El `:hover` va explícito y es obligatorio.** `marca.css` trae
   `a:hover { color: var(--cian-luz) }` con especificidad (0,1,1), y este
   selector es (0,1,2): sin repetirlo acá, la regla le gana y los enlaces de
   prosa se quedan sin ningún cambio al pasar el mouse.

   `:not(.btn)` protege a los botones sólidos que viven dentro de un párrafo. */
.prosa a,
p a:not(.btn) { color: var(--cian); text-decoration: underline; }
.prosa a:hover,
p a:not(.btn):hover { color: var(--cian-luz); }

html { scroll-behavior: smooth; }
body { overflow-x: hidden; }
h1, h2, h3 { margin: 0; line-height: 1.05; }
p { margin: 0; }
button { font-family: inherit; cursor: pointer; }
ul { margin: 0; padding: 0; list-style: none; }

/* ---------- Botones ---------- */
/* .btn base viene de marca.css: amarillo, mayúsculas, sombra dura roja. */
.btn { border-radius: var(--radio); white-space: nowrap; }
.btn:disabled { cursor: not-allowed; opacity: .45; box-shadow: none; }
.btn:disabled:hover { transform: none; box-shadow: none; background: var(--amarillo); }

/* El botón principal está hecho del mismo esmalte que el rótulo, así que
   responde con la misma luz: al pasar el mouse (o al recibir foco de teclado)
   le cruza el mismo barrido, una sola vez y más rápido, porque acá es
   respuesta a una acción y no un momento de contemplación. */
.btn-solid { position: relative; overflow: hidden; }
.btn-solid::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background-image: linear-gradient(100deg,
    transparent 40%,
    rgba(255,255,255,.75) 50%,
    transparent 60%);
  background-repeat: no-repeat;
  background-size: 220% 100%;
  background-position: 130% 0;
}
.btn-solid:hover::after,
.btn-solid:focus-visible::after { animation: boton-brillo .6s linear; }
@keyframes boton-brillo {
  from { background-position: 130% 0; }
  to   { background-position: -30% 0; }
}

.btn-outline {
  background: transparent; color: var(--cian);
  border-color: var(--cian); box-shadow: 4px 4px 0 var(--cian-oscuro);
}
.btn-outline:hover { background: var(--cian); color: var(--negro); box-shadow: 5px 5px 0 var(--cian-oscuro); }
.btn-outline:active { box-shadow: 0 0 0 var(--cian-oscuro); }

.btn-ghost {
  background: transparent; color: var(--cian); border-color: transparent;
  box-shadow: none; padding: .7rem;
}
.btn-ghost:hover { background: transparent; color: var(--cian-luz); border-color: var(--negro-3); box-shadow: none; transform: none; }
.btn-ghost:active { transform: none; }

.btn-lg { padding: 1rem 1.9rem; font-size: var(--t-cuerpo); }
/* Padding simétrico y no `aspect-ratio`: en un ítem flex el ancho lo gana el
   tamaño del contenido, así que `aspect-ratio` no llega a aplicarse y el botón
   sale rectangular. Con padding igual en los cuatro lados el cuadrado sale
   solo, y 28px de ícono + 24px de padding + 4px de borde dan los mismos 56px
   de alto que el botón principal de al lado. */
/* El botón queda cuadrado y a la misma altura que el CTA de al lado (56px):
   36 de ícono + 16 de padding + 4 de borde. Si se toca el ícono hay que
   recalcular el padding, o el WhatsApp deja de alinear con "Agendá tu cita". */
.btn-icon-only { padding: .5rem; justify-content: center; }
.btn-icon-only svg { width: 36px; height: 36px; }

/* El teléfono repica: quieto el 62% del ciclo y después un repique corto que
   se apaga. Es movimiento con significado —WhatsApp es un canal de contacto,
   no un adorno— y por eso descansa mucho más de lo que se mueve. */
.nav-actions .btn-icon-only svg { animation: whatsapp-repique 7s ease-in-out infinite; }
@keyframes whatsapp-repique {
  0%, 62%, 88%, 100% { transform: rotate(0); }
  66% { transform: rotate(-12deg); }
  70% { transform: rotate(10deg); }
  74% { transform: rotate(-7deg); }
  78% { transform: rotate(5deg); }
  82% { transform: rotate(-3deg); }
}
.nav-actions .btn-solid svg { width: 18px; height: 18px; flex-shrink: 0; }

/* Los íconos de los dos CTAs del nav: tatuaje (máquina) y perforaciones
   (oreja), los PNG que entregó el estudio en assets/iconos/. Van como máscara
   y no como etiqueta de imagen, para que el color sea siempre el del botón:
   currentColor pinta el negro sobre el amarillo del sólido, el cian del
   contorno y el negro de su hover, todo con un solo archivo por ícono.

   El PNG de la oreja está engrosado en origen (dilatación sobre el original
   del estudio): es un dibujo de trazo fino a 512px y sin engordar, a 20px de
   botón, el trazo se parte en polvo. El de la máquina es sólido y va tal cual.

   Escondido salvo que el navegador sepa de máscaras: sin el @supports, un
   navegador viejo pintaría el cuadrado de currentColor entero — un parche de
   color sin dibujo. Con texto al lado, perder el ícono no pierde nada.
   La prueba va contra `none` y no contra una url vacía: `url("")` resuelve al
   propio documento y se lee como un descuido, aunque @supports nunca la pida. */
.nav-cta-icono { display: none; }
@supports ((-webkit-mask-image: none) or (mask-image: none)) {
  .nav-cta-icono {
    display: inline-block; width: 22px; height: 22px; flex-shrink: 0;
    background: currentColor;
    -webkit-mask: var(--icono) center / contain no-repeat;
    mask: var(--icono) center / contain no-repeat;
  }
}
.icono-tatuaje { --icono: url("../assets/iconos/tatuaje.png"); }
.icono-perforacion { --icono: url("../assets/iconos/perforacion.png"); }

/* La cuenta del ancho del nav con el botón de Perforaciones, medida en vivo:
   con la frase entera, marca 62 + tres enlaces 257 + acciones 555 + gaps 48 +
   padding 40 = 962. De ahí los tres escalones, cada uno donde la cuenta lo
   exige y no antes:
   - En escritorio el enlace "Perforaciones" del menú se esconde: el botón de
     la derecha ya es ese destino (el porqué completo está en el HTML). Sin
     este recorte no cabía ni a 1440.
   - Bajo 970 el CTA se queda en "Cotizá" (a 969 la frase entera ya no entra).
   - Bajo 600 los dos CTAs pasan a solo-ícono: entre 561 y 574 ni siquiera
     "Cotizá" + "Perforaciones" caben juntos, así que el corte va en 600 con
     aire y no en 560 raspando. */
@media (min-width: 901px) {
  .nav-link-perforaciones { display: none; }
}
@media (max-width: 969px) {
  .cta-detalle { display: none; }
}
@media (max-width: 600px) {
  /* Solo-ícono (pedido del estudio): los oficios se reconocen por su dibujo
     —la máquina y la oreja—. El texto no se borra, se esconde: el aria-label
     del enlace dice lo mismo para quien no ve el ícono. 36px de ícono + 16 de
     padding + 4 de borde = los mismos 56px del botón de WhatsApp. */
  .nav-actions .nav-cta-texto { display: none; }
  .nav-actions .nav-cta { padding: .5rem; }
  .nav-actions .nav-cta .nav-cta-icono { width: 36px; height: 36px; }
}

/* ---------- Nav ---------- */
.nav {
  position: fixed; inset: 0 0 auto 0; z-index: 100;
  padding: .7rem 0; border-bottom: 2px solid transparent;
  transition: background .3s, border-color .3s;
}
.nav.is-scrolled { background: rgba(15,15,14,.94); backdrop-filter: blur(8px); border-bottom-color: var(--negro-3); }
.nav-inner { max-width: var(--max-ancho); margin: 0 auto; padding: 0 1.25rem; display: flex; align-items: center; gap: 1.5rem; }
/* El logo cuelga de un clavo: `transform-origin` arriba y al centro, y un
   péndulo lentísimo (±3° en 5s ≈ 3px de recorrido) que da señal de vida sin
   pedir atención. La escala del hover vive en `.brand` y el vaivén en la
   imagen, en elementos distintos a propósito: son dos transforms que se
   componen, y en un mismo elemento uno pisaría al otro. */
/* `flex-shrink: 0` no es de adorno: sin él, un botón largo en `.nav-actions`
   le come el ancho al logo. Con "Cotizá tu tatuaje" el rótulo pasó de 65px a
   18px — casi desaparecido. El logo nunca es lo que cede. */
.brand { display: flex; align-items: center; flex-shrink: 0; transition: transform .25s cubic-bezier(.2,.7,.2,1); }
.brand:hover, .brand:focus-visible { transform: scale(1.07); }
.brand-logo {
  display: block; height: 64px; width: auto;
  transform-origin: 50% 8%;
  animation: rotulo-pendulo 5s ease-in-out infinite;
}
@keyframes rotulo-pendulo {
  0%, 100% { transform: rotate(-3deg); }
  50%      { transform: rotate(3deg); }
}
.nav-links {
  display: flex; gap: 1.6rem; margin: 0 auto;
  font-family: var(--font-texto); font-weight: 600; font-size: var(--t-chico);
  letter-spacing: .06em; text-transform: uppercase; color: var(--hueso);
}
.nav-links a { position: relative; padding: .2rem 0; }
.nav-links a::after {
  content: ''; position: absolute; left: 0; bottom: -3px; height: 3px; width: 100%;
  background: var(--amarillo); transform: scaleX(0); transform-origin: left; transition: transform .22s;
}
.nav-links a:hover { color: var(--amarillo); }
.nav-links a:hover::after { transform: scaleX(1); }
.nav-actions { display: flex; align-items: center; gap: .5rem; }
.nav-burger { display: none; flex-direction: column; gap: 4px; background: none; border: none; padding: .4rem; }
.nav-burger span { width: 24px; height: 3px; background: var(--hueso); transition: transform .25s, opacity .25s; }

/* ---------- Hero: la vitrina ---------- */
/* El hero reproduce el rótulo de la vitrina: marco, saludo en script, y el
   nombre en tres capas (relleno amarillo, contorno rojo, sombra dura). */
.hero {
  position: relative; padding: 8rem 1.25rem 3rem;
  background: linear-gradient(180deg, rgba(27,173,234,.07), transparent 60%), var(--negro);
}
.hero-inner { max-width: var(--max-ancho); margin: 0 auto; }
.vitrina-marco {
  position: relative; border: 3px solid var(--negro-3); border-radius: var(--radio);
  padding: clamp(1.5rem, 5vw, 3.25rem);
}

/* El muestrario va en capa propia porque los destellos son absolutos y, sin
   z-index, pintarían encima de las fotos. Un diamante titilando sobre un
   tatuaje se lee como suciedad, no como luz. */
/* `100%` y no un `vw`: el ancho útil es el del marco menos su padding, y con
   82vw el muestrario se salía 27px del padding derecho de la vitrina en
   teléfono —sin desbordar la página, así que no se veía como error—. */
.muestrario { position: relative; z-index: 1; margin: var(--sp-4) auto 0; width: min(380px, 100%); }

/* La vitrina se parte en dos recién a los 1024px, y no antes, por una cuenta:
   el rótulo mide ~0.5 × el ancho del viewport (11vw de fuente × 4.5 de "Tattoo")
   y los dos botones piden 517px fijos. Restándole al marco la columna del
   muestrario y el hueco, la columna del rótulo nunca baja de esos dos valores
   —queda en 562px a 1024 y sube desde ahí—. Si se toca el ancho del muestrario
   o el hueco, hay que rehacer esa resta o el rótulo se parte. */
@media (min-width: 1024px) {
  .vitrina-marco {
    display: grid;
    grid-template-columns: 1fr clamp(260px, 28vw, 400px);
    /* Hueco de fila en 0: el ritmo vertical del rótulo ya lo dan sus márgenes. */
    gap: 0 clamp(1.5rem, 3vw, 3rem);
    align-items: center;
  }
  /* El `margin: auto` del apilado tiene que morir acá. En un ítem de grid un
     margen inline automático cancela el estirado: la columna deja de medir su
     pista y pasa a medir su contenido —el muestrario quedaba en 175px de los
     353 disponibles, y encima cambiaba de ancho con cada nombre del crédito—. */
  .muestrario { margin: 0; width: auto; }
}
.hero-saludo { display: flex; align-items: baseline; flex-wrap: wrap; gap: .75rem; }
/* `line-height: 1.6` y no 1: Sacramento tiene trazos ascendentes muy altos
   —la W y la L se salen 17px por encima de una caja ajustada al tamaño de
   fuente— y la máscara de escritura solo cubre la caja del elemento, así que
   todo lo que sobresalga se recorta. La caja tiene que contener la tinta. */
/* El piso del clamp es lo único que se ve en teléfono: por debajo de 686px el
   7vw nunca alcanza, así que el saludo queda clavado en ese valor. Subirlo de
   2.5 a 3rem agranda «Welcome» solo en móvil y deja escritorio intacto, donde
   manda el vw. Y no abre un salto en el corte: a 686px, 7vw da exactamente 3rem. */
.hero-script { font-family: var(--font-script); color: var(--cian); font-size: clamp(3rem, 7vw, 4.5rem); line-height: 1.6; }

/* La cola de la última «e» se sale de la caja del texto.
   Sacramento firma la palabra con un trazo de salida que la métrica no cuenta:
   a 72px el avance de «Welcome» mide 242.9px y la tinta llega a 247.5. Esos
   ~4.6px de más no molestaban a nadie... hasta que llegó la máscara de abajo,
   que solo pinta dentro de la caja y por lo tanto cortaba el trazo final.

   Se arregla ensanchando la caja, no la máscara: el padding la estira lo justo
   para que la tinta quepa y el margen negativo devuelve el ancho ocupado, así
   nada se corre en la fila del saludo. Va en `em` para que acompañe al clamp
   del tamaño; en px se quedaría corto en escritorio o sobraría en teléfono. */
.hero-script { padding-right: .09em; margin-right: -.09em; }

/* El saludo se escribe.
   Sacramento es una cursiva de rotulista, y una cursiva se traza de un solo
   golpe de izquierda a derecha: por eso la palabra se revela con una máscara
   que avanza en esa dirección, con el borde inclinado igual que la letra para
   que lea como la punta de la pluma y no como una cortina.

   Se usa máscara y no trazos SVG a propósito: el texto sigue siendo texto real,
   seleccionable y legible por lector de pantalla.

   El ciclo es largo (26s) porque el hero ya tiene el brillo del rótulo y los
   destellos; la escritura es un gesto ocasional, no un bucle que compita.
   Escribe (2.3s), se queda puesta 20s, y se va con la misma pluma hacia la
   derecha, así el movimiento nunca cambia de sentido ni da un salto visible. */
.hero-script {
  -webkit-mask-image: linear-gradient(100deg, #000 49%, transparent 53%);
          mask-image: linear-gradient(100deg, #000 49%, transparent 53%);
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-size: 300% 100%;
          mask-size: 300% 100%;
  /* Estado base: escrito. Si la animación no corre —reduced motion, sin
     soporte de máscara— la palabra se ve entera, nunca a medias ni ausente. */
  -webkit-mask-position: 0% 0;
          mask-position: 0% 0;
  animation: saludo-escribe 26s linear .35s infinite both;
}
@keyframes saludo-escribe {
  0%   { -webkit-mask-position: 100% 0;  mask-position: 100% 0; }   /* en blanco */
  9%   { -webkit-mask-position: 0% 0;    mask-position: 0% 0; }     /* escrito */
  86%  { -webkit-mask-position: 0% 0;    mask-position: 0% 0; }     /* se queda */
  94%  { -webkit-mask-position: -100% 0; mask-position: -100% 0; }  /* la pluma se lleva la tinta */
  100% { -webkit-mask-position: -100% 0; mask-position: -100% 0; }
}
.hero-title { font-size: var(--t-display); margin: .3rem 0 0; }

/* El brillo del esmalte.
   El rótulo real vive tras un vidrio: cuando el sol lo cruza, el esmalte
   fresco devuelve un reflejo que recorre las letras de izquierda a derecha.
   Ese barrido es el único momento autoral del hero, así que pasa una vez y
   se toma siete segundos antes de volver — un destello, no un parpadeo.

   Se monta como una capa aparte (::after con el mismo texto, recortado al
   glifo) para no tocar las tres capas del rótulo: el relleno amarillo, el
   contorno rojo y la sombra dura quedan intactos debajo. */
/* `width: fit-content` deja la caja pegada a los glifos. Sin eso el bloque
   ocupa todo el ancho del marco y el barrido recorre cientos de píxeles
   vacíos antes de tocar la primera letra. */
.hero-title-line { display: block; width: fit-content; position: relative; }
.hero-title-line::after {
  content: attr(data-text);
  position: absolute; inset: 0;
  pointer-events: none;
  -webkit-text-stroke-width: 0;
  text-shadow: none;
  color: transparent;
  background-image: linear-gradient(100deg,
    transparent 42%,
    rgba(255,255,255,.28) 47%,
    rgba(255,255,255,.9) 50%,
    rgba(255,255,255,.28) 53%,
    transparent 58%);
  background-repeat: no-repeat;
  background-size: 220% 100%;
  background-position: 130% 0;
  -webkit-background-clip: text;
  background-clip: text;
  /* Entra a los 3.2s: después de que el saludo termina de escribirse (0.35s +
     2.3s). El hero se lee como una secuencia —primero la pluma, después la
     luz— y no como dos efectos disparados encima del otro. */
  animation: rotulo-brillo 9s linear 3.2s infinite;
}
/* La luz cruza una línea y después la otra, como un reflejo rasante. */
.hero-title-line + .hero-title-line::after { animation-delay: 3.42s; }
@keyframes rotulo-brillo {
  0%   { background-position: 130% 0; }
  20%  { background-position: -30% 0; }
  100% { background-position: -30% 0; }
}

/* El bloque se encoge hasta el ancho de la línea más larga del rótulo
   ("Tattoo"). Así el arco de abajo puede pedir `width: 100%` y quedar centrado
   contra los glifos, no contra la vitrina entera: antes el SVG medía 600px
   fijos y su centro caía 28px a la derecha del centro de la palabra. */
.hero-marca { width: fit-content; max-width: 100%; }
/* `height: auto` NO es decorativo: el SVG lleva `height="15.33"` en el HTML
   (ver ahí por qué), y sin esto esa altura queda como altura usada. El
   preserveAspectRatio entonces encoge TODO el arco para caber en 543×15 —un
   17% de su tamaño— y el texto se vuelve ilegible. */
.hero-arco { display: block; width: 100%; height: auto; margin-top: .75rem; }
/* El tamaño va al revés de lo que parece. Son unidades del viewBox (600 de
   ancho), así que lo que se ve en pantalla es `unidades × anchoDelArco / 600`,
   y el arco mide lo que mide el rótulo — que crece con el viewport. Con un
   valor fijo el texto se encogía justo donde el rótulo era chico: 21 unidades
   daban 21px a 1440 pero 12.6px a 721. Por eso la fórmula RESTA vw: al crecer
   la pantalla crece el arco, así que las unidades tienen que bajar para que el
   resultado se mantenga. Da ~20px de 720 para arriba y baja a 13px en teléfono.
   Un `clamp` normal (creciente) haría exactamente lo contrario. */
.hero-arco text {
  font-family: var(--font-texto); font-weight: 700;
  font-size: clamp(22px, 60px - 3.5vw, 36px);
  letter-spacing: .1em; fill: var(--cian); text-transform: uppercase;
}
.hero-sub { max-width: 46ch; margin-top: var(--sp-3); font-size: var(--t-cuerpo); color: var(--hueso); }
.hero-cta { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-3); }

/* Destellos: el diamante de cuatro puntas del rótulo, repartido por el marco.
   Titilan como los del vidrio pintado, cada uno con su propio ritmo: duraciones
   primas entre sí y arranques negativos para que el grupo nunca lata al unísono. */
.hero-destellos { position: absolute; inset: 0; pointer-events: none; }
.hero-destellos .destello {
  position: absolute; opacity: .85;
  animation: destello-titila 3.7s ease-in-out infinite;
}
/* Los .hd-* van anidados para igualar la especificidad de la regla de arriba:
   si no, su forma abreviada `animation` gana y los cuatro laten al unísono. */
.hero-destellos .hd-1 { top: 8%; right: 9%; width: 26px; height: 26px; animation-duration: 4.3s; animation-delay: -.4s; }
.hero-destellos .hd-2 { top: 26%; right: 20%; width: 15px; height: 15px; color: var(--cian); animation-duration: 2.9s; animation-delay: -1.7s; }
.hero-destellos .hd-3 { bottom: 16%; right: 13%; width: 20px; height: 20px; animation-duration: 5.1s; animation-delay: -2.6s; }
.hero-destellos .hd-4 { bottom: 34%; right: 27%; width: 12px; height: 12px; color: var(--naranja); animation-duration: 3.3s; animation-delay: -.9s; }
@keyframes destello-titila {
  0%, 100% { opacity: .9;  transform: scale(1); }
  42%      { opacity: .18; transform: scale(.7); }
  62%      { opacity: 1;   transform: scale(1.06); }
}
/* Con el muestrario puesto, dos de los cuatro destellos quedaban tapados por una
   lámina opaca: animándose donde nadie los ve. Se corren a las dos franjas que
   el apilado deja libres —arriba y abajo de él— y siguen siendo cuatro.
   Va acá abajo y no en el bloque de layout de la vitrina a propósito: mismo peso
   de selector que las reglas de arriba, así que gana por venir después. */
@media (min-width: 1024px) {
  .hero-destellos .hd-2 { top: 9%; right: 30%; }
  .hero-destellos .hd-4 { top: auto; bottom: 11%; right: 34%; }
}

/* ---------- El muestrario: la otra mitad de la vitrina ---------- */
/* Toda tienda de tatuajes tiene el folder de láminas sobre el mostrador. Eso es
   esto: las fotos de trabajo apiladas como prints, la de encima entera y las de
   los lados asomando por debajo, cortadas por el marco.
   Es un apilado plano a propósito: nada de perspectiva 3D ni de desenfoque en
   las láminas del fondo (ver DESIGN.md → Elevation). Las de atrás se apagan con
   un velo opaco, no con opacidad, para que el traslape lea como papel encima de
   papel y no como dos fotos transparentes superpuestas. */
.muestrario { display: grid; align-content: center; }
.muestrario[hidden] { display: none; }

/* El visor recorta. Es el borde del folder: las láminas de los lados siguen
   más allá y se cortan ahí, que es justo lo que hace leer que hay más.
   El padding de abajo-derecha existe para que el recorte no se coma la sombra
   dura de la lámina de encima. */
/* El padding es simétrico a los lados aunque la sombra solo caiga a la derecha:
   el recorte pasa por la caja de padding, así que un padding suelto de 8px a la
   derecha dejaba la puntita de esa lámina 8px más ancha que la de la izquierda. */
.muestrario-visor {
  position: relative; overflow: hidden; padding: 0 8px 8px;
  /* El apilado no tiene botones: se arrastra. El cursor es todo el aviso que
     hay en escritorio, y es el correcto —no ensucia el hero con cromo—. */
  cursor: grab;
  user-select: none;
  /* `pan-y` y no `none`: el gesto horizontal es nuestro, el vertical sigue
     siendo el scroll de la página. Sin esto, arrastrar en el teléfono deja al
     visitante trabado en el hero. */
  touch-action: pan-y;
}
.muestrario-visor.esta-arrastrando { cursor: grabbing; }

/* La escena ES la caja de la lámina de encima. Así las de los lados se
   desplazan en porcentaje de su propio tamaño, fácil de razonar. */
/* 2:3 es la proporción en la que vienen las fotos de trabajo (733×1100), así que
   la lámina no recorta nada en la mayoría. Y es la proporción de un print: la
   vertical alta es la que hace que lea como papel y no como miniatura. */
.muestrario-escena {
  position: relative; width: 76%; margin-inline: auto;
  aspect-ratio: 2 / 3;
}
.muestrario-lamina {
  position: absolute; inset: 0; margin: 0;
  border: 2px solid var(--negro-3); border-radius: var(--radio);
  background: var(--negro-2); overflow: hidden;
  transform-origin: 50% 50%;
  transition: transform .55s cubic-bezier(.2, .7, .2, 1);
}
/* `-webkit-user-drag` apaga el arrastre nativo de imagen del navegador, que si
   no se dispara antes que el nuestro y el visitante termina arrastrando una
   miniatura fantasma de la foto por la pantalla. */
.muestrario-lamina img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  -webkit-user-drag: none;
}
/* El velo de las láminas del fondo. Va en ::after y no en `opacity` para que la
   lámina siga siendo opaca: lo que se ve debajo de la de encima tiene que ser
   papel, no una foto translúcida. */
.muestrario-lamina::after {
  content: ""; position: absolute; inset: 0;
  background: var(--negro); opacity: .68;
  transition: opacity .55s cubic-bezier(.2, .7, .2, 1);
}

/* Fuera de las tres posiciones visibles la lámina no existe: `display: none`
   evita que 54 cajas absolutas se pinten y se transicionen sin que nadie las vea. */
.muestrario-lamina { display: none; }
.muestrario-lamina.es-centro,
.muestrario-lamina.es-antes,
.muestrario-lamina.es-despues { display: block; }

/* El arrastre entra dentro de cada `translateX` —y no en un contenedor aparte—
   para que cada lámina conserve su escala y su rotación mientras se mueve.
   Son DOS valores, no uno: `--arrastre` es lo que recorre la lámina de frente,
   pegada al dedo, y `--arrastre-fondo` es lo que recorren las de atrás, una
   fracción de eso. Con un solo valor las tres se movían en bloque y el gesto
   parecía agarrar el folder entero en vez de el print de encima.
   Mover *solo* la de frente no sirve: a 100px de recorrido ya se abre un hueco
   de 13px de fondo negro entre ella y la de atrás (medido). La fracción es lo
   que deja que la frontal despegue sin destapar nada. */
.muestrario-lamina.es-centro {
  z-index: 3;
  transform: translateX(var(--arrastre, 0px));
  box-shadow: 5px 5px 0 var(--rojo);
}
.muestrario-lamina.es-centro::after { opacity: 0; }
/* La rotación es mínima y en el plano —nada de rotateY—: son prints tirados en
   el folder, no tarjetas girando en el aire. */
.muestrario-lamina.es-antes  { z-index: 1; transform: translateX(calc(-62% + var(--arrastre-fondo, 0px))) scale(.82) rotate(-3deg); }
.muestrario-lamina.es-despues { z-index: 1; transform: translateX(calc(62% + var(--arrastre-fondo, 0px))) scale(.82) rotate(3deg); }
/* Mientras el dedo está abajo no hay transición: la lámina tiene que ir pegada
   al puntero. Con la transición puesta, el apilado llega tarde y se siente
   elástico en vez de agarrado. */
.muestrario-visor.esta-arrastrando .muestrario-lamina { transition: none; }

.muestrario-credito { margin-top: var(--sp-2); text-align: center; line-height: 1.25; }
/* Escalón de "título de tarjeta" (1.375rem en Rye) y de "texto de apoyo": el
   nombre del artista es el título de la lámina; el rótulo que lo precede y el
   usuario de Instagram son apoyo. */
.muestrario-credito b {
  display: block; font-family: var(--font-rotulo); font-weight: 400;
  color: var(--amarillo); font-size: var(--t-h3); line-height: 1.15;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.muestrario-credito span { font-size: var(--t-chico); color: var(--hueso-tenue); }
/* Solo devuelve la tipografía de interfaz: el tamaño y el color ya se los da la
   regla de arriba, que alcanza a cualquier span del crédito. En Rye, "Artista:"
   pesaría igual que el nombre y el par dejaría de leerse como rótulo + dato. */
.muestrario-credito-rotulo { font-family: var(--font-texto); font-weight: 600; }

/* +5% de lámina en escritorio, y sale del recorte, no de la columna: ensanchar
   la pista del muestrario le quitaría ancho al rótulo, que a 1024px ya está al
   límite. Las puntitas de los lados bajan de 48 a 42px, que sigue alcanzando
   para leer que hay más atrás.
   Va acá abajo y no en el bloque de layout de la vitrina —donde estaría más a
   mano— porque el `width: 76%` de la escena se declara después: mismo peso de
   selector, así que allá arriba perdía y la lámina no crecía. */
@media (min-width: 1024px) {
  .muestrario-escena { width: 80%; }
}

.hero-datos {
  display: flex; flex-wrap: wrap; gap: var(--sp-3);
  border-top: 2px solid var(--negro-3); border-bottom: 2px solid var(--negro-3);
  padding: var(--sp-3) 0; margin-top: var(--sp-4);
}
.hero-datos > div { flex: 1 1 180px; }
.hero-datos strong { display: block; font-family: var(--font-rotulo); font-weight: 400; color: var(--amarillo); font-size: var(--t-h3); line-height: 1.1; }
.hero-datos span { color: var(--hueso-tenue); font-size: var(--t-chico); }

/* ---------- Secciones ---------- */
.section { max-width: var(--max-ancho); margin: 0 auto; padding: var(--sp-6) 1.25rem; }
.section-head { max-width: 640px; margin-bottom: var(--sp-4); }
/* h1 y h2 juntos: en la portada cada sección es un h2 bajo el h1 del rótulo,
   pero en /agendar/ y /perforaciones/ este encabezado ES el título de la
   página y tiene que ser h1 —una página sin h1 le esconde a Google de qué
   trata—. Se ven igual porque cumplen el mismo papel; lo que cambia es el
   nivel, que es información, no estilo. */
.section-head h1,
.section-head h2 { font-family: var(--font-rotulo); font-weight: 400; color: var(--amarillo); font-size: var(--t-h2); }
.section-sub { display: block; margin-top: .75rem; color: var(--hueso-tenue); }

/* ---------- Divisores ornamentales ----------
   Motivos de carreta tica, en la misma paleta pintada del rótulo. Son adorno
   puro: van con alt="" para que un lector de pantalla los salte, y sin
   pointer-events para que nunca intercepten un clic ni se dejen arrastrar.

   El margen negativo es lo importante: dos .section seguidas ya dejan 12rem de
   aire (6rem de padding cada una). Sin recortarlo, el divisor sumaría su altura
   encima y el corte quedaría más lejos que el propio motivo. Con -4rem por lado
   el ornamento cae *dentro* del aire que ya existía. */
.divisor {
  display: block;
  width: min(100% - 2.5rem, 640px);
  height: auto;
  margin: calc(var(--sp-5) * -1) auto;
  pointer-events: none;
  user-select: none;
}

/* El hero no cierra con 6rem sino con 3: el recorte completo metería el trazo
   dentro de la vitrina. Acá el aire del hero alcanza tal cual. */
.hero + .divisor { margin-top: 0; }

@media (max-width: 720px) {
  /* Las secciones siguen con 6rem de padding en móvil, pero el motivo se
     achica con el ancho: si se mantuviera -4rem, los rizos del trazo casi
     tocarían el título de abajo. Menos recorte, mismo ritmo relativo. */
  .divisor { width: calc(100% - 2rem); margin: calc(var(--sp-4) * -1) auto; }
  .hero + .divisor { margin-top: 0; }
}

/* ---------- Tickets escondidos (huevo de pascua → casting de Maxito TV) ----
   Un boleto de feria metido detrás de la tarjeta opaca de su sección: en
   reposo asoma la pura puntita por debajo del borde. Hover o foco (escritorio)
   o el primer toque (móvil, js/tickets.js) lo deslizan afuera; el clic con el
   boleto afuera navega al formulario de casting.

   El truco de capas es al revés de lo intuitivo: el boleto NO lleva z-index
   negativo — con z -1 queda detrás del área de hit de su propia sección y la
   puntita se ve pero no recibe clics (comprobado con elementFromPoint). El
   boleto queda en capa normal y es LA TARJETA que lo tapa la que sube a
   z-index: 1 (.sede-panels acá, .wizard-card en booking.css). Encima de la
   tarjeta los clics son de la tarjeta; en la puntita, del boleto.

   bottom: var(--sp-6) = el padding inferior de .section, o sea el borde
   inferior exacto de la tarjeta que lo tapa. Los translate van en porcentaje
   para que la puntita escale con el ancho del boleto en móvil. */
.ticket-oculto {
  position: absolute;
  bottom: var(--sp-6);
  width: min(300px, 64vw);
  user-select: none;
  /* La curva de la casa (la misma de .reveal y el wizard): probé un overshoot
     con rebote y era el único rebote de todo el sitio — desentonaba. */
  transition: transform .5s cubic-bezier(.2, .7, .2, 1);
  /* La brisa. Un papel asomado se mueve, y ese movimiento es lo que delata el
     huevo de pascua sin regalarlo: la puntita quieta parece un adorno; la
     puntita que tiembla pide un dedo encima.

     Va sobre `rotate` y `translate` —las propiedades sueltas— y no sobre
     `transform`, porque `transform` ya lo administra la transición de arriba
     para guardar y sacar el boleto: una animación ahí se la pisaría. Las
     sueltas componen con `transform` sin tocarlo, así que el vaivén se suma a
     cualquier pose (guardado o afuera) sin pelear con ella. Un navegador que
     no las conozca ignora los fotogramas y deja el boleto quieto: se pierde la
     invitación, no el boleto. */
  animation: ticket-brisa 7s infinite;
}
/* La mano lo detiene: agarrado (hover, foco o el primer toque) el papel deja
   de flamear. `paused` y no `none` para que no dé un salto al soltarlo; el
   fotograma congelado es un tilde de ≤2.6° que se funde con la pose sacada. */
.ticket-oculto:hover,
.ticket-oculto:focus-visible,
.ticket-oculto.is-out { animation-play-state: paused; }
/* Ningún bucle corre fuera de pantalla: js/tickets.js marca el boleto cuando
   su sección sale del viewport, igual que js/script.js hace con el hero. */
.ticket-oculto.is-offscreen { animation-play-state: paused; }
/* Una ráfaga cada 7 segundos, no un péndulo. El vaivén parejo se lee como
   mecanismo; el viento de verdad es un tirón corto con dos rebotes que se
   apagan, y después calma chicha con apenas una deriva. Los grados son pocos
   porque giran alrededor del centro del boleto y la puntita visible está en el
   borde: 2.6° ahí son unos 6px de aleteo. El alzón de -3px en la ráfaga es el
   papel levantándose antes de volver a caer. */
@keyframes ticket-brisa {
  0%   { rotate: 0deg;    translate: 0 0; }
  14%  { rotate: 0.9deg; }
  28%  { rotate: -0.5deg; }
  38%  { rotate: 0.3deg;  translate: 0 0; }
  46%  { rotate: -2.6deg; translate: 0 -3px; }
  54%  { rotate: 1.8deg;  translate: 0 -1px; }
  62%  { rotate: -0.9deg; translate: 0 0; }
  72%  { rotate: 0.4deg; }
  100% { rotate: 0deg;    translate: 0 0; }
}
.ticket-oculto img { display: block; width: 100%; height: auto; }

/* El asset viene sin texto: el rótulo va en HTML sobre el cuerpo del boleto
   (la zona a la izquierda de la perforación, ~60% del ancho), igual que el
   grito. Colores del propio componente ticket: tinta roja o cian oscuro
   sobre hueso, como en css/ticket.css. */
/* Medidas del propio SVG (viewBox 1000×420): el panel interior del cuerpo va
   de x=51 a x=722 —la perforación está en 756— así que su centro cae en 38.6%,
   no en el 50% de la imagen completa. Calcar el panel es lo que hace que el
   texto quede ópticamente centrado dentro del marco ornamental. */
.ticket-oculto-rotulo {
  position: absolute; left: 5.1%; top: 50%; width: 67.1%;
  transform: translateY(-50%);
  display: grid; gap: .05rem; justify-items: center; text-align: center;
  /* Invisible mientras el boleto está guardado: la rotación hunde la esquina
     del lado del rótulo y un texto cortado asomando delataba el secreto.
     Aparece recién cuando el boleto sale. */
  opacity: 0;
  transition: opacity .3s ease .12s;
}
.ticket-oculto:hover .ticket-oculto-rotulo,
.ticket-oculto:focus-visible .ticket-oculto-rotulo,
.ticket-oculto.is-out .ticket-oculto-rotulo { opacity: 1; }
.ticket-oculto-rotulo strong {
  font-family: var(--font-rotulo); font-weight: 400;
  font-size: var(--t-h3); letter-spacing: .03em; text-transform: uppercase;
  line-height: 1;
}
.ticket-oculto-rotulo small {
  font-family: var(--font-texto); font-weight: 700;
  font-size: var(--t-micro); letter-spacing: .2em; text-transform: uppercase;
}

/* Cian: abajo a la derecha de la tarjeta de sedes (index). Sale casi entero:
   detrás tiene 160px de aire (padding de la sección + del grito). */
.ticket-oculto--cian { right: 6%; transform: translateY(26%) rotate(6deg); }
.ticket-oculto--cian:hover,
.ticket-oculto--cian:focus-visible,
.ticket-oculto--cian.is-out { transform: translateY(92%) rotate(9deg); }
.ticket-oculto--cian .ticket-oculto-rotulo { color: var(--cian-oscuro); }

/* Rojo: abajo a la izquierda del formulario del wizard (agendar). Sale menos
   (72%) porque debajo solo están los 96px del padding de la sección: más
   recorrido y el borde superior del footer le pasaría una línea por encima. */
.ticket-oculto--rojo { left: 6%; transform: translateY(26%) rotate(-5deg); }
.ticket-oculto--rojo:hover,
.ticket-oculto--rojo:focus-visible,
.ticket-oculto--rojo.is-out { transform: translateY(72%) rotate(-8deg); }
.ticket-oculto--rojo .ticket-oculto-rotulo { color: var(--rojo); }

/* El ancla del cian (la del rojo, .wizard-section, vive en booking.css), y la
   tarjeta de sedes levantada por encima del boleto: sin este z-index el boleto
   —posicionado y posterior en el DOM— pintaría encima de los paneles. */
.sedes { position: relative; }
.sede-panels { position: relative; z-index: 1; }

/* ---------- Grito de cierre ----------
   La estrella y el texto van los dos en el HTML, en SVG: el texto porque es un
   dato real del estudio y tiene que poder leerse, buscarse y traducirse; la
   estrella porque hay que poder pintarla desde el CSS.

   **Hueca y en cian, no rellena y amarilla.** El asset trae la estrella con el
   tratamiento del rótulo del hero —relleno amarillo, doble contorno rojo— y a
   este tamaño era una segunda marca peleándole al nombre del estudio en el
   único momento autoral de la página. Acá se usa solo el contorno de la
   silueta, dejando pasar el negro, exactamente como el globo de la viñeta (ver
   DESIGN.md → La viñeta: ahí se probó el relleno y se descartó por lo mismo).
   El cian es el color con el que habla el estudio; el amarillo es del rótulo.

   El ancho del texto es lo que hay que respetar. La estrella tiene radio
   interior ~177 sobre un lienzo de 660, así que el texto no llega ni a la mitad
   del ancho: más ancho que eso y las palabras se salen por las puntas. Con dos
   líneas, el semiancho útil sale de √(r² − alto²).

   El límite va en el ancho del SVG del texto y no en `padding` del contenedor:
   un padding en porcentaje se resuelve contra el *padre*, no contra el
   elemento, y acá el padre es la página entera — la estrella se inflaba a
   627px con el texto aplastado a cero. */
/* La línea para quien ya se tatuó, justo antes del cierre. Sin filete ni caja:
   el `.grito-cierre` que viene abajo ya es el remate visual de la página, y
   meterle un borde acá pondría dos cierres seguidos.

   El `padding-top` es el `--sp-6` con el que termina la sección anterior, y el
   `padding-bottom` es cero porque el `--sp-5` de `.grito-cierre` es el que
   separa: si los dos pusieran aire, entre la frase y la estrella quedarían
   160px de nada. */
.cierre-guia {
  max-width: 46ch; margin: 0 auto; padding: var(--sp-6) 1.25rem 0;
  text-align: center; font-size: var(--t-chico); line-height: 1.6;
  color: var(--hueso-tenue);
}

.grito-cierre { display: grid; place-items: center; padding: var(--sp-5) 1.25rem var(--sp-6); }
.grito {
  position: relative;
  display: grid; place-items: center;
  /* **El cartel es un tubo con luz recorriéndolo.** Antes era un contorno de
     3px sobre un campo negro enorme: poquísima tinta para el cierre. Ahora la
     misma silueta se dibuja tres veces (ver el `<use>` en index.html) y de ahí
     salen el cuerpo y el movimiento. */
  /* El piso de 220px no es estético: el cuerpo del texto sale de él. Son
     unidades del viewBox (200 de ancho), así que en pantalla se ven
     `20 × anchoDelTexto / 200`, y el ancho del texto es el 64% de la estrella.
     Por debajo de 220 la frase baja de 14px y deja de leerse en Rye. */
  width: clamp(220px, 24vw, 280px); aspect-ratio: 1;
}
.grito-estrella { position: absolute; inset: 0; width: 100%; height: 100%; }
/* `non-scaling-stroke` en las tres capas: el trazo se mide en píxeles de
   pantalla y no en unidades del viewBox, así que los tres grosores se sostienen
   en todo el rango del `clamp` sin recalcular nada. La línea sigue en 3px, el
   mismo grosor que el marco del globo de la viñeta. */
.grito-estrella use {
  fill: none; vector-effect: non-scaling-stroke; stroke-linejoin: round;
}
/* El recuadro: un contorno más grueso y oscuro detrás de la línea. Es el mismo
   recurso de dos capas del rótulo del hero —relleno con contorno de otro
   color—, traído al registro cian del cierre. Duplica la tinta del elemento
   sin agregar una sombra ni un desenfoque, que el sistema no tiene. */
.grito-borde { stroke: var(--cian-oscuro); stroke-width: 9; }
.grito-linea { stroke: var(--cian); stroke-width: 3; }
/* El brillo que le da la vuelta, como la aguja de un reloj. Es un tercer
   contorno del que solo se ve un tramo: `stroke-dasharray` deja ese pedazo
   visible y el resto en hueco, y animar `stroke-dashoffset` lo empuja por el
   perímetro entero.

   **Los números están en unidades del viewBox y son del asset.** El perímetro
   de esta estrella mide **2857** (28 vértices, sumadas las 28 aristas), así que
   400 es un tramo del 14% y el hueco es el resto. Se intentó con
   `pathLength="100"` para poder escribirlo en porcentajes y **este navegador no
   lo respeta sobre un `<polygon>`**: con `50 50` tendría que pintarse media
   estrella y salieron rayitas de 50 unidades sobre un recorrido de 2857,
   invisibles. Si algún día cambia la polilínea hay que recalcular el perímetro
   —es la misma dependencia a mano que ya tiene la lista de puntos, ver
   DESIGN.md → El grito de cierre.

   `linear` y no una curva suave: una aguja de reloj no acelera. 7s da una
   vuelta lenta que se nota sin pedir la mirada, al final de la página.

   **5px y no 3, y esto se probó mirando el resultado.** Con el mismo grosor que
   la línea, el hueso sobre el cian no se distinguía: el tramo pasaba y no se
   veía pasar nada. A 5 el trazo engorda al pasar la luz, que es lo que hace
   leer el efecto como un brillo recorriendo el tubo y no como un cambio de
   color. */
.grito-brillo {
  stroke: var(--hueso); stroke-width: 5;
  stroke-dasharray: 400 2457;
  animation: grito-vuelta 7s linear infinite;
}
/* Una vuelta entera = el perímetro completo, 2857. Negativo para que el tramo
   avance en el sentido en que está escrita la polilínea, que es el del reloj. */
@keyframes grito-vuelta { to { stroke-dashoffset: -2857; } }
/* Ningún bucle corre a ciegas: js/script.js marca la sección cuando sale del
   viewport, igual que con el hero y con los boletos. */
.grito-cierre.is-offscreen .grito-brillo { animation-play-state: paused; }

.grito-texto { position: relative; width: 64%; height: auto; }
.grito-texto text {
  font-family: var(--font-rotulo); font-weight: 400;
  font-size: 20px; letter-spacing: .04em;
  text-transform: uppercase; fill: var(--cian);
}

.reveal { opacity: 0; transform: translateY(24px); transition: opacity .6s cubic-bezier(.2,.7,.2,1), transform .6s cubic-bezier(.2,.7,.2,1); }
.reveal.is-visible { opacity: 1; transform: translateY(0); }

/* ---------- Filtros ---------- */
.filters-label {
  font-size: var(--t-micro); font-weight: 600; letter-spacing: .22em;
  text-transform: uppercase; color: var(--cian); margin: 0 0 .6rem;
}
.filters { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: var(--sp-3); }
.filter-chip {
  font-family: var(--font-texto); font-weight: 700; font-size: var(--t-micro);
  letter-spacing: .08em; text-transform: uppercase; padding: .5rem .9rem;
  border: 2px solid var(--negro-3); border-radius: var(--radio);
  background: transparent; color: var(--hueso-tenue);
  transition: border-color .2s, color .2s, background .2s, box-shadow .2s;
}
.filter-chip:hover { border-color: var(--cian); color: var(--cian); }
.filter-chip.is-active { background: var(--amarillo); border-color: var(--amarillo); color: var(--negro); box-shadow: 3px 3px 0 var(--rojo); }

/* Cada sede tiene su color del rótulo: Los Yoses amarillo, Heredia cian. La
   sombra dura acompaña al relleno —rojo bajo el amarillo, cian oscuro bajo el
   cian—, igual que el botón fantasma de marca.css. Tres clases le ganan por
   especificidad a `.is-active` y a `:hover`, así que el orden no importa: la
   regla de sedes vive más abajo en el archivo y aun así pierde. */
.filter-chip.is-cian.is-active,
.sede-tab.is-cian.is-active {
  background: var(--cian); border-color: var(--cian); color: var(--negro);
  box-shadow: 3px 3px 0 var(--cian-oscuro);
}
.filters-style { margin-bottom: var(--sp-4); }

/* El botón para desplegar los estilos solo existe en teléfono: en escritorio
   los 18 chips entran en dos filas y esconderlos sería quitar de la vista un
   índice que ya se lee de un vistazo. */
.filters-mas { display: none; }

@media (max-width: 720px) {
  /* 19 chips ocupaban 10 filas y 412px —media pantalla— antes de llegar al
     primer tatuador. Plegados quedan dos: el chip activo y el botón.
     Se pliega con `display: none` y no con una altura máxima a propósito: un
     recorte por altura parte el chip de la última fila por la mitad y deja
     medio botón asomando, que se lee como error de render y no como "hay más". */
  .filters-style .filter-chip { display: none; }
  /* Dos chips sobreviven al plegado. El activo, porque es lo único que dice por
     qué el roster muestra 4 nombres en vez de 23. Y "Todos los estilos", porque
     es la salida: sin él hay que desplegar la lista entera para poder quitar un
     filtro, dos toques para deshacer uno. */
  .filters-style .filter-chip.is-active,
  .filters-style .filter-chip[data-style-filter="all"] { display: block; }
  .filters-style.esta-abierta .filter-chip { display: block; }

  .filters-mas {
    display: inline-flex; align-items: center; gap: .4rem;
    font-family: var(--font-texto); font-weight: 700; font-size: var(--t-micro);
    letter-spacing: .08em; text-transform: uppercase; padding: .5rem .9rem;
    border: 2px dashed var(--negro-3); border-radius: var(--radio);
    background: transparent; color: var(--cian);
    transition: border-color .2s, color .2s;
  }
  /* Borde punteado y no sólido: no es un filtro más, es la puerta a los que
     faltan. Con el mismo borde de los chips se leería como un estilo llamado
     "ver todos los estilos". */
  .filters-mas:hover, .filters-mas:focus-visible { border-color: var(--cian); color: var(--cian-luz); }
  .filters-mas::after {
    content: ""; width: 7px; height: 7px;
    border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
    transform: translateY(-2px) rotate(45deg);
    transition: transform .25s cubic-bezier(.2, .7, .2, 1);
  }
  .filters-mas[aria-expanded="true"]::after { transform: translateY(1px) rotate(-135deg); }
}

/* ---------- Roster de artistas ---------- */
.roster {
  position: relative; isolation: isolate; overflow: hidden; min-height: 620px;
  border: 3px solid var(--negro-3); border-radius: var(--radio);
  background: var(--negro-2); padding: 3.2rem 1.5rem;
}
.roster-bg {
  position: absolute; inset: 0; z-index: 0; background-size: cover; background-position: center;
  opacity: 0; transform: scale(1.08); transition: opacity .6s ease, transform 1.4s cubic-bezier(.2,.7,.2,1);
}
.roster-bg.is-active { opacity: .34; transform: scale(1); }
.roster-bg-overlay {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(0deg, var(--negro-2) 0%, rgba(15,15,14,.86) 45%, rgba(15,15,14,.55) 100%);
}
.roster-list { position: relative; z-index: 2; max-width: 720px; margin: 2.4rem auto 0; }
.roster-row {
  display: flex; align-items: center; gap: 1.25rem;
  padding: .9rem 0; border-bottom: 2px solid var(--negro-3); cursor: pointer; transition: border-color .25s;
}
.roster-row:last-child { border-bottom: none; }
.roster-row:hover, .roster-row.is-active { border-color: var(--cian-oscuro); }
.roster-identity { display: flex; align-items: center; gap: .85rem; flex: 1 1 auto; min-width: 0; }
/* La fila activa crece un poco. Va con `transform` y no con `width`/`font-size`
   porque un cambio de caja recalcula la lista entera y las 23 filas dan un
   brinco; el transform no toca el layout, así que solo se mueve la fila que se
   está mirando. La escala del avatar se come 3px del hueco de .85rem contra el
   nombre — entra sin tocarlo. */
/* La foto entra como elemento imagen hijo y ya no como `background-image` (ver
   roster.js: es lo que permite diferir la carga). El degradado de iniciales sí
   sigue siendo fondo, porque ahí no hay archivo que pedir. Y `overflow: hidden`
   es lo que recorta la foto al círculo ahora que es un elemento y no un
   relleno — antes lo hacía el propio `border-radius` sobre el fondo. */
.roster-avatar {
  flex: 0 0 auto; width: 44px; height: 44px; border-radius: 50%; overflow: hidden;
  border: 2px solid var(--negro-3);
  display: grid; place-items: center; font-weight: 700; font-size: var(--t-micro);
  color: var(--hueso-tenue);
  transition: border-color .25s, transform .3s cubic-bezier(.2, .7, .2, 1);
}
.roster-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.roster-row.is-active .roster-avatar { border-color: var(--amarillo); transform: scale(1.16); }
/* `transform-origin: left`: centrado, el nombre crecería hacia los dos lados y
   se despegaría del avatar. Anclado a la izquierda crece solo hacia adelante,
   como si el renglón se acercara. */
.roster-name {
  font-family: var(--font-rotulo); font-weight: 400; color: var(--hueso);
  font-size: var(--t-h3); line-height: 1;
  transform-origin: left center;
  transition: color .25s, transform .3s cubic-bezier(.2, .7, .2, 1);
}
.roster-row.is-active .roster-name { color: var(--amarillo); transform: scale(1.08); }
.roster-meta {
  display: flex; gap: 1rem; font-size: var(--t-micro); font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase; color: var(--hueso-tenue); white-space: nowrap;
}
.roster-meta span { min-width: 8ch; }
.roster-ig {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 50%; border: 2px solid var(--negro-3); color: var(--cian);
  transition: border-color .2s, color .2s;
}
.roster-ig svg { width: 16px; height: 16px; }
.roster-ig:hover, .roster-ig:focus-visible { border-color: var(--cian); color: var(--cian-luz); }
.roster-row[hidden] { display: none; }

.roster-corners { position: absolute; inset: 0; z-index: 3; pointer-events: none; }
.roster-corner { position: absolute; font-size: var(--t-micro); font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: var(--hueso-tenue); }
.roster-corner-tl { top: 1.4rem; left: 1.4rem; }
/* `filter: drop-shadow` y no `box-shadow`: la L no tiene relleno, son dos
   bordes. box-shadow proyectaría el cuadrado de 20×20 entero; drop-shadow
   sigue lo que está pintado, así que la sombra también es una L. */
.roster-bracket {
  display: block; width: 20px; height: 20px;
  border-top: 3px solid var(--amarillo); border-left: 3px solid var(--amarillo);
  filter: drop-shadow(3px 3px 0 var(--rojo));
}
.roster-corner-bl { bottom: 1.4rem; left: 1.4rem; }
.roster-corner-br { bottom: 1.4rem; right: 1.4rem; color: var(--amarillo); font-variant-numeric: tabular-nums; }
.roster-clock-blink { animation: roster-blink 1.2s step-start infinite; }
@keyframes roster-blink { 50% { opacity: 0; } }

@media (max-width: 720px) {
  .roster { padding: 4rem 1.1rem 3rem; min-height: 0; }
  .roster-meta { display: none; }
  .roster-corner-bl { display: none; }
}

/* ---------- Modal de artista ---------- */
body.modal-open { overflow: hidden; }
.artist-modal { position: fixed; inset: 0; z-index: 100; display: flex; align-items: center; justify-content: center; padding: 2rem 1.2rem; }
.artist-modal[hidden] { display: none; }
.artist-modal-backdrop { position: absolute; inset: 0; background: rgba(15,15,14,.9); animation: modal-fade .25s ease; }
.artist-modal-panel {
  position: relative; z-index: 1; width: 100%; max-width: 640px; max-height: 88vh; overflow-y: auto;
  background: var(--negro-2); border: 3px solid var(--negro-3); border-radius: var(--radio);
  padding: 2rem; animation: modal-pop .28s cubic-bezier(.2,.7,.2,1);
}
@keyframes modal-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes modal-pop { from { opacity: 0; transform: translateY(14px) scale(.97); } to { opacity: 1; transform: translateY(0) scale(1); } }
.artist-modal-close {
  position: absolute; top: 1.1rem; right: 1.1rem; z-index: 2; width: 36px; height: 36px; border-radius: 50%;
  border: 2px solid var(--negro-3); background: transparent; color: var(--hueso-tenue);
  display: inline-flex; align-items: center; justify-content: center; transition: border-color .2s, color .2s;
}
.artist-modal-close svg { width: 15px; height: 15px; }
.artist-modal-close:hover, .artist-modal-close:focus-visible { border-color: var(--cian); color: var(--cian); }
.artist-modal-head { display: flex; align-items: center; gap: 1.1rem; margin-bottom: 1.3rem; padding-right: 2.4rem; }
.artist-modal-photo {
  width: 76px; height: 76px; border-radius: 50%; flex-shrink: 0;
  background-size: cover; background-position: center; border: 2px solid var(--negro-3);
  display: grid; place-items: center; font-weight: 700; font-size: var(--t-cuerpo); color: var(--hueso-tenue);
}
.artist-modal-name-row { display: flex; align-items: center; gap: .7rem; }
.artist-modal-name { font-family: var(--font-rotulo); font-weight: 400; color: var(--amarillo); font-size: var(--t-h3); }
.artist-modal-ig { width: 28px; height: 28px; }
.artist-modal-ig svg { width: 14px; height: 14px; }
.artist-modal-meta {
  margin-top: .3rem; font-size: var(--t-micro); font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; color: var(--cian);
}
/* Los demás estilos del artista, entre la meta y la bio.
   NO usan `.filter-chip` aunque se parezcan: aquellos se tocan y filtran el
   roster, estos solo informan. Darles el mismo dibujo prometería un clic que
   no existe, así que van sin fondo, con borde fino y en el gris del texto
   secundario — se leen como etiqueta de dato, no como control.
   La especialidad no está en esta lista: ya va arriba, en `.artist-modal-meta`,
   y en cian. */
.artist-modal-estilos { margin-top: var(--sp-2); }
.artist-modal-estilos[hidden] { display: none; }
/* El rótulo del grupo va en el micro del sistema y en el gris tenue, no en
   cian: el cian de esta tarjeta ya lo tiene la especialidad, y dos cianes
   compitiendo en la misma columna la dejarían sin jerarquía. */
.artist-modal-estilos-rotulo {
  margin: 0 0 .4rem; font-size: var(--t-micro); font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; color: var(--hueso-tenue);
  opacity: .75;
}
.artist-modal-estilos-rotulo:not(:first-child) { margin-top: .7rem; }
.artist-modal-estilos-lista {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: .4rem;
}
.artist-modal-estilos-lista li {
  padding: .25rem .55rem;
  border: 1px solid var(--negro-3);
  border-radius: var(--radio);
  color: var(--hueso-tenue);
  font-size: var(--t-micro); font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase;
}

.artist-modal-bio { color: var(--hueso-tenue); font-size: var(--t-chico); line-height: 1.7; margin-top: var(--sp-2); }
.artist-modal-bio.is-placeholder { font-style: italic; }
.artist-modal-works { display: grid; grid-template-columns: repeat(3, 1fr); gap: .7rem; margin-top: var(--sp-3); }
.artist-modal-tile {
  aspect-ratio: 1; border-radius: var(--radio); overflow: hidden; background: var(--negro);
  border: 2px solid var(--negro-3); display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: .4rem;
}
.artist-modal-tile img { width: 100%; height: 100%; object-fit: cover; transition: transform .35s; }
.artist-modal-tile svg { width: 26px; height: 26px; }
.artist-modal-tile span { font-size: var(--t-micro); color: var(--hueso-tenue); text-align: center; padding: 0 .3rem; line-height: 1.2; }
.artist-modal-tile.is-clickable { position: relative; cursor: pointer; animation: tile-invite 2.8s ease-in-out infinite; }
.artist-modal-tile.is-clickable:hover img, .artist-modal-tile.is-clickable:focus-visible img { transform: scale(1.08); }
.artist-modal-tile.is-clickable:focus-visible { outline: 3px solid var(--amarillo); outline-offset: 3px; }
@keyframes tile-invite {
  0%, 100% { border-color: var(--negro-3); }
  50% { border-color: var(--amarillo-sombra); }
}
.artist-modal-tile-hint {
  position: absolute; right: 6px; bottom: 6px; z-index: 1; width: 24px; height: 24px; border-radius: 50%;
  background: rgba(15,15,14,.75); border: 2px solid var(--negro-3); color: var(--amarillo);
  display: grid; place-items: center; opacity: .9; transition: opacity .2s, transform .2s;
}
.artist-modal-tile-hint svg { width: 12px; height: 12px; }
.artist-modal-tile.is-clickable:hover .artist-modal-tile-hint,
.artist-modal-tile.is-clickable:focus-visible .artist-modal-tile-hint { opacity: 1; transform: scale(1.12); }

@media (max-width: 560px) {
  .artist-modal-panel { padding: 1.5rem; }
  .artist-modal-works { grid-template-columns: repeat(2, 1fr); }
}

/* ---------- Galería ---------- */
.gallery-modal { position: fixed; inset: 0; z-index: 110; display: flex; align-items: center; justify-content: center; padding: 2rem; }
.gallery-modal[hidden] { display: none; }
.gallery-modal-backdrop { position: absolute; inset: 0; background: rgba(15,15,14,.95); animation: modal-fade .2s ease; }
.gallery-modal-img {
  position: relative; z-index: 1; max-width: min(88vw, 900px); max-height: 84vh;
  border-radius: var(--radio); object-fit: contain; animation: modal-pop .25s cubic-bezier(.2,.7,.2,1);
}
.gallery-modal-close, .gallery-modal-nav {
  position: absolute; z-index: 2; border-radius: 50%; border: 2px solid var(--negro-3);
  background: rgba(15,15,14,.7); color: var(--hueso);
  display: inline-flex; align-items: center; justify-content: center; transition: border-color .2s, color .2s;
}
.gallery-modal-close { top: 1.4rem; right: 1.4rem; width: 38px; height: 38px; }
.gallery-modal-close svg { width: 16px; height: 16px; }
.gallery-modal-nav { top: 50%; transform: translateY(-50%); width: 46px; height: 46px; }
.gallery-modal-nav svg { width: 20px; height: 20px; }
.gallery-modal-close:hover, .gallery-modal-close:focus-visible,
.gallery-modal-nav:hover, .gallery-modal-nav:focus-visible { border-color: var(--amarillo); color: var(--amarillo); }
.gallery-modal-prev { left: 1rem; }
.gallery-modal-next { right: 1rem; }
.gallery-modal-nav[hidden] { display: none; }

@media (max-width: 560px) {
  .gallery-modal { padding: 1rem; }
  .gallery-modal-nav { width: 38px; height: 38px; }
  .gallery-modal-prev { left: .4rem; }
  .gallery-modal-next { right: .4rem; }
}

/* ---------- Estilos: la galería ---------- */
/* Grilla y no carril: con 18 estilos el carril horizontal escondía dos tercios
   del catálogo detrás de un scroll que nadie hace. `auto-fill` con un mínimo de
   180px da 5 columnas en escritorio y 2 en teléfono sin ningún breakpoint.
   Las celdas cuadradas: las fotos vienen 2:3 y el recorte a cuadrado las
   empareja con los íconos, que son cuadrados por naturaleza. */
/* El mínimo cede en teléfono: con 180px fijos, a 375 de viewport solo entraba
   UNA columna y la sección medía seis mil píxeles. `min(180px, 42vw)` deja el
   mínimo en 157 justo ahí y la grilla vuelve a dos columnas, sin breakpoint. */
.estilo-galeria { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(180px, 42vw), 1fr)); gap: var(--sp-2); }
.estilo-celda {
  position: relative; aspect-ratio: 1; overflow: hidden;
  border: 2px solid var(--negro-3); border-radius: var(--radio);
  background: var(--negro-2); padding: 0; cursor: pointer;
  transition: border-color .25s;
}
.estilo-celda:hover { border-color: var(--cian-oscuro); }
.estilo-celda img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform .35s cubic-bezier(.2, .7, .2, 1);
}
.estilo-celda:hover img, .estilo-celda:focus-visible img { transform: scale(1.08); }
.estilo-celda-icono { position: absolute; inset: 0; display: grid; place-items: center; }
.estilo-celda-icono svg { width: 52px; height: 52px; }

/* La lupa aparece en hover/foco sobre un velo sólido —nada de blur, el sistema
   no tiene desenfoques—. En táctil ni hover ni lupa: el rótulo de abajo ya dice
   que la celda es un botón. */
.estilo-celda-velo {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: rgba(15, 15, 14, .55); color: var(--hueso);
  opacity: 0; transition: opacity .25s;
}
.estilo-celda-velo svg { width: 30px; height: 30px; }
.estilo-celda:hover .estilo-celda-velo, .estilo-celda:focus-visible .estilo-celda-velo { opacity: 1; }

/* El nombre va siempre a la vista, en una placa sólida abajo: en táctil no hay
   hover, y una grilla de fotos sin rotular obliga a abrirlas una por una. */
.estilo-celda-nombre {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: .45rem .6rem;
  background: rgba(15, 15, 14, .82);
  font-family: var(--font-rotulo); font-weight: 400; font-size: 1.05rem;
  color: var(--amarillo); text-align: center; line-height: 1.15;
}

/* ---------- Visor de estilos ---------- */
.estilo-modal { position: fixed; inset: 0; z-index: 100; display: flex; align-items: center; justify-content: center; padding: 2rem 1.2rem; }
.estilo-modal[hidden] { display: none; }
.estilo-modal-backdrop { position: absolute; inset: 0; background: rgba(15, 15, 14, .9); animation: modal-fade .25s ease; }
.estilo-modal-panel {
  position: relative; z-index: 1; width: min(100%, 760px); max-height: 88vh; overflow-y: auto;
  display: grid; grid-template-columns: minmax(0, 300px) 1fr; gap: var(--sp-3);
  background: var(--negro-2); border: 3px solid var(--negro-3); border-radius: var(--radio);
  padding: var(--sp-4); animation: modal-pop .25s cubic-bezier(.2, .7, .2, 1);
}
.estilo-modal-cerrar {
  position: absolute; top: 1rem; right: 1rem; z-index: 2;
  width: 38px; height: 38px; border-radius: 50%; border: 2px solid var(--negro-3);
  background: rgba(15, 15, 14, .7); color: var(--hueso);
  display: inline-flex; align-items: center; justify-content: center; transition: border-color .2s, color .2s;
}
.estilo-modal-cerrar svg { width: 16px; height: 16px; }
.estilo-modal-cerrar:hover, .estilo-modal-cerrar:focus-visible { border-color: var(--amarillo); color: var(--amarillo); }
/* El marco del visual conserva el 2:3 de las fotos —acá no se recortan, la
   celda cuadrada era por la grilla—. El ícono, cuando no hay foto, se sienta
   en el mismo marco para que el modal no cambie de tamaño entre estilos. */
.estilo-modal-visual {
  aspect-ratio: 2 / 3; border-radius: var(--radio); overflow: hidden;
  background: var(--negro); border: 2px solid var(--negro-3);
  display: grid; place-items: center;
}
.estilo-modal-visual img { width: 100%; height: 100%; object-fit: cover; display: block; }
.estilo-modal-visual svg { width: 96px; height: 96px; }
.estilo-modal-info { display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; }
.estilo-modal-info h3 { font-family: var(--font-rotulo); font-weight: 400; color: var(--amarillo); font-size: var(--t-h2); line-height: 1.1; padding-right: 2.5rem; }
.estilo-modal-info p { color: var(--hueso); }
.estilo-modal-credito { color: var(--hueso-tenue); font-size: var(--t-chico); }
.estilo-modal-nav { display: flex; gap: .6rem; margin-top: auto; }
.estilo-modal-flecha {
  width: 44px; height: 44px; border-radius: 50%; border: 2px solid var(--negro-3);
  background: transparent; color: var(--hueso);
  display: inline-flex; align-items: center; justify-content: center; transition: border-color .2s, color .2s;
}
.estilo-modal-flecha svg { width: 18px; height: 18px; }
.estilo-modal-flecha:hover, .estilo-modal-flecha:focus-visible { border-color: var(--amarillo); color: var(--amarillo); }

@media (max-width: 640px) {
  /* Apilado: el visual arriba a media altura para que la ficha entre sin
     scroll interno en la mayoría de teléfonos. */
  .estilo-modal-panel { grid-template-columns: 1fr; padding: var(--sp-3); }
  .estilo-modal-visual { aspect-ratio: auto; height: 42vh; }
}

/* ---------- La viñeta: el personaje del estudio habla ---------- */
/* Esta sección cita el lenguaje del cómic —globo de diálogo con cola y esquinas
   redondas— y es la única del sitio que lo hace. No es una fuga del sistema:
   la marca del estudio YA es un personaje de cómic, así que dejarlo hablar en
   un globo es hablar su propio idioma. El globo va en cian, el mismo marco que
   tenía el pizarrón de acera antes de esta sección.

   El personaje sale de `assets/logo-mark.png`, el arte real. Nunca se redibuja. */
/* `.undecided` ya no recorta su padding de arriba. Lo tenía en 0 desde que la
   sección era una caja oscura más, casi continua con la anterior; ahora que el
   globo es hueso —una figura recortada, no una superficie— necesita el mismo
   aire de los dos lados. Con 0 arriba quedaba 96px contra 192px abajo, y la
   viñeta se leía como apéndice de "Lo que tatuamos". */

/* ---------- Bocadillo de cómic ----------
   Marco y esquinas de `assets/bocadillo-cian.svg`, pero **sin el relleno**: el
   globo deja ver el negro de la página, como el resto del sitio.

   Por eso la sombra va con `box-shadow` y no con el `filter: drop-shadow` del
   asset. drop-shadow sigue la silueta *pintada*: sin relleno, lo único opaco
   son el marco y las letras, así que dibujaba un fantasma cian de cada palabra.
   Una box-shadow externa, en cambio, el navegador la recorta a la parte de
   afuera de la caja — no se cuela por debajo de un fondo transparente— y deja
   solo el filo desplazado abajo y a la derecha, que es el registro corrido de
   una impresión de cómic. */
.bocadillo {
  background: transparent;
  border: 3px solid var(--rojo);
  border-radius: 30px;
  box-shadow: 6px 7px 0 var(--rojo-oscuro);
}
.bocadillo--cian {
  border-color: var(--cian);
  box-shadow: 6px 7px 0 var(--cian-oscuro);
}
.undecided-escena {
  display: flex; align-items: center; justify-content: center;
  gap: clamp(.5rem, 3vw, 2rem); max-width: 900px; margin: 0 auto;
}

/* El guiño vive dentro del propio WebP animado (49 cuadros, loop de 4s), así
   que acá no hay animación CSS: dos guiños superpuestos se pelearían. */
.undecided-personaje { position: relative; flex: 0 0 auto; width: clamp(130px, 22vw, 235px); }
.undecided-personaje img { width: 100%; height: auto; }

/* 480px = la medida del párrafo (~44ch) más el padding y el borde. Antes el
   globo iba a 560 pero el texto se cortaba en 44ch, y quedaban 83px muertos
   contra el borde derecho. Ahora el globo abraza al texto. */
/* Solo la disposición: el marco, las esquinas y la sombra los pone `.bocadillo`. */
.undecided-bocadillo {
  position: relative; flex: 1 1 420px; max-width: 480px;
  padding: var(--sp-4) var(--sp-3);
}
/* La cola: dos triángulos superpuestos, el cian hace de contorno y el negro
   de relleno. Ese negro es el de la página, no un relleno del globo: es la
   única forma de "vaciar" un triángulo hecho con bordes CSS.
   Sale del borde izquierdo a la altura de la boca del personaje. El asset la
   trae bajando hacia el hombro, pero acá el personaje está al lado, no
   debajo: la cola apunta a su boca, que era el pedido original. */
.undecided-bocadillo::before,
.undecided-bocadillo::after {
  content: ''; position: absolute; top: 62%; width: 0; height: 0;
  border-top: 15px solid transparent; border-bottom: 15px solid transparent;
}
.undecided-bocadillo::before { left: -27px; border-right: 27px solid var(--cian); }
.undecided-bocadillo::after  { left: -21px; border-right: 22px solid var(--negro); }

.undecided-bocadillo h2 { font-family: var(--font-rotulo); font-weight: 400; color: var(--amarillo); font-size: var(--t-h2); }
/* Sin `max-width`: la medida ya la fija el globo, y duplicarla acá era lo que
   dejaba el hueco a la derecha. */
.undecided-bocadillo p { margin: var(--sp-2) 0 var(--sp-3); color: var(--hueso-tenue); }
/* La salida secundaria bajo el botón. Chica y con el filete arriba para que se
   lea como una nota al pie del globo y no como un segundo llamado compitiendo
   con el botón: son dos caminos de distinto peso, no dos opciones iguales.
   `margin-bottom: 0` porque es lo último del globo y el padding ya cierra. */
.undecided-otras {
  margin: var(--sp-3) 0 0; padding-top: var(--sp-3);
  border-top: 2px solid var(--negro-3);
  font-size: var(--t-chico); line-height: 1.6;
}

@media (max-width: 720px) {
  /* Apilado con el bocadillo arriba y el personaje abajo. `column-reverse` da
     ese orden visual sin tocar el DOM: el personaje es decorativo y va con
     aria-hidden, así que el orden de lectura no se altera. */
  .undecided-escena { flex-direction: column-reverse; gap: 0; }
  /* El margen tiene que despejar la cola, no el globo. La cola baja 26px por
     debajo del borde inferior, así que con los 0.75rem de antes el personaje
     le entraba 14px encima y parecía pegado. 2.75rem deja 18px de aire limpio
     entre la punta y la cabeza. Si la cola cambia de alto, este número va
     detrás. */
  .undecided-personaje { width: 150px; margin-top: 2.75rem; z-index: 1; }
  .undecided-bocadillo { flex: 1 1 auto; width: 100%; text-align: center; }
  .undecided-bocadillo p { margin-inline: auto; }
  /* La cola baja del borde inferior, con los dos triángulos centrados sobre el
     mismo eje para que salga simétrica y apunte al personaje. */
  .undecided-bocadillo::before,
  .undecided-bocadillo::after { bottom: auto; border-bottom: none; }
  .undecided-bocadillo::before {
    left: calc(50% - 16px); top: 100%;
    border-left: 16px solid transparent; border-right: 16px solid transparent;
    border-top: 26px solid var(--cian);
  }
  .undecided-bocadillo::after {
    left: calc(50% - 12px); top: calc(100% - 5px);
    border-left: 12px solid transparent; border-right: 12px solid transparent;
    border-top: 20px solid var(--negro);
  }
}

/* ---------- Sedes ---------- */
.sede-tabs { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: var(--sp-3); }
.sede-tab {
  font-family: var(--font-texto); font-weight: 700; font-size: var(--t-micro);
  letter-spacing: .08em; text-transform: uppercase; padding: .6rem 1.2rem;
  border: 2px solid var(--negro-3); border-radius: var(--radio);
  background: transparent; color: var(--hueso-tenue); transition: border-color .2s, color .2s, background .2s, box-shadow .2s;
}
.sede-tab:hover { border-color: var(--cian); color: var(--cian); }
.sede-tab.is-active { background: var(--amarillo); border-color: var(--amarillo); color: var(--negro); box-shadow: 3px 3px 0 var(--rojo); }
/* Cada sede se pinta con su propio color del rótulo, y las dos son opuestas:
   Los Yoses lleva el amarillo en el título, el botón y el alfiler, con los
   íconos en cian; Heredia invierte el par. Es el mismo reparto que ya tenían
   su pestaña y su chip del roster.

   El acento viaja por custom properties y no por reglas por clase a propósito.
   Las propiedades se heredan, así que cada regla de abajo lee siempre la misma
   variable y es el panel el que decide su valor: no hay dos reglas compitiendo
   por especificidad ni un orden de archivo que respetar. Con reglas por clase,
   `.sede-panel--cian h3` y `.sede-panel h3` pesan exactamente igual y gana la
   última escrita — una trampa que ya se pagó dos veces en este archivo. */
.sede-panel {
  --acento: var(--amarillo);
  --acento-luz: var(--amarillo-luz);
  --acento-sombra: var(--rojo);
  --acento-icono: var(--cian);
  display: none; grid-template-columns: 1.1fr .9fr; gap: var(--sp-4);
  background: var(--negro-2); border: 2px solid var(--negro-3); border-radius: var(--radio); padding: var(--sp-4);
}
.sede-panel--cian {
  --acento: var(--cian);
  --acento-luz: var(--cian-luz);
  --acento-sombra: var(--cian-oscuro);
  --acento-icono: var(--amarillo);
}
.sede-panel.is-active { display: grid; }
.sede-panel h3 { font-family: var(--font-rotulo); font-weight: 400; color: var(--acento); font-size: var(--t-h3); margin-bottom: .6rem; }
.sede-panel p { color: var(--hueso-tenue); }
/* Cómo llegar. Toma prestado el vocabulario del chip —micro en mayúsculas,
   borde de 2px, radio 4— porque es lo mismo que es: un par de controles chicos.
   No lleva relleno activo: son salidas del sitio, no filtros, así que se quedan
   en el registro tranquilo hasta que alguien las apunta, y ahí toman el acento
   de su sede. */
.sede-comollegar { display: flex; flex-wrap: wrap; gap: .5rem; }
.sede-comollegar a {
  display: inline-flex; align-items: center; gap: .45rem;
  font-family: var(--font-texto); font-weight: 700; font-size: var(--t-micro);
  letter-spacing: .08em; text-transform: uppercase;
  padding: .5rem .9rem;
  border: 2px solid var(--negro-3); border-radius: var(--radio);
  color: var(--hueso-tenue); text-decoration: none;
  transition: border-color .2s, color .2s;
}
.sede-comollegar a:hover, .sede-comollegar a:focus-visible { border-color: var(--acento); color: var(--acento); }
/* 19 y no 15: a 15px la carita de Waze se deshacía en manchas —medido contra
   el original— y desde 19 se lee entera. El alfiler de Maps sube con ella
   porque dos íconos de distinto tamaño en la misma fila se leen como descuido,
   no como jerarquía. */
.sede-comollegar svg { width: 19px; height: 19px; flex-shrink: 0; }
/* El logo de Waze, pintado como máscara igual que los íconos del nav: la
   silueta es el archivo oficial y el color lo pone `currentColor`, así que
   acompaña al acento de la sede y a su hover sin duplicar assets. Sin soporte
   de máscaras no se dibuja nada — el nombre del servicio está al lado en texto
   y es lo que de verdad hace falta. */
.sede-icono { display: none; }
@supports ((-webkit-mask-image: none) or (mask-image: none)) {
  .sede-icono {
    display: inline-block; width: 19px; height: 19px; flex-shrink: 0;
    background: currentColor;
    -webkit-mask: var(--icono) center / contain no-repeat;
    mask: var(--icono) center / contain no-repeat;
  }
}
.icono-waze { --icono: url("../assets/iconos/waze.png"); }
/* En táctil los dos suben a 44px de alto, el mismo criterio que los mandos del
   muestrario: se tocan con el dedo. Solo crece el relleno vertical, así que
   siguen entrando los dos en una fila. */
@media (max-width: 720px) {
  .sede-comollegar a { padding-block: .65rem; }
}
/* El botón sigue la misma mecánica de hundirse contra su sombra que el de
   marca.css; solo cambia de familia de color. */
.sede-panel .btn-solid {
  background: var(--acento); border-color: var(--acento);
  box-shadow: 4px 4px 0 var(--acento-sombra);
}
.sede-panel .btn-solid:hover { background: var(--acento-luz); box-shadow: 5px 5px 0 var(--acento-sombra); }
.sede-panel .btn-solid:active { box-shadow: 0 0 0 var(--acento-sombra); }
.sede-meta { display: flex; flex-direction: column; gap: .8rem; margin-top: var(--sp-3); }
.sede-meta div { display: flex; gap: .7rem; align-items: flex-start; font-size: var(--t-chico); }
.sede-meta svg { width: 18px; height: 18px; flex-shrink: 0; margin-top: .2em; color: var(--acento-icono); }
/* El usuario de Instagram es la única fila que lleva a otro lado, así que se
   viste como las demás —mismo color de texto— y solo se delata por el subrayado
   y por tomar el acento al pasar el puntero. En cian brillante competiría con el
   título del panel. */
.sede-meta a { color: var(--hueso); text-decoration-color: var(--hueso-tenue); }
.sede-meta a:hover, .sede-meta a:focus-visible { color: var(--acento); text-decoration-color: currentColor; }
.sede-map {
  border-radius: var(--radio); min-height: 220px; background: var(--negro);
  border: 2px solid var(--negro-3); display: grid; place-items: center;
  color: var(--acento);
}
.sede-map svg { width: 56px; height: 56px; }

/* Con foto real, el recuadro deja de ser un marcador y pasa a ser la ventana a
   la fachada: la imagen llena la caja y el `place-items: center` de arriba deja
   de aplicar porque ya no hay un ícono que centrar. La foto se recorta con
   `cover` en vez de deformarse, y `object-position: center` la mantiene en el
   rótulo cuando el panel es más ancho que alto. Sin `overflow: hidden` las
   esquinas redondeadas del contenedor no recortarían la imagen. */
.sede-map--foto { overflow: hidden; padding: 0; }
.sede-map--foto img { width: 100%; height: 100%; min-height: 220px; object-fit: cover; object-position: center; display: block; }

/* En escritorio la foto deja de mandar sobre la altura de la tarjeta.
   Las dos fachadas son verticales (825×1100) y ese `height: 100%` de arriba no
   resuelve contra un padre de altura automática: la imagen se maqueta a su
   proporción natural y es ELLA la que fija el alto de la fila. Medido a 1440px:
   608px de foto contra los 312 que pide la columna de texto — casi 300px de
   negro vacío debajo del botón y una tarjeta de 692 de alto.

   Sacar la imagen del flujo invierte quién manda. Sin alto propio que aportar,
   la fila la define el texto y la foto se estira a llenarla como la ventana que
   es. `object-fit: cover` —ya declarado— recorta en vez de deformar, así que la
   fachada nunca se aplasta: se ve el 51% central de la vertical, que en las dos
   sedes es justo la banda del rótulo. La tarjeta baja de 692 a 396.

   Va en `min-width` y no dentro de un bloque de móvil porque debajo de 901px el
   panel pasa a una sola columna (ver la consulta de más abajo) y ahí la foto a
   todo lo ancho SÍ tiene que traer su propio alto: fuera del flujo colapsaría
   contra el `min-height: 220px` de `.sede-map` y quedaría una franja. */
@media (min-width: 901px) {
  .sede-map--foto { position: relative; }
  .sede-map--foto img { position: absolute; inset: 0; }
}

/* ---------- Campos (compartidos con agendar.html) ---------- */
/* input/select/textarea base viene de marca.css. */
.field { display: flex; flex-direction: column; gap: .4rem; }
/* **Obligatorio, no defensivo.** La regla de arriba declara `display`, y una
   declaración de clase le gana al `[hidden] { display: none }` del navegador:
   sin esta línea, poner el atributo `hidden` sobre un `.field` no esconde nada.

   Ya costó un defecto en producción. `#coverCampo` del wizard nace con `hidden`
   y `js/booking.js` lo tapa y lo destapa según la respuesta a "¿es un cover?" —
   pero el campo se pintaba siempre, así que a quien contestaba **No** el
   formulario le seguía pidiendo la foto del tatuaje a tapar. El JS estaba bien
   desde el primer día; lo que faltaba era esta línea. La trampa ya estaba
   documentada en booking.css para `.perfo-campo`, y aun así se parchó ahí por
   ID en vez de arreglarse en el origen. Va acá, junto a la clase que la causa. */
.field[hidden] { display: none; }
.field-wide { grid-column: 1 / -1; }
.field label { margin-bottom: 0; }
/* Solo vertical: a lo ancho el campo ya ocupa la fila entera, y dejar arrastrar
   horizontal lo saca de la cuadrícula del formulario. */
.field textarea { resize: vertical; min-height: 7rem; line-height: 1.55; }
/* El desplegable nativo lo pinta el sistema operativo. Como el campo tiene
   fondo negro, el navegador abría la lista en oscuro pero con el texto también
   oscuro, y las opciones quedaban ilegibles. `color-scheme: dark` le avisa que
   dibuje el control en modo oscuro, y las opciones fijan su propio par de
   colores para no depender de eso. */
.field select { color-scheme: dark; }
.field select option { background: var(--negro-2); color: var(--hueso); }

/* ---------- Botones de opción ---------- */
/* Vivían en booking.css y se mudaron acá el 2026-08-08, cuando /cuidados/ los
   necesitó: esa página tiene dos ("Hoy" / "Ayer") pero NO es una página de
   formulario y no tiene por qué cargar las 490 líneas del wizard. Con la regla
   allá, sus botones salían con el estilo nativo del navegador —una caja gris de
   sistema sobre una página negra— y no había nada que lo delatara salvo
   mirarlos, porque un `<button>` sin estilo se ve como un botón.

   La variante de sede (`.choice-btn.is-cian.is-selected`) se queda en booking.css:
   esa sí es de las dos páginas de formulario. Como booking.css se carga después
   de esta hoja, le sigue ganando a `.is-selected` de acá. */
.choice-row { display: flex; gap: .75rem; flex-wrap: wrap; }
.choice-btn {
  padding: .9rem 1.5rem; border-radius: var(--radio); border: 2px solid var(--negro-3);
  background: var(--negro); color: var(--hueso);
  font-family: var(--font-texto); font-weight: 700; font-size: var(--t-chico);
  letter-spacing: .04em; cursor: pointer;
  transition: border-color .2s, background .2s, color .2s, box-shadow .2s;
}
.choice-btn:hover { border-color: var(--cian); color: var(--cian); }
.choice-btn.is-selected {
  background: var(--amarillo); border-color: var(--amarillo); color: var(--negro);
  box-shadow: 4px 4px 0 var(--rojo);
}
.choice-row.wrap .choice-btn { flex: 1 1 120px; text-align: center; }

/* ---------- Aviso de privacidad ----------
   Una barra fija abajo, del ancho de la página. **No es una tarjeta ni un
   modal**: no lleva marco propio, no oscurece el fondo y no atrapa el foco. Se
   separa del contenido con un filete arriba, el mismo recurso con el que abren
   sus bloques `.wizard-confirm-fotos` y `.perfo-higiene-titulo`, y el peso lo
   lleva el texto — la primera frase en amarillo, que es el color de énfasis del
   sistema. Lo arma js/privacidad.js, que explica por qué el texto dice lo que
   dice.

   z-index 90: por debajo del nav y de los tres modales (100, y 110 el visor),
   para que cualquiera de ellos lo tape. No compite con el nav porque viven en
   bordes opuestos de la pantalla. */
.aviso-privacidad {
  position: fixed; z-index: 90; left: 0; right: 0; bottom: 0;
  background: var(--negro-2); border-top: 2px solid var(--negro-3);
  /* Nace abajo y afuera. El estado en reposo es el visible, no el escondido:
     si el JS no llegara a poner la clase, el peor caso es un aviso a la vista,
     no un aviso invisible que igual ocupa el borde de la pantalla. */
  transform: translateY(100%);
  transition: transform .45s cubic-bezier(.2, .7, .2, 1);
}
.aviso-privacidad.is-visible { transform: translateY(0); }
/* Mismo envoltorio que `.nav-inner` y `.footer-inner`: el ancho de página
   centrado. La barra se pinta de borde a borde, el contenido no. */
.aviso-privacidad-inner {
  max-width: var(--max-ancho); margin: 0 auto; padding: var(--sp-2) 1.25rem;
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3); flex-wrap: wrap;
}
.aviso-privacidad-texto {
  flex: 1 1 30rem; margin: 0;
  font-size: var(--t-chico); color: var(--hueso-tenue); line-height: 1.6;
}
.aviso-privacidad-texto strong { color: var(--amarillo); }
/* El botón no crece con la fila: es una acción corta y estirarlo a media
   pantalla lo haría leer como el llamado principal de la página, que no es. */
.aviso-privacidad-btn { flex: 0 0 auto; }

@media (max-width: 560px) {
  /* Apilado, y el botón a todo el ancho: en el teléfono es el único control de
     la barra y no hay nada con qué compartir la fila. */
  .aviso-privacidad-inner { flex-direction: column; align-items: stretch; gap: var(--sp-2); }
  .aviso-privacidad-texto { flex: 1 1 auto; }
  .aviso-privacidad-btn { justify-content: center; }
}

/* ---------- Pie ---------- */
.site-footer { border-top: 2px solid var(--negro-3); }
.footer-inner {
  max-width: var(--max-ancho); margin: 0 auto; padding: var(--sp-5) 1.25rem var(--sp-3);
  display: grid; grid-template-columns: 1.4fr repeat(3, 1fr); gap: var(--sp-3);
}
.footer-brand { display: flex; flex-direction: column; gap: .5rem; align-items: flex-start; }
/* El logo del pie no cuelga del clavo: quieto. El péndulo de `.brand-logo` es
   la señal de vida del rótulo que preside la página, y repetirlo acá lo abarata
   —dos relojes en la misma pared marcando distinta hora—. Además el pie es el
   final del recorrido: lo que se espera ahí es cerrar, no que algo pida
   atención. Los keyframes animan `transform`, así que sin animación el reposo
   es el logo derecho; no queda ninguna inclinación pegada. */
.footer-brand .brand-logo { height: 48px; margin-bottom: .2rem; animation: none; }
.footer-note { font-size: var(--t-chico); color: var(--hueso-tenue); }
.footer-col { display: flex; flex-direction: column; gap: .6rem; }
.footer-col h3 {
  font-size: var(--t-micro); font-weight: 600; letter-spacing: .22em;
  text-transform: uppercase; color: var(--cian); margin-bottom: .2rem;
}
.footer-col a, .footer-col span { font-size: var(--t-chico); color: var(--hueso-tenue); transition: color .2s; }
/* Las dos direcciones del pie. `address` viene en itálica por defecto del
   navegador y acá no corresponde: es un dato, no una cita. El nombre de la sede
   va en hueso lleno para que se lea la jerarquía sede → dirección de un vistazo. */
.footer-sedes {
  font-style: normal; font-size: var(--t-chico); color: var(--hueso-tenue);
  line-height: 1.5; margin-bottom: .6rem;
}
.footer-sedes strong { display: block; color: var(--hueso); font-weight: 700; }
/* El teléfono y el horario valen para las dos sedes, pero pegados a la
   dirección de Heredia se leían como datos solo de ella. El filete es el
   recurso de siempre (.wizard-confirm-fotos, .perfo-higiene-titulo) y acá
   dice: lo de abajo es del estudio entero, no del último renglón de arriba. */
.footer-datos-estudio {
  display: flex; flex-direction: column; gap: .6rem;
  border-top: 2px solid var(--negro-3); padding-top: .8rem; margin-top: .2rem;
}
.footer-col a:hover { color: var(--amarillo); }
.footer-bottom {
  text-align: center; padding: var(--sp-2) 1.25rem var(--sp-3);
  font-size: var(--t-micro); color: var(--hueso-tenue); border-top: 2px solid var(--negro-3);
}

/* ---------- Responsive ---------- */
/* La vitrina en teléfono: centrada.
   En escritorio el rótulo se alinea a la izquierda porque comparte la vitrina
   con el muestrario y las dos columnas necesitan un eje común. Apilado en una
   columna angosta esa razón desaparece: queda un bloque corrido a la izquierda
   con el borde derecho deshilachado —dos botones de anchos distintos, la bajada
   cortada a los 46ch, el saludo partido— y nada que lo justifique.

   Va acá abajo y no en el bloque del hero porque las reglas base están más
   arriba: mismo peso de selector, gana la que viene después.

   El corte es 720px y no 1024 a propósito: entre esos dos anchos el apilado ya
   tiene columna de sobra y la lectura a la izquierda sigue siendo la correcta. */
@media (max-width: 720px) {
  .vitrina-rotulo { text-align: center; }
  /* El saludo se parte en dos renglones limpios en vez de tres torcidos:
     "Welcome" toma la fila entera y las dos sedes bajan juntas. Sin esto el
     ancho del teléfono deja "– Los Yoses –" colgando de la palabra y manda
     "– Heredia –" sola al renglón siguiente. */
  .hero-saludo { justify-content: center; }
  .hero-script { flex-basis: 100%; }
  /* Los dos bloques son `fit-content` / `max-width`, así que centrarlos es
     cosa de márgenes automáticos: `text-align` no mueve una caja, mueve su
     contenido. Y las dos líneas del rótulo se centran una sobre otra —"Maxito"
     es más angosta que "Tattoo"— porque cada una es su propia caja ajustada. */
  .hero-marca, .hero-sub, .hero-title-line { margin-inline: auto; }
  /* Los dos botones pasan a medir lo mismo. Centrados y con anchos propios
     quedaban en 255 y 243: 6px de desnivel por lado, lo justo para leerse como
     descuido y no como decisión. La base de 14rem los deja lado a lado mientras
     haya sitio y los apila cuando no, sin que haya que elegir un corte; el tope
     de 18rem evita que en horizontal se estiren a media pantalla. */
  .hero-cta { justify-content: center; }
  .hero-cta .btn { flex: 1 1 14rem; max-width: 18rem; justify-content: center; }
}

@media (max-width: 900px) {
  .nav-inner { justify-content: space-between; }
  /* 5.9rem = 94px, apenas debajo del nav (88px con el logo grande). Si el logo
     o el botón cambian de alto, este número y el padding del hero van detrás. */
  .nav-links {
    position: fixed; inset: 5.9rem 1rem auto 1rem; flex-direction: column; gap: 1rem;
    background: var(--negro-2); border: 3px solid var(--negro-3); border-radius: var(--radio);
    padding: 1.25rem 1.5rem; transform: translateY(-140%); opacity: 0; pointer-events: none;
    /* `visibility` y no solo opacidad: sin esto los cinco enlaces siguen en el
       orden de tabulación y en el árbol de accesibilidad con el menú cerrado.

       Se conmuta en 0s con retraso, no se interpola. Al cerrar, los .3s de
       retraso dejan que el fundido de salida termine antes de desaparecer; al
       abrir (regla de abajo) el cambio es instantáneo, y eso importa: con una
       transición de verdad el valor calculado sigue siendo `hidden` en el
       instante en que se agrega la clase, y a un elemento invisible el
       navegador no le da el foco. El menú manda el foco a su primer enlace
       apenas abre (js/script.js), así que tiene que poder recibirlo ya. */
    visibility: hidden;
    transition: transform .3s, opacity .3s, visibility 0s .3s;
  }
  .nav-links.is-open {
    transform: translateY(0); opacity: 1; pointer-events: auto; visibility: visible;
    transition: transform .3s, opacity .3s, visibility 0s;
  }
  .nav-burger { display: flex; }
  .nav-actions .btn-ghost { display: none; }
  .sede-panel { grid-template-columns: 1fr; }
  .footer-inner { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 560px) {
  .hero { padding-top: 7.5rem; }
  .hero-datos { gap: var(--sp-2); }
  .footer-inner { grid-template-columns: 1fr; }
  .nav-links { inset: 5.9rem .8rem auto .8rem; }
  /* Los CTAs solo-ícono del nav viven en el bloque de la cuenta del nav, más
     arriba: el corte va en 600 y no acá en 560, porque entre 561 y 574 los dos
     botones con texto no caben juntos. */

  /* "Escribir por WhatsApp" con el `white-space: nowrap` de `.btn` pide 273px
     que no puede ceder, y con el aire del panel y de la sección eso obligaba a
     335 de documento: a 320px la página entera se iba de lado 15px. Soltarlo no
     cambia nada donde ya entra —`normal` permite cortar, no obliga—, solo deja
     que parta en dos líneas cuando no hay ancho. Es el mismo caso del botón de
     envío de perforaciones. */
  .sede-panel .btn { white-space: normal; text-align: center; }
}

/* Ningún bucle sigue corriendo fuera de pantalla: js/script.js marca el hero
   cuando deja el viewport y acá se congelan el brillo y los destellos. */
.hero.is-offscreen .hero-title-line::after,
.hero.is-offscreen .hero-script,
/* La viñeta ya no lleva animación CSS: el personaje se anima solo dentro del
   WebP, y a eso `animation-play-state` no lo toca. De pausarlo fuera de
   pantalla se encarga el navegador, que congela las imágenes no visibles. */
.hero.is-offscreen .hero-destellos .destello { animation-play-state: paused; }

@media (prefers-reduced-motion: reduce) {
  .roster-clock-blink, .artist-modal-tile.is-clickable { animation: none; }
  /* El vaivén del logo y el repique del teléfono se apagan enteros. Ninguno usa
     fill-mode, así que el estado base ya es la posición en reposo. */
  .brand-logo, .nav-actions .btn-icon-only svg { animation: none; }
  .brand { transition: none; }
  .hero-title-line::after, .hero-destellos .destello { animation: none; }
  .btn-solid:hover::after, .btn-solid:focus-visible::after { animation: none; }
  /* La brisa del boleto también: sin fill-mode, el reposo es rotate 0. */
  .ticket-oculto { animation: none; }
  /* Se apaga la vuelta del brillo, pero **el recuadro y la línea se quedan**:
     esos dos son la forma del cartel, no movimiento, y son los que le dieron
     cuerpo. Sin `animation` vale el estado base, que deja el tramo del brillo
     quieto arriba a la derecha — un destello más, no un hueco. */
  .grito-brillo { animation: none; }
  /* `animation: none` y no solo duración corta: marca.css fuerza .01ms, y con
     fill-mode both eso congelaría la máscara en el último fotograma, dejando
     el saludo invisible. Sin animación, vale el estado base: escrito. */
  .hero-script { animation: none; }
  /* El guiño se apaga entero: la cabeza queda quieta y el destello oculto
     (su estado base es opacity 0, así que no queda un asterisco pegado). */
  /* El WebP animado no responde a `prefers-reduced-motion`: en su lugar, el
     <picture> de index.html sirve un cuadro estático a quien pide menos
     movimiento. Esto no se resuelve desde CSS. */
  .roster-bg { transition: none; }
  html { scroll-behavior: auto; }
  .reveal { transition: none; opacity: 1; transform: none; }
}

/* ---------- Preguntas frecuentes ---------- */
/* Arranca bajo el nav fijo. Es el mismo 7.5rem de `.wizard-main` en
   booking.css, y es el mismo número compartido del nav: si el header cambia de
   alto, este también (ver DESIGN.md, Navigation). Va acá y no en booking.css
   porque esta página no es un formulario y no carga esa hoja. */
.pagina-main { padding-top: 7.5rem; }

/* `padding-top` chico y no el `--sp-6` de `.section`: ese ritmo separa secciones
   entre sí, y acá arriba no hay sección anterior sino el nav, que ya puso su
   propio hueco con `.pagina-main`. Sumados dejaban 128px muertos bajo el
   header. Mismo criterio que `.wizard-section`. */
.faq-section { max-width: 780px; padding-top: 1.5rem; }

/* Grupos separados por una línea, no por tarjetas. La página ya vive dentro de
   una sección; meter cada respuesta en su caja sería anidar tarjetas, y encima
   cortaría en pedazos algo que se lee de corrido. */
.faq-grupo + .faq-grupo { margin-top: var(--sp-5); padding-top: var(--sp-4); border-top: 2px solid var(--negro-3); }
.faq-grupo > h2 {
  font-family: var(--font-rotulo); font-weight: 400; color: var(--amarillo);
  font-size: var(--t-h3); margin-bottom: var(--sp-3);
}

.faq-item + .faq-item { margin-top: var(--sp-4); }
/* La pregunta en hueso lleno y no en amarillo: el amarillo ya lo lleva el
   título del grupo, y dos niveles de amarillo seguidos aplanan la jerarquía en
   vez de construirla. Acá el peso alcanza. */
.faq-item h3 {
  font-family: var(--font-texto); font-weight: 700; color: var(--hueso);
  font-size: var(--t-cuerpo); line-height: 1.3; margin-bottom: .6rem;
}
.faq-item p { margin: 0 0 .7rem; color: var(--hueso-tenue); line-height: 1.65; max-width: 68ch; }
.faq-item p:last-child { margin-bottom: 0; }
.faq-item strong { color: var(--hueso); font-weight: 700; }
/* Los subtítulos de los cuidados ("Los primeros días") en cian y sin cursiva:
   la cursiva sobre Archivo a este tamaño se lee sucia, y el cian ya es el color
   con el que el sistema separa. */
.faq-item em { font-style: normal; color: var(--cian); font-weight: 600; }

/* Los enlaces de las respuestas y del cierre los pinta la regla de prosa del
   principio del archivo (`p a:not(.btn)`): los dos contenedores son párrafos.
   Acá había un parche por selector y se fue cuando la regla se volvió
   automática. El subrayado importa especialmente en esta página, porque el `em`
   de arriba ya es cian y sin él un enlace y un subtítulo se verían iguales. */

.faq-cierre {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2);
  margin-top: var(--sp-5); padding-top: var(--sp-4);
  border-top: 2px solid var(--negro-3); color: var(--hueso-tenue);
}

/* ---------- Blancos táctiles ---------- */
/* Va al final del archivo a propósito: son ajustes que tienen que ganarle a la
   regla base de cada control, y con la misma especificidad manda el orden.
   (Es la trampa que ya nos costó el +5% del muestrario y los destellos.)

   La condición es `pointer: coarse` y no un ancho: lo que decide el tamaño de
   un blanco no es cuánto mide la pantalla sino con qué se toca. Un portátil con
   pantalla táctil necesita esto a 1400px; un mouse a 375px no lo necesita y no
   tiene por qué pagar la densidad. */
@media (pointer: coarse) {
  /* La hamburguesa era 37x30 siendo el único acceso al menú en el teléfono.
     Medida fija en vez de padding: las tres barras miden 24px y se centran
     solas dentro de la caja. */
  .nav-burger { width: 44px; height: 44px; padding: 0; align-items: center; justify-content: center; }

  /* `.filters-mas` es el "ver todos los estilos" del móvil: no lleva la clase
     de chip pero vive en la misma fila y se toca igual. */
  .filter-chip, .sede-tab, .filters-mas { min-height: 44px; }

  /* El Instagram de la sede es texto suelto en una lista donde ningún otro
     renglón es enlace. Crece por fuera como el del roster: si le diera altura
     real, ese renglón quedaría más alto que la dirección y el horario. Ancho
     completo (ya pasa de 44) y 44 de alto centrados sobre el texto. */
  .sede-meta a { position: relative; }
  .sede-meta a::after {
    content: ""; position: absolute; left: 0; right: 0;
    top: 50%; transform: translateY(-50%); height: 44px;
  }

  /* Los botones de los tres modales: el cierre y las flechas. Iban de 35 a 43
     —las del visor de estilos fallaban por un solo píxel— y son justo los
     controles que hay que acertar con el modal encima de todo.

     `min-*` y no `width`: hay una regla en ≤560px que achica las flechas del
     visor de fotos a 38, y un mínimo le gana a un ancho sin depender del orden
     de los archivos ni de la especificidad. */
  .artist-modal-close, .estilo-modal-cerrar, .estilo-modal-flecha,
  .gallery-modal-close, .gallery-modal-nav { min-width: 44px; min-height: 44px; }

  /* El pie tenía enlaces de 25px separados por 10: el error de un dedo no es
     tocar fuera de la lista, es tocar el renglón de al lado. Cada uno pasa a
     44 y el hueco entre ellos se achica, porque el aire ahora lo pone la altura
     de cada enlace y no el gap. */
  .footer-col { gap: .1rem; }
  /* El span de "Sedes" no es enlace y no necesita blanco táctil, pero sí entra
     en la misma altura de renglón: sin esto se quedaba sin el aire que ahora
     pone la altura en vez del gap, y esa columna aparecía pegada a su título. */
  .footer-col a, .footer-col span { min-height: 44px; display: flex; align-items: center; }

  /* El Instagram crece por fuera, no por dentro: el círculo conserva su tamaño
     —agrandarlo desbalancea la fila— y lo que llega a 44 es el área que recibe
     el toque. Lo que gana de cada lado se lo quita a la fila, que abre el
     modal; es poco, y es mejor que fallar el enlace.

     El área se declara medida y centrada, no con un `inset` negativo. Dos
     razones, las dos aprendidas midiendo: `inset` se cuenta desde la caja de
     PADDING del ancestro posicionado y no desde su caja de borde, así que el
     número nunca es el que uno cree; y este mismo componente mide 34 en el
     roster pero 28 dentro del modal de artista, con lo cual ningún inset fijo
     sirve para los dos. Un 44 declarado sí. */
  .roster-ig { position: relative; }
  .roster-ig::after {
    content: ""; position: absolute; top: 50%; left: 50%;
    transform: translate(-50%, -50%); width: 44px; height: 44px; border-radius: 50%;
  }

  /* El título de cada etapa de /cuidados/ es el control que la pliega. Medido,
     la fila da 43.x con el título en una sola línea: pasa raspando y por
     debajo. Va acá y no en cuidados.css porque los blancos táctiles viven
     todos en este bloque a propósito —repartirlos es cómo se pierde la cuenta
     de cuáles ya se revisaron—, y no lleva `align-items: center` para no
     pisar el `flex-start` que mantiene el chevron alineado con el primer
     renglón cuando el título se parte en dos. */
  .etapa-titulo { min-height: 44px; }
}

/* El menú desplegable solo existe abajo de 900px, así que la regla se acota ahí
   en vez de estirar los enlaces del nav horizontal de escritorio. */
@media (pointer: coarse) and (max-width: 900px) {
  .nav-links a { min-height: 48px; display: flex; align-items: center; }
}
