/* ══════════════════════════════════════════════════════════════════
   GROOMLY — hero d'accueil, deux colonnes et collage photo
   Portage natif du composant React « hero-section-9 ».

   Le projet est en Spring Boot + Thymeleaf : ni React, ni Tailwind,
   ni framer-motion, ni build. Chaque brique a son equivalent CSS :

     motion.div containerVariants ... @keyframes hsMonte + delais
     itemVariants (y: 20 -> 0) ...... translateY(20px) -> 0
     imageVariants (scale .8 -> 1) .. @keyframes hsPose
     floatingVariants (y: 0 -8 0) ... @keyframes hsFlotte, infinie
     staggerChildren: 0.2 ........... animation-delay par enfant
     Button variant="default" ....... .hs-btn-plein
     Button variant="outline" ....... .hs-btn-ligne
     grid lg:grid-cols-2 ............ .hs-grille

   Les jetons (--rose, --encre, --gris…) viennent de vitrine.css.
   ══════════════════════════════════════════════════════════════════ */

.hs {
  position: relative; overflow: hidden; isolation: isolate;
  background: var(--fond); padding: 56px 20px 72px;
}
@media (min-width: 1024px) { .hs { padding: 96px 24px 104px; } }

/* ══════════════════════════════════════════════════════════════════
   LE DEGRADE MAILLE ANIME
   Reprise de <MeshGradient> (@paper-design/shaders-react), qui dessine
   un maillage de couleurs en mouvement dans un canevas WebGL.

   Ici, pas de WebGL et pas de librairie : trois nappes de couleur
   floutees que l'on deplace lentement. C'est la technique classique du
   « mesh gradient » en CSS, et elle a deux avantages sur le shader :

     — Le flou est FIXE, seule la transformation bouge. Le navigateur
       peut donc confier l'animation au compositeur : pas de recalcul
       de mise en page, pas de repeinture, ca tourne sur le GPU comme
       le shader mais sans occuper un contexte WebGL.
     — Aucun script. Si le JS ne part pas, le fond vit quand meme.

   Le composant d'origine est noir (#000 / #1a1a1a / #2e2e2e / #fff).
   On garde le fond clair du site et on passe aux couleurs de la
   marque : rose, violet, ambre, tres dilues.
   ══════════════════════════════════════════════════════════════════ */
.hs-fond { position: absolute; inset: 0; z-index: -1; overflow: hidden; pointer-events: none; }

.hs-nuee {
  position: absolute; display: block; border-radius: 50%;
  filter: blur(70px); will-change: transform;
}
@media (min-width: 768px) { .hs-nuee { filter: blur(96px); } }

/* Trois durees premieres entre elles : les nappes ne repassent jamais
   par la meme configuration, le fond ne « boucle » donc pas a l'oeil. */
.hs-nuee-1 { top: -30%; left: -16%; width: 58vw; height: 58vw; max-width: 680px; max-height: 680px;
             background: radial-gradient(circle, rgba(244,63,94,.15) 0%, rgba(244,63,94,0) 70%);
             animation: hsDerive1 23s ease-in-out infinite; }
.hs-nuee-2 { top: 14%; right: -22%; width: 56vw; height: 56vw; max-width: 640px; max-height: 640px;
             background: radial-gradient(circle, rgba(139,92,246,.13) 0%, rgba(139,92,246,0) 70%);
             animation: hsDerive2 31s ease-in-out infinite; }
.hs-nuee-3 { bottom: -34%; left: 30%; width: 48vw; height: 48vw; max-width: 540px; max-height: 540px;
             background: radial-gradient(circle, rgba(251,191,36,.12) 0%, rgba(251,191,36,0) 70%);
             animation: hsDerive3 19s ease-in-out infinite; }

/* Le <filter id="glass-effect"> du composant : une turbulence posee
   par-dessus. Elle est declaree mais jamais appliquee dans l'original ;
   ici elle sert vraiment, a casser les bandes de degrade que les
   aplats tres dilues laissent apparaitre sur les grands ecrans. */
