/* =========================================================================
   ALTIPUR — dispositifs transverses et cinq scènes
   ========================================================================= */

/* =========================================================================
   1. LE FOND CONTINU — on ne redescend jamais au sol.
   ========================================================================= */

.fond-aerien {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.fond-aerien img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Le cliché d'origine est un ciel clair : sans ce réglage, aucun texte
     crème ne tiendrait le 4,5:1 par-dessus. */
  filter: brightness(0.3) saturate(0.55) contrast(1.05);
}

main,
.pied {
  position: relative;
  z-index: 1;
}

/* Voile de sécurité : chaque paire texte/fond est vérifiée par-dessus lui,
   jamais par-dessus la photo nue. Pas de backdrop-filter sur une surface
   de cette taille qui défile. */
main {
  background: linear-gradient(
    to bottom,
    rgba(8, 12, 20, 0.9) 0%,
    rgba(8, 12, 20, 0.74) 22%,
    rgba(8, 12, 20, 0.74) 78%,
    rgba(8, 12, 20, 0.9) 100%
  );
}

/* =========================================================================
   2. LA PILULE DE NAV
   ========================================================================= */

.nav {
  position: fixed;
  top: clamp(0.75rem, 2vh, 1.35rem);
  top: clamp(0.75rem, 2svh, 1.35rem);
  left: 50%;
  z-index: 90;
  translate: -50% 0;
  display: flex;
  align-items: center;
  gap: clamp(0.5rem, 1.4vw, 1.1rem);
  max-width: calc(100vw - 1.5rem);
  /* Sur écran étroit la pilule déborde et défile horizontalement : le geste
     ne doit pas entraîner la page. */
  overscroll-behavior: contain;
  padding: 0.42rem 0.42rem 0.42rem 1.15rem;
  border-radius: 999px;
  background: rgba(8, 12, 20, 0.8);
  border: 1px solid var(--trait);
  box-shadow: 0 18px 48px -24px rgba(0, 0, 0, 0.9);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-14px);
  transition:
    opacity calc(var(--d-state) * 0.75) var(--ease-sortie),
    transform calc(var(--d-state) * 0.75) var(--ease-sortie),
    visibility calc(var(--d-state) * 0.75) var(--ease-sortie);
}

.nav.est-visible {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition:
    opacity var(--d-state) var(--ease-productive),
    transform var(--d-state) var(--ease-productive),
    visibility var(--d-state) var(--ease-productive);
}

.nav__marque {
  font-family: var(--logotype);
  font-size: 0.78rem;
  letter-spacing: 0.28em;
  text-indent: 0.28em;
  color: var(--creme);
  white-space: nowrap;
  /* WCAG 2.5.8 : 24 px de haut au minimum. L'exception d'espacement
     s'appliquerait — le premier onglet est à près de 100 px de centre à
     centre — mais une cible qui fait la taille reste préférable à une cible
     qui plaide l'exception. */
  display: inline-flex;
  align-items: center;
  min-height: 24px;
}

.nav__liste {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.15rem;
}

.nav__lien {
  position: relative;
  z-index: 1;
  padding: 0.5rem 0.95rem;
  border-radius: 999px;
  font-size: 0.83rem;
  letter-spacing: 0.02em;
  color: var(--gris);
  white-space: nowrap;
  transition: color var(--d-micro) var(--ease-productive);
}

.nav__lien:hover,
.nav__lien[aria-current='true'] {
  color: var(--fond);
}

.nav__lien:hover:not([aria-current='true']) {
  color: var(--creme);
}

/* La pastille or glisse d'un onglet à l'autre, sur l'easing signature. */
/* LA PASTILLE EST DÉCOUPÉE, PAS REDIMENSIONNÉE.

   Elle animait `width` en même temps que `transform` : c'était la dernière
   transition sur une propriété de mise en page du site, et la charte les
   interdit depuis le gel de production — chacune invalide la mise en page à
   chaque image.

   `scaleX` n'était pas une option : sur une pastille à `border-radius: 999px`
   il écrase les deux bouts en ellipses, et la déformation se voit.

   `clip-path: inset(… round 999px)` fait exactement le travail : l'élément
   occupe toute la largeur de la liste, on ne découpe que la fenêtre visible,
   et le `round` garde des bouts parfaitement circulaires à chaque étape.
   C'est une propriété composée, jamais une propriété de mise en page. */
.nav__pastille {
  position: absolute;
  inset: 0;
  z-index: 0;
  opacity: 0;
  transition: opacity var(--d-micro) var(--ease-productive);
}

/* L'OR EST PEINT PAR LE PSEUDO-ÉLÉMENT, pas par la boîte elle-même.

   La boîte couvre toute la liste : c'est ce qui permet de ne découper que la
   fenêtre du lien actif. Mais un aplat or étendu derrière TOUS les liens fait
   conclure aux outils d'audit — et à axe en particulier — que le gris des
   liens inactifs se lit sur de l'or, soit 1,3:1. C'est faux à l'écran, le
   `clip-path` ne peint rien là, mais l'inférence est légitime : le DOM
   affirmait quelque chose que le rendu contredit.

   La boîte reste donc transparente et ne sert qu'au positionnement ; le
   `::before` porte la couleur et le découpage. Rendu identique, et plus
   aucun fond coloré derrière les liens inactifs. */
.nav__pastille::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 999px;
  background: var(--or);
  /* Fermée par défaut, à gauche : sans JS elle reste invisible. */
  clip-path: var(--decoupe, inset(0 100% 0 0 round 999px));
  transition: clip-path var(--d-state) var(--ease-productive);
}

.nav__pastille.sans-transition::before {
  transition: none;
}

.nav__cta {
  padding: 0.55rem 1.15rem;
  border-radius: 999px;
  border: 1px solid var(--trait-fort);
  font-size: 0.83rem;
  color: var(--or-lien);
  white-space: nowrap;
  transition:
    background-color var(--d-micro) var(--ease-productive),
    color var(--d-micro) var(--ease-productive);
}

.nav__cta:hover,
.nav__cta:focus-visible {
  background: var(--or);
  color: var(--fond);
}

.nav__burger {
  display: none;
  width: 42px;
  height: 42px;
  border: 1px solid var(--trait);
  border-radius: 999px;
  background: none;
  cursor: pointer;
  padding: 0;
  place-content: center;
  gap: 5px;
}

.nav__burger span {
  display: block;
  width: 16px;
  height: 1px;
  background: var(--or-lien);
  margin-inline: auto;
}

@media (max-width: 900px) {
  .nav__liste,
  .nav__cta {
    display: none;
  }
  .nav__burger {
    display: grid;
  }
  .nav {
    padding-right: 0.42rem;
  }
}

/* --- Menu mobile : popover natif (Escape, clic extérieur, focus offerts) - */

.menu {
  inset: 0;
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  margin: 0;
  padding: clamp(4.5rem, 14vh, 8rem) var(--gouttiere);
  padding: clamp(4.5rem, 14svh, 8rem) var(--gouttiere);
  border: 0;
  /* Opaque, pas translucide : à 0,92 le contenu de la page se lisait encore
     derrière les liens et la navigation devenait pénible. */
  background: var(--fond);
  color: var(--creme);
  display: grid;
  align-content: center;
  gap: clamp(0.6rem, 2vh, 1.2rem);
  gap: clamp(0.6rem, 2svh, 1.2rem);
  /* Le menu défile en interne quand la liste dépasse : le geste ne doit pas
     se propager à la page derrière une fois arrivé au bout. */
  overflow-y: auto;
  overscroll-behavior: contain;
  opacity: 0;
  /* Fermeture : 0,75 × 600 = 450 ms, sur une courbe qui accélère. Un
     panneau ouvert en expo.out qui se refermerait mollement puis d'un coup
     est exactement le défaut que cette asymétrie corrige. */
  transition:
    opacity calc(var(--d-panel) * 0.75) var(--ease-sortie),
    display calc(var(--d-panel) * 0.75) allow-discrete,
    overlay calc(var(--d-panel) * 0.75) allow-discrete;
}

.menu:popover-open {
  opacity: 1;
  transition:
    opacity var(--d-panel) var(--ease-expressive),
    display var(--d-panel) allow-discrete,
    overlay var(--d-panel) allow-discrete;
}

@starting-style {
  .menu:popover-open {
    opacity: 0;
  }
}

.menu::backdrop {
  background: rgba(8, 12, 20, 0.92);
}

.menu a {
  font-family: var(--display);
  font-size: clamp(1.9rem, 8vw, 3.2rem);
  letter-spacing: var(--tr-xl);
  text-transform: none;
  color: var(--creme);
  line-height: 1.06;
}

.menu a:hover,
.menu a:focus-visible {
  color: var(--or-lien);
}

.menu__fermer {
  justify-self: start;
  margin-top: 1.5rem;
  padding: 0.7rem 1.4rem;
  border: 1px solid var(--trait-fort);
  border-radius: 999px;
  background: none;
  color: var(--or-lien);
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  cursor: pointer;
}

/* =========================================================================
   3. LE BADGE CIRCULAIRE
   ========================================================================= */

