/* Púas Tatuajes — identidad aprobada por Gabriel (29-07-2026)
   Papel/pergamino crema + tinta negra + rojo terracota.
   OJO: los ornamentos polinésicos van como DETALLE sutil, no como identidad
   dominante: el estudio hace todos los estilos (realismo, color, fineline,
   piercing), así que nada de marcos tribales pesados. */

:root {
  /* Refuerzo CSS del <meta name="color-scheme"> de base.html: el sitio es
     SIEMPRE claro, nunca se invierte con el modo oscuro de Android/Chrome
     (ver la nota completa en base.html — bug reportado por Gabriel el
     09-08-2026 con capturas de su celular). */
  color-scheme: light;
  /* EL PAPEL SE AMARILLEO el 05-08. Antes era #EBDFC4, un crema palido, y al
     lado de la franja recortada del mockup se veia lavado y de otra familia.
     Los tres tonos salen de MUESTREAR el propio mockup en cuatro zonas de papel
     limpio (bajo la franja, los dos margenes y el hueco entre bloques): el
     promedio dio #E7CDA6.
     Se comprobo que el texto sigue pasando AA sobre el tono nuevo, con la
     formula de WCAG y no a ojo: tinta 11,79:1, tinta-suave 6,66:1 y
     terracota-texto 6,51:1. El claro y el oscuro se derivaron del mismo tono
     manteniendo la distancia que tenian. */
  --papel: #E7CDA6;
  --papel-claro: #F2E3C6;
  --papel-oscuro: #D9BE94;
  --tinta: #1A1512;
  --tinta-suave: #4A3F36;
  --terracota: #9B2C3B;
  --terracota-oscuro: #7A2231;
  /* Contraste (WCAG AA pide 4.5:1 para texto normal):
       El acento pasó del terracota anaranjado al VINO el 3-08-2026, a pedido de
       Gabriel: "que sea algo más tirado al vino / burdeo".
       De regalo mejoró el contraste, medido con la fórmula de WCAG:
         antes  #B23A2E sobre el papel #EBDFC4 = 4.49:1 → NO pasaba AA como texto.
         ahora  #9B2C3B sobre el papel        = 5.64:1 → sí pasa.
                #9B2C3B con blanco encima     = 7.45:1 (antes 5.94).
                #7A2231 sobre el papel        = 7.56:1 (antes 6.27).
       La regla se mantiene igual aunque el fondo ya pase AA: el terracota claro
       es SOLO fondo y todo lo que sea texto usa --terracota-texto. Cambiarla
       ahora obligaría a revisar cada uso, y el smoke test la vigila.
     Por eso el terracota claro se usa SOLO como fondo de botón (blanco encima
     da 5.9:1) y todo el texto en terracota usa --terracota-texto. */
  --terracota-texto: #7A2231;
  --borde: rgba(26, 21, 18, 0.18);
  --borde-fuerte: rgba(26, 21, 18, 0.38);
  --sombra: 0 2px 14px rgba(26, 21, 18, 0.12);
  /* Sombra de "foto montada sobre papel": una línea de luz arriba (el papel
     levantado) y una sombra difusa abajo. */
  --sombra-montada:
    inset 0 1px 0 rgba(255, 255, 255, 0.55),
    0 1px 2px rgba(26, 21, 18, 0.10),
    0 10px 26px -12px rgba(26, 21, 18, 0.30);
  /* ESCALA de elevación. Antes había UNA sola sombra para todo, así que una
     tarjeta chica y el hero flotaban igual y el sitio se leía plano: sin
     diferencia de altura no hay jerarquía, solo cosas puestas encima del papel.
     Regla: mientras más grande la superficie, más gruesa se lee — sombra más
     abierta y más desplazada. La línea de luz de arriba se mantiene en todas
     porque es lo que hace que el papel parezca levantado y no pegado. */
  --elev-1:                                     /* pastillas, chips, etiquetas */
    inset 0 1px 0 rgba(255, 255, 255, 0.5),
    0 1px 2px rgba(26, 21, 18, 0.10),
    0 2px 6px -2px rgba(26, 21, 18, 0.16);
  --elev-2:                                     /* tarjetas de la galería */
    inset 0 1px 0 rgba(255, 255, 255, 0.55),
    0 1px 2px rgba(26, 21, 18, 0.10),
    0 8px 20px -10px rgba(26, 21, 18, 0.30);
  --elev-3:                                     /* hero, mapa, piezas grandes */
    inset 0 1px 0 rgba(255, 255, 255, 0.6),
    0 2px 4px rgba(26, 21, 18, 0.10),
    0 18px 44px -18px rgba(26, 21, 18, 0.42),
    0 40px 80px -50px rgba(26, 21, 18, 0.35);
  /* Al levantar algo con el puntero se sube UN escalón, nunca dos: el salto
     grande se siente barato. */
  --elev-2-hover:
    inset 0 1px 0 rgba(255, 255, 255, 0.6),
    0 2px 4px rgba(26, 21, 18, 0.10),
    0 14px 30px -12px rgba(26, 21, 18, 0.38);
  --radio: 4px;
  --serif: 'Cormorant Garamond', Georgia, serif;
  /* Sacramento era demasiado fina: a tamaño grande se leía como invitación de
     matrimonio, no como el lettering pintado a mano del mockup. Kaushan Script
     es de pincel, tiene cuerpo y remata los trazos. (Great Vibes quedó aún más
     formal; Yellowtail más de cartel retro y con uniones muy delgadas.) */
  --script: 'Kaushan Script', 'Segoe Script', cursive;
  --sans: 'Inter', system-ui, sans-serif;

  /* --------------------------------------------------------------- ornamentos
     Todo lo decorativo es SVG en data-uri: sin archivos que subir, sin pedidos
     al servidor y escala sin pixelarse. Trazo fino, nunca tribal: el estudio
     hace todos los estilos y lo polinésico va sutil (regla 2). */

  /* Grano del papel. feTurbulence a baja opacidad: se siente la fibra sin que
     aparezca un "filtro" encima del diseño. */
  --ruido: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23g)' opacity='0.055'/%3E%3C/svg%3E");

  /* Greca de la barra bajo el header: onda de trazo delgado con un punto entre
     cada arco. Reemplaza el patrón de rayas verticales, que parecía un código
     de barras. */
  --greca: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='48' height='12' viewBox='0 0 48 12'%3E%3Cg fill='none' stroke='%231A1512' stroke-width='0.9' stroke-linecap='round'%3E%3Cpath d='M0 7.5c3-5.4 9-5.4 12 0s9 5.4 12 0 9-5.4 12 0 9 5.4 12 0'/%3E%3C/g%3E%3Cg fill='%231A1512'%3E%3Ccircle cx='12' cy='3.1' r='0.85'/%3E%3Ccircle cx='36' cy='3.1' r='0.85'/%3E%3C/g%3E%3C/svg%3E");

  /* Esquina del marco de página: un rulo fino con su punto, como en la orla de
     un documento antiguo. Se espeja con transform en las otras tres esquinas. */
  --ornamento-esquina: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3E%3Cg fill='none' stroke='%231A1512' stroke-width='1' stroke-linecap='round'%3E%3Cpath d='M0 12c7 0 12-5 12-12'/%3E%3Cpath d='M0 18c10.5 0 18-7.5 18-18' opacity='0.45'/%3E%3Cpath d='M4.5 10.5c2.6-.6 4.4-2.4 5-5'/%3E%3C/g%3E%3Ccircle cx='3' cy='3' r='1.5' fill='%231A1512'/%3E%3C/svg%3E");

  /* Filigrana chica: va sobre los títulos y bajo los kickers. */
  --filigrana: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='16' viewBox='0 0 120 16'%3E%3Cg fill='none' stroke='%237A2231' stroke-width='1' stroke-linecap='round'%3E%3Cpath d='M6 8h34'/%3E%3Cpath d='M80 8h34'/%3E%3Cpath d='M46 8c4.5 0 6-4.5 9-4.5S60 8 60 8s2-4.5 5-4.5S74 8 74 8'/%3E%3Cpath d='M46 8c4.5 0 6 4.5 9 4.5S60 8 60 8s2 4.5 5 4.5S74 8 74 8'/%3E%3C/g%3E%3Ccircle cx='60' cy='8' r='1.6' fill='%237A2231'/%3E%3C/svg%3E");

  /* Ornamento tenue para el fondo de la banda roja (trazo blanco). */
  --filigrana-clara: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='80' viewBox='0 0 180 80'%3E%3Cg fill='none' stroke='%23FFFFFF' stroke-width='1' stroke-linecap='round' opacity='0.5'%3E%3Cpath d='M0 40c22-26 44 26 66 0s44-26 66 0 26 12 48 0'/%3E%3Cpath d='M12 62c18-14 32 6 48-4'/%3E%3Cpath d='M120 18c18 14 32-6 48 4'/%3E%3C/g%3E%3C/svg%3E");
/* ------------------------------------------------- la banda bajo el header
   ESTA ES LA FRANJA DEL MOCKUP, RECORTADA DEL MOCKUP. No es un dibujo mío que
   se le parece: son los píxeles del prototipo que aprobó Gabriel.

   Se intentó tres veces redibujarla en SVG (moldura dorada, enredadera de línea
   fina, cadena de lazos) y las tres se veían como otra pieza al ponerlas al lado
   de la suya. La filigrana está grabada a mano y es irregular; una versión
   vectorial simétrica nunca iba a dar.

   Cómo se sacó, medido y no a ojo:
   · La franja va de la fila 96 a la 108 del mockup — se encontró barriendo la
     media y la desviación de cada fila, porque ahí la imagen se oscurece de 195
     a ~90 sobre 255.
   · El período del patrón son 8 px, hallado por autocorrelación (se comparó cada
     columna contra la de p píxeles más allá y se buscó el menor error). El tile
     usa 24, o sea TRES períodos: repite menos seguido y el ruido del JPEG se
     nota menos.
   · El punto de corte se eligió probando 240 posiciones y quedándose con la que
     deja la costura más invisible.
   · Va guardado a 2x (48x30 para 24x15 en pantalla) para que no se vea blando en
     pantallas densas.

   Va como data-uri y no como archivo suelto por lo mismo que el resto de lo
   decorativo: no suma una petición y no hay que acordarse de que viaje al
   deploy. Pesa poco más de 1 KB.
   El PNG también queda en core/static/img/franja-ornamental.png por si hay que
   volver a generarlo o retocarlo. */
  --greca-banda: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAeCAIAAADlxgqWAAABCGlDQ1BJQ0MgUHJvZmlsZQAAeJxjYGA8wQAELAYMDLl5JUVB7k4KEZFRCuwPGBiBEAwSk4sLGHADoKpv1yBqL+viUYcLcKakFicD6Q9ArFIEtBxopAiQLZIOYWuA2EkQtg2IXV5SUAJkB4DYRSFBzkB2CpCtkY7ETkJiJxcUgdT3ANk2uTmlyQh3M/Ck5oUGA2kOIJZhKGYIYnBncAL5H6IkfxEDg8VXBgbmCQixpJkMDNtbGRgkbiHEVBYwMPC3MDBsO48QQ4RJQWJRIliIBYiZ0tIYGD4tZ2DgjWRgEL7AwMAVDQsIHG5TALvNnSEfCNMZchhSgSKeDHkMyQx6QJYRgwGDIYMZAKbWPz9HbOBQAAALgUlEQVR42k2X2a4cN5KGI4JLMrP25ayWtVvqgeWZNvwA8wzzAvOO8xY9QKMH3W77yLJkbZZOnb2qMqsqk2REzEXJQPOC4AUJ/hGMIP4PNy//BxHJECEhooIqAxEa59AYQAQVZWYREQFQUFUF3S9AFBQRAUBZQAEAVJmZRcUgknXGWiQD/3JIVcmQsw4JOecuppSyigACItq23aqqirCwiBIiohGRlDNzBkRDxlhjjSVDCCAqnLOIAAIZBABVRQBEBAURIQRrLRElFe5aFlVVRNzrJiJEYs5d14kIETnnnfOEyMIibNerm5y5a9vdbptyttY557s23t7c1k2NSGVVDvqDwWAQQiBClty2bUqJiIrCIWLOGRG896qaUvLODYfDIoQU02bbbJpmv9k6i0jeF865pq4vLi62u12/3z88OJzN5t65LnWxi1YlSU4p7nJqQQGVJHe7bbNa3tR14713hrQsUYVACQBQDQGjEgiBICAqA8B+JlRCRVRCNYQEqpI4tYKI6oy1pNaAkZzabbOpawOaBn1JnRKgZNRsrbHgocJq0O+HUBLZLnaEFgEPD7Xf7w+Hw7IM3hfGGCJABGbOOasqEQCAiIgK/sswhgDAOdvvD5yzKXYsQkTeu8IHJAOIANC2W+eLsqpSjgqKhNY5e311Laqqaq2LkQEwpdR1yRhXFC6EEpHaNrZtB0iG9pcpszAzgCAigLIIM4uwqjKziiKhcxaRREWEEQAQui421KqiMCuSK0oArJvt7d2KiEIIzjn7t//7kRDJGARgkX3dARgAJTJERpVTTKJgrbHWGkMqysKgSoasQVFg5pxS27UxRgAsCu+cQwJhZlUyxjtHhMycswAAIhERGQKFGGPbtYZMVVXOOfvXv/7NOldVVa+qjLU5cdu2OTMRGWNEgDmmlFXBOYuIIszMSGjIWGuIgEVzSiICAN676WRWlj0Ac3t3e3V1ta7rzGyttdaI6P7/UFUEdN577wE0p2yMKUKwztp3Hz+VZZhNZ8PBaDab73bdcvXh6upKFax1iF+qBACNIeYUY1QV731RFM5ZEUkpt20LoIPBcDKbPXz0+N7X91JK3au8/fDp+uqu3taZxXvnrCM0iXOKUTJb76pe5axTVSK0zpMhW5S94Xh0eu/rp8//NJ/Pt9vO+iKJfP68iPXGex9CUFBh1iSqbMhUVX88Ho3H46osVWG73SwuLm6ub+rNdtN2WUGA2piX6+Z2ud51nbGu7IXBcNgvK2NsFhZmEG1jbDabZrsDVUMEJiGRff5v387msyePHz188ICMGebcGw1s4TdtXJwvMqgQcpbEGVGrqprP5/PZbDqbHBwczKZT69xqtfr11a+Rf765uX3/8TMrffi82G42v719e3Nz2+tVxydHR8cns+msCiUAKkIZQhnK29u7n89+fvf+XbvdASARIhj75++/995XvepmuWzbtiiKXq/39cOHy7qxztV1HVNMKRfeTyaj45OTk5OTEIJIijll1cLaoixP7n2F1i0Wi6vLq98/f/7w8XPbdV23G48nT54+fnD//mg0QjQqkhOTodFoPB6PR+OpAiLRx/cfu9iVZRmq0j54+ODu7u7du7cfPnzIKY/H46Ojo/nB/NmzZ1VVvXx59u7d+xjTaDR8+Ojh82fPhsPh5dXlr7++uVsuJ+PZcDggMoeHhz/88H3XxZ9/OvvHjz+eny9yyrP55LsX33334sVg0L+6uvz48cNqWbdtZ4wZjYfz+fz46PjRo4fGmO1md3NzPZmMJ5OJPZxPd5v67ub69atfui5WVfn7ZPL8+fPHTx6fHh9eXy7OP/2euq4K/vT48OH9e2TMxcXnxfnnt29/61WD6XQ6mU5nk/HhfFpVfVRd3t1u6lpEnjx6+B///uLp46d1vf5psXj18mVdNzEmZinLcHR0WDj3+NGDXhmuLs6Dt/funR4eHFoQdgZ7ZTHsVxvUbrdZ7Jrg7bBfDYeD+XR0fDi/ptvgrbdkDSgwATsDzqIh9Y56wYOkm6vLNIy90p8eHd5cXYnwydHhbDxyBjf1+vpysVreEpIzmLuu2+Zu15ccLeGwV50czIKl+/fvHxwc2Ne//rLdbMrCP//mKQs3db1ar3tlgSCFd0cHs019iiAGtVmvbq4vvS8swsFsGrw7ODiYTmfGmNS1v5ydFSGUoUTgfq+MXdftdsvb6+AdKk+n49PjYxXOLHk46PV7X51+NR4Obq4v18vV6u5Wckrdrt1u7P/+5S/OuX6/d3p6Oh6PRKRpGmvtZDKtqlB42zTNdrvp2vbu7vb8PEwmU+/9va/u9fu9J0+eFEX4+PHDq1evz88XItrv9xGx3e2apoltByCAMJvOvv3228locn19vdvtihBOT0+Pj48B4PXr129ev75cLLx3TV0PRyN7dvayLMuDgwMiU5bleDyeTufee2tNTskY1+8Pjo+PN5utcybFLKyj0WgymUyns6Ojo/V6vVrV5+eL8/MLZglFUYQgDO0u1qs6SUaiR48eTcbj49PT3mCYUg6h6PV6meX8fPHTT2cf3r9v220Zys22LcK1eTyjro3Nprm7vVveLWPXFUUIRWCRet2s1+sYUwhhMBj2elUIoQhhOBhOppMilHe3q7Ozs7///R+fPn3mrN55AFBBAINAANDFVK+bu+Vy2+6M88PxeDKZGmsXF5c//vOnH/95tri4ElFfFK4oBDDmjP/1w4gzZ04pRufd0dHRN0+/OTo6QsL1ar1crXJKoSqKokAARHDOjUaj4WgorBcXF2/e/Pb+/fu2i/3eoCzLnFNOAkCgKCgxxZyjcWY8GX117+vTk9N+1W82zW9v37158+budul90R/0vLeIqCLMgv/9nycIqCrb3a5td94XB/P5YDBQ1bquV6tVjJ11zntniACBiMpQVr0KkXa7bdM0u11EpFAUxticchczZ1YANAQICizKYCiEUJWlQdvFtN1tY9eJKBljjCFEUEVQBbV/evaUDBkyMcXtdiciRVE4a0UkBN/vlTF2ouKsdc4h4t4I+8J758ajvqETIotICgCizJISp5xVFC05Z40lAelSyikrc0rZWTMZDwf9figKVkkpC2cQJQJEtN//+QUSGTJIiIBfeAAhpZw5g4KoCLOxxnuPADEmAC2KoigKay0SCStnziKSRVRV/kATRGPIGEKDAoAAqNB13WbXIUBVlt570b2zExVBUEC1s+kYEBHRWWud886RMTHGpqm7DvauiBDIWGvM3hwigvdFWZZFUSBiijnFmEVz4pyTiBIRIRljjLPOWuNoHzMhppSa7S6nbIics0h7GEH5w3DattvtgQkAQIEIWWS9Xl9eXtZ1rareeec9kQEVQNhbLed8WZaDft85LwqgqoAxxt1uG7uEQN77sixDGbx3QKjCIoKInLmLiTkDgHPuS5pxbyaTiFj4An+iACqaWLu2XS6Xt7e3TdMgkfeFtRYUWJgIyxC8L5xPe7/rfIF7R4qUUkoptbFTBlY1ztmcVUVUmHPOvBcOAMwsqnuJIgoAOSfmLCJ2fniwJ0rrnCEnwnXd+BBCVbFIWZbO+r18VTXGhFAURfDeh1D4feYAFGDfqilxiilncc5XvbLwjjkzZxX9Ul9I1pi9GiLyziEa5pQ5izAA2NlsJgAAaqw15FS16g+G4/FJF/ckgEix61JORGQMWWuttc65PZ4CoMo+SEBEVeAszGKMcd4RQk5RhBERAEEBAIlI/0gPGQMAnDNL3reDLYpSAFSFFVgUEIqyDGUpiqiICCzsvBdRY/bFioQACISEZBFAUAwgAimoioJTsmhoj4mKZOgLZBAogqKo7L9zBNw/NzokIRZWkX2UwAqSmDkTkffeO49khTXnxKrGWGNwD4qKoMoqwiqEioAisI9fBERUQRFQAYQFdA8YXwYRCauIfOlzRAUgRAQEIABWgP8H4TBWY+pAhk8AAAAASUVORK5CYII=");
}

