/* ─────────────────────────────────────────────────────────────
   ESTILOS DEL SITIO — archivo CSS único.
   1. Base y variables
   2. Intro controlada por scroll (intro-scroll.html)
   3. Panel de proyectos del servicio (dentro del intro)
   4. Página de proyectos (proyectos.html)
   5. Menú y pie compartidos (layout.js)
   6. Ficha de proyecto (proyectos/<id>.html)
   7. Proyectos relacionados (maqueta — aún no vive en el pie)
   ───────────────────────────────────────────────────────────── */

/* 1 · BASE */
:root{
  --negro:  #0A0A08;
  --carbon: #101214;
  --crema:  #F5EFD5;
  --crema-70: rgba(245,239,213,.70);
  --crema-45: rgba(245,239,213,.45);
  --linea:  rgba(245,239,213,.14);
  --rayado: repeating-linear-gradient(115deg, #101214, #101214 38px, rgba(245,239,213,.05) 38px, rgba(245,239,213,.05) 39px);
  /* ficha de proyecto: fondo claro */
  --papel:  #EFEDE9;
  --tinta:  #16150F;
  --tinta-70: rgba(22,21,15,.72);
  --tinta-45: rgba(22,21,15,.45);
  --tinta-linea: rgba(22,21,15,.14);
  /* luces de fondo (.lay-luces, motor en layout.js) sobre páginas oscuras:
     desaturadas, dando vueltas alrededor del azul — solo --luz-2 se anima
     con algo más de saturación */
  --luz-1: hsl(0 0% 12%);
  --luz-2: hsl(202 13% 14%);
  --luz-3: hsl(210 5% 15%);
  --luz-4: hsl(0 0% 0%);
  /* mismas luces, versión clara: para páginas de fondo --papel (fichas de
     proyecto). Unos puntos más oscuras que --papel y con el mismo matiz por
     luz que la versión oscura, así se nota la variación sin ensuciar el
     fondo claro */
  --luz-l1: hsl(40 20% 85%);
  --luz-l2: hsl(201 35% 84%);
  --luz-l3: hsl(210 10% 87%);
  --luz-l4: hsl(202 18% 81%);
  /* vitrina audiovisual (bloque 10): único acento de color del sitio */
  --av-acento: #CF7A34;
  /* alias para el bloque 14 (plantilla-marca-digital.html): mismos valores
     que --av-acento y --linea, con el nombre que ya usa ese CSS — evita
     renombrar cientos de var(--acento)/var(--crema-linea) sin necesidad */
  --acento: var(--av-acento);
  --crema-linea: var(--linea);
}

/* transición entre páginas: la grilla y la ficha se funden en vez de recargar */
@view-transition{ navigation:auto; }
::view-transition-old(root), ::view-transition-new(root){ animation-duration:.35s; }
@media(prefers-reduced-motion:reduce){
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*){ animation:none !important; }
}
*{box-sizing:border-box; margin:0; padding:0;}
/* el atributo hidden gana siempre: varios elementos del sitio traen su
   propio display (flex/grid) y sin esto el UA no llega a esconderlos */
[hidden]{display:none !important;}

/* Tarjeta de un proyecto que todavía no tiene su ficha en /proyectos.
   La marca attrFicha() (servicios.js): el <a> se queda sin href para que
   no navegue a un 404, y acá se le saca el gesto de "clickeable". Se
   sigue viendo igual —foto, título, hover de fila, arrastre—: lo único
   que cambia es que no promete una página que no existe. */
[data-sin-ficha]{cursor:default;}

/* sin esto, el rebote elástico del navegador al pasarse de los bordes del
   scroll (más notorio en iOS) hace que el contenido position:fixed a
   pantalla completa —.sc-stage, pero también los paneles— se vea
   "desprenderse" y arrastrarse con la pestaña durante el rebote. No afecta
   el scroll normal, solo el rebote en los extremos. */
html{overscroll-behavior-y:none;}
body{
  background:var(--negro);
  color:var(--crema);
  font-family:'Playfair Display',serif;
  line-height:1.5;
  overflow-x:hidden;
  overscroll-behavior-y:none;
}
.mono{font-family:'IBM Plex Mono',monospace;}
a{color:inherit; text-decoration:none;}
img{display:block; max-width:100%;}
@keyframes entrar{ from{opacity:0; transform:translateY(10px);} to{opacity:1; transform:none;} }

/* GRANO + LUCES — capa universal inyectada por layout.js en cualquier
   página que lo cargue (salvo admin.html). Un solo motor para todo el
   sitio: layout.js detecta si el fondo real de la página es oscuro o claro
   (lee el background-color calculado del body) y elige paleta + color de
   motas acorde; anima ambas capas con su propio scroll+rAF, independiente
   del loop propio que tenga cada página.
   Las dos van con z-index NEGATIVO a propósito: un z-index negativo pinta
   por debajo de CUALQUIER otro elemento de la página, tenga o no posición
   explícita (a diferencia de un z-index positivo bajo, que igual queda por
   encima de todo lo no posicionado). Así quedan siempre entre el fondo liso
   del body y el resto — nunca tapan texto, menú, tarjetas ni miniaturas.
   -2/-1 en vez de -1/0: para que .lay-grano (el que va "arriba" de las dos)
   siga pintando después de .lay-luces sin competir con el 0 de cualquier
   elemento posicionado sin z-index propio. pointer-events:none en las dos
   para que nunca bloqueen clics aunque queden bajo un hueco transparente.
   No usa mix-blend-mode: "overlay"/"soft-light" no tienen ningún efecto
   sobre negro puro — en cambio pinta motas con alfa translúcido real (color
   fijo según el filtro elegido), que sí se notan sobre cualquier fondo. */
.lay-luces{
  position:fixed; inset:-15%; z-index:-2; pointer-events:none;
  filter:blur(clamp(50px,7vw,110px));
  will-change:background;
}
.lay-grano{
  position:fixed; inset:0; z-index:-1; opacity:.85; pointer-events:none;
}
/* variante para páginas con su propio contenedor position:fixed de pantalla
   completa (hoy solo intro-scroll.html, .sc-stage): ese contenedor forma su
   propia capa de apilamiento, así que un z-index negativo en el body no lo
   traspasa — quedaría tapado por el stage entero. Ahí layout.js cuelga estas
   dos DENTRO del stage (ver [data-layout="atmosfera"]), justo después del
   fondo/velo y antes que el resto (reglas, texto, menú); sin z-index propio
   alcanza con ese orden en el HTML para pintar encima de la foto de fondo
   pero debajo de todo lo demás, mismo truco que usaba el viejo .sc-luces. */
.lay-luces.en-stage, .lay-grano.en-stage{ position:absolute; z-index:auto; }
@media(prefers-reduced-motion:reduce), (max-width:600px){
  .lay-grano{display:none;}
}
@media(prefers-reduced-motion:reduce){
  .lay-luces{display:none;}
}

/* 2 · INTRO CONTROLADA POR SCROLL (intro-scroll.html) */
html:has(body.sc-body){scroll-behavior:auto;} /* el scroll manda: sin suavizado del navegador */
.sc-scroll{height:400vh;}
.sc-stage{
  position:fixed; inset:0; overflow:hidden; touch-action:pan-y;
  transition:transform .7s cubic-bezier(.16,1,.3,1), filter .7s ease, opacity .7s ease;
}
/* EL INTRO SE RETIRA — mientras se abre una sección, el intro se va para
   atrás: achica, desenfoca y baja de intensidad. Sin esto, panel e intro
   viven en el mismo plano y la apertura se lee como un reemplazo de
   pantalla; con el retroceso se lee como una capa que se pone encima.
   Se ve sobre todo en el momento en que la máscara todavía no cubrió
   todo — que es justo cuando el corte se notaba.
   La regla de is-atras repite la transición completa para sumarle
   visibility con retardo: cuando el panel ya cubre la pantalla el intro
   se apaga del todo (deja de costar un blur a pantalla completa), y al
   sacar la clase vuelve al instante porque la transición de visibility
   solo existe en este estado. Mismo patrón que .wb-cover (bloque 11).
   getBoundingClientRect sigue siendo válido con visibility:hidden, así
   que el cierre puede medir #scFrame para plegar la máscara. */
.sc-stage.is-atras{
  transform:scale(.96); filter:blur(5px); opacity:.45; visibility:hidden;
  transition:transform .7s cubic-bezier(.16,1,.3,1), filter .7s ease, opacity .7s ease,
             visibility 0s linear .7s;
}
@media (prefers-reduced-motion: reduce){
  .sc-stage, .sc-stage.is-atras{transition:none; transform:none; filter:none;}
}

/* fondo con la portada del servicio */
.sc-bg{
  position:absolute; inset:-6%; background-size:cover; background-position:center;
  opacity:0; will-change:opacity,transform,filter;
}
.sc-bg-shade{position:absolute; inset:0; background:var(--negro); opacity:.8; pointer-events:none;}

/* reglas verticales numeradas */
.sc-rule{position:absolute; top:0; bottom:0; width:1px; overflow:hidden;}
.sc-rule-l{left:33.33%;}
.sc-rule-r{left:66.66%;}
.sc-rule-track{position:absolute; top:-60px; left:0; will-change:transform;}
.sc-tick{display:block; height:46px; position:relative; border-left:1px solid rgba(245,239,213,.09);}
.sc-tick::before{content:''; position:absolute; left:0; top:0; width:5px; border-top:1px solid rgba(245,239,213,.2);}
.sc-tick i{
  position:absolute; left:6px; top:2px; font-style:normal;
  font-size:9px; letter-spacing:.06em; color:rgba(245,239,213,.28);
  writing-mode:vertical-rl;
}
.sc-rule-r .sc-tick i{left:auto; right:6px;}

