/* ==========================================================================
   CÁLIGO · Sistema de movimiento (Brief §6)
   Principio: el contenido es legible aunque la animación no corra.
   Solo se animan `transform` y `opacity`; el JS escribe progresos en
   custom properties (--p) y el CSS hace el trabajo visual.
   ========================================================================== */

/* Propiedades animables registradas: permiten interpolar y evitan repintados */
@property --p {
  syntax: '<number>';
  inherits: true;
  initial-value: 0;
}

@property --scroll {
  syntax: '<number>';
  inherits: false;
  initial-value: 0;
}

/* --------------------------------------------------------------------------
   1 · Reveal y stagger
   Solo se oculta cuando hay JS (html.js): sin JS todo se ve desde el inicio.
   -------------------------------------------------------------------------- */

html.js [data-reveal] {
  opacity: 0;
  translate: 0 2rem;
  transition: opacity var(--dur-slow) var(--ease-out), translate var(--dur-slow) var(--ease-out);
  transition-delay: calc(var(--i, 0) * 70ms);
}

html.js [data-reveal='scale'] {
  translate: none;
  scale: 0.96;
  transition-property: opacity, scale;
}

html.js [data-reveal='left'] {
  translate: -2rem 0;
}

html.js [data-reveal='right'] {
  translate: 2rem 0;
}

html.js [data-reveal].is-in {
  opacity: 1;
  translate: 0 0;
  scale: 1;
}

/* Sin JS pero con soporte nativo de timelines: reveal por CSS puro */
@supports (animation-timeline: view()) {
  html:not(.js) [data-reveal] {
    animation: reveal-in linear both;
    animation-timeline: view();
    animation-range: entry 5% entry 60%;
  }
}

@keyframes reveal-in {
  from {
    opacity: 0;
    translate: 0 2rem;
  }
  to {
    opacity: 1;
    translate: 0 0;
  }
}

/* --------------------------------------------------------------------------
   2 · Split-text por palabra con máscara por línea
   -------------------------------------------------------------------------- */

.split-line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.08em;
}

.split-word {
  display: inline-block;
  translate: 0 110%;
  transition: translate 0.9s var(--ease-out);
  transition-delay: calc(var(--i, 0) * 45ms);
  will-change: translate;
}

.is-in .split-word,
.split-word.is-in {
  translate: 0 0;
}

/* --------------------------------------------------------------------------
   2b · Hero: entrada frase por frase y disolución al salir
   -------------------------------------------------------------------------- */

html.js .hero__phrase {
  opacity: 0;
  translate: 0 0.65em;
  animation: hero-phrase-in 0.85s var(--ease-out) forwards;
  animation-delay: calc(var(--i, 0) * 0.32s + 0.12s);
}

@keyframes hero-phrase-in {
  to {
    opacity: 1;
    translate: 0 0;
  }
}

/* Al hacer scroll el bloque crece y se difumina. --p lo escribe el scrub "leave". */
html.js .hero__text {
  transform-origin: 0% 42%;
  scale: calc(1 + var(--p, 0) * 0.55);
  filter: blur(calc(var(--p, 0) * 18px));
  opacity: calc(1 - var(--p, 0) * 0.85);
}

/* --------------------------------------------------------------------------
   3 · Parallax por capas (scrub). --p va de -1 a 1 según la posición
        del elemento en el viewport; --speed define la velocidad de capa.
   -------------------------------------------------------------------------- */

[data-parallax] {
  translate: 0 calc(var(--p, 0) * var(--speed, 0.2) * 12rem);
  will-change: translate;
}

[data-parallax='x'] {
  translate: calc(var(--p, 0) * var(--speed, 0.2) * 12rem) 0;
}

/* Parallax interno de imagen dentro de una tarjeta */
.card__media [data-parallax] {
  scale: 1.12;
}

/* --------------------------------------------------------------------------
   4 · Clip-path por facetas (portafolio)
   -------------------------------------------------------------------------- */

html.js .facet-reveal {
  clip-path: polygon(0% 0%, 38% 0%, 12% 100%, 0% 100%);
  transition: clip-path 1.05s var(--ease-in-out);
}

html.js .facet-reveal.is-in {
  clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%);
}

/* --------------------------------------------------------------------------
   5 · Búho por facetas: ensamblado, vuelo con el scroll, ojos y parpadeo
   -------------------------------------------------------------------------- */

