/* ==========================================================================
   SPABAR — Micro-interacciones
   Capa ADITIVA sobre main.css. No redefine ni una sola regla existente:
   todo cuelga de clases nuevas con prefijo `mi-` que estampa js/micro.js.
   Si este archivo no carga, el sitio queda exactamente como estaba.

   Reglas de la casa que se respetan aquí:
   · El botón NUNCA persigue al puntero (nada de imanes en .btn).
   · Toda entrada usa la propiedad `scale`/`clip-path`, nunca `transform`,
     allí donde GSAP ya escribe transform. Así las dos capas componen en
     vez de pisarse.
   · Nada se anima con `filter`, `box-shadow` ni `width` en scroll continuo.
   ========================================================================== */

:root{
  /* Curvas propias, hermanas de las de main.css pero con nombre propio para
     que se pueda ajustar esta capa sin tocar el sistema base. */
  --mi-e:      cubic-bezier(.16,1,.3,1);      /* expo.out — entradas       */
  --mi-e-soft: cubic-bezier(.33,1,.68,1);     /* opacidades, sin rebote    */
  --mi-e-hero: cubic-bezier(.19,1,.22,1);     /* medios, recorrido largo   */

  /* Velocidad de scroll normalizada: 0 parado, 1 embalado. La publica
     micro.js sólo cuando el valor redondeado cambia de verdad. */
  --sv: 0;

}

/* @property permite interpolar --sv: sin esto el navegador la trata como
   texto y los calc() que dependen de ella saltan a escalones. */
@supports (background: paint(x)) {
  @property --sv { syntax: "<number>"; inherits: true; initial-value: 0; }
}


/* ==========================================================================
   1 · PRIMITIVA UNIVERSAL — nada aparece de golpe
   `mi-up` es el suelo: la estampa micro.js sobre todo bloque de contenido
   que no tuviera ya una entrada propia (.r-fade, .r-clip, [data-stagger],
   [data-split]). Recorrido corto (18px) a propósito: es el relleno entre
   los gestos grandes del sistema, no un gesto más.
   ========================================================================== */
.js .mi-up{
  opacity:0;
  transform:translate3d(0,18px,0);
  transition:opacity .68s var(--mi-e-soft) var(--mi-d,0s),
             transform .9s var(--mi-e) var(--mi-d,0s)
}
.js .mi-up.is-in{opacity:1;transform:none}

/* Variante lateral para filas de lista y renglones tabulares: descubrir de
   izquierda a derecha lee como algo que se escribe, no como algo que cae. */
.js .mi-wipe{
  opacity:0;
  clip-path:inset(0 100% 0 0);
  transition:opacity .4s linear var(--mi-d,0s),
             clip-path .85s var(--mi-e) var(--mi-d,0s)
}
.js .mi-wipe.is-in{opacity:1;clip-path:inset(0 0 0 0)}


/* ==========================================================================
   2 · MEDIOS — la foto se descubre y se posa
   Dos tiempos distintos sobre el mismo elemento, y ahí está la profundidad:
   · el CONTENEDOR se descubre de abajo arriba con clip-path,
   · la IMAGEN de dentro llega desde 1.10 y se posa en 1, más lenta.

   Se usa clip-path y no un pseudoelemento-cortina porque .gal__i, .gcard y
   .gift ya tienen ::after ocupado en main.css: la máscara no compite con
   nada. Y el `round var(--mi-r)` conserva el radio real del contenedor
   durante todo el barrido — micro.js lo lee del estilo calculado.

   La imagen se mueve con la propiedad `scale`, que NO es `transform`: así el
   parallax de GSAP (yPercent) y el hover del sistema (transform:scale)
   siguen funcionando encima sin pisarse.
   ========================================================================== */
.js .mi-media{
  clip-path:inset(0 0 100% 0 round var(--mi-r,0px));
  transition:clip-path 1.15s var(--mi-e) var(--mi-d,0s)
}
.js .mi-media.is-in{clip-path:inset(0 0 0 0 round var(--mi-r,0px))}

/* El zoom sólo se estampa donde el contenedor recorta de verdad; micro.js
   comprueba el overflow antes de poner la clase, así que aquí no hace falta
   condicionar nada: si una caja no recortase, la foto se saldría. */
.js .mi-media > img,
.js .mi-media > video,
.js .mi-media > picture > img{
  scale:1.10;
  transition:scale 1.6s var(--mi-e-hero) var(--mi-d,0s)
}
.js .mi-media.is-in > img,
.js .mi-media.is-in > video,
.js .mi-media.is-in > picture > img{scale:1}