/* columnas de clips */
.sc-col{position:absolute; top:0; width:16vw; height:100%; will-change:transform,opacity;}
.sc-col-l{left:0;}
.sc-col-r{right:0;}
.sc-clip{position:absolute; left:0; width:100%; aspect-ratio:16/9; overflow:hidden; background:#111;}
.sc-col-r .sc-clip{left:auto; right:0;}
.sc-clip img{width:100%; height:100%; object-fit:cover;}

/* eje vertical del slider */
.sc-mid{position:absolute; inset:0; opacity:0; pointer-events:none;}
.sc-spine{
  position:absolute; left:50%; top:50%; width:2px; height:0;
  transform:translate(-50%,-50%); background:linear-gradient(to bottom, #3E6B86, #6FA3C0, #3E6B86);
  opacity:0;
}

/* invitación a scrollear: se ve solo en el primer instante — la opacidad la
   maneja pintar() en JS (se apaga apenas p empieza a moverse), acá solo la
   flecha hace un rebote continuo para sugerir el gesto */
.sc-scroll-cue{
  position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
  display:flex; flex-direction:column; align-items:center; gap:10px;
  font-size:10px; letter-spacing:.34em; text-transform:uppercase;
  color:rgba(245,239,213,.55); pointer-events:none;
}
.sc-scroll-flecha{
  font-style:normal; font-size:15px; line-height:1;
  animation:sc-scroll-rebote 1.7s ease-in-out infinite;
}
@media(prefers-reduced-motion:reduce){
  .sc-scroll-flecha{animation:none;}
}
@keyframes sc-scroll-rebote{
  0%, 100%{transform:translateY(0);    opacity:.55;}
  50%     {transform:translateY(7px);  opacity:1;}
}

/* frase y nombre */
.sc-phrase{
  position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
  text-align:center; font-size:clamp(24px,3.4vw,50px); font-style:italic;
  line-height:1.3; white-space:nowrap;
}
.sc-line{display:block;}
.sc-g{display:inline-block; overflow:hidden; vertical-align:bottom;}
.sc-gi{display:inline-block; will-change:transform; transform:translateY(115%);}

.sc-word{
  position:absolute; top:50%; font-size:clamp(34px,5.4vw,82px);
  white-space:nowrap; will-change:transform;
}
.sc-word-l{right:50%; transform:translate(0,-50%); padding-right:.14em;}
.sc-word-r{left:50%;  transform:translate(0,-50%); padding-left:.14em; font-style:italic;}

.sc-tagline{
  position:absolute; left:50%; top:50%; transform:translate(-50%,-50%) translateY(7.6vh);
  font-size:11px; letter-spacing:.34em; text-transform:uppercase;
  color:rgba(245,239,213,.62); white-space:nowrap; opacity:0; will-change:transform,opacity;
}

/* título del servicio: ocupa los mismos anclajes que el nombre */
.sc-title{
  position:absolute; top:50%; font-size:clamp(28px,4.4vw,66px); line-height:1.05;
  font-style:italic; opacity:0; max-width:26vw; will-change:transform,opacity;
}
.sc-title-l{right:50%; text-align:right; padding-right:.3em;}
.sc-title-r{left:50%;  text-align:left;  padding-left:.3em;}

/* ficha del servicio */
.sc-card{
  position:absolute; left:33.33%; right:33.34%; top:50%; transform:translateY(-50%);
  opacity:0; pointer-events:none;
}
.sc-card-top, .sc-card-bot{
  display:flex; justify-content:space-between; align-items:center; gap:12px;
  font-size:11px; letter-spacing:.1em; color:var(--crema-70); padding:0 2px;
}
.sc-card-top{margin-bottom:10px;}
.sc-card-bot{margin-top:10px;}
.sc-card-icons{display:flex; gap:6px;}
.sc-card-icons i{
  width:16px; height:16px; border-radius:50%; border:1px solid rgba(245,239,213,.4);
  display:flex; align-items:center; justify-content:center; font-style:normal; font-size:8px;
}
.sc-frame{
  position:relative; width:100%; height:0; cursor:pointer;
  background:linear-gradient(160deg, rgba(120,150,175,.22), rgba(20,30,40,.35));
  backdrop-filter:blur(2px);
  /* nunca transicionar height: el bucle del intro se lo escribe inline en
     cada frame y una transición ahí arrastraría todo el scroll */
  transition:transform .22s ease, filter .22s ease, box-shadow .22s ease;
}
.sc-abrir{
  position:absolute; left:50%; top:100%; transform:translate(-50%,-24px);
  font-size:10px; letter-spacing:.12em; color:rgba(245,239,213,.55);
  white-space:nowrap; pointer-events:none;
  opacity:0; transition:opacity .25s;
}
.sc-frame:hover .sc-abrir{opacity:1;}
.sc-frame:hover .sc-brk{border-color:var(--crema);}
/* AL PASAR EL CURSOR el cuadro se enciende: sube el brillo del vidrio y
   suelta un halo alrededor, mientras las esquinas pasan a crema pleno y
   aparece el rótulo (las dos reglas de arriba). Es la señal de que el
   cuadro se puede abrir, así que tiene que leerse sin gritar — de ahí el
   halo abierto y sin borde: un marco completo pelearía con las esquinas,
   que son el lenguaje del sitio.
   Usa el mismo filter y la misma transición que el puente; como
   .sc-card.is-puente .sc-frame gana por especificidad, al abrir manda el
   puente y el hover no lo pisa. */
.sc-frame:hover{
  filter:brightness(1.22) saturate(1.08);
  box-shadow:0 0 46px rgba(245,239,213,.14);
}
.sc-brk{
  position:absolute; width:16px; height:16px;
  border:0 solid rgba(245,239,213,.7);
  transition:border-color .25s, transform .45s cubic-bezier(.16,1,.3,1), opacity .45s ease;
}
.sc-brk-tl{top:0; left:0;  border-top-width:1px; border-left-width:1px;}
.sc-brk-tr{top:0; right:0; border-top-width:1px; border-right-width:1px;}
.sc-brk-bl{bottom:0; left:0;  border-bottom-width:1px; border-left-width:1px;}
.sc-brk-br{bottom:0; right:0; border-bottom-width:1px; border-right-width:1px;}
.sc-cross{
  position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
  pointer-events:none;
  font-family:'IBM Plex Mono',monospace; font-size:18px; color:rgba(245,239,213,.55);
  transition:opacity .2s ease, transform .35s cubic-bezier(.16,1,.3,1);
}

/* PUENTE — el gesto que enlaza la tarjeta con la sección que se abre.
   Antes de que el panel despliegue su máscara, el cuadro central se
   desarma solo: los cuatro brackets salen en diagonal, el "+" crece y se
   apaga, el rótulo se va y el marco se enciende. El ojo sigue ese
   movimiento y cuando la máscara arranca ya no hay corte.
   Lo prende intro.js poniendo .is-puente en .sc-card, y lo apaga al
   cerrar. Se puede animar por clase sin pelear con el bucle porque
   pintar() solo escribe el alto del marco y la opacidad/transform de
   .sc-card — nunca sus hijos ni el transform del marco.
   Sale rápido (.22s, decidido) y vuelve lento (.45s, con la curva
   blanda): abrir es un golpe, cerrar es un asentar. */
.sc-card.is-puente .sc-frame{transform:scale(1.015); filter:brightness(1.25);}
.sc-card.is-puente .sc-abrir{opacity:0;}
.sc-card.is-puente .sc-brk{opacity:0; transition-duration:.25s, .22s, .22s;}
.sc-card.is-puente .sc-brk-tl{transform:translate(-14px,-14px);}
.sc-card.is-puente .sc-brk-tr{transform:translate( 14px,-14px);}
.sc-card.is-puente .sc-brk-bl{transform:translate(-14px, 14px);}
.sc-card.is-puente .sc-brk-br{transform:translate( 14px, 14px);}
.sc-card.is-puente .sc-cross{opacity:0; transform:translate(-50%,-50%) scale(1.6);}
@media (prefers-reduced-motion: reduce){
  .sc-card.is-puente .sc-brk, .sc-card.is-puente .sc-cross{transition:none;}
  .sc-card.is-puente .sc-frame{transform:none; filter:none;}
}

/* 3 · PREVISUALIZACIÓN DE PROYECTOS (se abre desde el cuadro central)
   Carrusel de fichas: la central nítida y grande, las de los lados
   oscurecidas; el fondo es su portada desenfocada y detrás va el nombre
   de la obra en tipografía gigante. --fh = alto de la ficha central. */
.sc-panel{
  --fh:clamp(210px,50vh,520px);
  position:fixed; inset:0; z-index:60; display:none; overflow:hidden;
  background:var(--negro);
  /* la curva vieja (.55s con cubic-bezier(.65,0,.2,1)) juntaba casi todo el
     recorrido en los últimos 200 ms y por eso la apertura pegaba un salto
     al final; esta sale rápido y frena larga. Si se cambia la duración hay
     que mover MASCARA_MS en intro.js, que espera a que termine */
  clip-path:inset(0 0 0 0); transition:clip-path .7s cubic-bezier(.16,1,.3,1);
}
.sc-panel.is-open{display:block;}
.sc-panel-bg{
  position:absolute; inset:-4%; background-size:cover; background-position:center;
  opacity:0; filter:blur(16px) saturate(.8); transform:scale(1.08);
  transition:opacity .6s ease;
}
.sc-panel-bg.is-on{opacity:.45;}
.sc-panel-shade{
  position:absolute; inset:0;
  background:linear-gradient(to bottom, rgba(10,10,8,.88) 0%, rgba(10,10,8,.64) 40%, rgba(10,10,8,.97) 100%);
}
/* BARRIDO DE LUZ — el destello diagonal que cruza la pantalla una sola vez
   al abrir la sección, como la luz de una sala de proyección pasando por
   delante del lente. Antes era una capa fija (un brillo estático que casi
   no se veía); ahora hace el gesto que su nombre siempre prometió.
   Va por encima de TODO el panel (z-index sobre .sc-panel-top, que llega a
   40): es luz delante de la escena, no una capa del fondo.
   position:fixed y no absolute porque tres de los cuatro paneles son su
   propio contenedor de scroll —un absolute se iría con el contenido al
   scrollear—; queda anclado igual porque el clip-path de .sc-panel lo
   convierte en bloque contenedor de sus hijos fixed.
   Arranca 120 ms después de que la máscara empieza a abrirse y dura más
   que ella (.55s): la luz sigue cruzando cuando el panel ya llegó, y es
   eso lo que sella la transición en vez de cortarla. */
.sc-panel-streak{
  position:fixed; top:0; bottom:0; left:-60%; width:80%; z-index:50;
  pointer-events:none; opacity:0;
  background:linear-gradient(115deg, transparent 0%, rgba(245,239,213,.07) 46%, transparent 100%);
}
/* 215% del propio ancho = el recorrido justo para salir por la derecha: la
   banda usa toda la animación cruzando y se apaga mientras se va, sin
   quedarse tildada fuera de pantalla al final */
.sc-panel.is-open .sc-panel-streak{animation:sc-barrido .9s cubic-bezier(.4,0,.25,1) .12s both;}
@keyframes sc-barrido{
  0%   {opacity:0; transform:translateX(0);}
  16%  {opacity:1;}
  62%  {opacity:1;}
  100% {opacity:0; transform:translateX(215%);}
}
@media (prefers-reduced-motion: reduce){
  .sc-panel.is-open .sc-panel-streak{animation:none;}
}

/* CONTRA-ZOOM — mientras la máscara se abre, lo de adentro viene un poco
   más grande y apagado y asienta en su tamaño real. La máscara sola
   revelaba una pantalla ya terminada y quieta: eso se lee como un corte,
   no como una transición. Con el contra-zoom la sensación es que se
   entra en la tarjeta en vez de que la tarjeta se reemplace.
   Se aplica a la pantalla de apertura de cada panel y no a un envoltorio
   de todo el contenido a propósito: durante la apertura es lo único que
   se ve, y un transform sobre todo el panel rompería el position:sticky
   de las tarjetas apiladas (.wb-card) y de la cinemática (#av-stage).
   #av-intro-card va aparte y solo con transform: su opacidad la maneja
   la cinemática por scroll, y pisarla desde acá la dejaría trabada. */
.sc-panel.is-open .wb-hero{animation:sc-contra .8s cubic-bezier(.16,1,.3,1) both;}
.sc-vidpanel.is-open #av-intro-card{animation:sc-contra-tr .8s cubic-bezier(.16,1,.3,1) both;}
@keyframes sc-contra{ from{transform:scale(1.06); opacity:.5;} to{transform:none; opacity:1;} }
@keyframes sc-contra-tr{ from{transform:scale(1.06);} to{transform:none;} }

/* …y el espejo al cerrar: la clase la pone intro.js al empezar el cierre y
   la saca junto con is-open. Va DESPUÉS de las reglas de is-open porque
   las dos conviven durante el cierre y tienen la misma especificidad:
   gana la última escrita. Sale más rápido de lo que entró — cerrar no se
   hace esperar. */
/* el panel se disuelve en el último tramo del plegado. Sin esto la máscara
   terminaba de cerrarse sobre un rectángulo todavía opaco que se apagaba de
   un frame al otro (display:none) — el "desaparece de golpe". Ahora, cuando
   el recuadro ya es chico, se funde contra el intro que para entonces ya
   volvió a foco, y llega a cero justo cuando el panel se apaga. */
.sc-panel.is-cerrando{animation:sc-panel-salida .7s ease both;}
@keyframes sc-panel-salida{ 0%,55%{opacity:1;} 100%{opacity:0;} }
.sc-panel.is-cerrando .wb-hero{animation:sc-contra-salida .5s cubic-bezier(.4,0,.2,1) both;}
.sc-vidpanel.is-cerrando #av-intro-card{animation:sc-contra-salida-tr .5s cubic-bezier(.4,0,.2,1) both;}
@keyframes sc-contra-salida{ from{transform:none; opacity:1;} to{transform:scale(1.04); opacity:0;} }
@keyframes sc-contra-salida-tr{ from{transform:none;} to{transform:scale(1.04);} }

/* TAPA DE SALIDA — la portada de la sección, de vuelta al cerrar. La arma
   intro.js (taparParaSalir) copiando el título de la portada de cada panel,
   así que acá solo va el aspecto: el mismo encuadre de .wb-hero, en fijo
   para que la recorte la máscara y se pliegue con ella.
   Solo entra: quien la apaga es el fundido del panel entero
   (sc-panel-salida), y así toda la salida se va con una única curva en vez
   de dos compitiendo.
   Por encima de .sc-panel-top (40) —el CERRAR no tiene sentido sobre una
   sección que ya se está yendo— y por debajo del barrido de luz (50). */
.sc-tapa{
  position:fixed; inset:0; z-index:45;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:22px;
  background:var(--negro); pointer-events:none;
  animation:sc-tapa-entra .22s ease both;
}
@keyframes sc-tapa-entra{ from{opacity:0;} to{opacity:1;} }
/* sus esquinas ya están puestas: no repiten la entrada escalonada de la
   portada de apertura, que acá sería ruido */
.sc-tapa .wb-brk{opacity:1; transform:none; animation:none;}
/* y arriba van a la misma altura que abajo: la tapa cubre la barra de
   CERRAR, así que no hay nada que esquivar */
.sc-panel .sc-tapa .wb-brk.tl, .sc-panel .sc-tapa .wb-brk.tr{top:32px;}

@media (prefers-reduced-motion: reduce){
  .sc-panel.is-open .wb-hero, .sc-vidpanel.is-open #av-intro-card,
  .sc-panel.is-cerrando .wb-hero, .sc-vidpanel.is-cerrando #av-intro-card{animation:none;}
  /* el fundido de salida sí se mantiene: no es movimiento, y sin él el
     panel se apagaría de un frame al otro */
  .sc-panel.is-cerrando{animation:sc-panel-salida .7s ease both;}
}

.sc-panel-rule{opacity:.35;}

.sc-panel-top{
  position:absolute; top:0; left:0; right:0; z-index:30;
  display:flex; justify-content:space-between; align-items:center; gap:24px;
  padding:22px clamp(18px,3vw,42px) 0;
  font-size:11px; letter-spacing:.12em; color:var(--crema-70);
}
.sc-panel-close{
  font-family:'IBM Plex Mono',monospace; font-size:11px; letter-spacing:.12em;
  color:var(--crema-70); background:transparent;
  border:1px solid rgba(245,239,213,.22); padding:8px 14px; cursor:pointer;
  transition:border-color .2s, color .2s;
}
.sc-panel-close:hover{border-color:var(--crema); color:var(--crema);}

/* capa tipográfica de fondo: se recorta contra los bordes, como en un cartel */
.sc-tipo{
  position:absolute; left:0; right:0; bottom:0; z-index:5;
  text-align:center; pointer-events:none; overflow:hidden;
  padding-bottom:clamp(6px,2.4vh,34px); will-change:transform;
}
.sc-tipo-linea{
  font-size:10px; letter-spacing:.34em; text-transform:uppercase;
  color:rgba(245,239,213,.35); white-space:nowrap; margin-bottom:.35em;
}
.sc-tipo-gigante{
  font-size:clamp(48px,12vw,180px); line-height:.92; font-weight:400; font-style:italic;
  white-space:nowrap; color:rgba(245,239,213,.17);
}
.sc-tipo.is-in .sc-tipo-linea, .sc-tipo.is-in .sc-tipo-gigante{animation:entrar .5s ease both;}

/* carrusel */
.sc-carr{position:absolute; inset:0; z-index:10; cursor:grab; touch-action:pan-y;}
.sc-carr.is-dragging{cursor:grabbing;}
.sc-carr-item{
  position:absolute; left:50%; top:47%;
  height:var(--fh); width:calc(var(--fh) * .75);
  padding:0; border:none; background:var(--carbon); cursor:pointer;
  transform:translate(-50%,-50%); will-change:transform,opacity;
}
.sc-carr-foto{position:absolute; inset:0; display:block; overflow:hidden;}
.sc-carr-foto img{width:100%; height:100%; object-fit:cover;}
.sc-carr-item.is-empty .sc-carr-foto{background:var(--rayado);}
.sc-carr-item::after{
  content:''; position:absolute; inset:0;
  border:1px solid rgba(245,239,213,.14); transition:border-color .35s;
}
.sc-carr-item.is-on::after{border-color:rgba(245,239,213,.8);}

/* rótulo sobre la ficha central y pie con sus datos */
.sc-kicker{
  position:absolute; left:0; right:0; top:calc(47% - var(--fh) / 2 - 28px); z-index:20;
  text-align:center; font-size:9px; letter-spacing:.32em; text-transform:uppercase;
  color:rgba(245,239,213,.6); pointer-events:none;
}
.sc-ficha{
  position:absolute; left:0; right:0; top:calc(47% + var(--fh) / 2 + 16px); z-index:20;
  display:flex; flex-direction:column; align-items:center; gap:8px;
  text-align:center; padding:0 24px;
}
.sc-ficha-tit{font-size:11px; letter-spacing:.2em; text-transform:uppercase;}
.sc-ficha-sub{font-size:9px; letter-spacing:.22em; text-transform:uppercase; color:rgba(245,239,213,.45);}
.sc-kicker.is-in, .sc-ficha.is-in > *{animation:entrar .5s ease both;}
.sc-panel-abrir{
  font-family:'IBM Plex Mono',monospace;
  font-size:10px; letter-spacing:.18em; color:rgba(245,239,213,.55);
  border-bottom:1px solid rgba(245,239,213,.2); padding-bottom:3px; margin-top:4px;
  transition:color .2s, border-color .2s;
}
.sc-panel-abrir:hover{color:var(--crema); border-color:var(--crema);}

/* servicio sin proyectos: se ocultan carrusel y textos */
.sc-panel-vacio{
  position:absolute; left:0; right:0; top:47%; z-index:20; display:none;
  text-align:center; font-size:11px; letter-spacing:.14em; color:rgba(245,239,213,.5);
}
.sc-panel.is-vacio .sc-panel-vacio{display:block;}
.sc-panel.is-vacio .sc-tipo,
.sc-panel.is-vacio .sc-kicker,
.sc-panel.is-vacio .sc-ficha{display:none;}

/* 3b · LISTA DE PROYECTOS (botón "PROYECTOS" del pie, solo intro-scroll.html)
   Pantalla completa que se monta encima de todo (por eso z-index por arriba
   del sc-panel) y se muestra/oculta con display, igual que sc-panel. El
   fondo negro vive en .sc-lista-track —la capa que de verdad se desliza—
   y NO en .sc-lista-panel: si el negro estuviera en el panel (que aparece
   con display, sin transición) se vería una pantalla negra saltando de
   golpe y el contenido deslizándose adentro suelto, en vez de sentirse
   como una sola pieza que sube. Con el fondo pegado al que se mueve, lo que
   se ve es el bloque completo (negro + lista) entrando desde abajo y, al
   cerrar, bajando y destapando el intro progresivamente por arriba.
   .sc-lista-track empieza en el 100% de su propio alto (fuera, abajo) y
   sube a 0 al agregarle .is-in un frame después de abrir, para que la
   transición sí dispare; además hace de contenedor con scroll propio si la
   lista no entra completa. Reutiliza tal cual el componente .rel-* de la
   maqueta de "proyectos relacionados". */
.sc-lista-panel{
  position:fixed; inset:0; z-index:65; display:none;
}
.sc-lista-panel.is-open{display:block;}
.sc-lista-track{
  position:absolute; inset:0; overflow-y:auto; -webkit-overflow-scrolling:touch;
  background:var(--negro);
  transform:translateY(100%);
  transition:transform .6s cubic-bezier(.22,1,.36,1);
}
.sc-lista-track.is-in{transform:translateY(0);}
@media(prefers-reduced-motion:reduce){
  .sc-lista-track{transition:none !important;}
}
.sc-lista-cerrar{
  position:sticky; top:16px; left:50%; transform:translateX(-50%); z-index:5;
  display:flex; align-items:center; justify-content:center;
  width:36px; height:36px; margin-bottom:-36px; /* no empuja el contenido de abajo */
  border-radius:50%; border:1px solid rgba(245,239,213,.28);
  background:rgba(10,10,8,.7); backdrop-filter:blur(6px);
  color:var(--crema-70); cursor:pointer; transition:border-color .2s, color .2s, transform .2s;
}
.sc-lista-cerrar:hover{border-color:var(--crema); color:var(--crema); transform:translateX(-50%) translateY(2px);}
.sc-lista-cerrar svg{width:15px; height:15px; display:block;}

/* 3c · PROYECTOS — grilla completa (botón "TRABAJO" del menú, solo
   intro-scroll.html). Mismo mecanismo que 3b (arriba): el fondo va pegado
   a la capa que se mueve, no al panel. Se desliza desde la DERECHA en vez
   de desde abajo — por eso translateX en vez de translateY, y el botón de
   cerrar (reutiliza .sc-lista-cerrar) lleva una flecha apuntando a la
   derecha. Adentro reaparecen literalmente los mismos pg- y mq- de
   proyectos.html (bloques 4 y 8, más abajo) — no hay CSS nuevo para la
   grilla ni los filtros, todo eso ya existe y se ve igual.
   OJO: al listar prefijos acá adentro, separarlos con " y " o con " · ",
   nunca con barra pegada a un asterisco: esa secuencia cierra el
   comentario antes de tiempo y el parser se come la regla que sigue. */
.sc-trabajo-panel{
  position:fixed; inset:0; z-index:65; display:none;
}
.sc-trabajo-panel.is-open{display:block;}
.sc-trabajo-track{
  position:absolute; inset:0; overflow-y:auto; -webkit-overflow-scrolling:touch;
  background:var(--negro);
  transform:translateX(100%);
  transition:transform .6s cubic-bezier(.22,1,.36,1);
}
.sc-trabajo-track.is-in{transform:translateX(0);}
@media(prefers-reduced-motion:reduce){
  .sc-trabajo-track{transition:none !important;}
}

/* 4 · PÁGINA DE PROYECTOS (proyectos.html) */

.pg-main{padding:0 clamp(18px,3vw,42px);}
.pg-hero{
  display:flex; align-items:flex-end; justify-content:space-between; gap:24px; flex-wrap:wrap;
  padding:clamp(48px,11vh,130px) 0 clamp(18px,3vh,34px);
}
.pg-kicker{
  font-size:11px; letter-spacing:.24em; text-transform:uppercase;
  color:rgba(245,239,213,.5); margin-bottom:12px;
}
.pg-titulo{font-size:clamp(40px,8vw,110px); font-weight:400; font-style:italic; line-height:1;}
.pg-conteo{font-size:11px; letter-spacing:.2em; color:var(--crema-70); padding-bottom:10px;}

/* filtros en dos niveles: servicio arriba, categorías del servicio debajo */
.pg-nav{ padding-bottom:clamp(20px,3.5vh,38px); border-bottom:1px solid var(--linea); }
.pg-filtros{ display:flex; flex-wrap:wrap; gap:10px; }
.pg-filtro{
  font-family:'IBM Plex Mono',monospace; font-size:11px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--crema-45);
  background:transparent; border:1px solid var(--linea); padding:9px 15px;
  cursor:pointer; transition:color .2s, border-color .2s;
}
.pg-filtro:hover{color:var(--crema);}
.pg-filtro.is-on{color:var(--crema); border-color:rgba(245,239,213,.7);}
.pg-filtro i{font-style:normal; color:rgba(245,239,213,.35);}

/* segundo nivel: sin caja, se distingue del primero por peso, no por color */
.pg-subfiltros{display:flex; flex-wrap:wrap; gap:6px 18px; margin-top:16px;}
.pg-subfiltros:empty{display:none;}
.pg-sub{
  font-family:'IBM Plex Mono',monospace; font-size:10px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--crema-45);
  background:transparent; border:0; border-bottom:1px solid transparent;
  padding:4px 0; cursor:pointer; transition:color .2s, border-color .2s;
}
.pg-sub:hover{color:var(--crema-70);}
.pg-sub.is-on{color:var(--crema); border-bottom-color:rgba(245,239,213,.7);}
.pg-sub i{font-style:normal; color:rgba(245,239,213,.3);}

