/* =========================================================================
   Lupa, feuille de style du site.

   Extraite de index.html le 22 aout 2026, sans qu'une seule regle change,
   pour que la page d'accueil et les quatre pages interieures partagent la
   MEME source de verite : les couleurs du guide de normes, la typographie,
   la barre de navigation, les boutons, le pied de page et les entrees.

   Si tu changes une couleur ou une police, c'est ICI et nulle part ailleurs.
   ========================================================================= */

/* ============================================================
   LUPA. Jetons de marque.
   Palette prélevée dans le monde de la vidéo : matin d'hiver,
   plâtre bleu-gris, chêne miel, lin, lumière givrée.
   ============================================================ */
:root{
  /* PALETTE OFFICIELLE, guide de normes de la cliente, 21 août 2026.
     Elle remplace la palette bleue choisie avant qu'on sache que ce guide
     existait. C'est elle qui rendait le site froid : sa couleur de marque
     est un terracotta chaud, nommé « proximité » dans son guide, et on
     l'avait remplacée par la couleur la plus froide du nuancier.
     Officiel : charcoal #353434, terracotta #B75C5A, crème #F0EEE8, blanc.
     Les sables et les gris ci-dessous sont dérivés de ces trois-là.
     Contrastes mesurés : charcoal sur crème 10,7. Gris chaud sur crème 6,25.
     Crème sur charcoal 10,7. Terracotta clair sur charcoal 6,01.
     ATTENTION : le terracotta officiel ne peut pas servir de texte courant,
     il tombe à 3,86 sur le crème. Accent, trait, bouton, rien de plus. */
  --canvas:#F0EEE8;
  --panel:#E7E3D9;
  --panel-2:#EBE7DE;
  --ink-deep:#353434;
  --ink-deep-2:#3F3D3B;
  --accent:#B75C5A;        /* terracotta officiel du guide, page 8 */
  --accent-text:#A04846;   /* le terracotta assombri pour le petit texte. Mesuré : 5,16 sur
                              le crème et 4,67 sur le sable, contre 3,86 et 3,26 pour le
                              terracotta pur, qui échouait le seuil de 4,5 sur les deux fonds. */
  --accent-btn:#B55A58;    /* le terracotta assombri de deux points pour le FOND des boutons.
                              Le blanc sur le #B75C5A officiel donnait 4,48, soit deux
                              centièmes sous le seuil. Question laissée ouverte au dossier
                              depuis le 21 août, tranchée le 22 : on fonce le bouton, on ne
                              touche pas au logo. L'écart est invisible à l'œil. */
  --accent-hover:#8F3D3B;
  --accent-muted:#CE9591;
  --text-primary:#353434;
  --text-secondary:#5A5654;
  /* La couleur du texte surligné, 16 septembre 2026. AUCUNE COULEUR NEUVE
     HORS DU GUIDE : c'est la terracotta officielle #B75C5A mélangée au crème
     officiel #F0EEE8 à 75 %. C'est la seule teinte qui garde lisibles LES
     DEUX couleurs de texte du site, mesuré : charbon 7,97 et gris secondaire
     4,66, pour un seuil de 4,5. Le #E7C2BF déjà présent dans la feuille
     donnait 4,45 avec le gris, deux centièmes sous le seuil, exactement la
     tolérance que le projet a refusée sur le bouton le 22 août. */
  --select:#E2CAC4;
  /* --oak:#B08856 retire le 23 aout 2026 : le chene ne figure nulle part dans le
     guide de normes, il avait deja quitte les etoiles d'avis le 22, et le jeton
     restait declare sans aucun usage. Ne pas le reintroduire. */
  --line:rgba(53,52,52,.16);
  --line-strong:rgba(53,52,52,.34);
  --field-line:rgba(53,52,52,.52);
  --field-line-dark:rgba(240,238,232,.42);

  /* Quatrième et dernière révision typographique, 22 août 2026. Le guide de
     normes officiel de la cliente, réalisé par l'agence Monument, gouverne
     désormais, au-dessus de toute décision de design prise avant sa réception.
     Sa page 10 nomme trois polices et donne leurs équivalents Google Fonts :

       Titres et sous-titres : Things Regular    -> Playfair Display
       Texte courant         : Neuvetica Regular -> Inter extralight
       Slogan                : Authenia Regular  -> aucun équivalent

     Le guide ne contient AUCUNE police à chasse fixe, donc il n'y en a plus
     nulle part : les étiquettes techniques passent à Inter en majuscules
     espacées. Le mot-symbole Lupa passe lui aussi à Playfair, en attendant
     les vrais fichiers du logo, que le guide interdit de recomposer dans une
     autre police.

     Décision du client, 22 août : appliquer le guide à la lettre, extralight
     compris. La réserve sur la finesse du texte courant a été dite et écartée.
     ATTENTION : typographie et voile du héros sont liés. Si l'une bouge,
     refaire lupa-tests/t8-legib.mjs au complet avant de montrer quoi que ce
     soit au client. */
  --display:"Playfair Display",Georgia,"Times New Roman",serif;
  --mark:"Playfair Display",Georgia,"Times New Roman",serif;
  --body:"Inter",system-ui,-apple-system,"Segoe UI",sans-serif;
  --mono:"Inter",system-ui,-apple-system,"Segoe UI",sans-serif;

  --ease:cubic-bezier(.22,.61,.36,1);
  --ease-soft:cubic-bezier(.4,.14,.3,1);

  --tshadow:0 1px 2px rgba(5,8,14,.95),0 3px 12px rgba(5,8,14,.78),0 10px 44px rgba(5,8,14,.8);
  --gut:clamp(1.25rem,5vw,5rem);
  --maxw:1320px;
}

*,*::before,*::after{box-sizing:border-box}
html,body{overflow-x:hidden;overflow-x:clip}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--canvas);color:var(--text-primary);
  font-family:var(--body);font-weight:200;font-size:clamp(1rem,.55vw + .88rem,1.125rem);
  line-height:1.62;-webkit-font-smoothing:antialiased;
}
img{max-width:100%;height:auto;display:block}
a{color:inherit}
h1,h2,h3,h4{font-family:var(--display);font-weight:700;line-height:1.12;margin:0;letter-spacing:-.02em}
p{margin:0}
button,input,select,textarea{font:inherit;color:inherit}

:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:2px}

/* ---------- Les surfaces du navigateur, 16 septembre 2026 -----------------
   Demande de Mathieu après le contrôle mené avec les skills du studio. Le
   plancher de qualité d'impeccable nomme un angle mort précis : les pièces
   que le NAVIGATEUR dessine et qu'aucune feuille n'habille. Il en restait
   trois ici, et la sélection était la plus voyante : surligner une phrase
   pour la copier posait le bleu du système en plein milieu d'une page crème
   et terracotta. C'était la seule couleur de la page qui n'appartenait pas
   à la cliente.

   RIEN D'AUTRE NE CHANGE. Aucune géométrie, aucune mise en page, aucun
   pixel déplacé : seules les couleurs de trois pièces du navigateur.

   DEUX FAMILLES DE FOND, DONC DEUX SÉLECTIONS. Les sections foncées portent
   du texte crème : une sélection pâle y serait crème sur crème, illisible.
   La liste des fonds foncés est celle de `FONCES` dans `pages.js`
   (pagehead, lupa, zones, cta, foot). SI TU AJOUTES UNE SECTION FONCÉE,
   ajoute sa classe ici AUSSI, comme pour la barre de navigation.
   Mesuré : crème #EFECE4 sur la terracotta sombre, 6,14. */
