/* ==========================================================================
   Window Portal Network — feuille de style du site public

   Les couleurs, polices et espacements viennent tous de tokens.css.
   Aucune valeur de marque n'est écrite en dur ici.

   RÈGLE DE KARL : les effets liés au défilement suivent le geste 1:1.
   Aucun `scroll-behavior: smooth` imposé, aucune inertie. Les transitions
   ci-dessous ne concernent que le survol et les apparitions — jamais la
   position de la page.
   ========================================================================== */

* { box-sizing: border-box; }

/* `overscroll-behavior-y: none` neutralise le rebond élastique de macOS.
   Sans lui, le geste qui pilote le logo en haut de page ferait aussi rebondir
   la page, et les deux effets se marcheraient dessus. */
/* `overflow-x: hidden` est proscrit ici : il force `overflow-y: auto`, ce qui
   fait de la racine un conteneur de défilement et neutralise TOUS les
   `position: sticky` de la page — la pile des trois onglets s'effondre.
   Le débordement horizontal est contenu autrement, bloc par bloc. */
html { overscroll-behavior-y: none; }

body {
  margin: 0;
  max-width: 100vw;
  background: var(--wpn-fond) url("../../images/texture-papier.jpg") repeat;
  background-size: 600px auto;
  background-blend-mode: multiply;
  color: var(--wpn-ancre);
  font-family: var(--police-texte);
  font-size: 17px;
  line-height: var(--interligne-normal);
  -webkit-font-smoothing: antialiased;
  /* Pas d'`overflow-x` ici non plus : même effet que sur `html`, il ferait du
     corps un conteneur de défilement et casserait la pile des onglets.
     Chaque bloc contient son propre débordement. */
}

.enveloppe {
  width: 100%;
  max-width: var(--largeur-contenu);
  margin: 0 auto;
  padding: 0 var(--espace-6);
}

a { color: inherit; }

/* La trame de points interactive. Elle couvrait autrefois toute la page ;
   elle est maintenant confinée au bloc de contact final, où sa réaction au
   curseur devient une invitation à jouer juste avant l'appel à écrire. */
#fond {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  z-index: 0; pointer-events: none;
}
#talk { position: relative; overflow: hidden; }
#talk > .enveloppe { position: relative; z-index: 1; }

/* Le contenu passe au-dessus des canvas de fond. Deux exclusions :
   le banc d'essai, qui garde son `position: fixed` pour recouvrir la page,
   et les trois blocs empilés, dont le `position: sticky` serait écrasé par
   cette règle — plus spécifique que `.bloc` malgré son apparence. */
body > *:not(.banc):not(.bloc):not(.champ-losanges) { position: relative; z-index: 1; }

/* ==========================================================================
   Navigation
   ========================================================================== */

.nav {
  position: sticky; top: 0; z-index: 50;
  background: rgba(245, 245, 244, 0.82);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid rgba(27, 31, 42, 0.07);
}
.nav-contenu {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--espace-6);
  padding: var(--espace-4) var(--espace-6);
  max-width: var(--largeur-contenu); margin: 0 auto;
}
.nav-marque { display: flex; align-items: center; gap: var(--espace-3); text-decoration: none; }
.nav-marque svg { width: 34px; height: auto; display: block; transition: transform .5s cubic-bezier(.2,.8,.2,1); }
.nav-marque:hover svg { transform: rotate(90deg); }
.nav-marque span {
  font-weight: var(--graisse-noire); font-size: 11px; line-height: 1.1;
  letter-spacing: 0.04em; text-transform: uppercase;
}

.nav-liens { display: flex; align-items: center; gap: var(--espace-6); }
.nav-liens a {
  position: relative;
  text-decoration: none; font-size: var(--texte-sm);
  font-weight: var(--graisse-moyenne); color: var(--wpn-neutre-500);
  padding: 4px 0;
}
/* Le soulignement se déploie depuis la gauche. */
.nav-liens a:not(.nav-bouton)::after {
  content: ""; position: absolute; left: 0; bottom: 0;
  width: 100%; height: 2px; background: var(--wpn-ancre);
  transform: scaleX(0); transform-origin: left;
  transition: transform .28s cubic-bezier(.2,.8,.2,1);
}
.nav-liens a:not(.nav-bouton):hover { color: var(--wpn-ancre); }
.nav-liens a:not(.nav-bouton):hover::after { transform: scaleX(1); }

.nav-bouton {
  background: var(--wpn-ancre); color: #fff !important;
  padding: 10px 18px; border-radius: var(--rayon-md);
  font-size: var(--texte-sm); font-weight: var(--graisse-moyenne);
  text-decoration: none; white-space: nowrap;
  transition: background .2s ease;
}
.nav-bouton:hover { background: var(--wpn-bleu-700); }
@media (max-width: 860px) { .nav-liens a:not(.nav-bouton) { display: none; } }

/* ==========================================================================
   Le prolongement du header
   --------------------------------------------------------------------------
   Ce bloc n'est pas une section à part : c'est la suite du header. Aucun
   fond propre, aucune bordure, aucune ombre — le fond de la page continue
   simplement, et son propre champ de losanges prend le relais de celui du
   header. Rien ne doit signaler qu'on change de section.
   ========================================================================== */

.suite {
  position: relative;
  /* Aucun padding : tout vide sous le bloc figé retarderait d'autant
     l'arrivée du bloc Window, qui part du bas de la section.
     Pas d'`overflow` non plus : `clip` comme `hidden` désactiverait le
     `position: sticky` de l'enfant figé. */
  padding: 0;
  background: transparent;
  /* La hauteur totale donne la COURSE du figement : c'est la différence
     entre cette hauteur et celle du bloc figé (88vh).

     Cette course doit dépasser UNE HAUTEUR D'ÉCRAN, sinon le figement lâche
     avant que le bloc Window ait fini de monter, et la fin du mouvement se
     transforme en défilement ordinaire — ce que Karl ne veut pas : « je ne
     veux pas que ça devienne un scroll, je veux vraiment que l'onglet
     embarque all the way. »

     100vh (bloc figé) + 100vh (la montée complète de Window) = 200vh.

     Le bloc Window remonte d'autant par sa marge négative (voir `.bloc-window`)
     pour partir du bas de l'ÉCRAN et non du bas de la section : sans cela il
     serait deux écrans plus bas et sa montée déborderait de la course. */
  min-height: 200vh;
}

/* Le contenu du prolongement se fige à l'écran pendant que Window monte
   par-dessus. C'est ce qui produit l'effet demandé : le carrousel ne monte
   plus, c'est l'onglet bleu qui vient le recouvrir.

   Sans cela, le carrousel défilait vers le haut et Window arrivait par le
   bas — on descendait VERS lui au lieu qu'il soit tiré par-dessus. */
.suite-fige {
  position: sticky;
  top: 0;
  /* La hauteur reste sous celle de l'écran : un élément collant aussi haut
     que la fenêtre n'a aucune marge pour se figer visiblement. */
  /* Le bloc figé occupe une hauteur d'écran. Le reste de la section — le
     surplus de `min-height` — est la course pendant laquelle il reste collé
     et le bloc Window monte par-dessus. */
  height: 100vh;
  box-sizing: border-box;
  display: flex; flex-direction: column; justify-content: center;
  padding: var(--espace-4) 0;
}

.suite-contenu { max-width: 760px; position: relative; z-index: 2; }

.suite-titre {
  font-family: var(--police-titre);
  font-weight: var(--graisse-noire);
  font-size: clamp(1.9rem, 4vw, 3rem);
  line-height: 1.02;
  letter-spacing: -0.035em;
  margin: 0 0 var(--espace-4);
  color: var(--wpn-ancre);
}

.suite-chapo {
  font-size: clamp(1rem, 1.7vw, 1.15rem);
  color: var(--wpn-neutre-500);
  max-width: 56ch;
  margin: 0 0 var(--espace-10);
}