.owl {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.owl .facet {
  transform-box: fill-box;
  transform-origin: center;
}

html.js .owl[data-assemble] .facet {
  opacity: 0;
  animation: facet-in 0.75s var(--ease-out) forwards;
  animation-delay: calc(var(--i, 0) * 45ms + 120ms);
}

@keyframes facet-in {
  from {
    opacity: 0;
    translate: calc(var(--fx, 0) * 1.6px) calc(var(--fy, 0) * 1.6px);
    rotate: calc(var(--fr, 0) * 1deg);
    scale: 0.82;
  }
  to {
    opacity: 1;
    translate: 0 0;
    rotate: 0deg;
    scale: 1;
  }
}

/* Las facetas se separan y "vuelan" al hacer scroll fuera del hero */
.owl[data-fly] .facet {
  translate: calc(var(--p, 0) * var(--fx, 0) * 1.1px) calc(var(--p, 0) * var(--fy, 0) * 1.1px);
  rotate: calc(var(--p, 0) * var(--fr, 0) * 0.6deg);
}

.owl .pupil {
  translate: calc(var(--ex, 0) * 1px) calc(var(--ey, 0) * 1px);
  transition: translate 0.18s linear;
}

.owl .lid {
  transform-box: fill-box;
  transform-origin: center top;
  scale: 1 0;
}

.owl.is-blinking .lid {
  animation: blink 0.42s var(--ease-in-out) 2;
}

@keyframes blink {
  0%,
  100% {
    scale: 1 0;
  }
  45%,
  55% {
    scale: 1 1;
  }
}

/* --------------------------------------------------------------------------
   6 · Manifiesto pinned: una frase por pantalla
   -------------------------------------------------------------------------- */

/* La altura del contenedor define cuánto scroll dura el pin (--n = nº de frases) */
html.js .frases {
  min-height: calc(var(--n, 4) * 85svh);
}

.frase {
  pointer-events: none;
}

.frase__texto {
  opacity: 0;
  translate: 0 2.5rem;
  transition: opacity 0.6s var(--ease-out), translate 0.7s var(--ease-out);
}

.frase__video {
  transition: opacity 0.7s var(--ease-out);
}

.frase[data-state='active'] {
  pointer-events: auto;
}

.frase[data-state='active'] .frase__texto {
  opacity: 1;
  translate: 0 0;
}

.frase[data-state='active'] .frase__video {
  opacity: 0.72;
}

.frase[data-state='after'] .frase__texto {
  opacity: 0;
  translate: 0 -2.5rem;
}

html:not(.js) .frase {
  grid-area: auto;
  margin-bottom: var(--space-l);
}

html:not(.js) .frase__texto {
  opacity: 1;
  translate: none;
}

html:not(.js) .frase__video {
  position: relative;
  left: auto;
  top: auto;
  width: 100%;
  height: 9rem;
  max-width: 100%;
  translate: none;
  opacity: 0.72;
  margin-bottom: var(--space-m);
}

html:not(.js) .frases__pin {
  position: static;
  min-height: 0;
}

/* Las frases entran por palabra cuando la sección está activa */
.frase[data-state='active'] .split-word {
  translate: 0 0;
}

/* --------------------------------------------------------------------------
   7 · Stacking cards (el reto)
   -------------------------------------------------------------------------- */

html.js .stack__item {
  scale: calc(1 - (var(--depth, 0) * 0.03));
  transform-origin: top center;
  transition: scale 0.5s var(--ease-out);
}

/* --------------------------------------------------------------------------
   8 · Ecosistema: scroll horizontal solo en desktop
   -------------------------------------------------------------------------- */

.eco__pin {
  position: static;
  height: auto;
}

.eco__track {
  flex-wrap: wrap;
}

.eco__track .eco__panel {
  width: 100%;
}

@media (min-width: 64rem) and (prefers-reduced-motion: no-preference) {
  html.js .eco {
    min-height: 260svh;
  }

  html.js .eco__pin {
    position: sticky;
    height: 100svh;
  }

  html.js .eco__track {
    flex-wrap: nowrap;
    translate: calc(var(--p, 0) * var(--eco-shift, 0px)) 0;
  }

  html.js .eco__track .eco__panel {
    width: min(26rem, 34vw);
  }
}

/* --------------------------------------------------------------------------
   9 · Paisaje (scrollytelling del manifiesto)
   -------------------------------------------------------------------------- */

/* Duración del recorrido: 5 escenas. En móvil se recorta (Brief §6.2). */
html.js .paisaje {
  min-height: 420svh;
}

@media (max-width: 47.99rem) {
  html.js .paisaje {
    min-height: 300svh;
  }
}

.paisaje__capa {
  transform-box: view-box;
  translate: 0 calc(var(--p, 0) * var(--depth, 0) * -14%);
}

.paisaje__capa[data-scale] {
  scale: calc(1 + var(--p, 0) * var(--depth, 0) * 0.12);
  transform-origin: 50% 100%;
}

/* Niebla: se disipa por capas con opacidad, nunca con filter: blur animado */
.niebla-1 {
  opacity: calc(1 - var(--p, 0) * 1.6);
}

.niebla-2 {
  opacity: calc(1 - var(--p, 0) * 1.05);
}

.niebla-3 {
  opacity: calc(0.85 - var(--p, 0) * 0.7);
}

/* Los ojos en la niebla: lo único visible al empezar el recorrido */
.ojos-niebla {
  opacity: calc(1 - var(--p, 0) * 7);
}

/* Amanecer: aparece con los colores de las facetas al final del recorrido */
.amanecer {
  opacity: calc((var(--p, 0) - 0.62) * 3);
}

.estrellas {
  opacity: calc(1 - var(--p, 0) * 2.4);
}

.buho-vuelo {
  translate: calc(var(--p, 0) * 42%) calc(var(--p, 0) * -18% + 6%);
  scale: calc(1 - var(--p, 0) * 0.35);
  transform-box: view-box;
  transform-origin: 50% 50%;
}

.escena {
  opacity: 0;
  translate: 0 2rem;
  transition: opacity 0.55s var(--ease-out), translate 0.65s var(--ease-out);
  pointer-events: none;
}

.escena[data-state='active'] {
  opacity: 1;
  translate: 0 0;
  pointer-events: auto;
}

.escena[data-state='after'] {
  opacity: 0;
  translate: 0 -2rem;
}

html:not(.js) .paisaje__pin {
  position: static;
  height: auto;
  padding-block: var(--space-2xl);
}

html:not(.js) .escena {
  grid-area: auto;
  opacity: 1;
  translate: none;
  margin-bottom: var(--space-xl);
}

/* Foco de luz que sigue el cursor en la escena de niebla ("ver lo que no se ve") */
.paisaje__foco {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(
    18rem circle at var(--mx, 50%) var(--my, 45%),
    color-mix(in srgb, var(--c-teal-2) 22%, transparent),
    transparent 70%
  );
  opacity: calc(1 - var(--p, 0) * 2.2);
  mix-blend-mode: screen;
}

/* --------------------------------------------------------------------------
   10 · Cursor personalizado del portafolio (solo puntero fino)
   -------------------------------------------------------------------------- */

.cursor {
  position: fixed;
  z-index: 60;
  top: 0;
  left: 0;
  width: 5rem;
  height: 5rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--c-ink);
  color: #fff;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  pointer-events: none;
  opacity: 0;
  scale: 0.4;
  translate: -50% -50%;
  transition: opacity 0.2s var(--ease-out), scale 0.3s var(--ease-out);
}

