/* ============================================================================
   FIT-NS — Système de mouvement.
   Adapté de « vie-et-mouvement / motion.css », réglé sur la marque.
   CSS pur, aucune dépendance. Rien ne s'active tout seul : on applique
   les classes dans le HTML.
   ========================================================================== */

:root {
  /* --- Marque ------------------------------------------------------------ */
  --vm-accent: #f26522;

  /* --- Durées : 120 à 400 ms. Ne jamais dépasser. ------------------------ */
  --vm-instant: 120ms;   /* retour tactile : pression */
  --vm-rapide:  180ms;   /* survol */
  --vm-normal:  260ms;   /* apparition, ouverture */
  --vm-lent:    380ms;   /* transition de bloc */

  /* --- Courbes ----------------------------------------------------------- */
  --vm-entree:  cubic-bezier(0.16, 0.84, 0.44, 1);
  --vm-sortie:  cubic-bezier(0.55, 0, 0.85, 0.35);
  --vm-doux:    cubic-bezier(0.4, 0, 0.2, 1);
  --vm-ressort: cubic-bezier(0.34, 1.4, 0.5, 1);

  --vm-cascade: 70ms;

  /* Permet d'animer une hauteur « auto » (accordéon FAQ). Chrome 129+,
     dégradation propre ailleurs : le dépliage devient instantané. */
  interpolate-size: allow-keywords;
}

/* ----------------------------------------------------------------------------
   ACCESSIBILITÉ — non négociable (WCAG 2.3.3).
   On ne supprime pas les états (le survol reste lisible), on supprime le
   déplacement.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .vm-reveal, .vm-reveal > * { opacity: 1 !important; transform: none !important; }
  .vm-carte, .vm-btn, .vm-cadre img { translate: none !important; scale: none !important; }
  .vm-ken-burns img { animation: none !important; }
  .vm-mot__int { transform: none !important; animation: none !important; }
  .vm-mot__masque { overflow: visible !important; }
  .vm-parallaxe, .vm-remise { animation: none !important; }
  .vm-remise { opacity: 1 !important; transform: none !important; }
}

/* ============================================================================
   1. RÉACTIVITÉ — tout ce qui est cliquable doit répondre
   ========================================================================== */

.vm-btn {
  --vm-btn-y: 0px;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6em;
  border: 0;
  cursor: pointer;
  isolation: isolate;
  text-decoration: none;
  /* « translate » et non « transform » : voir la note en fin de fichier. */
  translate: var(--vm-magnet-x, 0px) calc(var(--vm-btn-y) + var(--vm-magnet-y, 0px));
  transition:
    translate var(--vm-rapide) var(--vm-ressort),
    filter    var(--vm-rapide) var(--vm-doux),
    color     var(--vm-rapide) var(--vm-doux),
    border-color var(--vm-rapide) var(--vm-doux);
}
/* L'ombre est portée par un pseudo-élément : on anime son opacity, jamais la
   box-shadow elle-même (repaint coûteux à chaque frame). */
.vm-btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  box-shadow: 0 14px 30px -10px color-mix(in oklch, var(--vm-accent) 65%, transparent);
  opacity: 0;
  transition: opacity var(--vm-rapide) var(--vm-doux);
}
.vm-btn:hover  { --vm-btn-y: -2px; filter: brightness(1.07); }
.vm-btn:hover::before { opacity: 1; }
.vm-btn:active { --vm-btn-y: 1px; transition-duration: var(--vm-instant); }

/* Flèche qui avance. */
.vm-btn .vm-fleche {
  display: inline-flex;
  transition: translate var(--vm-rapide) var(--vm-ressort);
}
.vm-btn:hover .vm-fleche { translate: 4px 0; }

/* Reflet balayant — réservé au bouton principal, une seule fois par page. */
.vm-btn--reflet { overflow: hidden; }
.vm-btn--reflet::after {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: -60%;
  width: 45%;
  background: linear-gradient(100deg, transparent, rgb(255 255 255 / 0.3), transparent);
  transform: skewX(-18deg);
  transition: translate var(--vm-lent) var(--vm-doux);
  pointer-events: none;
}
.vm-btn--reflet:hover::after { translate: 340% 0; }