/* --- Le carrousel ---------------------------------------------------------
   Un seul élément à la fois, qui prend toute la place. Il reste en position
   un moment, puis cède la place au suivant. Aucun cadre, aucune boîte : le
   visuel flotte sur le fond, et seule sa propre ombre le détache.

   Les éléments sont superposés dans la même case de grille : celui qui est
   actif est visible, les autres attendent. C'est ce qui permet un fondu sans
   que la hauteur du bloc ne saute. */

.carrousel { position: relative; z-index: 2; }

.carrousel-scene {
  display: grid;
  place-items: center;
  min-height: clamp(300px, 36vw, 480px);
}

.carrousel-item {
  grid-area: 1 / 1;
  margin: 0;
  display: flex; flex-direction: column; align-items: center;
  gap: var(--espace-6);
  opacity: 0;
  transform: translateY(14px) scale(.985);
  transition: opacity .55s ease, transform .55s cubic-bezier(.16,.84,.28,1);
  pointer-events: none;
}
.carrousel-item.est-actif {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

.carrousel-item img {
  display: block;
  width: auto;
  max-width: min(100%, 880px);
  max-height: clamp(240px, 30vw, 400px);
  height: auto;
}

.carrousel-item figcaption {
  text-align: center;
  display: flex; flex-direction: column; gap: 4px;
}
.carrousel-item figcaption strong {
  font-family: var(--police-titre);
  font-size: clamp(1.1rem, 2vw, 1.4rem);
  font-weight: var(--graisse-noire);
  letter-spacing: -0.02em;
  color: var(--wpn-ancre);
}
.carrousel-item figcaption span {
  font-size: var(--texte-sm);
  color: var(--wpn-neutre-500);
}

/* --- Les commandes : flèches et points ---------------------------------- */

.carrousel-commandes {
  display: flex; align-items: center; justify-content: center;
  gap: var(--espace-5);
  margin-top: var(--espace-8);
}

.carrousel-fleche {
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border: 1px solid rgba(27,31,42,.16);
  border-radius: 50%;
  background: transparent;
  color: var(--wpn-ancre);
  cursor: pointer;
  transition: background .2s ease, border-color .2s ease, transform .2s ease;
}
.carrousel-fleche svg { width: 20px; height: 20px; }
.carrousel-fleche:hover {
  background: var(--wpn-ancre); color: #fff;
  border-color: var(--wpn-ancre);
}
.carrousel-fleche:active { transform: scale(.94); }

.carrousel-points { display: flex; gap: 10px; }

.carrousel-point {
  width: 9px; height: 9px; padding: 0;
  border: 0; border-radius: 2px;
  background: rgba(27,31,42,.2);
  transform: rotate(45deg);
  cursor: pointer;
  transition: background .25s ease, width .25s ease;
}
.carrousel-point[aria-current="true"] { background: var(--wpn-bleu-700); }
.carrousel-point:hover { background: rgba(27,31,42,.45); }

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

/* ==========================================================================
   Héros
   ========================================================================== */

.heros {
  /* Le header défile normalement avec la page. Il a été rendu collant un
     temps, à tort : Karl veut que « tout le bloc un soit scrollable ». Ce
     sont les trois onglets qui montent par-dessus, pas le header qui reste. */
  position: relative;
  min-height: 100vh;
  display: flex; flex-direction: column; justify-content: center;
  /* Le contenu est poussé vers le bas : cela laisse plus de course au-dessus
     de lui avant que le header ne sorte du champ, donc plus de temps pour
     voir le logo s'assembler. */
  padding: clamp(90px, 15vh, 190px) 0 clamp(34px, 5vh, 64px);
  /* Jamais `overflow: hidden` ici : cela rognerait les losanges écartés du
     logo pendant la convergence, et désactiverait `position: sticky`. */
  overflow: clip visible;
}

@media (max-width: 620px) {
  .heros-marque { font-size: clamp(2.2rem, 11vw, 3.2rem); }
  /* Sur petit écran, le lockup passe en colonne : le nom et le logo ne
     tiennent pas côte à côte sans devenir illisibles. */
  .heros-lockup { flex-direction: column; align-items: flex-start; }
  .losange-volant { height: auto; width: min(300px, 72vw); margin: 0 0 0 -8%; }
  .btn { padding: 14px 22px; font-size: var(--texte-sm); }
  .bloc, .section { border-radius: 22px 22px 0 0; }
  .bloc-mot { font-size: 5.5rem; }
}

/* --- Le logo qui se construit au défilement -------------------------------
   Le logo est collé à droite du nom : sa hauteur se cale sur celle du bloc de
   texte, pas sur une largeur arbitraire. Le viewBox porte du vide autour du
   dessin (300 × 200 pour un logo de 200 × 140), d'où les marges négatives qui
   rattrapent ce vide et rapprochent vraiment les deux. */

.losange-volant {
  display: block;
  /* Le logo doit faire la hauteur des trois lignes du nom : celui-ci fait
     3 lignes à line-height 0.78, soit 2,34 fois sa taille de police. Le
     viewBox (300 × 200) porte du vide autour du dessin, qu'il faut compenser
     — d'où le facteur 1,45. */
  height: calc(2.34em * 1.36);
  font-size: clamp(2.4rem, 7.2vw, 5.6rem);   /* la même échelle que le nom */
  width: auto;
  flex: none;
  margin: 0 -4% 0 -6%;
  overflow: visible;
  pointer-events: none;
  will-change: transform;
}

/* Les losanges écartés sortent du cadre du logo pendant la convergence :
   le SVG ne doit donc jamais rogner, et le header non plus. */
#lv-g-bleu, #lv-g-jaune, #lv-g-violet, #lv-coupe-rect {
  will-change: transform;
}

/* --- Le champ de losanges : le fond du header ---------------------------
   Des losanges jaunes et bleus de tailles variées qui dérivent en
   parallaxe. Aucun violet n'y est peint : il naît des croisements, calculé
   par comptage de couches (voir losanges.js). */

.champ-losanges {
  /* Le canvas couvre la zone d'accueil entière — le header ET son
     prolongement — en un seul morceau : sa hauteur est posée en JavaScript.
     C'est ce qui garantit un décor continu, sans répétition ni coupure.

     Il est enfant du header et en position absolue : posé en `fixed` comme
     enfant direct du corps, il se peignait au-dessus de tout le contenu, qui
     devenait invisible. */
  position: absolute;
  top: 0; left: 0;
  width: 100%;
  z-index: 0; pointer-events: none;
}


.heros-contenu { position: relative; z-index: 2; max-width: 940px; }

/* --- Le bloc de marque ---------------------------------------------------
   Le nom et le logo forment un seul ensemble, aligné à gauche. Le logo est
   collé au nom : c'est une signature, pas un titre avec une illustration
   posée à côté. */

.heros-lockup {
  display: flex;
  align-items: center;
  gap: 0;
  margin: 0 0 var(--espace-7);
  max-width: none;   /* le lockup déborde volontairement la colonne de texte */
}


.heros-etiquette {
  display: inline-flex; align-items: center; gap: var(--espace-3);
  font-size: var(--texte-xs); font-weight: var(--graisse-grasse);
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--wpn-neutre-500);
  margin: 0 0 var(--espace-4);
}
.heros-etiquette::before {
  content: ""; width: 10px; height: 10px;
  background: var(--wpn-jaune-400); border-radius: 2px;
  transform: rotate(45deg);
}

/* --- Le nom de la marque -------------------------------------------------
   Sous le logo, collé à gauche : c'est le titre de la page et la pièce
   maîtresse du header. Une ligne par mot, comme dans le lettrage du logo. */