.pg-grid{
  display:grid; grid-template-columns:repeat(3,1fr); gap:clamp(18px,2.4vw,34px);
  padding:clamp(26px,5vh,54px) 0 clamp(40px,8vh,96px);
}
@media(max-width:900px){ .pg-grid{grid-template-columns:repeat(2,1fr);} }
@media(max-width:560px){ .pg-grid{grid-template-columns:1fr;} }

.pg-card{display:block; animation:entrar .4s ease both; animation-delay:calc(var(--i) * 25ms);}
.pg-card-img{
  position:relative; display:block; aspect-ratio:4/3; overflow:hidden; background:var(--carbon);
}
.pg-card-img.is-empty{background:var(--rayado);}
.pg-card-img img{
  width:100%; height:100%; object-fit:cover;
  filter:brightness(.62) saturate(.8); transition:filter .35s, transform .5s;
}
.pg-card:hover .pg-card-img img{filter:none; transform:scale(1.04);}
.pg-card-img::after{content:''; position:absolute; inset:0; border:1px solid transparent; transition:border-color .25s;}
.pg-card:hover .pg-card-img::after{border-color:rgba(245,239,213,.7);}
.pg-card-num{
  position:absolute; top:9px; left:11px; z-index:2; font-style:normal;
  font-size:10px; letter-spacing:.14em; color:rgba(245,239,213,.55);
}

.pg-card-meta{display:flex; flex-direction:column; gap:5px; padding:13px 2px 0;}
.pg-card-cli{font-size:10px; letter-spacing:.18em; text-transform:uppercase; color:rgba(245,239,213,.5);}
.pg-card-tit{font-size:clamp(17px,1.5vw,22px); font-style:italic; line-height:1.2;}
.pg-card-tag{font-size:10px; letter-spacing:.14em; text-transform:uppercase; color:var(--crema-45);}

