html,
body {
  margin: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: #020711;
}

.seuil {
  position: relative;
  width: 100vw;
  height: 100vh;

  background-image: url("images/fond-seuil.png");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;

  overflow: hidden;
  isolation: isolate;
}


/* ==================================================
   VÉGA
   ================================================== */

.vega {
  position: absolute;
  left: 28.6vw;
  top: 40vh;

  width: clamp(44px, 4.9vw, 70px);
  height: auto;

  transform: translate(-50%, -50%) scale(1);

  cursor: pointer;
  opacity: .92;

  filter:
    brightness(1)
    drop-shadow(0 0 5px rgba(210, 235, 255, .35))
    drop-shadow(0 0 14px rgba(100, 170, 255, .22));

  animation:
    vega-breath var(--breath-duration, 5.6s)
      cubic-bezier(.42, 0, .25, 1) infinite,
    vega-light var(--breath-duration, 5.6s)
      cubic-bezier(.42, 0, .25, 1) infinite;

  z-index: 5;
}


/* Halo lorsque le curseur approche */

.vega.is-near {
  filter:
    brightness(1.45)
    drop-shadow(0 0 12px rgba(220, 245, 255, .75))
    drop-shadow(0 0 28px rgba(100, 170, 255, .45));
}


/* Respiration physique de l’étoile */

@keyframes vega-breath {

  0%,
  100% {
    transform: translate(-50%, -50%) scale(1);
  }

  18% {
    transform: translate(-50%, -50%) scale(1.01);
  }

  46% {
    transform: translate(-50%, -50%) scale(1.055);
  }

  55% {
    transform: translate(-50%, -50%) scale(1.035);
  }

  72% {
    transform: translate(-50%, -50%) scale(1.015);
  }
}


/* Respiration lumineuse de l’étoile */

@keyframes vega-light {

  0%,
  100% {
    opacity: .76;

    filter:
      brightness(.92)
      drop-shadow(0 0 7px rgba(210, 235, 255, .32))
      drop-shadow(0 0 18px rgba(120, 170, 255, .18));
  }

  20% {
    opacity: .82;

    filter:
      brightness(1.05)
      drop-shadow(0 0 10px rgba(210, 235, 255, .40))
      drop-shadow(0 0 24px rgba(120, 170, 255, .24));
  }

  48% {
    opacity: 1;

    filter:
      brightness(2.4)
      drop-shadow(0 0 24px rgba(240, 250, 255, 1))
      drop-shadow(0 0 62px rgba(110, 175, 255, .82));
  }

  58% {
    opacity: .93;

    filter:
      brightness(1.35)
      drop-shadow(0 0 15px rgba(220, 240, 255, .60))
      drop-shadow(0 0 34px rgba(110, 170, 255, .40));
  }

  78% {
    opacity: .80;

    filter:
      brightness(1.02)
      drop-shadow(0 0 9px rgba(210, 235, 255, .34))
      drop-shadow(0 0 20px rgba(110, 170, 255, .22));
  }
}


/* ==================================================
   TEXTE
   ================================================== */

.phrase {
  position: absolute;
  right: 8vw;
  bottom: 9vh;

  color: rgba(238, 232, 218, .88);

  font-family: "EB Garamond", serif;
  font-style: italic;
  font-size: clamp(1.1rem, 1.8vw, 2rem);

  letter-spacing: .03em;
  line-height: 1.9;
  text-align: right;

  pointer-events: none;

  text-shadow:
    0 0 18px rgba(210, 230, 255, .22);

  z-index: 6;
}

.invitation {
  transform: translateY(-12px);
}

.invitation p {
  opacity: 0;
  transform: translateY(8px);

  animation:
    phrase-apparition 4.8s ease forwards;
}

.invitation p:nth-child(1) {
  animation-delay: 2.4s;
}

.invitation p:nth-child(2) {
  animation-delay: 4.8s;
}

.invitation p:nth-child(3) {
  animation-delay: 7.2s;
}

.ligne2 {
  text-align: right;
  margin-right: 0;
}

.final {
  margin-top: .7em;

  opacity: 0;

  letter-spacing: .08em;

  text-shadow:
    0 0 12px rgba(220, 235, 255, .22),
    0 0 28px rgba(160, 200, 255, .15);

  animation:
    apparition-finale 4.5s ease 11.4s forwards;
}


@keyframes apparition-finale {

  0% {
    opacity: 0;
    transform: translateY(12px);
    filter: blur(2px);
  }

  45% {
    opacity: .45;
  }

  100% {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0);
  }
}


@keyframes phrase-apparition {

  to {
    opacity: 1;
    transform: translateY(0);
  }
}


/* ==================================================
   ATMOSPHÈRE AU REPOS
   ================================================== */

