/* ==========================================================================
   Le preloader, 23 septembre 2026, sur demande.

   Fond clair, la marque dans une tuile d'icône du design system (surface
   blanche, liseré, ombres), « Percer » qui s'écrit lettre par lettre à sa
   droite, et une barre grise dessous, qui arrive la première. Quand tout est
   là, la tuile roule sur le nom et l'efface pendant que le voile se lève,
   comme le préchargement de pulsor.agency (rideau et contenu en
   contre-course, sur la courbe fournie, --pre-levee).

   ⚠️ Il remplace la version sombre à radar du 15 septembre 2026, qui vivait
   sur une page de travail à part. Celui-ci est posé sur la home.

   La séquence, en temps depuis l'armement :
   1. le trait se trace de 0 à 100 % de sa longueur (0,1 à 1,1 s) ;
   2. la tuile sort du trait en roulant, d'un tour (à 0,45 s, 1,2 s) ;
   3. les six lettres montent une à une (à partir de 0,85 s, 45 ms de pas) ;
   4. dès que la page est chargée, et pas avant 2 s : la tuile roule sur le
      nom et le voile se lève, en même temps.

   Rien n'est caché sans script : le voile n'existe que sous
   html[data-preloader], posé par la ligne en ligne de index.html, et jamais
   sous prefers-reduced-motion.
   ========================================================================== */

.preloader {
  --pre-tuile: calc(var(--spacing) * 76);
  --pre-ecart: calc(var(--spacing) * 20);
  --pre-mot: clamp(calc(var(--spacing) * 48), 7vw, calc(var(--spacing) * 76));
  --pre-lettre-pas: 45ms;
  --pre-trait-ecart: calc(var(--spacing) * 28);
  --pre-roule: var(--pulsor-xl);
  --pre-rideau: var(--pulsor-xxl);
  /* La courbe de la levée, relevée point par point sur un tracé fourni le
     23 septembre 2026 : départ lent et presque droit, puis tout le mouvement
     dans le dernier cinquième. linear() la suit à l'identique ; la
     cubic-bezier n'est qu'un repli pour les moteurs sans linear(). */
  --pre-levee: cubic-bezier(.7, .05, .95, .45);

  position: fixed;
  inset: 0;
  z-index: 10000;
  display: none;
  place-items: center;
  overflow: hidden;
  background: var(--fond-page);
  pointer-events: none;
  transition: translate var(--pre-rideau) var(--pre-levee);
}

@supports (transition-timing-function: linear(0, 1)) {
  .preloader {
    --pre-levee: linear(0, .083 19.5%, .134 34%, .2 49%, .325 66%, .4 73%, .52 83%, .7 88%, .87 93%, .96 95.5%, 1);
  }
}

html[data-preloader="en-cours"] .preloader,
html[data-preloader="sort"] .preloader { display: grid; }

/* La page ne défile pas sous le voile. */
html[data-preloader="en-cours"],
html[data-preloader="sort"] { overflow: hidden; }

/* Le contenu part en contre-course : le rideau monte d'un écran, le contenu
   n'en monte qu'un quart, et c'est le bord du rideau qui le coupe. */
.preloader-contenu {
  display: grid;
  justify-items: start;
  row-gap: var(--pre-trait-ecart);
  transition: translate var(--pre-rideau) var(--pre-levee);
}

html[data-preloader="sort"] .preloader { translate: 0 -100%; }
html[data-preloader="sort"] .preloader-contenu { translate: 0 75vh; }

/* --- La marque --------------------------------------------------------- */

.preloader-marque {
  position: relative;
  display: flex;
  align-items: center;
  column-gap: var(--pre-ecart);
}

/* Le cadre de la tuile coupe tout ce qui passe sous le trait : la tuile sort
   du trait en roulant, d'un tour, et n'existe pas en dessous. Il ne coupe
   rien sur les côtés ni en haut, où la tuile roule à la sortie. */
.preloader-cadre {
  /* Au-dessus du nom : le cadre porte un clip-path, donc un contexte
     d'empilement, et sans z-index le mot, posé après lui, passait devant la
     tuile qui roule. */
  position: relative;
  z-index: 2;
  display: block;
  flex: none;
  clip-path: inset(-100vh -100vw calc(-1 * var(--pre-trait-ecart)) -100vw);
}

