@charset "UTF-8";

/* ==========================================================================
   Casa Paradisu — Hero piloté au défilement (« scrub »)

   Trois pièces, comme pour l'ancien hero séquentiel :

     .hero--scrub        la section, qui ne fait plus que contenir
     .hero-scrub__track  une piste haute de N écrans, dont l'unique rôle est
                         de donner au défilement la course nécessaire
     .hero-scrub__stage  une scène collante d'exactement un écran, qui reste
                         fixée pendant toute la traversée

   La hauteur de la piste est portée par `--hero-track-screens`. Elle vaut UN
   écran par défaut : sans JavaScript, sur écran tactile, sous
   `prefers-reduced-motion` ou si la vidéo est introuvable, la section est un
   hero classique d'une hauteur de fenêtre. Le script la remplace par la course
   réelle une fois la vidéo prête, et jamais avant.

   Ce fichier est chargé APRÈS `responsive.css` : à spécificité égale, c'est
   lui qui l'emporte sur les règles de `.hero`.
   ========================================================================== */

/* Repli pour les moteurs sans `svh`, à l'identique du hero séquentiel. */
@supports not (height: 100svh) {
  .hero--scrub { --hero-screen: 100vh; }
}

.hero--scrub {
  /* `.hero` est une boîte flexible d'une hauteur d'écran, qui coupe son
     débordement. Les trois sont à défaire ici : un ancêtre qui coupe le
     débordement désactive silencieusement `position: sticky` chez ses
     descendants. */
  display: block;
  min-height: 0;
  height: auto;
  overflow: visible;
}

/* Le voile supérieur de `.hero` défilerait avec la section, qui mesure
   plusieurs écrans : il ne protégerait la barre de navigation que sur le
   premier. Il est repris à l'identique par la scène, qui elle reste fixe. */
.hero--scrub::before { content: none; }

.hero-scrub__track {
  position: relative;
  height: calc(var(--hero-screen, 100svh) * var(--hero-track-screens, 1));
}

.hero-scrub__stage {
  position: sticky;
  top: 0;
  height: var(--hero-screen, 100svh);
  overflow: hidden;
  isolation: isolate;
  /* Fond d'attente en tons de marque, jamais un aplat noir : tant que la
     photographie n'est pas peinte, le bloc ne se lit pas comme une erreur. */
  background-color: var(--c-charcoal);
  background-image: linear-gradient(160deg, #2C302A 0%, #20231F 55%, #171A16 100%);
}

/* Voile sous l'en-tête, repris de `.hero::before` et posé sur la scène. */
.hero-scrub__stage::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: calc(var(--header-h) + 2rem);
  z-index: 4;
  pointer-events: none;
  background: linear-gradient(to bottom,
    rgba(8, 14, 16, 0.64) 0%,
    rgba(8, 14, 16, 0.46) 40%,
    rgba(8, 14, 16, 0) 100%);
}

/* --- Médias ----------------------------------------------------------------
   La photographie est TOUJOURS là, dessous. La vidéo se pose par-dessus et
   n'est révélée qu'une fois sa première image décodée : aucun écran noir ne
   peut apparaître, ni pendant le chargement, ni si le format est refusé.
   -------------------------------------------------------------------------- */
.hero-scrub__media {
  position: absolute;
  inset: 0;
  z-index: 1;
}

.hero-scrub__media img,
.hero-scrub__media video {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Même convention que l'ancien hero : un `--focal` posé sur le média suffit
     à déplacer le point de cadrage, sans toucher à cette règle. */
  object-position: var(--focal, 50% 50%);
}

.hero-scrub__media video {
  z-index: 2;
  opacity: 0;
  transition: opacity 700ms var(--ease, ease);
}
.hero--scrub.is-video-ready .hero-scrub__media video { opacity: 1; }

/* --- Rapprochement de la photographie --------------------------------------
   Les trois valeurs sont posées par `hero-scrub.js` à chaque image, et elles
   ne valent que sur le hero qui porte `data-hero-zoom`.

   L'ORDRE COMPTE : en CSS les transformations se lisent de droite à gauche.
   Le déplacement s'applique donc d'abord, dans le repère propre de l'image,
   puis l'agrandissement l'amplifie autour du centre. C'est ce qui permet de
   raisonner en fractions de l'image sans dépendre de l'échelle en cours.

   Aucune transition ici : la position suit le défilement au pixel près. Une
   durée ajouterait une traîne qui continuerait après l'arrêt du geste. */