/*
  ::before = souffle stellaire diffus
  ::after  = halo secret discret autour de Véga

  Lors du clic, ces deux calques changent d’animation :
  le souffle converge et le halo devient un voile global.
*/

.seuil::before {
  content: "";

  position: absolute;
  inset: -20%;

  background:
    radial-gradient(
      circle at 28.6% 40%,
      rgba(255, 255, 255, 1) 0%,
      rgba(235, 248, 255, .98) 9%,
      rgba(195, 228, 255, .82) 20%,
      rgba(135, 190, 245, .54) 38%,
      rgba(65, 115, 185, .28) 58%,
      rgba(18, 43, 82, .10) 74%,
      rgba(2, 7, 17, 0) 88%
    );

  opacity: 0;

  transform:
    translateX(0)
    scale(1);

  transform-origin:
    28.6% 40%;

  filter: blur(18px);

  animation:
    souffle 9s ease-in-out infinite;

  pointer-events: none;
  z-index: 1;
}


.seuil::after {
  content: "";

  position: absolute;
  inset: -12%;

  background:
    radial-gradient(
      circle at 28.6% 40%,
      rgba(210, 235, 255, .10),
      transparent 18%
    );

  opacity: 0;

  transform: scale(1);
  transform-origin: 28.6% 40%;

  animation:
    halo-secret 6.8s ease-in-out infinite;

  pointer-events: none;
  z-index: 2;
}


@keyframes souffle {

  0%,
  100% {
    opacity: 0;

    transform:
      translateX(-8%)
      scale(1);
  }

  28% {
    opacity: .16;
  }

  52% {
    opacity: .30;

    transform:
      translateX(4%)
      scale(1.035);
  }

  78% {
    opacity: .08;
  }
}


@keyframes halo-secret {

  0%,
  100% {
    opacity: 0;
    transform: scale(1);
  }

  45% {
    opacity: .55;
    transform: scale(1.08);
  }

  70% {
    opacity: .18;
    transform: scale(1.03);
  }
}


/* ==================================================
   TRANSITION AU CLIC
   ================================================== */

.seuil.is-opening {
  cursor: default;
}

/* Le texte se retire progressivement. */
.seuil.is-opening .phrase {
  opacity: 0;
  transform: translateY(10px);
  transition:
    opacity 1.05s ease,
    transform 1.25s ease;
}

/*
  Les ondes restent présentes après le clic.
  Leur mouvement devient instable et plus rapide,
  comme si le Kraken dérèglait le ciel.
*/
.seuil.is-opening .stellar-wave {
  opacity: 0 !important;
  animation: none;
  transition: opacity .45s ease-out;
}

/* Véga répond, mais ne grandit pratiquement plus. */
.seuil.is-opening .vega {
  pointer-events: none;
  z-index: 10;
  animation:
    vega-ouverture-stable 6.6s
    cubic-bezier(.20, .62, .25, 1)
    forwards;
}

/* Le grand souffle diffus est neutralisé : aucune limite rectangulaire. */
.seuil.is-opening::before {
  animation: none;
  opacity: 0;
  transition: opacity .55s ease;
}

/*
  Voile plein écran fixe.
  Aucun blur, aucun scale, aucune translation.
*/
.seuil.is-opening::after {
  position: fixed;
  inset: 0;
  z-index: 9;

  background:
    radial-gradient(
      circle at 28.6% 40%,
      rgba(255, 255, 255, .82) 0%,
      rgba(236, 248, 255, .55) 12%,
      rgba(190, 219, 245, .26) 29%,
      rgba(115, 155, 198, .10) 48%,
      rgba(2, 7, 17, 0) 70%
    );

  transform: none;
  filter: none;

  animation:
    ouverture-voile-sans-cadre 6.9s
    cubic-bezier(.20, .58, .24, 1)
    forwards;
}

/* ==================================================
   OUVERTURE DE VÉGA — TAILLE PRESQUE STABLE
   ================================================== */