.hs-grain {
  position: absolute; inset: 0; display: block; opacity: .04; mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='b'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23b)'/%3E%3C/svg%3E");
}

@keyframes hsDerive1 {
  0%, 100% { transform: translate3d(0,0,0) scale(1); }
  50%      { transform: translate3d(9%, 7%, 0) scale(1.14); }
}
@keyframes hsDerive2 {
  0%, 100% { transform: translate3d(0,0,0) scale(1.06); }
  50%      { transform: translate3d(-11%, -6%, 0) scale(.92); }
}
@keyframes hsDerive3 {
  0%, 100% { transform: translate3d(0,0,0) scale(.96); }
  50%      { transform: translate3d(6%, -9%, 0) scale(1.12); }
}

.hs-grille {
  position: relative; z-index: 1;
  width: 100%; max-width: var(--max); margin: 0 auto;
  display: grid; grid-template-columns: 1fr; align-items: center; gap: 52px;
}
@media (min-width: 1024px) { .hs-grille { grid-template-columns: 1fr 1fr; gap: 40px; } }

/* Un enfant de grille a « min-width: auto » : il refuse de descendre
   sous la largeur minimale de son contenu. Les deux boutons cote a cote
   imposaient donc une colonne plus large que l'ecran, et le hero, qui
   est en overflow:hidden, rognait le texte au lieu de le faire passer
   a la ligne. */
.hs-texte, .hs-collage { min-width: 0; }

/* ── COLONNE DE GAUCHE ───────────────────────────────────────────── */
.hs-texte { display: flex; flex-direction: column; align-items: center; text-align: center; }
@media (min-width: 1024px) { .hs-texte { align-items: flex-start; text-align: left; } }

.hs-titre {
  font-size: clamp(2.2rem, 5.4vw, 3.9rem); font-weight: 800;
  line-height: 1.04; letter-spacing: -.042em; margin: 0;
  color: var(--encre); max-width: min(15ch, 100%); text-wrap: balance;
  animation: hsMonte .5s cubic-bezier(.16,1,.3,1) backwards;
}
.hs-titre em { font-style: normal; color: var(--rose-fonce); }

/* ══════════════════════════════════════════════════════════════════
   LE TITRE LETTRE PAR LETTRE
   Reprise de containerAnimation / letterAnimation : chaque caractere
   monte de 30 px en s'opacifiant, decale de 50 ms sur le precedent.

   Le decoupage est fait en JS (hero-animation.js) et non dans le HTML,
   pour trois raisons :
     — le gabarit reste lisible et modifiable sans compter des <span> ;
     — sans JS, le titre s'affiche normalement avec son ancienne
       animation d'ensemble — rien n'est casse ;
     — le lecteur d'ecran lit la phrase, pas quarante lettres : le JS
       pose un aria-label et masque les <span>.

   Le decalage est ramene a 30 ms. A 50 ms, « Votre location impeccable
   a chaque arrivee. » fait 38 caracteres, donc 1,9 s avant la fin du
   titre et pres de 3 s avant que le bouton n'apparaisse — le temps que
   met un visiteur a decider s'il reste. */
.hs-titre.hs-decoupe { animation: none; }
.hs-mot { display: inline-block; white-space: nowrap; }
.hs-lettre {
  display: inline-block;
  animation: hsLettre .5s cubic-bezier(.16,1,.3,1) both;
  animation-delay: calc(var(--i) * 30ms);
}

.hs-sous {
  margin: 22px 0 0; font-size: 1.0625rem; line-height: 1.6;
  color: var(--gris); max-width: min(46ch, 100%);
  animation: hsMonte .5s cubic-bezier(.16,1,.3,1) backwards;
  animation-delay: calc(var(--hs-fin, 200ms) - 120ms);
}
@media (min-width: 768px) { .hs-sous { font-size: 1.125rem; } }

