/* OPEPARTNER — « Une heure pour avancer »
   Landing autonome, sans menu ni page interne autre que les deux pages légales.
   Priorité absolue au téléphone : la moitié des visites viennent d'un QR scanné debout.

   Aucun style inline dans index.html : la CSP peut donc interdire style-src 'unsafe-inline'
   (voir nginx.conf.template). Toute règle ajoutée doit rester dans ce fichier. */

html { scroll-behavior: smooth; }
html, body { margin: 0; padding: 0; background: var(--creme); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

/* Le focus doit rester visible : une part des visiteurs arrive au clavier ou au lecteur
   d'écran depuis le QR, et le parcours entier tient dans un seul bouton de réservation. */
:where(a, button, input, iframe):focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.ope-wrap {
  max-width: var(--container-max);
  margin: 0 auto;
  padding-left: clamp(20px, 5vw, 40px);
  padding-right: clamp(20px, 5vw, 40px);
}

/* Filet orange court, repris de section en section pour marquer les titres. */
.ope-filet {
  display: block; width: 56px; height: 2px; border: 0;
  background: var(--orange); margin: 22px 0 0;
}

.ope-titre {
  font-family: var(--font-display); font-weight: var(--fw-semibold);
  font-size: clamp(27px, 4.2vw, 44px); line-height: 1.12; letter-spacing: -0.015em;
  color: var(--marine); margin: 0; text-wrap: pretty;
}

.ope-section { padding-top: clamp(52px, 8vw, 92px); padding-bottom: clamp(52px, 8vw, 92px); }

/* Valeur qui reste à renseigner avant mise en ligne : doit sauter aux yeux.
   Même principe que .legal-todo sur les pages légales. */
.ope-todo {
  background: var(--orange); color: #FFFFFF;
  padding: 1px 7px; border-radius: var(--radius-sm);
  font-size: var(--fs-small); font-weight: var(--fw-semibold);
}

/* ============================================================
   BLOCS 1 + 2 — titre et calendrier
   ============================================================
   Le bandeau marine reprend la construction de la landing Entreprises : kicker à
   filet orange, titre en Spectral dont la dernière ligne bascule en doré, et une
   colonne de droite séparée par un filet vertical, qui porte le texte et le bouton.

   Ce que ça remplace, et pourquoi : le chapô était auparavant coupé en deux, et sa
   seconde moitié passait SOUS le calendrier sur téléphone, pour que le module de
   réservation apparaisse à 265px. Ce n'est plus tenable dès lors que le bouton doit
   être dans le premier écran — le calendrier y perd sa place, le bouton la prend et
   y mène. Toutes les valeurs mobiles ci-dessous sont donc resserrées : chaque pixel
   gagné ici est un pixel de calendrier plus haut. Voir README, « Choix techniques ». */

.hero { display: grid; }

.hero__intro {
  position: relative;
  background: var(--marine);
  padding-top: 16px;
  padding-bottom: 22px;
}

.hero__logo { height: 22px; width: auto; display: block; }

/* Empilée sous 860px, en deux colonnes au-delà. Le point de bascule est explicite et
   non calculé par auto-fit : c'est celui de toute la page — vague, logo, hauteur du
   calendrier — et deux ruptures voisines mais distinctes donneraient une zone bâtarde
   où la vague apparaîtrait avant les colonnes.
   align-items:end cale les deux colonnes sur leur bas : la dernière ligne du titre et
   le bouton arrivent alors à la même altitude. */
.hero__grille { display: grid; gap: 16px; }

/* Colonnes déséquilibrées à dessein, là où la landing Entreprises les prend égales :
   la ligne la plus longue du titre mesure 10,5 em, contre 8,9 em là-bas. À colonnes
   égales elle se couperait en deux au-delà de 860px — et c'est précisément la ligne
   dorée, celle dont la coupe défait la bascule. 1,2 / 0,8 lui donne la place ; le
   texte de droite est court et s'en accommode. */
@media (min-width: 860px) {
  .hero__grille {
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr);
    gap: clamp(36px, 5vw, 72px);
    align-items: end;
  }
}

/* Kicker. Le filet est un ::before plutôt qu'un élément vide : rien à ajouter dans le
   HTML, et il reste solidaire de la ligne de texte. */
.hero__kicker {
  display: flex; align-items: center; gap: 14px;
  font-size: 13px; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--beige-500);
  margin: 18px 0 14px;
}
.hero__kicker::before {
  content: ""; flex: 0 0 auto;
  width: 40px; height: 2px; background: var(--orange);
}

/* Échelle : même pente que la landing Entreprises (5,2vw) tant que le titre occupe
   toute la largeur. Les tailles retenues gardent partout une marge d'au moins 10 %
   sur les 10,5 em de la ligne dorée — c'est ce qui garantit les trois lignes.
   À 320px d'écran, aucune taille lisible ne la fait tenir : elle passe alors sur deux
   lignes, et c'est le seul cas où la composition en trois lignes cède. */
.hero__titre {
  font-family: var(--font-display); font-weight: var(--fw-semibold);
  font-size: clamp(29px, 5.2vw, 60px); line-height: 1.06; letter-spacing: -0.02em;
  color: var(--creme); margin: 0;
}
@media (max-width: 349px) { .hero__titre { font-size: 26px; } }

/* Le doré du wordmark, seul rescapé de colors.css que colors-1h.css ne remappe pas.
   C'est le contraste entre les trois participes en crème et cette dernière ligne qui
   porte la bascule : les quatre lignes de la même couleur, et l'effet tombe. */
.hero__titre-bascule { color: var(--beige-500); }

/* Filet vertical de séparation. Porté par le texte lui-même, pas par la colonne : il
   s'arrête donc avec le texte et ne descend pas le long du bouton. */
.hero__texte {
  padding-left: 26px;
  border-left: 1px solid var(--color-border-inverse);
  font-size: clamp(15px, 4vw, 17px); line-height: 1.65;
  color: var(--color-text-inverse-muted);
}
.hero__texte p { margin: 0; max-width: 58ch; text-wrap: pretty; }
.hero__texte p + p { margin-top: 8px; }

/* Le bouton est hors du filet, mais aligné sur le texte : même retrait de 26px. */
.hero__action { margin: 20px 0 0; padding-left: 26px; }

/* L'ombre détache le bouton du bandeau marine, où l'aplat orange ne se suffit pas.
   Elle reste locale au hero : le BLOC 8 est marine lui aussi, et son bouton s'en passe. */
.hero__action .ope-cta { box-shadow: 0 8px 22px rgba(6,32,46,0.28); }

/* Sous 480px, le hero est comprimé au maximum de ce qu'il supporte : c'est là que le
   QR code est scanné debout, et tout ce qui est gagné remonte le calendrier. La
   seconde phrase du texte descend au BLOC 4, qui la reprend en plus détaillé. */
@media (max-width: 479px) {
  /* Le kicker doit tenir sur une ligne : à 13px et 0,2em d'interlettre il déborde de
     335px et retombe sous son propre filet. Resserré, il tient jusqu'à 320px. */
  .hero__kicker { margin: 14px 0 12px; font-size: 11px; letter-spacing: 0.16em; gap: 10px; }
  .hero__kicker::before { width: 28px; }
  .hero__detail { display: none; }
  .hero__action { margin-top: 16px; }
  .hero__intro { padding-bottom: 18px; }
}

/* La vague coûte une centaine de pixels : sur téléphone, ce sont cent pixels de
   calendrier en moins dans le premier écran. On la réserve aux grands écrans ; la
   rupture franche marine / crème se tient très bien seule sur mobile. */
.hero__vague { display: none; }

@media (min-width: 860px) {
  /* 132px de fond laissaient 12px sous le bouton avant les 120px de vague : le bloc
     paraissait tassé et le bouton collé au bord. 200px rendent une vraie respiration
     (~80px de marine visible) et donnent au hero la hauteur qui lui manquait. */
  .hero__intro { padding-top: 44px; padding-bottom: 200px; }
  .hero__logo { height: 30px; }
  .hero__kicker { margin: 40px 0 20px; }
  /* La colonne vaut désormais un peu plus de la moitié de la page : l'échelle repart
     d'un cran plus bas, sans quoi la ligne dorée déborde. */
  .hero__titre { font-size: clamp(38px, 4.4vw, 54px); }
  .hero__vague {
    display: block; position: absolute; left: 0; right: 0; bottom: -1px;
    width: 100%; height: 120px;
  }
  /* Le bouton doit rester au-dessus de la vague, qui remonte jusque sous les colonnes. */
  .hero__grille { position: relative; z-index: 1; }
}