* { box-sizing: border-box; }

/* ---------------------------------------------------------------- accesibilidad
   Foco visible en TODO lo que se puede enfocar, no solo en los campos: sin esto
   el sitio no se puede recorrer con el teclado. `:focus-visible` deja el anillo
   para quien navega con teclado y no lo dibuja al hacer clic con el mouse. */
:focus-visible {
  outline: 3px solid var(--terracota-oscuro);
  outline-offset: 2px;
  border-radius: 2px;
}
.solo-lectores {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
/* Salto al contenido: aparece recién al enfocarlo con Tab. */
.saltar {
  position: absolute; left: 50%; top: 0; transform: translate(-50%, -120%);
  z-index: 200; background: var(--tinta); color: var(--papel);
  font-family: var(--sans); font-size: .8rem; padding: .7rem 1.2rem;
  border-radius: 0 0 var(--radio) var(--radio);
}
.saltar:focus { transform: translate(-50%, 0); color: var(--papel); }

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

/* ---------------------------------------------------------------- el papel
   Cinco capas, de arriba hacia abajo:
     1. viñeteado (fixed: no se desplaza con el scroll, así el papel se ve
        "iluminado al centro" en cualquier parte de la página),
     2. manchas de humedad tenues,
     3. dos brillos claros que hacen la fibra irregular,
     4. grano feTurbulence,
     5. el color base.
   Todo con alfas bajas: tiene que sentirse papel, no un filtro encima. */
body {
  margin: 0;
  min-height: 100vh;
  background-color: var(--papel);
  /* OJO: acá NO va ninguna capa `fixed`. El viñeteado vive en `.marco-pagina`,
     que ya es un overlay fijo. Motivo medido (06-08-2026): un fondo con
     `background-attachment: fixed` no se puede componer —cambia con el scroll y
     es parte del fondo de un elemento que se desplaza—, así que el navegador lo
     REPINTA EN CADA MARCO. En la galería, con el CPU frenado 4x para simular un
     celular de gama media, eso costaba 8,3 ms por marco contra 5,6 ms sin él:
     un tercio del presupuesto de cada cuadro gastado en redibujar una sombra
     que no se mueve. Las capas de ornamento se midieron aparte y no costaban
     nada (8,1 contra 8,3 ms), así que esas quedaron donde estaban. */
  background-image:
    radial-gradient(ellipse 22% 16% at 12% 22%, rgba(146, 112, 62, 0.10) 0, transparent 100%),
    radial-gradient(ellipse 26% 12% at 88% 61%, rgba(146, 112, 62, 0.09) 0, transparent 100%),
    radial-gradient(ellipse 18% 14% at 64% 88%, rgba(120, 92, 50, 0.07) 0, transparent 100%),
    radial-gradient(circle at 22% 28%, rgba(255, 255, 255, 0.40) 0, transparent 42%),
    radial-gradient(circle at 78% 72%, rgba(255, 252, 244, 0.30) 0, transparent 38%),
    var(--ruido);
  background-repeat: no-repeat, no-repeat, no-repeat, no-repeat, no-repeat, repeat;
  color: var(--tinta);
  font-family: var(--serif);
  font-size: 18px;
  line-height: 1.6;
}

/* ------------------------------------------------------- marco de la página
   Doble filete con las cuatro esquinas ornamentadas, como la orla de un
   documento antiguo. Va en un overlay `fixed` (no dentro del flujo) por dos
   razones: así el marco encuadra la ventana completa sin cortarse en páginas
   largas, y no puede empujar el contenido ni provocar scroll horizontal.
   `pointer-events: none` para que no se coma ningún clic.
   z-index 45: sobre el header (30), debajo del botón de WhatsApp (50) y del
   lightbox (100). */
.marco-pagina {
  position: fixed;
  inset: 0;
  z-index: 45;
  pointer-events: none;
  /* El viñeteado se mudó acá desde el `body` (ver el comentario en `body`).
     Este elemento YA era fijo, así que el navegador lo tiene en su propia capa
     y lo desplaza en vez de repintarlo: el mismo dibujo, sin costo por marco.
     Va sobre el contenido, que es como funciona un viñeteado de verdad, y es
     lo bastante suave (0,26 en las esquinas, 0 en el centro) para no ensuciar
     las fotos. `pointer-events: none` ya estaba, así que no roba ningún clic. */
  background: radial-gradient(125% 105% at 50% 38%,
    transparent 44%, rgba(90, 62, 28, 0.26) 100%);
}
.marco-pagina::before,
.marco-pagina::after {
  content: '';
  position: absolute;
  border: 1px solid var(--borde);
}
/* El filete exterior VUELVE a ser una línea fina.
   Llegó a ser una orla de greca en los cuatro lados (30-07) porque el sitio se
   sentía cuadrado, pero desde que la cabecera lleva su ornamento arriba y abajo
   del navbar, la orla le pasaba por encima a la franja de arriba: dos adornos
   distintos, uno sobre otro, en la misma pulgada de pantalla. Se ve en la
   captura, no es una opinión.
   El ornamento ahora vive donde se mira —la cabecera— y el marco vuelve a lo
   que sabe hacer: encuadrar callado. Las esquinas ornamentadas se quedan, así
   que el marco no pierde carácter. */
.marco-pagina::before {
  inset: 9px;
  border: 1px solid var(--borde-fuerte);
  opacity: .55;
}
.marco-pagina::after { inset: 26px; border-color: rgba(26, 21, 18, 0.13); }
/* Dos spans para tener cuatro pseudo-elementos: una esquina en cada uno. */
.marco-esquinas-arriba::before, .marco-esquinas-arriba::after,
.marco-esquinas-abajo::before, .marco-esquinas-abajo::after {
  content: '';
  position: absolute;
  width: 30px; height: 30px;
  background: var(--ornamento-esquina) no-repeat center / contain;
  opacity: .5;
}
.marco-esquinas-arriba::before { top: 11px; left: 11px; }
.marco-esquinas-arriba::after { top: 11px; right: 11px; transform: scaleX(-1); }
.marco-esquinas-abajo::before { bottom: 11px; left: 11px; transform: scaleY(-1); }
.marco-esquinas-abajo::after { bottom: 11px; right: 11px; transform: scale(-1); }

a { color: var(--terracota-texto); text-decoration: none; }
a:hover { color: var(--terracota-oscuro); }
img { max-width: 100%; display: block; }

.contenedor { width: min(1180px, 92vw); margin: 0 auto; }

/* ---------------------------------------------------------------- tipografía */
/* El tracking es específico del tamaño: NO puede haber un solo valor para todos
   los títulos. Las letras se leen más separadas a medida que crecen, así que el
   texto grande pide tracking NEGATIVO y el chico un pelo positivo. Antes h1, h2
   y h3 compartían .01em, o sea que estaba mal en al menos dos de los tres.
   El interlineado va al revés que el tamaño: apretado arriba, suelto abajo. */
h1, h2, h3 { font-family: var(--serif); font-weight: 600; margin: 0 0 .4em; font-optical-sizing: auto; }
h1 { letter-spacing: -0.02em; line-height: 1.06; }
h2 { letter-spacing: -0.012em; line-height: 1.14; }
h3 { letter-spacing: 0;        line-height: 1.24; }
/* Kaushan Script tiene mucha más altura de x que Sacramento, así que los
   tamaños bajan: con los clamp anteriores el título del hero se comía la
   pantalla. El interlineado sube a 1.1 porque los trazos de pincel suben y
   bajan de la línea base. */
.script {
  font-family: var(--script); font-weight: 400; line-height: 1.1;
  letter-spacing: .005em;
}
/* El tope de escritorio sube de 4.3 a 5.1rem. El piso y el factor vw NO se
   tocan hacia abajo (el mínimo de 2.6rem es el que manda bajo ~1075px), así que
   en el teléfono se ve exactamente igual que antes: esto solo agranda el título
   en pantallas anchas, que es donde el hero se veía chico y sin peso.
   Un script de pincel NO admite tracking negativo de verdad —las letras se
   tocan— así que a tamaño de titular apenas se neutraliza el positivo. */
h1.script { font-size: clamp(2.6rem, 5.6vw, 5.1rem); letter-spacing: -0.004em; line-height: 1.05; }
h2.script { font-size: clamp(2rem, 4.6vw, 3rem); }

/* Filigrana: el ornamento chico que va sobre los títulos. Decorativo puro, por
   eso siempre con aria-hidden en la plantilla. */
.filigrana {
  display: block;
  width: 120px; height: 16px; margin: 0 auto .7rem;
  background: var(--filigrana) no-repeat center / contain;
  opacity: .75;
}
.filigrana-izq { margin-left: 0; margin-right: auto; }
.kicker {
  font-family: var(--sans); font-size: .72rem; letter-spacing: .22em;
  text-transform: uppercase; color: var(--terracota-texto); font-weight: 600;
}
.subtitulo { font-size: 1.05rem; color: var(--tinta-suave); }
.centrado { text-align: center; }

/* ---------------------------------------------------------------- barras
   Greca fina bajo el header. Antes era un patrón de rayas verticales que se
   leía como código de barras; ahora es una onda de trazo delgado entre dos
   hairlines. Si la greca no cargara, quedan las dos líneas: el respaldo es
   una línea doble simple, que es preferible a algo barato. */
.barra-ornamento {
  /* Antes: 15px de alto y opacity .5, o sea que no se veia. Gabriel lo dijo
     derecho mirando su propia lamina: "se ve muy plano". La greca es parte de
     su identidad, no un adorno: tiene que leerse.
     15 px: es el alto real de la franja en el mockup (filas 95 a 110), medido,
     no elegido. */
  height: 15px;
  /* Nada de transparencia acá: el dorado se apaga y queda mostaza. Lo que antes
     atenuaba la onda para que no gritara no aplica — esta pieza SÍ tiene que
     verse, es la que le da el corte a la página bajo el header. (El smoke test falla si alguien la vuelve
     a atenuar, por eso la palabra no aparece ni en este comentario.)
     El color de fondo NO es decorativo: es el respaldo. Si el navegador no
     dibuja la data-uri, con `background` a secas quedaba una franja en blanco
     en medio de la página. Así, en el peor caso queda una moldura oscura con
     sus dos filetes de oro, que es pobre pero se sostiene. */
  background: var(--greca-banda) repeat-x center / 24px 15px, #4A330E;
  /* Los filetes se mantienen como RESPALDO: el recorte ya trae los suyos, así
     que en el caso normal se superponen y no se notan. Si el navegador no
     dibujara la imagen, sin esto quedaría una franja café lisa. */
  border-top: 1px solid rgba(204, 180, 132, .5);
  border-bottom: 1px solid rgba(204, 180, 132, .4);
}

/* ---------------------------------------------------------------- header */
/* Cualquier salto a un ancla tiene que dejar el destino DEBAJO de la cabecera
   pegada, no tapado por ella. Desde que la cabecera es un bloque de tres piezas
   mide 155px en el teléfono y 193px en escritorio: sin esto, al ir a
   /equipo/#resenas o al enlace "Ver más reseñas" el título quedaba escondido y
   parecía que el enlace no había hecho nada.
   El valor va con holgura sobre lo medido para que quede aire, no pegado. */
html { scroll-padding-top: 210px; }
@media (max-width: 900px) { html { scroll-padding-top: 170px; } }

/* La cabecera completa —franja, navbar, franja— se pega como UNA pieza.
   La fijación está acá y no en el `.header`: si cada parte se pegara por su
   cuenta, al bajar el navbar se despegaba de sus dos franjas y quedaba
   flotando sin remate. */
.cabecera-fija {
  position: sticky; top: 0; z-index: 30;
}

/* ====================================== la reserva (04-08-2026)
   El monto grande y la explicación pegada abajo. La duda real del cliente no es
   cuánto es, es si la pierde: por eso la frase "se descuenta del valor total"
   va del mismo tamaño que el resto del texto y no como letra chica. */
.caja-reserva { border-left: 3px solid var(--terracota); }
.reserva-monto {
  font-family: var(--serif); font-weight: 700;
  font-size: clamp(1.6rem, 4vw, 2.1rem);
  line-height: 1.1; color: var(--terracota-texto);
  margin: .6rem 0 .2rem;
}
.reserva-monto span {
  font-family: var(--sans); font-weight: 600;
  font-size: .62rem; letter-spacing: .18em; text-transform: uppercase;
  color: var(--tinta-suave); display: block; margin-top: .3rem;
}
.reserva-detalle { margin: 0 0 .5rem; }

/* ====================================== aviso de idiomas (04-08-2026)
   Franja finita en lo más alto de la cabecera pegada. Va en tinta y no en papel
   para que se lea como un dato del estudio y no como una fila del menú.

   Es UN aviso, no dos botones: sin enlaces, sin hover, sin cursor de mano. El
   sitio no está traducido y prometer una versión en inglés que no existe es
   peor que no decir nada.

   A 320 px las dos frases suman más que el ancho de la pantalla, así que ahí se
   apilan (`flex-wrap`) en vez de desbordar: son 2 líneas de 15 px, no 40 px de
   scroll horizontal. */
.franja-idiomas {
  background: var(--tinta);
  color: rgba(246, 238, 220, .82);
  padding: .2rem 0;
}
.idiomas {
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: center; gap: .3rem .55rem;
  font-family: var(--sans); font-size: .64rem;
  letter-spacing: .1em; text-transform: uppercase;
  line-height: 1.5;
}
.idioma { display: inline-flex; align-items: center; gap: .34rem; }
/* 12-08-2026: "We speak English" / "Nós falamos português" pasaron de <span>
   (aviso, sin clic) a <a> (selector real de idioma). Sin esto heredaban
   `a { color: var(--terracota-texto) }` del reset global, que es un rojo
   pensado para texto sobre papel claro y se pierde contra el fondo oscuro de
   `.franja-idiomas`. `color: inherit` deja el bloque IGUAL de visto que
   antes; el subrayado en hover/foco es la única señal nueva de que ahora se
   puede hacer clic. */
.idioma { color: inherit; text-decoration: none; }
.idioma:hover, .idioma:focus-visible { text-decoration: underline; }
/* El idioma activo se marca en negrita, no solo con color: alguien que no
   distingue el rojo del texto normal igual tiene que poder saber en cuál
   está parado. */
.idioma-activo { font-weight: 700; text-decoration: underline; }
/* El foco por defecto (`--terracota-oscuro`, ver arriba) es un rojo oscuro
   pensado para el papel claro: sobre `.franja-idiomas`, que es casi negra,
   pierde casi todo el contraste. Mismo criterio que ya usa el panel
   (`aside :focus-visible` en panel/base_panel.html) para su propio menú
   oscuro. */
.franja-idiomas :focus-visible { outline-color: var(--papel-claro); }
.bandera {
  width: 17px; height: 12px; flex: 0 0 auto;
  border-radius: 1px;
  /* El filete evita que la franja blanca de la bandera de EE.UU. se pierda
     contra un fondo claro (en el pie la franja va sobre papel). */
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .28);
  display: block;
}
.idiomas-punto { opacity: .45; }
/* En el pie el mismo bloque va sobre papel: hereda el color del texto de ahí y
   se alinea a la izquierda como el resto de los datos. */
.footer .idiomas {
  justify-content: flex-start;
  color: inherit;
  font-size: .62rem;
  margin-top: .15rem;
}
@media (max-width: 420px) {
  /* En el teléfono el punto separador sobra: las dos frases ya van una debajo
     de la otra y el punto queda flotando en una línea suelta. */
  .franja-idiomas .idiomas-punto { display: none; }
  .franja-idiomas .idiomas { gap: .1rem .5rem; font-size: .58rem; }
}
.header {
  /* El tono va DERIVADO de --papel-claro, no escrito a mano: estaba fijo en
     rgba(244,235,218,.95) —el crema viejo— y al amarillear el papel el navbar
     quedaba de otro color que el resto de la página. Con `color-mix` sigue al
     papel solo si alguien lo vuelve a cambiar.

     OPACO, no translúcido (06-08-2026). Tenía 95% de opacidad y un desenfoque
     de 6 px, y en la galería eso se veía como MANCHAS QUE SE MUEVEN: al bajar,
     las fotos de los tatuajes pasan por detrás de la cabecera pegada y se
     transparentaban a través de ella. Medido en producción comparando la misma
     franja de pantalla en cuatro posiciones de scroll: la cabecera cambiaba en
     todas, con diferencias de hasta 645 sobre 765.

     Un 5% de transparencia con un desenfoque chico NO es un material de vidrio:
     es una superficie apenas sucia. Y el vidrio tampoco corresponde acá — la
     metáfora del sitio es PAPEL, y el papel no se transparenta. */
  background: var(--papel-claro);
  border-bottom: 1px solid var(--borde);
}
.header-inner { display: flex; align-items: center; gap: 1.5rem; padding: .55rem 0; }
.logo { display: flex; align-items: center; gap: .7rem; font-family: var(--sans); font-weight: 700; letter-spacing: .04em; }
/* El logo llega en JPG negro sobre blanco. `multiply` hace que el blanco se funda
   con el papel crema, así no se ve el recuadro blanco y no hay que editar la imagen. */
.logo-img {
  width: 88px; height: 88px; object-fit: contain;
  mix-blend-mode: multiply;
}
/* El logo principal es el SELLO CIRCULAR ("Púas Tatuajes · Tattoo Studio ·
   desde 1992"), no el triangular: es la pieza protagonista del header en el
   mockup aprobado, así que va grande.
   El archivo viene con fondo negro cuadrado, por eso el recorte circular: sin
   él quedaría un cuadrado negro sobre el papel. Con `multiply` encima, el
   blanco de las letras toma el crema del papel y el negro se mantiene, o sea
   se lee como un sello estampado en la hoja. */
.logo-sello {
  width: clamp(84px, 9.5vw, 122px);
  height: auto; aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 2px 10px -2px rgba(26, 21, 18, 0.35);
}
.logo-sello-footer { width: clamp(104px, 12vw, 146px); }

.logo-fallback {
  width: 62px; height: 62px; border-radius: 50%; border: 2px solid var(--tinta);
  display: grid; place-items: center; font-size: .6rem; text-align: center;
  font-family: var(--sans); letter-spacing: .06em; line-height: 1.1; padding: 4px;
}
.nav { margin-left: auto; display: flex; align-items: center; gap: 1.6rem; }
.nav a {
  font-family: var(--sans); font-size: .78rem; letter-spacing: .14em;
  text-transform: uppercase; color: var(--tinta); font-weight: 500;
}
.nav a.activo, .nav a:hover { color: var(--terracota-texto); }