.pg-vacio{
  grid-column:1 / -1; padding:60px 0; text-align:center;
  font-size:11px; letter-spacing:.16em; color:rgba(245,239,213,.5);
}

/* 5 · MENÚ Y PIE COMPARTIDOS — los genera layout.js en todas las páginas */
.lay-head, .lay-foot{display:flex; justify-content:space-between; gap:24px;}
.lay-head{align-items:flex-start;}
.lay-foot{align-items:flex-end;}
.lay-marca{display:flex; gap:38px; align-items:baseline;}
.lay-logo{font-style:italic; font-size:19px;}
.lay-etiqueta, .lay-nav, .lay-foot span{
  font-family:'IBM Plex Mono',monospace; font-size:11px; letter-spacing:.1em;
  color:var(--crema-70);
}
.lay-nav{display:flex; gap:52px; line-height:1.7;}
.lay-nav a, .lay-foot a{transition:color .2s;}
.lay-nav a:hover, .lay-nav a.is-on, .lay-foot a:hover, .lay-foot a.is-on{color:var(--crema);}

/* fuera del intro: barra pegada arriba y pie al final del documento */
.lay-head:not(.sc-ui){
  position:sticky; top:0; z-index:50; padding:16px clamp(18px,3vw,42px);
  background:rgba(10,10,8,.92); backdrop-filter:blur(6px);
  border-bottom:1px solid var(--linea);
}
.lay-foot:not(.sc-ui){
  padding:24px clamp(18px,3vw,42px);
  border-top:1px solid var(--linea);
}

/* dentro del intro: posición absoluta y opacidad animada por el scroll */
.sc-ui{position:absolute; left:0; right:0; padding:16px 26px; opacity:0; will-change:transform,opacity;}
.sc-head{top:0;}
.sc-foot{bottom:0;}

@media(max-width:700px){
  .sc-panel{--fh:clamp(200px,42vh,340px);}
  .sc-tipo-linea{letter-spacing:.2em;}
  .sc-col{width:26vw;}
  .sc-phrase{font-size:22px; white-space:normal; width:80vw;}
  .lay-nav{gap:20px;}
  .lay-marca{gap:16px;}
  .sc-ui{padding:12px 14px;}
}

/* 7 · PROYECTOS RELACIONADOS — maqueta de una lista compacta (5 items) para
   el pie de página. Fila completa clicable. En reposo la miniatura es solo
   una línea horizontal (--linea-w de largo, casi sin alto); al pasar el
   cursor esa línea se estira en X —lento, es el gesto de "abrir"— y recién
   al terminar se abre en Y hasta --thumb-w/--thumb-h revelando la foto.
   Como es la última en el DOM y tiene fondo opaco, al crecer hacia la
   izquierda pasa por delante de los chips y el año de su propia fila (les
   da prioridad a la miniatura y al título, que no se mueve). --hueco
   reserva un margen angosto en la grilla para que el texto no choque
   contra la línea en reposo; cada fila sube su z-index al pasar el cursor
   para montarse también sobre las filas vecinas. */
.rel-section{
  --thumb-w:clamp(240px,26vw,380px);
  --thumb-h:clamp(160px,17vw,250px);
  --linea-w:clamp(46px,5.5vw,70px);
  --linea-color:rgba(245,239,213,.4);
  --hueco:clamp(20px,3vw,32px);
  padding:clamp(40px,8vh,90px) 0 clamp(50px,9vh,100px);
  border-top:1px solid var(--linea);
}
.rel-cabeza{padding:0 clamp(18px,3vw,42px) clamp(22px,3.5vh,36px);}
.rel-kicker{
  font-size:11px; letter-spacing:.24em; text-transform:uppercase;
  color:rgba(245,239,213,.5); margin-bottom:10px;
}
.rel-titulo{font-size:clamp(30px,4.2vw,54px); font-weight:400; font-style:italic; line-height:1;}

.rel-list{display:flex; flex-direction:column;}
.rel-row{
  position:relative; z-index:0; display:grid;
  /* título/chips/año del tamaño justo de su contenido, agrupados a la
     izquierda; el hueco de la línea es el que se estira con lo que sobra,
     así del otro lado del texto la fila queda limpia para la miniatura */
  grid-template-columns:auto auto auto minmax(var(--hueco),1fr);
  align-items:center; gap:clamp(14px,2.6vw,36px);
  padding:20px clamp(18px,3vw,42px);
  background:var(--negro);
  transition:background .3s ease, z-index .3s step-end;
}
.rel-row:nth-child(even){background:var(--carbon);}
.rel-row:hover, .rel-row:focus-visible, .rel-row.is-open{
  background:rgba(245,239,213,.07); z-index:5; transition:background .3s ease, z-index 0s;
  outline:none;
}

.rel-row-tit{
  font-size:clamp(19px,2.1vw,28px); font-style:italic; line-height:1.2;
  color:var(--crema); transform:translateX(0);
  transition:color .3s, transform .35s ease, font-size .35s ease;
}
.rel-row:hover .rel-row-tit, .rel-row:focus-visible .rel-row-tit, .rel-row.is-open .rel-row-tit{
  color:var(--crema-70); transform:translateX(-8px); font-size:clamp(16px,1.8vw,24px);
}

.rel-row-cats{display:flex; flex-wrap:wrap; gap:8px;}
.rel-chip{
  font-size:10px; letter-spacing:.1em; text-transform:uppercase; white-space:nowrap;
  color:var(--chip,var(--crema-70)); border:1px solid var(--chip,var(--linea));
  padding:7px 12px; transition:background .3s, color .3s;
}
.rel-row:hover .rel-chip, .rel-row:focus-visible .rel-chip, .rel-row.is-open .rel-chip{background:var(--chip,rgba(245,239,213,.35)); color:var(--negro);}

.rel-row-anio{font-size:11px; letter-spacing:.1em; color:var(--crema-45);}

/* .rel-row-hueco: celda muda (aria-hidden en el HTML), no necesita ancho
   propio — lo maneja el minmax() de su columna en .rel-row */

/* al abrir se estira primero en X (lento, ease-out) y solo cuando termina
   arranca Y (ease-in-back: retrocede un poco antes de tirar hacia
   adelante, da el golpe de "resorte"). La foto NO se achica ni se re-recorta
   con la caja: mide siempre --thumb-w/--thumb-h (su tamaño abierto final) y
   vive anclada al mismo borde derecho / centro vertical que .rel-row-thumb;
   la caja es solo la ventana (overflow:hidden) que la va destapando a
   medida que crece, como si ya estuviera ahí dentro. Por eso no hay fundido:
   la foto pasa de invisible a visible de un salto (transition de 0s) justo
   cuando arranca Y —en ese instante la ventana mide 2px, así que el salto
   no se nota— y al cerrar, al revés, se apaga apenas Y vuelve a 2px. */
/* el borde usa --linea-color en los dos estados y nunca transiciona: así la
   línea en reposo no es más que ese borde con el hueco tapado por su propio
   fondo, y al abrirse el borde se queda quieto haciendo de marco alrededor
   de la foto — no hay un color de línea que desaparece y una caja distinta
   que aparece, es el mismo marco creciendo. */
.rel-row-thumb{
  position:absolute; top:50%; right:clamp(18px,3vw,42px);
  width:var(--linea-w); height:2px;
  overflow:hidden; background:var(--linea-color);
  border:1px solid var(--linea-color);
  transform:translateY(-50%);
  transition:
    height .28s cubic-bezier(.4,0,.2,1),
    width  .3s  cubic-bezier(.4,0,.2,1) .28s,
    background-color .2s;
}
.rel-row-thumb img{
  position:absolute; top:50%; right:0; transform:translateY(-50%);
  width:var(--thumb-w); height:var(--thumb-h); object-fit:cover;
  opacity:0; filter:brightness(.7) saturate(.85);
  transition:opacity 0s linear .28s, filter .4s;
}
.rel-row:hover .rel-row-thumb, .rel-row:focus-visible .rel-row-thumb, .rel-row.is-open .rel-row-thumb{
  width:var(--thumb-w); height:var(--thumb-h); background:var(--carbon);
  box-shadow:0 26px 60px rgba(0,0,0,.55);
  transition:
    width  .6s  cubic-bezier(.65,0,.35,1),
    height .42s cubic-bezier(.36,0,.66,-.56) .6s,
    background-color .1s, box-shadow .3s .6s;
}
.rel-row:hover .rel-row-thumb.is-empty, .rel-row:focus-visible .rel-row-thumb.is-empty, .rel-row.is-open .rel-row-thumb.is-empty{background:var(--rayado);}
.rel-row:hover .rel-row-thumb img, .rel-row:focus-visible .rel-row-thumb img, .rel-row.is-open .rel-row-thumb img{
  opacity:1; filter:none;
  transition:opacity 0s linear .6s, filter .4s .6s;
}

@media(prefers-reduced-motion:reduce){
  .rel-row-thumb, .rel-row-thumb img, .rel-chip, .rel-row-tit{transition:none !important;}
}

@media(max-width:820px){
  .rel-row{grid-template-columns:1fr auto var(--hueco); row-gap:8px;}
  .rel-row-anio{display:none;}
}
@media(max-width:560px){
  .rel-section{ --thumb-w:clamp(140px,42vw,220px); --thumb-h:clamp(96px,29vw,150px); --hueco:14px; }
  .rel-row{grid-template-columns:1fr var(--hueco); gap:12px;}
  .rel-row-cats{display:none;}
}

/* 8 · GRILLA EN MOVIMIENTO (proyectos.html) — reemplazó a la vieja .pg-grid
   estática. Cada fila es una cinta infinita: se arma con el mismo chunk de
   proyectos duplicado una vez, así el punto donde "termina" un set es
   idéntico al que "empieza" el siguiente y el loop no se nota. El
   movimiento NO es un @keyframes de CSS: el JS de la página escribe
   `transform` a mano cuadro a cuadro (necesita poder tomar la cinta del
   mouse/dedo a mitad de camino sin que salte), con inercia al soltar que
   se apaga sola hasta volver a calzar con la velocidad habitual. Las
   filas alternan sentido según .mq-track-r (mismo mecanismo, signo
   contrario). Sin texto visible: cliente/título/categorías viven en
   .mq-card-info, oculta hasta hover o .is-open (tap en móvil); el JS
   pausa (suaviza a 0) la cinta de esa fila mientras tanto.
   .pg-grid/.pg-card* (bloque 4, más arriba) quedaron sin uso — la grilla
   estática vieja ya no se pinta en ningún lado, se dejaron por si hace
   falta volver atrás. */
.mq-wall{
  --mq-gap:clamp(10px,1.6vw,18px);
  --tile:calc((100vw - 2*clamp(18px,3vw,42px) - 4*var(--mq-gap)) / 5);
  display:flex; flex-direction:column; gap:var(--mq-gap);
  padding:clamp(20px,4vh,40px) 0 clamp(50px,8vh,90px);
}
.mq-row{position:relative; overflow:hidden; touch-action:pan-y; cursor:grab; user-select:none;}
.mq-row.is-dragging{cursor:grabbing;}
.mq-track{display:flex; gap:var(--mq-gap); width:max-content; will-change:transform;}

.mq-card{
  position:relative; flex:0 0 auto; display:block;
  width:var(--tile); aspect-ratio:4/3; overflow:hidden; background:var(--carbon);
}
.mq-card-img{position:absolute; inset:0;}
.mq-card-img.is-empty{background:var(--rayado);}
.mq-card-img img{
  width:100%; height:100%; object-fit:cover; -webkit-user-drag:none;
  filter:brightness(.62) saturate(.8); transition:filter .35s, transform .5s;
}
.mq-card:hover .mq-card-img img, .mq-card.is-open .mq-card-img img{filter:none; transform:scale(1.04);}
.mq-row.is-dragging .mq-card-img img{transition:none;}

/* info superpuesta: invisible salvo hover/is-open, no roba clics del resto
   de la tarjeta salvo cuando está abierta (para poder tocarla y navegar) */
.mq-card-info{
  position:absolute; inset:0; z-index:2; display:flex; flex-direction:column;
  justify-content:flex-end; gap:4px; padding:clamp(10px,1.4vw,16px);
  background:linear-gradient(to top, rgba(10,10,8,.88) 0%, rgba(10,10,8,.25) 65%, transparent 100%);
  opacity:0; transition:opacity .3s ease; pointer-events:none;
}
.mq-card:hover .mq-card-info, .mq-card.is-open .mq-card-info{opacity:1;}
.mq-card-cli{font-size:9px; letter-spacing:.16em; text-transform:uppercase; color:rgba(245,239,213,.6);}
.mq-card-tit{font-size:clamp(14px,1.3vw,19px); font-style:italic; line-height:1.22; color:var(--crema);}
.mq-card-tag{font-size:9px; letter-spacing:.1em; text-transform:uppercase; color:rgba(245,239,213,.45);}