.heros-marque {
  font-family: var(--police-titre);
  font-weight: var(--graisse-noire);
  /* Le nom est la pièce maîtresse du header : il prend toute la place que
     la ligne lui laisse une fois le logo posé à sa droite. */
  font-size: clamp(2.4rem, 7.2vw, 5.6rem);
  line-height: 0.78;
  letter-spacing: -0.055em;
  margin: 0;
  color: var(--wpn-ancre);
  flex: 0 1 auto;
  will-change: transform;
}
.heros-marque span { display: block; }

/* Les trois promesses « Your window / Your portal / Your network » ont été
   retirées du header le 25 août 2026 : Karl les réserve pour plus loin dans la
   page, et leur départ raccourcit un bloc qu'il jugeait trop long. Les règles
   ci-dessous restent parce qu'elles servent aux blocs de la page. */

@keyframes monter {
  from { opacity: 0; transform: translateY(105%); }
  to   { opacity: 1; transform: none; }
}

.mot { color: inherit; transition: color .5s ease; }
:root.ouvert .mot-window  { transition-delay: .55s; color: var(--wpn-bleu-700); }
:root.ouvert .mot-portal  { transition-delay: .70s; color: var(--wpn-violet-800); }
:root.ouvert .mot-network { transition-delay: .85s; color: var(--wpn-jaune-700); }

.heros-chapo {
  font-size: clamp(1rem, 1.7vw, 1.15rem);
  color: var(--wpn-neutre-500);
  /* Le résumé s'arrête avant la zone du logo, à droite. */
  max-width: min(58%, 50ch);
  margin: 0 0 var(--espace-6);
}
.heros-chapo strong { color: var(--wpn-ancre); font-weight: var(--graisse-moyenne); }

:root:not(.ouvert) .heros-etiquette,
:root:not(.ouvert) .heros-chapo,
:root:not(.ouvert) .heros-actions { opacity: 0; }
:root.ouvert .heros-etiquette { animation: paraitre .7s ease .05s both; }
:root.ouvert .heros-chapo     { animation: paraitre .7s ease .62s both; }
:root.ouvert .heros-actions   { animation: paraitre .7s ease .78s both; }