/* Bouton fantôme : le fond monte depuis le bas (scaleY, pas height). */
.vm-btn--fantome { background: transparent; overflow: hidden; }
.vm-btn--fantome::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--vm-accent);
  scale: 1 0;
  transform-origin: bottom;
  transition: scale var(--vm-normal) var(--vm-entree);
}
.vm-btn--fantome:hover::after { scale: 1 1; }

/* Lien de texte : soulignement qui se déroule. */
.vm-lien {
  color: inherit;
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 1.5px;
  transition: background-size var(--vm-normal) var(--vm-entree),
              color var(--vm-rapide) var(--vm-doux);
}
.vm-lien:hover, .vm-lien:focus-visible { background-size: 100% 1.5px; }

/* Carte réactive : soulèvement, bordure vivante, ombre par pseudo-élément. */
.vm-carte {
  position: relative;
  isolation: isolate;
  transition:
    translate    var(--vm-normal) var(--vm-entree),
    border-color var(--vm-normal) var(--vm-doux);
}
.vm-carte::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  box-shadow: 0 28px 56px -22px rgb(0 0 0 / 0.85);
  opacity: 0;
  transition: opacity var(--vm-normal) var(--vm-doux);
}
.vm-carte:hover { translate: 0 -5px; }
.vm-carte:hover::before { opacity: 1; }

/* Projecteur suivant le curseur — la bordure s'illumine côté pointeur.
   Les variables --mx / --my sont posées en JS, hors du cycle de rendu. */
.vm-projecteur::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  border-radius: inherit;
  padding: 1px;
  background: radial-gradient(
    240px circle at var(--mx, 50%) var(--my, 0%),
    color-mix(in oklch, var(--vm-accent) 85%, transparent),
    transparent 62%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  opacity: 0;
  transition: opacity var(--vm-normal) var(--vm-doux);
  pointer-events: none;
}
.vm-projecteur:hover::after,
.vm-projecteur:focus-within::after { opacity: 1; }

/* ============================================================================
   2. IMAGES
   ========================================================================== */

.vm-cadre { overflow: hidden; margin: 0; transform: translateZ(0); }
.vm-cadre img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: scale var(--vm-lent) var(--vm-doux);
}
.vm-cadre:hover img,
a:hover .vm-cadre img { scale: 1.05; }

/* Ken Burns — dérive très lente. UNE SEULE par page, jamais derrière un
   paragraphe qu'on lit longuement. */
.vm-ken-burns { overflow: hidden; }
.vm-ken-burns img {
  animation: vm-derive 32s var(--vm-doux) infinite alternate;
  transform-origin: 62% 42%;
}
@keyframes vm-derive {
  from { transform: scale(1.02) translate3d(0, 0, 0); }
  to   { transform: scale(1.11) translate3d(-1.6%, -1.2%, 0); }
}

/* ============================================================================
   3. APPARITIONS AU SCROLL
   Nécessite main.js. Sans JS, tout reste visible : le contenu ne dépend
   jamais du script.
   ========================================================================== */

html.vm-js .vm-reveal {
  opacity: 0;
  transform: translateY(18px);   /* jamais plus de 24px */
  transition:
    opacity   var(--vm-lent) var(--vm-entree),
    transform var(--vm-lent) var(--vm-entree);
  transition-delay: calc(var(--vm-i, 0) * var(--vm-cascade));
}
html.vm-js .vm-reveal.est-visible { opacity: 1; transform: none; }

html.vm-js .vm-reveal--gauche { transform: translateX(-24px); }
html.vm-js .vm-reveal--droite { transform: translateX(24px); }
html.vm-js .vm-reveal--zoom   { transform: scale(0.965); }