@media(max-width:900px){
  .mq-wall{ --tile:calc((100vw - 2*clamp(18px,3vw,42px) - 2*var(--mq-gap)) / 3); }
}
@media(max-width:560px){
  .mq-wall{ --tile:calc((100vw - 2*clamp(18px,3vw,42px) - 1*var(--mq-gap)) / 2); }
}

/* 8 · CURSOR PUNTO + RIPPLE */
*{cursor:none !important;}
.cur-dot{
  position:fixed; z-index:9999; pointer-events:none;
  width:8px; height:8px; border-radius:50%;
  background:var(--crema); mix-blend-mode:difference;
  transform:translate(-50%,-50%);
  transition:width .12s, height .12s, opacity .1s;
}
.cur-dot.is-oculto{opacity:0;}
.cur-ripple{
  position:fixed; z-index:9998; pointer-events:none;
  width:0; height:0; border-radius:50%;
  border-style:solid; border-color:var(--crema); border-width:0.5px;
  mix-blend-mode:difference;
  transform:translate(-50%,-50%);
  animation:ripple .55s ease-out forwards;
}
/* ya no se apaga con opacity: se abre al triple (180px) y desaparece
   adelgazando el borde hasta 0 en vez de esfumarse */
@keyframes ripple{
  0%  {width:0; height:0; border-width:1.5px; opacity:.7;}
  100%{width:120px; height:120px; border-width:0; opacity:.7;}
}
@media(pointer:coarse){
  *{cursor:auto !important;}
  .cur-dot,.cur-ripple{display:none;}
}

/* CTA DE CONTACTO — panel compartido, lo inyecta layout.js en toda página
   que lo cargue (antes vivía duplicado dentro de cada ficha, como sección
   fija .pw-cta al final del scroll). Dos capas, ambas fijas a pantalla
   completa y ambas entran deslizándose desde abajo — .pw-cta primero (chips
   de "Necesito"), .pw-form arriba de esa al confirmar (datos de contacto). */
.pw-cta{
  position:fixed; inset:0; z-index:105; overflow-y:auto;
  transform:translateY(100%); transition:transform .55s cubic-bezier(.22,1,.36,1);
  pointer-events:none;
  background:var(--papel); color:var(--tinta); text-align:center;
  min-height:100vh; min-height:100svh;
  display:flex; flex-direction:column; justify-content:center;
  padding:clamp(60px,10vh,120px) clamp(18px,4vw,60px);
}
.pw-cta.is-open{transform:none; pointer-events:auto;}

.pw-cta-titulo{
  position:relative; display:inline-block;
  font-family:'Playfair Display', serif; font-weight:400;
  font-size:clamp(38px,7vw,86px); line-height:1;
  margin-bottom:clamp(46px,7vh,80px);
}
/* "o qué?" cuelga del final del título */
.pw-cta-oque{
  position:absolute; left:77%; bottom:-.72em; transform:translateX(-50%);
  font-style:italic; font-size:.44em; color:var(--acento); white-space:nowrap;
}

/* barra: la frase se va armando acá */
.pw-barra{
  display:flex; align-items:center; gap:12px; flex-wrap:wrap;
  width:600px; max-width:92vw; margin:0 auto clamp(26px,4vh,44px);
  background:#fff; border-radius:34px; padding:12px 12px 12px clamp(18px,2.4vw,30px);
  box-shadow:0 2px 14px rgba(22,21,15,.07);
  text-align:left;
}
.pw-barra-label{font-family:'owners-wide', serif; font-size:clamp(15px,1.5vw,19px); color:var(--tinta-70);}
/* "+" junto a "Necesito": invita a elegir la primera categoría, y se esconde
   apenas hay una elegida — la barra ya no está vacía. */
.pw-barra-plus{
  display:flex; align-items:center; justify-content:center; flex-shrink:0;
  width:32px; height:32px; border-radius:9px;
  background:rgba(22,21,15,.06); color:var(--tinta-70); font-size:16px; line-height:1;
  transition:opacity .2s ease, transform .2s ease, width .2s ease, margin .2s ease;
}
.pw-barra-plus.is-oculto{
  opacity:0; transform:scale(.6); width:0; margin-left:-12px; pointer-events:none;
}
.pw-barra-sel{display:flex; align-items:center; gap:8px; flex-wrap:wrap; flex:1; min-height:36px;}
.pw-barra-chip{
  display:inline-flex; align-items:center; gap:8px;
  font-family:'owners-wide', sans-serif; font-weight:400; font-size:11px; letter-spacing:.04em;
  color:var(--tinta); background:rgba(207,122,52,.14); border:1px solid rgba(207,122,52,.34);
  border-radius:20px; padding:7px 13px; cursor:pointer;
  transition:background-color .2s ease;
  animation:pw-chip-in .28s cubic-bezier(.22,1,.36,1);
}
.pw-barra-chip:hover{background:rgba(207,122,52,.24);}
.pw-barra-chip b{color:var(--acento); font-weight:400;}
@keyframes pw-chip-in{ from{opacity:0; transform:translateY(6px) scale(.94);} to{opacity:1; transform:none;} }

.pw-enviar{
  font-family:'owners-wide', sans-serif; font-weight:400; font-size:11px;
  letter-spacing:.12em; text-transform:uppercase;
  color:var(--tinta-45); background:rgba(22,21,15,.06); border:0; border-radius:24px;
  padding:13px 26px; cursor:not-allowed; transition:background-color .25s ease, color .25s ease;
}
.pw-enviar.is-activo{color:var(--crema); background:var(--acento); cursor:pointer;}
.pw-enviar.is-activo:hover{filter:brightness(1.08);}

/* opciones sueltas */
.pw-ops{display:flex; flex-wrap:wrap; justify-content:center; gap:clamp(8px,1.2vw,16px); max-width:1100px; margin:0 auto;}
.pw-op-chip{
  display:inline-flex; align-items:center; justify-content:space-between; gap:26px;
  font-family:'owners-wide', sans-serif; font-weight:400; font-size:12px;
  color:var(--tinta); background:#fff; border:0; border-radius:26px;
  padding:14px 20px; cursor:pointer;
  box-shadow:0 1px 8px rgba(22,21,15,.06);
  transition:transform .2s ease, box-shadow .2s ease, opacity .25s ease;
}
.pw-op-chip span{color:var(--acento); font-size:15px; line-height:1;}
.pw-op-chip:hover{transform:translateY(-2px); box-shadow:0 4px 14px rgba(22,21,15,.11);}
.pw-op-chip.is-usado{opacity:.32; pointer-events:none; box-shadow:none;}

/* ── formulario: entra desde abajo, a pantalla completa, arriba del panel
   de chips, al confirmar la selección ── */
.pw-form{
  position:fixed; inset:0; z-index:110; overflow-y:auto;
  background:var(--papel); color:var(--tinta);
  transform:translateY(100%); transition:transform .55s cubic-bezier(.22,1,.36,1);
  pointer-events:none;
}
.pw-form.is-open{transform:none; pointer-events:auto;}
.pw-form-caja{
  width:min(92vw,520px); margin:0 auto;
  min-height:100vh; min-height:100svh;
  display:flex; flex-direction:column; justify-content:center;
  padding:clamp(70px,12vh,120px) 0 clamp(40px,7vh,70px);
}
.pw-form-titulo{font-family:'Playfair Display', serif; font-size:clamp(22px,2.6vw,32px); font-weight:400;}
.pw-form-resumen{
  display:flex; align-items:center; flex-wrap:wrap; gap:8px;
  font-family:'owners-wide', sans-serif; font-size:11px; color:var(--tinta-45);
  margin:10px 0 clamp(20px,3vh,30px);
}
/* las etiquetas del resumen usan el mismo look que .pw-cat de la ficha
   ampliada (mismo borde, mono, mayúsculas) pero sin cursor de clic, acá son
   solo lectura — se define acá porque .pw-cat en sí es de ficha-ampliada */
.pw-form-resumen .pw-cat{
  font-family:'owners-wide', sans-serif; font-weight:400; font-size:10px; letter-spacing:.12em;
  text-transform:uppercase; color:var(--tinta-45); border:1px solid var(--tinta-linea);
  padding:6px 13px; cursor:default;
}
.pw-campo{display:block; margin-bottom:15px;}
.pw-campo span{
  display:block; font-family:'owners-wide', sans-serif; font-size:10px; letter-spacing:.12em;
  text-transform:uppercase; color:var(--tinta-45); margin-bottom:6px;
}
.pw-campo input{
  width:100%; font-family:'Playfair Display', serif; font-size:15px; color:var(--tinta);
  background:#fff; border:1px solid var(--tinta-linea); border-radius:8px; padding:12px 14px;
  transition:border-color .2s ease;
}
.pw-campo input:focus{outline:none; border-color:var(--acento);}
.pw-form-btn{
  width:100%; margin-top:10px;
  font-family:'owners-wide', sans-serif; font-weight:400; font-size:11px;
  letter-spacing:.12em; text-transform:uppercase;
  color:var(--crema); background:var(--acento); border:0; border-radius:26px;
  padding:14px; cursor:pointer; transition:filter .2s ease;
}
.pw-form-btn:hover{filter:brightness(1.08);}
.pw-form-cerrar{
  position:fixed; top:clamp(18px,3vh,30px); right:clamp(18px,4vw,50px); z-index:111;
  font-family:'owners-wide', sans-serif; font-size:11px; letter-spacing:.12em;
  color:var(--tinta-45); background:none; border:0; cursor:pointer; transition:color .2s ease;
}
.pw-form-cerrar:hover{color:var(--tinta);}

@media(prefers-reduced-motion:reduce){
  .pw-barra-chip{animation:none;}
  .pw-cta, .pw-form{transition:none;}
}

/* 10 · GALERÍA WEBGL (panel de "Producción audiovisual", dentro de
   #scVidPanel en index.html). Plano curvo con scroll infinito, three.js +
   GSAP — ver avGaleria en intro.js. El panel es position:fixed inset:0
   (.sc-panel), así que el canvas simplemente lo llena entero; los gestos
   de arrastre/rueda se atan al propio panel, no a la ventana, para que
   solo respondan mientras está abierto. */
.sr-only{position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0,0,0,0);}

.sc-vidpanel .sc-panel-top{z-index:40;} /* por encima del canvas */
.av-gl{position:absolute; inset:0; width:100%; height:100%; display:block; cursor:grab;}
.sc-vidpanel.is-dragging .av-gl{cursor:grabbing;}

/* compartido con .wb-rec-dot (bloque 11): el parpadeo del punto "REC" */
@keyframes av-intro-parpadeo{ 0%,100%{opacity:1;} 50%{opacity:.2;} }

/* 11 · PANEL DE DISEÑO WEB (panel de "Diseño digital", dentro de #scWebPanel
   en intro-scroll.html). Mismo sc-panel que la vitrina audiovisual y misma
   apertura en clip-path desde el cuadro central, pero mucho más simple: una
   pantalla de apertura con el título y, debajo, la pila de portadas de los
   proyectos web. Es su propio contenedor de scroll (overflow-y:auto), así
   que el sticky de las tarjetas se mide contra ESE scroll, no contra window.
   Prototipo original: test-intro-web.html. */
.sc-webpanel{overflow-y:auto; overflow-x:hidden; -webkit-overflow-scrolling:touch; overscroll-behavior:contain;}
.sc-webpanel .sc-panel-top{z-index:40;}

/* ── pantalla de apertura ─────────────────────────────────── */
/* .wb-cover es la misma pantalla usada como tapa dentro del carrusel de
   fichas (#scPanelIntro): cubre el panel al abrir y se desvanece con el
   primer gesto. Queda por debajo de .sc-panel-top (z-index:30) para que
   CERRAR siga a mano, y por encima del carrusel (z-index hasta 20). */
.wb-cover{
  position:absolute; inset:0; z-index:25; background:var(--negro);
  opacity:0; visibility:hidden; pointer-events:none;
  transition:opacity .5s ease, visibility 0s linear .5s;
}
.wb-cover.is-on{opacity:1; visibility:visible; pointer-events:auto; transition:opacity .5s ease;}
.wb-cover .wb-hero{height:100%;}