@keyframes paraitre {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

/* --- Le signal de défilement --- */

.heros-signal {
  position: absolute; left: 50%; bottom: 30px;
  transform: translateX(-50%);
  width: 1px; height: 54px;
  background: rgba(27,31,42,.14);
  overflow: hidden;
}
.heros-signal span {
  display: block; width: 100%; height: 40%;
  background: var(--wpn-ancre);
  animation: descendre 2.1s cubic-bezier(.6,0,.4,1) infinite;
}
@keyframes descendre {
  0%   { transform: translateY(-100%); }
  100% { transform: translateY(250%); }
}
:root:not(.sequence-finie) .heros-signal { opacity: 0; }
.heros-signal { transition: opacity .6s ease; }

/* ==========================================================================
   Les trois blocs
   ========================================================================== */

/* --- Les trois onglets qu'on tire ----------------------------------------
   Les blocs Window, Portal et Network ne défilent pas : ils se collent en
   haut de l'écran, et le suivant monte par-dessus. On sent qu'on tire un
   document après l'autre hors d'une pile.

   Chaque bloc refermé laisse dépasser une bande en haut — son onglet, qui
   reste cliquable pour y revenir. Les onglets se décalent donc les uns par
   rapport aux autres, comme des intercalaires. `--onglet` gouverne cette
   hauteur, et `--rang` le numéro du bloc dans la pile : c'est le produit des
   deux qui donne le décalage.

   Le mécanisme est du `position: sticky` pur, sans JavaScript : le
   défilement reste 1:1 avec le geste, conformément à la règle du projet. */

:root { --onglet: 62px; }

.bloc {
  position: sticky;
  /* Chaque bloc se colle en haut de l'écran, décalé des onglets de ceux qui
     le précèdent. Le premier arrive quand le carrousel a fini de défiler ;
     les suivants se tirent ensuite chacun leur tour. */
  top: calc(var(--rang) * var(--onglet));
  padding: clamp(58px, 7vw, 88px) 0 clamp(74px, 9vw, 110px);
  color: #fff;
  /* Le bloc doit être OPAQUE : il recouvre le canvas fixe du décor, qui
     couvre toute la fenêtre. Sans fond propre, on voyait le décor à travers
     et le contenu du bloc semblait avoir disparu. */
  isolation: isolate;
  /* Jamais `overflow: hidden` : cela désactiverait `position: sticky` et
     toute la pile s'effondrerait. Même piège qu'au header. */
  overflow: clip visible;
  border-radius: 34px 34px 0 0;
  /* L'ombre vers le haut donne l'épaisseur de la feuille. */
  box-shadow: 0 -22px 50px rgba(27,31,42,.22);
  /* Le dernier arrivé passe devant : c'est ce qui fait la pile. Les valeurs
     partent de 10 pour rester au-dessus du z-index 1 des sections qui
     suivent la pile — sans quoi elles recouvriraient les onglets et le
     premier deviendrait incliquable. */
  z-index: calc(var(--rang) + 10);
  min-height: 84vh;
}

/* Le premier bloc remonte d'une hauteur d'écran : il part ainsi du bas de la
   fenêtre au moment où le carrousel se fige, et sa montée tient entièrement
   dans la course du figement. Sans cela, la fin du mouvement se transformait
   en défilement ordinaire. */
.bloc-window  { --rang: 0; margin-top: -100vh; }

/* Le conteneur borne le `sticky` : au bas de la pile, les blocs se décollent
   et laissent passer la section suivante. */
.pile { position: relative; }

/* --- La pile verrouillée -------------------------------------------------
   Une fois les trois blocs tirés, la pile reste : remonter ne la défait plus.
   Les onglets restent visibles et cliquables, et c'est le clic qui déroule un
   bloc — un seul à la fois, comme un accordéon.

   Le `position: fixed` est indispensable ici : `sticky` suit forcément le
   défilement dans les deux sens, il ne peut pas « rester en place » quand on
   remonte. C'est le seul endroit du site où le JavaScript pilote la
   position — ailleurs tout est en `sticky` pur. */

.pile-verrouillee .bloc {
  position: fixed;
  left: 0; right: 0;
  /* `--pile-glissee` descend les trois blocs ENSEMBLE quand on remonte : ils
     restent solidaires au lieu de se dérouler un par un. La valeur est posée
     par pile.js, en fonction directe du défilement. */
  top: calc(var(--rang) * var(--onglet) + var(--pile-glissee, 0px));
  margin-top: 0;
  transition: height .5s cubic-bezier(.16,.84,.28,1);
}

/* Un bloc fermé se réduit à son onglet : il ne reste que la bande.
   `min-height` doit être neutralisé explicitement — la règle de base pose
   `min-height: 84vh`, qui l'emporterait sur la hauteur réduite. */
.pile-verrouillee .bloc.est-ferme {
  height: var(--onglet) !important;
  min-height: 0 !important;
  padding: 0 !important;
  overflow: hidden;
}
.pile-verrouillee .bloc.est-ferme > .enveloppe,
.pile-verrouillee .bloc.est-ferme > .bloc-mot {
  opacity: 0;
  pointer-events: none;
  transition: opacity .25s ease;
}

/* Le bloc ouvert s'ouvre JUSTE SOUS SON PROPRE ONGLET, et occupe la place
   qui reste. Les onglets des blocs qui le suivent se rangent sous lui : c'est
   pour cela que sa position se calcule sur son rang, et non sur un décalage
   fixe. Sans cela, un bloc ouvert apparaissait sous les onglets de blocs qui
   viennent après lui dans la pile — un ordre incompréhensible. */
.pile-verrouillee .bloc.est-ouvert {
  top: calc(var(--rang) * var(--onglet)) !important;
  height: calc(100vh - 2 * var(--onglet)) !important;
  min-height: 0 !important;
  overflow-y: auto;
  z-index: 20 !important;
}

/* Les onglets des blocs qui suivent l'ouvert se rangent sous lui. */
.pile-verrouillee .bloc.est-ferme {
  z-index: 21 !important;
}
.pile-verrouillee .bloc.est-ouvert ~ .bloc.est-ferme {
  top: auto !important;
  bottom: calc((2 - var(--rang)) * var(--onglet)) !important;
}

/* --- L'enroulement ------------------------------------------------------
   En continuant à descendre une fois la pile constituée, le bloc du dessus
   s'enroule vers le haut et dévoile ce qui est dessous : le bloc suivant de
   la pile, puis la section d'après.

   `--pile-enroulee` va de 0 (bloc entier) à 1 (bloc réduit à son onglet).
   La hauteur est la seule chose qui change — le contenu se découvre par le
   bas, comme un store qu'on remonte. */

/* Les TROIS blocs s'enroulent ensemble : la pile entière se referme en
   bandes, et ce qui est dessous se découvre. N'enrouler que le dernier
   laissait apparaître le contenu tronqué de celui d'avant. */
.pile-enroulement .bloc {
  height: calc(var(--onglet)
               + (1 - var(--pile-enroulee, 0)) * (100vh - 3 * var(--onglet))) !important;
  min-height: 0 !important;
  overflow: hidden;
}

/* Le contenu s'efface avant que la bande ne se referme, pour qu'il ne soit
   jamais rogné en plein texte. */
.pile-enroulement .bloc > .enveloppe,
.pile-enroulement .bloc > .bloc-mot {
  opacity: calc(1 - var(--pile-enroulee, 0) * 2.2);
}

/* Les onglets appellent le clic. */
.pile-verrouillee .bloc-onglet { cursor: pointer; }
.pile-verrouillee .bloc-onglet::after {
  content: "";
  margin-left: auto;
  width: 8px; height: 8px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform .3s ease;
}
.pile-verrouillee .bloc.est-ouvert .bloc-onglet::after {
  transform: rotate(-135deg) translate(-2px, -2px);
}
.bloc-portal  { --rang: 1; }
.bloc-network { --rang: 2; }

/* L'onglet lui-même : la bande cliquable qui dépasse en haut du bloc une
   fois celui-ci recouvert. Elle porte le nom du bloc, aligné à gauche
   comme le reste du site. */
.bloc-onglet {
  position: absolute; top: 0; left: 0; right: 0;
  height: var(--onglet);
  display: flex; align-items: center;
  padding: 0 clamp(20px, 5vw, 64px);
  font-size: var(--texte-xs);
  font-weight: var(--graisse-grasse);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255,255,255,.72);
  text-decoration: none;
  z-index: 3;
}
.bloc-onglet:hover { color: #fff; }
.bloc-onglet::before {
  content: ""; width: 9px; height: 9px; margin-right: var(--espace-3);
  background: currentColor; border-radius: 2px;
  transform: rotate(45deg);
}

/* Le contenu commence sous l'onglet, pour ne jamais passer dessous. */
.bloc > .enveloppe { padding-top: var(--onglet); }

@media (max-width: 620px) {
  /* Sur petit écran, trois onglets mangeraient la moitié de la hauteur : on
     les réduit, et les blocs redeviennent de simples sections empilées. */
  :root { --onglet: 44px; }
  .bloc { position: relative; top: auto; min-height: 0; margin-top: -34px; }
}
.bloc-window  { background: var(--wpn-bleu-700); }
.bloc-portal  { background: var(--wpn-violet-800); }
.bloc-network { background: var(--wpn-jaune-400); color: var(--wpn-ancre); }

/* Le grain d'encre sérigraphiée, sur les aplats. */
.bloc::after {
  content: "";
  position: absolute; inset: 0;
  background: url("../../images/grain-riso.jpg") repeat;
  background-size: 420px;
  mix-blend-mode: multiply;
  opacity: 0.10;
  pointer-events: none;
}
.bloc-network::after { opacity: 0.06; }

/* --- Le mot géant qui déborde --- */
.bloc-mot {
  position: absolute;
  right: 3%; bottom: 10px;
  font-family: var(--police-titre);
  font-weight: var(--graisse-noire);
  /* Le mot doit se lire en entier : il est posé sur le bord inférieur du
     bloc, pas coupé par lui. */
  font-size: clamp(3.4rem, 9.5vw, 8rem);
  line-height: .82; letter-spacing: -0.045em;
  color: #fff; opacity: .10;
  pointer-events: none; user-select: none;
  white-space: nowrap;
}
.bloc-network .bloc-mot { color: var(--wpn-ancre); opacity: .13; }

.bloc-grille {
  position: relative; z-index: 1;
  display: grid;
  grid-template-columns: 1fr minmax(230px, 340px);
  gap: clamp(32px, 5vw, 68px);
  align-items: center;
}
.bloc-network .bloc-grille { direction: rtl; }
.bloc-network .bloc-grille > * { direction: ltr; }
@media (max-width: 880px) {
  .bloc-grille { grid-template-columns: 1fr; }
  .bloc-network .bloc-grille { direction: ltr; }
}

.bloc-numero {
  display: flex; align-items: center; gap: var(--espace-3);
  font-family: var(--police-mono, monospace);
  font-size: var(--texte-xs); font-weight: var(--graisse-grasse);
  letter-spacing: 0.18em; text-transform: uppercase;
  opacity: .62; margin: 0 0 var(--espace-5);
}
.bloc-numero span {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px;
  border: 1.5px solid currentColor; border-radius: 5px;
  transform: rotate(45deg); font-size: 10px; letter-spacing: 0;
}
.bloc-numero span::before { content: attr(data-x); }

.bloc h2 {
  font-family: var(--police-titre);
  font-weight: var(--graisse-noire);
  font-size: clamp(2rem, 4.4vw, 3rem);
  line-height: 1.04; letter-spacing: -0.032em;
  margin: 0 0 var(--espace-5);
}
.bloc-chapo {
  font-size: clamp(1rem, 1.6vw, 1.14rem);
  margin: 0 0 var(--espace-6);
  max-width: 50ch; opacity: .9;
}
.bloc-liste { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--espace-3); }
.bloc-liste li {
  display: flex; gap: var(--espace-3); align-items: flex-start;
  font-size: var(--texte-sm); opacity: .88;
}
.bloc-liste li::before {
  content: ""; flex-shrink: 0;
  width: 9px; height: 9px; margin-top: 9px;
  background: currentColor; border-radius: 2px;
  transform: rotate(45deg); opacity: .7;
}

/* --- Le lien de bloc, avec remplissage au survol --- */
.bloc-lien {
  position: relative; overflow: hidden;
  display: inline-block; margin-top: var(--espace-6);
  padding: 12px 24px; border-radius: var(--rayon-md);
  color: #fff; text-decoration: none;
  font-weight: var(--graisse-moyenne); font-size: var(--texte-base);
  border: 1.5px solid rgba(255,255,255,.34);
}
.bloc-lien span { position: relative; z-index: 1; transition: color .3s ease; }
.bloc-lien::before {
  content: ""; position: absolute; inset: 0;
  background: #fff; transform: scaleX(0); transform-origin: left;
  transition: transform .38s cubic-bezier(.2,.8,.2,1);
}
.bloc-lien:hover::before { transform: scaleX(1); }
.bloc-window .bloc-lien:hover span { color: var(--wpn-bleu-700); }
.bloc-portal .bloc-lien:hover span { color: var(--wpn-violet-800); }
.bloc-network .bloc-lien {
  color: var(--wpn-ancre); border-color: rgba(27,31,42,.3);
}
.bloc-network .bloc-lien::before { background: var(--wpn-ancre); }
.bloc-network .bloc-lien:hover span { color: var(--wpn-jaune-400); }

/* --- Médias du bloc --- */