.hs-actions {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 12px;
  margin-top: 30px; width: 100%;
  animation: hsMonte .5s cubic-bezier(.16,1,.3,1) backwards;
  animation-delay: calc(var(--hs-fin, 400ms) + 20ms);
}
@media (min-width: 1024px) { .hs-actions { justify-content: flex-start; } }

.hs-btn {
  display: inline-flex; align-items: center; gap: 9px; max-width: 100%;
  height: 50px; padding: 0 24px; border-radius: 13px;
  font-size: 15px; font-weight: 600; text-decoration: none;
  border: 1px solid transparent;
  transition: transform .16s, box-shadow .16s, background .16s, border-color .16s;
}
.hs-btn:focus-visible { outline: 2px solid var(--rose-fonce); outline-offset: 3px; }
.hs-btn svg { width: 17px; height: 17px; flex: none; }
.hs-btn-plein { background: var(--encre); color: var(--blanc); }
.hs-btn-plein:hover { background: #000; transform: translateY(-1px); }
/* variant « outline » : la bordure prend le rose de la marque au survol */
.hs-btn-ligne { background: var(--blanc); color: var(--encre); border-color: var(--trait); }
.hs-btn-ligne:hover { border-color: var(--rose); color: var(--rose-fonce); transform: translateY(-1px); }

/* ── LES CHIFFRES ────────────────────────────────────────────────
   Trois donnees verifiables, tirees de la grille tarifaire et de la
   zone reellement desservie. Aucun indicateur d'activite invente :
   annoncer « 15 000 clients » quand on en a un se voit, et se paie. */
.hs-chiffres {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 26px;
  margin-top: 44px;
  animation: hsMonte .5s cubic-bezier(.16,1,.3,1) backwards;
  animation-delay: calc(var(--hs-fin, 600ms) + 160ms);
}
@media (min-width: 1024px) { .hs-chiffres { justify-content: flex-start; gap: 32px; } }
.hs-chiffre { display: flex; align-items: center; gap: 11px; }

/* La pastille est un <span>, comme la legende. La regle de legende doit
   donc viser le <span> DANS le bloc de texte (.hs-chiffre div span), sinon
   elle atteint aussi la pastille : « .hs-chiffre span » pese 0,1,1 contre
   0,1,0 pour « .hs-pastille », elle lui rendait display:block et le
   centrage flex de l'icone ne s'appliquait plus — l'icone se calait en
   haut a gauche du cercle. */
.hs-chiffre .hs-pastille {
  width: 40px; height: 40px; border-radius: 50%; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  margin: 0; font-size: 0; line-height: 0;
  background: var(--blanc); border: 1px solid var(--trait); color: var(--rose-fonce);
}
.hs-pastille svg { width: 18px; height: 18px; display: block; }
.hs-chiffre div b { display: block; font-size: 1.125rem; font-weight: 800;
                    letter-spacing: -.02em; color: var(--encre); line-height: 1.2; }
.hs-chiffre div span { display: block; font-size: .8125rem; line-height: 1.35;
                       color: var(--gris); margin-top: 1px; }

/* ── COLONNE DE DROITE : le collage ──────────────────────────────
   Le composant d'origine empile trois images en position absolue sur
   une hauteur fixe (400/500 px). On garde le principe mais la hauteur
   suit la largeur : figee, elle laisse un trou sur grand ecran et fait
   chevaucher les vues sur petit. */
.hs-collage { position: relative; width: 100%; max-width: 520px; margin: 0 auto;
              aspect-ratio: 1 / 1; }
@media (min-width: 1024px) { .hs-collage { max-width: none; aspect-ratio: 1 / .94; } }

.hs-vue {
  position: absolute; border-radius: 20px; padding: 7px;
  background: var(--blanc); box-shadow: 0 22px 48px -20px rgba(15,15,30,.30);
  animation: hsPose .55s cubic-bezier(.16,1,.3,1) backwards;
}
.hs-vue img { display: block; width: 100%; height: 100%; border-radius: 14px; object-fit: cover; }

.hs-vue-2 { right: 0; top: 33%; width: 47%; aspect-ratio: 1/1;
            transform-origin: left center; animation-delay: .45s; }
.hs-vue-3 { left: 0; bottom: 0; width: 45%; aspect-ratio: 1/1;
            transform-origin: top right; animation-delay: .65s; }

/* La vue centrale est deja translatee horizontalement : son animation
   doit conserver ce decalage, sinon elle glisse hors de la colonne en
   apparaissant. Elle a donc sa propre suite d'images-cles. */
.hs-vue-1 { left: 50%; top: 0; width: 53%; aspect-ratio: 4/5;
            transform: translateX(-50%); transform-origin: bottom center;
            animation-name: hsPoseCentre; animation-delay: .25s; }

/* Formes flottantes : le rose, le violet et l'ambre de la marque,
   pas le bleu et le vert du composant d'origine. */
.hs-forme { position: absolute; border-radius: 50%; animation: hsFlotte 3s ease-in-out infinite; }
/* Les trois vues occupent presque tout le cadre : les formes sont posees
   dans les creux qui restent, sinon elles passent derriere une photo et
   ne servent a rien. */
.hs-forme-1 { top: -10px; left: 11%; width: 62px; height: 62px; background: rgba(244,63,94,.18); }
.hs-forme-2 { bottom: 6%; right: 20%; width: 46px; height: 46px; border-radius: 13px;
              background: rgba(139,92,246,.16); animation-delay: .5s; }
.hs-forme-3 { top: 6%; right: 4%; width: 26px; height: 26px;
              background: rgba(251,191,36,.34); animation-delay: 1s; }

@keyframes hsMonte      { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: none; } }
/* letterAnimation : { opacity: 0, y: 30 } -> { opacity: 1, y: 0 } */
@keyframes hsLettre     { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: none; } }
@keyframes hsPose       { from { opacity: 0; transform: scale(.8); }        to { opacity: 1; transform: scale(1); } }
@keyframes hsPoseCentre { from { opacity: 0; transform: translateX(-50%) scale(.8); }
                          to   { opacity: 1; transform: translateX(-50%) scale(1); } }