/* scroll-margin : le lien du BLOC 8 remonte ici, le titre ne doit pas coller au bord. */
.hero__book { padding-top: 22px; padding-bottom: clamp(40px, 6vw, 64px); scroll-margin-top: 12px; }

.hero__book-titre {
  font-family: var(--font-display); font-weight: var(--fw-semibold);
  font-size: clamp(20px, 5.2vw, 32px); line-height: 1.15; letter-spacing: -0.01em;
  color: var(--marine); margin: 0 0 14px;
}

/* Consigne au-dessus du calendrier. Volontairement en Manrope, pas en Spectral : c'est
   une instruction, pas un des deux titres de choix ci-dessous, et rien ne doit prêter à
   confusion entre les deux rôles. */
.hero__book-consigne {
  font-size: clamp(16px, 4.2vw, 18px); line-height: 1.5;
  color: var(--color-text-muted); margin: -4px 0 14px;
}

/* Cadre du module Axonaut.
   ------------------------
   Ni fond, ni ombre, ni arrondi : en intégration iframe, Axonaut masque son en-tête,
   resserre ses marges, force `background: transparent` et dessine sa propre carte
   blanche arrondie et ombrée. Un habillage de notre côté en ferait une seconde, visible
   autour de la première ; le crème de la section traverse jusqu'à la sienne.

   Hauteurs mesurées sur le module lui-même : 583px en deux colonnes, 1095px une fois
   empilé sur téléphone. On ne suit pas la hauteur qu'Axonaut annonce par `postMessage` :
   elle est fiable en environnement de test, mais un navigateur ordinaire y ajoute ce que
   la page charge en plus (assistant, fenêtres de dialogue hors flux) et annonce alors
   plusieurs centaines de pixels de trop — d'où un vide béant sous la carte, impossible à
   reproduire ici. Une hauteur fixe est prévisible et vérifiable ; si le module dépasse,
   il défile dans son propre cadre. */
.hero__frame {
  width: 100%; height: 1120px; border: 0; display: block;
  background: transparent;
}
@media (min-width: 860px) {
  .hero__frame { height: 600px; }
}

/* Formulaire d'attente, replié. Voir .si-creneaux / .si-vide plus bas : le déclencheur
   change de libellé selon l'état, le formulaire est le même dans les deux cas.
   L'écart avec ce qui précède se règle plus haut, sur le cadre lui-même : posé ici il
   subsisterait quand le calendrier est masqué. */
.repli { margin-top: 6px; }

/* Les deux libellés — « la prochaine session est en préparation » et « vous ne trouvez
   pas de créneau » — sont les deux faces d'un même choix : même style, un cran sous le
   titre du bloc. Le triangle, posé sur le libellé lui-même, suit la fin du texte plutôt
   que de rester isolé dans un coin, et signale seul que le bloc se déplie. */

/* La case pilote l'ouverture. Hors écran plutôt que `display:none` : elle doit rester
   atteignable au clavier, où la barre d'espace déplie le bloc. */
.repli__case {
  position: absolute; width: 1px; height: 1px;
  margin: 0; padding: 0; border: 0; clip-path: inset(50%); overflow: hidden;
}

.repli__declencheur {
  display: block; cursor: pointer;
  font-family: var(--font-display); font-weight: var(--fw-semibold);
  font-size: clamp(18px, 4.6vw, 22px); line-height: 1.3;
  letter-spacing: -0.01em; color: var(--marine);
  padding: 4px 0; max-width: 50ch; text-wrap: pretty;
}
.repli__declencheur:hover { color: var(--orange-survol); }
.repli__case:focus-visible + .repli__declencheur {
  outline: 2px solid var(--color-focus-ring); outline-offset: 4px; border-radius: 4px;
}

/* Collé au dernier mot sans espace intercalaire, le triangle n'a aucune occasion de
   partir seul à la ligne suivante : l'écart vient d'une marge, pas d'un blanc sécable.
   La rotation ne porte ainsi que sur le triangle. */
.repli__libelle::after {
  content: '\25BE';
  display: inline-block; margin-left: 0.28em; color: var(--orange);
  transition: transform 0.18s ease;
}
.repli__case:checked ~ .repli__declencheur .repli__libelle::after {
  transform: rotate(180deg);
}
@media (prefers-reduced-motion: reduce) {
  .repli__libelle::after { transition: none; }
}

/* Replié par défaut ; /etat.css force l'ouverture quand aucun créneau n'est disponible. */
.repli__contenu {
  display: none;
  background: #FFFFFF; border: 1px solid var(--gris-bleu-200);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-card);
  padding: clamp(24px, 5vw, 36px);
  margin-top: 12px;
}
.repli__case:checked ~ .repli__contenu { display: block; }

.repli__texte {
  font-size: clamp(16px, 4.2vw, 18px); line-height: 1.6;
  color: var(--marine); margin: 0 0 22px; max-width: 46ch; text-wrap: pretty;
}

/* ============================================================
   Bascule créneaux ouverts / fermés
   ============================================================
   .si-creneaux et .si-vide ne sont volontairement définies nulle part dans ce fichier :
   /etat.css tranche, et lui seul, en masquant l'un des deux états. En production nginx
   le génère à partir de OPE_CRENEAUX_OUVERTS et n'expose jamais un calendrier vide ;
   en local, public/etat.css sert de défaut. Ajouter ici une règle sur ces classes
   casserait la bascule — le détail est expliqué en tête de public/etat.css. */

/* ============================================================
   Formulaire
   ============================================================ */

.ope-form { display: grid; gap: 14px; }
@media (min-width: 620px) {
  .ope-form { grid-template-columns: 1fr 1fr; }
  .ope-form__large { grid-column: 1 / -1; }
}