.bloc-media { display: flex; justify-content: center; align-items: center; }

.objet-image {
  display: block; width: min(270px, 62vw); height: auto;
  filter: brightness(1.22);
}
.bloc-network .objet-image { filter: brightness(1.08); }

.telephone {
  width: 100%; max-width: 246px;
  border-radius: 32px; padding: 9px;
  background: #111318;
  box-shadow: 0 30px 70px rgba(0,0,0,.32);
}
.telephone video {
  display: block; width: 100%; height: auto;
  border-radius: 27px; background: #000;
}

/* ==========================================================================
   Sections claires
   ========================================================================== */

.section {
  position: relative;
  padding: clamp(90px, 12vw, 150px) 0;
  margin-top: -34px;
  border-radius: 34px 34px 0 0;
  background: var(--wpn-fond);
  box-shadow: 0 -22px 50px rgba(27,31,42,.10);
}
.section-voies { background: #fff; }

.section-entete { max-width: 60ch; margin-bottom: var(--espace-12); }
.section-entete.centre { margin-left: auto; margin-right: auto; text-align: center; }

.section-etiquette {
  font-size: var(--texte-xs); font-weight: var(--graisse-grasse);
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--wpn-neutre-400); margin: 0 0 var(--espace-4);
}
.section h2 {
  font-family: var(--police-titre); font-weight: var(--graisse-noire);
  font-size: clamp(2.1rem, 4.8vw, 3.3rem); line-height: 1.04;
  letter-spacing: -0.035em; margin: 0 0 var(--espace-5);
}
.section-chapo { font-size: var(--texte-lg); color: var(--wpn-neutre-500); margin: 0; }

/* ==========================================================================
   L'invitation
   ========================================================================== */

.section-invite { background: var(--wpn-ancre); }

.invite {
  display: grid;
  grid-template-columns: 190px 1fr;
  gap: clamp(28px, 5vw, 60px);
  align-items: center;
  width: 100%;
  padding: clamp(30px, 4vw, 52px);
  background: rgba(255,255,255,.045);
  border: 1.5px solid rgba(255,255,255,.14);
  border-radius: 28px;
  color: #fff; text-align: left;
  font-family: var(--police-texte);
  cursor: pointer;
  transition: background .3s ease, border-color .3s ease, transform .3s cubic-bezier(.2,.8,.2,1);
}
.invite:hover {
  background: rgba(255,255,255,.075);
  border-color: rgba(232,178,60,.5);
  transform: translateY(-3px);
}
.invite:focus-visible { outline: 2px solid var(--wpn-jaune-400); outline-offset: 4px; }
@media (max-width: 780px) {
  .invite { grid-template-columns: 1fr; text-align: center; justify-items: center; }
}

/* Le logo, en grand, dans l'invitation. Deux carrés et leur intersection. */
.invite-decor { position: relative; display: block; width: 170px; height: 170px; }
.invite-losange {
  position: absolute; top: 21%;
  width: 52%; height: 52%; border-radius: 13%;
  transform: rotate(45deg);
}
.invite-bleu  { left: 6%;  background: var(--wpn-bleu-700); }
.invite-jaune { left: 42%; background: var(--wpn-jaune-400); }
.invite-croix {
  position: absolute; top: 47%; left: 50%;
  width: 28%; height: 28%; margin: -14% 0 0 -14%;
  border-radius: 16%; transform: rotate(45deg);
  background: var(--wpn-violet-800);
}
.invite:hover .invite-bleu  { transform: rotate(45deg) translate(-6%, 6%); }
.invite:hover .invite-jaune { transform: rotate(45deg) translate(6%, -6%); }
.invite-losange { transition: transform .5s cubic-bezier(.2,.8,.2,1); }

.invite-texte { display: block; }
.invite-etiquette {
  display: block;
  font-size: var(--texte-xs); font-weight: var(--graisse-grasse);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--wpn-jaune-400); margin-bottom: var(--espace-3);
}
.invite-titre {
  display: block;
  font-family: var(--police-titre); font-weight: var(--graisse-noire);
  font-size: clamp(1.8rem, 4vw, 2.8rem); line-height: 1.05;
  letter-spacing: -.03em; margin-bottom: var(--espace-4);
}
.invite-sous {
  display: block; max-width: 54ch;
  color: var(--wpn-neutre-200); font-size: var(--texte-base);
  margin-bottom: var(--espace-6);
}
.invite-appel {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 13px 26px; border-radius: var(--rayon-md);
  background: var(--wpn-jaune-400); color: var(--wpn-ancre);
  font-weight: var(--graisse-grasse); font-size: var(--texte-base);
}
.invite-appel em {
  font-style: normal;
  transition: transform .3s cubic-bezier(.2,.8,.2,1);
}
.invite:hover .invite-appel em { transform: translateX(5px); }

/* ==========================================================================
   Le banc d'essai — deux fenêtres côte à côte
   ========================================================================== */

.banc[hidden] { display: none; }
.banc {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  padding: clamp(14px, 2.5vw, 34px);
}
.banc-fond {
  position: absolute; inset: 0;
  background: rgba(12, 14, 20, .82);
  backdrop-filter: blur(6px);
}

.banc-scene {
  position: relative;
  width: 100%; max-width: 1560px; height: 100%;
  display: flex; flex-direction: column; gap: var(--espace-5);
}

.banc-entete {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--espace-6); flex-wrap: wrap;
  color: #fff; flex-shrink: 0;
}
.banc-etiquette {
  font-size: var(--texte-xs); font-weight: var(--graisse-grasse);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--wpn-jaune-400); margin: 0 0 var(--espace-2);
}
.banc-entete h2 {
  font-family: var(--police-titre); font-weight: var(--graisse-noire);
  font-size: clamp(1.4rem, 2.6vw, 2.1rem); line-height: 1.08;
  letter-spacing: -.03em; margin: 0; color: #fff;
}
.banc-fermer {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 12px 22px; border-radius: var(--rayon-md);
  background: rgba(255,255,255,.1); color: #fff;
  border: 1.5px solid rgba(255,255,255,.2);
  font-family: var(--police-ui); font-size: var(--texte-sm);
  font-weight: var(--graisse-moyenne); cursor: pointer;
  transition: background .2s ease;
}
.banc-fermer:hover { background: rgba(255,255,255,.2); }

/* --- Les deux fenêtres --- */

.banc-duo {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(14px, 2vw, 26px);
  flex: 1; min-height: 0;
}
@media (max-width: 980px) {
  .banc-duo { grid-template-columns: 1fr; grid-template-rows: auto 1fr; }
  .fenetre-portail { max-height: 46vh; }
}

.fenetre {
  display: flex; flex-direction: column;
  min-height: 0; overflow: hidden;
  border-radius: 26px;
  box-shadow: 0 34px 90px rgba(0,0,0,.55);
}
.fenetre-portail { background: #171310; }
.fenetre-site { background: #171310; }

.fenetre-tete {
  display: flex; align-items: center; gap: var(--espace-4);
  padding: 13px 18px; flex-shrink: 0;
  background: rgba(0,0,0,.22);
  border-bottom: 1px solid rgba(255,255,255,.09);
  font-size: var(--texte-xs); color: rgba(255,255,255,.7);
}
.fenetre-pastilles { display: flex; gap: 6px; flex-shrink: 0; }
.fenetre-pastilles i {
  width: 10px; height: 10px; border-radius: 50%;
  background: rgba(255,255,255,.22);
}
.fenetre-nom {
  font-weight: var(--graisse-grasse); letter-spacing: .1em;
  text-transform: uppercase;
}
.fenetre-url {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 5px 14px; border-radius: 999px;
  background: rgba(255,255,255,.08);
  font-family: var(--police-mono, monospace); font-size: 11px;
}
.fenetre-cadenas {
  width: 8px; height: 10px; border-radius: 2px;
  border: 1.5px solid currentColor; border-top-width: 4px;
  opacity: .6;
}
.fenetre-aide {
  margin-left: auto; font-size: 10px;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--wpn-jaune-400);
}

/* Le voyant bat brièvement quand le site vient de recevoir un changement. */
.fenetre-direct.bat { animation: battre .9s ease; }
@keyframes battre {
  0%   { color: #fff; transform: scale(1.12); }
  100% { color: var(--wpn-jaune-400); transform: none; }
}

.fenetre-direct {
  margin-left: auto; display: inline-flex; align-items: center; gap: 7px;
  font-size: 10px; font-weight: var(--graisse-grasse);
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--wpn-jaune-400);
}
.fenetre-direct::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: currentColor;
}
.fenetre-direct.attente { color: rgba(255,255,255,.45); }