.wb-hero{
  position:relative; min-height:100%;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:22px;
  background:var(--negro); padding:0 24px;
}
.wb-rec{display:flex; align-items:center; gap:8px; font-size:11px; letter-spacing:.3em; color:#E5493A;}
.wb-rec-dot{width:8px; height:8px; border-radius:50%; background:#E5493A; animation:av-intro-parpadeo 1.1s ease-in-out infinite;}
.wb-title{
  font-family:'Playfair Display',serif; font-weight:400;
  font-size:clamp(30px,6vw,84px); line-height:1.08; text-align:center;
  letter-spacing:.03em; text-transform:uppercase;
}
.wb-sub{
  font-size:11px; letter-spacing:.28em; text-transform:uppercase;
  color:var(--crema-45); text-align:center;
}
.wb-scroll{
  position:absolute; bottom:34px; left:50%; transform:translateX(-50%);
  font-size:10px; letter-spacing:.24em; text-transform:uppercase; color:var(--crema-45);
  opacity:0; animation:wb-flecha 2s ease-in-out infinite;
}
@keyframes wb-flecha{ 0%,100%{transform:translate(-50%,0);} 50%{transform:translate(-50%,6px);} }
.wb-brk{position:absolute; width:22px; height:22px; opacity:0; transform:scale(0);}
/* cada esquina crece desde su propio vértice: el encuadre se dibuja solo */
.wb-brk.tl{top:32px; left:32px; border-top:1px solid rgba(245,239,213,.85); border-left:1px solid rgba(245,239,213,.85); transform-origin:top left;}
.wb-brk.tr{top:32px; right:32px; border-top:1px solid rgba(245,239,213,.85); border-right:1px solid rgba(245,239,213,.85); transform-origin:top right;}
/* adentro de un panel, las esquinas de arriba bajan para no chocar con la
   barra de CERRAR / el conteo de proyectos (.sc-panel-top) */
.sc-webpanel .wb-brk.tl, .sc-fotopanel .wb-brk.tl, .wb-cover .wb-brk.tl,
.sc-webpanel .wb-brk.tr, .sc-fotopanel .wb-brk.tr, .wb-cover .wb-brk.tr{top:70px;}
.wb-brk.bl{bottom:32px; left:32px; border-bottom:1px solid rgba(245,239,213,.85); border-left:1px solid rgba(245,239,213,.85); transform-origin:bottom left;}
.wb-brk.br{bottom:32px; right:32px; border-bottom:1px solid rgba(245,239,213,.85); border-right:1px solid rgba(245,239,213,.85); transform-origin:bottom right;}

/* ENTRADA ESCALONADA de la pantalla de apertura. Antes solo estaban en
   tiempos el título y el subtítulo: las esquinas y el "Scroll ↓" aparecían
   de una junto con la máscara, y ese golpe simultáneo era buena parte de
   lo que se sentía abrupto. Ahora entra en orden, como se arma un plano:
   primero el encuadre (.2s), después REC / título / subtítulo (.35 / .55 /
   .75s, los de siempre) y último la invitación a scrollear (.95s).
   .wb-scroll lleva dos animaciones porque wb-flecha ya le ocupa el
   transform: la entrada solo toca opacity y así no se pisan. */
.sc-webpanel.is-open .wb-brk,
.sc-fotopanel.is-open .wb-brk,
.wb-cover.is-on .wb-brk{animation:wb-esquina .55s cubic-bezier(.16,1,.3,1) .2s forwards;}
@keyframes wb-esquina{ to{opacity:1; transform:none;} }
/* entrada al abrir el panel: aparece el título, después el subtítulo */
.wb-in{opacity:0; transform:translateY(12px);}
.sc-webpanel.is-open .wb-in,
.sc-fotopanel.is-open .wb-in,
.wb-cover.is-on .wb-in{animation:wb-entrada .8s cubic-bezier(.22,1,.36,1) forwards;}
.wb-in--1{animation-delay:.35s;}
.wb-in--2{animation-delay:.55s;}
.wb-in--3{animation-delay:.75s;}
@keyframes wb-entrada{ to{opacity:1; transform:none;} }
.sc-webpanel.is-open .wb-scroll,
.sc-fotopanel.is-open .wb-scroll,
.wb-cover.is-on .wb-scroll{animation:wb-flecha 2s ease-in-out infinite, wb-aparecer .5s ease .95s forwards;}
@keyframes wb-aparecer{ to{opacity:1;} }

/* ── pila de tarjetas ─────────────────────────────────────── */
/* sticky escalonado por --i + reveal con IntersectionObserver, en paleta
   oscura (mismo mecanismo que .pw-stk de la ficha ampliada) */
.wb-sec{background:var(--negro); padding:clamp(60px,10vh,120px) clamp(20px,5vw,60px);}
.wb-sec-titulo{
  max-width:900px; margin:0 auto clamp(28px,5vh,56px);
  font-size:11px; letter-spacing:.28em; text-transform:uppercase; color:var(--crema-45);
}
.wb-stk{max-width:900px; margin:0 auto;}
.wb-slot{min-height:60vh;}
.wb-slot:last-child{min-height:auto;}
.wb-card{
  position:sticky; top:calc(60px + var(--i,0) * 28px);
  display:grid; grid-template-columns:1fr 1fr;
  background:var(--carbon); border-radius:6px; overflow:hidden;
  box-shadow:0 -2px 26px rgba(0,0,0,.5); border:1px solid var(--linea);
  transform:translateY(30px); opacity:0;
  transition:transform .65s cubic-bezier(.22,1,.36,1), opacity .5s;
}
.wb-card.is-in{transform:none; opacity:1;}
.wb-img{width:100%; height:100%; object-fit:cover; min-height:200px;}
.wb-texto{padding:clamp(20px,3vw,40px); display:flex; flex-direction:column; justify-content:center; gap:12px;}
.wb-cli{font-size:10px; letter-spacing:.22em; text-transform:uppercase; color:var(--crema-45);}
.wb-h{font-size:clamp(18px,1.8vw,26px); font-weight:400;}
.wb-p{font-size:12px; line-height:1.7; color:var(--crema-70);}
.wb-link{
  align-self:flex-start; margin-top:8px;
  font-size:10px; letter-spacing:.14em; text-transform:uppercase; color:var(--crema-45);
  border-bottom:1px solid transparent; padding-bottom:2px;
  transition:color .2s, border-color .2s;
}
.wb-link:hover{color:var(--crema); border-color:var(--crema-45);}
.wb-vacio{
  max-width:900px; margin:0 auto; text-align:center;
  font-size:12px; letter-spacing:.14em; color:var(--crema-45);
}

@media(max-width:820px){
  .wb-card{grid-template-columns:1fr; position:relative; top:auto;}
  .wb-slot{min-height:auto; margin-bottom:24px;}
  .wb-img{aspect-ratio:16/10; min-height:auto;}
}
@media(prefers-reduced-motion:reduce){
  /* ojo: acá hay que devolver opacity/transform a mano, porque el estado
     de partida de la entrada escalonada los deja invisibles y sin la
     animación que los trae de vuelta se quedarían así */
  .wb-rec-dot{animation:none;}
  .sc-webpanel.is-open .wb-scroll,
  .sc-fotopanel.is-open .wb-scroll,
  .wb-cover.is-on .wb-scroll,
  .wb-scroll{animation:none; opacity:1;}
  .wb-in, .wb-brk{opacity:1; transform:none;}
  .wb-card{transform:none !important; opacity:1 !important; transition:none !important;}
}

/* 12 · PANEL DE FOTOGRAFÍA (dentro de #scFotoPanel en intro-scroll.html).
   Mismo sc-panel y misma apertura en clip-path que los otros dos paneles
   propios: arranca con la pantalla de apertura (.wb-hero, bloque 11) y
   debajo, en vez del carrusel de fichas, va la galería masonry —
   column-count + break-inside, sin recortar ni deformar ninguna foto.
   Prototipo original: demo-masonry-galeria.html. */
.sc-fotopanel{overflow-y:auto; overflow-x:hidden; -webkit-overflow-scrolling:touch; overscroll-behavior:contain;}
.sc-fotopanel .sc-panel-top{z-index:40;}

.mg-galeria{--gap:clamp(10px,1.6vw,20px); column-count:1; column-gap:var(--gap); max-width:1600px; margin:0 auto;}
@media(min-width:600px){ .mg-galeria{column-count:2;} }
@media(min-width:900px){ .mg-galeria{column-count:3;} }
@media(min-width:1200px){ .mg-galeria{column-count:4;} }

.mg-item{
  display:block; break-inside:avoid; -webkit-column-break-inside:avoid; page-break-inside:avoid;
  margin:0 0 var(--gap); border-radius:3px; overflow:hidden; cursor:pointer;
}
.mg-item img, .mg-item video{
  display:block; width:100%; height:auto;   /* conserva el aspect-ratio real */
  opacity:0; filter:blur(10px) brightness(1.3);
  transition:opacity .9s ease, filter .9s ease, transform .45s ease;
  transition-delay:.15s;                    /* al desaparecer, fuera del centro */
}
.mg-item.is-visible img, .mg-item.is-visible video{opacity:1; filter:blur(0) brightness(1); transition-delay:0s;}
/* realce de foco: las demás se atenúan solo con el cursor sobre una
   miniatura de verdad (no en los huecos del masonry) */
.mg-galeria:has(.mg-item:hover) .mg-item.is-visible:not(:hover) img,
.mg-galeria:has(.mg-item:hover) .mg-item.is-visible:not(:hover) video{
  filter:blur(2.5px) brightness(.75) saturate(.85); opacity:.6; transition-delay:.15s;
}
.mg-galeria .mg-item:hover img, .mg-galeria .mg-item:hover video{filter:none; opacity:1; transform:scale(1.045); transition-delay:0s;}
.mg-pie{
  display:flex; justify-content:space-between; gap:12px; padding:8px 2px 0;
  font-size:10px; letter-spacing:.14em; text-transform:uppercase; color:var(--crema-45);
}

/* lightbox: por encima del panel (sc-panel va en z-index:60) */
.mg-lightbox{
  position:fixed; inset:0; z-index:70; background:rgba(10,10,8,.94);
  display:flex; align-items:center; justify-content:center; padding:clamp(20px,5vw,60px);
  opacity:0; pointer-events:none; transition:opacity .3s ease;
}
.mg-lightbox.is-open{opacity:1; pointer-events:auto;}
.mg-lightbox-fig{max-width:90vw; max-height:88vh; display:flex; transform:scale(.96); transition:transform .3s ease;}
.mg-lightbox.is-open .mg-lightbox-fig{transform:scale(1);}
.mg-lightbox-fig img{
  max-width:90vw; max-height:88vh; width:auto; height:auto;
  box-shadow:0 24px 70px rgba(0,0,0,.55);
}
.mg-lightbox-cerrar{
  position:fixed; top:clamp(16px,3vw,32px); right:clamp(16px,3vw,32px);
  font-family:'IBM Plex Mono',monospace; font-size:11px; letter-spacing:.12em; text-transform:uppercase;
  color:var(--crema-70); background:transparent; border:1px solid rgba(245,239,213,.22);
  padding:8px 14px; cursor:pointer; transition:border-color .2s, color .2s;
}
.mg-lightbox-cerrar:hover{border-color:var(--crema); color:var(--crema);}

@media(prefers-reduced-motion:reduce){
  .mg-item img, .mg-item video{transition:none !important; opacity:1 !important; filter:none !important;}
}


/* ─────────────────────────────────────────────────────────────
   14 · FICHA AMPLIADA — plantilla identidad de marca / diseño digital
   (proyectos/plantilla-marca-digital.html)

   Página de SCROLL LARGO (hero → herramientas → timeline → destacados
   → guía → foto → cierre). El body usa .pw-body con overflow-x:clip y
   no hidden a propósito: clip recorta igual, pero hidden convertiría al
   body en contenedor de scroll y eso desactiva el position:sticky que
   usan las tarjetas escalonadas de la guía y la galería.

   Prefijo pw-*. Depende de Adobe Fonts (owners-wide, cargada por <link>
   a use.typekit.net en el propio HTML) además de Playfair Display /
   IBM Plex Mono. ── */

.pw-body{
  background:var(--papel); color:var(--tinta);
  font-family:'Playfair Display', serif; line-height:1.5;
  overflow-x:clip;
}
/* ficha compañera de fotografía: mismo motor, tema invertido para
   diferenciarla de la digital (que se queda en el claro de siempre). Solo
   redefine los tokens de PÁGINA (papel/tinta) — los marcos con negro/crema
   fijos (hero, destacados, timeline, carrusel) son acentos ya pensados para
   funcionar solos y quedan iguales en las dos. */
.pw-body--foto{
  --papel: var(--negro);
  --tinta: var(--crema);
  --tinta-70: var(--crema-70);
  --tinta-45: var(--crema-45);
  --tinta-linea: var(--linea);
}

/* ── hero: categorías, título, año, portada ── */
.pw-hero{padding: clamp(34px,6vh,70px) clamp(18px,4vw,60px) 0;}

.pw-cats{display:flex; justify-content:center; flex-wrap:wrap; gap:9px; margin-bottom:clamp(22px,3.5vh,36px);}
.pw-cat{
  font-family:'owners-wide', sans-serif; font-weight:400; font-size:10px; letter-spacing:.12em;
  text-transform:uppercase; color:var(--tinta-45);
  background:transparent; border:1px solid var(--tinta-linea);
  padding:6px 13px; cursor:pointer;
  transition:border-color .2s ease, color .2s ease;
}
.pw-cat:hover{border-color:var(--tinta-45); color:var(--tinta-70);}
.pw-cat.is-on{border-color:var(--acento); color:var(--acento);}

.pw-titulo{
  font-family:'owners-wide', sans-serif; font-weight:800; text-align:center; text-transform:uppercase;
  font-size:clamp(34px,6.4vw,84px); letter-spacing:.01em;
}
.pw-anio{
  font-family:'owners-wide', sans-serif; font-weight:400; text-align:center; font-size:11px; letter-spacing:.2em; color:var(--tinta-45);
  margin-top:8px; margin-bottom:clamp(30px,5vh,52px);
}

.pw-frame{position:relative; background:var(--negro); padding:clamp(52px,11.4vw,160px); border-radius:18px;}
.pw-frame-in{
  position:relative;
  background:var(--crema); min-height:clamp(240px,42vw,540px); overflow:hidden; border-radius:10px;
  display:flex; align-items:center; justify-content:center; text-align:center;
  font-family:'owners-wide', sans-serif; font-weight:400; font-size:13px; letter-spacing:.1em;
  text-transform:uppercase; color:var(--tinta-45); padding:20px;
}
.pw-frame-in:has(img){padding:0;}
/* absolute + inset:0 en vez de width/height:100%: así la imagen siempre
   llena el recuadro exacto sin depender de cómo el flex resuelva el alto,
   que es lo que dejaba ver líneas del fondo en ciertos anchos */
.pw-frame-in img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover; border-radius:inherit;}
.pw-brk{position:absolute; width:16px; height:16px; border:1px solid var(--crema-linea);}
.pw-brk.tl{top:5px; left:5px; border-right:none; border-bottom:none;}
.pw-brk.tr{top:5px; right:5px; border-left:none; border-bottom:none;}
.pw-brk.bl{bottom:5px; left:5px; border-right:none; border-top:none;}
.pw-brk.br{bottom:5px; right:5px; border-left:none; border-top:none;}

/* ── rótulo compartido por las secciones de abajo ── */
.pw-kicker{
  font-family:'owners-wide', sans-serif; font-weight:400; display:flex; align-items:center; gap:10px;
  font-size:11px; letter-spacing:.22em; text-transform:uppercase;
  color:var(--tinta-45); margin-bottom:clamp(22px,3.5vh,34px);
}
.pw-kicker i{width:22px; height:1px; background:var(--acento); display:inline-block; font-style:normal;}
.pw-time .pw-kicker{color:var(--crema-45);}

/* ── herramientas: marquee infinito (mismo mecanismo que demo-marquee-infinito.html) ── */
.pw-herr{
  padding: clamp(50px,8vh,90px) clamp(18px,4vw,60px);
  margin-top:clamp(50px,8vh,90px);
  border-top:1px solid var(--tinta-linea); border-bottom:1px solid var(--tinta-linea);
}
.pw-mq-wrap{overflow:hidden;}
.pw-mq-track{display:flex; width:max-content; animation:pw-scroll 42s linear infinite; will-change:transform;}
.pw-mq-item{
  font-family:'Playfair Display', serif; font-weight:400; font-size:clamp(22px,3.8vw,46px); white-space:nowrap;
  padding:0 clamp(16px,2.2vw,30px);
}
.pw-mq-sep{font-family:'Playfair Display', serif; font-weight:400; font-size:clamp(22px,3.8vw,46px); color:var(--acento); opacity:.6;}
@keyframes pw-scroll{ from{transform:translateX(0);} to{transform:translateX(-50%);} }
@media (prefers-reduced-motion: reduce){ .pw-mq-track{animation:none;} }

/* ── timeline: grupos de tarjetas + barra con marcas ── */
.pw-time{
  background:var(--negro); color:var(--crema);
  padding:clamp(46px,7vh,80px) clamp(18px,4vw,60px) clamp(60px,9vh,100px);
}
.pw-time-grupos{display:flex; gap:clamp(8px,1.2vw,16px); overflow-x:auto; padding:0 25% 10px; scrollbar-width:none;}
.pw-time-grupos::-webkit-scrollbar{display:none;}
.pw-time-grupo{
  display:flex; gap:clamp(5px,0.8vw,10px); flex-shrink:0;
  padding:14px; border:1px solid transparent;
  transition:border-color .25s ease;
}
.pw-time-grupo.is-multi{border-color:rgba(207,122,52,.35);}
.pw-time-grupo.is-hover{border-color:var(--acento);}
.pw-time-card{width:clamp(290px,31vw,500px);}
.pw-time-card-img{
  position:relative; aspect-ratio:4/3; background:var(--crema); overflow:hidden;
  display:flex; align-items:center; justify-content:center; text-align:center;
  font-family:'owners-wide', sans-serif; font-weight:400; font-size:11px; letter-spacing:.1em;
  text-transform:uppercase; color:var(--tinta-45); padding:14px;
}
.pw-time-card-img:has(img){padding:0;}
.pw-time-card-img img{width:100%; height:100%; object-fit:cover;}
.pw-time-card-tag{position:absolute; top:8px; right:10px; font-family:'owners-wide', sans-serif; font-weight:400; font-size:10px; color:var(--tinta-45);}
.pw-time-card-pie{margin-top:9px; font-family:'owners-wide', sans-serif; font-weight:400; font-size:11px; color:var(--crema-45);}
.pw-time-card-pie b{color:var(--crema); font-weight:800;}

.pw-time-bar{
  position:relative; width:50%; margin:clamp(46px,7vh,78px) auto 0; padding:0 4px;
}
.pw-time-progreso{height:2px; background:var(--crema-linea); margin-bottom:14px;}
.pw-time-progreso-fill{height:100%; width:0%; background:var(--acento); transition:width .08s linear;}
.pw-time-linea{height:1px; background:var(--crema-linea);}
.pw-time-marcas{position:absolute; inset:0; display:flex; justify-content:space-between;}
.pw-time-marca{position:relative; display:flex; justify-content:center;}
.pw-time-marca-tick{width:1px; height:12px; background:var(--crema-linea); transition:background .25s ease;}
.pw-time-marca-label{
  position:absolute; top:18px; white-space:nowrap;
  font-family:'owners-wide', sans-serif; font-weight:400; font-size:10px; letter-spacing:.12em; text-transform:uppercase;
  color:var(--crema-45); padding:4px 10px;
  transition:transform .25s ease, background-color .25s ease, color .25s ease;
}
.pw-time-marca.is-hover .pw-time-marca-tick{background:var(--acento);}
.pw-time-marca.is-hover .pw-time-marca-label{background:var(--acento); color:var(--negro); transform:translateY(6px);}

/* ── destacados ── */
.pw-dest{padding: clamp(60px,9vh,110px) clamp(18px,4vw,60px) clamp(70px,10vh,120px);}
.pw-dest .pw-kicker{margin-bottom:14px;}
.pw-dest-titulo{
  font-family:'Playfair Display', serif; font-weight:400; font-size:clamp(24px,3.2vw,42px); font-style:italic; line-height:1.22;
  margin-bottom:clamp(30px,5vh,54px);
}
.pw-dest-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); gap:clamp(18px,2.6vw,32px);}
.pw-dest-frame{background:var(--negro); padding:clamp(12px,2.2vw,28px);}
.pw-dest-in{
  position:relative;
  background:var(--crema); aspect-ratio:4/3; overflow:hidden;
  display:flex; align-items:center; justify-content:center;
  font-family:'owners-wide', sans-serif; font-weight:400; font-size:12px; letter-spacing:.1em;
  text-transform:uppercase; color:var(--tinta-45);
}
.pw-dest-in img, .pw-dest-in video{position:absolute; inset:0; width:100%; height:100%; object-fit:cover;}
.pw-dest-pie{margin-top:10px; font-family:'owners-wide', sans-serif; font-weight:400; font-size:12px; color:var(--tinta-45);}
.pw-dest-pie b{color:var(--tinta); font-weight:800;}