/* --- La caméra -------------------------------------------------------------
   Les valeurs sont posées par `hero-scrub.js` à chaque image, et elles ne
   valent que sur le hero qui porte `data-hero-zoom`.

   L'ORDRE COMPTE : en CSS les transformations se lisent de droite à gauche. Le
   déplacement s'applique donc d'abord, dans le repère propre de l'image, puis
   l'agrandissement l'amplifie autour du centre, puis la caméra tourne, et la
   perspective projette enfin le tout. C'est ce qui permet de raisonner en
   fractions de l'image sans dépendre de l'échelle en cours.

   `perspective()` est écrite DANS la liste plutôt que posée sur le parent :
   sa distance peut ainsi varier en cours de route — c'est elle qui donne le
   travelling compensé — et aucun contexte 3D n'est créé sur la scène, où
   `overflow: hidden` et `position: sticky` restent intacts.

   La brume reçoit exactement la même transformation que l'image : elle lui est
   donc solidaire, et son dégradé reste sur l'horizon au lieu de glisser
   dessus.

   Aucune transition ici : la position suit le défilement au pixel près. Une
   durée ajouterait une traîne qui continuerait après l'arrêt du geste. */
.hero-scrub__plan,
.hero-scrub__brume {
  position: absolute;
  inset: 0;
  z-index: 1;
}

.hero--scrub.is-zoom-ready .hero-scrub__plan,
.hero--scrub.is-zoom-ready .hero-scrub__brume {
  transform:
    perspective(var(--zoom-focale, 1500px))
    rotateX(var(--zoom-tangage, 0deg))
    rotateY(var(--zoom-lacet, 0deg))
    rotateZ(var(--zoom-roulis, 0deg))
    scale(var(--zoom-echelle, 1))
    translate(var(--zoom-x, 0%), var(--zoom-y, 0%));
  /* La composition est annoncée au moteur pendant le hero seulement : la
     classe tombe dès que le rapprochement est désactivé. */
  will-change: transform;
}

/* --- Brume du lointain ------------------------------------------------------
   Un voile froid sur le fond, qui se retire à mesure qu'on avance : on sort de
   la brume en s'approchant. Ses deux bornes viennent du script, en fractions
   de la photographie ramenées dans la boîte, de sorte qu'elle s'arrête au
   feuillage quel que soit le format de l'écran. */
.hero-scrub__brume {
  z-index: 2;
  pointer-events: none;
  opacity: var(--zoom-brume, 0);
  background: linear-gradient(to bottom,
    rgba(198, 214, 226, 0.95) 0%,
    rgba(198, 214, 226, 0.60) var(--zoom-brume-haut, 34%),
    rgba(198, 214, 226, 0) var(--zoom-brume-bas, 52%));
}

/* --- Vignette ---------------------------------------------------------------
   En coordonnées d'ÉCRAN, et pas dans le plan : les angles qui s'assombrissent
   appartiennent à l'objectif, pas au paysage. Elle se resserre à mesure qu'on
   avance, ce qui ajoute au mouvement sans toucher à l'image.
   Sous le voile de l'en-tête (z-index 4) et sous la signature (5). */
.hero-scrub__vignette {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  opacity: var(--zoom-vignette, 0);
  background: radial-gradient(118% 84% at 50% 48%,
    rgba(10, 13, 11, 0) 40%,
    rgba(10, 13, 11, 0.18) 74%,
    rgba(10, 13, 11, 0.46) 100%);
}

@media (prefers-reduced-motion: reduce) {
  .hero-scrub__media video { transition: none; }
  /* Le hero redevient une photographie fixe, cadrée telle quelle : aucune
     caméra, aucun voile. */
  .hero--scrub .hero-scrub__plan {
    transform: none;
    will-change: auto;
  }
  .hero--scrub .hero-scrub__brume,
  .hero--scrub .hero-scrub__vignette { display: none; }
}

/* --- Signature de marque ---------------------------------------------------
   Reprise telle quelle du hero séquentiel : `.hero-intro__content`,
   `.hero-intro__title` et `.hero-intro__discover` sont déjà définis dans
   `pages.css` et `responsive.css`. Rien n'est redéclaré ici, seul le plan
   d'empilement est fixé — au-dessus du voile de l'en-tête.
   -------------------------------------------------------------------------- */
.hero--scrub .hero-intro__content { z-index: 5; }
