/* ==========================================================================
   OV7 Development — Couche mouvement
   Scène 3D, voile de lisibilité, voile de sortie, états de départ.

   Règle de sécurité : un élément n'est masqué que tant qu'un mécanisme actif
   s'engage à le révéler (`html.motion` pour GSAP, `html.reveal-js` pour le
   repli). Sans JavaScript, CDN bloqué ou module en échec, rien n'est caché.
   ========================================================================== */

/* ========================= Scène 3D ========================= */
.scene{
  position:fixed;
  inset:0;
  z-index:0;
  pointer-events:none;
  display:block;
  width:100%;
  height:100%;
}

/**
 * Voile de lisibilité.
 * La scène doit rester visible d'un bout à l'autre, mais le texte doit rester
 * lisible par-dessus : un voile renforcé sur les bords — où vivent les
 * colonnes de texte — laisse le centre de l'image respirer.
 */
.scene-scrim{
  position:fixed;
  inset:0;
  z-index:0;
  pointer-events:none;
  background:
    linear-gradient(90deg, var(--bg) 0%, var(--bg) 32%, transparent 66%, transparent 84%, var(--bg) 100%),
    radial-gradient(ellipse 78% 62% at 64% 48%, transparent 0%, var(--bg) 96%);
  opacity:.74;
}
:root[data-theme="light"] .scene-scrim{opacity:.8;}

/* Le contenu passe devant la scène.
   Attention : ne jamais toucher au `position` du header ni du menu mobile —
   ils sont fixes, et les repasser en `relative` les remettrait dans le flux. */
main,
.footer{position:relative;z-index:1;}

/* ========================= Barre de progression ========================= */
.scroll-progress{
  position:fixed;
  top:0;left:0;right:0;
  height:2px;
  z-index:calc(var(--z-header) + 1);
  background:linear-gradient(90deg,var(--brand),var(--brand-ember),var(--brand-glow));
  transform:scaleX(0);
  transform-origin:0 50%;
  pointer-events:none;
}

/* ========================= Voile de sortie ========================= */
/* Hors écran par défaut : il ne sert qu'à quitter la page, et ne peut donc
   jamais rester bloqué devant le contenu si une animation échoue. */
.curtain{
  position:fixed;
  inset:0;
  z-index:calc(var(--z-modal) + 10);
  background:linear-gradient(160deg,var(--bg-soft),var(--bg));
  pointer-events:none;
  display:grid;
  place-items:center;
  transform:translateY(100%);
}
.curtain__mark{
  font-family:var(--font-mono);
  font-size:var(--fs-label);
  letter-spacing:.4em;
  text-transform:uppercase;
  color:var(--text-3);
}

/* ========================= Texte masqué ========================= */
.line{
  display:block;
  overflow:hidden;
  padding-bottom:.08em;
}
.line__inner{display:block;}

/* ========================= États de départ ========================= */
html.motion [data-anim="fade"]{opacity:0;transform:translateY(24px);}
html.motion [data-anim="card"]{opacity:0;transform:translateY(28px);}

html.reveal-js [data-anim]{
  opacity:0;
  transform:translateY(18px);
  transition:opacity .7s var(--ease-out), transform .7s var(--ease-out);
  transition-delay:var(--reveal-delay,0ms);
}
html.reveal-js [data-anim].is-visible{opacity:1;transform:none;}

/* --- Hero : états de départ de la séquence d'ouverture ---
   Ils vivent en CSS et non dans un `gsap.from()` : si la timeline ne
   démarrait pas, le hero resterait vide. Retirer `html.motion` suffit à tout
   rendre visible — c'est exactement ce que fait le filet du <head>. */
html.motion .hero__statement .line__inner{transform:translateY(110%);}
html.motion [data-hero-hud]{opacity:0;transform:translateY(18px);}
html.motion .header .wordmark-link,
html.motion .header__right{opacity:0;}

/* ========================= Mouvement réduit ========================= */
@media (prefers-reduced-motion:reduce){
  html.motion [data-anim]{opacity:1;transform:none;}
  html.motion .hero__statement .line__inner{transform:none;}
  html.motion [data-hero-hud]{opacity:1;transform:none;}
  html.motion .header .wordmark-link,
  html.motion .header__right{opacity:1;}
  .curtain{display:none;}
  .scroll-progress{display:none;}
  .scroll-cue__rail::after{animation:none;}
}

/* ========================= Lisibilité par-dessus la scène =========================
   La caméra traverse le décor : selon la section, du texte peut se retrouver
   au-dessus de blocs éclairés. Un halo sombre très diffus décolle le texte du
   fond sans se lire comme une ombre portée. */
.manifesto,
.band__lead,
.about__text,
.offer__text,
.step__text,
.pole__desc,
.band__title,
.hero__statement,
.project-row__name{
  text-shadow:0 1px 28px var(--bg), 0 1px 8px var(--bg);
}
:root[data-theme="light"] .manifesto,
:root[data-theme="light"] .band__lead,
:root[data-theme="light"] .about__text,
:root[data-theme="light"] .offer__text,
:root[data-theme="light"] .step__text,
:root[data-theme="light"] .pole__desc,
:root[data-theme="light"] .band__title,
:root[data-theme="light"] .hero__statement,
:root[data-theme="light"] .project-row__name{
  text-shadow:0 1px 22px var(--bg);
}

/* Sur écran étroit, le texte occupe toute la largeur : le voile latéral
   n'a plus de sens, on passe à un voile uniforme un peu plus dense. */
@media (max-width:860px){
  .scene-scrim{
    background:
      linear-gradient(180deg, var(--bg) 0%, transparent 22%, transparent 72%, var(--bg) 100%),
      var(--bg);
    opacity:.6;
  }
}