.vm-cascade > .vm-reveal:nth-child(1) { --vm-i: 0; }
.vm-cascade > .vm-reveal:nth-child(2) { --vm-i: 1; }
.vm-cascade > .vm-reveal:nth-child(3) { --vm-i: 2; }
.vm-cascade > .vm-reveal:nth-child(4) { --vm-i: 3; }
.vm-cascade > .vm-reveal:nth-child(5) { --vm-i: 4; }
.vm-cascade > .vm-reveal:nth-child(6) { --vm-i: 5; }
.vm-cascade > .vm-reveal:nth-child(n+7) { --vm-i: 5; }

/* Titre découpé en mots — chaque mot se lève DERRIÈRE UN MASQUE.
   Le découpage est fait en JS, sur les titres uniquement, jamais sur un
   paragraphe : un paragraphe dont les mots bougent ne se lit plus.

   C'est le seul geste signature de la page. Il dit ce que la marque vend :
   quelque chose qui se relève. Tout le reste du mouvement est volontairement
   discret pour que celui-ci porte.

   Le masque déborde SOUS la ligne de base (padding + marge négative), sinon
   les jambages des g, j, p, q, y sont rognés dans l'état final — le piège
   classique de cet effet, invisible tant qu'on ne teste pas le bon mot. */
html.vm-js .vm-mot__masque {
  display: inline-block;
  overflow: hidden;
  padding-block-end: 0.16em;
  margin-block-end: -0.16em;
  vertical-align: bottom;
}
/* Le mot d'accent du hero est en display:block : son masque doit l'être
   aussi, sinon la ligne se replie sur la précédente. */
html.vm-js .vm-mot__masque--bloc { display: block; }

html.vm-js .vm-mot__int {
  display: inline-block;
  transform: translateY(105%);
  transition: transform var(--vm-lent) var(--vm-entree);
  transition-delay: calc(var(--vm-w, 0) * 55ms);
}
html.vm-js .vm-mot.est-visible .vm-mot__int { transform: none; }

/* Variante d'entrée de page. Le hero ne doit JAMAIS dépendre du défilement :
   ici le mouvement est une animation qui part au chargement, pas une
   transition déclenchée par un observateur. */
html.vm-js .vm-mot--entree .vm-mot__int {
  transform: none;
  transition: none;
  animation: vm-lever var(--vm-lent) var(--vm-entree) backwards;
  animation-delay: calc(90ms + var(--vm-w, 0) * 62ms);
}
@keyframes vm-lever { from { transform: translateY(105%); } }

/* ============================================================================
   4. ENTRÉE DE PAGE
   Le contenu au-dessus de la ligne de flottaison ne dépend JAMAIS du scroll.
   ========================================================================== */
.vm-entree > * { animation: vm-monte var(--vm-lent) var(--vm-entree) backwards; }
/* Le titre du hero porte déjà son propre lever, mot par mot. Le faire monter
   EN PLUS comme un bloc produit deux mouvements superposés qui se battent —
   le défaut de doublon le plus courant quand on ajoute une animation à une
   page qui en avait déjà une. */