.badge {
  position: fixed;
  right: clamp(1rem, 2.5vw, 2rem);
  bottom: clamp(1rem, 2.5vw, 2rem);
  z-index: 80;
  /* 120 px à l'écran. Le viewBox reste à 140 : c'est le rayon dont la
     baseline a besoin pour faire le tour sans se chevaucher, et le SVG se
     met à l'échelle. */
  width: 120px;
  height: 120px;
  display: grid;
  place-content: center;
  border-radius: 50%;
  background: rgba(8, 12, 20, 0.78);
  border: 1px solid var(--trait);
  color: var(--or-lien);
  opacity: 0;
  visibility: hidden;
  transform: scale(0.86);
  transition:
    opacity calc(var(--d-reveal) * 0.75) var(--ease-sortie),
    transform calc(var(--d-reveal) * 0.75) var(--ease-sortie),
    visibility calc(var(--d-reveal) * 0.75) var(--ease-sortie);
}

.hero-passe .badge {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition:
    opacity var(--d-reveal) var(--ease-expressive),
    transform var(--d-reveal) var(--ease-expressive),
    visibility var(--d-reveal) var(--ease-expressive);
}

.badge svg {
  overflow: visible;
}

.badge__anneau {
  transform-origin: 70px 70px;
  /* Boucle infinie : seconde et dernière durée littérale autorisée. */
  animation: tourne 24s linear infinite;
}

/* La baseline fait 56 signes. Sur un cercle de rayon 52, la circonférence
   vaut 327 px : au-delà de ~5,8 px par signe, le texte se rattrape et se
   chevauche. IBM Plex Mono avance de 0,6 em, d'où ces valeurs. */
.badge__texte {
  font-family: var(--mono);
  font-size: 7.6px;
  letter-spacing: 0.13em;
  fill: var(--or);
}

.badge__fleche {
  transition: transform var(--d-micro) var(--ease-productive);
  transform-origin: 70px 70px;
}

.badge:hover .badge__fleche,
.badge:focus-visible .badge__fleche {
  transform: translateY(3px);
}

@keyframes tourne {
  to {
    transform: rotate(360deg);
  }
}

/* WCAG 2.2.2 — le mouvement automatique de plus de cinq secondes doit
   pouvoir être arrêté. Le bouton du bandeau pose `.mouvement-pause` sur
   <html> et vaut donc pour les deux boucles du site. Le survol et le focus
   s'y ajoutent, sans jamais tenir lieu de mécanisme. */
.badge:hover .badge__anneau,
.badge:focus-visible .badge__anneau,
.mouvement-pause .badge__anneau {
  animation-play-state: paused;
}

@media (prefers-reduced-motion: reduce) {
  .badge__anneau {
    animation-play-state: paused;
  }
}

/* Sur mobile il n'y a pas la place : le badge disparaît plutôt que de venir
   se poser sur l'altimètre et sur les lignes de chantier. */
@media (max-width: 767px) {
  .badge {
    display: none;
  }
}

/* =========================================================================
   4. STRUCTURE DES SCÈNES
   ========================================================================= */

.scene {
  position: relative;
  /* Le filet est bord à bord, donc collé en haut de la section : le padding
     du haut est repris par le filet lui-même. */
  padding-block: 0 var(--scene-y);
  scroll-margin-top: 6.5rem;
}

/* LE FILET PLEINE LARGEUR — relevé sur PX PUSH.
   Un trait de 1 px bord à bord, sans marge, entre chaque section, avec le
   numéro et le libellé accrochés dessus à gauche. C'est ce qui donne
   l'impression d'un document structuré plutôt que d'une suite de blocs.

   Il remplace l'ancien `[ 0N ] Libellé` : le même contenu, mais accroché à
   une structure au lieu de flotter au-dessus d'un bloc. */
.filet {
  display: flex;
  align-items: baseline;
  gap: clamp(0.9rem, 2.5vw, 2.2rem);
  max-width: none;
  margin: 0 0 var(--scene-y);
  padding: clamp(0.9rem, 2.2vh, 1.4rem) var(--gouttiere) 0;
  padding: clamp(0.9rem, 2.2svh, 1.4rem) var(--gouttiere) 0;
  border-top: 1px solid var(--trait);
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  line-height: 1.7;
  font-variant-numeric: tabular-nums;
}

/* Variante interne : même grammaire, mais dans une colonne au lieu d'être
   bord à bord. Sert aux comparateurs, aux références et aux partenaires. */
.filet--interne {
  padding-inline: 0;
  margin-bottom: clamp(0.8rem, 2vh, 1.2rem);
  margin-bottom: clamp(0.8rem, 2svh, 1.2rem);
}

.filet__no {
  color: var(--or-lien);
  flex: none;
}

.filet__lib {
  color: var(--gris);
}

/* La première section suit le hero : son filet marquerait une coupure là où
   le fond continu ne doit justement pas en avoir. */
.scene:first-of-type .filet {
  border-top: 0;
}

/* =========================================================================
   L'INDICATEUR DE SECTION NUMÉROTÉ

   Relevé sur PX PUSH, dont les sections sont libellées `Nº001 / Intro`.
   Deux span empilés dans un conteneur en overflow hidden ; à chaque
   changement de section, flip vertical.

   Déclenché par IntersectionObserver, JAMAIS par ScrollTrigger : on est sous
   le hero pinné, et le pin plus Lenis décalent toutes les positions.

   `aria-hidden` et `pointer-events: none` : c'est une métadonnée de lecture,
   le vrai titre de chaque section est son <h2>. Masqué sous 861 px, où la
   gouttière ne fait plus que 1,25 rem et où il viendrait se poser sur le
   texte.
   ========================================================================= */

.indicateur {
  position: fixed;
  left: clamp(1rem, 2.5vw, 2rem);
  bottom: clamp(1rem, 2.5vw, 2rem);
  z-index: 80;
  pointer-events: none;
  /* Même langage que la pilule de nav et le badge : un fond opaque et un
     filet. Sans lui, l'indicateur se confondait avec l'étiquette du filet de
     la section suivante quand celle-ci passait près du coin bas gauche —
     deux libellés mono presque identiques, l'un fixe, l'autre qui défile.
     Fond plein et non `backdrop-filter` : sur une surface qui défile, il
     force une recomposition par image. */
  padding: 0.5rem 0.9rem;
  border-radius: 999px;
  background: rgba(8, 12, 20, 0.8);
  border: 1px solid var(--trait);
  opacity: 0;
  visibility: hidden;
  transition:
    opacity calc(var(--d-state) * 0.75) var(--ease-sortie),
    visibility calc(var(--d-state) * 0.75) var(--ease-sortie);
}

.hero-passe .indicateur {
  opacity: 1;
  visibility: visible;
  transition:
    opacity var(--d-state) var(--ease-productive),
    visibility var(--d-state) var(--ease-productive);
}

.indicateur__masque {
  /* Les deux span occupent la MÊME cellule de grille. En absolu, le masque
     n'aurait aucune largeur intrinsèque et se replierait à zéro ; ici il se
     dimensionne sur le plus large des deux libellés, et les deux restent
     empilés pour le flip. */
  display: grid;
  overflow: hidden;
  height: 1.4em;
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  line-height: 1.4;
  font-variant-numeric: tabular-nums;
  color: var(--gris);
}

.indicateur__i {
  grid-area: 1 / 1;
  display: block;
  white-space: nowrap;
}

.indicateur__i b {
  font-weight: 400;
  color: var(--or-lien);
}

/* Le span entrant ne porte AUCUN transform en CSS. Un `translateY(100%)`
   posé ici serait lu par GSAP comme un `y` de 16,7 px — une translation en
   pourcentage ne se relit pas dans la matrice calculée — et le `yPercent`
   du tween viendrait s'y ajouter au lieu de le remplacer : le span entrant
   n'arriverait jamais à sa place. Il est créé par le JS, donc sans JS il
   n'existe pas et n'a rien à masquer. */

@media (max-width: 860px) {
  .indicateur {
    display: none;
  }
}

.scene__titre {
  font-size: var(--t-xl);
  letter-spacing: var(--tr-xl);
  margin-bottom: clamp(1.8rem, 5vh, 3.4rem);
  margin-bottom: clamp(1.8rem, 5svh, 3.4rem);
}

/* L'or de titrage. Un seul dégradé pour tout le site, déclaré dans base.css.
   La classe .or-fond porte le background-clip et son repli @supports. */