@keyframes hsFlotte     { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }

/* Un fond qui derive en permanence est exactement ce que cette
   preference demande d'arreter : on fige les nappes, on ne les
   supprime pas — la composition de couleurs reste. */
@media (prefers-reduced-motion: reduce) {
  .hs-titre, .hs-sous, .hs-actions, .hs-chiffres, .hs-vue, .hs-forme,
  .hs-lettre, .hs-nuee { animation: none; }
  .hs-lettre { opacity: 1; transform: none; }
}

/* ══════════════════════════════════════════════════════════════════
   SUR TELEPHONE, LES NAPPES NE DERIVENT PLUS

   Trois disques de 700 a 760 px, flous de 80 a 110 px, deplaces en
   boucle et sans fin. Sur un ordinateur, le compositeur garde le flou
   en cache et ne fait que deplacer le calque. Sur un telephone, la
   marge de manoeuvre est bien plus mince : un flou de cette taille
   recalcule en continu, c'est du travail permanent pour un fond que
   personne ne regarde, et de la batterie qui part.

   On garde la composition de couleurs — c'est elle qu'on voit. On
   n'arrete que le mouvement, et seulement sous 768 px. Exactement ce
   que fait deja le bloc « prefers-reduced-motion » juste au-dessus,
   pour la meme raison.

   Honnetete sur la mesure : je n'ai PAS pu chiffrer ce gain ici. Un
   navigateur sans ecran ne produit aucune image quand la page est
   immobile — la trace revient vide, avec ou sans animation. Le
   raisonnement tient, la mesure manque. Si le telephone ne va pas
   mieux, c'est ce changement-la qu'il faut defaire en premier. */
@media (max-width: 767px) {
  /* Meme raison qu'ailleurs : un calque reserve pour un fond qui ne
     bouge plus n'est que de la memoire video immobilisee. */
  .hs-nuee, .hs-forme { animation: none; will-change: auto; }
}