/* ==========================================================================
   3 · TIPOGRAFÍA MENOR — caracteres, no bloques
   Los titulares grandes ya se parten en palabras (data-split). Esta capa se
   ocupa de lo pequeño: antetítulos, raíles, etiquetas en versalita. Sin
   máscara (nada de overflow) para no tocar una sola caja de la maquetación.
   ========================================================================== */
.js .mi-chars .mi-c{
  display:inline-block;
  opacity:0;
  transform:translate3d(0,.45em,0);
  transition:opacity .42s linear var(--cd,0s),
             transform .72s var(--mi-e) var(--cd,0s)
}
.js .mi-chars.is-in .mi-c{opacity:1;transform:none}


/* ==========================================================================
   4 · SUPERFICIES — destello de entrada en la foto, halo bajo el cursor
   Ambos efectos viven en pseudoelementos LIBRES de sus clases (verificado uno
   a uno en main.css: .card, .loc y .hcard no usan ninguno; .card__media,
   .man__img, .figure y .gal__i tienen el ::before libre).
   ========================================================================== */

/* 4a · Barrido de luz, una sola vez, al entrar en pantalla.
   Va sobre la FOTO, no sobre la tarjeta: un destello blanco sobre una tarjeta
   blanca no se ve — sobre la imagen sí, y es donde tiene sentido, porque lee
   como el reflejo de una superficie satinada al girarla.
   Arranca .3 s después de la máscara para no barrer una foto todavía tapada. */
.js .mi-sheen{position:relative;overflow:hidden}
.js .mi-sheen::before{
  content:"";position:absolute;inset:-1px;z-index:3;pointer-events:none;
  border-radius:inherit;opacity:0;
  background:linear-gradient(100deg,
    transparent 32%,
    color-mix(in oklab, var(--white), transparent 94%) 43%,
    color-mix(in oklab, var(--white), transparent 87%) 50%,
    color-mix(in oklab, var(--white), transparent 94%) 57%,
    transparent 68%);
  filter:blur(12px);
  transform:translate3d(-118%,0,0)
}
/* Tercera version, y la buena. Las dos anteriores fallaban por lo mismo: se
   VEIA la banda. Con un pico al 38 % de blanco y `expo.out` el reflejo salia
   disparado y frenaba en seco a la vista — leia como un flash de plastico
   barato pasando por encima de la foto, no como luz.

   Ahora el destello es una insinuacion:
   · pico al 13 % de blanco (era 38 %) y bordes al 6 % — nunca llega a
     blanquear la imagen, solo le sube el brillo un punto al pasar;
   · desenfoque de 12 px sobre una banda mas ancha: no hay canto que seguir
     con el ojo, que es lo que delataba el truco;
   · easing simetrico en vez de expo.out: la luz DESLIZA a velocidad pareja.
     Un reflejo real sobre una superficie satinada no acelera ni frena;
   · 1.05 s y una sola subida-bajada de opacidad, sin meseta. La meseta era
     lo que convertia el brillo en un OBJETO cruzando la foto.

   Si hay que tocarlo, se toca la parada del 50 % del degradado. Todo lo
   demas esta calibrado alrededor de ese numero.                          */
.js .mi-sheen.is-in::before{
  animation:mi-sheen 1.05s cubic-bezier(.42,.06,.34,.98) calc(var(--mi-d,0s) + .26s) both
}
@keyframes mi-sheen{
  0%  {opacity:0;transform:translate3d(-118%,0,0)}
  34% {opacity:.9}
  62% {opacity:.72}
  100%{opacity:0;transform:translate3d(118%,0,0)}
}

/* 4b · Halo suave bajo el cursor. Sólo pintado, cero layout, cero JS por
   frame: micro.js escribe --mx/--my (los mismos nombres que ya usa .btn).
   El `position:relative` no es decorativo: .card y .loc ya lo traen, pero
   .hcard no, y sin él el halo se anclaría a la sección entera en vez de a la
   tarjeta — un manchón del ancho de la página siguiendo al cursor. */