.scene__titre,
.couvreur__titre,
.appel__titre,
.procede__titre {
  background-image: var(--or-degrade);
  background-repeat: no-repeat;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

@supports not ((background-clip: text) or (-webkit-background-clip: text)) {
  .scene__titre,
  .couvreur__titre,
  .appel__titre,
  .procede__titre {
    background-image: none;
    color: var(--or);
  }
}

/* =========================================================================
   SCÈNE 01 — PERSONNE NE MONTE
   Effet signature : le split-text line-reveal.
   ========================================================================= */

.manifeste {
  display: grid;
  gap: clamp(0.1rem, 0.6vh, 0.5rem);
  gap: clamp(0.1rem, 0.6svh, 0.5rem);
}

.manifeste li {
  font-family: var(--display);
  font-size: var(--t-xl);
  line-height: 1.02;
  letter-spacing: var(--tr-xl);
  text-transform: none;
  color: var(--creme);
  text-wrap: balance;
}

/* Le découpage est fait une seule fois au load. Le texte réel reste dans le
   DOM ; on n'insère que des éléments de présentation.
   L'état masqué de départ est posé par le JS, pas ici : si le script ne se
   charge pas, ces lignes doivent rester lisibles plutôt que de rester
   coincées hors de leur cadre. */
/* Le masque de découpe ne doit RIEN AJOUTER À LA HAUTEUR.

   Le `padding-bottom` est là pour que `overflow: hidden` ne rogne pas les
   jambages pendant la révélation. Mais depuis que la découpe est défaite à la
   fin de l'animation — pour rendre au DOM les dix nœuds qu'elle occupait —
   ce padding disparaissait avec elle : le manifeste perdait 23 px, tout ce
   qui suit remontait d'autant, et ce seul décalage valait un CLS de 0,016,
   vingt fois le reste du site. Mesuré et corrigé.

   La marge négative de même valeur annule la hauteur ajoutée : la place pour
   les jambages existe, la boîte n'en tient pas compte, et défaire la découpe
   ne change plus rien. */
.manifeste .decoupe {
  display: block;
  overflow: hidden;
  padding-bottom: 0.05em;
  margin-bottom: -0.05em;
}

.manifeste .decoupe > * {
  display: block;
}

/* Rythme typographique, pas une hiérarchie : on reste dans la famille du
   crème, un gris bleuté ferait lire ces lignes-là comme désactivées. */
.manifeste li:nth-child(even) {
  color: rgba(242, 240, 235, 0.52);
}

.manifeste__sous {
  margin-top: clamp(2rem, 6vh, 3.5rem);
  margin-top: clamp(2rem, 6svh, 3.5rem);
  font-size: calc(var(--t-mono) * 1.15);
  letter-spacing: 0.24em;
}

.manifeste__note {
  margin-top: 0.9rem;
  text-transform: none;
  letter-spacing: 0.06em;
  color: var(--gris);
  opacity: 0.72;
  max-width: 48ch;
}

/* =========================================================================
   SCÈNE 02 — LE COUVREUR
   Effet signature : le compteur odomètre.
   ========================================================================= */

.couvreur {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: clamp(2.5rem, 7vw, 7rem);
  align-items: start;
}

.couvreur__titre {
  font-size: var(--t-l);
  margin-bottom: 1.4rem;
}

.couvreur__nom {
  margin-bottom: clamp(1.6rem, 4vh, 2.6rem);
  margin-bottom: clamp(1.6rem, 4svh, 2.6rem);
  letter-spacing: 0.2em;
}

.couvreur__corps {
  font-size: var(--t-s);
  color: var(--creme);
  opacity: 0.88;
  margin-bottom: 1.2rem;
}

.couvreur__chiffres {
  display: grid;
  gap: clamp(1.6rem, 4vh, 2.6rem);
  gap: clamp(1.6rem, 4svh, 2.6rem);
  padding-top: 0.4rem;
}

.odo {
  display: grid;
  gap: 0.5rem;
  border-top: 1px solid var(--trait);
  padding-top: clamp(0.9rem, 2.4vh, 1.5rem);
  padding-top: clamp(0.9rem, 2.4svh, 1.5rem);
}

.odo__valeur {
  display: flex;
  gap: 0.02em;
  font-family: var(--mono);
  font-weight: 500;
  font-size: clamp(3.2rem, 8vw, 6.2rem);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--or);
}

/* Chaque chiffre est une colonne 0-9 qui roule et s'arrête. */
.odo__col {
  height: 1em;
  overflow: hidden;
}

/* Pas de `will-change` ici. La règle vaudrait pour six rouleaux — trois
   compteurs de deux chiffres — et le budget du site est de trois éléments au
   maximum en statique, déjà pris par le canvas du hero et la piste du
   marquee. js/scenes.js le pose juste avant l'animation et le retire juste
   après : une couche de composition ouverte en permanence pour un compteur
   qui roule 1,2 s une seule fois est du gâchis. */
.odo__rouleau {
  display: block;
}

/* LE DÉGRADÉ EST POSÉ SUR LE CHIFFRE LUI-MÊME, et pas sur `.odo__valeur`.

   Posé sur le conteneur, il ne s'affichait pas du tout : `background-clip:
   text` découpe le fond de l'élément sur la forme de ses glyphes, mais
   `.odo__rouleau` porte un `transform` — il est translaté de -3 075 px pour
   amener le bon chiffre dans la fenêtre — et un descendant transformé est
   peint dans sa propre couche, donc ses glyphes sortent du masque du parent.
   Les chiffres étaient rendus en `color: transparent` avec plus rien
   derrière. Mesuré et corrigé au lot 4.

   Chaque chiffre porte donc le dégradé sur sa propre boîte. Sur un nombre à
   deux chiffres, les deux reçoivent la même course : ils se lisent comme une
   paire assortie, ce qui est le bon rendu ici. */
.odo__rouleau span {
  display: block;
  height: 1em;
  line-height: 1;
  background-image: var(--or-degrade);
  background-repeat: no-repeat;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

@supports not ((background-clip: text) or (-webkit-background-clip: text)) {
  .odo__rouleau span {
    background-image: none;
    color: var(--or);
  }
}

.odo__legende {
  color: var(--gris);
  letter-spacing: 0.18em;
}

@media (max-width: 860px) {
  .couvreur {
    grid-template-columns: 1fr;
  }
  .couvreur__chiffres {
    grid-template-columns: repeat(3, 1fr);
    gap: 1.2rem;
  }
}

/* =========================================================================
   SCÈNE 03 — LES QUATRE ALTITUDES
   Effet signature : le projecteur.
   ========================================================================= */

.altitudes {
  position: relative;
  container-type: inline-size;
}

.altitude {
  position: relative;
  border-top: 1px solid rgba(200, 169, 107, 0.16);
}

.altitude:last-child {
  border-bottom: 1px solid rgba(200, 169, 107, 0.16);
}

.altitude__lien {
  position: relative;
  z-index: 2;
  display: grid;
  /* Colonnes fixes, pas des fr : chaque ligne est sa propre grille, et des
     fractions se recalculeraient sur le contenu de la ligne. Les quatre
     lignes ne seraient alors jamais alignées entre elles. */
  grid-template-columns: 4.5rem clamp(11rem, 24vw, 20rem) minmax(0, 1fr) auto;
  align-items: baseline;
  gap: clamp(0.6rem, 2vw, 2rem);
  padding-block: clamp(1.5rem, 4.2vh, 2.6rem);
  padding-block: clamp(1.5rem, 4.2svh, 2.6rem);
  color: var(--creme);
  transition: color var(--d-micro) var(--ease-productive);
}

.altitude__num {
  color: var(--or);
  letter-spacing: 0.1em;
}

.altitude__nom {
  font-family: var(--display);
  font-size: var(--t-l);
  letter-spacing: var(--tr-l);
  text-transform: none;
  line-height: 1;
}

.altitude__quoi {
  font-size: var(--t-s);
  color: var(--gris);
}

.altitude__detail {
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gris);
  text-align: right;
}

.altitude__lien:hover .altitude__nom,
.altitude:has(:focus-visible) .altitude__nom {
  color: var(--or-lien);
}

/* Le faisceau : un masque radial qui suit le curseur en lerp. */
.altitude__vue {
  position: absolute;
  inset: 0;
  z-index: 1;
  overflow: hidden;
  background: var(--fond-2); /* la photo est en lazy : pas de trou en attendant */
  opacity: 0;
  transition: opacity var(--d-state) var(--ease-expressive);
  pointer-events: none;
}

.altitude__vue img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(0.3) brightness(0.62);
}

@media (hover: hover) and (pointer: fine) {
  .altitudes[data-projecteur] .altitude__vue {
    --mx: 50%;
    --my: 50%;
    -webkit-mask-image: radial-gradient(
      circle 190px at var(--mx) var(--my),
      #000 0%,
      rgba(0, 0, 0, 0.55) 55%,
      transparent 76%
    );
    mask-image: radial-gradient(
      circle 190px at var(--mx) var(--my),
      #000 0%,
      rgba(0, 0, 0, 0.55) 55%,
      transparent 76%
    );
  }

  .altitude:hover .altitude__vue {
    opacity: 1;
  }
}

/* Porte de sortie obligatoire : au clavier, la photo apparaît en bloc. */
.altitude:has(:focus-visible) .altitude__vue {
  opacity: 1;
  -webkit-mask-image: none;
  mask-image: none;
}

/* Porte de sortie obligatoire : sur pointeur grossier, pas de faisceau.
   La photo prend sa place dans le flux. La largeur compte autant que le
   pointeur : sur une fenêtre étroite, un faisceau de 190 px couvrirait la
   moitié de la ligne et ne révélerait plus rien. */