/* La tuile d'icône du design system, telle que la porte le titre du prix
   comparé : surface blanche, liseré à 12 %, cinq ombres bleutées. Rayon 20. */
.preloader-tuile {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  flex: none;
  inline-size: var(--pre-tuile);
  block-size: var(--pre-tuile);
  border-radius: var(--r-xl);
  background: var(--blanc);
  border: 1px solid rgb(28 28 28 / .12);
  box-shadow:
    0 1px 1px rgb(9 23 78 / .04),
    0 3px 3px rgb(9 23 78 / .04),
    0 6px 6px rgb(9 23 78 / .04),
    0 12px 12px rgb(9 23 78 / .04),
    0 24px 24px rgb(9 23 78 / .04);
  animation: pre-tuile var(--pulsor-xxl) var(--pulsor-expo-out) 450ms backwards;
}
.preloader-tuile img {
  inline-size: 50%;
  block-size: auto;
}

/* Le roulé : la tuile avance de --roule-d et tourne de --roule-a, deux
   valeurs posées par preloader.js sur la largeur réelle du mot. L'angle est
   un tour entier, pour que la marque retombe droite. */
html[data-preloader="sort"] .preloader-tuile {
  translate: var(--roule-d, 0px) 0;
  rotate: var(--roule-a, 360deg);
  transition:
    translate var(--pre-roule) var(--pulsor-smooth),
    rotate var(--pre-roule) var(--pulsor-smooth);
}

/* Le nom. Chaque lettre monte depuis sous sa ligne, coupée par le bas du
   mot. Translation et opacité seulement : le flou du premier essai coûtait
   un filtre par lettre et par image, et saccadait. */
.preloader-mot {
  display: flex;
  margin: 0;
  font-family: var(--font-titre);
  font-weight: var(--graisse-titre);
  font-size: var(--pre-mot);
  line-height: 1;
  letter-spacing: -.04em;
  color: var(--noir);
  white-space: nowrap;
  /* Effacé derrière la tuile qui roule : le bord gauche de la coupe suit le
     centre de la tuile, même durée et même courbe, donc ils restent collés. */
  clip-path: inset(-.3em -.3em 0 var(--coupe-debut, -1em));
}
.preloader-mot span {
  display: inline-block;
  animation: pre-lettre var(--pulsor-m) var(--pulsor-expo-out) backwards;
  animation-delay: calc(850ms + var(--i) * var(--pre-lettre-pas));
}
html[data-preloader="sort"] .preloader-mot {
  clip-path: inset(-.3em -.3em 0 var(--coupe-fin, 110%));
  transition: clip-path var(--pre-roule) var(--pulsor-smooth);
}

/* La barre, la première à entrer, tracée de gauche à droite sous toute la
   marque. Elle part à 0,1 s pour ne pas se jouer avant la première image, et
   son gris est plus soutenu que le gris de grille, qui ne se voyait pas sur le
   fond. Elle grandit par une échelle, qui se calcule sur la carte graphique,
   et non par une coupe. */
.preloader-barre {
  display: block;
  inline-size: 100%;
  block-size: 2px;
  border-radius: var(--r-full);
  background: rgb(28 28 28 / .14);
  transform-origin: left center;
  animation: pre-barre var(--pulsor-xl) var(--pulsor-smooth) 100ms backwards;
}

@keyframes pre-barre {
  from { scale: 0 1; }
}
@keyframes pre-tuile {
  from { translate: 0 calc(100% + var(--pre-trait-ecart) + 4px); rotate: -360deg; }
}
@keyframes pre-lettre {
  from { opacity: 0; translate: 0 100%; }
}

/* --- La page, dessous ---------------------------------------------------

   Les entrées du premier écran (barre de navigation, titre mot par mot,
   sous-titre, boutons, prix) sont des animations CSS : elles sont tenues en
   pause tant que le voile est posé, et partent avec lui. Aucun script n'a à
   se parler. */
html[data-preloader="en-cours"] .entete,
html[data-preloader="en-cours"] .entete *,
html[data-preloader="en-cours"] .s-hero,
html[data-preloader="en-cours"] .s-hero *,
html[data-preloader="en-cours"] .consentement { animation-play-state: paused !important; }

@media (prefers-reduced-motion: reduce) {
  .preloader { display: none !important; }
}