.ope-field { display: flex; flex-direction: column; gap: 6px; }
.ope-field label {
  font-size: var(--fs-small); font-weight: var(--fw-semibold); color: var(--marine);
}
.ope-field label span { font-weight: var(--fw-regular); color: var(--ardoise-700); }
.ope-field input {
  width: 100%; box-sizing: border-box;
  font-family: var(--font-sans); font-size: 16px; /* < 16px : iOS zoome au focus */
  color: var(--marine); background: #FFFFFF;
  border: 1px solid var(--gris-bleu-200); border-radius: var(--radius-md);
  padding: 12px 14px; outline: none;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.ope-field input:focus {
  border-color: var(--orange); box-shadow: var(--ring-focus);
}

/* Piège à robots : hors écran et hors du parcours clavier. Tout envoi dont ce champ
   est rempli est écarté côté n8n. Ne jamais lui ajouter de label ni de placeholder. */
.ope-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.ope-status {
  margin: 0; font-size: var(--fs-small); line-height: 1.5; color: var(--marine);
}
.ope-status:empty { display: none; }
.ope-status[data-erreur="1"] { color: #A33327; }

/* ============================================================
   Modale de confirmation d'envoi
   ============================================================
   Un <dialog> fermé est déjà en display:none par la feuille de l'agent utilisateur.
   Rien ici ne le masque, et rien ne doit le faire : c'est showModal() qui l'ouvre, et
   lui seul. Les règles ci-dessous ne décrivent que son apparence une fois ouvert.

   La largeur est bornée à la fenêtre moins deux gouttières : sur un téléphone tenu
   debout, la modale ne doit jamais toucher les bords. margin:auto la recentre — un
   <dialog> ouvert est en position absolute et ne se centre pas de lui-même. */

.ope-modale {
  width: min(430px, calc(100vw - 32px));
  box-sizing: border-box;
  margin: auto;
  padding: clamp(26px, 5vw, 34px);
  background: #FFFFFF;
  border: 1px solid var(--gris-bleu-200);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  color: var(--marine);
}
.ope-modale::backdrop { background: rgba(30, 58, 82, 0.55); }

.ope-modale__titre {
  font-family: var(--font-display); font-weight: var(--fw-semibold);
  font-size: clamp(22px, 5vw, 27px); line-height: 1.15; letter-spacing: -0.01em;
  color: var(--marine); margin: 0 0 16px; text-wrap: pretty;
}

.ope-modale__texte {
  font-size: clamp(15px, 4vw, 16.5px); line-height: 1.6;
  color: var(--marine); margin: 0 0 12px; text-wrap: pretty;
}

/* Le conseil sur les indésirables est un aparté, pas une troisième promesse : filet et
   couleur secondaire le détachent des deux phrases qui engagent. */
.ope-modale__note {
  margin: 18px 0 0; padding-top: 16px;
  border-top: 1px solid var(--gris-bleu-200);
  font-size: var(--fs-small); line-height: 1.55; color: var(--ardoise-700);
}
.ope-modale__note strong { color: var(--marine); font-weight: var(--fw-semibold); }

.ope-modale__fermer { margin-top: 24px; width: 100%; }

/* ============================================================
   Bouton d'action
   ============================================================ */

.ope-cta {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5em;
  font-family: var(--font-sans); font-weight: var(--fw-extrabold);
  font-size: 17px; letter-spacing: 0.01em; line-height: 1;
  padding: 17px 34px; border-radius: var(--radius-pill);
  background: var(--orange); border: 1px solid var(--orange); color: var(--marine);
  cursor: pointer; text-decoration: none; text-align: center;
  min-height: 48px; /* cible tactile confortable */
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.ope-cta:hover { background: var(--orange-survol); border-color: var(--orange-survol); color: #FFFFFF; }
.ope-cta[disabled] { opacity: 0.55; cursor: default; }

/* ============================================================
   BLOC 3 — C'est pour vous si…
   ============================================================ */

.pourqui { background: #FFFFFF; }

/* Trois cartes côte à côte plutôt que trois bandeaux empilés : trois bandeaux de même
   largeur et de même gris ne se distinguent que par leur texte, et rien ne se lit d'un
   coup d'œil. La borne de 820px en largeur de lecture n'a plus lieu d'être — elle
   étriquerait les colonnes. Le point de bascule est celui de toute la page.

   align-items:start, et non l'étirement par défaut : les trois textes tombent
   aujourd'hui sur deux lignes, les cartes ont donc la même hauteur d'elles-mêmes. Si
   l'un venait à s'allonger, mieux vaut une carte plus haute que trois cartes étirées
   dont deux garderaient un blanc de pied plus grand que leur blanc de tête. */
.pourqui__liste {
  list-style: none; margin: 30px 0 0; padding: 0; display: grid; gap: 14px;
}
@media (min-width: 860px) {
  .pourqui__liste { grid-template-columns: repeat(3, 1fr); gap: 20px; align-items: start; }
}

/* Fond crème sur la section blanche — l'inverse du reste de la page, et c'est ce qui
   détache le bloc. Les trois cartes sont identiques et alignées : ce qui les met en
   mouvement, c'est le flottement, pas une mise en avant.
   overflow:hidden pour que le liseré supérieur épouse l'arrondi. */
.pourqui__item {
  position: relative; overflow: hidden;
  background: var(--creme); border: 1px solid var(--gris-bleu-200);
  border-radius: var(--radius-xl); padding: 26px 24px;
  box-shadow: var(--shadow-card);
  animation: pourqui-flotte 5.4s var(--ease) infinite;
  transition: scale var(--dur-slow) var(--ease-out),
              box-shadow var(--dur-slow) var(--ease);

  /* Colonne, et non grille : la flèche occupe seule la première ligne, puis viennent
     le surtitre, le titre et le texte. */
  display: flex; flex-direction: column;
}

/* Filet marine sur toute la hauteur, à gauche, identique sur les trois : les cartes ne
   se distinguent plus par la couleur, seulement par leur place. inset:0 auto 0 0 le cale
   en haut, en bas et à gauche ; overflow:hidden sur la carte lui fait épouser l'arrondi
   des deux coins. */
.pourqui__item::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 3px;
  background: var(--marine);
}

.pourqui__fleche {
  align-self: flex-start; margin: 0 0 28px;
  display: block; width: 26px; height: auto; color: var(--orange);
  transition: translate var(--dur-slow) var(--ease-out);
}

/* Surtitre, sur le modèle du kicker du hero mais sans son filet — la flèche le porte
   déjà. Il n'est pas orange : à 12px, l'orange tombe à 2,5:1 sur le crème, très en
   dessous du seuil d'un texte (voir l'entête de colors-1h.css, qui le proscrit). D'où
   l'ardoise, qui y tient 5,9:1. */
.pourqui__kicker {
  margin: 0 0 10px;
  font-size: 12px; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--ardoise-700);
}

/* Pas de filet sous le titre, à la différence des autres blocs : la flèche et le liseré
   de tête tiennent déjà le rôle de repère coloré, et les trois ensemble faisaient
   doublon. */
.pourqui__titre {
  margin: 0;
  font-family: var(--font-display); font-weight: var(--fw-semibold);
  font-size: clamp(22px, 2vw, 26px); line-height: 1.15; color: var(--marine);
}

.pourqui__texte {
  margin: 14px 0 0;
  font-size: 16px; line-height: 1.6; color: var(--ardoise-700);
}

/* Rythme intérieur des cartes en trois colonnes. Il est repris de la maquette de
   référence, où l'écart entre blocs s'ouvre à mesure que la hiérarchie descend — 34px
   sous la flèche, 12 sous le surtitre, 24 sous le titre — et où rien ne dépasse le
   padding. Aucune hauteur n'est imposée : c'est le contenu qui la donne. Une hauteur
   décidée d'avance obligerait à répartir un vide qu'aucun contenu ne justifie, et
   c'est très exactement ce qui creusait un trou entre la flèche et le surtitre.

   Ce bloc vient après les règles de base, et non avec le reste du média : à spécificité
   égale, c'est la dernière déclaration qui l'emporte. */
@media (min-width: 860px) {
  /* Blancs égaux à l'œil — 36px sur les quatre côtés — ce qu'un padding uniforme ne
     donne pas ici. En haut, la boîte du SVG garde 2,5px de vide au-dessus du trait :
     34 suffisent donc pour 36 visibles. À gauche, le filet couvre 3px : il en faut 35.
     En bas, c'est la demi-interligne du dernier paragraphe qui s'ajoute sous les
     lettres — à line-height 1,6, (1,6 − 1) / 2 = 0,3em. On la reprend juste après. */
  .pourqui__item { padding: 34px 32px 36px 35px; }

  .pourqui__fleche { margin-bottom: 34px; }
  .pourqui__kicker { margin-bottom: 12px; }
  .pourqui__texte  { margin-top: 24px; margin-bottom: -0.3em; }

  /* Flèche plus présente : à 26px de large et 1,5 d'épaisseur, le trait était maigre à
     côté d'un titre de 26px. La règle vise le path — l'attribut stroke-width qu'il porte
     l'emporterait sur une valeur simplement héritée du SVG. */
  .pourqui__fleche { width: 32px; }
  .pourqui__fleche path { stroke-width: 2; }
}

/* Flottement continu. L'amplitude tient en six pixels et le cycle dure cinq secondes :
   assez pour que le bloc respire, trop peu pour qu'on lise le mouvement au lieu du
   texte. Les délais sont négatifs — l'animation démarre déjà entamée, les trois cartes
   sont donc désynchronisées dès la première image, sans temps mort au chargement.
   translate, propriété autonome, plutôt que transform : le survol peut ainsi poser un
   scale sans écraser le déplacement. */
@keyframes pourqui-flotte {
  0%, 100% { translate: 0 0; }
  50%      { translate: 0 -6px; }
}
.pourqui__item:nth-child(2) { animation-delay: -1.8s; }
.pourqui__item:nth-child(3) { animation-delay: -3.6s; }

/* Le survol fige la carte là où le flottement l'avait laissée, et l'agrandit à peine.
   Sous @media (hover:hover) : sur un écran tactile, :hover reste collé après le doigt
   et la carte resterait figée et zoomée. */
@media (hover: hover) {
  .pourqui__item:hover {
    scale: 1.025;
    animation-play-state: paused;
    box-shadow: var(--shadow-lg);
  }
  .pourqui__item:hover .pourqui__fleche { translate: 5px 0; }
}

@media (prefers-reduced-motion: reduce) {
  .pourqui__item { animation: none; transition: box-shadow var(--dur) var(--ease); }
  .pourqui__item:hover { scale: 1; }
  .pourqui__fleche { transition: none; }
  .pourqui__item:hover .pourqui__fleche { translate: 0; }
}

/* ============================================================
   BLOC 4 — Comment ça se passe
   ============================================================
   Un rail continu et trois points, pas trois blocs juxtaposés : c'est le rail qui
   dit le déroulement, les repères de temps le datent, et les libellés d'intervalle
   nomment ce qui se passe entre deux points. La seule étape qui porte une surface est
   celle du milieu — c'est la prestation, les deux autres ne font que l'encadrer.

   Toute la géométrie tient dans les cinq variables ci-dessous. Le rail est posé à
   --frise-rail-y, les points y sont centrés quel que soit leur diamètre, et les
   libellés d'intervalle s'y accrochent : changer une des cinq déplace l'ensemble d'un
   bloc, sans jamais désaligner deux éléments entre eux.

   Le rail est un ::before de la liste et non un élément : un <span> enfant direct d'un
   <ol> est du HTML invalide. C'est aussi ce qui garantit un trait UNIQUE — condition
   pour qu'il se trace d'un bout à l'autre en une seule transition, et pour qu'il ne se
   lise pas comme trois segments recollés. Il ne passe donc jamais À L'INTÉRIEUR d'un
   point : chacun le masque avec un anneau de la couleur du fond.

   Mise en page par défaut : empilée, rail vertical à gauche. Trois colonnes et rail
   horizontal à partir de 860px — même point de bascule que le hero, et il n'y en a
   qu'un : entre les deux, un rail horizontal sur des blocs empilés n'aurait aucun
   sens. */

.frise {
  --frise-gap: 30px;          /* gouttière entre colonnes, au-delà de 860px */
  --frise-rail-x: 22px;       /* axe du rail vertical, empilé */
  --frise-rail-y: 22px;       /* hauteur du rail, mesurée depuis le haut de l'étape */
  --frise-ligne-h: 16px;      /* hauteur figée d'une rangée de petite capitale — les deux */
  --frise-inter-gap: 8px;     /* du bas du libellé d'intervalle au rail, au-dessus */
  --frise-quand-gap: 10px;    /* du bas du point au repère, en dessous — trois colonnes */
  --frise-point: 20px;        /* les deux points d'extrémité */
  --frise-point-cle: 32px;    /* celui du jour J — c'est lui qui donne sa hauteur à la tête */
  --frise-anneau: 4px;        /* épaisseur de l'anneau qui masque le rail sous un point */
  --frise-contenu-gap: 14px;  /* du bas du point au premier élément de contenu */
  --frise-carte-pad: 26px;    /* padding haut de la carte — voir .frise__phase */
  --frise-titre-gap: 14px;    /* de la phase au titre — l'écart dont dépend leur alignement */

  /* Deux teintes qu'aucun jeton ne couvre : le marine à 20% n'est pas une bordure
     (--gris-bleu-200 tire au vert et se verrait sur le crème), et le halo n'a pas
     d'équivalent ailleurs sur la page. Elles restent locales — colors-1h.css est la
     palette de l'opération, pas un dépôt d'opacités. */
  --frise-rail: rgba(30,58,82,0.38);   /* marine #1E3A52 à 38% */
  --frise-halo: rgba(225,132,50,0.15); /* orange #E18432 à 15% */

  list-style: none; margin: 40px 0 0; padding: 0; position: relative;
  display: grid; gap: 36px;
}

.frise::before {
  content: ""; position: absolute;
  left: calc(var(--frise-rail-x) - 1px); top: var(--frise-rail-y); bottom: 0;
  width: 0; border-left: 2px dashed var(--frise-rail);
}

/* Empilé, le rail descend jusqu'au bas de la liste, donc au-delà du dernier
   point. Ce bout-là est recouvert d'un aplat crème plutôt que calculé : la hauteur
   du dernier bloc dépend de son texte, et aucune règle CSS ne peut s'y référer. Même
   procédé que l'anneau des points, et sous eux dans l'ordre de peinture. */
.frise__etape:last-child::before {
  content: ""; position: absolute;
  left: 0; width: calc(var(--frise-rail-x) * 2);
  top: var(--frise-rail-y); bottom: 0;
  background: var(--creme);
}

.frise__etape { position: relative; padding-left: 66px; }

/* Empilé, cette boîte ne fait que porter le repère de temps, qui revient dans le flux à
   droite du rail — il ne peut plus tenir au-dessus d'un point sorti du flux. En trois
   colonnes, elle reprend une hauteur et réserve la place du repère et du point.
   Elle reste `static` dans les deux mises en page : son ::before se positionne donc
   contre .frise__etape, seul ancêtre positionné, et les mêmes left/top valent partout. */
.frise__tete { display: block; }

/* Marine, et un corps au-dessus de celui de .frise__phase : ce sont les deux seules
   différences entre les deux rangées de petites capitales que la bande empile, et elles
   doivent suffire à dire laquelle est le repère. Même graisse : à 13px avec de
   l'interlettrage, un cran de plus écraserait au lieu de hiérarchiser. */
.frise__quand {
  margin: 0; font-family: var(--font-sans);
  font-size: 13px; font-weight: var(--fw-bold); line-height: var(--frise-ligne-h);
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--marine);
  white-space: nowrap;
}

/* Le point. Un pseudo-élément et non un <span> vide : un élément sans contenu qui ne
   porte qu'un fond finit supprimé un jour par quelqu'un qui croit nettoyer.
   Il ne porte plus de chiffre — chaque colonne disait trois fois sa position, entre le
   repère de temps, le chiffre et la phase. L'ordre reste dans l'<ol>, que les lecteurs
   d'écran annoncent, et dans le texte visible.
   Centré sur le rail par translate quel que soit son diamètre : les deux tailles se
   posent sur la même ligne sans réglage séparé. `translate` et non `transform` :
   l'animation d'apparition se sert de `scale`, et les deux propriétés individuelles se
   composent au lieu de s'écraser (même procédé qu'au BLOC 3).
   L'anneau crème masque le rail : il n'est pas découpé, il est recouvert. Son épaisseur
   se règle sur le diamètre du point — au-delà, le trou dans le rail devient plus large
   que le point lui-même et celui-ci paraît y flotter. */
.frise__tete::before {
  content: ""; position: absolute; z-index: 1;
  left: var(--frise-rail-x); top: var(--frise-rail-y); translate: -50% -50%;
  width: var(--frise-point); height: var(--frise-point); border-radius: 50%;
  background: var(--marine);
  box-shadow: 0 0 0 var(--frise-anneau) var(--creme);
}

/* Le seul qui diffère. Les points 1 et 3 sont strictement identiques : rien ici ne les
   distingue, aucune règle ne vise le troisième.
   Le halo est flou et non un second anneau — un anneau franc redessinerait un cercle
   concentrique, là où il s'agit de faire rayonner celui-ci. L'anneau crème est déclaré
   en premier, donc peint au-dessus : le halo n'émerge qu'à l'extérieur. */
.frise__etape:nth-child(2) .frise__tete::before {
  width: var(--frise-point-cle); height: var(--frise-point-cle);
  background: var(--orange);
  box-shadow: 0 0 0 var(--frise-anneau) var(--creme), 0 0 30px 4px var(--frise-halo);
}

/* Masqué en empilé, et seulement là. En trois colonnes, AVANT / PENDANT / APRÈS
   marquent la simultanéité de lecture des trois étapes — on les embrasse d'un regard et
   ces trois mots disent qu'elles se répondent. Empilé, l'argument tombe : « J - 2 » et
   « J + 2 » disent déjà la séquence, et le lecteur qui fait défiler ne compare rien. Il
   ne resterait qu'une quatrième petite capitale dans un axe vertical qui en porte déjà
   trois — le repère, le libellé d'intervalle, et celle-ci.
   Ce n'est pas une suppression : le texte reste dans le HTML, intact en trois colonnes.
   Le titre redevenant alors le premier enfant de la carte, il rend son écart de tête au
   padding de celle-ci — voir .frise__carte .frise__repere plus bas.

   L'alignement des trois colonnes tient ici, et nulle part ailleurs. « Pendant » est
   dans la carte, les deux autres sont sur le crème : pour que les trois tombent sur la
   même ligne de base, l'espace qui les sépare de la tête doit valoir de part et d'autre
   la marge de la carte PLUS son padding haut. D'où le calc en trois colonnes, ci-dessous.
   Une fois les trois phases alignées, les trois titres le sont d'eux-mêmes : l'écart
   phase → titre vaut 14px partout, carte comprise. Ne pas rétablir de marge nulle sur
   .frise__carte .frise__repere — c'est ce qui casserait l'alignement. */
.frise__phase {
  display: none;
  margin: var(--frise-contenu-gap) 0 0; font-family: var(--font-sans);
  font-size: 12px; font-weight: var(--fw-bold); line-height: 1.3;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--ardoise-700);
}

/* Ces trois valeurs ne sont pas un choix esthétique. « Un compte-rendu » est le plus
   long des trois titres et mesure 7,76 em en Spectral SemiBold à -0,02em d'interlettrage
   — mesuré, pas estimé. Il doit tenir sur UNE ligne : à deux lignes, tout le texte de la
   troisième colonne descendrait par rapport à celui de la première, et les trois colonnes
   cesseraient de se lire de front.
   Le cas le plus défavorable est le point de bascule exact de 860px, où la colonne ne
   fait que 240px : 29px y donnent 225px, soit 6% de marge. Le plafond de 42px est atteint
   vers 1235px, où la colonne fait 353px — sa largeur maximale, --container-max valant
   1200px — pour 326px de titre. Il reste aussi sous les 44px du .ope-titre : le titre de
   section garde le dessus.
   Remesurer si le libellé change : ouvrir le mot dans Spectral 600 à 100px et diviser. */
.frise__repere {
  margin: var(--frise-titre-gap) 0 0;
  font-family: var(--font-display); font-weight: var(--fw-semibold);
  font-size: clamp(29px, 3.4vw, 42px); line-height: 1.05; letter-spacing: -0.02em;
  color: var(--marine);
}

.frise__texte {
  margin: 14px 0 0; font-size: 16px; line-height: 1.65;
  color: var(--ardoise-700); text-wrap: pretty;
}

/* Un cran sous les repères de temps, et volontairement : ceux-ci annoncent, ceux-là
   commentent. Ardoise et non gris-bleu malgré l'aspect « repère discret » recherché :
   à cette taille le gris-bleu tombe à 3,8:1 sur le crème et ne passe pas (voir
   colors-1h.css). L'ardoise garde la même famille de teinte à 5,9:1. */
.frise__intervalle {
  margin: 22px 0 0; font-family: var(--font-sans);
  font-size: 12px; font-weight: var(--fw-medium); line-height: var(--frise-ligne-h);
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--ardoise-700);
}