@keyframes vega-ouverture-stable {
  0% {
    transform: translate(-50%, -50%) scale(1.00);
    opacity: 1;
    filter:
      brightness(1.35)
      drop-shadow(0 0 12px rgba(240, 250, 255, .62))
      drop-shadow(0 0 32px rgba(120, 185, 255, .34));
  }

  7% {
    transform: translate(-50%, -50%) scale(1.055);
    filter:
      brightness(2.15)
      drop-shadow(0 0 24px rgba(250, 254, 255, .92))
      drop-shadow(0 0 70px rgba(135, 198, 255, .60));
  }

  15% {
    transform: translate(-50%, -50%) scale(1.015);
    filter:
      brightness(1.72)
      drop-shadow(0 0 18px rgba(245, 252, 255, .76))
      drop-shadow(0 0 48px rgba(128, 192, 255, .46));
  }

  38% {
    transform: translate(-50%, -50%) scale(1.035);
    filter:
      brightness(2.55)
      drop-shadow(0 0 34px rgba(252, 255, 255, .96))
      drop-shadow(0 0 105px rgba(145, 208, 255, .72));
  }

  64% {
    transform: translate(-50%, -50%) scale(1.045);
    opacity: 1;
    filter:
      brightness(3.55)
      drop-shadow(0 0 54px rgba(255, 255, 255, 1))
      drop-shadow(0 0 190px rgba(172, 228, 255, .90));
  }

  82% {
    transform: translate(-50%, -50%) scale(1.035);
    opacity: .86;
    filter:
      brightness(4.55)
      drop-shadow(0 0 78px rgba(255, 255, 255, 1))
      drop-shadow(0 0 285px rgba(195, 238, 255, .98));
  }

  100% {
    transform: translate(-50%, -50%) scale(1.02);
    opacity: 0;
    filter:
      brightness(5.6)
      drop-shadow(0 0 105px rgba(255, 255, 255, 1))
      drop-shadow(0 0 380px rgba(225, 248, 255, 1));
  }
}


/* ==================================================
   LE MONDE S’EFFACE
   ================================================== */

@keyframes ouverture-voile-sans-cadre {
  0%   { opacity: 0;   background-color: rgba(232, 244, 255, 0); }
  12%  { opacity: .07; background-color: rgba(232, 244, 255, .01); }
  26%  { opacity: .15; background-color: rgba(233, 245, 255, .03); }
  42%  { opacity: .27; background-color: rgba(235, 246, 255, .08); }
  58%  { opacity: .43; background-color: rgba(238, 248, 255, .18); }
  72%  { opacity: .60; background-color: rgba(241, 249, 255, .34); }
  84%  { opacity: .76; background-color: rgba(245, 251, 255, .56); }
  93%  { opacity: .90; background-color: rgba(248, 252, 255, .78); }
  100% { opacity: 1;   background-color: rgba(252, 254, 255, .99); }
}


/* ==================================================
   ONDE STELLAIRE ALÉATOIRE
   ================================================== */

.stellar-wave {
  position: absolute;

  left: -25vw;
  top: var(--wave-top);

  width: var(--wave-width);
  height: var(--wave-height);

  background:
    radial-gradient(
      ellipse at 18% 45%,
      rgba(
        230,
        245,
        255,
        var(--wave-opacity)
      ),
      transparent 32%
    ),
    radial-gradient(
      ellipse at 52% 60%,
      rgba(
        170,
        210,
        255,
        calc(var(--wave-opacity) * .65)
      ),
      transparent 28%
    ),
    radial-gradient(
      ellipse at 82% 38%,
      rgba(
        230,
        245,
        255,
        calc(var(--wave-opacity) * .45)
      ),
      transparent 26%
    );

  filter:
    blur(var(--wave-blur));

  opacity: 0;

  transform:
    translateX(-20vw)
    rotate(var(--wave-angle))
    skewX(var(--wave-skew));

  pointer-events: none;

  animation:
    stellar-wave-pass
    var(--wave-duration)
    ease-in-out
    forwards;

  mix-blend-mode: screen;

  z-index: 3;
}


@keyframes stellar-wave-pass {

  0% {
    opacity: 0;

    transform:
      translateX(-20vw)
      rotate(var(--wave-angle))
      skewX(var(--wave-skew));
  }

  35% {
    opacity: .75;
  }

  100% {
    opacity: 0;

    transform:
      translateX(55vw)
      rotate(var(--wave-angle))
      skewX(var(--wave-skew));
  }
}


/* ==================================================
   DISTORSION SUBTILE DU SEUIL
   ================================================== */

.seuil.is-warping {
  animation:
    seuil-warp 6.5s ease-in-out;
}


@keyframes seuil-warp {

  0%,
  100% {
    filter: none;
    transform: scale(1);
  }

  35% {
    filter:
      blur(.15px)
      contrast(1.015);

    transform:
      scale(1.002)
      skewX(.12deg);
  }

  58% {
    filter:
      blur(.25px)
      contrast(1.025);

    transform:
      scale(1.004)
      skewX(-.16deg);
  }

  76% {
    filter:
      blur(.12px)
      contrast(1.01);

    transform:
      scale(1.001)
      skewX(.08deg);
  }
}


/* ==================================================
   ACCESSIBILITÉ : MOUVEMENTS RÉDUITS
   ================================================== */

@media (prefers-reduced-motion: reduce) {

  .vega,
  .invitation p,
  .final,
  .seuil::before,
  .seuil::after,
  .stellar-wave,
  .seuil.is-warping {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
  }

  .seuil.is-opening .phrase {
    transition-duration: .01ms !important;
  }
}