@media (pointer: coarse), (hover: none), (max-width: 860px) {
  /* Même sélecteur que le bloc du faisceau : à spécificité égale, c'est
     l'ordre qui tranche, et celui-ci vient après. */
  .altitudes[data-projecteur] .altitude__vue,
  .altitude__vue {
    position: relative;
    inset: auto;
    opacity: 1;
    height: clamp(200px, 52vw, 320px);
    margin-bottom: clamp(1.2rem, 3vh, 2rem);
    margin-bottom: clamp(1.2rem, 3svh, 2rem);
    -webkit-mask-image: none;
    mask-image: none;
  }

  .altitude__vue img {
    filter: none;
  }

  .altitude__lien {
    grid-template-columns: 3rem minmax(0, 1fr);
    row-gap: 0.35rem;
  }

  .altitude__quoi,
  .altitude__detail {
    grid-column: 2;
    text-align: left;
  }
}

@container (max-width: 720px) {
  .altitude__lien {
    grid-template-columns: 3rem minmax(0, 1fr);
    row-gap: 0.35rem;
  }
  .altitude__quoi,
  .altitude__detail {
    grid-column: 2;
    text-align: left;
  }
}

@media (prefers-reduced-motion: reduce) {
  .altitudes[data-projecteur] .altitude__vue,
  .altitude__vue {
    position: relative;
    inset: auto;
    opacity: 1;
    height: clamp(180px, 30vw, 280px);
    margin-bottom: 1.2rem;
    -webkit-mask-image: none;
    mask-image: none;
  }
}

/* =========================================================================
   SCÈNE 04 — LA PREUVE
   Effet signature : le comparateur au drag.
   ========================================================================= */

.preuve__intro {
  font-size: var(--t-s);
  color: var(--gris);
  margin-bottom: clamp(1.6rem, 4vh, 2.6rem);
  margin-bottom: clamp(1.6rem, 4svh, 2.6rem);
  max-width: 46ch;
}

/* Les quatre comparateurs réels, en deux colonnes. Toutes les paires sont
   ramenées au même format 4/3 : l'une d'elles est en portrait, et une grille
   de rapports mélangés laisserait des trous. Le recadrage se fait en
   `object-fit: cover` avec un `object-position` réglé par paire — la photo du
   client n'est jamais recadrée dans le fichier. */
.preuve__liste {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(30rem, 100%), 1fr));
  gap: clamp(2rem, 5vw, 4rem);
  margin-bottom: clamp(3rem, 8vh, 5rem);
  margin-bottom: clamp(3rem, 8svh, 5rem);
}

.preuve__rendu {
  max-width: 980px;
  margin-bottom: clamp(3rem, 9vh, 6rem);
  margin-bottom: clamp(3rem, 9svh, 6rem);
}

.cmp {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border: 1px solid var(--trait);
  background: var(--fond-2);
  touch-action: pan-y; /* le drag horizontal ne doit pas voler le scroll */
  --pos: 50%;
}

.cmp--rendu {
  width: min(100%, 980px);
  aspect-ratio: 900 / 290;
}

.cmp__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--cmp-pos, 50% 50%);
}

/* Les deux images occupent exactement la même boîte et c'est le rognage qui
   bouge, pas leur largeur. Un masque à largeur variable redimensionnerait
   l'image « avant » et les deux moitiés cesseraient d'être au même cadrage. */
.cmp__img--avant {
  clip-path: inset(0 calc(100% - var(--pos)) 0 0);
}

/* Le vrai contrôle est un input range : clavier, lecteur d'écran, tactile. */
.cmp__curseur {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: ew-resize;
  appearance: none;
  background: none;
}

.cmp__curseur::-webkit-slider-thumb {
  appearance: none;
  width: 56px;
  height: 100%;
}

.cmp__curseur::-moz-range-thumb {
  width: 56px;
  height: 100%;
  border: 0;
  background: none;
}

.cmp__poignee {
  position: absolute;
  top: 50%;
  left: var(--pos);
  z-index: 2;
  translate: -50% -50%;
  display: grid;
  place-content: center;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--fond);
  border: 1px solid var(--or);
  color: var(--or);
  pointer-events: none;
}

.cmp__poignee::before {
  content: '';
  position: absolute;
  left: 50%;
  /* `svh` et jamais `vh` : sur mobile, `vh` se mesure sur le viewport large
     et le trait dépasserait du comparateur pendant que la barre d'adresse se
     replie. */
  top: -50svh;
  width: 1px;
  height: 100svh;
  background: var(--or);
  opacity: 0.55;
  translate: -50% 0;
}

.cmp__curseur:focus-visible ~ .cmp__poignee {
  outline: 2px solid var(--or);
  outline-offset: 4px;
}

.cmp__etiquette {
  position: absolute;
  bottom: 0.9rem;
  z-index: 2;
  padding: 0.3rem 0.7rem;
  background: var(--voile);
  color: var(--creme);
  letter-spacing: 0.2em;
  pointer-events: none;
}

.cmp__etiquette--g {
  left: 0.9rem;
}

.cmp__etiquette--d {
  right: 0.9rem;
}

.preuve__legende {
  margin-top: 0.9rem;
  letter-spacing: 0.16em;
  opacity: 0.75;
}

.cmp__meta {
  margin-top: 0.9rem;
  letter-spacing: 0.16em;
  color: var(--gris);
}

/* --- Les références professionnelles ------------------------------------ */

.refs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  gap: clamp(1.2rem, 3vw, 2.6rem);
  margin-top: clamp(1.5rem, 4vh, 2.5rem);
  margin-top: clamp(1.5rem, 4svh, 2.5rem);
}

.ref {
  display: grid;
  gap: 0.9rem;
  align-content: start;
}

.ref img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  background: var(--fond-2);
  filter: saturate(0.82) contrast(1.04);
}

.ref figcaption {
  letter-spacing: 0.14em;
  color: var(--gris);
}

.refs__titre {
  font-size: var(--t-l);
  letter-spacing: var(--tr-l);
  margin-top: clamp(3rem, 8vh, 5rem);
  margin-top: clamp(3rem, 8svh, 5rem);
}

.chantiers {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr));
  gap: clamp(1.2rem, 3vw, 2.6rem);
}

.chantier {
  container-type: inline-size;
  align-content: start;
}

/* La vignette entière est le lien vers la page du chantier. C'est une seule
   cible, large, et il n'y a pas de « lire la suite » à côté d'une image
   cliquable — deux liens vers la même URL, c'est un arrêt de tabulation en
   trop pour rien. */
.chantier__lien {
  display: grid;
  gap: 0.75rem;
  align-content: start;
  color: var(--creme);
}

.chantier__nom {
  font-family: var(--display);
  font-size: var(--t-l);
  letter-spacing: var(--tr-l);
  line-height: 1.05;
  transition: color var(--d-micro) var(--ease-productive);
}

.chantier__lien:hover .chantier__nom,
.chantier__lien:focus-visible .chantier__nom {
  color: var(--or-lien);
}

.chantier__num {
  font-family: var(--display);
  font-size: 1.15rem;
  letter-spacing: 0.1em;
  background-image: var(--or-degrade);
  background-repeat: no-repeat;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

@supports not ((background-clip: text) or (-webkit-background-clip: text)) {
  .chantier__num {
    background-image: none;
    color: var(--or);
  }
}

.chantier__vue {
  overflow: hidden;
  background: var(--fond-2);
  aspect-ratio: 3 / 4;
}

.chantier__vue img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(0.82) contrast(1.04);
  transition: transform var(--d-panel) var(--ease-expressive);
}

.chantier__lien:hover .chantier__vue img {
  transform: scale(1.035);
}

.chantier__meta {
  letter-spacing: 0.14em;
  line-height: 1.9;
}

@media (prefers-reduced-motion: reduce) {
  .chantier__lien:hover .chantier__vue img {
    transform: none;
  }
}

/* =========================================================================
   SCÈNE 06 — LE SIMULATEUR
   Trois questions à gauche, la sortie à droite. Aucun champ libre, aucun
   prix. Les boutons reprennent la grammaire mono du site.
   ========================================================================= */

.simu {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: clamp(2.5rem, 6vw, 6rem);
  align-items: start;
}

.simu__questions {
  display: grid;
  gap: clamp(2rem, 5vh, 3.2rem);
  gap: clamp(2rem, 5svh, 3.2rem);
}

/* LE FILET EST SUR LA <legend>, PAS SUR LE <fieldset>.

   Deux pièges évités d'un coup. Une <legend> s'encastre par défaut DANS la
   bordure de son fieldset et la coupe : le filet passait au travers du
   libellé. Le remède habituel — `float: left` avec une largeur pleine — a
   été essayé et provoque pire : un flottant de 100 % ne laisse aucune place
   à côté de lui, la rangée de boutons qui suit se retrouve à 0 px de large,
   poussée hors de l'écran, et le site gagne un défilement horizontal sous
   900 px. Mesuré : 431 px de large pour un viewport de 320.

   Le fieldset n'a donc aucune bordure, et c'est la légende qui porte le
   filet. Rien à encastrer, rien à faire flotter. */
.simu__q {
  border: 0;
  padding: 0;
  margin: 0;
}