::selection{background:var(--select);color:var(--text-primary)}
.pagehead::selection,.lupa::selection,.zones::selection,.cta::selection,.foot::selection,
.pagehead ::selection,.lupa ::selection,.zones ::selection,.cta ::selection,.foot ::selection{
  background:var(--accent-hover);color:#EFECE4}

/* La barre de défilement suit la marque, mais GARDE SA LARGEUR NATIVE.
   `scrollbar-width` n'est volontairement pas déclaré : une barre plus mince
   décalerait la mise en page de quelques pixels sur toute la largeur, et ce
   lot ne doit rien déplacer. Propriété standard seulement, comprise par
   Chrome, Edge et Firefox ; un vieux Safari garde sa barre d'origine, ce qui
   est un repli propre. Mesuré : le pouce sur son rail donne 4,85. */
html{scrollbar-color:var(--accent-text) var(--panel-2)}

/* `color-scheme` n'était pas déclaré et sa valeur calculée était `normal`,
   donc le navigateur décidait seul. Un visiteur dont le téléphone ou
   l'ordinateur est réglé en mode sombre pouvait voir les SEIZE menus
   déroulants du site s'ouvrir en noir sur une page crème. Le site n'a qu'un
   seul monde, celui du guide, et il est clair : on le dit. */
:root{color-scheme:light}

.skip{position:absolute;left:-9999px;top:0;z-index:200;background:var(--accent-btn);color:#fff;padding:.75rem 1.25rem}
.skip:focus{left:.5rem;top:.5rem}

/* ---------- L'environnement fixe : la feuille de dessin ---------- */
.sheet{position:fixed;inset:0;z-index:0;pointer-events:none}
.sheet__grid{position:absolute;inset:0;opacity:.5;
  background-image:linear-gradient(var(--line) 1px,transparent 1px),linear-gradient(90deg,var(--line) 1px,transparent 1px);
  background-size:clamp(64px,7vw,116px) clamp(64px,7vw,116px);
  -webkit-mask-image:radial-gradient(ellipse 90% 70% at 50% 40%,#000 10%,transparent 78%);
  mask-image:radial-gradient(ellipse 90% 70% at 50% 40%,#000 10%,transparent 78%);
}
.sheet__glow{position:absolute;inset:-20%;
  background:radial-gradient(ellipse 46% 40% at 22% 18%,rgba(183,92,90,.22),transparent 62%),
             radial-gradient(ellipse 40% 46% at 84% 74%,rgba(176,136,86,.14),transparent 66%);
  /* L animation `drift` est retiree le 17 septembre 2026, a la demande de la
     cliente (« des animations inutiles qui ne servent a rien »). Elle faisait
     deriver ce halo pendant 96 s en boucle infinie sur un degrade que personne
     ne remarque, et elle forcait un redessin permanent. C est aussi elle qui
     rendait toute comparaison pixel a pixel du site inutilisable : voir
     LUPA-REPRISE, 24 aout. Le halo reste, immobile. */
}

/* ---------- Barre de navigation ---------- */
.nav{position:fixed;top:0;left:0;right:0;z-index:90;display:flex;align-items:center;justify-content:space-between;
  /* 1.3rem = 20,8 px : la ZONE DE PROTECTION du logo, page 05 du guide.
     Elle vaut 0,391 fois la hauteur du verrouillage, soit 20,3 px a 52 px de
     haut. Les liens du menu etaient mesures a 16,5 px, donc en conflit.
     NE DESCENDS PAS SOUS CETTE VALEUR sans reduire le logo d autant. */
  gap:1.3rem;padding:.9rem var(--gut);transition:background .5s var(--ease),backdrop-filter .5s var(--ease),border-color .5s var(--ease);
  border-bottom:1px solid transparent}
/* Aucune barre derrière la navigation, jamais. Demande du collègue de
   Marie-Claude, relayée par le client le 22 août 2026 : la bande claire qui
   apparaissait sous l'écriture une fois le héros passé se voyait comme un
   bandeau posé sur la page. Elle est retirée.

   Ce qui la remplace : l'écriture change de couleur selon la section qu'elle
   survole. Quatre sections sur huit ont un fond foncé, donc une écriture
   charbon fixe y serait invisible. La classe est posée par navUpdate(), qui
   lit la section située sous la barre et n'écrit dans le DOM qu'au changement,
   comme tout le reste du site. */
.nav.solid{background:none;backdrop-filter:none;border-bottom-color:transparent}
/* SUR TÉLÉPHONE SEULEMENT, la barre reprend un fond DÈS QU'ELLE A QUITTÉ LE
   HÉROS. Le collègue de Marie-Claude avait demandé « pas de petite bande
   beige quand tu scrolles » : sa demande visait le héros, l'image plein
   écran, et celui-ci reste absolument intact (.nav sans .solid = aucun fond).
   Dans le contenu, l'absence de fond faisait passer le mot Lupa par-dessus
   les phrases, illisible des deux côtés. Vu sur le vrai téléphone du client. */
@media (max-width:760px){
  .nav.solid{background:rgba(240,238,232,.92);backdrop-filter:blur(14px) saturate(1.1);
    border-bottom:1px solid var(--line)}
  .nav.solid:not(.on-light){background:rgba(21,26,33,.92);border-bottom-color:rgba(240,238,232,.14)}
}
/* --- La barre s'efface quand on descend, sur téléphone seulement ---
   Décision du client, 22 août 2026. La barre n'a aucun fond, demande du
   collègue, et du texte lui passait donc dessous à 76 pour cent des positions
   de défilement à 390 px, contre 35 pour cent à 1440. L'effacer règle la
   collision sans remettre la bande claire dont le collègue ne voulait pas.
   Le héros reste plein écran et l'ordinateur ne change pas d'un pouce.
   Le seuil est à 900 px : au-dessus, la collision retombe au niveau de
   l'ordinateur et le comportement serait déroutant sur un portable.
   La règle de base est écrite AVANT le media, jamais après : voir les deux
   défauts du 22 août causés exactement par l'ordre inverse. */
/* 25 AOUT : LE REPLI S'APPLIQUE MAINTENANT A TOUTES LES LARGEURS.
   Il etait enferme dans ce media, donc sur ordinateur la classe `repliee`
   s'ajoutait et ne faisait RIEN. Mesure : 209 collisions barre/texte sur neuf
   pages a 1440 px, dont le mot Lupa par-dessus le titre de la page Outils,
   creme sur creme, photographie par le client.
   C'est le meme remede que sur telephone, et il n'ajoute AUCUNE bande claire :
   la demande du collegue tient toujours. Le declenchement, lui, reste garde
   par le script : jamais pendant le heros, jamais sur le bandeau de titre. */
.nav{will-change:transform;
  transition:background .5s var(--ease),backdrop-filter .5s var(--ease),
  border-color .5s var(--ease),transform .34s var(--ease)}
.nav.repliee{transform:translateY(-100%)}
.nav__mark{display:flex;align-items:baseline;gap:.6rem;text-decoration:none;color:#fff;transition:color .5s var(--ease)}
.nav.on-light .nav__mark{color:var(--text-primary)}
/* Taille minimale du mot-symbole : le guide de normes, page 7, exige 30 px à
   l'écran pour « Lupa » seul. Le plancher du clamp est donc 1.875rem, soit
   exactement 30 px. Ne le descends jamais, ici ni dans la règle téléphone. */
/* 52 px, CHOISI PAR MATHIEU le 17 septembre 2026 pour que le petit texte du
   verrouillage se lise (« 52 px, plus lisible »). Il connaissait le prix : la
   barre passe de 76 a 82 px, donc tout le haut des treize pages descend de
   six pixels.
   Le verrouillage fait alors 197,6 px de large, 2,5 fois le minimum de 78 px
   de la page 07. Sa zone protegee vaut 0,391 x 52 = 20,3 px : le rembourrage
   de la barre est porte a 1.3rem pour la couvrir, parce que la barre porte
   une bordure inferieure, qui EST un element graphique. */
.nav__logo{display:block;height:52px;width:calc(52px * 3.8003);
  background-color:currentColor;
  -webkit-mask:url("logo-lupa-exp.svg") no-repeat left center;-webkit-mask-size:contain;
  mask:url("logo-lupa-exp.svg") no-repeat left center;mask-size:contain}
/* Repli : si le masque n est pas gere, on revoit le mot compose, jamais un
   rectangle plein de la couleur du texte. */
@supports not ((mask-size:contain) or (-webkit-mask-size:contain)){
  .nav__logo{width:auto;background:none;font-family:var(--mark);font-weight:500;
    font-size:1.875rem;letter-spacing:.02em;line-height:1;text-indent:0}
  .nav__logo::before{content:"Lupa"}
}
/* LE VERROUILLAGE « Lupa X exp » AILLEURS QUE DANS LA BARRE, 17 septembre 2026.
   Demande de Mathieu : « partout où il y a le signe Lupa courtiers immobiliers
   il faut rajouter eXp agence immobilière, comme tu as fait pour l'entête ».
   Même fichier et même masque que .nav__logo. La hauteur se calcule TOUJOURS
   depuis la largeur (aspect-ratio 336,97 / 88,67 = 3,8003), donc le dessin ne
   peut pas être déformé, et chaque largeur reste au-dessus des 78 px de la
   page 07 du guide.
   COULEURS, page 09 : BLANC sur la vidéo du héros et sur le fond du pied de
   page (#3F3D3B, qui n'est pas une couleur du guide), CRÈME sur le charbon
   officiel de l'intro (#353434).
   AUCUN EFFET, page 06 : pas d'ombre, pas de lettre par lettre, pas
   d'écrasement. Le logo apparaît en fondu, rien d'autre. */
.logo-exp{display:block;aspect-ratio:336.97/88.67;height:auto;margin:0;
  -webkit-mask:url("logo-lupa-exp.svg") no-repeat left center;-webkit-mask-size:contain;
  mask:url("logo-lupa-exp.svg") no-repeat left center;mask-size:contain}
/* Bande 1 du héros : la largeur suit celle de la bande, plafonnée. */
.band__logo{width:min(100%,520px);background-color:#fff}
.e-logo .band__logo{opacity:var(--k,1)}
/* Héros fixe (téléphone couché, mouvement réduit). */
.static-hero__logo{width:min(78vw,400px);background-color:#fff}
/* Pied de page : 44 px de haut, 167 px de large. Sa zone de protection vaut
   0,391 x 44 = 17 px. */
.foot__logo{width:calc(44px * 3.8003);background-color:#fff}
/* Repli : si le masque n'est pas géré, le mot composé revient, jamais un
   rectangle plein. */
@supports not ((mask-size:contain) or (-webkit-mask-size:contain)){
  .logo-exp{aspect-ratio:auto;width:auto;background:none!important;
    font-family:var(--mark);font-weight:500;font-size:2.4rem;line-height:1;color:#fff}
  .logo-exp::before{content:"Lupa"}
}
.nav__sub{font-family:var(--mono);font-size:.6rem;letter-spacing:.22em;text-transform:uppercase;opacity:.72}
.nav__links{display:flex;align-items:center;gap:clamp(1rem,2vw,1.85rem)}
.nav__links a{font-size:.82rem;letter-spacing:.13em;text-transform:uppercase;text-decoration:none;color:#fff;opacity:.9;white-space:nowrap;
  transition:color .5s var(--ease),opacity .3s var(--ease)}
.nav.on-light .nav__links a{color:var(--text-primary);opacity:.72}
.nav__links a:hover{opacity:1}
.nav__links .btn{opacity:1}
/* Les liens du menu ne se coupent jamais en deux, et ils disparaissent avant
   d'être à l'étroit. Entre les deux, la barre garde le mot-symbole et le
   bouton, qui est de toute façon la seule action de la page. */
/* Seuil monte de 1180 a 1320 le 23 aout 2026, quand l'onglet Outils a fait
   sept liens plus le bouton. Mesure a l'appui : a 1200px la barre debordait
   de 10px. Choix du client : garder tous les libelles au long et sortir le
   menu compact plus tot. Ce seuil existe a TROIS endroits, voir pages.js et
   le script en ligne de index.html. */
@media (max-width:1320px){.nav__links a:not(.btn){display:none}}

/* --- Le menu déroulant des Outils, 27 août 2026 ---------------------------
   Demande du client : « j'aimerais avoir un menu déroulant pour les outils
   étant donné qu'il y en a plusieurs ». Ils sont passés de deux à cinq.

   Le mot Outils RESTE un vrai lien vers la page : un menu déroulant dont la
   tête ne mène nulle part oblige à viser un sous-lien, et au doigt comme au
   clavier c'est une régression. Ici, cliquer va à la page, survoler ouvre la
   liste, et les deux marchent.

   Tout est en CSS, sans une ligne de script : `:hover` pour la souris,
   `:focus-within` pour le clavier. Le déroulant descend donc même si le
   JavaScript ne charge pas. */
.nav__drop{position:relative;display:flex;align-items:center}
.nav__drop__tete::after{content:"";display:inline-block;width:.4em;height:.4em;margin-left:.5em;
  border-right:1px solid currentColor;border-bottom:1px solid currentColor;
  transform:translateY(-.15em) rotate(45deg);transition:transform .3s var(--ease)}
.nav__drop:hover .nav__drop__tete::after,
.nav__drop:focus-within .nav__drop__tete::after{transform:translateY(.05em) rotate(225deg)}
/* Le `padding-top` fait le pont entre le mot et la liste : sans lui, le curseur
   traverse un trou en descendant et le menu se referme sous la souris. */
.nav__drop__menu{position:absolute;top:100%;left:-1rem;z-index:90;
  padding-top:.9rem;min-width:15rem;
  opacity:0;visibility:hidden;transform:translateY(-6px);pointer-events:none;
  transition:opacity .28s var(--ease),transform .28s var(--ease),visibility .28s var(--ease)}
.nav__drop:hover .nav__drop__menu,
.nav__drop:focus-within .nav__drop__menu{opacity:1;visibility:visible;transform:none;pointer-events:auto}
.nav__drop__in{background:var(--ink-deep);border:1px solid rgba(240,238,232,.16);
  box-shadow:0 24px 60px -28px rgba(5,8,14,.7);padding:.5rem 0}
/* Ces liens vivent toujours sur l'encre, même quand la barre est passée en
   version claire sur fond crème : ils gardent donc leur propre couleur, et la
   règle `.nav.on-light` ne doit pas les rattraper. */
.nav__links .nav__drop__in a,
.nav.on-light .nav__links .nav__drop__in a{display:block;padding:.62rem 1.2rem;
  font-size:.72rem;letter-spacing:.12em;color:rgba(240,238,232,.82);opacity:1;white-space:nowrap}
.nav__links .nav__drop__in a:hover,
.nav__links .nav__drop__in a:focus-visible{background:rgba(240,238,232,.08);color:#F0EEE8}
/* Sous le seuil, la barre passe au menu plein écran : le déroulant disparaît
   avec les autres liens. Les cinq outils restent atteignables, la page Outils
   les montre tous. */
@media (max-width:1320px){.nav__drop{display:none}}

/* Le menu du téléphone et de la tablette. Sous 1320 pixels les liens de la
   barre disparaissent : sans ce bouton il ne restait aucune navigation, et
   c'est exactement ce que le client a vu sur son cellulaire. */
.burger{display:none;flex-direction:column;justify-content:center;gap:6px;
  width:44px;height:44px;padding:0;background:none;border:0;cursor:pointer;flex:0 0 auto}
.burger__bar{display:block;width:24px;height:2px;margin:0 auto;background:#fff;
  transition:transform .4s var(--ease),opacity .3s var(--ease),background .5s var(--ease)}
.nav.on-light .burger__bar{background:var(--text-primary)}
.menu.on ~ .nav .burger__bar,.burger[aria-expanded="true"] .burger__bar{background:#F6F4EF}
.burger[aria-expanded="true"] .burger__bar:nth-child(1){transform:translateY(4px) rotate(45deg)}
.burger[aria-expanded="true"] .burger__bar:nth-child(2){transform:translateY(-4px) rotate(-45deg)}
@media (max-width:1320px){.burger{display:flex}}
@media (max-width:600px){.nav__links{display:none}}

.menu{position:fixed;inset:0;z-index:80;background:var(--ink-deep);
  opacity:0;visibility:hidden;transition:opacity .45s var(--ease),visibility .45s var(--ease)}
.menu.on{opacity:1;visibility:visible}
/* `safe center` et non `center` : signalé par le client le 25 août, capture à
   l'appui. Le menu a gagné deux liens depuis sa conception (Outils, Conseils)
   et ne tient plus dans un petit écran. Avec `center` tout court, un contenu
   plus haut que la fenêtre déborde PAR LE HAUT, sous le mot Lupa, et cette
   partie est inatteignable même en défilant : « Propriétés » s'écrivait sous
   le logo. `safe` bascule en alignement haut dès que ça déborde, le rembourrage
   de 5,5 rem reprend son rôle et tout se défile. La première ligne est le
   filet des vieux navigateurs, qui centrent comme avant. */
.menu__in{position:absolute;inset:0;display:flex;flex-direction:column;
  justify-content:center;justify-content:safe center;
  gap:.2rem;padding:5.5rem var(--gut) 2rem;overflow-y:auto}
.menu__in a{font-family:var(--display);font-weight:600;font-size:clamp(1.5rem,6.5vw,2.1rem);
  letter-spacing:-.01em;text-decoration:none;color:#F6F4EF;padding:.5rem 0;
  opacity:0;transform:translateY(14px);transition:opacity .5s var(--ease),transform .5s var(--ease),color .3s var(--ease)}
/* Sur un écran bas, on resserre aussi : neuf liens à 2rem de police ne
   rentreront jamais dans 700px, autant leur donner une chance.
   CE BLOC DOIT RESTER APRÈS la règle générale ci-dessus. Écrit avant elle, il
   avait exactement la même spécificité et perdait donc la cascade : le
   resserrement ne s'appliquait JAMAIS, sur aucun écran, et rien ne le signalait.
   Corrigé le 26 août 2026, trouvé par balayage-cascade.mjs. */
@media (max-height:900px){
  .menu__in a{font-size:clamp(1.3rem,5.2vw,1.7rem);padding:.38rem 0}
}
.menu.on .menu__in a{opacity:1;transform:none}
.menu.on .menu__in a:nth-child(1){transition-delay:.08s}
.menu.on .menu__in a:nth-child(2){transition-delay:.13s}
.menu.on .menu__in a:nth-child(3){transition-delay:.18s}
.menu.on .menu__in a:nth-child(4){transition-delay:.23s}
.menu.on .menu__in a:nth-child(5){transition-delay:.28s}
.menu.on .menu__in a:nth-child(6){transition-delay:.33s}
.menu__in a:hover{color:var(--accent-muted)}
/* Le sélecteur doit battre .menu__in a, sinon le bouton hérite de la taille
   des grands liens et déborde de son cadre. */
.menu__in a.menu__cta{font-family:var(--body);font-weight:400;font-size:.86rem;letter-spacing:.14em;
  line-height:1;margin-top:1.8rem;align-self:flex-start;color:#fff;padding:1rem 1.7rem}
.menu.on .menu__in a.menu__cta{transition-delay:.38s}
.menu__in a.menu__cta:hover{color:#fff;background:var(--accent-hover)}
.menu__tel,.menu__mail{margin-top:1.4rem;font-family:var(--mono);font-size:.72rem;letter-spacing:.12em}
.menu__mail{margin-top:.5rem;font-size:.68rem}
.menu__tel a,.menu__mail a{font-family:var(--mono);font-size:inherit;font-weight:400;letter-spacing:inherit;
  color:var(--accent-muted);padding:.35rem 0;opacity:1;transform:none}
body.menu-ouvert{overflow:hidden}

.btn{display:inline-flex;align-items:center;justify-content:center;gap:.55rem;
  background:var(--accent-btn);color:#fff;text-decoration:none;border:0;cursor:pointer;
  padding:.78rem 1.5rem;font-family:var(--body);font-weight:400;font-size:.82rem;letter-spacing:.14em;text-transform:uppercase;
  transition:background .35s var(--ease),transform .35s var(--ease),box-shadow .35s var(--ease);
  box-shadow:0 1px 0 rgba(53,52,52,.06)}
.btn:hover{background:var(--accent-hover);transform:translateY(-2px);box-shadow:0 10px 26px rgba(53,52,52,.16)}
.btn--ghost{background:transparent;color:inherit;border:1px solid currentColor;box-shadow:none}
.btn--ghost:hover{background:rgba(255,255,255,.1);box-shadow:none}
@media (pointer:coarse){.btn{min-height:44px;display:inline-flex;align-items:center;justify-content:center}}

/* ============================================================
   LE HÉROS DÉFILANT
   ============================================================ */
/* 350vh DEPUIS LE 1er OCTOBRE 2026, et trois bandes au lieu de quatre.
   Mathieu, sur la maquette de l'accueil court : « on garde le principe
   actuel du héros, mais raccourci ». C'était 800vh en août, 500vh le
   17 septembre. La vidéo joue au complet pareil, c'est la distance de
   défilement qui change : 2250 px de course à 1440 x 900, environ 630 px par
   bande, cinq coups de molette de 120 px chacune. Si c'est trop vif, c'est
   cette ligne qu'on tourne, et `t6-gates.mjs` relit les plages. */
.hero{position:relative;height:350vh;z-index:1}
.stage{position:sticky;top:0;height:100vh;overflow:hidden;background:#0E1218}
.stage__media{position:absolute;inset:0}
.poster{position:absolute;inset:0;background-size:cover;background-position:center;transform:scale(1.02)}
#hero{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;
  transition:opacity .9s var(--ease);will-change:transform;transform:translateZ(0)}
.stage.video-ready #hero{opacity:1}
.stage.video-ready .poster{opacity:0;transition:opacity 1.1s var(--ease)}
.scrim{position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(to right,rgba(8,11,17,.34) 0%,rgba(8,11,17,.26) 30%,rgba(8,11,17,.1) 48%,rgba(8,11,17,0) 62%),
             radial-gradient(ellipse 120% 90% at 34% 45%,rgba(10,12,20,0) 30%,rgba(10,12,20,.55) 100%)}
.scrim--floor{position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(to bottom,rgba(10,12,20,.5) 0%,rgba(10,12,20,0) 26%,rgba(10,12,20,0) 62%,rgba(10,12,20,.42) 100%)}

/* Grain fin : casse la bande de dégradé sur 8 bits et donne du grain de pellicule */
.grain{position:absolute;inset:0;pointer-events:none;z-index:3;opacity:.06;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='2' stitchTiles='stitch'/></filter><rect width='140' height='140' filter='url(%23n)'/></svg>");
  background-size:140px 140px}

/* L'anneau de chargement */
.ring{position:absolute;right:calc(var(--gut) - .25rem);bottom:calc(var(--gut) - .25rem);width:48px;height:48px;color:rgba(255,255,255,.82);
  transform:rotate(-90deg);transition:opacity .6s var(--ease);z-index:6}
.ring circle{transition:stroke-dashoffset .18s linear}
.stage.video-ready .ring{opacity:0}
.cue{position:absolute;right:var(--gut);bottom:var(--gut);z-index:6;display:flex;align-items:center;gap:.6rem;
  font-family:var(--mono);font-size:.62rem;letter-spacing:.2em;text-transform:uppercase;color:rgba(255,255,255,.8)}
.cue__line{display:block;width:1px;height:34px;background:linear-gradient(rgba(255,255,255,.1),rgba(255,255,255,.85));
  animation:cueSlide 2.8s var(--ease-soft) -.6s infinite}
@keyframes cueSlide{0%,100%{transform:scaleY(.4);transform-origin:top}50%{transform:scaleY(1);transform-origin:top}}

/* Les bandes de texte */
.bands{position:absolute;inset:0;z-index:5;pointer-events:none}
.band{position:absolute;left:var(--gut);top:50%;transform:translateY(-50%);
  width:min(50ch,52vw);opacity:0;text-shadow:var(--tshadow);color:#F6F4EF}
/* Pas de panneau derrière le texte. Une ombre de colonne uniforme de haut en
   bas, ancrée au bord gauche de l'écran et éteinte avant la fenêtre : la
   lumière tombe du côté de la fenêtre, comme dans la pièce filmée, et il n'y
   a aucune forme visible sur le mur. Le facteur --sf règle toute la famille.

   Forme revue le 22 août 2026, quand la nouvelle vidéo est entrée. L'ancienne
   chute était trop rapide : à 46 pour cent de l'écran le voile n'avait déjà
   plus que la moitié de sa force, et c'est exactement là que finit le dernier
   mot des bandes 3 et 4. Elles tombaient à 2,80 sur l'intérieur du salon.
   La chute est maintenant plus lente et s'éteint à 82 pour cent au lieu de 76.
   Le bord gauche ne bouge presque pas, donc toujours aucun panneau visible,
   mais le texte est protégé jusqu'à sa dernière lettre. Les cinq bandes sont
   remontées entre 3,93 et 6,98, sans toucher aux alphas --sa par bande.
   Si la vidéo change encore, refaire l'audit avec lupa-tests/audit-reel.mjs. */
.band::before{content:"";position:absolute;left:calc(-1*var(--gut));width:100vw;top:-160vh;height:420vh;
  pointer-events:none;z-index:-1;
  opacity:calc(.3 + .7*var(--k,1));
  background:linear-gradient(to right,
    rgba(6,9,15,calc(var(--sa,.7)*var(--sf,.74))) 0%,
    rgba(6,9,15,calc(var(--sa,.7)*var(--sf,.74)*.92)) 30%,
    rgba(6,9,15,calc(var(--sa,.7)*var(--sf,.74)*.72)) 50%,
    rgba(6,9,15,calc(var(--sa,.7)*var(--sf,.74)*.30)) 68%,
    rgba(6,9,15,0) 82%)}
.band .btn{text-shadow:none}
@media (max-width:1100px){.band{width:min(46ch,74vw)}}

.band__kicker{font-family:var(--mono);font-size:.66rem;letter-spacing:.28em;text-transform:uppercase;
  color:rgba(246,244,239,.78);margin-bottom:1.1rem}
.band__word{font-family:var(--mark);font-weight:500;font-size:clamp(4.2rem,12.5vw,11rem);line-height:.9;letter-spacing:.03em;margin:0}
.band__sub{font-family:var(--mono);font-size:clamp(.62rem,.7vw,.76rem);letter-spacing:.3em;text-transform:uppercase;
  margin-top:2.6rem;color:rgba(246,244,239,.86)}
.band__h{font-family:var(--display);font-weight:700;font-size:clamp(1.75rem,3.5vw,3rem);line-height:1.16;letter-spacing:-.02em;max-width:19ch}
/* La bande du nom : courte, donc elle a le droit d'être grande. */
/* 23 aout 2026 : la bande 4 ne porte plus un nom mais le slogan de la marque,
   qui est plus long. La largeur passe de 12ch a 19ch pour qu'il tombe en deux
   lignes au lieu de trois, et la taille baisse d'un cran pour que la surface de
   texte protegee par le voile n'explose pas. Lisibilite remesuree apres coup. */
.band__h--name{font-size:clamp(2.1rem,4.4vw,3.7rem);line-height:1.08;max-width:19ch}
.band__sub--tight{margin-top:1.4rem}
.e-depth .band__sub{--ks:clamp(0,(var(--k,0) - .42)*3,1);opacity:var(--ks);
  transform:translateY(calc((1 - var(--ks))*12px))}
.band__lede{margin-top:1.1rem;font-size:clamp(1rem,1vw + .7rem,1.2rem);color:rgba(246,244,239,.94);max-width:34ch;font-weight:400}
.band__row{display:flex;flex-wrap:wrap;gap:.85rem;margin-top:1.9rem;pointer-events:auto}

/* Découpage du texte pour les entrées */
.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.w{display:inline-block;white-space:pre}
.c{display:inline-block;will-change:transform,opacity}

/* (a) Éparpillement, écho de la poussière qui s'assemble dans le rayon */
.e-scatter .c{--kc:clamp(0,(var(--k,0) - var(--th,0))*2.6,1);opacity:var(--kc);
  transform:translate(calc((1 - var(--kc))*var(--jx,0px)),calc((1 - var(--kc))*var(--jy,0px))) rotate(calc((1 - var(--kc))*var(--jr,0deg)))}
/* (b) Montée mot par mot, écho de la lumière qui grimpe */
.e-rise .w{--kc:clamp(0,(var(--k,0) - var(--th,0))*2.8,1);opacity:var(--kc);
  transform:translateY(calc((1 - var(--kc))*26px))}
/* (c) Flou vers net, écho de la mise au point qui arrive */
.e-focus .ln{position:relative;display:block}
.e-focus .ln .soft{position:absolute;inset:0;filter:blur(11px);opacity:calc(1 - var(--kc,0));pointer-events:none}
.e-focus .ln .sharp{opacity:var(--kc,0)}
.e-focus .ln{--kc:clamp(0,(var(--k,0) - var(--th,0))*3,1);
  transform:translateY(calc((1 - var(--kc))*10px))}
/* (d) Approche depuis la profondeur */
.e-depth .inner{display:block;--kc:clamp(0,var(--k,0)*1.9,1);opacity:var(--kc);
  transform:scale(calc(.86 + .14*var(--kc)))}
/* (e) Repos : montée, puis sous-ligne, puis boutons */
.e-settle .w{--kc:clamp(0,(var(--k,0) - var(--th,0))*2.6,1);opacity:var(--kc);
  transform:translateY(calc((1 - var(--kc))*24px))}
.e-settle .band__lede{--ks:clamp(0,(var(--k,0) - .5)*3.4,1);opacity:var(--ks);
  transform:translateY(calc((1 - var(--ks))*14px))}
.e-settle .band__row{--kb:clamp(0,(var(--k,0) - .68)*3.6,1);opacity:var(--kb);
  transform:translateY(calc((1 - var(--kb))*16px))}

/* LE HÉROS RACCOURCI, 1er octobre 2026 : trois bandes au lieu de quatre.

   Le slogan de la marque quitte sa propre bande et se pose sous le
   verrouillage de la bande 1. LA ZONE DE PROTECTION DU GUIDE, page 05, vaut
   0,391 fois la hauteur du verrouillage. Le logo fait min(100 %, 520 px) de
   large et 3,8003 fois moins de haut ; la zone vaut donc la largeur divisée
   par 9,72. Le pseudo-élément ci-dessous a exactement la largeur du logo et
   un rapport de 9,2, un peu plus haut que la zone : elle est tenue à toutes
   les tailles, sans un chiffre écrit de tête. */
.band__sub--slogan{margin-top:0}
.band__sub--slogan::before{content:"";display:block;width:min(100%,520px);aspect-ratio:9.2}
.e-logo .band__sub--slogan{opacity:var(--k,1)}
/* Les noms de l'équipe, sous les boutons du repos. Ils arrivent en dernier. */
.band__noms{margin-top:1.4rem;font-size:.9rem;line-height:1.5;color:rgba(246,244,239,.86);pointer-events:auto;max-width:40ch}
.band__noms a{display:inline-block;margin-left:.35rem;font-family:var(--mono);font-size:.64rem;letter-spacing:.18em;
  text-transform:uppercase;color:#F6F4EF;text-decoration:none;border-bottom:1px solid rgba(246,244,239,.5);
  padding-bottom:2px;white-space:nowrap;position:relative}
.band__noms a:hover{border-bottom-color:#F6F4EF}
.band__noms a::after{content:"";position:absolute;left:0;right:0;top:50%;translate:0 -50%;height:46px}
.e-settle .band__noms{--kn:clamp(0,(var(--k,0) - .76)*3.6,1);opacity:var(--kn);
  transform:translateY(calc((1 - var(--kn))*12px))}

/* Le cadre signature, dans le héros */
.hero-frame{position:absolute;left:calc(var(--gut) - 1.4rem);right:34%;top:14%;bottom:14%;pointer-events:none;z-index:4}
.cnr{position:absolute;width:clamp(30px,3.4vw,48px);height:clamp(30px,3.4vw,48px);overflow:visible}
.cnr path{fill:none;stroke:rgba(246,244,239,.62);stroke-width:1.4;vector-effect:non-scaling-stroke}
.cnr--tl{left:0;top:0}
.cnr--tr{right:0;top:0;transform:scaleX(-1)}
.cnr--bl{left:0;bottom:0;transform:scaleY(-1)}
.cnr--br{right:0;bottom:0;transform:scale(-1)}
@media (max-width:1100px){.hero-frame{right:12%}}

/* Le même cadre, réutilisable sur n'importe quelle boîte */
.marks{position:absolute;inset:clamp(.5rem,1vw,.9rem);pointer-events:none;z-index:3}
.marks .cnr{width:clamp(18px,2.2vw,30px);height:clamp(18px,2.2vw,30px)}
.marks .cnr path{stroke:rgba(242,239,232,.85);stroke-width:1.2}
.marks--ink .cnr path{stroke:var(--line-strong)}

/* ============================================================
   LE SITE SOUS LE PLI
   ============================================================ */
/* Pas de fond opaque ici : la feuille de dessin et la lumière qui dérive sont
   posées derrière, et un fond plein sur main les cachait complètement. Le lin
   vient de body, les sections qui ont besoin d'un fond le déclarent elles-mêmes. */
main{position:relative;z-index:2}
/* Le vide entre deux sections était de 259 px sur un écran de 900 : presque un
   tiers d'écran de rien, entre chaque bloc de texte. Signalé par le client le
   26 août 2026, « moins de grosse espace inutile entre les textes ». Mesuré
   avant de couper, et coupé d'un tiers plutôt qu'à vue : 161 px entre deux
   sections, ce qui laisse encore la page respirer sans la faire bâiller. */
/* RYTHME RESSERRE, 19 septembre 2026, demande de Mathieu : « revois aussi les
   espaces sur tout le site, je trouve qu'il en a encore beaucoup ».
   Le remplissage d'une section valait 80,6 px a 1440, donc 161 px de BANDE
   MORTE entre deux sections avant meme leurs marges internes. Il vaut 49 px,
   donc 98 px entre deux. Mesure des treize pages avant et apres, par
   lupa-tests/espaces.mjs : 18,8 pour cent de la hauteur du site en bande
   morte, 13,3 apres, et 4797 px de hauteur en moins sans qu'une ligne de
   texte soit retiree.
   LE PLANCHER DU TELEPHONE DESCEND MOINS QUE LE PLAFOND DE L'ORDINATEUR
   (48 -> 34 px contre 81 -> 49) : un ecran de 390 px n'a jamais eu trop
   d'air, et c'est la que le texte a le plus besoin de respirer. */
.sec{position:relative;padding:clamp(2.1rem,3.4vw,3.1rem) var(--gut)}
:target,section[id],#main{scroll-margin-top:5.5rem}
.wrap{max-width:var(--maxw);margin:0 auto}
/* Les étiquettes de section utilisent le terracotta ASSOMBRI, pas le terracotta
   du guide. Mesuré le 22 août 2026 : le #B75C5A officiel donne 3,86 de contraste
   sur le crème, sous le seuil de 4,5 exigé pour du texte de cette taille. Le
   #A94F4D donne 4,63 et reste visiblement la même couleur.
   Le guide interdit de modifier les couleurs DU LOGO, page 6. Il ne dit rien
   d'un texte d'interface, et le terracotta pur reste intact partout où il est
   grand ou n'est pas du texte : le bouton, le trait du cadre, la signature,
   les étoiles des avis, l'anneau de focus. */
.kick{font-family:var(--mono);font-size:.66rem;letter-spacing:.28em;text-transform:uppercase;color:var(--accent-text);
  display:flex;align-items:center;gap:.9rem}
.kick::after{content:"";height:1px;flex:1;max-width:9rem;background:var(--line-strong)}
.h2{font-size:clamp(2.15rem,4.4vw,3.8rem);margin-top:1.1rem;max-width:15ch}
.lede{margin-top:1.05rem;max-width:56ch;color:var(--text-secondary)}

/* Trait de cote, séparateur */
.rule{display:block;width:100%;height:18px;overflow:visible}
.rule line,.rule path{stroke:var(--line-strong);stroke-width:1;fill:none;vector-effect:non-scaling-stroke}

/* --- 1. La recherche --- */
/* LA REMONTEE DE 5,5 rem N'EXISTE QUE SOUS LE HEROS. Le panneau de recherche
   ouvrait la page et mordait sur la video : c'est de la que vient ce
   margin-top negatif. Le 18 septembre 2026 Mathieu a fait descendre la
   recherche sous l'equipe et sous les trois chemins, et la remontee est
   devenue un defaut : le panneau passait 88 px PAR-DESSUS les trois vignettes,
   mesure. On ne remonte donc que quand la section precedente est le heros. */
.search{position:relative;z-index:3;padding:0 var(--gut) clamp(3rem,6vw,5rem);
  margin-top:clamp(0rem,3vw,2.6rem)}
.hero + .search,.static-hero + .search{margin-top:-5.5rem}
.search__panel{max-width:var(--maxw);margin:0 auto;background:var(--panel);border:1px solid var(--line);
  padding:clamp(1.5rem,3vw,2.6rem);box-shadow:0 26px 60px -34px rgba(21,26,33,.5)}
.search__top{display:flex;align-items:baseline;justify-content:space-between;gap:1rem;flex-wrap:wrap;margin-bottom:1.4rem}
/* Les quatre menus ne portent pas des mots de même longueur : « Salles de bain »
   se faisait couper quand les colonnes étaient égales. Chacune a sa part. */
.search__grid{display:grid;gap:.9rem;grid-template-columns:2fr .85fr .85fr 1.05fr 1.3fr auto}
@media (max-width:1200px){.search__grid{grid-template-columns:1fr 1fr}.search__grid .btn{grid-column:1/-1}}
@media (max-width:560px){.search__grid{grid-template-columns:1fr}}
.field{position:relative;display:block}
.field input,.field select{width:100%;background:var(--canvas);border:1px solid var(--field-line);
  padding:.85rem .95rem;font-weight:400;font-size:.95rem;border-radius:0;
  transition:border-color .3s var(--ease),box-shadow .3s var(--ease);appearance:none}
.field select{background-image:linear-gradient(45deg,transparent 50%,var(--text-secondary) 50%),linear-gradient(135deg,var(--text-secondary) 50%,transparent 50%);
  background-position:calc(100% - 18px) 50%,calc(100% - 13px) 50%;background-size:5px 5px,5px 5px;background-repeat:no-repeat;padding-right:2.2rem}
.field input:hover,.field select:hover{border-color:var(--text-secondary)}
.field input::placeholder{color:var(--text-secondary)}
.field input:focus,.field select:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px rgba(183,92,90,.16)}
.search__note{margin-top:1.2rem;padding:1rem 1.15rem;background:var(--canvas);border-left:2px solid var(--accent);
  font-size:.95rem;color:var(--text-secondary);display:none}
.search__note.on{display:block}
.search__note a{color:var(--accent-text);text-underline-offset:3px}

/* --- 2. La courtière --- */
.broker{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(2rem,5vw,5rem);align-items:center}
@media (max-width:900px){.broker{grid-template-columns:1fr}}
/* margin-block:0 est ici depuis le 23 août, en remplacement d'un style="margin:0"
   qui était écrit dans le HTML. Un style en ligne bat toutes les règles de cette
   feuille : il empêchait le décalage de la photo de s'appliquer, et il aurait
   bloqué n'importe quel réglage futur de marge sur cette figure. */
.broker__figure{position:relative;max-width:min(100%,440px);margin-block:0;margin-inline:auto;padding-top:2.6rem}
.broker__figure img{width:100%;position:relative;z-index:2}
/* Legende de la photo : depuis le virage equipe du 23 aout, le titre de la
   section parle des trois courtiers, donc la personne en photo doit se nommer. */
.broker__figure figcaption{position:relative;z-index:2;margin-top:.9rem;font-family:var(--mono);
  font-size:.66rem;letter-spacing:.16em;text-transform:uppercase;color:var(--text-secondary)}
.broker__plate{position:absolute;left:0;right:0;bottom:0;top:2.6rem;background:var(--panel);z-index:1}
.broker__plate .marks{inset:.8rem}

/* --- Les trois portraits en escalier, accueil, 26 août 2026 ---------------
   Remplace le portrait de Marie-Claude seule. L'escalier est un choix, pas un
   hasard : la rangée de trois cartes existe déjà sur Vendre et Acheter, et le
   client demandait dans le même souffle un site moins répétitif. Ici les
   portraits descendent en diagonale et le nom se pose dans le vide laissé à
   côté, ce qui remplit une colonne haute et étroite sans allonger la section. */
.trio{position:relative;max-width:min(100%,440px);margin-inline:auto;padding:2.6rem 0 1.6rem}
.trio__plate{position:absolute;left:0;right:0;top:0;bottom:0;background:var(--panel);z-index:1}
.trio__plate .marks{inset:.8rem}
.trio__liste{position:relative;z-index:2;display:grid;gap:clamp(.9rem,1.8vw,1.4rem);padding:0 1.4rem}
.trio__p{margin:0;display:grid;grid-template-columns:auto 1fr;align-items:center;
  gap:clamp(.9rem,1.8vw,1.25rem)}
/* L'escalier. Chaque portrait part un cran plus à droite que le précédent.
   Le pas est volontairement court : mesuré à 5,2rem, le rôle du troisième
   (« Résidentiel et commercial », le plus long des trois) passait sur deux
   lignes et touchait le bord du cadre. Le pas se règle ici, jamais en
   raccourcissant les libellés, qui sont ceux des cartes de Vendre et Acheter. */
.trio__p:nth-child(2){margin-left:clamp(.9rem,2.2vw,1.7rem)}
.trio__p:nth-child(3){margin-left:clamp(1.8rem,4.4vw,3.4rem)}
.trio__p a{display:block;position:relative;width:clamp(92px,12vw,122px);
  transition:transform .5s var(--ease)}
.trio__p a:hover{transform:translateY(-4px)}
.trio__p img{width:100%;display:block}
.trio__p figcaption{display:grid;gap:.28rem;min-width:0}
.trio__nom{font-weight:600;font-size:clamp(.86rem,1.15vw,.98rem);line-height:1.25;color:var(--text-primary)}
.trio__role{font-family:var(--mono);font-size:.6rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--text-secondary);line-height:1.35}
/* Sous 900px la section passe en une colonne : l'escalier se redresse, sinon le
   troisième portrait part chercher le bord droit de l'écran. */
@media (max-width:900px){
  .trio{max-width:min(100%,420px)}
  .trio__p:nth-child(2),.trio__p:nth-child(3){margin-left:0}
}
@media (prefers-reduced-motion:reduce){
  .trio__p a,.trio__p a:hover{transition:none;transform:none}
}
.broker__sig{font-family:var(--mark);font-weight:500;font-size:clamp(1.7rem,2.8vw,2.5rem);margin-top:1.8rem;color:var(--accent)}
.broker p + p{margin-top:1.05rem}
.broker__facts{display:flex;flex-wrap:wrap;gap:.6rem;margin-top:1.8rem}
.tag{font-family:var(--mono);font-size:.64rem;letter-spacing:.16em;text-transform:uppercase;
  border:1px solid var(--line-strong);padding:.5rem .8rem;color:var(--text-secondary)}

/* --- 3. Le moment Lupa --- */
.lupa{background:var(--ink-deep);color:#EFECE4}
.lupa .kick{color:var(--accent-muted)}
.lupa .kick::after{background:rgba(239,236,228,.26)}
.lupa .lede{color:rgba(239,236,228,.72)}

/* ==== L'ORBITE, 27 août 2026 ==============================================
   Elle remplace le lecteur, la photo de salon avec ses quatre points. Le
   client a apporté le composant « Radial Orbital Timeline » de 21st.dev, qui
   est écrit en React avec Tailwind et shadcn/ui ; ceci en est la traduction
   en CSS et en JavaScript ordinaire, sans une seule librairie ajoutée.

   LES QUATRE OBSERVATIONS SONT CELLES DU LECTEUR, MOT POUR MOT. Elles ont
   survécu à trois formes successives, ce sont les textes du client, et elles
   ne se retouchent pas. Ce qui est neuf : chaque point porte une photo qui
   montre sa preuve, et les points se relient deux à deux.

   Tout est préfixé `orb` : rien ici ne peut entrer en collision avec le
   reste de la feuille, qui est partagée par les treize pages.
   ========================================================================= */

/* La scène carrée qui porte l'orbite. La taille suit l'écran : le composant
   d'origine est en pleine hauteur d'écran avec un rayon fixe de 200 px, ce
   qui déborde d'un téléphone. */
/* LA PHOTO EST AU CENTRE DE L'ORBITE, ET L'ORBITE GRANDIT AUTOUR D'ELLE.
   Demande du client le 27 août au soir : « l'animation prend trop de place ».
   Elle en prenait beaucoup, en effet : la photo vivait dans la fiche, sous
   l'orbite, et lui ajoutait sa hauteur entière. En la posant au centre, la
   fiche n'est plus que du texte, et la section perd environ 350 px de haut
   malgré l'orbite agrandie. Le cœur terracotta s'efface derrière elle. */
/* L'ORBITE ENTIÈRE A GRANDI LE 28 AOÛT AU SOIR, deuxième demande du client
   dans la même soirée : « même l'outil au complet on peut le grossir, il est
   trop petit ». Fermée : de 30 à 34 rem sur ordinateur, et 86vw au lieu de
   72 sur téléphone. Ouverte : de 38 à 40 rem, et 92vw. Le cœur, les ondes et
   le mot suivent, plus bas. L'ouverte doit TOUJOURS dépasser la fermée d'au
   moins 20 px à toutes les largeurs, c'est mesuré par `orbite.mjs`. */
.orb{--taille:clamp(19rem,86vw,34rem);
  position:relative;width:var(--taille);height:var(--taille);
  margin:clamp(1.8rem,4vw,2.8rem) auto 0;
  /* AUCUNE SÉLECTION DE TEXTE DANS L'ORBITE, retour du client du 28 août :
     sur téléphone, un doigt tenu deux secondes sur un point passait en mode
     sélection, et la photo comme les orbes se retrouvaient surlignées en
     bleu. Rien ne se lit dans ce cercle, tout s'y touche : la sélection n'y a
     aucun rôle. La fiche de lecture, elle, vit SOUS l'orbite et reste
     sélectionnable. Le -webkit-touch-callout coupe le menu d'appui long
     d'iOS sur la photo du centre. */
  -webkit-user-select:none;user-select:none;
  -webkit-touch-callout:none;
  -webkit-tap-highlight-color:transparent;
  transition:width .62s var(--ease),height .62s var(--ease)}
/* L'orbite ouverte. L'anneau garde le même retrait, donc son rayon grandit
   avec la boîte et les quatre points s'écartent pour laisser la place. */
.orb[data-ouvert="1"]{--taille:clamp(23rem,92vw,40rem)}
/* Le rayon n'est PAS un jeton calculé ici : le script le lit sur l'anneau
   réel. C'est la seule façon d'être certain que les points tombent sur le
   cercle qu'on voit, à toutes les largeurs, même si ce retrait change. */
.orb__anneau{position:absolute;inset:clamp(2.6rem,7vw,3.4rem);
  border:1px solid rgba(240,238,232,.16);border-radius:50%}

/* Meme raison que pour le bouton : le coeur retrecit quand la photo arrive,
   donc son centrage doit vivre dans `translate` et pas dans `transform`. */
.orb__coeur{position:absolute;left:50%;top:50%;translate:-50% -50%;
  width:clamp(4.6rem,14vw,6.1rem);height:clamp(4.6rem,14vw,6.1rem);
  border-radius:50%;display:grid;place-items:center;
  background:radial-gradient(circle at 40% 35%,#C9706E,#A04846 62%,#8F3D3B);
  box-shadow:0 0 0 1px rgba(240,238,232,.14),0 10px 34px rgba(0,0,0,.45)}
.orb__coeur svg{width:46%;height:46%;display:block}
.orb__coeur svg circle,.orb__coeur svg path{stroke:#F6F4EF;stroke-width:2.4;
  fill:none;stroke-linecap:round}
.orb__mot{position:absolute;left:50%;top:calc(50% + clamp(3.1rem,8.5vw,3.9rem));
  transform:translateX(-50%);font-size:.66rem;letter-spacing:.16em;
  text-transform:uppercase;color:rgba(240,238,232,.62);white-space:nowrap}

/* Les deux ondes remplacent le `animate-ping` de l'original, mais lentement :
   c'est une maison qu'on regarde, pas un signal radar. */
.orb__onde{position:absolute;left:50%;top:50%;
  width:clamp(4.6rem,14vw,6.1rem);height:clamp(4.6rem,14vw,6.1rem);
  margin:0;border-radius:50%;border:1px solid rgba(207,149,145,.5);
  transform:translate(-50%,-50%);pointer-events:none;
  /* Les deux ondes sont retirees le 17 septembre 2026. C etait un battement
     decoratif qui n annoncait rien : le coeur de l orbite se clique deja, et
     le curseur le dit. L ELEMENT EST MASQUE, pas seulement fige : c est
     l animation qui portait son opacite, donc l enlever seule laissait un
     anneau opaque immobile au milieu de l outil. */
  display:none}

.orb__piste{position:absolute;inset:0}
/* `--x` et `--y` sont posés par le script, en pixels.
   PREMIÈRE VERSION ÉCARTÉE : la position se calculait en CSS avec `cos()` et
   `sin()`. C'est élégant, mais ces fonctions sont récentes, et si elles ne
   sont pas comprises le transform devient invalide et LES QUATRE POINTS
   S'EMPILENT AU CENTRE, sans la moindre erreur nulle part. */
.orb__noeud{position:absolute;left:50%;top:50%;width:0;height:0;
  transform:translate(var(--x,0px),var(--y,0px))}

/* `translate` EN PROPRIETE, PAS EN `transform`, ET CE N'EST PAS UN DETAIL.
   Le navigateur compose dans cet ordre : translate, rotate, scale, transform.
   Avec `transform:translate(-50%,-50%)` et `scale:1.24`, le deplacement est
   applique AVANT l'agrandissement, donc il est multiplie par 1,24 : le point
   ouvert se retrouvait decale de 5 px vers le haut a gauche. Mesure par
   `orbite.mjs`, qui a vu un point a 147 px du centre pour un rayon de 142.
   En propriete `translate`, l'agrandissement ne le touche plus. */
.orb__btn{position:absolute;left:50%;top:50%;translate:-50% -50%;
  width:2.6rem;height:2.6rem;border-radius:50%;cursor:pointer;
  display:grid;place-items:center;padding:0;
  background:var(--ink-deep);border:1px solid rgba(240,238,232,.42);
  color:#F0EEE8;font:inherit;
  transition:background .3s var(--ease),border-color .3s var(--ease),
             box-shadow .3s var(--ease),scale .3s var(--ease)}
.orb__btn:hover{border-color:var(--accent-muted);background:#3F3D3B}
.orb__btn:focus-visible{outline:2px solid var(--accent-muted);outline-offset:3px}
.orb__pt{width:.5rem;height:.5rem;border-radius:50%;
  background:var(--accent-muted);transition:background .3s var(--ease)}

/* `scale` est une propriété à part, PAS un `transform` : le transform du
   bouton porte déjà son centrage, et le piège déjà payé dans ce projet est
   qu'un second transform efface le premier. */
.orb__noeud[data-ouvert="1"] .orb__btn{background:#F0EEE8;border-color:#F0EEE8;
  scale:1.24;box-shadow:0 0 0 6px rgba(240,238,232,.12)}
.orb__noeud[data-ouvert="1"] .orb__pt{background:var(--accent-hover)}
.orb__noeud[data-lie="1"] .orb__btn{border-color:var(--accent);background:#4A3634}
.orb__noeud[data-lie="1"] .orb__pt{background:#F0EEE8}

.orb__nom{position:absolute;left:50%;top:calc(50% + 1.85rem);
  transform:translateX(-50%);white-space:nowrap;
  font-size:.7rem;letter-spacing:.06em;color:rgba(240,238,232,.72);
  transition:color .3s var(--ease)}
.orb__noeud[data-ouvert="1"] .orb__nom{color:#F0EEE8}
.orb__noeud[data-lie="1"] .orb__nom{color:var(--accent-muted)}

/* LE PANNEAU DE LECTURE EST FIXE, SOUS L'ORBITE, et c'est un choix mesuré.
   Dans l'original la fiche s'ouvre juste sous le nœud, en absolu. Avec un
   point qui tourne, elle sort de l'écran une fois sur deux, et à 390 px elle
   déborde toujours. C'était déjà le choix du lecteur qu'elle remplace : le
   point reste en place, la note va où elle est lisible. */
.orb__lecture{max-width:34rem;margin:clamp(1.6rem,4vw,2.4rem) auto 0;
  min-height:9.5rem;text-align:left}
/* LE FOND FONCE LE CHARCOAL, IL NE L'ÉCLAIRCIT PAS, et c'est mesuré, pas un
   goût. Un premier essai en crème à 5,5 pour cent paraissait anodin : il
   éclaircissait le fond juste assez pour faire tomber le terracotta clair de
   4,92 à 4,22, sous le seuil. Deux issues, inventer un terracotta plus pâle
   hors du guide de normes, ou foncer le fond. On fonce, la palette reste
   celle de la cliente, et le contraste remonte à 5,63. */
.orb__fiche{background:rgba(0,0,0,.18);border:1px solid rgba(240,238,232,.16);
  border-radius:3px;padding:clamp(1.1rem,3vw,1.5rem)}
/* Le rapport fixe et le fond sombre évitent que la fiche saute de hauteur
   pendant que la photo arrive. */
/* LA PHOTO DU CENTRE. Ronde, parce que tout le reste de la section l'est :
   une photo carrée au milieu d'une orbite se lit comme une erreur.
   `scale` et non `width` : on anime une propriété que le navigateur compose,
   donc l'apparition reste fluide pendant que la boîte de l'orbite grandit. */
/* AGRANDIE LE 27 AOÛT AU SOIR, demande du client : « on ne voit pas bien ».
   Elle passait de 208 à 336 px de diamètre à 1440, soit 61 pour cent de plus,
   ET SANS REPRENDRE UN SEUL PIXEL DE HAUTEUR : l'orbite ne change pas de
   taille, c'est le vide entre la photo et les points qui est récupéré.

   AGRANDIE LE 28 AOÛT AU SOIR, demande du client : « il est difficile de
   voir ce que c'est pour certaines ». La photo se mesure maintenant EN PART
   DE L'ORBITE, pas en part de l'écran : une part d'écran donnait 164 px sur
   téléphone et cassait aux largeurs moyennes, où l'orbite est presque aussi
   large que l'écran. 57 % de l'orbite partout, 62 % sur ordinateur où les
   points ont plus de marge, et l'orbite ouverte d'ordinateur passe de 36 à
   38 rem pour donner l'espace. Téléphone : 164 devient 210 px. Ordinateur :
   336 devient 377 px. La seule règle qui compte est mesurée par
   `orbite.mjs` : la photo ne touche jamais le bord intérieur des points. */
.orb__centre{position:absolute;left:50%;top:50%;
  width:clamp(9rem,calc(var(--taille)*.62),24rem);
  height:clamp(9rem,calc(var(--taille)*.62),24rem);
  border-radius:50%;object-fit:cover;background:rgba(0,0,0,.3);
  translate:-50% -50%;scale:0;opacity:0;pointer-events:none;
  box-shadow:0 0 0 1px rgba(240,238,232,.18),0 14px 40px rgba(0,0,0,.5);
  transition:scale .5s var(--ease),opacity .38s var(--ease)}
.orb[data-ouvert="1"] .orb__centre{scale:1;opacity:1}
/* Le cœur s'efface derrière elle, il ne se bat pas avec. */
.orb__coeur,.orb__mot{transition:opacity .34s var(--ease),scale .5s var(--ease)}
.orb[data-ouvert="1"] .orb__coeur{opacity:0;scale:.6}
.orb[data-ouvert="1"] .orb__mot{opacity:0}
/* Et les ondes se taisent : elles battaient autour du cœur, pas de la photo. */
.orb[data-ouvert="1"] .orb__onde{opacity:0;transition:opacity .3s linear}
.orb__cat{font-size:.66rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--accent-muted);font-weight:500;margin:0 0 .5rem}
.orb__t{font-family:var(--display);font-weight:400;font-size:1.28rem;
  margin:0 0 .6rem;color:#F0EEE8;line-height:1.25}
.orb__note{margin:0;line-height:1.62;color:rgba(240,238,232,.86)}
.orb__lien{margin:1rem 0 0;padding-top:.9rem;
  border-top:1px solid rgba(240,238,232,.14)}
.orb__lien h4{margin:0 0 .5rem;font-size:.66rem;letter-spacing:.16em;
  text-transform:uppercase;color:rgba(240,238,232,.62);font-weight:500}
.orb__lien p{margin:0 0 .7rem;line-height:1.6;font-size:.92rem;
  color:rgba(240,238,232,.78)}
.orb__aller{font:inherit;font-size:.84rem;cursor:pointer;background:transparent;
  color:var(--accent-muted);border:1px solid rgba(240,238,232,.3);
  border-radius:2px;padding:.42rem .8rem;
  transition:color .25s var(--ease),border-color .25s var(--ease),
             background .25s var(--ease)}
.orb__aller:hover{color:#F0EEE8;border-color:var(--accent-muted);
  background:rgba(240,238,232,.08)}
.orb__aller:focus-visible{outline:2px solid var(--accent-muted);outline-offset:2px}
.orb__aller span{color:rgba(240,238,232,.55);margin-left:.35rem}

/* L'invite. Règle du site depuis le 26 août : le geste ne doit RIEN demander
   à deviner. Elle dit aussi ce qui est propre à cette forme, que les points
   s'allument entre eux. */
.orb__invite{text-align:center;color:rgba(240,238,232,.6);
  padding:clamp(1.4rem,3vw,2rem) 0;line-height:1.6;margin:0}
.orb__invite .surTel{display:none}
@media (hover:none){
  .orb__invite .surSouris{display:none}
  .orb__invite .surTel{display:inline}
}

/* LA LISTE DE SECOURS, ET ELLE N'EST PAS DÉCORATIVE.
   Les quatre observations sont écrites dans la page, pas dans le script :
   c'est elle que le script lit pour bâtir l'orbite, puis qu'il masque. Si le
   JavaScript ne se charge pas, on lit donc les quatre observations en liste
   au lieu de regarder un cercle vide. Elle est stylée pour de vrai, parce
   qu'un visiteur pourrait la voir. */
.orb__source{list-style:none;margin:clamp(1.8rem,4vw,2.6rem) auto 0;padding:0;
  max-width:34rem;text-align:left;display:grid;gap:1.1rem}
/* CES DEUX LIGNES NE SONT PAS FACULTATIVES, et leur absence a produit un vrai
   défaut, vu à l'œil et raté par le test. L'attribut `hidden` ne fait que
   poser `display:none` depuis la feuille du navigateur : n'importe quelle
   règle d'auteur qui déclare un `display` le bat. Les deux règles ci-dessus
   en déclarent un, donc `hidden` ne masquait rien et la liste de secours
   restait affichée SOUS l'orbite, en double du contenu des fiches.
   Le test disait pourtant vrai : il vérifiait l'ATTRIBUT et pas l'EFFET.
   Il mesure maintenant le `display` calculé. */
.orb__source[hidden]{display:none}
.orb[hidden]{display:none}
.orb__source li{padding-bottom:1.1rem;border-bottom:1px solid rgba(240,238,232,.14)}
.orb__source li:last-child{border-bottom:0;padding-bottom:0}
.orb__source b{display:block;font-family:var(--display);font-weight:400;
  font-size:1.2rem;color:#F0EEE8;margin-bottom:.35rem}
.orb__source span{display:block;line-height:1.6;color:rgba(240,238,232,.82)}

/* Sous 430 px, les noms sous les points se marchent dessus : « La porte
   patio » fait 92 px de large et deux points voisins ne sont plus qu'à 70 px
   l'un de l'autre en bas de l'orbite. Le nom part donc dans la fiche, et le
   bouton grossit pour rester une bonne cible au doigt. */
@media (max-width:430px){
  .orb__nom{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
    overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
  .orb__btn{width:2.9rem;height:2.9rem}
}
/* Sous 720 px, la photo prend 55 % de l'orbite et non 62 : l'orbite ouverte
   y est presque aussi large que l'écran, donc les points n'ont pas la marge
   de l'ordinateur, et le point OUVERT y est le plus gourmand de tous, un
   bouton de 2,9 rem gonflé de 24 %. À 57 % la photo frôlait son bord au
   pixel près, mesuré par `orbite.mjs`. */
@media (max-width:720px){
  .orb__centre{width:clamp(9rem,calc(var(--taille)*.55),24rem);
    height:clamp(9rem,calc(var(--taille)*.55),24rem)}
}
/* `--len` vit ICI et non sur `.pin`, parce que la note en a besoin elle aussi
   depuis qu'elle a été sortie du point, et qu'elle n'est plus sa descendante. */
.reader{position:relative;margin-top:clamp(2rem,4vw,3.2rem);aspect-ratio:16/9;overflow:hidden;background:#0E1218;
  --len:clamp(48px,7vw,120px);
  border:1px solid rgba(239,236,228,.14);touch-action:manipulation;user-select:none}
/* ATTENTION : `--hz` DOIT rester dans cette liste. Le zoom au survol est porté
   par `.zoomable{transition:--hz .85s}`, plus bas. Cette règle-ci est plus
   spécifique (0,1,1 contre 0,1,0), donc elle REMPLACE la liste au complet :
   sans `--hz` ici, la variable n'est plus animée et la photo du moment Lupa
   grossit d'un coup sec au survol. Signalé par le client le 25 août 2026.
   Aucune erreur nulle part, aucun test ne tombait : `transition` ne se cumule
   pas entre règles, la plus forte gagne et efface le reste.
   `transform` reste volontairement HORS de la liste : c'est `--z` qui l'écrit
   au défilement, et il doit suivre le doigt sans retard. */
.reader img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  filter:saturate(calc(.82 + .18*var(--h,0))) brightness(calc(.84 + .16*var(--h,0)));
  transition:filter .18s linear, --hz .85s var(--ease)}
.reader__veil{position:absolute;inset:0;background:rgba(14,18,24,.4);opacity:calc(1 - .55*var(--h,0));transition:opacity .18s linear}

/* --- Les points et leurs notes, refaits en survol le 26 août 2026 ----------
   `--n` garde le sens qu'il avait : l'ARRIVÉE du point quand la section entre à
   l'écran, en séquence. Ce qui est nouveau, c'est que le trait et la note ne
   suivent plus `--n` mais l'état du point : survol, focus clavier, ou touche.
   Tout le survol est en CSS, comme sur les bulles ; le script ne sert qu'au
   tactile, qui n'a pas de survol, et au compte des quatre. */
.pins{position:absolute;inset:0;z-index:5}
.pin{position:absolute;left:var(--x);top:var(--y);
  z-index:5;background:none;border:0;padding:0;cursor:pointer;color:inherit}
/* La zone à viser fait 44 px, le minimum tactile, alors que le point n'en fait
   que 10. Elle est invisible et centrée sur le point. Sans elle, le point est
   une cible de 10 px au doigt, donc une cible qu'on rate. */
.pin::before{content:"";position:absolute;left:50%;top:50%;width:44px;height:44px;
  transform:translate(-50%,-50%)}
/* LE POINT DOIT SE VOIR DE LOIN, ET LA PREMIÈRE VERSION NE SE VOYAIT PAS.
   Un rond de 10 px, bordure rose pâle sur fond translucide, disparaissait
   littéralement dans le mur crème de la photo : à la capture, on devinait deux
   points sur quatre. C'était le maintien enfoncé qui revenait par la fenêtre,
   un geste à deviner. Le point est donc plein, dans le terracotta de la marque,
   cerclé de crème pour tenir sur un fond clair comme sur un fond sombre, et
   posé sur une ombre. Il se voit sur le mur, sur le plancher et dans le jardin. */
.pin .dot{position:absolute;left:-8px;top:-8px;width:16px;height:16px;border-radius:50%;
  background:var(--accent);border:2px solid rgba(240,238,232,.92);
  box-shadow:0 2px 10px rgba(5,8,14,.55);
  opacity:var(--n,0);transform:scale(calc(.3 + .7*var(--n,0)));
  /* `transform` DOIT rester dans cette liste : c'est le survol qui l'écrit
     ensuite, et sans elle le point saute d'un coup au lieu de grossir. */
  transition:background .3s var(--ease),border-color .3s var(--ease),transform .3s var(--ease)}
/* Le halo qui respire. Il est sur un pseudo-élément et n'anime que opacity et
   transform, donc il ne coûte rien. C'est LUI qui dit au visiteur qu'il y a
   quelque chose ici, et il bat en crème plutôt qu'en rose pâle pour la même
   raison que le point : le rose pâle se noie dans une pièce claire. */
.pin .dot::after{content:"";position:absolute;inset:-9px;border:2px solid rgba(240,238,232,.75);border-radius:50%;
  opacity:0;animation:respire 3.4s var(--ease) infinite}
.pin:nth-child(2) .dot::after{animation-delay:-.9s}
.pin:nth-child(3) .dot::after{animation-delay:-1.8s}
.pin:nth-child(4) .dot::after{animation-delay:-2.6s}
@keyframes respire{
  0%{opacity:0;transform:scale(.72)}
  35%{opacity:.55}
  100%{opacity:0;transform:scale(1.5)}
}
.pin:hover .dot,.pin:focus-visible .dot,.pin.ouvert .dot{background:#F0EEE8;border-color:var(--accent);transform:scale(1.25)}
.pin:hover .dot::after,.pin:focus-visible .dot::after,.pin.ouvert .dot::after{animation:none;opacity:0}
.pin:focus-visible{outline:2px solid var(--accent-muted);outline-offset:12px;border-radius:50%}

/* Le trait ne se dessine plus à l'arrivée : il part du point vers sa note au
   moment où on la demande. `--n` le garde à zéro tant que le point n'est pas né. */
/* Le trait est crème cerclé de sombre, pour la même raison que le point : en
   rose pâle d'un pixel, il disparaissait dans le mur et la note semblait
   flotter sans lien avec ce qu'elle désigne. */
.pin .line{position:absolute;top:0;height:2px;width:var(--len);background:rgba(240,238,232,.95);
  box-shadow:0 0 0 1px rgba(5,8,14,.35);
  opacity:0;transition:opacity .3s var(--ease),transform .45s var(--ease)}
.pin--r .line{left:0;transform:scaleX(0);transform-origin:left}
.pin--l .line{right:0;transform:scaleX(0);transform-origin:right}
.pin:hover .line,.pin:focus-visible .line,.pin.ouvert .line{opacity:calc(var(--n,0)*.85);transform:scaleX(var(--n,0))}

.notes{position:absolute;inset:0;pointer-events:none;z-index:4}
.note{position:absolute;left:var(--x);top:var(--y);margin:0;width:min(26ch,34vw);
  margin-top:-1.1em;
  font-family:var(--mono);font-size:clamp(.56rem,.7vw,.72rem);line-height:1.55;letter-spacing:.03em;color:#F0EEE8;
  background:rgba(8,11,16,.72);border:1px solid rgba(206,149,145,.34);backdrop-filter:blur(10px);padding:.5rem .7rem;
  text-shadow:0 1px 3px rgba(5,8,14,.85);
  opacity:0;visibility:hidden;transform:translateY(6px);
  transition:opacity .38s var(--ease),transform .38s var(--ease),visibility .38s var(--ease)}
.note--r{margin-left:calc(var(--len,clamp(48px,7vw,120px)) + .75rem)}
.note--l{margin-left:calc(-1 * (var(--len,clamp(48px,7vw,120px)) + .75rem));transform:translate(-100%,6px);text-align:right}
.note.on{opacity:1;visibility:visible;transform:none}
.note--l.on{transform:translateX(-100%)}
/* L'invite au repos. Sur ordinateur elle se pose sous l'image, discrète ; sur
   téléphone elle occupe la case des notes et se fait recouvrir par la première
   note ouverte. */
/* L'invite est une pastille et non du texte nu : posée à même une photo claire,
   du texte crème translucide ne se lisait pas. Même traitement que les petites
   étiquettes sur vidéo ailleurs sur le site. */
.reader__invite{position:absolute;left:50%;bottom:1rem;transform:translateX(-50%);margin:0;
  padding:.5rem .9rem;text-align:center;
  font-family:var(--mono);font-size:.62rem;letter-spacing:.16em;text-transform:uppercase;
  color:#F0EEE8;background:rgba(8,11,16,.62);border:1px solid rgba(240,238,232,.28);
  backdrop-filter:blur(10px);text-shadow:0 1px 3px rgba(5,8,14,.9);
  transition:opacity .4s var(--ease)}
.reader.explore .reader__invite{opacity:0}
.reader__invite .surTel{display:none}
@media (hover:none){
  .reader__invite .surSouris{display:none}
  .reader__invite .surTel{display:inline}
}
/* La pastille « Maintenez enfoncé » vivait ici. Elle a été retirée avec le
   maintien enfoncé le 22 août 2026, décision du client : les quatre annotations
   se dessinent maintenant toutes seules à l'arrivée de la section.
   ELLE AVAIT SERVI DE LEÇON, ET LA LEÇON RESTE : sa règle de base était écrite
   APRÈS son exception téléphone, et comme une parenthèse de largeur ne pèse pas
   plus lourd dans la cascade, l'exception était perdue. « top » et « bottom »
   devenaient actifs ensemble sur un élément en position absolue, donc il
   s'étirait de l'un à l'autre, 363 px de haut au lieu de 46, et cachait toute
   la photo. Le même piège vivait sur `.faq-grid__head`, plus bas, où il est
   commenté aussi. `node lupa-tests/balayage-cascade.mjs 390` les détecte. */
@media (max-width:720px){
  /* L'image était recadrée en portrait et les annotations posées par-dessus :
     on ne voyait plus qu'un bout de mur vide, et les meubles disparaissaient.
     Sur téléphone l'image garde sa forme entière et les annotations passent
     dessous, en liste. La pièce se voit au complet. */
  /* overflow:hidden et non visible depuis le 24 août : le zoom au défilement
     est arrivé APRÈS cette règle, et son agrandissement débordait du cadre,
     l'image sortait par les côtés. Vu sur le vrai téléphone d'un ami du
     client. Rien n'est coupé pour autant : la hauteur suit le contenu, donc
     les annotations en liste dessous restent entières. */
  .reader{aspect-ratio:auto;overflow:visible;border:0;background:none}
  .reader img{position:relative;width:100%;height:auto;aspect-ratio:16/9;
    object-fit:cover;object-position:56% center;border:1px solid rgba(239,236,228,.14)}
  /* Le voile et les points couvrent la PHOTO seule, pas la zone des notes qui
     vient dessous : d'où la hauteur en padding-bottom plutôt que `inset:0`. */
  .reader__veil{bottom:auto;height:0;padding-bottom:56.25%;border:0}
  .pins{bottom:auto;height:0;padding-bottom:56.25%}
  /* Les points RESTENT sur l'image et se touchent, c'est la demande du client.
     Ce sont les notes qui descendent : une note de trois lignes posée sur une
     image de 219 px de haut couvrirait la moitié de la pièce. Elles sont donc
     toutes empilées dans la MÊME case sous la photo, une seule visible à la
     fois, ce qui donne une zone de hauteur fixe où rien ne saute quand on
     passe d'un point à l'autre. */
  .notes{position:static;display:grid;margin-top:.7rem;min-height:5.2rem}
  .note,.reader__invite{grid-area:1/1}
  .note{position:static;width:auto;max-width:none;margin:0;text-align:left;font-size:.68rem;
    transform:translateY(6px)}
  .note--l,.note--r{margin-left:0;text-align:left}
  .note--l{transform:translateY(6px)}
  .note--l.on,.note.on{transform:none}
  .reader__invite{position:static;align-self:center;padding:.7rem 0;
    border:1px dashed rgba(239,236,228,.22)}
  /* Mouvement réduit : les quatre notes sont montrées ensemble, donc elles ne
     peuvent plus partager une case. Elles reprennent le flux et s'empilent. */
  .reader.tout .notes{display:block;min-height:0}
  .reader.tout .note{margin-bottom:.4rem}
  .reader.tout .reader__invite{display:none}
  /* Le trait qui relie le point à sa note n'a plus de note à rejoindre sur
     l'image : il ne sert plus à rien et il salirait la photo. */
  .pin .line{display:none}
}
@media (max-width:760px){
  .nav{padding:.85rem 1.1rem}
  .nav__sub{display:none}
  /* 34 px de haut -> 129,2 px de large, 1,7 fois le minimum du guide. Le
     minimum est une LARGEUR de 78 px, pas une taille de police : verifie dans
     le PDF le 17 septembre, ou le filet rouge de la page 07 mesure la largeur
     du verrouillage. Le rembourrage passe a .85rem (13,6 px) pour couvrir la
     zone de protection de 0,391 x 34 = 13,3 px. */
  .nav__logo{height:34px;width:calc(34px * 3.8003)}
  .nav .btn{font-size:.66rem;padding:.62rem .85rem;letter-spacing:.1em;white-space:nowrap}
}
.reader__done{margin-top:1.4rem;font-family:var(--display);font-weight:600;font-size:clamp(1.1rem,1.7vw,1.45rem);letter-spacing:-.01em;
  opacity:0;transform:translateY(10px);transition:opacity .8s var(--ease),transform .8s var(--ease)}
.reader__done.on{opacity:1;transform:none}

/* --- 4. Comment ça se passe --- */
.steps{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(1.4rem,2.6vw,2.4rem);margin-top:clamp(2.4rem,4vw,3.4rem)}
@media (max-width:880px){.steps{grid-template-columns:1fr}}
.step__media{position:relative;aspect-ratio:4/3;overflow:hidden;background:var(--panel)}
/* Même piège que sur `.reader img` ci-dessus, et il cachait un second défaut.
   Cette règle transitionnait `transform` sur 1,2 s, pour le survol de la ligne
   suivante, qui a été neutralisé plus bas le 24 août. Depuis, `transform` est
   écrit par `--z` au défilement : la transition faisait donc TRAÎNER le zoom
   d'une seconde et deux dixièmes derrière le doigt, sans que rien ne le
   signale. Elle est remplacée par `--hz`, qui est ce qu'il fallait animer. */
.step__media img{width:100%;height:100%;object-fit:cover;transition:--hz .85s var(--ease)}
.step:hover .step__media img{transform:scale(1.045)}
.step__frame{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
.step__frame path{fill:none;stroke:rgba(242,239,232,.7);stroke-width:1;vector-effect:non-scaling-stroke}
/* Trois cartes identiques alignées, c'est un gabarit. Décalées en escalier,
   c'est une progression, et ça dit la même chose que le texte. */
@media (min-width:881px){
  .step:nth-child(2){margin-top:clamp(1.8rem,3.4vw,3.4rem)}
  .step:nth-child(3){margin-top:clamp(3.6rem,6.8vw,6.8rem)}
}
.step__no{font-family:var(--mono);font-size:.7rem;letter-spacing:.2em;color:var(--accent-text);margin-top:1.3rem}
.step h3{font-family:var(--body);font-weight:500;letter-spacing:0;line-height:1.2;
  font-size:clamp(1.55rem,2vw,2rem);margin-top:.55rem}
.step p{margin-top:.7rem;color:var(--text-secondary);font-size:1rem}

/* --- 5. Les secteurs ---
   C'était la section la plus plate de la page : du texte noir sur du sable.
   Elle devient une bande photo pleine largeur, et les municipalités sont
   cadrées par l'élément signature, à sa plus grande taille du site. */
.zones{background:var(--ink-deep);color:#EFECE4;overflow:hidden}
.zones__bg{position:absolute;inset:0;pointer-events:none;
  background:url('hero-poster.jpg') center 42%/cover no-repeat;opacity:.62}   /* chemin relatif au dossier assets, pas a la page */
.zones__bg::after{content:"";position:absolute;inset:0;
  background:linear-gradient(105deg,rgba(11,15,21,.88) 0%,rgba(11,15,21,.58) 48%,rgba(11,15,21,.74) 100%)}
.zones .wrap{position:relative;z-index:2}
.zones .kick{color:var(--accent-muted)}
.zones .kick::after{background:rgba(239,236,228,.3)}
.zones__frame{position:relative;margin-top:clamp(2.2rem,4vw,3.4rem);
  padding:clamp(1.8rem,3.4vw,3.2rem) clamp(1.4rem,3vw,2.8rem)}
.zones__frame .marks{inset:0}
.zones__frame .marks .cnr{width:clamp(26px,3.4vw,46px);height:clamp(26px,3.4vw,46px)}
.zones__frame .marks .cnr path{stroke:rgba(239,236,228,.55);stroke-width:1.2}
.zones__note{color:rgba(239,236,228,.74)}
.zones__list{display:flex;flex-wrap:wrap;gap:.55rem 0;margin:0;padding:0}
.zones__list li{list-style:none;font-family:var(--display);font-weight:600;font-size:clamp(1.3rem,2.3vw,1.95rem);line-height:1.34;letter-spacing:-.01em;
  display:flex;align-items:baseline}
.zones__list li::after{content:"";display:inline-block;width:clamp(1.1rem,2.4vw,2.6rem);height:1px;
  background:rgba(239,236,228,.45);margin:0 clamp(.7rem,1.4vw,1.4rem);transform:translateY(-.35em)}
.zones__list li:last-child::after{display:none}
/* Sur téléphone les noms composés se cassaient en plein milieu. Une ville par
   ligne, le trait de cote passe devant au lieu de suivre. */
@media (max-width:620px){
  .zones__list{display:block}
  .zones__list li{font-size:clamp(1.4rem,5.4vw,1.7rem)}
  .zones__list li::after{display:none}
  .zones__list li::before{content:"";flex:0 0 auto;display:inline-block;width:1.1rem;height:1px;
    background:rgba(239,236,228,.45);margin-right:.75rem;transform:translateY(-.35em)}
}
.zones__note{margin-top:2.2rem;max-width:52ch;color:rgba(239,236,228,.74)}

/* --- 6. Témoignages ---
   Posés sur le sable au lieu du lin, pour que la section se détache de ses
   deux voisines, et une grande guillemet en filigrane derrière chaque mot. */
.tem{background:var(--panel)}
.quotes{display:grid;grid-template-columns:repeat(12,1fr);gap:clamp(2rem,3vw,3rem);margin-top:clamp(2.4rem,4vw,3.4rem)}
.q{position:relative;border-top:1px solid var(--line-strong);padding-top:1.5rem}
.q::before{content:"";position:absolute;left:0;top:-1px;width:clamp(2.4rem,4.5vw,3.8rem);height:2px;
  background:var(--accent);transform-origin:left;transform:scaleX(var(--qn,0));
  transition:transform .9s var(--ease)}
.q.in::before,.stg.in .q::before{--qn:1}
.q:nth-child(1){grid-column:1/span 7}
.q:nth-child(2){grid-column:8/span 5}
.q:nth-child(3){grid-column:1/span 5}
.q:nth-child(4){grid-column:6/span 7}
@media (max-width:820px){.q,.q:nth-child(n){grid-column:1/-1}}
.q blockquote{margin:0;font-family:var(--body);font-weight:400;font-size:clamp(1.12rem,1.6vw,1.42rem);line-height:1.52}
.q figcaption{margin-top:1rem;font-family:var(--mono);font-size:.66rem;letter-spacing:.2em;text-transform:uppercase;color:var(--text-secondary)}

/* La note et le nombre d'avis. C'est le vrai poids de preuve : soixante-dix-neuf
   avis se disent en une ligne, pas en soixante-dix-neuf encadrés. Chiffres réels
   relevés sur le module d'avis de son site actuel, jamais inventés. */
.score{display:flex;align-items:center;gap:.85rem;flex-wrap:wrap;margin-top:1.5rem}
/* Étoiles en terracotta, pas en chêne : le guide de normes ne contient que le
   charbon, le terracotta, le crème et le blanc. Le chêne venait d'une décision
   de design antérieure au guide, qui gouverne au-dessus d'elle. */
.score__stars{display:inline-flex;color:var(--accent);line-height:0}
.score__stars svg{width:clamp(96px,10vw,124px);height:auto}
.score__line{font-size:clamp(.95rem,1vw + .6rem,1.05rem);color:var(--text-secondary)}
.score__line strong{font-weight:700;color:var(--text-primary);font-size:1.18em;letter-spacing:-.01em}

/* Les douze autres avis, repliés par défaut : la preuve du nombre est là pour
   qui la cherche, sans allonger la page pour qui ne la cherche pas. */
.more{margin-top:clamp(2.4rem,4vw,3.4rem);border-top:1px solid var(--line-strong)}
.more__btn{list-style:none;display:flex;align-items:center;justify-content:space-between;gap:1.5rem;
  padding:1.35rem 0;cursor:pointer;font-family:var(--body);font-weight:500;
  font-size:clamp(.95rem,1.1vw,1.05rem);transition:color .3s var(--ease)}
.more__btn:hover{color:var(--accent-text)}
.more__btn::-webkit-details-marker{display:none}
.more__sign{flex:0 0 auto;width:12px;height:12px;position:relative}
.more__sign::before,.more__sign::after{content:"";position:absolute;background:var(--accent);
  transition:transform .45s var(--ease),opacity .45s var(--ease)}
.more__sign::before{left:0;right:0;top:50%;height:1px;margin-top:-.5px}
.more__sign::after{top:0;bottom:0;left:50%;width:1px;margin-left:-.5px}
.more[open] .more__sign::after{transform:rotate(90deg);opacity:0}
.more__body{overflow:hidden;height:0;transition:height .5s var(--ease)}
.more__flow{columns:3 22rem;column-gap:clamp(1.6rem,2.6vw,2.6rem);padding-bottom:.5rem}
.mq{break-inside:avoid;margin:0 0 1.5rem;padding-left:1rem;border-left:1px solid var(--line)}
.mq blockquote{margin:0;font-size:.94rem;line-height:1.62;color:var(--text-secondary)}
.mq figcaption{margin-top:.55rem;font-family:var(--mono);font-size:.6rem;letter-spacing:.18em;
  text-transform:uppercase;color:var(--text-primary)}

/* --- 7. Questions ---
   Deux colonnes : le titre reste accroché à gauche pendant que les questions
   défilent à droite. Ça remplit le vide et ça casse le gabarit répété
   étiquette, titre, contenu empilés que toutes les autres sections suivaient. */
.faq-grid{display:grid;grid-template-columns:minmax(0,.92fr) minmax(0,1.28fr);
  gap:clamp(2rem,5vw,5.5rem);align-items:start}
/* MÊME PIÈGE QUE .reader__hint, ET IL DOIT RESTER RÉGLÉ PAREIL : la règle de
   base vient AVANT son exception téléphone. Écrite après, elle remettait le
   titre en « collant » sous 940 px, où la grille n'a pourtant plus qu'une
   colonne. Le titre se décrochait donc et flottait par-dessus les questions,
   trois textes superposés. Corrigé le 22 août 2026. */
.faq-grid__head{position:sticky;top:7.5rem}
@media (max-width:940px){.faq-grid{grid-template-columns:1fr;gap:2rem}.faq-grid__head{position:static}}
.faq-grid__note{margin-top:1.8rem;max-width:34ch;color:var(--text-secondary)}
.faq-grid__note a{color:var(--accent-text);font-weight:500;text-underline-offset:3px}
.faq{max-width:none;margin:0}
.qa{border-bottom:1px solid var(--line)}
.qa__btn{list-style:none;width:100%;display:flex;align-items:baseline;justify-content:space-between;gap:1.5rem;
  background:none;border:0;padding:1.35rem 0;text-align:left;cursor:pointer;
  font-family:var(--body);font-weight:500;font-size:clamp(1.02rem,1.25vw,1.15rem);line-height:1.4;
  transition:color .3s var(--ease)}
.qa__btn:hover{color:var(--accent-text)}
.qa__btn::-webkit-details-marker{display:none}
.qa__sign{flex:0 0 auto;width:12px;height:12px;position:relative;transform:translateY(-.1em)}
.qa__sign::before,.qa__sign::after{content:"";position:absolute;background:var(--accent);
  transition:transform .45s var(--ease),opacity .45s var(--ease)}
.qa__sign::before{left:0;right:0;top:50%;height:1px;margin-top:-.5px}
.qa__sign::after{top:0;bottom:0;left:50%;width:1px;margin-left:-.5px}
.qa[open] .qa__sign::after{transform:rotate(90deg);opacity:0}
.qa__body{overflow:hidden;height:0;transition:height .5s var(--ease)}
.qa__body p{padding-bottom:1.5rem;color:var(--text-secondary);max-width:62ch}

/* --- 8. Évaluation --- */
.cta{background:var(--ink-deep);color:#EFECE4}
.cta .kick{color:var(--accent-muted)}
.cta .kick::after{background:rgba(239,236,228,.26)}
.cta__grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(2rem,5vw,5rem);align-items:start}
@media (max-width:900px){.cta__grid{grid-template-columns:1fr}}
/* La version miroir, 26 août 2026 : le formulaire à gauche, le texte à droite.
   Relevé qui l'a motivée : sur presque chaque page, la fin était le formulaire
   PUIS le FAQ, et les deux commençaient exactement à la même verticale. Toutes
   les pages finissaient donc de la même façon, ce qui est une bonne part du
   « tout est à gauche » du client. Posée sur deux pages seulement, pas sur
   toutes : lire le titre avant de remplir reste l'ordre naturel, c'est
   l'alternance qui est recherchée, pas l'inversion générale.
   En une colonne l'ordre de lecture doit redevenir le naturel, sinon le
   visiteur du téléphone tombe sur le formulaire sans savoir ce qu'il demande. */
.cta__grid--inverse > *:first-child{order:2}
.cta__grid--inverse > *:last-child{order:1}
@media (max-width:900px){
  .cta__grid--inverse > *:first-child{order:1}
  .cta__grid--inverse > *:last-child{order:2}
}
.cta__lede{margin-top:1.4rem;color:rgba(239,236,228,.76);max-width:44ch}
/* La fermeture courte de l'accueil, 27 août 2026, depuis que le grand
   formulaire d'évaluation est parti dans Outils. */
.cta__actions{margin-top:2rem;display:flex;flex-wrap:wrap;gap:1.4rem;align-items:center;justify-content:center}
.cta__lien{font-family:var(--mono);font-size:.72rem;letter-spacing:.18em;text-transform:uppercase;
  color:rgba(239,236,228,.82);text-decoration:none;border-bottom:1px solid rgba(239,236,228,.4);
  padding-bottom:3px;white-space:nowrap}
.cta__lien:hover{color:#EFECE4;border-bottom-color:#EFECE4}
.cta__phone{margin-top:2.2rem;font-family:var(--mono);font-size:.72rem;letter-spacing:.18em;text-transform:uppercase;color:rgba(239,236,228,.66)}
.cta__phone a{color:#EFECE4;text-decoration:none;white-space:nowrap;border-bottom:1px solid rgba(239,236,228,.4)}
.form{display:grid;gap:1rem}
.form .row{display:grid;grid-template-columns:1fr 1fr;gap:1rem}
@media (max-width:560px){.form .row{grid-template-columns:1fr}}
.form label{display:block;font-family:var(--mono);font-size:.62rem;letter-spacing:.2em;text-transform:uppercase;
  color:rgba(239,236,228,.6);margin-bottom:.5rem}
.form input,.form textarea,.form select{width:100%;background:rgba(239,236,228,.05);border:1px solid var(--field-line-dark);
  color:#EFECE4;padding:.85rem .95rem;font-weight:400;transition:border-color .3s var(--ease),background .3s var(--ease)}
.form input::placeholder,.form textarea::placeholder{color:rgba(239,236,228,.52)}
.form input:focus,.form textarea:focus,.form select:focus{outline:none;border-color:var(--accent-muted);background:rgba(239,236,228,.09)}
.form textarea{resize:vertical;min-height:92px}
/* Le bouton du formulaire garde la vraie terracotta de la marque plutôt qu'un
   rose éclairci : c'est l'action principale de toute la page. Sur le charcoal
   la terracotta seule ne se détacherait pas assez du fond, alors un filet clair
   lui donne son contour. */
.form .btn{background:var(--accent-btn);color:#fff;border:1px solid var(--accent-muted);
  margin-top:.4rem;justify-self:start}
/* Une deuxieme regle de survol traînait ici avec un bleu pale #C3D4DE, reste de
   la palette d'avant le guide de normes. Elle ecrasait le terracotta et
   donnait du blanc sur bleu pale au survol. Supprimee le 22 aout 2026. */
.form .btn:hover{background:var(--accent-hover);border-color:var(--accent-muted)}
.form__ok{display:none;border-left:2px solid var(--accent-muted);padding:1rem 1.15rem;background:rgba(239,236,228,.06);font-size:.95rem;line-height:1.6}
.form__ok a{color:var(--accent-muted);text-underline-offset:3px;white-space:nowrap}
.form__ok.on{display:block}

/* --- Le message d'erreur sous un champ, 27 août 2026 ---------------------
   Ajouté parce que les six formulaires acceptaient un envoi vide sans rien
   dire : `novalidate` éteint la vérification du navigateur, et rien ne la
   remplaçait. Le seul qui vérifiait, celui des alertes, se contentait de
   déplacer le curseur : pour le visiteur, cliquer ne faisait rien du tout.

   LA COULEUR DÉPEND DU FOND, et c'est exactement le piège du 26 août, quand
   `.form__note` portait un gris fait pour le crème et se retrouvait sur le
   charcoal à 1,71 pour 1. Le jeton `--err` porte donc la bonne valeur selon
   la section. Mesuré : `--accent-text` 5,16 sur le crème, `--accent-muted`
   4,92 sur le charcoal, pour un plancher de 4,5.

   L'ORDRE DES DEUX RÈGLES COMPTE. La règle de base vise le fond clair et
   l'exception sombre vient APRÈS, sinon elle perd la cascade à spécificité
   égale. C'est la leçon du menu mobile du 25 août, qui n'a jamais rien
   appliqué pendant deux jours pour cette raison. */
.form{--err:var(--accent-text)}
.cta .form,.zones .form{--err:var(--accent-muted)}

.form__err{display:flex;gap:.45rem;align-items:flex-start;margin-top:.45rem;
  font-size:.82rem;line-height:1.45;color:var(--err)}
.form__err[hidden]{display:none}
/* La pastille porte le point d'exclamation : la couleur seule ne doit jamais
   être le seul signal, sinon un visiteur daltonien ne voit aucune différence
   entre un champ correct et un champ fautif. */
.form__err::before{content:"!";flex:0 0 auto;width:1.05rem;height:1.05rem;margin-top:.08rem;
  border-radius:50%;border:1.5px solid currentColor;font-family:var(--mono);
  font-size:.68rem;font-weight:700;line-height:1;
  display:flex;align-items:center;justify-content:center}
.form [aria-invalid="true"]{border-color:var(--err)}

/* --- Pied de page --- */
.foot{background:var(--ink-deep-2);color:rgba(239,236,228,.72);padding:clamp(2.2rem,3.6vw,3.4rem) var(--gut) 1.6rem}
/* Quatre colonnes depuis le 22 août 2026, quand les pages intérieures sont
   arrivées : la marque, les pages, les coordonnées, les secteurs. */
.foot__grid{max-width:var(--maxw);margin:0 auto;display:grid;grid-template-columns:1.5fr 1fr 1fr 1fr;gap:2.4rem}
@media (max-width:1080px){.foot__grid{grid-template-columns:1fr 1fr}}
@media (max-width:820px){.foot__grid{grid-template-columns:1fr}}
.foot__word{font-family:var(--mark);font-weight:500;font-size:2rem;color:#EFECE4;letter-spacing:.02em}
.foot__sub{font-family:var(--mono);font-size:.6rem;letter-spacing:.22em;text-transform:uppercase;margin-top:.4rem}
/* h3 ET NON h4 depuis le 19 septembre 2026 : le titre juste au-dessus du pied
   est le <h2> de la fermeture, donc un <h4> sautait le niveau 3. Trouve par le
   detecteur d'impeccable sur la version finale, sur les treize pages. Rien ne
   change a l'oeil : ce sont les memes petites capitales. */
.foot h3{font-family:var(--mono);font-weight:400;font-size:.62rem;letter-spacing:.2em;text-transform:uppercase;
  color:rgba(239,236,228,.5);margin-bottom:1rem}
.foot a{color:rgba(239,236,228,.82);text-decoration:none;transition:color .3s var(--ease)}
.foot a:hover{color:#EFECE4}
.foot ul{list-style:none;margin:0;padding:0;display:grid;gap:.5rem;font-size:.92rem}
.foot__bar{max-width:var(--maxw);margin:clamp(1.8rem,3vw,2.6rem) auto 0;padding-top:1.2rem;
  border-top:1px solid rgba(239,236,228,.14);display:flex;flex-wrap:wrap;gap:1rem;justify-content:space-between;
  font-family:var(--mono);font-size:.6rem;letter-spacing:.14em;text-transform:uppercase;color:rgba(239,236,228,.6)}

/* ==== LES CIBLES AU DOIGT, 27 août 2026 ==================================
   Trouvées par `lupa-tests/mobile-qualite.mjs`, qui passe les treize pages à
   390 px avec le tactile émulé. Trois cibles étaient sous le seuil de 44 px.

   LA TECHNIQUE : un pseudo-élément invisible qui agrandit la zone de touche,
   SANS toucher à la boîte de l'élément. Rien ne bouge à l'écran, pas un
   pixel : ni la taille du texte, ni son alignement, ni l'espacement autour.
   C'est ce qui permet de corriger un site déjà approuvé par la cliente.

   POURQUOI 46 px ET NON 44 : le seuil est bien 44, mais la sonde qui le
   vérifie part du centre de la cible et avance d'un pixel à la fois, donc
   elle en perd un sur chaque bord et lisait 43 sur une cible de 44. Plutôt
   que d'assouplir la mesure pour qu'elle passe, on donne deux pixels de
   marge à la cible. Ça ne coûte rien, la barre fait 67 px de haut.

   POURQUOI PAS UN `padding` : il agrandirait la boîte, donc décalerait ses
   voisins. Sur une barre dont l'écriture suit la section qu'elle survole, et
   sur un mot-symbole dont le guide de normes fixe la taille au pixel, c'est
   exactement ce qu'il ne faut pas faire.

   CE QUI N'EST PAS TOUCHÉ, ET POURQUOI. Les liens téléphone EN LIGNE au
   milieu d'une phrase gardent leur taille : une zone de 44 px y mordrait sur
   les lignes voisines et volerait leurs touches. Les normes les exemptent
   pour cette raison même. Idem pour les liens du pied de page, qui ne sont
   qu'à 26 px les uns des autres. */

/* 1. Le mot Lupa de la barre, sur les treize pages. Il mesure 71 x 30 px,
      et sa hauteur est fixée par le guide de normes, page 7 : on ne la
      touche pas. La barre fait 67 px de haut, donc une zone de 44 px y tient
      sans déborder sur le contenu. */
.nav__mark{position:relative}
/* Absolu, donc PAS un élément flex : `.nav__mark` est un conteneur flex, et
   un pseudo en flux y deviendrait une case de plus. */
.nav__mark::after{content:"";position:absolute;left:0;right:0;
  top:50%;translate:0 -50%;height:46px}

/* 2. Les liens téléphone qui sont une action à eux seuls. Sur un téléphone
      c'est un appel en un doigt, l'action la plus utile du site pour un
      courtier, et ils mesuraient de 20 à 25 px de haut. */
.cta__lien,.aside__tel a[href^="tel:"],.menu__tel a[href^="tel:"]{position:relative}
.cta__lien::after,.aside__tel a[href^="tel:"]::after,.menu__tel a[href^="tel:"]::after{
  content:"";position:absolute;left:0;right:0;top:50%;translate:0 -50%;height:46px}

/* 3. Les cartes du blogue. Le titre seul était cliquable, sur 25 px de haut,
      alors que la carte entière en a l'air. La carte entière le devient.
      Elle ne contient qu'UN lien, donc rien n'est recouvert : c'est ce qui
      rend ce procédé sûr ici et le rendrait faux sur les cartes de nouvelles
      de l'OACIQ, qui en portent deux. */
.pcard{position:relative}
.pcard h3 a::after{content:"";position:absolute;inset:0}

/* --- Entrées au défilement --- */
.rv{opacity:0;transform:translateY(14px);transition:opacity .55s var(--ease),transform .55s var(--ease)}
.rv.in{opacity:1;transform:none}
.stg > *{opacity:0;transform:translateY(12px);transition:opacity .5s var(--ease),transform .5s var(--ease)}
.stg.in > *{opacity:1;transform:none}
.stg.in > *:nth-child(1){transition-delay:0ms}
.stg.in > *:nth-child(2){transition-delay:60ms}
.stg.in > *:nth-child(3){transition-delay:120ms}
.stg.in > *:nth-child(4){transition-delay:180ms}
.stg.done > *,.stg.done > *:nth-child(1),.stg.done > *:nth-child(2),.stg.done > *:nth-child(3),.stg.done > *:nth-child(4){transition-delay:0ms}
.draw{stroke-dasharray:var(--len,1200);stroke-dashoffset:var(--len,1200);transition:stroke-dashoffset 1.7s var(--ease)}
.in .draw,.draw.in{stroke-dashoffset:0}

/* --- LE TITRE QUI SE PRÉCISE, 27 août 2026 -------------------------------
   Approuvé par le client sur maquette. Traduit de la famille « Blur Reveal »
   de 21st.dev, qui l'écrit en React avec framer-motion : ici c'est du CSS.

   IL SE GREFFE SUR LE SYSTÈME EXISTANT, il n'en ajoute pas un second. Les
   titres portent déjà `.rv` individuellement dans les treize pages, donc
   l'observateur de `pages.js` leur pose déjà `.in`. Aucune page n'a été
   modifiée pour cet effet.

   POURQUOI VISER LE TEXTE ET PAS `.rv` TOUT COURT : `.rv` enveloppe aussi
   des blocs entiers, cartes et photos comprises. Un flou sur ces blocs-là
   coûte cher à calculer sur téléphone, pour un effet que personne n'a
   demandé. Le client a approuvé « le titre qui se précise », c'est donc le
   texte de titre, et lui seul.

   PIÈGE DE CASCADE, celui déjà noté au dossier : `transition` NE SE CUMULE
   PAS. Ces sélecteurs sont plus spécifiques que `.rv`, donc ils EFFACENT sa
   liste de transitions. Il faut donc réécrire `opacity` et `transform` ici,
   sinon le fondu et la montée disparaissent sans la moindre erreur nulle
   part. Le flou est plus léger sur les petits textes : 8 px sur un titre
   Playfair se lit comme une mise au point, 8 px sur la surtitre en petites
   capitales l'effacerait complètement. */
/* LE FLOU A L ENTREE EST RETIRE le 17 septembre 2026. C etait l effet du
   27 aout « le titre qui se precise » : les titres arrivaient hors foyer et
   se faisaient la mise au point. Approuve sur maquette a l epoque, mais c est
   le plus gros signe du « blog » que la cliente a nomme : un site de courtier
   AFFICHE son texte, il ne le developpe pas comme une photographie. Les
   titres gardent leur montee et leur fondu, qui sont plus courts qu avant. */

/* --- LA PHOTO QUI SE DÉVOILE, 27 août 2026 -------------------------------
   Approuvé sur maquette. Traduit de « Reveal Image Mask » de 21st.dev.
   Réservé aux GRANDES photos, comme le client l'a accepté. Mesuré avant de
   choisir : les étapes montent à 1488x836 et la photo d'équipe à 1296x479,
   tout le reste du site est sous 460 px de large, donc des vignettes.

   CLIP-PATH SEULEMENT, JAMAIS `transform`, ET CE N'EST PAS UN DÉTAIL.
   `.zoomable` porte DEUX zooms empilés dans un seul `transform` : `--z` qui
   suit le doigt au défilement et `--hz` qui vient du survol. Y écrire un
   `transform` les écraserait tous les deux d'un coup.

   ET `--hz` DOIT RESTER DANS LA LISTE DE TRANSITIONS ci-dessous, pour la
   même raison qu'au commentaire de la ligne 557 : ces sélecteurs sont plus
   spécifiques que `.step__media img` et que `.zoomable`, donc ils effacent
   leur liste. Sans `--hz` ici, le zoom au survol des étapes meurt en
   silence. */
.stg .step__media img,.equipe.rv img{clip-path:inset(0 0 100% 0);
  transition:--hz .85s var(--ease),clip-path 1.15s var(--ease)}
.stg.in .step__media img,.equipe.rv.in img{clip-path:inset(0 0 0 0)}

/* La photo suit la carte qui la porte. Les cartes d'un `.stg` entrent en
   cascade à 0, 90 et 180 ms : sans ces deux lignes, les trois photos se
   dévoileraient ensemble, donc celles des cartes 2 et 3 finiraient leur
   ouverture avant même que leur carte soit visible, et l'effet serait perdu
   sur deux des trois.

   ET LE RETOUR À ZÉRO N'EST PAS FACULTATIF, c'est la raison d'être de la
   classe `.done` juste au-dessus : sans lui, le délai d'entrée resterait
   collé à la photo pour toujours et le zoom au survol attendrait 180 ms
   avant de démarrer. La règle `.done` doit être PLUS spécifique que la règle
   d'entrée pour gagner, d'où le `:nth-child` répété des deux côtés. */
.stg > *:nth-child(2) .step__media img{transition-delay:90ms}
.stg > *:nth-child(3) .step__media img{transition-delay:180ms}
.stg.done > *:nth-child(2) .step__media img,
.stg.done > *:nth-child(3) .step__media img{transition-delay:0ms}

/* Poussière au niveau du murmure */
.motes{position:absolute;inset:0;pointer-events:none;overflow:hidden;z-index:1}
.mote{position:absolute;width:3px;height:3px;border-radius:50%;background:rgba(176,136,86,.5);
  animation:mote 22s linear infinite}
.live .mote{animation-play-state:running}
@keyframes mote{
  0%{transform:translate3d(0,20px,0);opacity:0}
  12%{opacity:.75}
  88%{opacity:.55}
  100%{transform:translate3d(26px,-140px,0);opacity:0}
}

/* --- Le héros statique : les cinq portes --- */
.static-hero{display:none;position:relative;min-height:100svh;align-items:flex-end;
  background:var(--ink-deep) center/cover no-repeat;padding:var(--gut);color:#F6F4EF}
/* La vidéo du téléphone. Un recadrage portrait de la même prise, qui joue en
   boucle aller-retour au lieu d'être pilotée par le défilement : sur un petit
   écran, huit cents pour cent de hauteur à faire défiler est une corvée, et
   une boucle muette est fiable sur tous les téléphones. Elle n'est chargée
   que dans la branche du héros statique, donc un ordinateur ne la voit jamais,
   et le mouvement réduit garde l'image fixe. */
.static-hero__video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:0;transition:opacity 1.1s var(--ease);will-change:transform;transform:translateZ(0)}
.static-hero.video-on .static-hero__video{opacity:1}
.static-hero__scrim{position:absolute;inset:0;background:linear-gradient(to bottom,rgba(10,13,19,.62) 0%,rgba(10,13,19,0) 24%),linear-gradient(to top,rgba(10,13,19,.9) 4%,rgba(10,13,19,.46) 46%,rgba(10,13,19,.24) 100%)}
.static-hero__in{position:relative;z-index:2;max-width:34ch;text-shadow:var(--tshadow);padding-bottom:2vh}
.static-hero__word{font-family:var(--mark);font-weight:500;font-size:clamp(3.4rem,15vw,6rem);line-height:.92;letter-spacing:.03em}
.static-hero__sub{font-family:var(--mono);font-size:.62rem;letter-spacing:.28em;text-transform:uppercase;margin-top:1.5rem;opacity:.86;text-wrap:balance}
@media (max-width:430px){.static-hero__sub{letter-spacing:.16em;font-size:.58rem}}
.static-hero__h{font-family:var(--display);font-weight:700;font-size:clamp(1.45rem,5.2vw,2.1rem);line-height:1.2;letter-spacing:-.02em;margin-top:2.2rem}
.static-hero__p{margin-top:1rem;font-size:1rem;color:rgba(246,244,239,.88)}
.static-hero .btn{margin-top:1.8rem}

/* 24 août : le héros défilant joue AUSSI sur téléphone, décision du client.
   Les portes passent de cinq à DEUX, identiques à la liste GATES du script de
   l'accueil : le téléphone couché sans hauteur, et le mouvement réduit. */
@media (orientation:landscape) and (pointer:coarse) and (max-height:560px),
       (prefers-reduced-motion:reduce){
  .hero{display:none}
  .static-hero{display:flex}
  .search{margin-top:0;padding-top:clamp(2.5rem,6vw,4rem)}
}
/* Sur téléphone, le voyage raccourcit encore. 400vh jusqu'au 30 septembre
   2026, 300vh depuis l'accueil court du 1er octobre : trois bandes au lieu de
   quatre, donc la même lecture par bande sur moins de pouce. */
@media (max-width:720px){
  .hero{height:300vh}
}
@media (max-height:560px){.cue,.ring{display:none}}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none!important;transition:none!important;transition-delay:0s!important}
  .rv,.stg > *{opacity:1;transform:none}
  /* Les tuiles des municipalités sont visibles ici même sans .in : leur grille
     doit donc garder ses filets, sinon elles se touchent sans séparation. */
  .villes.stg:not(.in){background-color:var(--line);border-color:var(--line)}
  /* Les deux effets du 27 août doivent être annulés ICI AUSSI, et il faut
     nommer l'état `.in` explicitement. Un @media n'ajoute AUCUNE spécificité :
     écrire seulement `.h2.rv` ne suffirait pas, parce que `.h2.rv.in` est plus
     spécifique et reprendrait la main dès que le script pose la classe. C'est
     le piège déjà payé deux fois dans ce projet. Sans ces deux lignes, et avec
     le `transition:none!important` juste au-dessus, un visiteur en mouvement
     réduit garderait un titre flou et une photo coupée POUR TOUJOURS. */
  .h2.rv,.kick.rv,.lede.rv,.h2.rv.in,.kick.rv.in,.lede.rv.in{filter:none}
  .stg .step__media img,.equipe.rv img,
  .stg.in .step__media img,.equipe.rv.in img{clip-path:none}
  .draw{stroke-dashoffset:0}
  .note{opacity:1;transform:none}
  html{scroll-behavior:auto}
}

/* =========================================================================
   PAGES INTÉRIEURES, ajoutées le 22 août 2026.

   Le collègue de Marie-Claude : « elle est montée comme une landing page,
   ça va prendre d'autres onglets ». Quatre pages sont nées de là : la
   courtière, vendre, acheter, contact.

   Tout ci-dessous réutilise les jetons du guide de normes déclarés en haut
   de ce fichier. Aucune nouvelle couleur, aucune nouvelle police.
   ========================================================================= */

/* --- La bande de titre en haut de chaque page intérieure ---
   Elle est foncée, donc la barre de navigation y passe automatiquement en
   écriture claire : la classe pagehead est dans la liste des fonds foncés
   de assets/pages.js. */
.pagehead{position:relative;background:var(--ink-deep);color:#EFECE4;overflow:hidden;
  /* 176 px en haut a 1440, dont 82 px passent SOUS la barre de navigation :
     l'air reellement visible au-dessus du surtitre etait de 94 px, et le bas
     en avait 80 de plus. 19 septembre 2026, demande de Mathieu sur les
     espaces. Le minimum de 8rem reste sur telephone, ou la barre mange la
     meme hauteur sans que l'ecran soit plus grand. */
  padding:clamp(7.4rem,11vw,9rem) var(--gut) clamp(2.6rem,4.4vw,3.6rem)}
.pagehead__in{max-width:var(--maxw);margin:0 auto;position:relative;z-index:2}
.pagehead .kick{color:var(--accent-muted)}
.pagehead .kick::after{background:rgba(239,236,228,.28)}
.pagehead h1{font-size:clamp(2.2rem,5.2vw,4.2rem);margin-top:1.2rem;max-width:17ch}
.pagehead__lede{margin-top:1.4rem;max-width:52ch;color:rgba(239,236,228,.78)}
/* L'image de fond de la bande, très assombrie : le texte passe devant sans
   qu'aucun panneau ne soit posé, comme dans le héros. */
.pagehead__bg{position:absolute;inset:0;z-index:0;background-size:cover;background-position:center 45%;
  opacity:.30}
/* La video d'ambiance du bandeau, 24 aout. Elle se glisse ENTRE la photo de
   fond et le voile : meme calque, meme opacite que la photo, donc le voile et
   les contrastes mesures au-dessus ne changent pas d'un cheveu. Elle apparait
   en fondu quand elle est prete ; avant et sans elle, la photo fait le travail. */
.pagehead__video{position:absolute;inset:0;z-index:0;width:100%;height:100%;
  object-fit:cover;object-position:center 45%;opacity:0;transition:opacity 1.2s var(--ease)}
.pagehead__video.on{opacity:.30}
/* CORRECTIF DU 24 AOÛT, signalé par le client : la vidéo se posait PAR-DESSUS
   la photo de fond, et les deux images se voyaient en même temps, en double
   exposition. Quand la vidéo joue, la photo s'efface en fondu croisé. Elle
   revient si la vidéo est retirée (mouvement réduit, échec de lecture). */
.pagehead__bg{transition:opacity 1.2s var(--ease)}
.pagehead--joue .pagehead__bg{opacity:0}
.pagehead__veil{position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(to right,rgba(53,52,52,.92) 0%,rgba(53,52,52,.86) 34%,rgba(53,52,52,.62) 68%,rgba(53,52,52,.5) 100%)}

/* --- Où se pose le titre de la page, 26 août 2026 -------------------------
   Le client : « il faut mélanger où est situé l'écriture, en ce moment tout
   est à gauche, on veut un site un peu moins identique ». Le bandeau de titre
   est la PREMIÈRE chose qu'on voit sur chacune des douze pages intérieures,
   et il était au même endroit sur les douze. C'est le levier le plus visible.

   Posé en système, pas au hasard : dans l'ordre du menu, ça donne centre,
   gauche, décalé, centre, gauche, décalé, centre, gauche. Deux pages voisines
   n'ouvrent donc jamais pareil.

   ATTENTION, ET C'EST LA PARTIE QUI COMPTE : le voile de ce bandeau est un
   dégradé de gauche à droite, sombre à gauche et clair à droite. Il a été
   dessiné pour protéger un texte à gauche. Déplacer le texte sans déplacer le
   voile le poserait sur la partie claire de la photo, donc chaque posture
   emmène SON voile. Contrastes remesurés page par page après la pose. */
.pagehead--centre .pagehead__in{text-align:center}
.pagehead--centre .kick{justify-content:center}
.pagehead--centre .kick::before{content:"";height:1px;flex:1;max-width:5rem;background:rgba(239,236,228,.28)}
.pagehead--centre .kick::after{max-width:5rem}
.pagehead--centre h1{margin-inline:auto;max-width:20ch}
.pagehead--centre .pagehead__lede{margin-inline:auto}
.pagehead--centre .pagehead__veil{
  background:linear-gradient(to right,rgba(53,52,52,.58) 0%,rgba(53,52,52,.88) 26%,rgba(53,52,52,.9) 74%,rgba(53,52,52,.58) 100%)}

.pagehead--decale .pagehead__in{padding-left:clamp(0rem,16vw,15rem)}
.pagehead--decale .pagehead__veil{
  background:linear-gradient(to right,rgba(53,52,52,.5) 0%,rgba(53,52,52,.66) 26%,rgba(53,52,52,.88) 56%,rgba(53,52,52,.92) 100%)}
@media (max-width:900px){
  /* En une colonne, le décalage n'a plus de place : le titre revient à gauche
     et reprend le voile d'origine, sinon il tombe sur la zone claire. */
  .pagehead--decale .pagehead__in{padding-left:0}
  .pagehead--decale .pagehead__veil{
    background:linear-gradient(to right,rgba(53,52,52,.92) 0%,rgba(53,52,52,.86) 34%,rgba(53,52,52,.62) 68%,rgba(53,52,52,.5) 100%)}
}

/* --- Le fil d'Ariane, sous le titre --- */
.crumbs{max-width:var(--maxw);margin:0 auto;padding:1.4rem var(--gut) 0;
  font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;color:var(--text-secondary)}
.crumbs a{color:var(--accent-text);text-decoration:none;text-underline-offset:3px}
.crumbs a:hover{text-decoration:underline}
.crumbs span{opacity:.6;margin:0 .5rem}

/* --- Le corps de texte long des pages --- */
.prose{max-width:64ch}
/* UN BLOC DE TEXTE SEUL, CENTRÉ SUR LA PAGE MAIS LU DE GAUCHE À DROITE.
   Demandé le 28 août pour la page des courtiers, quand l'encadré d'évaluation
   qui occupait la deuxième colonne est parti : sans ça le texte serait resté
   collé à gauche avec un trou à droite.
   Le BLOC est centré, pas les lignes. Centrer les lignes d'un texte de trois
   paragraphes et d'une liste à cinq points le rendrait pénible à lire, et la
   liste surtout. Si le client veut vraiment les lignes centrées, c'est
   `wrap--centre` qu'il faut poser sur le conteneur, et c'est un mot à changer. */
.prose--seul{margin-inline:auto}
.prose p{margin-top:1.15rem}
.prose p:first-child{margin-top:0}
/* h2 ET h3 SE RESSEMBLENT AU PIXEL PRES, et c'est voulu. Le premier bloc de
   texte d'une page porte des <h2> depuis le 19 septembre 2026, pour que le plan
   des titres ne saute pas du <h1> du bandeau au <h3> (trouve par le detecteur
   d'impeccable). Le NIVEAU change, la TAILLE ne change pas : une page d'article
   n'a pas besoin de deux graisses de titre, et Mathieu a valide cette echelle.
   Si tu changes l'une des deux valeurs, change l'autre. */
.prose h2,.prose h3{font-size:clamp(1.6rem,2.5vw,2.1rem);margin-top:2.1rem;letter-spacing:-.01em}
.prose h2:first-child,.prose h3:first-child{margin-top:0}
.prose ul{margin-top:1.15rem;padding-left:0;list-style:none}
.prose li{position:relative;padding-left:1.6rem;margin-top:.7rem}
.prose li::before{content:"";position:absolute;left:0;top:.62em;width:.7rem;height:1px;background:var(--accent)}

/* --- Deux colonnes, texte et panneau --- */
.duo{display:grid;grid-template-columns:1.25fr .75fr;gap:clamp(2.4rem,5vw,5rem);align-items:start}
@media (max-width:900px){.duo{grid-template-columns:1fr}}

/* --- La carte d'un point, utilisée en grille sur vendre et acheter --- */
.pcards{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(1.4rem,2.6vw,2.4rem);margin-top:clamp(2.4rem,4vw,3.4rem)}
@media (max-width:980px){.pcards{grid-template-columns:1fr 1fr}}
@media (max-width:620px){.pcards{grid-template-columns:1fr}}
.pcard{background:var(--panel-2);border:1px solid var(--line);padding:clamp(1.5rem,2.4vw,2.1rem)}
.pcard__no{font-size:.7rem;letter-spacing:.2em;color:var(--accent-text)}
.pcard h3{font-size:1.15rem;margin-top:.9rem;letter-spacing:-.01em}
.pcard p{margin-top:.75rem;color:var(--text-secondary);font-size:.97rem}

/* Les cartes de la page Conseils, 24 aout 2026.
   Deux corrections vues a l'oeil sur la capture pleine hauteur, jamais par un
   test : le titre d'une carte etait souligne au repos, ce qui alourdit une
   grille entiere, et quatre cartes dans trois colonnes en laissaient une seule
   sur la deuxieme ligne. Deux colonnes donnent un carre propre. */
/* LES CARTES DE FIN D'ARTICLE N'ONT PLUS QUE LEUR TITRE depuis le 17 septembre
   2026 : les phrases de resume etaient copiees du debut de l'article vise, donc
   ecrites quatre fois sur le site. La carte suit maintenant son contenu au lieu
   de garder la hauteur d'une carte a paragraphe. Les cartes du Blogue, qui ont
   encore leur phrase, ne sont pas touchees : la regle est bornee a .pcards--liens. */
.pcards--liens .pcard{padding-block:clamp(1.05rem,1.7vw,1.35rem)}
.pcards--liens .pcard h3{margin-top:0}
.pcards--conseils{grid-template-columns:1fr 1fr}
@media (max-width:620px){.pcards--conseils{grid-template-columns:1fr}}
.pcard h3 a{color:inherit;text-decoration:none;
  background-image:linear-gradient(var(--accent),var(--accent));
  background-size:0 1px;background-position:0 100%;background-repeat:no-repeat;
  transition:background-size .45s var(--ease)}
.pcard h3 a:hover,.pcard h3 a:focus-visible{background-size:100% 1px}
.pcard__no{font-family:var(--mono);font-size:.66rem;letter-spacing:.18em;
  text-transform:uppercase;color:var(--accent-text)}

/* --- Le panneau d'appel latéral --- */
.aside{background:var(--panel);border:1px solid var(--line);padding:clamp(1.6rem,2.6vw,2.2rem);position:relative}
.aside h3{font-size:1.2rem;letter-spacing:-.01em}
.aside p{margin-top:.9rem;color:var(--text-secondary);font-size:.97rem}
.aside .btn{margin-top:1.4rem}
.aside__tel{margin-top:1.1rem;font-size:.78rem;letter-spacing:.12em;text-transform:uppercase;color:var(--text-secondary)}
.aside__tel a{color:var(--text-primary);text-decoration:none;border-bottom:1px solid var(--line-strong);white-space:nowrap}

/* --- L'encadré des guides de l'OACIQ, 27 août 2026 ------------------------
   Voisin de `.aside` mais délibérément différent de lui : ce n'est pas notre
   parole, c'est un document officiel d'un tiers, et le visiteur doit le voir
   au premier coup d'oeil. D'où le fond crème plutôt que sable, le filet
   terracotta en haut, et la source écrite avant le titre. */
.guide{background:var(--canvas);border:1px solid var(--line);border-top:2px solid var(--accent);
  padding:clamp(1.6rem,2.6vw,2.2rem);position:relative}
/* L'ÉCART VIT ENTRE LES DEUX CARTES, PAS SUR L'UNE DES DEUX. Il était posé en
   `margin-top` sur `.guide`, donc il disparaissait dès qu'on échangeait
   l'ordre. Le 28 août le client a mis le guide au-dessus de l'alerte sur
   Acheter, et les deux cartes se sont retrouvées collées, sans un pixel entre
   elles, pendant que l'écart passait au-dessus du guide et le décalait de
   22 px par rapport à la colonne de texte. Écrit ainsi, il suit l'ordre quel
   qu'il soit, et le guide seul de Vendre reste aligné sur son texte. */
.guide + .aside, .aside + .guide{margin-top:1.4rem}
.guide__source{font-family:var(--mono);font-size:.64rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--accent-text)}
.guide h3{font-size:1.2rem;letter-spacing:-.01em;margin-top:.6rem}
.guide p{margin-top:.9rem;color:var(--text-secondary);font-size:.97rem}
.guide .btn{margin-top:1.4rem}
.guide__note{margin-top:1.1rem;font-size:.8rem}
/* Sur Vendre le guide est seul dans sa colonne : il n'a personne au-dessus de
   lui, donc pas de marge à rattraper. */
.duo > .guide{margin-top:0}

/* --- La bande d'appel en bas de chaque page --- */
/* LA SECTION LA PLUS VIDE DU SITE, ET ELLE EST SUR LES TREIZE PAGES : 224 px
   de vide pour 432 px de haut, soit 52 pour cent, pour un titre, une ligne et
   un bouton. Classement etabli par scratchpad/qui-est-vide.mjs, qui trie les
   sections par le vide qu'elles portent. Le remplissage passe de 112 a 63 px,
   le vide de 224 a 127. */
.endcta{background:var(--ink-deep);color:#EFECE4;padding:clamp(2.4rem,4.4vw,4rem) var(--gut);text-align:center}
.endcta h2{font-size:clamp(1.8rem,3.6vw,2.9rem);max-width:20ch;margin:0 auto}
.endcta p{margin-top:1rem;color:rgba(239,236,228,.76);max-width:48ch;margin-left:auto;margin-right:auto}
.endcta .btn{margin-top:1.6rem}

/* --- La grille des municipalités, page Habiter Québec ---
   Inspirée de la structure de « Habiter l'Estrie » sur le site que la cliente
   aime, mais en jetons Lupa et avec nos propres mots. */
.villes{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;margin-top:clamp(2.4rem,4vw,3.4rem);
  background:var(--line);border:1px solid var(--line)}
/* LE FOND DE LA GRILLE N'APPARAÎT QU'AVEC SES TUILES, 17 septembre 2026.
   Ce fond dessine les filets de 1 px entre les tuiles. Or les tuiles restent
   invisibles tant que la grille n'a pas reçu .in, et l'observateur de
   pages.js ignore les 12 % du bas de l'écran : à 1440 x 900, le haut de la
   grille s'affichait comme un rectangle gris vide jusqu'au premier coup de
   molette. Vu à l'œil, corrigé à la demande de Mathieu. */
.villes.stg{transition:background-color .5s var(--ease),border-color .5s var(--ease)}
.villes.stg:not(.in){background-color:transparent;border-color:transparent}
@media (max-width:900px){.villes{grid-template-columns:1fr 1fr}}
@media (max-width:560px){.villes{grid-template-columns:1fr}}
.ville{background:var(--canvas);padding:clamp(1.4rem,2.4vw,1.9rem);transition:background .4s var(--ease)}
.ville:hover{background:var(--panel-2)}
.ville h3{font-size:1.06rem;letter-spacing:-.01em}
.ville p{margin-top:.5rem;color:var(--text-secondary);font-size:.93rem}

/* --- Les blocs d'avantages, pages Vendre et Acheter ---
   Un titre, un paragraphe, parfois une liste. Le trait à l'accent marque le
   début de chaque bloc, comme les cotes d'un dessin. */
.avantages{margin-top:clamp(2.4rem,4vw,3.4rem);display:grid;gap:clamp(2rem,3.4vw,2.8rem)}
.avantage{position:relative;padding-left:clamp(1.2rem,2vw,1.8rem);border-left:1px solid var(--line)}
.avantage::before{content:"";position:absolute;left:-1px;top:.42em;width:1px;height:1.5em;background:var(--accent)}
.avantage h3{font-size:clamp(1.45rem,2.3vw,1.85rem);letter-spacing:-.01em}
.avantage p{margin-top:.75rem;color:var(--text-secondary);max-width:62ch}
.avantage ul{margin-top:.9rem;padding-left:0;list-style:none;max-width:62ch}
.avantage li{position:relative;padding-left:1.5rem;margin-top:.55rem;color:var(--text-secondary);font-size:.97rem}
.avantage li::before{content:"";position:absolute;left:0;top:.62em;width:.65rem;height:1px;background:var(--accent)}

/* Les blocs d'avantages sur fond foncé.
   Erreur attrapée par le banc d'essai le 22 août : le gris secondaire, prévu
   pour le crème, donnait 1,71 de contraste sur le charbon. Sur les sections
   foncées, le texte des blocs prend la teinte claire du site. */
.zones .avantage p,.zones .avantage li,
.cta .avantage p,.cta .avantage li,
.lupa .avantage p,.lupa .avantage li{color:rgba(239,236,228,.80)}
.zones .avantage,.cta .avantage,.lupa .avantage{border-left-color:rgba(239,236,228,.20)}
/* La douzième tuile, qui remplit le trou laissé par onze municipalités dans
   une grille à trois colonnes, et le remplit avec quelque chose d'utile. */
.ville--fin{background:var(--panel-2)}
.ville--fin a{color:var(--accent-text);text-underline-offset:3px}
/* Les listes déroulantes du formulaire : le navigateur leur impose sa propre
   flèche et son fond blanc. On les remet dans le même habit que les champs
   texte, avec une flèche dessinée aux couleurs du guide. */
.form select{appearance:none;-webkit-appearance:none;color:#EFECE4;cursor:pointer;
  padding-right:2.2rem;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23CE9591' stroke-width='1.4'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 1rem center}
.form select option{background:#353434;color:#EFECE4}

/* =========================================================================
   LA PAGE OUTILS, 23 août 2026. Les deux calculatrices.

   PIÈGE ÉVITÉ ICI, celui qui avait rendu trente-trois textes illisibles le
   22 août : un composant réutilisable doit déclarer ses couleurs pour LES DEUX
   familles de fond. Le calcul 1 est sur le lin, le calcul 2 sur l'encre. Les
   champs du site étaient stylés pour l'encre seulement, donc ils auraient été
   invisibles sur le lin. Chaque règle ci-dessous a donc sa jumelle.
   ========================================================================= */
.calc__grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(2.2rem,4.5vw,4.5rem);align-items:start}
@media (max-width:900px){.calc__grid{grid-template-columns:1fr}}
/* UNE SECTION SUR DEUX RENVERSE SES COLONNES. La page Outils empilait cinq
   calculatrices bâties pareil, texte à gauche et champs à droite, plus deux
   sections : `rythme.mjs` comptait six postures « colonnes » à la file depuis
   le premier jour, et il les tolérait parce qu'une grille n'est pas une pile à
   gauche. Mathieu l'a vu à l'œil le 18 septembre 2026 : « tout est beaucoup
   trop centré au milieu des pages, il faut mélanger un peu tout ça ».
   Les champs passent donc à gauche sur la mise de fonds et sur les alertes.
   EN UNE COLONNE L'ORDRE REVIENT : le titre doit rester avant ses champs,
   sinon on remplit un formulaire avant de savoir de quoi il parle. */
.calc__grid--inverse > *:first-child{order:2}
.calc__grid--inverse > *:last-child{order:1}
@media (max-width:900px){
  .calc__grid--inverse > *:first-child{order:1}
  .calc__grid--inverse > *:last-child{order:2}
}

.calc__lede{margin-top:1.1rem;max-width:46ch;color:var(--text-secondary)}
.zones .calc__lede{color:#D6D1C8}

/* Le bloc de résultat. Sur le lin il est en sable, sur l'encre il est en clair
   translucide, pour rester le même objet dans les deux mondes. */
.calc__out{margin-top:2.2rem;padding:clamp(1.4rem,2.6vw,2rem);background:var(--panel);
  border:1px solid var(--line)}
.zones .calc__out{background:rgba(239,236,228,.06);border-color:rgba(239,236,228,.20)}

.calc__label{font-family:var(--mono);font-size:.62rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--text-secondary)}
.zones .calc__label{color:#C9C3B8}

.calc__big{font-family:var(--display);font-weight:600;line-height:1;margin-top:.5rem;
  font-size:clamp(2.2rem,5vw,3.4rem);color:var(--text-primary);
  /* Ajouté le 27 août 2026 avec le chiffre qui monte. Sans les chiffres à
     largeur fixe, le « 1 » est plus étroit que le « 8 » et toute la ligne
     tremble pendant la montée. Utile aussi sans l'animation : le montant ne
     saute plus quand on tape un chiffre de plus dans le prix. */
  font-variant-numeric:tabular-nums}
.zones .calc__big{color:#F6F4EF}

.calc__detail{list-style:none;margin-top:1.5rem;padding:0;border-top:1px solid var(--line)}
.zones .calc__detail{border-top-color:rgba(239,236,228,.20)}
.calc__detail li{display:flex;justify-content:space-between;align-items:baseline;gap:1.2rem;
  padding:.72rem 0;border-bottom:1px solid var(--line);font-size:.95rem}
.zones .calc__detail li{border-bottom-color:rgba(239,236,228,.20)}
.calc__detail span{color:var(--text-secondary)}
.zones .calc__detail span{color:#D6D1C8}
.calc__detail b{font-weight:500;color:var(--text-primary);text-align:right}
.zones .calc__detail b{color:#F6F4EF}

.calc__note{margin-top:1.1rem;font-size:.9rem;line-height:1.5;color:var(--accent-text)}
.zones .calc__note{color:#E7C2BF}

.calc__paliers{margin-top:2.2rem}

/* Les champs sur fond CLAIR. Sans ce bloc, la calculatrice 1 aurait des champs
   presque blancs sur presque blanc, avec un texte pâle : illisible. */
.calc .form input,.calc .form select{background:var(--canvas);border-color:var(--field-line);
  color:var(--text-primary)}
.calc .form label{color:var(--text-secondary)}
.calc .form input::placeholder{color:rgba(53,52,52,.5)}
.calc .form input:focus,.calc .form select:focus{border-color:var(--accent);background:#fff}

/* Et sur fond FONCÉ, on rend au formulaire ses couleurs d'origine. */
.zones.calc .form input,.zones.calc .form select{background:rgba(239,236,228,.05);
  border-color:var(--field-line-dark);color:#F6F4EF}
.zones.calc .form label{color:#C9C3B8}
.zones.calc .form input::placeholder{color:rgba(239,236,228,.52)}
.zones.calc .form input:focus,.zones.calc .form select:focus{border-color:var(--accent-muted);
  background:rgba(239,236,228,.09)}

/* La flèche des listes déroulantes est un SVG rose pâle, dessiné pour l'encre.
   Sur le lin il faut la version foncée, sinon elle disparaît presque.

   PIÈGE QUI A ÉTÉ VU À L'OEIL ET PAR AUCUN TEST : la règle de champ ci-dessus
   utilise le raccourci `background`, qui remet `background-repeat` à `repeat`.
   La flèche de 10 par 6 pixels se répétait alors en mosaïque et les deux listes
   sortaient hachurées de rose. Il faut donc redéclarer la répétition et la
   position ici, jamais seulement l'image. */
.calc .form select{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23A04846' stroke-width='1.4'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 1rem center;background-color:var(--canvas)}
.zones.calc .form select{background-repeat:no-repeat;background-position:right 1rem center;
  background-color:rgba(239,236,228,.05)}

.calc__form{margin-top:2.2rem}
@media (max-width:520px){.calc .form .row{grid-template-columns:1fr}}

/* =========================================================================
   LES QUATRE ANIMATIONS DU 23 AOÛT 2026.
   Le comportement est dans assets/anim.js, qui explique d'où vient chaque
   effet et quel réglage le client a choisi. Ici, seulement l'apparence.

   Tout est en transform et en opacity, jamais autre chose : ce sont les deux
   seules propriétés que le navigateur anime sans repeindre la page.
   ========================================================================= */

/* ---- 1. L'intro ---------------------------------------------------------
   PLUS CHARGÉE DEPUIS LE 1er OCTOBRE 2026 : Mathieu a fait retirer l'intro
   pour qu'on arrive tout de suite sur le héros défilant. Aucune page ne pose
   plus `intro-avant`, et anim.js n'appelle plus intro(). Ces règles restent :
   garde-guide.mjs les lit encore, et le retour tient en une ligne.
   QUATRIÈME VERSION, 24 août 2026, corrigée sur les mots exacts du client.
   Les deux lignes encadrent le mot, se ferment en L'ÉCRASANT, se rouvrent à
   partir du milieu avec une ouverture qui se propage de gauche à droite, des
   maisons défilent lentement, et la dernière image est la façade où la vidéo
   du héros commence. Quatre classes : --go, --crush, --films, --out.

   Le rideau est en encre profonde, jamais en noir pur. Tout est fabriqué en
   JavaScript : sans JavaScript, aucun rideau n'existe. */
/* LE RIDEAU ANTI-FLASH, 25 août 2026. Le client voyait la façade du héros une
   fraction de seconde avant que l'intro ne démarre.
   La cause : `assets/anim.js` est chargé en FIN de page, donc le navigateur a
   déjà peint le héros quand l'intro se construit et se pose par-dessus.
   Ce rideau est peint dès la lecture de cette feuille, dans le <head>, donc
   AVANT le premier affichage. Un petit script en ligne dans le <head> de
   chaque page pose la classe, aux mêmes conditions exactement que `intro()` :
   première visite de la session, et mouvement réduit inactif.
   Il est à 9998, juste sous l'intro à 9999, donc l'intro le recouvre sans
   qu'aucun des deux ne clignote. anim.js le retire une fois l'intro en place.
   NE PAS le retirer sans retirer aussi le script des treize pages. */
html.intro-avant::before{content:"";position:fixed;inset:0;z-index:9998;
  background:var(--ink-deep);pointer-events:none}
.intro{position:fixed;inset:0;z-index:9999;background:var(--ink-deep);
  overflow:hidden;
  transition:opacity .8s var(--ease) .7s,visibility .8s var(--ease) .7s}
html.intro-on{overflow:hidden}                  /* rien ne défile pendant l'intro */

/* ============== LA QUATRIÈME VERSION EST DE RETOUR, 28 août au soir ======
   La cinquième, les photos lancées sur une table, a été montrée à la cliente
   et REFUSÉE : « la cliente aime pas ça on va remettre l'ancienne ». Elle
   vit dans l'historique Git (commits eac39df à 61cf134). NE LA REPROPOSE PAS.

   La quatrième, en place du 24 au 28 août, corrigée sur les mots exacts du
   client : les deux lignes encadrent le mot, se ferment en L'ÉCRASANT, se
   rouvrent à partir du milieu avec une ouverture qui se propage de gauche à
   droite, des maisons défilent lentement, et la dernière image est la façade
   où la vidéo du héros commence. Quatre classes : --go, --crush, --films,
   --out. Plus `--vite`, gardée du 28 : la sortie rapide du saut volontaire.

   LE PLAFOND DE CETTE INTRO EST À 6 SECONDES, sa règle du 25 août. Les 7 s
   accordées le 28 l'étaient pour la version des photos lancées.
   ========================================================================= */

/* Les deux lignes. Elles n'encerclent PAS l'écran : elles collent au mot,
   une juste au-dessus, une juste en dessous, à 9vh du centre. */
.intro__ligne{position:absolute;left:12vw;right:12vw;height:1px;background:var(--accent);
  opacity:0;z-index:3;
  transition:top 1.15s cubic-bezier(.65,0,.3,1),bottom 1.15s cubic-bezier(.65,0,.3,1),
    left .9s var(--ease),right .9s var(--ease),opacity .55s var(--ease)}
.intro__ligne--h{top:calc(50% - 9vh)}
.intro__ligne--b{bottom:calc(50% - 9vh)}
.intro--go .intro__ligne{opacity:.92}
/* 2e temps : elles se ferment l'une sur l'autre, au centre exact. */
.intro--crush .intro__ligne--h{top:calc(50% - 1px)}
.intro--crush .intro__ligne--b{bottom:calc(50% - 1px)}
/* 3e temps : elles se rouvrent jusqu'aux bords de la bande des maisons. */
.intro--films .intro__ligne--h{top:calc(50% - 17vh)}
.intro--films .intro__ligne--b{bottom:calc(50% - 17vh)}
/* Levée : elles s'écartent au-delà de l'écran et s'éteignent. */
.intro--out .intro__ligne--h{top:-3vh;opacity:0;transition-duration:1.1s}
.intro--out .intro__ligne--b{bottom:-3vh;opacity:0;transition-duration:1.1s}

/* Le mot, entre les deux lignes. */
/* Flex colonne et non grille : une grille à deux rangées ÉTIRAIT le mot et la
   sous-ligne sur toute la hauteur de l'écran, donc ils débordaient des deux
   lignes et l'écrasement les faisait passer À TRAVERS. Vu à l'image. Le bloc
   est maintenant un groupe serré au centre, pile entre les deux lignes. */
.intro__in{position:absolute;inset:0;z-index:2;display:flex;flex-direction:column;
  align-items:center;justify-content:center;padding:0 clamp(1rem,4vw,3rem)}
/* LE LOGO, depuis le 17 septembre 2026 : le verrouillage « Lupa X exp » du
   guide remplace le mot assemblé lettre par lettre, demande de Mathieu.
   CRÈME, parce que le fond de l'intro est le charbon officiel (#353434), et
   la page 09 le permet.
   SA HAUTEUR EST TENUE PAR LES DEUX LIGNES : elles sont à 9vh du centre, et la
   zone de protection du guide vaut 0,391 fois la hauteur du logo. Il faut donc
   h/2 + 0,391 h <= 9vh, soit h <= 10,1vh : on prend 9,5vh, plafonné par la
   largeur de l'écran sur téléphone (20vw, donc 76 vw de large au plus). */
.intro__logo{height:min(9.5vh,20vw);width:calc(min(9.5vh,20vw) * 3.8003);aspect-ratio:auto;
  background-color:var(--canvas);opacity:0;transform:translateY(12px);
  transition:opacity .6s var(--ease) .1s,transform .8s cubic-bezier(.2,.8,.2,1) .1s}
/* Plein à 0,7 s : les lignes partent à 0,95 s et n'atteignent le logo que
   vers 1,4 s, ce qui lui laisse sa lecture entière avant d'être recouvert. */
.intro--go .intro__logo{opacity:1;transform:none}

/* L'ÉCRASEMENT DEVIENT UN RECOUVREMENT, 17 septembre 2026. Jusque-là, le mot
   composé s'aplatissait entre les lignes (scaleY), comme le client l'avait
   décrit le 24 août. Le vrai logo ne peut pas être déformé : la page 06 du
   guide l'interdit. Les lignes se ferment donc PAR-DESSUS lui : une découpe
   qui part exactement d'elles (9vh du centre) et se referme au centre, avec
   la même durée et la même courbe que les lignes. Le geste reste le même à
   l'œil, et le dessin reste intact jusqu'au dernier pixel visible. */
.intro__in{clip-path:inset(calc(50% - 9vh) 0 calc(50% - 9vh) 0)}
.intro--crush .intro__in{clip-path:inset(50% 0 50% 0);opacity:0;
  transition:clip-path 1.15s cubic-bezier(.65,0,.3,1),opacity .55s var(--ease) .6s}

/* La bande des maisons, fermée en une fente au centre. À la réouverture, le
   coin GAUCHE s'ouvre en premier et l'ouverture se propage vers la droite :
   « à partir du milieu et de gauche à droite », les deux à la fois. */
.intro__fenetre{position:absolute;left:0;right:0;top:calc(50% - 17vh);bottom:calc(50% - 17vh);
  z-index:1;overflow:hidden;
  clip-path:polygon(0 50%,100% 50%,100% 50%,0 50%);
  transition:top 1s cubic-bezier(.6,0,.25,1),bottom 1s cubic-bezier(.6,0,.25,1)}
.intro--films .intro__fenetre{animation:introOuvre 1.05s cubic-bezier(.6,0,.25,1) forwards}
@keyframes introOuvre{
  0%{clip-path:polygon(0 50%,100% 50%,100% 50%,0 50%)}
  45%{clip-path:polygon(0 10%,100% 45%,100% 55%,0 90%)}
  100%{clip-path:polygon(0 0,100% 0,100% 100%,0 100%)}
}
/* Levée : la bande devient l'écran entier, posée sur la façade du héros. */
.intro--out .intro__fenetre{top:0;bottom:0;
  animation:none;clip-path:polygon(0 0,100% 0,100% 100%,0 100%)}

/* Le film : des panneaux pleine largeur qui glissent LENTEMENT vers la
   gauche (correction du client : pas trop vite) et décélèrent sur la façade.
   La largeur, la part de chaque panneau et la course sont calculées par
   anim.js selon le nombre d'images RÉELLEMENT arrivées. Ici, rien que
   l'assemblage. */
.intro__film{display:flex;height:100%;transform:translateX(0)}
.intro__film img{height:100%;object-fit:cover}

.intro--out{opacity:0;visibility:hidden;pointer-events:none}
/* Le saut demandé à la main (molette, clavier, glissement) part sans le
   retard du fondu normal, une protection gardée du 28 août : un visiteur qui
   venait de sauter attendait 1,5 s devant un écran figé, et sur téléphone ça
   passait pour une intro cassée. */
.intro.intro--vite{transition:opacity .45s var(--ease),visibility .45s var(--ease)}

/* ---- 2. La loupe : retirée le 24 août au soir, décision du client --------
   « on va garder seulement le curseur de la souris avec la traînée en
   arrière ». Le curseur est celui du système, nu. Ne réintroduis pas de faux
   curseur sans demande explicite. */

/* ---- 2 bis. La traînée liquide (lusion.co) ------------------------------
   Le canevas fait un tiers de l'écran : c'est le flou d'ici qui fond les
   gouttes en une nappe continue, et c'est ce qui donne le liquide sans 3D.
   Sous la loupe (9000), au-dessus du contenu, jamais au-dessus de l'intro.
   L'opacité reste basse : c'est un sillage, pas un rideau, et le texte
   dessous doit rester parfaitement lisible. */
.traine{position:fixed;inset:0;width:100vw;height:100vh;z-index:8998;
  pointer-events:none;filter:blur(11px) saturate(1.12);opacity:.5}
/* Sur telephone elle vit aussi, sous le doigt, a la demande du client. La
   boucle dort des que le doigt lache, donc elle ne coute rien a la batterie
   entre deux gestes. */
@media (prefers-reduced-motion:reduce){.traine{display:none}}

/* ---- 3. Le zoom continu des images --------------------------------------
   Le zoom s'écrit dans --z, une variable, jamais directement dans le style
   de l'élément. La feuille compose, donc rien n'écrase rien, et une image
   sans JavaScript reste simplement à sa taille normale.

   AUCUNE TRANSITION ICI, volontairement : le défilement est déjà continu, une
   transition ne ferait qu'ajouter du retard à un mouvement qui suit le doigt. */
/* Le zoom, deuxieme passe du 24 aout. Monter l'amplitude a 0.15 ne suffisait
   pas : etale sur toute la traversee de l'ecran, l'effet reste lent a l'oeil.
   On ajoute donc ce que zhenyary fait vraiment et que la cliente decrivait mot
   pour mot : « lorsqu'on survole une image, l'image zoom in ou out un peu ».
   Les deux zooms se COMPOSENT : --z vient du defilement (ecrit par anim.js,
   jamais de transition, il suit le doigt), --hz vient du survol (anime par la
   transition ci-dessous grace a @property). */
@property --hz{syntax:'<number>';initial-value:1;inherits:false}
.zoomable{transform:scale(calc(var(--z,1) * var(--hz,1)));will-change:transform;
  transition:--hz .85s var(--ease)}
.step__media:hover img.zoomable,.reader:hover img.zoomable{--hz:1.07}
img.zoomable{transform-origin:center}
.pagehead__bg.zoomable,.zones__bg.zoomable{transform-origin:center 45%}

/* Le survol des étapes faisait déjà grossir l'image de 4,5 pour cent. Il est
   retiré : l'image bouge maintenant tout le temps, donc le survol n'ajoutait
   plus rien et les deux transformations se seraient écrasées l'une l'autre.
   La règle d'origine est neutralisée ici plutôt que supprimée plus haut, pour
   qu'on retrouve son histoire. */
.step:hover .step__media img.zoomable{transform:scale(calc(var(--z,1) * var(--hz,1)))}

/* ---- 4. Le ruban d'avis -------------------------------------------------
   Il avance tout seul et le visiteur peut le pousser. Le masque sur les bords
   dit sans un mot qu'il continue au-delà de l'écran. */
.ruban{position:relative;margin-top:clamp(2rem,4vw,3rem);overflow:hidden;
  cursor:grab;-webkit-user-select:none;user-select:none;
  /* pan-y : le navigateur garde le defilement VERTICAL de la page, mais laisse
     le geste HORIZONTAL au ruban. Sans cette ligne, le premier mouvement du
     pouce declenchait le defilement natif, qui annulait le pointeur, et le
     ruban ne se poussait pas au doigt. Retour du vrai telephone du client. */
  touch-action:pan-y;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent)}
.ruban--tenu{cursor:grabbing}
/* Le ruban ne s'arrête plus jamais : il accélère sous le pointeur. */
.ruban{cursor:ew-resize}
.ruban__piste{display:flex;gap:clamp(1rem,2vw,1.6rem);width:max-content;
  will-change:transform}
/* margin:0 obligatoire : ce sont des <figure>, et le navigateur leur pose
   « margin: 1em 40px » par defaut. Cette feuille n'a pas de remise a zero
   globale des figures, donc les cartes se retrouvaient espacees de 80 px au
   lieu des 26 de la gouttiere, et la periode de la boucle etait fausse
   d'autant. Meme piege que la photo de Marie-Claude le 23 aout. */
.ruban__carte{margin:0;flex:0 0 clamp(17rem,26vw,23rem);background:var(--canvas);
  border:1px solid var(--line);padding:clamp(1.2rem,2.2vw,1.7rem);
  display:flex;flex-direction:column;gap:.9rem}
.ruban__carte blockquote{margin:0;font-size:.95rem;line-height:1.62;color:var(--text-primary)}
.ruban__carte figcaption{font-family:var(--mono);font-size:.62rem;letter-spacing:.2em;
  text-transform:uppercase;color:var(--text-secondary);margin-top:auto}
/* Les étoiles sont du TEXTE, donc elles tombent sous le seuil de 4,5. Le
   terracotta officiel donne 3,86 sur le crème : c'est écrit noir sur blanc au
   dossier depuis le 21 août, et je l'ai quand même réintroduit ici. Le jeton
   --accent-text existe exactement pour ça et donne 5,16. */
.ruban__etoiles{color:var(--accent-text);font-size:.8rem;letter-spacing:.12em}
/* Sur le sable, la carte prend le lin pour se détacher ; sur le lin, elle
   prend le sable. Le composant déclare ses deux fonds, comme tous les autres. */
.q-wrap .ruban__carte,.panelbg .ruban__carte{background:var(--canvas)}
.ruban__note{margin-top:1.4rem;font-family:var(--mono);font-size:.66rem;
  letter-spacing:.18em;text-transform:uppercase;color:var(--text-secondary)}

/* ---- Le mouvement réduit coupe les quatre --------------------------------
   Le site coupe déjà toutes les transitions en mouvement réduit. On ajoute
   ici ce qui lui est propre : la loupe disparaît, le zoom retourne à zéro,
   le ruban s'immobilise et redevient une liste qu'on fait défiler soi-même. */
@media (prefers-reduced-motion:reduce){
  .intro{display:none}
  .loupe{display:none}
  /* Les ondes du cœur de l'orbite s'effacent. La règle générale au-dessus
     arrête déjà leur animation, mais elle les figerait à leur première image,
     donc deux cercles inertes autour du cœur. Mieux vaut qu'ils n'y soient
     pas. L'orbite elle-même ne tourne pas non plus : c'est le script qui s'en
     charge, et les quatre points restent entièrement utilisables. */
  .orb__onde{display:none}
  .zoomable{transform:none}
  .ruban{overflow-x:auto;cursor:auto;
    -webkit-mask-image:none;mask-image:none}
  .ruban__piste{transform:none!important}
}

/* ==== 5. L'escalier vivant ================================================
   La dérive s'ajoute au décalage que la feuille pose déjà : --marche vaut
   zéro par défaut, donc sans JavaScript les trois marches restent exactement
   où elles étaient. */
.marche{transform:translate3d(0,var(--marche,0),0)}
@media (max-width:880px){.marche{transform:none}}   /* en colonne, l'escalier n'a plus de sens */

/* ==== 6. LE MÉDAILLON EST RETIRÉ, 17 septembre 2026 ====================
   Demande de Mathieu : « j'enlèverais les loupes au complet qui
   anciennement étaient animées, où c'est écrit évaluation gratuite
   autour ». Le médaillon, sa loupe et leurs règles sont partis, et la
   fonction qui le fabriquait dans anim.js aussi. Historique Git :
   dernier état 5f1ccd9. */

/* ==== 7. Le chevauchement de la photo ====================================
   Repris de zhenyary, où l'image passe par-dessus le grand titre. Ici elle ne
   mord QUE sur la gouttière vide entre les deux colonnes : pas un mot n'est
   couvert. Vérifié à l'oeil et par la mesure de chevauchement de texte.
   Au-dessus de 1100 pixels seulement ; en dessous, les colonnes s'empilent et
   l'effet n'aurait plus de sens. */
@media (min-width:1101px){
  .broker{grid-template-columns:1.05fr .82fr;gap:0;align-items:center}
  /* Le retrait à droite doit TOUJOURS dépasser les 3rem dont la photo mord,
     sinon un mot passe dessous. Mesuré : avec 4vw, à 1101px exactement, le
     dernier mot glissait de 4 pixels sous la photo. Le plancher du clamp est
     donc à 4,5rem, soit une bonne marge au-dessus des 3rem de chevauchement. */
  .broker > .rv:first-child{position:relative;z-index:1;padding-right:clamp(4.5rem,5vw,6rem)}
  /* margin-inline écrit en entier, et non margin-left seul : la règle de base
     de .broker__figure pose margin-inline:auto, qui reprenait la main sur le
     côté qu'on ne redéclarait pas. Mesuré : sans ça, le décalage restait à 0. */
  .broker__figure{position:relative;z-index:2;margin-inline:-3rem auto;
    max-width:min(100%,460px)}
}

/* ==== Le mouvement réduit coupe les trois ================================ */
@media (prefers-reduced-motion:reduce){
  .marche{transform:none}
}

/* ==== L'équipe : les trois associés ======================================
   La rangée carrée qui vivait ici a été remplacée le 25 août par les bulles,
   ci-dessous, à la demande du client. Ses règles sont retirées plutôt que
   laissées à dormir : plus rien dans le HTML ne portait ces classes.
   CE QUI RESTE VRAI ET COMPTE ENCORE, c'est la préparation des portraits :
   les trois photos ne venaient pas du même studio et ont été ramenées à une
   luminance de fond commune par `lupa-tests/portraits.sh` avant d'entrer dans
   assets/. NE JAMAIS remplacer un `portrait-*.jpg` par une photo brute sans
   repasser par là : la rangée se déséquilibre immédiatement. */

/* ==== Les trois bulles de l'équipe ======================================= */
/* Inspiré d'offmenu.design, demandé par le client le 25 août 2026. Là-bas,
   chaque vignette est un <a> en `rounded-full overflow-hidden` qui porte son
   propre agrandissement, et le groupe entier flotte doucement. Ici, trois
   bulles au lieu de neuf : elles sont donc plus grosses, alignées, et chacune
   ouvre sa fiche.

   TOUT LE SURVOL EST EN CSS, sans une ligne de script : la fiche vit DANS sa
   bulle, donc `.bulle:hover .bulle__fiche` suffit. Le script ne sert qu'au
   doigt, qui ne survole pas. Une bulle reste donc utilisable même si le script
   ne se charge pas. */
.bulles{position:relative;display:grid;grid-template-columns:repeat(3,1fr);
  gap:clamp(1.4rem,3vw,3rem);margin-top:clamp(2.4rem,4vw,3.4rem);
  /* La fiche s'ouvre par-dessus cette réserve, donc rien ne saute sous elle.
     La réserve et la fiche partagent la MEME hauteur, --fiche : c'est ce qui
     garantit que la fiche recouvre entièrement l'invite au lieu de la laisser
     dépasser dessous. Changer l'une sans l'autre casse le recouvrement. */
  --fiche:clamp(10.5rem,14vw,12rem);
  /* La réserve est plus creuse que la fiche : celle-ci peut dépasser sa
     hauteur minimale quand son texte est long, et elle mordait alors de
     quelques pixels sur les titres des bulles, qui se retrouvaient coupés.
     Ces 1,6 rem sont le coussin qui l'en empêche. Mesuré par bulles.mjs. */
  padding-bottom:calc(var(--fiche) + 1.6rem)}
.bulle{margin:0;text-align:center;position:static}
.bulle__rond{
  /* margin:0 obligatoire, c'est un <figure> : le navigateur lui met 1em 40px
     par défaut. Piège déjà rencontré deux fois sur ce site. */
  margin:0 auto;width:min(100%,clamp(9rem,14vw,12.5rem));aspect-ratio:1;
  border-radius:50%;overflow:hidden;background:var(--panel);
  border:1px solid var(--line);position:relative;
  /* DEUX MOUVEMENTS, DEUX PROPRIÉTÉS SÉPARÉES, et c'est obligatoire.
     La flottaison et l'agrandissement au survol écrivaient d'abord tous les
     deux dans `transform`. Une animation CSS l'emporte toujours sur une
     déclaration normale : la bulle ne grossissait donc JAMAIS au survol, et
     rien ne le signalait puisque la photo à l'intérieur, elle, grossissait.
     La flottaison prend `translate`, le survol prend `scale`. Les deux
     propriétés sont indépendantes et se composent sans se battre.
     NE PAS revenir à `transform` sur l'une des deux. */
  transition:scale .55s var(--ease),box-shadow .55s var(--ease),border-color .4s var(--ease);
  /* `bulleFlotte` est retiree le 17 septembre 2026 : les trois portraits
     montaient et descendaient de 11 px sans fin. Les reglages par rang
     (duree et retard decales) partent avec elle, sinon ils designent une
     animation qui n existe plus. Le survol garde son zoom. */}
.bulle__rond img{display:block;width:100%;height:100%;object-fit:cover;
  /* LE CADRAGE DES PASTILLES, corrige le 18 septembre 2026 a la demande de
     Mathieu (« ils ne sont pas bien centres »). Les pastilles montrent
     maintenant les cartes officielles 800 x 1000, les memes que l'accueil,
     et non plus les carres 600 x 600 ou Claudia etait decalee dans le coin.
     Dans un cercle, un portrait 4:5 se recadre par le haut : le visage vit
     dans le tiers superieur, donc on vise 50 % 22 % et non le centre. */
  object-position:50% 22%;
  transition:transform .55s var(--ease)}
.bulle__grande img{object-position:50% 22%}
.bulle__nom{font-family:var(--mark);font-weight:500;letter-spacing:-.01em;
  font-size:clamp(1.16rem,1.9vw,1.42rem);margin-top:1.15rem}
.bulle__titre{font-family:var(--mono);font-size:.64rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--accent-text);margin-top:.5rem}

/* L'ouverture : la bulle grossit, la photo grossit un peu plus dedans, et la
   fiche paraît sous la rangée. `:focus-within` fait la même chose au clavier. */
.bulle:hover .bulle__rond,
.bulle:focus-within .bulle__rond,
.bulle.ouverte .bulle__rond{
  scale:1.16;border-color:var(--accent);
  box-shadow:0 22px 50px -26px rgba(53,52,52,.5);
  animation-play-state:paused}
.bulle:hover .bulle__rond img,
.bulle:focus-within .bulle__rond img,
.bulle.ouverte .bulle__rond img{transform:scale(1.09)}

/* L'invite occupe la réserve tant qu'aucune fiche n'est ouverte. Elle n'a
   besoin d'aucun `:has()` ni d'aucun script : la fiche est opaque, de même
   boîte, et passe devant. Elle la couvre, tout simplement. */
.bulles__invite{position:absolute;left:0;right:0;bottom:0;z-index:0;
  min-height:var(--fiche);display:grid;place-items:center;text-align:center;
  border:1px dashed var(--line);color:var(--text-secondary);
  font-family:var(--mono);font-size:.68rem;letter-spacing:.16em;text-transform:uppercase}
.bulles__invite .surTel{display:none}
@media (hover:none){
  .bulles__invite .surSouris{display:none}
  .bulles__invite .surTel{display:inline}
}
.bulle__fiche{position:absolute;left:0;right:0;bottom:0;z-index:1;min-height:var(--fiche);text-align:left;
  background:var(--panel);border:1px solid var(--line);
  padding:clamp(1.3rem,2.4vw,1.9rem);
  display:grid;grid-template-columns:auto 1fr;gap:clamp(1.1rem,2.4vw,1.9rem);align-items:start;
  opacity:0;visibility:hidden;transform:translateY(14px);
  transition:opacity .45s var(--ease),transform .45s var(--ease),visibility .45s var(--ease)}
.bulle:hover .bulle__fiche,
.bulle:focus-within .bulle__fiche,
.bulle.ouverte .bulle__fiche{opacity:1;visibility:visible;transform:none}
.bulle__grande{margin:0;width:clamp(6rem,9vw,8.2rem);aspect-ratio:1;overflow:hidden;
  border:1px solid var(--line);background:var(--canvas)}
.bulle__grande img{display:block;width:100%;height:100%;object-fit:cover}
.bulle__fiche h4{font-family:var(--mark);font-weight:500;font-size:clamp(1.14rem,1.8vw,1.36rem)}
.bulle__champs{font-family:var(--mono);font-size:.63rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--accent-text);margin-top:.5rem}
.bulle__mot{margin-top:.85rem;font-size:.96rem;color:var(--text-secondary);max-width:58ch}

/* Sur téléphone : une bulle par ligne, la fiche entre DANS le flux au lieu de
   se poser par-dessus, et c'est le doigt qui l'ouvre. Aucune réserve à garder
   puisque plus rien ne flotte au-dessus du contenu. */
@media (max-width:760px){
  .bulles{grid-template-columns:1fr;padding-bottom:0;gap:2.2rem}
  .bulles__invite{display:none}
  .bulle__fiche{position:static;transform:none;visibility:visible;opacity:1;
    display:none;margin-top:1.2rem}
  .bulle.ouverte .bulle__fiche{display:grid}
  .bulle:hover .bulle__rond{scale:1}
  .bulle.ouverte .bulle__rond{scale:1.06}
}
@media (prefers-reduced-motion:reduce){
  .bulle__rond{animation:none;translate:none}
  .bulle:hover .bulle__rond,.bulle:focus-within .bulle__rond,.bulle.ouverte .bulle__rond{scale:1}
  .bulle__fiche{transform:none}
}

/* ==== Les nouvelles de l'OACIQ, page Blogue, 27 août 2026 ================
   Inspiré de la page que le client a montrée (charlesvend.ca/fr/blogue) : une
   liste verticale plutôt qu'une grille de cartes, chaque nouvelle avec son
   titre, quelques lignes, et un lien pour lire la suite.
   Ce qui change chez nous : pas d'image de couverture. Les images de ces
   nouvelles appartiennent à l'OACIQ, et en inventer une par nouvelle donnerait
   une illustration décorative qui ne dit rien. Le trait vertical et l'étiquette
   de source portent la mise en page à leur place. */
.nouvelles__date{margin-top:1.2rem;font-family:var(--mono);font-size:.66rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--text-secondary)}
.nouvelles{margin-top:clamp(1.8rem,3.4vw,2.6rem);display:grid;gap:0}
.nouvelle{position:relative;padding:clamp(1.5rem,2.6vw,2.1rem) 0 clamp(1.5rem,2.6vw,2.1rem) clamp(1.2rem,2.4vw,2rem);
  border-top:1px solid var(--line)}
.nouvelle:last-child{border-bottom:1px solid var(--line)}
/* Le trait de gauche est le rappel du trait de cote qui sépare les sections
   ailleurs sur le site : c'est le même vocabulaire de dessin. */
.nouvelle::before{content:"";position:absolute;left:0;top:clamp(1.5rem,2.6vw,2.1rem);bottom:clamp(1.5rem,2.6vw,2.1rem);
  width:2px;background:var(--accent);opacity:.5}
.nouvelle__source{font-family:var(--mono);font-size:.64rem;letter-spacing:.18em;text-transform:uppercase;
  color:var(--accent-text)}
.nouvelle__quoi{color:var(--text-secondary)}
.nouvelle h3{font-size:clamp(1.25rem,2.4vw,1.85rem);margin-top:.7rem;max-width:26ch}
.nouvelle h3 a{color:inherit;text-decoration:none;background-image:linear-gradient(var(--accent),var(--accent));
  background-size:0 1px;background-repeat:no-repeat;background-position:0 100%;
  transition:background-size .45s var(--ease)}
.nouvelle h3 a:hover,.nouvelle h3 a:focus-visible{background-size:100% 1px}
.nouvelle p{margin-top:.85rem;max-width:64ch;color:var(--text-secondary)}
.nouvelle__lien{font-family:var(--mono);font-size:.68rem;letter-spacing:.12em;text-transform:uppercase}
.nouvelle__lien a{color:var(--accent-text);text-decoration:none;border-bottom:1px solid var(--accent-muted);
  padding-bottom:2px}
.nouvelle__lien a:hover{border-bottom-color:var(--accent)}
.nouvelles__pied{margin-top:1.6rem;max-width:60ch;font-size:.82rem;color:var(--text-secondary)}

/* ==== LES SECTEURS REPLIÉS, 17 septembre 2026 ============================
   Idée de Mathieu : « un gros EMPLACEMENT ou VILLE, et quand on met notre
   souris dessus, là on voit toutes les villes qui s'ouvrent. Ça prendrait
   moins de place sur le site à moins qu'on veuille le voir. »

   LE SURVOL EST EN CSS, PAS EN JAVASCRIPT : le bandeau s'ouvre même si le
   script ne se charge pas. Le script de pages.js ne sert qu'au doigt et au
   clavier, où le survol n'existe pas, et il pose `data-ouvert`.

   LA HAUTEUR S'ANIME EN `grid-template-rows`, ET C'EST UNE CORRECTION.
   Elle s'animait d'abord en `max-height:22rem`, un plafond deviné. Mesuré le
   soir même : à 390 px le panneau fait 270 px et passe, mais à 320 px il fait
   387 px et le plafond EN COUPAIT 35. Le banc mesure à 390 px, il ne pouvait
   pas le voir. Une rangée de grille qui passe de 0fr à 1fr n'a aucun nombre à
   deviner : elle vaut toujours la hauteur exacte du contenu, quelle que soit
   la largeur de l'écran et la taille de police du visiteur.
   Le `max-height` reste comme voie de secours pour les navigateurs qui ne
   savent pas animer une rangée de grille, avec un plafond assez haut pour ne
   jamais couper. NE REMETS PAS UN PLAFOND DEVINÉ. */
.sec--mince{padding-block:clamp(1.6rem,3vw,2.6rem)}
.secteurs{border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.secteurs__tete{display:flex;align-items:baseline;gap:clamp(.7rem,1.6vw,1.4rem);width:100%;
  padding:clamp(1.1rem,2vw,1.5rem) 0;background:none;border:0;cursor:pointer;
  font:inherit;color:inherit;text-align:left}
.secteurs__kick{font-family:var(--mono);font-size:.68rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--accent-text);white-space:nowrap}
.secteurs__titre{font-family:var(--display);font-weight:600;letter-spacing:-.01em;
  font-size:clamp(1.25rem,2.4vw,1.85rem);line-height:1.1}
.secteurs__note{flex:1;min-width:0;font-size:.9rem;color:var(--text-secondary);white-space:nowrap}
/* SOUS 400 px, « onze municipalités » VA À LA LIGNE, et ce n'est pas cosmétique.
   Mesuré le 17 septembre : la note ne pouvait pas se replier, alors la rangée
   demandait 316 px dans un bandeau qui n'en faisait que 280, et LE SIGNE « + »
   SORTAIT DE L'ÉCRAN. C'est le seul signe qui dit au visiteur que le bandeau
   s'ouvre, et il disparaissait exactement sur les téléphones où le repli sert
   le plus. La page ne débordait pas pour autant, donc aucun outil ne criait. */
@media (max-width:400px){
  .secteurs__tete{flex-wrap:wrap}
  .secteurs__note{flex:1 0 100%;order:4;white-space:normal;margin-top:.35rem}
  .secteurs__sign{order:3}
}
/* Le signe, dessiné comme celui des questions : un plus qui devient un moins. */
.secteurs__sign{position:relative;width:14px;height:14px;flex:0 0 auto;align-self:center}
.secteurs__sign::before,.secteurs__sign::after{content:"";position:absolute;inset:50% 0 auto 0;
  height:1.5px;background:var(--accent);transition:transform .35s var(--ease)}
.secteurs__sign::after{transform:rotate(90deg)}
.secteurs:hover .secteurs__sign::after,
.secteurs[data-ouvert] .secteurs__sign::after{transform:rotate(0deg)}
.secteurs__panneau{max-height:0;overflow:hidden;opacity:0;
  transition:max-height .5s var(--ease),opacity .4s var(--ease)}
.secteurs:hover .secteurs__panneau,
.secteurs[data-ouvert] .secteurs__panneau{max-height:34rem;opacity:1}
.secteurs__in{padding-bottom:clamp(1.2rem,2.4vw,1.8rem)}
.secteurs__liste{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;
  gap:.5rem clamp(1rem,2.2vw,2rem)}
.secteurs__liste li{font-family:var(--display);font-weight:500;font-size:clamp(1rem,1.5vw,1.2rem);
  color:var(--text-primary)}
.secteurs__liste li + li{position:relative}
.secteurs__liste li + li::before{content:"";position:absolute;left:calc(clamp(1rem,2.2vw,2rem) / -2);
  top:50%;width:3px;height:3px;border-radius:50%;background:var(--accent-muted);transform:translateY(-50%)}
.secteurs__mot{margin-top:1.1rem;max-width:62ch;font-size:.92rem;color:var(--text-secondary)}
/* Sur un écran tactile, le survol n'existe pas : seul le doigt ouvre, par le
   script. Sans cette règle, certains navigateurs gardent un « survol collant »
   après un toucher et le bandeau resterait ouvert tout seul. */
@media (hover:none){
  .secteurs:hover .secteurs__panneau{max-height:0;opacity:0}
  .secteurs[data-ouvert] .secteurs__panneau{max-height:34rem;opacity:1}
  .secteurs:hover .secteurs__sign::after{transform:rotate(90deg)}
  .secteurs[data-ouvert] .secteurs__sign::after{transform:rotate(0deg)}
}

/* LA HAUTEUR EXACTE, LÀ OÙ LE NAVIGATEUR SAIT LA FAIRE. Ce bloc vient APRÈS
   celui du tactile et non avant : un `@supports` ne gagne rien d'être un
   `@supports`, il perd la cascade par l'ordre comme n'importe quelle règle.
   `min-height:0` sur le contenu n'est pas décoratif : sans lui, une rangée à
   0fr refuse de s'écraser et le panneau resterait ouvert. */
@supports (grid-template-rows: 0fr){
  .secteurs__panneau{display:grid;grid-template-rows:0fr;max-height:none;
    transition:grid-template-rows .5s var(--ease),opacity .4s var(--ease)}
  /* `min-height:0` retire la hauteur minimale automatique de la case, mais PAS
     son remplissage : mesuré, le bandeau fermé gardait exactement les 29 px du
     `padding-bottom` à 1440 px et 19 px à 390 px. Le remplissage descend donc
     sur la dernière ligne, en marge, et `overflow:hidden` empêche cette marge
     de s'échapper. Bandeau fermé : 0 px. */
  .secteurs__in{min-height:0;overflow:hidden;padding-bottom:0}
  .secteurs__mot{margin-bottom:clamp(1.2rem,2.4vw,1.8rem)}
  .secteurs:hover .secteurs__panneau,
  .secteurs[data-ouvert] .secteurs__panneau{grid-template-rows:1fr;max-height:none}
  @media (hover:none){
    .secteurs:hover .secteurs__panneau{grid-template-rows:0fr;opacity:0}
    .secteurs[data-ouvert] .secteurs__panneau{grid-template-rows:1fr;opacity:1}
  }
}

/* Le visiteur qui demande moins de mouvement voit le bandeau s'ouvrir d'un
   coup. Il s'ouvre quand même : c'est lui qui l'a demandé en posant la souris
   ou le doigt, ce n'est pas une animation qui part toute seule. */
@media (prefers-reduced-motion:reduce){
  .secteurs__panneau{transition:none}
  .secteurs__sign::before,.secteurs__sign::after{transition:none}
}

/* ==== LE TRIPTYQUE AU DÉFILEMENT, accueil, 18 septembre 2026 ==============
   Idée de Mathieu : « on fait avancer leur animation pour qu'ils se mettent en
   position de leur portrait, en défilant comme avec notre héros », et « un
   après l'autre, pour nous laisser découvrir les courtiers ». Même mécanique
   que le héros, en plus léger : la section est plus haute que l'écran, le
   triptyque reste collé pendant qu'on la traverse, et la position de
   défilement pilote l'image de chaque clip (script dans index.html).
   Les clips sont INVERSÉS : leur dernière image est le portrait officiel,
   et l'affiche (poster) est cette même image détourée, donc aucun cadre
   n'apparaît jamais vide. Ils sont SANS FOND : WebM VP9 avec transparence,
   la personne posée directement sur la page ; le MP4 de secours pour Safari
   porte la crème de la page cuite dedans (#F0EEE8). */
/* 280vh, ET LES DEUX DEMANDES DE MATHIEU TIENNENT ENSEMBLE GRACE AUX CLIPS
   COUPES. Il a dit la meme soiree « il defile beaucoup trop vite » ET « ca
   prend trop de place » : deux contraires, tant qu'on ne touche qu'a la
   hauteur. La sortie est dans les clips. Ils passaient 8,3 s de geste dont la
   premiere moitie etait du temps mort ou le modele avait derive ; coupes a
   leur partie vivante ils font 3,1 s. Resultat mesure, en secondes de clip par
   100vh de defilement : 6,2 avant, 3,4 maintenant. Donc pres de deux fois
   moins vite, sur une section 30 pour cent plus courte. */
/* 480vh DEPUIS LES CLIPS « 2 » DU 18 SEPTEMBRE AU SOIR, ET LE CHIFFRE VIENT
   DE DEUX DE SES RETOURS. Les nouveaux clips sont vivants d'un bout à l'autre
   (4,3 s : la personne se tourne vers le visiteur, puis se pose). Sur
   ordinateur, la vitesse perçue ne dépend QUE de la hauteur de la section :
   le défilement pilote l'image, un clip ralenti n'y change rien. En secondes
   de clip par 100vh de défilement : 6,2 la veille (« beaucoup trop vite »),
   3,4 après la coupe, 4,0 sur la première maquette de la scène à 320vh
   (« beaucoup trop vite » encore), et le héros de l'accueil, qu'il a gardé,
   tourne à 2,2. À 480vh on est à 2,7 : entre le héros et la coupe. */
/* 600vh DEPUIS LE 19 SEPTEMBRE AU SOIR, ET C'EST SA DEMANDE : « le defilement
   est saccade et trop vite, ajuste cela ». C'etait 480vh.

   ATTENTION, L'ALLURE SE CALCULE DE DEUX FACONS ET LE DOSSIER MELANGEAIT LES
   DEUX. La course reelle d'une section collee n'est pas sa hauteur, c'est sa
   hauteur MOINS un ecran : `progres()` divise par `offsetHeight - innerHeight`.
   Les chiffres du 18 septembre (6,2 / 4,0 / 2,7) etaient calcules sur la
   hauteur brute, donc ils flattent. Mesure, en px de defilement par courtier
   et en secondes de clip par 100vh, identique a toutes les tailles d'ecran :

       480vh -> 1140 px par courtier a 1440x900 -> 3,39 s par 100vh
       600vh -> 1500 px par courtier a 1440x900 -> 2,58 s par 100vh

   Soit un quart plus lent. Sur l'echelle du projet, un chiffre PLUS BAS veut
   dire PLUS LENT : moins de secondes de clip par ecran de defilement.
   Si ce n'est pas encore assez lent, il n'y a qu'une ligne a tourner, celle-ci.

   CETTE HAUTEUR NE CONCERNE QUE L'ORDINATEUR : sur telephone la section vaut
   `height:auto` et l'allure vient de la traversee de chaque carte. */
.eqscrub{height:600vh;position:relative}
.eqscrub__colle{position:sticky;top:0;min-height:100vh;display:flex;align-items:center;
  padding:clamp(3rem,5.6vw,5.6rem) var(--gut)}
.eqscrub__colle > .wrap{width:100%}
/* LA TETE EN RANGEE, 19 septembre 2026, sur sa demande d'enlever « des espaces
   inutiles ». Trois choses gagnees d'un coup : le titre tient sur une ligne
   (sa limite de 15 caracteres vaut pour un titre au milieu d'une page, pas
   pour celui-ci qui a toute la largeur), l'invite remplit le vide a droite au
   lieu de prendre sa propre ligne sous les portraits, et les deux ensemble
   rendent six rem de hauteur aux portraits. Sous 900 px la rangee se plie et
   l'invite repasse dessous, a sa place d'avant. */
.eqscrub__tete{display:flex;align-items:baseline;justify-content:space-between;gap:1rem 2.4rem;flex-wrap:wrap}
.eqscrub__tete .h2{max-width:32ch}
.eqscrub__tete .eqtrio__invite{margin-top:0;flex:0 0 auto}
@media (max-width:900px){
  .eqscrub__tete{display:block}
  .eqscrub__tete .eqtrio__invite{margin-top:clamp(1rem,2vw,1.4rem)}
}
.eqtrio{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(.8rem,1.6vw,1.4rem);
  margin-top:clamp(2rem,3.4vw,2.8rem)}
/* LE BLOC COLLE DOIT TENIR DANS L'ECRAN. Sinon les noms et le lien restent
   sous le pli pendant tout le defilement et n'apparaissent qu'au moment ou la
   section s'en va. Mesure le 18 septembre : 55 px de trop a 1440x900, 151 px a
   1366x768 et a 1280x720, les portables les plus courants. Le cadre se
   plafonne donc par la hauteur de l'ecran : 22 rem, c'est ce que prennent le
   titre, les noms, le lien et les marges sur un ecran bas ; le plancher de
   12 rem evite un cadre nul dans une fenetre absurde. Le plafond ne vaut
   qu'en mode colle : la requete statique plus bas le retire. */
/* 25rem, ET LE CHIFFRE EST MESURE, PAS DEVINE. C'est ce que prennent, en
   hauteur, le surtitre, le titre, les noms, les fonctions, l'invite et le
   remplissage du bloc : tout sauf le portrait. Relevé le 18 septembre au soir
   sur six tailles d'ecran, de 1024x768 a 1920x1080 : entre 23,2 et 24,9 rem.
   J'avais d'abord ecrit 19 en raisonnant (« la tete est passee a gauche, le
   lien est parti, donc ca prend moins de place ») : faux, le titre a gauche
   tient sur deux lignes larges et l'invite est arrivee. Le banc l'a attrape,
   78 px de trop a 1366x768. LE RAISONNEMENT NE REMPLACE PAS LA MESURE.
   Le cadre fait 4:5, donc sa hauteur vaut sa largeur fois 1,25 : borner la
   largeur a (100vh - 25rem) x 0,8 borne sa hauteur a (100vh - 25rem). */
/* 24rem, REMESURE le 19 septembre apres la mise en rangee de la tete, sur six
   tailles d'ecran de 1024x768 a 1920x1080. C'etait 29 quand le titre prenait
   deux lignes et que l'invite avait la sienne sous les portraits. Le chiffre
   n'est jamais raisonne : on mesure ce que prend TOUT sauf le portrait, on
   prend le pire des six, et on ajoute un demi-rem. */
.eqtrio__c{margin:0 auto;width:100%;max-width:max(12rem,calc((100vh - 24rem) * .8))}
@media (min-width:721px) and (max-height:900px){
  .eqscrub__colle{padding-block:2rem}
  .eqtrio{margin-top:clamp(1.4rem,2.4vw,2rem)}
}
/* LA FICHE AU SURVOL A REMPLACE LES BULLES, demande du 18 septembre au soir :
   « qu'a la place le texte descriptif de chacun apparait lorsqu'on mets notre
   souris sur un des courtiers dans le video defilant ». Le texte est celui des
   bulles, mot pour mot, il n'a pas ete reecrit. Il se pose DANS le cadre, donc
   il ne prend pas un pixel de hauteur de plus : c'etait l'autre moitie de sa
   phrase, « ca prend trop de place, il y a beaucoup d'espace vide ».
   Le survol est en CSS, comme celui des bulles l'etait ; le script ne sert
   qu'au doigt, la ou le survol n'existe pas. */
.eqtrio__cadre{overflow:hidden;aspect-ratio:4/5;background:transparent;position:relative}
.eqtrio__fiche{position:absolute;left:0;right:0;bottom:0;z-index:2;text-align:left;
  background:linear-gradient(to top,rgba(30,29,29,.96) 0%,rgba(30,29,29,.94) 62%,rgba(30,29,29,0) 100%);
  color:#F0EEE8;padding:clamp(2.2rem,4vw,3rem) clamp(1rem,1.7vw,1.4rem) clamp(1rem,1.7vw,1.35rem);
  opacity:0;visibility:hidden;transform:translateY(12px);
  transition:opacity .38s var(--ease),transform .38s var(--ease),visibility 0s linear .38s}
.eqtrio__c:hover .eqtrio__fiche,
.eqtrio__c:focus-within .eqtrio__fiche,
.eqtrio__c.ouverte .eqtrio__fiche{opacity:1;visibility:visible;transform:none;transition-delay:0s}
.eqtrio__champs{font-family:var(--mono);font-size:.6rem;letter-spacing:.18em;text-transform:uppercase;
  color:var(--accent-muted);margin:0 0 .5rem}
.eqtrio__mot{font-size:.9rem;line-height:1.5;color:rgba(240,238,232,.9);margin:0}
.eqtrio__c{cursor:default}
.eqtrio__c:focus-visible{outline:2px solid var(--accent);outline-offset:6px}
/* L'invite dit quoi faire, et elle change de mot selon l'appareil, comme celle
   des bulles le faisait. */
.eqtrio__invite{margin-top:clamp(1.4rem,2.4vw,2rem);font-family:var(--mono);font-size:.62rem;
  letter-spacing:.2em;text-transform:uppercase;color:var(--text-secondary)}
.eqtrio__invite .surTel{display:none}
@media (hover:none){
  .eqtrio__invite .surSouris{display:none}
  .eqtrio__invite .surTel{display:inline}
}
.eqtrio__clip{width:100%;height:100%;object-fit:cover;display:block;background:transparent}
/* ==== La scène derrière les courtiers, 18 septembre 2026 au soir ============
   Mathieu : « il manque quelque chose » ; ses choix, en question cliquable :
   « un décor derrière eux » et « plus de mouvement ». Posés sur la crème de
   la page, les trois flottaient : un pan de sable les assoit. Il S'ÉTEND au
   défilement, un tiers par courtier, sur le premier quart de la fenêtre de
   chacun (script dans pages.js : c'est --scene, de 0 à 1) ; le trait
   terracotta est son bord qui avance. Le pan sort de la grille à droite
   jusqu'au bord de l'écran : la page ne doit pas être centrée.
   SABLE, PAS CHARBON : la première maquette était en charbon, et Mathieu a vu
   « un peu de blanc sur le contour des photos ». C'est la frange d'un
   détourage fait sur fond clair, invisible sur un fond clair. Le MP4 de
   secours de Safari porte ce sable cuit dedans (preparer-alpha.sh, dixième
   argument E7E3D9) : si le pan change de couleur, les trois MP4 se refont.
   Sans script (mouvement réduit, téléphone), --scene vaut 1 : le pan est là. */
.eqscene{position:relative;margin-top:clamp(2rem,3.4vw,2.8rem);
  padding:clamp(1.2rem,2.4vw,2rem);padding-right:calc(var(--gut) + clamp(1.2rem,2.4vw,2rem));
  margin-right:calc(-1 * var(--gut))}
.eqscene .eqtrio{margin-top:0}
.eqscene__fond{position:absolute;inset:0;background:var(--panel);
  transform-origin:left center;transform:scaleX(var(--scene,1))}
.eqscene__trait{position:absolute;top:0;bottom:0;left:calc(var(--scene,1) * 100%);width:2px;margin-left:-2px;
  background:var(--accent);opacity:var(--trait,0)}
.eqscene .eqtrio__c{position:relative;z-index:1}
/* Le bas du détourage se fond dans la scène plutôt que d'être tranché net à
   la taille (vu sur la maquette charbon du 18 septembre au soir, gardé sur le
   sable). Le masque est sur la VIDÉO seule : posé sur le cadre, il effacerait
   aussi le bas de la fiche au survol, qui vit dans le même cadre. */
.eqscene .eqtrio__clip{-webkit-mask-image:linear-gradient(to bottom,#000 78%,rgba(0,0,0,0) 100%);
  mask-image:linear-gradient(to bottom,#000 78%,rgba(0,0,0,0) 100%)}
/* LE RIDEAU DES PORTRAITS, 19 septembre 2026 au soir. Il vaut `!important`
   parce qu'il doit gagner contre la version immobile du téléphone, qui force
   `opacity:1 !important` tant que pages.js n'a pas pris la main. C'est donc
   pages.js qui retire la classe, juste après avoir posé ses propres valeurs :
   sans ce retrait, les cartes resteraient invisibles pour toujours. */
html.eq-avant .eqtrio__c,
html.eq-avant .eqtrio__legende{opacity:0 !important}
.eqtrio__legende{margin:0}
.eqtrio__nom{font-family:var(--display);font-weight:500;font-size:1.05rem;
  letter-spacing:-.01em;margin-top:.85rem}
.eqtrio__titre{font-family:var(--mono);font-size:.64rem;letter-spacing:.18em;
  text-transform:uppercase;color:var(--text-secondary);margin-top:.3rem}
.lien-sec{display:inline-block;
  font-family:var(--mono);font-size:.7rem;letter-spacing:.18em;text-transform:uppercase;
  color:var(--accent-text);text-decoration:none;border-bottom:1px solid var(--accent-muted);padding-bottom:2px}
.lien-sec:hover,.lien-sec:focus-visible{border-bottom-color:var(--accent)}
/* Sous 620 px les trois passent en colonne. */
@media (max-width:620px){.eqtrio{grid-template-columns:1fr;max-width:22rem;margin-inline:auto}}
/* ==== LE TÉLÉPHONE, 19 septembre 2026 au soir : EN COLONNE, L'UN APRÈS
   L'AUTRE, ET C'EST LE DÉFILEMENT QUI DONNE L'IMAGE. ======================

   Deux demandes de Mathieu le même soir, dans cet ordre. D'abord : « sur la
   version mobile, les portraits défilant ne fonctionne pas, c'est simplement
   un vidéo qui part tout seul. » C'était vrai et mesurable : chaque clip
   partait sur une minuterie quand sa carte entrait à l'écran, si bien qu'au
   départ de la section le premier était DÉJÀ fini (4,30 s sur 4,30) et qu'à la
   fin le troisième n'en était qu'à 2,96. Ensuite, sur la première correction,
   qui empilait les trois dans une seule case collée : « maintenant les 3 sont
   1 par dessus l'autre, je n'aime pas ça. Mets les à la vertical un à la suite
   de l'autre. Comme sur la version WEB PC mais à la verticale. »

   LA MISE EN PAGE EST DONC CELLE D'AVANT, et elle ne bouge plus : rien de
   collé, les trois portraits en colonne, l'un sous l'autre. CE QUI CHANGE EST
   LA SOURCE DE L'IMAGE : chaque clip est piloté par la traversée de SA PROPRE
   carte à l'écran, pas par une horloge. Le script est dans pages.js.

   UN SEUL DÉCIDEUR, ET C'EST LE SCRIPT. Il pose `.eqscrub--vert` quand il
   prend la main ; la feuille garde la version immobile sous
   `:not(.eqscrub--vert)`. Sans JavaScript la classe n'existe pas, et le
   visiteur voit les trois portraits posés sur leur pan de sable, sans un
   mouvement : c'est la bonne dégradation, et il n'y a plus deux requêtes
   média à garder identiques dans deux fichiers. */
@media (max-width:720px),(max-height:500px),(prefers-reduced-motion:reduce){
  .eqscrub{height:auto}
  .eqscrub__colle{position:static;min-height:0}
  .eqtrio__c{max-width:none}
  .eqscene{margin-right:0;padding:clamp(1rem,4vw,1.6rem)}
}
@media (max-width:720px){
  /* Jusqu'à 720 px c'est une colonne, même au-dessus des 620 px de la règle
     plus haut : trois portraits côte à côte sur 700 px font 215 px chacun, et
     le récit « l'un après l'autre » n'existe plus. */
  .eqscrub--vert .eqtrio{grid-template-columns:1fr;max-width:22rem;margin-inline:auto}
  /* Un peu d'air entre les trois, pour qu'on les lise comme une suite et non
     comme un bloc. C'est le seul pixel d'espace ajouté par cette correction. */
  .eqscrub--vert .eqtrio{gap:clamp(1.4rem,4vw,1.8rem)}
}
/* SANS SCRIPT, MOUVEMENT RÉDUIT, OU ÉCRAN BAS : rien ne bouge, le pan est là
   en entier, les affiches (les portraits détourés) tiennent lieu de clips. */
@media (max-width:720px),(max-height:500px),(prefers-reduced-motion:reduce){
  .eqscrub:not(.eqscrub--vert) .eqtrio__c{opacity:1 !important;transform:none !important}
  .eqscrub:not(.eqscrub--vert) .eqscene{--scene:1}
  .eqscrub:not(.eqscrub--vert) .eqscene__trait{display:none}
  .eqscrub:not(.eqscrub--vert) .eqtrio__legende{opacity:1 !important;transform:none !important}
}
/* LE PAN NE S'ANIME PAS SUR TÉLÉPHONE, ET C'EST UNE MESURE QUI L'A DÉCIDÉ.
   Sur ordinateur il s'étend vers la droite d'un tiers par courtier, et son
   bord terracotta est la moitié de l'effet. Tourné d'un quart de tour pour
   descendre, ce bord doit rester SOUS le portrait qu'on regarde, sinon le
   sable n'est pas encore là quand la personne arrive dessus. Or « sous le
   portrait qu'on regarde », sur un écran de téléphone, veut dire sous le pli :
   relevé à seize hauteurs de défilement, le trait est resté entre 10 et 130 px
   SOUS le bas de l'écran tout du long, donc invisible d'un bout à l'autre.
   Le décor reste, entier, derrière les trois ; ce qui part est une
   transformation de 1600 px recalculée à chaque image pour rien, et Mathieu
   avait justement signalé que le défilement n'était « pas très fluide ». */
@media (max-width:720px){
  .eqscrub--vert .eqscene{--scene:1}
  .eqscrub--vert .eqscene__trait{display:none}
}
/* Un lien de fin de section est un petit texte en capitales : sa boite fait
   moins de 44 px. Le pseudo-element invisible agrandit la zone que le doigt
   atteint sans deplacer un pixel, la technique de mobile-qualite.mjs. */
.lien-sec{position:relative}
.lien-sec::after{content:"";position:absolute;inset:-14px -8px}

/* ==== LES TROIS PORTES DE L'ACCUEIL =====================================
   Demande de Mathieu le 18 septembre 2026, apres avoir montre
   samiraagnaou.com : « vois ce que tu peux utiliser pour remettre un peu
   d'informations sur notre page d'accueil ». Ce que ce site fait de mieux,
   c'est trois blocs cliquables sous sa presentation. Ici : Acheter, Vendre,
   Savoir ce qu'elle vaut. Les photos sont LES BANDEAUX DE CES TROIS PAGES,
   donc la page d'arrivee ressemble a la vignette qu'on a touchee.
   Aucun texte neuf : les phrases sont celles de ces pages.

   PIEGE PAYE : un <a> ne peut pas contenir de <div>, donc les blocs sont des
   <span>, et un <span> est EN LIGNE. Sans `display:block` le numero, le titre
   et la phrase se mettaient tous les trois sur une seule ligne, a cheval sur
   la photo. Vu le 18 septembre sur la maquette. */
.portes{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(.9rem,1.8vw,1.6rem);
  margin-top:clamp(2.4rem,4vw,3.4rem)}
.porte{position:relative;display:block;text-decoration:none;color:inherit;overflow:hidden;
  background:var(--ink-deep)}
.porte__media{position:relative;display:block;aspect-ratio:4/3;overflow:hidden}
.porte__media img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .8s var(--ease)}
.porte:hover .porte__media img,.porte:focus-visible .porte__media img{transform:scale(1.045)}
.porte__voile{position:absolute;inset:0;display:block;
  background:linear-gradient(to top,rgba(10,13,19,.86) 0%,rgba(10,13,19,.36) 54%,rgba(10,13,19,.12) 100%)}
.porte__in{position:absolute;inset:auto 0 0 0;padding:clamp(1.1rem,2vw,1.6rem)}
.porte__no,.porte__h,.porte__mot{display:block}
.porte__no{font-family:var(--mono);font-size:.62rem;letter-spacing:.2em;text-transform:uppercase;
  color:rgba(239,236,228,.72);margin:0 0 .4rem}
.porte__h{font-family:var(--display);font-weight:500;font-size:clamp(1.15rem,1.9vw,1.5rem);
  letter-spacing:-.01em;color:#fff;margin:0;text-shadow:0 2px 18px rgba(5,8,14,.5)}
.porte__mot{font-size:.86rem;color:rgba(239,236,228,.82);margin:.45rem 0 0;max-width:26ch}
.porte:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
@media (max-width:760px){.portes{grid-template-columns:1fr;max-width:26rem;margin-inline:auto}
  .porte__media{aspect-ratio:16/9}}

/* ==== La photo officielle du groupe, page des courtiers ================== */
/* La classe existait dans la page depuis le 25 août mais N'ÉTAIT ÉCRITE NULLE
   PART ici : une classe inexistante ne casse rien et ne fait crier aucun test,
   donc la figure gardait le 1em 40px que le navigateur met d'office sur un
   <figure>. La photo était rentrée de 40 px par rapport à la colonne de texte
   de sa propre section. Troisième fois que ce piège tombe dans ce fichier,
   voir les mêmes notes sur les cartes et sur les bulles. */
.equipe{margin:0}
/* Sur l'accueil depuis le 17 septembre 2026, la même photo remplace le texte
   de l'équipe et mène à la page des courtiers. Un lien est en ligne par
   défaut : il faut le poser en bloc, sinon l'image flotte dans une ligne
   de texte et garde un liseré sous elle. */
.equipe--lien{display:block;width:100%}
.equipe--lien img{width:100%}
.equipe--lien:focus-visible{outline-offset:6px}

/* ==== La page Outils, refaite le 25 août sur les remarques de Nassim ===== */
/* Son reproche : tout empilé, tout aligné à gauche, du vide. Réponses : une
   intro centrée, un CHOIX d'outil, deux calculatrices qui alternent leur
   mise en page, et une image qui casse le bloc final. */
.outils-intro{max-width:60ch;margin-inline:auto;text-align:center}
/* Cinq outils depuis le 27 août, deux auparavant. `auto-fit` avec un minimum
   de 15rem évite d'avoir à recompter les colonnes au prochain outil ajouté :
   la grille se réorganise seule, et une carte orpheline s'étire au lieu de
   laisser un trou. */
.choix{display:grid;grid-template-columns:repeat(auto-fit,minmax(15rem,1fr));
  gap:1rem;margin-top:clamp(1.8rem,3.4vw,2.6rem)}
@media (max-width:700px){.choix{grid-template-columns:1fr}}
.choix__btn{display:block;text-decoration:none;color:inherit;background:var(--panel-2);
  border:1px solid var(--line);border-radius:2px;padding:1.15rem 1.25rem 1.3rem;
  transition:border-color .3s var(--ease),background .3s var(--ease),box-shadow .3s var(--ease)}
.choix__btn:hover{border-color:var(--accent)}
.choix__btn:focus-visible{outline:2px solid var(--accent-text);outline-offset:3px}
.choix__nom{display:block;font-family:var(--display);font-weight:600;
  font-size:clamp(1.05rem,1.9vw,1.3rem);letter-spacing:-.01em}
.choix__quoi{display:block;margin-top:.45rem;font-size:.88rem;color:var(--text-secondary)}
/* L'outil choisi porte la couleur de la marque. aria-selected est posé par
   pages.js ; sans JavaScript, aucun bouton n'est « choisi » et les deux
   calculatrices restent simplement visibles, les ancres font le reste. */
.choix__btn[aria-selected="true"]{background:var(--ink-deep);border-color:var(--ink-deep);
  box-shadow:0 14px 30px -18px rgba(53,52,52,.55)}
.choix__btn[aria-selected="true"] .choix__nom{color:#F6F4EF}
.choix__btn[aria-selected="true"] .choix__quoi{color:rgba(246,244,239,.72)}
/* Un panneau écarté par le sélecteur disparaît du flux. */
section[data-panneau][hidden]{display:none}
.outils-fig{margin:0 0 1.5rem;border:1px solid var(--line);overflow:hidden;background:var(--panel)}
.outils-fig img{display:block;width:100%;height:auto}
/* Le duo inversé : la colonne étroite (image + encadré) passe à GAUCHE, la
   prose à droite. C'est l'alternance demandée : les autres pages font
   l'inverse. En une colonne, l'ordre naturel reprend. */
.duo--inverse{grid-template-columns:.75fr 1.25fr}
@media (max-width:920px){.duo--inverse{grid-template-columns:1fr}}

/* ==== LE RYTHME DES SECTIONS, 25 août 2026 ==============================
   Demande du client, appuyée par Nassim : « tout est trop collé à gauche
   tout le temps, il faut mélanger un peu ça » et « alterner mettons un à
   gauche, un dans le centre ».

   La réponse n'est PAS de tout centrer : un site tout centré est aussi
   monotone qu'un site tout à gauche, et la lecture y perd. C'est une
   ALTERNANCE qui casse la répétition. Trois postures, posées sur `.wrap` :

     (rien)          la posture d'origine, tout à gauche.
     .wrap--centre   l'en-tête et l'intro au centre, mesure resserrée.
     .wrap--decale   tout le bloc poussé vers la droite, aligné à gauche.

   Règle de pose : jamais deux sections voisines dans la même posture.
   Vérifié par `lupa-tests/rythme.mjs`, qui refuse deux voisines pareilles.

   La barre du `.kick` est un `flex:1` : centrée, elle dépasserait des deux
   côtés et mangerait la largeur. On la borne et on la met des DEUX côtés,
   ce qui donne une étiquette symétrique au lieu d'une flèche. */
.wrap--centre{text-align:center}
.wrap--centre > .kick{justify-content:center}
.wrap--centre > .kick::before{content:"";height:1px;flex:1;max-width:5rem;background:var(--line-strong)}
.wrap--centre > .kick::after{max-width:5rem}
.wrap--centre > .h2{max-width:22ch;margin-inline:auto}
.wrap--centre > .lede,
.wrap--centre > .prose{margin-inline:auto;max-width:58ch}
/* Le paragraphe des fermetures de page (.cta__lede) n'était pas dans cette
   liste : sous un titre centré, il restait collé à gauche. Vu à l'œil le
   17 septembre 2026 sur la fin de l'accueil. Sa mesure de 44ch ne change pas. */
.wrap--centre > .cta__lede{margin-inline:auto}
/* Le contenu qui SUIT l'en-tête garde son alignement à lui : une grille de
   cartes centrée deviendrait illisible. On ne centre que la tête. */
/* Liste RELEVEE dans les pages, pas devinee : ce sont toutes les grilles qui
   se trouvent reellement sous une section centree. Une carte au texte centre
   se lit mal des qu'elle depasse deux lignes, et c'est ce que le premier essai
   donnait sur les trois etapes de Vendre. On centre la TETE, jamais le corps. */
.wrap--centre > .villes,
.wrap--centre > .avantages,
.wrap--centre > .quotes,
.wrap--centre > .steps,
.wrap--centre > .pcards,
.wrap--centre > .ruban,
.wrap--centre > .pins,
.wrap--centre > .reader,
.wrap--centre > .bulles{text-align:left}

/* Le décalage : le bloc quitte le bord gauche sans se centrer. C'est la
   posture la plus utile entre deux sections centrées, parce qu'elle garde
   la lecture en drapeau à gauche tout en changeant la silhouette. */
.wrap--decale{max-width:calc(var(--maxw) - 9rem);margin-left:auto;margin-right:auto;
  padding-left:clamp(0rem,7vw,9rem)}
@media (max-width:900px){
  .wrap--decale{max-width:var(--maxw);padding-left:0}
}

/* ==== Les cartes des trois courtiers, pages Vendre et Acheter ============ */
/* Demande du client, 26 août, d'après la maquette concurrente qu'il m'a
   montrée : « le même style de mise en page avec les photos et les
   formulaires à remplir ». Les photos sont les portraits individuels
   officiels de l'équipe. Chaque carte mène à la page des courtiers. */
.eqcartes{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(.9rem,2vw,1.5rem);
  margin-top:clamp(2rem,3.6vw,3rem)}
@media (max-width:700px){.eqcartes{grid-template-columns:1fr;max-width:22rem;margin-inline:auto}}
.eqcarte{display:block;text-decoration:none;color:inherit;background:var(--panel);
  border:1px solid var(--line);border-radius:2px;overflow:hidden;
  transition:border-color .3s var(--ease),box-shadow .3s var(--ease)}
.eqcarte:hover{border-color:var(--accent);box-shadow:0 18px 40px -24px rgba(53,52,52,.45)}
.eqcarte:focus-visible{outline:2px solid var(--accent-text);outline-offset:3px}
.eqcarte figure{margin:0;aspect-ratio:4/5;overflow:hidden;background:#F4F2ED}
.eqcarte img{display:block;width:100%;height:100%;object-fit:cover;
  transition:transform .6s var(--ease)}
.eqcarte:hover img{transform:scale(1.045)}
.eqcarte figcaption{padding:.9rem 1rem 1.05rem}
.eqcarte__nom{font-family:var(--mark);font-weight:500;font-size:clamp(1.05rem,1.7vw,1.3rem);
  letter-spacing:-.01em}
.eqcarte__titre{margin-top:.35rem;font-family:var(--mono);font-size:.6rem;
  letter-spacing:.15em;text-transform:uppercase;color:var(--accent-text)}

/* La petite ligne sous les boutons d'envoi : elle dit la verite du mailto. */
/* Le formulaire vit toujours dans une section en encre, donc sa note prend le
   lin adouci comme .cta__lede et .cta__phone, jamais --text-secondary. Ce gris
   est fait pour le fond clair : posé sur le charcoal il donnait 1,71 pour 1,
   soit une ligne qu'on ne lit pas. Arrivé avec les formulaires du 26 août,
   corrigé le 26 août, trouvé par page.mjs. */
.form__note{margin-top:.7rem;font-size:.78rem;color:rgba(239,236,228,.72)}

/* ==== Le moteur de recherche d'aperçu, page Propriétés, 18 septembre 2026 ====
   Demande de Mathieu : « un faux moteur de recherche dans l'onglet propriétés,
   pour donner un avant-goût de quoi ça ressemblerait avec les autorisations
   Centris ». Le panneau de filtres reprend .search__panel et .field de
   l'accueil, pour que les deux recherches se ressemblent. Les cartes reprennent
   le sable et le trait des cartes du blogue, la photo et son zoom des portes.
   LES FICHES SONT DES EXEMPLES, et ça se voit sur chaque photo (.fiche__exemple,
   en charbon OPAQUE : un voile translucide sur une photo est illisible pour
   page.mjs, et parfois pour l'œil).
   LES [hidden] SONT ÉCRITS EXPRÈS : hidden perd contre tout display déclaré,
   et .lien-sec comme .fiches en déclarent un. */
.moteur__in{margin-top:clamp(2rem,3.4vw,2.8rem)}
.moteur__grid{display:grid;gap:.9rem;grid-template-columns:1.7fr 1.2fr .85fr .85fr 1fr 1.15fr}
/* Au téléphone : la ville et le type sur toute la largeur, puis les prix
   côte à côte, puis chambres et salles de bain côte à côte. Six champs en
   pile faisaient un panneau de 440 px avant la première fiche ; et à deux
   colonnes pleines, « Tous les types » et « Salles de bain » se faisaient
   couper par la flèche du menu. Mesuré à 390 px : une colonne fait 142 px,
   « Salles de bain » en tient 134 avec la flèche rapprochée et le texte à
   .9rem. Les deux vus sur les captures, pas devinés. */
@media (max-width:1200px){.moteur__grid{grid-template-columns:1fr 1fr 1fr}.moteur__q{grid-column:1/-1}}
@media (max-width:700px){
  .moteur__grid{grid-template-columns:1fr 1fr}
  .moteur__grid .field:nth-child(2){grid-column:1/-1}
  .moteur__grid select{font-size:.9rem;padding-right:1.7rem;background-position:calc(100% - 13px) 50%,calc(100% - 8px) 50%}
}
@media (max-width:340px){.moteur__grid{grid-template-columns:1fr}}
.moteur__tete{display:flex;align-items:center;gap:1rem 1.6rem;flex-wrap:wrap;margin-top:clamp(1.6rem,2.6vw,2.2rem)}
.moteur__compte{font-family:var(--display);font-weight:500;font-size:clamp(1.15rem,1.8vw,1.4rem);letter-spacing:-.01em}
.moteur__tri{margin-left:auto;min-width:16rem}
@media (max-width:600px){.moteur__tri{margin-left:0;width:100%}}
button.lien-sec{background:none;border:0;border-bottom:1px solid var(--accent-muted);border-radius:0;padding:0 0 2px;cursor:pointer}
.moteur__effacer[hidden],.moteur__vide[hidden],.moteur__suite[hidden],.fiches[hidden]{display:none}
.fiches{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(1rem,1.8vw,1.6rem);margin-top:clamp(1.2rem,2vw,1.6rem)}
@media (max-width:1000px){.fiches{grid-template-columns:1fr 1fr}}
@media (max-width:620px){.fiches{grid-template-columns:1fr}}
.fiche{position:relative;background:var(--panel-2);border:1px solid var(--line);
  transition:border-color .3s var(--ease),box-shadow .3s var(--ease);
  animation:fiche-in .5s var(--ease) both;animation-delay:calc(var(--i,0) * 45ms)}
.fiche--la{animation:none}
@keyframes fiche-in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.fiche{animation:none}}
.fiche:hover,.fiche:focus-within{border-color:var(--accent);box-shadow:0 18px 40px -24px rgba(53,52,52,.45)}
.fiche__media{margin:0;position:relative;aspect-ratio:3/2;overflow:hidden;background:var(--panel)}
.fiche__media img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .8s var(--ease)}
.fiche:hover .fiche__media img,.fiche:focus-within .fiche__media img{transform:scale(1.045)}
.fiche__etiq,.fiche__exemple{position:absolute;top:.8rem;font-family:var(--mono);font-size:.62rem;letter-spacing:.16em;
  text-transform:uppercase;padding:.45rem .65rem;line-height:1}
.fiche__etiq{left:.8rem;background:var(--accent-btn);color:#fff}
.fiche__exemple{right:.8rem;background:var(--ink-deep);color:#F0EEE8}
.fiche__corps{padding:1.1rem 1.2rem 1.25rem}
.fiche__prix{font-family:var(--display);font-weight:600;font-size:clamp(1.3rem,1.9vw,1.55rem);letter-spacing:-.02em}
.fiche__titre{margin-top:.35rem;font-weight:400;font-size:.97rem}
.fiche__ou{display:block;color:var(--text-secondary);font-size:.9rem;margin-top:.1rem}
.fiche__specs{margin-top:.8rem;padding-top:.8rem;border-top:1px solid var(--line);display:flex;flex-wrap:wrap;gap:.35rem 1.1rem;
  font-family:var(--mono);font-size:.68rem;letter-spacing:.14em;text-transform:uppercase;color:var(--text-secondary)}
/* Le bouton s'étire sur toute la carte par son ::after : un seul arrêt de
   tabulation par fiche, toute la carte cliquable, et des <p> valides autour,
   ce qu'un <button> ou un <a> enveloppant n'aurait pas permis. */
.fiche__lien{position:static;background:none;border:0;padding:0;margin-top:.95rem;display:inline-block;line-height:1;
  font-family:var(--mono);font-size:.68rem;letter-spacing:.18em;text-transform:uppercase;color:var(--accent-text);cursor:pointer}
.fiche__lien::after{content:"";position:absolute;inset:0}
.fiche__lien:focus-visible{outline:none}
.fiche:focus-within{outline:2px solid var(--accent);outline-offset:3px}
.moteur__suite{margin-top:clamp(1.6rem,2.6vw,2.2rem);text-align:center}
.moteur__plus{color:var(--text-primary)}
.moteur__plus:hover{background:var(--panel-2)}
.moteur__vide{margin-top:clamp(1.2rem,2vw,1.6rem);padding:clamp(1.6rem,3vw,2.4rem);background:var(--panel-2);border:1px solid var(--line);max-width:38rem}
.moteur__vide__t{font-family:var(--display);font-weight:600;font-size:1.3rem;letter-spacing:-.01em}
.moteur__vide p + p{margin-top:.8rem;color:var(--text-secondary)}
.moteur__vide .btn{margin-top:1.4rem}
/* La fiche ouverte : un <dialog> natif, deux colonnes sur ordinateur, la
   photo en pleine largeur sur téléphone. La page ne défile plus derrière. */
html.fdlg-ouvert{overflow:hidden}
.fdlg{border:0;padding:0;margin:auto;width:100%;max-width:min(64rem,calc(100vw - 2rem));max-height:min(90vh,calc(100vh - 2rem));
  overflow:auto;background:var(--canvas);color:var(--text-primary);box-shadow:0 40px 90px -30px rgba(21,26,33,.6)}
.fdlg::backdrop{background:rgba(53,52,52,.62)}
.fdlg__in{display:grid;grid-template-columns:1.1fr 1fr;min-height:100%}
.fdlg__media{margin:0;position:relative;background:var(--panel);min-height:18rem}
.fdlg__media img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
.fdlg__media .fiche__exemple{right:auto;left:.9rem;top:.9rem}
.fdlg__corps{padding:clamp(1.6rem,3vw,2.6rem)}
.fdlg__prix{margin-top:1.2rem;font-family:var(--display);font-weight:600;font-size:clamp(1.7rem,2.6vw,2.3rem);letter-spacing:-.02em}
.fdlg__titre{margin-top:.4rem;font-size:clamp(1.25rem,1.8vw,1.5rem);font-weight:500;letter-spacing:-.01em}
.fdlg__ou{margin-top:.25rem;color:var(--text-secondary)}
.fdlg__specs{margin:1.4rem 0 0;padding:1rem 0;border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  display:grid;grid-template-columns:repeat(3,1fr);gap:.9rem 1rem}
.fdlg__specs div{margin:0}
.fdlg__specs dt{font-family:var(--mono);font-size:.62rem;letter-spacing:.18em;text-transform:uppercase;color:var(--text-secondary)}
.fdlg__specs dd{margin:.25rem 0 0;font-weight:400}
.fdlg__mot{margin-top:1.2rem}
.fdlg__note{margin-top:1.1rem;padding:.9rem 1rem;background:var(--panel-2);border-left:2px solid var(--accent);font-size:.9rem;color:var(--text-secondary)}
.fdlg__actions{margin-top:1.6rem;display:flex;flex-wrap:wrap;gap:1rem 1.6rem;align-items:center}
.fdlg__fermer{position:absolute;top:.8rem;right:.8rem;z-index:2;width:44px;height:44px;border:0;border-radius:0;
  background:var(--ink-deep);cursor:pointer;display:grid;place-items:center;transition:background .3s var(--ease)}
.fdlg__fermer span{position:relative;width:16px;height:16px;display:block}
.fdlg__fermer span::before,.fdlg__fermer span::after{content:"";position:absolute;left:0;top:7px;width:16px;height:1.5px;background:#F0EEE8;transform:rotate(45deg)}
.fdlg__fermer span::after{transform:rotate(-45deg)}
.fdlg__fermer:hover{background:var(--accent-btn)}
@media (max-width:820px){
  .fdlg__in{grid-template-columns:1fr}
  .fdlg__media{aspect-ratio:16/10;min-height:0}
  .fdlg__specs{grid-template-columns:1fr 1fr}
}

/* La liste de « Comment on travaille » en deux colonnes sur grand ecran,
   19 septembre 2026, meme demande : elle tenait sur une seule colonne de
   700 px avec 500 px de vide a sa droite, et la section faisait 703 px de
   haut pour cinq lignes. Deux colonnes la ramenent a une hauteur de texte
   normale et remplissent le bloc. `break-inside` empeche une puce d'etre
   coupee en deux par le saut de colonne. */
@media (min-width:1100px){
  .prose--deux{max-width:none}
  .prose--deux > ul{column-count:2;column-gap:clamp(2rem,4vw,4rem)}
  .prose--deux > ul > li{break-inside:avoid;margin-top:0;margin-bottom:.9rem}
}

/* =========================================================================
   L'ACCUEIL COURT, 1er octobre 2026.
   Maquette validee par Mathieu le meme jour (lupa-review/maquette-court/),
   sur le modele de denistomani.com que la cliente a aime : leger en texte,
   gros, oriente vers une action, demander un appel. Aucune couleur neuve,
   aucune police neuve : les jetons du guide et les composants existants
   (portes, ruban, questions, formulaire). Seules les mises en page des
   sections neuves vivent ici.
   ========================================================================= */

/* 1. La preuve : le chiffre en tres grand, puis le ruban sur toute la largeur. */
.preuve{padding-top:clamp(2.6rem,4.4vw,4rem)}
.preuve__ligne{display:flex;align-items:center;gap:clamp(1.2rem,2.6vw,2.4rem);flex-wrap:wrap}
.preuve__note{font-family:var(--display);font-weight:700;letter-spacing:-.03em;line-height:.9;
  display:flex;align-items:baseline;gap:.5rem}
.preuve__note strong{font-size:clamp(3.4rem,7vw,6rem);font-weight:700}
.preuve__sur{font-family:var(--mono);font-size:.7rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--text-secondary);font-weight:400}
.preuve__quoi{display:grid;gap:.5rem}
.preuve__h{font-size:clamp(1.3rem,2.2vw,1.9rem);font-weight:500;max-width:22ch;letter-spacing:-.01em}
.preuve .ruban{margin-top:clamp(1.8rem,3vw,2.6rem)}

/* 2. Deux grandes portes, Vendre et Acheter. Le composant .porte d'avant,
      en deux colonnes et avec le mot en grand. */
.portes--deux{grid-template-columns:repeat(2,1fr);margin-top:clamp(2rem,3.2vw,2.8rem)}
.portes--deux .porte__media{aspect-ratio:16/10}
.portes--deux .porte__in{padding:clamp(1.4rem,2.6vw,2.4rem)}
.portes--deux .porte__h{font-size:clamp(2rem,3.6vw,3.2rem);font-weight:600;letter-spacing:-.02em}
.portes--deux .porte__mot{font-size:.95rem;margin-top:.6rem}
.porte__fleche{display:inline-block;margin-top:1.1rem;font-family:var(--mono);font-size:.66rem;letter-spacing:.2em;
  text-transform:uppercase;color:#fff;border-bottom:1px solid rgba(255,255,255,.5);padding-bottom:3px}
.porte:hover .porte__fleche,.porte:focus-visible .porte__fleche{border-bottom-color:#fff}
.eval-ligne{margin-top:clamp(1.4rem,2.4vw,2rem);display:flex;flex-wrap:wrap;gap:.6rem 1.2rem;align-items:baseline;
  padding-top:1.2rem;border-top:1px solid var(--line);color:var(--text-secondary)}
@media (max-width:760px){
  .portes--deux{grid-template-columns:1fr;max-width:none}
  .portes--deux .porte__media{aspect-ratio:16/10}
}

/* 3. Ce qui inquiete, puis ce qu'on fait. RETIREE DE L'ACCUEIL le 1er octobre
      2026, le jour meme, demande de Mathieu : « on enleve le Ce qu'on entend
      le plus souvent ». Ces regles ne sont plus chargees par aucune page ; elles
      restent pour un retour en une ligne (la section est dans 1a7c595).
      Section sombre (.cta), donc la
      barre passe en clair par-dessus, et la selection prend sa teinte sombre.
      Les inquietudes sont en Playfair DROIT : la feuille de polices ne charge
      pas l'italique, et un italique fabrique par le navigateur penche mal. */
.douleurs .h2{max-width:18ch}
.paires{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(1.6rem,3vw,2.8rem) clamp(2rem,5vw,5rem);
  margin-top:clamp(2rem,3.4vw,3rem)}
.paire{border-left:1px solid rgba(239,236,228,.22);padding-left:clamp(1.1rem,2vw,1.6rem)}
.paire__mal{font-family:var(--display);font-weight:500;font-size:clamp(1.3rem,2vw,1.7rem);line-height:1.25;
  letter-spacing:-.01em;color:#EFECE4}
.paire__fait{margin-top:.8rem;color:rgba(239,236,228,.78);max-width:46ch}
@media (max-width:760px){.paires{grid-template-columns:1fr}}

/* 4. Trois etapes, un titre chacune. Le bloc est centre, les lignes restent
      a gauche (regle de Mathieu du 18 septembre). */
.etapes .h2{margin-inline:auto;max-width:20ch}
.etapes__liste{list-style:none;margin:clamp(2rem,3.4vw,3rem) 0 0;padding:0;display:grid;
  grid-template-columns:repeat(3,1fr);gap:clamp(1.4rem,3vw,3rem);text-align:left}
.etape{border-top:1px solid var(--line-strong);padding-top:1.1rem}
.etape__no{display:block;font-family:var(--mono);font-size:.7rem;letter-spacing:.24em;color:var(--accent-text)}
.etape__h{display:block;margin-top:.6rem;font-family:var(--display);font-weight:500;
  font-size:clamp(1.15rem,1.7vw,1.45rem);line-height:1.3;letter-spacing:-.01em}
@media (max-width:760px){.etapes__liste{grid-template-columns:1fr}}

/* 6. L'appel. */
.appel .h2{max-width:14ch}

/* 1 bis. La photo de l'equipe, remise sur l'accueil le 1er octobre 2026,
      entre les avis et les deux portes. Pas de remplissage en haut : le bas
      de la section des avis donne deja l'air qu'il faut sous le ruban. */
.equipe-bande{padding-top:0}

/* ==== VENDRE COURT, 1er octobre 2026 =====================================
   Maquette validee par Mathieu (lupa-review/maquette-vendre/), dans l'esprit
   de l'accueil court. Les composants sont ceux du site ; ne vivent ici que
   les reglages propres a la page. */
/* Le titre de la premiere section est long : 15ch le coupait en trois lignes
   et laissait « prix. » seul. Equilibre sur deux lignes. */
.vendre__titre{max-width:24ch;text-wrap:balance}
/* La liste « ce qu'on regarde » passe en deux colonnes au-dessus de 1100 px
   (.prose--deux) ; le paragraphe garde sa largeur de lecture. */
.vendre__regard{margin-top:clamp(1.4rem,2.4vw,2rem);max-width:none}
.vendre__regard > p{max-width:62ch}
/* La ligne de l'evaluation gratuite, sous le telephone, sur fond charbon. */
.cta__eval{margin-top:1rem;font-size:.95rem;color:rgba(239,236,228,.76)}
.cta__eval a{color:var(--accent-muted);text-underline-offset:3px;white-space:nowrap}
.cta__eval a:hover{color:#EFECE4}
/* Trois avis de vendeurs, les cartes du ruban de l'accueil posees en rangee.
   Le texte des cartes reste aligne a gauche dans une section centree. */
.avis-trio{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(1rem,2vw,1.6rem);
  margin-top:clamp(1.8rem,3vw,2.6rem);text-align:left}
.avis-trio .ruban__carte{flex:none}
@media (max-width:900px){.avis-trio{grid-template-columns:1fr;max-width:34rem;margin-inline:auto}}