/* L'étape centrale est la seule à porter une surface. La carte s'ouvre sous « Pendant »,
   qui reste dehors, aligné sur « Avant » et « Après » : les trois petites capitales
   partagent ainsi la même ligne de base sans aucun rattrapage. */
.frise__carte {
  margin: var(--frise-contenu-gap) 0 0;
  padding: var(--frise-carte-pad) 28px 30px; border-radius: 16px;
  background: var(--marine); box-shadow: var(--shadow-card);
}
/* Crème atténué et non ardoise : sur le marine de la carte, l'ardoise des deux autres
   colonnes tomberait à 1,3:1. C'est le pendant exact de l'ardoise sur le crème. */
.frise__carte .frise__phase { margin-top: 0; color: var(--color-text-inverse-muted); }
.frise__carte .frise__repere { margin-top: 0; color: var(--creme); }
.frise__carte .frise__texte { color: var(--color-text-inverse-muted); }

/* Trois colonnes qui ne s'étirent pas : la carte centrale est plus haute que ses
   voisines, et « start » empêche les deux autres de se diluer sur sa hauteur. */
@media (min-width: 860px) {
  .frise {
    /* Au-dessus du rail il ne reste que la rangée des libellés d'intervalle : le rail
       ne descend plus que de sa hauteur, de l'écart qui l'en sépare, et du rayon du plus
       gros point. Le repère de temps, lui, est passé DESSOUS — d'où sa disparition de
       cette formule et son apparition dans la hauteur de .frise__tete. */
    --frise-rail-y: calc(var(--frise-ligne-h) + var(--frise-inter-gap) + var(--frise-point-cle) / 2);

    /* Le bas de .frise__tete tombe exactement sur le bas du point — sa hauteur vaut
       quand-h + quand-gap + point-cle, et le point est centré sur le rail à la moitié
       de ce dernier terme. Cette variable EST donc l'espace entre le bas du point et
       le haut de la carte, et .frise__phase le reprend augmenté du padding de la carte :
       l'agrandir descend les trois colonnes ensemble, l'alignement ne peut pas casser.
       Il faut cet air-là pour que le point désigne la carte au lieu de la toucher.
       Empilé, il n'a pas d'objet : le point est à GAUCHE de la carte, pas au-dessus,
       et cet écart-là vaut déjà 28px. Porter les 30px en vertical ne corrigerait rien
       et creuserait un trou entre le repère de temps et la phase. */
    --frise-contenu-gap: 30px;
    grid-template-columns: repeat(3, 1fr); gap: var(--frise-gap); align-items: start;
  }

  /* Du centre du premier point au centre du dernier, et pas au-delà : une
     ligne qui dépasse le dernier point paraît inachevée. Chaque point étant centré
     sur sa colonne, ce centre est à la moitié d'une colonne du bord — soit, pour trois
     colonnes de 1fr séparées par deux gouttières, (100% - 2 gouttières) / 6. */
  .frise::before {
    left: calc((100% - 2 * var(--frise-gap)) / 6);
    right: calc((100% - 2 * var(--frise-gap)) / 6);
    top: var(--frise-rail-y); bottom: auto;
    width: auto; height: 0;
    border-left: 0; border-top: 2px dashed var(--frise-rail);
  }
  .frise__etape { padding-left: 0; }
  .frise__etape:last-child::before { content: none; }

  /* Réserve la hauteur de tout ce qui est hors flux : la rangée d'intervalles, le point,
     et le repère passé dessous. Elle descend donc jusqu'au bas du repère — c'est ce bas-là,
     et lui seul, dont dépend l'alignement des trois colonnes.
     Deux formules pour un même point : celle-ci et le `top` du repère ci-dessous doivent
     tomber sur la même valeur. Elles sont écrites séparément exprès — si l'une dérive,
     l'écart se voit au lieu de se propager. */
  .frise__tete {
    height: calc(var(--frise-rail-y) + var(--frise-point-cle) / 2
                 + var(--frise-quand-gap) + var(--frise-ligne-h));
  }

  /* Sous le point, et non plus au-dessus. Pas de `bottom: 0` qui serait plus court :
     .frise__tete est `static`, le repère se positionne donc contre .frise__etape et
     `bottom` viserait le bas du bloc entier, pas le bas de la tête. */
  .frise__quand {
    position: absolute; left: 50%; translate: -50% 0;
    top: calc(var(--frise-rail-y) + var(--frise-point-cle) / 2 + var(--frise-quand-gap));
  }
  .frise__tete::before { left: 50%; }

  /* La rangée reparaît — c'est ici qu'elle a un sens — et avec elle la compensation
     d'alignement : empilé, il n'y a rien à aligner de front et cet écart creuserait un
     trou dans les colonnes 1 et 3. */
  .frise__phase {
    display: block;
    margin-top: calc(var(--frise-contenu-gap) + var(--frise-carte-pad));
  }
  /* Le titre n'est plus le premier enfant de la carte : il reprend l'écart qui le sépare
     de sa phase, le même que dans les deux autres colonnes. C'est cet écart commun qui
     aligne les trois titres une fois les trois phases alignées. */
  .frise__carte .frise__repere { margin-top: var(--frise-titre-gap); }

  /* Tendu d'un centre de point à l'autre : il part du milieu de sa colonne et court
     sur une colonne entière plus une gouttière, ce qui le centre exactement entre les
     deux points — y compris par-dessus la gouttière, que le rail traverse aussi.
     `translate: 0 -100%` le fait remonter de sa propre hauteur : il se pose sur le rail
     sans dépendre de sa taille de texte. */
  .frise__intervalle {
    position: absolute; margin: 0;
    left: 50%; width: calc(100% + var(--frise-gap));
    top: calc(var(--frise-rail-y) - var(--frise-inter-gap)); translate: 0 -100%;
    text-align: center;
  }
}