.simu__legende {
  display: block;
  width: 100%;
  border-top: 1px solid var(--trait);
  padding: clamp(1rem, 2.5vh, 1.5rem) 0 0;
  padding: clamp(1rem, 2.5svh, 1.5rem) 0 0;
  color: var(--or-lien);
  margin-bottom: clamp(0.9rem, 2.2vh, 1.3rem);
  margin-bottom: clamp(0.9rem, 2.2svh, 1.3rem);
}

.simu__opts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.simu__opt {
  min-height: 44px;
  padding: 0.55rem 1.1rem;
  border: 1px solid var(--trait);
  border-radius: 999px;
  background: none;
  color: var(--gris);
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
  transition:
    border-color var(--d-micro) var(--ease-productive),
    background-color var(--d-micro) var(--ease-productive),
    color var(--d-micro) var(--ease-productive);
}

.simu__opt:hover {
  border-color: var(--trait-fort);
  color: var(--creme);
}

/* L'état retenu est porté par `aria-pressed` et non par une classe : l'état
   visuel et l'état annoncé au lecteur d'écran ne peuvent pas diverger. */
.simu__opt[aria-pressed='true'] {
  background: var(--or);
  border-color: var(--or);
  color: var(--fond);
}

.simu__m2 {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  margin-bottom: 0.6rem;
}

.simu__m2-val {
  font-family: var(--mono);
  font-weight: 500;
  font-size: clamp(2.6rem, 6vw, 4.4rem);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  background-image: var(--or-degrade);
  background-repeat: no-repeat;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

@supports not ((background-clip: text) or (-webkit-background-clip: text)) {
  .simu__m2-val {
    background-image: none;
    color: var(--or);
  }
}

.simu__m2-unite {
  color: var(--gris);
  letter-spacing: 0.16em;
}

/* Le curseur natif, réhabillé. On ne remplace jamais le contrôle : c'est lui
   qui porte le clavier, le tactile et le lecteur d'écran. */
.simu__range {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 44px;
  background: none;
  cursor: ew-resize;
}

.simu__range::-webkit-slider-runnable-track {
  height: 1px;
  background: var(--trait-fort);
}

.simu__range::-moz-range-track {
  height: 1px;
  background: var(--trait-fort);
}

.simu__range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 22px;
  height: 22px;
  margin-top: -10.5px;
  border-radius: 50%;
  background: var(--or);
  border: 0;
}

.simu__range::-moz-range-thumb {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--or);
  border: 0;
}

.simu__bornes {
  display: flex;
  justify-content: space-between;
  color: var(--gris);
  letter-spacing: 0.14em;
}

.simu__resultats {
  margin-top: clamp(0.5rem, 1.5vh, 1rem);
  margin-top: clamp(0.5rem, 1.5svh, 1rem);
}

.simu__ligne {
  border-top: 1px solid var(--trait);
  padding-block: clamp(1rem, 2.6vh, 1.6rem);
  padding-block: clamp(1rem, 2.6svh, 1.6rem);
}

.simu__ligne:last-child {
  border-bottom: 1px solid var(--trait);
}

.simu__ligne dt {
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gris);
  margin-bottom: 0.4rem;
}

.simu__ligne dd {
  margin: 0;
  font-family: var(--display);
  font-size: var(--t-l);
  letter-spacing: var(--tr-l);
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  color: var(--creme);
}

.simu__sous {
  display: block;
  margin-top: 0.5rem;
  color: var(--gris);
  letter-spacing: 0.12em;
  text-transform: none;
  max-width: 46ch;
}

.simu__note {
  margin-block: clamp(1.2rem, 3vh, 2rem);
  margin-block: clamp(1.2rem, 3svh, 2rem);
  color: var(--gris);
  text-transform: none;
  letter-spacing: 0.08em;
  line-height: 1.8;
  max-width: 52ch;
}

@media (max-width: 900px) {
  .simu {
    grid-template-columns: 1fr;
  }
}

/* =========================================================================
   SCÈNE 05 — LE NETTOYEUR, « PASSEZ LA MAIN »

   Le canvas porte la photo encrassée, la photo propre est une vraie <img>
   posée dessous. On efface le canvas en `destination-out`, et le propre
   apparaît. C'est exactement ce que fait le drone, et c'est le visiteur qui
   le fait.

   Deux modes exclusifs, gouvernés par une classe posée en JS :
   — par défaut, et sans JS, c'est le COMPARATEUR qui s'affiche. C'est aussi
     ce que voient le pointeur grossier, le mouvement réduit, et le clavier ;
   — `.est-canvas` bascule sur le nettoyage.
   ========================================================================= */

.nettoyeur {
  width: min(100%, 980px);
}

.nettoyeur__scene {
  display: none;
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--fond-2);
  /* Le doigt doit pouvoir faire défiler la page par-dessus : on ne prend que
     le geste horizontal, comme pour le comparateur. */
  touch-action: pan-y;
  cursor: crosshair;
}

.nettoyeur.est-canvas .nettoyeur__scene {
  display: block;
}

.nettoyeur.est-canvas .nettoyeur__repli {
  display: none;
}

.nettoyeur__propre,
.nettoyeur__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.nettoyeur__propre {
  object-fit: cover;
  object-position: 50% 42%;
}

.nettoyeur__barre {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: clamp(1rem, 2.5vh, 1.6rem);
  margin-top: clamp(1rem, 2.5svh, 1.6rem);
}

/* LA PLACE DE LA RANGÉE EST RÉSERVÉE D'AVANCE.

   L'invite et les deux boutons sont `hidden` tant que le nettoyeur n'est pas
   monté ; la rangée fait donc 0 px, puis 44 dès que le canvas prend la main.
   Mesuré : les 44 px poussaient tout ce qui suit vers le bas et faisaient à
   eux seuls un CLS de 0,016 — vingt fois le reste du site.

   La réserve n'est posée QUE là où le canvas peut effectivement apparaître,
   c'est-à-dire aux mêmes conditions que js/scenes.js : pointeur fin et
   mouvement non réduit. Ailleurs les boutons ne sortent jamais, et réserver
   la rangée n'ajouterait qu'un vide. */
@media (hover: hover) and (pointer: fine) {
  .nettoyeur__barre {
    min-height: 44px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .nettoyeur__barre {
    min-height: 0;
  }
}

.nettoyeur__invite {
  letter-spacing: 0.16em;
  color: var(--gris);
  text-transform: none;
}

.nettoyeur__boutons {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

/* Le bouton mono du système : même grammaire que le bouton de fermeture du
   menu, donc rien de nouveau. 44 px de haut, bien au-delà des 24 de 2.5.8. */
.btn-mono {
  min-height: 44px;
  padding: 0.6rem 1.2rem;
  border: 1px solid var(--trait-fort);
  border-radius: 999px;
  background: none;
  color: var(--or-lien);
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  cursor: pointer;
  transition:
    background-color var(--d-micro) var(--ease-productive),
    color var(--d-micro) var(--ease-productive);
}

.btn-mono:hover,
.btn-mono:focus-visible {
  background: var(--or);
  color: var(--fond);
}

/* =========================================================================
   SCÈNE 04 — LE COOL ROOFING
   Aucun composant nouveau : le texte reprend la colonne de la section
   couvreur, les trois étapes reprennent `.procede__etape` à l'identique, et
   les bénéfices reprennent la grammaire du filet numéroté.
   ========================================================================= */

.cool__texte {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(28rem, 100%), 1fr));
  gap: clamp(1.5rem, 4vw, 3.5rem);
  margin-bottom: clamp(2rem, 5vh, 3.5rem);
  margin-bottom: clamp(2rem, 5svh, 3.5rem);
}

.cool__corps {
  font-size: var(--t-s);
  color: var(--creme);
  opacity: 0.88;
}

.cool__corps em {
  font-style: normal;
  color: var(--or-lien);
}

.cool__pour {
  grid-column: 1 / -1;
  max-width: 62ch;
  text-transform: none;
  letter-spacing: 0.08em;
  line-height: 1.8;
}

/* Les quatre bénéfices. Pas de chiffres : ce sont des allégations
   réglementées et rien n'a été vérifié. */
.benefices {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(17rem, 100%), 1fr));
  gap: 0 clamp(1.5rem, 4vw, 3.5rem);
  margin-top: clamp(2.5rem, 6vh, 4rem);
  margin-top: clamp(2.5rem, 6svh, 4rem);
}

.benefice {
  display: grid;
  grid-template-columns: 2.5rem minmax(0, 1fr);
  gap: 0.8rem;
  align-items: baseline;
  padding-block: clamp(0.9rem, 2.2vh, 1.4rem);
  padding-block: clamp(0.9rem, 2.2svh, 1.4rem);
  border-top: 1px solid var(--trait);
}

.benefice__no {
  color: var(--or-lien);
  letter-spacing: 0.1em;
}

.benefice__dit {
  font-size: var(--t-s);
  color: var(--creme);
  line-height: 1.45;
}

/* =========================================================================
   SCÈNE 05 — LE PROCÉDÉ
   Contenu pur : aucun effet. Cinq filets pleine largeur, cinq phrases.
   ========================================================================= */

.procede {
  margin-top: clamp(1rem, 3vh, 2rem);
  margin-top: clamp(1rem, 3svh, 2rem);
}