.btn {
  display: inline-block; font-family: var(--sans); font-size: .78rem; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; padding: .85rem 1.6rem;
  background: var(--terracota); color: #fff; border: 0; border-radius: var(--radio);
  cursor: pointer; box-shadow: var(--elev-1);
  /* `manipulation` saca el retraso de ~300ms que el navegador se guarda por si
     el toque era un doble-tap. Acá no hay doble-tap en ninguna parte, así que
     ese retraso es latencia regalada justo en el momento que el usuario mira. */
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition: background .18s ease, transform .18s ease, box-shadow .18s ease;
}
.btn:hover { background: var(--terracota-oscuro); color: #fff; transform: translateY(-1px); box-shadow: var(--elev-2); }
/* La respuesta vive en el PRESIONAR, no en el soltar. Un botón que solo
   reacciona cuando ya lo soltaste se siente muerto: el usuario está mirando
   justo el instante en que aprieta. 100ms y hacia adentro, como algo que cede
   bajo el dedo. Antes no existía ni un `:active` en las 878 líneas de CSS. */
.btn:active {
  transform: scale(.97);
  box-shadow: var(--elev-1);
  transition: transform 100ms ease-out, box-shadow 100ms ease-out;
}
.btn-linea { background: transparent; color: var(--tinta); border: 1px solid var(--tinta); box-shadow: none; }
.btn-linea:hover { background: var(--tinta); color: var(--papel); box-shadow: none; }
.btn-linea:active { background: var(--tinta); color: var(--papel); }
.btn-ancho { width: 100%; text-align: center; }

/* Lo mismo para todo lo demás que se toca: enlaces del menú, pastillas del
   filtro, tarjetas y el botón flotante. Un sitio donde SOLO los botones
   responden al tacto se siente parcialmente vivo, que es peor que uno quieto. */
.nav a, .pastilla, .tarjeta a, .tarjeta button, .flotante, .logo {
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.nav a:active, .pastilla:active { transform: scale(.97); transition: transform 100ms ease-out; }
/* El `:active` de los botones flotantes vive con su bloque, más abajo. Acá
   había una regla para `.whatsapp-flotante`, clase que nunca existió en el
   HTML. */

/* ---------------------------------------------------------------- hero */
/* ------------------------------------------------------------ hero a sangre
   La foto ocupa todo el ancho y el texto va encima, abajo a la izquierda.
   El alto se limita con `min-height` y no con `height: 100vh` a propósito: en
   un teléfono, 100vh incluye la barra del navegador que aparece y desaparece
   al hacer scroll, así que el hero "salta". Con min-height + un tope en dvh,
   si el texto crece (por una traducción o por el ajuste de tamaño de letra del
   sistema) la sección crece con él en vez de recortarlo. */
.hero-sangre {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: min(86vh, 760px);
  padding: clamp(3rem, 8vw, 7rem) 0 clamp(2.5rem, 5vw, 4rem);
  overflow: hidden;
}
.hero-sangre-fondo {
  position: absolute; inset: 0; z-index: 0;
  background-color: var(--papel-oscuro);
}
.hero-sangre-fondo img { width: 100%; height: 100%; object-fit: cover; }
/* El degradado NO es adorno: es lo que asegura que el texto se lea sobre
   CUALQUIER foto que suba Gabriel. Arranca transparente arriba para no matar
   la foto y llega casi opaco abajo, que es donde vive el texto. */
.hero-sangre::before {
  content: '';
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    /* 1) Capa anclada ABAJO y medida en píxeles: cubre exactamente la franja
          donde vive el texto, mida lo que mida el hero. En porcentajes esto
          fallaba en el teléfono — el hero es más bajo y el bloque de texto más
          alto, así que la bajada caía en la zona clara de la foto. */
    linear-gradient(to top,
      rgba(26, 21, 18, .94) 0,
      rgba(26, 21, 18, .88) 140px,
      rgba(26, 21, 18, .55) 300px,
      rgba(26, 21, 18, 0) 440px),
    /* 2) Velo general muy suave, para que la foto no compita con el menú. */
    linear-gradient(180deg,
      rgba(26, 21, 18, .10) 0%,
      rgba(26, 21, 18, .22) 100%);
}
.hero-sangre-texto { position: relative; z-index: 2; width: min(1180px, 92vw); margin: 0 auto; }
.hero-sangre-texto .filigrana { opacity: .9; filter: brightness(2.2); }
.hero-sangre-texto h1 { color: var(--papel-claro); margin-bottom: .18em; }
.hero-sangre-datos {
  margin: 0 0 .9rem;
  font-family: var(--sans); font-size: .78rem; font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase;
  /* Sobre el fondo oscuro el terracota de texto (#7A2231) se hunde: acá va el
     claro, que sobre la tinta da buen contraste. Es el mismo criterio de
     siempre —el color del texto depende del fondo— aplicado al revés. */
  color: #E093A6;
}
.hero-sangre-bajada {
  margin: 0 0 1.6rem; max-width: 42ch;
  color: rgba(246, 238, 220, .92); font-size: 1.12rem; line-height: 1.5;
}
.hero-sangre-cta { margin: 0; }
.hero-sangre-placeholder {
  width: 100%; height: 100%;
  display: grid; place-items: center; align-content: center; gap: .6rem;
  padding: 2rem; text-align: center;
  background-image: var(--ruido);
  font-family: var(--serif); font-style: italic; color: var(--tinta-suave);
}
@media (max-width: 620px) {
  .hero-sangre { min-height: min(78vh, 620px); }
  .hero-sangre-bajada { font-size: 1rem; }
}

/* ================================================== tarjeta de artista (equipo)
   Retrato a sangre en duotono terracota + placa de tinta abajo con el rol en
   cursiva y el nombre en versalitas anchas.

   EL DUOTONO SE HACE EN CSS, no editando las fotos: Gabriel las sube desde el
   panel desde el teléfono y no va a exportar una versión tratada de cada una.

   La receta es fondo TERRACOTA OSCURO + la foto en blanco y negro con
   `mix-blend-mode: screen`. Con `screen`, donde la foto es negra queda el color
   del fondo y donde es blanca queda blanco: o sea sombras en rojo hondo y luces
   limpias, que es exactamente el contraste de la referencia.
   El primer intento fue `luminosity` sobre terracota claro y salió rosado y
   lavado — se ve en la captura, no es opinión.
   El `isolation: isolate` del contenedor no es opcional: sin él la mezcla se
   escapa hacia el fondo de la página y tiñe lo que hay detrás.

   Al pasar el mouse la foto vuelve a su color real. El tratamiento es una
   pieza de diseño, no una forma de esconder la foto de nadie. */
.grilla-artistas { gap: clamp(1rem, 2vw, 1.6rem); }

.artista {
  position: relative;
  background: var(--tinta);
  box-shadow: var(--elev-2);
  overflow: hidden;
}
.artista-enlace {
  display: flex; flex-direction: column;
  height: 100%;
  color: inherit; text-decoration: none;
}
.artista-foto {
  position: relative;
  isolation: isolate;                 /* encierra la mezcla: ver arriba */
  background: var(--tinta);
  aspect-ratio: 4 / 5;
  overflow: hidden;
}
.artista-foto img,
.artista-foto .placeholder {
  width: 100%; height: 100%;
  object-fit: cover;
  /* El recorte se ancla arriba: en un retrato de alguien trabajando la cara
     está en el tercio superior, y centrado se llevaba el techo. */
  object-position: center 28%;
}
/* La foto se ve EN SU COLOR de entrada y pasa al duotono al pasar el mouse.
   Es al revés de como se hizo primero: el retrato real es lo que presenta a la
   persona, y el tratamiento es la reacción. */
.artista-foto img {
  filter: none;
  transition: filter .4s ease, transform .6s cubic-bezier(.22, 1, .36, 1);
}
.artista-foto .placeholder {
  display: grid; place-items: center; align-content: center;
  /* El hueco vacío se queda dentro del bloque oscuro en vez de abrir un
     rectángulo crema: con dos de las tres tarjetas sin foto, un placeholder
     claro rompía la fila entera. */
  background: var(--terracota-oscuro); background-image: var(--trama-placeholder);
  font-family: var(--serif); font-style: italic; color: rgba(246, 238, 220, .82);
  padding: 1rem; text-align: center;
}
@media (hover: hover) and (pointer: fine) {
  .artista:hover .artista-foto img {
    /* `screen` sobre el fondo terracota oscuro: donde la foto es negra queda el
       rojo hondo y donde es blanca queda blanco. La foto se pasa antes a blanco
       y negro con contraste, si no el color propio ensucia la mezcla. */
    mix-blend-mode: screen;
    /* El `brightness` va BAJO 1 a propósito: `screen` siempre aclara, así que
       con la foto a su brillo normal el duotono salía rosado y lavado. Se
       oscurece antes de mezclar para que las sombras queden rojo hondo y solo
       los brillos reales lleguen a blanco. */
    filter: grayscale(1) contrast(1.35) brightness(.72);
    transform: scale(1.03);
  }
  .artista-foto { background: var(--terracota-oscuro); }
}

.artista-placa {
  display: flex; flex-direction: column; align-items: center; gap: .28rem;
  padding: 1.1rem 1rem 1.25rem;
  text-align: center;
  background: var(--tinta);
}
.artista-rol {
  font-family: var(--serif); font-style: italic;
  font-size: .92rem; color: rgba(246, 238, 220, .72);
}
.artista-nombre {
  font-family: var(--sans); font-weight: 700;
  font-size: clamp(1rem, 1.5vw, 1.22rem);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--papel-claro);
  line-height: 1.2;
}
/* ---- artistas invitados ----
   La tarjeta es la misma del equipo (es el mismo modelo con `es_invitado`), así
   que la diferencia se dice con una etiqueta sobre la foto y las fechas bajo el
   nombre. Sin eso, un invitado que estuvo dos semanas queda publicado como si
   fuera parte del estudio. */
.artista-etiqueta {
  position: absolute; top: .55rem; left: .55rem;
  z-index: 2;
  padding: .22rem .6rem;
  background: var(--terracota); color: #fff;
  font-family: var(--sans); font-size: .62rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase;
  border-radius: 2px;
}
.artista-fechas {
  font-family: var(--sans); font-size: .68rem;
  letter-spacing: .1em; text-transform: uppercase;
  color: rgba(246, 238, 220, .6);
}
.ficha-fechas {
  font-family: var(--sans); font-size: .78rem;
  letter-spacing: .08em; color: var(--tinta-suave);
  margin: -.2rem 0 1rem;
}

/* El Instagram va FUERA del enlace de la tarjeta (un <a> dentro de otro <a> es
   HTML inválido) y se posiciona encima de la placa. */
.artista-ig {
  position: absolute; left: 50%; bottom: .5rem;
  transform: translateX(-50%);
  width: 26px; height: 26px;
  display: grid; place-items: center;
  color: rgba(246, 238, 220, .68);
  transition: color .25s ease, transform .25s ease;
}
.artista-ig svg { width: 16px; height: 16px; fill: currentColor; display: block; }
.artista-ig:hover { color: var(--papel-claro); transform: translateX(-50%) scale(1.12); }
/* Con Instagram cargado la placa necesita aire abajo para el icono. */
.artista:has(.artista-ig) .artista-placa { padding-bottom: 2.2rem; }

@media (max-width: 620px) {
  .artista-nombre { letter-spacing: .08em; }
  /* En el teléfono el icono medía 26x26: bajo el mínimo de 44 px, y encima está
     pegado al nombre del artista, que es OTRO enlace. Se agranda solo el ÁREA
     QUE RECIBE EL DEDO — el dibujo sigue en 16 px, así que la tarjeta se ve
     igual. Se hace solo acá porque con mouse 26 px se apunta sin problema. */
  .artista-ig { width: 44px; height: 44px; bottom: .1rem; }
  .artista:has(.artista-ig) .artista-placa { padding-bottom: 2.6rem; }
}

/* ------------------------------------------------------- sección de papel
   El bloque de trabajos de la portada estuvo sobre tinta y Gabriel pidió que
   fuera claro (revisión del 3-08). Para que la portada no quede plana de
   arriba abajo —que era justo el motivo del bloque oscuro— la sección va sobre
   el papel MÁS HONDO de la paleta, con un filete arriba y abajo. El escalón es
   chico a propósito: tiene que leerse como otra hoja, no como otra sección. */
.seccion-papel {
  position: relative;
  background-color: var(--papel-oscuro);
  /* La madera va PRIMERO en la lista (o sea encima del ruido) y mezclada en
     multiply contra el color de fondo del propio elemento. `.seccion-papel`
     tiene fondo opaco, así que tapaba el papel tapiz de la página entera y
     quedaba como un rectángulo liso en medio del sitio; en vez de volverla
     translúcida —lo que le cambiaría el tono— lleva su propia copia.
     `--textura` la define la plantilla; si no hay textura cargada, `none` y
     esto queda exactamente como estaba. */
  background-image: var(--textura, none), var(--ruido);
  background-size: 320px auto, auto;
  background-blend-mode: multiply, normal;
  /* Los filetes se mantienen como RESPALDO: el recorte ya trae los suyos, así
     que en el caso normal se superponen y no se notan. Si el navegador no
     dibujara la imagen, sin esto quedaría una franja café lisa. */
  border-top: 1px solid rgba(204, 180, 132, .5);
  border-bottom: 1px solid rgba(204, 180, 132, .4);
}

/* La SECCIÓN DE TINTA ya no existe.
   Fue un bloque oscuro a sangre que le daba ritmo a la portada, pensado contra
   la queja de "se ve plano". Gabriel y Diego pidieron lo contrario el 03 y el
   04-08: primero el muro de trabajos en claro, después TODO en pergamino
   ("los fondos cafés como 'de la casa', quitarlos, todo papel pergamino").
   El ritmo ahora lo dan `.seccion-papel` (el papel más hondo con sus filetes) y
   el estampado de los dibujos, no el contraste claro/oscuro.
   Si algún día vuelve a hacer falta un bloque oscuro, está en el historial:
   commit 4f29560 hacia atrás. No se deja el CSS muerto acá. */

/* --------------------------------------------------- línea de tiempo de logos
   La historia de los sellos del estudio. Es lo más difícil de copiar que tiene
   esta marca: 33 años de logos propios. Va sobre tinta para que los sellos
   —que son blanco sobre negro— se lean como piezas y no como recortes. */
.linea-logos {
  display: grid;
  /* `auto-fit` con un mínimo alto dejaba 5 columnas y mandaba el sexto sello a
     una segunda fila: es una LÍNEA DE TIEMPO, tiene que leerse de corrido. Se
     fijan las columnas al número de sellos y se achica la separación, que es
     lo que permite que sean grandes sin partir la serie.
     El número sale de la plantilla (`--logos`), NO escrito a mano: desde que
     Gabriel puede ocultar logos desde su panel, un 6 fijo deja una columna
     vacía a un lado en cuanto apaga uno (paso el 14-08 al sacar el sello rojo).
     El tope de 200px evita el otro extremo: con 2 sellos, `1fr` los dejaba de
     medio ancho de pantalla. `justify-content: center` es lo que mantiene la
     serie centrada sea cual sea la cantidad. */
  grid-template-columns: repeat(var(--logos, 6), minmax(0, 200px));
  justify-content: center;
  /* `start` y no el `stretch` por defecto: si no, las columnas con textos más
     largos estiran a las demás y los sellos dejan de estar en la misma línea. */
  align-items: start;
  gap: clamp(.9rem, 1.4vw, 1.3rem);
  margin-top: 2.4rem;
}
/* Entre tableta y escritorio angosto, seis en fila los deja diminutos: tres y
   tres se lee mejor y sigue siendo una serie. */
@media (max-width: 1000px) {
  /* `auto-fit` en vez de un 3 fijo: colapsa las columnas que quedan sin sello,
     asi que con menos de 3 la serie sigue centrada en vez de irse a la
     izquierda dejando un hueco (mismo problema que en escritorio). El ancho fijo
     de 200px es lo que hace que quepan 3 a 768px, que era la intencion original. */
  .linea-logos { grid-template-columns: repeat(auto-fit, 200px); }
}
/* `margin: 0` no es cosmético: <figure> trae `margin: 1em 40px` por defecto en
   el navegador, así que de los 167px de columna se comía 80 y el sello quedaba
   en 57px. Se detectó midiendo la caja, no mirando la captura. */
.linea-logo { text-align: center; margin: 0; }
/* El marco va CREMA, no oscuro, aunque la sección sea de tinta: los sellos de
   Gabriel son negros sobre transparente, así que sobre fondo oscuro
   desaparecen. Puesto sobre papel se leen como lo que son —sellos estampados—
   y de paso el bloque oscuro los enmarca como piezas de museo.
   Se comprobó montando los 8 sobre crema y sobre tinta antes de decidir. */
.linea-logo-marco {
  position: relative;
  aspect-ratio: 1;
  background: var(--papel-claro);
  background-image: var(--ruido);
  border: 1px solid rgba(26, 21, 18, .22);
  border-radius: var(--radio);
  box-shadow: var(--elev-2);
}
/* La imagen va ABSOLUTA para que no participe del tamaño de la caja. Con la
   imagen en el flujo, `aspect-ratio: 1` cedía ante los sellos verticales (hay
   dos, de 433x577 y 420x594) y esos dos marcos salían de 212 y 223px de alto
   en vez de 167: la fila quedaba desalineada. `aspect-ratio` es una sugerencia
   que pierde contra el tamaño mínimo del contenido.
   Sin `mix-blend-mode`: con los PNG recortados no hace falta y sobre papel
   arruinaría los sellos en color (hay uno rojo y uno turquesa). */
/* El margen baja de 1rem a .55rem: el sello es la pieza, no el marco. Con
   1rem los logos verticales —que ya pierden ancho al ajustarse dentro de un
   cuadrado— quedaban visiblemente más chicos que los circulares. */
.linea-logo-marco img {
  position: absolute; inset: .55rem;
  width: calc(100% - 1.1rem); height: calc(100% - 1.1rem);
  object-fit: contain;
}
/* Los pies iban en crema porque la sección era de tinta. Al pasar a papel
   (04-08) quedaron blancos sobre crema: ilegibles. Se vio en la captura.
   Ahora usan los colores de texto del sitio, que son los que están medidos
   contra el papel: --terracota-texto da 7,56:1 y --tinta-suave 7,73:1. */
.linea-logo-anio {
  display: block; margin-top: .7rem;
  font-family: var(--sans); font-size: .74rem; font-weight: 700;
  letter-spacing: .16em; color: var(--terracota-texto);
}
.linea-logo-desc { display: block; margin-top: .25rem; font-size: .92rem; color: var(--tinta-suave); }
/* En el teléfono el mínimo de 180px deja UNA sola columna (el contenedor mide
   379px a 412 de ancho) y la sección se vuelve una tira larguísima de seis
   sellos gigantes. Acá manda que se vean dos y se pueda comparar la serie. */
@media (max-width: 620px) {
  /* Igual que arriba: `auto-fit` para que un solo sello quede centrado y no
     pegado al borde izquierdo. 150px es lo que deja 2 por fila a 360px. */
  .linea-logos { grid-template-columns: repeat(auto-fit, 150px); gap: 1rem; }
}

/* El aire crece con la pantalla. Con 3.5rem fijos, en 1440 el hero ocupaba un
   tercio de lo que debía y el título quedaba apretado entre la greca y la
   franja: se leía como un encabezado más, no como la entrada al sitio. */
.hero {
  display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1.15fr); align-items: center;
  gap: clamp(2.5rem, 4vw, 4rem);
  padding: clamp(3.5rem, 7vw, 6.5rem) 0;
}
.hero-texto .desde {
  font-family: var(--sans); font-weight: 700; letter-spacing: .18em;
  color: var(--terracota-texto); font-size: .85rem; margin: .6rem 0 1.2rem;
}
/* La foto del hero va MONTADA sobre papel: el marco crema con su filete es el
   passepartout y la foto queda hundida adentro, con viñeteado en los bordes.
   Queda preparado para cuando llegue la foto de Gabriel: mientras el
   placeholder ocupa el mismo hueco y se ve igual de cuidado. */
.hero-foto {
  position: relative;
  padding: .7rem;
  background-color: var(--papel-claro);
  background-image: var(--ruido);
  border: 1px solid var(--borde);
  /* Es la pieza más grande de la página: tiene que leerse más gruesa que una
     tarjeta de la galería. Con la misma sombra que un elemento chico, una foto
     grande se ve pegada al fondo en vez de apoyada sobre él.
     Se COMPONE, no se reemplaza: se mantiene el montaje sobre papel (la línea
     de luz arriba y la sombra corta) y encima se agrega la caída larga que le
     da el peso. Sustituirlo por otra sombra le quitaba el passepartout, que es
     parte de la identidad aprobada. */
  box-shadow:
    var(--sombra-montada),
    0 18px 44px -18px rgba(26, 21, 18, 0.30),
    0 40px 80px -50px rgba(26, 21, 18, 0.35);
  aspect-ratio: 4 / 3;
}
.hero-foto > img,
.hero-foto > .placeholder {
  width: 100%; height: 100%; object-fit: cover;
  border: 1px solid var(--borde-fuerte);
}
/* Viñeteado sobre la foto: oscurece apenas las esquinas, como una copia en
   papel. Va por encima de la imagen pero sin robarle el clic. */