.fenetre-corps { flex: 1; min-height: 0; overflow-y: auto; padding: var(--espace-6); }
.fenetre-corps-plein { padding: 0; overflow: hidden; }
.fenetre-corps-plein iframe {
  width: 100%; height: 100%; border: 0; display: block; background: #171310;
}

/* --- Le portail dans sa fenêtre --- */

.banc-onglets {
  display: flex; gap: 4px; margin-bottom: var(--espace-5);
  padding-bottom: var(--espace-4);
  border-bottom: 1px solid rgba(255,255,255,.12);
  flex-wrap: wrap;
}
.banc-onglet {
  padding: 8px 15px; border: 0; border-radius: var(--rayon-md);
  background: transparent; color: rgba(255,255,255,.65);
  font-family: var(--police-ui); font-size: var(--texte-sm);
  font-weight: var(--graisse-moyenne); cursor: pointer;
}
.banc-onglet:hover { background: rgba(255,255,255,.09); color: #fff; }
.banc-onglet.actif { background: rgba(255,255,255,.17); color: #fff; }

.banc-panneau { display: none; }
.banc-panneau.actif { display: block; }

.banc-item {
  display: grid; grid-template-columns: 1fr 96px 36px;
  gap: 10px; align-items: end;
  padding: 12px; margin-bottom: 10px;
  background: rgba(255,255,255,.05); border-radius: var(--rayon-md);
}
.banc-champ { display: block; }
.banc-champ span {
  display: block; font-size: 10px; font-weight: var(--graisse-grasse);
  letter-spacing: .1em; text-transform: uppercase;
  color: rgba(255,255,255,.5); margin-bottom: 5px;
}
.banc-champ input,
.banc-heure input {
  width: 100%; padding: 9px 12px;
  border: 1.5px solid rgba(255,255,255,.16); border-radius: 8px;
  background: rgba(255,255,255,.07); color: #fff;
  font-family: var(--police-texte); font-size: var(--texte-sm);
}
.banc-champ input:focus,
.banc-heure input:focus {
  outline: none; border-color: var(--wpn-jaune-400);
  background: rgba(255,255,255,.12);
}
.banc-panneau > .banc-champ { margin-bottom: var(--espace-4); }

.banc-retirer {
  width: 36px; height: 36px; border: 0; border-radius: 8px;
  background: rgba(255,255,255,.07); color: rgba(255,255,255,.55);
  cursor: pointer; font-size: 13px;
}
.banc-retirer:hover { background: rgba(179,38,30,.75); color: #fff; }

.banc-ajouter {
  width: 100%; padding: 11px; margin-top: 6px;
  border: 1.5px dashed rgba(255,255,255,.24); border-radius: var(--rayon-md);
  background: transparent; color: rgba(255,255,255,.65);
  font-family: var(--police-ui); font-size: var(--texte-sm);
  font-weight: var(--graisse-moyenne); cursor: pointer;
}
.banc-ajouter:hover {
  border-color: var(--wpn-jaune-400); color: var(--wpn-jaune-400);
  border-style: solid;
}

.banc-heure {
  display: grid; grid-template-columns: 96px 1fr;
  gap: 10px; align-items: center; margin-bottom: 8px;
}
.banc-heure > span { font-size: var(--texte-sm); color: rgba(255,255,255,.8); }

.banc-depot {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: var(--espace-8) var(--espace-4); text-align: center;
  border: 1.5px dashed rgba(255,255,255,.22); border-radius: var(--rayon-md);
  color: rgba(255,255,255,.55); font-size: var(--texte-sm);
  cursor: pointer;
}
.banc-depot em {
  font-style: normal; font-family: var(--police-mono, monospace);
  font-size: 10px; color: rgba(255,255,255,.4);
}

.banc-pied {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--espace-4); flex-wrap: wrap;
  margin-top: var(--espace-6); padding-top: var(--espace-5);
  border-top: 1px solid rgba(255,255,255,.12);
}
.banc-etat { font-size: var(--texte-xs); color: rgba(255,255,255,.55); }
.banc-publier {
  padding: 11px 22px; border: 0; border-radius: var(--rayon-md);
  background: rgba(255,255,255,.16); color: #fff;
  font-family: var(--police-ui); font-size: var(--texte-sm);
  font-weight: var(--graisse-moyenne); cursor: pointer;
  transition: background .22s ease, color .22s ease;
}
.banc-publier.prete { background: var(--wpn-jaune-400); color: var(--wpn-ancre); }
.banc-publier:hover { background: #fff; color: var(--wpn-violet-800); }
.banc-publier:disabled { opacity: .6; cursor: default; }

.banc.publie .fenetre-site { box-shadow: 0 0 0 3px var(--wpn-jaune-400), 0 34px 90px rgba(0,0,0,.55); }
.fenetre-site { transition: box-shadow .35s ease; }

/* ==========================================================================
   Chiffres
   ========================================================================== */

.chiffres {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--espace-8);
  margin-bottom: var(--espace-16);
  padding-bottom: var(--espace-12);
  border-bottom: 1px solid var(--wpn-neutre-100);
}
.chiffre b {
  display: block;
  font-family: var(--police-titre); font-weight: var(--graisse-noire);
  font-size: clamp(2.8rem, 6vw, 4.4rem); line-height: 1;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
  color: var(--wpn-bleu-700);
}
.chiffre:nth-child(2) b { color: var(--wpn-violet-800); }
.chiffre:nth-child(3) b { color: var(--wpn-jaune-700); }
.chiffre span {
  display: block; margin-top: var(--espace-2);
  font-size: var(--texte-sm); color: var(--wpn-neutre-500);
}

/* ==========================================================================
   Réalisations
   ========================================================================== */

.travaux { display: grid; grid-template-columns: repeat(auto-fit, minmax(290px, 1fr)); gap: var(--espace-6); }
.travail {
  background: #fff; border: 1px solid var(--wpn-neutre-100);
  border-radius: var(--rayon-lg); overflow: hidden;
  text-decoration: none; display: flex; flex-direction: column;
  transition: transform .3s cubic-bezier(.2,.8,.2,1), box-shadow .3s ease;
}
.travail:hover { transform: translateY(-5px); box-shadow: var(--ombre-lg); }
.travail-image {
  aspect-ratio: 16 / 10; background: var(--wpn-neutre-100);
  display: flex; align-items: center; justify-content: center;
  color: var(--wpn-neutre-300); font-size: var(--texte-sm);
  overflow: hidden;
  transition: transform .45s cubic-bezier(.2,.8,.2,1);
}
.travail:hover .travail-image { transform: scale(1.04); }
.travail-texte { padding: var(--espace-6); flex: 1; }
.travail h3 { margin: 0 0 var(--espace-2); font-size: var(--texte-lg); }
.travail p { margin: 0; font-size: var(--texte-sm); color: var(--wpn-neutre-500); }
.travail-meta { display: flex; gap: var(--espace-2); flex-wrap: wrap; margin-top: var(--espace-4); }

.puce {
  font-size: 11px; font-weight: var(--graisse-grasse);
  letter-spacing: 0.06em; text-transform: uppercase;
  padding: 4px 9px; border-radius: 4px;
  transform: translateY(0);
  transition: transform .3s cubic-bezier(.2,.8,.2,1);
}
/* Les trois puces s'élèvent en cascade au survol de la carte. */
.travail:hover .puce:nth-child(1) { transform: translateY(-3px); transition-delay: 0s; }
.travail:hover .puce:nth-child(2) { transform: translateY(-3px); transition-delay: .06s; }
.travail:hover .puce:nth-child(3) { transform: translateY(-3px); transition-delay: .12s; }
.puce-w { background: var(--wpn-bleu-50);   color: var(--wpn-bleu-700); }
.puce-p { background: var(--wpn-violet-50); color: var(--wpn-violet-800); }
.puce-n { background: var(--wpn-jaune-100); color: var(--wpn-jaune-800); }

/* ==========================================================================
   Les trois voies
   ========================================================================== */

.voies { display: grid; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); gap: var(--espace-6); }
.voie {
  position: relative; overflow: hidden;
  background: var(--wpn-fond); border: 1px solid var(--wpn-neutre-100);
  border-radius: var(--rayon-lg); padding: var(--espace-8);
  display: flex; flex-direction: column;
  transition: transform .3s cubic-bezier(.2,.8,.2,1), border-color .3s ease;
}
.voie:hover { transform: translateY(-4px); }
.voie-1:hover { border-color: var(--wpn-bleu-700); }
.voie-2:hover { border-color: var(--wpn-violet-800); }
.voie-3:hover { border-color: var(--wpn-jaune-400); }

/* Au survol, un second losange rejoint le premier : la géométrie du logo
   se complète, et l'idée de l'échange devient visible. */
.voie-marque {
  position: relative;
  width: 26px; height: 26px; border-radius: 5px;
  transform: rotate(45deg); margin-bottom: var(--espace-6);
  transition: transform .45s cubic-bezier(.2,.8,.2,1);
}
.voie-marque::after {
  content: ""; position: absolute; inset: 0;
  border-radius: 5px; background: currentColor;
  opacity: 0; transform: translate(9px, 9px);
  transition: opacity .35s ease, transform .45s cubic-bezier(.2,.8,.2,1);
}
.voie:hover .voie-marque::after { opacity: .34; transform: translate(13px, 13px); }
.voie-1 .voie-marque { background: var(--wpn-bleu-700);   color: var(--wpn-jaune-400); }
.voie-2 .voie-marque { background: var(--wpn-violet-800); color: var(--wpn-jaune-400); }
.voie-3 .voie-marque { background: var(--wpn-jaune-400);  color: var(--wpn-bleu-700); }

.voie h3 { margin: 0 0 var(--espace-3); font-size: var(--texte-xl); }
.voie p { margin: 0 0 var(--espace-6); color: var(--wpn-neutre-500); font-size: var(--texte-sm); flex: 1; }
.voie-echange {
  font-size: var(--texte-sm); padding-top: var(--espace-4);
  border-top: 1px solid var(--wpn-neutre-100);
}
.voie-echange b { display: block; margin-bottom: 3px; }

/* ==========================================================================
   Boutons
   ========================================================================== */

.heros-actions { display: flex; gap: var(--espace-4); flex-wrap: wrap; align-items: center; }

.btn {
  position: relative; overflow: hidden;
  display: inline-block; text-decoration: none;
  font-family: var(--police-ui); font-weight: var(--graisse-moyenne);
  font-size: var(--texte-base);
  padding: 16px 32px; border-radius: var(--rayon-md);
  border: 1.5px solid transparent;
}
.btn span { position: relative; z-index: 1; transition: color .3s ease; }
.btn::before {
  content: ""; position: absolute; inset: 0;
  transform: scaleX(0); transform-origin: left;
  transition: transform .4s cubic-bezier(.2,.8,.2,1);
}
.btn:hover::before { transform: scaleX(1); }

.btn-primaire { background: var(--wpn-ancre); color: #fff; }
.btn-primaire::before { background: var(--wpn-bleu-700); }
.btn-fantome { border-color: rgba(27,31,42,.2); color: var(--wpn-ancre); }
.btn-fantome::before { background: var(--wpn-ancre); }
.btn-fantome:hover span { color: #fff; }

/* ==========================================================================
   Appel final et pied
   ========================================================================== */

.final { background: var(--wpn-ancre); color: #fff; }
.final h2 { color: #fff; }
.final .section-chapo { color: var(--wpn-neutre-200); }
.final .btn-primaire { background: var(--wpn-jaune-400); color: var(--wpn-ancre); }
.final .btn-primaire::before { background: #fff; }
.final .btn-fantome { border-color: rgba(255,255,255,.3); color: #fff; }
.final .btn-fantome::before { background: #fff; }
.final .btn-fantome:hover span { color: var(--wpn-ancre); }

.pied {
  background: var(--wpn-ancre); color: var(--wpn-neutre-300);
  padding: var(--espace-12) 0; font-size: var(--texte-sm);
  border-top: 1px solid rgba(255,255,255,.08);
}
.pied-contenu { display: flex; justify-content: space-between; gap: var(--espace-8); flex-wrap: wrap; }
.pied strong { color: #fff; }
.pied a { color: var(--wpn-neutre-200); text-decoration: none; }
.pied a:hover { color: #fff; }
.pied-liens { display: flex; gap: var(--espace-6); flex-wrap: wrap; }

/* ==========================================================================
   Apparition au défilement
   Aucune inertie, aucun retard : l'élément se révèle dès qu'il entre.
   ========================================================================== */

.apparait { opacity: 0; transform: translateY(18px); }
.apparait.vu {
  opacity: 1; transform: none;
  transition: opacity .5s linear, transform .5s cubic-bezier(.2,.8,.2,1);
}

/* Dans la pile des onglets, le contenu est visible d'emblée : le bloc étant
   collant, l'observateur d'apparition se déclenche mal et le texte pouvait
   rester à demi transparent, voire invisible. Ailleurs sur la page,
   l'apparition joue normalement. */
.bloc .apparait { opacity: 1; transform: none; }

/* ==========================================================================
   Mouvement réduit — tout s'affiche à l'état final, rien ne bouge.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
  }
  .apparait { opacity: 1; transform: none; }
  /* Le logo reste assemblé, dans sa position finale : c'est déjà l'état
     d'arrivée de l'animation, donc rien à figer de plus. */
  .heros-etiquette, .heros-chapo, .heros-actions { opacity: 1; }
  .mot-window  { color: var(--wpn-bleu-700); }
  .mot-portal  { color: var(--wpn-violet-800); }
  .mot-network { color: var(--wpn-jaune-700); }
  #fond { display: none; }
}


/* ==========================================================================
   Le calculateur d'estimation
   --------------------------------------------------------------------------
   Deux onglets : ce qu'on construit, ce qu'on échange. Le résultat reste
   visible dans les deux, pour qu'on voie l'effet d'un réglage sans changer
   de vue.
   ========================================================================== */

/* Le titre reste sur deux lignes courtes plutôt que de déborder, et l'espace
   sous l'introduction sépare franchement le discours des réglages. */
.section-estime .section-entete { max-width: 560px; margin-bottom: var(--espace-12); }
.section-estime .section-entete h2 { max-width: 14ch; }

.estime {
  display: grid;
  grid-template-columns: 1fr minmax(290px, 380px);
  gap: clamp(28px, 4vw, 60px);
  align-items: start;
}

/* --- Les onglets --------------------------------------------------------- */

.estime-onglets {
  display: flex;
  gap: var(--espace-2);
  margin-bottom: var(--espace-9);
  border-bottom: 1px solid rgba(27,31,42,.12);
}

.estime-onglet {
  display: inline-flex; align-items: center; gap: var(--espace-3);
  padding: var(--espace-4) var(--espace-5);
  border: 0; background: transparent;
  font-family: var(--police-texte);
  font-size: var(--texte-sm);
  font-weight: var(--graisse-moyenne);
  color: var(--wpn-neutre-500);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color .2s ease, border-color .2s ease;
}
.estime-onglet:hover { color: var(--wpn-ancre); }
.estime-onglet.est-actif {
  color: var(--wpn-ancre);
  border-bottom-color: var(--wpn-bleu-700);
}

.onglet-numero {
  display: grid; place-items: center;
  width: 20px; height: 20px;
  border-radius: 3px;
  background: rgba(27,31,42,.1);
  font-size: 11px; font-weight: var(--graisse-grasse);
}
.estime-onglet.est-actif .onglet-numero {
  background: var(--wpn-bleu-700); color: #fff;
}

.estime-volet { display: none; padding-top: var(--espace-7); }
.estime-volet.est-visible { display: block; }

.volet-intro {
  margin: 0 0 var(--espace-8);
  font-size: var(--texte-sm);
  line-height: 1.6;
  color: var(--wpn-neutre-500);
  max-width: 54ch;
}

/* --- Les modules à cocher ------------------------------------------------ */

.modules { border: 0; padding: 0; margin: 0 0 var(--espace-10); }
.modules legend {
  padding: 0;
  font-size: var(--texte-xs);
  font-weight: var(--graisse-grasse);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--wpn-neutre-500);
  margin-bottom: var(--espace-5);
}

.module {
  display: flex; align-items: flex-start; gap: var(--espace-4);
  padding: var(--espace-4) 0;
  cursor: pointer;
  border-top: 1px solid rgba(27,31,42,.08);
}
.module:has(input:disabled) { cursor: default; opacity: .62; }

.module input[type="checkbox"] {
  -webkit-appearance: none; appearance: none;
  flex: none;
  width: 20px; height: 20px; margin: 2px 0 0;
  border: 2px solid rgba(27,31,42,.24);
  border-radius: 3px;
  transform: rotate(45deg);
  cursor: inherit;
  transition: background .2s ease, border-color .2s ease;
}
.module input[type="checkbox"]:checked {
  background: var(--wpn-bleu-700);
  border-color: var(--wpn-bleu-700);
}
.module input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--wpn-bleu-700); outline-offset: 3px;
}

.module-corps { display: flex; flex-direction: column; gap: 3px; }
.module-titre {
  font-size: var(--texte-base, 1rem);
  font-weight: var(--graisse-moyenne);
  color: var(--wpn-ancre);
}
.module-titre em { font-style: normal; color: var(--wpn-neutre-500); font-weight: 400; }
.module-note { font-size: var(--texte-sm); color: var(--wpn-neutre-500); line-height: 1.5; }

.module-banniere {
  margin-top: var(--espace-6);
  border-top: 1px solid rgba(27,31,42,.08);
  border-bottom: 1px solid rgba(27,31,42,.08);
}
.module-banniere input[type="checkbox"]:checked {
  background: var(--wpn-jaune-700); border-color: var(--wpn-jaune-700);
}

/* --- Les curseurs -------------------------------------------------------- */

.reglage + .reglage { margin-top: var(--espace-8); }

.reglage label {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--espace-4);
  margin-bottom: var(--espace-3);
}
.reglage-titre {
  font-size: var(--texte-sm);
  font-weight: var(--graisse-moyenne);
  color: var(--wpn-neutre-500);
}
.reglage output {
  font-family: var(--police-titre);
  font-size: clamp(1.05rem, 1.8vw, 1.25rem);
  font-weight: var(--graisse-noire);
  letter-spacing: -0.02em;
  color: var(--wpn-ancre);
}
.reglage-note {
  margin: var(--espace-3) 0 0;
  font-size: var(--texte-sm);
  line-height: 1.5;
  color: var(--wpn-neutre-500);
  min-height: 3em;   /* la hauteur ne saute pas quand le texte change */
}

/* Les navigateurs ne s'accordent pas sur le style natif d'un `range` : on le
   neutralise et on redessine piste et poignée, en losange comme la marque. */
.reglage input[type="range"] {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 26px;
  background: transparent; cursor: pointer;
}
.reglage input[type="range"]::-webkit-slider-runnable-track {
  height: 3px; background: rgba(27,31,42,.16); border-radius: 2px;
}
.reglage input[type="range"]::-moz-range-track {
  height: 3px; background: rgba(27,31,42,.16); border-radius: 2px;
}
.reglage input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 18px; height: 18px; margin-top: -7.5px;
  background: var(--wpn-bleu-700);
  border: 0; border-radius: 3px;
  transform: rotate(45deg);
  transition: transform .2s ease;
}
.reglage input[type="range"]::-moz-range-thumb {
  width: 18px; height: 18px;
  background: var(--wpn-bleu-700);
  border: 0; border-radius: 3px;
  transform: rotate(45deg);
}
.reglage input[type="range"]:hover::-webkit-slider-thumb { transform: rotate(45deg) scale(1.15); }
.reglage input[type="range"]:focus-visible::-webkit-slider-thumb {
  outline: 2px solid var(--wpn-bleu-700); outline-offset: 3px;
}

/* Les curseurs de l'onglet « rabais » portent le jaune : céder de la place
   n'est pas le même geste que construire, et l'oeil doit le distinguer. */
#curseur-principale::-webkit-slider-thumb,
#curseur-secondaire::-webkit-slider-thumb { background: var(--wpn-jaune-700); }
#curseur-principale::-moz-range-thumb,
#curseur-secondaire::-moz-range-thumb { background: var(--wpn-jaune-700); }

/* --- Le résultat --------------------------------------------------------- */

.estime-resultat {
  position: sticky; top: var(--espace-8);
  padding: clamp(26px, 3.5vw, 38px);
  background: var(--wpn-ancre);
  color: #fff;
  border-radius: 20px;
}

.resultat-etiquette {
  margin: 0 0 var(--espace-3);
  font-size: var(--texte-xs);
  font-weight: var(--graisse-grasse);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255,255,255,.55);
}

.resultat-fourchette {
  margin: 0 0 var(--espace-6);
  font-family: var(--police-titre);
  font-weight: var(--graisse-noire);
  font-size: clamp(1.7rem, 3.4vw, 2.4rem);
  line-height: 1.05;
  letter-spacing: -0.03em;
  color: var(--wpn-jaune-400);
}

.resultat-detail {
  border-top: 1px solid rgba(255,255,255,.14);
  padding-top: var(--espace-4);
}
.detail-ligne {
  display: flex; justify-content: space-between; gap: var(--espace-4);
  padding: var(--espace-2) 0;
  font-size: var(--texte-sm);
  color: rgba(255,255,255,.65);
}
.detail-ligne span:last-child { color: rgba(255,255,255,.9); }
.detail-ligne.est-rabais span:last-child { color: var(--wpn-jaune-400); font-weight: var(--graisse-moyenne); }
.detail-ligne.est-rabais.est-nul span:last-child { color: rgba(255,255,255,.4); }
/* Le plafond doit se voir : au-delà, pousser les curseurs ne change plus rien. */
.detail-ligne.est-rabais.est-plafonne span:last-child::after {
  content: " (max)"; font-size: .85em; color: rgba(255,255,255,.5);
}

.resultat-note {
  margin: var(--espace-5) 0 var(--espace-6);
  font-size: var(--texte-sm);
  line-height: 1.5;
  color: rgba(255,255,255,.55);
}

.estime-resultat .btn-primaire {
  background: var(--wpn-jaune-400);
  color: var(--wpn-ancre);
  width: 100%; justify-content: center;
}

@media (max-width: 860px) {
  .estime { grid-template-columns: 1fr; }
  .estime-resultat { position: relative; top: auto; }
}