.procede__etape {
  display: grid;
  grid-template-columns: 4.5rem minmax(0, 1fr) auto;
  align-items: baseline;
  gap: clamp(0.6rem, 2vw, 2.5rem);
  /* Bord à bord, comme les filets de section : c'est la même grammaire. */
  padding: clamp(1.4rem, 3.4vh, 2.4rem) var(--gouttiere);
  padding: clamp(1.4rem, 3.4svh, 2.4rem) var(--gouttiere);
  border-top: 1px solid var(--trait);
}

.procede__etape:last-child {
  border-bottom: 1px solid var(--trait);
}

.procede__no {
  color: var(--or-lien);
  letter-spacing: 0.1em;
}

.procede__titre {
  font-size: var(--t-l);
  letter-spacing: var(--tr-l);
  margin-bottom: 0.5rem;
}

.procede__phrase {
  font-size: var(--t-s);
  color: var(--creme);
  opacity: 0.86;
  max-width: 54ch;
}

.procede__duree {
  text-align: right;
  color: var(--gris);
  white-space: nowrap;
}

@media (max-width: 860px) {
  .procede__etape {
    grid-template-columns: 3rem minmax(0, 1fr);
    row-gap: 0.4rem;
  }
  .procede__duree {
    grid-column: 2;
    text-align: left;
  }
}

/* =========================================================================
   SCÈNE 06 — LE TERRITOIRE
   Effet signature : le marquee à vélocité de scroll.
   ========================================================================= */

/* Quatre départements en très grand, chacun suivi de son numéro en exposant
   mono, et sous chacun la liste réelle de ses communes. Aucune carte : vingt
   communes réelles disent le territoire mieux qu'un polygone, et elles se
   référencent.

   Deux états. Déplié — le seul qui existe sans JavaScript, et le seul sur
   mobile, sur pointeur grossier et en mouvement réduit : les quatre listes
   se suivent. Replié — ajouté par js/scenes.js sur pointeur fin et écran
   large : les noms à gauche, une seule liste à droite. */

.territoire__deps {
  display: grid;
  gap: clamp(2rem, 5vh, 3.5rem);
  gap: clamp(2rem, 5svh, 3.5rem);
}

.territoire__dep {
  border-top: 1px solid var(--trait);
  padding-top: clamp(1rem, 2.5vh, 1.6rem);
  padding-top: clamp(1rem, 2.5svh, 1.6rem);
}

.territoire__nom {
  display: flex;
  align-items: flex-start;
  gap: 0.18em;
  font-size: var(--t-xl);
  letter-spacing: var(--tr-xl);
  line-height: 0.9;
  background-image: var(--or-degrade);
  background-repeat: no-repeat;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

@supports not ((background-clip: text) or (-webkit-background-clip: text)) {
  .territoire__nom {
    background-image: none;
    color: var(--or);
  }
}

/* Le numéro est une métadonnée posée en exposant, pas une partie du mot :
   il garde donc sa propre couleur pleine et ne suit pas le dégradé. */
.territoire__num {
  align-self: flex-start;
  font-size: clamp(0.7rem, 1.1vw, 0.95rem);
  letter-spacing: 0.14em;
  color: var(--or-lien);
  line-height: 1;
  padding-top: 0.15em;
}

.territoire__communes {
  margin-top: clamp(1rem, 2.5vh, 1.6rem);
  margin-top: clamp(1rem, 2.5svh, 1.6rem);
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(14rem, 100%), 1fr));
  gap: 0.15rem clamp(1rem, 3vw, 2.5rem);
  text-transform: none;
  letter-spacing: 0.06em;
  color: var(--creme);
  font-variant-numeric: tabular-nums;
}

.territoire__communes li {
  display: flex;
  justify-content: space-between;
  gap: 1.5rem;
  padding-block: 0.28rem;
  border-bottom: 1px solid rgba(200, 169, 107, 0.08);
}

/* La distance, quand le client l'aura fournie. Largeur fixe et chiffres
   tabulaires : la colonne s'aligne sur la décimale, pas sur la longueur du
   nom de commune. */
.territoire__communes .km {
  flex: none;
  min-width: 5.5ch;
  text-align: right;
  font-weight: 400;
  color: var(--or-lien);
  font-variant-numeric: tabular-nums;
}

/* --- État replié, ajouté par le JS -------------------------------------- */

/* La colonne de droite est en absolu dans la section, pas en grid-column :
   les listes sont petites-filles de la grille, une grille ne place que ses
   enfants directs, et `display: contents` sur le <li> casserait la
   sémantique de liste dans plusieurs lecteurs d'écran. */
.territoire.est-replie {
  position: relative;
}

.territoire.est-replie .territoire__deps {
  width: 48%;
  gap: 0;
}

.territoire.est-replie .territoire__nom {
  font-size: var(--t-xxl);
  letter-spacing: var(--tr-xxl);
  transition: opacity var(--d-state) var(--ease-productive);
}

/* Le département qui n'est pas lu passe en retrait. On agit sur l'opacité
   du nom seul : sur l'élément entier, la liste de droite s'éteindrait avec
   lui puisqu'elle est son enfant. */
.territoire.est-replie .territoire__dep:not(.est-actif) .territoire__nom {
  opacity: 0.28;
}

/* Les quatre listes occupent la même case de la deuxième colonne : elles se
   superposent sans que rien ne bouge de place au changement. */
.territoire.est-replie .territoire__communes {
  position: absolute;
  top: clamp(1rem, 2.5vh, 1.6rem);
  top: clamp(1rem, 2.5svh, 1.6rem);
  right: 0;
  width: 46%;
  margin-top: 0;
  grid-template-columns: 1fr;
  opacity: 0;
  visibility: hidden;
  transition:
    opacity calc(var(--d-state) * 0.75) var(--ease-sortie),
    visibility calc(var(--d-state) * 0.75) var(--ease-sortie);
}

.territoire.est-replie .territoire__dep.est-actif .territoire__communes {
  opacity: 1;
  visibility: visible;
  transition:
    opacity var(--d-state) var(--ease-expressive),
    visibility var(--d-state) var(--ease-expressive);
}

/* Quand GSAP est là, c'est lui qui pilote l'opacité, en `autoAlpha` et avec
   `easeReverse`. Les transitions ci-dessus sont le repli sans GSAP ; les
   laisser actives ferait transitionner chaque valeur écrite par le tween. */
.territoire.est-gsap .territoire__communes,
.territoire.est-gsap .territoire__nom {
  transition: none;
}

/* Le nom devient un vrai bouton quand le JS replie la section : sans lui, le
   clavier n'aurait aucun moyen de changer de liste. Le bouton n'existe que
   dans l'état replié — dans l'état déplié les quatre listes sont déjà là et
   un bouton qui ne commande rien serait un piège de plus à tabuler.

   Il ne porte ni couleur ni fond : le dégradé reste sur le <h3>, et
   `background-clip: text` découpe le texte de ses descendants tant qu'ils
   n'en peignent pas un autre. */
.territoire__bouton {
  display: flex;
  align-items: flex-start;
  gap: 0.18em;
  width: 100%;
  border: 0;
  padding: 0;
  margin: 0;
  background: none;
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
  text-align: left;
  text-transform: inherit;
  cursor: pointer;
}

.territoire__bouton:focus-visible {
  outline: 2px solid var(--or);
  outline-offset: 6px;
  border-radius: 2px;
}

.territoire__france {
  margin-top: clamp(2.5rem, 7vh, 4.5rem);
  margin-top: clamp(2.5rem, 7svh, 4.5rem);
  font-size: var(--t-l);
  font-family: var(--display);
  letter-spacing: var(--tr-l);
  text-transform: none;
  line-height: 1.06;
  max-width: 18ch;
}

.odo--rayon {
  margin-top: clamp(2rem, 5vh, 3.5rem);
  margin-top: clamp(2rem, 5svh, 3.5rem);
  max-width: 22rem;
}

@media (max-width: 860px) {
  .territoire__nom {
    font-size: var(--t-l);
  }
}

.territoire__photo {
  margin-top: clamp(2.5rem, 7vh, 4.5rem);
  margin-top: clamp(2.5rem, 7svh, 4.5rem);
  overflow: hidden;
  aspect-ratio: 16 / 9;
}

.territoire__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(0.7) brightness(0.86) contrast(1.05);
}

/* Le bandeau et son contrôle de pause. Le bouton est posé en absolu au-dessus
   du bandeau, à droite : il ne doit pas entrer dans la piste, qui défile. */
.bandeau {
  position: relative;
  margin-top: clamp(3rem, 9vh, 6rem);
  margin-top: clamp(3rem, 9svh, 6rem);
}

.bandeau__pause {
  position: absolute;
  right: clamp(0.75rem, 2vw, 1.5rem);
  top: 50%;
  translate: 0 -50%;
  z-index: 2;
  /* 44 × 44 : bien au-delà des 24 × 24 de WCAG 2.5.8, et rien d'autre ne
     s'approche à moins de 24 px de son centre. */
  width: 44px;
  height: 44px;
  display: grid;
  place-content: center;
  border: 1px solid var(--trait);
  border-radius: 50%;
  background: var(--voile-fort);
  color: var(--or-lien);
  cursor: pointer;
  padding: 0;
  transition:
    border-color var(--d-micro) var(--ease-productive),
    color var(--d-micro) var(--ease-productive);
}