.cursor[data-on='true'] {
  opacity: 1;
  scale: 1;
}

@media (pointer: coarse), (prefers-reduced-motion: reduce) {
  .cursor {
    display: none;
  }
}

/* --------------------------------------------------------------------------
   11 · Transición de página (View Transitions API)
   -------------------------------------------------------------------------- */

@view-transition {
  navigation: auto;
}

::view-transition-old(root) {
  animation: vt-out 0.28s var(--ease-in-out) both;
}

::view-transition-new(root) {
  animation: vt-in 0.4s var(--ease-out) both;
}

@keyframes vt-out {
  to {
    opacity: 0;
    translate: 0 -1.5rem;
  }
}

@keyframes vt-in {
  from {
    opacity: 0;
    translate: 0 1.5rem;
  }
}

/* --------------------------------------------------------------------------
   12 · Barra de progreso: nativa donde haya soporte, JS como respaldo
   -------------------------------------------------------------------------- */

@supports (animation-timeline: scroll()) {
  .progress {
    scale: 1 1;
    transform-origin: left;
    animation: progress-grow linear both;
    animation-timeline: scroll(root block);
  }

  @keyframes progress-grow {
    from {
      scale: 0 1;
    }
    to {
      scale: 1 1;
    }
  }
}

/* --------------------------------------------------------------------------
   13 · prefers-reduced-motion: obligatorio (Brief §6.3)
   Sin parallax, sin pin, sin scroll horizontal, sin marquee. Solo fades cortos.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.2s !important;
    scroll-behavior: auto !important;
  }

  /* Quien pide menos movimiento no debería depender del scroll para ver el
     contenido: nada se oculta, no hay nada que "aparecer" (Brief §6.3). */
  html.js [data-reveal],
  html.js [data-reveal].is-in {
    opacity: 1;
    translate: none;
    scale: 1;
    transition: none;
  }

  [data-parallax],
  .paisaje__capa,
  .buho-vuelo,
  .owl[data-fly] .facet,
  .hero__text {
    translate: none !important;
    scale: 1 !important;
    rotate: none !important;
    filter: none !important;
    opacity: 1 !important;
  }

  .hero__phrase {
    opacity: 1;
    translate: none;
    animation: none;
  }

  .split-word {
    translate: none;
  }

  html.js .facet-reveal {
    clip-path: none;
  }

  .frases__pin,
  .eco__pin,
  .paisaje__pin {
    position: static;
    height: auto;
    min-height: 0;
  }

  .paisaje--video .paisaje__video {
    position: relative;
    height: 42svh;
  }

  .paisaje--video .paisaje__veil {
    display: none;
  }

  html.js .frases,
  html.js .eco,
  html.js .paisaje {
    min-height: 0;
  }

  .frase,
  .escena {
    grid-area: auto;
    opacity: 1;
    translate: none;
    margin-bottom: var(--space-l);
    pointer-events: auto;
  }

  .frase__texto {
    opacity: 1;
    translate: none;
  }

  .frase__video {
    position: relative;
    left: auto;
    top: auto;
    width: 100%;
    height: 9rem;
    max-width: 100%;
    translate: none;
    opacity: 0.7;
    margin-bottom: var(--space-m);
  }

  .paisaje__foco {
    display: none;
  }

  html.js .stack__item {
    position: static;
    scale: 1;
  }

  @view-transition {
    navigation: none;
  }
}