.vm-entree > .vm-mot--entree { animation: none; }
.vm-entree > *:nth-child(1) { animation-delay: 60ms; }
.vm-entree > *:nth-child(2) { animation-delay: 140ms; }
.vm-entree > *:nth-child(3) { animation-delay: 220ms; }
.vm-entree > *:nth-child(4) { animation-delay: 300ms; }
.vm-entree > *:nth-child(5) { animation-delay: 380ms; }
.vm-entree > *:nth-child(n+6) { animation-delay: 440ms; }
@keyframes vm-monte {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

/* ============================================================================
   5. MATIÈRE DE FOND
   ========================================================================== */

/* Grain — supprime l'effet « aplat numérique ». SVG en data-URI, ~0,4 ko,
   posé sur un calque fixe : jamais sur un conteneur qui défile (repaints). */
.vm-grain {
  position: fixed;
  inset: 0;
  z-index: 90;
  pointer-events: none;
  opacity: 0.04;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* Lueur d'ambiance — radiale, très étalée, hors-centre, une seule teinte.
   Remplace le dégradé 45° du hero générique. */
.vm-lueur { position: relative; isolation: isolate; }
.vm-lueur::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    radial-gradient(70% 60% at var(--lueur-x, 10%) var(--lueur-y, 0%),
      color-mix(in oklch, var(--vm-accent) 14%, transparent), transparent 62%);
}

/* Barre de progression de lecture — pilotée par le scroll, sans JS.
   Seul cas où une animation liée au scroll est fiable partout où elle existe. */
.vm-progression {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  height: 2px;
  z-index: 120;
  background: var(--vm-accent);
  transform-origin: 0 50%;
  scale: 0 1;
}
@supports (animation-timeline: scroll()) {
  .vm-progression {
    animation: vm-progresser linear;
    animation-timeline: scroll(root block);
  }
  @keyframes vm-progresser { to { scale: 1 1; } }
}

/* Parallaxe pilotée par le scroll, sans JS et sans écouteur.
   Repli silencieux : sans support, l'élément reste immobile. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .vm-parallaxe {
      animation: vm-derapage linear both;
      animation-timeline: view();
      animation-range: entry 0% exit 100%;
    }
    @keyframes vm-derapage {
      from { transform: translateY(var(--par-de, 5%)); }
      to   { transform: translateY(var(--par-a, -5%)); }
    }
    /* Trait de liaison qui se dessine à mesure qu'on descend. */
    .vm-trace {
      animation: vm-tracer linear both;
      animation-timeline: view();
      animation-range: entry 30% cover 55%;
      transform-origin: 0 50%;
    }
    @keyframes vm-tracer { from { scale: 0 1; } to { scale: 1 1; } }

    /* Passage de relais du hero : le texte s'efface en montant pendant que
       la section sort. C'est le premier geste que fait le visiteur, donc le
       seul endroit où un effet lié au défilement se remarque vraiment.
       Piloté par la timeline de vue : rien sur le fil principal, aucun
       écouteur, et l'effet s'annule tout seul là où il n'est pas géré. */
    .vm-remise {
      animation: vm-remettre linear both;
      animation-timeline: view();
      animation-range: exit 10% exit 95%;
    }
    @keyframes vm-remettre {
      to { transform: translateY(-40px); opacity: 0; }
    }
  }
}

/* ============================================================================
   6. DÉTAILS
   ========================================================================== */

/* Accordéon FAQ — le signe pivote, le contenu se déplie. */
.vm-accordeon summary { cursor: pointer; list-style: none; }
.vm-accordeon summary::-webkit-details-marker { display: none; }
.vm-accordeon summary .vm-signe {
  display: inline-block;
  transition: rotate var(--vm-normal) var(--vm-ressort),
              color  var(--vm-rapide) var(--vm-doux);
}
.vm-accordeon[open] summary .vm-signe { rotate: 135deg; }
.vm-accordeon::details-content {
  block-size: 0;
  overflow: hidden;
  opacity: 0;
  transition:
    block-size var(--vm-normal) var(--vm-entree),
    opacity    var(--vm-normal) var(--vm-entree),
    content-visibility var(--vm-normal) allow-discrete;
}
.vm-accordeon[open]::details-content { block-size: auto; opacity: 1; }

/* ============================================================================
   NOTE D'ARCHITECTURE — « translate » plutôt que « transform »

   Un même élément est souvent à la fois une carte survolable et un bloc révélé
   au scroll (class="vm-carte vm-reveal"). Si les deux passent par « transform »,
   html.vm-js .vm-reveal.est-visible { transform: none } écrase
   .vm-carte:hover { transform: ... } et la carte ne se soulève plus jamais.

   Partage strict :
     • « transform »                        → apparitions (.vm-reveal, .vm-entree, .vm-parallaxe)
     • « translate » / « scale » / « rotate » → interactions (:hover, :active, :focus-within)
   Ce sont des propriétés indépendantes : elles se composent au lieu de s'écraser.
   ========================================================================== */