.bandeau__pause:hover,
.bandeau__pause:focus-visible {
  border-color: var(--or);
  color: var(--creme);
}

/* Le même bouton porte les deux états : deux barres, ou un triangle. */
.bandeau__pause-i--lecture {
  display: none;
}

.bandeau__pause[aria-pressed='true'] rect.bandeau__pause-i {
  display: none;
}

.bandeau__pause[aria-pressed='true'] .bandeau__pause-i--lecture {
  display: block;
}

.marquee {
  overflow: hidden;
  border-block: 1px solid var(--trait);
  padding-block: clamp(0.9rem, 2.4vh, 1.5rem);
  padding-block: clamp(0.9rem, 2.4svh, 1.5rem);
}

.marquee__piste {
  display: flex;
  width: max-content;
  will-change: transform; /* sur la piste uniquement, jamais sur les enfants */
}

.marquee__lot {
  display: flex;
  align-items: center;
  gap: 0;
  white-space: nowrap;
}

.marquee__lot i {
  font-family: var(--display);
  font-style: normal;
  font-size: clamp(1.35rem, 3.4vw, 2.6rem);
  letter-spacing: var(--tr-l);
  text-transform: none;
  color: var(--creme);
  padding-inline: 0.5em;
}

.marquee__lot b {
  font-weight: 400;
  color: var(--or);
  font-size: clamp(1.35rem, 3.4vw, 2.6rem);
}

/* =========================================================================
   LE RÉSEAU

   Deux blocs, un par partenaire. Chaque bloc est un <a> entier : une seule
   cible, large, et pas de « voir le site » qui doublerait l'arrêt de
   tabulation vers la même URL.

   La grille est en `auto-fit` : elle accepte un troisième et un quatrième
   partenaire sans une ligne de plus.
   ========================================================================= */

.reseau__intro {
  font-size: var(--t-s);
  color: var(--creme);
  opacity: 0.88;
  margin-bottom: clamp(2rem, 5vh, 3.5rem);
  margin-bottom: clamp(2rem, 5svh, 3.5rem);
}

.reseau {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(22rem, 100%), 1fr));
  gap: clamp(1.5rem, 4vw, 3rem);
}

.partenaire {
  display: grid;
  gap: clamp(0.9rem, 2.2vh, 1.4rem);
  gap: clamp(0.9rem, 2.2svh, 1.4rem);
  align-content: start;
  height: 100%;
  padding: clamp(1.5rem, 3.5vh, 2.2rem) clamp(1.2rem, 3vw, 2rem);
  padding: clamp(1.5rem, 3.5svh, 2.2rem) clamp(1.2rem, 3vw, 2rem);
  border: 1px solid var(--trait);
  color: var(--creme);
  transition:
    border-color var(--d-micro) var(--ease-productive),
    background-color var(--d-micro) var(--ease-productive);
}

.partenaire:hover,
.partenaire:focus-visible {
  border-color: var(--trait-fort);
  background: rgba(200, 169, 107, 0.04);
}

.partenaire__logo {
  display: flex;
  align-items: center;
  height: 64px;
}

/* Niveaux de gris qui reviennent en couleur au survol ET AU FOCUS — jamais
   au survol seul, sinon l'effet n'existe pas au clavier. */
.partenaire__logo img {
  max-height: 100%;
  width: auto;
  filter: grayscale(1) brightness(1.6) contrast(0.9);
  opacity: 0.75;
  transition:
    filter var(--d-state) var(--ease-productive),
    opacity var(--d-state) var(--ease-productive);
}

.partenaire:hover .partenaire__logo img,
.partenaire:focus-visible .partenaire__logo img {
  filter: none;
  opacity: 1;
}

.partenaire__nom {
  font-family: var(--display);
  font-size: var(--t-l);
  letter-spacing: var(--tr-l);
  line-height: 1.05;
  transition: color var(--d-micro) var(--ease-productive);
}

.partenaire:hover .partenaire__nom,
.partenaire:focus-visible .partenaire__nom {
  color: var(--or-lien);
}

.partenaire__metier {
  color: var(--gris);
  letter-spacing: 0.14em;
}

.partenaire__lien {
  font-size: var(--t-s);
  color: var(--creme);
  opacity: 0.82;
  line-height: 1.5;
}

@media (prefers-reduced-motion: reduce) {
  .partenaire__logo img {
    transition: none;
  }
}

/* =========================================================================
   LA FAQ

   <details> / <summary> natifs. `name="faq"` en fait un accordéon exclusif :
   c'est le navigateur qui referme la question précédente, sans une ligne de
   JavaScript.

   L'ANIMATION N'EST PAS UNE ANIMATION DE HAUTEUR. Le §5 du lot demandait
   `::details-content` avec `transition-behavior: allow-discrete`, ce qui
   suppose d'animer `block-size` — donc la hauteur, ce que la charte du projet
   interdit depuis le gel de production. On garde `::details-content` et
   `allow-discrete`, mais on anime l'opacité et une translation de 6 px : la
   boîte s'ouvre d'un coup comme le fait `<details>` nativement, et la réponse
   se pose par-dessus. Sans support du pseudo-élément, la règle est ignorée et
   la réponse s'affiche normalement — le repli est gratuit.
   ========================================================================= */

.faq__item {
  border-top: 1px solid var(--trait);
}

.faq__item:last-child {
  border-bottom: 1px solid var(--trait);
}

.faq__q {
  display: grid;
  grid-template-columns: 3.5rem minmax(0, 1fr) auto;
  align-items: baseline;
  gap: clamp(0.6rem, 2vw, 2rem);
  /* 44 px de haut au minimum, largement au-delà des 24 de WCAG 2.5.8. */
  padding-block: clamp(1.1rem, 2.8vh, 1.7rem);
  padding-block: clamp(1.1rem, 2.8svh, 1.7rem);
  cursor: pointer;
  list-style: none;
  transition: color var(--d-micro) var(--ease-productive);
}

/* Le triangle par défaut de Safari et de Chrome. */
.faq__q::-webkit-details-marker,
.faq__q::marker {
  display: none;
  content: '';
}

.faq__no {
  color: var(--or-lien);
  letter-spacing: 0.1em;
}

.faq__mot {
  font-family: var(--display);
  font-size: var(--t-l);
  letter-spacing: var(--tr-l);
  line-height: 1.1;
  color: var(--creme);
  transition: color var(--d-micro) var(--ease-productive);
}

.faq__q:hover .faq__mot,
.faq__item:has(.faq__q:focus-visible) .faq__mot {
  color: var(--or-lien);
}

.faq__chevron {
  align-self: center;
  flex: none;
  color: var(--or);
  transition: transform var(--d-state) var(--ease-productive);
}

.faq__item[open] .faq__chevron {
  transform: rotate(180deg);
}

.faq__r {
  grid-column: 2;
  padding: 0 0 clamp(1.2rem, 3vh, 1.9rem) calc(3.5rem + clamp(0.6rem, 2vw, 2rem));
  padding: 0 0 clamp(1.2rem, 3svh, 1.9rem) calc(3.5rem + clamp(0.6rem, 2vw, 2rem));
}

.faq__r p {
  font-size: var(--t-s);
  color: var(--creme);
  opacity: 0.88;
  max-width: 68ch;
}

.faq__item::details-content {
  opacity: 0;
  transform: translateY(-6px);
  transition:
    opacity var(--d-state) var(--ease-productive),
    transform var(--d-state) var(--ease-productive),
    content-visibility var(--d-state) allow-discrete;
}

.faq__item[open]::details-content {
  opacity: 1;
  transform: none;
}

@media (max-width: 860px) {
  .faq__q {
    grid-template-columns: 2.5rem minmax(0, 1fr) auto;
  }
  .faq__r {
    padding-left: calc(2.5rem + 0.6rem);
  }
}

/* =========================================================================
   APPEL
   ========================================================================= */

.appel {
  display: grid;
  justify-items: center;
  text-align: center;
  gap: clamp(1.6rem, 4vh, 2.6rem);
  gap: clamp(1.6rem, 4svh, 2.6rem);
}

.appel__titre {
  font-size: var(--t-xl);
  letter-spacing: var(--tr-xl);
  line-height: 1.02;
}

.bouton {
  display: inline-flex;
  align-items: center;
  gap: 0.8em;
  padding: 1rem 1.9rem;
  border-radius: 999px;
  border: 1px solid var(--or);
  color: var(--or-lien);
  font-size: var(--t-s);
  transition:
    background-color var(--d-micro) var(--ease-productive),
    color var(--d-micro) var(--ease-productive);
}

.bouton svg {
  transition: transform var(--d-micro) var(--ease-productive);
}

.bouton:hover,
.bouton:focus-visible {
  background: var(--or);
  color: var(--fond);
}

.bouton:hover svg {
  transform: translateX(4px);
}

.appel__tel {
  color: var(--gris);
  text-transform: none;
  letter-spacing: 0.1em;
}