.hero-foto::after {
  content: '';
  position: absolute; inset: .7rem;
  pointer-events: none;
  box-shadow:
    inset 0 0 34px rgba(26, 21, 18, 0.20),
    inset 0 0 90px rgba(26, 21, 18, 0.12);
}

/* Placeholder: mientras no llega la foto, tiene que verse como una hoja en
   blanco esperando, no como un error. Trama cruzada muy tenue, filete interior
   y el texto en serif itálica. */
.placeholder {
  width: 100%; height: 100%; min-height: 180px;
  /* align-content además de place-items: si no, las dos filas (la filigrana y el
     texto) se estiran a lo alto de la tarjeta y quedan separadas en las puntas
     en vez de juntas al centro. */
  display: grid; place-items: center; align-content: center; gap: .6rem;
  background-color: var(--papel-oscuro);
  background-image:
    var(--ruido),
    repeating-linear-gradient(45deg, rgba(26, 21, 18, 0.045) 0 1px, transparent 1px 11px),
    repeating-linear-gradient(-45deg, rgba(26, 21, 18, 0.045) 0 1px, transparent 1px 11px);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.35), inset 0 0 0 5px transparent;
  color: var(--tinta-suave); font-family: var(--serif); font-style: italic;
  font-size: .95rem; line-height: 1.35;
  letter-spacing: .01em; text-align: center; padding: 1.2rem;
}
.placeholder::before {
  content: '';
  width: 90px; height: 16px;
  background: var(--filigrana) no-repeat center / contain;
  opacity: .45;
}

/* ---------------------------------------------------------------- franjas */
.franja {
  display: flex; justify-content: center; gap: 3.5rem; flex-wrap: wrap;
  padding: 1.5rem 0; border-top: 1px solid var(--borde); border-bottom: 1px solid var(--borde);
  background: rgba(244, 235, 218, .55);
}
.franja-item {
  position: relative;
  display: flex; align-items: center; gap: .85rem;
  text-align: left; font-family: var(--sans);
}
/* La franja pasa de Inter a la SERIF del sitio, en versalitas anchas arriba y
   texto normal abajo. Es el mismo tratamiento que pidió Diego a partir de una
   referencia: el titular manda por espaciado, no por tamaño, y la bajada lo
   acompaña en la misma familia en vez de contrastar.
   El 700 de Cormorant se agregó al pedido de Google Fonts para esto: con 600 el
   titular quedaba blando al lado del texto. */
.franja-item strong {
  display: block;
  font-family: var(--serif); font-weight: 700;
  font-size: clamp(1rem, 1.35vw, 1.18rem);
  letter-spacing: .2em; text-transform: uppercase;
  line-height: 1.25;
}
.franja-item span {
  font-family: var(--serif);
  font-size: .95rem; color: var(--tinta-suave);
  letter-spacing: 0; line-height: 1.4;
}
/* Separador vertical fino entre ítems: se difumina en las puntas para que no
   parezca una tabla. Va centrado en el gap (3.5rem / 2 = 1.75rem). */
.franja-item + .franja-item::before {
  content: '';
  position: absolute; left: -1.75rem; top: 8%; bottom: 8%; width: 1px;
  background: linear-gradient(180deg, transparent, var(--borde-fuerte) 22%,
              var(--borde-fuerte) 78%, transparent);
}
/* Íconos de línea, dibujados a mano en SVG (espiral, tortuga, sol). Son
   decorativos: van con aria-hidden en la plantilla. */
/* Con el prefijo `.franja-item` para ganarle a `.franja-item span`, que si no le
   pisa el color al ícono. */
.franja-item .franja-icono {
  flex: 0 0 auto; width: 34px; height: 34px;
  color: var(--terracota-texto);
}
.franja-item .franja-icono svg { width: 100%; height: 100%; display: block; }

/* Mismo criterio que el hero: el aire escala con la pantalla. Con un padding
   fijo, en escritorio las secciones se amontonan y el sitio se lee como una
   lista continua en vez de bloques con respiración propia. */
.seccion { padding: clamp(3.5rem, 5.5vw, 5.5rem) 0; }
.seccion-titulo { text-align: center; margin-bottom: clamp(2.2rem, 3.2vw, 3.2rem); }

/* ---------------------------------------------------------------- grillas */
.grilla { display: grid; gap: 1.4rem; }
.grilla-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grilla-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grilla-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* ------------------------------------------------------------- mosaico
   La galería en columnas de alturas desparejas, no en una retícula de
   tarjetas idénticas. Antes todas las fotos iban recortadas a 3:4, así que
   47 piezas distintas se veían como 47 rectángulos iguales — de ahí la
   sensación de "cuadrado". Acá cada foto conserva SU proporción: las
   verticales se ven verticales y las anchas se ven anchas, y la irregularidad
   la produce el material, no un efecto.
   Se usa `columns` y no grid a propósito: no necesita JS ni medir imágenes, y
   si algo falla degrada a una columna, que sigue siendo una galería usable. */
.mosaico {
  columns: 4 260px;
  column-gap: 1.1rem;
}
.mosaico > * {
  /* Sin esto una tarjeta se puede partir entre dos columnas. */
  break-inside: avoid;
  page-break-inside: avoid;
  margin-bottom: 1.1rem;
}
@media (max-width: 900px) { .mosaico { columns: 2 150px; column-gap: .8rem; } .mosaico > * { margin-bottom: .8rem; } }
@media (max-width: 480px) { .mosaico { columns: 2 130px; } }

/* Dentro del mosaico la foto manda: se suelta el recorte a 3:4 para que cada
   pieza conserve su proporción real. Es LO que produce el desnivel entre
   columnas; sin esto el mosaico se ve igual que la retícula anterior. */
.mosaico .tarjeta-foto,
.mosaico .tarjeta-foto-btn { aspect-ratio: auto; }
.mosaico .tarjeta-foto img { height: auto; object-fit: contain; }

/* Un DISEÑO DE AUTORÍA no se recorta. En una foto de un tatuaje `cover` está
   bien —se ve la piel, no importa el borde—, pero acá el borde es el dibujo:
   una lámina de 916x1600 dentro de una caja de 554x739 perdía la aleta y la
   firma. Antes no se veía porque el archivo traía margen blanco y lo que se
   cortaba era el papel; al sacarle el fondo quedó a la vista que el recorte
   siempre estuvo ahí. `contain` y la altura la pone el dibujo. */
.tarjeta-diseno .tarjeta-foto,
.tarjeta-diseno .tarjeta-foto-btn { aspect-ratio: auto; }
.tarjeta-diseno .tarjeta-foto img { height: auto; object-fit: contain; }

/* El rótulo va SOBRE la foto, no en una franja debajo. Así la pieza ocupa
   toda la tarjeta y la galería se lee como un muro de trabajos y no como un
   catálogo de fichas.
   Va SIEMPRE visible, no al pasar el cursor: en un teléfono no hay cursor, y
   una etiqueta que solo aparece con hover es una etiqueta que la mitad de la
   gente nunca ve. El degradado la hace legible sobre cualquier foto. */
.mosaico .tarjeta-pie {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  padding: 2.4rem .85rem .8rem;
  text-align: left;
  color: #F6EEDC;
  background: linear-gradient(180deg, rgba(20, 16, 12, 0) 0%, rgba(20, 16, 12, .72) 55%, rgba(20, 16, 12, .88) 100%);
}
/* SIN MARCO. La foto va a borde, sin passepartout, sin filete y sin la hoja de
   papel debajo. El montaje sobre papel funciona para UNA pieza enmarcada —el
   hero, el mapa— pero repetido en una grilla de 40 fotos lee como álbum de los
   noventa y envejece la página entera. Acá manda la fotografía.
   Las reglas de `.tarjeta` y `.tarjeta-trabajo` se desarman a propósito en vez
   de tocarlas en su origen: ese tratamiento sigue siendo el correcto fuera del
   mosaico. */
.mosaico .tarjeta-trabajo {
  position: relative; padding: 0;
  background: none; border: 0; box-shadow: none;
}
.mosaico .tarjeta-foto,
.mosaico .tarjeta-foto-btn {
  border: 0; box-shadow: none; background: none;
}
/* La elevación pasa a la tarjeta completa, no al marco: al presionar y al pasar
   el puntero sigue respondiendo, pero sin dibujar una caja alrededor. */
.mosaico .tarjeta-trabajo:hover { box-shadow: var(--elev-2-hover); }
.mosaico .tarjeta-trabajo:active { box-shadow: var(--elev-1); }

/* ------------------------------------------------ revelado al pasar el mouse
   La foto se tiñe de terracota y el rótulo entra desde abajo, sobre un bloque
   sólido de tinta. La referencia es el rojo de marca de Tattoo Rockers, acá con
   el terracota del estudio.

   Va DENTRO de `@media (hover: hover)` a propósito: en un teléfono no existe el
   puntero, y una etiqueta que solo aparece al pasar el mouse es una etiqueta que
   la mitad de la gente nunca ve. En táctil el rótulo se queda visible como
   estaba; el efecto es un premio para quien tiene mouse, no un requisito para
   entender la galería.
   Se anima `opacity` y `transform` únicamente: son las dos propiedades que el
   navegador resuelve sin recalcular el diseño de la página. */
@media (hover: hover) and (pointer: fine) {
  .mosaico .tarjeta-foto-btn { position: relative; }
  /* Velo terracota en `multiply` (elegido por Diego): oscurece y satura, con
     más carácter que `color`. La contrapartida es que aplasta los medios tonos,
     así que la opacidad baja a .62 — a .85 el tatuaje se fundía con la piel y
     la pieza dejaba de leerse justo cuando el usuario la está mirando. */
  .mosaico .tarjeta-foto-btn::after {
    content: '';
    position: absolute; inset: 0; z-index: 1; pointer-events: none;
    background: var(--terracota);
    mix-blend-mode: multiply;
    opacity: 0;
    transition: opacity .28s ease;
  }
  .mosaico .tarjeta-trabajo:hover .tarjeta-foto-btn::after { opacity: .62; }

  /* El rótulo arranca escondido bajo el borde y sube al pasar el puntero. */
  .mosaico .tarjeta-pie {
    background: rgba(20, 16, 12, .92);
    opacity: 0;
    transform: translateY(100%);
    transition: opacity .26s ease, transform .26s cubic-bezier(.22, 1, .36, 1);
  }
  .mosaico .tarjeta-trabajo:hover .tarjeta-pie,
  /* Con el teclado el foco tiene que revelar lo mismo que el mouse: si no,
     recorrer la galería con Tab deja al usuario sin saber qué está enfocando. */
  .mosaico .tarjeta-trabajo:focus-within .tarjeta-pie {
    opacity: 1; transform: translateY(0);
  }
  .mosaico .tarjeta-trabajo:focus-within .tarjeta-foto-btn::after { opacity: .62; }
}