/* ── slider antes/después arrastrable (prefijo pw-dest-sl-),
   en una columna aparte debajo de la grilla de destacados ── */
.pw-dest-sl{margin-top:clamp(32px,5vh,52px);}
.pw-sl-wrap{
  position:relative; overflow:hidden; cursor:ew-resize;
  width:100%; aspect-ratio:16/10; border-radius:6px;
  touch-action:pan-y pinch-zoom; user-select:none;
}
.pw-sl-img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover; pointer-events:none;}
.pw-sl-clip{clip-path:inset(0 0 0 50%); z-index:1;}
.pw-sl-linea{
  position:absolute; top:0; bottom:0; left:50%; width:2px;
  background:var(--papel); z-index:2; transform:translateX(-50%); pointer-events:none;
}
.pw-sl-asa{
  position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);
  width:40px; height:40px; border-radius:50%; background:var(--papel);
  display:flex; align-items:center; justify-content:center;
  box-shadow:0 2px 8px rgba(0,0,0,.18);
}
.pw-sl-flechas{font-size:10px; letter-spacing:2px; color:var(--tinta-70);}
.pw-sl-et{
  position:absolute; bottom:16px; z-index:3; pointer-events:none;
  font-family:'owners-wide', sans-serif; font-size:11px; letter-spacing:.12em; text-transform:uppercase;
  color:var(--papel); background:rgba(10,10,8,.5); padding:5px 12px;
}
.pw-sl-et--a{left:16px;}
.pw-sl-et--d{right:16px;}

/* ── tarjetas de imagen clicables ── */
.pw-time-card-img.pw-clicable, .pw-dest-in.pw-clicable{cursor:pointer; transition:filter .2s ease;}
.pw-time-card-img.pw-clicable:hover, .pw-dest-in.pw-clicable:hover{filter:brightness(.94);}

/* ── modo cine: overlay a pantalla completa, se cierra con la X o clic afuera ── */
.pw-cine{
  position:fixed; inset:0; z-index:100; display:flex; align-items:center; justify-content:center;
  background:rgba(10,10,8,.95); opacity:0; pointer-events:none;
  transition:opacity .3s ease;
}
.pw-cine.is-open{opacity:1; pointer-events:auto;}
.pw-cine-fig{max-width:88vw; max-height:82vh;}
.pw-cine-fig img, .pw-cine-fig video{display:block; max-width:88vw; max-height:82vh; width:auto; height:auto;}
.pw-cine-fig.is-placeholder{
  width:min(88vw,700px); aspect-ratio:4/3; background:var(--crema); color:var(--tinta-45);
  font-family:'owners-wide', sans-serif; font-weight:400; font-size:14px; letter-spacing:.1em; text-transform:uppercase;
  display:flex; align-items:center; justify-content:center; text-align:center; padding:20px;
}
.pw-cine-cerrar{
  position:absolute; top:24px; right:clamp(18px,4vw,60px); z-index:1;
  background:none; border:0; color:var(--crema-70); font-size:11px; letter-spacing:.12em;
  cursor:pointer; transition:color .2s ease;
}
.pw-cine-cerrar:hover{color:var(--crema);}

/* ── fotografía y video: texto (izq.) + carrusel arrastrable (der.) ── */
.pw-foto{
  background:#232220; color:var(--crema);
  display:grid; grid-template-columns:1fr 1fr; gap:clamp(24px,4vw,50px); align-items:center;
  padding:clamp(46px,7vh,80px) 0 clamp(46px,7vh,80px) clamp(18px,4vw,60px);
  overflow:hidden;
}
.pw-foto-txt{max-width:560px;}
.pw-foto .pw-kicker{color:var(--crema-45); margin-bottom:clamp(16px,2.4vh,26px);}
.pw-foto-titulo{
  font-family:'Playfair Display', serif; font-weight:400;
  font-size:clamp(26px,3.4vw,46px); line-height:1.2;
}
.pw-foto-pregunta{
  font-family:'Playfair Display', serif; font-weight:400;
  font-size:clamp(26px,3.4vw,46px); line-height:1.2;
  text-align:right; margin-top:clamp(20px,3.4vh,38px);
}
.pw-foto-cta{display:flex; justify-content:flex-end; margin-top:14px;}
.pw-foto-btn{
  display:inline-block; text-decoration:none;
  font-family:'owners-wide', sans-serif; font-weight:400; font-size:11px;
  letter-spacing:.1em; text-transform:uppercase;
  color:var(--crema); background:var(--acento); border:0; border-radius:22px;
  padding:12px 24px; cursor:pointer; transition:filter .2s ease, transform .2s ease;
}
.pw-foto-btn:hover{filter:brightness(1.1); transform:translateY(-1px);}