/* Apparition au défilement — le rail se trace, les trois points se posent ensuite.
   Une seule fois : l'observateur se déconnecte au premier passage.

   TOUT l'état de départ est sous .frise--anime, classe posée par landing.js lui-même.
   Ce n'est pas un détail de style : le script est revalidé mais peut être servi depuis
   le cache dans une version antérieure à celle de la page (voir README). Si l'état
   masqué était le défaut CSS, un script absent, périmé ou en erreur laisserait la frise
   invisible pour de bon. Ici, pas de script = frise entière, immobile. */
.frise--anime::before {
  transform: scaleY(0); transform-origin: top;
  transition: transform 1s cubic-bezier(0.4, 0, 0.2, 1);
}
.frise--anime.visible::before { transform: none; }

.frise--anime .frise__tete::before {
  opacity: 0; scale: 0.6;
  transition: opacity 0.4s var(--ease), scale 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.frise--anime.visible .frise__tete::before { opacity: 1; scale: 1; }
.frise--anime .frise__etape:nth-child(1) .frise__tete::before { transition-delay: 0.35s; }
.frise--anime .frise__etape:nth-child(2) .frise__tete::before { transition-delay: 0.65s; }
.frise--anime .frise__etape:nth-child(3) .frise__tete::before { transition-delay: 0.95s; }

@media (min-width: 860px) {
  .frise--anime::before { transform: scaleX(0); transform-origin: left; }
  .frise--anime.visible::before { transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .frise--anime::before { transform: none; transition: none; }
  .frise--anime .frise__tete::before {
    opacity: 1; scale: 1; transition: none; transition-delay: 0s;
  }
}

/* ============================================================
   BLOC 5 — Pourquoi nous
   ============================================================ */

.pourquoi { background: var(--marine); color: var(--creme); }
.pourquoi .ope-titre { color: var(--creme); }
.pourquoi p {
  font-size: clamp(16px, 4.2vw, 18px); line-height: 1.7;
  color: var(--color-text-inverse-muted); margin: 24px 0 0; max-width: 62ch;
}
/* Deux niveaux dans cette section, et deux seulement : le corps en crème atténué, et
   la phrase ci-dessous en crème plein. Tout ce qui s'intercalait entre les deux —
   amorce, gras, incise — a été retiré : c'est l'échelle et le blanc qui annoncent, pas
   une phrase qui prévient.

   Sélecteur à deux classes : « .pourquoi p » ci-dessus vaut une classe et un élément,
   et l'emporterait sur une classe seule quel que soit l'ordre des règles.

   Les six directions ne sont nommées nulle part dans ce texte : elles le sont sous les
   pictogrammes qui les portent, en <span> de texte, donc déjà indexables. Les redire en
   phrase juste en dessous ne servait rien et se voyait. */

/* « Aussi longtemps que nécessaire. » — un paragraphe à part, et non un <br> dans le
   précédent : c'est une affirmation qui se tient seule, elle doit donc l'être dans le
   document, pas seulement à l'écran. La marge du haut est ramenée de 24 à 10px : assez
   pour qu'elle fasse ligne à part, trop peu pour qu'elle s'en détache tout à fait.
   Aucun autre écart de style — la section n'a que deux niveaux, et ils sont pris. */
.pourquoi .pourquoi__seule { margin-top: 10px; }

/* Trois valeurs à connaître avant d'y toucher :
   - `max-width: none` annule le 62ch hérité de « .pourquoi p ». Sans lui, la phrase se
     replierait dans la colonne du corps de texte et perdrait sa coupe en deux temps.
   - Le plafond de 42px reste sous les 44px du .ope-titre : le titre de section garde le
     dessus, la phrase domine le corps sans le rejoindre.
   - Le plancher de 26px vaut jusqu'à 684px de fenêtre (au-delà, 3,8vw reprend la main),
     et c'est donc lui seul qui décide sur téléphone. Mesuré dans la police réelle :
     à 26px la plus longue des deux moitiés fait 245px, pour 280px de contenu à 320px de
     fenêtre — le cas le plus étroit. Les deux lignes tiennent, la coupe du <br> est la
     seule. Une phrase plus longue repasserait à trois lignes sans prévenir : remesurer
     avant d'y toucher. */
.pourquoi .pourquoi__phrase {
  margin: clamp(44px, 7vw, 72px) 0; max-width: none;
  font-family: var(--font-display); font-weight: var(--fw-semibold);
  font-size: clamp(26px, 3.8vw, 42px); line-height: 1.18; letter-spacing: -0.02em;
  color: var(--creme); text-wrap: pretty;
}

/* ------------------------------------------------------------
   La bande des six directions
   ------------------------------------------------------------
   Reprise de la landing Entreprises, à quatre choses près, toutes dictées par le fond
   marine ou par le téléphone. Elles sont signalées « ÉCART » ci-dessous.

   Deux régimes, séparés à 1080px :
     ≥ 1080px  rangée fixe pleine largeur, chaque pastille grossit à son tour
     < 1080px  défilement continu, mis en pause au survol
   La rupture est celle de la référence, et elle n'est pas arbitraire : à 1080px pile,
   les six pastilles de 148px tiennent tout juste — 6×148 + 5×15 de gap + 2×43 de
   padding = 1049px pour 1080 disponibles. En dessous, elles ne tiendraient plus. */

@keyframes bandeDefile {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@keyframes bandePulse {
  0%   { transform: scale(1); }
  8%   { transform: scale(1.12); }
  17%  { transform: scale(1); }
  100% { transform: scale(1); }
}

/* ÉCART — la bande clôt la section : pas de filet bas, et le padding-bas de
   .ope-section est annulé juste en dessous. Le blanc du BLOC 6 fait le bord, ce qui en
   fait une transition et non un objet posé au milieu du marine. Le filet du haut reste :
   sans lui, la bande n'aurait aucune limite, le fond ne changeant pas.
   ÉCART — padding en clamp plutôt que les 62px fixes de la référence : le plafond est
   sa valeur, seul le téléphone se resserre, comme partout ailleurs dans cette feuille. */
.pourquoi { padding-bottom: 0; }
.bande {
  margin-top: clamp(48px, 7vw, 76px);
  border-top: 1px solid var(--color-border-inverse);
  padding: clamp(40px, 6vw, 62px) 0;
  overflow: hidden;
}

.bande__piste { display: flex; }
.bande__rangee { display: flex; list-style: none; margin: 0; padding: 0; }
.direction { display: flex; flex-direction: column; align-items: center; gap: 14px; will-change: transform; }

/* ÉCART — les couleurs. Sur marine, le disque blanc de la référence devient crème
   (10,4:1, et les pictogrammes sont déjà dessinés pour ce fond), la bordure grise
   devient du crème à 26%, et l'ombre portée est purement et simplement supprimée : une
   ombre foncée sur fond foncé ne creuse rien. Le relief vient du halo, plus bas.
   Le libellé est en crème PLEIN, et non dans le crème atténué du corps de texte : il
   nomme la direction que le pictogramme ne dit pas, c'est lui qui porte l'information. */
.direction__disque {
  width: 148px; height: 148px; border-radius: 50%;
  background: var(--creme); border: 1px solid var(--color-border-inverse);
  display: flex; align-items: center; justify-content: center;
}
.direction img { height: 52px; width: auto; max-width: 96px; display: block; }
/* Garde-fou repris tel quel : rien ne borne la largeur d'un libellé, et un libellé plus
   large que sa colonne empiéterait sur celle d'à côté au lieu de se replier. */
.direction__nom {
  max-width: 100%; overflow-wrap: break-word;
  font-size: 15px; font-weight: var(--fw-bold); line-height: 1.35;
  text-align: center; color: var(--creme);
}

@media (min-width: 1080px) {
  .bande__piste { width: 100%; }
  .bande__rangee { flex: 1; justify-content: space-between; gap: clamp(12px, 1.4vw, 28px); padding: 0 clamp(24px, 4vw, 56px); }
  .bande__rangee--clone { display: none; }
  .direction { flex: 1 1 0; min-width: 148px; animation: bandePulse 6s ease-in-out infinite; }
  .direction:nth-child(2) { animation-delay: 1s; }
  .direction:nth-child(3) { animation-delay: 2s; }
  .direction:nth-child(4) { animation-delay: 3s; }
  .direction:nth-child(5) { animation-delay: 4s; }
  .direction:nth-child(6) { animation-delay: 5s; }
}

/* Le défilement, et les trois valeurs qui le tiennent ensemble.

   ÉCART — disque à 110px au lieu de 148. À 148px sur un téléphone de 360px, on voit
   deux pastilles : c'est un carrousel, et le visiteur ne sait pas qu'il y en a six.
   110px avec 20px d'écart donnent un pas de 130px, soit trois pastilles à 390px de
   fenêtre et deux entières plus deux amorcées à 320px. Le libellé le plus large,
   « Commerciale », fait 88px dans la police réelle : il tient sous les 110.

   La piste n'a PAS de gap, et c'est un invariant, pas un oubli : « translateX(-50%) »
   déplace la piste de la moitié de sa largeur, alors que la boucle exige un déplacement
   d'exactement une longueur de rang. Les deux ne coïncident que si rien ne s'intercale
   entre les deux rangs. C'est le padding-right du rang qui fournit l'écart au raccord —
   les mêmes 20px qu'à l'intérieur, sinon la jointure se verrait.
   (La référence pose un gap de 32px sur sa piste : son raccord ouvre 64px au lieu de 32
   et la boucle saute de 16px à chaque tour. Corrigé ici, pas copié.)

   52s : la durée de la référence, reprise telle quelle. Les pastilles sont plus petites,
   donc la bande avance moins vite en pixels, mais une nouvelle pastille entre toutes les
   8,7s — contre 8,55s là-bas. C'est ce rythme-là qui se règle, pas la vitesse. */
@media (max-width: 1079px) {
  .bande__piste { width: max-content; animation: bandeDefile 52s linear infinite; }
  .bande__piste:hover { animation-play-state: paused; }
  .bande__rangee { gap: 20px; padding-right: 20px; }
  .direction { flex-shrink: 0; width: 110px; }
  .direction__disque { width: 110px; height: 110px; }
  .direction img { height: 39px; max-width: 71px; }

  /* Le relief : mise en avant de la pastille au centre de la bande.
     Il est enfermé dans cette requête de média, et pas seulement conditionné à la
     classe : au-dessus de 1080px, la rangée fixe a sa propre animation de « transform »
     et les deux se disputeraient l'élément. Ici, le CSS lui-même rend la chose
     impossible.

     Les valeurs viennent de landing.js, et la classe qui ouvre ces règles n'est posée
     qu'APRÈS la première écriture de --k et --g : c'est l'invariant d'ordre, le même que
     pour la frise du BLOC 4. Sans script, la classe n'existe pas, aucune de ces cinq
     déclarations ne s'applique, et les six pastilles restent pleines, opaques et nettes.
     Le relief est un bonus ; il n'est jamais une condition d'affichage. */
  .bande--relief .direction {
    transform: scale(calc(1.32 - 0.62 * var(--k)));
    opacity: calc(1 - 0.62 * var(--k));
    filter: blur(max(0px, calc(var(--k) * 3.2px - 1.92px)));
  }
  .bande--relief .direction img {
    filter: saturate(calc(1 - 0.45 * var(--k))) brightness(calc(1 - 0.16 * var(--k)));
  }
  /* Le halo remplace l'ombre portée de la référence, inopérante sur marine. Crème et non
     blanc : sur ce fond, le blanc pur vire au gris bleuté. */
  .bande--relief .direction__disque {
    box-shadow: 0 0 calc(18px + 26px * var(--g)) rgba(245, 240, 227, calc(0.5 * var(--g)));
  }
}

@media (prefers-reduced-motion: reduce) {
  .bande__piste { animation: none !important; transform: none !important; }
  .bande__rangee--clone { display: none !important; }
  .direction { animation: none !important; transform: none !important; opacity: 1 !important; filter: none !important; }
  .direction img { filter: none !important; }
  .direction__disque { box-shadow: none !important; }
}

/* ÉCART — sans défilement, les six pastilles doivent bien aller quelque part. Repliées
   à 110px, elles font une colonne de plus de 800px au milieu d'une page déjà longue ;
   à 84px, elles tiennent trois par ligne dès 360px de fenêtre. C'est la seule taille de
   disque que la référence ne prévoit pas — son bandeau n'est pas au milieu d'une page
   à défilement long, elle ne s'en aperçoit pas. */
@media (max-width: 1079px) and (prefers-reduced-motion: reduce) {
  .bande__piste { width: auto; }
  .bande__rangee { flex-wrap: wrap; justify-content: center; row-gap: 26px; padding-right: 0; }
  .direction { width: 96px; }
  .direction__disque { width: 84px; height: 84px; }
  .direction img { height: 30px; max-width: 56px; }
}

/* ============================================================
   BLOC 6 — Trois questions qu'on nous pose
   ============================================================
   Une section, et non plus un appendice sous le calendrier : ces trois réponses lèvent
   des freins à la réservation, elles doivent se lire sans clic et avant le dernier
   bouton. Plus de repli, donc : ni <details>, ni triangle, ni état à annoncer.

   Fond blanc comme le BLOC 3 : la section est prise entre le marine du BLOC 5 et le
   crème du BLOC 7, et le crème donnerait deux fonds identiques à la suite.

   Toujours pas de classe .repli__* — /etat.css les force ouvertes quand aucun créneau
   n'est disponible (voir README, « Ouvrir et fermer les créneaux »). La raison vaut
   même sans repli : elle vaudra encore pour le prochain bloc ajouté ici. */

.faq { background: #FFFFFF; }

/* Neutralise les marges propres de <dl> et <dd>, que la mise en page reprend à zéro. */
.faq__liste { margin: 34px 0 0; }

/* Un filet entre chaque question, aucun au-dessus ni en dessous : le titre et son filet
   orange ferment le haut, la fin de section ferme le bas. */
.faq__item { padding: 22px 0; }
.faq__item + .faq__item { border-top: 1px solid var(--gris-bleu-200); }

@media (min-width: 860px) {
  /* Un tiers / deux tiers. « Vous allez essayer de me vendre quelque chose ? » fait
     47 signes contre 30 aux deux autres : elle passera sur deux lignes quelle que soit
     la proportion tenable, et élargir sa colonne se ferait au prix des réponses. */
  .faq__item {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
    gap: clamp(24px, 4vw, 48px); align-items: start; padding: 26px 0;
  }
  .faq__reponse { margin: 0; }
}

.faq__question {
  margin: 0; font-size: clamp(16px, 4.2vw, 17px);
  font-weight: var(--fw-bold); line-height: 1.45; color: var(--marine);
  text-wrap: pretty;
}

/* Pas de borne en ch ici, contrairement aux paragraphes de la page : trois réponses de
   deux lignes face à une question courte laisseraient une colonne à moitié vide, qui se
   lit comme un défaut d'alignement. La colonne fait déjà office de largeur de lecture. */
.faq__reponse {
  margin: 8px 0 0; font-size: 16px; line-height: 1.6;
  color: var(--ardoise-700); text-wrap: pretty;
}

/* ============================================================
   BLOC 7 — Qui vous reçoit
   ============================================================
   Photo à gauche, deux blocs titrés à droite, phrase de clôture pleine largeur
   dessous. Rien n'est encadré : le contenu se pose sur le crème de la section.

   Alignement du haut : le portrait et le premier titre de bloc partagent la ligne
   du haut de la grille, à 0,00px mesuré. C'est align-items:start plus margin-top nul
   sur .hote__titre qui le produit, pas un décalage compensatoire — donc il ne dérive
   pas quand la police ou la largeur changent. Ne pas remettre de padding en tête de
   .hote__texte, ça le casserait.

   Le bas des deux colonnes ne s'aligne à aucune largeur, et on ne cherche pas à l'y
   forcer : le texte change de longueur avec la largeur d'écran, un calage fait sur une
   largeur casserait sur toutes les autres. La colonne photo est fixée à 240px, ce qui
   borne l'écart sans jamais l'annuler — mesuré, le texte descend plus bas que la photo
   de 69px à 860px, 17px à 1000px, 22px à 1200px et 27px à 1440px.

   Pourquoi une largeur fixe et non plus 1fr/2fr : en proportionnel la photo grandissait
   avec l'écran alors que le texte raccourcissait, et l'écart atteignait 138px de photo
   pendante à 1200px. Un 260px fixe donnerait un écart quasi nul de 1200 à 1440 — écarté
   volontairement, cette quasi-perfection tient au hasard de la longueur actuelle du
   texte et se déferait à la première retouche, sans que personne comprenne pourquoi. Un
   léger dépassement du texte est plus robuste, et se lit mieux qu'une photo qui pend. */

.hote { display: grid; gap: 28px; margin-top: 32px; }

@media (min-width: 860px) {
  /* Colonne photo fixe, colonne texte élastique. Le minmax(0,…) sur la seconde empêche
     un mot long de la pousser au-delà de la place disponible. */
  .hote {
    grid-template-columns: 240px minmax(0, 1fr);
    gap: 40px; align-items: start;
  }
}

/* <picture> est l'élément de grille, et l'<img> se dimensionne dedans. Surtout PAS
   display:contents ici : la grille blockifie ses éléments, le <source> — qui n'a pas
   de display:none en feuille UA — deviendrait alors une case à part entière, prendrait
   la première colonne et pousserait la photo dans celle du texte. En display:block le
   <source> reste un inline vide à l'intérieur, sans effet. */
.hote picture { display: block; }

/* 3/4 : le portrait est carré à la source, le recadrage centré retire 25 % de la
   largeur — soit le fond gris mort à gauche du sujet, qui reste entier. */
.hote__portrait {
  display: block; width: 100%; height: auto;
  aspect-ratio: 3 / 4;
  object-fit: cover; object-position: center;
  border-radius: var(--radius-lg);
}

/* Empilé, la contrainte n'est pas la même selon l'orientation, et aucune règle
   unique ne couvre les deux.

   Portrait : c'est la LARGEUR qui commande. On la borne pour que la hauteur déduite
   du 3/4 ne dépasse pas la mi-écran, sinon le premier bloc de texte passe sous la
   ligne de flottaison et la section s'ouvre sur un portrait muet. Borner la hauteur
   ici garderait la pleine largeur et écraserait le portrait en carré. */
@media (max-width: 859px) and (orientation: portrait) {
  .hote__portrait { max-width: min(100%, calc(50vh * 3 / 4)); }
}

/* Paysage : l'écran est court et large, c'est la HAUTEUR qui commande. On la fixe à
   70vh et on laisse la largeur suivre le ratio. Reprendre ici la borne en largeur du
   portrait donnerait une vignette de 146px dans une colonne de 764px ; et un simple
   max-height sur width:100% étirerait le portrait en bandeau horizontal. */
@media (max-width: 859px) and (orientation: landscape) {
  .hote__portrait { height: 70vh; width: auto; max-width: 100%; }
}

.hote__texte { display: grid; gap: 26px; }

/* Reprise à l'identique de .pourqui__titre, qui est le niveau « titre de bloc » de
   la page. Classe distincte et non réutilisation : ce bloc ne doit pas dépendre
   d'une section figée. Si l'un des deux bouge, c'est un choix, pas un effet de bord. */
.hote__titre {
  margin: 0;
  font-family: var(--font-display); font-weight: var(--fw-semibold);
  font-size: clamp(22px, 2vw, 26px); line-height: 1.15; color: var(--marine);
}

/* La borne en ch aligne ce bloc sur le reste de la page, qui borne sa prose entre 46
   et 62ch. Sans elle, la colonne texte atteignait 94ch à 1440px depuis que la photo
   est fixée à 240px — deux fois une largeur de lecture tenable. Mesuré : la ligne
   passe de 840px à 605px sans changer la hauteur du bloc, le texte tenant déjà en
   deux lignes par paragraphe à ces deux largeurs. */
.hote__para {
  margin: 14px 0 0; max-width: 62ch;
  font-size: 16px; line-height: 1.6; color: var(--ardoise-700);
  text-wrap: pretty;
}

/* Un appui par paragraphe, quatre pour la section : au-delà le gras cesse d'être un
   repère. Le passage en marine compte autant que la graisse — en gardant l'ardoise du
   corps, l'appui ne se verrait pas. Graisse 700 et non 600 : Manrope n'est chargé
   qu'en 400/500/700/800, un 600 serait synthétisé par le navigateur. */
.hote__para strong { font-weight: var(--fw-bold); color: var(--marine); }

/* Conclusion de la section, pas note de bas de page : nettement au-dessus du corps, et
   au-dessus des titres de bloc sur écran large. Elle reste en retrait de la phrase de
   marque de la section marine (.pourquoi__phrase), à environ 0,7 de sa taille à toutes
   les largeurs — c'est cet écart-là qui est intangible, pas le rapport aux titres de
   bloc, qui s'inverse sous 769px. Tenue en deux lignes de 860 à 1440px : au-delà de
   26px à 860px, ou de 32px à 1000px, elle passe à trois. Remesurer avant d'y toucher.

   Pas de filet au-dessus, et ne pas en remettre : les paragraphes s'arrêtant à 62ch,
   un filet pleine largeur venait souligner la bande vide à leur droite au lieu de la
   faire oublier. Le raccourcir à la largeur du texte est pire — il tombait alors à
   605px sous une phrase qui en fait 1004 à 1440px, et la page n'a pas d'idiome pour
   ça : ses séparateurs sont soit pleine largeur (.faq__item), soit le court filet
   orange de titre. La rupture est portée par le saut de graisse et de famille, vérifié
   jusqu'en 390px où il n'est pourtant que de 4px. */
.hote__cloture {
  margin: 52px 0 0;
  font-family: var(--font-display); font-weight: var(--fw-semibold);
  font-size: clamp(20px, 2.6vw, 32px); line-height: 1.25; letter-spacing: -0.01em;
  color: var(--marine); text-wrap: pretty;
}

/* ============================================================
   BLOC 8 — Réserver
   ============================================================ */

.reserver { background: var(--marine); color: var(--creme); }
.reserver__titre {
  font-family: var(--font-display); font-weight: var(--fw-semibold);
  font-size: clamp(28px, 6.4vw, 46px); line-height: 1.1; letter-spacing: -0.02em;
  color: var(--creme); margin: 0; text-wrap: balance;
}
.reserver__cta { margin-top: 28px; }

.reserver__coord {
  margin-top: clamp(38px, 6vw, 56px); padding-top: 28px;
  border-top: 1px solid var(--color-border-inverse);
  font-size: 15.5px; line-height: 1.7; color: var(--color-text-inverse-muted);
}
.reserver__coord p { margin: 0; }
.reserver__coord p + p { margin-top: 10px; }
.reserver__coord strong { color: var(--creme); font-weight: var(--fw-bold); }
.reserver__coord a { color: var(--creme); text-decoration: underline; text-underline-offset: 3px; }
.reserver__coord a:hover { color: var(--orange); }

.reserver__legal {
  margin-top: 26px; display: flex; flex-wrap: wrap; gap: 20px;
  font-size: 13px;
}
.reserver__legal a { color: rgba(245,240,227,0.55); text-decoration: none; }
.reserver__legal a:hover { color: var(--orange); }