/* Reducir movimiento no es quitar la información: el rótulo aparece igual, pero
   sin el desplazamiento. */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: reduce) {
  .mosaico .tarjeta-pie { transform: none; }
  .mosaico .tarjeta-trabajo:hover .tarjeta-pie { transform: none; }
}
.mosaico .tarjeta-pie::before { display: none; }   /* el filete corto no va sobre la foto */
.mosaico .tarjeta-pie:hover { color: #fff; }
.mosaico .tarjeta-sub { color: rgba(246, 238, 220, .82); }

.tarjeta {
  background-color: var(--papel-claro);
  background-image: var(--ruido);
  border: 1px solid var(--borde);
  box-shadow: var(--elev-2); overflow: hidden;
  transition: box-shadow .2s ease, transform .2s ease;
}
/* Un escalón de elevación al pasar por encima, y hacia adentro al presionar.
   No sube dos escalones ni se levanta 6px: la tarjeta es una hoja apoyada en el
   papel, no una carta que salta. */
.tarjeta:hover { box-shadow: var(--elev-2-hover); transform: translateY(-2px); }
.tarjeta:active { transform: scale(.985); box-shadow: var(--elev-1); transition: transform 100ms ease-out, box-shadow 100ms ease-out; }
.tarjeta-foto { aspect-ratio: 3 / 4; background: var(--papel-oscuro); }
.tarjeta-foto img { width: 100%; height: 100%; object-fit: cover; }
.tarjeta-pie {
  padding: .8rem; text-align: center; font-family: var(--sans);
  font-size: .74rem; letter-spacing: .14em; text-transform: uppercase;
  border-top: 1px solid var(--borde);
}
a.tarjeta-pie { display: block; color: var(--tinta); transition: color .18s ease; }
a.tarjeta-pie:hover { color: var(--terracota-texto); }
/* .75 y no .6: a .6 el texto queda justo en el límite (4.50:1 sobre el papel
   claro), sin margen para cualquier ajuste futuro del fondo. A .75 da 7.38:1. */
.tarjeta-sub { display: block; margin-top: .25rem; letter-spacing: .1em; opacity: .75; font-size: .68rem; }
.opaco { opacity: .75; }

/* ------------------------------------------------- tarjeta de la galería
   En el mockup cada foto va MONTADA sobre papel: hoja crema con margen, la
   foto hundida con su filete y su sombra, y abajo el nombre en serif centrado
   bajo un filete corto. Antes eran cards planas a sangre.
   El overflow vuelve a visible para que la sombra de la foto se vea salir
   sobre el papel. */
.tarjeta-trabajo {
  padding: .65rem .65rem 0;
  overflow: visible;
  transition: transform .2s ease, box-shadow .2s ease;
}
.tarjeta-trabajo:hover {
  transform: translateY(-2px);
  box-shadow: var(--elev-2-hover);
}
/* Este `:active` va acá, DESPUÉS de `.tarjeta-trabajo:hover`, y no arriba junto
   al de `.tarjeta`. Tienen la misma especificidad (clase + pseudoclase), así que
   manda el que aparece último: escrito más arriba, el hover de la tarjeta de
   trabajo le ganaba y la tarjeta no reaccionaba al presionar. Se detectó
   midiendo el `transform` con el puntero apretado, no leyendo el CSS. */
.tarjeta-trabajo:active {
  transform: scale(.985);
  box-shadow: var(--elev-1);
  transition: transform 100ms ease-out, box-shadow 100ms ease-out;
}
.tarjeta-trabajo .tarjeta-foto,
.tarjeta-trabajo .tarjeta-foto-btn {
  border: 1px solid var(--borde-fuerte);
  box-shadow: 0 4px 12px -4px rgba(26, 21, 18, 0.35);
  overflow: hidden;
}
/* El pie ya no necesita el borde de arriba: el filete corto centrado hace de
   separador y deja respirar el papel a los lados. */
.tarjeta-trabajo .tarjeta-pie {
  position: relative;
  border-top: 0;
  padding: 1.15rem .6rem 1rem;
  font-family: var(--serif); font-size: 1.06rem; font-weight: 500;
  letter-spacing: .01em; text-transform: none; line-height: 1.25;
}
.tarjeta-trabajo .tarjeta-pie::before {
  content: '';
  position: absolute; top: .5rem; left: 50%; transform: translateX(-50%);
  width: 52px; height: 1px;
  background: linear-gradient(90deg, transparent, var(--borde-fuerte), transparent);
}
.tarjeta-trabajo .tarjeta-sub {
  margin-top: .3rem;
  font-family: var(--sans); font-size: .66rem;
  letter-spacing: .18em; text-transform: uppercase;
}

/* La foto de la tarjeta es un botón (abre el lightbox), así que hay que
   desarmarle los estilos de botón sin perder el foco visible. */
.tarjeta-foto-btn {
  position: relative; display: block; width: 100%; padding: 0; margin: 0;
  border: 0; background: var(--papel-oscuro); cursor: zoom-in; font: inherit; color: inherit;
}
.tarjeta-lupa {
  position: absolute; right: .6rem; bottom: .6rem; width: 34px; height: 34px;
  display: grid; place-items: center; border-radius: 50%;
  background: rgba(26, 21, 18, .55); opacity: 0; transition: opacity .18s ease;
}
.tarjeta-lupa svg { width: 17px; height: 17px; fill: #fff; }
.tarjeta-foto-btn:hover .tarjeta-lupa,
.tarjeta-foto-btn:focus-visible .tarjeta-lupa { opacity: 1; }

/* ---------------------------------------------------------------- ficha del trabajo */
.miga {
  font-family: var(--sans); font-size: .74rem; letter-spacing: .06em;
  color: var(--tinta-suave); margin-bottom: 1.6rem;
}
.ficha { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr); gap: 2.5rem; align-items: start; }
/* En una cobertura la foto grande de arriba ya es el antes/después: la ficha
   se queda solo con los datos, en una columna, para no repetir la misma foto. */
.ficha.ficha-solo-datos { grid-template-columns: minmax(0,1fr); max-width: 46rem; margin: 0 auto; }
.ficha-foto {
  position: relative; display: block; width: 100%; padding: 0; margin: 0; cursor: zoom-in;
  border: 1px solid var(--borde); background: var(--papel-oscuro); box-shadow: var(--sombra);
}
.ficha-foto img { width: 100%; height: auto; }
/* Retrato del tatuador: se acota el alto y se recorta.
   `object-position: center 28%` no es un número al azar: en un retrato de
   alguien trabajando la cara queda en el tercio superior, así que anclando ahí
   el recorte se lleva el techo y el piso, no la persona. Medido con la foto de
   Gabriel (675x1200): sin esto la ficha quedaba en 1170 px de alto con el
   nombre y el botón flotando arriba.
   No se toca `.ficha-foto` a secas porque ESA es la de un tatuaje, y ahí
   recortar esconde la pieza —que es todo el punto de la página. */
.ficha-foto-retrato img {
  max-height: 620px;
  object-fit: cover;
  object-position: center 28%;
}
.ficha-foto:hover .tarjeta-lupa, .ficha-foto:focus-visible .tarjeta-lupa { opacity: 1; }
.ficha-datos h1 { font-size: clamp(1.8rem, 4vw, 2.6rem); margin-top: .2rem; }
.ficha-acciones { display: flex; gap: .8rem; flex-wrap: wrap; margin-top: 1.6rem; }

/* ---------------------------------------------------------------- lightbox */
body.sin-scroll { overflow: hidden; }
.lightbox {
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center; gap: 1rem;
  padding: clamp(1rem, 4vw, 3rem);
  /* El fondo se OSCURECE y se desenfoca a la vez: no es un telón opaco que
     tapa, es un material que se interpone. Al desenfocar lo que hay detrás, la
     foto ampliada queda sola aunque el fondo siga ahí. */
  background: rgba(20, 16, 12, .82);
  backdrop-filter: blur(14px) saturate(120%);
  -webkit-backdrop-filter: blur(14px) saturate(120%);
  opacity: 0;
  transition: opacity .22s ease;
}
.lightbox.abierto { opacity: 1; }
.lightbox[hidden] { display: none; }
.lightbox-figura {
  margin: 0; display: flex; flex-direction: column; align-items: center; gap: .9rem;
  max-width: min(1000px, 100%); max-height: 100%;
  /* La foto crece DESDE la miniatura que se tocó, no desde el centro de la
     pantalla. El JS escribe --origen-x/--origen-y con la posición real de esa
     miniatura, así que la relación entre lo que tocaste y lo que se abrió es
     evidente: si algo aparece, uno espera que venga de donde estaba.
     Los valores por defecto (el centro) cubren el caso de que el JS no corra. */
  transform-origin: var(--origen-x, 50%) var(--origen-y, 50%);
  transform: scale(.86);
  opacity: 0;
  transition: transform .26s cubic-bezier(.22, 1, .36, 1), opacity .2s ease;
  will-change: transform;
}
.lightbox.abierto .lightbox-figura { transform: scale(1); opacity: 1; }
/* Reducir movimiento no es quitar la respuesta, es darla sin desplazamiento:
   se mantiene el fundido y se elimina el crecimiento. */
@media (prefers-reduced-motion: reduce) {
  .lightbox-figura { transform: none; }
  .lightbox.abierto .lightbox-figura { transform: none; }
}
.lightbox-img {
  max-width: 100%; max-height: 74vh; object-fit: contain;
  border: 1px solid rgba(235, 223, 196, .25); background: var(--papel);
}
.lightbox-pie {
  text-align: center; font-family: var(--sans); color: var(--papel-claro);
  display: flex; flex-direction: column; gap: .3rem;
}
.lightbox-titulo { font-size: .95rem; font-weight: 600; letter-spacing: .06em; }
.lightbox-detalle { font-size: .76rem; letter-spacing: .14em; text-transform: uppercase; opacity: .7; }
.lightbox-ficha { font-size: .76rem; letter-spacing: .1em; color: #E7A79C; text-decoration: underline; }
.lightbox-ficha:hover { color: #fff; }
.lightbox-contador { font-size: .7rem; letter-spacing: .14em; opacity: .5; }
.lightbox-cerrar, .lightbox-nav {
  background: rgba(255, 255, 255, .08); color: var(--papel-claro);
  border: 1px solid rgba(235, 223, 196, .3); border-radius: 50%;
  cursor: pointer; display: grid; place-items: center; flex: 0 0 auto;
  transition: background .18s ease;
}
.lightbox-cerrar:hover, .lightbox-nav:hover { background: rgba(255, 255, 255, .2); }
.lightbox-cerrar {
  position: absolute; top: 1rem; right: 1rem; width: 44px; height: 44px; font-size: 1.7rem; line-height: 1;
}
.lightbox-nav { width: 52px; height: 52px; font-size: 2rem; line-height: 1; }
.lightbox-nav[hidden] { display: none; }

/* ---------------------------------------------------------------- símbolos */
.simbolo {
  background: var(--papel-claro); border: 1px solid var(--borde);
  box-shadow: var(--sombra); padding: 1.4rem; text-align: center;
  display: flex; flex-direction: column; gap: .8rem;
}
/* Antes eran 96×96 fijos, pensados para una silueta simple. Las láminas
   ilustradas de Gabriel traen el significado ESCRITO adentro y a ese tamaño no
   se leía nada. Ahora la figura ocupa el ancho de la tarjeta y la altura la
   pone la imagen (hasta 300px); las siluetas chicas siguen viéndose chicas
   porque la imagen nunca se estira más allá de su tamaño real. */
.simbolo-figura {
  width: 100%; min-height: 96px; max-height: 300px; margin: 0 auto;
  display: grid; place-items: center;
  padding: 0; border: 0; background: transparent; cursor: zoom-in;
}
.simbolo-figura img {
  max-width: 100%; max-height: 300px; width: auto; object-fit: contain;
  mix-blend-mode: multiply;
}
.simbolo-nombre { font-size: 1.35rem; margin: 0; }
.simbolo-atributos {
  list-style: none; margin: 0; padding: 0;
  display: flex; justify-content: center; flex-wrap: wrap; gap: .4rem;
}
.simbolo-atributos li {
  font-family: var(--sans); font-size: .68rem; letter-spacing: .12em; text-transform: uppercase;
  border: 1px solid var(--borde); border-radius: 999px; padding: .25rem .7rem; color: var(--tinta-suave);
}
.simbolo .ayuda { margin: 0; }

/* ---------------------------------------------------------------- filtros
   Rehechos el 31-07-2026 porque Gabriel no entendía para qué servían. Los tres
   problemas que tenían: (1) no decían en ninguna parte que eran un filtro;
   (2) el hover se pintaba EXACTAMENTE igual que el activo, así que al pasar el
   dedo/mouse parecía que ya estaba seleccionado; (3) no había cómo saber si un
   estilo tenía fotos antes de apretarlo. */
.filtros-caja {
  margin-bottom: 2.2rem; padding: 1.1rem 1rem;
  background: rgba(244, 235, 218, .55);
  border: 1px solid var(--borde); border-radius: var(--radio);
  box-shadow: var(--sombra);
}
.filtros-titulo {
  font-family: var(--sans); font-size: .72rem; font-weight: 600; letter-spacing: .14em;
  text-transform: uppercase; color: var(--tinta-suave); text-align: center; margin: 0 0 .85rem;
}
.filtros { display: flex; justify-content: center; gap: .5rem; flex-wrap: wrap; margin: 0; }
.filtro {
  display: inline-flex; align-items: center; gap: .45rem;
  font-family: var(--sans); font-size: .74rem; letter-spacing: .1em; text-transform: uppercase;
  padding: .5rem .9rem; border: 1px solid var(--borde-fuerte); border-radius: 999px;
  color: var(--tinta); background: var(--papel-claro);
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
/* El hover NO puede parecerse al activo: solo se oscurece el papel. */
.filtro:hover { background: var(--papel-oscuro); border-color: var(--tinta-suave); }
/* Cuántas fotos hay en ese estilo. Un filtro que lleva a una galería vacía es
   una trampa; con el número a la vista, nadie cae. */
.filtro-n {
  font-size: .68rem; letter-spacing: 0; font-weight: 600;
  background: rgba(26, 21, 18, .10); border-radius: 999px;
  padding: .1rem .45rem; min-width: 1.4em; text-align: center;
}
.filtro-check { display: none; font-size: .82rem; line-height: 1; }
.filtro.activo {
  background: var(--terracota); border-color: var(--terracota-oscuro); color: #fff;
  box-shadow: 0 2px 9px rgba(142, 44, 34, .35);
}
.filtro.activo:hover { background: var(--terracota-oscuro); }
.filtro.activo .filtro-check { display: inline; }
.filtro.activo .filtro-n { background: rgba(255, 255, 255, .25); color: #fff; }
/* Qué se está viendo, en castellano, y la salida para volver a todo. */
.filtros-resultado {
  font-family: var(--sans); font-size: .8rem; color: var(--tinta-suave);
  text-align: center; margin: .95rem 0 0; line-height: 1.6;
}
.filtro-quitar {
  display: inline-block; margin-left: .35rem; font-weight: 700;
  color: var(--terracota-texto); text-decoration: underline;
}

/* ------------------------------------------------- coberturas y reparaciones
   La especialidad de Gabriel. Dos fotos rotuladas, no un comparador que se
   arrastra: en el celular arrastrar pelea con el scroll de la página y encima
   hay que adivinar que se arrastra. Acá se ven las dos al mismo tiempo. */
.coberturas { margin: 0 0 2.8rem; }
.coberturas-intro { text-align: center; margin-bottom: 1.5rem; }
.coberturas-titulo { font-size: clamp(1.5rem, 3.4vw, 2.1rem); margin: 0 0 .4rem; }
.coberturas-intro .subtitulo { max-width: 44rem; margin: 0 auto; }
/* Sin caja. La hoja de papel con filete alrededor hacía que el bloque se leyera
   como una ficha impresa pegada en la página; las piezas tienen que respirar
   sobre el papel del sitio, igual que en el mosaico. */
.cobertura-item {
  background: none; border: 0; box-shadow: none;
  padding: 0; margin-bottom: 2.4rem;
}
/* Las dos fotos comparten ALTURA —que es lo que las vuelve comparables— pero
   cada una conserva SU ancho. Antes se las metía en una caja fija de 3:4 y,
   como son verticales de celular (9:16), sobraban dos bandas de papel a cada
   lado: la sección se veía a medio hacer. La regla de no recortar se mantiene
   intacta; lo que se saca es el hueco. */
.cobertura-par {
  display: flex; align-items: center; justify-content: center;
  gap: clamp(.6rem, 2vw, 1.6rem);
  flex-wrap: nowrap;
}
/* En el teléfono, TRES piezas en una fila dan 130 px cada una: no se ve el
   tatuaje, que es lo único que importa acá. Gabriel lo dijo mirando su celular
   ("esas tres ventanas ¿quedarían así montadas?").
   El antes y el después SIGUEN JUNTOS —separarlos rompe la comparación, que es
   el sentido del bloque— y el video, que es un extra, baja a su propia fila a
   todo el ancho. Así las dos fotos que hay que comparar pasan de 130 a 190 px
   y el video de 130 a 380. */
@media (max-width: 620px) {
  .cobertura-par { flex-wrap: wrap; align-items: stretch; }
  /* El antes y el después se REPARTEN la fila en partes iguales. Con `flex:1 1 0`
     la base es cero, así que el ancho de la foto no empuja y las dos quedan del
     mismo alto y alineadas. Sin esto se apilaban desparejas y la comparación
     —el motivo del bloque— se perdía. */
  .cobertura-par > .cobertura-lado:not(.cobertura-lado-video) { flex: 1 1 0; }
  .cobertura-flecha { width: 22px; height: 22px; }
  .cobertura-flecha svg { width: 18px; height: 12px; }
  /* El video es un extra, no parte de la comparación: se lleva su propia fila
     completa. De 130 px a todo el ancho. */
  .cobertura-lado-video { flex: 1 0 100%; margin-top: .7rem; }
  .cobertura-lado-video .cobertura-video { width: 100%; }
}
.cobertura-lado { margin: 0; position: relative; display: flex; }
/* El rótulo va SOBRE la foto, no en una pastilla flotando arriba: pegado a la
   imagen se lee como parte de la pieza y no como un control de interfaz. */
/* Pastilla chica anclada abajo a la izquierda, no una franja a todo el ancho:
   la franja tapaba parte del tatuaje, que es justamente lo que hay que ver. */
/* "En proceso" sobre la foto de la galería (Gabriel, 06-08-2026: "tatuaje en
   progreso con una marquita"). Va ARRIBA a la izquierda y no abajo, que es
   donde vive el rótulo de las coberturas: en una cobertura el rótulo dice qué
   foto es y acompaña; acá advierte, y tiene que leerse antes que la pieza.
   Sin `backdrop-filter`: son muchas tarjetas a la vez y un desenfoque por cada
   una se paga en cada marco al hacer scroll, que es justo lo que se acaba de
   arreglar. Con el fondo opaco se lee igual. */
.tarjeta-marca {
  position: absolute; left: .5rem; top: .5rem; z-index: 2;
  font-family: var(--sans); font-size: .56rem; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase;
  padding: .3rem .6rem; border-radius: 3px;
  color: #F6EEDC; background: var(--terracota-oscuro);
  pointer-events: none;
}

.cobertura-rotulo {
  position: absolute; left: .6rem; bottom: .6rem; z-index: 2;
  font-family: var(--sans); font-size: .6rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase;
  padding: .34rem .7rem; border-radius: 3px;
  color: #F6EEDC; background: rgba(20, 16, 12, .82);
  backdrop-filter: blur(4px);
}
.cobertura-rotulo-despues { background: var(--terracota); color: #fff; }
.cobertura-foto {
  display: block; padding: 0; cursor: zoom-in; border: 0; background: none;
  height: clamp(300px, 44vh, 500px);
  /* PROPORCION FIJA (04-08-2026, pedido de Diego): antes solo se fijaba la
     ALTURA y el ancho salia de la proporcion de cada foto, asi que una
     cobertura quedaba visiblemente mas angosta que la otra y las dos filas no
     se leian como el mismo bloque. Con aspect-ratio las cuatro cajas miden
     igual.
     El comentario de arriba decia que una caja fija dejaba bandas de papel a
     los lados: eso pasaba con `contain`. Con `cover` no hay bandas — se
     recorta. Es el intercambio: mismo tamano a cambio de perder un poco de
     borde, que en una foto de brazo no es donde esta el tatuaje. */
  aspect-ratio: 3 / 4;
  box-shadow: var(--elev-2);
  overflow: hidden;
}
/* Las dos cajas miden lo mismo (si una sale más alta, deja de leerse como
   comparación), pero la foto va CONTENIDA, no recortada: con `cover` las fotos
   verticales del celular (9:16) dentro de una caja 3:4 quedaban en un primer
   plano del hombro y no se veía la pieza entera. En una cobertura lo que hay
   que comparar es justamente el dibujo completo. El sobrante queda del color
   del papel, así que se ve como una foto montada. */
/* Altura fija, ancho segun la proporcion real de la foto: no se recorta nada
   (que era la razon de ser de este bloque) y tampoco sobra papel a los lados. */
.cobertura-foto img {
  display: block; height: 100%; width: 100%; max-width: none;
  /* `cover` + centrado: la foto llena la caja sin deformarse. Se recorta por
     arriba y por abajo, que en estas tomas es piel, no tatuaje. */
  object-fit: cover; object-position: center;
  background: var(--papel-oscuro);
}
/* En el teléfono la fila tiene que caber SIN scroll horizontal: dos fotos + el
   medallón + los dos huecos. Con 44vw por foto la suma daba 424px en un
   contenedor de 379 y desbordaba 19px. Los números están calculados, no
   tanteados: 2×36vw (297) + 32 del medallón + 2×.5rem (16) = 345 < 379. */
/* En el teléfono la fila tiene TRES piezas (antes, después y el video) más el
   medallón. Los anchos están calculados para el contenedor de 379px que da un
   viewport de 412: 3×26vw (321) + 26 del medallón + 3×.35rem (17) = 364 < 379.
   Con 36vw —el valor de cuando eran solo dos fotos— desbordaba 54px. */
@media (max-width: 620px) {
  .cobertura-foto { height: clamp(230px, 34vh, 320px); }
  /* El ancho ya lo fija aspect-ratio; el max-width sobraba. */
  .cobertura-par { gap: .35rem; }
  .cobertura-flecha { width: 26px; height: 26px; }
  .cobertura-flecha svg { width: 13px; height: 9px; }
  .cobertura-rotulo { left: .28rem; bottom: .28rem; font-size: .5rem; padding: .22rem .4rem; letter-spacing: .1em; }
}
/* Medallón terracota en vez de una flecha suelta: entre dos fotos oscuras, una
   flecha de 1px de trazo se pierde. Acá marca la dirección de la lectura. */
/* La flecha es un SIGNO, no un botón (06-08-2026, lo dijo Gabriel: "la flecha
   no te lleva a ningún lado"). Era un disco terracota con sombra, o sea igual
   que los botones del sitio: cualquiera la toca esperando que pase algo. Ahora
   es solo el trazo, del color del texto suave y sin fondo ni sombra. Sigue
   diciendo lo mismo —de acá para allá— sin prometer un clic. */
.cobertura-flecha {
  flex: 0 0 auto; display: grid; place-items: center;
  width: 34px; height: 34px;
  color: var(--tinta-suave); opacity: .55;
}
.cobertura-flecha svg { width: 26px; height: 16px; }

/* ------------------------------------------------- cobertura destacada (2 col) */
.cobertura-destacada {
  display: grid;
  /* La SEGUNDA pista va con `minmax(0, ...)` por el mismo motivo que la de
     móvil: `1.2fr` es `minmax(auto, 1.2fr)` y ese `auto` es el ancho mínimo del
     contenido, así que la fila del antes/después (tres piezas) empujaba la
     columna y la sección se salía del contenedor. Medido a 1024: el bloque
     terminaba en 1059 con la ventana en 1024. */
  grid-template-columns: minmax(280px, .8fr) minmax(0, 1.2fr);
  gap: clamp(2rem, 4vw, 4rem); align-items: center;
}
.cobertura-destacada-texto .kicker { display: block; margin-bottom: .5rem; }
.cobertura-destacada-texto h2 { margin-bottom: .6rem; }
.cobertura-destacada-texto .subtitulo { margin-bottom: 1.6rem; max-width: 38ch; }
.cobertura-destacada-par .cobertura-item { border: 0; padding: 0; background: none; box-shadow: none; }
.cobertura-destacada-par .cobertura-info { margin-top: 1rem; }
@media (max-width: 900px) {
  /* `minmax(0, 1fr)` y no `1fr` a secas: `1fr` es `minmax(auto, 1fr)` y ese
     `auto` es el ancho MÍNIMO DEL CONTENIDO, así que la fila del antes/después
     (tres piezas) empujaba la columna a 502 px dentro de un viewport de 412 y
     la sección se salía de la pantalla. Es el mismo error que ya apareció en
     `.grilla-4`: en una grilla, para que una columna pueda ENCOGER hay que
     decirlo. Medido: 127 px de desborde a 390, 106 a 412, 89 a 430. */
  .cobertura-destacada { grid-template-columns: minmax(0, 1fr); }
  .cobertura-destacada-texto { text-align: center; }
  .cobertura-destacada-texto .subtitulo { margin-left: auto; margin-right: auto; }
}
.cobertura-flecha svg { width: 42px; height: 26px; }
/* El pie es un pie de foto, no un titular: va discreto bajo la fila, con un
   filete corto que lo ata a las piezas de arriba en vez de flotar suelto. */
.cobertura-info { margin-top: 1.4rem; text-align: center; position: relative; padding-top: 1.1rem; }
.cobertura-info::before {
  content: '';
  position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  width: 52px; height: 1px;
  background: linear-gradient(90deg, transparent, var(--borde-fuerte), transparent);
}
.cobertura-nombre { font-size: 1.2rem; margin: 0 0 .3rem; letter-spacing: -.01em; }
.cobertura-nombre a { color: var(--tinta); }
.cobertura-nombre a:hover { color: var(--terracota-texto); }
.cobertura-texto {
  font-family: var(--serif); font-size: 1rem; line-height: 1.5;
  color: var(--tinta-suave); margin: 0 auto; max-width: 46ch;
}
/* El video es la TERCERA pieza de la fila: antes → después → en movimiento.
   Toma la misma altura que las fotos para que la fila se lea de corrido.
   Antes iba debajo y del ancho de la sección: obligaba a bajar la vista para
   relacionarlo con la comparación y competía con las fotos en vez de apoyarlas. */
.cobertura-lado-video { position: relative; display: flex; }
/* `object-fit: cover` para que LLENE el marco como las fotos: sin esto el video
   vertical deja franjas negras arriba y abajo y la tercera pieza de la fila se
   ve rota al lado de las otras dos. El ancho se fija con la misma proporción
   9:16 de las fotos, así los tres bloques quedan del mismo porte. */
.cobertura-video {
  display: block;
  height: clamp(300px, 44vh, 500px);
  width: calc(clamp(300px, 44vh, 500px) * 9 / 16);
  max-width: 42vw;
  background: var(--tinta); box-shadow: var(--elev-2);
  object-fit: cover;
}
@media (max-width: 620px) {
  .cobertura-video { height: clamp(230px, 34vh, 320px); max-width: 26vw; }
}
.coberturas-ficha { margin-bottom: 2rem; }
.coberturas-ficha .cobertura-par { max-width: 720px; margin: 0 auto; }
/* Etiqueta de cobertura en la tarjeta de la grilla (las que no tienen foto del
   antes, que igual son coberturas). */
.tarjeta-etiqueta {
  display: inline-block; margin-top: .3rem; font-family: var(--sans); font-size: .6rem;
  font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  color: var(--terracota-texto); border: 1px solid var(--borde-fuerte);
  border-radius: 999px; padding: .1rem .5rem;
}

/* ---------------------------------------------------------------- formularios */
.form-caja {
  background: var(--papel-claro); border: 1px solid var(--borde);
  box-shadow: var(--sombra); padding: 2rem;
}
.form-fila { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr); gap: 1rem; }
label { display: block; font-family: var(--sans); font-size: .76rem; font-weight: 600;
  letter-spacing: .06em; margin-bottom: .35rem; color: var(--tinta-suave); }
.campo {
  width: 100%; padding: .75rem .9rem; font-family: var(--sans); font-size: .92rem;
  background: rgba(255, 255, 255, .55); border: 1px solid var(--borde);
  border-radius: var(--radio); color: var(--tinta);
}
.campo:focus-visible { outline: 3px solid var(--terracota-oscuro); outline-offset: 1px; }
.campo:focus { border-color: var(--terracota-oscuro); }
.grupo { margin-bottom: 1.1rem; }
.ayuda { font-family: var(--sans); font-size: .72rem; color: var(--tinta-suave); margin-top: .3rem; }
.errores, .errorlist {
  color: var(--terracota-oscuro); font-family: var(--sans); font-size: .78rem;
  list-style: none; margin: .3rem 0 0; padding: 0;
}
.obligatorio { color: var(--terracota-oscuro); }
.label-inline { display: flex; align-items: center; gap: .5rem; cursor: pointer; }
/* El "¿Lo quieres con color?" quedaba con la casilla pegada al borde izquierdo y
   el texto tirado al derecho, partido en dos líneas. Causa: el formulario le
   pone la clase `.campo` a TODOS los campos, incluida la casilla, y `.campo`
   lleva `width: 100%`. Una casilla no se estira. Estaba anotado como pendiente
   desde el 30-07-2026. */
.label-inline input[type="checkbox"] { width: auto; flex: 0 0 auto; margin: 0; }
.campos-archivo { border: 1px solid var(--borde); border-radius: var(--radio); padding: 1rem 1.1rem; }
.campos-archivo legend {
  font-family: var(--sans); font-size: .76rem; font-weight: 600;
  letter-spacing: .06em; color: var(--tinta-suave); padding: 0 .4rem;
}
.campos-archivo input[type=file] { margin-bottom: .8rem; font-family: var(--sans); font-size: .82rem; }
.campos-archivo label { margin-top: .5rem; }
.campo[aria-invalid="true"] { border-color: var(--terracota-oscuro); border-width: 2px; }
/* Estrellas: el glifo se oculta a los lectores de pantalla y el puntaje se
   anuncia en texto ("5 de 5 estrellas"), si no se lee "estrella" cinco veces. */
.estrellas { color: var(--terracota-texto); letter-spacing: .2em; }

.aviso {
  font-family: var(--sans); font-size: .8rem; padding: .9rem 1.1rem; border-radius: var(--radio);
  border: 1px solid var(--borde); background: rgba(255, 255, 255, .5); margin-bottom: 1.2rem;
}
.aviso-ok { border-color: #4d7c3a; color: #365c26; }
.aviso-error { border-color: var(--terracota); color: var(--terracota-oscuro); }

/* nota de "esto no es una reserva" */
.nota-reserva {
  font-family: var(--sans); font-size: .78rem; color: var(--tinta-suave);
  display: flex; gap: .5rem; align-items: flex-start; margin-top: .8rem;
}

/* ---------------------------------------------------------------- datos */
.dato { display: flex; gap: .9rem; align-items: flex-start; padding: 1rem 0; border-bottom: 1px solid var(--borde); }
.dato:last-child { border-bottom: 0; }
.dato .etiqueta { font-family: var(--sans); font-size: .72rem; letter-spacing: .14em;
  text-transform: uppercase; color: var(--terracota-texto); font-weight: 600; }

/* ---------------------------------------------------------------- footer */
.footer { border-top: 1px solid var(--borde); background: rgba(223, 208, 176, .45); padding: 2.5rem 0 1.2rem; }
/* Cuatro columnas: sello, contacto, horarios y el mapa a la derecha (como en el
   mockup). El iframe lo pega Gabriel desde el panel; si está vacío queda el
   marcador de posición, que igual sirve porque linkea a Google Maps con la
   dirección real. */
.footer-grid { display: grid; grid-template-columns: auto minmax(0,1fr) minmax(0,1fr) minmax(0,1.05fr); gap: 2.2rem; align-items: start; }

/* Marco del mapa: mismo tratamiento de "montado sobre papel" que las fotos. */
.mapa-marco {
  padding: .5rem;
  background-color: var(--papel-claro);
  background-image: var(--ruido);
  border: 1px solid var(--borde);
  box-shadow: var(--sombra-montada);
}
.mapa-marco iframe {
  display: block; width: 100%; height: 190px; border: 1px solid var(--borde-fuerte);
  filter: sepia(.18) saturate(.85);
}
.mapa-vacio {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .5rem; min-height: 190px; padding: 1.1rem;
  border: 1px solid var(--borde-fuerte);
  background-color: var(--papel-oscuro);
  background-image:
    var(--ruido),
    repeating-linear-gradient(0deg, rgba(26, 21, 18, 0.05) 0 1px, transparent 1px 16px),
    repeating-linear-gradient(90deg, rgba(26, 21, 18, 0.05) 0 1px, transparent 1px 16px);
  text-align: center;
}
.mapa-vacio svg { width: 26px; height: 26px; color: var(--terracota-texto); }
.mapa-vacio .direccion { font-family: var(--serif); font-style: italic; font-size: .95rem; }
.mapa-vacio a { font-family: var(--sans); font-size: .74rem; letter-spacing: .1em; text-transform: uppercase; }
.footer-legal { text-align: center; font-family: var(--sans); font-size: .72rem;
  color: var(--tinta-suave); margin-top: 2rem; padding-top: 1rem; border-top: 1px solid var(--borde); }

/* La firma del que construyó el sitio. Va DEBAJO del copyright del estudio y
   más apagada: la página es de Púas Tatuajes, la firma es una nota al pie.
   Sin borde propio para que no parezca otra sección. */
.footer-firma {
  text-align: center; font-family: var(--sans); font-size: .68rem;
  letter-spacing: .06em;
  color: var(--tinta-suave); opacity: .78;
  margin-top: .45rem; padding-bottom: .2rem;
}
.footer-firma a { color: var(--terracota-texto); font-weight: 600; }
.footer-firma a:hover { text-decoration: underline; }

/* ---------------------------------------------------------------- whatsapp */
/* Los dos canales, en columna. WhatsApp abajo (es la acción y cae donde está
   el pulgar) e Instagram encima. Cada uno con el color de su marca: son
   afordancias que la gente reconoce de lejos y teñirlas de terracota las
   volvería un ícono que hay que descifrar. */
.flotantes {
  position: fixed; right: 22px; bottom: 22px; z-index: 50;
  display: flex; flex-direction: column; gap: .6rem;
}
.flotante {
  width: 58px; height: 58px; border-radius: 50%;
  display: grid; place-items: center;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .25);
  transition: transform .18s ease, box-shadow .18s ease;
}
.flotante svg { width: 30px; height: 30px; fill: #fff; }
.flotante-wa { background: #25D366; }
/* El degradado de Instagram es RADIAL y nace abajo a la izquierda: amarillo,
   naranjo, magenta y azul. Acá estaba puesto como lineal a 135°, que arranca
   arriba a la izquierda y se come justamente el amarillo y el azul — o sea las
   dos puntas que hacen que el logo se lea como Instagram. Quedaba una mancha
   rosada genérica, más chillona que la marca real y peleada con el papel.
   Los topes son los de la identidad de Meta, no elegidos a ojo. */
.flotante-ig {
  background: radial-gradient(circle at 30% 107%,
    #FDF497 0%, #FDF497 5%, #FD5949 45%, #D6249F 60%, #285AEB 90%);
}
.flotante:hover { transform: translateY(-2px); box-shadow: 0 10px 26px rgba(0, 0, 0, .3); }
/* Ojo: antes esta regla decía `.whatsapp-flotante`, una clase que NO EXISTE en
   el HTML (la real es `.wa-flotante`), así que el botón flotante era el único
   elemento del sitio que no respondía al presionar. Se detectó al agregar el
   de Instagram, buscando la clase en la plantilla. */
.flotante:active { transform: scale(.94); transition: transform 100ms ease-out; }
@media (max-width: 620px) {
  .flotantes { right: 14px; bottom: 14px; gap: .5rem; }
  .flotante { width: 52px; height: 52px; }
  .flotante svg { width: 27px; height: 27px; }
}
.banda-cta {
  position: relative; isolation: isolate;
  background: var(--terracota); color: #fff; padding: 1.9rem 0; margin: 3rem 0 0;
  border-top: 1px solid rgba(255, 255, 255, 0.22);
  border-bottom: 1px solid rgba(255, 255, 255, 0.22);
}
/* Ornamentos tenues de fondo, como en el mockup: la greca blanca repetida a
   muy baja opacidad más un filete interior. z-index negativo para quedar
   detrás del texto sin taparle el clic al botón. */
.banda-cta::before {
  content: '';
  position: absolute; inset: 0; z-index: -1;
  background: var(--filigrana-clara) repeat center / 180px 80px;
  opacity: .22;
}
.banda-cta::after {
  content: '';
  position: absolute; inset: 8px; z-index: -1;
  border: 1px solid rgba(255, 255, 255, 0.30);
  pointer-events: none;
}
.banda-cta .contenedor { display: flex; align-items: center; justify-content: space-between; gap: 1.5rem; flex-wrap: wrap; }
.banda-cta h3 { color: #fff; margin: 0; }
.banda-cta p { margin: 0; font-family: var(--sans); font-size: .85rem; opacity: .9; }
.banda-cta .btn { background: var(--papel-claro); color: var(--terracota-oscuro); }
.banda-cta .btn:hover { background: #fff; }

/* ---------------------------------------------------------------- responsive */
@media (max-width: 900px) {
  .hero, .grilla-4, .grilla-3, .grilla-2, .form-fila, .footer-grid, .ficha { grid-template-columns: minmax(0,1fr); }
  .grilla-4 { grid-template-columns: minmax(0,1fr) minmax(0,1fr); }
  .nav { display: none; }
  /* `z-index` EXPLÍCITO: el menú abierto cae justo encima de la franja
     ornamental que va bajo el navbar, y sin esto la franja le gana el hit-test.
     El menú se abría de verdad (269 px de alto, visible) pero los enlaces no se
     podían tocar: el dedo le pegaba a la franja. Diego lo reportó como "el
     botón no funciona" y la altura del nav decía que sí — se cazó con
     `elementFromPoint`, no mirando.
     `isolation: isolate` en la cabecera para que este z-index se resuelva
     DENTRO de ella y no dependa de quién más pinte encima más adelante. */
  .nav.abierto { display: flex; flex-direction: column; position: absolute; top: 100%; left: 0;
    right: 0; z-index: 5; background: var(--papel-claro); padding: 1.2rem;
    border-bottom: 1px solid var(--borde); box-shadow: var(--elev-3); }
  .menu-btn { margin-left: auto; background: transparent; border: 1px solid var(--tinta);
    border-radius: var(--radio); padding: .5rem .8rem; font-family: var(--sans); font-size: .74rem;
    letter-spacing: .1em; text-transform: uppercase; cursor: pointer; }
  body { font-size: 17px; }
  /* El marco se acerca al borde y las esquinas se achican: en 375 px de ancho
     el contenido (.contenedor, 92vw) deja 4vw ≈ 15 px de aire a cada lado, así
     que con el filete a 7 px sigue respirando y no se corta nada. */
  .marco-pagina::before { inset: 7px; }
  .marco-pagina::after { inset: 11px; }
  .marco-esquinas-arriba::before, .marco-esquinas-arriba::after,
  .marco-esquinas-abajo::before, .marco-esquinas-abajo::after { width: 20px; height: 20px; }
  .marco-esquinas-arriba::before { top: 7px; left: 7px; }
  .marco-esquinas-arriba::after { top: 7px; right: 7px; }
  .marco-esquinas-abajo::before { bottom: 7px; left: 7px; }
  .marco-esquinas-abajo::after { bottom: 7px; right: 7px; }
  /* Los ítems de la franja se apilan: el separador vertical dejaría de tener
     sentido (quedaría cruzado en el aire), así que se apaga. */
  .franja { gap: 1.1rem; flex-direction: column; align-items: center; }
  .franja-item { min-width: 210px; justify-content: center; }
  .franja-item + .franja-item::before { display: none; }
  .lightbox { gap: .3rem; padding: 3.5rem .5rem 1rem; }
  .lightbox-nav { width: 40px; height: 40px; font-size: 1.6rem; }
  .lightbox-img { max-height: 62vh; }
  /* Antes/después apilado: las dos fotos siguen visibles al mismo tiempo (una
     arriba de la otra) y la flecha gira para seguir apuntando al resultado. */
  .cobertura-par { grid-template-columns: minmax(0,1fr); gap: .7rem; }
  .cobertura-flecha svg { width: 26px; height: 42px; transform: rotate(90deg); }
  .cobertura-item { padding: .9rem; }
  /* En pantalla angosta la fila de filtros puede quedar de 3 líneas: se
     compacta para que la grilla no se vaya tan abajo. */
  .filtros-caja { padding: .9rem .7rem; }
  .filtro { padding: .45rem .7rem; font-size: .7rem; letter-spacing: .06em; }
}
@media (min-width: 901px) { .menu-btn { display: none; } }

/* ============================================================ reseñas de Google
   Las tarjetas tienen alto fijo y el texto recortado a propósito: antes una
   reseña larga estiraba toda la fila y las cortas quedaban con un hueco enorme. */
.rg{ display:grid; grid-template-columns: 220px minmax(0,1fr); gap:2rem; align-items:start; }

.rg-resumen{ text-align:center; padding:1.2rem .6rem; }
.rg-excelente{ font-family:var(--sans); font-weight:700; font-size:1.15rem;
  text-transform:uppercase; letter-spacing:.06em; color:var(--tinta); }
.rg-estrellas-grandes{ color:#F5A623; font-size:1.7rem; letter-spacing:.12em; line-height:1.4; }
.rg-base{ font-family:var(--sans); font-size:.82rem; color:var(--tinta-suave); }
.rg-google{ font-family:var(--sans); font-weight:700; font-size:1.5rem; margin-top:.5rem; letter-spacing:-.02em; }

.rg-tarjetas{ display:grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap:1rem; }
.rg-tarjeta{ display:flex; flex-direction:column; background:var(--papel-claro);
  border:1px solid var(--borde); border-radius:10px; padding:1.1rem; box-shadow:var(--sombra);
  min-height:250px; }

.rg-cabecera{ display:flex; align-items:center; gap:.65rem; }
.rg-avatar{ width:42px; height:42px; border-radius:50%; object-fit:cover; flex:0 0 42px; }
.rg-avatar-inicial{ display:grid; place-items:center; background:var(--terracota); color:#fff;
  font-family:var(--sans); font-weight:600; font-size:1.05rem; }
.rg-quien{ min-width:0; }
.rg-nombre{ font-family:var(--sans); font-weight:600; font-size:.9rem; color:var(--tinta);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.rg-fecha{ font-family:var(--sans); font-size:.75rem; color:var(--tinta-suave); }
.rg-g{ margin-left:auto; font-family:var(--sans); font-weight:700; font-size:1.05rem; color:#4285F4; }

.rg-estrellas{ color:#F5A623; letter-spacing:.08em; margin:.6rem 0 .4rem; font-size:1rem; }
.rg-estrellas .rg-apagada{ color:var(--papel-oscuro); }

.rg-texto{ font-size:.95rem; line-height:1.5; margin:0; color:var(--tinta); }
.rg-recortado{ display:-webkit-box; -webkit-line-clamp:5; line-clamp:5; -webkit-box-orient:vertical; overflow:hidden; }

.rg-mas{ align-self:flex-start; margin-top:.4rem; background:none; border:0; padding:0;
  font-family:var(--sans); font-size:.8rem; font-weight:600; color:var(--terracota);
  cursor:pointer; text-decoration:underline; }
.rg-mas:hover{ color:var(--terracota-oscuro); }

.rg-enlace{ margin-top:auto; padding-top:.8rem; font-family:var(--sans); font-size:.75rem;
  color:var(--tinta-suave); text-decoration:none; }
.rg-enlace:hover{ color:var(--terracota); }

@media (max-width:900px){
  .rg{ grid-template-columns: minmax(0,1fr); gap:1.2rem; }
  .rg-tarjetas{ grid-template-columns: minmax(0,1fr); }
  .rg-tarjeta{ min-height:0; }
}


/* Video de una pieza que NO es cobertura: antes no se mostraba en ninguna parte.

   OJO con heredar de .cobertura-video: ese tiene ALTO FIJO y `object-fit: cover`,
   que estan bien en la grilla de coberturas —tres videos uno al lado del otro
   tienen que verse parejos— pero aca hay UN solo video y no hay con que
   emparejarlo. Un video vertical dentro de una caja de 760 x 500 con `cover`
   queda recortado arriba y abajo: es lo que reporto Gabriel el 21-08-2026 en
   /trabajos/samurai-bajo-la-luna/ ("se ve como cortado, no se ve vertical").

   Aca el video manda: se deshacen las tres propiedades y se deja que conserve
   su proporcion, sea vertical u horizontal, sin tener que saber cual es. */
.ficha-video { max-width: 760px; margin: 0 auto 2rem; text-align: center; }
.ficha-video .cobertura-video {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 76vh;      /* que un vertical no empuje la pagina entera */
  object-fit: contain;   /* nada de recortar: se ve completo */
  border-radius: 10px;
  display: inline-block; /* centrado por el text-align del contenedor */
}


/* Formulario de solicitud + barra lateral. En clase y no inline, para que la
   media query pueda apilarlas: inline no hay forma de deshacerlo. */
.grilla-solicitud { grid-template-columns: minmax(0,1.6fr) minmax(0,1fr); gap: 2rem; }
@media (max-width: 820px) {
  .grilla-solicitud { grid-template-columns: minmax(0,1fr); gap: 1.5rem; }
}

/* ====================================================== CURSOR PUNTA DE LANZA
   El puntero es una PUNTA DE LANZA POLINÉSICA, dibujada a partir de la lámina
   "Puntas de Lanza" que hizo Gabriel (la misma que está en Significados).

   Antes fue la calavera del sello. La cambió él en la revisión del 3 de agosto:
   «yo le pondría una flecha no más... como una flecha polinésica, esas puntas
   de lanza». Tiene razón funcional además de estética: una flecha se entiende
   como puntero y sabe hacia dónde apunta; una calavera es una mancha simétrica
   y uno no sabe qué píxel está tocando.

   Va girada -38° para que la punta mire arriba-izquierda, como cualquier
   puntero, y el punto activo es LA PUNTA (1,1), no el centro ni una esquina.
   Lleva relleno oscuro con filete crema para recortarse igual sobre el papel,
   sobre las fotos y sobre el terracota.

   Cuatro cuidados, porque un cursor propio es de las cosas que más fácil
   arruinan un sitio:
   1. SOLO en punteros finos (mouse). En un teléfono no hay cursor, y en un
      trackpad grueso o un lápiz esto no aplica.
   2. SIEMPRE con el cursor nativo detrás de la coma (auto / pointer).
      Si el navegador rechaza la imagen —Chrome ignora cursores sobre 128px y
      algunos bloquean data-uri— queda el de siempre, no un puntero invisible.
   3. Los CAMPOS DE TEXTO conservan su cursor de texto. Con la calavera encima
      no se ve dónde va a caer el punto de inserción y escribir se vuelve
      adivinanza.
   4. Va en html ademas de body: el body no siempre llega hasta abajo de la
      ventana y quedaria una franja con el cursor del sistema.
   La calavera sigue viva en el icono de la pestaña, que es donde una silueta
   simétrica sí funciona. */
@media (hover: hover) and (pointer: fine) {
  html, body {
    cursor: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAeCAYAAAA2Lt7lAAAFdklEQVR42q2We2xTdRTHz717dG33aDtWusEmr4VHnIBkECAL4jSw+ECDEAVlkqggGoQYDJM/tiARiRJRMIYsBlABM5wIMmQLsMFgPBx7j3Yd3bqu3dbHuttu7drex9c/uiFEkY1x/rl/3Pzu557zPef7O9TvNLYFPeZKrke/tqjoQCwNBcrLIwEwNNYYcBoHeW8HIDkB0WUMcKY8/a2ylLsgIGJMAAS7DRXnTogrcrKFyvO/AfAAotM92GcqqDxzVD0EYR85GwSsZYa6CsgjWSE2Jkp8LmsBX1J8OAwSHO3OzoY3x5RNkDN9GXCbMGvaJCFj+lSM1yRAHslKLy9fytdWnQPgR9BjPnn70p/JYUh55KgAblvTGggOLFu6WExN1iJ/+0dIS9ZCER0JrTpB3LHtQwGCAwj2dHQZby4ZboARA5prKtIRsvt37tgKIpLeWbcaxw/vR/I4NXSJKiijI/Hs4ky+reUmILh4e0fNuqFyjRjCINRTc7HkOOLlMlGllOPkL4UoPnYQukQVJmgToY5VYEpqsnjl4ikJGIC9vWbTqCC81/y1z22SZkx9go+Xy7Aocw46W//C8cMHkKpLQvI4NbSaBOg0CVLZmWMC4IPTUrNmxMJ3t9c+A3jw9pqVYoIiBupYOT7P3waXtQlFP32PyRN10CWqoEtUQauOl/4oPiKG/PZQt6V2PhFRUVHRAyEsAOZcRd11CvRb3lr7GktEkkwmo6PHi6m11UTzM+fSnt35JJNFU0REBBHDMI11DRTBSFHKGMVpjmtQr1q1SnrgnAzX0edsLYDgwqLMOXySKg7xChm2bFoPR0c92pqrsGBuBlRKOWamT4Lb1iwiZEefrakEqI4qD3fVAwEsEVHjzUupCDl8R3/YJymjI6WJ48chTZeEzRtzUXhgD2bPSsd4TQI08Uq88PwS0dPbLiHkqLM0VU17qBbDL/1O47fgnVg4bzaviVciLVmLeLkM6lgFUpI0SEnSYII2EUSEhfMyRKu5AQGvxWJrr55x78/ep0H4UQAATKfVtUcUhP5dn+WxwWAIHq+XFAo5xcYqiWEYYlmWWJal7/bupA3v5rJWczvJ4uJSNWpNVb/blBFm/BtyXxactekDwIe8j9/njx3aL61+NQcJihgkj1MjXh4NXaIKxvrLEuBHkGvrHLC3GIRBW+eAw5AT/k7RQ0oFMF57ywWITgAu3K4ph0opR052Fkp+Pyql6pKQOfdJ0dvbjn5Xa6XFUiU/e/Yb2cicdciWnR36FL/7Tk+frckDuEKbN+RKBXlbAABnfj0kMUTYuP4NAQigr6v526GzUSOFMEREXEfjVK6nZYrgNZ/utTWj/nqpOOAy+iA68NWu7SIRoXD/bh4IoOtOde6oTPDeoXFb6jNC3o4AwPGebsMurlu/FxjE6hXLeVlkhHTjcomAkMvfabj2FBER/meq74fk57NAdRQREdd9ex8ADLhNLxIR4+fMjR6nCTOnTRbSJ6eKru4WBPstBr3+Styobj8ADACG4xrUAW/7p5ylScMwDLXVX5iOoMNTc61UVMiipVdysgXAi36H4cQjXUr/1c5dpmsrAR+OHNzLExF27djKAyE4zbWfjBoylMndNWbYv9zWxi+AIDa/t44nIqmk+AgPsU+yGq5mj2kjCQPDBjfQ23peDDiQteBpIUmjEk36GxLv7+7R3ypLYZgxrFXDYt6pu6rl/V1Ws7Ea4xPV4uLMOYIUciHAtV38x4rGqIet5UoWBLdYeupnnoik3NdXCFLQAY9dXzjmzXBYD0dH7RZAQMH2zfzKl5YJCNnhcxp76HHEMMTraPkxvII6EfSaS922prTHBWAAsDZbtcLvaq339d45gvx8lojob5S3x2Xg7+IQAAAAAElFTkSuQmCC") 1 1, auto;
  }
  /* Las clases van nombradas una por una a propósito: varios componentes ya
     traían su propio `cursor: pointer` o `zoom-in`, y una regla de clase le
     gana a `a` o a `button`. Sin esta lista, la lanza se veía en el fondo de
     la página pero desaparecía justo encima de los botones y las fotos.
     Las fotos pierden el `zoom-in` que tenían: era información (avisa que la
     foto se agranda), pero se decidió que la marca mande y esa señal queda en
     el hover, que ya oscurece la foto y muestra su pie. */
  a, button, summary, label, select,
  [role="button"], [data-ampliar],
  .btn, .menu-btn, .label-inline, .rg-mas,
  .tarjeta-foto-btn, .ficha-foto, .cobertura-foto, .simbolo-figura,
  .lightbox-nav, .lightbox-cerrar,
  input[type="submit"], input[type="button"], input[type="checkbox"], input[type="radio"] {
    cursor: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAAAAiCAYAAACuoaIwAAAG+UlEQVR42rVXa3BUZxl+v7Nnd5sbZDdkEwmmhFsIQqmIDglgxSli62CtU8FbvYAFpB3q1EsHRpvAaK2WdtAfKDK9jCPTlnIJUSgM1lBqQUIuJCHJZiHZbLLJZpNN9uyePXt2z3fO9/gj7AxqaQmm7//3e77ved73ed+P1BFvpx7tvZwIeTcrgTYX3QgANqBaoqkMddRnCC0IYByGFgzoo75nlUD73P8EBZsSsKTi96m9TVbrvt1m3HcJQBKGPpRMRnwHlUDbnJtB/28wTfGfM8JdOLFisVW7YrFo2PkED18+C0CFkRyM6aPdu0NXzuTcBHjHr5REOu21u900bf5ckGmygb+dki9ufxINO5821b6+aXfNKH2moGxhQ2yg9QHGmAWA7lRLCYbRTLKDsmbOZLAsKr5vNTHZxoInT8vvbXkc7b/fa9ps0qJpJSWntGHv8zU1NYyx3QI4bJs8mGm0cSOF6eULJK4mCJZFc765kWwOO5FlsesvvSLXb9oiwk0tVnbR3T/ZuePbZ8NXLxUztsGarI5Sqk+9ahk86FmymJxulxi5cJGcBQW0YPtWMvUU2fOnU6KnV7q04ymb79ArptNd/PnpJYXvRvxNFTdovW1AqWjNmgQ4b3SVzyfHjALBJIl6D71GRauqqHzbD8hMaGTLyiLGGHX8Zq/c+sJvTWd+/rxcV8G5eF/zognA26NUIiIydL2e5RWSq6KCiDHSh0IUOHKcSr+ynhZs2URWKkVERA5XPvW8+he5sXqP6czL9Tjy3W+ND14tvUGpdFtglIy/ZaTjZtHqKhmWgC07m4bOvk0xbzeVfHEdlW/fSoKbZBkGOdwu6j9WKzf98lnTmZNT6nQ46/r7L2QxiYkPa34JqJby51dd55rWPHNlFbKKPIKEIEOJUfDUabJSKfKsqqKFT2wjSZYJpkkOl4sCbx6Trx09ZmbPKF6a73C93Hi50f5hPSgR1UhERELXX3XMKGGe+1YRT2hkz8ul8DvvkdrTS+CcPCtXkHvZvWSl02QmElT68ENUsm6tTY+EBJOkBxeWZs9g7INfJxGRRUQUHVde19XR8bKH1ktybg4IIMENChw9TsKyyOZwks3hJAhBkt1Bao+fzGRSZLldEjg/kOtZFAIa7Ywx3BKMMYb6+nr57ntWR81E8iXXJ5ax4s991uLxOMm5uaR0dFHLrmfIu/8AacEgSTYbSU4HKZ2d1PTTnZI6PCKyPZ4d8cH2zYwt50C9fCswNuF51RJRDUYDTcV57kKfPhDMfvexHzJGxJhsI5E2yEqlyeZ0ELPbiQCCEGSMR2laRTmWP/cryi+bzbRxZeu0mRV/AiAxxsT7ViNjuwURSZ7Zy0NGLLbPtWiZVLbxEcuIRslMaEQA2afnEbPbSbLZSHCT8uaUUeXB/bRg8/cYUjrjhkF5he4D2mj31gnt/rf3bn6yACANNTX9Ws4e2lj+3UfnK13dYtYDX5AGT52hSMNlknNyyIjHSRgGOQvcVLRqJVnpNIHzCNd1m/Mup12A7p047msf3HSZ26ihrjWmPght1JdO87AZvnJO1FUuQV3lElz9w3P45+PfweF5xeg48LwprCiU/rYjihJwQRuYNSlnrq+fEFgNde0BVBjjPeA8jMbdP8bpB1fDsCKIBdutM+vX4Ng9czF4vs4EFMT6r2ya9JAFwDLWkxi99jt1xPsjLea/pvY0itZ9e6xktBfgYYQunbGOf6ocp9ZViVig1UonBrnS3/KZmxm6o4iFujbBDCMR7hKJke5YfLDjBKCg+9B+6/DcYpzf+g2L6yFokeu9SqDNBVRL1dWTHLBAvQw02gFIari7AXzUSoz6ugGfMxH21gNxNPziSfON2YVofbGGAxrUoY4TmdxJrxAZDeJh7ypARyLiqyUi0gZaZ+lK37A+7hdvf/1L1pGKj8N/8hAHklAGWnfdyJUnTWPG79RQx4Z4xLcos4MoPc3381QYY50XeN3KpeKvqz8pxrz/4jwVhhJoXnvHW9l/G2zm1uOB5l2Ajt66P/M3F87CP771ZUtX+oQe9Ycj/S0ljBHdzqx7X0oziSBiGR9UQ521gIYre3/O35hdiMaap0wgDnW46zwAaUoW3erqagmAFPW35GtjPT08GcI7j220Ds/7GK69/kcO6FCCbS/esX63ch0l0LQ8rQ2lY31XzJNrK0XtpysQbvo7B2KIDrQ+MmX/hQydykDbFkBF8FwtP7pkDs4+fL+lDXdbeqxPiQ+1V0wh4ARN8cH2lwEdnQdf4K+V5OPiz7ZZFh+BOuz1yzR1YQGHbX19udttY8FlFd9/dGl6LGJ6KitlSZaJJGqZ0u9XplJjIx3zUzH/GMQYzHTITIR9T9NHEbgxNZRQxwauhf3RgfavZgrp3z5tZr9wDnSaAAAAAElFTkSuQmCC") 1 1, pointer;
  }
  /* Escribir necesita ver el cursor de texto. */
  input[type="text"], input[type="email"], input[type="tel"], input[type="url"],
  input[type="search"], input[type="number"], input[type="date"], input[type="time"],
  input[type="password"], textarea {
    cursor: text;
  }
  button:disabled, [aria-disabled="true"] { cursor: not-allowed; }
}

/* ======================================================== MOVIMIENTO Y COLOR
   La página no tenía UNA sola animación (cero @keyframes en todo el archivo) y
   el color vivía casi entero en el botón: papel crema de arriba abajo con dos
   bloques de tinta. Todo aparecía de golpe y pesaba igual.

   Regla que ordena esta tanda: el movimiento ACOMPAÑA a la lectura, no la
   interrumpe. Nada parpadea, nada rebota en loop, nada se mueve mientras se
   lee. Todo entra una vez, hacia arriba y desde la transparencia, que es como
   se comporta el papel al pasar la hoja.

   El color nuevo NO inventa paleta: es el mismo terracota de la identidad,
   usado en más superficies y con menos miedo. */

/* --------------------------------------------------------------- 1. entrada
   El contenido entra al aparecer en pantalla.

   LO IMPORTANTE ES QUIÉN ESCONDE: esconder en CSS y revelar por JS deja la
   página EN BLANCO si el JS no corre (bloqueado, error, red a medias). Por eso
   el estado oculto cuelga de `html.js-revelar`, una clase que pone el propio
   JS: sin JS nunca se aplica y todo se ve, que es el comportamiento de hoy. */
html.js-revelar .revelar {
  opacity: 0;
  transform: translateY(20px);
}
html.js-revelar .revelar.visible {
  opacity: 1;
  transform: none;
  /* El retraso lo escribe el JS por elemento (`--retraso`) para escalonar los
     hijos de una grilla. Por defecto 0s: un elemento suelto no espera nada. */
  transition: opacity .75s cubic-bezier(.22, 1, .36, 1) var(--retraso, 0s),
              transform .75s cubic-bezier(.22, 1, .36, 1) var(--retraso, 0s);
}

/* ------------------------------------------------------------------ 2. hero
   Dos movimientos: la foto deriva muy lento hacia adelante y el texto sube
   escalonado. La deriva es de ida y NO alterna en bucle: una foto que respira
   para siempre marea y compite con el texto que hay encima. */
@keyframes puas-deriva {
  from { transform: scale(1.001); }
  to   { transform: scale(1.085); }
}
@keyframes puas-subir {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: none; }
}
.hero-sangre-fondo img {
  animation: puas-deriva 26s cubic-bezier(.22, .61, .36, 1) forwards;
  will-change: transform;
}
.hero-sangre-texto > * {
  animation: puas-subir .85s cubic-bezier(.22, 1, .36, 1) both;
}
.hero-sangre-texto > .filigrana   { animation-delay: .10s; }
.hero-sangre-texto > h1           { animation-delay: .18s; }
.hero-sangre-datos                { animation-delay: .30s; }
.hero-sangre-bajada               { animation-delay: .40s; }
.hero-sangre-cta                  { animation-delay: .50s; }

/* El apagado global de `prefers-reduced-motion` (arriba) deja las animaciones
   en .01ms, así que el texto queda visible al tiro —correcto— pero la foto
   saltaría de una a su tamaño final y quedaría recortada sin motivo. Acá se
   cancela del todo. */
@media (prefers-reduced-motion: reduce) {
  .hero-sangre-fondo img { animation: none !important; transform: none !important; }
}

/* ------------------------------------------------------------- 3. la franja
   Era una tira crema plana entre dos líneas. Ahora es una banda cálida con el
   terracota difuminado en las puntas: separa el hero del resto con color en
   vez de con una línea. Los íconos se colorean al pasar el mouse por su ítem. */
.franja {
  background:
    radial-gradient(120% 180% at 0% 50%, rgba(178, 58, 46, .13), transparent 62%),
    radial-gradient(120% 180% at 100% 50%, rgba(178, 58, 46, .13), transparent 62%),
    linear-gradient(180deg, rgba(244, 235, 218, .85), rgba(235, 223, 196, .5));
}
.franja-item .franja-icono {
  transition: transform .45s cubic-bezier(.22, 1, .36, 1);
}
/* El ícono se mueve pero NO cambia de color. El primer intento lo aclaraba a
   `--terracota` en el hover y el smoke test lo cazó: ese tono da 4,49:1 sobre el
   papel y AA pide 4,5, por eso existe `--terracota-texto`. La regla del proyecto
   es que el terracota claro solo sea FONDO, y un ícono de línea se comporta
   como texto. Se queda con el movimiento, que es lo que aporta. */
@media (hover: hover) and (pointer: fine) {
  .franja-item:hover .franja-icono { transform: rotate(-8deg) scale(1.12); }
}

/* -------------------------------------------------------- 4. bloques oscuros
   La tinta plana se leía como un rectángulo café. Un resplandor terracota muy
   tenue arriba le da profundidad y ata el bloque al resto de la paleta.
   Va en un pseudo-elemento con z-index 0 y el contenido queda encima: pintarlo
   como fondo del propio bloque taparía el `--ruido` que ya tiene. */

/* ------------------------------------------------------------- 5. la banda
   El rojo era plano de lado a lado. Ahora tiene un degradado diagonal entre el
   terracota y su versión oscura: la banda gana volumen sin cambiar de color.
   (Se descartó cruzarla con un brillo animado: sus dos pseudo-elementos ya
   están ocupados por la greca y el filete interior, y un destello en bucle
   sobre el llamado a la acción se lee como cartel de casino.) */
.banda-cta {
  background:
    linear-gradient(115deg, var(--terracota-oscuro) 0%, var(--terracota) 45%,
                    #AE3446 72%, var(--terracota-oscuro) 100%);
}

/* ------------------------------------------------------- 6. micro-reacciones
   Lo que se puede tocar avisa que se puede tocar. */
.btn {
  transition: background .25s ease, color .25s ease,
              transform .18s cubic-bezier(.22, 1, .36, 1), box-shadow .25s ease;
}
.btn:hover { transform: translateY(-2px); }

/* Los enlaces del menú ganan un filete que crece desde el centro. Se dibuja en
   un pseudo-elemento y no con `border-bottom` para poder animar el ancho sin
   mover el texto de lugar. */
.nav a { position: relative; }
.nav a::after {
  content: '';
  position: absolute; left: 50%; bottom: -.35em;
  width: 0; height: 1.5px;
  background: var(--terracota);
  transform: translateX(-50%);
  transition: width .3s cubic-bezier(.22, 1, .36, 1);
}
.nav a:hover::after,
.nav a[aria-current="page"]::after { width: 100%; }
.nav a.btn::after { display: none; }   /* el botón ya es un botón */

/* La flecha del antes/después se desplaza al pasar por la comparación: señala
   la dirección de la lectura sin texto. */
.cobertura-par .cobertura-flecha { transition: transform .5s cubic-bezier(.22, 1, .36, 1); }
@media (hover: hover) and (pointer: fine) {
  .cobertura-item:hover .cobertura-flecha { transform: translateX(6px); }
}

/* Las reseñas se levantan apenas y muestran su filete terracota. */
.rg-tarjeta {
  position: relative;
  transition: transform .3s cubic-bezier(.22, 1, .36, 1), box-shadow .3s ease;
}
.rg-tarjeta::before {
  content: '';
  position: absolute; left: 0; right: 0; top: 0; height: 3px;
  background: linear-gradient(90deg, var(--terracota), rgba(178, 58, 46, .25));
  transform: scaleX(0); transform-origin: left;
  transition: transform .45s cubic-bezier(.22, 1, .36, 1);
}
@media (hover: hover) and (pointer: fine) {
  .rg-tarjeta:hover { transform: translateY(-4px); box-shadow: var(--elev-2-hover); }
  .rg-tarjeta:hover::before { transform: scaleX(1); }
}

/* ------------------------------------------ 7. el desborde del antes/después
   A 412 px la página se iba 1 px a la derecha. Medido, no supuesto: la fila
   `.cobertura-par` mide 396,9 px dentro de un contenedor de 379.

   Eran DOS reglas perdiendo por orden de archivo, las dos escritas con la
   intención correcta:
   · `.cobertura-flecha { width: 26px }` vive en la media query de 620px, pero
     la regla BASE que la deja en 42px está escrita MÁS ABAJO en el archivo.
     Misma especificidad, gana la última: el medallón nunca se achicó en el
     teléfono. Medido: 42 px cuando debía tener 26.
   · `.cobertura-par { gap: .35rem }` (620px) queda pisado por un
     `gap: .7rem` de la media query de 900px, que está después y es un resto
     de cuando esto era una grilla apilada.

   Van acá, al final del archivo, porque es el único lugar donde ninguna regla
   posterior las puede volver a pisar. Las cuentas, para el que venga después:
   3 fotos de 26vw (321) + medallón 26 + 3 huecos de .35rem (17) = 364 < 379.
   A 320 px, que es la pantalla más angosta que se probó: 250 + 26 + 17 = 293
   contra un contenedor de 294. Entra, pero sin margen: si se agrega una cuarta
   pieza a esta fila, hay que rehacer la cuenta, no apretar el hueco. */
@media (max-width: 620px) {
  .cobertura-par { gap: .35rem; }
  .cobertura-flecha { width: 26px; height: 26px; }
}
/* Y ahora el arreglo de fondo, porque lo de arriba solo tapa un ancho a la vez.
   Las tres piezas de la fila se dimensionan por su ALTO (`height` en clamp) y
   el ancho sale de la proporción de la foto. El alto no sabe nada del ancho del
   contenedor, así que en cada pantalla que se probaba aparecía un desborde
   nuevo: 37 px a 768, 25 a 621, 110 a 1024. Ajustar el vw de turno es perseguir
   el síntoma; el problema es que la fila NO PUEDE ENCOGER.

   `min-width: 0` es la pieza que faltaba: un elemento de flex no se encoge por
   debajo del ancho de su contenido salvo que se le diga, y una foto sí puede
   angostarse. Con la cadena de `max-width: 100%` hacia adentro, la fila se
   ajusta sola a cualquier contenedor. Donde ya entraba, nada cambia — solo
   actúa cuando iba a desbordar. Se probaron 9 anchos, no dos. */
.cobertura-par { max-width: 100%; }
.cobertura-par > .cobertura-lado { min-width: 0; }
.cobertura-foto { max-width: 100%; }
.cobertura-foto img { max-width: 100%; }
.cobertura-video { max-width: 100%; }

/* --------------------------------------------- 8. la grilla en pantalla chica
   `/equipo/` se iba 27 px a la derecha a 320 px. Es ANTERIOR a esta tanda (se
   comprobó cargando la página con JavaScript apagado: el desborde es el mismo),
   pero se nota más ahora que hay tres láminas de significados cargadas.

   La causa: bajo 900 px `.grilla-4` queda en dos columnas de `1fr`, y `1fr` es
   `minmax(auto, 1fr)` — el mínimo es el ancho MÍNIMO DEL CONTENIDO, así que si
   una tarjeta no puede angostarse más, la columna crece y se lleva la grilla
   fuera de la pantalla. Medido: dos columnas de 155 px con 22 de hueco dentro
   de un contenedor de 294.

   Dos arreglos, y los dos hacen falta:
   · Bajo 480 px una sola columna. Dos tarjetas de significado en un teléfono
     angosto no se leen igual.
   · `minmax(0, 1fr)` en el tramo de dos columnas, para que la columna pueda
     angostarse por debajo del mínimo del contenido en vez de empujar. Sin
     esto, cualquier tarjeta futura con una palabra larga repite el problema. */
@media (max-width: 900px) {
  .grilla-4 { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}
@media (max-width: 480px) {
  .grilla-4 { grid-template-columns: minmax(0,1fr); }
}

/* Los logos históricos se enderezan al pasar por encima: hoy son seis marcos
   quietos y son la parte más entretenida de la página. */
.linea-logos figure { transition: transform .4s cubic-bezier(.22, 1, .36, 1); }
@media (hover: hover) and (pointer: fine) {
  .linea-logos figure:hover { transform: translateY(-6px) rotate(-1.5deg); }
}

/* ------------------------------------------- las tarjetas de artista en móvil
   Va al FINAL del archivo por orden de cascada, no por gusto: `.grilla-artistas`
   también lleva `.grilla-3`, y más abajo hay un
   `@media (max-width: 900px) { .grilla-3 { grid-template-columns: minmax(0,1fr) } }` que le ganaba por venir después. Medido: quedaba en 1 columna. Dos por fila y no una: con una sola, cada tarjeta mide 380x475 y las tres suman metro y medio de scroll para ver a un equipo de tres personas.

   26-08-2026: dos columnas FIJAS tenía el mismo problema que .grilla-3 en
   desktop -- con 1 solo invitado (Majo) dejaba una celda vacia al lado.
   auto-fit con columnas acotadas + justify-content resuelve los dos casos
   (1, 2 o 3 invitados) sin repetir la regla por cantidad.

   26-08-2026 (correccion): la primera vez puse el fix de desktop junto a
   `.grilla-artistas { gap: ... }`, cerca del inicio del archivo -- pero
   `.grilla-3` (misma especificidad, un permiso) se declara MAS ABAJO
   (linea ~1005) y le ganaba por orden de cascada, exactamente la misma
   trampa que ya advertia el comentario de arriba. Por eso el de desktop
   TAMBIEN va aca al final, no donde "naturalmente" iria. */
.grilla-artistas { grid-template-columns: repeat(auto-fit, minmax(280px, 380px)); justify-content: center; }
@media (max-width: 900px) {
  .grilla-artistas { grid-template-columns: repeat(auto-fit, minmax(240px, 340px)); justify-content: center; }
}

/* ============================================== ornamentos de página (marca de agua)
   Los dos dibujos de Gabriel flanqueando el título, muy tenues, como si
   estuvieran impresos en el papel. Es el detalle del mockup que pidió replicar.

   CÓMO DESAPARECE EL FONDO BLANCO: los dibujos llegan escaneados, línea negra
   sobre papel blanco (medido: ~100% de píxeles casi blancos). Con
   `mix-blend-mode: multiply` el blanco se vuelve transparente contra el crema y
   solo queda el trazo. Es el mismo truco que ya usa el sello del logo, y evita
   tener que pedirle a Gabriel versiones recortadas en PNG.

   POR QUÉ `position: absolute` Y NO `fixed`: tienen que quedarse arriba, junto
   al título, y pasar de largo al hacer scroll. Fijos convertirían el papel en un
   estampado que sigue al lector.

   Se apagan bajo 1100px: a esa altura invaden la columna de texto y un adorno
   nunca puede pelearle el espacio a lo que hay que leer. */
.ornamentos-pagina {
  position: absolute; inset: 0 0 auto 0;
  height: 0;                       /* no empuja nada: solo ancla a sus hijos */
  pointer-events: none;
  /* SIN `z-index` a propósito. Con `z-index: 0` este contenedor creaba un
     contexto de apilamiento, y `mix-blend-mode` solo mezcla dentro del suyo:
     los dibujos quedaban mezclándose contra un fondo transparente, o sea sin
     mezclarse con el papel. Lo que se veía era el blanco del escaneo al 16%,
     que es MÁS CLARO que el crema: un recuadro pálido alrededor de cada dibujo.
     Se vio en la captura. Que el adorno quede debajo del contenido lo resuelve
     el `z-index: 1` de las secciones, no este. */
}
.ornamento-pagina {
  position: absolute;
  top: clamp(1rem, 3vw, 3.5rem);
  width: clamp(150px, 15vw, 250px);
  height: auto;
  opacity: .16;
  mix-blend-mode: multiply;
  user-select: none;
}
.ornamento-1 { left: clamp(.5rem, 3vw, 4rem); transform: rotate(-8deg); }
.ornamento-2 { right: clamp(.5rem, 3vw, 4rem); transform: rotate(8deg) scaleX(-1); }

/* El contenido va POR ENCIMA del adorno. Sin esto, una marca de agua al 16%
   igual se cuela sobre el texto y lo ensucia. */
main > .seccion,
main > section,
main > div:not(.ornamentos-pagina) { position: relative; z-index: 1; }

@media (max-width: 1100px) {
  /* Bajo este ancho el adorno ya no cabe al lado del texto: se mete debajo. */
  .ornamentos-pagina { display: none; }
}
@media (prefers-reduced-motion: no-preference) {
  .ornamento-pagina { transition: opacity .6s ease; }
}

/* ================================= fondo de ornamentos (toda la página)
   Los dibujos de Gabriel repetidos por TODO el fondo, muy tenues, como el
   estampado de un papel antiguo. Es distinto de `.ornamentos-pagina`: aquellos
   son dos piezas grandes flanqueando el título (el detalle del mockup), este es
   la textura general que pidió después — "que sea en todo el fondo de la web".

   Cubre el documento completo, no la ventana: `position: absolute; inset: 0`
   dentro de `body`, cuyo alto es el del contenido. Se desplaza con el scroll, o
   sea queda IMPRESO en la hoja en vez de pegado a la pantalla, que es lo que
   hace que se lea como papel y no como una calcomanía.

   Las dos URLs llegan como variables desde la plantilla: son archivos de
   `media/` que Gabriel cambia desde el panel, y una hoja de estilos estática no
   puede saber cuáles son.

   La opacidad es MUY baja a propósito (.05). Es un fondo: si se nota, compite
   con las fotos de los tatuajes, que es lo único que la gente vino a mirar. */
/* `body` posicionado: sin esto, el ancla de una capa `absolute` es la VENTANA y
   el estampado medía 900px de alto en una página de 6708 — o sea aparecía solo
   en la primera pantalla, que es justo lo que habia que arreglar. Medido.

   Y `html` con fondo propio: esto NO es decorativo, es lo que hace que el
   `mix-blend-mode` funcione. Cuando `html` es transparente, el navegador
   PROPAGA el fondo del `body` al lienzo de la ventana, y el lienzo no es el
   fondo de ningún elemento: no hay contra qué mezclar. El estampado terminaba
   compuesto normal, o sea el blanco del escaneo al 5% sobre el papel — más
   claro que el papel — y se veían los RECUADROS de cada dibujo.
   Dándole fondo a `html`, el del `body` deja de propagarse, pasa a ser el fondo
   de un elemento de verdad y el multiply tiene contra qué trabajar. */
html { background-color: var(--papel); }
body { position: relative; }

/* ================================= papel tapiz de madera (04-08-2026)
   La textura de la tabla que mandó Gabriel, repetida y difuminada detrás de
   TODO. Es una capa aparte de los dibujos: los dibujos son el estampado (figuras
   reconocibles, muy separadas) y esto es el material de la hoja.

   Va PRIMERO en el documento, así los dibujos quedan encima.

   El difuminado y el aclarado NO están acá: vienen horneados en el archivo
   (`TexturaFondo`, en core/imagenes.py). Un `filter: blur()` sobre una capa del
   porte de la página se recalcula en cada scroll en el celular, y una opacidad
   escrita a ojo en el CSS se desajusta apenas suben otra foto.

   `mix-blend-mode: multiply` con el mismo cuidado de siempre: esta capa NO crea
   contexto de apilamiento propio (sin `isolation`, sin `filter`, sin `opacity`)
   y `html` tiene fondo, si no el navegador propaga el fondo del body al lienzo
   y no queda contra qué mezclar — que es de dónde salen los recuadros blancos
   que ya mordieron tres veces en este repo. */
.fondo-textura {
  content: '';
  position: absolute; inset: 0;
  z-index: 0;
  pointer-events: none;
  mix-blend-mode: multiply;
  background-image: var(--textura, none);
  background-repeat: repeat;
  background-size: 320px auto;
}
@media (max-width: 620px) {
  /* Más chica en el teléfono, por lo mismo que el estampado: a tamaño de
     escritorio la veta se lee como manchas y no como material. */
  .fondo-textura { background-size: 200px auto; }
}

/* Los dos dibujos van en CAPAS SEPARADAS y no como dos fondos del mismo
   elemento. El motivo: cada dibujo tiene una carga de tinta muy distinta -- el
   tiburón es una mancha casi maciza y la daga es de trazo fino -- así que a la
   misma opacidad el tiburón se comía al otro (lo notó Diego mirando la página).
   Como no se puede dar opacidad por capa de `background-image`, cada uno va en
   su propio elemento y se equilibra por separado. */
.fondo-ornamentos,
.fondo-ornamentos::after,
.seccion-papel::before,
.seccion-papel::after {
  content: '';
  position: absolute; inset: 0;
  z-index: 0;
  pointer-events: none;
  mix-blend-mode: multiply;
  background-repeat: repeat;
}
/* El de trazo macizo: más chico y más apagado. */
.fondo-ornamentos,
.seccion-papel::before {
  opacity: .034;
  background-image: var(--orn-a);
  background-size: 300px auto;
  background-position: 0 0;
}
/* El de trazo fino: necesita más peso para verse lo mismo. Desfasado para que
   la repetición no se lea como una cuadrícula. */
.fondo-ornamentos::after,
.seccion-papel::after {
  opacity: .075;
  background-image: var(--orn-b, none);
  background-size: 340px auto;
  background-position: 170px 180px;
}
/* `.seccion-papel` tiene color de fondo OPACO, así que tapaba el estampado que
   va detrás de toda la página: por eso el bloque "Nuestro trabajo" salía liso.
   En vez de volverlo translúcido —que le cambiaría el tono— lleva su propia
   copia del estampado, con los mismos valores de arriba. */
.seccion-papel > * { position: relative; z-index: 1; }
/* El contenido va encima del estampado.
   OJO CON `main`: lleva `position: relative` pero NO `z-index`, a propósito.
   Con z-index creaba un contexto de apilamiento, y los dos ornamentos grandes
   del título viven DENTRO de main: su `mix-blend-mode` quedaba encerrado ahí y
   dejaba de mezclarse con el papel, o sea volvía a verse el recuadro blanco del
   escaneo. Igual queda encima del estampado sin z-index, porque entre elementos
   posicionados sin z-index manda el orden del documento y main viene después. */
/* OJO: `.cabecera-fija` NO va en esta lista. Estaba, y `position: relative`
   ANULABA el `position: sticky` que tiene declarado arriba (linea ~315): el
   menu dejaba de quedarse pegado al hacer scroll. Esta regla existe para que el
   contenido quede sobre el estampado del fondo, y la cabecera ya lo consigue
   con su propio z-index: 30, que ademas es mayor. */
.header, .footer, .banda-cta, .marco-pagina { position: relative; z-index: 1; }
/* Se le sube el z-index para que pase POR ENCIMA del contenido al desplazarse:
   con z-index 30 y el contenido en 1 alcanza, pero el marco de pagina esta en
   45 y tiene que seguir arriba de todo. */
.cabecera-fija { z-index: 40; }
main { position: relative; }
.marco-pagina { z-index: 45; }     /* el marco conserva el suyo, que es mayor */

@media (max-width: 620px) {
  /* Más chico en el teléfono: al mismo tamaño, dos dibujos por pantalla se leen
     como manchas y no como textura. */
  .fondo-ornamentos, .seccion-papel::before { background-size: 190px auto; opacity: .03; }
  .fondo-ornamentos::after, .seccion-papel::after { background-size: 210px auto; opacity: .065; }
}

/* ============================== los disenos de Gabriel en la cabecera
   Sus dos dibujos de autoria (tiburon martillo y daga) flanqueando el menu.
   Son lo que hace que esta cabecera sea de Puas y no de cualquier estudio.

   `mix-blend-mode: multiply` porque los escaneos vienen con fondo BLANCO: sin
   eso queda un rectangulo blanco sobre el papel. En este repo eso ya mordio
   tres veces, asi que va con su fondo explicito -- si un ancestro crea un
   contexto de apilamiento, el multiply deja de actuar.
   La cabecera tiene z-index propio, asi que se comprueba mirando, no leyendo. */
/* EL RECORTE VA SOLO EN ESCRITORIO.
   `overflow: hidden` está acá para que los dibujos decorativos de detrás del
   navbar (`.nav-diseno`, que miden 190% de alto) no se salgan de la cabecera.
   Pero en el teléfono el menú es un DESPLEGABLE absoluto que baja hasta 418 px
   mientras la cabecera termina en 150: el recorte se lo comía entero. El menú
   se abría de verdad —269 px de alto, `visibility: visible`— y no se veía nada.
   Reportado como "el botón del menú no funciona"; se cazó recorriendo los
   ancestros del nav abierto y mirando cuál tenía `overflow`, no leyendo el CSS.
   Los dibujos ya están en `display: none` bajo 901 px, así que abajo no hay
   nada que recortar. */
.header { position: relative; }
@media (min-width: 901px) {
  .header { overflow: hidden; }
}
.nav-diseno {
  /* PRIMER INTENTO (04-08): iban DENTRO de la fila, a 46px, uno pegado al logo
     y el otro despues del boton. Se veia apretado y descolgado -- la fila ya
     lleva logo, cuatro enlaces y el llamado a la accion, no queda aire.
     Ahora van DETRAS, grandes y tenues: se leen como parte del papel y no
     compiten por espacio con nada. */
  position: absolute; top: 50%; transform: translateY(-50%);
  height: 190%; width: auto;
  mix-blend-mode: multiply;
  opacity: .07;
  pointer-events: none;
  z-index: 0;
  user-select: none;
}
.nav-diseno-izq  { left: 30%; }
.nav-diseno-der  { right: 4%; transform: translateY(-50%) scaleX(-1); }
/* El contenido de la cabecera va POR ENCIMA del dibujo. */
.header-inner { position: relative; z-index: 1; }
@media (max-width: 1100px) {
  /* En pantalla angosta el dibujo se cruza con el menu desplegado. */
  .nav-diseno { display: none; }
}

/* ------------------------------------------------- aire del pie en el teléfono
   En el celular el texto del pie quedaba pegado al borde izquierdo: el
   `.contenedor` deja 16 px a 412 px de ancho, que alcanza para un bloque de
   texto centrado pero se ve apretado en una columna de datos alineados a la
   izquierda, con sus filetes llegando hasta el borde. Se le suma aire propio
   en vez de tocar `.contenedor`, que lo usa toda la página. */
@media (max-width: 620px) {
  .footer .contenedor { padding-left: .9rem; padding-right: .9rem; }
}

/* ============================================== apertura del menú en el teléfono
   El panel BAJA desde debajo del navbar y los enlaces entran escalonados detrás.
   No es adorno: el menú aparece de golpe tapando media pantalla, y el
   movimiento explica de dónde salió y hacia dónde se va a cerrar.

   Va como `animation` y no como `transition` porque el menú alterna entre
   `display: none` y `display: flex`, y una transición no puede animar eso: el
   navegador salta al estado final sin pasar por el medio. Una animación, en
   cambio, corre cada vez que el elemento vuelve a mostrarse.

   Solo la APERTURA se anima. Al cerrar, `display: none` es inmediato y no hay
   nada que ver; animar la salida obligaría a retrasar el ocultamiento con JS y
   a manejar el caso de tocar dos veces rápido, que es más máquina de la que
   este menú necesita.

   El apagado por `prefers-reduced-motion` ya está resuelto arriba: la regla
   global deja las animaciones en .01ms, así que el menú aparece de una y queda
   igual de usable. */
@media (max-width: 900px) {
  .nav.abierto {
    animation: puas-menu-baja .26s cubic-bezier(.22, 1, .36, 1) both;
    transform-origin: top center;
  }
  .nav.abierto > * {
    animation: puas-menu-item .3s cubic-bezier(.22, 1, .36, 1) both;
  }
  /* El escalonado arranca cuando el panel ya va bajando, no antes: si entran
     junto con el fondo se lee como un temblor en vez de una secuencia.
     Y el paso es corto (40 ms) a propósito: con 50 el último enlace terminaba
     de entrar a los 0,60 s y un menú de navegación que tarda más de medio
     segundo en quedar quieto se siente lento. Así el último cierra en 0,48 s.
     Medido con capturas a 60, 140, 240 y 420 ms. */
  .nav.abierto > *:nth-child(1) { animation-delay: .06s; }
  .nav.abierto > *:nth-child(2) { animation-delay: .10s; }
  .nav.abierto > *:nth-child(3) { animation-delay: .14s; }
  .nav.abierto > *:nth-child(4) { animation-delay: .18s; }
  .nav.abierto > *:nth-child(5) { animation-delay: .22s; }
}
@keyframes puas-menu-baja {
  from { opacity: 0; transform: translateY(-12px) scaleY(.96); }
  to   { opacity: 1; transform: none; }
}
@keyframes puas-menu-item {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: none; }
}

/* "desde" antes del monto del abono: va chico y en versalitas para que el
   número siga siendo lo que se lee primero, pero sin que el precio quede
   afirmado como fijo (Gabriel, 06-08-2026: no le pide el mismo abono a todos). */
.reserva-desde {
  display: inline; font-family: var(--sans); font-size: .5em;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--tinta-suave); vertical-align: .35em;
}