/* el carrusel sangra hasta el borde derecho: la última tarjeta se corta a
   propósito, para que se lea que la tira sigue */
.pw-foto-carr{
  display:flex; gap:clamp(10px,1.5vw,18px);
  overflow-x:auto; scrollbar-width:none; cursor:grab;
  padding-right:clamp(18px,4vw,60px);
}
.pw-foto-carr::-webkit-scrollbar{display:none;}
.pw-foto-carr.is-dragging{cursor:grabbing;}
.pw-foto-card{
  position:relative;
  flex:0 0 auto; width:clamp(220px,24vw,380px); aspect-ratio:3/2;
  background:#C4D947; border-radius:8px; overflow:hidden;
  display:flex; align-items:center; justify-content:center; text-align:center; padding:12px;
  font-family:'owners-wide', sans-serif; font-weight:400; font-size:10px; letter-spacing:.1em;
  text-transform:uppercase; color:rgba(10,10,8,.45);
  transition:filter .2s ease, transform .25s ease;
}
.pw-foto-card img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover; pointer-events:none;}
.pw-foto-carr:not(.is-dragging) .pw-foto-card:hover{filter:brightness(.92); transform:translateY(-3px);}

@media(max-width:820px){
  .pw-foto{grid-template-columns:1fr; padding-right:0;}
  .pw-foto-pregunta, .pw-foto-cta{text-align:left; justify-content:flex-start;}
}

/* ── sección extra: espacio libre con subtítulo editable, cualquier
   recurso disponible (imagen o video) — reusa la grilla de destacados ── */
.pw-extra{padding: clamp(60px,9vh,110px) clamp(18px,4vw,60px) clamp(70px,10vh,120px);}

/* ── guía: tarjetas escalonadas (izq.) + galería sticky (der.) ── */
.pw-guia{
  display:grid; grid-template-columns:1fr 1fr; gap:clamp(24px,4vw,60px);
  align-items:start; padding:clamp(60px,9vh,110px) clamp(18px,4vw,60px) clamp(80px,11vh,130px);
}

/* Las tarjetas van sueltas dentro de .pw-stk (sin slot propio): sticky solo
   dura mientras el CONTENEDOR esté en pantalla, así que compartiendo padre
   las que ya llegaron a su tope se quedan pegadas y las siguientes suben
   por encima. El desfase de --i * 48px deja asomada la cabecera de cada una. */
.pw-stk-card{
  position:sticky; top:calc(90px + var(--i,0) * 48px); z-index:var(--i,0);
  background:var(--papel); border:1px solid var(--tinta-linea); border-radius:8px; overflow:hidden;
  box-shadow:0 -4px 24px rgba(0,0,0,.16);
  transform:translateY(30px); opacity:0;
  transition:transform .65s cubic-bezier(.22,1,.36,1), opacity .5s;
}
/* aire tras cada tarjeta = tramo de scroll antes de que la siguiente la alcance */
.pw-stk-card{margin-bottom:34vh;}
.pw-stk-card:last-of-type{margin-bottom:0;}
/* cola dentro del contenedor: una sticky se despega cuando el borde inferior
   de su contenedor la alcanza. Sin este bloque, al pegarse la última tarjeta
   el contenedor ya se terminó y despega a las anteriores — las cabeceras
   apiladas se irían con el scroll en vez de quedarse arriba. */
.pw-stk-cola{height:60vh;}
.pw-stk-card.is-in{transform:none; opacity:1;}
.pw-stk-head{
  background:var(--negro); color:var(--crema); padding:15px 20px; display:flex; align-items:center; gap:12px;
  font-family:'owners-wide', sans-serif; font-weight:400; font-size:11px; letter-spacing:.16em; text-transform:uppercase;
}
.pw-stk-head i{width:20px; height:1px; background:var(--acento); display:inline-block;}
.pw-stk-body{padding:clamp(18px,2.6vw,30px);}

/* colores */
.pw-sw-grid{display:grid; grid-template-columns:repeat(auto-fill,minmax(104px,1fr)); gap:9px; margin-bottom:16px;}
.pw-sw{border:1px solid var(--tinta-linea); border-radius:5px; overflow:hidden;}
.pw-sw-color{height:50px;}
.pw-sw-info{padding:6px 8px; background:var(--papel);}
.pw-sw-info b{display:block; font-size:10px; font-weight:500;}
.pw-sw-info span{font-size:9px; color:var(--tinta-45);}

/* tipografía */
.pw-type-row{padding:13px 0; border-top:1px solid var(--tinta-linea);}
.pw-type-row:first-child{border-top:none; padding-top:0;}
.pw-type-spec{font-size:9px; letter-spacing:.03em; color:var(--tinta-45); margin-top:6px;}

/* galería sticky */
.pw-gal-wrap{position:sticky; top:clamp(90px,10vh,130px);}
.pw-gal{column-count:3; column-gap:clamp(10px,1.6vw,18px);}
.pw-gal-item{
  display:block; break-inside:avoid; margin:0 0 clamp(10px,1.6vw,18px);
  border-radius:4px; overflow:hidden;
}
.pw-gal-item img{
  display:block; width:100%; height:auto;
  opacity:0; filter:blur(8px) brightness(1.3);
  transition:opacity .8s ease, filter .8s ease;
}
.pw-gal-item.is-in img{opacity:1; filter:blur(0) brightness(1);}

/* si la guía o la galería quedan sin nada cargado, la otra pasa a una sola
   columna en vez de dejar la mitad de la sección en blanco */
.pw-guia.is-solo{grid-template-columns:1fr;}
.pw-guia.is-solo .pw-gal-wrap{position:static;}

@media(max-width:820px){
  .pw-guia{grid-template-columns:1fr;}
  .pw-stk-card{position:relative; top:auto;}
  .pw-stk-card:not(:last-child){margin-bottom:20px;}
  .pw-gal-wrap{position:static;}
}
@media(prefers-reduced-motion:reduce){
  .pw-stk-card{transform:none !important; opacity:1 !important; transition:none !important;}
  .pw-gal-item img{transition:none !important; opacity:1 !important; filter:none !important;}
}

/* ─────────────────────────────────────────────────────────────
   15 · FICHA AUDIOVISUAL — plantilla producción audiovisual
   (proyectos/plantilla-audiovisual.html)

   Tercer motor de ficha, prefijo pv-*. Página corta: hero en video a
   pantalla completa → masonry (reusa .mg-galeria/.mg-item del bloque 12,
   sin tocarlos salvo sumarles `video` al selector de reveal) → player con
   capítulos (.pv-vid-*, más abajo) → cierre universal
   (reusa .pw-cta/.pw-form/.pw-cine del bloque 14 tal cual). ── */
.pv-hero{
  position:relative; height:100vh; height:100svh; overflow:hidden;
  display:flex; align-items:flex-end; justify-content:center;
}
.pv-hero-video{position:absolute; inset:0; width:100%; height:100%; object-fit:cover;}
.pv-hero-velo{
  position:absolute; inset:0;
  background:linear-gradient(to top, rgba(10,10,8,.8) 0%, rgba(10,10,8,.15) 55%, rgba(10,10,8,.4) 100%);
}
.pv-hero-vacio{display:none;}
/* sin video: el hero cae a un fondo papel con nota, en vez de desaparecer
   — es lo primero de la página, no puede quedar vacío del todo */
.pv-hero.is-vacio{background:var(--papel);}
.pv-hero.is-vacio .pv-hero-video, .pv-hero.is-vacio .pv-hero-velo{display:none;}
.pv-hero.is-vacio .pv-hero-vacio{
  display:block; position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);
  font-size:11px; letter-spacing:.1em; text-transform:uppercase; color:var(--tinta-45);
}
.pv-hero-contenido{position:relative; z-index:1; text-align:center; padding:0 clamp(18px,4vw,60px) clamp(50px,9vh,100px);}
/* sobre el video el texto es claro; sin video (fondo papel) vuelve al
   oscuro-sobre-claro de siempre — mismas categorías (.pw-cat), dos pieles */
.pv-hero:not(.is-vacio) .pv-hero-contenido{color:var(--crema);}
.pv-hero:not(.is-vacio) .pv-hero-contenido .pw-cat{color:var(--crema-45); border-color:var(--crema-linea);}
.pv-hero:not(.is-vacio) .pv-hero-contenido .pw-cat:hover{border-color:var(--crema-45); color:var(--crema-70);}
.pv-titulo{
  font-family:'Playfair Display', serif; font-weight:400;
  font-size:clamp(38px,7.4vw,100px); line-height:1;
  margin-top:clamp(18px,3vh,30px);
}
.pv-anio{margin-top:10px; font-size:11px; letter-spacing:.2em;}
.pv-hero:not(.is-vacio) .pv-anio{color:var(--crema-45);}
.pv-hero.is-vacio .pv-anio{color:var(--tinta-45);}

.pv-masonry{padding:clamp(50px,8vh,90px) clamp(18px,4vw,60px);}

.pv-player{padding:clamp(60px,9vh,110px) clamp(18px,4vw,60px) clamp(80px,11vh,130px);}
.pv-player .pw-kicker{justify-content:center;}

/* ── player con capítulos ──
   Venía del motor de ficha clásica (bloque 9e) con prefijo pj-vid-*.
   Al eliminarse el motor de ficha clásica quedó como componente exclusivo
   de esta plantilla, así que se renombró al prefijo de acá. Mismas reglas,
   sin cambios de diseño. */
.pv-vid-wrap{max-width:900px; margin:0 auto; border-radius:6px; overflow:hidden; background:var(--carbon);}
.pv-vid-player{width:100%; display:block;}
.pv-vid-caps{display:flex; flex-wrap:wrap; gap:8px; max-width:900px; margin:20px auto 0;}
.pv-vid-cap{
  display:flex; align-items:center; gap:10px;
  background:none; border:1px solid var(--tinta-linea);
  padding:10px 16px; cursor:pointer; border-radius:4px;
  transition:background .2s, border-color .2s, color .2s;
}
.pv-vid-cap:hover{background:rgba(22,21,15,.05); border-color:var(--tinta-45);}
.pv-vid-cap.is-on{background:var(--tinta); border-color:var(--tinta);}
.pv-vid-cap-t{font-size:11px; color:var(--tinta-45); transition:color .2s;}
.pv-vid-cap-titulo{font-size:13px; color:var(--tinta); transition:color .2s;}
.pv-vid-cap.is-on .pv-vid-cap-t,
.pv-vid-cap.is-on .pv-vid-cap-titulo{color:var(--papel);}
@media(max-width:820px){
  .pv-vid-caps{justify-content:center;}
}

@media(prefers-reduced-motion:reduce){
  .pv-hero-video{display:none;}
  .pv-hero{background:var(--negro);}
}


/* ─────────────────────────────────────────────────────────────
   16 · PÁGINA DE ERROR (404.html)

   Una sola pantalla centrada, sobre el negro y la capa de grano/luces
   que layout.js ya pone en cualquier página. Sin componentes propios:
   es lo mínimo para que un enlace roto caiga en el sitio y no en la
   pantalla en blanco del navegador. ── */
.e404{
  min-height:100svh;
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:14px; text-align:center; padding:0 clamp(18px,5vw,60px);
}
.e404-cod{font-size:10px; letter-spacing:.28em; color:var(--crema-45);}
.e404-titulo{
  font-weight:400; font-size:clamp(38px,8vw,96px); line-height:1.02;
  letter-spacing:-.01em;
}
.e404-texto{font-size:12px; letter-spacing:.04em; color:var(--crema-70); max-width:44ch;}
.e404-links{display:flex; flex-wrap:wrap; gap:22px; justify-content:center; margin-top:16px;}
.e404-links a{
  font-size:11px; letter-spacing:.16em; text-transform:uppercase; color:var(--crema-70);
  border-bottom:1px solid rgba(245,239,213,.24); padding-bottom:3px;
  transition:color .2s, border-color .2s;
}
.e404-links a:hover{color:var(--crema); border-color:var(--crema);}