/* =========================================================================
   LA BARRE D'ACTION PERSISTANTE

   Deux formes pour un seul composant :
   — sous 768 px, une barre pleine largeur collée en bas, deux boutons à parts
     égales, parce que le pouce y arrive et que c'est là qu'on la cherche ;
   — au-dessus, un bloc flottant en bas à droite. Une barre pleine largeur sur
     un écran de 1 440 px ferait lourd et mangerait le pied de page.

   Animée en `transform` et `opacity` uniquement, jamais en `height` ni en
   `bottom`. Fond opaque, jamais de `backdrop-filter` : sur une surface fixe
   au-dessus d'une page qui défile, il force une recomposition par image.
   ========================================================================= */

.barre {
  position: fixed;
  z-index: 85;
  display: flex;
  gap: 0.5rem;
  /* Sortie : 0,75 × l'entrée, sur une courbe qui accélère. */
  opacity: 0;
  visibility: hidden;
  transform: translate3d(0, 12px, 0);
  transition:
    opacity calc(var(--d-state) * 0.75) var(--ease-sortie),
    transform calc(var(--d-state) * 0.75) var(--ease-sortie),
    visibility calc(var(--d-state) * 0.75) var(--ease-sortie);
}

.barre.est-visible {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition:
    opacity var(--d-panel) var(--ease-expressive),
    transform var(--d-panel) var(--ease-expressive),
    visibility var(--d-panel) var(--ease-expressive);
}

/* --- Les deux boutons --------------------------------------------------- */

.barre__action {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  /* 48 px au minimum : bien au-delà des 24 × 24 du critère 2.5.8. */
  min-height: 48px;
  padding: 0.75rem 1.15rem;
  border-radius: 999px;
  border: 1px solid var(--or);
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
  /* Le numéro doit rester d'aplomb quand le libellé change. */
  font-variant-numeric: tabular-nums;
  transition:
    background-color var(--d-micro) var(--ease-productive),
    color var(--d-micro) var(--ease-productive);
}

.barre__action svg {
  flex: none;
}

/* Contour or sur fond sombre : l'action secondaire. */
.barre__action--appel {
  background: var(--voile-fort);
  color: var(--or-lien);
}

.barre__action--appel:hover,
.barre__action--appel:focus-visible {
  background: var(--or);
  color: var(--fond);
}

/* Or plein : l'action principale. */
.barre__action--devis {
  background: var(--or);
  color: var(--fond);
}

.barre__action--devis:hover,
.barre__action--devis:focus-visible {
  background: var(--or-lien);
}

/* --- Mobile : barre pleine largeur, deux parts égales -------------------- */

@media (max-width: 767px) {
  .barre {
    left: 0;
    right: 0;
    bottom: 0;
    gap: 0;
    padding: 0.6rem 0.6rem;
    /* ZONE DE SÉCURITÉ iOS. Sans ceci, la barre passe sous l'encoche et sous
       la barre de gestes. `viewport-fit=cover` est posé dans le <head> : sans
       lui, les variables `env()` valent zéro et la règle ne sert à rien. */
    padding-bottom: max(0.6rem, env(safe-area-inset-bottom));
    background: var(--voile-fort);
    border-top: 1px solid var(--trait);
  }

  .barre__action {
    flex: 1 1 0;
    min-width: 0;
    margin: 0 0.25rem;
    font-size: calc(var(--t-mono) * 0.95);
    letter-spacing: 0.1em;
    padding-inline: 0.6rem;
  }
}

/* --- Ordinateur : bloc flottant en bas à droite -------------------------- */

@media (min-width: 768px) {
  .barre {
    right: clamp(1rem, 2.5vw, 2rem);
    bottom: clamp(1rem, 2.5vw, 2rem);
    bottom: max(clamp(1rem, 2.5svw, 2rem), env(safe-area-inset-bottom));
    flex-direction: column;
    align-items: stretch;
  }

  /* Le badge circulaire occupait ce coin et proposait déjà « demander un
     devis ». La barre le fait mieux et le dit en toutes lettres : les deux
     ensemble feraient deux appels à l'action superposés dans le même angle.
     Le badge s'efface donc dès que la barre est armée — une seule ligne à
     retirer si le badge doit revenir. */
  html:has(.barre.est-visible) .badge {
    opacity: 0;
    visibility: hidden;
  }
}

@media (prefers-reduced-motion: reduce) {
  /* Fondu simple, sans translation. */
  .barre,
  .barre.est-visible {
    transform: none;
    transition:
      opacity 200ms linear,
      visibility 200ms linear;
  }
}

/* =========================================================================
   PIED DE PAGE
   ========================================================================= */

.pied {
  padding-block: clamp(4rem, 10vh, 7rem) clamp(1.5rem, 4vh, 2.5rem);
  padding-block: clamp(4rem, 10svh, 7rem) clamp(1.5rem, 4svh, 2.5rem);
  /* LA RÉSERVE POUR LA BARRE D'ACTION. Elle vient APRÈS les deux
     `padding-block` ci-dessus, sinon ils l'écrasent — c'est exactement
     l'erreur que la première version de cette règle contenait, et le pied
     passait sous la barre. `--barre-h` est mesurée et posée par
     js/global.js ; elle vaut 0 tant que la barre n'est pas visible. */
  padding-bottom: calc(clamp(1.5rem, 4svh, 2.5rem) + var(--barre-h, 0px));
  background: var(--voile-fort);
  border-top: 1px solid var(--trait);
}

.pied__grille {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr));
  gap: clamp(1.8rem, 4vw, 3.5rem);
}

.pied__grille .mono {
  color: var(--or-lien);
  margin-bottom: 0.9rem;
}

.pied__ligne {
  font-size: var(--t-s);
  line-height: 1.9;
  color: var(--creme);
}

.reseaux {
  display: flex;
  gap: 1rem;
  color: var(--or-lien);
}

.reseaux a {
  display: grid;
  place-content: center;
  width: 40px;
  height: 40px;
  border: 1px solid var(--trait);
  border-radius: 50%;
  transition:
    border-color var(--d-micro) var(--ease-productive),
    color var(--d-micro) var(--ease-productive);
}

.reseaux a:hover,
.reseaux a:focus-visible {
  border-color: var(--or);
  color: var(--creme);
}

/* LES SIGNAUX DE VIE. En mono discret, sur une seule ligne qui se replie.
   Les chiffres sont tabulaires : sans quoi l'heure ferait bouger la ligne à
   chaque minute, et une ligne qui gigote dans un pied de page se remarque. */
.pied__vie {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 0.7em;
  margin-top: clamp(2.5rem, 6vh, 4rem);
  margin-top: clamp(2.5rem, 6svh, 4rem);
  max-width: none;
  letter-spacing: 0.16em;
  color: var(--gris);
  font-variant-numeric: tabular-nums;
}

.pied__vie-heure {
  color: var(--creme);
}

.pied__vie-etat {
  font-weight: 400;
  color: var(--or-lien);
}

/* La mention du mode dégradé. Discrète, mais présente : un repli silencieux
   est un repli qu'on ne débogue jamais. Posée par js/global.js, et seulement
   quand le mode est réellement actif. */
.pied__degrade {
  margin-top: 0.6rem;
  max-width: none;
  font-size: calc(var(--t-mono) * 0.92);
  letter-spacing: 0.14em;
  text-transform: none;
  color: var(--gris);
  opacity: 0.7;
}

/* ALTIPUR en outline géant, qui se remplit au scroll. */
.pied__geant {
  margin-block: clamp(3rem, 9vh, 6rem) clamp(1.5rem, 4vh, 2.5rem);
  margin-block: clamp(3rem, 9svh, 6rem) clamp(1.5rem, 4svh, 2.5rem);
  font-family: var(--logotype);
  font-size: clamp(3.2rem, 17.5vw, 15rem);
  line-height: 0.9;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  text-align: center;
  color: transparent;
  -webkit-text-stroke: 1px rgba(200, 169, 107, 0.5);
  background-image: var(--or-degrade);
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 0%;
  -webkit-background-clip: text;
  background-clip: text;
}

.pied__geant[data-reveal] {
  opacity: 1;
  transform: none;
  transition: background-size var(--d-reveal) var(--ease-expressive);
}

.pied__geant[data-reveal].est-vu {
  background-size: 100% 100%;
}

.pied__credit {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.8rem;
  padding-top: 1.5rem;
  border-top: 1px solid rgba(200, 169, 107, 0.12);
  letter-spacing: 0.14em;
  /* Le reset pose `max-width: 62ch` sur tous les <p>. Ici il rognait le
     filet à 450 px et faisait passer les deux mentions l'une sur l'autre. */
  max-width: none;
}

/* Les deux éléments en fixed des coins bas — l'indicateur à gauche, le badge
   à droite — venaient se poser sur la ligne de crédits. Ils s'effacent dès
   que le pied entre à l'écran : l'un n'a plus de section à annoncer, et
   l'autre est redondant avec le téléphone et l'adresse juste au-dessus. */
.pied-en-vue .indicateur,
.pied-en-vue .badge {
  opacity: 0;
  visibility: hidden;
}