.js .mi-glow{position:relative}
.js .mi-glow::after{
  content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  border-radius:inherit;opacity:0;
  /* Tres paradas, no dos. Con `tinta → transparent 60%` el degradado se
     cortaba en seco a mitad de camino y se veía el canto del círculo
     siguiendo al cursor: eso es lo que leía a tosco. La parada intermedia
     alarga la caída y el halo muere sin borde.
     El radio sube a 560px porque un halo más ancho y más pálido lee a luz
     de sala; uno corto y más denso lee a foco de linterna.              */
  background:radial-gradient(560px circle at var(--mx,50%) var(--my,50%),
             color-mix(in oklab, var(--navy), transparent 94%) 0%,
             color-mix(in oklab, var(--navy), transparent 97.5%) 42%,
             transparent 78%);
  /* Entra algo más lento de lo que entra el cursor y sale aún más lento:
     la luz se apaga, no se corta.                                       */
  transition:opacity .8s var(--mi-e-soft)
}
@media (hover:hover) and (pointer:fine){
  .js .mi-glow:hover::after{opacity:1;transition-duration:.55s}
}
/* Sobre superficie oscura el halo tiene que ser de luz, no de tinta. */
.js .band .mi-glow::after,
.js .ph--dark .mi-glow::after{
  background:radial-gradient(560px circle at var(--mx,50%) var(--my,50%),
             color-mix(in oklab, var(--cream), transparent 91%) 0%,
             color-mix(in oklab, var(--cream), transparent 96%) 42%,
             transparent 78%)
}



/* ==========================================================================
   5 · LA GIFT CARD — el único objeto que se coge con la mano
   Un solo momento memorable por página, no veinte. Aquí es la tarjeta: se
   inclina hacia el puntero como si estuviera sobre la mesa.

   Va por la propiedad `rotate`, no por `transform`, y no es un capricho: al
   cambiar de monto main.css lanza @keyframes gcbump, que anima `transform`.
   Una animación gana siempre a la declaración, así que la inclinación se
   caería de golpe durante ese medio segundo. Con `rotate` las dos capas
   componen y el latido se suma a la inclinación en vez de borrarla.

   Se apaga entero en puntero grueso: en móvil no hay a dónde inclinarla.
   ========================================================================== */
@media (hover:hover) and (pointer:fine){
  .js .mi-tilt-stage{perspective:1100px}
  .js .mi-tilt{
    rotate:var(--ty,0) var(--tx,0) 0 var(--ta,0deg);
    transform-style:preserve-3d;
    transition:rotate .5s var(--mi-e-soft)
  }
  .js .mi-tilt.is-tilting{transition:rotate .12s linear}
}


/* ==========================================================================
   6 · SALIDA DE PÁGINA — deliberadamente vacío
   No se toca. main.css ya navega entre documentos con View Transitions
   (`@view-transition{navigation:auto}`), dejando barra y burbuja fuera del
   snapshot para que no parpadeen. Añadir aquí un fundido propio al pulsar un
   enlace sería peor que no hacer nada: la foto que toma el navegador saldría
   con la página ya medio apagada.
   ========================================================================== */


/* ==========================================================================
   7 · BARRA DE SCROLL VIVA
   La barra de progreso que ya construye main.js gana grosor y color con la
   velocidad. Es la única lectura continua de --sv: una sola capa, un solo
   elemento, coste nulo.
   ========================================================================== */
.js .prog{
  height:calc(2px + var(--sv) * 1.6px);
  transition:height .32s var(--mi-e-soft)
}


/* ==========================================================================
   8 · DEGRADACIONES
   Mismo contrato que main.css: si el usuario pide menos movimiento, si rAF
   está congelado o si no hay JS, TODO queda visible y quieto. Nunca hay un
   estado en el que el contenido se quede escondido.
   ========================================================================== */
html.no-motion .mi-up,
html.no-motion .mi-wipe,
html.no-motion .mi-chars .mi-c{opacity:1 !important;transform:none !important;clip-path:none !important}
html.no-motion .mi-media > img,
html.no-motion .mi-media > video,
html.no-motion .mi-media > picture > img{opacity:1 !important;scale:1 !important}
html.no-motion .mi-media{clip-path:none !important}
html.no-motion .mi-sheen::before{animation:none !important;opacity:0 !important}

@media (prefers-reduced-motion: reduce){
  .mi-up,.mi-wipe,.mi-chars .mi-c{opacity:1 !important;transform:none !important;clip-path:none !important;transition:none !important}
  .mi-media > img,.mi-media > video,.mi-media > picture > img{opacity:1 !important;scale:1 !important;transition:none !important}
  .mi-media{clip-path:none !important;transition:none !important}
  .mi-sheen::before{display:none}
  .mi-glow::after{display:none}
  .mi-tilt{rotate:none !important}
  .js .prog{height:2px}
}
